


Operations Manual

For

Increment/Decrement

Functions

(dBASE Version)













Written and Distributed by

Homegrown Data Systems                
St. Simons Is, GA                         

Fax "1" Of The Golden Isles
St. Simons Is, GA





Table Of Contents

1 - LIMITED WARRANTY	
2 - LICENSE AGREEMENT AND RIGHTS	
3 - PURCHASING THE SOFTWARE	
4 - GETTING TO KNOW WHAT YOU HAVE	
5 - GETTING STARTED WITH THE FUNCTIONS	
6 - USING THE FUNCTIONS	
6.0 - BASIC USE OF THE FUNCTIONS	
6.1 - LOGICAL INCREMENTS AND DECREMENTS	
6.2 - DATE INCREMENTS AND DECREMENTS	
6.3 - NUMERIC TYPE INCREMENTS AND DECREMENTS	
6.4 - ALPHABETIC INCREMENTS OR DECREMENTS	
7 - CASE STUDY	
8 - FUTURE PLANS	
9 - THE DEMO PROGRAM - IDDEMO.PRG	
10 - MAIL-IN ORDER FORM	




1 - Limited Warranty

HDS and Fax "1" (hereafter know as the SELLER) warrants that for a period of one (1) year from the date of acquisition, the Increment/Decrement functions (hereafter known as the SOFTWARE), if operated as directed, will achieve the functionality described in the Manual. The SELLER warrants that your use of the software will be reasonable free from errors.   The SELLER also warrants that the media containing the SOFTWARE, if provided by the SELLER, is free from defects in material and workmanship and will so remain for ninety (90) days from the date you acquired the SOFTWARE. The SELLER's sole liability for any breach of this warranty shall be, at the SELLER's sole discretion to: (1) replace any defective media; or (2) to advise you how to achieve substantially the same functionality with the SOFTWARE as described in the Manual through a different acquisition procedure; or (3) if the above remedies are impracticable, to refund the fee you paid for the SOFTWARE. Repaired, corrected, or replaced SOFTWARE and Documentation shall be covered by this limited warranty for the period remaining under the warranty that covered the original SOFTWARE. Only if you inform the SELLERS of your problem with the SOFTWARE during the applicable warranty period and provide evidence of the date you purchased a license to the SOFTWARE will the SELLERS be obligated to honor this warranty. 

THIS IS A LIMITED WARRANTY AND IT IS THE ONLY WARRANTY MADE BY THE SELLERS. THE SELLERS MAKE NO OTHER WARRANTY, EXPRESS OR IMPLIED, REGARDING MERCHANTABILITY AND OF FITNESS FOR A PARTICULAR PURPOSE.  NOTE THAT SOME JURISDICTIONS DO NOT ALLOW LIMITATIONS ON HOW LONG A WARRANTY LASTS, SO LIMITATIONS MAY NOT APPLY TO YOU. NO OTHER DEALER, AGENT, OR EMPLOYEE OF THE SELLERS IS AUTHORIZED TO MAKE ANY MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY. If any modifications are made to the Software by you during the warranty period; if the media is subjected to accident, abuse, or improper use; or if you violate the terms of this Agreement, then this warranty shall immediately be terminated. This warranty shall not apply if the Software is used on or in conjunction with hardware or software other than the unmodified version of hardware and software with which the software was designed to be used as described in the MANUAL.  THIS WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS, AND YOU MAY HAVE OTHER LEGAL RIGHTS THAT VARY BY JURISDICTION.

2 - License Agreement And Rights

The buyer is hereby granted a limited license to the SOFTWARE as a instructional tool in a stand-alone dBASE or compatible language environment and as programming tools in a dBASE or compatible programming environment.

If the SOFTWARE is used as a function (or set of functions) in any computer program developed by the BUYER, the source code of that program must, at some point, contain comments showing that the software was written by the SELLERS.

This License gives you the right to:

* use the SOFTWARE on a single computer for purposes of evaluation and instruction;
* use the SOFTWARE on a network, provided that each network station accessing the SOFTWARE through the network has an individual license agreement, purchased separately;
* copy the SOFTWARE twice for archival or backup purposes on media suitable for that purpose, provided any and all such copies of the SOFTWARE contain all of the original distribution files and no additional files;
* copy the SOFTWARE into programming project areas or directories where such projects reside, so that the SOFTWARE will be accessible to your software;
* distribute copies of the SOFTWARE as functions or linked object modules in dBASE IV or compatible programs.

