1 SUB M11MOD (FUNC$,F.END%) & 2 !******************************************************************** & ! & ! & ! M11MOD & ! & ! Maintains the Mailing List addresses & ! & ! & !******************************************************************** & ! 3 ! Subprogram : M11MOD & ! 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 use current value ! as default counter ! ! 1.1 24-May-84 Mike Brown ! Implemented new primary ID type. (1 = consecutive numbers, ! 2 = address hash, 3 = user defined.) Lines 1520 - 1550, ! 12012, 12020, 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 change module. & ! & ! notes for future enhancements: & ! Allow changes to a user-defined Primary ID (12160) & ! & ! & ! Calling Module: SMAIL & !-------------------------------------------------------------------- 200 ! & ! & ! 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 & ! & ! 400 !-------------------------------------------------------------------- & ! & ! & ! 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 & ! & ! & !******************************************************************** & & ON ERROR GOTO 19000 & \ ERR.CALLNAM$ = ERR.PROGNAM$ & \ ERR.PROGNAM$ = "M11MOD VER:00" & \ ERR.SUBNAM$ = "" & \ ERR.MSG$ = "Unexpected fatal error." & ! Set standard error trap. & ! Set up common for error reporting. & 1030 ALL.SP% = 2% & \ DF.KEY$ = "P" & \ 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$ = "Change" IF FUNC$ = "C" & \ FUNC.DPY$ = "Display" IF FUNC$ = "D" & ! Define some constants. & 1200 !-------------------------------------------------------------------- & ! & ! & ! Change or Display which address? & ! & ! & !-------------------------------------------------------------------- & & UNLOCK #CH.ADD% & \ CALL M11SCD (SCR.CH.EXAM.ADDR%) & \ M11.MSG$ = "Type P or A or END." & \ GO TO 1260 & ! Show the Change/Examine ID entry screen. & 1250 CALL M11SCW (M11.MSG$, 24%, 1%) & 1260 CALL M11SCR (ACCESS$, 17%, 39%, 1%, DF.KEY$, "A", F.END%) & \ GO TO 9000 IF F.END% & \ GO TO 1250 IF POS ("AP", ACCESS$, 1%) = 0% & \ DF.KEY$ = ACCESS$ & \ GO TO 1350 IF ACCESS$ = "P" & ! Get reply - branch. & & 1270 !-------------------------------------------------------------------- & ! & ! Change by Alternate ID & ! & !-------------------------------------------------------------------- & 1280 POINTER% = 21% & \ CALL M11SCR (ANS$, 9%, 45%, 10%, "", "A", F.END%) & \ GO TO 9000 IF F.END% & \ GO TO 1260 IF ANS$ = "" & \ SAV.ALTERNATE.ID$ = EDIT$ (ANS$, 8%+128%) & ! Get the alternate ID (wipe out leading + trailing spaces). & ! 'END' takes us back to the update menu. & ! Null entry takes us back to ID selection (P/A). & 1300 GET #CH.ADD%, KEY #1% GE SAV.ALTERNATE.ID$ & \ ADD.LEN% = RECOUNT & \ MORE% = FALSE% & ! Try to get the first address matching the alternate ID. & ! Assume for now that there are no MORE matches. & ! We trap to 1349 if there are no matches. & 1305 LENGTH% = LEN (SAV.ALTERNATE.ID$) & \ GO TO 1349 UNLESS SEG$ (MLF.KEY1$,1%,LENGTH%) = SAV.ALTERNATE.ID$ & ! Check that the first characters of the retrieved ID equal the & ! requested ID characters. & 1310 MOVE FROM #CH.ADD%, REC$ = ADD.LEN% & \ CALL M11UPK (REC$) & \ SAV.PRIME.ID$ = ADD.PRIME.ID$ + "" & ! Unpack the address into the ADD Map area. & ! Save the primary ID since user may change it. & 1320 GO SUB 13000 & \ GO TO 1339 IF REDISPLAY% & ! Display the data & prompts. & 1333 GET #CH.ADD% & \ ADD.LEN% = RECOUNT & \ GO TO 1337 IF SEG$ (MLF.KEY1$, 1%, LENGTH%) = SAV.ALTERNATE.ID$ & ! Try to get another with the same Alternate ID. & ! If there are no more with this ID, we drop to 1335. & ! Save the address length because RECOUNT will get clobbered by gets & ! and puts to the terminal, before unpacking this address. & 1335 GO TO 1400 UNLESS MORE% & \ M11.MSG$ = "(There are NO more addresses with this Alternate ID.) " & \ MORE% = FALSE% & \ GO TO 1338 & ! Bypass the questions if there is only one match, otherwise ... & ! Tell user there ain't no more. & 1337 M11.MSG$ = "(There is at least one other address with this Alternate ID.) " & \ MORE% = TRUE% & ! Tell user about other matching addresses. & 1338 CALL M11SCW (M11.MSG$, 23%, 1%) 1339 M11.MSG$ = "Is this the address you want?" & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ CALL M11SCR (ANS$, 24%, 32%, 1%, "Y", "Y", F.END%) & \ CALL M11SCW (ERASE.EOS$, 23%, 1%) & \ GO TO 1400 IF ANS$ = "Y" & \ GO TO 1200 IF F.END% & \ GO TO 1200 IF NOT MORE% & ! Put up message and question, get answer, wipe out msg/question. & 1340 M11.MSG$ = "Do you want to see the next matching address?" & \ CALL M11SCW (M11.MSG$, 24%, 1%) & \ CALL M11SCR (ANS$, 24%, 48%, 1%, "Y", "Y", F.END%) & \ GO TO 1200 IF ANS$ = "N" OR F.END% & \ GO TO 1310 IF ANS$ = "Y" & ! Show the user another address that matches that Alternate ID? & 1345 CALL M11SCW ("Another user is using that address. Please try later.", 24%, 1%) & \ GO TO 1280 & ! Tell the user that someone else has the record. & 1347 CALL M11SCW ("Another user is using the next address.", 24%, 1%) & \ SLEEP 2% & \ MORE% = FALSE% & \ GO TO 1339 & ! Tell the user that someone else has the record. & 1349 CALL M11SCW ("An address with that ID does not exist."+BEL, 24%,1%) & \ GO TO 1270 & ! Traps here if address doesn't exist. & 1350 !-------------------------------------------------------------------- & ! & ! Change by Primary ID & ! & !-------------------------------------------------------------------- & 1355 CALL M11SCR (ANS$, 7%, 42%, 16%, "", "A", F.END%) & \ GO TO 9000 IF F.END% & \ GO TO 1260 IF ANS$ = "" & \ IF HDR.SYS.DEF.PRIME.ID$ = "Y" OR HDR.SYS.DEF.PRIME.ID$ = "1" & THEN RSET ADD.PRIME.ID$ = ANS$ & ELSE LSET ADD.PRIME.ID$ = ANS$ & ! Get the primary ID. If the system is generating IDs, & ! then right justify, else, left justify. & ! 'END' takes us to the update menu, & ! Null key entry prompts for key type. & 1360 GET #CH.ADD%, KEY #0% EQ ADD.PRIME.ID$ & \ SAV.PRIME.ID$ = ADD.PRIME.ID$ + "" & ! Try to get this address, error traps to 1580. & ! Save the PID in case the user changes it 1370 MOVE FROM #CH.ADD%, REC$ = RECOUNT & \ CALL M11UPK (REC$) & 1380 POINTER% = 20% & \ GO SUB 13000 & \ GO TO 1400 & ! Display the data & prompts. & 1390 CALL M11SCW ("Another user is using that address. Please try later.", 24%, 1%) & \ GO TO 1355 & ! Tell the user that someone else has the record. & 1400 !-------------------------------------------------------------------- & ! & ! Display & ! & !-------------------------------------------------------------------- & & GO TO 1500 IF FUNC$ = "C" & \ UNLOCK #CH.ADD% & \ M11.MSG$ = "When through with address ..." & \ GO SUB 14900 & \ GO TO 1200 & ! Wait until user is through, then go back for another display. & 1500 !-------------------------------------------------------------------- & ! & ! Change & ! & !-------------------------------------------------------------------- & & GO SUB 11500 ! Let user make changes. & \ GO TO 1320 IF REDISPLAY% AND (POINTER% = 21%) & \ GO TO 1380 IF REDISPLAY% AND (POINTER% = 20%) & 1520 GET #CH.ADD%, KEY #0% EQ SAV.PRIME.ID$ IF ACCESS$ = "A" ! Reget the current record if this is by Alternate ID, because the ! program has wiped out the pointer to the record by looking for any ! other (next) record with the same Alternate ID. 1530 IF SAV.PRIME.ID$ = ADD.PRIME.ID$ THEN CALL M11PAK (REC$) SLEN% = LEN(REC$) MOVE TO #CH.ADD%, REC$ UPDATE #CH.ADD%, COUNT SLEN% GO TO 1200 END IF ! If the primary ID has not changed just update the record. 1540 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$ = "Change" M11.MSG$ = "" GOSUB 14900 ADD.ALL$ = SAV_ADD$ GOSUB 13000 END IF 1545 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 1545 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 1550 CASE "2" GOSUB 12165 GOTO 1500 CASE "3" CALL M11SCW ("No records modified.", 24%, 1% ) SLEEP 2% END SELECT GOTO 1200 1550 FIND #CH.ADD%, KEY #0% EQ SAV.PRIME.ID$ DELETE #CH.ADD% GOSUB 14200 ! Decrement MLF total 1555 CALL M11PAK (REC$) SLEN% = LEN(REC$) MOVE TO #CH.ADD%, REC$ PUT #CH.ADD%, COUNT SLEN% GOSUB 14100 ! Increment MLF total GOTO 1200 ! The user has changed the record's primary ID. Delete the original ! record, then write out the new one. We must GET the record again ! because the FIND at line 1540 changed the file context. 1570 CALL M11SCW ("Another user is using this address. Please wait.",24%,1%) & \ SLEEP 2% & \ CALL M11SCW (ERASE.EOS$,24%,1%) & \ GO TO 1520 & ! Attempt to reget record failed becuase record is locked. Try again. & 1580 CALL M11SCW ("An address with that ID does not exist."+BEL, 24%,1%) & \ GO TO 1355 & ! Address doesn't exist. & & 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 & ! & ! & !-------------------------------------------------------------------- & & CALL M11SCD (SCR.ADDR.ENTRY%) & \ CALL M11SCW (FUNC.DPY$, 1%, 2%) & \ CALL M11SCW ("Type '?' for help", 1%, 58%) IF FUNC.DPY$ = "Change" & \ 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 & ! & ! & !-------------------------------------------------------------------- & & 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 1200 END IF ! If user typed ^C go back to the Record Selection Menu. ! This allows the user to change his mind about updating ! the 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 CALL M11SCR (NEW.NAME$, 3%, 24%, 30%, ADD.NAME$, "a", F.END%) & \ 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 ! Check out the Zip. 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$ = STR$ (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. 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% ) 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 12162 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 12162 & 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 ID 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 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. Update 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. Update 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 1345 IF ERL = 1300 AND ERR = 154 & \ RESUME 1349 IF ERL = 1300 AND (ERR = 155 OR ERR = 11) & \ RESUME 1335 IF ERL = 1333 AND ERR = 11 & \ RESUME 1347 IF ERL = 1333 AND ERR = 154 & \ RESUME 1390 IF ERL = 1360 AND ERR = 154 & \ RESUME 1580 IF ERL = 1360 AND (ERR = 155 OR ERR = 11) & \ RESUME 1570 IF ERL = 1520 AND ERR = 154 & \ RESUME 1550 IF ERL = 1540 AND ERR = 155 & \ RESUME 1550 IF ERL = 1550 AND ERR = 154 & \ RESUME 1555 IF ERL = 1555 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