pc@ukc.ac.uk (R.P.A.Collinson) (02/02/91)
These diffs allow you to see when you have replied or forwarded mail by making a note at the top of the source message(s). Regular mh does this and I have long wanted xmh to do this too. The diffs have been sent into MIT - who told me that they will use them but will not distribute them at this time. I am unsure what news group(s) is/are appropriate so I am guessing - please forgive me if you consider this is unwarranted intrusion into your conversation. The diffs permit the `standard' xmh release with X11R4 to annotate messages that have been replied to or forwarded. I have tested this ONLY with mh6.7 on a Sparc 1+ running SunOs 4.1 and OpenWindows2. Annotation is controlled by resources - see the manual page. Annotation will not SHOW if a currently displayed message is annotated. Most of the work is done in a new file `anno.c', this also contains the theory of behaviour. Most of the other changes just insert code to call the appropriate code. PS. If anyone has fixed the problem where xmh current message is not that the same as that shown by mhpath cur - then please let me know. ------ patch away from here ------ *** /dev/null Wed Jan 2 22:32:51 1991 --- anno.c Sun Dec 23 21:14:56 1990 *************** *** 0 **** --- 1,271 ---- + /* + * anno.c + * - routines concerned with annotation + * File added by Peter Collinson, Hillside Systems + * pc@hillside.co.uk + */ + + /* + * Background + * mh6.7 uses various environment variables to permit message + * annotation. + * + * a) mhfolder + * contains the name of the folder to be annotated + * b) mhmessages + * space separated list of messages to annotate + * c) mhannotate + * text to use for annotation + * d) mhinplace + * 1 to annotate inplace + * 0 not to + * + * Theory + * Add a character string to a Scrn containing the message list + * for annotation. + * When send is called push the various objects into the + * environment + */ + #include "xmh.h" + #include "tocintrnl.h" + + static int MheLookup(); + static Scrn AnnoSearch(); + static char *MakeEnv(); + + /* + * Given a message - create an annotation list and + * return it + */ + char * + AnnoMsgCreate(msg) + Msg msg; + { + MsgListRec ml; + char *AnnoCreate(); + + ml.nummsgs = 1; + ml.msglist = &msg; + return (AnnoCreate(&ml)); + } + + /* + * given an mlist - create an annotation list + * and return it - the first element in the list is the + * name of the folder + * + */ + char * + AnnoCreate(mlist) + MsgList mlist; + { + char *anno; + char *folder; + int bytes; + register int d; + register int i; + char *src; + char numbuf[16]; + + if (mlist->nummsgs == 0) + return (NULL); + + folder = mlist->msglist[0]->toc->foldername; + anno = (char *)XtMalloc(512); + bytes = 512; + for (d = 0, src = app_resources.mail_path; anno[d++] = *src++;); + anno[d-1] = '/'; + for (src = folder; anno[d++] = *src++;); + d--; + + + for (i = 0; i < mlist->nummsgs; i++) + { + (void) sprintf(numbuf, "%d", mlist->msglist[i]->msgid); + + if (d+16 > bytes) + { bytes += 512; + anno = (char *)XtRealloc(anno, bytes); + } + /* add a space */ + anno[d++] = ' '; + for (src = numbuf; anno[d++] = *src++;); + d--; + } + anno[d] = '\0'; + return (anno); + } + + /* + * We will need to add and delete four things from + * the environment. This could be done after the fork() + * but this means that we have to change the environment + * to be sure of not affecting any other programs + * + * So the idea here is to copy the environment into our vector + * deleting the four things that we are interested in + * we then put OUR things in the first four string positions + */ + static char **our_env; /* this points at our environment */ + extern char **environ; /* what the world sees */ + + typedef struct addenv + { char *add; + int len; + } Addenv; + + static Addenv adde[] = + { + { "mhfolder=", 9 }, + { "mhmessages=", 11 }, + { "mhannotate=", 11 }, + { "mhinplace=", 10 }, + { NULL, 0 } + }; + + #define MHE_FOLDER 0 + #define MHE_MESSAGES 1 + #define MHE_ANNOTATE 2 + #define MHE_INPLACE 3 + + AnnoInitEnv() + { + register int count; /* number of things in the environment */ + register char **pt; + register char **dst; + char inp[16]; + + + if (our_env) + return; + + for (count = 0, pt = environ; *pt++; count++); + + our_env = (char **)XtMalloc((count+5)*sizeof (char **)); + our_env[0] = our_env[1] = our_env[2] = NULL; + + /* copy the environment into `our' environment */ + /* start at position 4 */ + dst = &our_env[4]; + + for (pt = environ; *pt; pt++) + { + if (MheLookup(*pt)) + continue; + *dst++ = *pt; + } + *dst = NULL; + /* + * set up the inplace value + */ + (void) sprintf(inp, "%s%d", adde[MHE_INPLACE].add, app_resources.annotate_in_place); + our_env[MHE_INPLACE] = XtNewString(inp); + } + + /* + * Look in the list of things we are dealing with + * to find a match in the environment + */ + static int + MheLookup(env) + char *env; + { + register Addenv *ae; + + for (ae = adde; ae->add; ae++) + if (strncmp(env, ae->add, ae->len) == 0) + return(1); + return 0; + } + + /* + * Reset the environment to the standard + */ + AnnoEnvReset() + { + environ = &our_env[4]; + } + + /* + * Set the environment to new values + */ + AnnoEnvSet(msg) + Msg msg; + { + Scrn scrn; + char *folder; + char *annotate; + char *s; + char *d; + register i; + Scrn AnnoSearch(); + char buf[512]; + + if ((scrn = AnnoSearch(msg)) == NULL) + return; + + switch (scrn->anno_type) + { + case ANrepl: + annotate = "Replied"; + break; + case ANforw: + annotate = "Forwarded"; + break; + default: /* shouldn't happen */ + return; + } + + for (i = 0; i < MHE_INPLACE; i++) + if (our_env[i]) + { XtFree(our_env[i]); + our_env[i] = NULL; + } + /* + * Munge the annotation list + * we see it as + * folder-name number number + */ + for (s = scrn->anno_list, d = buf; *s != ' '; *d++ = *s++); + *d = '\0'; + s++; + + our_env[MHE_FOLDER] = MakeEnv(&adde[MHE_FOLDER], buf); + our_env[MHE_MESSAGES] = MakeEnv(&adde[MHE_MESSAGES], s); + our_env[MHE_ANNOTATE] = MakeEnv(&adde[MHE_ANNOTATE], annotate); + environ = our_env; + } + + static Scrn + AnnoSearch(msg) + Msg msg; + { + register i; + AnnoKind ak; + + if (msg->num_scrns == 0) + return (NULL); + + for (i = 0; i < msg->num_scrns; i++) + { + if ((ak = msg->scrn[i]->anno_type) == ANrepl) + return(msg->scrn[i]); + else + if (ak == ANforw) + return(msg->scrn[i]); + } + return (NULL); + } + + + + static char * + MakeEnv(ad, value) + register Addenv *ad; + char *value; + { + char buf[512]; + + (void) sprintf(buf, "%s%s", ad->add, value); + return (XtNewString(buf)); + } *** Imakefile~ Wed Jan 2 22:36:59 1991 --- Imakefile Sun Dec 23 21:15:33 1990 *************** *** 8,17 **** SRCS = bbox.c command.c compfuncs.c folder.c icon.c init.c \ main.c menu.c mlist.c msg.c pick.c popup.c screen.c \ ! toc.c tocfuncs.c tocutil.c tsource.c util.c viewfuncs.c OBJS = bbox.o command.o compfuncs.o folder.o icon.o init.o \ main.o menu.o mlist.o msg.o pick.o popup.o screen.o \ ! toc.o tocfuncs.o tocutil.o tsource.o util.o viewfuncs.o ComplexProgramTarget(xmh) --- 8,17 ---- SRCS = bbox.c command.c compfuncs.c folder.c icon.c init.c \ main.c menu.c mlist.c msg.c pick.c popup.c screen.c \ ! toc.c tocfuncs.c tocutil.c tsource.c util.c viewfuncs.c anno.c OBJS = bbox.o command.o compfuncs.o folder.o icon.o init.o \ main.o menu.o mlist.o msg.o pick.o popup.o screen.o \ ! toc.o tocfuncs.o tocutil.o tsource.o util.o viewfuncs.o anno.o ComplexProgramTarget(xmh) *** compfuncs.c~ Wed Jan 2 22:39:07 1991 --- compfuncs.c Sun Dec 23 21:15:33 1990 *************** *** 117,122 **** --- 117,124 ---- { Scrn scrn; Msg msg; + char *AnnoCreate(); + scrn = NewCompScrn(); msg = TocMakeNewMsg(DraftsFolder); MsgLoadForward(scrn, msg, mlist); *************** *** 123,126 **** --- 125,133 ---- MsgSetTemporary(msg); MsgSetScrnForComp(msg, scrn); MapScrn(scrn); + if (app_resources.annotate_forw) { + scrn->anno_type = ANforw; + scrn->anno_list = AnnoCreate(mlist); + } + } *** globals.h~ Wed Jan 2 22:40:33 1991 --- globals.h Sun Dec 23 21:15:31 1990 *************** *** 76,81 **** --- 76,84 ---- int command_button_count; /* number of buttons in command box */ int app_defaults_version; /* for sanity check */ char *banner; /* defaults to xmh version string */ + Boolean annotate_repl; /* true if we are to annotate reply sources */ + Boolean annotate_forw; /* true if we are to annotate forw sources */ + int annotate_in_place; /* 0 if don't annotate inplace, 1 otherwise */ } app_resources; ext char *draftFile; /* Filename of draft. */ *** init.c~ Wed Jan 2 22:40:54 1991 --- init.c Sun Dec 23 21:15:31 1990 *************** *** 124,129 **** --- 124,135 ---- offset(app_defaults_version), XtRImmediate, (XtPointer)0}, {"banner", "Banner", XtRString, sizeof(char *), offset(banner), XtRString, "xmh MIT X Consortium R4"}, + {"annotateRepl", "AnnotateRepl", XtRBoolean, sizeof(Boolean), + offset(annotate_repl), XtRImmediate, (XtPointer)False}, + {"annotateForw", "AnnotateForw", XtRBoolean, sizeof(Boolean), + offset(annotate_forw), XtRImmediate, (XtPointer)False}, + {"annotateInPlace", "AnnotateInPlace", XtRInt, sizeof(int), + offset(annotate_in_place), XtRImmediate, (XtPointer)1}, }; #undef offset *************** *** 396,401 **** --- 402,413 ---- InitPick(); IconInit(); BBoxInit(); + + /* + * Initialise annotations if required + */ + if (app_resources.annotate_repl || app_resources.annotate_forw) + AnnoInitEnv(); XtAppAddActions( XtWidgetToApplicationContext(toplevel), actions, XtNumber(actions)); *** msg.c~ Wed Jan 2 22:41:05 1991 --- msg.c Sun Dec 23 21:15:32 1990 *************** *** 731,736 **** --- 731,737 ---- } (void) myfclose(from); (void) myfclose(to); + AnnoEnvSet(msg); argv = MakeArgv(3); argv[0] = "send"; argv[1] = "-push"; *************** *** 737,742 **** --- 738,744 ---- argv[2] = str; DoCommand(argv, (char *) NULL, (char *) NULL); XtFree((char *) argv); + AnnoEnvReset(); } *** screen.c~ Wed Jan 2 22:41:14 1991 --- screen.c Sun Dec 23 21:15:31 1990 *************** *** 391,396 **** --- 391,398 ---- Scrn scrn; scrn = CreateNewScrn(STcomp); scrn->assocmsg = (Msg)NULL; + scrn->anno_type = ANno; + scrn->anno_list = NULL; return scrn; } *************** *** 412,417 **** --- 414,423 ---- TocSetScrn((Toc) NULL, scrn); MsgSetScrnForce((Msg) NULL, scrn); lastInput.win = -1; + if (scrn->anno_list) { + XtFree(scrn->anno_list); + scrn->anno_list = NULL; + } } } *** tocfuncs.c~ Wed Jan 2 22:41:25 1991 --- tocfuncs.c Sun Dec 23 21:15:32 1990 *************** *** 651,656 **** --- 651,657 ---- Scrn nscrn; MsgList mlist; Msg msg; + char *AnnoMsgCreate(); if (toc == NULL) return; mlist = CurMsgListOrCurMsg(toc); *************** *** 657,662 **** --- 658,667 ---- if (mlist->nummsgs) { nscrn = NewCompScrn(); ScreenSetAssocMsg(nscrn, mlist->msglist[0]); + if (app_resources.annotate_repl) + { nscrn->anno_type = ANrepl; + nscrn->anno_list = AnnoMsgCreate(mlist->msglist[0]); + } msg = TocMakeNewMsg(DraftsFolder); MsgSetTemporary(msg); MsgLoadReply(msg, mlist->msglist[0]); *** viewfuncs.c~ Wed Jan 2 22:41:38 1991 --- viewfuncs.c Sun Dec 23 21:15:32 1990 *************** *** 76,85 **** --- 76,90 ---- Scrn scrn = (Scrn) client_data; Msg msg; Scrn nscrn; + char *AnnoMsgCreate(); if (scrn->msg == NULL) return; nscrn = NewCompScrn(); ScreenSetAssocMsg(nscrn, scrn->msg); + if (app_resources.annotate_repl) + { nscrn->anno_type = ANrepl; + nscrn->anno_list = AnnoMsgCreate(scrn->msg); + } msg = TocMakeNewMsg(DraftsFolder); MsgSetTemporary(msg); MsgLoadReply(msg, scrn->msg); *** xmh.h~ Wed Jan 2 22:41:57 1991 --- xmh.h Sun Dec 23 21:15:31 1990 *************** *** 90,95 **** --- 90,101 ---- STpick } ScrnKind; + typedef enum { + ANno, + ANrepl, + ANforw + } AnnoKind; + typedef struct _StackRec { char *data; struct _StackRec *next; *************** *** 119,124 **** --- 125,132 ---- Msg assocmsg; /* Associated message for reply, etc. */ Window wait_window; /* InputOnly window with busy cursor */ Stack folder_stack; /* Stack of folder names */ + AnnoKind anno_type; /* type of annotation */ + char * anno_list; /* list of messages to annotate */ } ScrnRec, *Scrn; *** xmh.man~ Wed Jan 2 22:42:07 1991 --- xmh.man Mon Dec 24 12:02:12 1990 *************** *** 921,926 **** --- 921,946 ---- The following resources are defined: .TP 8 + .B AnnotateRepl + Permits annotation of messages that are being replied to. + This uses the standard + .I mh + mechanism in + .IR send . + Default is false. + .TP 8 + .B AnnotateForw + Permits annotation of messages that are being forwarded. + This uses the standard + .I mh + mechanism in + .IR send . + Default is false. + .TP + .B AnnotateInPlace + When set to non-zero causes annotation to be done in place to preserve + links to the annotated message. + .TP 8 .B Banner A short string that is the default label of the folder, Table of Contents, and view. The default is "xmh MIT X Consortium R4". *************** *** 1241,1243 **** --- 1261,1265 ---- Terry Weissman, Digital Western Research Laboratory .br modified by Donna Converse, MIT X Consortium + .br + Annotation code by Peter Collinson, Hillside Systems
pc@ukc.ac.uk (R.P.A.Collinson) (02/15/91)
(**Contains bug fix to previous posting that must be applied**) These diffs allow you to see when you have replied or forwarded mail by making a note at the top of the source message(s). Regular mh does this and I have long wanted xmh to do this too. The diffs have been sent into MIT - who told me that they will use them but will not distribute them at this time. I regret that this is a second release of this. The first release broke xmh for people who DIDN'T want to annotate their mail. There are two files here: if you have installed the previous patches (<2485@ukc>) then you need to apply `bug_patch'. If not, throw bug_patch away and patch with the Diffs file. Apologies for this reposting - but it does seem sensible to keep all this together in one file. The diffs permit the `standard' xmh release with X11R4 to annotate messages that have been replied to or forwarded. I have tested this ONLY with mh6.7. Annotation is controlled by resources - see the manual page. Annotation will not SHOW if a currently displayed message is annotated. Most of the work is done in a new file `anno.c', this also contains the theory of behaviour. Most of the other changes just insert code to call the appropriate routines. #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # bug_patch # Diffs # This archive created: Thu Feb 14 22:45:00 1991 export PATH; PATH=/bin:$PATH echo shar: extracting "'bug_patch'" '(1492 characters)' if test -f 'bug_patch' then echo shar: will not over-write existing file "'bug_patch'" else sed 's/^ X//' << \SHAR_EOF > 'bug_patch' XTo: pc XSubject: bug in your annotation patches for xmh XDate: Thu, 14 Feb 91 16:00:45 +0100 XFrom: Sjoerd Mullender <sjoerd@cwi.nl> X X XI found a bug in your annotation patches for xmh. The problem is: when Xa user does not annotate his/her mail, AnnoInitEnv isn't called, but XAnnoEnvSet and AnnoEnvReset are called. Since our_env isn't Xinitialised, you get a core dump. I include a context diff of the Xpatched msg.c. X X*** msg.c.bug Mon Feb 4 11:08:04 1991 X--- msg.c Thu Feb 14 15:56:35 1991 X*************** X*** 731,737 **** X } X (void) myfclose(from); X (void) myfclose(to); X! AnnoEnvSet(msg); X argv = MakeArgv(3); X argv[0] = "send"; X argv[1] = "-push"; X--- 731,738 ---- X } X (void) myfclose(from); X (void) myfclose(to); X! if (app_resources.annotate_repl || app_resources.annotate_forw) X! AnnoEnvSet(msg); X argv = MakeArgv(3); X argv[0] = "send"; X argv[1] = "-push"; X*************** X*** 738,744 **** X argv[2] = str; X DoCommand(argv, (char *) NULL, (char *) NULL); X XtFree((char *) argv); X! AnnoEnvReset(); X } X X X--- 739,746 ---- X argv[2] = str; X DoCommand(argv, (char *) NULL, (char *) NULL); X XtFree((char *) argv); X! if (app_resources.annotate_repl || app_resources.annotate_forw) X! AnnoEnvReset(); X } X X X XSjoerd Mullender XCWI, dept. CST, Kruislaan 413, 1098 SJ Amsterdam, Netherlands Xemail: sjoerd@cwi.nl fax: +31 20 592 4199 Xphone: +31 20 592 4132 telex: 12571 mactr nl SHAR_EOF if test 1492 -ne "`wc -c < 'bug_patch'`" then echo shar: error transmitting "'bug_patch'" '(should have been 1492 characters)' fi chmod +x 'bug_patch' fi # end of overwriting check echo shar: extracting "'Diffs'" '(13986 characters)' if test -f 'Diffs' then echo shar: will not over-write existing file "'Diffs'" else sed 's/^ X//' << \SHAR_EOF > 'Diffs' XThese diffs permit the `standard' xmh release with X11R4 to annotate Xmessages that have been replied to or forwarded. I have tested this ONLY Xwith mh6.7. Annotation is controlled by resources - see the manual page. X XAnnotation will not SHOW if a currently displayed message is annotated. X XMost of the work is done in a new file `anno.c', this also contains Xthe theory of behaviour. Most of the other changes just insert code Xto call the appropriate code. X X(Note this is a second release of this. The first release broke for Xpeople who DIDN'T want to annotate their mail) X X*** /dev/null Thu Feb 14 21:34:02 1991 X--- anno.c Sun Dec 23 21:14:56 1990 X*************** X*** 0 **** X--- 1,271 ---- X+ /* X+ * anno.c X+ * - routines concerned with annotation X+ * File added by Peter Collinson, Hillside Systems X+ * pc@hillside.co.uk X+ */ X+ X+ /* X+ * Background X+ * mh6.7 uses various environment variables to permit message X+ * annotation. X+ * X+ * a) mhfolder X+ * contains the name of the folder to be annotated X+ * b) mhmessages X+ * space separated list of messages to annotate X+ * c) mhannotate X+ * text to use for annotation X+ * d) mhinplace X+ * 1 to annotate inplace X+ * 0 not to X+ * X+ * Theory X+ * Add a character string to a Scrn containing the message list X+ * for annotation. X+ * When send is called push the various objects into the X+ * environment X+ */ X+ #include "xmh.h" X+ #include "tocintrnl.h" X+ X+ static int MheLookup(); X+ static Scrn AnnoSearch(); X+ static char *MakeEnv(); X+ X+ /* X+ * Given a message - create an annotation list and X+ * return it X+ */ X+ char * X+ AnnoMsgCreate(msg) X+ Msg msg; X+ { X+ MsgListRec ml; X+ char *AnnoCreate(); X+ X+ ml.nummsgs = 1; X+ ml.msglist = &msg; X+ return (AnnoCreate(&ml)); X+ } X+ X+ /* X+ * given an mlist - create an annotation list X+ * and return it - the first element in the list is the X+ * name of the folder X+ * X+ */ X+ char * X+ AnnoCreate(mlist) X+ MsgList mlist; X+ { X+ char *anno; X+ char *folder; X+ int bytes; X+ register int d; X+ register int i; X+ char *src; X+ char numbuf[16]; X+ X+ if (mlist->nummsgs == 0) X+ return (NULL); X+ X+ folder = mlist->msglist[0]->toc->foldername; X+ anno = (char *)XtMalloc(512); X+ bytes = 512; X+ for (d = 0, src = app_resources.mail_path; anno[d++] = *src++;); X+ anno[d-1] = '/'; X+ for (src = folder; anno[d++] = *src++;); X+ d--; X+ X+ X+ for (i = 0; i < mlist->nummsgs; i++) X+ { X+ (void) sprintf(numbuf, "%d", mlist->msglist[i]->msgid); X+ X+ if (d+16 > bytes) X+ { bytes += 512; X+ anno = (char *)XtRealloc(anno, bytes); X+ } X+ /* add a space */ X+ anno[d++] = ' '; X+ for (src = numbuf; anno[d++] = *src++;); X+ d--; X+ } X+ anno[d] = '\0'; X+ return (anno); X+ } X+ X+ /* X+ * We will need to add and delete four things from X+ * the environment. This could be done after the fork() X+ * but this means that we have to change the environment X+ * to be sure of not affecting any other programs X+ * X+ * So the idea here is to copy the environment into our vector X+ * deleting the four things that we are interested in X+ * we then put OUR things in the first four string positions X+ */ X+ static char **our_env; /* this points at our environment */ X+ extern char **environ; /* what the world sees */ X+ X+ typedef struct addenv X+ { char *add; X+ int len; X+ } Addenv; X+ X+ static Addenv adde[] = X+ { X+ { "mhfolder=", 9 }, X+ { "mhmessages=", 11 }, X+ { "mhannotate=", 11 }, X+ { "mhinplace=", 10 }, X+ { NULL, 0 } X+ }; X+ X+ #define MHE_FOLDER 0 X+ #define MHE_MESSAGES 1 X+ #define MHE_ANNOTATE 2 X+ #define MHE_INPLACE 3 X+ X+ AnnoInitEnv() X+ { X+ register int count; /* number of things in the environment */ X+ register char **pt; X+ register char **dst; X+ char inp[16]; X+ X+ X+ if (our_env) X+ return; X+ X+ for (count = 0, pt = environ; *pt++; count++); X+ X+ our_env = (char **)XtMalloc((count+5)*sizeof (char **)); X+ our_env[0] = our_env[1] = our_env[2] = NULL; X+ X+ /* copy the environment into `our' environment */ X+ /* start at position 4 */ X+ dst = &our_env[4]; X+ X+ for (pt = environ; *pt; pt++) X+ { X+ if (MheLookup(*pt)) X+ continue; X+ *dst++ = *pt; X+ } X+ *dst = NULL; X+ /* X+ * set up the inplace value X+ */ X+ (void) sprintf(inp, "%s%d", adde[MHE_INPLACE].add, app_resources.annotate_in_place); X+ our_env[MHE_INPLACE] = XtNewString(inp); X+ } X+ X+ /* X+ * Look in the list of things we are dealing with X+ * to find a match in the environment X+ */ X+ static int X+ MheLookup(env) X+ char *env; X+ { X+ register Addenv *ae; X+ X+ for (ae = adde; ae->add; ae++) X+ if (strncmp(env, ae->add, ae->len) == 0) X+ return(1); X+ return 0; X+ } X+ X+ /* X+ * Reset the environment to the standard X+ */ X+ AnnoEnvReset() X+ { X+ environ = &our_env[4]; X+ } X+ X+ /* X+ * Set the environment to new values X+ */ X+ AnnoEnvSet(msg) X+ Msg msg; X+ { X+ Scrn scrn; X+ char *folder; X+ char *annotate; X+ char *s; X+ char *d; X+ register i; X+ Scrn AnnoSearch(); X+ char buf[512]; X+ X+ if ((scrn = AnnoSearch(msg)) == NULL) X+ return; X+ X+ switch (scrn->anno_type) X+ { X+ case ANrepl: X+ annotate = "Replied"; X+ break; X+ case ANforw: X+ annotate = "Forwarded"; X+ break; X+ default: /* shouldn't happen */ X+ return; X+ } X+ X+ for (i = 0; i < MHE_INPLACE; i++) X+ if (our_env[i]) X+ { XtFree(our_env[i]); X+ our_env[i] = NULL; X+ } X+ /* X+ * Munge the annotation list X+ * we see it as X+ * folder-name number number X+ */ X+ for (s = scrn->anno_list, d = buf; *s != ' '; *d++ = *s++); X+ *d = '\0'; X+ s++; X+ X+ our_env[MHE_FOLDER] = MakeEnv(&adde[MHE_FOLDER], buf); X+ our_env[MHE_MESSAGES] = MakeEnv(&adde[MHE_MESSAGES], s); X+ our_env[MHE_ANNOTATE] = MakeEnv(&adde[MHE_ANNOTATE], annotate); X+ environ = our_env; X+ } X+ X+ static Scrn X+ AnnoSearch(msg) X+ Msg msg; X+ { X+ register i; X+ AnnoKind ak; X+ X+ if (msg->num_scrns == 0) X+ return (NULL); X+ X+ for (i = 0; i < msg->num_scrns; i++) X+ { X+ if ((ak = msg->scrn[i]->anno_type) == ANrepl) X+ return(msg->scrn[i]); X+ else X+ if (ak == ANforw) X+ return(msg->scrn[i]); X+ } X+ return (NULL); X+ } X+ X+ X+ X+ static char * X+ MakeEnv(ad, value) X+ register Addenv *ad; X+ char *value; X+ { X+ char buf[512]; X+ X+ (void) sprintf(buf, "%s%s", ad->add, value); X+ return (XtNewString(buf)); X+ } X*** Imakefile~ Thu Feb 14 22:33:41 1991 X--- Imakefile Sun Dec 23 21:15:33 1990 X*************** X*** 8,17 **** X X SRCS = bbox.c command.c compfuncs.c folder.c icon.c init.c \ X main.c menu.c mlist.c msg.c pick.c popup.c screen.c \ X! toc.c tocfuncs.c tocutil.c tsource.c util.c viewfuncs.c X OBJS = bbox.o command.o compfuncs.o folder.o icon.o init.o \ X main.o menu.o mlist.o msg.o pick.o popup.o screen.o \ X! toc.o tocfuncs.o tocutil.o tsource.o util.o viewfuncs.o X X X ComplexProgramTarget(xmh) X--- 8,17 ---- X X SRCS = bbox.c command.c compfuncs.c folder.c icon.c init.c \ X main.c menu.c mlist.c msg.c pick.c popup.c screen.c \ X! toc.c tocfuncs.c tocutil.c tsource.c util.c viewfuncs.c anno.c X OBJS = bbox.o command.o compfuncs.o folder.o icon.o init.o \ X main.o menu.o mlist.o msg.o pick.o popup.o screen.o \ X! toc.o tocfuncs.o tocutil.o tsource.o util.o viewfuncs.o anno.o X X X ComplexProgramTarget(xmh) X*** compfuncs.c~ Thu Feb 14 22:33:42 1991 X--- compfuncs.c Sun Dec 23 21:15:33 1990 X*************** X*** 117,122 **** X--- 117,124 ---- X { X Scrn scrn; X Msg msg; X+ char *AnnoCreate(); X+ X scrn = NewCompScrn(); X msg = TocMakeNewMsg(DraftsFolder); X MsgLoadForward(scrn, msg, mlist); X*************** X*** 123,126 **** X--- 125,133 ---- X MsgSetTemporary(msg); X MsgSetScrnForComp(msg, scrn); X MapScrn(scrn); X+ if (app_resources.annotate_forw) { X+ scrn->anno_type = ANforw; X+ scrn->anno_list = AnnoCreate(mlist); X+ } X+ X } X*** globals.h~ Thu Feb 14 22:33:42 1991 X--- globals.h Sun Dec 23 21:15:31 1990 X*************** X*** 76,81 **** X--- 76,84 ---- X int command_button_count; /* number of buttons in command box */ X int app_defaults_version; /* for sanity check */ X char *banner; /* defaults to xmh version string */ X+ Boolean annotate_repl; /* true if we are to annotate reply sources */ X+ Boolean annotate_forw; /* true if we are to annotate forw sources */ X+ int annotate_in_place; /* 0 if don't annotate inplace, 1 otherwise */ X } app_resources; X X ext char *draftFile; /* Filename of draft. */ X*** init.c~ Thu Feb 14 22:33:43 1991 X--- init.c Sun Dec 23 21:15:31 1990 X*************** X*** 124,129 **** X--- 124,135 ---- X offset(app_defaults_version), XtRImmediate, (XtPointer)0}, X {"banner", "Banner", XtRString, sizeof(char *), X offset(banner), XtRString, "xmh MIT X Consortium R4"}, X+ {"annotateRepl", "AnnotateRepl", XtRBoolean, sizeof(Boolean), X+ offset(annotate_repl), XtRImmediate, (XtPointer)False}, X+ {"annotateForw", "AnnotateForw", XtRBoolean, sizeof(Boolean), X+ offset(annotate_forw), XtRImmediate, (XtPointer)False}, X+ {"annotateInPlace", "AnnotateInPlace", XtRInt, sizeof(int), X+ offset(annotate_in_place), XtRImmediate, (XtPointer)1}, X }; X X #undef offset X*************** X*** 396,401 **** X--- 402,413 ---- X InitPick(); X IconInit(); X BBoxInit(); X+ X+ /* X+ * Initialise annotations if required X+ */ X+ if (app_resources.annotate_repl || app_resources.annotate_forw) X+ AnnoInitEnv(); X X XtAppAddActions( XtWidgetToApplicationContext(toplevel), X actions, XtNumber(actions)); X*** msg.c~ Thu Feb 14 22:33:43 1991 X--- msg.c Thu Feb 14 22:24:25 1991 X*************** X*** 731,736 **** X--- 731,738 ---- X } X (void) myfclose(from); X (void) myfclose(to); X+ if (app_resources.annotate_repl || app_resources.annotate_forw) X+ AnnoEnvSet(msg); X argv = MakeArgv(3); X argv[0] = "send"; X argv[1] = "-push"; X*************** X*** 737,742 **** X--- 739,746 ---- X argv[2] = str; X DoCommand(argv, (char *) NULL, (char *) NULL); X XtFree((char *) argv); X+ if (app_resources.annotate_repl || app_resources.annotate_forw) X+ AnnoEnvReset(); X } X X X*** screen.c~ Thu Feb 14 22:33:44 1991 X--- screen.c Sun Dec 23 21:15:31 1990 X*************** X*** 391,396 **** X--- 391,398 ---- X Scrn scrn; X scrn = CreateNewScrn(STcomp); X scrn->assocmsg = (Msg)NULL; X+ scrn->anno_type = ANno; X+ scrn->anno_list = NULL; X return scrn; X } X X*************** X*** 412,417 **** X--- 414,423 ---- X TocSetScrn((Toc) NULL, scrn); X MsgSetScrnForce((Msg) NULL, scrn); X lastInput.win = -1; X+ if (scrn->anno_list) { X+ XtFree(scrn->anno_list); X+ scrn->anno_list = NULL; X+ } X } X } X X*** tocfuncs.c~ Thu Feb 14 22:33:44 1991 X--- tocfuncs.c Sun Dec 23 21:15:32 1990 X*************** X*** 651,656 **** X--- 651,657 ---- X Scrn nscrn; X MsgList mlist; X Msg msg; X+ char *AnnoMsgCreate(); X X if (toc == NULL) return; X mlist = CurMsgListOrCurMsg(toc); X*************** X*** 657,662 **** X--- 658,667 ---- X if (mlist->nummsgs) { X nscrn = NewCompScrn(); X ScreenSetAssocMsg(nscrn, mlist->msglist[0]); X+ if (app_resources.annotate_repl) X+ { nscrn->anno_type = ANrepl; X+ nscrn->anno_list = AnnoMsgCreate(mlist->msglist[0]); X+ } X msg = TocMakeNewMsg(DraftsFolder); X MsgSetTemporary(msg); X MsgLoadReply(msg, mlist->msglist[0]); X*** viewfuncs.c~ Thu Feb 14 22:33:45 1991 X--- viewfuncs.c Sun Dec 23 21:15:32 1990 X*************** X*** 76,85 **** X Scrn scrn = (Scrn) client_data; X Msg msg; X Scrn nscrn; X! X if (scrn->msg == NULL) return; X nscrn = NewCompScrn(); X ScreenSetAssocMsg(nscrn, scrn->msg); X msg = TocMakeNewMsg(DraftsFolder); X MsgSetTemporary(msg); X MsgLoadReply(msg, scrn->msg); X--- 76,90 ---- X Scrn scrn = (Scrn) client_data; X Msg msg; X Scrn nscrn; X! char *AnnoMsgCreate(); X! X if (scrn->msg == NULL) return; X nscrn = NewCompScrn(); X ScreenSetAssocMsg(nscrn, scrn->msg); X+ if (app_resources.annotate_repl) X+ { nscrn->anno_type = ANrepl; X+ nscrn->anno_list = AnnoMsgCreate(scrn->msg); X+ } X msg = TocMakeNewMsg(DraftsFolder); X MsgSetTemporary(msg); X MsgLoadReply(msg, scrn->msg); X*** xmh.h~ Thu Feb 14 22:33:45 1991 X--- xmh.h Sun Dec 23 21:15:31 1990 X*************** X*** 90,95 **** X--- 90,101 ---- X STpick X } ScrnKind; X X+ typedef enum { X+ ANno, X+ ANrepl, X+ ANforw X+ } AnnoKind; X+ X typedef struct _StackRec { X char *data; X struct _StackRec *next; X*************** X*** 119,124 **** X--- 125,132 ---- X Msg assocmsg; /* Associated message for reply, etc. */ X Window wait_window; /* InputOnly window with busy cursor */ X Stack folder_stack; /* Stack of folder names */ X+ AnnoKind anno_type; /* type of annotation */ X+ char * anno_list; /* list of messages to annotate */ X } ScrnRec, *Scrn; X X X*** xmh.man~ Thu Feb 14 22:33:46 1991 X--- xmh.man Mon Dec 24 12:02:12 1990 X*************** X*** 921,926 **** X--- 921,946 ---- X X The following resources are defined: X .TP 8 X+ .B AnnotateRepl X+ Permits annotation of messages that are being replied to. X+ This uses the standard X+ .I mh X+ mechanism in X+ .IR send . X+ Default is false. X+ .TP 8 X+ .B AnnotateForw X+ Permits annotation of messages that are being forwarded. X+ This uses the standard X+ .I mh X+ mechanism in X+ .IR send . X+ Default is false. X+ .TP X+ .B AnnotateInPlace X+ When set to non-zero causes annotation to be done in place to preserve X+ links to the annotated message. X+ .TP 8 X .B Banner X A short string that is the default label of the folder, Table of Contents, X and view. The default is "xmh MIT X Consortium R4". X*************** X*** 1241,1243 **** X--- 1261,1265 ---- X Terry Weissman, Digital Western Research Laboratory X .br X modified by Donna Converse, MIT X Consortium X+ .br X+ Annotation code by Peter Collinson, Hillside Systems SHAR_EOF if test 13986 -ne "`wc -c < 'Diffs'`" then echo shar: error transmitting "'Diffs'" '(should have been 13986 characters)' fi chmod +x 'Diffs' fi # end of overwriting check # End of shell archive exit 0
hodges@Breakaway.Stanford.EDU (Jeff Hodges) (03/06/91)
There's an enhancement to xmh that I wish someone would do (I just don't have the time)... One can't tell in the xmh table-of-contents (TOC) what messages one has or hasn't read. In another xmh-like "MailTool" I've used extensively, TOC entries were tagged, in this case with an '*', until read. For example... * 1 10/08 schwartz@latour.c Resource Discovery papers available by anonymous * 2 10/08 jkrey@venera.isi. RFC1183 on New DNS RR Definitions <<A new Reques 3 10/18 jkrey@venera.isi. RFC1186 on MD4 Message Digest Algorithm <<A new 4 11/15 jkrey@venera.isi. RFC1193 on Requirements for Real-Time Services < 5 11/20 mdavies@nri.resto ID Action: draft-slaski-ftpftam-00.txt <<A New I * 6 11/29 veizades@apple.co Resource Location BOF @ Boulder IETF <<In findin * 7 11/27 mdavies@nri.resto ID ACTION: draft-ietf-osids-friendlynaming-00.tx * 8 11/20 mdavies@nri.resto ID ACTION: draft-ietf-osix500-directories-00.txt ..in this TOC, I can tell at a glance that I haven't read 1, 2, 6, 7, or 8. I find that I'm constantly wondering what I've read and what I haven't, and not having it messes up my on-the-fly message-reading prioritization. If someone out there can push the code, I'd give it a whirl and can provide feedback on UI details and such. thanks, Jeff Hodges