home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / PULL55.ZIP / PULL55.DOC < prev    next >
Encoding:
Text File  |  1989-08-24  |  171.4 KB  |  3,882 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.                                    MULTI-LEVEL PULL-DOWN MENUS
  21.                                           USER'S GUIDE
  22.  
  23.                                            Version 5.5
  24.                                          August 24, 1989
  25.  
  26.  
  27.                        Copyright (C) 1987-1989 Eagle Performance Software
  28.                                       All Rights Reserved.
  29.  
  30.  
  31.  
  32.                                        _______
  33.                                   ____|__     |               (tm)
  34.                                --|       |    |-------------------
  35.                                  |   ____|__  |  Association of
  36.                                  |  |       |_|  Shareware
  37.                                  |__|   o   |    Professionals
  38.                                -----|   |   |---------------------
  39.                                     |___|___|    MEMBER
  40.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  41.  
  42.  
  43.  
  44.                                T A B L E   O F   C O N T E N T S
  45.  
  46.                 1. INTRODUCTION  . . . . . . . . . . . . . . . . . . . . . 4
  47.                      Features .  . . . . . . . . . . . . . . . . . . . . . 4
  48.                      Using the Manuals . . . . . . . . . . . . . . . . . . 4
  49.                      Licensing . . . . . . . . . . . . . . . . . . . . . . 5
  50.                      Customer Service  . . . . . . . . . . . . . . . . . . 5
  51.                      ASP . . . . . . . . . . . . . . . . . . . . . . . . . 6
  52.  
  53.                 2. GETTING STARTED . . . . . . . . . . . . . . . . . . . . 7
  54.                      Distribution Files  . . . . . . . . . . . . . . . . . 7
  55.                      Demonstration . . . . . . . . . . . . . . . . . . . . 7
  56.  
  57.                 3. PROGRAMMING MENUS . . . . . . . . . . . . . . . . . . . 11
  58.                      Using the Shell . . . . . . . . . . . . . . . . . . . 11
  59.                      Menu Modes  . . . . . . . . . . . . . . . . . . . . . 11
  60.                      Line Modes  . . . . . . . . . . . . . . . . . . . . . 14
  61.                      HiLite Control  . . . . . . . . . . . . . . . . . . . 15
  62.                      Adding Lines  . . . . . . . . . . . . . . . . . . . . 16
  63.                      Adding Menus  . . . . . . . . . . . . . . . . . . . . 17
  64.                      Adding Submenus . . . . . . . . . . . . . . . . . . . 18
  65.                      Help Messages . . . . . . . . . . . . . . . . . . . . 20
  66.                      Help Windows  . . . . . . . . . . . . . . . . . . . . 21
  67.                      Default Attributes  . . . . . . . . . . . . . . . . . 23
  68.                      Standard Borders  . . . . . . . . . . . . . . . . . . 24
  69.                      Control Flags . . . . . . . . . . . . . . . . . . . . 24
  70.                      Summary . . . . . . . . . . . . . . . . . . . . . . . 26
  71.  
  72.                 4. SCREEN DESIGN . . . . . . . . . . . . . . . . . . . . . 27
  73.                      Status Line . . . . . . . . . . . . . . . . . . . . . 27
  74.                      Top Line Menu . . . . . . . . . . . . . . . . . . . . 27
  75.                      Main Menu Row . . . . . . . . . . . . . . . . . . . . 27
  76.                      Submenu Row . . . . . . . . . . . . . . . . . . . . . 28
  77.                      Work Windows  . . . . . . . . . . . . . . . . . . . . 28
  78.                      Message Line  . . . . . . . . . . . . . . . . . . . . 28
  79.                      Help Windows  . . . . . . . . . . . . . . . . . . . . 29
  80.                      Start-Up Menu . . . . . . . . . . . . . . . . . . . . 29
  81.                      Overriding Defaults . . . . . . . . . . . . . . . . . 30
  82.                      Summary . . . . . . . . . . . . . . . . . . . . . . . 30
  83.  
  84.                 5. DATA WINDOWS  . . . . . . . . . . . . . . . . . . . . . 32
  85.                      Data Window Parts . . . . . . . . . . . . . . . . . . 32
  86.                      Data Window Record  . . . . . . . . . . . . . . . . . 32
  87.                      Data Window Variable  . . . . . . . . . . . . . . . . 33
  88.                      Fields  . . . . . . . . . . . . . . . . . . . . . . . 34
  89.                      Titles  . . . . . . . . . . . . . . . . . . . . . . . 35
  90.                      Editing Keys  . . . . . . . . . . . . . . . . . . . . 36
  91.                      Key Sets  . . . . . . . . . . . . . . . . . . . . . . 36
  92.                      Key Translation . . . . . . . . . . . . . . . . . . . 37
  93.                      Range Checking  . . . . . . . . . . . . . . . . . . . 38
  94.                      Help Messages . . . . . . . . . . . . . . . . . . . . 40
  95.                      Help Windows  . . . . . . . . . . . . . . . . . . . . 40
  96.                      Default Attributes and Border . . . . . . . . . . . . 40
  97.                      Default Location  . . . . . . . . . . . . . . . . . . 41
  98.  
  99.  
  100.                                                2
  101.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  102.  
  103.  
  104.                      Summary . . . . . . . . . . . . . . . . . . . . . . . 41
  105.  
  106.                 6. DATA ENTRY  . . . . . . . . . . . . . . . . . . . . . . 42
  107.                      Data Entry vs. Data Windows . . . . . . . . . . . . . 42
  108.                      Data Entry Record . . . . . . . . . . . . . . . . . . 42
  109.                      Adding Entries  . . . . . . . . . . . . . . . . . . . 43
  110.                      Displaying Fields . . . . . . . . . . . . . . . . . . 43
  111.                      Sequential Entry  . . . . . . . . . . . . . . . . . . 44
  112.                      Edit Mode . . . . . . . . . . . . . . . . . . . . . . 46
  113.                      Field Attributes  . . . . . . . . . . . . . . . . . . 47
  114.                      Single Entry  . . . . . . . . . . . . . . . . . . . . 47
  115.                      Summary . . . . . . . . . . . . . . . . . . . . . . . 47
  116.  
  117.                 7. WORK WINDOWS  . . . . . . . . . . . . . . . . . . . . . 48
  118.                      Making Steps  . . . . . . . . . . . . . . . . . . . . 48
  119.                      Reading the Keyboard  . . . . . . . . . . . . . . . . 49
  120.                      Multi-Level Windows . . . . . . . . . . . . . . . . . 51
  121.                      Managing Winddows . . . . . . . . . . . . . . . . . . 52
  122.  
  123.                 8. USER WINDOWS  . . . . . . . . . . . . . . . . . . . . . 54
  124.                      Pull-Down Directory . . . . . . . . . . . . . . . . . 54
  125.                      Interface . . . . . . . . . . . . . . . . . . . . . . 55
  126.  
  127.                 9. CONDITIONAL COMPILATION . . . . . . . . . . . . . . . . 57
  128.                      Define Symbols  . . . . . . . . . . . . . . . . . . . 57
  129.                      Recompiling . . . . . . . . . . . . . . . . . . . . . 57
  130.  
  131.                10. TROUBLE SHOOTING  . . . . . . . . . . . . . . . . . . . 58
  132.                      Goof Unit . . . . . . . . . . . . . . . . . . . . . . 58
  133.                      Far Addresses . . . . . . . . . . . . . . . . . . . . 58
  134.                      Multi-tasking . . . . . . . . . . . . . . . . . . . . 59
  135.                      Customer Service  . . . . . . . . . . . . . . . . . . 59
  136.  
  137.                 APPENDIX A: Other Products . . . . . . . . . . . . . . . . 60
  138.  
  139.                 APPENDIX B: Revision History . . . . . . . . . . . . . . . 62
  140.  
  141.                 APPENDIX C: Credits  . . . . . . . . . . . . . . . . . . . 63
  142.  
  143.                 APPENDIX D: Glossary . . . . . . . . . . . . . . . . . . . 64
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.                                                3
  162.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  163.  
  164.  
  165.            1.  I N T R O D U C T I O N
  166.  
  167.  
  168.            FEATURES
  169.  
  170.            Welcome to PULL multi-level pull-down menus!
  171.  
  172.            You have just obtained a copy of the highest performance pull-down menu
  173.            utilities available today for Turbo Pascal 5.5 (TP5).  Both novice and
  174.            professional programmers will appreciate these simple and very powerful
  175.            utilities that are fully featured and fully configurable.  They work on any
  176.            all IBM compatibles, including PS/2 and 3270 PC on any video page or any
  177.            text mode.
  178.  
  179.            Here are some of the features you will discover:
  180.  
  181.              - Uses the powerful routines of QWIK and WNDW.
  182.              - Work window(s) and complete interface for menus
  183.              - Pull-down menus with 3 menu modes and 8 line modes
  184.              - Pull-down file directory
  185.              - Highlighted command letters
  186.              - Unlimited levels of submenus
  187.              - Unlimited data entry windows for 9 types of data
  188.              - Data entry for the work window(s)
  189.                  Free field entry with either fixed column or flexible
  190.                  column length.
  191.                  Full editing capability including insert cursor mode
  192.                  Fields are easily selected with the cursor keys
  193.                  Automatic NumLock for numerical data entry
  194.                  Right or left justification for data entry output
  195.                  Error messages for invalid data entries
  196.                  Error messages for data entries out of range
  197.              - Automatic sizes and locations for menus
  198.              - Operation by cursor keys or command keys
  199.              - Pull/Pop between work window and nested submenu(s)
  200.              - Programmable control of pull and pop sequences
  201.              - Context-sensitive help windows
  202.              - Message lines for prompts and processing
  203.              - Writes direct to multi-tasking video buffers (MTVB).
  204.              - Full working shell for user development
  205.  
  206.            PULL has been designed with a fill-in-the-blank concept.  To get your
  207.            application up and running, you only need to fill in the appropriate
  208.            records or variables.
  209.  
  210.            TP4 - The units provided in this distributed file only work under TP5.
  211.            However, the source code, provided with registration, compiles equally well
  212.            under TP4.
  213.  
  214.  
  215.            USING THE MANUALS
  216.  
  217.            Disk Based Guides - The manuals for PULL are on disk so that you can
  218.            conveniently scan for the topic you are seeking.  You can do this with any
  219.            list or search utility with a search function.  You can also make a printed
  220.  
  221.  
  222.            Chapter 1, Introduction                                             Page 4
  223.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  224.  
  225.  
  226.            copy.  If you have not already printed this manual, refer to the READ.ME
  227.            file for instructions.  At the present time, no bound manuals are being
  228.            offered with registration.
  229.  
  230.            User's Guide - This manual, the one your are reading now, assumes that as a
  231.            programmer you are already familiar with Turbo Pascal 5.5, and that you
  232.            have a working knowledge of your disk operating system (DOS).  It also
  233.            assumes that you are familiar with QWIK screen utilities in QWIK55.ARC and
  234.            WNDW55.ARC.  This manual will provide the basic instructions for creating
  235.            and managing multi-level pull-down menus.  It also contains a tutorial to
  236.            guide you step-by-step to create your own application.
  237.  
  238.            Reference Guide - This manual describes in detail all procedures, functions
  239.            and variables used in PULL.  It is a alphabetically arranged for easy
  240.            access in a format similar to the TP5 manual.  Use this manual when you
  241.            have become familiar with the basic principles in the User's guide.
  242.  
  243.  
  244.            LICENSING
  245.  
  246.            Registration - These routines and the documentation have been released for
  247.            distribution as Shareware.  You have been given the chance to sample the
  248.            full capability of PULL without risk!  If you find that PULL is a valuable
  249.            tool, then you are expected to register.  You will find a reasonable
  250.            licensing schedule found in LICENSE.ARC to meet private or commercial
  251.            needs.  When registering, be sure to specify the version for Turbo Pascal
  252.            (such as TP4 or TP5) you wish to receive.
  253.  
  254.            Source Code - All registered users will receive source code when the signed
  255.            license agreement is returned with the registration.  All source code
  256.            compiles under TP4 as well as TP5.  The compiled units in the distributed
  257.            file were compiled with TP5 and only work in TP5.
  258.  
  259.  
  260.            CUSTOMER SERVICE
  261.  
  262.            If you have questions, comments, or suggestions, the Eagle can be contacted
  263.            by four means - (1) CompuServe, (2) telephone, (3) The Eagle BBS, or
  264.            (4) mail.
  265.  
  266.            CompuServe - The most dependable way to contact the Eagle is through
  267.            CompuServe.  James (Jim) H. LeMay has written the TP5 version of QWIK, but
  268.            the person to contact is Jordan Gallagher who can be reached on the Borland
  269.            Forum by typing GO BPROGA from the CompuServe main menu.  You will enter
  270.            the Forum for Turbo Pascal.  You can contact Jordan with his PPN number of
  271.            73557,2342.  Messages can also be left through EasyPlex.
  272.  
  273.            Telephone - Jordan can also be reached by phone at (214) 539-7855 on
  274.            weekdays and Saturday from 9:00 a.m. to 8:00 p.m CST.
  275.  
  276.            The Eagle BBS - You can also contact us on our 24-hour BBS at (214) 539-
  277.            9878, 1200/2400 N81.
  278.  
  279.            Mail - For registration or problems, please write:
  280.  
  281.  
  282.  
  283.            Chapter 1, Introduction                                             Page 5
  284.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  285.  
  286.  
  287.                Eagle Performance Software
  288.                P.O. Box 292786
  289.                Lewisville, TX  75029-2786
  290.  
  291.            In your written request for resolving problems, be sure to include:
  292.  
  293.              . A 5 1/4 inch diskette of compilable source code of the problem.
  294.              . The Eagle product and version number.
  295.              . The computer make and model.
  296.              . The type of video card, video monitor and keyboard.
  297.  
  298.  
  299.            ASP
  300.  
  301.            PULL is a Shareware program conforming to the standards of the Association
  302.            of Shareware Professionals (ASP).  You can get more information about ASP
  303.            by writing to:
  304.  
  305.              Association of Shareware Professionals
  306.              P.O. Box 5786
  307.              Bellevue,WA 98006
  308.  
  309.            This program is produced by a member of the Association of Shareware
  310.            Professionals (ASP).  ASP wants to make sure that the shareware principle
  311.            works for you.  If you are unable to resolve a shareware-related problem
  312.            with an ASP member by contacting the member directly, ASP may be able to
  313.            help.  The ASP Ombudsman can help you resolve a dispute or problem with an
  314.            ASP member, but does not provide technical support for member's products.
  315.            Please write to:
  316.  
  317.              ASP Ombudsman
  318.              P.O. Box 5786
  319.              Bellevue,WA 98006
  320.  
  321.            or send a CompuServe message via EasyPlex to ASP Ombudsman 7007,3536.
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344.            Chapter 1, Introduction                                             Page 6
  345.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  346.  
  347.  
  348.            2.  G E T T I N G   S T A R T E D
  349.  
  350.            This section will acquaint you with the files on distribution disk and show
  351.            you a couple of demonstrations to quickly see what PULL can accomplish.
  352.  
  353.  
  354.            DISTRIBUTION FILES
  355.  
  356.            In this version, PULL55.ARC contains:
  357.  
  358.              Read.   .me:   Note of printing instructions for manual.
  359.              Pull55  .doc:  This document - a user's guide to PULL.
  360.              PullRef .doc:  PULL Reference Guide document covering each
  361.                             routine and variable in detail.
  362.              Pull55  .tpu:  This unit has the full power of all of its
  363.                             capabilities.  Please note that because PULL55.TPU
  364.                             uses P55-VAR.INC all constants have been assigned.
  365.                             In order to make any changes in the data
  366.                             requirements, the complete source code will be
  367.                             required.
  368.              Pull55- .pas:  Shows the interface portion of PULL55.
  369.              P55-var .inc:  This file is the actual source code which lists
  370.                             all of the types, constants, and variables used
  371.                             for PULL55.TPU.
  372.              PullDemo.pas:  Fully functional working demo.
  373.              PullWork.pas:  Procedures for the main work window(s).
  374.              PullStat.pas:  Stats to configure the menus including global
  375.                             keys.
  376.              PullData.pas:  Data to configure data entry windows and fields.
  377.              PullDir-.pas:  Just interface for PULLDIR.PAS.
  378.              PullDir .tpu:  Unit for a pull-down file directory.
  379.              PullShel.arc:  Contains shell files to develop your own
  380.                             application.
  381.              Qwik55  .tpu:  Unit for quick screen writing.
  382.              Strs    .tpu:  Unit from QWIK55 for number-to-string conversions.
  383.              WndwP55 .tpu:  Multi-level virtual window unit for PULL.TPU.
  384.              Wutil   .tpu:  Independent utilities unit used in WNDW.TPU.
  385.              Goof    .pas:  Unit to display errors.
  386.              License .arc:  ARC file containing license agreement and ordering
  387.                             details.
  388.  
  389.  
  390.            DEMONSTRATION
  391.  
  392.            To get the feeling of the speed and features of PULL, let's run the
  393.            demonstration program that comes with the utilities.  Do the following
  394.            steps:
  395.  
  396.              1. Copy QWIK55.TPU to QWIK.TPU.
  397.              2. Copy WNDWp55.TPU (not WNDW55.TPU) to WNDW.TPU.  !!!
  398.              3. Copy PULL55.TPU to PULL.TPU.
  399.              4. Make, compile and run PULLDEMO.PAS.  (If you get an ERROR
  400.                 15 or 70, then steps 1-3 were not done carefully.)
  401.              5. Follow along in the overview below.
  402.  
  403.  
  404.  
  405.            Chapter 2, Getting Started                                          Page 7
  406.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  407.  
  408.  
  409.            Familiar Environment - You will probably feel right at home with the
  410.            environment created with PULL as it appears very similar to the TP5 editor.
  411.            It is interesting to note that PULL was developed with TP3 before TP4 was
  412.            ever released.  However, you should find the operation quite similar.
  413.            While you are running the demo, let's get familiar with the format and
  414.            operation of the environment and follow along with this overview:
  415.  
  416.              . Status Line - Row 1 just holds the title of this program.  It is
  417.                optional.
  418.  
  419.              . Top Line Menu - Row2 has been optionally assigned to be the top
  420.                line menu.  Press F10 at any time to access it.
  421.  
  422.              . Work Window - For this demo, Rows 4 to 23 has a 20x78 window for
  423.                the major part of your input/output.  You can also have multi-
  424.                level work windows.
  425.  
  426.              . Main Menu - To access a main menu, press RETURN or a command
  427.                letter (LTR) while the top line menu is highlighted on any
  428.                selection.  Or, you can use a combination of the ALT key and a
  429.                letter, such as Alt-F to get to the File menu.
  430.  
  431.              . Submenu - A submenu is a menu under a Main Menu.  To access a
  432.                submenu, press RETURN when the HiLite is at a menu line with the
  433.                three-bar symbol (which looks like a menu).  You can see three
  434.                levels of menus by pressing Alt-A/Tires/Brands.
  435.  
  436.            Local Keys and Letter Commands - While a window is shown, several keys
  437.            operate for just that window.  These keys can be listed in the message line
  438.            or they can be assumed to be the command letters highlighted on each menu
  439.            line.
  440.  
  441.              . Help Windows (F1) - While the Brands menu is still showing,
  442.                press F1 to get context-sensitive help.  A help window is
  443.                assigned to every window and menu.
  444.  
  445.              . Keys on Message Line - The bottom line of the CRT, being closest
  446.                to the keyboard, indicates the available keys that can be used
  447.                for the current context.  It is also used for help or error
  448.                messages.  While the help window is displayed, the next key
  449.                pressed will also pass through as a command.  For instance, press
  450.                RETURN now and see the help window removed and Firestone will
  451.                also become flagged.
  452.  
  453.              . Pop and Pull (F2) - F2 is a pop-and-pull key that toggles between
  454.                the pull-down menus and the work window.  Press F2 twice and you
  455.                will see that it remembers the last menu that was pulled.
  456.  
  457.              . Command Letters (LTR) - If you wanted to select WeatherGuard on
  458.                the Brands menu, just type the letter "W" which is highlighted.
  459.                These letters will work in any menu.
  460.  
  461.              . Cursor Keys - All of the cursor keys like the arrows, Home and
  462.                End keys, have assigned functions as well as the control-shifted
  463.                cursor keys.  You can discover what they do by experimenting with
  464.  
  465.  
  466.            Chapter 2, Getting Started                                          Page 8
  467.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  468.  
  469.  
  470.                them in a menu.
  471.  
  472.              . ESC Key - The ESC key always backs out of the current menu/window.
  473.  
  474.            Global Keys - Extended key combinations can be used to access any part of
  475.            the program.  In this demo, some have been assigned with the ALT key.
  476.            Press down ALT for a half second and see the available global keys listed
  477.            on the message line.
  478.  
  479.              . Directory (Alt-D) - Press Alt-D now to get a directory of your
  480.                disk.  If you would like to continue testing the directory, press
  481.                F1 for instructions.
  482.  
  483.              . Exit (Alt-X) -  To exit the program, one alternative is to use
  484.                Alt-X, but don't do it now.
  485.  
  486.              . Top Line Menu (F10) - As mentioned before, to get to the top line
  487.                menu, press F10 at any time.
  488.  
  489.            Data Entry Windows - Each menu can additionally pull down a data entry
  490.            window which is indicated with a small dot symbol on the menu line.  These
  491.            windows are fully configurable and have full editing capability.  They have
  492.            a free-field entry concept where a entire string is typed and edited before
  493.            entering.  Let's try a few fields.
  494.  
  495.              . Data Entry Types - Press Alt-E to see a menu of all the data
  496.                entry types available.  Press RETURN when the HiLite is at a menu
  497.                line with a small dot symbol.  Pressing RETURN again will exit
  498.                the window entering the data shown.  You can clear any data
  499.                entered by pressing ESC which also removes the window.
  500.  
  501.              . Editing - Press "I" while the main menu is still shown and enter
  502.                a value for the integer.  The virgin entry is highlighted until
  503.                you press a key.  The entry has full edit capability using the
  504.                cursor keys and some familiar WordStar control keys.  Press F1
  505.                for a list.  Even the insert mode is indicated with a half-block
  506.                cursor.
  507.  
  508.              . Options - All sorts of options are available for these windows
  509.                including range checking, fixed and flex fields, character
  510.                control and translation, automatic NumLock, justification,
  511.                titles, and attributes.
  512.  
  513.            Work Window Data Entry - The same procedures used for the data entry
  514.            windows can be used for entering data in the work windows.  In addition,
  515.            PULL has a smart algorithm that knows where several fields are on the
  516.            screen.  So moving from field to field with all the cursor keys is
  517.            intuitive.
  518.  
  519.              . Moving the HiLite - Press F2 to get back to the work window with
  520.                all of the data entry fields.  One field will be highlighted
  521.                which means it can be moved to select another field.  All of the
  522.                cursor keys move the HiLite including the control-shifted keys
  523.                and the Tab and Shift-Tab keys.  Move the HiLite to the Integer
  524.                field.
  525.  
  526.  
  527.            Chapter 2, Getting Started                                          Page 9
  528.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  529.  
  530.  
  531.  
  532.              . New Values - To enter a new value for the integer, simply start
  533.                typing some numbers and the HiLite will change colors.  You can
  534.                see that only numbers and the sign can be entered.  Press RETURN
  535.                to enter the new value or press ESC to restore the old value.
  536.  
  537.              . Editing - To edit the value currently shown in a field, press
  538.                RETURN or any WordStar control key.
  539.  
  540.            Other Features - There are many other features in the menus which will be
  541.            covered later including menu and line modes, and direct menu control.  You
  542.            may continue to discover other features in the demo if you want.  When
  543.            finished, press Alt-X to quit.
  544.  
  545.            Multi-tasking - This demo is already set to work in multi-tasking
  546.            environments compatible to DESQview, TaskView, and IBM 3270 PC.
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.            Chapter 2, Getting Started                                          Page 10
  589.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  590.  
  591.  
  592.            3.  P R O G R A M M I N G   M E N U S
  593.  
  594.            This section will get you familiar with the basics of window programming
  595.            by starting with very basic menus and then taking you step-by-step through
  596.            the full variety of options and modes available.
  597.  
  598.  
  599.            USING THE SHELL
  600.  
  601.            Shell Program - Let's experiment will PULL by developing our own
  602.            application to see how powerful it can be.  A shell program, which is a
  603.            bare bones application, has been provided with PULL in the file
  604.            PULLSHEL.ARC.  These files will help you get started for any application.
  605.            But for now, it can be an excellent learning tool.  To keep these files
  606.            separate from the PULLDEMO files, create another working directory and
  607.            unarchive the files in PULLSHEL.ARC.  The files to be extracted are:
  608.  
  609.              PullShel.pas
  610.              PullData.pas
  611.              PullStat.pas
  612.              PullWork.pas
  613.  
  614.            In addition, the follow files need to be on you unit path or copied into
  615.            the same directory:
  616.  
  617.              Qwik.tpu
  618.              Wndw.tpu
  619.              Wutil.tpu
  620.              Strs.tpu
  621.              Pull.tpu
  622.              Goof.pas
  623.  
  624.            Running the Shell - To make sure we have everything available, load
  625.            PULLSHEL.PAS, make, and run the program.  You should be able to operate
  626.            this program the same as PULLDEMO.PAS.  There are only two menus - First
  627.            and Quit.  To Quit, you can either use the Quit menu or use the global key
  628.            Alt-X.
  629.  
  630.            Features Available - The shell has every feature available.  They can be
  631.            added or eliminated.  However, some code cannot be entirely eliminated or
  632.            altered unless you are registered with the source code.  But let's continue
  633.            to see what the program can really do.
  634.  
  635.  
  636.            MENU MODES
  637.  
  638.            In this section, we will delve right into the menus and see how they
  639.            function and what changes can be made.  PULL has three menu modes for every
  640.            menu - ExecChoice, SingleChoice, and MultipleChoice.  These modes determine
  641.            how all the lines in the menu can interact as a whole.
  642.  
  643.            SingleChoice - You probably noticed that the First menu had one flag on it
  644.            because it was a SingleChoice menu.  One and only one item could be flagged
  645.            by pressing return on any one line.  Let's examine the data record of menu
  646.            and see how it was made to be single choice.
  647.  
  648.  
  649.            Chapter 3, Programming Menus                                        Page 11
  650.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  651.  
  652.  
  653.  
  654.              1. Load the file PULLSTAT.PAS into the TP editor.
  655.              2. Set PULLSHEL.PAS to be the Primary file.
  656.              3. Search for "with TopMenu".
  657.              4. See the following code:
  658.  
  659.                  GetMainMenu (FirstMenu);
  660.                  MenuMode := SingleChoice;
  661.                  SingleFlagLine := 3;
  662.                  Title   := 'First';
  663.                  Line[1] := 'A line';
  664.                  Line[2] := 'B line';
  665.                  Line[3] := 'C line';
  666.                  Line[4] := 'D line';
  667.                  DefaultLine := 2;
  668.                  MsgLineNum  := ord(MainML);
  669.                  HelpWndwNum := ord(MainMenuHW);
  670.                  SaveMainMenu;
  671.  
  672.            TopMenu - All these variables are fields in the current menu record called
  673.            TopMenu.  Notice that MenuMode is set to SingleChoice.  And that's how it
  674.            is done!  That's all it takes to tell PULL that all items on the menu are
  675.            single choice.  The program simply takes care of any selection.  So how do
  676.            you know which line has been selected?  Just get the value of
  677.            TopMenu.SingleFlagLine.  But also notice that SingleFlagLine has been
  678.            initially assigned to line 3.  Now you know why the "C line" is flagged
  679.            when the program first starts.  Setting SingleFlagLine is only needed for
  680.            the SingleChoice mode.  So how do you make it multiple choice?
  681.  
  682.            MultipleChoice - Let's change MenuMode to MultipleChoice and run the
  683.            program again.  Do it now.  This time you won't see any flags initially,
  684.            but each line can be toggled on and off by selecting any line with RETURN.
  685.            Ok, how do we know which line has been flagged now?  There are several more
  686.            variables in the menu record other than shown here.  Each Line has an
  687.            associated boolean variable called Flagged.  For example, if you want to
  688.            see if Line[3] has been flagged, just test and see if Flagged[3] is true.
  689.            But suppose we want some of those lines to be initially flagged?
  690.  
  691.            Flags - All the code we have seen is within a procedure called
  692.            GetUserPullStats which initializes all the menus from InitPull.  The
  693.            procedure GetMainMenu simply grabs a copy of the current menu record from
  694.            the heap which happens to be cleared with all zeros at this time.  That
  695.            means everything is a default value of zero unless we change it.  So, the
  696.            value of Flagged for each line is false.  Let's see if we can set a couple
  697.            of lines to be initially true by modifying the code to:
  698.  
  699.              ...
  700.              MenuMode := MultipleChoice;
  701.              SingleFlagLine := 3;
  702.              Title   := 'First';
  703.              Line[1] := 'A line';  Flagged[1] := true;
  704.              Line[2] := 'B line';  Flagged[2] := true;
  705.              ...
  706.  
  707.            Run the code again and verify that the first two lines are initially
  708.  
  709.  
  710.            Chapter 3, Programming Menus                                        Page 12
  711.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  712.  
  713.  
  714.            flagged.  If they are, then you are already getting the hang of how to
  715.            program pull-down menus!  PULL is based on a fill-in-the-blank concept
  716.            where you supply the data and the program takes care of the rest.
  717.  
  718.            Changed Flags - If there are several flags in the menu and just one is
  719.            changed, how can you know?  Anytime a flag is altered in the menu, the
  720.            variable "Changed" in the menu record is set to true which gives a quick
  721.            survey for any action that may be needed.  This value remains true until
  722.            your application program manually sets it false.
  723.  
  724.            Executing Procedures - But having a simple flag may not be enough for your
  725.            application.  Suppose you may also want to DO something as well.  So how
  726.            can we execute a procedure along with the selection?  Again, each line has
  727.            an associated execution pointer ProcPtr.  Simply assign any valid procedure
  728.            address to it and it executes it!  Try the following code:
  729.  
  730.              ...
  731.              MenuMode := MultipleChoice;
  732.              SingleFlagLine := 3;
  733.              Title   := 'First';
  734.              Line[1] := 'A line';  Flagged[1] := true;  ProcPtr[1] := @DummyProc;
  735.              Line[2] := 'B line';  Flagged[2] := true;  ProcPtr[2] := @DummyProc;
  736.              ...
  737.  
  738.            Run this code and you will find that every time line 1 or 2 is toggled, the
  739.            message "Processing ..." is displayed briefly on the message line which is
  740.            all this dummy procedure was supposed to do.  After it is processed, the
  741.            line is then flagged.  The procedure DummyProc is actually back a few lines
  742.            in the code just before GetUserPullStats.  This makes it very convenient to
  743.            have these procedures in the same file, but they don't have to be.  Since
  744.            the pointer is FAR, these procedures, which have been forced to FAR, can be
  745.            called from other units as well.
  746.  
  747.            Nil Pointer - So how come procedures were not executed before the pointers
  748.            were assigned?  Again, all values are zero until changed.  So, the pointer
  749.            was Nil.  The program simply ignores nil pointers and therefore does not
  750.            execute anything.
  751.  
  752.            ExecChoice - This mode only executes procedures with ProcPtr and just
  753.            ignores all flagging.  This is also the default mode.  Let's try this by
  754.            adding the following braces:
  755.  
  756.              ...
  757.            { MenuMode := MultipleChoice;
  758.              SingleFlagLine := 3; }
  759.              Title   := 'First';
  760.              Line[1] := 'A line';  Flagged[1] := true;  ProcPtr[1] := @DummyProc;
  761.              Line[2] := 'B line';  Flagged[2] := true;  ProcPtr[2] := @DummyProc;
  762.              ...
  763.  
  764.            Run it again.  You found that both line 1 and 2 executed the dummy
  765.            process, but the flags weren't toggled.  ExecChoice just ignores flagging.
  766.            Flags are usually not useful with ExecChoice mode and they can remain
  767.            false.  Lines 3 and 4 did absolutely nothing since the pointers were nil.
  768.  
  769.  
  770.  
  771.            Chapter 3, Programming Menus                                        Page 13
  772.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  773.  
  774.  
  775.            Default Mode - How come MenuMode was not assigned to ExecChoice and instead
  776.            was commented out with braces?  We could have if we wanted, but ExecChoice
  777.            is the default mode with an ordinal value of zero.  So, it saves code to
  778.            leave it out.
  779.  
  780.  
  781.            LINE MODES
  782.  
  783.            In this section, we will discover how each line in the menu can have one of
  784.            several different modes and then test each one to see its effect.
  785.  
  786.            Seven Line Modes - Not only does the whole menu have a mode, but each line
  787.            can have one of eight different modes:
  788.  
  789.              Choice     - permits flagging with Single- or MultipleChoice and
  790.                           executes the ProcPtr.
  791.              ExecOnly   - executes the ProcPtr without flagging.
  792.              NoChoice   - disabled by the your program.
  793.              Comment    - bypassed by the highlight.
  794.              Partition  - mid-menu horizontal border.
  795.              ToDataWndw - to pull a data entry window.
  796.              ToSubMenu  - to pull next submenu level.
  797.              ToUserWndw - like ExecOnly, and adds a Submenu symbol.
  798.  
  799.            These names are the actual identifiers used in LineModeType.  Each line has
  800.            an associated line mode saved in the variable LineMode.  For example, to
  801.            see what mode is on line 3, just check the value of LineMode[3].
  802.  
  803.            Choice - This is the default and, as you would guess, its ordinal value is
  804.            zero, so we never have to set it.  With this line mode and a menu mode of
  805.            SingleChoice or MultipleChoice, the line can be flagged like we have seen
  806.            in the previous examples.  But it is rare that any menu would have only
  807.            flags.  So, what other alternatives are there?
  808.  
  809.            ExecOnly - Let's suppose that just one of the lines on our First menu
  810.            should never be flagged, but all the others can.  How can we isolate it?
  811.            Back to the current example, revise the menu to be MultipleChoice with the
  812.            following changes:
  813.  
  814.              ...
  815.              MenuMode := MultipleChoice;
  816.            { SingleFlagLine := 3; }
  817.              Title   := 'First';
  818.              Line[1] := 'A line';  Flagged[1] := true;       ProcPtr[1] := @DummyProc;
  819.              Line[2] := 'B line';  LineMode[2] := ExecOnly;  ProcPtr[2] := @DummyProc;
  820.              ...
  821.  
  822.            Run it again and see that we can't toggle the flag on line 2 since it was
  823.            assigned as ExecOnly.  All it does is execute DummyProc even though the
  824.            menu mode is MultipleChoice.
  825.  
  826.            Comment - Suppose we wanted a title or some type of comment or help message
  827.            inside the menu itself.  That line should not be considered as a valid
  828.            choice.  In fact, the line should never be highlighted.  Try changing line
  829.            3 to the following:
  830.  
  831.  
  832.            Chapter 3, Programming Menus                                        Page 14
  833.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  834.  
  835.  
  836.  
  837.              ...
  838.              Line[2] := 'B line';  LineMode[2] := ExecOnly;  ProcPtr[2] := @DummyProc;
  839.              Line[3] := 'My comment'; LineMode[3] := Comment;
  840.              ...
  841.  
  842.            Run it and move the HiLite up and down.  You can see that the HiLite passes
  843.            right over line 3 and never accesses it.  By the way, notice also that the
  844.            first letter of "My comment" was not highlighted as a command letter.  In
  845.            fact, the entire line is a different attribute.  Also notice that the menu
  846.            has automatically increased in width to accommodate the new longest line.
  847.  
  848.            Partition - Sometimes it is easier to understand a menu when it is divided
  849.            into separate sections.  This can be done with the line mode of Partition.
  850.            Change LineMode[3] as follows:
  851.  
  852.              ...
  853.              Line[2] := 'B line';  LineMode[2] := ExecOnly;  ProcPtr[2] := @DummyProc;
  854.            { Line[3] := 'My comment'; }  LineMode[3] := Partition;
  855.              ...
  856.  
  857.            When you pull down the menu, you will see that line 3 has become an
  858.            extension of the border with the same style and attribute.  Moving the
  859.            highlight up and down will also show that the partition is passed over just
  860.            like a Comment.  Since Line[3] was unecessary and was commented out with
  861.            braces.
  862.  
  863.            NoChoice - Suppose you want a line to be temporarily unavailable because it
  864.            didn't apply at a given stage in your program.  You can overwrite the menu
  865.            record with a line mode of NoChoice which has the same effect as a Comment,
  866.            except you can enable it again by changing the line mode back to what it
  867.            was.  The command letter will again become available for that line.  In
  868.            contrast, Partition and Comment never have a command letter.
  869.  
  870.            Other Line Modes - There are three remaining modes, ToDataWndw, ToSubMenu,
  871.            and ToUserWndw, which will pull down another level of a menu or a window.
  872.            These can also be assigned to LineMode which will be covered in more detail
  873.            later.
  874.  
  875.  
  876.            HILITE CONTROL
  877.  
  878.            Highlight Line - The menu highlight bar is tracked by a variable called
  879.            HiLiteLine which is also in TopMenu.  Any time the highlight (also called
  880.            HiLite) is moved, this value is updated to the current line number and
  881.            saved.  So, upon re-entering the menu, the HiLite will still be on the same
  882.            line before as before.
  883.  
  884.            Default Line - The HiLite has to start somewhere.  In our current example,
  885.            the variable DefaultLine controls the initial line for the HiLite.  When
  886.            you run it, you can see that the first time the menu is pulled, line 2 is
  887.            highlighted.  Now move the HiLite down to line 4.  If you exit and re-enter
  888.            the menu, the HiLite is still on line 4.  So, we know that it always
  889.            remembers the current line.  But what is the default for DefaultLine?
  890.            Let's find out.  Comment out the following line:
  891.  
  892.  
  893.            Chapter 3, Programming Menus                                        Page 15
  894.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  895.  
  896.  
  897.  
  898.              ...
  899.              Line[4] := 'D line';
  900.            { DefaultLine := 2; }
  901.              MsgLineNum  := ord(MainML);
  902.              ...
  903.  
  904.            Run the program and you will find that the HiLite starts on line 1 and not
  905.            zero.  InitPull takes a second look at all menu records and makes sure that
  906.            all DefaultLines have been set.  If not, it sets DefaultLine to line 1.
  907.            But suppose we want the HiLite to start on the same line every time the
  908.            menu is pulled?
  909.  
  910.            Back To Default Line - You can force the HiLite to same initial line by
  911.            setting BackToDefault to true.  Let's try it on our current example:
  912.  
  913.              ...
  914.              Line[4] := 'D line';
  915.              DefaultLine := 2;
  916.              BackToDefault := true;
  917.              MsgLineNum  := ord(MainML);
  918.              ...
  919.  
  920.            When you pull-down the menu this time, the default line is 2.  But move the
  921.            HiLite to line 4 and exit the menu.  When the menu is pulled again, the
  922.            HiLite goes back to line 2.  Looking at the code, the Quit menu record is a
  923.            few lines down from the First menu.  There you can see that BackToDefault
  924.            is set to true for that menu as well which would keep a user from
  925.            inadvertently exiting the program.
  926.  
  927.  
  928.            ADDING LINES
  929.  
  930.            Adding Lines - To add more lines to a menu is a snap - just add a line.
  931.            Try the following modification on the First menu.
  932.  
  933.              ...
  934.              Line[4] := 'D line';
  935.              Line[5] := 'E line';   { add this line }
  936.              DefaultLine := 2;
  937.              ...
  938.  
  939.            The program automatically knows how many lines are in the menu so that it
  940.            is sized correctly and the HiLite knows how far to extend.  How many lines
  941.            can be added?
  942.  
  943.            Maximum Lines - To control the size of the menu record, the maximum number
  944.            of lines per menu is set by MaxMenuLines.  Go to a file called P55-VAR.INC
  945.            and you will find it to be the very first constant in the file and it has
  946.            been arbitrarily set to 15 lines.  This is one of several configuration
  947.            constants preset in PULL.  To be able to change these values, you must have
  948.            the source code to PULL which includes the file P55-VAR.INC.
  949.  
  950.            Maximum Characters - Each menu line is also limited to a maximum length.
  951.            You can discover this by testing this code:
  952.  
  953.  
  954.            Chapter 3, Programming Menus                                        Page 16
  955.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  956.  
  957.  
  958.  
  959.              ...
  960.              Line[4] := 'D line';
  961.              Line[5] := 'E line is longer than 20 characters';
  962.              DefaultLine := 2;
  963.              ...
  964.  
  965.            The menu is only wide enough to accommodate 20 characters which is also
  966.            preset with the constant MaxCharsPerLine.
  967.  
  968.  
  969.            ADDING MENUS
  970.  
  971.            Now that you are familiar with the scope of a single menu, you can take the
  972.            next step and learn how to include additional menus.
  973.  
  974.  
  975.            Main Menu Name - The first thing needed is a name for a new main menu.  On
  976.            the first page of PULLSTAT.PAS, find an enumerated type called
  977.            MainMenuNames and insert a new name called SecondMenu:
  978.  
  979.              MainMenuNames = (NoMainMenu,FirstMenu,SecondMenu,QuitMenu);
  980.  
  981.            It is important that these names are in order so that InitPull will
  982.            arrange them correctly.
  983.  
  984.            Main Menu Record - Now the record of SecondMenu can be added.  Between the
  985.            FirstMenu and QuitMenu records add the following code:
  986.  
  987.              GetMainMenu (SecondMenu);
  988.              MenuMode := MultipleChoice;
  989.              Title   := 'Second';
  990.              Line[1] := 'A2 line';
  991.              Line[2] := 'B2 line';
  992.              Line[3] := 'C2 line';
  993.              Line[4] := 'D2 line';
  994.              MsgLineNum  := ord(MainML);
  995.              HelpWndwNum := ord(MainMenuHW);
  996.              SaveMainMenu;
  997.  
  998.            Now run the program.  You can see that there are now three menus that can
  999.            be pulled down.  They are arranged in the order of the MainMenuNames.  Just
  1000.            for fun, let's reverse the names in MainMenuNames and see what happens:
  1001.  
  1002.              MainMenuNames = (NoMainMenu,SecondMenu,FirstMenu,QuitMenu);
  1003.  
  1004.            When you test this, you will find the two menus in different positions.
  1005.            This makes rearranging a snap.  We didn't even have to change anything
  1006.            about the MainMenu records themselves.
  1007.  
  1008.            Title - For a main menu, the title is required.  By default, the first
  1009.            letter is used for command letter after pressing F10.  Press F10 now and
  1010.            then press "S".  This will pull down the SecondMenu.  But what about the
  1011.            global key Alt-S?  Press F2 to get back to the work window and try Alt-S.
  1012.            Nothing happens.
  1013.  
  1014.  
  1015.            Chapter 3, Programming Menus                                        Page 17
  1016.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1017.  
  1018.  
  1019.  
  1020.            Global Key - To assign an extended key combination to this menu, go to the
  1021.            bottom of the file to the section called Check Global Keys.  In this code,
  1022.            an assignment can be made for this menu.  Insert the following line into
  1023.            the code:
  1024.  
  1025.              ...
  1026.              AltF: SetCmdSeq ('F');
  1027.              AltS: SetCmdSeq ('S');   { insert this line }
  1028.              AltQ: SetCmdSeq ('Q');
  1029.              ...
  1030.  
  1031.            This is part of a case statement, so the order is not important.  In
  1032.            addition, a value must be assigned to the constant AltS.  Back up a few
  1033.            lines and add:
  1034.  
  1035.              ...
  1036.              AltF = #33;
  1037.              AltS = #31;  { insert this line }
  1038.              AltQ = #45;
  1039.              ...
  1040.  
  1041.            Now run the code and try Alt-S again to find that it now works.  But what
  1042.            did we just do?  Any time an extended key is pressed at the keyboard, the
  1043.            program always passes through the procedure called CheckGlobalKeys.  If the
  1044.            extended keycode matches one in the case statement, the program sets a
  1045.            sequence of normal key codes that would be pressed just as if pressing F10
  1046.            and then "S".  The keycode constant can be referenced in Appendix C of the
  1047.            TP5 reference manual.
  1048.  
  1049.  
  1050.            ADDING SUBMENUS
  1051.  
  1052.            Every menu can pull down another submenu.  This section will show how to
  1053.            include one.  The method is much the same as with main menus.
  1054.  
  1055.  
  1056.            Submenu Name - Also at the beginning of PULLSTAT.PAS is an enumerated type
  1057.            called SubMenuNames which looks like:
  1058.  
  1059.              SubMenuNames = (NoSubMenu,MySubMenu);
  1060.  
  1061.            Let's go ahead and use the name MySubMenu.
  1062.  
  1063.            Submenu Record - Just after the main menu record QuitMenu is an area for
  1064.            submenus.  There is already a record made for MySubMenu and looks like the
  1065.            following:
  1066.  
  1067.              GetSubMenu (MySubMenu);
  1068.              MenuMode := SingleChoice;
  1069.              SingleFlagLine := 5;
  1070.              Line[1] := '1 line';
  1071.              Line[2] := '2 line';
  1072.              Line[3] := '3 line';
  1073.              Line[4] := '4 line';
  1074.  
  1075.  
  1076.            Chapter 3, Programming Menus                                        Page 18
  1077.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1078.  
  1079.  
  1080.              MsgLineNum  := ord(SubML);
  1081.              HelpWndwNum := ord(SubMenuHW);
  1082.              SaveSubMenu;
  1083.  
  1084.            It is exactly like the main menu record, except to get and save it,
  1085.            GetSubMenu and SaveSubMenu are used.  A title is not required for a
  1086.            submenu as InitPull automatically gives it the name of the parent menu.
  1087.            Now let's link the submenu to a main menu.
  1088.  
  1089.            Linking Menus - Choose SecondMenu line 2 for the line where MySubMenu is to
  1090.            be linked.  In the SecondMenu (not the submenu) record, modify line 2 to
  1091.            the following code:
  1092.  
  1093.              ...
  1094.              Title   := 'Second';
  1095.              Line[1] := 'A2 line';
  1096.              Line[2] := 'B2 line';  LineMode[2] := ToSubMenu;
  1097.                                     LinkNum [2] := ord(MySubMenu);
  1098.              ...
  1099.  
  1100.            Run the code and see that the submenu is pulled down when you press RETURN
  1101.            on line 2 of SecondMenu.  This is probably simpler than you thought!  You
  1102.            can also see a three-bar symbol on this line which indicates the line is
  1103.            linked to a submenu.  By setting the line mode to ToSubMenu, the program is
  1104.            prepared to pull-down another menu.  LinkNum identifies the record to be
  1105.            pulled which is MySubMenu.  LinkNum is a byte type so using Ord is
  1106.            required.
  1107.  
  1108.            Linking Configuration - The submenus link in a slide-up rather than a
  1109.            slide-under configuration.  Menus grow vertically as the list expands.  If
  1110.            the list gets too long, it can slide up when it hits the bottom of the
  1111.            screen.  This leaves both the main menu and submenu in full view.  In
  1112.            contrast, the data windows, which are covered later, use the slide-under
  1113.            configuration.
  1114.  
  1115.            Default Linking Direction - Most Submenu are linked to the main menu in a
  1116.            right-preferred arrangement.  When menus get crowded to the right, InitPull
  1117.            will automatically reverse to the left and all dot and 3-bar symbols will
  1118.            also appear on the left.  Each subequent Submenu will continue to link in
  1119.            the same direction as its parent as far as it can.
  1120.  
  1121.            Manual Linking Direction - As long as LinkDir is not specified like in our
  1122.            example, InitPull will configure it for you.  However, this may not be
  1123.            preferred in all cases.  To specify it manually, set the value of LinkDir
  1124.            in that menu record to Left or Right which forces all submenus to be linked
  1125.            in that direction.
  1126.  
  1127.            Global Key - Suppose this is a frequently used submenu and we want to
  1128.            assign an extended key, say Alt-M, to access it.  To do this, it is much
  1129.            the same as with a main menu, except there is an additional keystroke.  Add
  1130.            the following line to CheckGlobalKeys:
  1131.  
  1132.              AltM: SetCmdSeq ('SB');
  1133.  
  1134.            and include a value for the constant Alt-M:
  1135.  
  1136.  
  1137.            Chapter 3, Programming Menus                                        Page 19
  1138.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1139.  
  1140.  
  1141.  
  1142.              AltM = #50;  { the Alt-M  extended key code }
  1143.  
  1144.            When you run the program, pressing Alt-M will pull down both SecondMenu and
  1145.            MySubMenu just as if you had sequentially pressed F10, "S" and "B".
  1146.  
  1147.            SetCmdSeq - PULL saves the sequence of keystrokes for the current menu
  1148.            level in a global string variable called CmdSeq.  SetCmdSeq compares the
  1149.            current location of CmdSeq with the new destination and sets two variables
  1150.            for the shortest path - MoreCmdSeq and PopLevels.  This will be covered
  1151.            later in detail under the Control Flags section.
  1152.  
  1153.            SubSubmenus - SubSubmenus can be added in just the same way as submenus.
  1154.            In fact you could nest them as deep as you want.  InitPull expects the
  1155.            record names in SubMenuNames to be in a certain order so it can properly
  1156.            locate each one on the CRT.  Just be sure that the order is all Submenus
  1157.            first, all SubSub-menus second, all SubSubSubmenus third, etc.
  1158.  
  1159.  
  1160.            HELP MESSAGES
  1161.  
  1162.            Each menu has a help message that is displayed on the last line of the CRT
  1163.            where the application can indicate valid keys and status or error messages.
  1164.            In this section, you will discover how these messages can be linked to any
  1165.            menu while it is displayed.
  1166.  
  1167.  
  1168.            Reserved Messages - PULL has already included some predefined messages for
  1169.            several contexts including those for main menus and submenus.  In
  1170.            PULLSTAT.PAS, just below the last submenu record, you can find an array of
  1171.            MsgLines.  The ones reserved for main menus and submenus are MainML and
  1172.            SubML, respectively:
  1173.  
  1174.              MsgLine[ord(MainML)]:=' F1-help  F2-pop   LTR-cmd  ESC-return  '+
  1175.                                    '        '^[^Z' menus  '^X^Y'-hilight  CR-select';
  1176.              MsgLine[ord(SubML)] :=' F1-help  F2-pop   LTR-cmd  ESC-return  '+
  1177.                                    '                  '^X^Y'-hilight  CR-select';
  1178.  
  1179.            The concatenation is just so that it will fit within an 80 column width in
  1180.            the source code.  Back at the top of the file, you can find the enumerated
  1181.            type MsgLineNames that helps identify each message.  All the messages up to
  1182.            HelpML are reserved as PULL expects them to be in that order.  But new ones
  1183.            can be added.
  1184.  
  1185.            New Messages - To create a new message, just append a name in the
  1186.            MsgLineNames type and write out your new message.  Let's try it on the Quit
  1187.            menu by changing MsgLineNum in its menu record as follows:
  1188.  
  1189.              ...
  1190.              Line[2] := 'Quit';      ProcPtr[2] := @SetQuit;
  1191.              BackToDefault := true;
  1192.              MsgLineNum := ord(QuitML);
  1193.              ...
  1194.  
  1195.            Then append the name QuitML to the end of MsgLineNames:
  1196.  
  1197.  
  1198.            Chapter 3, Programming Menus                                        Page 20
  1199.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1200.  
  1201.  
  1202.  
  1203.              MsgLineNames = (NoML,WorkML,TopML,AltML,MainML,SubML,DW_ML,DE_ML,
  1204.                              SeqML,HelpML,ProcML,QuitML);
  1205.  
  1206.            And finally, let's create the message itself:
  1207.  
  1208.              MsgLine[ord(QuitML)] := ' Press "Q" if you are sure you want to quit.';
  1209.  
  1210.            Short messages are no problem, because PULL will clear the rest of the
  1211.            message line.  Run the program now and see that the new message appears
  1212.            when the Quit menu is pulled.  By now, you are seeing that pull-down menus
  1213.            can link other menus and messages quite easily.
  1214.  
  1215.            Alt Key Message - You may have noticed when you hold down the Alt for more
  1216.            than a half second, a message appears for the possible combinations.  When
  1217.            we created a submenu with global key access, it is not likely a first-time
  1218.            user would know the key was available.  The AltML message is reserved for
  1219.            this purpose.  Let's alter the line to:
  1220.  
  1221.              MsgLine[ord(AltML)] :=' Alt: F-First  M-MySubMenu              '+
  1222.                                    '                                 X-Exit';
  1223.  
  1224.            Run the program and hold down the Alt key to test the new message.
  1225.  
  1226.  
  1227.            HELP WINDOWS
  1228.  
  1229.            Many times the help message is not enough to fully explain the options
  1230.            available for the context.  In this section, you will discover how to
  1231.            create context-sensitive help windows and apply them to the menus.
  1232.  
  1233.  
  1234.            Help Window Record - Just as each menu has its own record, each Help Window
  1235.            also has one called HelpWndw.  There are only a couple of variables that
  1236.            need adjustment, to link in the number of lines to be included in the
  1237.            window.  Let's try creating a help window for a main menu.
  1238.  
  1239.            Example Window - Run the current example program again and test the F1
  1240.            key while the SecondMenu is pulled down.  You should see a two-line help
  1241.            window with the message "Main menu help message".  So, some help window is
  1242.            already there, but the message is just bare bones.  Let's find out how the
  1243.            message got there and alter it.
  1244.  
  1245.            Help Lines - In PULLSTAT.PAS after the MsgLine messages, there is another
  1246.            section for setting HelpLines.  You should be able to see the code:
  1247.  
  1248.              HelpLine[ord(HLm1)]:='Main menu help message';
  1249.              HelpLine[ord(HLmL)]:='';
  1250.  
  1251.            These are the actual messages you saw in the help window.  Each window can
  1252.            have a variable number of lines in the help window.  The program will
  1253.            automatically size the window to fit in all the lines.  Let's edit and add
  1254.            an extra line:
  1255.  
  1256.  
  1257.  
  1258.  
  1259.            Chapter 3, Programming Menus                                        Page 21
  1260.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1261.  
  1262.  
  1263.              HelpLine[ord(HLm1)]:='Main menu help message';
  1264.              HelpLine[ord(HLm2)]:='Press RETURN on the highlighted line to make';
  1265.              HelpLine[ord(HLmL)]:='your selection.';
  1266.  
  1267.            Since a new HelpLine name, HLm2, has been added, it must be inserted in the
  1268.            enumerated type HelpLineNames at the top of the file:
  1269.  
  1270.              ...
  1271.              HLt1,HLtL,        { Top Line Menu }
  1272.              HLm1,HLm2,HLmL,   { Main menu }        { Modify this line. }
  1273.              HLs1,HLsL         { Submenu }
  1274.              ...
  1275.  
  1276.            Now run the program and test the modified help window.  This time you
  1277.            should see the three lines.  With just a couple of changes, all help
  1278.            windows are still in order along with the contents because it is so easy to
  1279.            work with names instead of numbers.  How did the program know how many
  1280.            lines to display even though changes were made?
  1281.  
  1282.            Number of Help Lines - In the section just below the HelpLines, see the
  1283.            following code:
  1284.  
  1285.              ...
  1286.              HelpMsgLineNum := ord(HelpML);     { Standard message for a Help window }
  1287.              SetHelpLines (WorkWndwHW,HLw1,HLwL);
  1288.              SetHelpLines (TopMenuHW ,HLt1,HLtL);
  1289.              SetHelpLines (MainMenuHW,HLm1,HLmL);
  1290.              ...
  1291.  
  1292.            The call to SetHelpLines is a trivial procedure listed earlier in the code
  1293.            that simply sets the first and last line number into the help window record
  1294.            by using HelpLineNames.  Notice that the first and last line names end with
  1295.            1 and L respectively.  This makes it handy so these statements never need
  1296.            to be altered when new lines are added or inserted.
  1297.  
  1298.            Help Window Names - The window name is MainMenuHW which in listed the
  1299.            enumerated type HelpWndwNames at the beginning of PULLSTAT.PAS:
  1300.  
  1301.              HelpWndwNames = (NoHW,WorkWndwHW,TopMenuHW,MainMenuHW,SubMenuHW,
  1302.                               DataWndwHW);
  1303.  
  1304.            Help Window Record - A help window record is assigned to each one of these
  1305.            names.  In the SecondMenu record, we can find the window record name by
  1306.            examining the following:
  1307.  
  1308.              ...
  1309.              MsgLineNum  := ord(MainML);
  1310.              HelpWndwNum := ord(MainMenuHW);
  1311.              SaveMainMenu;
  1312.              ...
  1313.  
  1314.            So now we can finally see how this help window was assigned to the main
  1315.            menu.  Rather than having a standardized help window for each main menu as
  1316.            a whole, you can even create new ones just as new message lines were
  1317.            created:
  1318.  
  1319.  
  1320.            Chapter 3, Programming Menus                                        Page 22
  1321.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1322.  
  1323.  
  1324.  
  1325.              1. Append HelpWndwNames.
  1326.              2. Append HelpLineNames.
  1327.              3. Make HelpLine assignments.
  1328.              4. Use SetHelpLines to identify the first and last help lines.
  1329.              5. Assign the HelpWndwNum to the menu record.
  1330.  
  1331.            Help Message - Even the help window needs a help message.  One has already
  1332.            been standardized for you called HelpML.  InitPull will initialize all help
  1333.            windows to be assigned the message number in HelpMsgLineNum.
  1334.  
  1335.            Window Width - All help windows have a standard width which is set by a
  1336.            configuration constant in P55-VAR.INC called HelpCharsPerLine currently set
  1337.            at 50.  The program adds 2 to this value to leave a space between the left
  1338.            and right borders.  The value can only be changed with the source code.
  1339.  
  1340.            No Help Window - If there are selected records where a help window is not
  1341.            wanted, just set:
  1342.  
  1343.              HelpWndwNum := NoHW;
  1344.  
  1345.            Integrated Help Windows - This system will integrate the help windows into
  1346.            the EXE file.  With enumerated names, up to 255 lines can be included.  If
  1347.            you need more, it is suggested that you develop a disk-based help system
  1348.            which is currently beyond the scope of the this utility.
  1349.  
  1350.  
  1351.            DEFAULT ATTRIBUTES
  1352.  
  1353.            This section will show the variables used to create default attributes for
  1354.            menus, windows and messages.
  1355.  
  1356.  
  1357.            InitPull - At the very first of the procedure GetUserPullStats, several
  1358.            default attribute variables can be given assignments.  For instance,
  1359.            MainMenuWattr will be used by InitPull to give all main menus the same
  1360.            window attribute for Wattr in the menu record.  This saves you from having
  1361.            to make the same assignment to every menu record.
  1362.  
  1363.            Attributes - As a personal preference, many users prefer the screen to have
  1364.            different attribute when possible.  The following is the list of default
  1365.            attributes and what they affect:
  1366.  
  1367.                                Record
  1368.              Default variable  Variable   Description
  1369.              ----------------  ---------  ------------------------------------------
  1370.              TopLineMenuAttr   n/a        Full length of the top line menu.
  1371.              TopLineMenuHattr  n/a        Top line menu HiLite.
  1372.              TopLineMenuLattr  n/a        Top line menu command Letter.
  1373.  
  1374.              MainMenuWattr     Wattr      Main menu Window.
  1375.              MainMenuBattr     Battr      Main menu Border.
  1376.              MainMenuHattr     Hattr      Main menu HiLite.
  1377.              MainMenuLattr     Lattr      Main menu command Letter.
  1378.              MainMenuCattr     Cattr      Main menu Comment line.
  1379.  
  1380.  
  1381.            Chapter 3, Programming Menus                                        Page 23
  1382.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1383.  
  1384.  
  1385.  
  1386.              SubMenuWattr      Wattr      Sub menu Window.
  1387.              SubMenuBattr      Battr      Sub menu Border.
  1388.              SubMenuHattr      Hattr      Sub menu HiLite.
  1389.              SubMenuLattr      Lattr      Sub menu command Letter.
  1390.              SubMenuCattr      Cattr      Sub menu Comment line.
  1391.  
  1392.              HelpWndwWattr     Wattr      Help Window Window.
  1393.              HelpWndwBattr     Battr      Help Window Border.
  1394.  
  1395.              MsgLineAttr       n/a        Message line full length.
  1396.              ErrMsgAttr        n/a        Error messages.
  1397.              KeyStatusAttr     n/a        Key status of NumLock, Caps, and ScrollLock.
  1398.  
  1399.            Find the variable MainMenuBattr and modify it to inverse video:
  1400.  
  1401.              MainMenuBattr := LightGrayBG;
  1402.  
  1403.            When you run the program, you will find that every main menu has this new
  1404.            attribute.  All the other variables work similarly.
  1405.  
  1406.            Mono vs. Color - You probably noticed an "if" statement in the code testing
  1407.            the current video mode.  The results of this test allows you to configure
  1408.            the menus for either Monochrome or color monitors.  Refer to your technical
  1409.            reference manual for the effects of one attribute on either monitor.
  1410.  
  1411.  
  1412.            DEFAULT BORDERS
  1413.  
  1414.            This section will show the variables used to create default border styles
  1415.            for the menus and windows just like the attributes mentioned above.
  1416.  
  1417.  
  1418.            Border Styles - The following is a list of default border style variables
  1419.            and what they affect:
  1420.  
  1421.                                Record
  1422.              Default variable  Variable   Description
  1423.              ----------------  ---------  -----------------
  1424.              MainMenuBrdr      Border     All main menus.
  1425.              SubMenuBrdr       Border     All submenus.
  1426.              HelpWndwBrdr      Border     All help windows.
  1427.  
  1428.            The shell program has assigned MainMenuBrdr to a custom border UserBrdr1.
  1429.            Let's modify this to SingleBrdr:
  1430.  
  1431.              MainMenuBrdr := SingleBrdr;
  1432.  
  1433.            In addition, you can optionally comment out the assignment of UserBrdr1 in
  1434.            the previous line since it is no longer needed.  When the program is run,
  1435.            all main menus will now have a single-line border style including the
  1436.            partitions.
  1437.  
  1438.  
  1439.            CONTROL FLAGS
  1440.  
  1441.  
  1442.            Chapter 3, Programming Menus                                        Page 24
  1443.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1444.  
  1445.  
  1446.  
  1447.            The pull-down menus can be programmably controlled in your program by
  1448.            toggling various pull-down control flags.  This helps direct the users to
  1449.            the needed menus automatically instead of manually pressing a key sequence.
  1450.            In this section, you will discover these flags and what they control.  Save
  1451.            the shell program now for later use and get back to PULLDEMO for this
  1452.            section.
  1453.  
  1454.            Control Variables - Here is the list of variables that control the menus:
  1455.  
  1456.              PopToWorkWndw - (Type: boolean) if true, all menus are removed and
  1457.                              control is returned to the work window.
  1458.              PopToTop      - (Type: boolean) if true, control is set to the Top Line
  1459.                              menu.
  1460.              PopLevels     - (Type: byte) number of levels (or menus) to pop.
  1461.              Popped        - (function) pops all menus before execution of ExecPtr.
  1462.              MoreCmdSeq    - (Type: string) series of command letters to do after
  1463.                              popping.
  1464.              PullDown      - (Type: boolean) if true, the menus will be pulled down
  1465.                              according to MoreCmdSeq.
  1466.  
  1467.            Examples - Run PULLDEMO and access Alt-I/Update.  In the Update menu, there
  1468.            are six examples of how the menus can be controlled in combination with
  1469.            executing a ProcPtr.  Execute each of those six lines to see what they do.
  1470.            In PULLSTAT.PAS, search for "GetSubMenu (UpdateMenu)" and see that each
  1471.            line is executing ProcPtr in the menu, so let's find out what those
  1472.            procedures are doing.
  1473.  
  1474.            Process Then Pop - Back up until you find the ProcessThenPop procedure.
  1475.            Very simply, the program first executed DummyProc and then set
  1476.            PopToWorkWndw true.  When the flow of execution passes back through the key
  1477.            dispatcher, PULL will immediately pop all menus and return to the top work
  1478.            window.
  1479.  
  1480.            Pop Then Process - But suppose we want to do the reverse.  Anytime ProcPtr
  1481.            is used for execution, a copy of it is kept in the global variable ExecPtr.
  1482.            By using Popped, the function sets the appropriate flags to pop the menus.
  1483.            The first time Popped is tested, it is false.  So, DummyProc is not
  1484.            executed.  Once the menus are popped back to the work window, PULL executes
  1485.            ProcPtr again via ExecPtr.  This time Popped will be true and DummyProc
  1486.            will be executed.
  1487.  
  1488.            Pop, Process, and Pull - Let's go one step further and pull the same menus
  1489.            back down that were popped.  Looking few lines down further in the
  1490.            PopProcessAndPull procedure, the new line that was added is setting
  1491.            PullDown to true.  But how does the program know what menus to pull?  PULL
  1492.            keeps a copy of the last command sequence in the string MoreCmdSeq.  When
  1493.            PullDown is true, the menus are pulled down by MoreCmdSeq.  This is useful
  1494.            when there is something under the menus that needs to be changed like
  1495.            accessing another work window.
  1496.  
  1497.            Popping Levels - Or, if you just want to back up a number of menu levels,
  1498.            just specify the number of levels to pop with PopLevels.  In the procedure
  1499.            PopNumOfLevels, rather than making the menu completely disappear only to
  1500.            needlessly pull them back down again, this procedure pops back as far as it
  1501.  
  1502.  
  1503.            Chapter 3, Programming Menus                                        Page 25
  1504.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1505.  
  1506.  
  1507.            needs to go and then additionally pulls down another submenu (or data
  1508.            window).  This sequence is useful when you know exactly where you are and
  1509.            where you are going.
  1510.  
  1511.            Popping to New Menus - If you need to go to a new menu, you can use the
  1512.            flag PopToTop which will pop the menus up to the Top Line.  By setting
  1513.            PullDown true and MoreCmdSeq to the desired menu, you can get to the new
  1514.            destination like the procedure PopToNewMenu.
  1515.  
  1516.            Smart Pop and Pull - But suppose the menus will execute the same ProcPtr
  1517.            from three different locations in the menus, and still want it to appear
  1518.            smart like PopNumOfLevels does?  PULL has a procedure called SetCmdSeq that
  1519.            compares the current location, CmdSeq, with your destination.  It sets
  1520.            MoreCmdSeq and PopLevels to the shortest path.  In fact, PopNumOfLevels
  1521.            could have looked like:
  1522.  
  1523.              procedure PopNumOfLevels;
  1524.              begin
  1525.                PullDown := true;
  1526.                SetCmdSeq ('IY');
  1527.              end;
  1528.  
  1529.            The parameter for SetCmdSeq is the full sequence of command letters to be
  1530.            pressed from the Top Line.
  1531.  
  1532.            Sequential Data Windows - One application of these control flags may be
  1533.            sequential entry for data windows.  Access Alt-I/Date and press RETURN a
  1534.            few times to see how the menus are cycled in a loop for the date.  To see
  1535.            how it was done, follow the ProcPtrs in the DateMenu and see what flags
  1536.            were set.
  1537.  
  1538.  
  1539.            SUMMARY
  1540.  
  1541.            At this point in the tutorial, you've been able to master the configuration
  1542.            of the top line, main, and sub menus with all the menu modes and most of
  1543.            the line modes.  In addition, you found how to add menus and submenus
  1544.            and assign help messages and help windows.  You changed the appearance of
  1545.            the menus with attributes and borders.  You could even programmably control
  1546.            the sequence of menus that were pulled down.  These were all accomplished
  1547.            by just filling out the appropriate variables.
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.            Chapter 3, Programming Menus                                        Page 26
  1565.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1566.  
  1567.  
  1568.            4.  S C R E E N   D E S I G N
  1569.  
  1570.            You are now at a point where you understand most of the fundamental
  1571.            features in PULL.  In this section, you will discover how to control the
  1572.            arrangement of the major components of full screen design.  You will be
  1573.            able to relocate the Status line, Top Line menu, Main menus, Work
  1574.            window(s), and Message line.  Arrangement of the components will depend on
  1575.            the human factors needed for your application.
  1576.  
  1577.  
  1578.            STATUS LINE
  1579.  
  1580.            The Status line is a row that you can reserve for pertinent information.
  1581.            In the shell program, the status line is assumed to be row 1 where a
  1582.            program name, title, and copyright were placed.  In the TP5 environment,
  1583.            row 2 is the status line for line, column, and insert status.  Actually,
  1584.            PULL does nothing to program this line, but PULL was designed to work
  1585.            around it.
  1586.  
  1587.  
  1588.            TOP LINE MENU
  1589.  
  1590.            Showing the Top Line - The top line menu is automatically created by
  1591.            assembling the titles from each main menu.  So, the string is already
  1592.            created for you in the string variable TopLineStr.  To write this string to
  1593.            the screen, simply call ShowTopLine.  But where is it placed?
  1594.  
  1595.            Top Line Placement - Back in GetPullUserStat, search for the variable
  1596.            TopLineRow.  It is found in a section called Top Line Defaults.  This is
  1597.            the variable that determines where the top line is placed:
  1598.  
  1599.              TopLineRow := 2;     { Top Line menu to appear on row 2. }
  1600.  
  1601.            Let's try reversing the Status line and the Top line menu in the shell
  1602.            program.  Set TopLineRow to 1 and then look in PULLSHEL.PAS and modify the
  1603.            row of the Status line to 2:
  1604.  
  1605.              WWrite ( 2, 1,'PULLSHELL v5.5            Multi-level Pu'+
  1606.                            'll-down Menus       Copr 1989  J H LeMay');
  1607.  
  1608.            Now run the program and see both lines reversed, but when the main menus
  1609.            are pulled, they are still on row 3.  How can they be moved?
  1610.  
  1611.  
  1612.            MAIN MENU ROW
  1613.  
  1614.            Main Menu Row - The row on which the main menus appear is controlled by
  1615.            the value of MainMenuRow.  The Main menus do not have to be attached to Top
  1616.            Line menu and can appear on any row provided they do not interfere with
  1617.            the Message line.
  1618.  
  1619.            Moving the Row - Let's shift the Main menus back up so they will appear
  1620.            to be attached to the Top Line menu.  In PULLSTAT.PAS, search for:
  1621.  
  1622.              MainMenuRow := 3;  { First row of main menus to appear on row 3 }
  1623.  
  1624.  
  1625.            Chapter 4, Screen Design                                            Page 27
  1626.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1627.  
  1628.  
  1629.  
  1630.            and change it to 2.  Run the program again to see that the main menus pull-
  1631.            down now on row 2.  But also check the submenu by pressing Alt-M.  Even the
  1632.            submenu is correctly placed!  InitPull accommodates the changes.
  1633.  
  1634.  
  1635.            SUBMENU ROW
  1636.  
  1637.            SubMenu Row - Try to arrange the lines in your menus that link submenus so
  1638.            that they are as high in the menu as practical.  Otherwise, long menus will
  1639.            bottom out on the CRT and PULL will be sliding up the menus to keep them in
  1640.            view.  PULL handles this well by using the slide-up configuration, but the
  1641.            menus will not appear to have much foresight in your design.  The
  1642.            Alt-A/Tires/Brands menu is a good example of keeping menus high.
  1643.  
  1644.  
  1645.            WORK WINDOWS
  1646.  
  1647.            Window Modes - The major portion of the screen is intended to be the work
  1648.            window for your application.  This area can have one or more windows and
  1649.            they can be in any window mode that you chose - even virtual.  Usually one
  1650.            of the modes can be PermMode since there is no data to save under the
  1651.            screen, but with a TSR, you may need to save the screen, too.
  1652.  
  1653.            Window Size - The example in the shell program uses a 22x80 PermMode window
  1654.            with border.  Let's get rid of the Status line, make the window larger, and
  1655.            at the same time, take off the double border.  In PULLSHEL.PAS, comment out
  1656.            the Status line with braces and modify the MakeWindow statement to the
  1657.            following:
  1658.  
  1659.            { WWrite ( 1, 1,'PULLSHELL v5.5            Multi-level Pu'+
  1660.                            'll-down Menus       Copr 1989  J H LeMay'); }
  1661.              ShowTopLine;
  1662.              SetWindowModes (PermMode);
  1663.              MakeWindow (2,1,CRTrows-2,CRTcols,White+BlueBG,White+BlueBG,NoBrdr,
  1664.                          Window1);
  1665.  
  1666.            Running the program, you will see the work window took up all but the Top
  1667.            Line menu in Row 1 and the Message line on the last row.  Notice also that
  1668.            the contents of the window also moved because they have window-relative
  1669.            coordinates.  This shows you the flexibility of your screen design.
  1670.  
  1671.  
  1672.            MESSAGE LINE
  1673.  
  1674.            Message Line - This is the line on which all messages will appear and is
  1675.            usually in reference to CRTrows to accommodate different video modes.  If
  1676.            the message line is intended to list key commands, for human factor
  1677.            reasons, it is best to keep it near the bottom row.
  1678.  
  1679.            Location - The location of the line is set by the variable MsgLineRow in
  1680.            GetUserPullStats.  To whatever line it is assigned, be sure that there is
  1681.            no possibility that it may be covered by other windows.  You may need to
  1682.            set the window margins to do this.
  1683.  
  1684.  
  1685.  
  1686.            Chapter 4, Screen Design                                            Page 28
  1687.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1688.  
  1689.  
  1690.  
  1691.            HELP WINDOWS
  1692.  
  1693.            There are two defaults that can be set for the Help windows - the bottom
  1694.            row and the window modes.  This section shows how these can be modified.
  1695.  
  1696.            Bottom Row - All help windows are centered column-wise on the CRT.
  1697.            However, the default bottom row of the window is assigned to HelpBottomRow
  1698.            and is allowed to grow upward.  This variable is used to calculate the
  1699.            upper left corner of the window and sets the Row and Col for each help
  1700.            window record.
  1701.  
  1702.            Window Modes - The current example program uses a shadow with zoom effect
  1703.            when the help window appears.  The cursor mode is also turned off.  This
  1704.            default is assigned to HelpWndwModes which in turn assigns it to HWmodes in
  1705.            each help window record.
  1706.  
  1707.            Example - In the shell program, search for HelpWndwModes and modify the
  1708.            code to the following:
  1709.  
  1710.              ...
  1711.              HelpWndwModes := CursorOffMode;
  1712.              HelpBottomRow := CRTrows-10;
  1713.              ...
  1714.  
  1715.            When you test any help window this time, the window will appear instantly
  1716.            without the zoom effect and is placed higher from the bottom.
  1717.  
  1718.  
  1719.            START-UP MENU
  1720.  
  1721.            Control Variables - When the program first starts, you can also have the
  1722.            program pull down any menu using the Top Line variables MPulled, PullDown,
  1723.            and MoreCmdSeq.  Search again for TopMenuRow and see this code:
  1724.  
  1725.              TopMenuRow := 1;
  1726.              MPulled    := ord(FirstMenu);
  1727.              MoreCmdSeq := 'F';
  1728.              PullDown   := false;
  1729.  
  1730.            MPulled - This is initial assignment for the main menu title that would be
  1731.            highlighted when pressing F10 for the first time.
  1732.  
  1733.            MoreCmdSeq - This is the actual variable that is set by the global key
  1734.            routine SetCmdSeq.  When F2 is pressed for the first time, it would emulate
  1735.            pressing F10 and "F" from the keyboard as if it remembered the last
  1736.            sequence of keystrokes.  MoreCmdSeq can have as many characters as needed
  1737.            to get down to the desired menu or window.  It is a good practice to make
  1738.            sure the first character matches the MPulled menu.
  1739.  
  1740.            PullDown - If this is true, the program will pull-down the menus just as if
  1741.            F2 had been pressed so that the menus pulled match the sequence in
  1742.            MoreCmdSeq.  Try setting PullDown to true and see if FirstMenu is indeed
  1743.            pulled.
  1744.  
  1745.  
  1746.  
  1747.            Chapter 4, Screen Design                                            Page 29
  1748.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1749.  
  1750.  
  1751.  
  1752.            OVERRIDING DEFAULTS
  1753.  
  1754.            PULL configures almost everything automatically, but sometimes things don't
  1755.            always fit the mold.  This section will show you how to override the
  1756.            settings before and after PULL has configured them.
  1757.  
  1758.  
  1759.            GetUserPullStats - Row/Col locations for submenus are located by default at
  1760.            run time with the slide-up configuration when these values remain zero, and
  1761.            likewise DWrow/DWcol for data windows for slide-under.  You can override
  1762.            PULL and locate them absolutely by giving them non-zero values in the
  1763.            procedure GetUserPullStats.
  1764.  
  1765.            Submenu Location - If submenus are unusually wide and will not fit in the
  1766.            slide-up configuration, PULL will terminate the program with a warning
  1767.            message to let you know of the problem.  If you set the variable
  1768.            LocationWarning false in GetUserPullStats, you can go ahead and test all
  1769.            submenus to see the one not fitting the slide-up configuration.  PULL will
  1770.            attempt slide-under as a second best.  If it still doesn't fit, then you
  1771.            need an override for the Row and Col setting.  If you are satisfied with
  1772.            the menu locations, you can optionally set LocationWarning false.  But be
  1773.            sure to check all the menus on the CRT to make sure they have been properly
  1774.            placed.
  1775.  
  1776.            GetOverrideStats - This procedure in PULLSTAT is executed after all the
  1777.            automatic configuration has been done.  If there are exceptions in your
  1778.            program, you can assign them inside this procedure.  For just a few
  1779.            changes, you can edit the records right in the heap.  Take a look at this
  1780.            procedure in PULLSTAT for PULLDEMO.  What kind of things would you
  1781.            typically change?
  1782.  
  1783.            Menu Command Letters - Not all menus use the first letter for the command
  1784.            letter.  What happens when two lines start with the same one?  Only the
  1785.            first one will ever be reached.  So, the command letters must be changed.
  1786.            The variable in the menu record that contains these letter is CmdLtrs.  For
  1787.            instance, the command letters for FirstMenu are 'ABCD' where character one
  1788.            corresponds to line 1, etc.  They are always upper case in this string, but
  1789.            can be lower case in the menu.  So, you can edit this string to whatever
  1790.            your command letters need to be.  In addition, that letter will also be
  1791.            highlighted in the menu.  Inaccessible line modes like Comment and
  1792.            Partition replace the command letter with #00.
  1793.  
  1794.            Top Line Command Letters - You can also do the same with the Top Line
  1795.            command letters which are kept in a global variable called TopCmdLtrs.
  1796.  
  1797.            Attributes and Borders - Sometimes the default attributes and borders need
  1798.            to be changed in a place or two.  GetOverrideStats is the place to make
  1799.            those changes.
  1800.  
  1801.  
  1802.            SUMMARY
  1803.  
  1804.            If you have completed the tutorial with the shell program up to this point,
  1805.            you should now have enough confidence with the major components of screen
  1806.  
  1807.  
  1808.            Chapter 4, Screen Design                                            Page 30
  1809.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1810.  
  1811.  
  1812.            design.  You can now develop a concept for your application that can best
  1813.            be suited the needs of your users.  If you would like to stop now, save the
  1814.            shell program so that it can to be used later in the following sections.
  1815.  
  1816.  
  1817.  
  1818.  
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.  
  1825.  
  1826.  
  1827.  
  1828.  
  1829.  
  1830.  
  1831.  
  1832.  
  1833.  
  1834.  
  1835.  
  1836.  
  1837.  
  1838.  
  1839.  
  1840.  
  1841.  
  1842.  
  1843.  
  1844.  
  1845.  
  1846.  
  1847.  
  1848.  
  1849.  
  1850.  
  1851.  
  1852.  
  1853.  
  1854.  
  1855.  
  1856.  
  1857.  
  1858.  
  1859.  
  1860.  
  1861.  
  1862.  
  1863.  
  1864.  
  1865.  
  1866.  
  1867.  
  1868.  
  1869.            Chapter 4, Screen Design                                            Page 31
  1870.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1871.  
  1872.  
  1873.            5.  D A T A   W I N D O W S
  1874.  
  1875.            Often when a menu line is selected from a menu, a means is needed to enter
  1876.            data into the application such as numbers or file names.  PULL already has
  1877.            powerful utilities to do this for free-field data entry including flex
  1878.            fields, set checking, key translation, and range checking for nine types of
  1879.            data.
  1880.  
  1881.  
  1882.            DATA WINDOW PARTS
  1883.  
  1884.            There are two parts to a data entry window - the data entry field and the
  1885.            window.
  1886.  
  1887.            Data Entry Field - As the name implies, this is the place where characters
  1888.            are allowed to be entered for the data.  This is also called entry or field
  1889.            for short.
  1890.  
  1891.            Data Window - The window is the border and spacing surrounding the field.
  1892.            Using the term data window loosely refers to both the field and the window
  1893.            together.
  1894.  
  1895.  
  1896.            DATA WINDOW RECORD
  1897.  
  1898.            The arrangement of the records for data windows is very similar to the way
  1899.            menu records have been done.  So, the same concept of fill-in-the-blank is
  1900.            used.  In this section, you will find how these records can be filled out
  1901.            in the program.
  1902.  
  1903.  
  1904.            Top Data Window - Let's find the data window record and see what it
  1905.            contains:
  1906.  
  1907.              1. Load the file PULLDATA.PAS into the TP editor.
  1908.              2. Set PULLSHEL.PAS to be the Primary file.
  1909.              3. Search for "with TopDataWndw"
  1910.              4. See the following code:
  1911.  
  1912.                  GetDataWndw (ord(aByteDW));         { Just gets cleared DataWndw }
  1913.                  VarAddr       := @aByte;
  1914.                { TypeOfData    := Bytes; }           { This is the default }
  1915.                  Field         := 3;
  1916.                { MsgLineNum    := ord(DW_ML); }      { This is the default }
  1917.                { HelpWndwNum   := ord(DataWndwHW); } { This is the default }
  1918.                  SaveDataWndw;                       { Saves it in the heap }
  1919.  
  1920.            In the tutorial program of PULLSHEL.PAS, the program does not have any data
  1921.            windows linked to the menus yet, but this record has already been written
  1922.            to speed things along.  As you can see, only four lines were needed to be
  1923.            set in the Data Window record which is named aByteDW.  Let's go ahead and
  1924.            link this record into one of the menus.
  1925.  
  1926.            Linking Data Windows - Go back to PULLSTAT.PAS to find the FirstMenu record
  1927.            and revise it to add this data window to line 3:
  1928.  
  1929.  
  1930.            Chapter 5, Data Windows                                             Page 32
  1931.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1932.  
  1933.  
  1934.  
  1935.              GetMainMenu (FirstMenu);
  1936.              ...
  1937.              Line[1] := 'A line';
  1938.              Line[2] := 'B line';
  1939.              Line[3] := 'Enter Byte';  LineMode[3] := ToDataWndw;
  1940.                                        LinkNum [3] := ord(aByteDW);
  1941.              Line[4] := 'D line';
  1942.              ...
  1943.  
  1944.            When the program is run, pressing RETURN on line 3 will pull-down the data
  1945.            entry window.  The variable is a byte type which it was assigned by default
  1946.            in the data window record.  Go ahead and experiment with the entry by
  1947.            making mistakes such as a number over 255.  When you get an error message,
  1948.            just press ESC.  For the full list of editing keys, press F1 for the help
  1949.            window.
  1950.  
  1951.            Window Location - Notice that the location of the window is immediately
  1952.            underneath the HiLite and shifted slightly to the right.  This is called a
  1953.            slide-under configuration.  Since there is only one row in a Data Window,
  1954.            they tend to grow horizontally.   Should the window be too long for the
  1955.            right side of the screen, the window would then slide under the HiLite to
  1956.            the left until it fit.  This location is determined at run time.
  1957.  
  1958.            Justification - The entry is always left justified since it is an input-
  1959.            only window.
  1960.  
  1961.            Line Mode - If you remember about line modes, we did not get a chance to
  1962.            test ToDataWndw.  So, now you can see that this instructs PULL that a Data
  1963.            Window is linked to the menu and it then uses the named data window record
  1964.            for the window.
  1965.  
  1966.            Link Number - The number of the Data Window record linked is of course the
  1967.            value of the name aByteDW.  Again, names are used to easily arrange and
  1968.            identify the contents of the record.  So, how is the name assigned?
  1969.  
  1970.            Data Window Names - At the top of the file PULLSTAT.PAS (not PULLDATA.PAS),
  1971.            the enumerated type DataWndwNames has the following list:
  1972.  
  1973.              DataWndwNames = (NoDW,aByteDW);
  1974.  
  1975.            Only one window name has been assigned and that is the one being tested.
  1976.            There are no reserved names except NoDW since the window numbers are 1-
  1977.            based.  Notice that PULLDATA uses PULLSTAT.  Since DataWndwNames is in the
  1978.            interface, the names can also be used in PULLDATA.  Ok, the data is plugged
  1979.            into the window, but where is it being stored?
  1980.  
  1981.  
  1982.            DATA WINDOW VARIABLE
  1983.  
  1984.            Variable Address - To know where the variable is located, the record uses a
  1985.            pointer to the variable location.  The variable used in this window is
  1986.            aByte which is a typed constant declared at the beginning of PULLDATA.PAS
  1987.            and given a value of 100.  To get the address of the variable, you just
  1988.            place the "@" operator in front of the variable and it returns its FAR
  1989.  
  1990.  
  1991.            Chapter 5, Data Windows                                             Page 33
  1992.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  1993.  
  1994.  
  1995.            address.
  1996.  
  1997.            Type of Data - Because a pointer is being used instead of the variable
  1998.            itself, it is not known how many bytes the variable uses in memory and
  1999.            neither is the type of data.  So, PULL must be instructed what type of data
  2000.            is being accessed.  PULL can handle nine types of data which is enumerated
  2001.            in P55-VAR.INC:
  2002.  
  2003.              TypeOfDataType = (Bytes,Words,ShortInts,Integers,LongInts,Reals,UserNums,
  2004.                                Chars,Strings);
  2005.  
  2006.            The associated data types should be intuitive.  A special case is UserNums
  2007.            which are really strings, but are meant to be displayed as numbers like hex
  2008.            for example.  Remembering that all zero values in the record are the
  2009.            default, now you can see why TypeOfData defaulted to Bytes when nothing was
  2010.            assigned - good ol' fill-in-the-blank again.
  2011.  
  2012.            Matching the Type - Pascal has strong type checking and it can spoil you
  2013.            easily.  This arrangement of splitting the variable into a type and a
  2014.            pointer is most convenient for the Data Window.  However, it is up to your
  2015.            skills as a programmer to ensure that the type truly matches the data at
  2016.            that destination as PULL both reads and writes to it.
  2017.  
  2018.            Validity Check - All numeric types are given a validity check by using the
  2019.            Val procedure.  If the data entry can successfully be converted to the
  2020.            specified numeric type and without overflow, the data is considered valid.
  2021.            If not, the error message "Invalid entry." is displayed.  For now, here is
  2022.            a hint about error messages.  You can see the string for this message
  2023.            earlier in the file:
  2024.  
  2025.              ErrMsgLine[ord(InvalidEM)]:=' Invalid entry.           ESC-acknowledge';
  2026.  
  2027.  
  2028.            FIELDS
  2029.  
  2030.            This section gives instructions on how to adjust the field sizes for the
  2031.            data entry window.
  2032.  
  2033.            Field - Let's see how easy it to add a new data window on our own for
  2034.            strings and adjust the field sizes.  Right after the aByteDW record, add
  2035.            the following new record:
  2036.  
  2037.              GetDataWndw (ord(MyStringDW));
  2038.              VarAddr       := @MyString;
  2039.              TypeOfData    := Strings;
  2040.              Field         := 25;
  2041.              SaveDataWndw;
  2042.  
  2043.            At the top of the file, declare the constant MyString:
  2044.  
  2045.              ...
  2046.              aByte2: byte = 200;
  2047.              MyString: string[25] = 'This is my string.';
  2048.  
  2049.            Now let's link it into line 4 of the FirstMenu.  So, in PULLSTAT, modify
  2050.  
  2051.  
  2052.            Chapter 5, Data Windows                                             Page 34
  2053.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2054.  
  2055.  
  2056.            the FirstMenu record to:
  2057.  
  2058.              GetMainMenu (FirstMenu);
  2059.              ...
  2060.              Line[1] := 'A line';
  2061.              Line[2] := 'B line';
  2062.              Line[3] := 'Enter Byte';  LineMode[3] := ToDataWndw;
  2063.                                        LinkNum [3] := ord(aByteDW);
  2064.              Line[4] := 'My string';   LineMode[4] := ToDataWndw;
  2065.                                        LinkNum [4] := ord(MyStringDW);
  2066.              ...
  2067.  
  2068.            And let's not forget to add MyStringDW to the DataWndwNames type:
  2069.  
  2070.              DataWndwNames = (NoDW,aByteDW,MyStringDW);
  2071.  
  2072.            Run the program and test the data window.  Since Field was set to 25, the
  2073.            window was expanded to allow a 25 character entry with a space on either
  2074.            side.  So, whatever the field width is, that is how many characters can be
  2075.            entered in the string.  Notice that we were careful not to make Field
  2076.            larger than the string size so it would not overwrite too many characters
  2077.            at MyString's address.  But what if the string can have up to 100
  2078.            characters?  How can that be made to fit?
  2079.  
  2080.            Maximum Field - There are actually two variables to adjust the size of the
  2081.            entry field, one is Field and the other is MaxField.  Rather than
  2082.            explaining it, let's see what it can do.  First change the constant to:
  2083.  
  2084.              MyString: string[100] = 'This is my string.';
  2085.  
  2086.            and then add the variable setting of MaxField in the Data Window record:
  2087.  
  2088.              ...
  2089.              Field         := 25;
  2090.              MaxField      := pred(sizeof(MyString));      { = 100 }
  2091.              SaveDataWndw;
  2092.  
  2093.            Now when you run it, the field is flexible.  You can now enter up to 100
  2094.            characters even though the field only displays 25.  These fields are called
  2095.            flex fields.
  2096.  
  2097.            Default Field - By default, program sets MaxField equal to Field.  Anytime
  2098.            MaxField has been set and is not the equal to Field, the flex field becomes
  2099.            active.  So, this can be used with any type of data and not just strings.
  2100.  
  2101.  
  2102.            TITLES
  2103.  
  2104.            If your field is wide enough, you can easily add a title.  Try adding the
  2105.            following code to the MyStringDW record:
  2106.  
  2107.              GetDataWndw (ord(MyStringDW));
  2108.              Title         := 'Enter File Name';
  2109.              VarAddr       := @MyString;
  2110.              ...
  2111.  
  2112.  
  2113.            Chapter 5, Data Windows                                             Page 35
  2114.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2115.  
  2116.  
  2117.  
  2118.            Pulling down this data window, the title will be centered on the top row of
  2119.            the window.  Titles are optional and will be truncated if necessary to fit
  2120.            within the window.
  2121.  
  2122.  
  2123.            EDITING KEYS
  2124.  
  2125.            If you didn't get a chance to try out the full editing keys, here's the
  2126.            list and their function:
  2127.  
  2128.              Keys                          Movement
  2129.              ----------------------------  -----------------------------------------
  2130.              Left Arrow / ^S               Character Left/Right
  2131.              Right Arrow / ^D              Character Left/Right
  2132.              Home / Ctrl Left  Arrow / ^A  First character
  2133.              End  / Ctrl Right Arrow / ^F  Last character
  2134.              Del / ^G                      Deletes character under cursor
  2135.              Backspace / ^H                Deletes character to left of cursor
  2136.              Ins / ^V                      Toggles between insert and overwrite mode
  2137.              ^R/^U                         Restores original contents
  2138.              ^Y                            Deletes entire contents
  2139.  
  2140.            Insert Toggle - PULL allows you to use both insert and overwrite mode.  You
  2141.            can tell the status by the shape of the cursor.  The half-block cursor
  2142.            indicates the insert mode which appears correctly in any video mode.
  2143.  
  2144.            Cursor Handling - In flex fields, some special cursor handling has also
  2145.            been included that you will appreciate when the cursor is at either end.
  2146.            When adding characters to the far right there is always one space open
  2147.            until the maximum character is reached.  It helps identify the last
  2148.            character and shows the character when the Del key is used.  The same
  2149.            principle is used when backspacing - at least one character is always shown
  2150.            until the last one is deleted.  The cursor always remains confined inside
  2151.            the Field width on a flex field.
  2152.  
  2153.            One-Column Field - A special case is considered when Field is 1 column in
  2154.            width.  The cursor does not move and any valid character typed in will
  2155.            overwrite the contents.  Del or Backspace also deletes the contents.
  2156.            Please do not consider using flex fields for this case.
  2157.  
  2158.            AutoNumLock - On machines with enhanced keyboards, it may be an advantage
  2159.            to automatically turn on the NumLock when in Edit mode.  If so, by setting
  2160.            AutoNumLock true, numeric key pad will be have the NumLock turned on when
  2161.            you start editing.  After the edit, PULL will restore it to its original
  2162.            mode, on or off.  Please note that even though the "NUM" message appears on
  2163.            the message line to show the true internal status of NumLock, many machines
  2164.            do not have a smart enough BIOS to also toggle the NumLock LED on the
  2165.            keyboard itself.  Pressing the key can put it back in sync, but the "NUM"
  2166.            message is the thing to watch.
  2167.  
  2168.  
  2169.            KEY SETS
  2170.  
  2171.            This section gives instructions on how to use TP's powerful sets to screen
  2172.  
  2173.  
  2174.            Chapter 5, Data Windows                                             Page 36
  2175.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2176.  
  2177.  
  2178.            for valid keystrokes into the data entry.
  2179.  
  2180.  
  2181.            Entry Sets - As a preventative measure, each keystroke is checked against a
  2182.            set to see if it is valid before it is allowed into the field.  If it is
  2183.            not, the keystroke is simply ignored.  Several set have included and a
  2184.            default is given to each of the nine types of data:
  2185.  
  2186.              SetNames = (NoSet,UnsignedSet,SignedSet,RealSet,CharSet,
  2187.                          HexSet,FileNameSet,PathSet,MaskSet);
  2188.  
  2189.            where the following types are given the following sets:
  2190.  
  2191.              Type       Set
  2192.              ---------  -----------
  2193.              Bytes      UnsignedSet
  2194.              Words      UnsignedSet
  2195.              ShortInts  SignedSet
  2196.              Integer    SignedSet
  2197.              LongInts   SignedSet
  2198.              Reals      RealSet
  2199.              UserNums   CharSet
  2200.              Chars      CharSet
  2201.              Strings    CharSet
  2202.  
  2203.            Four more practical sets have also been included for your use.  To examine
  2204.            the contents of the sets, they are located in P55-VAR.INC in an array
  2205.            called EntrySet.  Since it is in the include file for PULL, these can only
  2206.            be modified when you have the complete source code.
  2207.  
  2208.            Assigning Sets - Most of your work can be done by default, but once in a
  2209.            while, a custom set will be required.  Let's change MyString to be a file
  2210.            name with only valid DOS characters by changing the MyStringDW record to:
  2211.  
  2212.              ...
  2213.              Field         := 25;
  2214.              MaxField      := pred(sizeof(MyString));      { = 100 }
  2215.              SetName       := FileNameSet;
  2216.              SaveDataWndw;
  2217.  
  2218.            Try entering a string into the window and find that invalid characters like
  2219.            the space, "\", and "*" can not be entered.  This gives the user immediate
  2220.            cues about the validity of the entry before it is completely entered.
  2221.  
  2222.  
  2223.            KEY TRANSLATION
  2224.  
  2225.            As each key is entered, it is possible to intercept the keystroke before it
  2226.            reaches the data entry editor.  This section will show how it is done.
  2227.  
  2228.  
  2229.            Translation Pointer - Each data window record has a translation pointer
  2230.            called TranslateProc.  You probably know by now, that the default is nil.
  2231.            If a valid FAR procedure is assigned to this pointer, it will be executed.
  2232.            Suppose you prefer to have the file name entries in upper case.  Modify
  2233.  
  2234.  
  2235.            Chapter 5, Data Windows                                             Page 37
  2236.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2237.  
  2238.  
  2239.            MyStringDW to:
  2240.  
  2241.              ...
  2242.              Field         := 25;
  2243.              MaxField      := pred(sizeof(MyString));      { = 100 }
  2244.              SetName       := FileNameSet;
  2245.              TranslateProc := @TranslateCase;
  2246.              SaveDataWndw;
  2247.  
  2248.            Back up a few lines to find this procedure and you will see:
  2249.  
  2250.              procedure TranslateCase;
  2251.              begin
  2252.                if not ExtKey then
  2253.                  Key := upcase(Key);        { Simple upper case translation }
  2254.              end;
  2255.  
  2256.            In PULL, Key is the character returned from ReadKey, and ExtKey is true if
  2257.            it is an extended key.  Notice that $F+ and $F- are used to force the
  2258.            procedure to FAR.  Run the program again and find that all keys typed in
  2259.            this data window are forced to upper case.
  2260.  
  2261.            Every Key - All keys can be translated with this procedure.  Even global
  2262.            or editing keys can be intercepted and translated to whatever is desired.
  2263.            It is also useful for foreign language translation.
  2264.  
  2265.  
  2266.            RANGE CHECKING
  2267.  
  2268.            After the entry is entered and checked as valid, there is one more option
  2269.            of checking the entry to make sure it is in the range or form that is
  2270.            acceptable to the program.  This section will show how to create range
  2271.            checking procedures and out of range error messages.
  2272.  
  2273.  
  2274.            Three Parts - Before setting up a range check, you need to understand how
  2275.            the data is transferred between the entry and the variable.  There are
  2276.            three parts to performing the data entry transfer - the data entry string,
  2277.            data pad, and destination variable.
  2278.  
  2279.            Data Entry String - The data entry string is the string that is seen and
  2280.            edited on the CRT.  This string is held in DataStr of type DataStrType and
  2281.            is declared in P55-VAR.INC.
  2282.  
  2283.            Reading - The data pad, called DataPad, is a two-way messenger that
  2284.            transfers data between the variable and DataStr.  When the data window is
  2285.            initially displayed, the data pad reads the contents of the variable and
  2286.            makes an exact copy of the value onto itself.  Then the program converts
  2287.            this value over to DataStr into a string form which the user can easily
  2288.            read and edit.
  2289.  
  2290.            Storing - As mentioned before, pressing RETURN after editing is completed,
  2291.            the program attempts to store the entry to the variable.  First, numeric
  2292.            data must pass a validity check by converting DataStr to a value.  If it
  2293.            passes, a copy of the converted data is now on the data pad.  Now is the
  2294.  
  2295.  
  2296.            Chapter 5, Data Windows                                             Page 38
  2297.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2298.  
  2299.  
  2300.            time to do a data range check.  By default, there is no check and the data
  2301.            would continue to be stored from the data pad to the destination variable
  2302.            as is.  But to do the range check, you need to know the identifiers that
  2303.            are used on the data pad.
  2304.  
  2305.            Data Pad Identifiers - The data pad is completely generic.  Any type of
  2306.            data occupies the exact same address.  So all you need to do is select the
  2307.            right identifier to match the type of data for your variable.  You can look
  2308.            at the data pad record in P55-VAR.INC for the field list, but here is a
  2309.            list of those identifiers:
  2310.  
  2311.              Type       Identifier
  2312.              ---------  ----------
  2313.              Bytes      Bdata
  2314.              Words      Wdata
  2315.              ShortInts  SIdata
  2316.              Integers   Idata
  2317.              LongInts   Ldata
  2318.              Reals      Rdata
  2319.              UserNums   UNdata
  2320.              Chars      Cdata
  2321.              Strings    Sdata
  2322.  
  2323.            Example - Let's set up a range check for aByteDW.  Modify its data window
  2324.            record to:
  2325.  
  2326.              GetDataWndw (ord(aByteDW));         { Just gets cleared DataWndw }
  2327.              ...
  2328.              Field         := 3;
  2329.              CheckRangeProc := @CheckAbyte;      { add this line. }
  2330.              SaveDataWndw;                       { Saves it in the heap }
  2331.  
  2332.            Arbitrarily, let the range for aByte be between 20 and 50 inclusive.  Now
  2333.            back up a few lines before the TranslateCase procedure and the following
  2334.            procedure has already been added for you:
  2335.  
  2336.              procedure CheckAbyte;
  2337.              begin
  2338.                with DataPad do
  2339.                  if ((Bdata<20) or (Bdata>50)) then
  2340.                    MakeErrMsg (20,50);
  2341.              end;
  2342.  
  2343.            Since aByte is byte type, Bdata is used for the comparison.  For the range
  2344.            check, any values under 20 or over 50 will run the MakeErrMsg procedure.
  2345.            Try it and see if you can produce the error message.
  2346.  
  2347.            Error Messages - How does PULL know if an error is found?  It tests the
  2348.            value of ErrMsg in DataPad.  If the value remains zero, then the range
  2349.            check is passed.  Otherwise, it has failed.  And, it uses this same value
  2350.            as the error message name.  The ErrMsgLines are much like the MsgLines
  2351.            using names for indexes.  Right after the implementation you can see the
  2352.            error message names:
  2353.  
  2354.              ErrMsgNames = (NoEM,UserEM,InvalidEM,MyEM);
  2355.  
  2356.  
  2357.            Chapter 5, Data Windows                                             Page 39
  2358.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2359.  
  2360.  
  2361.  
  2362.            The names up to InvalidEM are reserved.  The name UserEM is of most
  2363.            interest.  ErrMsgLine[ord(UserEM)] is meant to be customized by creating a
  2364.            message at run-time.  This saves you from making several hard-coded
  2365.            messages.  The example used MakeErrMsg, located a few lines back.  It is a
  2366.            good simple example how to set both ErrMsg and create a custom message on
  2367.            the UserEM.  But the important value is the change of ErrMsg.
  2368.  
  2369.            Message Length - Error messages tend to be short, so there is no need to
  2370.            allocate a full screen width for the message.  The maximum length of a
  2371.            message is set by MaxErrStrLength in P55-VAR.INC.  The program will
  2372.            automatically clear the remaining part of the line and takes special care
  2373.            not to do a needless full-line clear and thereby preventing a flicker
  2374.            effect.
  2375.  
  2376.            Maximum Message - Similarly, the maximum number of ErrMsgLines is set by
  2377.            NumOfErrMsgLines in P55-VAR.INC.
  2378.  
  2379.            Summary - The outcome of the range check is determined by the value of
  2380.            DataPad.ErrMsg.  PULL sets it to zero.  Compare your range with the DataPad
  2381.            identifiers in any fashion.  Only if it is out of range, set ErrMsg to the
  2382.            ErrMsgLine you want to show.
  2383.  
  2384.  
  2385.            HELP MESSAGES
  2386.  
  2387.            A help message can be assigned to the Data Window record exactly the same
  2388.            as the menus.  One name has already been reserved for the Data Window
  2389.            called DW_ML and is the default.  But you can also assign new ones.  The
  2390.            MsgLines and names are in PULLSTAT.PAS.
  2391.  
  2392.  
  2393.            HELP WINDOWS
  2394.  
  2395.            Again, just like the menus, help windows can be assigned to the Data
  2396.            Window.  The record name reserved for Data Window records is called
  2397.            DataWndwHW and is the default.  If you have not seen this window, run the
  2398.            program with a Data Window pulled and press F1.  The Help Window records
  2399.            and Help Lines are in PULLSTAT.PAS.
  2400.  
  2401.  
  2402.            DEFAULT ATTRIBUTES AND BORDER
  2403.  
  2404.            This section will show the variables used to create default attributes and
  2405.            border for the Data Window.
  2406.  
  2407.  
  2408.            Initialization - PULLDATA is self-initialized when it is included in the
  2409.            USES list.  There are two procedures that set up the colors and border:
  2410.  
  2411.              SetDefaultColors - assigns colors and border to the default variables.
  2412.              InitDataColors   - assigns the defaults to the Data Window record.
  2413.  
  2414.            SetDefaultColors - In PULLDATA, search for SetDefaultColors and see the
  2415.            following code:
  2416.  
  2417.  
  2418.            Chapter 5, Data Windows                                             Page 40
  2419.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2420.  
  2421.  
  2422.  
  2423.              DataWndwIattr  := Black+BrownBG;
  2424.              DataWndwOattr  := Yellow+BlackBG;
  2425.              DataWndwBattr  := Black+BrownBG;
  2426.              DataWndwBrdr   := HdoubleBrdr;
  2427.  
  2428.            InitDataColors - These variables in turn are assigned to the following
  2429.            record variables in DataWndw:
  2430.  
  2431.                                Record
  2432.              Default variable  Variable   Description
  2433.              ----------------  ---------  ----------------------------
  2434.              DataWndwIattr     Iattr      Attribute for Input
  2435.              DataWndwOattr     Oattr      Attribute for Output
  2436.              DataWndwBattr     Battr      Attribute of the Border
  2437.              DataWndwBrdr      Border     Border of the window
  2438.  
  2439.            Just like the menus, this saves you from having to make the same assignment
  2440.            to every menu record.  Try experimenting with the colors and border in the
  2441.            shell program and see the results.  Although NoBrdr is permissible, it is
  2442.            not suggested.
  2443.  
  2444.  
  2445.            DEFAULT LOCATION
  2446.  
  2447.            The location of a data window is placed by PULL at run time.  With the
  2448.            slide-under configuration, the menu is placed underneath the HiLite and
  2449.            shifted to the right 2 columns.  If necessary, it is shifted to the left to
  2450.            prevent wraparound.  To alter this position manually, set Row and Col in
  2451.            the menu record to your desired location.
  2452.  
  2453.  
  2454.            SUMMARY
  2455.  
  2456.            In addition to mastering the menus, you can now link data windows into the
  2457.            menus by adding and linking data window records in PULLDATA.PAS.  You have
  2458.            been able to address the entry variable and create a window suitable for
  2459.            the data type including the field type and size, title, key set and
  2460.            translation, range checking, error and help messages, and help windows.
  2461.            With this environment in your application along with the power and speed of
  2462.            QWIK and WNDW, your programs can match and even better professional
  2463.            programs.
  2464.  
  2465.  
  2466.  
  2467.  
  2468.  
  2469.  
  2470.  
  2471.  
  2472.  
  2473.  
  2474.  
  2475.  
  2476.  
  2477.  
  2478.  
  2479.            Chapter 5, Data Windows                                             Page 41
  2480.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2481.  
  2482.  
  2483.            6.  D A T A   E N T R Y
  2484.  
  2485.            Data Windows in the pull-down menus are not the only place where data is
  2486.            needed to be entered.  The work windows themselves may need several data
  2487.            entry fields as well.  PULL simply uses a subset of Data Windows to handle
  2488.            the job very easily.  In addition, a smart HiLite automatically knows the
  2489.            location of each field in the window.
  2490.  
  2491.  
  2492.            DATA ENTRY vs. DATA WINDOW
  2493.  
  2494.            Data Windows have both a data entry field and a window surrounding it.  In
  2495.            work windows, all that is needed is the data entry field.  So, to
  2496.            distinguish between data entry in the pull-down menus and the work windows,
  2497.            the Data Windows are only in the menus, while Data Entry will be considered
  2498.            in this document to be in the work windows.
  2499.  
  2500.  
  2501.            DATA ENTRY RECORD
  2502.  
  2503.            One Data Entry field has already been included in the work window.  Let's
  2504.            take a look at its record.  In PULLDATA, find GetDataEntryStats and search
  2505.            for "with TopEntry" to see the following code:
  2506.  
  2507.              GetDataEntry (ord(aIntegerDE));
  2508.              VarAddr     := @aInteger;
  2509.              TypeOfData  := Integers;
  2510.              Row         := 2;
  2511.              Col         := 11;
  2512.              Field       := 4;
  2513.              MaxField    := 3;
  2514.              CheckRangeProc := @VerifyAinteger;
  2515.            { MsgLineNum  := ord(DE_ML); }      { This is the default }
  2516.            { HelpWndwNum := ord(DataWndwHW); } { This is the default }
  2517.              SaveDataEntry;
  2518.  
  2519.            The record identifiers should look quite familiar because they are the same
  2520.            ones use in a Data Window record.  The only differences are the Get and
  2521.            Save procedures, because the record is of type DataEntryRec rather than
  2522.            DataWndwRec.  If you examine these type declarations in P55-VAR.INC, you
  2523.            will find there is a DataEntryRec inside of DataWndwRec.  So, Data Entry is
  2524.            truly a subset of Data Windows.
  2525.  
  2526.            Variable - The variable is aInteger which is a constant declared early in
  2527.            the file and is of type Integers.
  2528.  
  2529.            Row/Col - This time, a row and column is specified where the left column of
  2530.            the field is to appear in the work window.  These coordinates are window
  2531.            relative.
  2532.  
  2533.            Default Helps - Both the help message and help window are set to a default
  2534.            so your program can be up and running without being concerned about
  2535.            details.  Being in a different part of the pull-down menu environment, the
  2536.            DE_ML is different from DW_ML because the function of F2 is the opposite to
  2537.            either case.
  2538.  
  2539.  
  2540.            Chapter 6, Data Entry                                               Page 42
  2541.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2542.  
  2543.  
  2544.  
  2545.            Other Variables - All the other variables in the record should be familiar
  2546.            to you from the explanations in the previous section on Data Windows.  So,
  2547.            there is no need to repeat them here.
  2548.  
  2549.  
  2550.            ADDING ENTRIES
  2551.  
  2552.            Entry Record - We have already seen how to add entries with the fill-in-
  2553.            the-blank concept, so let's try adding another entry to the work window.
  2554.            Just after the aInteger record, add the following code:
  2555.  
  2556.              GetDataEntry (ord(aRealDE));
  2557.              VarAddr     := @aReal;
  2558.              TypeOfData  := Reals;
  2559.              Row         := 3;
  2560.              Col         := 11;
  2561.              Field       := 12;
  2562.              Decimals    := 2;
  2563.              SaveDataEntry;
  2564.  
  2565.            Decimal - This variable is just for reals to format the number of decimals
  2566.            for the output display.  If the value is negative, then no decimal is used.
  2567.  
  2568.            aReal - Be sure to set up a default value for aReal.  At the beginning of
  2569.            PULLDATA, add the constant aReal:
  2570.  
  2571.              ...
  2572.              aInteger: integer = 200;
  2573.              aReal:    real    = 4.56e7;
  2574.  
  2575.            aRealDE - Now append the data entry record name to the DataEntryNames list
  2576.            at the beginning of the file:
  2577.  
  2578.              DataEntryNames = (NoDE,aIntegerDE,aRealDE);
  2579.  
  2580.            Now run the code and see if it appears in the Work Window.  When it runs,
  2581.            the field does not appear.  Why?
  2582.  
  2583.  
  2584.            DISPLAYING FIELDS
  2585.  
  2586.            Work Window - The Work Window controls what is to appear inside the window
  2587.            and this code is in the file PULLWORK.PAS.  Note that PULLWORK uses
  2588.            PULLDATA.  Take a look at it and search for "case WorkWndwStep" and see:
  2589.  
  2590.              ...
  2591.              WWrite (2,2,'Integer:');
  2592.              DisplayFields (ord(aIntegerDE),ord(aIntegerDE));
  2593.              WorkWndwStep := 1;
  2594.              ...
  2595.  
  2596.            DisplayFields - This is the code that displayed the Integer field.  The
  2597.            DisplayFields procedure displays a sequence of fields in order of the list
  2598.            of DataEntryNames.  It is declared in the interface of PULL as:
  2599.  
  2600.  
  2601.            Chapter 6, Data Entry                                               Page 43
  2602.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2603.  
  2604.  
  2605.  
  2606.              procedure DisplayFields (First,Last: word);
  2607.  
  2608.            So, what it does is display each field starting with the record First and
  2609.            ending with Last.  Looking back in PULLWORK again, it displayed records
  2610.            both beginning and ending with aIntegerDE.  So, it never reached aRealDE.
  2611.            Let's modify the parameter to include aRealDE as follows:
  2612.  
  2613.              DisplayFields (ord(aIntegerDE),ord(aRealDE));
  2614.  
  2615.            Field Label - Running it, the aRealDE will be displayed this time.  But it
  2616.            doesn't have a label, so add one to the window with:
  2617.  
  2618.              ...
  2619.              WWrite (2,2,'Integer:');
  2620.              WWrite (3,2,'Real:');
  2621.              DisplayFields (ord(aIntegerDE),ord(aRealDE));
  2622.              ...
  2623.  
  2624.            Justification - aReal now appears on the screen with the field right
  2625.            justified.  By default, numbers are justified to the right and strings to
  2626.            the left.  To alter this, just include your setting in the Data Entry
  2627.            record.  Let's try left justifying aReal by adding the following code in
  2628.            PULLDATA:
  2629.  
  2630.              GetDataEntry (ord(aRealDE));
  2631.              ...
  2632.              Decimals    := 2;
  2633.              JustifyOutput := Left;           { Add this line. }
  2634.              SaveDataEntry;
  2635.  
  2636.            Everything appears correctly on the screen.  But when we try to move the
  2637.            HiLite, it just stays on the Integer field.  How can we make it select the
  2638.            other field?  Real easy - keep reading.
  2639.  
  2640.  
  2641.            SEQUENTIAL ENTRY
  2642.  
  2643.            With sequential entries of several fields, PULL gives you the advantage of
  2644.            using not just one movement with the HiLite, but both relative and
  2645.            sequential movement.
  2646.  
  2647.  
  2648.            EnterSeq - PULL makes sequential entry as natural as can be.  In PULLWORK,
  2649.            search for EnterSeq and see:
  2650.  
  2651.              EnterSeq (ord(aIntegerDE),ord(aIntegerDE),Start1);
  2652.  
  2653.            This procedure is also in the interface of PULL.PAS and is declared as:
  2654.  
  2655.              procedure EnterSeq (First,Last: word; VAR Start: word);
  2656.  
  2657.            EnterSeq allows you to enter a whole block of entries in the DataEntry
  2658.            array of records where First and Last are the first and last records in the
  2659.            block.  The aRealDE was not included in this block.  So let's modify the
  2660.  
  2661.  
  2662.            Chapter 6, Data Entry                                               Page 44
  2663.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2664.  
  2665.  
  2666.            code to:
  2667.  
  2668.              EnterSeq (ord(aIntegerDE),ord(aRealDE),Start1);
  2669.  
  2670.            Now run the code and find that the highlight can now move freely between
  2671.            the two fields.  That all there is to do!  PULL handles the rest, now.
  2672.  
  2673.            Start - Start is the record where the highlight is to begin.  At the bottom
  2674.            of the file, Start1 is initialized to aIntegerDE.  Or, Start1 could be made
  2675.            into a typed constant with a default value.  This lets EnterSeq remember
  2676.            where the HiLite is after using the menus.
  2677.  
  2678.            Smart HiLite Algorithms - Take a break from PULLSHEL and go back to
  2679.            PULLDEMO.  Run the program and take a look at the work window with several
  2680.            entries.  PULL has smart algorithms that know where all the fields are
  2681.            located on the screen.  The HiLite can be moved freely to select any field
  2682.            with the following keys:
  2683.  
  2684.              Keys                     Movement                   Type of Movement
  2685.              -----------------------  -------------------------  ----------------
  2686.              Left/Right Arrow         Left/Right                 Relative
  2687.              Up/Down Arrow            Up/Down nearest cursor     Relative
  2688.              Home / Ctrl Left  Arrow  First one on the row       Relative
  2689.              End  / Ctrl Right Arrow  Last one on the row        Relative
  2690.              PgUp / Ctrl Home         First in sequence          Sequential
  2691.              PgDn / Ctrl End          Last  in sequence          Sequential
  2692.              Tab / Shift Tab          Next/Previous in sequence  Sequential
  2693.  
  2694.            Relative Movement - PULL checks the block of entries to see where to move
  2695.            the HiLite relative to the current field.  If the field is already at its
  2696.            limit, say to the far left with the left arrow key, it does not wrap around
  2697.            to the far right.  When the HiLite is moved up or down, PULL looks for the
  2698.            field nearest the cursor, not the full width of the field, and also does
  2699.            not wrap.
  2700.  
  2701.            Sequential Movement - Primarily, the Tab key is used for sequential
  2702.            movement.  If you reach the end of the sequence, the next Tab will wrap
  2703.            back to the first.  What determines sequential movement?  It's the order of
  2704.            the DataEntryNames.  So, changing the sequence is as simple as reorganizing
  2705.            the names - no interlinks between fields are necessary!  Now you can insert
  2706.            a new field without fretting over links.
  2707.  
  2708.            Auto Tab - The value of sequential entry is the order in which you want to
  2709.            enter fields.  After entering one field, the program should be smart enough
  2710.            to go the next one.  With AutoTab set true, PULL will jump to the next
  2711.            field in sequence automatically after each entry.  Let's try it again on
  2712.            the PULLDEMO program.
  2713.  
  2714.              1. Get into the work window.
  2715.              2. Press PgUp to get to the "Byte" entry field.
  2716.              3. Enter any value in range and press RETURN.
  2717.              4. See that the HiLite is now on "Integer".
  2718.  
  2719.            To prove the point of relative and sequential movement, let's move one of
  2720.            the fields to a different location.  In PULLDATA, search for the data entry
  2721.  
  2722.  
  2723.            Chapter 6, Data Entry                                               Page 45
  2724.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2725.  
  2726.  
  2727.            record for aChar2DE, and change the location to:
  2728.  
  2729.              GetDataEntry (ord(aChar2DE));
  2730.              VarAddr     := @aChar2;
  2731.              TypeOfData  := Chars;
  2732.              Row         := 5;            { Change the row (was 15) }
  2733.              Col         := 5;            { Change the column (was 55) }
  2734.              ...
  2735.  
  2736.            Run PULLDEMO and see the field moved to (5,5).  Moving the up arrow as far
  2737.            as it will go, the HiLite will end up on aChar2DE.  But when you press Tab,
  2738.            the next field is String.  Now, suppose we want aChar2DE to be first in
  2739.            sequence.  How easy is it?  Look for DataEntryNames at the top of the file
  2740.            and see:
  2741.  
  2742.              DataEntryNames = (
  2743.                NoDE,aByte2DE,aWord2DE,aShortInt2DE,aInteger2DE,aLongInt2DE,aReal2DE,
  2744.                aHex2DE,aChar2DE,aString2DE,FileNameDE);
  2745.  
  2746.            There is a bunch of names here, but all we are interested in is moving
  2747.            aChar2DE.  Move the name to be right after NoDE.  But now we have changed
  2748.            the beginning name of the block from aByte2DE to aChar2DE.  So, go into
  2749.            PULLWORK and do a global search and replace of aByte2DE with aChar2DE.
  2750.            Three familiar lines will be changed.  Run the program now and see that
  2751.            PgUp will now move the HiLite to the top and a subsequent tab will move it
  2752.            to Byte.  This makes organizing your screen very easy.
  2753.  
  2754.            Setting AutoTab - In PULLDATA, search for AutoTab which is right at the
  2755.            beginning of the Data Entry records.  The current value is true.  If this
  2756.            value is set false, then the HiLite would stay in the same field after
  2757.            entry.
  2758.  
  2759.  
  2760.            EDIT MODE
  2761.  
  2762.            When the HiLite moves from field to field, it is in Select Mode.  But when
  2763.            your are editing a field, it is in Edit Mode.  What exactly makes it change
  2764.            from Select to Edit mode?
  2765.  
  2766.  
  2767.            Overwrite vs. Edit - To overwrite the contents, just start typing the new
  2768.            entry.  To edit the contents, the suggested key to use is the Return key.
  2769.            When pressed, the HiLite changes color and the cursor is set past the last
  2770.            character.
  2771.  
  2772.            Non-Extended Keys - In addition to the Return key, any non-extended key
  2773.            will work as well and will also apply that key to the field.  For example,
  2774.            while in select mode, if ^A is pressed, the HiLite would change into Edit
  2775.            mode and, in addition, the cursor would be moved to the first character.
  2776.  
  2777.            Invalid Characters - If the key pressed is not a member of the entry key
  2778.            set, it acts the same as return on the first key, but is otherwise ignored.
  2779.  
  2780.            Escape - To escape Edit mode and restore the original contents, just press
  2781.            ESC and the HiLite will return to Select Mode.  If ESC is pressed again,
  2782.  
  2783.  
  2784.            Chapter 6, Data Entry                                               Page 46
  2785.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2786.  
  2787.  
  2788.            the program would escape the entire sequence of entry and would return
  2789.            control to the WorkWindow procedure.
  2790.  
  2791.  
  2792.            FIELD ATTRIBUTES
  2793.  
  2794.            There are three attributes that can be modified for the Data Entry fields -
  2795.            the display, the edit, and the HiLite attributes.
  2796.  
  2797.  
  2798.            Default Attributes - Data Entry fields have default attributes for each
  2799.            record just like the Data Windows.  These variables are also set in
  2800.            SetDefaultColors and InitDataColors.
  2801.  
  2802.            SetDefaultColors - In PULLDATA, search for SetDefaultColors and see the
  2803.            following code:
  2804.  
  2805.              DataEntryIattr  := Yellow+MagentaBG;
  2806.              DataEntryOattr  := Black+LightGrayBG;
  2807.  
  2808.            InitDataColors - These variables in turn are assigned to the following
  2809.            record variables in DataEntry:
  2810.  
  2811.                                Record
  2812.              Default variable  Variable   Description
  2813.              ----------------  ---------  --------------------
  2814.              DataEntryIattr    Iattr      Attribute for Input
  2815.              DataEntryOattr    Oattr      Attribute for Output
  2816.  
  2817.            HiLite Bar - The HiLite attribute is set by the color on the data pad
  2818.            called DataPad.Hattr.  This variable is right next to AutoTab in PULLDATA.
  2819.            Rather than having both the cursor and the HiLite, the HiLite can be turned
  2820.            off by assigning Hattr the value of SameAttr.  Then each field will appear
  2821.            in its own display attribute.
  2822.  
  2823.  
  2824.            SINGLE ENTRY
  2825.  
  2826.            If you prefer to customize your own procedures, you can use the procedure
  2827.            Enter in lieu of EnterSeq.  The procedure is declared in PULL as:
  2828.  
  2829.              procedure Enter (RecNum: word);
  2830.  
  2831.            This accesses the same powerful editing features as EnterSeq, but only
  2832.            works on the one field indicated in the parameter.  It does not display the
  2833.            fields before or after editing which must be done with DisplayFields.
  2834.  
  2835.  
  2836.            SUMMARY
  2837.  
  2838.            You have just covered enough features to master data entry in the work
  2839.            windows or user windows.  You can enter the records, display and locate the
  2840.            fields, control the sequence of entry, and adjust the appearance with the
  2841.            justification and attributes.  You also learned how to direct PULL's built
  2842.            in HiLite bar for field selection.
  2843.  
  2844.  
  2845.            Chapter 6, Data Entry                                               Page 47
  2846.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2847.  
  2848.  
  2849.            7.  W O R K   W I N D O W S
  2850.  
  2851.            The bulk of your application needs to be displayed somewhere, and the Work
  2852.            Windows are used for this purpose.  In this section, you will discover how
  2853.            to integrate your work window procedures in a pull-down menu environment so
  2854.            the program can randomly access any procedure.  In addition, you can create
  2855.            a sophisticated multi-level window environment.
  2856.  
  2857.  
  2858.            MAKING STEPS
  2859.  
  2860.            In this section, you will find how to break down procedures into individual
  2861.            steps and still allow the flow of execution to cycle through the Key
  2862.            dispatcher.
  2863.  
  2864.  
  2865.            Requirements - When procedures are broken down into steps, your procedures
  2866.            can do most anything.  But each step must exit with two settings:
  2867.  
  2868.              1. Assignment made for the next WorkWndwStep.
  2869.              2. Assignment made for Key and ExtKey.
  2870.  
  2871.            Example - Let's do an example to understand the flow of execution.  Get the
  2872.            original files for PULLDEMO.PAS - PULLWORK and PULLDATA.  Now take a look
  2873.            at the last of PULLWORK and see:
  2874.  
  2875.              procedure WorkWndw;
  2876.              begin
  2877.                ...
  2878.                case WorkWndwStep of
  2879.                  0:  ShowFields;
  2880.                  1:  EditFields;
  2881.                end;
  2882.              end;
  2883.  
  2884.            With this construct, your work can be separated into different steps.  To
  2885.            add a new step, just insert one.  To demonstrate how to create a new step,
  2886.            let's separate the left and right columns of the data entry fields into two
  2887.            separate steps.  So, let's add step 2:
  2888.  
  2889.                ...
  2890.                  0:  ShowFields;
  2891.                  1:  EditFields;
  2892.                  2:  EditFields2;
  2893.                end;
  2894.  
  2895.            and change EditFields to:
  2896.  
  2897.              procedure EditFields;
  2898.              begin
  2899.                DisplayFields (ord(FileNameDE),ord(FileNameDE));
  2900.                EnterSeq (ord(aByte2DE),ord(aReal2DE),Start1);    { Change this line. }
  2901.                if Key=EscKey then                                { Add this line. }
  2902.                  WorkWndwStep := 2;                              { Add this line. }
  2903.              end;
  2904.  
  2905.  
  2906.            Chapter 7, Work Windows                                             Page 48
  2907.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2908.  
  2909.  
  2910.  
  2911.            This will isolate the sequence to the left column of fields.  And now add
  2912.            EditFields2:
  2913.  
  2914.              procedure EditFields2;
  2915.              begin
  2916.                DisplayFields (ord(FileNameDE),ord(FileNameDE));
  2917.                EnterSeq (ord(aHex2DE),ord(FileNameDE),Start2);
  2918.                if Key=EscKey then
  2919.                  WorkWndwStep := 1;
  2920.              end;
  2921.  
  2922.            Start2 has already been added for you.  Set the TP primary file to be
  2923.            PULLDEMO.PAS.  Now try the program and see that you can only access the
  2924.            left or right sequence of fields.  If you want to swap between the left and
  2925.            right columns, just press ESC.
  2926.  
  2927.            Flow of Execution - ESC has been assigned inside EnterSeq as the key that
  2928.            is used to exit the procedure.  This is called a gated exit.  Once it
  2929.            exits, it also exits WorkWndw and goes back into PULL to analyze the
  2930.            keystroke in a key dispatcher.  If no key combinations are used to access
  2931.            the menus, execution will return right back to WorkWndw and into the right
  2932.            step.  You can catch the execution flow, by testing for the Esc key right
  2933.            after EnterSeq.  If so, then change the step as we did in the example.
  2934.  
  2935.            Menu Access - Why even bother to test the key if ESC exits EnterSeq?  The
  2936.            Esc key is not the only key that would exit this procedure.  Any menu key
  2937.            like F10 will also exit the same way.  So, the "if" statement is needed to
  2938.            confirm the correct key before changing the step.
  2939.  
  2940.            Updating the Window - Did you notice that DisplayFields was used twice for
  2941.            just one field?  Any time you exit a menu and re-enter the window, there is
  2942.            a possibility that something may need to be updated.  And this time the
  2943.            File name field is a possibility because it was linked to the output of the
  2944.            file directory.  If you haven't had a chance, press Alt-D to get the
  2945.            directory and pick a file by pressing RETURN.  The selected file name will
  2946.            appear in the File name field.  The other link is that the file name data
  2947.            entry field also preselects the initial file name when the directory is
  2948.            pulled again.  But there are other alternatives than using DisplayFields
  2949.            twice.
  2950.  
  2951.            Changing Steps - This example was quite simple.  When step 1 was complete,
  2952.            WorkWndwStep was incremented to step 2.  When step 2 was done, it was
  2953.            cycled back to step 1.  It continues to stay in this loop until the program
  2954.            is terminated, or until some other procedure changes the step number.  In
  2955.            step 0, if we had failed to assign a new step at the end of the step, the
  2956.            program would have been locked in an infinite loop, because it never
  2957.            accesses any keyboard input.
  2958.  
  2959.  
  2960.            READING THE KEYBOARD
  2961.  
  2962.            In some steps, the program may need keyboard input while others do not.  In
  2963.            this section you will find out how to read the keyboard within each step.
  2964.  
  2965.  
  2966.  
  2967.            Chapter 7, Work Windows                                             Page 49
  2968.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  2969.  
  2970.  
  2971.            Output-Only Step - Step 0 in the example, is an output-only step that
  2972.            displays the fields in the window.  No keyboard input was required.  So, at
  2973.            the end of the step, we needed to emulate a keystroke of some kind to meet
  2974.            the Step requirements.  By setting Key to NullKey (#00), the key dispatcher
  2975.            and will bypass a call to the menus and ignore the key.  This guarantees
  2976.            that the flow of execution will return to back WorkWndw.  ExtKey should
  2977.            also be set properly if a valid combination is needed.  Some keys do not
  2978.            require it such as NullKey, EscKey, and RetKey.  See your reference book
  2979.            for more details.
  2980.  
  2981.            Input and Output Step - Most steps will require both input and output.
  2982.            Step 1 called EnterSeq which has a keyboard reading routine built in.  So,
  2983.            no keystroke emulation is needed.  However, the last line in the step still
  2984.            needs to check for a change of step.
  2985.  
  2986.            Custom Input - There will be several occasions where you will want to have
  2987.            your own procedures that read the key board.  If you have the source code,
  2988.            look at PULLDENT.INC for the construct of EnterSeq which looks like:
  2989.  
  2990.              repeat
  2991.                ...
  2992.                CheckForPullDown (ord(SeqML));
  2993.                ...
  2994.                CheckForPop;
  2995.              until (Key=EscKey) or Pop or PullDown;
  2996.  
  2997.            CheckForPullDown is a procedure available to you to read the key board.
  2998.            Its parameter, MsgLineNum, will show this message while the program pauses
  2999.            for entry.  A subroutine in CheckForPullDown is ReadKbd which can be used
  3000.            instead.  It just reads the keyboard and does not show a message.
  3001.  
  3002.            CheckForPop - This procedure is also available to you to check if any menu
  3003.            control flags have been set and regulates them.  If the flags indicate a
  3004.            pop it needed, then Pop will be set true.
  3005.  
  3006.            Gated Exit - Now you can see two more possible reasons that would cause the
  3007.            program to exit EnterSeq - Pop and PullDown.  These are the very same flags
  3008.            used for controlling the menus.  By gating the exit, the flow of execution
  3009.            is confined with the repeat/until construct until a control flag permits
  3010.            the exit.  Using these two flags allow EnterSeq to be used in either the
  3011.            Work Window or a User Window in the menus.  If the procedure is only going
  3012.            to be used in the Work Window, then Pop is not necessary.
  3013.  
  3014.            Non-Gated Exit - The step doesn't have to be gated at all.  You can use
  3015.            CheckForPullDown by itself if the flow of execution can continue through
  3016.            the dispatcher every time a key is pressed.  For EnterSeq, this would not
  3017.            work, because the HiLite would flash with each keystroke.  The next section
  3018.            shows an example where a non-gated Exit works perfectly fine.
  3019.  
  3020.            Idle Keyboard - Rather than just letting the program just sit there and
  3021.            wait for keyboard input, you could be letting the program do other
  3022.            background processing.  An indirect call from PULL inside ReadKbd
  3023.            continually runs the contents of the FAR procedure KbdIdle while no key is
  3024.            pressed.  Although KbdIdle is seen here in PULLWORK, it can be placed in
  3025.            any file, but it MUST be included somewhere, even if the procedure is
  3026.  
  3027.  
  3028.            Chapter 7, Work Windows                                             Page 50
  3029.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3030.  
  3031.  
  3032.            empty.  The variable AddKbdIdle declares its address.
  3033.  
  3034.  
  3035.            MULTI-LEVEL WINDOWS
  3036.  
  3037.            One work window may not be enough for your application and others may be
  3038.            needed.  The following example shows how to add a simple hidden Work
  3039.            Window.
  3040.  
  3041.            Making the Step - Add step 3 to WorkWindow:
  3042.  
  3043.                ...
  3044.                  2:  EditFields2;
  3045.                  3:  EditWorkWndw2;   { Add this line. }
  3046.                end;
  3047.  
  3048.            Now, create this editing step to just put ASCII keys into the window.  A
  3049.            non-gated procedure will work fine:
  3050.  
  3051.              procedure EditWorkWndw2;
  3052.              begin
  3053.                CheckForPullDown (ord(WorkML));
  3054.                if not ExtKey then
  3055.                  case Key of
  3056.                    #32..#126: write (Key);
  3057.                    RetKey:    writeln;
  3058.                    EscKey:    HideWorkWndw;
  3059.                  end;
  3060.              end;     { Non-gated exit }
  3061.  
  3062.  
  3063.            The key chosen to hide the window is ESC although any key could be assigned
  3064.            to do this.  But we also need to initialize the second work window to be
  3065.            available to the program.  So, add the following line to InitWorkWndws:
  3066.  
  3067.              procedure InitWorkWndws;
  3068.              begin
  3069.                ShowFields;
  3070.                MakeWorkWndw2;   { Add this line. }
  3071.                ...
  3072.              end;
  3073.  
  3074.            and then code the procedure to make a hidden window and place it just after
  3075.            the ShowFields procedure.  (The code is already there.  Just remove the
  3076.            braces for this example.)
  3077.  
  3078.              procedure MakeWorkWndw2;
  3079.              begin
  3080.                SetWindowModes (HiddenMode);
  3081.                MakeWindow ( 8,21,10,40,LightBlue+LightGrayBG,LightBlue+LightGrayBG,
  3082.                             DoubleBrdr,Window2);
  3083.                SetWindowModes (0);
  3084.                WriteToHidden (Window2);
  3085.                TitleWindow (Top,Left  ,SameAttr,'2');
  3086.                TitleWindow (Top,Center,SameAttr,' Press ESC to hide ');
  3087.  
  3088.  
  3089.            Chapter 7, Work Windows                                             Page 51
  3090.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3091.  
  3092.  
  3093.                TitleWindow (Top,Center,SameAttr,' Work Window 2 ');
  3094.                WWriteC (1,'Type in any input');
  3095.                WGotoRC (2,1);
  3096.                WriteToCRT;
  3097.              end;
  3098.  
  3099.            At the beginning of the file, let's also activate the multi-level work
  3100.            window code by placing the "$" code in front of the word "define" to look
  3101.            like:
  3102.  
  3103.              {$define MultiWorkWndws }
  3104.  
  3105.            This activates the AccessWorkWndw procedure which simply accesses the
  3106.            selected window set by TopWorkWndwName.  When TopWorkWndwName has changed,
  3107.            WorkWndwStep also needs to be reset.  In the procedure ResetWorkWndwStep,
  3108.            confirm that Window2 starts on the correct step:
  3109.  
  3110.              Window2:  WorkWndwStep := 3;
  3111.  
  3112.            Now we need some keys to get access to these windows.  Let Window1 and
  3113.            Window2 be assigned to the Alt-1 and Alt-2 keys.  To do this, go back to
  3114.            PULLSTAT.PAS and edit CheckGlobalKeys to the following:
  3115.  
  3116.                ...
  3117.                AltX:    SetQuit;
  3118.                Alt1:    SetWorkWndw (Window1);
  3119.                Alt2:    SetWorkWndw (Window2);
  3120.              else
  3121.              ...
  3122.  
  3123.            The constants for Alt1 and Alt2 have already been set for you.  SetWorkWndw
  3124.            is located just before CheckGlobalKeys and looks like:
  3125.  
  3126.              procedure SetWorkWndw (WN: WindowNames);
  3127.              begin
  3128.                PullDown        := false;
  3129.                PopToWorkWndw   := true;
  3130.                TopWorkWndwName := WN;
  3131.              end;
  3132.  
  3133.            This assigns a new Work Window name for the AccessWorkWndw procedure.  Now
  3134.            it is all set.  Give the program a run.  You will see that anytime you
  3135.            press Alt-1 or Alt-2, it immediately accesses that window even if you are
  3136.            in the menus!  And, when you get Window2, the contents are preserved.  If
  3137.            you were able to program this successfully, you have attained a highly
  3138.            sophisticated environment with little code.
  3139.  
  3140.  
  3141.            MANAGING WINDOWS
  3142.  
  3143.            We have just covered all the code necessary to have several work windows on
  3144.            the screen at once.  To randomly access any window, the Alt keys were
  3145.            assigned to a particular window number.  To hide a window, the Esc key was
  3146.            used and the contents were saved.
  3147.  
  3148.  
  3149.  
  3150.            Chapter 7, Work Windows                                             Page 52
  3151.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3152.  
  3153.  
  3154.            Should you decide to use temporary windows so that ESC would remove the
  3155.            window, just replace the two occurrences of HideWindow with RemoveWindow.
  3156.            Of course, you could make a combination of both.  You now have the tools
  3157.            for complete window management.
  3158.  
  3159.  
  3160.  
  3161.  
  3162.  
  3163.  
  3164.  
  3165.  
  3166.  
  3167.  
  3168.  
  3169.  
  3170.  
  3171.  
  3172.  
  3173.  
  3174.  
  3175.  
  3176.  
  3177.  
  3178.  
  3179.  
  3180.  
  3181.  
  3182.  
  3183.  
  3184.  
  3185.  
  3186.  
  3187.  
  3188.  
  3189.  
  3190.  
  3191.  
  3192.  
  3193.  
  3194.  
  3195.  
  3196.  
  3197.  
  3198.  
  3199.  
  3200.  
  3201.  
  3202.  
  3203.  
  3204.  
  3205.  
  3206.  
  3207.  
  3208.  
  3209.  
  3210.  
  3211.            Chapter 7, Work Windows                                             Page 53
  3212.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3213.  
  3214.  
  3215.            8.  U S E R   W I N D O W S
  3216.  
  3217.            While in the menus, you may have to create a window or a menu that differs
  3218.            from the ones in PULL.  This section will show you the pull-down directory
  3219.            included with the package and how to integrate any user window into the
  3220.            pull-down environment.
  3221.  
  3222.  
  3223.            PULL-DOWN DIRECTORY
  3224.  
  3225.            The pull-down directory unit has already been linked into the demo.  By
  3226.            now, you can probably figure out how the directory is accessed.  Looking in
  3227.            the FilesMenu, find the following code:
  3228.  
  3229.              Line[3]:='Directory';          LineMode[3]:=ToUserWndw;
  3230.                                             ProcPtr [3]:=@DoDir;
  3231.  
  3232.            To pull down a user window, the line mode is set to ToUserWndw which places
  3233.            a 3-bar symbol on that line.  Then, DoDir is the procedure that will access
  3234.            the directory and looks like:
  3235.  
  3236.              procedure DoDir;
  3237.              begin
  3238.                { Use (FileName,FileName) to initially Hilite a close match. }
  3239.                { Use (FileName,'') to start at default. }
  3240.                PullDirectory (FileName,FileName);
  3241.              end;
  3242.  
  3243.            PullDirectory handles every thing once inside the procedure.  A particular
  3244.            emphasis was made on end-user human factors in its development.
  3245.  
  3246.              . Single column - A single column, alphabetically sorted list is the
  3247.                easiest to visually scan quickly.  Multi-column lists such as the one
  3248.                provided in the TP5 environment require difficult zig-zag scanning.
  3249.  
  3250.              . Cursor key scanning - Cursor keys are the expected way to scan through
  3251.                the directory.  In addition, Home, ^Home, End, and ^End keys only move
  3252.                the HiLite while PgUp, ^PgUp, PgDn, and ^PgDn move only the page.
  3253.  
  3254.              . Letter key scanning - Any alpha-numeric key will scan for the first
  3255.                file name starting with the same first letter.  The page is moved and
  3256.                the cursor is centered as much as possible.
  3257.  
  3258.              . Lower-case text - Lower case text is more legible than the standard
  3259.                upper-case text provided by DOS.
  3260.  
  3261.              . Right justified extension - Visual searches for extensions are easier
  3262.                to read when aligned.  In addition, this also facilitates proper
  3263.                alphabetic sorting.
  3264.  
  3265.              . High speed sort - The sorting routine uses is a secondary-index quick
  3266.                sort which is the fastest kind for this application.  It is currently
  3267.                set at a limit of 250 file names are permitted, but it can be set to
  3268.                grow as much as your heap allows.
  3269.  
  3270.  
  3271.  
  3272.            Chapter 8, User Windows                                             Page 54
  3273.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3274.  
  3275.  
  3276.              . High speed scroll - The display is expected to be fast when scrolling
  3277.                and is.  Neither the HiLite nor the screen ever flicker.
  3278.  
  3279.              . Default HiLite - If a value file name is passed to the directory for
  3280.                the default other than '', the directory searches for a close match to
  3281.                HiLite.  In either case, the HiLite is centered as much as possible.
  3282.  
  3283.              . Picked file name - Pressing CR will replace the referenced file name
  3284.                passed to the directory.
  3285.  
  3286.  
  3287.            INTERFACE
  3288.  
  3289.            If you have the source code to PULLDIR.PAS, take a look at PullDirectory
  3290.            and see how the code interfaces the pull-down menus.  This is an excellent
  3291.            example of incorporating all the features to integrate with the menus:
  3292.  
  3293.              procedure PullDirectory; { (VAR NameToChange: FileNameStr;
  3294.                                              NameToHiLite: FileNameStr); }
  3295.              begin
  3296.                TurnArrows (On);                                         { 1 }
  3297.                with TopMenu do
  3298.                  CmdSeq := CmdSeq+CmdLtrs[HiLiteLine];                  { 2 }
  3299.                ShowDirMenu (NameToHiLite);                              { 3 }
  3300.                repeat
  3301.                  with DirectoryMenu do
  3302.                    begin
  3303.                      CheckForPullDown (DirectoryMenu.MsgLineNum);       { 4 }
  3304.                      if ExtKey then
  3305.                        begin
  3306.                          if HelpKeyPressed then
  3307.                            {$ifdef UseHelpWndwCode }
  3308.                            PullHelpWndw (HelpWndwNum)                   { 5 }
  3309.                            {$endif UseHelpWndwCode }
  3310.                          else ScanDirByCursor;
  3311.                        end
  3312.                      else
  3313.                        if Key<>RetKey then
  3314.                          ScanDirByLetter;
  3315.                      if (Key=RetKey) and (TotalFiles>0) then
  3316.                        begin
  3317.                          PopToWorkWndw := true;                         { 6 }
  3318.                          { ... }
  3319.                        end;
  3320.                      CheckForPop                                        { 7 }
  3321.                    end;  { with }
  3322.                until (Key=EscKey) or (Key=RetKey) or Pop;               { 8 }
  3323.                Key := NullKey;                                          { 9 }
  3324.                RemoveWindow;                                            { 10 }
  3325.                dec (CmdSeq[0]);                                         { 11 }
  3326.                TurnArrows (Off);                                        { 12 }
  3327.              end;
  3328.  
  3329.            Comments - Comments for the numbered lines follow.
  3330.  
  3331.  
  3332.  
  3333.            Chapter 8, User Windows                                             Page 55
  3334.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3335.  
  3336.  
  3337.              Line 1  - TurnArrows is a procedure that places arrow symbols on
  3338.                        the top menu to direct the user's attention to the new
  3339.                        menu.
  3340.              Line 2  - Append CmdSeq so that PULL can know how it got to this
  3341.                        menu.
  3342.              Line 3  - This procedure actually produces the window on the CRT
  3343.                        and it custom designed.
  3344.              Line 4  - CheckForPullDown monitors keyboard entry and displays a
  3345.                        message.
  3346.              Line 5  - You can include your custom help window here.
  3347.              Line 6  - Once the item was selected on the menu, this option
  3348.                        commands PULL to return to the top work window.  This is
  3349.                        optional.
  3350.              Line 7  - CheckForPop analyzes all the menu controls flags,
  3351.                        including PopToWorkWndw, to see if a request has been
  3352.                        made to pop out of the menu.  If so, Pop is set to true.
  3353.              Line 8  - The repeat/until construct provides a gated exit.
  3354.              Line 9  - Alter the value of Key so the next menu will ignore an
  3355.                        EscKey value.  ESC is meant to pop only one menu.  If the
  3356.                        key was not changed, the menus would continue to pop
  3357.                        until is was back into the work window.
  3358.              Line 10 - The exit has been confirmed and the window/menu needs to
  3359.                        be removed from the CRT.
  3360.              Line 11 - Adjust CmdSeq for one pop.
  3361.              Line 12 - Turn the arrows back off of the top menu.
  3362.  
  3363.            This same construct can be used for any user window/menu to be included
  3364.            with the pull-down menus.
  3365.  
  3366.  
  3367.  
  3368.  
  3369.  
  3370.  
  3371.  
  3372.  
  3373.  
  3374.  
  3375.  
  3376.  
  3377.  
  3378.  
  3379.  
  3380.  
  3381.  
  3382.  
  3383.  
  3384.  
  3385.  
  3386.  
  3387.  
  3388.  
  3389.  
  3390.  
  3391.  
  3392.  
  3393.  
  3394.            Chapter 8, User Windows                                             Page 56
  3395.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3396.  
  3397.  
  3398.            9.  C O N D I T I O N A L   C O M P I L A T I O N
  3399.  
  3400.            Many times your application may not need to use all of the features built
  3401.            into PULL.  Although most of the code is optimized out by the compiler,
  3402.            some of the code is nested and it would be helpful to eliminate some of
  3403.            that code.  This section will show you how easy it is to do this.
  3404.  
  3405.  
  3406.            DEFINE SYMBOLS
  3407.  
  3408.            Here is a complete list of the define symbols used in PULL:
  3409.  
  3410.              UseSubMenuCode   - to include submenus.
  3411.              UseHelpWndwCode  - to include help windows.
  3412.              UseDataEntryCode - to include data entry or data windows.
  3413.              UseMsgLineCode   - to include normal and error messages.
  3414.              MultiWorkWndws   - to include multi-level work windows.
  3415.  
  3416.            Location - You can find these directives defined on the first page of all
  3417.            *.PAS files.  Most files will not have every one of them, but only the ones
  3418.            that affect it.
  3419.  
  3420.            Definition - When you see the define directive, it will look like:
  3421.  
  3422.              {$define UseSubMenuCode }
  3423.  
  3424.            With the "$" in its place, UseSubMenuCode would be defined and would
  3425.            include all of the submenu code.  If you do not want the code, then
  3426.            undefine it by just removing the "$":
  3427.  
  3428.              { define UseSubMenuCode }
  3429.  
  3430.            Affected Files - Should you decide to undefine a symbol, you should
  3431.            undefine it in ALL affected files including PULL.  You can get away without
  3432.            changing PULL on all of them except UseMsgLineCode where you must change it
  3433.            in PULL as well.
  3434.  
  3435.  
  3436.            RECOMPILING
  3437.  
  3438.            Once you have changed all the needed directives, do a Make and the code
  3439.            will be ready for use.
  3440.  
  3441.  
  3442.  
  3443.  
  3444.  
  3445.  
  3446.  
  3447.  
  3448.  
  3449.  
  3450.  
  3451.  
  3452.  
  3453.  
  3454.  
  3455.            Chapter 9, Conditional Compilation                                  Page 57
  3456.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3457.  
  3458.  
  3459.            10.  T R O U B L E   S H O O T I N G
  3460.  
  3461.            PULL is a well thought out unit.  If you find that the program has not done
  3462.            what you expected, there may be something that you overlooked.  This
  3463.            section will try to help jog your memory as to what the problems may be.
  3464.  
  3465.  
  3466.            GOOF UNIT
  3467.  
  3468.            All programmers make mistakes, right?  So, what happens when you try to
  3469.            make more windows than there are records available?  Since WNDW and PULL
  3470.            are powerful tools and can even write in RAM, there is a good possibility
  3471.            that your mistake may not even show up on the screen.  How do you know if
  3472.            anything has gone wrong?  The GOOF unit was made especially for handling
  3473.            errors.
  3474.  
  3475.            Displaying Errors - When an error is found in your program, the ShowGoof
  3476.            procedure is called and the program is terminated.  The CRT will display an
  3477.            error message in a flashing window.  There are eight fatal errors that are
  3478.            listed in APPENDIX B in WNDWREF.DOC to identify problems before they
  3479.            happen.  Please refer to it for the error messages and their solutions.  If
  3480.            you do not have a copy of WNDW55.ARC, you can get one direct from the
  3481.            Eagle.
  3482.  
  3483.            Flexibility - ShowGoof is accessed indirectly with an indirect call.  This
  3484.            means that you can freely edit the GOOF unit without needing to recompile
  3485.            WNDW or PULL.  You can even edit it for use in your own applications.  The
  3486.            error message numbers 1-50 are reserved.  So, for your own applications, it
  3487.            is suggested that you start with number 51.  If you have thoroughly tested
  3488.            your program, some of the messages can be eliminated.
  3489.  
  3490.            Using GOOF - It is very important that GOOF be included in the USES list.
  3491.            You may find that it compiles without it, but if an error does occur, your
  3492.            system will surely crash.  Notice that GOOF is the last unit in the USES
  3493.            list in the main program.
  3494.  
  3495.  
  3496.            FAR ADDRESSES
  3497.  
  3498.            Because PULL uses several pointers for procedures and variables, it is
  3499.            quite possible to lock up your computer if these are not properly
  3500.            addressed.  A debugger is most helpful in these circumstances.  But if you
  3501.            do not have one, here is a check list of possible causes:
  3502.  
  3503.  
  3504.            Forcing FAR - The far pointers used by TranslateProc, CheckRangeProc, and
  3505.            ProcPtr must be calling FAR procedures.  All procedures that are not
  3506.            declared in the interface of a unit must be forced to FAR with the
  3507.            directive {$F+} when called by a pointer.
  3508.  
  3509.            Indirect Calls - PULL has several inline calls for indirect FAR calls
  3510.            outside of the calling unit.  The addresses for these units must be
  3511.            assigned in the destination unit with an Addr* variable and is usually done
  3512.            in the BEGIN/END for initialization.  Here is a list of those procedures
  3513.            and calling address variables:
  3514.  
  3515.  
  3516.            Chapter 10, Trouble Shooting                                        Page 58
  3517.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3518.  
  3519.  
  3520.  
  3521.               Procedure         Address Variable      Unit
  3522.               ----------------  --------------------  --------
  3523.               GetUserPullStats  AddrGetUserPullStats  PullStat
  3524.               GetOverrideStats  AddrGetOverrideStats  PullStat
  3525.               WorkWndw          AddrWorkWndw          PullWork
  3526.               CheckGlobalKeys   AddrCheckGlobalKeys   PullStat
  3527.               ShowGoof          AddrGoof              Goof
  3528.               KbdIdle           AddrKbdIdle           Any
  3529.  
  3530.            Using Units - Because of indirect calls, the compiler does not know that
  3531.            some units need to be linked.  PullStat, PullWork, and Goof are three units
  3532.            that MUST be in the USES list of the main program.
  3533.  
  3534.            KbdIdle - The far procedure KbdIdle must be used and can be located in any
  3535.            unit.  This procedure does background processing while the keyboard is
  3536.            idle.
  3537.  
  3538.            Data - The variable address and type of data in each data record must
  3539.            exactly match or risk possible data loss.  Strings lengths must not be
  3540.            longer than MaxField.
  3541.  
  3542.  
  3543.            MULTI-TASKING
  3544.  
  3545.            This demo has already been set to work in multi-tasking environments
  3546.            compatible to DESQview, TopView, and IBM 3270 PC Workstation.  It uses the
  3547.            multi-tasking video buffer (MTVB) whenever possible.  To always disable
  3548.            MTVB use, set PreferMultiTask to false in PULLSHEL.PAS.
  3549.  
  3550.            CUSTOMER SERVICE
  3551.  
  3552.            If you are still having problems, leave us a message or give us a call.
  3553.  
  3554.  
  3555.  
  3556.  
  3557.  
  3558.  
  3559.  
  3560.  
  3561.  
  3562.  
  3563.  
  3564.  
  3565.  
  3566.  
  3567.  
  3568.  
  3569.  
  3570.  
  3571.  
  3572.  
  3573.  
  3574.  
  3575.  
  3576.  
  3577.            Chapter 10, Trouble Shooting                                        Page 59
  3578.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3579.  
  3580.  
  3581.            A P P E N D I X   A :   O T H E R   P R O D U C T S
  3582.  
  3583.  
  3584.            Eagle Performance Software has developed identical products for both Turbo
  3585.            C and Turbo Pascal.  Our pledge is to provide you quality products with
  3586.            unparalleled performance and ease of use.
  3587.  
  3588.  
  3589.            QWIK
  3590.  
  3591.            QWIK - For direct screen video, QWIK is the highest performance screen
  3592.            writing tools available today for all text modes in any video
  3593.            configuration.  QWIK provides capabilities far beyond in the unit/library
  3594.            that comes with your compiler.   Here are some of the features:
  3595.  
  3596.              . Writes on all IBM compatible computers, displays and adapters
  3597.                including MDA, CGA, EGA, MCGA, VGA, 8514/A, Hercules and 3270
  3598.                PC.
  3599.              . Superior video detection routine.
  3600.              . Eliminates snow and flicker.
  3601.              . Writes directly to the screen in absolute rather than relative
  3602.                coordinates.
  3603.              . Writes in all text modes and column modes.
  3604.              . Writes on all video pages.
  3605.              . Writes on virtual screens in RAM.
  3606.              . Writes text and attribute, text only, or attribute only.
  3607.              . Reads strings, characters and attributes.
  3608.              . Uses End-Of-String (EOS) marker for quick string chaining.
  3609.              . Provides standardized cursor shapes for all adapters.
  3610.              . Enhanced cursor movement.
  3611.              . Compatible with DESQview and similar multitasking environments.
  3612.              . Over 650% faster than standard direct screen writing.
  3613.              . Only 2.7k bytes of code if all 43 utilities are used.
  3614.              . Writes direct to multi-tasking video buffers (MTVB).
  3615.              . Optimized by the compiler and drops unused code.
  3616.              . Used in all other Eagle products.
  3617.  
  3618.            Here are the product versions:
  3619.  
  3620.               File name    CIS name    Compiler  Release date
  3621.               -----------  ----------  --------  ------------
  3622.               QWIK55.ARC   QWIK55.ARC  TP4-5.5    08-24-89
  3623.               QWIKC21.ARC  QWKC21.ARC  TC2        07-06-89
  3624.  
  3625.  
  3626.            WNDW
  3627.  
  3628.            WNDW - For multi-level virtual windows, WNDW is the highest performance
  3629.            window utilities available today.  It offers very powerful utilities for
  3630.            full window control and management you probably never thought possible.
  3631.            They are simple and yet very powerful with high speed and tight code.  With
  3632.            WNDW, you can choose the absolute writing routines of QWIK, the window-
  3633.            relative writing routines of WNDW, and even customize your own.  Here are
  3634.            some of the features you will discover:
  3635.  
  3636.  
  3637.  
  3638.            Appendix A: Other Products                                          Page 60
  3639.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3640.  
  3641.  
  3642.            . Uses the powerful direct screen writing routines of QWIK.
  3643.            . Up to 254 fixed or virtual windows can be on the screen at one time.
  3644.            . Extremely high-speed virtual screens in RAM (up to 40 times faster).
  3645.            . Virtual windows are fully updated on screen, even if covered!
  3646.            . Virtual windows have virtual titles.
  3647.            . Fully supported hidden windows saved in RAM.
  3648.            . Fully supports all video pages.
  3649.            . Adjustable-rate moving, resizing, and scrolling.
  3650.            . All windows can be randomly accessed, not just stacked or tiled.
  3651.            . 28 window-relative writing routines.
  3652.            . 15 different border styles with shadow and zoom effects.
  3653.            . Full line drawing procedures.
  3654.            . Full cursor mode control for each window.
  3655.            . Writes in all text modes and column modes.
  3656.            . Writes direct to multi-tasking video buffers (MTVB).
  3657.            . Only 13k bytes of code if all 69 utilities are used.
  3658.            . Used in all other Eagle products.
  3659.  
  3660.            Here are the product versions:
  3661.  
  3662.               File name    CIS name    Compiler  Release date
  3663.               -----------  ----------  --------  ------------
  3664.               WNDW55.ARC   WNDW55.ARC  TP4-5.5    08-24-89
  3665.               WNDWC21.ARC  WNDC21.ARC  TC2        08-01-89
  3666.  
  3667.  
  3668.            PULL
  3669.  
  3670.            Here are the product versions:
  3671.  
  3672.               File name    CIS name    Compiler  Release date
  3673.               -----------  ----------  --------  ------------
  3674.               PULL55.ARC   PULL55.ARC  TP4-5.5    08-24-89
  3675.               PULLC21.ARC  PULC21.ARC  TC2        08-01-89
  3676.  
  3677.  
  3678.            ON-LINE SERVICES
  3679.  
  3680.            CompuServe - All updated files and later versions can be found on the
  3681.            CompuServe Borland Forums (GO BPROGA for TP and GO BPROGB for TC) or the
  3682.            IBM Programming Forum (GO IBMPRO).
  3683.  
  3684.  
  3685.            RELEASE DATES
  3686.  
  3687.            Please note that the release dates are only estimates.
  3688.  
  3689.  
  3690.  
  3691.  
  3692.  
  3693.  
  3694.  
  3695.  
  3696.  
  3697.  
  3698.  
  3699.            Appendix A: Other Products                                          Page 61
  3700.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3701.  
  3702.  
  3703.            A P P E N D I X   B :   R E V I S I O N   H I S T O R Y
  3704.  
  3705.            REVISIONS:
  3706.  
  3707.            Version 2.0 (01-12-88):
  3708.              . Converted to TP4 and incorporated QWIK40 and PULL40.
  3709.              . Added pull-down directory with path and mask.
  3710.              . Added global keys like Alt-F and Alt-X in PULLSTAT.PAS.
  3711.              . Eliminated PULLUSER.INC and instead allow access to user
  3712.                  windows direct through PullProc.Process.
  3713.              . Menu partitions now use Wndw.BrdrRec.
  3714.              . Added TypeOfDataTypes Word and LongInt.
  3715.              . Added "ClearScreen" option in InitPull.
  3716.              . Deleted i and j variables in PULL20.PAS.
  3717.              . Modified Pull.TempMsg; Deleted TempMsgArray.
  3718.              . Top menu record is available from TopMenuRecPtr^.
  3719.  
  3720.            Version 4.2 (01-03-89):
  3721.              . Incorporated QWIK42 and WNDW42.
  3722.              . Added excellent documentation.
  3723.              . Expanded the fill-in-the-blank concept.
  3724.              . Simplified work window data entry with sequential data entry
  3725.                routines.
  3726.              . Changed data windows to the slide-under configuration.
  3727.              . Added complete editing in data entry fields.
  3728.              . Added custom set control for data entry and deleted UserStrings.
  3729.              . Added key translation and range checking pointers.
  3730.              . Added multi-level window control.
  3731.              . Deleted PullProc.pas and the Process and Transfer procedures and
  3732.                replaced them with pointers.
  3733.              . Added automatic menu and line counting.
  3734.              . Simplified Menu Modes with execution pointers.
  3735.              . Changed menu records from global to dynamic data.
  3736.              . Improved submenu linking following the direction trend of the parent
  3737.                menu.
  3738.  
  3739.            Version 5.X (01-07-89):
  3740.              . Compiled PULL42 under TP5.  No other changes.
  3741.  
  3742.            Version 5.Xa (01-11-89):
  3743.              . Corrected right-arrow key problem in data entry (P5X-DATA.INC).
  3744.              . Improved cursor mode handling during dynamic updates.
  3745.  
  3746.            Version 5.Xb (03-04-89):
  3747.              . Incorporated QWIK5XA and WNDW5XB for multi-tasking.
  3748.              . Added new LineModeType of NoChoice for dynamic disabling of any line.
  3749.  
  3750.            Version 5.Xc (05-29-89):
  3751.              . Incorporated WNDW5XC.  No other changes.
  3752.  
  3753.            Version 5.5 (08-24-89):
  3754.              . Compiled PULL5XC under TP 5.5.  No other changes.
  3755.  
  3756.  
  3757.  
  3758.  
  3759.  
  3760.            Appendix B: Revision History                                        Page 62
  3761.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3762.  
  3763.  
  3764.            A P P E N D I X   C :   C R E D I T S
  3765.  
  3766.            Art Hill started some initial ideas on this with PullDown.arc
  3767.  
  3768.               Art Hill
  3769.               936 S. Kensington Ave.
  3770.               La Grange, IL 60525
  3771.               CIS 72307,3570
  3772.  
  3773.            Copyright (c) 1986-1989 by James H. LeMay for Eagle Performance Software.
  3774.            All Rights Reserved.  Protected by the United States Copyright Laws.
  3775.  
  3776.            Turbo Pascal is a trademark of Borland International.
  3777.            WordStar is a trademark of MicroPro International.
  3778.  
  3779.  
  3780.  
  3781.  
  3782.  
  3783.  
  3784.  
  3785.  
  3786.  
  3787.  
  3788.  
  3789.  
  3790.  
  3791.  
  3792.  
  3793.  
  3794.  
  3795.  
  3796.  
  3797.  
  3798.  
  3799.  
  3800.  
  3801.  
  3802.  
  3803.  
  3804.  
  3805.  
  3806.  
  3807.  
  3808.  
  3809.  
  3810.  
  3811.  
  3812.  
  3813.  
  3814.  
  3815.  
  3816.  
  3817.  
  3818.  
  3819.  
  3820.  
  3821.            Appendix C: Credits                                                 Page 63
  3822.            PULL Multi-level Pull-Down Menus                 User's Guide, Version 5.5
  3823.  
  3824.  
  3825.            A P P E N D I X   D :   G L O S S A R Y
  3826.  
  3827.            Command letter - A letter highlighted in a menu that executes that line.
  3828.            Command sequence - The sequence of command letters pressed to arrive at a
  3829.                            window or menu.
  3830.            Data entry    - Field for entering data into the application program in the
  3831.                            work windows or user windows.
  3832.            Data window   - Window for entering data into the application program from
  3833.                            the menus.
  3834.            Error message - A short message for data out of range.
  3835.            Field         - A highlighted area reserved for a data entry string to be
  3836.                            displayed.
  3837.            Flex field    - A field that allows more characters into the data entry
  3838.                            than what the field displays.
  3839.            Free field    - A field that allows a continuous string of characters to
  3840.                            expand in the field in any position.  This is in contrast
  3841.                            to formatted fields where each column is designated an
  3842.                            entry.
  3843.            Local key     - A key that only works within the menu or window.
  3844.            Gated exit    - A procedure that lets the flow of execution pass through
  3845.                            back to PULL's key dispatcher only on specific keystrokes.
  3846.            Global key    - A key that accesses a different part of the program at any
  3847.                            time.
  3848.            Help message  - A message appear on the message line for keyboard
  3849.                            instructions.
  3850.            Help window   - A window displayed by pressing F1 that provides context-
  3851.                            sensitive help.
  3852.            HiLited       - A highlighted bar pointed at in a menu.
  3853.            Level         - A window or menu where the program is operating.
  3854.            Line          - A row of text.
  3855.            Link          - A menu line showing a symbol (three-bar or dot) that pulls
  3856.                            another menu or window.  The symbol is also on the same
  3857.                            side where it is pulled.
  3858.            Main menu     - The first menu pulled from the Top Line menu.
  3859.            Menu          - A list of selectable lines.
  3860.            Message line  - The bottom row to display key helps or processing status.
  3861.            MTVB          - Multi-Tasking Video Buffer used in multi-tasking
  3862.                            environments.
  3863.            Pop           - removes menu and returns to the previous menu.
  3864.            PullDown      - pulls menus down to the previous level.
  3865.            Selection     - A line selected in a menu with a CR.
  3866.            Shell         - A bare bones program of pull-down menus to get you started
  3867.                            in your own application.
  3868.            Slide-under   - The configuration of data windows them to slide under the
  3869.                            HiLite if the field grows wider.
  3870.            Slide-up      - The configuration of submenus that allows them to slide
  3871.                            upward as the menu list grows.
  3872.            Status line   - A optional line reserved for status information pertinent
  3873.                            to your program.
  3874.            Submenu       - All subsequent menus pulled after a main menu.
  3875.            Top Line menu - The menu always shown (usually in row 1 or 2).
  3876.            Window        - Not a menu.
  3877.            Work window   - The window where the bulk of the application is shown.
  3878.  
  3879.  
  3880.  
  3881.  
  3882.            Appendix D: Glossary                                                Page 64
  3883.  
  3884.