UNIT PMEditor;

{************************************************************************
*                                                                       *
*                                                                       *
*          General Unit for Object-PM (C) 1993,94 R. Nrnberger         *
*                                                                       *
*                                                                       *
*************************************************************************}

INTERFACE

{$Z+}  {Inline strings}

USES PmTypes,PmObject,Dos,PmDialog,Crt;

CONST
     CM_FIND        =200;  {Find}
     CM_REPLACE     =201;  {Replace}
     CM_GOTO        =202;  {Goto}
     CM_SEARCHAGAIN =203;  {Search again}
     CM_CUT         =204;  {Cut text}
     CM_COPY        =205;  {Copy text}
     CM_PASTE       =206;  {Paste text}
     CM_UNDO        =207;  {Undo}
     CM_REDO        =208;  {Redo}
     CM_CONTEXTHELP =209;  {Context sensitive help}

     MaxEditors=32;          {Maximal editors to process}
     InitialBuf=32768;       {starting buffer size for editing}
     EditorMaxLines:WORD=28; {maximal editor lines for standard text}

VAR
   CharWidth:LONGWORD;
   CharHeight:LONGWORD;
   SelectDrawColor,SelectBackColor:LONGINT;
   ErrorDrawColor,ErrorBackColor:LONGINT;

TYPE
     PSliderData=^SliderData;
     SliderData=record
                      scrollbottom:LONGWORD; { Scroll lower border  }
                      scrolltop:LONGWORD;    { Scroll upper border  }
                      viewarea:LONGWORD;     { View area of window  }
                      intervall:WORD;        { Intervall of Slider  }
                      acvalue:LONGWORD;      { actual Slider value  }
                end;

     PTextBuf=^TTextBuf;
     TTextBuf=ARRAY[0..6553500] OF BYTE; {that should be enough ...}

     PEditor=^TEditor;  {Data structure for each editor}
     TEditor=RECORD
                   TextBuffer:PTextBuf; {Buffer to text}
                   ScreenBuffer:ARRAY[0..60] OF String[250];
                   TextLen:LONGWORD;    {Length of text +InitialBuf}
                   TextLow:LONGWORD;    {Actual low position in text}
                   TextHigh:LONGWORD;   {Actual high position in text}
                   HSlider,VSlider:SliderData;
                   CursorX,CursorY:LONGWORD; {Current cursor position}
                   InsertMode:BOOLEAN;
                   Title:String;
                   Untitled:BOOLEAN;
                   Modified:BOOLEAN;
                   TextLines:LONGWORD;
                   TextViewX,TextViewY:LONGWORD;
                   SelectLineStart,SelectColumnStart:WORD;
                   SelectLineEnd,SelectColumnEnd:WORD;
                   SelectAnchorLine,SelectAnchorColumn:WORD;
                   SelectLoAddr,SelectHiAddr:LONGWORD;
                   FrameWin:HWND;  {Frame window handle}
                   ChildWin:HWND;  {MDI Window handle}
                   ErrorMode:BOOLEAN;
                   ErrorStr:String;
                   ErrorLine:WORD;
                   ErrorCol:WORD;
                   LastSearch:BYTE;
                   LastSearchStr,LastReplStr:STRING;
                   LastSearchOpt:WORD;
             END;



TYPE TEditorApplication=OBJECT(TMDIApplication)
                   EditorCount:WORD;
                   UntitledCount:BYTE;
                   Editors:ARRAY[0..MaxEditors] OF PEditor;
                   StdExt:String;
                   SafetyBufSize:WORD;
                   NewEditorPtr:LONGWORD;
                   EditorCol,EditorBackCol:LONGINT;
                   CONSTRUCTOR Init;
                   DESTRUCTOR Done;
                   PROCEDURE SetEditorPtr(id,res:LONGWORD);VIRTUAL;
                   PROCEDURE HandleCommand(Win:HWND;Command:WORD):VIRTUAL;
                   FUNCTION MDIHandleEvent(Win:HWND;Msg:LONGWORD;para1,para2:POINTER;
                                           VAR Handled:BOOLEAN;
                                           Data:POINTER):LONGWORD:virtual;
                   FUNCTION HandleEvent(Win:HWND;Msg:LONGWORD;
                                        para1,para2:POINTER;
                                        VAR Handled:BOOLEAN):
                                        LONGWORD:VIRTUAL;
                   PROCEDURE MDIRedraw(rc:RECTL;_hps:HPS;Win:HWND;Data:POINTER):virtual;
                   PROCEDURE MDICreateNotify(MDIFrWin,MDIWin:HWND;Data:POINTER):virtual;
                   PROCEDURE MDINoMoreChilds:VIRTUAL;
                   PROCEDURE AppRunNotify(AppFrWin:HWND):VIRTUAL;
                   FUNCTION CreateMDIChild(resid:LONGWORD;Title:string;
                                           Extra:POINTER;fcfFlags:LONGWORD;
                                           Col,BCol:LONGINT):HWND:VIRTUAL;
                   PROCEDURE OpenNewFile;VIRTUAL;
                   PROCEDURE OpenFile(name:STRING);VIRTUAL;
                   PROCEDURE SaveFile;VIRTUAL;
                   PROCEDURE SaveFileAs;VIRTUAL;
                   PROCEDURE SaveAllFiles;VIRTUAL;
                   PROCEDURE SaveEditor(e:PEditor);VIRTUAL;
                   PROCEDURE InitEditor(e:Peditor);VIRTUAL;
                   PROCEDURE CheckHScrollBar(Win:HWND;para1,para2,Extra:PEditor);VIRTUAL;
                   PROCEDURE CheckVScrollBar(Win:HWND;para1,para2,Extra:PEditor);VIRTUAL;
                   PROCEDURE MDIHandleCharEvent(Win:HWND;ch:Char;Data:POINTER):VIRTUAL;
                   PROCEDURE MDIHandleScanEvent(Win:HWND;scan:Word;Data:POINTER):VIRTUAL;
                   PROCEDURE WMMDIClose(Win:HWND;Data:POINTER):VIRTUAL;
                   PROCEDURE SetCursor(Win:HWND;pp:PEditor);VIRTUAL;
                   PROCEDURE InvalidateEditorLine(Win:HWND;VAR s:string;
                                                  y:LONGWORD;Extra:PEditor);VIRTUAL;
                   FUNCTION CheckIfToScrollX(Win:HWND;Extra:PEditor;
                                             Update:BOOLEAN):BOOLEAN;VIRTUAL;
                   PROCEDURE DestroyEditor(e:PEditor);VIRTUAL;
                   PROCEDURE InvalidateEditorWindow(Win:HWND;Extra:PEditor);VIRTUAL;
                   FUNCTION GetUpperLine(VAR s:string;Extra:PEditor):BOOLEAN;VIRTUAL;
                   FUNCTION GetLowerLine(VAR s:string;Extra:PEditor):BOOLEAN;VIRTUAL;
                   FUNCTION AppendUpperLine(VAR s:string;Extra:PEditor):BOOLEAN;VIRTUAL;
                   FUNCTION AppendLowerLine(VAR s:string;Extra:PEditor):BOOLEAN;VIRTUAL;
                   PROCEDURE LineDown(Win:HWND;Extra:PEditor;
                                      CheckEmpty:BOOLEAN);VIRTUAL;
                   FUNCTION PageDown(Win:HWND;Extra:PEditor):BOOLEAN;VIRTUAL;
                   PROCEDURE LineUp(Win:HWND;Extra:PEditor);VIRTUAL;
                   PROCEDURE PageUp(Win:HWND;Extra:PEditor);VIRTUAL;
                   PROCEDURE GotoLine(Extra:PEditor;Line,Col:WORD);VIRTUAL;
                   PROCEDURE SearchEditor(VAR s:String;VAR e:PEditor);VIRTUAL;
                   PROCEDURE SetPosText(Win:HWND;Extra:PEditor);VIRTUAL;
                   FUNCTION ErrorLineHandled(Win:HWND;pp:PEditor;
                                             s:string):BOOLEAN;VIRTUAL;
                   PROCEDURE ClearErrorLine(Win:HWND;pp:PEditor);VIRTUAL;
                   PROCEDURE InsertText(Win:HWND;Extra:PEditor);VIRTUAL;
                   PROCEDURE PutText(Win:HWND;Extra:PEditor;Buf:PTextBuf;
                                     Len,CountLines:LONGWORD);VIRTUAL;
                   PROCEDURE ExtendEditor(Extra:PEditor);VIRTUAL;
                   PROCEDURE CopyEditor(e:PEditor;VAR Adresse,Len:LONGWORD);VIRTUAL;
                   PROCEDURE ContextHelp(Context:String);VIRTUAL;
                   PROCEDURE SetSliderValues(Win:HWND;Extra:PEditor);VIRTUAL;
                   FUNCTION CutSelectedText(Win:HWND;Extra:PEditor;
                                            VAR Len:LONGWORD):PTextBuf;VIRTUAL;
                   FUNCTION CopySelectedText(Win:HWND;Extra:PEditor;
                                             VAR Len:LONGWORD):PTextBuf;VIRTUAL;
                   FUNCTION FindText(s:string;Options:WORD):BOOLEAN;VIRTUAL;
                   FUNCTION ReplaceText(s,repl:string;Options:WORD):BOOLEAN;VIRTUAL;
                   PROCEDURE GetEditorOptions(VAR Insert,Indent,SynHigh,BackUps:
                                              BOOLEAN);VIRTUAL;
                   PROCEDURE DrawEditorStr(VAR pchString;
                                            lCount:LONGWORD;
                                            VAR pptlPoint:POINTL;
                                            _hps:HPS;DrawColor:LONGINT);VIRTUAL;
                   PROCEDURE DrawHighLightedStr(VAR pchString:STRING;
                                            lCount:LONGWORD;
                                            VAR pptlPoint:POINTL;
                                            _hps:HPS;DrawColor:LONGINT);VIRTUAL;
                   PROCEDURE EditorStatusMessage(msg:STRING);VIRTUAL;
                   PROCEDURE SetEditorTextHeight(h50:BOOLEAN);VIRTUAL;
                   PROCEDURE MDIWMEraseBackGround(Win:HWND;rc:RECTL;_hps:HPS):VIRTUAL;
              END;


IMPLEMENTATION

IMPORTS {Private}
      FUNCTION WinSetWindowText(psztext:PSZ;
                                _hwnd:HWND):LONGWORD:   PMWIN index 877;
      FUNCTION WinQueryWindow(cmd:LONGWORD;
                                  _hwnd:HWND):LONGWORD:    PMWIN index 834;
      FUNCTION WinWindowFromID(id:LONGWORD;
                                   hwndParent:HWND):HWND:  PMWIN index 899;
      FUNCTION WinSendMsg(MPARAM2,MPARAM1:POINTER;
                              msg:LONGWORD;
                              _hwnd:HWND):POINTER:         PMWIN index 920;
      FUNCTION WinQueryWindowRect(VAR prclDest:RECTL;
                                      _hwnd:HWND ):
                                      LONGWORD:            PMWIN index 840;
      PROCEDURE WinReleasePS(_hps:HPS):                    PMWIN index 848;
      FUNCTION  WinGetPS(Win:HWND):HPS:                    PMWIN index 757;
      PROCEDURE WinShowCursor(Visible:LONGWORD;
                              Win:HWND):                   PMWIN index 880;
      PROCEDURE GpiSetBackMix(Mix:LONGWORD;_hps:HPS):      PMGPI index 505;
      FUNCTION GpiSetColor(lColor:LONGWORD;
                             _hps:HPS):LONGINT:            PMGPI index 517;
      FUNCTION GpiSetBackColor(lColor:LONGINT;
                               _hps:HPS):LONGWORD:       PMGPI index 504;
      FUNCTION GpiCharStringAt(VAR pchString;
                               lCount:LONGWORD;
                               VAR pptlPoint:POINTL;
                               _hps:HPS):LONGWORD:       PMGPI index 359;
      FUNCTION WinLoadPointer(id:LONGWORD;
                              hmod:LONGWORD;
                              Desktop:HWND):LONGWORD:    PMWIN index 780;
      PROCEDURE WinDestroyPointer(hptr:LONGWORD):        PMWIN index 727;
      PROCEDURE WinSetPointer(hptr:LONGWORD;
                              Desktop:HWND):             PMWIN index 866;
      FUNCTION DosAllocSharedMem(Flag,cb:LONGWORD;
                                 Name:POINTER;
                                 VAR p:POINTER):LONGWORD:DOSCALLS index 300;
      FUNCTION WinOpenClipbrd(hab:LONGWORD):LONGWORD:    PMWin index 793;
      FUNCTION WinCloseClipbrd(hab:LONGWORD):LONGWORD:    PMWin index 707;
      FUNCTION WinEmptyClipbrd(hab:LONGWORD):LONGWORD:    PMWin index 733;
      FUNCTION WinSetClipbrdData(FmtInfo,fmt:LONGWORD;
                                 Data,hab:LONGWORD):LONGWORD:PMWin index 854;
      FUNCTION WinQueryClipbrdData(fmt,hab:LONGWORD):POINTER:PMWin index 806;
      FUNCTION WinMessageBox(flStyle:LONGWORD;
                             idWindow:LONGWORD;
                             pszCaption:PSZ;
                             pszText:PSZ;
                             hwndOwner:HWND;
                             hwndParent:HWND):LONGWORD:        PMWIN index 789;
      FUNCTION WinSetCapture(hwndDesktop,ahwnd:HWND):BOOL;
                    APIENTRY;             PMWIN index 852;
END;

CONST
     PAG_READ         =$00000001; {* read access *}
     PAG_WRITE        =$00000002; {* write access *}
     PAG_EXECUTE      =$00000004; {* execute access *}
     PAG_GUARD        =$00000008; {* guard protection *}
     PAG_DEFAULT      =$00000400; {* default (initial) access *}

     CFI_POINTER      =$0400;
     CF_TEXT          =1;

{* Commit *}

CONST
     PAG_COMMIT       =$00000010; {* commit storage *}
     PAG_DECOMMIT     =$00000020; {* decommit storage *}


{* Allocation attributes *}

CONST
     OBJ_TILE         =$00000040; {* tile object *}
     OBJ_PROTECTED    =$00000080; {* protect object
                                     NOTE: This flag is NOT available at
                                     the api level *}
     OBJ_GETTABLE     =$00000100; {* gettable by other processes      *}
     OBJ_GIVEABLE     =$00000200; {* giveable to other processes      *}


PROCEDURE TEditorApplication.MDIWMEraseBackGround(Win:HWND;rc:RECTL;_hps:HPS);
BEGIN
     Inherited.MDIWMEraseBackGround(Win,rc,_hps);
END;

FUNCTION TEditorApplication.CreateMDIChild(resid:LONGWORD;Title:string;
                                  Extra:POINTER;fcfFlags:LONGWORD;
                                  Col,BCol:LONGINT):HWND;
VAR res:HWND;
BEGIN
     res:=Inherited.CreateMDIChild(resid,Title,Extra,fcfFlags,Col,BCol);
     IF res<>0 THEN
     BEGIN
          SetMenuState(CM_FIND,TRUE);
          SetMenuState(CM_REPLACE,TRUE);
          SetMenuState(CM_GOTO,TRUE);
          SetMenuState(CM_SEARCHAGAIN,TRUE);
          SetMenuState(CM_CUT,TRUE);
          SetMenuState(CM_COPY,TRUE);
          SetMenuState(CM_PASTE,TRUE);
          SetMenuState(CM_UNDO,TRUE);
          SetMenuState(CM_REDO,TRUE);
     END;
     CreateMDIChild:=res;
END;

PROCEDURE TEditorApplication.MDINoMoreChilds;
BEGIN
     Inherited.MDINoMoreChilds;
     SetMenuState(CM_FIND,FALSE);
     SetMenuState(CM_REPLACE,FALSE);
     SetMenuState(CM_GOTO,FALSE);
     SetMenuState(CM_SEARCHAGAIN,FALSE);
     SetMenuState(CM_CUT,FALSE);
     SetMenuState(CM_COPY,FALSE);
     SetMenuState(CM_PASTE,FALSE);
     SetMenuState(CM_UNDO,FALSE);
     SetMenuState(CM_REDO,FALSE);
END;

PROCEDURE TEditorApplication.AppRunNotify(AppFrWin:HWND);
BEGIN
     Inherited.AppRunNotify(AppFrWin);
     SetMenuState(CM_FIND,FALSE);
     SetMenuState(CM_REPLACE,FALSE);
     SetMenuState(CM_GOTO,FALSE);
     SetMenuState(CM_SEARCHAGAIN,FALSE);
     SetMenuState(CM_CUT,FALSE);
     SetMenuState(CM_COPY,FALSE);
     SetMenuState(CM_PASTE,FALSE);
     SetMenuState(CM_UNDO,FALSE);
     SetMenuState(CM_REDO,FALSE);
END;




PROCEDURE TEditorApplication.GetEditorOptions(VAR Insert,Indent,SynHigh,
                                   BackUps:BOOLEAN);
BEGIN
     Indent:=FALSE; {Standard values}
     Insert:=TRUE;
     SynHigh:=FALSE;
     BackUps:=TRUE;
END;


PROCEDURE TEditorApplication.SetEditorTextHeight(h50:BOOLEAN);
VAR t,t1:BYTE;
    e:PEditor;
BEGIN
     IF h50 THEN {50 Zeilen}
     BEGIN
          IF CharHeight=8 THEN exit;
          CharHeight:=8;
          CharWidth:=9;
          EditorMaxLines:=60;
          IF EditorCount>0 THEN
          BEGIN
              FOR t:=0 TO EditorCount-1 DO
              BEGIN
                   e:=Editors[t];
                   FOR t1:=29 TO 60 DO GetUpperLine(e^.ScreenBuffer[t1],e);
                   e^.CursorY:=1;
                   SetSliderValues(e^.ChildWin,e);
              END;
          END;
          TileWindows;
     END
     ELSE {25 Zeilen}
     BEGIN
          IF CharHeight=16 THEN exit;
          CharHeight:=16;
          CharWidth:=8;
          EditorMaxLines:=28;
          IF EditorCount>0 THEN
          BEGIN
              FOR t:=0 TO EditorCount-1 DO
              BEGIN
                   e:=Editors[t];
                   FOR t1:=60 DOWNTO 29 DO AppendUpperLine(e^.ScreenBuffer[t1],e);
                   e^.CursorY:=1;
                   SetSliderValues(e^.ChildWin,e);
              END;
          END;
          TileWindows;
     END;
