home *** CD-ROM | disk | FTP | other *** search
-
- {*******************************************************}
- { }
- { Turbo Pascal Version 6.0 }
- { Turbo Vision Unit }
- { }
- { Copyright (c) 1990 Borland International }
- { }
- {*******************************************************}
-
- unit Editors;
-
- {$F+,I-,O+,S-,V-,X+,D-}
-
- interface
-
- uses Drivers, Objects, Views;
-
- const
- cmSave = 80;
- cmSaveAs = 81;
- cmFind = 82;
- cmReplace = 83;
- cmSearchAgain = 84;
-
- const
- cmCharLeft = 500;
- cmCharRight = 501;
- cmWordLeft = 502;
- cmWordRight = 503;
- cmLineStart = 504;
- cmLineEnd = 505;
- cmLineUp = 506;
- cmLineDown = 507;
- cmPageUp = 508;
- cmPageDown = 509;
- cmTextStart = 510;
- cmTextEnd = 511;
- cmNewLine = 512;
- cmBackSpace = 513;
- cmDelChar = 514;
- cmDelWord = 515;
- cmDelStart = 516;
- cmDelEnd = 517;
- cmDelLine = 518;
- cmInsMode = 519;
- cmStartSelect = 520;
- cmHideSelect = 521;
- cmIndentMode = 522;
- cmUpdateTitle = 523;
-
- const
- edOutOfMemory = 0;
- edReadError = 1;
- edWriteError = 2;
- edCreateError = 3;
- edSaveModify = 4;
- edSaveUntitled = 5;
- edSaveAs = 6;
- edFind = 7;
- edSearchFailed = 8;
- edReplace = 9;
- edReplacePrompt = 10;
-
- const
- efCaseSensitive = $0001;
- efWholeWordsOnly = $0002;
- efPromptOnReplace = $0004;
- efReplaceAll = $0008;
- efDoReplace = $0010;
- efBackupFiles = $0100;
-
- const
- CIndicator = #2#3;
- CEditor = #6#7;
- CMemo = #26#27;
-
- const
- MaxLineLength = 256;
-
- type
- TEditorDialog = function(Dialog: Integer; Info: Pointer): Word;
-
- type
- PIndicator = ^TIndicator;
- TIndicator = object(TView)
- Location: TPoint;
- Modified: Boolean;
- constructor Init(var Bounds: TRect);
- procedure Draw; virtual;
- function GetPalette: PPalette; virtual;
- procedure SetState(AState: Word; Enable: Boolean); virtual;
- procedure SetValue(ALocation: TPoint; AModified: Boolean);
- end;
-
- type
- PEditBuffer = ^TEditBuffer;
- TEditBuffer = array[0..65519] of Char;
-
- type
- PEditor = ^TEditor;
- TEditor = object(TView)
- HScrollBar: PScrollBar;
- VScrollBar: PScrollBar;
- Indicator: PIndicator;
- Buffer: PEditBuffer;
- BufSize: Word;
- BufLen: Word;
- GapLen: Word;
- SelStart: Word;
- SelEnd: Word;
- CurPtr: Word;
- CurPos: TPoint;
- Delta: TPoint;
- Limit: TPoint;
- DrawLine: Integer;
- DrawPtr: Word;
- DelCount: Word;
- InsCount: Word;
- IsValid: Boolean;
- CanUndo: Boolean;
- Modified: Boolean;
- Selecting: Boolean;
- Overwrite: Boolean;
- AutoIndent: Boolean;
- constructor Init(var Bounds: TRect;
- AHScrollBar, AVScrollBar: PScrollBar;
- AIndicator: PIndicator; ABufSize: Word);
- constructor Load(var S: TStream);
- destructor Done; virtual;
- function BufChar(P: Word): Char;
- function BufPtr(P: Word): Word;
- procedure ChangeBounds(var Bounds: TRect); virtual;
- procedure ConvertEvent(var Event: TEvent); virtual;
- function CursorVisible: Boolean;
- procedure DeleteSelect;
- procedure DoneBuffer; virtual;
- procedure Draw; virtual;
- function GetPalette: PPalette; virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- procedure InitBuffer; virtual;
- function InsertBuffer(var P: PEditBuffer; Offset, Length: Word;
- AllowUndo, SelectText: Boolean): Boolean;
- function InsertFrom(Editor: PEditor): Boolean; virtual;
- function InsertText(Text: Pointer; Length: Word;
- SelectText: Boolean): Boolean;
- procedure ScrollTo(X, Y: Integer);
- function Search(FindStr: String; Opts: Word): Boolean;
- function SetBufSize(NewSize: Word): Boolean; virtual;
- procedure SetCmdState(Command: Word; Enable: Boolean);
- procedure SetSelect(NewStart, NewEnd: Word; CurStart: Boolean);
- procedure SetState(AState: Word; Enable: Boolean); virtual;
- procedure Store(var S: TStream);
- procedure TrackCursor(Center: Boolean);
- procedure Undo;
- procedure UpdateCommands; virtual;
- function Valid(Command: Word): Boolean; virtual;
- private
- LockCount: Byte;
- UpdateFlags: Byte;
- KeyState: Integer;
- function CharPos(P, Target: Word): Integer;
- function CharPtr(P: Word; Target: Integer): Word;
- function ClipCopy: Boolean;
- procedure ClipCut;
- procedure ClipPaste;
- procedure DeleteRange(StartPtr, EndPtr: Word; DelSelect: Boolean);
- procedure DoUpdate;
- procedure DoSearchReplace;
- procedure DrawLines(Y, Count: Integer; LinePtr: Word);
- procedure FormatLine(var DrawBuf; LinePtr: Word;
- Width: Integer; Colors: Word);
- procedure Find;
- function GetMousePtr(Mouse: TPoint): Word;
- function HasSelection: Boolean;
- procedure HideSelect;
- function IsClipboard: Boolean;
- function LineEnd(P: Word): Word;
- function LineMove(P: Word; Count: Integer): Word;
- function LineStart(P: Word): Word;
- procedure Lock;
- procedure NewLine;
- function NextChar(P: Word): Word;
- function NextLine(P: Word): Word;
- function NextWord(P: Word): Word;
- function PrevChar(P: Word): Word;
- function PrevLine(P: Word): Word;
- function PrevWord(P: Word): Word;
- procedure Replace;
- procedure SetBufLen(Length: Word);
- procedure SetCurPtr(P: Word; SelectMode: Byte);
- procedure StartSelect;
- procedure ToggleInsMode;
- procedure Unlock;
- procedure Update(AFlags: Byte);
- end;
-
- type
- TMemoData = record
- Length: Word;
- Buffer: TEditBuffer;
- end;
-
- type
- PMemo = ^TMemo;
- TMemo = object(TEditor)
- constructor Load(var S: TStream);
- function DataSize: Word; virtual;
- procedure GetData(var Rec); virtual;
- function GetPalette: PPalette; virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- procedure SetData(var Rec); virtual;
- procedure Store(var S: TStream);
- end;
-
- type
- PFileEditor = ^TFileEditor;
- TFileEditor = object(TEditor)
- FileName: FNameStr;
- constructor Init(var Bounds: TRect;
- AHScrollBar, AVScrollBar: PScrollBar;
- AIndicator: PIndicator; AFileName: FNameStr);
- constructor Load(var S: TStream);
- procedure DoneBuffer; virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- procedure InitBuffer; virtual;
- function LoadFile: Boolean;
- function Save: Boolean;
- function SaveAs: Boolean;
- function SaveFile: Boolean;
- function SetBufSize(NewSize: Word): Boolean; virtual;
- procedure Store(var S: TStream);
- procedure UpdateCommands; virtual;
- function Valid(Command: Word): Boolean; virtual;
- end;
-
- type
- PEditWindow = ^TEditWindow;
- TEditWindow = object(TWindow)
- Editor: PFileEditor;
- constructor Init(var Bounds: TRect;
- FileName: FNameStr; ANumber: Integer);
- constructor Load(var S: TStream);
- procedure Close; virtual;
- function GetTitle(MaxSize: Integer): TTitleStr; virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- procedure Store(var S: TStream);
- end;
-
- function DefEditorDialog(Dialog: Integer; Info: Pointer): Word;
-
- const
- WordChars: set of Char = ['0'..'9', 'A'..'Z', '_', 'a'..'z'];
- EditorDialog: TEditorDialog = DefEditorDialog;
- EditorFlags: Word = efBackupFiles + efPromptOnReplace;
- FindStr: String[80] = '';
- ReplaceStr: String[80] = '';
- Clipboard: PEditor = nil;
-
- type
- TFindDialogRec = record
- Find: String[80];
- Options: Word;
- end;
-
- type
- TReplaceDialogRec = record
- Find: String[80];
- Replace: String[80];
- Options: Word;
- end;
-
- const
- REditor: TStreamRec = (
- ObjType: 70;
- VmtLink: Ofs(TypeOf(TEditor)^);
- Load: @TEditor.Load;
- Store: @TEditor.Store
- );
- RMemo: TStreamRec = (
- ObjType: 71;
- VmtLink: Ofs(TypeOf(TMemo)^);
- Load: @TMemo.Load;
- Store: @TMemo.Store
- );
- RFileEditor: TStreamRec = (
- ObjType: 72;
- VmtLink: Ofs(TypeOf(TFileEditor)^);
- Load: @TFileEditor.Load;
- Store: @TFileEditor.Store
- );
- RIndicator: TStreamRec = (
- ObjType: 73;
- VmtLink: Ofs(TypeOf(TIndicator)^);
- Load: @TIndicator.Load;
- Store: @TIndicator.Store
- );
- REditWindow: TStreamRec = (
- ObjType: 74;
- VmtLink: Ofs(TypeOf(TEditWindow)^);
- Load: @TEditWindow.Load;
- Store: @TEditWindow.Store
- );
-
- procedure RegisterEditors;
-
- implementation
-
- uses Memory, Buffers, Dos;
-
- const
- ufUpdate = $01;
- ufLine = $02;
- ufView = $04;
-
- const
- smExtend = $01;
- smDouble = $02;
-
- const
- sfSearchFailed = $FFFF;
-
- const
- FirstKeys: array[0..37 * 2] of Word = (37,
- Ord(^A), cmWordLeft, Ord(^C), cmPageDown,
- Ord(^D), cmCharRight, Ord(^E), cmLineUp,
- Ord(^F), cmWordRight, Ord(^G), cmDelChar,
- Ord(^H), cmBackSpace, Ord(^K), $FF02,
- Ord(^L), cmSearchAgain, Ord(^M), cmNewLine,
- Ord(^O), cmIndentMode, Ord(^Q), $FF01,
- Ord(^R), cmPageUp, Ord(^S), cmCharLeft,
- Ord(^T), cmDelWord, Ord(^U), cmUndo,
- Ord(^V), cmInsMode, Ord(^X), cmLineDown,
- Ord(^Y), cmDelLine, kbLeft, cmCharLeft,
- kbRight, cmCharRight, kbCtrlLeft, cmWordLeft,
- kbCtrlRight, cmWordRight, kbHome, cmLineStart,
- kbEnd, cmLineEnd, kbUp, cmLineUp,
- kbDown, cmLineDown, kbPgUp, cmPageUp,
- kbPgDn, cmPageDown, kbCtrlPgUp, cmTextStart,
- kbCtrlPgDn, cmTextEnd, kbIns, cmInsMode,
- kbDel, cmDelChar, kbShiftIns, cmPaste,
- kbShiftDel, cmCut, kbCtrlIns, cmCopy,
- kbCtrlDel, cmClear);
- QuickKeys: array[0..8 * 2] of Word = (8,
- Ord('A'), cmReplace, Ord('C'), cmTextEnd,
- Ord('D'), cmLineEnd, Ord('F'), cmFind,
- Ord('H'), cmDelStart, Ord('R'), cmTextStart,
- Ord('S'), cmLineStart, Ord('Y'), cmDelEnd);
- BlockKeys: array[0..5 * 2] of Word = (5,
- Ord('B'), cmStartSelect, Ord('C'), cmPaste,
- Ord('H'), cmHideSelect, Ord('K'), cmCopy,
- Ord('Y'), cmCut);
- KeyMap: array[0..2] of Pointer = (@FirstKeys, @QuickKeys, @BlockKeys);
-
- function DefEditorDialog(Dialog: Integer; Info: Pointer): Word;
- begin
- DefEditorDialog := cmCancel;
- end;
-
- function Min(X, Y: Integer): Integer; assembler;
- asm
- MOV AX,X
- CMP AX,Y
- JLE @@1
- MOV AX,Y
- @@1:
- end;
-
- function Max(X, Y: Integer): Integer; assembler;
- asm
- MOV AX,X
- CMP AX,Y
- JGE @@1
- MOV AX,Y
- @@1:
- end;
-
- function MinWord(X, Y: Word): Word; assembler;
- asm
- MOV AX,X
- CMP AX,Y
- JBE @@1
- MOV AX,Y
- @@1:
- end;
-
- function MaxWord(X, Y: Word): Word; assembler;
- asm
- MOV AX,X
- CMP AX,Y
- JAE @@1
- MOV AX,Y
- @@1:
- end;
-
- function CountLines(var Buf; Count: Word): Integer; assembler;
- asm
- LES DI,Buf
- MOV CX,Count
- XOR DX,DX
- MOV AL,0DH
- CLD
- @@1: JCXZ @@2
- REPNE SCASB
- JNE @@2
- INC DX
- JMP @@1
- @@2: MOV AX,DX
- end;
-
- function ScanKeyMap(KeyMap: Pointer; KeyCode: Word): Word; assembler;
- asm
- PUSH DS
- LDS SI,KeyMap
- MOV DX,KeyCode
- CLD
- LODSW
- MOV CX,AX
- @@1: LODSW
- MOV BX,AX
- LODSW
- OR BL,BL
- JE @@2
- CMP BL,DL
- JNE @@3
- OR BH,BH
- JE @@4
- @@2: CMP BH,DH
- JE @@4
- @@3: LOOP @@1
- XOR AX,AX
- @@4: POP DS
- end;
-
- function Scan(var Block; Size: Word; Str: String): Word; assembler;
- asm
- PUSH DS
- LES DI,Block
- LDS SI,Str
- MOV CX,Size
- JCXZ @@3
- CLD
- LODSB
- CMP AL,1
- JB @@5
- JA @@1
- LODSB
- REPNE SCASB
- JNE @@3
- JMP @@5
- @@1: XOR AH,AH
- MOV BX,AX
- DEC BX
- MOV DX,CX
- SUB DX,AX
- JB @@3
- LODSB
- INC DX
- INC DX
- @@2: DEC DX
- MOV CX,DX
- REPNE SCASB
- JNE @@3
- MOV DX,CX
- MOV CX,BX
- REP CMPSB
- JE @@4
- SUB CX,BX
- ADD SI,CX
- ADD DI,CX
- INC DI
- OR DX,DX
- JNE @@2
- @@3: XOR AX,AX
- JMP @@6
- @@4: SUB DI,BX
- @@5: MOV AX,DI
- SUB AX,WORD PTR Block
- @@6: DEC AX
- POP DS
- end;
-
- function IScan(var Block; Size: Word; Str: String): Word; assembler;
- var
- S: String;
- asm
- PUSH DS
- MOV AX,SS
- MOV ES,AX
- LEA DI,S
- LDS SI,Str
- XOR AH,AH
- LODSB
- STOSB
- MOV CX,AX
- MOV BX,AX
- JCXZ @@9
- @@1: LODSB
- CMP AL,'a'
- JB @@2
- CMP AL,'z'
- JA @@2
- SUB AL,20H
- @@2: STOSB
- LOOP @@1
- SUB DI,BX
- LDS SI,Block
- MOV CX,Size
- JCXZ @@8
- CLD
- SUB CX,BX
- JB @@8
- INC CX
- @@4: MOV AH,ES:[DI]
- AND AH,$DF
- @@5: LODSB
- AND AL,$DF
- CMP AL,AH
- LOOPNE @@5
- JNE @@8
- DEC SI
- MOV DX,CX
- MOV CX,BX
- @@6: REPE CMPSB
- JE @@10
- MOV AL,DS:[SI-1]
- CMP AL,'a'
- JB @@7
- CMP AL,'z'
- JA @@7
- SUB AL,20H
- @@7: CMP AL,ES:[DI-1]
- JE @@6
- SUB CX,BX
- ADD SI,CX
- ADD DI,CX
- INC SI
- MOV CX,DX
- JNE @@4
- @@8: XOR AX,AX
- JMP @@11
- @@9: MOV AX, 1
- JMP @@11
- @@10: SUB SI,BX
- MOV AX,SI
- SUB AX,WORD PTR Block
- INC AX
- @@11: DEC AX
- POP DS
- end;
-
- { TIndicator }
-
- constructor TIndicator.Init(var Bounds: TRect);
- var
- R: TRect;
- begin
- TView.Init(Bounds);
- GrowMode := gfGrowLoY + gfGrowHiY;
- end;
-
- procedure TIndicator.Draw;
- var
- Color: Byte;
- Frame: Char;
- L: array[0..1] of Longint;
- S: String[15];
- B: TDrawBuffer;
- begin
- if State and sfDragging = 0 then
- begin
- Color := GetColor(1);
- Frame := #205;
- end else
- begin
- Color := GetColor(2);
- Frame := #196;
- end;
- MoveChar(B, Frame, Color, Size.X);
- if Modified then WordRec(B[0]).Lo := 15;
- L[0] := Location.Y + 1;
- L[1] := Location.X + 1;
- FormatStr(S, ' %d:%d ', L);
- MoveStr(B[8 - Pos(':', S)], S, Color);
- WriteBuf(0, 0, Size.X, 1, B);
- end;
-
- function TIndicator.GetPalette: PPalette;
- const
- P: string[Length(CIndicator)] = CIndicator;
- begin
- GetPalette := @P;
- end;
-
- procedure TIndicator.SetState(AState: Word; Enable: Boolean);
- begin
- TView.SetState(AState, Enable);
- if AState = sfDragging then DrawView;
- end;
-
- procedure TIndicator.SetValue(ALocation: TPoint; AModified: Boolean);
- begin
- if (Longint(Location) <> Longint(ALocation)) or
- (Modified <> AModified) then
- begin
- Location := ALocation;
- Modified := AModified;
- DrawView;
- end;
- end;
-
- { TEditor }
-
- constructor TEditor.Init(var Bounds: TRect;
- AHScrollBar, AVScrollBar: PScrollBar;
- AIndicator: PIndicator; ABufSize: Word);
- begin
- TView.Init(Bounds);
- GrowMode := gfGrowHiX + gfGrowHiY;
- Options := Options or ofSelectable;
- EventMask := evMouseDown + evKeyDown + evCommand + evBroadcast;
- ShowCursor;
- HScrollBar := AHScrollBar;
- VScrollBar := AVScrollBar;
- Indicator := AIndicator;
- BufSize := ABufSize;
- CanUndo := True;
- InitBuffer;
- if Buffer <> nil then IsValid := True else
- begin
- EditorDialog(edOutOfMemory, nil);
- BufSize := 0;
- end;
- SetBufLen(0);
- end;
-
- constructor TEditor.Load(var S: TStream);
- begin
- TView.Load(S);
- GetPeerViewPtr(S, HScrollBar);
- GetPeerViewPtr(S, VScrollBar);
- GetPeerViewPtr(S, Indicator);
- S.Read(BufSize, SizeOf(Word));
- S.Read(CanUndo, SizeOf(Boolean));
- InitBuffer;
- if Buffer <> nil then IsValid := True else
- begin
- EditorDialog(edOutOfMemory, nil);
- BufSize := 0;
- end;
- Lock;
- SetBufLen(0);
- end;
-
- destructor TEditor.Done;
- begin
- DoneBuffer;
- TView.Done;
- end;
-
- function TEditor.BufChar(P: Word): Char; assembler;
- asm
- LES DI,Self
- MOV BX,P
- CMP BX,ES:[DI].TEditor.CurPtr
- JB @@1
- ADD BX,ES:[DI].TEditor.GapLen
- @@1: LES DI,ES:[DI].TEditor.Buffer
- MOV AL,ES:[DI+BX]
- end;
-
- function TEditor.BufPtr(P: Word): Word; assembler;
- asm
- LES DI,Self
- MOV AX,P
- CMP AX,ES:[DI].TEditor.CurPtr
- JB @@1
- ADD AX,ES:[DI].TEditor.GapLen
- @@1:
- end;
-
- procedure TEditor.ChangeBounds(var Bounds: TRect);
- begin
- SetBounds(Bounds);
- Delta.X := Max(0, Min(Delta.X, Limit.X - Size.X));
- Delta.Y := Max(0, Min(Delta.Y, Limit.Y - Size.Y));
- Update(ufView);
- end;
-
- function TEditor.CharPos(P, Target: Word): Integer;
- var
- Pos: Integer;
- begin
- Pos := 0;
- while P < Target do
- begin
- if BufChar(P) = #9 then Pos := Pos or 7;
- Inc(Pos);
- Inc(P);
- end;
- CharPos := Pos;
- end;
-
- function TEditor.CharPtr(P: Word; Target: Integer): Word;
- var
- Pos: Integer;
- begin
- Pos := 0;
- while (Pos < Target) and (P < BufLen) and (BufChar(P) <> #13) do
- begin
- if BufChar(P) = #9 then Pos := Pos or 7;
- Inc(Pos);
- Inc(P);
- end;
- if Pos > Target then Dec(P);
- CharPtr := P;
- end;
-
- function TEditor.ClipCopy: Boolean;
- begin
- ClipCopy := False;
- if (Clipboard <> nil) and (Clipboard <> @Self) then
- begin
- ClipCopy := Clipboard^.InsertFrom(@Self);
- Selecting := False;
- Update(ufUpdate);
- end;
- end;
-
- procedure TEditor.ClipCut;
- begin
- if ClipCopy then DeleteSelect;
- end;
-
- procedure TEditor.ClipPaste;
- begin
- if (Clipboard <> nil) and (Clipboard <> @Self) then InsertFrom(Clipboard);
- end;
-
- procedure TEditor.ConvertEvent(var Event: TEvent);
- var
- Key: Word;
- begin
- if Event.What = evKeyDown then
- begin
- Key := Event.KeyCode;
- if KeyState <> 0 then
- begin
- if (Lo(Key) >= $01) and (Lo(Key) <= $1A) then Inc(Key, $40);
- if (Lo(Key) >= $61) and (Lo(Key) <= $7A) then Dec(Key, $20);
- end;
- Key := ScanKeyMap(KeyMap[KeyState], Key);
- KeyState := 0;
- if Key <> 0 then
- if Hi(Key) = $FF then
- begin
- KeyState := Lo(Key);
- ClearEvent(Event);
- end else
- begin
- Event.What := evCommand;
- Event.Command := Key;
- end;
- end;
- end;
-
- function TEditor.CursorVisible: Boolean;
- begin
- CursorVisible := (CurPos.Y >= Delta.Y) and (CurPos.Y < Delta.Y + Size.Y);
- end;
-
- procedure TEditor.DeleteRange(StartPtr, EndPtr: Word; DelSelect: Boolean);
- begin
- if HasSelection and DelSelect then DeleteSelect else
- begin
- SetSelect(CurPtr, EndPtr, True);
- DeleteSelect;
- SetSelect(StartPtr, CurPtr, False);
- DeleteSelect;
- end;
- end;
-
- procedure TEditor.DeleteSelect;
- begin
- InsertText(nil, 0, False);
- end;
-
- procedure TEditor.DoneBuffer;
- begin
- if Buffer <> nil then FreeMem(Buffer, BufSize);
- end;
-
- procedure TEditor.DoSearchReplace;
- var
- I: Word;
- C: TPoint;
- begin
- repeat
- I := cmCancel;
- if not Search(FindStr, EditorFlags) then
- begin
- if EditorFlags and (efReplaceAll + efDoReplace) <>
- (efReplaceAll + efDoReplace) then
- EditorDialog(edSearchFailed, nil)
- end
- else if EditorFlags and efDoReplace <> 0 then
- begin
- I := cmYes;
- if EditorFlags and efPromptOnReplace <> 0 then
- begin
- MakeGlobal(Cursor, C);
- I := EditorDialog(edReplacePrompt, Pointer(C));
- end;
- if I = cmYes then
- begin
- Lock;
- InsertText(@ReplaceStr[1], Length(ReplaceStr), False);
- TrackCursor(False);
- Unlock;
- end;
- end;
- until (I = cmCancel) or (EditorFlags and efReplaceAll = 0);
- end;
-
- procedure TEditor.DoUpdate;
- begin
- if UpdateFlags <> 0 then
- begin
- SetCursor(CurPos.X - Delta.X, CurPos.Y - Delta.Y);
- if UpdateFlags and ufView <> 0 then DrawView else
- if UpdateFlags and ufLine <> 0 then
- DrawLines(CurPos.Y - Delta.Y, 1, LineStart(CurPtr));
- if HScrollBar <> nil then
- HScrollBar^.SetParams(Delta.X, 0, Limit.X - Size.X, Size.X div 2, 1);
- if VScrollBar <> nil then
- VScrollBar^.SetParams(Delta.Y, 0, Limit.Y - Size.Y, Size.Y - 1, 1);
- if Indicator <> nil then Indicator^.SetValue(CurPos, Modified);
- if State and sfActive <> 0 then UpdateCommands;
- UpdateFlags := 0;
- end;
- end;
-
- procedure TEditor.Draw;
- begin
- if DrawLine <> Delta.Y then
- begin
- DrawPtr := LineMove(DrawPtr, Delta.Y - DrawLine);
- DrawLine := Delta.Y;
- end;
- DrawLines(0, Size.Y, DrawPtr);
- end;
-
- procedure TEditor.DrawLines(Y, Count: Integer; LinePtr: Word);
- var
- Color: Word;
- B: array[0..MaxLineLength - 1] of Word;
- begin
- Color := GetColor($0201);
- while Count > 0 do
- begin
- FormatLine(B, LinePtr, Delta.X + Size.X, Color);
- WriteBuf(0, Y, Size.X, 1, B[Delta.X]);
- LinePtr := NextLine(LinePtr);
- Inc(Y);
- Dec(Count);
- end;
- end;
-
- procedure TEditor.Find;
- var
- FindRec: TFindDialogRec;
- begin
- with FindRec do
- begin
- Find := FindStr;
- Options := EditorFlags;
- if EditorDialog(edFind, @FindRec) <> cmCancel then
- begin
- FindStr := Find;
- EditorFlags := Options and not efDoReplace;
- DoSearchReplace;
- end;
- end;
- end;
-
- procedure TEditor.FormatLine(var DrawBuf; LinePtr: Word;
- Width: Integer; Colors: Word); assembler;
- asm
- PUSH DS
- LDS BX,Self
- LES DI,DrawBuf
- MOV SI,LinePtr
- XOR DX,DX
- CLD
- MOV AH,Colors.Byte[0]
- MOV CX,DS:[BX].TEditor.SelStart
- CALL @@10
- MOV AH,Colors.Byte[1]
- MOV CX,DS:[BX].TEditor.CurPtr
- CALL @@10
- ADD SI,DS:[BX].TEditor.GapLen
- MOV CX,DS:[BX].TEditor.SelEnd
- ADD CX,DS:[BX].TEditor.GapLen
- CALL @@10
- MOV AH,Colors.Byte[0]
- MOV CX,DS:[BX].TEditor.BufSize
- CALL @@10
- JMP @@31
- @@10: SUB CX,SI
- JA @@11
- RETN
- @@11: LDS BX,DS:[BX].TEditor.Buffer
- ADD SI,BX
- MOV BX,Width
- @@12: LODSB
- CMP AL,' '
- JB @@20
- @@13: STOSW
- INC DX
- @@14: CMP DX,BX
- JAE @@30
- LOOP @@12
- LDS BX,Self
- SUB SI,DS:[BX].TEditor.Buffer.Word[0]
- RETN
- @@20: CMP AL,0DH
- JE @@30
- CMP AL,09H
- JNE @@13
- MOV AL,' '
- @@21: STOSW
- INC DX
- TEST DL,7
- JNE @@21
- JMP @@14
- @@30: POP CX
- @@31: MOV AL,' '
- MOV CX,Width
- SUB CX,DX
- JBE @@32
- REP STOSW
- @@32: POP DS
- end;
-
- function TEditor.GetMousePtr(Mouse: TPoint): Word;
- begin
- MakeLocal(Mouse, Mouse);
- Mouse.X := Max(0, Min(Mouse.X, Size.X - 1));
- Mouse.Y := Max(0, Min(Mouse.Y, Size.Y - 1));
- GetMousePtr := CharPtr(LineMove(DrawPtr, Mouse.Y + Delta.Y - DrawLine),
- Mouse.X + Delta.X);
- end;
-
- function TEditor.GetPalette: PPalette;
- const
- P: String[Length(CEditor)] = CEditor;
- begin
- GetPalette := @P;
- end;
-
- procedure TEditor.HandleEvent(var Event: TEvent);
- var
- ShiftState: Byte absolute $40:$17;
- CenterCursor: Boolean;
- SelectMode: Byte;
- I: Integer;
- NewPtr: Word;
- D, Mouse: TPoint;
-
- procedure CheckScrollBar(P: PScrollBar; var D: Integer);
- begin
- if (Event.InfoPtr = P) and (P^.Value <> D) then
- begin
- D := P^.Value;
- Update(ufView);
- end;
- end;
-
- begin
- TView.HandleEvent(Event);
- ConvertEvent(Event);
- CenterCursor := not CursorVisible;
- SelectMode := 0;
- if Selecting or (ShiftState and $03 <> 0) then SelectMode := smExtend;
- case Event.What of
- evMouseDown:
- begin
- if Event.Double then SelectMode := SelectMode or smDouble;
- repeat
- Lock;
- if Event.What = evMouseAuto then
- begin
- MakeLocal(Event.Where, Mouse);
- D := Delta;
- if Mouse.X < 0 then Dec(D.X);
- if Mouse.X >= Size.X then Inc(D.X);
- if Mouse.Y < 0 then Dec(D.Y);
- if Mouse.Y >= Size.Y then Inc(D.Y);
- ScrollTo(D.X, D.Y);
- end;
- SetCurPtr(GetMousePtr(Event.Where), SelectMode);
- SelectMode := SelectMode or smExtend;
- Unlock;
- until not MouseEvent(Event, evMouseMove + evMouseAuto);
- end;
- evKeyDown:
- case Event.CharCode of
- #9,#32..#255:
- begin
- Lock;
- if Overwrite and not HasSelection then
- if CurPtr <> LineEnd(CurPtr) then SelEnd := NextChar(CurPtr);
- InsertText(@Event.CharCode, 1, False);
- TrackCursor(CenterCursor);
- Unlock;
- end;
- else
- Exit;
- end;
- evCommand:
- case Event.Command of
- cmFind: Find;
- cmReplace: Replace;
- cmSearchAgain: DoSearchReplace;
- else
- begin
- Lock;
- case Event.Command of
- cmCut: ClipCut;
- cmCopy: ClipCopy;
- cmPaste: ClipPaste;
- cmUndo: Undo;
- cmClear: DeleteSelect;
- cmCharLeft: SetCurPtr(PrevChar(CurPtr), SelectMode);
- cmCharRight: SetCurPtr(NextChar(CurPtr), SelectMode);
- cmWordLeft: SetCurPtr(PrevWord(CurPtr), SelectMode);
- cmWordRight: SetCurPtr(NextWord(CurPtr), SelectMode);
- cmLineStart: SetCurPtr(LineStart(CurPtr), SelectMode);
- cmLineEnd: SetCurPtr(LineEnd(CurPtr), SelectMode);
- cmLineUp: SetCurPtr(LineMove(CurPtr, -1), SelectMode);
- cmLineDown: SetCurPtr(LineMove(CurPtr, 1), SelectMode);
- cmPageUp: SetCurPtr(LineMove(CurPtr, -(Size.Y - 1)), SelectMode);
- cmPageDown: SetCurPtr(LineMove(CurPtr, Size.Y - 1), SelectMode);
- cmTextStart: SetCurPtr(0, SelectMode);
- cmTextEnd: SetCurPtr(BufLen, SelectMode);
- cmNewLine: NewLine;
- cmBackSpace: DeleteRange(PrevChar(CurPtr), CurPtr, True);
- cmDelChar: DeleteRange(CurPtr, NextChar(CurPtr), True);
- cmDelWord: DeleteRange(CurPtr, NextWord(CurPtr), False);
- cmDelStart: DeleteRange(LineStart(CurPtr), CurPtr, False);
- cmDelEnd: DeleteRange(CurPtr, LineEnd(CurPtr), False);
- cmDelLine: DeleteRange(LineStart(CurPtr), NextLine(CurPtr), False);
- cmInsMode: ToggleInsMode;
- cmStartSelect: StartSelect;
- cmHideSelect: HideSelect;
- cmIndentMode: AutoIndent := not AutoIndent;
- else
- Unlock;
- Exit;
- end;
- TrackCursor(CenterCursor);
- Unlock;
- end;
- end;
- evBroadcast:
- case Event.Command of
- cmScrollBarChanged:
- begin
- CheckScrollBar(HScrollBar, Delta.X);
- CheckScrollBar(VScrollBar, Delta.Y);
- end;
- else
- Exit;
- end;
- end;
- ClearEvent(Event);
- end;
-
- function TEditor.HasSelection: Boolean;
- begin
- HasSelection := SelStart <> SelEnd;
- end;
-
- procedure TEditor.HideSelect;
- begin
- Selecting := False;
- SetSelect(CurPtr, CurPtr, False);
- end;
-
- procedure TEditor.InitBuffer;
- begin
- Buffer := MemAlloc(BufSize);
- end;
-
- function TEditor.InsertBuffer(var P: PEditBuffer; Offset, Length: Word;
- AllowUndo, SelectText: Boolean): Boolean;
- var
- SelLen, DelLen, SelLines, Lines: Word;
- NewSize: Longint;
- begin
- InsertBuffer := True;
- Selecting := False;
- SelLen := SelEnd - SelStart;
- if (SelLen = 0) and (Length = 0) then Exit;
- DelLen := 0;
- if AllowUndo then
- if CurPtr = SelStart then DelLen := SelLen else
- if SelLen > InsCount then DelLen := SelLen - InsCount;
- NewSize := Longint(BufLen + DelCount - SelLen + DelLen) + Length;
- if NewSize > BufLen + DelCount then
- if (NewSize > $FFF0) or not SetBufSize(NewSize) then
- begin
- EditorDialog(edOutOfMemory, nil);
- InsertBuffer := False;
- Exit;
- end;
- SelLines := CountLines(Buffer^[BufPtr(SelStart)], SelLen);
- if CurPtr = SelEnd then
- begin
- if AllowUndo then
- begin
- if DelLen > 0 then Move(Buffer^[SelStart],
- Buffer^[CurPtr + GapLen - DelCount - DelLen], DelLen);
- Dec(InsCount, SelLen - DelLen);
- end;
- CurPtr := SelStart;
- Dec(CurPos.Y, SelLines);
- end;
- if Delta.Y > CurPos.Y then
- begin
- Dec(Delta.Y, SelLines);
- if Delta.Y < CurPos.Y then Delta.Y := CurPos.Y;
- end;
- if Length > 0 then Move(P^[Offset], Buffer^[CurPtr], Length);
- Lines := CountLines(Buffer^[CurPtr], Length);
- Inc(CurPtr, Length);
- Inc(CurPos.Y, Lines);
- DrawLine := CurPos.Y;
- DrawPtr := LineStart(CurPtr);
- CurPos.X := CharPos(DrawPtr, CurPtr);
- if not SelectText then SelStart := CurPtr;
- SelEnd := CurPtr;
- Inc(BufLen, Length - SelLen);
- Dec(GapLen, Length - SelLen);
- if AllowUndo then
- begin
- Inc(DelCount, DelLen);
- Inc(InsCount, Length);
- end;
- Inc(Limit.Y, Lines - SelLines);
- Delta.Y := Max(0, Min(Delta.Y, Limit.Y - Size.Y));
- if not IsClipboard then Modified := True;
- SetBufSize(BufLen + DelCount);
- if (SelLines = 0) and (Lines = 0) then Update(ufLine) else Update(ufView);
- end;
-
- function TEditor.InsertFrom(Editor: PEditor): Boolean;
- begin
- InsertFrom := InsertBuffer(Editor^.Buffer,
- Editor^.BufPtr(Editor^.SelStart),
- Editor^.SelEnd - Editor^.SelStart, CanUndo, IsClipboard);
- end;
-
- function TEditor.InsertText(Text: Pointer; Length: Word;
- SelectText: Boolean): Boolean;
- begin
- InsertText := InsertBuffer(PEditBuffer(Text),
- 0, Length, CanUndo, SelectText);
- end;
-
- function TEditor.IsClipboard: Boolean;
- begin
- IsClipboard := Clipboard = @Self;
- end;
-
- function TEditor.LineEnd(P: Word): Word; assembler;
- asm
- PUSH DS
- LDS SI,Self
- LES BX,DS:[SI].TEditor.Buffer
- MOV DI,P
- MOV AL,0DH
- CLD
- MOV CX,DS:[SI].TEditor.CurPtr
- SUB CX,DI
- JBE @@1
- ADD DI,BX
- REPNE SCASB
- JE @@2
- MOV DI,DS:[SI].TEditor.CurPtr
- @@1: MOV CX,DS:[SI].TEditor.BufLen
- SUB CX,DI
- JCXZ @@4
- ADD BX,DS:[SI].TEditor.GapLen
- ADD DI,BX
- REPNE SCASB
- JNE @@3
- @@2: DEC DI
- @@3: SUB DI,BX
- @@4: MOV AX,DI
- POP DS
- end;
-
- function TEditor.LineMove(P: Word; Count: Integer): Word;
- var
- Pos: Integer;
- I: Word;
- begin
- I := P;
- P := LineStart(P);
- Pos := CharPos(P, I);
- while Count <> 0 do
- begin
- I := P;
- if Count < 0 then
- begin
- P := PrevLine(P);
- Inc(Count);
- end else
- begin
- P := NextLine(P);
- Dec(Count);
- end;
- end;
- if P <> I then P := CharPtr(P, Pos);
- LineMove := P;
- end;
-
- function TEditor.LineStart(P: Word): Word; assembler;
- asm
- PUSH DS
- LDS SI,Self
- LES BX,DS:[SI].TEditor.Buffer
- MOV DI,P
- MOV AL,0DH
- STD
- MOV CX,DI
- SUB CX,DS:[SI].TEditor.CurPtr
- JBE @@1
- ADD BX,DS:[SI].TEditor.GapLen
- ADD DI,BX
- DEC DI
- REPNE SCASB
- JE @@2
- SUB BX,DS:[SI].TEditor.GapLen
- MOV DI,DS:[SI].TEditor.CurPtr
- @@1: MOV CX,DI
- JCXZ @@4
- ADD DI,BX
- DEC DI
- REPNE SCASB
- JNE @@3
- @@2: INC DI
- INC DI
- SUB DI,BX
- CMP DI,DS:[SI].TEditor.CurPtr
- JE @@4
- CMP DI,DS:[SI].TEditor.BufLen
- JE @@4
- CMP ES:[BX+DI].Byte,0AH
- JNE @@4
- INC DI
- JMP @@4
- @@3: XOR DI,DI
- @@4: MOV AX,DI
- POP DS
- end;
-
- procedure TEditor.Lock;
- begin
- Inc(LockCount);
- end;
-
- procedure TEditor.NewLine;
- const
- CrLf: array[1..2] of Char = #13#10;
- var
- I, P: Word;
- begin
- P := LineStart(CurPtr);
- I := P;
- while (I < CurPtr) and ((Buffer^[I] = ' ') or (Buffer^[I] = #9)) do Inc(I);
- InsertText(@CrLf, 2, False);
- if AutoIndent then InsertText(@Buffer^[P], I - P, False);
- end;
-
- function TEditor.NextChar(P: Word): Word; assembler;
- asm
- PUSH DS
- LDS SI,Self
- MOV DI,P
- CMP DI,DS:[SI].TEditor.BufLen
- JE @@2
- INC DI
- CMP DI,DS:[SI].TEditor.BufLen
- JE @@2
- LES BX,DS:[SI].TEditor.Buffer
- CMP DI,DS:[SI].TEditor.CurPtr
- JB @@1
- ADD BX,DS:[SI].TEditor.GapLen
- @@1: CMP ES:[BX+DI-1].Word,0A0DH
- JNE @@2
- INC DI
- @@2: MOV AX,DI
- POP DS
- end;
-
- function TEditor.NextLine(P: Word): Word;
- begin
- NextLine := NextChar(LineEnd(P));
- end;
-
- function TEditor.NextWord(P: Word): Word;
- begin
- while (P < BufLen) and (BufChar(P) in WordChars) do
- P := NextChar(P);
- while (P < BufLen) and not (BufChar(P) in WordChars) do
- P := NextChar(P);
- NextWord := P;
- end;
-
- function TEditor.PrevChar(P: Word): Word; assembler;
- asm
- PUSH DS
- LDS SI,Self
- MOV DI,P
- OR DI,DI
- JE @@2
- DEC DI
- JE @@2
- LES BX,DS:[SI].TEditor.Buffer
- CMP DI,DS:[SI].TEditor.CurPtr
- JB @@1
- ADD BX,DS:[SI].TEditor.GapLen
- @@1: CMP ES:[BX+DI-1].Word,0A0DH
- JNE @@2
- DEC DI
- @@2: MOV AX,DI
- POP DS
- end;
-
- function TEditor.PrevLine(P: Word): Word;
- begin
- PrevLine := LineStart(PrevChar(P));
- end;
-
- function TEditor.PrevWord(P: Word): Word;
- begin
- while (P > 0) and not (BufChar(PrevChar(P)) in WordChars) do
- P := PrevChar(P);
- while (P > 0) and (BufChar(PrevChar(P)) in WordChars) do
- P := PrevChar(P);
- PrevWord := P;
- end;
-
- procedure TEditor.Replace;
- var
- ReplaceRec: TReplaceDialogRec;
- begin
- with ReplaceRec do
- begin
- Find := FindStr;
- Replace := ReplaceStr;
- Options := EditorFlags;
- if EditorDialog(edReplace, @ReplaceRec) <> cmCancel then
- begin
- FindStr := Find;
- ReplaceStr := Replace;
- EditorFlags := Options or efDoReplace;
- DoSearchReplace;
- end;
- end;
- end;
-
- procedure TEditor.ScrollTo(X, Y: Integer);
- begin
- X := Max(0, Min(X, Limit.X - Size.X));
- Y := Max(0, Min(Y, Limit.Y - Size.Y));
- if (X <> Delta.X) or (Y <> Delta.Y) then
- begin
- Delta.X := X;
- Delta.Y := Y;
- Update(ufView);
- end;
- end;
-
- function TEditor.Search(FindStr: String; Opts: Word): Boolean;
- var
- I, Pos: Word;
- begin
- Search := False;
- Pos := CurPtr;
- repeat
- if Opts and efCaseSensitive <> 0 then
- I := Scan(Buffer^[BufPtr(Pos)], BufLen - Pos, FindStr)
- else I := IScan(Buffer^[BufPtr(Pos)], BufLen - Pos, FindStr);
- if (I <> sfSearchFailed) then
- begin
- Inc(I, Pos);
- if (Opts and efWholeWordsOnly = 0) or
- not (((I <> 0) and (BufChar(I - 1) in WordChars)) or
- ((I + Length(FindStr) <> BufLen) and
- (BufChar(I + Length(FindStr)) in WordChars))) then
- begin
- Lock;
- SetSelect(I, I + Length(FindStr), False);
- TrackCursor(not CursorVisible);
- Unlock;
- Search := True;
- Exit;
- end else Pos := I + 1;
- end;
- until I = sfSearchFailed;
- end;
-
- procedure TEditor.SetBufLen(Length: Word);
- begin
- BufLen := Length;
- GapLen := BufSize - Length;
- SelStart := 0;
- SelEnd := 0;
- CurPtr := 0;
- Longint(CurPos) := 0;
- Longint(Delta) := 0;
- Limit.X := MaxLineLength;
- Limit.Y := CountLines(Buffer^[GapLen], BufLen) + 1;
- DrawLine := 0;
- DrawPtr := 0;
- DelCount := 0;
- InsCount := 0;
- Modified := False;
- Update(ufView);
- end;
-
- function TEditor.SetBufSize(NewSize: Word): Boolean;
- begin
- SetBufSize := NewSize <= BufSize;
- end;
-
- procedure TEditor.SetCmdState(Command: Word; Enable: Boolean);
- var
- S: TCommandSet;
- begin
- S := [Command];
- if Enable and (State and sfActive <> 0) then
- EnableCommands(S) else DisableCommands(S);
- end;
-
- procedure TEditor.SetCurPtr(P: Word; SelectMode: Byte);
- var
- Anchor: Word;
- begin
- if SelectMode and smExtend = 0 then Anchor := P else
- if CurPtr = SelStart then Anchor := SelEnd else Anchor := SelStart;
- if P < Anchor then
- begin
- if SelectMode and smDouble <> 0 then
- begin
- P := PrevLine(NextLine(P));
- Anchor := NextLine(PrevLine(Anchor));
- end;
- SetSelect(P, Anchor, True);
- end else
- begin
- if SelectMode and smDouble <> 0 then
- begin
- P := NextLine(P);
- Anchor := PrevLine(NextLine(Anchor));
- end;
- SetSelect(Anchor, P, False);
- end;
- end;
-
- procedure TEditor.SetSelect(NewStart, NewEnd: Word; CurStart: Boolean);
- var
- Flags: Byte;
- P, L: Word;
- begin
- if CurStart then P := NewStart else P := NewEnd;
- Flags := ufUpdate;
- if (NewStart <> SelStart) or (NewEnd <> SelEnd) then
- if (NewStart <> NewEnd) or (SelStart <> SelEnd) then
- Flags := ufView;
- if P <> CurPtr then
- begin
- if P > CurPtr then
- begin
- L := P - CurPtr;
- Move(Buffer^[CurPtr + GapLen], Buffer^[CurPtr], L);
- Inc(CurPos.Y, CountLines(Buffer^[CurPtr], L));
- CurPtr := P;
- end else
- begin
- L := CurPtr - P;
- CurPtr := P;
- Dec(CurPos.Y, CountLines(Buffer^[CurPtr], L));
- Move(Buffer^[CurPtr], Buffer^[CurPtr + GapLen], L);
- end;
- DrawLine := CurPos.Y;
- DrawPtr := LineStart(P);
- CurPos.X := CharPos(DrawPtr, P);
- DelCount := 0;
- InsCount := 0;
- SetBufSize(BufLen);
- end;
- SelStart := NewStart;
- SelEnd := NewEnd;
- Update(Flags);
- end;
-
- procedure TEditor.SetState(AState: Word; Enable: Boolean);
- begin
- TView.SetState(AState, Enable);
- case AState of
- sfActive:
- begin
- if HScrollBar <> nil then HScrollBar^.SetState(sfVisible, Enable);
- if VScrollBar <> nil then VScrollBar^.SetState(sfVisible, Enable);
- if Indicator <> nil then Indicator^.SetState(sfVisible, Enable);
- UpdateCommands;
- end;
- sfExposed:
- if Enable then Unlock;
- end;
- end;
-
- procedure TEditor.StartSelect;
- begin
- HideSelect;
- Selecting := True;
- end;
-
- procedure TEditor.Store(var S: TStream);
- begin
- TView.Store(S);
- PutPeerViewPtr(S, HScrollBar);
- PutPeerViewPtr(S, VScrollBar);
- PutPeerViewPtr(S, Indicator);
- S.Write(BufSize, SizeOf(Word));
- S.Write(CanUndo, SizeOf(Boolean));
- end;
-
- procedure TEditor.ToggleInsMode;
- begin
- Overwrite := not Overwrite;
- SetState(sfCursorIns, not GetState(sfCursorIns));
- end;
-
- procedure TEditor.TrackCursor(Center: Boolean);
- begin
- if Center then
- ScrollTo(CurPos.X - Size.X + 1, CurPos.Y - Size.Y div 2) else
- ScrollTo(Max(CurPos.X - Size.X + 1, Min(Delta.X, CurPos.X)),
- Max(CurPos.Y - Size.Y + 1, Min(Delta.Y, CurPos.Y)));
- end;
-
- procedure TEditor.Undo;
- var
- Length: Word;
- begin
- if (DelCount <> 0) or (InsCount <> 0) then
- begin
- SelStart := CurPtr - InsCount;
- SelEnd := CurPtr;
- Length := DelCount;
- DelCount := 0;
- InsCount := 0;
- InsertBuffer(Buffer, CurPtr + GapLen - Length, Length, False, True);
- end;
- end;
-
- procedure TEditor.Unlock;
- begin
- if LockCount > 0 then
- begin
- Dec(LockCount);
- if LockCount = 0 then DoUpdate;
- end;
- end;
-
- procedure TEditor.Update(AFlags: Byte);
- begin
- UpdateFlags := UpdateFlags or AFlags;
- if LockCount = 0 then DoUpdate;
- end;
-
- procedure TEditor.UpdateCommands;
- begin
- SetCmdState(cmUndo, (DelCount <> 0) or (InsCount <> 0));
- if not IsClipboard then
- begin
- SetCmdState(cmCut, HasSelection);
- SetCmdState(cmCopy, HasSelection);
- SetCmdState(cmPaste, (Clipboard <> nil) and (Clipboard^.HasSelection));
- end;
- SetCmdState(cmClear, HasSelection);
- SetCmdState(cmFind, True);
- SetCmdState(cmReplace, True);
- SetCmdState(cmSearchAgain, True);
- end;
-
- function TEditor.Valid(Command: Word): Boolean;
- begin
- Valid := IsValid;
- end;
-
- { TMemo }
-
- constructor TMemo.Load(var S: TStream);
- var
- Length: Word;
- begin
- TEditor.Load(S);
- S.Read(Length, SizeOf(Word));
- if IsValid then
- begin
- S.Read(Buffer^[BufSize - Length], Length);
- SetBufLen(Length);
- end
- else S.Seek(S.GetPos + Length);
- end;
-
- function TMemo.DataSize: Word;
- begin
- DataSize := BufSize + SizeOf(Word);
- end;
-
- procedure TMemo.GetData(var Rec);
- var
- Data: TMemoData absolute Rec;
- begin
- Data.Length := BufLen;
- Move(Buffer^, Data.Buffer, CurPtr);
- Move(Buffer^[CurPtr + GapLen], Data.Buffer[CurPtr], BufLen - CurPtr);
- FillChar(Data.Buffer[BufLen], BufSize - BufLen, 0);
- end;
-
- function TMemo.GetPalette: PPalette;
- const
- P: String[Length(CMemo)] = CMemo;
- begin
- GetPalette := @P;
- end;
-
- procedure TMemo.HandleEvent(var Event: TEvent);
- begin
- if (Event.What <> evKeyDown) or (Event.KeyCode <> kbTab) then
- TEditor.HandleEvent(Event);
- end;
-
- procedure TMemo.SetData(var Rec);
- var
- Data: TMemoData absolute Rec;
- begin
- Move(Data.Buffer, Buffer^[BufSize - Data.Length], Data.Length);
- SetBufLen(Data.Length);
- end;
-
- procedure TMemo.Store(var S: TStream);
- begin
- TEditor.Store(S);
- S.Write(BufLen, SizeOf(Word));
- S.Write(Buffer^, CurPtr);
- S.Write(Buffer^[CurPtr + GapLen], BufLen - CurPtr);
- end;
-
- { TFileEditor }
-
- constructor TFileEditor.Init(var Bounds: TRect;
- AHScrollBar, AVScrollBar: PScrollBar;
- AIndicator: PIndicator; AFileName: FNameStr);
- begin
- TEditor.Init(Bounds, AHScrollBar, AVScrollBar, AIndicator, 0);
- if AFileName <> '' then
- begin
- FileName := FExpand(AFileName);
- if IsValid then IsValid := LoadFile;
- end;
- end;
-
- constructor TFileEditor.Load(var S: TStream);
- var
- SStart, SEnd, Curs: Word;
- begin
- TEditor.Load(S);
- S.Read(FileName[0], SizeOf(Char));
- S.Read(Filename[1], Length(FileName));
- if IsValid then IsValid := LoadFile;
- S.Read(SStart, SizeOf(Word));
- S.Read(SEnd, SizeOf(Word));
- S.Read(Curs, SizeOf(Word));
- if IsValid and (SEnd <= BufLen) then
- begin
- SetSelect(SStart, SEnd, Curs = SStart);
- TrackCursor(True);
- end;
- end;
-
- procedure TFileEditor.DoneBuffer;
- begin
- if Buffer <> nil then DisposeBuffer(Buffer);
- end;
-
- procedure TFileEditor.HandleEvent(var Event: TEvent);
- begin
- TEditor.HandleEvent(Event);
- case Event.What of
- evCommand:
- case Event.Command of
- cmSave: Save;
- cmSaveAs: SaveAs;
- else
- Exit;
- end;
- else
- Exit;
- end;
- ClearEvent(Event);
- end;
-
- procedure TFileEditor.InitBuffer;
- begin
- NewBuffer(Pointer(Buffer));
- end;
-
- function TFileEditor.LoadFile: Boolean;
- var
- Length: Word;
- FSize: Longint;
- F: File;
- begin
- LoadFile := False;
- Length := 0;
- Assign(F, FileName);
- Reset(F, 1);
- if IOResult <> 0 then LoadFile := True else
- begin
- FSize := FileSize(F);
- if (FSize > $FFF0) or not SetBufSize(Word(FSize)) then
- EditorDialog(edOutOfMemory, nil) else
- begin
- BlockRead(F, Buffer^[BufSize - Word(FSize)], FSize);
- if IOResult <> 0 then EditorDialog(edReadError, @FileName) else
- begin
- LoadFile := True;
- Length := FSize;
- end;
- end;
- Close(F);
- end;
- SetBufLen(Length);
- end;
-
- function TFileEditor.Save: Boolean;
- begin
- if FileName = '' then Save := SaveAs else Save := SaveFile;
- end;
-
- function TFileEditor.SaveAs: Boolean;
- begin
- SaveAs := False;
- if EditorDialog(edSaveAs, @FileName) <> cmCancel then
- begin
- FileName := FExpand(FileName);
- Message(Owner, evBroadcast, cmUpdateTitle, nil);
- SaveAs := SaveFile;
- if IsClipboard then FileName := '';
- end;
- end;
-
- function TFileEditor.SaveFile: Boolean;
- var
- F: File;
- BackupName: FNameStr;
- D: DirStr;
- N: NameStr;
- E: ExtStr;
- begin
- SaveFile := False;
- if EditorFlags and efBackupFiles <> 0 then
- begin
- FSplit(FileName, D, N, E);
- BackupName := D + N + '.BAK';
- Assign(F, BackupName);
- Erase(F);
- Assign(F, FileName);
- Rename(F, BackupName);
- InOutRes := 0;
- end;
- Assign(F, FileName);
- Rewrite(F, 1);
- if IOResult <> 0 then EditorDialog(edCreateError, @FileName) else
- begin
- BlockWrite(F, Buffer^, CurPtr);
- BlockWrite(F, Buffer^[CurPtr + GapLen], BufLen - CurPtr);
- if IOResult <> 0 then EditorDialog(edWriteError, @FileName) else
- begin
- Modified := False;
- Update(ufUpdate);
- SaveFile := True;
- end;
- Close(F);
- end;
- end;
-
- function TFileEditor.SetBufSize(NewSize: Word): Boolean;
- var
- N: Word;
- begin
- SetBufSize := False;
- if NewSize > $F000 then NewSize := $FFF0 else
- NewSize := (NewSize + $0FFF) and $F000;
- if NewSize <> BufSize then
- begin
- if NewSize > BufSize then
- if not SetBufferSize(Buffer, NewSize) then Exit;
- N := BufLen - CurPtr + DelCount;
- Move(Buffer^[BufSize - N], Buffer^[NewSize - N], N);
- if NewSize < BufSize then SetBufferSize(Buffer, NewSize);
- BufSize := NewSize;
- GapLen := BufSize - BufLen;
- end;
- SetBufSize := True;
- end;
-
- procedure TFileEditor.Store(var S: TStream);
- begin
- TEditor.Store(S);
- S.Write(FileName, Length(FileName) + 1);
- S.Write(SelStart, SizeOf(Word) * 3);
- end;
-
- procedure TFileEditor.UpdateCommands;
- begin
- TEditor.UpdateCommands;
- SetCmdState(cmSave, True);
- SetCmdState(cmSaveAs, True);
- end;
-
- function TFileEditor.Valid(Command: Word): Boolean;
- var
- D: Integer;
- begin
- if Command = cmValid then Valid := IsValid else
- begin
- Valid := True;
- if Modified then
- begin
- if FileName = '' then D := edSaveUntitled else D := edSaveModify;
- case EditorDialog(D, @FileName) of
- cmYes: Valid := Save;
- cmNo: Modified := False;
- cmCancel: Valid := False;
- end;
- end;
- end;
- end;
-
- { TEditWindow }
-
- constructor TEditWindow.Init(var Bounds: TRect;
- FileName: FNameStr; ANumber: Integer);
- var
- HScrollBar, VScrollBar: PScrollBar;
- Indicator: PIndicator;
- R: TRect;
- begin
- TWindow.Init(Bounds, '', ANumber);
- Options := Options or ofTileable;
- R.Assign(18, Size.Y - 1, Size.X - 2, Size.Y);
- HScrollBar := New(PScrollBar, Init(R));
- HScrollBar^.Hide;
- Insert(HScrollBar);
- R.Assign(Size.X - 1, 1, Size.X, Size.Y - 1);
- VScrollBar := New(PScrollBar, Init(R));
- VScrollBar^.Hide;
- Insert(VScrollBar);
- R.Assign(2, Size.Y - 1, 16, Size.Y);
- Indicator := New(PIndicator, Init(R));
- Indicator^.Hide;
- Insert(Indicator);
- GetExtent(R);
- R.Grow(-1, -1);
- Editor := New(PFileEditor, Init(
- R, HScrollBar, VScrollBar, Indicator, FileName));
- Insert(Editor);
- end;
-
- constructor TEditWindow.Load(var S: TStream);
- begin
- TWindow.Load(S);
- GetSubViewPtr(S, Editor);
- end;
-
- procedure TEditWindow.Close;
- begin
- if Editor^.IsClipboard then Hide else TWindow.Close;
- end;
-
- function TEditWindow.GetTitle(MaxSize: Integer): TTitleStr;
- begin
- if Editor^.IsClipboard then GetTitle := 'Clipboard' else
- if Editor^.FileName = '' then GetTitle := 'Untitled' else
- GetTitle := Editor^.FileName;
- end;
-
- procedure TEditWindow.HandleEvent(var Event: TEvent);
- begin
- TWindow.HandleEvent(Event);
- if (Event.What = evBroadcast) and (Event.Command = cmUpdateTitle) then
- begin
- Frame^.DrawView;
- ClearEvent(Event);
- end;
- end;
-
- procedure TEditWindow.Store(var S: TStream);
- begin
- TWindow.Store(S);
- PutSubViewPtr(S, Editor);
- end;
-
- procedure RegisterEditors;
- begin
- RegisterType(REditor);
- RegisterType(RMemo);
- RegisterType(RFileEditor);
- RegisterType(RIndicator);
- RegisterType(REditWindow);
- end;
-
- end.
-