*
* GENMENU - Menu code generator.
*
* Copyright (c) 1990 - 1993 Microsoft Corp.
* 1 Microsoft Way
* Redmond, WA 98052
*
* Description:
* This program generates menu code which was designed in the
* FoxPro 2.5 MENU BUILDER.
*
* Notes:
* In this program, for clarity/readability reasons, we use variable
* names that are longer than 10 characters. Note, however, that only
* the first 10 characters are significant.
*
* Modification History:
* December 13, 1990 JAC Program Created
*
* Modifed for FoxPro 2.5 by WJK.
*
PARAMETER m.projdbf, m.recno
PRIVATE ALL
IF SET("TALK") = "ON"
SET TALK OFF
m.talkstate = "ON"
ELSE
m.talkstate = "OFF"
ENDIF
m.escape = SET("ESCAPE")
*SET ESCAPE OFF
m.trbetween = SET("TRBET")
SET TRBET OFF
m.comp = SET("COMPATIBLE")
SET COMPATIBLE OFF
mdevice = SET("DEVICE")
SET DEVICE TO SCREEN
*
* Declare Constants
*
#DEFINE c_esc CHR(27)
#DEFINE c_null CHR(0)
#DEFINE c_aliaslen 10
*
* Possible values of Objtype field in SCX database.
*
#DEFINE c_menu 1
#DEFINE c_submenu 2
#DEFINE c_item 3
*
* Some of the values of Objcode field in SCX database.
*
#DEFINE c_global 1
#DEFINE c_proc 80
#DEFINE c_maxsnippets 25
#DEFINE c_maxpads 25
#DEFINE c_pjx20flds 33
#DEFINE c_pjxflds 31
#DEFINE c_mnxflds 23
#DEFINE c_20mnxflds 22
#DEFINE c_authorlen 45
#DEFINE c_complen 45
#DEFINE c_addrlen 45
#DEFINE c_citylen 20
#DEFINE c_statlen 5
#DEFINE c_ziplen 10
#DEFINE c_countrylen 40
#DEFINE c_error_1 "Minor"
#DEFINE c_error_2 "Serious"
#DEFINE c_error_3 "Fatal"
IF _MAC
m.g_dlgface = "Geneva"
m.g_dlgsize = 10.000
m.g_dlgstyle = ""
ELSE
m.g_dlgface = "MS Sans Serif"
m.g_dlgsize = 8.000
m.g_dlgstyle = "B"
ENDIF
#DEFINE c_replace 0
#DEFINE c_append 1
#DEFINE c_before 2
#DEFINE c_after 3
#DEFINE c_pathsep "\"
*
* Declare Variables
*
STORE "" TO m.cursor, m.consol, m.bell, m.onerror, ;
m.exact, m.print, m.fixed, m.delimiters, m.mpoint, m.mcollate,m.mmacdesk
STORE 0 TO m.deci, m.memowidth
m.g_error = .F.
m.g_errlog = ""
m.g_homedir = ""
m.g_location = 0
m.g_menucolor = 0
m.g_menumark = ""
m.g_nohandle = .T.
m.g_nsnippets = 0
m.g_outfile = ""
m.g_padloca = ""
m.g_projalias = ""
m.g_projdbf = m.projdbf
m.g_projpath = ""
m.g_status = 0
m.g_snippcnt = 0
m.g_thermwidth = 0
m.g_workarea = 0
m.g_graphic = .F.
m.g_20mnx = .F.
m.g_devauthor = PADR("Author's Name",45," ")
m.g_devcompany = PADR("Company Name",45, " ")
m.g_devaddress = PADR("Address",45," ")
m.g_devcity = PADR("City",20," ")
m.g_devstate = " "
m.g_devzip = PADR("Zip",10," ")
m.g_devctry = PADR("Country",40," ")
m.g_boxstrg = ['Ä','Ä','³','³','Ú','¿','À','Ù','Ä','Ä','³','³','Ú','¿','À','Ù']
STORE "" TO m.g_corn1, m.g_corn2, m.g_corn3, m.g_corn4, m.g_corn5, ;
m.g_corn6, m.g_verti2
STORE "*" TO m.g_horiz, m.g_verti1
*
* Array Declarations
*
* g_mnxfile [1] - Normalized path + name
* g_mnxfile [2] - Basename
* g_mnxfile [3] - Opened originally?
* g_mnxfile [4] - Alias
*
DIMENSION g_mnxfile[4]
g_mnxfile[1] = ""
g_mnxfile[2] = ""
g_mnxfile[3] = .F.
g_mnxfile[4] = ""
*
* g_pads - names of generated menu pads
*
DIMENSION g_pads(c_maxpads)
*
* g_snippets [*,1] - generated snippet procedure name
* g_snippets [*,2] - recno()
*
DIMENSION g_snippets (c_maxsnippets,2)
g_snippets = ""
IF AT("WINDOWS", UPPER(VERSION())) <> 0 OR ;
AT("MAC", UPPER(VERSION())) <> 0
m.g_graphic = .T.
ELSE
m.g_graphic = .F.
ENDIF
*
* Main program
*
m.onerror = ON("ERROR")
ON ERROR DO errorhandler WITH MESSAGE(), LINENO(), c_error_3
IF PARAMETERS()=2
DO setup
IF validparams()
ON ESCAPE DO eschandler
SET ESCAPE ON
DO refreshprefs
DO BUILD
ENDIF
DO cleanup
ELSE
DO errorhandler WITH "Invalid number of parameters passed to"+;
" the generator",LINENO(),c_error_3
ENDIF
ON ERROR &onerror
RETURN m.g_status
**
** Setup, Cleanup, Validparams, and Refreshprefs of Main Program
**
*
* STARTUP - Create program's environment.
*
* Description:
* Save the user's environment so that we can set it back when
* we are done, then issue various SET commands. The only state
* we cannot conveniently save is SET TALK, because storing the
* state involves an assignment statement, and assignments
* generate unwanted output if TALK is set ON.
*
* Side Effects:
* Creates a temporary file which is deleted in the Cleanup
* procedure executed at the end of MENUGEN.
*
PROCEDURE setup
CLEAR PROGRAM
CLEAR GETS
m.g_workarea = SELECT()
m.delimiters = SET('TEXTMERGE',1)
SET TEXTMERGE DELIMITERS TO
SET UDFPARMS TO VALUE
m.bell = SET("BELL")
SET BELL OFF
m.consol = SET("CONSOLE")
SET CONSOLE OFF
m.cursor = SET("CURSOR")
SET CURSOR OFF
m.deci = SET("DECIMALS")
SET DECIMALS TO 0
mdevice = SET("DEVICE")
SET DEVICE TO SCREEN
m.memowidth = SET("MEMOWIDTH")
SET MEMOWIDTH TO 256
m.exact = SET("EXACT")
SET EXACT ON
m.print = SET("PRINT")
SET PRINT OFF
m.fixed = SET("FIXED")
SET FIXED ON
mpoint = SET("POINT")
SET POINT TO "."
mcollate = SET("COLLATE")
SET COLLATE TO "machine"
#if "MAC" $ UPPER(VERSION(1))
IF _MAC
m.mmacdesk = SET("MACDESKTOP")
SET MACDESKTOP ON
ENDIF
#endif
*
* CLEANUP - restore environment to pre-execution state.
*
* Description:
* Close all databases opened in the course of the execution of MENUGEN.
* Restore the environment to the pre-execution of MENUGEN. Delete
* the VIEW file since there is no further use for it.
*
* Side Effects:
* Closes databases.
* Deletes the temporary view file.
*
PROCEDURE cleanup
PRIVATE m.delilen, m.ldelimi, m.rdelimi
IF EMPTY(m.g_projalias)
RETURN
ENDIF
SELECT (m.g_projalias)
USE
IF NOT EMPTY(g_mnxfile[3])
IF USED(g_mnxfile[4])
SELECT (g_mnxfile[4])
USE
ENDIF
ENDIF
SELECT (m.g_workarea)
m.delilen = LEN(m.delimiters)
m.ldelimi = SUBSTR(m.delimiters,1,;
IIF(MOD(m.delilen,2)=0,m.delilen/2,CEILING(m.delilen/2)))
m.rdelimi = SUBSTR(m.delimiters,;
IIF(MOD(m.delilen,2)=0,m.delilen/2+1,CEILING(m.delilen/2)+1))
SET TEXTMERGE DELIMITERS TO m.ldelimi, m.rdelimi
IF m.bell = "ON"
SET BELL ON
ENDIF
IF m.cursor = "ON"
SET CURSOR ON
ELSE
SET CURSOR OFF
ENDIF
IF m.consol = "ON"
SET CONSOLE ON
ENDIF
IF m.escape = "ON"
SET ESCAPE ON
ELSE
SET ESCAPE OFF
ENDIF
IF m.print = "ON"
SET PRINT ON
ENDIF
IF m.exact = "OFF"
SET EXACT OFF
ENDIF
IF m.fixed = "OFF"
SET FIXED OFF
ENDIF
SET DECIMALS TO m.deci
SET MEMOWIDTH TO m.memowidth
SET DEVICE TO &mdevice
IF m.trbetween = "ON"
SET TRBET ON
ENDIF
IF m.comp = "ON"
SET COMPATIBLE ON
ENDIF
IF m.talkstate = "ON"
SET TALK ON
ENDIF
SET POINT TO "&mpoint"
SET COLLATE TO "&mcollate"
SET MESSAGE TO
#if "MAC" $ UPPER(VERSION(1))
IF _MAC
SET MACDESKTOP &mmacdesk
ENDIF
#endif
ON ERROR &onerror
*
* VALIDPARAMS - Validate generator parameters.
*
* Description:
* Attempt to open the project database. If error encountered then
* on error routine takes over and issues 'CANCEL'. The output file
* cannot be erased, name not known.
*
FUNCTION validparams
SELECT 0
m.g_projalias = IIF(USED("projdbf"),"P"+;
SUBSTR(LOWER(SYS(3)),2,8),"projdbf")
USE (m.projdbf) ALIAS (m.g_projalias)
IF versnum() > "2.5"
SET NOCPTRANS TO devinfo, arranged, symbols, object
ENDIF
m.g_errlog = stripext(m.projdbf)
m.g_projpath = SUBSTR(m.projdbf,1,RAT("\",m.projdbf))
IF FCOUNT() <> c_pjxflds
DO errorhandler WITH "Generator out of date.",;
LINENO(), c_error_2
RETURN .F.
ENDIF
GOTO RECORD m.recno
m.g_outfile = ALLTRIM(SUBSTR(outfile,1,AT(c_null,outfile)-1))
m.g_outfile = FULLPATH(m.g_outfile, m.g_projpath)
IF _MAC AND RIGHT(m.g_outfile,1) = ":"
m.g_outfile = m.g_outfile + justfname(SUBSTR(outfile,1,AT(c_null,outfile)-1))
ENDIF
g_mnxfile[1] = FULLPATH(ALLTRIM(name), m.g_projpath)
IF _MAC AND RIGHT(g_mnxfile[1],1) = ":"
g_mnxfile[1] = g_mnxfile[1] + justfname(name)
ENDIF
g_mnxfile[2] = basename(g_mnxfile[1])
*
* REFRESHPREFS - Refresh comment style and developer preferences.
*
* Description:
* Get the newest preferences for documentation style and developer
* data from the project database.
*
PROCEDURE refreshprefs
PRIVATE m.start, m.savrecno
m.savrecno = RECNO()
LOCATE FOR TYPE = "H"
IF NOT FOUND ()
DO errorhandler WITH "Missing header record in "+m.g_projdbf,;
LINENO(), c_error_2
GOTO RECORD m.savrecno
RETURN
ENDIF
m.g_homedir = ALLTRIM(SUBSTR(homedir,1,AT(c_null,homedir)-1))
m.start = 1
m.g_devauthor = subdevinfo(m.start,c_authorlen,m.g_devauthor)
m.start = m.start + c_authorlen + 1
m.g_devcompany = subdevinfo(m.start,c_complen,m.g_devcompany)
m.start = m.start + c_complen + 1
m.g_devaddress = subdevinfo(m.start,c_addrlen,m.g_devaddress)
m.start = m.start + c_addrlen + 1
m.g_devcity = subdevinfo(m.start,c_citylen,m.g_devcity)
m.start = m.start + c_citylen + 1
m.g_devstate = subdevinfo(m.start,c_statlen,m.g_devstate)
m.start = m.start + c_statlen + 1
m.g_devzip = subdevinfo(m.start,c_ziplen,m.g_devzip)
m.start = m.start + c_ziplen + 1
m.g_devctry = subdevinfo(m.start,c_countrylen,m.g_devctry)
IF cmntstyle = 0
m.g_corn1 = "Ö"
m.g_corn2 = "·"
m.g_corn3 = "Ó"
m.g_corn4 = "½"
m.g_corn5 = "Ç"
m.g_corn6 = "¶"
m.g_horiz = "Ä"
m.g_verti1 = "º"
m.g_verti2 = "º"
ENDIF
GOTO RECORD m.savrecno
*
* SUBDEVINFO - Substring the DEVINFO memo filed.
*
FUNCTION subdevinfo
PARAMETER m.start, m.stop, m.default
PRIVATE m.string
m.string = SUBSTR(devinfo, m.start, m.stop+1)
m.string = SUBSTR(m.string, 1, AT(c_null,m.string)-1)
RETURN IIF(EMPTY(m.string), m.default, m.string)
**
** Menu Code Generator's Main Module.
**
*
* BUILD - Generate code for a menu.
*
* Description:
* Call BUILDENABLE to open .MNX database specified by the user.
* If the above is successfully accomplished, then proceed to generate
* the menu code. After the menu code is generated, call BUILDDISABLE
* to disable code generation between SET TEXTMERGE ON and
* SET TEXTMERGE OFF.
*
PROCEDURE BUILD
IF NOT buildenable()
RETURN
ENDIF
DO acttherm WITH "Generating Menu Code..."
DO updtherm WITH 10
DO HEADER
DO gensetupcleanup WITH "setup"
DO definemenu
DO definepopups
DO updtherm WITH 75
DO globaldefaults
DO updtherm WITH 95
DO gensetupcleanup WITH "cleanup"
DO genprocedures
IF m.g_graphic
SET MESSAGE TO 'Generation Complete'
ENDIF
DO builddisable
DO updtherm WITH 100
DO deactthermo
*
* BUILDENABLE - Enable code generation.
*
* Description:
* Call opendb to open .MNX database.
* Call openfile to open file to hold the generated program.
* If error(s) encountered in opendb or openfile then don't do
* anything and exit, otherwise enable code generation with the
* SET TEXTMERGE ON command.
*
* Returns:
* .T. on success; .F. on failure
*
FUNCTION buildenable
PRIVATE m.stat
m.stat = opendb(g_mnxfile[1]) AND openfile()
IF m.stat
SET TEXTMERGE ON
ENDIF
RETURN m.stat
*
* BUILDDISABLE - Disable code generation.
*
* Description:
* Issue the command SET TEXTMERGE OFF.
* Close the generated menu code output file.
* If anything goes wrong display appropriate message to the user.
*
PROCEDURE builddisable
SET ESCAPE OFF
ON ESCAPE
SET TEXTMERGE OFF
IF NOT FCLOSE(_TEXT)
DO errorhandler WITH "Unable to Close the Application File",;
LINENO(), c_error_2
ENDIF
*
* OPENDB - Prepare database for processing.
*
* Description:
* Attempt to USE a database. If attempt fails and error is reported
* call ERRORHANDLER routine to display a friendly message. Return
* with a status of .F.. If attempt succeeds, return with status of .T.
*
* Returns:
* .T. on success; .F. on failure
*
FUNCTION opendb
PARAMETER m.dbname
PRIVATE m.dbalias
ON ERROR DO errorhandler WITH MESSAGE(), LINENO(), c_error_2
m.dbalias = LEFT(basename(m.dbname),c_aliaslen)
IF USED (m.dbalias)
SELECT (m.dbalias)
IF RAT(".MNX",DBF())<>0
g_mnxfile[3] = .F.
g_mnxfile[4] = m.dbalias
ELSE
g_mnxfile[4] = "M"+SUBSTR(LOWER(SYS(3)),2,8)
SELECT 0
USE (m.dbname) AGAIN ALIAS (g_mnxfile[4])
g_mnxfile[3] = .T.
ENDIF
ELSE
IF illegalname(m.dbalias)
g_mnxfile[4] = "M"+SUBSTR(LOWER(SYS(3)),2,8)
ELSE
g_mnxfile[4] = m.dbalias
ENDIF
SELECT 0
USE (m.dbname) AGAIN ALIAS (g_mnxfile[4])
g_mnxfile[3] = .T.
ENDIF
IF FCOUNT() <> c_mnxflds
IF FCOUNT() = c_20mnxflds
m.g_20mnx = .T.
ELSE
DO errorhandler WITH "Menu "+m.dbalias+" is invalid",LINENO(),;
c_error_2
RETURN .F.
ENDIF
ELSE
m.g_20mnx = .F.
ENDIF
ON ERROR DO errorhandler WITH MESSAGE(), LINENO(), c_error_3
IF m.g_error = .T.
RETURN .F.
ENDIF
*
* ILLEGALNAME - Check if default alias will be used when this
* database is USEd. (i.e., 1st letter is not A-Z,
* a-z or '_', or any one of ramaining letters is not
* alphanumeric.)
*
FUNCTION illegalname
PARAMETER m.menuname
PRIVATE m.start, m.aschar, m.length
m.length = LEN(m.menuname)
m.start = 0
IF m.length = 1
*
* If length 1, then check if default alias can be used,
* i.e., name is different than A-J and a-j.
*
m.aschar = ASC(m.menuname)
IF (m.aschar >= 65 AND m.aschar <= 74) OR ;
(m.aschar >= 97 AND m.aschar <= 106)
RETURN .T.
ENDIF
ENDIF
DO WHILE m.start < m.length
m.start = m.start + 1
m.aschar = ASC(SUBSTR(m.menuname, m.start, 1))
IF m.start<>1 AND (m.aschar >= 48 AND m.aschar <= 57)
LOOP
ENDIF
IF NOT ((m.aschar >= 65 AND m.aschar <= 90) OR ;
(m.aschar >= 97 AND m.aschar <= 122) OR m.aschar = 95)
RETURN .T.
ENDIF
ENDDO
RETURN .F.
*
* OPENFILE - Create and open the application output file.
*
* Description:
* Create a file that will hold the generated menu code.
* Open the newly created file. If error(s) encountered
* at any time issue an error message and return .F.
*
* Returns:
* .T. on success; .F. on failure
*
FUNCTION openfile
PRIVATE m.msg
_TEXT = FCREATE(m.g_outfile)
IF (_TEXT = -1)
m.msg = "Cannot open file "+m.g_outfile
DO errorhandler WITH m.msg, LINENO(), c_error_3
m.g_nohandle = .T.
RETURN .F.
ENDIF
m.g_nohandle = .F.
*
* DEFINEMENU - Define main menu and its pads.
*
* Description:
* Issue DEFINE MENU ... command.
* Call a procedure to define all menu pads.
* Call a procedure to generate ON PAD statements when appropriate.
*
PROCEDURE definemenu
IF m.g_graphic
SET MESSAGE TO 'Generating menu definitions...'
ENDIF
DO commentblock WITH "menu"
SELECT (g_mnxfile[4])
LOCATE FOR objtype = c_menu
m.g_location = location
m.g_padloca = ALLTRIM(name)
LOCATE FOR objtype = c_submenu AND objcode = c_global
m.g_menucolor = SCHEME
m.g_menumark = MARK
IF m.g_location = c_replace
\SET SYSMENU TO
\
ENDIF
\SET SYSMENU AUTOMATIC
\
DO updtherm WITH 25
DO defmenupads
DO updtherm WITH 35
DO defonpad
\
DO updtherm WITH 45
*
* DEFMENUPADS - Define all pads for the menu bar.
*
* Description:
* Scan the menu database for all objects of the type item which
* have the levelname=_MSYSMENU.
* For each such item, generate a statement DEFINE PAD... where
* the name of the pad is the contents of NAME field or (if Name
* field is empty) an automatically generated name.
* Call procedures addkey, addskipfor, and mark to generate
* KEY, SKIPFOR, or MARK clauses when appropriate.
*
PROCEDURE defmenupads
PRIVATE m.padname, m.prompt
SCAN FOR objtype=c_item AND UPPER(levelname)="_MSYSMENU"
IF NOT EMPTY(ALLTRIM(name))
g_pads[VAL(Itemnum)] = name
ELSE
g_pads[VAL(Itemnum)] = LOWER(SYS(2015))
ENDIF
\DEFINE PAD <<g_pads[VAL(Itemnum)]>> OF _MSYSMENU
IF MOD(VAL(itemnum),25)=0
DIMENSION g_pads[VAL(Itemnum)+25]
ENDIF
m.prompt = SUBSTR(PROMPT,1,LEN(PROMPT))
\\ PROMPT "<<m.prompt>>"
\\ COLOR SCHEME <<m.g_menucolor>>
IF m.g_menumark<>c_null AND m.g_menumark<>""
\\ ;
\ MARK "<<m.g_menumark>>"
ENDIF
DO CASE
CASE m.g_location = c_before
\\ ;
\ BEFORE <<m.g_padloca>>
CASE m.g_location = c_after
\\ ;
\ AFTER
IF VAL(itemnum) = 1
\\ <<m.g_padloca>>
ELSE
\\ <<g_pads[VAL(Itemnum)-1]>>
ENDIF
ENDCASE
DO addkey
DO addskipfor
DO addmessage
ENDSCAN
*
* DEFONPAD - Generate ON PAD... statements.
*
* Description:
* Generate ON PAD statements for each pad off of the main menu which
* has a submenu associated with it.
* For pads which have no submenus, but there is a command associated
* with them, issue ON SELECTION PAD... statements. If the code
* associated with a pad is a snippet, then issue a call to the
* generated procedure and place the snippet code in it.
*
PROCEDURE defonpad
PRIVATE m.padname
SCAN FOR objtype=c_item AND UPPER(levelname)="_MSYSMENU"
IF NOT EMPTY(ALLTRIM(name))
m.padname = name
ELSE
m.padname = g_pads[VAL(Itemnum)]
ENDIF
m.therec = RECNO()
SKIP
IF objtype=c_submenu AND numitems<>0
\ON PAD <<m.padname>> OF _MSYSMENU
\\ ACTIVATE POPUP <<LOWER(Name)>>
GOTO m.therec
ELSE
GOTO m.therec
DO onselection WITH "pad", m.padname, '_MSYSMENU'
ENDIF
ENDSCAN
*
* DEFINEPOPUPS - Define popups and their bars.
*
* Description:
* Scan the Menu database to find all objecttypes = submenu.
* They all correspond to popups. For each such object found, issue
* command DEFINE POPUP.... Add MARK, KEY, and SKIP FOR clauses
* if appropriate by calling procedures to handle these tasks. Call
* procedure Defbars to define all bars of each popup.
*
PROCEDURE definepopups
PRIVATE m.savrecno, m.popname, m.sch
IF m.g_graphic
SET MESSAGE TO 'Generating popup definitions...'
ENDIF
SCAN FOR objtype=c_submenu AND UPPER(levelname)<>"_MSYSMENU" ;
AND numitems <> 0
m.savrecno = RECNO()
m.popname = ALLTRIM(LOWER(levelname))
m.sch = SCHEME
\DEFINE POPUP <<LOWER(Name)>> MARGIN RELATIVE SHADOW
\\ COLOR SCHEME <<m.sch>>
DO addmark
DO addkey
DO defbars WITH m.popname, numitems
DO defonbar WITH m.popname
\
GOTO RECORD m.savrecno
ENDSCAN
*
* DEFBARS - Define bars for each popup.
*
* Description:
* Scan the menu database for all objects of the type item whose
* name equals to the current popup name.
* For each such item, generate a statement DEFINE BAR....
* Call procedures addkey, addskipfor, and addmark to generate
* KEY, SKIPFOR, or MARK clauses when appropriate.
*
PROCEDURE defbars
PARAMETER m.popname, m.howmany, m.name
PRIVATE m.itemno, m.prompt
SCAN FOR objtype=c_item AND LOWER(levelname)=m.popname
m.itemno = ALLTRIM(itemnum)
IF NOT EMPTY(ALLTRIM(name))
m.name = name
\DEFINE BAR <<m.name>> OF <<LOWER(m.popname)>>
ELSE
\DEFINE BAR <<m.itemno>> OF <<LOWER(m.popname)>>
ENDIF
m.prompt = SUBSTR(PROMPT, 1,LEN(PROMPT))
\\ PROMPT "<<m.prompt>>"
DO addmark
DO addkey
DO addskipfor
DO addmessage
IF VAL(m.itemno)=m.howmany
RETURN
ENDIF
ENDSCAN
*
* DEFONBAR - Generate ON BAR... statements.
*
* Description:
* Generate ON BAR statements for each popup.
* For bars which have no submenus, but there is a command associated
* with them, issue ON SELECTION BAR... statements. If a snippet is
* associated with the code then generate a call statement to the
* generated procedure containing the snippet code.
*
PROCEDURE defonbar
PARAMETER m.popname
PRIVATE m.itemno
SCAN FOR objtype=c_item AND LOWER(levelname)=m.popname
IF EMPTY(ALLTRIM(name))
m.itemno = ALLTRIM(itemnum)
ELSE
m.itemno = name
ENDIF
SKIP
IF objtype=c_submenu AND numitems<>0
\ON BAR <<m.itemno>> OF <<LOWER(m.popname)>>
\\ ACTIVATE POPUP <<LOWER(Name)>>
SKIP -1
ELSE
SKIP -1
DO onselection WITH "BAR", m.itemno, m.popname
ENDIF
ENDSCAN
*
* GLOBALDEFAULTS - Generate global default statements
*
* Description:
* Search the menu database for information needed to generate any of
* the following commands:
* ON SELECTION MENU <name> DO <action>
* ON SELECTION POPUP ALL DO <action>
* ON SELECTION POPUP <name> DO <action>
* It is possible that none of the above mentioned statements will be
* generated. It is also possible that the action is a snippet of
* code and a call to the generated procedure containing the snippet
* will be generated.
*
* First try to generate ON SELECTION MENU...
* Then try to generate ON POPUP ALL...
* Lastly, try to generate ON SELECTION POPUP...
*
PROCEDURE globaldefaults
LOCATE FOR objtype = c_menu
m.mrk = MARK
IF FOUND() AND MARK <> ""
IF MARK = c_null
\SET MARK OF MENU _MSYSMENU TO " "
ELSE
\SET MARK OF MENU _MSYSMENU TO "<<Mark>>"
ENDIF
ENDIF
IF FOUND() AND NOT EMPTY(PROCEDURE)
\ON SELECTION MENU _MSYSMENU
DO genproccall
ENDIF
LOCATE FOR objtype = c_submenu AND objcode = c_global
IF FOUND() AND NOT EMPTY(PROCEDURE)
\ON SELECTION POPUP ALL
DO genproccall
ENDIF
SCAN FOR (objtype=c_submenu AND UPPER(levelname)<>"_MSYSMENU";
AND NOT EMPTY(PROCEDURE))
\ON SELECTION POPUP <<ALLTRIM(LOWER(Levelname))>>
DO genproccall
ENDSCAN
**
** Subroutines for processing menu clause options.
**
*
* ADDMARK - Generate a MARK clause whenever appropriate.
*
* Description:
* Add a MARK clause to the current PAD or BAR definition.
* If a field named Mark is not empty, then add the continuation
* character, ";", to the previous line, and then add the MARK... clause.
*
PROCEDURE addmark
IF MARK<>c_null AND MARK<>""
\\ ;
\ MARK "<<Mark>>"
ENDIF
*
* ADDKEY - Generate KEY... clause whenever appropriate.
*
* Description:
* Add a KEY clause to the current PAD or BAR definition.
* If a field named Keyname is not empty, then add the continuation
* character, ";", to the previous line, and then add the KEY... clause.
*
PROCEDURE addkey
IF NOT EMPTY(keyname)
\\ ;
\ KEY <<Keyname>>, "<<Keylabel>>"
ENDIF
*
* ADDSKIPFOR - Generate SKIP FOR... clause whenever appropriate.
*
* Description:
* Add a ADDSKIPFOR clause to the current PAD or BAR definition.
* If a field named Addskipfor is not empty, then add the continuation
* character, ";", to the previous line, and then add the SKIP FOR...
* clause.
*
PROCEDURE addskipfor
PRIVATE m.skip
m.skip = skipfor
IF NOT EMPTY(skipfor)
\\ ;
\ SKIP FOR <<m.skip>>
ENDIF
*
* ADDMESSAGE - Generate MESSAGE clause whenever appropriate.
*
* Description:
* Add a MESSAGE clause to the current PAD or BAR definition.
* If a field named MESSAGE is not empty and it is not a 2.0 menu,
* then add the continuation character, ";", to the previous line,
* and then add the MESSAGE clause.
*
PROCEDURE addmessage
IF !m.g_20mnx AND NOT EMPTY(MESSAGE)
\\ ;
\ MESSAGE <<Message>>
ENDIF
*
* HEADER - Generate generated program's header.
*
* Description:
* As a part of the automatically generated program's header generate
* program name, name of the author of the program, copyright notice,
* company name and address, and the word 'Description:' which will be
* followed with a short description of the generated code.
*
PROCEDURE HEADER
\\* <<m.g_corn1>><<REPLICATE(m.g_horiz,57)>><<m.g_corn2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_verti1>> <<DATE()>>
\\<<PADC(UPPER(ALLTRIM(strippath(m.g_outfile))),IIF(SET("CENTURY")="ON",35,37))," ")>>
\\ <<TIME()>> <<m.g_verti2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_corn5>><<REPLICATE(m.g_horiz,57)>><<m.g_corn6>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_verti1>> <<m.g_devauthor>>
\\<<REPLICATE(" ",56-LEN(m.g_devauthor))>><<m.g_verti2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_verti1>>
\\ Copyright (c) <<YEAR(DATE())>>
IF LEN(ALLTRIM(m.g_devcompany)) <= 36
\\ <<ALLTRIM(m.g_devcompany)>>
\\<<REPLICATE(" ",37-LEN(ALLTRIM(m.g_devcompany)))>>
\\<<m.g_verti2>>
ELSE
\\ <<REPLICATE(" ",37)>><<m.g_verti2>>
\* <<m.g_verti1>> <<m.g_devcompany>>
\\<<REPLICATE(" ",56-LEN(m.g_devcompany))>><<m.g_verti2>>
ENDIF
\* <<m.g_verti1>> <<m.g_devaddress>>
\\<<REPLICATE(" ",56-LEN(m.g_devaddress))>><<m.g_verti2>>
\* <<m.g_verti1>> <<ALLTRIM(m.g_devcity)>>, <<m.g_devstate>>
\\ <<ALLTRIM(m.g_devzip)>>
\\<<REPLICATE(" ",50-(LEN(ALLTRIM(m.g_devcity)+ALLTRIM(m.g_devzip))))>>
\\<<m.g_verti2>>
IF !INLIST(ALLTRIM(UPPER(m.g_devctry)),"USA","COUNTRY") AND !EMPTY(m.g_devctry)
\* <<m.g_verti1>> <<ALLTRIM(m.g_devctry)>>
\\<<REPLICATE(" ",50-(LEN(ALLTRIM(m.g_devctry))))>>
\\<<m.g_verti2>>
ENDIF
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_verti1>> Description:
\\ <<m.g_verti2>>
\* <<m.g_verti1>>
\\ This program was automatically generated by GENMENU.
\\ <<m.g_verti2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_corn3>><<REPLICATE(m.g_horiz,57)>><<m.g_corn4>>
\
*
* GENFUNCHEADER - Generate Comment for Function/Procedure.
*
PROCEDURE genfuncheader
PARAMETER m.procname
PRIVATE m.place, m.prompt
m.g_snippcnt = m.g_snippcnt + 1
DO CASE
CASE objtype = c_menu
m.place = "ON SELECTION MENU _MSYSMENU"
CASE objtype = c_submenu AND objcode = c_global
m.place = "ON SELECTION POPUP ALL"
CASE objtype = c_submenu AND objcode <> c_global
m.place = "ON SELECTION POPUP "+LOWER(ALLTRIM(name))
CASE objtype = c_item AND UPPER(levelname) = "_MSYSMENU"
m.place = "ON SELECTION PAD "
CASE objtype = c_item AND UPPER(levelname) <> "_MSYSMENU"
m.place = "ON SELECTION BAR "+ALLTRIM(itemnum)+;
+" OF POPUP "+LOWER(ALLTRIM(levelname))
OTHERWISE
m.place = ""
ENDCASE
\
\* <<m.g_corn1>><<REPLICATE(m.g_horiz,57)>><<m.g_corn2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_verti1>> <<UPPER(PADR(m.procname,10))>> <<m.place>>
\\<<REPLICATE(" ",44-LEN(m.place))>><<m.g_verti2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_verti1>> Procedure Origin:
\\<<REPLICATE(" ",39)>><<m.g_verti2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_verti1>> From Menu:
\\ <<ALLTRIM(strippath(m.g_outfile))>>
\\, Record: <<STR(RECNO(),3)>>
\\<<REPLICATE(" ",22-LEN(ALLTRIM(strippath(m.g_outfile))+STR(RECNO(),3))))>>
\\<<m.g_verti2>>
\* <<m.g_verti1>> Called By: <<m.place>>
\\<<REPLICATE(" ",44-LEN(m.place))>><<m.g_verti2>>
IF NOT EMPTY(PROMPT)
m.prompt = removemeta()
\* <<m.g_verti1>> Prompt: <<ALLTRIM(m.prompt)>>
\\<<REPLICATE(" ",44-LEN(ALLTRIM(m.prompt)))>><<m.g_verti2>>
ENDIF
\* <<m.g_verti1>> Snippet:
\\ <<ALLTRIM(STR(m.g_snippcnt,2))>>
\\<<REPLICATE(" ",44-LEN(ALLTRIM(STR(m.g_snippcnt,2))))>><<m.g_verti2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_corn3>><<REPLICATE(m.g_horiz,57)>><<m.g_corn4>>
\*
*
* REMOVEMETA - Remove meta characters for documentation.
*
FUNCTION removemeta
PRIVATE m.prompt, m.hotkey
m.prompt = PROMPT
m.hotkey = AT("\<",m.prompt)
IF m.hotkey <> 0
m.prompt = STUFF(m.prompt,m.hotkey,2,"")
ENDIF
m.disabl = AT("\",m.prompt)
IF m.disabl <> 0
m.prompt = STUFF(m.prompt,m.disabl,1,"")
ENDIF
RETURN m.prompt
*
* COMMENTBLOCK - Generate a comment block.
*
PROCEDURE commentblock
PARAMETER m.snippet
\
\* <<m.g_corn1>><<REPLICATE(m.g_horiz,57)>><<m.g_corn2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
DO CASE
CASE m.snippet == "setup"
\* <<m.g_verti1>>
\\ <<PADC(" Setup Code",56," ")>>
CASE m.snippet == "cleanup"
\* <<m.g_verti1>>
\\ <<PADC(" Cleanup Code & Procedures",56," ")>>
CASE m.snippet == "init"
\* <<m.g_verti1>>
\\ <<PADC(" Initializing Code",56," ")>>
CASE m.snippet == "menu"
\* <<m.g_verti1>>
\\ <<PADC(" Menu Definition",56," ")>>
ENDCASE
\\<<m.g_verti2>>
\* <<m.g_verti1>><<REPLICATE(" ",57)>><<m.g_verti2>>
\* <<m.g_corn3>><<REPLICATE(m.g_horiz,57)>><<m.g_corn4>>
\*
\
**
** Supporting routines
**
*
* ONSELECTION - Generate ON SELECTION... statements for menu items.
*
* Description:
* For pads and bars which have no submenu associated with them but
* instead have a non-empty Command field in the database, issue
* the ON SELECTION <command> statements. If a snippet is associated
* with a pad then issue a call statement to the generated procedure
* containing the snippet. Generated snippet procedure will be
* appended to the end of the output file.
*
PROCEDURE onselection
PARAMETER m.which, m.name, m.ofname, m.commd
PRIVATE m.trimname, m.basename
IF EMPTY(PROCEDURE) AND EMPTY(COMMAND)
RETURN
ENDIF
DO CASE
CASE m.which == "pad"
\ON SELECTION PAD <<m.name>>
CASE m.which == "BAR"
\ON SELECTION <<m.which+" "+m.name>>
ENDCASE
\\ OF <<m.ofname>>
IF objcode = c_proc
DO gensnippname
m.trimname = SYS(2014,UPPER(m.g_outfile),UPPER(m.g_homedir))
m.trimname = stripext(m.trimname)
m.basename = basename(m.trimname)
\\ ;
\ DO <<g_snippets[g_nsnippets,1]>> ;
\ IN LOCFILE("<<m.trimname>>"
\\ ,"MPX;MPR|FXP;PRG"
\\ ,"Where is <<m.basename>>?")
ELSE
m.commd = COMMAND
\\ <<m.commd>>
ENDIF
*
* GENSNIPPNAME - Generate a unique name for snippet procedure.
*
* Description:
* Lookup the #NAME name of this snippet, or alternatively
* provide a unique name for a snippet of code associated with the
* generated menu. Save this name in an array g_snippets.
*
PROCEDURE gensnippname
g_nsnippets = g_nsnippets + 1
g_snippets[g_nsnippets,1] = getcname(procedure)
g_snippets[g_nsnippets,2] = RECNO()
IF MOD(g_nsnippets,25) = 0
DIMENSION g_snippets [g_nsnippets+25,2]
ENDIF
*
* GENPROCCALL - Generate a call statement to snippet procedure.
*
* Description:
* Generate a call to the snippet procedure in the menu definition
* code.
*
PROCEDURE genproccall
PRIVATE m.trimname, m.basename, m.proc
IF singleline()
m.proc = PROCEDURE
\\ <<MLINE(m.proc,1)>>
ELSE
DO gensnippname
m.trimname = SYS(2014,UPPER(m.g_outfile),UPPER(m.g_homedir))
m.trimname = stripext(m.trimname)
m.basename = basename(m.trimname)
\\ ;
\ DO <<g_snippets[m.g_nsnippets,1]>> ;
\ IN LOCFILE("<<m.trimname>>"
\\ ,"MPX;MPR|FXP;PRG"
\\ ,"Where is <<m.basename>>?")
ENDIF
*
* SINGLELINE - Determine if Memo contains only one line.
*
* Description:
* This procedure is used to decide if an ON SELECTION... statement
* and a snippet procedure will be needed (i.e., if more than one
* line of snippet code then its a snippet, otherwise its a command)
*
FUNCTION singleline
PRIVATE m.size, m.i
m.size = MEMLINES(PROCEDURE)
IF m.size = 1
RETURN .T.
ENDIF
m.i = m.size
DO WHILE m.i > 1
m.line = MLINE(PROCEDURE, m.i)
IF NOT EMPTY(m.line)
RETURN .F.
ENDIF
m.i = m.i - 1
ENDDO
*
* GENPROCEDURES - Generate procedure/snippet code.
*
* Description:
* Generate 'PROCEDURE procedurename' statement and its body.
*
PROCEDURE genprocedures
PRIVATE m.i
IF m.g_graphic
SET MESSAGE TO 'Generating procedures...'
ENDIF
FOR m.i = 1 TO m.g_nsnippets
GOTO RECORD (g_snippets[m.i,2])
DO genfuncheader WITH g_snippets[m.i,1]
\PROCEDURE <<g_snippets[m.i,1]>>
DO writecode WITH procedure
\
ENDFOR
*
* WRITECODE - Write contents of a memo to a low level file.
*
* Description:
* Receive a memo field as a parameter and write its contents out
* to the currently opened low level file whose handle is stored
* in the system memory variable _TEXT. Contents of the system
* memory variable _pretext will affect the positioning of the
* generated text.
*
PROCEDURE writecode
PARAMETER m.memo
PRIVATE m.lines, m.i, m.thisline
m.lines = MEMLINES(m.memo)
_MLINE = 0
FOR m.i = 1 TO m.lines
m.thisline = MLINE(m.memo, 1, _MLINE)
IF LEFT(UPPER(LTRIM(m.thisline)),5) == "#INSE" && #INSERT
DO GenInsertCode WITH m.thisline
ELSE
IF LEFT(UPPER(LTRIM(m.thisline)),5) <> "#NAME"
\<<m.thisline>>
ENDIF
ENDIF
ENDFOR
*
* GENSETUPCLEANUP - Generate setup/cleanup code.
*
PROCEDURE gensetupcleanup
PARAMETER m.choice
LOCATE FOR objtype = c_menu
DO CASE
CASE m.choice == "setup"
IF EMPTY(setup)
RETURN
ENDIF
IF m.g_graphic
SET MESSAGE TO 'Generating Menu Setup Code...'
ENDIF
DO commentblock WITH m.choice
DO writecode WITH setup
CASE m.choice == "cleanup"
IF EMPTY(cleanup)
RETURN
ENDIF
IF m.g_graphic
SET MESSAGE TO 'Generating Menu Cleanup Code...'
ENDIF
DO commentblock WITH m.choice
DO writecode WITH cleanup
ENDCASE
*
* STRIPEXT - Strip the extension from a file name.
*
* Description:
* Use the algorithm employed by FoxPRO itself to strip a
* file of an extension (if any): Find the rightmost dot in
* the filename. If this dot occurs to the right of a "\"
* or ":", then treat everything from the dot rightward
* as an extension. Of course, if we found no dot,
* we just hand back the filename unchanged.
*
* Parameters:
* filename - character string representing a file name
*
* Return value:
* The string "filename" with any extension removed
*
FUNCTION stripext
PARAMETER m.filename
PRIVATE m.dotpos, m.terminator
m.dotpos = RAT(".", m.filename)
m.terminator = MAX(RAT("\", m.filename), RAT(":", m.filename))
IF m.dotpos > m.terminator
m.filename = LEFT(m.filename, m.dotpos-1)
ENDIF
RETURN m.filename
*
* STRIPPATH - Strip the path from a file name.
*
* Description:
* Find positions of backslash in the name of the file. If there is one
* take everything to the right of its position and make it the new file
* name. If there is no slash look for colon. Again if found, take
* everything to the right of it as the new name. If neither slash
* nor colon are found then return the name unchanged.
*
* Parameters:
* filename - character string representing a file name
*
* Return value:
* The string "filename" with any path removed
*
FUNCTION strippath
PARAMETER m.filename
PRIVATE m.slashpos, m.namelen, m.colonpos
m.slashpos = RAT("\", m.filename)
IF m.slashpos > 0
m.namelen = LEN(m.filename) - m.slashpos
m.filename = RIGHT(m.filename, m.namelen)
ELSE
m.colonpos = RAT(":", m.filename)
IF m.colonpos > 0
m.namelen = LEN(m.filename) - m.colonpos
m.filename = RIGHT(m.filename, m.namelen)
ENDIF
ENDIF
RETURN m.filename
*
* BASENAME - returns strippath(stripext(filespec))
*
FUNCTION basename
PARAMETER m.filespec
RETURN strippath(stripext(m.filespec))
*
* GENINSERTCODE - Emit code from the #insert file, if any
*
PROCEDURE GenInsertCode
PARAMETER strg
PRIVATE m.word1, m.filname, m.ins_fp, m.buffer
IF UPPER(LEFT(LTRIM(m.strg),5)) == "#INSE"
m.word1 = wordnum(m.strg,1)
m.filname = SUBSTR(m.strg,LEN(m.word1)+1)
m.filname = ALLTRIM(CHRTRAN(m.filname,CHR(9),""))
* Bail out if we can't find the file either explicitly or on the DOS path
IF !FILE(m.filname)
filname = FULLPATH(m.filname,1)
IF !FILE(m.filname)
\*Insert file <<m.filname>> could not be found
RETURN
ENDIF
ENDIF
ins_fp = FOPEN(m.filname)
IF ins_fp > 0
\* Inserted from <<strippath(m.filname)>>
DO WHILE !feof(ins_fp)
m.buffer = fgets(ins_fp)
\<<m.buffer>>
ENDDO
=fclose(m.ins_fp)
\* End of inserted lines
ENDIF
ENDIF
*!*****************************************************************************
*!
*! Function: JUSTPATH
*!
*! Called by: FORCEEXT() (function in GENSCRN.PRG)
*!
*!*****************************************************************************
FUNCTION justpath
* Return just the path name from "filname"
PARAMETERS m.filname
PRIVATE ALL
m.filname = ALLTRIM(UPPER(m.filname))
IF '\' $ m.filname
m.filname = SUBSTR(m.filname,1,RAT('\',m.filname))
IF RIGHT(m.filname,1) = '\' AND LEN(m.filname) > 1 ;
AND SUBSTR(m.filname,LEN(m.filname)-1,1) <> ':'
filname = SUBSTR(m.filname,1,LEN(m.filname)-1)
ENDIF
RETURN m.filname
ELSE
RETURN ''
ENDIF
**
** Code Associated with the Thermometer
**
*
* ACTTHERM(<text>) - Activate thermometer.
*
* Description:
* Activates thermometer. Update the thermometer with UPDTHERM().
* Thermometer window is named "thermometer." Be sure to RELEASE
* this window when done with thermometer. Creates the global
* m.g_thermwidth.
*
PROCEDURE acttherm
PARAMETER m.text
PRIVATE m.prompt
IF m.g_graphic
m.prompt = m.g_outfile
m.prompt = thermfname(m.prompt)
DO CASE
CASE _WINDOWS
DEFINE WINDOW thermomete ;
AT INT((SROW() - (( 5.615 * ;
FONTMETRIC(1, m.g_dlgface, m.g_dlgsize, m.g_dlgstyle )) / ;
FONTMETRIC(1, WFONT(1,""), WFONT( 2,""), WFONT(3,"")))) / 2), ;
INT((SCOL() - (( 63.833 * ;
FONTMETRIC(6, m.g_dlgface, m.g_dlgsize, m.g_dlgstyle )) / ;
FONTMETRIC(6, WFONT(1,""), WFONT( 2,""), WFONT(3,"")))) / 2) ;
SIZE 5.615,63.833 ;
FONT m.g_dlgface, m.g_dlgsize ;
STYLE m.g_dlgstyle ;
NOFLOAT ;
NOCLOSE ;
NONE ;
COLOR RGB(0, 0, 0, 192, 192, 192)
MOVE WINDOW thermomete CENTER
ACTIVATE WINDOW thermomete NOSHOW
@ 0.5,3 SAY m.text FONT m.g_dlgface, m.g_dlgsize STYLE m.g_dlgstyle
@ 1.5,3 SAY m.prompt FONT m.g_dlgface, m.g_dlgsize STYLE m.g_dlgstyle
@ 0.000,0.000 TO 0.000,63.833 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 0.000,0.000 TO 5.615,0.000 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 0.385,0.667 TO 5.231,0.667 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 0.308,0.667 TO 0.308,63.167 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 0.385,63.000 TO 5.308,63.000 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 5.231,0.667 TO 5.231,63.167 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 5.538,0.000 TO 5.538,63.833 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 0.000,63.667 TO 5.615,63.667 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 3.000,3.333 TO 4.231,3.333 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 3.000,60.333 TO 4.308,60.333 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 3.000,3.333 TO 3.000,60.333 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 4.231,3.333 TO 4.231,60.333 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
m.g_thermwidth = 56.269
CASE _MAC
DEFINE WINDOW thermomete ;
AT INT((SROW() - (( 5.62 * ;
FONTMETRIC(1, m.g_dlgface, m.g_dlgsize, m.g_dlgstyle )) / ;
FONTMETRIC(1, WFONT(1,""), WFONT( 2,""), WFONT(3,"")))) / 2), ;
INT((SCOL() - (( 63.83 * ;
FONTMETRIC(6, m.g_dlgface, m.g_dlgsize, m.g_dlgstyle )) / ;
FONTMETRIC(6, WFONT(1,""), WFONT( 2,""), WFONT(3,"")))) / 2) ;
SIZE 5.62,63.83 ;
FONT m.g_dlgface, m.g_dlgsize ;
STYLE m.g_dlgstyle ;
NOFLOAT ;
NOCLOSE ;
NONE ;
COLOR RGB(0, 0, 0, 192, 192, 192)
MOVE WINDOW thermomete CENTER
ACTIVATE WINDOW thermomete NOSHOW
@ 0.000,0.000 TO 5.62,63.83 PATTERN 1;
COLOR RGB(192, 192, 192, 192, 192, 192)
IF ISCOLOR()
@ 0.000,0.000 TO 5.62,63.83 PATTERN 1;
COLOR RGB(192, 192, 192, 192, 192, 192)
@ 0.000,0.000 TO 0.000,63.83 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 0.000,0.000 TO 5.62,0.000 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 0.385,0.67 TO 5.23,0.67 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 0.31,0.67 TO 0.31,63.17 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 0.385,63.000 TO 5.31,63.000 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 5.23,0.67 TO 5.23,63.17 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 5.54,0.000 TO 5.54,63.83 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 0.000,63.67 TO 5.62,63.67 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 3.000,3.33 TO 4.23,3.33 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 3.000,60.33 TO 4.31,60.33 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
@ 3.000,3.33 TO 3.000,60.33 ;
COLOR RGB(128, 128, 128, 128, 128, 128)
@ 4.23,3.33 TO 4.23,60.33 ;
COLOR RGB(255, 255, 255, 255, 255, 255)
ELSE
@ 0.000, 0.000 TO 5.62, 63.830 PEN 2
@ 0.230, 0.500 TO 5.39, 63.333 PEN 1
ENDIF
@ 0.5,3 SAY m.text FONT m.g_dlgface, m.g_dlgsize STYLE m.g_dlgstyle+"T" ;
COLOR RGB(0,0,0,192,192,192)
@ 1.5,3 SAY m.prompt FONT m.g_dlgface, m.g_dlgsize STYLE m.g_dlgstyle+"T" ;
COLOR RGB(0,0,0,192,192,192)
m.g_thermwidth = 56.27
IF !ISCOLOR()
@ 3.000,3.33 TO 4.23, (m.g_thermwidth + 1) + 3.33
ENDIF
ENDCASE
SHOW WINDOW thermomete TOP
ELSE
m.prompt = SUBSTR(SYS(2014,UPPER(m.g_outfile)),1,48)+;
IIF(LEN(m.g_outfile)>48,"...","")
DEFINE WINDOW thermomete;
FROM INT((SROW()-6)/2), INT((SCOL()-57)/2) ;
TO INT((SROW()-6)/2) + 6, INT((SCOL()-57)/2) + 57;
DOUBLE COLOR SCHEME 5
ACTIVATE WINDOW thermomete NOSHOW
m.g_thermwidth = 50
@ 0,3 SAY m.text
@ 1,3 SAY UPPER(m.prompt)
@ 2,1 TO 4,m.g_thermwidth+4 &g_boxstrg
SHOW WINDOW thermomete TOP
ENDIF
*
* UPDTHERM(<percent>) - Update thermometer.
*
PROCEDURE updtherm
PARAMETER m.percent
PRIVATE m.nblocks, m.percent
ACTIVATE WINDOW thermomete
m.nblocks = (m.percent/100) * (m.g_thermwidth)
DO CASE
CASE _WINDOWS
@ 3.000,3.333 TO 4.231,m.nblocks + 3.333 ;
PATTERN 1 COLOR RGB(128, 128, 128, 128, 128, 128)
CASE _MAC
@ 3.000,3.33 TO 4.23,m.nblocks + 3.33 ;
PATTERN 1 COLOR RGB(0, 0, 128, 0, 0, 128)
OTHERWISE
@ 3,3 SAY REPLICATE("Û",m.nblocks)
ENDCASE
*
* DEACTTHERMO - Deactivate and Release thermometer window.
*
PROCEDURE deactthermo
RELEASE WINDOW thermomete
*!*****************************************************************************
*!
*! Procedure: THERMFNAME
*!
*!*****************************************************************************
FUNCTION thermfname
PARAMETER m.fname
PRIVATE m.addelipse, m.g_pathsep, m.g_thermfface, m.g_thermfsize, m.g_thermfstyle
#define c_space 40
IF _MAC
m.g_thermfface = "Geneva"
m.g_thermfsize = 10
m.g_thermfstyle = "B"
ELSE
m.g_thermfface = "MS Sans Serif"
m.g_thermfsize = 8
m.g_thermfstyle = "B"
ENDIF
* Translate the filename into Mac native format
IF _MAC
m.g_pathsep = ":"
m.fname = LOWER(SYS(2027, m.fname))
ELSE
m.g_pathsep = "\"
ENDIF
IF TXTWIDTH(m.fname,m.g_thermfface,m.g_thermfsize,m.g_thermfstyle) > c_space
* Make it fit in c_space
m.fname = partialfname(m.fname, c_space - 1)
m.addelipse = .F.
DO WHILE TXTWIDTH(m.fname+'...',m.g_thermfface,m.g_thermfsize,m.g_thermfstyle) > c_space
m.fname = LEFT(m.fname, LEN(m.fname) - 1)
m.addelipse = .T.
ENDDO
IF m.addelipse
m.fname = m.fname + "..."
ENDIF
ENDIF
RETURN m.fname
*!*****************************************************************************
*!
*! Procedure: PARTIALFNAME
*!
*!*****************************************************************************
FUNCTION partialfname
PARAMETER m.filname, m.fillen
* Return a filname no longer than m.fillen characters. Take some chars
* out of the middle if necessary. No matter what m.fillen is, this function
* always returns at least the file stem and extension.
PRIVATE m.bname, m.elipse, m.remain
m.elipse = "..." + m.g_pathsep
IF _MAC
m.bname = SUBSTR(m.filname, RAT(":",m.filname)+1)
ELSE
m.bname = justfname(m.filname)
ENDIF
DO CASE
CASE LEN(m.filname) <= m.fillen
m.retstr = m.filname
CASE LEN(m.bname) + LEN(m.elipse) >= m.fillen
m.retstr = m.bname
OTHERWISE
m.remain = MAX(m.fillen - LEN(m.bname) - LEN(m.elipse), 0)
IF _MAC
m.retstr = LEFT(SUBSTR(m.filname,1,RAT(":",m.filname)-1),m.remain) ;
+m.elipse+m.bname
ELSE
m.retstr = LEFT(justpath(m.filname),m.remain)+m.elipse+m.bname
ENDIF
ENDCASE
RETURN m.retstr
**
** Error Handling Code
**
*
* ERRORHANDLER - Error Processing Center.
*
PROCEDURE errorhandler
PARAMETERS m.messg, m.lineno, m.code
IF ERROR() = 22
ON ERROR &onerror
DO cleanup
CANCEL
ENDIF
DO CASE
CASE m.code == "Minor"
DO errlog WITH m.messg, m.lineno
m.g_status = 1
CASE m.code == "Serious"
DO errlog WITH m.messg, m.lineno
DO errshow WITH m.messg, m.lineno
m.g_error = .T.
m.g_status = 2
ON ERROR
CASE m.code == "Fatal"
IF NOT m.g_nohandle
DO errlog WITH m.messg, m.lineno
ENDIF
DO errshow WITH m.messg, m.lineno
IF WEXIST("Thermomete") AND WVISIBLE("Thermomete")
RELEASE WINDOW thermometer
ENDIF
ON ERROR
DO cleanup
CANCEL
ENDCASE
*
* ESCHANDLER - Escape handler.
*
PROCEDURE eschandler
ON ERROR
WAIT WINDOW "Generation process stopped." NOWAIT
DO builddisable
IF m.g_status > 0
ERASE (m.g_outfile)
ENDIF
IF WEXIST("Thermomete") AND WVISIBLE("Thermomete")
RELEASE WINDOW thermometer
ENDIF
DO cleanup
CANCEL
*
* ERRLOG - Insert error message into the error log.
*
PROCEDURE errlog
PARAMETER m.messg, m.lineno
PRIVATE m.savehandle
m.savehandle = _TEXT
DO openerrfile
SET CONSOLE OFF
\\GENERATOR: <<ALLTRIM(m.messg)>>
IF NOT EMPTY(m.lineno)
\\ LINE NUMBER: <<m.lineno>>
ENDIF
\
= FCLOSE(_TEXT)
_TEXT = m.savehandle
*
* ERRSHOW - Display error message in the alert box.
*
PROCEDURE errshow
PARAMETER m.msg, m.lineno
PRIVATE m.curcursor
IF m.g_graphic
DEFINE WINDOW alert ;
AT INT((SROW() - (( 5.615 * ;
fontmetric(1, m.g_dlgface, m.g_dlgsize, m.g_dlgstyle )) / ;
fontmetric(1, wfont(1,""), wfont(2,""), wfont(3,"")))) / 2), ;
INT((SCOL() - (( 63.833 * ;
fontmetric(6, m.g_dlgface, m.g_dlgsize, m.g_dlgstyle )) / ;
fontmetric(6, wfont(1,""), wfont(2,""), wfont(3,"")))) / 2) ;
SIZE 5.615,63.833 ;
font m.g_dlgface, m.g_dlgsize ;
STYLE m.g_dlgstyle ;
NOCLOSE ;
DOUBLE ;
TITLE "Genmenu Error" ;
COLOR rgb(0, 0, 0, 255, 255, 255)
ACTIVATE WINDOW alert NOSHOW
m.msg = SUBSTR(m.msg,1,44)+IIF(LEN(m.msg)>44,"...","")
@ 1,(WCOLS()-txtwidth( m.msg ))/2 SAY m.msg
m.msg = "Line Number: "+STR(m.lineno, 4)
@ 2,(WCOLS()-txtwidth( m.msg ))/2 SAY m.msg
m.msg = "Press any key to cleanup and exit..."
@ 3,(WCOLS()-txtwidth( m.msg ))/2 SAY m.msg
SHOW WINDOW alert
ELSE
DEFINE WINDOW alert;
FROM INT((SROW()-6)/2), INT((SCOL()-50)/2) TO INT((SROW()-6)/2) + 6, INT((SCOL()-50)/2) + 50 ;
FLOAT NOGROW NOCLOSE NOZOOM SHADOW DOUBLE;
COLOR SCHEME 7
ACTIVATE WINDOW alert
@ 0,0 CLEAR
@ 1,0 SAY PADC(SUBSTR(m.msg,1,44)+;
IIF(LEN(m.msg)>44,"...",""), WCOLS())
@ 2,0 SAY PADC("Line Number: "+STR(m.lineno, 4), WCOLS())
@ 3,0 SAY PADC("Press any key to cleanup and exit...", WCOLS())
ENDIF
m.curcursor = SET( "CURSOR" )
SET CURSOR OFF
WAIT ""
RELEASE WINDOW alert
SET CURSOR &curcursor
RELEASE WINDOW alert
*
* OPENERRFILE - Open error file.
*
PROCEDURE openerrfile
PRIVATE m.errfile, m.errhandle
m.errfile = m.g_errlog+".ERR"
m.errhandle = FOPEN(m.errfile,2)
IF m.errhandle < 0
m.errhandle = FCREATE(m.errfile)
IF m.errhandle < 0
DO errshow WITH ".ERR could not be opened...", LINENO()
m.g_status = 2
IF WEXIST("Thermomete") AND WVISIBLE("Thermomete")
RELEASE WINDOW thermometer
ENDIF
ON ERROR
RETURN TO MASTER
ENDIF
ELSE
= FSEEK(m.errhandle,0,2)
ENDIF
IF SET("TEXTMERGE") = "OFF"
SET TEXTMERGE ON
ENDIF
_TEXT = m.errhandle
*
* GETCNAME - Manufacture a procedure name, unless there is a #NAME directive
*
FUNCTION getcname
PARAMETERS snippet
PRIVATE ALL
IF proctype = 1
numlines = MEMLINES(snippet)
IF m.numlines > 0
_MLINE = 0
m.i = 1
DO WHILE m.i <= m.numlines
m.thisline = UPPER(ALLTRIM(MLINE(snippet,1, _MLINE)))
DO CASE
CASE LEFT(m.thisline,5) == "#NAME"
RETURN ALLTRIM(SUBSTR(m.thisline,6))
CASE EMPTY(m.thisline) OR iscomment(m.thisline)
* Do nothing. Get next line.
OTHERWISE
EXIT
ENDCASE
m.i = m.i + 1
ENDDO
ENDIF
ENDIF
RETURN LOWER(SYS(2015))
*
* ISCOMMENT - Determine if textline is a comment line.
*
FUNCTION IsComment
PARAMETER m.textline
PRIVATE m.asterisk, m.isnote, m.ampersand, m.statement
IF EMPTY(m.textline)
RETURN .F.
ENDIF
m.statement = UPPER(ALLTRIM(m.textline))
m.asterisk = AT("*", LEFT(m.statement,1))
m.ampersand = AT(CHR(38)+CHR(38), LEFT(m.statement,2))
m.isnote = AT("NOTE", LEFT(m.statement,4))
DO CASE
CASE (m.asterisk = 1 OR m.ampersand = 1)
RETURN .T.
CASE (m.isnote = 1 ;
AND (LEN(m.statement) <= 4 OR SUBSTR(m.statement,5,1) = ' '))
* Don't be fooled by something like "notebook = 7"
RETURN .T.
ENDCASE
RETURN .F.
*
* WORDNUM - Returns w_num-th word from string strg
*
FUNCTION wordnum
PARAMETERS strg,w_num
PRIVATE strg,s1,w_num,ret_str
m.s1 = ALLTRIM(m.strg)
* Replace tabs with spaces
m.s1 = CHRTRAN(m.s1,CHR(9)," ")
* Reduce multiple spaces to a single space
DO WHILE AT(' ',m.s1) > 0
m.s1 = STRTRAN(m.s1,' ',' ')
ENDDO
ret_str = ""
DO CASE
CASE m.w_num > 1
DO CASE
CASE AT(" ",m.s1,m.w_num-1) = 0 && No word w_num. Past end of string.
m.ret_str = ""
CASE AT(" ",m.s1,m.w_num) = 0 && Word w_num is last word in string.
m.ret_str = SUBSTR(m.s1,AT(" ",m.s1,m.w_num-1)+1,255)
OTHERWISE && Word w_num is in the middle.
m.strt_pos = AT(" ",m.s1,m.w_num-1)
m.ret_str = SUBSTR(m.s1,strt_pos,AT(" ",m.s1,m.w_num)+1 - strt_pos)
ENDCASE
CASE m.w_num = 1
IF AT(" ",m.s1) > 0 && Get first word.
m.ret_str = SUBSTR(m.s1,1,AT(" ",m.s1)-1)
ELSE && There is only one word. Get it.
m.ret_str = m.s1
ENDIF
ENDCASE
RETURN ALLTRIM(m.ret_str)
*!*****************************************************************************
*!
*! Function: VERSNUM
*!
*!*****************************************************************************
FUNCTION versnum
* Return string corresponding to FoxPro version number
RETURN wordnum(vers(),2)
*!*****************************************************************************
*!
*! Function: JUSTFNAME
*!
*! Called by: FORCEEXT() (function in GENSCRN.PRG)
*!
*!*****************************************************************************
FUNCTION justfname
PARAMETERS m.filname
PRIVATE ALL
IF RAT('\',m.filname) > 0
m.filname = SUBSTR(m.filname,RAT('\',m.filname)+1,255)
ENDIF
IF AT(':',m.filname) > 0
m.filname = SUBSTR(m.filname,AT(':',m.filname)+1,255)
ENDIF
RETURN ALLTRIM(UPPER(m.filname))
===================
*:*****************************************************************************
*:
*: Program:
*:
*: System:
*: Author:
*: Copyright (c) 1998,
*: Last modified: 11/18/98 16:57
*:
*: Called by: MANTMENU.PRG
*:
*: Calls: LASTKEY() (function in ?)
*:
*: Documented 11/19/98 at 10:19 FoxDoc version 2.10f
*:*****************************************************************************
*-------------------------------------------------imEXMENU.prg
* import - Export routine
*--------------------------------------------------
@03,30 CLEAR TO 03,48
SET COLOR TO GR+
CDESP='** Import / Export Menu **'
CLEN = LEN(CDESP)
CPOS=(80-CLEN) / 2
@03,CPOS say CDESP
set color to BG+
k_esc =27
set date french
set colo to W+/B+
declare itbl[2]
itbl[1] = "\<1 Back Up "
itbl[2] = "\<2 Restore"
i_choice = 0
do while .t.
set colo to W+/B+
@08,34 menu itbl,02 title 'Import/Export'
read menu to r_choice save
save screen to impexp
if lastkey() = K_ESC
@05,00 clear to 24,79
exit
endif
do case
case r_choice = 1
DO EXPORTFL
case r_choice = 2
*DO IMPORTFL
otherwise
loop
endcase
restore screen from impexp
enddo
*SET COLOR TO BG+
return
*: EOF: IMEXMENU.PRG
=======================================================
*--------------------------------------------------INDXFILE.PRG
* Index files
*--------------------------------------------------
set safety off
CLOSE ALL
DO REPLPAN
CLOSE ALL
set colo to bg+
@ 5,00 clear to 23,79
@ 5,00 to 05,79
*----------variables
@03,30 clear to 03,48
set colo to gr+
CDESP=' ** Reindexing File **'
CLEN = LEN(CDESP)
CPOS=(80-CLEN) / 2
@03,CPOS say CDESP
set date french
SET CENT ON
set colo to bg/gr+
@06,59 clear to 23,76
@06,59 to 23,77
@06,61 say 'Indexed File'
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing PARTYMST '
sele 01
use PARTYMST
pack
inde on str(p_code,6) to PARTYMST
INDE on p_name to PARTYNAM
index on p_code to PARTYMST
use
sele 01
use PARTYMST
pack
index on p_name to PARTYNAM
@07,60 say 'PARTYMST'
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing TYPEMAST'
sele 02
use TYPEMAST
pack
index on type_cd to TYPEMAST
@08,60 say 'TYPEMAST'
use
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing SUBTYPE'
sele 03
use SUBTYPE
pack
index on type_cd+stype_cd to SUBTYPE
@09,60 say 'SUBTYPE '
use
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing SUBTYPE'
sele 04
use EXCHANGE
pack
index on excg_no to EXCHANGE
@010,60 say 'EXCHANGE'
use
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing DGMMAST '
sele 05
use GMMAST
inde on pgm_no+gm_no to GMMAST
use
sele 05
use PGMMAST
inde on pgm_no to PGMMAST
use
sele 05
use DGMMAST
pack
index on pgm_no+gm_no+dgm_no to DGMMAST
use
SELE 05
USE dgmexcg
pack
index on pgm_no+gm_no+dgm_no+excg_no to DGMEXCG
use
@11,60 say 'DGMMAST '
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing DEMAST '
sele 06
use DEMAST
pack
index on pgm_no+gm_no+dgm_no+excg_No+de_no to DEMAST
use
@12,60 say 'DEMAST '
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing SDEMAST '
sele 07
use SDEMAST
pack
index on pgm_no+gm_no+dgm_no+excg_no+de_no+sde_no to SDEMAST
use
sele 07
use MESSAGES
inde on file_type+srl_no to MESSAGES
use
@13,60 say 'MESSAGES'
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing VEHICLE '
sele 08
use VEHICLE
pack
index on v_no to VEHICLE
use
@14,60 say 'VEHICLE '
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing DEALASST '
sele 09
use DEALASST
pack
index on da_cd to DEALASST
use
@15,60 say 'DEALASST'
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing GUARDS '
sele 11
use GUARDS
pack
index on excg_no to GUARDS
use
@16,60 say 'GUARDS '
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing PEREASON '
sele 12
use PEREASON
pack
index on reas_no to PEREASON
use
@17,60 say 'PEREASON'
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing VOUCMAST '
USE VOUCDEL
APPE FROM VOUCMAST FOR DELETED()
USE
sele 20
use VOUCMAST
repl all remarks with ' '
pack
index on str(slno,5) to VOUCMAST
use
sele 21
use BILLNO
pack
inde on str(p_code,6)+bill_no+dtoc(bill_date)+str(amount,10) to BILLNO
use
@18,60 say 'VOUCMAST'
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing ADVCMAST '
sele 23
use ADVCMAST
pack
index on unit+adv_no to ADVCMAST
use
@19,60 say 'ADVCMAST'
@23,02 CLEAR TO 23,70
@23,02 say 'Wait !! Indexing TENDER '
sele 18
use TENDER
pack
index on type+tender_no to TENDER
use
sele 18
use TENDTYPE
inde on type to TENDTYPE
@20,60 say 'TENDER'
use achead
index on accode to achead
use
use billtype
inde on bill_ty to BILTYPE
msrl_no = '999'
do usemsg
@06,59 clear to 23,76
set color to bg+
close all
return
*: EOF: INDXFILE.PRG
======================================
*------------------------------------------- : install.prg
* install Program for payroll System
*--------------------------------------------
set escape off
SET COLOR TO BG+
SET TALK OFF
SET STAT OFF
SET ALTERNATE OFF
SET BELL OFF
SET CONFIRM OFF
SET CONSOLE ON
SET DELETED ON
SET DELIMITERS TO "[]"
SET DELIMITERS ON
SET DEVICE TO SCREEN
SET EXACT OFF
SET INTENSITY ON
SET MARGIN TO 0
SET PRINT OFF
SET UNIQUE OFF
SET CENTURY OFF
SET DATE FRENCH
set score off
SET SAFETY OFF
=INSMODE(.f.)
SET DATE FRENCH
CLEAR
CLOSE DATABASES
user_msg1 = space(60)
user_msg2 = space(60)
ans_msg = space(1)
mdesp=space(40)
MCL_SHRT=SPACE(20)
maddr1=space(30)
maddr2 = space(30)
maddr3 = space(30)
maddr4 = space(30)
mpincode = space(6)
mtel_o = space(8)
mtel_o_2 = space(8)
msign = space(20)
mpass = space(6)
SET COLOR TO W/RB+
@12,25 SAY "***************************"
@13,25 SAY "* ---------------*"
@14,25 say "* --------------- *"
@15,25 say "* ------------ *"
@16,25 SAY "***************************"
*------------------------ variables
mflnm=space(12)
mfield=space(10)
flen=0
mrecno=0
wrecno=0
mcode=0
mloc_code = space(3)
mloc_desc = space(20)
mbran_code = space(3)
mbran_desc = space(20)
CLOSE ALL
SET COLO TO RB+
sdesp = " TOM SYSTEM "
*--------------------------------------------------------
do bigchars with 1,10," TOM |SYSTEM"
WAIT WINDOW ('Please Wait!!') TIMEOUT 1
clear
*o CLNTADD
DO USERSUP
close all
clear all
return
===========================================================
Visual FoxPro (VFP) is a data-centric procedural programming language and relational database management system (RDBMS) that was developed by Microsoft. It is known for its strong data handling capabilities and its rapid application development (RAD) features. Although Microsoft officially ended support for Visual FoxPro in 2015, it remains a powerful tool for maintaining and developing legacy applications.
Here's a basic overview of coding in Visual FoxPro, including its main features and some examples to get you started.
### Basic Concepts
1. **Database and Table Management:**
- **Tables:** Store data in rows and columns.
- **Indexes:** Improve the performance of queries.
- **Views:** Provide a virtual table based on a query.
2. **Data Manipulation:**
- **Commands:** `SELECT`, `INSERT`, `UPDATE`, `DELETE`.
- **Functions:** Built-in functions for data manipulation.
3. **Procedural Programming:**
- **Commands and Functions:** Similar to other procedural languages.
- **Error Handling:** Using `TRY...CATCH` blocks.
### Basic Syntax and Examples
#### 1. **Creating and Using Tables**
- **Creating a Table:**
```foxpro
CREATE TABLE employees ( ;
emp_id I NOT NULL, ;
emp_name C(100), ;
emp_salary N(10,2), ;
hire_date D )
```
- **Inserting Data:**
```foxpro
INSERT INTO employees (emp_id, emp_name, emp_salary, hire_date) ;
VALUES (1, 'John Doe', 50000.00, DATE())
```
- **Selecting Data:**
```foxpro
SELECT * FROM employees
```
- **Updating Data:**
```foxpro
UPDATE employees SET emp_salary = 55000.00 WHERE emp_id = 1
```
- **Deleting Data:**
```foxpro
DELETE FROM employees WHERE emp_id = 1
```
#### 2. **Indexing and Views**
- **Creating an Index:**
```foxpro
INDEX ON emp_salary TAG salary_index
```
- **Creating a View:**
```foxpro
CREATE VIEW high_salary AS ;
SELECT * FROM employees ;
WHERE emp_salary > 50000
```
#### 3. **Procedural Programming**
- **Simple Procedure:**
```foxpro
PROCEDURE ShowEmployee(emp_id)
LOCAL lcName, lnSalary, ldHireDate
SELECT emp_name, emp_salary, hire_date ;
FROM employees ;
WHERE emp_id = emp_id INTO CURSOR csrEmployee
IF RECCOUNT('csrEmployee') > 0
lcName = csrEmployee.emp_name
lnSalary = csrEmployee.emp_salary
ldHireDate = csrEmployee.hire_date
? "Name: " + lcName
? "Salary: " + TRANSFORM(lnSalary)
? "Hire Date: " + DTOC(ldHireDate)
ELSE
? "Employee not found."
ENDIF
ENDPROC
```
- **Error Handling with TRY...CATCH:**
```foxpro
TRY
DELETE FROM employees WHERE emp_id = 999
IF _TALLY = 0
? "No records deleted."
ENDIF
CATCH TO loException
? "An error occurred: " + loException.Message
ENDTRY
```
#### 4. **Forms and Controls**
Visual FoxPro provides a graphical interface to create forms with various controls.
- **Creating a Form:**
```foxpro
CREATE FORM employeeForm
```
- **Adding Controls:**
You can drag and drop controls like text boxes, buttons, and grids onto the form. Here’s a simple example of how you might set up a button click event:
```foxpro
* In the form's button click event
PROCEDURE cmdSave.Click
IF EMPTY(thisform.txtEmpName.Value) OR EMPTY(thisform.txtEmpSalary.Value)
MESSAGEBOX("Name and Salary must be filled out.")
ELSE
INSERT INTO employees (emp_name, emp_salary) ;
VALUES (thisform.txtEmpName.Value, thisform.txtEmpSalary.Value)
MESSAGEBOX("Employee saved.")
ENDIF
ENDPROC
```
### Key Points
- **Data Handling:** VFP excels at data handling and allows for rapid development of data-centric applications.
- **Forms and Reports:** Visual FoxPro includes tools for designing user interfaces and generating reports.
- **Legacy Code:** Despite being outdated, VFP codebases are still in use, particularly in legacy systems.
### Summary
Visual FoxPro is a powerful tool for building database applications with a strong focus on data manipulation and rapid development. Although it's no longer officially supported, many organizations continue to use it for maintaining legacy systems. The examples provided cover basic table operations, procedural programming, and form creation to help you get started with Visual FoxPro coding.
If you have specific questions or need further assistance with Visual FoxPro, feel free to ask!
======
Visual
FoxPro is a data-centric, object-oriented, and procedural programming language
that offers a wide range of commands for database manipulation, user interface
design, and general programming tasks. Below is a categorized list of some key
commands commonly used in Visual FoxPro:
# 1. File
Handling Commands
- OPEN
DATABASE: Opens a database file.
```foxpro
OPEN DATABASE myDatabase
```
- CLOSE
DATABASES: Closes all open databases.
```foxpro
CLOSE DATABASES
```
- USE: Opens
a table for use.
```foxpro
USE myTable
```
- CLOSE:
Closes the currently open table or all tables.
```foxpro
CLOSE ALL
```
- COPY TO:
Copies a table to a new file.
```foxpro
COPY TO newTable.dbf
```
- DELETE FILE:
Deletes a specified file.
```foxpro
DELETE FILE myFile.dbf
```
# 2. Data
Manipulation Commands
- APPEND:
Adds a new record to the table.
```foxpro
APPEND BLANK
```
- DELETE:
Marks records for deletion.
```foxpro
DELETE FOR condition
```
- RECALL:
Restores deleted records.
```foxpro
RECALL FOR condition
```
- REPLACE:
Replaces the contents of a field in the current record or records.
```foxpro
REPLACE fieldName WITH newValue
```
- BROWSE:
Opens a browse window to view and edit records.
```foxpro
BROWSE
```
- INDEX:
Creates an index for a table.
```foxpro
INDEX ON fieldName TAG tagName
```
# 3. Table
and Database Commands
- CREATE
TABLE: Creates a new table.
```foxpro
CREATE TABLE myTable (id INT, name CHAR(30))
```
- ALTER
TABLE: Modifies the structure of an existing table.
```foxpro
ALTER TABLE myTable ADD COLUMN newField INT
```
- DROP TABLE:
Deletes a table from the database.
```foxpro
DROP TABLE myTable
```
- PACK:
Permanently removes records marked for deletion.
```foxpro
PACK
```
# 4. Programming
Flow Control Commands
- IF...ENDIF:
Conditional branching.
```foxpro
IF condition
* Statements
ENDIF
```
- DO
WHILE...ENDDO: Loops while a condition is true.
```foxpro
DO WHILE condition
* Statements
ENDDO
```
- FOR...ENDFOR:
Iterates a block of code for a defined range.
```foxpro
FOR i = 1 TO 10
* Statements
ENDFOR
```
# 5. Error
Handling Commands
- TRY...CATCH...FINALLY:
Handles errors in a block of code.
```foxpro
TRY
* Code that may cause an error
CATCH TO oError
* Error handling code
FINALLY
* Code to execute after TRY or CATCH
ENDTRY
```
# 6. Report
and Output Commands
- REPORT
FORM: Generates a report from a specified form.
```foxpro
REPORT FORM reportName TO PRINTER
```
- LIST:
Lists records or fields to the screen or a file.
```foxpro
LIST
```
- DISPLAY:
Displays records in a formatted output.
```foxpro
DISPLAY ALL
```
# 7. Form
and User Interface Commands
- CREATE
FORM: Creates a form to be used in an application.
```foxpro
CREATE FORM myForm
```
- DO FORM:
Runs an existing form.
```foxpro
DO FORM myForm
```
# 8. Miscellaneous
Commands
- SET:
Changes environment settings such as view options or behavior.
```foxpro
SET TALK OFF
```
- WAIT:
Pauses program execution for a specified time or until the user presses a key.
```foxpro
WAIT WINDOW "Processing..."
These are
just a few commands in Visual FoxPro. The language is quite rich and allows for
the creation of robust database applications with a blend of procedural and
object-oriented approaches.
=====
Here are some sample
cases with commands in Visual FoxPro, demonstrating how to handle various
common tasks such as database manipulation, user interface creation, and file
management. Each case includes a brief scenario and corresponding commands.
---
# Case 1: Creating a
Database and Table
Scenario: You want to
create a new database and a table that stores employee details (ID, name, and
salary).
```foxpro
* Creating the
database
CREATE DATABASE
EmployeeDB
* Open the database
OPEN DATABASE
EmployeeDB
* Create the Employee
table with fields: ID, Name, Salary
CREATE TABLE
Employees (ID INT, Name CHAR(30), Salary FLOAT)
* Add some sample
data
INSERT INTO Employees
(ID, Name, Salary) VALUES (1, 'John Doe', 50000)
INSERT INTO Employees
(ID, Name, Salary) VALUES (2, 'Jane Smith', 55000)
* View the data in a
browse window
BROWSE
```
---
# Case 2: Inserting
and Deleting Records in a Table
Scenario: You want to
add a few more records to the Employees table and delete one of the records.
```foxpro
* Open the Employee
table
USE Employees
* Insert new records
INSERT INTO Employees
(ID, Name, Salary) VALUES (3, 'Mike Johnson', 60000)
INSERT INTO Employees
(ID, Name, Salary) VALUES (4, 'Anna Lee', 48000)
* Display the current
data
LIST
* Mark the record for
deletion where the employee name is 'Mike Johnson'
DELETE FOR Name =
'Mike Johnson'
* Recall the record
in case the deletion was a mistake
RECALL FOR Name =
'Mike Johnson'
* Finally, remove the
record permanently
DELETE FOR Name =
'Mike Johnson'
PACK
```
---
# Case 3: Updating
Data in a Table
Scenario: You need to
increase the salary of all employees earning less than $50,000 by 10%.
```foxpro
* Open the Employee
table
USE Employees
* Update the salary
for employees earning less than $50,000
REPLACE ALL Salary
WITH Salary * 1.1 FOR Salary < 50000
* Display updated
records
LIST
```
---
# Case 4: Creating an
Index for a Table
Scenario: You need to
create an index on the `Salary` field to optimize queries based on salary.
```foxpro
* Open the Employee
table
USE Employees
* Create an index on
the Salary field
INDEX ON Salary TAG
SalaryIndex
* Verify that the
index is active by sorting the records using the index
SET ORDER TO
SalaryIndex
BROWSE
```
---
# Case 5: Creating a
Simple Form
Scenario: You want to
create a simple form that allows the user to view and add employee records.
```foxpro
* Create a new form
CREATE FORM
EmployeeForm
* Inside the form,
add text boxes for ID, Name, and Salary fields
* Add buttons to
navigate through the records (Next, Previous)
* Add a button to
append a new record
* Save the form and
run it
DO FORM EmployeeForm
```
---
# Case 6: Querying
Data
Scenario: You need to
query all employees who have a salary greater than $50,000 and display them.
```foxpro
* Open the Employee
table
USE Employees
* Query employees
with salary greater than 50000
SELECT * FROM
Employees WHERE Salary > 50000 INTO CURSOR HighEarners
* Display the results
BROWSE
# Case 7: Error
Handling with TRY...CATCH
Scenario: You are
working with file operations and want to handle any potential errors gracefully
(e.g., file not found).
```foxpro
* Open a file with
error handling
TRY
USE NonExistentFile
CATCH TO oError
* Display the error message
WAIT WINDOW "Error: " +
oError.Message
ENDTRY
```
---
# Case 8: Exporting
Data to a CSV File
Scenario: You want to
export the `Employees` table to a CSV file for use in another program.
```foxpro
* Open the Employee
table
USE Employees
* Export the data to
a CSV file
COPY TO
EmployeeData.csv TYPE CSV
```
---
# Case 9: Deleting a
File
Scenario: You need to
delete an obsolete table file from the directory.
```foxpro
* Ensure the file is
closed
CLOSE ALL
* Delete the file
DELETE FILE
oldEmployeeTable.dbf
* Confirm the file is
deleted
IF
!FILE('oldEmployeeTable.dbf')
WAIT WINDOW "File deleted
successfully."
ENDIF
```
---
# Case 10: Reporting
and Printing
Scenario: You need to
generate and print a report of all employees.
```foxpro
* Create a report in
the Report Designer (done visually)
CREATE REPORT
EmployeeReport
* Once the report
design is done, print the report
REPORT FORM
EmployeeReport TO PRINTER
* To preview the
report before printing
REPORT FORM
EmployeeReport PREVIEW
These examples
demonstrate various basic operations in Visual FoxPro, from creating tables and
querying data to error handling, UI design, and reporting. These commands form
the foundation for more complex application development in FoxPro.
=====
Designing, analyzing, and documenting FoxPro applications involves several key steps and best practices. Visual FoxPro (VFP) is a data-centric programming environment, and understanding its architecture and functionality is essential for effective application development. Here’s a comprehensive guide on how to approach these tasks:
## 1. **Designing FoxPro Applications**
### a. Requirements Gathering
- **Identify Stakeholders**: Work with users and stakeholders to gather requirements.
- **Understand Business Processes**: Analyze current processes and identify pain points.
- **Document Requirements**: Create a detailed list of functional and non-functional requirements.
### b. System Architecture
- **Define the Architecture**: Choose between a client-server architecture or a standalone application based on requirements.
- **Data Model Design**:
- Create an Entity-Relationship Diagram (ERD) to represent the data model.
- Define tables, relationships, and normalization.
- **User Interface Design**:
- Design intuitive user interfaces using forms and controls.
- Consider usability principles, such as consistency and accessibility.
### c. Data Structures
- **Define Tables and Fields**: Create tables in the VFP database, defining the necessary fields, data types, and constraints.
- **Indexes**: Design appropriate indexing strategies to optimize query performance.
### d. Application Logic
- **Procedures and Functions**: Organize business logic into reusable procedures and functions.
- **Modular Design**: Structure the application into modules or components for easier maintenance and scalability.
## 2. **Analyzing FoxPro Applications**
### a. Code Analysis
- **Review Existing Code**: Examine the current FoxPro codebase for logic, structure, and efficiency.
- **Identify Bottlenecks**: Use profiling tools to identify performance bottlenecks or inefficient queries.
### b. User Feedback
- **Conduct User Testing**: Gather feedback from users to understand usability issues or feature requests.
- **Analyze Support Tickets**: Review support tickets and issue logs to identify common problems.
### c. Performance Metrics
- **Monitor Performance**: Measure application performance (e.g., response times, resource usage) to identify areas for improvement.
- **Evaluate Database Performance**: Analyze query execution times, and check for locking and blocking issues in the database.
### d. Compliance and Security
- **Evaluate Security**: Ensure that the application adheres to security best practices (e.g., data encryption, user authentication).
- **Compliance**: Confirm that the application complies with relevant regulations (e.g., GDPR, HIPAA).
## 3. **Documenting FoxPro Applications**
### a. Code Documentation
- **Inline Comments**: Use comments within the code to explain complex logic or important decisions.
- **Function and Procedure Documentation**: Create documentation for all procedures and functions, including parameters, return values, and usage examples.
### b. User Documentation
- **User Manuals**: Develop comprehensive user manuals that explain how to use the application, including screenshots and examples.
- **FAQs and Troubleshooting Guides**: Provide users with FAQs and troubleshooting guides to address common issues.
### c. Technical Documentation
- **Architecture Diagrams**: Create architecture diagrams that depict the overall system architecture, including data flow and integration points.
- **Data Model Documentation**: Document the data model, including table structures, field definitions, and relationships.
- **API Documentation**: If the application interacts with external services, document the APIs, including endpoints and data formats.
### d. Version Control and Change Logs
- **Maintain Version Control**: Use version control systems (e.g., Git) to track changes to the codebase and manage releases.
- **Change Logs**: Document changes made in each version, including new features, bug fixes, and improvements.
## 4. **Best Practices**
- **Consistent Naming Conventions**: Use clear and consistent naming conventions for variables, tables, and procedures to improve code readability.
- **Regular Backups**: Implement a backup strategy to protect data and application code.
- **Testing**: Conduct thorough testing (unit testing, integration testing) before deploying changes to production.
- **User Training**: Provide training sessions for users to familiarize them with new features and workflows.
## Conclusion
Designing, analyzing, and documenting FoxPro applications requires a structured approach to ensure clarity, maintainability, and usability. By following best practices in requirements gathering, system architecture, performance analysis, and thorough documentation, you can create robust FoxPro applications that meet user needs and facilitate future enhancements.
===
Being excellent in coding, testing, installation, and maintenance of FoxPro software applications requires a deep understanding of Visual FoxPro (VFP) and its capabilities, as well as adherence to best practices throughout the software development lifecycle. Below is an outline that encapsulates key strategies and tips for each aspect of working with FoxPro applications:
## 1. Coding
### a. Coding Best Practices
- **Modular Programming**: Break down your application into smaller, manageable modules or functions to improve readability and maintainability.
- **Consistent Naming Conventions**: Use descriptive and consistent naming conventions for variables, tables, and functions (e.g., prefix function names with "fn_" for clarity).
- **Commenting**: Write clear comments and documentation within your code to explain complex logic, algorithms, and any non-obvious choices made during development.
### b. Use of Object-Oriented Principles
- **Encapsulation**: Create classes to encapsulate related data and functionality, which helps organize the code better.
- **Inheritance**: Utilize inheritance for reusing code in classes, reducing redundancy.
- **Polymorphism**: Implement polymorphism to enhance flexibility and allow different data types to be treated as instances of the same class.
### c. Effective Use of Built-in Functions
- Leverage VFP's built-in functions (e.g., string manipulation, date handling) to simplify coding and improve performance.
### d. Error Handling
- Implement robust error handling using `TRY...CATCH` blocks to manage exceptions gracefully and log errors for future analysis.
---
## 2. Testing
### a. Unit Testing
- **Automated Tests**: Create automated unit tests for individual functions and modules to ensure they work as intended.
- **Test Cases**: Develop comprehensive test cases that cover various scenarios, including edge cases.
### b. Integration Testing
- **Module Interaction**: Test how different modules interact with each other to ensure that data flows correctly throughout the application.
- **Database Interaction**: Verify that all database transactions (CRUD operations) work as expected.
### c. User Acceptance Testing (UAT)
- **Involve End Users**: Collaborate with end users during UAT to validate that the application meets their requirements and expectations.
- **Feedback Mechanism**: Implement a feedback mechanism to capture user experiences and suggestions for improvement.
### d. Performance Testing
- Assess the application under load to identify potential bottlenecks and ensure it can handle expected user volumes.
---
## 3. Installation
### a. Packaging the Application
- **Installation Scripts**: Create installation scripts or programs that automate the installation process for users.
- **Dependencies**: Ensure that all necessary dependencies (e.g., database drivers, configuration files) are included in the installation package.
### b. Configuration Management
- **Configuration Files**: Use configuration files to allow easy adjustments of parameters without modifying code (e.g., database connections, paths).
- **Environment Setup**: Clearly document how to set up different environments (development, testing, production) to ensure consistency.
### c. Documentation
- Provide installation documentation that outlines system requirements, installation steps, and troubleshooting tips for users.
---
## 4. Maintenance
### a. Regular Updates
- **Bug Fixes**: Monitor for bugs reported by users and prioritize fixes based on severity and impact.
- **Feature Enhancements**: Gather user feedback to identify opportunities for enhancements and new features.
### b. Version Control
- **Source Control**: Utilize a version control system (e.g., Git) to manage code changes, track history, and collaborate effectively.
- **Release Management**: Maintain a clear release management process, documenting changes and ensuring smooth transitions between versions.
### c. Backup and Recovery
- **Regular Backups**: Implement a regular backup strategy for both code and data to prevent data loss.
- **Recovery Plans**: Develop recovery plans to quickly restore functionality in case of failure or data corruption.
### d. Monitoring and Support
- **Monitoring Tools**: Use monitoring tools to track application performance and error rates.
- **Help Desk Support**: Establish a help desk or support channel for users to report issues or seek assistance.
---
## Conclusion
Excelling in coding, testing, installation, and maintenance of FoxPro applications involves a combination of best practices, thorough testing, and effective user communication. By following these guidelines, developers can create robust, efficient, and user-friendly applications while ensuring that they remain maintainable and scalable over time. This comprehensive approach not only enhances the quality of the software but also improves the overall user experience and satisfaction.
====
Dynamic Link Libraries (DLLs) play a significant role in extending the functionality of applications built with Visual FoxPro (VFP). Here’s a detailed overview of DLLs, including their purpose, how they can be used in VFP, and some best practices.
### What is a Dynamic Link Library (DLL)?
- **Definition**: A DLL is a collection of reusable functions and procedures that can be used by multiple applications simultaneously. It allows for modularization of code, enabling easier updates and maintenance.
- **Purpose**: DLLs help reduce the memory footprint of applications by allowing multiple programs to share the same code. They can contain code, data, and resources such as icons or images.
### How to Use DLLs in Visual FoxPro
#### 1. **Declaring Functions from a DLL**
To use functions from a DLL in Visual FoxPro, you need to declare them first. This is done using the `DECLARE` statement.
**Syntax**:
```foxpro
DECLARE <function name> FROM <DLL name> AS <return type> [WITH <parameter types>]
```
**Example**:
```foxpro
* Declare a function from a DLL
DECLARE INTEGER MessageBox IN user32;
STRING lpText, STRING lpCaption, INTEGER uType
```
In this example, the `MessageBox` function from the `user32.dll` is declared. This function creates a pop-up message box.
#### 2. **Calling Functions from a DLL**
After declaring a function, you can call it like a regular FoxPro function.
**Example**:
```foxpro
* Call the MessageBox function
MessageBox("Hello, World!", "Greetings", 0)
```
### 3. **Creating and Using Custom DLLs**
You can create custom DLLs using languages like C, C++, or C#. These DLLs can then be called from Visual FoxPro applications.
- **Steps to Create a DLL**:
1. **Write the Code**: Write the functions you want in your preferred programming language.
2. **Export Functions**: Use appropriate keywords or attributes to export the functions you want to make available (e.g., `__declspec(dllexport)` in C/C++).
3. **Compile the Code**: Compile the code into a DLL file.
- **Using Custom DLLs in VFP**: Similar to using system DLLs, declare and call your custom functions using the `DECLARE` statement.
### 4. **Handling Parameters and Return Types**
When declaring functions, it is crucial to specify the correct data types for parameters and return values. Mismatches can lead to errors or unexpected behavior.
- **Common Data Types**:
- **INTEGER**: 32-bit integer.
- **STRING**: A string value.
- **VOID**: Indicates no return value.
### 5. **Working with COM DLLs**
Visual FoxPro can also interact with Component Object Model (COM) DLLs. This is common for libraries that expose objects and methods to be used in other applications.
- **Creating an Instance**:
```foxpro
* Create an instance of a COM object
oExcel = CREATEOBJECT("Excel.Application")
```
- **Calling Methods**: After creating an instance, you can call methods and properties on the object:
```foxpro
oExcel.Visible = .T. && Make Excel visible
```
### Best Practices for Using DLLs in Visual FoxPro
1. **Error Handling**: Always implement error handling when calling DLL functions. This is essential for diagnosing issues.
2. **Documentation**: Document the functions and parameters used from the DLL to aid in maintenance and debugging.
3. **Testing**: Test the integration of DLL functions thoroughly to ensure they work as expected in all scenarios.
4. **Version Control**: Keep track of DLL versions to prevent compatibility issues when updating or deploying applications.
5. **Security Considerations**: Be cautious when using third-party DLLs. Ensure they are from a trusted source to avoid security vulnerabilities.
### Conclusion
Dynamic Link Libraries are powerful tools in Visual FoxPro that allow developers to extend application functionality by leveraging existing system libraries or creating custom code. By understanding how to declare, call, and manage DLLs, developers can enhance the performance and capabilities of their FoxPro applications significantly. With best practices in place, using DLLs can lead to more efficient, modular, and maintainable code.
===
Developing forms in Visual FoxPro (VFP) is a key aspect of creating user interfaces for applications. Forms allow users to interact with the application, input data, and display information. Below is a detailed guide on how to develop forms in VFP, including planning, creating, designing, and programming forms.
### Steps to Develop a Form in Visual FoxPro
#### 1. **Planning the Form**
Before you start building a form, it’s essential to plan its structure and functionality:
- **Identify the Purpose**: Determine the primary purpose of the form (e.g., data entry, reporting, user interaction).
- **Gather Requirements**: Collect user requirements to understand what fields, buttons, and functionalities are needed.
- **Sketch the Layout**: Create a rough sketch of the form layout, indicating where fields, labels, buttons, and other controls will be placed.
#### 2. **Creating a New Form**
To create a new form in VFP:
1. **Open Visual FoxPro**: Launch the VFP IDE (Integrated Development Environment).
2. **Create New Form**:
- Go to the **File** menu.
- Select **New** and then choose **Form**.
- This opens the Form Designer window.
#### 3. **Designing the Form**
In the Form Designer, you can add various controls to the form:
- **Adding Controls**:
- Use the **Toolbox** to drag and drop controls onto the form. Common controls include:
- **Text Box**: For user input.
- **Label**: To describe the purpose of a field.
- **Combo Box**: For selection from a predefined list.
- **Command Button**: For actions like Save, Cancel, or Close.
- **Grid**: To display data from a table or cursor.
- **Setting Control Properties**:
- Each control has properties that can be set in the **Properties Window**. Common properties include:
- **Name**: A unique identifier for the control.
- **Caption**: The text displayed on labels or buttons.
- **Control Source**: Specifies which field in the database the control is bound to (for input fields).
- **Visible**: Determines whether the control is displayed.
- **Arranging Controls**:
- Use alignment and layout options in the Form Designer to organize controls neatly.
#### 4. **Binding Data to the Form**
To display or enter data using the form, you’ll need to bind the controls to a data source:
- **Set the DataSource**:
- If the form is bound to a table or view, set the `DataSource` property of the form to the appropriate cursor or table.
- **Control Binding**:
- Set the `ControlSource` property of text boxes and other input controls to the corresponding fields in the data source.
#### 5. **Writing Form Logic**
Once the form is designed, you’ll need to add logic to handle events and user interactions:
- **Form Events**: Visual FoxPro provides several event triggers for forms, such as:
- **Init**: Fires when the form is initialized.
- **Load**: Fires when the form is loaded.
- **Unload**: Fires when the form is closed.
- **Click**: Fires when a button or control is clicked.
- **Writing Event Handlers**:
- Open the Code window for the form by clicking the **View Code** button in the Form Designer.
- Write the appropriate event handlers in the code window. For example, to handle the click event of a "Save" button, you might write:
```foxpro
PROCEDURE btnSave.Click
IF NOT EMPTY(thisform.txtName.Value)
INSERT INTO myTable (Name, Age) VALUES (thisform.txtName.Value, thisform.txtAge.Value)
MESSAGEBOX("Record Saved!")
ELSE
MESSAGEBOX("Please enter a name.")
ENDIF
ENDPROC
```
#### 6. **Testing the Form**
- **Run the Form**: Use the **Run** button in the Form Designer to test the form.
- **Check Functionality**: Verify that all controls function as expected and that data can be entered, saved, and retrieved correctly.
#### 7. **Refining the Form**
- **User Feedback**: If possible, gather feedback from users to identify any usability issues or additional features needed.
- **Debugging**: Use the VFP debugger to identify and fix any bugs or issues encountered during testing.
#### 8. **Deployment**
- **Create an EXE**: Once the form is finalized and tested, you can compile the project into an executable (EXE) file.
- **Distribute**: Share the executable and any necessary supporting files with users.
### Conclusion
Developing forms in Visual FoxPro involves a structured approach, from planning and designing to coding and testing. By following the steps outlined above, developers can create effective and user-friendly forms that facilitate interaction with the application and data. Leveraging the capabilities of VFP allows for the creation of robust desktop applications tailored to user needs.
==
Creating reports in Visual FoxPro (VFP) is a vital aspect of many applications, enabling users to generate, format, and present data in a structured manner. Below is a comprehensive guide on how to develop reports in VFP, including steps from planning and designing to generating and exporting reports.
### Steps to Develop a Report in Visual FoxPro
#### 1. **Planning the Report**
Before creating a report, it's essential to plan its content and layout:
- **Define the Purpose**: Determine what data the report will present and its intended audience.
- **Identify Data Sources**: Specify which tables, views, or cursors will provide the data for the report.
- **Outline the Structure**: Decide on the sections of the report (e.g., header, detail, footer) and any grouping or sorting requirements.
#### 2. **Creating a New Report**
To create a report in VFP:
1. **Open Visual FoxPro**: Start the VFP IDE.
2. **Create New Report**:
- Go to the **File** menu.
- Select **New**, and then choose **Report**.
- This opens the **Report Designer** window.
#### 3. **Designing the Report**
In the Report Designer, you can add and configure various elements of the report:
- **Report Sections**:
- **Header**: Contains the report title and any static information (e.g., date, company name).
- **Group Header**: Optional sections that appear before detail records based on specific grouping criteria.
- **Detail**: The main section where data records are displayed.
- **Group Footer**: Optional sections that summarize data for each group.
- **Footer**: Contains summary information for the entire report.
- **Adding Controls**:
- Use the **Toolbox** to drag and drop controls into the report sections. Common controls include:
- **Text Box**: For displaying data fields.
- **Label**: For titles and descriptions.
- **Line**: For horizontal or vertical lines to separate sections.
- **Image**: To add logos or other images.
- **Setting Properties**:
- Select each control and set its properties in the **Properties Window**. Common properties include:
- **ControlSource**: Specifies the data field the control will display.
- **Caption**: The text displayed on labels.
- **Font**: To set the font style, size, and color.
#### 4. **Binding Data to the Report**
To display data in the report, you need to set the data source:
- **Setting the Data Environment**:
- In the **Report Designer**, right-click on the report and select **Data Environment** to specify the data source.
- You can use a **Table**, **Cursor**, or **View** as the data source.
- **Defining SQL Queries** (optional):
- If you need to filter or aggregate data, you can define a SQL query to retrieve the desired dataset. This is done in the **Data Environment** by adding a query object.
#### 5. **Adding Calculated Fields and Summaries**
You may want to add calculations or summaries within the report:
- **Calculated Fields**: Use expressions to perform calculations. For example, to calculate a total price:
```foxpro
= Quantity * UnitPrice
```
- **Summary Fields**: Use the **Group Footer** to add summary fields, such as totals or averages for grouped data. For example, to calculate a total for a group, you can use:
```foxpro
SUM(FieldName)
```
#### 6. **Programming Report Logic (Optional)**
In some cases, you may want to add additional logic to the report generation process. This can be done using the **Report Properties** and event handlers:
- **Before/After Output**: You can write code in the **Before Output** or **After Output** events to manipulate data before or after the report is generated.
#### 7. **Testing the Report**
- **Preview the Report**: Use the **Preview** button in the Report Designer to generate a preview of the report and check for accuracy and formatting.
- **Check Layout**: Ensure that all controls are correctly aligned and that the report displays the data as expected.
#### 8. **Generating and Printing the Report**
Once the report is designed and tested, you can generate and print it:
- **Run the Report**: You can run the report from the **Report Designer** or through code in a VFP program.
**Example**:
```foxpro
REPORT FORM MyReport TO PRINTER
```
- **Export Options**: VFP allows you to export reports in various formats (e.g., PDF, Excel). You can specify the output format when generating the report:
```foxpro
REPORT FORM MyReport TO FILE "output.pdf" TYPE PDF
```
#### 9. **Deploying the Report**
- **Distribute the Report**: Once finalized, ensure that the report files and necessary resources are included when distributing your application.
### Conclusion
Developing reports in Visual FoxPro is a systematic process that involves planning, designing, and testing. By following the steps outlined above, developers can create effective and professional reports that meet user needs. VFP's reporting capabilities allow for extensive customization, enabling the presentation of data in a clear and visually appealing manner. Whether for internal use or external distribution, well-designed reports can enhance the value of any application.
===
Visual FoxPro (VFP) is a powerful development tool for building database applications, but it has several limitations when compared to modern technologies and development practices. Here’s a detailed overview of the limitations of Visual FoxPro in the context of contemporary technology:
### 1. **End of Support**
- **No Active Development**: Microsoft discontinued support for Visual FoxPro in 2010, meaning there are no new updates, features, or official patches available. This lack of support makes it increasingly difficult to maintain applications as environments and technologies evolve.
- **Compatibility Issues**: As operating systems and hardware change, VFP applications may face compatibility challenges, particularly with 64-bit systems and newer versions of Windows.
### 2. **Limited Integration with Modern Technologies**
- **Web Development**: VFP is primarily a desktop application development environment and lacks robust tools for creating modern web applications. While there are workarounds (like using VFP as a backend for web services), this requires significant effort and does not provide the flexibility found in modern web frameworks.
- **Mobile Development**: VFP does not support mobile application development directly, which limits the ability to create apps for smartphones and tablets. In contrast, modern frameworks like React Native or Flutter provide native mobile application capabilities.
### 3. **Database Limitations**
- **Single-User Limitations**: VFP's database file format (DBF) is designed for single-user access, making it less suitable for high-transaction environments or applications requiring robust multi-user capabilities.
- **Scalability**: As applications grow, VFP's performance can degrade, especially with larger datasets. Modern databases (like SQL Server, MySQL, or PostgreSQL) are designed to handle large volumes of data and concurrent user access more efficiently.
- **Lack of Advanced Database Features**: VFP lacks support for advanced database features such as stored procedures, triggers, and foreign key constraints, which are standard in modern relational database management systems.
### 4. **User Interface Limitations**
- **Aging UI Components**: VFP's built-in controls and UI components appear dated compared to modern user interface frameworks (like WPF, WinForms, or web-based UI frameworks). This can result in a less appealing user experience.
- **Responsive Design**: VFP does not support responsive design principles, making it challenging to create applications that work well on different screen sizes and resolutions.
### 5. **Limited Development Tools and Frameworks**
- **Toolset Limitations**: The development environment and tools available for VFP are limited compared to modern IDEs like Visual Studio, which offer advanced features like integrated debugging, code analysis, and modern language support.
- **Lack of Modern Language Features**: VFP does not support modern programming paradigms and features such as asynchronous programming, lambda expressions, or extensive library support that are available in languages like C#, Java, or Python.
### 6. **Community and Resources**
- **Decreasing Community Support**: As the user base for VFP continues to decline, the community support, resources, and knowledge sharing are also diminishing. Finding solutions, examples, or expertise in VFP has become more challenging compared to more widely used technologies.
- **Limited Documentation and Learning Resources**: With the discontinuation of support, there are fewer updated learning materials or documentation available, making it harder for new developers to learn VFP effectively.
### 7. **Version Control and Collaboration**
- **Version Control Integration**: VFP lacks seamless integration with modern version control systems (like Git). This complicates collaborative development, especially in teams that adopt agile practices or continuous integration/continuous deployment (CI/CD) methodologies.
- **Code Sharing**: Sharing code between developers can be cumbersome due to the nature of VFP projects, which do not lend themselves well to modularization and reuse compared to modern programming practices.
### 8. **Security Concerns**
- **Outdated Security Practices**: VFP does not inherently provide modern security features, making it challenging to implement contemporary security best practices. This includes secure authentication, authorization, and data encryption mechanisms.
- **Vulnerability to Attacks**: As with any older technology, VFP applications may be more susceptible to security vulnerabilities and attacks, especially if not maintained or updated to address emerging threats.
### Conclusion
While Visual FoxPro was a robust tool for its time, its limitations in the face of modern technology present significant challenges for current development needs. Organizations using VFP may find themselves at a crossroads, needing to evaluate the potential benefits of migrating to newer technologies and platforms that offer better support, integration, scalability, and user experience. Transitioning to modern development environments can help ensure applications remain relevant and secure in today's fast-paced technological landscape.
===
Despite the limitations and the end of official support for Visual FoxPro (VFP) by Microsoft, many organizations and developers continue to use it for various reasons. Here are some key factors contributing to the ongoing use of VFP:
### 1. **Legacy Systems and Applications**
- **Existing Investments**: Many businesses have significant investments in applications built with VFP. Rewriting or migrating these applications to newer platforms can be costly and time-consuming.
- **Stability and Reliability**: VFP applications, once developed, tend to be stable and reliable. Organizations often prefer to continue using these systems rather than risk disruptions associated with migrating to new technology.
### 2. **Familiarity and Expertise**
- **Skilled Workforce**: There are still many developers and IT professionals who are experienced in VFP. Their familiarity with the language and environment allows for efficient maintenance and updates to existing applications.
- **Rapid Development**: VFP is known for its rapid application development capabilities, enabling developers to create forms and reports quickly. This speed can be an advantage for maintaining legacy systems.
### 3. **Simplicity and Productivity**
- **Ease of Use**: VFP provides a straightforward environment for database management and application development. Its integrated tools allow developers to perform a range of tasks without needing to switch between different applications.
- **Integrated Development Environment**: The built-in IDE in VFP allows for easy design, testing, and debugging of applications, which can enhance productivity, especially for small to medium-sized applications.
### 4. **Cost-Effectiveness**
- **Low Overhead**: Organizations with existing VFP applications do not incur additional costs associated with migrating to a new platform, such as training, new software licenses, or infrastructure changes.
- **Free to Use**: VFP can still be downloaded and used without licensing fees, making it accessible for small businesses or startups that need a cost-effective solution.
### 5. **Data Management Capabilities**
- **Strong Data Handling**: VFP is adept at handling data, making it suitable for applications focused on data entry, reporting, and manipulation. It offers efficient data processing and management tools that some organizations find sufficient for their needs.
- **Built-in Support for DBF Files**: Many businesses still use DBF file formats for their data storage. VFP's native support for these files allows for straightforward management of existing data.
### 6. **Community and Third-Party Support**
- **Active User Community**: Although the official support has ended, there are still active user groups and online communities that provide resources, forums, and support for VFP developers.
- **Third-Party Tools**: Some third-party tools and libraries continue to enhance VFP's functionality, offering solutions for integrating modern features into existing applications (e.g., web services, newer database systems).
### 7. **Migration Options**
- **Incremental Migration**: Some organizations use VFP for specific tasks while gradually migrating other functionalities to modern systems. This hybrid approach allows businesses to leverage existing VFP applications while exploring modern alternatives.
- **Interfacing with Modern Systems**: VFP can be integrated with newer technologies and systems (such as .NET applications or web services) to extend its functionality, enabling organizations to maintain VFP while benefiting from modern capabilities.
### 8. **Use in Niche Applications**
- **Specific Use Cases**: Some industries or specific applications (like small businesses, accounting systems, or point-of-sale systems) have found that VFP meets their needs effectively without requiring the complexity of modern solutions.
- **Customization and Specificity**: VFP is often tailored for particular business processes or workflows, making it valuable for organizations with unique requirements that are well-served by existing VFP solutions.
### Conclusion
While Visual FoxPro may not be a front-runner in modern application development, its ongoing use in many organizations is a testament to its reliability, ease of use, and the strong existing investments made in VFP applications. As long as there is a need for rapid application development and the management of legacy systems, VFP will likely continue to find its place in the software landscape, albeit in a niche capacity. Organizations may need to consider a future transition strategy, but for now, VFP remains a viable option for specific use cases.
==
Yes, Visual FoxPro (VFP) can be downloaded for free, but there are some important considerations to keep in mind:
### 1. **Availability of Visual FoxPro**
- **Last Version**: The last released version of Visual FoxPro was **Visual FoxPro 9.0**, which was made available in 2004. While Microsoft discontinued support for it in 2010, the software itself remains available for download from various sources.
- **Microsoft Download Center**: Microsoft no longer provides direct downloads for VFP from its official website, but you can still find the installation files through other repositories or archives.
### 2. **Open Source Alternatives**
- **Community Contributions**: Some members of the VFP community have created tools and frameworks that enhance or extend the functionality of Visual FoxPro. These may also be available for free download and can be used in conjunction with VFP.
### 3. **Legal Considerations**
- **Licensing**: While you can find downloads for VFP, it is important to ensure that you are obtaining it from a reputable source and that you comply with any licensing agreements. Since VFP is no longer supported, Microsoft does not actively enforce its licensing policies, but it is always best to check the legality of the source from which you are downloading.
### 4. **Installation Files**
- **Third-Party Sources**: There are various online forums, community sites, and repositories where you can find installation files for Visual FoxPro. Some popular places to check include:
- **GitHub**: Occasionally, developers share old software for community use.
- **Developer Forums**: Sites like Stack Overflow or specialized VFP community forums may have links to download VFP.
### 5. **Installation Process**
- **Running the Installer**: Once you have downloaded the installation files, running the installer typically requires administrative privileges on your computer. Follow the prompts to complete the installation.
- **Compatibility**: Be aware that Visual FoxPro was originally designed for older versions of Windows. If you are running a newer operating system (like Windows 10 or 11), you may need to adjust compatibility settings to install and run VFP successfully.
### Conclusion
Visual FoxPro can still be downloaded and used for free, especially for those looking to maintain or develop legacy applications. However, users should ensure they obtain it from legitimate sources and be aware of the limitations and potential compatibility issues with modern operating systems.
===
Visual FoxPro (VFP) is a procedural programming
language and development environment from Microsoft, ideal for creating
data-driven applications. Here's an overview of some simple programming
concepts in VFP:
---
1. Hello,
World!
```foxpro
? "Hello, World!"
```
The `?` command displays text in the output window.
---
2. Variables
and Basic Operations
```foxpro
LOCAL num1, num2, result
num1 = 10
num2 = 20
result = num1 + num2
? "The sum is: " +
TRANSFORM(result)
```
- `LOCAL` declares variables.
- `TRANSFORM()` converts numeric values to strings for
concatenation.
---
3. Creating a
Simple Table
```foxpro
CREATE TABLE Test (ID INT, Name CHAR(50))
INSERT INTO Test VALUES (1,
"Alice")
INSERT INTO Test VALUES (2, "Bob")
```
- `CREATE TABLE` creates a new table.
- `INSERT INTO` adds records.
---
4. Reading Data
from a Table
```foxpro
USE Test
SCAN
?
"ID: " + TRANSFORM(ID) + ", Name: " + Name
ENDSCAN
```
- `USE` opens a table.
- `SCAN...ENDSCAN` loops through records.
---
5. Conditional
Statements
```foxpro
LOCAL age
age = 18
IF age >= 18
?
"You are eligible to vote."
ELSE
?
"You are not eligible to vote."
ENDIF
```
---
6. Simple Loops
```foxpro
LOCAL i
FOR i = 1 TO 5
?
"Number: " + TRANSFORM(i)
NEXT
```
- `FOR...NEXT` is used for looping.
---
7. Simple
Function
```foxpro
FUNCTION Greet(name)
RETURN "Hello, " + name + "!"
ENDFUNC
? Greet("Alice")
```
---
8. Basic Form
Creation
You can use the Form Designer, but programmatically:
```foxpro
oForm = CREATEOBJECT("Form")
oForm.Caption = "My First Form"
oForm.Width = 300
oForm.Height = 200
oLabel = CREATEOBJECT("Label")
oLabel.Caption = "Hello, Visual
FoxPro!"
oLabel.Top = 50
oLabel.Left = 50
oForm.AddObject("myLabel", oLabel)
oForm.Show()
READ EVENTS
```
---These examples demonstrate foundational concepts.
Visual FoxPro also supports database operations, reports, and advanced user
interface development. If you're starting, focus on understanding table
manipulations and simple user interface programming.
===
*-----------------------------------------------To run
set colo to bg+
@03,00 TO 03,79
SET COLOR TO GR+
hed= "User Addition"
lhed = LEN(hed)
SET COLOR TO GR+
@03,(79-lhed)/2 say hed
set color to BG+
K_ESC=27
@ 4,00 clear to 24,79
@ 3,00 to 03,79
@24,00 TO 24,79 '°'
*----------Variables
msrl_no =
space(3)
ans_msg =
space(1)
mname =
spac(8)
sp =
space(78)
mpass =
spac(8)
mspass =
spac(8)
mnm =
spac(08)
superpass = space(8)
authpass1 = space(8)
mrole =
'Operator '
mloc_code = '001'
mans = 'N'
pm_setup = .t.
mchksup = .t.
msupvisor = .t.
msfound = .f.
*
set colo to n/w+
@ 3, 65 say "<Esc to Exit..>"
set colo to bg+
*
sele 26
USE LOGUSER INDE LOGUSER
save scre to
pass1
loca for level = '@'
*
if foun()
mnm = name
superpass =
notouse
else
msrl_no =
"050"
do usemsg
retu
endif
loca for level = '$'
if found()
mnm1 = name
authpass1 =
notouse
mchksup = .t.
msupvisor =
.t.
else
mchksup = .f.
msupvisor =
.f.
endif
*
con1pass = .t.
*
set colo to bg+
do whil con1pass
msuper = 'Y'
@ 06,01 say
"Authorisation Password: "
set colo to n
@ 06, 25 get
mspass pict "@!" func 'N'
read
set colo to
bg+
if
last() = 27
* restore
scre from pass1
return
endif
if mspass =
space(8)
loop
else
mspass =
chrt(mspass,;
'ABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()-=+_<>?|./\{}[]
0123456789',;
'9876543210P~!@#$%^&*()-=+_<>?|./\{}[]ABCDEFGHIJKLMNO
QRSTUVWXYZ')
*
sele 26
set filt to
level = '@'
go top
do while
!eof()
if
mspass # notouse
sele
26
skip
loop
else
mnm = name
superpass = notouse
msfound = .t.
exit
endif
enddo
endif
*
if mspass #
superpass
mchksup =
.t.
else
* @ 06, 30
say name
mrole =
'Super User'
@ 06,01
clea to 06,78
@ 06, 01
say mrole
mchksup =
.f.
endif
*
sele 26
set filt to
if mchksup =
.t.
sele 26
set filt
to level = '$'
go top
do while
!eof()
if
mspass # notouse
sele
26
skip
loop
else
msfound = .t.
@
06, 30 say name
mrole = 'Supervisor'
@
06, 40 say mrole
exit
endif
enddo
sele 26
set filt
to
go top
*
if msfound
# .t.
msrl_no
= '053'
do
usemsg
exit
endif
endif
*
mname = spac(8)
mspass =
spac(8)
mlevel = '^'
@ 08,01 say
'User Role ............:'
@ 08,25 get
mrole when acc_role(mrole) pict '@!' valid val_role(mrole)
read
if
last() = 27
rest scre
from pass1
exit
endi
set colo to
bg+
do case
case
mrole = 'SUPER USER'
mlevel =
'0'
case
mrole = 'SUPERVISOR'
mlevel =
'1'
case
mrole = 'USERS'
mlevel =
'2'
case
mrole = 'OPERATOR'
mlevel =
'3'
endcase
*
@ 10,01 say
"User Name ............:"
@ 10,25 get
mname pict "@!" func 'A'
read
if
last() = 27
rest scre
from pass1
exit
endi
*
sele 26
seek mname
if found()
msrl_no =
"001"
do usemsg
@ 06,00
clea to 24,79
loop
endif
*
@ 11,01 say
"User Password.........: "
set colo to n
set inte off
@ 11,25 get
mspass pict "@!" func 'N'
read
set colo to
bg+
if
last() = 27
rest scre
from pass1
exit
endi
mspass =
chrt(mspass,;
'ABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()-=+_<>?|./\{}[]
0123456789',;
'9876543210P~!@#$%^&*()-=+_<>?|./\{}[]ABCDEFGHIJKLMNO
QRSTUVWXYZ')
sele 26
appe blank
replace
name with mname
replace
notouse with mspass
do case
case
mlevel = '0'
mlevel = '@'
case
mlevel = '1'
mlevel = '$'
case
mlevel = '2'
mlevel = '~'
case
mlevel = '3'
mlevel = '^'
endcase
repl
level with mlevel
msrl_no =
'006'
do usemsg
exit
enddo
retu
*
func acc_role
para p_role
*
*if msupvisor = .F.
if mchksup = .f.
set colo to
w+/rb
defi popu
rolepop from 07,49 to 13,79 ;
footer
"<ENTER>-Select <ESC>-Exit"
defi bar 1 of
rolepop prom " Super User "
defi bar 2 of
rolepop prom " Supervisor "
defi bar 3 of
rolepop prom " Users "
defi bar 4 of
rolepop prom " Operator "
on sele popu
rolepop do rolepop with prom()
activ popu
rolepop
else
defi popu rolepop from 07,49 to 10,79 ;
footer
"<ENTER>-Select <ESC>-Exit"
defi bar 1 of
rolepop prom " Users "
defi bar 2 of
rolepop prom " Operator "
on sele popu
rolepop do rolepop with prom()
activ popu
rolepop
endif
set colo to bg+
retu p_role
*
func rolepop
para mprom
*mrole = uppe(subs(mprom,6,10))
mrole = allt(uppe(mprom))
deactivate popu rolepop
return
*
func val_role
para mrole
if mrole # "SUPER USER" and mrole #
"SUPERVISOR" and mrole # "USERS" and mrole #
"OPERATOR"
retu .F.
else
retu .T.
endif
retu
===
close all
clear
set dele on
hide menu all
hide popup all
sele a
use cheqreg
set order to tag cheqno
sele b
use funds
mcheqno = 0
mans = space(1)
m.part = space(35)
m.cheqdt = ctod("//")
m.cheqamt = 0
fdate = ctod("//")
@ 5,10 say " ** CANCEL CHEQUE **"
@ 7,10 say "CHEQUE NO. : " get mcheqno valid cheqno()
read
@ 9,10 say
"CHEQ-DATE :" get
m.cheqdt
@ 11,10 say "PARTICULARS :" get m.part
@ 13,10 say "AMOUNT :" get m.cheqamt pict
"9999999999.99"
@ 15,10 say "CHEQUE CANCEL...? (Y/N)" get
mans pict "@!x"
read
if lastkey()
= 27
close all
clear
return
endif
if mans =
"Y"
sele
cheqreg
repl stat
with "C"
delete
fdate =
f_Date
sele funds
set order
to tag fundsa
seek fdate
repl
curbal with curbal+m.cheqamt
endif
close all
clear
return
*-------------------------------
function cheqno
sele cheqreg
seek str(mcheqno,10)
if found()
m.part =
part
m.cheqdt
= cheqdt
m.cheqamt
= cheqamt
else
wait
window "Please check Cheque Number..." timeout 3
_curobj =
objnum(mcheqno)
endif
*----------------------------------------
clos all
clear
set stat off
sele a
use cheqreg
define window wshow from 3,3 to 23,73 double title "CHEQUE NO. ENTRY"
define window wshow1 from 3,3 to 23,80 double title "CHEQUE DATE ENTRY"
*brow fields part :H = 'PARTICULARS',cheqamt :H = 'AMOUNT',cheqno :H = 'CHEQ.NO' freeze cheqno for cheqno = 0 window wshow
*brow fields part :H = 'PARTICULARS',cheqamt :H = 'AMOUNT',cheqno :H = ' CHEQ.NO',cheqdt :H ='CHEQ.DT' FREEZE cheqdt for cheqdt = ctod("//") window wshow1
brow fields part :H = 'PARTICULARS',cheqamt :H = 'AMOUNT',cheqno :H = 'CHEQ.NO' for cheqno = 0 window wshow
brow fields part :H = 'PARTICULARS',cheqamt :H = 'AMOUNT',cheqno :H = ' CHEQ.NO',cheqdt :H ='CHEQ.DT' FREEZE cheqdt for cheqdt = ctod("//") window wshow1
*BROWSE FIELDS ytdpurch :H = 'Purchases:' , ;
* company :H = 'Company:' ;
* FREEZE ytdpurch
close all
===
close
all
clear
hide
menu all
hide
popup all
sele
a
use
cheqreg
sele
b
use
chq
copy
stru to cheque
sele
c
use
cheque
mfr
= 0
mto
= 0
ans
= space(1)
@
5,10 say "** CHEQUE PRINTING **"
@
7,10 say "CHEQUE RANGE"
@
7,25 say "FROM : " get mfr
@
7,45 say "TO : " get mto
read
@
9,10 say "PRINT ? (Y/N).." get ans pict "@!x"
read
if ans = "Y"
do getrec
brow
wait window "Please check the
Printer & Cheque Stationary.."
do chqprn
else
close all
clear
return to menu1
endif
close
all
clear
return
to menu1
*-------------------------------------------------------------------
proc
getrec
sele
* from cheqreg where cheqno >= mfr and cheqno <= mto into table tmp
sele
tmp
do while !eof()
sele cheque
appe blank
repl br_name with tmp.part,;
dwamt with tmp.cheqamt,;
cheq_no with tmp.cheqno,;
dt with tmp.cheqdt
sele tmp
if !eof()
skip
loop
endif
enddo
sele
cheque
GO
TOP
do
while !eof()
do newnum
sele cheque
if !eof()
skip
loop
endif
enddo
*--------------------------
PROC
NEWNUM
PARA
NUM
num
= cheque.dwamt
PUBLIC
ALL
GLOBAL_STRING
= ""
NOTOWORD_STRING
= ""
DIME
NUMNO(27)
NUMNO(1)
= 1
NUMNO(2)
= 2
NUMNO(3)
= 3
NUMNO(4)
= 4
NUMNO(5)
= 5
NUMNO(6)
= 6
NUMNO(7)
= 7
NUMNO(8)
= 8
NUMNO(9)
= 9
NUMNO(10)
= 10
NUMNO(11)
= 11
NUMNO(12)
= 12
NUMNO(13)
= 13
NUMNO(14)
= 14
NUMNO(15)
= 15
NUMNO(16)
= 16
NUMNO(17)
= 17
NUMNO(18)
= 18
NUMNO(19)
= 19
NUMNO(20)
= 20
NUMNO(21)
= 30
NUMNO(22)
= 40
NUMNO(23)
= 50
NUMNO(24)
= 60
NUMNO(25)
= 70
NUMNO(26)
= 80
NUMNO(27)
= 90
DIME
WORD(32)
WORD(1)
= "One"
WORD(2)
= "Two"
WORD(3)
= "Three"
WORD(4)
= "Four"
WORD(5)
= "Five"
WORD(6)
= "Six"
WORD(7)
= "Seven"
WORD(8)
= "Eight"
WORD(9)
= "Nine"
WORD(10)
= "Ten"
WORD(11)
= "Eleven"
WORD(12)
= "Twelve"
WORD(13)
= "Thirteen"
WORD(14)
= "Fourteen"
WORD(15)
= "Fifteen"
WORD(16)
= "Sixteen"
WORD(17)
= "Seventeen"
WORD(18)
= "Eighteen"
WORD(19)
= "Ninteen"
WORD(20)
= "Twenty"
WORD(21)
= "Thirty"
WORD(22)
= "Forty"
WORD(23)
= "Fifty"
WORD(24)
= "Sixty"
WORD(25)
= "Seventy"
WORD(26)
= "Eighty"
WORD(27)
= "Ninty"
WORD(28)
= "Paise"
WORD(29)
= ""
WORD(30)
= "Hundred"
WORD(31)
= "Thousand"
WORD(32)
= "Lakh"
STRNUM
= STR(NUM,10,2)
DECI
= VAL(SUBSTR(STRNUM,6,2))
HUND
= VAL(SUBSTR(STRNUM,5,1))
THOU
= VAL(SUBSTR(STRNUM,3,2))
LACK
= VAL(SUBSTR(STRNUM,1,2))
PAIS
= VAL(SUBSTR(STRNUM,9,2))
DIME
SPLIT(5)
SPLIT(5)
= PAIS
SPLIT(4)
= DECI
SPLIT(3)
= HUND
SPLIT(2)
= THOU
SPLIT(1)
= LACK
J
= 1
DO
WHILE J <= 5
IF RETWORD(SPLIT(J)) == .T.
NOTOWORD_STRING = NOTOWORD_STRING+ " "+GLOBAL_STRING+"
"+WORD(33-j)
ENDIF
j = j+1
ENDDO
NEW=
ALLTRIM(NOTOWORD_STRING)+" ONLY"
I
= LEN(NEW)
IF I > 40
SELE CHEQUE
REPL AMOUNT1 WITH
UPPER(LEFT(ALLTRIM(NEW),39))+ "-";
AMOUNT2 WITH "-"+
UPPER(RIGHT(ALLTRIM(NEW),I-39))
else
sele cheque
repl amount1 with upper(alltrim(NEW))
ENDIF
*-----------------------------------------
PROCEDURE
RETWORD20
PARA
NO
I
= 1
DO
WHILE I<=27
IF NUMNO(I) == NO
GLOBAL_STRING = WORD(I)
RETURN .T.
ENDIF
I=I+1
ENDDO
RETURN
.F.
PROCEDURE
RETWORD
PARA
NO
WRD1
= ""
IF
RETWORD20(NO) == .F.
ST = STR(NO,2)
NO1 = VAL(LEFT(ST,1))*10
NO2 = VAL(RIGHT(ST,1))
IF RETWORD20(NO1) == .T.
WRD1 = GLOBAL_STRING
IF RETWORD20(NO2) == .T.
GLOBAL_STRING
= WRD1 + " "+GLOBAL_STRING
RETURN .T.
ENDIF
ENDIF
RETURN .F.
ENDIF
RETURN
.T.
*--------------------------------
*-----------------------------------------------CLNTMAST.prg
* CLIENT Master Creation
*------------------------------------------------------------
@03,30 CLEAR TO 03,48
SET COLOR TO GR+
CDESP='** Client Master Change **'
CLEN = LEN(CDESP)
CPOS=(80-CLEN) / 2
@03,CPOS say CDESP
set color to BG+
K_ESC=27
@ 4,00 clear to 24,79
@ 5,00 to 05,79
@24,00 TO 24,79 '°'
*----------variables
M_CL_NM_OUT = SPACE(60)
mshrt_name = space(20)
msrl_no = space(3)
mclnt_code = '001'
m_cl_name = space(50)
m_add1 = space(40)
m_add2 = space(40)
m_add3 = space(40)
m_city = space(15)
m_state = space(20)
m_pin = space(8)
m_tanno = space(20)
m_tel_r = space(15)
m_tel_o = space(15)
mcont_per = space(20)
mi_date = space(8)
m_fax = space(40)
m_email = space(50)
m_sign = space(15)
mfrom_year = 0
mto_year = 0
mf_add1 = space(40)
mf_add2 = space(40)
mbill_auth = space(40)
mcdl_prd = 90
ans_msg=space(1)
declare opt[5]
option = space(1)
*---------------------------------------------
sele 1
use CLIENT
INDEX ON CLNT_CODE TO CLIENT
sele 1
DO WHILE (option # 'E')
@ 5,00 clear to 24,79
@ 5,00 to 05,79
@4,01 clear TO 04,78
@ 4, 10 PROMPT '\<Change'
opt[ 1] = 'C'
@ 4, 55 PROMPT '\<View'
opt[ 2] = 'V'
@ 4, 70 PROMPT '\<Exit'
opt[ 3] = 'E'
@ 4, 75 SAY SPACE(3)
set intensity on
nopt = 1
menu to nopt
set intensity off
if nopt >= 1 .and. nopt <= 3
option = opt[nopt]
else
option = space(1)
endif
if option = 'E'
exit
else
if option = 'V'
do VIEWFLDS
@ 5,01 to 05,78
else
set filter to
@ 5,00 clear to 24,79
@ 5,00 to 05,79
mclnt_code = '001'
do DISPSCRE && Display Screen
DO WHILE LASTKEY() != K_ESC
do CLOSE_OPEN
do GETKEY
if LASTKEY() = K_ESC
exit
else
sele CLIENT
seek (mclnt_code)
DO CASE
case option = 'C'
do CHANGE_OPT
case option = 'D'
do DELETE_OPT
ENDCASE
endif
ENDDO ( mclnt_code # '0')
endif
endif
ENDDO (option # 'E')
CLOSE ALL
@6,00 clear to 20,79
RETURN
*---------------------------------------------------
PROCEDURE CHANGE_OPT
if found()
do TRAFFLD
do DISPFLDS
do GETFLDS
*read
do REPLFLD
MSRL_NO = '007'
DO USEMSG
else
MSRL_NO = '002'
DO USEMSG
endif
set color to BG+
RETURN
*---------------------------------------------------------
PROCEDURE REPLFLD
sele CLIENT
repl clnt_code with mclnt_code
repl clnt_name with m_cl_name
repl short_name with mshrt_name
repl clnt_add1 with m_add1
repl clnt_add2 with m_add2
repl clnt_add3 with m_add3
repl clnt_city with m_city
repl clnt_state with m_state
repl clnt_pin with m_pin
repl clnt_telr with m_tel_r
repl clnt_telo with m_tel_o
repl clnt_tanno with m_tanno
repl clnt_contr with mcont_per
repl clnt_sign with m_sign
repl clnt_fax with m_fax
repl clnt_email with m_email
repl from_year with mfrom_year
repl to_year with mto_year
repl f_add1 with mf_add1
repl f_add2 with mf_add2
repl bill_auth with mbill_auth
do updtuser
RETURN
*---------------------------------------------------------
PROCEDURE DISPSCRE
@ 6, 0 clear to 24, 79
set colo to n/w+
@ 05, 65 say '<Esc to Exit..>'
set colo to bg+
@ 6, 1 SAY 'Tele. Office Code.:'
@ 8, 1 SAY 'Name .............:'
@ 09, 1 SAY 'Short Name.......:'
@ 10, 1 SAY 'Address line1....:'
@ 11, 1 SAY 'Address line2....:'
@ 12, 1 SAY 'Address line3....:'
@ 13, 1 SAY 'City Name........:'
@ 13, 45 SAY 'State..:'
@ 14, 1 SAY 'Pin code.........:'
@15,1 to 15,78
@ 16, 1 SAY 'Contact Person...:'
@ 17, 1 SAY 'Phone (Res) (Off):'
@ 18, 1 SAY 'Fax No...........:'
@ 19, 1 SAY 'E_Mail Address ..:'
@ 20, 1 SAY 'Fin.From-To Years:'
@ 21, 1 SAY 'From Name.& Addr.:'
@ 22, 1 SAY 'Address-2........:'
@ 23, 1 SAY 'Billing Authority:'
RETURN
*----------------------------------------------------
PROCEDURE GETKEY
DO WHILE .T.
@ 6, 19 get mclnt_code pict '@!'
read
if lastkey() = k_esc
exit
endif
if mclnt_code # clnt_code
msrl_no = '002'
do USEMSG
loop
else
exit
endif
ENDDO
RETURN
*------------------------------------------------------
PROCEDURE GETFLDS
@ 8, 19 get m_cl_name pict '@!'
@ 09, 19 get mshrt_name pict '@!'
@ 10, 19 get m_add1 pict '@!'
@ 11, 19 get m_add2 pict '@!'
@ 12, 19 get m_add3 pict '@!'
@ 13, 19 get m_city pict '@!'
@ 13, 55 get m_state pict '@!'
@ 14, 19 get m_pin pict '@!'
@ 16, 19 GET mcont_per
@ 17, 19 GET m_tel_r pict '@!'
@ 17, 39 GET m_tel_o pict '@!'
@ 18, 19 GET m_fax
@ 19, 19 GET m_email
do while .t.
@ 20, 19 get mfrom_year pict '9999'
@ 20, 40 get mto_year pict '9999'
read
if mto_year < mfrom_year
loop
else
exit
endif
enddo
@21, 19 get mf_add1 pict '@!'
@22, 19 get mf_add2 pict '@!'
@23, 19 get mbill_auth pict '@!'
read
SET COLO TO BG+
RETURN
*------------------------------------------------------
PROCEDURE DISPFLDS
@ 8, 20 say m_cl_name pict '@!'
@ 09, 20 say mshrt_name pict '@!'
@ 10, 20 say m_add1 pict '@!'
@ 11, 20 say m_add2 pict '@!'
@ 12, 20 say m_add3 pict '@!'
@ 13, 20 say m_city pict '@!'
@ 13, 56 say m_state pict '@!'
@ 14, 20 say m_pin pict '@!'
@ 16, 20 say mcont_per pict '@!'
@ 17, 20 say m_tel_r pict '@!'
@ 17, 40 say m_tel_o pict '@!'
@ 18, 20 say m_fax
@ 19, 20 say m_email
@ 20,20 say mfrom_year pict '9999'
@ 20, 41 say mto_year pict '9999'
@21, 20 say mf_add1 pict '@!'
@22, 20 say mf_add2 pict '@!'
@23, 20 say mbill_auth pict '@!'
RETURN
*------------------------------------------------------
PROCEDURE INITFLDS
m_cl_name = space(50)
mshrt_name = space(20)
m_add1 = space(40)
m_add2 = space(40)
m_add3 = space(40)
m_city = space(15)
m_state = space(20)
m_pin = space(8)
m_tel_r = space(15)
m_tel_o = space(15)
m_fax = space(40)
m_email = space(50)
mcont_per = space(10)
m_tanno = space(20)
m_sign = space(15)
mfrom_year = 0
mto_year = 0
mf_add1 = space(40)
mf_add2 = space(40)
mbill_auth = space(40)
RETURN
*--------------------------------------------------
PROCEDURE TRAFFLD
m_cl_name = clnt_name
mshrt_name = short_name
m_add1 = clnt_add1
m_add2 = clnt_add2
m_add3 = clnt_add3
m_city = clnt_city
m_state= clnt_state
m_pin = clnt_pin
m_tel_r = clnt_telr
m_tel_o = clnt_telo
mcont_per = clnt_contr
m_fax = clnt_fax
m_email = clnt_email
mfrom_year = from_year
mto_year = to_year
mf_add1 = f_add1
mf_add2 = f_add2
mbill_auth = bill_auth
RETURN
*--------------------------------------------------
PROCEDURE VIEWFLDS
SELE CLIENT
go top
do TRAFFLD
do DISPSCRE
do DISPFLDS
WAIT""
*BROWSE NOEDIT
@05, 00 clear to 24, 79
RETURN
*---------------------------------------------------
PROCEDURE CLOSE_OPEN
sele 1
use
sele 1
use CLIENT index CLIENT
RETURN
*--------------------------------------------------
PROCEDURE GET_SNAME
l=len(m_cl_name)
ms_name = ''
ms_name= substr(m_cl_name,1,1)+' '
spc_pos1 = AT(' ',m_cl_name)
ms_name = ms_name+substr(m_cl_name,spc_pos1+1,1)
x=substr(m_cl_name,spc_pos1+1,l)
l=len(x)
spc_pos2 = AT(' ',x)
ms_name=ms_name+substr(x,spc_pos2,spc_pos2+1)
mshrt_name = ms_name
RETURN
====
In Visual
FoxPro (VFP), SET commands are used to configure the environment and
control the behavior of the system. These commands allow developers to
customize settings such as data handling, user interface properties, and system
behavior. Below is a categorized overview of some commonly used SET commands
in Visual FoxPro:
1. Data
Handling Commands
- SET ALTERNATE
Controls whether output is sent to an alternate file.
·
SET
ALTERNATE ON
·
SET
ALTERNATE TO log.txt
- SET DATE
Specifies the date format.
·
SET DATE
TO DMY && Day-Month-Year
- SET CENTURY
Determines whether a four-digit year is used.
·
SET
CENTURY ON
- SET DELETED
Specifies whether records marked for deletion are included in the result
set.
·
SET
DELETED ON
- SET EXACT
Determines whether string comparisons must be exact.
·
SET EXACT
ON
2.
Display and Formatting Commands
- SET COLOR
Sets the color scheme for the interface.
·
SET COLOR
TO N/W && Normal text is white
on black
- SET BELL
Enables or disables the system bell.
·
SET BELL
OFF
- SET ECHO
Determines whether commands in a program are displayed on the screen.
·
SET ECHO
OFF
- SET FORMAT
Controls how fields are displayed in output.
·
SET
FORMAT TO
- SET TALK
Controls whether command results are displayed.
·
SET TALK
OFF
3. File
and Memory Management
- SET DEFAULT
Specifies the default directory.
·
SET
DEFAULT TO C:\Projects
- SET PATH
Specifies the search path for files.
·
SET PATH
TO C:\Data
- SET SAFETY
Determines whether confirmation is required when overwriting files.
·
SET
SAFETY OFF
4.
Indexing and Sorting
- SET ORDER
Specifies the active index tag in the currently selected work area.
·
SET ORDER
TO TAG CustomerID
- SET COLLATE
Sets the collation sequence for string comparisons.
·
SET
COLLATE TO "MACHINE"
5. SQL
and Query Settings
- SET ANSI
Controls how SQL queries treat string comparisons.
·
SET ANSI
OFF
- SET ENGINEBEHAVIOR
Configures how the SQL engine processes commands.
·
SET
ENGINEBEHAVIOR 70
6.
Environment Configuration
- SET EXCLUSIVE
Determines whether a table is opened exclusively or shared.
·
SET
EXCLUSIVE OFF
- SET MULTILOCKS
Enables or disables record locking for multiple records.
·
SET
MULTILOCKS ON
- SET CURRENCY
Specifies the currency symbol.
·
SET
CURRENCY TO "$"
7.
Debugging and Development
- SET STEP ON
Enables the debugger during program execution.
·
SET STEP
ON
- SET DEBUG
Turns the Debug Window on or off.
·
SET DEBUG
ON
8.
Miscellaneous
- SET SYSFORMATS
Controls whether system formats are used.
·
SET
SYSFORMATS ON
- SET PRINTER
Directs output to the printer.
·
SET
PRINTER ON
·
SET
PRINTER TO NAME "HP_LaserJet"
Example:
Combining SET Commands
SET DATE TO DMY
SET CENTURY ON
SET DELETED ON
SET EXCLUSIVE OFF
SET PATH TO C:\MyApp\Data
SET TALK OFF
This
configuration ensures:
- Date formats use
day-month-year with a four-digit year.
- Deleted records are excluded
from results.
- Tables are opened in shared
mode.
- The data path is set to a
specific directory.
- Command results are not
displayed.
Conclusion
SET
commands in Visual FoxPro are powerful tools for customizing the application
environment. Proper usage ensures smoother operations, better debugging, and
adherence to project requirements.
====
No comments:
Post a Comment