This License does not give you the right to:

* permit other individuals to use the SOFTWARE except under the terms listed above;
* modify, translate, reverse engineer, decompile, disassemble, or create derivative works based on the SOFTWARE;
* copy the SOFTWARE other than as specified above;
* rent, lease, grant a security interest in, or otherwise transfer rights to the SOFTWARE; or
* remove any proprietary  notices or labels on or in the SOFTWARE.

The license will terminate automatically if you fail to comply with the limitations described herein.  On termination, you must destroy all copies of the SOFTWARE and Manual.  Any violations of this License Agreement will be seem as an attempt to steal, pirate, or illegally copy the software, and will result in criminal prosecution.

3 - Purchasing The SOFTWARE

The software that you downloaded is a demonstration version of the full package.  It will allow you to enjoy all the functions of the fully operational version, but will only work for 100 calls before quitting.  This limit is not built into the fully operation version, which you must have before using the SOFTWARE in a programming project.

This software is not freeware.  It was developed during many hours of hard work, and is not a thrown-together hacked piece of vaporware.  It is a set of professional, quality functions that can be truly useful for the application programmer.  

The authors of this software are marketing it as shareware in order to reach the largest market with the least amount of cost and trouble.  The price of the software is set at a reasonable $14.95 (US).  

The SELLERS of the software will send you a compressed file (ZIP usually, but in any format you request) with the full version upon receipt of payment.  The software may be delivered by either e-mail (free) or by USPS ($2.00 S&H).  Other methods, such as FedEX or UPS are available, but may require higher shipping and handling charges.  Payment can be made by either check or money order.  Please remit your payment to:

Meschke Development

and send your payments to either:

Homegrown Data Systems
344 Brockinton Drive
St. Simons Is, GA  31522

or 

Fax "1" of the Golden Isles
237 Sand Castle Road
St. Simons Island, GA  31522

To make ordering easier, we have included an order form at the end of the manual.  In the form you will find spaces to check off your method of payment, your preferred archive style, and the method of shipment you would like.  Orders are guaranteed to be shipped within one business day of receipt of your order.  We do not accept orders via e-mail, but will send you an e-mail message with the full version attached within 24 hours.

4 - Getting to Know What You Have

Inc/Dec is a collection of two dBASE user-defined functions which will allow the programmer to increment and decrement the values of either memory variables or field values.  Inc/Dec is supplied in the form of two .DBO files which are meant to be called by the programmer's stand-alone program, or linked into an executable program compiled with the Borland Database Compiler.  The DBO files can be used under dBASE IV or V for DOS and have been used in dBASE for Windows 5.0 and Visual dBASE 5.5.  The source code has found its way into a Foxpro application and worked there with minimal changes.

There is one function for incrementing and one for decrementing.  The names of the .DBO files are incfield.dbo and decfield.dbo.  The files occupy approximately 12,000 bytes of memory each, and will count as one open file each when they are used in a program.  There are no public variables used in the distributed functions, although the demo version of the functions does use one public variable.  The files must reside somewhere in the dBASE search path to be accessible to your dBASE programs, or the compiler.

Because of the recent and growing concern with the year 2000 crises, incfield and decfield have both been certified as year 2000 complient.  This complience is assured from version 1.1 onward.

5 - Getting Started With The Functions

The procedure for installing the functions onto your computer is easy.  First,  though, it is a good idea to print this manual.  It isn't very long, and will save you a lot of headaches looking for instructions later.  If you wish, you may create a separate directory for the documentation.  To do this, follow these instructions:

in MS-DOS or PC-DOS:
Change the current device to where you desire to place the new directory:
	c:\>d:  (example)
Make the new directory and change the current working directory:
	d:\>md id-docs (example)
	d:\>cd id-docs (example)
copy the documentation:
	d:\id-docs>xcopy a:\*.docs

In Windows 3.x and NT 3.51 and lesser:
Bring up the File Manager from the Main group in Program Manager.
Change to the device/directory where you wish to create the new directory.
Create the directory by pressing <Alt>F|E or by using the mouse by choosing File|Create Directory and enter the name of the new directory (id-docs).
Move back to the device/directory where the documentation resides, and select all of the *.doc files.

