home *** CD-ROM | disk | FTP | other *** search
/ DOS Wares / doswares.zip / doswares / DATABASE / DBASE5 / SAMPLES.ZIP / LIBRARY.PRG < prev    next >
Encoding:
Text File  |  1994-06-24  |  45.0 KB  |  1,344 lines

  1. ******************************************************************************
  2. * PROGRAM NAME: LIBRARY.PRG
  3. *               LIBRARY OF PROCEDURES COMMON TO ALL BUSINESS PROGRAMS
  4. *               SAMPLE BUSINESS APPLICATION PROGRAM
  5. * LAST CHANGED: 03/11/93
  6. * WRITTEN BY:   Borland International Inc.
  7. ******************************************************************************
  8.  
  9. PROCEDURE Add_new
  10.    * Add new record to database file
  11.    * Erase previous record number from screen
  12.    lAddNew = .T.
  13.    @ 0,65 SAY SPACE(15) COLOR &c_yellow.
  14.    * Display F9 lookup key message, if lookup available
  15.    IF lookup_ok
  16.       DO Sho_look WITH dbf
  17.    ENDIF
  18.    DO Init_fld
  19.    DO Get_data
  20.    READ
  21.    * Erase lookup message from screen
  22.    @ 0,0 SAY SPACE(51)
  23.    * If user didn't enter data into key fields, exit without saving
  24.    IF "" = TRIM(&key.) .OR. READKEY() < 256
  25.        RETURN
  26.    ELSE
  27.       * Each application checks for duplicates if duplicate keys not allowed
  28.       * If duplicate key (when not allowed), exit from add mode without saving
  29.       IF rec_is_dup
  30.          * Reset status flag and exit
  31.          rec_is_dup = .F.
  32.          RETURN
  33.       ELSE
  34.          * Append and save validated record
  35.          DO Sav_data
  36.          GO record_num
  37.       ENDIF
  38.    ENDIF
  39. RETURN
  40.  
  41. PROCEDURE Bar_def
  42.    * Define the main popup OPTION MENU, main_mnu
  43.    mesg = "Press first letter of Menu choice, or highlight and press <Enter>"
  44.    DEFINE POPUP main_mnu FROM 2,58 TO 22,78 MESSAGE mesg
  45.    DEFINE BAR  1 OF main_mnu PROMPT "==  OPTION MENU  ==" SKIP
  46.    DEFINE BAR  2 OF main_mnu PROMPT " Add record"
  47.    DEFINE BAR  3 OF main_mnu PROMPT " Edit record"
  48.    DEFINE BAR  4 OF main_mnu PROMPT " Delete record"
  49.    DEFINE BAR  5 OF main_mnu PROMPT "-------------------" SKIP
  50.    DEFINE BAR  6 OF main_mnu PROMPT " Next record"
  51.    DEFINE BAR  7 OF main_mnu PROMPT " Previous record"
  52.    DEFINE BAR  8 OF main_mnu PROMPT " Top record"
  53.    DEFINE BAR  9 OF main_mnu PROMPT " Bottom record"
  54.    DEFINE BAR 10 OF main_mnu PROMPT " Skip records"
  55.    DEFINE BAR 11 OF main_mnu PROMPT " Find record"
  56.    DEFINE BAR 12 OF main_mnu PROMPT "-------------------" SKIP
  57.    DEFINE BAR 13 OF main_mnu PROMPT " List records"
  58.    DEFINE BAR 14 OF main_mnu PROMPT " Output reports"
  59.    DEFINE BAR 15 OF main_mnu PROMPT " Group records" SKIP FOR dbf = "ACCT_REC"
  60.    DEFINE BAR 16 OF main_mnu PROMPT " Count records"
  61.    DEFINE BAR 17 OF main_mnu PROMPT " Index database"
  62.    DEFINE BAR 18 OF main_mnu PROMPT " Help"
  63.    DEFINE BAR 19 OF main_mnu PROMPT " Quit to MAIN MENU"
  64.    * Define the popup dest_mnu for printing reports to a destination
  65.    DEFINE POPUP dest_mnu FROM 13,10 TO 19,38 MESSAGE mesg
  66.    DEFINE BAR 1 OF dest_mnu PROMPT "======= DESTINATION =======" SKIP
  67.    DEFINE BAR 2 OF dest_mnu PROMPT " Printer"
  68.    DEFINE BAR 3 OF dest_mnu PROMPT " File"
  69.    DEFINE BAR 4 OF dest_mnu PROMPT " Screen"
  70.    DEFINE BAR 5 OF dest_mnu PROMPT " Exit to OPTION MENU"
  71.    * Define the popup rpt_mnu for printing reports to a destination
  72.    DEFINE POPUP rpt_mnu FROM 11, 5 TO 17,38 MESSAGE mesg
  73.    DEFINE BAR 1 OF rpt_mnu  PROMPT "============ REPORTS ===========" SKIP
  74.    DEFINE BAR 2 OF rpt_mnu  PROMPT " Database report: " + dbf
  75.    DEFINE BAR 3 OF rpt_mnu  PROMPT " Mailing list: "  + mlist ;
  76.       SKIP FOR mlist = "NOT AVAILABLE"
  77.    DEFINE BAR 4 OF rpt_mnu  PROMPT " Custom programmed report: " + cust_rpt ;
  78.       SKIP FOR cust_rpt = "N/A"
  79.    DEFINE BAR 5 OF rpt_mnu  PROMPT " Exit to OPTION MENU"
  80.    * Define which procedures are executed by the defined popups
  81.    ON SELECTION POPUP main_mnu DO Barpop
  82.    ON SELECTION POPUP rpt_mnu  DO Barpop_r
  83.    ON SELECTION POPUP dest_mnu DO Barpop_d
  84.    * Define windows for text, msgs, etc.
  85.    IF "MONO" $ SET( "DISPLAY" )
  86.       DEFINE WINDOW alert      FROM 15, 3 TO 22,46 DOUBLE COLOR &c_alert.
  87.       DEFINE WINDOW duplicat   FROM 15, 5 TO 21,70 DOUBLE COLOR &c_alert.
  88.       DEFINE WINDOW lister     FROM  5, 5 TO 22,70 DOUBLE COLOR &c_list.
  89.       DEFINE WINDOW look       FROM  6, 5 TO 16,65 DOUBLE COLOR &c_list.
  90.       DEFINE WINDOW memo_windo FROM  7, 4 TO 19,75 DOUBLE COLOR &c_list.
  91.    ELSE
  92.       DEFINE WINDOW alert      FROM 15, 3 TO 22,46 PANEL COLOR &c_alert.
  93.       DEFINE WINDOW duplicat   FROM 15, 5 TO 21,70 PANEL COLOR &c_alert.
  94.       DEFINE WINDOW lister     FROM  5, 5 TO 22,70 PANEL COLOR &c_list.
  95.       DEFINE WINDOW look       FROM  6, 5 TO 16,65 PANEL COLOR &c_list.
  96.       DEFINE WINDOW memo_windo FROM  7, 4 TO 19,75 PANEL COLOR &c_list.
  97.    ENDIF
  98. RETURN
  99.  
  100. PROCEDURE Barpop
  101.    * Perform action selected by user from OPTION MENU bars
  102.    DO CASE
  103.        * BAR() = 1 is title of menu
  104.        CASE BAR() = 2                  && Add record
  105.           DO Add_new
  106.        CASE BAR() = 3                  && Edit record
  107.           DO Edit
  108.        CASE BAR() = 4                  && Delete record
  109.           DO Eraser
  110.        CASE BAR() = 6                  && Next record
  111.           DO Skip_rec WITH 1
  112.        CASE BAR() = 7                  && Previous record
  113.           DO Skip_rec WITH -1
  114.        CASE BAR() = 8                  && Top record, in active index order
  115.           GO TOP
  116.        CASE BAR() = 9                  && Bottom record, in active index order
  117.           GO BOTTOM
  118.        CASE BAR() = 10                 && Skip records
  119.           DO Skip_rec WITH 0
  120.        CASE BAR() = 11                 && Find record
  121.           DO Find_rec WITH key, key1, keyname1, key2, keyname2, key3, keyname3
  122.        CASE BAR() = 13                 && List records
  123.           DO List_rec
  124.        CASE BAR() = 14                 && Output reports
  125.           SAVE SCREEN TO Pre_rept      && Save screen image
  126.           ACTIVATE POPUP rpt_mnu
  127.           RESTORE SCREEN FROM Pre_rept
  128.           RELEASE SCREEN Pre_rept
  129.        CASE BAR() = 15              && Group records
  130.           DO Filter
  131.        CASE BAR() = 16                 && Count records
  132.           ************
  133.           IF NETWORK()
  134.              * Turn off file lock to count
  135.              SET LOCK off
  136.              DO Kount
  137.              SET LOCK on
  138.              ***********
  139.           ELSE
  140.              DO Kount
  141.           ENDIF
  142.        CASE BAR() = 17                  && Index database
  143.           ************
  144.           IF NETWORK()
  145.              old_tag = ORDER()
  146.              USE (dbf) EXCLUSIVE
  147.              IF net_choice <> 27        && check Net_err user choice (Esc=27)
  148.                 DO Indexer
  149.                 SET EXCLUSIVE off
  150.                 USE (dbf) ORDER (old_tag)
  151.              ENDIF
  152.              ***********************
  153.           ELSE
  154.              DO Indexer
  155.           ENDIF
  156.        CASE BAR() = 18                  && Help
  157.           SET COLOR TO &c_standard.
  158.           DO Helper
  159.        CASE BAR() = 19                && Quit to Main Menu
  160.           DEACTIVATE POPUP
  161.    ENDCASE
  162.    DO Dstatus                         && Display record no and filter status
  163.    DO Show_data                       && Display screen with current record
  164.    CLEAR GETS
  165.    SET COLOR TO &c_popup.
  166. RETURN
  167.  
  168. PROCEDURE Barpop_d
  169.    * Perform action selected by user from Destination menu
  170.    SET COLOR TO &c_popup.
  171.    DO CASE
  172.       * BAR() 1 is title of menu
  173.       CASE BAR() = 2                  && Output to printer
  174.          ll_esc = .F.
  175.          DO Prt_menu                  && Activate menu for print options
  176.          IF .NOT. ll_esc
  177.             SET PRINTER on
  178.             SET CONSOLE off
  179.             DO Printout               && Output selected report
  180.             SET PRINTER off
  181.             SET CONSOLE on
  182.          ENDIF
  183.       CASE BAR() = 3                  && Output to file
  184.          answer = SPACE(8)
  185.          ACTIVATE WINDOW alert
  186.             @ 0,0 SAY "----------- SEND REPORT TO FILE ----------"
  187.             @ 2,1 SAY "Enter filename for report: " GET answer ;
  188.                VALID "" <> TRIM(answer) ;
  189.                MESSAGE "Enter a filename of up to eight characters"
  190.             READ
  191.          DEACTIVATE WINDOW alert
  192.          SET ALTERNATE TO &answer.
  193.          SET ALTERNATE on
  194.          SET CONSOLE off
  195.          GO TOP
  196.          DO Printout                  && Output report or labels to file
  197.          SET ALTERNATE off
  198.          SET CONSOLE on
  199.       CASE BAR() = 4                  && Output to screen
  200.          SET COLOR TO &c_standard.
  201.          CLEAR
  202.          * Store current page settings
  203.          plength  = _plength
  204.          rmargin  = _rmargin
  205.          * Set page width & length for screen
  206.          _plength = 25
  207.          _rmargin = 80
  208.          DO Printout                  && Output chosen report/labels to screen
  209.          CLEAR
  210.          * Reset page settings
  211.          _plength = plength
  212.          _rmargin = rmargin
  213.          GO record_num                && Return to original record
  214.       CASE BAR() = 5                  && Exit to OPTION MENU
  215.          DEACTIVATE POPUP
  216.    ENDCASE
  217.    SET COLOR TO &c_standard.
  218.    DEACTIVATE POPUP
  219. RETURN
  220.  
  221. PROCEDURE Barpop_r
  222.    * Select available reports menu
  223.    SET COLOR TO &c_popup.
  224.    reportype = SPACE(6)
  225.    DO CASE
  226.       CASE BAR() = 2                  && Output standard report to destination
  227.          reportype = "LISTING"
  228.          ACTIVATE POPUP dest_mnu      && Activate printer destination menu
  229.       CASE BAR() = 3                  && Output mailing labels to destination
  230.          reportype = "LABELS"
  231.          ACTIVATE POPUP dest_mnu      && Activate printer destination menu
  232.       CASE BAR() = 4                  && Output custom report to destination
  233.          reportype = "CUSTOM"
  234.          ACTIVATE WINDOW alert
  235.             * Get custom report name from user
  236.             * First, allow READ errors and warning bell
  237.             SET BELL ON
  238.             rpt_name = SPACE(8)
  239.             @ 0,0 SAY "-------- CUSTOM PROGRAMMED REPORT --------"
  240.             @ 2,1 SAY "Enter report program name:" GET rpt_name ;
  241.                VALID FILE(TRIM(rpt_name) + ".prg") ;
  242.                MESSAGE "Enter a filename of up to eight " + ;
  243.                        "characters, e.g. Emp_rept " ;
  244.                ERROR "Invalid filename, please re-enter"
  245.             READ
  246.             SET BELL OFF
  247.          DEACTIVATE WINDOW alert
  248.          IF LASTKEY() <> 27           && A report filename was found
  249.             SET COLOR TO &c_popup.
  250.             ACTIVATE POPUP dest_mnu
  251.          ENDIF
  252.    ENDCASE
  253.    SET COLOR TO &c_popup.
  254.    DEACTIVATE POPUP
  255. RETURN
  256.  
  257. PROCEDURE Sub_ret
  258.    IF erased
  259.       * Pack deleted records (if any) - erases completely from database
  260.       ************
  261.       IF NETWORK()
  262.          USE (dbf) EXCLUSIVE
  263.       ENDIF
  264.       IF net_choice <> 27       && Skip if user pressed Esc
  265.       *******************       && error condition
  266.          ?? CHR(7)
  267.          ACTIVATE WINDOW alert
  268.             @ 0,0 SAY "----------- PACKING  DATABASE ------------"
  269.             @ 2,1 SAY "ERASING deleted records now......"
  270.             @ 3,1 SAY "Please wait......DO NOT TURN OFF"
  271.             PACK
  272.          DEACTIVATE WINDOW alert
  273.       ENDIF
  274.    ENDIF
  275.    * Houskeeping
  276.    CLOSE DATABASES
  277.    CLEAR WINDOWS
  278.    RELEASE ALL
  279.    CLEAR
  280.    ON KEY LABEL F9             && Turn off ON KEY LABEL F9/F10 commands
  281.    ON KEY LABEL F10
  282.    * Restore environment (in case user began at Control Center or dot prompt)
  283.    DO Rest_env
  284.    CLEAR
  285. RETURN TO MASTER               && Exit Subapplication
  286.  
  287. FUNCTION Duplicat
  288.    PARAMETERS key
  289.    * Used if duplicates are not allowed in a database
  290.    * Set rec_is_dup to .T. if user entered duplicate key data
  291.    rec_is_dup = .F.
  292.    IF RECCOUNT() = 0 .OR. "" = TRIM(key)
  293.       * Do not check if database or key field(s) is empty
  294.       RETURN rec_is_dup
  295.    ENDIF
  296.    record_num = RECNO()               && Save current record position
  297.    SEEK  TRIM(key)
  298.    * Determine if record is duplicate key
  299.    * PROMPT() used instead of BAR() for clarity
  300.    DO CASE
  301.       CASE PROMPT() = " Edit record"
  302.          * If seek finds a record other than the current one,
  303.          * the edited record has a duplicate key
  304.          rec_is_dup =  record_num <> RECNO() .AND. FOUND()
  305.       CASE PROMPT() = " Add record"
  306.          * New record is duplicate if seek finds any record that matches
  307.          rec_is_dup = FOUND()
  308.    ENDCASE
  309.    IF rec_is_dup                      && Show duplicate record in window
  310.       ACTIVATE WINDOW duplicat
  311.          CLEAR
  312.          DO Warnbell
  313.          ?  "------------------ DUPLICATE " + dbf + ;
  314.             " RECORD ------------------"
  315.          ?  "                    Duplicates not allowed"
  316.          DO CASE
  317.             CASE dbf = "CUST"
  318.                ?  " " + cust_id + " " + customer
  319.                ? "This is the EXISTING record in the database; " + ;
  320.                  "re-enter Cust.ID."
  321.             CASE dbf = "VENDORS"
  322.                ?  " " + vendor_id + " " + vendor
  323.                ? "This is the EXISTING record in the database; " + ;
  324.                  "re-enter Vendor ID."
  325.             CASE dbf = "GOODS"
  326.                ?  " " + part_id + " " + part_name
  327.                ? "This is the EXISTING record in the database; " + ;
  328.                  "re-enter Part ID."
  329.             CASE dbf = "ACCT_REC"
  330.                ?  " " + invoice_no + " " + cust_id + " " + DTOC(dat_of_bil)
  331.                ? "This is the EXISTING record in the database; " + ;
  332.                  "re-enter Invoice ID."
  333.          ENDCASE
  334.          WAIT "     Press spacebar to continue..."
  335.       DEACTIVATE WINDOW duplicat
  336.    ENDIF
  337.    GO record_num                     && Return to original record
  338. RETURN .NOT. rec_is_dup
  339.  
  340. PROCEDURE Dstatus
  341.    * Display filter status and current record number
  342.    * Set colors with blink on/off depending on hardware
  343.    IF filters_on
  344.       * Show blinking msg for filter status
  345.       @ 0,51 SAY "Filter is ON" COLOR &c_blink.
  346.    ELSE
  347.       SET COLOR TO &c_standard.
  348.       * Erase message - filter is off
  349.       @ 0,51
  350.    ENDIF
  351.    * Show  current record number on screen
  352.    @ 0,66 SAY "Record #" + STR(RECNO(),5,0) COLOR &c_yellow.
  353. RETURN
  354.  
  355. PROCEDURE Edit
  356.    * Edit current record
  357.    * Display lookup key message if lookup available (set in each application)
  358.    lAddNew = .F.
  359.    IF lookup_ok
  360.       DO Sho_look WITH dbf
  361.    ENDIF
  362.    record_num = RECNO()
  363.    * Load data from record into memory variables
  364.    IF .NOT. NETWORK()
  365.       DO Load_fld
  366.    ELSE
  367.       DO WHILE .NOT. RLOCK()
  368.          *------------------------------------------------
  369.          *-- Net_Err will continue to make the record lock
  370.          *-- attempt until the user presses Escape.  The
  371.          *-- escape will terminate the sub-application
  372.          *------------------------------------------------
  373.          DO Net_Err WITH 109, .T.
  374.       ENDDO
  375.       DO Load_fld
  376.    ENDIF
  377.  
  378.    DO Get_data
  379.    READ                           && Edit data
  380.  
  381.    *****
  382.    * Erase F9 lookup message from screen
  383.    @ 0,0 SAY SPACE(51)
  384.    IF "" = TRIM(&key.) .OR. READKEY() < 256
  385.       * Exit if user blanked key, did not change data, or deleted record
  386.       UNLOCK
  387.       RETURN
  388.    ELSE
  389.       * Save edited data to disk
  390.       DO Sav_data
  391.    ENDIF
  392. RETURN
  393.  
  394. PROCEDURE Eraser
  395.    * Erase current record
  396.    IF NodShake( " ;   Erase this data record?   ", ;
  397.                 9, 26, 2, 29, .F. )
  398.  
  399.       DELETE
  400.       * Position to the next record
  401.       SKIP
  402.       * Check if the last record was deleted
  403.       DO CASE
  404.          CASE filters_on .AND. EOF()
  405.             * If no records left in filter subset, turn off filter
  406.             SET FILTER TO
  407.             filters_on = .F.
  408.             * If last record deleted, go to beginning of database
  409.             GO TOP
  410.          CASE .NOT. filters_on .AND. EOF()
  411.             * If last record deleted, go to beginning of database
  412.             GO TOP
  413.       ENDCASE
  414.       * Set erased status flag that record was deleted
  415.       erased = .T.
  416.    ENDIF
  417. RETURN
  418.  
  419. PROCEDURE Filt_ans
  420.    * Get answer from user about filtering data into subset
  421.    IF filters_on
  422.       *-- Filter window - to turn off filter
  423.       IF NodShake( " ;    GROUP into SUBSET (Filter)   ;" + ;
  424.                    "   Subset is currently selected.   ;" + ;
  425.                    "         Turn Filter off?", ;
  426.                    7, 22, 4, 35, .F. )
  427.          choice = "T"
  428.       ELSE
  429.          choice = "N"
  430.       ENDIF
  431.    ELSE
  432.       *-- Filter window - to turn on filter
  433.       IF NodShake( " ;    GROUP into SUBSET (Filter)   ;" + ;
  434.                    "   Select temporary subset of data   ;" + ;
  435.                    "   by entering filter condition(s)   ;" + ;
  436.                    "             Proceed?", ;
  437.                    7, 21, 5, 37, .F. )
  438.          choice = "Y"
  439.       ELSE
  440.          choice = "N"
  441.       ENDIF
  442.  
  443.    ENDIF
  444. RETURN
  445.  
  446. PROCEDURE Findcode
  447.    PARAMETERS acity
  448.    * Look up area code for phone number - by city
  449.    acode = 0
  450.    ACTIVATE WINDOW alert
  451.       CLEAR
  452.       acode = LOOKUP(Codes->code,TRIM(acity),Codes->city)
  453.       ? "------------- AREA CODE LOOKUP -----------"
  454.       IF .NOT. FOUND("Codes") .OR. "" = TRIM(acity)
  455.          DO Warnbell
  456.          ? "City: " + TRIM(acity) + " was"    AT 2
  457.          ? "NOT FOUND in areacodes database." AT 2
  458.       ELSE
  459.          ?
  460.          ? "AREA CODE is: " + STR(acode,3) AT 2
  461.          ? "for " + TRIM(acity)  AT 16
  462.       ENDIF
  463.       ?
  464.       WAIT "  Press spacebar to continue..."
  465.    DEACTIVATE WINDOW alert
  466. RETURN
  467.  
  468. PROCEDURE Findcust
  469.    PARAMETERS custid
  470.    * Look up customer from customer ID
  471.    acust = ""
  472.    ACTIVATE WINDOW alert
  473.       CLEAR
  474.       acust = LOOKUP(Cust->customer,TRIM(custid),Cust->cust_id)
  475.       ? "---------- CUSTOMER ID  LOOKUP -----------"
  476.       IF .NOT. FOUND("Cust") .OR. "" = TRIM(custid)
  477.          DO Warnbell
  478.          ? "Customer ID: " + TRIM(custid) + " was" AT 2
  479.          ? "NOT FOUND in Cust database." AT 2
  480.       ELSE
  481.          ? "Customer: " + TRIM(acust)  AT 2
  482.          ? "Phone:    " + Cust->phone  AT 2
  483.          ? "for ID: "   + TRIM(custid) AT 12
  484.       ENDIF
  485.       WAIT "  Press spacebar to continue..."
  486.    DEACTIVATE WINDOW alert
  487. RETURN
  488.  
  489. PROCEDURE Find_rec
  490.    PARAMETERS key, key1, keyname1, key2, keyname2, key3, keyname3
  491.    * Get target data to find/seek and show data record after retrieving
  492.    STORE "" TO target1, target2, target3
  493.    target1 = IIF(TYPE(key1) = "C", SPACE(LEN(&key1.)), {  /  /  })
  494.    * If key2 exists (database requires two keys)
  495.    IF "NONE" <> key2
  496.       target2 = IIF(TYPE(key2) = "C", SPACE(LEN(&key2.)), {  /  /  })
  497.       * If key3 exists (database has three keys)
  498.       IF "NONE" <> key3
  499.          target3 = IIF(TYPE(key3) = "C", SPACE(LEN(&key3.)), {  /  /  })
  500.       ENDIF
  501.    ENDIF
  502.    ACTIVATE WINDOW alert
  503.       @ 0,0 SAY "-------- ENTER TARGET DATA TO FIND -------"
  504.       @ 2, 1 SAY keyname1
  505.       @ 2,15 GET target1  MESSAGE "Enter " + keyname1
  506.       IF "NONE" <> key2
  507.          @ 3, 1 SAY keyname2
  508.          @ 3,15 GET target2
  509.          IF "NONE" <> key3
  510.             @ 4, 1 SAY keyname3
  511.             @ 4,15 GET target3
  512.          ENDIF
  513.       ENDIF
  514.       @ 5,1 SAY "Enter partial or entire data"
  515.       READ
  516.    DEACTIVATE WINDOW alert
  517.    target = IIF(type(key1) = "C", target1, DTOC(target1))
  518.    IF "NONE" <> key2
  519.       target = target + IIF(type(key2) = "C", target2, DTOC(target2))
  520.       IF "NONE" <> key3
  521.          target = target + IIF(type(key3) = "C", target3, DTOC(target3))
  522.       ENDIF
  523.    ENDIF
  524.    target = TRIM(target)
  525.    IF RIGHT(target, 6) = "  /  /"
  526.       * If a date key wasn't filled in, remove the template
  527.       target = LEFT(target, LEN(target) - 6)
  528.    ENDIF
  529.    IF "" = target
  530.       * If user entered nothing (blank key) => exit
  531.       RETURN
  532.    ENDIF
  533.    * Store record no. that the user was viewing
  534.    record_num = RECNO()
  535.    * Find record with target key
  536.    IF .NOT. SEEK(target)
  537.       * If target not found, uppercase & look again
  538.       IF .NOT. SEEK(UPPER(target))
  539.          * Sound bell and alert user with message
  540.          DO Warnbell
  541.          DO Show_msg WITH "Record with target data was NOT found."
  542.          * Return to original record user was viewing
  543.          GO record_num
  544.       ENDIF
  545.    ENDIF
  546. RETURN
  547.  
  548. PROCEDURE Findpart
  549.    PARAMETERS partid
  550.    * Look up part data using part ID number in Goods database when
  551.    * function key pressed
  552.    p_name = SPACE(30)
  553.    ACTIVATE WINDOW alert
  554.       CLEAR
  555.       p_name = LOOKUP(Goods->part_name,TRIM(partid),Goods->part_id)
  556.       ? "------------ PART CODE  LOOKUP ----------"
  557.       IF .NOT. FOUND("Goods") .OR. "" = TRIM(partid)
  558.          DO Warnbell
  559.          ? "Part ID: " + TRIM(partid) AT 2
  560.          ? "was NOT FOUND in Goods database." AT 2
  561.       ELSE
  562.          ? "For ID:    " + partid       AT 2
  563.          ? "Part name: " + TRIM(p_name) AT 2
  564.          ? "Qty on hand: " + STR(Goods->qty_onhand,4) AT 2
  565.          ? "Price: $  " AT 2, Goods->price PICTURE "99,999.99"
  566.       ENDIF
  567.       WAIT " .....Press spacebar to continue....."
  568.    DEACTIVATE WINDOW alert
  569. RETURN
  570.  
  571. PROCEDURE Findvend
  572.    PARAMETERS vendr
  573.    * Look up vendor name using vendor ID number in Vendor database
  574.    * when function key pressed
  575.    v_name = SPACE(30)
  576.    ACTIVATE WINDOW alert
  577.       CLEAR
  578.       v_name = LOOKUP(Vendors->vendor,TRIM(vendr),Vendors->vendor_id)
  579.       ? "----------- VENDOR CODE LOOKUP -----------"
  580.       IF .NOT. FOUND("Vendors")
  581.          DO Warnbell
  582.          ? "Vendor ID: " + TRIM(vendr)    AT 2
  583.          ? "was NOT FOUND in Vendors database." AT 2
  584.       ELSE
  585.          ? "VENDOR is: " + TRIM(v_name)   AT 2
  586.          ? "Phone:     " + Vendors->phone AT 2
  587.          ? "for ID:  "   + vendr          AT 16
  588.       ENDIF
  589.       WAIT "   Press spacebar to continue..."
  590.    DEACTIVATE WINDOW alert
  591. RETURN
  592.  
  593. PROCEDURE Kount
  594.    * Count and display number of records in database
  595.    record_num = RECNO()
  596.    ACTIVATE WINDOW alert
  597.      @ 0,0 SAY "------------- COUNT  RECORDS -------------"
  598.      @ 2,1 SAY "Counting, please wait..."
  599.      * Use count if filter is active (subset of records)
  600.      COUNT TO kount
  601.      @ 2,1 SAY "There are: " + STR (kount,6) + " records in "+ dbf
  602.      ?
  603.      WAIT " Press any key to continue..."
  604.    DEACTIVATE WINDOW alert
  605.    * Return to original record (before count)
  606.    GO record_num
  607. RETURN
  608.  
  609. PROCEDURE List_rec
  610.    * Lists records (in active index order) from current record on
  611.    * If filter is active, then subset listed
  612.    lEscape = SET("ESCAPE") = "ON"
  613.    SET ESCAPE OFF
  614.    record_num = RECNO()                 && Store current record position
  615.    GO TOP
  616.    ACTIVATE WINDOW lister
  617.       answer = " "
  618.       CLEAR
  619.       @ 0,0 SAY "------------------------- LIST RECORDS " + ;
  620.                 "-------------------------" ;
  621.             COLOR &c_red.
  622.       SCAN WHILE .NOT. answer $ "rR"
  623.          LIST OFF NEXT 10 &list_flds.
  624.          WAIT "Press spacebar to continue or R to return to " + ;
  625.               "OPTION MENU." TO answer
  626.          CLEAR
  627.       ENDSCAN
  628.    DEACTIVATE WINDOW lister
  629.    IF lEscape
  630.       SET ESCAPE OFF
  631.    ENDIF
  632.    * Return to original record (before viewing list)
  633.    GO record_num
  634. RETURN
  635.  
  636. PROCEDURE Look_msg
  637.    DO CASE                                && Show proper lookup msg in window
  638.       CASE similar = .F.                  && No similar data found
  639.          @ 1,1 SAY "Entered "+look_name+" ID does not exist in " + ;
  640.                look_dbf+" database."
  641.          ?
  642.          WAIT "No " + look_name + " ID's are similar - " + ;
  643.               "press R to return to screen." TO answer
  644.       CASE similar = .T. .AND. listcount > 0
  645.          && Similar data found and listed
  646.          WAIT "Press spacebar to continue list or " + ;
  647.               "R to return to screen." TO answer
  648.          CLEAR
  649.    ENDCASE
  650.    CLEAR
  651. RETURN
  652.  
  653. FUNCTION Lookupid
  654.    PARAMETERS l_target, look_dbf, look_name, matchchars
  655.    * During data entry or editing, validate data entered into any of the
  656.    * fields of customer ID, parts ID, vendor ID, and employee ID by checking
  657.    * for their existence in their respective databases - list any similar data
  658.    * by matching the first one or more characters (between entered data and
  659.    * database).
  660.    * Note: matchchars = number of initial matching characters for lookup lists
  661.    * Example: list will show customers whose cust_id's first two characters
  662.    * match with the entered cust_id's first two characters (matchchars = 2)
  663.    IF .NOT. SEEK(l_target,(look_dbf))     && Seek data in its respective dbf
  664.       ACTIVATE WINDOW look
  665.       DO Warnbell
  666.       answer = " "
  667.       similar = .F.
  668.       SELECT (look_dbf)                   && Use appropriate dbf for listing
  669.       GO TOP
  670.       DO WHILE .NOT. (EOF() .OR. answer $ "rR")
  671.          * Show list of records having identical initial character(s)
  672.          * in ID number
  673.          @ 0,0 SAY "-------- DATA ENTRY ERROR: " + look_name + ;
  674.                    " ID WAS INVALID -------"
  675.          @ 1,0 SAY "          This is a list of similar " + look_name + ;
  676.                    " ID's"
  677.          ?
  678.          listcount = 0
  679.          DO CASE                         && Check which database screen in use
  680.            CASE dbf = "ORDERS"
  681.               DO CASE                    && Check which field is being read
  682.                  CASE VARREAD() = "CUST_ID"
  683.                     SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",cust_id) ;
  684.                        WHILE listcount <= 4
  685.                        ? cust_id, customer           && Display a record
  686.                        listcount = listcount + 1     && Increment list counter
  687.                        similar = .T.                 && Data found and listed
  688.                     ENDSCAN
  689.                  CASE VARREAD() = "PART_ID"
  690.                     SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",part_id) ;
  691.                        WHILE listcount <= 4
  692.                        ? part_id, SUBSTR(part_name,1,21), ;
  693.                          SUBSTR(descript,1,24)
  694.                        listcount = listcount + 1     && Increment list counter
  695.                        similar = .T.                 && Data found and listed
  696.                     ENDSCAN
  697.                  CASE VARREAD() = "EMP_ID"
  698.                     SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",emp_id) ;
  699.                        WHILE listcount <= 4
  700.                        ? emp_id, lastname, firstname && Display a record
  701.                        listcount = listcount + 1     && Increment list counter
  702.                        similar = .T.                 && Data found and listed
  703.                     ENDSCAN
  704.               ENDCASE
  705.            CASE dbf = "GOODS"
  706.               SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",vendor_id) ;
  707.                  WHILE listcount <= 4
  708.                  ? vendor_id, vendor                 && Display a record
  709.                  listcount = listcount + 1           && Increment list counter
  710.                  similar = .T.                       && Data found and listed
  711.               ENDSCAN
  712.            CASE dbf = "ACCT_REC"
  713.               SCAN FOR LIKE(SUBSTR(l_target,1,matchchars)+"*",cust_id) ;
  714.                  WHILE listcount <= 4
  715.                  ? cust_id, customer                 && Display a record
  716.                  listcount = listcount + 1           && Increment list counter
  717.                  similar = .T.                       && Data found and listed
  718.               ENDSCAN
  719.          ENDCASE
  720.          DO Look_msg                                 && Show message in window
  721.       ENDDO
  722.       DEACTIVATE WINDOW look
  723.       SELECT 1                                       && Use original dbf
  724.    ENDIF
  725. RETURN not_valid = .NOT. FOUND((look_dbf))
  726.  
  727. PROCEDURE Net_err
  728.    PARAMETERS err_number, plForce
  729.    * Error procedure for networks
  730.    DO CASE
  731.       CASE err_number = 108
  732.          * File is in use by another person
  733.          IF "" <> TRIM(LKSYS(2))
  734.             message = " " + dbf + " is in use by: " + LKSYS(2)
  735.          ELSE
  736.             message = " " + dbf + " is in use by someone"
  737.          ENDIF
  738.       CASE err_number = 109
  739.          * Record is locked by another person
  740.          message = " Record is locked by: " + LKSYS(2)
  741.       CASE err_number = 110
  742.          * File must be in exclusive use for indexing/packing
  743.          message = "File should be USEd EXCLUSIVE"
  744.       CASE err_number = 372 .OR. err_number = 373
  745.          * File or record is in use by another
  746.          message = MESSAGE()
  747.       OTHERWISE
  748.          message = " Unknown error: " + MESSAGE()
  749.    ENDCASE
  750.    DO Warnbell
  751.    ACTIVATE WINDOW alert
  752.       CLEAR
  753.       ? "------------ NETWORK ERROR --------------"
  754.       ?
  755.       ? message AT 1
  756.       ? "Press spacebar to try again" AT 1
  757.       ? " - or press Esc to Quit" AT 1
  758.       SET CONSOLE OFF
  759.       SET ESCAPE OFF
  760.       WAIT
  761.       SET ESCAPE ON
  762.       SET CONSOLE ON
  763.       net_choice = LASTKEY()          && Wait for user to press a key
  764.    DEACTIVATE WINDOW alert
  765.    IF net_choice <> 27               && User did not press Esc key
  766.       * Execute command again that caused network error
  767.       IF plForce
  768.          RETURN
  769.       ELSE
  770.          RETRY
  771.       ENDIF
  772.    ELSE
  773.       DO Gen_Err WITH ;
  774.         IIF( ISBLANK( ERROR() ), err_number, ERROR() ), ;
  775.         IIF( ISBLANK( MESSAGE() ), message, MESSAGE() )
  776.    ENDIF
  777. RETURN
  778.  
  779. PROCEDURE Printout
  780.    * Print report or label
  781.    DO CASE
  782.       CASE reportype = "LISTING"
  783.          REPORT FORM &dbf.
  784.       CASE reportype = "LABELS"
  785.          LABEL FORM &dbf.
  786.       CASE reportype = "CUSTOM"
  787.          DO &rpt_name.
  788.    ENDCASE
  789.    GO record_num
  790. RETURN
  791.  
  792. PROCEDURE Prt_menu
  793.    * Display menu of print options
  794.    msg_num   = "Enter a number"
  795.    msg_logic = "Enter a Y or N"
  796.    msg_enum  = "Press spacebar for other options"
  797.    * Set up default values to print variables for reports
  798.    loffset  = 0
  799.    lmargin  = 0
  800.    rmargin  = 80
  801.    indent   = 4
  802.    plength  = 66           && 60 - HP laserjet printer
  803.    STORE 1 TO pspacing, pbpage, pcopies
  804.    pepage   = 9999
  805.    peject   = "NONE  "
  806.    STORE .F. TO pwait, pquality
  807.    ppitch   = "PICA     "
  808.    *
  809.    ACTIVATE WINDOW lister
  810.    CLEAR
  811.    @  0, 0 SAY "------------------------- PRINT MENU " + ;
  812.               "---------------------------" COLOR &c_red.
  813.    @  2, 1 SAY "Page settings:"
  814.    @  3, 1 SAY "============="
  815.    @  4, 1 SAY "Offset from left  " GET loffset ;
  816.            PICTURE "99" MESSAGE msg_num
  817.    @  5, 1 SAY "Left margin       " GET lmargin ;
  818.            PICTURE "99" MESSAGE msg_num
  819.    @  6, 1 SAY "Right margin      " GET rmargin ;
  820.            PICTURE "99" MESSAGE msg_num
  821.    @  7, 1 SAY "Indentation       " GET indent ;
  822.            PICTURE "99" MESSAGE msg_num
  823.    @  8, 1 SAY "Page length       " GET plength ;
  824.            PICTURE "99" MESSAGE msg_num
  825.    @  9, 1 SAY "Spacing           " GET pspacing ;
  826.            PICTURE "9"  RANGE 1,3 MESSAGE msg_num
  827.    @  2,26 SAY "Print settings:"
  828.    @  3,26 SAY "=============="
  829.    @  4,26 SAY "Begin printing on page  " GET pbpage ;
  830.            PICTURE "999"  MESSAGE msg_num
  831.    @  5,26 SAY "End printing on page    " GET pepage ;
  832.            PICTURE "9999" MESSAGE msg_num
  833.    @  6,26 SAY "Number of copies        " ;
  834.            GET pcopies  PICTURE "999"  MESSAGE msg_num
  835.    @  7,26 SAY "Eject paper             " GET peject ;
  836.            PICTURE "@M BEFORE,AFTER,BOTH,NONE"  MESSAGE msg_enum
  837.    @  8,26 SAY "Wait between pages      " GET pwait ;
  838.            PICTURE "Y" MESSAGE msg_logic
  839.    @  9,26 SAY "Pitch                   " GET ppitch ;
  840.            PICTURE "@M DEFAULT,PICA,ELITE,CONDENSED" MESSAGE msg_enum
  841.    @ 10,26 SAY "Quality print           " GET pquality ;
  842.            PICTURE "Y" MESSAGE msg_logic
  843.    @ 12, 1 SAY "Please enter desired settings; press Esc to cancel"
  844.    READ
  845.    DEACTIVATE WINDOW lister
  846.    IF LASTKEY() = 27                    && If Escaped presses
  847.       ll_esc = .T.
  848.    ELSE
  849.       ll_esc = .F.
  850.  
  851.       * Assign values to system variables
  852.       _ploffset = loffset
  853.       _lmargin  = lmargin
  854.       _rmargin  = rmargin
  855.       _indent   = indent
  856.       _plength  = plength
  857.       _pspacing = pspacing
  858.       _pbpage   = pbpage
  859.       _pepage   = pepage
  860.       _pcopies  = pcopies
  861.       _peject   = peject
  862.       _pwait    = pwait
  863.       IF PRINTSTATUS()
  864.         _ppitch   = ppitch
  865.       ENDIF
  866.       _pquality = pquality
  867.    ENDIF
  868.    SET COLOR TO &c_standard.
  869. RETURN
  870.  
  871. PROCEDURE Rest_env
  872.    IF TYPE( "gl_MainMenu" ) = "L"
  873.       RETURN
  874.    ENDIF
  875.  
  876.    * Restore database environment
  877.    SET COLOR TO &c_standard.
  878.    SET SCOREBOARD &scor.
  879.    SET DELIMITERS &deli.
  880.    SET HELP &hellp.
  881.    SET ESCAPE &esca.
  882.    SET DELETED &delee.
  883.    SET HEADING &head.
  884.    SET SAFETY &safe.
  885.    SET EXACT &exac.
  886.    SET BELL &bell.
  887.    SET NEAR &near.
  888.    * Reset colors to system defaults
  889.    DO Colo_rese
  890.    SET CLOCK &clock.
  891.    SET STATUS &stat.
  892.    SET TALK &talk.
  893. RETURN
  894.  
  895. PROCEDURE Sav_data
  896.    * If data is new: append record currently in memory to database.
  897.    * If edited/modified data: replace database record with memory fields.
  898.    IF NodShake( " ;   Save this data to disk?   ", ;
  899.                 9, 26, 2, 29, .F. )
  900.       IF lAddNew
  901.          APPEND BLANK
  902.          record_num = RECNO()
  903.       ELSE
  904.          record_num = RECNO()
  905.       ENDIF
  906.       * Replace database file fields with contents of memory variables
  907.       DO Repl_fld
  908.    ELSE
  909.       * Do not save data to disk, return to original record
  910.       GO record_num
  911.    ENDIF
  912.    UNLOCK
  913. RETURN
  914.  
  915. PROCEDURE Set_env
  916.    IF TYPE( "FILTERS_ON" ) = "L"
  917.       filters_on = .F.
  918.    ENDIF
  919.    IF TYPE( "gl_MainMenu" ) = "L"
  920.       RETURN                            && Setup already done by BUSINESS.PRG
  921.    ENDIF
  922.    PUBLIC talk                  && First set TALK OFF
  923.    IF SET( "TALK" ) = "ON"
  924.       SET TALK OFF
  925.       talk = "ON"
  926.    ELSE
  927.       talk = "OFF"
  928.    ENDIF
  929.  
  930.    PUBLIC c_Save
  931.    c_save = SET( "ATTRIBUTES" )
  932.  
  933.    PUBLIC c_standard, c_data, c_fields, c_popup, c_alert, c_list
  934.    PUBLIC c_red, c_blue, c_yellow, c_yelowhit, c_green, c_blink
  935.  
  936.    * Set color variables for applications
  937.    IF ISCOLOR()
  938.       * Color video card/monitor
  939.       c_standard = "W/B,BG+/R,B"
  940.       c_data     = "B/W,R/BG,B"
  941.       c_fields   = "B/BG"
  942.       c_popup    = "B/W,GR+/R"
  943.       c_alert    = "GR+/R,B/W,R/G"
  944.       c_list     = "W+/G,GR+/B,GR+/GR"
  945.       c_red      = "R/W"
  946.       c_blue     = "B/W"
  947.       c_yellow   = "GR+/B"
  948.       c_yelowhit = "GR+/W"
  949.       c_green    = "G/W"
  950.       c_blink    = "GR+*/B"
  951.    ELSE
  952.       * Monochrome video card/monitor
  953.       STORE "W+/N" TO c_standard, c_data, c_popup, c_alert, c_list
  954.       STORE "W" TO  c_red, c_blue, c_yellow, c_yelowhit, c_green, c_fields
  955.       c_blink = "W+*/N,N/W"
  956.    ENDIF
  957.    SET COLOR OF MESSAGES TO &c_blue.
  958.    SET COLOR TO &c_standard.
  959.  
  960.    * Configure working environment
  961.    * Store SET environment in case started from Control Center or dot prompt
  962.    PUBLIC scor, deli, hellp, clock, esca, delee, head, stat, safe
  963.    PUBLIC exac, bell, near
  964.    scor  = SET("SCOREBOARD")
  965.    deli  = SET("DELIMITERS")
  966.    hellp = SET("HELP")
  967.    clock = SET("CLOCK")
  968.    esca  = SET("ESCAPE")
  969.    delee = SET("DELETED")
  970.    head  = SET("HEADING")
  971.    stat  = SET("STATUS")
  972.    safe  = SET("SAFETY")
  973.    exac  = SET("EXACT")
  974.    bell  = SET("BELL")
  975.    near  = SET("NEAR")
  976.  
  977.    * Set database environment for applications
  978.    SET SCOREBOARD off
  979.    SET DELIMITERS off
  980.    SET HELP    off
  981.    SET CLOCK   off
  982.    SET ESCAPE  on && off
  983.    SET DELETED on
  984.    SET HEADING on
  985.    SET STATUS  off
  986.    SET SAFETY  off
  987.    SET TALK    off
  988.    SET EXACT   off
  989.    SET BELL    off
  990.    SET NEAR    off
  991.    PUBLIC erased, not_valid, rec_is_dup, filters_on, lookup_ok, choice
  992.    PUBLIC record_num, net_choice
  993.    PUBLIC target, look_dbf, matchchar, scanfield
  994.    * Logical variables used for status flags
  995.    STORE .F. TO  erased, not_valid, rec_is_dup, filters_on
  996.    lookup_ok = .T.
  997.    * Other variables
  998.    STORE "" TO choice,subset
  999.    STORE 0 TO record_num, net_choice
  1000.    ************************************************
  1001.    * Setup error processing if running on a network
  1002.    IF NETWORK()
  1003.       * Network programming assumes databases have been CONVERTed
  1004.       SET EXCLUSIVE off
  1005.       ON ERROR DO Net_err WITH ERROR()
  1006.       * Retry a reasonable amount of time (depends on computer)
  1007.       SET REPROCESS TO 3
  1008.    ELSE
  1009.       ON ERROR DO Gen_err WITH ERROR(), MESSAGE()
  1010.    ENDIF
  1011.  
  1012. RETURN
  1013.  
  1014. PROCEDURE Gen_Err
  1015. PARAMETERS pn_Error, pc_Message
  1016.    DO Err_Box WITH pc_Message
  1017.    gl_Error = .T.
  1018.    ON ERROR
  1019.    ON KEY LABEL F1
  1020.    ON KEY LABEL F9
  1021.    ON KEY LABEL F10
  1022. RETURN TO MASTER
  1023.  
  1024. *   IF TYPE( "gl_MainMenu" ) <> "L"
  1025. *      DO Rest_env                          && environment back.
  1026. *      ON ERROR
  1027. *      ON KEY LABEL F1
  1028. *      ON KEY LABEL F9
  1029. *      ON KEY LABEL F10
  1030. *      CLEAR ALL
  1031. *      CLOSE ALL
  1032. *      CLEAR
  1033. *      CANCEL
  1034. *   ENDIF
  1035. *RETURN TO MASTER
  1036.  
  1037. PROCEDURE Sho_look
  1038.    PARAMETERS db
  1039.    * Show lookup function keys on screen (if available for database)
  1040.    DO CASE
  1041.       CASE db = "EMPLOYEE" .OR. db = "CUST" .OR. db = "VENDORS"
  1042.          look_txt = "Press F9 to look up Area code"
  1043.       CASE db = "GOODS"
  1044.          look_txt = "Press F9 to look up Vendor name and phone"
  1045.       CASE db = "ORDERS"
  1046.          look_txt = "Press F9 to look up Cust data; F10 for Part ID data"
  1047.       CASE db = "ACCT_REC"
  1048.          look_txt = "Press F9 to look up Customer name and phone"
  1049.    ENDCASE
  1050.    @ 0,0 SAY look_txt COLOR &c_blink.
  1051.    i = INKEY(1)                                  && Blink for 1 second
  1052.    @ 0,0 SAY look_txt COLOR &c_yellow.
  1053. RETURN
  1054.  
  1055. PROCEDURE Show_msg
  1056.    PARAMETERS u_message
  1057.    _wrap = .T.
  1058.    ACTIVATE WINDOW alert
  1059.       @ 1,0 SAY u_message
  1060.       ?
  1061.       WAIT " Press spacebar to continue..."
  1062.    DEACTIVATE WINDOW alert
  1063. RETURN
  1064.  
  1065. PROCEDURE Skip_rec
  1066.    PARAMETERS skipno
  1067.    * Skip forward or backward in database by one or more records
  1068.    DO CASE
  1069.    CASE skipno = 1         && Skip to next record (in active index order)
  1070.       IF .NOT. EOF()
  1071.          SKIP
  1072.       ENDIF
  1073.    CASE skipno = -1        && Skip to previous record (in active index order)
  1074.       IF .NOT. BOF()
  1075.          SKIP -1
  1076.       ENDIF
  1077.    CASE skipno = 0
  1078.       * Skip records - to goto/view records ahead of or behind current record
  1079.       numb_2skip = 0
  1080.       ACTIVATE WINDOW alert
  1081.          @ 0,0 SAY "-------- SKIP NUMBER OF RECORDS ----------"
  1082.          @ 2,1 SAY "How many records do you want to skip?"
  1083.          @ 3,0 SAY "   (Example: 15 or -5) ?   " ;
  1084.                GET numb_2skip PICTURE "9999" ;
  1085.                MESSAGE "Enter positive no. to go forward " + ;
  1086.                        "or negative no. to go backward"
  1087.          READ
  1088.       DEACTIVATE WINDOW alert
  1089.       IF .NOT. (BOF() .AND. numb_2skip < 0) .OR. (EOF() .AND. numb_2skip > 0)
  1090.          SKIP numb_2skip
  1091.       ENDIF
  1092.    ENDCASE
  1093.  
  1094.    * Check whether record pointer hits beginning or end of file
  1095.    DO CASE
  1096.       CASE EOF()
  1097.          GO BOTTOM                  && reset record pointer if EOF
  1098.          DO Show_msg WITH " Bottom record in " + dbf + " database"
  1099.       CASE BOF()
  1100.          DO Show_msg WITH " Top record in " + dbf + " database"
  1101.    ENDCASE
  1102. RETURN
  1103.  
  1104. PROCEDURE Warnbell
  1105.    PRIVATE mwrap
  1106.    mwrap = _wrap           && Save _wrap value
  1107.    _wrap = .F.
  1108.    * Sound unique warning for errors
  1109.    SET BELL TO 880,4
  1110.    ?? CHR(7)
  1111.    SET BELL TO 1400,4
  1112.    ?? CHR(7)
  1113.    SET BELL TO 880,4
  1114.    ?? CHR(7)
  1115.    SET BELL TO
  1116.    _wrap = mwrap
  1117. RETURN
  1118.  
  1119.  
  1120. FUNCTION NodShake
  1121. PARAMETERS pc_mssg, pn_up, pn_left, pn_height, pn_max, pl_dflt_no
  1122. *---------------------------------------------------------------------------
  1123. * NAME
  1124. *   NodShake
  1125. *
  1126. * DESCRIPTION
  1127. *   Accepts a YES/NO response from user
  1128. *
  1129. * SYNOPSIS
  1130. *   DO _NodShake WITH pc_mssg, pn_up, pn_left, pn_height, pn_max, pl_dflt_no
  1131. *
  1132. * PARAMETERS
  1133. *   pc_mssg:    dialog box message
  1134. *   pn_up:      upper corrdinate of dialog box
  1135. *   pn_left:    left coordinate of dialog box
  1136. *   pn_height:  height of dialog box
  1137. *   pn_max:     maximum width of a line in message
  1138. *   pl_dflt_no: flag indicating if default pad highlighted should be "NO"
  1139. *       
  1140. * EXAMPLE
  1141. *    pl_set = _NodShake( pc_vermssg, 13, 25, 2, 28, .T. )
  1142. *       
  1143. * LIMITATIONS
  1144. *   None
  1145. *
  1146. * DEPENDENCIES
  1147. *   None
  1148. *---------------------------------------------------------------------------
  1149.  
  1150.   PRIVATE ll_ans, ll_console, ll_wrapset, ln_pspset
  1151.  
  1152.   ll_console = SET( "CONSOLE" ) = "OFF"
  1153.   SET CONSOLE ON
  1154.   ll_wrapset = _wrap
  1155.   ln_pspset = _pspacing
  1156.   _wrap = .F.
  1157.   _pspacing = 1
  1158.  
  1159.   DEFINE WINDOW NodShake DOUBLE ;
  1160.      FROM pn_up, pn_left TO pn_up + pn_height + 4, pn_left + pn_max + 1
  1161.  
  1162.   DEFINE MENU NodShake
  1163.   DEFINE PAD Yes OF NodShake PROMPT "Yes" ;
  1164.      AT pn_height + 1, (pn_max - 12) / 2;
  1165.      MESSAGE "Select option and press ENTER, or press first letter" + ;
  1166.              " of desired option"
  1167.  
  1168.   ON SELECTION PAD Yes OF NodShake DEACTIVATE MENU
  1169.   DEFINE PAD No OF NodShake PROMPT "No" ;
  1170.      AT pn_height + 1, (pn_max - 12) / 2 + 10 ;
  1171.      MESSAGE "Select option and press ENTER, or press first letter" + ;
  1172.              " of desired option"
  1173.  
  1174.   ON SELECTION PAD No OF NodShake DEACTIVATE MENU
  1175.   ACTIVATE WINDOW NodShake
  1176.   CLEAR
  1177.   ?
  1178.   @ 0, 0
  1179.   ?? pc_mssg FUNCTION ";"
  1180.  
  1181.   ON KEY LABEL Y KEYBOARD "{Alt-Y}{13}"
  1182.   ON KEY LABEL N KEYBOARD "{Alt-N}{13}"
  1183.  
  1184.   IF pl_dflt_no
  1185.     KEYBOARD "{Alt-N}"
  1186.   ENDIF
  1187.  
  1188.   ON KEY LABEL RIGHTARROW
  1189.   ON KEY LABEL LEFTARROW
  1190.  
  1191.   ACTIVATE MENU NodShake
  1192.  
  1193.   ON KEY LABEL Y
  1194.   ON KEY LABEL N
  1195.  
  1196.   IF PAD() = "YES"
  1197.     ll_ans = .T.
  1198.   ELSE
  1199.     ll_ans = .F.
  1200.   ENDIF
  1201.  
  1202.   RELEASE WINDOW NodShake
  1203.   RELEASE MENU NodShake
  1204.   _wrap = ll_wrapset
  1205.   _pspacing = ln_pspset
  1206.  
  1207.   IF ll_console
  1208.     SET CONSOLE OFF
  1209.   ENDIF
  1210.  
  1211. RETURN ll_ans
  1212. *-- EOF: NodShake( pc_mssg, pn_up, pn_left, pn_height, pn_max, pl_dflt_no )
  1213.  
  1214. PROCEDURE Err_Box
  1215. PARAMETERS pc_msg
  1216. *----------------------------------------------------------------------------
  1217. * NAME
  1218. *   Err_Box - Display an error box
  1219. *
  1220. * SYNOPSIS
  1221. *   DO Err_Box WITH <pc_msg>
  1222. *
  1223. * DESCRIPTION
  1224. *   _Err_Box will display the <pc_msg> string in a box and prompt the
  1225. *   user to press any key to continue processing.  _Err_Box will display
  1226. *   the message based on the length of <pc_msg>.
  1227. *
  1228. * PARAMETERS
  1229. *   pc_msg - the error message to display in the box.  If the length is
  1230. *            greater than 76, the trailing part is chopped off.
  1231. *
  1232. * EXAMPLE
  1233. *   DO Err_Box WITH "Incorrect window size"
  1234. *   Displays the message in a window as follows at row 9 on the screen:
  1235. *                      +------------------------------+
  1236. *                      |                              |
  1237. *                      |    Incorrect window size     |
  1238. *                      |                              |
  1239. *                      | Press any key to continue... |
  1240. *                      |                              |
  1241. *                      +------------------------------+
  1242. *   Note that the width of the window will increase to accommodate a longer
  1243. *   message string.
  1244. *
  1245. * LIMITATIONS
  1246. *   Truncates the message after 76 characters.  Assumes an 80 character
  1247. *   wide screen.  Looks best with SET CURSOR OFF.
  1248. *
  1249. *----------------------------------------------------------------------------
  1250.  
  1251.   PRIVATE lc_anykey, lc_msg, lc_msglen, lc_win, ln_press, ln_width, ll_trap,;
  1252.           ll_escape
  1253.  
  1254.   lc_anykey = [Press any key to continue...]
  1255.   ln_press  = LEN( lc_anykey )
  1256.   lc_win = WINDOW()                     && Currently activated window if any
  1257.   lc_msg = LTRIM( RTRIM( pc_msg ) )     && Trimmed message
  1258.   ln_msglen = LEN( lc_msg )             && Trimmed length of message
  1259.   ln_width = 0                          && Width of display area in window.
  1260.   ll_escape = SET("ESCAPE") = "ON"
  1261.   SET ESCAPE OFF
  1262.  
  1263.   *-- Determine the width needed for the window:
  1264.   IF ln_msglen <= ln_press
  1265.     ln_width = ln_press
  1266.   ELSE
  1267.     *-- Make sure the message fits in the window:
  1268.     IF ln_msglen > 76
  1269.       lc_msg = LEFT( lc_msg, 76 )
  1270.       ln_msglen = 76
  1271.     ENDIF
  1272.     ln_width = ln_msglen
  1273.   ENDIF
  1274.   DEFINE WINDOW _err_box FROM 9, ((76 - ln_width) + .5) / 2 ;
  1275.                 TO 15, (ln_width + 83) / 2 DOUBLE
  1276.   ln_width = ( ln_width + 2 )
  1277.  
  1278.   *-- Display the message and prompt to the window and wait for a key press
  1279.   ACTIVATE WINDOW _err_box
  1280.   @ 1, ( ln_width - ln_msglen ) / 2 SAY lc_msg
  1281.   @ 3, ( ln_width - ln_press ) / 2 SAY lc_anykey
  1282.   SET CONSOLE OFF                       && For mouse click recognition
  1283.   WAIT
  1284.   SET CONSOLE ON
  1285.  
  1286.   *-- Clean up the window display and reactivate the previous window
  1287.   RELEASE WINDOW _err_box
  1288.   IF ISBLANK( lc_win )
  1289.     ACTIVATE SCREEN
  1290.   ENDIF
  1291.  
  1292.   IF ll_escape
  1293.     SET ESCAPE ON
  1294.   ELSE
  1295.     SET ESCAPE OFF
  1296.   ENDIF
  1297.  
  1298. RETURN
  1299. *-- EOP: Err_Box WITH pc_msg
  1300.  
  1301. PROCEDURE Colo_rese
  1302. PRIVATE old_color, c_messages, c_titles, c_box, c_info, c_fields
  1303.  
  1304. old_color = c_save
  1305.  
  1306. * Set the Primary colors
  1307. SET COLOR TO
  1308. SET COLOR TO &old_color.
  1309. CLEAR
  1310.  
  1311. * Remove primary colors and start at the secondary colors
  1312. old_color = STUFF(old_color, 1, AT("&",old_color)+2, "")
  1313.  
  1314. comma = AT(",",old_color)
  1315. c_messages = LEFT(old_color, comma-1)        && Get MESSAGES color
  1316. old_color = STUFF(old_color, 1, comma, "")    && Remove MESSAGES color
  1317.  
  1318. comma = AT(",",old_color)
  1319. c_titles = LEFT(old_color, comma-1)        && Get TITLES color
  1320. old_color = STUFF(old_color, 1, comma, "")    && Remove TITLES color
  1321.  
  1322. comma = AT(",",old_color)
  1323. c_box = LEFT(old_color, comma-1)        && Get BOX color
  1324. old_color = STUFF(old_color, 1, comma, "")    && Remove BOX color
  1325.  
  1326. comma = AT(",",old_color)
  1327. c_info = LEFT(old_color, comma-1)        && Get INFORMATION color
  1328. old_color = STUFF(old_color, 1, comma, "")    && Remove INFORMATION color
  1329.  
  1330. comma = AT(",",old_color)
  1331. c_fields = old_color                && Get FIELDS color
  1332.  
  1333. SET COLOR OF MESSAGES    TO &c_messages.
  1334. SET COLOR OF TITLES      TO &c_titles.
  1335. SET COLOR OF BOX         TO &c_box.
  1336. SET COLOR OF INFORMATION TO &c_info.
  1337. SET COLOR OF FIELDS      TO &c_fields.
  1338. RETURN
  1339.  
  1340. **************************** END OF LIBRARY.PRG ******************************
  1341.  
  1342.  
  1343.  
  1344.