END;

PROCEDURE TEditorApplication.EditorStatusMessage(msg:STRING);
BEGIN
END;

PROCEDURE TEditorApplication.DrawHighLightedStr(VAR pchString:STRING;
                                                lCount:LONGWORD;
                                                VAR pptlPoint:POINTL;
                                                _hps:HPS;DrawColor:LONGINT);
BEGIN
     GpiCharStringAt(pchString[1],lCount,pptlPoint,_hps);
END;

PROCEDURE TEditorApplication.DrawEditorStr(VAR pchString;
                                                lCount:LONGWORD;
                                                VAR pptlPoint:POINTL;
                                                _hps:HPS;DrawColor:LONGINT);
VAR Insert,Indent,SynHigh,BackUps:BOOLEAN;
    s:STRING;
BEGIN
     IF lCount=0 THEN exit;
     GetEditorOptions(Insert,Indent,SynHigh,BackUps);
     IF SynHigh THEN
     BEGIN
          s[0]:=chr(lCount);
          move(pchString,s[1],lCount);
          s[lcount+1]:=#0;
          s[lcount+2]:=#0;
          DrawHighLightedStr(s,lCount,pptlPoint,_hps,DrawColor);
     END
     ELSE GpiCharStringAt(pchString,lCount,pptlPoint,_hps);
END;

FUNCTION TEditorApplication.FindText(s:string;Options:WORD):BOOLEAN;
VAR CaseSens:BOOLEAN;
    t,t1:BYTE;
    e:PEditor;
    res:BOOLEAN;
    OldLine:WORD;
    OldColumn:WORD;
    FoundPosX:WORD;
    s1,s2:STRING;
Label l,l1,l2;
BEGIN
     res:=FALSE;
     IF Options AND 1=1 THEN CaseSens:=TRUE
     ELSE
     BEGIN
          CaseSens:=FALSE;
          FOR t:=1 TO length(s) DO s[t]:=upcase(s[t]);
     END;
     MDIGetTopWindow(e);
     IF e=NIL THEN goto l;

     EditorStatusMessage('Find text:');
     e^.LastSearch:=1;
     e^.LastSearchStr:=s;
     e^.LastSearchOpt:=Options;
     OldLine:=e^.VSlider.acvalue+e^.CursorY;
     OldColumn:=e^.HSlider.acvalue+e^.CursorY;
     IF Options AND 2=0 THEN GotoLine(e,1,1);
     {First look in the ScreenBuffer}
     IF e^.CursorY>1 THEN FOR t:=0 TO e^.CursorY-2 DO
     BEGIN
          inc(e^.VSlider.acvalue);
          AppendLowerLine(e^.ScreenBuffer[t],e);
     END;
     FOR t:=e^.CursorY-1 TO EditorMaxLines DO
     BEGIN
          s1:=e^.ScreenBuffer[t];
          IF t=e^.CursorY-1 THEN IF e^.CursorX>1 THEN Delete(s1,1,e^.CursorX-1);
          IF not CaseSens THEN FOR t1:=1 TO length(s1) DO s1[t1]:=upcase(s1[t1]);
          IF pos(s,s1)<>0 THEN  {Item found}
          BEGIN
               FoundPosX:=pos(s,s1);
               IF t=e^.CursorY-1 THEN IF e^.CursorX>0 THEN
                 inc(FoundPosX,e^.CursorX-1);
               FOR t1:=EditorMaxLines DOWNTO t DO
                 AppendUpperLine(e^.ScreenBuffer[t1],e);
               FOR t1:=0 TO EditorMaxLines DO
                 GetUpperLine(e^.ScreenBuffer[t1],e);
               res:=TRUE;
               goto l;
          END;
          inc(e^.VSlider.acvalue);
          AppendLowerLine(e^.ScreenBuffer[t],e);
     END;
     {Now search in upper editor section}
l1:
     IF not GetUpperLine(s1,e) THEN
     BEGIN
          FOR t:=EditorMaxLines DOWNTO 0 DO
          BEGIN
               dec(e^.VSLider.acvalue);
               GetLowerLine(e^.ScreenBuffer[t],e);
          END;
          goto l;
     END;
     s2:=s1;
     IF not CaseSens THEN FOR t1:=1 TO length(s1) DO s1[t1]:=upcase(s1[t1]);
     IF pos(s,s1)<>0 THEN  {Item found}
     BEGIN
          FoundPosX:=pos(s,s1);
          e^.ScreenBuffer[0]:=s2;
          FOR t1:=1 TO EditorMaxLines DO GetUpperLine(e^.ScreenBuffer[t1],e);
          res:=TRUE;
          goto l;
     END;
     inc(e^.VSlider.acvalue);
     AppendLowerLine(s2,e);
     goto l1;
l:
     EditorStatusMessage('');
     IF res THEN {found}
     BEGIN
          e^.CursorY:=2;
          e^.CursorX:=FoundPosX+length(s);
          e^.HSlider.acvalue:=0;
          e^.SelectAnchorLine:=e^.VSlider.acvalue;
          e^.SelectAnchorColumn:=FoundPosX;

          e^.SelectLineStart:=e^.SelectAnchorLine;
          e^.SelectLineEnd:=e^.SelectLineStart;
          e^.SelectColumnStart:=e^.SelectAnchorColumn;
          e^.SelectColumnEnd:=e^.SelectColumnStart+length(s)-1;
          e^.SelectLoAddr:=0;
          e^.SelectHiAddr:=0;

          GotoLine(e,e^.SelectLineStart+1,e^.CursorX);
     END
     ELSE IF e<>NIL THEN GotoLine(e,OldLine,OldColumn);
l2:
     EditorStatusMessage('');
     FindText:=res;
END;

FUNCTION TEditorApplication.ReplaceText(s,repl:string;Options:WORD):BOOLEAN;
Label l,l1;
VAR res:BOOLEAN;
    s1,msg:String;
    result:LONGWORD;
    e:PEditor;
BEGIN
     res:=TRUE;
     MDIGetTopWindow(e);
     IF e=NIL THEN goto l1;
l:
     res:=FALSE;
     IF FindText(s,Options) THEN
     BEGIN
          e^.LastSearch:=2;
          e^.LastSearchStr:=s;
          e^.LastReplStr:=Repl;
          e^.LastSearchOpt:=Options;
          s1:='Replace text';
          msg:='Replace this occurrence ?';
          result:=WinMessageBox(MB_YESNOCANCEL or MB_MOVEABLE or MB_QUERY
                                or MB_ICONQUESTION,0,s1,
                                msg,AppWinFrameHandle,HWND_Desktop);
          CASE result OF
             MBID_YES:
             BEGIN
                  IF e^.CursorX>length(s) THEN
                  BEGIN
                      s1:=e^.ScreenBuffer[e^.CursorY-1];
                      delete(s1,e^.CursorX-length(s),length(s));
                      insert(Repl,s1,e^.CursorX-length(s));
                      e^.ScreenBuffer[e^.CursorY-1]:=s1;
                      e^.SelectColumnEnd:=e^.SelectColumnStart+length(repl)-1;
                      e^.CursorX:=(e^.CursorX-length(s))+length(Repl);
                      e^.Modified:=TRUE;
                  END;
             END;
             MBID_CANCEL:
             BEGIN
                  res:=TRUE;
                  goto l1;
             END;
          END; {case}
          IF Options AND 4=4 THEN
          BEGIN
               Options:=Options OR 2; {From cursor}
               goto l;
          END
          ELSE res:=TRUE;
     END
     ELSE  {Text not found}
     BEGIN
          e^.LastSearch:=2;
          e^.LastSearchStr:=s;
          e^.LastReplStr:=Repl;
          e^.LastSearchOpt:=Options;
     END;
l1:
     ReplaceText:=res;
END;

PROCEDURE TEditorApplication.CopyEditor(e:PEditor;VAR Adresse,Len:LONGWORD);
VAR
   l,lLow,lHigh,l1:LONGWORD;
   t:BYTE;
   s:String;
   p,source:^Byte;
BEGIN
     lLow:=e^.TextLow-LONGWORD(e^.TextBuffer);
     l:=0;
     FOR t:=0 TO EditorMaxLines DO
     BEGIN
          s:=e^.ScreenBuffer[t];
          WHILE s[length(s)]=#32 do dec(s[0]);
          l:=l+length(s)+2;
     END;
     l1:=LONGWORD(e^.TextBuffer)+e^.textlen;  {Maximal adress}
     lHigh:=l1-e^.TextHigh;
     IF lHigh>0 THEN dec(lHigh); {!!!}
     Len:=LLow+LHigh+l; {Gesamtlnge}
     Getmem(p,Len);
     Adresse:=LONGWORD(p);

     IF lLow>0 THEN
     BEGIN
          source:=POINTER(e^.TextBuffer);
          Move(source^,p^,lLow);
          inc(p,LLow);
     END;
     FOR t:=0 TO EditorMaxLines DO
     BEGIN
          s:=e^.ScreenBuffer[t];
          WHILE s[length(s)]=#32 do dec(s[0]);
          s:=s+#13+#10;
          move(s[1],p^,length(s));
          inc(p,length(s));
     END;
     source:=POINTER(e^.TextHigh+1);
     Move(Source^,p^,LHigh);
END;

PROCEDURE TEditorApplication.SaveEditor(e:PEditor);
VAR f:file;
    d:dirstr;
    n:namestr;
    ex:extstr;
    s,s1:String;
    Buf:LONGWORD;
    Len:LONGWORD;
    t,t1:BYTE;
    sp:PString;
    Insert,Indent,SynHigh,Backups:BOOLEAN;
    w:word;
    Adresse,Max:LONGWORD;
LABEL l,ex_this;
BEGIN
     IF e=NIL THEN exit;
     IF e^.Untitled THEN
     BEGIN
          GetDir(0,s);
          IF s[length(s)]='\' THEN dec(s[0]);
          s:=s+'\'+e^.Title;
          e^.Title:=s;
          e^.Untitled:=FALSE;
          sp:=s;
          WinSetWindowText(sp,e^.FrameWin);
     END;
     EditorStatusMessage('Saving:'+e^.Title);
     GetEditorOptions(Insert,Indent,SynHigh,BackUps);
     IF Backups THEN
     BEGIN
          s:=e^.Title;
          assign(f,s);
          fsplit(s,d,n,ex);
          IF d[length(d)]='\' THEN dec(d[0]);
          s:=d+'\'+n+'.BAK';
          Erase(s);  {Delete old .BAK file}
          Rename(f,s);
     END;
     s:=e^.Title;
     Assign(f,s);
     Rewrite(f,1);
     IF ioresult<>0 THEN
     BEGIN
          ErrorBox(MB_ICONHAND,'Could not create file (Disk full ?)');
          EditorStatusMessage('');
          exit;
     END;
     Buf:=LONGWORD(e^.TextBuffer);
     Len:=e^.TextLow-Buf;
     IF Len>0 THEN
     BEGIN
          BlockWrite(f,e^.TextBuffer^[0],Len);
          IF ioresult<>0 THEN
          BEGIN
              ErrorBox(MB_ICONHAND,'Could not write file (Disk full ?)');
              Close(f);
              EditorStatusMessage('');
              exit;
          END;
     END;

     FOR t:=0 TO EditorMaxLines DO
     BEGIN
          s:=e^.ScreenBuffer[t];
          while s[length(s)]=#32 do dec(s[0]);
          IF s='' THEN
          BEGIN
               Adresse:=e^.TextHigh;
               Max:=LONGWORD(e^.TextBuffer)+e^.TextLen;
               IF Adresse>=Max THEN  {No more lines in upper section}
               BEGIN
                    IF t=EditorMaxLines THEN goto ex_this;
                    {Check if there are more not empty lines}
                    FOR t1:=t+1 TO EditorMaxLines DO
                    BEGIN
                         s1:=e^.ScreenBuffer[t1];
                         while s1[length(s1)]=#32 do dec(s1[0]);
                         IF s1<>'' THEN goto l;  {still a line}
                    END;
                    {There are no more lines --> exit}
                    goto ex_this;
               END;
          END;
l:
          s:=s+#13+#10;
          BlockWrite(f,s[1],length(s));
          IF ioresult<>0 THEN
          BEGIN
              ErrorBox(MB_ICONHAND,'Could not write file (Disk full ?)');
              Close(f);
              EditorStatusMessage('');
              exit;
          END;
     END;

     Len:=Buf+e^.Textlen;  {Maximal adress}
     Len:=Len-e^.TextHigh;
     IF Len>0 THEN
     BEGIN
          BlockWrite(f,e^.TextBuffer^[e^.TextHigh-Buf],len);
          IF ioresult<>0 THEN
          BEGIN
             ErrorBox(MB_ICONHAND,'Could not write file (Disk full ?)');
             Close(f);
             EditorStatusMessage('');
             exit;
          END;
     END;
ex_this:
     Close(f);
     IF ioresult<>0 THEN
     BEGIN
          ErrorBox(MB_ICONHAND,'Could not write file (Disk full ?)');
          EditorStatusMessage('');
          exit;
     END;
     e^.Modified:=FALSE;
     EditorStatusMessage('');
END;

PROCEDURE TEditorApplication.WMMDIClose(Win:HWND;Data:POINTER);
VAR
   e:PEditor;
   name:Namestr;
   dir:dirstr;
   ext:extstr;
BEGIN
     e:=Data;
     IF e^.Modified THEN
     BEGIN
       FSplit(e^.Title,dir,name,ext);
       IF ConfirmBox(MB_ICONQUESTION,name+ext+' has been modified.'+#13+
                     'Save ??') THEN SaveFile;
     END;
     Inherited.WMMDIClose(Win,Data);
END;

PROCEDURE TEditorApplication.SaveFile;  {Save upper editor file}
VAR e:PEditor;
    s:string;
    sp:PString;
    f:file;
LABEL l;
BEGIN
     IF EditorCount=0 THEN exit;
     MDIGetTopWindow(e);
     IF e=NIL THEN exit;
     IF e^.Untitled THEN
     BEGIN
l:
          IF FileSaveDialog(AppWinHandle,s) THEN
          BEGIN
               IF pos('.',s)=0 THEN s:=s+StdExt;
               assign(f,s);
               FileMode:=$40;  {fmInput}
               reset(f,1);
               FileMode:=$42;  {fmInOut}
               IF ioresult=0 THEN  {file exists}
               BEGIN
                    Close(f);
                    IF not ConfirmBox(MB_ICONQUESTION,'File exists. Overwrite ??')
                      THEN goto l;
               END;
               e^.Title:=s;
               e^.Untitled:=FALSE;
               sp:=s;
               WinSetWindowText(sp,e^.FrameWin);
          END
          ELSE exit; {Canceled}
     END;
     SaveEditor(e);
     SetPosText(e^.FrameWin,e);
END;

PROCEDURE TEditorApplication.SaveFileAs;  {Save upper editor file}
VAR e:PEditor;
    s:string;
    sp:PString;
    f:file;
LABEL l;
BEGIN
     IF EditorCount=0 THEN exit;
     MDIGetTopWindow(e);
     IF e=NIL THEN exit;
l:
     IF FileSaveDialog(AppWinHandle,s) THEN
     BEGIN
          IF pos('.',s)=0 THEN s:=s+StdExt;
          assign(f,s);
          FileMode:=$40;  {fmInput}
          reset(f,1);
          FileMode:=$42;  {fmInOut}
          IF ioresult=0 THEN  {file exists}
          BEGIN
               Close(f);
               IF not ConfirmBox(MB_ICONQUESTION,'File exists. Overwrite ??')
                 THEN goto l;
          END;
          e^.Title:=s;
          e^.Untitled:=FALSE;
          sp:=s;
          WinSetWindowText(sp,e^.FrameWin);
     END
     ELSE exit; {Canceled}
     SaveEditor(e);
     SetPosText(e^.FrameWin,e);
END;

PROCEDURE TEditorApplication.SaveAllFiles;
VAR t:BYTE;
    e:PEditor;
    s:STRING;
    sp:PString;
    F:FILE;
LABEL l,l1;
BEGIN
     IF EditorCount=0 THEN exit;
     FOR t:=0 TO EditorCount-1 DO
     BEGIN
          e:=Editors[t];
          IF e^.Modified THEN
          BEGIN
               IF e^.Untitled THEN
               BEGIN
l:
                   IF FileSaveDialog(AppWinHandle,s) THEN
                   BEGIN
                       IF pos('.',s)=0 THEN s:=s+StdExt;
                       assign(f,s);
                       FileMode:=$40;  {fmInput}
                       reset(f,1);
                       FileMode:=$42;  {fmInOut}
                       IF ioresult=0 THEN  {file exists}
                       BEGIN
                            Close(f);
                            IF not ConfirmBox(MB_ICONQUESTION,'File exists. Overwrite ??')
                             THEN goto l;
                       END;
                   END
                   ELSE goto l1;  {Canceled}
                   e^.Title:=s;
                   e^.Untitled:=FALSE;
                   sp:=s;
                   WinSetWindowText(sp,e^.FrameWin);
               END; {not untitled}
               SaveEditor(e);
               SetPosText(e^.FrameWin,e);
l1:
          END; {not modified}
     END; {for}
END;


PROCEDURE TEditorApplication.SearchEditor(VAR s:String;VAR e:PEditor);
VAR t:BYTE;
BEGIN
     e:=NIL;
     IF EditorCount=0 THEN exit;
     FOR t:=0 TO EditorCount-1 DO
       IF Editors[t]^.Title=s THEN e:=Editors[t];
END;


FUNCTION CalcMaxSliderPositions(VAR scrolldata:SliderData):WORD;
VAR as:WORD;
BEGIN
     as:=(scrolldata.scrolltop-scrolldata.scrollbottom)-scrolldata.viewarea;
     inc(as,2);
     scrolldata.intervall:=as;
     CalcMaxSliderPositions:=as;
END;

FUNCTION CalcSliderfromValue(wert:LONGWORD;scrolldata:SliderData):WORD;
VAR og:LONGWORD;
    rec:RECTL;
BEGIN
     og:=(scrolldata.scrolltop-scrolldata.viewarea)+1;
     IF wert<scrolldata.scrollbottom THEN wert:=scrolldata.scrollbottom;
     IF wert>og THEN wert:=og;
     CalcSliderfromValue:=(wert-scrolldata.scrollbottom)+1;
END;

