home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR19 / RLIBDOC.ZIP / RLIB.DOC < prev   
Text File  |  1993-08-20  |  511KB  |  13,019 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.                                       RLIB
  13.                                    Version 3.0
  14.  
  15.  
  16.  
  17.  
  18.              Useful Functions for the Clipper Application Programmer
  19.                                  by Richard Low
  20.                                  August 1, 1991
  21.  
  22.  
  23.  
  24.  
  25.                            Copyright 1991 Richard Low
  26.                                All Rights Reserved
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.                                   RLIB Software
  51.                               Post Office Box 3232
  52.                           Durham, North Carolina 27715
  53.                                  (919) 383-0488
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82.                             For My Wife and Children
  83.  
  84.  
  85.    Copyright Notice
  86.  
  87.       The RLIB function library is protected by United States copyright laws
  88.       and international treaty provisions.  The RLIB function library,
  89.       source code, demonstration program, and documentation Copyright 1991
  90.       Richard Low.  All rights reserved.  No part of the RLIB function
  91.       library, source code, demonstration program, documentation or related
  92.       files may be reproduced, photocopied, or transmitted except as
  93.       provided by the license.
  94.  
  95.  
  96.    Software License Agreement
  97.  
  98.       The RLIB function library (hereinafter referred to as "RLIB" or "the
  99.       Software") consists of the binary code which has been compiled and
  100.       assembled into a library file, together with the source code, the
  101.       demonstration programs, sample source code and software documentation. 
  102.       All notices, copyright and otherwise, together with the license
  103.       agreement, restrictions and warranties apply to all of the components
  104.       of RLIB.  Richard Low is the sole author of RLIB.  Hereinafter, the
  105.       term "Author" refers to Richard Low.
  106.  
  107.  
  108.       Shareware Version
  109.  
  110.       The Author is offering you a license to use the RLIB function library
  111.       for a trial period of for 21 days.  If you continue to use RLIB 3.0
  112.       after the 21 day evaluation period, you are obligated to purchase it. 
  113.       The shareware version of RLIB, together with the accompanying
  114.       documentation may be freely copied and shared with others provided
  115.       that the following conditions are met:
  116.  
  117.           1. You may not distribute the shareware version of RLIB in any
  118.              modified form.
  119.  
  120.           2. You may not charge any fee for the shareware version of RLIB or
  121.              for its distribution.
  122.  
  123.           3. You must distribute all of the components of the shareware
  124.              version of RLIB as described in the section entitled Contents.
  125.  
  126.  
  127.       Registered Version
  128.  
  129.       As a registered owner of RLIB your are granted a license to use RLIB
  130.       on a single computer for a period of 99 years.  RLIB may not be
  131.       installed on a network unless each person who may access RLIB from
  132.       such a network possesses their own registered copy of RLIB.
  133.  
  134.       With the registered version of RLIB the Author also grants you a
  135.       license to use the single user version of Message Reader on a single
  136.       computer, also for a period of 99 years.  The single user version of
  137.       the Message Reader program may not be installed on a network unless
  138.       each person who may use Message Reader from such a network possesses
  139.       their own registered copy of RLIB or Message Reader.
  140.  
  141.                                                                           iii
  142.  
  143.  
  144.       Programs that you write and compile which make use of one or more of
  145.       the functions in RLIB may be used, given away, or sold without any
  146.       additional license fee or royalty due to the Author.  You are not
  147.       required to indicate that your programs were developed using the RLIB
  148.       function library or that they contain source code provided with RLIB. 
  149.       However, the source code that is supplied with RLIB is copyrighted
  150.       material.  You may use the source code to support your licensed copy
  151.       of RLIB.  You may include the source code in your own development
  152.       programs, but you may only distribute copies of them in executable
  153.       form.  If your program source contains RLIB function or demo program
  154.       source code, you may not distribute the parts of your source code that
  155.       contain RLIB function or demo program source code.  In other words,
  156.       you may not distribute any part of the RLIB function library or demo
  157.       program source code.  You may not distribute the RLIB library in
  158.       object code except as included in your executable programs as outlined
  159.       above.  You are, of course, free to distribute your own source code
  160.       which may reference RLIB functions.
  161.  
  162.       You may modify the RLIB source code, but the modified source code,
  163.       regardless of the extent of the modifications, shall always remain the
  164.       Authors source code.  Modification or rewriting of the source code
  165.       does not give you rights of ownership.  You may not remove or modify
  166.       the Authors copyright and other proprietary rights notices.  You may
  167.       not distribute any part of the source code, regardless of the extent
  168.       of the modifications, and you may not transport any of the source code
  169.       to another computer or language development environment.  You shall be
  170.       responsible for all claims, liability, and damages arising from your
  171.       own modifications and the products which include them.
  172.  
  173.       Message Reader Program
  174.  
  175.       The Message Reader program and source code are Copyright 1991 by
  176.       Richard Low and may not be reproduced in any form.  You do not own the
  177.       Message Reader or RLIB source code; it is supplied for demonstration
  178.       and instructional purposes only.  Just as with a book, you may
  179.       reference the source code, but you may not copy it in any form,
  180.       electronic or otherwise.  Even if you modify the Message Reader source
  181.       code, it still remains the sole property of the Author.  Modification
  182.       or rewriting of the source code does not give you rights of ownership. 
  183.       You may not distribute the Message Reader or RLIB source code even if
  184.       you make modifications, and you may not distribute any modified
  185.       version of the Message Reader executable program.
  186.  
  187.    Copyright
  188.  
  189.       The RLIB function library, source code, and documentation, and the
  190.       Message Reader program, source code, and documentation are protected
  191.       by United States copyright laws and international treaty provisions. 
  192.       Therefore, you must treat this software like any other copyrighted
  193.       material such as a book.  You are authorized to make archival copies
  194.       for the sole purpose of backing up the software.  You may also copy
  195.       RLIB to a single hard disk, and move RLIB from one hard disk to
  196.       another, provided that this copy of RLIB is not used on more than one
  197.       computer at the same time.  You may not copy the written documentation
  198.       which accompanies RLIB.
  199.  
  200.                                                                            iv
  201.  
  202.  
  203.    Limited Warranty
  204.  
  205.       The RLIB function library software is provided "as is".  The Author
  206.       will replace, at no charge, defective media and product materials that
  207.       are returned within 90 days of the original date of purchase.  The
  208.       Author warrants that RLIB will perform in substantial compliance with
  209.       the documentation.  If you report, in writing, a significant defect to
  210.       the Author, and the Author is unable to correct it within 90 days of
  211.       the date you report the defect, you may return the software and all
  212.       accompanying materials and destroy any and all copies of the software
  213.       you may have made, and the Author will refund the purchase price. 
  214.       Should you encounter problems with the Software, the Author's entire
  215.       liability and your exclusive remedy shall be that the Author, at the
  216.       Author's sole option, will be to either refund you the purchase price
  217.       (upon the conditions met above) or to repair or replace the Software.
  218.  
  219.    Disclaimer of Warranties
  220.  
  221.       The Author makes no claims or representations as to the suitability of
  222.       the Software for any specific use.  Except for the Limited Warranty
  223.       stated above, the Author disclaims any and all other warranties,
  224.       express or implied, oral or written, including any implied warranties
  225.       of merchantability or fitness for a particular purpose.  In no event
  226.       will the Author be liable to you for damages, including any loss of
  227.       profits, lost savings, or other incidental or consequential damages
  228.       arising out of your use of or inability to use the software, even if
  229.       the Author or an authorized representative of the Author has been
  230.       advised of the possibility of such damages.
  231.  
  232.       This limited warranty gives you specific legal rights, but you may
  233.       have other rights, which vary from state to state.  Some states do not
  234.       allow excluding or limiting implied warranties or limiting liability
  235.       for incidental or consequential damages, therefore the above
  236.       limitations may not apply to you.
  237.  
  238.    Trademark Acknowledgements
  239.  
  240.       Blinker is a trademark of Blink, Inc.
  241.       Clipper and Nantucket are trademarks of Nantucket Corporation.
  242.       CompuServe is a trademark of CompuServe Incorporated.
  243.       dBASE, and dBASE III are trademarks of Ashton-Tate, Inc.
  244.       IBM, PC, XT, AT, PS/2, and PC-DOS are trademarks of International
  245.       Business Machines Corp.
  246.       LOTUS and 123 are trademarks of Lotus Development Corporation.
  247.       MASM, LIB, MS-DOS, Microsoft, Microsoft Object Linker and Microsoft
  248.       Library Manager are trademarks of Microsoft Corporation.
  249.       The Norton Guides, The Norton Guide Reference Database Engine are
  250.       trademarks of Peter Norton Computing, Inc.
  251.       PLINK86 and PLINK86plus are trademarks of Phoenix Technologies, Ltd.
  252.       TAPCIS is a trademark of Support Group, Inc.
  253.       TLINK, Turbo Link, TLIB, and Turbo Librarian are trademarks of Borland
  254.       International.
  255.  
  256.       Any other trademarks of other companies which may appear in this
  257.       documentation are for identification purposes only.
  258.  
  259.                                                                             v
  260.  
  261.  
  262.                                 TABLE OF CONTENTS
  263.  
  264.  
  265.  
  266.    Chapter 1: Introduction
  267.           What Is RLIB?  . . . . . . . . . . . . . . . . . . . . . . . .    2
  268.           What You Get!  . . . . . . . . . . . . . . . . . . . . . . . .    3
  269.           The Source Code  . . . . . . . . . . . . . . . . . . . . . . .    4
  270.           Contents . . . . . . . . . . . . . . . . . . . . . . . . . . .    5
  271.              Shareware Version . . . . . . . . . . . . . . . . . . . . .    5
  272.              Registered Version  . . . . . . . . . . . . . . . . . . . .    6
  273.           Changes From Version 2.0 . . . . . . . . . . . . . . . . . . .    7
  274.              Functions Enhanced from RLIB version 2.0  . . . . . . . . .    9
  275.  
  276.    Chapter 2: Obtaining RLIB
  277.           Registration . . . . . . . . . . . . . . . . . . . . . . . . .   11
  278.           Technical Support  . . . . . . . . . . . . . . . . . . . . . .   11
  279.           Order Information  . . . . . . . . . . . . . . . . . . . . . .   12
  280.  
  281.    Chapter 3: Using RLIB
  282.           System Requirements  . . . . . . . . . . . . . . . . . . . . .   15
  283.           Installation . . . . . . . . . . . . . . . . . . . . . . . . .   15
  284.           Linking RLIB Into Your Applications  . . . . . . . . . . . . .   16
  285.              Dynamic Overlay Linkers . . . . . . . . . . . . . . . . . .   16
  286.           Modifying The RLIB Library . . . . . . . . . . . . . . . . . .   17
  287.              Clipper Summer '87  . . . . . . . . . . . . . . . . . . . .   17
  288.              Clipper 5.0 . . . . . . . . . . . . . . . . . . . . . . . .   17
  289.           RLIB Function Overview . . . . . . . . . . . . . . . . . . . .   18
  290.              Parameter Syntax Verification . . . . . . . . . . . . . . .   18
  291.              RLIB Error Reporting  . . . . . . . . . . . . . . . . . . .   18
  292.           Quick Function Listing . . . . . . . . . . . . . . . . . . . .   19
  293.           Source Code File List  . . . . . . . . . . . . . . . . . . . .   21
  294.  
  295.    Chapter 4: The Message Reader Demo Program
  296.           A Full Feature Application . . . . . . . . . . . . . . . . . .   24
  297.           Message Reader Source Code . . . . . . . . . . . . . . . . . .   24
  298.              Source Code Files . . . . . . . . . . . . . . . . . . . . .   24
  299.           RLIB Functions Used in Message Reader  . . . . . . . . . . . .   25
  300.              The PROGNAME() Function . . . . . . . . . . . . . . . . . .   25
  301.           Compiling and Linking Message Reader . . . . . . . . . . . . .   26
  302.  
  303.    Chapter 5: RLIB Function Reference
  304.           ABOXASK()  . . . . . . . . . . . . . . . . . . . . . . . . . .   29
  305.           ACRONYM()  . . . . . . . . . . . . . . . . . . . . . . . . . .   31
  306.           ADIM2()  . . . . . . . . . . . . . . . . . . . . . . . . . . .   32
  307.           ALIST()  . . . . . . . . . . . . . . . . . . . . . . . . . . .   33
  308.           ALPHADATE()  . . . . . . . . . . . . . . . . . . . . . . . . .   35
  309.           ANYCHARSIN() . . . . . . . . . . . . . . . . . . . . . . . . .   36
  310.           ARRAYLEN() . . . . . . . . . . . . . . . . . . . . . . . . . .   37
  311.           ATINSAY()  . . . . . . . . . . . . . . . . . . . . . . . . . .   38
  312.           BARMENU()  . . . . . . . . . . . . . . . . . . . . . . . . . .   39
  313.           BEEP() . . . . . . . . . . . . . . . . . . . . . . . . . . . .   42
  314.           BIN2DEC()  . . . . . . . . . . . . . . . . . . . . . . . . . .   43
  315.           BLIP() . . . . . . . . . . . . . . . . . . . . . . . . . . . .   44
  316.  
  317.  
  318.    Table of Contents                                                       vi
  319.  
  320.  
  321.           BORDERBOX()  . . . . . . . . . . . . . . . . . . . . . . . . .   45
  322.           BOXASK() . . . . . . . . . . . . . . . . . . . . . . . . . . .   47
  323.           BOXMENU()  . . . . . . . . . . . . . . . . . . . . . . . . . .   50
  324.           BRIGHT() . . . . . . . . . . . . . . . . . . . . . . . . . . .   54
  325.           BUZZ() . . . . . . . . . . . . . . . . . . . . . . . . . . . .   55
  326.           CALENDAR() . . . . . . . . . . . . . . . . . . . . . . . . . .   56
  327.           CATF() . . . . . . . . . . . . . . . . . . . . . . . . . . . .   59
  328.           CENTER() . . . . . . . . . . . . . . . . . . . . . . . . . . .   61
  329.           CFTA() . . . . . . . . . . . . . . . . . . . . . . . . . . . .   63
  330.           CHANGED()  . . . . . . . . . . . . . . . . . . . . . . . . . .   65
  331.           CHECKFILE()  . . . . . . . . . . . . . . . . . . . . . . . . .   67
  332.           CLOSEAREA()  . . . . . . . . . . . . . . . . . . . . . . . . .   70
  333.           DBFCREATE()  . . . . . . . . . . . . . . . . . . . . . . . . .   72
  334.           DEC2HEX()  . . . . . . . . . . . . . . . . . . . . . . . . . .   74
  335.           DECRYPTED()  . . . . . . . . . . . . . . . . . . . . . . . . .   75
  336.           DIVIDE() . . . . . . . . . . . . . . . . . . . . . . . . . . .   76
  337.           ENCRYPTED()  . . . . . . . . . . . . . . . . . . . . . . . . .   77
  338.           FEOF() . . . . . . . . . . . . . . . . . . . . . . . . . . . .   78
  339.           FILEDATE() . . . . . . . . . . . . . . . . . . . . . . . . . .   79
  340.           FILES()  . . . . . . . . . . . . . . . . . . . . . . . . . . .   80
  341.           FILESIZE() . . . . . . . . . . . . . . . . . . . . . . . . . .   81
  342.           FILETIME() . . . . . . . . . . . . . . . . . . . . . . . . . .   82
  343.           FORGET() . . . . . . . . . . . . . . . . . . . . . . . . . . .   83
  344.           FPROMPT()  . . . . . . . . . . . . . . . . . . . . . . . . . .   85
  345.           FREADLINE()  . . . . . . . . . . . . . . . . . . . . . . . . .   87
  346.           FRESTSCREEN()  . . . . . . . . . . . . . . . . . . . . . . . .   88
  347.           FSAVESCREEN()  . . . . . . . . . . . . . . . . . . . . . . . .   90
  348.           GETFILE()  . . . . . . . . . . . . . . . . . . . . . . . . . .   92
  349.           GETKEY() . . . . . . . . . . . . . . . . . . . . . . . . . . .   94
  350.           GETPARM()  . . . . . . . . . . . . . . . . . . . . . . . . . .   96
  351.           HEX2DEC()  . . . . . . . . . . . . . . . . . . . . . . . . . .   98
  352.           ISDBF()  . . . . . . . . . . . . . . . . . . . . . . . . . . .   99
  353.           ISFIELD()  . . . . . . . . . . . . . . . . . . . . . . . . . .  100
  354.           KEYINPUT() . . . . . . . . . . . . . . . . . . . . . . . . . .  101
  355.           MAKEALIAS()  . . . . . . . . . . . . . . . . . . . . . . . . .  103
  356.           MARKREC()  . . . . . . . . . . . . . . . . . . . . . . . . . .  104
  357.           MEMORIZE() . . . . . . . . . . . . . . . . . . . . . . . . . .  107
  358.           MIDDLE() . . . . . . . . . . . . . . . . . . . . . . . . . . .  109
  359.           MREPLACE() . . . . . . . . . . . . . . . . . . . . . . . . . .  110
  360.           MULTIMENU()  . . . . . . . . . . . . . . . . . . . . . . . . .  111
  361.           NAMESPLIT()  . . . . . . . . . . . . . . . . . . . . . . . . .  113
  362.           NO_APPEND()  . . . . . . . . . . . . . . . . . . . . . . . . .  114
  363.           NO_FLOCK() . . . . . . . . . . . . . . . . . . . . . . . . . .  116
  364.           NO_RLOCK() . . . . . . . . . . . . . . . . . . . . . . . . . .  118
  365.           NOTEMPTY() . . . . . . . . . . . . . . . . . . . . . . . . . .  120
  366.           NTXKEYVAL()  . . . . . . . . . . . . . . . . . . . . . . . . .  121
  367.           OLDERFILE()  . . . . . . . . . . . . . . . . . . . . . . . . .  123
  368.           OPENED() . . . . . . . . . . . . . . . . . . . . . . . . . . .  125
  369.           PARENT() . . . . . . . . . . . . . . . . . . . . . . . . . . .  129
  370.           PATHTO() . . . . . . . . . . . . . . . . . . . . . . . . . . .  130
  371.           PDOWNINIT()  . . . . . . . . . . . . . . . . . . . . . . . . .  131
  372.           PDOWNMENU()  . . . . . . . . . . . . . . . . . . . . . . . . .  136
  373.           PICKCOLOR()  . . . . . . . . . . . . . . . . . . . . . . . . .  140
  374.           PICKFILE() . . . . . . . . . . . . . . . . . . . . . . . . . .  142
  375.  
  376.  
  377.    Table of Contents                                                      vii
  378.  
  379.  
  380.           PICKREC()  . . . . . . . . . . . . . . . . . . . . . . . . . .  144
  381.           POPBOX() . . . . . . . . . . . . . . . . . . . . . . . . . . .  154
  382.           POPUPPICK()  . . . . . . . . . . . . . . . . . . . . . . . . .  155
  383.           PRINTCODE()  . . . . . . . . . . . . . . . . . . . . . . . . .  158
  384.           QUERY()  . . . . . . . . . . . . . . . . . . . . . . . . . . .  160
  385.           REPORTINIT() . . . . . . . . . . . . . . . . . . . . . . . . .  165
  386.           REVDATE()  . . . . . . . . . . . . . . . . . . . . . . . . . .  168
  387.           RH_HEADER()  . . . . . . . . . . . . . . . . . . . . . . . . .  169
  388.           RH_LINES() . . . . . . . . . . . . . . . . . . . . . . . . . .  171
  389.           RH_TEXT()  . . . . . . . . . . . . . . . . . . . . . . . . . .  173
  390.           RH_WIDTH() . . . . . . . . . . . . . . . . . . . . . . . . . .  175
  391.           RJUSTIFY() . . . . . . . . . . . . . . . . . . . . . . . . . .  177
  392.           RLIBERROR()  . . . . . . . . . . . . . . . . . . . . . . . . .  178
  393.           RLIBINIT() . . . . . . . . . . . . . . . . . . . . . . . . . .  179
  394.           RLIBVER()  . . . . . . . . . . . . . . . . . . . . . . . . . .  180
  395.           SAYINBOX() . . . . . . . . . . . . . . . . . . . . . . . . . .  181
  396.           SETCURSOR()  . . . . . . . . . . . . . . . . . . . . . . . . .  183
  397.           STARTREPORT()  . . . . . . . . . . . . . . . . . . . . . . . .  184
  398.           STR2DATE() . . . . . . . . . . . . . . . . . . . . . . . . . .  189
  399.           STRETCH()  . . . . . . . . . . . . . . . . . . . . . . . . . .  190
  400.           TARGET() . . . . . . . . . . . . . . . . . . . . . . . . . . .  191
  401.           TEMPFILE() . . . . . . . . . . . . . . . . . . . . . . . . . .  194
  402.           TYPEC()  . . . . . . . . . . . . . . . . . . . . . . . . . . .  195
  403.           VALTYPEC() . . . . . . . . . . . . . . . . . . . . . . . . . .  197
  404.           VRANGE() . . . . . . . . . . . . . . . . . . . . . . . . . . .  199
  405.  
  406.    Appendix A - RLIB Error Codes
  407.           Debugging Aid  . . . . . . . . . . . . . . . . . . . . . . . .  201
  408.  
  409.    Appendix B - The RHELP Compiler
  410.           What is RHELP? . . . . . . . . . . . . . . . . . . . . . . . .  205
  411.              RHELP Source Code . . . . . . . . . . . . . . . . . . . . .  205
  412.              Why Compile?  . . . . . . . . . . . . . . . . . . . . . . .  205
  413.              Advantages  . . . . . . . . . . . . . . . . . . . . . . . .  205
  414.           Help Source File Format  . . . . . . . . . . . . . . . . . . .  206
  415.           Creating Help  . . . . . . . . . . . . . . . . . . . . . . . .  207
  416.           Function API Quick Reference . . . . . . . . . . . . . . . . .  208
  417.           Building RHC.EXE and RHDC.EXE  . . . . . . . . . . . . . . . .  208
  418.              Demonstration Version . . . . . . . . . . . . . . . . . . .  208
  419.           An Example . . . . . . . . . . . . . . . . . . . . . . . . . .  208
  420.  
  421.    Appendix C - Author's Note
  422.           Clipper Summer '87 and 5.0 . . . . . . . . . . . . . . . . . .  211
  423.              Local and Static Variables  . . . . . . . . . . . . . . . .  211
  424.              Macro Differences . . . . . . . . . . . . . . . . . . . . .  211
  425.              A Macro Example . . . . . . . . . . . . . . . . . . . . . .  212
  426.              RLIB Differences  . . . . . . . . . . . . . . . . . . . . .  213
  427.  
  428.    Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  214
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.    Table of Contents                                                     viii
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.         ┌───────────────────────────────────────────────────────────────┐
  455.         │                                                               │
  456.         │                                                               │
  457.         │                                                               │
  458.         │                                                               │
  459.         │                                                               │
  460.         │                                                               │
  461.         │                                                               │
  462.         │                                                               │
  463.         │                          Chapter 1                            │
  464.         │                         Introduction                          │
  465.         │                                                               │
  466.         │                                                               │
  467.         │                                                               │
  468.         │                                                               │
  469.         │                                                               │
  470.         │                                                               │
  471.         │                                                               │
  472.         │                                                               │
  473.         │                                                               │
  474.         │                                                               │
  475.         └───────────────────────────────────────────────────────────────┘
  476.  
  477.  
  478.    Chapter 1: Introduction
  479.  
  480.  
  481.    What Is RLIB?
  482.  
  483.       RLIB is a Clipper function library that furnishes the application
  484.       programmer a collection of routines to aid in rapid program
  485.       development.  RLIB also contains a set of sophisticated high level
  486.       functions to help you build intuitive end user applications.
  487.  
  488.       Good applications require a solid and consistent user interface. 
  489.       Creating routines for menus, data entry and editing is a time
  490.       consuming process, one we all hope to avoid on a repetitive basis. 
  491.       RLIB is a collection of functions that simplify a wide range of
  492.       applications oriented programming tasks such as creating and
  493.       maintaining menus, message boxes, database record selection routines,
  494.       network locking functions and much more.
  495.  
  496.       The first publicly released version of RLIB, version 2.0 was very
  497.       popular because the RLIB functions let you produce applications
  498.       quickly!  There are many products that help improve programmer
  499.       productivity, such as application and code generators, some of which
  500.       rely on the template concept.  RLIB permits the programmer to retain
  501.       control over code creation and still crank out slick, powerful
  502.       applications at a high level.  The programmer using RLIB functions
  503.       does not have to learn any applications development system, just draw
  504.       from a rich set of high level and versatile functions.  RLIB will not
  505.       create applications for you, but you can significantly speed up your
  506.       application prototyping and development time.
  507.  
  508.       RLIB version 3.0 continues this tradition.  Several functions have
  509.       been expanded and many new ones have been added, all with the same
  510.       intent - to help the Clipper programmer develop good, consistent
  511.       applications quickly!  Hey, isn't that what we all want?
  512.  
  513.       There are many libraries available for Clipper programmers that
  514.       provide indispensable functions.  Most of these library functions are
  515.       written in C and Assembler and provide access to features which are
  516.       not currently supported in Clipper.  RLIB was not designed to provide
  517.       these types of functions, which are widely available from a number of
  518.       sources and provide excellent functionality.  RLIB was designed for
  519.       the Clipper programmer that creates customized application programs
  520.       and systems and who is interested in using a collection of functions
  521.       to make this job faster and above all, consistent.
  522.  
  523.       All RLIB functions are written in Clipper and all of the routines that
  524.       RLIB utilizes are in the CLIPPER and EXTEND libraries distributed in
  525.       the Clipper package.  Clipper has a rich set of commands and
  526.       functions.  If you are curious as to some of the capabilities of
  527.       Clipper, then check out the functions in RLIB.  They are ALL WRITTEN
  528.       100% IN CLIPPER!
  529.  
  530.  
  531.  
  532.  
  533.  
  534.    Introduction                                                             2
  535.  
  536.  
  537.    What You Get!
  538.  
  539.       Good software doesn't have to cost a lot of money!  RLIB 3.0 costs
  540.       only $99.00 and with your registered copy of RLIB v3.0 you get a lot!
  541.  
  542.       *   The RLIB function library in both Summer '87 and Clipper 5.01
  543.           versions which includes over 90 application development functions,
  544.           crafted with over three years of real world usage.
  545.  
  546.       *   Over 200 pages of professionally printed documentation containing
  547.           an extensive function reference, with descriptions, information and
  548.           examples.
  549.  
  550.       *   Over 9,000 lines of executable source code in both Summer '87 and
  551.           5.0.  This source code is extremely well formatted and legible with
  552.           extensive comments.  The code is a great source for both Summer '87
  553.           and 5.0 learning.  See how and what can be done in Clipper!
  554.  
  555.       *   The Message Reader application and printed user manual.  Not only
  556.           is this included with RLIB as a sample of what RLIB can do, it is
  557.           also a full featured application which includes full source code. 
  558.           There are over 3,500 lines of commented and highly instructional
  559.           source code.  Message Reader is also a useful application to manage
  560.           and view CompuServe forum message bases.
  561.  
  562.       *   The RHELP compiler and function API which lets you create text-
  563.           based, indexed access help files.  Compile the Message Reader demo
  564.           program and summon help with F1 to see fast, context sensitive help
  565.           in action.
  566.  
  567.       *   A Norton Guides on-line function reference database for instant
  568.           pop-up RLIB reference.
  569.  
  570.       *   Free technical support via CompuServe Mail.
  571.  
  572.       *   Just a few standout function highlights are:
  573.  
  574.           -  PICKREC()    The premier database picklist function!  Use it
  575.                           once and you'll never give it up.  Much easier to
  576.                           use for pick lists than DBEDIT() or TBROWSE().
  577.  
  578.           -  PDOWNMENU()  Professional pull down menus with separator lines,
  579.                           dynamic graying of options and much more.
  580.  
  581.           -  QUERY()      With one function call you have a complete query
  582.                           manager.  Try out the Query option in the Message
  583.                           Reader demo program to see QUERY() in action.
  584.  
  585.           -  OPENED()     Open multiple database and index files with one
  586.                           call to OPENED() with complete error reporting. 
  587.                           Reduce coding, especially in network environments
  588.                           by 90%!
  589.  
  590.           See the Quick Function Listing for a complete list and descriptions
  591.  
  592.  
  593.    Introduction                                                             3
  594.  
  595.  
  596.    The Source Code
  597.  
  598.       The big bonus to RLIB is that you get the source code for all of the
  599.       functions and to the demonstration program, Message Reader.  All RLIB
  600.       functions are meticulously coded with extensive comments.
  601.  
  602.       The source code offers several benefits.  First, you can tailor RLIB
  603.       functions if you so desire.  You can expand or limit the operation of
  604.       functions to suit your needs.  If a particular function behaves in a
  605.       way you would like to change, then all you have to do is change it.
  606.  
  607.       Secondly, the source code is a great source of instruction for those
  608.       of you who may be starting off with Clipper or just want to see what
  609.       Clipper can do.  These functions are the result of years of Clipper
  610.       programming experience, constantly exploring every Clipper feature.
  611.  
  612.       Third, each RLIB function is available in both the Clipper Summer '87
  613.       and 5.0 versions.  The functions for the 5.0 version have been updated
  614.       and modified specifically to take advantage of the new Clipper 5.0
  615.       storage classes (Local and Static) and code blocks to increase speed
  616.       and efficiency and reduce object code size.
  617.  
  618.       By looking over this source code you can get an idea of the techniques
  619.       and methods for converting to LOCAL and STATIC variables and still
  620.       retain the functionality of PRIVATES and PUBLICS.  You can see how to
  621.       employ STATICs to have them visible to called functions (like
  622.       PRIVATES), and to be visible globally just like PUBLICS.
  623.  
  624.  
  625.  
  626.  
  627.  
  628.  
  629.  
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.    Introduction                                                             4
  653.  
  654.  
  655.    Contents
  656.  
  657.       Shareware Version
  658.  
  659.       The RLIB 3.0 shareware package consists of a shareware version of the
  660.       RLIB 3.0 library in Clipper 5.01 object format.  The RLIB shareware
  661.       package also contains a sample demo program ready to compile and link,
  662.       and this documentation on disk.
  663.  
  664.       The RLIB shareware package is distributed in a single ZIP file named
  665.       RLIB30.ZIP.  PKUNZIP.EXE is needed to extract the contents of this ZIP
  666.       file.  PKUNZIP.EXE (and PKZIP.EXE) are available for downloading from
  667.       most BBSs including many of the forum libraries on CompuServe.  The
  668.       contents of RLIB30.ZIP are as follows:
  669.  
  670.       RLIB30.ZIP    -  RLIB 3.0 Shareware Package
  671.  
  672.           READ.ME         Latest Information and Contents
  673.           RLIB.LIB        RLIB 3.0 Shareware Library for Clipper 5.01
  674.           RLIB.DOC        User Manual (this file)
  675.           DEMO.PRG        Demo Program Source Code
  676.           DEMO.DBF        Demo Program Database 
  677.           DEMO.DBT        Demo Program Memo File
  678.           MAKEDEMO.BAT    Batch file to make the Demo Program
  679.           ORDER.DOC       Order Form on Disk
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.    Introduction                                                             5
  712.  
  713.  
  714.       Registered Version
  715.  
  716.       The RLIB package you purchase consists of the RLIB library, the
  717.       demonstration program Message Reader, a printed and bound manual, full
  718.       source code to all RLIB functions and demonstration programs, and a
  719.       Norton Guides on-line reference database.  That's quite a bit for
  720.       $99.00!
  721.  
  722.       The RLIB package is distributed on two (3) 5.25" diskettes or one (2)
  723.       3.5" diskette2.  Included in the diskettes are four (4) self-
  724.       extracting ZIP files which contain the various components of RLIB in
  725.       compressed form.  The following is a list of the self-extracting ZIP
  726.       files and their contents.
  727.  
  728.  
  729.       1.  RLIB50.EXE - RLIB 3.0 Library, Source, and Make files for 5.01
  730.  
  731.           RLIB.LIB        RLIB Function Library for Clipper 5.01
  732.           RLIB.MAK        RLIB.LIB Make file
  733.           RLIB.RSP        RLIB.LIB Turbo Librarian Response File
  734.           RHC.PRG         RHELP Compiler source code - Clipper 5.01
  735.           RHDC.PRG        RHELP De-Compiler source code - Clipper 5.01
  736.           MAKERLIB.BAT    Batch file to make RLIB.LIB
  737.           MAKERHC.BAT     Batch file to make RHC.EXE and RHDC.EXE
  738.           RL_*.PRG        RLIB 3.0 for 5.01 source code files (see page 21)
  739.  
  740.       2.  RLIB87.EXE - RLIB 3.0 Library, Source, and Make files for S'87
  741.  
  742.           RLIB.LIB        RLIB Function Library for Summer '87
  743.           RLIB.MAK        RLIB.LIB Make file
  744.           RLIB.RSP        RLIB.LIB Turbo Librarian Response File
  745.           RHC.PRG         RHELP Compiler source code - Summer '87
  746.           RHDC.PRG        RHELP De-Compiler source code - Summer '87
  747.           MAKERLIB.BAT    Batch file to make RLIB.LIB Function Library
  748.           MAKERHC.BAT     Batch file to make RHC.EXE and RHDC.EXE
  749.           RL_*.PRG        RLIB 3.0 for S'87 source code files (see page 21)
  750.  
  751.       3.  RLIBMR.EXE - RLIB 3.0 Demo Message Reader Program
  752.  
  753.           MR.CFG          Message Reader Configuration File
  754.           MR.HLP          Message Reader Program Help File
  755.           MR.RHC          RHELP source for Message Reader help system
  756.           MAKEMR.BAT      Batch file to make Message Reader - MR.EXE
  757.           MAKEMR50.BAT    Batch file to make MR.EXE in Clipper 5.01
  758.           SAMPLE.MSG      Sample messages file for Message Reader
  759.           FORUMS.DBF      Sample forums database for Message Reader
  760.           PROGNAME.ASM    Assembly function to retrieve .EXE file path
  761.           PROGNAME.OBJ    Assembled and linkable PROGNAME.ASM
  762.           *.PRG           Message Reader source code files (see page 24)
  763.  
  764.       4.  RLIBNG.EXE - RLIB 3.0 Norton Guide Reference Database
  765.  
  766.           RLIB.NG         RLIB 3.0 Norton Guide Reference Database
  767.  
  768.  
  769.  
  770.    Introduction                                                             6
  771.  
  772.  
  773.    Changes From Version 2.0
  774.  
  775.       RLIB version 3.0 contains 91 functions, 58 that are brand new.  Many
  776.       of the version 2.0 functions have been enhanced.  Below is a quick
  777.       overview of the additions and enhancements.  An asterisk (*) indicates
  778.       functions that are new in version 3.0, and a plus sign (+) indicates
  779.       functions that are enhanced from version 2.0.
  780.  
  781.       Array Functions
  782.       ---------------
  783.    *  ADIM2()          Formulate two dimension reference to a linear array.
  784.    *  ALIST()          List the elements of an array in a screen window.
  785.    *  ARRAYLEN()       Count the number of contiguous elements in an array.
  786.  
  787.       Character Functions
  788.       -------------------
  789.    *  ACRONYM()        Convert a text string to its abbreviated acronym.
  790.    *  ANYCHARSIN()     Test if any characters in a string are in another.
  791.       BRIGHT()         Convert Clipper color string to its bright equivalent.
  792.       DECRYPTED()      Decrypt a character string encrypted with ENCRYPTED().
  793.       ENCRYPTED()      Encrypt a character string.
  794.    *  GETKEY()         Replace INKEY() to allow internal customization.
  795.       GETPARM()        Retrieve comma delimited token from character string.
  796.    *  MIDDLE()         Center string by padding with leading/trailing spaces.
  797.       NAMESPLIT()      Swap from First Middle Last to Last, First Middle.
  798.    *  NOTEMPTY()       Validate that data was entered in a field.
  799.       PARENT()         Retrieve parent directory for a specified directory.
  800.       PATHTO()         Search DOS path for path leading to a given filename.
  801.    *  STRETCH()        Pad string with blanks or truncate to a defined width.
  802.    *  TYPEC()          Test if a PUBLIC/PRIVATE is character and not blank.
  803.    *  VALTYPEC()       Test if a LOCAL/STATIC is character and not blank.
  804.  
  805.       Database Functions
  806.       ------------------
  807.    *  CATF()           Copy array values to database fields.
  808.    *  CFTA()           Copy database field values to an array.
  809.       CHANGED()        Test if memory copies of fields have been changed.
  810.       CLOSEAREA()      Close multiple database work areas with one command.
  811.    *  DBFCREATE()      Dynamically create a database from a structure array.
  812.       FORGET()         Release field variables created with MEMORIZE().
  813.    *  ISDBF()          Test if a file is a valid .DBF format database file.
  814.    *  ISFIELD()        Test if a field name is valid in the selected area.
  815.    *  MAKEALIAS()      Construct a database alias from a full filename.
  816.    +  MARKREC()        Mark/select multiple records from a pick list.
  817.       MEMORIZE()       Save fields from database record to memory variables.
  818.       MREPLACE()       Replace fields with memvars created with MEMORIZE().
  819.    *  NO_APPEND()      Network append blank function with error trapping.
  820.    *  NO_FLOCK()       Network file lock function with error trapping.
  821.    *  NO_RLOCK()       Network record lock function with error trapping.
  822.       NTXKEYVAL()      Get controlling index key value of the current record.
  823.    *  OPENED()         Open multiple databases with network error checking.
  824.    +  PICKREC()        Pop up a scrollable pick list of database records.
  825.    *  POPUPPICK()      Generic pop-up pick list handler.
  826.    *  QUERY()          Create a logical query/filter string via menu prompts.
  827.  
  828.  
  829.    Introduction                                                             7
  830.  
  831.  
  832.       Date Functions
  833.       --------------
  834.       ALPHADATE()      Convert date variables to alphabetic format.
  835.    *  CALENDAR()       Pop up a configurable calendar on the screen.
  836.    *  REVDATE()        Reverse date fields for reverse index ordering.
  837.    +  STR2DATE()       Convert date strings to a Clipper date type variable.
  838.  
  839.       File Functions
  840.       --------------
  841.    *  CHECKFILE()      Verify valid filenames, optionally pop up a pick list.
  842.    *  FEOF()           Test for the End Of File status on a binary file.
  843.       FILEDATE()       Retrieve last update date for a given file from DOS.
  844.       FILES()          Test for the existence of multiple files.
  845.    *  FILESIZE()       Retrieve the size of a file from DOS directory.
  846.       FILETIME()       Retrieve the last update time for a given file.
  847.    *  FREADLINE()      Read line from text file opened with FOPEN()/FCREATE()
  848.    *  GETFILE()        Full featured user dialogue box for GETing filenames.
  849.    *  OLDERFILE()      Determine the older of two disk files.
  850.       PICKFILE()       Pop up directory listing from which to select a file.
  851.    *  TEMPFILE()       Generate a temporary filename.
  852.  
  853.       Help Functions
  854.       --------------
  855.    *  RH_HEADER()      Retrieve the header from a RHELP compiled help file.
  856.    *  RH_LINES()       Get the number of text lines within a help text block.
  857.    *  RH_TEXT()        Extract help text for a key from compiled .HLP file.
  858.    *  RH_WIDTH()       Get the maximum line width within a help text block.
  859.  
  860.       Menu Functions
  861.       --------------
  862.       BARMENU()        Create horizontal light bar menus.
  863.    +  BOXMENU()        Create boxed framed highlight bar (pop up) menus.
  864.       MULTIMENU()      Create multi-column menus with 4 way cursor movement.
  865.    +  PDOWNINIT()      Initialize the PDOWNMENU() function for use.
  866.    +  PDOWNMENU()      Activate pull-down menu initialized with PDOWNINIT().
  867.  
  868.       Miscellaneous and Internal Functions
  869.       ------------------------------------
  870.       BEEP()           Ring the system bell one or more times.
  871.    *  BLIP()           Generate a blipping sound for warnings or errors.
  872.    *  BUZZ()           Generate a buzzing sound for warnings or errors.
  873.    *  RLIBERROR()      Return and optionally set the last RLIB error number.
  874.    *  RLIBINIT()       Initialize internal RLIB PUBLIC/STATIC variable(s).
  875.    *  RLIBVER()        Retrieve the version number of the RLIB.LIB linked.
  876.  
  877.       Numeric Functions
  878.       -----------------
  879.    *  BIN2DEC()        Convert binary number to its equivalent decimal value.
  880.    *  DEC2HEX()        Convert decimal numeric value to a hexadecimal string.
  881.    *  DIVIDE()         Divide numbers with divide by zero protection.
  882.    *  HEX2DEC()        Convert hex string to equivalent decimal value.
  883.    *  VRANGE()         Numeric range validation with error handling.
  884.  
  885.  
  886.  
  887.  
  888.    Introduction                                                             8
  889.  
  890.  
  891.       Printer Functions
  892.       -----------------
  893.    *  PRINTCODE()      Convert text printer codes into escape sequences.
  894.    *  REPORTINIT()     Initialize databases used by StartReport() function.
  895.    *  STARTREPORT()    Report format and print control facility.
  896.    *  TARGET()         Provide a pop-up target printer output selection menu.
  897.  
  898.       Screen Functions
  899.       ----------------
  900.    *  ABOXASK()        Pop up a centered message box using array of messages.
  901.       ATINSAY()        Display expression at in a specified color.
  902.    *  BORDERBOX()      Draw a box with a one line title area at the top.
  903.    +  BOXASK()         Pop up a centered message box using multiple messages.
  904.    +  CENTER()         Center a string and/or get the center position.
  905.    *  FPROMPT()        Display formatted and highlighted prompt strings.
  906.    *  FRESTSCREEN()    Restore screen from a file saved with FSAVESCREEN().
  907.    *  FSAVESCREEN()    Save screen to file to restore with FRESTSCREEN().
  908.       KEYINPUT()       Get keyboard input optionally echoing dots to screen.
  909.    *  PICKCOLOR()      Pick a color setting from a boxed display.
  910.    *  POPBOX()         Restore a screen from a SAYINBOX() screen variable.
  911.       RJUSTIFY()       Move trailing blanks to the front.
  912.    +  SAYINBOX()       Pop up centered message box using multiple messages.
  913.    *  SETCURSOR()      Retrieve and optionally set the current cursor state.
  914.  
  915.  
  916.       Functions Enhanced from RLIB version 2.0
  917.  
  918.       All RLIB 3.0 functions that were in RLIB version 2.0 maintain upward
  919.       compatibility.  If new parameters have been added, parameter checking
  920.       is such that existing function usage will not be adversely affected. 
  921.       Basically, you can keep using your RLIB 2.0 function syntax but take a
  922.       look at what's new... you might want to update your code.
  923.  
  924.  
  925.       Function         Enhancements
  926.       -----------      -----------------------------------------
  927.       BOXASK()         New valid keys parameter
  928.       BOXMENU()        Expanded colors, additional parameters
  929.       CENTER()         New color parameter
  930.       MARKREC()        Additional parameters for greater control
  931.       PDOWNINIT()      Better use of static parameters
  932.       PDOWNMENU()      Significant enhancements to parameters
  933.       PICKFILE()       Now returns a fully qualified filename
  934.       PICKREC()        Additional parameters for greater control
  935.       SAYINBOX()       POPBOX() companion function
  936.       STR2DATE()       Better date string parsing
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.    Introduction                                                             9
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.         ┌───────────────────────────────────────────────────────────────┐
  966.         │                                                               │
  967.         │                                                               │
  968.         │                                                               │
  969.         │                                                               │
  970.         │                                                               │
  971.         │                                                               │
  972.         │                                                               │
  973.         │                                                               │
  974.         │                          Chapter 2                            │
  975.         │                        Obtaining RLIB                         │
  976.         │                                                               │
  977.         │                                                               │
  978.         │                                                               │
  979.         │                                                               │
  980.         │                                                               │
  981.         │                                                               │
  982.         │                                                               │
  983.         │                                                               │
  984.         │                                                               │
  985.         │                                                               │
  986.         └───────────────────────────────────────────────────────────────┘
  987.  
  988.  
  989.    Chapter 2: Obtaining RLIB
  990.  
  991.  
  992.    Registration
  993.  
  994.       This shareware version of RLIB provides you with a way to see just how
  995.       useful RLIB functions are by personally trying them out in your own
  996.       applications!  The shareware version of RLIB is not limited in any way
  997.       and it contains all of the features of the distribution version.  The
  998.       only difference is that, like most shareware products, a product
  999.       introduction screen is displayed when you first start applications
  1000.       that link in shareware RLIB functions.
  1001.  
  1002.       The best part about this type of test drive is that it lets you
  1003.       actually use RLIB functions in your own applications.  When you
  1004.       register all you have to do is re-link your application with the
  1005.       distribution RLIB library, no code changes are necessary!
  1006.  
  1007.       If you like RLIB and want to use it, by all means purchase your own
  1008.       copy.  It costs only $99.00 plus shipping and you get a lot!  You will
  1009.       receive the lastest version of RLIB on diskette, a 250+ page spiral
  1010.       bound manual, on-line Norton Guide database, the Message Reader
  1011.       program, manual and source code, and unlimited free technical support
  1012.       via CompuServe Mail.  Also, the big bonus is that you get the complete
  1013.       source code for all of the RLIB functions and for the Message Reader
  1014.       demonstration program.
  1015.  
  1016.       A registered copy of RLIB contains a license to use the single user
  1017.       version of the Message Reader program.  If you want to use Message
  1018.       Reader on a network, a network version is available separately. 
  1019.       Additional manuals are also available (for the network version only). 
  1020.       See the order form for information on how to order.
  1021.  
  1022.  
  1023.    Technical Support
  1024.  
  1025.       Technical support is available free of charge to paid registered users
  1026.       as described below.  When you order and receive you registered copy of
  1027.       RLIB, you will be asked to complete and return the registration form
  1028.       by mail to ensure that you are entitled to technical support.
  1029.  
  1030.       The fastest and best way to obtain technical support is via electronic
  1031.       mail on CompuServe.  Send your support questions to CompuServe account
  1032.       number 72007,1063.  You may usually expect a reply within 24 hours.
  1033.  
  1034.       Support is available on a limited basis by telephone for the first 30
  1035.       days following registration.  If no one is available, telephone calls
  1036.       will be answered electronically and return calls will be placed
  1037.       collect.
  1038.  
  1039.       You can always send a letter by U.S. Mail.  Letters will usually be
  1040.       answered within 48 hours of receipt.
  1041.  
  1042.  
  1043.  
  1044.  
  1045.    Obtaining RLIB                                                          11
  1046.  
  1047.  
  1048.    Order Information
  1049.  
  1050.       To order your copy of RLIB, please provide the information requested
  1051.       on the Order Form on the following page.  If you are paying by check
  1052.       or money order please enclose payment with your order.  All checks or
  1053.       money orders must be made in U.S. dollars.  For Visa and MasterCard
  1054.       orders be sure to complete the section requesting your card number,
  1055.       expiration date and signature.
  1056.  
  1057.       You may order over the telephone by completing the order form and
  1058.       calling the telephone number listed, or FAXing a copy to the FAX
  1059.       number listed on the order form.  You may also order on-line via
  1060.       CompuServe Mail by sending the completed order form on disk
  1061.       (ORDER.DOC) to CompuServe Mail account 72007,1063.
  1062.  
  1063.       Telephone, FAX, and electronic mail orders will be accepted by credit
  1064.       card only.  C.O.D. orders will be accepted for domestic orders only. 
  1065.       Please add an additional $4 for C.O.D. orders.
  1066.  
  1067.       Regular shipping is via U.S. Priority Mail.  International orders are
  1068.       sent by Air Mail.  Overnight shipping is by U.S. Express Mail and is
  1069.       available only in the U.S. and Canada.
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.    Obtaining RLIB                                                          12
  1105.  
  1106.  
  1107.                               O R D E R    F O R M
  1108.  
  1109.  
  1110.    Send to:  RLIB SOFTWARE                    Telephone: (919) 383-0488
  1111.              P. O. BOX 3232                   FAX:       (919) 382-3028
  1112.              DURHAM, NC 27715                 CompuServe:    72007,1063
  1113.  
  1114.  
  1115.    Quantity  Item Description                    Unit Cost      Total
  1116.  
  1117.     _____    RLIB 3.0 Function Library in both      $99.00    ________
  1118.              Summer '87 and Clipper 5.01 versions,
  1119.              full source code, printed manual, and
  1120.              single user license for Message Reader
  1121.  
  1122.     _____    Message Reader v2.0 Network version   $199.00    ________
  1123.              with single file server license
  1124.  
  1125.     _____    Additional Message Reader printed      $10.00    ________
  1126.              manual.  (Available only with the 
  1127.              Network version)
  1128.  
  1129.     SHIPPING & HANDLING - SELECT ONE OF THE FOLLOWING:
  1130.  
  1131.     _____    Within the U.S. and Canada              $6.00    ________
  1132.     
  1133.     _____    Outside the U.S. and Canada            $18.00    ________
  1134.  
  1135.     _____    Overnight (Only in U.S. and Canada)    $20.00    ________
  1136.  
  1137.     _____   C.O.D. Orders (add $4)                   $4.00    ________
  1138.  
  1139.                                                      TOTAL $__________
  1140.  
  1141.  
  1142.    Your Name:   ______________________________________________________
  1143.  
  1144.      Company:   ______________________________________________________
  1145.  
  1146.      Address:   ______________________________________________________
  1147.  
  1148.         City:   _______________________________ State: _______________
  1149.  
  1150.     Zip Code:   _________________ Country: ___________________________
  1151.  
  1152.    Telephone:   (________)____________________________
  1153.  
  1154.    Disk Size:   ______3.5"          ______5.25"
  1155.  
  1156.      Payment:   ______Check/M.O.    ______MasterCard       _______VISA
  1157.  
  1158.       Card #:   ______________________________  Expires: _____________
  1159.  
  1160.    Name as it appears on card: _______________________________________
  1161.  
  1162.    Signature:   ______________________________________________________
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.         ┌───────────────────────────────────────────────────────────────┐
  1181.         │                                                               │
  1182.         │                                                               │
  1183.         │                                                               │
  1184.         │                                                               │
  1185.         │                                                               │
  1186.         │                                                               │
  1187.         │                                                               │
  1188.         │                                                               │
  1189.         │                          Chapter 3                            │
  1190.         │                         Using  RLIB                           │
  1191.         │                                                               │
  1192.         │                                                               │
  1193.         │                                                               │
  1194.         │                                                               │
  1195.         │                                                               │
  1196.         │                                                               │
  1197.         │                                                               │
  1198.         │                                                               │
  1199.         │                                                               │
  1200.         │                                                               │
  1201.         └───────────────────────────────────────────────────────────────┘
  1202.  
  1203.  
  1204.    Chapter 3: Using RLIB
  1205.  
  1206.  
  1207.    System Requirements
  1208.  
  1209.       To make use of the RLIB function library you need either the Summer
  1210.       '87 or 5.0 version of the Clipper compiler.  Of course you must also
  1211.       have an IBM PC, XT, AT, PS/2 or 100% compatible and PC/MS-DOS version
  1212.       2.1 or above.  You also need a hard disk.
  1213.  
  1214.       Your disk space requirements will vary depending upon which versions
  1215.       of Clipper you install RLIB to support.  The RLIB library requires
  1216.       about 150K of disk space and the source code files require another
  1217.       320K.  This space requirement is approximate for either the Clipper
  1218.       Summer '87 or 5.0 version of RLIB.  If you will install both versions,
  1219.       double the figures.
  1220.  
  1221.  
  1222.    Installation
  1223.  
  1224.       The RLIB package comes on two (2) 5.25" diskettes or one (1) 3.5"
  1225.       diskette.  Included in the diskettes are four (4) self-extracting ZIP
  1226.       files which contain the various components of RLIB in compressed form. 
  1227.       See the section entitled Contents for a list of the self-extracting
  1228.       ZIP files and their contents.
  1229.  
  1230.       The files within the self-extracting ZIP files are extracted or un-
  1231.       compressed by simply "running" the self-extracting zip file; it is an
  1232.       executable file with an .EXE file extension.  To extract the files
  1233.       into the proper directory, change directory to the location where you
  1234.       want the files to reside and execute the self-extracting ZIP file.  It
  1235.       is assumed that you know how to copy and install software and that you
  1236.       have your own preferred directory structure.  A suggested directory
  1237.       structure appears as follows:
  1238.  
  1239.           C:\
  1240.           └──CLIPPER
  1241.              ├──501
  1242.              │  ├──BIN           --> Clipper 5.01 executable
  1243.              │  ├──INCLUDE       --> Clipper 5.01 include files
  1244.              │  └──LIB           --> Clipper 5.01 libraries
  1245.              │     └──RLIB       --> 5.01 version of RLIB.LIB
  1246.              │        ├──DEMO    --> RLIB demo program files
  1247.              │        └──SOURCE  --> 5.01 version of RLIB source code
  1248.              └──S87              --> The Clipper Summer '87 executable
  1249.                 └──LIB           --> Third Party Libraries (like RLIB)
  1250.                    └──RLIB       --> Summer '87 version of RLIB.LIB
  1251.                       ├──DEMO    --> RLIB demo program files
  1252.                       └──SOURCE  --> Summer '87 version of RLIB source code
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.    Using RLIB                                                              15
  1261.  
  1262.  
  1263.    Linking RLIB Into Your Applications
  1264.  
  1265.       To include any RLIB functions in your application, you must include
  1266.       the RLIB library name in your list of libraries when linking.  The
  1267.       only requirement is that you must include the Clipper EXTEND.LIB
  1268.       library since RLIB makes use of functions in this library.  Also you
  1269.       MUST list RLIB BEFORE EXTEND.LIB so the linker will properly pick up
  1270.       the routines.  (Apparently, some linkers do not make a second pass
  1271.       through the libraries to see if a library that follows one on the list
  1272.       calls a routine in a preceding one).
  1273.  
  1274.  
  1275.       The syntax for using RTLINK is:
  1276.  
  1277.              rtlink FILE yourprog LIB clipper,rlib,extend
  1278.  
  1279.  
  1280.       To use PLINK86, type:
  1281.  
  1282.              plink86 FILE yourprog LIB clipper,rlib,extend
  1283.  
  1284.  
  1285.       To use BLINKER, type:
  1286.  
  1287.              blinker FILE yourprog LIB clipper,rlib,extend
  1288.  
  1289.  
  1290.       To use MS-LINK, type:
  1291.  
  1292.              link yourprog,,,clipper+rlib+extend
  1293.  
  1294.  
  1295.       To use TLINK, type:
  1296.  
  1297.              tlink yourprog,,,clipper+rlib+extend
  1298.  
  1299.  
  1300.  
  1301.                 << *** REMEMBER TO LIST RLIB BEFORE EXTEND *** >>
  1302.  
  1303.  
  1304.       Dynamic Overlay Linkers
  1305.  
  1306.       The RLIB 3.0 library is written entirely in Clipper hence the RLIB
  1307.       library is compatible with standard Clipper dynamic overlay linkers
  1308.       such as Blinker.  RLIB can be entirely overlaid using the Blinker
  1309.       ALLOCATE link script command.
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.    Using RLIB                                                              16
  1320.  
  1321.  
  1322.    Modifying The RLIB Library
  1323.  
  1324.       You may want to custom tailor some of the functions in RLIB to meet
  1325.       your own needs.  Since the source code is provided for RLIB, this
  1326.       capability is what makes RLIB so versatile.  All you need is, of
  1327.       course, a copy of Clipper and a library manager program such as LIB
  1328.       from Microsoft.  Included with this package is a make file named
  1329.       RLIB.MAK which can be used to maintain the library.  See the
  1330.       discussion of how to use a library manager in the documentation that
  1331.       comes with the package you use.
  1332.  
  1333.  
  1334.       Clipper Summer '87
  1335.  
  1336.       When writing a collection of functions to build into a library, the
  1337.       biggest difference between Clipper compiled functions and functions
  1338.       written in other languages is that Clipper uses the filename to
  1339.       generate the public symbol that will be placed in the resulting object
  1340.       file.  If you write a program named TEST.PRG and compile it with
  1341.       Clipper, the resulting object file is named TEST.OBJ and the public
  1342.       symbol in that object file (the function name that you call) is named
  1343.       TEST.  That's ok if TEST.PRG does something useful, but if all
  1344.       TEST.PRG does is to contain a function named TEST, then Clipper will
  1345.       give you a SYMBOL REDEFINITION ERROR.  This is because Clipper is
  1346.       trying to create two symbols for the linker, both with the same name;
  1347.       one named TEST for the .PRG file program itself, and the other for the
  1348.       function named TEST contained in that .PRG file.
  1349.  
  1350.       For this reason, .PRG files that contain nothing but a function must
  1351.       have a name different from the function name itself.  Therefore, all
  1352.       the RLIB functions are contained in .PRG files starting with "RL_" and
  1353.       ending with the first 5 letters of the function name.  Of course you
  1354.       could get around this by having one .PRG file named RLIB.PRG with all
  1355.       of the functions separately listed within it, but this nullifies the
  1356.       advantage of using a library.  If you did it that way, all of the code
  1357.       would be linked into your application whether you called all the
  1358.       functions within it or not.  Having the functions contained in a
  1359.       library is handy because only those functions you use are extracted
  1360.       and included in your .EXE file when linked.
  1361.  
  1362.  
  1363.       Clipper 5.0
  1364.  
  1365.       Clipper 5.0 has resolved this issue with the addition of the /N
  1366.       compile switch.  The purpose of this new switch is to suppress the
  1367.       definition of a procedure with the same name as the .PRG file.  This
  1368.       definition of a procedure creates an entry point to the program file
  1369.       on the first non-comment line of the source file.  The /N switch
  1370.       forces the compiler to not create this entry point and thereby not
  1371.       create a public symbol with the same name as the program file.  What
  1372.       this all means is that in Clipper 5.0 you can have a source file named
  1373.       BOXMENU.PRG with only one function in it named BOXMENU and Clipper
  1374.       will not complain if you compile this with the /N compiler command
  1375.       line switch.
  1376.  
  1377.  
  1378.    Using RLIB                                                              17
  1379.  
  1380.  
  1381.       For consistency, the 5.0 versions of the RLIB source code have the
  1382.       same source file names as the Summer '87 versions, that is, they all
  1383.       are prefaced with RL_.
  1384.  
  1385.  
  1386.    RLIB Function Overview
  1387.  
  1388.       Parameter Syntax Verification
  1389.  
  1390.       All of the RLIB functions employ parameter verification to ensure that
  1391.       the correct parameters were supplied for the function to properly
  1392.       execute.  If one or more parameters is missing or is of the wrong data
  1393.       type, the RLIB function is designed to return gracefully to the
  1394.       calling routine without crashing the application.  Nothing is more
  1395.       annoying than to have a function bomb an application albeit due to a
  1396.       coding error.  However, there is another side to this coin.  If an
  1397.       application crashes, at least it is painfully evident that something
  1398.       is wrong.  By gracefully returning it is not always clear that a
  1399.       function did not perform as expected.
  1400.  
  1401.       Take for instance the Clipper Summer '87 implementation of the
  1402.       SCROLL() function.  If the fifth parameter, the number of lines to
  1403.       scroll, is omitted, SCROLL() simply returns without doing anything. 
  1404.       This is good because it does not crash your application.  However, it
  1405.       may not be immediately clear that something is not working.  If the
  1406.       program crashed with even a cryptic error message such as "Proc:
  1407.       SCROLL  Line: 0  Parameter Error" at least you know something is wrong
  1408.       within the SCROLL() function.  (Note: The Clipper 5.01 version of the
  1409.       SCROLL() function clears the screen if no parameters are provided.)
  1410.  
  1411.  
  1412.       RLIB Error Reporting
  1413.  
  1414.       RLIB functions give you the best of both worlds.  As mentioned above,
  1415.       all RLIB functions verify the correct number of and parameter types. 
  1416.       If a parameter is missing or of the incorrect type, the RLIB function
  1417.       will not bomb but will return to the calling routine.  What the RLIB
  1418.       function will do is set a flag via the RLIBERROR() function. 
  1419.       RLIBERROR() maintains a public variable named <rliberror> which is a
  1420.       numeric value that indicates the last error that may have occurred.  A
  1421.       normal value is zero.  Through the use of RLIBERROR() the application
  1422.       programmer can set break points in the Clipper debugger during testing
  1423.       to trap any syntax errors in RLIB functions.  To learn more about
  1424.       RLIBERROR() see the function description in the function reference and
  1425.       Appendix A - RLIB Error Codes.
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.    Using RLIB                                                              18
  1438.  
  1439.  
  1440.    Quick Function Listing
  1441.  
  1442.       ABOXASK()        Pop up a centered message box using array of messages.
  1443.       ACRONYM()        Convert a text string to its abbreviated acronym.
  1444.       ADIM2()          Formulate a two dimension reference to a linear array.
  1445.       ALIST()          List the elements of an array in a screen window.
  1446.       ALPHADATE()      Convert date variables to alphabetic format.
  1447.       ANYCHARSIN()     Test if any characters in a string are in another.
  1448.       ARRAYLEN()       Count the number of contiguous elements in an array.
  1449.       ATINSAY()        Display expression at in a specified color.
  1450.       BARMENU()        Create horizontal light bar menus.
  1451.       BEEP()           Ring the system bell one or more times.
  1452.       BIN2DEC()        Convert binary number to its equivalent decimal value.
  1453.       BLIP()           Generate a blipping sound for warnings or errors.
  1454.       BORDERBOX()      Draw a box with a one line title area at the top.
  1455.       BOXASK()         Pop up a centered message box using multiple messages.
  1456.       BOXMENU()        Create boxed framed highlight bar (pop up) menus.
  1457.       BRIGHT()         Convert Clipper color string to its bright equivalent.
  1458.       BUZZ()           Generate a buzzing sound for warnings or errors.
  1459.       CALENDAR()       Pop up a configurable calendar on the screen.
  1460.       CATF()           Copy array values to database fields.
  1461.       CENTER()         Center a string and/or get the center position.
  1462.       CFTA()           Copy database field values to an array.
  1463.       CHANGED()        Test if memory copies of fields have been changed.
  1464.       CHECKFILE()      Verify valid filenames, optionally pop up a pick list.
  1465.       CLOSEAREA()      Close multiple database work areas with one command.
  1466.       DBFCREATE()      Dynamically create a database from a structure array.
  1467.       DEC2HEX()        Convert decimal numeric value to a hexadecimal string.
  1468.       DECRYPTED()      Decrypt a character string encrypted with ENCRYPTED().
  1469.       DIVIDE()         Divide numbers with divide by zero protection.
  1470.       ENCRYPTED()      Encrypt a character string.
  1471.       FEOF()           Test for the End Of File status on a binary file.
  1472.       FILEDATE()       Retrieve last update date for a given file from DOS.
  1473.       FILES()          Test for the existence of multiple files.
  1474.       FILESIZE()       Retrieve the size of a file from DOS directory.
  1475.       FILETIME()       Retrieve the last update time for a given file.
  1476.       FORGET()         Release field variables created with MEMORIZE().
  1477.       FPROMPT()        Display formatted and highlighted prompt strings.
  1478.       FREADLINE()      Read line from text file opened with FOPEN()/FCREATE()
  1479.       FRESTSCREEN()    Restore screen from a file saved with FSAVESCREEN().
  1480.       FSAVESCREEN()    Save screen to file to restore with FRESTSCREEN().
  1481.       GETFILE()        Full featured user dialogue box for GETing filenames.
  1482.       GETKEY()         Replace INKEY() to allow internal customization.
  1483.       GETPARM()        Retrieve comma delimited token from character string.
  1484.       HEX2DEC()        Convert hex string to equivalent decimal value.
  1485.       ISDBF()          Test if a file is a valid .DBF format database file.
  1486.       ISFIELD()        Test if a field name is valid in the selected area.
  1487.       KEYINPUT()       Get keyboard input optionally echoing dots to screen.
  1488.       MAKEALIAS()      Construct a database alias from a full filename.
  1489.       MARKREC()        Mark/select multiple records from a pick list.
  1490.       MEMORIZE()       Save fields from database record to memory variables.
  1491.       MIDDLE()         Center string by padding with leading/trailing spaces.
  1492.       MREPLACE()       Replace fields with memvars created with MEMORIZE().
  1493.       MULTIMENU()      Create multi-column menus with 4 way cursor movement.
  1494.  
  1495.  
  1496.    Using RLIB                                                              19
  1497.  
  1498.  
  1499.    Quick Function Listing (Continued)
  1500.  
  1501.       NAMESPLIT()      Swap from First Middle Last to Last, First Middle.
  1502.       NO_APPEND()      Network append blank function with error trapping.
  1503.       NO_FLOCK()       Network file lock function with error trapping.
  1504.       NO_RLOCK()       Network record lock function with error trapping.
  1505.       NOTEMPTY()       Validate that data was entered in a field.
  1506.       NTXKEYVAL()      Get controlling index key value of the current record.
  1507.       OLDERFILE()      Determine the older of two disk files.
  1508.       OPENED()         Open multiple databases with network error checking.
  1509.       PARENT()         Retrieve parent directory for a specified directory.
  1510.       PATHTO()         Search DOS path for path leading to a given filename.
  1511.       PDOWNINIT()      Initialize the PDOWNMENU() function for use.
  1512.       PDOWNMENU()      Activate pull-down menu initialized with PDOWNINIT().
  1513.       PICKCOLOR()      Pick a color setting from a boxed display.
  1514.       PICKFILE()       Pop up directory listing from which to select a file.
  1515.       PICKREC()        Pop up a scrollable pick list of database records.
  1516.       POPBOX()         Restore a screen from a SAYINBOX() screen variable.
  1517.       POPUPPICK()      Generic pop-up pick list handler.
  1518.       PRINTCODE()      Convert text printer codes into escape sequences.
  1519.       QUERY()          Create a logical query/filter string via menu prompts.
  1520.       REPORTINIT()     Initialize StartReport() databases.
  1521.       REVDATE()        Reverse date fields for reverse index ordering.
  1522.       RH_HEADER()      Retrieve the header from a RHELP compiled help file.
  1523.       RH_LINES()       Get the number of text lines within a help text block.
  1524.       RH_TEXT()        Extract help text for a key from compiled .HLP file.
  1525.       RH_WIDTH()       Get the maximum line width within a help text block.
  1526.       RJUSTIFY()       Move trailing blanks to the front.
  1527.       RLIBERROR()      Return and optionally set the last RLIB error number.
  1528.       RLIBINIT()       Initialize internal RLIB PUBLIC/STATIC variable(s).
  1529.       RLIBVER()        Retrieve the version number of the RLIB.LIB linked.
  1530.       SAYINBOX()       Pop up centered message box using multiple messages.
  1531.       SETCURSOR()      Retrieve and optionally set the current cursor state.
  1532.       STARTREPORT()    General report format and print control function.
  1533.       STR2DATE()       Convert date strings to a Clipper date type variable.
  1534.       STRETCH()        Pad string with blanks or truncate to a defined width.
  1535.       TARGET()         Provide a pop-up target printer output selection menu.
  1536.       TEMPFILE()       Generate a temporary filename.
  1537.       TYPEC()          Test if a PUBLIC/PRIVATE is character and not blank.
  1538.       VALTYPEC()       Test if a LOCAL/STATIC is character and not blank.
  1539.       VRANGE()         Numeric range validation with error handling.
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545.  
  1546.  
  1547.  
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.    Using RLIB                                                              20
  1556.  
  1557.  
  1558.    Source Code File List
  1559.  
  1560.       As mentioned earlier, the RLIB function library includes complete
  1561.       source code to all functions, demo programs, and the Message Reader
  1562.       program.  The source code for each RLIB function is contained in a
  1563.       separate disk file.  All RLIB function source code file names begin
  1564.       with RL_.  Chapter 5, Function Reference lists the name of each source
  1565.       file as part of each function description.  Below is a list of each
  1566.       RLIB function and the name of it's associated source code file.
  1567.  
  1568.  
  1569.       NO.    RLIB FUNCTION   SOURCE FILE      CATEGORY
  1570.       ---    -------------   ------------     ------------- 
  1571.        1.    ABOXASK()       RL_ABOXA.PRG     Screen
  1572.        2.    ACRONYM()       RL_ACRON.PRG     Character
  1573.        3.    ADIM2()         RL_ADIM2.PRG     Array
  1574.        4.    ALIST()         RL_ALIST.PRG     Debugging
  1575.        5.    ALPHADATE()     RL_ALPHA.PRG     Date
  1576.        6.    ANYCHARSIN()    RL_ANYCH.PRG     Character
  1577.        7.    ARRAYLEN()      RL_ARRAY.PRG     Array
  1578.        8.    ATINSAY()       RL_ATINS.PRG     Screen
  1579.        9.    BARMENU()       RL_BARME.PRG     Menu
  1580.       10.    BEEP()          RL_BEEP.PRG      Miscellaneous
  1581.       11.    BIN2DEC()       RL_BIN2D.PRG     Numeric
  1582.       12.    BLIP()          RL_BLIP.PRG      Miscellaneous
  1583.       13.    BORDERBOX()     RL_BORDE.PRG     Screen
  1584.       14.    BOXASK()        RL_BOXAS.PRG     Screen
  1585.       15.    BOXMENU()       RL_BOXME.PRG     Menu
  1586.       16.    BRIGHT()        RL_BRIGH.PRG     Character
  1587.       17.    BUZZ()          RL_BUZZ.PRG      Miscellaneous
  1588.       18.    CALENDAR()      RL_CALEN.PRG     Date
  1589.       19.    CATF()          RL_CATF.PRG      Database
  1590.       20.    CENTER()        RL_CENTE.PRG     Screen
  1591.       21.    CFTA()          RL_CFTA.PRG      Database
  1592.       22.    CHANGED()       RL_CHANG.PRG     Database
  1593.       23.    CHECKFILE()     RL_CHECK.PRG     File
  1594.       24.    CLOSEAREA()     RL_CLOSE.PRG     Database
  1595.       25.    DBFCREATE()     RL_DBFCR.PRG     Database
  1596.       26.    DEC2HEX()       RL_DEC2H.PRG     Numeric
  1597.       27.    DECRYPTED()     RL_DECRY.PRG     Character
  1598.       28.    DIVIDE()        RL_DIVID.PRG     Numeric
  1599.       29.    ENCRYPTED()     RL_ENCRY.PRG     Character
  1600.       30.    FEOF()          RL_FEOF.PRG      File
  1601.       31.    FILEDATE()      RL_FILED.PRG     File
  1602.       32.    FILES()         RL_FILES.PRG     File
  1603.       33.    FILESIZE()      RL_FSIZE.PRG     File
  1604.       34.    FILETIME()      RL_FILET.PRG     File
  1605.       35.    FORGET()        RL_FORGE.PRG     Database
  1606.       36.    FPROMPT()       RL_FPROM.PRG     Screen
  1607.       37.    FREADLINE()     RL_FREAD.PRG     File
  1608.       38.    FRESTSCREEN()   RL_FREST.PRG     Screen
  1609.       39.    FSAVESCREEN()   RL_FSAVE.PRG     Screen
  1610.       40.    GETFILE()       RL_GETFI.PRG     File
  1611.       41.    GETKEY()        RL_GETKE.PRG     Character
  1612.  
  1613.  
  1614.    Using RLIB                                                              21
  1615.  
  1616.  
  1617.    Source Code File List (Continued)
  1618.  
  1619.       NO.    RLIB FUNCTION   SOURCE FILE      CATEGORY
  1620.       ---    -------------   ------------     ------------- 
  1621.       42.    GETPARM()       RL_GETPA.PRG     Character
  1622.       43.    HEX2DEC()       RL_HEX2D.PRG     Numeric
  1623.       44.    ISDBF()         RL_ISDBF.PRG     Database
  1624.       45.    ISFIELD()       RL_ISFIE.PRG     Database
  1625.       46.    KEYINPUT()      RL_KEYIN.PRG     Screen
  1626.       47.    MAKEALIAS()     RL_MAKEA.PRG     Database
  1627.       48.    MARKREC()       RL_MARKR.PRG     Database
  1628.       49.    MEMORIZE()      RL_MEMOR.PRG     Database
  1629.       50.    MIDDLE()        RL_MIDDL.PRG     Character
  1630.       51.    MREPLACE()      RL_MREPL.PRG     Database
  1631.       52.    MULTIMENU()     RL_MULTI.PRG     Menu
  1632.       53.    NAMESPLIT()     RL_NAMES.PRG     Character
  1633.       54.    NO_APPEND()     RL_NO_AP.PRG     Database
  1634.       55.    NO_FLOCK()      RL_NO_FL.PRG     Database
  1635.       56.    NO_RLOCK()      RL_NO_RL.PRG     Database
  1636.       57.    NOTEMPTY()      RL_NOTEM.PRG     Character
  1637.       58.    NTXKEYVAL()     RL_NTXKE.PRG     Database
  1638.       59.    OLDERFILE()     RL_OLDER.PRG     File
  1639.       60.    OPENED()        RL_OPENE.PRG     Database
  1640.       61.    PARENT()        RL_PAREN.PRG     Character
  1641.       62.    PATHTO()        RL_PATHT.PRG     Character
  1642.       63.    PDOWNINIT()     RL_PDINI.PRG     Menu
  1643.       64.    PDOWNMENU()     RL_PDOWN.PRG     Menu
  1644.       65.    PICKCOLOR()     RL_PICKC.PRG     Screen
  1645.       66.    PICKFILE()      RL_PICKF.PRG     File
  1646.       67.    PICKREC()       RL_PICKR.PRG     Database
  1647.       68.    POPBOX()        RL_SAYIN.PRG     Screen
  1648.       69.    POPUPPICK()     RL_POPUP.PRG     Database
  1649.       70.    PRINTCODE()     RL_PRINT.PRG     Printer
  1650.       71.    QUERY()         RL_QUERY.PRG     Database
  1651.       72.    REPORTINIT()    RL_REPOR.PRG     Printer
  1652.       73.    REVDATE()       RL_REVDA.PRG     Date
  1653.       74.    RH_HEADER()     RL_RHELP.PRG     Help
  1654.       75.    RH_LINES()      RL_RHELP.PRG     Help
  1655.       76.    RH_TEXT()       RL_RHELP.PRG     Help
  1656.       77.    RH_WIDTH()      RL_RHELP.PRG     Help
  1657.       78.    RJUSTIFY()      RL_RJUST.PRG     Screen
  1658.       79.    RLIBERROR()     RL_RLIBE.PRG     Internal
  1659.       80.    RLIBINIT()      RL_RLIBI.PRG     Internal
  1660.       81.    RLIBVER()       RL_RLIBV.PRG     Internal
  1661.       82.    SAYINBOX()      RL_SAYIN.PRG     Screen
  1662.       83.    SETCURSOR()     RL_SETCU.PRG     Screen
  1663.       84.    STARTREPORT()   RL_START.PRG     Printer
  1664.       85.    STR2DATE()      RL_STR2D.PRG     Date
  1665.       86.    STRETCH()       RL_STRET.PRG     Character
  1666.       87.    TARGET()        RL_TARGE.PRG     Printer
  1667.       88.    TEMPFILE()      RL_TEMPF.PRG     File
  1668.       89.    TYPEC()         RL_TYPEC.PRG     Character
  1669.       90.    VALTYPEC()      RL_VALTY.PRG     Character
  1670.       91.    VRANGE()        RL_VRANG.PRG     Numeric
  1671.  
  1672.  
  1673.    Using RLIB                                                              22
  1674.  
  1675.  
  1676.  
  1677.  
  1678.  
  1679.  
  1680.  
  1681.  
  1682.  
  1683.  
  1684.  
  1685.  
  1686.  
  1687.  
  1688.  
  1689.  
  1690.  
  1691.         ┌───────────────────────────────────────────────────────────────┐
  1692.         │                                                               │
  1693.         │                                                               │
  1694.         │                                                               │
  1695.         │                                                               │
  1696.         │                                                               │
  1697.         │                                                               │
  1698.         │                                                               │
  1699.         │                                                               │
  1700.         │                          Chapter 4                            │
  1701.         │               The Message Reader Demo Program                 │
  1702.         │                                                               │
  1703.         │                                                               │
  1704.         │                                                               │
  1705.         │                                                               │
  1706.         │                                                               │
  1707.         │                                                               │
  1708.         │                                                               │
  1709.         │                                                               │
  1710.         │                                                               │
  1711.         │                                                               │
  1712.         └───────────────────────────────────────────────────────────────┘
  1713.  
  1714.  
  1715.    Chapter 4: The Message Reader Demo Program
  1716.  
  1717.  
  1718.    A Full Feature Application
  1719.  
  1720.       Message Reader is a program for PC-DOS Personal Computers and 100%
  1721.       compatibles which simplifies and diversifies the management of
  1722.       messages captured from CompuServe forums.  Refer to the Message Reader
  1723.       documentation for a full description of Message Reader features.
  1724.  
  1725.       The Message Reader program demonstrates the power and versatility of
  1726.       using RLIB functions.  Message Reader is written in Clipper Summer '87
  1727.       and makes extensive use of a majority of the RLIB functions.  The
  1728.       source code to Message Reader is included as part of the registered
  1729.       distribution version of RLIB 3.0.  By looking through the source code
  1730.       you can gain an appreciation of just how much time and effort you can
  1731.       save by using RLIB functions.
  1732.  
  1733.       Not only does Message Reader demonstrate the power of RLIB, but it is
  1734.       also a full featured application program.  In fact, Message Reader is
  1735.       sold separately by RLIB Software as an aid to handling the voluminous
  1736.       amounts of information to be gleaned from the CompuServe forum message
  1737.       bases.
  1738.  
  1739.       Take a moment to read through the Message Reader manual, and enjoy the
  1740.       program!
  1741.  
  1742.  
  1743.    Message Reader Source Code
  1744.  
  1745.       The Message Reader source code is comprised of over 3,500 lines of
  1746.       commented and highly instructional executable source code.  This
  1747.       source code line count would be much higher were it not for RLIB
  1748.       functions.  Given that many of the RLIB functions do so much a lot of
  1749.       the coding effort has already been accomplished.  For example, the
  1750.       entire Message Reader query building process is handled through one
  1751.       call to the RLIB QUERY() function!
  1752.  
  1753.       Source Code Files
  1754.  
  1755.           DEFINES.PRG     Public definitions (#define's in 5.01)
  1756.           MRSTART.PRG     Start up and command line parser
  1757.           MAIN.PRG        Main program loop
  1758.           MENU.PRG        Menu control function
  1759.           FORUM.PRG       Forum options functions
  1760.           IMPORT.PRG      Message import functions
  1761.           OPTIONS.PRG     Options menu functions
  1762.           PRINT.PRG       Print functions
  1763.           QRY.PRG         Query builder
  1764.           SEARCH.PRG      Search functions
  1765.           SEND.PRG        Message compose and send functions
  1766.           VIEW.PRG        Viewing functions
  1767.           ERRORSYS.PRG    Customized Summer '87 error handler
  1768.           PROGNAME.ASM    Gets executing program name, aka argv[0]
  1769.  
  1770.  
  1771.    The Message Reader Demo Program                                         24
  1772.  
  1773.  
  1774.    RLIB Functions Used in Message Reader
  1775.  
  1776.       Here is a list of some of the RLIB functions used in the Message
  1777.       Reader program source code.  As you can see they provide a wide
  1778.       variety of uses.  In particular pay close attention to PICKREC(),
  1779.       which essentially drives the view screen.
  1780.  
  1781.       ANYCHARSIN()     Verifies valid characters in filenames
  1782.       BORDERBOX()      Draws all boxes with titled headers
  1783.       BOXASK()         Creates all screen centered message dialogue boxes
  1784.       BOXMENU()        Provides the second level from the PDOWNMENU()
  1785.       CALENDAR()       Shift-F1 pops up a handy calendar
  1786.       CHECKFILE()      Verifies filenames and provides pop-up directory
  1787.       CLOSEAREA()      Used to close database files
  1788.       DEC2HEX()        Used to generate unique MAIL message numbers
  1789.       DBFCREATE()      Creates Message Reader database files
  1790.       FPROMPT()        Provides the highlighted prompts at bottom of screen
  1791.       FREADLINE()      Used to read text lines during the import process
  1792.       FILESIZE()       Used to determine if enough disk space exists for copy
  1793.       GETFILE()        Used to get filenames whenever requested
  1794.       MEMORIZE()       Used during field edit routines
  1795.       MREPLACE()       Used to replace edited field data
  1796.       NO_APPEND()      Appends new records, testing for network errors
  1797.       NO_FLOCK()       Used for network file locking
  1798.       NO_RLOCK()       Used for network record locking
  1799.       NOTEMPTY()       Used in field edit VALID clause to confirm data entry
  1800.       OPENED()         Used whenever databases are opened
  1801.       PARENT()         Parses path to help generate help file path
  1802.       PDOWNMENU()      Provides the pull-down menu system
  1803.       PICKCOLOR()      Performs the color selection routine
  1804.       PICKFILE()       Provides the pop-up file directory listing
  1805.       PICKREC()        *** The view screen is controlled by PICKREC() ***
  1806.       QUERY()          This IS the query builder!
  1807.       SAYINBOX()       Provides status indicators during indexing, etc...
  1808.       SETCURSOR()      Cursor control is through this function
  1809.       TARGET()         Provides the print target output menu
  1810.  
  1811.  
  1812.       The PROGNAME() Function
  1813.  
  1814.       Message Reader makes use of one assembly language function named
  1815.       PROGNAME().  PROGNAME() retrieves the name of the currently executing
  1816.       program (MR.EXE) as a fully qualified filename.  For instance, if the
  1817.       Message Reader program is started with the command C:\DEMO\MR, then
  1818.       PROGNAME() will return C:\DEMO\MR.EXE.  In the C language this is
  1819.       known as argv[0].  Clipper does not have a (documented) built in
  1820.       function to retrieve this value.
  1821.  
  1822.       The program name returned by PROGNAME() is stripped to a path
  1823.       specification with the RLIB function PARENT(), to extract the
  1824.       directory in which the MR.EXE file is located.  This path is then used
  1825.       to build the help file name for MR.HLP so Message Reader can find its
  1826.       own help file.  This assumes the help file is stored in the same
  1827.       directory as the MR.EXE executable file.
  1828.  
  1829.  
  1830.    The Message Reader Demo Program                                         25
  1831.  
  1832.  
  1833.       PROGNAME() works only with DOS versions 3.0 and above.  In the event
  1834.       you are using DOS version 2.x, Message Reader lets you explicitly
  1835.       specify the directory in which the help file can be found.  The
  1836.       PROGNAME() function (PROGNAME.OBJ) is compatible with both Clipper
  1837.       Summer '87 and Clipper 5.0 (and 5.01).
  1838.  
  1839.       The assembly language source code for PROGNAME() is in the file
  1840.       PROGNAME.ASM and the already assembled linkable object module is in
  1841.       PROGNAME.OBJ (in case you do not have an assembler program).  You may
  1842.       wish to add the PROGNAME.OBJ module to RLIB.LIB or even to EXTEND.LIB
  1843.       for convenience.  You will need a library manager such as Microsoft's
  1844.       LIB or Borland's TLIB.  See your library manager documentation for the
  1845.       proper syntax.
  1846.  
  1847.  
  1848.    Compiling and Linking Message Reader
  1849.  
  1850.       Making the Message Reader executable program is as simple as running
  1851.       the MAKEMR.BAT batch file.  This batch file, which can be found in the
  1852.       RLIBDEMO.EXE self-extracting ZIP file, compiles the Message Reader
  1853.       source code files and links the resulting object module with the
  1854.       Clipper and RLIB 3.0 libraries.
  1855.  
  1856.       Message Reader is written in the Summer '87 version of Clipper but has
  1857.       also been compiled using Clipper 5.01.  If you want to compile Message
  1858.       Reader with 5.01 be sure to omit any of the new Clipper 5.01 command
  1859.       line switches.  This will enforce compatibility with Summer '87 code. 
  1860.       You will also want to make sure you link the 5.01 compiled object
  1861.       module with the Clipper 5.01 version of RLIB.LIB.  Future versions of
  1862.       Message Reader will be only in Clipper 5.01 format.
  1863.  
  1864.       The demonstration RLIB package contains the Message Reader program in
  1865.       compiled, object file format, in both Clipper Summer '87 and Clipper
  1866.       5.01 versions.  These object files are ready to link with the RLIB
  1867.       library to produce a demonstration version of Message Reader.  Two
  1868.       batch files are included to simplify this process.  These batch files
  1869.       are named MAKEMR.BAT and MAKEMR50.BAT, and they make Clipper Summer
  1870.       '87 and 5.01 executable versions of Message Reader respectively.
  1871.  
  1872.       The MAKEMR.BAT batch file uses the PLINK86 linker included with
  1873.       Clipper Summer '87, and the MAKEMR50.BAT batch file uses the RTLINK
  1874.       linker included with Clipper 5.0.  You may substitute your preferred
  1875.       linker.  Message Reader has been successfully linked with PLINK86,
  1876.       BLINKER, and Borland's TLINK.  The Clipper 5.01 version has been
  1877.       linked with RTLINK and BLINKER 1.5.
  1878.  
  1879.  
  1880.  
  1881.  
  1882.  
  1883.  
  1884.  
  1885.  
  1886.  
  1887.  
  1888.  
  1889.    The Message Reader Demo Program                                         26
  1890.  
  1891.  
  1892.  
  1893.  
  1894.  
  1895.  
  1896.  
  1897.  
  1898.  
  1899.  
  1900.  
  1901.  
  1902.  
  1903.  
  1904.  
  1905.  
  1906.  
  1907.         ┌───────────────────────────────────────────────────────────────┐
  1908.         │                                                               │
  1909.         │                                                               │
  1910.         │                                                               │
  1911.         │                                                               │
  1912.         │                                                               │
  1913.         │                                                               │
  1914.         │                                                               │
  1915.         │                                                               │
  1916.         │                          Chapter 5                            │
  1917.         │                    RLIB Function Reference                    │
  1918.         │                                                               │
  1919.         │                                                               │
  1920.         │                                                               │
  1921.         │                                                               │
  1922.         │                                                               │
  1923.         │                                                               │
  1924.         │                                                               │
  1925.         │                                                               │
  1926.         │                                                               │
  1927.         │                                                               │
  1928.         └───────────────────────────────────────────────────────────────┘
  1929.  
  1930.  
  1931.    Chapter 5: RLIB Function Reference
  1932.  
  1933.  
  1934.       The following section contains the detailed function descriptions. 
  1935.       Each function reference starts on a separate page and includes a
  1936.       standardized header with the following information:
  1937.  
  1938.  
  1939.           Function:       The name of the function
  1940.  
  1941.           Purpose:        A one line function purpose description
  1942.  
  1943.           Syntax:         Function syntax listing parameters and sequence
  1944.  
  1945.           Arguments:      Detailed description of each parameter
  1946.  
  1947.           Returns:        The return value of the function
  1948.  
  1949.           Description:    A detailed description of the function
  1950.  
  1951.           Notes:          Notes and points about the function and behavior
  1952.  
  1953.           Example:        Code example of the function in use
  1954.  
  1955.           Source:         The name of the file containing the source code
  1956.  
  1957.           See also:       Related functions
  1958.  
  1959.  
  1960.  
  1961.  
  1962.  
  1963.  
  1964.  
  1965.  
  1966.  
  1967.  
  1968.  
  1969.  
  1970.  
  1971.  
  1972.  
  1973.  
  1974.  
  1975.  
  1976.  
  1977.  
  1978.  
  1979.  
  1980.  
  1981.  
  1982.  
  1983.  
  1984.  
  1985.  
  1986.  
  1987.    RLIB Function Reference                                                 28
  1988.  
  1989.  
  1990.    Function:    ABOXASK()
  1991.  
  1992.    Purpose:     Pop up a centered message box using an array of messages.
  1993.  
  1994.    Syntax:      ABOXASK( array [, color [, keys [, timeout ] ] ] )
  1995.  
  1996.    Arguments:   array       - Array of character string messages to display
  1997.                               in a message box that is centered on the
  1998.                               screen.  Each message can be up to 65
  1999.                               characters in length.  Longer strings will be
  2000.                               truncated.
  2001.  
  2002.                 color       - Optional Clipper color string used for the box
  2003.                               and message display.  If omitted or a non-
  2004.                               character value is given, the default is the
  2005.                               current color setting.
  2006.  
  2007.                 keys        - Optional character string of keys that cause
  2008.                               ABOXASK() to terminate if pressed.  This string
  2009.                               may consist of letters or control characters. 
  2010.                               If omitted or a non-character value is given,
  2011.                               the default is any keypress will cause
  2012.                               ABOXASK() to terminate.
  2013.  
  2014.                 timeout     - Optional numeric value indicating the number of
  2015.                               seconds to wait before timing out and returning
  2016.                               a null string ("").  If omitted or a non-
  2017.                               numeric value is given, the default wait period
  2018.                               is forever (INKEY(0)).
  2019.  
  2020.    Returns:     The single character pressed in response to the boxed message
  2021.                 displayed.  If the character is lower case (a-z), it is
  2022.                 converted to upper case before being returned.  If the
  2023.                 optional timeout parameter is supplied and no key is pressed
  2024.                 within the timeout period, a null character ("") is returned.
  2025.  
  2026.    Description: ABOXASK() is a relative of the BOXASK() and SAYINBOX()
  2027.                 functions.  It pops up a message box centered on the screen
  2028.                 and displays the message strings that are contained in the
  2029.                 message array argument.  If the optional keys argument is
  2030.                 provided, these keys (expressed as a character string) will
  2031.                 be the only keys that, when pressed, will cause ABOXASK() to
  2032.                 terminate, all other keys pressed will be ignored.  If the
  2033.                 optional timeout is given, ABOXASK() will wait the indicated
  2034.                 number of seconds for a keypress by issuing the GETKEY()
  2035.                 function with timeout as the argument.  If no timeout is
  2036.                 given, ABOXASK() will wait forever for a keypress. 
  2037.  
  2038.    Notes:       ABOXASK() performs essentially the exact same task as
  2039.                 BOXASK().  However, when a large number of message lines are
  2040.                 being passed to BOXASK() as arguments, code can get wordy. 
  2041.                 ABOXASK() accepts a single array argument that contains the
  2042.                 several messages to display.  If only one or two messages are
  2043.                 being displayed you may want to use BOXASK() since it removes
  2044.  
  2045.  
  2046.    RLIB Function Reference                                                 29
  2047.  
  2048.  
  2049.                 the need for declaring an extra array.  ABOXASK() simplifies
  2050.                 box messages and allows you to maintain pre-defined arrays of
  2051.                 standard messages and frees you of having to clutter your
  2052.                 code with the message text strings. 
  2053.  
  2054.                 ABOXASK() will force all letters entered in response to the
  2055.                 message prompt to upper case.  All other keys are returned as
  2056.                 their CHR() values.
  2057.  
  2058.    Example:     *-- example of a SEEK or LOCATE failure notification
  2059.                 DECLARE msg[3]
  2060.                 msg[1] = "No record was found with the name you selected!"
  2061.                 msg[2] = "This name may have been misspelled"
  2062.                 msg[3] = "Press [ENTER] to try again, or [ESCAPE] to abort"
  2063.  
  2064.                 *-- present message, wait 30 seconds, default to ENTER
  2065.                 IF ABOXASK( msg, "W+/R", CHR(13)+CHR(27), 30 ) = CHR(27)
  2066.                    *-- ESCAPE key was explicitly pressed
  2067.                    EXIT
  2068.                 ENDIF
  2069.  
  2070.    Source:      RL_ABOXA.PRG
  2071.  
  2072.    See also:    BOXASK(), SAYINBOX()
  2073.  
  2074.  
  2075.  
  2076.  
  2077.  
  2078.  
  2079.  
  2080.  
  2081.  
  2082.  
  2083.  
  2084.  
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.  
  2096.  
  2097.  
  2098.  
  2099.  
  2100.  
  2101.  
  2102.  
  2103.  
  2104.  
  2105.    RLIB Function Reference                                                 30
  2106.  
  2107.  
  2108.    Function:    ACRONYM()
  2109.  
  2110.    Purpose:     Convert a text string to its abbreviated acronym.
  2111.  
  2112.    Syntax:      ACRONYM( string )
  2113.  
  2114.    Arguments:   string      - The character string to parse into an Acronym
  2115.  
  2116.    Returns:     An acronym consisting of each starting alphabetic character
  2117.                 starting at the beginning of the string and after each space.
  2118.  
  2119.    Description: Just what you always wanted, an acronym builder!  Suppose you
  2120.                 are writing a report and you want a short name for each
  2121.                 division to appear in a column that will identify the
  2122.                 division but not take up a lot of real estate on the report. 
  2123.                 Instead of printing a full name like "System Testing Under
  2124.                 Preliminary Investigation Division", this function will
  2125.                 reduce that long drawn out name to its proper acronym,
  2126.                 "STUPID".
  2127.  
  2128.    Notes:       Each acronym letter is retrieved from the string at each
  2129.                 break of one or more spaces.  If no spaces are found in the
  2130.                 string (i.e.  it is a single word), only the first letter of
  2131.                 the string will be returned.
  2132.  
  2133.                 If you want to ensure that the returned acronym is all upper
  2134.                 case, force the return value to upper case with
  2135.                 UPPER(ACRONYM(string)).
  2136.  
  2137.    Example:     ? ACRONYM("Three Letter Acronym")
  2138.                 *-- returns "TLA"
  2139.  
  2140.    Source:      RL_ACRON.PRG
  2141.  
  2142.    See also:    STR2DATE()
  2143.  
  2144.  
  2145.  
  2146.  
  2147.  
  2148.  
  2149.  
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155.  
  2156.  
  2157.  
  2158.  
  2159.  
  2160.  
  2161.  
  2162.  
  2163.  
  2164.    RLIB Function Reference                                                 31
  2165.  
  2166.  
  2167.    Function:    ADIM2()
  2168.  
  2169.    Purpose:     Formulate a two dimension reference to a linear array.
  2170.  
  2171.    Syntax:      ADIM2( row, col, numcols )
  2172.  
  2173.    Arguments:   row         - Numeric row of the two dimensional array
  2174.  
  2175.                 col         - Numeric column of the two dimensional array
  2176.  
  2177.                 numcols     - Number of columns in the two dimensional array
  2178.  
  2179.    Returns:     A linear number corresponding to the array element number
  2180.                 that would be located in a two dimensional array at the
  2181.                 positions row, column.
  2182.  
  2183.    Description: Functions like ADIM2() have been implemented many ways, this
  2184.                 one allows any array to be referenced by explicitly stating
  2185.                 the number of columns rather that setting up a PUBLIC
  2186.                 variable which limits an application to only one two
  2187.                 dimension array.
  2188.  
  2189.    Notes:       To implement a pseudo two-dimensional array in Clipper Summer
  2190.                 '87, the Clipper manual suggests that you declare a PUBLIC
  2191.                 variable named COLS so that the function will know how many
  2192.                 columns are in the array.  This limits access to only one
  2193.                 pseudo two dimensional array at a time since the example
  2194.                 function explicitly references the PUBLIC variable named
  2195.                 COLS.  By using ADIM2(), and passing the number of columns as
  2196.                 a parameter, you can use ADIM2() to access several two
  2197.                 dimensional arrays simultaneously.
  2198.  
  2199.    Example:     *-- set up a matrix array for small spreadsheet with 100 rows
  2200.                 *-- by 20 columns
  2201.                 DECLARE spread[ 100 * 20 ]
  2202.  
  2203.                 *-- simulate a Data Fill down, from 1 to 2000
  2204.                 x = 1
  2205.                 FOR col = 1 TO 20
  2206.                    FOR row = 1 TO 100
  2207.                       spread[ ADIM2(row,col,20) ] = x
  2208.                       x = x + 1
  2209.                    NEXT row
  2210.                 NEXT col
  2211.  
  2212.    Source:      RL_ADIM2.PRG
  2213.  
  2214.    See also:    ALIST()
  2215.  
  2216.  
  2217.  
  2218.  
  2219.  
  2220.  
  2221.  
  2222.  
  2223.    RLIB Function Reference                                                 32
  2224.  
  2225.  
  2226.    Function:    ALIST()
  2227.  
  2228.    Purpose:     List the elements of an array in a screen window.
  2229.  
  2230.    Syntax:      ALIST( array )
  2231.  
  2232.    Arguments:   array       - The array to list.
  2233.  
  2234.    Returns:     True if array listed successfully, false otherwise.
  2235.  
  2236.    Description: This function is most likely to be used from within the
  2237.                 Clipper debug session.  It takes an array reference as a
  2238.                 parameter and permits viewing of the elements in an array.
  2239.  
  2240.    Notes:       Since this function was designed as a tool for debugging, the
  2241.                 window is positioned on the right side of the screen so as to
  2242.                 overlay as little of the Clipper debug screen as possible. 
  2243.                 An easy enhancement would be to add window coordinates and
  2244.                 some display positioning logic.
  2245.  
  2246.                 If ALIST() is to be called from within a Clipper debug
  2247.                 session, and not included in your application, you need to
  2248.                 make the function available by using the EXTERNAL Alist
  2249.                 statement.  This places the function name in your
  2250.                 application's symbol table so the linker will bring in the
  2251.                 ALIST() function code so you can call it from debug.
  2252.  
  2253.    Example:     *-- the Clipper (Summer '87) debugger normally shows an array
  2254.                 *-- as just A from within the Clipper debugger.  To show a
  2255.                 *-- listing of the elements of an array, in the Summer '87
  2256.                 *-- debug Expression window, enter the following:
  2257.                 ALIST(array)
  2258.  
  2259.                 *-- a screen similar to the following will appear, with
  2260.                 *-- the elements of your array listed
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.  
  2269.  
  2270.  
  2271.  
  2272.  
  2273.  
  2274.  
  2275.  
  2276.  
  2277.  
  2278.  
  2279.  
  2280.  
  2281.  
  2282.    RLIB Function Reference                                                 33
  2283.  
  2284.  
  2285.                 ╔══════════════════════════════════════════════════════════╗
  2286.                 ║ [#]  TYPE  VALUE                                         ║
  2287.                 ╟──────────────────────────────────────────────────────────╢
  2288.                 ║  1.  C     "This is a character array element"           ║
  2289.                 ║  2.  C     "This is a very long character array elemen...║
  2290.                 ║  3.  N              1                                    ║
  2291.                 ║  4.  N              2                                    ║
  2292.                 ║  5.  N              3                                    ║
  2293.                 ║  6.  N             45.55555                              ║
  2294.                 ║  7.  L     T                                             ║
  2295.                 ║  8.  L     F                                             ║
  2296.                 ║  9.  D     04/10/91                                      ║
  2297.                 ║ 10.  C     "The rest of the array elements are charact...║
  2298.                 ║ 11.  C     "The rest of the array elements are charact...║
  2299.                 ║ 12.  C     "The rest of the array elements are charact...║
  2300.                 ║ 13.  C     "The rest of the array elements are charact...║
  2301.                 ║ 14.  C     "The rest of the array elements are charact...║
  2302.                 ║ 15.  C     "The rest of the array elements are charact...║
  2303.                 ║ 16.  C     "The rest of the array elements are charact...║
  2304.                 ║ 17.  C     "The rest of the array elements are charact...║
  2305.                 ║ 18.  C     "The rest of the array elements are charact...║
  2306.                 ║ 19.  C     "The rest of the array elements are charact...║
  2307.                 ║ Press any key for next screen, Escape to quit            ║
  2308.                 ╚══════════════════════════════════════════════════════════╝
  2309.  
  2310.  
  2311.    Source:      RL_ALIST.PRG
  2312.  
  2313.    See also:    ADIM2()
  2314.  
  2315.  
  2316.  
  2317.  
  2318.  
  2319.  
  2320.  
  2321.  
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327.  
  2328.  
  2329.  
  2330.  
  2331.  
  2332.  
  2333.  
  2334.  
  2335.  
  2336.  
  2337.  
  2338.  
  2339.  
  2340.  
  2341.    RLIB Function Reference                                                 34
  2342.  
  2343.  
  2344.    Function:    ALPHADATE()
  2345.  
  2346.    Purpose:     Convert date variables to alphabetic format
  2347.  
  2348.    Syntax:      ALPHADATE( [ date ] )
  2349.  
  2350.    Arguments:   date        - Optional date type date variable to display. 
  2351.                               If omitted the default DATE() is used.
  2352.  
  2353.    Returns:     The specified date as a character string in the form
  2354.                 January 1, 1990 
  2355.  
  2356.    Description: ALPHADATE() provides a convenient method of printing a date
  2357.                 in the form January 1, 1988.  If you print out text date
  2358.                 strings often in your application, using the following code
  2359.                 gets old quick: 
  2360.  
  2361.                 CMONTH(date) + ' ' + LTRIM(STR(DAY(date))) + ;
  2362.                 '  ' + STR(YEAR(date),4,0) 
  2363.  
  2364.    Notes:       If an invalid parameter is passed, RLIBERROR() will be set
  2365.                 and a null string will be returned.
  2366.  
  2367.    Example:     ? DATE()                        && if it is 01/01/90,
  2368.                 ? ALPHADATE()                   && returns "January 1, 1990"
  2369.                 ? ALPHADATE(DATE()+1)           && and "January 2, 1990"
  2370.  
  2371.                 ? ALPHADATE(CTOD("12/31/90"))   && "December 31, 1990"
  2372.  
  2373.                 ? ALPHADATE(12/31/90)           && bad parameter, returns ""
  2374.                                                 && and sets RLIBERROR()=1008
  2375.  
  2376.    Source:      RL_ALPHA.PRG
  2377.  
  2378.    See also:    FILEDATE()
  2379.  
  2380.  
  2381.  
  2382.  
  2383.  
  2384.  
  2385.  
  2386.  
  2387.  
  2388.  
  2389.  
  2390.  
  2391.  
  2392.  
  2393.  
  2394.  
  2395.  
  2396.  
  2397.  
  2398.  
  2399.  
  2400.    RLIB Function Reference                                                 35
  2401.  
  2402.  
  2403.    Function:    ANYCHARSIN()
  2404.  
  2405.    Purpose:     Test if any characters in one string are found in another
  2406.  
  2407.    Syntax:      ANYCHARSIN( characters, string )
  2408.  
  2409.    Arguments:   characters  - Characters to test for existence in the
  2410.                               <string> parameter.  May be any combination of
  2411.                               one or more characters.
  2412.  
  2413.                 string      - The character string to test if any of the
  2414.                               characters in the <characters> parameter exist.
  2415.  
  2416.    Returns:     Zero if none of the characters in <characters> are found in
  2417.                 <string>, otherwise returns the position in <characters> of
  2418.                 the 1st character found in <string>.
  2419.  
  2420.    Description: ANYCHARSIN() is used to test if any characters in one string
  2421.                 are contained in a second string.  If a character is found,
  2422.                 its position in <characters> is returned.  This is useful to
  2423.                 validate that only valid characters are contained in strings
  2424.                 such as filenames.
  2425.  
  2426.    Notes:       If an invalid parameter or an invalid number of parameters
  2427.                 are passed, a zero will be returned and RLIBERROR() set. 
  2428.  
  2429.    Example:     fname = SPACE(66)
  2430.                 @ 1,0 SAY "Enter filename:" GET fname VALID GoodFname(fname)
  2431.                 READ
  2432.                 RETURN
  2433.  
  2434.  
  2435.                 *-----------------------------------------------------------
  2436.                 FUNCTION GoodFname
  2437.                 PARAMETER filename
  2438.                 PRIVATE badchars, position
  2439.                 badchars = ' "/[]:*<>|+=;,?'
  2440.                 position = AnyCharsIn( badchars, filename )
  2441.                 IF position > 0
  2442.                    BUZZ()
  2443.                    BOXASK( 'W+/R', 'The "' + SUBSTR(badchars,position,1) +;
  2444.                            '" character is not allowed in filenames!',;
  2445.                            'Press any key to continue', 10 )
  2446.                 ENDIF
  2447.                 RETURN (position = 0)
  2448.  
  2449.    Source:      RL_ANYCH.PRG
  2450.  
  2451.    See also:    BOXASK()
  2452.  
  2453.  
  2454.  
  2455.  
  2456.  
  2457.  
  2458.  
  2459.    RLIB Function Reference                                                 36
  2460.  
  2461.  
  2462.    Function:    ARRAYLEN()
  2463.  
  2464.    Purpose:     Count the number of contiguous elements in an array.
  2465.  
  2466.    Syntax:      ARRAYLEN( array )
  2467.  
  2468.    Arguments:   array       - Array in which to count the contiguous
  2469.                               elements.
  2470.  
  2471.    Returns:     The number of contiguous elements in an array, starting at
  2472.                 the beginning array element.
  2473.  
  2474.    Description: ARRAYLEN() is useful for determining the actual number of
  2475.                 elements in an array where some elements may be missing.  The
  2476.                 LEN() function returns the length of an array as it was
  2477.                 declared.  However, if all of the array positions are not
  2478.                 filled, and you try to parse each element in a FOR loop, you
  2479.                 will encounter a run time error on the undeclared elements.
  2480.  
  2481.    Notes:       Will return zero if an invalid array parameter or no
  2482.                 parameter is passed and will set RLIBERROR().
  2483.  
  2484.    Example:     DECLARE array[10]
  2485.                 array[1] = "Hello"
  2486.                 array[2] = " world."
  2487.  
  2488.                 FOR x = 1 TO LEN(array)       && will be 10
  2489.                    ?? array[x]                && on #3 will produce run-time
  2490.                 NEXT x                        &&  error Undefined Identifier
  2491.  
  2492.                 *-- corrected version
  2493.                 FOR x = 1 TO ArrayLen(array)  && will be 2
  2494.                    ?? array[x]
  2495.                 NEXT x
  2496.  
  2497.    Source:      RL_ARRAY.PRG
  2498.  
  2499.    See also:    ALIST()
  2500.  
  2501.  
  2502.  
  2503.  
  2504.  
  2505.  
  2506.  
  2507.  
  2508.  
  2509.  
  2510.  
  2511.  
  2512.  
  2513.  
  2514.  
  2515.  
  2516.  
  2517.  
  2518.    RLIB Function Reference                                                 37
  2519.  
  2520.  
  2521.    Function:    ATINSAY()
  2522.  
  2523.    Purpose:     Display an expression at coordinates in a specified color.
  2524.  
  2525.    Syntax:      ATINSAY( row, column, color, string )
  2526.  
  2527.    Arguments:   row         - Numeric value indicating the row on which to
  2528.                               display <string>.  Value must be between 0 and
  2529.                               24, or MAXROW() in the Clipper 5.0 version.
  2530.  
  2531.                 column      - Numeric value indicating the column position on
  2532.                               which to display <string>.  Value must be
  2533.                               between 0 and 79.
  2534.  
  2535.                 color       - Character string indicating the color setting
  2536.                               to use in displaying <string>.  This character
  2537.                               string must be consistent with Clipper's color
  2538.                               setting requirements.  See the Clipper manual
  2539.                               under SET COLOR for details.
  2540.  
  2541.                 string      - The character string to display at screen
  2542.                               coordinates <row>,<column> in <color> 
  2543.  
  2544.    Returns:     Nothing useful, a null string.
  2545.  
  2546.    Description: This function takes the repetition out of displaying strings
  2547.                 in various color settings.   You simply give this function
  2548.                 the row,column coordinates, the color setting, and the string
  2549.                 to display and it does the rest, and resets the color when
  2550.                 finished.
  2551.  
  2552.    Notes:       If no parameters, an invalid number, or invalid type of
  2553.                 parameters are passed, no action is taken and RLIBERROR()
  2554.                 set.
  2555.  
  2556.    Example:     *-- old way of displaying a message in White on Red, then
  2557.                 *-- changing back to White on Black
  2558.                 SET COLOR TO w/r
  2559.                 @ 24,30 SAY 'A sample message on line 24'
  2560.                 SET COLOR TO w/n
  2561.  
  2562.                 *-- new way
  2563.                 ATINSAY( 24, 30, 'w/r', 'A sample message on line 24' )
  2564.  
  2565.    Source:      RL_ATINS.PRG
  2566.  
  2567.    See also:    BOXASK(), CENTER(), KEYINPUT(), RJUSTIFY(), SAYINBOX()
  2568.  
  2569.  
  2570.  
  2571.  
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577.    RLIB Function Reference                                                 38
  2578.  
  2579.  
  2580.    Function:    BARMENU()
  2581.  
  2582.    Purpose:     Create horizontal light bar menus.
  2583.  
  2584.    Syntax:      BARMENU( row, options [, columns [, start [, altkeys [,;
  2585.                          exitkeys [, messages [, msg_row [, colors ]]]]]]])
  2586.  
  2587.    Arguments:   row         - Numeric value which indicates the row on which
  2588.                               the bar menu is to appear.  Value must be
  2589.                               between 0 and 24, or MAXROW() in the Clipper
  2590.                               5.0 version.
  2591.  
  2592.                 options     - Array of character strings to display as bar
  2593.                               menu option choices.
  2594.  
  2595.                 columns     - Optional array of numeric values used as column
  2596.                               numbers on which to display each option.
  2597.  
  2598.                 start       - Optional starting array element number for the
  2599.                               menu option to highlight upon start-up.
  2600.  
  2601.                 altkeys     - Optional list of alternate selection keys which
  2602.                               when pressed, cause an option to be selected.
  2603.  
  2604.                 exitkeys    - Optional list of keys to cause a zero return
  2605.                               value exit.  Pass a null string to skip.  The
  2606.                               default key is Escape.  Pass a value of False
  2607.                               (.F.) to disable the zero return value exit
  2608.                               capability altogether.
  2609.  
  2610.                 messages    - Optional array of menu option messages which
  2611.                               are displayed as each menu option is
  2612.                               highlighted.
  2613.  
  2614.                 msg_row     - Optional row number on which these messages
  2615.                               appear.  The default row for these messages in
  2616.                               row 24.  In the Clipper 5.0 version the default
  2617.                               message row in MAXROW(), the bottom screen row.
  2618.  
  2619.                 colors      - Optional array of character strings specifying
  2620.                               the color settings to use.  The colors used for
  2621.                               the different parts of the menu are specified
  2622.                               as follows:
  2623.  
  2624.                                  colors[1] = Menu options
  2625.                                  colors[2] = Menu highlight bar
  2626.                                  colors[3] = <not used>
  2627.                                  colors[4] = Menu messages
  2628.                                  colors[5] = Selected option on exit
  2629.  
  2630.    Returns:     A numeric value indicating the number of the array element
  2631.                 option selected or zero if the escape key was pressed (or one
  2632.                 of the <exitkeys>).
  2633.  
  2634.  
  2635.  
  2636.    RLIB Function Reference                                                 39
  2637.  
  2638.  
  2639.    Description: BARMENU() makes creating horizontal light bar menus a snap. 
  2640.                 Although creating this type of menu has been simplified with
  2641.                 Clipper's PROMPT and MENU TO commands, this function offers
  2642.                 additional flexibility while keeping your code to a minimum.
  2643.  
  2644.    Notes:       In the Clipper 5.0 version of BARMENU(), the <row> parameter
  2645.                 may be any row value between 0 and MAXROW().
  2646.  
  2647.                 Optional parameters are not required, but if you wish to skip
  2648.                 an optional parameter, you must pass a dummy value.  The best
  2649.                 dummy value to use is a null string "" (set up a memvar named
  2650.                 dummy where dummy = "").
  2651.  
  2652.                 In addition to the right and left arrow keys, the space bar
  2653.                 and back space keys move the menu bar to the right and left. 
  2654.                 The menu bar line background (color[4]) is used to clear the
  2655.                 menu line and place it in that color.
  2656.  
  2657.    Example:     *-- declare arrays for menu and message options
  2658.                 DECLARE option[5], prompt[5]
  2659.  
  2660.                 *-- menu choices
  2661.                 option[1] = 'File'
  2662.                 option[2] = 'Edit'
  2663.                 option[3] = 'Next'
  2664.                 option[4] = 'Previous'
  2665.                 option[5] = 'Quit'
  2666.  
  2667.                 *-- corresponding message prompts
  2668.                 prompt[1] = 'Load, Save, Transfer, Erase, Quit'
  2669.                 prompt[2] = 'New orders, Repairs, Exchanges, Quit'
  2670.                 prompt[3] = 'Skip to the next entry'
  2671.                 prompt[4] = 'Skip to the previous entry'
  2672.                 prompt[5] = 'Quit and return to DOS'
  2673.  
  2674.                 *-- set up column position numbers so options fill screen
  2675.                 *-- File        Edit        Next        Previous       Quit
  2676.  
  2677.  
  2678.                 *-- if omitted options will look like this:
  2679.                 *-- File  Edit  Next  Previous  Quit
  2680.                 column[1] =  0
  2681.                 column[2] = 18
  2682.                 column[3] = 36
  2683.                 column[4] = 54
  2684.                 column[5] = 76
  2685.  
  2686.  
  2687.                 *-- let the down and up arrows also select Next and Previous
  2688.                 *-- the AT() position of altkeys in the string must match the
  2689.                 *-- corresponding array element number.
  2690.                 altkeys = 'FE' + CHR(24) + CHR(5) + 'Q'
  2691.  
  2692.  
  2693.  
  2694.  
  2695.    RLIB Function Reference                                                 40
  2696.  
  2697.  
  2698.                 *-- set up colors to be used
  2699.                 DECLARE colors[5]
  2700.                 colors[1] = 'B/BG'            && options are Blue on Cyan
  2701.                 colors[2] = 'B/W'             && menu bar is Blue on White
  2702.                 colors[3] = ''                && not used
  2703.                 colors[4] = 'B/BG'            && menu line also Blue on Cyan
  2704.                 colors[5] = 'W+/BG'           && selected option Bright White
  2705.  
  2706.                 *-- keep Escape from causing exit, force them to press Q
  2707.                 xitkeys = .F.
  2708.  
  2709.                 *-- initial choice = 'File' = 1
  2710.                 choice = 1        && initial menu choice is #1, File
  2711.                 toprow = 1        && put menu on top row, row #1
  2712.                 msgrow = 2        && show menu messages on row #2
  2713.  
  2714.                 *-- display menu on row 1 with messages on row 2
  2715.                 choice = BARMENU( toprow, column, option, choice, altkeys,;
  2716.                                   xitkeys, prompts, msgrow, colors )
  2717.  
  2718.    Source:      RL_BARME.PRG
  2719.  
  2720.    See also:    BOXMENU(), MULTIMENU(), PDOWNMENU()
  2721.  
  2722.  
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.  
  2747.  
  2748.  
  2749.  
  2750.  
  2751.  
  2752.  
  2753.  
  2754.    RLIB Function Reference                                                 41
  2755.  
  2756.  
  2757.    Function:    BEEP()
  2758.  
  2759.    Purpose:     Ring the system bell one or more times.
  2760.  
  2761.    Syntax:      BEEP( [ count ] )
  2762.  
  2763.    Arguments:   count       - Optional numeric variable specifying the number
  2764.                               of times to ring the bell.  If no parameter is
  2765.                               specified, the bell will be sounded one time.
  2766.  
  2767.    Returns:     A null string ("").
  2768.  
  2769.    Description: This function merely rings the system bell the specified
  2770.                 number of times.  BEEP() is a desired replacement for the ??
  2771.                 CHR(7) + CHR(7) sequence.  It may not be very sophisticated,
  2772.                 but you may find yourself using it all the time!
  2773.  
  2774.    Notes:       No known weird behavior.
  2775.  
  2776.    Example:     *-- ring the bell
  2777.                 BEEP()
  2778.  
  2779.                 *-- ring it 10 times
  2780.                 BEEP(10)
  2781.  
  2782.    Source:      RL_BEEP.PRG
  2783.  
  2784.    See also:    BLIP(), BUZZ()
  2785.  
  2786.  
  2787.  
  2788.  
  2789.  
  2790.  
  2791.  
  2792.  
  2793.  
  2794.  
  2795.  
  2796.  
  2797.  
  2798.  
  2799.  
  2800.  
  2801.  
  2802.  
  2803.  
  2804.  
  2805.  
  2806.  
  2807.  
  2808.  
  2809.  
  2810.  
  2811.  
  2812.  
  2813.    RLIB Function Reference                                                 42
  2814.  
  2815.  
  2816.    Function:    BIN2DEC()
  2817.  
  2818.    Purpose:     Convert a binary number to its equivalent decimal value.
  2819.  
  2820.    Syntax:      BIN2DEC( bin_str )
  2821.  
  2822.    Arguments:   bin_str     - A character string representing the binary
  2823.                               number to convert to decimal value.
  2824.  
  2825.    Returns:     The decimal value of the binary string parameter.
  2826.  
  2827.    Description: BIN2DEC() converts a string that represents a binary number
  2828.                 into its decimal equivalent.
  2829.  
  2830.    Notes:       BIN2DEC() only converts positive numbers, there is no
  2831.                 provision for determining the sign bit.  The <bin_str>
  2832.                 parameter must be a valid binary string, i.e.  all characters
  2833.                 must be either a zero or a one.  If a character is not a one
  2834.                 ("1"), then BIN2DEC() will assume it to represent a zero in
  2835.                 its parse calculation.
  2836.  
  2837.                 If the required parameter is omitted, a zero will be returned
  2838.                 and RLIBERROR() set.
  2839.  
  2840.    Example:     bin_num = "11001101"
  2841.                 dec_val = BIN2DEC(bin_num)
  2842.                 ? dec_val                     && result = 205
  2843.  
  2844.    Source:      RL_BIN2D.PRG
  2845.  
  2846.    See also:    DEC2HEX(), HEX2DEC()
  2847.  
  2848.  
  2849.  
  2850.  
  2851.  
  2852.  
  2853.  
  2854.  
  2855.  
  2856.  
  2857.  
  2858.  
  2859.  
  2860.  
  2861.  
  2862.  
  2863.  
  2864.  
  2865.  
  2866.  
  2867.  
  2868.  
  2869.  
  2870.  
  2871.  
  2872.    RLIB Function Reference                                                 43
  2873.  
  2874.  
  2875.    Function:    BLIP()
  2876.  
  2877.    Purpose:     Generate a blipping sound for warnings or errors.
  2878.  
  2879.    Syntax:      BLIP( [ count ] )
  2880.  
  2881.    Arguments:   count       - Optional numeric value specifying the number of
  2882.                               times to make a BLIP sound.  If no parameter is
  2883.                               specified, one BLIP will be sounded.
  2884.  
  2885.    Returns:     Zero.
  2886.  
  2887.    Description: BLIP() is a convenient function whenever you want to make the
  2888.                 PC speaker emit a short "BLIP" sound, such as when the user
  2889.                 encounters an error condition.  The Clipper function to do
  2890.                 this is TONE( frequency, duration ).  For a Blip sound, the
  2891.                 frequency would be 500Khz and the duration should be around
  2892.                 2/18ths of a second.  Instead of having to remember
  2893.                 TONE(500,2) as being the function to make a BLIP sound, it is
  2894.                 much easier to simply use a function named BLIP().
  2895.  
  2896.    Notes:       No limitations other than one that may be imposed upon the
  2897.                 Clipper TONE() function.
  2898.  
  2899.    Example:     *-- user does something wrong
  2900.                 BLIP()
  2901.  
  2902.                 *-- user does something really wrong!
  2903.                 BLIP(3)
  2904.  
  2905.    Source:      RL_BLIP.PRG
  2906.  
  2907.    See also:    BEEP(), BUZZ()
  2908.  
  2909.  
  2910.  
  2911.  
  2912.  
  2913.  
  2914.  
  2915.  
  2916.  
  2917.  
  2918.  
  2919.  
  2920.  
  2921.  
  2922.  
  2923.  
  2924.  
  2925.  
  2926.  
  2927.  
  2928.  
  2929.  
  2930.  
  2931.    RLIB Function Reference                                                 44
  2932.  
  2933.  
  2934.    Function:    BORDERBOX()
  2935.  
  2936.    Purpose:     Draw a box with a one line title area at the top.
  2937.  
  2938.    Syntax:      BORDERBOX( t,l,b,r, title, [,clear [,box  [,color ]]] )
  2939.  
  2940.    Arguments:   t,l,b,r     - Numeric values specifying the Top, Left, Bottom
  2941.                               and Right screen coordinates of the display
  2942.                               box.  The top and bottom row values must be
  2943.                               between 0 and 24 (MAXROW() in 5.0), and the
  2944.                               left and right column values must be between 0
  2945.                               and 79.
  2946.  
  2947.                 title       - Character string or expression to display as a
  2948.                               title in the box header area.
  2949.  
  2950.                 clear       - Optional logical flag telling BORDERBOX()
  2951.                               whether or not to clear the box area.  If
  2952.                               omitted or a non-logical parameter is passed,
  2953.                               the default value is True.
  2954.  
  2955.                 box         - Optional character string to be used as the box
  2956.                               characters.  Specify either double, single, or
  2957.                               solid box characters.  If omitted or a non-
  2958.                               character value is passed, the default is
  2959.                               double.
  2960.  
  2961.                 color       - Optional character string to use as the color
  2962.                               setting for the border box and header.  If
  2963.                               omitted or a non-character value is passed, the
  2964.                               default is SETCOLOR().
  2965.  
  2966.    Returns:     True if the box was painted, false if an error occurred or if
  2967.                 any required parameters are missing or are an invalid type.
  2968.  
  2969.    Description: This function paints a double line box with a one line title
  2970.                 in it.  You can optionally specify whether or not to clear
  2971.                 the inside area.
  2972.  
  2973.    Notes:       The first four parameters are required.  If omitted, the box
  2974.                 will not be drawn and a false value returned.  If you do not
  2975.                 want a title in the box, pass a null string ("") for the
  2976.                 title parameter.
  2977.  
  2978.                 The title string is centered in the header area of the border
  2979.                 box.  Because of this centering feature, no provision is made
  2980.                 to truncate the string if it is too wide to fit in the width
  2981.                 of the box.  Therefore, you must ensure that the title string
  2982.                 is not wider that the width of the inside of the box.  If so,
  2983.                 the title string will spill over on the left and right sides.
  2984.  
  2985.                 A false value for the clear parameter is useful for not
  2986.                 disturbing the contents of a previously displayed box on
  2987.                 re-entry.  If omitted, the inside of the box area is cleared.
  2988.  
  2989.  
  2990.    RLIB Function Reference                                                 45
  2991.  
  2992.  
  2993.                 The box parameter lets you customize the frame.  However, the
  2994.                 concept of the border box is that the left side of the border
  2995.                 line must match the horizontal boxing character.  This
  2996.                 function only uses three characters, the single side (├), the
  2997.                 double side (╟), and the solid side (█).  If the vertical
  2998.                 part of your box character string is none of these, you will
  2999.                 need to modify this function, or use only single, double or
  3000.                 solid boxes.  See the Clipper documentation on the @ ...  BOX
  3001.                 ..  command for more information on box strings.
  3002.  
  3003.    Example:     *-- set up a bordered box for a PICKREC() display to show a
  3004.                 *-- help pick list of available Account numbers
  3005.  
  3006.                 top    =  1
  3007.                 left   = 40
  3008.                 bottom = 10
  3009.                 right  = 68
  3010.                 title  = "AVAILABLE ACCOUNT NUMBERS"
  3011.                 BORDERBOX( top, bottom, left, right, title )
  3012.  
  3013.                 *-- now fill with PICKREC() selections, note that the
  3014.                 *-- PICKREC() coordinates are offset 1 row/column in
  3015.                 display = "' '+AcctNum+' - '+AcctName+' '"
  3016.  
  3017.                 choice = PICKREC(top+3, left+1, bottom-1, right-1, display)
  3018.  
  3019.                 *-- output will look something like this
  3020.                 *                        ╔═══════════════════════════╗
  3021.                 *                        ║ AVAILABLE ACCOUNT NUMBERS ║
  3022.                 *                        ╟───────────────────────────╢
  3023.                 *                        ║ 1000 - OFFICE SUPPLIES    ║
  3024.                 *                        ║ 1001 - EQUIPMENT PURCHASE ║
  3025.                 *                        ║ 1002 - EQUIPMENT LEASE    ║
  3026.                 *                        ║ 1003 - TELEPHONE EXPENSE  ║
  3027.                 *                        ║ 1004 - RENT               ║
  3028.                 *                        ║ 1005 - UTILITIES          ║
  3029.                 *                        ╚═══════════════════════════╝
  3030.  
  3031.    Source:      RL_BORDE.PRG
  3032.  
  3033.    See also:    PICKREC(), POPUPPICK()
  3034.  
  3035.  
  3036.  
  3037.  
  3038.  
  3039.  
  3040.  
  3041.  
  3042.  
  3043.  
  3044.  
  3045.  
  3046.  
  3047.  
  3048.  
  3049.    RLIB Function Reference                                                 46
  3050.  
  3051.  
  3052.    Function:    BOXASK()
  3053.  
  3054.    Purpose:     Pop up a centered message box using multiple message strings.
  3055.  
  3056.    Syntax:      BOXASK( [color] [keys] message1 [...message9] [timeout] )
  3057.  
  3058.    Arguments:   color       - If the FIRST parameter has a slash "/"
  3059.                               character in the 2nd, 3rd, or 4th position, 
  3060.                               this parameter will be interpreted as the color
  3061.                               setting for the message box.  (All color
  3062.                               strings look like: R/W, or R+/W, or R+*/W) 
  3063.  
  3064.                 keys        - If the FIRST or SECOND parameter begins with a
  3065.                               dollar sign character "$", the parameter will
  3066.                               be interpreted as a string of valid keys that
  3067.                               can be pressed to terminate BOXASK().  The "$"
  3068.                               character is easily remembered because it is
  3069.                               the Clipper substring "contained in" operator.
  3070.  
  3071.                 message1,9  - Any other character parameters, including the
  3072.                               first and or second parameters if they don't
  3073.                               meet the above conditions, will be displayed as
  3074.                               BOXASK() messages.  Up to nine message lines
  3075.                               may be passed and displayed.
  3076.  
  3077.                 timeout     - If the LAST parameter is a numeric value, it
  3078.                               will be used as a timeout value for the message
  3079.                               box.  This timeout is the number of seconds
  3080.                               BOXASK() will wait for a keypress.  If no key
  3081.                               is pressed before the timeout is reached,
  3082.                               BOXASK() will exit and return a null string. 
  3083.                               If no timeout is supplied, BOXASK() will wait
  3084.                               forever for a keypress.
  3085.  
  3086.    Returns:     The single character pressed in response to the message box 
  3087.                 displayed on the screen.  If the key pressed is an alphabetic 
  3088.                 character BOXASK will return the character normalized to
  3089.                 upper case.  As a consequence, character comparisons need
  3090.                 only compare against upper case characters.  See examples.
  3091.  
  3092.    Description: BOXASK() is a function that becomes addictive!  Once you
  3093.                 start using it you'll never stop.  It's perfect for
  3094.                 displaying all sorts of messages in a consistent manner. 
  3095.                 BOXASK() displays up to nine lines of text messages, centered
  3096.                 on the screen in a single line box, in a defined color.  Each
  3097.                 line may be up to 68 characters long.  All of the screen
  3098.                 centering is done automatically.  After the message box is
  3099.                 displayed BOXASK() waits for a user keypress (in response to
  3100.                 the message).  If no time out parameter is given, BOXASK will
  3101.                 wait forever for a response.  If the optional keys parameter
  3102.                 is supplied, the characters that appear in the keys string
  3103.                 will be the only character accepted as valid keypresses to
  3104.                 terminate BOXASK().
  3105.  
  3106.  
  3107.  
  3108.    RLIB Function Reference                                                 47
  3109.  
  3110.  
  3111.    Notes:       BOXASK() accepts a variable number of parameters and will act
  3112.                 differently on the parameters depending on their format.  All
  3113.                 parameters (except the timeout, which must be the last
  3114.                 parameter) are expected to be character type.
  3115.  
  3116.                 If the first parameter is a color setting, BOXASK() will use
  3117.                 that color combination instead of the default current color
  3118.                 SETCOLOR().  If either the first or second parameters begin
  3119.                 with the "$" character, the string following the dollar sign
  3120.                 will be used as a list of valid keypresses from which to
  3121.                 exit.
  3122.  
  3123.                 Ideally, all functions should be as BLACK BOX as possible. 
  3124.                 This means that if a function alters a system state such as
  3125.                 the screen color, it should restore the system to the way it
  3126.                 was on entry.  Since BOXASK() will query a user for a
  3127.                 keypress, ideally the cursor should be on.  However, since
  3128.                 Clipper Summer '87 has no native way of querying the state of
  3129.                 the cursor, BOXASK() has no way of knowing whether or not the
  3130.                 cursor was on, and can not set cursor on and expect to
  3131.                 restore the system to the way it was.  To get around this
  3132.                 limitation, and still allow BOXASK to turn the cursor on, an
  3133.                 RLIB function named SETCURSOR() is provided.  (See the
  3134.                 documentation SETCURSOR)  If you utilize the SETCURSOR()
  3135.                 function, BOXASK() will know and will be able to restore the
  3136.                 state of the cursor on exit.  The Clipper 5.0 version uses
  3137.                 the internal SETCURSOR function instead.
  3138.  
  3139.                 If the key that is pressed in response to BOXASK() is a lower
  3140.                 case letter (a - z), BOXASK() will return the response as an
  3141.                 upper case letter.  In other words, BOXASK() will uppercase
  3142.                 letters between a-z, so you do not have to use the UPPER()
  3143.                 function to test if the user pressed a "Y" for instance.  All
  3144.                 other keys are returned as their CHR() values.  BOXASK() will
  3145.                 wait forever for a keypress unless a timeout value is given.
  3146.  
  3147.                 In the Clipper 5.0 version of BOXASK(), the PARAMETERS have
  3148.                 remained as PRIVATE variables since they are referenced via
  3149.                 macro substitution, and this will not work with local
  3150.                 variables.
  3151.  
  3152.    Example:     *-- example of a SEEK or LOCATE failure notification
  3153.                 msg1 = "No record was found with the name you selected!"
  3154.                 msg2 = "This name may have been misspelled"
  3155.                 msg3 = "Press [ENTER] to try again, or [ESCAPE] to abort"
  3156.  
  3157.                 color = "W+/R"
  3158.                 keys  = "$" + CHR(13) + CHR(27)
  3159.                 *-- present message, wait 30 seconds, default to ENTER
  3160.                 IF BOXASK( color, keys, msg1, msg2, msg3, 30 ) = CHR(27)
  3161.                    *-- ESCAPE key was explicitly pressed
  3162.                    EXIT
  3163.                 ENDIF
  3164.                 *-- will fall through if timed out, result = CHR(13) or NULL
  3165.  
  3166.  
  3167.    RLIB Function Reference                                                 48
  3168.  
  3169.  
  3170.    Source:      RL_BOXAS.PRG
  3171.  
  3172.    See also:    ABOXASK(), SAYINBOX()
  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.  
  3212.  
  3213.  
  3214.  
  3215.  
  3216.  
  3217.  
  3218.  
  3219.  
  3220.  
  3221.  
  3222.  
  3223.  
  3224.  
  3225.  
  3226.    RLIB Function Reference                                                 49
  3227.  
  3228.  
  3229.    Function:    BOXMENU()
  3230.  
  3231.    Purpose:     Create boxed framed highlight bar (pop up) menus.
  3232.  
  3233.    Syntax:      BOXMENU( row, column, options [, choice [, altkeys;
  3234.                          [, exitkeys [, messages [, msg_row [, colors;
  3235.                          [, header [, restore ]]]]]]]]] )
  3236.  
  3237.    Arguments:   row         - Numeric value indicating the row for the top
  3238.                               left corner of the menu box.  Value must be
  3239.                               between 0 and 24, or MAXROW() in the Clipper
  3240.                               5.0 version.
  3241.  
  3242.                 column      - Numeric value indicating the column for the top
  3243.                               left corner of the menu box.  The value must be
  3244.                               between 0 and 79.
  3245.  
  3246.                 options     - Array of character strings to use as menu
  3247.                               options.  Each element of the array is
  3248.                               displayed as a menu option filling the box.
  3249.  
  3250.                 choice      - Optional numeric value indicating the starting
  3251.                               menu option number.  Value checked to be
  3252.                               between 1 and the number of elements in the
  3253.                               option array.  If an out of range value is
  3254.                               given, the starting number will be 1.
  3255.  
  3256.                 altkeys     - Optional character string indicating what keys
  3257.                               may be pressed to select the corresponding menu
  3258.                               option.  The default is the first letter of
  3259.                               each of the menu options but, if this string is
  3260.                               provided, it is added to that list.  The
  3261.                               requirement is that the AT() position of the
  3262.                               character in the alternate key list is the
  3263.                               numeric equivalent of the corresponding menu
  3264.                               choice.
  3265.  
  3266.                 exitkeys    - Optional character string indicating which keys
  3267.                               if pressed will cause an exit and return zero. 
  3268.                               If omitted or an empty (or null) string is
  3269.                               specified, the Escape Key will default to being
  3270.                               the only key to cause a return zero exit.  If
  3271.                               this parameter is specified as a logical .F.,
  3272.                               no keys will cause a return 0 exit (it will be
  3273.                               disabled), and only the Enter Key will cause an
  3274.                               exit condition.
  3275.  
  3276.                 messages    - Optional array of character strings to display
  3277.                               as messages corresponding to each of the menu
  3278.                               options.   
  3279.  
  3280.                 msg_row     - Optional numeric value indicating the row for
  3281.                               the optional prompt messages to appear.  This
  3282.                               value must be between 0 and 24, or MAXROW() in
  3283.  
  3284.  
  3285.    RLIB Function Reference                                                 50
  3286.  
  3287.  
  3288.                               the Clipper 5.0 version.  The default is row
  3289.                               24.  In the 5.0 version the default row is
  3290.                               MAXROW(), the bottom screen row.
  3291.  
  3292.                 colors      - Optional array of character strings specifying
  3293.                               the color settings to use.  The colors used for
  3294.                               the different parts of the menu are specified
  3295.                               as follows:
  3296.  
  3297.                                  color[1] -  Menu choices (item options)
  3298.                                  color[2] -  Menu selection bar
  3299.                                  color[3] -  Active menu box (on entry)
  3300.                                  color[4] -  Inactive menu box (on exit)
  3301.                                  color[5] -  Menu choice upon selection
  3302.                                  color[6] -  Messages displayed on promptrow
  3303.  
  3304.                 header      - Optional character string which, if supplied
  3305.                               will force BOXMENU() to extend the box around
  3306.                               the menu to include a header area.  The string
  3307.                               supplied will be centered in this area as a
  3308.                               menu title.  See BORDERBOX() for additional
  3309.                               details.
  3310.  
  3311.                 restore     - Optional logical value indicating whether or
  3312.                               not to save and restore the screen region
  3313.                               underneath the menu on exit.  The default is
  3314.                               false.
  3315.  
  3316.    Returns:     The number of the array element option picked, or 0 if escape
  3317.                 was pressed.
  3318.  
  3319.    Description: BOXMENU() follows a popular and logical sequence for
  3320.                 producing box style menus.  The active menu is surrounded by
  3321.                 a double line box.  When it becomes inactive after a choice
  3322.                 is made, the box border changes to a single line to indicate
  3323.                 the menu is no longer active.  If the row and/or column
  3324.                 positions supplied are out of bounds (not between 0 and 24
  3325.                 (MAXROW() in 5.0 version), and 0 and 79) a default row or
  3326.                 column of 1 will be used.  Also, since this is mainly a menu
  3327.                 building tool, no provision has been made to scroll menu
  3328.                 items below the bottom of the menu box.  Consequently, you
  3329.                 should consider how many options will be in the menu when
  3330.                 determining the top row, as the bottom of the box is
  3331.                 calculated by adding the number of options in the array.  If
  3332.                 more elements exist in the array than will fit in the box,
  3333.                 unpredictable screen displays will occur.  This exclusion was
  3334.                 made for the benefit of speed and compactness of code.  If a
  3335.                 scrollable menu is needed, use ACHOICE().
  3336.  
  3337.    Notes:       If an optional parameter is skipped, you must pass a dummy in
  3338.                 its place.
  3339.  
  3340.                 If you use the color feature, DECLARE your colors array to
  3341.                 have at least 6 elements.  If the colors option is not
  3342.  
  3343.  
  3344.    RLIB Function Reference                                                 51
  3345.  
  3346.  
  3347.                 specified or there are less than 5 elements, then the default
  3348.                 colors are used.  These defaults are: the current Standard
  3349.                 color is used for the box and item displays, and the Enhanced
  3350.                 color is used for the menu bar.  The sixth element is new to
  3351.                 version 3.0 (See below) 
  3352.  
  3353.                 The colors array may now contain six elements.  The sixth
  3354.                 element is used as the color for displaying the optional
  3355.                 messages on <promptrow>.  In RLIB version 2.0, these messages
  3356.                 used to be displayed in the same color as the menu options
  3357.                 which was not always (and rarely) desirable.  To maintain
  3358.                 upward compatibility, the color array table may remain at 5
  3359.                 elements.  The 6th element is optional.  If the 6th element
  3360.                 for the optional messages color is not given, then the Option
  3361.                 color (element #1) is used.
  3362.  
  3363.  
  3364.    Example:     *-- declare arrays for menu and message options
  3365.                 DECLARE option[5], message[5]
  3366.  
  3367.                 *-- menu choices
  3368.                 option[1] = " 1.  Add new records (Append) "
  3369.                 option[2] = " 2.  Edit records    (Change) "
  3370.                 option[3] = " 3.  Delete records  (Remove) "
  3371.                 option[4] = " 4.  Update records  (Modify) "
  3372.                 option[5] = " 5.  Quit and return (eXit)   "
  3373.  
  3374.                 *-- corresponding messages
  3375.                 message[1] = "Add new records to the database"
  3376.                 message[2] = "Edit records already in the database"
  3377.                 message[3] = "Delete selected records"
  3378.                 message[4] = "Update dates of last appointments"
  3379.                 message[5] = "Leave this menu and return to previous"
  3380.  
  3381.                 *-- in addition to 1,2,3,4, or 5, (default select keys)
  3382.                 *-- let the following keys also select the choices
  3383.                 alt_keys = 'AEDUQ' + 'ACRMX'
  3384.  
  3385.                 DECLARE colors[6]
  3386.                 colors[1] = 'N/BG'      && options are Black on Cyan
  3387.                 colors[2] = 'W+/GR'     && menu bar is Bright White on Brown
  3388.                 colors[3] = 'R+/BG'     && active menu is Bright Red on Cyan
  3389.                 colors[4] = 'R/BG'      && in-active is Red on Cyan
  3390.                 colors[5] = 'R/BG'      && selected choice is Red on Cyan
  3391.                 colors[6] = 'BG/N'      && messages are Cyan on Black
  3392.  
  3393.                 *-- allow Escape and Left and Right arrow keys to exit
  3394.                 exit_keys = CHR(27) + CHR(19) + CHR(4)
  3395.  
  3396.                 *-- start with first choice
  3397.                 choice = 1
  3398.  
  3399.                 *-- header message
  3400.                 header = "AVAILABLE OPTIONS"
  3401.  
  3402.  
  3403.    RLIB Function Reference                                                 52
  3404.  
  3405.  
  3406.                 *-- put up menu on row 2, column 10, with messages on row 24
  3407.                 choice = BOXMENU( 2,10, option, choice, alt_keys, exit_keys,;
  3408.                                   message, 24, colors, header )
  3409.  
  3410.    Source:      RL_BOXME.PRG
  3411.  
  3412.    See also:    BARMENU(), MULTIMENU(), PDOWNMENU()
  3413.  
  3414.  
  3415.  
  3416.  
  3417.  
  3418.  
  3419.  
  3420.  
  3421.  
  3422.  
  3423.  
  3424.  
  3425.  
  3426.  
  3427.  
  3428.  
  3429.  
  3430.  
  3431.  
  3432.  
  3433.  
  3434.  
  3435.  
  3436.  
  3437.  
  3438.  
  3439.  
  3440.  
  3441.  
  3442.  
  3443.  
  3444.  
  3445.  
  3446.  
  3447.  
  3448.  
  3449.  
  3450.  
  3451.  
  3452.  
  3453.  
  3454.  
  3455.  
  3456.  
  3457.  
  3458.  
  3459.  
  3460.  
  3461.  
  3462.    RLIB Function Reference                                                 53
  3463.  
  3464.  
  3465.    Function:    BRIGHT()
  3466.  
  3467.    Purpose:     Convert a Clipper color string to its bright equivalent.
  3468.  
  3469.    Syntax:      BRIGHT( [color] )
  3470.  
  3471.    Arguments:   color       - Optional character string indicating the color
  3472.                               setting from which to extract the bright
  3473.                               portion.  If omitted, the current color setting
  3474.                               returned by SETCOLOR() is used.
  3475.  
  3476.    Returns:     A character string indicating the bright color setting.  This
  3477.                 bright color setting is created by extracting the standard
  3478.                 part of the color setting and adding a '+' onto the
  3479.                 foreground part.
  3480.  
  3481.    Description: BRIGHT() returns the bright color attribute setting for
  3482.                 either the current color, or the optionally supplied color
  3483.                 parameter.  This is useful for switching around color
  3484.                 combinations without having to clutter up your code with all
  3485.                 that SUBSTR(SUBSTR(...  garbage.
  3486.  
  3487.    Notes:       If the standard color setting foreground is white, then
  3488.                 BRIGHT() makes the high intensity color Yellow (GR+) instead
  3489.                 of bright white.  This was done out of preference and remains
  3490.                 for compatibility with RLIB version 2.0.
  3491.  
  3492.    Example:     *-- save incoming color, then get bright portion
  3493.                 save_color = SETCOLOR(BRIGHT())
  3494.                 CENTER(10,'*** TRY AGAIN ***')
  3495.                 SETCOLOR(save_color)
  3496.  
  3497.    Source:      RL_BRIGH.PRG
  3498.  
  3499.    See also:    GETPARM()
  3500.  
  3501.  
  3502.  
  3503.  
  3504.  
  3505.  
  3506.  
  3507.  
  3508.  
  3509.  
  3510.  
  3511.  
  3512.  
  3513.  
  3514.  
  3515.  
  3516.  
  3517.  
  3518.  
  3519.  
  3520.  
  3521.    RLIB Function Reference                                                 54
  3522.  
  3523.  
  3524.    Function:    BUZZ()
  3525.  
  3526.    Purpose:     Generate a buzzing sound for warnings or errors.
  3527.  
  3528.    Syntax:      BUZZ( [ count ] )
  3529.  
  3530.    Arguments:   count       - Optional numeric variable specifying the number
  3531.                               of times to make a BUZZ sound.  If no parameter
  3532.                               is specified, one BUZZ will be sounded.
  3533.  
  3534.    Returns:     A numeric zero. 
  3535.  
  3536.    Description: Whenever you want to make the PC speaker emit a short "BUZZ"
  3537.                 sound, such as when the user encounters an error condition,
  3538.                 the Clipper function to do this is TONE(frequency,duration). 
  3539.                 For a Buzz sound, the frequency would be 100Khz and the
  3540.                 duration should be around 6/18ths of a second.  Instead of
  3541.                 having to remember the command TONE(100,6) as being the
  3542.                 command to make a BUZZ sound, it is easier to simply use a
  3543.                 function named BLIP(), BUZZ(), or BEEP().
  3544.  
  3545.    Notes:       Nothing weird.
  3546.  
  3547.    Example:     *-- user does something wrong
  3548.                 BUZZ()
  3549.  
  3550.                 *-- user does something really wrong!
  3551.                 BUZZ(3)
  3552.  
  3553.    Source:      RL_BUZZ.PRG
  3554.  
  3555.    See also:    BEEP(), BLIP()
  3556.  
  3557.  
  3558.  
  3559.  
  3560.  
  3561.  
  3562.  
  3563.  
  3564.  
  3565.  
  3566.  
  3567.  
  3568.  
  3569.  
  3570.  
  3571.  
  3572.  
  3573.  
  3574.  
  3575.  
  3576.  
  3577.  
  3578.  
  3579.  
  3580.    RLIB Function Reference                                                 55
  3581.  
  3582.  
  3583.    Function:    CALENDAR()
  3584.  
  3585.    Purpose:     Pop up a configurable calendar on the screen
  3586.  
  3587.    Syntax:      CALENDAR( [ date [, colors  [, row [, column ] ] ] ] )
  3588.  
  3589.    Arguments:   date        - Optional date onto which to position the
  3590.                               cursor.
  3591.  
  3592.                 colors      - Optional array of character strings specifying
  3593.                               the color settings to use.  The colors used for
  3594.                               the different parts of the on screen calendar
  3595.                               are specified as follows: 
  3596.  
  3597.                               color[1] -  Calendar box and headers
  3598.                               color[2] -  Current day marker, (the cursor)
  3599.                               color[3] -  Day numbers inside the calendar
  3600.  
  3601.                 row         - Optional numeric top row of the calendar. 
  3602.                               Valid rows are from row 0 to row 10.  If not
  3603.                               specified or an invalid row value is given, the
  3604.                               default row is 1.
  3605.  
  3606.                 column      - Optional numeric left column of the calendar. 
  3607.                               Valid columns are from column 0 to column 56. 
  3608.                               If not specified or an invalid column value is
  3609.                               given, the default column is 56.
  3610.  
  3611.    Returns:     The date selected by pressing ENTER, or an EMPTY date if
  3612.                 Escape was pressed.
  3613.  
  3614.    Description: Function to provide a pop up calendar from which to select a
  3615.                 date.  Typical uses are to provide pop-up help for entering
  3616.                 dates in date fields.  The example below shows how this can
  3617.                 be done.  Other uses would include a global SET KEY procedure
  3618.                 to invoke a procedure that calls CALENDAR().  This provides
  3619.                 the end user with a handy reference calendar at any time. 
  3620.                 The calendar display is 15 rows tall and 24 columns wide, and
  3621.                 appears as: 
  3622.  
  3623.  
  3624.  
  3625.  
  3626.  
  3627.  
  3628.  
  3629.  
  3630.  
  3631.  
  3632.  
  3633.  
  3634.  
  3635.  
  3636.  
  3637.  
  3638.  
  3639.    RLIB Function Reference                                                 56
  3640.  
  3641.  
  3642.                             ╒══════════════════════╕
  3643.                             │      November  1990  │
  3644.                             ├──────────────────────┤
  3645.                             │  S  M  T  W  T  F  S │
  3646.                             │              1  2  3 │
  3647.                             │  4  5  6  7  8  9 10 │
  3648.                             │ 11 12 13 14 15 16 17 │
  3649.                             │ 18 19 20 21 22 23 24 │
  3650.                             │ 25 26 27 28 29 30    │
  3651.                             │                      │
  3652.                             ├──────────────────────┤
  3653.                             │  Day   Month   Year  │
  3654.                             │  < >   PgUp    ^PgUp │
  3655.                             │  v ^   PgDn    ^PgDn │
  3656.                             ╘══════════════════════╛
  3657.                                 ^
  3658.                                 │
  3659.                                 └── The unprintable left, right, up, and down
  3660.                                     arrow key characters appear here on the
  3661.                                     screen.
  3662.  
  3663.                 CALENDAR() is fairly perpetual inasmuch as Clipper's date
  3664.                 routines are.  The screen calendar can be moved and
  3665.                 CALENDAR() will remember the last screen location the next
  3666.                 time it is invoked (during an application session).  The
  3667.                 default location of the calendar is in the upper right hand
  3668.                 corner of the screen @ 1,56.
  3669.  
  3670.    Notes:       CALENDAR() will not handle dates beyond 2999.  If the color
  3671.                 string is not provided, the current color setting will be
  3672.                 used to determine the Standard and Enhanced colors, and
  3673.                 BRIGHT() will be used to create the color used for the
  3674.                 calendar numbers inside the box.
  3675.  
  3676.                 If you provide row,column parameters, CALENDAR() will
  3677.                 position to that location regardless of where the user may
  3678.                 have moved it with the control-arrow keys.
  3679.  
  3680.                 CALENDAR() handles the following keys as follows: 
  3681.  
  3682.                 Date positioning keys:
  3683.                 ----------------------------------
  3684.                 Up          - Back one week
  3685.                 Down        - Forward one week
  3686.                 Left        - Back one day
  3687.                 Right       - Forward one day
  3688.                 PgUp        - Back one month
  3689.                 PgDn        - Forward one month
  3690.                 Ctrl-PgUp   - Back one year
  3691.                 Ctrl-PgDn   - Forward one year 
  3692.  
  3693.  
  3694.  
  3695.  
  3696.  
  3697.  
  3698.    RLIB Function Reference                                                 57
  3699.  
  3700.  
  3701.                 Calendar screen placement keys
  3702.                 ----------------------------------
  3703.                 Ctrl-Up     - Move up one row
  3704.                 Ctrl-Down   - Move down one row
  3705.                 Ctrl-Left   - Move left one column
  3706.                 Ctrl-Right  - Move right one column
  3707.  
  3708.                 The <colors> argument may optionally be a SETCOLOR() style
  3709.                 color string where the 1st, 2nd, and 3rd colors correspond to
  3710.                 the Standard, Enhanced and Unselected color positions
  3711.                 respectively.  This permits an in-line call to CALENDAR() to
  3712.                 take the form CALENDAR(DATE(),"R/W,W/R,,R+/W") which can
  3713.                 simplify having to declare an array just to pass color
  3714.                 settings.
  3715.  
  3716.    Example:     *-- set key procedure to provide F1 pop-up date help in READs
  3717.                 PROCEDURE MyHelp
  3718.                 PARAMETERS callproc, linenum, readvar
  3719.                 PRIVATE temp
  3720.                 SET KEY 28 TO                 && disable help while in help
  3721.                 IF TYPE(readvar) = "D"        && if variable is a date type
  3722.                    temp = CALENDAR(&readvar)  && pop up the calendar
  3723.                    IF .NOT.  EMPTY(temp)         && if a date was selected
  3724.                       &readvar = temp         &&  assign to the readvar
  3725.                    ENDIF
  3726.                 ENDIF
  3727.                 SET KEY 28 TO MyHelp          && turn help back on
  3728.                 RETURN
  3729.  
  3730.    Source:      RL_CALEN.PRG
  3731.  
  3732.    See also:    STR2DATE()
  3733.  
  3734.  
  3735.  
  3736.  
  3737.  
  3738.  
  3739.  
  3740.  
  3741.  
  3742.  
  3743.  
  3744.  
  3745.  
  3746.  
  3747.  
  3748.  
  3749.  
  3750.  
  3751.  
  3752.  
  3753.  
  3754.  
  3755.  
  3756.  
  3757.    RLIB Function Reference                                                 58
  3758.  
  3759.  
  3760.    Function:    CATF()
  3761.  
  3762.    Purpose:     Copy array values to database fields (Copy Array To Fields)
  3763.  
  3764.    Syntax:      CATF( array [, memcopies [, first [, last ]]] )
  3765.  
  3766.    Arguments:   array       - Array of values to copy into database fields.
  3767.  
  3768.                 memcopies   - Optional logical flag to copy array values to
  3769.                               existing public memory variables with the same
  3770.                               names as database fields.
  3771.  
  3772.                 first       - Optional numeric value indicating the first
  3773.                               field in the database to be copied.  If not
  3774.                               specified the default is field #1.
  3775.  
  3776.                 last        - Optional numeric value indicating the last
  3777.                               field in the database to be copied.  If not
  3778.                               specified the default is FCOUNT().
  3779.  
  3780.    Returns:     True if all elements copied successfully.
  3781.  
  3782.    Description: CATF() is a function to copy values of each array element in
  3783.                 the specified array to the corresponding ordinal field in the
  3784.                 current record of the currently selected database, optionally
  3785.                 specifying to copy these array values to memory variable
  3786.                 copies rather than to the actual database fields.
  3787.  
  3788.                 This function is useful for stacking database record data
  3789.                 into and out of arrays.  The companion function is CFTA() to
  3790.                 copy fields to arrays, and the MEMORIZE() - MREPLACE() -
  3791.                 FORGET() team of functions.  Typically a database's record
  3792.                 contents are placed in PUBLIC variables with MEMORIZE(),
  3793.                 edited, then saved back to the database with MREPLACE(), then
  3794.                 released with the FORGET() function.  CATF() and CFTA() let
  3795.                 you temporarily hold and stack these field values into arrays
  3796.                 which can be later retrieved, or copied (saved) into the
  3797.                 database, or another database with the same structure.  This
  3798.                 forms a nice set of functions for simply manipulating data
  3799.                 among numbers of databases that share the same structure.
  3800.  
  3801.    Notes:       Assumes that ARRAY has at least FCOUNT() elements and that
  3802.                 the array element positions match up with the database field
  3803.                 numbers and also that the data type in each array element
  3804.                 MATCHES the data type of the corresponding database record. 
  3805.                 This also assumes that if the database fields are being
  3806.                 REPLACEd that any necessary file or record locks are in
  3807.                 place.
  3808.  
  3809.                 The database whose structure defines the fields being
  3810.                 replaced MUST be currently selected since CATF() uses the
  3811.                 field definitions from the currently selected database for
  3812.                 its operations.
  3813.  
  3814.  
  3815.  
  3816.    RLIB Function Reference                                                 59
  3817.  
  3818.  
  3819.    Example:     *-- swap data between record #1 and record #2 in a database
  3820.                 DECLARE rec1[FCOUNT()], rec2[FCOUNT()]
  3821.  
  3822.                 GOTO 1               && record #1
  3823.                 CFTA(rec1)           && copy field values to rec1 array
  3824.                 GOTO 2               && record #2
  3825.                 CFTA(rec2)           && copy field values to rec2 array
  3826.                 CATF(rec1)           && shove in record #1's field values
  3827.                 GOTO 1               && back to record #1
  3828.                 CATF(rec2)           && copy rec2 array field values in
  3829.  
  3830.    Source:      RL_CATF.PRG
  3831.  
  3832.    See also:    CFTA(), FORGET(), MEMORIZE(), MREPLACE()
  3833.  
  3834.  
  3835.  
  3836.  
  3837.  
  3838.  
  3839.  
  3840.  
  3841.  
  3842.  
  3843.  
  3844.  
  3845.  
  3846.  
  3847.  
  3848.  
  3849.  
  3850.  
  3851.  
  3852.  
  3853.  
  3854.  
  3855.  
  3856.  
  3857.  
  3858.  
  3859.  
  3860.  
  3861.  
  3862.  
  3863.  
  3864.  
  3865.  
  3866.  
  3867.  
  3868.  
  3869.  
  3870.  
  3871.  
  3872.  
  3873.  
  3874.  
  3875.    RLIB Function Reference                                                 60
  3876.  
  3877.  
  3878.    Function:    CENTER()
  3879.  
  3880.    Purpose:     Center a string and/or get the center position.
  3881.  
  3882.    Syntax:      CENTER( [ row ,] string [, color ] )
  3883.  
  3884.    Arguments:   row         - Optional numeric value which, if passed, will
  3885.                               cause CENTER() to print <string> centered on
  3886.                               row number <row>.  Value checked to be between
  3887.                               0 and 24, or MAXROW() in the Clipper 5.0
  3888.                               version.
  3889.  
  3890.                 string      - Target character string used to determine
  3891.                               center position, and optionally, to print on
  3892.                               row number <row> if <row> is given as a
  3893.                               parameter.
  3894.  
  3895.                 color       - Optional character color string (in Clipper
  3896.                               format) used to display <string> on screen.
  3897.  
  3898.    Returns:     The column number to center <string> on an 80 column monitor. 
  3899.                 If <row> is specified, it displays <string> centered on
  3900.                 <row>.
  3901.  
  3902.    Description: Almost everyone has a function to center text on the screen. 
  3903.                 So why should RLIB have one also?  This does just what you
  3904.                 think; it takes the string provided, and returns the numeric
  3905.                 column position to center the text on an 80 column display. 
  3906.                 Only this center can also do the displaying, and can do that
  3907.                 job in the color you select.  All this helps cut down on the
  3908.                 amount of code.
  3909.  
  3910.    Notes:       The maximum string length supported, naturally, is 80 since
  3911.                 that is the maximum screen width.
  3912.  
  3913.    Example:     *-- this method requires two lines of code and a memvar
  3914.                 memvar = 'This is the string to center on row 23'
  3915.                 @ 23,CENTER(memvar) SAY memvar
  3916.  
  3917.                 *-- or without assigning string to memvar (very wordy)
  3918.                 @ 23,CENTER('This is the string to center on row 23') ;
  3919.                 SAY 'This is the string to center on row 23'
  3920.  
  3921.                 *-- the simpler way
  3922.                 CENTER(23,'This is the string to center on row 23')
  3923.  
  3924.                 *-- and if you want it in another color..  the old way
  3925.                 save_color = SETCOLOR("R/W")
  3926.                 @ 23,CENTER("Please wait...") SAY "Please wait..."
  3927.                 SETCOLOR(save_color)
  3928.  
  3929.                 *-- CENTER() cuts down the SLOCs (Source Lines Of Code)
  3930.                 CENTER( 23, "Please wait...", "R/W" )
  3931.  
  3932.  
  3933.  
  3934.    RLIB Function Reference                                                 61
  3935.  
  3936.  
  3937.    Source:      RL_CENTE.PRG
  3938.  
  3939.    See also:    MIDDLE()
  3940.  
  3941.  
  3942.  
  3943.  
  3944.  
  3945.  
  3946.  
  3947.  
  3948.  
  3949.  
  3950.  
  3951.  
  3952.  
  3953.  
  3954.  
  3955.  
  3956.  
  3957.  
  3958.  
  3959.  
  3960.  
  3961.  
  3962.  
  3963.  
  3964.  
  3965.  
  3966.  
  3967.  
  3968.  
  3969.  
  3970.  
  3971.  
  3972.  
  3973.  
  3974.  
  3975.  
  3976.  
  3977.  
  3978.  
  3979.  
  3980.  
  3981.  
  3982.  
  3983.  
  3984.  
  3985.  
  3986.  
  3987.  
  3988.  
  3989.  
  3990.  
  3991.  
  3992.  
  3993.    RLIB Function Reference                                                 62
  3994.  
  3995.  
  3996.    Function:    CFTA()
  3997.  
  3998.    Purpose:     Copy database field values to an array (Copy Fields To Array)
  3999.  
  4000.    Syntax:      CFTA( array [, memcopies [, first [, last ]]] )
  4001.  
  4002.    Arguments:   array       - Existing array to receive field values from the
  4003.                               database fields.
  4004.  
  4005.                 memcopies   - Optional logical flag to fill the array values
  4006.                               from existing public memory variables with the
  4007.                               same names as database fields.
  4008.  
  4009.                 first       - Optional numeric value indicating the first
  4010.                               field in the database to copy.  If not
  4011.                               specified the default is field #1.
  4012.  
  4013.                 last        - Optional numeric value indicating the last
  4014.                               field in the database to copy.  If not
  4015.                               specified the default is FCOUNT().
  4016.  
  4017.    Returns:     True if all field values copied successfully.
  4018.  
  4019.    Description: Function to copy values of each field in the current record
  4020.                 of the currently selected database into the array specified,
  4021.                 optionally indicating to copy these values from existing
  4022.                 public memory variables with the same names as the database
  4023.                 fields.
  4024.  
  4025.                 This function is useful for stacking database record data
  4026.                 into and out of arrays.  The companion function is CATF() to
  4027.                 copy array values to fields, and the
  4028.                 MEMORIZE()-MREPLACE()-FORGET() team of functions.  Typically
  4029.                 a database's record contents are placed in PUBLIC variables
  4030.                 with MEMORIZE(), edited, then saved back to the database with
  4031.                 MREPLACE(), then released with the FORGET() function.  CATF()
  4032.                 and CFTA() let you temporarily hold and stack these field
  4033.                 values into arrays which can be later retrieved, or copied
  4034.                 (saved) into the database, or another database with the same
  4035.                 structure.  This forms a nice set of functions for simply
  4036.                 manipulating data among numbers of databases that share the
  4037.                 same structure.
  4038.  
  4039.    Notes:       Assumes that ARRAY has at least FCOUNT() elements.
  4040.  
  4041.                 The database whose structure defines the fields being copied
  4042.                 MUST be currently selected since CFTA() uses the field
  4043.                 definitions from the currently selected database for its
  4044.                 operations.
  4045.  
  4046.    Example:     *-- swap data between record #1 and record #2 in a database
  4047.                 DECLARE rec1[FCOUNT()], rec2[FCOUNT()]
  4048.  
  4049.                 GOTO 1               && record #1
  4050.  
  4051.  
  4052.    RLIB Function Reference                                                 63
  4053.  
  4054.  
  4055.                 CFTA(rec1)           && copy field values to rec1 array
  4056.                 GOTO 2               && record #2
  4057.                 CFTA(rec2)           && copy field values to rec2 array
  4058.                 CATF(rec1)           && shove in record #1's field values
  4059.                 GOTO 1               && back to record #1
  4060.                 CATF(rec2)           && copy rec2 array field values in
  4061.  
  4062.    Source:      RL_CFTA.PRG
  4063.  
  4064.    See also:    CATF(), FORGET(), MEMORIZE(), MREPLACE()
  4065.  
  4066.  
  4067.  
  4068.  
  4069.  
  4070.  
  4071.  
  4072.  
  4073.  
  4074.  
  4075.  
  4076.  
  4077.  
  4078.  
  4079.  
  4080.  
  4081.  
  4082.  
  4083.  
  4084.  
  4085.  
  4086.  
  4087.  
  4088.  
  4089.  
  4090.  
  4091.  
  4092.  
  4093.  
  4094.  
  4095.  
  4096.  
  4097.  
  4098.  
  4099.  
  4100.  
  4101.  
  4102.  
  4103.  
  4104.  
  4105.  
  4106.  
  4107.  
  4108.  
  4109.  
  4110.  
  4111.    RLIB Function Reference                                                 64
  4112.  
  4113.  
  4114.    Function:    CHANGED()
  4115.  
  4116.    Purpose:     Test if memory copies of database fields have been changed.
  4117.  
  4118.    Syntax:      CHANGED()
  4119.  
  4120.    Arguments:   None
  4121.  
  4122.    Returns:     True if any changes made to field variables since the last
  4123.                 REPLACE, MREPLACE(), or MEMORIZE().
  4124.  
  4125.    Description: CHANGED() is a database function designed to serve as a
  4126.                 replacement for the Clipper UPDATED() function when used in
  4127.                 conjunction with the MEMORIZE() function.  It may also be
  4128.                 used to compare the contents of all fields in a record to
  4129.                 previously MEMORIZED() copies to determine if changes have
  4130.                 been made to the record since it was MEMORIZED().  CHANGED()
  4131.                 tests to see if memory field variables have been changed from
  4132.                 the associated field values after an edit.  This works better
  4133.                 than Clipper's UPDATED() function because once you test for
  4134.                 UPDATED(), the flag is cleared.  So if you go back and READ
  4135.                 the data again, in a loop for instance, but do NOT change
  4136.                 anything this second time around, UPDATED() will return .F.,
  4137.                 even though something was changed previously.  Ideally, when
  4138.                 testing for UPDATED() you want it to be .T. if any values
  4139.                 have changed since the last REPLACE.
  4140.  
  4141.    Notes:       CHANGED() is used in conjunction with the MEMORIZE(),
  4142.                 MREPLACE(), and FORGET() functions.  These functions
  4143.                 reference all of the fields in the current database and store
  4144.                 the field values to memory variables of the same name,
  4145.                 prefaced by M->.
  4146.  
  4147.    Example:     *-- this way will not trap an update on a re-read
  4148.                 DO WHILE .T.
  4149.                    @ 1,0 GET M->name                && get data
  4150.                    @ 2,0 GET M->city
  4151.                    @ 3,0 GET M->state
  4152.                    READ
  4153.                    *-- if changed this will be true, however after going back
  4154.                    *-- through the second time UPDATED() will only be true if
  4155.                    *-- another change was made.  Pressing Escape the second
  4156.                    *-- time will not be trapped as UPDATED() will be False.
  4157.                    IF UPDATED()
  4158.                       IF LASTKEY() = 27             && escape key
  4159.                          IF BOXASK("W/R", "Abort edit? (y/N) ") != "Y"
  4160.                             LOOP
  4161.                          ENDIF
  4162.                       ENDIF
  4163.                    ENDIF
  4164.                    EXIT
  4165.                 ENDDO
  4166.  
  4167.                 *-- the following way will work correctly!
  4168.  
  4169.  
  4170.    RLIB Function Reference                                                 65
  4171.  
  4172.  
  4173.                 *-- save all database field data to field variables
  4174.                 MEMORIZE()
  4175.                 DO WHILE .T.
  4176.                    *-- get data (remember to preface memvars with M->)
  4177.                    @ 1,0 GET M->name
  4178.                    @ 2,0 GET M->city
  4179.                    @ 3,0 GET M->state
  4180.                    READ
  4181.                    *-- CHANGED() will compare all M->memvars with the twin
  4182.                    *-- field name to see if any values are different, and
  4183.                    *-- will catch it no matter how many times thru the loop
  4184.                    IF CHANGED()
  4185.                       IF LASTKEY() = 27             && escape key
  4186.                          IF BOXASK("W/R", "Abort edit? (y/N) ") != "Y"
  4187.                             LOOP
  4188.                          ENDIF
  4189.                       ENDIF
  4190.                    ENDIF
  4191.                    EXIT
  4192.                 ENDDO
  4193.  
  4194.    Source:      RL_CHANG.PRG
  4195.  
  4196.    See also:    MEMORIZE(), MREPLACE(), FORGET()
  4197.  
  4198.  
  4199.  
  4200.  
  4201.  
  4202.  
  4203.  
  4204.  
  4205.  
  4206.  
  4207.  
  4208.  
  4209.  
  4210.  
  4211.  
  4212.  
  4213.  
  4214.  
  4215.  
  4216.  
  4217.  
  4218.  
  4219.  
  4220.  
  4221.  
  4222.  
  4223.  
  4224.  
  4225.  
  4226.  
  4227.  
  4228.  
  4229.    RLIB Function Reference                                                 66
  4230.  
  4231.  
  4232.    Function:    CHECKFILE()
  4233.  
  4234.    Purpose:     Verify valid filenames, optionally popping up a pick list.
  4235.  
  4236.    Syntax:      CHECKFILE( @filename [, filelist [, mustexist [, confirm ]]])
  4237.  
  4238.    Arguments:   @filename   - Character file name to check.  The file name
  4239.                               may be fully qualified or have no directory
  4240.                               path, in which case the current default
  4241.                               directory will be used for file searches.  This
  4242.                               parameter must be PASSED BY REFERENCE by
  4243.                               prefacing the variable name with the "@"
  4244.                               character as shown above.  Passing this
  4245.                               variable by reference lets CHECKFILE() change
  4246.                               the value to a new filename selected through
  4247.                               the pop-up directory option.
  4248.  
  4249.                 listfiles   - Optional logical value indicating whether or
  4250.                               not to pop-up a file listing window if
  4251.                               wildcards are entered.  The default value is
  4252.                               True (.T.) 
  4253.  
  4254.                 mustexist   - Optional logical value indicating whether or
  4255.                               not to verify that the filename entered exists. 
  4256.                               The default value is False (.F.) 
  4257.  
  4258.                 confirm     - Optional logical value indicating whether or
  4259.                               not to confirm a file overwrite if the file
  4260.                               exists.  The default value is True (.T.) 
  4261.  
  4262.    Returns:     True if a valid filename was entered and all optional flag
  4263.                 conditions are met.  If any of these conditions fail, or if
  4264.                 the user presses ESCAPE, false is returned.
  4265.  
  4266.    Description: CHECKFILE() is a high level file function usually used during
  4267.                 the VALID clause of an @...GET...READ, to test if the
  4268.                 filename entered is a valid DOS file name.  The optional
  4269.                 flags permit control over other features provided by
  4270.                 CHECKFILE() which may or may not be desired, depending upon
  4271.                 the application.
  4272.  
  4273.                 The default parameters make CHECKFILE() an ideal VALID clause
  4274.                 for entering target filenames for such things as reports. 
  4275.                 The defaults are: <mustexist> is False since the target file
  4276.                 must not exist in this situation, and <confirm> is True to
  4277.                 notify the user before overwriting a file.  The RLIB function
  4278.                 GETFILE() makes a call to CHECKFILE() in this way.
  4279.  
  4280.    Notes:       The <listfiles> parameter is True by default.  If the
  4281.                 filename that is to be checked contains wildcards (* or ?),
  4282.                 CHECKFILE() will pop-up a centered file directory window of
  4283.                 the directory specified in the filename.  If no directory
  4284.                 path was entered as part of the filename, the directory
  4285.                 listing will be of the current directory.  This feature can
  4286.  
  4287.  
  4288.    RLIB Function Reference                                                 67
  4289.  
  4290.  
  4291.                 be disabled by setting the <listfiles> parameter to False. 
  4292.                 If the <filename> parameter is blank and the <listfiles>
  4293.                 parameter is True (the default), a directory listing will
  4294.                 pop-up when ENTER is pressed.
  4295.  
  4296.                 The pop-up file listing is provided by the RLIB function
  4297.                 PICKFILE().  See the documentation on PICKFILE() for more
  4298.                 information.
  4299.  
  4300.                 If a filename is selected from the pop-up directory listing,
  4301.                 CHECKFILE() uses Clipper's pass-by-reference feature to
  4302.                 assign the selected file name to the variable referenced by
  4303.                 the @filename parameter.  In the case of the READ...VALID
  4304.                 example cited above, this has the effect of stuffing the
  4305.                 selected filename into the READ, but in a much more elegant
  4306.                 manner than KEYBOARDing characters.  However, since the "@"
  4307.                 pass-by-reference operator cannot be applied to array
  4308.                 elements, the filename argument to CHECKFILE() may not be an
  4309.                 array element.  Attempting to do so will result in a compile
  4310.                 time error - "@ error" in Summer '87 or "Illegal use of @
  4311.                 (pass by reference) operator" in 5.0.  The bottom line is
  4312.                 that, fortunately, the compiler won't let you do it.  For
  4313.                 this reason, only use memory variables as the data being
  4314.                 READ.
  4315.  
  4316.                 The <mustexist> parameter is False by default.  Its purpose
  4317.                 is to optionally force CHECKFILE() to verify that the
  4318.                 filename entered does in fact exist.  This is useful in
  4319.                 applications that request the user to enter a filename for a
  4320.                 function that requires an existing file.  An example would be
  4321.                 a function that uses MEMOWRITE(MEMOEDIT(MEMOREAD(filename)))
  4322.                 to implement a rudimentary editor.  The statement to query
  4323.                 the user for a file name must verify the file exists. 
  4324.                 CHECKFILE() can do all that with one VALID statement.
  4325.  
  4326.                 The <confirm> parameter is True by default.  Its purpose is
  4327.                 to optionally force CHECKFILE() to confirm that the user
  4328.                 wants to overwrite a file that already exists.  This is
  4329.                 useful in report applications where the user is queried to
  4330.                 enter a target print file name for disk output.
  4331.  
  4332.                 If an optional parameter is to be skipped a dummy parameter
  4333.                 must be supplied in its place.  Use a null ("") for a dummy
  4334.                 parameter.
  4335.  
  4336.                 If a condition is not met, CHECKFILE() will BLIP() or BUZZ()
  4337.                 (depending on the severity) and display a BOXASK() or
  4338.                 SAYINBOX() error message in color "W+/R" on color monitors or
  4339.                 "N/W" on monochrome monitors.
  4340.  
  4341.                 The part of CHECKFILE() that verifies valid DOS filenames
  4342.                 checks the filename for any of the invalid characters
  4343.                 ( "/[]*<>|+=;,?) using the ANYCHARSIN() function, and
  4344.                 displays an error message indicating the offending character
  4345.  
  4346.  
  4347.    RLIB Function Reference                                                 68
  4348.  
  4349.  
  4350.                 if one is encountered.
  4351.  
  4352.    Example:     mfile = SPACE(120)
  4353.                 @ 10, 0 SAY "Enter target file for report output:";
  4354.                 @ 10,37 GET mfile PICTURE "@!KS40" VALID CHECKFILE(@mfile)
  4355.                 READ
  4356.  
  4357.    Source:      RL_CHECK.PRG
  4358.  
  4359.    See also:    ANYCHARSIN(), GETFILE(), PICKFILE()
  4360.  
  4361.  
  4362.  
  4363.  
  4364.  
  4365.  
  4366.  
  4367.  
  4368.  
  4369.  
  4370.  
  4371.  
  4372.  
  4373.  
  4374.  
  4375.  
  4376.  
  4377.  
  4378.  
  4379.  
  4380.  
  4381.  
  4382.  
  4383.  
  4384.  
  4385.  
  4386.  
  4387.  
  4388.  
  4389.  
  4390.  
  4391.  
  4392.  
  4393.  
  4394.  
  4395.  
  4396.  
  4397.  
  4398.  
  4399.  
  4400.  
  4401.  
  4402.  
  4403.  
  4404.  
  4405.  
  4406.    RLIB Function Reference                                                 69
  4407.  
  4408.  
  4409.    Function:    CLOSEAREA()
  4410.  
  4411.    Purpose:     Close multiple database work areas with one command.
  4412.  
  4413.    Syntax:      CLOSEAREA( [ area [, area ...  ] ] )
  4414.  
  4415.    Arguments:   area        - Character or numeric work area to close.  If
  4416.                               <area> is character, it must be a valid alias
  4417.                               name of an open work area.  If <area> is a
  4418.                               number, it must be a valid select area number. 
  4419.                               If no arguments are given, the current work
  4420.                               area is closed.
  4421.  
  4422.    Returns:     True if the requested work areas have been closed.
  4423.  
  4424.    Description: CLOSEAREA() allows you to close up to nine database files at
  4425.                 one time with one line of code without having to leave the
  4426.                 currently selected work area.  This is useful when you have
  4427.                 several database files open and you want to close all but one
  4428.                 or two of them.
  4429.  
  4430.    Notes:       Select area numbers and work area Alias names may be
  4431.                 intermixed as arguments.  Up to nine areas may be specified. 
  4432.                 If no argument is given, this will be the same as issuing the
  4433.                 USE command, closing the current work area.
  4434.  
  4435.                 CLOSEAREA() steps through the work areas specified and issues
  4436.                 a USE command to close the database.  After all is finished,
  4437.                 control is returned to the selected work area at entry.  A
  4438.                 return value of .F. should only occur if an invalid argument
  4439.                 is passed (i.e.  a Date, Memo, or Logical type parameter) or
  4440.                 if you specify an alias name that does not exist.  Normally
  4441.                 an invalid alias name will trigger a TYPE MISMATCH runtime
  4442.                 error, so CLOSEAREA() tests any alias names for their proper
  4443.                 existence.
  4444.  
  4445.    Example:     If you had seven databases open and wanted to close all but
  4446.                 the databases in work areas 1 and 3 (aliases SALES and
  4447.                 CUSTOMERS), one of the ways to accomplish this task would be
  4448.                 with the following code:
  4449.  
  4450.                 SELECT 1
  4451.                 marker1 = RECNO()
  4452.                 SELECT 3
  4453.                 marker3 = RECNO()
  4454.                 CLOSE DATABASES
  4455.                 SELECT 1
  4456.                 USE Sales INDEX Sales ALIAS Sales
  4457.                 GOTO marker1
  4458.                 SELECT 3
  4459.                 USE Cust INDEX Cust ALIAS Customers
  4460.                 GOTO marker3
  4461.  
  4462.  
  4463.  
  4464.  
  4465.    RLIB Function Reference                                                 70
  4466.  
  4467.  
  4468.                 *-- Another way to do this would be as follows:
  4469.  
  4470.                 SELECT 2             && Invoices
  4471.                 USE
  4472.                 SELECT 4             && Payments
  4473.                 USE
  4474.                 SELECT 5             && Payables
  4475.                 USE
  4476.                 SELECT 6             && Inventory
  4477.                 USE
  4478.                 SELECT 7             && Ledger
  4479.                 USE
  4480.  
  4481.                 *-- With CLOSEAREA(), the following is a LOT easier and
  4482.                 *-- simpler!!!
  4483.  
  4484.                 CLOSEAREA(2, 4, 5, 6, 7)
  4485.  
  4486.                 *-- or, even more readable is:
  4487.  
  4488.                 CLOSEAREA("Inovices", "Payments", "Payables", 6, "Ledger")
  4489.  
  4490.                 *-- This example shows how you can mix numeric and character
  4491.                 *-- arguments.
  4492.  
  4493.    Source:      RL_CLOSE.PRG
  4494.  
  4495.    See also:    OPENED()
  4496.  
  4497.  
  4498.  
  4499.  
  4500.  
  4501.  
  4502.  
  4503.  
  4504.  
  4505.  
  4506.  
  4507.  
  4508.  
  4509.  
  4510.  
  4511.  
  4512.  
  4513.  
  4514.  
  4515.  
  4516.  
  4517.  
  4518.  
  4519.  
  4520.  
  4521.  
  4522.  
  4523.  
  4524.    RLIB Function Reference                                                 71
  4525.  
  4526.  
  4527.    Function:    DBFCREATE()
  4528.  
  4529.    Purpose:     Dynamically create a database from a structure array.
  4530.  
  4531.    Syntax:      DBFCREATE( filename, structure [, appendfile ] )
  4532.  
  4533.    Arguments:   filename    - Character filename to create.  This must be a
  4534.                               valid DOS filename and may be fully qualified
  4535.                               (i.e.  have a full path specification).  If no
  4536.                               path specification is provided as part of the
  4537.                               filename, the file is created in the current
  4538.                               default directory.
  4539.  
  4540.                 structure   - An array containing the structure definition
  4541.                               for the .DBF file to be created.  This is an
  4542.                               array of character strings with each element
  4543.                               defining the structure of each field.  See the
  4544.                               tables below for examples.
  4545.  
  4546.                 appendfile  - Optional character filename of the .DBF format
  4547.                               file to append into the newly DBFCREATED file. 
  4548.                               This filename may be fully qualified and, if
  4549.                               not, the file must exist in the current default
  4550.                               directory.
  4551.  
  4552.    Returns:     True if the file was successfully created, false otherwise.
  4553.  
  4554.    Description: DBFCREATE() is a database function that creates a database
  4555.                 file from a structure array.  If an append file is specified,
  4556.                 it is appended into the newly created database file.  The
  4557.                 format of the character structure array is as follows: 
  4558.  
  4559.                 ELEMENT     FIELD NAME TYPE  LENGTH   DECIMALS
  4560.                 ----------  ---------- ----  ------   --------
  4561.                 array[1] = "NAME         C     30         " 
  4562.                 array[2] = "BIRTHDATE    D      8         " 
  4563.                 array[3] = "AGE          N      2        0" 
  4564.                 array[4] = "MALE         L      1         " 
  4565.                 array[5] = "NOTES        M     10         " 
  4566.  
  4567.                 This structure is not rigid.  The number of spaces between
  4568.                 the field name, field type, length and decimals may vary. 
  4569.                 The only rules are: space for field names must be at least 10
  4570.                 spaces; field type - 1 space, field length - 4 spaces, and 4
  4571.                 spaces for field decimals.  If the field type is character,
  4572.                 no field decimal need be specified.
  4573.  
  4574.    Notes:       Although the Clipper manual does not state that the CREATE,
  4575.                 CREATE FROM, or APPEND FROM commands require the target file
  4576.                 to be FLOCK()ed or USEd EXCLUSIVEly, in a Network
  4577.                 environment, for safety sake, and for data integrity sake,
  4578.                 you may wish to SET EXCLUSIVE ON before calling this
  4579.                 function.  Although you may not experience any problems by
  4580.                 not doing so, common data design sense should dictate
  4581.  
  4582.  
  4583.    RLIB Function Reference                                                 72
  4584.  
  4585.  
  4586.                 otherwise.
  4587.  
  4588.    Example:     *-- create a database named TEST.DBF, and append existing
  4589.                 *-- old data in from TEST.BAK
  4590.                 DECLARE struc[5]
  4591.                 struc[1] = "NAME         C     20    0"
  4592.                 struc[2] = "ADDRESS      C     30    0"
  4593.                 struc[3] = "CITY         C     20    0"
  4594.                 struc[4] = "STATE        C      2    0"
  4595.                 struc[5] = "ZIP          C      5    0"
  4596.                 DBFCREATE( "TEST.DBF", struc, "TEST.BAK" )
  4597.  
  4598.    Source:      RL_DBFCR.PRG
  4599.  
  4600.    See also:    CLOSEAREA(), OPENED()
  4601.  
  4602.  
  4603.  
  4604.  
  4605.  
  4606.  
  4607.  
  4608.  
  4609.  
  4610.  
  4611.  
  4612.  
  4613.  
  4614.  
  4615.  
  4616.  
  4617.  
  4618.  
  4619.  
  4620.  
  4621.  
  4622.  
  4623.  
  4624.  
  4625.  
  4626.  
  4627.  
  4628.  
  4629.  
  4630.  
  4631.  
  4632.  
  4633.  
  4634.  
  4635.  
  4636.  
  4637.  
  4638.  
  4639.  
  4640.  
  4641.  
  4642.    RLIB Function Reference                                                 73
  4643.  
  4644.  
  4645.    Function:    DEC2HEX()
  4646.  
  4647.    Purpose:     Convert decimal numeric value to a hexadecimal string.
  4648.  
  4649.    Syntax:      DEC2HEX( dec_val )
  4650.  
  4651.    Arguments:   dec_val     - The decimal numeric value to convert to a
  4652.                               hexadecimal character string.
  4653.  
  4654.    Returns:     The hexadecimal equivalent of <dec_val> as a character
  4655.                 string.
  4656.  
  4657.    Description: This function converts numeric decimal values into their
  4658.                 hexadecimal equivalent.  There are many libraries that 
  4659.                 implement this feature but it's nice to know you don't need
  4660.                 assembly language experience to accomplish this task! 
  4661.  
  4662.    Notes:       Only converts positive numbers.
  4663.  
  4664.    Example:     dec_num = 15
  4665.                 hex_str = DEC2HEX(dec_num)
  4666.                 ? hex_str                     && result = "F"
  4667.  
  4668.                 ? DEC2HEX(11281950)           && returns "AC261E"
  4669.  
  4670.    Source:      RL_DEC2H.PRG
  4671.  
  4672.    See also:    BIN2DEC(), HEX2DEC()
  4673.  
  4674.  
  4675.  
  4676.  
  4677.  
  4678.  
  4679.  
  4680.  
  4681.  
  4682.  
  4683.  
  4684.  
  4685.  
  4686.  
  4687.  
  4688.  
  4689.  
  4690.  
  4691.  
  4692.  
  4693.  
  4694.  
  4695.  
  4696.  
  4697.  
  4698.  
  4699.  
  4700.  
  4701.    RLIB Function Reference                                                 74
  4702.  
  4703.  
  4704.    Function:    DECRYPTED()
  4705.  
  4706.    Purpose:     Decrypt a character string encrypted with ENCRYPTED()
  4707.  
  4708.    Syntax:      DECRYPTED( string )
  4709.  
  4710.    Arguments:   string      - The character encrypted with ENCRYPTED() to be
  4711.                               decrypted.
  4712.  
  4713.    Returns:     An un-encrypted version of <string> of identical length.
  4714.  
  4715.    Description: The is the companion to the ENCRYPTED() function.  Strings
  4716.                 encrypted with the ENCRYPTED() function must be decrypted
  4717.                 with this function.
  4718.  
  4719.    Notes:       Strings decrypted with this function must have been encrypted
  4720.                 with the companion ENCRYPTED() function.
  4721.  
  4722.    Example:     *-- check a password stored in encrypted format
  4723.                 @ 5,0 SAY "Enter your password:"
  4724.  
  4725.                 *-- allow only 40 characters, upper case, and echo dots
  4726.                 password = KEYINPUT(40, .T., .F.)        && see KEYINPUT()
  4727.  
  4728.                 USE system.dbf
  4729.                 IF .NOT. password == DECRYPTED(pword)
  4730.                    *-- assumes password stored on encrypted format.
  4731.                    SAYINBOX( "W/R", "*** ACCESS DENIED! ***", 6 )
  4732.                    USE
  4733.                    RETURN
  4734.                 ENDIF
  4735.  
  4736.    Source:      RL_DECRY.PRG
  4737.  
  4738.    See also:    ENCRYPTED(), KEYINPUT()
  4739.  
  4740.  
  4741.  
  4742.  
  4743.  
  4744.  
  4745.  
  4746.  
  4747.  
  4748.  
  4749.  
  4750.  
  4751.  
  4752.  
  4753.  
  4754.  
  4755.  
  4756.  
  4757.  
  4758.  
  4759.  
  4760.    RLIB Function Reference                                                 75
  4761.  
  4762.  
  4763.    Function:    DIVIDE()
  4764.  
  4765.    Purpose:     Divide numbers with built in divide by zero protection.
  4766.  
  4767.    Syntax:      DIVIDE( dividend, divisor )
  4768.  
  4769.    Arguments:   dividend    - Number to be divided 
  4770.  
  4771.                 divisor     - Number to divide it by.
  4772.  
  4773.    Returns:     <dividend> / <divisor> with divide by zero protection.
  4774.  
  4775.    Description: This is a simple function but proves to be invaluable when
  4776.                 doing division math.  Invariably in reports you always end up
  4777.                 not trapping some circumstance where a number may be divided
  4778.                 by zero and cause a runtime error.  Very bad!  With
  4779.                 consistent use of this UDF in place of simple division, you
  4780.                 can rest easy.
  4781.  
  4782.    Notes:       If parameters are omitted or are non-numeric, zero is
  4783.                 returned and RLIBERROR() set.
  4784.  
  4785.    Example:     ? DIVIDE(10,2)             && result = 5
  4786.  
  4787.    Source:      RL_DIVID.PRG
  4788.  
  4789.    See also:    BIN2DEC(), DEC2HEX(), HEX2DEC()
  4790.  
  4791.  
  4792.  
  4793.  
  4794.  
  4795.  
  4796.  
  4797.  
  4798.  
  4799.  
  4800.  
  4801.  
  4802.  
  4803.  
  4804.  
  4805.  
  4806.  
  4807.  
  4808.  
  4809.  
  4810.  
  4811.  
  4812.  
  4813.  
  4814.  
  4815.  
  4816.  
  4817.  
  4818.  
  4819.    RLIB Function Reference                                                 76
  4820.  
  4821.  
  4822.    Function:    ENCRYPTED()
  4823.  
  4824.    Purpose:     Encrypt a character string
  4825.  
  4826.    Syntax:      ENCRYPTED( string )
  4827.  
  4828.    Arguments:   string      - The character to be encrypted.
  4829.  
  4830.    Returns:     An encrypted version of <string> of identical length.
  4831.  
  4832.    Description: The are several Encrypt/Decrypt functions available, most of
  4833.                 which are written in assembly or C.  This is a simple
  4834.                 encryption scheme done entirely in Clipper which is not only
  4835.                 functional, but the source is easily altered to provide
  4836.                 unique algorithms.  Data encrypted with this function is
  4837.                 decrypted with the companion DECRYPTED() function.
  4838.  
  4839.    Notes:       Strings encrypted with this function can only be decrypted
  4840.                 with the companion DECRYPTED() function!  However,
  4841.                 DECRYPTED() is not bulletproof, it uses a simple data
  4842.                 encryption scheme and is meant to conceal data from the
  4843.                 curious.
  4844.  
  4845.    Example:     *-- get a password, then store it in encrypted format
  4846.                 @ 5,0 SAY "Enter your password:"
  4847.  
  4848.                 *-- allow only 40 characters, upper case, and echo dots
  4849.                 password = KEYINPUT(40, .T., .F.)        && see KEYINPUT()
  4850.  
  4851.                 USE system.dbf
  4852.                 REPLACE pword WITH ENCRYPTED(password)
  4853.  
  4854.    Source:      RL_ENCRY.PRG
  4855.  
  4856.    See also:    DECRYPTED(), KEYINPUT()
  4857.  
  4858.  
  4859.  
  4860.  
  4861.  
  4862.  
  4863.  
  4864.  
  4865.  
  4866.  
  4867.  
  4868.  
  4869.  
  4870.  
  4871.  
  4872.  
  4873.  
  4874.  
  4875.  
  4876.  
  4877.  
  4878.    RLIB Function Reference                                                 77
  4879.  
  4880.  
  4881.    Function:    FEOF()
  4882.  
  4883.    Purpose:     Test for the End Of File status on a binary file.
  4884.  
  4885.    Syntax:      FEOF( handle )
  4886.  
  4887.    Arguments:   handle      - The numeric file handled returned by a previous
  4888.                               call to FOPEN() or FCREATE().  If omitted or a
  4889.                               non-numeric parameter is passed, FEOF() will
  4890.                               return True.
  4891.  
  4892.    Returns:     True if the current file pointer is at EOF, false otherwise.
  4893.  
  4894.    Description: FEOF() is a low level file function used to test if a binary
  4895.                 file opened with FOPEN() or FCREATE() is at the end of file. 
  4896.                 It is written in Clipper (as are all RLIB functions) which
  4897.                 further illustrates that you do not need assembler or C
  4898.                 experience to accomplish this task.
  4899.  
  4900.    Notes:       Assumes the file to be tested has already been opened with
  4901.                 the FOPEN() or FCREATE() function.  If the file is not open
  4902.                 (an invalid handle is supplied) FEOF will return True.
  4903.  
  4904.                 If the file handle is omitted or is non-numeric, FOEF() will
  4905.                 return True and set RLIBERROR().
  4906.  
  4907.    Example:     *-- read in CONFIG.SYS into a single field database file
  4908.                 DECLARE structure[1]
  4909.                 structure[1] = "LINE       C  80  0"      && define structure
  4910.  
  4911.                 IF .NOT. DBFCREATE("test.dbf",structure)  && create .DBF file
  4912.                    BUZZ()
  4913.                    SAYINBOX("W+/R", "Error creating TEST.DBF", 30)
  4914.                    RETURN
  4915.                 ENDIF
  4916.                 handle = FOPEN("c:\config.sys")           && open CONFIG.SYS
  4917.                 IF FERROR() != 0
  4918.                    ? "Error opening c:\config.sys"
  4919.                    RETURN
  4920.                 ENDIF
  4921.                 USE test                                  && open database
  4922.                 DO WHILE .NOT.  FEOF(handle)              && read in lines
  4923.                    APPEND BLANK
  4924.                    REPLACE line WITH FREADLINE(handle)
  4925.                 ENDDO
  4926.  
  4927.                 *-- now do whatever with config.sys lines
  4928.                 *-- perhaps look for the PATH, etc...
  4929.                 FCLOSE(handle)                            && close up shop
  4930.                 USE
  4931.  
  4932.    Source:      RL_FEOF.PRG
  4933.  
  4934.    See also:    FILEDATE(), FILESIZE(), FILETIME(), FREADLINE()
  4935.  
  4936.  
  4937.    RLIB Function Reference                                                 78
  4938.  
  4939.  
  4940.    Function:    FILEDATE()
  4941.  
  4942.    Purpose:     Retrieve the last update date for a given file from DOS.
  4943.  
  4944.    Syntax:      FILEDATE( filename )
  4945.  
  4946.    Arguments:   filename    - Character string or variable indicating the
  4947.                               name of the file for which to extract the date. 
  4948.                               This filename (filespec) must and may adhere to
  4949.                               any fully qualified filename as required by
  4950.                               ADIR().
  4951.  
  4952.    Returns:     Date from the file directory entry (last update date).
  4953.  
  4954.    Description: This function extracts the date from the given file directory
  4955.                 entry information.  It is useful for comparing the dates of
  4956.                 two files, or for using the file date for a variety of
  4957.                 purposes.  FILEDATE() may be used in conjunction with
  4958.                 FILETIME() to determine if an index file is current with the
  4959.                 associated .DBF file.  FILEDATE() simplifies all the ADIR()
  4960.                 and associated lines of code to get the file date.
  4961.  
  4962.    Notes:       If an invalid filename is given, or if the file does not
  4963.                 exist, FILEDATE() will return an empty date (  /  /  ). 
  4964.                 Beware that if the file being checked is currently open, the
  4965.                 date from the directory entry may not reflect updates until
  4966.                 the file is closed.
  4967.  
  4968.    Example:     *-- see if the date and time of the .DBF and .NTX files agree
  4969.                 ok = (FILEDATE("myfile.dbf") == FILEDATE("myfile.ntx") .AND.;
  4970.                       FILETIME("myfile.dbf") == FILETIME("myfile.ntx"))
  4971.                 USE myfile INDEX myfile
  4972.                 IF .NOT.  ok
  4973.                    pbox = SAYINBOX("Please wait, updating index")
  4974.                    REINDEX
  4975.                    GO TOP
  4976.                    POPBOX(pbox)
  4977.                 ENDIF
  4978.  
  4979.  
  4980.                 *-- a second example, prompt user for file backup request
  4981.                 lastback = FILEDATE("myfile.bak")
  4982.                 IF BOXASK("MYFILE.DBF was last backed up on"+DTOC(lastback),;
  4983.                           "Do you want to back it up now? (Y/N) ") = "Y"
  4984.                    ERASE myfile.bak
  4985.                    COPY FILE myfile.dbf TO myfile.bak
  4986.                 ENDIF
  4987.  
  4988.    Source:      RL_FILED.PRG
  4989.  
  4990.    See also:    FILESIZE(), FILETIME()
  4991.  
  4992.  
  4993.  
  4994.  
  4995.  
  4996.    RLIB Function Reference                                                 79
  4997.  
  4998.  
  4999.    Function:    FILES()
  5000.  
  5001.    Purpose:     Test for the existence of multiple files in one function.
  5002.  
  5003.    Syntax:      FILES( filename [, filename...filename ] )
  5004.  
  5005.    Arguments:   filename    - Character string or variable of the file to
  5006.                               test for existence.
  5007.  
  5008.    Returns:     True if all the specified files exist.
  5009.  
  5010.    Description: FILES() is a file function that tests for the existence of
  5011.                 multiple files.  It is useful for reducing a series of FILE()
  5012.                 functions .AND.ed together into a single function call.  If
  5013.                 you have to test for more than one file often, this really
  5014.                 cleans things up and makes code very readable.
  5015.  
  5016.    Notes:       FILES() will accept as many file name arguments as Clipper
  5017.                 will allow you to pass.  A practical limit of the number of
  5018.                 filenames which can be passed should be 10.  FILES() uses the
  5019.                 Clipper FILE() function to successively test for each file
  5020.                 specified.  If any test fails, FILES() returns False.  Since
  5021.                 the FILE() function is used, it follows Clippers current SET
  5022.                 DEFAULT setting.
  5023.  
  5024.                 If FILES() encounters a non-character argument, it will fail,
  5025.                 set RLIBERROR() and return False.
  5026.  
  5027.    Example:     *-- see if all needed index files exist
  5028.                 USE Sales
  5029.  
  5030.                 IF FILES( "Custno.ntx",   "Invoice.ntx",;
  5031.                           "Salesman.ntx", "Repair.ntx",;
  5032.                           "Saledate.ntx" )
  5033.                    SET INDEX TO Custno, Invoice, Salesman, Repair, Saledate
  5034.                 ELSE
  5035.                    *-- do indexing
  5036.                 ENDIF
  5037.  
  5038.                 *-- the old way to do it
  5039.                 IF FILE("Custno.ntx"  ) .AND.  FILE("Invoice.ntx") .AND.;
  5040.                    FILE("Salesman.ntx") .AND.  FILE("Repair.ntx" ) .AND.;
  5041.                    FILE("Saledate.ntx")
  5042.  
  5043.    Source:      RL_FILES.PRG
  5044.  
  5045.    See also:    FILEDATE(), FILESIZE(), FILETIME()
  5046.  
  5047.  
  5048.  
  5049.  
  5050.  
  5051.  
  5052.  
  5053.  
  5054.  
  5055.    RLIB Function Reference                                                 80
  5056.  
  5057.  
  5058.    Function:    FILESIZE()
  5059.  
  5060.    Purpose:     Retrieve the size of a file from DOS directory information.
  5061.  
  5062.    Syntax:      FILESIZE( filename )
  5063.  
  5064.    Arguments:   filename    - Character string or variable indicating the
  5065.                               name of the file for which to extract the size. 
  5066.                               This filename (filespec) must and may adhere to
  5067.                               any fully qualified filename as required by
  5068.                               ADIR().
  5069.  
  5070.    Returns:     Numeric size in bytes of <filename> from the DOS directory
  5071.                 entry.
  5072.  
  5073.    Description: This function extracts the size from the given file directory
  5074.                 entry information.  It is useful for comparing the sizes of
  5075.                 two files, or for using the file size for a variety of
  5076.                 purposes.
  5077.  
  5078.    Notes:       If an invalid filename is given, or if the file does not
  5079.                 exist, FILESIZE() will return zero.  Beware that if the file
  5080.                 being checked is currently open, the size from the directory
  5081.                 entry may not reflect updates until the file is closed.
  5082.  
  5083.                 Since FILESIZE() uses ADIR() (and presumably DOS directory's
  5084.                 function calls) the file does not have to be opened with
  5085.                 FOPEN() to get the size.  This can be useful if file handles
  5086.                 are in short supply.
  5087.  
  5088.    Example:     *-- verify enough disk space for a faster sort operation
  5089.                 IF DISKSPACE(0) > FILESIZE("myfile.dbf")
  5090.                    USE myfile INDEX myfile
  5091.                    COPY TO myfile.sor
  5092.                    USE
  5093.                    ERASE myfile.dbf
  5094.                    RENAME myfile.sor TO myfile.dbf
  5095.                 ELSE
  5096.                    BUZZ()
  5097.                    SAYINBOX( "R/W", "Insufficient disk space!", 30 )
  5098.                 ENDIF
  5099.  
  5100.    Source:      RL_FSIZE.PRG
  5101.  
  5102.    See also:    FILEDATE(), FILETIME()
  5103.  
  5104.  
  5105.  
  5106.  
  5107.  
  5108.  
  5109.  
  5110.  
  5111.  
  5112.  
  5113.  
  5114.    RLIB Function Reference                                                 81
  5115.  
  5116.  
  5117.    Function:    FILETIME()
  5118.  
  5119.    Purpose:     Retrieve the last update time for a given file.
  5120.  
  5121.    Syntax:      FILETIME( filename )
  5122.  
  5123.    Arguments:   filename    - Character string or variable indicating the
  5124.                               name of the file for which to extract the time. 
  5125.                               This filename (filespec) must and may adhere to
  5126.                               any fully qualified filename as required by
  5127.                               ADIR().
  5128.  
  5129.    Returns:     Character time string of <filename> from the DOS directory
  5130.                 entry.
  5131.  
  5132.    Description: This function extracts the time from the given file directory
  5133.                 entry information.  It is useful for comparing the times of
  5134.                 two files, or for using the file time for a variety of
  5135.                 purposes.  FILETIME() can be used in conjunction with
  5136.                 FILEDATE() to determine if an index file is current with the
  5137.                 associated .DBF file.  FILETIME() simplifies all the ADIR()
  5138.                 and associated lines of code to get the file time.
  5139.  
  5140.    Notes:       If an invalid filename is given, or if the file does not
  5141.                 exist, FILETIME() will return a null string ("").  Beware
  5142.                 that if the file being checked is currently open, the time
  5143.                 from the directory entry may not reflect updates until the
  5144.                 file is closed.
  5145.  
  5146.    Example:     *-- see if the date and time of the .DBF and .NTX files agree
  5147.                 ok = (FILETIME("myfile.dbf") == FILETIME("myfile.ntx") .AND.;
  5148.                       FILEDATE("myfile.dbf") == FILEDATE("myfile.ntx"))
  5149.                 USE myfile INDEX myfile
  5150.                 IF .NOT.  ok
  5151.                    pbox = SAYINBOX("Please wait, updating index")
  5152.                    REINDEX
  5153.                    GO TOP
  5154.                    POPBOX(pbox)
  5155.                 ENDIF
  5156.  
  5157.    Source:      RL_FILET.PRG
  5158.  
  5159.    See also:    FILEDATE(), FILESIZE()
  5160.  
  5161.  
  5162.  
  5163.  
  5164.  
  5165.  
  5166.  
  5167.  
  5168.  
  5169.  
  5170.  
  5171.  
  5172.  
  5173.    RLIB Function Reference                                                 82
  5174.  
  5175.  
  5176.    Function:    FORGET()
  5177.  
  5178.    Purpose:     Release field memory variables created with MEMORIZE().
  5179.  
  5180.    Syntax:      FORGET( [ firstfield [, lastfield ] ] )
  5181.  
  5182.    Arguments:   firstfield  - Optional numeric value indicating the first
  5183.                               field in the database whose PUBLIC M-> copy
  5184.                               variable is to be RELEASEd.  The default is
  5185.                               field number 1.
  5186.  
  5187.                 lastfield   - Optional numeric value indicating the last
  5188.                               field in the database whose PUBLIC M-> copy
  5189.                               variable is to be RELEASEd.  The default is the
  5190.                               last field, FCOUNT().
  5191.  
  5192.    Returns:     True (.T.) if all fields were successively released.
  5193.  
  5194.    Description: This function is designed to be used in conjunction with
  5195.                 CHANGED(), MEMORIZE(), and MREPLACE(); they are all a team. 
  5196.                 Put together, they simplify the tedious task of making memory
  5197.                 variable copies of each field in a database record (some
  5198.                 languages call them temporary field variables).  FORGET() is
  5199.                 used to release the PUBLIC variables created by MEMORIZE(),
  5200.                 when your editing and REPLACEing is finished.
  5201.  
  5202.    Notes:       Since variables created with MEMORIZE() are declared PUBLIC,
  5203.                 FORGET() releases them to reclaim memory and to avoid any
  5204.                 potential name conflicts.  Some programmers save field values
  5205.                 to memory variables with a common prefix (like m_), and when
  5206.                 they are finished with them do a RELEASE ALL LIKE m_*.  This
  5207.                 is fine if the variables are released in the same procedure
  5208.                 in which they were created.  However, it is more efficient to
  5209.                 do this storing in a sub-procedure, hence the need to make
  5210.                 these variables PUBLIC.  The problem is that in Clipper, you
  5211.                 cannot RELEASE ALL LIKE m_* if the m_* variables are PUBLIC
  5212.                 variables that were created in another procedure.  FORGET()
  5213.                 takes care of all this by explicitly naming each variable to
  5214.                 be RELEASEd, which is the only way you can release a PUBLIC
  5215.                 variable created in another procedure.
  5216.  
  5217.                 FORGET() uses the field definitions in the currently selected
  5218.                 database to create the PUBLIC variable names to release.  If
  5219.                 no database is open in the current select area, FORGET() will
  5220.                 return .F.  and set the appropriate RLIBERROR().
  5221.  
  5222.    Example:     *-- store empty field values for a new record
  5223.                 MEMORIZE(.T.)
  5224.  
  5225.                 *-- get the data
  5226.                 @ 1,0 SAY "Enter full name" GET M->name
  5227.                 @ 2,0 SAY "Enter birthdate" GET M->birthdate
  5228.                 @ 3,0 SAY "Enter age      " GET M->age  PICTURE "##"
  5229.                 *-- remember to always PICTURE numeric memory variables!
  5230.  
  5231.  
  5232.    RLIB Function Reference                                                 83
  5233.  
  5234.  
  5235.                 READ
  5236.  
  5237.                 *-- now add the new record and put in the data
  5238.                 IF NO_APPEND()
  5239.                    SAYINBOX( "R/W", "Append failure, record not saved!" )
  5240.                 ELSE
  5241.                    MREPLACE()
  5242.                 ENDIF
  5243.  
  5244.                 *-- now release the public variables!
  5245.                 FORGET()
  5246.  
  5247.    Source:      RL_FORGE.PRG
  5248.  
  5249.    See also:    CHANGED(), MEMORIZE(), MREPLACE()
  5250.  
  5251.  
  5252.  
  5253.  
  5254.  
  5255.  
  5256.  
  5257.  
  5258.  
  5259.  
  5260.  
  5261.  
  5262.  
  5263.  
  5264.  
  5265.  
  5266.  
  5267.  
  5268.  
  5269.  
  5270.  
  5271.  
  5272.  
  5273.  
  5274.  
  5275.  
  5276.  
  5277.  
  5278.  
  5279.  
  5280.  
  5281.  
  5282.  
  5283.  
  5284.  
  5285.  
  5286.  
  5287.  
  5288.  
  5289.  
  5290.  
  5291.    RLIB Function Reference                                                 84
  5292.  
  5293.  
  5294.    Function:    FPROMPT()
  5295.  
  5296.    Purpose:     Display color formatted and highlighted prompt strings.
  5297.  
  5298.    Syntax:      FPROMPT( [ prompt [, color [, hilite [, row [, col ;
  5299.                          [, comma ] ] ] ] ] ] )
  5300.  
  5301.    Arguments:   prompt      - The character string to format and print as the
  5302.                               prompt.  See the discussion below for the
  5303.                               format of <prompt>.
  5304.  
  5305.                 color       - Optional character string which specifies the
  5306.                               color to use to display the prompt text which
  5307.                               appears at and to the right of the equal sign. 
  5308.                               This color string must adhere to Clipper color
  5309.                               setting standards.  If omitted or a non-
  5310.                               character parameter is given, the default color
  5311.                               is the current SETCOLOR() setting.
  5312.  
  5313.                 hilite      - Optional character string which specifies the
  5314.                               color to use to display the highlighted portion
  5315.                               of the prompt.  This highlighted portion
  5316.                               appears to the left of the equal sign.  This
  5317.                               color string must adhere to Clipper color
  5318.                               setting standards.  If omitted or a non-
  5319.                               character parameter is given, the default is
  5320.                               the BRIGHT() version of the current color
  5321.                               SETCOLOR().
  5322.  
  5323.                 row         - Optional numeric value indicating the row on
  5324.                               which to display the formatted prompt.  If
  5325.                               omitted or a non-numeric value is passed, the
  5326.                               default row is row 24.  In the Clipper 5.0
  5327.                               version, the default row is MAXROW().
  5328.  
  5329.                 col         - Optional numeric value indicating the starting
  5330.                               column on which to display the formatted
  5331.                               prompt.  If omitted or a non-numeric value is
  5332.                               passed, the default column is column zero.
  5333.  
  5334.                 comma       - Optional single character which indicates the
  5335.                               character to recognize as the separator or
  5336.                               prompt token delimiter in the <prompt> string. 
  5337.                               If omitted or a non-character is provided, the
  5338.                               default separator character is the comma.
  5339.  
  5340.    Returns:     True if the <prompt> was displayed properly, false otherwise.
  5341.  
  5342.    Description: FPROMPT() is a screen function used to paint prompts where a
  5343.                 portion of the prompt is highlighted and another portion is
  5344.                 in a normal display color.  As an example, when FPROMPT() is
  5345.                 given the string "F1=Help,F10=Menu", FPROMPT() will say "F1"
  5346.                 in a bright color with the "=Help" portion in the standard
  5347.                 color.  FPROMPT()'s behavior is best understood through
  5348.  
  5349.  
  5350.    RLIB Function Reference                                                 85
  5351.  
  5352.  
  5353.                 examples.
  5354.  
  5355.    Notes:       The prompt string will be formatted to be centered on the row
  5356.                 specified with an even number of spaces separating the
  5357.                 individual elements, or tokens, in the prompt.  Each separate
  5358.                 individual prompt element in the string must be separated
  5359.                 with a single comma (or other character specified by the
  5360.                 <comma> parameter), therefore, individual prompt elements may
  5361.                 not contain embedded commas.  If you want an embedded comma
  5362.                 in a prompt element, specify and use another delimiter
  5363.                 character other than the comma.
  5364.  
  5365.                 If no parameters are given, or if the <prompt> parameter is
  5366.                 empty or non-character, FPROMPT() will clear the display line
  5367.                 from the column indicated to the end of the screen.  If no
  5368.                 column is specified, column zero is assumed.
  5369.  
  5370.  
  5371.                 Clipper 5.0 Only!
  5372.  
  5373.                 The 5.0 library version of FPROMPT() includes a companion
  5374.                 function named SETFPROMPT().  This function is an example of
  5375.                 the benefits of the static class of variables supported by
  5376.                 Clipper 5.0.  The SETFPROMPT() function is used to
  5377.                 pre-establish the values of the <color>, <hilite>, <row>,
  5378.                 <col>, and <comma> arguments so that they need not be
  5379.                 supplied in every call to FPROMPT().  This helps to reduce
  5380.                 "code wordiness".  Because this would have to be implemented
  5381.                 as a series of PUBLIC variables in the Summer '87 version,
  5382.                 this feature is only included in the 5.0 version of the RLIB
  5383.                 library.
  5384.  
  5385.                 The syntax for SETFPROMPT() is the same as for FPROMPT(),
  5386.                 just exclude the first parameter, <prompt>.
  5387.  
  5388.    Example:     *-- this will paint a prompt with the F1, F9, F10, and Esc
  5389.                 *-- portions displayed in Bright Cyan on Blue with the items
  5390.                 *-- =Help, =Mark, =Select, and =Quit displayed in Cyan on
  5391.                 *-- Blue.  Each option will be evenly spaced to center the
  5392.                 *-- entire prompt on row 24, similar to the following:
  5393.  
  5394.                 FPROMPT("F1=Help,F9=Mark,F10=Select,Esc=Quit","BG/B","BG+/B")
  5395.  
  5396.                 F1=Help         F9=Mark         F10=Select         Esc=Quit
  5397.  
  5398.  
  5399.    Source:      RL_FPROM.PRG
  5400.  
  5401.    See also:    CENTER(), MIDDLE(), RJUSTIFY()
  5402.  
  5403.  
  5404.  
  5405.  
  5406.  
  5407.  
  5408.  
  5409.    RLIB Function Reference                                                 86
  5410.  
  5411.  
  5412.    Function:    FREADLINE()
  5413.  
  5414.    Purpose:     Read a line from a text file opened with FOPEN() or FCREATE()
  5415.  
  5416.    Syntax:      FREADLINE( fhandle )
  5417.  
  5418.    Arguments:   fhandle     - The numeric file handled returned by a previous
  5419.                               call to FOPEN() or FCREATE().
  5420.  
  5421.    Returns:     The next sequential line read from the indicated file handle.
  5422.  
  5423.    Description: FREADLINE() is a low level file I/O function (written in
  5424.                 Clipper) to read a single carriage return/line feed delimited
  5425.                 line from a text file.
  5426.  
  5427.    Notes:       Assumes the file to be read has already been opened with the
  5428.                 FOPEN() or FCREATE() function.  If the file handle argument
  5429.                 is omitted or a non-numeric value is supplied, FREADLINE()
  5430.                 will return a null and set RLIBERROR().
  5431.  
  5432.                 FREADLINE() will read lines up to 512 characters long.  This
  5433.                 line width is sufficient for most text files.  If files with
  5434.                 lines longer than 512 characters are to be accessed,
  5435.                 FREADLINE() may be modified by increasing the value from 512
  5436.                 on the following lines:
  5437.  
  5438.                 rl_bufffer = SPACE(512)
  5439.                 rl_sizread = FREAD( p_handle, @rl_buffer, 512 )
  5440.  
  5441.                 Unlike some other FREADLINE functions, this one does not
  5442.                 return the carriage return/line feed pair (CR/LF) in the line
  5443.                 which is the desired behavior.  Who needs it anyway! 
  5444.  
  5445.    Example:     *-- read AUTOEXEC.BAT and look for a SET CLIPPER= statement
  5446.                 handle = FOPEN("c:\autoexec.bat")
  5447.                 DO WHILE .NOT.  FEOF(handle)
  5448.                    line = FREADLINE(handle)
  5449.                    IF "SET CLIPPER=" $ UPPER(line)
  5450.                       *-- do whatever...
  5451.                    ENDIF
  5452.                 ENDDO
  5453.                 FCLOSE(handle)          && remember to close the file!
  5454.  
  5455.    Source:      RL_FREAD.PRG
  5456.  
  5457.    See also:    FEOF()
  5458.  
  5459.  
  5460.  
  5461.  
  5462.  
  5463.  
  5464.  
  5465.  
  5466.  
  5467.  
  5468.    RLIB Function Reference                                                 87
  5469.  
  5470.  
  5471.    Function:    FRESTSCREEN()
  5472.  
  5473.    Purpose:     Restore screen from a disk file saved with FSAVESCREEN().
  5474.  
  5475.    Syntax:      FRESTSCREEN( filename )
  5476.  
  5477.    Arguments:   filename    - Character filename from which to restore the
  5478.                               screen.  This file must have been created with
  5479.                               the companion FSAVESCREEN() function.  If the
  5480.                               filename is not fully qualified, FRESTSCREEN()
  5481.                               will search the current default directory for
  5482.                               the given filename.
  5483.  
  5484.    Returns:     True if screen restored.  If a file I/O error occurs or if
  5485.                 the <filename> does not exist, FRESTSCREEN() will return
  5486.                 false.
  5487.  
  5488.    Description: FRESTSCREEN() is a screen function used to restore a screen
  5489.                 from a disk file created with the companion FSAVESCREEN()
  5490.                 function.  Saving many screens to memory variables can
  5491.                 quickly consume large amounts of free pool memory.  Each
  5492.                 screen consumes at least 4000 bytes of memory.  Saving
  5493.                 screens to disk files can limit this potential problem.
  5494.  
  5495.    Notes:       FRESTSCREEN() opens the disk file with the Clipper low level
  5496.                 file functions, reads the file contents, then restores the
  5497.                 screen.  If a file open or read failure occurs, FRESTSCREEN()
  5498.                 returns false.
  5499.  
  5500.                 FRESTSCREEN() makes no checks on the contents of the file
  5501.                 from which to restore a screen.  If the file was not saved
  5502.                 with FSAVESCREEN() (or another similar save screen to file
  5503.                 function) then results are guaranteed to be interesting.  For
  5504.                 instance, FRESTSCREEN("c:bigfile.dbf") is guaranteed to put
  5505.                 something strange looking on your screen.
  5506.  
  5507.                 If the file is not at least 4000 bytes in size, or 4000 bytes
  5508.                 are not read from the file, FRESTSCREEN() will fail and
  5509.                 return False.
  5510.  
  5511.                 Clipper 5.0
  5512.  
  5513.                 FRESTSCREEN() uses the values of MAXROW() and MAXCOL() to
  5514.                 determine the screen size, and hence the number of bytes to
  5515.                 read from <filename>.  To prevent strange behavior, neither
  5516.                 MAXROW() nor MAXCOL() must be changed with the SETMODE()
  5517.                 function between a FSAVESCREEN() and FRESTSCREEN() call.
  5518.  
  5519.    Example:     *-- save the current screen to file, and save some memory(0)
  5520.                 FSAVESCREEN("screen1.scr")
  5521.                 CLEAR
  5522.                 *-- do something
  5523.                 FRESTSCREEN("screen1.scr")
  5524.  
  5525.  
  5526.  
  5527.    RLIB Function Reference                                                 88
  5528.  
  5529.  
  5530.    Source:      RL_FREST.PRG
  5531.  
  5532.    See also:    FSAVESCREEN()
  5533.  
  5534.  
  5535.  
  5536.  
  5537.  
  5538.  
  5539.  
  5540.  
  5541.  
  5542.  
  5543.  
  5544.  
  5545.  
  5546.  
  5547.  
  5548.  
  5549.  
  5550.  
  5551.  
  5552.  
  5553.  
  5554.  
  5555.  
  5556.  
  5557.  
  5558.  
  5559.  
  5560.  
  5561.  
  5562.  
  5563.  
  5564.  
  5565.  
  5566.  
  5567.  
  5568.  
  5569.  
  5570.  
  5571.  
  5572.  
  5573.  
  5574.  
  5575.  
  5576.  
  5577.  
  5578.  
  5579.  
  5580.  
  5581.  
  5582.  
  5583.  
  5584.  
  5585.  
  5586.    RLIB Function Reference                                                 89
  5587.  
  5588.  
  5589.    Function:    FSAVESCREEN()
  5590.  
  5591.    Purpose:     Save screen to a disk file to be restored with FRESTSCREEN().
  5592.  
  5593.    Syntax:      FSAVESCREEN( filename )
  5594.  
  5595.    Arguments:   filename    - Character filename to which to save the screen. 
  5596.                               If the filename is not fully qualified, the
  5597.                               saved screen file will be placed in the current
  5598.                               default directory.
  5599.  
  5600.    Returns:     True if screen saved successfully.  If a file I/O error
  5601.                 occurs while opening on writing the file, FSAVESCREEN() will
  5602.                 return false.
  5603.  
  5604.    Description: FSAVESCREEN() is a screen function used to save a screen to a
  5605.                 disk file, to be later restored with the companion
  5606.                 FRESTSCREEN() function.
  5607.  
  5608.    Notes:       FSAVESCREEN() opens the disk file with the Clipper low level
  5609.                 file functions.  If a file create or open failure occurs,
  5610.                 FSAVESCREEN() returns false.
  5611.  
  5612.                 Although FSAVESCREEN() uses 4k of memory during operation,
  5613.                 that memory is released when the function exits.  Saving
  5614.                 screens to disk can conserve enormous amounts of memory
  5615.                 rather that storing multiple screens in memory variables.
  5616.  
  5617.                 FSAVESCREEN() will check for bad parameters or file I/O
  5618.                 errors and return false if something went wrong.  The way to
  5619.                 check that you can successfully save a screen to memory is to
  5620.                 check MEMORY(0) and verify at least 4K of free pool memory is
  5621.                 available.  Not only does this function conserve memory use
  5622.                 but also makes error correction a little easier.
  5623.  
  5624.                 Clipper 5.0
  5625.  
  5626.                 FSAVESCREEN() uses the values of MAXROW() and MAXCOL() to
  5627.                 determine the screen size, and hence the number of bytes to
  5628.                 write to <filename>.  To prevent strange behavior, neither
  5629.                 MAXROW() nor MAXCOL() must be changed with the SETMODE()
  5630.                 function between a FSAVESCREEN() and FRESTSCREEN() call.
  5631.  
  5632.    Example:     *-- save the current screen to file, and save some memory(0)
  5633.                 FSAVESCREEN("screen1.scr")
  5634.                 CLEAR
  5635.                 *-- do something
  5636.                 FRESTSCREEN("screen1.scr")
  5637.  
  5638.  
  5639.                 *-- old way of saving screens to memory variables
  5640.                 IF MEMORY(0) < 4
  5641.                    *-- error message
  5642.                 ELSE
  5643.  
  5644.  
  5645.    RLIB Function Reference                                                 90
  5646.  
  5647.  
  5648.                    SAVE SCREEN TO memvar
  5649.                 ENDIF
  5650.  
  5651.                 *-- new way saves memory and two lines of code
  5652.                 IF .NOT.  FSAVESCREEN("scrfile1.tmp")
  5653.                    *-- error message
  5654.                 ENDIF
  5655.  
  5656.    Source:      RL_FSAVE.PRG
  5657.  
  5658.    See also:    FRESTSCREEN()
  5659.  
  5660.  
  5661.  
  5662.  
  5663.  
  5664.  
  5665.  
  5666.  
  5667.  
  5668.  
  5669.  
  5670.  
  5671.  
  5672.  
  5673.  
  5674.  
  5675.  
  5676.  
  5677.  
  5678.  
  5679.  
  5680.  
  5681.  
  5682.  
  5683.  
  5684.  
  5685.  
  5686.  
  5687.  
  5688.  
  5689.  
  5690.  
  5691.  
  5692.  
  5693.  
  5694.  
  5695.  
  5696.  
  5697.  
  5698.  
  5699.  
  5700.  
  5701.  
  5702.  
  5703.  
  5704.    RLIB Function Reference                                                 91
  5705.  
  5706.  
  5707.    Function:    GETFILE()
  5708.  
  5709.    Purpose:     Full featured user dialog box for GETing filenames.
  5710.  
  5711.    Syntax:      GETFILE( [ filespec [, header [, mustexist [, confirm;
  5712.                          [, toprow [, restore ] ] ] ] ] )
  5713.  
  5714.    Arguments:   filespec    - Optional character file name or file
  5715.                               specification.  If omitted or a non-character
  5716.                               parameter is passed, the default is blank.
  5717.  
  5718.                 header      - Optional character title to display in the
  5719.                               header area of the filename entry dialog box. 
  5720.                               If omitted or a non-character argument is
  5721.                               given, the default header text is "Enter
  5722.                               Filename".
  5723.  
  5724.                 mustexist   - Optional logical value indicating whether or
  5725.                               not to verify that the filename entered exists. 
  5726.                               If omitted or a non-logical argument is given,
  5727.                               the default value is False (.F.) 
  5728.  
  5729.                 confirm     - Optional logical value indicating whether or
  5730.                               not to confirm a file overwrite if the file
  5731.                               exists.  The default value is True (.T.) 
  5732.  
  5733.                 toprow      - Optional numeric top row of the filename entry
  5734.                               dialog box.  Valid rows are from row 0 to row
  5735.                               20.  If not specified or an invalid row value
  5736.                               or a non-numeric value is given, the default
  5737.                               row is row number 8.
  5738.  
  5739.                 restore     - Optional logical value indicating whether or
  5740.                               not to save and restore the screen region
  5741.                               underneath the file entry box on exit.  If not
  5742.                               specified or a non-logical value is given, the
  5743.                               default is to restore the screen on exit, or
  5744.                               true.
  5745.  
  5746.    Returns:     The filename entered or a null string ("") if escape pressed.
  5747.  
  5748.    Description: GETFILE() is a file/screen function that puts up an entry
  5749.                 dialog box in the following format:
  5750.  
  5751.                             ╔════════════════════════════════════════╗
  5752.                             ║             Enter Filename             ║
  5753.                             ╠════════════════════════════════════════╣
  5754.                             ║████████████████████████████████████████║
  5755.                             ╚════════════════════════════════════════╝
  5756.  
  5757.                 The major use of this function is to query the user for a
  5758.                 file name.  The arguments permit control over certain aspects
  5759.                 such as whether or not to verify that the file entered
  5760.                 already exists.
  5761.  
  5762.  
  5763.    RLIB Function Reference                                                 92
  5764.  
  5765.  
  5766.    Notes:       All arguments are optional.  However a dummy must be passed
  5767.                 to get at a trailing argument.
  5768.  
  5769.                 The file entry box is drawn in double lines as show above,
  5770.                 and is centered on the screen beginning at the top row
  5771.                 specified.
  5772.  
  5773.                 The filename is retrieved using the @ x,y GET...READ
  5774.                 commands.  Therefore, in Clipper Summer '87 this function
  5775.                 must not be embedded within a pending READ, such as in a
  5776.                 VALID statement.  This is because nested READ's are not
  5777.                 supported directly in the Summer '87 version of Clipper.
  5778.  
  5779.                 In the Clipper 5.0 version of RLIB, GETFILE() declares
  5780.                 GETLIST as a LOCAL which allows a call to GETFILE() to be
  5781.                 nested within other READS.
  5782.  
  5783.                 The width of the file entry dialog box is 42 characters. 
  5784.                 Since fully qualified filenames may be longer the @GET
  5785.                 display scrolls horizontally by virtue of the @S40 function
  5786.                 in the PICTURE template.
  5787.  
  5788.                 GETFILE() uses the CHECKFILE() function to perform the edit
  5789.                 checks specified by the various arguments.
  5790.  
  5791.    Example:     *-- get a target file for a set printer command
  5792.                 target = GETFILE("", "Enter target output file", .F., .T.)
  5793.                 IF EMPTY(target)
  5794.                    RETURN
  5795.                 ENDIF
  5796.                 SET PRINTER TO (target)
  5797.  
  5798.  
  5799.                 *-- in this example, the default target file is OUTPUT.PRN
  5800.                 *-- accepting all other GETFILE() defaults
  5801.                 target = GETFILE("OUTPUT.PRN")
  5802.                 SET PRINTER TO (target)
  5803.  
  5804.  
  5805.    Source:      RL_GETFI.PRG
  5806.  
  5807.    See also:    CHECKFILE(), BORDERBOX(), PATHTO(), PARENT(), TARGET()
  5808.  
  5809.  
  5810.  
  5811.  
  5812.  
  5813.  
  5814.  
  5815.  
  5816.  
  5817.  
  5818.  
  5819.  
  5820.  
  5821.  
  5822.    RLIB Function Reference                                                 93
  5823.  
  5824.  
  5825.    Function:    GETKEY()
  5826.  
  5827.    Purpose:     Function to replace INKEY() to allow internal customization
  5828.  
  5829.    Syntax:      GETKEY( timeout )
  5830.  
  5831.    Arguments:   timeout     - REQUIRED numeric value which is the number of
  5832.                               seconds to wait for a keypress, as in INKEY().
  5833.  
  5834.    Returns:     The INKEY() value of the key pressed.
  5835.  
  5836.    Description: GETKEY() is a character function which is used as a
  5837.                 replacement for INKEY() in all RLIB functions that accept
  5838.                 INKEY() input.  It can otherwise be referred to as a "stub"
  5839.                 function which lets the programmer create their own
  5840.                 customized GETKEY() to replace the keyboard wait routines in
  5841.                 RLIB functions.  One such use is to trap the F1 key (INKEY()
  5842.                 = 28) within GETKEY() in order to extend the calling of HELP
  5843.                 routines from within RLIB functions.  This is because INKEY()
  5844.                 is not considered a "wait" state and help is not called when
  5845.                 F1 is pressed at an INKEY() state.  By installing the example
  5846.                 function below, you can have both help and INKEY().
  5847.  
  5848.    Notes:       All of the RLIB functions that solicit keyboard input use the
  5849.                 RLIB GETKEY() function instead of INKEY().  This enables you
  5850.                 to provide your own "hook" into the internals of RLIB
  5851.                 functions.  By creating your own customized GETKEY() function
  5852.                 and including it in your application, you can trap keystrokes
  5853.                 and act on them before they even get to the RLIB function. 
  5854.                 Take a look at the GETKEY() function in the Message Reader
  5855.                 demo program source code to see how GETKEY() expands the
  5856.                 capabilities of the RLIB PICKREC() function.
  5857.  
  5858.                 A sample program KEYBOARD.PRG is provided with the 5.01
  5859.                 version of Clipper that illustrates the same concept of
  5860.                 "stubbing out" the INKEY() function.
  5861.  
  5862.                 WARNING: NO ARGUMENT CHECKING IS PERFORMED IN GETKEY()!!!. 
  5863.                 You MUST pass the <timeout> parameter.  This was done in the
  5864.                 interest of speed since a parameter will always be used.  If
  5865.                 someone is stomping on the down arrow key in PICKREC(),
  5866.                 parameter checking on every call to this function would slow
  5867.                 it down needlessly.  To add parameter checking, include the
  5868.                 sample GETKEY() function below.
  5869.  
  5870.                 Usually, the internal HELP routine receives three parameters;
  5871.                 the calling procedure name, line number, and input variable. 
  5872.                 Any help called from this function will have GETKEY as the
  5873.                 calling procedure.
  5874.  
  5875.    Example:     *-- sample customized GETKEY() that traps the F1 Help key
  5876.                 FUNCTION GetKey
  5877.                 PARAMETER timeout
  5878.                 PRIVATE ikey
  5879.  
  5880.  
  5881.    RLIB Function Reference                                                 94
  5882.  
  5883.  
  5884.                 *-- add this if you want parameter checking for safety.
  5885.                 timeout = IF( TYPE("timeout") = "N", timeout, 0 )
  5886.  
  5887.                 DO WHILE .T.
  5888.                    ikey = INKEY(timeout)
  5889.                    IF ikey != 28
  5890.                       EXIT
  5891.                    ENDIF
  5892.                    DO Help WITH PROCNAME(), PROCLINE(), READVAR()
  5893.                 ENDDO
  5894.                 RETURN (ikey)
  5895.  
  5896.    Source:      RL_GETKE.PRG
  5897.  
  5898.    See also:    KEYINPUT(), PICKREC()
  5899.  
  5900.  
  5901.  
  5902.  
  5903.  
  5904.  
  5905.  
  5906.  
  5907.  
  5908.  
  5909.  
  5910.  
  5911.  
  5912.  
  5913.  
  5914.  
  5915.  
  5916.  
  5917.  
  5918.  
  5919.  
  5920.  
  5921.  
  5922.  
  5923.  
  5924.  
  5925.  
  5926.  
  5927.  
  5928.  
  5929.  
  5930.  
  5931.  
  5932.  
  5933.  
  5934.  
  5935.  
  5936.  
  5937.  
  5938.  
  5939.  
  5940.    RLIB Function Reference                                                 95
  5941.  
  5942.  
  5943.    Function:    GETPARM()
  5944.  
  5945.    Purpose:     Retrieve a comma delimited token from a character string
  5946.  
  5947.    Syntax:      GETPARM( position, string )
  5948.  
  5949.    Arguments:   position    - Numeric value indicating the ordinal position
  5950.                               in the comma delimited token list.
  5951.  
  5952.                 string      - The comma delimited string from which to
  5953.                               extract the token following the <position>-1
  5954.                               comma.
  5955.  
  5956.    Returns:     The extracted portion of <string> starting at the
  5957.                 (<position>-1)th comma up to the next comma or the end of the
  5958.                 string.   If no characters exist at the ordinal position
  5959.                 indicated, or if any arguments are missing or an invalid
  5960.                 type, GETPARM() will return a null string.
  5961.  
  5962.    Description: This function is used to retrieve a comma delimited parameter
  5963.                 from a character string.  The ways in which this can be used
  5964.                 are unlimited, but as an example, several RLIB functions use
  5965.                 GETPARM() to retrieve color settings from SETCOLOR().
  5966.  
  5967.    Notes:       GETPARM() is used in many RLIB functions to parse SETCOLOR()
  5968.                 to retrieve default colors when no color arrays are specified
  5969.                 in functions that offer color as an option.  Therefore, you
  5970.                 must not remove GETPARM() from RLIB! 
  5971.  
  5972.    Example:     *-- get the current Enhanced color setting from the
  5973.                 *-- second part of SETCOLOR()
  5974.                 mreverse = GETPARM(2, SETCOLOR())
  5975.  
  5976.                 *-- this will return "W/R" if SETCOLOR()="R/W,W/R,,,R/BG"
  5977.                 *-- 2nd token parameter is -------------------^
  5978.  
  5979.  
  5980.                 Example #2:
  5981.  
  5982.                 *-- write a function that accepts several parameters, all
  5983.                 *-- contained in one character string.
  5984.  
  5985.                 *-- Here is a sample parameter
  5986.                 files = "TEST1.DBF, TEST2.DBF, TEST3.DBF, TEST4.DBF"
  5987.  
  5988.  
  5989.                 *-- here is the call to the function
  5990.                 *-- open all the files in the string in separate work areas
  5991.                 OPENFILES(files)
  5992.  
  5993.  
  5994.                 *----------------------------------------------------------
  5995.                 *-- now here's your UDF to open many files in one swoop
  5996.                 *----------------------------------------------------------
  5997.  
  5998.  
  5999.    RLIB Function Reference                                                 96
  6000.  
  6001.  
  6002.                 FUNCTION OpenFiles
  6003.                 PARAMETER filenames
  6004.                 PRIVATE file2open, x
  6005.                 x = 1
  6006.                 DO WHILE .T.
  6007.                    file2open = GETPARM(x, filenames)
  6008.                    IF EMPTY(file2open)
  6009.                       EXIT
  6010.                    ENDIF
  6011.                    SELECT 0
  6012.                    USE (file2open)
  6013.                    x = x + 1
  6014.                 ENDDO
  6015.                 RETURN .T.
  6016.  
  6017.    Source:      RL_GETPA.PRG
  6018.  
  6019.    See also:    BRIGHT()
  6020.  
  6021.  
  6022.  
  6023.  
  6024.  
  6025.  
  6026.  
  6027.  
  6028.  
  6029.  
  6030.  
  6031.  
  6032.  
  6033.  
  6034.  
  6035.  
  6036.  
  6037.  
  6038.  
  6039.  
  6040.  
  6041.  
  6042.  
  6043.  
  6044.  
  6045.  
  6046.  
  6047.  
  6048.  
  6049.  
  6050.  
  6051.  
  6052.  
  6053.  
  6054.  
  6055.  
  6056.  
  6057.  
  6058.    RLIB Function Reference                                                 97
  6059.  
  6060.  
  6061.    Function:    HEX2DEC()
  6062.  
  6063.    Purpose:     Convert a hexadecimal string to its equivalent decimal value.
  6064.  
  6065.    Syntax:      HEX2DEC( hex_str )
  6066.  
  6067.    Arguments:   hex_str     - The hexadecimal value to convert to a decimal
  6068.                               value, expressed as a character string.
  6069.  
  6070.    Returns:     The decimal value of the hexadecimal string <hex_str> 
  6071.  
  6072.    Description: This function converts hexadecimal values expressed as
  6073.                 character strings to their decimal value equivalents.  There
  6074.                 are many libraries that implement this function but it's nice
  6075.                 to know you don't need assembly language experience to
  6076.                 accomplish this task! 
  6077.  
  6078.    Notes:       The string must be a valid hexadecimal number (i.e.  contains
  6079.                 only digits and letters A-F).  If a letter is encountered
  6080.                 that is not in the range A-F, HEX2DEC() will calculate that
  6081.                 letter as zero, and that letter will be ignored.  However,
  6082.                 this may cause erroneous results.  Ensure that hex strings
  6083.                 contain only valid hexadecimal characters.
  6084.  
  6085.                 HEX2DEC() ignores case so it does not matter if the hex
  6086.                 string contains lower, upper, or mixed case letters.
  6087.  
  6088.    Example:     ? HEX2DEC("FFFF")          && result = 65535
  6089.                 ? HEX2DEC("010")           && result = 16
  6090.                 ? HEX2DEC("Fr0")           && result = 3840
  6091.  
  6092.    Source:      RL_HEX2D.PRG
  6093.  
  6094.    See also:    BIN2DEC(), DEC2HEX()
  6095.  
  6096.  
  6097.  
  6098.  
  6099.  
  6100.  
  6101.  
  6102.  
  6103.  
  6104.  
  6105.  
  6106.  
  6107.  
  6108.  
  6109.  
  6110.  
  6111.  
  6112.  
  6113.  
  6114.  
  6115.  
  6116.  
  6117.    RLIB Function Reference                                                 98
  6118.  
  6119.  
  6120.    Function:    ISDBF()
  6121.  
  6122.    Purpose:     Test if a file is a valid .DBF format database file.
  6123.  
  6124.    Syntax:      ISDBF( filename [, showerror ] )
  6125.  
  6126.    Arguments:   filename    - Character string or variable indicating the
  6127.                               name of the file to check if is a valid .DBF
  6128.                               format database file.
  6129.  
  6130.                 showerror   - Optional logical value indicating whether or
  6131.                               not to display an error message if the file is
  6132.                               not a valid .DBF format file.  If omitted or a
  6133.                               non-logical value is given, the default is
  6134.                               False, do not display any error message.
  6135.  
  6136.    Returns:     True if the file is a valid .DBF format file, false if not.
  6137.  
  6138.    Description: ISDBF() is a file function used to test if a given file is a
  6139.                 valid .DBF format file.  This is useful in situations where
  6140.                 the format of a file cannot be assumed to be .DBF.
  6141.  
  6142.    Notes:       If the required filename parameter is omitted, or is not a
  6143.                 character type parameter, ISDBF() will return False and set
  6144.                 RLIBERROR().
  6145.  
  6146.                 The .DBF file format dictates that the first byte of the file
  6147.                 be either 0x03 or 0x83 hexadecimal values (3 or 131 decimal),
  6148.                 0x03 for regular .DBF files, 0x83 for .DBF files with one or
  6149.                 more memo fields.
  6150.  
  6151.    Example:     *-- verify a file is .DBF before trying to USE it
  6152.                 IF ISDBF("myfile.dbf")
  6153.                    USE myfile.dbf
  6154.                 ELSE
  6155.                    ? "Not a valid .DBF file."
  6156.                 ENDIF
  6157.  
  6158.    Source:      RL_ISDBF.PRG
  6159.  
  6160.    See also:    DBFCREATE(), ISFIELD()
  6161.  
  6162.  
  6163.  
  6164.  
  6165.  
  6166.  
  6167.  
  6168.  
  6169.  
  6170.  
  6171.  
  6172.  
  6173.  
  6174.  
  6175.  
  6176.    RLIB Function Reference                                                 99
  6177.  
  6178.  
  6179.    Function:    ISFIELD()
  6180.  
  6181.    Purpose:     Test if a field name is valid in the selected database.
  6182.  
  6183.    Syntax:      ISFIELD( fieldname )
  6184.  
  6185.    Arguments:   fieldname   - Character name to test if is a field in the
  6186.                               currently selected database.
  6187.  
  6188.    Returns:     True if <fieldname> is a field in the currently selected
  6189.                 database.
  6190.  
  6191.    Description: ISFIELD() is a database function used mainly to verify a 
  6192.                 fieldname in the current database file.  This can be helpful
  6193.                 in verifying that fields explicitly named in your application
  6194.                 have not been altered, removed, or renamed in the database
  6195.                 file outside the control of your application.
  6196.  
  6197.    Notes:       If no fieldname is provided, ISFIELD() will return false and
  6198.                 set the appropriate RLIBERROR() 
  6199.  
  6200.    Example:     *-- verify Name field before replacing
  6201.                 IF ISFIELD("name")
  6202.                    REPLACE name WITH "Richard Low"
  6203.                 ELSE
  6204.                    BUZZ()
  6205.                    SAYINBOX( "W+/R", "Internal database error!",;
  6206.                                      "Field NAME does not exist", 10 )
  6207.                 ENDIF
  6208.  
  6209.    Source:      RL_ISFIE.PRG
  6210.  
  6211.    See also:    ISDBF()
  6212.  
  6213.  
  6214.  
  6215.  
  6216.  
  6217.  
  6218.  
  6219.  
  6220.  
  6221.  
  6222.  
  6223.  
  6224.  
  6225.  
  6226.  
  6227.  
  6228.  
  6229.  
  6230.  
  6231.  
  6232.  
  6233.  
  6234.  
  6235.    RLIB Function Reference                                                100
  6236.  
  6237.  
  6238.    Function:    KEYINPUT()
  6239.  
  6240.    Purpose:     Get keyboard input, optionally echoing dots to the screen
  6241.  
  6242.    Syntax:      KEYINPUT( length, upper_case, echo_chars, string )
  6243.  
  6244.    Arguments:   length      - Optional numeric value specifying the maximum
  6245.                               length of the string that may be entered (and
  6246.                               returned by KEYINPUT).  If omitted or an
  6247.                               invalid parameter is passed, the default length
  6248.                               will be 80 characters.
  6249.  
  6250.                 upper_case  - Optional logical value indicating if all
  6251.                               characters that are typed will be forced to
  6252.                               upper case.  If omitted or an invalid parameter
  6253.                               is passed, the default is false, characters
  6254.                               will be returned as entered.
  6255.  
  6256.                 echo_chars  - Optional logical value indicating if typed
  6257.                               characters will appear on the screen.  If this
  6258.                               value is false, dots will echo on screen.  If
  6259.                               omitted or an invalid parameter is passed, the
  6260.                               default is true, characters will echo on screen
  6261.                               as entered.
  6262.  
  6263.                 string      - Optional starting character string for key
  6264.                               input.  If omitted or an invalid parameter is
  6265.                               passed, KEYINPUT() starts with a null (empty)
  6266.                               string.
  6267.  
  6268.    Returns:     The character string typed in, or a null string ("") if the
  6269.                 Escape key was pressed.
  6270.  
  6271.    Description: KEYINPUT() is a screen function used for accepting direct
  6272.                 keyboard input from the user while giving the programmer
  6273.                 control over each key press.  One such use is for direct dots
  6274.                 onto the screen instead of the characters typed.  This is
  6275.                 most often used during password entry.
  6276.  
  6277.    Notes:       There is no built in way of allowing key input while echoing
  6278.                 dots on the screen to prevent on-lookers from seeing what is
  6279.                 being entered.  SETting COLOR TO X will blank out the screen
  6280.                 but then you cannot see how many characters have been
  6281.                 entered.  We may want to see dots echo (as most BBS' do) so
  6282.                 we can tell how many characters we have entered.  With
  6283.                 KEYINPUT() you can easily do this, while also determining the
  6284.                 maximum length of the input string, whether or not it is to
  6285.                 be all upper case, and whether or not to echo the actual
  6286.                 characters on the screen, or just dots.
  6287.  
  6288.                 KEYINPUT() starts accepting character input at the current
  6289.                 cursor location on the screen and terminates when either the
  6290.                 maximum character count has been reached or ENTER or ESCAPE
  6291.                 is pressed.
  6292.  
  6293.  
  6294.    RLIB Function Reference                                                101
  6295.  
  6296.  
  6297.                 If <length> is greater than the remaining width of the
  6298.                 screen, KEYINPUT() will wrap to the next line.
  6299.  
  6300.    Example:     *-- get the user's password, keep it less than or equal to 30
  6301.                 *-- characters, make upper case, and echo dots on screen
  6302.                 @ 5,0 SAY "Enter your password: "
  6303.                 password = KEYINPUT( 30, .T., .F.  )
  6304.  
  6305.    Source:      RL_KEYIN.PRG
  6306.  
  6307.    See also:    BOXASK(), GETFILE()
  6308.  
  6309.  
  6310.  
  6311.  
  6312.  
  6313.  
  6314.  
  6315.  
  6316.  
  6317.  
  6318.  
  6319.  
  6320.  
  6321.  
  6322.  
  6323.  
  6324.  
  6325.  
  6326.  
  6327.  
  6328.  
  6329.  
  6330.  
  6331.  
  6332.  
  6333.  
  6334.  
  6335.  
  6336.  
  6337.  
  6338.  
  6339.  
  6340.  
  6341.  
  6342.  
  6343.  
  6344.  
  6345.  
  6346.  
  6347.  
  6348.  
  6349.  
  6350.  
  6351.  
  6352.  
  6353.    RLIB Function Reference                                                102
  6354.  
  6355.  
  6356.    Function:    MAKEALIAS()
  6357.  
  6358.    Purpose:     Construct a database work area alias from a full filename.
  6359.  
  6360.    Syntax:      MAKEALIAS( filename )
  6361.  
  6362.    Arguments:   filename    - Character string or variable name of the file
  6363.                               from which to construct a default work area
  6364.                               alias name.  If omitted or a non-character
  6365.                               parameter is provided, a null string is
  6366.                               returned and RLIBERROR() set.
  6367.  
  6368.    Returns:     A default work alias for a supplied DBF file name.
  6369.  
  6370.    Description: This function will strip off a trailing .DBF extension and
  6371.                 any leading drive/path name qualifiers to create a default
  6372.                 alias.  This is useful in a runtime environment where it is
  6373.                 necessary to supply a valid alias name where otherwise one
  6374.                 would not be available.
  6375.  
  6376.    Notes:       This can be most useful for creating generic file open
  6377.                 functions where a standard default work area alias name must
  6378.                 be generated when a file is opened.  MAKEALIAS() is used
  6379.                 internally by OPENED() to construct an alias name from the
  6380.                 database file name.
  6381.  
  6382.    Example:     ? MAKEALIAS("c:\data\myfile.dbf")      && returns "MYFILE"
  6383.  
  6384.    Source:      RL_MAKEA.PRG
  6385.  
  6386.    See also:    OPENED()
  6387.  
  6388.  
  6389.  
  6390.  
  6391.  
  6392.  
  6393.  
  6394.  
  6395.  
  6396.  
  6397.  
  6398.  
  6399.  
  6400.  
  6401.  
  6402.  
  6403.  
  6404.  
  6405.  
  6406.  
  6407.  
  6408.  
  6409.  
  6410.  
  6411.  
  6412.    RLIB Function Reference                                                103
  6413.  
  6414.  
  6415.    Function:    MARKREC()
  6416.  
  6417.    Purpose:     Mark and select multiple records from a database pick list.
  6418.  
  6419.    Syntax:      MARKREC( t, l, b, r, fieldlist, markkey, markfield, colors )
  6420.  
  6421.    Arguments:   t,l,b,r     - Numeric values specifying the Top, Left, Bottom
  6422.                               and Right screen coordinates of the display
  6423.                               box.  The top and bottom row values must be
  6424.                               between 0 and 24 (MAXROW() in 5.0), and the
  6425.                               left and right column values must be between 0
  6426.                               and 79.
  6427.  
  6428.                 fieldlist   - Character expression which evaluates to a field
  6429.                               list to be displayed at runtime.  This value is
  6430.                               macro substituted, so it must evaluate
  6431.                               correctly to a character string.  Any valid
  6432.                               expression may be used.
  6433.  
  6434.                 markkey     - Optional mark/unmark key ASCII value which,
  6435.                               when pressed, toggles the current record being
  6436.                               included in a "marked" list.  If omitted or a
  6437.                               non-numeric value is passed the default ASCII
  6438.                               key value is -8, for the F9 key.
  6439.  
  6440.                 markfield   - Optional field name or expression evaluated and
  6441.                               used to add an item to the marked list.  If
  6442.                               omitted or <markfield> is non-character in type
  6443.                               or empty, then the default expression used to
  6444.                               add items to the marked list is
  6445.                               "STR(RECNO(),8,0)" 
  6446.  
  6447.                 colors      - Optional array of color settings used to govern
  6448.                               the colors of various parts of the MARKREC()
  6449.                               display.  See the table listed below for
  6450.                               options and default values if the array is not
  6451.                               provided.
  6452.  
  6453.    Returns:     A character string of selected record numbers, each eight
  6454.                 digits long, delimited with a comma ",", or a null string if
  6455.                 Escape was pressed.  If the optional <markfield> parameter is
  6456.                 provided, the character string returned consists of elements
  6457.                 added during the marking process.
  6458.  
  6459.    Description: MARKREC() is a function for cursoring through a pick list
  6460.                 selection of records from the currently selected database,
  6461.                 and marking the records to work with by pressing a designated
  6462.                 key (default = F9).  When the MARKREC() session is completed,
  6463.                 MARKREC() returns a single character string which contains
  6464.                 comma delimited tokens.  This string can then be parsed to
  6465.                 extract each token in succession to process the records that
  6466.                 were marked.
  6467.  
  6468.                 MARKREC() lets a user select multiple records from a database
  6469.  
  6470.  
  6471.    RLIB Function Reference                                                104
  6472.  
  6473.  
  6474.                 to be included in some subsequent operation.  One such use is
  6475.                 for prompting the user for records to include in a report. 
  6476.                 The user cursors up and down through a database pick list and
  6477.                 presses a designated mark key to select each record.  When
  6478.                 the user terminates by pressing the Enter key, MARKREC()
  6479.                 returns a list of record numbers or field contents of the
  6480.                 records selected.
  6481.  
  6482.    Notes:       MARKREC() behaves very similar to PICKREC() except that
  6483.                 instead if picking one record, you mark several records for
  6484.                 processing.  MARKREC() skips forward and backward through the
  6485.                 database records as the up and down arrow keys are pressed. 
  6486.                 The PgUp and PgDn scroll one window full of records.  When
  6487.                 the Enter key is pressed, MARKREC() exits and returns a list
  6488.                 of selected records in the form of a string of record
  6489.                 numbers, each 8 digits with a comma delimiter.  For example,
  6490.                 if the marked records were record numbers 5, 12 and 123, the
  6491.                 string would be: "       5,      12,     123,".  Notice the
  6492.                 trailing comma; a comma is added to the end of each selected
  6493.                 record number.  To process the selected records you may use
  6494.                 either FOR <data> $ string logic, or a loop to extract each
  6495.                 record number to process.  See the example.  If the markfield
  6496.                 parameter is supplied, this field (or expression) is
  6497.                 extracted, and a trailing comma added to the end.  You can
  6498.                 create your parsing loop based on the length of this field or
  6499.                 expression.
  6500.  
  6501.                 MARKREC() merely packages the parameters and makes a call to
  6502.                 PICKREC() specifying the proper marking arguments.  See the
  6503.                 PICKREC() function documentation for more details.  PICKREC()
  6504.                 can be called directly.
  6505.  
  6506.                 The elements of the color array are:
  6507.  
  6508.                 Element#  Description                 Default
  6509.                 --------  --------------------------  ---------------------
  6510.                 color[1]  Normal text display         Standard - SETCOLOR()
  6511.                 color[2]  Selected or Marked          BRIGHT() Standard
  6512.                 color[3]  Hi-lited (scroll bar)       Enhanced
  6513.                 color[4]  Hi-lited & Selected/Marked  Enhanced/Bright/Blink
  6514.                 color[5]  Color on exit from XITKEYS  BRIGHT() Standard
  6515.                 color[6]  Normal text IF (color[8])   Standard - SETCOLOR()
  6516.                 color[7]  Hi-lited IF (color[8])      Enhanced
  6517.                 color[8]  Character condition         "(.T.)"
  6518.  
  6519.    Example:     *-- database of customer orders, select orders to print
  6520.                 *-- Orderno and Customer are fields in your database
  6521.                 output = "Orderno + ' ' + Customer"
  6522.  
  6523.                 *-- draw a double line box with a title header
  6524.                 BORDERBOX( 1, 0, 22, 36, "CUSTOMER ORDERS" )
  6525.  
  6526.                 *-- make the F5 key (INKEY() = -4) be the marking key
  6527.                 marked = MARKREC( 4, 2, 21, 35, output, -4 )
  6528.  
  6529.  
  6530.    RLIB Function Reference                                                105
  6531.  
  6532.  
  6533.                 *-- now you can print information in one of two ways
  6534.  
  6535.                 *-- Method #1
  6536.                 REPORT FORM custrepo FOR STR(RECNO(),8,0)+"," $ marked
  6537.                 *-- the comma on the end solves the problem of a mistaken
  6538.                 *-- match from two record numbers concatenated together
  6539.                 *-- "       110000000" = record 1 and 10000000, but would
  6540.                 *-- match on record number 11 or 110 or 1100 etc...
  6541.  
  6542.  
  6543.                 *-- Method #2 is a little more code but much quicker
  6544.                 DO WHILE LEN(marked) > 0
  6545.                    *-- get a record number from list (1st 8 digits in list)
  6546.                    mrecord = VAL(SUBSTR(marked,1,8))
  6547.                    *-- or you could do this another way
  6548.                    *-- mrecord = VAL(GETPARM(1,marked))
  6549.                    GOTO (mrecord)
  6550.                    DO <your_report_printing_routine>
  6551.                    *-- strip off first 9 characters (8 digits plus a comma)
  6552.                    marked = SUBSTR(marked,10)
  6553.                 ENDDO
  6554.  
  6555.    Source:      RL_MARKR.PRG
  6556.  
  6557.    See also:    GETPARM(), PICKREC()
  6558.  
  6559.  
  6560.  
  6561.  
  6562.  
  6563.  
  6564.  
  6565.  
  6566.  
  6567.  
  6568.  
  6569.  
  6570.  
  6571.  
  6572.  
  6573.  
  6574.  
  6575.  
  6576.  
  6577.  
  6578.  
  6579.  
  6580.  
  6581.  
  6582.  
  6583.  
  6584.  
  6585.  
  6586.  
  6587.  
  6588.  
  6589.    RLIB Function Reference                                                106
  6590.  
  6591.  
  6592.    Function:    MEMORIZE()
  6593.  
  6594.    Purpose:     Save field values from a database record to memory variables.
  6595.  
  6596.    Syntax:      MEMORIZE( [ blank ] )
  6597.  
  6598.    Arguments:   blank       - Optional logical value which if specified as
  6599.                               True tells MEMORIZE() to create an empty
  6600.                               M->memvar of the associated field type for each
  6601.                               database field.
  6602.  
  6603.    Returns:     True if all fields successively stored to memory variables.
  6604.  
  6605.    Description: This function is designed to be used in conjunction with the
  6606.                 CHANGED(), MREPLACE(), and FORGET() functions; they are all a
  6607.                 team.  Put together, they simplify the scattering and
  6608.                 gathering of database field contents into and from associated
  6609.                 memory variables (some languages call them temporary field
  6610.                 variables).  What MEMORIZE() does is to create a PUBLIC
  6611.                 memory variable with the same name as each of the fields in
  6612.                 the current record of the currently selected database file,
  6613.                 and assign to that memory variable the value of its
  6614.                 associated field.  You then GET the contents of the memory
  6615.                 variable rather than GETting the field directly.  After your
  6616.                 READ is finished, you check to see if any of the memory
  6617.                 variable values have CHANGED() from their database field
  6618.                 counterparts and, if so, issue a MREPLACE() then FORGET()
  6619.                 them.  The process may seem a little complicated at first,
  6620.                 but it's a lot easier than cluttering up code with STORE TO's
  6621.                 and REPLACE WITH's.
  6622.  
  6623.    Notes:       Used to store a working copy of all the database record field
  6624.                 contents to memory variables for editing.  This is good
  6625.                 programming practice in that you should never GET a field
  6626.                 directly, but only work with a copy which can later be
  6627.                 REPLACEd.  The <blank> option is useful for creating a set of
  6628.                 field variables when appending a new record.  Remember,
  6629.                 memory variables created with MEMORIZE() have the same name
  6630.                 as their database field counterparts.  Whenever there are
  6631.                 fields and memory variables with the same names, fields take
  6632.                 precedence.  So to access these variables you must preface
  6633.                 the variable name with the memory variable identifier alias
  6634.                 M->.
  6635.  
  6636.                 Each memory variable created is the same data type as its
  6637.                 associated field.  If the optional blank parameter is
  6638.                 supplied, each of these variables are empty (Memo field
  6639.                 variables are initialized as a character string of zero
  6640.                 length).  The following table of samples gives the data types
  6641.                 created: 
  6642.  
  6643.  
  6644.  
  6645.  
  6646.  
  6647.  
  6648.    RLIB Function Reference                                                107
  6649.  
  6650.  
  6651.                 FIELD NAME  FIELD TYPE  LEN  VARIABLE NAME  BLANK VALUE
  6652.                 ----------  ----------  ---  -------------  ------------
  6653.                 Name        Character    32  M->name        SPACE(32)
  6654.                 BirthDate   Date          8  M->birthdate   CTOD(" ")
  6655.                 Age         Numeric       2  M->age         0
  6656.                 Male        Logical       1  M->male        .F.
  6657.                 Comments    Memo         10  M->comments    ""
  6658.  
  6659.    Example:     *-- store empty field values for a new record
  6660.                 MEMORIZE(.T.)
  6661.  
  6662.                 *-- get the data
  6663.                 @ 1,0 SAY "Enter full name" GET M->name
  6664.                 @ 2,0 SAY "Enter birthdate" GET M->birthdate
  6665.                 @ 3,0 SAY "Enter age      " GET M->age  PICTURE "##"
  6666.                 *-- remember to always PICTURE numeric memory variables
  6667.                 READ
  6668.  
  6669.                 *-- now add the new record and put in the data
  6670.                 IF NO_APPEND()
  6671.                    *-- error message
  6672.                    RETURN
  6673.                 ENDIF
  6674.                 MREPLACE()
  6675.  
  6676.                 *-- now release the public variables
  6677.                 FORGET()
  6678.  
  6679.    Source:      RL_MEMOR.PRG
  6680.  
  6681.    See also:    CHANGED(), MREPLACE(), FORGET()
  6682.  
  6683.  
  6684.  
  6685.  
  6686.  
  6687.  
  6688.  
  6689.  
  6690.  
  6691.  
  6692.  
  6693.  
  6694.  
  6695.  
  6696.  
  6697.  
  6698.  
  6699.  
  6700.  
  6701.  
  6702.  
  6703.  
  6704.  
  6705.  
  6706.  
  6707.    RLIB Function Reference                                                108
  6708.  
  6709.  
  6710.    Function:    MIDDLE()
  6711.  
  6712.    Purpose:     Center a string by padding with leading and trailing spaces.
  6713.  
  6714.    Syntax:      MIDDLE( string, width )
  6715.  
  6716.    Arguments:   string      - Character string or variable which is to be
  6717.                               padded with leading and trailing spaces
  6718.                               sufficient to center in <width>.
  6719.  
  6720.                 width       - Optional numeric value representing the desired
  6721.                               width of the returned string.  If omitted or an
  6722.                               invalid parameter is passed, the default width
  6723.                               is 80 characters.
  6724.  
  6725.    Returns:     <string> padded with leading and trailing spaces to center
  6726.                 <string> in a line of length <width>.
  6727.  
  6728.    Description: MIDDLE() is a character/screen function used to pad strings
  6729.                 with leading and trailing spaces sufficient to center the
  6730.                 string in <width>.  It can most commonly be used in menuing
  6731.                 and field edit schemes where a centered prompt message is
  6732.                 needed at the bottom of the screen.  This can also be
  6733.                 accomplished with the CENTER() function.  However, since
  6734.                 middle returns strings with leading and trailing blanks, the
  6735.                 line does not need to be erased first.
  6736.  
  6737.    Notes:       The default width is 80 characters, ideal for screen oriented
  6738.                 displays.  MIDDLE() works fine with wider widths for printed
  6739.                 reports.
  6740.  
  6741.                 The difference between MIDDLE() and CENTER() is that MIDDLE()
  6742.                 can effectively erase any previous screen data.
  6743.  
  6744.    Example:     *-- use MIDDLE() to display centered prompts
  6745.                 @ 24,0 SAY MIDDLE("Press any key to continue")
  6746.  
  6747.    Source:      RL_MIDDL.PRG
  6748.  
  6749.    See also:    CENTER()
  6750.  
  6751.  
  6752.  
  6753.  
  6754.  
  6755.  
  6756.  
  6757.  
  6758.  
  6759.  
  6760.  
  6761.  
  6762.  
  6763.  
  6764.  
  6765.  
  6766.    RLIB Function Reference                                                109
  6767.  
  6768.  
  6769.    Function:    MREPLACE()
  6770.  
  6771.    Purpose:     Replace fields with memory variables created with MEMORIZE()
  6772.  
  6773.    Syntax:      MREPLACE()
  6774.  
  6775.    Arguments:   None
  6776.  
  6777.    Returns:     True if all fields successively replaced.
  6778.  
  6779.    Description: This function is designed to be used in conjunction with the
  6780.                 MEMORIZE(), CHANGED(), and FORGET() functions; they are all a
  6781.                 team.  Put together, they simplify the scattering and
  6782.                 gathering of database field contents into and from associated
  6783.                 memory variables (some languages call them temporary field
  6784.                 variables).  What MREPLACE() does is to replace each field in
  6785.                 the current database record with the associated field memory
  6786.                 variable that was created with MEMORIZE() and usually,
  6787.                 recently edited.
  6788.  
  6789.    Notes:       Memory variables created with MEMORIZE() have the same name
  6790.                 as their database field counterparts.  Whenever there exist
  6791.                 fields and memory variables with the same name, fields take
  6792.                 precedence.  To access these variables you must preface the
  6793.                 variable name with the memory variable identifier alias M->.
  6794.  
  6795.                 MREPLACE() does a REPLACE <field> WITH <fieldvar> for each
  6796.                 field of the database record.
  6797.  
  6798.    Example:     *-- store field values to memvar copies
  6799.                 MEMORIZE()
  6800.  
  6801.                 *-- get the data
  6802.                 @ 1,0 SAY "Enter full name" GET M->name
  6803.                 @ 2,0 SAY "Enter birthdate" GET M->birthdate
  6804.                 @ 3,0 SAY "Enter age      " GET M->age  PICTURE "##"
  6805.                 *-- remember to always PICTURE numeric memory variables
  6806.                 READ
  6807.  
  6808.                 *-- don't bother replacing if no change
  6809.                 IF CHANGED()
  6810.                    IF .NOT.  MREPLACE()
  6811.                       SAYINBOX("Error writing fields!  Replace failed.")
  6812.                    ENDIF
  6813.                 ENDIF
  6814.  
  6815.                 *-- now release the public variables
  6816.                 FORGET()
  6817.  
  6818.    Source:      RL_MREPL.PRG
  6819.  
  6820.    See also:    CHANGED(), FORGET(), MEMORIZE()
  6821.  
  6822.  
  6823.  
  6824.  
  6825.    RLIB Function Reference                                                110
  6826.  
  6827.  
  6828.    Function:    MULTIMENU()
  6829.  
  6830.    Purpose:     Create multi-column menus with four way cursor movement.
  6831.  
  6832.    Syntax:      MULTIMENU( t, l, b, r, options [, columns [, messages ;
  6833.                             [, msg_row [, colors ] ] ] ] )
  6834.  
  6835.    Arguments:   t,l,b,r     - Numeric values specifying the Top, Left, Bottom
  6836.                               and Right screen coordinates of the display
  6837.                               box.  The top and bottom row values must be
  6838.                               between 0 and 24 (MAXROW() in 5.0), and the
  6839.                               left and right column values must be between 0
  6840.                               and 79.
  6841.  
  6842.                 options     - Array of character strings to use as menu
  6843.                               options.  Each element of the array is
  6844.                               displayed as a menu option filling the box.
  6845.  
  6846.                 columns     - Optional numeric value indicating the number of
  6847.                               columns to use for displaying the options.  If
  6848.                               omitted or a non numeric parameter is passed,
  6849.                               or if it is zero, the columns will be
  6850.                               calculated to fit the most options across the
  6851.                               left and right window boundaries.
  6852.  
  6853.                 messages    - Optional array of character strings to display
  6854.                               as messages corresponding to each of the menu
  6855.                               options.
  6856.  
  6857.                 msg_row     - Optional numeric value indicating the row for
  6858.                               the optional messages to appear.  This value
  6859.                               must be between 0 and 24 (MAXROW() in 5.0). 
  6860.                               The default is row 24, or MAXROW() in the
  6861.                               Clipper 5.0 version.
  6862.  
  6863.                 colors      - Optional array of character strings specifying
  6864.                               the color settings to use.  See the color table
  6865.                               below for the colors used for the different
  6866.                               components of the menu.
  6867.  
  6868.    Returns:     The number of the array element chosen, or zero if the escape
  6869.                 key was pressed.
  6870.  
  6871.    Description: MULTIMENU is a multi-column menu selection function.  Many
  6872.                 programs offer a list of options to choose from displayed
  6873.                 across the screen allowing you to cursor up, down, left and
  6874.                 right to navigate around the options.  This function takes an
  6875.                 array of character strings and displays them in this format.
  6876.  
  6877.    Notes:       If any of the first four parameters specifying the window
  6878.                 coordinates are out of bounds, or the <right> is less than or
  6879.                 equal to <left>, or <bottom> is less than or equal to <top>,
  6880.                 MULTIMENU() will fail and return zero.  Also, if the options
  6881.                 array is empty, a zero will be returned.  If the number of
  6882.  
  6883.  
  6884.    RLIB Function Reference                                                111
  6885.  
  6886.  
  6887.                 columns option is omitted (or zero to make the number of
  6888.                 columns automatic), MULTIMENU() will position columns so that
  6889.                 columns are separated by at least one space.  If more
  6890.                 elements exist in the array than will fit in the display
  6891.                 window given the number of columns being used, the PgDn and
  6892.                 PgUp keys will skip forward and back between windows.
  6893.  
  6894.                 The following color table shows which features of the menu
  6895.                 each element of the color array controls:
  6896.  
  6897.                             colors[1] = Menu choices.
  6898.                             colors[2] = Menu selection bar.
  6899.                             colors[3] = <not used>
  6900.                             colors[4] = <not used>
  6901.                             colors[5] = Selected choice on exit.
  6902.  
  6903.                 If you use this color feature, DECLARE your colors array to
  6904.                 have at least 5 elements.  If the colors option is not
  6905.                 specified or there are less than 5 elements, then the default
  6906.                 colors are used.  These defaults are: the current Standard
  6907.                 color is used for the item displays, and the Enhanced color
  6908.                 is used for the menu selection bar.
  6909.  
  6910.  
  6911.    Example:     *-- display fields in box with structure for each shown below
  6912.                 USE manyflds.dbf
  6913.  
  6914.                 *-- declare arrays for field names
  6915.                 num = FCOUNT()
  6916.                 DECLARE fields[num], types[num], widths[num], dec[num]
  6917.                 DECLARE struct[num]
  6918.                 AFIELDS( fields, types, widths, dec )  && fill with .DBF info
  6919.  
  6920.                 FOR x = 1 TO num
  6921.                    *-- now make each field name 12 spaces wide
  6922.                    fields[x] = STRETCH(fields[x],12)
  6923.                    *-- and build field description message for each
  6924.                    struct[x] = IF( types[x] = "C", "Character",;
  6925.                                IF( types[x] = "N", "Numeric",;
  6926.                                IF( types[x] = "L", "Logical",;
  6927.                                IF( types[x] = "D", "Date", "Memo")))) +;
  6928.                                "  Length: "   + STR(widths[x],3,0) +;
  6929.                                "  Decimals: " + STR(dec[x],3,0)
  6930.                 NEXT x
  6931.                 *-- now present these fields in a single line box
  6932.                 @ 1,0,10,79 BOX "╔═╗║╝═╚║"
  6933.  
  6934.                 *-- present fields with structure for each on line 11
  6935.                 *-- the zero makes UDF calc column number dynamically
  6936.                 fieldnum = MULTIMENU( 2,1,9,78, fields, 0, struct, 11 )
  6937.  
  6938.    Source:      RL_MULTI.PRG
  6939.  
  6940.    See also:    BARMENU(), BOXMENU()
  6941.  
  6942.  
  6943.    RLIB Function Reference                                                112
  6944.  
  6945.  
  6946.    Function:    NAMESPLIT()
  6947.  
  6948.    Purpose:     Convert names from First Middle Last to Last, First Middle.
  6949.  
  6950.    Syntax:      NAMESPLIT( name )
  6951.  
  6952.    Arguments:   name        - Character string indicating the name string in
  6953.                               the form First Middle Last to parse into Last,
  6954.                               First Middle.
  6955.  
  6956.    Returns:     A character string equal to <name> flipped to lastname first,
  6957.                 with a comma space inserted.
  6958.  
  6959.    Description: NAMESPLIT() is a character function used to parse names to
  6960.                 split into the last name, middle name, and first name
  6961.                 components.  What NAMESPLIT() does is let you type in a name
  6962.                 in the form RICHARD C.  LOW, and it returns LOW, RICHARD C. 
  6963.                 This is particularly useful for SEEKing names from an index
  6964.                 that was indexed on PAD(TRIM(Lastname)+', '+Firstname,32). 
  6965.                 Such an index will insure the correct ordering of names. 
  6966.                 This is especially helpful in front end applications as a
  6967.                 user interface tool...NAMESPLIT() can allow a user to perform
  6968.                 a name search without regard to internal name storage format.
  6969.  
  6970.    Notes:       NAMESPLIT() is aware of the standard name suffixes, i.e. 
  6971.                 JR., SR., II, 2ND, III, 3RD, 4TH, M.D., PHD, and will
  6972.                 recognize these as not being lastnames.  Without this, a name
  6973.                 entered as RICHARD C.  LOW, JR.  may incorrectly be split
  6974.                 into JR., RICHARD C.  However, there will be occasions where
  6975.                 a name/ suffix combination may not work.  The good news is
  6976.                 that NAMESPLIT() makes name entering easier 99% of the time.
  6977.  
  6978.    Example:     ? NAMESPLIT("John Smith")
  6979.                    *-- returns "Smith, John"
  6980.  
  6981.                 ? NAMESPLIT("John M.  Smith, MD")
  6982.                    *-- returns "Smith MD, John M."
  6983.  
  6984.  
  6985.                 *-- consider a file indexed on the following key:
  6986.                 *-- (note that the above index expression is built to, then
  6987.                 *-- limited to 32 characters in order to keep the index key
  6988.                 *-- a constant length)
  6989.                 INDEX ON UPPER(PAD(TRIM(Lastname)+", "+Firstname,32)) TO x
  6990.  
  6991.                 ? "Enter name to locate:"
  6992.                 mname = KEYINPUT(40,.T.)         && they enter "RICHARD LOW"
  6993.                 SEEK NAMESPLIT(mname)            && it finds "LOW, RICHARD"
  6994.  
  6995.    Source:      RL_NAMES.PRG
  6996.  
  6997.    See also:    GETPARM(), KEYINPUT()
  6998.  
  6999.  
  7000.  
  7001.  
  7002.    RLIB Function Reference                                                113
  7003.  
  7004.  
  7005.    Function:    NO_APPEND()
  7006.  
  7007.    Purpose:     Network append blank function with specific error trapping
  7008.  
  7009.    Syntax:      NO_APPEND( [ color [, msg1 [, msg2 [, msg3 ] ] ] ] )
  7010.  
  7011.    Arguments:   color       - Optional character string color setting in
  7012.                               which to display error messages.  If omitted or
  7013.                               an invalid value is passed, the default color
  7014.                               is IF( ISCOLOR(), "W+/R", "N/W" ) 
  7015.  
  7016.                 msg1        - Optional character string first line message to
  7017.                               appear in the error box if an error occurs.  If
  7018.                               omitted or an invalid parameter is passed, the
  7019.                               default messages shown below are used.
  7020.  
  7021.                 msg2        - Optional character string second line message
  7022.                               to appear in the error box if an error occurs. 
  7023.                               If omitted or an invalid parameter is passed,
  7024.                               the default messages shown below are used.
  7025.  
  7026.                 msg3        - Optional character string third line message to
  7027.                               appear in the error box if an error occurs.  If
  7028.                               omitted or an invalid parameter is passed, the
  7029.                               default messages shown below are used.
  7030.  
  7031.    Returns:     True if an APPEND BLANK operation is NOT successful.  A
  7032.                 return value of False indicates a record was successfully
  7033.                 appended.
  7034.  
  7035.    Description: This function, if successful, will append a blank record to
  7036.                 the currently selected database file.  NO_APPEND() is most
  7037.                 commonly used in a network environment to provide run time
  7038.                 recovery options from append failures because of file/record
  7039.                 locking conflicts, or from disk failures.  It is simpler to
  7040.                 use because it packages the APPEND BLANK command into a loop
  7041.                 which will test for NETERR() and allow retry or abort.
  7042.  
  7043.    Notes:       In a network environment NO_APPEND() abides by the same
  7044.                 record and file lock logistics as APPEND BLANK.  If
  7045.                 successful, a record lock is left in place on the newly
  7046.                 appended record unless a file lock was previously in place,
  7047.                 in which case the file lock is left intact.
  7048.  
  7049.                 The NO_APPEND() return value is the reverse of True
  7050.                 indicating success.  True indicates failure, False success. 
  7051.                 The advantage of this approach is apparent during coding
  7052.                 because most often, specific branch action is taken if an
  7053.                 append fails.  See the example for details.
  7054.  
  7055.                 The default first, second, and third line messages that
  7056.                 appear in the BOXASK() message box are as follows:
  7057.  
  7058.  
  7059.  
  7060.  
  7061.    RLIB Function Reference                                                114
  7062.  
  7063.  
  7064.                      ┌────────────────────────────────────────────────┐
  7065.                      │                                                │
  7066.                      │              Append record failed!             │
  7067.                      │     Another user must have this file locked    │
  7068.                      │           Do you want to re-try? (Y/n)         │
  7069.                      │                                                │
  7070.                      └────────────────────────────────────────────────┘
  7071.  
  7072.                 You should use the default messages unless you ensure that
  7073.                 the message you give will let the user know they have the
  7074.                 option to re-try the append operation.
  7075.  
  7076.                 The default answer to the third line prompt is YES, retry. 
  7077.                 This will keep the append attempt in a loop.  The function
  7078.                 used to get this response is BOXASK() and is set with a
  7079.                 timeout value of 30 seconds.  If the user does not respond
  7080.                 within this time, the function will timeout and attempt to do
  7081.                 the append.  This allows an append error condition to
  7082.                 automatically recover without user intervention (like in the
  7083.                 middle of the night!)  If you program batch mode operations
  7084.                 and must ensure that the program does not enter a loop, use
  7085.                 the APPEND BLANK, command directly then test for NETERR(). 
  7086.                 See the Clipper manual section on networking operations.
  7087.  
  7088.                 If you want to skip the first color parameter and get at the
  7089.                 following message parameters, as in all cases, pass a dummy
  7090.                 parameter for the color.  Although the color parameter is
  7091.                 character in type, a null dummy ("") will work fine since the
  7092.                 parameter is tested with the TYPEC() function which not only
  7093.                 verifies that it is a character type, but that it is not
  7094.                 blank (as is a null).
  7095.  
  7096.    Example:     *-- store empty field values for a new record
  7097.                 MEMORIZE(.T.)
  7098.  
  7099.                 *-- get the data
  7100.                 @ 1,0 SAY "Enter full name" GET M->name
  7101.                 @ 2,0 SAY "Enter birthdate" GET M->birthdate
  7102.                 @ 3,0 SAY "Enter age      " GET M->age  PICTURE "##"
  7103.                 *-- remember to always PICTURE numeric memory variables!
  7104.                 READ
  7105.  
  7106.                 *-- now add the new record and put in the data
  7107.                 IF NO_APPEND()
  7108.                    SAYINBOX( "R/W", "Record not saved!" )
  7109.                 ELSE
  7110.                    MREPLACE()
  7111.                 ENDIF
  7112.                 *-- now release the public variables!
  7113.                 FORGET()
  7114.  
  7115.    Source:      RL_NO_AP.PRG
  7116.  
  7117.    See also:    OPENED(), NO_FLOCK(), NO_RLOCK(), TYPEC()
  7118.  
  7119.  
  7120.    RLIB Function Reference                                                115
  7121.  
  7122.  
  7123.    Function:    NO_FLOCK()
  7124.  
  7125.    Purpose:     Network file lock function with specific error trapping
  7126.  
  7127.    Syntax:      NO_FLOCK( [ alias [, color [, msg1 [, msg2 [, msg3 ]]]]] )
  7128.  
  7129.    Arguments:   alias       - Optional character string work area alias name
  7130.                               to lock.  If omitted or an invalid parameter is
  7131.                               passed the default is the current work area.
  7132.  
  7133.                 color       - Optional character string color setting in
  7134.                               which to display error messages.  If omitted or
  7135.                               an invalid value is passed, the default color
  7136.                               is IF( ISCOLOR(), "W+/R", "N/W" ) 
  7137.  
  7138.                 msg1        - Optional character string first line message to
  7139.                               appear in the error box if an error occurs.  If
  7140.                               omitted or an invalid parameter is passed, the
  7141.                               default messages shown below are used.
  7142.  
  7143.                 msg2        - Optional character string second line message
  7144.                               to appear in the error box if an error occurs. 
  7145.                               If omitted or an invalid parameter is passed,
  7146.                               the default messages shown below are used.
  7147.  
  7148.                 msg3        - Optional character string third line message to
  7149.                               appear in the error box if an error occurs.  If
  7150.                               omitted or an invalid parameter is passed, the
  7151.                               default messages shown below are used.
  7152.  
  7153.    Returns:     True if a lock on the database file in the currently selected
  7154.                 work area failed.  A return value of false indicates the file
  7155.                 lock was placed successfully.
  7156.  
  7157.    Description: NO_FLOCK() is a network database function that simplifies the
  7158.                 tedious task of network database locking mechanics.  This
  7159.                 function, if successful, will place a Clipper FLOCK() on the
  7160.                 database file in the current work area, or upon the file in
  7161.                 the work area designated by the parameter ALIAS.  NO_FLOCK()
  7162.                 will return to the current select area if an alias is given.
  7163.  
  7164.                 The benefit of using NO_FLOCK() over a simple FLOCK() call is
  7165.                 the automatic re-try built into NO_FLOCK().  If the file lock
  7166.                 fails the user is presented with a BOXASK() message
  7167.                 indicating that they may re-try or cancel the attempt.  This
  7168.                 BOXASK() message will timeout after 30 seconds and re-try the
  7169.                 FLOCK().
  7170.  
  7171.    Notes:       The default first, second and third line messages that appear
  7172.                 in the BOXASK() message box are as follows:
  7173.  
  7174.  
  7175.  
  7176.  
  7177.  
  7178.  
  7179.    RLIB Function Reference                                                116
  7180.  
  7181.  
  7182.                      ┌────────────────────────────────────────────────┐
  7183.                      │                                                │
  7184.                      │                File lock failed!               │
  7185.                      │     Another user must have this file locked    │
  7186.                      │           Do you want to re-try? (Y/n)         │
  7187.                      │                                                │
  7188.                      └────────────────────────────────────────────────┘
  7189.  
  7190.  
  7191.                 If you want to supply your own message(s) but do not want to
  7192.                 designate a different alias other that the current work area,
  7193.                 you may either supply the current work area alias as the
  7194.                 first parameter (ALIAS()), or pass an invalid argument such
  7195.                 as a null string or a logical.
  7196.  
  7197.                 You should use the default messages unless you make sure the
  7198.                 message you give will let the user know they have the option
  7199.                 to re-try.
  7200.  
  7201.                 If an invalid alias name is supplied as the first parameter,
  7202.                 i.e.  the work area alias name is not in use, NO_FLOCK() will
  7203.                 return .T. and set the appropriate RLIBERROR() value.
  7204.  
  7205.                 The default answer to the third line prompt is YES, retry. 
  7206.                 This will keep the lock attempt in a loop.  The function used
  7207.                 to get this response is BOXASK() and is set with a timeout
  7208.                 value of 30 seconds.  If the user does not respond within
  7209.                 this time, the function will timeout and attempt to do the
  7210.                 file lock.  This allows a lock error condition to
  7211.                 automatically recover without user intervention (like in the
  7212.                 middle of the night!) 
  7213.  
  7214.    Example:     *-- place a file lock to perform a REPLACE ALL
  7215.                 IF NO_FLOCK()
  7216.                    BOXASK( "File unavailable for update at this time",;
  7217.                             "Press any key to continue" )
  7218.                 ELSE
  7219.                    REPLACE ALL flag_field WITH "*"
  7220.                    UNLOCK                           && !!!!!!!
  7221.                 ENDIF
  7222.  
  7223.  
  7224.                 *-- another example: lock two database files at one time
  7225.                 IF NO_FLOCK("Customer") .OR.  NO_FLOCK("Orders")
  7226.                    BOXASK( "File unavailable for update at this time",;
  7227.                             "Press any key to continue" )
  7228.                 ELSE
  7229.                    *-- do multiple updates here
  7230.                    UNLOCK ALL
  7231.                 ENDIF
  7232.  
  7233.    Source:      RL_NO_FL.PRG
  7234.  
  7235.    See also:    OPENED(), NO_APPEND(), NO_RLOCK()
  7236.  
  7237.  
  7238.    RLIB Function Reference                                                117
  7239.  
  7240.  
  7241.    Function:    NO_RLOCK()
  7242.  
  7243.    Purpose:     Network record lock function with specific error trapping
  7244.  
  7245.    Syntax:      NO_RLOCK( [ alias [, color [, msg1 [, msg2 [, msg3 ]]]]] )
  7246.  
  7247.    Arguments:   alias       - Optional character string work area alias name
  7248.                               to lock.  If omitted or an invalid parameter is
  7249.                               passed the default is the current work area.
  7250.  
  7251.                 color       - Optional character string color setting in
  7252.                               which to display error messages.  If omitted or
  7253.                               an invalid value is passed, the default color
  7254.                               is IF( ISCOLOR(), "W+/R", "N/W" ) 
  7255.  
  7256.                 msg1        - Optional character string first line message to
  7257.                               appear in the error box if an error occurs.  If
  7258.                               omitted or an invalid parameter is passed, the
  7259.                               default messages shown below are used.
  7260.  
  7261.                 msg2        - Optional character string second line message
  7262.                               to appear in the error box if an error occurs. 
  7263.                               If omitted or an invalid parameter is passed,
  7264.                               the default messages shown below are used.
  7265.  
  7266.                 msg3        - Optional character string third line message to
  7267.                               appear in the error box if an error occurs.  If
  7268.                               omitted or an invalid parameter is passed, the
  7269.                               default messages shown below are used.
  7270.  
  7271.    Returns:     True if a lock on the database record in the currently
  7272.                 selected work area failed.  A return value of False indicates
  7273.                 that the lock was placed successfully.
  7274.  
  7275.    Description: NO_RLOCK() is a network database function that simplifies the
  7276.                 tedious task of network database locking mechanics.  This
  7277.                 function, if successful, will place a Clipper RLOCK() on the
  7278.                 database record in the current work area, or upon the file in
  7279.                 the work area designated by the parameter ALIAS.  NO_RLOCK()
  7280.                 will return to the current select area if an alias is given.
  7281.  
  7282.                 The benefit of using NO_RLOCK() over a simple RLOCK() call is
  7283.                 the automatic re-try built into NO_RLOCK().  If the record
  7284.                 lock fails the user is presented with a BOXASK() message
  7285.                 indicating that they may re-try or cancel the attempt.  This
  7286.                 BOXASK() message will timeout after 30 seconds and re-try the
  7287.                 RLOCK().
  7288.  
  7289.    Notes:       The default first, second, and third line messages that
  7290.                 appear in the BOXASK() message box are as follows:
  7291.  
  7292.  
  7293.  
  7294.  
  7295.  
  7296.  
  7297.    RLIB Function Reference                                                118
  7298.  
  7299.  
  7300.                 ┌─────────────────────────────────────────────────────────┐
  7301.                 │                                                         │
  7302.                 │                      Lock failed!                       │
  7303.                 │    Another user must have this file or record locked    │
  7304.                 │               Do you want to re-try? (Y/n)              │
  7305.                 │                                                         │
  7306.                 └─────────────────────────────────────────────────────────┘
  7307.  
  7308.  
  7309.                 If you want to supply your own message(s) but do not want to
  7310.                 designate a different alias other that the current work area,
  7311.                 you may either supply the current work area alias as the
  7312.                 first parameter (ALIAS()), or pass an invalid argument such
  7313.                 as a null string or a logical.
  7314.  
  7315.                 You should use the default messages unless you make sure the
  7316.                 message you give will let the user know they have the option
  7317.                 to re-try.
  7318.  
  7319.                 If an invalid alias name is supplied as the first parameter,
  7320.                 i.e.  the work area alias name is not in use, NO_RLOCK() will
  7321.                 return .T. and set the appropriate RLIBERROR() value.
  7322.  
  7323.                 The default answer to the third line prompt is YES, retry. 
  7324.                 This will keep the lock attempt in a loop.  The function used
  7325.                 to get this response is BOXASK() and is set with a timeout
  7326.                 value of 30 seconds.  If the user does not respond within
  7327.                 this time, the function will timeout and attempt to do the
  7328.                 file lock.  This allows a lock error condition to
  7329.                 automatically recover without user intervention (like in the
  7330.                 middle of the night!) 
  7331.  
  7332.    Example:     *-- place a record lock to perform a REPLACE
  7333.                 IF NO_RLOCK()
  7334.                    BOXASK( "Record unavailable for update at this time",;
  7335.                             "Press any key to continue" )
  7336.                 ELSE
  7337.                    REPLACE flag_field WITH "U"
  7338.                    UNLOCK                        && !!!!!!!
  7339.                 ENDIF
  7340.  
  7341.                 *-- Example #2: lock two database file records at one time
  7342.                 IF NO_RLOCK("Customer") .OR.  NO_RLOCK("Orders")
  7343.                    BOXASK( "Record unavailable for update at this time",;
  7344.                            "Press any key to continue" )
  7345.                 ELSE
  7346.                    REPLACE CUSTOMER->lastorder WITH DATE(),;
  7347.                            ORDERS->count WITH ORDERS->count + 1
  7348.                    UNLOCK ALL
  7349.                 ENDIF
  7350.  
  7351.    Source:      RL_NO_RL.PRG
  7352.  
  7353.    See also:    OPENED(), NO_APPEND(), NO_FLOCK()
  7354.  
  7355.  
  7356.    RLIB Function Reference                                                119
  7357.  
  7358.  
  7359.    Function:    NOTEMPTY()
  7360.  
  7361.    Purpose:     Generic function to validate that data was entered in a field
  7362.  
  7363.    Syntax:      NOTEMPTY( expression )
  7364.  
  7365.    Arguments:   expression  - An expression of any type to test if is EMPTY()
  7366.  
  7367.  
  7368.    Returns:     True if <expression> is NOT an empty value.
  7369.  
  7370.    Description: NOTEMPTY() is usually used in the VALID clause of an @
  7371.                 READ...  GET...  VALID statement to force data entry in the
  7372.                 GET field.  NOTEMPTY() simplifies this chore and provides a
  7373.                 consistent generic error message when all that is needed is a
  7374.                 prompt that the field may not be blank.
  7375.  
  7376.    Notes:       All NOTEMPTY() does is call the EMPTY() function to test if
  7377.                 <expression> is empty.  However, NOTEMPTY() goes one step
  7378.                 further by packaging a BOXASK() error message if EMPTY()
  7379.                 returns True.  The error message is as follows: 
  7380.  
  7381.                             ┌──────────────────────────────────────┐
  7382.                             │                                      │
  7383.                             │     This field may not be blank!     │
  7384.                             │      Press any key to continue       │
  7385.                             │                                      │
  7386.                             └──────────────────────────────────────┘
  7387.  
  7388.                 NOTEMPTY() will also BUZZ(), then the BOXASK() message will
  7389.                 timeout after three (3) seconds.
  7390.  
  7391.                 The message is displayed in color IF(ISCOLOR(),"W+/R","N/W") 
  7392.  
  7393.    Example:     *-- set up a READ requiring all fields to be entered
  7394.                 @ 1,0 SAY "Full name:" GET name    VALID NotEmpty(name)
  7395.                 @ 2,0 SAY "Address:  " GET address VALID NotEmpty(address)
  7396.                 READ
  7397.  
  7398.    Source:      RL_NOTEM.PRG
  7399.  
  7400.    See also:    ANYCHARSIN(), BUZZ(), ISFIELD()
  7401.  
  7402.  
  7403.  
  7404.  
  7405.  
  7406.  
  7407.  
  7408.  
  7409.  
  7410.  
  7411.  
  7412.  
  7413.  
  7414.  
  7415.    RLIB Function Reference                                                120
  7416.  
  7417.  
  7418.    Function:    NTXKEYVAL()
  7419.  
  7420.    Purpose:     Get the controlling index key value of the current record
  7421.  
  7422.    Syntax:      NTXKEYVAL()
  7423.  
  7424.    Arguments:   None 
  7425.  
  7426.    Returns:     The value of the current database record index key, of a type
  7427.                 determined by the type of field in the index key expression.
  7428.  
  7429.    Description: This function allows you to easily get the value of an index
  7430.                 key field from the currently selected database.  It is handy
  7431.                 in place of using the INDEXKEY() function and subsequent
  7432.                 macro substitution.
  7433.  
  7434.    Notes:       If no database file is open, or no index file is open,
  7435.                 NTXKEYVAL() returns a null string ("").
  7436.  
  7437.                 NTXKEYVAL() returns the value of the index key expression,
  7438.                 not the index expression string.  It is used to evaluate the
  7439.                 index key for the current record of the currently selected
  7440.                 database.  Retrieving the value of the index key field is
  7441.                 useful if you have applications that list records on the
  7442.                 screen.
  7443.  
  7444.                 For instance, while using PICKREC(), you may want to instruct
  7445.                 PICKREC() to refresh the screen if, after a record was
  7446.                 edited, the value of a field used as part of the controlling
  7447.                 index expression was changed.  This is because changing such
  7448.                 a record causes the order of the database to appear
  7449.                 different.  NTXKEYVAL() can be used to retrieve the value of
  7450.                 the key field before and after the edit.  If changed,
  7451.                 PICKREC() can be instructed to repaint the screen with a
  7452.                 <row> value of -1.
  7453.  
  7454.    Example:     *-- index a database with a 12 character long Name field
  7455.                 *-- and a 6 character serial number field
  7456.                 INDEX ON Name+Serialnum TO myindex
  7457.                 SEEK "Low"
  7458.                 ? INDEXKEY()            && returns "Name+Serialnum"
  7459.                 ? INDEXKEYVAL()         && returns "Low         12345 "
  7460.  
  7461.                 *------------------------------------------------------------
  7462.                 *-- test if and index key field was changed during an edit
  7463.                 *-- save the index key value for comparison
  7464.                 savekey = NTXKEYVAL()
  7465.                 @ x,y GET keyfield
  7466.                 READ
  7467.                 *-- see if an index key field was changed in the process
  7468.                 IF savekey != NTXKEYVAL()
  7469.                    *-- do corrective things
  7470.                 ENDIF
  7471.  
  7472.  
  7473.  
  7474.    RLIB Function Reference                                                121
  7475.  
  7476.  
  7477.                 *------------------------------------------------------------
  7478.                 mrow = 0
  7479.                 DO WHILE .T.
  7480.                    FPROMPT(" ─┘=Edit,Ins=Insert,Del=Delete,Esc=Exit")
  7481.                    mrow =PICKREC(1,0,20,79,"CUSTOMER->Name","","",mrow,.F.,1)
  7482.                    DO CASE
  7483.                    CASE LASTKEY() = 27          && Escape
  7484.                       EXIT
  7485.  
  7486.                    CASE LASTKEY() = 22          && Insert
  7487.                       newrec = .T.
  7488.  
  7489.                    CASE ( BOF() .OR.  EOF() )   && a record must exist
  7490.                       LOOP
  7491.  
  7492.                    CASE LASTKEY() = 13          && Enter
  7493.                       savekey = NTXKEYVAL()     && save current key value
  7494.                       DO EditRoutine
  7495.                       IF savekey != NTXKEYVAL() && did it change
  7496.                          mrow = -1              && refill box from top
  7497.                       ENDIF
  7498.  
  7499.                    CASE LASTKEY() = 7           && Delete key
  7500.                       BLIP()
  7501.                       IF BOXASK("Delete record? (Y/N) ")="Y"
  7502.                          IF .NOT.  NO_RLOCK()
  7503.                             DELETE
  7504.                             UNLOCK
  7505.                             mrow = 0            && force PICKREC() refresh
  7506.                          ENDIF
  7507.                       ENDIF
  7508.                       LOOP
  7509.  
  7510.                    OTHERWISE                    && trap other exits
  7511.                       LOOP
  7512.  
  7513.                    ENDCASE
  7514.                 ENDDO
  7515.  
  7516.    Source:      RL_NTXKE.PRG
  7517.  
  7518.    See also:    PICKREC()
  7519.  
  7520.  
  7521.  
  7522.  
  7523.  
  7524.  
  7525.  
  7526.  
  7527.  
  7528.  
  7529.  
  7530.  
  7531.  
  7532.  
  7533.    RLIB Function Reference                                                122
  7534.  
  7535.  
  7536.    Function:    OLDERFILE()
  7537.  
  7538.    Purpose:     Determine the older of two disk files.
  7539.  
  7540.    Syntax:      OLDERFILE( file1, file2 [, timedigits ] )
  7541.  
  7542.    Arguments:   file1       - Character string or variable indicating the
  7543.                               name of the file to compare with <file2> to
  7544.                               determine which is older. 
  7545.  
  7546.                 file2       - Character string or variable indicating the
  7547.                               name of the file to compare with <file1> to
  7548.                               determine which is older.
  7549.  
  7550.                 timedigits  - Numeric value indicating the number of
  7551.                               significant digits in the file time character
  7552.                               string to use.  If not specified or an invalid
  7553.                               parameter is passed the default of 5
  7554.                               significant digits is used which yields time
  7555.                               comparison to the minutes ("10:01") 
  7556.  
  7557.    Returns:     A numeric value indicating one of the following: 
  7558.  
  7559.                              0 = file dates and times are equal
  7560.                              1 = file 1 is older than file 2
  7561.                              2 = file 2 is older than file 1
  7562.                             -1 = file 1 does not exist
  7563.                             -2 = file 2 does not exist
  7564.                             -3 = Other (syntax error) 
  7565.  
  7566.    Description: OLDERFILE() is a file function useful for easily comparing
  7567.                 two files to determine which file is older.  Alternately, it
  7568.                 can be used to quickly test if two files share the same file
  7569.                 date and time stamp.
  7570.  
  7571.    Notes:       Time precision is only accurate to seconds, not hundredths of
  7572.                 seconds.  It is VERY unlikely that two files will have the
  7573.                 exact same creation time to the second much less the
  7574.                 hundredths of a second, hence the default time string
  7575.                 precision is to 5 digits.  To get accuracy to the second make
  7576.                 the precision 8 (10:00:00), to hundredths of seconds make the
  7577.                 precision 11 (10:00:00.00) 
  7578.  
  7579.                 OLDERFILE() uses the RLIB functions FILEDATE() and FILETIME()
  7580.                 to extract file dates/times from the DOS directory
  7581.                 information.  File date and time stamps are subject to the
  7582.                 limitations posed by DOS's maintenance schedule.  In other
  7583.                 words, if a file is already open, the date and/or time stamp
  7584.                 from the directory information may not be updated until the
  7585.                 file is closed.
  7586.  
  7587.    Example:     *-- check if database file was updated since last indexed
  7588.                 IF OlderFile("myfile.dbf", "myfile.ntx") = 1
  7589.                    *-- reindex here
  7590.  
  7591.  
  7592.    RLIB Function Reference                                                123
  7593.  
  7594.  
  7595.                    *-- or do something else
  7596.                 ENDIF
  7597.  
  7598.    Source:      RL_OLDER.PRG
  7599.  
  7600.    See also:    FILEDATE(), FILES(), FILETIME()
  7601.  
  7602.  
  7603.  
  7604.  
  7605.  
  7606.  
  7607.  
  7608.  
  7609.  
  7610.  
  7611.  
  7612.  
  7613.  
  7614.  
  7615.  
  7616.  
  7617.  
  7618.  
  7619.  
  7620.  
  7621.  
  7622.  
  7623.  
  7624.  
  7625.  
  7626.  
  7627.  
  7628.  
  7629.  
  7630.  
  7631.  
  7632.  
  7633.  
  7634.  
  7635.  
  7636.  
  7637.  
  7638.  
  7639.  
  7640.  
  7641.  
  7642.  
  7643.  
  7644.  
  7645.  
  7646.  
  7647.  
  7648.  
  7649.  
  7650.  
  7651.    RLIB Function Reference                                                124
  7652.  
  7653.  
  7654.    Function:    OPENED()
  7655.  
  7656.    Purpose:     Open one or more databases with network error checking.
  7657.  
  7658.    Syntax:      OPENED( [ errorFlag ] database [ ...  database10 ] )
  7659.  
  7660.    Arguments:   errorFlag   - Optional LOGICAL value which if true will cause
  7661.                               automatic error messages to be displayed.  The
  7662.                               default value is True.
  7663.  
  7664.                 database    - Character string similar in form to that
  7665.                               supplied to the USE command.  This string may
  7666.                               contain one or more INDEX files, and ALIAS name
  7667.                               specifier and an EXCLUSIVE or SHAREABLE keyword
  7668.                               qualifier.  Up to 10 database parameter strings
  7669.                               may be passed allowing up to 10 files to be
  7670.                               opened at once.
  7671.  
  7672.    Returns:     True if all files were opened successfully, false otherwise. 
  7673.                 If a false is returned an errorlevel is also passed via the
  7674.                 RlibError() function.  See below for specific error values.
  7675.  
  7676.    Description: OPENED() is a database function which lets you open several
  7677.                 database files and indexes with one call!  It also checks to
  7678.                 make sure everything opened ok before returning.  If any one
  7679.                 of the file opens fails, all files opened thus far in the
  7680.                 call to OPENED() are closed, and a false (and RlibError())
  7681.                 are returned.  This is primarily intended to aid the
  7682.                 developer in dealing with opening multiple databases in a
  7683.                 network environment where error trapping is critical. 
  7684.                 OPENED() eliminates the messy and cumbersome nested IF
  7685.                 statements necessary to ensure proper error trapping. 
  7686.                 OPENED() can also benefit the single user developer by
  7687.                 greatly reducing the amount of code needed to open files and
  7688.                 indexes.  See the example below for sample syntax and the
  7689.                 amount of coding it can save! 
  7690.  
  7691.    Notes:       OPENED() works by parsing each of up to ten parameters, one
  7692.                 at a time.  Each parameter is first verified to be character
  7693.                 then left and right trimmed and converted to upper case. 
  7694.                 Next, each parameter is checked for the following keyword
  7695.                 strings: 
  7696.  
  7697.                 " ALIAS "     -- An alias name was specified.
  7698.                 " INDEX "     -- Index file(s) are to be opened.
  7699.                 " EXCLUSIVE"  -- File is to be opened in exclusive mode.
  7700.                 " SHAREABLE"  -- File is to be opened in shareable mode.
  7701.  
  7702.                 The exclusive and shareable keywords are EXPLICIT
  7703.                 instructions.  This means that OPENED() will use the current
  7704.                 default state of SET EXCLUSIVE unless either of these flags
  7705.                 is specified.  Since there is no way in native Summer '87
  7706.                 Clipper to query the status of SET EXCLUSIVE, OPENED() cannot
  7707.                 change the setting and return it to its incoming state.  This
  7708.  
  7709.  
  7710.    RLIB Function Reference                                                125
  7711.  
  7712.  
  7713.                 is one area where OPENED() is not black boxed.  (For
  7714.                 compatibility reasons, the Clipper 5.0 version of OPENED()
  7715.                 will NOT save and restore the setting of SET EXCLUSIVE.  Some
  7716.                 applications may come to expect the state of SET EXCLUSIVE to
  7717.                 be as the last call to OPENED() left it).
  7718.  
  7719.                 Work area selection: 
  7720.  
  7721.                 Upon successful completion, OPENED() leaves the last database
  7722.                 specified as the currently selected work area.  If OPENED()
  7723.                 fails, the work area selected upon entry is re-selected, and
  7724.                 all files OPENED() may have successfully opened are closed.
  7725.  
  7726.                 Important points: 
  7727.  
  7728.                 1.  Index file names MUST be separated by commas, not spaces.
  7729.                 2.  Four letter abbreviations such as INDE are NOT allowed.
  7730.  
  7731.                 Parameter sequence: 
  7732.  
  7733.                 The order in which the keyword string ALIAS, INDEX,
  7734.                 EXCLUSIVE, and SHAREABLE is arbitrary.  The only requirement
  7735.                 is that, naturally, the name of the database file to open is
  7736.                 the first part of the string.
  7737.  
  7738.                 Any of the parameters may be a logical value.  If a logical
  7739.                 parameter is encountered, its value is used to set the flag
  7740.                 whether or not automatic error messages are displayed.  The
  7741.                 default state is true which means that if a file is not
  7742.                 found, or and index file is not present, or a file open
  7743.                 fails, then an error message will be displayed before
  7744.                 OPENED() stops and returns .F.  (plus setting RLIBERROR()). 
  7745.                 If this flag is set to false, then error messages will not be
  7746.                 generated, only a return value will signal your application
  7747.                 which may then generate its own error messages.
  7748.  
  7749.                 These logical values may be listed multiple times, the status
  7750.                 takes effect on all files opened after the logical value is
  7751.                 encountered.
  7752.  
  7753.                 One interesting side effect of turning automatic error
  7754.                 messages off is that the user will not have the option of
  7755.                 re-trying to open a file in a network environment, if the
  7756.                 open failed due to an exclusive use conflict; OPENED() will
  7757.                 simply fail and return .F.  plus RlibError() = 1101.
  7758.  
  7759.                 RLIBERROR() return values: 
  7760.  
  7761.                 The possible RlibError() return values from OPENED() are:
  7762.  
  7763.  
  7764.  
  7765.  
  7766.  
  7767.  
  7768.  
  7769.    RLIB Function Reference                                                126
  7770.  
  7771.  
  7772.                    0  =  Success
  7773.                 1101  =  File sharing violation
  7774.                 1102  =  Database .DBF file not found
  7775.                 1103  =  Associated .NTX file not found
  7776.                 1104  =  Associated .DBT file not found (future)
  7777.                 1105  =  Invalid alias name syntax or other syntax error
  7778.  
  7779.                 These error values are established to be in an increasing
  7780.                 order of severity.  Normally an error level of 1101 means
  7781.                 that the file was not available in a network environment. 
  7782.                 Error levels of 1102, 1103, or 1104 indicate that a run-time
  7783.                 file is not present.  This is usually recoverable by
  7784.                 correcting the situation outside of the program.  An
  7785.                 errorlevel of 1105 or above is intended to indicate a calling
  7786.                 program syntax problem.
  7787.  
  7788.    Example:     *-- Open three dbf's and indexes in various modes with error
  7789.                 *-- reports in a network environment.  See how simple it is!
  7790.  
  7791.                 d1= "cust ALIAS Customers INDEX custName, custNumb SHAREABLE"
  7792.                 d2= "invt ALIAS Inventory INDEX invtNumb, invtDesc SHAREABLE"
  7793.                 d3= "tempdbf.001 INDEX tempntx.001 ALIAS Tempfile EXCLUSIVE"
  7794.                 IF .NOT.  OPENED( d1, d2, d3 )
  7795.                    RETURN
  7796.                 ENDIF
  7797.                 *-- ALL DONE!!!!!!!!!!!!!
  7798.  
  7799.  
  7800.                 *-- =============  T H E   O L D   W A Y  =============
  7801.                 *-- Look at all this monstrous code!  Yecch!  Use OPENED()!
  7802.                 SET EXCLUSIVE OFF
  7803.                 IF ! (FILE("cust.dbf")     .AND. FILE("invt.dbf")     .AND.;
  7804.                       FILE("tempdbf.001")  .AND. FILE("custname.ntx") .AND.;
  7805.                       FILE("custnumb.ntx") .AND. FILE("invtnumb.ntx") .AND.;
  7806.                       FILE("invtdesc.ntx") .AND. FILE("tempntx.001"))
  7807.                    *-- You think this is overkill?  What happens if one file
  7808.                    *-- gets deleted from under your nose on a network?
  7809.                    BUZZ(2)
  7810.                    BOXASK( "W+/R", "Required file(s) are missing" )
  7811.                    RETURN
  7812.                 ENDIF
  7813.  
  7814.                 *-- we've only just begun, lots of code still must follow!
  7815.                 SET EXCLUSIVE OFF
  7816.                 SELECT 0
  7817.                 DO WHILE .T.
  7818.                    USE cust ALIAS Customers
  7819.                    IF .NOT.  NETERR()
  7820.                       EXIT
  7821.                    ENDIF
  7822.                    IF BOXASK( "File in use by another.  Re-try?", 30 ) = "N"
  7823.                       RETURN
  7824.                    ENDIF
  7825.                 ENDDO
  7826.  
  7827.  
  7828.    RLIB Function Reference                                                127
  7829.  
  7830.  
  7831.                 SET INDEX TO custname, custnumb
  7832.  
  7833.                 SELECT 0
  7834.                 DO WHILE .T.
  7835.                    USE invt ALIAS Inventory
  7836.                    IF .NOT.  NETERR()
  7837.                       EXIT
  7838.                    ENDIF
  7839.                    IF BOXASK( "File in use by another.  Re-try?", 30 ) = "N"
  7840.                       CLOSEAREA("Customers")
  7841.                       RETURN
  7842.                    ENDIF
  7843.                 ENDDO
  7844.                 SET INDEX TO invtNumb, invtDesc
  7845.  
  7846.                 SELECT 0
  7847.                 SET EXCLUSIVE ON
  7848.                 DO WHILE .T.
  7849.                    USE tempdbf.001 ALIAS Tempfile
  7850.                    IF .NOT.  NETERR()
  7851.                       EXIT
  7852.                    ENDIF
  7853.                    IF BOXASK( "File in use by another.  Re-try?", 30 ) = "N"
  7854.                       CLOSEAREA("Customers", "Inventory")
  7855.                       RETURN
  7856.                    ENDIF
  7857.                 ENDDO
  7858.                 SET INDEX TO tempntx.001
  7859.                 *-- FINALLY, we're done!  Yech, what a pile of code!
  7860.  
  7861.    Source:      RL_OPENE.PRG
  7862.  
  7863.    See also:    BOXASK(), CLOSEAREA(), RLIBERROR()
  7864.  
  7865.  
  7866.  
  7867.  
  7868.  
  7869.  
  7870.  
  7871.  
  7872.  
  7873.  
  7874.  
  7875.  
  7876.  
  7877.  
  7878.  
  7879.  
  7880.  
  7881.  
  7882.  
  7883.  
  7884.  
  7885.  
  7886.  
  7887.    RLIB Function Reference                                                128
  7888.  
  7889.  
  7890.    Function:    PARENT()
  7891.  
  7892.    Purpose:     Retrieve the parent directory for a specified directory.
  7893.  
  7894.    Syntax:      PARENT( [ directory ] )
  7895.  
  7896.    Arguments:   directory   - Optional character string indicating the name
  7897.                               of the directory whose parent directory you
  7898.                               wish to find.  If not specified or an invalid
  7899.                               parameter is passed, the current directory is
  7900.                               assumed.
  7901.  
  7902.    Returns:     A character string indicating the name of the parent
  7903.                 directory (i.e.  the directory above) the specified
  7904.                 directory.
  7905.  
  7906.    Description: PARENT() is an environment/character function used to parse a
  7907.                 directory name and return the name of the parent directory.
  7908.  
  7909.    Notes:       This can be useful in directory/file management routines when
  7910.                 you want to let a user navigate through the directory
  7911.                 structure.  Although you can get the names of sub-directories
  7912.                 with ADIR(), if you want to take them 'back up' a directory,
  7913.                 you have to get the current directory name, and strip it down
  7914.                 to find the parent directory part.  PARENT() makes this task
  7915.                 easy.
  7916.  
  7917.                 If the current or supplied directory is at the top level
  7918.                 (i.e.  the root directory), PARENT() will return '\'.
  7919.  
  7920.                 PARENT() will return the directory portion of a fully
  7921.                 qualified filename.  (See the third example)
  7922.  
  7923.    Example:     *-- if the current directory is \APPS\CLIPPER\TEST
  7924.                 ? PARENT()                             && "\APPS\CLIPPER"
  7925.  
  7926.                 *-- PARENT() with parameters
  7927.                 ? PARENT("C:\DOS\UTILITY")             && "C:\DOS"
  7928.                 ? PARENT("C:\CLIPPER\CLIPPER.EXE")     && "C:\CLIPPER"
  7929.  
  7930.    Source:      RL_PAREN.PRG
  7931.  
  7932.    See also:    PATHTO()
  7933.  
  7934.  
  7935.  
  7936.  
  7937.  
  7938.  
  7939.  
  7940.  
  7941.  
  7942.  
  7943.  
  7944.  
  7945.  
  7946.    RLIB Function Reference                                                129
  7947.  
  7948.  
  7949.    Function:    PATHTO()
  7950.  
  7951.    Purpose:     Search the DOS path for the path leading to a given filename.
  7952.  
  7953.    Syntax:      PATHTO( filename )
  7954.  
  7955.    Arguments:   filename    - Character string indicating the name of the
  7956.                               file to locate through the DOS path.
  7957.  
  7958.    Returns:     A character string indicating the path pointing to <filename>
  7959.                 plus a trailing backslash '\'.  If the file is not found
  7960.                 along the DOS path, a null string ("") is returned.
  7961.  
  7962.    Description: PATHTO() is an environment/character function used to search
  7963.                 the current DOS path to find the path pointing to <filename>. 
  7964.                 This can be used to build a fully qualified filename (such as
  7965.                 d:[path]filename) as a character string to be used to open a
  7966.                 file.  In the example below, a help file is kept in the same
  7967.                 drive and directory as the program (.EXE) file.  The path to
  7968.                 the .EXE file is found and used to point to the help file. 
  7969.                 This way, the help file can be located at runtime, provided
  7970.                 the .EXE file is in a directory that is in the DOS path.
  7971.  
  7972.    Notes:       PATHTO() only searches the DOS environment variable PATH so
  7973.                 it will only find files that are located in a drive or
  7974.                 directory that is listed in the path.
  7975.  
  7976.    Example:     *-- Example program name is DEMO.EXE, and help file is named
  7977.                 *-- DEMO.HLP and both are located in C:\MYAPPS.
  7978.                 *-- path=C:\;C:\DOS;C:\CLIPPER;C:\UTILITY;C:\MYAPPS
  7979.  
  7980.                 PROCEDURE Help
  7981.                 PARAMETERS a,b,c
  7982.                 helppath = PATHTO("demo.exe")       && returns "C:\MYAPPS\"
  7983.                 helpfile = helppath + "DEMO.HLP"    && "C:\MYAPPS\DEMO.HLP"
  7984.  
  7985.                 IF FILE(helpfile)
  7986.                    USE (helpfile)
  7987.                    *-- <help code goes here>
  7988.                 ENDIF
  7989.                 RETURN
  7990.  
  7991.    Source:      RL_PATHT.PRG
  7992.  
  7993.    See also:    PARENT()
  7994.  
  7995.  
  7996.  
  7997.  
  7998.  
  7999.  
  8000.  
  8001.  
  8002.  
  8003.  
  8004.  
  8005.    RLIB Function Reference                                                130
  8006.  
  8007.  
  8008.    Function:    PDOWNINIT()
  8009.  
  8010.    Purpose:     Initialize the PDOWNMENU() function for use.
  8011.  
  8012.    Syntax:      PDOWNINIT( row, columns, menus, items, starts ;
  8013.                            [, menu_msgs [, msg_row [, colors ;
  8014.                            [, altkeys [, canexit [, restscrn ]]]]]] ) 
  8015.  
  8016.    Arguments:   row         - Numeric value indicating the row on which the
  8017.                               top of the Pull Down Menu is to appear.  Value
  8018.                               may be between 0 and 24 (MAXROW() in the 5.0
  8019.                               version).  However, in practice the value will
  8020.                               usually be row number 0 or 1.
  8021.  
  8022.                 columns     - Array of numeric values indicating the column
  8023.                               number on which each top level menu option will
  8024.                               be displayed.  These column numbers control how
  8025.                               the options and their pull down menus are
  8026.                               spaced across the screen.
  8027.  
  8028.                 menus       - Array of character strings which will be used
  8029.                               as the top menu options displayed across the
  8030.                               top of the pull down menu.  Each <menu> element
  8031.                               will display at its corresponding <columns>
  8032.                               element number.  For example, Menu #2 will
  8033.                               display at coordinate position row,columns[2].
  8034.  
  8035.                 items       - Array of character strings which will be used
  8036.                               as the elements, or items, of each of the
  8037.                               pulled down menus.  This is a linear array with
  8038.                               each group of pull down menu items being
  8039.                               defined by a starting element number in the
  8040.                               <starts> array.
  8041.  
  8042.                 starts      - Array of starting element numbers.  Each
  8043.                               element in this array is a number which
  8044.                               indicates the starting position in the <items>
  8045.                               array at which each group of menu items begin. 
  8046.                               There should be one element for each
  8047.                               corresponding menu in the <menus> array.
  8048.  
  8049.                 menu_msgs   - Optional array of messages which correspond to
  8050.                               each of the menu choices in the <menus> array. 
  8051.                               There should be one element for each menu.  If
  8052.                               a menu message is to be blank (omitted), insert
  8053.                               a null string ("") as the element value.  If
  8054.                               omitted then no messages will display.
  8055.  
  8056.                 msg_row     - Optional numeric value which indicates the row
  8057.                               on which the messages contained in the
  8058.                               <menu_msgs> array are to appear.  If omitted or
  8059.                               a non-numeric value is supplied, the default
  8060.                               row is row 24.  (In the Clipper 5.0 version,
  8061.                               the default row is MAXROW()).
  8062.  
  8063.  
  8064.    RLIB Function Reference                                                131
  8065.  
  8066.  
  8067.                 colors      - Optional array of character strings indicating
  8068.                               the colors to use for the top bar and pull down
  8069.                               box menus.  Each element in the color array
  8070.                               table represents and controls the color for a 
  8071.                               separate part of the pull down menu system.
  8072.  
  8073.                               color[1] - Menu choices (item options)
  8074.                               color[2] - Menu selection bar
  8075.                               color[3] - Pull-down ACTIVE menu box
  8076.                               color[4] - Pull-down IN_ACTIVE menu box
  8077.                               color[5] - Menu choice item upon selection
  8078.                               color[6] - Messages displayed on <msg_row>
  8079.                               color[7] - Un-selectable option
  8080.                               color[8] - Top menu bar option upon selection
  8081.  
  8082.                 altkeys     - Optional array of character strings which
  8083.                               indicate the set of characters to use as
  8084.                               alternate select keys for each of the pull-down
  8085.                               menu choices.  There should be one element for
  8086.                               each corresponding menu.  If omitted, the
  8087.                               default direct select keys are the first letter
  8088.                               of each menu item.
  8089.  
  8090.                 canexit     - Optional logical value which indicates if
  8091.                               pressing the escape key will cause an exit of
  8092.                               the top level menu.  If omitted the default
  8093.                               value is false.
  8094.  
  8095.                 restscrn    - Optional logical value which indicates if the
  8096.                               screen area displaced by PDOWNMENU() is to be
  8097.                               used as the screen to restore on each "pull
  8098.                               down" side step.  The default is false.  See
  8099.                               the notes below for a more in-depth explanation
  8100.                               of this option.
  8101.  
  8102.    Returns:     True if initialization successful, false if parameters error.
  8103.  
  8104.    Description: PDOWNINIT() initializes PDOWNMENU() for operation and is
  8105.                 required to set up the variables used to control PDOWNMENU(). 
  8106.                 Since PDOWNMENU() has a lot of work to do, it is inefficient
  8107.                 to repeat many of the processes and parameter passing every
  8108.                 time the function is called.  Therefore, the pull down menu
  8109.                 function is split into an initialization routine and the main
  8110.                 menu routine.
  8111.  
  8112.                 A call to PDOWNINIT() establishes the working environment for
  8113.                 PDOWNMENU().  This working environment consists of such items
  8114.                 as the menu column coordinates, the underlying screen, menu
  8115.                 colors, and alternate select keys.  If this information had
  8116.                 to be passed to PDOWNMENU() on each call, which is many times
  8117.                 in a menu control loop, then the parameter passing and
  8118.                 parameter parsing overhead would slow PDOWNMENU() down
  8119.                 unnecessarily.
  8120.  
  8121.  
  8122.  
  8123.    RLIB Function Reference                                                132
  8124.  
  8125.  
  8126.    Notes:       Upon initialization, a PUBLIC array is established to hold
  8127.                 various environment information.  This array is named
  8128.                 RL_PD[], so check that this name does not conflict with any
  8129.                 others in your program.  To release this public array, and
  8130.                 clear the PDOWNMENU environment, issue the PDOWNINIT()
  8131.                 function with no parameters.  Although not absolutely
  8132.                 necessary, it is probably a good idea to release variables
  8133.                 and arrays that are not being used.
  8134.  
  8135.                 Optional parameters are not required but if you wish to skip
  8136.                 an optional parameter you must pass a dummy value.  The best
  8137.                 dummy value to use is a null string "".
  8138.  
  8139.                 The example that follows shows a basic menu and how simple it
  8140.                 is to construct a full featured pull down menu system.  For
  8141.                 an extensive example of the ultimate in menu options and
  8142.                 control, see the menu initialization routine in the Message
  8143.                 Reader demo program source code.
  8144.  
  8145.                 Changes from Version 2.0
  8146.  
  8147.                 All changes from version 2.0 are upward compatible.  You will
  8148.                 not need to modify any existing code.  However, you may want
  8149.                 to modify existing code to take advantage of the new
  8150.                 features.  The following sections list the changes that are
  8151.                 specific to some of the parameters, listing the parameter
  8152.                 name, an indicator of the change, and a description of the
  8153.                 change.
  8154.  
  8155.                 <starts> - Expanded from v2.0
  8156.  
  8157.                 If a zero is provided as the starting element number in the
  8158.                 <items> array for the associated menu number, then no pull
  8159.                 down menu will show for that top menu option.  This is useful
  8160.                 when you want a top menu option to be a single command all by
  8161.                 itself.
  8162.  
  8163.                 <menu_msgs> - Ignored in v2.0
  8164.  
  8165.                 Although specified in the documentation as the array of menu
  8166.                 ITEM messages, it was not used by PDOWNINIT().   This array
  8167.                 is now used by PDOWNMENU() as the list of messages for each
  8168.                 top (bar) menu option (not the pull-down menu items).  This
  8169.                 now gives you the capability of attaching a single line
  8170.                 message to each of the top menu choices as well as the
  8171.                 individual menu items in the sub-menus.
  8172.  
  8173.                 <menu_msgs> - Ignored in v2.0
  8174.  
  8175.                 The <msg_row> parameter was being ignored in version 2.0. 
  8176.                 This has now been corrected and is being used as the row on
  8177.                 which messages are display.  In version 2.0 messages were
  8178.                 always displayed on row 24.
  8179.  
  8180.  
  8181.  
  8182.    RLIB Function Reference                                                133
  8183.  
  8184.  
  8185.                 <colors> - Expanded
  8186.  
  8187.                 The colors array may now contain eight elements.  The sixth
  8188.                 element is now used as the color for displaying the optional
  8189.                 messages on <msg_row>.  These messages used to be displayed
  8190.                 in the same color as the menu options which was not always,
  8191.                 and rarely, desirable.  To maintain upward compatibility, the
  8192.                 color array table may remain at 6 elements however the 6th
  8193.                 element has changed from the top menu bar color on exit. 
  8194.                 (See my apology note below).  The 7th and 8th elements are
  8195.                 optional.  If the 7th element for un-selectable options color
  8196.                 is not given, then the Option color (element #1) is used.  If
  8197.                 the 8th element for the top menu bar on selection is not
  8198.                 provided, BRIGHT() is used.  The defaults for the menu colors
  8199.                 are as follows:
  8200.  
  8201.                 colors[1] - Current color
  8202.                 colors[2] - Enhanced color
  8203.                 colors[3] - BRIGHT() of current color
  8204.                 colors[4] - Current color
  8205.                 colors[5] - BRIGHT() of current color
  8206.                 colors[6] - Current color
  8207.                 colors[7] - Current color
  8208.                 colors[8] - BRIGHT() of current color
  8209.  
  8210.  
  8211.                 <restscrn> - New parameter
  8212.  
  8213.                 RLIB version 2.0 PDOWNINIT() saved the area of the screen
  8214.                 that was displaced by the menu boxes upon initialization and
  8215.                 restored this original screen upon each entry and side
  8216.                 movement in PDOWNMENU().  This is fine if you don't care if
  8217.                 your screen underneath the PDOWNMENU() is disrupted.  In the
  8218.                 case of a pull-down menu that is to overlay an area of the
  8219.                 screen, this is un-desirable.  The <restscrn> parameter lets
  8220.                 you control this action.  Althought the default value is True
  8221.                 to maintain upward compatibility with RLIB version 2.0, the
  8222.                 better desired default value is False.  See the demo.
  8223.  
  8224.  
  8225.                 Separator Lines
  8226.  
  8227.                 If an menu item in a pull-down menu consists of a separator
  8228.                 line composed of ASCII CHR(196) characters, then such lines
  8229.                 will be treated as separator lines and skipped as menu item
  8230.                 selections.  The requirements are that a separator line must
  8231.                 not be a pull down menu's first or last option (that doesn't
  8232.                 make any sense anyway) and the line must begin at position #1
  8233.                 in the option string.
  8234.  
  8235.                 Apology Note
  8236.  
  8237.                 At a slight cost of upward compatibility, the <colors> array
  8238.                 has been ordered to be the same as the colors used by
  8239.  
  8240.  
  8241.    RLIB Function Reference                                                134
  8242.  
  8243.  
  8244.                 BOXMENU().  Many times you may want to have a BOXMENU() that
  8245.                 cascades below a PDOWNMENU().  By making the color array
  8246.                 tables consistent, you can now pass the same color array to
  8247.                 both PDOWNINIT() and BOXMENU().  Sorry for possibly changing
  8248.                 your menu colors, but it's worth it!
  8249.  
  8250.    Example:     *-- arrays to hold top menu, columns, and starting elements
  8251.                 DECLARE menus[5], columns[5], starts[5]
  8252.  
  8253.                 *-- array to hold each pull down menu items
  8254.                 DECLARE items[12]
  8255.  
  8256.                 menus[1] = "File"
  8257.                 menus[2] = "Edit"
  8258.                 menus[3] = "View"
  8259.                 menus[4] = "Utility"
  8260.                 menus[5] = "Quit"
  8261.  
  8262.                 columns[1] =  0
  8263.                 columns[2] = 24
  8264.                 columns[3] = 41
  8265.                 columns[4] = 58
  8266.                 columns[5] = 76
  8267.  
  8268.                 starts[1] = 1
  8269.                 items[ 1] = "Retrieve "
  8270.                 items[ 2] = "Save     "
  8271.                 items[ 3] = "Erase    "
  8272.  
  8273.                 starts[2] = 4
  8274.                 items[ 4] = "Record "
  8275.                 items[ 5] = "File   "
  8276.                 items[ 6] = "Memo   "
  8277.  
  8278.                 starts[3] = 7
  8279.                 items[ 7] = "Record "
  8280.                 items[ 8] = "File   "
  8281.                 items[ 9] = "Memo   "
  8282.  
  8283.                 starts[4] = 10
  8284.                 items[10] = "Directory "
  8285.                 items[11] = "Reccount  "
  8286.                 items[12] = "Index     "
  8287.  
  8288.                 starts[5] = 0
  8289.  
  8290.                 *-- initialize menu on row 1 using default colors & keys
  8291.                 CLEAR
  8292.                 PDOWNINIT( 1, columns, menus, items, starts )
  8293.  
  8294.    Source:      RL_PDINI.PRG (RL_PDOWN.PRG in 5.0 Library)
  8295.  
  8296.    See also:    BARMENU(), BOXMENU(), MULTIMENU(), PDOWNMENU()
  8297.  
  8298.  
  8299.  
  8300.    RLIB Function Reference                                                135
  8301.  
  8302.  
  8303.    Function:    PDOWNMENU()
  8304.  
  8305.    Purpose:     Activate the pull-down menu initialized with PDOWNINIT().
  8306.  
  8307.    Syntax:      PDOWNMENU( @menu, @item, menus, items, columns, starts;
  8308.                            [, item_msgs [, canexit [, itemflags ]]] )
  8309.  
  8310.    Arguments:   @menu       - Numeric variable which indicates the starting
  8311.                               top menu option.  This variable must be PASSED
  8312.                               BY REFERENCE by preceding the variable name
  8313.                               with the @ operator.  Passing this variable by
  8314.                               reference allows PDOWNMENU() to change its
  8315.                               value.
  8316.  
  8317.                 @item       - Numeric variable which indicates the starting
  8318.                               menu item for the starting menu option
  8319.                               indicated by <@menu>.  This variable must be
  8320.                               PASSED BY REFERENCE by preceding the variable
  8321.                               name with the @ operator.  Passing this
  8322.                               variable by reference allows PDOWNMENU() to
  8323.                               change its value.  A value of zero indicates
  8324.                               that the pull-down menu should not be "dropped"
  8325.                               and the menu bar should remain on the top menu
  8326.                               option.  The <item> number is relative to the
  8327.                               menu.
  8328.  
  8329.                 menus       - Array of character strings which will be used
  8330.                               as the top menu options displayed across the
  8331.                               top of the pull down menu.  Each <menu> element
  8332.                               will display at its corresponding <columns>
  8333.                               element number.  For example, Menu #2 will
  8334.                               display at coordinate position row,columns[2].
  8335.  
  8336.                 items       - Array of character strings which will be used
  8337.                               as the elements, or items, of each of the
  8338.                               pulled down menus.  This is a linear array with
  8339.                               each group of pull down menu items being
  8340.                               defined by a starting element number in the
  8341.                               <starts> array.
  8342.  
  8343.                 columns     - Array of numeric values indicating the column
  8344.                               number on which each top level menu option will
  8345.                               be displayed.  These column numbers control how
  8346.                               the options and their pull down menus are
  8347.                               spaced across the screen.
  8348.  
  8349.                 starts      - Array of starting element numbers.  Each
  8350.                               element in this array is a number which
  8351.                               indicates the starting position in the <items>
  8352.                               array at which each group of menu items begin. 
  8353.                               There should be one element for each
  8354.                               corresponding menu in the <menus> array.
  8355.  
  8356.                 item_msgs   - Optional array of messages which correspond to
  8357.  
  8358.  
  8359.    RLIB Function Reference                                                136
  8360.  
  8361.  
  8362.                               each of the pull-down menu items in the <items>
  8363.                               array.  There should be one element for each
  8364.                               menu item.  If a pull-down menu item message is
  8365.                               to be blank (omitted), insert a null string
  8366.                               ("") as the element value.  If omitted then no
  8367.                               messages will display.
  8368.  
  8369.                 canexit     - Optional logical value which indicates if
  8370.                               pressing the escape key will cause an exit of
  8371.                               the top level menu.  If omitted the default
  8372.                               value is false.
  8373.  
  8374.                 itemflags   - Optional array of logical flags which parallel
  8375.                               each menu item in the <items> array.  Each
  8376.                               element value is a logical True or False which
  8377.                               indicates whether or not the corresponding
  8378.                               pull-down menu item is selectable.  Un-
  8379.                               selectable menu items are displayed in the un-
  8380.                               selectable color initialized in the color array
  8381.                               in PDOWNINIT().  If this parameter is omitted
  8382.                               or a non-array value is passed, the default is
  8383.                               that all menu items are selectable.
  8384.  
  8385.    Returns:     Since the <menu> and <item> parameters are passed by
  8386.                 reference with the @ operator, the menu and item number
  8387.                 selected is changed for the calling procedure.  However,
  8388.                 PDOWNMENU() also returns a single value which is the element
  8389.                 number of the item array element chosen.  If only a top menu
  8390.                 option is selected, then the menu array element number is
  8391.                 returned as a negative value.  If escape was pressed, and no
  8392.                 selection was made, zero is returned.
  8393.  
  8394.    Description: The pull down menu consists of two parts: the "top" level
  8395.                 menu which looks and acts like BARMENU(), and the "pulled
  8396.                 down" menus, which look and act like BOXMENU()s.  When the
  8397.                 menu starts, the left and right arrow keys move the highlight
  8398.                 bar across the top menu options.  When either the ENTER key
  8399.                 or the first letter of one of the menu options is pressed,
  8400.                 the menu drops down to the pull down menu.  At this point the
  8401.                 up and down arrow keys highlight the different menu item
  8402.                 options and the ENTER key or first letter will selects each
  8403.                 one.  The left and right arrow keys at this point cause
  8404.                 PDOWNMENU() to skip left and right from pull down menu to
  8405.                 pull down menu.
  8406.  
  8407.    Notes:       Make sure that the numeric values referenced by <menu> and
  8408.                 <item> are integer in nature, that is, do not have any
  8409.                 decimal parts.  Since Clipper stores numeric values in
  8410.                 internal binary format and not ASCII, numeric comparisons can
  8411.                 sometimes lead to un-predictable and undesired results. 
  8412.                 Consider this situation: 
  8413.  
  8414.                 x = (1.10 - 1.00) * 10       && will = 1.00
  8415.                 ? x = 1                      && Clipper will return .F.
  8416.  
  8417.  
  8418.    RLIB Function Reference                                                137
  8419.  
  8420.  
  8421.                 Since PDOWNMENU() makes only integer comparisons, make sure
  8422.                 the MENU and ITEM numeric values have no decimal parts.
  8423.  
  8424.                 PDOWNMENU(), like all RLIB functions, uses the RLIB GETKEY()
  8425.                 function to retrieve keystrokes during the menu process.  If
  8426.                 you create your own customized version of GETKEY() (see the
  8427.                 function notes for GETKEY()), you can perform various actions
  8428.                 while the pull down menu is in action.  Since the <menu> and
  8429.                 <item> parameters are passed by reference, you can examine
  8430.                 their values, as they change, while the menu is active.  This
  8431.                 opens up enormous capabilities of things you can do while a
  8432.                 menu is in progress!  Consider a demo program that, while the
  8433.                 user is cursoring through a pull-down menu, a box on the
  8434.                 bottom right side of the screen is changing with descriptions
  8435.                 of each menu option.
  8436.  
  8437.                 See the notes for the preceding PDOWNINIT() function.
  8438.  
  8439.    Example:     *-- after having been initialized (see above), do the menu
  8440.                 menu   = 1                   && start on menu number 1
  8441.                 choice = 0                   && do not "pull down" on entry
  8442.  
  8443.                 DO WHILE menu < 5            && menu #5 = Quit
  8444.                    PDOWNMENU( @menu, @choice, menus, items, columns, starts )
  8445.  
  8446.                    DO CASE
  8447.                       CASE menu == 1                 && File
  8448.                          FileOp(choice)
  8449.                       CASE menu == 2                 && Edit
  8450.                          EditOp(choice)
  8451.                       CASE menu == 3                 && View
  8452.                          ViewOp(choice)
  8453.                       CASE menu == 4                 && Utility
  8454.                          UtilOp(choice)
  8455.                    ENDCASE
  8456.                 ENDDO
  8457.                 RETURN
  8458.  
  8459.                 *------------------------------------------------------
  8460.                 * Function: FileOp()
  8461.                 * Purpose:  Specific file operations based on the value
  8462.                 *           of the <choice> parameter.
  8463.                 * Notes:    You would have a similar function for
  8464.                 *           EditOp(), ViewOp(), and UtilOp()
  8465.                 *------------------------------------------------------
  8466.                 FUNCTION fileop
  8467.                 PARAMETER choice
  8468.  
  8469.                 DO CASE
  8470.                    CASE choice = 1
  8471.                       DO retrieve
  8472.                    CASE choice = 2
  8473.                       DO save
  8474.                    CASE choice = 3
  8475.  
  8476.  
  8477.    RLIB Function Reference                                                138
  8478.  
  8479.  
  8480.                       DO erase
  8481.                 ENDCASE
  8482.                 RETURN
  8483.  
  8484.    Source:      RL_PDOWN.PRG
  8485.  
  8486.    See also:    BARMENU(), BOXMENU(), MULTIMENU(), PDOWNINIT()
  8487.  
  8488.  
  8489.  
  8490.  
  8491.  
  8492.  
  8493.  
  8494.  
  8495.  
  8496.  
  8497.  
  8498.  
  8499.  
  8500.  
  8501.  
  8502.  
  8503.  
  8504.  
  8505.  
  8506.  
  8507.  
  8508.  
  8509.  
  8510.  
  8511.  
  8512.  
  8513.  
  8514.  
  8515.  
  8516.  
  8517.  
  8518.  
  8519.  
  8520.  
  8521.  
  8522.  
  8523.  
  8524.  
  8525.  
  8526.  
  8527.  
  8528.  
  8529.  
  8530.  
  8531.  
  8532.  
  8533.  
  8534.  
  8535.  
  8536.    RLIB Function Reference                                                139
  8537.  
  8538.  
  8539.    Function:    PICKCOLOR()
  8540.  
  8541.    Purpose:     Pick a color setting from a boxed display.
  8542.  
  8543.    Syntax:      PICKCOLOR( [ pick_color [, box_color [, x_string [, toprow;
  8544.                            [, leftcolumn [, show_names ] ] ] ] ] ] )
  8545.  
  8546.    Arguments:   pick_color  - Character string indicating the initial color
  8547.                               to position the highlight bar on as the
  8548.                               selected color.  The default is the current
  8549.                               color setting.
  8550.  
  8551.                 box_color   - Character string indicating the color to use
  8552.                               for the display box border and color names
  8553.                               text.  The default is the current color
  8554.                               setting.
  8555.  
  8556.                 x_string    - String to use instead of the X's as the fill
  8557.                               characters in the color boxes.  The default
  8558.                               string is a five character string " XXX ".
  8559.  
  8560.                 toprow      - Numeric value indicating the top row on which
  8561.                               to position the color grid box.  Valid range is
  8562.                               from 0 to 5.  If omitted or an invalid number
  8563.                               is given, the default row of 4 will be used.
  8564.  
  8565.                 leftcolumn  - Numeric value indicating the left column of the
  8566.                               box display.  The default is calculated so as
  8567.                               to center the box on the screen.
  8568.  
  8569.                 show_names  - Logical true or false indicating whether or not
  8570.                               to display the color names along the right side
  8571.                               of the selection box.  The default is True
  8572.                               (.T.) 
  8573.  
  8574.    Returns:     The selected color as a Clipper character color string, or a
  8575.                 null string ("") if terminated by pressing the Escape key.
  8576.  
  8577.    Description: PICKCOLOR() is very useful as a function to allow the user to
  8578.                 interactively select a color setting from within an
  8579.                 application.  PICKCOLOR() draws a box on the screen either
  8580.                 centered or at the column you specify, and fills it with a
  8581.                 grid of 16 rows by 8 columns of " XXX ", or the string you
  8582.                 specify, displaying each of the 128 possible color
  8583.                 combinations.  Optionally, the descriptive names of each of
  8584.                 these colors is displayed to the right of the display box. 
  8585.                 At the bottom of the screen two sample lines are shown in the
  8586.                 highlighted color setting.
  8587.  
  8588.    Notes:       PICKCOLOR() occupies most of the screen area when displaying
  8589.                 the color grid.  Initially PICKCOLOR() was designed to clear
  8590.                 the screen.  This was later removed so that an application
  8591.                 could leave instructions somewhere on the screen, perhaps the
  8592.                 menu choice showing the user which color option they were
  8593.  
  8594.  
  8595.    RLIB Function Reference                                                140
  8596.  
  8597.  
  8598.                 selecting.
  8599.  
  8600.                 PICKCOLOR() does save and restore the screen area underneath
  8601.                 when it terminates.  The initial <pick_color> parameter
  8602.                 determines where the highlight bar is initially positioned in
  8603.                 the grid.
  8604.  
  8605.                 The default x_string is " XXX " with automatic centering.  If
  8606.                 you specify a longer (or shorter) string, and you also
  8607.                 specify the left column, PICKCOLOR() will determine if the
  8608.                 column you provided would cause the grid to fall off the
  8609.                 screen.  If this happens, the grid will be shifted left the
  8610.                 necessary number of columns.  All of these positioning
  8611.                 considerations vary depending whether or not the color names
  8612.                 are displayed, since they take up room on the right side of
  8613.                 the grid.
  8614.  
  8615.    Example:     *-- set up default screen color settings
  8616.                 SETCOLOR("R/W,W/R,,,BG/R")
  8617.  
  8618.                 *-- retrieve current Enhanced & Unselected color settings
  8619.                 m_getcolor = GETPARM( 2, SETCOLOR() )
  8620.                 m_unselect = GETPARM( 5, SETCOLOR() )
  8621.  
  8622.                 *-- present routine to let user select GET color scheme
  8623.                 @ 1,0 SAY "Select color for highlighted variables:"
  8624.  
  8625.                 *-- pop up grid in White on Blue, showing blocks of " ## "
  8626.                 *-- in the top right corner of the screen, no color names
  8627.                 *-- Hint: the column of 79 forces right side alignment
  8628.                 m_getcolor = PICKCOLOR(m_getcolor, "W/B", " ## ", 0, 79, .F.)
  8629.  
  8630.                 @ 1,0 SAY "Select color for unselected variables:"
  8631.                 m_unselect = PICKCOLOR(m_unselect, "W/B", " ## ", 0, 79, .F.)
  8632.  
  8633.    Source:      RL_PICKC.PRG
  8634.  
  8635.    See also:    BRIGHT(), GETPARM()
  8636.  
  8637.  
  8638.  
  8639.  
  8640.  
  8641.  
  8642.  
  8643.  
  8644.  
  8645.  
  8646.  
  8647.  
  8648.  
  8649.  
  8650.  
  8651.  
  8652.  
  8653.  
  8654.    RLIB Function Reference                                                141
  8655.  
  8656.  
  8657.    Function:    PICKFILE()
  8658.  
  8659.    Purpose:     Pop up a directory listing from which to select a file.
  8660.  
  8661.    Syntax:      PICKFILE( [ filespec [, top [, left [, bottom [, colors;
  8662.                           [, expanded [, showpath ]]]]]]] )
  8663.  
  8664.    Arguments:   filespec    - Optional character string indicating the
  8665.                               filespec to use for the directory search.  This
  8666.                               filespec must follow the conventions required
  8667.                               by ADIR().  If omitted, PICKFILE() defaults to
  8668.                               all files (*.*).
  8669.  
  8670.                 top         - Optional numeric value indicating the top row
  8671.                               for the directory box.  If omitted or an
  8672.                               invalid type parameter is specified, the
  8673.                               default row is row 6 to center the box on the
  8674.                               screen.
  8675.  
  8676.                 left        - Optional numeric value indicating the left
  8677.                               column for the directory box.  If omitted or an
  8678.                               invalid parameter is specified, the default is
  8679.                               the column position necessary to center the
  8680.                               directory box on the screen.
  8681.  
  8682.                 bottom      - Optional numeric value indicating the bottom
  8683.                               row for the directory box.  If omitted or an
  8684.                               invalid type parameter is specified, the
  8685.                               default row is row 19, to center the box on the
  8686.                               screen.
  8687.  
  8688.                 colors      - Optional character string specifying the color
  8689.                               settings to use.  This color setting is passed
  8690.                               to ACHOICE() so the format is that required by
  8691.                               ACHOICE().
  8692.  
  8693.                 expanded    - Optional logical value indicating if the file
  8694.                               listing display is to be expanded to include
  8695.                               the file size, date, and time.  If omitted or
  8696.                               an invalid parameter is passed, the default
  8697.                               value is true, display expanded listing.
  8698.  
  8699.                 showpath    - Optional logical value indicating whether or
  8700.                               not to display the filepath specified on the
  8701.                               top of the box.  If omitted or an invalid
  8702.                               parameter is passed, the default value is
  8703.                               false.
  8704.  
  8705.    Returns:     The selected filename as a character string, or a null string
  8706.                 ("") if the Escape key was pressed.
  8707.  
  8708.    Description: PICKFILE() is a full featured file function which provides
  8709.                 easy access to a pop-up boxed file directory listing from
  8710.                 which to choose a file.  PICKFILE() is very useful for
  8711.  
  8712.  
  8713.    RLIB Function Reference                                                142
  8714.  
  8715.  
  8716.                 popping up file selection menus when a user is required to
  8717.                 enter a filename for a file that already exists on disk.
  8718.  
  8719.    Notes:       After the file selection is made, the menu box disappears and
  8720.                 the screen below it is restored.
  8721.  
  8722.                 The previous version of PICKFILE() in RLIB v 2.0 would not
  8723.                 return a fully qualified filename.  If you selected a file
  8724.                 that was not in the current directory, only the filename was
  8725.                 returned, not the full path preceding it.  This has been
  8726.                 fixed in version 3.0 
  8727.  
  8728.    Example:     *-- ask user for name of .DBF file to USE
  8729.                 *-- make the F10 key the pop-up controller
  8730.                 SET KEY -9 TO FileLister
  8731.  
  8732.                 *-- allocate plenty of space for fully qualified filename
  8733.                 dbf_file = SPACE(60)
  8734.                 @ 10,0 SAY "Enter filename or press F10 for a list";
  8735.                        GET dbf_file PICTURE "@!S40"
  8736.                 READ
  8737.                 USE (dbf_file)
  8738.  
  8739.                 *--<now do whatever>
  8740.  
  8741.  
  8742.                 *-----------------------------------------------------------
  8743.                 * Procedure: FileLister
  8744.                 * Notes:     Procedure to pop-up list of .DBF files.  This
  8745.                 *            example uses the macro operator to assign the
  8746.                 *            picked filename to the READVAR.  In Clipper
  8747.                 *            5.0 if the READVAR() is not a PUBLIC or PRIVATE
  8748.                 *            variable, this will not work.
  8749.                 *-----------------------------------------------------------
  8750.                 PROCEDURE FileLister
  8751.                 PARAMETERS callproc, callline, inputvar
  8752.                 &inputvar = STRETCH( PICKFILE("*.DBF"), LEN(&inputvar) )
  8753.                 RETURN
  8754.  
  8755.    Source:      RL_PICKF.PRG
  8756.  
  8757.    See also:    FILEDATE(), FILESIZE(), FILETIME(), PICKREC()
  8758.  
  8759.  
  8760.  
  8761.  
  8762.  
  8763.  
  8764.  
  8765.  
  8766.  
  8767.  
  8768.  
  8769.  
  8770.  
  8771.  
  8772.    RLIB Function Reference                                                143
  8773.  
  8774.  
  8775.    Function:    PICKREC()
  8776.  
  8777.    Purpose:     Pop up a scrollable pick list of database records.
  8778.  
  8779.    Syntax:      PICKREC( t, l, b, r, fieldlist [, procname [, condition ;
  8780.                          [, pickrow [, exitkeys [, pickmode ;
  8781.                          [, markkey [, markfield [, colors [, boxchars ;
  8782.                          [, boxheader [, restore ]]]]]]]]]]] )
  8783.  
  8784.    Arguments:   t,l,b,r     - Numeric values specifying the Top, Left, Bottom
  8785.                               and Right screen coordinates of the display
  8786.                               box.  The top and bottom row values must be
  8787.                               between 0 and 24 (MAXROW() in 5.0), and the
  8788.                               left and right column values must be between 0
  8789.                               and 79.
  8790.  
  8791.                 fieldlist   - Character string that evaluates to a valid
  8792.                               character expression.  This character
  8793.                               expression is evaluated via macro expansion to
  8794.                               produce the text that is displayed in the
  8795.                               PICKREC() display box and the scrolling
  8796.                               highlight bar.  Since it is macro expanded, it
  8797.                               must evaluate correctly to a character string. 
  8798.                               Any valid expression may be used.  Normally the
  8799.                               expression contains a database field list such
  8800.                               as "Lastname + ' ' + Firstname", hence the name
  8801.                               <fieldlist>.
  8802.  
  8803.                 procname    - Optional character string indicating the name
  8804.                               of the procedure to call after each keypress. 
  8805.                               Since the call to this procedure is named at
  8806.                               runtime via macro substitution, the procedure
  8807.                               name must be identified to the compiler/linker
  8808.                               by using the EXTERNAL declaration unless it is
  8809.                               included in or is a module that will be linked. 
  8810.                               If omitted or an invalid or empty character
  8811.                               parameter is provided, the default is no
  8812.                               procedure will be called.
  8813.  
  8814.                 condition   - Optional character string indicating the
  8815.                               condition that records must meet to be included
  8816.                               in the list.  This character string is
  8817.                               evaluated at runtime via macro substitution,
  8818.                               therefore it MUST evaluate to a logical
  8819.                               expression!  If omitted or an invalid or empty
  8820.                               character parameter is provided, the default
  8821.                               condition is ".T.", i.e.  all records in the
  8822.                               database will be included.
  8823.  
  8824.                 pickrow     - Numeric value indicating the current row number
  8825.                               of the 'selection bar'.  This parameter is
  8826.                               required to allow PICKREC() to 'remember' where
  8827.                               the bar was upon return from a previous
  8828.                               selection.  Additionally, this parameter allows
  8829.  
  8830.  
  8831.    RLIB Function Reference                                                144
  8832.  
  8833.  
  8834.                               display refresh control by optionally passing
  8835.                               the following values: 
  8836.  
  8837.                                0 -  Clear display box, GO to the TOP of the
  8838.                                     selected database or to the first record
  8839.                                     meeting the <condition> if specified, and
  8840.                                     display records until box filled, End Of
  8841.                                     File, or <condition> is false.  Zero is
  8842.                                     the value passed at startup.
  8843.  
  8844.                               -1 -  Clear display box, display records
  8845.                                     starting at the current record until box
  8846.                                     filled, EOF() .OR. (.NOT. &condition).
  8847.  
  8848.                 exitkeys    - Optional character string which consists of a
  8849.                               set of characters which, when pressed, will
  8850.                               cause PICKREC() to exit.  If omitted or an
  8851.                               invalid parameter is passed, the default is
  8852.                               CHR(22) + CHR(7) which are the character values
  8853.                               of the Insert and Delete keys.
  8854.  
  8855.                 pickmode    - Optional numeric value indicating the action
  8856.                               mode for PICKREC().  If omitted or an invalid
  8857.                               parameter is passed, the default mode is zero. 
  8858.                               See the detailed notes section for more
  8859.                               information.  The allowed values are:
  8860.  
  8861.                                0 -  No refresh, pick up at current
  8862.                                     record/row.
  8863.  
  8864.                                1 -  Refresh record display at current
  8865.                                     record/row.
  8866.  
  8867.                                2 -  Same as mode 1 above but tell PICKREC()
  8868.                                     to not wait for or process any keys but
  8869.                                     to immediately exit.
  8870.  
  8871.                 markkey     - Optional mark/unmark key ASCII value which,
  8872.                               when pressed, toggles the current record being
  8873.                               included in a "marked" list.  If omitted or a
  8874.                               non-numeric value is passed then mark toggling
  8875.                               will not be activated.  If numeric with a value
  8876.                               of zero, the default ASCII key value is -8, for
  8877.                               the F9 key.
  8878.  
  8879.                 markfield   - Optional field name or expression evaluated and
  8880.                               used to add an item to the marked list.  If the
  8881.                               mark option is not activated (<markkey> not
  8882.                               defined), then <markfield> is ignored.  If
  8883.                               marking is on and <markfield> is either omitted
  8884.                               or is non-character in type or empty, then the
  8885.                               default expression used to add items to the
  8886.                               marked list is "STR(RECNO(),8,0)" 
  8887.  
  8888.  
  8889.  
  8890.    RLIB Function Reference                                                145
  8891.  
  8892.  
  8893.                 colors      - Optional array of color settings used to govern
  8894.                               the colors of various parts of the PICKREC()
  8895.                               display.  See the table listed below for
  8896.                               options and default values if the array is not
  8897.                               provided.
  8898.  
  8899.                 boxchars    - Optional character string to use in drawing a
  8900.                               box around the PICKREC() border using the
  8901.                               @..BOX command.  The boxing character string
  8902.                               must be in a form acceptable to BORDERBOX()
  8903.                               since BORDERBOX() is used to draw the box and
  8904.                               header (if specified).  If omitted, empty, or a
  8905.                               non-character type parameter is passed, no box
  8906.                               will be drawn.
  8907.  
  8908.                 boxheader   - Optional character string to use as a header to
  8909.                               display in a header area of a BORDERBOX() style
  8910.                               box.  The string must be in a form acceptable
  8911.                               to BORDERBOX().  If omitted or a non-character
  8912.                               type parameter is passed (or boxchars) was not
  8913.                               specified, no box header will be drawn.
  8914.  
  8915.                 restore     - Optional logical value indicating whether or
  8916.                               not to restore the screen area displaced with
  8917.                               the PICKREC() to its contents prior to
  8918.                               PICKREC() being called.  If omitted or a
  8919.                               non-logical value is passed, the default is
  8920.                               False.
  8921.  
  8922.    Returns:     The row number of the selected record, or zero if the Escape
  8923.                 Key was pressed to exit.  If either the insert or delete keys
  8924.                 are pressed, the routine exits to the calling procedure which
  8925.                 can test for Insert or Delete with the LASTKEY() function.
  8926.  
  8927.    Description: PICKREC() is a database interface function which permits
  8928.                 scrolling through a picklist of records from the currently
  8929.                 selected database.  It provides an easy method to PICK a
  8930.                 RECord from a database.  Pressing the ENTER key selects a
  8931.                 record for further processing.  Views are also supported in
  8932.                 that the fieldlist data which is displayed can be any valid
  8933.                 expression including field data from related databases.
  8934.  
  8935.                 Some of the most functional uses are to produce pop-up
  8936.                 listings in windows for on line help, or for supplying a menu
  8937.                 of database records from which to select for editing,
  8938.                 appending or deleting.  You simply give the function the four
  8939.                 screen coordinates defining the display box, and the field
  8940.                 list or expression to display, and it lists these expressions
  8941.                 in a box for you to cursor up and down through to find the
  8942.                 one you want and select it by pressing ENTER.  Other
  8943.                 parameters allow you to call a procedure to perform display
  8944.                 duties each time the arrow keys are pressed, and facilities
  8945.                 for controlling the display refresh.
  8946.  
  8947.  
  8948.  
  8949.    RLIB Function Reference                                                146
  8950.  
  8951.  
  8952.                 This description is only the tip of the iceberg.  PICKREC()
  8953.                 is a powerful tool!  The various parameters extend the finest
  8954.                 level of control while not forcing you to write your own
  8955.                 customized DBEDIT() style picklist routine; most of the grunt
  8956.                 work has been done for you.
  8957.  
  8958.    Notes:       PICKREC() skips forward and backward through the database
  8959.                 records as the up and down arrow keys are pressed.  The PgUp
  8960.                 and PgDn scroll one window full of records.  When the Enter
  8961.                 key is pressed, PICKREC() exits with the record pointer
  8962.                 positioned at the selected record.  If the Escape Key is
  8963.                 pressed, the record pointer is at the last displayed record,
  8964.                 but PICKREC() returns zero.
  8965.  
  8966.                 As always, if any parameter is to be skipped, pass a dummy
  8967.                 parameter such as a null string in place of the actual
  8968.                 parameter.
  8969.  
  8970.                 Key handling: 
  8971.  
  8972.                 The following default key actions are defined for PICKREC(): 
  8973.  
  8974.                 Key         Action
  8975.                 ---------   -------------------------------------------------
  8976.                 Up          Skip back one record, scroll screen if at top
  8977.                 Down        Skip forward 1 record, scroll screen if at bottom
  8978.                 PgUp        Skip back <n> records (n = winBottom - winTop)
  8979.                 PgDn        Skip forward <n> records
  8980.                 Home        Goto logical top (GO TOP if no condition)
  8981.                 End         Goto logical bottom (GO BOTTOM if no condition)
  8982.                 Escape      Abort, return zero
  8983.                 Enter       Highlight current record, return current pickrow
  8984.                 Alt-R       Refresh screen
  8985.                 Character   Start/continue indexed search
  8986.  
  8987.  
  8988.                 Screen refresh: (Alt-R)
  8989.  
  8990.                 If you use your own replacement GETKEY() function you can
  8991.                 send PICKREC() certain messages in the form of keystroke
  8992.                 requests such as inkey value 275 which equals Alt-R to
  8993.                 refresh the screen.
  8994.  
  8995.  
  8996.                 Indexed search:
  8997.  
  8998.                 PICKREC() has built in an indexed search capability. 
  8999.                 However, this feature is only available if the database
  9000.                 underlying the PICKREC() session is indexed and that index is
  9001.                 active.  The index must be character in nature.
  9002.  
  9003.                 The index feature works as follows.  When PICKREC() is
  9004.                 active, if the user presses a character key, such as a
  9005.                 letter, PICKREC() performs a SEEK on that letter.  If a
  9006.  
  9007.  
  9008.    RLIB Function Reference                                                147
  9009.  
  9010.  
  9011.                 record is found, the PICKREC() display is refreshed with the
  9012.                 found record appearing at the top of the display box.  At
  9013.                 this point the index search is still "active" and the user
  9014.                 can "home in" on the correct record by pressing another
  9015.                 letter key.  PICKREC() will then SEEK the first letter
  9016.                 pressed plus this next letter.  This process will continue
  9017.                 until the SEEK fails or a standard PICKREC() control key,
  9018.                 such as the up or down arrow, is pressed.
  9019.  
  9020.                 For example, if PICKREC() were listing a database of customer
  9021.                 names, lastname first, and the user pressed "L", PICKREC()
  9022.                 would jump to the first record with a lastname beginning with
  9023.                 "L".  If the user next pressed "O", PICKREC() would jump to
  9024.                 the first name beginning with "LO", and so on.
  9025.  
  9026.  
  9027.                 Additional parameter information:
  9028.  
  9029.                 <fieldlist>
  9030.  
  9031.                 If the <fieldlist> is wider than the width of the display box
  9032.                 area (right - left - 1) PICKREC() will truncate the
  9033.                 expression text to fit in the display box.  If <fieldlist> is
  9034.                 narrower than the display box width, PICKREC() will pad the
  9035.                 <fieldlist> text with spaces sufficient to extend the
  9036.                 highlight bar the width of the display box.
  9037.  
  9038.                 <procname>
  9039.  
  9040.                 This feature is useful for creating applications that refresh
  9041.                 an area of the screen as the user scrolls through the
  9042.                 PICKREC() display.  As PICKREC() cycles through the loop that
  9043.                 retrieves keystrokes it displays the <fieldlist> expression
  9044.                 for the current record then calls <procname> before
  9045.                 retrieving the next keystroke.  <procname> is called as a
  9046.                 procedure via macro substitution with the code "DO &procname"
  9047.                 therefore the <procname> procedure must be known at runtime. 
  9048.                 This means that the linker will not find and resolve
  9049.                 <procname> on its own.  The best way to ensure that
  9050.                 <procname> is linked in is to declare it as EXTERNAL in the
  9051.                 module which contains the PICKREC() call.
  9052.  
  9053.                 <condition>
  9054.  
  9055.                 The <condition> parameter does not perform the function of a
  9056.                 FILTER.  Instead <condition> is intended to be used with an
  9057.                 indexed database.  PICKREC() abides by <condition> on a WHILE
  9058.                 basis.  This means that the database should be indexed such
  9059.                 that all of the records that meet the <condition> are
  9060.                 logically grouped together.  Furthermore, if <condition> is
  9061.                 specified, the programmer must position the database record
  9062.                 pointer to a record that meets the <condition> before the
  9063.                 call to PICKREC().
  9064.  
  9065.  
  9066.  
  9067.    RLIB Function Reference                                                148
  9068.  
  9069.  
  9070.                 The <condition> character string MUST evaluate to a logical
  9071.                 expression.  For example, to list all sales orders for
  9072.                 customer code RCL100, the condition would be "ALIAS->CUSTNO =
  9073.                 'RCL100'".  Notice that strings enclosed in quotes are
  9074.                 bounded by quotes within quotes.  If this condition does not
  9075.                 evaluate to a logical expression, a runtime TYPE MISMATCH
  9076.                 error may occur.  RLIB will make an attempt to verify that
  9077.                 the string is logical in nature.
  9078.  
  9079.                 <exitkeys>
  9080.  
  9081.                 To maintain upward compatibility with previous versions of
  9082.                 PICKREC(), the default exit keys are INSERT and DELETE.  In
  9083.                 addition, the default keys which cause an exit condition are
  9084.                 ENTER and ESCAPE.  Escape will force a return of zero while
  9085.                 ENTER will cause the current record to be highlighted.  Do
  9086.                 not supply CHR(27)+CHR(13) (ENTER and ESCAPE) as exit keys
  9087.                 unless you purposefully want to bypass the default actions
  9088.                 that are performed when ENTER or ESCAPE is pressed.  If you
  9089.                 do pass these keys, or any other keys (such as up, down etc.)
  9090.                 the internal actions that PICKREC() performs on these keys
  9091.                 will be circumvented.  This usually is not desired, however
  9092.                 this does allow you the option to bypass the standard
  9093.                 function of one of these keys and substitute your own routine
  9094.                 instead.  To bypass this parameter, you must pass some
  9095.                 parameter so pass a non-character such as a logical.  If you
  9096.                 pass a null this will disable the default exit keys of Insert
  9097.                 and Delete.
  9098.  
  9099.                 Most keys can safely be represented in this string in their
  9100.                 CHR() forms.  Certain function keys, notably F2-F10 return
  9101.                 negative inkey() values.  Their CHR() return values wrap to
  9102.                 the very high ASCII characters.  For instance the inkey value
  9103.                 for F2 is -1.  To express this with the CHR() function,
  9104.                 CHR(F2) is the same as CHR(-1), which is the CHR(254)
  9105.                 character.  Likewise, F3 is -2 and CHR(-2) = CHR(253) and so
  9106.                 on.  The end result is that placing function key values on
  9107.                 the <exitkey> string reveals a string with high ascii
  9108.                 characters.  This works fine.  The only potential, albeit
  9109.                 very slight, problem is if a user were to hold down the alt
  9110.                 key and press 253 on the numeric keypad, they would get the
  9111.                 same action if they had pressed F2.
  9112.  
  9113.                 <pickmode>
  9114.  
  9115.                 This is a numeric "action" indicator which tells PICKREC()
  9116.                 how to display records.  It is usually used on re-entry to
  9117.                 PICKREC() since an initial call to PICKREC() uses a <pickrow>
  9118.                 parameter value of 0, or -1.  (See the <pickrow> parameter
  9119.                 details above.)  This mode parameter can be used in
  9120.                 conjunction with <pickrow> so that PICKREC() can use the
  9121.                 saved value of <pickrow> to help refresh the record display
  9122.                 in a more natural way.  Usually, you will save the screen
  9123.                 after a PICKREC() selection, do some processing, then loop
  9124.  
  9125.  
  9126.    RLIB Function Reference                                                149
  9127.  
  9128.  
  9129.                 back to the next call to PICKREC() after restoring the
  9130.                 screen.  If the <pickrow> parameter is intact, (not 0 or -1)
  9131.                 PICKREC() does not do any record displaying, it just picks up
  9132.                 and displays the current record on the row indicated. 
  9133.                 However, after a record INSERT or DELETE, a value of -1 is
  9134.                 best passed which forces a record re-fresh, but from the top
  9135.                 row.  This doesn't always look very clean.
  9136.  
  9137.                 The following action modes are defined:
  9138.  
  9139.                              0   -  No refresh, pick up at current
  9140.                                     record/row.  This is the default mode. 
  9141.                                     The <pickrow> parameter is used to tell
  9142.                                     PICKREC() whether or not to fill the box
  9143.                                     with records.
  9144.  
  9145.                              1   -  Refresh record display at current
  9146.                                     record/row.  PICKREC() will fill the box
  9147.                                     with records from the current record.  It
  9148.                                     will SKIP backwards to fill from the
  9149.                                     current row back up to the top, then will
  9150.                                     go back to the starting record, fill
  9151.                                     forward the remaining box, then return to
  9152.                                     the starting record.  If you've ever
  9153.                                     watched the DBEDIT() function refresh the
  9154.                                     screen when you page down, you'll notice
  9155.                                     how this behaves.
  9156.  
  9157.                              2   -  Same as mode 1 above but tell PICKREC()
  9158.                                     to not wait for or process any keys but
  9159.                                     to immediately exit.  This is useful for
  9160.                                     using PICKREC() to perform screen
  9161.                                     refreshes for you without having to code
  9162.                                     a bunch of DO WHILE..  SKIPs etc....  If
  9163.                                     the <pickrow> parameter is zero, then the
  9164.                                     box will fill from the GO TOP (see
  9165.                                     <pickrow> parameter), but this mode will
  9166.                                     instruct PICKREC() to exit.
  9167.  
  9168.                 <markkey>
  9169.  
  9170.                 An enhancement to PICKREC() was to give it MARKREC()
  9171.                 capabilities.  The "mark" parameters are optional, if they
  9172.                 are supplied, PICKREC() will adopt MARKREC() characteristics,
  9173.                 but in all other ways will continue to behave just like
  9174.                 PICKREC().  The main reason for doing this was to exercise
  9175.                 practical memory usage.  Since the two functions share almost
  9176.                 identical code, it was sensible to merge the two.  For upward
  9177.                 compatibility reasons, the existing function names still
  9178.                 exist, except that MARKREC() now simply calls PICKREC() with
  9179.                 the extended parameters.
  9180.  
  9181.                 One interesting note is that you can use PICKREC() as
  9182.                 MARKREC() directly.  However, PICKREC() returns a numeric
  9183.  
  9184.  
  9185.    RLIB Function Reference                                                150
  9186.  
  9187.  
  9188.                 value and MARKREC() returns a character string (the string of
  9189.                 marks).  If you want to use PICKREC() directly, you must
  9190.                 establish a memory variable named <rl_marked> before calling
  9191.                 PICKREC().  This is precisely what MARKREC() does; it
  9192.                 initializes <rl_marked>, then calls PICKREC() with the
  9193.                 appropriate parameter values, then returns <rl_marked>.  If
  9194.                 you want to preserve the value of this marker variable
  9195.                 <rl_marked> when PICKREC() exits (for instance you need to
  9196.                 exit PICKREC() temporarily to process a F1 Help request),
  9197.                 then you would establish <rl_marked> by setting it to a null
  9198.                 ("") before the very first call to PICKREC().  Remember
  9199.                 however to make sure you release <rl_marked> or re-initialize
  9200.                 it back to a null ("") before your next fresh call to
  9201.                 PICKREC() for marking.  For this reason, <rl_marked> is not
  9202.                 declared PRIVATE in this code.
  9203.  
  9204.                 <colors>
  9205.  
  9206.                 Another side benefit to all this is that you can now
  9207.                 explicitly define color settings for PICKREC().  If you do
  9208.                 not want to use marking but want to get at the color
  9209.                 parameter, pass as the markkey parameter a non-numeric
  9210.                 parameter ("") to get at the colors array.  This allows you
  9211.                 more control over the highlight color rather that accepting
  9212.                 the BRIGHT() version of the default color.
  9213.  
  9214.                 The elements of the color array are: 
  9215.  
  9216.                 Element#  Description                Default
  9217.                 --------  -------------------------  ----------------------
  9218.                 color[1]  Normal text display        Standard - SETCOLOR()
  9219.                 color[2]  Selected or Marked         BRIGHT() Standard
  9220.                 color[3]  Hi-lited (scroll bar)      Enhanced
  9221.                 color[4]  Hi-lited & Selected/Marked Enhanced/Bright/Blinking
  9222.                 color[5]  Color on exit from XITKEYS BRIGHT() Standard 
  9223.  
  9224.  
  9225.                 Advanced Color Features:
  9226.  
  9227.                 The color array elements #6, 7 and 8 can be used to display
  9228.                 records in a different color if a specified condition exists. 
  9229.                 The condition is a logical expression which is represented by
  9230.                 the color array element #8.  If this condition expression
  9231.                 evaluates to True (via macro substitution) then the
  9232.                 <fieldlist> text will be displayed in color[6] for normal
  9233.                 display, and color[7] when highlighted.
  9234.  
  9235.                 Element#  Description                 Default
  9236.                 --------  -------------------------   -----------------------
  9237.                 color[6]  Normal text IF (color[8])   Standard - SETCOLOR()
  9238.                 color[7]  Hi-lited IF (color[8])      Enhanced
  9239.                 color[8]  Character condition         (.T.)
  9240.  
  9241.    Example:     See several examples in the Message Reader demo program.
  9242.  
  9243.  
  9244.    RLIB Function Reference                                                151
  9245.  
  9246.  
  9247.                 *-- Example #1, fairly basic pick and edit routine
  9248.                 fieldlist = "Lastname+', '+Firstname+' - '+Fonenumber"
  9249.                 pickrow   = 0
  9250.                 pickmode  = 1
  9251.                 boxchars  = "╔═╗║╝═╚║"
  9252.                 boxheader = "AVAILABLE PHONE LISTINGS"
  9253.                 restore   = .F.
  9254.  
  9255.                 SELECT Fonebook
  9256.                 DO WHILE .T.
  9257.                    *-- now present records from database to choose from
  9258.                    pickrow = PICKREC( 4, 40, 23, 79, fieldlist, "", "",;
  9259.                                       pickrow, xitkeys, pickmode, "", "",;
  9260.                                       "", boxchars, boxheader, restore )
  9261.                    DO CASE
  9262.                       CASE pickrow = 0      && Escape returns 0
  9263.                          EXIT
  9264.  
  9265.                       CASE LASTKEY() = 22   && Insert Key - add a record
  9266.                          MEMORIZE(.T.)      && Initialize empty structure
  9267.                          DO edit_proc       && perform edits on new entry
  9268.                          pickrow = -1       && force screen refresh with -1
  9269.  
  9270.                       CASE LASTKEY() = 7    && Delete Key
  9271.                          IF BOXASK("W/R","Are you sure? (Y/N)") = "Y"
  9272.                             DELETE
  9273.                             pickrow = 0     && start over at top of file
  9274.                          ENDIF
  9275.  
  9276.                       CASE LASTKEY() = 13   && Enter Key - edit record
  9277.                          *-- get controlling index key expression if any
  9278.                          ntx_key = NTXKEYVAL()
  9279.                          DO edit_proc
  9280.  
  9281.                          *-- now see if edits changed an index key value
  9282.                          IF .NOT. ntx_key == NTXKEYVAL()
  9283.                             *-- field contents changed from before edits
  9284.                             *-- must refresh screen so order is in sync
  9285.                             pickrow = -1
  9286.                          ENDIF
  9287.  
  9288.                    ENDCASE
  9289.                 ENDDO
  9290.  
  9291.  
  9292.                 *-- Example #2:
  9293.                 *-- use PICKREC() to provide pop-up help in field edits
  9294.                 SET KEY -1 TO PopUpHelp           && F2 key is pop-up help
  9295.  
  9296.  
  9297.                 mzip = SPACE(5)
  9298.                 @ 10,0 SAY "Enter zip code (press F2 for listing)";
  9299.                        GET mzip PICTURE '#####'
  9300.                 READ
  9301.  
  9302.  
  9303.    RLIB Function Reference                                                152
  9304.  
  9305.  
  9306.                 .
  9307.                 .
  9308.                 .
  9309.                 .
  9310.  
  9311.  
  9312.                 PROCEDURE PopUpHelp
  9313.                 PARAMETERS callproc, linenum, inputvar
  9314.                 PRIVATE inarea
  9315.                 inarea = SELECT()
  9316.                 SELECT ZipCodes
  9317.  
  9318.                 BORDERBOX( 1, 50, 20, 79, "ZIP CODE LISTING" )
  9319.                 IF PICKREC( 4, 51, 19, 78, "Zip + ' - ' + City" ) > 0
  9320.                    mzip = ZIPCODES->ZipCode
  9321.                 ENDIF
  9322.                 SELECT (inarea)
  9323.                 RETURN
  9324.  
  9325.  
  9326.    Source:      RL_PICKR.PRG
  9327.  
  9328.    See also:    MARKREC()
  9329.  
  9330.  
  9331.  
  9332.  
  9333.  
  9334.  
  9335.  
  9336.  
  9337.  
  9338.  
  9339.  
  9340.  
  9341.  
  9342.  
  9343.  
  9344.  
  9345.  
  9346.  
  9347.  
  9348.  
  9349.  
  9350.  
  9351.  
  9352.  
  9353.  
  9354.  
  9355.  
  9356.  
  9357.  
  9358.  
  9359.  
  9360.  
  9361.  
  9362.    RLIB Function Reference                                                153
  9363.  
  9364.  
  9365.    Function:    POPBOX()
  9366.  
  9367.    Purpose:     Restore a screen from a SAYINBOX() screen variable.
  9368.  
  9369.    Syntax:      POPBOX( sayinbox_return_string )
  9370.  
  9371.    Arguments:   The specialized character string that was returned by the
  9372.                 last call to the SAYINBOX() function.
  9373.  
  9374.    Returns:     True.
  9375.  
  9376.    Description: POPBOX() is a companion function to the SAYINBOX() function. 
  9377.                 SAYINBOX() returns a character string which contains not only
  9378.                 the contents of the displaced screen image, but also the
  9379.                 coordinates of this screen region displaced by SAYINBOX(). 
  9380.                 This character string can be used as a parameter to this
  9381.                 companion function to restore the screen to the way it was
  9382.                 before SAYINBOX() was called.  This feature is ideal for
  9383.                 situations where you want to put up a message box, do some
  9384.                 processing, then remove the message box while restoring the
  9385.                 screen to its previous state.
  9386.  
  9387.    Notes:       The string parameter must be the one returned by SAYINBOX(),
  9388.                 otherwise unpredictable results may occur.  This is due to
  9389.                 the fact that SAYINBOX() stores the four screen coordinates
  9390.                 (top, left, bottom, right) as the first four characters in
  9391.                 the return string, and POPBOX() uses these coordinates as the
  9392.                 screen coordinates to issue a RESTSCREEN() function.
  9393.  
  9394.    Example:     *-- example of an INDEX message
  9395.                 pbox = SAYINBOX( "BG+/B", "Indexing, please wait" )
  9396.  
  9397.                 *-- Do the indexing, message will remain
  9398.                 INDEX ON keyfield TO indexfile
  9399.  
  9400.                 *-- Remove the message
  9401.                 POPBOX(pbox)
  9402.  
  9403.    Source:      RL_SAYIN.PRG
  9404.  
  9405.    See also:    ABOXASK(), BOXASK(), SAYINBOX()
  9406.  
  9407.  
  9408.  
  9409.  
  9410.  
  9411.  
  9412.  
  9413.  
  9414.  
  9415.  
  9416.  
  9417.  
  9418.  
  9419.  
  9420.  
  9421.    RLIB Function Reference                                                154
  9422.  
  9423.  
  9424.    Function:    POPUPPICK()
  9425.  
  9426.    Purpose:     Generic pop-up pick list handler
  9427.  
  9428.    Syntax:      POPUPPICK( t, l, b, r, disp_field [, message, [, box_title,;
  9429.                            [, rtrn_field [, alias [, color ] ] ] ] ] )
  9430.  
  9431.    Arguments:   t,l,b,r     - Top, Left, Bottom, Right window coordinates
  9432.                               bound checked to be within 0,0 to 24,79.  Also,
  9433.                               if the left + width of disp_field would cause
  9434.                               the display to overflow the right side of the
  9435.                               window, the display is truncated as per
  9436.                               PICKREC() 
  9437.  
  9438.                 disp_field  - Character string which is the name of the
  9439.                               database field or expression  to display in a
  9440.                               PICKREC() box.  This may be any expression that
  9441.                               evaluates to a character string.
  9442.  
  9443.                 message     - Optional message to display on line 24.  If
  9444.                               omitted or an invalid or empty character
  9445.                               parameter is given, then default message will
  9446.                               be: "Choose with ^X^Y, select with ^Q─┘, or
  9447.                               press ESCAPE to quit" it will be centered on
  9448.                               row 24.  In the Clipper 5.0 version the message
  9449.                               is displayed on MAXROW().
  9450.  
  9451.                 box_title   - Optional character string indicating the title
  9452.                               to appear in the pop-up box header area.  If no
  9453.                               title is specified, the box will have no header
  9454.                               area.
  9455.  
  9456.                 rtrn_field  - Optional character string indicating the field
  9457.                               or expression to return as the selected value. 
  9458.                               This may be any expression.  If omitted or a
  9459.                               non-character parameter is supplied, the
  9460.                               default field is [disp_field].
  9461.  
  9462.                 alias       - Optional character string indicating the name
  9463.                               of the database work area to select for the
  9464.                               pop-up.  If omitted or a non-character
  9465.                               parameter is given, the default is the current
  9466.                               work area, ALIAS().
  9467.  
  9468.                 color       - Optional array of color settings used to govern
  9469.                               the colors of various parts of the display. 
  9470.                               This color array has the same structure as the
  9471.                               color array required by PICKREC().  See the
  9472.                               table below.
  9473.  
  9474.    Returns:     Selected <rtrn_field> contents, or a null string if escape
  9475.                 pressed.
  9476.  
  9477.    Description: POPUPPICK() is a database function to provide a pop-up
  9478.  
  9479.  
  9480.    RLIB Function Reference                                                155
  9481.  
  9482.  
  9483.                 listing for a database.  It is particularly helpful in
  9484.                 applications where you need a consistent convention for
  9485.                 calling help pick lists.  POPUPPICK() is also very useful for
  9486.                 creating pick lists in data entry validation functions.
  9487.  
  9488.    Notes:       The first five parameters are required.  If any of the
  9489.                 remaining parameters are to be skipped, you must pass a dummy
  9490.                 parameter such as a null in its place.  The message is
  9491.                 displayed on line 24 (or MAXROW() in the 5.0 version) in the
  9492.                 current color setting before the color is changed.
  9493.  
  9494.                 POPUPPICK() assumes the required database(s) is/are already
  9495.                 opened.  The database need not be SELECTed if the alias name
  9496.                 parameter is specified.
  9497.  
  9498.                 <colors>
  9499.  
  9500.                 Element#  Description                Default
  9501.                 --------  -------------------------  ----------------------
  9502.                 color[1]  Normal text display        Standard - SETCOLOR()
  9503.                 color[2]  Selected or Marked         BRIGHT() Standard
  9504.                 color[3]  Hi-lited (scroll bar)      Enhanced
  9505.                 color[4]  Hi-lited & Selected/Marked Enhanced/Bright/Blinking
  9506.                 color[5]  Color on exit from XITKEYS BRIGHT() Standard 
  9507.                 color[6]  Normal text IF (color[8])  Standard - SETCOLOR()
  9508.                 color[7]  Hi-lited IF (color[8])     Enhanced
  9509.                 color[8]  Character condition        (.T.)
  9510.  
  9511.  
  9512.    Example:     *------------------------------------------------------------
  9513.                 * Procedure: Help
  9514.                 * Purpose:   Help facility, called with SET KEY 28 TO Help
  9515.                 *------------------------------------------------------------
  9516.                 PROCEDURE Help
  9517.                 PARAMETERS callproc, linenum, readvar
  9518.                 PRIVATE htop, hleft, hbottom, hright, houtput, hmessage
  9519.                 PRIVATE htitle, hfield, halias, hpick
  9520.  
  9521.  
  9522.                 *-- By default, Clipper starts every application with the F1
  9523.                 *-- key set to call Help.  This is equivilent to issuing the
  9524.                 *-- command: SET KEY 28 TO Help.  Since we don't want Help to
  9525.                 *-- be called recursively while in Help, we need to disable
  9526.                 *-- the F1 help key with the following command:
  9527.                 SET KEY 28 TO               
  9528.  
  9529.                 IF readvar == "VENDOR"
  9530.                    htop     =  1
  9531.                    hleft    = 78            && will force right alignment
  9532.                    hbottom  = 22
  9533.                    hright   = 79
  9534.                    houtput  = "' '+VENDOR->name"
  9535.                    hmessage = "Select a vendor from the following list"
  9536.                    htitle   = "VENDOR LISTING"
  9537.  
  9538.  
  9539.    RLIB Function Reference                                                156
  9540.  
  9541.  
  9542.                    hfield   = "VENDOR->name"
  9543.                    halias   = "Vendors"
  9544.                    hpick    = PopUpPick( htop, hleft, hbottom, hright,;
  9545.                                          houtput, hmessage, htitle,;
  9546.                                          hfield, halias )
  9547.  
  9548.                    IF LASTKEY() != 27
  9549.                       M->vendor = STRETCH( hpick, LEN(M->vendor) )
  9550.                    ENDIF
  9551.                 ENDIF
  9552.  
  9553.                 *-- ok, now turn Help back on
  9554.                 SET KEY 28 TO help
  9555.                 RETURN
  9556.  
  9557.    Source:      RL_POPUP.PRG
  9558.  
  9559.    See also:    PICKREC(), RH_HEADER(), RH_LINES(), RH_TEXT(), RH_WIDTH()
  9560.  
  9561.  
  9562.  
  9563.  
  9564.  
  9565.  
  9566.  
  9567.  
  9568.  
  9569.  
  9570.  
  9571.  
  9572.  
  9573.  
  9574.  
  9575.  
  9576.  
  9577.  
  9578.  
  9579.  
  9580.  
  9581.  
  9582.  
  9583.  
  9584.  
  9585.  
  9586.  
  9587.  
  9588.  
  9589.  
  9590.  
  9591.  
  9592.  
  9593.  
  9594.  
  9595.  
  9596.  
  9597.  
  9598.    RLIB Function Reference                                                157
  9599.  
  9600.  
  9601.    Function:    PRINTCODE()
  9602.  
  9603.    Purpose:     Convert text printer codes into actual escape sequence codes.
  9604.  
  9605.    Syntax:      PRINTCODE( textcodes )
  9606.  
  9607.    Arguments:   textcodes   - The character text printer codes to parse and
  9608.                               convert into actual printer control codes.
  9609.  
  9610.    Returns:     The parsed printer control codes.
  9611.  
  9612.    Description: PRINTCODE() is a printer function that helps application
  9613.                 programmers easily store and retrieve printer control codes
  9614.                 as character strings that can be edited.
  9615.  
  9616.                 The format of the <textcodes> string is industry familiar. 
  9617.                 ASCII codes are entered as a series of comma delimited
  9618.                 numbers, each one representing one control character.  Actual
  9619.                 characters may be entered instead of or in conjunction with
  9620.                 ASCII codes, the only requirement being that literal codes
  9621.                 are enclosed in double or single quote delimiters.
  9622.  
  9623.    Notes:       Printer control strings that are parsed by PRINTCODE() have
  9624.                 either the form: "27,'(s3B'", or "27,40,115,51,66".  The
  9625.                 first format combines an ASCII character designation for the
  9626.                 escape character (ASCII value = 27 decimal) followed by the
  9627.                 actual literal character sequence "(s3B".  The second example
  9628.                 specifies the escape sequence as a list of decimal ASCII
  9629.                 values.
  9630.  
  9631.                 The PRINTCODE() function is used by the REPORTINIT() function
  9632.                 to initialize printer control codes.
  9633.  
  9634.    Example:     *-- store some LaserJet control codes in a database
  9635.                 USE printers
  9636.                 REPLACE reset     WITH "27,'E'"
  9637.                 REPLACE bold_on   WITH "27,'(s3B'"
  9638.                 REPLACE bold_off  WITH "27,'(s0B'"
  9639.  
  9640.                 *-- or it could be entered as
  9641.                 REPLACE bold_off  WITH "27,40,115,51,66"
  9642.  
  9643.                 *-- use PRINTCODE() to translate codes stored in a database
  9644.                 *-- and place printer in Bold mode
  9645.                 ? PRINTCODE(reset) + PRINTCODE(bold_on)
  9646.                 ?? "RLIB users program quicker and better!"
  9647.                 ?? PRINTCODE(bold_off)
  9648.  
  9649.                 *-- or, create character enhancement functions
  9650.                 ? BOLD("Hello RLIB world")
  9651.  
  9652.                 *-- where the following function is defined
  9653.                 *-------------------------------------------------------
  9654.                 FUNCTION Bold
  9655.  
  9656.  
  9657.    RLIB Function Reference                                                158
  9658.  
  9659.  
  9660.                 PARAMETER string
  9661.                 RETURN PRINTCODE(bold_on) + string + PRINTCODE(bold_off)
  9662.  
  9663.    Source:      RL_PRINT.PRG
  9664.  
  9665.    See also:    REPORTINIT(), STARTREPORT()
  9666.  
  9667.  
  9668.  
  9669.  
  9670.  
  9671.  
  9672.  
  9673.  
  9674.  
  9675.  
  9676.  
  9677.  
  9678.  
  9679.  
  9680.  
  9681.  
  9682.  
  9683.  
  9684.  
  9685.  
  9686.  
  9687.  
  9688.  
  9689.  
  9690.  
  9691.  
  9692.  
  9693.  
  9694.  
  9695.  
  9696.  
  9697.  
  9698.  
  9699.  
  9700.  
  9701.  
  9702.  
  9703.  
  9704.  
  9705.  
  9706.  
  9707.  
  9708.  
  9709.  
  9710.  
  9711.  
  9712.  
  9713.  
  9714.  
  9715.  
  9716.    RLIB Function Reference                                                159
  9717.  
  9718.  
  9719.    Function:    QUERY()
  9720.  
  9721.    Purpose:     Create a logical query/filter string via menu prompts.
  9722.  
  9723.    Syntax:      QUERY( [ names [, fields [, types ] ] ] )
  9724.  
  9725.    Arguments:   names       - Optional character array containing the field
  9726.                               names or expression names to pop up as
  9727.                               selections to the query builder.  If omitted or
  9728.                               an invalid parameter is passed, the default
  9729.                               will be all field names in the currently
  9730.                               selected database.
  9731.  
  9732.                 fields      - Optional character array containing the field
  9733.                               or expressions to be evaluated corresponding to
  9734.                               the fields or expression names in the <names>
  9735.                               array.  If omitted or an invalid parameter is
  9736.                               passed, the default will be all field names in
  9737.                               the currently selected database.
  9738.  
  9739.                 types       - Optional array of single character elements in
  9740.                               which each element identifies the type to use
  9741.                               in the query process for each corresponding
  9742.                               expression in the <fields> array.  If a given
  9743.                               type element is not character in type, or is
  9744.                               not one of the characters C,N,D,L,M then the
  9745.                               query type will be determined by the actual
  9746.                               type of the <fields> element.
  9747.  
  9748.    Returns:     A character string containing the selected <fields>
  9749.                 expressions which must evaluate to a logical true or false
  9750.                 when expanded via macro expansion.
  9751.  
  9752.    Description: QUERY() is a high level full screen function that provides
  9753.                 menu driven access to a powerful query builder.  A list of
  9754.                 fields or expressions from the current database is presented
  9755.                 from which the user selects.  After a field is selected, a
  9756.                 menu of operators for the particular data type of the field
  9757.                 is presented.  Once an operator is selected, the query data
  9758.                 is requested.  An optional array of expressions may be given
  9759.                 in place of default field names.  QUERY() provides a very
  9760.                 sophisticated and powerful tool to give end-user applications
  9761.                 full report query control.
  9762.  
  9763.                 To learn more about the power of QUERY() see the RLIB Message
  9764.                 Reader demo program, and select the Query option!
  9765.  
  9766.    Notes:       The <names> array contains the names you want shown in the
  9767.                 pop up selection box.  The <fields> array contains the actual
  9768.                 field or expression names to be evaluated.  For instance if
  9769.                 one of the fields is named MSG_CNT, specify "Message Count"
  9770.                 in the <names> array whereas in the <fields> array specify
  9771.                 "MSG_CNT".  This lets the user pick a descriptive field from
  9772.                 the list and be shielded from the actual cryptic field names.
  9773.  
  9774.  
  9775.    RLIB Function Reference                                                160
  9776.  
  9777.  
  9778.                 If the <names> array is omitted (or skipped by passing a
  9779.                 dummy parameter) then the <fields> array will default to the
  9780.                 same names in the <names> array EVEN IF YOU SPECIFY A
  9781.                 <fields> ARRAY.  This is because the names must match the
  9782.                 fields.
  9783.  
  9784.                 The <fields> array may contain any valid expressions,
  9785.                 including references to user-defined functions.  The only
  9786.                 criteria is that the expression must evaluate correctly at
  9787.                 run-time.  The query builder will check all expressions and
  9788.                 if an invalid expression is encountered will set RLIBERROR()
  9789.                 and return a null.
  9790.  
  9791.                 The <types> array allows you to force QUERY to pop up a
  9792.                 specific selection scheme regardless of the actual type of
  9793.                 the <fields> array element selected.  A specific example of
  9794.                 this is when you supply a <fields> element that uses
  9795.                 QUERY()'s built in macro substitution, or replaceable
  9796.                 parameter.  Suppose for instance that the <fields> element is
  9797.                 "CONTAINS('%v')" and the CONTAINS() UDF returns a logical
  9798.                 type result.  By default QUERY() would evaluate CONTAINS() as
  9799.                 logical and present the selection window for a True or False
  9800.                 selection.  But suppose the purpose of your CONTAINS()
  9801.                 function was to take a character parameter, and return true
  9802.                 if that parameter was contained in multiple records (hence
  9803.                 why you could not simply use the $ operator.)  By giving a
  9804.                 <types> element of "C", QUERY would present the character
  9805.                 selection choices, then insert your selection into CONTAINS()
  9806.                 by virtue of the macro %v option.  See the example for a more
  9807.                 detailed and specific example.
  9808.  
  9809.                 The three macros are: 
  9810.  
  9811.                             %v   -  Replace %v with the data value entered,
  9812.                                     as a character string.
  9813.  
  9814.                             %o   -  Replace %o with the operator (i.e. =, <,
  9815.                                     > ) as a character string.
  9816.  
  9817.                             %c   -  Replace %c with ".T." if case is to be
  9818.                                     honored, or ".F." if case is to be
  9819.                                     ignored.
  9820.  
  9821.                 <types> is an advanced feature which you do not have to use. 
  9822.                 It is there to provide total control over the query building
  9823.                 process.  USE IT WITH CARE!  Query() normally verifies that
  9824.                 all field expressions are valid.  However, because of the
  9825.                 macro substitution feature these fields would not otherwise
  9826.                 evaluate.  So if you plan on using the %% feature you will
  9827.                 HAVE to supply a TYPE for each field that uses %% AND Query
  9828.                 will bypass the expression validation for each of those
  9829.                 fields.
  9830.  
  9831.                 RLIBQUERY: 
  9832.  
  9833.  
  9834.    RLIB Function Reference                                                161
  9835.  
  9836.  
  9837.                 In addition to returning a logical expression value, QUERY()
  9838.                 declares a public variable named RLIBQUERY.  Query() stores
  9839.                 the resulting query text, that shows in the query window, in
  9840.                 this public variable for your reference.  It is a character
  9841.                 string with hard carriage returns between each statement and
  9842.                 can easily be displayed with MEMOEDIT().
  9843.  
  9844.                 The Example
  9845.  
  9846.                 In the example below there are two databases.  The first is
  9847.                 named INVOICES and contains records of all invoices created. 
  9848.                 The second database, DETAIL contains the detail for each line
  9849.                 item associated with an invoice.  Each DETAIL record
  9850.                 represents one line item entry into an invoice and each 
  9851.                 record contains the invoice number which is the key to the
  9852.                 parent invoice.
  9853.  
  9854.                 Most of the field names, descriptions and types are self-
  9855.                 explanatory and the defaults will suffice.  However, scanning
  9856.                 the line item DETAIL file can be tricky.  This is a perfect
  9857.                 example of how to use the macros built into QUERY().  The
  9858.                 third <fields> element is "DetailDesc('%v',%c).  This is a
  9859.                 user-defined function that accepts two parameters.  The first
  9860.                 parameter is a text string for which to scan the DETAIL line
  9861.                 item description records and the second is a logical value
  9862.                 indicating whether case should be respected.  DetailDesc()
  9863.                 returns a logical True if a detail record is found which
  9864.                 contains the indicated text. For this reason the <types>
  9865.                 array element must be forced to "C" to tell QUERY() to ask
  9866.                 the user for character type data rather than logical, the
  9867.                 default for the DetailDesc() function.  (Also, QUERY() cannot
  9868.                 properly evaluate DetailDesc() at runtime to determine its
  9869.                 type because of the embedded macro references.
  9870.  
  9871.                 Once the query is built a temporary index is created.  The
  9872.                 index evaluates the query and if a record meets the query
  9873.                 condition, it is placed at the front of the index.  This is
  9874.                 accomplished through the use of the IF() function.  Once
  9875.                 indexed, the "subset" or "view" of records meeting the query
  9876.                 is presented for view with PICKREC() with the condition being
  9877.                 that all records must meet the query condition.
  9878.  
  9879.    Example:     DECLARE names[5], fields[5], types[5]
  9880.  
  9881.                 names[1] = "Invoice Number"
  9882.                 names[2] = "PO Number"
  9883.                 names[3] = "Item Description"
  9884.                 names[4] = "Amount Paid"
  9885.                 names[5] = "Date Paid"
  9886.  
  9887.                 fields[1] = "INVOICE"
  9888.                 fields[2] = "PONUMBER"
  9889.                 fields[3] = "DetailDesc('%v',%c)"
  9890.                 fields[4] = "AMTPAID"
  9891.  
  9892.  
  9893.    RLIB Function Reference                                                162
  9894.  
  9895.  
  9896.                 fields[5] = "DATEPAID"
  9897.  
  9898.                 types[1] = ""
  9899.                 types[2] = ""
  9900.                 types[3] = "C"
  9901.                 types[4] = ""
  9902.                 types[5] = ""
  9903.  
  9904.                 *-- open the necessary databases, return if not successful
  9905.                 IF .NOT. OPENED( "invoices", "detail INDEX detail" )
  9906.                    RETURN
  9907.                 ENDIF
  9908.  
  9909.                 *-- clear screen for the query, if selected, proceed
  9910.                 CLEAR
  9911.                 SELECT Invoices
  9912.                 tempntx = TEMPFILE()
  9913.                 myquery = QUERY( names, fields, types )
  9914.  
  9915.                 IF .NOT. EMPTY(myquery)
  9916.                    pbox = SAYINBOX("Indexing query, one moment")
  9917.                    INDEX ON IF(&myquery,"A","Z")+Invoice TO (tempntx)
  9918.                    POPBOX(pbox)
  9919.                    fieldlist = "Invoice+' '+PoNumber+' '+STR(AmtPaid,8,2)"
  9920.                    BORDERBOX( 1, 0, 23, 79, "INVOICE QUERY RESULTS" )
  9921.                    PICKREC( 4, 1, 22, 78, fieldlist, "", myquery )
  9922.                 ENDIF
  9923.                 CLOSE DATABASES
  9924.                 ERASE (tempntx)
  9925.                 RETURN
  9926.  
  9927.                 *----------------------------------------------------------
  9928.                 * Function: DetailDesc()
  9929.                 * Syntax:   DetailDesc( string, honorcase )
  9930.                 * Notes:    The <honorcase> flag is really shown here for
  9931.                 *           example, QUERY() would force the target string
  9932.                 *           to upper case for us if the user selected the
  9933.                 *           Case Insensitive option in QUERY().
  9934.                 *----------------------------------------------------------
  9935.                 FUNCTION DetailDesc
  9936.                 PARAMETERS string, honorcase
  9937.                 PRIVATE inrecno, found
  9938.  
  9939.                 *-- first uppercase the string if not honoring case
  9940.                 IF .NOT. honorcase
  9941.                    string = UPPER(string)
  9942.                 ENDIF
  9943.  
  9944.                 *-- save the record number where we are in the detail file
  9945.                 SELECT Detail
  9946.                 inrecno = RECNO()
  9947.  
  9948.                 *-- now scan through the detail file for this invoice
  9949.                 LOCATE FOR string $ DETAIL->ItemDesc WHILE ;
  9950.  
  9951.  
  9952.    RLIB Function Reference                                                163
  9953.  
  9954.  
  9955.                       DETAIL->invoice == INVOICES->invoice
  9956.  
  9957.                 *-- fix up things and return true if string was found
  9958.                 found = FOUND()
  9959.                 GOTO (inrecno)
  9960.                 SELECT Invoices
  9961.                 RETURN found
  9962.  
  9963.    Source:      RL_QUERY.PRG
  9964.  
  9965.    See also:    STARTREPORT()
  9966.  
  9967.  
  9968.  
  9969.  
  9970.  
  9971.  
  9972.  
  9973.  
  9974.  
  9975.  
  9976.  
  9977.  
  9978.  
  9979.  
  9980.  
  9981.  
  9982.  
  9983.  
  9984.  
  9985.  
  9986.  
  9987.  
  9988.  
  9989.  
  9990.  
  9991.  
  9992.  
  9993.  
  9994.  
  9995.  
  9996.  
  9997.  
  9998.  
  9999.  
  10000.  
  10001.  
  10002.  
  10003.  
  10004.  
  10005.  
  10006.  
  10007.  
  10008.  
  10009.  
  10010.  
  10011.    RLIB Function Reference                                                164
  10012.  
  10013.  
  10014.    Function:    REPORTINIT()
  10015.  
  10016.    Purpose:     Initialize the PRINTERS and REPORTS StartReport() databases.
  10017.  
  10018.    Syntax:      REPORTINIT( [ create ] )
  10019.  
  10020.    Arguments:   create      - Optional logical value which if supplied, and
  10021.                               is True, the databases will be created even if
  10022.                               they already exist.  The default value is
  10023.                               false, which means the databases will be
  10024.                               created and filled with data only if they do
  10025.                               not already exist.
  10026.  
  10027.    Returns:     Logical true if databases created successfully and/or if they
  10028.                 currently exist, or False if they do not exist and an error
  10029.                 occurred when attempting to create and/or append records.
  10030.  
  10031.    Description: REPORTINIT() is a printer/database function that is used to
  10032.                 generically set up two database files that are used by the
  10033.                 StartReport() RLIB function.  These two files, a description,
  10034.                 their structures, and field contents follow.
  10035.  
  10036.                 PRINTERS.DBF - This database contains printer names and
  10037.                 control codes.  ReportInit() will initially create this
  10038.                 database with printer drivers for ASCII Text, HP LaserJet+,
  10039.                 and Epson FX printers.  Since it is a database file you as
  10040.                 the application programmer may design an interface to allow
  10041.                 users to add, edit, or delete records.  This can give the end
  10042.                 user complete printer control.
  10043.  
  10044.                 Structure of PRINTERS.DBF 
  10045.  
  10046.  
  10047.  
  10048.  
  10049.  
  10050.  
  10051.  
  10052.  
  10053.  
  10054.  
  10055.  
  10056.  
  10057.  
  10058.  
  10059.  
  10060.  
  10061.  
  10062.  
  10063.  
  10064.  
  10065.  
  10066.  
  10067.  
  10068.  
  10069.  
  10070.    RLIB Function Reference                                                165
  10071.  
  10072.  
  10073.                 Field Name   Type   Len   Dec  Description
  10074.                 ----------   ----   ---   ---  ----------------------------
  10075.                 NAME         C       24        Descriptive name for printer
  10076.                 PGHEIGHT     N        4     1  Printable page height inches
  10077.                 PGWIDTH      N        4     1  Printable page width in inches
  10078.                 RESET        C       60        Printer reset initialize code
  10079.                 SIX_LPI      C       60        Six lines per inch
  10080.                 EIGHT_LPI    C       60        Eight lines per inch
  10081.                 PORTRAIT     C       60        Portrait mode on (Laser only)
  10082.                 LANDSCAPE    C       60        Landscape mode on (Laser only)
  10083.                 BOLD_ON      C       60        Bold print on
  10084.                 BOLD_OFF     C       60        Bold print off
  10085.                 COND_ON      C       60        Condensed mode on
  10086.                 COND_OFF     C       60        Condensed mode off
  10087.                 WIDE_ON      C       60        Wide print on
  10088.                 WIDE_OFF     C       60        Wide print off
  10089.                 ITAL_ON      C       60        Italics font on
  10090.                 ITAL_OFF     C       60        Italics font off
  10091.                 UNDR_ON      C       60        Underline on
  10092.                 UNDR_OFF     C       60        Underline off
  10093.                 SUPER_ON     C       60        Superscript on
  10094.                 SUPER_OFF    C       60        Superscript off
  10095.                 SUB_ON       C       60        Subscript on
  10096.                 SUB_OFF      C       60        Subscript off
  10097.  
  10098.  
  10099.                 REPORTS.DBF - This database contains report definitions.  It
  10100.                 can be used as a user definable report scheme.
  10101.  
  10102.  
  10103.                 Structure of REPORTS.DBF
  10104.  
  10105.  
  10106.                 Field Name   Type   Len   Dec  Description
  10107.                 ----------   ----   ---   ---  ----------------------------
  10108.                 NAME         C       40        Descriptive name for report
  10109.                 TITLE        C       40        Definable title for report
  10110.                 DESCRIP      C      254        Description of report
  10111.                 PRNAME       C       24        Selected printer driver name
  10112.                 WIDTH        N        3     0  Report width in columns
  10113.                 PITCH        C        1        N=Normal, C=Condensed
  10114.                 ORIENT       C        1        P=Portrait, L=Landscape
  10115.                 SPACING      N        1     0  6=Six LPI, 8=Eight LPI
  10116.                 LEFTMARGIN   N        2     0  Left margin (in columns)
  10117.                 TOPMARGIN    N        2     0  Top margin (in lines)
  10118.                 BOTMARGIN    N        2     0  Bottom margin (in lines)
  10119.                 SETUPSTR     C       60     0  Additional setup string
  10120.  
  10121.    Notes:       Passing a <create> argument value of True is useful to ensure
  10122.                 that any existing PRINTERS.DBF and REPORTS.DBF have the
  10123.                 proper database structure.  The default is false.  If create
  10124.                 is specified and the file already exists, the old data will
  10125.                 be appended into the newly created files.  If you want the
  10126.                 files to be empty when created, OPENED() them then ZAP before
  10127.  
  10128.  
  10129.    RLIB Function Reference                                                166
  10130.  
  10131.  
  10132.                 calling REPORTINIT().
  10133.  
  10134.                 The printer control codes are stored in the PRINTERS database
  10135.                 in a text form that can be both read and edited.  These codes
  10136.                 are converted to actual printer control codes (escape
  10137.                 sequences) using the RLIB PRINTCODE() function.  See the
  10138.                 documentation for PRINTCODE() for details.
  10139.  
  10140.    Example:     *-- preparation startup code in order to use StartReport()
  10141.                 ReportInit()
  10142.                 .
  10143.                 .
  10144.                 .
  10145.                 IF StartReport()
  10146.                    *... do report stuff here
  10147.                 ENDIF
  10148.  
  10149.    Source:      RL_REPOR.PRG
  10150.  
  10151.    See also:    PRINTCODE(), STARTREPORT()
  10152.  
  10153.  
  10154.  
  10155.  
  10156.  
  10157.  
  10158.  
  10159.  
  10160.  
  10161.  
  10162.  
  10163.  
  10164.  
  10165.  
  10166.  
  10167.  
  10168.  
  10169.  
  10170.  
  10171.  
  10172.  
  10173.  
  10174.  
  10175.  
  10176.  
  10177.  
  10178.  
  10179.  
  10180.  
  10181.  
  10182.  
  10183.  
  10184.  
  10185.  
  10186.  
  10187.  
  10188.    RLIB Function Reference                                                167
  10189.  
  10190.  
  10191.    Function:    REVDATE()
  10192.  
  10193.    Purpose:     Reverse date fields to index in reverse chronological order.
  10194.  
  10195.    Syntax:      REVDATE( date )
  10196.  
  10197.    Arguments:   date        - Date type field or variable to be reversed.
  10198.  
  10199.    Returns:     A character string which, when used as an index key, will
  10200.                 order a database in reverse chronological order with the most
  10201.                 recent dates first.
  10202.  
  10203.    Description: REVDATE() is a date function which REVerses a DATE to allow
  10204.                 indexing and/or searching on dates in descending order.  The
  10205.                 function converts the year, month, and day into a reverse
  10206.                 string format to formulate a descending date order.  As an
  10207.                 example: 
  10208.  
  10209.                 date                     = CTOD("01/31/87")
  10210.                 STR(3000-YEAR(date),4,0) = STR(3000 - 1987) = "1013" +;
  10211.                 STR(13-MONTH(date),2,0)  = STR(13 - 1 )     = "12"   +;
  10212.                 STR(32-DAY(date),2,0)    = STR(32 - 1 )     = "31"
  10213.                 REVDATE(date)            = "10131231" 
  10214.  
  10215.                 Example dates: (note that dates must be converted from char) 
  10216.  
  10217.                 REVDATE(CTOD("01/01/88")) = "10111231"
  10218.                 REVDATE(CTOD("02/01/88")) = "10111131" *-- note that this
  10219.                 places the date 02/01/88 before 01/01/88 
  10220.  
  10221.    Notes:       Since REVDATE() has parameter error checking built in, there
  10222.                 is some overhead associated with each function call.  If you
  10223.                 plan on using REVDATE() in an indexing key you may want to
  10224.                 remove the RlibInit() and TYPE() error checking lines to
  10225.                 decrease overhead and increase indexing speed.  However, if
  10226.                 REVDATE() is to be used dynamically, as in ad hoc user
  10227.                 querying or reporting, you as the application programmer must
  10228.                 ensure that the proper date type is passed as a parameter
  10229.                 since REVDATE() will no longer check.
  10230.  
  10231.    Example:     *-- order customer sales database with most recent sale first
  10232.                 IF .NOT.  OPENED("Sales")
  10233.                    RETURN
  10234.                 ENDIF
  10235.                 INDEX ON Customer + REVDATE(SaleDate) TO sales.ntx
  10236.  
  10237.    Source:      RL_REVDA.PRG
  10238.  
  10239.    See also:    ALPHADATE(), STR2DATE()
  10240.  
  10241.  
  10242.  
  10243.  
  10244.  
  10245.  
  10246.  
  10247.    RLIB Function Reference                                                168
  10248.  
  10249.  
  10250.    Function:    RH_HEADER()
  10251.  
  10252.    Purpose:     Retrieve the header from a RHELP compiled help file
  10253.  
  10254.    Syntax:      RH_HEADER( rhelpFile )
  10255.  
  10256.    Arguments:   rhelpFile   - This parameter may be either the rhelp compiled
  10257.                               filename, or the numeric file handle returned
  10258.                               from a previous call to FOPEN() to open the
  10259.                               help file.
  10260.  
  10261.    Returns:     The header from the specified help file.
  10262.  
  10263.    Description: This function reads and returns the header from a help file
  10264.                 that was compiled with the Rhelp compiler.  This header has a
  10265.                 specific structure, but you need not concern yourself with
  10266.                 the details of this structure unless you want to access the
  10267.                 header record elements directly.  All header and header
  10268.                 record information is available through calls to the various
  10269.                 Rhelp functions (API).
  10270.  
  10271.                 See Appendix C entitled The RHELP Compiler for more detailed
  10272.                 information and examples.
  10273.  
  10274.    Notes:       If the helpfile parameter is supplied as a character string,
  10275.                 it is deemed to be the name of the Rhelp file.  In this case
  10276.                 the help file is opened (using FOPEN()), the header is then
  10277.                 extracted, the help file closed, and the header returned.  If
  10278.                 the FOPEN() fails, a null is returned, and RLIBERROR() set.
  10279.  
  10280.                 If the helpfile parameter is supplied as a numeric value, it
  10281.                 is deemed to be the numeric file handle returned by
  10282.                 previously FOPEN()ing the help file.  In this case, the
  10283.                 header is read and returned, but the file is not closed. 
  10284.                 This feature allows you the flexibility of leaving the help
  10285.                 file open during the course of your application, therefore
  10286.                 speeding up access by not having to constantly open and close
  10287.                 the help file.  This method of access is not recommended if
  10288.                 you are short on file handles or you are not comfortable with
  10289.                 low level file operations.  If you use this method, always
  10290.                 remember to FCLOSE() your files.
  10291.  
  10292.                 You should not need to explicitly extract the header since
  10293.                 all help functions are available.  However, the header may be
  10294.                 manipulated directly for speed considerations.  Also, the
  10295.                 other help functions use this function to extract the header.
  10296.  
  10297.    Example:     helpHeader = RH_HEADER("myapp.hlp")
  10298.  
  10299.                 *-- or
  10300.  
  10301.                 helpHandle = FOPEN("myapp.hlp")
  10302.                 helpHeader = RH_HEADER( helpHandle )
  10303.  
  10304.  
  10305.  
  10306.    RLIB Function Reference                                                169
  10307.  
  10308.  
  10309.    Source:      RL_RHELP.PRG
  10310.  
  10311.    See also:    RH_TEXT(), RH_WIDTH(), RH_LINES()
  10312.  
  10313.  
  10314.  
  10315.  
  10316.  
  10317.  
  10318.  
  10319.  
  10320.  
  10321.  
  10322.  
  10323.  
  10324.  
  10325.  
  10326.  
  10327.  
  10328.  
  10329.  
  10330.  
  10331.  
  10332.  
  10333.  
  10334.  
  10335.  
  10336.  
  10337.  
  10338.  
  10339.  
  10340.  
  10341.  
  10342.  
  10343.  
  10344.  
  10345.  
  10346.  
  10347.  
  10348.  
  10349.  
  10350.  
  10351.  
  10352.  
  10353.  
  10354.  
  10355.  
  10356.  
  10357.  
  10358.  
  10359.  
  10360.  
  10361.  
  10362.  
  10363.  
  10364.  
  10365.    RLIB Function Reference                                                170
  10366.  
  10367.  
  10368.    Function:    RH_LINES()
  10369.  
  10370.    Purpose:     Get the number of text lines within a help text block
  10371.  
  10372.    Syntax:      RH_LINES( rhelpfile, help_key )
  10373.  
  10374.    Arguments:   rhelpfile   - This parameter may be either the rhelp compiled
  10375.                               filename, or the numeric file handle returned
  10376.                               from a previous call to FOPEN() to open the
  10377.                               help file.
  10378.  
  10379.                 help_key    - Character value indicating the text associated
  10380.                               as the key for the desired help.  This text can
  10381.                               any length but only the first 16 characters are
  10382.                               significant.  Case is insensitive.
  10383.  
  10384.    Returns:     Numeric line count in the associated help text block.  If the
  10385.                 specified help key is not found, or an error occurs, zero is
  10386.                 returned.
  10387.  
  10388.    Description: This function reads and returns the number of lines within a
  10389.                 block of help text associated with the help key, from a help
  10390.                 file that was compiled with the Rhelp compiler.  Knowing this
  10391.                 line count allows you to tailor the help display window size
  10392.                 to the size of the text.
  10393.  
  10394.                 The help key is a unique character string which is
  10395.                 significant to the first 16 characters, that identifies an
  10396.                 entry in the Rhelp compiled help file.  This allows help
  10397.                 systems to be queried by supplying a descriptive character
  10398.                 string.
  10399.  
  10400.                 See Appendix C entitled The RHELP Compiler for more detailed
  10401.                 information and examples.
  10402.  
  10403.    Notes:       If the helpfile parameter is supplied as a character string,
  10404.                 it is deemed to be the name of the Rhelp file.  In this case
  10405.                 the help file is opened (using FOPEN()), the header is then
  10406.                 extracted, the help file closed, and the header returned.  If
  10407.                 the FOPEN() fails, a null is returned, and RLIBERROR() set.
  10408.  
  10409.                 If the helpfile parameter is supplied as a numeric value, it
  10410.                 is deemed to be the numeric file handle returned by
  10411.                 previously FOPEN()ing the help file.  In this case, the text
  10412.                 is read and returned, but the file is not closed.  This
  10413.                 feature allows you the flexibility of leaving the help file
  10414.                 open during the course of your application, therefore
  10415.                 speeding up access by not having to constantly open and close
  10416.                 the help file.  This method of access is not recommended if
  10417.                 you are short on file handles or you are not comfortable with
  10418.                 low level file operations.  If you use this method, always
  10419.                 remember to FCLOSE() your files.
  10420.  
  10421.                 The help file pointer position is left unchanged.
  10422.  
  10423.  
  10424.    RLIB Function Reference                                                171
  10425.  
  10426.  
  10427.    Example:     helpLines = RH_LINES("myapp.hlp", "MENU HELP" )
  10428.  
  10429.                 *-- or
  10430.  
  10431.                 helpHandle = FOPEN("myapp.hlp")
  10432.                 helpLines  = RH_LINES( helpHandle, "MENU HELP" )
  10433.  
  10434.    Source:      RL_RHELP.PRG
  10435.  
  10436.    See also:    RH_HEADER(), RH_TEXT(), RH_WIDTH()
  10437.  
  10438.  
  10439.  
  10440.  
  10441.  
  10442.  
  10443.  
  10444.  
  10445.  
  10446.  
  10447.  
  10448.  
  10449.  
  10450.  
  10451.  
  10452.  
  10453.  
  10454.  
  10455.  
  10456.  
  10457.  
  10458.  
  10459.  
  10460.  
  10461.  
  10462.  
  10463.  
  10464.  
  10465.  
  10466.  
  10467.  
  10468.  
  10469.  
  10470.  
  10471.  
  10472.  
  10473.  
  10474.  
  10475.  
  10476.  
  10477.  
  10478.  
  10479.  
  10480.  
  10481.  
  10482.  
  10483.    RLIB Function Reference                                                172
  10484.  
  10485.  
  10486.    Function:    RH_TEXT()
  10487.  
  10488.    Purpose:     Get help text for specified help key from compiled .HLP file
  10489.  
  10490.    Syntax:      RH_TEXT( rhelpfile, help_key )
  10491.  
  10492.    Arguments:   rhelpfile   - This parameter may be either the rhelp compiled
  10493.                               filename, or the numeric file handle returned
  10494.                               from a previous call to FOPEN() to open the
  10495.                               help file.
  10496.  
  10497.                 help_key    - Character value indicating the text associated
  10498.                               as the key for the desired help.  This text can
  10499.                               any length but only the first 16 characters are
  10500.                               significant.  Case is insensitive.
  10501.  
  10502.    Returns:     The associated help text block as a character string.  If the
  10503.                 specified help key is not found, or an error occurs, a null
  10504.                 string ("") is returned.
  10505.  
  10506.    Description: This function reads and returns a block of help text
  10507.                 associated with the specified help key from a help file that
  10508.                 was compiled with the Rhelp compiler.  The help key is a
  10509.                 unique character string that identifies an entry in the Rhelp
  10510.                 compiled help file.  This allows help systems to be queried
  10511.                 by supplying a descriptive character string.  RH-TEXT()
  10512.                 function does all the work.
  10513.  
  10514.                 See Appendix C entitled The RHELP Compiler for more detailed
  10515.                 information and examples.
  10516.  
  10517.    Notes:       If the helpfile parameter is supplied as a character string,
  10518.                 it is deemed to be the name of the Rhelp file.  In this case
  10519.                 the help file is opened (using FOPEN()), the header is then
  10520.                 extracted, the help file closed, and the header returned.  If
  10521.                 the FOPEN() fails, a null is returned, and RLIBERROR() set.
  10522.  
  10523.                 If the helpfile parameter is supplied as a numeric value, it
  10524.                 is deemed to be the numeric file handle returned by
  10525.                 previously FOPEN()ing the help file.  In this case, the text
  10526.                 is read and returned, but the file is not closed.  This
  10527.                 feature allows you the flexibility of leaving the help file
  10528.                 open during the course of your application, therefore
  10529.                 speeding up access by not having to constantly open and close
  10530.                 the help file.  This method of access is not recommended if
  10531.                 you are short on file handles or you are not comfortable with
  10532.                 low level file operations.  If you use this method, always
  10533.                 remember to FCLOSE() your files.
  10534.  
  10535.                 After reading the help text, the file pointer position is
  10536.                 left after the text (perhaps at the next text location.) 
  10537.  
  10538.    Example:     helpText = RH_TEXT("myapp.hlp", "MENU HELP" )
  10539.  
  10540.  
  10541.  
  10542.    RLIB Function Reference                                                173
  10543.  
  10544.  
  10545.                 *-- or
  10546.  
  10547.                 helpHandle = FOPEN("myapp.hlp")
  10548.                 helpText = RH_TEXT( helpHandle, "MENU HELP" )
  10549.  
  10550.    Source:      RL_RHELP.PRG
  10551.  
  10552.    See also:    RH_HEADER(), RH_WIDTH(), RH_LINES()
  10553.  
  10554.  
  10555.  
  10556.  
  10557.  
  10558.  
  10559.  
  10560.  
  10561.  
  10562.  
  10563.  
  10564.  
  10565.  
  10566.  
  10567.  
  10568.  
  10569.  
  10570.  
  10571.  
  10572.  
  10573.  
  10574.  
  10575.  
  10576.  
  10577.  
  10578.  
  10579.  
  10580.  
  10581.  
  10582.  
  10583.  
  10584.  
  10585.  
  10586.  
  10587.  
  10588.  
  10589.  
  10590.  
  10591.  
  10592.  
  10593.  
  10594.  
  10595.  
  10596.  
  10597.  
  10598.  
  10599.  
  10600.  
  10601.    RLIB Function Reference                                                174
  10602.  
  10603.  
  10604.    Function:    RH_WIDTH()
  10605.  
  10606.    Purpose:     Get the maximum line width within a help text block
  10607.  
  10608.    Syntax:      RH_WIDTH( rhelpfile, help_key )
  10609.  
  10610.    Arguments:   rhelpfile   - This parameter may be either the rhelp compiled
  10611.                               filename, or the numeric file handle returned
  10612.                               from a previous call to FOPEN() to open the
  10613.                               help file.
  10614.  
  10615.                 help_key    - Character value indicating the text associated
  10616.                               as the key for the desired help.  This text can
  10617.                               any length but only the first 16 characters are
  10618.                               significant.  Case is insensitive.
  10619.  
  10620.    Returns:     Numeric maximum line width with the associated help text
  10621.                 block.  If the specified help key is not found, or an error
  10622.                 occurs, zero is returned.
  10623.  
  10624.    Description: This function reads and returns a block of the maximum line
  10625.                 width of all the text lines within a help text associated
  10626.                 with the specified help key, from a help file that was
  10627.                 compiled with the Rhelp compiler.  Knowing this maximum width
  10628.                 allows you to tailor the help display window width to the
  10629.                 size of the text.
  10630.  
  10631.                 The help key is a unique character string which is
  10632.                 significant to the first 16 characters, that identifies an
  10633.                 entry in the Rhelp compiled help file.  This allows help
  10634.                 systems to be queried by supplying a descriptive character
  10635.                 string.
  10636.  
  10637.                 See Appendix C entitled The RHELP Compiler for more detailed
  10638.                 information and examples.
  10639.  
  10640.    Notes:       If the helpfile parameter is supplied as a character string,
  10641.                 it is deemed to be the name of the Rhelp file.  In this case
  10642.                 the help file is opened (using FOPEN()), the header is then
  10643.                 extracted, the help file closed, and the header returned.  If
  10644.                 the FOPEN() fails, a null is returned, and RLIBERROR() set.
  10645.  
  10646.                 If the helpfile parameter is supplied as a numeric value, it
  10647.                 is deemed to be the numeric file handle returned by
  10648.                 previously FOPEN()ing the help file.  In this case, the text
  10649.                 is read and returned, but the file is not closed.  This
  10650.                 feature allows you the flexibility of leaving the help file
  10651.                 open during the course of your application, therefore
  10652.                 speeding up access by not having to constantly open and close
  10653.                 the help file.  This method of access is not recommended if
  10654.                 you are short on file handles or you are not comfortable with
  10655.                 low level file operations.  If you use this method, always
  10656.                 remember to FCLOSE() your files.
  10657.  
  10658.  
  10659.  
  10660.    RLIB Function Reference                                                175
  10661.  
  10662.  
  10663.                 The help file pointer position is left unchanged.
  10664.  
  10665.    Example:     helpMaxWidth = RH_WIDTH("myapp.hlp", "MENU HELP" )
  10666.  
  10667.                 *-- or
  10668.  
  10669.                 helpHandle = FOPEN("myapp.hlp")
  10670.                 helpMaxWidth = RH_WIDTH( helpHandle, "MENU HELP" )
  10671.  
  10672.    Source:      RL_RHELP.PRG
  10673.  
  10674.    See also:    RH_HEADER(), RH_TEXT(), RH_LINES()
  10675.  
  10676.  
  10677.  
  10678.  
  10679.  
  10680.  
  10681.  
  10682.  
  10683.  
  10684.  
  10685.  
  10686.  
  10687.  
  10688.  
  10689.  
  10690.  
  10691.  
  10692.  
  10693.  
  10694.  
  10695.  
  10696.  
  10697.  
  10698.  
  10699.  
  10700.  
  10701.  
  10702.  
  10703.  
  10704.  
  10705.  
  10706.  
  10707.  
  10708.  
  10709.  
  10710.  
  10711.  
  10712.  
  10713.  
  10714.  
  10715.  
  10716.  
  10717.  
  10718.  
  10719.    RLIB Function Reference                                                176
  10720.  
  10721.  
  10722.    Function:    RJUSTIFY()
  10723.  
  10724.    Purpose:     Right justify string by moving trailing blanks to the front.
  10725.  
  10726.    Syntax:      RJUSTIFY( string )
  10727.  
  10728.    Arguments:   string      - Character string or variable to be right
  10729.                               justified.
  10730.  
  10731.    Returns:     String with trailing blanks moved to the front of the string.
  10732.  
  10733.    Description: Takes a character string and moves any trailing blanks to the
  10734.                 front of the string, to allow for right justification in
  10735.                 display or printing.
  10736.  
  10737.    Notes:       Useful for displaying or printing character data that may
  10738.                 have trailing blanks flush right in reports.
  10739.  
  10740.                 The string returned is the same length as the one provided.
  10741.  
  10742.    Example:     acct_num = SPACE(20)
  10743.                 @ 1,0 SAY "Enter account number:" GET acct_num
  10744.                 READ
  10745.  
  10746.                 *-- they entered 12-34-567890 which has 8 trailing spaces
  10747.                 *-- you want it printed flush right under the page number
  10748.                 *-- on an 80 column display
  10749.                 @ 1,67 SAY "Page No.: " + STR(pageno,3,0)
  10750.                 @ 1,60 SAY RJUSTIFY(acct_num)
  10751.                 *-- replaces: @ 1,60+20-LEN(TRIM(acct_num)) SAY ...
  10752.  
  10753.    Source:      RL_RJUST.PRG
  10754.  
  10755.    See also:    CENTER(), MIDDLE(), SAYINBOX()
  10756.  
  10757.  
  10758.  
  10759.  
  10760.  
  10761.  
  10762.  
  10763.  
  10764.  
  10765.  
  10766.  
  10767.  
  10768.  
  10769.  
  10770.  
  10771.  
  10772.  
  10773.  
  10774.  
  10775.  
  10776.  
  10777.  
  10778.    RLIB Function Reference                                                177
  10779.  
  10780.  
  10781.    Function:    RLIBERROR()
  10782.  
  10783.    Purpose:     Return and, optionally set, the last RLIB error number.
  10784.  
  10785.    Syntax:      RLIBERROR( [newerror] )
  10786.  
  10787.    Arguments:   newerror    - Optional numeric value to set RLIBERROR.
  10788.  
  10789.    Returns:     The last RLIB error number.
  10790.  
  10791.    Description: This is an error function used to query for the last error
  10792.                 that occurred in an RLIB function.  Optionally this error
  10793.                 value may be set to a new value.  This capability is used
  10794.                 primarily by all RLIB functions internally to set the error
  10795.                 value initially to zero, and to set the error value if and
  10796.                 when an error occurs.
  10797.  
  10798.                 For a complete list of RLIB error values and their meanings,
  10799.                 see Appendix A - RLIB Error Codes.
  10800.  
  10801.    Notes:       Every RLIB function sets this error value to zero on entry.
  10802.  
  10803.    Example:     IF .NOT.  OPENED("dbf1 INDEX ntx1", "dbf2 INDEX ntx2")
  10804.                    *-- OPENED() returned False, but why.....
  10805.                    DO CASE
  10806.                    CASE RLIBERROR() = 1101
  10807.                       message = "File sharing violation"
  10808.                    CASE RLIBERROR() = 1102
  10809.                       message = "Database file not found"
  10810.                    CASE RLIBERROR() = 1103
  10811.                       message = "Associated index file not found"
  10812.                    CASE RLIBERROR() = 1104
  10813.                       message = "Associated memo file not found"
  10814.                    CASE RLIBERROR() = 1105
  10815.                       message = "Invalid alias name or other syntax error"
  10816.                    ENDCASE
  10817.                    BOXASK( "W+/R", "Error opening required database files:",;
  10818.                             message, "Press any key to continue" )
  10819.                 ENDIF
  10820.  
  10821.    Source:      RL_RLIBE.PRG
  10822.  
  10823.    See also:    RLIBINIT(), RLIBVER()
  10824.  
  10825.  
  10826.  
  10827.  
  10828.  
  10829.  
  10830.  
  10831.  
  10832.  
  10833.  
  10834.  
  10835.  
  10836.  
  10837.    RLIB Function Reference                                                178
  10838.  
  10839.  
  10840.    Function:    RLIBINIT()
  10841.  
  10842.    Purpose:     Initialize internal RLIB PUBLIC/STATIC variable(s).
  10843.  
  10844.    Syntax:      RLIBINIT()
  10845.  
  10846.    Arguments:   None
  10847.  
  10848.    Returns:     Zero 
  10849.  
  10850.    Description: This is an internal function which is called at the beginning
  10851.                 of every RLIB function.  Its purpose is to initialize the
  10852.                 PUBLIC variable <rliberror> to zero.  This variable is used
  10853.                 throughout as a debugging aid to return information about the
  10854.                 state and/or failure code of an RLIB function.  See Appendix
  10855.                 A - RLIB Error Codes for more information.
  10856.  
  10857.    Notes:       The additional benefit of this central function comes in its
  10858.                 central nature.  Global modifiers can easily be added to all
  10859.                 Rlib functions in this module.
  10860.  
  10861.    Example:     Used internally.  See individual function code.
  10862.  
  10863.    Source:      RL_RLIBI.PRG
  10864.  
  10865.    See also:    RLIBVER()
  10866.  
  10867.  
  10868.  
  10869.  
  10870.  
  10871.  
  10872.  
  10873.  
  10874.  
  10875.  
  10876.  
  10877.  
  10878.  
  10879.  
  10880.  
  10881.  
  10882.  
  10883.  
  10884.  
  10885.  
  10886.  
  10887.  
  10888.  
  10889.  
  10890.  
  10891.  
  10892.  
  10893.  
  10894.  
  10895.  
  10896.    RLIB Function Reference                                                179
  10897.  
  10898.  
  10899.    Function:    RLIBVER()
  10900.  
  10901.    Purpose:     Retrieve the version number of the RLIB.LIB linked.
  10902.  
  10903.    Syntax:      RLIBVER()
  10904.  
  10905.    Arguments:   None
  10906.  
  10907.    Returns:     The version of RLIB linked as a character string such as
  10908.                 "3.00"
  10909.  
  10910.    Description: Use this to test for a proper version.  Useful when debugging
  10911.                 so you don't end up chasing what you think was a bug for
  10912.                 three hours only to find you had linked in an older version
  10913.                 of RLIB.
  10914.  
  10915.    Notes:       Returns the version as a character string NOT a number! 
  10916.  
  10917.    Example:     IF RLIBVER() < "3.0"
  10918.                    ? "Update now!"
  10919.                 ENDIF
  10920.  
  10921.    Source:      RL_RLIBV.PRG
  10922.  
  10923.    See also:    RLIBERROR(), RLIBINIT()
  10924.  
  10925.  
  10926.  
  10927.  
  10928.  
  10929.  
  10930.  
  10931.  
  10932.  
  10933.  
  10934.  
  10935.  
  10936.  
  10937.  
  10938.  
  10939.  
  10940.  
  10941.  
  10942.  
  10943.  
  10944.  
  10945.  
  10946.  
  10947.  
  10948.  
  10949.  
  10950.  
  10951.  
  10952.  
  10953.  
  10954.  
  10955.    RLIB Function Reference                                                180
  10956.  
  10957.  
  10958.    Function:    SAYINBOX()
  10959.  
  10960.    Purpose:     Pop up a centered message box using multiple message strings.
  10961.  
  10962.    Syntax:      SAYINBOX( [color] message1 [...message9] [timeout] )
  10963.  
  10964.    Arguments:   color       - If the FIRST parameter has a slash "/"
  10965.                               character in the 2nd, 3rd, or 4th position, 
  10966.                               this parameter will be interpreted as the color
  10967.                               setting for the message box.  (All color
  10968.                               strings look like: R/W, or R+/W, or R+*/W) 
  10969.  
  10970.                 message1,9  - Any other character parameters, including the
  10971.                               first and or second parameters if they don't
  10972.                               meet the above conditions, will be displayed as
  10973.                               BOXASK() messages.  Up to nine message lines
  10974.                               may be passed and displayed.
  10975.  
  10976.                 timeout     - If the LAST parameter is a numeric value, it
  10977.                               will be used as a timeout value for the message
  10978.                               box.  This timeout is the number of seconds
  10979.                               BOXASK() will wait for a keypress.  If no key
  10980.                               is pressed before the timeout is reached,
  10981.                               BOXASK() will exit and return a null string. 
  10982.                               If no timeout is supplied, BOXASK() will wait
  10983.                               forever for a keypress.
  10984.  
  10985.    Returns:     A formatted character string where the first four bytes are
  10986.                 the screen coordinates of the screen area underneath the
  10987.                 SAYINBOX() box and message, plus the SAVESCREEN() string
  10988.                 itself.  This is used as a parameter to the POPBOX() function
  10989.                 to restore a screen to its state before a SAYINBOX() message
  10990.                 was displayed.
  10991.  
  10992.    Description: SAYINBOX() is a screen function very similar to BOXASK(). 
  10993.                 However, it is different in two very distinct ways.  First,
  10994.                 BOXASK() is intended to query the user for a keypress
  10995.                 response to a message, and to return the key pressed. 
  10996.                 SAYINBOX() does not wait for key input from the user. 
  10997.                 Secondly, SAYINBOX() returns a character string which
  10998.                 contains the coordinates of the screen region displaced by
  10999.                 the SAYINBOX() image.  This character string can be used as a
  11000.                 parameter to the companion function POPBOX() to restore the
  11001.                 screen to the way it was before SAYINBOX() was called.  This
  11002.                 feature is ideal for situations where you want to put up a
  11003.                 message box, do some processing, then remove the message box
  11004.                 and restore the screen to its previous state.
  11005.  
  11006.                 This is a function that becomes addictive!  Once you start
  11007.                 using it you'll never stop.  It's perfect for displaying all
  11008.                 types of messages in a consistent manner.  SAYINBOX()
  11009.                 displays up to nine lines of text messages, centered on the
  11010.                 screen in a single line box, in a user definable color.  Each
  11011.                 line may be up to 68 characters long.  All of the screen
  11012.  
  11013.  
  11014.    RLIB Function Reference                                                181
  11015.  
  11016.  
  11017.                 centering is done for you.
  11018.  
  11019.    Notes:       SAYINBOX() accepts a variable number of parameters and will
  11020.                 act differently on the parameters depending on their format. 
  11021.                 All parameters except the timeout are expected to be of
  11022.                 character type.
  11023.  
  11024.                 If the first parameter is a color setting, SAYINBOX() will
  11025.                 use that color combination instead of the default current
  11026.                 color.
  11027.  
  11028.                 If the optional <timeout> argument is supplied, SAYINBOX()
  11029.                 will wait the specified number of seconds, then restore the
  11030.                 screen and terminate.
  11031.  
  11032.    Example:     *-- example of an INDEX message
  11033.                 pbox = SAYINBOX( "BG+/B", "Indexing, please wait" )
  11034.                 INDEX ON keyfield TO indexfile
  11035.                 POPBOX(pbox)
  11036.  
  11037.    Source:      RL_SAYIN.PRG
  11038.  
  11039.    See also:    ABOXASK(), BOXASK(), POPBOX()
  11040.  
  11041.  
  11042.  
  11043.  
  11044.  
  11045.  
  11046.  
  11047.  
  11048.  
  11049.  
  11050.  
  11051.  
  11052.  
  11053.  
  11054.  
  11055.  
  11056.  
  11057.  
  11058.  
  11059.  
  11060.  
  11061.  
  11062.  
  11063.  
  11064.  
  11065.  
  11066.  
  11067.  
  11068.  
  11069.  
  11070.  
  11071.  
  11072.  
  11073.    RLIB Function Reference                                                182
  11074.  
  11075.  
  11076.    Function:    SETCURSOR()
  11077.  
  11078.    Purpose:     Retrieve and optionally set the current cursor state.
  11079.  
  11080.    Syntax:      SETCURSOR( value )
  11081.  
  11082.    Arguments:   value       - Optional numeric argument to cause the cursor
  11083.                               state to be  changed.  <value> may be either a
  11084.                               numeric value where 1 indicates the cursor
  11085.                               should be turned ON and a value of 0 indicates
  11086.                               the cursor should be turned OFF.  <value> may
  11087.                               optionally be a logical type value where a
  11088.                               value of True (.T.) causes the cursor to be
  11089.                               turned ON and a value of False (.F.) causes the
  11090.                               cursor to be turned OFF.
  11091.  
  11092.    Returns:     The current SETCURSOR() state as a numeric value where a
  11093.                 value of one (1) means the cursor is currently ON, and a
  11094.                 value of zero (0) means the cursor is currently OFF.
  11095.  
  11096.    Description: SETCURSOR() is an environment function used to be able to
  11097.                 make functions "black boxed" such that they may return the
  11098.                 system state to the way it was after having made a change. 
  11099.                 If used consistently throughout an application, SETCURSOR()
  11100.                 provides a facility to retrieve the current state of the
  11101.                 cursor, optionally setting it on or off.
  11102.  
  11103.    Notes:       SETCURSOR() maintains the current state of the cursor via a
  11104.                 PUBLIC memvar named RLIBCURSOR.  If this variable does not
  11105.                 exist as a Numeric type variable, it is created and
  11106.                 initialized to True (assuming the cursor is ON by default).
  11107.  
  11108.                 Several RLIB functions such as BOXASK() will detect if the
  11109.                 SETCURSOR() function is being used to control the cursor
  11110.                 state by testing if the public variable RLIBCURSOR exists as
  11111.                 a numeric type variable.  If it does exist, BOXASK() will
  11112.                 turn the cursor ON (to query the user for a keypress) then
  11113.                 restore the cursor to its incoming state on exit.
  11114.  
  11115.                 The SETCURSOR() only exists in the Summer'87 version of RLIB
  11116.                 since Clipper 5.0 has a built in SETCURSOR() function.
  11117.  
  11118.    Example:     *-- save the current cursor state and turn it on
  11119.                 incursor = SETCURSOR(1)   && or SETCURSOR(.T.)
  11120.                 WAIT "Press 'Y' for Yes or 'N' for No:" TO answer
  11121.                 SETCURSOR(incursor)
  11122.                 IF answer = "Y"
  11123.                    *-- do whatever for a yes answer
  11124.                 ENDIF
  11125.  
  11126.    Source:      RL_SETCU.PRG
  11127.  
  11128.    See also:    BOXASK()
  11129.  
  11130.  
  11131.  
  11132.    RLIB Function Reference                                                183
  11133.  
  11134.  
  11135.    Function:    STARTREPORT()
  11136.  
  11137.    Purpose:     General purpose report format and print control function.
  11138.  
  11139.    Syntax:      STARTREPORT( [ reportname  [, say_colors  [, msg_color ]]] )
  11140.  
  11141.    Arguments:   reportname  - Optional character string name of the report. 
  11142.                               This name can be a name identified in a .PRG
  11143.                               module or dynamically retrieved from a pick
  11144.                               list of reports in the database REPORTS.DBF. 
  11145.                               If specified, this name is LOCATEd in the
  11146.                               reports definition database REPORTS.DBF.  If
  11147.                               not specified or the given name is not found in
  11148.                               REPORTS.DBF then the default report
  11149.                               configuration is used.  See below for this
  11150.                               default configuration.
  11151.  
  11152.                 say_colors  - Optional character color string in the same
  11153.                               format as other Clipper color strings which is
  11154.                               used for the report definition window.  Normal
  11155.                               text is displayed in the Standard color, and
  11156.                               GETs are displayed in the Enhanced color.  If
  11157.                               not specified or an invalid parameter is passed
  11158.                               the default color settings will be the current
  11159.                               SETCOLOR().
  11160.  
  11161.                 msg_color   - Optional character color string used to display
  11162.                               the SAYINBOX() message that the report is being
  11163.                               printed.  If not specified or an invalid
  11164.                               parameter is passed, the default color is the
  11165.                               current Enhanced color setting (that used for
  11166.                               GETs).
  11167.  
  11168.    Returns:     True if all is a go, false otherwise (escaped or canceled) 
  11169.  
  11170.    Description: STARTREPORT() is a high level printer function which
  11171.                 simplifies the process of formatting printed reports.  Its
  11172.                 main use is in automating all the steps necessary to set up a
  11173.                 printer for a report.  It is used in conjunction with the
  11174.                 REPORTINIT() and STOPREPORT() RLIB functions.  REPORTINIT()
  11175.                 initializes the printer and reports databases for use by
  11176.                 STARTREPORT() while STOPREPORT() cleans up printer settings
  11177.                 when the report is finished.
  11178.  
  11179.                 In addition to performing the necessary settings to send
  11180.                 output to a printer, STARTREPORT() pops up a generic report
  11181.                 configuration window which lets the end user customize the
  11182.                 appearance of any report.  The STARTREPORT() screen appears
  11183.                 as follows:
  11184.  
  11185.  
  11186.  
  11187.  
  11188.  
  11189.  
  11190.  
  11191.    RLIB Function Reference                                                184
  11192.  
  11193.  
  11194.                             ╔════════════════════════════════════════════╗
  11195.                             ║         REPORT PRINT CONFIGURATION         ║
  11196.                             ║              Destination: PRN              ║
  11197.                             ╟────────────────────────────────────────────╢
  11198.                             ║ Report Title:         Purchase Requisition ║
  11199.                             ║                                            ║
  11200.                             ║ Printer Driver:           Epson FX Printer ║
  11201.                             ║                                            ║
  11202.                             ║ Print size (width):                 Normal ║
  11203.                             ║ Page orientation:                 Portrait ║
  11204.                             ║ Line spacing (lines per inch):       6 LPI ║
  11205.                             ║ Top margin (in lines):                   0 ║
  11206.                             ║ Bottom margin (in lines):                0 ║
  11207.                             ║ Left margin (in columns):                0 ║
  11208.                             ║ Report width (in columns):              80 ║
  11209.                             ║ Report setup string:                       ║
  11210.                             ╚════════════════════════════════════════════╝
  11211.                               Press S to start, F to format, ESC to quit
  11212.  
  11213.  
  11214.                 The basic control functions extended to the user are:
  11215.  
  11216.                             * Report title and width
  11217.                             * Printer driver selection
  11218.                             * Page orientation and line spacing
  11219.                             * Top, left, and bottom margins
  11220.                             * Customized printer control codes 
  11221.  
  11222.                 All of these settings are saved in the REPORTS.DBF database
  11223.                 so they may be easily retrieved repeatedly.
  11224.  
  11225.                 For the programmer, STARTREPORT() initializes a set of PUBLIC
  11226.                 variables which can be used programmatically to control the
  11227.                 appearance of printed output.  There are two basic sets of
  11228.                 PUBLIC variables; those that begin with "PRN_" are printer
  11229.                 control codes and printer information, those that begin with
  11230.                 "RPT_" are report definition settings.  The complete list is:
  11231.  
  11232.  
  11233.                 Printer setup information
  11234.                 -------------------------
  11235.                 prn_name         Descriptive name of the selected printer
  11236.                 prn_pgheight     Printable page height in inches
  11237.                 prn_pgwidth      Printable page width in inches
  11238.                 prn_setup        Printer setup string for the report which is
  11239.                                  the combination of codes necessary to
  11240.                                  implement the report format configuration
  11241.                                  selected.
  11242.  
  11243.  
  11244.  
  11245.  
  11246.  
  11247.  
  11248.  
  11249.  
  11250.    RLIB Function Reference                                                185
  11251.  
  11252.  
  11253.                 Printer control codes (escape sequences)
  11254.                 ----------------------------------------
  11255.                 prn_reset        Printer reset (initialize) code
  11256.                 prn_6lpi         Six lines per inch line spacing
  11257.                 prn_8lpi         Eight lines per inch line spacing
  11258.                 prn_boldon       Bold print on
  11259.                 prn_boldoff      Bold print off
  11260.                 prn_condon       Condensed mode on
  11261.                 prn_condoff      Condensed mode off
  11262.                 prn_wideon       Wide print on
  11263.                 prn_wideoff      Wide print off
  11264.                 prn_italon       Italics font on
  11265.                 prn_italoff      Italics font off
  11266.                 prn_undron       Underline on
  11267.                 prn_undroff      Underline off
  11268.                 prn_supron       Superscript on
  11269.                 prn_suproff      Superscript off
  11270.                 prn_subson       Subscript on
  11271.                 prn_subsoff      Subscript off
  11272.                 prn_portrait     Portrait mode on (Laser only)
  11273.                 prn_landscape    Landscape mode on (Laser only)
  11274.  
  11275.  
  11276.                 Report definitions
  11277.                 ------------------
  11278.                 rpt_title     Char     User definable title for report
  11279.                 rpt_width     Num      Report width in columns
  11280.                 rpt_pitch     Char     "N"=Normal, "C"=Condensed
  11281.                 rpt_orient    Char     "P"=Portrait, "L"=Landscape
  11282.                 rpt_space     Num      6=Six LPI, 8=Eight LPI
  11283.                 rpt_lmarg     Num      Left margin (in columns)
  11284.                 rpt_tmarg     Num      Top margin (in lines)
  11285.                 rpt_bmarg     Num      Bottom margin (in lines)
  11286.                 rpt_setup     Char     User defined additional report setup
  11287.                                        string which is sent to the printer
  11288.                                        after PRN_SETUP.
  11289.  
  11290.                 Other
  11291.                 -----
  11292.                 rpt_popbox    This is the SAYINBOX() saved screen from the
  11293.                               prompt that is displayed after the user selects
  11294.                               the Startreport() option.  This public variable
  11295.                               is used in STOPREPORT() to restore the screen
  11296.                               area under the SAYINBOX() message when the
  11297.                               report has finished printing.
  11298.  
  11299.    Notes:       STARTREPORT() performs the following sequence of events: 
  11300.  
  11301.                 1.          Initializes report  "rpt_" PUBLIC variables
  11302.                 2.          Initializes printer "prn_" PUBLIC variables
  11303.                 3.          Queries the user for target destination with
  11304.                             TARGET()
  11305.                 4.          Opens the PRINTERS and REPORTS databases,
  11306.                             retrieves any existing formats for the named
  11307.  
  11308.  
  11309.    RLIB Function Reference                                                186
  11310.  
  11311.  
  11312.                             report.
  11313.                 5.          Pops up a report format description window and
  11314.                             asks the user to press "S" to start report or "F"
  11315.                             to format.
  11316.                 6.          If they respond with Start, the printer is set to
  11317.                             the specified target with the following sequence:
  11318.  
  11319.                               IF .NOT.  target == "CON"
  11320.                                  SET PRINTER TO (M->rpt_target)
  11321.                                  SET DEVICE TO PRINT
  11322.                                  SET CONSOLE OFF
  11323.                                  SET PRINT ON
  11324.                                  SET MARGIN TO rpt_lmarg
  11325.                                  ?? M->prn_reset+M->prn_setup+M->rpt_setup
  11326.                               ENDIF 
  11327.  
  11328.                                        * * *   W A R N I N G   * * *
  11329.  
  11330.                 Always remember to make a call to the STOPREPORT() function
  11331.                 when you are finished.  When you do all the SET PRINTER stuff
  11332.                 by hand, you usually remember to end with a corresponding SET
  11333.                 PRINTER TO to close the print output from a printer or file
  11334.                 or whatever.  With STARTREPORT() this is done for you, and if
  11335.                 you do not finish with a call to STOPREPORT(), your
  11336.                 application will remain directed to wherever you selected
  11337.                 with TARGET().  If this was to a printer or a file, SET
  11338.                 CONSOLE will remain off and all screen writes will go to that
  11339.                 device.  Furthermore, to make it appear everything is screwed
  11340.                 up, some screen writes will go to the screen; things like
  11341.                 @...  BOX, RESTORE SCREEN etc, things that write to the
  11342.                 screen.
  11343.  
  11344.                 The STOPREPORT() function is included in the STARTREPORT()
  11345.                 module rather than being contained in a separate library
  11346.                 module.  Since STOPREPORT() will ALWAYS be called when
  11347.                 STARTREPORT() is being used it makes sense to include it in
  11348.                 the same code.
  11349.  
  11350.                 The STOPREPORT() function issues a form feed and printer
  11351.                 reset then returns print and device control back to the
  11352.                 screen.
  11353.  
  11354.    Example:     *-- instead of lines and lines of code necessary to
  11355.                 *-- prepare a report, use one function
  11356.                 IF StartReport()
  11357.                    DO MyReort
  11358.                    StopReport()
  11359.                 ENDIF
  11360.                 RETURN
  11361.  
  11362.  
  11363.                 *-- This procedure assumes target output was selected by a
  11364.                 *-- call to STARTREPORT() which also initializes the printer
  11365.                 *-- control codes beginning with PRN_
  11366.  
  11367.  
  11368.    RLIB Function Reference                                                187
  11369.  
  11370.  
  11371.                 PROCEDURE MyReport
  11372.                 ? prn_undron + "C U S T O M E R   S T A T U S" + prn_undroff
  11373.                 ?
  11374.                 ?
  11375.                 ? "Customer: " + BOLD(CUST->name)
  11376.                 ? "Account#: " + BOLD(CUST->acctno)
  11377.                 ? "Last Chg: " + BOLD(DTOC(CUST->lastchg))
  11378.                 ? "Balance:  " + BOLD(TRANSFORM(CUST->balance,"###,###.##"))
  11379.                 ? "Avail Cr: " + BOLD(TRANSFORM(CUST->availcr,"###,###.##"))
  11380.                 RETURN
  11381.  
  11382.  
  11383.                 *-----------------------------------------------------------
  11384.                 * Function: BOLD()
  11385.                 * Syntax:   BOLD( string )
  11386.                 * Assumes:  StartReport() printer control code variables are
  11387.                 *           visible
  11388.                 *-----------------------------------------------------------
  11389.                 FUNCTION Bold
  11390.                 PARAMETER string
  11391.                 RETURN prn_boldon + string + prn_boldoff
  11392.  
  11393.    Source:      RL_START.PRG
  11394.  
  11395.    See also:    REPORTINIT()
  11396.  
  11397.  
  11398.  
  11399.  
  11400.  
  11401.  
  11402.  
  11403.  
  11404.  
  11405.  
  11406.  
  11407.  
  11408.  
  11409.  
  11410.  
  11411.  
  11412.  
  11413.  
  11414.  
  11415.  
  11416.  
  11417.  
  11418.  
  11419.  
  11420.  
  11421.  
  11422.  
  11423.  
  11424.  
  11425.  
  11426.  
  11427.    RLIB Function Reference                                                188
  11428.  
  11429.  
  11430.    Function:    STR2DATE()
  11431.  
  11432.    Purpose:     Convert date strings to a Clipper date type variable.
  11433.  
  11434.    Syntax:      STR2DATE( datestring )
  11435.  
  11436.    Arguments:   datestring  - Character date string to be converted.  The
  11437.                               string may be in either the long or short month
  11438.                               spelling format but in either case must be in
  11439.                               the general format of "January 31, 1990".
  11440.  
  11441.    Returns:     A date variable corresponding to the date supplied in the
  11442.                 string.  If the string is in an invalid format, an empty date
  11443.                 ("  /  /  ") is returned.
  11444.  
  11445.    Description: STR2DATE() is a character/date function used to translate
  11446.                 dates which are expressed in spelled out form to Clipper date
  11447.                 type variables.  A date that is expressed as Feb 28, 1990 is
  11448.                 converted into a date type of 02/28/90.  This is useful when
  11449.                 the need arises to convert dates which are stored in
  11450.                 character format to date type fields.  Some software packages
  11451.                 export date data in this character format.
  11452.  
  11453.    Notes:       STR2DATE() is fairly robust and it can handle dates that omit
  11454.                 the comma after the month.  If an invalid date string
  11455.                 argument is given, STR2DATE() will set RLIBERROR() and return
  11456.                 an empty date.
  11457.  
  11458.    Example:     ? STR2DATE("Feb 1, 1990")        && Date value = 02/01/90
  11459.                 ? STR2DATE("feb 01 90")          && Date value = 02/01/90
  11460.  
  11461.  
  11462.                 *-- Example #2
  11463.                 *-- Get data from an import text file from other software
  11464.                 APPEND FROM textfile DELIMITED
  11465.  
  11466.                 *-- date string is in field named StringDate
  11467.                 *-- convert date in form Sep 10, 1988 to date variable
  11468.                 REPLACE Startdate WITH STR2DATE(Stringdate)
  11469.  
  11470.    Source:      RL_STR2D.PRG
  11471.  
  11472.    See also:    ALPHADATE(), CALENDAR(), REVDATE()
  11473.  
  11474.  
  11475.  
  11476.  
  11477.  
  11478.  
  11479.  
  11480.  
  11481.  
  11482.  
  11483.  
  11484.  
  11485.  
  11486.    RLIB Function Reference                                                189
  11487.  
  11488.  
  11489.    Function:    STRETCH()
  11490.  
  11491.    Purpose:     Pad a string with blanks or truncate to a defined width.
  11492.  
  11493.    Syntax:      STRETCH( string, length )
  11494.  
  11495.    Arguments:   string      - Character string to pad with spaces (or to
  11496.                               truncate) to make length <length>.
  11497.  
  11498.                 length      - Numeric desired length of the resulting string.
  11499.  
  11500.    Returns:     <string> padded with spaces or truncated to <length>.
  11501.  
  11502.    Description: STRETCH() is a character function used to normalized strings
  11503.                 to a certain length.  This is most often used to guarantee
  11504.                 that a character string will be a certain length, either by
  11505.                 added spaces onto the end of the string, or by truncating
  11506.                 characters off of the string.
  11507.  
  11508.    Notes:       STRETCH() is also very useful is reports to aid in lining up
  11509.                 columns.  If a variable may be an undetermined length, or if
  11510.                 you fear a field may be lengthened or shortened, STRETCH()
  11511.                 can be used to guarantee a defined output width.
  11512.  
  11513.                 STRETCH() performs the same function as many PAD() functions
  11514.                 but lacks other options which make it leaner.  STRETCH() may
  11515.                 be customized to fit your particular needs.
  11516.  
  11517.                 If a <length> of zero is specified, or if invalid arguments
  11518.                 are supplied, STRETCH() will return a null string ("").
  11519.  
  11520.    Example:     *-- expand a variable for edit length
  11521.                 help_path = STRETCH(help_path,60)
  11522.                 @ 10,20 SAY "Enter path for help files:"
  11523.                 @ 11,20 GET help_path PICTURE "@!S40"
  11524.                 READ
  11525.                 *-- now trim it back down
  11526.                 help_path = TRIM(help_path)
  11527.  
  11528.    Source:      RL_STRET.PRG
  11529.  
  11530.    See also:    CENTER(), MIDDLE()
  11531.  
  11532.  
  11533.  
  11534.  
  11535.  
  11536.  
  11537.  
  11538.  
  11539.  
  11540.  
  11541.  
  11542.  
  11543.  
  11544.  
  11545.    RLIB Function Reference                                                190
  11546.  
  11547.  
  11548.    Function:    TARGET()
  11549.  
  11550.    Purpose:     Provide a pop-up target printer output selection menu.
  11551.  
  11552.    Syntax:      TARGET( [ row [, column [, colors [, confirm ;
  11553.                         [, header [, fileext ] ] ] ] ] ] )
  11554.  
  11555.    Arguments:   row         - Optional numeric value indicating the top row
  11556.                               on which to place the TARGET() selection menu. 
  11557.                               If not specified or an invalid parameter is
  11558.                               passed, the default row is 10.  Valid rows are
  11559.                               from 0 to 10.
  11560.  
  11561.                 column      - Optional numeric value indicating the left
  11562.                               column on which to place the TARGET() selection
  11563.                               menu.  If not specified or an invalid parameter
  11564.                               is passed, the default column is 21.  Valid
  11565.                               columns are from 0 to 41.
  11566.  
  11567.                 colors      - Optional array of character strings specifying
  11568.                               the color settings to use.  This color array is
  11569.                               identical to the array required by BOXMENU(). 
  11570.                               The colors used for the different parts of the
  11571.                               menu are specified as follows: 
  11572.  
  11573.                               colors[1]   -  Menu choices (item options)
  11574.                               colors[2]   -  Menu selection bar
  11575.                               colors[3]   -  Active menu box (on entry)
  11576.                               colors[4]   -  Inactive menu box (on exit)
  11577.                               colors[5]   -  Menu choice upon selection
  11578.                               colors[6]   -  Messages displayed on promptrow
  11579.  
  11580.                 confirm     - Optional logical value indicating whether or
  11581.                               not to warn if a selected filename already
  11582.                               exists and to confirm an overwrite.  The
  11583.                               default value is True.
  11584.  
  11585.                 header      - Optional character string to display as the
  11586.                               header in the BOXMENU() style print target
  11587.                               menu.  If this parameter is omitted or a
  11588.                               non-character type parameter is passed, the
  11589.                               default header text will be: "PRINT SELECTION
  11590.                               MENU".
  11591.  
  11592.                 fileext     - Optional character string indicating the
  11593.                               default file extension to append to the end of
  11594.                               a target file name if one is entered.  Specify
  11595.                               only the three character file extension, do not
  11596.                               include the leading dot.  If omitted or a
  11597.                               non-character  argument is supplied the default
  11598.                               extension is ".PRN".  If the character string
  11599.                               is longer than three characters, only the first
  11600.                               three characters will be used for the file
  11601.                               extension.  To disable the automatic extension
  11602.  
  11603.  
  11604.    RLIB Function Reference                                                191
  11605.  
  11606.  
  11607.                               append feature, pass a null ("") for the
  11608.                               <fileext>.
  11609.  
  11610.    Returns:     The selected target output device as a character string of
  11611.                 either "CON", "PRN", "LPT1", "LPT2", "LPT3", "COM1", "COM2",
  11612.                 <filename>, or a null ("") if escape was pressed or Abort
  11613.                 selected.
  11614.  
  11615.    Description: TARGET() is a high level printer control function that takes
  11616.                 the hassle out of prompting the user for directed printer or
  11617.                 file output.  TARGET() pops up a centered BOXMENU() style
  11618.                 menu which lets the user select a desired target for further
  11619.                 output.  Selections include standard printer (PRN), other
  11620.                 device (LPT 1,2,3, COM 1,2), screen, or to a file, the name
  11621.                 of which the user is prompted to enter.
  11622.  
  11623.    Notes:       All arguments are optional.  As with all Clipper functions,
  11624.                 an argument may be skipped, but a "dummy" argument must be
  11625.                 supplied in its place.
  11626.  
  11627.                 The colors array is identical in structure to the array used
  11628.                 in BOXMENU() and the same array may be used interchangeably.
  11629.  
  11630.                 TARGET() maintains a PUBLIC memvar named RL_TARGET which
  11631.                 saves the last target filename entered, if any.  This lets
  11632.                 TARGET() display the last entered target filename on
  11633.                 subsequent calls.
  11634.  
  11635.                 The TARGET() menu appears as follows:
  11636.  
  11637.                             ╔═════════════════════════════════════╗
  11638.                             ║        PRINT SELECTION MENU         ║
  11639.                             ╟─────────────────────────────────────╢
  11640.                             ║ Printer - print to the standard PRN ║
  11641.                             ║ Device  - select a different port   ║
  11642.                             ║ Screen  - send output to screen     ║
  11643.                             ║ File    - send output to a file     ║
  11644.                             ║ Abort   - cancel this request       ║
  11645.                             ╚═════════════════════════════════════╝
  11646.  
  11647.                 If the Device option is selected, a sub-menu appears with the
  11648.                 following options:
  11649.  
  11650.  
  11651.  
  11652.  
  11653.  
  11654.  
  11655.  
  11656.  
  11657.  
  11658.  
  11659.  
  11660.  
  11661.  
  11662.  
  11663.    RLIB Function Reference                                                192
  11664.  
  11665.  
  11666.                             ┌─────────────────────────────────────┐
  11667.                             │        PRINT SELECTION MENU         │
  11668.                             ├─────────────────────────────────────┤
  11669.                             │ Printer - print to the standard PRN │
  11670.                             │ Device  - select a different port   │
  11671.                             │ Screen  - ╔═════════════╗screen     │
  11672.                             │ File    - ║PRINT DEVICES║a file     │
  11673.                             │ Abort   - ╟─────────────╢uest       │
  11674.                             └───────────║ 1.  LPT1    ║───────────┘
  11675.                                         ║ 2.  LPT2    ║
  11676.                                         ║ 3.  LPT3    ║
  11677.                                         ║ 4.  COM1    ║
  11678.                                         ║ 5.  COM2    ║
  11679.                                         ╚═════════════╝
  11680.  
  11681.                 If the File option is selected a data entry box appears as
  11682.                 follows:
  11683.  
  11684.                               ┌─────────────────────────────────────┐
  11685.                               │        PRINT SELECTION MENU         │
  11686.                               ├─────────────────────────────────────┤
  11687.                               │ Printer - print to the standard PRN │
  11688.                               │ Device  - select a different port   │
  11689.                               │ Screen  - send output to screen     │
  11690.                               │ File    - send output to a file     │
  11691.                             ╔════════════════════════════════════════╗
  11692.                             ║             Enter Filename             ║
  11693.                             ╟────────────────────────────────────────╢
  11694.                             ║                                        ║
  11695.                             ╚════════════════════════════════════════╝
  11696.  
  11697.    Example:     *-- query user for desired output
  11698.                 mtarget = TARGET()
  11699.                 IF .NOT.  mtarget == "CON"             && not to the screen
  11700.                    SET PRINTER TO (mtarget)
  11701.                    SET PRINT ON
  11702.                    SET CONSOLE OFF
  11703.                    DO MyReport
  11704.                    SET PRINT OFF
  11705.                    SET PRINTER TO
  11706.                    SET CONSOLE ON
  11707.                 ENDIF
  11708.  
  11709.    Source:      RL_TARGE.PRG
  11710.  
  11711.    See also:    GETFILE(), REPORTINIT(), STARTREPORT()
  11712.  
  11713.  
  11714.  
  11715.  
  11716.  
  11717.  
  11718.  
  11719.  
  11720.  
  11721.  
  11722.    RLIB Function Reference                                                193
  11723.  
  11724.  
  11725.    Function:    TEMPFILE()
  11726.  
  11727.    Purpose:     Generate a temporary filename.
  11728.  
  11729.    Syntax:      TEMPFILE( [ extension ] )
  11730.  
  11731.    Arguments:   extension   - Optional character string indicating the file
  11732.                               extension to assign to the temporary filename. 
  11733.                               Specify only the 1 to 3 character extension, do
  11734.                               not include the dot leader.  If more than three
  11735.                               characters are specified, only the first three
  11736.                               will be used.  If omitted or an invalid
  11737.                               argument is given, the default file extension
  11738.                               is ".TMP".
  11739.  
  11740.    Returns:     A unique temporary filename or a null ("") if an error
  11741.                 occurred.
  11742.  
  11743.    Description: TEMPFILE() is a file function used to create a unique
  11744.                 temporary file name.  This is most often used to create
  11745.                 temporary index files, or other temporary storage files.
  11746.  
  11747.    Notes:       This function is not 100% foolproof!  In a Network
  11748.                 environment two workstations could conceivably acquire the
  11749.                 same filename although it is HIGHLY UNLIKELY.  This function
  11750.                 can be made very safe in a network if the optional extension
  11751.                 is supplied and is unique to each workstation making the
  11752.                 call.  For instance, if the network assigns workstation
  11753.                 numbers, and the current workstation is assigned station
  11754.                 number 1, then a temporary file extension could be passed to
  11755.                 TEMPFILE() as "S1".  In this manner each workstation would be
  11756.                 guaranteed a unique extension.
  11757.  
  11758.    Example:     *-- build a temporary index file for a Query condition
  11759.                 USE mydbf
  11760.                 tempindex = TEMPFILE()
  11761.                 condition = QUERY()
  11762.                 pbox = SAYINBOX( "Building query index, please wait" )
  11763.                 INDEX ON IF(&condition, "A", "Z") TO (tempindex)
  11764.                 POPBOX(pbox)
  11765.                 SEEK "A"
  11766.                 DBEDIT()
  11767.                 SET INDEX TO
  11768.                 ERASE (tempindex)
  11769.                 USE
  11770.  
  11771.    Source:      RL_TEMPF.PRG
  11772.  
  11773.    See also:    CHECKFILE(), FILEDATE(), FILESIZE(), FILETIME(), PICKFILE()
  11774.  
  11775.  
  11776.  
  11777.  
  11778.  
  11779.  
  11780.  
  11781.    RLIB Function Reference                                                194
  11782.  
  11783.  
  11784.    Function:    TYPEC()
  11785.  
  11786.    Purpose:     Test if a PUBLIC/PRIVATE is character type and not blank.
  11787.  
  11788.    Syntax:      TYPEC( "memvar" )
  11789.  
  11790.    Arguments:   memvar      - The name of the PUBLIC or PRIVATE variable to
  11791.                               test.  The variable name must be passed to
  11792.                               TYPEC() as a string and therefore must be
  11793.                               enclosed in single or double quotes.
  11794.  
  11795.    Returns:     True if the indicated variable is of character type and is
  11796.                 not empty (blank or a null string).
  11797.  
  11798.    Description: This function is very useful if you need to not only verify
  11799.                 that a variable or argument is of character type but also
  11800.                 that it is not empty or a null string.  TYPEC() is especially
  11801.                 useful in user-defined functions where parameter verification
  11802.                 is important.
  11803.  
  11804.    Notes:       TYPEC() follows the same convention as the Clipper TYPE()
  11805.                 function.
  11806.  
  11807.    Example:     PRIVATE blank_var, null_var, char_var, num_var
  11808.                 blank_var = " "
  11809.                 null_var  = ""
  11810.                 char_var  = "Y"
  11811.                 num_var   = 1
  11812.  
  11813.                 ? TYPEC("blank_var")            && .F.
  11814.                 ? TYPEC("null_var")             && .F.
  11815.                 ? TYPEC("char_var")             && .T.
  11816.                 ? TYPEC("num_var")              && .F.
  11817.                 ? MyOpen()                      && .F.
  11818.                 ? MyOpen(" ")                   && .F.
  11819.                 ? MyOpen("my.dbf")              && .T.
  11820.  
  11821.                 *------------------------------------------------------------
  11822.                 * Function: MyOpen()
  11823.                 * Purpose:  Open a database named with the character filename
  11824.                 *           parameter after verifying the correct parameter
  11825.                 *           usage, and that the file exists.
  11826.                 *------------------------------------------------------------
  11827.                 FUNCTION MyOpen
  11828.                 PARAMETER filename
  11829.                 IF .NOT. TYPEC("filename")
  11830.                    *-- not only will this verify that the required parameter
  11831.                    *-- is Character in type, but also that it is not blank.
  11832.                    BOXASK("No filename given.", 10)
  11833.                    RETURN .F.
  11834.                 ENDIF
  11835.                 USE (filename)
  11836.                 RETURN .T.
  11837.  
  11838.  
  11839.  
  11840.    RLIB Function Reference                                                195
  11841.  
  11842.  
  11843.    Source:      RL_TYPEC.PRG
  11844.  
  11845.    See also:    VALTYPEC()
  11846.  
  11847.  
  11848.  
  11849.  
  11850.  
  11851.  
  11852.  
  11853.  
  11854.  
  11855.  
  11856.  
  11857.  
  11858.  
  11859.  
  11860.  
  11861.  
  11862.  
  11863.  
  11864.  
  11865.  
  11866.  
  11867.  
  11868.  
  11869.  
  11870.  
  11871.  
  11872.  
  11873.  
  11874.  
  11875.  
  11876.  
  11877.  
  11878.  
  11879.  
  11880.  
  11881.  
  11882.  
  11883.  
  11884.  
  11885.  
  11886.  
  11887.  
  11888.  
  11889.  
  11890.  
  11891.  
  11892.  
  11893.  
  11894.  
  11895.  
  11896.  
  11897.  
  11898.  
  11899.    RLIB Function Reference                                                196
  11900.  
  11901.  
  11902.    Function:    VALTYPEC()
  11903.  
  11904.    Purpose:     Test if a LOCAL/STATIC is character type and not blank.
  11905.  
  11906.    Syntax:      VALTYPEC( memvar )
  11907.  
  11908.    Arguments:   memvar      - The STATIC or LOCAL memory variable to test. 
  11909.                               As with all Clipper 5.0 Static and Local
  11910.                               variables, do not enclose the variable name in
  11911.                               quotes as with the TYPEC() function.
  11912.  
  11913.    Returns:     True if the indicated variable is of character type and is
  11914.                 not empty (blank or a null string).
  11915.  
  11916.    Description: This function is very useful if you need to not only verify
  11917.                 that a variable or argument is of character type but also
  11918.                 that it is not empty or a null string.  VALTYPEC() is
  11919.                 especially useful in user-defined functions where parameter
  11920.                 verification is important.
  11921.  
  11922.    Notes:       Pass the LOCAL or STATIC variable directly to VALTYPEC() just
  11923.                 as you would to VALTYPE().  Do not enclose the variable name
  11924.                 in quotes, as in the syntax for TYPEC().  Doing so will
  11925.                 allays yield a false return value since STATIC and LOCAL
  11926.                 variables are not known by name at run time.
  11927.  
  11928.                 VALTYPEC() is specific to the Clipper 5.0 version of RLIB and
  11929.                 does not exist in the Summer '87 version of RLIB.LIB.
  11930.  
  11931.    Example:     LOCAL blank_var, null_var, char_var, num_var
  11932.                 blank_var := " "
  11933.                 null_var  := ""
  11934.                 char_var  := "Y"
  11935.                 num_var   := 1
  11936.  
  11937.                 ? VALTYPEC(blank_var)            // .F.
  11938.                 ? VALTYPEC(null_var)             // .F.
  11939.                 ? VALTYPEC(char_var)             // .T.
  11940.                 ? VALTYPEC(num_var)              // .F.
  11941.  
  11942.  
  11943.                 ? MyOpen()                       // .F.
  11944.                 ? MyOpen(" ")                    // .F.
  11945.                 ? MyOpen("my.dbf")               // .T.
  11946.  
  11947.                 *------------------------------------------------------------
  11948.                 * Function: MyOpen()
  11949.                 * Purpose:  Open a database named with the character filename
  11950.                 *           parameter after verifying the correct parameter
  11951.                 *           usage and that file exists.
  11952.                 *------------------------------------------------------------
  11953.                 FUNCTION MyOpen ( filename )
  11954.                 IF .NOT. VALTYPEC(filename)
  11955.                    *-- not only will this verify that the required parameter
  11956.  
  11957.  
  11958.    RLIB Function Reference                                                197
  11959.  
  11960.  
  11961.                    *-- is Character in type, but also that it is not blank.
  11962.                    BOXASK( "No filename given.", 10 )
  11963.                    RETURN .F.
  11964.                 ENDIF
  11965.                 USE (filename)
  11966.                 RETURN .T.
  11967.  
  11968.    Source:      RL_VALTY.PRG
  11969.  
  11970.    See also:    TYPEC()
  11971.  
  11972.  
  11973.  
  11974.  
  11975.  
  11976.  
  11977.  
  11978.  
  11979.  
  11980.  
  11981.  
  11982.  
  11983.  
  11984.  
  11985.  
  11986.  
  11987.  
  11988.  
  11989.  
  11990.  
  11991.  
  11992.  
  11993.  
  11994.  
  11995.  
  11996.  
  11997.  
  11998.  
  11999.  
  12000.  
  12001.  
  12002.  
  12003.  
  12004.  
  12005.  
  12006.  
  12007.  
  12008.  
  12009.  
  12010.  
  12011.  
  12012.  
  12013.  
  12014.  
  12015.  
  12016.  
  12017.    RLIB Function Reference                                                198
  12018.  
  12019.  
  12020.    Function:    VRANGE()
  12021.  
  12022.    Purpose:     Numeric range validation with error handling.
  12023.  
  12024.    Syntax:      VRANGE( value, lower, upper [, color ] )
  12025.  
  12026.    Arguments:   value       - Numeric value to validate as being between the 
  12027.                               <lower> and <upper> limits, inclusive.
  12028.  
  12029.                 lower       - Numeric lower limit that <value> must be equal
  12030.                               to or greater for VRANGE() to return True.
  12031.  
  12032.                 upper       - Numeric upper limit that <value> must be equal
  12033.                               to or less than for VRANGE() to return True.
  12034.  
  12035.                 color       - Optional character color string to use when
  12036.                               displaying error messages.  If omitted or an
  12037.                               invalid parameter is passed, the default color
  12038.                               is Bright White on Red (W+/R) for color
  12039.                               monitors and High intensity for monochrome.
  12040.  
  12041.    Returns:     True if <value> is between <lower> and <upper> inclusive.
  12042.  
  12043.    Description: VRANGE() is a numeric function most often used within VALID
  12044.                 clauses of GET statements.  Its best use is as a replacement
  12045.                 for the limited RANGE clause.
  12046.  
  12047.                 VRANGE() checks that <value> is greater than or equal to
  12048.                 <lower> and that <value> is less than or equal to <upper>. 
  12049.                 If this is false, VRANGE() displays a SAYINBOX() error
  12050.                 message (in the optional <color> specified) and waits for a
  12051.                 confirming keypress for 10 seconds.  After 10 seconds,
  12052.                 VRANGE() times out and returns False.
  12053.  
  12054.    Notes:       If any of the first three arguments are either missing or
  12055.                 non- numeric in type, VRANGE() will set the appropriate
  12056.                 RLIBERROR() value and return False.
  12057.  
  12058.    Example:     *-- prevent a negative age with a nice looking error message
  12059.                 age = 0
  12060.                 @ 10, 0 SAY "Enter your age:"
  12061.                 @ 10,16 GET M->age PICTURE "##" ;
  12062.                    VALID Vrange( M->age, 1, 99, "GR+/R" )
  12063.                 READ
  12064.  
  12065.    Source:      RL_VRANG.PRG
  12066.  
  12067.    See also:    BOXASK(), NOTEMPTY(), SAYINBOX()
  12068.  
  12069.  
  12070.  
  12071.  
  12072.  
  12073.  
  12074.  
  12075.  
  12076.    RLIB Function Reference                                                199
  12077.  
  12078.  
  12079.  
  12080.  
  12081.  
  12082.  
  12083.  
  12084.  
  12085.  
  12086.  
  12087.  
  12088.  
  12089.  
  12090.  
  12091.  
  12092.  
  12093.  
  12094.         ┌───────────────────────────────────────────────────────────────┐
  12095.         │                                                               │
  12096.         │                                                               │
  12097.         │                                                               │
  12098.         │                                                               │
  12099.         │                                                               │
  12100.         │                                                               │
  12101.         │                                                               │
  12102.         │                                                               │
  12103.         │                          Appendix A                           │
  12104.         │                       RLIB Error Codes                        │
  12105.         │                                                               │
  12106.         │                                                               │
  12107.         │                                                               │
  12108.         │                                                               │
  12109.         │                                                               │
  12110.         │                                                               │
  12111.         │                                                               │
  12112.         │                                                               │
  12113.         │                                                               │
  12114.         │                                                               │
  12115.         └───────────────────────────────────────────────────────────────┘
  12116.  
  12117.  
  12118.    Appendix A - RLIB Error Codes
  12119.  
  12120.  
  12121.       All RLIB functions are designed to handle runtime errors with as much
  12122.       grace as possible.  When a runtime error occurs, the programmer has a
  12123.       choice of trapping these errors or letting the error crash your
  12124.       program.  RLIB functions use the former method.
  12125.  
  12126.       The most frequent errors that occur when calling Clipper functions are
  12127.       parameter omission and/or type mismatches.  Most of the RLIB functions
  12128.       test for the proper number of parameters and for the proper parameter
  12129.       types.  If a required parameter is omitted or if a parameter type is
  12130.       mismatched, and the function cannot rely on a default value, the
  12131.       function will simply return.  If the function returns a value that is
  12132.       indicative of success, the return value in such a case will be the
  12133.       failure value.
  12134.  
  12135.       As do all Clipper functions, every RLIB function must return some
  12136.       value.  Additionally, as with functions in Clipper and C, RLIB
  12137.       functions may return ONLY ONE VALUE.
  12138.  
  12139.  
  12140.    Debugging Aid
  12141.  
  12142.       To make program debugging a little easier, all RLIB functions maintain
  12143.       an error value which can be retrieved by a call to the RLIBERROR()
  12144.       function.  Normal function completion will always set this value to
  12145.       zero.  Any non-zero value is an indication of some level of failure in
  12146.       the last RLIB function called.
  12147.  
  12148.       This error value is also used by some RLIB functions to return more
  12149.       specific error information to the calling routine.  In such a case the
  12150.       error was not fatal (or an invalid syntax error) but merely an
  12151.       additional bit of information on the result of the function operation. 
  12152.       A good example is the OPENED() function where the RLIBERROR() value
  12153.       returns details on why the files were not opened successfully.
  12154.  
  12155.       If you find that during your application development testing phase, a
  12156.       particular routine is not operating correctly, and the routine calls
  12157.       one or more RLIB functions, fire up the Clipper debugger and, at the
  12158.       point in question, evaluate RLIBERROR() to get the last error value. 
  12159.       This can be a tremendous time saver in tracking down missing or
  12160.       invalid RLIB parameters.
  12161.  
  12162.       One additional technical note, RLIBERROR() simply maintains a PUBLIC
  12163.       variable named rliberror, and this variable is always visible.  Rather
  12164.       than making explicit calls to RLIBERROR(), you may set a breakpoint
  12165.       (in Clipper Summer '87) or to a tracepoint (in Clipper 5.0) to the
  12166.       expression RLIBERROR != 0.  In this manner your debugging execution
  12167.       will stop at the point of failure, when RLIBERROR becomes non-zero. 
  12168.       Below is a table of all of the RLIBERROR error codes and their
  12169.       meanings.  These numbers were assigned sequentially as the RLIB
  12170.       functions were coded and modified, so they are not in any logical
  12171.       order and are not necessarily grouped by function.
  12172.  
  12173.  
  12174.    Appendix A - RLIB Error Codes                                          201
  12175.  
  12176.  
  12177.       CODE   INDICATION
  12178.       ----   ----------
  12179.          0   Normal completion, no error occurred.
  12180.       1002   Non-character type or no parameter passed to ISFIELD()
  12181.       1003   Non-array type or no parameter passed to ARRAYLEN()
  12182.       1004   Non-array type or no parameter passed to ABOXASK()
  12183.       1005   Non-character type, empty, or no parameter passed to ACRONYM()
  12184.       1006   Non-numeric type, none, or partial parameters passed to ADIM2()
  12185.       1007   Non-array type or no parameter passed to ALIST()
  12186.       1008   Non-date type parameter passed to ALPHADATE()
  12187.       1009   Non-character or insufficient parameters passed to ANYCHARSIN()
  12188.       1010   Invalid or insufficient parameters passed to ATINSAY()
  12189.       1011   Non-array type or no parameter passed to BARMENU()
  12190.       1012   Non-character type or no parameter passed to BIN2DEC()
  12191.       1013   Invalid or insufficient parameters passed to BORDERBOX()
  12192.       1014   Non-character type or no parameter passed to BOXASK()
  12193.       1015   Invalid or insufficient parameters passed to BOXMENU()
  12194.       1016   Invalid or insufficient parameters (1-5) passed to PDOWNINIT()
  12195.       1017   Mismatched array element count in parameter 2 & 3 to PDOWNINIT()
  12196.       1018   No field array provided and no database selected in QUERY()
  12197.       1019   Non character value in names/fields array in QUERY()
  12198.       1020   Invalid expression in fields array in QUERY()
  12199.       1021   Invalid or insufficient parameters passed to DBFCREATE()
  12200.       1022   Non-numeric type or no parameter passed to FREADLINE()
  12201.       1023   Non-character type or no parameter passed to MAKEALIAS()
  12202.       1024   Non-array type or no parameter passed to CATF() or CFTA()
  12203.       1025   No database selected in CATF() or CFTA()
  12204.       1026   Array or first/last out of bounds in CATF() or CFTA()
  12205.       1027   No database selected in CHANGED()
  12206.       1028   No database selected or no fields in MEMORIZE()
  12207.       1029   First or last out of bounds in MEMORIZE()
  12208.       1030   PUBLIC variable undeclared or wrong type in CHANGED()
  12209.       1031   No database selected or no fields in MREPLACE()
  12210.       1032   First or last out of bounds in MREPLACE()
  12211.       1033   PUBLIC variable undeclared or wrong type in MREPLACE()
  12212.       1034   Non-character type or no parameter passed to CHECKFILE()
  12213.       1035   Non-numeric type or no parameter passed to DEC2HEX()
  12214.       1036   Non-character type or no parameter passed to DECRYPTED()
  12215.       1037   Non-character type or no parameter passed to ENCRYPTED()
  12216.       1038   Non-numeric type, none, or partial parameters passed to DIVIDE()
  12217.       1039   Non-numeric type or no parameter passed to FEOF()
  12218.       1040   Non-character type or no parameter passed to FILEDATE()
  12219.       1041   Non-character type or no parameter passed to FILETIME()
  12220.       1042   Non-character type or no parameter passed to FILESIZE()
  12221.       1043   Non-character type or no parameter passed to FILES()
  12222.       1044   No database selected or no fields in FORGET()
  12223.       1045   First or last out of bounds in FORGET()
  12224.       1046   Non-character type or no parameter passed to SAYINBOX()
  12225.       1047   Invalid or insufficient parameters passed to GETPARM()
  12226.       1048   Non-character type or no parameter passed to HEX2DEC()
  12227.       1049   Non-character type or no parameter passed to ISDBF()
  12228.       1050   Invalid or insufficient parameters passed to PICKREC()
  12229.       1051   Non-character type or no parameter passed to MIDDLE()
  12230.       1052   Invalid or insufficient parameters passed to MULTIMENU()
  12231.  
  12232.  
  12233.    Appendix A - RLIB Error Codes                                          202
  12234.  
  12235.  
  12236.       CODE   INDICATION
  12237.       ----   ----------
  12238.       1053   Invalid window coordinates or array length in MULTIMENU()
  12239.       1054   Non-character type or no parameter passed to NAMESPLIT()
  12240.       1055   Invalid or non-existent alias passed to NO_FLOCK()
  12241.       1056   Invalid or non-existent alias passed to NO_RLOCK()
  12242.       1057   No parameter passed to NOTEMPTY()
  12243.       1058   Non-character or insufficient parameters passed to OLDERFILE()
  12244.       1059   Non-character type or no parameter passed to PATHTO()
  12245.       1060   Invalid or insufficient parameters passed to POPUPPICK()
  12246.       1061   Non-character type or no parameter passed to PRINTCODE()
  12247.       1062   Invalid type or no parameter passed to RH_HEADER()
  12248.       1063   Error opening file in RH_HEADER()
  12249.       1064   Invalid format in file given to RH_HEADER() (missing signature)
  12250.       1065   Invalid type or no parameter passed to RH_HEADER()
  12251.       1066   Error opening file in RH_TEXT()
  12252.       1067   Error reading file in RH_TEXT()
  12253.       1068   Non-character type or no help key parameter passed to RH_TEXT()
  12254.       1069   Error opening file in RH_WIDTH()
  12255.       1070   Invalid type or no parameter passed to RH_WIDTH()
  12256.       1071   Non-character type or no help key parameter passed to RH_WIDTH()
  12257.       1072   Error opening file in RH_LINES()
  12258.       1073   Invalid type or no parameter passed to RH_LINES()
  12259.       1074   Non-character type or no help key parameter passed to RH_LINES()
  12260.       1075   Invalid or insufficient parameters passed to MARKREC()
  12261.       1076   Non-date type parameter passed to REVDATE()
  12262.       1077   Invalid or insufficient parameters passed to STRETCH()
  12263.       1078   Non-character type or no parameter passed to RJUSTIFY()
  12264.       1079   Invalid or insufficient parameters passed to PDOWNMENU()
  12265.       1080   Non-character type or no parameter passed to STR2DATE()
  12266.       1081   Invalid date string parameter passed to STR2DATE()
  12267.       1082   Error opening REPORTS.DBF or PRINTERS.DBF in STARTREPORT()
  12268.       1083   Error locking REPORTS.DBF or PRINTERS.DBF in STARTREPORT()
  12269.       1084   Invalid or insufficient parameters passed to VRANGE()
  12270.       1085   Append file not found in DBFCREATE()
  12271.       1086   Error opening file in ISDBF()
  12272.  
  12273.       1101   Function OPENED() - File sharing violation
  12274.       1102   Function OPENED() - Database .DBF file not found
  12275.       1103   Function OPENED() - Associated .NTX file not found
  12276.       1104   Function OPENED() - Associated .DBT file not found (future use)
  12277.       1105   Function OPENED() - Invalid alias name or other syntax error
  12278.       1106   Function OPENED() - More than seven index files specified
  12279.       1107   Function OPENED() - More than 10 parameters specified
  12280.  
  12281.  
  12282.  
  12283.  
  12284.  
  12285.  
  12286.  
  12287.  
  12288.  
  12289.  
  12290.  
  12291.  
  12292.    Appendix A - RLIB Error Codes                                          203
  12293.  
  12294.  
  12295.  
  12296.  
  12297.  
  12298.  
  12299.  
  12300.  
  12301.  
  12302.  
  12303.  
  12304.  
  12305.  
  12306.  
  12307.  
  12308.  
  12309.  
  12310.         ┌───────────────────────────────────────────────────────────────┐
  12311.         │                                                               │
  12312.         │                                                               │
  12313.         │                                                               │
  12314.         │                                                               │
  12315.         │                                                               │
  12316.         │                                                               │
  12317.         │                                                               │
  12318.         │                                                               │
  12319.         │                          Appendix B                           │
  12320.         │                      The RHELP Compiler                       │
  12321.         │                                                               │
  12322.         │                                                               │
  12323.         │                                                               │
  12324.         │                                                               │
  12325.         │                                                               │
  12326.         │                                                               │
  12327.         │                                                               │
  12328.         │                                                               │
  12329.         │                                                               │
  12330.         │                                                               │
  12331.         └───────────────────────────────────────────────────────────────┘
  12332.  
  12333.  
  12334.    Appendix B - The RHELP Compiler
  12335.  
  12336.  
  12337.    What is RHELP?
  12338.  
  12339.       RHELP is a text-based help system that lets you easily build and
  12340.       maintain context-sensitive help files.  RHELP includes an Application
  12341.       Programming Interface (API) that lets you build help systems from the
  12342.       simple to the complex.  It provides all the necessary pieces so you
  12343.       don't have to do the nitty gritty work.
  12344.  
  12345.       The RHELP system consists of the RHELP compiler program (RHC.EXE)
  12346.       which builds the indexed help file from a text based source file. 
  12347.       Also included is the RHELP de-compiler program RHDC.EXE which de-
  12348.       compiles a RHELP.HLP file into a source text file.  Finally a set of
  12349.       API functions are included that extract help information from an
  12350.       indexed help file based on a unique key value.  The RHELP compiler RHC
  12351.       compiles (indexes) a help source file into a single file which
  12352.       contains the help text along with a header containing an index.
  12353.  
  12354.  
  12355.       RHELP Source Code
  12356.  
  12357.       As with all RLIB components, the RHELP system comes with full source
  12358.       code included.  This includes the source code for RHC.EXE, RHDC.EXE
  12359.       and the API functions, which are included in the RLIB function
  12360.       library.
  12361.  
  12362.  
  12363.       Why Compile?
  12364.  
  12365.       Compiling a help source file with RHC results in a single runtime help
  12366.       file that contains both the index and the help text.  It is accessed
  12367.       with the Clipper low level file I/O functions.  However, you do not
  12368.       need to concern yourself with the low level file functions because all
  12369.       help information is retrieved via simple to use RLIB functions.  For
  12370.       example, to retrieve a block of help text associated with the key
  12371.       "EDIT SCREEN" from a help file named MYAPP.HLP, you only need to issue
  12372.       one function call; helpText = RH_TEXT("myapp.hlp", "EDIT SCREEN"). 
  12373.       Once the help text is retrieved you display it in your preferred way. 
  12374.       An example of a help display function follows in the section entitled
  12375.       "An Example".
  12376.  
  12377.  
  12378.       Advantages
  12379.  
  12380.       The advantage of the RHELP approach becomes apparent when you try to
  12381.       create a help system for a product to be distributed, especially when
  12382.       it will run on a network.  Many Clipper developed help systems use a
  12383.       database file with memo fields to store help keys and text.  Using a
  12384.       .DBF file to contain help information has limitations.  First, the
  12385.       help text is usually contained in a memo file and the help database
  12386.       file is usually indexed into an index file.  This means that your help
  12387.       system now consists of three files; HELP.DBF, HELP.DBT, and HELP.NTX. 
  12388.  
  12389.  
  12390.    Appendix B - The RHELP Compiler                                        205
  12391.  
  12392.  
  12393.       Furthermore, you may wish to set the file attributes of help files to
  12394.       ReadOnly to protect from accidental overwrite or erasure.  Clipper and
  12395.       dBASE will not open a database file that is marked ReadOnly.  Clipper
  12396.       5.0 has just overcome this limitation with the READONLY clause to the
  12397.       USE command but Clipper Summer '87 still will not open a database file
  12398.       that is marked ReadOnly.  Because RHELP help files are accessed with
  12399.       the Clipper low level file functions, a ReadOnly attribute will not
  12400.       affect the ability to open these files.
  12401.  
  12402.       Another advantage of the RHELP approach over a .DBF file based help
  12403.       system is the fact that the source help text is maintained in a plain
  12404.       ASCII text file.  This file can be edited and maintained with your
  12405.       favorite editor or word processor which may include a spell checker
  12406.       and thesaurus.  With a .DBF file based help system you must either use
  12407.       dBASE or write a custom application just to enter or edit help text,
  12408.       not to mention that the editor in such a system may not be as
  12409.       desirable as some word processors.
  12410.  
  12411.  
  12412.    Help Source File Format
  12413.  
  12414.       A RHELP help file is compiled (or indexed) from a text-based source
  12415.       file with the RHELP compiler RHC.EXE.  Help text is delimited by help
  12416.       keyword Id markers.  When RHC finds a help Id marker, it records file
  12417.       location information which is stored in the resulting help file header
  12418.       for fast text retrieval.  RHC is not really a compiler but rather an
  12419.       indexer - it creates an index to help text which is stored at the
  12420.       beginning of the resulting help file.  RHC compiled help files have an
  12421.       extension of .HLP by default.
  12422.  
  12423.       RHC compiles help text files which have keyword and Id markers. 
  12424.       Keywords are text strings which uniquely identify a block of help
  12425.       text.  Id markers are special characters that delimit keywords.  These
  12426.       keywords are stored in the help file header, and are the strings that
  12427.       are used to look up help text blocks via the RHELP API functions.
  12428.  
  12429.       Id markers are denoted by the special colon and vertical bar character
  12430.       sequence ":|" left justified in the first two line column positions. 
  12431.       They may not be indented, if they are, the text will be treated as
  12432.       normal help text.  Immediately following the Id marker is the help
  12433.       keyword.  Keyword text may be any length but only the first 16
  12434.       characters are significant.  Case is not significant, keywords may be
  12435.       upper, lower, or mixed case.  All keywords are normalized to upper
  12436.       case at lookup time.  Id markers and keywords must appear on a single
  12437.       line together by themselves.  The actual help text begins on the next
  12438.       line.  The following is a sample excerpt from a RHELP help source
  12439.       file.
  12440.  
  12441.  
  12442.  
  12443.  
  12444.  
  12445.  
  12446.  
  12447.  
  12448.  
  12449.    Appendix B - The RHELP Compiler                                        206
  12450.  
  12451.  
  12452.         ┌────────────────────────────────────────────────────────────────┐
  12453.        1│My applications help source file.  (this line will be ignored!) │
  12454.        2│:|MAIN MENU               This is an Id marker                  │
  12455.        3│                                                                │
  12456.        4│    This is help text associated with a main menu option        │
  12457.        5│                                                                │
  12458.        6│Press the directional arrow keys to navigate through the menu   │
  12459.        7│items, press ENTER to select a menu item, or ESCAPE to leave.   │
  12460.        8│                                                                │
  12461.        9│:|CUSTOMER EDIT SCREEN                                          │
  12462.       10│                                                                │
  12463.       11│Press the up and down arrow keys to move between edit fields.   │
  12464.       12│Enter data in all of the fields highlighted.  The fields are:   │
  12465.       13│                                                                │
  12466.       14│Name    - Enter the customer's full name, last name first.      │
  12467.       15│                                                                │
  12468.       16│Address - Enter the street address for the customer             │
  12469.       17└────────────────────────────────────────────────────────────────┘
  12470.  
  12471.       In the above example, line number one is ignored by RHC because it is
  12472.       not associated (comes after or under) an Id marker.  Line number two
  12473.       is an Id marker line because the two character sequence ":|" appears
  12474.       in the left column.  Only the first 16 characters of this Id marker
  12475.       (not including the Id marker ":|" itself) are saved as the help key. 
  12476.       In this example the keyword is "MAIN MENU".  Any characters appearing
  12477.       on this line after the 16th character are ignored by RHC.  In this
  12478.       example the comment "This is an Id Marker" is ignored.  The next six
  12479.       lines are the help text associated with the help key MAIN MENU.  The
  12480.       next line (line #9) is another Id marker line.  The help key is saved
  12481.       as "CUSTOMER EDIT SC" since these are the first 16 characters.  The
  12482.       following seven lines are its associated help text.
  12483.  
  12484.       RHC will compile help files with a limit of 500 Id markers (keywords). 
  12485.       Since RHC stores pointer information in arrays during the compile,
  12486.       making this limit larger consumes more memory.  To increase (or
  12487.       decrease) the number of keys allowed, just change the MAXKEYS variable
  12488.       (or #define in the 5.01 version) in the RHC.PRG source code and re-
  12489.       compile and re-link RHC.EXE.  You should note that the practical limit
  12490.       is about 1000 keys.  With MAXKEYS set to 1000 the runtime executable
  12491.       program requires about 512K of RAM to run.
  12492.  
  12493.  
  12494.    Creating Help
  12495.  
  12496.       You can create RHELP-based help systems a number of ways.  One way is
  12497.       to mark sections of your source code with unique help keys.  For
  12498.       instance, in your customer data entry screen, just before the READ
  12499.       command, set a global (PUBLIC or STATIC) variable named rh_HelpKey to
  12500.       "CUSTOMER ENTRY" (rh_HelpKey = "CUSTOMER ENTRY").  Do this throughout
  12501.       your code building a list of help keys as you go along.  Then collect
  12502.       this list of help keys and write your help text source file with
  12503.       specific help text for each unique help key.  A handy way to collect
  12504.       the list of help keys is with a text search or grep program, by
  12505.       scanning all .PRG files for the text "rh_HelpKey = ".
  12506.  
  12507.  
  12508.    Appendix B - The RHELP Compiler                                        207
  12509.  
  12510.  
  12511.       The next step is to compile your help source file into a .HLP file
  12512.       with RHC.  The default filename extension assumed by RHC is .RHC so if
  12513.       your source file is named MYAPP.RHC, you would compile this help
  12514.       source file with the command:  RHC myapp   The .RHC file extension is
  12515.       optional.  If your help source file has an extension other than .RHC,
  12516.       use the full filename on the command line such as RHC myapp.src.  This
  12517.       will compile and create a file named MYAPP.HLP.  This is the runtime
  12518.       help file which is ready to be queried with the RLIB RHELP API
  12519.       functions.  See the example that follows for a sample help display
  12520.       function.
  12521.  
  12522.  
  12523.    Function API Quick Reference
  12524.  
  12525.       RH_HEADER()   Retrieve the header from a RHELP compiled help file.
  12526.       RH_LINES()    Get the number of text lines within a help text block.
  12527.       RH_TEXT()     Extract help text from a compiled .HLP file.
  12528.       RH_WIDTH()    Get the maximum line width within a help text block.
  12529.  
  12530.  
  12531.    Building RHC.EXE and RHDC.EXE
  12532.  
  12533.       To create the RHELP compiler RHC.EXE and de-compiler RHDC.EXE, simply
  12534.       run the MAKERHC.BAT batch file supplied.  RHC.PRG and RHDC.PRG are
  12535.       both written in Clipper Summer '87 but may also be compiled with
  12536.       Clipper 5.0.  Both RHC.EXE and RHDC.EXE use the RLIB function library.
  12537.  
  12538.  
  12539.       Demonstration Version
  12540.  
  12541.       The demonstration RLIB package contains the RHELP compiler program RHC
  12542.       in linkable object file format which has already been compiled with
  12543.       Clipper Summer '87.  The registered distribution version of the RLIB
  12544.       package contains the RHELP compiler and RHELP de-compiler program
  12545.       source code files RHC.PRG and RHDC.PRG.
  12546.  
  12547.  
  12548.    An Example
  12549.  
  12550.       The following is an example of a help system which utilizes the RHELP
  12551.       API functions contained in the RLIB function library.  This help
  12552.       system reads help text from a designated help file and displays the
  12553.       text centered on the screen.
  12554.  
  12555.  
  12556.  
  12557.  
  12558.  
  12559.  
  12560.  
  12561.  
  12562.  
  12563.  
  12564.  
  12565.  
  12566.  
  12567.    Appendix B - The RHELP Compiler                                        208
  12568.  
  12569.  
  12570.       *====================================================================
  12571.       * Procedure:  Help
  12572.       * Purpose:    Generic help module.
  12573.       * Syntax:     DO help WITH (helpkey), (helpfile)
  12574.       * Parameters: helpkey  - The text of the "Help keyword" to lookup
  12575.       *             helpfile - Name of the RHELP compiled help (.HLP) file.
  12576.       *====================================================================
  12577.       PROCEDURE Help
  12578.       PARAMETERS sv_helpkey, sv_hlpfile
  12579.  
  12580.       PRIVATE inrow, incol, incolor, inscreen, incursor
  12581.       PRIVATE help_text, help_width, help_lines, HelpColor
  12582.       PRIVATE win_width, win_lines, win_top, win_left, win_bottom, win_right
  12583.  
  12584.       IF TYPE("sv_helpkey") + TYPE("sv_hlpfile") != "CC"
  12585.          RETURN
  12586.       ENDIF
  12587.       IF .NOT. FILE(sv_hlpfile)
  12588.          BLIP()
  12589.          BOXASK( "Help file " + sv_hlpfile + " does not exist",;
  12590.                  "Help is not available", "Press any key to return", 30 )
  12591.          SETCURSOR(incursor)
  12592.          RETURN
  12593.       ENDIF
  12594.       helpColor  = "B/W"                        && set your color here
  12595.       incursor   = SETCURSOR(.F.)               && save and turn off cursor
  12596.       inrow      = ROW()
  12597.       incol      = COL()
  12598.       help_lines = RH_LINES( sv_hlpfile, sv_helpkey )
  12599.       help_width = RH_WIDTH( sv_hlpfile, sv_helpkey )
  12600.       help_text  = RH_TEXT(  sv_hlpfile, sv_helpkey )
  12601.  
  12602.       IF help_lines = 0 .OR. help_width = 0 .OR. EMPTY(help_text)
  12603.          BOXASK(HelpColor,"No help available","Press any key to return",30)
  12604.       ELSE
  12605.          win_width  = MIN( help_width, 76 )
  12606.          win_lines  = MIN( help_lines, 20 )
  12607.          win_top    = 11 - ROUND(win_lines / 2, 0)     && middle of screen
  12608.          win_bottom = win_top + win_lines + 1          && calc bottom row
  12609.          win_left   =  2 + INT( (76 - win_width) / 2 )
  12610.          win_right  = 79 - win_left
  12611.          incolor    = SETCOLOR(HelpColor)
  12612.          inscreen   = SAVESCREEN(win_top,win_left-2,win_bottom,win_right+2)
  12613.          @ win_top, win_left-2, win_bottom, win_right+2 BOX "┌─┐│┘─└│ "
  12614.          @ win_top,   37 SAY " Help "
  12615.          @ win_bottom,26 SAY " Press ESCAPE to exit help "
  12616.          MEMOEDIT(help_text,win_top+1,win_left,win_bottom-1,win_right,;
  12617.                   .F., "", help_width)
  12618.          RESTSCREEN(win_top,win_left-2,win_bottom,win_right+2,inscreen)
  12619.          SETCOLOR(incolor)
  12620.          @ inrow,incol SAY ""
  12621.       ENDIF
  12622.       SETCURSOR(incursor)
  12623.       RETURN
  12624.  
  12625.  
  12626.    Appendix B - The RHELP Compiler                                        209
  12627.  
  12628.  
  12629.  
  12630.  
  12631.  
  12632.  
  12633.  
  12634.  
  12635.  
  12636.  
  12637.  
  12638.  
  12639.  
  12640.  
  12641.  
  12642.  
  12643.  
  12644.         ┌───────────────────────────────────────────────────────────────┐
  12645.         │                                                               │
  12646.         │                                                               │
  12647.         │                                                               │
  12648.         │                                                               │
  12649.         │                                                               │
  12650.         │                                                               │
  12651.         │                                                               │
  12652.         │                                                               │
  12653.         │                          Appendix C                           │
  12654.         │                         Author's Note                         │
  12655.         │                                                               │
  12656.         │                                                               │
  12657.         │                                                               │
  12658.         │                                                               │
  12659.         │                                                               │
  12660.         │                                                               │
  12661.         │                                                               │
  12662.         │                                                               │
  12663.         │                                                               │
  12664.         │                                                               │
  12665.         └───────────────────────────────────────────────────────────────┘
  12666.  
  12667.  
  12668.    Appendix C - Author's Note
  12669.  
  12670.  
  12671.    Clipper Summer '87 and 5.0
  12672.  
  12673.       RLIB contains libraries for both Clipper Summer '87 and Clipper 5.0. 
  12674.       The 5.0 version of RLIB was specifically written to take advantage of
  12675.       the new Clipper LOCAL and STATIC storage classes.  This results in
  12676.       optimized function performance, object code size reduction, and symbol
  12677.       and address resolution at compile time rather than at run time.
  12678.  
  12679.  
  12680.       Local and Static Variables
  12681.  
  12682.       Probably the most important change to Clipper was the addition of true
  12683.       Local and Static storage classes.  I will not attempt to go into an
  12684.       explanation of these storage classes, the Clipper manual does a good
  12685.       job of that.  I do want to add my two cents worth.  Local and Static
  12686.       variables finally let you truly hide information within a function. 
  12687.       Not only are local variables not visible below the function (in
  12688.       routines which the function calls, unlike PRIVATE variables), but
  12689.       their name is resolved at compile time.  This means simply that if you
  12690.       have a local variable in your function named HOURLYRATE that this is
  12691.       only meaningful in your source code.  Once it is compiled the need for
  12692.       the name is gone, it is resolved to an offset address in your code. 
  12693.       In Clipper Summer '87, your executable ended up with a symbol (some
  12694.       text), HOURLYRATE, contained in the .EXE file.  Aside from the 16 to
  12695.       22 or so bytes of space that consumed for each variable, it was there
  12696.       for the poking at run time.
  12697.  
  12698.       Static variables are exciting for the same, yet an additional reason. 
  12699.       Values you assign to static variables aren't released when the
  12700.       function exits.  This means you can write functions that can remember
  12701.       details about the state they were in, and have that information
  12702.       available the next time the function is invoked.  Again, the Clipper
  12703.       manual does a very good job of explaining these concepts as do a
  12704.       number of third party publications.  
  12705.  
  12706.       The Clipper 5.0 version of the RLIB library makes extensive use of
  12707.       LOCAL and STATIC variables, not only for more efficient and faster
  12708.       functions, but also as a matter of good code form.  I just want to
  12709.       stress my feeling of satisfaction over the inclusion of Locals and
  12710.       Statics into Clipper 5.0.
  12711.  
  12712.  
  12713.       Macro Differences
  12714.  
  12715.       Unfortunately, this is not a perfect world.  One of the things I
  12716.       stressed as a benefit of RLIB version 2.0 was that it came (as does
  12717.       version 3.0) will full source code included.  When Nantucket upgraded
  12718.       Clipper to a new version, the RLIB owner would only have to re-compile
  12719.       the RLIB functions to create an upgraded RLIB.  Libraries that were
  12720.       written in C and Assembler, and particularly those that poked into the
  12721.       internals of Clipper, would have to be upgraded by their authors
  12722.  
  12723.  
  12724.    Appendix C - Author's Notes                                            211
  12725.  
  12726.  
  12727.       before you could get your upgrade.  Well, my upgrade plan was fine as
  12728.       long as Clipper itself maintained 100% upgrade compatibility with
  12729.       itself.  Unfortunately, this was not the case.  There are a few areas
  12730.       where Summer '87 and 5.0 code behave differently, most importantly in
  12731.       the handling of macros.
  12732.  
  12733.       This macro handling incompatibility affected two of the RLIB 2.0
  12734.       functions, CHANGED() and MREPLACE().  They didn't act the same when
  12735.       compiled under Clipper 5.0.  Specifically, the aliasing in the REPLACE
  12736.       statement does not work under Clipper 5.0 the way it did in Summer
  12737.       '87.  If you have a memory variable with the same name as a database
  12738.       field, you normally override the default field by prefacing the memvar
  12739.       with the M->.  This works fine if you do it explicitly, but not if it
  12740.       is done through a macro reference.  So the code: REPLACE
  12741.       &malias.->&mfield WITH M->&mfield works fine under Summer '87 but does
  12742.       not under 5.0.  Clipper 5.0 still retrieves the database field
  12743.       contents in the code M->&mfield so the REPLACE does nothing but
  12744.       replace the field with itself!  The fix is to embed the M-> memvar
  12745.       qualifier within the macro variable.  In the example above, the
  12746.       expression REPLACE &malias.->&mfield ... is replaced with REPLACE
  12747.       &mfldvar ...where MFLDVAR is the string "M->FIELDNAME".
  12748.  
  12749.  
  12750.       A Macro Example
  12751.  
  12752.       To illustrate the problem, compile the sample program below under
  12753.       Summer '87 and 5.0 and observe the results.
  12754.  
  12755.  
  12756.           *-- Create a simple database named "TEST"
  12757.           *-- with a single character field named "DATA" of length 12
  12758.  
  12759.           USE test
  12760.           APPEND BLANK
  12761.           REPLACE data WITH "FIELD DATA"
  12762.           M->data = "MEMVAR DATA"
  12763.           ? data             && prints "FIELD DATA" as expected
  12764.           ? M->data          && prints "MEMVAR DATA" as expected
  12765.           memvar = "data"    && assign the memvar name for macro reference
  12766.           ? M->&memvar       && 5.0 prints "FIELD DATA" S'87, "MEMVAR DATA"
  12767.           memvar = "M->data" && embed the M-> reference in the memvar
  12768.           ? &memvar          && 5.0 now prints "MEMVAR DATA"
  12769.           USE
  12770.           RETURN
  12771.  
  12772.       These differences have been fixed in RLIB by altering the expression
  12773.       of macros and, in the 5.0 library, by replacing macro references with
  12774.       code blocks and new Clipper functions for getting and putting field
  12775.       values.  The new Clipper functions for accomplishing these tasks are
  12776.       far superior to using macros so the rule of thumb is that you can
  12777.       probably do without macros in Clipper 5.0.
  12778.  
  12779.  
  12780.  
  12781.  
  12782.  
  12783.    Appendix C - Author's Notes                                            212
  12784.  
  12785.  
  12786.       RLIB Differences
  12787.  
  12788.       There are a few differences between the Summer '87 and 5.0 versions of
  12789.       the RLIB library.  These differences are limited to functions that are
  12790.       not appropriate in one or the other library.
  12791.  
  12792.  
  12793.           SETCURSOR()  Clipper now has its own internal SETCURSOR() function. 
  12794.                        The Summer '87 version of RLIB has a SETCURSOR()
  12795.                        function that takes a single numeric value as an
  12796.                        argument, and is compatible with the 5.0 version. 
  12797.                        Since Clipper 5.0 now has a SETCURSOR() function, it
  12798.                        is not present in the 5.0 version of RLIB.
  12799.  
  12800.           VALTYPEC()   This RLIB function is specific to, and only exists in,
  12801.                        the 5.0 version of RLIB.
  12802.  
  12803.  
  12804.  
  12805.  
  12806.  
  12807.  
  12808.  
  12809.  
  12810.  
  12811.  
  12812.  
  12813.  
  12814.  
  12815.  
  12816.  
  12817.  
  12818.  
  12819.  
  12820.  
  12821.  
  12822.  
  12823.  
  12824.  
  12825.  
  12826.  
  12827.  
  12828.  
  12829.  
  12830.  
  12831.  
  12832.  
  12833.  
  12834.  
  12835.  
  12836.  
  12837.  
  12838.  
  12839.  
  12840.  
  12841.  
  12842.    Appendix C - Author's Notes                                            213
  12843.  
  12844.  
  12845.    Index
  12846.  
  12847.  
  12848.  
  12849.    A                                       Shareware Version . . . . . . . 11
  12850.                                            Directory Structure . . . . . . 15
  12851.    ABOXASK() . . . . . . . . . . .  29     Disk Space  . . . . . . . . . . 15
  12852.    ACRONYM() . . . . . . . . . . .  31     Diskettes . . . . . . . . . . .  6
  12853.    ADIM()  . . . . . . . . . . . .  32     DIVIDE()  . . . . . . . . . . . 76
  12854.    ALIST() . . . . . . . . . . . .  33     Dynamic Overlays  . . . . . . . 16
  12855.    ALPHADATE() . . . . . . . . . .  35
  12856.    ANYCHARSIN()  . . . . . . . . .  36
  12857.    ARRAYLEN()  . . . . . . . . . .  37     E
  12858.    ATINSAY() . . . . . . . . . . .  38
  12859.    Author's Note . . . . . . . .   211     ENCRYPTED() . . . . . . . . . . 77
  12860.  
  12861.  
  12862.    B                                       F
  12863.  
  12864.    BARMENU() . . . . . . . . . . .  39     FEOF()  . . . . . . . . . . . . 78
  12865.    BEEP()  . . . . . . . . . . . .  42     FILEDATE()  . . . . . . . . . . 79
  12866.    BIN2DEC() . . . . . . . . . . .  43     FILES() . . . . . . . . . . . . 80
  12867.    Blinker . . . . . . . . . . . .  16     FILESIZE()  . . . . . . . . . . 81
  12868.    BLIP()  . . . . . . . . . . . .  44     FILETIME()  . . . . . . . . . . 82
  12869.    BORDERBOX() . . . . . . . . . .  45     FORGET()  . . . . . . . . . . . 83
  12870.    BOXASK()  . . . . . . . . . . .  47     FPROMPT() . . . . . . . . . . . 85
  12871.    BOXMENU() . . . . . . . . . . .  50     FREADLINE() . . . . . . . . . . 87
  12872.    BRIGHT()  . . . . . . . . . . .  54     FRESTSCREEN() . . . . . . . . . 88
  12873.    BUZZ()  . . . . . . . . . . . .  55     FSAVESCREEN() . . . . . . . . . 90
  12874.  
  12875.  
  12876.    C                                       G
  12877.  
  12878.    CALENDAR()  . . . . . . . . . .  56     GETFILE() . . . . . . . . . . . 92
  12879.    CATF()  . . . . . . . . . . . .  59     GETKEY()  . . . . . . . . . . . 94
  12880.    CENTER()  . . . . . . . . . . .  61     GETPARM() . . . . . . . . . . . 96
  12881.    CFTA()  . . . . . . . . . . . .  63
  12882.    CHANGED() . . . . . . . . . . .  65
  12883.    Changes                                 H
  12884.       From RLIB 2.0  . . . . . . .   7
  12885.       Upward Compatibility   . . .   9     Help
  12886.    CHECKFILE() . . . . . . . . . .  67        Sample Program   . . . . .  209
  12887.    CLOSEAREA() . . . . . . . . . .  70     HEX2DEC() . . . . . . . . . . . 98
  12888.    Code Generators . . . . . . . .   2
  12889.    CompuServe  . . . . . . . . . .  24
  12890.    Contents  . . . . . . . . . . .   5     I
  12891.    Copyright . . . . . . . . . .   iii
  12892.                                            Installation
  12893.                                               Diskettes  . . . . . . . . . 15
  12894.    D                                       Introduction  . . . . . . . . .  2
  12895.                                            ISDBF() . . . . . . . . . . . . 99
  12896.    DBFCREATE() . . . . . . . . . .  72     ISFIELD() . . . . . . . . . .  100
  12897.    DEC2HEX() . . . . . . . . . . .  74
  12898.    DECRYPTED() . . . . . . . . . .  75
  12899.  
  12900.  
  12901.    Index                                                                  214
  12902.  
  12903.  
  12904.    K                                       P
  12905.  
  12906.    KEYINPUT()  . . . . . . . . .   101     Parameter Verification  . . . . 18
  12907.                                            PARENT()  . . . . . . . . . .  129
  12908.                                            PATHTO()  . . . . . . . . . .  130
  12909.    L                                       PDOWNINIT() . . . . . . . . .  131
  12910.                                            PDOWNMENU() . . . . . . . . .  136
  12911.    Libraries                               PICKCOLOR() . . . . . . . . .  140
  12912.       CLIPPER  . . . . . . . . . .   2     PICKFILE()  . . . . . . . . .  142
  12913.       EXTEND   . . . . . . . . . .   2     PICKREC() . . . . . . . . . .  144
  12914.    Linking RLIB  . . . . . . . . .  16     PLINK86 . . . . . . . . . . . . 16
  12915.    Local Variables . . . . . . .   211     POPBOX()  . . . . . . . . . .  154
  12916.                                            POPUPPICK() . . . . . . . . .  155
  12917.                                            PRINTCODE() . . . . . . . . .  158
  12918.    M                                       PROGNAME()  . . . . . . . . . . 25
  12919.  
  12920.    Macros
  12921.       Differences  . . . . . . .   211     Q
  12922.    MAKEALIAS() . . . . . . . . .   103
  12923.    MARKREC() . . . . . . . . . .   104     QUERY() . . . . . . . . . . .  160
  12924.    MEMORIZE()  . . . . . . . . .   107
  12925.    Message Reader  . . . . . . . .  24
  12926.       Functions Used In  . . . . .  25     R
  12927.    MIDDLE()  . . . . . . . . . .   109
  12928.    MREPLACE()  . . . . . . . . .   110     Registration  . . . . . . . . . 11
  12929.    MS-LINK . . . . . . . . . . . .  16     REPORTINIT()  . . . . . . . .  165
  12930.    MULTIMENU() . . . . . . . . .   111     REVDATE() . . . . . . . . . .  168
  12931.                                            RH_HEADER() . . . . . . . . .  169
  12932.                                            RH_LINES()  . . . . . . . . .  171
  12933.    N                                       RH_TEXT() . . . . . . . . . .  173
  12934.                                            RH_WIDTH()  . . . . . . . . .  175
  12935.    NAMESPLIT() . . . . . . . . .   113     RHELP . . . . . . . . . . . . .  3
  12936.    NO_APPEND() . . . . . . . . .   114     RHELP Compiler  . . . . . . .  205
  12937.    NO_FLOCK()  . . . . . . . . .   116        Creating Help  . . . . . .  207
  12938.    NO_RLOCK()  . . . . . . . . .   118        File Format  . . . . . . .  206
  12939.    Norton Guides . . . . . . . .  3, 6        Function Reference   . . .  208
  12940.    NOTEMPTY()  . . . . . . . . .   120     RJUSTIFY()  . . . . . . . . .  177
  12941.    NTXKEYVAL() . . . . . . . . .   121     RLIB
  12942.                                               Changes From Version 2.0   .  7
  12943.                                               Enhanced Functions   . . . .  9
  12944.    O                                          New Functions  . . . . . . .  7
  12945.                                               Registered Version   . . . .  6
  12946.    OLDERFILE() . . . . . . . . .   123     RLIB Error Codes  . . . . . .  201
  12947.    On-line Reference Database  . .   6     RLIBERROR() . . . . . 18, 178, 201
  12948.    OPENED()  . . . . . . . . . .   125     RLIBINIT()  . . . . . . . . .  179
  12949.    Order Information . . . . . . .  12     RLIBVER() . . . . . . . . . .  180
  12950.       Order Form   . . . . . . . .  13     RTLink  . . . . . . . . . . . . 16
  12951.       ORDER.DOC  . . . . . . . . .  12
  12952.       Shipping   . . . . . . . . .  13
  12953.  
  12954.  
  12955.  
  12956.  
  12957.  
  12958.  
  12959.  
  12960.    Index                                                                  215
  12961.  
  12962.  
  12963.    S
  12964.  
  12965.    SAYINBOX()  . . . . . . . . .   181
  12966.    Self-Extracting ZIP Files . . .  15
  12967.       Contents   . . . . . . . . .   6
  12968.       Shareware Version  . . . . .   5
  12969.       Registered Version   . . . .   6
  12970.    SETCURSOR() . . . . . . . . .   183
  12971.    Source Code . . . . . . . .   4, 11
  12972.       Clipper 5.0  . . . . . . . .   4
  12973.       Space Required   . . . . . .  15
  12974.       Summer '87   . . . . . . . .   4
  12975.    STARTREPORT() . . . . . . . .   184
  12976.    Static Variables  . . . . . .   211
  12977.    Storage Classes
  12978.       Local  . . . . . . . . . . .   4
  12979.       Static   . . . . . . . . . .   4
  12980.    STR2DATE()  . . . . . . . . .   189
  12981.    STRETCH() . . . . . . . . . .   190
  12982.    System Requirements . . . . . .  15
  12983.  
  12984.  
  12985.    T
  12986.  
  12987.    TARGET()  . . . . . . . . . .   191
  12988.    Technical Support . . . . . . .  11
  12989.       CompuServe Mail  . . . . . .  11
  12990.       Telephone  . . . . . . . . .  11
  12991.    TEMPFILE()  . . . . . . . . .   194
  12992.    TLINK . . . . . . . . . . . . .  16
  12993.    TYPEC() . . . . . . . . . . .   195
  12994.  
  12995.  
  12996.    V
  12997.  
  12998.    VALTYPEC()  . . . . . . . . .   197
  12999.    VRANGE()  . . . . . . . . . .   199
  13000.  
  13001.  
  13002.    W
  13003.  
  13004.    Warranty  . . . . . . . . . . .   v
  13005.    What Is RLIB? . . . . . . . . .   2
  13006.    What You Get  . . . . . . . . .   3
  13007.  
  13008.  
  13009.  
  13010.  
  13011.  
  13012.  
  13013.  
  13014.  
  13015.  
  13016.  
  13017.  
  13018.  
  13019.    Index                                                                  216