Category : Dbase (Clipper, FoxBase, etc) Languages Source Code
Archive   : TN8911.ZIP
Filename : NET.TXT

 
Output of file : NET.TXT contained in archive : TN8911.ZIP
Network Format Files
Gary Gregory
This article is intended to ease the generation of format files for network
applications. The first thing we'll do is to create a .GEN file that will
generate an .FMT file with memory variables instead of field names. Next,
we'll alter that .GEN file and add a .PRG file to manipulate the memory
variables. I'm assuming that you are familiar with the general concepts
surrounding the template language environment. You will also need the dBASE
IV 1.0 Developer's Edition which contains all of the template source code and
the template language compiler DTC.EXE. For more information on the subject
please read the "Introduction to the Template Language" in the February '89
edition of TechNotes/dBASE IV.

The first thing you will want to do is work with a copy of FORM.COD. From the
DOS prompt type:


C:\>CD \DBASE\DTL
C:\DBASE\DTL> COPY FORM.COD MFORM.COD
This .COD file must be compiled to the .GEN format in order for dBASE IV to
understand it. To compile MForm.COD, type, at a DOS prompt:

C:\DBASE\DTL> DTC -iMForm.COD
The dBAS IV Template Compiler (DTC) is invoked with the -i
parameter that tells it which file to compile. The output will be, by
default, the same file name but with a .GEN extension. So the above command
will produce a file called MForm.GEN. You must then copy that file into the
dBASE directory. At the DOS prompt type:

C:\DBASE\DTL> COPY MForm.GEN C:\DBASE
Now tell dBASE to use this new .GEN file when generating screen forms by
typing (from the DOS prompt)

C:\DBASE> SET DTL_FORM=MFORM.GEN
Now we can go into dBASE and generate the .FMT files.
The Premise
When you are programming in a network environment you will want to minimize
record lock time and also avoid locking an entire database file. The most
widely used method to do this is to copy a record to memory variables, edit
those variables and then copy the data from the memory variables back to the
record. This article will show you how to create a screen form which will
generate the code to perform these operations.

MForm.COD
The first change is the simplest, we changed the names of the field names to
have the letter m as a prefix. So instead of generating an @.GET with
company, MForm.GEN will generate an @.GET with mcompany. To be consistent,
we made those changes across the whole source .COD file so that @.SAYs will
also use the new memory variables. Note that calculated field names do not
change and that other memory variables are still generated with the "m->"
prefix. The "m->" is not be confused with our "m" prefix; "m->" tells dBASE
IV to use what follows asa memory variable while our "m" is just the first
letter of a memory variable. You will want to be careful when using pick
lists in the forms generator. If you choose to enter a field name in an
expression with a pick list, add an m as the first character! You will not
have to do this if you type in the expressions yourself. The format files
generated will not handle memo fields beyond 254 characters since you cannot
put a whole memo in a memory variable and the length of a memory variable
cannot exceed 254 characters. You could conceivably copy a memo field into
an array of strings and manipulate those. We will leave this dBASE IV
programming issue for you to play with and concentrate on the template
language here.

At a DOS prompt type:
SET DTL_FORM=MFORM.GEN
Then regenerate your .FMT files in dBASE IV.
The way we perform the changes to the template is quite simple: the name of a
field is stored in a selector called Fld_fieldname. So what we will do is
search for all instances of Fld_fieldname and decide whether we should prefix
the expression containing it with the letter m. Prefixing a field with an m
brings up the possibility of a conflict. dBASE IV will allow variable name
to be over ten (10) characters long in a source file but only the first ten
characters will be significant. This means that field names that have the
exact same first nine (9) characters will end up being the same when prefixed
with the letter m. So watch out for your field names. As a last but
important note, this template will not completely emulate a real format file.
Since memory variables are used, we cannot jump up and down records as the
user presses PgUp and PgDn.

Since there are few occurrences of the selector we are looking for, we will
list these sections of code rather than the entire new MForm.COD. Now let's
look at our copy of MForm.COD and occurrences of Fld_fieldname. The line
numbers we give are from the original unmodified FORM.COD file located in the
DBASE\DTL directory.

