[alt.sources] Xmh patches for repl/forw style annotation

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