home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / PIBMENU.ZIP / PIBMENUS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1986-01-16  |  50.0 KB  |  1,058 lines

  1. (*----------------------------------------------------------------------*)
  2. (*           PIBMENUS.PAS   --- Menu Routines for Turbo Pascal          *)
  3. (*----------------------------------------------------------------------*)
  4. (*                                                                      *)
  5. (*  Author:  Philip R. Burns                                            *)
  6. (*  Date:    January, 1985                                              *)
  7. (*  Version: 1.0                                                        *)
  8. (*  Systems: For MS-DOS on IBM PCs and close compatibles only.          *)
  9. (*           Note:  I have checked these on Zenith 151s under           *)
  10. (*                  MSDOS 2.1 and IBM PCs under PCDOS 2.0.              *)
  11. (*                                                                      *)
  12. (*  History: These routines represent my substantial upgrading of the   *)
  13. (*           simple menu routines written by Barry Abrahamsen which     *)
  14. (*           I believe appeared originally in the TUG newsletter.       *)
  15. (*           The windowing facility provides windows similar to those   *)
  16. (*           implemented in QMODEM by John Friel III.                   *)
  17. (*                                                                      *)
  18. (*           Suggestions for improvements or corrections are welcome.   *)
  19. (*           Please leave messages on Gene Plantz's BBS (312) 882 4145  *)
  20. (*           or Ron Fox's BBS (312) 940 6496.                           *)
  21. (*                                                                      *)
  22. (*           If you use this code in your own programs, please be nice  *)
  23. (*           and give all of us credit.                                 *)
  24. (*                                                                      *)
  25. (*----------------------------------------------------------------------*)
  26. (*                                                                      *)
  27. (*  Needs:  These routines need the include files MINMAX.PAS,           *)
  28. (*          GLOBTYPE.PAS, and ASCII.PAS.  These files are not           *)
  29. (*          included here, since Turbo regrettably does not allow       *)
  30. (*          nested includes.                                            *)
  31. (*                                                                      *)
  32. (*----------------------------------------------------------------------*)
  33. (*                                                                      *)
  34. (*  What these routines do:                                             *)
  35. (*                                                                      *)
  36. (*    These routines provide a straight-forward menu-selection          *)
  37. (*    facility, similar to that used in programs like Lotus.  A pop-up  *)
  38. (*    window holds the menu.  The menu is contained in a frame.  The    *)
  39. (*    items are displayed within the frame.  The currently selected     *)
  40. (*    item is highlighted in reverse video.  You move up and down in    *)
  41. (*    the list of menu items by using the up and down arrow keys, or    *)
  42. (*    the space bar.  To make a selection, hit the Enter (Return) key.  *)
  43. (*                                                                      *)
  44. (*    Note that code for stacked windows is available here.  You may    *)
  45. (*    want to modify this to use compile-time window spaces, or remove  *)
  46. (*    the current push-down stack structure.                            *)
  47. (*                                                                      *)
  48. (*----------------------------------------------------------------------*)
  49. (*                                                                      *)
  50. (*  Use:                                                                *)
  51. (*                                                                      *)
  52. (*     (1)  Define a variable of type Menu_Type, say, MYMENU.           *)
  53. (*                                                                      *)
  54. (*     (2)  Define the following entries in MYMENU:                     *)
  55. (*                                                                      *)
  56. (*             Menu_Size    --- Number of entries in this menu          *)
  57. (*             Menu_Title   --- Title for the menu                      *)
  58. (*             Menu_Row     --- Row where menu should appear (upper LHC *)
  59. (*             Menu_Column  --- Column where menu should appear         *)
  60. (*             Menu_Width   --- Width of menu                           *)
  61. (*             Menu_Height  --- Height of menu                          *)
  62. (*             Menu_Default --- Ordinal of the default menu entry       *)
  63. (*             Menu_Tcolor  --- Color to display menu text              *)
  64. (*             Menu_Bcolor  --- Color for menu background               *)
  65. (*             Menu_Fcolor  --- Color for menu frame box                *)
  66. (*                                                                      *)
  67. (*     (3)  Now for each of Menu_Size Menu_Entries, define:             *)
  68. (*             Menu_Text   --- Text of menu item                        *)
  69. (*                                                                      *)
  70. (*     (4)  Call  Menu_Display_Choices  to display menu.  The default   *)
  71. (*          menu choice will be highlighted.                            *)
  72. (*                                                                      *)
  73. (*     (5)  Call  Menu_Get_Choice  to retrieve menu choice.  The up and *)
  74. (*          down arrows, and the space bar, can be used to move         *)
  75. (*          through the menu items.  Each item is highlighted in turn.  *)
  76. (*          Whichever item is highlighted when a carriage return is     *)
  77. (*          entered is returned as the chosen item.                     *)
  78. (*                                                                      *)
  79. (*----------------------------------------------------------------------*)
  80.  
  81.                    (* Character Constants *)
  82.  
  83. Const
  84.  
  85.    Up_arrow         = ^E;    (* move up in menu code   *)
  86.    Down_arrow       = ^X;    (* move down in menu code *)
  87.    Space_bar        = #32;   (* space bar              *)
  88.    Ch_cr            = #13;   (* Carriage return *)
  89.    Ch_esc           = #27;   (* Escape *)
  90.    Bell             = #07;   (* Bell *)
  91.  
  92.    Max_Menu_Items   =  10;   (* Maximum number of menu choices *)
  93.  
  94.    Dont_Erase_Menu  = FALSE;
  95.    Erase_Menu       = TRUE;
  96.  
  97.  
  98.                    (* Menu Types *)
  99. Type
  100.  
  101.    String40   = String[40]         (* Menu entry string type               *);
  102.    String60   = String[60]         (* Menu title string type               *);
  103.  
  104.    Menu_Entry = Record
  105.       Menu_Item_Text   : String40; (* Text of entry                        *)
  106.       Menu_Item_Row    : Integer;  (* Row position of menu item            *)
  107.       Menu_Item_Column : Integer;  (* Column position of menu item         *)
  108.    End;
  109.  
  110.    Menu_Type = Record
  111.       Menu_Size     : 1 .. Max_Menu_Items;    (* No. of items in menu      *)
  112.       Menu_Title    : String60;               (* Menu title                *)
  113.       Menu_Row      : Integer;                (* Row position of menu      *)
  114.       Menu_Column   : Integer;                (* Column position of menu   *)
  115.       Menu_Width    : Integer;                (* Width of menu             *)
  116.       Menu_Height   : Integer;                (* Height of menu            *)
  117.       Menu_Default  : 1 .. Max_Menu_Items;    (* Default value position    *)
  118.       Menu_TColor   : Integer;                (* Foreground text color     *)
  119.       Menu_BColor   : Integer;                (* BackGround color          *)
  120.       Menu_FColor   : Integer;                (* Frame color               *)
  121.  
  122.                                               (* Menu items themselves     *)
  123.       Menu_Entries  : Array[ 1 .. Max_Menu_Items ] Of Menu_Entry;
  124.    End;
  125.  
  126.                    (* Screen Types *)
  127.  
  128. Const
  129.      Color_Screen_Address   = $B800;   (* Address of color screen          *)
  130.      Mono_Screen_Address    = $B000;   (* Address of mono screen           *)
  131.      Screen_Length          = 4000;    (* 80 x 25 x 2 = screen area length *)
  132.      Max_Saved_Screen       = 5;       (* Maximum no. of saved screens     *)
  133.  
  134. Type
  135.                                               (* A screen image            *)
  136.    Screen_Type       = Array[ 1 .. Screen_Length ] Of Byte;
  137.  
  138.    Screen_Ptr        = ^Screen_Image_Type;
  139.    Screen_Image_Type = Record
  140.                           Screen_Image: Screen_Type;
  141.                        End;
  142.  
  143.                                               (* Screen stack entries      *)
  144.    Saved_Screen_Ptr  = ^Saved_Screen_Type;
  145.    Saved_Screen_Type = Record
  146.                           Screen_Image  : Screen_Type;
  147.                           Screen_Row    : Integer;
  148.                           Screen_Column : Integer;
  149.                           Screen_X1     : Integer;
  150.                           Screen_Y1     : Integer;
  151.                           Screen_X2     : Integer;
  152.                           Screen_Y2     : Integer;
  153.                        End;
  154.  
  155.  
  156.                    (* Screen Variables *)
  157.  
  158. Var
  159.                                               (* Memory-mapped screen area *)
  160.    Actual_Screen        : Screen_Ptr;
  161.  
  162.                                               (* Saves screen behind menus *)
  163.    Saved_Screen         : Saved_Screen_Ptr;
  164.  
  165.                                               (* Stack of saved screens    *)
  166.    Saved_Screen_List    : Array[ 1 .. Max_Saved_Screen ] Of Saved_Screen_Ptr;
  167.  
  168.                                               (* Depth of saved screen stack *)
  169.    Current_Saved_Screen : 0 .. Max_Saved_Screen;
  170.  
  171. (*----------------------------------------------------------------------*)
  172. (*    Color_Screen_Active --- Determine if color or mono screen         *)
  173. (*----------------------------------------------------------------------*)
  174.  
  175. Function Color_Screen_Active : Boolean;
  176.  
  177. (*                                                                      *)
  178. (*     Function:   Color_Screen_Active                                  *)
  179. (*                                                                      *)
  180. (*     Purpose:    Determines if color or mono screen active            *)
  181. (*                                                                      *)
  182. (*     Calling Sequence:                                                *)
  183. (*                                                                      *)
  184. (*        Color_Active := Color_Screen_Active : Boolean;                *)
  185. (*                                                                      *)
  186. (*           Color_Active --- set to TRUE if the color screen is        *)
  187. (*                            active, FALSE if the mono screen is       *)
  188. (*                            active.                                   *)
  189. (*                                                                      *)
  190. (*     Calls:   INTR                                                    *)
  191. (*                                                                      *)
  192.  
  193. Var
  194.    Regs : Record       (* 8088 registers *)
  195.              Ax, Bx, Cx, Dx, Bp, Si, Di, Ds, Es, Flags : Integer
  196.           End;
  197.  
  198. Begin  (* Color_Screen_Active *)
  199.  
  200.    Regs.Ax := 15 SHL 8;
  201.  
  202.    INTR( $10 , Regs );
  203.  
  204.    Color_Screen_Active := ( Regs.Ax AND $FF ) <> 7;
  205.  
  206. End    (* Color_Screen_Active *);
  207.  
  208. (*----------------------------------------------------------------------*)
  209. (*        Get_Screen_Address --- Get address of current screen          *)
  210. (*----------------------------------------------------------------------*)
  211.  
  212. Procedure Get_Screen_Address( Var Actual_Screen : Screen_Ptr );
  213.  
  214. (*                                                                      *)
  215. (*     Procedure:  Get_Screen_Address                                   *)
  216. (*                                                                      *)
  217. (*     Purpose:    Gets screen address for current type of display      *)
  218. (*                                                                      *)
  219. (*     Calling Sequence:                                                *)
  220. (*                                                                      *)
  221. (*        Get_Screen_Address( Var Actual_Screen : Screen_Ptr );         *)
  222. (*                                                                      *)
  223. (*           Actual_Screen --- pointer whose value receives the         *)
  224. (*                             current screen address.                  *)
  225. (*                                                                      *)
  226. (*     Calls:   Color_Screen_Active                                     *)
  227. (*              PTR                                                     *)
  228. (*                                                                      *)
  229.  
  230. Begin  (* Get_Screen_Address *)
  231.  
  232.    If Color_Screen_Active Then
  233.       Actual_Screen := PTR( Color_Screen_Address , 0 )
  234.    Else
  235.       Actual_Screen := PTR( Mono_Screen_Address , 0 );
  236.  
  237. End    (* Get_Screen_Address *);
  238.  
  239. (*----------------------------------------------------------------------*)
  240. (*                Video Display Control Routines                        *)
  241. (*----------------------------------------------------------------------*)
  242. (*                                                                      *)
  243. (*       RvsVideoOn  --- Turn On Reverse Video                          *)
  244. (*       RvsVideoOff --- Turn Off Reverse Video                         *)
  245. (*                                                                      *)
  246. (*----------------------------------------------------------------------*)
  247.  
  248. Procedure RvsVideoOn( Foreground_Color, Background_Color : Integer );
  249.  
  250. Begin (* RvsVideoOn *)
  251.  
  252.    TextColor     ( Background_color );
  253.    TextBackGround( Foreground_color );
  254.  
  255. End   (* RvsVideoOn *);
  256.  
  257. (*----------------------------------------------------------------------*)
  258.  
  259. Procedure RvsVideoOff( Foreground_Color, Background_Color : Integer );
  260.  
  261. Begin (* RvsVideoOff *)
  262.  
  263.    TextColor     ( Foreground_color );
  264.    TextBackGround( Background_color );
  265.  
  266. End   (* RvsVideoOff *);
  267.  
  268.  
  269. (*----------------------------------------------------------------------*)
  270. (*                TURBO Pascal Window Location Routines                 *)
  271. (*----------------------------------------------------------------------*)
  272. (*                                                                      *)
  273. (*  These routines and constants give the four corners of the current   *)
  274. (*  Turbo window:                                                       *)
  275. (*                                                                      *)
  276. (*    Lower right-hand corner: (Lower_Right_Column, Lower_Right_Row)    *)
  277. (*    Upper left_hand corner:  (Upper_Left_Column, Upper_Right_Column)  *)
  278. (*                                                                      *)
  279. (*----------------------------------------------------------------------*)
  280.  
  281.                                    (* Lower right corner of     *)
  282.                                    (* current TURBO window      *)
  283. Var
  284.    Lower_Right_Column  : Byte ABSOLUTE Cseg:$016A;
  285.    Lower_Right_Row     : Byte ABSOLUTE Cseg:$016B;
  286.  
  287. (*----------------------------------------------------------------------*)
  288. (*    Upper_Left_Column ---  Upper Left Col. Position of current window *)
  289. (*----------------------------------------------------------------------*)
  290.  
  291. Function Upper_Left_Column : Integer;
  292.  
  293. (*                                                                      *)
  294. (*     Function:   Upper_Left_Column                                    *)
  295. (*                                                                      *)
  296. (*     Purpose:    Returns upper left col. pos. of current TURBO window *)
  297. (*                                                                      *)
  298. (*     Calling Sequence:                                                *)
  299. (*                                                                      *)
  300. (*        Pos := Upper_Left_Column : Integer;                           *)
  301. (*                                                                      *)
  302. (*     Calls:   Mem                                                     *)
  303. (*                                                                      *)
  304.  
  305. Begin  (* Upper_Left_Column *)
  306.  
  307.    Upper_Left_Column := Mem[ Dseg:$0156 ] + 1;
  308.  
  309. End    (* Upper_Left_Column *);
  310.  
  311. (*----------------------------------------------------------------------*)
  312. (*    Upper_Left_Row ---  Upper Left Row Position of current window     *)
  313. (*----------------------------------------------------------------------*)
  314.  
  315. Function Upper_Left_Row : Integer;
  316.  
  317. (*                                                                      *)
  318. (*     Function:   Upper_Left_Row                                       *)
  319. (*                                                                      *)
  320. (*     Purpose:    Returns upper left row pos. of current TURBO window  *)
  321. (*                                                                      *)
  322. (*     Calling Sequence:                                                *)
  323. (*                                                                      *)
  324. (*        Pos := Upper_Left_Row : Integer;                              *)
  325. (*                                                                      *)
  326. (*     Calls:   Mem                                                     *)
  327. (*                                                                      *)
  328.  
  329. Begin  (* Upper_Left_Row *)
  330.  
  331.    Upper_Left_Row := Mem[ Dseg:$0157 ] + 1;
  332.  
  333. End    (* Upper_Left_Row *);
  334.  
  335. (*----------------------------------------------------------------------*)
  336. (*                Set/Reset Text Color Routines                         *)
  337. (*----------------------------------------------------------------------*)
  338. (*                                                                      *)
  339. (*   These routines set and reset the global text foreground and        *)
  340. (*   background colors.                                                 *)
  341. (*                                                                      *)
  342. (*----------------------------------------------------------------------*)
  343.  
  344.                    (* Global Text Color Variables *)
  345.  
  346. Var
  347.    Global_ForeGround_Color : Integer;
  348.    Global_BackGround_Color : Integer;
  349.  
  350. (*----------------------------------------------------------------------*)
  351. (*    Set_Global_Colors --- Reset global foreground, background cols.   *)
  352. (*----------------------------------------------------------------------*)
  353.  
  354. Procedure Set_Global_Colors( ForeGround, BackGround : Integer );
  355.  
  356. (*                                                                      *)
  357. (*     Procedure:  Set_Global_Colors                                    *)
  358. (*                                                                      *)
  359. (*     Purpose:    Sets global text foreground, background colors.      *)
  360. (*                                                                      *)
  361. (*     Calling Sequence:                                                *)
  362. (*                                                                      *)
  363. (*        Set_Global_Colors( ForeGround, BackGround : Integer );        *)
  364. (*                                                                      *)
  365. (*           ForeGround --- Default foreground color                    *)
  366. (*           BackGround --- Default background color                    *)
  367. (*                                                                      *)
  368. (*     Calls:   TextColor                                               *)
  369. (*              TextBackGround                                          *)
  370. (*                                                                      *)
  371.  
  372. Begin  (* Set_Global_Colors *)
  373.  
  374.    Global_ForeGround_Color := ForeGround;
  375.    GLobal_BackGround_Color := BackGround;
  376.  
  377.    TextColor     ( Global_ForeGround_Color );
  378.    TextBackground( Global_BackGround_Color );
  379.  
  380. End    (* Set_Global_Colors *);
  381.  
  382. (*----------------------------------------------------------------------*)
  383. (*  Reset_Global_Colors --- Reset global foreground, background cols.   *)
  384. (*----------------------------------------------------------------------*)
  385.  
  386. Procedure Reset_Global_Colors;
  387.  
  388. (*                                                                      *)
  389. (*     Procedure:  Reset_Global_Colors                                  *)
  390. (*                                                                      *)
  391. (*     Purpose:    Resets text foreground, background colors to global  *)
  392. (*                 defaults.                                            *)
  393. (*                                                                      *)
  394. (*     Calling Sequence:                                                *)
  395. (*                                                                      *)
  396. (*        Reset_Global_Colors;                                          *)
  397. (*                                                                      *)
  398. (*     Calls:   TextColor                                               *)
  399. (*              TextBackGround                                          *)
  400. (*                                                                      *)
  401.  
  402. Begin  (* Reset_Global_Colors *)
  403.  
  404.    TextColor     ( Global_ForeGround_Color );
  405.    TextBackground( Global_BackGround_Color );
  406.  
  407. End    (* Reset_Global_Colors *);
  408.  
  409. (*----------------------------------------------------------------------*)
  410. (*                 Screen Manipulation Routines                         *)
  411. (*----------------------------------------------------------------------*)
  412. (*                                                                      *)
  413. (*   These routines save and restore screen images in support of the    *)
  414. (*   windowing facility.  Also, the current screen image can be printed *)
  415. (*   and text extracted from the screen memory.                         *)
  416. (*                                                                      *)
  417. (*----------------------------------------------------------------------*)
  418.  
  419. (*----------------------------------------------------------------------*)
  420. (*       Get_Screen_Text_Line --- Extract text from screen image        *)
  421. (*----------------------------------------------------------------------*)
  422.  
  423. Procedure Get_Screen_Text_Line( Var Text_Line     : AnyStr;
  424.                                     Screen_Line   : Integer;
  425.                                     Screen_Column : Integer );
  426.  
  427. (*                                                                      *)
  428. (*     Procedure:  Get_Screen_Text_Line                                 *)
  429. (*                                                                      *)
  430. (*     Purpose:    Extracts text from current screen image              *)
  431. (*                                                                      *)
  432. (*     Calling Sequence:                                                *)
  433. (*                                                                      *)
  434. (*        Get_Screen_Text_Line( Var Text_Line     : AnyStr;             *)
  435. (*                                  Screen_Line   : Integer;            *)
  436. (*                                  Screen_Column : Integer );          *)
  437. (*                                                                      *)
  438. (*           Text_Line        --- receives text extracted from screen   *)
  439. (*           Screen_Line      --- line on screen to extract             *)
  440. (*           Screen_Column    --- starting column to extract            *)
  441. (*                                                                      *)
  442. (*     Calls:   None                                                    *)
  443. (*                                                                      *)
  444. (*     Remarks:                                                         *)
  445. (*                                                                      *)
  446. (*        Only the text -- not attributes -- from the screen is         *)
  447. (*        returned.                                                     *)
  448. (*                                                                      *)
  449.  
  450. Var
  451.    First_Pos  : Integer;
  452.    Last_Pos   : Integer;
  453.    I          : Integer;
  454.  
  455. Begin  (* Print_Screen *)
  456.  
  457.    Screen_Line   := Max( Min( Screen_Line   , 25 ) , 1 );
  458.    Screen_Column := Max( Min( Screen_Column , 80 ) , 1 );
  459.  
  460.    Text_Line     := '';
  461.    First_Pos     := ( ( Screen_Line - 1 ) * 80 + Screen_Column ) * 2;
  462.    Last_Pos      := Screen_Line * 160;
  463.  
  464.    Repeat
  465.       Text_Line := Text_Line + CHR( Actual_Screen^.Screen_Image[ First_Pos ] );
  466.       First_Pos := First_Pos + 2;
  467.    Until ( First_Pos > Last_Pos );
  468.  
  469. End    (* Print_Screen *);
  470.  
  471. (*----------------------------------------------------------------------*)
  472. (*                Print_Screen --- Print current screen image           *)
  473. (*----------------------------------------------------------------------*)
  474.  
  475. Procedure Print_Screen;
  476.  
  477. (*                                                                      *)
  478. (*     Procedure:  Print_Screen                                         *)
  479. (*                                                                      *)
  480. (*     Purpose:    Prints current screen image (memory mapped area)     *)
  481. (*                                                                      *)
  482. (*     Calling Sequence:                                                *)
  483. (*                                                                      *)
  484. (*        Print_Screen;                                                 *)
  485. (*                                                                      *)
  486. (*     Calls:   None                                                    *)
  487. (*                                                                      *)
  488. (*     Remarks:                                                         *)
  489. (*                                                                      *)
  490. (*        Only the text from the screen is printed.                     *)
  491. (*                                                                      *)
  492.  
  493. Var
  494.    I         : Integer;
  495.    Text_Line : String[80];
  496.  
  497. Begin  (* Print_Screen *)
  498.  
  499.    For I := 1 To 25 Do
  500.       Begin
  501.          Get_Screen_Text_Line( Text_Line, I, 1 );
  502.          Writeln( Lst , Text_Line );
  503.       End;
  504.  
  505. End    (* Print_Screen *);
  506.  
  507. (*----------------------------------------------------------------------*)
  508. (*                Save_Screen --- Save current screen image             *)
  509. (*----------------------------------------------------------------------*)
  510.  
  511. Procedure Save_Screen( Var Saved_Screen_Pointer : Saved_Screen_Ptr );
  512.  
  513. (*                                                                      *)
  514. (*     Procedure:  Save_Screen                                          *)
  515. (*                                                                      *)
  516. (*     Purpose:    Saves current screen image (memory mapped area)      *)
  517. (*                                                                      *)
  518. (*     Calling Sequence:                                                *)
  519. (*                                                                      *)
  520. (*        Save_Screen( Var Saved_Screen_Pointer : Saved_Screen_Ptr );   *)
  521. (*                                                                      *)
  522. (*           Saved_Screen_Pointer  --- pointer to record receiving      *)
  523. (*                                     screen image, window location,   *)
  524. (*                                     and current cursor location.     *)
  525. (*                                                                      *)
  526. (*     Calls:   Move                                                    *)
  527. (*              Upper_Left_Column                                       *)
  528. (*              Upper_Left_Row                                          *)
  529. (*                                                                      *)
  530. (*     Remarks:                                                         *)
  531. (*                                                                      *)
  532. (*        This version doesn't check for stack overflow.                *)
  533. (*        Caveat Programmer.                                            *)
  534. (*                                                                      *)
  535.  
  536. Begin  (* Save_Screen *)
  537.  
  538.    Current_Saved_Screen := Current_Saved_Screen + 1;
  539.    New( Saved_Screen_Pointer );
  540.    Saved_Screen_List[ Current_Saved_Screen ] := Saved_Screen_Pointer;
  541.  
  542.    With Saved_Screen_Pointer^ Do
  543.       Begin
  544.  
  545.          Screen_X1     := Upper_Left_Column;
  546.          Screen_Y1     := Upper_Left_Row;
  547.          Screen_X2     := Lower_Right_Column;
  548.          Screen_Y2     := Lower_Right_Row;
  549.  
  550.          Screen_Row    := WhereY;
  551.          Screen_Column := WhereX;
  552.  
  553.          Move( Actual_Screen^.Screen_Image, Screen_Image, Screen_Length );
  554.  
  555.       End;
  556.  
  557. End   (* Save_Screen *);
  558.  
  559. (*----------------------------------------------------------------------*)
  560. (*              Restore_Screen --- Restore saved screen image           *)
  561. (*----------------------------------------------------------------------*)
  562.  
  563. Procedure Restore_Screen( Var Saved_Screen_Pointer : Saved_Screen_Ptr );
  564.  
  565. (*                                                                      *)
  566. (*     Procedure:  Restore_Screen                                       *)
  567. (*                                                                      *)
  568. (*     Purpose:    Restores previously saved screen image.              *)
  569. (*                                                                      *)
  570. (*     Calling Sequence:                                                *)
  571. (*                                                                      *)
  572. (*        Restore_Screen( Var Saved_Screen_Pointer: Saved_Screen_Ptr ); *)
  573. (*                                                                      *)
  574. (*           Saved_Screen_Pointer  --- pointer to record with saved     *)
  575. (*                                     screen image, window location,   *)
  576. (*                                     and cursor location.             *)
  577. (*                                                                      *)
  578. (*     Calls:   Window                                                  *)
  579. (*              Move                                                    *)
  580. (*              GoToXY                                                  *)
  581. (*                                                                      *)
  582. (*     Remarks:                                                         *)
  583. (*                                                                      *)
  584. (*        All saved screen pointers from the last saved down to the     *)
  585. (*        argument pointer are popped from the saved screen list.       *)
  586. (*                                                                      *)
  587.  
  588. Begin  (* Restore_Screen *)
  589.  
  590.    With Saved_Screen_Pointer^ Do
  591.       Begin
  592.  
  593.          Window( Screen_X1, Screen_Y1, Screen_X2, Screen_Y2 );
  594.  
  595.          Move( Screen_Image, Actual_Screen^.Screen_Image, Screen_Length );
  596.  
  597.          GoToXY( Screen_Column, Screen_Row );
  598.  
  599.       End;
  600.  
  601.    While( Saved_Screen_List[ Current_Saved_Screen ] <> Saved_Screen_Pointer ) Do
  602.       Current_Saved_Screen := Current_Saved_Screen - 1;
  603.  
  604.    If Current_Saved_Screen > 0 Then
  605.       Current_Saved_Screen := Current_Saved_Screen - 1;
  606.  
  607.    Dispose( Saved_Screen_Pointer );
  608.  
  609. End    (* Restore_Screen *);
  610.  
  611. (*----------------------------------------------------------------------*)
  612. (*                Draw_Menu_Frame --- Draw a Frame                      *)
  613. (*----------------------------------------------------------------------*)
  614.  
  615. Procedure Draw_Menu_Frame( UpperLeftX,  UpperLeftY,
  616.                            LowerRightX, LowerRightY : Integer;
  617.                            Frame_Color, Title_Color : Integer;
  618.                            Menu_Title: AnyStr );
  619.  
  620. (*                                                                      *)
  621. (*     Procedure:  Draw_Menu_Frame                                      *)
  622. (*                                                                      *)
  623. (*     Purpose:    Draws a titled frame using PC graphics characters    *)
  624. (*                                                                      *)
  625. (*     Calling Sequence:                                                *)
  626. (*                                                                      *)
  627. (*        Draw_Menu_Frame( UpperLeftX,  UpperLeftY,                     *)
  628. (*                         LowerRightX, LowerRightY,                    *)
  629. (*                         Frame_Color, Title_Color : Integer;          *)
  630. (*                         Menu_Title: AnyStr );                        *)
  631. (*                                                                      *)
  632. (*           UpperLeftX,  UpperLeftY  --- Upper left coordinates        *)
  633. (*           LowerRightX, LowerRightY --- Lower right coordinates       *)
  634. (*           Frame_Color              --- Color for frame               *)
  635. (*           Title_Color              --- Color for title text          *)
  636. (*           Menu_Title               --- Menu Title                    *)
  637. (*                                                                      *)
  638. (*     Calls:   GoToXY                                                  *)
  639. (*              Window                                                  *)
  640. (*              ClrScr                                                  *)
  641. (*                                                                      *)
  642. (*     Remarks:                                                         *)
  643. (*                                                                      *)
  644. (*        The area inside the frame is cleared after the frame is       *)
  645. (*        drawn.  If a box without a title is desired, enter a null     *)
  646. (*        string for a title.                                           *)
  647.  
  648. Var
  649.    I  : Integer;
  650.    L  : Integer;
  651.    LT : Integer;
  652.  
  653. Begin (* Draw_Menu_Frame *)
  654.  
  655.                                    (* Move to top left-hand corner of menu *)
  656.    GoToXY( UpperLeftX, UpperLeftY );
  657.  
  658.    L  := LowerRightX - UpperLeftX;
  659.    LT := LENGTH( Menu_Title );
  660.                                    (* Adjust title length if necessary *)
  661.    If LT > ( L - 5 ) Then Menu_Title[0] := CHR( L - 5 );
  662.  
  663.                                    (* Color for frame                  *)
  664.    TextColor( Frame_Color );
  665.                                    (* Write upper left hand corner and title *)
  666.    If LT > 0 Then
  667.       Begin
  668.          Write('╒[ ');
  669.          TextColor( Title_Color );
  670.          Write( Menu_Title );
  671.          TextColor( Frame_Color );
  672.          Write(' ]');
  673.       End
  674.    Else
  675.       Write('╒════');
  676.                                    (* Draw remainder of top of frame *)
  677.  
  678.    For I := ( UpperLeftX + LT + 5 ) To ( LowerRightX - 1 ) Do Write('═');
  679.  
  680.    Write('╕');
  681.                                   (* Draw sides of frame *)
  682.  
  683.    For I := UpperLeftY+1 To LowerRightY-1 Do
  684.       Begin
  685.          GoToXY( UpperLeftX  , I );  Write( '│' );
  686.          GoToXY( LowerRightX , I );  Write( '│' );
  687.       End;
  688.  
  689.                                   (* Draw bottom of frame     *)
  690.  
  691.    GoToXY( UpperLeftX, LowerRightY );
  692.    Write( '╘' );
  693.  
  694.    For I := UpperLeftX+1 To LowerRightX-1 Do Write( '═' );
  695.    Write( '╛' );
  696.  
  697.                                    (* Establish scrolling window area *)
  698.  
  699.    Window( UpperLeftX+1, UpperLeftY+1, LowerRightX-1, LowerRightY-1 );
  700.  
  701.                                    (* Clear out the window area       *)
  702.    Clrscr;
  703.                                    (* Ensure proper color for text    *)
  704.    TextColor( Title_Color );
  705.  
  706. End   (* Draw_Menu_Frame *);
  707.  
  708. (*----------------------------------------------------------------------*)
  709. (*                Menu_Click --- Make short click noise                 *)
  710. (*----------------------------------------------------------------------*)
  711.  
  712. Procedure Menu_Click;
  713.  
  714. (*                                                                      *)
  715. (*     Procedure:  Menu_Click                                           *)
  716. (*                                                                      *)
  717. (*     Purpose:    Clicks Terminal Bell                                 *)
  718. (*                                                                      *)
  719. (*     Calling Sequence:                                                *)
  720. (*                                                                      *)
  721. (*        Menu_Click;                                                   *)
  722. (*                                                                      *)
  723. (*     Calls:    Sound                                                  *)
  724. (*               Delay                                                  *)
  725. (*               NoSound                                                *)
  726. (*                                                                      *)
  727.  
  728. Begin (* Menu_Click *)
  729.  
  730.   Sound( 2000 );
  731.   Delay( 10 );
  732.   NoSound;
  733.  
  734. End   (* Menu_Click *);
  735.  
  736. (*----------------------------------------------------------------------*)
  737. (*                Menu_Beep --- Ring Terminal Bell                      *)
  738. (*----------------------------------------------------------------------*)
  739.  
  740. Procedure Menu_Beep;
  741.  
  742. (*                                                                      *)
  743. (*     Procedure:  Menu_Beep                                            *)
  744. (*                                                                      *)
  745. (*     Purpose:    Rings Terminal Bell                                  *)
  746. (*                                                                      *)
  747. (*     Calling Sequence:                                                *)
  748. (*                                                                      *)
  749. (*        Menu_Beep;                                                    *)
  750. (*                                                                      *)
  751. (*     Calls:    None                                                   *)
  752. (*                                                                      *)
  753.  
  754. Begin (* Menu_Beep *)
  755.  
  756.    Write( Bell );
  757.  
  758. End   (* Menu_Beep *);
  759.  
  760. (*----------------------------------------------------------------------*)
  761. (*                Menu_Turn_On --- Highlight Menu Choice                *)
  762. (*----------------------------------------------------------------------*)
  763.  
  764. Procedure Menu_Turn_On( Menu: Menu_Type; Menu_Item : Integer );
  765.  
  766. (*                                                                      *)
  767. (*     Procedure:  Menu_Turn_On                                         *)
  768. (*                                                                      *)
  769. (*     Purpose:    Highlight a menu item using reverse video            *)
  770. (*                                                                      *)
  771. (*     Calling Sequence:                                                *)
  772. (*                                                                      *)
  773. (*        Menu_Turn_On( Menu: Menu_Type; Menu_Item : Integer );         *)
  774. (*                                                                      *)
  775. (*           Menu      : Menu containing item to highlight              *)
  776. (*           Menu_Item : Menu entry to highlight                        *)
  777. (*                                                                      *)
  778. (*     Calls:    GoToXY                                                 *)
  779. (*               RvsVideoOn                                             *)
  780. (*               RvsVideoOff                                            *)
  781. (*                                                                      *)
  782.  
  783. Begin (* Menu_Turn_On *)
  784.  
  785.    With Menu.Menu_Entries[ Menu_Item ] Do
  786.       Begin
  787.  
  788.          GoToXY( Menu_Item_Column, Menu_Item_Row );
  789.  
  790.          RvsVideoOn( Menu.Menu_Tcolor, Menu.Menu_Bcolor );
  791.  
  792.          Write( Menu_Item_Text );
  793.  
  794.          RvsVideoOff( Menu.Menu_Tcolor, Menu.Menu_Bcolor );
  795.  
  796.       End;
  797.  
  798. End   (* Menu_Turn_On *);
  799.  
  800. (*----------------------------------------------------------------------*)
  801. (*                Menu_Turn_Off --- UnHighlight Menu Choice             *)
  802. (*----------------------------------------------------------------------*)
  803.  
  804. Procedure Menu_Turn_Off( Menu: Menu_Type; Menu_Item : Integer );
  805.  
  806. (*                                                                      *)
  807. (*     Procedure:  Menu_Turn_Off                                        *)
  808. (*                                                                      *)
  809. (*     Purpose:    Removes highlighting from menu item                  *)
  810. (*                                                                      *)
  811. (*     Calling Sequence:                                                *)
  812. (*                                                                      *)
  813. (*        Menu_Turn_Off( Menu : Menu_Type; Menu_Item : Integer );       *)
  814. (*                                                                      *)
  815. (*           Menu        : Menu containing item to unhighlight          *)
  816. (*           RvsVideoOff : Menu entry to un-highlight                   *)
  817. (*                                                                      *)
  818. (*     Calls:    GoToXY                                                 *)
  819. (*               NormVideo                                              *)
  820. (*                                                                      *)
  821.  
  822. Begin (* Menu_Turn_Off *)
  823.  
  824.    With Menu.Menu_Entries[ Menu_Item ] Do
  825.       Begin
  826.  
  827.          GoToXY( Menu_Item_Column , Menu_Item_Row );
  828.  
  829.          RvsVideoOff( Menu.Menu_Tcolor, Menu.Menu_Bcolor );
  830.  
  831.          Write( Menu_Item_Text );
  832.  
  833.       End;
  834.  
  835. End   (* Menu_Turn_Off *);
  836.  
  837. (*----------------------------------------------------------------------*)
  838. (*                Menu_IBMCh --- Interpret IBM keyboard chars.          *)
  839. (*----------------------------------------------------------------------*)
  840.  
  841. Procedure Menu_IBMCh( Var C : Char );
  842.  
  843. (*                                                                      *)
  844. (*     Procedure:  Menu_IBMCh                                           *)
  845. (*                                                                      *)
  846. (*     Purpose:    Interpret IBM keyboard chars.                        *)
  847. (*                                                                      *)
  848. (*     Calling Sequence:                                                *)
  849. (*                                                                      *)
  850. (*        Menu_IBMCh( Var C : Char );                                   *)
  851. (*                                                                      *)
  852. (*           C --- On input, char following escape;                     *)
  853. (*                 on output, char revised to Wordstar command code.    *)
  854. (*                                                                      *)
  855. (*     Calls:   None                                                    *)
  856. (*                                                                      *)
  857.  
  858. Begin  (* Menu_IBMCh *)
  859.  
  860.    Read( Kbd , C );
  861.  
  862.    Case C Of
  863.  
  864.       'H' : C := Up_arrow;
  865.       'P' : C := Down_arrow;
  866.  
  867.    End;
  868.  
  869. End   (* Menu_IBMCh *);
  870.  
  871. (*----------------------------------------------------------------------*)
  872. (*                Menu_Display_Choices --- Display Menu Choices         *)
  873. (*----------------------------------------------------------------------*)
  874.  
  875. Procedure Menu_Display_Choices( Menu : Menu_Type );
  876.  
  877. (*                                                                      *)
  878. (*     Procedure:  Menu_Display_Choices                                 *)
  879. (*                                                                      *)
  880. (*     Purpose:    Displays Menu Choices                                *)
  881. (*                                                                      *)
  882. (*     Calling Sequence:                                                *)
  883. (*                                                                      *)
  884. (*        Menu_Display_Choices( Menu : Menu_Type );                     *)
  885. (*                                                                      *)
  886. (*           Menu --- Menu record to be displayed.                      *)
  887. (*                                                                      *)
  888. (*     Calls:   ClsScr                                                  *)
  889. (*              GoToXY                                                  *)
  890. (*              Draw_Menu_Frame                                         *)
  891. (*              Save_Screen                                             *)
  892.  
  893. Var
  894.    I    : Integer;
  895.    J    : Integer;
  896.    XL   : Integer;
  897.    YL   : Integer;
  898.    XR   : Integer;
  899.    YR   : Integer;
  900.    MaxX : Integer;
  901.    MaxY : Integer;
  902.  
  903. Begin (* Menu_Display_Choices *)
  904.  
  905.                                    (* Establish menu size *)
  906.  
  907.    XL := Menu.Menu_Column;
  908.    YL := Menu.Menu_Row;
  909.  
  910.    XR := LENGTH( Menu.Menu_Title ) + XL - 1;
  911.    YR := YL;
  912.  
  913.    MaxX := Menu.Menu_Width;
  914.    MaxY := Menu.Menu_Height;
  915.  
  916.    For I := 1 To Menu.Menu_Size Do
  917.       With Menu.Menu_Entries[I] Do
  918.       Begin
  919.          If Menu_Item_Row > MaxY Then MaxY := Menu_Item_Row;
  920.          J := LENGTH( Menu_Item_Text ) + Menu_Item_Column - 1;
  921.          If J > MaxX Then MaxX := J;
  922.       End;
  923.  
  924.    J := XL + MaxX - 1;
  925.    If J > XR Then XR := J;
  926.  
  927.    J := YL + MaxY - 1;
  928.    If J > YR Then YR := J;
  929.  
  930.    XL := XL - 4;
  931.    If XL < 0 Then XL := 0;
  932.  
  933.    YL := YL - 1;
  934.    If YL < 0 Then YL := 0;
  935.  
  936.    YR := YR + 1;
  937.    If YR > 25 Then YR := 25;
  938.  
  939.    If XR > 80 Then XR := 80;
  940.  
  941.                                    (* Save current screen image *)
  942.    Save_Screen( Saved_Screen );
  943.  
  944.                                    (* Draw the menu frame       *)
  945.    Draw_Menu_Frame( XL, YL, XR, YR, Menu.Menu_FColor, Menu.Menu_TColor,
  946.                     Menu.Menu_Title );
  947.  
  948.                                    (* Display Menu Entries *)
  949.  
  950.    For I := 1 To Menu.Menu_Size Do
  951.       With Menu.Menu_Entries[I] Do
  952.          Begin
  953.             GoToXY( Menu_Item_Column , Menu_Item_Row );
  954.             Write( Menu_Item_Text );
  955.          End;
  956.                                    (* Highlight Default Choice *)
  957.  
  958.    Menu_Turn_On( Menu, Menu.Menu_Default );
  959.  
  960. End   (* Menu_Display_Choices *);
  961.  
  962. (*----------------------------------------------------------------------*)
  963. (*                Menu_Get_Choice --- Get Menu Choice                   *)
  964. (*----------------------------------------------------------------------*)
  965.  
  966. Function Menu_Get_Choice( Menu: Menu_Type; Erase_After: Boolean ) : Integer;
  967.  
  968. (*                                                                      *)
  969. (*     Function:  Menu_Get_Choice                                       *)
  970. (*                                                                      *)
  971. (*     Purpose:   Retrieves Menu Choice from current menu               *)
  972. (*                                                                      *)
  973. (*     Calling Sequence:                                                *)
  974. (*                                                                      *)
  975. (*        Ichoice := Menu_Get_Choice( Menu       : Menu_Type;           *)
  976. (*                                    Erase_After: Boolean ) : Integer; *)
  977. (*                                                                      *)
  978. (*           Menu        --- Currently displayed menu                   *)
  979. (*           Erase_After --- TRUE to erase menu after choice found      *)
  980. (*           Ichoice     --- Returned menu item chosen                  *)
  981. (*                                                                      *)
  982. (*      Calls:   Menu_Click                                             *)
  983. (*               Menu_IBMCh                                             *)
  984. (*               Menu_Turn_Off                                          *)
  985. (*               Menu_Turn_On                                           *)
  986. (*                                                                      *)
  987. (*      Remarks:                                                        *)
  988. (*                                                                      *)
  989. (*         The current menu item is highlighted in reverse video.       *)
  990. (*         It may be chosen by hitting the return key.  Movement        *)
  991. (*         to other menu items is done using the up-arrow and           *)
  992. (*         down-arrow.                                                  *)
  993. (*                                                                      *)
  994.  
  995. Var
  996.    C       : Char;
  997.    Current : Integer;
  998.    Last    : Integer;
  999.  
  1000. Begin  (* Menu_Get_Choice *)
  1001.  
  1002.    Current := Menu.Menu_Default;
  1003.  
  1004.    Last    := Current - 1;
  1005.    If Last < 1 Then Last := Menu.Menu_Size;
  1006.  
  1007.    Repeat  (* Loop until return key hit *)
  1008.  
  1009.                                    (* Read a character *)
  1010.       Read( Kbd , C );
  1011.       Menu_Click;
  1012.                                    (* Convert character to menu code *)
  1013.       If C = Ch_Esc Then Menu_IBMCh( C );
  1014.                                    (* Process character *)
  1015.       Case C Of
  1016.  
  1017.          Down_arrow,
  1018.          Space_bar     : Begin (* Move down menu *)
  1019.                             Last    := Current;
  1020.                             Current := Current + 1;
  1021.                             If Current > Menu.Menu_Size Then
  1022.                                Current := 1;
  1023.                          End;
  1024.  
  1025.          Up_arrow      : Begin (* Move up menu *)
  1026.                             Last    := Current;
  1027.                             Current := Current - 1;
  1028.                             If Current < 1 Then
  1029.                                Current := Menu.Menu_Size;
  1030.                          End   (* Move up menu *);
  1031.  
  1032.          Else
  1033.             If C <> ch_cr Then Menu_Beep;
  1034.  
  1035.       End (* Case of C *);
  1036.                                    (* Highlight new menu choice *)
  1037.  
  1038.       If C In [ Up_arrow, Down_arrow, Space_bar ] Then
  1039.          Begin
  1040.             Menu_Turn_Off( Menu, Last    );
  1041.             Menu_Turn_On ( Menu, Current );
  1042.          End;
  1043.  
  1044.    Until C = ch_cr;
  1045.  
  1046.                                    (* Return index of chosen value *)
  1047.    Menu_Get_Choice := Current;
  1048.  
  1049.                                    (* Erase menu from display      *)
  1050.    If Erase_After Then
  1051.       Begin                        (* Restore previous screen      *)
  1052.          Restore_Screen( Saved_Screen );
  1053.                                    (* Restore global colors        *)
  1054.          Reset_Global_Colors;
  1055.       End;
  1056.  
  1057. End   (* Menu_Get_Choice *);
  1058.