The first occurrence is at line 143 and deals with memo windows. We will skip
this one since it is in a comment. The second occurrence is at line 164 and
171. This piece of code handles the SET CARRY TO command. Since we are
dealing with memory variables, we will ignore this setting. This code could
also be deleted. If we cared about following the CARRY setting we would need
to generate some extra dBASE code to go fetch data from the previous record
and remember what the current values are for the next time around, etc.
Next, at line 203, the selector is just used for comments. We do not want to
change those anyway because doing so would affect the name of calculated
fields or memory variables.

The only real change we need to make is in the section of code that generates
the @.SAY and @.GET commands (starting at line 240). We want to change the
way field names are generated, which happens on lines 250 and 266. Here are
lines 249 and 250

which we'll change to
Next, lines 265 and 266 go from
to

What the above template language statement says in English is this: if the
current field is a database field then make temp equal to the empty string;
otherwise make temp equal to "m->".

The field name is then created in the @.SAY and @.GET as temp followed by the
actual field name. The "m->" will tell dBASE when it is running that the name
after "m->" is a memory variable. What we want to do is give a different
name to each database field name. So instead of assigning "" to temp we have
just assigned the letter m to temp instead! We also changed the expression
to let the database field come out in upper case with our m prefix in lower
case.

Now we can compile the new template, set the DTL_FORM DOS environment variable
and bang away some forms. Here is how you can test this new form on the
EMPLOYEE.DBF sample file. From the DOS prompt, type


C:\DBASE\DTL> DTC -iMForm.COD
C:\DBASE\DTL> COPY MForm.GEN ..
C:\DBASE\DTL> CD ..
C:\DBASE> SET DTL_FORM=MForm.GEN
C:\DBASE> DBASE

Then, from within dBASE IV, type

. USE EMPLOYEE
. CREATE SCREEN MTEST
Once within the screen generator, choose quick layout (it's quicker). After
saving the screen, the resulting file, MTest.FMT, will contain the same text
as a normal .FMT except that all the field names are in upper case, prefixed
with the letter m.

Making MForm More Comprehensive
The changes that we've made so far are extremely simple and produce simple
results. Let's summarize the issues that we have encountered before we move
on to the second part of this article. Field names in a database that are 10
characters long and have the first nine characters identical will cause a
problem by creating identical memory variable names. Memo fields are only
supported by this template for the first 254 characters. Another feature not
supported is the SET CARRY TO command.

We could stop here, but we won't. We want this whole thing to be a bit more
comprehensive, so what we'll have the template generate some support code for
this format file. What we want to be generated automatically are four
procedures.

Procedure InitVars will create and initialize memory variables. Character
variables will be set to spaces equal to the size of that field in the
database. Logical fields will be set to FALSE, numeric variables to 0 and
date variables to today's date.

Procedure Rec2Vars will transfer data from all fields of the current record to
the memory variable.

Procedure Vars2Rec will copy the data from the memory variables back to the
current record.

Procedure MyLocker is a simple record locking routine and is called by both
the Rec2Vars and Vars2Rec procedures. Although it would be nice if MyLocker
could be a UDF so it would be consistent with the RLOCK() function, MyLocker
uses a restricted command (ON ERROR), so it must be a procedure.

The last three procedures, Rec2Var, Vars2Rec and MyLocker all need a logical
parameter passed to them. They will all change that parameter to TRUE if
they were successful and FALSE if they were not.

We'll put the code that generates these procedures in a file called
InitForm.COD. We don't have to compile this file since we have included it
automatically when we compile MForm.COD by inserting the include statement in
MForm.COD at line 361. Here's what lines 360 to 362 look like now:


fileerase(fmt_name+".FMO");
nogen:
return 0;

Insert the include command so that it looks like this:

fileerase(fmt_name+".FMO");
include "InitForm.COD";
nogen:
return 0;

The listing for InitForm.COD starts on page 15.
Generating the procedure file
Let's examine the different sections of InitForm.COD. The first section (line
56) creates the actual procedure file. The template language has a number
of very useful file routines that we used. The most important one here is
create() which creates the .PRG procedure file. Here is a brief explanation
of the template language functions we used. For a complete description,
consult the Template Language manual that comes with the dBASE IV Developer's
edition.

