home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / 552 / GSOB_EDT.PAS < prev    next >
Pascal/Delphi Source File  |  1993-10-07  |  14KB  |  542 lines

  1. {-----------------------------------------------------------------------------
  2.                                  Editor Routines
  3.  
  4.        GSOB_Edt Copyright (c)  Richard F. Griffin
  5.  
  6.        08 May 1993
  7.  
  8.        102 Molded Stone Pl
  9.        Warner Robins, GA  31088
  10.  
  11.        -------------------------------------------------------------
  12.        This unit handles the objects for a simple editor.
  13.  
  14.                  --- DOES NOT COMPILE UNDER WINDOWS ---
  15.  
  16.        Changes:
  17.  
  18. ------------------------------------------------------------------------------}
  19.  
  20. Unit GSOB_Edt;
  21.  
  22. interface
  23.  
  24. uses
  25.    GSOB_Obj,
  26.    GSOB_Str,
  27.    CRT,
  28.    DOS;
  29.  
  30. type
  31.  
  32.    TEvent = record
  33.       What: Integer;
  34.       case Integer of
  35.             0: (KeyCode: Word);
  36.             1: (CharCode: Char;
  37.                 ScanCode: Byte);
  38.    end;
  39.  
  40.    TPoint = Record
  41.       X : Integer;
  42.       Y : Integer;
  43.    end;
  44.  
  45.  
  46.    GSP_ShowView = ^GSO_ShowView;
  47.    GSO_ShowView = object(TObject)
  48.       edLineColl  : GSP_LineCollection;
  49.       LineRet     : byte;
  50.       Work_Line   : string;
  51.       LineOnly    : boolean;
  52.       Cursor,
  53.       Delta,
  54.       Size,
  55.       Limit,
  56.       PhyPos      : TPoint;
  57.       constructor Init(P : GSP_LineCollection);
  58.       procedure   Draw; virtual;
  59.       procedure   FindLine(linenum : integer);
  60.       procedure   FixView;
  61.       procedure   HandleEvent(var Event : TEvent); virtual;
  62.       function    WorkView : boolean;
  63.    end;
  64.  
  65.    GSP_EditView = ^GSO_EditView;
  66.    GSO_EditView = object(GSO_ShowView)
  67.       Edit_Lgth   : integer;          {Max size of each line}
  68.       InsertOn    : boolean;
  69.       Modified    : boolean;
  70.       constructor Init(P : GSP_LineCollection; L : Integer);
  71.       Procedure   Draw; virtual;
  72.       Procedure   EditLine(Ch_Work : char);
  73.       procedure   GetNewLine;
  74.       procedure   HandleEvent(var Event : TEvent); virtual;
  75.       Procedure   Pressed_Bsp;
  76.       Procedure   Pressed_CrtlY;
  77.       Procedure   Pressed_Del;
  78.       Procedure   Pressed_Ret;
  79.       procedure   PutLine;
  80.       procedure   ReleaseLine;
  81.       Procedure   WordWrap;
  82.    end;
  83.  
  84. implementation
  85.  
  86. const
  87.  
  88.    InsStatOn  = '[Ins]';
  89.    InsStatOff = '[OvL]';
  90.    EmptyLine  : String[1] = '';
  91.    TabSpaces  = 8;
  92.  
  93.  
  94. { Extended key codes }
  95.  
  96.    kbEsc       = $011B;
  97.    kbBack      = $0E08;
  98.    kbShiftTab  = $0F00;
  99.    kbTab       = $0F09;
  100.    kbEnter     = $1C0D;
  101.    kbF1        = $3B00;
  102.    kbF10       = $4400;
  103.    kbHome      = $4700;
  104.    kbUp        = $4800;
  105.    kbPgUp      = $4900;
  106.    kbLeft      = $4B00;
  107.    kbRight     = $4D00;
  108.    kbEnd       = $4F00;
  109.    kbDown      = $5000;
  110.    kbPgDn      = $5100;
  111.    kbIns       = $5200;
  112.    kbDel       = $5300;
  113.    kbCtrlEnd   = $7500;
  114.    kbCtrlPgDn  = $7600;
  115.    kbCtrlHome  = $7700;
  116.    kbCtrlPgUp  = $8400;
  117.  
  118. var
  119.    Tmp_Line : string;
  120.    Ch_Work  : char;
  121.  
  122.    GS_KeyE_Scn   : byte;
  123.    GS_KeyE_Esc,
  124.    GS_KeyE_Fuc   : boolean;
  125.    GS_KeyE_Chr,
  126.    GS_KeyE_Cde   : char;
  127.  
  128.  
  129. { GS_KeyE_GetKey reads and returns a character from the keyboard.  If the
  130.   character is a function key, GS_KeyE_Func is set true.  The character is
  131.   also saved in unit local variable GS_KeyE_Chr.  The scan code is saved in
  132.   unit local variable GS_KeyE_ScanCode. }
  133.  
  134. function GS_KeyE_GetKey : char;
  135. var
  136.    reg : Registers;
  137. begin
  138.   reg.AX := 0;
  139.   Intr($16,reg);
  140.   GS_KeyE_Cde := char(reg.AL);
  141.   GS_KeyE_Scn := reg.AH;
  142.   if GS_KeyE_Cde = #0 then
  143.     begin
  144.       GS_KeyE_Fuc := true;
  145.       GS_KeyE_Chr := char(GS_KeyE_Scn);
  146.     end
  147.   else
  148.   begin
  149.     GS_KeyE_Fuc := false;
  150.     GS_KeyE_Chr := GS_KeyE_Cde;
  151.   end;
  152.   GS_KeyE_GetKey := GS_KeyE_Chr;
  153. end; {GS_KeyE_GetKey}
  154.  
  155.  
  156.  
  157. {------------------------------------------------------------------------------
  158.                                 GSO_ShowView
  159. ------------------------------------------------------------------------------}
  160.  
  161. constructor GSO_ShowView.Init(P : GSP_LineCollection);
  162. var
  163.    i : integer;
  164. begin
  165.    Cursor.X := 0;
  166.    Cursor.Y := 0;
  167.    Size.X := Lo(WindMax)-Lo(WindMin)+1;
  168.    Size.Y := Hi(WindMax)-Hi(WindMin)-1;
  169.    Delta.X := 0;
  170.    Delta.Y := 0;
  171.    Limit.X := Size.X;
  172.    Limit.Y := P^.Count;
  173.    PhyPos.X := 0;
  174.    PhyPos.Y := 0;
  175.    Work_Line := '';
  176.    edLineColl := P;
  177.    LineOnly := false;
  178.    GoToXY(1,Size.Y+1);
  179.    for i := 1 to Size.X do write(#205);
  180.    GoToXY(1,Size.Y+2);
  181.    write(' F10 to Quit    ESC to Abort');
  182.    if edLineColl^.Count = 0 then exit;
  183.    FindLine(0);
  184.    Draw;
  185. end;
  186.  
  187. procedure GSO_ShowView.Draw;
  188. var
  189.    Y     : Integer;
  190.    i     : integer;
  191.    s     : String;
  192.    z     : boolean;
  193. begin
  194.    FixView;
  195.    for Y := 0 to Size.Y-1 do
  196.    begin
  197.       z := false;
  198.       i := (Y+Delta.Y);
  199.       if i > Limit.Y then z := true;
  200.       if (LineOnly) then
  201.           if Y = Cursor.Y then
  202.              s := Work_Line else z := true
  203.       else
  204.       if (i < edLineColl^.Count) then
  205.             s := GSP_LineBuf(edLineColl^.Items^[i])^.LineText
  206.          else
  207.             s := EmptyLine;
  208.       if not z then
  209.       begin
  210.          FillChar(Tmp_Line[1],Size.X,' ');
  211.          Tmp_Line := s;
  212.          Tmp_Line[0] := char(Size.X);
  213.          GoToXY(1,Y+1);
  214.          Write(Tmp_Line);
  215.       end
  216.       else if (i > Limit.Y) and not LineOnly then
  217.       begin
  218.          GoToXY(1,Y+1);
  219.          ClrEol;
  220.       end;
  221.    end;
  222.    LineOnly := false;
  223.    gotoxy(65,Size.Y+2);
  224.    write('Line: ',PhyPos.Y+1,'':4);
  225.    GoToXY(1,Cursor.Y+1);
  226. end;
  227.  
  228. procedure GSO_ShowView.FindLine(linenum : integer);
  229. var
  230.    p : GSP_LineBuf;
  231. begin
  232.    if linenum < 0 then linenum := 0;
  233.    if linenum >= edLineColl^.Count then linenum := edLineColl^.Count-1;
  234.    p := edLineColl^.At(linenum);
  235.    Work_Line := p^.LineText;
  236.    LineRet := p^.LineRetn;
  237.    PhyPos.Y := linenum;
  238. end;
  239.  
  240. procedure GSO_ShowView.FixView;
  241. var
  242.    D : TPoint;
  243. begin
  244.    D := Delta;
  245.    if Cursor.Y > Size.Y-1 then
  246.    begin
  247.       Delta.Y := Delta.Y + (Cursor.Y-(Size.Y-1));
  248.       Cursor.Y := Size.Y-1;
  249.    end
  250.    else
  251.    begin
  252.       if Cursor.Y < 0 then
  253.       begin
  254.          Delta.Y := Delta.Y+Cursor.Y;
  255.          Cursor.Y := 0;
  256.       end;
  257.    end;
  258.    if Delta.Y >= Limit.Y then Delta.Y := Limit.Y-1;
  259.    if Delta.Y < 0 then Delta.Y := 0;
  260.    if Cursor.X >= Size.X then Cursor.X := Size.X-1
  261.    else
  262.       if Cursor.X < 0 then Cursor.X := 0;
  263.    FindLine(Delta.Y+Cursor.Y);
  264.    Cursor.Y := (PhyPos.Y - Delta.Y);
  265.    if Cursor.Y < 0 then Cursor.Y := 0;
  266.    if Cursor.Y >= (Limit.Y) then Cursor.Y := Limit.Y-1;
  267.    PhyPos.X := Cursor.X;
  268.    LineOnly := LineOnly and (D.Y = Delta.Y);
  269. end;
  270.  
  271. procedure GSO_ShowView.HandleEvent(var Event : TEvent);
  272. var
  273.    cw    : char;
  274.    D,
  275.    Mouse : TPoint;
  276. begin
  277.    D := Delta;
  278.    case Event.KeyCode of
  279.       kbCtrlPgUp : Delta.Y := 0;
  280.       kbCtrlPgDn : Delta.Y := Limit.Y;
  281.       kbCtrlHome : Cursor.Y := 0;
  282.       kbCtrlEnd  : Cursor.Y := Size.Y-1;
  283.       kbPgUp     : Delta.Y := Delta.Y-(Size.Y)-1;
  284.       kbPgDn     : Delta.Y := Delta.Y+(Size.Y)-1;
  285.       kbHome     : Cursor.X := 0;
  286.       kbEnd      : Cursor.X := Length(Work_Line);
  287.       kbLeft     : if Cursor.X > 0 then Dec(Cursor.X);
  288.       kbRight    : if Cursor.X < Length(Work_Line) then Inc(Cursor.X);
  289.       kbUp       : dec(Cursor.Y);
  290.       kbDown     : inc(Cursor.Y);
  291.       kbEsc,
  292.       kbF10      : begin end;
  293.       else exit;
  294.    end;
  295.    LineOnly := D.Y = Delta.Y;
  296.    if edLineColl^.Count > 0 then Draw;
  297.    Event.KeyCode := 0;
  298. END;
  299.  
  300. Function GSO_ShowView.WorkView : boolean;
  301. var
  302.    Event : TEvent;
  303.    kch   : char;
  304.    kcd   : word;
  305. begin
  306.    repeat
  307.       kch := GS_KeyE_GetKey;  {Get the next keyboard entry}
  308.       Event.CharCode := GS_KeyE_Cde;
  309.       Event.ScanCode := GS_KeyE_Scn;
  310.       kcd := Event.KeyCode;
  311.       HandleEvent(Event);
  312.    until (kcd = kbF10) or (kcd = kbEsc);
  313.    WorkView := kcd <> kbEsc;
  314. end;
  315.  
  316. {------------------------------------------------------------------------------
  317.                                 GSO_EditView
  318. ------------------------------------------------------------------------------}
  319.  
  320. constructor GSO_EditView.Init(P : GSP_LineCollection; L : Integer);
  321. begin
  322.    GSO_ShowView.Init(P);
  323.    Modified := false;
  324.    Edit_Lgth := L;
  325.    InsertOn := True;               {Start in insert mode}
  326.    if L > Size.X then Edit_Lgth := Size.X;
  327.    if edLineColl^.Count = 0 then GetNewLine;
  328. end;
  329.  
  330. Procedure GSO_EditView.Draw;
  331. begin
  332.    PutLine;
  333.    GSO_ShowView.Draw;
  334.    gotoxy(48,Size.Y+2);
  335.    if InsertOn then write(InsStatOn) else write(InsStatOff);
  336.    gotoxy(55,Size.Y+2);
  337.    write('Col: ',Cursor.X+1:2);
  338.    if Cursor.X > length(Work_Line) then Cursor.X := length(Work_Line);
  339.    GotoXY(Cursor.X+1,Cursor.Y+1);  {Go to current position in the screen}
  340. end;
  341.  
  342. Procedure GSO_EditView.EditLine(Ch_Work : char);
  343. begin
  344.    Modified := true;
  345.    if InsertOn then System.Insert(Ch_Work, Work_Line, PhyPos.X+1)
  346.       else Work_Line[PhyPos.X+1] := Ch_Work;
  347.    Inc(PhyPos.X);                {Step to the next location in the string}
  348.    if length(Work_Line) >= Edit_Lgth then WordWrap
  349.       else LineOnly := true;
  350. end; { EditLine }
  351.  
  352. procedure GSO_EditView.GetNewLine;
  353. begin
  354.    Work_Line := '';
  355.    LineRet := $0D;
  356.    edLineColl^.InsertItemAt($8D,Work_Line,PhyPos.Y);
  357.    Limit.Y := edLineColl^.Count;
  358. end;
  359.  
  360. procedure GSO_EditView.HandleEvent(var Event : TEvent);
  361. begin
  362.    GSO_ShowView.HandleEvent(Event);
  363.    case Event.KeyCode of
  364.       0         : Exit;
  365.       kbBack    : Pressed_Bsp;
  366.       kbDel     : Pressed_Del;
  367.       kbEnter   : Pressed_Ret;
  368.       kbIns     : InsertOn := not InsertOn;
  369.       else
  370.          case Event.CharCode of
  371.          #25       : Pressed_CrtlY;
  372.          #32..#255  : EditLine(Event.CharCode);
  373.          else exit;
  374.       end;
  375.    end;
  376.    Cursor.Y := PhyPos.Y-Delta.Y;
  377.    Cursor.X := PhyPos.X;
  378.    Draw;
  379. END;
  380.  
  381. procedure GSO_EditView.Pressed_Bsp;
  382. var
  383.    bb : byte;
  384. begin
  385.    Modified := true;
  386.    if PhyPos.X > 0 then
  387.    begin
  388.       System.Delete(Work_Line, PhyPos.X, 1);
  389.       Dec(PhyPos.X);
  390.    end
  391.    else
  392.    begin
  393.       if PhyPos.Y > 0 then
  394.       begin
  395.          bb := LineRet;
  396.          Tmp_Line := Work_Line;
  397.          ReleaseLine;
  398.          if PhyPos.Y < (Limit.Y-1) then FindLine(PhyPos.Y-1);
  399.          PhyPos.X := length(Work_Line);
  400.          Work_Line := Work_Line + Tmp_Line;
  401.          LineRet := bb;
  402.          WordWrap;
  403.          LineOnly := false;
  404.       end;
  405.    end;
  406. end;
  407.  
  408. procedure GSO_EditView.Pressed_Del;
  409. begin
  410.    Modified := true;
  411.    if PhyPos.X < Length(Work_Line)-1 then
  412.       System.Delete(Work_Line, PhyPos.X+1, 1)
  413.    else
  414.    begin
  415.       if PhyPos.Y < edLineColl^.Count-1 then
  416.       begin
  417.          PutLine;
  418.          FindLine(PhyPos.Y+1);
  419.          PhyPos.X := 0;
  420.          Pressed_Bsp;
  421.       end;
  422.    end;
  423. end;
  424.  
  425. procedure GSO_EditView.Pressed_Ret;
  426. begin         {Return}
  427.    Modified := true;
  428.    if InsertOn then
  429.    begin
  430.       Tmp_Line := copy(Work_Line,1,PhyPos.X);
  431.       System.delete(Work_Line,1,PhyPos.X);
  432.       PutLine;
  433.       GetNewLine;
  434.       LineRet := $0D;
  435.       Work_Line := Tmp_Line;
  436.    end;
  437.    PutLine;
  438.    FindLine(PhyPos.Y+1);
  439.    PhyPos.X := 0;
  440. end;
  441.  
  442. procedure GSO_EditView.Pressed_CrtlY;
  443. begin
  444.    Modified := true;
  445.    if edLineColl^.Count = 1 then
  446.       Work_Line := ''
  447.    else
  448.       ReleaseLine;
  449. end;
  450.  
  451. Procedure GSO_EditView.PutLine;
  452. begin
  453.    if edLineColl^.Count = 0 then exit;
  454.    edLineColl^.Free(edLineColl^.At(PhyPos.Y));
  455.    edLineColl^.InsertItemAt(LineRet,Work_Line,PhyPos.Y);
  456. end;
  457.  
  458. Procedure GSO_EditView.ReleaseLine;
  459. begin
  460.    if PhyPos.Y = 0 then exit;
  461.    edLineColl^.Free(edLineColl^.At(PhyPos.Y));
  462.    if PhyPos.Y >= edLineColl^.Count then
  463.       PhyPos.Y := edLineColl^.Count-1;
  464.    FindLine(PhyPos.Y);
  465.    Limit.Y := edLineColl^.Count;
  466. end;
  467.  
  468. Procedure GSO_EditView.WordWrap;
  469. var
  470.    lCnt : integer;                    {Counter for line length in characters}
  471.    linterm : byte;                    {Holds line termination code}
  472.    linchr : boolean;
  473.    wrapped : boolean;
  474.    A_L    : longint;
  475.  
  476.  
  477.    function WrapLine : boolean;
  478.    BEGIN                       { WordWrap }
  479.       if (length(Work_Line) < Edit_Lgth) then
  480.       begin
  481.          WrapLine := false;
  482.          exit;
  483.       end;
  484.       lCnt := Edit_Lgth;
  485.       linchr := false;
  486.       if Work_Line[lcnt] <> ' ' then
  487.       begin
  488.          dec(lcnt);
  489.          while (not linchr) and (lcnt > 0) do
  490.             if Work_Line[lCnt] in [' ','-'] then linchr := true
  491.                else dec(lCnt);
  492.       end;
  493.       if (lCnt = 0) then lcnt := Edit_Lgth;
  494.                                       {If no break point, truncate line}
  495.       Tmp_Line := Work_Line;
  496.       Work_Line[0] := chr(lcnt);
  497.       system.delete(Tmp_Line,1,lCnt);
  498.       if PhyPos.X >= lcnt-1 then
  499.       begin
  500.          PhyPos.X := PhyPos.X-lcnt;
  501.          inc(A_L);
  502.       end;
  503.       WrapLine := true;
  504.    end;
  505.  
  506. BEGIN
  507.    wrapped := false;
  508.    A_L := PhyPos.Y;
  509.    while WrapLine do
  510.    begin
  511.       wrapped := true;
  512.       if LineRet = $0D then
  513.       begin
  514.          LineRet := $8D;
  515.          PutLine;
  516.          inc(PhyPos.Y);
  517.          GetNewLine;
  518.          LineRet := $0D;
  519.       end
  520.       else
  521.       begin
  522.          PutLine;
  523.          inc(PhyPos.Y);
  524.          if edLineColl^.Count > PhyPos.Y then FindLine(PhyPos.Y)
  525.             else GetNewLine;
  526.       end;
  527.       Work_Line := Tmp_Line + Work_Line;
  528.    end;
  529.    if not wrapped then
  530.       LineOnly := true
  531.    else
  532.    begin
  533.       PutLine;
  534.       FindLine(A_L);
  535.    end;
  536. end;                         {WordWrap}
  537.  
  538.  
  539. end.
  540. {------------------------------------------------------------------------------}
  541.  
  542.