Copy the documentation files by either pressing F8, by pressing <Alt>F|C, or by using the mouse to choose File|Copy.  In the dialog box, enter the new device and directory name.  Another alternative to this is to open a second window in the File Manager, selecting the files to copy, and then drag and drop the files into the new device/directory.

In Windows NT 4.0/Windows 95:
From the Start button, bring up the programs menu.  From there, bring up Windows Explorer.
Change to the device/folder where you would like to create the new folder for the documentation.
Create the new folder by either pressing <Alt>F|W|Folder, or by using the mouse to choose File|New|Folder.
Enter the name of the new folder in the namespace of the newly created folder (try "Inc-Dec Documentation").
Change to the drive/folder where the documentation resides, and select all the files that end in .DOC.
Press <Ctrl>C (copy) or use the mouse to select Edit|Copy.
Move back to your new folder.
Press <Ctrl>V  or use the mouse and select Edit|Paste to paste the copied files into your new folder.

Now you must copy the two function files into the dBASE directory or your program development directory.  The following directions assume that you want the functions to be in your dBASE directory.  You can substitute any directory name you wish for installing the software, so long as dBASE can find it.

If you are in MS-DOS or PC-DOS:
Change to the device/directory where your dBASE IV program (dbase.exe) is located:
	c:\>cd \dBASE
Copy the two object files to the dBASE directory:
	c:\dbase>xcopy a:\*.dbo

In Windows 3.1/3.11 or NT 3.51 or lesser:
In the File Manager, change to the directory where you have exploded the compressed file.
Select the two .DBO files.
Copy the files to the directory where your dBASE program (dbase.exe) resides by either pressing <Alt>F|C, by pressing F8 or by using the mouse to select File|Copy.  In the dialog box, enter the name of the destination directory.

In Windows NT 4.0/Windows 95
In the Windows Explorer, move to the folder or device where you have placed the .DBO files.
Select the files, and press <Ctrl>C or use the mouse to select Edit|Copy to copy them.
Move to the folder where you have placed your dBASE program (dbase.exe).
Press <Ctrl>V or use the mouse to select Edit|Paste to paste the files into the new folder.

That's it!

Using these procedures, you may also move the demonstration program, iddemo.prg to the dBASE directory or folder.  A little more about this program later.





6 - Using the Functions

6.0 - Basic Use Of The Functions

The basic purpose of these functions is to increase or decrease the value of database fields or memory variables by one ordinal value.  The functions are very powerful, and work very hard to figure out what you want.

The functions are intended to be used to provide on-demand increment or decrement operations; by this, we mean that the application program would be written so that these routines are called in response to a user-generated event, such as pressing a key or hitting a mouse button.

The routines were NOT meant to be used in an interactive fashion; it would be more simple, and a lot faster in execution, for the programmer to write custom routines to increment or decrement a field within a database with 1000 records  than it would be to use inc/dec.

The increment/decrement functions can be used for any of the data types in dBASE IV and greater.  These types are logical, date, numeric and floating-point, and character/memo.

The basic usage of the increment/decrement functions is as follows:

return value = incField(data[, rule]) for increment, and

return value = decField(data[, rule]) for decrement.

The return value is the value of the data returned from the call.  If there are any errors detected in the input parameters, the functions will return the original data value.  The data parameter is the data the programmer wishes to manipulate.  The rule is a parameter which is used with the numeric/float and character/memo types, and is explained in more detail later.  

The functions will automatically detect the type of the incoming data, and adjust its increment or decrement operations accordingly.  The return value's data type will be the same as the type of the incoming data.


6.1 - Logical Increments and Decrements

Logical types that are incremented or decremented always return the opposite value of the incoming value.  For example, if the incoming value is .T., the returned value will be .F. no matter which of the two routines is used.  The question now on your mind is, "why was this included when a simple .NOT. statement would have sufficed?"  This type was included for the sake of completeness.  The designers of the functions wanted the routines to be as general as possible in as small a package as possible.

Here is an example of how the decrement function would operate from the dot prompt:

.set talk off
.public test1, test2
.test1 = .F.
.test2 = decField(test1)
.? test2
.T.
.


6.2 - Date Increments and Decrements

Date value calculations are not handled well in dBASE - leap years in particular.  If the programmer attempts to do a normal addition or subtraction to derive a leap date, the result is a NULL date (  /  /  ).  This bug with dates also makes date difference calculations dangerously inaccurate for long spans of time.  The increment/decrement functions remove this serious bug by correctly detecting the presence of a leap year and then returning the correctly incremented or decremented date.

