home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Database / CLIPR503.W96 / RLFRONT.PR_ / RLFRONT.PR
Text File  |  1995-06-26  |  40KB  |  1,976 lines

  1. /***
  2. *  
  3. *  Rlfront.prg
  4. *
  5. *  Front end for REPORT and LABEL FORM design program
  6. *  
  7. *  Copyright (c) 1987-1993, Computer Associates International, Inc.
  8. *  All rights reserved.
  9. *  
  10. *  Note: Compile with /m /n
  11. *
  12. */
  13.  
  14. // File-wide definitions
  15. #include "inkey.ch"
  16. #include "setcurs.ch"
  17.  
  18. // Event types
  19. #define E_CANCEL        1       // Cancel, continue
  20. #define E_NO            2       // Exit, no save
  21. #define E_OK            3       // Exit, save
  22.  
  23.  
  24. /***
  25. *
  26. *  Setup()
  27. *
  28. *  Save/Restore info when entering/exiting RL
  29. *
  30. */
  31. PROCEDURE Setup()
  32.  
  33.    LOCAL  cStartScr
  34.    PUBLIC file_error, exit_status, my_update, no_save_flag, form_state
  35.  
  36.    file_error = 0                // File ok
  37.  
  38.    SET SCOREBOARD OFF            // Row 0 is being used
  39.    SET WRAP ON
  40.    SAVE SCREEN TO cStartScr      // Save beginning screen
  41.  
  42.    RlMain()                      // Edit reports and label definitions
  43.  
  44.    RESTORE SCREEN FROM cStartScr
  45.    RETURN
  46.  
  47.  
  48.  
  49. /***
  50. *
  51. *  SayMsg( cMessage ) --> NIL
  52. *
  53. *  Display a message to the message line
  54. *
  55. */
  56. FUNCTION SayMsg( cMsg )
  57.     LOCAL cLastColor := SETCOLOR("n/gr")
  58.     @ 2,0 SAY cMsg 
  59.     SETCOLOR( cLastColor )  
  60.     RETURN NIL
  61.  
  62.  
  63.  
  64. /***
  65. *
  66. *    SignOn() --> NIL
  67. *
  68. *    Display the sign-on message and wait for a key
  69. *
  70. */
  71. FUNCTION SignOn( aMenu )
  72.     LOCAL cLastColor, lLastCursor
  73.  
  74.     cLastColor = SETCOLOR("N/BG")
  75.     @ 0, 0 SAY aMenu[ 1 ] 
  76.     SETCOLOR( cLastColor )
  77.     lLastCursor := SETCURSOR( SC_NONE )
  78.  
  79.     @ 0, 10 SAY aMenu[ 2 ]
  80.     @ 0, 19 SAY aMenu[ 3 ]
  81.    @ 1, 0  TO 1, MAXCOL()
  82.    SayMsg( "RL - Copyright (c) 1986-1993, Computer Associates International, Inc." )
  83.  
  84.     CLEAR TYPEAHEAD
  85.     nKey = INKEY(0)
  86.     @ 2, 0
  87.     KEYBOARD CHR( nKey )
  88.  
  89.     SETPOS( 0, 0 )
  90.     SETCURSOR( lLastCursor )
  91.  
  92.     RETURN NIL
  93.  
  94.  
  95.  
  96. /***
  97. *
  98. *  RlMain()
  99. *
  100. *  main procedure
  101. *
  102. *     event types are:
  103. *       1 = cancel, (continue)
  104. *       2 = No,     (exit-no save)
  105. *       3 = Ok,     (exit-w/ save)
  106. */
  107. PROCEDURE RlMain
  108.     LOCAL aMainMenu
  109.  
  110.     PRIVATE rl_opt1, rl_opt2, rl_quit
  111.     PRIVATE rl_choice, execute, filename, open_name, file_box, event_type
  112.  
  113.     // item functions must be listed in ascending order...that
  114.     // is, higher numbered items must be located at a higher
  115.     // row number, a higher column number, or both.
  116.     DECLARE file_box[5]
  117.  
  118.     // item functions used in this program
  119.     file_box[1] = "enter_title(sysparam)"
  120.     file_box[2] = "rl_getfil(sysparam)"
  121.     file_box[3] = "ok_button(sysparam)"
  122.     file_box[4] = "cancel_button(sysparam)"
  123.     file_box[5] = "filelist(sysparam)"
  124.  
  125.     okee_dokee = "do_it()"
  126.     execute = .T.
  127.     aMainMenu := { " Report ", " Label ", " Quit " }
  128.  
  129.     SET COLOR TO BG+/B,N/BG,,,N/W
  130.    CLEAR
  131.    SignOn( aMainMenu )
  132.  
  133.     DO WHILE execute
  134.         CLEAR
  135.  
  136.         event_type   = E_CANCEL         // loop
  137.         filename     = SPACE(64)
  138.  
  139.         // Set flags
  140.         my_update    = .F.
  141.         no_save_flag = .F.
  142.  
  143.         // Display main menu
  144.         @ 0, 0  PROMPT aMainMenu[ 1 ]
  145.         @ 0, 10 PROMPT aMainMenu[ 2 ]
  146.         @ 0, 19 PROMPT aMainMenu[ 3 ]
  147.       @ 1, 0  TO 1, MAXCOL()
  148.  
  149.         MENU TO rl_choice
  150.         SET CURSOR OFF
  151.  
  152.         DO CASE
  153.         CASE rl_choice == 3 .OR. rl_choice == 0
  154.  
  155.             // Exit
  156.             execute = .F.
  157.  
  158.         CASE rl_choice == 1
  159.  
  160.             // Select REPORT FORM
  161.             DECLARE files[adir("*.FRM") + 1]
  162.             afill(files,"")
  163.             adir("*.FRM", files)
  164.  
  165.             IF multibox(7, 17, 7, 5, file_box) = 0      // <esc> or cancel?
  166.                 LOOP
  167.             ENDIF
  168.  
  169.          // add an extension if none was found (.frm)
  170.             open_name = EXT_ADD(filename, "R")  
  171.  
  172.         CASE rl_choice == 2
  173.  
  174.             // Select LABEL FORM
  175.             DECLARE files[adir("*.LBL") + 1]
  176.             afill(files,"")
  177.             adir("*.LBL", files)
  178.  
  179.             IF multibox(7, 17, 7, 5, file_box) = 0      // <esc> or cancel?
  180.                 LOOP
  181.             ENDIF
  182.  
  183.          // Add an extension if none was found (.lbl)
  184.             open_name = EXT_ADD(filename, "L")  
  185.  
  186.         ENDCASE
  187.  
  188.     IF EMPTY( filename )
  189.         execute = .F.
  190.     ENDIF
  191.  
  192.     IF execute
  193.  
  194.       * report choice was selected from menu bar
  195.         IF rl_choice == 1
  196.  
  197.             SET COLOR TO BG*+/B
  198.             @ 2,0 SAY "Loading..."
  199.             SET COLOR TO BG+/B,N/BG,,,N/W
  200.  
  201.             IF !FRM_LOAD(open_name, "FRM_FILE.DBF", "FRM_FILE.MEM")
  202.                 FRM_ERROR(open_name, file_error)
  203.                 EXIT
  204.             ENDIF
  205.  
  206.             * proceed to editing the report
  207.             DO WHILE (event_type == 1)
  208.  
  209.             * initital state of report screen (fields screen)
  210.             form_state = 3
  211.  
  212.             * the edit routine
  213.             IF FRM_EDIT(open_name, "FRM_FILE.DBF", "FRM_FILE.MEM")
  214.  
  215.                 * get the event_type from selection box upon exit
  216.                 event_type = SYSTEM_EXIT()
  217.  
  218.                     IF event_type == 2      // 'No' button was selected
  219.                         event_type = 0
  220.                     ENDIF
  221.  
  222.                     IF event_type == 3      // 'Ok' button was selected
  223.                   IF !FRM_SAVE(open_name, "FRM_FILE.DBF", "FRM_FILE.MEM")
  224.                      FRM_ERROR(open_name, file_error)
  225.  
  226.                      * exit while loop, some error was found
  227.                      event_type = 0
  228.                         ENDIF
  229.                     ENDIF
  230.  
  231.                 ELSE
  232.  
  233.                * no update (my_update) when editing, go home
  234.                     event_type = 0    
  235.  
  236.                 ENDIF
  237.  
  238.             ENDDO
  239.  
  240.             * delete work files, always
  241.             DELETE FILE frm_file.dbf
  242.             DELETE FILE frm_file.mem
  243.  
  244.         ENDIF    // rl_choice = 1
  245.  
  246.       * label choice was selected from menu bar
  247.         IF rl_choice == 2    
  248.  
  249.             SET COLOR TO BG*+/B
  250.             @ 2,10 SAY "Loading..."
  251.             SET COLOR TO BG+/B
  252.             IF !LBL_LOAD(open_name, "LBL_FILE.DBF", "LBL_FILE.MEM")
  253.                 LBL_ERROR(open_name, file_error)
  254.                 EXIT
  255.             ENDIF
  256.  
  257.             *  edit the label file
  258.             DO WHILE (event_type == 1)
  259.  
  260.                 IF LBL_EDIT(open_name, "LBL_FILE.DBF", "LBL_FILE.MEM")
  261.  
  262.                     event_type = SYSTEM_EXIT()
  263.  
  264.                     IF event_type == 2      // 'No' button
  265.                         event_type = 0
  266.                     ENDIF
  267.  
  268.                     IF event_type == 3
  269.                         IF !LBL_SAVE(open_name, "LBL_FILE.DBF", "LBL_FILE.MEM")
  270.                             LBL_ERROR(open_name, file_error)
  271.                             event_type = 0
  272.                         ENDIF
  273.                     ENDIF
  274.  
  275.                 ELSE
  276.  
  277.                * no update (my_update) when editing, go home
  278.                     event_type = 0
  279.  
  280.                 ENDIF
  281.  
  282.             ENDDO
  283.  
  284.             * delete work files
  285.             DELETE FILE lbl_file.dbf
  286.             DELETE FILE lbl_file.mem
  287.  
  288.         ENDIF
  289.  
  290.     ENDIF
  291.  
  292. ENDDO
  293.  
  294. SET CURSOR ON
  295. // end of RlMain (procedure)
  296.  
  297.  
  298.  
  299. ***
  300. * lbl_clear (function)
  301. *
  302. * clear gets for label system
  303. ***
  304. PROCEDURE lbl_clear
  305. PARAMETERS dummy1, dummy2, dummy3
  306. CLEAR GETS
  307. RETURN
  308.  
  309.  
  310.  
  311. ***
  312. * lbl_edit (function)
  313. *
  314. * edit a label file
  315. ***
  316. FUNCTION LBL_EDIT
  317. PARAMETERS label_file, label_dbf, label_mem
  318.  
  319. PRIVATE field_list, paint_only
  320.  
  321. exit_status = .F.
  322.  
  323. // get default .MEM file info
  324. RESTORE FROM &label_mem ADDITIVE
  325.  
  326. // .DBF file info
  327. SELECT 0
  328. USE &label_dbf ALIAS label_dbf
  329.  
  330. DECLARE field_list[FCOUNT()]
  331.  
  332. FOR n = 1 TO FCOUNT()
  333.     field_list[n] = FIELDNAME(n)
  334. NEXT
  335.  
  336. // draw the screen once
  337. LBL_SCR(label_file)
  338.  
  339. // cursor back on (multibox sets it off)
  340. SET CURSOR ON
  341.  
  342. paint_only = .T.
  343. DO WHILE !exit_status
  344.  
  345.     * set 'break-out' key, toggle switch
  346.     SET KEY -1 TO lbl_clear    // (F2)
  347.  
  348.     * set label format key
  349.     SET KEY -2 TO lab_setup
  350.  
  351.     * set F10 key to the exit procedure
  352.     SET KEY -9 TO set_exit_flag
  353.  
  354.     @ 05,16 GET lbl_width  PICTURE "999"
  355.     @ 06,16 GET lbl_height PICTURE "999" VALID LINE_CHK(lbl_height)
  356.     @ 07,16 GET lbl_across PICTURE "999"
  357.  
  358.     @ 05,52 GET lbl_margin PICTURE "999"
  359.     @ 06,52 GET lbl_lines  PICTURE "999"
  360.     @ 07,52 GET lbl_spaces PICTURE "999"
  361.  
  362.     @ 09,16 GET lbl_remark
  363.  
  364.     IF !paint_only
  365.         READ
  366.     ENDIF
  367.  
  368.     my_update = my_update .OR. UPDATED()
  369.  
  370.     IF exit_status
  371.         EXIT
  372.    ENDIF
  373.  
  374.     * send the escape key to exit from dbedit the first time    
  375.     IF paint_only
  376.         CLEAR GETS
  377.         KEYBOARD CHR(27)
  378.         paint_only = .F.
  379.     ENDIF
  380.  
  381.     * view/edit field expressions
  382.     SET KEY -9 TO
  383.    SET KEY 1  TO Home_key
  384.    SET KEY 6  TO End_key
  385.    SET KEY -1 TO
  386.  
  387.    SET CURSOR OFF
  388.    @ 12,0 SAY "Line " + LTRIM(STR(RECNO())) + " ═"
  389.    DBEDIT(11, 7, 23, 79, field_list, "LBL_ED")
  390.    SET CURSOR ON
  391.  
  392.    SET KEY -9 TO set_exit_flag
  393.    SET KEY 1  TO 
  394.    SET KEY 6  TO 
  395.  
  396. ENDDO
  397.  
  398. CLOSE DATABASES
  399.  
  400. IF my_update .AND. !no_save_flag
  401.     * save off to .mem file, if it was updated and 'No' was not selected
  402.    SAVE ALL LIKE lbl_* TO &label_mem
  403. ENDIF
  404.  
  405. // disable SET KEY's
  406. SET KEY -1 TO
  407. SET KEY -2 TO
  408. SET KEY -9 TO
  409.  
  410. RETURN (my_update)
  411. // end of lbl_edit (function)
  412.  
  413.  
  414.  
  415. PROCEDURE Home_key
  416. KEYBOARD CHR(31)
  417. RETURN
  418.  
  419.  
  420.  
  421. PROCEDURE End_key
  422. KEYBOARD CHR(30)
  423. RETURN   
  424.  
  425.  
  426.  
  427. ***
  428. *   lab_setup (procedure)
  429. *
  430. *   handle the various formats that dBASE supports
  431. ***
  432. PROCEDURE lab_setup
  433. PARAMETERS procName, dummy2, dummy3
  434.  
  435. PRIVATE double, more, type, type1, type2, type3, type4, type5
  436.  
  437. double = "╔═╗║╝═╚║"
  438.  
  439. SAVE SCREEN
  440.  
  441. @ 08,18,20,57 BOX ""    // space around window
  442.  
  443. // make window
  444. @ 10,20,18,55 BOX double
  445.  
  446. // disable options
  447. SET KEY -1 TO
  448. SET KEY -2 TO
  449. SET KEY 1  TO 
  450. SET KEY 6  TO 
  451.  
  452. // no F10 here, ESC returns
  453. SET KEY -9 TO
  454.  
  455. // various label types
  456. type1 = "     3 1/2 x 15/16 by 1       "
  457. type2 = "     3 1/2 x 15/16 by 2       "
  458. type3 = "     3 1/2 x 15/16 by 3       "
  459. type4 = "       4 x 17/16 by 1         "
  460. type5 = "3 2/10 x 11/12 by 3 (Cheshire)"
  461.  
  462. more = .T.
  463. DO WHILE more
  464.  
  465.     * selections
  466.     @ 12,23 PROMPT type1
  467.     @ 13,23 PROMPT type2
  468.     @ 14,23 PROMPT type3
  469.     @ 15,23 PROMPT type4
  470.     @ 16,23 PROMPT type5
  471.  
  472.     MENU TO lab_choice
  473.  
  474.     * set up the strings, based on choice
  475.     DO CASE
  476.         CASE lab_choice = 0
  477.             more = .F.
  478.         CASE lab_choice = 1
  479.             type = LTRIM(TRIM(type1)) + SPACE(60-18)
  480.             more = stuff_label(35,5,0,1,0,1,type)
  481.             UpdateHeight(5)
  482.         CASE lab_choice = 2
  483.             type = LTRIM(TRIM(type2)) + SPACE(60-18)
  484.             more = stuff_label(35,5,0,1,2,2,type)
  485.             UpdateHeight(5)
  486.         CASE lab_choice = 3
  487.             type = LTRIM(TRIM(type3)) + SPACE(60-18)
  488.             more = stuff_label(35,5,0,1,2,3,type)
  489.             UpdateHeight(5)
  490.         CASE lab_choice = 4
  491.             type = LTRIM(TRIM(type4)) + SPACE(60-14)
  492.             more = stuff_label(40,8,0,1,0,1,type)
  493.             UpdateHeight(8)
  494.         CASE lab_choice = 5
  495.             type = type5 + SPACE(60-30)
  496.             more = stuff_label(32,5,0,1,2,3,type)
  497.             UpdateHeight(5)
  498.     ENDCASE
  499.  
  500. ENDDO
  501.  
  502. SET KEY 1  TO Home_key
  503. SET KEY 6  TO End_key
  504.  
  505. CLEAR GETS
  506.  
  507. // break out of dbedit()
  508. KEYBOARD CHR(27)
  509.  
  510. RESTORE SCREEN
  511. RETURN
  512. // end of lab_setup (procedure)
  513.  
  514.  
  515.  
  516. ***
  517. *   stuff_label (function)
  518. *
  519. *   stuff label variables with values from lbl_setup, return .F.
  520. ***
  521. FUNCTION stuff_label
  522. PARAMETERS one,two,three,four,five,six,seven
  523.  
  524. lbl_width  = one
  525. lbl_height = two
  526. lbl_margin = three
  527. lbl_lines  = four
  528. lbl_spaces = five
  529. lbl_across = six
  530. lbl_remark = seven
  531.  
  532. // generates an update
  533. my_update = .T.
  534.  
  535. RETURN (.F.)
  536. // end of stuff_label (function)
  537.  
  538.  
  539.  
  540. ***
  541. *   lbl_ed (function)
  542. *
  543. *   user defined function to be called from DBEDIT, used in LBL_EDIT
  544. ***
  545. FUNCTION LBL_ED
  546. PARAMETERS mode, i
  547.  
  548. PRIVATE cur_field
  549.  
  550. // get the name of the current field into a regular variable
  551. cur_field = field_list[i]
  552.  
  553. DO CASE
  554. CASE mode = 0
  555.     * idle mode...
  556.     @ 12,0 SAY "Line " + LTRIM(STR(RECNO())) + " ═"
  557.     RETURN(1)
  558.  
  559. CASE mode = 1
  560.     KEYBOARD CHR(30)
  561.     RETURN 1
  562.  
  563. CASE mode = 2
  564.   KEYBOARD CHR(31)
  565.   RETURN 1
  566.  
  567. CASE mode < 4
  568.   * case action can be implemented for each mode
  569.   RETURN (1)
  570.  
  571. CASE LASTKEY() = -1                                   // F2
  572.     SET CURSOR ON
  573.     RETURN (0)
  574.  
  575. CASE LASTKEY() = 7
  576.   * Del..delete current line.
  577.   rec_num = RECNO()
  578.   DELETE
  579.   PACK
  580.   APPEND BLANK
  581.  
  582.   GO REC_NUM
  583.   my_update = .t.
  584.  
  585.   RETURN 2
  586.  
  587. CASE LASTKEY() = 27
  588.     RETURN (0)
  589.  
  590. CASE LASTKEY() = 13 .OR. LASTKEY() > 32 .AND. LASTKEY() < 128
  591.     * force key into GET field
  592.     IF LASTKEY() != 13
  593.         KEYBOARD CHR(LASTKEY())
  594.   ENDIF
  595.  
  596.     * enter key..edit the current field
  597.     * ..current row and col are correct
  598.     @ ROW(), COL() GET &cur_field
  599.  
  600.     * set curson on and edit the expressions
  601.     SET CURSOR ON
  602.     SET KEY -9 TO set_exit_flag
  603.     SET KEY 1 TO
  604.     SET KEY 6 TO
  605.  
  606.     READEXIT(.T.)
  607.     READ
  608.     READEXIT(.F.)
  609.  
  610.     SET KEY -9 TO
  611.     SET KEY 1 TO home_key
  612.     SET KEY 6 TO end_key
  613.  
  614.     SET CURSOR OFF
  615.  
  616.     * set the update flag
  617.     my_update = my_update .OR. UPDATED()
  618.     IF LASTKEY() = 13
  619.         KEYBOARD CHR(24)
  620.     ENDIF
  621.  
  622.     * don't quit
  623.      RETURN(1)
  624.  
  625. CASE LASTKEY() = -9
  626.     exit_status = .T.
  627.     RETURN 0
  628.  
  629. OTHERWISE
  630.     * don't quit
  631.     RETURN 1
  632.  
  633. ENDCASE
  634. // end of lbl_ed (function)
  635.  
  636.  
  637.  
  638. ***
  639. * lbl_scr (function)
  640. *
  641. * paint the label screen using SAY's
  642. ***
  643. FUNCTION LBL_SCR
  644. PARAMETERS label_file
  645.  
  646. CLEAR
  647.  
  648. @ 0,00 SAY "F1"
  649. @ 0,09 SAY "F2"
  650. @ 0,20 SAY "F3"
  651. @ 0,70 SAY "F10"
  652.  
  653. @ 1,00 SAY "Help"
  654. @ 1,09 SAY "Toggle"
  655. @ 1,20 SAY "Formats"
  656. @ 1,70 SAY "Exit"
  657.  
  658. @ 2,0 SAY REPLICATE(CHR(196),80)
  659.  
  660. // display the filename all the way to the right
  661. @ 03,80-LEN("File " + label_file) SAY "File " + label_file
  662.  
  663. // display headers
  664. @ 04,01 SAY "Dimensions"
  665. @ 04,30 SAY "Formatting"
  666.  
  667. @ 05,06 SAY "Width   "
  668. @ 06,06 SAY "Height  "
  669. @ 07,06 SAY "Across  "
  670. @ 05,36 SAY "Margin  "
  671. @ 06,36 SAY "Lines   "
  672. @ 07,36 SAY "Spaces  "
  673. @ 09,06 SAY "Remarks "
  674.  
  675. RETURN ("")
  676. // end of lbl_scr (function)
  677.  
  678.  
  679.  
  680. ***
  681. * line_chk (function)
  682. *
  683. * Check the line_height variable.  Report error if not in range. Modify 
  684. * database to accomodate new values, if any. Return Boolean valid_flag.
  685. ***
  686. FUNCTION LINE_CHK
  687. PARAMETERS height, file
  688.  
  689. PRIVATE lines, range_error, valid_flag, i
  690.  
  691. range_error = "(Valid range is between 1 and 16.)"
  692. valid_flag  = .T.
  693.  
  694. SET CURSOR OFF
  695.  
  696. IF height > 16 .OR. height <= 0
  697.         @ 24, CENTER(range_error,80) SAY range_error
  698.         valid_flag = .F.
  699.  
  700. ELSEIF height != LASTREC()
  701.  
  702.         UpdateHeight(height)
  703.     @ 24,0  // ok to clear line
  704. END
  705.  
  706. SET CURSOR ON
  707.  
  708. RETURN (valid_flag)
  709. // end of line_chk (function)
  710.  
  711.  
  712.  
  713. ***
  714. *
  715. *    UpdateHeight(height, lines)
  716. *       Delete added lines or expand to fill if lines are less than height.
  717. *       Uses inherited privates vars.
  718. *
  719. *       8/13/89 CEW
  720. *
  721. PROCEDURE UpdateHeight
  722.  
  723.         PARAMETERS height
  724.  
  725.     * delete lineitems
  726.     DELETE ALL FOR RECNO() > height
  727.     PACK
  728.  
  729.         * add lineitems
  730.         lines = RECCOUNT()
  731.     IF height > lines
  732.         DO WHILE lines < height
  733.             APPEND BLANK
  734.             SKIP
  735.             lines = lines + 1
  736.         ENDDO
  737.         GO TOP  // reset
  738.     ENDIF
  739.  
  740. RETURN
  741.  
  742.  
  743.  
  744. ***
  745. *  set_exit_flag (procedure)
  746. *
  747. *  sets the global exit_status flag to .T. upon exit (F10).
  748. ***
  749. PROCEDURE set_exit_flag
  750. CLEAR GETS
  751. exit_status = .T.
  752. RETURN
  753. // end of set_exit_flag (procedure)
  754.  
  755.  
  756.  
  757. ***
  758. * system_exit (function)
  759. *
  760. * save changes to file ...?   Ok     - Save and exit
  761. *                                 No     - Exit
  762. *                                    Cancel - loop (continue)
  763. ****
  764. FUNCTION system_exit
  765. PARAMETERS dummy1, dummy2, dummy3
  766.  
  767. PRIVATE exit_box, continue
  768.  
  769. continue = 3    // save and exit
  770.  
  771. DECLARE exit_box[4]
  772.  
  773. exit_box[1] = "save_title(sysparam)"
  774. exit_box[2] = "ok_button(sysparam)"
  775. exit_box[3] = "no_button(sysparam)"
  776. exit_box[4] = "can_button(sysparam)"
  777.  
  778. SET CURSOR OFF
  779. IF multibox(7, 17, 7, 2, exit_box) = 0      // save changes? (Y,N,C)
  780.  
  781.     continue = 1         // cancel
  782.  
  783.     IF no_save_flag     // set inside multibox routine
  784.         continue = 2
  785.     ENDIF
  786.  
  787. ENDIF
  788. SET CURSOR ON
  789.  
  790. RETURN (continue)
  791. // end of system_exit (function)
  792.  
  793.  
  794.  
  795. ****
  796. * frm_edit (function)
  797. *
  798. * this routine calls 6 procedures, using SET KEY <n> TO ...
  799. *
  800. * F-key:                      (procedure name):
  801. * F2 = pageheading screen     (form_layout)
  802. * F3 = group/subgroup screen  (form_groups)
  803. * F4 = default fields screen  (form_fields)
  804. * F5 = delete                 (form_delete)
  805. * F6 = insert                 (form_insert)
  806. * F7 = goto field             (form_goto)
  807. *
  808. ****
  809. FUNCTION FRM_EDIT
  810. PARAMETERS form_file, form_dbf, form_mem
  811. PRIVATE lNonBlank
  812. PRIVATE phdr_lines, chdr_lines, i, lkey, insert_flag
  813.  
  814. // get default .MEM file info
  815. RESTORE FROM &form_mem ADDITIVE
  816.  
  817. // .DBF file info
  818. SELECT 0
  819. USE &form_dbf ALIAS form_dbf
  820.  
  821. // set up work arrays
  822. DECLARE phdr_lines[4]
  823. DECLARE chdr_lines[24*4]    // 24 fields, 4 lines each
  824.  
  825. // inititalize pagetitle array
  826. afill(phdr_lines,SPACE(60))
  827.  
  828. // translate semicolons into lines and stuff array
  829. fstart_pos = 1
  830. phdr_lines[1] = XLATE(frm_pagehdr, ";", 60)
  831. phdr_lines[2] = XLATE(frm_pagehdr, ";", 60)
  832. phdr_lines[3] = XLATE(frm_pagehdr, ";", 60)
  833. phdr_lines[4] = XLATE(frm_pagehdr, ";", 60)
  834.  
  835. // initalize contents header array
  836. afill(chdr_lines, SPACE(65), 1, 24*4)
  837.  
  838. // set the array index
  839. ar_index = 1
  840.  
  841. // get the strings from datafile
  842. GO TOP
  843. FOR i = 1 TO RECCOUNT()
  844.  
  845.    * set field start position   
  846.     fstart_pos = 1
  847.  
  848.     * set up fields contents headers
  849.     chdr_lines[ar_index]   = XLATE(form_dbf->header, ";", 65)
  850.     chdr_lines[ar_index+1] = XLATE(form_dbf->header, ";", 65)
  851.     chdr_lines[ar_index+2] = XLATE(form_dbf->header, ";", 65)
  852.     chdr_lines[ar_index+3] = XLATE(form_dbf->header, ";", 65)
  853.  
  854.    * next one
  855.     SKIP
  856.  
  857.     * increment array subscript (in groups of four)
  858.     ar_index = ar_index + 4
  859.  
  860. NEXT
  861.     
  862. // pad the group/subgroup area, if necessary
  863. frm_grpexpr  = frm_grpexpr + SPACE(200 - LEN(frm_grpexpr))
  864. frm_grphdr   = frm_grphdr  + SPACE( 50 - LEN(frm_grphdr ))
  865. frm_subexpr  = frm_subexpr + SPACE(200 - LEN(frm_subexpr))
  866. frm_subhdr   = frm_subhdr  + SPACE( 50 - LEN(frm_subhdr ))
  867.  
  868. // modifying old file
  869. GO TOP
  870. IF frm_colcount != 0    
  871.  
  872.     m_contents = form_dbf->contents
  873.     m_width    = form_dbf->width
  874.     m_decimals = form_dbf->decimals
  875.     m_totals   = form_dbf->totals
  876.  
  877. ***** 03/29/88
  878. * originally:
  879. *   total_fields   = frm_colcount
  880. * fix:
  881.     TOTAL_FIELDS = int(FRM_COLCOUNT)
  882.  
  883.  
  884. ELSE    // modifying new file, frm_colcount == 0
  885.  
  886.     m_contents = SPACE(254)
  887.     m_width    = 10
  888.     m_decimals = 0
  889.     m_totals   = "N"
  890.     total_fields   = 1
  891.  
  892. ENDIF
  893.     
  894. // get the data again if 'Cancel' on filebox
  895. IF my_update
  896.  
  897.     m_contents = form_dbf->contents
  898.     m_width    = form_dbf->width
  899.     m_decimals = form_dbf->decimals
  900.     m_totals   = form_dbf->totals
  901.  
  902. ENDIF
  903.  
  904. insert_flag = .F.   // no inserted fields yet
  905. exit_status = .F.   // exit not set yet
  906.  
  907. // exit on F10
  908. SET KEY -9 TO set_exit_flag
  909.  
  910. key = form_state        // the fields screen
  911.  
  912. // index is always 1 on entry
  913. ar_index = 1
  914.  
  915. // control loop for frm_edit
  916. DO WHILE !exit_status
  917.  
  918.    * set page function keys 
  919.     SET KEY -1 TO clear_gets   // F2
  920.     SET KEY -2 TO clear_gets   // F3        
  921.     SET KEY -3 TO clear_gets   // F4
  922.  
  923.     DO CASE
  924.         CASE M->form_state == 1
  925.             UpdateColumn(.T.)
  926.             DO form_layout
  927.         CASE M->form_state == 2
  928.             UpdateColumn(.T.)
  929.             DO form_groups
  930.         CASE M->form_state == 3
  931.             UpdateColumn(.T.)
  932.             DO form_fields
  933.         CASE M->form_state == 4
  934.             UpdateColumn(.T.)
  935.             DO form_delete
  936.             form_state = 3
  937.             * DON'T get new key 
  938.             LOOP
  939.         CASE M->form_state == 5
  940.             UpdateColumn(.T.)
  941.             DO form_insert
  942.             form_state = 3
  943.             * DON'T get new key 
  944.             LOOP
  945.         CASE M->form_state == 6
  946.             UpdateColumn(.T.)
  947.             DO form_goto
  948.             form_state = 3
  949.             * DON'T get new key 
  950.             LOOP
  951.     ENDCASE
  952.  
  953.     * get the key
  954.     key = LASTKEY()
  955.  
  956.     DO CASE
  957.  
  958.       * if key was F10
  959.         CASE M->key == -9
  960.             DO set_exit_flag
  961.  
  962.         CASE M->key == 27 .OR. M->key == 18 .OR. M->key == 3
  963.             * define your own special 'read-exit' keys here, if needed
  964.         
  965.         ***** 03/29/88
  966.         * fix:
  967.         case m->KEY > 27 .and. m->KEY < 255
  968.  
  969.         OTHERWISE   // the function keys
  970.             form_state = VAL(SUBSTR(LTRIM(STR(M->key)),2))  // get the new state
  971.  
  972.     ENDCASE
  973.  
  974. ENDDO
  975.  
  976. //   Note: dBASE III+ uses a semi-colon to delimit report title fields
  977. //         and saves them in the .FRM file in the following manner
  978. //         (where digit <n> represents the field line number):
  979. //          
  980. //         titles               .FRM file
  981. //         ------               ---------
  982. //         1                    1
  983. //         1 2                  1;2
  984. //         1 2 3 4              1;2;3;4
  985. //         1   3                1;;3
  986. //         (none)               [blank]
  987. //               4              ;;;4
  988. //           2   4              ;2;;4
  989. //
  990. lNonBlank := .F.
  991.  
  992. frm_pagehdr := ""      
  993.  
  994. FOR i = 4 TO 2 STEP -1
  995.  
  996.    // test for first nonblank
  997.    lNonBlank := IIF( lNonBlank, lNonBlank, ! EMPTY( phdr_lines[ i ] ) )
  998.  
  999.    // once a nonblank is encountered, prefix all but the first
  1000.    // entry with a semi-colon
  1001.    frm_pagehdr := IIF( lNonBlank, ";", "" ) + TRIM( phdr_lines[ i ] ) + ;
  1002.       frm_pagehdr
  1003.  
  1004. NEXT i
  1005.  
  1006. frm_pagehdr = TRIM( phdr_lines[ i ] ) + frm_pagehdr
  1007.  
  1008. // strip of spaces in the group/subgroup areas
  1009. frm_grpexpr  = TRIM(frm_grpexpr)
  1010. frm_grphdr   = TRIM(frm_grphdr)
  1011. frm_subexpr  = TRIM(frm_subexpr)
  1012. frm_subhdr   = TRIM(frm_subhdr)
  1013.  
  1014. // save if updated and 'No' was not selected
  1015. IF my_update .AND. !no_save_flag
  1016.  
  1017.     *  set number of fields
  1018.     frm_colcount = MAX(total_fields, frm_colcount)
  1019.  
  1020.    SAVE ALL LIKE frm_* TO &form_mem
  1021.     
  1022.     * put the semicolon's back on, the simple way
  1023.     i = 1
  1024.     GO TOP
  1025.     DO WHILE .NOT. EOF()
  1026.         REPLACE form_dbf->header WITH ;
  1027.         TRIM(chdr_lines[i]) + ";" + TRIM(chdr_lines[i+1]) + ";" + ;
  1028.         TRIM(chdr_lines[i+2]) + ";" + TRIM(chdr_lines[i+3])
  1029.         SKIP
  1030.         i = i + 4
  1031.     ENDDO
  1032.  
  1033. ENDIF
  1034.  
  1035. CLOSE DATABASES
  1036.  
  1037. // disable SET KEYs ...
  1038. FOR i = 1 TO 6
  1039.     SET KEY -i TO
  1040. NEXT
  1041. SET KEY -9 TO 
  1042.  
  1043. RETURN (my_update)
  1044. // end of frm_edit (function)
  1045.  
  1046.  
  1047.  
  1048. ****
  1049. * form_fields (procedure)
  1050. *
  1051. * called from frm_edit, processes editing requests
  1052. ****
  1053. PROCEDURE form_fields
  1054.  
  1055. PRIVATE stay_msg, no_more_fields, rec_saved
  1056.  
  1057. SET CURSOR ON
  1058.  
  1059. // set up function keys
  1060. SET KEY -4 TO clear_gets    // delete (F5)
  1061. SET KEY -5 TO clear_gets    // insert (F6)
  1062. SET KEY -6 TO clear_gets    // goto # (F7)
  1063.  
  1064. SET KEY -3 TO   // disable this option (F4)
  1065.  
  1066. // draw screen
  1067. FRM_SCR(3)
  1068.  
  1069. // possible error messages
  1070. stay_msg       = "(Must type in inserted field, or delete, before moving)."
  1071. no_more_fields = "(You have reached end of file)."
  1072.  
  1073. break_out = .F.     // flag to break out of WHILE loop
  1074.  
  1075. DO WHILE !exit_status
  1076.  
  1077.    * just in case
  1078.    @ 4,71 SAY IF (!BOF(), "Field " + LTRIM(STR(RECNO())) + " ", "<bof>  ")
  1079.    @ 4,71 SAY IF (!EOF(), "Field " + LTRIM(STR(RECNO())) + " ", "<eof>  ")
  1080.  
  1081.    @ 5,71 SAY "Total " + LTRIM(STR(total_fields)) + " "
  1082.  
  1083.    @ 07,09 GET m_contents PICTURE "@S65"
  1084.  
  1085.    @ 11,09 GET chdr_lines[ar_index]
  1086.    @ 12,09 GET chdr_lines[ar_index+1]
  1087.    @ 13,09 GET chdr_lines[ar_index+2]
  1088.    @ 14,09 GET chdr_lines[ar_index+3]
  1089.  
  1090.    @ 19,10 GET m_width    PICTURE "99"
  1091.    @ 20,10 GET m_decimals PICTURE "99"
  1092.    @ 21,10 GET m_totals   PICTURE "!"
  1093.  
  1094.    READ
  1095.  
  1096.    lkey = LASTKEY()
  1097.  
  1098.    IF break_out     // set in clear_gets procedure
  1099.       EXIT
  1100.    ENDIF
  1101.  
  1102.    * was it updated?
  1103.    my_update = my_update .OR. UPDATED()
  1104.  
  1105.    * F10?
  1106.    IF exit_status
  1107.       IF RECNO() < 24
  1108.          UpdateColumn(.T.)
  1109.       ELSEIF total_fields > 0
  1110.          total_fields = total_fields - 1
  1111.       ENDIF
  1112.  
  1113.    ENDIF
  1114.  
  1115.    DO CASE
  1116.       CASE lkey == 13 .OR. lkey == 3    // CR or PgDn
  1117.     
  1118.             * put the information in the file when going forward
  1119.             UpdateColumn(.F.)
  1120.  
  1121.             IF insert_flag .AND. !my_update
  1122.                 @ 24,CENTER(stay_msg,80) SAY stay_msg
  1123.                 INKEY(5)
  1124.                 @ 24,0
  1125.                 LOOP
  1126.             ELSE
  1127.                 * reset insert flag 
  1128.                 insert_flag = .F.
  1129.             ENDIF
  1130.  
  1131.             * add a new one
  1132.             IF (UPDATED() .AND. RECNO() == LASTREC()) .OR. (RECNO() == LASTREC() .AND. !EMPTY(m_contents))
  1133.  
  1134.                 * save for restore, if illegal APPEND
  1135.                 rec_saved = RECNO()
  1136.  
  1137.                 APPEND BLANK
  1138.  
  1139.                 * no more than 24 fields allowed
  1140.                 IF RECNO() > 24
  1141.  
  1142.                     @ 24,CENTER(no_more_fields,80) SAY no_more_fields
  1143.                     INKEY(2)
  1144.                     DELETE
  1145.                     PACK
  1146.  
  1147.                     @ 24,0
  1148.                     * restore
  1149.                     GO rec_saved
  1150.  
  1151.                     LOOP
  1152.                 ENDIF
  1153.  
  1154.                 * increment array subscript
  1155.                 IF ar_index <= 92
  1156.                     ar_index = ar_index + 4
  1157.                 ENDIF
  1158.  
  1159.                 * add the total field count
  1160.                 total_fields = total_fields + 1
  1161.  
  1162.                 * init new field
  1163.                 m_contents = SPACE(254)
  1164.                 m_width    = 10
  1165.                 m_decimals =  0
  1166.                 m_totals   = "N"
  1167.  
  1168.             ELSE
  1169.  
  1170.             SKIP
  1171.             IF ar_index <= 92
  1172.                 ar_index = ar_index + 4
  1173.             ENDIF
  1174.  
  1175.                 IF EOF()
  1176.  
  1177.                 * no more ...
  1178.                     @ 24,CENTER(no_more_fields,80) SAY no_more_fields
  1179.                     INKEY(3)
  1180.                     @ 24,0
  1181.  
  1182.                 SKIP -1
  1183.  
  1184.                 IF RECNO() < 24
  1185.                 IF ar_index > 1
  1186.                         ar_index = ar_index - 4
  1187.                     ENDIF
  1188.                 ENDIF
  1189.  
  1190.             ENDIF
  1191.     
  1192.                 m_contents = form_dbf->contents
  1193.                 m_width    = form_dbf->width
  1194.                 m_decimals = form_dbf->decimals
  1195.                 m_totals   = form_dbf->totals
  1196.     
  1197.             ENDIF
  1198.                                 
  1199.       CASE lkey == 18   // PgUp
  1200.  
  1201.         * put the information in the file when going backward
  1202.         UpdateColumn(.F.)
  1203.  
  1204.         IF insert_flag .AND. !my_update
  1205.             @ 24,CENTER(stay_msg,80) SAY stay_msg
  1206.             INKEY(3)
  1207.             @ 24,0
  1208.             LOOP
  1209.         ELSE
  1210.             * reset insert flag 
  1211.             insert_flag = .F.
  1212.         ENDIF
  1213.  
  1214.         IF !BOF()
  1215.  
  1216.             SKIP -1
  1217.  
  1218.             IF ar_index > 1
  1219.                 ar_index = ar_index - 4
  1220.             ENDIF
  1221.  
  1222.            m_contents = form_dbf->contents
  1223.            m_width    = form_dbf->width
  1224.            m_decimals = form_dbf->decimals
  1225.            m_totals   = form_dbf->totals
  1226.  
  1227.         ENDIF
  1228.  
  1229.    ENDCASE
  1230.  
  1231. ENDDO
  1232.  
  1233. my_update = my_update .OR. UPDATED()
  1234.  
  1235. RETURN
  1236. // end of form_fields (procedure)
  1237.  
  1238.  
  1239.  
  1240. ***
  1241. * form_insert (procedure)
  1242. *
  1243. * insert a column (field) in the report file
  1244. *
  1245. * insert a field only when:
  1246. *   a) field is not the first one, first time
  1247. *   b) field is not the last one
  1248. *   c) total field count is not larger than maximum, 24
  1249. *
  1250. * Purpose:
  1251. *  shifts fields up by one, inserts a new one
  1252. * Note: Field that is left blank creates an error in expression area.
  1253. *       Delete 'unused' field to avoid this.
  1254. *
  1255. ***
  1256. PROCEDURE form_insert
  1257. PARAMETERS dummy1, dummy2, dummy3
  1258.  
  1259. PRIVATE saved_record, insert_error, temp
  1260.  
  1261. insert_error = "(Cannot insert field. Insert (F6) invalid here, or maximum is reached)."
  1262.  
  1263. IF RECNO() != 1 .AND. RECNO() != LASTREC() .AND. RECCOUNT() < 24 .AND. !EMPTY(form_dbf->contents)
  1264.  
  1265.     * save position before insert call
  1266.     saved_record = RECNO()
  1267.  
  1268.     * new field, return Boolean to insert_flag for processing in form_fields
  1269.     insert_flag = insert_blank(RECNO())
  1270.     
  1271.     * restore record#
  1272.     GO saved_record
  1273.  
  1274.     * add an item in array, starting at ar_index pos
  1275.     FOR temp = ar_index TO ar_index + 3
  1276.         ains(chdr_lines, ar_index)
  1277.         chdr_lines[ar_index] = SPACE(65)        // no (U) here!
  1278.     NEXT
  1279.  
  1280.     * increment field count variables
  1281.     total_fields = total_fields + 1
  1282.     frm_colcount = frm_colcount + 1
  1283.  
  1284.     * initialize new field
  1285.     m_contents = SPACE(254)
  1286.     REPLACE form_dbf->contents WITH SPACE(254)
  1287.     REPLACE form_dbf->header   WITH SPACE(260)
  1288.     REPLACE form_dbf->width    WITH 10
  1289.     REPLACE form_dbf->totals   WITH "N"
  1290.     REPLACE form_dbf->decimals WITH 0
  1291.  
  1292.     * no update flag for insert
  1293.     my_update = .F.
  1294.  
  1295. ELSE
  1296.  
  1297.     @ 24,CENTER(insert_error,80) SAY insert_error
  1298.     INKEY(4)
  1299. ENDIF
  1300.  
  1301. RETURN
  1302. // end of form_insert (procedure)
  1303.  
  1304.  
  1305.  
  1306. ***
  1307. *  insert_blank (function)
  1308. *
  1309. *  insert a blank record in dbf at position 'pos'
  1310. *
  1311. ***
  1312. FUNCTION insert_blank
  1313. PARAMETERS pos
  1314.  
  1315. PRIVATE inserted
  1316.  
  1317. // yes, we are inserting, set flag
  1318. inserted = .T.
  1319.  
  1320. // set position for insert
  1321. @ 3,0 SAY "Insert at field " + LTRIM(STR(pos)) + " ..."
  1322.  
  1323. // position
  1324. GO pos
  1325.  
  1326. // make temp file, copy the rest of file
  1327. COPY NEXT LASTREC() TO temp
  1328.  
  1329. // mark them, delete
  1330. DELETE ALL FOR RECNO() >= pos
  1331.  
  1332. // add a new one
  1333. APPEND BLANK
  1334.  
  1335. // get the tail list
  1336. APPEND FROM temp
  1337.  
  1338. // remove deleted items
  1339. PACK
  1340.  
  1341. // delete temporary work file, insertion done!
  1342. DELETE FILE temp.DBF
  1343.  
  1344. RETURN (inserted)
  1345. // end of insert_blank (function)
  1346.  
  1347.  
  1348.  
  1349. ***
  1350. * form_delete (procedure)
  1351. *
  1352. * purpose:
  1353. *    delete a column (field) in the report file
  1354. *
  1355. * delete a field when the field is already blank
  1356. * so user has the option to abort process.
  1357. *
  1358. * note: a deletion sets the my_update flag so the file may
  1359. *       be saved to disk.
  1360. ***
  1361. PROCEDURE form_delete
  1362. PARAMETERS dummy1, dummy2, dummy3
  1363.  
  1364. PRIVATE temp, saved_record, content_error
  1365.  
  1366. content_error = "(Field must be blank to do that.  Use Ctrl-Y to delete)."
  1367.  
  1368. // field contents is empty, OK to delete
  1369. IF EMPTY(m_contents)
  1370.  
  1371.     * remove items in array, starting at ar_index pos
  1372.     FOR temp = ar_index TO ar_index + 3
  1373.         adel(chdr_lines, ar_index)
  1374.         chdr_lines[LEN(chdr_lines)] = SPACE(65)     // no (U) here!
  1375.     NEXT
  1376.  
  1377.     * save this record before delete
  1378.     saved_record = RECNO()
  1379.  
  1380.     DELETE
  1381.     PACK
  1382.  
  1383.     * reset insert flag, in case of 'insert-notyping-delete' process
  1384.     insert_flag = .F.
  1385.  
  1386.     IF !EOF()
  1387.  
  1388.         IF saved_record = total_fields
  1389.             GO saved_record - 1
  1390.             IF ar_index > 1
  1391.                 ar_index = ar_index - 4
  1392.             ENDIF
  1393.         ELSE
  1394.             GO saved_record
  1395.         ENDIF
  1396.  
  1397.     ELSE
  1398.  
  1399.         APPEND BLANK
  1400.  
  1401.         REPLACE form_dbf->contents WITH SPACE(254)
  1402.         REPLACE form_dbf->header   WITH SPACE(260)
  1403.         REPLACE form_dbf->width    WITH 10
  1404.         REPLACE form_dbf->totals   WITH "N"
  1405.         REPLACE form_dbf->decimals WITH  0
  1406.  
  1407.     ENDIF
  1408.  
  1409.     IF total_fields > 1
  1410.         total_fields = total_fields - 1
  1411.         frm_colcount = frm_colcount - 1
  1412.     ENDIF
  1413.  
  1414.     * get the new data
  1415.     m_contents = form_dbf->contents
  1416.     m_width    = form_dbf->width
  1417.     m_decimals = form_dbf->decimals
  1418.     m_totals   = form_dbf->totals
  1419.  
  1420.     my_update = .T.     // generates an update...
  1421.  
  1422. ELSE    // field content is not empty, error
  1423.  
  1424.     * honk 
  1425.     ?? CHR(7)
  1426.  
  1427.     * display the error msg
  1428.     @ 24,CENTER(content_error,80) SAY content_error
  1429.     INKEY(4)
  1430. ENDIF
  1431.  
  1432. RETURN
  1433. // end of form_delete (procedure)
  1434.  
  1435.  
  1436.  
  1437. ***
  1438. *   form_goto (procedure)
  1439. *
  1440. *   goto specified field (F7)
  1441. ***
  1442. PROCEDURE form_goto
  1443.  
  1444. PRIVATE goto_str, goto_field, goto_error, goto_ok, recno_saved
  1445.  
  1446. * for this procedure only
  1447. SET CONFIRM ON
  1448.  
  1449. goto_str   = "Go to field number "
  1450. goto_error = "(Field not in valid range.  Range is 1 to 24)."
  1451. goto_field = RECNO()
  1452.  
  1453. goto_ok = .F.
  1454. DO WHILE !goto_ok
  1455.  
  1456.     @ 24,0
  1457.     @ 24,20 SAY goto_str
  1458.     @ 24,39 GET goto_field PICTURE "99"
  1459.     READ
  1460.  
  1461.    * abort if <esc> key was hit
  1462.    IF LASTKEY() == 27
  1463.       RETURN   
  1464.    ENDIF
  1465.  
  1466.    * save, to restore if error (eof)
  1467.    recno_saved = RECNO()
  1468.  
  1469.    * first check
  1470.    GO goto_field
  1471.  
  1472.    * entry ok?
  1473.    IF goto_field <= 0 .OR. goto_field >= 25 .OR. EOF()
  1474.         @ 24,CENTER(goto_error,80) SAY goto_error
  1475.         INKEY(4)
  1476.       IF EOF()
  1477.          GO recno_saved
  1478.       ENDIF
  1479.     ELSE
  1480.         goto_ok = .T.
  1481.     ENDIF
  1482.  
  1483. ENDDO
  1484.  
  1485. // new field position
  1486. GO goto_field
  1487.  
  1488. // set ar_index to new position
  1489. ar_index = (goto_field * 4) - 3
  1490.  
  1491. // the data of the new position
  1492. m_contents = form_dbf->contents
  1493. m_width    = form_dbf->width
  1494. m_decimals = form_dbf->decimals
  1495. m_totals   = form_dbf->totals
  1496.  
  1497. // set back to default
  1498. SET CONFIRM OFF
  1499.  
  1500. RETURN
  1501. // end of form_goto (procedure)
  1502.  
  1503.  
  1504.  
  1505. ***
  1506. *   clear_gets (procedure)
  1507. *
  1508. *   exit read
  1509. ***
  1510. PROCEDURE clear_gets
  1511. PARAMETERS dummy1,dummy2,dummy3
  1512.  
  1513. IF form_state = 3   // break out of loop when in fields procedure only
  1514.     break_out = .T.
  1515. ENDIF
  1516. CLEAR GETS
  1517. RETURN
  1518. // end of clear_gets (procedure)
  1519.  
  1520.  
  1521.  
  1522. ***
  1523. * form_layout (procedure)
  1524. *
  1525. * display the pageheading and items related to report layout
  1526. ***
  1527. PROCEDURE form_layout
  1528.  
  1529. LOCAL bValidHeader := { | cString | ! ( ";" $ cString ) }
  1530. // this represents the minimum constraint --  calculation should account for
  1531. // column widths
  1532. LOCAL bValidRMargin := { | nExp | nExp < frm_pagewidth .AND. nExp >= 0 }
  1533.  
  1534. LOCAL nHeaderIndex
  1535.  
  1536. FRM_SCR(1)
  1537.  
  1538. SET CURSOR ON
  1539.  
  1540. SET KEY -4 TO   // no delete option
  1541. SET KEY -5 TO  // no insert option
  1542. SET KEY -6 TO   // no goto option here
  1543. SET KEY -1 TO   // disable this option
  1544.  
  1545. // get page headers from user
  1546. FOR nHeaderIndex := 1 TO LEN( phdr_lines )
  1547.  
  1548.    @ 05 + nHeaderIndex, 12 GET phdr_lines[ nHeaderIndex ] VALID ;
  1549.       VCondition( bValidHeader, ;
  1550.       "Semicolon (;) not permitted in page heading" )
  1551.  
  1552. NEXT nHeaderIndex
  1553.     
  1554. @ 12,42 GET frm_pagewidth PICTURE "999"
  1555. @ 13,42 GET frm_leftmarg  PICTURE "999"
  1556.  
  1557.  
  1558. @ 14,42 GET frm_rightmarg PICTURE "999" VALID VCondition( bValidRMargin, ;
  1559.    "Invalid right margin -- must be between 0 and " + ;
  1560.    ltrim( str( frm_pagewidth - 1 ) ) )
  1561.  
  1562.  
  1563. @ 15,42 GET frm_linespage PICTURE "999"
  1564. @ 16,42 GET frm_dblspaced PICTURE "!"
  1565.             
  1566. @ 20,49 GET frm_pebp      PICTURE "!"
  1567. @ 21,49 GET frm_peap      PICTURE "!"
  1568. @ 22,49 GET frm_plainpage PICTURE "!"
  1569.             
  1570. READ
  1571.  
  1572. IF UPDATED()
  1573.     my_update = .T.
  1574. ENDIF
  1575.  
  1576. RETURN
  1577. // end of form_layout (procedure)
  1578.  
  1579.  
  1580.  
  1581. /***
  1582. *
  1583. *  VCondition( <bCondition>, [<cErrMsg>], [<lEcho>] ) --> lValid
  1584. *
  1585. *  Test current GET for specified condition; optionally display
  1586. *  error message.
  1587. *
  1588. */
  1589. STATIC FUNCTION VCondition( bCondition, cErrMsg, lEcho )
  1590.    LOCAL lValid := .F.
  1591.  
  1592.    cErrMsg := IIF( cErrMsg == NIL, "Invalid", cErrMsg )
  1593.  
  1594.    xExp := GetActive():varGet()
  1595.  
  1596.    lEcho := IIF( lEcho == NIL, .T., lEcho )
  1597.  
  1598.    lValid := EVAL( bCondition, xExp )
  1599.  
  1600.    IF lEcho
  1601.       SET CURSOR OFF
  1602.  
  1603.       @ 24,0 SAY PADC( IIF( !lValid, cErrMsg, ""), 80 )
  1604.  
  1605.       SET CURSOR ON
  1606.  
  1607.    ENDIF
  1608.  
  1609.    RETURN ( lValid )
  1610.  
  1611.  
  1612.  
  1613. ***
  1614. * form_groups (procedure)
  1615. *
  1616. * display the group and subgroup headers, plus summary and eject options
  1617. ***
  1618. PROCEDURE form_groups
  1619.  
  1620. FRM_SCR(2)
  1621.  
  1622. SET CURSOR ON
  1623.  
  1624. SET KEY -4 TO   // no delete option here
  1625. SET KEY -5 TO  // no insert option here
  1626. SET KEY -6 TO   // no goto option here
  1627.  
  1628. SET KEY -2 TO   // disable this option
  1629.  
  1630. @ 06,25 GET frm_grpexpr PICTURE "@S50"
  1631. @ 07,25 GET frm_grphdr
  1632.  
  1633. @ 11,23 GET frm_summary PICTURE "!"
  1634. @ 12,23 GET frm_pe PICTURE "!"
  1635.  
  1636. @ 18,25 GET frm_subexpr PICTURE "@S50"
  1637. @ 19,25 GET frm_subhdr
  1638.  
  1639. READ    
  1640.     
  1641. IF UPDATED()
  1642.     my_update = .T.
  1643. ENDIF
  1644.  
  1645. RETURN
  1646. // end of form_groups (procedure)
  1647.  
  1648.  
  1649.  
  1650. ***
  1651. * frm_scr (function)
  1652. *
  1653. * draw the report screens, indicated by parameter 'screen'
  1654. ***
  1655. FUNCTION FRM_SCR
  1656. PARAMETERS screen
  1657.  
  1658. PRIVATE pagehead, field_def, group, sub_group, m_exit, m_nogo
  1659. PRIVATE m_f1, m_f2, m_f3, m_f4, m_f5, m_f6, m_f10, m_layout, m_groups, m_fields
  1660. PRIVATE m_insert, m_delete, m_help
  1661.  
  1662. pagehead  = "═══ Page Header ═══"
  1663. field_def = "═══ Column Definitions ═══"
  1664. group     = "═══ Group Specifications ═══"
  1665. sub_group = "═══ Sub-Group Specifications ═══"
  1666.  
  1667. m_f1  = "F1"
  1668. m_f2  = "F2"
  1669. m_f3  = "F3"
  1670. m_f4  = "F4"
  1671. m_f5  = "F5"
  1672. m_f6  = "F6"
  1673. m_f7  = "F7"
  1674. m_f10 = "F10"
  1675.  
  1676. m_help   = "Help  "
  1677. m_layout = "Report"         // "Layout"
  1678. m_groups = "Groups"
  1679. m_fields = "Columns"        //  "Fields"
  1680. m_delete = "Delete"
  1681. m_insert = "Insert"
  1682. m_goto   = "Go To "
  1683. m_exit   = "Exit  "
  1684. m_nogo   = "...    "
  1685.  
  1686. CLEAR
  1687.  
  1688. // Display menu line.
  1689. @ 00,01 SAY m_f1
  1690. @ 00,11 SAY m_f2
  1691. @ 00,21 SAY m_f3
  1692. @ 00,31 SAY m_f4
  1693. @ 00,41 SAY m_f5
  1694. @ 00,51 SAY m_f6
  1695. @ 00,61 SAY m_f7
  1696. @ 00,70 SAY m_f10
  1697.  
  1698. @ 01,01 SAY m_help
  1699. @ 01,11 SAY m_layout
  1700. @ 01,21 SAY m_groups
  1701. @ 01,31 SAY m_fields
  1702. @ 01,41 SAY m_delete
  1703. @ 01,51 SAY m_insert
  1704. @ 01,61 SAY m_goto
  1705. @ 01,70 SAY m_exit
  1706.  
  1707. @ 02,00 SAY REPLICATE(CHR(196),80)
  1708.  
  1709. DO CASE
  1710.  
  1711.     CASE screen == 1
  1712.         * Page definition screen.
  1713.  
  1714.         @ 01,11 SAY m_nogo   // this option 'disabled'
  1715.         @ 01,41 SAY m_nogo   // delete 'disabled'
  1716.         @ 01,51 SAY m_nogo   // insert 'disabled'
  1717.         @ 01,61 SAY m_nogo   // go to  'disabled'
  1718.  
  1719.         @ 03,80-LEN("File " + form_file) SAY "File " + form_file
  1720.  
  1721.         @ 04,30 SAY pagehead
  1722.  
  1723.         @ 11,27 SAY "Formatting "
  1724.     
  1725.         @ 12,27 SAY "Page Width"
  1726.         @ 13,27 SAY "Left Margin"
  1727.         @ 14,27 SAY "Right Margin"
  1728.         @ 15,27 SAY "Lines Per Page"
  1729.         @ 16,27 SAY "Double Spaced?"
  1730.     
  1731.         @ 19,24 SAY "Printer Directives"
  1732.  
  1733.         @ 20,24 SAY "Page Eject Before Print"
  1734.         @ 21,24 SAY "Page Eject After Print"
  1735.         @ 22,24 SAY "Plain Page"
  1736.  
  1737.     CASE screen == 2
  1738.         * Group definition screen.
  1739.  
  1740.         @ 01,21 SAY m_nogo   // this option 'disabled'
  1741.         @ 01,41 SAY m_nogo  // delete 'disabled'
  1742.         @ 01,51 SAY m_nogo   // insert 'disabled'
  1743.         @ 01,61 SAY m_nogo  // go to  'disabled'
  1744.  
  1745.         @ 03,80-LEN("File " + form_file) SAY "File " + form_file
  1746.  
  1747.         @ 04,CENTER(group,80) SAY group
  1748.  
  1749.         @ 06,0 SAY "Group On Expression"
  1750.         @ 07,0 SAY "Group Heading" 
  1751.  
  1752.         @ 11,0 SAY "Summary Report Only"
  1753.         @ 12,0 SAY "Page Eject After Group"
  1754.  
  1755.         @ 16,CENTER(sub_group, 80) SAY sub_group
  1756.  
  1757.         @ 18,0 SAY "Sub-Group On Expression"
  1758.         @ 19,0 SAY "Sub-Group Heading"
  1759.  
  1760.     CASE screen == 3
  1761.  
  1762.         * Column definition screen.
  1763.         @ 03,80-LEN("File " + form_file) SAY "File " + form_file
  1764.         @ 01,31 SAY m_nogo
  1765.  
  1766.         @ 05,CENTER(field_def, 80) SAY field_def
  1767.  
  1768.         @ 07,00 SAY "Contents"
  1769.         @ 10,00 SAY "Heading"
  1770.  
  1771.         @ 11,06 SAY "1"
  1772.         @ 12,06 SAY "2"
  1773.         @ 13,06 SAY "3"
  1774.      @ 14,06 SAY "4"
  1775.         @ 18,00 SAY "Formatting"
  1776.  
  1777.         @ 19,00 SAY "Width"
  1778.         @ 20,00 SAY "Decimals"
  1779.         @ 21,00 SAY "Totals"
  1780.  
  1781. ENDCASE
  1782.  
  1783. RETURN ("")
  1784. // end of frm_scr (function)
  1785.  
  1786.  
  1787.  
  1788. ***
  1789. * frm_error (function)
  1790. *
  1791. * display the report file errors
  1792. ****
  1793. FUNCTION FRM_ERROR
  1794. PARAMETERS fname, dos_error
  1795.  
  1796. PRIVATE err_str, dos_code
  1797.  
  1798. dos_code = LTRIM(STR(dos_error))
  1799.  
  1800. DO CASE
  1801.  
  1802.     CASE dos_error == -3        // eof while reading
  1803.         err_str = "Code " + dos_code + " " + "eof while reading report " + fname
  1804.  
  1805.     CASE dos_error == -2        // disk full
  1806.         err_str = "Code " + dos_code + " " + "disk full saving report " + fname
  1807.  
  1808.     CASE dos_error == -1        // not a report file
  1809.         err_str = "Code " + dos_code + " " + "not a report file " + fname
  1810.  
  1811.     CASE dos_error == 2     // Open error, file not found
  1812.         err_str = "Code " + dos_code + " " + "error opening report " + fname
  1813.  
  1814.     CASE dos_error == 6     // Close error, invalid handle
  1815.         err_str = "Code " + dos_code + " " + "error closing report " + fname
  1816.  
  1817.    CASE dos_error == 25   // Seek error, FSEEK
  1818.         err_str = "Code " + dos_code + " " + "error seeking report " + fname
  1819.  
  1820.     CASE dos_error == 29        // Write error, write fault
  1821.         err_str = "Code " + dos_code + " " + "error writing report " + fname
  1822.  
  1823.     CASE dos_error == 30        // Read error, read fault
  1824.         err_str = "Code " + dos_code + " " + "error reading report " + fname
  1825.  
  1826.   OTHERWISE
  1827.         err_str = "Code " + dos_code + " " + "see DOS extended error codes"
  1828.  
  1829. ENDCASE
  1830.  
  1831. @ 24,CENTER(err_str,80) SAY err_str
  1832. INKEY(4)
  1833. @ 24,0
  1834.  
  1835. RETURN ("")
  1836. // end of frm_error (function)
  1837.  
  1838.  
  1839.  
  1840. ***
  1841. * lbl_error (function)
  1842. *
  1843. * display the label file errors
  1844. ***
  1845. FUNCTION LBL_ERROR
  1846. PARAMETERS fname, dos_error
  1847.  
  1848. PRIVATE err_str, dos_code
  1849.  
  1850. dos_code = LTRIM(STR(dos_error))
  1851.  
  1852. DO CASE
  1853.  
  1854.     CASE dos_error == -3        // eof while reading
  1855.         err_str = "Code " + dos_code + " " + "eof while reading label " + fname
  1856.  
  1857.     CASE dos_error == -2        // disk full
  1858.         err_str = "Code " + dos_code + " " + "disk full saving label " + fname
  1859.  
  1860.     CASE dos_error == -1        // not a label file
  1861.         err_str = "Code " + dos_code + " " + "not a label file " + fname
  1862.  
  1863.     CASE dos_error == 2     // Open error, file not found
  1864.         err_str = "Code " + dos_code + " " + "error opening label " + fname
  1865.  
  1866.     CASE dos_error == 6     // Close error, invalid handle
  1867.         err_str = "Code " + dos_code + " " + "error closing label " + fname
  1868.  
  1869.    CASE dos_error == 25   // Seek error, FSEEK
  1870.         err_str = "Code " + dos_code + " " + "error seeking label " + fname
  1871.  
  1872.     CASE dos_error == 29        // Write error, write fault
  1873.         err_str = "Code " + dos_code + " " + "error writing label " + fname
  1874.  
  1875.     CASE dos_error == 30        // Read error, read fault
  1876.         err_str = "Code " + dos_code + " " + "error reading label " + fname
  1877.  
  1878.   OTHERWISE
  1879.         err_str = "Code " + dos_code + " " + "see DOS extended error codes"
  1880.  
  1881. ENDCASE
  1882.  
  1883. @ 24,CENTER(err_str,80) SAY err_str
  1884. INKEY(4)
  1885. @ 24,0
  1886.  
  1887. RETURN ("")
  1888. // end of lbl_error (function)
  1889.  
  1890.  
  1891.  
  1892. ***
  1893. * center (function)
  1894. *
  1895. * center a string
  1896. ***
  1897. FUNCTION CENTER
  1898. PARAMETER string,length
  1899. RETURN INT((length-LEN(string))/2)
  1900.  
  1901. //**
  1902. // ext_add (function)
  1903. //
  1904. // append an .FRM/.LBL extension if one was not found
  1905. //**
  1906. FUNCTION EXT_ADD
  1907. PARAMETERS fname, type
  1908.  
  1909. PRIVATE open
  1910.  
  1911. IF AT(".", fname) == 0
  1912.     IF type == "L"
  1913.         open = TRIM(fname) + ".LBL"
  1914.     ENDIF
  1915.     IF type == "R"
  1916.         open = TRIM(fname) + ".FRM"
  1917.     ENDIF
  1918. ELSE
  1919.     open = TRIM(fname)
  1920. ENDIF
  1921.  
  1922. RETURN (open)
  1923. // end of ext_add (function)
  1924.  
  1925.  
  1926.  
  1927. ***
  1928. * Xlate()
  1929. *   Translate the semicolons
  1930. ***
  1931. FUNCTION XLATE
  1932. PARAMETERS source, char, len
  1933.  
  1934. PRIVATE xlated_str
  1935.  
  1936. fend_pos = AT(char, SUBSTR(source, fstart_pos, len))
  1937.  
  1938. IF fend_pos = 0
  1939.     xlated_str = SUBSTR(source, fstart_pos, len)
  1940.     fstart_pos = fstart_pos + LEN(xlated_str)
  1941. ELSE
  1942.     xlated_str = SUBSTR(source, fstart_pos, fend_pos - 1)
  1943.     fstart_pos = fstart_pos + LEN(xlated_str) + 1
  1944. ENDIF
  1945.  
  1946. // pad string with spaces when needed
  1947. IF LEN(xlated_str) != len
  1948.     xlated_str = xlated_str + SPACE(len - LEN(xlated_str))
  1949. ENDIF
  1950.  
  1951. RETURN (xlated_str)
  1952.  
  1953. ***
  1954. *
  1955. * UpdateColumn()
  1956. *   update the contents and parameters of column for report
  1957. *   when change the screen
  1958. ***
  1959. FUNCTION UpdateColumn( isCheckUpd )
  1960.    IF isCheckUpd
  1961.       IF !my_update
  1962.          RETURN (NIL)
  1963.       ENDIF
  1964.    ENDIF
  1965.  
  1966.    form_dbf->contents = m_contents
  1967.    form_dbf->width = m_width
  1968.    form_dbf->decimals = m_decimals
  1969.    form_dbf->totals = m_totals
  1970.  
  1971.    RETURN (NIL)
  1972.