FUNCTION CalcValuefromSlider(Wert:WORD;scrolldata:SliderData):
         LONGWORD;
VAR og:WORD;
BEGIN
     og:=(scrolldata.scrolltop-scrolldata.scrollbottom)-scrolldata.viewarea;
     inc(og,2);
     IF Wert<1 THEN Wert:=1;
     IF Wert>og THEN Wert:=og;
     CalcValuefromSlider:=(Wert+scrolldata.scrollbottom)-1;
END;


FUNCTION TEditorApplication.GetUpperLine(VAR s:string;Extra:PEditor):BOOLEAN;
VAR Adresse:LONGWORD;
    Buffer:POINTER;
    Max:LONGWORD;
    result:BOOLEAN;
Label l;
BEGIN
     Adresse:=Extra^.TextHigh+1;
     Max:=LONGWORD(Extra^.TextBuffer)+Extra^.TextLen;
     IF Adresse>=Max THEN
     BEGIN
          Extra^.TextHigh:=Max;
          s:='';
          result:=FALSE;
          goto l;
     END;
     Buffer:=Extra^.TextBuffer;
     ASM
        MOV CL,0
        MOV EDI,$s
        INC EDI
        MOV ESI,$Adresse
!rep_lab:
        CMP ESI,$Max
        JAE !crlf
        MOV AL,[ESI+0]
        INC ESI
        CMP AL,13
        JE !cr
        CMP AL,10
        JE !crlf

        INC CL
        MOV [EDI+0],AL
        INC EDI
        CMP CL,251
        JAE !crlf
        JMP !rep_lab
!cr:
        MOV AL,[ESI+0]
        CMP AL,10
        JNE !crlf
        INC ESI
!crlf:
        CLD
        MOV AL,0
        STOSB
        MOV EDI,$s
        MOV [EDI+0],CL   ;Set text len
        DEC ESI
        CMP ESI,$Max
        JBE !ok1
        MOV ESI,$Max
!ok1:
        MOV $Adresse,ESI
     END;
     Extra^.TextHigh:=Adresse;
     result:=TRUE;
l:
     IF length(s)>250 THEN s[0]:=#250;
     ASM
        MOV EDI,$s
        MOV AL,[EDI+0]
        CMP AL,250
        JE !eee
        ;Length to short --> fill up with space
        MOVZX EAX,AL
        MOVB [EDI+0],250
        ADD EDI,EAX
        INC EDI
        MOV ECX,250
        SUB ECX,EAX
        MOV AL,32
        CLD
        REP
        STOSB
        MOV AL,0
        STOSB
!eee:
     END;
     GetUpperLine:=result;
END;

FUNCTION TEditorApplication.GetLowerLine(VAR s:string;Extra:PEditor):BOOLEAN;
VAR Adresse:LONGWORD;
    Buffer:POINTER;
    Result:BOOLEAN;
Label l;
BEGIN
     Adresse:=Extra^.TextLow;
     Buffer:=Extra^.TextBuffer;
     IF Adresse<=LONGWORD(Buffer) THEN
     BEGIN
          Extra^.TextLow:=LONGWORD(Buffer);
          Result:=FALSE;
          s:='';
          goto l;
     END;
     ASM
         MOV CL,0
         MOV EDI,$s
         INC EDI
         MOV ESI,$Adresse
         SUB ESI,3
!rep_lab1:
         CMP ESI,$Buffer
         JB !cr1
         CMP CL,251
         JAE !cr1
         MOV AL,[ESI+0]
         CMP AL,10
         JE !cr1
         CMP AL,13
         JE !cr1
         DEC ESI
         INC CL
         JMP !rep_lab1
!cr1:
         INC ESI
         MOVZX ECX,CL
         PUSH ECX
         PUSH ESI
         CMP ECX,0
         JE !no_copy
         CLD
         REP
         MOVSB
!no_copy:
         CLD
         MOV AL,0
         STOSB
         POP ESI
         POP ECX
         MOV EDI,$s
         MOV [EDI+0],CL
         CMP ESI,$Buffer
         JAE !ok
         MOV ESI,$Buffer
!ok:
         MOV $Adresse,ESI
     END;
     Extra^.TextLow:=Adresse;
     Result:=TRUE;
l:
     IF length(s)>250 THEN s[0]:=#250;
     ASM
        MOV EDI,$s
        MOV AL,[EDI+0]
        CMP AL,250
        JE !eee1
        ;Length to short --> fill up with space
        MOVZX EAX,AL
        MOVB [EDI+0],250
        ADD EDI,EAX
        INC EDI
        MOV ECX,250
        SUB ECX,EAX
        MOV AL,32
        CLD
        REP
        STOSB
        MOV AL,0
        STOSB
!eee1:
     END;
     GetLowerLine:=Result;
END;

PROCEDURE TEditorApplication.ExtendEditor(Extra:PEditor);  {grow up Editor and set
                                                            limits}
BEGIN
     Messagebox('Must extend editor !!');
END;

FUNCTION TEditorApplication.AppendUpperLine(VAR s:string;Extra:PEditor):BOOLEAN;
VAR Adresse,Max:LONGWORD;
    Buffer:POINTER;
Label l;
BEGIN
     WHILE s[length(s)]=#32 DO dec(s[0]);
     Adresse:=Extra^.TextHigh;
     Max:=LONGWORD(Extra^.TextBuffer)+Extra^.TextLen;
     IF s='' THEN IF Adresse>=Max THEN goto l;
     IF Extra^.TextHigh-Extra^.TextLow<SafetyBufSize THEN ExtendEditor(Extra);
     Buffer:=Extra^.TextBuffer;
     ASM
         MOV EDI,$Adresse
         MOV AL,10
         STD
         STOSB
         MOV AL,13
         STOSB
         MOV ESI,$s
         MOV CL,[ESI+0]
         MOVZX ECX,CL
         ADD ESI,ECX
         CMP ECX,0
         JE !no_copy1
         STD
         REP
         MOVSB
!no_copy1:
         MOV $Adresse,EDI
     END;
     Extra^.TextHigh:=Adresse;
l:
     AppendUpperLine:=TRUE;
END;

FUNCTION TEditorApplication.AppendLowerLine(VAR s:string;Extra:PEditor):BOOLEAN;
VAR Adresse:LONGWORD;
    Buffer:POINTER;
BEGIN
     WHILE s[length(s)]=#32 DO dec(s[0]);
     IF Extra^.TextHigh-Extra^.TextLow<SafetyBufSize THEN ExtendEditor(Extra);
     Adresse:=Extra^.TextLow;
     Buffer:=Extra^.TextBuffer;
     ASM
        MOV EDI,$Adresse
        MOV ESI,$s
        MOV CL,[ESI+0]
        MOVZX ECX,CL
        INC ESI
        CMP ECX,0
        JE !no_copy2
        CLD
        REP
        MOVSB
!no_copy2:
        MOV AL,13
        STOSB
        MOV AL,10
        STOSB
        MOV $Adresse,EDI
     END;
     Extra^.TextLow:=Adresse;
     AppendLowerLine:=TRUE;
END;

PROCEDURE TEditorApplication.SetEditorPtr(id,res:LONGWORD);
VAR Ptr:LONGWORD;
BEGIN
     Ptr:=WinLoadPointer(id,res,HWND_DESKTOP);
     IF Ptr<>0 THEN NewEditorPtr:=Ptr;
END;

CONSTRUCTOR TEditorApplication.Init;
VAR t:WORD;
BEGIN
     inherited.Init;
     EditorCol:=CLR_YELLOW;
     EditorBackCol:=CLR_DARKBLUE;
     NewEditorPtr:=0;
     SelectBackColor:=15; {CLR_PALEGRAY}
     SelectDrawColor:=1; {CLR_BLUE}
     ErrorDrawColor:=15; {CLR_PALEGRAY}
     ErrorBackColor:=2;  {CLR_RED}
     StdExt:='.TXT';
     EditorCount:=0;
     UntitledCount:=0;
     CharHeight:=16;
     CharWidth:=8;
     SafetyBufSize:=768; {Minimum of 768 Bytes between Texthigh and TextLow}
     FOR t:=0 TO MaxEditors DO Editors[t]:=NIL;
END;

DESTRUCTOR TEditorApplication.Done;
BEGIN
END;

PROCEDURE TEditorApplication.DestroyEditor(e:PEditor);
VAR t,t1:WORD;
label l;
BEGIN
     freemem(e^.TextBuffer,e^.TextLen);
     FOR t:=0 TO MaxEditors DO IF Editors[t]=e THEN goto l;
     Errorbox(MB_ICONHAND,'FATAL:Could not free editor data !');
     exit;
l:
     FOR t1:=t TO MaxEditors DO Editors[t1]:=Editors[t1+1];
     dec(EditorCount);
     dispose(e);
END;

PROCEDURE TEditorApplication.InitEditor(e:Peditor);
VAR Adresse:LONGWORD;
    Max:LONGWORD;
    Insert,Indent,BackUps,SynHigh:BOOLEAN;
BEGIN
     Editors[EditorCount]:=e;
     inc(EditorCount);
     e^.CursorX:=1;
     e^.CursorY:=1;
     e^.HSlider.AcValue:=0;
     e^.VSlider.AcValue:=0;
     GetEditorOptions(Insert,Indent,SynHigh,BackUps);
     IF Insert THEN e^.InsertMode:=FALSE
     ELSE e^.InsertMode:=TRUE;
     e^.LastSearch:=0;
     e^.Untitled:=FALSE;
     e^.Modified:=FALSE;
     e^.SelectLineStart:=65535;
     e^.SelectLineEnd:=65535;
     e^.SelectColumnStart:=65535;
     e^.SelectColumnEnd:=65535;
     e^.SelectLoAddr:=0;
     e^.SelectHiAddr:=0;
     e^.ErrorMode:=FALSE;
     {Adresse:=e^.TextHigh;
     Max:=EditorMaxLines*2;
     ASM
        MOV ECX,$Max
        MOV EDI,$Adresse
        STD
!cploop:
        MOV AL,10
        STOSB
        MOV AL,13
        STOSB
        LOOP !cploop
        CLD
        MOV $Adresse,EDI
     END;
     e^.TextHigh:=Adresse;}
END;

PROCEDURE TEditorApplication.OpenNewFile;
VAR e:PEditor;
    t:WORD;
    s:string;
    fr:LONGWORD;
BEGIN
      IF EditorCount>=MaxEditors THEN
      BEGIN
           ErrorBox(MB_ICONHAND,'Too much files opened');
           exit;
      END;
      new(e);
      getmem(e^.TextBuffer,InitialBuf); {reserve 32K initially}
      e^.Textlen:=InitialBuf;
      e^.TextLow:=LONGWORD(e^.TextBuffer);
      e^.TextHigh:=e^.TextLow+e^.textLen;  {Clear Editor}
      e^.TextLines:=EditorMaxLines;
      InitEditor(e);
      FOR t:=0 TO EditorMaxLines DO
      BEGIN
           e^.ScreenBuffer[t]:='';
           s:=e^.ScreenBuffer[t];
           ASM
              CLD
              LEA EDI,$s
              MOV AL,250
              STOSB
              MOV ECX,250
              MOV AL,32
              REP
              STOSB
           END;
           e^.ScreenBuffer[t]:=s;
      END;
      s:=Tostr(UntitledCount);
      inc(UntitledCount);
      IF length(s)=1 THEN s:='0'+s;
      e^.Title:='NONAME'+s+StdExt;
      e^.untitled:=TRUE;
      fr:=FCF_VERTSCROLL or FCF_HORZSCROLL;
      IF ChildIconRes<>0 THEN fr:=fr or FCF_ICON;
      e^.FrameWin:=CreateMDIChild(ChildIconRes,e^.Title,e,fr,EditorCol,
                                  EditorBackCol);
END;

PROCEDURE TEditorApplication.OpenFile(name:string);
VAR e:PEditor;
    t:WORD;
    f:file;
    size:LONGWORD;
    Adresse:LONGWORD;
    Zeilen:LONGWORD;
    BufAdresse:LONGWORD;
    BufLen:LONGWORD;
    fr:LONGWORD;
LABEL l;
BEGIN
      SearchEditor(name,e);
      IF e<>NIL THEN {file already loaded}
      BEGIN
           MDIBringToTop(e^.FrameWin);
           exit;
      END;

      IF EditorCount>=MaxEditors THEN
      BEGIN
           ErrorBox(MB_ICONHAND,'Too much files opened');
           exit;
      END;

      EditorStatusMessage('Loading:'+name);
      assign(f,name);
      FileMode:=$40;  {fmInput}
      reset(f,1);
      FileMode:=$42;  {fmInOut}
      if ioresult<>0 THEN
      BEGIN
           ErrorBox(MB_ICONHAND,'Error reading:'+name);
           EditorStatusMessage('');
           exit;
      END;
      size:=FileSize(f);
      new(e);
      getmem(e^.TextBuffer,InitialBuf+size); {reserve 32K initially}
      e^.Textlen:=InitialBuf+size;
      e^.TextLow:=LONGWORD(e^.TextBuffer);
      e^.TextHigh:=e^.TextLow+e^.TextLen;  {Clear Editor}
      e^.TextLines:=EditorMaxLines;
      InitEditor(e);
      dec(e^.TextHigh,size+3);  {2 Byte for CR+LF}
      Adresse:=e^.TextHigh+1;
      ASM
         LEA EAX,$f
         PUSH EAX
         PUSHL $Adresse
         PUSHL $Size
         CALLN32 System._BlockRead
      END;
      IF ioresult<>0 THEN
      BEGIN
l:
           close(f);
           freemem(e^.TextBuffer,InitialBuf+size);
           EditorStatusMessage('');
           ErrorBox(MB_ICONHAND,'Error reading:'+name);
           exit;
      END
      ELSE IF Size<>BlockReadResult THEN goto l;
      close(f);
      ASM
         MOV EDI,$Adresse
         ADD EDI,$Size
         MOVB [EDI+0],13
         MOVB [EDI+1],10
      END;
      {Count Zeilnums}
      Zeilen:=0;
      BufAdresse:=e^.TextHigh+1;
      BufLen:=e^.TextLow+InitialBuf+size;
      ASM
         MOV ESI,$BufAdresse
         CLD
!cloop:
         CMP ESI,$BufLen
         JAE !zexit
         LODSB
         CMP AL,13
         JE !zfoundcr
         CMP AL,10
         JE !zFound
         JMP !cloop
!zfoundcr:
         LODSB
         CMP AL,10
         JE !zfound
         DEC ESI
!zfound:
         INCD $Zeilen
         JMP !cloop
!zexit:
      END;
      e^.TextLines:=Zeilen;
      FOR t:=0 TO EditorMaxLines DO GetUpperLine(e^.ScreenBuffer[t],e);
      e^.Title:=name;
      fr:=FCF_VERTSCROLL or FCF_HORZSCROLL;
      IF ChildIconRes<>0 THEN fr:=fr OR FCF_ICON;
      e^.FrameWin:=CreateMDIChild(ChildIconRes,e^.Title,e,fr,EditorCol,
                                  EditorBackCol);
      EditorStatusMessage('');
END;

FUNCTION TEditorApplication.CopySelectedText(Win:HWND;Extra:PEditor;
                         VAR Len:LONGWORD):PTextBuf;
VAR
   CountSelectedLines:WORD;
   SelEnd,SelStart:WORD;
   t:LONGWORD;
   dest,sourc:^Byte;
   p:PTextBuf;
   s:string;
   SelLowLen,SelHighLen:LONGWORD;
label l,l1,l2;
BEGIN
     p:=NIL;
     Len:=0;
     IF Extra^.SelectLineStart=65535 THEN goto l;
     IF Extra^.SelectLineEnd=65535 THEN goto l;
     CountSelectedLines:=(Extra^.SelectLineEnd-Extra^.SelectLineStart)+1;

     IF Extra^.SelectLineEnd<Extra^.VSlider.acvalue THEN
     BEGIN  {whole text is in the lower editor section}
          sourc:=POINTER(Extra^.SelectLoAddr);
          len:=Extra^.SelectHiAddr-Extra^.SelectLoAddr;
          getmem(p,len);
          move(sourc^,p^,len);
          goto l;
     END;

     IF Extra^.SelectLineStart+1>Extra^.VSlider.acvalue+EditorMaxLines THEN
     BEGIN  {whole text is in the upper editor section}
          sourc:=POINTER(Extra^.SelectLoAddr);
          len:=Extra^.SelectHiAddr-Extra^.SelectLoAddr;
          getmem(p,len);
          move(sourc^,p^,len);
          goto l;
     END;

     IF Extra^.SelectLineStart<Extra^.VSlider.acvalue THEN
     BEGIN {Text starts in the lower Editor section}
          Len:=Extra^.TextLow-Extra^.SelectLoAddr; {Part in the lower section}
          IF Extra^.SelectLineEnd+1>Extra^.VSlider.acvalue+EditorMaxLines THEN
          BEGIN {Upperline is in upper section}
               SelLowLen:=Len;
               FOR t:=0 TO EditorMaxLines DO
               BEGIN
                    s:=Extra^.ScreenBuffer[t];
                    WHILE s[length(s)]=#32 DO dec(s[0]);
                    inc(len,length(s)+2);
               END;
               SelHighLen:=Extra^.SelectHiAddr-Extra^.TextHigh;
               inc(Len,SelHighLen);
               getmem(p,len);
               sourc:=POINTER(Extra^.SelectLoAddr);
               move(sourc^,p^,SelLowLen);
               FOR t:=0 TO EditorMaxLines DO
               BEGIN
                    s:=Extra^.ScreenBuffer[t];
                    WHILE s[length(s)]=#32 DO dec(s[0]);
                    s:=s+#13+#10;
                    move(s[1],p^[SelLowLen],length(s));
                    inc(SelLowLen,Length(s));
               END;
               Sourc:=POINTER(Extra^.TextHigh);
               move(sourc^,p^[SelLowLen],SelHighlen);
          END
          ELSE  {Upperline is within the line buffer}
          BEGIN
               SelLowLen:=Len;
               SelEnd:=Extra^.SelectLineEnd-Extra^.VSlider.acvalue;
               FOR t:=0 TO SelEnd DO
               BEGIN
                    s:=Extra^.ScreenBuffer[t];
                    WHILE s[length(s)]=#32 DO dec(s[0]);
                    inc(len,length(s)+2);
               END;
               sourc:=POINTER(Extra^.SelectLoAddr);
               getmem(p,len);
               move(sourc^,p^,SelLowLen);
               FOR t:=0 TO SelEnd DO
               BEGIN
                    s:=Extra^.ScreenBuffer[t];
                    WHILE s[length(s)]=#32 DO dec(s[0]);
                    s:=s+#13+#10;
                    move(s[1],p^[SelLowLen],length(s));
                    inc(SelLowLen,Length(s));
               END;
          END;
          goto l;
     END;

     {Text starts in the LineBuffer}
     SelStart:=Extra^.SelectLineStart-Extra^.VSlider.acvalue;
     Len:=0;
     SelLowLen:=0;
     SelEnd:=Extra^.SelectLineEnd-Extra^.VSlider.acvalue;
     IF Extra^.SelectLineEnd+1>Extra^.VSlider.acvalue+EditorMaxLines THEN
     BEGIN {Upperline is in upper section}
          FOR t:=SelStart TO EditorMaxLines DO
          BEGIN
               s:=Extra^.ScreenBuffer[t];
               WHILE s[length(s)]=#32 DO dec(s[0]);
               inc(len,length(s)+2);
          END;
          SelHighLen:=Extra^.SelectHiAddr-Extra^.TextHigh;
          inc(Len,SelHighLen);
          getmem(p,len);
          FOR t:=SelStart TO EditorMaxLines DO
          BEGIN
                s:=Extra^.ScreenBuffer[t];
                WHILE s[length(s)]=#32 DO dec(s[0]);
                s:=s+#13+#10;
                move(s[1],p^[SelLowLen],length(s));
                inc(SelLowLen,Length(s));
          END;
          Sourc:=POINTER(Extra^.TextHigh);
          move(sourc^,p^[SelLowLen],SelHighlen);
     END
     ELSE  {Upperline is within the line buffer}
     BEGIN
          FOR t:=SelStart TO SelEnd DO
          BEGIN
               s:=Extra^.ScreenBuffer[t];
               WHILE s[length(s)]=#32 DO dec(s[0]);
               inc(len,length(s)+2);
          END;
          getmem(p,len);
          FOR t:=SelStart TO SelEnd DO
          BEGIN
                s:=Extra^.ScreenBuffer[t];
                WHILE s[length(s)]=#32 DO dec(s[0]);
                s:=s+#13+#10;
                move(s[1],p^[SelLowLen],length(s));
                inc(SelLowLen,Length(s));
          END;
     END;
