(****************************************************************************

              P32IDEU - 32bit Pascal Compiler with IDE

 ---------------------------------------------------------------------------
                   Michael Goddard - magnesium@hehe.com (IDE)
                       Johan Prins - jprins@knoware.nl (P32)
 ==========================================================================
 IDE Code unit (v0.02c)                                       P32IDE (c)'98
 http://www.cryogen.com/p32
 --------------------------------------------------------------------------
 Note: This is a very early version so be nice :) Remembering constructive
       critisism is best taken with the source to fix it. (If you know how)

 ToDo: Rewrite Text Highlighting to be faster & do ()[]'s
       Text Selecting / Copy / Paste . . .

 Idea: Automatic Comment remover which DOESN'T Remove Compiler directives!
       Expression evaluator can use Constants from programs
       A Fon't Loader to load FT & RAW fonts (Maybe?)
       Type ahead for commonly used things, like a ; after a )
       Runtime error recovery (Clear enough memory so at RunError in
                               P32_ERR, it calls ProcessEvents)

 Type inheritance tree
---------------------------

  WindowType
   |
   +-- Dialog  (Contains a Collection of Text/Button/TextBox.. Objects which
   |            all inherit a basic DialogObjectType so dif. obj's can be called
   |            by same calling thing, remember inherited paint; etc.
   +-- TextWindow
           |
           + SourceWindow
           |
           + HelpWindow (Not done yet)

 Object Structure
-------------------

  IDE_Desktop                   (1 Object)
   |
   +-- IDE_WindowType           (x Number of Windows, type above)
          |
          +-- IDE_ItemBaseType  (x Number of items)

  Method calls are passed down the tree to the active object that uses
 them, like KeyEvent or Paint.

*)

