_A DATABASE SYSTEM FOR AUTOMATING E-MAIL_ by Chris Ohlsen [LISTING ONE] /* You will need the Paradox Engine to compile this program. If you have */ /* placed directory for Engine in your INCLUDE path and LIBRARY path, the */ /* modules should compile fine with: tcc -ml mci parse send pxengtcl.lib */ /* Otherwise, specify where Engine header file and library files are */ /* using the -I and -L compiler switches. */ #define MCIMAIN #include #include #include #include "mci.h" void closeTables(void); void getFldNames(void); void makeTblExist(char *tblName,int nFlds,char **fld,char **types, int keyFields); void openTables(void); void shutdownEngine(void); void startEngine(void); /**** DEFINE HEADER TABLE INFORMATION ****/ char *headerFields[] = { "Date Received","Message#","Subject","From User","From ID" }; char *headerTypes[] = { "D","N","A40","A20","A8" }; int headerKeyFields = 2; #define headerNFields sizeof(headerTypes)/sizeof(char*) /**** DEFINE MESSAGE TABLE INFORMATION ****/ char *msgFields[] = { "Message#","Line#","Text" }; char *msgTypes[] = { "N","N","A80" }; int msgKeyFields = 2; #define msgNFields sizeof(msgTypes)/sizeof(char*) /**** DEFINE ROUTE TABLE INFORMATION ****/ char *routeFields[] = { "Message#","TOorCC","User Name","User ID" }; char *routeTypes[] = { "N","A5","A20","A8" }; int routeKeyFields = 3; #define routeNFields sizeof(routeTypes)/sizeof(char*) int lastPXErr; FIELDHANDLE fh[] = {1}; TABLEHANDLE headerTbl,msgTbl,routeTbl; int main(int argc,char *argv[]) { startEngine(); openTables(); getFldNames(); if (argc > 1) parse(argv[1]); /* only add to tables if filename passed in */ send(); closeTables(); shutdownEngine(); return 0; } void startEngine(void) { PXCheck(0x101,PXInit()); } void shutdownEngine(void) { PXCheck(0x110,PXExit()); } void openTables(void) { makeTblExist("Header",headerNFields,headerFields,headerTypes,headerKeyFields); makeTblExist("Message",msgNFields,msgFields,msgTypes,msgKeyFields); makeTblExist("Route",routeNFields,routeFields,routeTypes,routeKeyFields); PXCheck(0x120,PXTblOpen("Header",&headerTbl,0,0)); PXCheck(0x121,PXTblOpen("Message",&msgTbl,0,0)); PXCheck(0x122,PXTblOpen("Route",&routeTbl,0,0)); PXCheck(0x123,PXRecBufOpen(headerTbl,&headerRec)); PXCheck(0x125,PXRecBufOpen(msgTbl,&msgRec)); PXCheck(0x126,PXRecBufOpen(routeTbl,&routeRec)); } void closeTables(void) { PXCheck(0x130,PXTblClose(headerTbl)); PXCheck(0x131,PXTblClose(msgTbl)); PXCheck(0x132,PXTblClose(routeTbl)); } void getFldNames(void) { PXCheck(0x140,PXFldHandle(headerTbl,"Date Received",&hdrDateFld)); PXCheck(0x141,PXFldHandle(headerTbl,"Message#",&hdrMsgFld)); PXCheck(0x142,PXFldHandle(headerTbl,"Subject",&hdrSubjectFld)); PXCheck(0x143,PXFldHandle(headerTbl,"From User",&hdrUserFld)); PXCheck(0x144,PXFldHandle(headerTbl,"From ID",&hdrIDFld)); PXCheck(0x145,PXFldHandle(msgTbl,"Message#",&msgMsgNumFld)); PXCheck(0x146,PXFldHandle(msgTbl,"Line#",&msgLineFld)); PXCheck(0x147,PXFldHandle(msgTbl,"Text",&msgTextFld)); PXCheck(0x148,PXFldHandle(routeTbl,"Message#",&routeMsgFld)); PXCheck(0x149,PXFldHandle(routeTbl,"ToOrCC",&routeToFld)); PXCheck(0x14A,PXFldHandle(routeTbl,"User Name",&routeUserFld)); PXCheck(0x14B,PXFldHandle(routeTbl,"User ID",&routeIDFld)); return; } void makeTblExist(char *tblName,int nFlds,char **fld,char **types, int keyFields) { int exist; PXCheck(0x150,PXTblExist(tblName,&exist)); if (!exist) { PXCheck(0x151,PXTblCreate(tblName,nFlds,fld,types)); if (keyFields) PXCheck(0x152,PXKeyAdd(tblName,keyFields,fh,PRIMARY)); } return; } void PXCheck(int loc,int errCode) { lastPXErr=errCode; if(errCode==PXSUCCESS) return; switch (loc) { case 0x234: case 0x237: case 0x247: case 0x253: case 0x254: return; default: printf("Error '%s' at %04x\n",PXErrMsg(errCode),loc); exit (1); } } int PXLastErr(void) { return lastPXErr; } [LISTING TWO] #ifdef MCIMAIN #define extern #endif #define MESSAGELENGTH 90 #define STARTOFNEWMESSAGE "Date:" #define ENDOFSCRIPT "Command:" int PXLastErr(void); void PXCheck(int loc,int errCode); void send(void); void parse(char *filename); extern short MessageID; extern TABLEHANDLE headerTbl,msgTbl,routeTbl; extern RECORDHANDLE headerRec,msgRec,routeRec; extern FIELDHANDLE hdrDateFld; extern FIELDHANDLE hdrMsgFld; extern FIELDHANDLE hdrSubjectFld; extern FIELDHANDLE hdrUserFld; extern FIELDHANDLE hdrIDFld; extern FIELDHANDLE msgMsgNumFld; extern FIELDHANDLE msgLineFld; extern FIELDHANDLE msgTextFld; extern FIELDHANDLE routeMsgFld; extern FIELDHANDLE routeToFld; extern FIELDHANDLE routeUserFld; extern FIELDHANDLE routeIDFld; [LISTING THREE] #include #include #include #include #include "mci.h" void getCC(FILE *inMsgFp,char inBuffer[],int msgID); void getHeaderInfo(FILE *inMsgFp,char inBuffer[],int msgID); short getNextMsgID(short *MessageID); void getTo(FILE *inMsgFp,char inBuffer[],int msgID); void parseAddr(char inBuffer[],char Person[],char ID[]); void parseDate(char *dateStr); void whoFrom(FILE *inMsgFp,char inBuffer[],int msgID); int convertMonth(char *str); void parse(char *filename) { FILE *inMsgFp; char inBuffer[MESSAGELENGTH+1]; short LineNumber; if ((inMsgFp = fopen(filename,"r")) == NULL) { perror(filename); PXExit(); return; } /* Parse through text file searching for first MCI message. */ while (fgets(inBuffer,MESSAGELENGTH,inMsgFp)) if(strstr(inBuffer,STARTOFNEWMESSAGE) == inBuffer) break; do { /* If STARTOFNEWMESSAGE is at beginning of current line, save last */ /* message and get remainder of header information for the message. */ /* Otherwise, keep getting text. */ if (strstr(inBuffer,ENDOFSCRIPT) == inBuffer) break; /* Reached end of messages */ if (strstr(inBuffer,STARTOFNEWMESSAGE) == inBuffer) { LineNumber = 1; getNextMsgID(&MessageID); getHeaderInfo(inMsgFp,inBuffer,MessageID); } if (strlen(inBuffer) > 0 && inBuffer[strlen(inBuffer)-1] == '\n') inBuffer[strlen(inBuffer)-1] = '\0'; PXCheck(0x300,PXPutAlpha(msgRec,msgTextFld,inBuffer)); PXCheck(0x301,PXPutShort(msgRec,msgLineFld,LineNumber++)); PXCheck(0x302,PXPutShort(msgRec,msgMsgNumFld,MessageID)); PXCheck(0x303,PXRecAppend(msgTbl,msgRec)); }while (fgets(inBuffer,MESSAGELENGTH,inMsgFp)); fclose(inMsgFp); return; } void getHeaderInfo(FILE *inMsgFp,char inBuffer[],int msgID) { char subject[41],dummy[1]; parseDate(inBuffer); whoFrom(inMsgFp,inBuffer,msgID); /*Skip the Blank Line*/ fgets(inBuffer,MESSAGELENGTH,inMsgFp); /*Skip the First TO: line (ignore address to self) */ fgets(inBuffer,MESSAGELENGTH,inMsgFp); getTo(inMsgFp,inBuffer,msgID); getCC(inMsgFp,inBuffer,msgID); parseAddr(inBuffer,subject,dummy); PXCheck(0x330,PXPutAlpha(headerRec,hdrSubjectFld,subject)); PXCheck(0x331,PXRecAppend(headerTbl,headerRec)); /* Skip blank lines */ fgets(inBuffer,MESSAGELENGTH,inMsgFp); fgets(inBuffer,MESSAGELENGTH,inMsgFp); } void getTo(FILE *inMsgFp,char inBuffer[],int msgID) { char person[MESSAGELENGTH+1]; char id[MESSAGELENGTH+1]; while (fgets(inBuffer,MESSAGELENGTH,inMsgFp) && strstr(inBuffer,"TO") || strstr(inBuffer,"EMS")) { parseAddr(inBuffer,person,id); PXCheck(0x310,PXPutAlpha(routeRec,routeUserFld,person)); PXCheck(0x311,PXPutAlpha(routeRec,routeIDFld,id)); PXCheck(0x312,PXPutShort(routeRec,msgMsgNumFld,msgID)); PXCheck(0x313,PXPutAlpha(routeRec,routeToFld,"TO")); PXCheck(0x314,PXRecAppend(routeTbl,routeRec)); } } void getCC(FILE *inMsgFp,char inBuffer[],int msgID) { char person[MESSAGELENGTH+1]; char id[MESSAGELENGTH+1]; while (strstr(inBuffer,"CC")) { parseAddr(inBuffer,person,id); PXCheck(0x320,PXPutAlpha(routeRec,routeUserFld,person)); PXCheck(0x321,PXPutAlpha(routeRec,routeIDFld,id)); PXCheck(0x322,PXPutShort(routeRec,msgMsgNumFld,msgID)); PXCheck(0x323,PXPutAlpha(routeRec,routeToFld,"CC")); PXCheck(0x324,PXRecAppend(routeTbl,routeRec)); fgets(inBuffer,MESSAGELENGTH,inMsgFp); } } void whoFrom(FILE *inMsgFp,char inBuffer[],int msgID) { char person[MESSAGELENGTH+1]; char id[MESSAGELENGTH+1]; fgets(inBuffer,MESSAGELENGTH,inMsgFp); parseAddr(inBuffer,person,id); printf("From: %s\n",person); printf("MCI ID: %s\n",id); PXCheck(0x350,PXPutAlpha(headerRec,hdrIDFld,id)); PXCheck(0x351,PXPutAlpha(headerRec,hdrUserFld,person)); PXCheck(0x352,PXPutShort(headerRec,hdrMsgFld,msgID)); } void parseAddr(char *inBuffer,char *person,char *id) { char *p; char *s = person; if ((p = strchr(inBuffer,':'))!=NULL) { while (*(++p) == ' ' || *p == '*') ; while ( (*s++ = *p++) != '/' && *p) ; *(--s) = '\0'; } s = id; if ((p = strchr(p,':'))!=NULL) { while ( *(++p) == ' ') ; while ( (*s++ = *p++) != '\n') ; *(--s) = '\0'; } } short getNextMsgID(short *msgID) { RECORDNUMBER nRecs; PXCheck(0x360,PXTblNRecs(msgTbl,&nRecs)); if (nRecs == 0) *msgID = 1; else { PXCheck(0x370,PXRecLast(msgTbl)); PXCheck(0x371,PXRecGet(msgTbl,msgRec)); PXCheck(0x372,PXGetShort(msgRec,msgMsgNumFld,msgID)); ++(*msgID); } return(*msgID); } void parseDate(char *dateStr) { char *mon,*day,*year; int iMon,iDay,iYear; long engDate; strtok(dateStr," "); strtok(NULL," "); mon=strtok(NULL," "); day=strtok(NULL," "); year=strtok(NULL," "); if((iMon=convertMonth(mon))==0) PXCheck(0x380,PXERR_INVDATE); iDay=atoi(day); iYear=atoi(year); PXCheck(381,PXRecBufEmpty(headerRec)); PXCheck(382,PXDateEncode(iMon,iDay,iYear,&engDate)); PXCheck(383,PXPutDate(headerRec,hdrDateFld,engDate)); } int convertMonth(char *str) { switch (str[0]) { case 'A': switch (str[1]) { case 'p': return 4; /* April */ case 'u': return 8; /* August */ } case 'D': return 12; /* December */ case 'F': return 2; /* February */ case 'J': switch (str[1]) { case 'a': return 1; /* January */ case 'u': switch (str[2]) { case 'l': return 7; /* July */ case 'n': return 6; /* June */ } } case 'M': switch (str[2]) { case 'r': return 3; /* March */ case 'y': return 5; /* May */ } case 'N': return 11; /* November */ case 'S': return 9; /* September */ case 'O': return 10; /* October */ } return 0; } [LISTING FOUR] #include #include #include #include "mci.h" void createIndex(TABLEHANDLE *tbl,FIELDHANDLE fld[3]); void processMany(FILE *fp,FIELDHANDLE f[3],TABLEHANDLE t,int pn,char *st); void processFile(FILE *fp,FIELDHANDLE f[3],TABLEHANDLE t,int pn); void nextPendNum(TABLEHANDLE t,FIELDHANDLE f,short *pn); #define PENDFIELD 0 #define ACTFIELD 1 #define TEXTFIELD 2 void send(void) { TABLEHANDLE tbl; FIELDHANDLE flds[3]; FILE *output; int exists; short pendNum; PXCheck(0x200,PXTblExist("Pending",&exists)); if(!exists) return; createIndex(&tbl,flds); PXCheck(0x201,PXTblOpen("Pending",&tbl,0,0)); pendNum=1; output=fopen("mci-send.txt","wt"); if(output==NULL) { perror("mci-send.txt"); exit(1); } do { fprintf(output,"\ncr\n"); processMany(output,flds,tbl,pendNum,"TO"); fputs("\n",output); processMany(output,flds,tbl,pendNum,"CC"); fputs("\n",output); processMany(output,flds,tbl,pendNum,"Subject"); processFile(output,flds,tbl,pendNum); fputs("\n/\n\n\Yes\n",output); nextPendNum(tbl,flds[PENDFIELD],&pendNum); }while(pendNum>0); fputs("exit\n",output); fclose(output); PXCheck(0x202,PXTblClose(tbl)); PXCheck(0x203,PXTblDelete("Pending")); return; } void createIndex(TABLEHANDLE *tbl,FIELDHANDLE fld[3]) { PXCheck(0x210,PXTblOpen("Pending",tbl,0,0)); PXCheck(0x211,PXFldHandle(*tbl,"Pending#",&fld[PENDFIELD])); PXCheck(0x212,PXFldHandle(*tbl,"Action",&fld[ACTFIELD])); PXCheck(0x213,PXFldHandle(*tbl,"Text",&fld[TEXTFIELD])); PXCheck(0x214,PXTblClose(*tbl)); PXCheck(0x215,PXKeyAdd("Pending",1,&fld[ACTFIELD],SECONDARY)); } void processMany(FILE *fp,FIELDHANDLE f[3],TABLEHANDLE t,int pn,char *st) { char txtSt[81]; RECORDHANDLE srchRec,rec; PXCheck(0x230,PXRecBufOpen(t,&rec)); PXCheck(0x231,PXRecBufOpen(t,&srchRec)); PXCheck(0x232,PXPutShort(srchRec,f[PENDFIELD],pn)); PXCheck(0x233,PXPutAlpha(srchRec,f[ACTFIELD],st)); PXCheck(0x234,PXSrchKey(t,srchRec,2,SEARCHFIRST)); while(PXLastErr()==PXSUCCESS) { PXCheck(0x235,PXRecGet(t,rec)); PXCheck(0x236,PXGetAlpha(rec,f[TEXTFIELD],sizeof(txtSt),txtSt)); fprintf(fp,"%s\n",txtSt); PXCheck(0x237,PXSrchKey(t,srchRec,2,SEARCHNEXT)); } PXCheck(0x238,PXRecBufClose(rec)); PXCheck(0x239,PXRecBufClose(srchRec)); } void processFile(FILE *fp,FIELDHANDLE f[3],TABLEHANDLE t,int pn) { char txtSt[81],fname[21]; FILE *inFp; RECORDHANDLE srchRec,rec; PXCheck(0x240,PXRecBufOpen(t,&rec)); PXCheck(0x241,PXRecBufOpen(t,&srchRec)); PXCheck(0x242,PXPutShort(srchRec,f[PENDFIELD],pn)); PXCheck(0x243,PXPutAlpha(srchRec,f[ACTFIELD],"Filename")); PXCheck(0x244,PXSrchKey(t,srchRec,2,SEARCHFIRST)); while(PXLastErr()==PXSUCCESS) { PXCheck(0x245,PXRecGet(t,rec)); PXCheck(0x246,PXGetAlpha(rec,f[TEXTFIELD],sizeof(fname),fname)); if((inFp=fopen(fname,"rt"))==NULL) { perror(fname); exit(1); } while(fgets(txtSt,80,inFp)!=NULL) fputs(txtSt,fp); fclose(inFp); unlink(fname); PXCheck(0x247,PXSrchKey(t,srchRec,2,SEARCHNEXT)); } PXCheck(0x248,PXRecBufClose(rec)); PXCheck(0x249,PXRecBufClose(srchRec)); } void nextPendNum(TABLEHANDLE t,FIELDHANDLE f,short *pn) { RECORDHANDLE r; PXCheck(0x250,PXRecBufOpen(t,&r)); PXCheck(0x251,PXPutShort(r,f,*pn)); PXCheck(0x252,PXSrchKey(t,r,1,SEARCHFIRST)); while(PXLastErr()==PXSUCCESS) PXCheck(0x253,PXSrchKey(t,r,1,SEARCHNEXT)); PXCheck(0x254,PXRecNext(t)); if(PXLastErr()==PXSUCCESS) { PXCheck(0x255,PXRecGet(t,r)); PXCheck(0x256,PXGetShort(r,f,pn)); PXCheck(0x257,PXRecBufClose(r)); } else *pn=0; } [LISTING FIVE] editor = "ED" ; Change this to your word processor PROC BuildHdrForm() {Forms} {Design} {Header} {2} {Brief Header} ; Design form for HEADER " Date Recvd From Subject" ; Place text... Enter " ----------- -------------------- ----------------------------------------" Enter " " Menu {Field} {Place} {Regular} {Date Received} ; Place DATE field Enter Enter Right Menu {Field} {Place} {Regular} {From User} ; Place FROM USER field Enter Enter Right Menu {Field} {Place} {Regular} {Subject} ; Place SUBJECT field Enter Enter CtrlHome Menu {Multi} {Records} {Define} ; Define as MultiRecord Enter Left Enter Down Down Down Down Down Down Down Enter Do_It! ; Save this form ENDPROC ; BuildHdrForm PROC BuildMsgForms() {Forms} {Design} {Message} {1} {Message Body} ; Design form for MESSAGE MENU {Field} {Place} {Regular} {Line#} ; Place LINE# field ENTER LEFT LEFT LEFT LEFT LEFT LEFT LEFT LEFT LEFT LEFT; Truncate field size LEFT LEFT LEFT LEFT LEFT LEFT LEFT LEFT LEFT LEFT LEFT LEFT LEFT ENTER MENU {Field} {Place} {Regular} {Text} ; Place TEXT field RIGHT ENTER ENTER MENU {Multi} {Records} {Define} ; Define as MultiRecord fields ENTER LEFT ENTER DOWN DOWN DOWN DOWN DOWN DOWN DOWN DOWN ENTER ; The next four lines set up the position and color for hiding the line# ; field. It currently sets the color to a light grey on light grey. HOME CTRLHOME MENU {Style} {Color} {Area} ENTER DOWN DOWN DOWN DOWN DOWN DOWN DOWN DOWN ENTER RIGHT RIGHT RIGHT RIGHT RIGHT RIGHT RIGHT ENTER DO_IT! ; Save this form {Forms} {Design} {Header} {1} {Message} ; Design for for HEADER table ENTER " Date Received " ; Set up position and text MENU {Field} {Place} {Regular} {Date Received} ; Place DATE RECEIVED field ENTER ENTER ENTER " Subject ..... " ; Set up position and text MENU {Field} {Place} {Regular} {Subject} ; Place SUBJECT field ENTER ENTER ENTER " From ........ " ; Set up position and text MENU {Field} {Place} {Regular} {From User} ; Place FROM USER field ENTER ENTER MENU {Multi} {Tables} {Place} ; Place MultiTable Linked Form from {Linked} {Message} {1} {Message#} ; MESSAGE table. UP UP UP UP UP UP UP UP UP ENTER ; Position the field DO_IT! ; Save this form ENDPROC ; BuildMsgForms PROC MenuScrn() CANVAS OFF @4,0 SETMARGIN 25 PAINTCANVAS ATTRIBUTE 31 2,0,24,79 ; Fill Background w/White on Blue PAINTCANVAS ATTRIBUTE 0 5,27,8,54 ; Shadow Box in Black STYLE ATTRIBUTE 7 TEXT ---------------------------- | MCI Message System | | | ---------------------------- ENDTEXT SETMARGIN 0 @22,0 TEXT ---------------------------------------------------------------------------- Use Cursor Keys <- -> To Move Between Menu Choices, or 1st Character ---------------------------------------------------------------------------- ENDTEXT PAINTCANVAS ATTRIBUTE 31 22,0,24,79 CANVAS ON ENDPROC ; MenuScrn PROC Inbox() IF ( ISEMPTY("Header") ) THEN @ 20,27 ?? "No messages to be viewed" RETURN ENDIF VIEW "Header" PICKFORM 2 WAIT TABLE PROMPT "Arrow to message, press RETURN to view.", "ESC aborts to main menu." UNTIL "Enter", "Esc" SWITCH CASE retval = "Enter" : ViewMessage() CASE retval = "Esc" : CLEAR CLEARALL RETURN ENDSWITCH ENDPROC ; Inbox PROC ViewMessage() PICKFORM 1 DOWNIMAGE WHILE (TRUE) WAIT TABLE PROMPT "F3/F4 move to Previous/Next message. INS responds to message.", "Arrow keys scroll the current message. ESC aborts to main menu." UNTIL "Esc", "F3", "F4", "Ins" SWITCH CASE retval = "Ins": Respond(); PICKFORM 1 DOWNIMAGE CASE retval = "F3": UPIMAGE PGUP DOWNIMAGE CASE retval = "F4": UPIMAGE PGDN DOWNIMAGE CASE retval = "Esc": QUITLOOP ENDSWITCH ENDWHILE CLEAR CLEARALL ENDPROC ; ViewMessage PROC CheckPending() IF ( NOT ISTABLE("Pending") ) THEN CREATE "Pending" "Pending#" : "N*", "Action" : "A8*", "Text" : "A40*" RETURN 1 ELSE IF ( ISEMPTY("Pending") ) THEN RETURN 1 ELSE RETURN CMAX("Pending","Pending#") + 1 ENDIF ENDIF ENDPROC ; CheckPending PROC Respond() UPIMAGE mnum = [Message#] subject = [Subject] from = [From ID] pnum = CheckPending() QUERY Route | Message# | TOorCC | User Name | User ID | | ~mnum | Check | | Check | | | | | | | | | | | ENDQUERY DO_IT! VIEW "Answer" IF ( ISEMPTY("Answer") ) THEN answerTable=TRUE ELSE answerTable=FALSE ENDIF VIEW "Pending" EDIT "Pending" END DOWN [Pending#] = pnum [Action] = "Filename" [Text] = "Pending." + STRVAL(pnum) DOWN [Pending#] = pnum [Action] = "Subject" [Text] = "RE:" + subject DOWN [Pending#] = pnum [Action] = "TO" [Text] = from DOWN UPIMAGE IF ( NOT answerTable ) THEN WHILE ( TRUE ) to_cc = [TOorCC] uid = [User ID] DOWNIMAGE [Pending#] = pnum [Action] = to_cc [Text] = uid DOWN UPIMAGE IF ( ATLAST() ) THEN QUITLOOP ENDIF DOWN ENDWHILE ENDIF DO_IT! RUN BIG editor + " Pending." + STRVAL(pnum) CLEAR CLEARIMAGE ; Close the Pending Table CLEARIMAGE ; Close the Answer Table UPIMAGE CLEARIMAGE ; Close Route Query Table ENDPROC ; Respond() PROC Compose() pnum = CheckPending() VIEW "Pending" EDIT "Pending" END DOWN [Pending#] = pnum [Action] = "Filename" [Text] = "Pending." + STRVAL(pnum) DOWN CLEAR @ 0,0 GetMultiple("TO",TRUE); IF ( NOT retval ) THEN CANCELEDIT CLEAR CLEARALL RETURN ENDIF GetMultiple("CC",FALSE); IF ( NOT retval ) THEN CANCELEDIT CLEAR CLEARALL RETURN ENDIF sub = "" WHILE( LEN(sub) = 0 ) ? "Subject: " ACCEPT "A40" to sub IF ( NOT retval ) THEN CANCELEDIT CLEAR CLEARALL RETURN ENDIF ENDWHILE [Pending#] = pnum [Action] = "Subject" [Text] = sub DO_IT! RUN BIG editor + " Pending." + STRVAL(pnum) CLEAR CLEARALL ENDPROC ; Compose PROC GetMultiple(where,one) IF (one) THEN name = "" WHILE ( LEN(name) = 0 ) ; Loop until at least one [where] field ? where + ": " ; has been input. ACCEPT "A20" TO name IF ( NOT retval ) THEN ; Esc was pressed RETURN FALSE ENDIF ENDWHILE [Pending#] = pnum [Action] = where [Text] = name DOWN ENDIF WHILE (TRUE) ? where + ": " ACCEPT "A20" TO name IF ( NOT retval ) THEN ; Esc was pressed RETURN FALSE ENDIF IF ( LEN(name) = 0 ) THEN QUITLOOP ENDIF [Pending#] = pnum [Action] = where [Text] = name DOWN ENDWHILE RETURN TRUE ENDPROC ; GetMultiple PROC Main() WHILE (TRUE) Menuscrn() SHOWMENU "Inbox" : "View Current Messages", "Compose": "Compose a new Message", "Quit" : "Quit the MCI Message System" TO choice SWITCH CASE choice = "Inbox" : Inbox() CASE choice = "Compose" : Compose() CASE choice = "Quit" : SHOWMENU "No" : "Do NOT Quit The Application.", "Yes" : "Quit The Application." TO theexit IF ( theexit = "Yes" ) THEN MENU {Exit} {Yes} ENDIF ENDSWITCH ENDWHILE ENDPROC ; Main ;**** Mainline **** RESET CLEAR CLEARALL IF ( NOT ISTABLE("Message") ) OR ( NOT ISTABLE("Header") ) OR ( NOT ISTABLE("Route") ) THEN @ 12,17 ?? "You must run MCI.EXE before running this script" SLEEP 5000 RETURN ENDIF IF ( NOT ISFILE("Header.F1") ) OR ( NOT ISFILE("Message.F1") ) THEN BuildMsgForms(); ENDIF IF ( NOT ISFILE("Header.F2") ) THEN BuildHdrForm(); ENDIF Main()