The functions also maintain the currently configured format of the date in the returned data.  Some locations use date formats other than MM/DD/YY, and the functions will adapt.  They will also return the current date separator character (known as MARK, in the config.db file).  The routines will turn on the century parameter for internal use, remember what the current CENTURY setting is for the executing platform, and then reset the parameter what it is finished.  If the original data is passed to the program without CENTURY being used (YY as opposed to YYYY), the return value will truncate the years to the two right-most digits.

Both functions are year 2000 complient.  DBASE stores dates internally as MMDDYYYY, so dBASE is complient as well.  However, either by accident or design, some programs and databases are NOT complient.  Having incfield and decfield be so will remove one more worry for the future.

Here are some examples of date increment and decrement:
.set talk off
.public test1, test2
.test1 = {01/01/96}
.test2 = decField(test1)
.? test2
12/31/1996
.test1 = {2/28/96}
.test1 = incField(test1)
.? test1
02/29/1996
? incField(test1)
03/01/1996

Note that CENTURY is set ON on the platform on which Inc/Dec was developed, but that it was set OFF during part of the testing.

6.3 - Numeric Type Increments and Decrements

As you might expect, one of the most simple form of the numeric increment/decrement is an addition or subtraction operation, with the number as the first operator and "1" being the second operator.  Like the logical type, this could also be seen as somewhat redundant.  After all, the programmer could just as easily add or subtract one with a single statement.  

However, the routines can do much more than just this basic math.  With the addition of a second parameter to the function call, called a rule, the user can inform the routines as to the maximum numeric value of the data (a ceiling value), and a desired number of places to the right of the decimal point.  The function can also be instructed to increment or decrement by a value of other than "1".

But to make this a little more clear, lets look at the way that the rule parameter is structured and how the data parameter is treated:

* The rule is a character string, of no more than 18 characters.
* If a rule is not provided, the routines will supply a default rule of "XXXXXXXXXXXXXX"
* A rule is composed of the digits 0-9, an X, or a single decimal point (.).
* The input data is treated as a character string.
* The increment/decrement operation will be performed on the data parameter on a character by character basis, starting from the rightmost rule character and moving to the left.  The operation is complete when the leftmost rule character is considered.
* If the data parameter has less digits than the rule string has characters, the data will be padded with zeros to the right and not padded to the left.
* If the rule has less decimal places than the data parameter, the parameter's decimal places will be truncated.

Here is how an increment or decrement operation is carried out:

* An internal CARRY/BORROW flag will be set ON before the operation starts.
* If the current rule character is an X, the routine will add (subtract) the carry/borrow flag to the current digit.  Any result greater than 10 (less than 0) will turn the carry/borrow flag on for the next digit; otherwise the carry/borrow flag will be turned off.
* If the current rule character is a decimal point (.), the point will be transferred to the returning data and no increment/decrement operation will be performed.
* If the current rule character is in the range of 0-9, the carry/borrow flag will be turned off.  The character is added (subtracted) to the current digit.  If the result of the operation is greater than 10 (less than 0), the carry/borrow flag will be set on, and will be added (subtracted) into the next leftward digit.
* If the result of the leftmost increment/decrement is greater than 10 (less than 0), any overflow/underflow will be LOST.


Note that no provisions exist for negative numbers inside of a rule string aside from the results of an increment or decrement.  The data can be any value, negative or positive.

Now, for a few examples of how to use the functions to perform a numeric increment or decrement and the implications of using a rule.  First, let's see what will happen if a rule is NOT used:

Incoming data     Incrementing Result     Decrementing result
-------------     -------------------     -------------------
     66                   67                      65
     66.02                67                      65

Why do the routines drop the decimal point in the second example?  Remember than the routines will supply a default rule, which does not contain any decimal points.  According to the way that the rules operate, the incoming data will have its decimal points truncated.  This means that the second example above will lose its decimal places before the operation ever takes place.

Now, let's look at what happens when a rule is used.  Let's make it relatively simple, and then build on that.  Let's use the rule "XXX.XX" which means a maximum value of 999.99, with two places to the right of the decimal point.  

This rule will also have the effect of adding .01 to the number for each increment or decrement operation.  You ask yourself "why?"  Remember that the internal carry/borrow flag is set ON before the operation starts, and even if a zero is added from the rule (the X always means 0), the carry/borrow flag will also be added.

