home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 16 / 16.iso / w / w048 / 2.ddi / MSSRC.ARC / MSTEXT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-12-21  |  46.7 KB  |  1,661 lines

  1. {                            MSTEXT.PAS
  2.                                MS 4.0
  3.                 Copyright (c) 1985, 87 by Borland International, Inc.         }
  4.  
  5. {$I msdirect.inc}
  6.  
  7. unit MsText;
  8.   {-Text processing commands}
  9.  
  10. interface
  11.  
  12. uses
  13.   Crt,                       {Basic video operations - standard unit}
  14.   Dos,                       {DOS interface - standard unit}
  15.   Errors,                    {Runtime error handler}
  16.   MsVars,                    {Global types and declarations}
  17.   MsScrn1,                   {Fast screen writing routines}
  18.   MsString,                  {String primitives}
  19.   MsPtrOp,                   {Primitive pointer operations}
  20.   EscSeq,                    {Returns text string for extended scan codes}
  21.   MsCmds,                    {Maps keystrokes to commands}
  22.   Int24,                     {DOS critical error handler}
  23.   Message,                   {Message system}
  24.   MsUser,                    {User keyboard input, line editing and error reporting}
  25.   MsMemOp,                   {Text buffer allocation and deallocation}
  26.   MsBack,                    {Background processes}
  27.   MsScrn2,                   {Editor screen updating}
  28.   MsMenu,                    {Pulldown and custom menu system}
  29.   MsDir,                     {Popup directory picker}
  30.   MsEdit;                    {Basic editing commands}
  31.  
  32. procedure EdPromptGotoCol;
  33.   {-Process goto col #n command}
  34.  
  35. procedure EdPromptGotoLine;
  36.   {-Process goto line #n command}
  37.  
  38. procedure EdPromptGotoPage;
  39.   {-Prompt for and go to page}
  40.  
  41. procedure EdShowMemory;
  42.   {-Show free memory for text}
  43.  
  44. procedure EdSetMarker(M : Byte);
  45.   {-Process set text marker command}
  46.  
  47. procedure EdChangeCase(Mode : CaseChange);
  48.   {-Change case of current character or block}
  49.  
  50. procedure EdNextSentence;
  51.   {-Advance cursor to start of next sentence}
  52.  
  53. procedure EdPrevSentence;
  54.   {-Move cursor to start of sentence}
  55.  
  56. procedure EdInsertPrintFormat(Ch : Char);
  57.   {-Insert print font toggles surrounding current cursor or marked block}
  58.  
  59. procedure EdReformParagraph;
  60.   {-Reformat the current paragraph}
  61.  
  62. procedure EdReformBlock;
  63.   {-Reformat marked block}
  64.  
  65. procedure EdDeleteLineNoRecourse;
  66.   {-Process delete line command without pushing to undo stack}
  67.  
  68. procedure EdSysInfo;
  69.   {-display editor information}
  70.  
  71. procedure EdSizeWindow;
  72.   {-Interactively size the current window}
  73.  
  74. procedure EdWhatFont;
  75.   {-Display the font type of the character at the cursor}
  76.  
  77. procedure EdPromptGotoWindow;
  78.   {-Prompt for a window and go to it}
  79.  
  80. procedure EdPromptJumpMarker;
  81.   {-Use a menu to choose and jump to a text marker}
  82.  
  83. procedure EdPromptSetMarker;
  84.   {-Use a menu to choose and set a text marker}
  85.  
  86. procedure EdChooseAppending(var Choice : Integer);
  87.   {-Use a menu to choose between append and overwrite}
  88.  
  89. procedure EdHelpMenu;
  90.   {-Use a menu to select and display a help section}
  91.  
  92. procedure EdInsertUndoBuffer;
  93.   {-Insert the entire undo buffer prior to the current line of text}
  94.  
  95. procedure EdFlushUndo;
  96.   {-Delete the contents of the undo buffer}
  97.  
  98. procedure EdJumpLastPosition;
  99.   {-Move the cursor to its previous position}
  100.  
  101. procedure EdMoveToBegin;
  102.   {-Move cursor to prior line with equal indentation to current line}
  103.  
  104. procedure EdMoveToEnd;
  105.   {-Move cursor to following line with equal indent to current line}
  106.  
  107.   {==========================================================================}
  108.  
  109. implementation
  110.  
  111. type
  112.   SentencePosType = (InBlank, InSentence, AtStartofSentence, AtEndofSentence);
  113.  
  114.   {$L MSTEXT}
  115.  
  116.   function EdWordsInBuffer(var Buffer; Len : Integer) : Integer; external;
  117.   {-Fast word count for a single line, alphas=['a'..'z','A'..'Z','-',apostrophe]}
  118.  
  119.   procedure EdPromptGotoCol;
  120.     {-Prompt for and go to column}
  121.   var
  122.     Cno : Integer;
  123.  
  124.   begin                      {EdPromptGotoCol}
  125.     Cno := EdGetnumber(EdGetMessage(311), Curwin^.Colno);
  126.     if (Cno > 0) and (Cno <= Maxlinelength) then begin
  127.       EdGotoColumn(Cno);
  128.       ExitMenu := True;
  129.     end;
  130.   end;                       {EdPromptGotoCol}
  131.  
  132.   procedure EdPromptGotoLine;
  133.     {-Prompt for and go to line}
  134.   var
  135.     Lno : Integer;
  136.  
  137.   begin                      {EdPromptGotoLine}
  138.     {Assure line count is up to date for current window}
  139.     Intrflag := NoInterr;
  140.     EdGenLineOne(Curwin);
  141.     Intrflag := Interr;
  142.     Lno := EdGetnumber(EdGetMessage(312), Curwin^.Clineno);
  143.     if Lno > 0 then begin
  144.       EdGotoLine(Lno);
  145.       ExitMenu := True;
  146.     end;
  147.   end;                       {EdPromptGotoLine}
  148.  
  149.   procedure EdPromptGotoPage;
  150.     {-Prompt for and go to page}
  151.   var
  152.     Pnum : Integer;
  153.  
  154.   begin                      {EdPromptGotoPage}
  155.     if Curwin^.PA then begin
  156.       Pnum := EdGetnumber(EdGetMessage(357), EdGetPageNum(Curwin^.Curline));
  157.       if Pnum < 1 then
  158.         Pnum := 1
  159.       else if Pnum > MaxPage then
  160.         Pnum := MaxPage;
  161.       EdGotoPage(Pnum);
  162.       ExitMenu := True;
  163.     end else
  164.       EdErrormsg(40);
  165.   end;                       {EdPromptGotoPage}
  166.  
  167.   procedure EdShowMemory;
  168.     {-Show free memory for text}
  169.   var
  170.     Ch : Char;
  171.  
  172.   begin                      {EdShowMemory}
  173.     EdDisplayPromptWindow(
  174.                           EdCalcMemory+'-'+EdGetMessage(305), EdYcenterWindow(3), [#27], Ch, NormalBox);
  175.   end;                       {EdShowMemory}
  176.  
  177.   procedure EdSetMarker(M : Byte);
  178.     {-Process set text marker command}
  179.  
  180.   begin                      {EdSetMarker}
  181.     if not(M in [0..MaxMarker]) then begin
  182.       EdErrormsg(28);
  183.       Exit;
  184.     end;
  185.     with Marker[M] do begin
  186.       {Reset any previous version of mark}
  187.       if EdPtrNotNil(Line) then
  188.         EdClrFlag(Line, InMark);
  189.       {Set new mark}
  190.       with Curwin^ do begin
  191.         if (Line = Curline) and (Col = Colno) then
  192.           {Setting mark on current mark, clears mark}
  193.           EdSetPtrNil(Line)
  194.         else begin
  195.           Line := Curline;
  196.           Col := Colno;
  197.         end;
  198.       end;
  199.     end;
  200.     {Turn on mark display}
  201.     Markhide := True;
  202.     EdToggleTextMarker;
  203.   end;                       {EdSetMarker}
  204.  
  205.   procedure EdChangeCase(Mode : CaseChange);
  206.     {-Change case of current character or block}
  207.   var
  208.     P : PlineDesc;
  209.     I, Cmin, Cmax : Integer;
  210.  
  211.     procedure EdChangeCaseOneChar(Line : PlineDesc; Col : Integer);
  212.       {-Change case as requested by mode}
  213.     var
  214.       Ch : Char;
  215.  
  216.     begin                    {EdChangeCaseOneChar}
  217.       if Col <= Line^.Bufflen then begin
  218.         Ch := Line^.Txt^[Col];
  219.         case Mode of
  220.           ToUpper :
  221.             if (Ch >= 'a') and (Ch <= 'z') then
  222.               Ch := Chr(Ord(Ch)-32);
  223.           ToLower :
  224.             if (Ch >= 'A') and (Ch <= 'Z') then
  225.               Ch := Chr(Ord(Ch)+32);
  226.           Toggle :
  227.             if (Ch >= 'A') and (Ch <= 'Z') then
  228.               Ch := Chr(Ord(Ch)+32)
  229.             else if (Ch >= 'a') and (Ch <= 'z') then
  230.               Ch := Chr(Ord(Ch)-32);
  231.         end;
  232.         Line^.Txt^[Col] := Ch;
  233.       end;
  234.     end;                     {EdChangeCaseOneChar}
  235.  
  236.   begin                      {EdChangeCase}
  237.     with Curwin^ do begin
  238.  
  239.       Modified := True;
  240.  
  241.       if EdNoBlock then
  242.         EdChangeCaseOneChar(Curline, Colno)
  243.       else if not(EdCursorInBlock(Curline, Colno, False)) then
  244.         EdChangeCaseOneChar(Curline, Colno)
  245.       else begin
  246.         {A visible block is defined, change case throughout the block}
  247.         P := Blockfrom.Line;
  248.         Cmin := Blockfrom.Col;
  249.  
  250.         repeat
  251.           if P = Blockto.Line then
  252.             Cmax := Pred(Blockto.Col)
  253.           else
  254.             Cmax := P^.Bufflen;
  255.           for I := Cmin to Cmax do
  256.             EdChangeCaseOneChar(P, I);
  257.           Cmin := 1;
  258.           if P = Blockto.Line then
  259.             EdSetPtrNil(P)
  260.           else
  261.             EdFwdPtr(P);
  262.         until EdPtrIsNil(P);
  263.  
  264.       end;
  265.     end;
  266.   end;                       {EdChangeCase}
  267.  
  268.   procedure EdReformOneParagraph(BlockMode : Boolean);
  269.     {-Reformat a single paragraph to fit within the right margin}
  270.   label
  271.     ExitPoint;
  272.   var
  273.     C, R, EffLen, Len, MinCol, Junk : Integer;
  274.     SaveInsert : Boolean;
  275.  
  276.     function EdEmptyLine(P : PlineDesc; var Len : Integer) : Boolean;
  277.       {-return true if line is empty or starts with a format char or ends the block}
  278.  
  279.     begin                    {EdEmptyLine}
  280.       if EdPtrIsNil(P) then
  281.         EdEmptyLine := True
  282.       else begin
  283.         Len := EdTextLength(P);
  284.         EdEmptyLine := (Len = 0) or (P^.Txt^[1] = FormatChar) or (BlockMode and (P = Blockto.Line));
  285.       end;
  286.     end;                     {EdEmptyLine}
  287.  
  288.   begin                      {EdReformOneParagraph}
  289.  
  290.     with Curwin^ do begin
  291.  
  292.       {Check for empty line}
  293.       if EdEmptyLine(Curline, Len) then begin
  294.         EdDownLine;
  295.         Colno := 1;
  296.         Exit;
  297.       end;
  298.  
  299.       {Force insert mode for this operation}
  300.       SaveInsert := Insertflag;
  301.       Insertflag := True;
  302.  
  303.       R := Rmargin;
  304.  
  305.       {Assure first line is within left margin}
  306.       while (Colno < Lmargin) and (Curline^.Txt^[Colno] = Blank) do
  307.         Inc(Colno);
  308.       if Colno < Lmargin then begin
  309.         if not(EdInsertSpace(Curline, Colno, Wmargin-Colno)) then
  310.           Exit;
  311.         Colno := Lmargin;
  312.       end;
  313.  
  314.       {Reset pagination process}
  315.       EdResetPageLine(Curwin);
  316.  
  317.       {Continue until a termination line is found}
  318.       while not(EdEmptyLine(Curline, Len)) do begin
  319.  
  320.         if CW then begin
  321.           {Remove excess blanks}
  322.           Junk := 1;
  323.           EdCompress(Curline, Wmargin, Junk, Len);
  324.         end;
  325.         EffLen := EdComputeEffectiveColNo(True, Curline, Len);
  326.  
  327.         {Pull up succeeding lines until this line fills margin}
  328.         while (EffLen <= R) and EdPtrNotNil(Curline^.Fwdlink) and not(EdEmptyLine(Curline^.Fwdlink, Junk)) do begin
  329.           Colno := Len+2;
  330.           EdJoinline;
  331.           if Goterror then
  332.             goto ExitPoint;
  333.           if CW then
  334.             {Remove excess blanks}
  335.             EdCompress(Curline, Wmargin, Junk, Len)
  336.           else begin
  337.             {Remove leading blanks}
  338.             while Curline^.Txt^[Colno] = Blank do
  339.               EdDeleteRightChar;
  340.             Len := EdTextLength(Curline);
  341.           end;
  342.           EffLen := EdComputeEffectiveColNo(True, Curline, Len);
  343.         end;
  344.  
  345.         {Break line to stay within margin}
  346.         if EffLen > R then begin
  347.  
  348.           with Curline^ do begin
  349.             C := Len;
  350.             while EdComputeEffectiveColNo(True, Curline, C) > R do begin
  351.               {Move left to previous blank}
  352.               while (C > 0) and (Txt^[C] <> Blank) do
  353.                 Dec(C);
  354.               {Move left to previous non-blank}
  355.               while (C > 0) and (Txt^[C] = Blank) do
  356.                 Dec(C);
  357.             end;
  358.             {Right to blank}
  359.             Inc(C);
  360.             {Right to next non-blank}
  361.             while (C < Len) and (Txt^[C] = Blank) do
  362.               Inc(C);
  363.           end;
  364.           Colno := C;
  365.  
  366.           {Make sure a legal break point was found}
  367.           if AI then
  368.             MinCol := EdLineIndent(Curline)
  369.           else
  370.             MinCol := Wmargin;
  371.           if EdComputeEffectiveColNo(True, Curline, Colno) <= MinCol then begin
  372.             {Error, could not break line within margin}
  373.             EdErrormsg(25);
  374.             goto ExitPoint;
  375.           end;
  376.  
  377.           {Break the line here}
  378.           EdInsertLine;
  379.  
  380.           {Apply right justification}
  381.           if JU then begin
  382.             EdRightJustify(Curline, Wmargin, R);
  383.             if Goterror then
  384.               goto ExitPoint;
  385.           end;
  386.  
  387.         end;
  388.  
  389.         if EdPtrNotNil(Curline^.Fwdlink) then begin
  390.           {Move to next line}
  391.           EdFwdPtr(Curline);
  392.           Colno := Wmargin;
  393.         end else begin
  394.           {End of file, force exit}
  395.           EdRightLine;
  396.           goto ExitPoint;
  397.         end;
  398.  
  399.       end;
  400.  
  401. ExitPoint:
  402.       Insertflag := SaveInsert;
  403.       EdRealign;
  404.  
  405.     end;
  406.   end;                       {EdReformOneParagraph}
  407.  
  408.   procedure EdAdvance(var P : PlineDesc; var C, Len : Integer);
  409.     {-Advance cursor to next column or line}
  410.  
  411.   begin                      {EdAdvance}
  412.     if C <= Len then
  413.       Inc(C)
  414.     else if EdPtrNotNil(P^.Fwdlink) then begin
  415.       EdFwdPtr(P);
  416.       Len := EdTextLength(P);
  417.       C := 1;
  418.     end;
  419.   end;                       {EdAdvance}
  420.  
  421.   function EdSentencePos(P : PlineDesc; C, Len : Integer) : SentencePosType;
  422.     {-Return position in sentence}
  423.   var
  424.     Ch : Char;
  425.  
  426.   begin                      {EdSentencePos}
  427.     if Len = 0 then begin
  428.       if EdPtrIsNil(P^.Fwdlink) then
  429.         EdSentencePos := AtStartofSentence
  430.       else
  431.         EdSentencePos := AtEndofSentence;
  432.     end else if C > Len then begin
  433.       if EdPtrIsNil(P^.Fwdlink) then
  434.         EdSentencePos := AtStartofSentence
  435.       else
  436.         EdSentencePos := InBlank;
  437.     end else begin
  438.       Ch := P^.Txt^[C];
  439.       if (Ch <= Blank) then
  440.         EdSentencePos := InBlank
  441.       else if (Ch in SentenceEnd) then
  442.         EdSentencePos := AtEndofSentence
  443.       else if ((C = 1) and (Ch = FormatChar)) then
  444.         EdSentencePos := AtStartofSentence
  445.       else
  446.         EdSentencePos := InSentence;
  447.     end;
  448.   end;                       {EdSentencePos}
  449.  
  450.   procedure EdNextSentence;
  451.     {-Advance cursor to start of next sentence}
  452.   var
  453.     SentencePos : SentencePosType;
  454.     Len : Integer;
  455.  
  456.   begin                      {EdNextSentence}
  457.     with Curwin^ do begin
  458.  
  459.       {Work within the current line buffer}
  460.       EdMoveCursorIntoLine;
  461.  
  462.       {Advance to end of current sentence}
  463.       Len := EdTextLength(Curline);
  464.       repeat
  465.         SentencePos := EdSentencePos(Curline, Colno, Len);
  466.         if SentencePos <> AtEndofSentence then
  467.           EdAdvance(Curline, Colno, Len);
  468.       until (SentencePos <> InSentence) and (SentencePos <> InBlank);
  469.  
  470.       {Advance to start of next sentence}
  471.       if SentencePos <> AtStartofSentence then
  472.         repeat
  473.           EdAdvance(Curline, Colno, Len);
  474.           SentencePos := EdSentencePos(Curline, Colno, Len);
  475.         until (SentencePos <> InBlank) and (SentencePos <> AtEndofSentence);
  476.  
  477.     end;
  478.     EdRealignOne(Curwin);
  479.   end;                       {EdNextSentence}
  480.  
  481.   procedure EdPrevSentence;
  482.     {-Move cursor to start of sentence}
  483.   var
  484.     CurC, PrevC : Integer;
  485.     CurL, PrevL : PlineDesc;
  486.     SentencePos : SentencePosType;
  487.  
  488.     procedure EdRetreatToPrev;
  489.       {-Retreat to end of previous sentence}
  490.     var
  491.       Len : Integer;
  492.  
  493.       procedure EdRetreat(var Top, P : PlineDesc; var C, Len : Integer);
  494.         {-Regress cursor to previous column or line}
  495.  
  496.       begin                  {EdRetreat}
  497.         if C > 1 then
  498.           Dec(C)
  499.         else if EdPtrNotNil(P^.Backlink) then begin
  500.           if P = Top then begin
  501.             EdBackPtr(Top);
  502.             P := Top;
  503.           end else
  504.             EdBackPtr(P);
  505.           Len := EdTextLength(P);
  506.           C := Succ(Len);
  507.         end;
  508.       end;                   {EdRetreat}
  509.  
  510.       function EdSentencePosBack(P : PlineDesc; C, Len : Integer) : SentencePosType;
  511.         {-Return position in sentence when moving backwards}
  512.       var
  513.         Ch : Char;
  514.  
  515.       begin                  {EdSentencePosBack}
  516.         if Len = 0 then
  517.           EdSentencePosBack := {InBlank} AtEndofSentence
  518.         else if (C = 1) and EdPtrIsNil(P^.Backlink) then
  519.           EdSentencePosBack := AtStartofSentence
  520.         else begin
  521.           Ch := P^.Txt^[C];
  522.           if (Ch <= Blank) then
  523.             EdSentencePosBack := InBlank
  524.           else if (Ch in SentenceEnd) then
  525.             EdSentencePosBack := AtEndofSentence
  526.           else if ((C = 1) and (Ch = FormatChar)) then
  527.             EdSentencePosBack := AtStartofSentence
  528.           else
  529.             EdSentencePosBack := InSentence;
  530.         end;
  531.       end;                   {EdSentencePosBack}
  532.  
  533.     begin                    {EdRetreatToPrev}
  534.       with Curwin^ do begin
  535.         Len := EdTextLength(Curline);
  536.         repeat
  537.           EdRetreat(TopLine, Curline, Colno, Len);
  538.           SentencePos := EdSentencePosBack(Curline, Colno, Len);
  539.         until (SentencePos <> InSentence) and (SentencePos <> InBlank);
  540.       end;
  541.     end;                     {EdRetreatToPrev}
  542.  
  543.     procedure EdAdvanceToNext;
  544.       {-Advance cursor to start of next sentence}
  545.     var
  546.       Len : Integer;
  547.  
  548.     begin                    {EdAdvanceToNext}
  549.       with Curwin^ do begin
  550.         Len := EdTextLength(Curline);
  551.         if SentencePos <> AtStartofSentence then
  552.           repeat
  553.             EdAdvance(Curline, Colno, Len);
  554.             SentencePos := EdSentencePos(Curline, Colno, Len);
  555.           until (SentencePos <> InBlank) and (SentencePos <> AtEndofSentence);
  556.       end;
  557.     end;                     {EdAdvancetoNext}
  558.  
  559.     function EdBeyond(P : PlineDesc; Pc : Integer; Q : PlineDesc; Qc : Integer) : Boolean;
  560.       {-Return true when the marker p:pc is equal or beyond the marker q:qc in the text stream}
  561.  
  562.     begin                    {EdBeyond}
  563.       if P = Q then
  564.         EdBeyond := (Pc >= Qc)
  565.       else begin
  566.         {Scan back from p looking for q}
  567.         repeat
  568.           EdBackPtr(P);
  569.           if P = Q then begin
  570.             EdBeyond := True;
  571.             Exit;
  572.           end;
  573.         until EdPtrIsNil(P);
  574.         EdBeyond := False;
  575.       end;
  576.     end;                     {EdBeyond}
  577.  
  578.   begin                      {EdPrevSentence}
  579.     with Curwin^ do begin
  580.  
  581.       {Get out if at beginning of file}
  582.       if (Colno = 1) and EdPtrIsNil(Curline^.Backlink) then
  583.         Exit;
  584.  
  585.       {Work within the current line buffer}
  586.       EdMoveCursorIntoLine;
  587.  
  588.       {Store current position}
  589.       CurL := Curline;
  590.       CurC := Colno;
  591.       PrevL := CurL;
  592.       PrevC := CurC;
  593.  
  594.       while EdBeyond(Curline, Colno, CurL, CurC) do begin
  595.         {Continue until solution prior to original cursor is found}
  596.         Curline := PrevL;
  597.         Colno := PrevC;
  598.  
  599.         {Go back another sentence}
  600.         EdRetreatToPrev;
  601.  
  602.         {Store current position}
  603.         PrevC := Colno;
  604.         PrevL := Curline;
  605.  
  606.         if SentencePos <> AtStartofSentence then
  607.           {Advance to start of next}
  608.           EdAdvanceToNext;
  609.       end;
  610.  
  611.     end;
  612.     EdRealignOne(Curwin);
  613.   end;                       {EdPrevSentence}
  614.  
  615.   procedure EdInsertPrintFormat(Ch : Char);
  616.     {-Insert print font toggles surrounding current cursor or marked block}
  617.   var
  618.     C : BlockMarker;
  619.     SaveInsertMode : Boolean;
  620.  
  621.     procedure EdUpdateVisibleAttributes;
  622.       {-Assure line attribute flags are updated}
  623.     var
  624.       P : PlineDesc;
  625.       L : Integer;
  626.  
  627.     begin                    {EdUpdateVisibleAttributes}
  628.       with Curwin^ do begin
  629.         {Get pointer to last text line visible in current window}
  630.         P := TopLine;
  631.         L := 1;
  632.         while EdPtrNotNil(P) and (L <= Succ(Lastlineno-Firsttextno)) do begin
  633.           EdFwdPtr(P);
  634.           Inc(L);
  635.         end;
  636.       end;
  637.       {Update font flags up to that point, without interruption}
  638.       Intrflag := NoInterr;
  639.       EdSetAttrOne(Curwin, P);
  640.       Intrflag := Interr;
  641.     end;                     {EdUpdateVisibleAttributes}
  642.  
  643.   begin                      {EdInsertPrintFormat}
  644.     with Curwin^ do begin
  645.  
  646.       Modified := True;
  647.  
  648.       {Assure insert mode}
  649.       SaveInsertMode := Insertflag;
  650.       Insertflag := True;
  651.  
  652.       if EdNoBlock then begin
  653.         {Insert a pair of toggles}
  654.         EdProcesstext(Ch, False);
  655.         EdProcesstext(Ch, False);
  656.         {Note that attribute changed within line}
  657.         EdChangeFlag(Curline, True, NewAttr);
  658.         {Put cursor between the pair}
  659.         EdLeftChar;
  660.         {Assure line attribute flags are updated}
  661.         EdUpdateVisibleAttributes;
  662.       end else begin
  663.         {Insert toggles surrounding marked block}
  664.         with C do begin
  665.           Line := Curline;
  666.           Col := Colno;
  667.         end;
  668.         EdJumpMarker(Blockfrom);
  669.         EdProcesstext(Ch, False);
  670.         {Note that attribute changed within line}
  671.         EdChangeFlag(Curline, True, NewAttr);
  672.         EdJumpMarker(Blockto);
  673.         EdProcesstext(Ch, False);
  674.         {Note that attribute changed within line}
  675.         EdChangeFlag(Curline, True, NewAttr);
  676.         {Assure line attribute flags are updated}
  677.         EdUpdateVisibleAttributes;
  678.         {Turn off block marking so the font display is apparent}
  679.         Blockhide := True;
  680.         EdOffblock;
  681.         {Return to original position}
  682.         EdJumpMarker(C);
  683.       end;
  684.  
  685.       Insertflag := SaveInsertMode;
  686.     end;
  687.   end;                       {EdInsertPrintFormat}
  688.  
  689.   procedure EdReformParagraph;
  690.     {-Reformat the current paragraph}
  691.  
  692.   begin                      {EdReformParagraph}
  693.  
  694.     {Allow reformat only when Word Wrap mode is set}
  695.     if not(Curwin^.WW) then begin
  696.       EdErrormsg(60);
  697.       Exit;
  698.     end;
  699.  
  700.     EdReformOneParagraph(False);
  701.  
  702.   end;                       {EdReformParagraph}
  703.  
  704.   procedure EdReformBlock;
  705.     {-Reformat marked block}
  706.  
  707.   begin                      {EdReformBlock}
  708.     with Curwin^ do begin
  709.  
  710.       {Allow reformat only when Word Wrap mode is set}
  711.       if not(WW) then begin
  712.         EdErrormsg(60);
  713.         Exit;
  714.       end;
  715.  
  716.       {See if a contiguous, visible block is defined}
  717.       if EdNoBlock then begin
  718.         EdErrormsg(26);
  719.         Exit;
  720.       end;
  721.       if not(EdCursorInBlock(Curline, Colno, False)) then begin
  722.         EdErrormsg(59);
  723.         Exit;
  724.       end;
  725.  
  726.       {Can't reformat a single line block}
  727.       if Blockfrom.Line = Blockto.Line then
  728.         Exit;
  729.  
  730.       {Reformat entire marked block}
  731.       EdWait;
  732.       EdJumpMarker(Blockfrom);
  733.       repeat
  734.         EdReformOneParagraph(True);
  735.       until Goterror or Abortcmd or (Curline = Blockto.Line);
  736.  
  737.     end;
  738.   end;                       {EdReformBlock}
  739.  
  740.   procedure EdDeleteLineNoRecourse;
  741.     {-Process delete line command without pushing to undo stack}
  742.  
  743.   begin                      {EdDeleteLineNoRecourse}
  744.     UndoLimit := 0;
  745.     EdDeleteLine;
  746.     UndoLimit := SaveUndoLimit;
  747.   end;                       {EdDeleteLineNoRecourse}
  748.  
  749.   procedure EdSysInfo;
  750.     {-display editor information}
  751.   label
  752.     ExitPoint;
  753.   const
  754.     Items = 14;
  755.   var
  756.     W : WindowRec;
  757.     Ch : Char;
  758.     I : Byte;
  759.     Value, Line, CurDir : VarString;
  760.     JustMenu : Boolean;
  761.     WrdCnt : LongInt;
  762.  
  763.     function EdDOSversion : VarString;
  764.       {-Return the DOS version number, e.g., 3.1}
  765.     var
  766.       regs : registers;
  767.       Major, Minor : string[3];
  768.  
  769.     begin                    {EdDOSversion}
  770.       with regs do begin
  771.         Ah := $30;
  772.         intr($21, regs);
  773.         Str(Al, Major);
  774.         Str(Ah, Minor);
  775.         EdDOSversion := Major+'.'+Minor;
  776.       end;
  777.     end;                     {EdDOSversion}
  778.  
  779.     function EdMax(I, J : Integer) : Integer;
  780.       {-Return the maximum of two Words}
  781.  
  782.     begin                    {EdMax}
  783.       if I > J then
  784.         EdMax := I
  785.       else
  786.         EdMax := J;
  787.     end;                     {EdMax}
  788.  
  789.     function EdDateTime : VarString;
  790.       {-Return a formatted string containing date and time}
  791.     var
  792.       regs : registers;
  793.       Date, Time : VarString;
  794.       Year, Month, Day, Hour, Minute, Second, AmPm : string[4];
  795.  
  796.       function EdZeroPad(S : VarString) : VarString;
  797.         {-Left pad string with zeros until length is at least 2}
  798.  
  799.       begin                  {EdZeroPad}
  800.         while Length(S) < 2 do
  801.           S := '0'+S;
  802.         EdZeroPad := S;
  803.       end;                   {EdZeroPad}
  804.  
  805.     begin                    {EdDateTime}
  806.       with regs do begin
  807.         Ah := $2a;
  808.         intr($21, regs);
  809.         EdClearString(Date);
  810.         Str(dl, Day);
  811.         Month := Copy(Months, Succ(3*Pred(Dh)), 3);
  812.         Str(Cx, Year);
  813.         Date := Month+Blank+Day+','+Blank+Year;
  814.         Ah := $2C;
  815.         intr($21, regs);
  816.         Str(Dh, Second);
  817.         Str(Cl, Minute);
  818.         if Ch = 0 then begin
  819.           Ch := 12;
  820.           AmPm := 'AM';
  821.         end else if Ch < 12 then
  822.           AmPm := 'AM'
  823.         else begin
  824.           if Ch > 12 then
  825.             Ch := Ch-12;
  826.           AmPm := 'PM';
  827.         end;
  828.         Str(Ch, Hour);
  829.         Time := Blank+Hour+':'+EdZeroPad(Minute)+':'+EdZeroPad(Second)+Blank+AmPm;
  830.       end;
  831.       EdDateTime := Time+'  '+Date;
  832.     end;                     {EdDateTime}
  833.  
  834.     function EdGetWordCnt : LongInt;
  835.       {-Return the number of words in the current window}
  836.     var
  837.       P : PlineDesc;
  838.       Cnt : LongInt;
  839.  
  840.     begin                    {EdGetWordCnt}
  841.  
  842.       P := EdTopofStream(Curwin);
  843.       Cnt := 00;
  844.  
  845.       while EdPtrNotNil(P) do begin
  846.  
  847.         if EdKeyInterrupt then
  848.           Exit;
  849.  
  850.         with P^ do
  851.           Cnt := Cnt+EdWordsInBuffer(Txt^[1], Bufflen);
  852.  
  853.         EdFwdPtr(P);
  854.       end;
  855.       EdGetWordCnt := Cnt;
  856.     end;                     {EdGetWordCnt}
  857.  
  858.   begin                      {EdSysInfo}
  859.  
  860.     EdEraseMenuHelp;
  861.     EdWritePromptLine(EdGetMessage(255));
  862.  
  863.     JustMenu := (WindowCount = 0);
  864.  
  865.     {Set up a window}
  866.     GetDir(0, CurDir);
  867.     I := 4+EdMax(Length(CurDir), Length(Curwin^.Filename));
  868.     if I < 32 then
  869.       I := 32;
  870.     EdSaveTextWindow(Border, EdGetMessage(343)+Version+Blank, 24, 8, 24+I, 9+Items, W);
  871.  
  872.     {Write info to the window}
  873.     with W, Curwin^ do
  874.       for I := 1 to Items do begin
  875.  
  876.         EdClearString(Line);
  877.  
  878.         case I of
  879.  
  880.           1 :                {Current file message}
  881.             Line := EdGetMessage(402);
  882.  
  883.           2 :                {Current filename}
  884.             Line := Blank+Filename;
  885.  
  886.           3 :                {File modified status}
  887.             if not(JustMenu) then
  888.               if Modified then
  889.                 Line := EdGetMessage(398)
  890.               else
  891.                 Line := EdGetMessage(399);
  892.  
  893.           4 :                {Line count}
  894.             if not(JustMenu) then begin
  895.               EdGenLineOne(Curwin);
  896.               if not(EdKeyInterrupt) then begin
  897.                 Str(TlineNo, Value);
  898.                 if TlineNo = 1 then
  899.                   Line := Blank+Value+EdGetMessage(252)
  900.                 else
  901.                   Line := Blank+Value+EdGetMessage(400);
  902.               end;
  903.             end;
  904.  
  905.           5 :                {Byte count}
  906.             if not(JustMenu) then
  907.               if not(EdKeyInterrupt) then begin
  908.                 Str(TcharNo, Value);
  909.                 if TcharNo = 1 then
  910.                   Line := Blank+Value+EdGetMessage(251)
  911.                 else
  912.                   Line := Blank+Value+EdGetMessage(354);
  913.               end;
  914.  
  915.           6 :                {Word count}
  916.             if not(JustMenu) then begin
  917.               WrdCnt := EdGetWordCnt;
  918.               if not(EdKeyInterrupt) then begin
  919.                 Str(WrdCnt, Value);
  920.                 if WrdCnt = 01 then
  921.                   Line := Blank+Value+EdGetMessage(253)
  922.                 else
  923.                   Line := Blank+Value+EdGetMessage(254);
  924.               end;
  925.             end;
  926.  
  927.           7 :                {Page count}
  928.             if not(JustMenu) then
  929.               if PA then begin
  930.                 EdRepaginateOne(Curwin);
  931.                 if not(EdKeyInterrupt) then begin
  932.                   Str(Tpageno, Value);
  933.                   if Tpageno = 1 then
  934.                     Line := Blank+Value+EdGetMessage(250)
  935.                   else
  936.                     Line := Blank+Value+EdGetMessage(397);
  937.                 end;
  938.               end;
  939.  
  940.           8 :                {Blank line}
  941.             ;
  942.  
  943.           9 :                {Date and time}
  944.             Line := EdDateTime;
  945.  
  946.           10 :               {RAM bytes free}
  947.             Line := EdCalcMemory;
  948.  
  949.           11 :               {DOS version}
  950.             Line := EdGetMessage(352)+EdDOSversion;
  951.  
  952.           12 :               {Disk bytes free}
  953.             begin
  954.               Str(DiskFree(0), Value);
  955.               Line := Blank+Value+EdGetMessage(336);
  956.             end;
  957.  
  958.           13 :               {Current directory message}
  959.             Line := EdGetMessage(335);
  960.  
  961.           14 :               {Current directory}
  962.             Line := Blank+CurDir;
  963.  
  964.         end;
  965.         EdFastWrite(Line, YPosn+I, XPosn+2, ScreenAttr[MnColor]);
  966.       end;
  967.  
  968. ExitPoint:
  969.  
  970.     {Prompt for <Esc>}
  971.     EdWritePromptLine(EdGetMessage(305));
  972.  
  973.     {Wait for an Escape}
  974.     repeat
  975.       Ch := EdGetAnyChar;
  976.     until Abortcmd or (Ch = #27);
  977.  
  978.     {Restore the screen}
  979.     EdRestoreTextWindow(W);
  980.   end;                       {EdSysInfo}
  981.  
  982.   procedure EdSizeWindow;
  983.     {-Interactively size the current window}
  984.   type
  985.     SizeCommands = (Bigger, Smaller, Accept, None);
  986.   var
  987.     CursorState, TopEdge, Done : Boolean;
  988.  
  989.     procedure EdGrowWindow(TopEdge : Boolean);
  990.       {-Increase size of current window by one line}
  991.     var
  992.       W : Pwindesc;
  993.  
  994.     begin                    {EdGrowWindow}
  995.  
  996.       {Two or more windows previously guaranteed open}
  997.  
  998.       if TopEdge then begin
  999.         {Bottom Window}
  1000.         {Add to top of window, taking it from previous window}
  1001.         W := Curwin^.Backlink;
  1002.         if (W^.Lastlineno-W^.Firsttextno) < MinWindowLines then
  1003.           Exit;
  1004.         Curwin^.Firstlineno := Pred(Curwin^.Firstlineno);
  1005.         W^.Lastlineno := Pred(W^.Lastlineno);
  1006.         EdSetTextNo(Curwin);
  1007.       end else begin
  1008.         {Top or middle window}
  1009.         {Add to bottom of window, taking it from next window}
  1010.         W := Curwin^.Fwdlink;
  1011.         {Make sure the other window can be shrunk}
  1012.         if (W^.Lastlineno-W^.Firsttextno) < MinWindowLines then
  1013.           Exit;
  1014.         Curwin^.Lastlineno := Succ(Curwin^.Lastlineno);
  1015.         W^.Firstlineno := Succ(W^.Firstlineno);
  1016.         EdSetTextNo(W);
  1017.       end;
  1018.  
  1019.       EdBackupCurline(W);
  1020.       UpdateScreen := True;
  1021.  
  1022.     end;                     {EdGrowWindow}
  1023.  
  1024.     procedure EdShrinkWindow(TopEdge : Boolean);
  1025.       {-Reduce the size of the current window}
  1026.     var
  1027.       W : Pwindesc;
  1028.  
  1029.     begin                    {EdShrinkWindow}
  1030.  
  1031.       {Two or more windows previously guaranteed open}
  1032.  
  1033.       {And that window is large enough to shrink}
  1034.       if (Curwin^.Lastlineno-Curwin^.Firsttextno) < MinWindowLines then
  1035.         Exit;
  1036.  
  1037.       if TopEdge then begin
  1038.         {Bottom Window}
  1039.         {Subtract from top of window, adding it from previous window}
  1040.         W := Curwin^.Backlink;
  1041.         Inc(Curwin^.Firstlineno);
  1042.         Inc(W^.Lastlineno);
  1043.         EdSetTextNo(Curwin);
  1044.       end else begin
  1045.         {Top or middle window}
  1046.         {Subtract from bottom of window, adding it to next window}
  1047.         W := Curwin^.Fwdlink;
  1048.         Curwin^.Lastlineno := Pred(Curwin^.Lastlineno);
  1049.         W^.Firstlineno := Pred(W^.Firstlineno);
  1050.         EdSetTextNo(W);
  1051.       end;
  1052.       EdBackupCurline(Curwin);
  1053.       UpdateScreen := True;
  1054.     end;                     {EdShrinkWindow}
  1055.  
  1056.     function EdGetCommand(TopEdge : Boolean) : SizeCommands;
  1057.       {-Get a window sizing command}
  1058.     var
  1059.       Ch : Char;
  1060.  
  1061.     begin                    {EdGetCommand}
  1062.       EdGetCommand := None;
  1063.       Ch := EdGetAnyChar;
  1064.       if Ch = Null then begin
  1065.         {Extended character, get the other half}
  1066.         Ch := EdGetAnyChar;
  1067.         case Ch of
  1068.           #72 :              {Up arrow}
  1069.             if TopEdge then
  1070.               EdGetCommand := Bigger
  1071.             else
  1072.               EdGetCommand := Smaller;
  1073.           #80 :              {Down arrow}
  1074.             if TopEdge then
  1075.               EdGetCommand := Smaller
  1076.             else
  1077.               EdGetCommand := Bigger;
  1078.         end;
  1079.       end else if (Ch = ^M) or (Ch = ^[) then
  1080.         EdGetCommand := Accept;
  1081.     end;                     {EdGetCommand}
  1082.  
  1083.   begin                      {EdSizeWindow}
  1084.  
  1085.     {Assure there are two windows or more}
  1086.     if Zoomed or (WindowCount <= 1) then begin
  1087.       EdErrormsg(56);
  1088.       Exit;
  1089.     end;
  1090.  
  1091.     {See whether top or bottom edge of window is changing}
  1092.     TopEdge := (Curwin^.Fwdlink = Window1);
  1093.  
  1094.     {Put up a prompt}
  1095.     EdZapPromptLine;
  1096.     EdAppPromptLine(EdGetMessage(355));
  1097.     {Avoid leaving the solid cursor in the wrong window}
  1098.     if SolidCursor then
  1099.       EdEraseSolidCursor;
  1100.     CursorState := SolidCursor;
  1101.     SolidCursor := False;
  1102.     UpdateScreen := True;
  1103.  
  1104.     {Loop until done}
  1105.     Done := False;
  1106.     repeat
  1107.       if UpdateScreen then begin
  1108.         {Force redraw of entire screen}
  1109.         Intrflag := NoInterr;
  1110.         EdUpdateScreen;
  1111.       end;
  1112.       case EdGetCommand(TopEdge) of
  1113.         Bigger :
  1114.           EdGrowWindow(TopEdge);
  1115.         Smaller :
  1116.           EdShrinkWindow(TopEdge);
  1117.         Accept :
  1118.           Done := True;
  1119.       end;
  1120.     until Done;
  1121.  
  1122.     SolidCursor := CursorState;
  1123.     UpdateScreen := True;
  1124.  
  1125.   end;                       {EdSizeWindow}
  1126.  
  1127.   procedure EdWhatFont;
  1128.     {-Display the font type of the character at the cursor}
  1129.   var
  1130.     FontByte : Byte;
  1131.     NextOff : Boolean;
  1132.     Col, Ipos : Integer;
  1133.     C, Clast : PrintCommandtype;
  1134.     S : VarString;
  1135.  
  1136.   begin                      {EdWhatFont}
  1137.  
  1138.     with Curwin^, Curline^ do begin
  1139.  
  1140.       if not(AT) then begin
  1141.         {The font bytes are accurate only when fonts are displayed}
  1142.         EdErrormsg(111);
  1143.         Exit;
  1144.       end;
  1145.  
  1146.       {Assure attributes are fully updated for current line}
  1147.       EdSetAttrOne(Curwin, Curline^.Fwdlink);
  1148.       if EdKeyInterrupt then
  1149.         Exit;
  1150.  
  1151.       {Analyze the line up to the cursor}
  1152.       FontByte := Font;
  1153.       if Colno > Bufflen then
  1154.         Col := Bufflen
  1155.       else
  1156.         Col := Colno;
  1157.       NextOff := False;
  1158.       for Ipos := 1 to Col do begin
  1159.         if NextOff then begin
  1160.           EdUpdateFont(Clast, FontByte);
  1161.           NextOff := False;
  1162.         end;
  1163.         C := PrintMap[Txt^[Ipos]];
  1164.         if C <> PrtNone then
  1165.           if (FontByte and (1 shl Ord(C))) <> 0 then begin
  1166.             {Toggle the bit after the next character}
  1167.             NextOff := True;
  1168.             Clast := C;
  1169.           end else
  1170.             {Toggle appropriate bit of font byte}
  1171.             EdUpdateFont(C, FontByte);
  1172.       end;
  1173.     end;
  1174.  
  1175.     {Build a string to display}
  1176.     EdClearString(S);
  1177.     for C := PrtBold to PrtAlt2 do
  1178.       if (FontByte and (1 shl Ord(C))) <> 0 then begin
  1179.         if not(EdStringEmpty(S)) then
  1180.           S := S+'+';
  1181.         S := S+EdGetMessage(414+Ord(C));
  1182.       end;
  1183.     if EdStringEmpty(S) then
  1184.       {Normal text}
  1185.       S := EdGetMessage(406);
  1186.  
  1187.     {Display string and wait for keypress}
  1188.     if EdPtrNotNil(CurrMenu) then
  1189.       {Erase menus}
  1190.       EdEraseMenus;
  1191.     EdWritePromptLine(S);
  1192.     EdUpdateCursor;
  1193.     EdWaitforKey;
  1194.  
  1195.   end;                       {EdWhatFont}
  1196.  
  1197.   procedure EdPromptGotoWindow;
  1198.     {-Prompt for a window and go to it}
  1199.   var
  1200.     Menu : CustomMenuRec;
  1201.     Choice : Integer;
  1202.  
  1203.     function EdBuildMessages(var Menu : CustomMenuRec) : Boolean;
  1204.       {-Build the message table for the menu}
  1205.     var
  1206.       Item : Integer;
  1207.       S : VarString;
  1208.       W : Pwindesc;
  1209.  
  1210.     begin                    {EdBuildMessages}
  1211.       EdBuildMessages := False;
  1212.       with Menu do begin
  1213.  
  1214.         if EdMemAvail(Succ(MaxChoice) shl 2, FreeListTemp) then
  1215.           {Get the pointers}
  1216.           GetMem(Messages, Succ(MaxChoice) shl 2)
  1217.         else
  1218.           Exit;
  1219.  
  1220.         {Get the string space and fill in the file names}
  1221.         W := Window1;
  1222.         Item := 0;
  1223.         repeat
  1224.           Inc(Item);
  1225.           Str(Item, S);
  1226.           S := S+Blank+W^.Filename;
  1227.           if EdMemAvail(Succ(Length(S)), FreeListTemp) then
  1228.             GetMem(Messages^[Item], Succ(Length(S)))
  1229.           else
  1230.             Exit;
  1231.           Messages^[Item]^ := S;
  1232.           EdFwdPtr(W);
  1233.         until W = Window1;
  1234.  
  1235.       end;
  1236.       EdBuildMessages := True;
  1237.     end;                     {EdBuildMessages}
  1238.  
  1239.   begin                      {EdPromptGotoWindow}
  1240.  
  1241.     if WindowCount <= 1 then begin
  1242.       EdErrormsg(56);
  1243.       Exit;
  1244.     end;
  1245.  
  1246.     {Initialize the menu}
  1247.     with Menu do begin
  1248.       Xmin := 17;
  1249.       Ymin := 8;
  1250.       MessageNum := 304;
  1251.       PromptNum := 313;
  1252.       MinChoice := 1;
  1253.       MaxChoice := WindowCount;
  1254.       InitChoice := 1;
  1255.       CmdSet := NumCmdSet;
  1256.       UseLetters := False;
  1257.     end;
  1258.     if not(EdBuildMessages(Menu)) then begin
  1259.       EdErrormsg(35);
  1260.       Exit;
  1261.     end;
  1262.  
  1263.     {Get the menu choice}
  1264.     EdGetCustomMenuChoice(Menu, Choice);
  1265.  
  1266.     {Go to the selected window}
  1267.     if not(Abortcmd) then begin
  1268.       EdWindowGoto(Choice);
  1269.       ExitMenu := True;
  1270.     end;
  1271.  
  1272.   end;                       {EdPromptGotoWindow}
  1273.  
  1274.   procedure EdPromptJumpMarker;
  1275.     {-Use a menu to choose and jump to a text marker}
  1276.   var
  1277.     Menu : CustomMenuRec;
  1278.     Choice : Integer;
  1279.  
  1280.     function EdBuildMessages(var Menu : CustomMenuRec) : Boolean;
  1281.       {-Build the message table for the menu}
  1282.     var
  1283.       Item, Lcount : Integer;
  1284.       S, Ss : VarString;
  1285.       W : Pwindesc;
  1286.       P : PlineDesc;
  1287.  
  1288.     begin                    {EdBuildMessages}
  1289.       EdBuildMessages := False;
  1290.       with Menu do begin
  1291.  
  1292.         if EdMemAvail(Succ(MaxChoice) shl 2, FreeListTemp) then
  1293.           {Get the pointers}
  1294.           GetMem(Messages, Succ(MaxChoice) shl 2)
  1295.         else
  1296.           Exit;
  1297.  
  1298.         {Get the string space and fill in the markers}
  1299.         for Item := MinChoice to MaxChoice do begin
  1300.           S := Blank+Chr(48+Item);
  1301.           if EdPtrIsNil(Marker[Item].Line) then
  1302.             S := S+EdGetMessage(382)
  1303.           else begin
  1304.             W := EdFindWindow(Marker[Item].Line);
  1305.             if EdPtrIsNil(W) then
  1306.               S := S+EdGetMessage(380)
  1307.             else begin
  1308.               {Display file and line number}
  1309.               S := S+Blank+EdEndOfPath(W^.Filename);
  1310.               Lcount := 0;
  1311.               P := Marker[Item].Line;
  1312.               while EdPtrNotNil(P) do begin
  1313.                 Inc(Lcount);
  1314.                 EdBackPtr(P);
  1315.               end;
  1316.               Str(Lcount, Ss);
  1317.               S := S+' : '+Ss;
  1318.             end;
  1319.           end;
  1320.           if EdMemAvail(Succ(Length(S)), FreeListTemp) then
  1321.             GetMem(Messages^[Item], Succ(Length(S)))
  1322.           else
  1323.             Exit;
  1324.           Messages^[Item]^ := S;
  1325.         end;
  1326.       end;
  1327.       EdBuildMessages := True;
  1328.     end;                     {EdBuildMessages}
  1329.  
  1330.   begin                      {EdPromptJumpMarker}
  1331.  
  1332.     {Initialize the menu}
  1333.     with Menu do begin
  1334.       Xmin := 24;
  1335.       Ymin := 11;
  1336.       MessageNum := 304;
  1337.       PromptNum := 381;
  1338.       MinChoice := 0;
  1339.       MaxChoice := MaxMarker;
  1340.       InitChoice := 0;
  1341.       CmdSet := NumCmdSet;
  1342.       UseLetters := False;
  1343.     end;
  1344.     if not(EdBuildMessages(Menu)) then begin
  1345.       EdErrormsg(35);
  1346.       Exit;
  1347.     end;
  1348.  
  1349.     {Get the menu choice}
  1350.     EdGetCustomMenuChoice(Menu, Choice);
  1351.  
  1352.     {Go to the selected window}
  1353.     if not(Abortcmd) then
  1354.       if EdPtrNotNil(Marker[Choice].Line) then
  1355.         EdJumpMarker(Marker[Choice]);
  1356.  
  1357.   end;                       {EdPromptJumpMarker}
  1358.  
  1359.   procedure EdPromptSetMarker;
  1360.     {-Use a menu to choose and set a text marker}
  1361.   var
  1362.     Menu : CustomMenuRec;
  1363.     Choice : Integer;
  1364.  
  1365.     function EdBuildMessages(var Menu : CustomMenuRec) : Boolean;
  1366.       {-Build the message table for the menu}
  1367.     var
  1368.       Item, Lcount : Integer;
  1369.       S, Ss : VarString;
  1370.       W : Pwindesc;
  1371.       P : PlineDesc;
  1372.  
  1373.     begin                    {EdBuildMessages}
  1374.       EdBuildMessages := False;
  1375.       with Menu do begin
  1376.  
  1377.         if EdMemAvail(Succ(MaxChoice) shl 2, FreeListTemp) then
  1378.           {Get the pointers}
  1379.           GetMem(Messages, Succ(MaxChoice) shl 2)
  1380.         else
  1381.           Exit;
  1382.  
  1383.         {Get the string space and fill in the markers}
  1384.         for Item := MinChoice to MaxChoice do begin
  1385.           S := Blank+Chr(48+Item);
  1386.           if EdPtrIsNil(Marker[Item].Line) then
  1387.             S := S+EdGetMessage(379)
  1388.           else begin
  1389.             W := EdFindWindow(Marker[Item].Line);
  1390.             if EdPtrIsNil(W) then
  1391.               S := S+EdGetMessage(380)
  1392.             else begin
  1393.               {Display file and line number}
  1394.               S := S+Blank+EdEndOfPath(W^.Filename);
  1395.               Lcount := 0;
  1396.               P := Marker[Item].Line;
  1397.               while EdPtrNotNil(P) do begin
  1398.                 Inc(Lcount);
  1399.                 EdBackPtr(P);
  1400.               end;
  1401.               Str(Lcount, Ss);
  1402.               S := S+' : '+Ss;
  1403.             end;
  1404.           end;
  1405.           if EdMemAvail(Succ(Length(S)), FreeListTemp) then
  1406.             GetMem(Messages^[Item], Succ(Length(S)))
  1407.           else
  1408.             Exit;
  1409.           Messages^[Item]^ := S;
  1410.         end;
  1411.       end;
  1412.       EdBuildMessages := True;
  1413.     end;                     {EdBuildMessages}
  1414.  
  1415.   begin                      {EdPromptSetMarker}
  1416.  
  1417.     {Initialize the menu}
  1418.     with Menu do begin
  1419.       Xmin := 10;
  1420.       Ymin := 11;
  1421.       MessageNum := 304;
  1422.       PromptNum := 381;
  1423.       MinChoice := 0;
  1424.       MaxChoice := MaxMarker;
  1425.       InitChoice := 0;
  1426.       CmdSet := NumCmdSet;
  1427.       UseLetters := False;
  1428.     end;
  1429.     if not(EdBuildMessages(Menu)) then begin
  1430.       EdErrormsg(35);
  1431.       Exit;
  1432.     end;
  1433.  
  1434.     {Get the menu choice}
  1435.     EdGetCustomMenuChoice(Menu, Choice);
  1436.  
  1437.     {Go to the selected window}
  1438.     if not(Abortcmd) then
  1439.       EdSetMarker(Choice);
  1440.  
  1441.   end;                       {EdPromptSetMarker}
  1442.  
  1443.   procedure EdChooseAppending(var Choice : Integer);
  1444.     {-Use a menu to choose between append and overwrite}
  1445.   var
  1446.     Menu : CustomMenuRec;
  1447.  
  1448.     function EdBuildMessages(var Menu : CustomMenuRec) : Boolean;
  1449.       {-Build the message table for the menu}
  1450.     var
  1451.       Item : Integer;
  1452.       S : VarString;
  1453.  
  1454.     begin                    {EdBuildMessages}
  1455.       EdBuildMessages := False;
  1456.       with Menu do begin
  1457.         if EdMemAvail(Succ(MaxChoice) shl 2, FreeListTemp) then
  1458.           {Get the pointers}
  1459.           GetMem(Messages, Succ(MaxChoice) shl 2)
  1460.         else
  1461.           Exit;
  1462.  
  1463.         {Get the string space and fill in the items}
  1464.         for Item := MinChoice to MaxChoice do begin
  1465.           S := EdGetMessage(370+Item);
  1466.           if EdMemAvail(Succ(Length(S)), FreeListTemp) then
  1467.             GetMem(Messages^[Item], Succ(Length(S)))
  1468.           else
  1469.             Exit;
  1470.           Messages^[Item]^ := S;
  1471.         end;
  1472.       end;
  1473.       EdBuildMessages := True;
  1474.     end;                     {EdBuildMessages}
  1475.  
  1476.   begin                      {EdChooseAppending}
  1477.  
  1478.     {Initialize the menu}
  1479.     with Menu do begin
  1480.       Xmin := 45;
  1481.       Ymin := 14;
  1482.       MessageNum := 304;
  1483.       PromptNum := 309;
  1484.       MinChoice := 1;
  1485.       MaxChoice := 2;
  1486.       InitChoice := 1;
  1487.       CmdSet := PrtCmdSet;
  1488.       UseLetters := True;
  1489.     end;
  1490.     if not(EdBuildMessages(Menu)) then begin
  1491.       EdErrormsg(35);
  1492.       Exit;
  1493.     end;
  1494.  
  1495.     {Get the menu choice}
  1496.     EdGetCustomMenuChoice(Menu, Choice);
  1497.  
  1498.     if Abortcmd then
  1499.       Choice := 0;
  1500.  
  1501.   end;                       {EdChooseAppending}
  1502.  
  1503.   procedure EdHelpMenu;
  1504.     {-Use a menu to select and display a help section}
  1505.   var
  1506.     Menu : CustomMenuRec;
  1507.     Choice : Integer;
  1508.  
  1509.     function EdBuildMessages(var Menu : CustomMenuRec) : Boolean;
  1510.       {-Build the message table for the menu}
  1511.     var
  1512.       Item : Integer;
  1513.       S : VarString;
  1514.  
  1515.     begin                    {EdBuildMessages}
  1516.       EdBuildMessages := False;
  1517.       with Menu do begin
  1518.         if EdMemAvail(Succ(MaxChoice) shl 2, FreeListTemp) then
  1519.           {Get the pointers}
  1520.           GetMem(Messages, Succ(MaxChoice) shl 2)
  1521.         else
  1522.           Exit;
  1523.  
  1524.         {Get the string space and fill in the items}
  1525.         for Item := MinChoice to MaxChoice do begin
  1526.           S := EdGetMessage(281+Item);
  1527.           if EdMemAvail(Succ(Length(S)), FreeListTemp) then
  1528.             {Get the pointers}
  1529.             GetMem(Messages^[Item], Succ(Length(S)))
  1530.           else
  1531.             Exit;
  1532.           Messages^[Item]^ := S;
  1533.         end;
  1534.       end;
  1535.       EdBuildMessages := True;
  1536.     end;                     {EdBuildMessages}
  1537.  
  1538.   begin                      {EdHelpMenu}
  1539.  
  1540.     if not(HelpAvailable) then begin
  1541.       EdErrormsg(64);
  1542.       Exit;
  1543.     end;
  1544.  
  1545.     {Initialize the menu}
  1546.     with Menu do begin
  1547.       Xmin := 36;
  1548.       Ymin := 7;
  1549.       MessageNum := 304;
  1550.       PromptNum := 324;
  1551.       MinChoice := 1;
  1552.       MaxChoice := 16;
  1553.       InitChoice := 1;
  1554.       CmdSet := PrtCmdSet;
  1555.       UseLetters := False;
  1556.     end;
  1557.  
  1558.     repeat
  1559.  
  1560.       if not(EdBuildMessages(Menu)) then begin
  1561.         EdErrormsg(35);
  1562.         Exit;
  1563.       end;
  1564.  
  1565.       {Get the menu choice}
  1566.       EdGetCustomMenuChoice(Menu, Choice);
  1567.  
  1568.       if not(Abortcmd) then begin
  1569.         EdHelpWindow(CommandType(Ord(CmdHelpMenu)+Choice));
  1570.         EdSetCursor(CursorOff);
  1571.       end;
  1572.     until Abortcmd;
  1573.  
  1574.   end;                       {EdHelpMenu}
  1575.  
  1576.   procedure EdInsertUndoBuffer;
  1577.     {-Insert the entire undo buffer prior to the current line of text}
  1578.  
  1579.   begin                      {EdInsertUndoBuffer}
  1580.     while UndoLimit*UndoCount > 0 do
  1581.       EdUndo;
  1582.   end;                       {EdInsertUndoBuffer}
  1583.  
  1584.   procedure EdFlushUndo;
  1585.     {-Delete the contents of the undo buffer}
  1586.   var
  1587.     P : PlineDesc;
  1588.  
  1589.   begin                      {EdFlushUndo}
  1590.  
  1591.     {If either Undolimit or Undocount = 0, we don't have anything to flush}
  1592.     if UndoLimit*UndoCount = 0 then
  1593.       Exit;
  1594.  
  1595.     while UndoCount > 0 do begin
  1596.       Dec(UndoCount);
  1597.       P := UndoStack;
  1598.       EdFwdPtr(UndoStack);
  1599.       if EdPtrIsNil(UndoStack) then
  1600.         EdSetPtrNil(UndoEnd);
  1601.       EdDesTextDesc(P);
  1602.     end;
  1603.  
  1604.   end;                       {EdFlushUndo}
  1605.  
  1606.   procedure EdJumpLastPosition;
  1607.     {-Move the cursor to its previous position}
  1608.   var
  1609.     W : Pwindesc;
  1610.  
  1611.   begin                      {EdJumpLastPosition}
  1612.     W := EdFindWindow(LastPosition.Line);
  1613.     if EdPtrIsNil(W) then
  1614.       {Last position was deleted}
  1615.       Exit;
  1616.     EdJumpMarker(LastPosition);
  1617.   end;                       {EdJumpLastPosition}
  1618.  
  1619.   procedure EdMoveToBegin;
  1620.     {-Move cursor to prior line with equal indentation to current line}
  1621.   var
  1622.     I : Integer;
  1623.  
  1624.   begin                      {EdMovetobegin}
  1625.     with Curwin^ do begin
  1626.       {Get out if we're already at top of file}
  1627.       if EdPtrIsNil(Curline^.Backlink) then
  1628.         Exit;
  1629.       {Get indent of current line}
  1630.       I := EdLineIndent(Curline);
  1631.       if I = 0 then
  1632.         Exit;
  1633.       {Move up to first prior line with equal indent}
  1634.       repeat
  1635.         EdUpLine;
  1636.       until EdPtrIsNil(Curline^.Backlink) or (EdLineIndent(Curline) = I);
  1637.       Colno := I;
  1638.     end;
  1639.   end;                       {EdMovetobegin}
  1640.  
  1641.   procedure EdMoveToEnd;
  1642.     {-Move cursor to following line with equal indent to current line}
  1643.   var
  1644.     I : Integer;
  1645.  
  1646.   begin                      {EdMovetoend}
  1647.     with Curwin^ do begin
  1648.       if EdPtrIsNil(Curline^.Fwdlink) then
  1649.         Exit;
  1650.       I := EdLineIndent(Curline);
  1651.       if I = 0 then
  1652.         Exit;
  1653.       repeat
  1654.         EdDownLine;
  1655.       until EdPtrIsNil(Curline^.Fwdlink) or (EdLineIndent(Curline) = I);
  1656.       Colno := I;
  1657.     end;
  1658.   end;                       {EdMovetoend}
  1659.  
  1660. end.
  1661.