home *** CD-ROM | disk | FTP | other *** search
- FILENAME: MAILLIST.DOC, 09/17/77 by Ward Christensen
- ------------------------------------------------------------
- DOCUMENTATION FILE FOR THE COMPUTER CLUB
- MAILING LIST PROGRAMS WRITTEN IN BASIC-E.
- -------------------------------------------------------
- THESE PROGRAMS ARE BEING PROVIDED THROUGH THE COURTESY OF THE
- AUTHOR FOR THE SOLE USE OF HOBBYIST COMPUTER CLUBS IN
- MAINTAINING THEIR MAILING LISTS.
- ------------------------------------------------------
-
- The needs of a computer club in maintaining a mailing
- list consist of the following requirements:
-
- 1) A file of names with sufficient information
- about each member.
- 2) A maintenance program to add, change, and delete
- records.
- 3) A sort program to change the order of the file (by
- last name, zip, etc.) for report purposes.
- 4) A program to print:
- Alphabetic master listings
- Mailing labels (usually in Zip sequence)
- Name tags for meeting use.
-
- The programs on this disk fulfill these needs.
-
- 1) PREFMT.BAS preformats the required size file
- 2) MAINT.BAS maintains the mailing list
- 3) SORT.ASM sorts the file, producing an index file
- 4) REPORT.BAS prints listings labels and name tags.
- ------------------------------------------------------------
- As currently implemented, the file consists of 512, 128
- byte (1 sector) records. It was originally thought that
- 1 sector records would be required because of the sort
- program written in assembler. However, the sort program
- was eventually written to be independent of file length.
- Note that 128 is still a very good value, because of
- the efficiency of BASIC/E only having to
- read 1 sector per record. If the record length was
- say, 150 bytes, then 2 sectors would always have to
- be read. Also, random writing would have to read
- modify, and write sectors because of the sector overlap.
-
-
- For speed of access during maintenance, the file is
- written using a randomizing or hashing technique on the
- person's name. The algorithm is as follows: A variable
- is initialized to 0. Then, every other letter in the person's
- name (1, 3, 5 ... n) is, one at a time, added into the
- variable. The variable is doubled between each addition.
- Then, the result is divided by the number of records in
- the file, and the remainder is used as a record number.
- When adding, if the record is already in use, the file is
- sequentially read from that point until an open record is
- found. When retrieving, the record randomized to is read,
- and the name is matched. If it is not the right name,
- the file is read sequentially until the a record with
- a matching name is found. You may press 'DEL' (or rubout)
- to stop the scan in case, for instance, you misspelled the
- name. Note that the technique is simple, and is not for-
- giving of misspelled names.
-
- The algorithm, in BASIC this is:
- KEY=0
- FOR I=1 TO LEN(KEY$) STEP 2
- KEY = 2*KEY + ASC(MID$(KEY$,I,1))
- NEXT I
- KEY = KEY- FILE.SIZE*INT(KEY/FILE.SIZE)
- IF KEY = 0 THEN KEY = 1
- ------------------------------------------------------------
- The file currently has the following fields in the record:
-
- SORT: A 4 byte field on which the file is sorted, to
- be in alpha sequence. This means that you do
- not store the file as 'lastname,firstname'
- which is very 'computeristic' and 'impersonal'.
- instead, you key in the name in it's natural
- form, then use the 4 byte SORT field
- for sorting. For example, if the name is
- James R. Smith, then the sort field would be
- keyed in as SMIT.
-
- NAME: The person's 'natural' name, i.e. first name first.
- Remember BASIC won't allow commas,
- so don't key in J. SMITH, JR. but rather
- J. SMITH JR.
-
- ORGANIZATION: This field is normally blank, but is provided
- when a 4-line address is required. When
- adding a person, BASIC/E will not accept
- a totally blank input, so 1 blank must be keyed
- when ORGANIZATION is not present.
-
- STREET: The street address
-
- CITY: The city AND state. Since BASIC will not
- allow a comma in an input line, simply use
- a space after the city, such as:
- CHICAGO IL
- I originally considered putting STATE as a
- separate field, but BASIC/E files use quotes
- around each field, and separate fields by
- commas. Thereore, a 2 byte state field would
- take 5 bytes. There just wasn't sufficient
- room in a 128 byte record. (Although recall
- that I now realize the record length does not
- have to be restricted to 128 bytes.
-
- ZIP: 5 byte numeric zip code
-
- PHONE: 10 digits, with parenthesis, spaces, and dash, as:
- (312) 555-1212
-
- COMPUTER: A 5 byte field used to keep track of the
- computer owned, such as A8800, IMSAI, DGZ80, etc.
-
- PAID: A 2 byte field showing when membership is again due,
- in the form YYMM such as 7809
-
- TYPE: A 1 byte 'type of member' field. Currently used:
- G Group (another computer club)
- M Magazine
- H Hobbyist
- V Vendor
-
- These are arbitrary values, however the REPORT
- program, when printing name tags for a meeting,
- will not print tags for type G or type M.
-
- --------------------PREFORMAT PROGRAM--------------------
-
- This program preformats the file. It writes records
- with a '0' flag byte, i.e. empty records. From then
- on, the Maint program is used to add, change, and delete
- members of the file.
-
- ------------------MAINTENANCE PROGRAM--------------------
-
- This program maintains the file. It has the following
- commands implemented to do so:
-
- MACRO: Allows issuing a string of up to 10
- commands, over and over. Useful for
- doing such things as scanning the
- file for a certain field
- value, then changing the value,
- and doing it over and over.
- FORMAT: MACRO
- You will be prompted for input.
- When running in MACRO mode, a DEL
- from the keyboard will stop execution
-
- HELP: Prints a summary of the commands
- available.
-
- FIND: This is the ONLY command which
- accesses the file thru the randomizing routine.
- FORMAT: FIND name where name is the
- exactly spelled name of a person in the file.
- EXAMPLE: FIND WARD CHRISTENSEN
- The name is arithmetically hashed to a record
- number. The file is scanned from that record
- number forward (wraps from end to beginning)
- until a matching name is found. You can press
- DEL at any time to stop the scan and return
- to command mode.
-
- READ: This command is used to read a particular
- record in the file by record number. It is
- not frequently needed.
- FORMAT: READ recno
- EXAMPLE: READ 20
-
- DUMP: This command sequentially dumps the file
- from a given starting record number.
- Press DEL to stop the dumping.
- FORMAT: DUMP recno
- EXAMPLE: DUMP 155
-
- C: This command is used to change the contents
- of a field in the record most recently read
- into memory. It can change an entire field
- by replacing it with a new value, or can do
- a character string replacement such as to correct
- a misspelled field value.
- FORMAT: C fieldname newvalue
- EXAMPLE: C NAME J. SMITH
- The field name can be abbreviated. The
- table of field names in the program will
- be searched until the first 'n' letters
- of a name match the 'n' letters in the field name
- used in the C command. N is therefore a sufficient
- abbreviation for NAME, but C will find CITY
- and not COMPUTER, so use CO for COMPUTER.
-
- FORMAT: C fieldname /oldvalue/newvalue/
- EXAMPLE: C N /TIANSON/TENSEN/
- The above example would change WARD CHRISTIANSON
- to WARD CHRISTENSEN. The closing '/' is
- optional.
-
- LIST: Used to list the contents of the record
- most recently read into memory.
- FORMAT: LIST
-
- ?: This command is used to scan the disk
- from the current position (the last record
- number read) for any field matching a value
- placed in the command. Only the first 'n'
- characters of the field on disk are matched,
- where 'n' is the number of characters given
- in the command. The match always starts
- with the leftmost byte of the field.
- FORMAT: ? fieldname value
- EXAMPLE: ? CO ALTAIR
- The contents of each field read will be
- displayed whether or not it matches.
- Use DEL to stop the scan.
-
- F: This command (Find) works like C
- except that the field read from disk is scanned
- for a match at each position in the field, not
- just the first. For example, if everyone
- in the club having a Z-80 computer has
- a 'Z' somewhere in their COMPUTER field,
- but it differs from user to user (such as DGZ80,
- IMSZ8, Z2, etc.) then you could find
- someone with a Z80 by saying:
- F CO Z
- FORMAT: F fieldname charstring
- EXAMPLE: F STATE IL
- NOTE this runs 'lots' slower than '?' because
- of multiple comparisons being done on each
- field.
-
- WRITE: This command is used to randomize and write
- a record to disk. It is used after the ADD
- command, or when changing someones name.
- See "CHANGING A NAME" below.
- FORMAT: WRITE
-
- ADD: This command is used to add a new name
- to the file. You will be prompted for each
- field. If a field is blank, you cannot just
- press C/R because BASIC/E will give you a
- WARNING II message. Therefore, put in 1 space
- the press return.
-
- If you want to stop the ADD function, such as
- if you realize you made a mistake and don't
- want to go back and change it with the C function,
- type QUIT in response to any input.
- FORMAT: ADD
- You will be prompted for the input.
- NOTE the record is only built in a matrix
- in memory, and that the WRITE function must be
- executed to actually write the name to disk.
- This allows using the C and LIST command to
- verify and change the contents of the record
- before writing it to disk.
- Also, see "CHANGING A NAME" below.
-
- There is one problem when adding records to
- the file, and that is that you cannot add a record
- which exceeds the record length. BASIC/E will
- unforgivingly issue an ER error and drop you
- back into CP/M. Due to the preallocation of the file,
- however, this is not serious as only the record
- currently being added is lost. A 'lot' of
- code could be added to add up the lengths of each
- field, plus 1 for the flag, plus 3 for each field
- (the quotes around the value, plus the comma separating
- values) but I just decided not to bother.
-
- ERASE: This command will erase the record most
- recently read. The record will still remain in memory
- such that a WRITE command could be used to write
- it back to disk, as would be required with a name
- change.
- FORMAT: ERASE
-
- UPDATE: This command writes a record BACK to disk, and
- is used following a FIND or READ command. Npote
- that if used after an ADD command, you will overlay
- the wrong record. You must use WRITE after ADD.
- FORMAT: UPDATE
-
- FREE: Used to determine how much memory is left
- during the running of the MAINT program. Used
- during program development to see if room remained
- to add more function
-
- PURGE: Used to purge the file of records whose memberships
- have expired. The file is scanned for a matching
- date (PAID field) as given in the command, and
- all records matching are deleted. It is suggested
- the printer be turned on before issuing the PURGE
- command to keep an 'audit trail' of who was purged.
- FORMAT: PURGE yymm
- EXAMPLE: PURGE 7709
-
- END: Used to end execution. Control-C can also
- be used, as the file doesn't have to be closed,
- because it is pre-allocated.
-
- CHANGING A NAME: Since the file is written by randomizing
- the name field, you cannot simply FIND someone, use C
- to change their name, and UPDATE the record. Why?
- Next time you want to find them, you will type
- FIND newname and will randomize to it. However,
- the name is stored under the randomizing of the
- OLD name. Therefore, after changing a name,
- issue an ERASE to get rid of the old record, then
- WRITE to re-randomize the new name and write the
- record. This works because ERASE doesn't change
- the contents of the record maintained in the
- matrix in memory.
- --------------------SORT PROGRAM--------------------
-
- The sort program is an assembler program which reads the
- mailing list, extracting the first 5 characters of a
- specified field, and doing a memory-resident bubble sort
- of the field and it's correspoiding record number.
- It then writes an ASCII file of just the record numbers.
- It is currently set up for 3 byte record numbers,
- but may be easily changed for 4 byte record numbers.
- (Comments in SORT.ASM show how). The file of record
- numbers is then used in the REPORT program to process the
- file in the sequence asked for. The index file is read
- into a table rather than accessed sequentially, for speed.
-
- FORMAT: SORT infilename outfilename fieldnumber
- EXAMPLE: SORT CACHE.FIL NAME 1
-
- Note that 'outfilename' can be any valid
- CP/M file name.
-
- The field numbers currently implemented are as
- follows:
-
- 1. SORT
- 2. NAME
- 3. ORGANIZATION
- 4. STREET
- 5. CITY
- 6. ZIP
- 7. PHONE
- 8. COMPUTER
- 9. PAID
- 10. TYPE
-
- --------------------REPORT PROGRAM--------------------
-
- The report program is used to produce listings,
- mailing labels, and name tags. The listings can
- be either 130 columns wide, or can be printed with 2
- lines for each person, on 8.5 wide paper. Name tags
- and Labels may be printed 3-up or 4-up, with variable
- width and height labels. It is currently written for a
- Centronics 101 with the feature of expanding the width
- of characters when you print CHR$(14). If you do
- not have this facility, the program will have to
- be changed. Note this affects only the printing of name
- tags (which print the name and computer double width)
- and the title of the report. Also the program prints CHR$(11)
- (Vertical Tab) to eject the paper to a new page. If you
- do not have this feature, you will have to insert the proper
- number of null print statements to cause an eject to the
- next page. Some printers may require CHR$(12)
- (Forms Feed) instead.
-
- Since there is not currently a way to turn on the
- printer from BASIC/E, this program requires a CBIOS
- with manual printer control, such as thru a sense switch,
- to operate correctly. The program prompts you with
- 'press linefeed' which then allows you time to
- turn on the sense switch. When it sees the linefeed on
- the keyboard port, it starts the listing.
- When the listing is complete, it awaits a 'del'
- from the keyboard before continuing. This again gives
- you time to turn off the sense switch controlling the
- printer.
-
- The commands currently implemented in the program are:
-
- HELP: Prints a summary of commands available.
-
- INDEX: Names the file of record numbers (output
- from the SORT program), and causes the file to
- be read into memory.
-
- FORMAT: INDEX filename
- EXAMPLE: INDEX NAME.FIL
-
- POSITION: Positions the file to a particular
- record relative to the INDEX file which has
- been read. Used to restart a listing, or
- to scan for starting the listing in the middle.
- It can position either by record number, or
- by the contents of the field sorted upon.
-
- FORMAT: POSITION recno
- EXAMPLE: POSITION 55
- or
- FORMAT: POSITION fieldname fieldvalue
- EXAMPLE: POSITION ZIP 60419
-
- In the first example, the file is positioned
- to the 55th record in the index
- table. In the second example, the file is
- sequentially read (from whatever position is
- currently is at) until a zip matching 60419 is
- found. You may find it useful to use the
- first format to get 'close' because positioning by
- record number is fast, then use the position by
- field value until the exact one is found.
- NOTE that it is somewhat meaningless to POSITION
- on a field which is not the sort field, as the
- field being positioned upon is not read in order.
-
- NOTE if you stop the listing, then want to
- restart it from the beginning, you must
- issue POSITION 1 to start over again.
-
- TITLE: This command is used to supply a title
- for the listing.
-
- FORMAT: TITLE any character string
- EXAMPLE: TITLE SEPTEMBER MEETING ALPHA LISTING
-
- PRINT: This command is used to initiate the printing
- of a listing. The listing will be either:
- 72 columns wide if width < 80, or
- 132 columns wide if width > 79.
- Other than being less than or greater than 80,
- the setting of width does not effect the output
- of the PRINT function.
- FORMAT: PRINT
-
- WIDTH: Sets print width. The meaning of the width
- depends upon the function being asked for:
-
- TAGS or LABELS - the WIDTH setting is the actual
- number of characters wide the labels are.
-
- PRINT - the WIDTH setting determines the report width
- but only as to whether width is <80 or >79.
-
- FORMAT: WIDTH nn
- EXAMPLE: WIDTH 36
-
- LENGTH: Sets the length of the gummed
- labels used for the LABELS or TAGS function.
- Default is 6 lines long.
-
- FORMAT: LENGTH nn
- EXAMPLE: LENGTH 5
-
- TAGS: Initiates the printing of name tags.
- An algorithm is used to split the first name
- from the last name: The name is scanned from
- the back until a space is found. The part
- of the name to the right of the space is now
- considered the last name, and the part to the
- left the first name. Then, certain 'reasonableness'
- tests are performed: If the first 2 letters of the
- last name are JR, then the scan continues again
- to the left. Then, the last few characters of
- the 'first name' are checked to see if they are any
- of the common double word last names, such as
- ' VAN' or ' DE' or ' DI' or ' MC'. If so,
- scanning continues again. You might have to change
- this algorithm depending upon the names you encounter,
- such as 3 word names (VAN DER HEIDE) or VON, or
- the myriad of names I have not yet dreamed of.
- FORMAT: TAGS
-
- LABELS: This initiates the printing of mailing labels.
- It uses the settings of WIDTH, LENGTH, and UP
- to determine the physical format.
-
- A typical label is printed as follows:
-
- FERN P. DOCK 7709
- HENWAY CORPORATION
- BOX 1234
- FERNWOOD OH 12345
-
- (What's a HENWAY? about 3 pounds).
-
- Note the PAID date is printed in the upper
- right of the label.
- FORMAT: LABELS
-
- CHECK: This function checks the setting of the
- various variables, such as what record
- you are positioned to, whether an index has
- been read or not, and the current settings
- of: WIDTH, LENGTH, etc.
- FORMAT: CHECK
-
- UP: This is used to cause printing of LABELS
- or name TAGS 3-UP or 4-UP. (UP referring to
- how many labels are printed side-by-side.
- The program has not been generalized to handle
- 1-up or 2-up.
-
- FORMAT: UP n
- EXAMPLE: UP 3
-
- 3 or 4 are the only values supported.
-
- END: Causes ending of program execution.
-
- --------------------MISC. COMMENTS--------------------
-
- Use abbreviations to keep the width of each field
- within the width allowed in the report program,
- or else the TAB to the next field will cause an extra
- line to be printed. This will offset the line counter,
- and may cause the program to print a page which is too
- long.
-
-