Incoming data     Rule      Incrementing Result     Decrementing result
-------------     ------    -------------------     -------------------
     66           XXX.XX           66.01                   65.99
     66.02        XXX.XX           66.03                   66.01

You must be aware of the carry/borrow flag and its effects on the operation if you want to have a successful call.  In the above example, the carry/borrow flag adds .01 to the final result, at the same time that the rule string adds 000.00.  Let's move on to a much more complex example of a rule, and see the influence of the carry/borrow flag.  Let's make the rule X5X.XX, which would appear to increment the incoming data by 50, and repeat the data from the examples above.


Incoming data     Rule      Incrementing Result     Decrementing result
-------------     ------    -------------------     -------------------
     66           X5X.XX          116.01                   15.99
     66.02        X5X.XX          116.03                   16.01

Now, you see the problem - you may have thought that the results for the first increment would be 116.00.  But don't forget that the carry/borrow flag is always ON at the start of an increment/decrement operation, and is explicitly added when the rule character is an X.  In order to correct for the flag's effects, you must either design the rule to prevent this from happening, or immediately follow up with a call to decField.  

The correct rule to increment or decrement by 50 is therefore not X5X.XX but 050.00.  The numeric characters in the rule will have the effect of disregarding the setting of the carry/borrow flag.  Also, keep an eye on the leftmost character of the rule.  If that character had been left as an "X," the carry/borrow flag would have been added/subtracted and the results would have been different.

This is also a good example of a more powerful rule than the ones presented before.  It defines the maximum size of the returned data and the number of decimal points (regardless of the size of the source field or variable), and provides for an increment or decrement of 50.


6.4 - Alphabetic Increments or Decrements

The most powerful feature of the increment/decrement functions is the ability to increment or decrement alphanumeric fields.  There are so many ways that we have found to use this feature that it is impossible to list them all.  With this feature you can increment or decrement a character or memo field, either including or excluding character groups by use of an alpha rule.

What is meant by "character groups?"  The increment/decrement functions operate over the ASCII range of 32 (space) to 126 (~).  These characters include numbers, specials, uppercase letters, lowercase letters and the space character.  This ASCII range has been split into these five types by the designers of the increment/decrement software, and placed into five separate groups.  These groups are very important to the correct design of an appropriate alphanumeric rule.

Unlike the numeric rule, the alpha rule does not define a maximum size of the field.  The size is already known because of dBASE's tendency to pad spaces to the right in a character or memo field.  But to increment/decrement functions, the size is not important.  What the alpha rule actually does is to define which character groups the programmer would like to include in the carry/borrow rollover or explicitly exclude from the increment/decrement operation.  These are also the names of the two kinds of group rules within the alpha rule: inclusive and exclusive.

But first, here is the structure of the alpha rule:

* The rule is a character string, of no more than 10 characters.
* The rule is composed of the characters A, a, !, 9, ~, or " " (space).
* The rule is composed of sub-rules that control the action of a particular character group.
* If no rule is presented to the functions, they will assume a default rule of "Aa9! " (include everything, exclude nothing).

* An inclusive sub-rule is composed of one only of the characters, A, a, !, 9, or " " (space).
* An exclusive sub-rule is composed of only one of the characters A, a, !, 9, or " " (space) preceded by the ~ character.
* An inclusive or exclusive rule is used only ONCE in an alpha rule.

Here is the operation of the alphanumeric increment/decrement:

* The data parameter is first preprocessed by trimming off any right-padded space characters.
* The increment/decrement operation begins at the rightmost character, and proceeds to the left one character at a time.
* At the start of the operation, a carry/borrow flag will be set ON.
* If the character is in an inclusive group, the character will be incremented/decremented according to the current setting of the carry/borrow flag.
* If the character is in an exclusive group, the character will be skipped, and the carry/borrow flag will be left alone.
* If the result of the operation results in overflowing from the current character group, the next ASCII character in the next higher/lower character group will be the result.
* If the result of the increment/decrement results in the character being higher/lower than the highest/lowest defined group, the carry/borrow flag will be set ON for the next character.

* If an increment/decrement operation results in a space character in the rightmost character position, the routines will jump to the next defined group.

Here are a few tips about using alpha rules and the alphanumeric increment/decrement:

