home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / extra18 / ide / txedit.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1992-01-30  |  56.7 KB  |  2,189 lines

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