l:
     {Set SelectColumnEnd}
     IF p<>NIL THEN IF Len>2 THEN
      IF Extra^.SelectLineEnd-Extra^.SelectLineStart>0 THEN
     BEGIN
          FOR t:=Len-3 downto Len-256 DO
          BEGIN
               IF p^[t]=10 THEN
               BEGIN
l2:
                    inc(t,Extra^.SelectColumnEnd+1);
                    IF t>Len-2 THEN t:=Len
                    ELSE
                    BEGIN
                         Len:=t+1;
                         p^[t]:=13;
                         p^[t+1]:=10;
                    END;
                    goto l1;
               END
               ELSE IF p^[t]=13 THEN goto l2;
          END;
l1:
     END;
     CopySelectedText:=p;
END;

PROCEDURE TEditorApplication.SetSliderValues(Win:HWND;Extra:PEditor);
VAR
   ww,ww1:WORD;
   p:POINTER;
   ScrollWin,FrameWin:HWND;
   r:LONGWORD;
   rc:RECTL;
BEGIN
     WinQueryWindowrect(rc,Win);
     FrameWin:=WinQueryWindow(QW_PARENT,Win);

     {init horicontal ScrollWindow}
     ScrollWin:=WinWindowFromID(FID_HORZSCROLL,FrameWin);
     r:=(rc.XRight-rc.XLeft) div CharWidth;
     Extra^.TextViewX:=r;
     Extra^.HSlider.scrollbottom:=0;
     Extra^.HSlider.scrolltop:=239;
     Extra^.HSlider.viewarea:=r;

     {define horizontal Scroll intervall}
     ww1:=1;
     ww:=CalcMaxSliderPositions(Extra^.HSlider);
     p:=MPFROM2SHORT(ww1,ww);
     WinSendMsg(p,LongToPointer(1),SBM_SETSCROLLBAR,ScrollWin);

     {Set horizontal slider size}
     ww1:=Extra^.HSlider.viewarea;
     ww:=Extra^.HSlider.scrolltop-Extra^.HSlider.scrollbottom+1;
     p:=MPFROM2SHORT(ww1,ww);
     WinSendmsg(NIL,p,SBM_SETTHUMBSIZE,ScrollWin);

     {init vertical ScrollWindow}
     ScrollWin:=WinWindowFromID(FID_VERTSCROLL,FrameWin);
     r:=(rc.yTop-rc.yBottom) div CharHeight;
     Extra^.TextViewY:=r;
     Extra^.VSlider.scrollbottom:=0;
     Extra^.VSlider.scrolltop:=Extra^.TextLines;
     Extra^.VSlider.viewarea:=r;

     {define vertical Scroll intervall}
     ww1:=1;
     ww:=CalcMaxSliderPositions(Extra^.VSlider);
     p:=MPFROM2SHORT(ww1,ww);
     WinSendMsg(p,LongToPointer(1),SBM_SETSCROLLBAR,ScrollWin);

     {Set vertical slider size}
     ww1:=Extra^.VSlider.viewarea;
     ww:=Extra^.VSlider.scrolltop-Extra^.VSlider.scrollbottom+1;
     p:=MPFROM2SHORT(ww1,ww);
     WinSendmsg(NIL,p,SBM_SETTHUMBSIZE,ScrollWin);
END;

FUNCTION TEditorApplication.CutSelectedText(Win:HWND;Extra:PEditor;
                         VAR Len:LONGWORD):PTextBuf;
VAR
   pres:PTextBuf;
   CountLines,t:WORD;
   sstart:WORD;
   CopyLen:LONGWORD;
   SourcBuf,DestBuf:PTextBuf;
Label l;
BEGIN
     {Get the text}
     pres:=CopySelectedText(Win,Extra,Len);
     {Now cut this text}
     CountLines:=Extra^.SelectLineEnd-Extra^.SelectLineStart;
     inc(CountLines);
     IF Extra^.SelectLineEnd<Extra^.VSlider.acvalue THEN
     BEGIN  {whole text is in the lower editor section}
          CopyLen:=Extra^.TextLow-Extra^.SelectHiAddr;
          IF CopyLen>0 THEN
          BEGIN
               SourcBuf:=POINTER(Extra^.SelectHiAddr);
               DestBuf:=POINTER(Extra^.SelectLoAddr);
               Move(SourcBuf^,DestBuf^,CopyLen);
          END;
          Extra^.TextLow:=Extra^.SelectLoAddr+CopyLen;
          goto l;
     END;

     IF Extra^.SelectLineStart+1>Extra^.VSlider.acvalue+EditorMaxLines THEN
     BEGIN  {whole text is in the upper editor section}
          CopyLen:=Extra^.SelectLoAddr-Extra^.TextHigh;
          IF CopyLen>0 THEN
          BEGIN
               SourcBuf:=POINTER(Extra^.TextHigh);
               DestBuf:=POINTER(Extra^.SelectHiAddr-CopyLen);
               Move(SourcBuf^,DestBuf^,CopyLen);
          END;
          Extra^.TextHigh:=Extra^.SelectHiAddr-CopyLen;
          goto l;
     END;

     IF Extra^.SelectLineStart<Extra^.VSlider.acvalue THEN
     BEGIN {Text starts in the lower Editor section}
          Extra^.TextLow:=Extra^.SelectLoAddr;
          IF Extra^.SelectLineEnd+1>Extra^.VSlider.acvalue+EditorMaxLines THEN
          BEGIN {Upperline is in upper section}
               Extra^.TextHigh:=Extra^.SelectHiAddr;
               FOR t:=0 TO EditorMaxLines DO
                 GetUpperLine(Extra^.ScreenBuffer[t],Extra);
          END
          ELSE  {Upperline is within the line buffer}
          BEGIN
               countlines:=Extra^.SelectLineEnd-Extra^.VSlider.acvalue;
               inc(countlines);
               FOR t:=0 TO EditorMaxLines-countlines DO
                 Extra^.ScreenBuffer[t]:=Extra^.ScreenBuffer[t+countlines];
               FOR t:=(EditorMaxLines-countlines)+1 TO EditorMaxLines DO
                 GetUpperLine(Extra^.ScreenBuffer[t],Extra);
          END;
          goto l;
     END;

     {Text starts in the LineBuffer}
     IF Extra^.SelectLineEnd+1>Extra^.VSlider.acvalue+EditorMaxLines THEN
     BEGIN {Upperline is in upper section}
          Extra^.TextHigh:=Extra^.SelectHiAddr;
          sstart:=Extra^.SelectLineStart-Extra^.VSlider.acvalue;
          FOR t:=sstart TO EditorMaxLines DO
            GetUpperLine(Extra^.ScreenBuffer[t],Extra);
     END
     ELSE  {Upperline is within the line buffer}
     BEGIN
          sstart:=Extra^.SelectLineStart-Extra^.VSlider.acvalue;
          FOR t:=sstart TO EditorMaxLines-countlines DO
           Extra^.ScreenBuffer[t]:=Extra^.ScreenBuffer[t+countlines];
          FOR t:=(EditorMaxLines-countlines)+1 TO EditorMaxLines DO
           GetUpperLine(Extra^.ScreenBuffer[t],Extra);
     END;
l:
     dec(Extra^.TextLines,Extra^.SelectLineEnd-Extra^.SelectLineStart);
     CutSelectedText:=pres;
END;

PROCEDURE TextToClipBoard(p:PTextBuf;Len:LONGWORD;e:PEditor);
VAR
   PBuf:PTextBuf;
   EndText:LONGWORD;
   SelLen:LONGWORD;
BEGIN
     IF e^.SelectColumnStart>0 THEN
     BEGIN
         inc(p,e^.SelectColumnStart-1);
         dec(Len,e^.SelectColumnStart-1);
     END;
     SelLen:=e^.SelectColumnEnd;
     IF e^.SelectLineEnd-e^.SelectLineStart=0 THEN
      IF e^.SelectColumnStart>0 THEN dec(SelLen,e^.SelectColumnStart-1);
     {Search for end of text}
     ASM
        MOV ESI,$p
        ADD ESI,$Len
        DEC ESI     ;Overread LF
        DEC ESI     ;and CR
!tnfound:
        CMP ESI,$p
        JBE !tfound
        CMPB [ESI-1],10
        JE !tfound
        CMPB [ESI-1],13
        JE !tfound
        DEC ESI
        JMP !tnfound
!tfound:
        ADD ESI,$SelLen
        MOV EDI,$p
        ADD EDI,$Len
        CMP ESI,EDI
        JBE !tok
        MOV ESI,EDI
!tok:
        SUB ESI,$p
        MOV $Len,ESI
     END;
     IF WinOpenClipBrd(AppHandle)<>0 THEN
     BEGIN
          DosAllocSharedMem(PAG_WRITE OR PAG_COMMIT OR OBJ_GIVEABLE,
                            Len,NIL,PBuf);
          IF PBuf=NIL THEN
          BEGIN
               ErrorBox(MB_ICONHAND,'Could not copy/cut text');
               exit;
          END;
          Move(p^,PBuf^,Len);
          WinEmptyClipBrd(AppHandle);
          WinSetClipBrdData(CFI_POINTER,CF_TEXT,LONGWORD(PBuf),AppHandle);
          WinCloseClipBrd(AppHandle);
     END
     ELSE ErrorBox(MB_ICONHAND,'Could not access clipboard');
END;

FUNCTION GetClipBoardText(VAR Len:LONGWORD;VAR CountLines:WORD):PTextBuf;
VAR p,p1:PTextBuf;
Label l,l1;
BEGIN
     p1:=NIL;
     CountLines:=0;
     IF WinOpenClipBrd(AppHandle)<>0 THEN
     BEGIN
          p:=WinQueryClipBrdData(CF_TEXT,AppHandle);
          IF p=NIL THEN goto l1;
          FOR Len:=0 TO 10000000 DO
          BEGIN
               IF p^[Len]=10 THEN inc(CountLines);
               IF p^[Len]=0 THEN goto l;
          END;
          ErrorBox(MB_ICONHAND,'Cannot paste clipboard');
          goto l1;
l:
          Getmem(p1,Len);
          Move(p^,p1^,Len);
          WinCloseClipBrd(AppHandle);
     END;
l1:
     GetClipBoardText:=p1;
END;

PROCEDURE TEditorApplication.ContextHelp(Context:String);
BEGIN
END;

PROCEDURE TEditorApplication.HandleCommand(Win:HWND;Command:WORD);
VAR
   e:PEditor;
   p:PTextBuf;
   Len:LONGWORD;
   CountLines:WORD;
   s:string;
   bs,be,b:BYTE;
Label l,l1,l2,l3;
BEGIN
     Inherited.HandleCommand(Win,Command);
     IF EditorCount=0 THEN exit;
     MDIGetTopWindow(e);
     IF e=NIL THEN exit;
     CASE Command OF
         CM_SEARCHAGAIN:
         BEGIN
              CASE e^.LastSearch OF
                1:
                BEGIN
                   IF not FindText(e^.LastSearchStr,e^.LastSearchOpt OR 2) THEN
                    Errorbox(MB_WARNING,'Item not found !');
                END;
                2:
                BEGIN
                   IF not ReplaceText(e^.LastSearchStr,e^.LastReplStr,
                                      e^.LastSearchOpt OR 2) THEN
                    Errorbox(MB_WARNING,'Item not found !');
                END;
              END; {case}
         END;
         CM_CONTEXTHELP:
         BEGIN
              s:=e^.ScreenBuffer[e^.CursorY-1];
              bs:=e^.CursorX;
              be:=bs;
              b:=ord(s[bs]);
              IF b<65 THEN exit;
              IF b>122 THEN exit;
              IF b>90 THEN IF b<97 THEN exit;
              IF bs>1 THEN
              BEGIN
l1:
                   b:=ord(s[bs-1]);
                   IF b<65 THEN goto l;
                   IF b>122 THEN goto l;
                   IF b>90 THEN IF b<97 THEN goto l;
                   dec(bs);
                   IF bs>1 THEN goto l1;
              END;
l:
              IF be<length(s) THEN
              BEGIN
l3:
                   b:=ord(s[be+1]);
                   IF b<65 THEN goto l2;
                   IF b>122 THEN goto l2;
                   IF b>90 THEN IF b<97 THEN goto l2;
                   inc(be);
                   IF be<length(s) THEN goto l3;
              END;
l2:
              SubStr(s,bs,(be-bs)+1);
              FOR b:=1 TO length(s) DO s[b]:=Upcase(s[b]);
              ContextHelp(s);
         END;
         CM_COPY:
         BEGIN
              EditorStatusMessage('Copy selected text');
              p:=CopySelectedText(e^.ChildWin,e,Len);
              IF p=NIL THEN
              BEGIN
                   EditorStatusMessage('');
                   exit;
              END;
              TextToClipBoard(p,Len,e);
              FreeMem(p,Len);
              InvalidateEditorWindow(e^.ChildWin,e);
              EditorStatusMessage('');
         END;
         CM_CUT:
         BEGIN
              IF e^.SelectLineStart=65535 THEN exit;
              IF e^.SelectLineEnd=65535 THEN exit;
              GotoLine(e,e^.SelectLineStart+1,e^.SelectColumnStart);
              EditorStatusMessage('Cut selected text');
              p:=CutSelectedText(e^.ChildWin,e,Len);
              IF p=NIL THEN
              BEGIN
                   EditorStatusMessage('');
                   exit;
              END;
              SetSliderValues(e^.ChildWin,e);
              TextToClipBoard(p,Len,e);
              FreeMem(p,Len);
              e^.Modified:=TRUE;
              e^.SelectColumnStart:=65535;
              e^.SelectLineStart:=65535;
              e^.SelectColumnEnd:=65535;
              e^.SelectLineEnd:=65535;
              e^.SelectLoAddr:=0;
              e^.SelectHiAddr:=0;
              InvalidateEditorWindow(e^.ChildWin,e);
              EditorStatusMessage('');
         END;
         CM_PASTE:
         BEGIN
              EditorStatusMessage('Paste text in clipboard');
              p:=GetClipBoardText(Len,CountLines);
              inc(CountLines);
              IF p=NIL THEN
              BEGIN
                   EditorStatusMessage('');
                   exit;
              END;
              e^.SelectColumnStart:=1;
              e^.SelectColumnEnd:=250;
              e^.SelectLineStart:=1;
              e^.SelectLineEnd:=1+CountLines;
              PutText(e^.ChildWin,e,p,Len,CountLines);
              InvalidateEditorWindow(e^.ChildWin,e);
              EditorStatusMessage('');
         END;
     END; {case}
END;

FUNCTION TEditorApplication.HandleEvent(Win:HWND;Msg:LONGWORD;
                                        para1,para2:POINTER;
                                        VAR Handled:BOOLEAN):LONGWORD;
VAR r:LONGWORD;
BEGIN
     r:=Inherited.HandleEvent(Win,Msg,para1,para2,Handled);
     HandleEvent:=r;
END;

PROCEDURE TEditorApplication.SetPosText(Win:HWND;Extra:PEditor);
VAR
   s,s1:String;
   di:dirstr;
   na:namestr;
   ex:extstr;
   sp:PString;
   FrameWin:HWND;
BEGIN
     s1:=Extra^.Title;
     IF length(s1)>60 THEN
     BEGIN
           fsplit(s1,di,na,ex);
           s1:='...\'+na+ex;
     END;
     s:=s1+'   '+tostr(Extra^.CursorY+Extra^.VSlider.acvalue)+':'+
       tostr(Extra^.CursorX+Extra^.HSlider.acvalue);
     IF Extra^.Modified THEN s:=s+' *';
     sp:=s;
     FrameWin:=WinQueryWindow(QW_PARENT,Win);
     WinSetWindowText(sp,FrameWin);
END;

PROCEDURE TEditorApplication.ClearErrorLine(Win:HWND;pp:PEditor);
BEGIN
END;


PROCEDURE TEditorApplication.SetCursor(Win:HWND;pp:PEditor);
VAR cux,cuy:LONGWORD;
    rec:RECTL;
    ScrollWin,FrameWin:HWND;
    w:WORD;
    p:POINTER;
    ww,ww1:WORD;
    t:LONGWORD;