The increment/decrement functions do not reset any ON ERROR DO vectors in your dBASE program, so if there is an error it will halt your program.  Generally speaking, the error will be an "UNKNOWN TYPE" error, and is caused by an unexpected group in your input data.

Unless you are sure that your data will never contain a character from one of the character groups, define all five groups in your rules.  If in doubt, play it safe.  Since the routines will note the ABSENCE of a group definition along with the PRESENCE of group definitions, the effort costs you nothing in processing time and may result in fewer errors.

During the call, the routines preprocess the string by trimming off any right-padded spaces.  This is because dBASE pads spaces to the right in a character field, and it was felt that these extra spaces were undesired whitespace.  Be prepared for the effects of this policy on your data.  See the discussion below regarding losing string length.

Memo fields are handled the same as character fields, but are limited to only 254 characters at a time within the routines.  You can make successive calls to the routines using the substr() function.

It is a matter of style, but try to define all of your inclusive rules at the start of the alpha rule, and your exclusive rules next.  This will follow the examples used in this manual.

Now, lets see some examples of how to use the character increment/decrement features.  First, Let's see what happens with a well known string and no passed rules:

Incoming data     Incrementing Result     Decrementing result
-------------     -------------------     -------------------
Hello, World!        Hello, World"        Hello, World~

When this data is passed to the functions, they will assume that you mean to include everything, because of the default rule of "Aa9! ".  The results of the increment are expected, but you may be a little confused by the decrement.  If you look at an ASCII chart, you will see that the ! character is ASCII 33, and that the character below that is a space (ASCII 32).  In order to avoid losing length from the right of the data string when the alpha string is pre-processed, it was decided that inc/dec would NEVER increment or decrement to a space in the rightmost character position.  This is something that you will have to adjust for.

Now, lets move on to the effects of a single exclusive rule.  At the same time, we will have to define inclusive rules for the example data.  Using the data above, let's exclude special characters from the operation.  Let's also make the rule to include uppercase letters, lowercase letters and spaces.  Now the rule will look like this: "Aa ~!"

Incoming data     Rule      Incrementing Result     Decrementing result
-------------     ------    -------------------     -------------------
Hello, World!     Aa ~!     Hello, Worle!           Hello, Worlc!

As you can see, the functions have ignored the ! at the end of the phrase.  Now, let's change the rule a little bit to see what would happen if we also excluded lower case letters:

Incoming data     Rule      Incrementing Result     Decrementing result
-------------     ------    -------------------     -------------------
Hello, World!     A ~a~!    Hello, Xorld!           Hello, Vorld!

As you can see, both routines have skipped over the ! mark and the four lower case letters until they encounter the only characters they had been instructed to notice, which is upper case.

In the real world, you can never be sure that your typist will not make a mistake and enter an incorrect character (a "typo") into a data field.  Therefore, the above example is incomplete.  A more appropriate alphanumeric rule would define all five groups, and would look like "A ~a~!~9" and would mean to include upper case letters and spaces in the carry operation, and exclude lowercase letters, specials, and numbers.

7 - Case Study

Let's look at an example of real-world data, a case study if you will, and see some of the possibilities in using inc/dec.  We will assume that we have a simple database that tracks information regarding court cases.  The database has fields for the date, the case number and a brief description of the case (plaintiff name vs. defendant name).  What we want to do is to apply inc/dec as much as possible to make data entry easier and faster.  Let's start by looking at the fields that can actually benefit by using inc/dec.

In our legal system, every case is referred to by a unique docket or action number.  A typical case number in Civil or Superior court might look like this: 96CV-05966.  This means Civil Venue (the Court with jurisdiction), year 1996, case number 05966.  As you examine this case number, you immediately see that there are characters that we don't want to increment or decrement.  

The "96" is the year, and that won't change more than once per year.  If we decide to include numeric characters, the year characters would eventually be incremented or decremented, even if only by accident.  But, by its position at the extreme left of the field, the year will be very unlikely to be changed by an inc/dec operation.  We do want to be able to increment and decrement the last five characters of the field, which are also numerics.  

From a data entry standpoint, for every record we would have to enter 10 characters into this field.  However, courts generally record the day's docket sorted by the case number, in ascending order.  This field is an excellent candidate for incField and a special rule.  Remember that the programmer can write his program to recognize a special key for invoking incField, and compare the advantage of having one keypress replaced 10 keypresses. 

