home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / tptools.zip / FIRSTED.ZIP / EDEDIT.PAS < prev    next >
Pascal/Delphi Source File  |  1987-12-21  |  30KB  |  1,103 lines

  1. {                          EDEDIT.PAS
  2.                              ED 4.0
  3.              Copyright (c) 1985, 87 by Borland International, Inc.            }
  4.  
  5. {$I eddirect.inc}
  6.  
  7. unit EdEdit;
  8.   {-Basic text editing commands}
  9.  
  10. interface
  11.  
  12. uses
  13.   crt,                       {Basic video operations - standard unit}
  14.   Dos,                       {DOS calls - standard unit}
  15.   Errors,                    {Runtime error handler}
  16.   EdVars,                    {Global types and declarations}
  17.   EdScrn1,                   {Fast screen writing routines}
  18.   EdString,                  {String primitives}
  19.   EdPtrOp,                   {Primitive pointer operations}
  20.   EdCmds,                    {Maps keystrokes to commands}
  21.   int24,                     {DOS critical error handler}
  22.   Message,                   {Message system}
  23.   EdUser,                    {User keyboard input, line editing and error reporting}
  24.   EdMemOp,                   {Text buffer allocation and deallocation}
  25.   EdBack,                    {Background processes}
  26.   EdScrn2;                   {Editor screen updating}
  27.  
  28. procedure EdUpLine;
  29.   {-Process up line command}
  30.  
  31. procedure EdDownLine;
  32.   {-Process down line command}
  33.  
  34. procedure EdLeftLine;
  35.   {-Move cursor to left edge of line}
  36.  
  37. procedure EdRightLine;
  38.   {-Move cursor to right edge of line}
  39.  
  40. procedure EdWindowBottomFile;
  41.   {-Move cursor to bottom of file}
  42.  
  43. procedure EdDeleteRightChar;
  44.   {-Process delete right character command}
  45.  
  46. procedure EdDeleteLeftChar;
  47.   {-Process delete left character command}
  48.  
  49. procedure EdNewLine;
  50.   {-Process <Enter> key}
  51.  
  52. procedure EdInsertLine;
  53.   {-Process insert line command}
  54.  
  55. procedure EdJumpMarker(M : BlockMarker);
  56.   {-Move cursor to marker at line,column}
  57.  
  58. procedure EdLeftChar;
  59.   {-Process left character command}
  60.  
  61. procedure EdRightChar;
  62.   {-Process right character command}
  63.  
  64. procedure EdScrollUp;
  65.   {-Process scroll up command}
  66.  
  67. procedure EdScrollDown;
  68.   {-Process scroll down command}
  69.  
  70. procedure EdUpPage;
  71.   {-Process up page command}
  72.  
  73. procedure EdDownPage;
  74.   {-Process down page command}
  75.  
  76. procedure EdLeftWord;
  77.   {-Move cursor to previous word}
  78.  
  79. procedure EdRightWord;
  80.   {-Advance cursor to next word}
  81.  
  82. procedure EdDeleteRightWord;
  83.   {-Process delete right word command}
  84.  
  85. procedure EdProcesstext(Ch : Char);
  86.   {-Process text input}
  87.  
  88. procedure EdInsertCtrlChar;
  89.   {-Insert literal character as text into file}
  90.  
  91. procedure EdUndo;
  92.   {-Process UNDO command}
  93.  
  94. procedure EdRestoreCurrentLine;
  95.   {-Restore text and flags of current line}
  96.  
  97. procedure EdDeleteLine;
  98.   {-Process delete line command}
  99.  
  100. procedure EdDeleteLineRight;
  101.   {-Kill text to right of cursor}
  102.  
  103. procedure EdFlagExit;
  104.   {-Set flag to exit editor}
  105.  
  106. procedure EdSysInfo;
  107.   {-Display editor information}
  108.  
  109. procedure EdSizeWindow;
  110.   {-Interactively size the current window}
  111.  
  112.   {==========================================================================}
  113.  
  114. implementation
  115.  
  116.   {***}
  117.   procedure EdUpLine;
  118.     {-Process up line command}
  119.  
  120.   begin                      {EdUpLine}
  121.     with CurWin^ do
  122.       if EdPtrNotNil(CurLine^.Backlink) then begin
  123.         Dec(Clineno);
  124.         EdBackPtr(CurLine);
  125.         if LineNo = 1 then begin
  126.           EdBackPtr(TopLine);
  127.           TempScroll := 1;
  128.         end else begin
  129.           TempScroll := 0;
  130.           Dec(LineNo);
  131.         end;
  132.       end else
  133.         TempScroll := 0;
  134.   end;                       {EdUpLine}
  135.  
  136.   {***}
  137.   procedure EdDownLine;
  138.     {-Process down line command}
  139.  
  140.   begin                      {EdDownLine}
  141.     with CurWin^ do
  142.       if EdPtrNotNil(CurLine^.FwdLink) then begin
  143.         Inc(Clineno);
  144.         EdFwdPtr(CurLine);
  145.         if LineNo > (LastLineNo-FirstTextNo) then begin
  146.           EdFwdPtr(TopLine);
  147.           TempScroll := -1;
  148.         end else begin
  149.           TempScroll := 0;
  150.           Inc(LineNo);
  151.         end;
  152.       end else
  153.         TempScroll := 0;
  154.   end;                       {EdDownLine}
  155.  
  156.   procedure EdRightLine;
  157.     {-Move cursor to right edge of line}
  158.  
  159.   begin                      {EdRightLine}
  160.     with CurWin^ do begin
  161.       ColNo := Succ(EdTextLength(CurLine));
  162.       if ColNo > MaxLineLength then
  163.         ColNo := MaxLineLength;
  164.     end;
  165.   end;                       {EdRightLine}
  166.  
  167.   procedure EdDeleteRightChar;
  168.     {-Process delete right character command}
  169.  
  170.   begin                      {EdDeleteRightChar}
  171.     with CurWin^ do begin
  172.  
  173.       if ColNo > CurLine^.Bufflen then
  174.         Exit;
  175.  
  176.       Modified := True;
  177.  
  178.       with CurLine^ do begin
  179.         if ColNo < Bufflen then
  180.           Move(Txt^[Succ(ColNo)], Txt^[ColNo], Bufflen-ColNo);
  181.         Txt^[Bufflen] := Blank;
  182.       end;
  183.  
  184.       {Fix up markers}
  185.       EdFixBlockInsertedSpace(CurLine, ColNo, -1);
  186.       EdCheckNoMarker;
  187.       EdFixMarkInsertedSpace(CurLine, ColNo-1, -1);
  188.     end;
  189.   end;                       {EdDeleteRightChar}
  190.  
  191.   {***}
  192.   procedure EdDeleteLeftChar;
  193.     {-Process delete left character command}
  194.  
  195.   begin                      {EdDeleteLeftChar}
  196.     with CurWin^ do begin
  197.  
  198.       if ColNo = 1 then begin
  199.  
  200.         {Beginning of line}
  201.         if EdPtrNotNil(CurLine^.Backlink) then begin
  202.           Modified := True;
  203.           {Move to end of previous line and join}
  204.           EdUpLine;
  205.           EdRightLine;
  206.           EdJoinline;
  207.           EdRealign;
  208.           {Force screen to be fully updated}
  209.           IntrFlag := NoInterr;
  210.         end;
  211.  
  212.       end else begin
  213.  
  214.         {Middle or end of line}
  215.         Dec(ColNo);
  216.         EdDeleteRightChar;
  217.  
  218.       end;
  219.     end;
  220.   end;                       {EdDeleteLeftChar}
  221.  
  222.   procedure EdNewLine;
  223.     {-Process <Enter> key}
  224.  
  225.   begin                      {EdNewLine}
  226.     with CurWin^ do begin
  227.       if InsertFlag or EdPtrIsNil(CurLine^.FwdLink) then begin
  228.         EdNewLinePrimitive;
  229.         EdRealign;
  230.       end else begin
  231.         EdDownLine;
  232.         ColNo := 1;
  233.       end;
  234.       LeftEdge := 1;
  235.     end;
  236.   end;                       {EdNewLine}
  237.  
  238.   procedure EdInsertLine;
  239.     {-Process insert line command}
  240.   var
  241.     CurL : PlineDesc;
  242.     CurC : Integer;
  243.  
  244.   begin                      {EdInsertLine}
  245.  
  246.     {Save cursor position}
  247.     with CurWin^ do begin
  248.       CurL := CurLine;
  249.       CurC := ColNo;
  250.     end;
  251.  
  252.     {Use Newline to do the work}
  253.     EdNewLinePrimitive;
  254.     if GotError then
  255.       Exit;
  256.  
  257.     {Restore cursor position}
  258.     with CurWin^ do begin
  259.       CurLine := CurL;
  260.       ColNo := CurC;
  261.     end;
  262.  
  263.     EdRealign;
  264.  
  265.   end;                       {EdInsertLine}
  266.  
  267.   {***}
  268.   procedure EdJumpMarker(M : BlockMarker);
  269.     {-Move cursor to marker at line,column}
  270.   var
  271.     W : PwinDesc;
  272.     Mline : PlineDesc;
  273.  
  274.   begin                      {Edjumpmarker}
  275.  
  276.     Mline := M.Line;
  277.     if EdPtrIsNil(Mline) then begin
  278.       EdErrormsg(29);
  279.       Exit;
  280.     end;
  281.  
  282.     {Determine which window holds the marked line}
  283.     W := EdFindWindow(Mline);
  284.     if EdPtrIsNil(W) then begin
  285.       {Mark is not in displayable text}
  286.       EdErrormsg(30);
  287.       Exit;
  288.     end;
  289.  
  290.     CurWin := W;
  291.  
  292.     with CurWin^ do begin
  293.  
  294.       {See if marker is towards top of file, but on current screen}
  295.       while EdPtrNotNil(CurLine^.Backlink) and (CurLine <> TopLine) and (CurLine <> Mline) do
  296.         EdUpLine;
  297.  
  298.       {See if marker is towards end of file}
  299.       while EdPtrNotNil(CurLine^.FwdLink) and (CurLine <> Mline) do
  300.         EdDownLine;
  301.  
  302.       if CurLine <> Mline then begin
  303.         {Marker must be above top of screen}
  304.         TopLine := Mline;
  305.         CurLine := Mline;
  306.         LineNo := 1;
  307.       end;
  308.  
  309.       {Set column number}
  310.       ColNo := M.Col;
  311.  
  312.     end;
  313.   end;                       {Edjumpmarker}
  314.  
  315.   procedure EdLeftChar;
  316.     {-Process left character command}
  317.  
  318.   begin                      {EdLeftChar}
  319.     with CurWin^ do
  320.       if ColNo > 1 then begin
  321.         Dec(ColNo);
  322.         if EditUsercommandInput = 0 then begin
  323.           EdHscrollOne(CurWin);
  324.           EdUpdateCursor;
  325.           EdUpdateStatusLine(CurWin);
  326.         end;
  327.       end;
  328.   end;                       {EdLeftChar}
  329.  
  330.   procedure EdRightChar;
  331.     {-Process right character command}
  332.  
  333.   begin                      {EdRightChar}
  334.     with CurWin^ do
  335.       if ColNo < MaxLineLength then begin
  336.         Inc(ColNo);
  337.         if EditUsercommandInput = 0 then begin
  338.           EdHscrollOne(CurWin);
  339.           EdUpdateCursor;
  340.           EdUpdateStatusLine(CurWin);
  341.         end;
  342.       end;
  343.   end;                       {EdRightChar}
  344.  
  345.   {***}
  346.   procedure EdScrollUp;
  347.     {-Process scroll up command}
  348.  
  349.   begin                      {EdScrollUp}
  350.     with CurWin^ do
  351.       if EdPtrNotNil(TopLine^.Backlink) then begin
  352.         EdBackPtr(TopLine);
  353.         if LineNo > (LastLineNo-FirstTextNo) then begin
  354.           Dec(Clineno);
  355.           EdBackPtr(CurLine);
  356.         end else
  357.           Inc(LineNo);
  358.         Inc(FullScroll);
  359.       end;
  360.   end;                       {EdScrollUp}
  361.  
  362.   {***}
  363.   procedure EdScrollDown;
  364.     {-Process scroll down command}
  365.  
  366.   begin                      {EdScrollDown}
  367.     with CurWin^ do
  368.       if EdPtrNotNil(TopLine^.FwdLink) then begin
  369.         EdFwdPtr(TopLine);
  370.         if LineNo = 1 then begin
  371.           Inc(Clineno);
  372.           EdFwdPtr(CurLine);
  373.         end else
  374.           Dec(LineNo);
  375.         Dec(FullScroll);
  376.       end;
  377.   end;                       {EdScrollDown}
  378.  
  379.   {***}
  380.   procedure EdUpPage;
  381.     {-Process up page command}
  382.   var
  383.     PageSize, I : Integer;
  384.  
  385.   begin                      {EdUpPage}
  386.     with CurWin^ do begin
  387.       PageSize := Succ(LastLineNo-FirstTextNo);
  388.       I := 1;
  389.       while (I < PageSize) and EdPtrNotNil(TopLine^.Backlink) do begin
  390.         {Back the screen up}
  391.         EdBackPtr(TopLine);
  392.         EdBackPtr(CurLine);
  393.         Dec(Clineno);
  394.         Inc(I);
  395.       end;
  396.       while (I < PageSize) do begin
  397.         {Back the cursor up if needed}
  398.         EdUpLine;
  399.         Inc(I);
  400.       end;
  401.     end;
  402.   end;                       {EdUpPage}
  403.  
  404.   {***}
  405.   procedure EdDownPage;
  406.     {-Process down page command}
  407.   var
  408.     PageSize, I : Integer;
  409.  
  410.   begin                      {EdDownPage}
  411.     with CurWin^ do begin
  412.       PageSize := Succ(LastLineNo-FirstTextNo);
  413.       I := 1;
  414.       while (I < PageSize) and EdPtrNotNil(TopLine^.FwdLink) do begin
  415.         EdFwdPtr(TopLine);
  416.         Inc(I);
  417.         if EdPtrIsNil(CurLine^.FwdLink) then
  418.           Dec(LineNo)
  419.         else begin
  420.           Inc(Clineno);
  421.           EdFwdPtr(CurLine);
  422.         end;
  423.       end;
  424.     end;
  425.   end;                       {EdDownPage}
  426.  
  427.   {***}
  428.   procedure EdLeftWord;
  429.     {-Move cursor to previous word}
  430.  
  431.     procedure EdBackOneLine;
  432.       {-Move cursor up to the end of the previous line}
  433.  
  434.     begin                    {EdBackOneLine}
  435.       if EdPtrNotNil(CurWin^.CurLine^.Backlink) then begin
  436.         EdUpLine;
  437.         EdRightLine;
  438.       end;
  439.     end;                     {EdBackOneLine}
  440.  
  441.   begin                      {EdLeftWord}
  442.     with CurWin^ do
  443.  
  444.       if ColNo <= 1 then
  445.  
  446.         {Beginning of line, move to end of previous line}
  447.         EdBackOneLine
  448.  
  449.       else
  450.         with CurLine^ do begin
  451.  
  452.           {Work within the current line}
  453.           EdMoveCursorIntoLine;
  454.  
  455.           if (Txt^[ColNo] in Alphas) then begin
  456.  
  457.             {Currently within a word}
  458.             Dec(ColNo);
  459.             if not(Txt^[ColNo] in Alphas) then
  460.               {Go to end of previous word}
  461.               while (ColNo > 0) and not(Txt^[ColNo] in Alphas) do
  462.                 Dec(ColNo);
  463.  
  464.             {Go to beginning of this word}
  465.             while (ColNo > 0) and (Txt^[ColNo] in Alphas) do
  466.               Dec(ColNo);
  467.  
  468.             {Forward to next Alpha}
  469.             Inc(ColNo);
  470.  
  471.           end else begin
  472.  
  473.             {Currently between words}
  474.             {Go to end of previous word}
  475.             while (ColNo > 0) and not(Txt^[ColNo] in Alphas) do
  476.               Dec(ColNo);
  477.             if ColNo <> 0 then
  478.               {Go to begin of previous word}
  479.               while (ColNo > 0) and (Txt^[ColNo] in Alphas) do
  480.                 Dec(ColNo);
  481.             Inc(ColNo);
  482.  
  483.           end;
  484.  
  485.         end;
  486.   end;                       {EdLeftWord}
  487.  
  488.   {***}
  489.   procedure EdRightWord;
  490.     {-Advance cursor to next word}
  491.  
  492.   begin                      {EdRightWord}
  493.     with CurWin^ do begin
  494.  
  495.       if EdPtrIsNil(CurLine^.FwdLink) and (ColNo >= EdTextLength(CurLine)) then
  496.         Exit;
  497.  
  498.       {Work within the current line buffer}
  499.       EdMoveCursorIntoLine;
  500.  
  501.       with CurLine^ do
  502.         if (Txt^[ColNo] in Alphas) then begin
  503.  
  504.           {Starting within a word}
  505.           while (ColNo <= Bufflen) and (Txt^[ColNo] in Alphas) do
  506.             {Advance to next non-alpha}
  507.             Inc(ColNo);
  508.  
  509.           if (ColNo <= Bufflen) then begin
  510.             {Skip over spaces after the word}
  511.             while (ColNo <= Bufflen) and not(Txt^[ColNo] in Alphas) do
  512.               Inc(ColNo);
  513.             if ColNo > Bufflen then
  514.               {Rest of line was non-alpha, stop after last word}
  515.               EdRightLine;
  516.           end;
  517.  
  518.         end else begin
  519.  
  520.           {Starting in white space, get to next non-blank}
  521.           while (ColNo <= Bufflen) and not(Txt^[ColNo] in Alphas) do
  522.             {Advance to next non-space on this line}
  523.             Inc(ColNo);
  524.  
  525.           if (ColNo <= Bufflen) then
  526.             {Found a non-blank}
  527.             Exit;
  528.  
  529.           EdDownLine;
  530.           ColNo := 1;
  531.  
  532.         end;
  533.     end;
  534.   end;                       {EdRightWord}
  535.  
  536.   {***}
  537.   procedure EdDeleteRightWord;
  538.     {-Process delete right word command}
  539.   var
  540.     StartClass : Integer;
  541.  
  542.     function EdClass : Integer;
  543.     var
  544.       Ch : Char;
  545.  
  546.     begin                    {EdClass}
  547.       with CurWin^ do
  548.         Ch := CurLine^.Txt^[ColNo];
  549.       if Ch = Blank then
  550.         EdClass := 1
  551.       else if (Ch in Alphas) then
  552.         EdClass := 2
  553.       else
  554.         EdClass := 3
  555.     end;                     {EdClass}
  556.  
  557.   begin                      {EdDeleteRightWord}
  558.  
  559.     with CurWin^ do
  560.  
  561.       if ColNo > EdTextLength(CurLine) then begin
  562.  
  563.         {Join next line to end of this one}
  564.         Modified := True;
  565.         EdJoinline;
  566.         {Flag forces the newly joined line to be rebuffered for ^QL}
  567.         Blockop := True;
  568.  
  569.       end else begin
  570.  
  571.         if CurLine^.Txt^[ColNo] <> Blank then begin
  572.           {In a word - delete to next space}
  573.           StartClass := EdClass;
  574.           while (EdClass = StartClass) and (ColNo <= CurLine^.Bufflen) do
  575.             EdDeleteRightChar;
  576.         end;
  577.         {In white space - delete spaces}
  578.         while (CurLine^.Txt^[ColNo] = Blank) and (ColNo <= EdTextLength(CurLine)) do
  579.           EdDeleteRightChar;
  580.  
  581.       end;
  582.  
  583.     {Force screen to be fully updated}
  584.     IntrFlag := NoInterr;
  585.  
  586.   end;                       {EdDeleteRightWord}
  587.  
  588.   {***}
  589.   procedure EdProcesstext(Ch : Char);
  590.     {-Process text input}
  591.   label
  592.     ExitPoint;
  593.   var
  594.     Len : Integer;
  595.  
  596.   begin                      {EdProcesstext}
  597.  
  598.     with CurWin^ do begin
  599.  
  600.       if ColNo >= MaxLineLength then
  601.         {Cursor sitting at maximum length, ignore further characters}
  602.         Exit;
  603.  
  604.       with CurLine^ do begin
  605.  
  606.         if InsertFlag then begin
  607.           {Insert mode, shift existing characters right}
  608.  
  609.           if ColNo >= Bufflen then
  610.             Len := ColNo
  611.           else
  612.             Len := Succ(EdTextLength(CurLine));
  613.  
  614.           if (Len >= Bufflen) then
  615.             {Text buffer is full, size it up - keep at least one blank at end}
  616.             if not EdSizeline(CurLine, Succ(Len), True) then
  617.               Exit;
  618.  
  619.           {Shift existing text over one character}
  620.           Move(Txt^[ColNo], Txt^[Succ(ColNo)], Bufflen-ColNo);
  621.  
  622.           {Fix up markers}
  623.           EdFixBlockInsertedSpace(CurLine, ColNo, 1);
  624.           EdFixMarkInsertedSpace(CurLine, ColNo, 1);
  625.  
  626.         end else
  627.           {Overwrite mode}
  628.           if Succ(ColNo) >= Bufflen then
  629.             if not EdSizeline(CurLine, Succ(ColNo), True) then
  630.               Exit;
  631.  
  632.         {Add new character}
  633.         Txt^[ColNo] := Ch;
  634.  
  635.       end;                   {with Curline^}
  636.  
  637. ExitPoint:
  638.       Inc(ColNo);
  639.       Modified := True;
  640.  
  641.       {Get out fast if macro is in progress}
  642.       if EditUsercommandInput = 0 then begin
  643.         {Assure horizontal scroll is up to date for this window}
  644.         EdHscrollOne(CurWin);
  645.  
  646.         {Update the cursor}
  647.         EdUpdateCursor;
  648.  
  649.         {Update the current line on screen}
  650.         EdUpdateLine(CurLine, Pred(FirstTextNo+LineNo), LeftEdge, LeftCol, AT);
  651.  
  652.         {Update the status line}
  653.         EdUpdateStatusLine(CurWin);
  654.  
  655.         {Assure rest of screen updated when there is time}
  656.         UpdateScreen := True;
  657.       end;
  658.     end;
  659.   end;                       {EdProcesstext}
  660.  
  661.   procedure EdInsertCtrlChar;
  662.     {-Insert literal character as text into file}
  663.  
  664.   begin                      {EdInsertCtrlChar}
  665.     {Let us see the ^P character}
  666.     EdDisplayCommandBuffer;
  667.     {And assure ^U will get through}
  668.     AbortEnable := False;
  669.     EdProcesstext(EdGetAnyChar);
  670.   end;                       {EdInsertCtrlChar}
  671.  
  672.   procedure EdLeftLine;
  673.     {-Move cursor to left edge of line}
  674.   begin                      {EdLeftLine}
  675.     EdGotoColumn(1);
  676.   end;                       {EdLeftLine}
  677.  
  678.   {***}
  679.   procedure EdWindowBottomFile;
  680.     {-Move cursor to bottom of file}
  681.  
  682.   begin                      {EdWindowBottomFile}
  683.     while EdPtrNotNil(CurWin^.CurLine^.FwdLink) do
  684.       EdDownLine;
  685.     {Go to end of line}
  686.     EdRightLine;
  687.   end;                       {EdWindowBottomFile}
  688.  
  689.   {***}
  690.   procedure EdUndo;
  691.     {-Process UNDO command}
  692.   var
  693.     P : PlineDesc;
  694.  
  695.   begin                      {EdUndo}
  696.  
  697.     {If either Undolimit or Undocount = 0, we don't have anything to undo}
  698.     if UndoLimit*UndoCount = 0 then
  699.       Exit;
  700.  
  701.     {Put the line back into the editing environment}
  702.  
  703.     Dec(UndoCount);
  704.     P := UndoStack;
  705.     EdFwdPtr(UndoStack);
  706.     if EdPtrIsNil(UndoStack) then
  707.       EdSetPtrNil(UndoEnd);
  708.  
  709.     {Reset all flags}
  710.     P^.Flags := 0;
  711.  
  712.     {Insert the line into the current text stream}
  713.  
  714.     with CurWin^ do begin
  715.  
  716.       Modified := True;
  717.  
  718.       if EdPtrIsNil(TopLine^.Backlink) and EdPtrIsNil(TopLine^.FwdLink) and (EdTextLength(CurLine) = 0) then begin
  719.  
  720.         {File is empty, don't insert, just copy}
  721.         {Size up topline if needed}
  722.         if EdSizeline(TopLine, Succ(P^.Bufflen), True) then
  723.           Move(P^.Txt^[1], TopLine^.Txt^[1], P^.Bufflen);
  724.         EdDesTextDesc(P);
  725.  
  726.       end else begin
  727.  
  728.         {Really insert the buffer}
  729.         P^.Backlink := CurLine^.Backlink;
  730.         if EdPtrNotNil(P^.Backlink) then
  731.           P^.Backlink^.FwdLink := P;
  732.         P^.FwdLink := CurLine;
  733.         CurLine^.Backlink := P;
  734.         if CurLine = TopLine then
  735.           {Keep Topline above Curline}
  736.           TopLine := P;
  737.         {Backup current line}
  738.         CurLine := P;
  739.  
  740.       end;
  741.     end;
  742.  
  743.     EdRealign;
  744.   end;                       {EdUndo}
  745.  
  746.   procedure EdRestoreCurrentLine;
  747.     {-Restore text and flags of current line}
  748.   var
  749.     M : Integer;
  750.  
  751.   begin                      {EdRestoreCurrentLine}
  752.     with CurWin^ do
  753.  
  754.       {Assure something has been stored}
  755.       if CurLineBuf^.Bufflen <> 0 then begin
  756.  
  757.         {Reset blocks and markers as needed}
  758.         if Blockfrom.Line = CurLine then
  759.           Blockfrom.Col := CurLineFrom.Col;
  760.         if Blockfrom.Line <> CurLineFrom.Line then begin
  761.           Blockfrom.Line := CurLineFrom.Line;
  762.           {Reset screen attributes}
  763.           EdOffblock;
  764.         end;
  765.         if Blockto.Line = CurLine then
  766.           Blockto.Col := CurLineTo.Col;
  767.         if Blockto.Line <> CurLineTo.Line then begin
  768.           Blockto.Line := CurLineTo.Line;
  769.           EdOffblock;
  770.         end;
  771.  
  772.         if EdFlagSet(CurLine, InMark) and not(EdFlagSet(CurLineBuf, InMark)) then begin
  773.           {Text mark was added - reset it}
  774.           for M := 0 to MaxMarker do
  775.             if Marker[M].Line = CurLine then
  776.               EdSetPtrNil(Marker[M].Line);
  777.           {Any mark stolen from another line is lost}
  778.         end;
  779.  
  780.         CurLine^.Flags := CurLineBuf^.Flags;
  781.  
  782.         Move(CurLineBuf^.Txt^[1], CurLine^.Txt^[1], CurLineBuf^.Bufflen);
  783.         if CurLineBuf^.Bufflen < CurLine^.Bufflen then
  784.           {Line has grown in the meantime, so right fill with blanks}
  785.           FillChar(CurLine^.Txt^[Succ(CurLineBuf^.Bufflen)],
  786.                    CurLine^.Bufflen-CurLineBuf^.Bufflen, Blank);
  787.         {Reset the cursor}
  788.         ColNo := CurLineCol;
  789.         LeftEdge := 1;
  790.         EdHscrollOne(CurWin);
  791.         {Restoring the line may have modified the file}
  792.         Modified := True;
  793.       end;
  794.   end;                       {EdRestoreCurrentLine}
  795.  
  796.   {***}
  797.   procedure EdDeleteLine;
  798.     {-Process delete line command}
  799.   var
  800.     P : PlineDesc;
  801.  
  802.     procedure EdDelline(P : PlineDesc);
  803.       {-Delete line from text stream}
  804.  
  805.     begin                    {EdDelline}
  806.  
  807.       {Check block limits}
  808.       if P = Blockfrom.Line then begin
  809.  
  810.         if (P = Blockto.Line) then begin
  811.           {Remove block altogether}
  812.           EdSetPtrNil(Blockfrom.Line);
  813.           EdSetPtrNil(Blockto.Line);
  814.         end else begin
  815.           {Note p^.fwdlink cannot be nil in this condition}
  816.           Blockfrom.Line := P^.FwdLink;
  817.           Blockfrom.Col := 1;
  818.         end;
  819.  
  820.       end else if P = Blockto.Line then begin
  821.  
  822.         {Blockto is being deleted}
  823.         if EdPtrIsNil(P^.FwdLink) then begin
  824.           {Note that p^.backlink cannot be nil in this condition}
  825.           Blockto.Line := P^.Backlink;
  826.           Blockto.Col := Succ(EdTextLength(P^.Backlink));
  827.         end else begin
  828.           Blockto.Line := P^.FwdLink;
  829.           Blockto.Col := 1;
  830.         end;
  831.  
  832.       end;
  833.  
  834.       {Fix up topline, curline, lineno of any window now pointing to the line p}
  835.       EdFixUpWindowSpan(P);
  836.  
  837.       {Put the line on undo stack if possible}
  838.       if EdPtrNotNil(P^.FwdLink) or (EdTextLength(P) > 0) then
  839.         EdPushUndo(P);
  840.  
  841.     end;                     {EdDelline}
  842.  
  843.   begin                      {EdDeleteLine}
  844.     with CurWin^ do begin
  845.       Modified := True;
  846.       P := CurLine;
  847.       if EdPtrIsNil(P^.FwdLink) then begin
  848.  
  849.         {This is the only line or the last line in the file}
  850.         CurLine := EdMaktextdesc(1);
  851.         if GotError then
  852.           Exit;
  853.         CurLine^.Backlink := P^.Backlink;
  854.         EdSetPtrNil(CurLine^.FwdLink);
  855.         if EdPtrNotNil(P^.Backlink) then
  856.           P^.Backlink^.FwdLink := CurLine;
  857.         if P = TopLine then
  858.           TopLine := CurLine;
  859.  
  860.       end else if EdPtrIsNil(P^.Backlink) then begin
  861.  
  862.         {It's the first line in the file}
  863.         TopLine := CurLine^.FwdLink;
  864.         CurLine := TopLine;
  865.         EdSetPtrNil(TopLine^.Backlink);
  866.  
  867.       end else begin
  868.  
  869.         {In the middle of the file}
  870.         if P = TopLine then
  871.           EdFwdPtr(TopLine);
  872.         EdFwdPtr(CurLine);
  873.         CurLine^.Backlink := P^.Backlink;
  874.         P^.Backlink^.FwdLink := CurLine;
  875.  
  876.       end;
  877.  
  878.       EdDelline(P);
  879.       ColNo := 1;
  880.  
  881.     end;
  882.     EdRealign;
  883.  
  884.     {Force screen to fully update after this command}
  885.     IntrFlag := NoInterr;
  886.  
  887.   end;                       {EdDeleteLine}
  888.  
  889.   procedure EdDeleteLineRight;
  890.     {-Kill text to right of cursor}
  891.   var
  892.     M : Integer;
  893.  
  894.   begin                      {EdDeleteLineRight}
  895.     with CurWin^ do begin
  896.  
  897.       if ColNo > CurLine^.Bufflen then
  898.         Exit;
  899.  
  900.       {Just blank out the text}
  901.       FillChar(CurLine^.Txt^[ColNo], Succ(CurLine^.Bufflen-ColNo), Blank);
  902.  
  903.       Modified := True;
  904.  
  905.       {Fix up markers}
  906.       if (Blockfrom.Line = CurLine) and (Blockfrom.Col > ColNo) then begin
  907.         EdClrFlag(CurLine, InBlock);
  908.         if (Blockto.Line = CurLine) or EdPtrIsNil(CurLine^.FwdLink) then begin
  909.           {whole block deleted}
  910.           EdSetPtrNil(Blockfrom.Line);
  911.           EdSetPtrNil(Blockto.Line);
  912.         end else begin
  913.           Blockfrom.Line := CurLine^.FwdLink;
  914.           Blockfrom.Col := 1;
  915.         end;
  916.       end;
  917.       if (Blockto.Line = CurLine) and (Blockto.Col > ColNo) then
  918.         Blockto.Col := ColNo;
  919.       if EdFlagSet(CurLine, InMark) then
  920.         for M := 0 to MaxMarker do
  921.           with Marker[M] do
  922.             if (Line = CurLine) and (Col > ColNo) then
  923.               Col := ColNo;
  924.  
  925.     end;
  926.   end;                       {EdDeleteLineRight}
  927.  
  928.   {***}
  929.   procedure EdFlagExit;
  930.     {-Set flag to exit editor}
  931.  
  932.   begin                      {EdFlagExit}
  933.     Rundown := True;
  934.     if CleanupAtExit then begin
  935.       {Dispose of heap space used by text}
  936.       EdDeleteAllText(CurWin);
  937.       {Push window onto free list}
  938.       EdPushWindowStack(CurWin);
  939.     end;
  940.   end;                       {EdFlagExit}
  941.  
  942.   {***}
  943.   procedure EdSysInfo;
  944.     {-Display editor information}
  945.   var
  946.     Ch : Char;
  947.  
  948.   begin                      {EdSysInfo}
  949.     {Show version number and prompt for <Esc>}
  950.     EdWritePromptLine(EdGetMessage(343)+Version+'-'+EdGetMessage(305));
  951.  
  952.     {Wait for <Esc>}
  953.     repeat
  954.       Ch := EdGetAnyChar;
  955.     until Abortcmd or (Ch = #27);
  956.  
  957.     {Restore the screen}
  958.     EdWritePromptLine('');
  959.   end;                       {EdSysInfo}
  960.  
  961.   {***}
  962.   procedure EdSizeWindow;
  963.     {-Interactively size the current window}
  964.   type
  965.     SizeCommands = (Bigger, Smaller, Accept, None);
  966.   var
  967.     TopEdge, Done : Boolean;
  968.  
  969.     procedure EdGrowWindow(TopEdge : Boolean);
  970.       {-Increase size of current window by one line}
  971.     var
  972.       W : PwinDesc;
  973.  
  974.     begin                    {EdGrowWindow}
  975.  
  976.       {Two or more windows previously guaranteed open}
  977.  
  978.       if TopEdge then begin
  979.         {Bottom Window}
  980.         {Add to top of window, taking it from previous window}
  981.         W := CurWin^.Backlink;
  982.         if (W^.LastLineNo-W^.FirstTextNo) < MinWindowLines then
  983.           Exit;
  984.         CurWin^.FirstLineNo := Pred(CurWin^.FirstLineNo);
  985.         W^.LastLineNo := Pred(W^.LastLineNo);
  986.         EdSetTextNo(CurWin);
  987.       end else begin
  988.         {Top or middle window}
  989.         {Add to bottom of window, taking it from next window}
  990.         W := CurWin^.FwdLink;
  991.         {Make sure the other window can be shrunk}
  992.         if (W^.LastLineNo-W^.FirstTextNo) < MinWindowLines then
  993.           Exit;
  994.         CurWin^.LastLineNo := Succ(CurWin^.LastLineNo);
  995.         W^.FirstLineNo := Succ(W^.FirstLineNo);
  996.         EdSetTextNo(W);
  997.       end;
  998.  
  999.       EdBackupCurline(W);
  1000.       UpdateScreen := True;
  1001.  
  1002.     end;                     {EdGrowWindow}
  1003.  
  1004.     procedure EdShrinkWindow(TopEdge : Boolean);
  1005.       {-Reduce the size of the current window}
  1006.     var
  1007.       W : PwinDesc;
  1008.  
  1009.     begin                    {EdShrinkWindow}
  1010.  
  1011.       {Two or more windows previously guaranteed open}
  1012.  
  1013.       {Check that window is large enough to shrink}
  1014.       if (CurWin^.LastLineNo-CurWin^.FirstTextNo) < MinWindowLines then
  1015.         Exit;
  1016.  
  1017.       if TopEdge then begin
  1018.         {Bottom Window}
  1019.         {Subtract from top of window, adding it from previous window}
  1020.         W := CurWin^.Backlink;
  1021.         CurWin^.FirstLineNo := Succ(CurWin^.FirstLineNo);
  1022.         W^.LastLineNo := Succ(W^.LastLineNo);
  1023.         EdSetTextNo(CurWin);
  1024.       end else begin
  1025.         {Top or middle window}
  1026.         {Subtract from bottom of window, adding it to next window}
  1027.         W := CurWin^.FwdLink;
  1028.         CurWin^.LastLineNo := Pred(CurWin^.LastLineNo);
  1029.         W^.FirstLineNo := Pred(W^.FirstLineNo);
  1030.         EdSetTextNo(W);
  1031.       end;
  1032.  
  1033.       EdBackupCurline(CurWin);
  1034.       UpdateScreen := True;
  1035.  
  1036.     end;                     {EdShrinkWindow}
  1037.  
  1038.     function EdGetCommand(TopEdge : Boolean) : SizeCommands;
  1039.       {-Get a window sizing command}
  1040.     var
  1041.       Ch : Char;
  1042.  
  1043.     begin                    {EdGetCommand}
  1044.       EdGetCommand := None;
  1045.       Ch := EdGetAnyChar;
  1046.       if Ch = Null then begin
  1047.         {Extended character, get the other half}
  1048.         Ch := EdGetAnyChar;
  1049.         case Ch of
  1050.           #72 :              {Up arrow}
  1051.             if TopEdge then
  1052.               EdGetCommand := Bigger
  1053.             else
  1054.               EdGetCommand := Smaller;
  1055.           #80 :              {Down arrow}
  1056.             if TopEdge then
  1057.               EdGetCommand := Smaller
  1058.             else
  1059.               EdGetCommand := Bigger;
  1060.         end;
  1061.       end else if (Ch = ^M) or (Ch = ^[) then
  1062.         EdGetCommand := Accept;
  1063.     end;                     {EdGetCommand}
  1064.  
  1065.   begin                      {EdSizeWindow}
  1066.  
  1067.     {Make sure there are two windows or more}
  1068.     if (WindowCount <= 1) then begin
  1069.       EdErrormsg(56);
  1070.       Exit;
  1071.     end;
  1072.  
  1073.     {See whether top or bottom edge of window is changing}
  1074.     TopEdge := (CurWin^.FwdLink = Window1);
  1075.  
  1076.     {Put up a prompt}
  1077.     EdWritePromptLine(EdGetMessage(355));
  1078.     UpdateScreen := True;
  1079.  
  1080.     {Loop until done}
  1081.     Done := False;
  1082.     repeat
  1083.       if UpdateScreen then begin
  1084.         {Force redraw of entire screen}
  1085.         IntrFlag := NoInterr;
  1086.         EdUpdateScreen;
  1087.       end;
  1088.       case EdGetCommand(TopEdge) of
  1089.         Bigger :
  1090.           EdGrowWindow(TopEdge);
  1091.         Smaller :
  1092.           EdShrinkWindow(TopEdge);
  1093.         Accept :
  1094.           Done := True;
  1095.       end;
  1096.     until Done;
  1097.  
  1098.     UpdateScreen := True;
  1099.  
  1100.   end;                       {EdSizeWindow}
  1101.  
  1102. end.
  1103.