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