BEGIN
     WinShowCursor(0,Win);
     WinQueryWindowRect(rec,Win);
     cux:=2+(pp^.CursorX-1)*CharWidth;
     cuy:=rec.yTop-(pp^.CursorY)*CharHeight;
     dec(cuy,2);
     ASM
        ;Set window cursor
        PUSHL 0      ;whole window
        PUSHL 8004h  ;CURSOR_SETPOS
        PUSHL 2      ;Cusizey
        PUSHL _CharWidth
        PUSHL $cuy
        PUSHL $cux
        PUSHL $Win
        MOV AL,7
        CALLDLL PMWIN,715  ;WinCreateCursor
        ADD ESP,28
    END;
    WinShowCursor(1,Win);
    SetPosText(Win,pp);
    FrameWin:=WinQueryWindow(QW_PARENT,Win);
    ScrollWin:=WinWindowFromID(FID_HORZSCROLL,FrameWin);
    w:=CalcSliderfromValue(pp^.HSlider.acvalue,pp^.HSlider);
    p:=MPFROMSHORT(w);
    WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
    ScrollWin:=WinWindowFromID(FID_VERTSCROLL,FrameWin);
    w:=CalcSliderfromValue(pp^.VSlider.acvalue,pp^.VSlider);
    p:=MPFROMSHORT(w);
    WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
END;

FUNCTION TEditorApplication.ErrorLineHandled(Win:HWND;pp:PEditor;
                            s:string):BOOLEAN;
BEGIN
     ErrorLineHandled:=FALSE;
END;

PROCEDURE TEditorApplication.MDIRedraw(rc:RECTL;_hps:HPS;Win:HWND;Data:POINTER);
VAR facename,s:string;
    rec:RECTL;
    pp:PEditor;
    Lines:LONGWORD;
    t:LongWord;
    pt:POINTL;
    ScrollX:LONGWORD;
    SelectLoLine,SelectHiLine:WORD;
    SelectLoColumn,SelectHiColumn:WORD;
    AcLine,AcColumn,help,TextViewX,Mul,Mul1:WORD;
    TextDrawColor,TextBackColor:LONGINT;
    incd:BOOLEAN;
Label l,l1,weiter;
BEGIN
    Inherited.MDIRedraw(rc,_hps,Win,Data);
    WinShowCursor(0,Win);
    facename:='System VIO';
    IF CharHeight=8 THEN CreateLogFont(_hps,facename,CharHeight,CharWidth-1,
                         FATTR_SEL_BOLD) {small font}
    ELSE CreateLogFont(_hps,facename,CharHeight,CharWidth,0); {default font}
    pp:=Data;
    GpiSetBackMix(2,_hps); {BM_OverPaint}
    WinQueryWindowRect(rec,Win);
    Lines:=(rec.ytop-rec.ybottom) div CharHeight; {Lines to draw}
    pt.x:=2;
    pt.y:=rec.yTop-CharHeight;
    ScrollX:=pp^.HSlider.acvalue;

    SelectLoLine:=pp^.SelectLineStart;
    SelectHiLine:=pp^.SelectLineEnd;
    SelectLoColumn:=pp^.SelectColumnStart;
    SelectHiColumn:=pp^.SelectColumnEnd;
    AcLine:=pp^.VSlider.acvalue;
    AcColumn:=ScrollX+1;
    TextViewX:=pp^.TextViewX+1;

    IF SelectLoColumn<65535 THEN
    BEGIN
        IF SelectLoColumn>AcColumn-1 THEN
        BEGIN
             Dec(SelectLoColumn,AcColumn-1);
             Mul:=CharWidth*(SelectLoColumn-1);
        END
        ELSE SelectLoColumn:=0;
    END
    ELSE SelectLoColumn:=0;

    IF SelectHiColumn<65535 THEN
    BEGIN
        IF SelectHiColumn>AcColumn-1 THEN
        BEGIN
             Dec(SelectHiColumn,AcColumn-1);
             Mul1:=CharWidth*SelectHiColumn;
        END
        ELSE SelectHiColumn:=0;
    END
    ELSE SelectHiColumn:=0;

    TextDrawColor:=GetMDIColor(Win);
    TextBackColor:=GetMDIBackColor(Win);
    GpiSetColor(TextDrawColor,_hps);
    GpiSetBackColor(TextBackColor,_hps);
    FOR t:=0 TO Lines-1 DO
    BEGIN
        help:=t+AcLine;
        IF pp^.ErrorMode THEN
        BEGIN
             IF Help+1=pp^.ErrorLine THEN
             BEGIN
                  GpiSetColor(ErrorDrawColor,_hps);
                  GpiSetBackColor(ErrorBackColor,_hps);
                  GpiCharStringAt(pp^.ScreenBuffer[t][ScrollX+1],pp^.TextViewX+1,pt,_hps);
                  GpiSetColor(TextDrawColor,_hps);
                  GpiSetBackColor(TextBackColor,_hps);
                  goto weiter;
             END;
        END;
        IF ((help>=SelectLoLine)AND(Help<=SelectHiLine)) THEN
        BEGIN
             CASE Help OF
                SelectLoLine:
                BEGIN
                     IF SelectLoColumn>0 THEN
                     BEGIN
                          dec(SelectLoColumn);
                          IF SelectLoColumn>0 THEN
                          BEGIN
                              DrawEditorStr(pp^.ScreenBuffer[t][AcColumn],
                                            SelectLoColumn+2,pt,_hps,
                                            TextDrawColor);
                              inc(pt.x,Mul);
                              incd:=TRUE;
                          END
                          ELSE incd:=FALSE;
                          GpiSetColor(SelectDrawColor,_hps);
                          GpiSetBackColor(SelectBackColor,_hps);
                          IF Help=SelectHiLine THEN
                          BEGIN
                               GpiCharStringAt(pp^.ScreenBuffer[t][AcColumn+
                                          SelectLoColumn],SelectHiColumn-
                                          SelectLoColumn,pt,_hps);
                               GpiSetColor(TextDrawColor,_hps);
                               GpiSetBackColor(TextBackColor,_hps);
                               inc(pt.x,mul1-mul);
                               IF SelectHiColumn<TextViewX THEN
                               DrawEditorStr(pp^.ScreenBuffer[t][AcColumn+
                                             SelectLoColumn+
                                            (SelectHiColumn-SelectLoColumn)],
                                             TextViewX-SelectHiColumn,pt,_hps,
                                             TextDrawColor)
                               ELSE DrawEditorStr(pp^.ScreenBuffer[t][AcColumn+
                                                  SelectLoColumn+
                                                  (SelectHiColumn-SelectLoColumn)],
                                                  TextViewX,pt,_hps,
                                                  TextDrawColor)
                               dec(pt.x,mul1-mul);
                          END
                          ELSE GpiCharStringAt(pp^.ScreenBuffer[t][AcColumn+
                                          SelectLoColumn],TextViewX-SelectLoColumn,
                                          pt,_hps);
                          IF incd THEN dec(pt.x,Mul);
                     END
                     ELSE
                     BEGIN
l:
                          GpiSetColor(SelectDrawColor,_hps);
                          GpiSetBackColor(SelectBackColor,_hps);
l1:
                          GpiCharStringAt(pp^.ScreenBuffer[t][AcColumn],
                                          pp^.TextViewX+1,pt,_hps);
                     END;
                     GpiSetColor(TextDrawColor,_hps);
                     GpiSetBackColor(TextBackColor,_hps);
                END;
                SelectHiLine:
                BEGIN
                     IF SelectHiColumn>0 THEN
                     BEGIN
                          GpiSetColor(SelectDrawColor,_hps);
                          GpiSetBackColor(SelectBackColor,_hps);
                          GpiCharStringAt(pp^.ScreenBuffer[t][AcColumn],
                                          SelectHiColumn+2,pt,_hps);
                          inc(pt.x,Mul1);
                          GpiSetColor(TextDrawColor,_hps);
                          GpiSetBackColor(TextBackColor,_hps);
                          IF SelectHiColumn<TextViewX THEN
                          DrawEditorStr(pp^.ScreenBuffer[t][AcColumn+
                                        SelectHiColumn],TextViewX-SelectHiColumn,
                                        pt,_hps,TextDrawColor)
                          ELSE DrawEditorStr(pp^.ScreenBuffer[t][AcColumn+
                                             SelectHiColumn],TextViewX,
                                             pt,_hps,TextDrawColor)
                          dec(pt.x,Mul1);
                     END
                     ELSE goto l1;
                END;
                ELSE
                BEGIN
                     GpiSetColor(SelectDrawColor,_hps);
                     GpiSetBackColor(SelectBackColor,_hps);
                     GpiCharStringAt(pp^.ScreenBuffer[t][AcColumn],
                                     pp^.TextViewX+1,pt,_hps);
                     GpiSetColor(TextDrawColor,_hps);
                     GpiSetBackColor(TextBackColor,_hps);
                END;
             END; {case}
        END
        ELSE DrawEditorStr(pp^.ScreenBuffer[t][ScrollX+1],pp^.TextViewX+11,
                           pt,_hps,TextDrawColor);
weiter:
        dec(pt.y,CharHeight);
    END;

    IF pp^.ErrorMode THEN
    BEGIN
         inc(pt.y,CharHeight);
         s:='Error in '+tostr(pp^.ErrorLine)+','+tostr(pp^.ErrorCol)+':';
         s:=s+pp^.ErrorStr;
         IF not ErrorLineHandled(Win,pp,s) THEN
         BEGIN
              WHILE length(s)<pp^.TextViewX+2 DO s:=s+' ';
              GpiSetColor(ErrorDrawColor,_hps);
              GpiSetBackColor(ErrorBackColor,_hps);
              GpiCharStringAt(s[1],pp^.TextViewX+1,pt,_hps);
         END;
    END;
    WinShowCursor(1,Win);
    SetCursor(Win,pp);
END;

PROCEDURE TEditorApplication.CheckHScrollBar(Win:HWND;para1,para2,Extra:PEditor);
VAr w:Word;
    p,p1:POINTER;
    l:LONGWORD;
    ScrollWin,FrameWin:HWND;
    SliderID:LONGWORD;
    HSliderX:SliderData;
LABEL lab;
BEGIN
     HSliderX:=Extra^.HSlider;

     l:=PointerToLong(para2);
     SliderID:=PointerToLong(para1);
     SliderID:=lo(SliderID);
     w:=hi(l);
     FrameWin:=WinQueryWindow(QW_PARENT,Win);
     ScrollWin:=WinWindowFromID(SliderID,FrameWin);
     CASE w OF
         SB_LINELEFT:
         BEGIN
              IF HSliderX.acvalue>0 THEN dec(HSliderX.acvalue);
              {ELSE HSliderX.acvalue:=HSliderX.scrollbottom;}
              {IF HSliderX.acValue+Extra^.CursorX<HSliderX.ScrollBottom THEN
              BEGIN
                  Beep(1200,200);
                  HSliderX.acvalue:=0;
              END;}
              w:=HSliderX.acvalue; {CalcSliderfromValue(HSliderX.acvalue,HSliderX);}
              p:=MPFROMSHORT(w);
              WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
              InvalidateEditorWindow(Win,Extra);
         END;
         SB_LINERIGHT:
         BEGIN
              IF HSliderX.acvalue+1<HSliderX.scrolltop THEN inc(HSliderX.acvalue);
              {ELSE HSliderX.acvalue:=HSliderX.scrolltop;}
              IF HSliderX.acValue+Extra^.CursorX>HSliderX.ScrollTop THEN
              BEGIN
                  Beep(1200,200);
                  HSliderX.acvalue:=HSliderX.ScrollTop-Extra^.CursorX;
              END;
              w:=HSliderX.acvalue; {CalcSliderfromValue(HSliderX.acvalue,HSliderX);}
              p:=MPFROMSHORT(w);
              WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
              InvalidateEditorWindow(Win,Extra);
         END;
         SB_PAGELEFT:
         BEGIN
              IF HSliderX.acvalue<HSliderX.Viewarea THEN HSliderX.acvalue:=0
              ELSE
              BEGIN
                  IF HSliderX.acvalue-HSliderX.viewarea>HSliderX.scrollbottom THEN
                    dec(HSliderX.acvalue,HSliderX.viewarea)
                  ELSE HSliderX.acvalue:=HSliderX.scrollbottom;
              END;
              goto lab;
         END;
         SB_PAGERIGHT:
         BEGIN
              IF HSliderX.acvalue+HSliderX.viewarea<HSliderX.scrolltop THEN
                 inc(HSliderX.acvalue,HSliderX.viewarea)
              ELSE HSliderX.acvalue:=HSliderX.scrolltop;
lab:
              IF HSliderX.acValue+Extra^.CursorX>HSliderX.ScrollTop THEN
              BEGIN
                  Beep(1200,200);
                  HSliderX.acvalue:=HSliderX.ScrollTop-Extra^.CursorX;
              END;
              w:=HSliderX.acvalue; {CalcSliderfromValue(HSliderX.acvalue,HSliderX);}
              p:=MPFROMSHORT(w);
              WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
         END;
         SB_SLIDERPOSITION:
         BEGIN
              w:=lo(l);
              HSliderX.acvalue:=CalcValuefromSlider(w,HSliderX);
              IF HSliderX.acValue+Extra^.CursorX>HSliderX.ScrollTop THEN
              BEGIN
                   Beep(1200,200);
                   HSliderX.acvalue:=HSliderX.ScrollTop-Extra^.CursorX;
                   w:=CalcSliderfromValue(HSliderX.acvalue,HSliderX);
                   p:=MPFROMSHORT(w);
                   WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
              END;
         END;
         ELSE exit;
     END; {Case}
     Extra^.HSlider:=HSliderX;
END;


FUNCTION TEditorApplication.CheckIfToScrollX(Win:HWND;Extra:PEditor;
                                             Update:BOOLEAN):BOOLEAN;
VAR ScrollX:LONGWORD;
    rec:RECTL;
BEGIN
     IF Extra^.CursorX>Extra^.TextViewX THEN
     BEGIN
          ScrollX:=Extra^.CursorX-Extra^.TextViewX;
          dec(Extra^.Cursorx,ScrollX);
          inc(Extra^.HSlider.acvalue,ScrollX);
          IF Update THEN InvalidateEditorWindow(Win,Extra);
          CheckIfToScrollX:=TRUE;
     END
     ELSE CheckIfToScrollX:=FALSE;
END;


PROCEDURE TEditorApplication.MDIHandleCharEvent(Win:HWND;ch:CHAR;Data:POINTER);
VAR s:string;
    x,y:LongWord;
    Extra1:PEditor;
label L;
BEGIN
     Extra1:=Data;
     Extra1^.ErrorMode:=FALSE;
     ClearErrorLine(Win,Data);
     x:=Extra1^.CursorX+Extra1^.HSlider.acvalue;
     IF x>=Extra1^.HSlider.ScrollTop THEN
     BEGIN
l:
          beep(1200,200);
          exit;
     END;
     y:=Extra1^.CursorY-1;
     s:=Extra1^.ScreenBuffer[y];
     Extra1^.Modified:=TRUE;
     IF Extra1^.insertmode THEN s[x]:=ch
     ELSE
     BEGIN
          Insert(ch,s,x);
          IF Length(s)>250 THEN s[0]:=#250;
     END;
     inc(Extra1^.CursorX);
     Extra1^.ScreenBuffer[y]:=s;
     IF CheckIfToScrollX(Win,Extra1,TRUE) THEN exit;
     InvalidateEditorLine(Win,s,y+1,Extra1);
END;

PROCEDURE TEditorApplication.PageUp(Win:HWND;Extra:PEditor);
VAR t,t1:WORD;
    TextView:WORD;
BEGIN
     IF Extra^.TextLow<=LONGWORD(Extra^.TextBuffer) THEN
     BEGIN
          Extra^.CursorY:=1;
          exit;
     END;
     IF Extra^.VSlider.acvalue=0 THEN
     BEGIN
          Extra^.CursorY:=1;
          exit;
     END;
     TextView:=Extra^.TextViewY-1;
     IF TextView>Extra^.VSlider.acvalue THEN
     BEGIN
          TextView:=Extra^.VSlider.acvalue;
          Extra^.CursorY:=1;
     END;
     FOR t:=EditorMaxLines DOWNTO (EditorMaxLines-TextView)+1 DO
     BEGIN
          IF Extra^.VSlider.acvalue+t=Extra^.SelectLineEnd
            THEN Extra^.SelectHiAddr:=Extra^.TextHigh+1;
          AppendUpperLine(Extra^.ScreenBuffer[t],Extra);
          IF Extra^.VSlider.acvalue+t=Extra^.SelectLineStart
            THEN Extra^.SelectLoAddr:=Extra^.TextHigh+1;
     END;
     t1:=EditorMaxLines-TextView;  {Lines to transmit}
     ASM
        MOVZXW EAX,$t1
        INC EAX
        MOV EBX,63
        MUL EBX           ;multiply with 252 and divide by 4
        MOV ECX,EAX

        MOV ESI,$Extra    ;Source buffer
        MOVZXW EAX,_EditormaxLines
        MOVZXW EBX,$TextView
        SUB EAX,EBX
        INC EAX
        MOV EBX,252        ;multiply with 252
        MUL EBX
        ADD ESI,EAX       ;Source

        MOV EDI,$Extra    ;Destination
        MOVZXW EAX,_EditorMaxLines
        INC EAX
        MOV EBX,252
        MUL EBX           ;multiply with 252
        ADD EDI,EAX       ;Destination

        STD
        REP
        MOVSW             ;MOVSD
     END;
     FOR t:=TextView-1 DOWNTO 0 DO GetLowerLine(Extra^.ScreenBuffer[t],Extra);
     Dec(Extra^.VSlider.acvalue,TextView);
END;

