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

  1. {                            MSMAIN.PAS
  2.                                MS 4.0
  3.                 Copyright (c) 1985, 87 by Borland International, Inc.         }
  4.  
  5. {$I msdirect.inc}
  6.  
  7. unit MsMain;
  8.   {-Top level routines for MicroStar}
  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,                   {Pointer primitives}
  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 edit, error report, help}
  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.   MsText,                    {Text processing commands}
  32.   MsTabs,                    {Tab commands}
  33.   MsBlok,                    {Block move, copy, delete}
  34.   MsFind,                    {Find, replace routines}
  35.   MsFile,                    {File I/O routines}
  36.   MsMacro,                   {Macro editing and processing}
  37.   MsSet,                     {Setup and installation}
  38.   MsPrtM,                    {Print job setup}
  39.   MsSpell,                   {Spelling checker}
  40.   Invoke,                    {General purpose DOS shell}
  41.   MsInvoke;                  {DOS shell specialized for MicroStar}
  42.  
  43. procedure EdInitialize;
  44.   {-Initialize editor variables and data structures}
  45.  
  46. procedure EdMainMenu;
  47.   {-Get command line parameters and set up for initial file}
  48.  
  49. procedure EdSchedule;
  50.   {-Schedule editor}
  51.  
  52.   {==========================================================================}
  53.  
  54. implementation
  55.  
  56. var
  57.   Argcount : Byte;           {Number of DOS command line arguments}
  58.  
  59.   procedure EdProcessMacroChars(CurrentUserChars : Integer);
  60.     forward;
  61.   {-Processes characters pushed in a Find and Macro command}
  62.  
  63.   procedure EdInitialize;
  64.     {-Initialize editor variables and data structures}
  65.   var
  66.     HelpFile : Filepath;     {Pathname to indexed help file}
  67.     MacroFile : Filepath;    {Pathname to default macro file}
  68.     PrtDefFile : Filepath;   {Pathname to default printer definition}
  69.  
  70.     procedure EdInitPromptLine;
  71.       {-Set up the prompt line to display help for the menu system}
  72.     var
  73.       MenuStr : VarString;
  74.       Kptr : Integer;
  75.       Special : Boolean;
  76.  
  77.     begin                    {EdInitPromptLine}
  78.       FillChar(PromptLine[1], PhyScrCols, Blank);
  79.       PromptCol := 1;
  80.       if ShowMenuHelp then begin
  81.         Kptr := 1;
  82.         EdClearString(MenuStr);
  83.         while Kptr <= Length(MenuPrime) do
  84.           MenuStr := MenuStr+EdTextRepresentation(MenuPrime, Kptr, Special);
  85.         MenuStr := MenuStr+EdGetMessage(394);
  86.         MaxPromptChars := Pred(PhyScrCols-Length(MenuStr));
  87.         MenuHelpPos := Succ(PhyScrCols-Length(MenuStr));
  88.         FillChar(HelpPromptLine[1], PhyScrCols, Blank);
  89.         Move(MenuStr[1], HelpPromptLine[MenuHelpPos], Length(MenuStr));
  90.         Move(HelpPromptLine[1], PromptLine[1], PhyScrCols);
  91.       end else
  92.         MaxPromptChars := PhyScrCols;
  93.     end;                     {EdInitPromptLine}
  94.  
  95.     function EdReturnFullPath(Path : Filepath) : Filepath;
  96.       {-Return default directory if path is empty}
  97.  
  98.     begin                    {EdReturnFullPath}
  99.       if Length(Path) = 0 then
  100.         GetDir(0, Path);
  101.       EdReturnFullPath := EdAddTrailingBackslash(Path);
  102.     end;                     {EdReturnFullPath}
  103.  
  104.   begin                      {EdInitialize}
  105.  
  106.     if EdStringEmpty(AddwinPrime) then begin
  107.       {If the add window command is installed as nothing, we can't do much}
  108.       WriteLn;
  109.       WriteLn(EdGetMessage(62));
  110.       Halt(1);
  111.     end;
  112.  
  113.     {Initialize the first window}
  114.     Curwin :=
  115.     EdAllocateWindow
  116.     (LogtopScr,              {Physical top of window}
  117.      LogscrRows,             {Length of window}
  118.      Line1,                  {Initial position in window}
  119.      Col1,                   {Initial position in window}
  120.      NoFile                  {Editing no file}
  121.      );
  122.  
  123.     {Define top and only window}
  124.     Window1 := Curwin;
  125.     Window1^.Fwdlink := Window1;
  126.     Window1^.Backlink := Window1;
  127.  
  128.     {Set initial zoom state}
  129.     Zoomed := False;
  130.     if SaveInitZoomState then
  131.       EdZoomWindow(False);
  132.  
  133.     {Last cursor position}
  134.     LastPosition.Line := Curwin^.TopLine;
  135.     LastPosition.Col := 1;
  136.  
  137.     {Define the support path}
  138.     SupportPath := EdReturnFullPath(SaveSupportPath);
  139.  
  140.     {Build path names for support files}
  141.     HelpFile := SupportPath+ProgName+'.'+HelpFileExt;
  142.     MacroFile := SupportPath+ProgName+'.'+MacroFileExt;
  143.     PrtDefFile := SaveDeviceName;
  144.  
  145.     {See whether help is available}
  146.     HelpAvailable := EdExistFile(HelpFile);
  147.     if HelpAvailable then begin
  148.       {Open help file and leave it open}
  149.       Assign(Helpf, HelpFile);
  150.       Reset(Helpf, 1);
  151.     end;
  152.  
  153.     {Get the default macro file if found}
  154.     if EdExistFile(MacroFile) then
  155.       EdReadMacroFile(MacroFile);
  156.  
  157.     {Initialize printer definition}
  158.     EdPrintSetDefaults(PrtDefFile);
  159.  
  160.     {Initialize the prompt line to show menu help}
  161.     EdInitPromptLine;
  162.  
  163.   end;                       {EdInitialize}
  164.  
  165.   procedure EdMainMenu;
  166.     {-Get command line arguments and determine initial keystrokes of editor}
  167.   var
  168.     CmdString, Arg : String255;
  169.     Fcount : Integer;
  170.  
  171.   begin                      {EdMainMenu}
  172.     if Argcount > 0 then begin
  173.       {Take DOS command line for file names, up to 3 windows}
  174.       EdClearString(CmdString);
  175.       Fcount := 1;
  176.       while (Argcount > 0) and (Fcount <= 3) do begin
  177.         Arg := ParamStr(Fcount);
  178.         CmdString := CmdString+AddwinPrime+Arg+^M;
  179.         if EdHasWildCards(Arg) then begin
  180.           {Display menu system if first parameter had wildcards}
  181.           if Fcount = 1 then
  182.             CmdString := MenuPrime+'FO'+Arg+^M;
  183.           {Stop taking arguments after one containing wildcards}
  184.           Argcount := 1;
  185.         end;
  186.         Inc(Fcount);
  187.         Dec(Argcount);
  188.       end;
  189.       Argcount := 0;
  190.     end else if OpeningMenu then
  191.       {Display menu for File Open}
  192.       CmdString := MenuPrime+'FO'
  193.     else
  194.       {Start up with noname file}
  195.       CmdString := AddwinPrime+^X^M;
  196.  
  197.     {Push commands into keyboard buffer}
  198.     EdUserPush(CmdString);
  199.   end;                       {EdMainMenu}
  200.  
  201.   procedure EdFindReplace(ApplyMacro : Boolean);
  202.     {-Process find and replace command}
  203.   label
  204.     ExitPoint;
  205.   const
  206.     Xmin = 5;
  207.     XSize = 70;
  208.     YSize = 5;
  209.   var
  210.     Ch : Char;
  211.     NotFound, ShowUpdates, NoReplace,
  212.     Done, HaveWindow, CursorState : Boolean;
  213.     Ymin, Count, Fcol : Integer;
  214.     P : PlineDesc;
  215.     M : BlockMarker;
  216.     W : WindowPtr;
  217.     CmdPrompt, Prompt : VarString;
  218.  
  219.     procedure RestoreScreen;
  220.       {-Get rid of the prompt window if appropriate}
  221.  
  222.     begin                    {RestoreScreen}
  223.       if HaveWindow then begin
  224.         {Remove window}
  225.         EdRestoreWindow(W, Xmin, Ymin, XSize, YSize);
  226.         {Restore cursor}
  227.         SolidCursor := CursorState;
  228.         EdSetCursorOff;
  229.         if EdPtrIsNil(CurrMenu) then begin
  230.           EdShowMenuHelp;
  231.           EdUpdateCursor;
  232.         end;
  233.       end;
  234.     end;                     {RestoreScreen}
  235.  
  236.     procedure EdReplacestring(StartCol : Integer);
  237.       {-Perform string replacement}
  238.     var
  239.       EndOfSearch, EndOfReplace : Integer;
  240.       LenDiff : Integer;
  241.  
  242.     begin                    {EdReplacestring}
  243.       with Curwin^ do begin
  244.  
  245.         Modified := True;
  246.         EndOfSearch := StartCol+Length(SearchStr);
  247.         EndOfReplace := StartCol+Length(ReplaceStr);
  248.         LenDiff := Length(ReplaceStr)-Length(SearchStr);
  249.  
  250.         if LenDiff < 0 then begin
  251.           {Line getting shorter}
  252.           with Curline^ do begin
  253.             Move(Txt^[EndOfSearch], Txt^[EndOfReplace], Succ(Bufflen-EndOfSearch));
  254.             FillChar(Txt^[Succ(Bufflen)+LenDiff], -LenDiff, Blank);
  255.           end;
  256.           {Fix up markers}
  257.           EdFixBlockInsertedSpace(Curline, StartCol, LenDiff);
  258.           EdCheckNoMarker;
  259.           EdFixMarkInsertedSpace(Curline, StartCol, LenDiff);
  260.  
  261.         end else if LenDiff > 0 then begin
  262.           {Line getting longer}
  263.           if not EdSizeline(Curline, Curline^.Bufflen+LenDiff, True) then begin
  264.             EdErrormsg(35);
  265.             {Stop searching}
  266.             Done := True;
  267.             Exit;
  268.           end;
  269.           with Curline^ do
  270.             Move(Txt^[EndOfSearch], Txt^[EndOfReplace], Succ(Bufflen-EndOfReplace));
  271.           {Fix up markers}
  272.           EdFixBlockInsertedSpace(Curline, StartCol, LenDiff);
  273.           EdFixMarkInsertedSpace(Curline, StartCol, LenDiff);
  274.  
  275.         end;
  276.  
  277.         Move(ReplaceStr[1], Curline^.Txt^[StartCol], Length(ReplaceStr));
  278.         EdResetPageLine(Curwin);
  279.       end;
  280.     end;                     {EdReplacestring}
  281.  
  282.     procedure EdModifyString(StartCol : Integer);
  283.       {-Select between replace and macro application}
  284.     var
  285.       CurrentUserChars : Integer;
  286.       LfindUpper : Boolean;
  287.       LfindBackward : Boolean;
  288.       LfindWholeWord : Boolean;
  289.       Lpreview : Boolean;
  290.       Lglobal : Boolean;
  291.       LblockFind : Boolean;
  292.       LsearchStr : VarString;
  293.  
  294.     begin                    {EdModifyString}
  295.       case LastSearchOp of
  296.         Replace :
  297.           EdReplacestring(StartCol);
  298.  
  299.         RunMacro :
  300.           begin
  301.  
  302.             {Store number of characters already pushed (nested macros)}
  303.             CurrentUserChars := EditUsercommandInput;
  304.  
  305.             {Store global search parameters in case changed by macro}
  306.             LsearchStr := SearchStr;
  307.             LfindUpper := Findupper;
  308.             LfindBackward := Findbackward;
  309.             LfindWholeWord := Findwholeword;
  310.             Lpreview := Preview;
  311.             Lglobal := Global;
  312.             LblockFind := Blockfind;
  313.  
  314.             {Push macro onto typeahead buffer}
  315.             EdInsertMacro(Macronum, 1);
  316.  
  317.             {Process characters}
  318.             {Special handler to avoid problems if a macro calls EdFind}
  319.             Recurring := True;
  320.             EdProcessMacroChars(CurrentUserChars);
  321.             Recurring := False;
  322.  
  323.             {Restore search parameters}
  324.             SearchStr := LsearchStr;
  325.             Findupper := LfindUpper;
  326.             Findbackward := LfindBackward;
  327.             Findwholeword := LfindWholeWord;
  328.             Preview := Lpreview;
  329.             Global := Lglobal;
  330.             Blockfind := LblockFind;
  331.             LastSearchOp := RunMacro;
  332.  
  333.             {Guarantee abort checking is active again}
  334.             AbortEnable := True;
  335.           end;
  336.       end;
  337.     end;                     {EdModifyString}
  338.  
  339.     procedure EdAdjustEOLmatch;
  340.       {-Adjust replace string when searching for ^M^J}
  341.     var
  342.       EolPos : Integer;
  343.  
  344.     begin                    {EdAdjustEOLmatch}
  345.       EolPos := Pos(^M^J, SearchStr);
  346.       if (Length(ReplaceStr) > 1) and (EolPos = Pred(Length(SearchStr))) then begin
  347.         EolPos := Pos(^M^J, ReplaceStr);
  348.         if EolPos = Pred(Length(ReplaceStr)) then
  349.           {Truncate ^M^J from replace string}
  350.           ReplaceStr := Copy(ReplaceStr, 1, Length(ReplaceStr)-2);
  351.       end;
  352.     end;                     {EdAdjustEOLmatch}
  353.  
  354.   begin                      {EdFindReplace}
  355.  
  356.     {Protect against recursive find-and-macro calls}
  357.     if Recurring then begin
  358.       EdErrormsg(73);
  359.       Exit;
  360.     end;
  361.  
  362.     AbortEnable := True;
  363.     LastSearchOp := None;
  364.  
  365.     if PromptForInput and (EditUsercommandInput = 0) then begin
  366.       {Set up a prompt box}
  367.       EdEraseMenuHelp;
  368.       EdUpdateCmdLine;
  369.       HaveWindow := True;
  370.       with Curwin^ do
  371.         Ymin := (Firstlineno+Lastlineno) shr 1;
  372.       if Ymin > 20 then
  373.         Ymin := 20;
  374.       if EdPtrNotNil(CurrMenu) then
  375.         if Ymin < 10 then
  376.           Ymin := 10;
  377.       if ApplyMacro then
  378.         if Ymin > 10 then
  379.           Ymin := 10;
  380.       W := EdSetupWindow(Border, Xmin, Ymin, Pred(Xmin+XSize), Pred(Ymin+YSize), NormalBox);
  381.       CursorState := SolidCursor;
  382.       SolidCursor := False;
  383.     end else
  384.       HaveWindow := False;
  385.  
  386.     if PromptForInput then begin
  387.       if HaveWindow then begin
  388.         {Display the prompt}
  389.         Prompt := EdGetMessage(323);
  390.         EdFastWrite(Prompt, Ymin, Xmin+(XSize-Length(Prompt)) shr 1, ScreenAttr[MfColor]);
  391.       end;
  392.       EdGetSearchString(Xmin, Succ(Ymin), XSize, XSize-3, HaveWindow, SearchStr);
  393.     end;
  394.     if Abortcmd or EdStringEmpty(SearchStr) then begin
  395.       RestoreScreen;
  396.       Exit;
  397.     end;
  398.  
  399.     if ApplyMacro then begin
  400.  
  401.       {Find out which macro to use}
  402.       if PromptForInput then begin
  403.         if HaveWindow then begin
  404.           {Display the prompt}
  405.           Prompt := EdGetMessage(315);
  406.           EdFastWrite(Prompt, Ymin, Xmin+(XSize-Length(Prompt)) shr 1, ScreenAttr[MfColor]);
  407.         end;
  408.         EdGetMacroNumber(304, Macronum);
  409.       end;
  410.       if Abortcmd or not(Macronum in [0..MaxMacro]) then begin
  411.         RestoreScreen;
  412.         Exit;
  413.       end;
  414.       if HaveWindow then
  415.         if EdPtrNotNil(Macronames[Macronum]) then
  416.           EdFastWrite(Macronames[Macronum]^, Ymin+2, Succ(Xmin), ScreenAttr[MnColor]);
  417.       EdClearString(ReplaceStr);
  418.       CmdPrompt := EdGetMessage(330);
  419.       LastSearchOp := RunMacro;
  420.  
  421.     end else begin
  422.  
  423.       if PromptForInput then begin
  424.         if HaveWindow then begin
  425.           {Redraw border}
  426.           EdDrawBox(Border, Xmin, Ymin, XSize, 5, NormalBox);
  427.           {Display the prompt}
  428.           Prompt := EdGetMessage(338);
  429.           EdFastWrite(Prompt, Ymin, Xmin+(XSize-Length(Prompt)) shr 1, ScreenAttr[MfColor]);
  430.         end;
  431.         EdGetSearchString(Xmin, Ymin+2, XSize, XSize-3, HaveWindow, ReplaceStr);
  432.       end;
  433.       if Abortcmd then begin
  434.         RestoreScreen;
  435.         Exit;
  436.       end;
  437.  
  438.       {Set up command prompt}
  439.       CmdPrompt := EdGetMessage(339);
  440.       LastSearchOp := Replace;
  441.  
  442.     end;
  443.  
  444.     {Ask for options}
  445.     if HaveWindow then begin
  446.       {Redraw border}
  447.       EdDrawBox(Border, Xmin, Ymin, XSize, 5, NormalBox);
  448.       {Draw new prompt}
  449.       Prompt := EdGetMessage(337);
  450.       EdFastWrite(Prompt, Ymin, Xmin+(XSize-Length(Prompt)) shr 1, ScreenAttr[MfColor]);
  451.     end;
  452.     EdGetOptions(Xmin, Ymin+3, XSize, 6, HaveWindow);
  453.     Count := FindCount;
  454.  
  455.     {Get rid of prompt box}
  456.     RestoreScreen;
  457.  
  458.     if Abortcmd or Goterror then
  459.       Exit;
  460.  
  461.     if Blockfind then begin
  462.       EdBlockInit;
  463.       if Goterror then
  464.         Exit;
  465.     end else if Global then
  466.       EdGlobalInit;
  467.  
  468.     {Adjust for end of line searches}
  469.     EdAdjustEOLmatch;
  470.  
  471.     {Search for the pattern}
  472.     NotFound := True;
  473.     ShowUpdates := True;
  474.     Done := False;
  475.     {Set cursor to proper start position to avoid repeated finds}
  476.     Fcol := EdSetStartCol(Curwin^.Colno);
  477.  
  478.     with Curwin^ do
  479.       repeat
  480.  
  481.         if ShowUpdates then begin
  482.           EdWritePromptLine(EdGetMessage(326));
  483.           {Update entire screen at least once}
  484.           EdUpdateScreen;
  485.           {Show further updates only if previewing}
  486.           ShowUpdates := Preview;
  487.         end else if not(EdKeyInterrupt) then
  488.           {Update the prompt line only if no keys are pending}
  489.           EdWritePromptLine(EdGetMessage(327));
  490.  
  491.         {Find the next match}
  492.         P := EdScanpattern(Curline, SearchStr, Fcol);
  493.  
  494.         if Abortcmd then
  495.           goto ExitPoint;
  496.  
  497.         if EdPtrIsNil(P) then
  498.  
  499.           {No match, force exit}
  500.           Done := True
  501.  
  502.         else begin
  503.  
  504.           {Found at least one occurrence of the pattern}
  505.           NotFound := False;
  506.  
  507.           {Move cursor to the position found}
  508.           M.Line := P;
  509.           if PositionFindAtStart or Findbackward then
  510.             M.Col := Fcol
  511.           else
  512.             M.Col := Fcol+Length(SearchStr);
  513.           EdJumpMarker(M);
  514.  
  515.           {Assume the replacement will be done}
  516.           NoReplace := False;
  517.  
  518.           {Optional preview before replacement}
  519.           if Preview then begin
  520.             EdWritePromptLine('');
  521.             {Show the found string clearly}
  522.             EdHighlightScreen(Fcol, Pred(Fcol+Length(SearchStr)), ScreenAttr[BordColor], False);
  523.             with Curwin^ do
  524.               if Firsttextno+Lineno < 5 then
  525.                 Ymin := Succ(Firsttextno+Lineno)
  526.               else
  527.                 Ymin := Firsttextno+Lineno-4;
  528.             {Prompt for action}
  529.             EdDisplayPromptWindow(CmdPrompt+EdGetMessage(329), Ymin,
  530.                                   [^Y, ^N, ^A, ^Q], Ch, NormalBox);
  531.             if Abortcmd then
  532.               goto ExitPoint;
  533.  
  534.             case Ch of
  535.               ^Y :
  536.                 EdModifyString(Fcol);
  537.  
  538.               ^N :
  539.                 {Flag that replacement was not done}
  540.                 NoReplace := True;
  541.  
  542.               ^A :
  543.                 begin
  544.                   {Modify string and do the rest without asking}
  545.                   EdModifyString(Fcol);
  546.                   Preview := False;
  547.                 end;
  548.  
  549.               ^Q :
  550.                 begin
  551.                   Done := True;
  552.                   NoReplace := True;
  553.                 end;
  554.             end;
  555.  
  556.           end else
  557.             {Modify without asking}
  558.             EdModifyString(Fcol);
  559.  
  560.           if not(Done or Blockfind or Global) then begin
  561.             Dec(Count);
  562.             if Count <= 0 then
  563.               Done := True;
  564.           end;
  565.  
  566.           if Done then begin
  567.             {Move the cursor past the last string found or replaced}
  568.             if not(ApplyMacro or Findbackward or PositionFindAtStart) then begin
  569.               if NoReplace then
  570.                 Colno := Fcol+Length(SearchStr)
  571.               else
  572.                 Colno := Fcol+Length(ReplaceStr);
  573.             end;
  574.           end else begin
  575.             {Proceed to the next instance}
  576.             if Findbackward then begin
  577.               Dec(Colno);
  578.               if Colno < Length(SearchStr) then
  579.                 {No hope of further matches on this line}
  580.                 if EdPtrIsNil(Curline^.Backlink) then
  581.                   {Force exit}
  582.                   Done := True
  583.                 else begin
  584.                   EdUpLine;
  585.                   EdRightLine;
  586.                 end;
  587.             end else begin
  588.               {Advance over the replace string to prevent left recursive search/replace}
  589.               if not(ApplyMacro) then
  590.                 if NoReplace and EdStringEmpty(ReplaceStr) then
  591.                   {Don't get stuck in place}
  592.                   Colno := Succ(Fcol)
  593.                 else
  594.                   Colno := Fcol+Length(ReplaceStr);
  595.               if Colno+Length(SearchStr) > Curline^.Bufflen then
  596.                 {No hope of further matches on this line}
  597.                 if EdPtrIsNil(Curline^.Fwdlink) then begin
  598.                   {Force exit}
  599.                   Done := True;
  600.                   EdRightLine;
  601.                 end else begin
  602.                   EdDownLine;
  603.                   Colno := 1;
  604.                 end;
  605.             end;
  606.             if Blockfind then
  607.               if not(EdCursorInBlock(Curline, Colno, True)) then
  608.                 {Cursor moved outside of block - force exit}
  609.                 Done := True;
  610.             {Set "find" column for next pass}
  611.             Fcol := Colno;
  612.           end;
  613.         end;
  614.  
  615.       until Done;
  616.  
  617.     if NotFound then
  618.       {Pattern not found}
  619.       EdErrormsg(38);
  620.  
  621. ExitPoint:
  622.     ExitMenu := True;
  623.     EdRealign;
  624.  
  625.   end;                       {EdFindReplace}
  626.  
  627.   procedure EdSaveFile;
  628.     {-Save file and return to same position for further editing}
  629.   var
  630.     C : BlockMarker;
  631.  
  632.   begin                      {EdSaveFile}
  633.     with Curwin^, C do begin
  634.       Line := Curline;
  635.       Col := Colno;
  636.       if Filename = NoFile then begin
  637.         if EdWriteNamedFile then
  638.           ;
  639.       end else
  640.         EdFileWrite(Filename, False);
  641.     end;
  642.     EdJumpMarker(C);
  643.   end;                       {EdSaveFile}
  644.  
  645.   procedure EdSaveQuit;
  646.     {-Save file and leave editor if all windows are closed}
  647.  
  648.   begin                      {EdSaveQuit}
  649.     repeat
  650.       with Curwin^ do begin
  651.         if Modified then begin
  652.           {Only save if modified}
  653.           if Filename = NoFile then begin
  654.             {Get a filename before writing}
  655.             if not(EdWriteNamedFile) then
  656.               exit;
  657.           end else
  658.             EdFileWrite(Filename, (WindowCount = 1));
  659.           if Goterror then
  660.             Exit;
  661.         end;
  662.         EdShutWindow(True);
  663.         if WindowCount >= 1 then
  664.           {Give some visual feedback while saving multiple files}
  665.           EdUpdateScreen;
  666.       end;
  667.     until WindowCount < 1;
  668.   end;                       {EdSaveQuit}
  669.  
  670.   procedure EdAbandonAllFiles;
  671.     {-Abandon all open windows and exit to DOS}
  672.  
  673.   begin                      {EdAbandonAllFiles}
  674.     repeat
  675.       EdAbandonFile(True);
  676.       if AbortCmd then
  677.         exit;
  678.       if WindowCount >= 1 then
  679.         EdUpdateScreen;
  680.     until WindowCount < 1;
  681.   end;                       {EdAbandonAllFiles}
  682.  
  683.   procedure EdFindNext;
  684.     {-Process find next command}
  685.  
  686.   begin                      {EdFindNext}
  687.     PromptForInput := False;
  688.     case LastSearchOp of
  689.       Find : EdFind;
  690.       Replace : EdFindReplace(False);
  691.       RunMacro : EdFindReplace(True);
  692.     end;
  693.     PromptForInput := True;
  694.   end;                       {EdFindNext}
  695.  
  696.   procedure EdNewFile;
  697.     {-Read a new file into an existing window}
  698.   var
  699.     Fname : Filepath;
  700.  
  701.   begin                      {EdNewFile}
  702.  
  703.     {See if current window is modified, and if so, prompt to save it}
  704.     if not CheckCurwinModified then
  705.       exit;
  706.  
  707.     if WindowCount > 0 then
  708.       if EdLinkedWindow(Curwin) then begin
  709.         {Create a new text stream for the window}
  710.         if not(EdNewTextStream(Curwin)) then
  711.           Exit;
  712.         Curwin^.Filename := NoFile;
  713.       end else begin
  714.         {Clearing the text stream from memory may take a while}
  715.         EdWait;
  716.         EdDeleteAllText(Curwin);
  717.         EdResetWindow(Curwin);
  718.       end;
  719.  
  720.     if WindowCount <= 1 then
  721.       {No files currently open, indicate by blank screen}
  722.       ClrScr
  723.     else
  724.       EdUpdateScreen;
  725.  
  726.     repeat
  727.       Abortcmd := False;
  728.       Goterror := False;
  729.       {Read the new file into memory}
  730.       Fname := EdGetFileName(EdGetMessage(320), DefExtension, EdYcenterWindow(3), 0, LastFileEdit, True);
  731.       if Abortcmd then begin
  732.         {Shut the window or enter the menu system}
  733.         Abortcmd := False;
  734.         Goterror := False;
  735.         EdShutWindow(False);
  736.       end else if not(Goterror) then
  737.         EdReadFile(Fname);
  738.     until not(Goterror);
  739.  
  740.   end;                       {EdNewFile}
  741.  
  742.   procedure EdAddWindow;
  743.     {-Add a text window, get a file for it, read it in, and move to it}
  744.   label
  745.     ExitPoint;
  746.   var
  747.     WindToDivide : Integer;
  748.     Rezoom : Boolean;
  749.  
  750.   begin                      {EdAddWindow}
  751.  
  752.     {Add a window only if allowed}
  753.     if (WindowCount >= MaxWindows) then begin
  754.       EdErrormsg(127);
  755.       Exit;
  756.     end;
  757.  
  758.     {Undo zoom if currently on}
  759.     Rezoom := Zoomed;
  760.     if Rezoom then
  761.       EdZoomWindow(False);
  762.  
  763.     if WindowCount > 0 then begin
  764.       {Get most likely window to divide into two}
  765.       WindToDivide := EdGetWindowToDivide;
  766.  
  767.       {Divide window if possible}
  768.       EdWindowCreate(WindToDivide);
  769.       if Goterror then
  770.         {Could not create window, message already displayed}
  771.         goto ExitPoint;
  772.  
  773.       {Move to new window}
  774.       EdWindowGoto(Succ(WindToDivide));
  775.     end;
  776.  
  777.     {Read the new file into memory}
  778.     EdReadFile(EdGetFileName(EdGetMessage(320), DefExtension, EdYcenterWindow(3), 0, LastFileEdit, True));
  779.  
  780.     if Goterror then begin
  781.       if WindowCount > 0 then begin
  782.         {Didn't get file, remove window just created}
  783.         EdWindowGoto(WindToDivide);
  784.         EdWindowDelete(Succ(WindToDivide));
  785.         ExitMenu := True;
  786.       end else begin
  787.         {Clear any text from first window, stay in menu system}
  788.         EdDeleteAllText(Curwin);
  789.         EdResetWindow(Curwin);
  790.         ExitMenu := False;
  791.       end;
  792.     end else begin
  793.       Inc(WindowCount);
  794.       ExitMenu := True;
  795.     end;
  796.  
  797. ExitPoint:
  798.     {Redo zoom if we started that way}
  799.     if Rezoom then
  800.       EdZoomWindow(False);
  801.  
  802.   end;                       {EdAddwindow}
  803.  
  804.   procedure EdSaveAndNewFile;
  805.     {-Save current file and prompt for a new one in the same window}
  806.   var
  807.     Fname : Filepath;
  808.  
  809.   begin                      {EdSaveAndNewFile}
  810.  
  811.     {Save the file}
  812.     with Curwin^ do begin
  813.       if Filename = NoFile then begin
  814.         {Get a filename and save stream to it}
  815.         if not(EdWriteNamedFile) then
  816.           Exit;
  817.       end else
  818.         EdFileWrite(Filename, False);
  819.       if Goterror then
  820.         Exit;
  821.     end;
  822.  
  823.     {Clear the window for a new file}
  824.     if EdLinkedWindow(Curwin) then begin
  825.       {Create a new text stream for the window}
  826.       if not(EdNewTextStream(Curwin)) then
  827.         Exit;
  828.       Curwin^.Filename := NoFile;
  829.     end else begin
  830.       {Clearing the text stream from memory may take a while}
  831.       EdWait;
  832.       EdDeleteAllText(Curwin);
  833.       EdResetWindow(Curwin);
  834.     end;
  835.     if WindowCount <= 1 then
  836.       {No files currently open, indicate by blank screen}
  837.       ClrScr
  838.     else
  839.       EdUpdateScreen;
  840.  
  841.     {Get a new file}
  842.     repeat
  843.       {Reset from previous errors}
  844.       Abortcmd := False;
  845.       Goterror := False;
  846.       {Read the new file into memory}
  847.       Fname := EdGetFileName(EdGetMessage(320), DefExtension, EdYcenterWindow(3), 0, LastFileEdit, True);
  848.       if Abortcmd then begin
  849.         {Shut the window or enter the menu system}
  850.         Abortcmd := False;
  851.         Goterror := False;
  852.         EdShutWindow(False);
  853.       end else if not(Goterror) then
  854.         EdReadFile(Fname);
  855.     until not(Goterror);
  856.  
  857.   end;                       {EdSaveAndNewFile}
  858.  
  859.   procedure EdWriteOrAppendBlock;
  860.     {-If a block is marked, write or append it to a file}
  861.   var
  862.     Fname : Filepath;
  863.     Exists, Appending : Boolean;
  864.     WhichItem : Integer;
  865.  
  866.   begin                      {EdWriteOrAppendBlock}
  867.  
  868.     {Make sure a block is marked}
  869.     if EdNoBlock then begin
  870.       EdErrormsg(26);
  871.       Exit;
  872.     end;
  873.  
  874.     {Get a file name to write to}
  875.     Fname := EdGetFileName(EdGetMessage(310), DefExtension, EdYcenterWindow(3), 0, LastBlockWrite, False);
  876.     if Abortcmd or EdStringEmpty(Fname) then
  877.       Exit;
  878.  
  879.     {See if file already exists}
  880.     Exists := EdExistFile(Fname);
  881.     if Goterror then
  882.       Exit;
  883.  
  884.     if Exists then begin
  885.  
  886.       {Return 0=Abort, 1=Append, 2=Overwrite}
  887.       EdChooseAppending(WhichItem);
  888.  
  889.       if Abortcmd or (WhichItem = 0) then
  890.         Exit;
  891.  
  892.       Appending := (WhichItem = 1);
  893.       if not(Appending) then begin
  894.         {Create a .BAK file}
  895.         EdMakeBakFile(Fname);
  896.         if Goterror then
  897.           Exit;
  898.       end;
  899.  
  900.     end else
  901.       Appending := False;
  902.  
  903.     {Write the block}
  904.     EdWriteBlock(Fname, Exists, Appending);
  905.  
  906.   end;                       {EdWriteOrAppendBlock}
  907.  
  908.   procedure EdPromptLogDrive;
  909.     {-Prompt for and move to new directory}
  910.   var
  911.     CurDir : Filepath;
  912.  
  913.   begin                      {EdPromptLogDrive}
  914.     {Current directory is default}
  915.     GetDir(0, CurDir);
  916.     EdLogDrive(EdGetFileName(EdGetMessage(317), '', EdYcenterWindow(3), 16, CurDir, False));
  917.   end;                       {EdPromptLogDrive}
  918.  
  919.   procedure EdPrintFile;
  920.     {-Initialize for printing, or abort current print}
  921.  
  922.   begin                      {EdPrintFile}
  923.     if Printing then begin
  924.       {Should printing be stopped?}
  925.       if EdYesNo(EdGetMessage(388)) then
  926.         EdPrintExit;
  927.     end else if EdPrintSetup then begin
  928.       {Initialize the print job}
  929.       EdInitPrintState;
  930.       {Start printing if no error during initialization}
  931.       Printing := not(Goterror);
  932.     end;
  933.   end;                       {EdPrintFile}
  934.  
  935.   procedure EdProcessCommand(C : CommandType);
  936.     {-Top level dispatcher for all editor commands}
  937.   var
  938.     Lastline : PlineDesc;
  939.     Lastcol : Integer;
  940.  
  941.     procedure EdCursorCommands(C : CommandType);
  942.       {-Dispatcher for cursor movement commands}
  943.  
  944.     begin                    {EdCursorCommands}
  945.       case C of
  946.         CmdLeftChar : EdLeftChar; {Left character}
  947.         CmdRightChar : EdRightChar; {Right character}
  948.         CmdLeftWord : EdLeftWord; {Left lexeme}
  949.         CmdRightWord : EdRightWord; {Right lexeme}
  950.         CmdUpLine :          {Up line}
  951.           begin
  952.             EdUpLine;
  953.             FullScroll := FullScroll+TempScroll;
  954.           end;
  955.         CmdDownLine :        {Down line}
  956.           begin
  957.             EdDownLine;
  958.             FullScroll := FullScroll+TempScroll;
  959.           end;
  960.         CmdScrollUp : EdScrollUp; {Scroll up}
  961.         CmdScrollDown : EdScrollDown; {Scroll down}
  962.         CmdDownPage : EdDownPage; {Down page}
  963.         CmdUpPage : EdUpPage; {Up page}
  964.       end;
  965.     end;                     {EdCursorCommands}
  966.  
  967.     procedure EdQuickCommands(C : CommandType);
  968.       {-Dispatcher for quick movement commands}
  969.  
  970.     begin                    {EdQuickCommands}
  971.       case C of
  972.         CmdWindowTopFile : EdWindowTopFile; {Top of window}
  973.         CmdWindowBottomFile : EdWindowBottomFile; {Bottom of window}
  974.         CmdLeftLine : EdLeftLine; {Cursor to left side}
  975.         CmdRightLine : EdRightLine; {Cursor to right side}
  976.         CmdTopScreen : EdTopScreen; {Top of screen}
  977.         CmdBottomScreen : EdBottomScreen; {Bottom of screen}
  978.         CmdMoveToBegin : EdMoveToBegin; {Move to previous BEGIN line}
  979.         CmdMoveToEnd : EdMoveToEnd; {Move to previous END line}
  980.         CmdCpgotoln : EdPromptGotoLine; {Goto line n}
  981.         CmdGotoColumn : EdPromptGotoCol; {Goto column n}
  982.         CmdGotoWindow : EdPromptGotoWindow; {Goto window n}
  983.         CmdJumpLastPosition : EdJumpLastPosition; {Previous cursor position}
  984.       end;
  985.     end;                     {EdQuickCommands}
  986.  
  987.     procedure EdDeleteCommands(C : CommandType);
  988.       {-Dispatcher for commands which delete or insert text}
  989.  
  990.     begin                    {EdDeleteCommands}
  991.       case C of
  992.         CmdUndo : EdUndo;    {Undo last deletion}
  993.         CmdRestoreCurrentLine : EdRestoreCurrentLine; {Restore line as on entry}
  994.         CmdTab : EdTab;      {Tab}
  995.         CmdInsertCtrlChar : EdInsertCtrlChar; {Insert control character into text}
  996.         CmdNewLine : EdNewLine; {New line in text buffer}
  997.         CmdInsertLine : EdInsertLine; {Insert line}
  998.         CmdDeleteRightChar : EdDeleteRightChar; {Delete current character}
  999.         CmdDeleteLeftChar : EdDeleteLeftChar; {Delete left character}
  1000.         CmdDeleteRightWord : EdDeleteRightWord; {Delete right lexeme}
  1001.         CmdDeleteLineRight : EdDeleteLineRight; {Delete line right}
  1002.         CmdDeleteLine : EdDeleteLine; {Delete line}
  1003.         CmdDelLineNoRecourse : EdDeleteLineNoRecourse;
  1004.       end;
  1005.  
  1006.       {All of these commands may affect pagination}
  1007.       EdResetPageLine(Curwin);
  1008.  
  1009.     end;                     {EdDeleteCommands}
  1010.  
  1011.     procedure EdFileCommands(C : CommandType);
  1012.       {-Dispatcher for commands which read and write files}
  1013.  
  1014.     begin                    {EdFileCommands}
  1015.       case C of
  1016.         CmdFind : EdFind;    {Find pattern}
  1017.         CmdFindReplace : EdFindReplace(False); {Find and replace}
  1018.         CmdFindAndMacro : EdFindReplace(True); {Search and apply macro at position}
  1019.         CmdFindNext : EdFindNext; {Find next}
  1020.         CmdInvokeDOS : EdInvokeDOS; {Invoke a DOS shell}
  1021.         CmdBackTab : EdBackTab; {Backwards tab}
  1022.         CmdNewFile : EdNewFile; {Edit a new file in current window}
  1023.         CmdAbandonFile : EdAbandonAllFiles;  {Abandon all open files}
  1024.         CmdReadBlock :       {Read file into window}
  1025.           EdReadtextfile(EdGetFileName(EdGetMessage(321), DefExtension,
  1026.                          EdYcenterWindow(3), 0, LastBlockRead, True),
  1027.                          True);
  1028.         CmdSaveFile : EdSaveFile; {Save file}
  1029.         CmdWriteBlock : EdWriteOrAppendBlock; {Write marked block to file}
  1030.         CmdSaveQuit : EdSaveQuit; {Save file and exit}
  1031.       end;
  1032.     end;                     {EdFileCommands}
  1033.  
  1034.     procedure EdWindowCommands(C : CommandType);
  1035.       {-Dispatcher for commands which manipulate windows}
  1036.  
  1037.     begin                    {EdWindowCommands}
  1038.       case C of
  1039.         CmdAddWindow : EdAddWindow; {Add another window}
  1040.         CmdSizeWindow : EdSizeWindow; {Size current window}
  1041.         CmdDoneFile : EdSaveAndNewFile; {Save and get another file in the window}
  1042.         CmdWindowDown : EdWindowDown; {Switch windows}
  1043.         CmdZoomWindow : EdZoomWindow(True); {Current window fills screen}
  1044.         CmdHelpSummary : EdHelpWindow(CmdHelpHelp); {Write a help summary}
  1045.       end;
  1046.     end;                     {EdWindowCommands}
  1047.  
  1048.     procedure EdBlockCommands(C : CommandType);
  1049.       {-Dispatcher for block operations and markers}
  1050.  
  1051.     begin                    {EdBlockCommands}
  1052.       case C of
  1053.         CmdBlockBegin : EdBlockBegin; {Begin block}
  1054.         CmdBlockEnd : EdBlockEnd; {End block}
  1055.         CmdJumpTopOfBlock : EdJumpMarker(Blockfrom); {Top of block}
  1056.         CmdJumpBottomBlock : EdJumpMarker(Blockto); {Bottom of block}
  1057.         CmdBlockCopy : EdBlockCopy; {Copy block}
  1058.         CmdBlockMove : EdBlockMove; {Move block}
  1059.         CmdBlockDelete : EdBlockDelete; {Delete block}
  1060.         CmdBlockHide : EdBlockHide; {Hide/display toggle block}
  1061.         CmdBlockWord : EdBlockWord; {Mark current word as block}
  1062.         CmdToggleTextMarker : EdToggleTextMarker; {Toggle text marker display}
  1063.         CmdSetMarker0..CmdSetMarker9 :
  1064.           EdSetMarker(Ord(C)-Ord(CmdSetMarker0)); {Set marker}
  1065.         CmdJumpMarker0..CmdJumpMarker9 :
  1066.           EdJumpMarker(Marker[Ord(C)-Ord(CmdJumpMarker0)]); {Jump marker}
  1067.       end;
  1068.  
  1069.       {Assure that current line buffer is updated}
  1070.       Blockop := True;
  1071.     end;                     {EdBlockCommands}
  1072.  
  1073.     procedure EdMacroCommands(C : CommandType);
  1074.       {-Dispatcher for commands which manipulate and insert macros}
  1075.     var
  1076.       Junk : Filepath;
  1077.  
  1078.     begin                    {EdMacroCommands}
  1079.       case C of
  1080.         CmdReadMacroFile :
  1081.           begin
  1082.             {Load a set of macros from disk}
  1083.             Junk := '*.'+MacroFileExt;
  1084.             EdReadMacroFile(
  1085.               EdGetFileName(EdGetMessage(307), MacroFileExt, EdYcenterWindow(3), 0, Junk, True));
  1086.           end;
  1087.         CmdWriteMacroFile :
  1088.           begin
  1089.             {Write current macros to disk}
  1090.             EdClearString(Junk);
  1091.             EdWriteMacroFile(
  1092.                              EdGetFileName(EdGetMessage(308), MacroFileExt, EdYcenterWindow(3), 0, Junk, False));
  1093.           end;
  1094.         CmdToggleMacroRecord : EdToggleMacroRecord; {Toggle macro record}
  1095.         CmdInsertScrapPrompted : EdInsertMacro(0, 0); {Insert scrap macro n times (prompted)}
  1096.         CmdInsertScrap1..CmdInsertScrap9 : {Insert scrap macro 1..9 times}
  1097.           EdInsertMacro(0, Succ(Ord(C)-Ord(CmdInsertScrap1)));
  1098.         CmdInsertMacro1..CmdInsertMacro9 : {Insert Macro n once}
  1099.           EdInsertMacro(Succ(Ord(C)-Ord(CmdInsertMacro1)), 1);
  1100.       end;
  1101.     end;                     {EdMacroCommands}
  1102.  
  1103.     procedure EdTextCommands(C : CommandType);
  1104.       {-Dispatcher for commands which perform word processing functions}
  1105.  
  1106.     begin                    {EdTextCommands}
  1107.       case C of
  1108.         CmdSysInfo : EdSysInfo; {Show info about system and editor}
  1109.         CmdShowMem : EdShowMemory; {Show available memory}
  1110.         CmdToggleInsert : EdToggleBoolean(Curwin^.Insertflag); {Toggle insert mode}
  1111.         CmdToggleAutoindent : EdToggleBoolean(Curwin^.AI); {Toggle autoindent mode}
  1112.         CmdToggleCase : EdChangeCase(Toggle); {Toggle case of character(s)}
  1113.         CmdLowerCase : EdChangeCase(ToLower); {Lower case character(s)}
  1114.         CmdUpperCase : EdChangeCase(ToUpper); {Upper case character(s)}
  1115.         CmdSetRightMargin : EdSetRightMargin; {Set a new right margin}
  1116.         CmdReformParagraph : EdReformParagraph; {Reformat a single paragraph}
  1117.         CmdToggleWordWrap : EdToggleWordWrap; {Toggle the state of word wrap}
  1118.         CmdSetLeftMargin : EdSetLeftMargin; {Set a new left margin}
  1119.         CmdToggleTabLine : EdToggleTabLine; {Toggle display of the tab line}
  1120.         CmdInsertUndoBuffer : EdInsertUndoBuffer; {Insert the undo buffer into the text}
  1121.         CmdToggleJustify : EdToggleJustify; {Toggle state of right justification}
  1122.         CmdTogglePaginate : EdTogglePaginate; {Toggle Pagination display}
  1123.         CmdToggleAttribute : EdToggleBoolean(Curwin^.AT); {Toggle on-screen attribute display}
  1124.         CmdCenterLine : EdCenterLine; {Center the current line in margins}
  1125.         CmdSetColors : EdSetColors; {Support installation of editor colors}
  1126.         CmdSaveDefaults : EdSaveDefaults; {Save editor defaults to disk}
  1127.       end;
  1128.     end;                     {EdTextCommands}
  1129.  
  1130.     procedure EdUtilityCommands(C : CommandType);
  1131.       {-Dispatcher for commands which perform utility functions}
  1132.  
  1133.     begin                    {EdUtilityCommands}
  1134.       case C of
  1135.         CmdPrintFile : EdPrintFile; {Start printing a file}
  1136.         CmdFlushUndo : EdFlushUndo; {Flush the undo buffer}
  1137.         CmdLogDrive : EdPromptLogDrive; {Prompt for and move to new directory}
  1138.         CmdDirectory : EdDirectory; {display a file directory}
  1139.         CmdGotoPage : EdPromptGotoPage; {Go to specified page}
  1140.         CmdSetTopMargin : EdSetTopMargin; {Set default top margin}
  1141.         CmdSetBotMargin : EdSetBotMargin; {Set default bottom margin}
  1142.         CmdSetPageLength : EdSetPageLength; {Set default page length}
  1143.         CmdSetUndoLimit : EdSetUndoLimit; {Set default undo limit}
  1144.         CmdToggleTabExpansion : EdToggleBoolean(ReadExpandTabs); {Toggle tab expansion on read-in}
  1145.         CmdGetDefaultExtension : EdGetDefaultExtension; {Get a new default extension}
  1146.         CmdSetTabLine : EdSetTabLine; {Set tabs based on current template}
  1147.         CmdSetTabSize : EdSetTabSize; {Set default tab size}
  1148.         CmdSaveTabLine : EdSaveTabLine; {Write current tab line into text}
  1149.         CmdEditTabLine : EdEditTabLine; {Interactively edit the tabs}
  1150.         CmdSetTempMargin : EdSetTempMargin; {Set temporary margin for word wrap}
  1151.         CmdReformBlock : EdReformBlock; {Reformat marked block}
  1152.         CmdCloseTillLast : EdAbandonFile(False); {Close windows but stay in editor}
  1153.       end;
  1154.     end;                     {EdUtilityCommands}
  1155.  
  1156.     procedure EdRareCommands(C : CommandType);
  1157.       {-Dispatcher for commands rarely used}
  1158.  
  1159.     begin                    {EdRareCommands}
  1160.       case C of
  1161.         CmdPromptSetMarker : EdPromptSetMarker; {Prompt for a marker number to set}
  1162.         CmdPromptJumpMarker : EdPromptJumpMarker; {Prompt for a marker to jump to}
  1163.         CmdPromptInsertMacro : EdPromptMacroInsert; {Prompt for a macro to insert}
  1164.         CmdToggleTabMode : EdToggleFixedTabs; {Toggle fixed tabs}
  1165.         CmdSetTempAtCursor : EdSetTempAtCursor; {Set temp margin at cursor}
  1166.         CmdSetSupportPath : EdSetSupportPath; {Set a new home directory for the editor}
  1167.         CmdToggleStripMode : EdToggleBoolean(SaveStripMode); {Toggle high bit stripping}
  1168.         CmdEditMacro : EdEditMacro; {Edit a macro definition}
  1169.         CmdWriteNamedFile : {Write current window to a new file}
  1170.           if EdWriteNamedFile then
  1171.             ;
  1172.         CmdToggleKeyHelp : EdToggleBoolean(SaveKeyHelpMode); {Toggle display of keystroke help in menus}
  1173.         CmdWindowUp : EdWindowUp; {Move to previous window on screen}
  1174.         CmdNextSentence : EdNextSentence; {Move cursor to start of next sentence}
  1175.         CmdPrevSentence : EdPrevSentence; {Move cursor to start of previous sentence}
  1176.         CmdRestoreDefaultTabs : EdSetEvenTabs(Curwin^.Tabs); {Put tabs on even boundaries}
  1177.         CmdWhatFont : EdWhatFont; {What font is cursor on}
  1178.         CmdChooseBold : EdInsertPrintFormat(^B); {Insert Bold toggle}
  1179.         CmdChooseDbl : EdInsertPrintFormat(^D); {Insert Doublestrike toggle}
  1180.         CmdChooseUnd : EdInsertPrintFormat(^S); {Insert Underscore toggle}
  1181.         CmdChooseSup : EdInsertPrintFormat(^T); {Insert Superscript toggle}
  1182.         CmdChooseSub : EdInsertPrintFormat(^V); {Insert Subscript toggle}
  1183.         CmdChooseAlt1 : EdInsertPrintFormat(^A); {Insert Alt1 font toggle}
  1184.         CmdChooseAlt2 : EdInsertPrintFormat(^N); {Insert Alt2 font toggle}
  1185.         CmdToggleRetraceMode : EdToggleRetraceMode; {Toggle snow control}
  1186.         CmdToggleSolidCursor : EdToggleSolidCursor; {Toggle display of block cursor}
  1187.         CmdToggleEga43Line : EdToggleEga43Line; {Toggle use of 25 and 43 line screen modes}
  1188.         CmdMarginRelease : EdToggleBoolean(MarginRelease); {Reset or release margin}
  1189.         CmdSpellCheck : EdSpellingCheck; {Check document for spelling}
  1190.         CmdToggleWriteTabs : EdToggleBoolean(WriteCompressTabs); {Toggle writing of tabs on output}
  1191.         CmdToggleCompressWrap : EdToggleCompressWrap; {Toggle compression of lines prior to wrap}
  1192.         CmdToggleInitZoomState : EdToggleInitZoomState; {Change initial zoom state}
  1193.         CmdHelpMenu : EdHelpMenu; {Put up a menu of help topics}
  1194.         CmdHelpHelp..CmdFunctionKeyHelp : EdHelpWindow(C); {Select a help subsection}
  1195.       end;
  1196.     end;                     {EdRareCommands}
  1197.  
  1198.   begin                      {EdProcessCommand}
  1199.  
  1200.     {Clear the command line indicator}
  1201.     EdResetPromptLine;
  1202.  
  1203.     repeat
  1204.  
  1205.       {See if menu command}
  1206.       if C = CmdMenu then begin
  1207.         {Get command from menu system}
  1208.         EdUpdateCmdLine;
  1209.         EdGetMenuChoice(C, ExitMenu);
  1210.       end else
  1211.         ExitMenu := True;
  1212.  
  1213.       {Store the soon to be a previous position}
  1214.       with Curwin^ do begin
  1215.         Lastcol := Colno;
  1216.         Lastline := Curline;
  1217.       end;
  1218.  
  1219.       {Store a global record of current command for the help system}
  1220.       GlobalCmd := C;
  1221.  
  1222.       {Branch based on basic command groups}
  1223.       case C of
  1224.         CmdLeftChar..CmdUpPage : EdCursorCommands(C);
  1225.         CmdWindowTopFile..CmdJumpLastPosition : EdQuickCommands(C);
  1226.         CmdUndo..CmdDelLineNoRecourse : EdDeleteCommands(C);
  1227.         CmdFind..CmdSaveQuit : EdFileCommands(C);
  1228.         CmdAddWindow..CmdZoomWindow : EdWindowCommands(C);
  1229.         CmdBlockBegin..CmdJumpMarker9 : EdBlockCommands(C);
  1230.         CmdReadMacroFile..CmdInsertScrap9 : EdMacroCommands(C);
  1231.         CmdSysInfo..CmdSaveDefaults : EdTextCommands(C);
  1232.         CmdPrintFile..CmdCloseTillLast : EdUtilityCommands(C);
  1233.         CmdPromptSetMarker..CmdFunctionKeyHelp : EdRareCommands(C);
  1234.       end;
  1235.  
  1236.       if not(ExitMenu) then
  1237.         {Loop within menu system}
  1238.         C := CmdMenu
  1239.       else if EdPtrNotNil(CurrMenu) then
  1240.         {Remove menus from screen}
  1241.         EdEraseMenus
  1242.       else
  1243.         {Assure menu help is on-screen}
  1244.         EdShowMenuHelp;
  1245.  
  1246.       {Reset from any effect of the called command}
  1247.       EdZapPromptLine;
  1248.       Abortcmd := False;
  1249.       Goterror := False;
  1250.       AbortEnable := False;
  1251.  
  1252.       if WindowCount > 0 then begin
  1253.  
  1254.         with LastPosition, Curwin^ do begin
  1255.           if (Curline <> Lastline) or (Colno <> Lastcol) then begin
  1256.             {Store the previous position}
  1257.             Line := Lastline;
  1258.             Col := Lastcol;
  1259.             {Reset the temporary left margin as needed}
  1260.             if WW then
  1261.               EdResetTempMargin(Curwin, False);
  1262.           end;
  1263.  
  1264.           {Buffer line if it changed}
  1265.           if Blockop or (Curline <> Lastline) then begin
  1266.             EdBufferCurrentLine;
  1267.             Blockop := False;
  1268.             {Turn off margin release}
  1269.             MarginRelease := False;
  1270.           end;
  1271.         end;
  1272.  
  1273.         {Don't update the screen inside of macros}
  1274.         if (EditUsercommandInput = 0) then begin
  1275.           {Special handling of single line scrolls for CGA speed}
  1276.           if FullScroll <> 0 then
  1277.             if Recurring then
  1278.               FullScroll := 0
  1279.             else
  1280.               EdBiosScroll;
  1281.           {The screen may need to be updated in the background}
  1282.           UpdateScreen := True;
  1283.         end;
  1284.  
  1285.       end;
  1286.  
  1287.     until ExitMenu;
  1288.  
  1289.   end;                       {EdProcessCommand}
  1290.  
  1291.   procedure EdClassifyInput;
  1292.     {-Route keyboard input to text or command handlers}
  1293.   var
  1294.     Ch : Char;
  1295.     CmdCode : CommandType;
  1296.  
  1297.   begin                      {EdClassifyInput}
  1298.  
  1299.     {Read a character}
  1300.     Ch := EdGetInput;
  1301.  
  1302.     if (CmdPtr = 0) and (Ch >= #32) and (Ch <> #127) then begin
  1303.  
  1304.       {A normal character}
  1305.       {Store previous position}
  1306.       with LastPosition, Curwin^ do begin
  1307.         Col := Colno;
  1308.         Line := Curline;
  1309.       end;
  1310.  
  1311.       {Process the character}
  1312.       EdProcessText(Ch, True);
  1313.  
  1314.       if EditUsercommandInput = 0 then
  1315.         {Buffer line if it changed due to word wrap}
  1316.         if Curwin^.Curline <> LastPosition.Line then
  1317.           EdBufferCurrentLine;
  1318.  
  1319.     end else begin
  1320.  
  1321.       {Potentially a command}
  1322.       Inc(CmdPtr);
  1323.       if (CmdPtr > 1) and (CmdBuf[Pred(CmdPtr)] <> Null) then
  1324.         {Accept lower/upper/control chars as equivalent for second char of command}
  1325.         CmdBuf[CmdPtr] := EdControlFilter(Ch)
  1326.       else
  1327.         CmdBuf[CmdPtr] := Ch;
  1328.  
  1329.       case EdScanCmdList(CmdPtr, CmdCode) of
  1330.  
  1331.         Match :
  1332.           {Process the command}
  1333.           EdProcessCommand(CmdCode);
  1334.  
  1335.         NoMatch :
  1336.           {Reset and ignore}
  1337.           EdResetPromptLine;
  1338.  
  1339.         PartMatch :
  1340.           {Leave char in CmdBuf to complete match}
  1341.           {Indicate via command line that a partial command has been entered}
  1342.           EdDisplayCommandBuffer;
  1343.  
  1344.       end;                   {Case}
  1345.     end;                     {Potential command}
  1346.  
  1347.   end;                       {EdClassifyInput}
  1348.  
  1349.   procedure EdProcessMacroChars {(CurrentUserChars : integer)} ;
  1350.     {-Processes characters pushed in a Find and Macro command}
  1351.  
  1352.   begin                      {EdProcessMacroChars}
  1353.     {Process the macro characters}
  1354.     while EditUsercommandInput > CurrentUserChars do
  1355.       EdClassifyInput;
  1356.   end;                       {EdProcessMacroChars}
  1357.  
  1358.   procedure EdSchedule;
  1359.     {-Schedule editor}
  1360.  
  1361.     procedure EdBackgroundProcess;
  1362.       {-Process background functions}
  1363.  
  1364.     begin                    {EdBackgroundProcess}
  1365.  
  1366.       {Align windows horizontally}
  1367.       EdHscroll;
  1368.  
  1369.       {Update the cursor}
  1370.       if UpdateCursor then
  1371.         EdUpdateCursor;
  1372.  
  1373.       {Update the screen if something's new}
  1374.       if UpdateScreen then begin
  1375.         {Redraw the screen}
  1376.         EdUpdateScreen;
  1377.         {Assure the cursor is always off when solidcursor is used}
  1378.         EdSetCursorOff;
  1379.       end;
  1380.       if EdKeyInterrupt then
  1381.         Exit;
  1382.  
  1383.       {Mark any new lines in block}
  1384.       EdMarkblock;
  1385.       if EdKeyInterrupt then
  1386.         Exit;
  1387.  
  1388.       {Update the screen again if attributes changed}
  1389.       if UpdateScreen then begin
  1390.         EdUpdateScreen;
  1391.         if EdKeyInterrupt then
  1392.           Exit;
  1393.       end;
  1394.  
  1395.       {Show on-screen font attributes}
  1396.       EdSetAttributes;
  1397.       if EdKeyInterrupt then
  1398.         Exit;
  1399.  
  1400.       {Update the screen again if attributes changed}
  1401.       if UpdateScreen then begin
  1402.         EdUpdateScreen;
  1403.         if EdKeyInterrupt then
  1404.           Exit;
  1405.       end;
  1406.  
  1407.       {Print files}
  1408.       if Printing then begin
  1409.         EdPrintNext(PrintChars);
  1410.         if EdKeyInterrupt then
  1411.           Exit;
  1412.       end;
  1413.  
  1414.       {Keep window modified flags up to date}
  1415.       EdCloneModifiedFlags;
  1416.       if EdKeyInterrupt then
  1417.         Exit;
  1418.  
  1419.       {Generate page numbers for every window}
  1420.       EdRepaginate;
  1421.       if EdKeyInterrupt then
  1422.         Exit;
  1423.  
  1424.       {Generate line number and byte count for every window}
  1425.       EdGenLineNo;
  1426.  
  1427.       {Print until interrupted}
  1428.       if Printing then
  1429.         EdPrintNext(MaxInt);
  1430.  
  1431.     end;                     {EdBackgroundProcess}
  1432.  
  1433.   begin                      {EdSchedule}
  1434.     Rundown := False;
  1435.     repeat
  1436.       if EdKeyPressed then
  1437.         {Foreground operations - classify keystrokes and process commands}
  1438.         EdClassifyInput
  1439.       else
  1440.         {Horizontal scroll, paint screen, etc.}
  1441.         EdBackgroundProcess;
  1442.     until Rundown;
  1443.   end;                       {EdSchedule}
  1444.  
  1445. begin
  1446.   Argcount := ParamCount;    {Number of DOS command line parameters}
  1447. end.
  1448.