/* e_buffer.cpp * * Copyright (c) 1994-1996, Marko Macek * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * */ #include "fte.h" EBuffer *SSBuffer = 0; // scrap buffer (clipboard) /////////////////////////////////////////////////////////////////////////////// EBuffer::EBuffer(int createFlags, EModel **ARoot, const char * /*AName*/) :EModel(createFlags, ARoot), TP(0,0), CP(0,0), BB(-1,-1), BE(-1,-1), PrevPos(-1, -1), SavedPos(-1, -1), Match(-1, -1) { Modified = 0; Loaded = 0; Loading = 0; FileName = 0; LL = 0; VV = 0; FF = 0; RGap = RCount = RAllocated = 0; VGap = VCount = VAllocated = 0; FCount = 0; Modified = 0; BlockMode = bmStream; ExtendGrab = 0; AutoExtend = 0; MatchLen = MatchCount = 0; #ifdef CONFIG_UNDOREDO US.Num = 0; US.Data = 0; US.Top = 0; US.UndoPtr = 0; US.NextCmd = 1; US.Record = 1; US.Undo = 0; #endif #ifdef CONFIG_BOOKMARKS BMCount = 0; BMarks = 0; #endif #ifdef CONFIG_OBJ_ROUTINE rlst.Count = 0; rlst.Lines = 0; Routines = 0; #endif #ifdef CONFIG_WORD_HILIT WordList = 0; WordCount = 0; #endif //Name = strdup(AName); Allocate(0); AllocVis(0); Mode = GetModeForName(""); Flags = (Mode->Flags); BFI(this, BFI_Undo) = 0; BFI(this, BFI_ReadOnly) = 0; Modified = 0; MinRedraw = -1; MaxRedraw = -1; RedrawToEos = 0; #ifdef CONFIG_SYNTAX_HILIT StartHilit = 0; EndHilit = -1; HilitProc = 0; if (Mode && Mode->fColorize) HilitProc = GetHilitProc(Mode->fColorize->SyntaxParser); #endif InsertLine(CP,0,0); /* there should always be at least one line in the edit buffer */ Flags = (Mode->Flags); Modified = 0; } EBuffer::~EBuffer() { #ifdef CONFIG_HISTORY if (FileName != 0 && Loaded) UpdateFPos(FileName, VToR(CP.Row), CP.Col); #endif if (FileName && Loaded) markIndex.storeForBuffer(this); Clear(); if (LL) free(LL); //free(Name); if (FileName) free(FileName); #ifdef CONFIG_BOOKMARKS if (BMCount != 0) { for (int i = 0; i < BMCount; i++) free(BMarks[i].Name); free(BMarks); BMarks = 0; BMCount = 0; } #endif #ifdef CONFIG_OBJ_ROUTINE if (rlst.Lines) { free(rlst.Lines); rlst.Lines = 0; } #endif } void EBuffer::DeleteRelated() { #ifdef CONFIG_OBJ_ROUTINE if (Routines) { ::ActiveView->DeleteModel(Routines); Routines = 0; } #endif } int EBuffer::Clear() { Modified = 1; #ifdef CONFIG_SYNTAX_HILIT EndHilit = -1; StartHilit = 0; while (WordCount--) { free(WordList[WordCount]); } free(WordList); WordCount = 0; WordList = 0; #endif #ifdef CONFIG_OBJ_ROUTINE rlst.Count = 0; if (rlst.Lines) { free(rlst.Lines); rlst.Lines = 0; } #endif if (LL) { for (int i = 0; i < RCount; i++) delete LL[GapLine(i, RGap, RCount, RAllocated)]; free(LL); LL = 0; } RCount = RAllocated = RGap = 0; VCount = VAllocated = VGap = 0; if (VV) { free(VV); VV = 0; } #ifdef CONFIG_UNDOREDO FreeUndo(); #endif if (FCount != 0) { free(FF); FCount = 0; FF = 0; } return 0; } #ifdef CONFIG_UNDOREDO int EBuffer::FreeUndo() { for (int j = 0; j < US.Num; j++) free(US.Data[j]); free(US.Top); free(US.Data); US.Num = 0; US.Data = 0; US.Top = 0; US.Undo = 0; US.Record = 1; US.UndoPtr = 0; return 1; } #endif int EBuffer::Modify() { if (BFI(this, BFI_ReadOnly)) { Msg(S_ERROR, "File is read-only."); return 0; } if (Modified == 0) { struct stat StatBuf; if ((FileName != 0) && FileOk && (stat(FileName, &StatBuf) == 0)) { if (FileStatus.st_size != StatBuf.st_size || FileStatus.st_mtime != StatBuf.st_mtime) { View->MView->Win->Choice(GPC_ERROR, "Warning! Press Esc!", 0, "File %-.55s changed on disk!", FileName); switch (View->MView->Win->Choice(0, "File Changed on Disk", 2, "&Modify", "&Cancel", "%s", FileName)) { case 0: break; case 1: case -1: default: return 0; } } } #ifdef CONFIG_UNDOREDO if (BFI(this, BFI_Undo)) if (PushUChar(ucModified) == 0) return 0; #endif } Modified++; if (Modified == 0) Modified++; return 1; } int EBuffer::LoadRegion(EPoint * /*A*/, int /*FH*/, int /*StripChar*/, int /*LineChar*/) { return 0; } int EBuffer::InsertLine(EPoint Pos, int ACount, char *AChars) { if (InsLine(Pos.Row, 0) == 0) return 0; if (InsText(Pos.Row, Pos.Col, ACount, AChars) == 0) return 0; return 1; } int EBuffer::UpdateMark(EPoint &M, int Type, int Row, int Col, int Rows, int Cols) { switch (Type) { case umInsert: /* text inserted */ switch (BlockMode) { case bmLine: case bmColumn: if (M.Row >= Row) M.Row += Rows; break; case bmStream: if (Cols) { if (M.Row == Row) if (M.Col >= Col) M.Col += Cols; } if (Rows) { if (M.Row >= Row) M.Row += Rows; } break; } break; case umDelete: switch (BlockMode) { case bmLine: case bmColumn: if (M.Row >= Row) if (InRange(Row, M.Row, Row + Rows)) M.Row = Row; else M.Row -= Rows; break; case bmStream: if (Cols) { if (M.Row == Row) if (M.Col >= Col) if (M.Col < Col + Cols) M.Col = Col; else M.Col -= Cols; } if (Rows) { if (M.Row >= Row) if (M.Row < Row + Rows) { M.Row = Row; M.Col = 0; } else M.Row -= Rows; } } break; case umSplitLine: switch (BlockMode) { case bmLine: case bmColumn: if (M.Row == Row) { if (Col <= M.Col) { M.Row++; M.Col -= Col; } } else if (M.Row > Row) M.Row++; break; case bmStream: if (M.Row == Row) { if (Col <= M.Col) { M.Row++; M.Col -= Col; } } else if (M.Row > Row) M.Row++; break; } break; case umJoinLine: switch (BlockMode) { case bmLine: case bmColumn: if (M.Row == Row + 1) M.Row--; else if (M.Row > Row) M.Row--; break; case bmStream: if (M.Row == Row + 1) { M.Row--; M.Col += Col; } else if (M.Row > Row) M.Row--; break; } break; } return 1; } int EBuffer::UpdateMarker(int Type, int Row, int Col, int Rows, int Cols) { EPoint OldBB = BB, OldBE = BE; EView *V; UpdateMark(SavedPos, Type, Row, Col, Rows, Cols); UpdateMark(PrevPos, Type, Row, Col, Rows, Cols); UpdateMark(BB, Type, Row, Col, Rows, Cols); UpdateMark(BE, Type, Row, Col, Rows, Cols); V = View; while (V) { if (V->Model != this) assert(1 == 0); if (V != View) { EPoint M; M = GetViewVPort(V)->TP; UpdateMark(GetViewVPort(V)->TP, Type, Row, Col, Rows, Cols); GetViewVPort(V)->TP.Col = M.Col; UpdateMark(GetViewVPort(V)->CP, Type, Row, Col, Rows, Cols); } V = V->NextView; } #ifdef CONFIG_OBJ_ROUTINE for (int i = 0; i < rlst.Count && rlst.Lines; i++) { EPoint M; M.Col = 0; M.Row = rlst.Lines[i]; UpdateMark(M, Type, Row, Col, Rows, Cols); rlst.Lines[i] = M.Row; } #endif for (int f = 0; f < FCount; f++) { EPoint M; M.Col = 0; M.Row = FF[f].line; UpdateMark(M, Type, Row, Col, Rows, Cols); FF[f].line = M.Row; } #ifdef CONFIG_BOOKMARKS for (int b = 0; b < BMCount; b++) UpdateMark(BMarks[b].BM, Type, Row, Col, Rows, Cols); #endif if (OldBB.Row != BB.Row) { int MinL = Min(OldBB.Row, BB.Row); int MaxL = Max(OldBB.Row, BB.Row); if (MinL != -1 && MaxL != -1) Draw(MinL, MaxL); } if (OldBE.Row != BE.Row) { int MinL = Min(OldBE.Row, BE.Row); int MaxL = Max(OldBE.Row, BE.Row); if (MinL != -1 && MaxL != -1) Draw(MinL, MaxL); } return 1; } int EBuffer::ValidPos(EPoint Pos) { if ((Pos.Col >= 0) && (Pos.Row >= 0) && (Pos.Row < VCount)) return 1; return 0; } int EBuffer::RValidPos(EPoint Pos) { if ((Pos.Col >= 0) && (Pos.Row >= 0) && (Pos.Row < RCount)) return 1; return 0; } int EBuffer::AssertLine(int Row) { if (Row == RCount) if (InsLine(RCount, 0) == 0) return 0; return 1; } int EBuffer::SetFileName(const char *AFileName, const char *AMode) { FileOk = 0; free(FileName); FileName = strdup(AFileName); Mode = 0; if (AMode) Mode = FindMode(AMode); if (Mode == 0) Mode = GetModeForName(AFileName); assert(Mode != 0); Flags = (Mode->Flags); #ifdef CONFIG_SYNTAX_HILIT HilitProc = 0; if (Mode && Mode->fColorize) HilitProc = GetHilitProc(Mode->fColorize->SyntaxParser); #endif UpdateTitle(); return FileName?1:0; } int EBuffer::SetPos(int Col, int Row, int tabMode) { assert (Col >= 0 && Row >= 0 && Row < VCount); #ifdef CONFIG_UNDOREDO if (BFI(this, BFI_Undo) == 1 && BFI(this, BFI_UndoMoves) == 1) { if (PushULong(CP.Col) == 0) return 0; if (PushULong(CP.Row) == 0) return 0; if (PushUChar(ucPosition) == 0) return 0; } #endif if (AutoExtend) { BlockExtendBegin(); AutoExtend = 1; } PrevPos = CP; PrevPos.Row = (CP.Row < VCount) ? VToR(CP.Row) : (CP.Row - VCount + RCount); CP.Row = Row; CP.Col = Col; if (AutoExtend) { BlockExtendEnd(); AutoExtend = 1; } // if (View && View->Model == this ) { // View->GetVPort(); // } if (BFI(this, BFI_CursorThroughTabs) == 0) { if (tabMode == tmLeft) { if (MoveTabStart() == 0) return 0; } else if (tabMode == tmRight) { if (MoveTabEnd() == 0) return 0; } } if (ExtendGrab == 0 && AutoExtend == 0 && BFI(this, BFI_PersistentBlocks) == 0) { if (CheckBlock() == 1) if (BlockUnmark() == 0) return 0; } return 1; } int EBuffer::SetPosR(int Col, int Row, int tabMode) { assert (Row >= 0 && Row < RCount && Col >= 0); int L = RToV(Row); if (L == -1) if (ExposeRow(Row) == 0) return 0; L = RToV(Row); return SetPos(Col, L, tabMode); } int EBuffer::SetNearPos(int Col, int Row, int tabMode) { if (Row >= VCount) Row = VCount - 1; if (Row < 0) Row = 0; if (Col < 0) Col = 0; return SetPos(Col, Row, tabMode); } int EBuffer::SetNearPosR(int Col, int Row, int tabMode) { if (Row >= RCount) Row = RCount - 1; if (Row < 0) Row = 0; if (Col < 0) Col = 0; return SetPosR(Col, Row, tabMode); } int EBuffer::CenterPos(int Col, int Row, int tabMode) { assert(Row >= 0 && Row < VCount && Col >= 0); if (SetPos(Col, Row, tabMode) == 0) return 0; if (View && View->Model == this) { Row -= GetVPort()->Rows / 2; if (Row < 0) Row = 0; Col -= GetVPort()->Cols - 8; if (Col < 0) Col = 0; if (GetVPort()->SetTop(Col, Row) == 0) return 0; GetVPort()->ReCenter = 1; } return 1; } int EBuffer::CenterPosR(int Col, int Row, int tabMode) { int L; assert(Row >= 0 && Row < RCount && Col >= 0); L = RToV(Row); if (L == -1) if (ExposeRow(Row) == 0) return 0; L = RToV(Row); return CenterPos(Col, L, tabMode); } int EBuffer::CenterNearPos(int Col, int Row, int tabMode) { if (Row >= VCount) Row = VCount - 1; if (Row < 0) Row = 0; if (Col < 0) Col = 0; return CenterPos(Col, Row, tabMode); } int EBuffer::CenterNearPosR(int Col, int Row, int tabMode) { if (Row >= RCount) Row = RCount - 1; if (Row < 0) Row = 0; if (Col < 0) Col = 0; return CenterPosR(Col, Row, tabMode); } int EBuffer::LineLen(int Row) { assert(Row >= 0 && Row < RCount); PELine L = RLine(Row); return ScreenPos(L, L->Count); } int EBuffer::LineChars(int Row) { assert(Row >= 0 && Row < RCount); return RLine(Row)->Count; } int EBuffer::DelLine(int Row, int DoMark) { int VLine; int GapSize; // printf("DelLine: %d\n", Row); if (Row < 0) return 0; if (Row >= RCount) return 0; if (Modify() == 0) return 0; VLine = RToV(Row); if (VLine == -1) if (ExposeRow(Row) == 0) return 0; VLine = RToV(Row); assert(VLine != -1); if (FindFold(Row) != -1) { if (FoldDestroy(Row) == 0) return 0; } VLine = RToV(Row); assert(VLine != -1); #ifdef CONFIG_UNDOREDO if (BFI(this, BFI_Undo) == 1) { if (PushUData(RLine(Row)->Chars, RLine(Row)->Count) == 0) return 0; if (PushULong(RLine(Row)->Count) == 0) return 0; if (PushULong(Row) == 0) return 0; if (PushUChar(ucDelLine) == 0) return 0; } #endif if (DoMark) UpdateMarker(umDelete, Row, 0, 1, 0); //puts("Here"); Draw(Row, -1); Hilit(Row); assert(RAllocated >= RCount); if (RGap != Row) if (MoveRGap(Row) == 0) return 0; GapSize = RAllocated - RCount; delete LL[RGap + GapSize]; LL[RGap + GapSize] = 0; RCount--; GapSize++; if (RAllocated - RAllocated / 2 > RCount) { memmove(LL + RGap + GapSize - RAllocated / 3, LL + RGap + GapSize, sizeof(PELine) * (RCount - RGap)); if (Allocate(RAllocated - RAllocated / 3) == 0) return 0; } assert(VAllocated >= VCount); if (VGap != VLine) if (MoveVGap(VLine) == 0) return 0; GapSize = VAllocated - VCount; VV[VGap + GapSize] = 0; VCount--; GapSize++; if (VAllocated - VAllocated / 2 > VCount) { memmove(VV + VGap + GapSize - VAllocated / 3, VV + VGap + GapSize, sizeof(VV[0]) * (VCount - VGap)); if (AllocVis(VAllocated - VAllocated / 3) == 0) return 0; } return 1; } int EBuffer::InsLine(int Row, int DoAppend, int DoMark) { PELine L; int VLine = -1; // printf("InsLine: %d\n", Row); if (Row < 0) return 0; if (Row > RCount) return 0; if (Modify() == 0) return 0; if (DoAppend) { Row++; } if (Row < RCount) { VLine = RToV(Row); if (VLine == -1) if (ExposeRow(Row) == 0) return 0; VLine = RToV(Row); assert(VLine != -1); } else { VLine = VCount; } L = new ELine(0, (char *)0); if (L == 0) return 0; #ifdef CONFIG_UNDOREDO if (BFI(this, BFI_Undo) == 1) { if (PushULong(Row) == 0) return 0; if (PushUChar(ucInsLine) == 0) return 0; } #endif if (DoMark) UpdateMarker(umInsert, Row, 0, 1, 0); Draw(Row, -1); Hilit(Row); VLine = RToVN(Row); assert(RCount <= RAllocated); // printf("++ %d G:C:A :: %d - %d - %d\n", Row, RGap, RCount, RAllocated); if (RCount == RAllocated) { if (Allocate(RCount ? (RCount * 2) : 1) == 0) return 0; memmove(LL + RAllocated - (RCount - RGap), LL + RGap, sizeof(PELine) * (RCount - RGap)); } if (RGap != Row) if (MoveRGap(Row) == 0) return 0; LL[RGap] = L; RGap++; RCount++; // printf("-- %d G:C:A :: %d - %d - %d\n", Row, RGap, RCount, RAllocated); assert(VCount <= VAllocated); if (VCount == VAllocated) { if (AllocVis(VCount ? (VCount * 2) : 1) == 0) return 0; memmove(VV + VAllocated - (VCount - VGap), VV + VGap, sizeof(VV[0]) * (VCount - VGap)); } if (VGap != VLine) if (MoveVGap(VLine) == 0) return 0; VV[VGap] = Row - VGap; VGap++; VCount++; /* if (AllocVis(VCount + 1) == 0) return 0; memmove(VV + VLine + 1, VV + VLine, sizeof(VV[0]) * (VCount - VLine)); VCount++; Vis(VLine, Row - VLine);*/ return 1; } int EBuffer::DelChars(int Row, int Ofs, int ACount) { PELine L; // printf("DelChars: %d:%d %d\n", Row, Ofs, ACount); if (Row < 0) return 0; if (Row >= RCount) return 0; L = RLine(Row); if (Ofs < 0) return 0; if (Ofs >= L->Count) return 0; if (Ofs + ACount >= L->Count) ACount = L->Count - Ofs; if (ACount == 0) return 1; if (Modify() == 0) return 0; #ifdef CONFIG_UNDOREDO if (BFI(this, BFI_Undo) == 1) { if (PushUData(L->Chars + Ofs, ACount) == 0) return 0; if (PushULong(ACount) == 0) return 0; if (PushULong(Ofs) == 0) return 0; if (PushULong(Row) == 0) return 0; if (PushUChar(ucDelChars) == 0) return 0; } #endif if (L->Count > Ofs + ACount) memmove(L->Chars + Ofs, L->Chars + Ofs + ACount, L->Count - Ofs - ACount); L->Count -= ACount; if (L->Allocate(L->Count) == 0) return 0; Draw(Row, Row); Hilit(Row); // printf("OK\n"); return 1; } int EBuffer::InsChars(int Row, int Ofs, int ACount, char *Buffer) { PELine L; // printf("InsChars: %d:%d %d\n", Row, Ofs, ACount); assert(Row >= 0 && Row < RCount && Ofs >= 0); L = RLine(Row); if (Ofs < 0) return 0; if (Ofs > L->Count) return 0; if (ACount == 0) return 1; if (Modify() == 0) return 0; #ifdef CONFIG_UNDOREDO if (BFI(this, BFI_Undo) == 1) { if (PushULong(Row) == 0) return 0; if (PushULong(Ofs) == 0) return 0; if (PushULong(ACount) == 0) return 0; if (PushUChar(ucInsChars) == 0) return 0; } #endif if (L->Allocate(L->Count + ACount) == 0) return 0; if (L->Count > Ofs) memmove(L->Chars + Ofs + ACount, L->Chars + Ofs, L->Count - Ofs); if (Buffer == 0) memset(L->Chars + Ofs, ' ', ACount); else memmove(L->Chars + Ofs, Buffer, ACount); L->Count += ACount; Draw(Row, Row); Hilit(Row); // printf("OK\n"); return 1; } int EBuffer::UnTabPoint(int Row, int Col) { ELine *L; int Ofs, Pos, TPos; assert(Row >= 0 && Row < RCount && Col >= 0); L = RLine(Row); Ofs = CharOffset(L, Col); if (Ofs >= L->Count) return 1; if (L->Chars[Ofs] != '\t') return 1; Pos = ScreenPos(L, Ofs); if (Pos < Col) { TPos = NextTab(Pos, BFI(this, BFI_TabSize)); if (DelChars(Row, Ofs, 1) != 1) return 0; if (InsChars(Row, Ofs, TPos - Pos, 0) != 1) return 0; } return 1; } int EBuffer::ChgChars(int Row, int Ofs, int ACount, char * /*Buffer*/) { PELine L; assert(Row >= 0 && Row < RCount && Ofs >= 0); L = RLine(Row); if (Ofs < 0) return 0; if (Ofs > L->Count) return 0; if (ACount == 0) return 1; if (Modify() == 0) return 0; #ifdef CONFIG_UNDOREDO if (BFI(this, BFI_Undo) == 1) { if (PushUData(L->Chars + Ofs, ACount) == 0) return 0; if (PushULong(ACount) == 0) return 0; if (PushULong(Ofs) == 0) return 0; if (PushULong(Row) == 0) return 0; if (PushUChar(ucDelChars) == 0) return 0; if (PushULong(Row) == 0) return 0; if (PushULong(Ofs) == 0) return 0; if (PushULong(ACount) == 0) return 0; if (PushUChar(ucInsChars) == 0) return 0; } #endif Hilit(Row); Draw(Row, Row); return 1; } int EBuffer::DelText(int Row, int Col, int ACount, int DoMark) { int L, B, C; // printf("DelTExt: %d:%d %d\n", Row, Col, ACount); assert(Row >= 0 && Row < RCount && Col >= 0); if (Modify() == 0) return 0; if (ACount == 0) return 1; L = LineLen(Row); if (Col >= L) return 1; if (ACount == -1 || ACount + Col > L) ACount = L - Col; if (UnTabPoint(Row, Col) == 0) return 0; if (UnTabPoint(Row, Col + ACount) == 0) return 0; B = CharOffset(RLine(Row), Col); C = CharOffset(RLine(Row), Col + ACount); if ((ACount > 0) && (B != -1) && (C != -1)) { if (DelChars(Row, B, C - B) == 0) return 0; if (DoMark) UpdateMarker(umDelete, Row, Col, 0, ACount); } // printf("OK\n"); return 1; } int EBuffer::InsText(int Row, int Col, int ACount, char *ABuffer, int DoMark) { int B, L; // printf("InsText: %d:%d %d\n", Row, Col, ACount); assert(Row >= 0 && Row < RCount && Col >= 0 && ACount >= 0); if (ACount == 0) return 1; if (Modify() == 0) return 0; if (DoMark) UpdateMarker(umInsert, Row, Col, 0, ACount); L = LineLen(Row); if (L < Col) { if (InsChars(Row, RLine(Row)->Count, Col - L, 0) == 0) return 0; } else if (UnTabPoint(Row, Col) == 0) return 0; B = CharOffset(RLine(Row), Col); if (InsChars(Row, B, ACount, ABuffer) == 0) return 0; // printf("OK\n"); return 1; } int EBuffer::PadLine(int Row, int Length) { int L; L = LineLen(Row); if (L < Length) if (InsChars(Row, RLine(Row)->Count, Length - L, 0) == 0) return 0; return 1; } int EBuffer::InsLineText(int Row, int Col, int ACount, int LCol, PELine Line) { int Ofs, Pos, TPos, C, B, L; //fprintf(stderr, "\n\nInsLineText: %d:%d %d %d", Row, Col, ACount, LCol); assert(Row >= 0 && Row < RCount && Col >= 0 && LCol >= 0); if (BFI(this, BFI_ReadOnly) == 1) return 0; L = ScreenPos(Line, Line->Count); if (LCol >= L) return 1; if (ACount == -1) ACount = L - LCol; if (ACount + LCol > L) ACount = L - LCol; if (ACount == 0) return 1; assert(ACount > 0); B = Ofs = CharOffset(Line, LCol); if (Ofs < Line->Count && Line->Chars[Ofs] == '\t') { Pos = ScreenPos(Line, Ofs); if (Pos < LCol) { TPos = NextTab(Pos, BFI(this, BFI_TabSize)); if (InsText(Row, Col, TPos - LCol, 0) == 0) return 0; Col += TPos - LCol; ACount -= TPos - LCol; LCol = TPos; B++; } } C = Ofs = CharOffset(Line, LCol + ACount); if (Ofs < Line->Count && Line->Chars[Ofs] == '\t') { Pos = ScreenPos(Line, Ofs); if (Pos < LCol + ACount) { if (InsText(Row, Col, LCol + ACount - Pos, 0) == 0) return 0; } } //fprintf(stderr, "B = %d, C = %d\n", B, C); C -= B; if (C <= 0) return 1; if (InsText(Row, Col, C, Line->Chars + B) == 0) return 0; // printf("OK\n"); return 1; } int EBuffer::SplitLine(int Row, int Col) { int VL; assert(Row >= 0 && Row < RCount && Col >= 0); if (BFI(this, BFI_ReadOnly) == 1) return 0; VL = RToV(Row); if (VL == -1) if (ExposeRow(Row) == 0) return 0; if (Row > 0) { VL = RToV(Row - 1); if (VL == -1) if (ExposeRow(Row - 1) == 0) return 0; } VL = RToV(Row); assert(VL != -1); if (Col == 0) { if (InsLine(Row, 0, 1) == 0) return 0; } else { UpdateMarker(umSplitLine, Row, Col, 0, 0); if (InsLine(Row, 1, 0) == 0) return 0; RLine(Row)->StateE = short((Row > 0) ? RLine(Row - 1)->StateE : 0); if (Col < LineLen(Row)) { int P, L; //if (RLine(Row)->ExpandTabs(Col, -2, &Flags) == 0) return 0; if (UnTabPoint(Row, Col) != 1) return 0; P = CharOffset(RLine(Row), Col); L = LineLen(Row); if (InsText(Row + 1, 0, RLine(Row)->Count - P, RLine(Row)->Chars + P, 0) == 0) return 0; if (DelText(Row, Col, L - Col, 0) == 0) return 0; } } Draw(Row, -1); Hilit(Row); return 1; } int EBuffer::JoinLine(int Row, int Col) { int Len, VLine; if (BFI(this, BFI_ReadOnly) == 1) return 0; if (Row < 0 || Row >= RCount - 1) return 0; if (Col < 0) return 0; Len = LineLen(Row); if (Col < Len) Col = Len; VLine = RToV(Row); if (VLine == -1) { if (ExposeRow(Row) == 0) return 0; if (ExposeRow(Row + 1) == 0) return 0; } VLine = RToV(Row); if (Col == 0 && RLine(Row)->Count == 0) { if (DelLine(Row, 1) == 0) return 0; } else { if (InsText(Row, Col, RLine(Row + 1)->Count, RLine(Row + 1)->Chars, 0) == 0) return 0; if (DelLine(Row + 1, 0) == 0) return 0; UpdateMarker(umJoinLine, Row, Col, 0, 0); } Draw(Row, -1); Hilit(Row); return 1; }