home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / l / l044 / 2.ddi / TVISION.ZIP / EDITORS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-10-23  |  44.6 KB  |  1,933 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Turbo Pascal Version 6.0                        }
  5. {       Turbo Vision Unit                               }
  6. {                                                       }
  7. {       Copyright (c) 1990 Borland International        }
  8. {                                                       }
  9. {*******************************************************}
  10.  
  11. unit Editors;
  12.  
  13. {$F+,I-,O+,S-,V-,X+,D-}
  14.  
  15. interface
  16.  
  17. uses Drivers, Objects, Views;
  18.  
  19. const
  20.   cmSave        = 80;
  21.   cmSaveAs      = 81;
  22.   cmFind        = 82;
  23.   cmReplace     = 83;
  24.   cmSearchAgain = 84;
  25.  
  26. const
  27.   cmCharLeft    = 500;
  28.   cmCharRight   = 501;
  29.   cmWordLeft    = 502;
  30.   cmWordRight   = 503;
  31.   cmLineStart   = 504;
  32.   cmLineEnd     = 505;
  33.   cmLineUp      = 506;
  34.   cmLineDown    = 507;
  35.   cmPageUp      = 508;
  36.   cmPageDown    = 509;
  37.   cmTextStart   = 510;
  38.   cmTextEnd     = 511;
  39.   cmNewLine     = 512;
  40.   cmBackSpace   = 513;
  41.   cmDelChar     = 514;
  42.   cmDelWord     = 515;
  43.   cmDelStart    = 516;
  44.   cmDelEnd      = 517;
  45.   cmDelLine     = 518;
  46.   cmInsMode     = 519;
  47.   cmStartSelect = 520;
  48.   cmHideSelect  = 521;
  49.   cmIndentMode  = 522;
  50.   cmUpdateTitle = 523;
  51.  
  52. const
  53.   edOutOfMemory   = 0;
  54.   edReadError     = 1;
  55.   edWriteError    = 2;
  56.   edCreateError   = 3;
  57.   edSaveModify    = 4;
  58.   edSaveUntitled  = 5;
  59.   edSaveAs        = 6;
  60.   edFind          = 7;
  61.   edSearchFailed  = 8;
  62.   edReplace       = 9;
  63.   edReplacePrompt = 10;
  64.  
  65. const
  66.   efCaseSensitive   = $0001;
  67.   efWholeWordsOnly  = $0002;
  68.   efPromptOnReplace = $0004;
  69.   efReplaceAll      = $0008;
  70.   efDoReplace       = $0010;
  71.   efBackupFiles     = $0100;
  72.  
  73. const
  74.   CIndicator = #2#3;
  75.   CEditor    = #6#7;
  76.   CMemo      = #26#27;
  77.  
  78. const
  79.   MaxLineLength = 256;
  80.  
  81. type
  82.   TEditorDialog = function(Dialog: Integer; Info: Pointer): Word;
  83.  
  84. type
  85.   PIndicator = ^TIndicator;
  86.   TIndicator = object(TView)
  87.     Location: TPoint;
  88.     Modified: Boolean;
  89.     constructor Init(var Bounds: TRect);
  90.     procedure Draw; virtual;
  91.     function GetPalette: PPalette; virtual;
  92.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  93.     procedure SetValue(ALocation: TPoint; AModified: Boolean);
  94.   end;
  95.  
  96. type
  97.   PEditBuffer = ^TEditBuffer;
  98.   TEditBuffer = array[0..65519] of Char;
  99.  
  100. type
  101.   PEditor = ^TEditor;
  102.   TEditor = object(TView)
  103.     HScrollBar: PScrollBar;
  104.     VScrollBar: PScrollBar;
  105.     Indicator: PIndicator;
  106.     Buffer: PEditBuffer;
  107.     BufSize: Word;
  108.     BufLen: Word;
  109.     GapLen: Word;
  110.     SelStart: Word;
  111.     SelEnd: Word;
  112.     CurPtr: Word;
  113.     CurPos: TPoint;
  114.     Delta: TPoint;
  115.     Limit: TPoint;
  116.     DrawLine: Integer;
  117.     DrawPtr: Word;
  118.     DelCount: Word;
  119.     InsCount: Word;
  120.     IsValid: Boolean;
  121.     CanUndo: Boolean;
  122.     Modified: Boolean;
  123.     Selecting: Boolean;
  124.     Overwrite: Boolean;
  125.     AutoIndent: Boolean;
  126.     constructor Init(var Bounds: TRect;
  127.       AHScrollBar, AVScrollBar: PScrollBar;
  128.       AIndicator: PIndicator; ABufSize: Word);
  129.     constructor Load(var S: TStream);
  130.     destructor Done; virtual;
  131.     function BufChar(P: Word): Char;
  132.     function BufPtr(P: Word): Word;
  133.     procedure ChangeBounds(var Bounds: TRect); virtual;
  134.     procedure ConvertEvent(var Event: TEvent); virtual;
  135.     function CursorVisible: Boolean;
  136.     procedure DeleteSelect;
  137.     procedure DoneBuffer; virtual;
  138.     procedure Draw; virtual;
  139.     function GetPalette: PPalette; virtual;
  140.     procedure HandleEvent(var Event: TEvent); virtual;
  141.     procedure InitBuffer; virtual;
  142.     function InsertBuffer(var P: PEditBuffer; Offset, Length: Word;
  143.       AllowUndo, SelectText: Boolean): Boolean;
  144.     function InsertFrom(Editor: PEditor): Boolean; virtual;
  145.     function InsertText(Text: Pointer; Length: Word;
  146.       SelectText: Boolean): Boolean;
  147.     procedure ScrollTo(X, Y: Integer);
  148.     function Search(FindStr: String; Opts: Word): Boolean;
  149.     function SetBufSize(NewSize: Word): Boolean; virtual;
  150.     procedure SetCmdState(Command: Word; Enable: Boolean);
  151.     procedure SetSelect(NewStart, NewEnd: Word; CurStart: Boolean);
  152.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  153.     procedure Store(var S: TStream);
  154.     procedure TrackCursor(Center: Boolean);
  155.     procedure Undo;
  156.     procedure UpdateCommands; virtual;
  157.     function Valid(Command: Word): Boolean; virtual;
  158.   private
  159.     LockCount: Byte;
  160.     UpdateFlags: Byte;
  161.     KeyState: Integer;
  162.     function CharPos(P, Target: Word): Integer;
  163.     function CharPtr(P: Word; Target: Integer): Word;
  164.     function ClipCopy: Boolean;
  165.     procedure ClipCut;
  166.     procedure ClipPaste;
  167.     procedure DeleteRange(StartPtr, EndPtr: Word; DelSelect: Boolean);
  168.     procedure DoUpdate;
  169.     procedure DoSearchReplace;
  170.     procedure DrawLines(Y, Count: Integer; LinePtr: Word);
  171.     procedure FormatLine(var DrawBuf; LinePtr: Word;
  172.       Width: Integer; Colors: Word);
  173.     procedure Find;
  174.     function GetMousePtr(Mouse: TPoint): Word;
  175.     function HasSelection: Boolean;
  176.     procedure HideSelect;
  177.     function IsClipboard: Boolean;
  178.     function LineEnd(P: Word): Word;
  179.     function LineMove(P: Word; Count: Integer): Word;
  180.     function LineStart(P: Word): Word;
  181.     procedure Lock;
  182.     procedure NewLine;
  183.     function NextChar(P: Word): Word;
  184.     function NextLine(P: Word): Word;
  185.     function NextWord(P: Word): Word;
  186.     function PrevChar(P: Word): Word;
  187.     function PrevLine(P: Word): Word;
  188.     function PrevWord(P: Word): Word;
  189.     procedure Replace;
  190.     procedure SetBufLen(Length: Word);
  191.     procedure SetCurPtr(P: Word; SelectMode: Byte);
  192.     procedure StartSelect;
  193.     procedure ToggleInsMode;
  194.     procedure Unlock;
  195.     procedure Update(AFlags: Byte);
  196.   end;
  197.  
  198. type
  199.   TMemoData = record
  200.     Length: Word;
  201.     Buffer: TEditBuffer;
  202.   end;
  203.  
  204. type
  205.   PMemo = ^TMemo;
  206.   TMemo = object(TEditor)
  207.     constructor Load(var S: TStream);
  208.     function DataSize: Word; virtual;
  209.     procedure GetData(var Rec); virtual;
  210.     function GetPalette: PPalette; virtual;
  211.     procedure HandleEvent(var Event: TEvent); virtual;
  212.     procedure SetData(var Rec); virtual;
  213.     procedure Store(var S: TStream);
  214.   end;
  215.  
  216. type
  217.   PFileEditor = ^TFileEditor;
  218.   TFileEditor = object(TEditor)
  219.     FileName: FNameStr;
  220.     constructor Init(var Bounds: TRect;
  221.       AHScrollBar, AVScrollBar: PScrollBar;
  222.       AIndicator: PIndicator; AFileName: FNameStr);
  223.     constructor Load(var S: TStream);
  224.     procedure DoneBuffer; virtual;
  225.     procedure HandleEvent(var Event: TEvent); virtual;
  226.     procedure InitBuffer; virtual;
  227.     function LoadFile: Boolean;
  228.     function Save: Boolean;
  229.     function SaveAs: Boolean;
  230.     function SaveFile: Boolean;
  231.     function SetBufSize(NewSize: Word): Boolean; virtual;
  232.     procedure Store(var S: TStream);
  233.     procedure UpdateCommands; virtual;
  234.     function Valid(Command: Word): Boolean; virtual;
  235.   end;
  236.  
  237. type
  238.   PEditWindow = ^TEditWindow;
  239.   TEditWindow = object(TWindow)
  240.     Editor: PFileEditor;
  241.     constructor Init(var Bounds: TRect;
  242.       FileName: FNameStr; ANumber: Integer);
  243.     constructor Load(var S: TStream);
  244.     procedure Close; virtual;
  245.     function GetTitle(MaxSize: Integer): TTitleStr; virtual;
  246.     procedure HandleEvent(var Event: TEvent); virtual;
  247.     procedure Store(var S: TStream);
  248.   end;
  249.  
  250. function DefEditorDialog(Dialog: Integer; Info: Pointer): Word;
  251.  
  252. const
  253.   WordChars: set of Char = ['0'..'9', 'A'..'Z', '_', 'a'..'z'];
  254.   EditorDialog: TEditorDialog = DefEditorDialog;
  255.   EditorFlags: Word = efBackupFiles + efPromptOnReplace;
  256.   FindStr: String[80] = '';
  257.   ReplaceStr: String[80] = '';
  258.   Clipboard: PEditor = nil;
  259.  
  260. type
  261.   TFindDialogRec = record
  262.     Find: String[80];
  263.     Options: Word;
  264.   end;
  265.  
  266. type
  267.   TReplaceDialogRec = record
  268.     Find: String[80];
  269.     Replace: String[80];
  270.     Options: Word;
  271.   end;
  272.  
  273. const
  274.   REditor: TStreamRec = (
  275.     ObjType: 70;
  276.     VmtLink: Ofs(TypeOf(TEditor)^);
  277.     Load: @TEditor.Load;
  278.     Store: @TEditor.Store
  279.   );
  280.   RMemo: TStreamRec = (
  281.     ObjType: 71;
  282.     VmtLink: Ofs(TypeOf(TMemo)^);
  283.     Load: @TMemo.Load;
  284.     Store: @TMemo.Store
  285.   );
  286.   RFileEditor: TStreamRec = (
  287.     ObjType: 72;
  288.     VmtLink: Ofs(TypeOf(TFileEditor)^);
  289.     Load: @TFileEditor.Load;
  290.     Store: @TFileEditor.Store
  291.   );
  292.   RIndicator: TStreamRec = (
  293.     ObjType: 73;
  294.     VmtLink: Ofs(TypeOf(TIndicator)^);
  295.     Load: @TIndicator.Load;
  296.     Store: @TIndicator.Store
  297.   );
  298.   REditWindow: TStreamRec = (
  299.     ObjType: 74;
  300.     VmtLink: Ofs(TypeOf(TEditWindow)^);
  301.     Load: @TEditWindow.Load;
  302.     Store: @TEditWindow.Store
  303.   );
  304.  
  305. procedure RegisterEditors;
  306.  
  307. implementation
  308.  
  309. uses Memory, Buffers, Dos;
  310.  
  311. const
  312.   ufUpdate = $01;
  313.   ufLine   = $02;
  314.   ufView   = $04;
  315.  
  316. const
  317.   smExtend = $01;
  318.   smDouble = $02;
  319.  
  320. const
  321.   sfSearchFailed = $FFFF;
  322.  
  323. const
  324.   FirstKeys: array[0..37 * 2] of Word = (37,
  325.     Ord(^A), cmWordLeft, Ord(^C), cmPageDown,
  326.     Ord(^D), cmCharRight, Ord(^E), cmLineUp,
  327.     Ord(^F), cmWordRight, Ord(^G), cmDelChar,
  328.     Ord(^H), cmBackSpace, Ord(^K), $FF02,
  329.     Ord(^L), cmSearchAgain, Ord(^M), cmNewLine,
  330.     Ord(^O), cmIndentMode, Ord(^Q), $FF01,
  331.     Ord(^R), cmPageUp, Ord(^S), cmCharLeft,
  332.     Ord(^T), cmDelWord, Ord(^U), cmUndo,
  333.     Ord(^V), cmInsMode, Ord(^X), cmLineDown,
  334.     Ord(^Y), cmDelLine, kbLeft, cmCharLeft,
  335.     kbRight, cmCharRight, kbCtrlLeft, cmWordLeft,
  336.     kbCtrlRight, cmWordRight, kbHome, cmLineStart,
  337.     kbEnd, cmLineEnd, kbUp, cmLineUp,
  338.     kbDown, cmLineDown, kbPgUp, cmPageUp,
  339.     kbPgDn, cmPageDown, kbCtrlPgUp, cmTextStart,
  340.     kbCtrlPgDn, cmTextEnd, kbIns, cmInsMode,
  341.     kbDel, cmDelChar, kbShiftIns, cmPaste,
  342.     kbShiftDel, cmCut, kbCtrlIns, cmCopy,
  343.     kbCtrlDel, cmClear);
  344.   QuickKeys: array[0..8 * 2] of Word = (8,
  345.     Ord('A'), cmReplace, Ord('C'), cmTextEnd,
  346.     Ord('D'), cmLineEnd, Ord('F'), cmFind,
  347.     Ord('H'), cmDelStart, Ord('R'), cmTextStart,
  348.     Ord('S'), cmLineStart, Ord('Y'), cmDelEnd);
  349.   BlockKeys: array[0..5 * 2] of Word = (5,
  350.     Ord('B'), cmStartSelect, Ord('C'), cmPaste,
  351.     Ord('H'), cmHideSelect, Ord('K'), cmCopy,
  352.     Ord('Y'), cmCut);
  353.   KeyMap: array[0..2] of Pointer = (@FirstKeys, @QuickKeys, @BlockKeys);
  354.  
  355. function DefEditorDialog(Dialog: Integer; Info: Pointer): Word;
  356. begin
  357.   DefEditorDialog := cmCancel;
  358. end;
  359.  
  360. function Min(X, Y: Integer): Integer; assembler;
  361. asm
  362.     MOV    AX,X
  363.     CMP    AX,Y
  364.     JLE    @@1
  365.     MOV    AX,Y
  366. @@1:
  367. end;
  368.  
  369. function Max(X, Y: Integer): Integer; assembler;
  370. asm
  371.     MOV    AX,X
  372.     CMP    AX,Y
  373.     JGE    @@1
  374.     MOV    AX,Y
  375. @@1:
  376. end;
  377.  
  378. function MinWord(X, Y: Word): Word; assembler;
  379. asm
  380.     MOV    AX,X
  381.     CMP    AX,Y
  382.     JBE    @@1
  383.     MOV    AX,Y
  384. @@1:
  385. end;
  386.  
  387. function MaxWord(X, Y: Word): Word; assembler;
  388. asm
  389.     MOV    AX,X
  390.     CMP    AX,Y
  391.     JAE    @@1
  392.     MOV    AX,Y
  393. @@1:
  394. end;
  395.  
  396. function CountLines(var Buf; Count: Word): Integer; assembler;
  397. asm
  398.     LES    DI,Buf
  399.     MOV    CX,Count
  400.     XOR    DX,DX
  401.     MOV    AL,0DH
  402.     CLD
  403. @@1:    JCXZ    @@2
  404.     REPNE    SCASB
  405.     JNE    @@2
  406.     INC    DX
  407.     JMP    @@1
  408. @@2:    MOV    AX,DX
  409. end;
  410.  
  411. function ScanKeyMap(KeyMap: Pointer; KeyCode: Word): Word; assembler;
  412. asm
  413.     PUSH    DS
  414.     LDS    SI,KeyMap
  415.     MOV    DX,KeyCode
  416.     CLD
  417.     LODSW
  418.     MOV    CX,AX
  419. @@1:    LODSW
  420.     MOV    BX,AX
  421.     LODSW
  422.     OR    BL,BL
  423.     JE    @@2
  424.     CMP    BL,DL
  425.     JNE    @@3
  426.     OR    BH,BH
  427.     JE    @@4
  428. @@2:    CMP    BH,DH
  429.     JE    @@4
  430. @@3:    LOOP    @@1
  431.     XOR    AX,AX
  432. @@4:    POP    DS
  433. end;
  434.  
  435. function Scan(var Block; Size: Word; Str: String): Word; assembler;
  436. asm
  437.     PUSH    DS
  438.     LES    DI,Block
  439.     LDS    SI,Str
  440.     MOV    CX,Size
  441.     JCXZ    @@3
  442.     CLD
  443.     LODSB
  444.     CMP    AL,1
  445.     JB    @@5
  446.     JA    @@1
  447.     LODSB
  448.     REPNE    SCASB
  449.     JNE    @@3
  450.     JMP    @@5
  451. @@1:    XOR    AH,AH
  452.     MOV    BX,AX
  453.         DEC     BX
  454.     MOV    DX,CX
  455.     SUB    DX,AX
  456.     JB    @@3
  457.     LODSB
  458.     INC    DX
  459.     INC    DX
  460. @@2:    DEC    DX
  461.     MOV    CX,DX
  462.     REPNE    SCASB
  463.     JNE    @@3
  464.     MOV    DX,CX
  465.     MOV    CX,BX
  466.     REP    CMPSB
  467.     JE    @@4
  468.     SUB    CX,BX
  469.     ADD    SI,CX
  470.     ADD    DI,CX
  471.     INC    DI
  472.     OR    DX,DX
  473.     JNE    @@2
  474. @@3:    XOR    AX,AX
  475.     JMP    @@6
  476. @@4:    SUB    DI,BX
  477. @@5:    MOV    AX,DI
  478.     SUB    AX,WORD PTR Block
  479. @@6:    DEC    AX
  480.     POP    DS
  481. end;
  482.  
  483. function IScan(var Block; Size: Word; Str: String): Word; assembler;
  484. var
  485.   S: String;
  486. asm
  487.     PUSH    DS
  488.     MOV    AX,SS
  489.     MOV    ES,AX
  490.     LEA    DI,S
  491.     LDS    SI,Str
  492.     XOR    AH,AH
  493.     LODSB
  494.     STOSB
  495.     MOV    CX,AX
  496.     MOV    BX,AX
  497.     JCXZ    @@9
  498. @@1:    LODSB
  499.     CMP    AL,'a'
  500.     JB    @@2
  501.     CMP    AL,'z'
  502.     JA    @@2
  503.     SUB    AL,20H
  504. @@2:    STOSB
  505.     LOOP    @@1
  506.     SUB    DI,BX
  507.     LDS    SI,Block
  508.     MOV    CX,Size
  509.     JCXZ    @@8
  510.     CLD
  511.     SUB    CX,BX
  512.     JB    @@8
  513.     INC    CX
  514. @@4:    MOV    AH,ES:[DI]
  515.     AND    AH,$DF
  516. @@5:    LODSB
  517.     AND    AL,$DF
  518.     CMP    AL,AH
  519.     LOOPNE    @@5
  520.     JNE    @@8
  521.     DEC    SI
  522.     MOV    DX,CX
  523.         MOV    CX,BX
  524. @@6:    REPE    CMPSB
  525.     JE    @@10
  526.     MOV    AL,DS:[SI-1]
  527.     CMP    AL,'a'
  528.     JB    @@7
  529.     CMP    AL,'z'
  530.     JA    @@7
  531.     SUB    AL,20H
  532. @@7:    CMP    AL,ES:[DI-1]
  533.     JE    @@6
  534.     SUB    CX,BX
  535.     ADD    SI,CX
  536.     ADD    DI,CX
  537.     INC    SI
  538.     MOV    CX,DX
  539.     JNE    @@4
  540. @@8:    XOR    AX,AX
  541.     JMP    @@11
  542. @@9:    MOV    AX, 1
  543.     JMP    @@11
  544. @@10:    SUB    SI,BX
  545.     MOV    AX,SI
  546.     SUB    AX,WORD PTR Block
  547.     INC    AX
  548. @@11:    DEC    AX
  549.     POP    DS
  550. end;
  551.  
  552. { TIndicator }
  553.  
  554. constructor TIndicator.Init(var Bounds: TRect);
  555. var
  556.   R: TRect;
  557. begin
  558.   TView.Init(Bounds);
  559.   GrowMode := gfGrowLoY + gfGrowHiY;
  560. end;
  561.  
  562. procedure TIndicator.Draw;
  563. var
  564.   Color: Byte;
  565.   Frame: Char;
  566.   L: array[0..1] of Longint;
  567.   S: String[15];
  568.   B: TDrawBuffer;
  569. begin
  570.   if State and sfDragging = 0 then
  571.   begin
  572.     Color := GetColor(1);
  573.     Frame := #205;
  574.   end else
  575.   begin
  576.     Color := GetColor(2);
  577.     Frame := #196;
  578.   end;
  579.   MoveChar(B, Frame, Color, Size.X);
  580.   if Modified then WordRec(B[0]).Lo := 15;
  581.   L[0] := Location.Y + 1;
  582.   L[1] := Location.X + 1;
  583.   FormatStr(S, ' %d:%d ', L);
  584.   MoveStr(B[8 - Pos(':', S)], S, Color);
  585.   WriteBuf(0, 0, Size.X, 1, B);
  586. end;
  587.  
  588. function TIndicator.GetPalette: PPalette;
  589. const
  590.   P: string[Length(CIndicator)] = CIndicator;
  591. begin
  592.   GetPalette := @P;
  593. end;
  594.  
  595. procedure TIndicator.SetState(AState: Word; Enable: Boolean);
  596. begin
  597.   TView.SetState(AState, Enable);
  598.   if AState = sfDragging then DrawView;
  599. end;
  600.  
  601. procedure TIndicator.SetValue(ALocation: TPoint; AModified: Boolean);
  602. begin
  603.   if (Longint(Location) <> Longint(ALocation)) or
  604.     (Modified <> AModified) then
  605.   begin
  606.     Location := ALocation;
  607.     Modified := AModified;
  608.     DrawView;
  609.   end;
  610. end;
  611.  
  612. { TEditor }
  613.  
  614. constructor TEditor.Init(var Bounds: TRect;
  615.   AHScrollBar, AVScrollBar: PScrollBar;
  616.   AIndicator: PIndicator; ABufSize: Word);
  617. begin
  618.   TView.Init(Bounds);
  619.   GrowMode := gfGrowHiX + gfGrowHiY;
  620.   Options := Options or ofSelectable;
  621.   EventMask := evMouseDown + evKeyDown + evCommand + evBroadcast;
  622.   ShowCursor;
  623.   HScrollBar := AHScrollBar;
  624.   VScrollBar := AVScrollBar;
  625.   Indicator := AIndicator;
  626.   BufSize := ABufSize;
  627.   CanUndo := True;
  628.   InitBuffer;
  629.   if Buffer <> nil then IsValid := True else
  630.   begin
  631.     EditorDialog(edOutOfMemory, nil);
  632.     BufSize := 0;
  633.   end;
  634.   SetBufLen(0);
  635. end;
  636.  
  637. constructor TEditor.Load(var S: TStream);
  638. begin
  639.   TView.Load(S);
  640.   GetPeerViewPtr(S, HScrollBar);
  641.   GetPeerViewPtr(S, VScrollBar);
  642.   GetPeerViewPtr(S, Indicator);
  643.   S.Read(BufSize, SizeOf(Word));
  644.   S.Read(CanUndo, SizeOf(Boolean));
  645.   InitBuffer;
  646.   if Buffer <> nil then IsValid := True else
  647.   begin
  648.     EditorDialog(edOutOfMemory, nil);
  649.     BufSize := 0;
  650.   end;
  651.   Lock;
  652.   SetBufLen(0);
  653. end;
  654.  
  655. destructor TEditor.Done;
  656. begin
  657.   DoneBuffer;
  658.   TView.Done;
  659. end;
  660.  
  661. function TEditor.BufChar(P: Word): Char; assembler;
  662. asm
  663.     LES    DI,Self
  664.     MOV    BX,P
  665.     CMP    BX,ES:[DI].TEditor.CurPtr
  666.     JB    @@1
  667.     ADD    BX,ES:[DI].TEditor.GapLen
  668. @@1:    LES    DI,ES:[DI].TEditor.Buffer
  669.     MOV    AL,ES:[DI+BX]
  670. end;
  671.  
  672. function TEditor.BufPtr(P: Word): Word; assembler;
  673. asm
  674.     LES    DI,Self
  675.     MOV    AX,P
  676.     CMP    AX,ES:[DI].TEditor.CurPtr
  677.     JB    @@1
  678.     ADD    AX,ES:[DI].TEditor.GapLen
  679. @@1:
  680. end;
  681.  
  682. procedure TEditor.ChangeBounds(var Bounds: TRect);
  683. begin
  684.   SetBounds(Bounds);
  685.   Delta.X := Max(0, Min(Delta.X, Limit.X - Size.X));
  686.   Delta.Y := Max(0, Min(Delta.Y, Limit.Y - Size.Y));
  687.   Update(ufView);
  688. end;
  689.  
  690. function TEditor.CharPos(P, Target: Word): Integer;
  691. var
  692.   Pos: Integer;
  693. begin
  694.   Pos := 0;
  695.   while P < Target do
  696.   begin
  697.     if BufChar(P) = #9 then Pos := Pos or 7;
  698.     Inc(Pos);
  699.     Inc(P);
  700.   end;
  701.   CharPos := Pos;
  702. end;
  703.  
  704. function TEditor.CharPtr(P: Word; Target: Integer): Word;
  705. var
  706.   Pos: Integer;
  707. begin
  708.   Pos := 0;
  709.   while (Pos < Target) and (P < BufLen) and (BufChar(P) <> #13) do
  710.   begin
  711.     if BufChar(P) = #9 then Pos := Pos or 7;
  712.     Inc(Pos);
  713.     Inc(P);
  714.   end;
  715.   if Pos > Target then Dec(P);
  716.   CharPtr := P;
  717. end;
  718.  
  719. function TEditor.ClipCopy: Boolean;
  720. begin
  721.   ClipCopy := False;
  722.   if (Clipboard <> nil) and (Clipboard <> @Self) then
  723.   begin
  724.     ClipCopy := Clipboard^.InsertFrom(@Self);
  725.     Selecting := False;
  726.     Update(ufUpdate);
  727.   end;
  728. end;
  729.  
  730. procedure TEditor.ClipCut;
  731. begin
  732.   if ClipCopy then DeleteSelect;
  733. end;
  734.  
  735. procedure TEditor.ClipPaste;
  736. begin
  737.   if (Clipboard <> nil) and (Clipboard <> @Self) then InsertFrom(Clipboard);
  738. end;
  739.  
  740. procedure TEditor.ConvertEvent(var Event: TEvent);
  741. var
  742.   Key: Word;
  743. begin
  744.   if Event.What = evKeyDown then
  745.   begin
  746.     Key := Event.KeyCode;
  747.     if KeyState <> 0 then
  748.     begin
  749.       if (Lo(Key) >= $01) and (Lo(Key) <= $1A) then Inc(Key, $40);
  750.       if (Lo(Key) >= $61) and (Lo(Key) <= $7A) then Dec(Key, $20);
  751.     end;
  752.     Key := ScanKeyMap(KeyMap[KeyState], Key);
  753.     KeyState := 0;
  754.     if Key <> 0 then
  755.       if Hi(Key) = $FF then
  756.       begin
  757.         KeyState := Lo(Key);
  758.         ClearEvent(Event);
  759.       end else
  760.       begin
  761.         Event.What := evCommand;
  762.         Event.Command := Key;
  763.       end;
  764.   end;
  765. end;
  766.  
  767. function TEditor.CursorVisible: Boolean;
  768. begin
  769.   CursorVisible := (CurPos.Y >= Delta.Y) and (CurPos.Y < Delta.Y + Size.Y);
  770. end;
  771.  
  772. procedure TEditor.DeleteRange(StartPtr, EndPtr: Word; DelSelect: Boolean);
  773. begin
  774.   if HasSelection and DelSelect then DeleteSelect else
  775.   begin
  776.     SetSelect(CurPtr, EndPtr, True);
  777.     DeleteSelect;
  778.     SetSelect(StartPtr, CurPtr, False);
  779.     DeleteSelect;
  780.   end;
  781. end;
  782.  
  783. procedure TEditor.DeleteSelect;
  784. begin
  785.   InsertText(nil, 0, False);
  786. end;
  787.  
  788. procedure TEditor.DoneBuffer;
  789. begin
  790.   if Buffer <> nil then FreeMem(Buffer, BufSize);
  791. end;
  792.  
  793. procedure TEditor.DoSearchReplace;
  794. var
  795.   I: Word;
  796.   C: TPoint;
  797. begin
  798.   repeat
  799.     I := cmCancel;
  800.     if not Search(FindStr, EditorFlags) then
  801.     begin
  802.       if EditorFlags and (efReplaceAll + efDoReplace) <>
  803.           (efReplaceAll + efDoReplace) then
  804.         EditorDialog(edSearchFailed, nil)
  805.     end
  806.     else if EditorFlags and efDoReplace <> 0 then
  807.     begin
  808.       I := cmYes;
  809.       if EditorFlags and efPromptOnReplace <> 0 then
  810.       begin
  811.         MakeGlobal(Cursor, C);
  812.         I := EditorDialog(edReplacePrompt, Pointer(C));
  813.       end;
  814.       if I = cmYes then
  815.       begin
  816.         Lock;
  817.         InsertText(@ReplaceStr[1], Length(ReplaceStr), False);
  818.         TrackCursor(False);
  819.         Unlock;
  820.       end;
  821.     end;
  822.   until (I = cmCancel) or (EditorFlags and efReplaceAll = 0);
  823. end;
  824.  
  825. procedure TEditor.DoUpdate;
  826. begin
  827.   if UpdateFlags <> 0 then
  828.   begin
  829.     SetCursor(CurPos.X - Delta.X, CurPos.Y - Delta.Y);
  830.     if UpdateFlags and ufView <> 0 then DrawView else
  831.       if UpdateFlags and ufLine <> 0 then
  832.         DrawLines(CurPos.Y - Delta.Y, 1, LineStart(CurPtr));
  833.     if HScrollBar <> nil then
  834.       HScrollBar^.SetParams(Delta.X, 0, Limit.X - Size.X, Size.X div 2, 1);
  835.     if VScrollBar <> nil then
  836.       VScrollBar^.SetParams(Delta.Y, 0, Limit.Y - Size.Y, Size.Y - 1, 1);
  837.     if Indicator <> nil then Indicator^.SetValue(CurPos, Modified);
  838.     if State and sfActive <> 0 then UpdateCommands;
  839.     UpdateFlags := 0;
  840.   end;
  841. end;
  842.  
  843. procedure TEditor.Draw;
  844. begin
  845.   if DrawLine <> Delta.Y then
  846.   begin
  847.     DrawPtr := LineMove(DrawPtr, Delta.Y - DrawLine);
  848.     DrawLine := Delta.Y;
  849.   end;
  850.   DrawLines(0, Size.Y, DrawPtr);
  851. end;
  852.  
  853. procedure TEditor.DrawLines(Y, Count: Integer; LinePtr: Word);
  854. var
  855.   Color: Word;
  856.   B: array[0..MaxLineLength - 1] of Word;
  857. begin
  858.   Color := GetColor($0201);
  859.   while Count > 0 do
  860.   begin
  861.     FormatLine(B, LinePtr, Delta.X + Size.X, Color);
  862.     WriteBuf(0, Y, Size.X, 1, B[Delta.X]);
  863.     LinePtr := NextLine(LinePtr);
  864.     Inc(Y);
  865.     Dec(Count);
  866.   end;
  867. end;
  868.  
  869. procedure TEditor.Find;
  870. var
  871.   FindRec: TFindDialogRec;
  872. begin
  873.   with FindRec do
  874.   begin
  875.     Find := FindStr;
  876.     Options := EditorFlags;
  877.     if EditorDialog(edFind, @FindRec) <> cmCancel then
  878.     begin
  879.       FindStr := Find;
  880.       EditorFlags := Options and not efDoReplace;
  881.       DoSearchReplace;
  882.     end;
  883.   end;
  884. end;
  885.  
  886. procedure TEditor.FormatLine(var DrawBuf; LinePtr: Word;
  887.   Width: Integer; Colors: Word); assembler;
  888. asm
  889.     PUSH    DS
  890.     LDS    BX,Self
  891.     LES    DI,DrawBuf
  892.     MOV    SI,LinePtr
  893.     XOR    DX,DX
  894.     CLD
  895.     MOV    AH,Colors.Byte[0]
  896.     MOV    CX,DS:[BX].TEditor.SelStart
  897.     CALL    @@10
  898.     MOV    AH,Colors.Byte[1]
  899.     MOV    CX,DS:[BX].TEditor.CurPtr
  900.     CALL    @@10
  901.     ADD    SI,DS:[BX].TEditor.GapLen
  902.     MOV    CX,DS:[BX].TEditor.SelEnd
  903.     ADD    CX,DS:[BX].TEditor.GapLen
  904.     CALL    @@10
  905.     MOV    AH,Colors.Byte[0]
  906.     MOV    CX,DS:[BX].TEditor.BufSize
  907.     CALL    @@10
  908.     JMP    @@31
  909. @@10:    SUB    CX,SI
  910.     JA    @@11
  911.     RETN
  912. @@11:    LDS    BX,DS:[BX].TEditor.Buffer
  913.     ADD    SI,BX
  914.     MOV    BX,Width
  915. @@12:    LODSB
  916.     CMP    AL,' '
  917.     JB    @@20
  918. @@13:    STOSW
  919.     INC    DX
  920. @@14:    CMP    DX,BX
  921.     JAE    @@30
  922.     LOOP    @@12
  923.     LDS    BX,Self
  924.     SUB    SI,DS:[BX].TEditor.Buffer.Word[0]
  925.     RETN
  926. @@20:    CMP    AL,0DH
  927.     JE    @@30
  928.     CMP    AL,09H
  929.     JNE    @@13
  930.     MOV    AL,' '
  931. @@21:    STOSW
  932.     INC    DX
  933.     TEST    DL,7
  934.     JNE    @@21
  935.     JMP    @@14
  936. @@30:    POP    CX
  937. @@31:    MOV    AL,' '
  938.     MOV    CX,Width
  939.     SUB    CX,DX
  940.     JBE    @@32
  941.     REP    STOSW
  942. @@32:    POP    DS
  943. end;
  944.  
  945. function TEditor.GetMousePtr(Mouse: TPoint): Word;
  946. begin
  947.   MakeLocal(Mouse, Mouse);
  948.   Mouse.X := Max(0, Min(Mouse.X, Size.X - 1));
  949.   Mouse.Y := Max(0, Min(Mouse.Y, Size.Y - 1));
  950.   GetMousePtr := CharPtr(LineMove(DrawPtr, Mouse.Y + Delta.Y - DrawLine),
  951.     Mouse.X + Delta.X);
  952. end;
  953.  
  954. function TEditor.GetPalette: PPalette;
  955. const
  956.   P: String[Length(CEditor)] = CEditor;
  957. begin
  958.   GetPalette := @P;
  959. end;
  960.  
  961. procedure TEditor.HandleEvent(var Event: TEvent);
  962. var
  963.   ShiftState: Byte absolute $40:$17;
  964.   CenterCursor: Boolean;
  965.   SelectMode: Byte;
  966.   I: Integer;
  967.   NewPtr: Word;
  968.   D, Mouse: TPoint;
  969.  
  970. procedure CheckScrollBar(P: PScrollBar; var D: Integer);
  971. begin
  972.   if (Event.InfoPtr = P) and (P^.Value <> D) then
  973.   begin
  974.     D := P^.Value;
  975.     Update(ufView);
  976.   end;
  977. end;
  978.  
  979. begin
  980.   TView.HandleEvent(Event);
  981.   ConvertEvent(Event);
  982.   CenterCursor := not CursorVisible;
  983.   SelectMode := 0;
  984.   if Selecting or (ShiftState and $03 <> 0) then SelectMode := smExtend;
  985.   case Event.What of
  986.     evMouseDown:
  987.       begin
  988.         if Event.Double then SelectMode := SelectMode or smDouble;
  989.         repeat
  990.           Lock;
  991.           if Event.What = evMouseAuto then
  992.           begin
  993.             MakeLocal(Event.Where, Mouse);
  994.             D := Delta;
  995.             if Mouse.X < 0 then Dec(D.X);
  996.             if Mouse.X >= Size.X then Inc(D.X);
  997.             if Mouse.Y < 0 then Dec(D.Y);
  998.             if Mouse.Y >= Size.Y then Inc(D.Y);
  999.             ScrollTo(D.X, D.Y);
  1000.           end;
  1001.           SetCurPtr(GetMousePtr(Event.Where), SelectMode);
  1002.           SelectMode := SelectMode or smExtend;
  1003.           Unlock;
  1004.         until not MouseEvent(Event, evMouseMove + evMouseAuto);
  1005.       end;
  1006.     evKeyDown:
  1007.       case Event.CharCode of
  1008.         #9,#32..#255:
  1009.           begin
  1010.             Lock;
  1011.             if Overwrite and not HasSelection then
  1012.               if CurPtr <> LineEnd(CurPtr) then SelEnd := NextChar(CurPtr);
  1013.             InsertText(@Event.CharCode, 1, False);
  1014.             TrackCursor(CenterCursor);
  1015.             Unlock;
  1016.           end;
  1017.       else
  1018.         Exit;           
  1019.       end;
  1020.     evCommand:
  1021.       case Event.Command of
  1022.         cmFind: Find;
  1023.         cmReplace: Replace;
  1024.         cmSearchAgain: DoSearchReplace;
  1025.       else
  1026.         begin
  1027.           Lock;
  1028.           case Event.Command of
  1029.             cmCut: ClipCut;
  1030.             cmCopy: ClipCopy;
  1031.             cmPaste: ClipPaste;
  1032.             cmUndo: Undo;
  1033.             cmClear: DeleteSelect;
  1034.             cmCharLeft: SetCurPtr(PrevChar(CurPtr), SelectMode);
  1035.             cmCharRight: SetCurPtr(NextChar(CurPtr), SelectMode);
  1036.             cmWordLeft: SetCurPtr(PrevWord(CurPtr), SelectMode);
  1037.             cmWordRight: SetCurPtr(NextWord(CurPtr), SelectMode);
  1038.             cmLineStart: SetCurPtr(LineStart(CurPtr), SelectMode);
  1039.             cmLineEnd: SetCurPtr(LineEnd(CurPtr), SelectMode);
  1040.             cmLineUp: SetCurPtr(LineMove(CurPtr, -1), SelectMode);
  1041.             cmLineDown: SetCurPtr(LineMove(CurPtr, 1), SelectMode);
  1042.             cmPageUp: SetCurPtr(LineMove(CurPtr, -(Size.Y - 1)), SelectMode);
  1043.             cmPageDown: SetCurPtr(LineMove(CurPtr, Size.Y - 1), SelectMode);
  1044.             cmTextStart: SetCurPtr(0, SelectMode);
  1045.             cmTextEnd: SetCurPtr(BufLen, SelectMode);
  1046.             cmNewLine: NewLine;
  1047.             cmBackSpace: DeleteRange(PrevChar(CurPtr), CurPtr, True);
  1048.             cmDelChar: DeleteRange(CurPtr, NextChar(CurPtr), True);
  1049.             cmDelWord: DeleteRange(CurPtr, NextWord(CurPtr), False);
  1050.             cmDelStart: DeleteRange(LineStart(CurPtr), CurPtr, False);
  1051.             cmDelEnd: DeleteRange(CurPtr, LineEnd(CurPtr), False);
  1052.             cmDelLine: DeleteRange(LineStart(CurPtr), NextLine(CurPtr), False);
  1053.             cmInsMode: ToggleInsMode;
  1054.             cmStartSelect: StartSelect;
  1055.             cmHideSelect: HideSelect;
  1056.             cmIndentMode: AutoIndent := not AutoIndent;
  1057.           else
  1058.             Unlock;
  1059.             Exit;
  1060.           end;
  1061.           TrackCursor(CenterCursor);
  1062.           Unlock;
  1063.         end;
  1064.       end;
  1065.     evBroadcast:
  1066.       case Event.Command of
  1067.         cmScrollBarChanged:
  1068.           begin
  1069.             CheckScrollBar(HScrollBar, Delta.X);
  1070.             CheckScrollBar(VScrollBar, Delta.Y);
  1071.           end;
  1072.       else
  1073.         Exit;
  1074.       end;
  1075.   end;
  1076.   ClearEvent(Event);
  1077. end;
  1078.  
  1079. function TEditor.HasSelection: Boolean;
  1080. begin
  1081.   HasSelection := SelStart <> SelEnd;
  1082. end;
  1083.  
  1084. procedure TEditor.HideSelect;
  1085. begin
  1086.   Selecting := False;
  1087.   SetSelect(CurPtr, CurPtr, False);
  1088. end;
  1089.  
  1090. procedure TEditor.InitBuffer;
  1091. begin
  1092.   Buffer := MemAlloc(BufSize);
  1093. end;
  1094.  
  1095. function TEditor.InsertBuffer(var P: PEditBuffer; Offset, Length: Word;
  1096.   AllowUndo, SelectText: Boolean): Boolean;
  1097. var
  1098.   SelLen, DelLen, SelLines, Lines: Word;
  1099.   NewSize: Longint;
  1100. begin
  1101.   InsertBuffer := True;
  1102.   Selecting := False;
  1103.   SelLen := SelEnd - SelStart;
  1104.   if (SelLen = 0) and (Length = 0) then Exit;
  1105.   DelLen := 0;
  1106.   if AllowUndo then
  1107.     if CurPtr = SelStart then DelLen := SelLen else
  1108.       if SelLen > InsCount then DelLen := SelLen - InsCount;
  1109.   NewSize := Longint(BufLen + DelCount - SelLen + DelLen) + Length;
  1110.   if NewSize > BufLen + DelCount then
  1111.     if (NewSize > $FFF0) or not SetBufSize(NewSize) then
  1112.     begin
  1113.       EditorDialog(edOutOfMemory, nil);
  1114.       InsertBuffer := False;
  1115.       Exit;
  1116.     end;
  1117.   SelLines := CountLines(Buffer^[BufPtr(SelStart)], SelLen);
  1118.   if CurPtr = SelEnd then
  1119.   begin
  1120.     if AllowUndo then
  1121.     begin
  1122.       if DelLen > 0 then Move(Buffer^[SelStart],
  1123.         Buffer^[CurPtr + GapLen - DelCount - DelLen], DelLen);
  1124.       Dec(InsCount, SelLen - DelLen);
  1125.     end;
  1126.     CurPtr := SelStart;
  1127.     Dec(CurPos.Y, SelLines);
  1128.   end;
  1129.   if Delta.Y > CurPos.Y then
  1130.   begin
  1131.     Dec(Delta.Y, SelLines);
  1132.     if Delta.Y < CurPos.Y then Delta.Y := CurPos.Y;
  1133.   end;
  1134.   if Length > 0 then Move(P^[Offset], Buffer^[CurPtr], Length);
  1135.   Lines := CountLines(Buffer^[CurPtr], Length);
  1136.   Inc(CurPtr, Length);
  1137.   Inc(CurPos.Y, Lines);
  1138.   DrawLine := CurPos.Y;
  1139.   DrawPtr := LineStart(CurPtr);
  1140.   CurPos.X := CharPos(DrawPtr, CurPtr);
  1141.   if not SelectText then SelStart := CurPtr;
  1142.   SelEnd := CurPtr;
  1143.   Inc(BufLen, Length - SelLen);
  1144.   Dec(GapLen, Length - SelLen);
  1145.   if AllowUndo then
  1146.   begin
  1147.     Inc(DelCount, DelLen);
  1148.     Inc(InsCount, Length);
  1149.   end;
  1150.   Inc(Limit.Y, Lines - SelLines);
  1151.   Delta.Y := Max(0, Min(Delta.Y, Limit.Y - Size.Y));
  1152.   if not IsClipboard then Modified := True;
  1153.   SetBufSize(BufLen + DelCount);
  1154.   if (SelLines = 0) and (Lines = 0) then Update(ufLine) else Update(ufView);
  1155. end;
  1156.  
  1157. function TEditor.InsertFrom(Editor: PEditor): Boolean;
  1158. begin
  1159.   InsertFrom := InsertBuffer(Editor^.Buffer,
  1160.     Editor^.BufPtr(Editor^.SelStart),
  1161.     Editor^.SelEnd - Editor^.SelStart, CanUndo, IsClipboard);
  1162. end;
  1163.  
  1164. function TEditor.InsertText(Text: Pointer; Length: Word;
  1165.   SelectText: Boolean): Boolean;
  1166. begin
  1167.   InsertText := InsertBuffer(PEditBuffer(Text),
  1168.     0, Length, CanUndo, SelectText);
  1169. end;
  1170.  
  1171. function TEditor.IsClipboard: Boolean;
  1172. begin
  1173.   IsClipboard := Clipboard = @Self;
  1174. end;
  1175.  
  1176. function TEditor.LineEnd(P: Word): Word; assembler;
  1177. asm
  1178.     PUSH    DS
  1179.     LDS    SI,Self
  1180.     LES    BX,DS:[SI].TEditor.Buffer
  1181.     MOV    DI,P
  1182.     MOV    AL,0DH
  1183.     CLD
  1184.     MOV    CX,DS:[SI].TEditor.CurPtr
  1185.     SUB    CX,DI
  1186.     JBE    @@1
  1187.     ADD    DI,BX
  1188.     REPNE    SCASB
  1189.     JE    @@2
  1190.     MOV    DI,DS:[SI].TEditor.CurPtr
  1191. @@1:    MOV    CX,DS:[SI].TEditor.BufLen
  1192.     SUB    CX,DI
  1193.     JCXZ    @@4
  1194.     ADD    BX,DS:[SI].TEditor.GapLen
  1195.     ADD    DI,BX
  1196.     REPNE    SCASB
  1197.     JNE    @@3
  1198. @@2:    DEC    DI
  1199. @@3:    SUB    DI,BX
  1200. @@4:    MOV    AX,DI
  1201.     POP    DS
  1202. end;
  1203.  
  1204. function TEditor.LineMove(P: Word; Count: Integer): Word;
  1205. var
  1206.   Pos: Integer;
  1207.   I: Word;
  1208. begin
  1209.   I := P;
  1210.   P := LineStart(P);
  1211.   Pos := CharPos(P, I);
  1212.   while Count <> 0 do
  1213.   begin
  1214.     I := P;
  1215.     if Count < 0 then
  1216.     begin
  1217.       P := PrevLine(P);
  1218.       Inc(Count);
  1219.     end else
  1220.     begin
  1221.       P := NextLine(P);
  1222.       Dec(Count);
  1223.     end;
  1224.   end;
  1225.   if P <> I then P := CharPtr(P, Pos);
  1226.   LineMove := P;
  1227. end;
  1228.  
  1229. function TEditor.LineStart(P: Word): Word; assembler;
  1230. asm
  1231.     PUSH    DS
  1232.     LDS    SI,Self
  1233.     LES    BX,DS:[SI].TEditor.Buffer
  1234.     MOV    DI,P
  1235.     MOV    AL,0DH
  1236.     STD
  1237.     MOV    CX,DI
  1238.     SUB    CX,DS:[SI].TEditor.CurPtr
  1239.     JBE    @@1
  1240.         ADD    BX,DS:[SI].TEditor.GapLen
  1241.     ADD    DI,BX
  1242.     DEC    DI
  1243.     REPNE    SCASB
  1244.     JE    @@2
  1245.     SUB    BX,DS:[SI].TEditor.GapLen
  1246.     MOV    DI,DS:[SI].TEditor.CurPtr
  1247. @@1:    MOV    CX,DI
  1248.     JCXZ    @@4
  1249.     ADD    DI,BX
  1250.     DEC    DI
  1251.     REPNE    SCASB
  1252.     JNE    @@3
  1253. @@2:    INC    DI
  1254.     INC    DI
  1255.     SUB    DI,BX
  1256.     CMP    DI,DS:[SI].TEditor.CurPtr
  1257.     JE    @@4
  1258.     CMP    DI,DS:[SI].TEditor.BufLen
  1259.     JE    @@4
  1260.     CMP    ES:[BX+DI].Byte,0AH
  1261.     JNE    @@4
  1262.     INC    DI
  1263.     JMP    @@4
  1264. @@3:    XOR    DI,DI
  1265. @@4:    MOV    AX,DI
  1266.     POP    DS
  1267. end;
  1268.  
  1269. procedure TEditor.Lock;
  1270. begin
  1271.   Inc(LockCount);
  1272. end;
  1273.  
  1274. procedure TEditor.NewLine;
  1275. const
  1276.   CrLf: array[1..2] of Char = #13#10;
  1277. var
  1278.   I, P: Word;
  1279. begin
  1280.   P := LineStart(CurPtr);
  1281.   I := P;
  1282.   while (I < CurPtr) and ((Buffer^[I] = ' ') or (Buffer^[I] = #9)) do Inc(I);
  1283.   InsertText(@CrLf, 2, False);
  1284.   if AutoIndent then InsertText(@Buffer^[P], I - P, False);
  1285. end;
  1286.  
  1287. function TEditor.NextChar(P: Word): Word; assembler;
  1288. asm
  1289.     PUSH    DS
  1290.     LDS    SI,Self
  1291.     MOV    DI,P
  1292.     CMP    DI,DS:[SI].TEditor.BufLen
  1293.     JE    @@2
  1294.     INC    DI
  1295.     CMP    DI,DS:[SI].TEditor.BufLen
  1296.     JE    @@2
  1297.     LES    BX,DS:[SI].TEditor.Buffer
  1298.     CMP    DI,DS:[SI].TEditor.CurPtr
  1299.     JB    @@1
  1300.     ADD    BX,DS:[SI].TEditor.GapLen
  1301. @@1:    CMP    ES:[BX+DI-1].Word,0A0DH
  1302.     JNE    @@2
  1303.     INC    DI
  1304. @@2:    MOV    AX,DI
  1305.     POP    DS
  1306. end;
  1307.  
  1308. function TEditor.NextLine(P: Word): Word;
  1309. begin
  1310.   NextLine := NextChar(LineEnd(P));
  1311. end;
  1312.  
  1313. function TEditor.NextWord(P: Word): Word;
  1314. begin
  1315.   while (P < BufLen) and (BufChar(P) in WordChars) do
  1316.     P := NextChar(P);
  1317.   while (P < BufLen) and not (BufChar(P) in WordChars) do
  1318.     P := NextChar(P);
  1319.   NextWord := P;
  1320. end;
  1321.  
  1322. function TEditor.PrevChar(P: Word): Word; assembler;
  1323. asm
  1324.     PUSH    DS
  1325.     LDS    SI,Self
  1326.     MOV    DI,P
  1327.     OR    DI,DI
  1328.     JE    @@2
  1329.     DEC    DI
  1330.     JE    @@2
  1331.     LES    BX,DS:[SI].TEditor.Buffer
  1332.     CMP    DI,DS:[SI].TEditor.CurPtr
  1333.     JB    @@1
  1334.     ADD    BX,DS:[SI].TEditor.GapLen
  1335. @@1:    CMP    ES:[BX+DI-1].Word,0A0DH
  1336.     JNE    @@2
  1337.     DEC    DI
  1338. @@2:    MOV    AX,DI
  1339.     POP    DS
  1340. end;
  1341.  
  1342. function TEditor.PrevLine(P: Word): Word;
  1343. begin
  1344.   PrevLine := LineStart(PrevChar(P));
  1345. end;
  1346.  
  1347. function TEditor.PrevWord(P: Word): Word;
  1348. begin
  1349.   while (P > 0) and not (BufChar(PrevChar(P)) in WordChars) do
  1350.     P := PrevChar(P);
  1351.   while (P > 0) and (BufChar(PrevChar(P)) in WordChars) do
  1352.     P := PrevChar(P);
  1353.   PrevWord := P;
  1354. end;
  1355.  
  1356. procedure TEditor.Replace;
  1357. var
  1358.   ReplaceRec: TReplaceDialogRec;
  1359. begin
  1360.   with ReplaceRec do
  1361.   begin
  1362.     Find := FindStr;
  1363.     Replace := ReplaceStr;
  1364.     Options := EditorFlags;
  1365.     if EditorDialog(edReplace, @ReplaceRec) <> cmCancel then
  1366.     begin
  1367.       FindStr := Find;
  1368.       ReplaceStr := Replace;
  1369.       EditorFlags := Options or efDoReplace;
  1370.       DoSearchReplace;
  1371.     end;
  1372.   end;
  1373. end;
  1374.  
  1375. procedure TEditor.ScrollTo(X, Y: Integer);
  1376. begin
  1377.   X := Max(0, Min(X, Limit.X - Size.X));
  1378.   Y := Max(0, Min(Y, Limit.Y - Size.Y));
  1379.   if (X <> Delta.X) or (Y <> Delta.Y) then
  1380.   begin
  1381.     Delta.X := X;
  1382.     Delta.Y := Y;
  1383.     Update(ufView);
  1384.   end;
  1385. end;
  1386.  
  1387. function TEditor.Search(FindStr: String; Opts: Word): Boolean;
  1388. var
  1389.   I, Pos: Word;
  1390. begin
  1391.   Search := False;
  1392.   Pos := CurPtr;
  1393.   repeat
  1394.     if Opts and efCaseSensitive <> 0 then
  1395.       I := Scan(Buffer^[BufPtr(Pos)], BufLen - Pos, FindStr)
  1396.     else I := IScan(Buffer^[BufPtr(Pos)], BufLen - Pos, FindStr);
  1397.     if (I <> sfSearchFailed) then
  1398.     begin
  1399.       Inc(I, Pos);
  1400.       if (Opts and efWholeWordsOnly = 0) or
  1401.          not (((I <> 0) and (BufChar(I - 1) in WordChars)) or
  1402.               ((I + Length(FindStr) <> BufLen) and
  1403.                (BufChar(I + Length(FindStr)) in WordChars))) then
  1404.       begin
  1405.         Lock;
  1406.         SetSelect(I, I + Length(FindStr), False);
  1407.         TrackCursor(not CursorVisible);
  1408.         Unlock;
  1409.         Search := True;
  1410.         Exit;
  1411.       end else Pos := I + 1;
  1412.     end;
  1413.   until I = sfSearchFailed;
  1414. end;
  1415.  
  1416. procedure TEditor.SetBufLen(Length: Word);
  1417. begin
  1418.   BufLen := Length;
  1419.   GapLen := BufSize - Length;
  1420.   SelStart := 0;
  1421.   SelEnd := 0;
  1422.   CurPtr := 0;
  1423.   Longint(CurPos) := 0;
  1424.   Longint(Delta) := 0;
  1425.   Limit.X := MaxLineLength;
  1426.   Limit.Y := CountLines(Buffer^[GapLen], BufLen) + 1;
  1427.   DrawLine := 0;
  1428.   DrawPtr := 0;
  1429.   DelCount := 0;
  1430.   InsCount := 0;
  1431.   Modified := False;
  1432.   Update(ufView);
  1433. end;
  1434.  
  1435. function TEditor.SetBufSize(NewSize: Word): Boolean;
  1436. begin
  1437.   SetBufSize := NewSize <= BufSize;
  1438. end;
  1439.  
  1440. procedure TEditor.SetCmdState(Command: Word; Enable: Boolean);
  1441. var
  1442.   S: TCommandSet;
  1443. begin
  1444.   S := [Command];
  1445.   if Enable and (State and sfActive <> 0) then
  1446.     EnableCommands(S) else DisableCommands(S);
  1447. end;
  1448.  
  1449. procedure TEditor.SetCurPtr(P: Word; SelectMode: Byte);
  1450. var
  1451.   Anchor: Word;
  1452. begin
  1453.   if SelectMode and smExtend = 0 then Anchor := P else
  1454.     if CurPtr = SelStart then Anchor := SelEnd else Anchor := SelStart;
  1455.   if P < Anchor then
  1456.   begin
  1457.     if SelectMode and smDouble <> 0 then
  1458.     begin
  1459.       P := PrevLine(NextLine(P));
  1460.       Anchor := NextLine(PrevLine(Anchor));
  1461.     end;
  1462.     SetSelect(P, Anchor, True);
  1463.   end else
  1464.   begin
  1465.     if SelectMode and smDouble <> 0 then
  1466.     begin
  1467.       P := NextLine(P);
  1468.       Anchor := PrevLine(NextLine(Anchor));
  1469.     end;
  1470.     SetSelect(Anchor, P, False);
  1471.   end;
  1472. end;
  1473.  
  1474. procedure TEditor.SetSelect(NewStart, NewEnd: Word; CurStart: Boolean);
  1475. var
  1476.   Flags: Byte;
  1477.   P, L: Word;
  1478. begin
  1479.   if CurStart then P := NewStart else P := NewEnd;
  1480.   Flags := ufUpdate;
  1481.   if (NewStart <> SelStart) or (NewEnd <> SelEnd) then
  1482.     if (NewStart <> NewEnd) or (SelStart <> SelEnd) then
  1483.       Flags := ufView;
  1484.   if P <> CurPtr then
  1485.   begin
  1486.     if P > CurPtr then
  1487.     begin
  1488.       L := P - CurPtr;
  1489.       Move(Buffer^[CurPtr + GapLen], Buffer^[CurPtr], L);
  1490.       Inc(CurPos.Y, CountLines(Buffer^[CurPtr], L));
  1491.       CurPtr := P;
  1492.     end else
  1493.     begin
  1494.       L := CurPtr - P;
  1495.       CurPtr := P;
  1496.       Dec(CurPos.Y, CountLines(Buffer^[CurPtr], L));
  1497.       Move(Buffer^[CurPtr], Buffer^[CurPtr + GapLen], L);
  1498.     end;
  1499.     DrawLine := CurPos.Y;
  1500.     DrawPtr := LineStart(P);
  1501.     CurPos.X := CharPos(DrawPtr, P);
  1502.     DelCount := 0;
  1503.     InsCount := 0;
  1504.     SetBufSize(BufLen);
  1505.   end;
  1506.   SelStart := NewStart;
  1507.   SelEnd := NewEnd;
  1508.   Update(Flags);
  1509. end;
  1510.  
  1511. procedure TEditor.SetState(AState: Word; Enable: Boolean);
  1512. begin
  1513.   TView.SetState(AState, Enable);
  1514.   case AState of
  1515.     sfActive:
  1516.       begin
  1517.         if HScrollBar <> nil then HScrollBar^.SetState(sfVisible, Enable);
  1518.         if VScrollBar <> nil then VScrollBar^.SetState(sfVisible, Enable);
  1519.         if Indicator <> nil then Indicator^.SetState(sfVisible, Enable);
  1520.         UpdateCommands;
  1521.       end;
  1522.     sfExposed:
  1523.       if Enable then Unlock;
  1524.   end;
  1525. end;
  1526.  
  1527. procedure TEditor.StartSelect;
  1528. begin
  1529.   HideSelect;
  1530.   Selecting := True;
  1531. end;
  1532.  
  1533. procedure TEditor.Store(var S: TStream);
  1534. begin
  1535.   TView.Store(S);
  1536.   PutPeerViewPtr(S, HScrollBar);
  1537.   PutPeerViewPtr(S, VScrollBar);
  1538.   PutPeerViewPtr(S, Indicator);
  1539.   S.Write(BufSize, SizeOf(Word));
  1540.   S.Write(CanUndo, SizeOf(Boolean));
  1541. end;
  1542.  
  1543. procedure TEditor.ToggleInsMode;
  1544. begin
  1545.   Overwrite := not Overwrite;
  1546.   SetState(sfCursorIns, not GetState(sfCursorIns));
  1547. end;
  1548.  
  1549. procedure TEditor.TrackCursor(Center: Boolean);
  1550. begin
  1551.   if Center then
  1552.     ScrollTo(CurPos.X - Size.X + 1, CurPos.Y - Size.Y div 2) else
  1553.     ScrollTo(Max(CurPos.X - Size.X + 1, Min(Delta.X, CurPos.X)),
  1554.       Max(CurPos.Y - Size.Y + 1, Min(Delta.Y, CurPos.Y)));
  1555. end;
  1556.  
  1557. procedure TEditor.Undo;
  1558. var
  1559.   Length: Word;
  1560. begin
  1561.   if (DelCount <> 0) or (InsCount <> 0) then
  1562.   begin
  1563.     SelStart := CurPtr - InsCount;
  1564.     SelEnd := CurPtr;
  1565.     Length := DelCount;
  1566.     DelCount := 0;
  1567.     InsCount := 0;
  1568.     InsertBuffer(Buffer, CurPtr + GapLen - Length, Length, False, True);
  1569.   end;
  1570. end;
  1571.  
  1572. procedure TEditor.Unlock;
  1573. begin
  1574.   if LockCount > 0 then
  1575.   begin
  1576.     Dec(LockCount);
  1577.     if LockCount = 0 then DoUpdate;
  1578.   end;
  1579. end;
  1580.  
  1581. procedure TEditor.Update(AFlags: Byte);
  1582. begin
  1583.   UpdateFlags := UpdateFlags or AFlags;
  1584.   if LockCount = 0 then DoUpdate;
  1585. end;
  1586.  
  1587. procedure TEditor.UpdateCommands;
  1588. begin
  1589.   SetCmdState(cmUndo, (DelCount <> 0) or (InsCount <> 0));
  1590.   if not IsClipboard then
  1591.   begin
  1592.     SetCmdState(cmCut, HasSelection);
  1593.     SetCmdState(cmCopy, HasSelection);
  1594.     SetCmdState(cmPaste, (Clipboard <> nil) and (Clipboard^.HasSelection));
  1595.   end;
  1596.   SetCmdState(cmClear, HasSelection);
  1597.   SetCmdState(cmFind, True);
  1598.   SetCmdState(cmReplace, True);
  1599.   SetCmdState(cmSearchAgain, True);
  1600. end;
  1601.  
  1602. function TEditor.Valid(Command: Word): Boolean;
  1603. begin
  1604.   Valid := IsValid;
  1605. end;
  1606.  
  1607. { TMemo }
  1608.  
  1609. constructor TMemo.Load(var S: TStream);
  1610. var
  1611.   Length: Word;
  1612. begin
  1613.   TEditor.Load(S);
  1614.   S.Read(Length, SizeOf(Word));
  1615.   if IsValid then
  1616.   begin
  1617.     S.Read(Buffer^[BufSize - Length], Length);
  1618.     SetBufLen(Length);
  1619.   end
  1620.   else S.Seek(S.GetPos + Length);
  1621. end;
  1622.  
  1623. function TMemo.DataSize: Word;
  1624. begin
  1625.   DataSize := BufSize + SizeOf(Word);
  1626. end;
  1627.  
  1628. procedure TMemo.GetData(var Rec);
  1629. var
  1630.   Data: TMemoData absolute Rec;
  1631. begin
  1632.   Data.Length := BufLen;
  1633.   Move(Buffer^, Data.Buffer, CurPtr);
  1634.   Move(Buffer^[CurPtr + GapLen], Data.Buffer[CurPtr], BufLen - CurPtr);
  1635.   FillChar(Data.Buffer[BufLen], BufSize - BufLen, 0);
  1636. end;
  1637.  
  1638. function TMemo.GetPalette: PPalette;
  1639. const
  1640.   P: String[Length(CMemo)] = CMemo;
  1641. begin
  1642.   GetPalette := @P;
  1643. end;
  1644.  
  1645. procedure TMemo.HandleEvent(var Event: TEvent);
  1646. begin
  1647.   if (Event.What <> evKeyDown) or (Event.KeyCode <> kbTab) then
  1648.     TEditor.HandleEvent(Event);
  1649. end;
  1650.  
  1651. procedure TMemo.SetData(var Rec);
  1652. var
  1653.   Data: TMemoData absolute Rec;
  1654. begin
  1655.   Move(Data.Buffer, Buffer^[BufSize - Data.Length], Data.Length);
  1656.   SetBufLen(Data.Length);
  1657. end;
  1658.  
  1659. procedure TMemo.Store(var S: TStream);
  1660. begin
  1661.   TEditor.Store(S);
  1662.   S.Write(BufLen, SizeOf(Word));
  1663.   S.Write(Buffer^, CurPtr);
  1664.   S.Write(Buffer^[CurPtr + GapLen], BufLen - CurPtr);
  1665. end;
  1666.  
  1667. { TFileEditor }
  1668.  
  1669. constructor TFileEditor.Init(var Bounds: TRect;
  1670.   AHScrollBar, AVScrollBar: PScrollBar;
  1671.   AIndicator: PIndicator; AFileName: FNameStr);
  1672. begin
  1673.   TEditor.Init(Bounds, AHScrollBar, AVScrollBar, AIndicator, 0);
  1674.   if AFileName <> '' then
  1675.   begin
  1676.     FileName := FExpand(AFileName);
  1677.     if IsValid then IsValid := LoadFile;
  1678.   end;
  1679. end;
  1680.  
  1681. constructor TFileEditor.Load(var S: TStream);
  1682. var
  1683.   SStart, SEnd, Curs: Word;
  1684. begin
  1685.   TEditor.Load(S);
  1686.   S.Read(FileName[0], SizeOf(Char));
  1687.   S.Read(Filename[1], Length(FileName));
  1688.   if IsValid then IsValid := LoadFile;
  1689.   S.Read(SStart, SizeOf(Word));
  1690.   S.Read(SEnd, SizeOf(Word));
  1691.   S.Read(Curs, SizeOf(Word));
  1692.   if IsValid and (SEnd <= BufLen) then
  1693.   begin
  1694.     SetSelect(SStart, SEnd, Curs = SStart);
  1695.     TrackCursor(True);
  1696.   end;
  1697. end;
  1698.  
  1699. procedure TFileEditor.DoneBuffer;
  1700. begin
  1701.   if Buffer <> nil then DisposeBuffer(Buffer);
  1702. end;
  1703.  
  1704. procedure TFileEditor.HandleEvent(var Event: TEvent);
  1705. begin
  1706.   TEditor.HandleEvent(Event);
  1707.   case Event.What of
  1708.     evCommand:
  1709.       case Event.Command of
  1710.         cmSave: Save;
  1711.         cmSaveAs: SaveAs;
  1712.       else
  1713.         Exit;
  1714.       end;
  1715.   else
  1716.     Exit;
  1717.   end;
  1718.   ClearEvent(Event);
  1719. end;
  1720.  
  1721. procedure TFileEditor.InitBuffer;
  1722. begin
  1723.   NewBuffer(Pointer(Buffer));
  1724. end;
  1725.  
  1726. function TFileEditor.LoadFile: Boolean;
  1727. var
  1728.   Length: Word;
  1729.   FSize: Longint;
  1730.   F: File;
  1731. begin
  1732.   LoadFile := False;
  1733.   Length := 0;
  1734.   Assign(F, FileName);
  1735.   Reset(F, 1);
  1736.   if IOResult <> 0 then LoadFile := True else
  1737.   begin
  1738.     FSize := FileSize(F);
  1739.     if (FSize > $FFF0) or not SetBufSize(Word(FSize)) then
  1740.       EditorDialog(edOutOfMemory, nil) else
  1741.     begin
  1742.       BlockRead(F, Buffer^[BufSize - Word(FSize)], FSize);
  1743.       if IOResult <> 0 then EditorDialog(edReadError, @FileName) else
  1744.       begin
  1745.         LoadFile := True;
  1746.         Length := FSize;
  1747.       end;
  1748.     end;
  1749.     Close(F);
  1750.   end;
  1751.   SetBufLen(Length);
  1752. end;
  1753.  
  1754. function TFileEditor.Save: Boolean;
  1755. begin
  1756.   if FileName = '' then Save := SaveAs else Save := SaveFile;
  1757. end;
  1758.  
  1759. function TFileEditor.SaveAs: Boolean;
  1760. begin
  1761.   SaveAs := False;
  1762.   if EditorDialog(edSaveAs, @FileName) <> cmCancel then
  1763.   begin
  1764.     FileName := FExpand(FileName);
  1765.     Message(Owner, evBroadcast, cmUpdateTitle, nil);
  1766.     SaveAs := SaveFile;
  1767.     if IsClipboard then FileName := '';
  1768.   end;
  1769. end;
  1770.  
  1771. function TFileEditor.SaveFile: Boolean;
  1772. var
  1773.   F: File;
  1774.   BackupName: FNameStr;
  1775.   D: DirStr;
  1776.   N: NameStr;
  1777.   E: ExtStr;
  1778. begin
  1779.   SaveFile := False;
  1780.   if EditorFlags and efBackupFiles <> 0 then
  1781.   begin
  1782.     FSplit(FileName, D, N, E);
  1783.     BackupName := D + N + '.BAK';
  1784.     Assign(F, BackupName);
  1785.     Erase(F);
  1786.     Assign(F, FileName);
  1787.     Rename(F, BackupName);
  1788.     InOutRes := 0;
  1789.   end;
  1790.   Assign(F, FileName);
  1791.   Rewrite(F, 1);
  1792.   if IOResult <> 0 then EditorDialog(edCreateError, @FileName) else
  1793.   begin
  1794.     BlockWrite(F, Buffer^, CurPtr);
  1795.     BlockWrite(F, Buffer^[CurPtr + GapLen], BufLen - CurPtr);
  1796.     if IOResult <> 0 then EditorDialog(edWriteError, @FileName) else
  1797.     begin
  1798.       Modified := False;
  1799.       Update(ufUpdate);
  1800.       SaveFile := True;
  1801.     end;
  1802.     Close(F);
  1803.   end;
  1804. end;
  1805.  
  1806. function TFileEditor.SetBufSize(NewSize: Word): Boolean;
  1807. var
  1808.   N: Word;
  1809. begin
  1810.   SetBufSize := False;
  1811.   if NewSize > $F000 then NewSize := $FFF0 else
  1812.     NewSize := (NewSize + $0FFF) and $F000;
  1813.   if NewSize <> BufSize then
  1814.   begin
  1815.     if NewSize > BufSize then
  1816.       if not SetBufferSize(Buffer, NewSize) then Exit;
  1817.     N := BufLen - CurPtr + DelCount;
  1818.     Move(Buffer^[BufSize - N], Buffer^[NewSize - N], N);
  1819.     if NewSize < BufSize then SetBufferSize(Buffer, NewSize);
  1820.     BufSize := NewSize;
  1821.     GapLen := BufSize - BufLen;
  1822.   end;
  1823.   SetBufSize := True;
  1824. end;
  1825.  
  1826. procedure TFileEditor.Store(var S: TStream);
  1827. begin
  1828.   TEditor.Store(S);
  1829.   S.Write(FileName, Length(FileName) + 1);
  1830.   S.Write(SelStart, SizeOf(Word) * 3);
  1831. end;
  1832.  
  1833. procedure TFileEditor.UpdateCommands;
  1834. begin
  1835.   TEditor.UpdateCommands;
  1836.   SetCmdState(cmSave, True);
  1837.   SetCmdState(cmSaveAs, True);
  1838. end;
  1839.  
  1840. function TFileEditor.Valid(Command: Word): Boolean;
  1841. var
  1842.   D: Integer;
  1843. begin
  1844.   if Command = cmValid then Valid := IsValid else
  1845.   begin
  1846.     Valid := True;
  1847.     if Modified then
  1848.     begin
  1849.       if FileName = '' then D := edSaveUntitled else D := edSaveModify;
  1850.       case EditorDialog(D, @FileName) of
  1851.         cmYes: Valid := Save;
  1852.         cmNo: Modified := False;
  1853.         cmCancel: Valid := False;
  1854.       end;
  1855.     end;
  1856.   end;
  1857. end;
  1858.  
  1859. { TEditWindow }
  1860.  
  1861. constructor TEditWindow.Init(var Bounds: TRect;
  1862.   FileName: FNameStr; ANumber: Integer);
  1863. var
  1864.   HScrollBar, VScrollBar: PScrollBar;
  1865.   Indicator: PIndicator;
  1866.   R: TRect;
  1867. begin
  1868.   TWindow.Init(Bounds, '', ANumber);
  1869.   Options := Options or ofTileable;
  1870.   R.Assign(18, Size.Y - 1, Size.X - 2, Size.Y);
  1871.   HScrollBar := New(PScrollBar, Init(R));
  1872.   HScrollBar^.Hide;
  1873.   Insert(HScrollBar);
  1874.   R.Assign(Size.X - 1, 1, Size.X, Size.Y - 1);
  1875.   VScrollBar := New(PScrollBar, Init(R));
  1876.   VScrollBar^.Hide;
  1877.   Insert(VScrollBar);
  1878.   R.Assign(2, Size.Y - 1, 16, Size.Y);
  1879.   Indicator := New(PIndicator, Init(R));
  1880.   Indicator^.Hide;
  1881.   Insert(Indicator);
  1882.   GetExtent(R);
  1883.   R.Grow(-1, -1);
  1884.   Editor := New(PFileEditor, Init(
  1885.     R, HScrollBar, VScrollBar, Indicator, FileName));
  1886.   Insert(Editor);
  1887. end;
  1888.  
  1889. constructor TEditWindow.Load(var S: TStream);
  1890. begin
  1891.   TWindow.Load(S);
  1892.   GetSubViewPtr(S, Editor);
  1893. end;
  1894.  
  1895. procedure TEditWindow.Close;
  1896. begin
  1897.   if Editor^.IsClipboard then Hide else TWindow.Close;
  1898. end;
  1899.  
  1900. function TEditWindow.GetTitle(MaxSize: Integer): TTitleStr;
  1901. begin
  1902.   if Editor^.IsClipboard then GetTitle := 'Clipboard' else
  1903.     if Editor^.FileName = '' then GetTitle := 'Untitled' else
  1904.       GetTitle := Editor^.FileName;
  1905. end;
  1906.  
  1907. procedure TEditWindow.HandleEvent(var Event: TEvent);
  1908. begin
  1909.   TWindow.HandleEvent(Event);
  1910.   if (Event.What = evBroadcast) and (Event.Command = cmUpdateTitle) then
  1911.   begin
  1912.     Frame^.DrawView;
  1913.     ClearEvent(Event);
  1914.   end;
  1915. end;
  1916.  
  1917. procedure TEditWindow.Store(var S: TStream);
  1918. begin
  1919.   TWindow.Store(S);
  1920.   PutSubViewPtr(S, Editor);
  1921. end;
  1922.  
  1923. procedure RegisterEditors;
  1924. begin
  1925.   RegisterType(REditor);
  1926.   RegisterType(RMemo);
  1927.   RegisterType(RFileEditor);
  1928.   RegisterType(RIndicator);
  1929.   RegisterType(REditWindow);
  1930. end;
  1931.  
  1932. end.
  1933.