home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / progmisc / dblib201.zip / SCREEN.PRG < prev    next >
Text File  |  1993-04-27  |  102KB  |  2,476 lines

  1. *-------------------------------------------------------------------------------
  2. *-- Program...: SCREEN.PRG
  3. *-- Programmer: Ken Mayer (CIS: 71333,1030)
  4. *-- Date......: 02/23/1993
  5. *-- Notes.....: A few routines not left in PROC.PRG, these are not used as much
  6. *--             by my own systems. See the file: README.TXT for details on how
  7. *--             to use this library file.
  8. *-------------------------------------------------------------------------------
  9.  
  10. FUNCTION Radio
  11. *-------------------------------------------------------------------------------
  12. *-- Programmer..: Ed Lafferty (CIS: 76150,3302)
  13. *-- Date........: 06/08/1992
  14. *-- Notes.......: Routine to create and size a popup with radio buttons
  15. *--               for choosing only one of up to four options.  Pressing
  16. *--               the <Space Bar> on an option turns it on or off.
  17. *--               Pressing <Enter> chooses the selected option and leaves
  18. *--               the routine.
  19. *-- Written for.: dBase IV, 1.1
  20. *-- Rev. History: 02/25/1992 - original procedure.
  21. *--               02/27/1992 -- Ken Mayer -- added option for color, but had
  22. *--               to take number of choices back to 4 to do so. Minor 
  23. *--               alterations performed to add color choice ... and cleaning
  24. *--               up after self ... (original cleared the screen first ...
  25. *--               this version saves screen, restores back to it ...) Oh yeah,
  26. *--               I turned it into a function, rather than a procedure, as well.
  27. *-- Calls.......: CENTER                Procedure in PROC.PRG
  28. *--               SHADOW                Procedure in PROC.PRG
  29. *--               COLORBRK()            Function in PROC.PRG
  30. *-- Called by...: Any
  31. *-- Usage.......: Radio(<nULRow>,<nULCol>,<nChoice>,"<cTxt1>","<cTxt2>",;
  32. *--                        "<cTxt3>","<cTxt4>","<cTitle>","<cColor>")
  33. *-- Example.....: cPort = Radio(8,15,1,"LPT1","LPT2","LPT3","",;
  34. *--                             "Choose a printer port","rg+/gb,n/w,rg+/gb")
  35. *-- Returns.....: number of chosen button in nChoice
  36. *-- Parameters..: nUlrow  = upper left row of popup
  37. *--               nUlcol  = upper left column of popup
  38. *--               nChoice = default chosen button
  39. *--               cTxt1   = Text for 1st button
  40. *--               cTxt2   =  "    "  2nd   "
  41. *--               cTxt3   =  "    "  3rd   "
  42. *--               cTxt4   =  "    "  4th   "
  43. *--               cTitle  = Text for the box title
  44. *--               cColor  = Color string (i.e., "RG+/GB,N/W,RG+/GB")
  45. *-------------------------------------------------------------------------------
  46.  
  47.     parameters nUlrow, nUlcol, nChoice, cTxt1, cTxt2, cTxt3, cTxt4, ;
  48.                     cTitle, cColor
  49.     private nHeight, nKey, nCnt, nWidth, cStr, cTxt0, cMidCol, cFirstCol,;
  50.                    cCursor
  51.     
  52.     cCursor = set("CURSOR")
  53.     store cTitle to cTxt0
  54.     save screen to sRadio
  55.     store 0 to nHeight, nKey, nCnt, nWidth
  56.     store nChoice to nOrig  && in case user presses <Esc> to exit ...
  57.     
  58.     *-- deal with these colors in displaying some stuff ...
  59.     cMidCol = colorbrk(cColor,2)
  60.     *-- First color (for message) is easier ...
  61.     cFirstCol = colorbrk(cColor,1)
  62.     
  63.     *-- Determine height and width of popup
  64.     do case
  65.         case len(cTxt4) > 0
  66.            nHeight = 4
  67.         case len(cTxt3) > 0
  68.            nHeight = 3
  69.         case len(cTxt2) > 0
  70.            nHeight = 2
  71.         otherwise
  72.            nHeight = 1
  73.     endcase
  74.     
  75.     do while nCnt <=nHeight
  76.        store "cTxt"+str(nCnt,1) to cStr
  77.        if len(&cstr) > nWidth
  78.           nWidth = len(&cStr)
  79.        endif
  80.        nCnt = nCnt + 1
  81.     enddo
  82.     
  83.     *-- create popup
  84.     define window wRadio from nUlRow,nUlCol to nUlRow+nHeight+3,nUlCol+nWidth+9;
  85.             double color &cColor
  86.     do center with 23,80,"&cFirstCol","Press "+chr(24)+chr(25)+;
  87.                                     ", <Space> to select/de-select, <Enter> to quit"
  88.     activate screen
  89.     do shadow with nULRow, nULCol, nULRow+nHeight+3, nULCol+nWidth+9
  90.     activate window wRadio
  91.     
  92.     *-- display screen
  93.     store 1 to nCnt
  94.     do center with 0, nWidth+8, "", cTitle
  95.     do while nCnt <= nHeight
  96.        store "cTxt"+str(nCnt,1) to cStr
  97.        @ nCnt+1, 2 SAY "[ ]" color &cMidCol
  98.         @ nCnt+1, 6 say &cStr
  99.        nCnt = nCnt + 1
  100.     enddo
  101.     
  102.     *-- prepare for and get nChoice
  103.     if nChoice > 0
  104.        store nChoice to nCnt
  105.         @nCnt+1,3 say "■" color &cMidCol
  106.     else
  107.        store 1 to nCnt
  108.     endif
  109.     store .F. to ldone
  110.     
  111.     *-- this loop processes user input ... 
  112.     do while .not. ldone
  113.         @ nCnt+1,3 say "" color &cMidCol
  114.         nkey = inkey(0)
  115.         do case
  116.         case nkey = 27                   && Press Esc to exit
  117.            store nOrig to nChoice        && Leave at "default"
  118.            store .T. to ldone
  119.         case nkey = 13
  120.            store .T. to ldone
  121.         case nkey = 32                   && Press Enter or Space
  122.               set cursor off
  123.               if nChoice = nCnt
  124.                  @ nCnt+1,3 say " " color &cMidCol
  125.                  store 0 to nChoice
  126.               else
  127.                  @ nChoice+1,3 say " " color &cMidCol
  128.                  @ nCnt+1,3 say "■" color &cMidCol
  129.                  store nCnt to nChoice
  130.               endif
  131.               set cursor on
  132.         case nkey = 5                    && Press up arrow
  133.            if nCnt > 1
  134.               nCnt = nCnt - 1
  135.            else
  136.               nCnt = nHeight
  137.            endif
  138.         case nkey = 24                   && Press down arrow
  139.            if nCnt < nHeight
  140.               nCnt = nCnt + 1
  141.            else
  142.               nCnt = 1
  143.            endif
  144.         endcase
  145.     enddo
  146.     
  147.     *-- cleanup
  148.     deact window wRadio
  149.     release window wRadio
  150.     restore screen from sRadio
  151.     release screen sRadio
  152.     set message to
  153.     set cursor &cCursor
  154.     
  155. RETURN nChoice
  156. *-- EoF: Radio()
  157.  
  158. PROCEDURE CheckBox
  159. *-------------------------------------------------------------------------------
  160. *-- Programmer..: Ed Lafferty (CIS: 76150,3302)
  161. *-- Date........: 04/22/1993
  162. *-- Notes.......: Routine to create and size a popup with check boxes
  163. *--               for choosing any of a number (up to five) options.  Pressing
  164. *--               the <Space Bar> on an option turns it on or off.
  165. *--               Pressing <Enter> chooses the selected option and leaves
  166. *--               the routine. You must use a data structure with logical
  167. *--               fields, or memvars that are logical for this. Either way,
  168. *--               even if you don't use five logical fields/memvars, you must
  169. *--               pass a field/memvar to the procedure -- see Example below 
  170. *--               (the logicals -- lCHK1, lCHK2, etc.-- must be fields or
  171. *--               memvars due to a limitation in parameter passing in dBASE IV.)
  172. *-- Written for.: dBase IV, Version 1.5+
  173. *-- Rev. History: 02/25/1992 -- Original procedure.
  174. *--               02/28/1992 -- Ken Mayer -- modified to allow passing cColor,
  175. *--               and a little cleanup of code and such. Minor changes.
  176. *--               04/22/1993 -- Angus Scott-Fleming:
  177. *--                   Revised for 1.5:
  178. *--                   Turned cursor on
  179. *--                   Moved help-line info inside box.
  180. *--                   Reorganized parameters to allow calling
  181. *--                      with variable # of choices, and evaluate with pCOUNT()
  182. *--                   NOTE: If more than 9 pairs are needed, two loops will
  183. *--                      have to be changed from STR(NCNT,1) to lTrim STR(cCnt,2))
  184. *--                   Enabled error-trapping for poorly located boxes.
  185. *--                   Appended "." to all &Macros.
  186. *-- Calls.......: CENTER               Procedure in PROC.PRG
  187. *--               SHADOW               Procedure in PROC.PRG
  188. *--               COLORBRK()           Function in PROC.PRG
  189. *-- Called by...: Any
  190. *-- Usage.......: do checkbox with <nULCol>,<nULRow>,<cTitle>,<cColor>,;
  191. *--                          <lchk1>,<cTxt1>,[<lchk2>,<cTxt2>];
  192. *--                          [,<lchk3>,<cTxt3>][,<lchk4>,<cTxt4>];
  193. *--                          [... to 9]
  194. *-- Example.....: do Checkbox with 8, 15, "Choose a printer port",;
  195. *--                    "rg+/gb,w+/n,rg+/gb", lchk1, "LPT1", lchk2, "LPT2", ;
  196. *--                    lchk3, "LPT3"
  197. *-- Returns.....: .T. for selected items, .F. for non-selected items --
  198. *--               this routine changes the value of the logical fields passed
  199. *--               to it.
  200. *-- Parameters..: nULRow = upper left row of popup
  201. *--               nULCol = upper left column of popup
  202. *--               cTitle = Title for box
  203. *--               cColor = Colors for window
  204. *--               lChkn  = default value of box 'n' -- MUST BE FIELDS/MEMVARS
  205. *--               cTxtn  = Text for 'n'th box
  206. *--               cColor = Colors to be used in window ...
  207. *-------------------------------------------------------------------------------
  208.  
  209.     parameters nUlrow, nUlcol, cTitle, cColor, lChk1, cTxt1, lChk2, cTxt2,;
  210.                   lChk3, cTxt3, lChk4, cTxt4, lChk5, cTxt5, lChk6, cTxt6,;
  211.                  lChk7, cTxt7, lChk8, cTxt8, lChk9, cTxt9
  212.     private nHeight, nKey, nCnt, nWidth, cMidCol, cFirstCol, cCursor,;
  213.                cPrompt, nBRRow, nBRCol
  214.     
  215.     *-- setup ...
  216.     cCursor = set("CURSOR")
  217.     save screen to sCheck
  218.     store 0 to nHeight, nKey, nWidth
  219.     cPrompt = "Press "+chr(24)+chr(25)+;
  220.         ", <Space> to select/de-select, <Enter> to quit"
  221.         
  222.     *-- save original settings, in case <Esc> gets pressed below ...
  223.     *-- determine height/width of popup
  224.     nWidth  = max(len(cPrompt),len(cTitle))
  225.     nHeight = (pcount() - 4)/2
  226.     nCnt    = 0
  227.     do while nCnt < nHeight
  228.         nCnt = nCnt + 1
  229.         cCnt = str(nCnt,1)
  230.         private lOrig&cCnt.
  231.         store lChk&cCnt. to lOrig&cCnt.
  232.         nWidth = max(nWidth,len(cTxt&cCnt.))
  233.     enddo
  234.     *-- add border to window
  235.     nWidth = min(nWidth+8,79)
  236.     
  237.     *-- deal with some colors ...
  238.     cMidCol   = colorbrk(cColor,2)
  239.     cFirstCol = colorbrk(cColor,1)
  240.     
  241.     *-- create popup and trap errors defining the window
  242.     nBrRow = nULRow + nHeight + 5
  243.     nBRCol = nULCol + nWidth
  244.     if nBRRow > 24
  245.         *-- center window vertically
  246.         nULRow = max(12-(nHeight+5)/2,0)
  247.         nBRRow = min(23,(nULRow+nHeight+5))
  248.     endif
  249.     if nBRCol > 80
  250.         *-- center window horizontally
  251.         nULCol = max(40 - nWidth/2,0)
  252.         nBRCol = min(79,(nULCol+nWidth))
  253.     endif
  254.     
  255.     define window wCheck from nUlrow, nUlcol to nBRRow, nBRCol;
  256.         double color &cColor.
  257.     activate screen
  258.     do shadow with nULRow,nULCol,nBRRow,nBRCol
  259.     activate window wCheck
  260.     
  261.     *-- paint screen
  262.     do center with 0,nWidth,"",cTitle
  263.     store 1 to nCnt
  264.     do while nCnt <= nHeight
  265.         store "cTxt"+str(nCnt,1) to cStr
  266.         store "lChk"+str(nCnt,1) to cChk
  267.         @nCnt+1,2 say "["+iif(&cChk.,"X"," ")+"]" color &cMidCol.
  268.         @nCnt+1,6 say left(&cStr.,nWidth-9)
  269.         nCnt = nCnt + 1
  270.     enddo
  271.     do center with nCnt+2,nWidth,"",cPrompt
  272.         
  273.     *-- prepare for and get nChoice
  274.     store 1 to nCnt
  275.     store .F. to ldone
  276.     do while .not. ldone
  277.         store "lChk"+str(nCnt,1) to cChk
  278.         @ nCnt+1,3 say "" color &cMidCol.
  279.         nkey = inkey(0)
  280.         do case
  281.             case nkey = 27                   && Press Esc to exit
  282.                 nCnt = 0
  283.                 do while nCnt < nHeight
  284.                     nCnt = nCnt + 1
  285.                     cCnt = str(nCnt,1)
  286.                     store lOrig&cCnt. to lChk&cCnt.
  287.                 enddo
  288.                store .T. to ldone
  289.             case nkey = 13                   && Press Enter when finished
  290.                store .T. to ldone
  291.             case nkey = 32                   && Press Space
  292.                   set cursor off
  293.                   if &cChk.                  && Box was already selected,
  294.                      @ nCnt+1,3 say " " color &cMidCol.  && so now de-select it
  295.                      store .F. to &cChk.
  296.                   else                       && Box was not already selected,
  297.                      @ nCnt+1,3 say "X" color &cMidCol.  && so now select it
  298.                      store .T. to &cChk.
  299.                   endif
  300.                   set cursor on
  301.             case nkey = 5                    && Press up arrow
  302.                if nCnt > 1
  303.                   nCnt = nCnt - 1
  304.                else
  305.                   nCnt = nHeight
  306.                endif
  307.             case nkey = 24                   && Press down arrow
  308.                if nCnt < nHeight
  309.                   nCnt = nCnt + 1
  310.                else
  311.                   nCnt = 1
  312.                endif
  313.         endcase
  314.     enddo
  315.     
  316.     *-- Cleanup
  317.     release window wCheck
  318.     restore screen from sCheck
  319.     release screen sCheck
  320.     set message to
  321.     set cursor &cCursor.
  322.     
  323. RETURN
  324. *-- EoP: ChkBox
  325.  
  326. FUNCTION MenuPad
  327. *-------------------------------------------------------------------------------
  328. *-- Programmer..: Douglas P. Saine (CIS: 74660,3574)
  329. *-- Date........: 02/11/1992
  330. *-- Notes.......: Used to create menu prompts of an even length. It works
  331. *--               on any prompt - menu pads or popups.
  332. *-- Written for.: dBASE IV, 1.1
  333. *-- Rev. History: 02/07/1992 - original function.
  334. *--               02/11/1992 -- Ken Mayer -- modified to truncate <cChoice>
  335. *--                 if it's longer than <nLength>.
  336. *-- Calls.......: ALLTRIM()            Function in PROC.PRG
  337. *-- Called by...: Any
  338. *-- Usage.......: MenuPad("<cChoice>",<nLength>)
  339. *-- Example.....: Define pad pPad1 of mMain;
  340. *--                      prompt MenuPad("Menu Choice1",25) at 2,5
  341. *-- Returns.....: <cChoice> padded with spaces (or truncated, if necessary)
  342. *--               to <nLength>.
  343. *-- Parameters..: cChoice = Menu-Pad/Popup-Bar Prompt description
  344. *--               nLength = Length of pad/bar ...
  345. *-------------------------------------------------------------------------------
  346.  
  347.     parameters cChoice, nLength
  348.     private cReturn
  349.     
  350.     if len(alltrim(cChoice)) > nLength  && is it too long?
  351.         cReturn = left(cChoice,nLength)  && truncate it ...
  352.     else             && otherwise, pad it with spaces to the length required
  353.         cReturn = cChoice + space(nLength-len(alltrim(cChoice)))
  354.     endif
  355.  
  356. RETURN cReturn
  357. *-- EoF: MenuPad()
  358.  
  359. FUNCTION Banner
  360. *-------------------------------------------------------------------------------
  361. *-- Programmer..: Dan Madoni (Borland)
  362. *-- Date........: 09/01/1991
  363. *-- Notes.......: This will display a left-scrolling message on the screen
  364. *--               within the boundaries specified in the UDF by the user.
  365. *--               It will wait for a keypress and then go away. Taken from
  366. *--               TECHNOTES.
  367. *-- Written for.: dBASE IV, 1.1
  368. *-- Rev. History: 09/01/1991 -- Original
  369. *-- Usage.......: Banner(<nRow>,<nCol>,<nWidth>,"<cMessage>","<cColor>")
  370. *-- Example.....: ?? Banner(5,30,20,"Love your tie, is it new?","w+/r")
  371. *-- Returns.....: Null ("")
  372. *-- Parameters..: nRow     = Leftmost ROW position of scrolled message
  373. *--               nCol     = Leftmost COL position of scrolled message
  374. *--               nWidth   = Length of displayable area starting at nRow,nCol
  375. *--               cMessage = Message to be scrolled
  376. *--               cColor   = Color of scrolling message
  377. *-------------------------------------------------------------------------------
  378.  
  379.     parameters nRow,nCol,nWidth,cMessage,cColor
  380.     private cCursor,cTalk,cMsg,nCounter,cPause
  381.     
  382.     *-- save some environment essentials
  383.     save screen to sBanner
  384.     cCursor = set("CURSOR")
  385.     cTalk   = set("TALK")
  386.     set cursor off
  387.     set talk off
  388.     
  389.     *-- deal with message
  390.     cMsg = space(nWidth)+cMessage+" "
  391.     nCounter = 0
  392.     
  393.     *-- loop
  394.     do while .t.
  395.         nCounter = nCounter + 1
  396.         if nCounter > len(cMsg)
  397.             nCounter = 1
  398.         endif
  399.         
  400.         *-- user hits any key
  401.         cPause = inkey(.15)
  402.         if cPause # 0
  403.             exit
  404.         endif
  405.         
  406.         *-- display message within scrollable area
  407.         @nRow,nCol say substr(cMsg,nCounter,nWidth) color &cColor
  408.     enddo
  409.     
  410.     *-- restore environment
  411.     restore screen from sBanner
  412.     release screen sBanner
  413.     set cursor &cCursor
  414.     set talk &cTalk
  415.  
  416. RETURN ""
  417. *-- EoF: Banner()
  418.  
  419. FUNCTION SeeMatch
  420. *-------------------------------------------------------------------------------
  421. *-- Programmer..: Dan Madoni (Borland)
  422. *-- Date........: 06/12/1992
  423. *-- Notes.......: Can be included in format screen to display an instant
  424. *--               lookup match on a particular field. A shadowed box will
  425. *--               appear with the matching value ... Taken from TECHNOTES.
  426. *-- Written for.: dBASE IV, 1.1
  427. *-- Rev. History: 09/01/1991 -- Original
  428. *--               06/12/1992 -- Minor -- added call to RECOLOR
  429. *-- Calls.......: RECOLOR              Procedure in PROC.PRG
  430. *-- Called by...: None
  431. *-- Usage.......: SeeMatch("<cFile>",<cSeekExp>,"<cReturn>",<nULRow>,<nULCol>,;
  432. *--                        <nBRRow>,<nBRCol>,"<cColor>)
  433. *-- Example.....: SeeMatch("TRAVEL",LASTNAME,"TRAVELCODE",2,40,4,60,"w+/r")
  434. *-- Returns.....: .t.
  435. *-- Parameters..: cFile    = Database alias in which lookup will be performed.
  436. *--                          -- this file must already be USEd in some area.
  437. *--               cSeekExp = Expression which will be SEEKed.
  438. *--               cReturn  = Name of field to contain the 'return' value.
  439. *--               nULRow   = Upper Left Row for box
  440. *--               nULCol   = Upper Left Column for box
  441. *--               nBRRow   = Bottom Right Row
  442. *--               nBRCol   = Bottom Right Column
  443. *--               cColor   = Color of box
  444. *-------------------------------------------------------------------------------
  445.     
  446.     parameters cFile,cSeeExp,cReturn,nULRow,nULCol,nBRRow,nBRCol,cColor
  447.     private cRetVal, cAttr, cStartFile
  448.     
  449.     *-- store starting position ...
  450.     cStartFile = alias()
  451.     select &cFile
  452.     
  453.     *-- look for a matching expression
  454.     seek cSeekExp
  455.     if found()
  456.         cRetVal = &cReturn
  457.     else
  458.         cRetVal = "<Not Found>"
  459.     endif
  460.     
  461.     *-- Store current color and draw a box
  462.     cAttr = set("ATTRIBUTES")
  463.     @nULRow+1,nULCol+1 fill to nBRRow+1,nBRCol+1 color w/n  && shadow
  464.     set color to &cColor
  465.     @nULRow,nULCol clear to nBRRow,nBRCol  && clear out area text will go in
  466.     @nULRow,nULCol To       nBRRow,nBRCol  && draw box
  467.     
  468.     *-- display matching expresion, and return to initial area ...
  469.     @nULRow+1,nULCol+2 say cRetVal
  470.     do ReColor with cAttr
  471.     select cStartFile
  472.     
  473. RETURN .t.
  474. *-- EoF: SeeMatch()
  475.  
  476. FUNCTION Dialog
  477. *-------------------------------------------------------------------------------
  478. *-- Programmer..: Larry Quaglia (Borland)
  479. *-- Date........: 06/09/1992
  480. *-- Notes.......: This routine provides a 'standard' set of dialogue boxes
  481. *--               and buttons for all applications. The concept is to provide
  482. *--               standardization for your apps. Taken from TECHNOTES.
  483. *-- Written for.: dBASE IV, 1.1
  484. *-- Rev. History: 11/01/1991 -- first published in TechNotes.
  485. *--               06/09/1992 -- Modified to handle explicit colors, changed
  486. *--               the color parameters a tad ... (Ken Mayer)
  487. *-- Calls.......: SHADOW               Function in PROC.PRG
  488. *--               RECOLOR              Procedure in PROC.PRG
  489. *-- Called by...: Any
  490. *-- Usage.......: Dialog("<cMsg>",<nType>,"<cBorder>",<nDefBut>,<lShadow>,;
  491. *--                      "<cWind>","<cButton>")
  492. *-- Example.....: Dialog("We have completed the transaction.",0,"DOUBLE",;
  493. *--                      0,.t.,"RG+/GB","W+/N")
  494. *-- Returns.....: Character -- Either 'ERROR' or title of Button.
  495. *-- Parameters..: cMsg    = Message to be displayed -- maximum of 78 characters
  496. *--                          (one line only)
  497. *--               nType   = Dialogue box TYPE. Options are 0 to 5:
  498. *--                         0:   'OK'
  499. *--                         1: 'OK'  'CANCEL'
  500. *--                         2: 'ABORT'  'RETRY'  'IGNORE'
  501. *--                         3: 'YES'  'NO'  'CANCEL'
  502. *--                         4: 'YES'  'NO'
  503. *--                         5: 'RETRY' 'CANCEL'
  504. *--               cBorder = Border Style -- options are: "" (null) for SINGLE
  505. *--                         DOUBLE or PANEL.
  506. *--               nDefBut = Default Button. 
  507. *--               lShadow = Display with a shadow or not (both on window and
  508. *--                         buttons)?
  509. *--               cWind   = Window Colors (must be valid dBASE color combo:
  510. *--                          i.e., "RG+/GB")
  511. *--               cButton = Highlighted Button Color (Same as above, should 
  512. *--                         contrast ...)
  513. *-------------------------------------------------------------------------------
  514.  
  515.     parameters cMsg,nType,cBorder,nDefBut,lShadow,cWind,cButton
  516.     private nMsgLen,cNewColor,aButton,nMaxLine,nY,nBoxLen,nNumButton,nCounter,;
  517.             nBasex,nYCol,nMsgLoc,cCurColor
  518.  
  519.     save screen to sDialog              && so we can restore at end of routine
  520.     
  521.     *-- determine length of message
  522.     nMsgLen = len(trim(ltrim(cMsg))) + 1
  523.     
  524.     *-- Check for valid parms
  525.     do case
  526.         case nMsgLen > 78
  527.             RETURN "ERROR - Message Length"
  528.         case .not. (upper(cBorder) = "DOUBLE" .or. upper(cBorder) = "PANEL" .or.;
  529.                     len(trim(cBorder)) = 0)
  530.             RETURN "ERROR - Border"
  531.     endcase
  532.     
  533.     *-- save current color info and set color to user-defined
  534.     cCurColor = set("ATTRIBUTES")
  535.     set color of normal    to &cWind
  536.     set color of box       to &cWind
  537.     set color of message   to &cWind
  538.     set color of highlight to &cButton
  539.     
  540.     *-- Allow use of <Tab> to move from button to button
  541.     on key label tab keyboard chr(4)  && act as if right arrow were pushed
  542.     
  543.     *-- Define button array -- max of 3 buttons (at the moment)
  544.     declare aButton[3]
  545.     aButton[1] = ""
  546.     aButton[2] = ""
  547.     aButton[3] = ""
  548.     
  549.     *-- Establish screen height to properly center dialogue box
  550.     nMaxLine = iif(right(set("DISP"),2) = "43",43,24)
  551.     
  552.     *-- Determine length of passed "message" parameter. If long enough, make
  553.     *-- the dialog box a little bigger. If very short, make it just big
  554.     *-- enough to accomodate the three buttons.
  555.     nY = iif(int(nMsgLen) > 30,int(nMsgLen/2)+2,24)
  556.     nBoxLen = 2 * nY
  557.     
  558.     *-- Setup the window and determine if shadow ... if yes, call shadow
  559.     define window wDialog from int(nMaxLine/2)-5,40-nY to ;
  560.         int(nMaxLine/2)+4,40+nY &cBorder 
  561.     if lShadow
  562.         activate screen
  563.         do shadow with int(nMaxLine/2)-5,40-nY,int(nMaxLine/2)+4,40+nY
  564.     endif
  565.     activate window wDialog
  566.     clear
  567.     
  568.     *-- Determine the type of buttons and set appropriate parms.
  569.     *-- These could be modified to your own needs.
  570.     do case
  571.         case nType = 0
  572.             nNumButton = 1
  573.             aButton[1] = "   OK   "
  574.         case nType = 1
  575.             nNumButton = 2
  576.             aButton[1] = "   OK   "
  577.             aButton[2] = " CANCEL "
  578.         case nType = 2
  579.             nNumButton = 3
  580.             aButton[1] = " ABORT  "
  581.             aButton[2] = " RETRY  "
  582.             aButton[3] = " IGNORE "
  583.         case nType = 3
  584.             nNumButton = 3
  585.             aButton[1] = "   YES  "
  586.             aButton[2] = "   NO   "
  587.             aButton[3] = " CANCEL "
  588.         case nType = 4
  589.             nNumButton = 2
  590.             aButton[1] = "   YES  "
  591.             aButton[2] = "   NO   "
  592.         case nType = 5
  593.             nNumButton = 2
  594.             aButton[1] = " RETRY  "
  595.             aButton[2] = " CANCEL "
  596.     endcase
  597.     
  598.     *-- Get dialog box length to create a bar menu of appropriate size.
  599.     *-- Define the bar menu in a loop. Deactivate it upon selection of
  600.     *-- one of the buttons.
  601.     nCounter = 1
  602.     nBaseX = nBoxLen / (nNumButton + 1)
  603.     define menu mDialog
  604.     do while nCounter <= nNumButton
  605.         pPadName = "PAD"+str(nCounter,1)  && pad name is 'PAD #'
  606.         nYCol = (nCounter * nBaseX) - (int(len(aButton[nCounter]) /2))
  607.         define pad &pPadName of mDialog prompt aButton[nCounter] at 4,nYCol
  608.         
  609.         *-- If shadow is on, put shadows on buttons as well ...
  610.         if lShadow
  611.             activate screen
  612.             do shadow with 3,nYCol-2,5,nYCol+(len(aButton[nCounter]))-1
  613.         endif
  614.         @3,nYCol-1 to 5,nYCol+(len(aButton[nCounter]))  && box around button
  615.         on selection pad &pPadName of mDialog deactivate menu
  616.         nCounter = nCounter + 1
  617.     enddo
  618.     
  619.     *-- place message (centered in box)
  620.     nMsgLoc = int(nBoxLen/2) - int(nMsgLen/2)
  621.     @1,nMsgLoc say cMsg
  622.     
  623.     *-- place cursor to the default button specified by the user
  624.     nCounter = 1
  625.     do while nCounter < nDefBut
  626.         keyboard chr(4)
  627.         nCounter = nCounter + 1
  628.     enddo
  629.     
  630.     *-- Activate the whole thing, and return the button name
  631.     activate menu mDialog
  632.     cValue = trim(ltrim(prompt()))
  633.     
  634.     *-- deactivate it all, restore screen, etc.
  635.     deactivate window wDialog
  636.     release window wDialog
  637.     release menu mDialog
  638.     restore screen from sDialog
  639.     release screen sDialog
  640.     do ReColor with cCurColor
  641.     on key label tab
  642.     
  643. RETURN cValue
  644. *-- EoF: Dialog()
  645.  
  646. FUNCTION MsgExp
  647. *-------------------------------------------------------------------------------
  648. *-- Programmer..: Adam Menkes (Borland)
  649. *-- Date........: 02/05/1993
  650. *-- Notes.......: Allows you to display message (or error message), centered
  651. *--               like SET MESSAGE ... with added utility. Does not use
  652. *--               "(Press Space)", which can be annoying. The message and the
  653. *--               line on which it is displayed will be the same color.
  654. *--               Taken from TECHNOTES.
  655. *-- Written for.: dBASE IV, 1.1
  656. *-- Rev. History: 09/01/1991 -- Original routine
  657. *--               02/05/1993 -- Modified by Lee Hite to handle a string that
  658. *--                             is greater than 80 characters (this can be
  659. *--                             a real problem if the message is in row 24!)
  660. *-- Usage.......: MsgExp("<cExp>")
  661. *-- Example.....: MsgExp("This is a message")
  662. *-- Returns.....: Message displayed (centered) on screen
  663. *-- Parameters..: cExp  = Message to be displayed
  664. *-------------------------------------------------------------------------------
  665.  
  666.     parameters cMsg
  667.     private nLen
  668.     
  669.     nLen = (80-len(trim(cMsg)))/2
  670.  
  671. RETURN space(nLen) + trim(cMsg) + space(nLen+0.5)
  672. *-- EoF: MsgExp
  673.  
  674. FUNCTION YesNoCan
  675. *-------------------------------------------------------------------------------
  676. *-- Programmer..: Miriam Liskin
  677. *-- Date........: 02/01/1993
  678. *-- Notes.......: Asks a yes/no/cancel question in a dialog window/box
  679. *-- Written for.: dBASE IV, 1.1
  680. *-- Rev. History: 04/19/1991 - Modified by Ken Mayer to become a function
  681. *--               04/29/1991 - Modified to Ken Mayer add shadow
  682. *--               05/13/1991 - Modified to Ken Mayer remove need for extra 
  683. *--                            procedures (YES/NO) that were used for returning
  684. *--                            values from Menu
  685. *--                            (suggested by Clinton L. Warren (VBCES))
  686. *--               01/20/1992 - Modified by Martin Leon (HMan) to handle user
  687. *--                            pressing 'Y' or 'N' keys (with ON KEY ...).
  688. *--               06/11/1992 - Modified by Joey Carroll (JOEY) to allow
  689. *--                            answer choices to be "Yes", "No", or "Cancel"
  690. *--                            or to allow for parameters to pass the contents
  691. *--                            of the prompts. If none are passed, they default
  692. *--                            to "Yes", "No", "Cancel". Further modified to
  693. *--                            allow specification of location by row if 
  694. *--                            desired. Window size now varies as parameters 
  695. *--                            dictate.
  696. *--               09/21/1992 - Modified by JOEY to fix bug caused if leading
  697. *--                            blanks in parameters cPrompt1,cPrompt2,cPrompt3
  698. *--                            Corrected example - case pad()="PPAD1"
  699. *--                            instead of          case pad()=PPAD1
  700. *--               02/01/1993 - Mods by Lee Hite: Routine would not wait for
  701. *--                            user response if "default" answer did not match
  702. *--                            one of the prompts. Now first prompt becomes
  703. *--                            default if no match is found on invocation.
  704. *--                            Also, match is no longer case sensitive.  Also
  705. *--                            made window height variable if message
  706. *--                            lines 2 and/or 3 are null strings.  Finally,
  707. *--                            added "confirmation" parameter which when set
  708. *--                            true will force user to press [Enter] before
  709. *--                            function returns.
  710. *-- Calls.......: SHADOW               Procedure in PROC.PRG
  711. *--               CENTER               Procedure in PROC.PRG
  712. *--               ISBLANK()            Function in MISC.PRG, Internal in 1.5
  713. *-- Called by...: Any
  714. *-- Usage.......: YesNoCan("<cAnswer>","<cMess1>","<cMess2>","<cMess3>",;
  715. *--                 "<cPrompt1>","<cPrompt2>","<cPrompt3>",;
  716. *--                  <nTopRow>,"<cColor>",[lConfirm])
  717. *-- Example.....: cAnswer="Y"
  718. *--               cAnswer=YesNoCan(cAnswer,"*** Warning ***",;
  719. *--                            "A serious error has occured.",;
  720. *--                             "Choose carefully.","Proceed",;
  721. *--                             "Retry","Cancel",10,;
  722. *--                             "w+/r,n/w,w+/r")
  723. *--               do case
  724. *--                  case cAnswer="Y"    && OR case pad()="PPAD1"
  725. *--                     * do your thing
  726. *--                  case cAnswer="N"    && OR case pad()="PPAD2"
  727. *--                     skip
  728. *--                  case cAnswer="C"    && OR case pad()="PPAD3"
  729. *--                     * e.g. - return
  730. *--               endcase
  731. *--
  732. *--                 The middle set of colors should be different, as they
  733. *--                 will be the colors of the YES/NO selections ...
  734. *--                 Options may be blank by using nul values ("")
  735. *-- Returns.....: First character of selected pad
  736. *-- Parameters..: cAnswer  =  default value (Yes or No or Cancel) for menu
  737. *--               cMess1   =  First line of Message
  738. *--               cMess2   =  Second line of message
  739. *--               cMess3   =  Third line of message
  740. *--               cPrompt1 =  Optional prompt for left pad
  741. *--               cPrompt2 =  Optional prompt for middle pad
  742. *--               cPrompt3 =  Optional prompt for right pad
  743. *--               nTopRow  =  Optional top row of window
  744. *--               cColor   =  Optional colors for window/menu/box
  745. *--               lConfirm =  Optional "confirmation" parameter -- if true
  746. *--                           user must press [Enter], otherwise pressing
  747. *--                           a valid prompt key automatically returns
  748. *-------------------------------------------------------------------------------
  749.  
  750.    parameter cAnswer,cMess1,cMess2,cMess3,;
  751.       cPrompt1,cPrompt2,cPrompt3,nTopRow,cColor,lConfirm
  752.    private nLMargin,nRMargin,lWrap,nTopRowMax,cKey1,cKey2,cKey3,nWinWidth, ;
  753.       cConfirm, nWinHgth, nMsgRow
  754.     private cPrompt1,cPrompt2,cPrompt3 
  755.     
  756.     *-- save screen so we can restore ...
  757.    save screen to sYesNoCan
  758.    * locate top row of window
  759.    nTopRowMax = iif(set("STATUS") = "OFF",17,14) && protect Status Line
  760.    nTopRow = iif(isblank(nTopRow),14,nTopRow) && no parameter passed
  761.    nTopRow = min(nTopRowMax,nTopRow)
  762.  
  763.    * set pad prompts if none passed
  764.    cPrompt1 = iif(isblank(cPrompt1),"Yes",cPrompt1)
  765.    cPrompt2 = iif(isblank(cPrompt2),"No",cPrompt2)
  766.    cPrompt3 = iif(isblank(cPrompt3),"Cancel",cPrompt3)
  767.    cAnswer = iif(isblank(cAnswer),cPrompt1,cAnswer)
  768.  
  769.    * program bombs if prompts passed contain leading blanks
  770.    cPrompt1 = ltrim(trim(cPrompt1))
  771.    cPrompt2 = ltrim(trim(cPrompt2))
  772.    cPrompt3 = ltrim(trim(cPrompt3))
  773.  
  774.    * determine how wide the window needs to be
  775.    nWinWidth = max(19,len(cPrompt1 + cPrompt2 + cPrompt3) +13)
  776.    nWinWidth = max(nWinWidth,len(cMess1)+4)
  777.    nWinWidth = max(nWinWidth,len(cMess2)+4)
  778.    nWinWidth = max(nWinWidth,len(cMess3)+4)
  779.    * and how high it needs to be
  780.    nWinHgth = iif(""=cMess2,7,8)
  781.    nWinHgth = iif(""=cMess3,nWinHgth-1,nWinHgth)
  782.    * and center it
  783.    define window wYesNoCan from nTopRow,40-(nWinWidth+2)/2 ;
  784.       to nTopRow+nWinHgth-1,40+(nWinWidth+2)/2 double color &cColor.
  785.    define menu mYesNoCan
  786.    define pad pPad1 of mYesNoCan Prompt "["+cPrompt1+"]" ;
  787.       at nWinHgth-3,02
  788.    * center middle prompt between other two, not center of window
  789.    define pad pPad2 of mYesNoCan Prompt "["+cPrompt2+"]" at nWinHgth-3, ;
  790.       ((nWinWidth-len(cPrompt2))/2+(len(cPrompt1)-len(cPrompt3))/2)
  791.    define pad pPad3 of mYesNoCan Prompt "["+cPrompt3+"]"  ;
  792.       at nWinHgth-3,(nWinWidth-3)-(len(cPrompt3))
  793.    on selection pad pPad1 of mYesNoCan deactivate menu
  794.    on selection pad pPad2 of mYesNoCan deactivate menu
  795.    on selection pad pPad3 of mYesNoCan deactivate menu
  796.     
  797.    activate screen
  798.    do shadow with nTopRow,40-(nWinWidth+2)/2,nTopRow+nWinHgth-1, ;
  799.       40+(nWinWidth+2)/2
  800.    activate window wYesNoCan
  801.     
  802.    do center with 0,nWinWidth,"",cMess1       && center the text
  803.    *-- deal with blank message lines
  804.    nMsgRow = 2
  805.    if "" <> cMess2
  806.       do center with nMsgRow,nWinWidth,"",cMess2
  807.       nMsgRow = nMsgRow + 1
  808.    endif
  809.    if "" <> cMess3
  810.       do center with nMsgRow,nWinWidth,"",cMess3
  811.    endif
  812.    *-- deal with user pressing first key of prompt
  813.    cKey1 = left(cPrompt1,1)
  814.    cKey2 = left(cPrompt2,1)
  815.    cKey3 = left(cPrompt3,1)
  816.  
  817.    *-- set [CR] at end of keyboard command depending on "confirm" parameter
  818.    cConfirm = iif(lConfirm,"",chr(13))
  819.  
  820.    on key label &cKey1. keyboard iif( PAD() = "PPAD1", "", ;
  821.       iif(pad() = "PPAD2", chr(19),CHR(4) )) + cConfirm
  822.    on key label &cKey2. keyboard iif( PAD() = "PPAD2",  "", ;
  823.       iif(pad() = "PPAD1",CHR(4),chr(19) )) + cConfirm
  824.    on key label &cKey3. keyboard iif( PAD() = "PPAD3", "", ;
  825.       iif(pad() = "PPAD2", CHR(4),chr(19))) + cConfirm
  826.    clear typeahead
  827.     *-- otherwise deal with regular "menu" abilities
  828.    do case
  829.       case upper(cAnswer)=upper(cKey1)
  830.            activate menu mYesNoCan pad pPad1
  831.       case upper(cAnswer)=upper(cKey2)
  832.            activate menu mYesNoCan pad pPad2
  833.       case upper(cAnswer)=upper(cKey3)
  834.            activate menu mYesNoCan pad pPad3
  835.       otherwise
  836.            activate menu mYesNoCan pad pPad1
  837.    endcase
  838.     
  839.     *-- clear out ON KEY settings ...
  840.    on key label &cKey1.
  841.    on key label &cKey2.
  842.    on key label &cKey3.
  843.     *-- reset environment
  844.    deactivate window wYesNoCan
  845.    release window wYesNoCan
  846.    restore screen from sYesNoCan
  847.    release screen sYesNoCan
  848.    release menu mYesNoCan
  849.  
  850. RETURN upper(substr(prompt(),2,1))
  851. *-- EoF: YesNoCan()
  852.  
  853. PROCEDURE ProgBar2
  854. *-------------------------------------------------------------------------------
  855. *-- Programmer..: Joey D. Carroll (JOEY)
  856. *-- Date........: 10/26/1992
  857. *-- Notes.......: A crippled version of PROGBAR for those who want it simple.
  858. *--               A visual indicator of program activity, i.e. shows
  859. *--               user program didn't die during long processes which
  860. *--               do not normally show 'on screen'.  Serves same purpose
  861. *--               as MONITOR, but is more graphic.
  862. *--               For best appearance, set cursor 'off' from calling
  863. *--               program, outside of the loop which calls PROGBAR.
  864. *-- Written for.: dBASE IV, 1.5
  865. *-- Rev. History: 06/28/1992 -- Original
  866. *--               10/26/1992 -- protected existing active window.
  867. *-- Calls.......: None
  868. *-- Called by...: Any
  869. *-- Usage.......: do PROGBAR2 with <nQuan>,<cWindCol>,<cFillCol1>,cFillCol2>
  870. *-- Example.....: *-- determine what process will be monitored and what the
  871. *--               *-- final value will be, e.g. nReccount = reccount()
  872. *--               use <anyfile>
  873. *--               nReccount = reccount()
  874. *--               set cursor off
  875. *--               scan
  876. *--                  do progbar2 with nReccount,",,w+/n","w+/r","w+/g"
  877. *--                  *-- do some needed process here
  878. *--               endscan
  879. *--               *-- cleanup
  880. *-- Returns.....: None
  881. *-- Parameters..: nQuan     = maximum number of iterations
  882. *--               cWindCol  = the window colors
  883. *--               cFillCol1 = color of ruler before process
  884. *--               cFillCol2 = color of ruler after process
  885. *-------------------------------------------------------------------------------
  886.  
  887.    parameters nQuan,cWindCol,cFillCol1,cFillCol2   && e.g. how many records
  888.    private nWindWidth
  889.    nWindWidth = 78  && hard coded, wall to wall
  890.  
  891.    *-- skip this section if we've been here before
  892.    *-- this procedure called from inside a loop
  893.    *-- following section ignored except on first iteration thru loop
  894.    if type("nTimes") = "U"
  895.       save screen to sProgBar
  896.       public nFactor,nTimes,wPrevWind
  897.         wPrevWind = window()
  898.       if set("status") = "ON"  && different location if status "on"
  899.          define window wProgBar from 19,0 to 21,79 double color &cWindCol
  900.       else
  901.          define window wProgBar from 21,0 to 23,79 double color &cWindCol
  902.       endif   && set("status") = "ON"
  903.       activate window wProgBar
  904.       @ 0,0 say replicate(".",nWindWidth - 1)  && the ruler
  905.       @ 0,0 say "0%"                        && and some gradation %'s
  906.       @ 0,nWindWidth / 4 - 2 say "25%"
  907.       @ 0,nWindWidth / 2 - 2 say "50%"
  908.       @ 0,3*(nWindWidth / 4) - 2 say "75%"
  909.       @ 0,nWindWidth - 4 say "100%"
  910.       @ 0,0 fill to 0,nWindWidth - 1 color &cFillCol1  && color of ruler before process
  911.       nFactor = nQuan/nWindWidth   && e.g. how many records per bar part(cols)
  912.       nTimes = 0  && times thru loop
  913.    endif      && type("nTimes") = "U"
  914.  
  915.    *-- the section will be processed as many times as required by nQuan
  916.    nTimes = nTimes+1
  917.    @ 0,0 fill to 0,int(nTimes/nFactor) ;
  918.          - iif(int(nTimes/nFactor) -1 >= 0,1,0) ;
  919.          color &cFillCol2    && color of ruler as processing takes place
  920.  
  921.    if nTimes = nQuan  && we done
  922.       x = inkey(.5)   && leave on screen just a liitle while after completion
  923.       * cleanup your mess
  924.       deactivate window wProgBar
  925.       release window wProgBar
  926.       restore screen from sProgBar
  927.       release screen sProgBar
  928.         *-- if window was active, re-activate
  929.         if .not. isblank(wPrevWind)
  930.             activate window wPrevWind
  931.         endif
  932.       release nProgBar,nFactor,nTimes,nWindWidth,x,wPrevWind
  933.    endif
  934.  
  935. RETURN
  936. *-- EoP: PROGBAR2
  937.  
  938. PROCEDURE MovePad
  939. *-------------------------------------------------------------------------------
  940. *-- Programmer..: Angus Scott-Fleming (CIS: 75500,3223)
  941. *-- Date........: 07/29/1992
  942. *-- Notes.......: Used to move the selected pad in a dBASE Bar Menu if the user
  943. *--               selects the first letter/key of the pad. The routine doesn't
  944. *--               re-evalute PAD(), and is based on Genifer code (improved on
  945. *--               by Angus). This should be used with the ON KEY command.
  946. *--               NOTE: This routine assumes you are using the dUFLP/dHUNG
  947. *--               standard for naming pads, and that the first character of
  948. *--               each pad NAME is 'p' (i.e., pColor, pExit, etc.).
  949. *-- Written for.: dBASE IV, 1.5, should work in 1.1.
  950. *-- Rev. History: 07/24/1992 -- Original
  951. *--               07/29/1992 -- Added header/notes.
  952. *-- Calls.......: None
  953. *-- Called by...: Any
  954. *-- Usage.......: do MovePad with <cLetter>,<lSelect>,<cChoices>
  955. *-- Example.....: on key label "C" do MovePad with "C",.t.,cChoices
  956. *-- Returns.....: None
  957. *-- Parameters..: cLetter  = first letter/key on pad
  958. *--               lSelect  = select pad, or move cursor to it? (Act as if user
  959. *--                          pressed <Enter> after moving to it?)
  960. *--               cChoices = list of possible choices (i.e., 
  961. *--                                 "Enter,Edit,Delete,Print,Exit")
  962. *-------------------------------------------------------------------------------
  963.  
  964.    parameters cLetter, lSelect, cChoices
  965.    private nToMove
  966.  
  967.    *-- determine how many pads to move, based on position of choice in list
  968.    *-- of choices (cChoices).
  969.    nToMove = at(cLetter,cChoices) - at(substr(pad(),2,1),cChoices)
  970.  
  971.    *-- if it is a negative value, move to the left, and press <Enter> if 
  972.    *-- lSelect = .t. (otherwise, just move there and stop).
  973.    if nToMove < 0
  974.         keyboard replicate(chr(5), -nToMove) + iif(lSelect,chr(13),"")
  975.     else
  976.         keyboard replicate(chr(24), nToMove) + iif(lSelect,chr(13),"")
  977.     endif
  978.  
  979. RETURN
  980. *-- EoP: MovePad
  981.  
  982. PROCEDURE Monitor
  983. *-------------------------------------------------------------------------------
  984. *-- Programmer..: Miriam Liskin
  985. *-- Date........: 06/08/1992
  986. *-- Notes.......: Displays a status message to monitor a long-running 
  987. *--                 operation that operates on multiple records . . . 
  988. *--                 Should be used with MONITOROFF (below) to cleanup.
  989. *-- Written for.: dBASE IV, 1.1
  990. *-- Rev. History: 04/29/1991 - Modified by Ken Mayer to add shadow
  991. *--               06/08/1992 - Modified to handle explicit color setting
  992. *-- Calls.......: SHADOW               Procedure in PROC.PRG
  993. *--               CENTER               Procedure in PROC.PRG
  994. *-- Called by...: Any
  995. *-- Usage.......: do monitor with "<cText>","<cColor>"
  996. *-- Example.....: do monitor with "Processing REPORT.DBF","rg+/gb,rg+/gb,rg+/gb"
  997. *--               nRec = 0
  998. *--               do while  && (or SCAN)
  999. *--                  && stuff -- process records
  1000. *--                  nRec = nRec + 1
  1001. *--                  @4,30 display ltrim(str(nRec)) && current record
  1002. *--                                                 && in window MONITOR
  1003. *--               enddo  && (or endscan)
  1004. *--               do MonitorOff  && procedure to clean-up after this one
  1005. *-- Returns.....: None
  1006. *-- Parameters..: cText  = Text to display
  1007. *--               cColor = Colors for window
  1008. *-------------------------------------------------------------------------------
  1009.  
  1010.     parameters cText,cColor
  1011.     private cTempCol
  1012.     
  1013.     save screen to sMonitor
  1014.     activate screen
  1015.     define window wMonitor From 10,10 to 18,70 double color &cColor
  1016.     do shadow with 10,10,18,70
  1017.     activate window wMonitor
  1018.     
  1019.     do center with 1,60,"",cText
  1020.     do center with 2,60,"","Please do not interrupt"
  1021.     @4,10 say "Working on record          of " + ltrim(str(reccount(),5))
  1022.     
  1023. RETURN
  1024. *-- EoP: Monitor
  1025.  
  1026. PROCEDURE MonitorOff
  1027. *-------------------------------------------------------------------------------
  1028. *-- Programmer..: Ken Mayer (CIS: 71333,1030)
  1029. *-- Date........: 05/23/1991
  1030. *-- Notes.......: Used to deal with ending routines for MONITOR
  1031. *--                 procedure above.
  1032. *-- Written for.: dBASE IV, 1.1
  1033. *-- Rev. History: 05/23/1991 -- Original
  1034. *-- Calls.......: None
  1035. *-- Called by...: Routine using MONITOR  Procedure in PROC.PRG
  1036. *-- Usage.......: do monitoroff
  1037. *-- Example.....: do monitoroff
  1038. *-- Returns.....: None
  1039. *-- Parameters..: None
  1040. *-------------------------------------------------------------------------------
  1041.  
  1042.     deactivate window wMonitor
  1043.     release window wMonitor
  1044.     restore screen from sMonitor
  1045.     release screen sMonitor
  1046.     
  1047. RETURN
  1048. *-- EoP: MonitorOff
  1049.  
  1050. FUNCTION NewBorder
  1051. *-------------------------------------------------------------------------------
  1052. *-- Programmer..: Kenneth J. Mayer (CIS: 71333,1030)
  1053. *-- Date........: 01/20/1993
  1054. *-- Notes.......: Will save current border setting (the returned value),
  1055. *--               and set a new one with one of a set of pre-defined
  1056. *--               borders. This will create a new variable if it doesn't
  1057. *--               already exist, called: c_Border, which is a PUBLIC Character
  1058. *--               variable. The purpose is so that you can keep using this
  1059. *--               string for other purpose (i.e., DEFINE WINDOW and such ...)
  1060. *-- Written for.: dBASE IV, 1.5
  1061. *-- Rev. History: 01/20/1993 -- Original
  1062. *-- Calls.......: None
  1063. *-- Called by...: Any
  1064. *-- Usage.......: NewBorder("<cStyle>")
  1065. *-- Example.....: cOldBorder = NewBorder("K")
  1066. *--               @5,10 to 15,60  && draw box with new "border" setting
  1067. *--               *-- define a window with new "border" setting
  1068. *--               define window wTest from 10,20 to 20,60 &c_Border
  1069. *--               set border to &cOldBorder  && reset border to original
  1070. *-- Returns.....: Current border setting (before calling routine)
  1071. *-- Parameters..: cStyle = Style from one of the following:
  1072. *--                        A = Double
  1073. *--                                     ╔════╗
  1074. *--                                     ║    ║
  1075. *--                                     ╚════╝
  1076. *--                        B = Single
  1077. *--                                     ┌────┐
  1078. *--                                     │    │
  1079. *--                                     └────┘
  1080. *--                        C = Panel
  1081. *--                                     ██████
  1082. *--                                     █    █
  1083. *--                                     ██████
  1084. *--                        D = None
  1085. *--                        E = Double Top, Single Left, Right, and Bottom
  1086. *--                                      ╒════╕
  1087. *--                                      │    │
  1088. *--                                      └────┘
  1089. *--                        F = Single Top, Double Left, Right and Bottom
  1090. *--                                      ╓────╖
  1091. *--                                      ║    ║
  1092. *--                                      ╚════╝
  1093. *--                        G = Double Top, Left, Right, Single Bottom
  1094. *--                                      ╔════╗
  1095. *--                                      ║    ║
  1096. *--                                      ╙────╜
  1097. *--                        H = Single Top, Left, Right, Double Bottom
  1098. *--                                      ┌────┐
  1099. *--                                      │    │
  1100. *--                                      ╘════╛
  1101. *--                        I = Double Top, Single Left and Right, Double Bottom
  1102. *--                                      ╒════╕
  1103. *--                                      │    │
  1104. *--                                      ╘════╛
  1105. *--                        J = Single Top, Double Left and Right, Single Bottom
  1106. *--                                      ╓────╖
  1107. *--                                      ║    ║
  1108. *--                                      ╙────╜
  1109. *--                        K = Single Top and Left, Double Right and Bottom
  1110. *--                                      ┌────╖
  1111. *--                                      │    ║
  1112. *--                                      ╘════╝
  1113. *--                        L = Single Top, Double Left, Single Right, Dbl Bottom
  1114. *--                                      ╓────┐
  1115. *--                                      ║    │
  1116. *--                                      ╚════╛
  1117. *--                        M = Double Top and Left, Single Right and Bottom
  1118. *--                                      ╔════╕
  1119. *--                                      ║    │
  1120. *--                                      ╙────┘
  1121. *--                        N = Double Top, Single Left, Double Right, Sgl Bottom
  1122. *--                                      ╒════╗
  1123. *--                                      │    ║
  1124. *--                                      └────╜
  1125. *--                        O = Double Top, Single Left, Double Right and Bottom
  1126. *--                                      ╒════╗
  1127. *--                                      │    ║
  1128. *--                                      ╘════╝
  1129. *--                        P = Double Top, Left, Single Right, Double Bottom
  1130. *--                                      ╔═════╕
  1131. *--                                      ║     │
  1132. *--                                      ╚═════╛
  1133. *--                        Q = Single Top, Double Left, Single Right and Bottom
  1134. *--                                      ╓─────┐
  1135. *--                                      ║     │
  1136. *--                                      ╙─────┘
  1137. *--                        R = Single Top and Left, Double Right, Single Bottom
  1138. *--                                      ┌─────╖
  1139. *--                                      │     ║
  1140. *--                                      └─────╜
  1141. *--                        S = Panel, but with more room on the interior ...
  1142. *--                            the default 'panel' mode for borders uses
  1143. *--                            ASCII 219 (alla way around), where this 
  1144. *--                            uses 220-223 ...
  1145. *--                                      ▐▀▀▀▀▀▌
  1146. *--                                      ▐     ▌
  1147. *--                                      ▐▄▄▄▄▄▌
  1148. *-------------------------------------------------------------------------------
  1149.  
  1150.     parameters cStyle
  1151.     cReturn = set("BORDER")    && current border -- if version of dBASE is
  1152.                                && less than 1.5, comment this out ...
  1153.     
  1154.     if type("c_Border") = "U"  && if this is undefined
  1155.         public c_Border         &&   declare it as public
  1156.     endif
  1157.     
  1158.     *-- here we go ...
  1159.     do case
  1160.         case cStyle = "A"   
  1161.             c_Border = "DOUBLE"   && pre-defined
  1162.         case cStyle = "B"
  1163.             c_Border = "SINGLE"   && pre-defined
  1164.         case cStyle = "C"
  1165.             c_Border = "PANEL"    && pre-defined
  1166.         case cStyle = "D"
  1167.             c_Border = "NONE"     && pre-defined
  1168.         case cStyle = "E"
  1169.             *-- items are: top line, bottom line, left line, right line,
  1170.             *-- upper left corner, upper right corner, bottom left corner,
  1171.             *-- bottom right corner
  1172.             c_Border = "205,196,179,179,213,184,192,217"
  1173.         case cStyle = "F"
  1174.             c_Border = "196,205,186,186,214,183,200,188"
  1175.         case cStyle = "G"
  1176.             c_Border = "205,196,186,186,201,187,211,189"
  1177.         case cStyle = "H"
  1178.             c_Border = "196,205,179,179,218,191,212,190"
  1179.         case cStyle = "I"
  1180.             c_Border = "205,205,179,179,213,184,212,190"
  1181.         case cStyle = "J"
  1182.             c_Border = "196,196,186,186,214,183,211,189"
  1183.         case cStyle = "K"
  1184.             c_Border = "196,205,179,186,218,183,212,188"
  1185.         case cStyle = "L"
  1186.             c_Border = "196,205,186,179,214,191,200,190"
  1187.         case cStyle = "M"
  1188.             c_Border = "205,196,186,179,201,184,211,217"
  1189.         case cStyle = "N"
  1190.             c_Border = "205,196,179,186,213,187,192,189"
  1191.         case cStyle = "O"
  1192.             c_Border = "205,205,179,186,213,187,212,188"
  1193.         case cStyle = "P"
  1194.             c_Border = "205,205,186,179,201,184,200,190"
  1195.         case cStyle = "Q"
  1196.             c_Border = "196,196,186,179,214,191,211,217"
  1197.         case cStyle = "R"
  1198.             c_Border = "196,196,179,186,218,183,192,189"
  1199.         case cStyle = "S"
  1200.             c_Border = "223,220,222,221,222,221,222,221"
  1201.     endcase
  1202.     
  1203.     set border to &c_Border
  1204.  
  1205. RETURN cReturn
  1206. *-- EoF: NewBorder
  1207.  
  1208. FUNCTION VidRow
  1209. *-------------------------------------------------------------------------------
  1210. *-- Programmer..: Ken Mayer (CIS: 71333,1030)
  1211. *-- Date........: 01/28/1993
  1212. *-- Notes.......: Calls VDCURSOR.BIN (David Frankenbach, CIS: 72147,2635)
  1213. *--               to return the ABSOLUTE position of the current ROW on the
  1214. *--               screen, despite any active windows, etc.
  1215. *--               This is based on original routines by David Frankenbach,
  1216. *--               but includes the load/release in one routine, rather
  1217. *--               than requiring three functions to perform this ...
  1218. *--               ***************************
  1219. *--               ** REQUIRES VDCURSOR.BIN **
  1220. *--               ***************************
  1221. *-- Written for.: dBASE IV, 1.5
  1222. *-- Rev. History: 01/28/1993 -- Original
  1223. *-- Calls.......: VDCURSOR.BIN
  1224. *-- Called by...: Any 
  1225. *-- Usage.......: VidRow()
  1226. *-- Example.....: ?VidRow()
  1227. *-- Returns.....: Numeric ROW position for current row on screen
  1228. *-- Parameters..: None
  1229. *-------------------------------------------------------------------------------
  1230.  
  1231.     private cX
  1232.     
  1233.     cX = space(2)             && define argument memvar
  1234.     load vdcursor             && load the .BIN file
  1235.     call vdcursor with cX     && call it with the memvar
  1236.     release module vdcursor   && release from memory
  1237.  
  1238. RETURN (asc(substr(cX,2))-1) && return the value of the absolute cursor position
  1239. *-- EoF: VidRow()
  1240.  
  1241. FUNCTION VidCol
  1242. *-------------------------------------------------------------------------------
  1243. *-- Programmer..: Ken Mayer (CIS: 71333,1030)
  1244. *-- Date........: 01/28/1993
  1245. *-- Notes.......: Calls VDCURSOR.BIN (David Frankenbach, CIS: 72147,2635)
  1246. *--               to return the ABSOLUTE position of the current COLUMN on the
  1247. *--               screen, despite any active windows, etc.
  1248. *--               This is based on original routines by David Frankenbach,
  1249. *--               but includes the load/release in one routine, rather
  1250. *--               than requiring three functions to perform this ...
  1251. *--               ***************************
  1252. *--               ** REQUIRES VDCURSOR.BIN **
  1253. *--               ***************************
  1254. *-- Written for.: dBASE IV, 1.5
  1255. *-- Rev. History: 01/28/1993 -- Original
  1256. *-- Calls.......: VDCURSOR.BIN
  1257. *-- Called by...: Any 
  1258. *-- Usage.......: VidCol()
  1259. *-- Example.....: ?VidCol()
  1260. *-- Returns.....: Numeric COLUMN position for current Col on screen
  1261. *-- Parameters..: None
  1262. *-------------------------------------------------------------------------------
  1263.  
  1264.     private cX
  1265.     
  1266.     cX = space(2)             && define argument memvar
  1267.     load vdcursor             && load the .BIN file
  1268.     call vdcursor with cX     && call it with the memvar
  1269.     release module vdcursor   && release from memory
  1270.  
  1271. RETURN (asc(substr(cX,1))-1) && return the value of the absolute cursor position
  1272. *-- EoF: VidCol()
  1273.  
  1274. FUNCTION PwdMask
  1275. *-------------------------------------------------------------------------------
  1276. *-- Programmer..: Kenneth J. Mayer
  1277. *-- Date........: 01/29/1993
  1278. *-- Notes.......: Designed to display a mask on the screen when a user is
  1279. *--               entering a password, rather than a blank surface. Should
  1280. *--               handle backspaces to delete ... ASSUMES <cField> is a
  1281. *--               memvar.
  1282. *--               ***************************
  1283. *--               ** REQUIRES VDCURSOR.BIN **
  1284. *--               ***************************
  1285. *-- Written for.: dBASE IV, 1.5
  1286. *-- Rev. History: 01/29/1993 -- Original
  1287. *-- Calls.......: VidRow()             Function in SCREEN.PRG
  1288. *--               VidCol()             Function in SCREEN.PRG
  1289. *-- Called by...: Any
  1290. *-- Usage.......: PwdMask("<cField>"[,<nMaskChar>])
  1291. *-- Example.....: @5,10 get password when PwdMask("Password");
  1292. *--                      valid required .not. isblank(password);
  1293. *--                      error chr(7)+"Password cannot be blank)
  1294. *-- Returns.....: .T., and field will have password placed in it when done.
  1295. *-- Parameters..: cField    = name of the field
  1296. *--               nMaskChar = ASCII code for mask character. OPTIONAL parameter.
  1297. *--                           if not provided, will use asterisk. Suggested
  1298. *--                           characters include: 176,177,178,219,248,249,254
  1299. *--                                                ░   ▒   ▓   █   °   ∙   ■
  1300. *-------------------------------------------------------------------------------
  1301.  
  1302.     parameters cField, nMaskChar
  1303.     private nLength, nChar, nX
  1304.     
  1305.     *-- deal with mask character
  1306.     if type("NMASKCHAR") = "L"
  1307.         nMaskChar = 42               && *
  1308.     endif
  1309.     
  1310.     lCursor = set("CURSOR") = "ON"
  1311.     set cursor off             && rather than have the cursor in the way ...
  1312.     nLength = len(&cField.)    && get length of current field
  1313.     nChar = 0                  && input character
  1314.     nRow = vidrow()            && get absolute cursor location
  1315.     nCol = vidcol()            && ditto
  1316.     cTemp = ""                 && initialize temp memvar
  1317.     do while len(cTemp) < nLength .and. nChar # 13  
  1318.                                && loop until we hit end of field
  1319.                                && or user presses <Enter>
  1320.     
  1321.         nChar = inkey(0)        && wait for user to enter something
  1322.         
  1323.         do case  
  1324.                                       
  1325.             case nChar = 127                    && <BackSpace>
  1326.                 if isblank(cTemp)                && if empty, don't delete anything
  1327.                     ?? chr(7)                     && instead, BEEP
  1328.                 else
  1329.                     cTemp = left(cTemp,len(cTemp)-1)  && backup one
  1330.                 endif
  1331.                 
  1332.             case (nChar => 65 .and. nChar <= 90) .or.;
  1333.                  (nChar => 97 .and. nChar <= 122) && alphabetic input only
  1334.                 cTemp = cTemp + chr(nChar)         && add character
  1335.                 
  1336.             case nChar = 13                       && <Enter>
  1337.                 exit
  1338.                 
  1339.             otherwise
  1340.                 ?? chr(7)                          && otherwise, BEEP
  1341.                 loop
  1342.         endcase
  1343.         
  1344.         *-- create the current "mask", padding with spaces ...
  1345.         cMask = replicate(chr(nMaskChar),len(cTemp)) + space(nLength-len(cTemp))
  1346.         *-- display it in same color as the current "GET"
  1347.         @nRow,nCol get cMask
  1348.         clear gets
  1349.         *-- put password into current memvar
  1350.         store cTemp to &cField.
  1351.         
  1352.     enddo
  1353.     
  1354.     *-- turn cursor on if it was prior to this routine
  1355.     if lCursor
  1356.         set cursor on
  1357.     endif
  1358.     
  1359.     keyboard chr(13)   && send a final <Enter> to exit this GET
  1360.     
  1361. RETURN .T.
  1362. *-- EoF: PwdMask()
  1363.  
  1364. PROCEDURE MultiPick
  1365. *----------------------------------------------------------------------------
  1366. *-- Programmer..: Jay Parsons (JPARSONS)
  1367. *-- Date........: 02/06/1993
  1368. *-- Notes.......: Permits selecting 0 or more elements of an array.
  1369. *--               The array must contain two columns, the first of which
  1370. *--               contains the prompt for the row and the second of which
  1371. *--               contains logical .T. if the row is selected by default,
  1372. *--               or .F.  Array may contain additional columns.
  1373. *--                     This is written for programmers, not end users.
  1374. *--               It assumes the active window and border style are set before
  1375. *--               it is called, and no error handling is provided for
  1376. *--               attempts to write outside the current window, impossible
  1377. *--               colors, truncation of prompts or other calling errors that
  1378. *--               should become evident on testing.
  1379. *--
  1380. *--               If array contains elements "Hydrangea",.T. and "Tulip",.F.,
  1381. *--               initial display after setting a window and calling will be
  1382. *--               something like this:
  1383. *--
  1384. *--                  [ √ ] Hydrangea
  1385. *--                  [   ] Tulip
  1386. *--
  1387. *--               This program will use the mouse if two conditions exist:
  1388. *--                   1) The variable nG_MusClic must exist and must hold the
  1389. *--               inkey() value of the character "keyboarded" for a click
  1390. *--               by the mouse-event handler.  Note that this is often, but
  1391. *--               need not be, the same as asc( <character> ).
  1392. *--                   2) The mouse must be made active and visible by a
  1393. *--               mouse-control .bin such as JPMOUSE.BIN and MUSCLICK.BIN
  1394. *--               must be loaded and installed.
  1395. *--               *******************************
  1396. *--               **** REQUIRES MUSCLICK.BIN ****
  1397. *--               ****          JPMOUSE.BIN  ****
  1398. *--               ****          VDCURSOR.BIN ****
  1399. *--               *******************************
  1400. *-- Written for.: dBASE IV, 1.5
  1401. *-- Rev. History: 01/16/93 - original procedure
  1402. *--               02/06/93 - revised to use cWnSize, etc.
  1403. *--               02/24/93 - parameters changed, functions called moved out
  1404. *--               02/28/93 - symbolic constants and support for tab added
  1405. *-- Calls.......: SMultPick                 Child procedure to paint screen
  1406. *--               Arrayrows()               Function in Array.prg
  1407. *--               MUSCLICK.BIN              Binary mouse-event handler
  1408. *--               CWnSize()                 Function to find window size
  1409. *--               CWnDecode()               Function to decode the above
  1410. *--               YnMouse()                 Yesno function for mouse
  1411. *--               NormColors()              Function to return normal colors
  1412. *--               HighColors()              Function to return highlight colors
  1413. *--               ForeColor()               Function to return foreground color
  1414. *--
  1415. *-- Called by...: Any
  1416. *-- Usage.......: DO Multipick WITH <cArray>,<nDown>,<nLast>,<nRows>,<nLength>
  1417. *--                                 [, <cColors> [, <cCheck> ] ]
  1418. *-- Example.....: DO Multipick WITH "Myarray",3,15,10,18,"RG+/G,N/W",chr(2)
  1419. *-- Parameters..: cArray      = Name of the array of selectable items.  See
  1420. *--                             Notes, above, for required structure.
  1421. *--               nDown       = first useable row of window
  1422. *--               nLast       = last useable row of window
  1423. *--               nRows       = number of items to show on screen at once
  1424. *--               nLength     = maximum length of prompts
  1425. *--               cColors     = optional, colors to use for noncurrent
  1426. *--                             and current items.  Default is NORMAL and
  1427. *--                             HIGHLIGHT colors for the current window.
  1428. *--                             Pass default as .F. if cCheck is included.
  1429. *--               cCheck      = optional, character to use to show selection.
  1430. *--                             Default is "√".  See "cBox" variables in the
  1431. *--                             procedure for bracketing characters.
  1432. *-- Also uses...: global numeric variable nG_MusClic, giving the inkey()
  1433. *--               value of the character "keyboarded" by a mouse click.
  1434. *--               If this variable does not exist, mouse support is absent.
  1435. *-- Side effects: On return, the values of the second column of the array
  1436. *--               are .T. or .F. in accordance with selections made.
  1437. *-- Special note: The CWnSize function called by this routine uses
  1438. *--               VDCURSOR.BIN, which must be available for this routine
  1439. *--               to work, and disables any ON ERROR trap.
  1440. *-------------------------------------------------------------------------------
  1441.  
  1442.         parameters cArray, nDown, nLast, nRows, nLength, cColors, cCheck
  1443.         private cChar, cCols, cNorm, cHigh, nAt, nTop, nKey, cBoxl, cBoxr
  1444.         private nElems, lGotMouse, nMTop, nMBot, nMLeft, nMRight, cCols
  1445.         private cMrow, cMcol, nMrow, nMcol, cEsc, cWin, nWinTop, nWinLeft
  1446.         private nWinBot, nWinRight, nK, cK, cTemp, nX, cQuit, nRo, lOnPicks
  1447.         private lOk
  1448.  
  1449.         *  These "symbolic constants" are C-style, just to avoid "magic
  1450.         *  numbers" scattered throughout the routine.  Of course, they
  1451.         *  may also slow it down absent a true compiler
  1452.         private NBOXLEN, NEXTRAROWS, NPADLEN, NTWOPADS
  1453.         NBOXLEN    =  6         && length of the "[ √ ] " structure
  1454.         NEXTRAROWS =  4         && blank row at top, 3 rows for quit pads
  1455.         NPADLEN    =  6         && length of the OK and Cancel pads
  1456.         NTWOPADS   = 13         && length of two pads and a space between
  1457.  
  1458.         * set escape
  1459.         cEsc = set("ESCAPE")
  1460.         set escape off
  1461.  
  1462.         * set delimiter chars
  1463.         cBoxl = "[ "
  1464.         cBoxr = " ] "
  1465.  
  1466.         * set colors if specified
  1467.         if type( "cColors" ) = "C"
  1468.           cCols = cColors
  1469.         else
  1470.           cCols = set( "ATTRIBUTES" )
  1471.           cCols = left( cCols, at( "&", cCols ) - 2 )
  1472.         endif
  1473.         cNorm = NormColors( cCols )
  1474.         cHigh = HighColors( cCols )
  1475.         * set up quit pad colors
  1476.         cQuit = cHigh
  1477.  
  1478.         * set checkmark char, default is "√" ( chr( 251 ) )
  1479.         cChar = iif( type( "cCheck" ) # "L", cCheck, "√" )
  1480.  
  1481.         * calculate array rows and set up temporary array for restoration
  1482.         nElems = arrayrows( cArray )
  1483.         declare cTemp[ nElems ]
  1484.         nX = 1
  1485.         do while nX <= nElems
  1486.           cTemp[ nX ] = &cArray[ nX, 2 ]
  1487.           nX = nX + 1
  1488.         enddo
  1489.  
  1490.         *  find borders of current window and determine centering offset
  1491.         cWin = cWnSize()
  1492.         if len( cWin ) > 0
  1493.           nWinTop   = cWnDecode( cWin, "T" )
  1494.           nWinLeft  = cWnDecode( cWin, "L" )
  1495.           nWinBot   = cWnDecode( cWin, "B" )
  1496.           nWinRight = cWnDecode( cWin, "R" )
  1497.         else
  1498.           activate screen
  1499.           ? "Can't find VDCURSOR.BIN - aborting"
  1500.           wait
  1501.           cancel
  1502.         endif
  1503.         nRight = int( ( nWinRight - nWinLeft - NBOXLEN - nLength ) / 2 )
  1504.         nCkCol = nRight + 2
  1505.  
  1506.         *  we need at least 13 columns for the quit pads, and enough for
  1507.         *  the checkbox table itself
  1508.         if nWinRight - nWinLeft < max( NTWOPADS, NBOXLEN + nLength )
  1509.           activate screen
  1510.           ? "Too few columns in this window - aborting"
  1511.           wait
  1512.           cancel
  1513.         endif
  1514.  
  1515.         *  determine rows to use if window is small
  1516.         nRo = min( nRows, min( nLast - nDown, nWinBot - nWinTop - NEXTRAROWS ) )
  1517.         if nRo < 1
  1518.           activate screen
  1519.           ? "Too few rows in this window - aborting"
  1520.           wait
  1521.           cancel
  1522.         endif
  1523.  
  1524.         * test for mouse support and set boundaries of active click area
  1525.         * nMx variables represent absolute screen positions of the edges
  1526.         * of the checkbox table
  1527.         lGotMouse = .F.
  1528.         if type( "nG_MusClick" ) = "N"
  1529.           lGotMouse = .T.
  1530.           nMTop   = nWinTop +  nDown - 1           && row above table
  1531.           nMLeft  = nWinLeft + nRight              && left edge of table
  1532.           nMBot   = nMTop + nRo + 1                && row below table
  1533.           nMRight = nMleft + NBOXLEN + nLength - 1 && right edge
  1534.         endif
  1535.  
  1536.         * position quit pads ( they are displayed by Smultpick )
  1537.         * nLpad and nRpad are column offsets within the active window
  1538.         * of the two pads, "  OK  " and "Cancel"
  1539.         if NPADLEN + nLength > NTWOPADS
  1540.           nLpad = nRight
  1541.         else
  1542.           nLpad = int( ( nWinRight - nWinLeft ) / 4 ) - ( NPADLEN / 2 )
  1543.         endif
  1544.         nRpad = nWinRight - nWinLeft - NPADLEN - nLpad
  1545.  
  1546.         * initialize display as if "Home" had been pressed
  1547.         * nTop is the index into the array of the element to be shown
  1548.         *   on the top row of the table
  1549.         * nHigh is the index into the array of the element to be shown
  1550.         *   highlighted ( the current element )
  1551.         * lOnPicks is the "focus"; .T. means we are in the pick table,
  1552.         *   not on the quit pads
  1553.         nTop = 1
  1554.         nHigh = nTop
  1555.         keyboard "{Home}"
  1556.         lOnPicks = .T.
  1557.  
  1558.         * commence main key-handling loop
  1559.         do while .T.
  1560.           nKey = inkey()
  1561.           if nKey = 0
  1562.             loop
  1563.           endif
  1564.           do case
  1565.             case nKey = 23      && Ctrl-End
  1566.               exit
  1567.             case nKey = 27      && Escape
  1568.               if YesQuit()
  1569.                 exit
  1570.               endif
  1571.             case nKey = 79 .or. nKey = 111   && 'O' or 'o'
  1572.               exit
  1573.             case nKey = 67 .or. nKey = 99    && 'C' or 'c'
  1574.               if YesQuit()
  1575.                 exit
  1576.               endif
  1577.             case nKey = 9                    && Tab
  1578.               if lOnPicks
  1579.                 lOk = .T.                    && default tab is "OK"
  1580.                 @ row(), nRight say cBoxl + iif( &cArray.[ nHigh, 2], ;
  1581.                     cChar, " " ) + cBoxr color &cNorm
  1582.                 @ row(), col() say left( &cArray.[ nHigh, 1 ] ;
  1583.                      + space( nLength ), nLength ) color &cNorm
  1584.                 @ nLast, nLpad + NPADLEN / 2 say ""
  1585.               else
  1586.                 do SmultPick
  1587.               endif
  1588.               lOnPicks = .not. lOnPicks
  1589.             case lGotMouse .and. nKey = nG_MusClick      && mouse click
  1590.               store chr(255) to cMrow, cMcol
  1591.               call MUSCLICK with cMrow, cMcol
  1592.               nMrow = asc( cMrow )
  1593.               nMcol = asc( cMcol )
  1594.               if nMrow >= nMTop .and. nMrow <= nMBot .and. ;
  1595.                 nMcol >= nMLeft .and. nMcol <= nMRight   && in active area
  1596.                 nAt = nHigh - nTop + nMTop + 1
  1597.                 do case
  1598.                   case nMrow = nAt
  1599.                     keyboard chr( 13 )
  1600.                   case nMrow = nMTop
  1601.                     keyboard "{PgUp}"
  1602.                   case nMrow = nMBot
  1603.                     keyboard "{PgDn}"
  1604.                   case nMrow > nAt
  1605.                     do while nAt < nMrow
  1606.                       keyboard "{DNARROW}"
  1607.                       nAt = nAt + 1
  1608.                     enddo
  1609.                   case nMrow < nAt
  1610.                     do while nAt > nMrow
  1611.                       keyboard "{UPARROW}"
  1612.                       nAt = nAt - 1
  1613.                     enddo
  1614.                 endcase
  1615.               else
  1616.                 * if it was on a pad
  1617.                 if nMrow = nWinTop + nLast
  1618.                   if nMcol >= nWinLeft + nLpad .and. nMcol < nWinLeft + ;
  1619.                       nLpad + NPADLEN
  1620.                     keyboard "O"
  1621.                     loop
  1622.                   endif
  1623.                   if nMcol >= nWinLeft + nRpad .and. nMcol < nWinLeft + ;
  1624.                       nRpad + NPADLEN
  1625.                     keyboard "C"
  1626.                     loop
  1627.                   endif
  1628.                 endif
  1629.                 keyboard "{Esc}"
  1630.               endif
  1631.             otherwise
  1632.               if lOnPicks
  1633.                 do case
  1634.                   case nKey = 26      && Home
  1635.                     nTop = 1
  1636.                     nHigh = nTop
  1637.                     do SMultPick
  1638.                   case nKey = 2       && End
  1639.                     nTop = nElems - nRo + 1
  1640.                     nHigh = nElems
  1641.                     do SMultPick
  1642.                   case nKey = 24        && down arrow
  1643.                     if nHigh = nTop + nRo - 1 .or. nHigh = nElems
  1644.                       keyboard "{PgDn}"
  1645.                     else
  1646.                       @ nHigh - nTop + nDown, nRight say ""
  1647.                       @ row(), nRight say cBoxl + iif( &cArray.[ nHigh, 2], ;
  1648.                          cChar, " " ) + cBoxr color &cNorm
  1649.                       @ row(), col() say left( &cArray.[ nHigh, 1 ] ;
  1650.                          + space( nLength ), nLength ) color &cNorm
  1651.                       nHigh = nHigh + 1
  1652.                       @ row() + 1, nRight say cBoxl + iif( &cArray.[ nHigh, 2], ;
  1653.                          cChar, " " ) +cBoxr color &cHigh
  1654.                       @ row(), col() say left( &cArray.[ nHigh, 1 ] ;
  1655.                          + space( nLength ), nLength ) color &cHigh
  1656.                       @ row(), nCkCol say ""
  1657.                     endif
  1658.                   case nKey = 5         && up arrow
  1659.                     if nHigh = nTop
  1660.                       keyboard "{PgUp}"
  1661.                     else
  1662.                       @ nHigh - nTop + nDown, nRight say ""
  1663.                       @ row(), nRight say cBoxl + iif( &cArray.[ nHigh, 2], ;
  1664.                          cChar, " " ) + cBoxr color &cNorm
  1665.                       @ row(), col() say left( &cArray.[ nHigh, 1 ] ;
  1666.                          + space( nLength ), nLength ) color &cNorm
  1667.                       nHigh = max( 1, nHigh - 1 )
  1668.                       @ row() - 1, nRight say cBoxl + iif( &cArray.[ nHigh, 2], ;
  1669.                          cChar, " " ) + cBoxr color &cHigh
  1670.                       @ row(), col() say left( &cArray.[ nHigh, 1 ] ;
  1671.                          + space( nLength ), nLength ) color &cHigh
  1672.                       @ row(), nCkCol say ""
  1673.                     endif
  1674.                   case nKey = 32 .or. nKey = 13  && space and enter are toggles
  1675.                     &cArray.[ nHigh, 2 ] = .not. &cArray[ nHigh, 2 ]
  1676.                     @ row(), nCkCol say iif( &cArray.[ nHigh, 2], cChar, " " ) ;
  1677.                        color &cHigh
  1678.                     @ row(), ncKCol say ""
  1679.                   case nKey = 3      && PgDn
  1680.                     if nHigh = nTop + nRo - 1 .or. nHigh = nElems
  1681.                       nTop = min( nHigh, nElems - nRows + 1 )
  1682.                       do SmultPick
  1683.                     else
  1684.                       @ row(), nRight say cBoxl + iif( &cArray.[ nHigh, 2], ;
  1685.                          cChar, " " ) + cBoxr color &cNorm
  1686.                       @ row(), col() say left( &cArray.[ nHigh, 1 ] ;
  1687.                          + space( nLength ), nLength ) color &cNorm
  1688.                       nHigh = nTop + nRo - 1
  1689.                       @ nDown + nRo - 1, nRight say ""
  1690.                       @ row(), nRight say cBoxl + iif( &cArray.[ nHigh, 2], ;
  1691.                          cChar, " " ) + cBoxr color &cHigh
  1692.                       @ row(), col() say left( &cArray.[ nHigh, 1 ] ;
  1693.                          + space( nLength ), nLength ) color &cHigh
  1694.                       @ row(), nCkCol say ""
  1695.                     endif
  1696.                   case nKey = 18      && PgUp
  1697.                     if nHigh = nTop
  1698.                       nTop = max( 1, nHigh - nRo + 1 )
  1699.                       do SmultPick
  1700.                     else
  1701.                       nHigh = nTop
  1702.                       @ nDown, nRight say ""
  1703.                       @ row(), nRight say cBoxl + iif( &cArray.[ nHigh, 2], ;
  1704.                          cChar, " " ) + cBoxr color &cHigh
  1705.                       @ row(), col() say left( &cArray.[ nHigh, 1 ] ;
  1706.                          + space( nLength ), nLength ) color &cHigh
  1707.                       @ row(), nCkCol say ""
  1708.                     endif
  1709.                 endcase
  1710.               else
  1711.                 do case
  1712.                   case nKey = 32 .or. nKey = 4 .or. nKey = 19  && space, r & l
  1713.                     lOk = .not. lOk
  1714.                     @ nLast, iif( lOk, nLpad, nRpad ) + NPADLEN / 2 say ""
  1715.                   case nKey = 13        && and enter quits
  1716.                     if lOK
  1717.                       keyboard "{CTRL-END}"
  1718.                     else
  1719.                       keyboard "{ESC}"
  1720.                     endif
  1721.                 endcase
  1722.               endif
  1723.           endcase
  1724.         enddo
  1725.  
  1726.         if cEsc ="ON"
  1727.           set escape on
  1728.         endif
  1729. RETURN
  1730. *-- EoP: MultiPick
  1731.  
  1732. PROCEDURE SMultPick
  1733. *-------------------------------------------------------------------------------
  1734. *-- Programmer..: Jay Parsons (JPARSONS)
  1735. *-- Date........: 01/16/1993
  1736. *-- Notes.......: Does screen display loop for Multipick procedure.
  1737. *-- Written for.: dBASE IV, 1.5
  1738. *-- Rev. History: Original function 01/16/1993.
  1739. *-- Calls.......: None
  1740. *-- Called by...: Multipick
  1741. *-- Usage.......: DO SMultpick
  1742. *-- Parameters..: None, but procedure uses various variables set by the
  1743. *--               parent Multipick procedure.
  1744. *-------------------------------------------------------------------------------
  1745.  
  1746.         private nThisOff, nThisRow, nThisElem, nHiRow, nR
  1747.         nThisOff = 0
  1748.         nR = min( nRo, nElems - nTop + 1 )
  1749.         do while nThisOff < nRo
  1750.           nThisRow = nDown + nThisOff
  1751.           nThisElem = nTop + nThisOff
  1752.           if nThisoff < nR
  1753.             if nThisElem = nHigh
  1754.               @ nThisRow, nRight say cBoxl + iif( &cArray.[ nThisElem, 2], ;
  1755.                 cChar, " " ) + cBoxr color &cHigh
  1756.               @ nThisRow, col() say left( &cArray.[ nThisElem, 1 ] ;
  1757.                 + space( nLength ), nLength ) color &cHigh
  1758.               nHiRow = nThisRow
  1759.             else
  1760.               @ nThisRow, nRight say cBoxl + iif( &cArray.[ nThisElem, 2], ;
  1761.                 cChar, " " ) + cBoxr color &cNorm
  1762.               @ nThisRow, col() say left( &cArray.[ nThisElem, 1 ] ;
  1763.                 + space( nLength ), nLength ) color &cNorm
  1764.             endif
  1765.           else
  1766.             @ nThisRow, nRight say space( nCkCol + len( cBoxr ) + nLength )
  1767.           endif
  1768.           nThisoff = nThisOff + 1
  1769.         enddo
  1770.         @ nLast, nLpad say " Done " color &cQuit
  1771.         @ nLast, nRpad say "Cancel" color &cQuit
  1772.         @ nHiRow, nCkCol say ""
  1773. RETURN
  1774. *-- EoP: SMultPick
  1775.  
  1776. FUNCTION YesQuit
  1777. *-------------------------------------------------------------------------------
  1778. *-- Programmer..: Jay Parsons       CIS 70160,340
  1779. *-- Date........: 02/24/1993
  1780. *-- Notes.......: Asks whether to quit and cancel changes; does so if yes.
  1781. *-- Written for.: dBASE IV, Version 1.5.
  1782. *-- Rev. History: 02/.24/1993 -- Original Release
  1783. *-- Calls.......: YnMouse()            Function in SCREENS.PRG
  1784. *-- Called by...: Multipick
  1785. *-- Usage.......: YesQuit()
  1786. *-- Example.....: ? Yesquit()
  1787. *-- Parameters..: None
  1788. *-- Returns.....: Logical, .T. for "Yes" or .F. for "No"
  1789. *-- Side effects: If "Yes", restores cArray[ , 2 ] values from cTemp
  1790. *-------------------------------------------------------------------------------
  1791.         private nX, lRet
  1792.         lRet = YnMouse( "","Do you wish to restore", ;
  1793.                     "the original selection","and leave this routine?" )
  1794.         if lRet
  1795.           nX = 1
  1796.           do while nX <= nElems
  1797.             &cArray[ nX, 2 ] = cTemp[ nX ]
  1798.             nX = nX + 1
  1799.           enddo
  1800.         endif
  1801. RETURN lRet
  1802. *-- EoF: YesQuit()
  1803.  
  1804. FUNCTION YnMouse
  1805. *-------------------------------------------------------------------------------
  1806. *-- Programmer..: Jay Parsons       CIS 70160,340
  1807. *-- Date........: 02/28/1993
  1808. *-- Notes.......: Returns .T. or .F. answer to question without leaving
  1809. *--               mouse droppings.  Will not respond to left arrow properly
  1810. *--               unless set( "ESCAPE" ) is off.
  1811. *--               *******************************
  1812. *--               **** REQUIRES MUSCLICK.BIN ****
  1813. *--               *******************************
  1814. *-- Written for.: dBASE IV, Version 1.5.
  1815. *-- Rev. History: 02/23/93 - original function
  1816. *--               02/28/93 - revised to support right and left arrows
  1817. *-- Calls.......: HighColors()          Function in COLOR.PRG
  1818. *--               Center                Procedure in PROC.PRG ( if centering )
  1819. *-- Called by...: Any
  1820. *-- Usage.......: YnMouse( <cColors>, <cP1> [, <cP2>...] [,<lYes>] )
  1821. *-- Example.....: ? YnMouse( "", "Are you sure?" )
  1822. *-- Parameters..: cColors   -   String, either blank or holding desired
  1823. *--                             colors as standard [ , enhanced [, border ] ]
  1824. *--               cP<n>     -   One or more strings of prompt characters.
  1825. *--                             < only 7 may be passed as literals using
  1826. *--                             dBASE IV 1.5 >.  They will be printed
  1827. *--                             one below the other.  There may not in
  1828. *--                             any event be more than the number of
  1829. *--                             useable screen rows less 6; the parameters
  1830. *--                             line will have to be changed to use more
  1831. *--                             than 20.
  1832. *--                             As furnished, the justification of the
  1833. *--                             prompt strings is flush left.  To center
  1834. *--                             them, see the commented lines in the code.
  1835. *--                             Centering uses the Center procedure in PROC.PRG.
  1836. *--               lYes      -   A logical .T. if the default answer is "Yes"
  1837. *--                             This must be the last parameter, but it may
  1838. *--                             follow any number of prompt lines.
  1839. *-- Returns.....: Logical, .T. for "Yes" or .F. for "No"
  1840. *-------------------------------------------------------------------------------
  1841.  
  1842.         parameters cColors, cP01, cP02, cP03, cP04, cP05, cP06, cP07, cP08,;
  1843.                 cP09, cP10, cP11, cP12, cP13, cP14, cP15, cP16, cP17, cP18,;
  1844.                 cP19, cP20, lYes
  1845.  
  1846.         private cYn, nX, lY, nParams, nRows, nCols, cWhich, nBot, nTop, nLeft
  1847.         private cColrs, cPads, nLpad, nRpad, lRet, nScr
  1848.  
  1849.         * obtain number of prompts, and default answer if provided
  1850.         nParams = pcount() - 1
  1851.         lY = .F.
  1852.  
  1853.         * if we have 22 parameters, last must be the default answer
  1854.         if nParams = 21
  1855.           lY = lYes
  1856.         * otherwise look at the last parameter's type--if it is logical
  1857.         * that's the default answer and not a prompt
  1858.         else
  1859.           cWhich = "cP" + right( str( 100 + nParams ), 2 )
  1860.           if type( cWhich ) = "L"
  1861.             lY = &cWhich
  1862.             nParams = nParams - 1
  1863.           endif
  1864.         endif
  1865.  
  1866.         * we need six rows for top and bottom borders, space before prompts,
  1867.         * space after prompts, yes/no pads and space after them
  1868.         nRows = nParams + 6
  1869.         nScr = iif( "43" $ set( "DISPLAY" ), 43, 25 )
  1870.  
  1871.         * don't overwrite messages, status or scoreboard
  1872.         nBot = nScr - 2
  1873.         nTop = 0
  1874.         if set( "STATUS" ) = "ON"
  1875.           nBot = nBot - 2
  1876.         else
  1877.           if set( "SCOREBOARD" ) = "ON"
  1878.             nTop = 1
  1879.           endif
  1880.         endif
  1881.         if nRows > nBot - nTop
  1882.           activate screen
  1883.           ? "Too many prompt lines for screen size - aborting"
  1884.           wait
  1885.           cancel
  1886.         endif
  1887.  
  1888.         * find longest prompt line and window width it requires including
  1889.         * a space at both ends
  1890.         nX = 1
  1891.         nCols = 13               && 11 spaces for the pads, 2 for border
  1892.         do while nX <= nParams
  1893.           cWhich = "cP" + right( str( 100 + nX ), 2 )
  1894.           nCols = max( nCols, len( trim( &cWhich ) ) + 2 )
  1895.           nX = nX + 1
  1896.         enddo
  1897.  
  1898.         * round up to even number of columns in order to center the window
  1899.         nCols = 2 * ceiling( nCols/ 2 )
  1900.         if nCols > 80
  1901.           activate screen
  1902.           ? "Prompts are too long for screen - aborting"
  1903.           wait
  1904.           cancel
  1905.         endif
  1906.  
  1907.         * calculate screen row of top and bottom of centered window
  1908.         nTop = max( nTop, int( ( nScr - nRows ) / 2 ) )
  1909.         nBot = nTop + nRows
  1910.  
  1911.         * and screen column of left edge
  1912.         nLeft = 39 - nCols / 2
  1913.  
  1914.         * obtain colors to use, using highlight for pads
  1915.         cColrs = iif( "" # cColors, cColors, set( "ATTRIBUTES" ) )
  1916.         if "&" $ cColrs
  1917.           cColrs = left( cColrs, at( "&", cColrs ) - 1  )
  1918.         endif
  1919.         cPads = HighColors( cColrs )
  1920.  
  1921.         * calculate column positions of yes/no pads
  1922.         nLpad = int( ( nCols - 2 ) / 4 ) - 2
  1923.         nRpad = nCols - nLpad - 6
  1924.  
  1925.         * now open the window and print prompts
  1926.         define window cYn from nTop, nLeft to nBot, nLeft + nCols color &cColrs
  1927.         activate window cYn
  1928.         nX = 1
  1929.         do while nX <= nParams
  1930.           cWhich = "cP" + right( str( 100 + nX ), 2 )
  1931. *  To change from flush left to centered justification of the prompts,
  1932. *  uncomment the next code line and comment out the one following.
  1933. *  You will then need the "Center" procedure in PROC.PRG.
  1934. *         do Center with nX, nCols, "", &cWhich
  1935.           @ nX, 1 say &cWhich
  1936.           nX = nX + 1
  1937.         enddo
  1938.  
  1939.         * print pads
  1940.         @ nX + 1, nLpad say " Yes " color &cPads
  1941.         @ nX + 1, nRpad say "  No " color &cPads
  1942.         @ nX + 1, iif( lY, nLpad, nRpad ) + 2 say ""
  1943.  
  1944.         * and begin a loop that may last forever
  1945.         clear typeahead
  1946.         do while .T.
  1947.           nk = inkey()
  1948.             if nk = 0
  1949.               loop
  1950.             endif
  1951.             do case
  1952.               case nk = 89 .or. nk = 121    && 'Y' or 'y'
  1953.                 lRet = .T.
  1954.                 exit
  1955.               case nK = 78 .or. nK = 110 .or. nK = 27   && 'N' or 'n' or Esc
  1956.                 lRet = .F.
  1957.                 exit
  1958.               case nK = 13 .or. nK = 23     && Enter or Ctrl-End
  1959.                 lRet = lY
  1960.                 exit
  1961.               case nK = 4 .or. nK = 19      && right or left arrow
  1962.                 lY = .not. lY
  1963.                 @ nX + 1, iif( lY, nLpad, nRpad ) + 2 say ""
  1964.               case type( "nG_MusClic" ) = "N" .and. nk = nG_MusClic
  1965.                 store chr(255) to cMrow, cMcol
  1966.                 call MUSCLICK with cMrow, cMcol
  1967.                 nMrow = asc( cMrow )
  1968.                 nMcol = asc( cMcol )
  1969.                 if nMrow = nTop + nX + 2      && one more for border
  1970.                   if nMcol >= nLpad + nLeft .and. nMcol < nLpad + nLeft + 5
  1971.                     lRet = .T.
  1972.                     exit
  1973.                   endif
  1974.                   if nMcol >= nRpad + nLeft .and. nMcol <nRpad + nLeft + 5
  1975.                     lRet = .F.
  1976.                     exit
  1977.                   endif
  1978.                 endif
  1979.             endcase
  1980.           enddo
  1981.           deactivate window cYn
  1982.           release window cYn
  1983.  
  1984. RETURN lRet
  1985. *-- EoF: YnMouse()
  1986.  
  1987. FUNCTION CWnDecode
  1988. *-------------------------------------------------------------------------------
  1989. *-- Programmer..: Jay Parsons       CIS 70160,340
  1990. *-- Date........: 02/06/1993
  1991. *-- Notes.......: Returns the numeric value of one of the four codes for
  1992. *--               edges of the window held in a string of the type returned
  1993. *--               by cWnSize.  These represent numbers of rows or columns.
  1994. *-- Written for.: dBASE IV, Versions 1.0 - 1.5.
  1995. *-- Rev. History: 02/06/1993 -- Original Release
  1996. *-- Calls.......: None
  1997. *-- Called by...: Any
  1998. *-- Usage.......: cWnDecode( <cWnString>,<cEdge>|<nPos> )
  1999. *-- Example.....: cWinTop = cWnDecode( cWin, "T" )
  2000. *-- Parameters..: cWnString -   A string returned by CWnSize
  2001. *--               cEdge -       A character parameter beginning with one
  2002. *--                             of the four characters "T","L","B",or "R",
  2003. *--                             ( upper or lower case ), OR
  2004. *--               nPos  -       A number indicating the position in the
  2005. *--                             cWnString of the code for the edge.
  2006. *--                             These correspond to the following:
  2007. *--                             Window edge       cEdge       nPos
  2008. *--                               top              T           1
  2009. *--                               left             L           2
  2010. *--                               bottom           B           3
  2011. *--                               right            R           4
  2012. *--                             Either cEdge or nPos must be furnished,
  2013. *--                             not both.
  2014. *-- Returns.....: numeric value of the row or column; -1 for argument
  2015. *--               out of range or cWnString holds garbage or is empty.
  2016. *-------------------------------------------------------------------------------
  2017.         parameters cWnString, xEdge
  2018.         private nPos, nRet
  2019.         nRet = -1
  2020.         if type( "xEdge" ) = "C"
  2021.           nPos = at( upper( left( xEdge, 1 ) ), "TLBR" )
  2022.         else
  2023.           if type( "xEdge" ) = "N"
  2024.             nPos = xEdge
  2025.           endif
  2026.         endif
  2027.         if nPos > 0 .and. nPos < 5 .and. len( cWnString ) = 4
  2028.           nRet = asc( substr( cWnString, nPos, 1 ) ) - 1
  2029.         endif
  2030.         if nRet > iif( mod( nPos, 2 ) > 0, 43, 80 )
  2031.           nRet = -1
  2032.         endif
  2033. RETURN nRet
  2034. *-- EoF: CWnDecode
  2035.  
  2036. FUNCTION CWnSize
  2037. *-------------------------------------------------------------------------------
  2038. *-- Programmer..: Jay Parsons       CIS 70160,340
  2039. *-- Date........: 02/06/1993
  2040. *-- Notes.......: Returns a string of four characters which are chr()
  2041. *--               values of one more each than the top, left, bottom
  2042. *--               and right row and column numbers of the usable surface
  2043. *--               of the current window, or of the screen.  ( one more
  2044. *--               to avoid chr( 0 ) problems )
  2045. *--               Returns "" if unable to find VDCURSOR.BIN
  2046. *--               *******************************
  2047. *--               **** REQUIRES VDCURSOR.BIN ****
  2048. *--               *******************************
  2049. *-- Written for.: dBASE IV, Versions 1.0 - 1.5.
  2050. *-- Rev. History: 02/06/1993 -- Original Release
  2051. *-- Calls.......: nWBsrch()           function included
  2052. *-- Called by...: Any
  2053. *-- Usage.......: cWnSize()
  2054. *-- Example.....: cWin = cWnSize()
  2055. *--               WinBot = asc( substr( cWin, 3 1 ) )
  2056. *-- Parameters..: None
  2057. *-- Returns.....: character string of four chr() values, or "" if error
  2058. *-- Side effects: Called function nWBsrch disables any error trap
  2059. *-------------------------------------------------------------------------------
  2060.         private nHi, nLo, nL, cV
  2061.  
  2062.         cV = ""
  2063.         if file( "VDCURSOR.BIN" )
  2064.           load VDCURSOR
  2065.           @ 0,0 say ""
  2066.           cV = call( "VDCURSOR","  " )
  2067.           release module VDCURSOR
  2068.           * reverse bytes so row comes first
  2069.           cV = right( cV, 1 ) + left( cV, 1 )
  2070.           * this is the first row, and one more than maximum last
  2071.           nL = asc( cV ) - 1
  2072.           nLo = nL
  2073.           nHi = 44
  2074.           cV = cV + chr( nL + nWBsrch( nLo, nHi, "Down" ) + 1 )
  2075.           * first column and one more than last
  2076.           nL = asc( substr( cV, 2, 1 ) ) - 1
  2077.           nLo = nL
  2078.           nHi = 80
  2079.           cV = cV + chr( nL + nWBsrch( nLo, nHi, "Across" ) + 1 )
  2080.         endif
  2081.  
  2082. RETURN cV
  2083. *-- EoF: CWnSize()
  2084.  
  2085. FUNCTION nWBsrch
  2086. *-------------------------------------------------------------------------------
  2087. *-- Programmer..: Jay Parsons       CIS 70160,340
  2088. *-- Date........: 02/06/1993
  2089. *-- Notes.......: special binary search routine for window edges
  2090. *-- Written for.: dBASE IV, Versions 1.0 - 1.5.
  2091. *-- Rev. History: 02/06/1993 -- Original Release
  2092. *-- Calls.......: None
  2093. *-- Called by...: cWnSize
  2094. *-- Usage.......: nWBsrch( < nLo >, < nHi >, < cDir > )
  2095. *-- Example.....: Lastrow = nWBsrch( 0, 44, "Down" )
  2096. *-- Parameters..: nLo           Number, top row or left column
  2097. *--               nHi           Number, bottom or right screen edge + 1
  2098. *--               cDir          char, direction - "Down" or "Across"
  2099. *-- Returns.....: number of highest row or column that may be written to.
  2100. *-- Side effects: Disables any ON ERROR trap
  2101. *-------------------------------------------------------------------------------
  2102.         parameters nLo, nHi, cDir
  2103.         private lToohigh, nTry, cD
  2104.         cD = upper( left( cDir, 1 ) )
  2105.         do while nHi > nLo + 1
  2106.           lTooHigh = .F.
  2107.           nTry = int( ( nHi + nLo ) / 2 )
  2108.           on error lTooHigh = .T.
  2109.           if cD $ "DB"
  2110.             @ nTry, 0 say ""
  2111.           else
  2112.             @ 0, nTry say ""
  2113.           endif
  2114.           if lToohigh
  2115.             nHi = nTry - 1
  2116.           else
  2117.             nLo = nTry
  2118.           endif
  2119.         enddo
  2120.         on error
  2121.  
  2122. RETURN nLo
  2123. *-- EoF(): nWBsrch
  2124.  
  2125. PROCEDURE SetBorder
  2126. *-------------------------------------------------------------------------------
  2127. *-- Programmer..: Kenneth J. Mayer (CIS: 71333,1030)
  2128. *-- Date........: 03/22/1993
  2129. *-- Notes.......: This routine is designed as a front-end for the NEWBORDR
  2130. *--               routine. It's purpose is to display a sample of the specific
  2131. *--               border from a picklist, and allow the user to select
  2132. *--               one ...
  2133. *-- Written for.: dBASE IV, 2.0
  2134. *-- Rev. History: 03/22/1993
  2135. *-- Calls.......: NEWBORDR()           (Function in SCREEN.PRG)
  2136. *--               SHADOW               (Procedure in PROC.PRG)
  2137. *--               DRAWIT               (Procedure in SCREEN.PRG)
  2138. *-- Called by...: Any
  2139. *-- Usage.......: Do SetBordr with <cColor>
  2140. *-- Example.....: Do SetBordr with cWind1
  2141. *-- Returns.....: None
  2142. *-- Parameters..: cColor = colors for window ...
  2143. *-------------------------------------------------------------------------------
  2144.  
  2145.     parameters cColor
  2146.     private cWindow,cBorder,cHigh
  2147.     
  2148.     *-- start off with a few basics
  2149.     save screen to sBorder        && save screen so we can cleanup
  2150.     cWindow = window()            && save current window (if any)
  2151.     activate screen
  2152.     cBorder = set("BORDER")       && save current border setting, in
  2153.                                   && case user doesn't select one ...
  2154.     
  2155.     *-- define a window ... note that we're using the current default border
  2156.     define window wBorder from 5,5 to 15,70 color &cColor.
  2157.     do shadow with 5,5,15,70
  2158.     activate window wBorder
  2159.  
  2160.     cHigh = colorbrk(cColor,2)
  2161.     @0,40 fill to 8,60 color &cHigh.
  2162.     @0,40 to 8,60 color &cHigh.
  2163.     @4,45 say "Test Area" color &cHigh.
  2164.  
  2165.     *-- create the popup ...
  2166.     define popup pBorders from 0,0
  2167.     define bar  1 of pBorders prompt "A) Double"
  2168.     define bar  2 of pBorders prompt "B) Single"
  2169.     define bar  3 of pBorders prompt "C) Panel (Normal)"
  2170.     define bar  4 of pBorders prompt "D) None"
  2171.     define bar  5 of pBorders prompt "E) Double Top, Single Rest"
  2172.     define bar  6 of pBorders prompt "F) Single Top, Double Rest"
  2173.     define bar  7 of pBorders prompt "G) Single Bottom, Double Rest"
  2174.     define bar  8 of pBorders prompt "H) Double Bottom, Single Rest"
  2175.     define bar  9 of pBorders prompt "I) Double Top/Bottom, Single Rest"
  2176.     define bar 10 of pBorders prompt "J) Single Top/Bottom, Double Rest"
  2177.     define bar 11 of pBorders prompt "K) Single Top/Left, Double Rest"
  2178.     define bar 12 of pBorders prompt "L) Single Top/Right, Double Rest"
  2179.     define bar 13 of pBorders prompt "M) Double Top/Left, Single Rest"
  2180.     define bar 14 of pBorders prompt "N) Double Top/Right, Single Rest"
  2181.     define bar 15 of pBorders prompt "O) Single Left, Double Rest"
  2182.     define bar 16 of pBorders prompt "P) Single Right, Double Rest"
  2183.     define bar 17 of pBorders prompt "Q) Double Left, Single Rest"
  2184.     define bar 18 of pBorders prompt "R) Double Right, Single Rest"
  2185.     define bar 19 of pBorders prompt "S) Panel (Thin)"
  2186.     on popup pBorders do drawit 
  2187.     on selection popup pBorders deactivate popup
  2188.     
  2189.     *-- Now to play inside the window
  2190.     activate popup pBorders    
  2191.  
  2192.     *-- if user didn't select _anything_, then return to original ...
  2193.     if lastkey() = 27 .or. lastkey() = 4 .or. lastkey() = 19
  2194.       set border to &cBorder.
  2195.       c_Border = cBorder
  2196.     endif
  2197.  
  2198.     *-- cleanup
  2199.     release window wBorder
  2200.     release popup pBorders
  2201.     restore screen from sBorder
  2202.     release screens Border
  2203.  
  2204. RETURN
  2205. *-- EoP: SetBorder
  2206.  
  2207. PROCEDURE DrawIt
  2208. *-------------------------------------------------------------------------------
  2209. *-- Programmer..: Kenneth J. Mayer (CIS: 71333,1030)
  2210. *-- Date........: 03/22/1993
  2211. *-- Notes.......: Used specifically with SETBORDER above, to display the current
  2212. *--               selection from the popup.
  2213. *-- Written for.: dBASE IV, 2.0
  2214. *-- Rev. History: 03/22/1993 -- Original
  2215. *-- Calls.......: NewBorder()          Function in SCREEN.PRG
  2216. *-- Called by...: SetBorder            Procedure in SCREEN.PRG
  2217. *-- Usage.......: Do DrawIt
  2218. *-- Example.....: Do DrawIt
  2219. *-- Returns.....: None
  2220. *-- Parameters..: None
  2221. *-------------------------------------------------------------------------------
  2222.  
  2223.     cStyle = left(Prompt(),1)
  2224.     x = NewBorder(cStyle)
  2225.     if c_Border = "SINGLE"
  2226.         set border to single
  2227.   endif
  2228.     if c_Border = "NONE"
  2229.       @0,40 say space(21) color &cHigh.
  2230.       @8,40 say space(21) color &cHigh.
  2231.       nCounter = 0
  2232.       do while nCounter < 8
  2233.          nCounter = nCounter + 1
  2234.          @nCounter,40 say space(1) color &cHigh.
  2235.          @nCounter,60 say space(1) color &cHigh.
  2236.       enddo
  2237.     else
  2238.         @0,40 to 8,60 color &cHigh.
  2239.     endif
  2240.  
  2241. RETURN
  2242. *-- EoP: DrawIt
  2243.  
  2244. FUNCTION Wait4Key
  2245. *-------------------------------------------------------------------------------
  2246. *-- Programmer..: Angus Scott-Fleming (CIS: 75500,3223)
  2247. *--               GeoApplications, Tucson, Arizona
  2248. *-- Date........: 03/24/1993
  2249. *-- Notes.......: Time-out option for a READ screen.
  2250. *-- Written for.: dBASE IV, 1.1
  2251. *-- Rev. History: 03/24/1993 -- Original
  2252. *-- Calls.......: None
  2253. *-- Called by...: Any
  2254. *-- Usage.......: @x,y GET <fieldname> when Wait4Key(<nSeconds>)
  2255. *-- Example.....: @10,10 get m->cTest when Wait4Key(5)
  2256. *-- Returns.....: logical -- .t. if key pressed within nSeconds, .f. if not.
  2257. *-- Parameters..: nSeconds = how long to wait for time-out.
  2258. *-------------------------------------------------------------------------------
  2259.  
  2260.     parameters nSeconds
  2261.     private nDummy, lKeyPressd
  2262.     
  2263.     nDummy = inkey(nSeconds)
  2264.     if nDummy = 0                    && no keypress
  2265.         *-- abort the read
  2266.         keyboard chr(27)              && send an <Esc>
  2267.         lKeyPressd = .f.
  2268.     else
  2269.         *-- keyboard the character
  2270.         keyboard chr(nDummy)
  2271.         lKeyPressd = .t.
  2272.     endif
  2273.  
  2274. RETURN lKeyPressd
  2275. *-- EoF: Wait4Key()
  2276.  
  2277. *-------------------------------------------------------------------------------
  2278. *--       Library functions included for convenience
  2279. *-------------------------------------------------------------------------------
  2280.  
  2281. FUNCTION NormColors
  2282. *-------------------------------------------------------------------------------
  2283. *-- Programmer..: Jay Parsons       CIS 70160,340
  2284. *-- Date........: 02/23/1993
  2285. *-- Notes.......: Returns the "normal" portion of a color string
  2286. *-- Written for.: dBASE IV, Version 1.5.
  2287. *-- Rev. History: 02/23/1993 -- Original Release
  2288. *-- Calls.......: None
  2289. *-- Called by...: Any
  2290. *-- Usage.......: NormColors( <cColor> )
  2291. *-- Example.....: ? NormColors( "N/BG,BG+/N,W+/B" )
  2292. *-- Parameters..: cColor    -   String holding colors
  2293. *-- Returns.....: Character, normal color portion of string.
  2294. *-------------------------------------------------------------------------------
  2295.         parameters cColor
  2296.         private cRet
  2297.         cRet = cColor
  2298.         if "," $ cRet
  2299.           cRet = left( cRet, at( ",", cRet ) - 1 )
  2300.         endif
  2301. RETURN upper( ltrim( trim ( cRet ) ) )
  2302. *-- EoF: NormColors()
  2303.  
  2304. FUNCTION HighColors
  2305. *-------------------------------------------------------------------------------
  2306. *-- Programmer..: Jay Parsons       CIS 70160,340
  2307. *-- Date........: 02/23/1993
  2308. *-- Notes.......: Returns the "highlight" portion of a color string
  2309. *-- Written for.: dBASE IV, Version 1.5.
  2310. *-- Rev. History: 02/23/1993 -- Original Release
  2311. *-- Calls.......: None
  2312. *-- Called by...: Any
  2313. *-- Usage.......: HighColors( <cColor> )
  2314. *-- Example.....: ? HighColors( "N/BG,BG+/N,W+/B" )
  2315. *-- Parameters..: cColor    -   String holding colors
  2316. *-- Returns.....: Character, highlight color portion of string.
  2317. *--               Returns empty string if no such portion.
  2318. *-------------------------------------------------------------------------------
  2319.         parameters cColor
  2320.         private cRet
  2321.         cRet = ""
  2322.         if "," $ cColor
  2323.           cRet = substr( cColor, at( ",",cColor ) + 1 )
  2324.           if "," $ cRet
  2325.             cRet = left( cRet, at( ",", cRet ) - 1 )
  2326.           endif
  2327.         endif
  2328. RETURN upper( ltrim( trim( cRet ) ) )
  2329. *-- EoF: HighColors()
  2330.  
  2331. FUNCTION ForeColor
  2332. *-------------------------------------------------------------------------------
  2333. *-- Programmer..: Jay Parsons       CIS 70160,340
  2334. *-- Date........: 02/24/1993
  2335. *-- Notes.......: Returns foreground part of color string.
  2336. *-- Written for.: dBASE IV, Version 1.5.
  2337. *-- Rev. History: 02/24/1993 -- Original Release
  2338. *-- Calls.......: None
  2339. *-- Called by...: Any
  2340. *-- Usage.......: ForeColor( <cColor> )
  2341. *-- Example.....: ? ForeColor( "N/BG" )
  2342. *-- Parameters..: cColor    -   String holding color foreground and background
  2343. *-- Returns.....: Character, string with foreground portion of the color
  2344. *-------------------------------------------------------------------------------
  2345.         parameters cColor
  2346.         private cRet
  2347.         cRet = upper( trim( ltrim( cColor ) ) )
  2348.         if "/" $ cRet
  2349.           cRet = left( cRet, at( "/", cRet ) - 1 )
  2350.         endif
  2351.         if "*" $ cColor
  2352.           cRet = cRet + "*"
  2353.         endif
  2354.         if "+" $ cColor
  2355.           cRet = cRet + "+"
  2356.         endif
  2357.  
  2358. RETURN cRet
  2359. *-- EoF: ForeColor()
  2360.  
  2361. PROCEDURE Center
  2362. *-------------------------------------------------------------------------------
  2363. *-- Programmer..: Miriam Liskin
  2364. *-- Date........: 05/24/1991
  2365. *-- Notes.......: Centers text on the screen with @says
  2366. *-- Written for.: dBASE IV, 1.1
  2367. *-- Rev. History: This and all other procedures/functions listed in this
  2368. *--               file attributed to Miriam Liskin came from "Liskin's
  2369. *--               Programming dBASE IV Book". Very good, worth the money.
  2370. *-- Calls.......: None
  2371. *-- Called by...: Any
  2372. *-- Usage.......: do center with <nLine>,<nWidth>,"<cColor>","<cText>"
  2373. *-- Example.....: do center with 5,65,"RG+/GB","WARNING! This will blow up!"
  2374. *--                  Note that the color field may be blank: ""
  2375. *-- Returns.....: None
  2376. *-- Parameters..: nLine  = Line or Row for @/Say
  2377. *--               nWidth = Width of screen
  2378. *--               cColor = Colors to be used ("Forg/Back") (may be nul "", in
  2379. *--                           order to use the default colors of window/screen)
  2380. *--               cText  = Message to center on screen
  2381. *-------------------------------------------------------------------------------
  2382.     
  2383.     parameters nLine,nWidth,cColor,cText
  2384.     private nCol
  2385.     
  2386.     nCol = (nWidth - len(cText)) /2
  2387.     @nLine,nCol say cText color &cColor.
  2388.     
  2389. RETURN
  2390. *-- EoP: Center
  2391.  
  2392. FUNCTION ArrayRows
  2393. *-------------------------------------------------------------------------------
  2394. *-- Programmer..: Jay Parsons (JPARSONS)
  2395. *-- Date........: 03/01/1992
  2396. *-- Notes.......: Number of Rows in an array
  2397. *-- Written for.: dBASE IV, 1.1
  2398. *-- Rev. History: 03/01/1992 -- Original Release
  2399. *-- Calls.......: None
  2400. *-- Called by...: Any
  2401. *-- Usage.......: ArrayRows("<aArray>")
  2402. *-- Example.....: n = ArrayRows("aTest")
  2403. *-- Returns.....: numeric
  2404. *-- Parameters..: aArray      = Name of array 
  2405. *-------------------------------------------------------------------------------
  2406.  
  2407.     parameters aArray
  2408.     private nHi, nLo, nTrial, nDims
  2409.     nLo = 1
  2410.     nHi = 1170
  2411.     if type( "&aArray[ 1, 1 ]" ) = "U"
  2412.       nDims = 1
  2413.     else
  2414.      nDims = 2
  2415.     endif
  2416.     do while .T.
  2417.      nTrial = int( ( nHi + nLo ) / 2 )
  2418.       if nHi < nLo
  2419.         exit
  2420.       endif
  2421.      if nDims = 1 .and. type( "&aArray[ nTrial ]" ) = "U" .or. ;
  2422.        nDims = 2 .and. type( "&aArray[ nTrial, 1 ]" ) = "U"
  2423.         nHi = nTrial - 1
  2424.       else
  2425.         nLo = nTrial + 1
  2426.       endif
  2427.     enddo
  2428.     
  2429. RETURN nTrial
  2430. *-- EoF: ArrayRows()
  2431.  
  2432. PROCEDURE ReColor
  2433. *-------------------------------------------------------------------------------
  2434. *-- Programmer..: Jay Parsons (Jparsons)
  2435. *-- Date........: 04/23/1992
  2436. *-- Notes.......: Restores colors to those held in a string of the form
  2437. *--               returned by set("ATTRIBUTE").
  2438. *-- Written for.: dBASE IV, Versions 1.0 - 1.5.
  2439. *-- Rev. History: 04/23/1992 -- Original Release
  2440. *-- Calls.......: None
  2441. *-- Called by...: Any
  2442. *-- Usage.......: DO ReColor WITH <cColors>
  2443. *-- Example.....: DO Recolor WITH OldColors
  2444. *-- Parameters..: cColors, a string in the form returned by set("ATTRIBUTE").
  2445. *-- Returns.....: None
  2446. *-- Side effects: Changes the screen colors.
  2447. *-------------------------------------------------------------------------------
  2448.  
  2449.   parameters cColors
  2450.   private cThis, cNext, nAt, cLeft, nX, cAreas
  2451.   cAreas = "   NORMHIGHBORDMESSTITLBOX INFOFIEL"
  2452.   cLeft = cColors + ", "
  2453.   nX = 0
  2454.   do while nX < 8
  2455.     nX = nX + 1
  2456.     cThis = substr( cAreas, 4 * nX, 4 )
  2457.     if nX = 3
  2458.       nAt = at( "&", cLeft )
  2459.       cNext = left( cLeft, nAt - 2 )
  2460.       cLeft = substr( cLeft, nAt + 3 )
  2461.       SET COLOR TO , , &cNext
  2462.     else
  2463.       nAt = at( ",", cLeft )
  2464.       cNext = left( cLeft, nAt - 1 )
  2465.       cLeft = substr( cLeft, nAt + 1 )
  2466.       SET COLOR OF &cThis TO &cNext
  2467.     endif
  2468.   enddo
  2469.  
  2470. RETURN
  2471. *-- EoP: ReColor
  2472.  
  2473. *-------------------------------------------------------------------------------
  2474. *-- EoP: SCREEN.PRG
  2475. *-------------------------------------------------------------------------------
  2476.