PROCEDURE TEditorApplication.LineUp(Win:HWND;Extra:PEditor);
VAR t:WORD;
BEGIN
     IF Extra^.CursorY=1 THEN
     BEGIN
          IF Extra^.VSlider.acvalue=0 THEN exit;
          IF Extra^.TextLow<=LONGWORD(Extra^.TextBuffer) THEN
          BEGIN
               Extra^.VSlider.Acvalue:=0;
               exit;
          END;
          IF Extra^.VSlider.acvalue+EditorMaxLines=Extra^.SelectLineEnd THEN
             Extra^.SelectHiAddr:=Extra^.TextHigh+1;
          dec(Extra^.VSlider.acvalue);
          AppendUpperLine(Extra^.ScreenBuffer[EditorMaxLines],Extra);
          IF Extra^.VSlider.acvalue+1+EditorMaxLines=Extra^.SelectLineStart
            THEN Extra^.SelectLoAddr:=Extra^.TextHigh+1;
          ASM
             MOVZXW EAX,_EditorMaxLines
             MOV EBX,63
             MUL EBX           ;multiply with 252 and divide by 4
             MOV ECX,EAX

             MOV ESI,$Extra    ;Source
             MOVZXW EAX,_EditorMaxLines
             INC EAX
             MOV EBX,252
             MUL EBX           ;multiply with 252
             ADD ESI,EAX
             MOV EDI,ESI       ;Destination
             SUB ESI,252       ;Source

             STD
             REP
             MOVSW             ;MOVSD
          END;
          GetLowerLine(Extra^.ScreenBuffer[0],Extra);
     END
     ELSE dec(Extra^.CursorY);
END;

PROCEDURE TEditorApplication.LineDown(Win:HWND;Extra:PEditor;
                                      CheckEmpty:BOOLEAN);
VAR t:Word;
    s:STRING;
label l;
BEGIN
     IF not CheckEmpty THEN goto l;
     IF Extra^.TextHigh>=LONGWORD(Extra^.TextBuffer)+Extra^.TextLen THEN
     BEGIN
          {Check if there are more lines}
          FOR t:=Extra^.CursorY TO EditorMaxLines DO
          BEGIN
               s:=Extra^.ScreenBuffer[t];
               WHILE s[length(s)]=#32 DO dec(s[0]);
               IF s<>'' THEN goto l;
          END;
          exit;
     END;
l:
     inc(Extra ^.CursorY);
     IF Extra^.CursorY>Extra^.TextViewY THEN {We must scroll}
     BEGIN
          IF Extra^.VSlider.acvalue=Extra^.SelectLineStart THEN
            Extra^.SelectLoAddr:=Extra^.TextLow;
          Extra^.CursorY:=Extra^.TextViewY;
          inc(Extra^.VSlider.acvalue);
          AppendLowerLine(Extra^.ScreenBuffer[0],Extra);
          IF Extra^.VSlider.acvalue-1=Extra^.SelectLineEnd THEN
            Extra^.SelectHiAddr:=Extra^.TextLow;
          ASM
             MOVZXW EAX,_EditorMaxLines
             MOV EBX,63
             MUL EBX           ;multiply with 252 and divide by 4
             MOV ECX,EAX

             MOV EDI,$Extra    ;Destination
             ADD EDI,4
             MOV ESI,EDI       ;Source
             ADD ESI,252

             CLD
             REP
             MOVSW             ;MOVSD
          END;
          GetUpperLine(Extra^.ScreenBuffer[EditorMaxLines],Extra);
     END;
END;

FUNCTION TEditorApplication.PageDown(Win:HWND;Extra:PEditor):BOOLEAN;
VAR
    Count:WORD;
    TextView:WORD;
    t,t1:WORD;
    s:STRING;
LABEL l;
BEGIN
     IF Extra^.TextHigh>=LONGWORD(Extra^.TextBuffer)+Extra^.TextLen THEN
     BEGIN
          {Check if there are more lines}
          FOR t:=Extra^.TextViewY TO EditorMaxLines DO
          BEGIN
               s:=Extra^.ScreenBuffer[t];
               WHILE s[length(s)]=#32 DO dec(s[0]);
               IF s<>'' THEN goto l;
          END;
          Extra^.CursorY:=Extra^.TextViewY;  {on last line}
          PageDown:=FALSE;
          exit;
     END;
l:
     TextView:=Extra^.TextViewY-1;
     FOR t:=0 TO TextView-1 DO
     BEGIN
          IF Extra^.VSlider.acvalue+t=Extra^.SelectLineStart THEN
            Extra^.SelectLoAddr:=Extra^.TextLow;
          AppendLowerLine(Extra^.ScreenBuffer[t],Extra);
          IF Extra^.VSlider.acvalue+t=Extra^.SelectLineEnd THEN
            Extra^.SelectHiAddr:=Extra^.TextLow;
     END;
     t1:=(EditorMaxLines-TextView)+1;  {Lines to transmit}
     ASM
        MOVZXW EAX,$t1
        MOV EBX,63
        MUL EBX           ;multiply with 252 and divide by 4
        MOV ECX,EAX

        MOV ESI,$Extra    ;Source buffer
        ADD ESI,4
        MOVZXW EAX,$TextView
        MOV EBX,252
        MUL EBX           ;multiply with 252

        ADD ESI,EAX       ;onto ScreenBuffer[TextView]
        MOV EDI,$Extra
        ADD EDI,4         ;onto ScreenBuffer[0]
        CLD
        REP
        MOVSW             ;MOVSD
     END;
     FOR t:=t1 TO EditorMaxLines DO GetUpperLine(Extra^.ScreenBuffer[t],Extra);
     Inc(Extra^.VSlider.acvalue,TextView);
     PageDown:=TRUE;
END;

PROCEDURE TEditorApplication.CheckVScrollBar(Win:HWND;para1,para2,Extra:PEditor);
VAr w:Word;
    p,p1:POINTER;
    l,r:LONGWORD;
    ScrollWin,FrameWin:HWND;
    SliderID:LONGWORD;
    t:WORD;
    t1:LONGWORD;
    acval:LONGWORD;
    aclineval:LONGWORD;
    acpageval:LONGWORD;
BEGIN
     l:=PointerToLong(para2);
     SliderID:=PointerToLong(para1);
     SliderID:=lo(SliderID);
     w:=hi(l);
     FrameWin:=WinQueryWindow(QW_PARENT,Win);
     ScrollWin:=WinWindowFromID(SliderID,FrameWin);
     CASE w OF
         SB_LINEUP:
         BEGIN
              Extra^.CursorY:=1;
              LineUp(Win,Extra);
              w:=CalcSliderfromValue(Extra^.VSlider.acvalue,Extra^.VSlider);
              p:=MPFROMSHORT(w);
              WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
              InvalidateEditorWindow(Win,Extra);
         END;
         SB_LINEDOWN:
         BEGIN
              Extra^.CursorY:=Extra^.TextViewY;
              LineDown(Win,Extra,TRUE);
              w:=CalcSliderfromValue(Extra^.VSlider.acvalue,Extra^.VSlider);
              p:=MPFROMSHORT(w);
              WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
              InvalidateEditorWindow(Win,Extra);
         END;
         SB_PAGEUP:
         BEGIN
              PageUp(Win,Extra);
              w:=CalcSliderfromValue(Extra^.VSlider.acvalue,Extra^.VSlider);
              p:=MPFROMSHORT(w);
              WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
         END;
         SB_PAGEDOWN:
         BEGIN
              PageDown(Win,Extra);
              w:=CalcSliderfromValue(Extra^.VSlider.acvalue,Extra^.VSlider);
              p:=MPFROMSHORT(w);
              WinSendMsg(NIL,p,SBM_SETPOS,ScrollWin);
         END;
         SB_SLIDERPOSITION:
         BEGIN
              w:=lo(l);
              acval:=CalcValuefromSlider(w,Extra^.VSlider);
              IF acval=Extra^.VSlider.acvalue THEN exit;
              IF acval>Extra^.VSlider.acvalue THEN
              BEGIN
                   r:=(acval-Extra^.VSlider.acvalue)+Extra^.TextViewY;
                   acpageval:=r div Extra^.TextViewY;
                   aclineval:=r mod Extra^.TextViewY;
                   FOR t1:=1 TO acpageval DO PageDown(Win,Extra);
                   FOR t1:=1 TO aclineval+acpageval DO LineDown(Win,Extra,TRUE);
              END
              ELSE
              BEGIN
                   r:=(Extra^.VSlider.acvalue-acval)+Extra^.TextViewY;
                   acpageval:=r div Extra^.TextViewY;
                   aclineval:=r mod Extra^.TextViewY;
                   FOR t1:=1 TO acpageval DO PageUp(Win,Extra);
                   FOR t1:=1 TO aclineval+acpageval DO LineUp(Win,Extra);
              END;
         END;
     END; {Case}
END;

PROCEDURE TEditorApplication.GotoLine(Extra:PEditor;Line,Col:WORD);
VAR
    acpageval,aclineval,r:WORD;
    t,t1,count,Save:WORD;
    Win:HWND;
Label l,l1,l2;
BEGIN
     IF EditorCount=0 THEN exit;
     EditorStatusMessage('Goto line:'+tostr(Line));
     Extra^.CursorX:=Col;
     Extra^.HSlider.AcValue:=0;
     IF Extra^.CursorX>Extra^.TextViewX THEN
     BEGIN
          Extra^.HSlider.acvalue:=Extra^.CursorX-Extra^.TextViewX;
          Extra^.CursorX:=Extra^.TextViewX;
     END;
     Win:=Extra^.ChildWin{FrameWin};
     t1:=Extra^.VSlider.acvalue+Extra^.CursorY;
     IF Line=t1 THEN
     BEGIN
          EditorStatusMessage('');
          exit;
     END;
     IF Line>t1 THEN
     BEGIN
          r:=Line-t1;
          acpageval:=r div Extra^.TextViewY;
          aclineval:=r mod Extra^.TextViewY;
          FOR t1:=1 TO acpageval DO
          BEGIN
               IF PageDown(Win,Extra)=FALSE THEN goto l2;
          END;
          FOR t1:=1 TO aclineval+acpageval DO LineDown(Win,Extra,TRUE);
          WHILE Extra^.CursorY+Extra^.VSlider.acvalue>Line DO
            LineUp(Win,Extra);
    END
    ELSE
    BEGIN
         r:=t1-Line;
         acpageval:=r div Extra^.TextViewY;
         aclineval:=r mod Extra^.TextViewY;
         FOR t1:=1 TO acpageval DO PageUp(Win,Extra);
         FOR t1:=1 TO aclineval+acpageval DO LineUp(Win,Extra);
         WHILE Extra^.CursorY+Extra^.VSlider.acvalue<Line DO
          LineDown(Win,Extra,TRUE);
    END;
    Save:=Extra^.CursorY;
    r:=Extra^.TextViewY DIV 2;
    IF Save=r THEN
    BEGIN
         EditorStatusMessage('');
         exit;
    END;
    IF Save>r THEN  {actual position greater}
    BEGIN
         r:=Save-r;
         Extra^.CursorY:=Extra^.TextViewY;
         count:=0;
         FOR t1:=1 TO r DO
         BEGIN
              t:=Extra^.vSlider.Acvalue;
              LineDown(Win,Extra,TRUE);
              IF t=Extra^.VSlider.Acvalue THEN goto l;
              inc(Count);
         END;
l:
         Extra^.CursorY:=save-count;
    END
    ELSE
    BEGIN
         dec(r,save);
         Extra^.CursorY:=1;
         count:=0;
         FOR t1:=1 TO r DO
         BEGIN
              t:=Extra^.vSlider.Acvalue;
              LineUp(Win,Extra);
              IF t=Extra^.VSlider.Acvalue THEN goto l1;
              inc(Count);
         END;
l1:
         Extra^.CursorY:=save+count;
    END;
l2:
    EditorStatusMessage('');
    InvalidateEditorWindow(Win,Extra);
END;

PROCEDURE TEditorApplication.MDICreateNotify(MDIFrWin,MDIWin:HWND;Data:POINTER);
VAR
    ww,ww1:Word;
    p:POINTER;
    p1:POINTER;
    ScrollWin:HWND;
    pp:PEditor;
    rec:RECTL;
    Lines:LONGWORD;
BEGIN
     inherited.MDICreateNotify(MDIFrWin,MDIWin,Data);
     pp:=Data;
     pp^.ChildWin:=MDIWin;
     pp^.FrameWin:=MDIFrWin;
     SetSliderValues(MDIWin,pp);
     pp^.HSlider.acvalue:=pp^.HSlider.scrollbottom;
END;

PROCEDURE TEditorApplication.InvalidateEditorLine(Win:HWND;var s:string;
                                                  y:LONGWORD;Extra:PEditor);
VAR _hps:LONGWORD;
    rec:RECTL;
    pt:POINTL;
    facename:String;
    scrollX:LONGWORD;
    SelectLoLine,SelectHiLine:WORD;
    SelectLoColumn,SelectHiColumn:WORD;
    acline,accolumn:WORD;
    help,TextViewX:WORD;
    pp:PEditor;
    mul,mul1,t:WORD;
    TextDrawColor,TextbackColor:LONGINT;
    incd:BOOLEAN;
Label l,l1,weiter;
BEGIN
     WinShowCursor(0,Win);
     _hps:=WinGetPS(Win);
     WinQueryWindowRect(rec,Win);
     facename:='System VIO';
     IF CharHeight=8 THEN CreateLogFont(_hps,facename,CharHeight,CharWidth-1,
                                        FATTR_SEL_BOLD) {small font}
     ELSE  CreateLogFont(_hps,facename,CharHeight,CharWidth,0); {default font}
     pt.x:=2;
     pt.y:=rec.yTop-y*CharHeight;
     scrollX:=Extra^.HSlider.acvalue;
     GpiSetBackMix(2,_hps);  {BM_OverPaint}
     pp:=Extra;

     SelectLoLine:=pp^.SelectLineStart;
     SelectHiLine:=pp^.SelectLineEnd;
     SelectLoColumn:=pp^.SelectColumnStart;
     SelectHiColumn:=pp^.SelectColumnEnd;
     AcLine:=pp^.VSlider.acvalue;
     AcColumn:=ScrollX+1;
     TextViewX:=pp^.TextViewX+1;

     IF SelectLoColumn<65535 THEN
     BEGIN
         IF SelectLoColumn>AcColumn-1 THEN
         BEGIN
              Dec(SelectLoColumn,AcColumn-1);
              Mul:=CharWidth*(SelectLoColumn-1);
         END
         ELSE SelectLoColumn:=0;
     END
     ELSE SelectLoColumn:=0;

     IF SelectHiColumn<65535 THEN
     BEGIN
         IF SelectHiColumn>AcColumn-1 THEN
         BEGIN
              Dec(SelectHiColumn,AcColumn-1);
              Mul1:=CharWidth*SelectHiColumn;
         END
         ELSE SelectHiColumn:=0;
     END
     ELSE SelectHiColumn:=0;

     TextDrawColor:=GetMDiColor(Win);
     TextBackColor:=GetMDIBackColor(Win);
     GpiSetColor(TextDrawColor,_hps);
     GpiSetBackColor(TextBackColor,_hps);
     t:=y;
     help:=t+AcLine;
     IF pp^.ErrorMode THEN
     BEGIN
          IF Help=pp^.ErrorLine THEN
          BEGIN
               GpiSetColor(ErrorDrawColor,_hps);
               GpiSetBackColor(ErrorBackColor,_hps);
               GpiCharStringAt(s[ScrollX+1],pp^.TextViewX+1,pt,_hps);
               goto weiter;
          END;
     END;
     IF ((help>=SelectLoLine)AND(Help<=SelectHiLine)) THEN
     BEGIN
          CASE Help OF
              SelectLoLine:
              BEGIN
                   IF SelectLoColumn>0 THEN
                   BEGIN
                        dec(SelectLoColumn);
                        IF SelectLoColumn>0 THEN
                        BEGIN
                             DrawEditorStr(s[AcColumn],
                                           SelectLoColumn+2,pt,_hps,
                                           TextDrawColor);
                             inc(pt.x,Mul);
                             incd:=TRUE;
                        END
                        ELSE incd:=FALSE;
                        GpiSetColor(SelectDrawColor,_hps);
                        GpiSetBackColor(SelectBackColor,_hps);
                        IF Help=SelectHiLine THEN
                        BEGIN
                            GpiCharStringAt(s[AcColumn+
                                       SelectLoColumn],SelectHiColumn-
                                       SelectLoColumn,pt,_hps);
                            GpiSetColor(TextDrawColor,_hps);
                            GpiSetBackColor(TextBackColor,_hps);
                            inc(pt.x,mul1-mul);
                            GpiCharStringAt(s[AcColumn+
                                       SelectLoColumn+
                                       (SelectHiColumn-SelectLoColumn)],
                                       TextViewX-SelectHiColumn,pt,_hps);
                            dec(pt.x,mul1-mul);
                        END
                        ELSE GpiCharStringAt(s[AcColumn+
                                        SelectLoColumn],TextViewX-SelectLoColumn,
                                        pt,_hps);
                        IF incd THEN dec(pt.x,Mul);
                 END
                 ELSE
                 BEGIN
l:
                      GpiSetColor(SelectDrawColor,_hps);
                      GpiSetBackColor(SelectBackColor,_hps);
l1:
                      GpiCharStringAt(s[AcColumn],
                                       pp^.TextViewX+1,pt,_hps);
                 END;
                GpiSetColor(TextDrawColor,_hps);
                GpiSetBackColor(TextBackColor,_hps);
           END;
           SelectHiLine:
           BEGIN
                IF SelectHiColumn>0 THEN
                BEGIN
                      GpiSetColor(SelectDrawColor,_hps);
                      GpiSetBackColor(SelectBackColor,_hps);
                      GpiCharStringAt(s[AcColumn],
                                        SelectHiColumn+2,pt,_hps);
                      inc(pt.x,Mul1);
                      GpiSetColor(TextDrawColor,_hps);
                      GpiSetBackColor(TextBackColor,_hps);
                      IF SelectHiColumn<TextViewX THEN
                      DrawEditorStr(s[AcColumn+
                                  SelectHiColumn],TextViewX-SelectHiColumn,
                                  pt,_hps,TextDrawColor)
                      ELSE DrawEditorStr(s[AcColumn+
                                         SelectHiColumn],TextViewX,
                                         pt,_hps,TextDrawColor);
                      dec(pt.x,Mul1);
                END
                ELSE goto l1;
            END;
            ELSE
            BEGIN
                 GpiSetColor(SelectDrawColor,_hps);
                 GpiSetBackColor(SelectBackColor,_hps);
                 GpiCharStringAt(s[AcColumn],
                                 pp^.TextViewX+1,pt,_hps);
                 GpiSetColor(TextDrawColor,_hps);
                 GpiSetBackColor(TextBackColor,_hps);
            END;
        END; {case}
     END
     ELSE DrawEditorStr(s[ScrollX+1],pp^.TextViewX+11,pt,_hps,TextDrawColor);
