home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a108 / 15.ddi / FXAPCODE.PR_ / FXAPCODE.bin
Encoding:
Text File  |  1994-03-10  |  92.4 KB  |  3,060 lines

  1. * FoxApp 2.6 -- FoxPro 2.6 application generator
  2. * Author: Walter J. Kennamer
  3. * Copyright 1994, Microsoft Corporation
  4. * Adapted for wizards and localization by: John L. Alden, Alden Anderson
  5. * ------------------------------------------------------------------------
  6. * The following code was migrated here from the #SECTION 1 SETUP code in
  7. * the APPSCX screen. FxApCode.prg is now the Main file in the FoxApp 
  8. * project, rather than appscx.
  9.  
  10. PARAMETERS rscused, forceregen, fxapAppname
  11. PRIVATE ALL
  12. EXTERNAL PROCEDURE MSGBOX
  13.  
  14. * For debugging, set this memvar to .t. 
  15.  
  16. * Parameter    Type     Description
  17. * ----------   ------   --------------------------------------------------
  18. * rscused      L        Determines whether the resource file
  19. *                          is checked for relations
  20. * forceregen   L or N   Determines whether FoxApp generates full or
  21. *                          abbreviated project files.  It can take these
  22. *                          values:
  23. *                          1 (or .T.)   Always generate full project
  24. *                          2 (or .F.)   Always generate abbreviated project
  25. *                          3            Check CONFIG.FP for instructions
  26. * fxapAppname  C        Memvar included when called from Catalog Manager. Name of
  27. *                        .app file is stored to this memvar before returning.
  28.  
  29.  
  30. * --- Localization --------------------------------------------------------------
  31.  
  32. * Note on localization: Function "versiondate" in this file uses English strings when looking
  33. * in the string returned by VERS(1) for the month of the FoxPro build. As of 2/4/94 this
  34. * string was not being localized, so the English strings were left in place. If in
  35. * future builds VERS() is localized, then these strings ought to be lifted up into this 
  36. * localization section and turned into #DEFINE's.
  37.  
  38. #DEFINE C_BADPLAT    "This version of FoxApp only runs on Windows, DOS or Macintosh."
  39. #DEFINE C_SOURCE1    "FoxApp source files must be available to build projects."
  40. #DEFINE C_LOCSRC     "Please locate the FOXAPP.SRC file:"
  41. #DEFINE C_SOURCE2    "FoxApp cannot build a full project without its source files."
  42. #DEFINE C_INDEXFOR   "Indexing for "
  43. #DEFINE C_INDEXON    "Indexing on "
  44. #DEFINE C_ISCOMP     " is complete!"
  45. #DEFINE C_NOFIND     "Could not find "
  46. #DEFINE C_FAILAPP    "FoxApp could not complete this application."
  47. #DEFINE C_LOCDBF     "Please locate the database"
  48. #DEFINE C_SCXCREA1    "Creating screen "
  49. #DEFINE C_SCXMADE    "Screen has been created."
  50. #DEFINE C_DBFNOOPN   "Database could not be opened."
  51. #DEFINE C_WHERE      "Where is "
  52. #DEFINE C_NOTFND     " could not be found!"
  53. #DEFINE C_RSCRO      "Resource file is read-only.  Not updated."
  54. #DEFINE C_RSCREC     "Existing resource record is read-only.  Not updated."
  55. #DEFINE C_WINPOS     "Saving window positions."
  56. #DEFINE C_ERRLINE     "Line No.: "
  57. #DEFINE C_ERRPRG     "Program: "
  58. #DEFINE C_ERRERR     "  Error: "
  59. #DEFINE C_ERRSRC     " Source: "
  60. #DEFINE C_ESCPRESS     "Escape pressed.  FoxApp is terminating."
  61. #DEFINE C_BADDBF     "Invalid database name."
  62. #DEFINE C_SCXNAME     "A screen file name is not allowed here."
  63. #DEFINE C_MNXNAME     "A menu file name is not allowed here."
  64. #DEFINE C_DBFPMT     "Database name:"
  65. #DEFINE C_BADSCX     "Invalid screen name."
  66. #DEFINE C_SCXPMT     "Screen file name:"
  67. #DEFINE C_SCXCREA2      "Creating screen file"
  68. #DEFINE C_SAVEARR     "\<Save Arrangement!" KEY ALT+S        && Note keyboard shortcuts
  69. #DEFINE C_CANCPMT     "\<Cancel!" KEY ALT+C                    && may change with localization
  70. #DEFINE C_CTRLTITL     "Control panel"
  71. #DEFINE C_NOREC1     "FoxApp couldn't find any "
  72. #DEFINE C_NOREC2     " records for this screen."
  73. #DEFINE C_NOTABLE     "No table name entered.  Enter one and try again."
  74. #DEFINE C_ERRGEN     "Error generating application"
  75. #DEFINE C_NAMEPMT     "Name your application:"
  76. #DEFINE C_SAMENAME     "I named my program FoxApp.  You have to name yours something else."
  77. #DEFINE C_SAVDBWIN     "Saving database relations and window positions."
  78. #DEFINE C_GENMSG     "Generating application "
  79. #DEFINE C_TMDESC     | Description:
  80. #DEFINE C_TMHEAD     | This program was automatically generated by FoxApp.
  81. #DEFINE C_TMRUN         To run this application, type DO
  82. #DEFINE C_TMENV          Set up runtime environment
  83. #DEFINE C_TMFONT     Store current screen font and set it to something reasonable.
  84. #DEFINE C_TMDESCD     ║ Description:    
  85. #DEFINE C_TMHEADD     ║ This program was automatically generated by FoxApp.
  86. #DEFINE C_TGETMENU     Summon the main application menu
  87. #DEFINE C_TOPENDBF     Open the main database
  88. #DEFINE C_TPLSLOC     "Please locate the "
  89. #DEFINE C_TDBF         " database"
  90. #DEFINE C_TTHE         "The "
  91. #DEFINE C_TDBNOTFD     " database could not be found."
  92. #DEFINE C_TCHKIDX     Make sure the index exists and is hooked up
  93. #DEFINE C_TRECDEL     all records were deleted!
  94. #DEFINE C_NOTCONT     " does not contain "
  95. #DEFINE C_RECORDS     " records."
  96. #DEFINE C_PUTTING     "Putting "
  97. #DEFINE C_SCXINWIN     " screen into window."
  98. #DEFINE C_FACOMM     "THE FOLLOWING LINE WAS ADDED BY FOXAPP"
  99. #DEFINE C_NOSCXHD     "Screen heading record could not be found."
  100. #DEFINE C_NOSCXOPN     "Screen could not be opened."
  101. #DEFINE C_TDBSET     Set up any related databases
  102. #DEFINE C_TSCXDISP     Display the main screen file
  103. #DEFINE C_TNODBCLS     Make sure nothing closed the database unexpectedly
  104. #DEFINE C_TCLEANUP     Clean up after the application
  105. #DEFINE C_TRESTENV     Restore databases, indexes and environment
  106. #DEFINE C_RESTERR     Restore original error and escape routines
  107. #DEFINE C_TSREL1     This procedure opens subsidiary databases (if any) and establishes
  108. #DEFINE C_TSREL2     the relations between the main database and the subsidiary
  109. #DEFINE C_TSREL3     databases.  It will be empty if there are no subsidiary databases.
  110. #DEFINE C_TDBF2         " database:"
  111. #DEFINE C_TSEEREC1     Restore the following line if you only want to see records in the
  112. #DEFINE C_TSEEREC2     parent file that have related records in the child file.
  113. #DEFINE C_TDEFARR     Define the dbflist array
  114. #DEFINE C_BLDPJX     "Building project"
  115. #DEFINE C_CTRLMSG     "Adding control panel"
  116. #DEFINE C_BLDAPP     "Building application"
  117. #DEFINE C_RSCTITLE     "FoxApp Resource File Entries"
  118. #DEFINE C_NOTADBF     "The file you have chosen is not a valid table."
  119. #DEFINE C_NOLIB         " is not available."
  120. #DEFINE C_LOCATE     "Please locate "
  121. #DEFINE C_ONELTR     "Table name must be longer than one character."
  122. * -------------------------------------------------------------------------------
  123. * Used in FA_Alert() function.
  124. #DEFINE C_WINLIB        "FOXTOOLS.FLL"
  125. #DEFINE C_OK            0
  126. #DEFINE C_YESNO            4
  127. #DEFINE C_YES              6
  128. #DEFINE C_ICONQ            32
  129. #DEFINE C_ICONEXCL      48
  130.  
  131. * Record the status of TALK and SAFETY
  132. IF SET('TALK') = 'ON'
  133.    SET TALK OFF
  134.    m.app_talk = 'ON'
  135. ELSE
  136.    m.app_talk = 'OFF'
  137. ENDIF
  138.  
  139. DO CASE
  140. CASE _WINDOWS
  141.     m.app_platform = "WINDOWS"
  142.     m.g_dfltfface = "MS Sans Serif"
  143.     m.g_dfltfsize = 8
  144.     m.g_dfltfstyle = "B"
  145.     m.libfile = C_WINLIB
  146.     m.libext  = "FLL"
  147. CASE _MAC
  148.     m.app_platform = "MAC"
  149.     m.g_dfltfface = "Geneva"
  150.     m.g_dfltfsize = 10
  151.     m.g_dfltfstyle = ""
  152.     m.libfile = ""
  153. CASE _DOS
  154.     m.app_platform = "DOS"
  155.     m.g_dfltfface = "FoxFont"
  156.     m.g_dfltfsize = 10
  157.     m.g_dfltfstyle = ""
  158.     m.libfile = ""
  159.     m.libext  = "PLB"
  160. OTHERWISE
  161.     WAIT WINDOW C_BADPLAT NOWAIT
  162.     RETURN
  163. ENDCASE
  164.  
  165. m.fa_libavail = .t.
  166. m.fa_loadlib = len(m.libfile) > 0
  167. if m.fa_loadlib
  168.   if ! m.libfile $ SET("LIBRARY",1)
  169.     m.fa_libavail = .f.
  170.     IF !FILE(SYS(2004)+m.libfile)
  171.         m.templib=LOCFILE(m.libfile,m.libext,C_LOCATE+m.libfile+':')
  172.         IF EMPTY(m.templib)
  173.            WAIT WINDOW m.libfile + C_NOLIB
  174.              return
  175.         ELSE
  176.            m.libfile = m.templib
  177.         ENDIF
  178.     ELSE
  179.       m.libfile = sys(2004)+m.libfile
  180.     ENDIF
  181.     SET LIBRARY TO (m.libfile) ADDITIVE  
  182.   ENDIF
  183. endif
  184.  
  185. m.app_safe = SET("SAFETY")
  186. SET SAFETY OFF
  187. m.app_dele = SET("DELETED")
  188. SET DELETED ON
  189.  
  190. m.fa_fldset = SET("FIELDS")            && on or off
  191. m.fa_fldscope = SET("FIELDS",2)        && local or global
  192. SET FIELDS OFF
  193. SET FIELDS GLOBAL
  194.  
  195. IF PARAMETERS() < 3
  196.    m.fxapAppname = ""     && memvar will acquire name of .app file
  197. ENDIF
  198. IF PARAMETERS() < 2
  199.    m.forceregen  = 3     && forces check of CONFIG.FP
  200. ENDIF
  201. IF PARAMETERS() < 1
  202.    m.rscused     = .T.   && store/restore relations from resource file?
  203. ENDIF
  204.  
  205. * Map the 'forceregen' variable into numeric form.
  206. IF TYPE('forceregen') = "L"
  207.    IF m.forceregen
  208.       m.forceregen = 1
  209.    ELSE
  210.       m.forceregen = 2
  211.    ENDIF
  212. ENDIF
  213.  
  214. m.appfile = ""        && this is the memvar that FoxApp uses to track the 
  215.                     && name of the .app that is generated. When called
  216.                     && by the Catlaog Manager, this value will be 
  217.                     && assigned to the incoming parameter m.fxapAppname.
  218.                     
  219. m.GenSuccess = .f.    && flag indicating successful generation of FoxApp app.                    
  220.  
  221. DO APPSCX.SPR
  222.  
  223. m.fxapAppname = iif(m.GenSuccess, alltrim(m.appfile), "")
  224. release appfile
  225.  
  226. if m.libfile <> "" and ! m.fa_libavail        && library was not in use originally
  227.     RELEASE LIBRARY (m.libfile)
  228. endif
  229.  
  230. set fields &fa_fldset
  231. set fields &fa_fldscope
  232.  
  233. return
  234.  
  235.  
  236. *---------------------------------------------------------------------
  237. * Common procedure code for FoxApp, migrated here from screen snippets
  238. *---------------------------------------------------------------------
  239.  
  240. *!*****************************************************************
  241. *!
  242. *!      Procedure: CLOSE_UP
  243. *!
  244. *!*****************************************************************
  245. PROCEDURE close_up
  246. * Do closing housekeeping for FoxApp.
  247.  
  248. SET TOPIC TO (mtopic)
  249.  
  250. RELEASE scxname, dbfname, invname, cdxname, repname, tmfname, ;
  251.    bailout, origname, dbflist, mnuname  && , appfile
  252. RELEASE origdbflist
  253.  
  254. CLOSE DATABASES
  255.  
  256. CLEAR WINDOW
  257.  
  258. * Restore the PUSH-ed system menu 
  259. POP MENU _msysmenu
  260.  
  261. POP KEY
  262.  
  263. CLEAR PROGRAM
  264. m.scrn_font   = WFONT(1,"")
  265. m.scrn_fsize  = WFONT(2,"")
  266. m.scrn_fstyle = WFONT(3,"")
  267. IF ! _DOS
  268.   MODIFY WINDOW SCREEN FONT m.scrn_font,m.scrn_fsize STYLE m.scrn_fstyle
  269. ENDIF
  270.  
  271. * Restore original ON ERROR & ON ESCAPE routines
  272. ON ERROR  &app_error
  273. ON ESCAPE &app_escape
  274. RELEASE app_error, app_escape
  275.  
  276. * Get rid of any vue files that might be hanging around
  277. IF FILE('qprview.vue')
  278.    DELETE FILE qprview.vue
  279. ENDIF
  280. IF FILE('appview.vue')
  281.    DELETE FILE appview.vue
  282. ENDIF
  283. IF FILE('dbfselec.vue')
  284.    DELETE FILE dbfselec.vue
  285. ENDIF
  286. IF FILE('foxapp.vue')
  287.    SET VIEW TO foxapp
  288.    DELETE FILE foxapp.vue
  289. ENDIF
  290.  
  291. IF m.app_talk = "ON"
  292.    SET TALK ON
  293. ENDIF
  294. IF m.app_dele = "OFF"
  295.    SET DELETED OFF
  296. ENDIF
  297. IF m.app_safe = "ON"
  298.    SET SAFETY ON
  299. ENDIF
  300.  
  301. RELEASE app_talk, app_safe, app_dele, dbflist
  302.  
  303. return
  304.  
  305.  
  306. *!*****************************************************************
  307. *!
  308. *!      Procedure: COPYPIECE
  309. *!
  310. *!*****************************************************************
  311. PROCEDURE copypiece
  312. * Copy FoxApp pieces to project directory
  313.  
  314. IF _MAC
  315.   fxpath = addbs(SYS(2027,foxappdir))         && probably C:\foxpro2\foxapp\
  316. ELSE
  317.   fxpath = addbs(foxappdir)
  318. ENDIF
  319. projdir = addbs(justpath(m.appfile))
  320.  
  321. =putout('prgs\appproc.prg',m.fxpath,m.projdir)
  322. =putout('menus\appmenu.mnx',m.fxpath,m.projdir)
  323. =putout('menus\appmenu.mnt',m.fxpath,m.projdir)
  324. =putout('screens\getdest.scx',m.fxpath,m.projdir)
  325. =putout('screens\getdest.sct',m.fxpath,m.projdir)
  326. =putout('screens\getorder.scx',m.fxpath,m.projdir)
  327. =putout('screens\getorder.sct',m.fxpath,m.projdir)
  328. =putout('screens\appabout.scx',m.fxpath,m.projdir)
  329. =putout('screens\appabout.sct',m.fxpath,m.projdir)
  330. =putout('screens\appsrch.scx',m.fxpath,m.projdir)
  331. =putout('screens\appsrch.sct',m.fxpath,m.projdir)
  332. =putout('screens\prtsetup.scx',m.fxpath,m.projdir)
  333. =putout('screens\prtsetup.sct',m.fxpath,m.projdir)
  334. =putout('screens\prtopts.scx',m.fxpath,m.projdir)
  335. =putout('screens\prtopts.sct',m.fxpath,m.projdir)
  336. =putout('screens\appctrl.scx',m.fxpath,m.projdir)
  337. =putout('screens\appctrl.sct',m.fxpath,m.projdir)
  338.  
  339. *!*****************************************************************
  340. *!
  341. *!      Procedure: PUTOUT
  342. *!
  343. *!*****************************************************************
  344. FUNCTION putout
  345. * Copies a file with name "Pathname" from the path specified in "source"
  346. * the the "target" path.
  347.  
  348. PARAMETERS pathname, source, target
  349. PRIVATE pathname, source, target, filname, file1, file2
  350.  
  351. m.filname = justfname(m.pathname)
  352. m.target = addbs(m.target)
  353. m.source = addbs(m.source)
  354. m.file1 = m.source + m.pathname
  355. m.file2 = m.target + m.filname
  356. IF FILE(m.file1)
  357.    COPY FILE (file1) TO (file2)
  358. ENDIF
  359.  
  360.  
  361. *!*****************************************************************
  362. *!
  363. *!      Function: FINDSRC
  364. *!
  365. *!*****************************************************************
  366. FUNCTION findsrc
  367. parameter appdir
  368. * Make sure that the FoxApp source files have been installed.
  369. * If they haven't, I can't build a project.
  370. m.targfile = addbs(SYS(2004))+'FOXAPP\FOXAPP.SRC'
  371. IF !FILE(m.targfile)
  372.    m.targfile = addbs(SYS(2004))+'FOXAPPW\FOXAPP.SRC'
  373.    IF !FILE(m.targfile)
  374.       * See if we are in the FOXAPP directory itself then
  375.       m.targfile = addbs(SYS(2004))+'GOODIES\FOXAPP\FOXAPP.SRC'
  376.       IF !FILE(m.targfile)
  377.          * See if we are in the FOXAPP directory itself then
  378.          m.targfile = addbs(CURDIR())+'FOXAPP.SRC'
  379.          IF !FILE(m.targfile)
  380.             WAIT WINDOW C_SOURCE1 NOWAIT
  381.             m.targfile = GETFILE('SRC',C_LOCSRC)
  382.             IF EMPTY(m.targfile)
  383.                DO alert WITH C_SOURCE2
  384.                DO close_up
  385.                RETURN ''
  386.             ELSE
  387.                m.newpath = SET('PATH')+';'+justpath(m.targfile)
  388.                SET PATH TO (m.newpath)
  389.             ENDIF
  390.          ENDIF
  391.       ENDIF
  392.    ENDIF
  393. ENDIF
  394. RETURN justpath(m.targfile)
  395.  
  396. *!*****************************************************************
  397. *!
  398. *!      Procedure: VERSIONDATE
  399. *!
  400. *!*****************************************************************
  401. FUNCTION versiondate
  402. * Returns the FoxPro build date as a date value
  403.  
  404. * VERSION(1) returns a string like this:
  405. *     FoxPro/LAN 2.0 (X) [Nov 15 1991 16:16:06] Serial # DEV001296 
  406. * We want to return 11/15/91 as a date value
  407.  
  408. m.v1 = VERSION(1)
  409.  
  410. * extract the portion of the VERSION(1) string between the brackets
  411. m.vdatestr = SUBSTR(m.v1,AT('[',m.v1)+1,RAT(']',m.v1)-AT('[',m.v1))
  412.  
  413. * extract just the date portion of the date/time string
  414. m.vdatestr = ALLTRIM(SUBSTR(m.vdatestr,1,AT(' ',m.vdatestr,3)-1))
  415.  
  416. * Pull out the month abbreviation and figure out which month number it is
  417. m.vmonthstr = UPPER(SUBSTR(m.vdatestr,1,3))
  418.  
  419. DO CASE
  420. CASE INLIST(m.vmonthstr,'JANUARY','JAN')
  421.    m.vmonth = 1
  422. CASE INLIST(m.vmonthstr,'FEBRUARY','FEB')
  423.    m.vmonth = 2
  424. CASE INLIST(m.vmonthstr,'MARCH','MAR')
  425.    m.vmonth = 3
  426. CASE INLIST(m.vmonthstr,'APRIL','APR')
  427.    m.vmonth = 4
  428. CASE INLIST(m.vmonthstr,'MAY')
  429.    m.vmonth = 5
  430. CASE INLIST(m.vmonthstr,'JUNE','JUN')
  431.    m.vmonth = 6
  432. CASE INLIST(m.vmonthstr,'JULY','JUL')
  433.    m.vmonth = 7
  434. CASE INLIST(m.vmonthstr,'AUGUST','AUG')
  435.    m.vmonth = 8
  436. CASE INLIST(m.vmonthstr,'SEPTEMBER','SEP','SEPT')
  437.    m.vmonth = 9
  438. CASE INLIST(m.vmonthstr,'OCTOBER','OCT')
  439.    m.vmonth = 10
  440. CASE INLIST(m.vmonthstr,'NOVEMBER','NOV')
  441.    m.vmonth = 11
  442. CASE INLIST(m.vmonthstr,'DECEMBER','DEC')
  443.    m.vmonth = 12
  444. ENDCASE
  445.  
  446. * Reconstruct the string by using the month number 
  447. m.vdatestr = STR(m.vmonth,2)+'/'+LTRIM(SUBSTR(m.vdatestr,AT(' ',m.vdatestr)))
  448.  
  449. * Replace spaces with slashes
  450. m.vdatestr = CHRTRAN(m.vdatestr,' ','/')
  451. RETURN CTOD(m.vdatestr)
  452.  
  453. *!*****************************************************************
  454. *!
  455. *!      Procedure: TRIMZERO
  456. *!
  457. *!*****************************************************************
  458. FUNCTION trimzero
  459. * Trims ASCII 0 characters from strg
  460. PARAMETER m.strg
  461. RETURN CHRTRAN(m.strg,CHR(0),"")
  462.  
  463. *!*****************************************************************
  464. *!
  465. *!      Procedure: FORCEEXT
  466. *!
  467. *!*****************************************************************
  468. FUNCTION forceext
  469. * Force the extension of "filname" to be whatever ext is.
  470. PARAMETERS filname,ext
  471. PRIVATE ALL
  472. IF SUBSTR(m.ext,1,1) = "."
  473.    m.ext = SUBSTR(m.ext,2,3)
  474. ENDIF
  475.  
  476. m.pname = justpath(m.filname)
  477. m.filname = justfname(UPPER(ALLTRIM(m.filname)))
  478. IF AT('.',m.filname) > 0
  479.    m.filname = SUBSTR(m.filname,1,AT('.',m.filname)-1) + '.' + m.ext
  480. ELSE
  481.    m.filname = m.filname + '.' + m.ext
  482. ENDIF
  483. RETURN addbs(m.pname) + m.filname
  484.  
  485. *!*****************************************************************
  486. *!
  487. *!      Procedure: DEFAULTEXT
  488. *!
  489. *!*****************************************************************
  490. FUNCTION defaultext
  491. * Force the extension of "filname" to be whatever ext is, unless it
  492. * already has an extension.
  493. PARAMETERS filname,ext
  494. PRIVATE ALL
  495. IF EMPTY(justext(m.filname))
  496.    RETURN forceext(m.filname,m.ext)
  497. ELSE
  498.    RETURN m.filname
  499. ENDIF   
  500.  
  501. *!*****************************************************************
  502. *!
  503. *!      Procedure: JUSTFNAME
  504. *!
  505. *!*****************************************************************
  506. FUNCTION justfname
  507. * Return just the filename (i.e., no path) from "filname"
  508. PARAMETERS filname
  509. PRIVATE ALL
  510. IF RAT('\',m.filname) > 0
  511.    m.filname = SUBSTR(m.filname,RAT('\',m.filname)+1,255)
  512. ENDIF
  513. IF RAT(':',m.filname) > 0
  514.    m.filname = SUBSTR(m.filname,RAT(':',m.filname)+1,255)
  515. ENDIF
  516. RETURN ALLTRIM(UPPER(m.filname))
  517.  
  518. *!*****************************************************************
  519. *!
  520. *!      Procedure: JUSTSTEM
  521. *!
  522. *!*****************************************************************
  523. FUNCTION juststem
  524. * Return just the stem name from "filname"
  525. PARAMETERS m.filname
  526. PRIVATE ALL
  527. IF RAT('\',m.filname) > 0
  528.    m.filname = SUBSTR(m.filname,RAT('\',m.filname)+1,255)
  529. ENDIF
  530. IF RAT(':',m.filname) > 0
  531.    m.filname = SUBSTR(m.filname,RAT(':',m.filname)+1,255)
  532. ENDIF
  533. IF AT('.',m.filname) > 0
  534.    m.filname = SUBSTR(m.filname,1,AT('.',m.filname)-1)
  535. ENDIF
  536. RETURN ALLTRIM(UPPER(m.filname))
  537.  
  538. *!*****************************************************************
  539. *!
  540. *!      Procedure: JUSTEXT
  541. *!
  542. *!*****************************************************************
  543. FUNCTION justext
  544. * Return just the extension from "filname"
  545. PARAMETERS m.filname
  546. PRIVATE ALL
  547. filname = JustFname(m.filname)   && prevents problems with ..\ paths
  548. m.ext = ""
  549. IF AT('.',m.filname) > 0
  550.    m.ext = SUBSTR(m.filname,AT('.',m.filname)+1,3)
  551. ENDIF
  552. RETURN UPPER(m.ext)
  553.  
  554.  
  555. *!*****************************************************************
  556. *!
  557. *!      Procedure: JUSTPATH
  558. *!
  559. *!*****************************************************************
  560. FUNCTION justpath
  561. * Return just the path name from "filname"
  562. PARAMETERS m.filname
  563. PRIVATE ALL
  564. m.filname = ALLTRIM(UPPER(m.filname))
  565. m.pathsep = IIF(_MAC,":", "\")
  566. IF _MAC
  567.    m.found_it = .F.
  568.    m.maxchar = max(RAT("\", m.filname), RAT(":", m.filname))
  569.    IF m.maxchar > 0
  570.       m.filname = SUBSTR(m.filname,1,m.maxchar)
  571.       IF RIGHT(m.filname,1) $ ":\" AND LEN(m.filname) > 1 ;
  572.             AND !(SUBSTR(m.filname,LEN(m.filname)-1,1)  $ ":\")
  573.          m.filname = SUBSTR(m.filname,1,LEN(m.filname)-1)
  574.       ENDIF
  575.       RETURN m.filname
  576.    ENDIF
  577. ELSE
  578.    IF m.pathsep $ filname
  579.       m.filname = SUBSTR(m.filname,1,RAT(m.pathsep,m.filname))
  580.       IF RIGHT(m.filname,1) = m.pathsep AND LEN(m.filname) > 1 ;
  581.             AND SUBSTR(m.filname,LEN(m.filname)-1,1) <> m.pathsep
  582.          m.filname = SUBSTR(m.filname,1,LEN(m.filname)-1)
  583.       ENDIF
  584.       RETURN m.filname
  585.    ENDIF      
  586. ENDIF
  587. RETURN ''
  588.  
  589. *!*****************************************************************
  590. *!
  591. *!      Procedure: ADDBS
  592. *!
  593. *!*****************************************************************
  594. FUNCTION addbs
  595. * Add a backslash to a path name if there isn't already one there
  596. PARAMETER m.pathname
  597. PRIVATE ALL
  598. m.pathname = ALLTRIM(UPPER(m.pathname))
  599. IF !(RIGHT(m.pathname,1) $ '\:') AND !EMPTY(m.pathname)
  600.    m.pathname = m.pathname + IIF(_MAC,':','\')
  601. ENDIF
  602. RETURN m.pathname
  603.  
  604. *!*****************************************************************
  605. *!
  606. *!      Function: ADDCOLON
  607. *!
  608. *!*****************************************************************
  609. FUNCTION Addcolon
  610. PARAMETER m.strg
  611. PRIVATE m.retval
  612. * If strg is the name of the current disk, add a colon to it.  This 
  613. * function is used mainly by SET DEFAULT TO statements, where we have
  614. * to have the colon.
  615. IF UPPER(m.strg)+":" == UPPER(SET("DEFAULT"))
  616.    m.retval = m.strg + ":"
  617. ELSE
  618.    m.retval = m.strg 
  619. ENDIF      
  620. RETURN m.retval
  621.  
  622. *!*****************************************************************
  623. *!
  624. *!      Function: TERM
  625. *!
  626. *!*****************************************************************
  627. FUNCTION term
  628. * Returns the item-th term from string strg, where a term is a set of characters
  629. * separated by commas.
  630.  
  631. PARAMETERS m.strg, m.item
  632. m.numcommas = OCCURS(",",strg)
  633. IF m.item > m.numcommas + 1
  634.    RETURN ""
  635. ELSE   
  636.     DO CASE
  637.     CASE m.item = 1
  638.        RETURN LEFT(m.strg,AT(",",m.strg)-1)
  639.     CASE m.item = m.numcommas + 1
  640.        RETURN SUBSTR(m.strg,RAT(",",m.strg)+1)
  641.     OTHERWISE
  642.        RETURN SUBSTR(m.strg,AT(",",m.strg,m.item-1)+1,;
  643.           AT(",",m.strg,m.item) - AT(",",m.strg,m.item-1) - 1)
  644.     ENDCASE
  645. ENDIF     
  646.  
  647. *!*****************************************************************
  648. *!
  649. *!      Procedure: INVERT
  650. *!
  651. *!*****************************************************************
  652. PROCEDURE invert
  653. * Completely invert the "filname" database into a CDX file, creating
  654. * an index tag on each field.
  655.  
  656. PARAMETERS m.filname
  657. PRIVATE m.filname, m.i, m.safe_stat, m.comp_stat, m.in_area, m.fldname
  658.  
  659. m.comp_stat = SET("COMPATIBLE")
  660. m.safe_stat = SET("SAFETY")
  661. SET COMPATIBLE TO FOXPLUS
  662. SET SAFETY OFF
  663.  
  664. m.in_area = SELECT()            && currently selected area
  665.  
  666. m.fstem = makealias(juststem(m.filname))
  667. IF USED(m.fstem)
  668.    SELECT (m.fstem)
  669. ELSE
  670.    SELECT 0
  671.    USE (m.filname)
  672. ENDIF
  673.  
  674. FOR m.i = 1 TO FCOUNT()
  675.    m.fldname = FIELD(m.i)
  676.    WAIT WINDOW C_INDEXON + m.fldname + "." NOWAIT
  677.    IF !INLIST(TYPE(m.fldname),"M","G","P")
  678.       IF TYPE(m.fldname) = "C" AND LEN(&fldname) >= 99
  679.          INDEX ON SUBSTR(&fldname,1,99) TO (m.fldname)
  680.       ELSE
  681.          INDEX ON &fldname TAG (m.fldname)
  682.       ENDIF
  683.    ENDIF
  684. ENDFOR
  685. WAIT WINDOW C_INDEXFOR + m.fstem + C_ISCOMP NOWAIT
  686.  
  687. IF m.in_area <> SELECT()
  688.    USE
  689. ENDIF
  690. SELECT (m.in_area)
  691. IF m.comp_stat = "ON" OR m.comp_stat = "DB4"
  692.    SET COMPATIBLE TO DB4
  693. ENDIF
  694. IF m.safe_stat = "ON"
  695.    SET SAFETY ON
  696. ENDIF
  697. RETURN
  698.  
  699.  
  700. *!*****************************************************************
  701. *!
  702. *!      Procedure: MERGECTRL
  703. *!
  704. *!*****************************************************************
  705. PROCEDURE mergectrl
  706. * Merge the FoxApp control panel into user's screen to create a 
  707. * screen set.  This routine also forces all other screens to be
  708. * modal.
  709.  
  710. PARAMETERS m.pjxname, m.scxname, m.ctrl_y, m.ctrl_x
  711. PRIVATE pjxname, scxname, in_area, ctrl_y, ctrl_x, sname, ctrl_name
  712.  
  713. m.in_area = SELECT()
  714.  
  715. * name of the control panel screen, as it exists inside FOXAPP.APP
  716. * (or copied onto the disk, if regen is in effect)
  717. IF m.regen
  718.    m.ctrl_scx   = addbs(justpath(m.pjxname))+'APPCTRL.SCX'
  719. ELSE
  720.    m.ctrl_scx   = addbs(SYS(2004))+'FOXAPP\SCREENS\APPCTRL.SCX'
  721. ENDIF
  722. IF _MAC
  723.   m.ctrl_scx = SYS(2027, m.ctrl_scx)
  724. ENDIF
  725. IF FILE(m.ctrl_scx)
  726.    SELECT 0
  727.    USE (m.ctrl_scx) AGAIN ALIAS ctrlscx
  728.    LOCATE FOR ALLTRIM(platform) = ALLTRIM(m.app_platform) AND ;
  729.      objtype = 1
  730.    IF FOUND()
  731.      REPLACE ctrlscx.hpos WITH m.ctrl_x, ctrlscx.vpos WITH m.ctrl_y
  732.    ENDIF
  733.    USE
  734. ELSE
  735.    = FA_Alert(C_NOFIND + m.ctrl_scx)
  736.    RETURN   
  737. ENDIF
  738.  
  739. * Quit now if the project file is hiding.
  740. IF !FILE(m.pjxname)
  741.    RETURN
  742. ENDIF
  743.  
  744. * The lower case comparisons won't work if COLLATE <> MACHINE
  745. m.mcollate = SET("COLLATE")
  746. SET COLLATE TO "MACHINE"
  747.  
  748. IF USED(makealias(juststem(m.pjxname)))
  749.    * Open it again with the 'pjxfile' alias.
  750.    m.sname = makealias(juststem(m.pjxname))
  751.    SELECT (sname)
  752. ELSE
  753.    SELECT 0
  754. ENDIF
  755. USE (m.pjxname) ALIAS pjxfile
  756.  
  757. * Find the home directory
  758. LOCATE FOR UPPER(pjxfile.type) == "H" 
  759. IF FOUND()
  760.    m.homename = pjxfile.homedir
  761. ELSE
  762.    m.homename = CURDIR()
  763. ENDIF
  764.  
  765. * Locate the master screen set record
  766. LOCATE FOR UPPER(justfname(trimzero(pjxfile.name))) ;
  767.    == UPPER(forceext(justfname(m.scxname),'SPR')) AND pjxfile.type = 'S'
  768. IF FOUND()
  769.    m.setnum = pjxfile.setid
  770.    * Now locate the user screen SCX record
  771.    GOTO TOP
  772.    LOCATE FOR UPPER(justfname(trimzero(pjxfile.name)));
  773.        == UPPER(justfname(m.scxname)) ;
  774.       AND setid = m.setnum
  775.    IF FOUND()
  776.       * Use the coordinates stored in the screen file itself.  These
  777.       * reflect the changes that the user made to the screen location
  778.       * while inside FoxApp.
  779.       REPLACE pjxfile.arranged  WITH "WINDOWS"+CHR(0)+"N"+"N";
  780.          +PADL(LTRIM(STR(m.ctrl_y,4)),8)+PADL(LTRIM(STR(m.ctrl_x,4)),8) ;
  781.          +"MAC     "+CHR(0)+"N"+"N";
  782.          +PADL(LTRIM(STR(m.ctrl_y,4)),8)+PADL(LTRIM(STR(m.ctrl_x,4)),8)
  783.       REPLACE pjxfile.scrnorder WITH 0
  784.    ENDIF
  785.  
  786.    * Figure out how many screens are in this screen set (usually 1
  787.    * if this is a FoxApp generated app, but perhaps the user has 
  788.    * added some more screens).   
  789.    GOTO TOP
  790.    COUNT FOR pjxfile.setid = m.setnum TO m.ctrl_order
  791.  
  792.    * Put the control panel into the project as a screen set member 
  793.    * of the user's screen set.  If it is already there, update it.
  794.    * If not, create a new record and insert it.
  795.    GOTO TOP
  796.    LOCATE FOR justfname(UPPER(ALLTRIM(trimzero(pjxfile.name))))  ;
  797.       == UPPER(justfname(m.ctrl_scx)) 
  798.  
  799.    IF !FOUND()
  800.       APPEND BLANK
  801.    ELSE
  802.       m.ctrl_order = m.ctrl_order - 1   && don't count existing one
  803.    ENDIF
  804.  
  805.    * Update the project file to point to the control panel as part of the
  806.    * user screen set. 
  807.    IF m.regen
  808.       m.user_scx =   m.ctrl_scx
  809.    ELSE
  810.       m.user_scx =   SYS(2014,m.ctrl_scx,m.pjxname)
  811.    ENDIF
  812.    REPLACE pjxfile.name WITH m.user_scx, ;
  813.       pjxfile.TYPE      WITH 's',        ;
  814.       pjxfile.setid     WITH m.setnum,   ;
  815.       pjxfile.timestamp WITH 0,          ;
  816.       pjxfile.exclude   WITH .F.,        ;
  817.       pjxfile.scrnorder WITH m.ctrl_order
  818.    SET COLLATE TO "&mcollate"
  819. ELSE
  820.    * This means that something went badly wrong during BUILD PROJECT
  821.    = FA_Alert(C_FAILAPP)
  822.    SET DEFAULT TO (c_path)
  823.    SET COLLATE TO "&mcollate"
  824.    DO close_up
  825.    CANCEL
  826. ENDIF
  827.  
  828. USE
  829. SELECT (in_area)
  830.  
  831.  
  832. *!*****************************************************************
  833. *!
  834. *!      Procedure: INITDBFLIST
  835. *!
  836. *!*****************************************************************
  837. PROCEDURE initdbflist
  838. * Initialize the DBFLIST array 
  839. PRIVATE m.i,m.j
  840.  
  841. PUBLIC dbflist[m.numareas,m.numcols]
  842.  
  843. * Format the stem names for the popup
  844. FOR m.i = 1 TO m.numareas
  845.    dbflist[m.i,m.cstemnum]   = '\'   && start everything off disabled
  846.    dbflist[m.i,m.arranged]   = "N"   && user hasn't arranged the screen yet
  847.    dbflist[m.i,m.theFont]    = defaultfont
  848.    dbflist[m.i,m.cascadenum] = defaultcasc
  849. ENDFOR
  850.  
  851. * Initialize the other columns in the dbflist array, except screen
  852. * positions
  853. FOR m.i = 1 TO m.numareas
  854.    FOR m.j = 2 TO m.srownum - 1
  855.       dbflist[m.i,m.j] = ''
  856.    ENDFOR
  857. ENDFOR
  858.  
  859. * Initialize the screen positions
  860. FOR m.i = 1 TO m.numareas
  861.    dbflist[m.i,m.srownum] = ALLTRIM(STR(m.i,3))
  862.    dbflist[m.i,m.scolnum] = ALLTRIM(STR(m.i,3))
  863.    dbflist[m.i,m.erownum] = "6"                     && 6 rows high
  864.    dbflist[m.i,m.ecolnum] = ALLTRIM(STR(76-m.i,3))  && width
  865. ENDFOR
  866.  
  867. *!*****************************************************************
  868. *!
  869. *!      Procedure: OPENDBF
  870. *!
  871. *!*****************************************************************
  872. FUNCTION opendbf
  873. * Open a DBF and return the alias, or blanks if the database could 
  874. *   not be opened.
  875. PARAMETERS fname
  876. PRIVATE fname, stem, thealias, olderror
  877. IF FILE(m.fname)
  878.    m.stem = juststem(m.fname)
  879.    m.thealias = LEFT(m.stem,10)
  880.    m.thealias = CHRTRAN(m.thealias, ' ', '_')
  881.    IF USED(m.thealias)
  882.       SELECT (m.thealias)
  883.    ELSE
  884.       SELECT 0
  885.       m.fname = LOCFILE(m.fname,'DBF',C_LOCDBF)
  886.       IF EMPTY(m.fname)
  887.          RETURN ''
  888.       ELSE
  889.          m.olderror = ON("ERROR")
  890.          ON ERROR DO TEMPERR
  891.          USE (m.fname)
  892.          ON ERROR &olderror
  893.       ENDIF
  894.    ENDIF
  895.    RETURN ALIAS()
  896. ELSE
  897.    RETURN ''
  898. ENDIF
  899.  
  900. *!*****************************************************************
  901. *!
  902. *!      Procedure: CREATESCX
  903. *!
  904. *!*****************************************************************
  905. PROCEDURE createscx
  906. PRIVATE maxh, maxv, s_name
  907. * Create a quick-screen SCX file from the named database
  908. m.scxname = ALLTRIM(m.scxname)
  909. IF !EMPTY(opendbf(m.dbfname))
  910.    m.s_name = addbs(justpath(m.scxname)) + juststem(m.scxname)   && don't need extension
  911.    IF _MAC
  912.      WAIT WINDOW C_SCXCREA1 +SYS(2027,m.s_name) NOWAIT
  913.    ELSE
  914.      WAIT WINDOW C_SCXCREA1 + m.s_name NOWAIT
  915.    ENDIF
  916.    CREATE SCREEN (m.s_name) FROM (m.dbfname) ROW
  917.    m.scxname = forceext(m.scxname,"SCX")
  918.    IF FILE(m.scxname)
  919.       SHOW GET addscx DISABLE
  920.       SHOW GET modscx ENABLE
  921.    ENDIF
  922.    IF !EMPTY(m.scxname)
  923.       SELECT 0
  924.       USE (m.scxname) ALIAS fxscxname
  925.       locate for alltrim(platform) = m.app_platform and objtype = 1
  926.       REPLACE fxscxname.width WITH MIN(my_scols(),fxscxname.width)
  927.       m.maxh = width
  928.       m.maxv = height
  929.  
  930.       IF relateddbfs() AND UPPER(dbflist[1,m.arranged]) = "N"
  931.          * No screen position yet defined for the main database.  Center it,
  932.          * unless there are lots of related databases.  If there are, put
  933.          * it closer to the top of the screen.
  934.          IF m.nextdbf < 3  && just one database used in app
  935.             m.start_row = MAX(INT(my_srows()/2-height/2),0)
  936.             m.start_col = MAX(INT(my_scols()/2-width/2),0)
  937.          ELSE
  938.             m.start_row = 1
  939.             m.start_col = MAX(INT(my_scols()/2-width/2),0)
  940.          ENDIF
  941.       ELSE   && center the screen horizontally if it hasn't been arranged.
  942.          m.start_row = 1
  943.          m.start_col = MAX(INT(my_scols()/2-width/2),0)
  944.       ENDIF
  945.       m.start_row = MAX(0,m.start_row)
  946.       m.start_col = MAX(0,m.start_col)
  947.       
  948.       REPLACE ALL fxscxname.vpos WITH m.start_row, fxscxname.hpos WITH m.start_col;
  949.          FOR objtype = 1 AND platform = getplat()
  950.          
  951.       * Make some space around the fields
  952.       REPLACE ALL fxscxname.hpos WITH fxscxname.hpos + 1,;
  953.          fxscxname.vpos WITH fxscxname.vpos + 1 ;
  954.          FOR objtype > 4 AND objtype <> 23 AND platform = getplat()
  955.          
  956.       SCAN FOR objtype > 4 and objtype <> 23
  957.          m.thish = fxscxname.hpos + fxscxname.width ;
  958.           * FONTMETRIC(6,fxscxname.fontface,fxscxname.fontsize, ;
  959.              whatstyle(fxscxname.fontstyle)) ;
  960.           /  FONTMETRIC(6,WFONT(1,""),WFONT(2,""),WFONT(3,""))
  961.          m.thisv = fxscxname.vpos + fxscxname.height ;
  962.           * FONTMETRIC(1,fxscxname.fontface,fxscxname.fontsize, ;
  963.              whatstyle(fxscxname.fontstyle)) ;
  964.           /  FONTMETRIC(1,WFONT(1,""),WFONT(2,""),WFONT(3,""))
  965.          m.maxh = MAX(m.thish,m.maxh)
  966.          m.maxv = MAX(m.thisv,m.maxv)
  967.       ENDSCAN
  968.       GOTO TOP
  969.       REPLACE fxscxname.center WITH .T.,;
  970.          fxscxname.width WITH m.maxh + 6, ;
  971.          fxscxname.height WITH m.maxv + 1,;
  972.          fxscxname.name WITH makealias(juststem(m.scxname)), ;
  973.          fxscxname.style WITH 2,;
  974.          fxscxname.border WITH 1,;
  975.          fxscxname.tag WITH '" '+makealias(juststem(m.scxname))+' "'
  976.          
  977.       IF relateddbfs()
  978.          dbflist[1,m.srownum] = ALLTRIM(STR(m.start_row,4))
  979.          dbflist[1,m.scolnum] = ALLTRIM(STR(m.start_col,4))
  980.          dbflist[1,m.erownum] = ALLTRIM(STR(fxscxname.height,4))
  981.          dbflist[1,m.ecolnum] = ALLTRIM(STR(fxscxname.width,4))
  982.       ENDIF
  983.                
  984.       USE
  985.    ENDIF
  986.    WAIT WINDOW C_SCXMADE NOWAIT
  987. ELSE
  988.    DO errshow WITH C_DBFNOOPN,10
  989. ENDIF
  990. SHOW GETS
  991. RETURN
  992.  
  993.  
  994. *!*****************************************************************
  995. *!
  996. *!      Procedure: FILATTR
  997. *!
  998. *!*****************************************************************
  999. FUNCTION filattr
  1000. * Return file attributes of "filname"
  1001. PARAMETER m.filname
  1002. PRIVATE filarray, m.filpos
  1003. m.filname = UPPER(ALLTRIM(m.filname))
  1004. IF ADIR(filarray,m.filname) > 0
  1005.    m.filpos = ASCAN(filarray,justfname(m.filname))
  1006.    IF m.filpos > 0
  1007.       RETURN filarray[m.filpos,5]
  1008.    ENDIF
  1009. ENDIF
  1010. RETURN ''
  1011. *!*****************************************************************
  1012. *!
  1013. *!      Procedure: RELATEDDBFS
  1014. *!
  1015. *!*****************************************************************
  1016. FUNCTION relateddbfs
  1017. * RETURN T if related DBF files have been defined through FoxApp
  1018. RETURN m.nextdbf > 2
  1019.  
  1020. *!*****************************************************************
  1021. *!
  1022. *!      Procedure: GETDBFLIST
  1023. *!
  1024. *!*****************************************************************
  1025. FUNCTION getdbflist
  1026. * Retrieve dbflist from resource file
  1027.  
  1028. PARAMETERS cstem
  1029. PRIVATE m.nextdbf, m.in_area, m.cstem, m.i, m.j, m.j1_at, m.j2_at
  1030.  
  1031. IF !FILE(SYS(2005))    && resource file not found.
  1032.    RETURN 0
  1033. ENDIF
  1034.  
  1035. m.nextdbf = 0
  1036. m.in_area = SELECT(0)
  1037.  
  1038. m.cstem = UPPER(ALLTRIM(m.cstem))
  1039. IF EMPTY(m.cstem)
  1040.    RETURN 0
  1041. ENDIF
  1042.  
  1043. m.memwidth = SET('MEMOWIDTH')
  1044. SET MEMOWIDTH TO 255
  1045.  
  1046. SELECT 0
  1047. USE (SYS(2005)) AGAIN ALIAS rsc
  1048.  
  1049. LOCATE FOR UPPER(ALLTRIM(rsc.type)) == m.rsctype;
  1050.    AND UPPER(ALLTRIM(rsc.id)) == 'DBFLIST' ;
  1051.    AND UPPER(ALLTRIM(rsc.name)) == m.cstem ;
  1052.    AND !DELETED()
  1053.  
  1054. IF FOUND() AND !EMPTY(rsc.data)
  1055.    WAIT WINDOW "Retrieving stored relationships." NOWAIT
  1056.  
  1057.    IF TYPE("dbflist") = "U"
  1058.       DO initdbflist
  1059.    ENDIF
  1060.  
  1061.    * First get the position of the control panel
  1062.    m.ctrlline = MLINE(rsc.data,1)
  1063.    m.ctrlrow  = VAL(SUBSTR(m.ctrlline,1,AT(';',m.ctrlline)-1))
  1064.    m.ctrlcol  = VAL(SUBSTR(m.ctrlline,AT(';',m.ctrlline)+1))
  1065.    m.ctrlrow  = MIN(my_srows()-3,m.ctrlrow)
  1066.    m.ctrlcol  = MIN(my_scols()-3,m.ctrlcol)
  1067.  
  1068.    FOR m.i = 1 TO m.numareas
  1069.       m.this_dbf = MLINE(rsc.data,m.i+1)
  1070.       FOR m.j = 1 TO m.numcols
  1071.          DO CASE
  1072.          CASE m.j = 1
  1073.             IF AT(';',m.this_dbf) = 1
  1074.                dbflist[m.i,m.j] = '\'   && make this empty area disabled in the list
  1075.             ELSE
  1076.                dbflist[m.i,m.j] = SUBSTR(m.this_dbf,1,AT(';',m.this_dbf)-1)
  1077.             ENDIF
  1078.          CASE m.j = m.numcols
  1079.             dbflist[m.i,m.j] = SUBSTR(m.this_dbf,AT(';',m.this_dbf,m.numcols-1)+1)
  1080.          OTHERWISE
  1081.             m.j1_at = AT(';',m.this_dbf,m.j-1)
  1082.             m.j2_at = AT(';',m.this_dbf,m.j)
  1083.             dbflist[m.i,m.j] = SUBSTR(m.this_dbf,m.j1_at + 1,m.j2_at - m.j1_at - 1)
  1084.          ENDCASE
  1085.  
  1086.       ENDFOR
  1087.  
  1088.       IF !EMPTY(dbflist[m.i,m.cstemnum])       ;
  1089.             AND dbflist[m.i,m.cstemnum] <> '\' ;
  1090.             AND !USED(dbflist[m.i,m.cstemnum])
  1091.  
  1092.          IF !FILE(dbflist[m.i,m.cdbfnum])
  1093.             * See if we can find it anywhere along the path
  1094.             IF FILE(FULLPATH(dbflist[m.i,m.cdbfnum]))
  1095.                dbflist[m.i,m.cdbfnum] = FULLPATH(dbflist[m.i,m.cdbfnum])
  1096.                dbflist[m.i,m.cstemnum] = makealias(juststem(dbflist[m.i,m.cdbfnum]))
  1097.             ELSE   && it is nowhere to be found.  Ask where it is.
  1098.                dbflist[m.i,m.cdbfnum] = GETFILE('DBF',;
  1099.                   C_WHERE +juststem(dbflist[m.i,m.cdbfnum])+'?')
  1100.                IF EMPTY(dbflist[m.i,m.cdbfnum]) OR !FILE(dbflist[m.i,m.cdbfnum])
  1101.                   DO alert WITH dbflist[m.i,m.cstemnum]+ C_NOTFND
  1102.                   DO close_up
  1103.                ENDIF
  1104.             ENDIF
  1105.          ENDIF
  1106.  
  1107.          dbflist[m.i,m.cstemnum] = makealias(juststem(dbflist[i,m.cdbfnum]))
  1108.  
  1109.          IF FILE(dbflist[m.i,m.cdbfnum])
  1110.             * full name of database including path
  1111.             SELECT 0
  1112.             USE (dbflist[m.i,m.cdbfnum]) AGAIN
  1113.          ENDIF
  1114.  
  1115.          * Ensure that this database has a corresponding CDX file
  1116.          DO makecdx WITH dbflist[m.i,m.cdbfnum], dbflist[m.i,m.cfldnum]
  1117.       ENDIF
  1118.  
  1119.       * Record the first open database area
  1120.       IF !EMPTY(dbflist[m.i,m.cstemnum]) AND dbflist[m.i,m.cstemnum] <> '\'
  1121.          m.nextdbf = m.i+1
  1122.       ENDIF
  1123.  
  1124.    ENDFOR
  1125.    WAIT CLEAR
  1126. ENDIF
  1127. SELECT rsc
  1128. USE
  1129. SELECT (m.in_area)
  1130. SET MEMOWIDTH TO m.memwidth
  1131.  
  1132. RETURN m.nextdbf
  1133.  
  1134.  
  1135. *!*****************************************************************
  1136. *!
  1137. *!      Procedure: PUTDBFLIST
  1138. *!
  1139. *!*****************************************************************
  1140. FUNCTION putdbflist
  1141. PARAMETERS cstem
  1142. PRIVATE m.cstem, m.in_area, m.i, m.j, m.repl_str
  1143.  
  1144. * Store the dbflist array in the resource file
  1145. * The format for storing the dbflist array in the data memo field is:
  1146. *    string;string;string;string... CHR(13)+CHR(10)
  1147.  
  1148. IF !FILE(SYS(2005)) OR EMPTY(m.cstem)
  1149.    RETURN 0
  1150. ENDIF
  1151.  
  1152. * Don't update if this is a read-only file
  1153. * SYS(2026,filename) is a last-minute function that returns 'Y' if the 
  1154. * file is both open and marked read-only, for any reason (e.g., it's in an APP, it's
  1155. * the resource file for another instance of FoxPro, etc.)
  1156. IF 'R' $ filattr(SYS(2005)) OR SYS(2026,SYS(2005)) <> "N"
  1157.    WAIT WINDOW C_RSCRO NOWAIT
  1158.    m.storersc = .F.
  1159.    =INKEY(2)
  1160.    RETURN 0
  1161. ENDIF
  1162.  
  1163. m.cstem = UPPER(ALLTRIM(m.cstem))
  1164. m.in_area = SELECT()
  1165.  
  1166. SELECT 0
  1167. USE (SYS(2005)) AGAIN ALIAS rsc
  1168. LOCATE FOR UPPER(ALLTRIM(rsc.type)) == m.rsctype ;
  1169.    AND UPPER(ALLTRIM(rsc.id)) == 'DBFLIST' ;
  1170.    AND UPPER(ALLTRIM(rsc.name)) == m.cstem
  1171. IF !FOUND()
  1172.    APPEND BLANK
  1173. ELSE
  1174.    IF rsc.readonly
  1175.       WAIT WINDOW C_RSCREC NOWAIT
  1176.       =INKEY(1)   && wait 1 second
  1177.       USE
  1178.       SELECT (m.in_area)
  1179.       RETURN 0
  1180.    ENDIF
  1181. ENDIF
  1182.  
  1183. * Write out the control panel upper left coordinates first
  1184. m.repl_str = ALLTRIM(STR(m.ctrlrow,7,3))+';';
  1185.    +ALLTRIM(STR(m.ctrlcol,7,3))+CHR(13)+CHR(10)
  1186.  
  1187. * Write the dbflist data for each row/col
  1188. FOR m.i = 1 TO m.numareas
  1189.    FOR m.j = 1 TO m.numcols
  1190.       m.repl_str = m.repl_str +IIF(m.j=1,'',';') ;
  1191.          + IIF(INLIST(TYPE("dbflist[m.i,m.j]"),'U','L'),'',TRIM(dbflist[m.i,m.j]));
  1192.          + IIF(m.j=m.numcols,CHR(13)+CHR(10),'')
  1193.    ENDFOR
  1194. ENDFOR
  1195. REPLACE rsc.data WITH m.repl_str, ;
  1196.    rsc.type      WITH m.rsctype, ;
  1197.    rsc.id        WITH 'DBFLIST',  ;
  1198.    rsc.name      WITH m.cstem,    ;
  1199.    rsc.ckval     WITH VAL(SYS(2007,rsc.data)),;
  1200.    rsc.updated   WITH DATE(),;
  1201.    rsc.readonly  WITH .F.
  1202.  
  1203. * Set the flag that notifies the rest of the program that the 
  1204. * relations have been stored in the resource file.
  1205. rsc_stored = .T.
  1206.  
  1207. USE
  1208. SELECT (m.in_area)
  1209. RETURN 0
  1210.  
  1211. *!*****************************************************************
  1212. *!
  1213. *!      Procedure: MAKECDX
  1214. *!
  1215. *!*****************************************************************
  1216. PROCEDURE makecdx
  1217. parameter filname, tagname
  1218. * Ensure that filename has a CDX file with a tag name of tagname
  1219. PRIVATE m.filname, m.tagname, m.cdxname, m.i, m.justtag
  1220.  
  1221. justtag = m.tagname
  1222. * Strip off alias names from fields like parent.fldname
  1223. IF AT('.',m.justtag) > 0
  1224.    m.justtag = ALLTRIM(UPPER(SUBSTR(m.justtag,AT('.',m.justtag)+1)))
  1225. ENDIF
  1226.  
  1227. cdxname = forceext(m.filname,'CDX')
  1228. =opendbf(m.filname)
  1229. DO CASE
  1230. CASE !FILE(m.cdxname)
  1231.    DO invert WITH m.filname
  1232. OTHERWISE
  1233.    * Cycle through the tags looking for one to match the key field
  1234.    m.i = 1
  1235.    DO WHILE (TAG(m.cdxname,m.i) != m.justtag) ;
  1236.          AND !EMPTY(TAG(m.cdxname,m.i))
  1237.       m.i = m.i + 1
  1238.    ENDDO
  1239.    IF EMPTY(TAG(m.cdxname,m.i))
  1240.       DO invert WITH m.filname
  1241.    ENDIF
  1242. ENDCASE
  1243.  
  1244.  
  1245.  
  1246. *!*****************************************************************
  1247. *!
  1248. *!      Procedure: DEFINEWINDOW
  1249. *!
  1250. *!*****************************************************************
  1251. PROCEDURE definewindow
  1252. * Defines a window for use by the error reporting routines
  1253.  
  1254. parameter m.hight, m.width, m.name, m.scheme
  1255. PRIVATE m.fromrow, m.fromcol, m.torow, m.tocol
  1256.  
  1257. m.fromrow = INT((srow()-m.hight)/2)
  1258. m.fromcol = INT((scol()-m.width)/2)
  1259. m.torow   = m.fromrow + m.hight
  1260. m.tocol   = m.fromcol + m.width
  1261.  
  1262. DEFINE WINDOW (m.name);
  1263.    FROM m.fromrow, m.fromcol TO m.torow, m.tocol;
  1264.    FLOAT NOGROW NOCLOSE NOZOOM SHADOW DOUBLE;
  1265.    COLOR SCHEME (m.scheme)
  1266.  
  1267. RETURN
  1268. *!*****************************************************************
  1269. *!
  1270. *!      Function: Maptochar
  1271. *!
  1272. *!*****************************************************************
  1273. FUNCTION maptochar
  1274. * Maps the numeric values used in SCX files to the string that FONTMETRIC needs
  1275. PARAMETERS stylenum
  1276. DO CASE
  1277. CASE m.stylenum = 0
  1278.    RETURN ""
  1279. CASE m.stylenum = 1
  1280.    RETURN "B"
  1281. CASE m.stylenum = 2
  1282.    RETURN "I"
  1283. CASE m.stylenum = 3
  1284.    RETURN "BI"
  1285. OTHERWISE
  1286.    RETURN ""   
  1287. ENDCASE            
  1288.  
  1289. *!*****************************************************************
  1290. *!
  1291. *!      Function: TRANFONT
  1292. *!
  1293. *!*****************************************************************
  1294. FUNCTION tranfont
  1295. * Translates coordinates from one font to another
  1296. PARAMETERS units, code, fromfont, fromsize, fromstyle, tofont, tosize, tostyle
  1297. * Units is the width/height term
  1298. * code = 1 for height, 6 for width
  1299. PRIVATE strflag, retval
  1300.  
  1301. IF PARAMETERS() < 8
  1302.    m.tostyle = WFONT(3,"")
  1303. ENDIF
  1304. IF PARAMETERS() < 7
  1305.    m.tosize = WFONT(2,"")
  1306. ENDIF
  1307. IF PARAMETERS() < 6
  1308.    m.tofont = WFONT(1,"")
  1309. ENDIF
  1310. m.strflag = .F.
  1311. IF TYPE("units") = "C"
  1312.    m.units = VAL(m.units)
  1313.    m.strflag = .T.
  1314. ENDIF   
  1315. IF TYPE("fromstyle") = "N"
  1316.    m.fromstyle = MapToChar(m.fromstyle)
  1317. ENDIF
  1318. IF TYPE("tostyle") = "N"
  1319.    m.tostyle = MapToChar(m.tostyle)
  1320. ENDIF
  1321. IF TYPE("tosize") = "C"
  1322.    m.tosize = VAL(m.tosize)
  1323. ENDIF
  1324. IF TYPE("fromsize") = "C"
  1325.    m.fromsize = VAL(m.fromsize)
  1326. ENDIF
  1327.     
  1328. m.tofont = FONTMETRIC(m.code,m.tofont, m.tosize, m.tostyle)
  1329. m.fromfont = FONTMETRIC(m.code,m.fromfont,m.fromsize,m.fromstyle)
  1330. IF m.tofont <> 0     && avoid division by zero
  1331.    retval =  m.units *  m.fromfont / m.tofont * 1.00
  1332.    IF strflag
  1333.       retval = ALLTRIM(STR(retval,10))
  1334.    ENDIF
  1335. ELSE
  1336.    retval = IIF(strflag,"0",0)
  1337. ENDIF
  1338. RETURN retval
  1339. *!*****************************************************************
  1340. *!
  1341. *!      Procedure: ARRSAVE
  1342. *!
  1343. *!*****************************************************************
  1344. PROCEDURE arrsave
  1345. * Save arrangement of windows and return to dbfselect screen
  1346.  
  1347. * Set exit flag for READ VALID--can't be PRIVATE
  1348. m.arrexflg = .T.
  1349.  
  1350. * Record window coordinates and release all the application windows
  1351. IF WEXIST('CTRL')
  1352.   m.ctrlrow = WLROW('CTRL')
  1353.   m.ctrlcol = WLCOL('CTRL')
  1354.   RELEASE WINDOW ctrl
  1355. ENDIF
  1356.  
  1357. * Store the coordinates for the main window
  1358. IF !EMPTY(dbflist[1,m.cstemnum]) AND dbflist[1,m.cstemnum] <> '\'
  1359.    dbflist[1,m.srownum] = ALLTRIM(STR(WLROW(dbflist[1,m.cstemnum]),7,3))
  1360.    dbflist[1,m.scolnum] = ALLTRIM(STR(WLCOL(dbflist[1,m.cstemnum]),7,3))
  1361.    dbflist[1,m.erownum] = ALLTRIM(STR(WROWS(dbflist[1,m.cstemnum]),7,3))
  1362.    dbflist[1,m.ecolnum] = ALLTRIM(STR(WCOLS(dbflist[1,m.cstemnum]),7,3))
  1363.    RELEASE WINDOW (dbflist[1,m.cstemnum])
  1364. ENDIF
  1365. dbflist[1,m.arranged] = "Y"
  1366.  
  1367. FOR m.i = 2 TO m.numareas
  1368.    IF !EMPTY(dbflist[m.i,m.cstemnum]) AND dbflist[m.i,m.cstemnum] <> '\'
  1369.       dbflist[m.i,m.srownum] = ALLTRIM(STR(WLROW(dbflist[m.i,m.cstemnum]),7,3))
  1370.       dbflist[m.i,m.scolnum] = ALLTRIM(STR(WLCOL(dbflist[m.i,m.cstemnum]),7,3))
  1371.       * WROWS() reports one more pixel than we want.
  1372.       dbflist[m.i,m.erownum] = ALLTRIM(STR(WROWS(dbflist[m.i,m.cstemnum]) - 1/FONTMETRIC(1),7,3))
  1373.       dbflist[m.i,m.ecolnum] = ALLTRIM(STR(WCOLS(dbflist[m.i,m.cstemnum]),7,3))
  1374.       RELEASE WINDOW (dbflist[m.i,m.cstemnum])
  1375.    ENDIF
  1376.    dbflist[m.i,m.arranged] = "Y"
  1377. ENDFOR
  1378.  
  1379. * Store relations into resource file if needed
  1380. IF TYPE("DBFLIST") <> "U" AND !rsc_stored AND m.storersc
  1381.    WAIT WINDOW C_WINPOS NOWAIT
  1382.    DO putdbflist WITH dbflist[1,1]
  1383. ENDIF
  1384.  
  1385. * Restore environment 
  1386. POP MENU _msysmenu
  1387. SHOW WINDOW appgen
  1388. ACTIVATE WINDOW appgen
  1389.  
  1390. CLEAR READ
  1391.  
  1392. RETURN
  1393.  
  1394. *!*****************************************************************
  1395. *!
  1396. *!      Function: PUTFONTVAL
  1397. *!
  1398. *!*****************************************************************
  1399. FUNCTION putfontval
  1400. PARAMETER m.value, m.code, m.i
  1401.  
  1402. RETURN TRANFONT(m.value, m.code, WFONT(1,""), WFONT(2,""), WFONT(3,""), ;
  1403.    term(dbflist[m.i,m.thefont],1), VAL(term(dbflist[m.i,m.thefont],2)), ;
  1404.    term(dbflist[m.i,m.thefont],3) )
  1405.  
  1406. *!*****************************************************************
  1407. *!
  1408. *!      Procedure: ARREXIT
  1409. *!
  1410. *!*****************************************************************
  1411. PROCEDURE arrexit
  1412. * Exit without saving window positions
  1413. PRIVATE m.i
  1414. * Set exit flag for READ VALID--can't be PRIVATE
  1415. m.arrexflg = .T.
  1416.  
  1417. * Release all the application windows
  1418. RELEASE WINDOW ctrl
  1419. FOR m.i = 1 TO m.numareas
  1420.    IF !EMPTY(dbflist[m.i,m.cstemnum]) AND dbflist[m.i,m.cstemnum] <> '\'
  1421.       RELEASE WINDOW (dbflist[m.i,m.cstemnum])
  1422.    ENDIF
  1423. ENDFOR
  1424.  
  1425. * Restore environment 
  1426. POP MENU _msysmenu
  1427. SHOW WINDOW appgen
  1428.  
  1429. ACTIVATE WINDOW appgen
  1430.  
  1431. CLEAR READ
  1432.  
  1433. RETURN
  1434.  
  1435. FUNCTION getplat
  1436. DO CASE
  1437. CASE _MAC
  1438.    RETURN "MAC"
  1439. CASE _WINDOWS
  1440.    RETURN "WINDOWS"
  1441. CASE _DOS
  1442.    RETURN "DOS"
  1443. CASE _UNIX
  1444.    RETURN "UNIX"
  1445. OTHERWISE
  1446.    RETURN "UNKNOWN"
  1447. ENDCASE
  1448.  
  1449. *!*****************************************************************
  1450. *!
  1451. *!      Procedure: HASCHILD
  1452. *!
  1453. *!*****************************************************************
  1454. FUNCTION haschild
  1455. * Does the database at position "dbfnum" of DBFLIST have a child
  1456. * table?
  1457. parameter dbfnum
  1458. PRIVATE m.dbfnum, m.i
  1459.  
  1460. * See if another database has this one as its parent
  1461. FOR m.i = 1 TO m.numareas
  1462.    IF ALLTRIM(dbflist[m.i,m.pdbfnum]) ;
  1463.          == ALLTRIM(dbflist[m.dbfnum,m.cstemnum])
  1464.       RETURN .T.
  1465.    ENDIF
  1466. ENDFOR
  1467. RETURN .F.
  1468.  
  1469.  
  1470. *!*****************************************************************
  1471. *!
  1472. *!      Procedure: ACTWIN
  1473. *!
  1474. *!*****************************************************************
  1475. FUNCTION actwin
  1476. * Activate window wind_name
  1477.  
  1478. parameter wind_name
  1479. PRIVATE ALL
  1480. wind_name = UPPER(ALLTRIM(m.wind_name))
  1481. IF !EMPTY(m.wind_name) AND WEXIST(m.wind_name)
  1482.    ACTIVATE WINDOW (m.wind_name)
  1483. ENDIF
  1484. RETURN ''
  1485.  
  1486. *!*****************************************************************
  1487. *!
  1488. *!      Procedure: ERRSHOW
  1489. *!
  1490. *!*****************************************************************
  1491. PROCEDURE errshow
  1492. * Procedure to display an error message 
  1493.  
  1494. parameter m.messg, m.lineno
  1495. PRIVATE ALL
  1496. DO definewindow WITH 4, 70, "ALERT", 7
  1497. ACTIVATE WINDOW alert
  1498.  
  1499. SET CURSOR OFF
  1500. @ 0,0 CLEAR
  1501. @ 1,0 SAY PADC(ALLTRIM(m.messg), WCOLS())
  1502. WAIT ""
  1503. SET CURSOR ON
  1504.  
  1505. RELEASE WINDOW alert
  1506. RETURN
  1507.  
  1508. *!*****************************************************************
  1509. *!
  1510. *!      Procedure: ALERT
  1511. *!
  1512. *!*****************************************************************
  1513. PROCEDURE alert
  1514. * Display an error message, automatically sizing the message window
  1515. *    as necessary.  Semicolons in "strg" mean "new line".
  1516. PARAMETERS strg
  1517. PRIVATE m.in_talk, m.numlines, m.i, m.remain, m.in_cons
  1518.  
  1519. m.in_talk = SET('TALK')
  1520. SET TALK OFF
  1521. m.in_cons = SET('CONSOLE')
  1522.  
  1523. m.numlines = OCCURS(';',m.strg) + 1
  1524.  
  1525. DIMENSION alert_arry[m.numlines]
  1526. m.remain = m.strg
  1527. m.maxlen = 0
  1528. FOR i = 1 TO m.numlines
  1529.    IF AT(';',m.remain) > 0
  1530.       alert_arry[i] = SUBSTR(m.remain,1,AT(';',m.remain)-1)
  1531.       alert_arry[i] = CHRTRAN(alert_arry[i],';','')
  1532.       m.remain = SUBSTR(m.remain,AT(';',m.remain)+1)
  1533.    ELSE
  1534.       alert_arry[i] = m.remain
  1535.       m.remain = ''
  1536.    ENDIF
  1537.    IF LEN(alert_arry[i]) > my_scols() - 6
  1538.       alert_arry[i] = SUBSTR(alert_arry[i],1,my_scols()-6)
  1539.    ENDIF
  1540.    IF LEN(alert_arry[i]) > m.maxlen
  1541.       m.maxlen = LEN(alert_arry[i])
  1542.    ENDIF
  1543. ENDFOR
  1544.  
  1545. m.top_row = INT( (my_srows() - 4 - m.numlines) / 2)
  1546. m.bot_row = m.top_row + 3 + m.numlines
  1547.  
  1548. m.top_col = INT((my_scols() - m.maxlen - 6) / 2)
  1549. m.bot_col = m.top_col + m.maxlen + 6
  1550.  
  1551. DEFINE WINDOW alert FROM m.top_row,m.top_col TO m.bot_row,m.bot_col;
  1552.    DOUBLE COLOR SCHEME 7
  1553. ACTIVATE WINDOW alert
  1554.  
  1555. FOR m.i = 1 TO m.numlines
  1556.    @ m.i,3 SAY PADC(alert_arry[m.i],m.maxlen)
  1557. ENDFOR
  1558.  
  1559. CLEAR TYPEAHEAD
  1560. SET CONSOLE OFF
  1561. m.keycode = 0
  1562. DO WHILE m.keycode = 0
  1563.    m.keycode = INKEY(0,'HM')
  1564. ENDDO
  1565. SET CONSOLE ON
  1566.  
  1567. RELEASE WINDOW alert
  1568.  
  1569. IF m.in_talk = "ON"
  1570.    SET TALK ON
  1571. ENDIF
  1572. IF m.in_cons = "OFF"
  1573.    SET CONSOLE OFF
  1574. ENDIF
  1575.  
  1576. *!*****************************************************************
  1577. *!
  1578. *!      Procedure: APPERROR
  1579. *!
  1580. *!*****************************************************************
  1581. PROCEDURE apperror
  1582. * Simple ON ERROR routine for FoxApp application
  1583.  
  1584. PARAMETERS e_program,e_message,e_source,e_lineno,e_error
  1585. ON ERROR
  1586. m.e_source = ALLTRIM(m.e_source)
  1587. DO CASE
  1588. CASE m.e_error = 1707     && CDX not found.  Ignore it.
  1589.    RETURN
  1590. OTHERWISE
  1591.    DO alert WITH C_ERRLINE + ALLTRIM(STR(m.e_lineno,5))+';' ;
  1592.       +C_ERRPRG + m.e_program +';' ;
  1593.       +C_ERRERR + m.e_message +';' ;
  1594.       +C_ERRSRC + IIF(LEN(m.e_source)<50,;
  1595.       m.e_source,SUBSTR(m.e_source,1,50)+'...')
  1596.    DO close_up
  1597. ENDCASE
  1598. RETURN
  1599.  
  1600. *!*****************************************************************
  1601. *!
  1602. *!      Procedure: APPESCAPE
  1603. *!
  1604. *!*****************************************************************
  1605. PROCEDURE appescape
  1606. * Simple ON ESCAPE routine for FoxApp application
  1607.  
  1608. PARAMETERS e_program,e_message,e_source,e_lineno,e_error
  1609. WAIT WINDOW C_ESCPRESS NOWAIT
  1610. =INKEY(1.5)
  1611. m.m_quitting = .T.
  1612. * Enable the Window pad
  1613. SET SKIP OF PAD _msm_windo OF _msysmenu .F.
  1614.  
  1615. CLEAR READ
  1616. DO close_up
  1617. RETURN
  1618.  
  1619. *!*****************************************************************************
  1620. *!
  1621. *!       Function: WHATSTYLE
  1622. *!
  1623. *!      Called by: ALLCHARTOGRAPHIC   (procedure in TRANSPRT.PRG)
  1624. *!               : FILLININFO         (procedure in TRANSPRT.PRG)
  1625. *!               : ITEMSINBOXES       (procedure in TRANSPRT.PRG)
  1626. *!               : GETWINDFONT        (procedure in TRANSPRT.PRG)
  1627. *!               : ADJHEIGHTANDWIDTH  (procedure in TRANSPRT.PRG)
  1628. *!
  1629. *!*****************************************************************************
  1630. FUNCTION whatstyle
  1631. PARAMETER m.stylenum
  1632. IF NOT EMPTY(m.stylenum)
  1633.    DO CASE
  1634.    CASE m.stylenum = 1
  1635.       RETURN "B"
  1636.    CASE m.stylenum = 2
  1637.       RETURN "I"
  1638.    CASE m.stylenum = 3
  1639.       RETURN "BI"
  1640.    ENDCASE
  1641. ELSE
  1642.    RETURN ""
  1643. ENDIF
  1644.  
  1645. *!*****************************************************************************
  1646. *!
  1647. *!    Procedure: FNADDQUOTES
  1648. *!
  1649. *!*****************************************************************************
  1650. FUNCTION fnaddquotes
  1651. PARAMETER m.fname
  1652.  
  1653. DO CASE
  1654. CASE INLIST(LEFT(m.fname,1), "'", '"', '[')
  1655.    RETURN m.fname
  1656. CASE AT('"', m.fname) = 0
  1657.    RETURN '"' + m.fname + '"'
  1658. CASE AT("'", m.fname) = 0
  1659.    RETURN "'" + m.fname + "'"
  1660. CASE AT("[", m.fname) = 0 AND AT("]", m.fname) = 0
  1661.    RETURN "[" + m.fname + "]"
  1662. OTHERWISE
  1663.    RETURN m.fname      
  1664. ENDCASE
  1665.  
  1666. *!*****************************************************************************
  1667. *!
  1668. *!    Procedure: MAKEALIAS
  1669. *!
  1670. *!*****************************************************************************
  1671. FUNCTION makealias
  1672. PARAMETER filname
  1673. m.filname = UPPER(ALLTRIM(m.filname))
  1674. m.filname = CHRTRAN(m.filname, ' ', '_')
  1675. m.filname = LEFT(m.filname, 10)
  1676. RETURN m.filname
  1677.  
  1678. *!*****************************************************************************
  1679. *!
  1680. *!    Procedure: ISWIZ
  1681. *!
  1682. *!*****************************************************************************
  1683. FUNCTION iswiz
  1684. PARAMETER strg
  1685. * Was this screen created by a FoxPro wizard?
  1686. RETURN IIF("*~ WIZARDSCREEN" $ UPPER(m.strg), .T., .F.)
  1687.  
  1688. *!*****************************************************************************
  1689. *!
  1690. *!    Function: MY_SROWS
  1691. *!
  1692. *!*****************************************************************************
  1693. FUNCTION my_srows
  1694. IF _MAC
  1695.    RETURN (SYSMETRIC(2) - SYSMETRIC(20) ) / FONTMETRIC(1,m.g_dfltfface, m.g_dfltfsize, m.g_dfltfstyle)
  1696. ELSE
  1697.    RETURN SROWS()
  1698. ENDIF   
  1699.  
  1700. *!*****************************************************************************
  1701. *!
  1702. *!    Function: MY_SCOLS
  1703. *!
  1704. *!*****************************************************************************
  1705. FUNCTION my_scols
  1706. DO CASE
  1707. CASE _MAC
  1708.    RETURN SYSMETRIC(1) / FONTMETRIC(6,m.g_dfltfface, m.g_dfltfsize, m.g_dfltfstyle)
  1709. CASE _DOS
  1710.    RETURN SCOLS()
  1711. OTHERWISE
  1712.    RETURN SCOLS()
  1713. ENDCASE   
  1714.  
  1715.  
  1716. PROCEDURE DbfNameWhen
  1717. * WHEN clause from m.dbfname get in appscx
  1718. *------------------------------------------------------------------
  1719. m.origname = m.dbfname
  1720. IF !EMPTY(m.dbfname) AND _MAC
  1721.    m.dbfname = SYS(2027, m.dbfname)
  1722. ENDIF   
  1723. m.dbfname  = PADR(m.dbfname,m.apppathlen)
  1724. SHOW GETS
  1725. SET CURSOR ON
  1726. RETURN .T.
  1727.  
  1728.  
  1729. PROCEDURE DbfNameValid
  1730. * VALID clause from m.dbfname get in appscx
  1731. *------------------------------------------------------------------
  1732. *  #NAME dbfvalid
  1733.  
  1734. m.dbfname = UPPER(ALLTRIM(m.dbfname))
  1735. IF m.dbfname == m.origname
  1736.    * do nothing--make sure comparison is "==" however. 
  1737. ELSE
  1738.    * Database name changed.  Check resource file again.
  1739.    rsc_check = .F.
  1740. ENDIF
  1741.  
  1742. SET CURSOR OFF
  1743.  
  1744. IF !EMPTY(m.dbfname)
  1745.    IF _MAC
  1746.      m.dbfname = SYS(2027,FULLPATH(m.dbfname))
  1747.    ELSE
  1748.      m.dbfname = FULLPATH(m.dbfname)
  1749.    ENDIF
  1750. ENDIF
  1751.  
  1752. IF ! chktblname(m.dbfname)
  1753.   RETURN 0
  1754. ELSE
  1755.    IF !('.' $ justfname(m.dbfname)) AND !EMPTY(m.dbfname)
  1756.       m.dbfname = forceext(m.dbfname,'DBF')
  1757.    ENDIF
  1758.  
  1759.    dbfname = UPPER(ALLTRIM(m.dbfname))
  1760.    IF !EMPTY(m.dbfname)
  1761.       m.dbfalias = opendbf(m.dbfname)
  1762.       IF EMPTY(m.scxname)
  1763.          m.scxname = forceext(m.dbfname,'SCX')
  1764.       ENDIF
  1765.    ENDIF
  1766.  
  1767.    * Poke this database into the first position of DBFLIST
  1768.    IF TYPE('DBFLIST') <> 'U'
  1769.       dbflist[1,m.cstemnum] = makealias(juststem(m.dbfname))
  1770.    ENDIF
  1771.  
  1772.    SHOW GETS
  1773.    RETURN .T.
  1774. ENDIF
  1775.  
  1776.  
  1777. PROCEDURE CHKTBLNAME
  1778.  
  1779. PARAMETER TNAME
  1780.  
  1781. DO CASE
  1782. CASE EMPTY(juststem(m.tname)) AND !EMPTY(m.tname)
  1783.    = FA_Alert(C_BADDBF)
  1784.    RETURN .f.
  1785. CASE (EMPTY(justext(m.tname)) OR justext(m.tname) = 'DBF')   ;
  1786.       AND (justfname(m.tname) >= 'A' AND justfname(m.tname) <= 'Z') ;
  1787.       AND LEN(juststem(m.tname))<=1
  1788.    * Don't allow single letter database names--they get confused with areas
  1789.    = FA_Alert(C_ONELTR)
  1790.    RETURN .f.
  1791. CASE INLIST(justext(m.tname),'SCX','SCT','SPR')
  1792.    = FA_Alert(C_SCXNAME)
  1793.    RETURN .f.
  1794. CASE INLIST(justext(m.tname),'MNX','MNT','MPR')
  1795.    = FA_Alert(C_MNXNAME)
  1796.    RETURN .f.
  1797. OTHERWISE
  1798.    RETURN .t.
  1799. ENDCASE
  1800.  
  1801.  
  1802. PROCEDURE ListDbfValid
  1803. * VALID clause from m.Listdbf button in appscx
  1804. *------------------------------------------------------------------
  1805.  
  1806. PRIVATE m.testdbf
  1807. IF UPPER(ALLTRIM(m.dbfname)) <> UPPER(ALLTRIM(m.origname))
  1808.    m.rsc_check = .F.
  1809. ENDIF
  1810.  
  1811. m.origname = m.dbfname
  1812. CLOSE DATABASES
  1813. m.dbfname = GETFILE('DBF',C_DBFPMT)
  1814. IF EMPTY(m.dbfname)
  1815.    m.dbfname = m.origname
  1816. ELSE
  1817.     IF _MAC
  1818.         m.dbfname = SYS(2027, m.dbfname)
  1819.     ENDIF
  1820.    m.testdbf = opendbf(m.dbfname)
  1821.    if len(alltrim(m.testdbf)) = 0
  1822.      m.dbfname = m.origname
  1823.      return
  1824.    endif
  1825.    if ! chktblname(m.dbfname)
  1826.      _curobj = objnum(dbfname)
  1827.      return
  1828.    endif
  1829.    IF EMPTY(m.scxname)
  1830.       IF _MAC
  1831.         m.scxname = SYS(2027,forceext(m.dbfname,'SCX'))
  1832.       ELSE
  1833.         m.scxname = forceext(m.dbfname,'SCX')
  1834.       ENDIF
  1835.    ENDIF
  1836. ENDIF
  1837.  
  1838. * Poke this database into the first position of DBFLIST
  1839. IF TYPE('DBFLIST') <> 'U'
  1840.    dbflist[1,m.cstemnum] = makealias(juststem(m.dbfname))
  1841. ENDIF
  1842.  
  1843. SHOW GETS
  1844. RETURN .T.
  1845.  
  1846.  
  1847. PROCEDURE AddDbfValid
  1848. * VALID clause from m.adddbf button in appscx
  1849. *------------------------------------------------------------------
  1850.  
  1851. IF EMPTY(m.dbfname)
  1852.    m.dbfname = PUTFILE(C_DBFPMT,'','DBF')
  1853.    IF EMPTY(m.dbfname)
  1854.       RETURN .F.   && don't do anything
  1855.    ENDIF
  1856. ENDIF
  1857. IF !FILE(m.dbfname)
  1858.    * This window controls the colors used by CREATE 
  1859.    DEFINE WINDOW mywin FROM INT((srow()-20)/2),INT((scol()-71)/2);
  1860.       TO INT((srow()-20)/2)+19,INT((scol()-71)/2)+70 ;
  1861.       FLOAT CLOSE SHADOW MINIMIZE SYSTEM COLOR SCHEME 8
  1862.    ACTIVATE WINDOW mywin NOSHOW
  1863.  
  1864.    CREATE (m.dbfname)
  1865.    DEACTIVATE WINDOW mywin
  1866.    RELEASE WINDOW mywin
  1867. ELSE    && this shouldn't be possible since the control should be disabled
  1868.    m.dname = opendbf(m.dbfname)
  1869.    IF !EMPTY(m.dname)
  1870.       MODIFY STRUCTURE
  1871.    ENDIF
  1872.    SHOW GET adddbf DISABLE
  1873.    SHOW GET moddbf ENABLE
  1874. ENDIF
  1875. SHOW GETS
  1876. RETURN .T.
  1877.  
  1878.  
  1879. PROCEDURE ModDbfValid
  1880. * VALID clause from m.moddbf button in appscx
  1881. *------------------------------------------------------------------
  1882.  
  1883. IF !EMPTY(m.dbfname)
  1884.    IF !EMPTY(opendbf(m.dbfname))
  1885.       MODIFY STRUCTURE
  1886.    ELSE
  1887.       SHOW GET moddbf DISABLE
  1888.       RETURN -2
  1889.    ENDIF
  1890. ENDIF
  1891. RETURN .T.
  1892.  
  1893.  
  1894. PROCEDURE OtherValid
  1895. * VALID clause from m.other button in appscx ("Related...")
  1896. *------------------------------------------------------------------
  1897.  
  1898. IF _MAC AND !FILE(m.dbfname)
  1899.    WAIT WINDOW C_NOFIND + TRIM(m.dbfname) NOWAIT
  1900.    RETURN
  1901. ENDIF
  1902.  
  1903. DO opendbf WITH m.dbfname
  1904.  
  1905. DO dbfselec.spr
  1906.  
  1907. * Leave the main database open when through with picking subsidiary
  1908. *   databases.
  1909. m.dbfalias = opendbf(m.dbfname)
  1910. IF relateddbfs() AND !EMPTY(m.scxname) AND FILE(m.scxname)
  1911.    SHOW GET arrange ENABLE
  1912. ELSE
  1913.    SHOW GET arrange DISABLE
  1914. ENDIF      
  1915.  
  1916.  
  1917. PROCEDURE ScxNameWhen
  1918. * WHEN clause from m.scxname get in appscx
  1919. *------------------------------------------------------------------
  1920. m.scxname = PADR(m.scxname,m.apppathlen)
  1921. IF ! FILE(m.scxname)
  1922.   SHOW GET addscx ENABLE
  1923.   SHOW GET modscx DISABLE
  1924. ELSE
  1925.   SHOW GET addscx DISABLE
  1926.   SHOW GET modscx ENABLE
  1927. ENDIF
  1928. SET CURSOR ON
  1929. RETURN .T.
  1930.  
  1931.  
  1932. PROCEDURE ScxNameValid
  1933. * VALID clause from m.scxname get in appscx
  1934. *------------------------------------------------------------------
  1935.  
  1936. SET CURSOR OFF
  1937. m.scxname = UPPER(ALLTRIM(m.scxname))
  1938. IF !EMPTY(m.scxname)
  1939.    m.scxname = FULLPATH(m.scxname)
  1940. ENDIF
  1941.  
  1942. scxname = ALLTRIM(m.scxname)
  1943. IF !('.' $ justfname(m.scxname)) AND !EMPTY(justfname(m.scxname))
  1944.    scxname = forceext(m.scxname,'SCX')
  1945. ENDIF
  1946. m.scxname = UPPER(m.scxname)
  1947.  
  1948. DO CASE
  1949. CASE !EMPTY(m.scxname) AND EMPTY(juststem(m.scxname)) 
  1950.    = FA_Alert(C_BADSCX)
  1951.    RETURN 0
  1952. ENDCASE
  1953. IF _MAC
  1954.   m.scxname = SYS(2027, m.scxname)
  1955. ENDIF
  1956. SHOW GETS
  1957.  
  1958.  
  1959. PROCEDURE ListScxValid
  1960. * VALID clause from m.Listscx button in appscx
  1961. *------------------------------------------------------------------
  1962. m.origname = m.scxname
  1963. m.scxname = GETFILE('SCX',C_SCXPMT)
  1964. IF EMPTY(scxname)
  1965.    m.scxname = m.origname
  1966. ELSE
  1967.    IF _MAC
  1968.      m.scxname = SYS(2027, m.scxname)
  1969.    ENDIF
  1970. ENDIF
  1971. SHOW GETS
  1972. RETURN .T.
  1973.  
  1974.  
  1975. PROCEDURE AddScxValid
  1976. * VALID clause from m.addscx button in appscx
  1977. *------------------------------------------------------------------
  1978. IF EMPTY(m.scxname)
  1979.    m.scxname = PUTFILE(C_SCXPMT,'','SCX')
  1980.    IF EMPTY(m.scxname)
  1981.       m.scxname = 'UNTITLED.SCX'
  1982.    ENDIF
  1983. ELSE
  1984.    IF FILE(m.scxname)
  1985.       MODIFY SCREEN (m.scxname)
  1986.    ELSE
  1987.       DO createscx
  1988.    ENDIF
  1989. ENDIF
  1990. SHOW GETS
  1991. RETURN .T.
  1992.  
  1993.  
  1994. PROCEDURE ModScxWhen
  1995. * WHEN clause from m.modscx button in appscx
  1996. *------------------------------------------------------------------
  1997. IF !FILE(m.scxname)
  1998.    WAIT WINDOW C_SCXCREA2 NOWAIT
  1999.    DO createscx
  2000. ENDIF
  2001. RETURN .T.
  2002.  
  2003. PROCEDURE ModScxValid
  2004. * VALID clause from m.modscx button in appscx
  2005. *------------------------------------------------------------------
  2006. IF FILE(m.scxname) AND !EMPTY(m.scxname)
  2007.    if used("scrnfile")
  2008.      use in scrnfile
  2009.    endif
  2010.    MODIFY SCREEN (m.scxname)
  2011. ELSE
  2012.    WAIT WINDOW C_SCXCREA1 NOWAIT
  2013.    DO createscx
  2014. ENDIF
  2015. SHOW GET addscx DISABLE
  2016. SHOW GETS
  2017. RETURN .T.
  2018.  
  2019.  
  2020. PROCEDURE ArrangeValid
  2021. * VALID clause from m.arrange button in appscx
  2022. *------------------------------------------------------------------
  2023. PRIVATE m.wiz_screen, m.tree_up, m.arrexflg, m.in_area, m.maxcapt, m.maxlen, m.maxheight, m.start_row, ;
  2024.    m.start_col, m.sheight, m.swidth, m.ws_col, m.ws_row, m.we_row, m.we_col
  2025.  
  2026. DO opendbf WITH m.dbfname
  2027.  
  2028. PUSH MENU _msysmenu
  2029.  
  2030. RELEASE arrexflg   && causes upcoming Foundation read to terminate
  2031. PUBLIC  arrexflg
  2032. m.arrexflg = .F.
  2033.  
  2034. m.tree_up = WVISIBLE('treewind')
  2035.  
  2036. HIDE WINDOW appgen
  2037. IF WEXIST('dbfselec')
  2038.    HIDE WINDOW dbfselec
  2039. ENDIF
  2040. IF WEXIST('treewind')
  2041.    HIDE WINDOW treewind
  2042. ENDIF
  2043.  
  2044. DEFINE PAD a_save OF _msysmenu PROMPT C_SAVEARR,"" COLOR SCHEME 3
  2045. DEFINE PAD a_cancel OF _msysmenu PROMPT C_CANCPMT,"" COLOR SCHEME 3
  2046. ON SELECTION PAD a_save   OF _msysmenu DO arrsave
  2047. ON SELECTION PAD a_cancel OF _msysmenu DO arrexit
  2048.  
  2049. RELEASE PAD _MSM_SYSTM  OF _msysmenu
  2050. RELEASE PAD _MSM_FILE   OF _msysmenu
  2051. RELEASE PAD _MSM_EDIT   OF _msysmenu
  2052. RELEASE PAD _MSM_DATA   OF _msysmenu
  2053. RELEASE PAD _MSM_RECRD  OF _msysmenu
  2054. RELEASE PAD _MSM_PROG   OF _msysmenu
  2055. RELEASE PAD _MSM_WINDO  OF _msysmenu
  2056. RELEASE PAD RUN         OF _msysmenu
  2057.  
  2058. * Save the screen and start the arranging from a blank screen
  2059. SAVE SCREEN TO arr_scrn
  2060. ACTIVATE SCREEN
  2061. CLEAR
  2062.  
  2063. m.wiz_screen = .F.
  2064. m.in_area = SELECT()
  2065. SELECT 0
  2066. USE (m.scxname) AGAIN
  2067. LOCATE FOR platform = m.app_platform AND objtype = 1
  2068. IF FOUND()
  2069.    m.wiz_screen = iswiz(setupcode)
  2070. ENDIF
  2071. USE
  2072. SELECT (m.in_area)
  2073.  
  2074. IF !m.wiz_screen
  2075.    * See how wide and tall the actual control panel is.
  2076.    m.dname = addbs(m.foxappdir)+'screens\appctrl.scx'
  2077.    IF FILE(m.dname)
  2078.       m.in_area = SELECT()
  2079.       SELECT 0
  2080.       USE (dname) AGAIN ALIAS ctrl
  2081.       LOCATE FOR platform = m.app_platform AND objtype = 1
  2082.       IF FOUND()
  2083.          m.ctrl_width     = ctrl.width
  2084.          m.ctrl_height    = ctrl.height
  2085.       ELSE
  2086.          m.ctrl_width = 73.167    && go with default values then
  2087.          m.ctrl_height = 3.846
  2088.       ENDIF
  2089.       USE
  2090.       SELECT (m.in_area)
  2091.    ELSE
  2092.       m.ctrl_width = 73.167
  2093.       m.ctrl_height = 3.846
  2094.    ENDIF
  2095.    m.ctrlrow = MAX(0,m.ctrlrow)
  2096.    m.ctrlrow = MIN(my_srows()-3,m.ctrlrow)
  2097.    m.ctrlcol = MAX(0,m.ctrlcol)
  2098.    m.ctrlcol = MIN(my_scols()-7,m.ctrlcol)
  2099.  
  2100.    * Define window for control panel
  2101.    DEFINE WINDOW ctrl ;
  2102.       AT m.ctrlrow,m.ctrlcol ;
  2103.       SIZE m.ctrl_height, m.ctrl_width ;
  2104.       TITLE C_CTRLTITL ;
  2105.       HALF ;
  2106.       FONT m.g_dfltfface, m.g_dfltfsize ;
  2107.       STYLE m.g_dfltfstyle ;
  2108.       FLOAT NOZOOM NOCLOSE
  2109.    ACTIVATE WINDOW ctrl
  2110. ENDIF
  2111.  
  2112. m.sfontface  = m.g_dfltfface
  2113. m.sfontsize  = m.g_dfltfsize
  2114. m.sfontstyle = m.g_dfltfstyle
  2115.  
  2116. * Figure out how tall and wide the main database screen will be
  2117. IF EMPTY(m.scxname) OR !FILE(m.scxname)
  2118.    * If a screen hasn't been defined yet, look at the database fields
  2119.    SELECT (dbflist[1,m.cstemnum])
  2120.    m.maxlen  = 0
  2121.    m.maxheight = FCOUNT() + 4
  2122.    m.maxcapt = 0
  2123.    FOR m.i = 1 TO FCOUNT()
  2124.       m.maxlen  = MAX(m.maxlen,FSIZE(FIELD(m.i)))  && max field length
  2125.       m.maxcapt = MAX(m.maxcapt,LEN(FIELD(m.i))+2) && max field name length
  2126.    ENDFOR
  2127.    m.maxlen = m.maxlen + m.maxcapt + 4   && allow for borders
  2128.    m.sheight   = m.maxheight
  2129.    m.swidth    = m.maxlen   
  2130. ELSE         && otherwise, look to the SCX itself
  2131.    SELECT 0
  2132.    USE (m.scxname) AGAIN ALIAS fxscxnme
  2133.    LOCATE FOR platform = m.app_platform AND Objtype = 1
  2134.    IF FOUND()
  2135.       m.sfontface  = fxscxnme.fontface
  2136.       m.sfontsize  = fxscxnme.fontsize
  2137.       m.sfontstyle = num2style(fxscxnme.fontstyle)
  2138.       m.sheight    = fxscxnme.height
  2139.       m.swidth     = fxscxnme.width
  2140.    ELSE
  2141.       m.platformword = IIF(_MAC,"Macintosh", IIF(_DOS,"DOS","Windows"))
  2142.       = FA_Alert(C_NOREC1 + m.platformword + C_NOREC2)
  2143.       m.sheight = 21
  2144.       m.swidth  = 74
  2145.    ENDIF
  2146.    USE
  2147. ENDIF
  2148.  
  2149. * Determine position for main database window and define window
  2150. DO CASE
  2151. CASE UPPER(dbflist[1,m.arranged]) = "N"
  2152.    * No screen position yet defined for the main database.  Center it,
  2153.    * unless there are lots of related databases.  If there are, put
  2154.    * it closer to the top of the screen.
  2155.    IF m.nextdbf < 3  && just one database used in app
  2156.       m.start_row = MAX(INT(my_srows()/2-m.sheight/2),0)
  2157.       m.start_col = MAX(INT(my_scols()/2-m.swidth/2),0)
  2158.    ELSE
  2159.       m.start_row = 1
  2160.       m.start_col = MAX(INT(my_scols()/2-m.swidth/2),0)
  2161.    ENDIF
  2162. OTHERWISE   && show it where the user put it last
  2163.    m.start_row    = VAL(dbflist[1,m.srownum])
  2164.    m.start_col    = VAL(dbflist[1,m.scolnum])
  2165. ENDCASE
  2166. m.start_row = MAX(0,m.start_row)
  2167. m.start_col = MAX(0,m.start_col)
  2168.  
  2169. * Define the blank window for the main database
  2170. DEFINE WINDOW (dbflist[1,m.cstemnum]) ;
  2171.    AT m.start_row,m.start_col ;
  2172.    SIZE m.sheight,m.swidth ;
  2173.    TITLE dbflist[1,m.cstemnum] ;
  2174.    FONT m.sfontface, m.sfontsize ;
  2175.    STYLE m.sfontstyle ;
  2176.    NOGROW FLOAT NOZOOM NOCLOSE ;
  2177.    COLOR SCHEME 1
  2178.  
  2179. * Define windows for child databases
  2180. FOR m.i = 2 TO m.numareas
  2181.    IF !EMPTY(dbflist[m.i,m.cstemnum]) AND dbflist[m.i,m.cstemnum] <> '\'
  2182.       IF dbflist[m.i,m.arranged] = "N"
  2183.          * Try to place browse windows immediately beneath main screen
  2184.          m.win_height = 8      && minimum height of a BROWSE window
  2185.          IF m.start_row + m.sheight + (m.i-2)*(m.win_height+1) + 2 < my_srows() - 3
  2186.             m.ws_row = m.start_row + m.sheight + (m.i-2)*(m.win_height+1) + 2
  2187.             m.ws_col = 1
  2188.             m.we_row = m.win_height
  2189.             m.we_col = 74                     && width
  2190.          ELSE     && put the browse windows in the upper left of the screen
  2191.             m.ws_row = m.i
  2192.             m.ws_col = m.i
  2193.             m.we_row = MIN(m.win_height,my_srows()-m.ws_row-1)   && height
  2194.             m.we_col = 74                     && width
  2195.          ENDIF
  2196.       ELSE
  2197.          m.fontstrg = dbflist[m.i,m.thefont]
  2198.          m.ws_row = VAL(dbflist[m.i,m.srownum])
  2199.          m.ws_col = VAL(dbflist[m.i,m.scolnum])
  2200.          m.we_row = VAL(dbflist[m.i,m.erownum])
  2201.          m.we_col = VAL(dbflist[m.i,m.ecolnum])
  2202.  
  2203.       ENDIF
  2204.       DEFINE WINDOW (dbflist[m.i,m.cstemnum]) ;
  2205.          AT m.ws_row,m.ws_col ;
  2206.          SIZE m.we_row,m.we_col ;
  2207.          SYSTEM ;
  2208.          TITLE dbflist[m.i,m.cstemnum] ;
  2209.          GROW FLOAT NOZOOM NOCLOSE ;
  2210.          HALF ;
  2211.          FONT m.g_dfltfface, m.g_dfltfsize ;
  2212.          STYLE m.g_dfltfstyle ;
  2213.          COLOR SCHEME 10
  2214.       ACTIVATE WINDOW (dbflist[m.i,m.cstemnum])
  2215.    ENDIF
  2216. ENDFOR
  2217.  
  2218. * Activate the main window and let user move things around.
  2219. ACTIVATE WINDOW (dbflist[1,m.cstemnum])
  2220.  
  2221. * The foundation read terminates when the user selects "Save" or "Exit" from the menu
  2222. READ VALID m.arrexflg
  2223.  
  2224. IF m.tree_up AND WEXIST('treewind')
  2225.    SHOW WINDOW treewind
  2226. ENDIF
  2227. RELEASE arrexflg, ws_row, ws_col, we_row, we_col, i, tree_up, win_height, sheight, swidth
  2228.  
  2229. RESTORE SCREEN FROM arr_scrn
  2230.  
  2231. RETURN
  2232.  
  2233.  
  2234. FUNCTION num2style
  2235. * Translate a font style number to its equivalent string representation
  2236. PARAMETER m.num
  2237. PRIVATE m.i, m.strg, m.pow, m.stylechars, m.outstrg
  2238. m.strg = ""
  2239. * These are the style characters.  Their position in the string matches the bit 
  2240. * position in the num byte.
  2241. m.stylechars = "BIUOSCE-"
  2242.  
  2243. * Look at each of the bits in the num byte
  2244. FOR m.i = 8 TO 1 STEP -1
  2245.    m.pow = ROUND(2^(i-1),0)  
  2246.     IF m.num >= m.pow
  2247.        m.strg = m.strg + SUBSTR(stylechars,m.i,1)
  2248.     ENDIF
  2249.     m.num = m.num % m.pow
  2250. ENDFOR
  2251.  
  2252. * Now reverse the string so that style codes appear in the traditional order
  2253. m.outstrg = ""
  2254. FOR m.i = 1 TO LEN(m.strg)
  2255.    m.outstrg = m.outstrg + SUBSTR(m.strg,LEN(m.strg)+1-m.i,1)
  2256. ENDFOR
  2257. RETURN m.outstrg
  2258.  
  2259.  
  2260. PROCEDURE GenerateValid
  2261. * VALID clause from m.generate button in appscx
  2262. *------------------------------------------------------------------
  2263. #define fa_european 0
  2264.  
  2265. PRIVATE m.win_string, m.dname, m.quoted, m.sc_file, m.i, m.j, m.wizscreen, m.dest, m.msg, ;
  2266.    m.c_path, m.userapp_dir, m.valid_name
  2267. m.wizscreen = .F.   && assume it isn't a screen wizard screen--they have their own ctrl panel
  2268. IF m.generate = 1
  2269.  
  2270.    IF !FILE(m.dbfname) OR EMPTY(m.dbfname)
  2271.       DO CASE
  2272.       CASE EMPTY(m.dbfname)
  2273.          m.msg = C_NOTABLE
  2274.          m.dest = -9
  2275.       CASE !FILE(m.dbfname)
  2276.          m.msg = C_NOFIND + justfname(m.dbfname)
  2277.          m.dest = -9
  2278.       OTHERWISE
  2279.          * This code shouldn't exectute
  2280.          m.dest = -9
  2281.          m.msg = C_ERRGEN
  2282.       ENDCASE
  2283.       WAIT WINDOW m.msg NOWAIT
  2284.       SHOW GETS
  2285.       RETURN m.dest   && bounce out of generate and return to the dbfname field
  2286.    ENDIF
  2287.  
  2288.    SET CURSOR OFF
  2289.  
  2290.    * Create a default input screen if the one the user specified doesn't
  2291.    * exist.
  2292.    IF EMPTY(m.scxname)
  2293.       m.scxname = forceext(m.dbfname,'SCX')
  2294.    ENDIF
  2295.    IF !FILE(m.scxname)
  2296.       DO createscx
  2297.    ENDIF
  2298.  
  2299.    CLOSE DATABASES
  2300.  
  2301.    m.scxname  = UPPER(ALLTRIM(m.scxname))
  2302.    m.dbfname  = UPPER(ALLTRIM(m.dbfname))
  2303.    m.mnuname  = UPPER(ALLTRIM(m.mnuname))
  2304.  
  2305.    SET CURSOR ON
  2306.  
  2307.    * Note the current directory and path
  2308.    m.c_path = SET('DEFAULT') + CURDIR()
  2309.  
  2310.    m.appfile = forceext(m.scxname,'APP')
  2311.    m.userapp_dir = addcolon(justpath(m.scxname))
  2312.    SET DEFAULT TO (m.userapp_dir)
  2313.    RELEASE m.userapp_dir
  2314.  
  2315.    m.mpoint = SET("POINT")
  2316.    SET POINT TO "."
  2317.  
  2318.    m.valid_name = .F.
  2319.    DO WHILE !m.valid_name
  2320.       m.appfile = PUTFILE(C_NAMEPMT,forceext(m.appfile,'APP'),'APP')
  2321.       DO CASE
  2322.       CASE UPPER(ALLTRIM(justfname(m.appfile))) == 'FOXAPP.APP'
  2323.          DO ALERT WITH C_SAMENAME
  2324.          m.valid_name = .F.
  2325.       OTHERWISE
  2326.          m.valid_name = .T.
  2327.       ENDCASE
  2328.    ENDDO
  2329.    RELEASE m.valid_name
  2330.  
  2331.    IF EMPTY(m.appfile)   && user pressed 'cancel'.  Return to top screen.
  2332.       SHOW GETS
  2333.    ELSE                  && time to create the APP
  2334.       SET CONSOLE OFF
  2335.  
  2336.       * Store relations into resource file if needed
  2337.       IF TYPE("DBFLIST") <> "U" AND !m.rsc_stored AND m.storersc
  2338.          WAIT WINDOW C_SAVDBWIN NOWAIT
  2339.          DO putdbflist WITH dbflist[1,1]
  2340.       ENDIF
  2341.  
  2342.       m.win_string = C_GENMSG +PROPER(juststem(m.appfile))+'.'
  2343.       WAIT WINDOW m.win_string NOWAIT
  2344.       HIDE WINDOW (WOUTPUT())
  2345.       RELEASE m.win_string
  2346.  
  2347.       * tmfname is the name of the scaffolding program that pulls all the
  2348.       * FoxApp application modules together.
  2349.       m.tmfname = addbs(justpath(m.appfile))+'scaffold.prg'
  2350.       SET TEXTMERGE TO (m.tmfname)
  2351.  
  2352.       SET TEXTMERGE ON
  2353.       IF _MAC OR _WINDOWS
  2354.          \\*      +---------------------------------------------------------+
  2355.          \*       |                                                         |
  2356.          \*       | <<DATE()>>               scaffold.prg            <<TIME()>> |
  2357.          \*       |                                                         |
  2358.          \*       +---------------------------------------------------------+
  2359.          \*       |                                                         |
  2360.          \*       C_TMDESC                                            |
  2361.          \*       C_TMHEAD     |
  2362.          \*       |                                                         |
  2363.          \*       +---------------------------------------------------------+
  2364.       ELSE
  2365.          \\*       ╓─────────────────────────────────────────────────────────╖
  2366.          \*       ║                                                         ║
  2367.          \*       ║ <<DATE()>>               scaffold.prg            <<TIME()>> ║
  2368.          \*       ║                                                         ║
  2369.          \*       ╟─────────────────────────────────────────────────────────╢
  2370.          \*       ║                                                         ║
  2371.          \*       C_TMDESCD                                            ║
  2372.          \*       C_TMHEADD     ║
  2373.          \*       ║                                                         ║
  2374.          \*       ╙─────────────────────────────────────────────────────────╜
  2375.       ENDIF
  2376.       \*
  2377.       \*       C_TMRUN <<UPPER(justfname(m.appfile))>>
  2378.       \*
  2379.       \* C_TMENV
  2380.       \CREATE VIEW appview
  2381.       \SET TALK OFF
  2382.       \PUSH MENU _msysmenu
  2383.       \PUSH KEY CLEAR
  2384.       \fxapp_error = ON('ERROR')
  2385.       \fxapp_esc   = ON('ESCAPE')
  2386.  
  2387.       \SET SAFETY OFF
  2388.       \SAVE MACROS TO foxapp
  2389.       \SET SAFETY ON
  2390.       \SET DELETED ON
  2391.       \SET ESCAPE OFF
  2392.       \SET STEP OFF
  2393.       \SET ECHO OFF
  2394.       \SET PROCEDURE TO appproc.prg
  2395.       \SET CURSOR ON
  2396.  
  2397.       \m.set_point = SET("POINT")
  2398.  
  2399.       #IF fa_european
  2400.       \SET POINT TO ","
  2401.       #endif
  2402.  
  2403.       \CLOSE DATABASES
  2404.       \ON ERROR DO apperror WITH PROGRAM(),MESSAGE(),MESSAGE(1),LINENO(),ERROR()
  2405.       \
  2406.       \IF _WINDOWS OR _MAC
  2407.       \   * C_TMFONT
  2408.       \   m.scrn_font   = WFONT(1,"")
  2409.       \   m.scrn_fsize  = WFONT(2,"")
  2410.       \   m.scrn_fstyle = WFONT(3,"")
  2411.       \   MODIFY WINDOW SCREEN FONT "<<m.g_dfltfface>>",<<m.g_dfltfsize>> STYLE "<<m.g_dfltfstyle>>"
  2412.       \ENDIF
  2413.       \
  2414.       \IF TYPE("BAILOUT") <> "U"
  2415.       \   RELEASE m.bailout
  2416.       \ENDIF
  2417.       \IF TYPE("DBFNAME") <> "U"
  2418.       \   RELEASE m.dbfname
  2419.       \ENDIF
  2420.       \IF TYPE("WIN_NAME") <> "U"
  2421.       \   RELEASE m.win_name
  2422.       \ENDIF
  2423.       \IF TYPE("FILT_EXPR") <> "U"
  2424.       \   RELEASE m.filt_expr
  2425.       \ENDIF
  2426.       \IF TYPE("SRCHTERM") <> "U"
  2427.       \   RELEASE m.srchterm
  2428.       \ENDIF
  2429.       IF m.regen
  2430.          \regen = .T.   && use SPR/MPR files instead of PRGs
  2431.          \EXTERNAL SCREEN    getdest, getorder, appabout, ;
  2432.          \                    appsrch, prtopts, prtsetup
  2433.       ELSE
  2434.          \regen = .F.
  2435.          \EXTERNAL PROCEDURE getdest, getorder, appabout, ;
  2436.          \                    appsrch, prtopts, prtsetup
  2437.       ENDIF
  2438.       \
  2439.       \PUBLIC bailout, dbfname, win_name, wiz_screen, filt_expr, srchterm
  2440.       \m.bailout = .F.
  2441.       \m.dbfname = "<<m.dbfname>>"     && database name
  2442.       \m.qprpath = justpath(m.dbfname) && query file path
  2443.       \m.filt_expr = ""                && filter expression, if any
  2444.       \m.srchterm = SPACE(60)          && search term
  2445.       \m.win_name = ""                 && name assigned below
  2446.       \m.wiz_screen = .F.              && assume false for now
  2447.       \
  2448.       \* Define constants for addressing DBFLIST
  2449.       \m.numareas   = <<m.numareas>>
  2450.       \m.numcols    = <<m.numcols>>
  2451.       \m.cstemnum   = <<m.cstemnum>>
  2452.       \m.relstrnum  = <<m.relstrnum>>
  2453.       \m.pfldnum    = <<m.pfldnum>>
  2454.       \m.cfldnum    = <<m.cfldnum>>
  2455.       \m.cdbfnum    = <<m.cdbfnum>>
  2456.       \m.pdbfnum    = <<m.pdbfnum>>
  2457.       \m.srownum    = <<m.srownum>>
  2458.       \m.scolnum    = <<m.scolnum>>
  2459.       \m.erownum    = <<m.erownum>>
  2460.       \m.ecolnum    = <<m.ecolnum>>
  2461.       \m.arranged   = <<m.arranged>>
  2462.       \m.thefont    = <<m.thefont>>
  2463.       \m.cascadenum = <<m.cascadenum>>
  2464.       \m.ctrlrow    = <<INT(m.ctrlrow)>>
  2465.       \m.ctrlcol    = <<INT(m.ctrlcol)>>
  2466.       \m.nextdbf    = <<m.nextdbf>>
  2467.       \DO DefineDbf                    && define the DBFLIST array
  2468.       \
  2469.       \
  2470.       \* C_TGETMENU
  2471.       m._mname = FNAddQuotes(forceext(juststem(m.mnuname),IIF(regen,'MPR','PRG')))
  2472.       \DO <<m._mname>>
  2473.       \
  2474.       \* C_TOPENDBF
  2475.       \m.stem = makealias(juststem(m.dbfname))
  2476.       \IF USED(m.stem)
  2477.       \   SELECT (m.stem)
  2478.       \ELSE
  2479.       \   SELECT 0
  2480.       \   IF !FILE(m.dbfname)
  2481.       \      m.dbfname = GETFILE('DBF',C_TPLSLOC+JustStem(m.dbfname)+C_TDBF)
  2482.       \   ENDIF
  2483.       \   IF EMPTY(m.dbfname) OR !FILE(m.dbfname)
  2484.       \      DO alert WITH C_TTHE +m.stem+C_TDBNOTFD
  2485.       \      DO cleanup
  2486.       \      RETURN
  2487.       \   ELSE
  2488.       \      USE (m.dbfname)
  2489.       \   ENDIF
  2490.       \ENDIF
  2491.       \* C_TCHKIDX
  2492.       \IF EMPTY(CDX(1))
  2493.       \   IF !FILE(forceext(m.dbfname,'CDX'))
  2494.       \      DO invert WITH m.dbfname
  2495.       \   ELSE
  2496.       \      SET INDEX TO (forceext(m.dbfname,'CDX'))
  2497.       \   ENDIF
  2498.       \ENDIF
  2499.       \SET ORDER TO 1
  2500.       \
  2501.       \IF RECCOUNT() = 0
  2502.       \   APPEND BLANK
  2503.       \ELSE
  2504.       \   IF RECCOUNT() < 10
  2505.       \      COUNT FOR !DELETED() TO notdel
  2506.       \      IF m.notdel = 0
  2507.       \         APPEND BLANK  && C_TRECDEL
  2508.       \      ENDIF
  2509.       \   ENDIF
  2510.       \ENDIF
  2511.       \GOTO TOP
  2512.       \
  2513.       \CLEAR
  2514.  
  2515.       m.sc_file = LOWER(forceext(juststem(m.scxname),'SPR'))
  2516.  
  2517.       * Force user screen into a window and figure out its size
  2518.       m.vcoord = 0
  2519.       m.hcoord = 0
  2520.       IF FILE(m.scxname)
  2521.          SELECT 0
  2522.          USE (m.scxname) ALIAS scrnfile
  2523.          COUNT FOR UPPER(ALLTRIM(platform)) == m.app_platform TO m.platcnt
  2524.          IF platcnt = 0
  2525.             m.platword = IIF(_MAC,"Macintosh",IIF(_DOS,"DOS","Windows"))
  2526.             = FA_Alert(m.scxname + C_NOTCONT + m.platword + C_RECORDS)
  2527.             SET TEXTMERGE TO
  2528.               SET TEXTMERGE OFF
  2529.               SET CONSOLE ON
  2530.               SET NOTIFY OFF
  2531.             ACTIVATE WINDOW (WOUTPUT())
  2532.             RETURN .F.
  2533.          ENDIF
  2534.  
  2535.          LOCATE FOR objtype == 1 ;
  2536.             AND UPPER(ALLTRIM(platform)) == m.app_platform
  2537.          IF FOUND()
  2538.             m.win_name = makealias(UPPER(ALLTRIM(scrnfile.name)))
  2539.             m.wizscreen = iswiz(setupcode)
  2540.             IF !m.wizscreen
  2541.                * Make sure that user screen goes into a window
  2542.                IF EMPTY(scrnfile.name)
  2543.                   win_msg = C_PUTTING +juststem(m.scxname)+C_SCXINWIN
  2544.                   WAIT WINDOW win_msg TIMEOUT 1
  2545.                   m.scrn_face  = scrnfile.fontface
  2546.                   m.scrn_size  = scrnfile.fontsize
  2547.                   m.scrn_style = scrnfile.fontstyle
  2548.                   REPLACE scrnfile.name WITH juststem(m.appfile), ;
  2549.                      scrnfile.style WITH 2,                  ;
  2550.                      scrnfile.border WITH 1,                 ;
  2551.                      scrnfile.center WITH .F.,               ;
  2552.                      scrnfile.vpos WITH 1,                   ;
  2553.                      scrnfile.hpos WITH 3
  2554.                   WAIT CLEAR
  2555.                ENDIF
  2556.  
  2557.                * Figure out where to put the screen and control panel
  2558.                IF relateddbfs()
  2559.                   m.scrn_face  = scrnfile.fontface
  2560.                   m.scrn_size  = scrnfile.fontsize
  2561.                   m.scrn_style = scrnfile.fontstyle
  2562.  
  2563.                   m.vcoord = m.ctrlrow   && bottom of the screen
  2564.                   m.hcoord = m.ctrlcol
  2565.                   REPLACE scrnfile.center   WITH .F.
  2566.                   IF dbflist[1,m.arranged] = 'Y'
  2567.                      REPLACE scrnfile.vpos WITH VAL(dbflist[1,m.srownum])
  2568.                      REPLACE scrnfile.hpos WITH VAL(dbflist[1,m.scolnum])
  2569.                   ELSE
  2570.                      * Set default placement of browse windows if user hasn't arranged them
  2571.                      FOR m.i = 2 to m.numareas
  2572.                         * Position it below the previous browse or screen
  2573.                         m.rnum = MIN(VAL(dbflist[m.i-1,m.srownum]);
  2574.                            + VAL(dbflist[m.i-1,m.erownum]) + 2.5, my_srows())
  2575.                         dbflist[m.i,m.srownum] = ALLTRIM(STR(m.rnum,4))
  2576.                         * Center it horizontally
  2577.                         m.cnum = (my_scols() - VAL(dbflist[m.i,m.ecolnum])) / 2
  2578.                         dbflist[m.i,m.scolnum] = ALLTRIM(STR(m.cnum,4))
  2579.                      ENDFOR
  2580.                   ENDIF
  2581.                ELSE
  2582.                   * Use the screen coordinates in the SCX file to figure out
  2583.                   * where to put the control panel
  2584.                   IF scrnfile.center
  2585.                      m.vcoord = (my_srows() + scrnfile.height) / 2 + 3
  2586.                   ELSE
  2587.                      m.vcoord = scrnfile.vpos + scrnfile.height + 1
  2588.                   ENDIF
  2589.                   m.hcoord = INT((my_scols()-tranfont(73,6,m.g_dfltfface,m.g_dfltfsize,m.g_dfltfstyle))/2)
  2590.                   IF m.vcoord + 3 > my_srows()
  2591.                      m.vcoord = my_srows()-3
  2592.                   ENDIF
  2593.                ENDIF
  2594.                REPLACE FLOAT WITH .T., CLOSE WITH .T.
  2595.  
  2596.                * Force a select of the dbfname database whenever the screen
  2597.                * is activated.  This is necessary for the 1-to-many operations,
  2598.                * where clicking on a browse window will select some other
  2599.                * database.  We have to reselect dbfname when the user clicks in
  2600.                * on the dbfname screen.  This code stuffs a "SELECT dbfname"
  2601.                * into the activate snippet of the user screen, but only if there
  2602.                * isn't one there already.
  2603.                m.found_line = .F.
  2604.  
  2605.                * First scan for a previous FoxApp inserted line
  2606.                _MLINE = 0
  2607.                m.numlines = MEMLINES(scrnfile.activate)
  2608.                m.i = 1
  2609.                m.newact = ""
  2610.                DO WHILE m.i <= m.numlines
  2611.                   m.theline   = MLINE(scrnfile.activate,1,_MLINE)
  2612.                   m.theline = ALLTRIM(UPPER(m.theline))
  2613.                   DO CASE
  2614.                   CASE UPPER("SELECT ") $ theline AND "**FOXAPP**" $ theline
  2615.                      * We found a previous FoxApp 2.5 insert.  Is it the right one?
  2616.                      * It might not be if the user renamed the database.
  2617.                      IF UPPER("SELECT "+makealias(juststem(m.dbfname)))+" " $ m.theline
  2618.                         m.found_line = .T.
  2619.                         m.newact = m.newact + CHR(13) + CHR(10) + m.theline
  2620.                      ELSE
  2621.                         * FoxApp statement, but the wrong one.  Ignore it.
  2622.                      ENDIF
  2623.                   CASE C_FACOMM $ theline
  2624.                      * FoxApp 2.0 insert.  Drop this comment and the line that
  2625.                      * follows it, unless the following line doesn't look like
  2626.                      * one of mine.  The insert should always be a SELECT
  2627.                      * statement.
  2628.                      m.theline   = MLINE(scrnfile.activate,1,_MLINE)
  2629.                      m.theline = ALLTRIM(UPPER(m.theline))
  2630.                      IF !("SELECT " $ m.theline)
  2631.                         m.newact = m.newact + CHR(13) + CHR(10) + m.theline
  2632.                      ENDIF
  2633.                   OTHERWISE   && not a FoxApp statement
  2634.                      m.newact = m.newact + CHR(13) + CHR(10) + m.theline
  2635.                   ENDCASE
  2636.                   m.i = m.i + 1
  2637.                ENDDO
  2638.                IF !m.found_line
  2639.                   m.newact = m.newact  ;
  2640.                      + CHR(13) + CHR(10) + "SELECT "+makealias(juststem(m.dbfname))+"   "+CHR(38)+CHR(38)+" Added by **FOXAPP**"
  2641.                ENDIF
  2642.                REPLACE scrnfile.activate WITH m.newact
  2643.                USE
  2644.             ENDIF   && not wizard screen
  2645.          ELSE
  2646.             * This should never happen
  2647.             = FA_Alert(C_NOSCXHD)
  2648.             RETURN .F.
  2649.          ENDIF
  2650.       ELSE
  2651.          * This should never happen
  2652.           = FA_Alert(C_NOSCXOPN)
  2653.          RETURN .F.
  2654.       ENDIF
  2655.       RELEASE newact, found_line, theline, i, numlines
  2656.  
  2657.       \m.win_name = "<<m.win_name>>"
  2658.       \m.wiz_screen = <<IIF(m.wizscreen,".T.", ".F.")>>
  2659.       * This is the main loop to display the screen and any related browses.
  2660.       \DO WHILE !m.bailout
  2661.       \   * C_TDBSET
  2662.       \   DO setrelat
  2663.       \   * C_TSCXDISP
  2664.       \   DO <<FNAddQuotes(m.sc_file)>>
  2665.       \   * C_TNODBCLS
  2666.       \   m.stem = makealias(juststem(m.dbfname))
  2667.       \   IF !USED(m.stem)
  2668.       \      SELECT 0
  2669.       \      USE (m.dbfname)
  2670.       \   ENDIF
  2671.       \ENDDO
  2672.       \DO cleanup
  2673.       \RETURN
  2674.       \
  2675.       \
  2676.       \*******************************************************************
  2677.       \PROCEDURE cleanup
  2678.       \* C_TCLEANUP
  2679.       \SET PROCEDURE TO
  2680.       \CLOSE DATABASES
  2681.       \CLEAR WINDOWS
  2682.       \IF _WINDOWS OR _MAC
  2683.       \   MODIFY WINDOW SCREEN FONT m.scrn_font, m.scrn_fsize STYLE m.scrn_fstyle
  2684.       \ENDIF
  2685.  
  2686.       \IF SET('TALK') = 'ON'
  2687.       \   SET TALK OFF
  2688.       \   m.t_stat = 'ON'
  2689.       \ELSE
  2690.       \   m.t_stat = 'OFF'
  2691.       \ENDIF
  2692.       \SET TALK OFF
  2693.       \* C_TRESTENV
  2694.       \IF FILE("appview.vue")
  2695.       \   SET VIEW TO appview
  2696.       \   SET TALK OFF
  2697.       \   DELETE FILE appview.vue
  2698.       \ENDIF
  2699.  
  2700.       \IF FILE("foxapp.fky")
  2701.       \   RESTORE MACROS FROM foxapp
  2702.       \   DELETE FILE foxapp.fky
  2703.       \ENDIF
  2704.       \IF m.t_stat = "ON"
  2705.       \   SET TALK ON
  2706.       \ENDIF
  2707.  
  2708.       \SET POINT TO "&set_point"
  2709.       \POP KEY ALL
  2710.       \POP MENU _msysmenu
  2711.       \CLEAR PROGRAM
  2712.       \
  2713.       \* C_RESTERR
  2714.       \IF TYPE('fxapp_error') = 'C'
  2715.       \   ON ERROR &fxapp_error
  2716.       \ENDIF
  2717.       \
  2718.       \IF TYPE('fxapp_esc') = 'C'
  2719.       \   ON ESCAPE &fxapp_esc
  2720.       \ENDIF
  2721.       \
  2722.  
  2723.       \SET SAFETY ON
  2724.       \RELEASE m.bailout, m.dbfname, m.win_name, m.wiz_screen, m.filt_expr, m.srchterm, m.skipvar, m.act3
  2725.       \RELEASE dbflist
  2726.       \RETURN
  2727.  
  2728.       \
  2729.       \*******************************************************************
  2730.       \PROCEDURE setrelat
  2731.       \* C_TSREL1
  2732.       \* C_TSREL2
  2733.       \* C_TSREL3
  2734.       IF TYPE("DBFLIST") <> "U"
  2735.          m.i = 2
  2736.          DO WHILE !EMPTY(dbflist[m.i,m.cstemnum]) AND dbflist[m.i,m.cstemnum] <> '\'
  2737.             m.b_font = dbflist[m.i,m.thefont]
  2738.             \SELECT <<m.i>>
  2739.             tagname = SUBSTR(dbflist[m.i,m.cfldnum],AT('.',dbflist[m.i,m.cfldnum])+1)
  2740.             \dname = "<<dbflist[m.i,m.cdbfnum]>>"
  2741.             \IF !FILE(m.dname)
  2742.             \   m.dname = GETFILE('DBF',C_TPLSLOC+Juststem(m.dname)+ C_TDBF2)
  2743.             \   IF EMPTY(m.dname) OR !FILE(m.dname)
  2744.             \      DO alert WITH C_TTHE +ALLTRIM(m.dname+C_TDBNOTFD)
  2745.             \      DO cleanup
  2746.             \      CANCEL
  2747.             \   ELSE
  2748.             \      SET PATH TO (SET('PATH') + ';' + Justpath(m.dname))
  2749.             \      dbflist[<<m.i>>,m.cdbfnum]  = m.dname
  2750.             \      dbflist[<<m.i>>,m.cstemnum] = makealias(juststem(m.dname))
  2751.             \   ENDIF
  2752.             \ENDIF
  2753.             \USE (m.dname) ALIAS <<dbflist[m.i,m.cstemnum]>> ;
  2754.             \   ORDER TAG <<m.tagname>>
  2755.             \DEFINE WINDOW <<"W_"+dbflist[m.i,m.cstemnum]>> ;
  2756.             \   AT   <<CHRTRAN(dbflist[m.i,m.srownum],",",".")>>, ;
  2757.             \        <<CHRTRAN(dbflist[m.i,m.scolnum],",",".")>>  ;
  2758.             \   SIZE <<CHRTRAN(dbflist[m.i,m.erownum],",",".")>>, ;
  2759.             \        <<CHRTRAN(dbflist[m.i,m.ecolnum],",",".")>> ;
  2760.             \   FLOAT GROW ZOOM NOCLOSE MINIMIZE ;
  2761.             \   FONT "<<m.g_dfltfface>>",<<m.g_dfltfsize>> ;
  2762.             \   STYLE "<<m.g_dfltfstyle>>" ;
  2763.             \   HALF ;
  2764.             \   COLOR SCHEME 10
  2765.             \BROWSE NOWAIT;
  2766.             \   PREFERENCE <<"P_"+dbflist[m.i,m.cstemnum]>> ;
  2767.             \   WINDOW <<"W_"+dbflist[m.i,m.cstemnum]>> ;
  2768.             \   NOAPPEND ;
  2769.             \   <<IIF(m.nextdbf>1,"NODELETE","")>> ;
  2770.             \   COLOR SCHEME 10
  2771.  
  2772.             m.i = m.i + 1
  2773.          ENDDO
  2774.  
  2775.          m.i = 2
  2776.          DO WHILE !EMPTY(dbflist[m.i,m.cstemnum]) AND dbflist[m.i,m.cstemnum] <> '\'
  2777.             \SELECT <<makealias(Juststem(dbflist[m.i,m.pdbfnum]))>>
  2778.             \<<dbflist[m.i,m.relstrnum]>> ADDITIVE
  2779.             \
  2780.             \* C_TSEEREC1
  2781.             \* C_TSEEREC2
  2782.             \*SET FILTER TO FOUND('<<dbflist[m.i,m.cstemnum]>>')
  2783.             \
  2784.             m.i = m.i + 1
  2785.          ENDDO
  2786.          \SELECT <<makealias(Juststem(m.dbfname))>>
  2787.       ENDIF
  2788.       \RETURN
  2789.       \
  2790.       \
  2791.       \*******************************************************************
  2792.       \PROCEDURE definedbf
  2793.       \* C_TDEFARR
  2794.       \PUBLIC dbflist[m.numareas,m.numcols]
  2795.       FOR m.i = 1 TO m.numareas
  2796.          FOR m.j = 1 TO m.numcols
  2797.             IF TYPE("DBFLIST") <> "U"
  2798.                IF TYPE("dbflist[m.i,m.j]") = "C"
  2799.                   \DBFLIST[<<m.i>>,<<m.j>>] = <<'"'+dbflist[m.i,m.j]+'"'>>
  2800.                ELSE
  2801.                   \DBFLIST[<<m.i>>,<<m.j>>] = <<dbflist[m.i,m.j]>>
  2802.                ENDIF
  2803.             ELSE
  2804.                \DBFLIST[<<m.i>>,<<m.j>>] = ''
  2805.             ENDIF
  2806.          ENDFOR
  2807.       ENDFOR
  2808.       \
  2809.       \
  2810.       \*******************************************************************
  2811.  
  2812.       SET TEXTMERGE TO
  2813.       SET TEXTMERGE OFF
  2814.       SET CONSOLE ON
  2815.       SET NOTIFY OFF
  2816.  
  2817.       SET POINT TO &mpoint
  2818.  
  2819.       * Release the large dbflist array so that we don't run out of
  2820.       * memory and/or other system resources during project generation
  2821.       RELEASE dbflist, i, j, m.b_font
  2822.  
  2823.       m.appname  = UPPER(ALLTRIM(m.appfile))
  2824.       m.projname = forceext(m.appname,'PJX')
  2825.  
  2826.       * Compute the mimimum path between the project home directory
  2827.       * and the SCX file. We'll want the mimimum path stored in the
  2828.       * project file we are about to build so that the project will
  2829.       * be portable across directories.
  2830.       m.sc_name = SYS(2014,m.scxname,m.appname)
  2831.  
  2832.       m.p_path = addcolon(justpath(m.projname))
  2833.       SET DEFAULT TO (m.p_path)
  2834.  
  2835.       * Clear any existing project files.  Start with a clean slate.
  2836.       IF FILE(m.projname)
  2837.          DELETE FILE (m.projname)
  2838.       ENDIF
  2839.       pjtname = forceext(m.projname,'PJT')
  2840.       IF FILE(m.pjtname)
  2841.          DELETE FILE (m.pjtname)
  2842.       ENDIF
  2843.  
  2844.       * One last check to make sure that the user didn't leave a
  2845.       * poisonous MPR hanging around.
  2846.       m.mpr_name = FULLPATH(addbs(justpath(m.projname))+'APPMENU.MPR')
  2847.       IF FILE(m.mpr_name)
  2848.          DELETE FILE (mpr_name)
  2849.          m.mpx_name = FULLPATH(addbs(justpath(m.projname))+'APPMENU.MPX')
  2850.          IF FILE(m.mpx_name)
  2851.             DELETE FILE (mpx_name)
  2852.          ENDIF
  2853.       ENDIF
  2854.       RELEASE mpr_name, mpx_name
  2855.  
  2856.       * Build the actual application project file and APP now
  2857.       SET MESSAGE TO C_BLDPJX
  2858.       IF m.regen
  2859.          DO copypiece   && copy FoxApp pieces to project directory
  2860.          BUILD PROJECT (m.projname) FROM ;
  2861.             (m.tmfname),    ;
  2862.             (m.scxname),    ;
  2863.             appproc.prg,    ;
  2864.             appmenu.mnx,    ;
  2865.             prtsetup.scx,   ;
  2866.             getdest.scx,    ;
  2867.             getorder.scx,   ;
  2868.             appabout.scx,   ;
  2869.             appsrch.scx
  2870.       ELSE
  2871.          prg1 = addbs(m.foxappdir)+'PRGS\appproc.prg'
  2872.          prg2 = addbs(m.foxappdir)+'MENUS\appmenu.prg'
  2873.          prg3 = addbs(m.foxappdir)+'SCREENS\prtsetup.prg'
  2874.          prg4 = addbs(m.foxappdir)+'SCREENS\getdest.prg'
  2875.          prg5 = addbs(m.foxappdir)+'SCREENS\getorder.prg'
  2876.          prg6 = addbs(m.foxappdir)+'SCREENS\appabout.prg'
  2877.          prg7 = addbs(m.foxappdir)+'SCREENS\appsrch.prg'
  2878.       
  2879.          BUILD PROJECT (m.projname) FROM              ;
  2880.             (m.tmfname),                              ;
  2881.             (prg1),    ;
  2882.             (prg2),   ;
  2883.             (prg3),;
  2884.             (prg4), ;
  2885.             (prg5),;
  2886.             (prg6),;
  2887.             (prg7), ;
  2888.             (m.sc_name)
  2889.       ENDIF
  2890.  
  2891.       IF !m.wizscreen
  2892.          * Modify the new project to merge the FoxApp control panel
  2893.          * with the user screen (SCXNAME) into one screen set.
  2894.          SET MESSAGE TO C_CTRLMSG
  2895.  
  2896.          DO mergectrl WITH m.projname, m.scxname, m.vcoord, m.hcoord
  2897.       ENDIF
  2898.       SET MESSAGE TO C_BLDAPP
  2899.       BUILD APP (m.appname) FROM (m.projname)
  2900.  
  2901.       * Set the default path back to what it was
  2902.       SET DEFAULT TO (c_path)
  2903.  
  2904.       SET NOTIFY ON
  2905.  
  2906.       CLEAR READ
  2907.    ENDIF
  2908. ENDIF
  2909. m.GenSuccess = .t.
  2910.  
  2911. RETURN .T.
  2912.  
  2913.  
  2914. PROCEDURE AppScxShow
  2915. * READ-level SHOW clause for appscx screen
  2916. *------------------------------------------------------------------
  2917. DO CASE
  2918. CASE EMPTY(m.dbfname)
  2919.    IF !_MAC
  2920.      SHOW GET generate DISABLE
  2921.      SHOW GET other    DISABLE
  2922.    ENDIF
  2923.    SHOW GET adddbf   DISABLE
  2924.    SHOW GET moddbf   DISABLE
  2925. CASE !FILE(m.dbfname)
  2926.    IF !_MAC
  2927.      SHOW GET generate DISABLE
  2928.      SHOW GET other    DISABLE
  2929.    ENDIF
  2930.    SHOW GET adddbf   ENABLE
  2931.    SHOW GET moddbf   DISABLE
  2932. OTHERWISE   && everything is ok
  2933.    SHOW GET generate ENABLE
  2934.    SHOW GET other    ENABLE
  2935.    SHOW GET adddbf   DISABLE
  2936.    SHOW GET moddbf   ENABLE
  2937. ENDCASE
  2938.  
  2939. DO CASE
  2940. CASE EMPTY(m.scxname)
  2941.    SHOW GET addscx   DISABLE
  2942.    SHOW GET modscx   DISABLE
  2943.    SHOW GET arrange  DISABLE
  2944.    SHOW GET generate DISABLE
  2945. CASE !FILE(m.scxname)
  2946.    SHOW GET addscx   ENABLE
  2947.    SHOW GET modscx   DISABLE
  2948.    SHOW GET arrange  DISABLE
  2949. OTHERWISE   && everything is ok
  2950.    SHOW GET addscx   DISABLE
  2951.    SHOW GET modscx   ENABLE
  2952.    SHOW GET arrange  ENABLE
  2953. ENDCASE
  2954.  
  2955. * See if there is a stored resource for this database in the current
  2956. *    resource file.  This is in the SHOW snippet instead of in the
  2957. *    VALID for the "related" button since we want to get this information
  2958. *    even if the user never presses "related" in this session.
  2959. IF !EMPTY(m.dbfname) AND !m.rsc_check AND m.retrieversc
  2960.    IF !EMPTY(ALIAS())
  2961.       m.nextdbf = getdbflist(ALIAS())
  2962.       * Only check the resource file once
  2963.       m.rsc_check = .T.
  2964.    ENDIF
  2965. ENDIF
  2966.  
  2967. IF relateddbfs() AND !EMPTY(m.scxname) AND FILE(m.scxname)
  2968.    SHOW GET arrange  ENABLE
  2969. ELSE
  2970.    SHOW GET arrange  DISABLE
  2971. ENDIF   
  2972.  
  2973.  
  2974. PROCEDURE BrResValid
  2975. * Browse FoxApp resource file entries
  2976. * VALID clause for from Browse Resources button on Advance screen
  2977. *------------------------------------------------------------------
  2978. PRIVATE m.in_area, m.in_del
  2979. m.in_del  = SET("DELETED")
  2980. SET DELETED ON
  2981. m.in_area = SELECT()
  2982. SELECT 0
  2983. USE (SYS(2005)) AGAIN ALIAS app_rsc
  2984. DO CASE
  2985. CASE _MAC
  2986.    DEFINE WINDOW rsc_brow FROM 4,my_scols()/2-35/2 TO 14,my_scols()/2+35/2 ;
  2987.       CLOSE GROW FLOAT ZOOM MINIMIZE ;
  2988.       TITLE C_RSCTITLE ;
  2989.       FONT "Monaco",9
  2990.  
  2991. CASE _DOS
  2992.    DEFINE WINDOW rsc_brow FROM 4,my_scols()/2-35/2 TO 14,my_scols()/2+35/2 ;
  2993.       TITLE C_RSCTITLE ;
  2994.       SYSTEM ;
  2995.       FLOAT ;
  2996.       CLOSE ;
  2997.       SHADOW ;
  2998.       MINIMIZE 
  2999.  
  3000. OTHERWISE
  3001.    DEFINE WINDOW rsc_brow FROM 4,my_scols()/2-35/2 TO 14,my_scols()/2+35/2 ;
  3002.       CLOSE GROW FLOAT ZOOM MINIMIZE ;
  3003.       TITLE C_RSCTITLE ;
  3004.       FONT "FoxFont",9
  3005.  
  3006. ENDCASE
  3007.  
  3008. BROWSE LAST ;
  3009.    WINDOW rsc_brow ;
  3010.    FIELD app_rsc.type, app_rsc.id, app_rsc.name ;
  3011.    FOR UPPER(ALLTRIM(app_rsc.type)) == UPPER(ALLTRIM(m.rsctype))
  3012. USE
  3013. RELEASE WINDOW rsc_brow
  3014. SELECT (m.in_area)
  3015. SET DELETED &in_del
  3016. return
  3017.  
  3018.  
  3019. PROCEDURE TEMPERR
  3020. * Trap specific error if dbf not selected
  3021.  
  3022. = FA_Alert(C_NOTADBF)
  3023.  
  3024. return
  3025.       
  3026.       
  3027. PROCEDURE FA_Alert
  3028. * Alert dialog that uses MSGBOX() in foxtools.fll, if that library
  3029. * was loaded.
  3030. * ----------------------------------------------------------------
  3031.  
  3032. PARAMETER fa_emsg,fa_alerttype
  3033.  
  3034. if ! fa_loadlib
  3035.   wait window fa_emsg
  3036.   return
  3037. endif
  3038.  
  3039. IF TYPE('fa_emsg')<>'C'
  3040.    return
  3041. ENDIF
  3042.  
  3043. IF EMPTY(fa_alerttype) OR TYPE('fa_alerttype')#'N'
  3044.   fa_alerttype=0
  3045. ENDIF
  3046.  
  3047. * for evaluating macro substitutions
  3048. IF AT('&',fa_emsg)>0
  3049.     fa_emsg='&fa_emsg'
  3050. ENDIF
  3051.  
  3052. IF fa_alerttype=1
  3053.   RETURN msgbox(m.fa_emsg,"FoxApp",C_YESNO+C_ICONQ)=C_YES
  3054. ELSE
  3055.   RETURN msgbox(m.fa_emsg,"FoxApp",C_OK+C_ICONEXCL)
  3056. ENDIF      
  3057.       
  3058.       
  3059.