FEATURE APPLICATION
Customer List Manager
Much more than a phonebook
By Thomas Andrews
Keep your important lists up-to-date with this powerful but user-friendly BASIC telephone/mailing list database. Works on 8-bit Atari computers with at least 48K memory, disk drive and a printer.
My family operates a retail vegetable business on our farm in central New York. We have a series of lists of customers who make quantity purchases each year and wish to be informed when certain seasonal products become available.
When we call these customers we want to have some information at hand concerning each one's preferences and a history of recent orders to aid them in making this year's purchases. Customer List Manager lets us find this information with ease. It's much better than the method we used before our Atari 800 arrived--a spiral notebook.
Customer List Manager is a telephone/mailing list/database program. Each record contains a customer's name, phone number and address, along with the type of product they want, some notes on personal preferences and a five year history of past orders. Each list has a title and year attached to identify it.
The list can be displayed on the screen, printed on most 80-column printers, or output to a word processor file. Entries can be edited or deleted, and histories updated, in one easy operation, thanks to the program's sorting and selecting routines.
The records in each list (referred to as "items" within the program) can be sorted on one or two levels. Subgroups of list records can be selected for processing under a search routine which allows use of a wildcard character in the search sequence. In case of disaster, the list can be reconstructed from the last editing operation or from the word processor file. All this--and it can be customized to better suit your own needs as well.
GETTING STARTED
Type in Listing 1, MANAGER.BAS, and check it with TYPO II. Be sure to SAVE a copy before you RUN it. If you have trouble typing the special Atari characters in lines 50, 60, 65, 85, and 86, don't type them. Listing 2 will create these lines for you. Type in Listing 2, check it with TYPO II, and SAVE a copy.
When you RUN Listing 2 it will create a file containing these hard-to-type lines called LINES.LST. Merge this file into Listing 1 by typing LOAD "D:MANAGER.BAS" and then ENTER "D:LINES.LST". Be sure to SAVE the final version of the file.
If you have the Antic Monthly Disk, you should copy MANAGER.BAS to another disk before you try to use it, since the program needs to be able to write files to disk. You can either copy the file from DOS using command C or O, or LOAD and SAVE the file from BASIC. Make sure the disk to which you copy MANAGER.BAS also contains DOS.
The program is menu driven and most operations are self-explanatory. When you first RUN the program the main menu will appear. If no list has been loaded, only options A (Start New List), C (Load List From Disk), and H (Change List Title) will operate.
Note that the [BREAK] key is NOT disabled. To return to the main menu after an accidental BREAK, type GOTO 100. Records in memory should remain intact!
CUSTOMIZING LISTS
Customer List Manager uses a variable length field and record system to lower wasted memory space. Provisions have been made to limit the total list size to 19,000 characters and/or 100 records. This size allows the program and storage area to fit in a 48K Atari with standard DOS 2.5 configuration with about 1K bytes left over.
To change the maximum list length, change the value assigned to MAX in line 40. To change the maximum number of records, change the value of HUN in the same line. Remember that each record allowed uses seven bytes of bookkeeping overhead.
Each record has ten fields. The first five are labeled NAME, PHONE, ADDR., TYPE, and NOTES. These labels can be changed in line 90 by changing FNAME$. Be sure to use no more than five characters, padded with spaces if shorter, and separate each label with a colon.
The last five fields contain the history of the last five years and the labels for these fields are determined by the year of the list. The maximum length L of any field is 60 and the minimum is 1. Anything outside these limits will be either cut off or padded with a space.
Both upper and lower case characters are allowed in the list. Inverse characters are not allowed and will be changed to normal if they are used.
Menu selections D, E, and G (editing, saving, and printing) allow the operation to be performed on only, part of the items on the list. Items are flagged for processing through the use of a search routine that uses the question mark (?) as a wildcard character.
As an example, a search of phone numbers using the sequence 5?5 will flag all items with two files separated by any other character in the phone number field. Use all capital letters in the search sequence, and Customer List Manager will search for both upper and lower case.
To change the wildcard character, change the question mark in the machine language routine SRCH in line e 60 to any character you wish. Keep in mind that the character used as a wildcard cannot be used as a regular character. DON'T change anything else in line 60 as this could cause your computer to lock up. Also change the screen prompt in line 15060 as a reminder that a different wildcard is in effect.
EDITING
The editing option is quite simple. There are three editing modesÑedit and update, edit only, and update only. Update means that the list year is incremented by 1, the oldest year of history is dropped, the remaining history is shifted, and a new year is added to the end of each record.
The update-only mode is completely automatic and all list items will be updated. A space is inserted for the new history year field as the new list is written to a special edit flle on the disk. After the entire list has been updated, the old list will be cleared from memory and the new list is input from the edit file.
The Edit and Update mode allows you to enter information for the newly-added year. You can also change the contents of any of the fields, or you can delete a whole item (or record) from the list. You must go through all of the items on the list in this mode. To edit, move the cursor to the desired line and change it to read as you like.
Because of the way the List Manager reads the list item from the screen, the INSERT and DELETE functions are disabled during editing, as is the clear screen command. When you have finished editing an item press [CONTROL] [A]. The item is read from the screen and placed in the edit file while Customer List Manager goes on to the next item.
To delete an item press [CONTROL] [D]. The item will not be sent to the edit file. (A Last-chance "Are you sure?" question is asked before deletion is done.) If an item gets so messed up during editing that it would be easier to start over, press [ESC].
The edit-only mode allows the selection of part of the entries for processing. A menu comes up, letting you choose how much of your file you want to edit. If you decide to just edit some of the items (option B), you will be asked which field you want to use for the selection. Enter one, and you will then be prompted for the search sequence to use for a match. Remember, the ? character is the wild card that matches any other character.
If you want to leave edit-only mode without editing all the items flagged for processing, press [CONTROL] [M]. The rest of the flagged items will be moved to the edit file on disk, with no changes. The program will load the new list from the disk, ready for any further operations.
In all modes, once the editing operation is done, the edit file is left on the disk as a backup file that can be recovered using main menu option I. Each time a list is edited the old edit file is replaced with a new one.
List sorting can be done on any two fields. The primary field is selected first, followed by the secondary. To sort on only one field, use the same one for both primary and secondary. The sort routine is completely automatic once started.
PRINTING
The print option assumes a generic, no frills, 80-column printer using continuous paper. Therefore, it ought to work on just about any printer you would connect to your Atari. It is not necessary to print the entire list if you only need part of the pages. Customer List Manager will print any individual page or group of pages, and as with editing, you may select to print only those records which contain a specified string in the chosen field.
If your printer has capabilities beyond the minimum supported here (and most do) you might wish to write a new printer routine to take advantage of them. But if you don't want to do this, the program will print a list to a disk file that most word processors should be able to use. You can then use your word processor to add any special touches you want before you print out.
Customer List Manager has the ability to reconstruct a list from the word processor file (without the formatting commands or any other changes), providing a second emergency backup system. Use menu option I.
You can't merge two lists with Customer List Manager, but you can merge files using your word processor. Load the two list files into the word processor one after the other. (Do not mix Customer List Manager word processor files with files saved with menu option E. They use a different format.)
Remove the list title and year from the second list and save the completed list on your disk. Load the combined list into Customer List Mariager using menu option I. If the combined list is longer than the maximum allowed, the program will load as many records as will fit, then stop.
It has been my experience that most practical application programs cannot precisely fit the needs of all users, and databases are no exception. That is why there are so many database programs out thereÑeach user has different requirements.
Beyond changing field names and memory limits as discussed above, further changes would require more extensive rewriting of the program code. I have tried to program in a fairly modular, structured form to make this easier to do. If Customer List Manager does not suit your needs, study the listing and the instructions below, so you can adapt the database the way you want it.
ABOUT THE PROGRAM
At the heart of Customer List Manager lies FIND, a machine language routine by Scott Sheck published in the December, 1984 Antic. The article, "Word Storage Space Saver," detailed an efficient method for storing strings of varying lengths.
As presented, FIND required that the strings be stored sequentially, unpadded with spaces, with the first character of each changed to inverse as a delimiter. The routine also required that an inverse character be appended to the end of the last field. Each string could be no longer than 255 characters.
FIND started at the beginning of a string and counted inverse characters until the desired field was encountered. FIND then determined the string position of the start and the length of the field.
This sequential access would be fine for most text adventures since FIND is quite fast. However, in the case of search or sort operation where 100 or more calls to this routine are possible, or even likely, processing time mounts up quickly.
I added an index to the main storage area to provide pseudo-random access. The string position of the first character of each record is placed in a numerical array called LI. Now, if I want to examine the fifth field of record number 42, I use the contents of LI(42) as a starting point and go five fields from there. This provides very fast accessÑnearly as fast as if I had used fixed-length fields and calculated the positionÑand is much less wasteful of RAM.
Since the FIND routine uses inverse characters as delimiters, it follows that inverse characters cannot be allowed in the middle of a field. This necessitates a routine that does a character by character check of the input field, changing the frst character to inverse and the rest of the characters to normal.
Since a BASIC routine to do this would be quite slow, I wrote the machine language routine CHNGR to do it more quickly. The call for CHNGR is:
DMY= USR(CHNGR,ADR(FIELD$),LEN(FIELD$))
CHNGR is the address of the routine in memory that operates on the string FIELD$. The USR routine SRCH will examine any block of memory for an occurrence of a specified sequence of characters. The sequence may contain any combination of letters, numbers, and punctuation. Capital letters (normal video) are checked as both upper and lower case. All other characters are examined only in the case and video type actually specified. The call for SRCH is:
X = USR(SRCH,ADR(SEQ$),LEN(SEQ$),ADR(AREA$),LEN(AREA$))
SRCH is the address of the routine that attempts to find SEQ$ in string AREAS. A one is returned in X if the sequence is found anywhere in the search area, and a zero if the search was unsuccessful. The length of the sequence may vary from 1 to 255 characters. The search area can be any length from 1K to 64K.
SORT ROUTINE
The sort routine uses an insertion sort on two levels. For those unfamiliar with the insertion sort, consider a file drawer that needs sorting. You start on either end and thumb through the folders one at a time until you fnd one that is out of the proper sequence. You then check back through the folders you have just done until you find the proper position for the misplaced one.
Then, you shift the folders to make room and insert the one in question in the right spot and go back to where you left off. When you reach the end, the sort is done. This type of sort, while certainly not the fastest type available, has the advantage of being very fast if most of the items are already in order, as is usually the case with Customer List Manager. It is also nearly as easy to program in BASIC as the bubble sort and is usually faster.
It is important to note that I do not actually move the text of the list around during the sortÑI change the order of the pointers to that text. The reason for this is simple: When I move a pointer, I only have to move six bytes. Since the size of each record (item) in a list can vary anywhere from 10 to 600 bytes, not only would I have to move more bytes, but I would have to determine the length of the record I have to move each time. It is easy to see which way is better.
The usual method used during an insertion sort with a numerical array is to shift the array elements one at a time as you are checking for proper position. In this sort, I wait until I have found the proper position and shift the elements in a block using a machine language block memory mover, SHIFT.
This routine is a little different than the usual block mover in that it is bilateral. Most routines, including the string functions of Atari BASIC, will not work for moving in both directions when the source and destination blocks overlap. SHIFT checks for the direction of the move and starts at the correct end of the block to properly shift it in that direction. The call for SHIFT is as follows:
DMY= USR(SHIFT,HERE,THERE,LENGTH)
SHIFT is the address of the routine, HERE is the address of the first byte of the source, THERE is the address of the first byte of the destination and LENGTH is the number of bytes to move.
To determine the address of the numerical array, DIMensioned a string just before it, determined the address of that string with the ADR function, and added the DIMensioned length of the string to it. Each element of the array takes six bytes. (Remember that the first element of the array has a subscript of 0.) Since I do not use LI(0) in CLM, I added six more bytes to the base address for LI.
Thomas Andrews has a degree in electrical engineering. He found his Atari 800, some software and 12 issues of Antlc at a garage sale in 1985.
Listing: MANAGER.BAS Download