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

  1. {                            MSSCRN2.PAS
  2.                                MS 4.0
  3.                 Copyright (c) 1985, 87 by Borland International, Inc.         }
  4.  
  5. {$I msdirect.inc}
  6.  
  7. unit MsScrn2;
  8.   {-Screen updating routines specific to 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,                   {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.   MsBack;                    {Background processes}
  26.  
  27. procedure EdUpdateStatusLine(W : Pwindesc);
  28.   {-Update window status line for specified window}
  29.  
  30. procedure EdUpdateLine(P : PlineDesc; Row, Leftedge, Leftcol : Integer; Attribs : Boolean);
  31.   {-Update one row of the screen}
  32.  
  33. procedure EdUpdatewindow(W : Pwindesc);
  34.   {-Update a single window on the screen}
  35.  
  36. procedure EdBiosScroll;
  37.   {-Use the IBM BIOS to scroll up or down one line rapidly}
  38.  
  39. procedure EdUpdateScreen;
  40.   {-Update physical screen}
  41.  
  42. procedure EdHighlightScreen(Col1, Col2 : Integer; Attr : Byte; WaitForKey : Boolean);
  43.   {-Change attribute of a screen string and wait for keystroke}
  44.  
  45. procedure EdInterruptibleDelay(Time : Integer);
  46.   {-Generate a delay which can be interrupted by a keystroke}
  47.  
  48. function EdCmdAccessible(Menu : Menuptr; Sub : Byte) : Boolean;
  49.   {-Return true if command is currently accessible from the menu}
  50.  
  51. procedure EdDrawItem(Menu : Menuptr; Sub : Byte);
  52.   {-Draw menu item "sub" of the chosen menu}
  53.  
  54. procedure EdUndrawMenu(Menu : Menuptr);
  55.   {-remove the menu and its children from the screen}
  56.  
  57. procedure EdDrawMenu(Menu : Menuptr);
  58.   {-Draw a menu and its selected children on the screen}
  59.  
  60. procedure EdEraseMenus;
  61.   {-Remove the menu system from the screen}
  62.  
  63.   {==========================================================================}
  64.  
  65. implementation
  66.  
  67. const
  68.   {Positions on Window status line}
  69.   ZoomFlagCol = 0;           {Uses columns 00-03}
  70.   NameCol = 4;               {04-16}
  71.   PercentCol = 17;           {17-21}
  72.   LineTitleCol = 22;         {22-26}
  73.   LineNumCol = 27;           {27-32}
  74.   ColTitleCol = 33;          {33-36}
  75.   ColNumCol = 37;            {37-40}
  76.   PageTitleCol = 41;         {41-45}
  77.   PageNumCol = 46;           {46-49}
  78.   InsertFlagCol = 50;        {50-56, or Overwrite}
  79.   IndentFlagCol = 57;        {57-63}
  80.   WordWrapFlagCol = 64;      {64-68, or Margin Release}
  81.   JustifyFlagCol = 69;       {69-76}
  82.   MacroFlagCol = 77;         {77-79, or Printing, or Attribute}
  83.  
  84.   {Strings for Window status line}
  85.   StLine : string[4] = 'Line';
  86.   StCol : string[3] = 'Col';
  87.   Stai : string[6] = 'Indent';
  88.   StIns : string[6] = 'Insert';
  89.   StOvr : string[6] = 'Over';
  90.   StPage : string[4] = 'Page';
  91.   StMr : string[3] = ^P'R'^Q;
  92.   StPr : string[3] = ^P'P'^Q;
  93.   StWw : string[4] = 'Wrap';
  94.   StRel : string[12] = 'Marg Release';
  95.   StJu : string[7] = 'Justify';
  96.   StZoom : string[3] = ^P'Z'^Q;
  97.   StCarat : string[3] = '^  ';
  98.  
  99.   procedure EdUpdateStatusLine(W : Pwindesc);
  100.     {-Update window status line}
  101.   var
  102.     St : VarString;
  103.     Ch : Char;
  104.     Pnum : Integer;
  105.     Percent : Integer;
  106.  
  107.     procedure EdUpdateTabLine(W : Pwindesc);
  108.       {-Write the tab line to the screen}
  109.     const
  110.       DashChar : Char = #196;
  111.       TabChar : Char = #31;
  112.       LeftChar : Char = 'L';
  113.       WrapChar : Char = #16;
  114.       RightChar : Char = 'R';
  115.     var
  116.       T, L, I, ScrCols : Integer;
  117.       Tpos : Integer;
  118.  
  119.       procedure EdBuildTabLine(Tpos : Integer; C : Char);
  120.         {-Set the tab display to the specified character}
  121.  
  122.       begin                  {EdBuildTabLine}
  123.         if (Tpos >= 0) and (Tpos < ScrCols) then
  124.           Tline[Tpos] := C;
  125.       end;                   {EdBuildTabLine}
  126.  
  127.     begin                    {EdUpdateTabLine}
  128.  
  129.       with W^ do begin
  130.  
  131.         {Initialize the text line}
  132.         FillChar(Tline, PhyScrCols, DashChar);
  133.         L := Leftedge;
  134.         ScrCols := PhyScrCols-Leftcol;
  135.  
  136.         {Fill in the tab markers}
  137.         I := 1;
  138.         repeat
  139.           T := Tabs[I];
  140.           Tpos := T-L;
  141.           if not(WW) or ((T >= Lmargin) and (T <= Rmargin)) then
  142.             EdBuildTabLine(Leftcol+Tpos, TabChar);
  143.           Inc(I);
  144.         until (I > MaxNumTabs) or (Tpos >= ScrCols);
  145.  
  146.         if WW then begin
  147.           {Display the margins}
  148.           EdBuildTabLine(Leftcol-L+Wmargin, WrapChar);
  149.           EdBuildTabLine(Leftcol-L+Lmargin, LeftChar);
  150.           EdBuildTabLine(Leftcol-L+Rmargin, RightChar);
  151.         end;
  152.  
  153.         {Write it to screen}
  154.         EdWrline(Succ(Firstlineno));
  155.  
  156.       end;
  157.     end;                     {EdUpdateTabLine}
  158.  
  159.   begin                      {EdUpdateStatusLine}
  160.  
  161.     if EdKeyInterrupt then
  162.       Exit;
  163.  
  164.     with W^ do begin
  165.  
  166.       {Initialize the screen attribute of the status line}
  167.       FillChar(Aline, PhyScrCols, ScreenAttr[BordColor]);
  168.       {Fill status line with blanks}
  169.       FillChar(Tline, PhyScrCols, Blank);
  170.  
  171.       {Display the zoom marker}
  172.       if Zoomed then
  173.         Move(StZoom[1], Tline[ZoomFlagCol], Length(StZoom));
  174.  
  175.       {Print the file name}
  176.       St := EdEndOfPath(Filename);
  177.       Move(St[1], Tline[NameCol], Length(St));
  178.  
  179.       {Relative position in file}
  180.       if (Crelpos >= 1000) then
  181.         {Only show 100 at very end of file}
  182.         St := '100'
  183.       else if (Crelpos > 990) then
  184.         St := '99'
  185.       else if (Crelpos > 0) and (Crelpos < 10) then
  186.         {Only show 0 at very beginning of file}
  187.         St := '1'
  188.       else begin
  189.         {Round to nearest percent}
  190.         Percent := Crelpos div 10;
  191.         if Crelpos mod 10 >= 5 then
  192.           Inc(Percent);
  193.         Str(Percent, St);
  194.       end;
  195.       Move(St[1], Tline[PercentCol], Length(St));
  196.       Tline[PercentCol+Length(St)] := '%';
  197.  
  198.       {Line number}
  199.       Move(StLine[1], Tline[LineTitleCol], Length(StLine));
  200.       if Clineno <= 0 then
  201.         St := '..'
  202.       else if PA and (Clineno > PageLen) then
  203.         St := '..'
  204.       else
  205.         Str(Clineno:1, St);
  206.       Move(St[1], Tline[LineNumCol], Length(St));
  207.  
  208.       {Column number}
  209.       Move(StCol[1], Tline[ColTitleCol], Length(StCol));
  210.       Str(Colno:1, St);
  211.       Move(St[1], Tline[ColNumCol], Length(St));
  212.  
  213.       {Page number}
  214.       if PA then begin
  215.         {Show current page number}
  216.         Move(StPage[1], Tline[PageTitleCol], Length(StPage));
  217.         Pnum := EdGetPageNum(Curline);
  218.         if Pnum <= 0 then
  219.           St := '..'
  220.         else
  221.           Str(Pnum, St);
  222.         Move(St[1], Tline[PageNumCol], Length(St));
  223.       end;
  224.  
  225.       {Insert/overtype symbol}
  226.       if Insertflag then
  227.         Move(StIns[1], Tline[InsertFlagCol], Length(StIns))
  228.       else
  229.         Move(StOvr[1], Tline[InsertFlagCol], Length(StOvr));
  230.  
  231.       {Autoindent mode symbol}
  232.       if AI then
  233.         Move(Stai[1], Tline[IndentFlagCol], Length(Stai));
  234.  
  235.       {Word wrap and Justify symbols}
  236.       if WW then
  237.         if MarginRelease then
  238.           Move(StRel[1], Tline[WordWrapFlagCol], Length(StRel))
  239.         else begin
  240.           Move(StWw[1], Tline[WordWrapFlagCol], Length(StWw));
  241.           if JU then
  242.             Move(StJu[1], Tline[JustifyFlagCol], Length(StJu));
  243.         end;
  244.  
  245.       if Recording then
  246.         {Macro recording symbol}
  247.         Move(StMr[1], Tline[MacroFlagCol], Length(StMr))
  248.       else if Printing then
  249.         {Printing symbol}
  250.         Move(StPr[1], Tline[MacroFlagCol], Length(StPr));
  251.  
  252.       if AT then
  253.         if (W = Curwin) and (Colno <= Curline^.Bufflen) then begin
  254.           {Character type symbol - distinguishes control characters when hidden}
  255.           Ch := Curline^.Txt^[Colno];
  256.           if Ch < Blank then begin
  257.             StCarat[2] := Chr(Ord(Ch)+64);
  258.             Move(StCarat[1], Tline[MacroFlagCol], 3);
  259.           end;
  260.         end;
  261.  
  262.       {Write it to the screen}
  263.       EdWrline(Firstlineno);
  264.  
  265.       {Write the tab line if selected}
  266.       if TL then
  267.         EdUpdateTabLine(W);
  268.  
  269.     end;
  270.   end;                       {EdUpdateStatusLine}
  271.  
  272.   {***}
  273.   procedure EdUpdateLine(P : PlineDesc; Row, Leftedge, Leftcol : Integer; Attribs : Boolean);
  274.     {-Update one row of the screen}
  275.   var
  276.     Fl : Word;
  277.     ScrCols : Integer;
  278.  
  279.     procedure EdBuildLineNoAttribs(P : PlineDesc; Leftedge, Leftcol, ScrCols : Integer; Attr : Byte);
  280.       {-Build TLINE and ALINE without text attribute display}
  281.     var
  282.       Len : Integer;
  283.  
  284.     begin                    {EdBuildLineNoAttribs}
  285.  
  286.       {Get the displayed part of the text}
  287.       Len := Succ(EdTextLength(P))-Leftedge;
  288.       if Len > 0 then begin
  289.         if Len >= ScrCols then begin
  290.           {Line covers full width of screen}
  291.           Move(P^.Txt^[Leftedge], Tline[Leftcol], ScrCols);
  292.           FillChar(Aline[Leftcol], ScrCols, Attr);
  293.         end else begin
  294.           {Line covers part of screen, right fill with blanks}
  295.           Move(P^.Txt^[Leftedge], Tline[Leftcol], Len);
  296.           FillChar(Tline[Leftcol+Len], ScrCols-Len, Blank);
  297.           FillChar(Aline[Leftcol], Len, Attr);
  298.           FillChar(Aline[Leftcol+Len], ScrCols-Len, ScreenAttr[TxtColor]);
  299.         end;
  300.       end else begin
  301.         {Text scrolled off left edge of screen}
  302.         FillChar(Tline[Leftcol], ScrCols, Blank);
  303.         FillChar(Aline[Leftcol], ScrCols, ScreenAttr[TxtColor]);
  304.       end;
  305.     end;                     {EdBuildLineNoAttribs}
  306.  
  307.     procedure EdBuildLineAttribs(P : PlineDesc; Leftedge,
  308.                                  Leftcol, ScrCols : Integer;
  309.                                  Fl : Word);
  310.       {-Build TLINE and ALINE when attributes are activated}
  311.     var
  312.       Attr, FontByte : Byte;
  313.       Ipos, Epos, Opos, Len : Integer;
  314.       Ch : Char;
  315.       C : PrintCommandtype;
  316.  
  317.     begin                    {EdBuildLineAttribs}
  318.  
  319.       {Get the font descriptor at start of line, computed by a background process}
  320.       FontByte := P^.Font;
  321.       Attr := FontAttribute[FontByte];
  322.  
  323.       if (Fl and NewAttr) = 0 then
  324.  
  325.         {Line is all of one attribute}
  326.         EdBuildLineNoAttribs(P, Leftedge, Leftcol, ScrCols, Attr)
  327.  
  328.       else begin
  329.  
  330.         {Line contains font toggles}
  331.  
  332.         {Build the line character by character}
  333.         Len := EdTextLength(P);
  334.         Opos := Leftcol;
  335.         Ipos := 1;
  336.         Epos := 0;
  337.  
  338.         with P^ do
  339.           while (Opos < PhyScrCols) do begin
  340.  
  341.             if Ipos <= Len then begin
  342.               {Evaluate next character from text line}
  343.               Ch := Txt^[Ipos];
  344.               C := PrintMap[Ch];
  345.             end else begin
  346.               {Beyond end of line, use nominal attribute}
  347.               Ch := Blank;
  348.               Attr := ScreenAttr[TxtColor];
  349.               C := PrtNone;
  350.             end;
  351.  
  352.             if C = PrtNone then begin
  353.               {Fill in text and attribute lines}
  354.               Inc(Epos);
  355.               if Epos >= Leftedge then begin
  356.                 Tline[Opos] := Ch;
  357.                 Aline[Opos] := Chr(Attr);
  358.                 Inc(Opos);
  359.               end;
  360.             end else begin
  361.               {Change font attribute}
  362.               EdUpdateFont(C, FontByte);
  363.               Attr := FontAttribute[FontByte];
  364.             end;
  365.  
  366.             Inc(Ipos);
  367.  
  368.           end;
  369.       end;
  370.     end;                     {EdBuildLineAttribs}
  371.  
  372.     procedure EdShowBlockMarkers(P : PlineDesc; Leftedge, Leftcol, ScrCols : Integer; Attribs : Boolean);
  373.       {-Set up attributes for block marked lines}
  374.     var
  375.       M, N : Integer;
  376.       Attr : Byte;
  377.  
  378.     begin                    {EdShowBlockMarkers}
  379.  
  380.       Attr := ScreenAttr[BlockColor];
  381.  
  382.       {Special cases for partially marked lines}
  383.       if P = Blockfrom.Line then begin
  384.  
  385.         M := EdComputeEffectiveColNo(Attribs, Blockfrom.Line, Blockfrom.Col)-Leftedge;
  386.  
  387.         if (P = Blockto.Line) then begin
  388.  
  389.           {Block is totally within one line}
  390.           if M <= ScrCols then begin
  391.             {Block shows on screen}
  392.             if M <= 0 then
  393.               M := 0;
  394.             N := EdComputeEffectiveColNo(Attribs, Blockto.Line, Blockto.Col)-Leftedge;
  395.             if N > ScrCols then
  396.               {Right edge of block off of screen}
  397.               FillChar(Aline[M+Leftcol], ScrCols-M, Attr)
  398.             else begin
  399.               if Attribs then
  400.                 if PrintMap[P^.Txt^[Blockto.Col]] <> PrtNone then
  401.                   N := Succ(N);
  402.               if N < 0 then
  403.                 N := 0;
  404.               FillChar(Aline[M+Leftcol], N-M, Attr);
  405.             end;
  406.           end;
  407.  
  408.         end else begin
  409.  
  410.           {First line of block}
  411.           if M <= ScrCols then begin
  412.             {Block shows on screen}
  413.             if M <= 0 then
  414.               M := 0;
  415.             FillChar(Aline[M+Leftcol], ScrCols-M, Attr);
  416.           end;
  417.  
  418.         end;
  419.  
  420.       end else if P = Blockto.Line then begin
  421.  
  422.         {Last line of block}
  423.         N := EdComputeEffectiveColNo(Attribs, Blockto.Line, Blockto.Col)-Leftedge;
  424.         if N > ScrCols then
  425.           {Whole visible line in block}
  426.           FillChar(Aline[Leftcol], ScrCols, Attr)
  427.         else if N > 0 then begin
  428.           if Attribs then
  429.             if PrintMap[P^.Txt^[Blockto.Col]] <> PrtNone then
  430.               N := Succ(N);
  431.           FillChar(Aline[Leftcol], N, Attr);
  432.         end;
  433.  
  434.       end else
  435.  
  436.         {Line fully in block}
  437.         FillChar(Aline[Leftcol], ScrCols, Attr);
  438.  
  439.     end;                     {EdShowBlockMarkers}
  440.  
  441.     procedure EdShowTextMarkers(P : PlineDesc; Leftedge, Leftcol, ScrCols : Integer; Attribs : Boolean);
  442.       {-Display the text markers}
  443.     var
  444.       M, N : Integer;
  445.  
  446.     begin                    {EdShowTextMarkers}
  447.       for M := 0 to MaxMarker do
  448.         with Marker[M] do
  449.           if P = Line then begin
  450.             {Change the marked position to the mark number in border color}
  451.             N := EdComputeEffectiveColNo(Attribs, P, Col)-Leftedge;
  452.             if (N >= 0) and (N < ScrCols) then begin
  453.               {Change the displayed character}
  454.               Tline[N+Leftcol] := Chr(M+Ord('0'));
  455.               {Change the attribute}
  456.               Aline[N+Leftcol] := Chr(ScreenAttr[BordColor]);
  457.             end;
  458.           end;
  459.     end;                     {EdShowTextMarkers}
  460.  
  461.     procedure EdShowPageMarkers(Fl, Leftcol : Integer);
  462.       {-Display page breaks}
  463.  
  464.     begin                    {EdShowPageMarkers}
  465.       FillChar(Aline, Leftcol, ScreenAttr[BordColor]);
  466.       {Insert new page marker}
  467.       if (Fl and NewPage) <> 0 then
  468.         FillChar(Tline, Leftcol, #175)
  469.       else
  470.         FillChar(Tline, Leftcol, Blank);
  471.     end;                     {EdShowPageMarkers}
  472.  
  473.   begin                      {EdUpdateLine}
  474.  
  475.     {Screen columns available for text display}
  476.     ScrCols := PhyScrCols-Leftcol;
  477.  
  478.     if EdPtrIsNil(P) then begin
  479.  
  480.       {Blank line at end of file}
  481.       FillChar(Tline[Leftcol], ScrCols, Blank);
  482.       FillChar(Aline[Leftcol], ScrCols, ScreenAttr[TxtColor]);
  483.       Fl := 0;
  484.  
  485.     end else begin
  486.  
  487.       Fl := P^.Flags;
  488.  
  489.       if Attribs then
  490.         EdBuildLineAttribs(P, Leftedge, Leftcol, ScrCols, Fl)
  491.       else
  492.         EdBuildLineNoAttribs(P, Leftedge, Leftcol, ScrCols, ScreenAttr[TxtColor]);
  493.  
  494.       {Show block markers}
  495.       if (Fl and InBlock) <> 0 then
  496.         EdShowBlockMarkers(P, Leftedge, Leftcol, ScrCols, Attribs);
  497.  
  498.       {Display text markers}
  499.       if (Fl and InMark) <> 0 then
  500.         EdShowTextMarkers(P, Leftedge, Leftcol, ScrCols, Attribs);
  501.  
  502.     end;
  503.  
  504.     {Display pagination marks}
  505.     if Leftcol <> 0 then
  506.       EdShowPageMarkers(Fl, Leftcol);
  507.  
  508.     {Write the line to screen after translating control characters}
  509.     EdWrlineCtrl(Row);
  510.  
  511.   end;                       {EdUpdateLine}
  512.  
  513.   procedure EdUpdatewindow(W : Pwindesc);
  514.     {-Update a single window on the screen}
  515.   var
  516.     P : PlineDesc;
  517.     I, R, Le, Lc : Integer;
  518.     Attribs : Boolean;
  519.  
  520.   begin                      {EdUpdateWindow}
  521.     with W^ do begin
  522.       Le := Leftedge;
  523.       Lc := Leftcol;
  524.       Attribs := AT;
  525.       I := 0;
  526.  
  527.       {Update from one past the current line to bottom of window}
  528.       P := Curline^.Fwdlink;
  529.       for R := (Firsttextno+Lineno) to Lastlineno do begin
  530.         EdUpdateLine(P, R, Le, Lc, Attribs);
  531.         Inc(I);
  532.         {Check every 4th line for a keyboard interrupt}
  533.         if I and 3 = 0 then
  534.           if EdKeyInterrupt then
  535.             Exit;
  536.         if EdPtrNotNil(P) then
  537.           EdFwdPtr(P);
  538.       end;
  539.  
  540.       {Now update from top of window to current line}
  541.       P := TopLine;
  542.       for R := Firsttextno to Pred(Firsttextno+Lineno) do begin
  543.         EdUpdateLine(P, R, Le, Lc, Attribs);
  544.         Inc(I);
  545.         if I and 3 = 0 then
  546.           if EdKeyInterrupt then
  547.             Exit;
  548.         if EdPtrNotNil(P) then
  549.           EdFwdPtr(P);
  550.       end;
  551.  
  552.     end;
  553.   end;                       {EdUpdateWindow}
  554.  
  555.   procedure EdBiosScroll;
  556.     {-use the IBM BIOS to scroll up or down one line rapidly}
  557.   var
  558.     regs : registers;
  559.     P : PlineDesc;
  560.     R : Integer;
  561.     Delta : Integer;
  562.  
  563.   begin                      {EdBiosScroll}
  564.     with Curwin^ do begin
  565.  
  566.       {Avoid a snake of solid cursor appearing during fast scroll}
  567.       if SolidCursor then
  568.         EdEraseSolidCursor;
  569.  
  570.       {Scroll the current window up or down via BIOS call}
  571.       with regs do begin
  572.         Al := 1;
  573.         if FullScroll < 0 then begin
  574.           Ah := 6;
  575.           Delta := 1;
  576.         end else begin
  577.           Ah := 7;
  578.           Delta := -1;
  579.         end;
  580.         Ch := Pred(Firsttextno);
  581.         Cl := 0;
  582.         Dh := Pred(Lastlineno);
  583.         dl := 79;
  584.         Bh := lo(ScreenAttr[TxtColor]);
  585.       end;
  586.       intr($10, regs);
  587.  
  588.       {Write the newly scrolled line}
  589.       if FullScroll > 0 then
  590.         EdUpdateLine(TopLine, Firsttextno, Leftedge, Leftcol, AT)
  591.       else begin
  592.         {Get pointer to last line on screen}
  593.         P := TopLine;
  594.         for R := Firsttextno to Pred(Lastlineno) do
  595.           if EdPtrNotNil(P) then
  596.             EdFwdPtr(P);
  597.         EdUpdateLine(P, Lastlineno, Leftedge, Leftcol, AT);
  598.       end;
  599.  
  600.     end;
  601.     if UpdateCursor then
  602.       EdUpdateCursor;
  603.     FullScroll := FullScroll+Delta;
  604.   end;                       {EdBiosScroll}
  605.  
  606.   procedure EdUpdateScreen;
  607.     {-Update physical screen}
  608.   var
  609.     W : Pwindesc;
  610.  
  611.   begin                      {EdUpdateScreen}
  612.  
  613.     {Update the current line}
  614.     with Curwin^ do
  615.       EdUpdateLine(Curline, Pred(Firsttextno+Lineno), Leftedge, Leftcol, AT);
  616.  
  617.     {Get out if keys are waiting}
  618.     if EdKeyInterrupt then
  619.       Exit;
  620.  
  621.     {Update the rest of the screen window by window, starting with current}
  622.     W := Curwin;
  623.     repeat
  624.       if W^.Visible then begin
  625.         EdUpdatewindow(W);
  626.         if EdKeyInterrupt then
  627.           Exit;
  628.         EdUpdateStatusLine(W);
  629.       end;
  630.       EdFwdPtr(W);
  631.     until W = Curwin;
  632.  
  633.     {Update the command line}
  634.     EdUpdateCmdLine;
  635.  
  636.     {Indicate that the screen has been fully updated}
  637.     UpdateScreen := False;
  638.     FullScroll := 0;
  639.     Intrflag := Interr;
  640.  
  641.   end;                       {EdUpdateScreen}
  642.  
  643.   procedure EdHighlightScreen(Col1, Col2 : Integer; Attr : Byte; WaitForKey : Boolean);
  644.     {-Change attribute of a screen string and wait for keystroke}
  645.   var
  646.     Dis, C1, C2, Len : Integer;
  647.     CenterWindow, Cwb, Cwt : Integer;
  648.     GenLine : Boolean;
  649.  
  650.   begin                      {EdHighLightScreen}
  651.  
  652.     {Remove menus from screen}
  653.     if EdPtrNotNil(CurrMenu) then begin
  654.       EdEraseMenus;
  655.       ExitMenu := True;
  656.     end;
  657.  
  658.     with Curwin^ do begin
  659.  
  660.       {Compute effective column numbers on display}
  661.       C1 := EdComputeEffectiveColNo(AT, Curline, Col1);
  662.       C2 := EdComputeEffectiveColNo(AT, Curline, Col2);
  663.  
  664.       {Horizontal scroll}
  665.       if C1 <= Leftedge then begin
  666.         if C1 > 1 then
  667.           Leftedge := Pred(C1)
  668.         else
  669.           Leftedge := C1;
  670.       end else if C2 >= (Leftedge+PhyScrCols-2-Leftcol) then
  671.         Leftedge := C2-PhyScrCols+Leftcol+2;
  672.  
  673.       {Vertical scroll to keep highlight somewhat centered in window}
  674.       CenterWindow := Succ((Lastlineno-Firsttextno) shr 1);
  675.       Cwt := CenterWindow-(CenterWindow shr 1);
  676.       Cwb := CenterWindow+(CenterWindow shr 1);
  677.       while EdPtrNotNil(TopLine^.Fwdlink) and (Lineno > Cwb) do begin
  678.         EdFwdPtr(TopLine);
  679.         Dec(Lineno);
  680.       end;
  681.       while EdPtrNotNil(TopLine^.Backlink) and (Lineno < Cwt) do begin
  682.         EdBackPtr(TopLine);
  683.         Inc(Lineno);
  684.       end;
  685.  
  686.       {Update the screen}
  687.       EdUpdateCursor;
  688.       EdZapPromptLine;
  689.       EdUpdateScreen;
  690.  
  691.       {Change attribute of selected string}
  692.       Dis := Succ(C1-Leftedge+Leftcol);
  693.       Len := Succ(C2-C1);
  694.       if Pred(Dis+Len) > DefNoCols then
  695.         {Avoid overwriting edge of screen}
  696.         Len := Succ(DefNoCols-Dis);
  697.       EdChangeAttribute(Len, Pred(Firsttextno+Lineno), Dis, Attr);
  698.       if SolidCursor then
  699.         EdDrawSolidCursor;
  700.  
  701.     end;
  702.  
  703.     if WaitForKey then begin
  704.       {Wait for a keystroke}
  705.       GenLine := True;
  706.       repeat
  707.         if GenLine then begin
  708.           EdGenLineOne(Curwin);
  709.           if UpdateScreen then begin
  710.             EdUpdateStatusLine(Curwin);
  711.             UpdateScreen := False;
  712.             GenLine := False;
  713.           end;
  714.         end;
  715.         if Printing then
  716.           EdPrintNext(PrintChars);
  717.       until Abortcmd or EdKeyPressed;
  718.     end;
  719.   end;                       {EdHighLightScreen}
  720.  
  721.   procedure EdInterruptibleDelay(Time : Integer);
  722.     {-Generate a delay which can be interrupted by a keystroke}
  723.   var
  724.     Total : Integer;
  725.  
  726.   begin                      {EdInterruptibleDelay}
  727.     EdUpdateScreen;
  728.     Total := 0;
  729.     while (Total < Time) do begin
  730.       if EdKeyPressed or Abortcmd then
  731.         Exit;
  732.       Delay(5);
  733.       Total := Total+5;
  734.     end;
  735.   end;                       {EdInterruptibleDelay}
  736.  
  737.   function EdCmdAccessible(Menu : Menuptr; Sub : Byte) : Boolean;
  738.     {-Return true if command is currently accessible from the menu}
  739.  
  740.   begin                      {EdCmdAccessible}
  741.     if WindowCount = 0 then
  742.       EdCmdAccessible := (Menu^.SubMenus^[Sub].Command in MainCommands)
  743.     else
  744.       EdCmdAccessible := True;
  745.   end;                       {EdCmdAccessible}
  746.  
  747.   procedure EdDrawItem(Menu : Menuptr; Sub : Byte);
  748.     {-Draw menu item "sub" of the chosen menu}
  749.   const
  750.     {Flags used for status display in menu system}
  751.     NoStat = 0;              {Entry displays no status}
  752.     BoolStat = 1;            {Entry displays boolean - ON/OFF - status}
  753.     NumStat = 2;             {Entry displays numeric status}
  754.     StrStat = 3;             {Entry displays string status}
  755.   var
  756.     R, C, Len : Byte;
  757.     S : VarString;
  758.     Orient : MenuOrientation;
  759.  
  760.     procedure EdEvaluateSpecial(C : CommandType; Stat : Byte; var S : VarString);
  761.       {-Modify s to contain special status info}
  762.     var
  763.       Ss : VarString;
  764.       BoolVal : Boolean;
  765.       NumVal : Integer;
  766.  
  767.       function EdTruncateString(S : Filepath; Maxlen : Integer) : Filepath;
  768.         {-Truncate a string if it exceeds maxlen}
  769.  
  770.       begin                  {EdTruncateString}
  771.         if Length(S) <= Maxlen then
  772.           EdTruncateString := S
  773.         else
  774.           EdTruncateString := Copy(S, 1, Maxlen-3)+'...';
  775.       end;                   {EdTruncateString}
  776.  
  777.     begin                    {EdEvaluateSpecial}
  778.       with Curwin^ do
  779.         case Stat of
  780.  
  781.           BoolStat :         {Status is a boolean}
  782.             begin
  783.               case C of
  784.                 CmdToggleInsert : BoolVal := Insertflag;
  785.                 CmdToggleWordWrap : BoolVal := WW;
  786.                 CmdToggleAutoindent : BoolVal := AI;
  787.                 CmdToggleTabLine : BoolVal := TL;
  788.                 CmdToggleJustify : BoolVal := JU;
  789.                 CmdTogglePaginate : BoolVal := PA;
  790.                 CmdToggleAttribute : BoolVal := AT;
  791.                 CmdToggleTabMode : BoolVal := FT;
  792.                 CmdToggleTabExpansion : BoolVal := ReadExpandTabs;
  793.                 CmdZoomWindow : BoolVal := Zoomed;
  794.                 CmdToggleStripMode : BoolVal := SaveStripMode;
  795.                 CmdToggleKeyHelp : BoolVal := SaveKeyHelpMode;
  796.                 CmdToggleRetraceMode : BoolVal := RetraceMode;
  797.                 CmdToggleSolidCursor : BoolVal := SolidCursor;
  798.                 CmdToggleEga43Line : BoolVal := Ega43lineMode;
  799.                 CmdToggleInitZoomState : BoolVal := SaveInitZoomState;
  800.                 CmdToggleWriteTabs : BoolVal := WriteCompressTabs;
  801.                 CmdToggleCompressWrap : BoolVal := CW;
  802.               end;
  803.               Ss := OnOff[BoolVal];
  804.             end;
  805.  
  806.           NumStat :          {Status is a number}
  807.             begin
  808.               case C of
  809.                 CmdSetLeftMargin : NumVal := Lmargin;
  810.                 CmdSetRightMargin : NumVal := Rmargin;
  811.                 CmdSetTopMargin : NumVal := Tmargin;
  812.                 CmdSetBotMargin : NumVal := Bmargin;
  813.                 CmdSetPageLength : NumVal := PageLen;
  814.                 CmdSetTabSize : NumVal := SaveTabSize;
  815.                 CmdSetUndoLimit : NumVal := UndoLimit;
  816.               end;
  817.               Str(NumVal, Ss);
  818.             end;
  819.  
  820.           StrStat :          {Status is a string}
  821.             case C of
  822.               CmdGetDefaultExtension : Ss := DefExtension;
  823.               CmdSetSupportPath : Ss := EdTruncateString(SaveSupportPath, 14);
  824.             end;
  825.         end;
  826.  
  827.       {Right justify the substring in the already padded main string}
  828.       Move(Ss[1], S[Length(S)-Length(Ss)], Length(Ss));
  829.     end;                     {EdEvaluateSpecial}
  830.  
  831.   begin                      {EdDrawItem}
  832.  
  833.     {Get the orientation of the current menu}
  834.     Orient := MenuDesc[Menu^.MenuLev].Orientation;
  835.  
  836.     with Menu^, SubMenus^[Sub] do begin
  837.  
  838.       {Copy the prompt to a work string}
  839.       Len := Ord(Prompt^[0]);
  840.       R := YPosn;
  841.       C := XPosn;
  842.  
  843.       {Pad with blanks left and right}
  844.       if Orient = Vertical then begin
  845.         S[0] := Chr(XSize);
  846.         R := R+Doffset;
  847.       end else begin
  848.         S[0] := Chr(Len+2);
  849.         C := C+Doffset;
  850.       end;
  851.  
  852.       FillChar(S[1], Length(S), Blank);
  853.       Move(Prompt^[1], S[2], Len);
  854.  
  855.       if StatVal <> NoStat then
  856.         {Special cases to display status items, etc}
  857.         EdEvaluateSpecial(Command, StatVal, S);
  858.  
  859.       if Menu^.SubCur <> Sub then begin
  860.         if EdCmdAccessible(Menu, Sub) then begin
  861.           {Write item with highlighted selection character}
  862.           EdFastWrite(Copy(S, 1, Soffset), R, C, ScreenAttr[MnColor]);
  863.           EdFastWrite(S[Succ(Soffset)], R, C+Soffset, ScreenAttr[MhColor]);
  864.           EdFastWrite(Copy(S, Soffset+2, Length(S)), R, Succ(C+Soffset), ScreenAttr[MnColor]);
  865.         end else
  866.           EdFastWrite(S, R, C, ScreenAttr[MnColor]);
  867.       end else
  868.         {Write the selected prompt}
  869.         EdFastWrite(S, R, C, ScreenAttr[MsColor]);
  870.     end;
  871.   end;                       {EdDrawItem}
  872.  
  873.   procedure EdUndrawMenu(Menu : Menuptr);
  874.     {-remove the menu and its children from the screen}
  875.  
  876.   begin                      {EdUndrawmenu}
  877.  
  878.     if EdPtrIsNil(Menu) then
  879.       Exit;
  880.  
  881.     with Menu^ do begin
  882.       {Undraw any submenus - must do first to get proper screen restore}
  883.       if SubOn then begin
  884.         EdUndrawMenu(SubMenus^[SubCur].SubMenu);
  885.         SubOn := False;
  886.       end;
  887.  
  888.       with MenuDesc[MenuLev] do
  889.         {Restore whatever the menu overlapped on the screen}
  890.         EdRestoreWindow(Overlap, Pred(XPosn), Pred(YPosn), XSize+2, YSize+2);
  891.     end;
  892.   end;                       {EdUndrawmenu}
  893.  
  894.   procedure EdEraseMenus;
  895.     {-Remove the menu system from the screen}
  896.  
  897.   begin                      {EdEraseMenus}
  898.     EdUndrawMenu(RootMenu);
  899.     EdSetPtrNil(CurrMenu);
  900.     EdShowMenuHelp;
  901.   end;                       {EdEraseMenus}
  902.  
  903.   procedure EdDrawMenu(Menu : Menuptr);
  904.     {-Draw a menu and its selected children on the screen}
  905.   var
  906.     I : Byte;
  907.     S : VarString;
  908.  
  909.   begin                      {EdDrawMenu}
  910.  
  911.     if EdPtrIsNil(Menu) then
  912.       Exit;
  913.  
  914.     with Menu^ do begin
  915.  
  916.       with MenuDesc[MenuLev] do begin
  917.         {Store current screen to be overlapped and draw border for window}
  918.         Overlap :=
  919.         EdSetupWindow(Border, Pred(XPosn), Pred(YPosn), XPosn+XSize, YPosn+YSize, NormalBox);
  920.  
  921.         {For horizontal windows, clear out the box}
  922.         if Orientation = Horizontal then begin
  923.           FillChar(S[1], XSize, Blank);
  924.           S[0] := Chr(XSize);
  925.           for I := 0 to Pred(YSize) do
  926.             EdFastWrite(S, YPosn+I, XPosn, ScreenAttr[MnColor]);
  927.         end;
  928.       end;
  929.  
  930.       {Draw each item in the menu}
  931.       for I := 1 to SubMax do
  932.         EdDrawItem(Menu, I);
  933.  
  934.       {Draw any submenus}
  935.       if SubOn then
  936.         EdDrawMenu(SubMenus^[SubCur].SubMenu);
  937.  
  938.     end;
  939.   end;                       {EdDrawmenu}
  940.  
  941. end.
  942.