Create() This function will create the named file in which all
subsequent output will be directed. You can issue another Create() or
Append() to change the output again. We use this function to create a
procedure filename with the same name as the template but with a .PRG
extension (line 69).

FileOK() This function tells you if the is a valid DOS
file name (line 59).

FileErase() This function erases the named file. The template will
erase any old copy of the .PRG procedure file (line 67) and its associated
compiled .DBO (line 68).

Generating the InitVars dBASE procedure
The code that generates that procedure is split into two parts. First we
declare the memory variables PUBLIC and we then create the assignment
statements. All of the memory variables that we define must be made public
so that their definitions remain when we exit the InitVars procedure. The
code starting with the dBASE keyword PUBLIC (line 95) will handle the
generation of that statement following this syntax:

PUBLIC mvar1, mvar2, mvar3 ...
There is a foreach loop at line 112 that will go through all the fields
defined in the screen form. The if statement below that foreach will only be
entered if we are dealing with a database field. Since a statement can span
more than one line, we keep track of how long the line is with the template
variable public_len (line 114). We break up a line and terminate it with a
semi-colon if the next statement can go beyond the 80th column (line 133).
We also keep track of how long the whole command is getting since a dBASE IV
command may not exceed 1024 characters (line 122). If the command gets too
big we split it up (lines 123-126). This may seem like a lot of detail, but
a template must always be written to handle all cases. In part two of this
procedure, the assignment statements are generated in a foreach loop (line
171). We go through all fields and only produce an assignment for database
fields. The assignment is started, at line 173, with

m{Fld fieldname} = \
This outputs the memory variable name. A case statement follows on which type
of field the data will be coming from. We assign a 0 for numerical fields,
0.00 for floats, .F. for logical fields, the dBASE DATE() function for dates
and spaces for character variables. We use a selector called Fld_length to
determine the number to pass to the dBASE SPACE() function. The Fld_length
selector holds the width of the current field in the database. Since the
width of memo fields is 10 in the database structure definition we must make
sure that 254 is the number of spaces assigned to the memory variable and not
10. The procedure ends with a RETURN statement at line 185.

Generating the Rec2Vars procedure
The Rec2Vars procedure at line 189 is the easiest one to generate. We have a
simple foreach loop through all field elements (lines 204-208). The
assignment is only generated for database fields and takes the form:

mFIELDNAME = FIELDNAME
This procedure is closed with a RETURN statement.
Generating the Vars2Rec procedure
This procedure will generate the replace statements that copy the data from
the memory variables to the current record. A foreach loop at line 244 that
will go through all the field elements defined in the screen form. The if
statement below that foreach will only be entered if we are dealing with a
database field. Much like the InitVars procedure, a good deal of code deals
with the possibility that the REPLACE command line will exceed 80 or 1024
characters. We keep track of the command length in the template variable
replace_lent and the length of the current line (break it up at the 80th
column) in the variable replace_len.

The simplest way to put MTEST.FMT and MTEST.PRG to work is, from the dot
prompt, type


SET TALK OFF
USE EMPLOYEE
SET PROCEDURE TO MTEST
SET FORMAT TO MTEST
DO InitVars
Ok = .F.
DO Rec2Vars WITH Ok
? Ok
READ
DO Vars2Rec WITH Ok
? Ok

We're almost doneÄjust one last change. Let's add an informational header to
MForm.COD for those folks who might issue the "TYPE MFORM.GEN" command from
the DOS prompt. So, at line 10, right underneath the copyright, insert


So there you have it. As a project you could create a template that in
addition would generate dBASE IV code to handle keystrokes to move around
records with the PgUp and PgDn keys by transferring data back and forth from
memory variables and records. The READ statement above will exit when the
cursor is moved off the screen. A full blown READ on a normal file would
move up and down the file. Until we meet again... t



  3 Responses to “Category : Dbase (Clipper, FoxBase, etc) Languages Source Code
Archive   : TN8911.ZIP
Filename : NET.TXT

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/