1 SUB M11ADD (FUNC$, F.END%) & 2 !******************************************************************** & ! & ! & ! M11ADD & ! & ! Adds addresses to the Mailing List & ! & ! & !******************************************************************** & ! & ! Subprogram : M11ADD & ! Version : 1A 28-Jan-82 & ! Programmer : John Montrym & ! Jean Fullerton & ! Releaser : & ! & ! 11 !-------------------------------------------------------------------- & ! & ! & ! C O P Y R I G H T & ! & ! & !-------------------------------------------------------------------- & 20 !******************************************************************** & ! & ! & ! Modification History & ! & ! & !******************************************************************** & ! 21 ! REV DATE BY REASON ! --- -------- ---- ------ ! 1.0A 16-Feb-84 M Brown Changed 'Enter' ! to 'Type" ! throughout ! 1.0A 16-Feb-84 M Brown Changed line 12140 ! to show current value ! as default counter ! ! 1.1 24-May-84 Mike Brown ! Implemented new primary ID type. (1=system defined consecutive ! numbers, 2 = system defined address hash, 3 = user defined.) ! Lines 3300, 12012, 12020, 12070, 12160-12165, FN.STRIP$, misc ! references to HDR.SYS.DEF.PRIME.ID$. ! ! 1.1 11-Jun-84 Mike Brown ! Edited 12079 to prevent wrapping on terminals set to wrap. ! !******************************************************************** 100 ! & ! & ! & ! Summary: & ! & ! This subprogram is the Smart Mailer add an address module. & ! & ! & ! Calling Module: SMAIL & !-------------------------------------------------------------------- & ! & ! & ! Interfaces: & ! & ! & ! 300 !-------------------------------------------------------------------- & ! & ! & ! Input / Output & ! & ! & ! & ! CHANNEL FILE NAME MAP NAME STATUS AT ENTRY/EXIT & ! ------- --------- -------- -------------------- & ! CH.KB User keyboard None Closed/Closed & ! CH.ADD Address file MAPADD Closed/Closed & ! CH.SCR Screen file None Closed/Closed & ! & ! & !-------------------------------------------------------------------- & ! & ! & ! Variables and Arrays & ! & ! & ! & ! ERL Line in which error occurred & ! ERR Set to error after error & ! 600 !******************************************************************** & ! & ! & ! Common Declarations & ! & ! & !******************************************************************** & & 650 !******************************************************************** & ! & ! & ! MAP Statements & ! & ! & !******************************************************************** & & 700 !-------------------------------------------------------------------- & ! & ! & ! Subprograms & ! & ! & ! M11PAK Packs a record for writing to mailing list file & ! M11UPK Unpacks a record from mailing list file & ! & ! M11SCD Displays a screen & ! M11SCR Reads input from user keyboard & ! M11SCW Writes text at specififed coordinates & ! & ! 800 !-------------------------------------------------------------------- & ! & ! Subroutines: & ! & ! & ! 11000 Displays all prompts & ! 11500 Asks user for changes to displayed address & ! 12nn0 Accepts entry to prompt #nn & ! 13000 Displays the data from the & ! record in MAPADD & ! & !-------------------------------------------------------------------- & ! & ! Functions: & ! & ! & ! 16000 FN.GENERATE.ALT.ID$(X$) & ! Generates an alternate ID from & ! its argument, which is assumed & ! to be a name. & ! 16200 FN.REMOVE$(A$,B$) & ! Removes all occurrences of B$ & ! from A$. & ! & !-------------------------------------------------------------------- & 1000 !******************************************************************** & ! & ! & ! S T A R T S U B P R O G R A M L O G I C & ! & ! & !******************************************************************** & 1010 ON ERROR GOTO 19000 & \ ERR.CALLNAM$ = ERR.PROGNAM$ & \ ERR.PROGNAM$ = "M11ADD VER:00" & \ ERR.SUBNAM$ = "" & \ ERR.MSG$ = "Unexpected fatal error." & ! Set standard error trap. & ! Set up common for error reporting. & 1030 ALL.SP% = 2% & \ ST$="/AK/AL/AR/AZ/CA/CO/CT/DC/DE/FL/GA/GU/HI/IA/ID/IL/IN/KS" & +"/KY/LA/MA/MD/ME/MI/MN/MO/MS/MT/NC/ND/NE/NH/NJ/NM/NV/NY" & +"/OH/OK/OR/PA/PR/RI/SC/SD/TN/TX/UT/VA/VI/VT/WA/WI/WV/WY/" & \ FUNC.DPY$ = "Add" & ! Define some constants. & 3200 !-------------------------------------------------------------------- & ! & ! & ! Add & ! & ! & !-------------------------------------------------------------------- & & ADD.ALL$ = STRING$ (LEN(ADD.ALL$), 0%) & ! Clear out the first address record. & 3215 GO SUB 11000 & \ GO TO 3220 & ! Put up the screen of prompts. & 3217 CALL M11SCW (ERASE.EOL$, I%, 24%) FOR I% = 1% TO 6% & \ CALL M11SCW (ERASE.EOL$, I%, 24%) FOR I% = 7% TO 9% & IF HDR.LAST.ADDR.DEF$ = "N" & \ CALL M11SCW (ERASE.EOL$, 7%, 49%) IF HDR.LAST.ADDR.DEF$ = "Y" & \ CALL M11SCW (ERASE.EOL$, I%, 36%) FOR I% = 8% TO 9% & IF HDR.LAST.ADDR.DEF$ = "Y" & \ CALL M11SCW (ERASE.EOL$, I%, 24%) FOR I% = 10% TO 17% & \ CALL M11SCW (ERASE.EOL$, 18%, 15%) & \ CALL M11SCW (ERASE.EOL$, I%, 24%) FOR I% = 19% TO 22% & ! Clear out all the old address information. & ! Leave the old city/state/zip, if using them as defaults. & 3220 IF HDR.LAST.ADDR.DEF$ = "Y" & THEN ADD.SECT1$ = "" & \ ADD.SECT2$ = "" & ELSE ADD.ALL$ = "" & ! If we are to save the last address entered, clear around it. & ! Otherwise, clear the entire record. & 3230 IF HDR.SYS.DEF.PRIME.ID$ = "Y" OR HDR.SYS.DEF.PRIME.ID$ = "1" THEN & ADD.PRIME.ID$ = HDR.NEXT.PRIME.ID$ & \ PRIME.ID$ = EDIT$ (ADD.PRIME.ID$,8%) IF HDR.SYS.DEF.PRIME.ID$="Y" & OR HDR.SYS.DEF.PRIME.ID$ = "1" & \ CALL M11SCW (PRIME.ID$, 20%, 24%) & ! If system is generating primary IDs, then do so now & ! and display it. & 3232 ADD.COUNTER% = 0% & ! Initialize the counter for each address, in case the user 'line & ! feeds' out of the address. & 3234 DISPLAY_HASHED_ID% = FALSE% ! Don't display hashed ID until user has entered address fields ! (or typed a LF). 3235 GOSUB 12010 & \ GO TO 9000 IF F.END% & \ GO TO 3215 IF REDISPLAY% & \ GOSUB 12020 & \ GO TO 3240 IF F.END% & \ GOSUB 12030 & \ GO TO 3240 IF F.END% & \ GOSUB 12040 & \ GO TO 3240 IF F.END% & \ GOSUB 12050 & \ GO TO 3240 IF F.END% & \ GOSUB 12060 & \ GO TO 3240 IF F.END% & \ GOSUB 12070 & \ GO TO 3240 IF F.END% & \ DISPLAY_HASHED_ID% = TRUE% & \ GOSUB 12080 & \ GO TO 3240 IF F.END% & \ GOSUB 12140 & \ GO TO 3240 IF F.END% & \ GOSUB 12150 & \ GO TO 3240 IF F.END% 3237 GOSUB 12161 UNLESS HDR.SYS.DEF.PRIME.ID$ = "Y" & OR HDR.SYS.DEF.PRIME.ID$ = "1" & \ GO TO 3240 IF F.END% & \ GOSUB 12170 & \ GO TO 3240 IF F.END% & \ GO TO 3250 & ! User fills in all the prompts. & ! User can type "END" to 'Name:' to get out, & ! or "END" to any other prompt to start over. & 3240 IF M11.ALL.DONE% THEN M11.ALL.DONE% = FALSE% & \ DISPLAY_HASHED_ID% = TRUE% & \ F.END% = FALSE% & \ GO TO 3237 & ELSE GO TO 3235 & ! Check to see if the user typed in a Line Feed at the beginning of & ! the field to signal completion of the address. & 3250 GO SUB 11500 & \ GO TO 3215 IF REDISPLAY% & \ GOTO 3235 IF EDIT$( ADD.PRIME.ID$, 140% ) = "" & ! Ask for changes. & ! Send user back to "Name:" prompt if nothing was entered. This & ! prevents a user from entering a blank ID. 3270 GO TO 3290 IF HDR.SYS.DEF.PRIME.ID$ <> "Y" & AND HDR.SYS.DEF.PRIME.ID$ <> "1" & \ JUNK$ = SUM$ (HDR.NEXT.PRIME.ID$, "1") & \ RSET HDR.NEXT.PRIME.ID$ = JUNK$ & \ HDR.KEY0$ = HDR.CHR$ + "000000000000001" & ! The string arithmetic add routine (SUM) is used because the number & ! can be up to 16 characters long. & 3280 FIND #CH.ADD%, KEY #0% EQ HDR.KEY0$ & \ SLEN% = LEN(HDR.ALL$) & \ MOVE TO #CH.ADD%, HDR.ALL$ & \ UPDATE #CH.ADD%, COUNT SLEN% & ! Update and rewrite the system's primary ID. & ! This section of code is somewhat time-consuming - it requires the & ! system to update the header record for every address added to the & ! Mailing List File. & 3290 CALL M11PAK (REC$) & \ SLEN% = LEN(REC$) & \ MOVE TO #CH.ADD%, REC$ & \ PUT #CH.ADD%, COUNT SLEN% & \ GOSUB 14100 & \ GO TO 3217 & ! Compact the record & write it out. & ! Update the total fields in the file header. & ! Go ask another record number. & 3300 GOTO 3320 IF HDR.SYS.DEF.PRIME.ID$ = "1" OR & HDR.SYS.DEF.PRIME.ID$ = "Y" GET #CH.ADD%, KEY #0% EQ ADD.PRIME.ID$ SLEN% = RECOUNT M11.MSG$ = BEL + BEL + "A record with the same primary ID already exists ..." CALL M11SCW (M11.MSG$, 23%, 1% ) CALL M11SCW ("Do you want to see it?", 24%, 1%) CALL M11SCR ( ANS$, 24%, 24%, 1%, "Y", "Y", F.END% ) IF ANS$ = "Y" THEN SAV_ADD$ = ADD.ALL$ + "" CALL M11SCW ( ERASE.EOS$, 23%, 1% ) MOVE FROM #CH.ADD%, REC$ = SLEN% CALL M11UPK ( REC$ ) FUNC.DPY$ = "" GOSUB 13000 FUNC.DPY$ = "Add" M11.MSG$ = "" GOSUB 14900 ADD.ALL$ = SAV_ADD$ GOSUB 13000 END IF 3310 M11.MSG$ = "You can: (1) Replace the existing record (2) Change" CALL M11SCW ( M11.MSG$, 23%, 1% ) M11.MSG$ = "the primary key (3) Cancel this record operation. Option?" CALL M11SCW ( M11.MSG$, 24%, 1% ) CALL M11SCR ( ANS$, 24%, 63%, 1%, "1", "A", F.END% ) GOTO 3310 IF POS ( "123", ANS$, 1% ) = 0% CALL M11SCW ( ERASE.EOS$, 23%, 1% ) SELECT ANS$ CASE "1" DELETE #CH.ADD% GOSUB 14200 ! Decrement MLF total GOTO 3290 CASE "2" GOSUB 12165 GOTO 3250 CASE "3" M11.MSG$ = "No records modified." SLEEP 2% END SELECT GOTO 3217 ! Error traps here if duplicate key detected at 3290. If the ! primary ID is user defined, or system defined address hash, ! allow user to view the existing record and take appropriate action. 3320 WORK$ = ADD.PRIME.ID$ ! The PID already in use & \ HDR.KEY0$ = HDR.CHR$ + "000000000000001" & \ FIND #CH.ADD%, KEY #0% EQ HDR.KEY0$ & \ SLEN% = LEN(HDR.ALL$) & \ MOVE TO #CH.ADD%, HDR.ALL$ & \ ADD.PRIME.ID$ = HDR.NEXT.PRIME.ID$ ! Next available PID & \ CALL M11SCW(EDIT$(ADD.PRIME.ID$, 136%), 20%, 24%) & \ JUNK$ = SUM$ (HDR.NEXT.PRIME.ID$, "1") & \ RSET HDR.NEXT.PRIME.ID$ = JUNK$ & \ SLEN% = LEN(HDR.ALL$) & \ MOVE TO #CH.ADD%, HDR.ALL$ & \ UPDATE #CH.ADD%, COUNT SLEN% & \ M11.MSG$ = "The Primary ID was changed because " + & EDIT$(WORK$,136%) + " was in use." & \ GOSUB 14900 & \ GO TO 3290 & ! Handle similar situation for system defined PID. & ! If this primary ID is already being used by another record, it & ! means that some one else just used it. Look up the next available & ! PID and inform the user what the new one will be. & 9000 !******************************************************************** & ! & ! & ! E N D O F P R O C E S S I N G & ! & ! & !******************************************************************** & & ERR.PROGNAM$ = ERR.CALLNAM$ & \ UNLOCK #CH.ADD% & \ GO TO 32767 & ! Jump around the junk and leave. & & & 10000 !******************************************************************** & ! & ! & ! Local Subroutines & ! & ! & !******************************************************************** & 11000 !-------------------------------------------------------------------- & ! & ! & ! Display Address Prompts & ! & ! & !-------------------------------------------------------------------- & 11010 CALL M11SCD (SCR.ADDR.ENTRY%) & \ CALL M11SCW (FUNC.DPY$, 1%, 2%) & \ CALL M11SCW ("Type '?' for help", 1%, 58%) & \ CALL M11SCW (HDR.CAT.PROMPT$(I%), 10%+I%, 5%) FOR I% = 1% TO 6% & \ REDISPLAY% = FALSE% & \ RETURN & ! Put up the screen of questions. We must fill in the custom stuff. & & 11300 !-------------------------------------------------------------------- & ! & ! & ! Offer Help & ! & ! & !-------------------------------------------------------------------- & & CALL M11SCD (SCR.HLP.7A%) & \ CALL M11SCR (ANS$, 24%, 72%, 4%, "", "A", F.END%) & \ RETURN UNLESS SEG$ (ANS$, 1%, 1%) = "M" & ! Show help screen, return if this is sufficient. & 11320 CALL M11SCD (SCR.HLP.7B%) & \ M11.MSG$ = "When through reading the information ..." & \ GO SUB 14900 & \ RETURN & ! Display the last screen and return. & 11500 !-------------------------------------------------------------------- & ! & ! & ! Ask for Changes & ! & ! & !-------------------------------------------------------------------- & 11540 CALL M11SCW ("Change which line (1-17):", 23%, 5%) & \ CALL M11SCW ("Press RETURN to accept.", 24%, 5%) & ! Display the prompt. & 11550 M11.PROG.LINE% = 11550% CALL M11SCR (ANS$, 23%, 33%, 2%, "", "N", F.END%) M11.PROG.LINE% = 0% IF M11.UPDATE.CODE% = CNTRL.C% THEN M11.UPDATE.CODE% = OK% GOTO 3235 END IF ! Return to 'Name' prompt if user typed ^C here. ! This allows user to get out without saving record. ! (21-JAN-85 MJB) GO TO 11590 IF F.END% ! Read in which address field to update. 11560 GO TO 11570 IF ANS$ = '?' & \ ANS% = VAL(ANS$) & \ GO TO 11590 IF ANS% = 0% ! CR means no change & \ GO TO 11580 IF ANS% > 0% AND ANS% < 18% & ! Check that the number is within the range. & 11570 M11.MSG$ = "Type in a line number from 1 to 17, or press RETURN to continue." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 11550 & ! Offer help. & 11580 CAT% = ANS% - 7% & \ ON ANS% GOSUB & 12010, 12020, 12030, 12040, 12050, 12060, 12070, & 12085, 12085, 12085, 12085, 12085, 12085, & 12140, 12150, 12160, 12170 & \ RETURN IF REDISPLAY% & \ GO TO 11550 & ! Accept the correct entry. & 11590 RETURN & & 12000 !-------------------------------------------------------------------- & ! & ! & ! Single Prompts & ! & ! & !-------------------------------------------------------------------- & 12010 M11.PROG.LINE% = 12010% CALL M11SCR (NEW.NAME$, 3%, 24%, 30%, ADD.NAME$, "a", F.END%) M11.PROG.LINE% = 0% IF M11.UPDATE.CODE% = CNTRL.C% THEN M11.UPDATE.CODE% = OK% GOTO 9000 END IF ! Return to Update Menu If user typed ^C at this prompt. ! This allows a user to get out without saving the record. ! (21-Jan-85 MJB) REDISPLAY% = FALSE% RETURN IF F.END% IF NEW.NAME$ = "?" THEN GO SUB 11300 REDISPLAY% = TRUE% RETURN ! Get the name; return to ACR Menu if requested. ! Go offer two help screens if requested, then redisplay prompts, but ! do not wipe out information already entered - use it as defaults. 12012 RETURN IF NEW.NAME$ = ADD.NAME$ ! Just return if user didn't change name. ADD.NAME$ = NEW.NAME$ ! Store the new name. GOSUB 12162 IF HDR.SYS.DEF.PRIME.ID$ = "2" ! Set up and display the new primary ID if necessary IF HDR.SYS.DEF.ALT.ID$ = "Y" THEN DF$ = FN.GENERATE.ALT.ID$ (ADD.NAME$) CALL M11SCW (ERASE.EOL$, 21%, 24%) CALL M11SCW (DF$, 21%, 24%) LSET ADD.ALTERNATE.ID$ = DF$ END IF ! Set up and display the new alternate ID if necessary. RETURN 12020 CALL M11SCR (WORK$, 4%, 24%, 30%, ADD.ADDR1$, "a", F.END%) CALL M11SCW (ERASE.EOL$, 24%, 1%) RETURN IF F.END% ! Get 1st address line ADD.ADDR1$ = WORK$ ! Get 1st address line IF WORK$ = "?" THEN M11.MSG$ = "Type the first line of the address (eg, 123 Main St)." CALL M11SCW (M11.MSG$, 24%, 1%) GO TO 12020 END IF ! Give help if requested. ! OLD_ADDR$ = ADD.ADDR1$ + "" !ADD.ADDR1$ = WORK$ !IF HDR.SYS.DEF.PRIME.ID$ = "2" & ! AND ADD.PRIME.ID$ > " " & ! AND WORK$ <> OLD_ADDR$ !THEN ! GOSUB 12162 !END IF ! Store the new address line. ! Set up and display new prime ID if necessary. GOSUB 12162 IF HDR.SYS.DEF.PRIME.ID$ = "2" ! Set up and display the new primary ID if necessary RETURN ! Get address line 1. 12030 CALL M11SCR (WORK$, 5%, 24%, 30%, ADD.ADDR2$, "a", F.END%) CALL M11SCW (ERASE.EOL$, 24%, 1%) RETURN IF F.END% ADD.ADDR2$ = WORK$ ! Get 2nd address line IF WORK$ = "?" THEN M11.MSG$ = "Type the second line of the address (eg, Apt 3A)." CALL M11SCW (M11.MSG$, 24%, 1%) GO TO 12030 END IF ! Give help if requested. ! OLD_ADDR$ = ADD.ADDR2$ + "" !ADD.ADDR2$ = WORK$ !IF HDR.SYS.DEF.PRIME.ID$ = "2" & ! AND ADD.PRIME.ID$ > " " & ! AND WORK$ <> OLD_ADDR$ !THEN ! GOSUB 12162 !END IF ! Store the new address line. ! Set up and display new prime ID if necessary. GOSUB 12162 IF HDR.SYS.DEF.PRIME.ID$ = "2" ! Set up and display the new primary ID if necessary RETURN ! Get address line 2. 12040 CALL M11SCR (WORK$, 6%, 24%, 30%, ADD.ADDR3$, "a", F.END%) CALL M11SCW (ERASE.EOL$, 24%, 1%) RETURN IF F.END% ADD.ADDR3$ = WORK$ ! Get 3rd address line. IF WORK$ = "?" THEN M11.MSG$ = "Type the third line of the address (eg, c/o Mr. Smith)." CALL M11SCW (M11.MSG$, 24%, 1%) GO TO 12040 END IF ! Give help if requested. GOSUB 12162 IF HDR.SYS.DEF.PRIME.ID$ = "2" ! Set up and display the new primary ID if necessary RETURN 12050 CALL M11SCR (WORK$, 7%, 24%, 25%, ADD.CITY$, "a", F.END%) & \ ADD.CITY$ = WORK$ UNLESS F.END% & \ RETURN UNLESS ADD.CITY$ = "?" & \ M11.MSG$ = "Type the name of the city or town." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 12050 & ! Get city name. & 12060 CALL M11SCW (ERASE.EOL$, 8%, 36%) & \ CALL M11SCW (ERASE.EOL$,10%, 36%) & \ CALL M11SCR (WORK$, 8%, 24%, 12%, ADD.STATE$, "a", F.END%) & \ ADD.STATE$ = WORK$ UNLESS F.END% & \ IF ADD.STATE$ = "?" & THEN M11.MSG$ = "Type the name of the state or country." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 12060 & ELSE RETURN IF F.END% & OR HDR.COUNTRY$ <> "A" & \ P% = 8% & \ ADD.STATE$ = EDIT$ (ADD.STATE$, 32%) & \ A.STATE$ = "/" + EDIT$ (ADD.STATE$, ALL.SP%) + "/" & \ GO TO 12079 IF POS (ST$, A.STATE$, 1%) = 0% & AND ADD.STATE$ > " " & \ RETURN & ! Get state abbrev. & ! Set up search string for state. & 12070 CALL M11SCW (ERASE.EOL$, 9%, 36%) CALL M11SCW (ERASE.EOL$, 10%, 36%) CALL M11SCR (WORK$, 9%, 24%, 10%, ADD.ZIP$, "a", F.END%) RETURN IF F.END% ADD.ZIP$ = WORK$ ! Get zip code IF WORK$ = "?" THEN M11.MSG$ = "Type the postal zip code." CALL M11SCW (M11.MSG$, 24%, 1%) GO TO 12070 END IF ! Give help if requested. ! OLD_ZIP$ = ADD.ZIP$ + "" !ADD.ZIP$ = WORK$ !IF HDR.SYS.DEF.PRIME.ID$ = "2" & ! AND ADD.PRIME.ID$ > " " & ! AND OLD_ZIP$ <> ADD.ZIP$ !THEN ! GOSUB 12162 !END IF ! Display new prime ID if necessary GOSUB 12162 IF HDR.SYS.DEF.PRIME.ID$ = "2" ! Set up and display the new primary ID if necessary RETURN IF HDR.COUNTRY$ <> "A" P% = 9% GO TO 12079 IF FN.BAD.ZIP% AND (ADD.ZIP$ > " ") RETURN ! Get ZIP code. 12079 M11.MSG$ = "State should be a valid 2-character code" IF P%=8% & \ M11.MSG$ = "US zip format is NNNNN or NNNNN-NNNN" IF P%=9% & \ M11.MSG$ = BEL + BEL + M11.MSG$ & \ CALL M11SCW ( SEG$ ( M11.MSG$, 1%, 80%-37% ), P%, 37%) & \ M11.MSG$ = "You can change it after typing address" & \ CALL M11SCW ( SEG$ ( M11.MSG$, 1%, 80%-37% ), 10%, 37%) & \ RETURN & ! Warn user about wrong state or zip code, but do not force a change. & ! Truncate message to prevent wrapping. 12080 FOR CAT% = 1% TO 6% & & \ TST$ = HDR.CAT.TYPE$(CAT%) & \ TST$ = "a" IF TST$ = "A" & \ DF$ = ADD.CATEGORIES$(CAT%-1%) & \ DF$ = DATE$ (0%) IF TST$ = "D" 12081 CALL M11SCR (J$, 10%+CAT%, 24%, 10%, DF$, TST$,F.END%) & \ RETURN IF F.END% & \ IF J$ = "?" THEN & M11.MSG$ = "Type the information for this category." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 12081 12082 ADD.CATEGORIES$(CAT%-1%) = J$ & & \ NEXT CAT% & \ RETURN & ! This code is only executed if this is an ADD operation (not CHANGE) & ! For each category ... & ! Check the type of information necessary and pass the code to & ! for validation. & ! Get the category information. & ! Offer a one-line help message if requested. & 12085 TST$ = HDR.CAT.TYPE$(CAT%) & \ TST$ = "a" IF TST$ = "A" & \ DF$ = ADD.CATEGORIES$(CAT%-1%) & \ CALL M11SCR (J$, 10%+CAT%, 24%, 10%, DF$, TST$, F.END%) & \ RETURN IF F.END% & \ IF J$ = "?" & THEN M11.MSG$ = "Type the information for this category." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 12085 & ELSE ADD.CATEGORIES$(CAT%-1%) = J$ & \ RETURN & ! This code is only executed if this is an CHANGE operation (not ADD) & ! Check the type of information necessary and pass the code to & ! for validation. & ! Get the category information. & ! Offer a one-line help message if requested. & & 12140 DF$ = NUM1$ (ADD.COUNTER%) & \ CALL M11SCR (ANS$, 17%, 24%, 4%, DF$, "I", F.END%) & \ IF ANS$ = "?" & THEN M11.MSG$ ="Type a value between 0 and 9999 for this address." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 12140 & ELSE ADD.COUNTER% = VAL(ANS$) & \ RETURN & ! Get counter value. & 12150 CALL M11SCR (WORK$, 18%, 15%, 65%, ADD.COMMENT$, "a",F.END%) & \ ADD.COMMENT$ = WORK$ UNLESS F.END% & \ RETURN UNLESS ADD.COMMENT$ = "?" & \ M11.MSG$ = "Type any remark or comment." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 12150 & ! Get comment. & 12160 GOTO 12161 UNLESS HDR.SYS.DEF.PRIME.ID$ = "1" OR & HDR.SYS.DEF.PRIME.ID$ = "Y" CALL M11SCW ("You may not change the Primary ID"+BEL, 24%, 1%) RETURN ! The primary ID is system defined consecutive numbers. 12161 GOTO 12165 IF HDR.SYS.DEF.PRIME.ID$ <> "2" 12162 Z9$ = FN.STRIP$ ( ADD.NAME$ ) Z9$ = EDIT$ (Z9$, 128%) Z9.LEN% = LEN (Z9$) GO TO 12163 IF SEG$ (Z9$, I%, I% ) = " " & FOR I% = Z9.LEN% TO 1% STEP -1% I% = 0% ! Remove titles and words ending with "." . ! Locate space before last name. 12163 FIRST_INIT$ = SEG$ (Z9$, 1%, 1%) FIRST_INIT$ = " " IF I% = 0% ! Extract first initial. Make it a space if no first ! name was typed. LAST$ = SEG$ (Z9$, I% + 1%, Z9.LEN%) LAST$ = LAST$ + SPACE$ (4% - LEN (LAST$)) IF LEN (LAST$) < 4% ! Extract last name. Pad if less than 4 characters. IF ADD.ADDR3$ > " " THEN HASH1$ = ADD.ADDR2$ HASH2$ = ADD.ADDR3$ ELSE HASH1$ = ADD.ADDR1$ HASH2$ = ADD.ADDR2$ END IF ! Form address hash from the most significant address lines. ! If ADD.ADDR3$ is not blank, use lines 2 and 3. Otherwise, ! use lines 1 and 2. ADDR1$ = EDIT$ (HASH1$, 32%) ADDR1$ = FN.REMOVE$ (ADDR1$, "THE ") ADDR1$ = EDIT$ (ADDR1$, 2%) ADDR1$ = FN.REMOVE$ (ADDR1$, ".") ! Remove spaces, "." and "The " from 1st address line. ADDR1$ = ADDR1$ + SPACE$(3% - LEN(ADDR1$)) IF LEN (ADDR1$) < 3% ! Pad to 3 characters if necessary. MAIL ROOM request. ADDR2$ = EDIT$ (HASH2$, 2% + 32%) ADDR2$ = FN.REMOVE$ (ADDR2$, ".") ADDR2$ = FN.REMOVE$ (ADDR2$, ",") ! Remove spaces, "." and "," from 2nd address line. ADDR2$ = ADDR2$ + SPACE$(4% - LEN(ADDR2$)) IF LEN (ADDR2$) < 4% ! Pad to 4 characters if necessary. MAIL ROOM request. ZIP$ = SEG$(ADD.ZIP$, 1%, 5%) ZIP$ = EDIT$( ZIP$, 8% + 4% + 32%) ZIP$ = STRING$(5% - LEN(ZIP$), 48%) + ZIP$ IF LEN(ZIP$) < 5% ! Replace leading spaces and nulls in the PID field with zeroes. ! This fixes a bug in field test version 1.1 which stored the ! PID with leading spaces, making it impossible to access the ! record by PID (M11GET strips leading and trailing spaces from ! user input. 16-Jan-85 MJB ADD.PRIME.ID$ = ZIP$ & + SEG$ ( LAST$, 1%, 2% ) & + SEG$ ( LAST$, 4%, 4% ) & + FIRST_INIT$ & + SEG$ ( ADDR1$, 1%, 3% ) & + SEG$ ( ADDR2$, 1%, 4% ) IF SEG$( LAST$, 4%, 4% ) = " " THEN ADD.PRIME.ID$ = SEG$ ( ADD.PRIME.ID$, 1%, 7% ) & + SEG$( LAST$, 3%, 3% ) & + SEG$( ADD.PRIME.ID$, 9%, 16% ) END IF ! Use 3rd character of last name if 4th character is blank. ! Construct hashed key as follows: ! 5 digit zip ! 1st, 2nd, 4th characters of last name ! ( 1st 3 char if no 4th character ) ! 1st character of first name ! 1st three characters of address line 1 ! (except " " and "." and "The ") ! 1st four characters of address line 2 ! (except " " and "." ) IF ANS% = 16% OR ADD.PRIME.ID$ = "" THEN GOSUB 12165 ELSE CALL M11SCW ( ADD.PRIME.ID$, 20%, 24% ) & IF DISPLAY_HASHED_ID% = TRUE% END IF ! Allow user to change PID if that was requested. Also, ! make sure the PID isn't blank. Otherwise, ! just display the new PID. RETURN ! Build hashed key, display it, and return 12165 J$ = "" & \ J$ = ADD.PRIME.ID$ IF HDR.SYS.DEF.PRIME.ID$ = "2" & \ CALL M11SCR (J$, 20%, 24%, 16%, J$,"A",F.END%) & \ CALL M11SCW ("A Primary ID is required.", 24%, 1%) IF J$ = "" & \ GO TO 12165 IF J$ = "" & \ IF J$ = "?" & THEN M11.MSG$ = "Type the first ID by which to identify this address." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 12165 & ELSE LSET ADD.PRIME.ID$ = J$ & \ RETURN & ! Load up the primary ID. By definition we left-justify. & 12170 DF$ = ADD.ALTERNATE.ID$ & \ DF$ = FN.GENERATE.ALT.ID$ (ADD.NAME$) & IF HDR.SYS.DEF.ALT.ID$ = "Y" !*** AND DF$ = "" & ! Use system defined value as default & \ CALL M11SCR (J$, 21%, 24%, 10%, DF$, "A", F.END%) & \ IF J$ = "?" & THEN M11.MSG$ = "Type an ID by which to identify this address." & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ GO TO 12170 & ELSE LSET ADD.ALTERNATE.ID$ = J$ UNLESS F.END% & \ RETURN & ! Get alternate ID. Generate default if that flag is set. & & 13000 !-------------------------------------------------------------------- & ! & ! & ! Display an Address & ! & ! input: POINTER% & ! ADD.- & ! FUNC$ & ! & !-------------------------------------------------------------------- & 13020 GO SUB 11000 ! Put up prompts. & & \ CALL M11SCW (ADD.ADDR$(I%), 3%+I%, 24%) FOR I% = 0% TO 4% & \ CALL M11SCW (ADD.STATE$, 8%, 24%) & \ CALL M11SCW (ADD.ZIP$, 9%, 24%) & \ CALL M11SCW (ADD.CATEGORIES$(I%), 11%+I%, 24%) FOR I% = 0% TO 5% & \ CALL M11SCW (NUM1$(ADD.COUNTER), 17%, 24%) & \ CALL M11SCW (ADD.COMMENT$, 18%, 15%) & \ PRIME.ID$ = EDIT$ (ADD.PRIME.ID$, 8%) & \ CALL M11SCW (PRIME.ID$, 20%, 24%) & \ CALL M11SCW (ADD.ALTERNATE.ID$, 21%, 24%) & \ CALL M11SCW ("<--- selected by", POINTER%, 45%) UNLESS FUNC$ = "A" & OR FUNC.DPY$ = "" & ! Display all the prompts. Then display all the data. & 13040 RETURN & & 14000 !-------------------------------------------------------------------- & ! & ! Update total fields in file header & ! & ! & !-------------------------------------------------------------------- & 14100 GET #CH.ADD%, KEY #0% EQ HDR.CHR$ IF MLF_TOTAL_FLAG$ = CHR$(1%) THEN MLF_TOTAL = MLF_TOTAL + 1 UPDATE #CH.ADD% END IF RETURN ! A record has been added to the file. Increment the total ! in the file header. Note: Smart Mailer V1.0 did not store ! the total in the file header, so these fields may be blank. ! M11RP1 initializes these fields if necessary. 14200 GET #CH.ADD%, KEY #0% EQ HDR.CHR$ IF MLF_TOTAL_FLAG$ = CHR$(1%) THEN MLF_TOTAL = MLF_TOTAL - 1 UPDATE #CH.ADD% END IF RETURN ! A record has been removed from the file. Decrement the total ! in the file header. Note: Smart Mailer V1.0 did not store ! the total in the file header, so these fields may be blank. ! M11RP1 initializes these fields if necessary. 15000 !*************************************************************** & ! & ! & ! F U N C T I O N S L O C A L T O & ! & ! T H I S S U B P R O G R A M & ! & ! & !*************************************************************** & & 16000 !-------------------------------------------------------------------- & ! & ! & ! FN.GENERATE.ALT.ID$ (ARG$) & ! & !-------------------------------------------------------------------- & ! & ! This function generates a 10-byte alternate ID from & ! the argument ARG$, which is assumed to be a name. & ! & ! Note: XTABL$ must have been defined before this & ! function is called; it is used to XLATE the input, & ! removing everything except letters and spaces, and & ! coverting lowercase letters to uppercase. & ! & ! & !-------------------------------------------------------------------- & 16020 DEF FN.GENERATE.ALT.ID$ (ARG$) & ! Define the function. & 16050 Z9$ = FN.STRIP$ ( ARG$ ) ! Remove titles and words ending with "." . 16100 Z9$ = EDIT$ (Z9$, 128%) & \ Z9.LEN% = LEN (Z9$) & \ GO TO 16120 IF MID (Z9$, I%, 1%) = " " & FOR I% = Z9.LEN% TO 1% STEP -1% & \ I% = 0% & ! When we get to 16120, I% will equal the position in the & ! name of the space just in front of the last word. & 16120 L% = HDR.LAST.NAME.MIX% & \ F% = HDR.FIRST.NAME.MIX% & \ Z1$ = "" IF L% = 0% & \ Z1$ = SEG$ (SEG$(Z9$, I% + 1%, Z9.LEN%),1%,L%) IF L% > 0% & \ LENZ1% = LEN (Z1$) & \ Z1$ = Z1$ + SPACE$ (L% - LENZ1%) IF LENZ1% < L% & ! Set Z1$ to first L characters of the last word. & & \ Z9$ = SEG$ (Z9$, 1%, I%) & ! Strip the surname just taken from the name. & & \ Z.WORD1.END% = POS (Z9$," ",1%) & ! Set marker to position of first space in the name. & & \ Z1$ = Z1$ + SEG$ (SEG$ (Z9$,1%,Z.WORD1.END%-1%),1%,F%) IF F% > 0% & ! Tack on first F characters of first name. & 16150 FN.GENERATE.ALT.ID$ = Z1$ & \ FNEND & 16200 !-------------------------------------------------------------------- & ! & ! & ! FN.REMOVE$ (A$, B$) & ! & !-------------------------------------------------------------------- & ! & ! This function removes all occurrences of B$ from & ! A$ and returns the result as the function value. & ! & ! & !-------------------------------------------------------------------- & 16220 DEF FN.REMOVE$ (A$, B$) & \ Z.B.LEN% = LEN (B$) & \ Z.LOC% = POS (A$, B$, 1%) & ! Define the function. & 16240 UNTIL Z.LOC% = 0% & \ A$ = SEG$(A$,1%,Z.LOC%-1%) + SEG$(A$,Z.LOC%+Z.B.LEN%,LEN(A$)) & \ Z.LOC% = POS (A$, B$, 1%) & \ NEXT & ! Loop removing B$ from A$ (as many times as necessary). & 16260 FN.REMOVE$ = A$ & \ FNEND & 16300 !********************************************************************* ! ! FN.STRIP$ ( ARG$ ) ! !********************************************************************* 16310 DEF FN.STRIP$ ( ARG$ ) 16350 Z9$ = EDIT$ (ARG$, 56%) & ! After all this, everything is uppercase alphabetic only & ! except for periods, and single spaces which delimit words. & 16370 Z9$ = FN.REMOVE$ (Z9$, "THE ") & \ Z9$ = FN.REMOVE$ (Z9$, " III") & \ Z9$ = FN.REMOVE$ (Z9$, " II") & ! Remove all the formal stuff. & ! For most names, we are now left with a first name, an optional & ! middle name or initial, and a surname as the last word in the name. & 16380 Z9$ = Z9$ + " " & \ DOT% = POS (Z9$, ". ", 1%) & \ GO TO 16400 IF DOT% = 0% & \ LENZ9% = LEN (Z9$) & \ SPACE% = 0% & \ SPACE% = J% IF MID (Z9$, J%, 1%) = " " FOR J% = 1% TO DOT%-1% & \ Z1$ = "" & \ Z1$ = SEG$ (Z9$,1%,SPACE%) IF SPACE% > 0% & \ Z1$ = Z1$ + SEG$ (Z9$,DOT%+2%,LEN(Z9$)) IF (DOT%+2%) <= LENZ9% & \ Z9$ = Z1$ & \ GO TO 16380 & & ! Wipe out any word in the name field that ends in "." . & ! This means that Mr., Jr., Lic. and initials (with a ".") are wiped, & ! but that names with an imbedded "." and initials without are left. & ! The algorithm searches for each ". " until no more are found. & ! It then searches for each space up to the ".". & ! The position of the last space before the "." is left in the & ! variable (SPACE%). & ! The new name string is set to the first portion, including the & ! space, plus the last portion after the ". ". & 16400 FN.STRIP$ = Z9$ & \ FNEND & 19000 !*************************************************************** & ! & ! & ! S T A N D A R D E R R O R H A N D L I N G & ! & ! & !*************************************************************** & 19010 GO TO 19990 IF ERN$ <> SEG$ (ERR.PROGNAM$,1%,6%) & ! Only tracing back an error from another subprogram. & 19100 RESUME 3250 IF ERL = 3250 AND ERR = 154 & \ RESUME 3270 IF ERL = 3250 AND (ERR = 155 OR ERR = 11) & \ RESUME 3280 IF ERL = 3280 AND ERR = 154 & \ RESUME 3320 IF ERL = 3320 AND ERR = 154 & \ RESUME 3300 IF ERL = 3290 AND ERR = 134 & \ RESUME 3290 IF ERL = 3290 AND ERR = 154 & \ RESUME 14100 IF ERL = 14100 AND ERR = 154 & \ RESUME 14200 IF ERL = 14200 AND ERR = 154 & ! Errors which can be handled logically. & 19900 ERR.ERL% = ERL & \ ERR.ERR% = ERR & \ ERR.CODE% = FATAL.ERROR% & 19990 ON ERROR GO BACK & ! Return to calling program for fatal error processing. & 32767 SUBEND