weiter:
     WinReleasePS(_hps);
     WinShowCursor(1,Win);
     SetCursor(Win,Extra);
END;

PROCEDURE TEditorApplication.InvalidateEditorWindow(Win:HWND;Extra:PEditor);
VAR _hps:LONGWORD;
    rec:RECTL;
BEGIN
     _hps:=WinGetPS(Win);
     WinQueryWindowRect(rec,Win);
     MDIRedraw(rec,_hps,Win,Extra);
     WinReleasePs(_hps);
END;

PROCEDURE GetBufferLine(VAR s:String;VAR Buffer:PTextBuf;Len:LONGWORD;
                        Max:LONGWORD);
VAR
    Adresse:LONGWORD;
Label l;
BEGIN
     Adresse:=LONGWORD(Buffer);
     IF Adresse>=Max THEN
     BEGIN
          s:='';
          goto l;
     END;
     ASM
        MOV CL,0
        MOV EDI,$s
        INC EDI
        MOV ESI,$Adresse
!rep_lab_1:
        CMP ESI,$Max
        JAE !crlf_1
        MOV AL,[ESI+0]
        INC ESI
        CMP AL,13
        JE !cr_1
        CMP AL,10
        JE !crlf_1

        INC CL
        MOV [EDI+0],AL
        INC EDI
        CMP CL,251
        JAE !crlf_1
        JMP !rep_lab_1
!cr_1:
        MOV AL,[ESI+0]
        CMP AL,10
        JNE !crlf_1
        INC ESI
!crlf_1:
        CLD
        MOV AL,0
        STOSB
        MOV EDI,$s
        MOV [EDI+0],CL   ;Set text len
        CMP ESI,$Max
        JBE !ok1_1
        MOV ESI,$Max
!ok1_1:
        MOV $Adresse,ESI
     END;
     Buffer:=POINTER(Adresse)
l:
     IF length(s)>250 THEN s[0]:=#250;
     ASM
        MOV EDI,$s
        MOV AL,[EDI+0]
        CMP AL,250
        JE !eee_1
        ;Length to short --> fill up with space
        MOVZX EAX,AL
        MOVB [EDI+0],250
        ADD EDI,EAX
        INC EDI
        MOV ECX,250
        SUB ECX,EAX
        MOV AL,32
        CLD
        REP
        STOSB
        MOV AL,0
        STOSB
!eee_1:
     END;
END;


PROCEDURE TEditorApplication.PutText(Win:HWND;Extra:PEditor;Buf:PTextBuf;
                                     Len,CountLines:LONGWORD);
VAR s,s1,s2:String;
    r:LONGWORD;
    rc:RECTL;
    ww,ww1:WORD;
    p:POINTER;
    x:WORD;
    FrameWin,ScrollWin:HWND;
    NewLStart,NewCStart,NewCEnd:WORD;
    OldCursorY:WORD;
    BLen,BufEnd:LONGWORD;
    t,t1:WORD;
    pb:^Byte;
BEGIN
     IF Extra^.SelectColumnStart=0 THEN inc(Extra^.SelectColumnStart);
     IF Extra^.SelectColumnEnd=0 THEN inc(Extra^.SelectColumnEnd);
     BufEnd:=LONGWORD(Buf)+Len;  {Highest buffer address}
     Extra^.Modified:=TRUE;
     s:=Extra^.ScreenBuffer[Extra^.CursorY-1];
     NewLStart:=Extra^.VSlider.AcValue+(Extra^.CursorY-1);
     x:=Extra^.CursorX+Extra^.HSlider.acvalue;
     s1:=copy(s,1,x-1);
     NewCStart:=Length(s1)+1;
     delete(s,1,x-1);
     WHILE s[length(s)]=#32 DO dec(s[0]);

     IF CountLines=1 THEN
     BEGIN
          GetBufferLine(s2,Buf,Len,BufEnd);
          IF Length(s2)>Extra^.SelectColumnStart-1 THEN
          BEGIN
               Delete(s2,1,Extra^.SelectColumnStart-1);
               ww:=Extra^.SelectColumnEnd-Extra^.SelectColumnStart;
               IF length(s2)>ww+1 THEN s2[0]:=chr(ww+1);
          END
          ELSE s2:='';

          WHILE s2[length(s2)]=#32 DO dec(s2[0]);
          NewCEnd:=Length(s1)+Length(s2);
          s:=s1+s2+s;
          WHILE Length(s)<250 DO s:=s+' ';
          IF Length(s)>250 THEN s[0]:=#250;
          Extra^.ScreenBuffer[Extra^.CursorY-1]:=s;
     END
     ELSE
     BEGIN
          IF s<>'' THEN
          BEGIN
               WHILE Length(s)<250 DO s:=s+' ';
               inc(Extra^.TextLines);
               AppendUpperLine(Extra^.ScreenBuffer[EditorMaxLines],Extra);
               FOR t:=EditorMaxLines DOWNTO Extra^.CursorY+1 DO
                  Extra^.ScreenBuffer[t]:=Extra^.ScreenBuffer[t-1];
               Extra^.ScreenBuffer[Extra^.CursorY]:=s;
          END;

          GetBufferLine(s,Buf,Len,BufEnd);
          IF Length(s)>Extra^.SelectColumnStart-1 THEN
            Delete(s,1,Extra^.SelectColumnStart-1)
          ELSE s:='';
          s1:=s1+s;
          WHILE Length(s1)<250 DO s1:=s1+' ';
          IF Length(s1)>250 THEN s1[0]:=#250;
          Extra^.ScreenBuffer[Extra^.CursorY-1]:=s1;

          NewCEnd:=240;

          OldCursorY:=Extra^.CursorY;
          FOR t:=2 TO CountLines DO
          BEGIN
               IF Extra^.CursorY<=EditormaxLines THEN
               BEGIN
                    AppendUpperLine(Extra^.ScreenBuffer[EditorMaxLines],Extra);
                    IF Extra^.CursorY<EditorMaxLines THEN
                      FOR t1:=EditorMaxLines DOWNTO Extra^.CursorY+1 DO
                        Extra^.ScreenBuffer[t1]:=Extra^.ScreenBuffer[t1-1];
                    GetBufferLine(s,Buf,Len,BufEnd);
                    Extra^.ScreenBuffer[Extra^.CursorY]:=s;
               END
               ELSE
               BEGIN
                    BLen:=BufEnd-LONGWORD(Buf); {remaining bytes in buffer}
                    r:=Extra^.TextHigh-Blen;
                    IF r<Extra^.TextLow THEN ExtendEditor(Extra);
                    IF r-Extra^.TextLow<SafetyBufSize THEN ExtendEditor(Extra);
                    Extra^.SelectHiAddr:=Extra^.TextHigh+1;
                    dec(Extra^.TextHigh,BLen-1);
                    pb:=POINTER(Extra^.TextHigh);
                    Move(Buf^,pb^,BLen);
                    dec(Extra^.TextHigh);
                    inc(Extra^.TextLines,(CountLines-t));
                    t:=CountLines; {End of loop}
               END;
               inc(Extra^.CursorY);
               inc(Extra^.TextLines);
          END;
          Extra^.CursorY:=OldCursorY;
          SetSliderValues(Win,Extra);
     END;
     Extra^.SelectLineStart:=NewLStart;
     Extra^.SelectLineEnd:=NewLStart+(CountLines-1);
     Extra^.SelectColumnStart:=NewCStart;
     Extra^.SelectColumnEnd:=NewCEnd;
END;

PROCEDURE TEditorApplication.InsertText(Win:HWND;Extra:PEditor);
VAR
   p:PTextBuf;
   Len:LONGWORD;
   CountLines:WORD;
BEGIN
     p:=CopySelectedText(Win,Extra,Len);
     IF p=NIL THEN exit;
     CountLines:=(Extra^.SelectLineEnd-Extra^.SelectLineStart)+1;
     PutText(Win,Extra,p,Len,CountLines);
     Freemem(p,Len);
     InvalidateEditorWindow(Win,Extra);
END;



PROCEDURE TEditorApplication.MDIHandleScanEvent(Win:HWND;scan:Word;Data:POINTER);
VAR hsp:LONGWORD;
    r:LongWord;
    x,y:LONGWORD;
    s,s1:string;
    t,t1:WORD;
    ScrollWin,FrameWin:HWND;
    p:POINTER;
    ww,ww1,NewX:WORD;
    rc:RECTL;
    Extra1:PEditor;
    _Insert,Indent,Backups,SynHigh:BOOLEAN;
    ShiftSelect:BOOLEAN;
Label lfound,lend,lstart,rend,rstart,cl,cr,cu,cd,sl;
BEGIN
     Inherited.MDIHandleScanEvent(Win,scan,Data);
     Extra1:=Data;
     Extra1^.ErrorMode:=FALSE;
     ClearErrorLine(Win,Data);
     ShiftSelect:=FALSE;
     CASE Scan OF
         kbShiftCLeft:
         BEGIN
              ShiftSelect:=TRUE;
              IF extra1^.SelectLineStart=65535 THEN
              BEGIN
                   Extra1^.SelectLineStart:=Extra1^.VSlider.acvalue+
                      Extra1^.CursorY;
                   dec(Extra1^.SelectLineStart);
                   Extra1^.SelectColumnStart:=Extra1^.HSlider.acvalue+
                      Extra1^.CursorX;
                   Extra1^.SelectLineEnd:=Extra1^.SelectLineStart;
                   Extra1^.SelectColumnEnd:=Extra1^.SelectColumnStart;
              END;
              goto cl;
         END;
         kbShiftCRight:
         BEGIN
              ShiftSelect:=TRUE;
              IF extra1^.SelectLineStart=65535 THEN
              BEGIN
                   Extra1^.SelectLineStart:=Extra1^.VSlider.acvalue+
                      Extra1^.CursorY;
                   dec(Extra1^.SelectLineStart);
                   Extra1^.SelectColumnStart:=Extra1^.HSlider.acvalue+
                      Extra1^.CursorX;
                   Extra1^.SelectLineEnd:=Extra1^.SelectLineStart;
                   Extra1^.SelectColumnEnd:=Extra1^.SelectColumnStart;
              END;
              goto cr;
         END;
         kbShiftCUp:
         BEGIN
              ShiftSelect:=TRUE;
              IF extra1^.SelectLineStart=65535 THEN
              BEGIN
                   Extra1^.SelectLineStart:=Extra1^.VSlider.acvalue+
                      Extra1^.CursorY;
                   dec(Extra1^.SelectLineStart);
                   Extra1^.SelectColumnStart:=Extra1^.HSlider.acvalue+
                      Extra1^.CursorX;
                   Extra1^.SelectLineEnd:=Extra1^.SelectLineStart;
                   Extra1^.SelectColumnEnd:=Extra1^.SelectColumnStart;
              END;
              goto cu;
         END;
         kbShiftCDown:
         BEGIN
              ShiftSelect:=TRUE;
              IF extra1^.SelectLineStart=65535 THEN
              BEGIN
                   Extra1^.SelectLineStart:=Extra1^.VSlider.acvalue+
                      Extra1^.CursorY;
                   dec(Extra1^.SelectLineStart);
                   Extra1^.SelectColumnStart:=Extra1^.HSlider.acvalue+
                      Extra1^.CursorX;
                   Extra1^.SelectLineEnd:=Extra1^.SelectLineStart;
                   Extra1^.SelectColumnEnd:=Extra1^.SelectColumnStart;
              END;
              goto cd;
         END;
         kbCtrlKC:InsertText(Win,Data);
         kbCtrlKB:
         BEGIN
              Extra1^.SelectLineStart:=Extra1^.VSlider.acvalue+
                       Extra1^.CursorY;
              dec(Extra1^.SelectLineStart);
              Extra1^.SelectColumnStart:=Extra1^.HSlider.acvalue+
                       Extra1^.CursorX;
              Extra1^.SelectLineEnd:=Extra1^.SelectLineStart;
              Extra1^.SelectColumnEnd:=Extra1^.SelectColumnStart;
              InvalidateEditorWindow(Win,Extra1);
         END;
         kbCtrlKK:
         BEGIN
sl:
              IF Extra1^.SelectLineStart<65535 THEN
              BEGIN
                   ww:=Extra1^.VSlider.acvalue+Extra1^.CursorY;
                   dec(ww);
                   ww1:=Extra1^.HSlider.acvalue+Extra1^.CursorX;
                   dec(ww1);
                   IF ww<Extra1^.SelectLineStart THEN
                   BEGIN
                        Extra1^.SelectLineStart:=ww;
                        Extra1^.SelectColumnStart:=ww1+1;
                   END
                   ELSE
                   BEGIN
                        IF ww>Extra1^.SelectLineStart THEN
                        BEGIN
                             Extra1^.SelectLineEnd:=ww;
                             Extra1^.SelectColumnEnd:=ww1;
                        END
                        ELSE
                        BEGIN
                             IF ww1>Extra1^.SelectColumnStart-1 THEN
                               Extra1^.SelectColumnEnd:=ww1
                             ELSE Extra1^.SelectColumnStart:=ww1+1;
                        END;
                   END;
                   InvalidateEditorWindow(Win,Extra1);
              END;
         END;
         kbCtrlA,kbCtrlCLeft: {Word left}
         BEGIN
              y:=Extra1^.CursorY-1;
              s:=Extra1^.ScreenBuffer[y];
              while s[length(s)]=#32 do dec(s[0]);

              x:=Extra1^.CursorX+Extra1^.HSlider.acvalue;
              IF x>length(s) THEN x:=length(s);

              IF x<=1 THEN
              BEGIN
lend:
                   {Move to end of previous line}
                   IF Extra1^.CursorY=1 THEN
                   BEGIN
                        IF Extra1^.VSlider.acvalue=0 THEN exit;
                        LineUp(Win,Extra1);
                        InvalidateEditorWindow(Win,Extra1);
                   END
                   ELSE LineUp(Win,Extra1);
                   y:=Extra1^.CursorY-1;
                   s:=Extra1^.ScreenBuffer[y];
                   while s[length(s)]=#32 do dec(s[0]);
                   x:=length(s)+1;
                   goto lfound;
              END;

              FOR t:=x-1 downto 1 DO
              BEGIN
                   CASE s[t] OF
                     'A'..'Z','a'..'z','0'..'9','_':goto lstart;
                     ELSE IF x>0 THEN dec(x);
                   END; {case}
              END;
lstart:
              IF x<=1 THEN goto lend;
              FOR t:=x-1 downto 1 DO
              BEGIN
                   CASE s[t] OF
                     ' '..'/',':'..'@','['..#96,'{'..#255:
                     BEGIN
                          x:=t+1;
                          goto lfound;
                     END;
                   END; {case}
              END;
              x:=1;
lfound:
              Extra1^.CursorX:=x;
              r:=Extra1^.HSlider.acvalue;
              Extra1^.HSlider.acvalue:=0;
              IF CheckIfToScrollX(Win,Extra1,TRUE) THEN exit;
              IF r<>0 THEN
              BEGIN
                   InvalidateEditorWindow(Win,Extra1);
                   exit;
              END;
         END;
         kbCtrlF,kbCtrlCRight: {Word right}
         BEGIN
              y:=Extra1^.CursorY-1;
              s:=Extra1^.ScreenBuffer[y];
              while s[length(s)]=#32 do dec(s[0]);

              x:=Extra1^.CursorX+Extra1^.HSlider.acvalue;
              IF x>length(s) THEN x:=length(s);

              IF x>=length(s) THEN
              BEGIN
rend:
                   {Move to start of next line}
                   Extra1^.CursorX:=1;
                   Extra1^.HSlider.AcValue:=0;
                   IF Extra1^.CursorY=Extra1^.TextViewY THEN
                   BEGIN
                       LineDown(Win,Extra1,TRUE);
                       InvalidateEditorWindow(Win,Data);
                       exit;
                   END
                   ELSE LineDown(Win,Extra1,TRUE);
                   x:=1;
                   goto lfound;
              END;

              FOR t:=x+1 to length(s) DO
              BEGIN
                   CASE s[t] OF
                     'A'..'Z','a'..'z','0'..'9','_':goto rstart;
                     ELSE IF x<length(s) THEN inc(x);
                   END; {case}
              END;
rstart:
              IF x>=length(s) THEN goto rend;
              FOR t:=x+1 to length(s) DO
              BEGIN
                   CASE s[t] OF
                     ' '..'/',':'..'@','['..#96,'{'..#255:
                     BEGIN
                          x:=t+1;
                          IF s[x] IN ['A'..'Z','a'..'z','0'..'9','_']
                             THEN goto lfound;
                     END;
                   END; {case}
              END;
              x:=length(s)+1;
              goto lfound;
         END;
         kbCtrlPos1:Extra1^.CursorY:=1;
         kbCtrlEnd:Extra1^.CursorY:=Extra1^.TextViewY;
         kbCtrlPageUp:GotoLine(Extra1,1,1);     {Start of text}
         kbCtrlPageDown:GotoLine(Extra1,65530,1);
         kbAlt0:
         BEGIN
              r:=CM_LIST;
              WinSendMsg(NIL,POINTER(r),WM_COMMAND,ClientHandle);
              exit;
         END;
         kbCtrlY,kbCtrlZ:
         BEGIN
              Extra1^.Modified:=TRUE;
              FOR t:=Extra1^.CursorY-1 TO EditorMaxLines-1 DO
                Extra1^.ScreenBuffer[t]:=Extra1^.ScreenBuffer[t+1];
              IF GetUpperLine(Extra1^.ScreenBuffer[EditorMaxLines],Extra1)
               THEN Dec(Extra1^.TextLines);
              InvalidateEditorWindow(Win,Extra1);
         END;
         kbCDown,kbCtrlX:
         BEGIN
cd:
              IF Extra1^.CursorY=Extra1^.TextViewY THEN
              BEGIN
                   LineDown(Win,Extra1,TRUE);
                   IF ShiftSelect THEN goto sl;
                   InvalidateEditorWindow(Win,Data);
                   exit;
              END
              ELSE LineDown(Win,Extra1,FALSE);
              IF ShiftSelect THEN goto sl;
         END;
         kbCUp,kbCtrlE:
         BEGIN