{-$DEFINE MemTrick} {- causes problems but makes better use of memory -}
                   {- The Heap-End needs to be patched and I'm not sure how -}
{-$DEFINE Debug}
{-$DEFINE FrontWindowShadowOnly}
{$DEFINE NoBlockHilite}
{$DEFINE P32IDE}

{$IFDEF P32IDE}
Unit P32IDEU;

Interface

Uses Objects;

Const
   P32IDE_Ver = 'v0.02b';

Procedure ShowERROR(nLine: Longint;St: String);
Procedure ProcessEvents;
Procedure IDE_Init;
Procedure IDE_Done;
Procedure CompileStatus_NewFile(St: String);
Procedure CompileStatus_cLineSet(l: Longint);

{$ELSE}
Uses Dos, Crt, MMouse, Objects, Key_Unit;
{$ENDIF}

Const MaxIDEFiles = 2048;

Var
 {*** johan}
 textsegment: word;

 {- IDE variables and things like colours -}
 IDE: Record
  Quit: Boolean;
  TabSize: Byte;
  SmartTab: Boolean;
  SyntaxHighlight: Boolean;
  BlockHighlight: Boolean;
  QuickHighlight: Boolean;
  DoubleClick: Longint; {- miliseconds for doubleclick -}
  SmallFont: Boolean;
  NestComment: Boolean;
  c: Record
   Error, BlockHi, BlockSel, Button, ButtonH: Byte;
   Syntax: Record
    none, Comment, Reserved, Reserved2, Identifiers, Symbols, STrings, Numbers, AsmSrc: Byte;
   end;
  end;
  P32: Record
   nNoname: Longint;
   Noname: STring[8];
   Ext: String[3];
  end;
 end;


{+--------------------------------------------------------------------------+}
{|                                                                          |}
{|    Desktop Object Definitions                                            |}
{|                                                                          |}
{+--------------------------------------------------------------------------+}
Type
 KeyType = record Ch: Char;Shift, Ctrl, Alt, Ext: Boolean;end;

Const tMenuMax = 10;
      tSubMenuMax = 22;
Type
 pMenuType = ^MenuType;
 MenuType = Record
  NameSt: String[20];
  HelpSt: String[70];
  Accel: KeyType;
  cItem: Integer;
  SubMenu: Array[0..tSubMenuMax] of Record NameSt: String[40];
                                  Accel: KeyType;
                                  ID: Word;
                                  HelpSt: String[70];
                                 end;
 end;
 IDE_DesktopType = Object

  IDE_BottomHelpST: String;
  Menu_cItem: Word; {- 0=NoneSelected else Selected -}
  cSubMenu: Record
   nItem: Word; {number of items}
   sX, eX: Integer; {Start-X & EndX}
  end;
  {tMenu: tCollection;}
  tMenu: Array[1..tMenuMax] of MenuType;

   tWin: tCollection;
   DontDrawNext_B: Boolean;

   Constructor Init;
   Destructor Done;
   Procedure Paint;
   Procedure QuickPaint;
   Procedure MenuPaint;
   Procedure ProcessMouseEvent;
   Procedure ProcessKeyEvent;
   Procedure MenuHandler(cKey: KeyType; mX, mY: Integer;mLeft, mMiddle, mRight: Boolean);
   Procedure IDE_BottomHelp(St: String);
   Procedure DontDrawNext;
 end;
Var
 IDE_Desktop: ^IDE_DesktopType;

 Procedure cmSend(cm: word);
 var cmSend_St: String;

Const
 cm_NewEdit     = $1000;  { These are used to call whatever code does them }
 cm_OpenEdit    = $1001;
 cm_Exit        = $0001;
 cm_LoadEdit    = $1002;
 cm_SaveEdit    = $1003;
 cm_SaveAsEdit  = $1004;
 cm_LoadFile    = $1005; {- LoadEdit on the first window -}

 cm_UserScreen  = $6000;
 cm_UserWindow  = $6001;
 cm_DOSShell    = $6002;
 cm_AboutWindow = $6003;
 cm_ContribWindow = $6004;

 cm_Compile     = $5000;
 cm_Build       = $5001;
 cm_Run         = $5002;
 cm_Link        = $5003;
 cm_InfoBOX     = $500F;

 cm_ASCIIWin    = $A003;
 cm_CALCWin     = $A004;

 cm_SyntaxHighlightToggle = $A000;
 cm_BlockHighlightToggle  = $A001;
 cm_HeightToggle          = $A002;


{$IFDEF P32IDE}
Implementation
{$ENDIF}


{$IFDEF P32IDE}
Uses Dos, Crt, MMouse, Key_Unit, P32_ERR, P32, P32_CFG, P32_ASM, P32_SCAN, P32_SYMB, P32_CODE, P32_PREP;
{$ENDIF}

Procedure Beep;begin;sound(523);delay(5);nosound;end;
Procedure Beep2;begin;sound(1000);delay(5);nosound;end;

{$IFDEF PMODE}
Const IDE_MaxTextSize = 65520; {- Maximum SourceWindow size -}
{$ELSE}
Const IDE_MaxTextSize = 32768; {- Maximum SourceWindow size -}
{$ENDIF}


Const
 IDE_cDesktop  = $89;
 IDE_cMenu     = $70;
 IDE_cMenuH    = $24;

 IDE_cWinFrame = $1F;
 IDE_cWinIcon  = $1A;
 IDE_cWinSize  = $1A;
 IDE_cWinSlide = $31;
 IDE_cWinBack  = $17;
 IDE_ScrWidth  = 80;
 IDE_ScrHeight = 23;

 IDE_cDWinBack  = $7F;
 IDE_cDWinFrame = $7F;
 IDE_cDWinIcon  = $7A;
 IDE_cDWinSize  = $7A;
 IDE_cDWinSlide = $3A;


Const
 NoKey: KeyType =(Ch:#0;Shift:False;Ctrl:False;Alt:False;Ext:False);
 Space: KeyType =(Ch:#32;Shift:False;Ctrl:False;Alt:False;Ext:False);
Type p64kArray = ^t64kArray;t64kArray= Array[0..65520] of byte;

 Function NoKeyP(k: KeyType):Boolean;begin;if (k.Ch=#0)and(k.Ext=False) then NoKeyP:= True else NoKeyP := False;end;
 function IDE_MouseX: Integer;begin;IDE_MouseX := MMouse_GetX div 1;end;
 function IDE_MouseY: Integer;begin;IDE_MouseY := MMouse_GetY div 1;end;
 function IDE_MouseXL: Integer;begin;IDE_MouseXL := MMouse_GetXL div 1;end;
 function IDE_MouseYL: Integer;begin;IDE_MouseYL := MMouse_GetYL div 1;end;
 function IDE_MouseL: Boolean;begin;IDE_MouseL := MMouse_ButtonLeft;end;
 function IDE_MouseR: Boolean;begin;IDE_MouseR := MMouse_ButtonRight;end;
 function IDE_MouseMoved: boolean;begin;IDE_MouseMoved := MMouse_Moved;end;
 procedure IDE_HighBack;assembler;asm;Mov Ax, 1003h;Mov Bl, 0;Int 10h;end;
 function UCase(St:String):String;var i:byte;begin;for i:=1 to length(St) do St[i] := UpCase(St[i]);UCase := St;end;
 Procedure IDE_GetKey(var k: KeyType);begin;k.Ch    := Readkey; k.Ext   := False;
     if k.Ch = #0 then begin;k.Ext := True;k.Ch := Readkey;end; k.Shift := (Key_lShift or Key_rShift);
     k.Alt   := Key_Alt; k.Ctrl  := Key_Ctrl; end;

 Function GetLTime: Longint;
 var w1, w2, w3, w4: word;
 begin
  GetTime(w1, w2, w3, w4);
  GetLTime := longint(w4) + longint(w3) * longint(100) + longint(w2) * longint(6000) + longint(w1) * longint(360000);
 end;

{* Check's if a file exists *}
Function FileExists(FileName: String): Boolean;
Var F:file;
Begin;
 {$I-} {- Turn OFF I/O checking so TP doesn't give us an error -}
  Assign(F,FileName); {- Try to open the file, read-only mode -}
  FileMode:=0;
  Reset(F);
  Close(F);
 {$I+}
 FileExists:=(IOResult=0)and(FileName<>''); {- Check if we got an error -}
 FileMode:=2; {- Set everything back to normal -}
End;

Procedure DeleteFile(St: String);Var Fh: File;Begin;{$I-}Assign(Fh, St);Reset(Fh, 1);Erase(Fh);{$I+}end;
Procedure RenameFile(St,StT: String);var Fh: File;begin If not FileExists(StT) then Begin;{$I-}Assign(Fh, St);Rename(Fh, StT);
          {$I+}end;end;

{* Check's if a directory exists *}
Function DirExists(DirName: String): Boolean;
var DirInfo: SearchRec;
begin
 FindFirst(DirName, Directory, DirInfo);
 if (DirInfo.Name = '') or (DirInfo.Attr and VolumeID > 0) then
    DirExists := False else DirExists := True;
end;


Const
 IdenSt: String[60] = ('!@%^&*()-=+/.,;:<>?|\[]'#0#32#255#10#13'{}'#34#39);

 {JOHAN}

 ResWord_n = 63;
 ResWord: Array[0..ResWord_n] of String[16] =(
  {- Line MUST be in order -}  'BEGIN','ASM','RECORD','CASE','END',
  'AND','ARRAY','CONST','CONSTRUCTOR','DESTRUCTOR','DIV','DO',
  'DOWNTO','ELSE','EXPORTS','FILE','FOR','FUNCTION','GOTO','IF',
  'IMPLEMENTATION','IN','INHERITED','INLINE','INTERFACE','LABEL',
  'LIBRARY','MOD','NIL','NOT','OBJECT','OF','OR','PACKED','PROCEDURE',
  'PROGRAM','REPEAT','SET','SHL','SHR','STRING','THEN','TO','TYPE',
  'UNIT','UNTIL','USES','VAR','WHILE','WITH','XOR',
  {- Things that go at the end of a line, used less -}
  'ABSOLUTE','ASSEMBLER','EXPORT','EXTERNAL','FAR','FORWARD','INDEX',
  'INTERRUPT','NEAR','PRIVATE','PUBLIC','RESIDENT','VIRTUAL');


 Res2Word_n = 10;
 Res2Word: Array[0..Res2Word_n] of String[16] =(
  {- Not really Reserved words but it's nice to hilight them -}
  'WRITE','WRITELN','INC','DEC','BYTE','WORD','DWORD','LONGINT','INTEGER',
  'BOOLEAN','CHAR');


Var
 Sym: Record
  Filled: Boolean;
  LastProgST: String;
  cLine, tLine: Longint;
 end;

 {- Screen variables, allows upto 80x50 -}
 IDE_Screen: Record
  Buffer: Array[0..49+1,0..79] of record Ch,Col: Byte;end;
  CPX, CPY: Integer;
  SwapBuffer: Pointer;  {- Buffer to saved display page -}
  SwapBufferSize: Word;
  SwapCx, SwapCy: Byte;
  SwapVM: Byte;
  ScrWidth, ScrHeight: Word;
  tIns: Boolean;
 end;
 Const HexStr: String[16] =('0123456789ABCDEF');

 Procedure IDE_WriteXYC_Ch(X,Y:Integer; C:Char;Col:Byte); assembler;
{*** johan}
   asm
      mov  bx, word ptr [x]
      mov  ax, word ptr [y]
      cmp  bx, 0
      jl   @exit
      cmp  ax, 0
      jl   @exit
      cmp  bx, word ptr [IDE_Screen.ScrWidth]
      jge  @exit
      cmp  ax, word ptr [IDE_Screen.ScrHeight]
      jge   @exit

      mov  cl, byte ptr [c]
      mov  ch, byte ptr [col]

      mov  dl, 160
      mul  dl
      shl  bx, 1
      add  ax, bx
      mov  di, offset [IDE_Screen.Buffer]
      add  di, ax
      mov  word ptr [di], cx
 @exit:
{  if (X<0) or (Y<0) or (X>IDE_Screen.ScrWidth-1) or (Y>IDE_Screen.ScrHeight-1) then exit;
  IDE_Screen.Buffer[Y, X].Ch  := Ord(Ch);
  IDE_Screen.Buffer[Y, X].Col := Col;}
end;

procedure IDE_WriteXYC_ChNB(X,Y:Integer;C:Char;Col:Byte); assembler;
{*** johan}
{hmmm....this one is never used....}
{*** Michael - it's meant to be used in dialog box texts, and it is now}
{              how bout a chat! via the comment statements ??? >;-| }
   asm
      mov  bx, word ptr [x]
      mov  ax, word ptr [y]
      cmp  bx, 0
      jl   @exit
      cmp  ax, 0
      jl   @exit
      cmp  bx, word ptr [IDE_Screen.ScrWidth]
      jge  @exit
      cmp  ax, word ptr [IDE_Screen.ScrHeight]
      jge   @exit

      mov  cl, byte ptr [c]
      mov  ch, byte ptr [col]
      and  ch, $F

      mov  dl, 160
      mul  dl
      shl  bx, 1
      add  ax, bx
      mov  di, offset [IDE_Screen.Buffer]
      add  di, ax
      {** Michael, Johan, you forgot a +1 to access the colour byte!}
      mov  dh, byte ptr [di+1]
      and  dh, $F0
      add  ch, dh
      mov  word ptr [di], cx
 @exit:
{  if (X<0) or (Y<0) or (X>IDE_Screen.ScrWidth-1) or (Y>IDE_Screen.ScrHeight-1) then exit;
  IDE_Screen.Buffer[Y, X].Ch  := Ord(Ch);
  IDE_Screen.Buffer[Y, X].Col := (Col and $F) + (IDE_Screen.Buffer[Y, X].Col and $F0);}
end;

procedure IDE_Grey(X,Y:Integer); assembler;
{*** johan}
   asm
      mov  bx, word ptr [x]
      mov  ax, word ptr [y]
      cmp  bx, 0
      jl   @exit
      cmp  ax, 0
      jl   @exit
      cmp  bx, word ptr [IDE_Screen.ScrWidth]
      jge  @exit
      cmp  ax, word ptr [IDE_Screen.ScrHeight]
      jge   @exit

      mov  ch, $07;

      mov  dl, 160
      mul  dl
      shl  bx, 1
      add  ax, bx
      mov  di, offset [IDE_Screen.Buffer]
      add  di, ax
      mov  byte ptr [di+1], ch
 @exit:
{  if (X<0) or (Y<0) or (X>IDE_Screen.ScrWidth-1) or (Y>IDE_Screen.ScrHeight-1) then exit;
  IDE_Screen.Buffer[Y, X].Col := $07;}
end;

 Procedure IDE_SetBC(X,Y:Integer;c: byte);
 begin
  if (X<0) or (Y<0) or (X>IDE_Screen.ScrWidth-1) or (Y>IDE_Screen.ScrHeight-1) then exit;
  IDE_Screen.Buffer[Y, X].Col := (c Shl 4) + (IDE_Screen.Buffer[Y, X].Col and $F);
 end;

 Procedure IDE_WriteXYC(X, Y: integer;const st: String;Col: Byte);
 {***johan}
 var i, c: byte;
     _tilda, _excl:word;
 begin
  c := 0;
  if St[0] > #0 then
    begin
      for i:=1 to ord(St[0]) do
         begin
           _tilda:=Pos(St[i+1], HexStr);
           if (St[i] = '~') and (_tilda > 0) then
             begin
               Col := (Col and $F0) + (_tilda - 1);
               inc(i);
             end
           else
             begin
               _excl:=Pos(St[i+1], HexStr);
               if (St[i] = '!') and (_excl > 0) then
                 begin
                   Col := (Col and $0F) + (_excl-1) * $F;
                   Inc(i);
                 end
               else
                 begin;
                   IDE_WriteXYC_Ch(X+c, Y, St[i], Col);inc(c);
                 end;
             end;
            if i >= ord(st[0]) then break;
         end;
    end;
end;

 Procedure IDE_WriteXYC_NB(X, Y: integer;const st: String;Col: Byte);
 var i, c: byte;
     _tilda, _excl:word;
 begin
  c := 0;
  if St[0] > #0 then
    begin
      for i:=1 to ord(St[0]) do
         begin
           _tilda:=Pos(St[i+1], HexStr);
           if (St[i] = '~') and (_tilda > 0) then
             begin
               Col := (Col and $F0) + (_tilda - 1);
               inc(i);
             end
           else
            IDE_WriteXYC_ChNB(X+c, Y, St[i], Col);inc(c);
            if i >= ord(st[0]) then break;
         end;
    end;
end;

 Procedure IDE_WriteXY(X, Y: integer;const st: String;Col: Byte);
 var i: byte;
 begin
  if St[0] > #0 then
      for i:=1 to ord(St[0]) do
          IDE_WriteXYC_Ch(X+i-1, Y, St[i], Col);
 end;

 {- Returns the length of a string removing colour information -}
 Function LengthC(St: String): Byte;
 begin
  if (Pos('~', St) > 0) then
  repeat
   Delete(St, Pos('~', St), 2);
  until (Pos('~', St) = 0);
  if (Pos('!', St) > 0) then
  repeat
   Delete(St, Pos('!', St), 2);
  until (Pos('!', St) = 0);
  LengthC := Length(St);
 end;

 {- Returns the length of a string removing tilda information -}
 Function LengthT(St: String): Byte;
 begin
  if (Pos('~', St) > 0) then
  repeat
   Delete(St, Pos('~', St), 1);
  until (Pos('~', St) = 0);
  LengthT := Length(St);
  if St = '' then LengthT := 0;
 end;

 {- Converts Tilda's to Colour-Strings -}
 Function TildaToC(St: String): String;
 var i: byte; InCc: Boolean;St2: String;
 begin
  i := 1; InCc := False;
  repeat
   if St[i] = '~' then
    begin
     InCc := not InCc;
     if InCc then
      Insert(HexStr[1+(IDE_cMenuH and $F)], St, i+1)
     else
      Insert(HexStr[1+(IDE_cMenu and $F)], St, i+1);

     Inc(i);
    end;
    Inc(i);
  until i >= Length(St);
  TildaToC := St;
 end;

{ procedure IDE_HeapShrink; {- free up all unused heap (+1 for safety in 8-byte allocs) -}
{ var _bx: word;
 begin
{   _bx := memw[seg(heapptr) : ofs(heapptr) + 2] - prefixseg + 1;
   {_bx := seg(HeapPtr^) + (ofs(HeapPtr^)+15) div 16 - prefixseg;}
{   asm
    Mov Bx, PrefixSeg
    Mov Es, Bx
    Mov Bx, _bx
    Mov Ah, 04Ah
    Int 21h
   end;
 end;

 procedure IDE_Heapexpand; {- reclaim unused heap -}
{ var _bx: Word;
{ begin
   _bx := memw[seg(heapend) : ofs(heapend) + 2] - prefixseg;
   {_bx := seg(HeapEnd^) - prefixseg;}
{   asm
    Mov Bx, PrefixSeg
    Mov Es, Bx
    Mov Bx, _bx
    Mov Ah, $4A
    Int 21h
   end;
 end;
}
 var IDE_SaveHeap_bx, IDE_SaveHeap_dx: word;
 procedure IDE_SaveHeap;
 begin
{$IFNDEF PMODE}
   IDE_SaveHeap_bx := memw[seg(heapptr) : ofs(heapptr) + 2];
   IDE_SaveHeap_dx := memw[seg(heapptr) : ofs(heapptr) + 0];
{$ENDIF}
 end;
 procedure IDE_RestoreHeap;
 begin
{$IFNDEF PMODE}
   memw[seg(heapptr) : ofs(heapptr) + 2] := IDE_SaveHeap_bx;
   memw[seg(heapptr) : ofs(heapptr) + 0] := IDE_SaveHeap_dx;
{$ENDIF}
 end;

Procedure IDE_HideCursor; Assembler;Asm;Mov Ax, 0100h; Mov Cx, 2607h;Int 10h;end;
Procedure IDE_ShowCursor; Assembler;Asm;Mov Ax, 0100h;Mov Cx, 0506h; Int 10h;end;
Procedure IDE_ShowCursorINS; Assembler;Asm;Mov Ax, 0100h;Mov Cx, 0007h; Int 10h;end;

 Procedure IDE_UpdateVideo;
 begin
  MMouse_Hide;
   {**** johan}

   {Case MemW[$40:$63] of
    $3B4: }
  Move(IDE_Screen.Buffer[0,0].Ch, Mem[textsegment:MemW[Seg0040:$4E]], IDE_Screen.SwapBufferSize);
  { else
     Move32(IDE_Screen.Buffer[0,0].Ch, Mem[$B800:MemW[$40:$4E]], IDE_Screen.SwapBufferSize);
   end;}
  MMouse_Show;

   if (IDE_Screen.CPX >= 0) and (IDE_Screen.CPX < IDE_Screen.ScrWidth) and
      (IDE_Screen.CPY >= 1) and (IDE_Screen.CPY < IDE_Screen.ScrHeight-1) then
   begin
    GotoXy(IDE_Screen.CPX+1, IDE_Screen.CPY+1);
    if IDE_Screen.tIns then IDE_ShowCursorINS else IDE_ShowCursor;
   end
   else
    IDE_HideCursor;
 end;

Procedure IDE_Reset;
begin
 MMouse_Hide;
 if IDE.SmallFont then TextMode(CO80 + Font8x8) else TextMode(CO80);
 IDE_HighBack;
 MMouse_Show;
 if IDE.SmallFont then
  IDE_Screen.SwapBufferSize := MemW[Seg0040:$4C]*2
 else
  IDE_Screen.SwapBufferSize := MemW[Seg0040:$4C];

  IDE_Screen.ScrWidth := MemW[Seg0040:$4A];
  if IDE.SmallFont then
   IDE_Screen.ScrHeight := 50
  else
   IDE_Screen.ScrHeight := (MemW[Seg0040:$4C] div (MemW[Seg0040:$4A]*2));

end;

Procedure IDE_SwapVideoOut;
begin
 TextMode(CO80);
 MMouse_Hide;
  Asm
   Mov Al, IDE_Screen.SwapVM
   Mov Ah, 0h
   Int 10h
  end;

{**** johan}
  {Case MemW[$40:$63] of
   $3B4: }
  Move(IDE_Screen.SwapBuffer^, Mem[textsegment:MemW[Seg0040:$4E]], IDE_Screen.SwapBufferSize);
  {else
    Move32(IDE_Screen.SwapBuffer^, Mem[$B800:MemW[$40:$4E]], IDE_Screen.SwapBufferSize);
  end;}
  GotoXy(IDE_Screen.SwapCx, IDE_Screen.SwapCy);
end;

Procedure IDE_SwapVideoIn;
begin
  IDE_Screen.SwapCx := WhereX;
  IDE_Screen.SwapCy := WhereY;

{**** johan}
  {Case MemW[$40:$63] of
   $3B4: }
  Move(Mem[textsegment:MemW[Seg0040:$4E]], IDE_Screen.SwapBuffer^, IDE_Screen.SwapBufferSize);
  {else
    Move32(Mem[$B800:MemW[$40:$4E]], IDE_Screen.SwapBuffer^, IDE_Screen.SwapBufferSize);
  end;}
  Asm
   Mov Ax, 0F00h
   Int 10h
   Mov IDE_Screen.SwapVM, Al
  end;
 if IDE.SmallFont then TextMode(CO80 + Font8x8);
 IDE_HighBack;
 MMouse_Show;
end;

Procedure IDE_Init;
begin
Write('*');
  if IDE.SmallFont then
   IDE_Screen.SwapBufferSize := MemW[Seg0040:$4C]*2
  else
   IDE_Screen.SwapBufferSize := MemW[Seg0040:$4C];
Write('*');
  GetMem(IDE_Screen.SwapBuffer, IDE_Screen.SwapBufferSize);
Write('*');
  IDE_SwapVideoIn;
Write('*');
  IDE_Screen.ScrWidth := MemW[Seg0040:$4A];
Write('*');
  if IDE.SmallFont then
   IDE_Screen.ScrHeight := 50
  else
   IDE_Screen.ScrHeight := (MemW[Seg0040:$4C] div (MemW[Seg0040:$4A]*2));
Write('*');

  if IDE_Screen.ScrHeight > 50 then IDE_Screen.ScrHeight := 50;
Write('*');

  New(IDE_Desktop, init);
Write('*');
 end;

Procedure IDE_Done;
begin
  Dispose(IDE_Desktop, done);
  IDE_SwapVideoOut;
  FreeMem(IDE_Screen.SwapBuffer, IDE_Screen.SwapBufferSize);
end;




{+--------------------------------------------------------------------------+}
{|                                                                          |}
{|    Window/Desktop Objects                                                |}
{|                                                                          |}
{+--------------------------------------------------------------------------+}

Type
 pIDE_WindowType = ^IDE_WindowType;
 IDE_WindowType = Object
  Xo, Yo: Integer;
  Xs, Ys: Word;
  sXo, sYo: Integer; { Stored X & Y coords }
  sXs, sYs: Word;
  sDblClick_Time: Longint;

  {- Source windows can be compiled -}
  ID: (_NotSource, _Source);

  {- Title String -}
  Title, FileTitle: String;
  {- Colours -}
  cWinFrame, cWinIcon, cWinSize, cWinSlide, cWinBack, cText: Byte;
  {- Cursor Positions -}
  CPX, CPY: Integer;
  { Internal variables used to communicate between functions }
  Moving: Boolean; { Window is being moved or resized }
  MouseEvent_Done: Boolean;
  Modal: Boolean;

  SizeAble, Maximised: Boolean;
  {- For SourceWin - MUST be here or it can't be disposed of, blame TP7 -}
  pText: p64kArray; {- Pointer to Text -}
  pTextUSE: Boolean;

   Constructor Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
   Destructor Done;
   Procedure Paint; virtual;
   Function InFront: Boolean;
   Procedure Maximise;

   Procedure MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
   Procedure KeyEvent(Key: KeyType); virtual;
   {- Called b4 window is closed -}
   Procedure CloseWin; virtual;
 end;

 pIDE_DialogWindowType = ^IDE_DialogWindowType;
 IDE_DialogWindowType = Object(IDE_WindowType)

   tItem: tCollection; { Collection of TextBox/Buttons/Text . . . }

   Constructor Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
   Procedure Paint; virtual;
   Procedure KeyEvent(Key: KeyType); virtual;
   Procedure MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
 end;

 pIDE_TextWindowType = ^IDE_TextWindowType;
 IDE_TextWindowType = Object(IDE_WindowType)
   { If window has been modified }
   Modified: Boolean;

   Constructor Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
   Procedure Paint; virtual;
 end;

 pIDE_UserWindowType = ^IDE_UserWindowType;
 IDE_UserWindowType = Object(IDE_TextWindowType)

   vXo, vYo: integer;

   Procedure MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
   Constructor Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
   Procedure Paint; virtual;
 end;

 HiLiteBlockType = Record
  bt : (_none, _String1, _String2, _Comment1, _Comment2);
  _AsmSrc: Boolean;
  bNestLvl: Integer;
 end;

 pIDE_SourceWindowType = ^IDE_SourceWindowType;
 IDE_SourceWindowType = object(IDE_TextWindowType)

  pTextSize: Longint;
  pTextPos: Longint;
  pTextCX, pTextCY: Integer;
  pTextCXMax, pTextCYMax: Integer;
  pTextSX, pTextSY: Integer;
  tIns: Boolean; {- InsertMode -}
  pTextSelStart, pTextSelEnd: Longint;
  pTextSel: Boolean;

  InPaint: Boolean;

  pTextHiStart, pTextHiEnd, pTextHiFirst: HiLiteBlockType; {- Used for quick Syntax Hilite -}
  PaintWinOnMove: Boolean;
  pSyntaxHighlight: Boolean;


  Constructor Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
  Destructor Done; virtual;
  Procedure Paint; virtual;
  Procedure MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
  Procedure KeyEvent(Key: KeyType); virtual;
  Procedure UpdateCP;
  Procedure UpdateCPMove;
  Procedure ShowCursorST;
  Procedure CalcTextHI;
  Function CalcTextPos(cx, cy: integer): Longint;
  Function StringAT(cx, cy: integer): String;
  Procedure LoadFile(St: String);
  Procedure SaveFile(St: String);
  Procedure InsertFile(St: String);
 end;



{---------------------------------------------------------------------------

              Item Objects, that go in the windows

---------------------------------------------------------------------------}
{ IDE_DialogWindowType Uses them }
Type
 pIDE_ItemBaseType = ^IDE_ItemBaseType;
 IDE_ItemBaseType = Object
  wXo, wYo: Integer; {- Parent Window's Position - for painting -}
  Xp, Yp: Integer;
  Xs, Ys: Word;
  iSt, tSt: String;
  ItemExit, ItemUpdate: Boolean;

  Constructor init(X1, Y1, X2, Y2: Integer; nSt: String);
  Destructor Done; virtual;
  Procedure Paint; virtual;
  Procedure MouseOn(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
  Procedure KeyOn(Key: KeyType); virtual;
 end;

constructor IDE_ItemBaseType.init(X1, Y1, X2, Y2: Integer; nSt: String);
begin
 Xp := X1; Yp := Y1; if X2>0 then Xs:=X2 else Xs:=0; if Y2>0 then Ys:=Y2 else Ys:=0;
 iSt := nSt; ItemExit := False; ItemUpdate := True;
end;

Destructor IDE_ItemBaseType.done;
begin
end;

Procedure IDE_ItemBaseType.Paint;
begin
 IDE_Screen.CPX := $FF; IDE_Screen.CPY := $FF;
end;

Procedure IDE_ItemBaseType.MouseOn(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
begin
end;

Procedure IDE_ItemBaseType.KeyOn(Key: KeyType);
begin
end;

Type
 pIDE_ItemLabelType = ^IDE_ItemLabelType;
 IDE_ItemLabelType = Object(IDE_ItemBaseType)

  Procedure Paint; virtual;
 end;

Procedure IDE_ItemLabelType.Paint;
begin
  IDE_WriteXYC(wXo+Xp, wYo+Yp, iSt, $7F);
  IDE_Screen.CPX := $FF; IDE_Screen.CPY := $FF;
  ItemUpdate := False;
end;



Type
 pIDE_ItemTextType = ^IDE_ItemTextType;
 IDE_ItemTextType = Object(IDE_ItemBaseType)
  iSt_cPos, iSt_sPos: Integer;
  pSt: Pointer;

  Constructor init(X1, Y1, X2, Y2: Integer; p: Pointer; ntSt: String);
  Destructor Done; virtual;
  Procedure Paint; virtual;
  Procedure KeyOn(Key: KeyType); virtual;
 end;

Constructor IDE_ItemTextType.init(X1, Y1, X2, Y2: Integer; p: Pointer; ntSt: String);
begin
 pSt := p; iSt_cPos := 0; iSt_sPos := 0; tSt := ntSt;
 ItemExit := False; ItemUpdate := False;
 Inherited Init(x1, y1, x2, y2, '');
end;

Procedure IDE_ItemTextType.Paint;
var i: integer;
begin
  IDE_WriteXYC(wXo+Xp, wYo+Yp-1, tSt, $7F);
  IDE_Screen.CPX := $FF; IDE_Screen.CPY := $FF;

 if iSt_cPos > Length(iSt) then iSt_cPos := Length(iSt);

 iSt_sPos := 0;
 if (iSt_cPos >= Xs-1) then iSt_sPos := iSt_cPos - Xs+1;

 if pSt <> nil then Move(pSt^, iSt, 256);

  for i:=0 to Xs-1+1 do
   IDE_WriteXYC_Ch(wXo+Xp+i, wYo+Yp, ' ', $1F);

  for i:=1 to Xs-1 do
   if i<=Length(iSt) then
   IDE_WriteXYC_CH(wXo+Xp+i, wYo+Yp, iSt[iSt_sPos+i], $1F);

 IDE_Screen.CPX := (iSt_cPos-iSt_sPos)+wXo+Xp+1; IDE_Screen.CPY := wYo+Yp;

end;

Procedure IDE_ItemTextType.KeyOn(Key: KeyType);
var i: word;
begin
 if pSt <> nil then Move(pSt^, iSt, 256);

 if (not Key.Alt) and (not Key.Ctrl) and (not Key.Ext) then
 Case Key.Ch of
  #13: begin
        if FileExists(iSt) then ItemExit := True else
        if DirExists(iSt) then ItemUpdate := True else ItemExit := True;
       end;
  #27: begin;ItemExit:=True;iSt:='';end;
   #8: if iSt<>'' then begin;Delete(iSt, iSt_cPos, 1);
       if iSt_cPos>0 then Dec(iSt_cPos);end;
  else
   begin;Insert(Key.Ch, iSt, iSt_cPos+1);inc(iSt_cPos);end;
 end
 else
 if (not Key.Alt) and (not Key.Ctrl) and (Key.Ext) then
 Case Key.Ch of
  'K' : if iSt_cPos>0 then Dec(iSt_cPos);
  'M' : if iSt_cPos<Length(iSt) then Inc(iSt_cPos);
  'S' : if iSt<>'' then Delete(iSt, iSt_cPos+1, 1);

 end;

 if pSt <> nil then Move(iSt, pSt^, 256);
end;


Destructor IDE_ItemTextType.Done;
begin
end;

Type
 pIDE_ButtonType = ^IDE_ButtonType;
 IDE_ButtonType = object(IDE_ItemBaseType)
  IsPressed: Boolean;
  IsDown: Boolean;

  Constructor init(X1, Y1, X2, Y2: Integer; St: String);
  Destructor Done; virtual;
  Procedure Paint; virtual;
  Procedure KeyOn(Key: KeyType); Virtual;
  Procedure MouseOn(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
 end;

Constructor IDE_ButtonType.init(X1, Y1, X2, Y2: Integer; St: String);
begin
 IsPressed := False; IsDown := False;
 Inherited init(x1, y1, x2, y2, St);
end;

Destructor IDE_ButtonType.done;
begin
 inherited done;
end;

Procedure IDE_ButtonType.Paint;
var i: integer;
begin
 if IsDown then
 begin
  for i:=0 to Xs do
   IDE_WriteXYC(wXo+Xp+i+1, wYo+Yp, ' ', IDE.c.Button);
   IDE_WriteXYC(wXo+Xp+1+((1+Xs-LengthT(iSt)) div 2), wYo+Yp, TildaToC(iSt), IDE.c.Button);
 end
 else
 begin
  for i:=0 to Xs do
   IDE_WriteXYC(wXo+Xp+i, wYo+Yp, ' ', IDE.c.Button);

  for i:=1 to Xs+1 do
   IDE_WriteXYC(wXo+Xp+i, wYo+Yp+1, 'ß', $70);

  IDE_WriteXYC(wXo+Xp+Xs+1, wYo+Yp, 'Ü', $70);


   IDE_WriteXYC(wXo+Xp+0+((1+Xs-LengthT(iSt)) div 2), wYo+Yp, TildaToC(iSt), IDE.c.Button);
 end;

end;

Procedure IDE_ButtonType.KeyOn(Key: KeyType);
begin
 beep2;
end;

Procedure IDE_ButtonType.MouseOn(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
begin
 if mLeft then
  begin
   IsDown := True;
   While IDE_MouseL do
   begin
    IDE_Desktop^.QuickPaint;
    While not IDE_MouseMoved do;

    if (IDE_MouseX>=wXo+Xp) and (IDE_MouseX<=wXo+Xp+Xs) and
       (IDE_MouseY>=wYo+Yp) and (IDE_MouseY<=wYo+Yp+Ys) then
        IsDown := True else IsDown := False;

   end;
   IsPressed := IsDown;
   IDE_Desktop^.QuickPaint;
  end;
end;



Type
 pIDE_FileTextType_pFiles = Array[0..MaxIDEFiles] of String[12];
 pIDE_FileTextType = ^IDE_FileTextType;
 IDE_FileTextType = Object(IDE_ItemBaseType)
  iSt_cPos, iSt_sPos: Integer;
  pSt: Pointer;
  FSPC: String;
  pFiles: pIDE_FileTextType_pFiles;
  pFiles_n: Integer;
  InFocus: Boolean; { Is FileBox infocus }

  TextBox: IDE_ItemTextType;
  fb_cFile, fb_cFOfs: Longint;
  FileTextLastClickT: Longint;

  Constructor init(X1, Y1, X2, Y2: Integer; p: Pointer; nFSPC: String);
  Destructor Done; virtual;
  Procedure Paint; virtual;
  Procedure GetFiles(St: String);
  Procedure KeyOn(Key: KeyType); Virtual;
  Procedure MouseOn(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
 end;

Constructor IDE_FileTextType.init(X1, Y1, X2, Y2: Integer; p: Pointer; nFSPC: String);
begin
 pSt := p; iSt_cPos := 0; iSt_sPos := 0; FSPC := nFSPC;
 InFocus := False;ItemExit := False;
 Move(FSPC[0], p^, 256);
 TextBox.Init(X1, Y1, X2, 2, p, '~EN~Fame');
 fb_cFile := 0;
 fb_cFOfs := 0;
{- Read Files -}
 GetFiles('*.'+IDE.P32.Ext);
 Inherited Init(x1, y1+3, x2, y2, '');


end;

Destructor IDE_FileTextType.done;
begin
 inherited done;
end;

Procedure IDE_FileTextType.Paint;
var i, x, y: integer;
begin
  IDE_WriteXYC(wXo+Xp, wYo+Yp-1, '~EF~Files', $7F);
  IDE_Screen.CPX := $FF; IDE_Screen.CPY := $FF;

if InFocus then
begin
 if fb_cFile<0 then fb_cFile := 0;
 if fb_cFile>pFiles_n-1 then fb_cFile := pFiles_n-1;
 if fb_cFile<fb_cFOfs then Dec(fb_cFOfs, Ys-1);
 if fb_cFile>=fb_cFOfs+Ys+Ys-2 then Inc(fb_cFOfs, Ys-1);
 FSPC := pFiles[fb_cFile];
 TextBox.iSt := FSPC; {- This really isn't needed but who carez -}
 Move(FSPC, pSt^, 256);
end;

{- Update command signaled -}
if TextBox.ItemUpdate then
begin
 TextBox.ItemUpdate := False;
 Move(pSt^, FSPC[0], 256);
 GetFiles(FSPC);
end;
if TextBox.ItemExit then
begin
  ItemExit := True;
  TextBox.ItemExit := False;
end;

  TextBox.wXo := wXo; TextBox.wYo := wYo;
  TextBox.Paint;

 for i:=0 to Ys-2 do
 begin
   for x:=0 to Xs-1 do IDE_SetBC(wXo+Xp+x, wYo+Yp+i, 3);
   for y:=0 to 1 do
   begin
    if fb_cFile = i+y*(Ys-1)+fb_cFOfs then
    begin
     IDE_WriteXY(wXo+Xp+1+y*(Xs div 2), wYo+Yp+i, pFiles[i+y*(Ys-1)+fb_cFOfs], $3F);
     for x:=0 to (Xs div 2)-2 do IDE_SetBC(wXo+Xp+x+y*(Xs div 2), wYo+Yp+i, 2);
    end
    else
     IDE_WriteXY(wXo+Xp+1+y*(Xs div 2), wYo+Yp+i, pFiles[i+y*(Ys-1)+fb_cFOfs], $30);

   end;


  IDE_WriteXYC(wXo+Xp+(Xs div 2)-1, wYo+Yp+i, '³', $31);

 end;

  for x:=1 to Xs-2 do IDE_WriteXYC(wXo+Xp+x, wYo+Yp+Ys-1, '±', $31);
  IDE_WriteXYC(wXo+Xp+0,    wYo+Yp+Ys-1, #17, $13);
  IDE_WriteXYC(wXo+Xp+Xs-1, wYo+Yp+Ys-1, #16, $13);

 if InFocus then
 begin
  IDE_Screen.CPX := $FF; IDE_Screen.CPY := $FF;
 end;

end;

Procedure IDE_FileTextType.KeyOn(Key: KeyType);
var i: word;
begin
 if (Key.Ch = #9) and (not Key.Ext) and (not Key.Alt) and (not Key.Ctrl) then InFocus := not InFocus
 else if not InFocus then TextBox.KeyOn(Key)
 else
  if Key.Ext then
   Case Key.Ch of
    'P': Inc(fb_cFile);
    'H': Dec(fb_cFile);
    'K': Dec(fb_cFile, Ys-1);
    'M': Inc(fb_cFile, Ys-1);
    'G': fb_cFile := 0; {- Home -}
    'O': fb_cFile := $7FFF; {- End -}
    'I': Dec(fb_cFile, (Ys-1)*2); {- Page Up -}
    'Q': Inc(fb_cFile, (Ys-1)*2); {- Page Down -}
   end
  else
   Case Key.Ch of
    #13:begin
         if FileExists(TextBox.iSt) then TextBox.ItemExit := True else TextBox.ItemUpdate := True;
        end;
   end;
end;

Procedure IDE_FileTextType.MouseOn(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
var ox, oy, ofl, i: integer;
begin
 if mY<Ys then
 if mLeft then
 begin
  InFocus := True;
  ox := IDE_MouseX - mX;
  oy := IDE_MouseY - mY;
  ofl := fb_cFile;
  if (IDE_MouseX-ox) < Xs div 2 then
   fb_cFile := fb_cFOfs+(IDE_MouseY-oy)
  else
   fb_cFile := fb_cFOfs+(IDE_MouseY-oy)+(Ys-1);

  if (FileTextLastClickT>GetLTime-IDE.DoubleClick) and
      (ofl = fb_cFile) then
          begin
           if FileExists(TextBox.iSt) then TextBox.ItemExit := True else
           if DirExists(TextBox.iSt) then TextBox.ItemUpdate := True else
           TextBox.ItemExit := True;

           IDE_Desktop^.QuickPaint;
           exit;
          end
  else
  Repeat
   if (IDE_MouseX-ox) < Xs div 2 then
    fb_cFile := fb_cFOfs+(IDE_MouseY-oy)
   else
    fb_cFile := fb_cFOfs+(IDE_MouseY-oy)+(Ys-1);
  IDE_Desktop^.QuickPaint;
   repeat until IDE_MouseMoved;
  until not IDE_MouseL;

  FileTextLastClickT := GetLTime;

 end;
end;

Procedure IDE_FileTextType.GetFiles(St: String);
 Function InOrder(St1, St2: String): Boolean;
 var i, w: byte;
 begin
  w := Length(St1); if Length(St2)<w then w := Length(St2);
  InOrder := True;
  if (St1[Length(St1)] = '\') and (St2[Length(St2)] <> '\') then InOrder := False;
  for i:=1 to w do
  begin
   if ord(St1[i]) > ord(St2[i]) then InOrder := False;
   if ord(St1[i]) < ord(St2[i]) then break;
  end;
  if (St1[Length(St1)] <> '\') and (St2[Length(St2)] = '\') then InOrder := True;
 end;

var DirInfo: SearchRec;i, w: word;tSt2: String;
begin
 if St = '' then St := '*.' + IDE.P32.Ext;
 fb_cFile := 0; fb_cFOfs := 0;

 for i:=1 to Length(St) do if St[i] = '/' then St[i] := '\';
 if (Pos('\', St)>0) or (Pos('..', St)>0) then
 begin
{$I-}
  if St[Ord(St[0])] = '\' then Dec(St[0]);
  Chdir(St);
  if IOResult <> 0 then beep;
{$I+}
  St := '*.'+IDE.P32.Ext;
 end;

 FSPC := St;
 for i := 0 to MaxIDEFiles-1 do pFiles[i] := '';
 pFiles_n := 0;

 FindFirst(FSPC, Archive, DirInfo);
 while (DosError = 0) and (pFiles_n<MaxIDEFiles) do
 begin
   pFiles[pFiles_n] := DirInfo.Name;
   Inc(pFiles_n);
   FindNext(DirInfo);
 end;

 FindFirst('*.*', Directory, DirInfo);
 while (DosError = 0) and (pFiles_n<MaxIDEFiles) do
 begin
   if DirInfo.name <> '.' then
   if DirInfo.name <> '..' then
   if DirInfo.Attr and Directory > 0 then
   begin
    pFiles[pFiles_n] := DirInfo.Name+'\';
    Inc(pFiles_n);
   end;
   FindNext(DirInfo);
 end;

{- Sort directory entrys -}
 if pFiles_n>2 then
 for w := 0 to pFiles_n-1 do
  for i := 0 to pFiles_n-2 do
    if not InOrder(pFiles[i], pFiles[i+1]) then
      begin
       tSt2 := pFiles[i];
       pFiles[i] := pFiles[i+1];
       pFiles[i+1] := tSt2;
      end;
   { It's nicer for the ..\ to be the last entry }
   pFiles[pFiles_n] := '..\'; Inc(pFiles_n);

end;
















Constructor IDE_WindowType.Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
begin
 {- Center when asked -}
 if (nXo = $FF) then nXo := (IDE_Screen.ScrWidth - nXs) div 2;
 if (nYo = $FF) then nYo := (IDE_Screen.ScrHeight - nYs) div 2 - 1;
 {- Set defaults -}
 Xo := nXo; Yo := nYo + 1; Xs := nXs; Ys := nYs; Title := nTitle;
 sXo := Xo; sYo := Yo; sXs := Xs; sYs := Ys;
 Moving := False; CPX := 1; CPY := 1; SizeAble := False;
 Maximised := False; Modal := False;
 {- Set Colours -}
 cWinFrame := IDE_cDWinFrame; cWinIcon  := IDE_cDWinIcon; cWinSize  := IDE_cDWinSize;
 cWinSlide := IDE_cDWinSlide; cWinBack  := IDE_cDWinBack; cText := cWinBack and $F0;
 ID := _NotSource;
 {- Insert SELF into WindowList -}
 IDE_Desktop^.tWin.Insert(@Self);
 {- Repaint the screen -}
 IDE_Desktop^.Paint;
 pTextUSE := False;
 pText := nil;
end;

Destructor IDE_WindowType.Done;
begin
 if (pTextUSE) and (pText <> nil) then FreeMem(pText, IDE_MaxTextSize);
 IDE_Desktop^.tWin.Delete(@Self);
 IDE_Desktop^.Paint;
 Dispose(@Self);exit;
end;

Function IDE_WindowType.InFront: Boolean;
begin
 if IDE_Desktop^.tWin.At(IDE_Desktop^.tWin.Count-1) = @Self then InFront := True else InFront := False;
end;

Procedure IDE_WindowType.KeyEvent(Key: KeyType);
begin
 if (Modal) and
   ((Key.Ch = #27) and (not Key.Ext)) or
   ((Key.Ch =  #1) and (Key.Ext)) then
 begin
     IDE_WindowType.CloseWin;
     IDE_WindowType.Done;
     IDE_Desktop^.Paint;
 end;
end;

Procedure IDE_WindowType.Maximise;
begin
 if not SizeAble then exit;
 if Maximised then
 begin
  Xo := sXo; Yo := sYo; Xs := sXs; Ys := sYs;
  Maximised := False;
 end
 else
 begin
  sXo := Xo; sYo := Yo; sXs := Xs; sYs := Ys;
  Maximised := True;
  Xo := 0;Yo := 0; Xs := IDE_Screen.ScrWidth; Ys := IDE_Screen.ScrHeight-2;
 end;
 IDE_Desktop^.Paint;
end;

Procedure IDE_WindowType.CloseWin;
begin
end;

Procedure IDE_WindowType.Paint;
var i, ii: integer; BorderCol: Byte;
    ON_DB, ON_Front: Boolean;St: String;
begin
 { Keep window variables within bounds }
 if (Yo <= 0) then Yo := 1;
 if (Yo > IDE_Screen.ScrHeight-2) then Yo := IDE_Screen.ScrHeight-2;
 if (Xs > IDE_Screen.ScrWidth) then Xs := IDE_Screen.ScrWidth;
 If (Ys > IDE_Screen.ScrHeight-2) then Ys := IDE_Screen.ScrHeight-2;
 if (Xs < 23) then Xs := 23; if (Ys < 5) then Ys := 5;

 if (Xs = IDE_Screen.ScrWidth) and
    (Ys = IDE_Screen.ScrHeight-2) then Maximised := True else Maximised := False;


 { Hide Cursor }
 IDE_Screen.CPX := $FF; IDE_Screen.CPY := $FF;
 IDE_Screen.tIns := False;

BorderCol := cWinFrame;
if Moving then BorderCol := cWinSize;
if InFront then ON_Front := True else ON_Front := False;

if not ON_Front then BorderCol := cWinBack;

if (Moving) or (not InFront) then ON_DB := True else ON_DB := False;
if (InFront) then ON_Front := True else ON_Front := False;



if ON_DB then
begin
 IDE_WriteXYC_Ch(Xo,      Yo     , 'Ú', BorderCol);
 IDE_WriteXYC_Ch(Xo+Xs-1, Yo     , '¿', BorderCol);
 IDE_WriteXYC_Ch(Xo     , Yo+Ys-1, 'À', BorderCol);
 IDE_WriteXYC_Ch(Xo+Xs-1, Yo+Ys-1, 'Ù', BorderCol);
 for i:=1 to Xs-2 do IDE_WriteXYC_Ch(Xo+i, Yo, 'Ä', BorderCol);
 for i:=1 to Xs-2 do IDE_WriteXYC_Ch(Xo+i, Yo+Ys-1, 'Ä', BorderCol);

 for ii:=1 to Ys-2 do
 begin
  IDE_WriteXYC_Ch(Xo, Yo+ii, '³', BorderCol);
  IDE_WriteXYC_Ch(Xo+Xs-1, Yo+ii, '³', BorderCol);
  for i:=1 to Xs-2 do IDE_WriteXYC_Ch(Xo+i, Yo+ii, ' ', cWinFrame);
 end;
end
else
begin
 IDE_WriteXYC_Ch(Xo,      Yo     , 'É', BorderCol);
 IDE_WriteXYC_Ch(Xo+Xs-1, Yo     , '»', BorderCol);
 IDE_WriteXYC_Ch(Xo     , Yo+Ys-1, 'È', BorderCol);
 IDE_WriteXYC_Ch(Xo+Xs-1, Yo+Ys-1, '¼', BorderCol);
 for i:=1 to Xs-2 do IDE_WriteXYC_Ch(Xo+i, Yo, 'Í', BorderCol);
 for i:=1 to Xs-2 do IDE_WriteXYC_Ch(Xo+i, Yo+Ys-1, 'Í', BorderCol);

 for ii:=1 to Ys-2 do
 begin
  IDE_WriteXYC_Ch(Xo, Yo+ii, 'º', BorderCol);
  IDE_WriteXYC_Ch(Xo+Xs-1, Yo+ii, 'º', BorderCol);
  for i:=1 to Xs-2 do IDE_WriteXYC_Ch(Xo+i, Yo+ii, ' ', cWinFrame);
 end;

end;

{$IFDEF FrontWindowShadowOnly}
if InFront then
{$ENDIF}
begin
 for i:=0 to Xs-1 do if (Xo+i+2 < 80) and (Xo+i+2 >= 0) then IDE_Grey(Xo+i+2, Yo+Ys);
 for i:=0 to Ys-1 do
  if (Yo+i+1 >= 1) and (Yo+i+1 < IDE_Screen.ScrHeight-1) and (Xo+Xs >= 0) and (Xo+Xs < IDE_Screen.ScrWidth) then
  IDE_Grey(Xo+Xs, Yo+i+1);
 for i:=0 to Ys-1 do
  if (Yo+i+1 >= 1) and (Yo+i+1 < IDE_Screen.ScrHeight-1) and (Xo+Xs+1 >= 0) and (Xo+Xs+1 < IDE_Screen.ScrWidth) then
  IDE_Grey(Xo+Xs+1, Yo+i+1);
end;

{- Write Title clipping at edge of free space -}
St := ' ' + Title + ' ';
for i := 1 to Length(St) do
begin
 ii := integer(integer(integer(Xs)-integer(Length(St))) div 2)+i-1;
 if (ii >= 5) and (ii < Xs-5) and (ON_Front) then IDE_WriteXYC(Xo+ii, Yo, St[i], BorderCol);
 if (ii >= 2) and (ii < Xs-2) and (not ON_Front) then IDE_WriteXYC(Xo+ii, Yo, St[i], BorderCol);
end;

if On_Front then
begin

{ Close Window Icon }
 IDE_WriteXYC_Ch(Xo+2, Yo, '[', BorderCol);
 IDE_WriteXYC_Ch(Xo+3, Yo, 'þ', cWinIcon);
 IDE_WriteXYC_Ch(Xo+4, Yo, ']', BorderCol);


end;

end;

Procedure IDE_WindowType.MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
Var oXo, oYo, oXs, oYs: Integer; w1,w2,w3,w4: word;l: Longint;
begin
 {- Move Window when border pressed -}
 if (mLeft) then
 begin

  if (mX >= 2) and (mX <= 4) and (mY = 0) then
  begin
    repeat

    { Close Window Icon }
     IDE_WriteXYC_Ch(Xo+2, Yo, '[', cWinFrame);
   if (IDE_MouseX >= Xo+2) and (IDE_MouseX <= Xo+4) and (IDE_MouseY = Yo) then
     IDE_WriteXYC_Ch(Xo+3, Yo, #15, cWinIcon)
   else
     IDE_WriteXYC_Ch(Xo+3, Yo, 'þ', cWinIcon);
     IDE_WriteXYC_Ch(Xo+4, Yo, ']', cWinFrame);

     IDE_UpdateVideo;
     Repeat until IDE_MouseMoved;

    until not IDE_MouseL;
   if (IDE_MouseX >= Xo+2) and (IDE_MouseX <= Xo+4) and (IDE_MouseY = Yo) then
    begin
     IDE_WindowType.CloseWin;
     IDE_WindowType.Done;
     IDE_Desktop^.Paint;
    end;
    MouseEvent_Done := True;
  end
  else
  if (mX >= Xs-5) and (mX <= Xs-3) and (mY = 0) and (SizeAble) then
  begin
    sDblClick_Time := 0; {- Reset DblClick count -}
    Maximise;
    MouseEvent_Done := True;
  end
  else
  if (mY=0) then
     begin
      GetTime(w1, w2, w3, w4);
      l := w4 + w3 * 100 + w2 * 6000 + w1 * 360000;
      if (l-IDE.DoubleClick < sDblClick_Time) then
      begin
       Maximise;
       sDblClick_Time := 0; {- Reset DblClick count -}
      end
      else
      begin
       GetTime(w1, w2, w3, w4);
       sDblClick_Time := w4 + w3 * 100 + w2 * 6000 + w1 * 360000;
       Moving := True;
       IDE_Desktop^.IDE_BottomHelp('#~'#24#25#26#27'~ Move  ~Shift+'#24#25#26#27'~ Resize  ~'#17'ÄÙ~ Done  ~Esc~ Cancel');
       IDE_Desktop^.Paint;
       oXo := Xo; oYo := Yo;
       repeat

        repeat until IDE_MouseMoved;
        Xo := IDE_MouseX - mX;
        Yo := IDE_MouseY - mY;
        IDE_Desktop^.Paint;

       until not IDE_MouseL;
       Moving := False;
       IDE_Desktop^.IDE_BottomHelp('');
       IDE_Desktop^.Paint;
       if (oXo <> Xo) or (oYo <> Yo) then {- Only reset if moved -}
        sDblClick_Time := 0; {- Reset DblClick count -}

      MouseEvent_Done := True;
      end;
   end
   else
   if ((mY=Ys-1) and (mX > Xs-3) and (mX < Xs)) and (SizeAble) then
   begin
      Moving := True;
      IDE_Desktop^.IDE_BottomHelp('#~'#24#25#26#27'~ Move  ~Shift+'#24#25#26#27'~ Resize  ~'#17'ÄÙ~ Done  ~Esc~ Cancel');
      IDE_Desktop^.Paint;
      oXs := Xs; oYs := Ys;
      oXo := Xo; oYo := Yo;
      sDblClick_Time := 0; {- Reset DblClick count -}
      repeat

       repeat until IDE_MouseMoved;
       Xs := (IDE_MouseX - mX)+oXs-oXo;
       Ys := (IDE_MouseY - mY)+oYs-oYo;
       if Xs > 160 then Xs := 0;
       if Ys > 50 then Ys := 0;
       IDE_Desktop^.Paint;

      until not IDE_MouseL;
      Moving := False;
      IDE_Desktop^.IDE_BottomHelp('');
      IDE_Desktop^.Paint;
      MouseEvent_Done := True;
   end;

 end

end;




Constructor IDE_DialogWindowType.Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
begin
 tItem.Init(16, 4);
 Inherited Init(nXo, nYo, nXs, nYs, nTitle);
 pTextUSE := False;
 Modal := True;
end;

Procedure IDE_DialogWindowType.Paint;
 Procedure PaintItem(p: pIDE_ItemBaseType); far;
 begin
  p^.wXo := Xo;
  p^.wYo := Yo;
  p^.Paint;
 end;
begin
 inherited Paint;
 if tItem.Count>0 then tItem.ForEach(@PaintItem);
end;

Procedure IDE_DialogWindowType.MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
var pI: pIDE_ItemBaseType;
 Procedure CheckOn(p: pIDE_ItemBaseType); far;
 begin
  if (mX>=p^.Xp) and (mY>=p^.Yp) and
     (mX<p^.Xp+p^.Xs) and(mY<p^.Yp+p^.Ys) then
      pI := p;
 end;
begin
 Inherited MouseEvent(mLeft, mMiddle, mRight, mX, mY);
 if tItem.Count>0 then
 begin
  pI := nil;
  tItem.ForEach(@CheckOn);
  if pI <> nil then pI^.MouseOn(mLeft, mMiddle, mRight, mX-pI^.Xp, mY-pI^.Yp);
 end;
end;

Procedure IDE_DialogWindowType.KeyEvent(Key: KeyType);
var pI: pIDE_ItemBaseType;
begin
 Inherited KeyEvent(Key);
 if tItem.Count>0 then
 begin
  pI := tItem.At(tItem.Count-1);
  pI^.KeyOn(Key);
 end;
end;

Constructor IDE_UserWindowType.Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
begin
 Inherited init(nXo, nYo, nXs, nYs, nTitle);
 pTextUSE := False;
 cWinBack  := cWinBack  and $F;
 cWinSize  := cWinSize  and $F;
 cWinIcon  := cWinIcon  and $F;
 cWinFrame := cWinFrame and $F;
 cWinSlide := cWinSlide and $F;
 cText := cWinBack and $F0;
 vXo := 0; vYo := 0;
 IDE_Desktop^.QuickPaint;
end;

Procedure IDE_UserWindowType.Paint;
var x, y, i: word;
begin
 if Ys > 27 then Ys := 27;
 if Xs > 80 then Xs := 80;
 Inherited Paint;
 if (vXo+Xs > 81) then vXo := 82-Xs;
 if (vYo+Ys > 26) then vYo := 27-Ys;
 if vXo < 0 then vXo := 0;
 if vYo < 0 then vYo := 0;

 IDE_Screen.CPX := (IDE_Screen.SwapCx+Xo)-vXo;
 IDE_Screen.CPY := (IDE_Screen.SwapCy+Yo)-vYo;
 if (IDE_Screen.SwapCx-vXo >= Xs-1) or (IDE_Screen.SwapCy-vYo >= Ys-1) or
    (IDE_Screen.SwapCx-vXo <= 0   ) or (IDE_Screen.SwapCy-vYo <= 0   ) then
 begin;IDE_Screen.CPX:=$FF;IDE_Screen.CPY:=$FF;end;

 {- Display Slider indicator -}
 if InFront then
 begin
  if (vXo >= 0) and (vXo<=82) then if Xs<82 then
   IDE_WriteXYC_Ch(Xo+19+ round((Xs-23)*(vXo)/(82-Xs)) , Yo+Ys-1, #254, IDE_cWinSlide)
  else
   IDE_WriteXYC_Ch(Xo+Xs-4 , Yo+Ys-1, #254, IDE_cWinSlide);
  if (vYo >= 0) and (vYo<=27) then if Ys<27 then
   IDE_WriteXYC_Ch(Xo+Xs-1, Yo+2+ round((Ys-5)*(vYo)/(27-Ys)), #254, IDE_cWinSlide)
  else
   IDE_WriteXYC_Ch(Xo+Xs-1, Yo+2, #254, IDE_cWinSlide);
 end;


 x := 80;
 if x > xs-2 then x := xs-2;
 if x+xo >= 80 then y := 80-xo;
 for y:=0 to 24 do
 if (y+2< ys) and (y+yo+1 < 50) then
 begin
  for i:=0 to x-1 do
   if ((i+xo)+1 >= 0) and ((i+xo) < IDE_Screen.ScrWidth-1) then
    Move(Mem[Seg(IDE_Screen.SwapBuffer^):Ofs(IDE_Screen.SwapBuffer^)+(i+vXo)*2+(y+vYo)*160],
         IDE_Screen.Buffer[Yo+y+1, Xo+1+i], 2);

 end;
end;

Procedure IDE_UserWindowType.MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
var oCPX, oCPY, i: Integer;l: Longint;
begin
 MouseEvent_Done := False;
 inherited MouseEvent(mLeft, mMiddle, mRight, mX, mY);
 if (not MouseEvent_Done) and (mLeft) then
 begin
 {- Scroll Left -}
   if (mX = 18) and (mY = Ys-1) and (vXo>0) and
      (IDE_MouseX-Xo = 18) and (IDE_MouseY-Yo = Ys-1) then
    begin
     Dec(vXo);CPX:=$FF;IDE_Desktop^.QuickPaint;
     i:=30; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     while (IDE_MouseX-Xo=18) and (IDE_MouseY-Yo=Ys-1) and (vXo>0) and (IDE_MouseL) do
     begin
      Dec(vXo);CPX:=$FF;IDE_Desktop^.QuickPaint;
      i:=3; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     end;
    end;
 {- Scroll Right -}
   if (mX = Xs-3) and (mY = Ys-1) and
      (IDE_MouseX-Xo = Xs-3) and (IDE_MouseY-Yo = Ys-1) then
    begin
     Inc(vXo);CPX:=$FF;IDE_Desktop^.QuickPaint;
     i:=30; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     While (IDE_MouseX-Xo=Xs-3) and (IDE_MouseY-Yo=Ys-1) and (IDE_MouseL) do
     begin
      Inc(vXo);CPX:=$FF;IDE_Desktop^.QuickPaint;
      i:=3; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     end;
    end;
 {- Horizontal Bar scroll -}
   if (mX > 18) and (mX < Xs-3) and (mY = Ys-1) and
      (IDE_MouseX-Xo > 18) and (IDE_MouseX-Xo < Xs-3) and (IDE_MouseY-Yo = Ys-1) then
      begin
       {- Calculate scroller, using Longint to prevent overflows -}
       vXo := (longint(mX-19) * longint(82-Xs)) div longint(Xs-23);
       CPX:=$FF;CPY:=$FF;IDE_Desktop^.QuickPaint;
       repeat
       if (IDE_MouseX-Xo > 18) and (IDE_MouseX-Xo < Xs-3) and
          (IDE_MouseY-Yo >= Ys-2) and (IDE_MouseY-Yo <= Ys) then
       begin
        vXo := (longint((IDE_MouseX-Xo)-19) * longint(82-Xs)) div longint(Xs-23);
        CPX:=$FF;CPY:=$FF;IDE_Desktop^.QuickPaint;
       end;
        repeat until IDE_MouseMoved;
       until not IDE_MouseL;
      end;



 {- Scroll Up -}
   if (mX = Xs-1) and (mY = 1) and (vYo>0) and
      (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo = 1) then
    begin
     Dec(vYo);CPY:=$FF;IDE_Desktop^.QuickPaint;
     i:=40; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     While (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo = 1) and (vYo>0) and (IDE_MouseL) do
     begin
      Dec(vYo);CPY:=$FF;IDE_Desktop^.QuickPaint;
      i:=5; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     end;
    end;

 {- Scroll Down -}
   if (mX = Xs-1) and (mY = Ys-2) and
      (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo = Ys-2) then
    begin
     Inc(vYo);CPY:=$FF;IDE_Desktop^.QuickPaint;
     i:=40; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     While (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo = Ys-2) and (IDE_MouseL) do
     begin
      Inc(vYo);CPY:=$FF;IDE_Desktop^.QuickPaint;
      i:=5; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     end;
    end;
 {- Vertical Scroller -}
   if (mX = Xs-1) and (mY > 1) and (mY < Ys-2) and
      (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo > 1) and (IDE_MouseY-Yo < Ys-2) then
    begin
       {- Calculate scroller, using Longint to prevent overflows -}
       vYo := (longint(mY-2) * longint(27-Ys)) div longint(Ys-5);
       CPX:=$FF;CPY:=$FF;IDE_Desktop^.QuickPaint;
       repeat
       if (IDE_MouseX-Xo >= Xs-2) and (IDE_MouseX-Xo <= Xs) and
          (IDE_MouseY-Yo > 1) and (IDE_MouseY-Yo < Ys-2) then
       begin
        vYo := (longint((IDE_MouseY-Yo)-2) * longint(27-Ys)) div longint(Ys-5);
        CPX:=$FF;CPY:=$FF;IDE_Desktop^.QuickPaint;
       end;
        repeat until IDE_MouseMoved;
       until not IDE_MouseL;
    end;



  end;
end;



Constructor IDE_TextWindowType.Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
begin
 {- Center when asked -}
 if (nXo = $FF) then nXo := (IDE_Screen.ScrWidth - nXs) div 2;
 if (nYo = $FF) then nYo := (IDE_Screen.ScrHeight - nYs) div 2 - 1;
 {- Set defaults -}
 Xo := nXo; Yo := nYo + 1; Xs := nXs; Ys := nYs; Title := nTitle;
 sXo := Xo; sYo := Yo; sXs := Xs; sYs := Ys;
 Moving := False; CPX := 1; CPY := 1;
 SizeAble := True; Modified := False; Maximised := False; Modal := False;
 {- Set Colours -}
 cWinFrame := IDE_cWinFrame; cWinIcon  := IDE_cWinIcon; cWinSize  := IDE_cWinSize;
 cWinSlide := IDE_cWinSlide; cWinBack  := IDE_cWinBack; cText := cWinBack and $F0;
 ID := _NotSource;
 {- Insert SELF into WindowList -}
 IDE_Desktop^.tWin.Insert(@Self);
 {- Repaint the screen -}
 IDE_Desktop^.Paint;
 pTextUSE := False;
end;


Procedure IDE_TextWindowType.Paint;
var i: integer; BorderCol: Byte;
begin
  inherited Paint;

 {- Update Cursor Position -}
 IDE_Screen.CPX := Xo+CPX; IDE_Screen.CPY := Yo+CPY;
 if (CPX >= Xs-1) or (CPY >= Ys-1) or (CPX < 1) or (CPY < 1) or
    (CPX > IDE_Screen.ScrWidth) or (CPY > IDE_Screen.ScrHeight) then
      begin;IDE_Screen.CPX:=$FF;IDE_Screen.CPY:=$FF;end;

 BorderCol := cWinFrame;
 if Moving then BorderCol := cWinSize;
 if not InFront then BorderCol := cWinBack;

 if Modified then
  IDE_WriteXYC_Ch(Xo+2, Yo+Ys-1, #15, BorderCol);

if InFront then
begin
 { Slider bar - Horizontal }
  for i:=19 to Xs-4 do IDE_WriteXYC_Ch(Xo+i, Yo+Ys-1, '±', IDE_cWinSlide);
  IDE_WriteXYC_Ch(Xo+18, Yo+Ys-1, #17, IDE_cWinSlide);
  IDE_WriteXYC_Ch(Xo+Xs-3, Yo+Ys-1, #16, IDE_cWinSlide);
 { Slider bar - Vertical }
  for i:=2 to Ys-3 do IDE_WriteXYC_Ch(Xo+Xs-1, Yo+i, '±', IDE_cWinSlide);
  IDE_WriteXYC_Ch(Xo+Xs-1, Yo+1, #30, IDE_cWinSlide);
  IDE_WriteXYC_Ch(Xo+Xs-1, Yo+Ys-2, #31, IDE_cWinSlide);


{ Min/Max Icon }
 if SizeAble then
 begin
  IDE_WriteXYC_Ch(Xo+Xs-5, Yo, '[', BorderCol);
  if Maximised then
   IDE_WriteXYC_Ch(Xo+Xs-4, Yo, #18, cWinIcon)
  else
   IDE_WriteXYC_Ch(Xo+Xs-4, Yo, #24, cWinIcon);
  IDE_WriteXYC_Ch(Xo+Xs-3, Yo, ']', BorderCol);

  IDE_WriteXYC_Ch(Xo+Xs-2, Yo+Ys-1, 'Ä', cWinIcon);
  IDE_WriteXYC_Ch(Xo+Xs-1, Yo+Ys-1, 'Ù', cWinIcon);

 end;

end;

end;



Constructor IDE_SourceWindowType.init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
begin
 {- Allocate and Clear buffer -}
 GetMem(pText, IDE_MaxTextSize);
 Fillchar(pText^, IDE_MaxTextSize, $A);
 pTextSize := 0;
 pTextPos  := 0;
 pTextCX   := 0;
 pTextCY   := 0;
 pTextSX   := 0;
 pTextSY   := 0;
 tIns := True;
 pTextCXMax := 1; pTextCYMax := 1;
 InPaint := False;
 pTextHiStart.bt := _none; pTextHiStart.bNestLvl := 0;
 pTextHiStart._AsmSrc := False;
 pTextHiEnd.bt := _none; pTextHiEnd.bNestLvl := 0;
 pTextHiEnd._AsmSrc := False;
 PaintWinOnMove := False;
 pTextSelStart := 0; pTextSelEnd := 0;
 pTextSel := False;
 FileTitle := UCase(nTitle);

 Inherited Init(nXo, nYo, nXs, nYs, nTitle);
 ID := _Source;
 pTextUSE := True;
end;

Destructor IDE_SourceWindowType.Done;
begin
 if pTextUSE then FreeMem(pText, IDE_MaxTextSize);
 pTextUSE := fAlse;
 inherited done;
end;


Procedure IDE_SourceWindowType.MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
var oCPX, oCPY, i: Integer;l: Longint;
begin
 MouseEvent_Done := False;
 inherited MouseEvent(mLeft, mMiddle, mRight, mX, mY);
 if not MouseEvent_Done then
 if mLeft then
 begin
  if (mX >= 1) and (mY >= 1) and (mX < Xs-1) and (mY < Ys-1) then
  begin
   pTextCX := ((IDE_MouseX-Xo)-1) + pTextSX;
   pTextCY := ((IDE_MouseY-Yo)-1) + pTextSY;
   if pTextCX <= 0 then pTextCX := 0;
   if pTextCY <= 0 then pTextCY := 0;
   pTextSel := False;
   UpdateCPMove;
    l := CalcTextPos(pTextCX, pTextCY);
    pTextSelStart := l; pTextSelEnd := l;
   Repeat
    repeat until IDE_MouseMoved;
{$IFNDEF NoBlockHilite}
    pTextCX := ((IDE_MouseX-Xo)-1) + pTextSX;
    pTextCY := ((IDE_MouseY-Yo)-1) + pTextSY;
    if pTextCX <= 0 then pTextCX := 0;
    if pTextCY <= 0 then pTextCY := 0;
    l := CalcTextPos(pTextCX, pTextCY);
    if l < pTextSelStart then pTextSelStart := l;
    if l > pTextSelEnd   then pTextSelEnd   := l;
    pTextSel := not True;
    IDE_Desktop^.QuickPaint;
{$ENDIF}
   until (not IDE_MouseL);
     CalcTextHI;

  end;

 {- Scroll Left -}
   if (mX = 18) and (mY = Ys-1) and (pTextSX>0) and
      (IDE_MouseX-Xo = 18) and (IDE_MouseY-Yo = Ys-1) then
    begin
     Dec(pTextSX);CPX:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
     i:=30; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     while (IDE_MouseX-Xo=18) and (IDE_MouseY-Yo=Ys-1) and (pTextSX>0) and (IDE_MouseL) do
     begin
      Dec(pTextSX);CPX:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
      i:=3; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     end;
    end;
 {- Scroll Right -}
   if (mX = Xs-3) and (mY = Ys-1) and (pTextSX+1<pTextCXMax) and
      (IDE_MouseX-Xo = Xs-3) and (IDE_MouseY-Yo = Ys-1) then
    begin
     Inc(pTextSX);CPX:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
     i:=30; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     While (IDE_MouseX-Xo=Xs-3) and (IDE_MouseY-Yo=Ys-1) and (pTextSX<pTextCXMax) and (IDE_MouseL) do
     begin
      Inc(pTextSX);CPX:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
      i:=3; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     end;
    end;
 {- Horizontal Bar scroll -}
   if (mX > 18) and (mX < Xs-3) and (mY = Ys-1) and (pTextCXMax > 0) and
      (IDE_MouseX-Xo > 18) and (IDE_MouseX-Xo < Xs-3) and (IDE_MouseY-Yo = Ys-1) then
      begin
       {- Calculate scroller, using Longint to prevent overflows -}
       pTextSX := (longint(mX-19) * longint(pTextCXMax)) div longint(Xs-23);
       CPX:=$FF;CPY:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
       repeat
       if (IDE_MouseX-Xo > 18) and (IDE_MouseX-Xo < Xs-3) and
          (IDE_MouseY-Yo >= Ys-2) and (IDE_MouseY-Yo <= Ys) then
       begin
        pTextSX := (longint((IDE_MouseX-Xo)-19) * longint(pTextCXMax)) div longint(Xs-23);
        CalcTextHI;
        CPX:=$FF;CPY:=$FF;IDE_Desktop^.QuickPaint;
       end;
        repeat until IDE_MouseMoved;
       until not IDE_MouseL;
      end;

 {- Scroll Up -}
   if (mX = Xs-1) and (mY = 1) and (pTextSY>0) and
      (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo = 1) then
    begin
     Dec(pTextSY);CPY:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
     i:=40; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     While (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo = 1) and (pTextSY>0) and (IDE_MouseL) do
     begin
      Dec(pTextSY);CPY:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
      i:=5; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     end;
    end;

 {- Scroll Down -}
   if (mX = Xs-1) and (mY = Ys-2) and (pTextSY+1<pTextCYMax) and
      (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo = Ys-2) then
    begin
     Inc(pTextSY);CPY:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
     i:=40; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     While (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo = Ys-2) and (pTextSY<pTextCYMax) and (IDE_MouseL) do
     begin
      Inc(pTextSY);CPY:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
      i:=5; repeat Delay(10);Dec(i);until (IDE_MouseMoved) or (i=0);
     end;
       CalcTextHI;
    end;
 {- Vertical Scroller -}
   if (mX = Xs-1) and (mY > 1) and (mY < Ys-2) and
      (IDE_MouseX-Xo = Xs-1) and (IDE_MouseY-Yo > 1) and (IDE_MouseY-Yo < Ys-2) then
    begin
       {- Calculate scroller, using Longint to prevent overflows -}
       pTextSY := (longint(mY-2) * longint(pTextCYMax)) div longint(Ys-5);
       CPX:=$FF;CPY:=$FF;CalcTextHI;IDE_Desktop^.QuickPaint;
       repeat
       if (IDE_MouseX-Xo >= Xs-2) and (IDE_MouseX-Xo <= Xs) and
          (IDE_MouseY-Yo > 1) and (IDE_MouseY-Yo < Ys-2) then
       begin
        pTextSY := (longint((IDE_MouseY-Yo)-2) * longint(pTextCYMax)) div longint(Ys-5);
        CalcTextHI;
        CPX:=$FF;CPY:=$FF;IDE_Desktop^.QuickPaint;
       end;
        repeat until IDE_MouseMoved;
       until not IDE_MouseL;
    end;

 end;

end;


Procedure IDE_SourceWindowType.KeyEvent(Key: KeyType);
 Procedure InsertChar(Ch: Char);
 var l: Longint;
 begin
    if (tIns) or (pText^[pTextPos] = $A) then
    begin
     Move(pText^[pTextPos], pText^[pTextPos+1], Abs(pTextSize-pTextPos)+1);
     Inc(pTextSize);
    end;

    pText^[pTextPos] := Ord(Ch);
    Inc(pTextPos); Inc(pTextCX);
    if Key.Ch = #$A then begin
                          Inc(pTextCY);
                          pTextCX := 0;
                          pTextSX := 0;
                          if IDE.SmartTab then
                          begin
                           l := IDE_SourceWindowType.CalcTextPos(0, pTextCY-1);
                           While (Chr(pText^[l]) in [#32,#0,#255]) do
                            begin;Inc(l);Inc(pTextCX);end;
                          end;

                         end;
 end;
 Procedure FindEOL;
 var l: Longint; x, y: integer;
 begin
    {- Find Y Position -}
    l := 0; y := 0;
    while (y<pTextCY) and (l<pTextSize) do
    begin
     if (pText^[l] = $A) then Inc(y);
     Inc(l);
    end;
    {- Find X Position and insert needed spaces -}
    x := 0;
    while (pText^[l] <> $A) and (l<pTextSize) do
    begin
     Inc(l); inc(x);
    end;
    pTextCX := x;

 end;
 Procedure InsertCharCheck(Ch: Char);
 Label FindPosition;
 var l: Longint; x, y, i: integer;
 begin
    {- Find Y Position -}
    FindPosition:
    l := 0; y := 0;
    while (y<pTextCY) and (l<pTextSize) do
    begin
     if (pText^[l] = $A) then Inc(y);
     Inc(l);
    end;
    {- Insert lines -}
    if (y<pTextCY) then
    begin
     pTextPos := pTextSize;
     x := pTextCY; if x > 0 then dec(x);
     for i:=y to (x) do Begin;InsertChar(#10);Dec(pTextCX);end;
     Goto FindPosition;
    end;

    {- Find X Position and insert needed spaces -}
    x := 0;
    while (x<pTextCX) and (pText^[l] <> $A) and (l<pTextSize) do
    begin
     Inc(l);Inc(x);
    end;

    pTextPos := l;

    { #0 is used for special functions }
    if Ch = #0 then exit;

    if ((x<pTextCX) and (pText^[l] = $A)) then
    begin
     y := pTextCX;
     FindEOL; if y > 0 then Dec(y);
     for i:=x to y do InsertChar(#32);
    end;


   if Ch < #$FF then InsertChar(Ch);
 end;
var l: Longint;i: integer;w: word;
begin
 l := CalcTextPos(pTextCX, pTextCY);
 if (not Key.Ext) and (not Key.Alt) and (not Key.Ctrl) then
 Case Key.Ch of
   #9: if IDE.TabSize > 0 then
        for i:=0 to IDE.TabSize-1 do KeyEvent(Space)
       else
       begin {- Smart-TAB - NOT COMPLETED -}
        w := 0;
        Repeat
         Inc(w);l := IDE_SourceWindowType.CalcTextPos(0, pTextCY-w);
        Until (pText^[l] <> 10) or (w>50);
         l := IDE_SourceWindowType.CalcTextPos(pTextCX, pTextCY-w);
         w := 0;
         if (Chr(pText^[l]) in [#32,#0,#255]) then
         While ((Chr(pText^[l]) in [#32,#0,#255])) and (pText^[l]<>10) do
          begin;Inc(l);Inc(pTextCX);Inc(w);end
         else
         begin
          While (not (Chr(pText^[l]) in [#32,#0,#255])) and (pText^[l]<>10) do
           begin;Inc(l);Inc(pTextCX);Inc(w);end;
           if (pText^[l]=10) and (w<2) then begin;Inc(l,7);Inc(pTextCX,7);end;
          Inc(l);Inc(pTextCX);
         end;
        {- Old Tab Code
         for w:=0 to 7 do KeyEvent(Space);}
       end;
   #8:begin
      InsertCharCheck(#255);
      if (pTextPos > 0) and (pTextSize > 0) then
      begin
       if pTextCX > 0 then Dec(pTextCX) else begin;Dec(pTextCY);FindEOL;end;
       InsertCharCheck(#0);
       Move(pText^[pTextPos+1], pText^[pTextPos], Abs(pTextSize-pTextPos));
       if pTextSize > 0 then Dec(pTextSize);
       if pTextPos > 0 then Dec(pTextPos);
      end;
      end;
   #13: begin
         {- This workaround fixes an annoying bug which makes the cursor jump -}
         InsertCharCheck(#$FF);
         Key.Ch := #$0A;
         KeyEvent(Key);
         exit;
        end;
   #27:exit;
  else
   if pTextSize < IDE_MaxTextSize then
   begin
    {- Insert key -}
    InsertCharCheck(Key.Ch);
    {- No AutoInsert, it doesn't work well -}
    {if (Key.Ch = ')') and (pText^[pTextPos] = $A) then
     begin
      InsertCharCheck(';');
      Dec(pTextPos);Dec(pTextCx);tIns := True;
     end;}

   end;
 end;
 if (Key.Ext) and (not Key.Alt) and (not Key.Ctrl) then
 Case Key.Ch of
  'G': pTextCX := 0; {- Home -}
  'O': FindEOL; {- End -}
  'I': begin {- Page Up -}
        if pTextCY > Ys-2 then Dec(pTextCY, Ys-2) else pTextCY := 0;
        if pTextSY > Ys-2 then Dec(pTextSY, Ys-2) else pTextSY := 0;
        {- Update SyntaxHighlighting -}
        CalcTextHI;
       end;
  'Q': begin {- Page Down -}
        if pTextCY < (pTextCYMax+Ys-2) then Inc(pTextCY, Ys-2) else pTextCY := pTextCYMax;
        if pTextSY < (pTextCYMax+Ys-2) then Inc(pTextSY, Ys-2) else pTextSY := pTextCYMax;
        {- Update SyntaxHighlighting -}
        pTextHiStart := pTextHiEnd;
       end;
  'R': tIns := not tIns; {- Insert -}
  'S': begin {- Delete -}
        InsertCharCheck(#255);
        if (pTextPos < pTextSize) and (pTextSize > 0) then begin
         Move(pText^[pTextPos+1], pText^[pTextPos], Abs(pTextSize-pTextPos));
         if pTextSize > 0 then Dec(pTextSize);
        end;
       end;
  'K': {- Left -} if pTextCX > 0 then Dec(pTextCX);
  'M': {- Right -}{if pTextCX <= pTextCXMax then} Inc(pTextCX);
  'H': begin {- Up -}
        if pTextCY > 0 then Dec(pTextCY);
        {- Update SyntaxHighlighting -}
        CalcTextHI;
       end;
  'P': begin {- Down -}
        if pTextCY <= pTextCYMax+Ys then Inc(pTextCY);
        {- Update SyntaxHighlighting -}
        pTextHiStart := pTextHiFirst;
       end;
 end;
 if (Key.Ext) and (not Key.Alt) and (Key.Ctrl) then
 Case Key.Ch of
  #132: begin
        pTextSX := 0; pTextSY := 0; pTextCX := 0; pTextCY := 0;
        IDE_Desktop^.QuickPaint;
       end;
  #118: begin
        pTextSX := 0; pTextSY := pTextCYMax-Ys; pTextCX := 0; pTextCY := pTextCYMax;
        IDE_Desktop^.QuickPaint;
       end;
  #119: begin
         pTextCY := pTextSY;
         IDE_Desktop^.QuickPaint;
        end;
  #117: begin
         pTextCY := pTextSY + Ys-3;
         IDE_Desktop^.QuickPaint;
        end;
 end;

{$IFNDEF NoBlockHilite}
 if Key.Shift then
  begin
   if (l < pTextSelStart) or (l>pTextSelEnd) then
   begin
    l := CalcTextPos(pTextCX, pTextCY);
    pTextSelStart := l; pTextSelEnd := l;
   end
   else
   begin
    l := CalcTextPos(pTextCX, pTextCY);
    if (l < pTextSelStart) then pTextSelStart := l;
    if (l > pTextSelEnd) then pTextSelEnd := l;
   end;
   pTextSel := True;
  end;
{$ENDIF}

if IDE_Desktop^.DontDrawNext_B then exit;

{ if Key.Ch > #0) then Modified := True;}
 CPX:=0;CPY:=0; {- Paint wil set these -}
 {- An Arrowkey only involves moving the cursor, so don't redraw the screen -}
 if (Key.Ext) and not (Key.Ch in ['S','I','Q']) then
  UpdateCPMove
 else
 begin
  if (not Key.Ext) or ((Key.Ext) and (Key.Ch = 'S')) then begin;Modified := True;UpdateCPMove;end;
   IDE_Desktop^.QuickPaint;

 end;
end;

Procedure IDE_SourceWindowType.ShowCursorST;
var St: String;
begin
 {- Display cursor position -}
 if not InFront then exit;
 IDE_Screen.tIns := not tIns;
  Str(pTextCX+1, St);
 if Moving then
  IDE_WriteXYC(Xo+10-Length(St)-1, Yo+Ys-1, ' ' + St + ':', cWinSize)
 else
  IDE_WriteXYC(Xo+10-Length(St)-1, Yo+Ys-1, ' ' + St + ':', cWinFrame);
  Str(pTextCY+1, St);
 if Moving then
  IDE_WriteXYC(Xo+11, Yo+Ys-1, St + ' ', cWinSize)
 else
  IDE_WriteXYC(Xo+11, Yo+Ys-1, St + ' ', cWinFrame);
end;

{- Update CursorPosition without moving scroller -}
Procedure IDE_SourceWindowType.UpdateCP;
var NeedPaint: Boolean;
begin
  NeedPaint := False;
 if CPX <> $FF then
 begin
  CPX := pTextCX-pTextSX+1;
 end else CPX := pTextCX-pTextSX+1;
 if CPY <> $FF then
 begin
  CPY := pTextCY-pTextSY+1;
 end else CPY := pTextCY-pTextSY+1;

 IDE_Screen.tIns := not tIns;

 if not InPaint then
 if NeedPaint then IDE_Desktop^.QuickPaint else
 begin
  {- Update Cursor Position -}
  IDE_Screen.CPX := Xo+CPX; IDE_Screen.CPY := Yo+CPY;
  if (CPX >= Xs-1) or (CPY >= Ys-1) or (CPX < 1) or (CPY < 1) or
     (CPX > IDE_Screen.ScrWidth) or (CPY > IDE_Screen.ScrHeight) then
       begin;IDE_Screen.CPX:=$FF;IDE_Screen.CPY:=$FF;end;

   ShowCursorST;

  if not IDE_Desktop^.DontDrawNext_B then IDE_UpdateVideo;
 end;
end;

{- Update CursorPosition moving scroller -}
Procedure IDE_SourceWindowType.UpdateCPMove;
var NeedPaint: Boolean;St: String;
begin
  NeedPaint := False;
 if CPX <> $FF then
 begin
  CPX := pTextCX-pTextSX+1;
  if (CPX > Xs-3) then pTextSX := (pTextCX-(Xs-3));
  if (CPX < 1) then pTextSX := (pTextCX);
  if CPX <> (pTextCX-pTextSX+1) then NeedPaint := True;
  CPX := pTextCX-pTextSX+1;
  if (pTextSX > pTextCXMax) then pTextCXMax := pTextSX;
 end else CPX := pTextCX-pTextSX+1;
 if CPY <> $FF then
 begin
  CPY := pTextCY-pTextSY+1;
  if (CPY > Ys-3) then pTextSY := (pTextCY-(Ys-3));
  if (CPY < 1) then pTextSY := (pTextCY);
  if CPY <> (pTextCY-pTextSY+1) then NeedPaint := True;
  CPY := pTextCY-pTextSY+1;
  if pTextSY > pTextCYMax then pTextCYMax := pTextSY;
 end else CPY := pTextCY-pTextSY+1;

 IDE_Screen.tIns := not tIns;

 if not InPaint then
 if NeedPaint then IDE_Desktop^.QuickPaint else
 begin
  {- Update Cursor Position -}
  IDE_Screen.CPX := Xo+CPX; IDE_Screen.CPY := Yo+CPY;
  if (CPX >= Xs-1) or (CPY >= Ys-1) or (CPX < 1) or (CPY < 1) or
     (CPX > IDE_Screen.ScrWidth) or (CPY > IDE_Screen.ScrHeight) then
       begin;IDE_Screen.CPX:=$FF;IDE_Screen.CPY:=$FF;end;

   ShowCursorST;
{$IFDEF Debug}
 IDE_Desktop^.QuickPaint;
{$ELSE}
  St := UCase(StringAT(pTextCX, pTextCY));
  if (St = 'BEGIN') or (St = 'END') or (St = 'CASE') or (St = 'RECORD') or (St = 'ASM') or
     (PaintWinOnMove) then
   IDE_Desktop^.QuickPaint else IDE_UpdateVideo;
{$ENDIF}
 end;
end;

Procedure IDE_SourceWindowType.Paint;

Var cX, cY: Integer;l, il: Longint;sCol, sBCol: Byte;sBNest: Integer;
    pTHi : HiLiteBlockType;cWBack: Byte; pCP: Longint;
    comNextLev: Longint;

    Procedure OutText(St: String);
    var i: byte;wx, wy: integer;
    begin
     sCol := (sCol and $F) + (cWBack and $F0);
     for i:=1 to Length(St) do
     if St[i] <> #$A then
     begin
      wx := cX-pTextSX; wy := cY;
      if (wx >= 0) and (wx < Xs-2) then
{$IFNDEF NoBlockHilite}
       if ((il+i-1 > pTextSelStart) and (il+i-1 < pTextSelEnd)) and (pTextSel) then
        IDE_WriteXYC_Ch(wX+Xo+1, wY+Yo+1, St[i], (sCol and $F) + (IDE.c.BlockSel Shl 4))
       else
{$ENDIF}
        IDE_WriteXYC_Ch(wX+Xo+1, wY+Yo+1, St[i], sCol);
      Inc(cX);
     end else break;
     cWBack := cWinBack and $F0;
    end;

    Procedure CalcCol;
    begin
     if pTHi._AsmSrc then sCol := IDE.c.Syntax.AsmSrc;
     Case pTHi.bt of
      _Comment1, _Comment2: sCol := IDE.c.Syntax.Comment;
      _String1, _String2: sCol := IDE.c.Syntax.Strings;
     end;
     sCol := (sCol and $F) + (cWBack and $F0);
    end;
    Procedure ColourWord(St: String);
    var i, w: word;
    begin
     w:=$FF;
     St := UCase(St);

     for i:=0 to Res2Word_n do
      if St = Res2Word[i] then begin;sCol := IDE.c.Syntax.Reserved2;break;end;

{** johan}
{     for i:=0 to word(MaxToken) do
      if St = TokenName[token(i)] then
        begin;w:=i;sCol := IDE.c.Syntax.Reserved; break;end;
}
     for i:=0 to ResWord_n do
      if St = ResWord[i] then begin;w:=i;sCol := IDE.c.Syntax.Reserved;break;end;

     cWBack := cWinBack and $F0;

     if IDE.BlockHighlight then
     begin
      if (w <= 3) and
       ((pTHi.bNestLvl > 0) or ((pCP >= il) and (pCP <= il+Length(St)))) then
          Inc(pTHi.bNestLvl);

      if (w <= 4) and (pTHi.bNestLvl = 1) then
        begin; cWBack := IDE.c.BlockHi Shl 4;PaintWinOnMove:=True;end;

      if (w = 4) and (pTHi.bNestLvl > 0) then Dec(pTHi.bNestLvl);
     end;

    end;
    Procedure WriteHiLine;
    var BreakChar: Char; cWord: String;
    begin
     cX := 0;
     Repeat
      cWord := '';
      il := l;
      while (Pos(Chr(pText^[l]), IdenSt) = 0) do
      begin
       cWord := cWord + Chr(pText^[l]);
       Inc(l); if Length(cWord) >= $FF then break; {- Prevent string from overflowing -}
      end;
      BreakChar := chr(pText^[l]); Inc(l);

      if IDE.SyntaxHighlight and pSyntaxHighlight then
      begin
       sCol := $E;
       if (pTHi.bt = _none) then
       begin
        Case cWord[1] of
         '0'..'9','$': if (not pTHi._AsmSrc) then sCol := IDE.c.Syntax.Numbers;
         '#': sCol := IDE.c.Syntax.Strings;
        end;
        if (not pTHi._AsmSrc) then ColourWord(cWord);
       end;
       CalcCol;
       if (pTHi._asmSrc) and (UCase(cWord)='END') then sCol := (sCol and $F0)+IDE.c.Syntax.Reserved;
       sCol := (sCol and $F) + (cWBack and $F0);
       OutText(cWord);
       sCol := IDE.c.Syntax.Symbols;
       CalcCol;
       Case pTHi.bt of
        _Comment1, _Comment2:
                  begin

                  Case BreakChar of
                    '{': begin;Inc(comNextLev);pTHi.bt := _Comment1;end;
                    '(': if pText^[l] = $2A then begin;Inc(comNextLev);pTHi.bt := _Comment2;end;
                    '}': begin
                          if comNextLev>0 then Dec(comNextLev);
                          if (comNextLev=0) or (not IDE.NestComment) then begin;pTHi.bt := _none;end;
                         end;
                    ')': if (pText^[l-2] = $2A) then begin
                          if comNextLev>0 then Dec(comNextLev);
                          if (comNextLev=0) or (not IDE.NestComment) then begin;pTHi.bt := _none;end;
                         end;
                  end;
                  if comNextLev<>0 then begin;sCol := IDE.c.Syntax.Comment;end;

                  end;
        _String1: if BreakChar = #34 then begin;sCol := IDE.c.Syntax.Strings;pTHI.bt := _none;end;
        _String2: if BreakChar = #39 then begin;sCol := IDE.c.Syntax.Strings;pTHI.bt := _none;end;
        else
        begin
          if pTHI._AsmSrc then if (UCase(cWord)='END') then
                        if (Pos(BreakChar, IdenSt)>0) then
                         begin;sCol := IDE.c.Syntax.Symbols;pTHI._AsmSrc := False;end;
         if pTHi.bt = _none then
         Case BreakChar of
           '{': begin;sCol := IDE.c.Syntax.Comment;pTHI.bt := _Comment1;Inc(comNextLev);end;
           '(': if pText^[l] = $2A then begin;sCol := IDE.c.Syntax.Comment;pTHI.bt := _Comment2;Inc(comNextLev);end;
           #34: begin;sCol := IDE.c.Syntax.Strings;pTHI.bt := _String1;end;
           #39: begin;sCol := IDE.c.Syntax.Strings;pTHI.bt := _String2;end;
           #10,#32,#0,#255,';': if (UCase(cWord)='ASM') then begin;sCol := IDE.c.Syntax.AsmSrc;pTHI._AsmSrc := True;end;
         end;
        end;
       end;
       cWBack := cWinBack and $F0;
       OutText(BreakChar);
      end
      else
      begin
       sCol := IDE.c.Syntax.none;
       cWBack := cWinBack and $F0;
       il := l - 1;
       OutText(cWord);
       OutText(BreakChar);
      end;
     until BreakChar = #$A;
      Case pTHi.bt of
       _String1, _String2: pTHi.bt := _none;
      end;
    end;
Var St: String;
begin
 PaintWinOnMove := False;
 comNextLev := 0;

 if Pos('.PAS', UCase(Title)) > 0 then pSyntaxHighlight := True else pSyntaxHighlight := False;

 InPaint := True; {- This causes UpdateCP to NOT call Paint again -}
 UpdateCP;        {- otherwise, blank-tik-tik-tik-tik-tik (Recursive call to self, or an endless loop) -}
 InPaint := False;
 Inherited Paint; {- Paint the window -}

 {- Display Slider indicator -}
 if InFront then
 begin
  if (pTextCXMax > 0) and (pTextSX<=pTextCXMax) then
   IDE_WriteXYC_Ch(Xo+19+ round((Xs-23)*pTextSX/(pTextCXMax-(Xs-23))) , Yo+Ys-1, #254, IDE_cWinSlide);
  if (pTextCYMax > 0) and (pTextSY<=pTextCYMax) then
   IDE_WriteXYC_Ch(Xo+Xs-1, Yo+2+ round((Ys-5)*pTextSY/(pTextCYMax-(Ys-5))), #254, IDE_cWinSlide);
 end;

 {- Display cursor position -}
  ShowCursorST;

 {- Calc Cursor Position -}
 pCP := CalcTextPos(pTextCX, pTextCY);

 pTHi := pTextHiStart;

 l := IDE_SourceWindowType.CalcTextPos(0, pTextSY);
 sCol := IDE.c.Syntax.none;
 cWBack := cWinBack and $F0;
 if Ys > 3 then
  for cY := 0 to Ys-3 do
   begin
    WriteHiLine;
    if cY = 0 then pTextHiFirst := pTHi
   end;

 pTextHiEnd := pTHi;
end;


{- Quickly loads a text file into the window -}
Procedure IDE_SourceWindowType.LoadFile(St: String);
var Fh: File; Buf: Array[0..512] of byte; BufC, w, mX, mY: Word; l: Longint;
begin
 if FileExists(St) then
 begin
  Assign(Fh, St);
  Reset(Fh, 1);
  pTextSize := 0;
   Repeat
    BlockRead(Fh, Buf[0], 512, w);
    if w>0 then
     for BufC := 0 to w-1 do if Buf[BufC] <> $D then
       begin
       if Buf[BufC] = 9 then
        for l := 0 to 7 do begin;pText^[pTextSize] := 32;Inc(pTextSize);end
       else
        begin;pText^[pTextSize] := Buf[BufC];Inc(pTextSize);end;
       end;
   until eof(Fh) or (FilePos(Fh)>=IDE_MaxTextSize-512);
  Close(Fh);

 {- Calculate Length - for Scrollbars -}
 mX := 0; mY := 0; l := 0;
 While (l<= pTextSize) do
 begin
  w := 0;
  repeat inc(l);Inc(w);Until pText^[l] = $A;
  if w > mX then mX := w;
  Inc(mY);
 end;
 pTextCXMax := mX; pTextCYMax := mY;
 end;
 Modified := False;
 IDE_Desktop^.QuickPaint;
end;

{- Quickly saves a text file into the window -}
Procedure IDE_SourceWindowType.SaveFile(St: String);
var Fh: File; Buf: Array[0..514] of byte; w, mX, mY, BufC: Word; l: Longint;
    St2: String;
begin
 { Make backup }
 St2:=St;if Pos('.', St2)>0 then St2[0]:=Chr(Pos('.', St2)-1);St2:=St2+'.BAK';
 if FileExists(St) then
  begin
   if FileExists(St2) then DeleteFile(St2);
   RenameFile(St, St2);
  end;

  FileMode := 1;
  Assign(Fh, St);
  Rewrite(Fh, 1);
   l := 0; BufC := 0;
  While (l<pTextSize) do
  begin
   Buf[BufC] := pText^[l]; Inc(BufC);
   if Buf[BufC-1] = $A then begin;Buf[BufC-1] := $D;Buf[BufC] := $A; Inc(BufC);end;
   if BufC >= 512 then
   begin
    BlockWrite(Fh, Buf[0], BufC, w);
    BufC := 0;
   end;
   Inc(l);
  end;
   BlockWrite(Fh, Buf[0], BufC, w);

  Close(Fh);
  FileMode := 2;

 Modified := False;
end;

Procedure IDE_SourceWindowType.InsertFile(St: String);
 Procedure InsertString(inSt: String);
 var k: KeyType;i: byte;
 begin
  k.Ctrl := False; k.Alt := False; k.Shift := False;
  k.Ext := False;
  for i:=1 to length(inSt) do begin;k.Ch := inSt[i];IDE_Desktop^.DontDrawNext_B:=True;KeyEvent(k);
                                    IDE_Desktop^.DontDrawNext_B:=False;end;
 end;
var Fh: File; Buf: Array[0..512] of byte;BufC, w: Word;
begin

 IDE_Desktop^.DontDrawNext_B := True;
 if FileExists(St) then
 begin
  Assign(Fh, St);
  Reset(Fh, 1);
  if Pos('.', St)>0 then St[Pos('.',St)] := '_';
  InsertString(#13'Const '+St+'_data: Array[0..'+Numb(FileSize(Fh)-1)+'] of byte =('#13'  ');
   Repeat
    BlockRead(Fh, Buf[0], 512, w);
    if w>0 then
     for BufC := 0 to w-1 do
      begin;
        if (w=512) or (BufC<w-1) then
         InsertString('$'+HexStr[(Buf[BufC] Shr 4)+1]+HexStr[(Buf[BufC] and $F)+1]+',')
        else
         InsertString('$'+HexStr[(Buf[BufC] Shr 4)+1]+HexStr[(Buf[BufC] and $F)+1]);
        {- This relies on Auto-tab -}
        if BufC and 15 = 15 then InsertString(#13);
      end;

   until eof(Fh) or (FilePos(Fh)>=IDE_MaxTextSize-512);
  Close(Fh);
  InsertString(');'#13);
 end;
 IDE_Desktop^.DontDrawNext_B := False;
 UpdateCPMove;
 IDE_Desktop^.QuickPaint;
end;


Function IDE_SourceWindowType.CalcTextPos(cx, cy: integer): Longint;
var l: Longint; i, x, y: Word;
begin

    {- Find Y Position -}
    l := 0; y := 0;
    while (y<cy) and (l+1<pTextSize) do
    begin
     if (pText^[l] = $A) then Inc(y);
     Inc(l);
    end;
    {- Find X Position -}
    x := 0;
    while (x<cx) and (pText^[l] <> $A) and (l<pTextSize) do
    begin
     Inc(l);Inc(x);
    end;

    CalcTextPos := l;
end;

Function IDE_SourceWindowType.StringAT(cx, cy: integer): String;
var sl, l, il: Longint; St: String;
begin
 l := CalcTextPos(cx, cy);
 if Pos(Chr(pText^[l]), IdenSt) > 0 then begin;StringAT := '';exit;end;
 {- Find start of string -}
 while (l>0) and (Pos(Chr(pText^[l]), IdenSt)=0) do Dec(l);
  sL := l;Inc(l);
 {- Find end of string -}
 while (l<pTextSize) and (Pos(Chr(pText^[l]), IdenSt)=0) do Inc(l);
 St := ''; Inc(sl);Dec(l);
 for il:=sl to l do St := St + Chr(pText^[il]);
 StringAT := St;
end;

Procedure IDE_SourceWindowType.CalcTextHI;
var l, lend: Longint;cWord: String[5];BreakChar: Char;
    comNextLev: Longint;
begin
 if (not IDE.SyntaxHighlight) or (IDE.QuickHighlight) then exit;

 lend := CalcTextPos(pTextSX, pTextSY);
 l := 0; pTextHiStart.bt := _none; pTextHiStart._AsmSrc := False;
 comNextLev := 0;
 while (l<lend) and (l<pTextSize) do
 begin
  cWord[0] := #3;
  Move(pText^[l], cWord[1], 3);

  Case pTextHiStart.bt of
   _String1 : if (Chr(pText^[l]) = #34) then pTextHiStart.bt := _none;
   _String2 : if (Chr(pText^[l]) = #39) then pTextHiStart.bt := _none;
(*   _Comment1: if (Chr(pText^[l]) = '}') then pTextHiStart.bt := _none;
   _Comment2: if (Chr(pText^[l]) = '*') and (Chr(pText^[l+1]) = ')') then pTextHiStart.bt := _none;*)
   _Comment1, _Comment2:
                begin
                  Case chr(pText^[l]) of
                    '{': Inc(comNextLev);
                    '(': if pText^[l+1] = $2A then Inc(comNextLev);
                    '}': begin
                          if comNextLev>0 then Dec(comNextLev);
                          if (comNextLev=0) or (not IDE.NestComment) then begin;pTextHiStart.bt := _none;end;
                         end;
                    ')': if (pText^[l-1] = $2A) then begin
                          if comNextLev>0 then Dec(comNextLev);
                          if (comNextLev=0) or (not IDE.NestComment) then begin;pTextHiStart.bt := _none;end;
                         end;
                  end;
                  if (comNextLev<>0) and
                     (pTextHiStart.bt<>_Comment1) and
                     (pTextHiStart.bt<>_Comment2) then pTextHiStart.bt := _Comment1;
                 end;
   _none: begin
          Case Chr(pText^[l]) of
            #34: pTextHiStart.bt := _String1;
            #39: pTextHiStart.bt := _String2;
            '{': begin;pTextHiStart.bt := _Comment1;Inc(comNextLev);end;
            '(': if Chr(pText^[l+1]) = '*' then begin;pTextHiStart.bt := _Comment2;Inc(comNextLev);end;
            'A','a': if (UCase(cWord)='ASM') then
                      if (Pos(Chr(pText^[l-1]), IdenSt)>0) then
                       if (Pos(Chr(pText^[l+3]), IdenSt)>0) then
                         pTextHiStart._AsmSrc := True;
          end;
          if pTextHiStart._AsmSrc then
{           if Chr(pText^[l-1]) in [#32,#0,#255,';',#10] then
           if Chr(pText^[l+3]) in [#32,#0,#255,';',#10] then}
           if (Pos(Chr(pText^[l-1]), IdenSt)>0) then
           if (Pos(Chr(pText^[l+3]), IdenSt)>0) then
            if (UCase(cWord)='END') then pTextHiStart._AsmSrc := False;
         end;
  end;
  Inc(l);
 end;

end;









Constructor IDE_DesktopType.Init;
var i, ii: word;
begin
 tWin.Init(16, 4);

 Menu_cItem := 0;

 {- Clear Menu structure -}
 for i:=1 to tMenuMax do
 begin
   tMenu[ i].NameSt      := '';
   tMenu[ i].HelpSt      := '';
   tMenu[ i].Accel.Ch    := #0;
   tMenu[ i].Accel.Alt   := False;
   tMenu[ i].Accel.Shift := False;
   tMenu[ i].Accel.Ctrl  := False;
   tMenu[ i].Accel.Ext   := False;
   tMenu[ i].cItem       := 1;
  for ii:=1 to tSubMenuMax do
  begin
   tMenu[ i].SubMenu[ii].NameSt      := '';
   tMenu[ i].SubMenu[ii].HelpSt      := '';
   tMenu[ i].SubMenu[ii].Accel.Ch    := #0;
   tMenu[ i].SubMenu[ii].Accel.Alt   := False;
   tMenu[ i].SubMenu[ii].Accel.Shift := False;
   tMenu[ i].SubMenu[ii].Accel.Ctrl  := False;
   tMenu[ i].SubMenu[ii].Accel.Ext   := False;
  end;
 end;

 tMenu[ 1].NameSt := '~F~ile';
 tMenu[ 1].HelpSt := 'File management commands (Open, New, Save, etc.)';
 tMenu[ 1].Accel.Ch  := #33{'F'};
 tMenu[ 1].Accel.Alt := True;

 tMenu[ 1].SubMenu[1].NameSt := '~N~ew';
 tMenu[ 1].SubMenu[1].Accel.Ch := 'N';
 tMenu[ 1].SubMenu[1].ID       := cm_NewEdit;
 tMenu[ 1].SubMenu[1].HelpSt   := 'Create a new Edit window';

 tMenu[ 1].SubMenu[2].NameSt := '~O~pen...'#8'F3';
 tMenu[ 1].SubMenu[2].Accel.Ch := 'O';
 tMenu[ 1].SubMenu[2].ID       := cm_OpenEdit;
 tMenu[ 1].SubMenu[2].HelpSt   := 'Open a file in an Edit window';

 tMenu[ 1].SubMenu[3].NameSt := '~S~ave'#8'F2';
 tMenu[ 1].SubMenu[3].Accel.Ch := 'S';
 tMenu[ 1].SubMenu[3].ID       := cm_SaveEdit;
 tMenu[ 1].SubMenu[3].HelpSt   := 'Save the file in the Edit window';

 tMenu[ 1].SubMenu[4].NameSt := 'Save ~a~s';
 tMenu[ 1].SubMenu[4].Accel.Ch := 'A';
 tMenu[ 1].SubMenu[4].ID       := cm_SaveAsEdit;
 tMenu[ 1].SubMenu[4].HelpSt   := 'Save the current Edit window under a different name';

 tMenu[ 1].SubMenu[5].NameSt := '-';

 tMenu[ 1].SubMenu[6].NameSt := '~D~OS Shell'#8'Alt-Z';
 tMenu[ 1].SubMenu[6].Accel.Ch := 'D';
 tMenu[ 1].SubMenu[6].ID       := cm_DOSShell;
 tMenu[ 1].SubMenu[6].HelpSt   := 'Shell to DOS';

 tMenu[ 1].SubMenu[7].NameSt := 'E~x~it'#8'Alt-X';
 tMenu[ 1].SubMenu[7].Accel.Ch := 'X';
 tMenu[ 1].SubMenu[7].ID       := cm_Exit;
 tMenu[ 1].SubMenu[7].HelpSt   := 'Exit P32IDE';


 tMenu[ 2].NameSt := '~E~dit';
 tMenu[ 2].HelpSt := 'Cut-and-paste editing commands';
 tMenu[ 2].Accel.Ch  := #18{'E'};
 tMenu[ 2].Accel.Alt := True;


 tMenu[ 3].NameSt := '~S~earch';
 tMenu[ 3].HelpSt := 'Text searching commands';
 tMenu[ 3].Accel.Ch  := #31{'S'};
 tMenu[ 3].Accel.Alt := True;

 tMenu[ 4].NameSt := '~R~un';
 tMenu[ 4].HelpSt := 'Execution commands';
 tMenu[ 4].Accel.Ch  := #19{'R'};
 tMenu[ 4].Accel.Alt := True;

  tMenu[ 4].SubMenu[1].NameSt := '~R~un';
  tMenu[ 4].SubMenu[1].Accel.Ch := 'R';
  tMenu[ 4].SubMenu[1].ID       := cm_Run;
  tMenu[ 4].SubMenu[1].HelpSt   := 'Build/Run';



 tMenu[ 5].NameSt := '~C~ompile';
 tMenu[ 5].HelpSt := 'Source Building commands';
 tMenu[ 5].Accel.Ch  := #46{'C'};
 tMenu[ 5].Accel.Alt := True;

  tMenu[ 5].SubMenu[1].NameSt := '~C~ompile';
  tMenu[ 5].SubMenu[1].Accel.Ch := 'C';
  tMenu[ 5].SubMenu[1].ID       := cm_Compile;
  tMenu[ 5].SubMenu[1].HelpSt   := 'Compile Source';

  tMenu[ 5].SubMenu[2].NameSt := '~L~ink';
  tMenu[ 5].SubMenu[2].Accel.Ch := 'L';
  tMenu[ 5].SubMenu[2].ID       := cm_Link;
  tMenu[ 5].SubMenu[2].HelpSt   := 'Link Pre-compiled Source';

  tMenu[ 5].SubMenu[3].NameSt := '~B~uild';
  tMenu[ 5].SubMenu[3].Accel.Ch := 'B';
  tMenu[ 5].SubMenu[3].ID       := cm_Build;
  tMenu[ 5].SubMenu[3].HelpSt   := 'Build Executable';


  tMenu[ 5].SubMenu[4].NameSt := '-';

  tMenu[ 5].SubMenu[5].NameSt := '~I~nformation';
  tMenu[ 5].SubMenu[5].Accel.Ch := 'I';
  tMenu[ 5].SubMenu[5].ID       := cm_InfoBOX;
  tMenu[ 5].SubMenu[5].HelpSt   := 'Show status information';

 tMenu[ 6].NameSt := '~D~ebug';
 tMenu[ 6].HelpSt := 'Various Commands';
 tMenu[ 6].Accel.Ch  := #32{'D'};
 tMenu[ 6].Accel.Alt := True;


  tMenu[ 6].SubMenu[1].NameSt := '~U~ser Screen';
  tMenu[ 6].SubMenu[1].Accel.Ch := 'U';
  tMenu[ 6].SubMenu[1].ID       := cm_UserScreen;
  tMenu[ 6].SubMenu[1].HelpSt   := 'Switch to the full screen user output';

 tMenu[ 7].NameSt := '~T~ools';
 tMenu[ 7].HelpSt := 'User Installed Tools and preferences';
 tMenu[ 7].Accel.Ch  := #20{'T'};
 tMenu[ 7].Accel.Alt := True;


 tMenu[ 7].SubMenu[1].NameSt := 'Toggle ~S~yntax Highlights'#8'Alt-F7';
 tMenu[ 7].SubMenu[1].Accel.Ch := 'S';
 tMenu[ 7].SubMenu[1].ID       := cm_SyntaxHighlightToggle;
 tMenu[ 7].SubMenu[1].HelpSt   := 'Toggles Sytax Highlighting';

 tMenu[ 7].SubMenu[2].NameSt   := 'Toggle ~B~lock Highlights'#8'Alt-F8';
 tMenu[ 7].SubMenu[2].Accel.Ch := 'B';
 tMenu[ 7].SubMenu[2].ID       := cm_BlockHighlightToggle;
 tMenu[ 7].SubMenu[2].HelpSt   := 'Toggles Block Highlighting';

 tMenu[ 7].SubMenu[3].NameSt   := 'Toggle Screen Si~z~e'#8'Alt-F10';
 tMenu[ 7].SubMenu[3].Accel.Ch := 'Z';
 tMenu[ 7].SubMenu[3].ID       := cm_HeightToggle;
 tMenu[ 7].SubMenu[3].HelpSt   := 'Toggles Screen Size';

 tMenu[ 7].SubMenu[4].NameSt   := '-';

 tMenu[ 7].SubMenu[5].NameSt   := '~U~ser Screen'#8'Alt-F5';
 tMenu[ 7].SubMenu[5].Accel.Ch := 'U';
 tMenu[ 7].SubMenu[5].ID       := cm_UserScreen;
 tMenu[ 7].SubMenu[5].HelpSt   := 'Show the full screen user output';

 tMenu[ 7].SubMenu[6].NameSt   := 'User ~W~indow'#8'Alt-Q';
 tMenu[ 7].SubMenu[6].Accel.Ch := 'W';
 tMenu[ 7].SubMenu[6].ID       := cm_UserWindow;
 tMenu[ 7].SubMenu[6].HelpSt   := 'Show the full screen user output';

 tMenu[ 7].SubMenu[7].NameSt   := '-';

 tMenu[ 7].SubMenu[8].NameSt   := '~A~SCII Table';
 tMenu[ 7].SubMenu[8].Accel.Ch := 'A';
 tMenu[ 7].SubMenu[8].ID       := cm_ASCIIWin;
 tMenu[ 7].SubMenu[8].HelpSt   := 'Show''s an ASCII Table';

 tMenu[ 7].SubMenu[9].NameSt   := '~C~alculator';
 tMenu[ 7].SubMenu[9].Accel.Ch := 'C';
 tMenu[ 7].SubMenu[9].ID       := cm_CALCWin;
 tMenu[ 7].SubMenu[9].HelpSt   := 'Display''s a Calculator';


 tMenu[ 8].NameSt := '~O~ptions';
 tMenu[ 8].HelpSt := 'Set compiler options';
 tMenu[ 8].Accel.Ch  := #24{'O'};
 tMenu[ 8].Accel.Alt := True;

 tMenu[ 9].NameSt := '~W~indow';
 tMenu[ 9].HelpSt := 'Windowing commands';
 tMenu[ 9].Accel.Ch  := #17{'W'};
 tMenu[ 9].Accel.Alt := True;


 tMenu[10].NameSt := '~H~elp';
 tMenu[10].HelpSt := 'Help commands (No Online Help yet)';
 tMenu[10].Accel.Ch  := #35{'H'};
 tMenu[10].Accel.Alt := True;


 tMenu[10].SubMenu[1].NameSt   := '~C~ontributors';
 tMenu[10].SubMenu[1].Accel.Ch := 'C';
 tMenu[10].SubMenu[1].ID       := cm_ContribWindow;
 tMenu[10].SubMenu[1].HelpSt   := 'Show who helped make this';

 tMenu[10].SubMenu[2].NameSt   := '~A~bout'#8'Alt-A';
 tMenu[10].SubMenu[2].Accel.Ch := 'A';
 tMenu[10].SubMenu[2].ID       := cm_AboutWindow;
 tMenu[10].SubMenu[2].HelpSt   := 'Show version information';

 DontDrawNext_B := False;

 IDE_DesktopType.Paint;
end;

Destructor IDE_DesktopType.Done;
 Procedure CloseWindow(pW: pIDE_WindowType); far;
 begin
  pW^.done;
 end;
begin
{--** NOTE: This give RunTime errors?? y?  **--}
{ tWin.ForEach(@CloseWindow);}
{ tMenu.DeleteAll;}
 tWin.DeleteAll;
{ tWin.Done;}
end;


Procedure IDE_DesktopType.QuickPaint;
var pW: pIDE_WindowType;
begin
 if DontDrawNext_B then begin;DontDrawNext_B := False;exit;end;
 if tWin.count > 0 then
 begin
  pW := tWin.At(tWin.Count-1);
  pW^.Paint;
 end;

 MenuPaint;

 IDE_UpdateVideo;
end;

Procedure IDE_DesktopType.DontDrawNext;
begin
 DontDrawNext_B := True;
end;

Procedure IDE_DesktopType.Paint;
 Procedure PaintWin(pW: pIDE_WindowType); far;
 begin
  if pW <> nil then pW^.Paint;
 end;
var i: word;
begin
 if DontDrawNext_B then begin;{DontDrawNext_B := False;}exit;end;
 IDE_Screen.CPX:=$FF;IDE_Screen.CPY:=$FF;

 {- Paint the background -}
 for i:=1 to IDE_Screen.ScrHeight-2 do
  IDE_WriteXYC(0,  i, '°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°', IDE_cDesktop);

{ IDE_WriteXYC(5,  5, 'He~1l~2l~3o', $71);}

 IDE_WriteXYC(32,  (IDE_Screen.ScrHeight div 2)-2, 'PPPPP°°333°°°222°', IDE_cDesktop);
 IDE_WriteXYC(32,  (IDE_Screen.ScrHeight div 2)-1, 'PP°°PP°°°°3°2°°°2', IDE_cDesktop);
 IDE_WriteXYC(32,  (IDE_Screen.ScrHeight div 2)  , 'PPPPP°°°33°°°°°2°', IDE_cDesktop);
 IDE_WriteXYC(32,  (IDE_Screen.ScrHeight div 2)+1, 'PP°°°°°°°°3°°°2°°', IDE_cDesktop);
 IDE_WriteXYC(32,  (IDE_Screen.ScrHeight div 2)+2, 'PP°°°°°333°°22222', IDE_cDesktop);

 IDE_WriteXYC(25,  (IDE_Screen.ScrHeight div 2)+5, 'Beta version - Under Development', IDE_cDesktop);
 IDE_WriteXYC(34,  (IDE_Screen.ScrHeight div 2)+6, 'So be nice ;-)', IDE_cDesktop);

 if (@tWin <> nil) then
  tWin.ForEach(@PaintWin);

 QuickPaint;
end;

Procedure IDE_DesktopType.MenuPaint;
Var xPos, cMenu, sxPos: Integer; HLPSt: String;
 Procedure DrawMenu(i: Word);
 begin
  if (cMenu = Menu_cItem) then
   IDE_WriteXYC(xPos, 0, ' '+TildaToC(tMenu[i].NameSt)+' ', IDE_cMenuH)
  else
   IDE_WriteXYC(xPos, 0, ' '+TildaToC(tMenu[i].NameSt)+' ', IDE_cMenu);
  if (cMenu = Menu_cItem) then sxPos := xPos;

  Inc(xPos, LengthC(TildaToC(tMenu[i].NameSt))+2);
 end;
 Procedure ShowSubMenu(cM: Word);
 var xS, i, w: Integer;St, cSt: String;
 begin
  IDE_Screen.CPX := $FF; IDE_Screen.CPY := $FF;

  cSubMenu.nItem := 0;
  for i := 1 to tSubMenuMax do if LengthT(tMenu[cM].SubMenu[i].NameSt) > 0 then Inc(cSubMenu.nItem) else break;
{  for i := 1 to 25 do if Pos(#8,tMenu[cM].SubMenu[i].NameSt) > 0 then begin;Inc(xS, 2);break;end;}

  {- Find Max-Width -}
  xS := 0; for i := 1 to cSubMenu.nItem do
   if Pos(#8,tMenu[cM].SubMenu[i].NameSt)>0 then
    begin;if LengthT(tMenu[cM].SubMenu[i].NameSt)+3 > xS then xS := LengthT(tMenu[cM].SubMenu[i].NameSt)+3;end
   else
    if LengthT(tMenu[cM].SubMenu[i].NameSt) > xS then xS := LengthT(tMenu[cM].SubMenu[i].NameSt);


  cSubMenu.sX := sxPos+1;
  cSubMenu.eX := sxPos+xS;

  {- Clip window to side of screen -}
  if cSubMenu.eX+xS >= IDE_Screen.ScrWidth then
  begin
   sxPos := IDE_Screen.ScrWidth-xS-5;
   cSubMenu.sX := sxPos+1;
   cSubMenu.eX := sxPos+xS;
  end;

  if tMenu[cM].cItem > 0 then
   HLPSt := tMenu[cM].SubMenu[tMenu[cM].cItem].HelpSt;

   St := ' Ú';
   for i:=0 to xS+1 do St := St + 'Ä';
   St := St + '¿ ';
  IDE_WriteXYC(sxPos-1, 1, St, IDE_cMenu);

  for i:=0 to 24 do
  begin
   if tMenu[cM].SubMenu[i+1].NameSt = '' then break;
   cSt := TildaToC(tMenu[cM].SubMenu[i+1].NameSt);

   if cSt[1] = '-' then
   begin
    St := ' Ã';
    for w:=0 to xS+1 do St := St + 'Ä';
    St := St + '´ ';
    IDE_WriteXYC(sxPos-1, i+2, St, IDE_cMenu);
    IDE_Grey(sxPos-1+Length(St), i+2);
    IDE_Grey(sxPos+Length(St), i+2);
   end
   else
   begin
    St := ' ³';
    for w:=0 to xS+1 do St := St + ' ';

    St := St + '³ ';
    IDE_WriteXYC(sxPos-1, i+2, St, IDE_cMenu);
    IDE_Grey(sxPos-1+Length(St), i+2);
    IDE_Grey(sxPos+Length(St), i+2);

    if (Pos(#8, cSt) > 0) then
     begin
      St := cSt;
      w := Pos(#8, cSt);
      Delete(St, 1, w);
      cSt[0] := Chr(w-1);
      IDE_WriteXYC(sxPos-1+3, i+2, cSt, IDE_cMenu);
      IDE_WriteXYC(sxPos-1+3 + xS - Length(St), i+2, St, IDE_cMenu);
     end
    else
     IDE_WriteXYC(sxPos-1+3, i+2, cSt, IDE_cMenu);

    if (i+1=tMenu[cM].cItem) then
     for w:=0 to xS+1 do IDE_SetBC(sxPos+1+W, i+2, IDE_cMenuH Shr 4);
   end;

  end;

   w := i;
   St := ' À';
   for i:=0 to xS+1 do St := St + 'Ä';
   St := St + 'Ù ';
   IDE_WriteXYC(sxPos-1, w+2, St, IDE_cMenu);
   IDE_Grey(sxPos-1+Length(St), w+2);
   IDE_Grey(sxPos+Length(St), w+2);
   for i:=1 to xS+7 do IDE_Grey(sxPos+i-1, w+3);

 end;
var pW: pIDE_WindowType;
begin
  if tWin.Count>0 then
  begin
   pW := tWin.At(tWin.Count-1);
   if pW^.Moving then begin;IDE_BottomHelp(IDE_BottomHelpST);exit;end;
  end;

  {- Clear the Top and Bottom Lines -}
  IDE_WriteXYC(0,  0, '                                                                                ', IDE_cMenu);
  IDE_WriteXYC(0, IDE_Screen.ScrHeight-1,
                      '                                                                                ', IDE_cMenu);
  IDE_BottomHelp('#1');

  {- Draw the top menu -}
  xPos := 1; for cMenu := 1 to tMenuMax do DrawMenu(cMenu);
  {- Show help line -}
  if Menu_cItem > 0 then
  begin
   HLPSt := tMenu[Menu_cItem].HelpSt;
   {- Display Sub-Menu -}
   ShowSubMenu(Menu_cItem);


   IDE_BottomHelp(HlpSt);
  end;

end;

Procedure IDE_DesktopType.IDE_BottomHelp(St: String);
var i: byte;
begin
 IDE_BottomHelpST := St;
 if St = '' then St := TildaToC(' ~F1~ Help ³ ') + '~8No help available' else
 if St = '#1' then St := {TildaToC(' ~F1~ Help ³ ') + }' ~8No Shortcuts available' else
 if St[1] = '#' then begin;Delete(St,1,1);St := ' ' + TildaToC(St);end else
  St := TildaToC(' ~F1~ Help ³ ') + TildaToC(St);
 for i:=0 to IDE_Screen.ScrWidth-1 do
  IDE_WriteXYC_CH(i, IDE_Screen.ScrHeight-1, ' ', IDE_cMenu);
 IDE_WriteXYC(0, IDE_Screen.ScrHeight-1, St, IDE_cMenu);
end;

Procedure IDE_DesktopType.ProcessMouseEvent;
Var ml,mm,mr:boolean;mx,my: integer;pWin: pIDE_WindowType;
    ModalFound: Boolean;
 Procedure CheckInFront(pW: pIDE_WindowType); far;
 begin
  if pW^.Modal then begin;pWin := nil;ModalFound := True;end;
  if (mx >= pW^.Xo) and (mx < pW^.Xo+pW^.Xs) and
     (my >= pW^.Yo) and (my < pW^.Yo+pW^.Ys) then
      pWin := pW;
 end;
begin
 ml := IDE_MouseL;
 mr := IDE_MouseR;
 mm := (ml and mr);
 mx := IDE_MouseXL;
 my := IDE_MouseYL;

 if Menu_cItem = 0 then
 begin
  pWin := nil;
  ModalFound := False;
  tWin.ForEach(@CheckInFront);
  { Found Window }
  if pWin <> nil then
  begin
   { Is window in front? }
   if (pWin = tWin.At(tWin.Count-1)) or (Key_Ctrl) then
    { Window is infront so pass on the mouse information }
    pWin^.MouseEvent(ml,mm,mr,mx-pWin^.Xo,my-pWin^.Yo)
   else
    { Window is not infront so bring to front first if clicked }
   begin
    if ml then
    begin
     tWin.Delete(pWin);
     tWin.Insert(pWin);
     IDE_Desktop^.Paint;
     if ml then repeat until not IDE_MouseL;
    end;
   end;

  end;

 end;
 { Send the MenuHandler the mousepress }
 Menu_cItem := 0;
 if not ModalFound then
 if (my = 0) and (ml) then MenuHandler(NoKey, mx, my, Ml, Mm, Mr);

end;

Procedure IDE_DesktopType.ProcessKeyEvent;
Var k: KeyType; pW: pIDE_WindowType;
begin
 if not Keypressed then exit;
  IDE_GetKey(k);
 Case k.Alt of
   True: Case k.Ch of {- When Alt-Pressed -}
 {- Alt-X -}  #45: if k.Ext then cmSend(cm_Exit);
 {- Alt-Z -}  #44: if k.Ext then cmSend(cm_DOSShell);
 {- Alt-N -}  #49: if k.Ext then cmSend(cm_NewEdit);
 {- Alt-L -}  #38: if k.Ext then cmSend(cm_LoadFile);
 {- Alt-Q -}  #16: if k.Ext then cmSend(cm_UserWindow);
 {- Alt-A -}  #30: if k.Ext then cmSend(cm_AboutWindow);
 { Alt-F5 }   #108: if k.Ext then cmSend(cm_UserScreen);
 { Alt-F7 }   #110: if k.Ext then cmSend(cm_SyntaxHighlightToggle);
 { Alt-F8 }   #111: if k.Ext then cmSend(cm_BlockHighlightToggle);
              #113: if k.Ext then cmSend(cm_HeightToggle);
              #112: if k.Ext then
                    begin
                     cmSend(cm_Compile);
                     cmSend(cm_Link);
                    end;

            else
              MenuHandler(k, 0, 0, False, False, False);
         end;
  False: begin
          if (k.Ext) and (k.Ch=#67) then cmSend(cm_SyntaxHighlightToggle)
          else
 { F2 }   if (k.Ext) and (k.Ch=#60) then cmSend(cm_SaveEdit)
          else
 { F3 }   if (k.Ext) and (k.Ch=#61) then cmSend(cm_LoadFile)
          else
{Ctrl-F9} if (k.Ext) and (k.Ctrl) and (k.Ch = #67) then
          begin
           {cmSend(cm_BUILD);}
           cmSend(cm_Compile);
           cmSend(cm_Link);
           cmSend(cm_RUN);
          end
          else
          {- Send the key to a window -}
          if tWin.Count>0 then
          begin
           pW := tWin.At(tWin.Count-1);
           pW^.KeyEvent(K);
          end;
         end;
 end;


end;


Procedure IDE_DesktopType.MenuHandler(cKey: KeyType; mX, mY: Integer;mLeft, mMiddle, mRight: Boolean);
Label SelectMenu, SelectSubMenu, EndSelectMenu, SelectMenuEND;
Var xPos, cMenu, cSMenu: Integer; nMx, nMy: Integer;
var nCMD: Word;
 Procedure MouseMenuCheck(i: word);
 begin
  if nMx >= xPos then
  begin
   Inc(xPos, LengthC(TildaToC(tMenu[i].NameSt))+2);
   if nMx <= xPos then Menu_cItem := i;
  end;
 end;
 Procedure KeyMenuCheck(i: word);
 begin
   if cKey.Ch = tMenu[i].Accel.Ch then Menu_cItem := i;
 end;
 Procedure KeySubMenuCheck(i: Word);
 begin
   if (cKey.Ext = tMenu[cMenu].SubMenu[i].Accel.Ext) and
      (UpCase(cKey.Ch) = UpCase(tMenu[cMenu].SubMenu[i].Accel.Ch)) then
       begin
        tMenu[cMenu].cItem := i;
        nCMD := tMenu[cMenu].SubMenu[i].ID;
       end;
 end;
begin
nCMD := 0;


SelectMenu:
 {- Mouse selection of Menu -}
   if (IDE_MouseY = 0) and (IDE_MouseL) then
   begin
    nMx := IDE_MouseX;
    Menu_cItem := 0;
    xPos := 1;
    for cMenu := 1 to tMenuMax do MouseMenuCheck(cMenu);
    if Menu_cItem > 0 then tMenu[Menu_cItem].cItem := 0;
   end;
 {- Keyboard Selection -}
   if (cKey.Alt) then
   begin
    for cMenu := 1 to tMenuMax do KeyMenuCheck(cMenu);
   end;

SelectMenuEND:

 if Menu_cItem > 0 then
   IDE_Desktop^.Paint
 else
    Goto EndSelectMenu;

cMenu := Menu_cItem;

SelectSubMenu:
nCMD := 0;

 if IDE_MouseL then
  Repeat until (IDE_MouseMoved) or (Keypressed)
 else
  Repeat until ((IDE_MouseMoved) and (IDE_MouseL)) or (Keypressed);



 {- Keyboard Selection -}

   if (keypressed) then
   begin
    IDE_GetKey(cKey);

    if (cKey.Alt) then Goto SelectMenu;
    if (not cKey.Alt) then
     begin
      if (not cKey.Ext) then
       begin
        for cSMenu := 1 to tSubMenuMax do KeySubMenuCheck(cSMenu);
        if cKey.Ch = #13 then nCMD := tMenu[cMenu].SubMenu[tMenu[cMenu].cItem].ID;
        if nCMD > 0 then goto EndSelectMenu;

       end;
      if (cKey.Ext) then
       Case cKey.Ch of
        'G':  tMenu[cMenu].cItem := 1; {- Home -}
        'O':  tMenu[cMenu].cItem := cSubMenu.nItem; {- End -}
        'K':  begin {- Left -}
               if Menu_cItem > 1 then Dec(Menu_cItem) else Menu_cItem := tMenuMax;
               goto SelectMenuEND;
              end;
        'M':  begin {- Right -}
               if Menu_cItem < tMenuMax then Inc(Menu_cItem) else Menu_cItem := 1;
               goto SelectMenuEND;
              end;
        'H':  begin {- Up -}
               if tMenu[cMenu].cItem > 1 then Dec(tMenu[cMenu].cItem);
               if tMenu[cMenu].SubMenu[tMenu[cMenu].cItem].NameSt = '-' then
                  Dec(tMenu[cMenu].cItem);
              end;
        'P':  begin {- Down -}
               if tMenu[cMenu].cItem < cSubMenu.nItem then Inc(tMenu[cMenu].cItem);
               if tMenu[cMenu].SubMenu[tMenu[cMenu].cItem].NameSt = '-' then
                  Inc(tMenu[cMenu].cItem);
              end;
        'I':  begin {- Page-Up -}
               if tMenu[cMenu].cItem > 1 then Dec(tMenu[cMenu].cItem);
               if tMenu[cMenu].SubMenu[tMenu[cMenu].cItem].NameSt = '-' then
                  Dec(tMenu[cMenu].cItem);
               While (tMenu[cMenu].SubMenu[tMenu[cMenu].cItem].NameSt <> '-') and
                     (tMenu[cMenu].cItem > 1) do Dec(tMenu[cMenu].cItem);
              end;
        'Q':  begin {- Page-Down -}
               if tMenu[cMenu].cItem < cSubMenu.nItem then Inc(tMenu[cMenu].cItem);
               While (tMenu[cMenu].SubMenu[tMenu[cMenu].cItem].NameSt <> '-') and
                     (tMenu[cMenu].cItem < cSubMenu.nItem) do Inc(tMenu[cMenu].cItem);
               if tMenu[cMenu].SubMenu[tMenu[cMenu].cItem].NameSt = '-' then
                  Inc(tMenu[cMenu].cItem);
              end;
       end;
     end;
      IDE_Desktop^.Paint;
    if ((cKey.Ch = #27) and (not cKey.Ext)) or
       ((cKey.Ch = #1) and (cKey.Ext)) then Goto EndSelectMenu;
   end;

if (IDE_MouseL) and (IDE_MouseY = 0) then Goto SelectMenu;
if (IDE_MouseL) and (IDE_MouseY > 0) then
begin
 Repeat
  nCMD := 0;
  tMenu[cMenu].cItem := 0;
  if (IDE_MouseX >= cSubMenu.sX) and (IDE_MouseX <= cSubMenu.eX+2) and
     (IDE_MouseY >= 2) and (IDE_MouseY <= 2+cSubMenu.nItem) then
     begin
      tMenu[cMenu].cItem := IDE_MouseY-1;
      nCMD := tMenu[cMenu].SubMenu[tMenu[cMenu].cItem].ID;
      IDE_Desktop^.QuickPaint;
     end;

  if (IDE_MouseY = 0) then Goto SelectMenu;
  repeat until (IDE_MouseMoved);
 until not IDE_MouseL;
 if (IDE_MouseY = 0) then Goto SelectMenu;
 Goto EndSelectMenu
end;

nCMD := 0;
if tMenu[cMenu].cItem = 0 then
begin
 tMenu[cMenu].cItem := 1;
 IDE_Desktop^.Paint;
end;

 goto SelectSubMenu;
EndSelectMenu:

  Menu_cItem := 0;
  IDE_Desktop^.Paint;
  if nCMD > 0 then cmSend(nCMD);


end;

















Type
 pAboutDialogType = ^AboutDialogType;
 AboutDialogType = Object(IDE_DialogWindowType)

   pOKButton: pIDE_ButtonType;

  Constructor Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
  Procedure Paint; virtual;
 end;

Constructor AboutDialogType.Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
begin
 New(pOKButton, init(14, 15, 8, 1, '~O~k'));
 Inherited Init((IDE_Screen.ScrWidth div 2)-19, (IDE_Screen.ScrHeight div 2)-9, 38, 18, nTitle);
 tItem.Insert(pOKButton);
 IDE_Desktop^.QuickPaint;
end;

Procedure AboutDialogType.Paint;
begin
 Inherited Paint;

 IDE_WriteXYC(Xo+2, Yo+ 2, '     P32 IDE version '+P32IDE_Ver, $70);
 IDE_WriteXYC(Xo+2, Yo+ 4, '      by Michael Goddard', $70);
 IDE_WriteXYC(Xo+2, Yo+ 5, '    (magnesium@hehe.com/', $70);
 IDE_WriteXYC(Xo+2, Yo+ 6, '   cgoddard@ozemail.com.au)', $70);

 IDE_WriteXYC(Xo+2, Yo+ 8, '      P32 version '+P32_Version, $70);
 IDE_WriteXYC(Xo+1, Yo+10, ' by Johan Prins (jprins@knoware.nl)', $70);
 IDE_WriteXYC(Xo+1, Yo+11, '    http://www.cryogen.com/p32/', $70);

 {**johan}
 IDE_WriteXYC(Xo+1, Yo+13, ' Compiled on: ' + compiledate,  $70);

 if pOKButton^.IsPressed then begin;done;exit;end;

end;

Type
 pContribDialogType = ^ContribDialogType;
 ContribDialogType = Object(IDE_DialogWindowType)

   pOKButton: pIDE_ButtonType;

  Constructor Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
  Procedure Paint; virtual;
 end;

Constructor ContribDialogType.Init(nXo,nYo: Integer; nXs,nYs: Word; nTitle: String);
begin
 New(pOKButton, init(30, 12, 8, 1, '~O~k'));
 Inherited init($FF, $FF, 76, 16, nTitle);
 tItem.Insert(pOKButton);
 IDE_Desktop^.QuickPaint;
end;

Procedure ContribDialogType.Paint;
begin
 Inherited Paint;

 IDE_WriteXYC(Xo+2, Yo+ 2, 'Compiler by Johan Prins (jprins@knoware.nl)', $70);
 IDE_WriteXYC(Xo+3, Yo+ 3, '- Jose A.Vericat, frodobolson@hotmail.com: Some floating point routines', $70);
 IDE_WriteXYC(Xo+3, Yo+ 4, '- Daniel D. Bennett, ddbennet@mtu.edu: Unit saving routines', $70);
 IDE_WriteXYC(Xo+3, Yo+ 5, '- David Boshell: floating point runtime routines', $70);
 IDE_WriteXYC(Xo+3, Yo+ 6, '- Laurie Boshell: break, continue, exit statements', $70);
 IDE_WriteXYC(Xo+3, Yo+ 7, '- Michael Goddard: RLE Compressed Units', $70);
 IDE_WriteXYC(Xo+2, Yo+ 9, 'IDE by Michael Goddard (magnesium@hehe.com)', $70);
 IDE_WriteXYC(Xo+3, Yo+10, '- Johan, some lil bits', $70);
 IDE_WriteXYC(Xo+3, Yo+11, '- Anyone wana help?', $70);

 if pOKButton^.IsPressed then begin;done;exit;end;

end;


{* Converts a number to a Comma separated string, looks nicer than Str *}
Function PadComma(l: Longint): String;
Var St: String;i: word;
Begin
 {- Convert number 'l' to String 'St' -}
 Str(l, St);
 {- If it's over 3 characters long it needs a comma -}
 if Length(St) > 3 then
 for i:=1 to length(St)-1 do
 {- Search for every third place and insert a comma -}
  if (i+1) mod 4 = 3 then Insert(',',St,length(St)-i);
 {- Return the new string -}
 PadComma := St;
End;


Type
 pErrMsgWindowType = ^ErrMsgWindowType;
 ErrMsgWindowType = Object(IDE_DialogWindowType)

  Constructor Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
  Procedure Paint; virtual;
 end;

Var ErrMsg_St: String;

Constructor ErrMsgWindowType.Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
begin
 Inherited Init(nXo, nYo, Length(ErrMsg_St)+4, 5, nTitle);
  cWinFrame := (cWinFrame and $F) + (IDE.c.Error and $F0);
  cWinIcon  := (cWinIcon  and $F) + (IDE.c.Error and $F0);
  cWinSize  := (cWinSize  and $F) + (IDE.c.Error and $F0);
  cWinSlide := (cWinSlide and $F) + (IDE.c.Error and $F0);
  cWinBack  := (cWinBack  and $F) + (IDE.c.Error and $F0);
  cText     := IDE.c.Error;
 IDE_Desktop^.QuickPaint;
end;

Procedure ErrMsgWindowType.Paint;
begin
 Modal := True;

 Inherited Paint;

 IDE_WriteXYC(Xo+2, Yo+2, ErrMsg_St, cText);
end;




Procedure ErrorMSG(St: String);
Var pERRMSGWin: pErrMsgWindowType;
begin
 ErrMsg_St := St;
 New(pERRMSGWin, init($FF, $FF, 0, 0, 'Error Message'));
end;






Type
 pInfoWindowType = ^InfoWindowType;
 InfoWindowType = Object(IDE_DialogWindowType)

  pOKButton: pIDE_ButtonType;

  Constructor Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
  Procedure Paint; virtual;
 end;


Constructor InfoWindowType.Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
begin
 New(pOKButton, init(20, 7, 8, 1, '~O~k'));
 Inherited Init(nXo, nYo, 50, 10, nTitle);
 tItem.Insert(pOKButton);
 IDE_Desktop^.QuickPaint;
end;

Procedure InfoWindowType.Paint;
var w: word;
begin
 Modal := True;

 Inherited Paint;

 IDE_WriteXYC(Xo+3, Yo+2, 'Free Heap (REAL): '+PadComma(MemAvail{ div 1024}){+'k'}, cText);
 if Sym.LastProgST = '' then
  IDE_WriteXYC(Xo+3, Yo+3, 'Last Program    : none', cText)
 else
 begin
  IDE_WriteXYC(Xo+3, Yo+3, 'Last Program    : '+Sym.LastProgST, cText);
  IDE_WriteXYC(Xo+3, Yo+4, '       Lines    : '+PadComma(Sym.cLine)+'/'+PadComma(Sym.tLine), cText);

 end;

 Asm;Mov Ax, Sp; Mov w, Ax;end;

 IDE_WriteXYC(Xo+3, Yo+5, 'Stack Free (SP) : '+PadComma(w), cText);

 if pOKButton^.IsPressed then begin;done;exit;end;

end;





Type
 pFileWindowType = ^FileWindowType;
 FileWindowType = Object(IDE_DialogWindowType)

  FileSt: String;
  pOKButton, pCANCELButton, pCONSTButton: pIDE_ButtonType;
  InsConst: Boolean;

  Constructor Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
  Procedure Paint; virtual;

  Procedure MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
  Procedure KeyEvent(Key: KeyType); virtual;
  Procedure CloseWin; virtual;
 end;


Constructor FileWindowType.Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
Var pItemText: pIDE_ItemTextType;
    pFileText: pIDE_FileTextType;
begin
 FileSt := '';
 InsConst := False;

 New(pOKButton, init(40, 5, 8, 1, '~O~k'));
 New(pCANCELButton, init(40, 8, 8, 1, '~C~ancel'));
 New(pCONSTButton, init(40, 11, 8, 1, '~C~onst'));
 New(pFileText, init(3, 3, 32, 9, @FileSt, '*.PAS'));

 Inherited Init(nXo, nYo, 54, 18, nTitle);

 tItem.Insert(pOKButton);
 tItem.Insert(pCANCELButton);
 if Pos('Save', nTitle)=0 then tItem.Insert(pCONSTButton);
 tItem.Insert(pFileText);

 IDE_Desktop^.QuickPaint;
end;

Procedure FileWindowType.Paint;
var e: boolean; pEditWindow: pIDE_SourceWindowType;
 Procedure CheckExit(pI: pIDE_ItemBaseType); far;
 begin
  if pI^.ItemExit then begin;e := True;pI^.ItemExit := False;end;
 end;
begin
 Modal := True;
 Inherited Paint;

 e := False;
 tItem.ForEach(@CheckExit);
 InsConst := False;
 if pOKButton^.IsPressed then
  begin;pOKButton^.IsDown := False;pOKButton^.IsPressed:=False;
        pOKButton^.Paint;e:=True;end;
 if pCANCELButton^.IsPressed then
  begin;pCANCELButton^.IsDown := False;pCANCELButton^.IsPressed:=False;
        pCANCELButton^.Paint;FileSt := '';e:=True;end;
 if (Pos('Save', Title)=0) and (pCONSTButton^.IsPressed) then
  begin;pCONSTButton^.IsDown := False;pCONSTButton^.IsPressed:=False;
        pCONSTButton^.Paint;e:=True;InsConst := True;end;
 if e then begin;CloseWin;done;exit;end;
end;

Procedure FileWindowType.MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
begin
 Inherited MouseEvent(mLeft, mMiddle, mRight, mX, mY);
end;

Procedure FileWindowType.KeyEvent(Key: KeyType);
var pEditWindow: pIDE_SourceWindowType;
begin

 Inherited KeyEvent(Key);

 IDE_Desktop^.QuickPaint;
end;

Procedure FileWindowType.CloseWin;
var e: boolean; pEditWindow: pIDE_SourceWindowType;
 Procedure CheckExit(pI: pIDE_ItemBaseType); far;
 begin
  if pI^.ItemExit then e := True;
 end;
begin
{ e := False;
 tItem.ForEach(@CheckExit);
 if (e) then}
 FileSt := UCase(FileSt);

 if FileSt <> '' then
 begin
  if Pos('Save', Title)>0 then
  begin
    if IDE_Desktop^.tWin.Count>=2 then
    begin
     pEditWindow := IDE_Desktop^.tWin.At(IDE_Desktop^.tWin.Count-2);
     if pEditWindow^.ID = _Source then
     begin
      pEditWindow^.SaveFile(FileSt);
      pEditWindow^.Title := FileSt;
      pEditWindow^.FileTitle := FileSt;
     end else ErrorMSG('Window is not a Source Window');
    end else ErrorMSG('No Window to Save');

  end
  else
  if InsConst then
  begin
    pEditWindow := IDE_Desktop^.tWin.At(IDE_Desktop^.tWin.Count-2);
    if pEditWindow^.ID = _Source then
     pEditWindow^.InsertFile(FileSt)
    else
     ErrorMSG('Window is not a Source Window');
  end
  else
  begin
   New(pEditWindow, init(0, 0, 80, 50, FileSt));
   pEditWindow^.LoadFile(FileSt);
  end;
 end else IDE_Desktop^.Paint;

end;



Type
 pCompilingWindowType = ^CompilingWindowType;
 CompilingWindowType = Object(IDE_DialogWindowType)

  cFile, operSt: String;
  cLine, tLine: Longint;

  Constructor Init;
  Destructor Done; virtual;
  Procedure Paint; virtual;
  Procedure KeyEvent(Key: KeyType); virtual;
  Procedure setOperation(St: String);
 end;
var CompilingWindow: CompilingWindowType;

Constructor CompilingWindowType.Init;
begin
 cFile := ''; cLine := 0; tLine := 0;
 Inherited Init($FF, $FF, 45, 12, 'Compiling Source');
end;

Destructor CompilingWindowType.done;
begin
 Inherited done;
end;

Procedure CompilingWindowType.Paint;
var w: word;
begin
 inherited Paint;
 IDE_WriteXYC(Xo+3, Yo+2, 'Operation: ' + operSt, cText);
 IDE_WriteXYC(Xo+3, Yo+3, '     File: ' + cFile, cText);

 IDE_WriteXYC(Xo+3, Yo+4, 'Cur. Line: ' + PadComma(cLine), cText);
 IDE_WriteXYC(Xo+3, Yo+5, 'Tot. Line: ' + PadComma(tLine+cLine), cText);

 Asm;Mov Ax, Sp; Mov w, Ax;end;

 IDE_WriteXYC(Xo+3, Yo+6, 'Stack(SP): '+PadComma(w), cText);
 IDE_WriteXYC(Xo+3, Yo+7, 'Heap(MEM): '+PadComma(MemAvail), cText);


 if operSt = 'done' then
   IDE_WriteXYC(Xo+1, Yo+Ys-2, '         Press Any Key to Continue         ', $1F);

end;

Procedure CompilingWindowType.KeyEvent(Key: KeyType);
begin
 {- This should _stop_ compilation if <ESC> pressed or something like that I guess -}
end;

Procedure CompilingWindowType.setOperation(St: String);
begin
 operSt := St;
 IDE_Desktop^.QuickPaint;
end;


Type
 pASCIIWindowType = ^ASCIIWindowType;
 ASCIIWindowType = Object(IDE_DialogWindowType)

  pOKButton, pINSNButton, pINSCButton, pINSHButton, pINSBButton: pIDE_ButtonType;
  cChar: Byte;

  Constructor Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
  Procedure Paint; virtual;
  Procedure MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
  Procedure KeyEvent(Key: KeyType); virtual;
 end;


Constructor ASCIIWindowType.Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
begin
 New(pOKButton, init(36, 2, 8, 1, '~C~lose'));
 New(pINSNButton, init(36, 5, 8, 1, '~N~umber'));
 New(pINSCButton, init(36, 8, 8, 1, '~C~har'));
 New(pINSHButton, init(48, 2, 8, 1, '~H~ex'));
 New(pINSBButton, init(48, 5, 8, 1, '~B~in'));
 cChar := 0;
 Inherited Init(nXo, nYo, 62, 11, nTitle);

 tItem.Insert(pOKButton);
 tItem.Insert(pINSNButton);
 tItem.Insert(pINSCButton);
 tItem.Insert(pINSHButton);
 tItem.Insert(pINSBButton);

 IDE_Desktop^.QuickPaint;
end;

Procedure ASCIIWindowType.Paint;
var x, y: word; pS: pIDE_WindowType;mKey: KeyType;
begin
 Modal := True;

 Inherited Paint;

 for y := 0 to 7 do
  for x := 0 to 31 do
   IDE_WriteXYC_Ch(x+1+Xo, y+1+Yo, Chr(x+y*32), $0A);

 for x := 0 to 31 do IDE_WriteXYC_Ch(x+1+Xo, 9+Yo, ' ', $0A);

 IDE_WriteXYC(3+Xo, Yo+9, 'Char: ', $0A);
 IDE_WriteXYC_Ch(9+Xo, Yo+9, chr(cChar), $0A);

 IDE_WriteXYC(16+Xo, Yo+9, 'ASCII: '+PadComma(cChar), $0A);

 if pOKButton^.IsPressed then begin;done;exit;end;
 if (pINSCButton^.IsPressed) or (pINSNButton^.IsPressed) or
    (pINSHButton^.IsPressed) or (pINSBButton^.IsPressed) then
   begin
{    if IDE_Desktop^.tWin.Count <= 2 then begin;ErrorMSG('No Window to insert to');done;exit;end;}
    pS := IDE_Desktop^.tWin.At(IDE_Desktop^.tWin.Count-2);
    if pS^.ID = _Source then
    begin
     mKey.Ext   := False;
     mKey.Alt   := False;
     mKey.Ctrl  := False;
     mKey.Shift := False;
     if pINSCButton^.IsPressed then
     begin
      mKey.Ch    := chr(cChar);
      pINSCButton^.IsPressed := False;
      pS^.KeyEvent(mKey);
     end
     else if (pINSNButton^.IsPressed) then
     begin
      pINSNButton^.IsPressed := False;
      mKey.Ch    := chr(48+((cChar div 100)));
      if cChar >= 100 then pS^.KeyEvent(mKey);
      mKey.Ch    := chr(48+((cChar div 10) mod 10));
      if cChar >= 10 then pS^.KeyEvent(mKey);
      mKey.Ch    := chr(48+(cChar mod 10));
      pS^.KeyEvent(mKey);
     end
     else if (pINSHButton^.IsPressed) then
     begin
      pINSHButton^.IsPressed := False;
      mKey.Ch    := '$';
      pS^.KeyEvent(mKey);
      mKey.Ch    := HexStr[1+((cChar div 16) and $F)];
      pS^.KeyEvent(mKey);
      mKey.Ch    := HexStr[1+(cChar and $F)];
      pS^.KeyEvent(mKey);
     end
     else if (pINSBButton^.IsPressed) then
     begin
      pINSBButton^.IsPressed := False;
      for x:=0 to 7 do
      begin
       mKey.Ch := Chr(48+ ((cChar Shr (7-x)) and 1));
       pS^.KeyEvent(mKey);
      end;
      mKey.Ch    := 'b';
      pS^.KeyEvent(mKey);
     end;
     done;exit;
    end
    else
     done;
     ErrorMSG('Window is not a Source Window');
     exit;
   end;
end;

Procedure ASCIIWindowType.MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
begin
 Inherited MouseEvent(mLeft, mMiddle, mRight, mX, mY);
 if mLeft then
 if (mX > 0) and (mY > 0) and (mX <= 32) and (mY <= 8) then
    begin
      While IDE_MouseL do
      begin
       if ((IDE_MouseX-Xo) > 0)   and ((IDE_MouseY-Yo) > 0) and
          ((IDE_MouseX-Xo) <= 32) and ((IDE_MouseY-Yo) <= 8) then
       begin
        cChar := ((IDE_MouseX-Xo)-1) + ((IDE_MouseY-Yo)-1) * 32;
        IDE_Desktop^.QuickPaint;
       end;
       While not IDE_MouseMoved do;
      end;
    end;
end;

Procedure ASCIIWindowType.KeyEvent(Key: KeyType);
begin
 Inherited KeyEvent(Key);
end;







Type
 pCALCWindowType = ^CALCWindowType;
 CALCWindowType = Object(IDE_DialogWindowType)

  pOKButton: pIDE_ButtonType;

  Constructor Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
  Procedure Paint; virtual;
  Procedure MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer); virtual;
  Procedure KeyEvent(Key: KeyType); virtual;
 end;


Constructor CALCWindowType.Init(nXo, nYo: Integer; nXs, nYs: Word; nTitle: String);
begin
 New(pOKButton, init(8, 4, 8, 1, '~C~lose'));

 Inherited Init(nXo, nYo, 30, 7, nTitle);

 tItem.Insert(pOKButton);

 IDE_Desktop^.QuickPaint;
end;

Procedure CALCWindowType.Paint;
var x, y: word; pS: pIDE_WindowType;mKey: KeyType;
begin
 Modal := True;

 Inherited Paint;

 IDE_WriteXYC_NB(Xo+3, Yo+2, 'Calculator not finished', 5);

 if pOKButton^.IsPressed then begin;done;exit;end;

end;

Procedure CALCWindowType.MouseEvent(mLeft, mMiddle, mRight: Boolean; mX, mY: Integer);
begin
 Inherited MouseEvent(mLeft, mMiddle, mRight, mX, mY);
end;

Procedure CALCWindowType.KeyEvent(Key: KeyType);
begin
 Inherited KeyEvent(Key);
end;






















var cm_Send_Wait: Boolean;

 Procedure cmSend(cm: word);
  var pEditWindow: pIDE_SourceWindowType;St: String;
      pUserWindow: pIDE_UserWindowType;i, w: word;
      pAboutDiag: pAboutDialogType;
      pContribDiag: pContribDialogType;
      pFileWindow: pFileWindowType;
      pInfoWindow: pInfoWindowType;
      pASCIIWin: pASCIIWindowType;
      pCALCWin: pCALCWindowType;
 begin
  Case cm of
         cm_Exit: IDE.Quit := True;
   cm_UserScreen:begin
                  IDE_SwapVideoOut;
                  repeat until keypressed or IDE_MouseL;
                  while keypressed do readkey;
                  if IDE_MouseL then repeat until not IDE_MouseL;
                  IDE_SwapVideoIn;
                  IDE_Desktop^.Paint;
                 end;
   cm_UserWindow: New(pUserWindow, init(0, 0, 80, 25, 'User Output'));
   cm_AboutWindow: New(pAboutDiag, init((IDE_Screen.ScrWidth div 2)-19, (IDE_Screen.ScrHeight div 2)-9, 38, 16, 'About'));
   cm_ContribWindow: New(pContribDiag, init($FF, $FF, 76, 13, 'P32 Contributors'));
   cm_ASCIIWin: New(pASCIIWin, init($FF, $FF, 1, 1, 'ASCII Table'));
    cm_CALCWin: New(pCALCWin, init($FF, $FF, 1, 1, 'Calculator'));
   cm_DOSShell:begin
                  IDE_SwapVideoOut;
  {**johan}
                  {IDE_HeapShrink;}
                  {SwapVectors;}
                  Execute('','');
                  {SwapVectors;
                  IDE_HeapExpand;}

                  while keypressed do readkey;
                  if IDE_MouseL then repeat until not IDE_MouseL;
                  IDE_SwapVideoIn;
                  IDE_Desktop^.Paint;
               end;
   cm_NewEdit: if (MemAvail > 8192+IDE_MaxTextSize) then
               begin
                 St := ''; w := IDE.P32.nNoname;
                 for i:=Length(IDE.P32.NoName) to 7 do begin;St := Chr((w mod 10)+48) + St;w:=w div 10;end;
                 New(pEditWindow, init(0, 0, $FF, $FF, IDE.P32.NoName+St+'.'+IDE.P32.Ext));
                 Inc(IDE.P32.nNoname);
               end else ErrorMSG('Not Enough Heap to Create New Window.');
   cm_SyntaxHighlightToggle: begin
                              IDE.SyntaxHighlight := not IDE.SyntaxHighlight;
                              IDE_Desktop^.Paint;
                             end;
   cm_BlockHighlightToggle: begin
                              IDE.BlockHighlight := not IDE.BlockHighlight;
                              IDE_Desktop^.Paint;
                             end;
   cm_HeightToggle: begin
                     {IDE_Done;}
                     IDE.SmallFont := not IDE.SmallFont;
                     IDE_Reset;
                     {IDE_Init;}
                     IDE_Desktop^.Paint;
                    end;
   cm_Compile: if IDE_Desktop^.tWin.Count>0 then
               begin
                pEditWindow := IDE_Desktop^.tWin.At(IDE_Desktop^.tWin.Count-1);
                if pEditWindow^.ID = _Source then
                begin
                CompilingWindow.Init;
                CompilingWindow.setOperation('Saving Source');
                 if pEditWindow^.Modified then cmSend(cm_SaveEdit);

                CompilingWindow.setOperation('Compiling');
                 Sym.LastProgST := pEditWindow^.FileTitle;
 {$IFDEF P32IDE}
(*                 if Sym.Filled then begin;DestroySymbolList(GlobalTable);Sym.Filled := False;end;
                 Init; {Reads system unit}
                 Compile(pEditWindow^.FileTitle);
                 Sym.Filled := True;*)
{- Use Above method to keep symboltable -}
{$IFDEF MemTrick}
                IDE_SaveHeap;
{$ENDIF}
{- A few things need to be done from the unit's Begin/End -}
  { From P32_CFG.PAS }
  SetCompilerDir;
  CPU := i486;
  { From P32_PREP.PAS }
  CreateStringList(directive_names);
  AddStringName(directive_names,'P32V040');
  {- Just thought I'd add this for no reason -}
  AddStringName(directive_names,'P32IDE');



                 Init; {Reads system unit}
                 Compile(pEditWindow^.FileTitle);
                 DestroySymbolList(GlobalTable);

{$IFDEF MemTrick}
                IDE_RestoreHeap;
{$ENDIF}
                CompilingWindow.setOperation('Assembling');

 {$ENDIF}

                CompilingWindow.setOperation('done');

                 if cm_Send_Wait then
                 begin
                  While IDE_MouseL do;
                  repeat until (keypressed) or (IDE_MouseL);
                  While Keypressed do readkey;
                  While IDE_MouseL do;
                 end;
                CompilingWindow.done;
                end else ErrorMSG('Cannot Compile this Window type');
              end else ErrorMSG('Cannot Compile, there are no open windows');
   cm_LINK: begin
               { if config.assembler = '' then
                   ErrorMSG('Assembler Not Set')
                 else
                   if config.linker = '' then
                     ErrorMSG('Linker Not Set')
                     else}
   {**michael}
             pEditWindow := IDE_Desktop^.tWin.At(IDE_Desktop^.tWin.Count-1);
             if pEditWindow^.ID = _Source then
             begin
   {**johan}
             IDE_SwapVideoOut;
             {IDE_HeapShrink;}
             St:=pEditWindow^.FileTitle;
             Delete(St, Pos('.', St), 4);

             ExecuteBatchFile(St);
{   Exec(GetENV('COMSPEC'), '/C C.BAT');}

             {IDE_HeapExpand;}
             IDE_SwapVideoIn;
             IDE_Desktop^.Paint;
             end else ErrorMSG('Cannot compile this window type');
            end;

   cm_BUILD: begin;cm_Send_Wait:=False;cmSend(cm_Compile);cmSend(cm_LINK);end;
     cm_RUN: begin;cmSend(cm_BUILD);
                  IDE_SwapVideoOut;
                  {IDE_HeapShrink;}
                  St := pEditWindow^.FileTitle;
                  if Pos('.',St)>0 then St[0] := Chr(Pos('.',St)-1);
                   {**johan}
                   {Exec(GetENV('COMSPEC'), St+'.EXE');}
                   Execute(st+'.EXE', '');
                  {IDE_HeapExpand;}
                  IDE_SwapVideoIn;
                  IDE_Desktop^.Paint;
             end;

   cm_InfoBOX: New(pInfoWindow, init($FF, $FF, 50, 8, 'Information'));
   cm_SaveEdit: if IDE_Desktop^.tWin.Count>0 then
                begin
                 pEditWindow := IDE_Desktop^.tWin.At(IDE_Desktop^.tWin.Count-1);
                 if pEditWindow^.ID = _Source then
                 begin
                  pEditWindow^.SaveFile(pEditWindow^.FileTitle);
                 end;
                end;
   cm_SaveAsEdit: if IDE_Desktop^.tWin.Count>0 then
                  begin
                   pEditWindow := IDE_Desktop^.tWin.At(IDE_Desktop^.tWin.Count-1);
                   if pEditWindow^.ID = _Source then
                    New(pFileWindow, init($FF, $FF, 30, 8, 'Save File As'));
                  end;
   cm_LoadEdit: begin
                 New(pEditWindow, init(0, 0, 80, 50, cmSend_St));
                 pEditWindow^.LoadFile(cmSend_St);
                end;
   cm_LoadFile,
   cm_OpenEdit: New(pFileWindow, init($FF, $FF, 30, 8, 'Load File'));

  end;
  cm_Send_Wait := True;
 end;



Procedure ProcessEvents;
begin
  if IDE_MouseMoved then IDE_Desktop^.ProcessMouseEvent;
  if keypressed then IDE_Desktop^.ProcessKeyEvent;
end;


{- For the P32IDE bit -}
Procedure ShowERROR(nLine: Longint;St: String);
var i: word; pW: pIDE_SourceWindowType;
begin
 CompilingWindow.Done;

 pW := IDE_Desktop^.tWin.At(IDE_Desktop^.tWin.Count-1);

  pW^.pTextCY := nLine-1;
  pW^.pTextCX := 0; {- Anyone know how to get the current cursor pos? (P32s) -}
  IDE_Desktop^.QuickPaint;

 for i:=1 to pW^.Xs-2 do
  IDE_WriteXYC_Ch(i+pW^.Xo, pW^.Yo+1, ' ', IDE.c.Error);

 for i:=1 to Length(St) do
  if (i<pW^.Xs) then IDE_WriteXYC_Ch(i+pW^.Xo+1, pW^.Yo+1, St[i], IDE.c.Error);

  IDE_UpdateVideo;

 Repeat until (Keypressed) or (IDE_MouseL);
 While IDE_MouseL do;
 While keypressed do readkey;

 IDE_Desktop^.QuickPaint;
 repeat
  ProcessEvents;
 until IDE.Quit;
 IDE_Done;
 exit;
end;




Procedure CompileStatus_NewFile(St: String);
begin
 CompilingWindow.cFile := St;
 IDE_Desktop^.QuickPaint;
end;

var CompilerStatus_cLineSet_Last: Longint;
Procedure CompileStatus_cLineSet(l: Longint);
var w1, w2, w3, w4: word; l2: longint;
begin
 if l < CompilingWindow.cLine then Inc(CompilingWindow.tLine, CompilingWindow.cLine);
 CompilingWindow.cLine := l;
 Sym.cLine := CompilingWindow.cLine;
 Sym.tLine := CompilingWindow.tLine;

  GetTime(w1, w2, w3, w4);
  l2 := longint(w4) + longint(w3) * 100 + longint(w2) * 6000 + longint(w1) * 360000;
  if l2 > CompilerStatus_cLineSet_Last + 1 then
  begin
   IDE_Desktop^.QuickPaint;
   CompilerStatus_cLineSet_Last := l2;
  end;


end;





var
 pTestWin: pIDE_WindowType;
 pTestTextWin: pIDE_SourceWindowType;
 pTestDiagWin: pIDE_DialogWindowType;
 i: word;

Begin
   {**** johan}
   if MemW[$40:$63]=$3B4 then textsegment:=SegB000
                         else textsegment:=SegB800;

{- Setup variables -}
   IDE.c.Syntax.none       := 14 + 16;
   IDE.c.Syntax.Comment    := 7  + 16;
   IDE.c.Syntax.Reserved   := 15 + 16;
   IDE.c.Syntax.Reserved2  := 11 + 16;
   IDE.c.Syntax.Identifiers:= 14 + 16;
   IDE.c.Syntax.Symbols    := 9  + 16;
   IDE.c.Syntax.Strings    := 12 + 16;
   IDE.c.Syntax.Numbers    := 13 + 16;
   IDE.c.Syntax.AsmSrc     := 10 + 16;
   IDE.c.Error             := $4F;
   IDE.c.BlockHi           := 6;
   IDE.c.BlockSel          := 1;
   IDE.c.Button            := $20;
   IDE.c.ButtonH           := $2C;
{   IDE.TabSize             := 8;}
   IDE.TabSize             := 0;  {- 0 means AutoTab -}
   IDE.SmartTab            := True;
   IDE.SyntaxHighlight     := True;
   IDE.BlockHighlight      := True;
   IDE.QuickHighlight      := False;
   IDE.DoubleClick         := 100; {- 100ms Double Click -}
   IDE.SmallFont           := False;
   IDE.NestComment         := True;

   IDE.P32.nNoname := 0;
   IDE.P32.Noname  := 'NONAME';
   IDE.P32.Ext     := 'PAS';

   Sym.Filled := False;


 {$IFDEF P32IDE}
  NestedComments := IDE.NestComment;
  ReadConfig;
  ReadDefinition(FSearch(config.asmdef,config.asmdef+';.;'+GetEnv('P32')+';'+GetEnv('PATH')));
  IDE.NestComment := NestedComments;
 {$ENDIF}

 {$IFNDEF P32IDE}

 Writeln('P32 IDE  Version '+P32IDE_Ver+' by Michael Goddard (magnesium@hehe.com)');
 Writeln('P32      Version '+P32_Version+' by Johan Prins (jprins@knoware.nl)');

 IDE_Init;

 IDE.Quit := False;
 repeat

  if IDE_MouseMoved then IDE_Desktop^.ProcessMouseEvent;
  if keypressed then IDE_Desktop^.ProcessKeyEvent;

 until {$IFDEF Debug}IDE_MouseR or{$ENDIF} IDE.Quit;
 if keypressed then repeat readkey until not keypressed;
 if MMouse_ButtonRight then repeat until not MMouse_ButtonRight;
{ Dispose(IDE_Desktop, Done);}
 IDE_Done;
 {$ENDIF}
End.