The date field is also a good candidate for increment/decrement operations.  If the data entry operator enters cases a month at a time, then there will be many times when the date will have to be re-entered as new data.  Note that both the case number field and the date field are good candidates for SET CARRY ON.

The last field, the description, is not a good candidate for an increment or decrement operation.  This is because the data is too changeable from case to case.

Now, let's build the rules for the two fields.  A date field does not require any rules, and even if the programmer passes a rule parameter, the routines will ignore it.  So, let's look at the case number field and see what rule we need.  The CV is something that we will not want the function to change but to enter manually for every court or venue.  Both of these characters are in upper case, so we would write an exclusive rule for uppers.  This will be "~A".  Next, the "-" character will also never change, so we want to write an exclusive rule for specials.  This is "~!".  

Lastly, we want to make sure numbers are changed, so we write the inclusive rule for numbers, which is "9".  One note about the numbers: even though the year is also numbers, and will EVENTUALLY be incremented, the position of the year to the left of the field guarantees that the two-digit year will change last.  It is very unlikely that these numbers will ever change during the course of normal data entry operations.

Let's not forget that data entry operators sometimes makes mistakes, and might enter typos.  We can define the other two groups to be exclusive: "~ ~a", which means "exclude lower case letters and spaces."  Now the whole rule for the case number becomes "9~a~A~!~ " which means include numbers, and exclude specials, upper and lower case letters and spaces from the operation.

The next step is to write the dBASE code that will perform the operation.  It looks like this:

for the date: date = incField(date)

and for the case number: casenum = incField(caseNum, "9~a~A~!~ ").

The programmer will also have to account for determining which field is being edited, and making sure that the program is sensitive to the keys that are being used to invoke the incField function.  A good way to do this is to use the ROW() and COL() functions provide by dBASE, and to use the ON KEY [label] command to redirect keys.  Note also that the programmer should include calls and key sensitivity for decField, just in case the operator changes her mind and wants to decrement.

Generated from the dBASE conrol center, here is an example of a form that has had some code added to it:

*---------------------------------------------------------------------
* Name.......: COURTS.FMT
* Date.......: 10-27-96
* Version....: dBASE IV, Format 2.0
* Notes......: Format files use "" as delimiters!
*---------------------------------------------------------------------

*-- Format file initialization code --------------------------------------

*-- Some of these PRIVATE variables are created based on CodeGen and may not 
*-- be used by your particular .fmt file
PRIVATE ll_talk, ll_cursor, lc_display, lc_status, ll_carry, lc_proc

IF SET("TALK") = "ON"
  SET TALK OFF
  ll_talk = .T.
ELSE
  ll_talk = .F.
ENDIF
ll_cursor = SET("CURSOR") = "ON"
SET CURSOR ON
lc_display = SET("DISPLAY")
lc_status = SET("STATUS")
*-- SET STATUS was OFF when you went into the Forms Designer.
IF lc_status = "ON"
   SET STATUS OFF
ENDIF


ll_carry = SET("CARRY") = "ON"
SET CARRY ON
*-- Fields to carry forward during APPEND.
SET CARRY TO                            && Clear previous SET CARRY TO list
SET CARRY TO Date,Casenum ADDITIVE

*-- Added code
on key label ALT-I do incit
on key label ALT-D do decit

*-- @ SAY GETS Processing. -----------------------------------------------

*--  Format Page: 1
@ 1,0 SAY "Court Data Input Form" 
@ 4,0 SAY "Date " 
@ 5,4 GET Date 
@ 7,0 SAY "Case Number" 
@ 8,4 GET Casenum PICTURE "XXXXXXXXXX" 
@ 10,0 SAY "Description" 
@ 11,3 GET Descriptio PICTURE ;
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 
*-- Format file exit code ------------------------------------------------

*-- SET STATUS was OFF when you went into the Forms Designer.
IF lc_status = "ON"  && Entered form with status on
   SET STATUS ON     && Turn STATUS "ON" on the way out
ENDIF
IF .NOT. ll_carry
  SET CARRY OFF
ENDIF
IF .NOT. ll_cursor
  SET CURSOR OFF
ENDIF

IF SET( "DISPLAY" ) <> lc_display
  SET DISPLAY TO &lc_display.      && Reset Screen size if changed
ENDIF


RELEASE ll_carry,lc_fields,lc_status
IF TYPE( "ll_echo" ) = "L"
  IF ll_echo
    SET ECHO ON
  ENDIF
