home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a100 / 4.ddi / FBASE.ARC / G3.PRG < prev    next >
Encoding:
Text File  |  1989-03-23  |  38.3 KB  |  1,173 lines

  1. *:*********************************************************************
  2. *:
  3. *:        Program: G3.PRG
  4. *:
  5. *:         System: G3.prg
  6. *:         Author: ACF
  7. *:      Copyright (c) 1989, Fox Software, Inc.
  8. *:  Last modified: 01/24/89     11:09
  9. *:
  10. *:  Procs & Fncts: MAIN
  11. *:               : HOUSEKEEP
  12. *:               : HOTKEY
  13. *:               : VALIDATE
  14. *:               : OPENDBF
  15. *:               : OPENNDX
  16. *:               : ROWVAL
  17. *:               : COLVAL
  18. *:               : GENVAL
  19. *:               : TRACKER
  20. *:               : HELPGRAPH
  21. *:               : PROCEED
  22. *:               : ERRHAND
  23. *:               : ERRMSG
  24. *:               : MAINMENU
  25. *:               : LIGHTBAR
  26. *:               : REDRAW
  27. *:               : GETGRF
  28. *:               : GET3MC
  29. *:               : RESTOREIT
  30. *:
  31. *:          Calls: MAIN             (procedure in G3.PRG)
  32. *:
  33. *:     Documented: 01/24/89 at 11:13               FoxDoc version 1.0
  34. *:*********************************************************************
  35. PARAMETER loadfile
  36. SET PROCEDURE TO G3
  37. DO main
  38. PROCEDURE main
  39. RELEASE ALL EXCEPT loadfile
  40. PUBLIC dbxl
  41. SET TALK OFF
  42. ***************************************************************************
  43. * Initialize smallest set of variables needed to access the error handler *
  44. ***************************************************************************
  45. ON ERROR DO errhand
  46. STORE SPACE(80) TO errmsg
  47. STORE 1 TO oldfld
  48. dbxl = IIF(UPPER(LEFT(VERSION(),4)) = 'DBXL', .T., .F.)
  49. if dbxl
  50.    set oops to ''
  51. endif
  52.  
  53. SET CONFIRM OFF
  54. SET BELL OFF
  55. SET STATUS OFF
  56. SET SCOREBOARD OFF
  57. SET ESCAPE OFF
  58. SET TYPEAHEAD TO 128
  59. SET COLOR TO N/BG, GR+, BG
  60. CLEAR
  61. *************************
  62. * Initialize GET fields *
  63. *************************
  64. STORE IIF(LEN(TRIM(DBF())) > 50, DBF(), LEFT(DBF()+SPACE(50),50)) TO setup1, oldval1
  65. IF LEN(TRIM(m->setup1)) > 0
  66.    SET ORDER TO 0     && Can't tell which is master, so deactivate all
  67. ENDIF
  68. STORE SPACE(50) TO setup2, oldval2
  69. STORE .F. TO setup3, oldval3
  70. STORE SPACE(40) TO setup4, setup5, setup6, oldval4, oldval5, oldval6
  71. I = 7
  72. DO WHILE m->i < 30
  73.    s = LTRIM(STR(m->i))
  74.    STORE SPACE(40) TO setup&s, oldval&s
  75.    I = m->i + 1
  76. ENDDO
  77. ******************************
  78. * Initialize other variables *
  79. ******************************
  80. STORE 1 TO themenu
  81. STORE 0 TO macstat, KEY
  82. STORE SPACE(50) TO filename, macro
  83. STORE TRIM(m->loadfile) TO loadfile
  84. STORE CHR(16) TO arrow
  85. **************************
  86. * Main menu control loop *
  87. **************************
  88. DO WHILE m->themenu < 7
  89.    IF LEN(m->loadfile) = 0
  90.       DO mainmenu
  91.       SET FUNCTION 'F10' TO IIF(m->themenu = 1, CHR(3), CHR(27))
  92.    ELSE
  93.       IF m->themenu = 1
  94.          filename = LEFT(m->loadfile+SPACE(21),21)
  95.          command = ''
  96.          DO getgrf
  97.          DO restoreit WITH command
  98.          themenu = IIF(LEN(TRIM(m->filename)) > 0, 3, 6)
  99.       ELSE
  100.          themenu = 6
  101.       ENDIF
  102.    ENDIF
  103.    
  104.    @ 0,0
  105.    DO CASE
  106.    CASE m->themenu = 1
  107.       *************************************************************
  108.       * Collect information for designing the graph               *
  109.       *************************************************************
  110.       IF LEN(TRIM(m->filename)) = 0
  111.          I = 1
  112.          DO WHILE m->i < 30
  113.             s = LTRIM(STR(m->i))
  114.             oldval&s = setup&s
  115.             I = m->i + 1
  116.          ENDDO
  117.       ENDIF
  118.       line23 = "           Position to fields - " + ;
  119.          CHR(24)+CHR(25)+CHR(26)+CHR(27) + ".  Help - F1.  Main Menu - F10."
  120.       rc = '02170317041702550355045506170655075511091145120912451309134514091445'+;
  121.          '150915451609164517091745180918451909194520092045'
  122.       DO redraw WITH 30, 24                 && fldno, lineno
  123.       STORE 1 TO fldnum, oldfld
  124.       DO WHILE m->fldnum > 0 .AND. m->fldnum < 30
  125.          s = LTRIM(STR(m->fldnum))
  126.          fcode = '@' + IIF(fldnum < 10, IIF(fldnum = 3, ' y', 's20'), 's30')
  127.          @ VAL(SUBSTR(rc,m->fldnum*4-3,2)),VAL(SUBSTR(rc,m->fldnum*4-1,2)) GET setup&s PICTURE fcode
  128.          SET CONFIRM ON
  129.          READ
  130.          SET CONFIRM OFF
  131.          DO validate
  132.       ENDDO
  133.    CASE m->themenu = 2
  134.       ************************************
  135.       * All about the FoxGraph interface *
  136.       ************************************
  137.       CLEAR
  138.       DO helpgraph
  139.    CASE m->themenu = 3
  140.       *************************************************************
  141.       * Call FoxGraph with name of file containing graph info     *
  142.       *************************************************************
  143.       ********************************
  144.       * See if they want to continue *
  145.       ********************************
  146.       IF LEN(m->loadfile) = 0
  147.          errmsg = "Proceed with graph generation"
  148.          IF m->macstat = 1
  149.             errmsg = m->errmsg + " - Macro Active"
  150.          ELSE
  151.             IF m->macstat = 2
  152.                errmsg = m->errmsg + " - Recording Macro"
  153.             ENDIF
  154.          ENDIF
  155.          DO errmsg
  156.          DO proceed with 1
  157.          IF m->key = -9 .OR. m->key = 27
  158.             LOOP
  159.          ENDIF
  160.       ENDIF
  161.       errmsg = "Building data files - Please wait"
  162.       DO errmsg
  163.       **************************************************
  164.       * If SETUP is not complete, just invoke FoxGraph *
  165.       **************************************************
  166.       IF LEN(TRIM(setup7)) = 0
  167.          COMMAND = 'foxgraph /q'
  168.          IF LEN(TRIM(m->setup6)) <> 0
  169.             COMMAND = m->command + ' ' + TRIM(m->setup6)
  170.          ENDIF
  171.          IF m->macstat <> 0
  172.             COMMAND = m->command + IIF(m->macstat=1,' /r:',' /w:')+TRIM(m->macro)
  173.             macstat = 0
  174.          ENDIF
  175.          RUN foxswap &command
  176.          SET COLOR TO N/BG, GR+, BG
  177.          CLEAR
  178.          LOOP
  179.       ENDIF
  180.       *******************************************************
  181.       * Create a temporary data file to be used by FoxGraph *
  182.       *******************************************************
  183.       STORE "3dDATA\FOXGRAPH.DAT" TO graphfile
  184.       page = 1
  185.       SET CONSOLE OFF
  186.       SET ALTERNATE TO &graphfile
  187.       **********************************************
  188.       * Write general graphing information to file *
  189.       **********************************************
  190.       SET ALTERNATE ON
  191.       ?? '"%%Upper_Top_Left: 11, 2, 1%%"'
  192.       ? '"%%Title: 8, 1%%"'
  193.       ? '"%%Subtitle: 8, 2%%"'
  194.       ? '"%%Row_Title: 9, 1%%"'
  195.       ? '"%%Column_Title: 9, 2%%"'
  196.       ? '"%%Row_Headers: 11, 1%%"'
  197.       ? '"%%Column_Headers: 10, 2%%"'
  198.       ? '"'+TRIM(m->setup4)+'" '+'"'+TRIM(m->setup5)+'"'
  199.       ? '"'+TRIM(m->setup8)+'" '+'"'+TRIM(m->setup9)+'"'
  200.       Lines = 9
  201.       counter = 28
  202.       DO WHILE m->counter > 9    && Find out how many columns are used
  203.          s = LTRIM(STR(m->counter))
  204.          IF LEN(TRIM(setup&s)) > 0
  205.             EXIT
  206.          ENDIF
  207.          counter = m->counter - 2
  208.       ENDDO
  209.       COMMAND = ","          && Print column headers
  210.       I = 11
  211.       DO WHILE m->i <= m->counter + 1
  212.          s = LTRIM(STR(m->i))
  213.          COMMAND = m->command + [ "] + TRIM(setup&s) + ["]
  214.          I = m->i + 2
  215.       ENDDO
  216.       ? m->command
  217.       Lines = m->lines + 1
  218.       ********************
  219.       * Process the data *
  220.       ********************
  221.       errmsg = 'Only the first 246 rows of data will be graphed'
  222.       IF LEN(DBF()) <> 0
  223.          dbfopen = .T.
  224.          GO TOP
  225.       ELSE
  226.          dbfopen = .F.
  227.       ENDIF
  228.       IF m->setup3 .AND. dbfopen
  229.          I = 10
  230.          DO WHILE m->i <= m->counter
  231.             s = LTRIM(STR(m->i))
  232.             sum&s = 0
  233.             I = m->i + 2
  234.          ENDDO
  235.          sum7 = &setup7        && Note current key value
  236.          DO WHILE .T.
  237.             IF sum7 <> &setup7 .OR. EOF()  && Group change??
  238.                I = 10          && Store group summary info in file
  239.                COMMAND = ["]+TRIM(sum7)+["]
  240.                DO WHILE m->i <= m->counter
  241.                   s = LTRIM(STR(m->i))
  242.                   COMMAND = m->command + "," + STR(sum&s,14,2)
  243.                   sum&s = 0
  244.                   I = m->i + 2
  245.                ENDDO
  246.                ? m->command
  247.                Lines = m->lines + 1
  248.                sum7 = &setup7      && First element of value
  249.                IF EOF()
  250.                   EXIT                  && Finished last group
  251.                ENDIF
  252.                IF m->lines > 255
  253.                   SET ALTERNATE OFF
  254.                   SET CONSOLE ON
  255.                   DO errmsg
  256.                   DO proceed WITH 1
  257.                   SET CONSOLE OFF
  258.                   SET ALTERNATE ON
  259.                   EXIT
  260.                ENDIF
  261.             ENDIF
  262.             I = 10
  263.             DO WHILE m->i <= m->counter && For each column, add to summary
  264.                s = LTRIM(STR(m->i))
  265.                thevalue = setup&s
  266.                IF LEN(TRIM(m->thevalue)) <> 0
  267.                   IF thevalue = '+'
  268.                      sum&s = sum&s + 1
  269.                   ELSE
  270.                      sum&s = sum&s + &thevalue
  271.                   ENDIF
  272.                ENDIF
  273.                I = m->i + 2
  274.             ENDDO
  275.             SKIP
  276.          ENDDO && WHILE .T.
  277.       ELSE
  278.          DO WHILE .NOT. EOF() 
  279.             COMMAND = ["] + TRIM(&setup7) + ["]
  280.             I = 10
  281.             DO WHILE m->i <= m->counter
  282.                s = LTRIM(STR(m->i))
  283.                thevalue = setup&s
  284.                IF LEN(TRIM(thevalue)) <> 0
  285.                   IF thevalue = '+'
  286.                      COMMAND = m->command + "," + STR(1,14,2)
  287.                   ELSE
  288.                      COMMAND = m->command + "," + STR(&thevalue,14,2)
  289.                   ENDIF
  290.                ENDIF
  291.                I = m->i + 2
  292.             ENDDO
  293.             ? m->command
  294.             Lines = m->lines + 1
  295.             IF .NOT. dbfopen
  296.                EXIT
  297.             ENDIF
  298.             IF m->lines > 255
  299.                SET ALTERNATE OFF
  300.                SET CONSOLE ON
  301.                DO errmsg
  302.                DO proceed WITH 1
  303.                SET CONSOLE OFF
  304.                SET ALTERNATE ON
  305.                EXIT
  306.             ENDIF
  307.             SKIP
  308.          ENDDO
  309.       ENDIF && IF m->sumonly
  310.       ******************************************************
  311.       * Mark the end of the data, close file, and graph it *
  312.       ******************************************************
  313.       ? '"%%Lower_Bottom_Right: '+STR(m->lines);
  314.          +','+STR((m->counter-6)/2)+','+STR(m->page)+'%%"' 
  315.       CLOSE ALTERNATE
  316.       SET CONSOLE ON
  317.       COMMAND = 'foxgraph '
  318.       IF LEN(TRIM(m->setup6)) <> 0
  319.          COMMAND = m->command + ' ' + TRIM(m->setup6)
  320.       ENDIF
  321.       IF m->macstat <> 0
  322.          COMMAND = m->command + IIF(m->macstat=1,' /r:',' /w:')+TRIM(m->macro)
  323.       ENDIF
  324.       COMMAND = m->command + ' /q /d:' + graphfile
  325.       IF m->key <> -9 .AND. m->key <> 27
  326.          RUN foxswap &command
  327.       ENDIF
  328.       SET COLOR TO N/BG, GR+, BG
  329.       CLEAR
  330.       IF m->macstat = 2                 && Turn off recording mode
  331.          macstat = 0
  332.       ENDIF
  333.    CASE m->themenu = 4
  334.       ****************************************
  335.       * Load and Save graph definition files *
  336.       ****************************************
  337.       @ 0,0 CLEAR TO 23,79
  338.       SET CONFIRM ON
  339.       theitem = 1
  340.       lbm1 = 'Load Definition' + SPACE(24)
  341.       lbm2 = 'Save Definition' + SPACE(24)
  342.       lbrc = '02310331'
  343.       lbstring = 'LB'
  344.       lbprompt = .F.
  345.       @ 1,30 TO 4,70 DOUBLE
  346.       DO WHILE .T.
  347.          line23 =  "            Position to options - " + CHR(24)+CHR(25) + ;
  348.             ".  Select - " + CHR(17)+CHR(217) +".  Main Menu - F10.   "
  349.          @ 23,0 SAY m->line23
  350.          DO lightbar WITH theitem
  351.          IF m->theitem = 1             && Load a graph definition
  352.             DO WHILE .T.
  353.                COMMAND = ''
  354.                DO getgrf
  355.                IF LEN(m->command) > 0          && Filename was entered
  356.                   DO restoreit WITH COMMAND
  357.                   IF LEN(TRIM(m->filename)) <> 0       && no errors
  358.                      EXIT
  359.                   ELSE
  360.                      IF LEN(m->loadfile) <> 0
  361.                         EXIT
  362.                      ENDIF
  363.                   ENDIF
  364.                ELSE
  365.                   EXIT                                 && Escape pressed
  366.                ENDIF
  367.             ENDDO
  368.          ELSE
  369.             IF m->theitem = 2          && Save a graph definition
  370.                COMMAND = ''
  371.                DO getgrf
  372.                IF LEN(m->command) > 0
  373.                   @ 24,0           && Be prepared for overwrite mssg
  374.                   @ 23,0
  375.                   STORE TRIM(m->macro) TO oldval30
  376.                   STORE m->macstat TO oldval31
  377.                   SAVE TO &command ALL LIKE oldval*
  378.                   @ 22,0           && Erase Please wait mssg
  379.                   @ 24,0           && Erase overwrite mssg
  380.                ENDIF
  381.             ELSE
  382.                EXIT
  383.             ENDIF
  384.          ENDIF
  385.       ENDDO
  386.       SET CONFIRM OFF
  387.       CLEAR
  388.    CASE m->themenu = 5
  389.       ****************************************
  390.       * Use or record keyboard macro files *
  391.       ****************************************
  392.       @ 0,0 CLEAR TO 23,79
  393.       SET CONFIRM ON
  394.       theitem = 1
  395.       lbrc = '02310331'
  396.       lbprompt = .F.
  397.       @ 1,30 TO 4,70 DOUBLE
  398.       DO WHILE .T.
  399.          lbm1 = IIF(m->macstat <> 1, 'Activate Macro'+SPACE(25), ;
  400.             LEFT('Deactivate Macro ==> '+m->macro+SPACE(19), 39))
  401.          lbm2 = IIF(m->macstat <> 2, 'Start Recording'+SPACE(24), ;
  402.             LEFT('Stop Recording ==> '+m->macro+SPACE(21), 39))
  403.          lbstring = LEFT(lbm1,1)+LEFT(lbm2,1)
  404.          line23 = "            Position to options - " + CHR(24)+CHR(25) + ;
  405.             ".  Select - " + CHR(17)+CHR(217) +".  Main Menu - F10.     "
  406.          @ 23,0 SAY m->line23
  407.          errmsg = IIF(m->macstat=1, 'Macro active - ' + m->macro, ;
  408.             IIF(m->macstat=2, 'Macro recording mode on - ' + m->macro, ;
  409.             'Macro inactive'))
  410.          DO errmsg
  411.          DO lightbar WITH theitem
  412.          line23 = "         Enter file name - Finish with " + ;
  413.             CHR(17)+CHR(217) + ".  Help - F1.  Abort Entry - Esc."
  414.          @ 23,0 SAY m->line23
  415.          IF m->theitem = 1             && Activate/Deactivate a macro
  416.             IF m->macstat = 1
  417.                macstat = 0
  418.             ELSE
  419.                @ 22,0
  420.                DO WHILE .T.
  421.                   COMMAND = ''
  422.                   DO get3mc
  423.                   IF LEN(m->command) > 0
  424.                      IF FILE(m->command)         && Macro exists
  425.                         STORE 1 TO macstat
  426.                         EXIT
  427.                      ELSE
  428.                         errmsg = m->command+' does not exist'
  429.                         DO errmsg
  430.                      ENDIF
  431.                   ELSE
  432.                      EXIT                                 && Escape pressed
  433.                   ENDIF
  434.                ENDDO
  435.             ENDIF
  436.          ELSE
  437.             IF m->theitem = 2          && Start/Stop recording a macro
  438.                IF m->macstat = 2
  439.                   macstat = 0
  440.                ELSE
  441.                   @ 22,0
  442.                   COMMAND = ''
  443.                   DO get3mc
  444.                   IF LEN(m->command) > 0
  445.                      macstat = 2
  446.                      IF FILE(m->command)         && Macro exists
  447.                         @ 24,0
  448.                         @ 23,78
  449.                         WAIT m->command+' already exists, overwrite it (Y/N)? ' TO I
  450.                         IF UPPER(m->i) <> 'Y'
  451.                            macstat = 0
  452.                         ENDIF
  453.                         @ 24,0
  454.                      ENDIF
  455.                   ENDIF
  456.                ENDIF
  457.             ELSE
  458.                EXIT
  459.             ENDIF
  460.          ENDIF
  461.       ENDDO
  462.       SET CONFIRM OFF
  463.       CLEAR
  464.    CASE m->themenu = 6
  465.       *************************************************************
  466.       * Bye-bye                                                   *
  467.       *************************************************************
  468.       IF LEN(m->loadfile) <> 0
  469.          EXIT
  470.       ELSE
  471.          DO proceed with 3
  472.          IF m->key <> -9 .AND. m->key <> 27
  473.             EXIT
  474.          ENDIF
  475.       ENDIF
  476.    ENDCASE
  477. ENDDO
  478. DO housekeep
  479. SET CONSOLE OFF
  480. CANCEL
  481. RETURN
  482. *************************************************************
  483. * Housekeeping: Restore previous settings                   *
  484. *************************************************************
  485. PROCEDURE housekeep
  486. ON KEY
  487. ON ERROR
  488. SET ESCAPE ON
  489. SET SCOREBOARD ON
  490. SET STATUS OFF
  491. SET BELL ON
  492. SET CONFIRM OFF
  493. SET COLOR TO
  494. IF LEN(m->loadfile) = 0
  495.    SET FUNCTION 'F10' TO 'edit;'
  496. ENDIF
  497. CLEAR
  498. SET TALK ON
  499. RETURN
  500. *********************************************************
  501. * HOTKEY - provide assistance during the READ command   *
  502. *********************************************************
  503. PROCEDURE hotkey
  504. @22,0                           && Clear message line
  505. DO CASE
  506. CASE m->fldnum = 1        && Database field
  507.    CLEAR
  508.    @0,0
  509.    DISPLAY Files LIKE *.dbf
  510.    DO proceed with 5
  511.    DO redraw WITH 30, 24
  512. CASE m->fldnum = 2        && Index field
  513.    CLEAR
  514.    @ 0,0
  515.    DISPLAY Files LIKE *.ndx
  516.    DO proceed WITH 6
  517.    DO redraw WITH 30, 24
  518. CASE m->fldnum = 7 .OR. (m->fldnum > 9 .AND. MOD(m->fldnum,2) = 0)  && Row and Column values
  519.    STORE 1 TO k, J, counter
  520.    lbrc = '0000001600320048006401000116013201480164' + ;
  521.       '0200021602320248026403000316033203480364' + ;
  522.       '0400041604320448046405000516053205480564' + ;
  523.       '0600061606320648066407000716073207480764'
  524.    lbrc = lbrc + '0800081608320848086409000916093209480964' + ;
  525.       '1000101620321048106411001116113211481164' + ;
  526.       '120012161232'
  527.    STORE '' TO lbstring
  528.    lbprompt = .F.
  529.    IF m->setup3                           && Summary only
  530.       IF m->fldnum <> 7
  531.          lbm1 = '+ - Count'
  532.          k = m->k + 1
  533.       ENDIF
  534.    ENDIF
  535.    limit = 1
  536.    DO WHILE LEN(LTRIM(FIELD(m->limit))) <> 0
  537.       limit = m->limit + 1
  538.    ENDDO
  539.    limit = m->limit - 1
  540.    DO WHILE m->counter <= m->limit .AND. m->k < 64  && Initialize popup menu
  541.       s = LTRIM(STR(m->k))
  542.       lbm&s = FIELD(m->counter)
  543.       counter = m->counter + 1
  544.       IF TYPE(lbm&s) = 'N' .OR. fldnum = 7
  545.          lbstring = m->lbstring + LEFT(lbm&s,1)
  546.          k = m->k + 1            && Skip non-numerics for columns
  547.       ENDIF
  548.    ENDDO
  549.    counter = 1
  550.    k = m->k - 1
  551.    errmsg = IIF(fldnum = 7,;
  552.       "Select an expression for the row definition",;
  553.       "Select a numeric expression for the column definition")
  554.    DO errmsg
  555.    IF m->k > 0                      && Accept user selection
  556.       @ 0,0 CLEAR TO 21,79
  557.       @ 23,0 say "         Position to options - " + CHR(27)+CHR(26) + ;
  558.       ".  Select - " + CHR(17)+CHR(217) +".  Abort Selection - Esc.     "
  559.       DO lightbar WITH J
  560.       s = LTRIM(STR(m->fldnum))
  561.       lbstring = LTRIM(STR(m->j))
  562.       setup&s = LEFT(lbm&lbstring+SPACE(40),40)
  563.       DO redraw WITH 30, 24
  564.    ENDIF
  565. CASE m->fldnum = 3
  566.    errmsg = 'Summarize data by groups (Y) or graph for all records (N)'
  567.    DO errmsg
  568. CASE m->fldnum = 4
  569.    errmsg = 'Enter title to appear at the top of the graph display'
  570.    DO errmsg
  571. CASE m->fldnum = 5
  572.    errmsg = 'Enter subtitle to appear at the bottom of the graph display'
  573.    DO errmsg
  574. CASE m->fldnum = 8 .OR. (m->fldnum > 8 .AND. MOD(m->fldnum,2) = 1)
  575.    IF fldnum = 8
  576.       errmsg = 'Enter row title to appear along the row axis of the graph'
  577.    ELSE
  578.       IF fldnum = 9
  579.          errmsg = 'Enter column title to appear along the column axis of the graph'
  580.       ELSE
  581.          errmsg = 'Enter column header to appear below the corresponding column'
  582.       ENDIF
  583.    ENDIF
  584.    DO errmsg
  585. CASE m->fldnum = 6
  586.    CLEAR
  587.    @ 0,0
  588.    DISPLAY Files LIKE 3dlooks\*.3gr
  589.    DO proceed WITH 7
  590.    DO redraw WITH 30,24
  591. ENDCASE
  592. RETURN
  593. ****************************************************
  594. * VALIDATE - Controlling routine to validate READs *
  595. ****************************************************
  596. PROCEDURE validate
  597. DO CASE
  598. CASE m->fldnum = 1
  599.    DO opendbf
  600. CASE m->fldnum = 2
  601.    DO openndx
  602. CASE m->fldnum = 7
  603.    DO rowval
  604. CASE m->fldnum > 9 .AND. MOD(m->fldnum,2) = 0
  605.    DO colval
  606. OTHERWISE
  607.    DO genval
  608. ENDCASE
  609. RETURN
  610. *********************************************************
  611. * OPENDBF - open the selected dbf                       *
  612. *********************************************************
  613. PROCEDURE opendbf
  614. @ 22,0
  615. DO tracker
  616. IF m->fldnum = 0
  617.    RETURN
  618. ENDIF
  619. IF m->oldval1 <> m->setup1    && value changed
  620.    STORE SPACE(50) TO setup2, oldval2    && Clear index field
  621.    USE &setup1
  622.    IF LEN(DBF()) = 0 .AND. LEN(TRIM(m->setup1))<>0  && dbf not successfully opened
  623.       fldnum = 1
  624.       RETURN
  625.    ENDIF
  626.    oldval1 = m->setup1
  627. ENDIF
  628. IF LEN(DBF()) = 0 .AND. m->fldnum = 2    && If no dbf, then no index
  629.    fldnum = 4                            && ... and no summary
  630. ENDIF
  631. IF m->fldnum <> 2
  632.    DO redraw WITH 7, 4
  633. ENDIF
  634. RETURN
  635. *************************************************************
  636. * OPENNDX - open the selected index                         *
  637. *************************************************************
  638. PROCEDURE openndx
  639. @ 22,0
  640. DO tracker
  641. IF m->fldnum = 0
  642.    RETURN
  643. ENDIF
  644. IF m->oldval2 <> m->setup2            && value changed
  645.    oldfld = 2
  646.    SET INDEX TO &setup2               && Try opening index
  647.    IF LEN(TRIM(m->setup2)) <> 0       && Index name entered
  648.       IF m->fldnum = 2
  649.          RETURN
  650.       ENDIF
  651.       GO BOTT                          && Test out the index
  652.       SKIP
  653.       IF .NOT. EOF()
  654.          fldnum = 2
  655.          RETURN
  656.       ENDIF
  657.       ndxopen = .T.
  658.    ELSE                             && index name erased
  659.       ndxopen = .F.
  660.    ENDIF
  661.    oldval2 = m->setup2
  662. *   STORE SPACE(40) TO setup7, oldval7
  663.    STORE ndxopen TO setup3, oldval3
  664.    IF m->fldnum <> 3
  665.       DO redraw WITH 7, 4
  666.    ENDIF
  667. ENDIF
  668. RETURN 
  669. ***************************************************************
  670. * ROWVAL - make sure that the row value is a valid expression *
  671. ***************************************************************
  672. PROCEDURE  rowval
  673. @ 22,0
  674. IF m->oldval7 <> m->setup7
  675.    IF TYPE(m->setup7) <> 'C' .AND. LEN(TRIM(m->setup7)) <> 0
  676.       errmsg = "Row definition must be a character expression"      
  677.       DO errmsg
  678.       RETURN 
  679.    ENDIF
  680.    oldval7 = m->setup7
  681. ENDIF
  682. DO tracker
  683. RETURN 
  684. *************************************************************
  685. * COLVAL - check to see that column values are valid        *
  686. *************************************************************
  687. PROCEDURE colval
  688. @ 22,0
  689. s = LTRIM(STR(m->fldnum))
  690. IF oldval&s <> setup&s
  691.    IF TYPE(setup&s) <> 'N' .AND. setup&s <> '+' .AND. ;
  692.          LEN(TRIM(setup&s)) > 0
  693.       errmsg = 'Column definitions must be valid numeric expressions'
  694.       DO errmsg
  695.       RETURN 
  696.    ENDIF
  697.    oldval&s = setup&s
  698. ENDIF
  699. DO tracker
  700. RETURN 
  701. *************************************************************
  702. * GENVAL - general validation routine                       *
  703. *************************************************************
  704. PROCEDURE genval
  705. @ 22,0
  706. s = LTRIM(STR(m->fldnum))
  707. oldval&s = setup&s
  708. oldfld = m->fldnum
  709. DO tracker
  710. IF LEN(DBF()) = 0 .AND. m->fldnum = 3 .AND. m->oldfld = 4
  711.    fldnum = 1
  712. ENDIF
  713. RETURN 
  714. *************************************************************
  715. * TRACKER - track which GET field we are on currently       *
  716. *************************************************************
  717. PROCEDURE tracker
  718. KEY = MOD(READKEY(),256)
  719. DO CASE
  720. CASE KEY = 15 .OR. KEY = 1 .OR. KEY = 3 .OR. KEY = 5 && Forward
  721.    fldnum = m->fldnum + 1
  722. CASE KEY = 0 .OR. KEY = 2 .OR. KEY = 4             && Backward
  723.    fldnum = m->fldnum - 1
  724. CASE KEY = 12                                  && Escape
  725.    fldnum = 0
  726. CASE KEY = 14 .OR. KEY = 6 .OR. KEY = 7            && Save
  727.    fldnum = 30
  728. CASE KEY = 36                                  && Help
  729.    DO hotkey
  730. ENDCASE
  731. RETURN
  732. ************************************************
  733. * HELPGRAPH - Provide general HELP information *
  734. ************************************************
  735. PROCEDURE helpgraph
  736. TEXT
  737.  Use the SETUP menu option to specify the data you want to include in your 
  738.  graph.  Graph data may be derived from database files or they may be values 
  739.  that you enter directly.  When you are defining your graph, it is easiest to
  740.  think of your graph as a two-dimensional grid with rows and columns. 
  741.  
  742.  Example: Using an employee file, salary and bonus amounts can be graphed for 
  743.  each employee.  The following SETUP definitions are fields in the database:
  744.  
  745.                      ROW DEFINITION      = LASTNAME
  746.                      COLUMN 1 DEFINITION = SALARY
  747.                      COLUMN 2 DEFINITION = BONUS
  748.  
  749.                       ┌────────────┬────────────┐
  750.     ┌──────> Brown    │   25,000   │    3,000   <───── COLUMN VALUE
  751.     │                 ├────────────┼────────────┤
  752.    ROW       Johnson  │   36,000   │    4,500   │
  753.   VALUE               ├────────────┼────────────┤
  754.              Young    │   18,000   │    2,000   │
  755.                       └────────────┴────────────┘
  756.                      │Annual Salary   1988 Bonus │
  757.                      └─────────────┬─────────────┘
  758.                             COLUMN HEADERS
  759. ENDTEXT
  760. DO proceed WITH 2
  761. IF m->key = -9 .OR. m->key = 27            && Escape
  762.    RETURN
  763. ENDIF
  764. TEXT
  765.  The row values are determined by the ROW DEFINITION. If your graph is based on
  766.  database records, the row definition should be a character expression contain-
  767.  ing one or more database fields. When you display summary information, the row
  768.  definition should be the key upon which the file is either sorted or currently
  769.  indexed. In this case, there will be one row for each distinct key value.  If
  770.  you are not summarizing the data, there will be one row for each record in the
  771.  primary database.
  772.  
  773.  The columns are determined by the COLUMN DEFINITIONs.  These definitions must 
  774.  be numeric expressions.  Every row will contain a value for each column that
  775.  you define.  Keep in mind, column definitions may include numeric operations
  776.  for scaling or other manipulation of data values.
  777.  
  778.  When you display summary information on a database, the special expression '+'
  779.  is available in addition to normally valid numeric expressions.  The '+' ex-
  780.  pression indicates that the number of records within each key group is to be
  781.  displayed for each row value.  For example, if you had a customer database,
  782.  you could sort it by state (row definition) and use the '+' expression (column
  783.  1 definition) to graph the number of customers you have in each state. 
  784.  
  785.  Alternately, you could use the TOTAL command to build a summary database 
  786.  before performing the SETUP. In this case, you would not request SUMMARY ONLY 
  787.  and your graph would have a row for each record in the TOTALed database.
  788. ENDTEXT
  789. DO proceed WITH 2
  790. IF m->key = -9 .OR. m->key = 27            && Escape
  791.    RETURN
  792. ENDIF
  793. TEXT
  794.  As you are entering information in the SETUP screen, you may press F1 at any 
  795.  point to get specific HELP information.  If you press F1 while you are on the 
  796.  ROW DEFINITION or COLUMNs DEFINITION fields, a popup menu will be displayed 
  797.  which contains items appropriate to that field.  You may select these items by
  798.  positioning with the arrow keys and selecting with the Return key.
  799.  
  800.  When you have completed the SETUP, choose the DRAW menu option.  At this point
  801.  the data is summarized (if indicated) and written to a temporary data file for
  802.  use by FoxGraph.  FoxGraph is then invoked and an initial graph is displayed 
  803.  based on your SETUP information.  You may then choose other formats for the 
  804.  graph and/or select different ranges of data to display in the graph. Once you
  805.  are satisfied with the appearance of the graph you may save it and print it.
  806.  
  807.  You may also wish to save the SETUP definition so that you can generate the 
  808.  graph again more conveniently.  Use the FILES menu option to save and load 
  809.  graph definitions.
  810.  
  811.  Sometimes it is desirable to define a canned procedure for performing a set of
  812.  tasks within the graphing program itself. With the MACROS menu option, you may
  813.  either indicate that you wish to record a macro (sequence of keystrokes) while
  814.  you are running FoxGraph or that you want to activate an existing macro to 
  815.  control a FoxGraph session.
  816. ENDTEXT
  817. DO proceed WITH 2
  818. RETURN
  819. *******************************************************
  820. * PROCEED - Display message at bottom of help screen *
  821. *******************************************************
  822. PROCEDURE proceed
  823. PARAMETER mnum
  824. @ 24,0
  825. SET COLOR TO GR+/N
  826. DO CASE
  827. CASE mnum = 1          && Proceed with graph generation?
  828.    @ 24,0 SAY '                   F10 - Main Menu.  Any other key - Proceed.';
  829.       + SPACE(19)
  830. CASE mnum = 2          && Proceed with help screens?
  831.    @ 24,0 SAY '                   F10 - Main Menu.  Any other key - Continue.';
  832.       + SPACE(18)
  833. CASE mnum = 3          && Proceed with exiting?
  834.    @ 24,0 SAY '                     F10 - Main Menu.  Any other key - Exit.';
  835.       + SPACE(20)
  836. CASE mnum = 4          && Proceed with exiting?
  837.    @ 24,0 SAY '                             Press any key to exit.';
  838.       + SPACE(29)
  839. CASE mnum = 5
  840.    @ 24,0 SAY "          Directory listing of databases - Press any key to continue.";
  841.       + SPACE(10)
  842. CASE mnum = 6
  843.    @ 24,0 SAY "           Directory listing of indexes - Press any key to continue.";
  844.       + SPACE(11)
  845. CASE mnum = 7
  846.    @ 24,0 SAY "         Directory listing of graph styles - Press any key to continue.";
  847.       + SPACE(9)
  848. CASE mnum = 8
  849.    @ 24,0 SAY "       Directory listing of setup definitions - Press any key to continue.";
  850.       + SPACE(6)
  851. CASE mnum = 9
  852.    @ 24,0 SAY "        Directory listing of keyboard macros - Press any key to continue.";
  853.       + SPACE(7)
  854. ENDCASE
  855. SET COLOR TO N/BG
  856. IF m->mnum = 1 .OR. m->mnum = 4
  857.    ?? CHR(7)
  858. ENDIF
  859. KEY = 0
  860. DO WHILE m->key = 0
  861.    KEY = INKEY()
  862. ENDDO
  863. CLEAR
  864. RETURN
  865. *************************************************************
  866. * ERRHAND - General error handling  routine                 *
  867. *************************************************************
  868. PROCEDURE errhand
  869. @ 22,0
  870. errmsg = MESSAGE()
  871. DO CASE
  872. CASE ERROR() = 6 .OR. ERROR() = 21 .OR. ERROR() = 43 .OR. ERROR() = 1310 ;
  873.                  .OR. ERROR() = 1410 .OR. (dbxl .AND. ERROR() < 6)
  874.    IF dbxl
  875.       pos = AT(':', m->errmsg)
  876.       errmsg = IIF(m->pos > 0, LEFT(m->errmsg, m->pos - 1), m->errmsg)
  877.    ENDIF
  878.    errmsg = m->errmsg + ' - Check CONFIG file values'
  879.    DO errmsg
  880.    DO proceed WITH 4
  881.    DO housekeep
  882.    RETURN TO MASTER
  883. CASE m->oldfld = 2
  884.    errmsg = 'Invalid index file'
  885.    fldnum = 2
  886. CASE ERROR() = 55
  887.    filename = SPACE(50)
  888. ENDCASE
  889. DO errmsg
  890. RETURN
  891. *************************************************************
  892. * ERRMSG - Display an error message on line 22              *
  893. *************************************************************
  894. PROCEDURE errmsg
  895. SET COLOR TO GR+*/BG
  896. @ 22,0 SAY SPACE((80-LEN(m->errmsg)-6)/2)+"<< "
  897. SET COLOR TO GR+/GB
  898. @ 22,COL() SAY m->errmsg
  899. SET COLOR TO GR+*/BG
  900. @ 22,COL() SAY " >>"
  901. @ 22,COL()
  902. SET COLOR TO N/BG
  903. RETURN
  904. ************************************
  905. * MAINMENU - Display the main menu *
  906. ************************************
  907. PROCEDURE mainmenu
  908. lbm1 = 'Setup'
  909. lbm2 = 'Help'
  910. lbm3 = 'Draw'
  911. lbm4 = 'Files'
  912. lbm5 = 'Macros'
  913. lbm6 = 'Exit'
  914. lbp1 = "Setup parameters and values for the graph"
  915. lbp2 = "Display general information about FoxGraph"
  916. lbp3 = "Build temporary files, and display/modify graph"
  917. lbp4 = "Load or save graph definition from/to file"
  918. lbp5 = "Use or record keyboard macros from/to file"
  919. lbp6 = "Exit FoxGraph"
  920. lbstring = 'SHDFME'
  921. lbprompt = .T.
  922. lbrc = '000000100020003000400050'
  923. @ 22,0
  924. @ 23,0
  925. DO lightbar WITH themenu
  926. IF m->themenu = 0
  927.    themenu = 6
  928. ENDIF
  929. RETURN
  930. ********************************************************************
  931. * LIGHTBAR - Generic routine to replace @ ... PROMPT/MENU commands *
  932. ********************************************************************
  933. PROCEDURE lightbar
  934. * Calling seqence:
  935. *   Assign menu items to lbm1 ...lbmn
  936. *   Assign corresponding prompts to lbp1 ... lbpn
  937. *   Assign corresponding row and column numbers to lbrc
  938. *   Assign corresponding letters to lbstring
  939. *   Assign .t. or .f. to lbprompt
  940. PARAMETER which
  941. choices = LEN(lbstring)
  942. oldchoice = -1
  943. DO WHILE .T.
  944.    IF m->oldchoice = -1
  945.       N = 1
  946.       DO WHILE m->n <= m->choices
  947.          mstr = LTRIM(STR(m->n))
  948.          @ VAL(SUBSTR(m->lbrc,m->n*4-3,2)), VAL(SUBSTR(m->lbrc,m->n*4-1,2)) SAY lbm&mstr
  949.          N = m->n + 1
  950.       ENDDO
  951.    ELSE
  952.       mstr = LTRIM(STR(m->oldchoice))
  953.       @ VAL(SUBSTR(m->lbrc,m->oldchoice*4-3,2)), VAL(SUBSTR(m->lbrc,m->oldchoice*4-1,2)) SAY lbm&mstr
  954.    ENDIF
  955.    oldchoice = which
  956.    mstr = LTRIM(STR(which))
  957.    @ VAL(SUBSTR(lbrc,which*4-3,2)), VAL(SUBSTR(lbrc,which*4-1,2)) GET lbm&mstr             && Highlight current choice
  958.    IF lbprompt                                   && Display prompt, if any
  959.       @ 24,0
  960.       N = (80 - LEN(lbp&mstr))/2
  961.       @ 24,N SAY lbp&mstr
  962.    ENDIF
  963.    N = 0
  964.    DO WHILE N <= 0                               && Capture input key
  965.       N = INKEY()
  966.       IF n = -9
  967.          n = IIF(lbprompt, 0, 27)
  968.       ENDIF
  969.    ENDDO
  970.    DO CASE
  971.    CASE N = 4 .OR. N = 24                        && Right or down arrow
  972.       which = m->which + 1
  973.       IF m->which > choices
  974.          which = 1
  975.       ENDIF
  976.    CASE N = 19 .OR. N = 5                        && Left or up arrow
  977.       which = m->which - 1
  978.       IF m->which < 1
  979.          which = choices
  980.       ENDIF
  981.    CASE N = 1 .OR. N = 18                        && Home or PgUp
  982.       which = 1
  983.    CASE N = 6 .OR. N = 3                         && End or PgDn
  984.       which = choices
  985.    CASE N = 13                                   && Carriage return
  986.       EXIT
  987.    CASE N = 27
  988.       which = 0
  989.       EXIT
  990.    OTHERWISE                                     && Was a letter entered?
  991.       N = AT(UPPER(CHR(N)), lbstring)
  992.       IF N <> 0
  993.          which = N
  994.          IF lbprompt                             && Display prompt, if any
  995.             mstr = LTRIM(STR(m->which))
  996.             @ 24,0
  997.             N = (80 - LEN(lbp&mstr))/2
  998.             @ 24,N SAY lbp&mstr
  999.          ENDIF
  1000.          EXIT
  1001.       ENDIF
  1002.    ENDCASE
  1003.    CLEAR GETS
  1004. ENDDO
  1005. CLEAR GETS
  1006. RETURN
  1007. ***********************************************
  1008. * REDRAW - Routine to redraw the setup screen *
  1009. ***********************************************
  1010. PROCEDURE redraw
  1011. PARAMETER fldno, lineno
  1012. IF m->fldno = 30 .AND. m->lineno = 24             && Full redraw
  1013. @ 0,0 CLEAR TO lineno,79
  1014. @ 0,0
  1015. TEXT
  1016.  
  1017.   Database                              Graph Title
  1018.   Index                                 Graph Subtitle
  1019.   Summary Only?                         Graph Style
  1020.  
  1021.   Row Definition                        Row Title
  1022.                                         Columns Title
  1023.  
  1024.  
  1025.   Column         Definitions                            Headers
  1026.     01
  1027.     02
  1028.     03
  1029.     04
  1030.     05
  1031.     06
  1032.     07
  1033.     08
  1034.     09
  1035.     10
  1036. ENDTEXT
  1037. @ 1,0 TO 21,79 DOUBLE
  1038. ENDIF
  1039. k = 1
  1040. DO WHILE m->k < m->fldno
  1041.    s = LTRIM(STR(k))
  1042.    fcode = '@' + IIF(k < 10, IIF(k = 3, ' y', 's20'), 's30')
  1043.    @ VAL(SUBSTR(rc,k*4-3,2)),VAL(SUBSTR(rc,k*4-1,2)) GET setup&s PICTURE fcode
  1044.    k = k + 1
  1045. ENDDO
  1046. @ 23,0 SAY m->line23    
  1047. CLEAR GETS
  1048. RETURN
  1049. ******************************************************************
  1050. * GETGRF - Get user to input the name of a setup definition file *
  1051. ******************************************************************
  1052. PROCEDURE getgrf
  1053. line23 = "       Enter file name - Finish with " + ;
  1054.    CHR(17)+CHR(217) + ".  Help - F1.  Abort Entry - Esc."
  1055. DO WHILE .T.
  1056.    IF LEN(m->loadfile) = 0
  1057.       @ 23,0 SAY m->line23
  1058.       filename = IIF(LEN(m->filename) > 50, m->filename, LEFT(m->filename+SPACE(50), 50))
  1059.       @ m->theitem+1,47 GET m->arrow
  1060.       CLEAR GETS
  1061.       @ m->theitem+1,48 GET m->filename FUNCTION "@s22"
  1062.       READ
  1063.       KEY = MOD(READKEY(),256)
  1064.       IF m->key = 36
  1065.          CLEAR
  1066.          @ 0,0
  1067.          DISP Files LIKE *.gr3
  1068.          DO proceed WITH 8
  1069.          CLEAR
  1070.          IF m->theitem = 1
  1071.             @ 02,31 GET lbm1
  1072.             @ 03,31 SAY lbm2
  1073.          ELSE
  1074.             @ 02,31 SAY lbm1
  1075.             @ 03,31 GET lbm2
  1076.          ENDIF
  1077.          CLEAR GETS
  1078.          @ 23,0 SAY m->line23
  1079.          @ 1,30 TO 4,70 DOUBLE
  1080.          LOOP
  1081.       ENDIF
  1082.    ENDIF
  1083.    IF m->key <> 12 .AND. LEN(TRIM(m->filename)) > 0
  1084.       I = AT('.', m->filename) + 1
  1085.       IF m->i > 1
  1086.          filename = STUFF(m->filename,m->i,LEN(SUBSTR(m->filename,m->i)),'gr3')
  1087.       ELSE
  1088.          filename = TRIM(m->filename) + '.gr3'
  1089.       ENDIF
  1090.       COMMAND = TRIM(m->filename)
  1091.       IF LEN(m->loadfile) = 0
  1092.          errmsg = IIF(m->theitem = 1,"Loading ","Saving ")+m->command+" - Please wait"
  1093.          DO errmsg
  1094.       ENDIF
  1095.    ENDIF
  1096.    EXIT
  1097. ENDDO
  1098. RETURN
  1099. *******************************************************
  1100. * GET3MC - Get user to input the name of a macro file *
  1101. *******************************************************
  1102. PROCEDURE get3mc
  1103. @ 22,0
  1104. DO WHILE .T.
  1105.    macro = IIF(LEN(m->macro) > 50, m->macro, LEFT(m->macro+SPACE(50), 50))
  1106.    @ m->theitem+1,47 GET m->arrow
  1107.    CLEAR GETS
  1108.    @ m->theitem+1,48 GET m->macro FUNCTION "@s22"
  1109.    READ
  1110.    KEY = MOD(READKEY(),256)
  1111.    IF m->key = 36
  1112.       CLEAR
  1113.       @ 0,0
  1114.       DISP Files LIKE *.3mc
  1115.       DO proceed WITH 9
  1116.       CLEAR
  1117.       IF m->theitem = 1
  1118.          @ 02,31 GET lbm1
  1119.          @ 03,31 SAY lbm2
  1120.       ELSE
  1121.          @ 02,31 SAY lbm1
  1122.          @ 03,31 GET lbm2
  1123.       ENDIF
  1124.       CLEAR GETS
  1125.       @ 23,0 SAY m->line23
  1126.       @ 1,30 TO 4,70 DOUBLE
  1127.       LOOP
  1128.    ENDIF
  1129.    IF m->key <> 12 .AND. LEN(TRIM(m->macro)) > 0
  1130.       I = AT('.', m->macro) + 1
  1131.       IF m->i > 1
  1132.          macro = STUFF(m->macro,m->i,LEN(SUBSTR(m->macro,m->i)),'3mc')
  1133.       ELSE
  1134.          macro = TRIM(m->macro) + '.3mc'
  1135.       ENDIF
  1136.       COMMAND = TRIM(m->macro)
  1137.    ENDIF
  1138.    EXIT
  1139. ENDDO
  1140. RETURN
  1141. **********************************************************
  1142. * RESTOREIT - Restore setup information from a save file *
  1143. **********************************************************
  1144. PROCEDURE restoreit
  1145. PARAMETER savefile
  1146. IF .NOT. FILE(savefile)
  1147.    errmsg = 'File does not exist'
  1148.    DO errmsg
  1149.    filename = SPACE(50)
  1150. ELSE
  1151.    RESTORE FROM &savefile ADDITIVE
  1152.    IF LEN(TRIM(m->filename)) <> 0       && no errors
  1153.       @ 22,0        && Erase Please wait mssg
  1154.       I = 1
  1155.       DO WHILE m->i < 32
  1156.          s = LTRIM(STR(m->i))
  1157.          setup&s = oldval&s
  1158.          I = m->i + 1
  1159.       ENDDO
  1160.       IF LEN(TRIM(m->setup1)) > 0
  1161.          IF LEN(TRIM(m->setup2)) > 0
  1162.             USE &setup1 INDEX &setup2
  1163.          ELSE
  1164.             USE &setup1
  1165.          ENDIF
  1166.       ELSE
  1167.          USE
  1168.       ENDIF
  1169.    ENDIF
  1170. ENDIF
  1171. RETURN
  1172. *: EOF: G3.PRG
  1173.