cu:
              IF Extra1^.CursorY=1 THEN
              BEGIN
                   IF Extra1^.VSlider.acvalue=0 THEN exit;
                   LineUp(Win,Extra1);
                   IF ShiftSelect THEN goto sl;
                   InvalidateEditorWindow(Win,Extra1);
                   exit;
              END
              ELSE LineUp(Win,Extra1);
              IF ShiftSelect THEN goto sl;
         END;
         kbCR,kbCtrlN:
         BEGIN
              IF Extra1^.InsertMode THEN
              BEGIN
                   GetEditorOptions(_Insert,Indent,SynHigh,BackUps);
                   Extra1^.CursorX:=1;
                   Extra1^.HSlider.acvalue:=0;
                   IF Extra1^.CursorY=Extra1^.TextViewY THEN
                   BEGIN
                        LineDown(Win,Extra1,FALSE);
                        IF Indent THEN
                        BEGIN
                             s:=Extra1^.ScreenBuffer[Extra1^.CursorY-1];
                             WHILE s[length(s)]=#32 DO dec(s[0]);
                             FOR t:=1 TO length(s) DO
                             BEGIN
                                  IF s[t]<>#32 THEN
                                  BEGIN
                                       Extra1^.CursorX:=t;
                                       t:=length(s);
                                  END;
                             END;
                        END;
                        InvalidateEditorWindow(Win,Data);
                        exit;
                   END
                   ELSE
                   BEGIN
                        IF Indent THEN
                        BEGIN
                             s:=Extra1^.ScreenBuffer[Extra1^.CursorY];
                             WHILE s[length(s)]=#32 DO dec(s[0]);
                             FOR t:=1 TO length(s) DO
                             BEGIN
                                IF s[t]<>#32 THEN
                                BEGIN
                                     Extra1^.CursorX:=t;
                                     t:=length(s);
                               END;
                             END;
                        END;
                        LineDown(Win,Extra1,FALSE);
                   END;
              END
              ELSE
              BEGIN
                   GetEditorOptions(_Insert,Indent,SynHigh,BackUps);
                   Extra1^.Modified:=TRUE;
                   s:=Extra1^.ScreenBuffer[Extra1^.CursorY-1];
                   NewX:=1;
                   IF Indent THEN
                   BEGIN
                       s1:=s;
                       WHILE s1[length(s1)]=#32 DO dec(s1[0]);
                       FOR t:=1 TO length(s1) DO
                       BEGIN
                           IF s1[t]<>#32 THEN
                           BEGIN
                               NewX:=t;
                               t:=length(s1);
                           END;
                       END;
                   END;
                   x:=Extra1^.CursorX+Extra1^.HSlider.acvalue;
                   s1:=copy(s,1,x-1);
                   WHILE Length(s1)<250 DO s1:=s1+' ';
                   Extra1^.ScreenBuffer[Extra1^.CursorY-1]:=s1;
                   delete(s,1,x-1);
                   WHILE s[length(s)]=#32 DO dec(s[0]);
                   inc(Extra1^.CursorY);
                   Extra1^.CursorX:=NewX;
                   Extra1^.HSlider.acvalue:=0;
                   inc(Extra1^.TextLines);
                   SetSliderValues(Win,Extra1);
                   AppendUpperLine(Extra1^.ScreenBuffer[EditorMaxLines],Extra1);
                   FOR t:=EditorMaxLines DOWNTO Extra1^.CursorY DO
                    Extra1^.ScreenBuffer[t]:=Extra1^.ScreenBuffer[t-1];
                   IF NewX>1 THEN FOR t:=2 TO NewX DO s:=' '+s;
                   WHILE Length(s)<250 DO s:=s+' ';
                   Extra1^.ScreenBuffer[Extra1^.CursorY-1]:=s;
                   Dec(Extra1^.CursorY);
                   LineDown(Win,Extra1,FALSE);
                   InvalidateEditorWindow(Win,Data);
              END;
         END;
         kbPageDown,kbCtrlC:
         BEGIN
              PageDown(Win,Extra1);
              InvalidateEditorWindow(Win,Extra1);
              exit;
         END;
         kbPageUp,kbCtrlR:
         BEGIN
              PageUp(Win,Extra1);
              InvalidateEditorWindow(Win,Extra1);
              exit;
         END;
         kbCRight,kbCtrlD:
         BEGIN
cr:
              x:=Extra1^.CursorX+Extra1^.HSlider.acvalue;
              IF x>=Extra1^.HSlider.ScrollTop THEN exit;
              inc(Extra1^.CursorX);
              IF CheckIfToScrollX(Win,Extra1,FALSE) THEN
              BEGIN
                  IF ShiftSelect THEN goto sl;
                  InvalidateEditorWindow(Win,Extra1);
                  exit;
              END;
              IF ShiftSelect THEN goto sl;
         END;
         kbCLeft,kbCtrlS:
         BEGIN
cl:
              IF Extra1^.CursorX=1 THEN
              BEGIN
                   IF Extra1^.HSlider.acvalue=0 THEN exit;
                   dec(Extra1^.HSlider.acvalue);
                   IF ShiftSelect THEN goto sl;
                   InvalidateEditorWindow(Win,Extra1);
                   exit;
              END
              ELSE dec(Extra1^.CursorX);
              IF ShiftSelect THEN goto sl;
         END;
         kbPos1:
         BEGIN
              Extra1^.CursorX:=1;
              r:=Extra1^.HSlider.acvalue;
              Extra1^.HSlider.acvalue:=0;
              if r<>0 THEN
              BEGIN
                   InvalidateEditorWindow(Win,Extra1);
                   exit;
              END;
         END;
         kbEnd:
         BEGIN
              x:=Extra1^.CursorY-1;
              s:=Extra1^.ScreenBuffer[x];
              while s[length(s)]=#32 do dec(s[0]);
              Extra1^.CursorX:=length(s)+1;
              r:=Extra1^.HSlider.acvalue;
              Extra1^.HSlider.acvalue:=0;
              IF CheckIfToScrollX(Win,Extra1,TRUE) THEN exit;
              IF r<>0 THEN
              BEGIN
                   InvalidateEditorWindow(Win,Extra1);
                   exit;
              END;
         END;
         kbDel,kbCtrlG:
         BEGIN
              Extra1^.Modified:=TRUE;
              y:=Extra1^.CursorY-1;
              s:=Extra1^.ScreenBuffer[y];
              x:=Extra1^.CursorX+Extra1^.HSlider.acvalue;
              t1:=0;
              for t:=length(s) downto x do if s[t]<>#32 then t1:=t;
              if t1<x then
              begin
                   while s[length(s)]=#32 do dec(s[0]);
                   IF x>0 THEN IF length(s)<x THEN for t:=1 TO x do s:=s+' ';
                   s1:=Extra1^.ScreenBuffer[y+1];
                   while s1[length(s1)]=#32 do dec(s1[0]);
                   if length(s)+length(s1)>250 then s1[0]:=chr(250-length(s));
                   s:=s+s1;
                   while length(s)<250 do s:=s+' ';
                   Extra1^.ScreenBuffer[y]:=s;
                   FOR t:=y+1 TO EditorMaxLines-1 DO
                     Extra1^.ScreenBuffer[t]:=Extra1^.ScreenBuffer[t+1];
                   IF GetUpperLine(Extra1^.ScreenBuffer[EditorMaxLines],Extra1)
                    THEN Dec(Extra1^.TextLines);
                   InvalidateEditorWindow(Win,Extra1);
              end
              else
              begin
                   delete(s,x,1);
                   s:=s+' ';
                   Extra1^.ScreenBuffer[y]:=s;
                   InvalidateEditorLine(Win,s,y+1,Extra1);
              end;
              exit;
         END;
         kbBS,kbCtrlH:
         BEGIN
              Extra1^.Modified:=TRUE;
              y:=Extra1^.CursorY-1;
              x:=Extra1^.CursorX+Extra1^.HSlider.acvalue;
              s:=Extra1^.ScreenBuffer[y];
              IF length(s)>=x-1 THEN IF x<>1 THEN delete(s,x-1,1);
              while length(s)<250 do s:=s+' ';
              Extra1^.ScreenBuffer[y]:=s;
              IF Extra1^.CursorX=1 THEN
              BEGIN
                   IF Extra1^.HSlider.acvalue>0 THEN dec(Extra1^.HSlider.acvalue)
                   ELSE
                   BEGIN
                        IF Extra1^.CursorY=1 THEN
                         IF Extra1^.VSlider.AcValue=0 THEN
                         BEGIN
                              InvalidateEditorWindow(Win,Extra1);
                              exit;
                         END;
                        {Delete actual line and jump to previous}
                        FOR t:=Extra1^.CursorY-1 TO EditorMaxLines-1 DO
                          Extra1^.ScreenBuffer[t]:=Extra1^.ScreenBuffer[t+1];
                        IF GetUpperLine(Extra1^.ScreenBuffer[EditorMaxLines],Extra1)
                          THEN Dec(Extra1^.TextLines);
                        LineUp(Win,Extra1);
                        x:=Extra1^.CursorY-1;
                        s:=Extra1^.ScreenBuffer[x];
                        while s[length(s)]=#32 do dec(s[0]);
                        Extra1^.CursorX:=length(s)+1;
                        r:=Extra1^.HSlider.acvalue;
                        Extra1^.HSlider.acvalue:=0;
                        IF CheckIfToScrollX(Win,Extra1,TRUE) THEN exit;
                        IF r<>0 THEN
                        BEGIN
                             InvalidateEditorWindow(Win,Extra1);
                             exit;
                        END;
                   END;
                   InvalidateEditorWindow(Win,Extra1);
                   exit;
              END
              ELSE
              BEGIN
                   dec(Extra1^.CursorX);
                   InvalidateEditorLine(Win,s,y+1,Extra1);
                   exit;
              END;
         END;
         kbCtrlIns:
         BEGIN
              r:=CM_COPY;
              WinSendMsg(NIL,POINTER(r),WM_COMMAND,ClientHandle);
         END;
         kbShiftDel:
         BEGIN
              r:=CM_CUT;
              WinSendMsg(NIL,POINTER(r),WM_COMMAND,ClientHandle);
         END;
         kbShiftIns:
         BEGIN
              r:=CM_PASTE;
              WinSendMsg(NIL,POINTER(r),WM_COMMAND,ClientHandle);
         END;
         kbInsert,kbCtrlV:
         BEGIN
              Extra1^.InsertMode:=not(Extra1^.InsertMode);
              IF Extra1^.InsertMode THEN r:=CharHeight
              ELSE r:=2;
              ASM
                  ;Destroy the cursor
                  PUSHL $Win
                  MOV AL,1
                  CALLDLL PMWIN,725  ;WinDestroyCursor
                  ADD ESP,4

                  ;Create the cursor
                  PUSHL 0  ;whole window
                  PUSHL 4  ;CURSOR_SOLID | CURSOR_FLASH
                  PUSHL $r ;Cursorheigth
                  PUSHL _CharWidth
                  PUSHL 40
                  PUSHL 40
                  PUSHL $Win
                  MOV AL,7
                  CALLDLL PMWIN,715  ;WinCreateCursor
                  ADD ESP,28
              END;
              WinShowCursor(1,Win);
         END;
         ELSE exit;
     END; {CASE}
     SetCursor(Win,Extra1);
END;


FUNCTION TEditorApplication.MDIHandleEvent(Win:HWND;Msg:LONGWORD;para1,
                      para2:POINTER;VAR Handled:BOOLEAN;
                      Data:POINTER):LONGWORD;
VAR r:LONGWORD;
    rc:RECTL;
    H:BOOLEAN;
    w:WORD;
    ch:CHAR;
    b:Byte;
    pp:PEditor;
    FrameWin,ScrollWin:HWND;
    ww,ww1:WORD;
    p:POINTER;
    po:points;
    lx,ly,wx,wy:Integer;
Label l,ll,ll1,sel;
BEGIN
     r:=Inherited.MDIHandleEvent(Win,Msg,para1,para2,Handled,Data);
     H:=TRUE;
     r:=0;
     CASE MSG OF
          WM_MOUSEMOVE:
          BEGIN
               IF NewEditorPtr<>0 THEN WinSetPointer(NewEditorPtr,HWND_DESKTOP)
               ELSE IF Not Handled THEN H:=FALSE;
               IF MouseButton1Down THEN goto sel;
          END;
          WM_SIZE:
          BEGIN
               SetSliderValues(Win,Data);
               IF not Handled THEN H:=FALSE;
          END;
          WM_DESTROY:
          BEGIN
               DestroyEditor(Data);
               IF not Handled THEN H:=FALSE;
          END;
          WM_HSCROLL:CheckHScrollBar(Win,para1,para2,Data);
          WM_VSCROLL:CheckVScrollBar(Win,para1,para2,Data);
          WM_SETFOCUS:  {EingabeFocus neu setzen}
          BEGIN
               pp:=Data;
               IF pp^.InsertMode THEN r:=CharHeight
               ELSE r:=2;
               ASM
                  MOV EAX,$Para2
                  CMP EAX,0
                  JE !dc      ;Window is loosing focus

                  ;Window becomes focus --> Create the cursor
                  PUSHL 0  ;whole window
                  PUSHL 4  ;CURSOR_SOLID | CURSOR_FLASH
                  PUSHL $r ;Cursorheigth
                  PUSHL _CharWidth
                  PUSHL 40
                  PUSHL 40
                  PUSHL $Win
                  MOV AL,7
                  CALLDLL PMWIN,715  ;WinCreateCursor
                  ADD ESP,28
               END;
               WinShowCursor(1,Win);
               SetCursor(Win,Data);
               InvalidateWindow(Win);
               goto l;

               ASM
!dc:
                  ;Window is loosing focus --> Destroy the cursor
                  PUSHL $Win
                  MOV AL,1
                  CALLDLL PMWIN,725  ;WinDestroyCursor
                  ADD ESP,4
               END;
l:
          END;
          WM_BUTTON1Up:WinSetCapture(HWND_DESKTOP,0);
          WM_BUTTON1Down,WM_BUTTON1Click:
          BEGIN
               pp:=Data;
               pp^.ErrorMode:=FALSE;
               ClearErrorLine(Win,pp);
               po:=Points(Para1);
               lx:=po.x DIV CharWidth;
               ly:=po.y DIV CharHeight;
               WinQueryWindowrect(rc,Win);
               wx:=(rc.xright-rc.xleft) DIV CharWidth;
               wy:=(rc.ytop-rc.ybottom) DIV CharHeight;
               inc(lx);
               if lx>wx then lx:=wx;
               ly:=wy-ly;
               if ly<1 then ly:=1;
               pp:=Data;
               pp^.SelectColumnStart:=65535;
               pp^.SelectLineStart:=65535;
               pp^.SelectColumnEnd:=65535;
               pp^.SelectLineEnd:=65535;
               pp^.SelectLoAddr:=0;
               pp^.SelectHiAddr:=0;
               IF lx=pp^.CursorX THEN IF ly=pp^.Cursory THEN goto ll;
               pp^.CursorX:=lx;
               pp^.CursorY:=ly;
               SetCursor(Win,pp);
               InvalidateEditorWindow(Win,pp)
ll:
               IF not Handled THEN H:=FALSE;
               IF Msg=WM_BUTTON1DOWN THEN WinSetCapture(HWND_DESKTOP,Win);
          END;
          WM_MOUSEDRAG1:
          BEGIN
sel:
               po:=Points(Para1);
               lx:=po.x DIV CharWidth;
               ly:=po.y DIV CharHeight;
               WinQueryWindowrect(rc,Win);
               wx:=(rc.xright-rc.xleft) DIV CharWidth;
               wy:=(rc.ytop-rc.ybottom) DIV CharHeight;
               inc(lx);
               if lx>wx then lx:=wx;
               ly:=wy-ly;
               if ly<1 then ly:=1;
               pp:=Data;
               IF lx=pp^.CursorX THEN IF ly=pp^.Cursory THEN
                 IF ly<pp^.TextViewY-1 THEN IF ly>1 THEN goto ll1;
               pp^.CursorX:=lx;
               pp^.CursorY:=ly;
               SetCursor(Win,pp);

               ww:=pp^.HSlider.acvalue+pp^.CursorX-1;
               ww1:=pp^.vSlider.acvalue+pp^.CursorY-1;

               IF pp^.SelectLineStart=65535 THEN
               BEGIN
                    pp^.SelectLineStart:=ww1;
                    pp^.SelectAnchorLine:=ww1;
               END;

               IF ww1>=pp^.SelectAnchorLine THEN
               BEGIN
                    pp^.SelectLineEnd:=ww1;
                    pp^.SelectLineStart:=pp^.SelectAnchorLine;
               END;
               ELSE
               BEGIN
                    pp^.SelectLineStart:=ww1;
                    pp^.SelectLineEnd:=pp^.SelectAnchorLine;
               END;

               IF pp^.SelectColumnStart=65535 THEN
               BEGIN
                    pp^.SelectColumnStart:=ww;
                    pp^.SelectAnchorColumn:=ww;
               END;

               IF ww1=pp^.SelectLineStart THEN
               BEGIN
                    IF ww>=pp^.SelectAnchorColumn THEN
                    BEGIN
                        IF ww1=pp^.SelectLineEnd THEN pp^.SelectColumnEnd:=ww;
                        pp^.SelectColumnStart:=pp^.SelectAnchorColumn;
                    END;
                    ELSE
                    BEGIN
                        pp^.SelectColumnStart:=ww;
                        IF ww1=pp^.SelectLineEnd THEN pp^.SelectColumnEnd:=
                               pp^.SelectAnchorColumn;
                    END;
               END;

               IF ww1=pp^.SelectLineEnd THEN IF ww1<>pp^.SelectLineStart THEN
                   pp^.SelectColumnEnd:=ww;

               dec(ww1,pp^.VSlider.AcValue);

               IF ww1>=pp^.TextViewY-1 THEN
               BEGIN
                    LineDown(Win,pp,TRUE);
                    LastDragPos:=para1;
                    DragWindow:=Win;
                    Drag_Mode:=TRUE;
               END
               ELSE
               BEGIN
                    IF ww1=0 THEN
                    BEGIN
                         LineUp(Win,pp);
                         LastDragPos:=para1;
                         DragWindow:=Win;
                         Drag_Mode:=TRUE;
                    END
                    ELSE Drag_Mode:=FALSE;
               END;
               InvalidateEditorWindow(Win,pp);
ll1:
               IF not Handled THEN H:=FALSE;
          END;
          ELSE IF not Handled THEN H:=FALSE;
     END; {Case}
     Handled:=H;
     MDIHandleEvent:=r;
END;

BEGIN
END.