ENDIF
IF ll_talk
  SET TALK ON
ENDIF
*-- EOP: COURTS.FMT


*-- added code
*-- incit - increment a field according to the row number
procedure incit

do case
	case row() = 5
		date = incFIeld(date)

	case row() = 8
		casenum = incField(casenum, "9~A~a~!~ ")

	otherwise
		@ 0,0 say chr(7)  &&  beep
enecase

return

*-- decit - decrement a field according to the row number
procedure decit

do case
	case row() = 5
		date = decField(date)

	case row() = 8
		casenum = decField(caseNum, "9~A~a~!~ ")

	otherwise
		@ 0,0 say chr(7)

endcase

return


This dBASE IV program will respond to the ALT-I and ALT-D keys for increment and decrement.  As you can see, the program will respond to the keys and then invoke the desired function.  Don't worry about incField and decField trimming any of the spaces in the return value; when the data is written to the database, dBASE will automatically pad right with spaces.

The code above is intended for illustration purposes only.  For a working version of this code, try using the iddemo.prg program.  Or try out your own ideas!

8 - Future Plans

Any function can be improved, and these two are no exception.  I do plan to add some enhancements in the future, and will try to port incField and decField to other languages, including Clipper, FoxPro, Visual dBASE, Paradox, Basic, C, and Pascal.

It would be much appreciated if you were to let us know of any enhancements you would like to see, or if you have any suggestions or comments.  We never intended this code to be static or written and then just abandoned, as many other companies have done over the years.  This code was written to make life easier at our site, and we can't tell what will make life easier for you.  Any real-world experience that you can add will eventually allow us to enhance our product.  You can reach us by the e-mail addresses above or by snail mail.

9 - The Demo Program - iddemo.prg

In the original downloaded demonstration version of incField and decField, a small demonstration program was included.  This program was intended to show how to write code to support the two new functions.  The name of this code is iddemo.prg, and it was based on the form generated above in section 8.

To use the program, switch to the directory containing the .prg file and start dbase.  We have included a config.db file, which is what we use on our development platform.  The programmer who wrote the subroutines always likes to fiddle around a little bit, so if the settings in config.db don't suit you, you can always change them yourself.

From the dot prompt (our config.db says READY>) type in "do iddemo"  The program will start running and display its main screen and then enter a loop waiting for you to press a key.  The program uses a series of GETS to enter the data, and the keys ALT-I, ALT-D and ALT-X have been redirected.  The ALT-I will cause the current data to be incremented and pressing the ALT-D key will decrement the data.

In keeping with the example from Section 8, the increment or decrement functions will only work in the date field and the case number field.  If you try to press the ALT-I or ALT-D keys on the description field, the program will beep at you.  The date field will be manipulated as a date, and the case number field will change as a string.  The increment and decrement functions will automatically pick up the data field's type (date and character), and perform the correct type of operation.

To leave the demonstration program, press ALT-X.  Note that the demonstration versions of incField and decField will only work 100 times before refusing to do anything more than returning the original data.  If you have the full versions of the routines, this restriction will not be present.

If you wish, you may print out the iddemo program.

10 - Mail-in Order Form

To make ordering easier for you, we have included this easy-to-use Mail-In Order Form.  Please cut the page at the divider or make a photocopy and send the form to one of the following addresses:

Homegrown Data Systems
344 Brockinton Drive
Saint Simons Island, GA  31522

or 

Fax "1" of the Golden Isles
237 Sand Castle Road
St. Simons Island, GA  31522

We will accept cash, but sending cash through the mail can be dangerous.  We suggest that you use either a check or a money order.  Make payment to Meschke Development.


______________________________________________________________________________

Yes!  I would like to order the dBASE IV version of the Inc/Dec routines!

Enclosed you will find payment of $14.95 by either check or money order made out to Meschke Development, plus Shipping and Handling fees.

Please send the software to:

Name      _________________________________________________

Address   _________________________________________________

          _________________________________________________

City      ___________________  State _____  Zip  __________

Country   _________________________________________________


VIA       USPS        ($2.00 S/H)

          UPS         ($4.00 S/H)

          FedEX       ($4.00 S/H) 

          Other      _____________________  ($6.00 S/H)

          e-mail to  ______________________________________ (Free Shipping)


FORMAT    ZIP   ARC   ARJ   LZH   ZOO   None   Other  _____________________

______________________________________________________________________________


