home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / CLIPB52.ZIP / HORWITH.ZIP / PRC.PRG
Encoding:
Text File  |  1990-05-24  |  19.6 KB  |  668 lines

  1. *  PRC.PRG      Test Application Procedures
  2.  
  3. ******************************************************
  4. *   Below this line belongs in library
  5. ******************************************************
  6.  
  7. * ───────────────────────────────────────────────────────────
  8. FUNC opendata
  9.    PARA malias
  10.    PRIV i,mindex,mkey
  11.    PRIV        index1,index2,index3,index4,index5,index6,;
  12.                index7,index8,index9,index10,index11,index12
  13.    STORE [] TO index1,index2,index3,index4,index5,index6,;
  14.                index7,index8,index9,index10,index11,index12
  15.    IF SELE([datahead])=0
  16.       DO datahead
  17.    ELSE
  18.       SELE datahead
  19.    ENDIF
  20.    SEEK UPPER(malias)
  21.    morder = []
  22.    FOR i = 1 TO p_maxindex
  23.        mntx = [index]+LTRIM(STR(i))
  24.        IF ! EMPTY(&mntx.)
  25.           mkey = [indexkey]+LTRIM(STR(i))
  26.           MAKE_NTX(M->malias,&mntx.,&mkey.)
  27.           M->&mntx = &mntx
  28.        ENDIF
  29.    NEXT
  30.    IF SELE(M->malias) = 0
  31.       SELE 0
  32.       USE &malias
  33.    ELSE
  34.       SELE &malias
  35.    ENDIF
  36.    SET INDE TO &index1,&index2,&index3,&index4,&index5,&index6,;
  37.                &index7,&index8,&index9,&index10,&index11,&index12
  38.    mret = ! NETERR()
  39. RETU mret
  40.  
  41. * ───────────────────────────────────────────────────────────
  42. PROC dataflds                                                             && call dataflds database
  43.   CHECK_NTX([dataflds],[dataflds],[alias+field_name])
  44.   CHECK_OPEN([dataflds],[dataflds])
  45. RETURN
  46.  
  47. * ───────────────────────────────────────────────────────────
  48. PROC datahead                                                             && call datahead database
  49.   CHECK_NTX([datahead],[datahead],[alias])
  50.   CHECK_OPEN([datahead],[datahead])
  51. RETURN
  52.  
  53. * ───────────────────────────────────────────────────────────
  54. PROC datarela                                                             && call dataflds database
  55.   CHECK_NTX([datarela],[datarela],[s_alias+s_field])
  56.   CHECK_OPEN([datarela],[datarela])
  57. RETURN
  58.  
  59. * ───────────────────────────────────────────────────────────
  60. FUNC check_open
  61.    PRIVATE ntx1,ntx2,ntx3,ntx4,ntx5,ntx6,ntx7,ntx8,ntx9,ntx10,ntx11,mret
  62.    STORE [] TO ntx1,ntx2,ntx3,ntx4,ntx5,ntx6,ntx7,ntx8,ntx9,ntx10,ntx11
  63.    PARA dbf,ntx1,ntx2,ntx3,ntx4,ntx5,ntx6,ntx7,ntx8,ntx9,ntx10,ntx11
  64.    IF ! OPEN_FILE(dbf,ntx1,ntx2,ntx3,ntx4,ntx5,ntx6,ntx7,ntx8,ntx9,ntx10,ntx11)
  65.       DO kbhit WITH [Error opening ] + dbf +[. Returning to menu. Any key ...]
  66.       BREAK
  67.    ENDIF
  68. RETU []
  69.  
  70. * ───────────────────────────────────────────────────────────
  71. FUNC check_ntx
  72.    PARA dbf,ntx,key
  73.    IF ! MAKE_NTX(M->dbf,M->ntx,M->key)
  74.       DO kbhit WITH [Error opening ] + dbf +[ for indexing. Returning to menu. Any key ...]
  75.       BREAK
  76.    ENDIF
  77. RETU []
  78.  
  79. * ───────────────────────────────────────────────────────────
  80. FUNC dispfile                                                       && use memofield to show code
  81.    PARA fname
  82.    BEGIN SEQUENCE
  83.       IF ! ([PRG] $ UPPER(ALLTRIM(fname)) .OR. [TXT] $ UPPER(ALLTRIM(fname)))
  84.          DO kbhit WITH [Can only show PRGs and TXTs. Sorry. Anykey continues ...]
  85.          BREAK
  86.       ENDIF
  87.       PRIV calls,mfname,mpname,msname,mscreen
  88.       mfname = ALLTRIM(fname)
  89.       mpname = SUBS(mfname,1,AT([.],mfname)-1)
  90.       msname = SUBS(mfname,AT([.],mfname)+1)
  91.       calls  = 0
  92.       CO_PUSH()                                                         && fdi89 - co_procs
  93.       CO_CHG(c_pop3)                                                    && fdi89 - co_procs
  94.       mscreen = SAVESCR(0,0,24,79)
  95.       @ 24,0
  96.       @ 24,0 SAY 'Press [Esc] when done.'
  97.       FRAMEBOX(0,0,23,79,[File: ]+mfname)
  98.       CO_CHG(c_backdrop)                                                && fdi89 - co_procs
  99.       MEMOEDIT(MEMOREAD([&mpname..&msname]),1,1,22,78,.F.,[memofunc],165)
  100.       CO_POP()                                                          && fdi89 - co_procs
  101.       RESTSCR(mscreen)
  102.    END SEQUENCE
  103. RETU []
  104.  
  105.  
  106. PROC std_e   && Standard Edit         - INCORPORATES DATABASE DICTIONARY
  107.    mloop    = .T.
  108.    fromread = .T.
  109.  
  110.    IF DELE()
  111.       DO kbhit WITH [Record has been deleted.  Any key continues...]
  112.       RETU
  113.    ENDIF
  114.  
  115.    * ─── Lock record ────────────────────────
  116.    DO WHIL ! rec_lock(5)
  117.       ?? CHR(7)
  118.       DO yes_no WITH [Record not available.  Do you wish to retry? (Y/N)]
  119.       IF myn = [N]
  120.          RETURN      && go back to browse
  121.       ENDIF
  122.    ENDDO
  123.  
  124.    * record is now locked !
  125.    CURS_ON()
  126.  
  127.    * ─── Initialize mem vars ────────────────
  128.    oldkey = &key_field
  129.    IF full_screen
  130.          mloop = .F.
  131.          IF browse
  132.             CO_PUSH()
  133.             CO_CHG(c_fullscr,c_frame)
  134.             DO &module._frame
  135.          ENDIF
  136.  
  137.          DO &meminit WITH [E]
  138.          CO_CHG(curr_grp,c_sayget)
  139.          @ 24,0
  140.          @ 24,0 SAY scr_prompt
  141.          DO &module._gets WITH [M]
  142.          READ
  143.          IF ! ESC()     && not keeping these changes
  144.             DO &mreplace     &&  replace fields with current mem vars
  145.          ENDIF
  146.          IF browse .AND. ! stayinfull
  147.             CO_POP()
  148.             RESTSCR(mscreen)
  149.          ENDIF
  150.    ELSE
  151.          DO &meminit WITH [E]    && initialize mem vars.
  152.          **         CO_CHG(curr_grp,c_sayget)
  153.          DO &module._gets WITH cur_row
  154.          READ
  155.          IF ESC()
  156.             @ cur_row,left_col+4 SAY &wfields
  157.          ELSE
  158.             *   Check in dictionary for changed keyfields
  159.             IF ChkRelEdit(ALIAS())
  160.                DO &mreplace     &&  replace fields with current mem vars
  161.             ENDIF
  162.  
  163.             IF oldkey = &key_field
  164.                @ cur_row,left_col+4 SAY &wfields
  165.             ELSE   && Changed a key field, so exit!
  166.                mloop = .F.
  167.             ENDIF
  168.          ENDIF
  169.          @ 24,0
  170.          @ 24,0 SAY mprompt
  171.    ENDIF
  172.    UNLOCK
  173.    CURS_OFF()
  174. RETURN
  175.  
  176. FUNC DELETING
  177. RETU [D] $ [mchoice+fchoice]
  178.  
  179. FUNC std_d                         &&   - INCORPORATES DATABASE DICTIONARY
  180.    PRIVATE deleted
  181.    deleted = .F.
  182.  
  183.    BEGIN SEQUENCE
  184.  
  185.       IF ! yes_no( [Sure you want to delete this one? (Y/N) ] )
  186.          DO kbhit WITH [Spared!  Any key continues...]
  187.          BREAK
  188.       ENDIF
  189.  
  190.       IF ! ChkRelDele(ALIAS())
  191.          BREAK
  192.       ENDIF
  193.  
  194.       DO WHIL ! rec_lock(5)
  195.          ?? CHR(7)
  196.          IF ! yes_no( [Record not available.  Do you wish to retry? (Y/N)] )
  197.             BREAK      && go back to browse
  198.          ENDIF
  199.       ENDDO
  200.  
  201.       * record is now locked!
  202.       DELETE
  203.       deleted = .T.
  204.       UNLOCK
  205.       SKIP                            &&  get to record after deletion.
  206.       IF OFF()
  207.            none_left = .T.
  208.            BOTT()
  209.       ELSE
  210.            none_left = .F.
  211.       ENDIF
  212.       lastrec = RECNO()               && new last record, we deleted old one
  213.       browse = DEFAULT([browse],.F.)
  214.       IF browse
  215.            * shift the screen UP, from cur_row:
  216.            IF cur_row <> lastrow
  217.               SCROLL(cur_row,left_col+1,lastrow,right_col-1,1)  && up one
  218.            ENDIF
  219.  
  220.            * display the new bottom record (one past old bottom)
  221.            SKIP (lastrow - cur_row)
  222.            IF OFF() .OR. none_left
  223.               SCROLL(lastrow,left_col+1,lastrow,right_col-1,0)
  224.               IF cur_row = lastrow     && were we on the last?
  225.                  cur_row = MAX(firstrow, cur_row - 1)  && up one
  226.               ENDIF
  227.               lastrow = MAX(firstrow,lastrow - 1)     && up one
  228.               BOTT()
  229.            ENDIF
  230.            IF ! OFF()
  231.               @ lastrow,left_col+4 SAY &wfields  && new bottom record
  232.            ENDIF
  233.            GOTO lastrec
  234.            white = .F.
  235.       ENDIF
  236.    END SEQUENCE
  237. RETURN M->deleted
  238.  
  239. FUNC cascade
  240.    PARA mode,;      &&  edit or delete
  241.         continue    &&  return .T. as soon as related data is found
  242.    continue = IF(TYPE([continue])=[U],.T.,.F.)
  243.    PRIV ctrlfield,s_a,s_f,mret
  244.    mret = .F.
  245.    BEGIN SEQUENCE
  246.       WAIT_ON([Checking related files ...])
  247.       ctrlfld = s_alias+s_field
  248.       s_a = ALLTRIM(s_alias)
  249.       s_f = ALLTRIM(s_field)
  250.       mpreedit = &s_a.->&s_f.
  251.       DO WHILE ctrlfld = s_alias+s_field
  252.           t_alias = t_alias
  253.           t_field = t_field
  254.  
  255.           * Decide if there is an index to use
  256.           IF SELE(t_alias)=0
  257.              OPENDATA(t_alias)
  258.           ENDIF
  259.           SELE &t_alias
  260.           t_order = INDEXORD()
  261.           indexed = .F.
  262.           j = 1
  263.           DO WHILE ! EMPTY(INDEXKEY(j))
  264.               IF UPPER(INDEXKEY(j)) = UPPER(datarela->t_field)
  265.                  SET ORDER TO j
  266.                  indexed = .T.
  267.               ENDIF
  268.               j = j + 1
  269.           ENDDO
  270.           IF indexed
  271.              SEEK mpreedit
  272.              IF FOUND() .AND. ! continue
  273.                 mret = .T.
  274.                 BREAK
  275.              ENDIF
  276.              t_field = t_field
  277.              DO WHILE t_field == mpreedit
  278.                 REC_LOCK(5)
  279.                 IF mode = [edit]
  280.                    REPL &t_field WITH M->&mfield.
  281.                 ENDIF
  282.                 IF mode = [delete]
  283.                    DELETE
  284.                 ENDIF
  285.                 UNLOCK
  286.                 SEEK mpreedit
  287.              ENDDO
  288.              SET ORDE TO t_order
  289.           ELSE
  290.              IF ! continue
  291.                 LOCA FOR &t_field = mpreedit
  292.                 IF FOUND()
  293.                    mret = .T.
  294.                    BREAK
  295.                 ENDIF
  296.              ENDIF
  297.              IF mode = [edit]
  298.                 REC_LOCK(5)
  299.                 REPL &t_field WITH M->&mfield. FOR &t_field = mpreedit
  300.                 UNLOCK
  301.              ENDIF
  302.              IF mode = [delete]
  303.                 DELE FOR &t_field = mpreedit .AND. REC_LOCK(5)
  304.              ENDIF
  305.           ENDIF
  306.           SELE datarela
  307.           SKIP
  308.       ENDDO
  309.       mret = .T.
  310.    END SEQUENCE
  311.    WAIT_OFF()
  312. RETU mret
  313.  
  314. FUNC chkreledit
  315.    PARA source_alias
  316.    PRIV i,mret,mfield,ctrlfld,t_alias,t_field,indexed,mpreedit,;
  317.         j,mfunc,num_of_fields,dummy
  318.    mret   = .T.
  319.    malias = SELE()
  320.    num_of_fields = &source_alias.->(FCOUNT())
  321.    FOR i = 1 TO num_of_fields
  322.       mfield = &source_alias.->(FIELD(i))
  323.       IF &source_alias.->&mfield. <> M->&mfield             && has data been changed
  324.          seekval = SUBS(source_alias+SPAC(8),1,8)+mfield
  325.          DO datarela
  326.          SEEK seekval
  327.          IF FOUND()
  328.             DO CASE
  329.                CASE edit_rule = [STOP]
  330.                   IF CASCADE([edit],.T.)
  331.                      KBHIT([Sorry - Related data found - No edit allowed on field: ] + mfield)
  332.                      mret = .F.
  333.                   ENDIF
  334.                CASE edit_rule = [CASCADE]
  335.                   CASCADE([edit])
  336.                CASE [(] $ edit_rule
  337.                   mfunc = edit_rule
  338.                   dummy = &mfunc.
  339.               ENDCASE
  340.          ENDIF
  341.       ENDIF
  342.    NEXT
  343.    SELE (malias)
  344. RETU mret
  345.  
  346.  
  347. FUNC chkreldele
  348.    PARA source_alias
  349.    PRIV i,mret,mfield,ctrlfld,t_alias,t_field,indexed,mpreedit,j,mfunc,dummy
  350.    mret          = .T.
  351.    malias        = SELE()
  352.    num_of_fields = &source_alias->(FCOUNT())
  353.    FOR i = 1 TO num_of_fields
  354.       mfield = &source_alias.->(FIELD(i))
  355.       seekval = SUBS(source_alias+SPAC(8),1,8)+mfield
  356.       DO datarela
  357.       SEEK seekval
  358.       IF FOUND()
  359.          DO CASE
  360.             CASE dele_rule = [STOP]
  361.                IF CASCADE([delete],.T.)
  362.                   KBHIT([Sorry - Related data found - No delete allowed.])
  363.                   mret = .F.
  364.                ENDIF
  365.             CASE dele_rule = [CASCADE]
  366.                CASCADE([delete])
  367.                CASE [(] $ dele_rule
  368.                   mfunc = delerule
  369.                   dummy = &mfunc.
  370.          ENDCASE
  371.       ENDIF
  372.    NEXT
  373.    SELE (malias)
  374. RETU mret
  375.  
  376. FUNC vchk
  377.    PARA mret,mess
  378.    mess = IF(TYPE([M->mess])=[U],[Invalid Entry, Please Re-Enter Data.],M->mess)
  379.    IF ! mret
  380.       KBHIT(mess+[ Anykey ...])
  381.    ENDIF
  382. RETU mret
  383.  
  384.  
  385. PROC rebuild
  386.    PRIV askpack,pack_em,i,num_ele,mname,needed,pick_all
  387.    askpack = .T.
  388.    PARA askpack
  389.    DO datahead
  390.    BEGIN SEQUENCE
  391.       IF askpack
  392.          pack_em = yes_no([Also pack the databases?])
  393.       ELSE
  394.          pack_em = .F.
  395.       ENDIF
  396.       ESCBREAK()
  397.  
  398.       * create an array of database file names:
  399.       WAIT_ON()
  400.       num_ele = ADIR([*.dbf])
  401.       PRIVATE files[num_ele]
  402.       ADIR([*.dbf],files)
  403.       SELE 0
  404.       CREATE temp&msta
  405.       USE temp&msta EXCL
  406.       MAKE_FIELD([name],[C],8)
  407.       CREA temp2&msta FROM temp&msta
  408.       USE temp2&msta EXCL
  409.       FOR i = 1 TO num_ele
  410.          IF ! [temp] $ LOWER(files[i]) .AND. ! [datahead] $ LOWER(files[i])
  411.             APPE BLAN
  412.             files[i] = SUBS(files[i],1,AT([.],files[i])-1)
  413.             REPL name WITH  files[i]
  414.          ENDIF
  415.       NEXT
  416.       INDE ON name TO temp&msta
  417.       GO TOP
  418.       WAIT_OFF()
  419.       mtitle = [Databases]
  420.       wtitle = [────Name─────]
  421.       wfields= [name]
  422.       PRIV apicks[num_ele]
  423.       AFILL([apicks],[])
  424.       pick_all = [ ]
  425.       @ 24,0
  426.       @ 24,0 SAY [P)ick certain databases or rebuild A)ll  (P/A) ] GET M->pick_all PICT [!] VALID M->pick_all $ [PA]
  427.       SET CONF OFF
  428.       READ
  429.       SET CONF ON
  430.       @ 24,0
  431.       IF pick_all = [P]
  432.          APICKS(apicks,6,15,20)
  433.       ELSE
  434.          FOR i = 1 TO RECCOUNT()
  435.             apicks[i] = i
  436.          NEXT
  437.       ENDIF
  438.       *-------------now process all the elements of the array:
  439.       BOX(6,15,11,47,[Erasing old index files],.F.)
  440.       FOR i = 1 TO LEN(apicks)
  441.           IF EMPTY(apicks[i])
  442.              EXIT
  443.           ENDIF
  444.           SELE temp2&msta
  445.           GOTO apicks[i]
  446.           dbf_name = name
  447.           IF ! EMPTY(dbf_name)
  448.              SELE 0
  449.              failed = .T.
  450.              DO WHILE failed
  451.                 USE &dbf_name EXCLUSIVE
  452.                 failed = NETERR()
  453.                 IF failed
  454.                    IF YES_NO(dbf_name+[ is in use elsewhere. Try again? ])
  455.                       LOOP
  456.                    ELSE
  457.                       KBHIT([Exiting rebuild routine ...],5)
  458.                       BREAK
  459.                    ENDIF
  460.                 ENDIF
  461.              ENDDO
  462.              IF M->pack_em
  463.                 SAY_MESS(dbf_name,[Packing])
  464.                 COPY TO temp&msta.  && will shrink the memo fields
  465.                 ZAP
  466.                 APPE FROM temp&msta.
  467.              ENDIF
  468.              SELE datahead
  469.              SEEK dbf_name
  470.              IF FOUND()
  471.                 SAY_MESS(dbf_name,[Rebuilding Indices])
  472.                 OPENDATA(dbf_name)
  473.                 USE
  474.              ELSE
  475.                 KBHIT([File ]+ TRIM(dbf_name) + [ is not in data dictionary. Will not reindex. Anykey ...],5)
  476.              ENDIF
  477.           ENDIF
  478.  
  479.       NEXT i
  480.    END SEQUENCE
  481.    ERASE temp&msta.dbf
  482.    ERASE temp2&msta.dbf
  483.    ERASE temp&msta.ntx
  484.    CLOSE DATA
  485. RETURN
  486.  
  487.  
  488. PROC say_mess
  489.    PARA file,message
  490.    @ 09,16 SAY SPAC(46)
  491.    SCROLL(10,16,19,61,1)
  492.    @ 19,17 SAY DOTS(M->file,20)+M->message
  493.    @24,0 SAY []  && position the cursor in case there are DOS messages
  494. RETURN
  495.  
  496. FUNC libhelp
  497.      PARA call_prg,input_var
  498.      PRIV datafound,libfound,malias
  499.      malias    = ALIAS()
  500.      libfound  = .T.
  501.      datafound = .F.
  502.      IF ! EMPTY(input_var)
  503.         DO datarela
  504.         SEEK SUBS(malias+SPAC(8),1,8)+TRIM(input_var)
  505.         datafound = FOUND()
  506.      ENDIF
  507.      DO CASE
  508.         CASE datafound
  509.            IF ! EMPTY(help_mod)
  510.               PRIV mscreen,targetdbf,defmodule
  511.               defmodule = help_mod+[_def]
  512.               targetdbf = t_alias
  513.               targetfld = t_field
  514.               SEEKHELP(targetdbf)
  515.               DO &defmodule
  516.               mscreen   = WINDOW()
  517.               &input_var = IF(ESC(), M->&input_var, &targetfld)
  518.               RESTSCR(mscreen)
  519.               KEYBOARD CHR(13)
  520.            ENDIF
  521.  
  522.         CASE TYPE(M->input_var) = [D]     && date variable
  523.            DO cal_help WITH M->input_var
  524.  
  525.         CASE call_prg = [GET_KEY]
  526.            DO hc_help WITH [browsehelp]
  527.  
  528.         CASE call_prg = [MEMOEDIT]
  529.            DO hc_help WITH [memokeys]
  530.            SET CURSOR ON
  531.  
  532.         CASE input_var = [PRINTER] .OR. call_prg = [PRINTIT]
  533.            IF FILE([stdprint.dbf])
  534.               DO pick_print
  535.            ELSE
  536.               DO netprint
  537.            ENDIF
  538.         OTHERWISE
  539.            libfound = .F.
  540.      ENDCASE
  541. RETU M->libfound
  542.  
  543. FUNC savescr   && Originally by Greg Martin, Modified by Financial Dynamics
  544.      PARA tr,lc,br,rc
  545.      PRIV screen,corners,mret,mtemp
  546.      screen  = SAVESCREEN(tr,lc,br,rc)
  547.      corners = CHR(tr)+CHR(lc)+CHR(br)+CHR(rc)
  548.      IF TYPE([scrfile])=[U] .OR. LEN(corners + M->screen) < 512
  549.         mret   =  corners + M->screen
  550.      ELSE
  551.         mret   = NEXTSCRFILE()
  552.         screen = corners+screen
  553.         SCRNWRIT(mret, M->screen)
  554.      ENDIF
  555. RETU mret
  556.  
  557. FUNC restscr   && Originally by Greg Martin, Modified by Financial Dynamics
  558.      PARA screen
  559.      PRIV tr,lc,br,rc
  560.  
  561.      IF ASC(SUBS(M->screen,1,1)) > 24
  562.         screen = SCRNREAD(M->screen)
  563.      ENDIF
  564.      tr     = ASC(SUBS(screen,1,1))
  565.      lc     = ASC(SUBS(screen,2,1))
  566.      br     = ASC(SUBS(screen,3,1))
  567.      rc     = ASC(SUBS(screen,4,1))
  568.      RESTSCREEN(M->tr,M->lc,M->br,M->rc,SUBS(M->screen,5))
  569. RETU .T.
  570.  
  571. FUNC nextscrfile
  572.      * scrfile is public counter - static in 5.0
  573.      * scrfile will be 6 bytes
  574.      scrfile = RIGHT([000000]+ALLTRIM(STR(VAL(scrfile)+1,4,0)),6)
  575. RETU scrfile
  576.  
  577. * tempscr.txt  structure
  578. *     Byte 1 - 5120:      headers
  579. *          Header: 1-6    screen number
  580. *                  7-12   starting byte for screen
  581. *                  13-16  number of bytes
  582. *          5121 to end:   screens
  583.  
  584.  
  585.  
  586. FUNC scrnwrit
  587.    PARA scrname,screen
  588.    PRIV handle,mhead,len,start,headpos
  589.    IF ! FILE([tempsc&msta..scr])
  590.       handle = FCREATE([tempsc&msta..scr])
  591.       FWRITE(handle,SPAC(5120))       && seed len of header area
  592.    ELSE
  593.       handle = FOPEN([tempsc&msta..scr],2)
  594.    ENDIF
  595.    len   = RIGHT([0000]+LTRIM(STR(LEN(screen),4,0)),4)
  596.    start = RIGHT([000000]+LTRIM(STR(FSEEK(handle,0,2))),6)
  597.    mhead = scrname + ;         && name of screen, 6 bytes
  598.            start   + ;         && start of screen, 6 bytes
  599.            len                 && length of screen, 4 bytes
  600.    headpos = (VAL(scrname)*16)-15
  601.    FSEEK(handle,headpos,0)        && move to end of file
  602.    FWRITE(handle,mhead)
  603.    FSEEK(handle,0,2)
  604.    FWRITE(handle,screen)
  605.    FCLOSE(handle)
  606. RETU []
  607.  
  608. FUNC scrnread
  609.    PARA scrname
  610.    PRIV handle,len,headpos,buffer,start,len,mret
  611.    handle = FOPEN([tempsc&msta..scr],0)
  612.    headpos = (VAL(scrname)*16)-15
  613.    FSEEK(handle,headpos,0)
  614.    buffer = FREADSTR(handle,16)
  615.    IF VAL(scrname) = VAL(SUBS(buffer,1,6))
  616.       start = VAL(SUBS(buffer,7,6))
  617.       len   = VAL(SUBS(buffer,13,4))
  618.       FSEEK(handle,start,0)
  619.       mret = SPAC(len)
  620.       FREAD(handle,@mret,len)
  621.    ELSE
  622.       KBHIT([Error in restore screen. Breaking to Menu ...])
  623.       BREAK
  624.    ENDIF
  625.    FCLOSE(handle)
  626. RETU mret
  627.  
  628. PROC leave
  629.    PARAMETER r1,c1
  630.    PRIVATE manswer
  631.    CO_PUSH()
  632.    CO_CHG(c_pop3)
  633.    manswer = [ ]
  634.    r1 = DEFAULT([r1],10)
  635.    c1 = DEFAULT([c1],23)
  636.    DO BOX WITH r1,c1,4,44,[Leave the system], .F.
  637.    CO_CHG(curr_grp, c_sayget)
  638.    @ r1+3,c1+3  SAY [Sure you want to quit? ] GET manswer PICT [!]
  639.    SET CONFIRM OFF
  640.    READ
  641.    SET CONFIRM ON
  642.    IF manswer $ [QY]
  643.       ERASE tempsc&msta..scr
  644.       SET COLO TO W/N          && white on black
  645.       CLEAR
  646.       QUIT
  647.    ENDIF
  648.    CO_POP()
  649. RETU
  650.  
  651. FUNC maxindex
  652.    PRIV mret,mfield
  653.    DO datahead
  654.    FOR i = FCOUNT() TO 1 STEP -1
  655.       mfield = FIELD(i)
  656.       IF LEN(ALLTRIM(mfield))<=7 .AND. UPPER(SUBS(mfield,1,5)) = [INDEX]
  657.          mret = VAL(SUBS(mfield,AT([X],mfield)+1))
  658.          EXIT
  659.       ENDIF
  660.    NEXT
  661.    USE
  662. RETU mret
  663.  
  664. FUNC dd
  665.    BOXX(10,10,[Loading Data Dictionary ...])
  666.    OVERLAY([g:dd],0)
  667. RETU []
  668.