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