Xref: utzoo comp.windows.x:32760 comp.mail.mh:1446 alt.sources:3219 Path: utzoo!utgpu!cs.utexas.edu!helios!bcm!dimacs.rutgers.edu!seismo!uunet!mcsun!ukc!pc From: pc@ukc.ac.uk (R.P.A.Collinson) Newsgroups: comp.windows.x,comp.mail.mh,alt.sources Subject: Xmh patches for repl/forw style annotation (unofficial) + bug fix Message-ID: <2525@ukc> Date: 15 Feb 91 00:59:05 GMT Reply-To: pc@ukc.ac.uk (R.P.A.Collinson) Followup-To: comp.windows.x Organization: Computing Lab, University of Kent at Canterbury, UK. Lines: 676 (**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 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