Xmh patches for repl/forw style annotation (unofficial)

R.P.A.Collinson pc at ukc.ac.uk
Sat Feb 2 12:03:55 AEST 1991


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 at 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



More information about the Alt.sources mailing list