[comp.sources.x] v01i017: xfig: a MacDraw like graphics editor, Patch4

mikew@wyse.wyse.com (Mike Wexler) (08/31/88)

Submitted-by: dana@thumper.bellcore.com (Dana A. Chee)
Posting-number: Volume 1, Issue 17
Archive-name: xfig/patch4




Below are the patches which incorportate the changes that John Kohl
announced in comp.windows.x.  This is patch 4 (in keeping with expo)
and is being submitted to comp.sources.x and stored on expo.

It should create a patch file (since I didn't have one).  The reason
it is patchlevel 3 is to stay in line with the minor version number
(which is now 3).
 
			Dana Chee
			Bellcore
			MRE 2Q-250
			(201) 829-4488
			dana@bellcore.com
==================== xfig.patch.4
diff -c /dev/null patchlevel.h
*** /dev/null	Fri Aug 26 09:30:01 1988
--- patchlevel.h	Fri Aug 26 09:06:45 1988
***************
*** 0 ****
--- 1 ----
+ #define PATCHLEVEL 3
diff -c README.X11.orig README.X11
*** README.X11.orig	Fri Aug 12 22:30:14 1988
--- README.X11	Fri Aug 26 10:28:14 1988
***************
*** 61,63 ****
--- 61,78 ----
  		Dana Chee of Bellcore contributed lots of cleanups
  		and put right some features I didn't know how
  		to do properly. (Thanks, Dana.) Released to world.
+ 
+ xfig 1.4.2:
+ 
+ 23 Aug 88 	Dana Chee (Bellcore)
+ 	  	Fixed color, added mouse tracking option.
+ 
+ xfig 1.4.3:
+ 
+ 26 Aug 88 	Dana Chee (Bellcore)
+ 	  	Added John Kohl's changes to fix color and make
+ 	  	inverse video work on a monochrome display.
+ 	  	Allow scaling of compound objects on a side as well as
+ 	  	a corner.
+ 	  	Allow compound objects within a compound.
+ 
diff -c /tmp/panel.c panel.c
*** /tmp/panel.c	Fri Aug 26 09:38:46 1988
--- panel.c	Thu Aug 25 11:25:16 1988
***************
*** 132,138 ****
--- 132,144 ----
  	{ XtNheight, (XtArgVal)0 },
  	{ XtNhSpace, (XtArgVal)SWITCH_ICON_SPACING },
  	{ XtNvSpace, (XtArgVal)SWITCH_ICON_SPACING },
+ 	/* Fix the size of the panel window by chaining both top & bottom
+ 	   to the top, and both left & right to the right */
+ 	{ XtNtop, (XtArgVal)XtChainTop},
+ 	{ XtNbottom, (XtArgVal)XtChainTop},
  	{ XtNleft, (XtArgVal)XtChainLeft },
+ 	{ XtNright, (XtArgVal)XtChainLeft },
+ 	{ XtNresizable, (XtArgVal) FALSE },
  };
  
  extern void button_select();
***************
*** 152,157 ****
--- 158,164 ----
  	{ XtNheight, (XtArgVal)0 },
  	{ XtNbackgroundPixmap, (XtArgVal)NULL },
  	{ XtNcallback, (XtArgVal)button_callbacks },
+ 	{ XtNresizable, (XtArgVal) FALSE },
  };
  
  extern int	PANEL_LEFT, PANEL_TOP, PANEL_HEIGHT, PANEL_WID;
***************
*** 206,212 ****
  	XSetForeground(d, cgc, fg);
  	XSetBackground(d, cgc, bg);
  	
- 	/*XCopyGC(d, gc, ~0, cgc);*/
  	for (i = 0; i < N_SWITCHES; ++i)
  	{
  		sw = &switches[i];
--- 213,218 ----
diff -c /tmp/ruler.c ruler.c
*** /tmp/ruler.c	Fri Aug 26 09:38:50 1988
--- ruler.c	Fri Aug 26 08:51:05 1988
***************
*** 18,28 ****
--- 18,36 ----
  #define			QUARTER_MARK		8
  #define			SIXTEENTH_MARK		6
  
+ #ifndef	X11
  #define			MARK_HT			5
  #define			TRM_WID			15
  #define			TRM_HT			8
  #define			SRM_WID			8
  #define			SRM_HT			15
+ #else
+ #define			MARK_HT			5
+ #define			TRM_WID			16
+ #define			TRM_HT			8
+ #define			SRM_WID			8
+ #define			SRM_HT			16
+ #endif
  
  extern int		CANVAS_HEIGHT, CANVAS_WIDTH;
  extern int		SIDERULER_WIDTH, SIDERULER_HEIGHT;
***************
*** 31,37 ****
  extern int		TOPRULER_LEFT, TOPRULER_TOP;
  extern			null_proc();
  extern int		RHS_PANEL;
! extern int		tracking;
  
  static			lasty = -100;
  static			lastx = -100;
--- 39,45 ----
  extern int		TOPRULER_LEFT, TOPRULER_TOP;
  extern			null_proc();
  extern int		RHS_PANEL;
! extern int		TRACKING;
  
  static			lasty = -100;
  static			lastx = -100;
***************
*** 39,44 ****
--- 47,53 ----
  static char		*number[] = {"0", "1", "2", "3", "4", "5", 
  					"6", "7", "8", "9", "10", "11" };
  static int		troffx = -7, troffy = -10;
+ #ifndef	X11
  static short		tr_marker_image[8] = {
  				0xFFFE,	/* *************** */
  				0x7FFC,	/*  *************  */
***************
*** 49,56 ****
--- 58,78 ----
  				0x0380,	/*       ***       */
  				0x0100	/*        *        */
  				};
+ #else
+ static char		tr_marker_image[16] = {
+ 				0xFF, 0xFE,	/* *************** */
+ 				0x7F, 0xFC,	/*  *************  */
+ 				0x3F, 0xF8,	/*   ***********   */
+ 				0x1F, 0xF0,	/*    *********    */
+ 				0x0F, 0xE0,	/*     *******     */
+ 				0x07, 0xC0,	/*      *****      */
+ 				0x03, 0x80,	/*       ***       */
+ 				0x01, 0x00	/*        *        */
+ 				};
+ #endif
  static			mpr_static(trm_pr, TRM_WID, TRM_HT, 1, tr_marker_image);
  static int		srroffx = 2, srroffy = -7;
+ #ifndef	X11
  static short		srr_marker_image[15] = {
  				0x0100,	/*          *  */
  				0x0300,	/*         **  */
***************
*** 68,80 ****
  				0x0300,	/*         **  */
  				0x0100	/*          *  */
  				};
- #ifndef	X11
- static		mpr_static(srrm_pr, SRM_WID, SRM_HT, 1, srr_marker_image);
  #else
! static		mpr_static(srrm_pr, 16, SRM_HT, 1, srr_marker_image);
  #endif
  
  static int		srloffx = -10, srloffy = -7;
  static short		srl_marker_image[15] = {
  				0x8000,	/*  *          */
  				0xC000,	/*  **         */
--- 90,119 ----
  				0x0300,	/*         **  */
  				0x0100	/*          *  */
  				};
  #else
! static char		srr_marker_image[16] = {
! 				0x01,	/*          *  */
! 				0x03,	/*         **  */
! 				0x07,	/*        ***  */
! 				0x0F,	/*       ****  */
! 				0x1F,	/*      *****  */
! 				0x3F,	/*     ******  */
! 				0x7F,	/*    *******  */
! 				0xFF,	/*   ********  */
! 				0x7F,	/*    *******  */
! 				0x3F,	/*     ******  */
! 				0x1F,	/*      *****  */
! 				0x0F,	/*       ****  */
! 				0x07,	/*        ***  */
! 				0x03,	/*         **  */
! 				0x01,	/*          *  */
! 				0x00
! 				};
  #endif
+ static		mpr_static(srrm_pr, SRM_WID, SRM_HT, 1, srr_marker_image);
  
  static int		srloffx = -10, srloffy = -7;
+ #ifndef	X11
  static short		srl_marker_image[15] = {
  				0x8000,	/*  *          */
  				0xC000,	/*  **         */
***************
*** 92,102 ****
  				0xC000,	/*  **         */
  				0x8000	/*  *          */
  				};
- #ifndef	X11
- static		mpr_static(srlm_pr, SRM_WID, SRM_HT, 1, srl_marker_image);
  #else
! static		mpr_static(srlm_pr, 16, SRM_HT, 1, srl_marker_image);
  #endif
  
  #ifdef	X11
  static Pixmap		toparrow_pm, sidearrow_pm;
--- 131,157 ----
  				0xC000,	/*  **         */
  				0x8000	/*  *          */
  				};
  #else
! static char		srl_marker_image[16] = {
! 				0x80,	/*  *          */
! 				0xC0,	/*  **         */
! 				0xE0,	/*  ***        */
! 				0xF0,	/*  ****       */
! 				0xF8,	/*  *****      */
! 				0xFC,	/*  ******     */
! 				0xFE,	/*  *******    */
! 				0xFF,	/*  ********   */
! 				0xFE,	/*  *******    */
! 				0xFC,	/*  ******     */
! 				0xF8,	/*  *****      */
! 				0xF0,	/*  ****       */
! 				0xE0,	/*  ***        */
! 				0xC0,	/*  **         */
! 				0x80,	/*  *          */
! 				0x00
! 				};
  #endif
+ static		mpr_static(srlm_pr, SRM_WID, SRM_HT, 1, srl_marker_image);
  
  #ifdef	X11
  static Pixmap		toparrow_pm, sidearrow_pm;
***************
*** 111,121 ****
  	pw_write(topruler_pixwin, x + troffx, RULER_WIDTH + troffy, 
  		TRM_WID, TRM_HT, INV_PAINT, &trm_pr, 0, 0);
  #else
! 	XCopyArea(tool_d, toparrow_pm, topruler_pixwin, gccache[INV_PAINT],
  		0, 0, trm_pr.width, trm_pr.height,
- 		lastx + troffx, TOPRULER_HEIGHT + troffy);
- 	XCopyArea(tool_d, toparrow_pm, topruler_pixwin, gccache[INV_PAINT],
- 		0, 0, trm_pr.width, trm_pr.height,
  		x + troffx, TOPRULER_HEIGHT + troffy);
  #endif	X11
  	lastx = x;
--- 166,176 ----
  	pw_write(topruler_pixwin, x + troffx, RULER_WIDTH + troffy, 
  		TRM_WID, TRM_HT, INV_PAINT, &trm_pr, 0, 0);
  #else
! 	XClearArea(tool_d, topruler_pixwin,lastx + troffx,
! 		   TOPRULER_HEIGHT + troffy,trm_pr.width,
! 		   trm_pr.height, False);
! 	XCopyArea(tool_d, toparrow_pm, topruler_pixwin, topgc,
  		0, 0, trm_pr.width, trm_pr.height,
  		x + troffx, TOPRULER_HEIGHT + troffy);
  #endif	X11
  	lastx = x;
***************
*** 181,186 ****
--- 236,246 ----
  	{ XtNhorizDistance, (XtArgVal)0 },
  	{ XtNfromVert, (XtArgVal)NULL },
  	{ XtNvertDistance, (XtArgVal)0 },
+ 	{ XtNresizable, (XtArgVal)FALSE },
+ 	{ XtNtop, (XtArgVal)XtRubber },
+ 	{ XtNbottom, (XtArgVal)XtRubber },
+ 	{ XtNleft, (XtArgVal)XtRubber },
+ 	{ XtNright, (XtArgVal)XtRubber },
  };
  
  extern int	SIDERULER_WIDTH, SIDERULER_HEIGHT;
***************
*** 193,203 ****
--- 253,275 ----
  	ruler_args[3].value = SIDERULER_HEIGHT = CANVAS_HEIGHT;
  	ruler_args[5].value = (XtArgVal)canvas_sw;
  	ruler_args[7].value = (XtArgVal)topruler_sw;
+ 	/* Place the sideruler below the topruler, next to the canvas,
+ 	   but fixed offset from the top of the form */
+ 	ruler_args[10].value = (XtArgVal)XtChainTop;
+ 	ruler_args[11].value = (XtArgVal)XtRubber;
+ 	ruler_args[12].value = (XtArgVal)XtRubber;
+ 	ruler_args[13].value = (XtArgVal)XtRubber;
+ 	
  	sideruler_sw = XtCreateWidget("sruler", labelWidgetClass, tool,
  		ruler_args, XtNumber(ruler_args));
  	return(1);
  }
  
+ redisplay_sideruler()
+ {
+ 	XClearWindow(tool_d, sideruler_pixwin);
+ }
+ 
  setup_rulers()
  {
  	register int		i, j;
***************
*** 254,259 ****
--- 326,350 ----
  	ruler_args[0].value = (XtArgVal)p;
  	XtSetValues(topruler_sw, ruler_args, 1);
  
+ 	/* The arrows will be XORed into the rulers.
+ 	   We want the foreground color in the arrow to result in
+ 	   the foreground or background color in the display.
+ 	   so if the source pixel is fg^bg, it produces fg when XOR'ed
+ 	   with bg, and bg when XOR'ed with bg.
+ 
+ 	   If the source pixel is zero, it produces fg when XOR'ed with
+ 	   fg, and bg when XOR'ed with bg.
+ 	   */
+ 	XSetForeground(tool_d, gc, fg ^ bg);
+ 	XSetBackground(tool_d, gc, 0);
+ 
+ 	/* make pixmaps for top ruler arrow */
+ 	toparrow_pm = XCreatePixmap(tool_d, topruler_pixwin, trm_pr.width,
+ 				    trm_pr.height,
+ 				    DefaultDepthOfScreen(tool_s));
+ 	XPutImage(tool_d, toparrow_pm, gc, &trm_pr, 0, 0, 0, 0,
+ 		trm_pr.width, trm_pr.height);
+ 	
  	/* side ruler, adjustments for digits are kludges based on 6x13 char */
  	p = XCreatePixmap(tool_d, sideruler_pixwin,
  			  SIDERULER_WIDTH, SIDERULER_HEIGHT,
***************
*** 317,329 ****
  	ruler_args[0].value = (XtArgVal)p;
  	XtSetValues(sideruler_sw, ruler_args, 1);
  
! 	/* make pixmaps for ruler arrows */
! 	toparrow_pm = XCreatePixmap(tool_d, topruler_pixwin, trm_pr.width,
! 				    trm_pr.height,
! 				    DefaultDepthOfScreen(tool_s));
! 	XPutImage(tool_d, toparrow_pm, gc, &trm_pr, 0, 0, 0, 0,
! 		trm_pr.width, trm_pr.height);
! 	
  	if( RHS_PANEL )
  	{
  		sidearrow_pm = XCreatePixmap(tool_d, sideruler_pixwin,
--- 408,418 ----
  	ruler_args[0].value = (XtArgVal)p;
  	XtSetValues(sideruler_sw, ruler_args, 1);
  
! 	/* Colors set as above */
! 	XSetForeground(tool_d, gc, fg ^ bg);
! 	XSetBackground(tool_d, gc, 0);
! 
! 	/* make pixmaps for side ruler arrow */
  	if( RHS_PANEL )
  	{
  		sidearrow_pm = XCreatePixmap(tool_d, sideruler_pixwin,
***************
*** 434,443 ****
--- 523,545 ----
  	ruler_args[2].value = TOPRULER_WIDTH = CANVAS_WIDTH;;
  	ruler_args[3].value = TOPRULER_HEIGHT = RULER_WIDTH;
  	ruler_args[5].value = (XtArgVal)panel_sw;
+ 	ruler_args[7].value = (XtArgVal)NULL;
+ 	/* fix the top & bottom to the top of the form,
+ 	   the left to the panel, and the right is rubber */
+ 	ruler_args[10].value = (XtArgVal)XtChainTop;
+ 	ruler_args[11].value = (XtArgVal)XtChainTop;
+ 	ruler_args[12].value = (XtArgVal)XtRubber;
+ 	ruler_args[13].value = (XtArgVal)XtRubber;
+ 	
  	topruler_sw = XtCreateWidget("truler", labelWidgetClass, tool,
  		ruler_args, XtNumber(ruler_args));
  	return(1);
  }
+ 
+ redisplay_topruler()
+ {
+ 	XClearWindow(tool_d, topruler_pixwin);
+ }
  #endif	X11
  
  #ifndef	X11
***************
*** 479,485 ****
  set_rulermark(x, y)
  int	x, y;
  {
! 	if( tracking )
  	{
  		set_siderulermark(y);
  		set_toprulermark(x);
--- 581,587 ----
  set_rulermark(x, y)
  int	x, y;
  {
! 	if( TRACKING )
  	{
  		set_siderulermark(y);
  		set_toprulermark(x);
***************
*** 486,491 ****
--- 588,601 ----
  	}
  }
  
+ #ifdef	X11
+ redisplay_rulers()
+ {
+ 	redisplay_topruler();
+ 	redisplay_sideruler();
+ }
+ #endif
+ 
  set_siderulermark(y)
  int	y;
  {
***************
*** 508,528 ****
  	lasty = sy;
  #else
  	if( RHS_PANEL ) {
  		XCopyArea(tool_d, sidearrow_pm, sideruler_pixwin,
! 			  gccache[INV_PAINT], 0, 0, srlm_pr.width,
! 			  srlm_pr.height, RULER_WIDTH+srloffx, lasty + srloffy);
! 		XCopyArea(tool_d, sidearrow_pm, sideruler_pixwin,
! 			  gccache[INV_PAINT], 0, 0, srlm_pr.width,
  			  srlm_pr.height, RULER_WIDTH+srloffx, y + srloffy);
  	}
  	else
  	{
  		XCopyArea(tool_d, sidearrow_pm, sideruler_pixwin,
! 			  gccache[INV_PAINT], 0, 0, srrm_pr.width,
! 			  srrm_pr.height, -srroffx, lasty + srroffy);
! 		XCopyArea(tool_d, sidearrow_pm, sideruler_pixwin,
! 			  gccache[INV_PAINT], 0, 0, srrm_pr.width,
! 			  srrm_pr.height, -srroffx, y + srroffy);
  	}
  	lasty = y;
  #endif	X11
--- 618,642 ----
  	lasty = sy;
  #else
  	if( RHS_PANEL ) {
+ 		/* Because the ruler uses a background pixmap, we can win
+ 		   here by using XClearArea to erase the old thing. */
+ 		XClearArea(tool_d, sideruler_pixwin,
+ 			   RULER_WIDTH+srloffx, lasty + srloffy,
+ 			   srlm_pr.width, srlm_pr.height, False);
  		XCopyArea(tool_d, sidearrow_pm, sideruler_pixwin,
! 			  sidegc, 0, 0, srlm_pr.width,
  			  srlm_pr.height, RULER_WIDTH+srloffx, y + srloffy);
  	}
  	else
  	{
+ 		/* Because the ruler uses a background pixmap, we can win
+ 		   here by using XClearArea to erase the old thing. */
+ 		XClearArea(tool_d, sideruler_pixwin,
+ 			   srroffx, lasty + srroffy,
+ 			   srlm_pr.width, srlm_pr.height, False);
  		XCopyArea(tool_d, sidearrow_pm, sideruler_pixwin,
! 			  sidegc, 0, 0, srrm_pr.width,
! 			  srrm_pr.height, srroffx, y + srroffy);
  	}
  	lasty = y;
  #endif	X11
diff -c /tmp/main.c main.c
*** /tmp/main.c	Fri Aug 26 09:38:54 1988
--- main.c	Thu Aug 25 11:19:36 1988
***************
*** 54,65 ****
  extern int		DEBUG;
  extern int		RHS_PANEL;
  extern int		INVERSE;
  
  TOOL			tool;
  int			WINDOW_WIDTH, WINDOW_HEIGHT;
  char			file_header[32] = "#FIG ";
  static char		*file = NULL;
- int			tracking = 1;
  
  get_args(argc, argv)
  int	argc;
--- 54,65 ----
  extern int		DEBUG;
  extern int		RHS_PANEL;
  extern int		INVERSE;
+ extern int		TRACKING;
  
  TOOL			tool;
  int			WINDOW_WIDTH, WINDOW_HEIGHT;
  char			file_header[32] = "#FIG ";
  static char		*file = NULL;
  
  get_args(argc, argv)
  int	argc;
***************
*** 115,125 ****
  				 break;
  
  			 case 't':	/* turn on tracking */
! 				 tracking = 1;
  				 break;
  
  			 case 'n':	/* turn off tracking */
! 				 tracking = 0;
  				 break;
  					 
  			 default:
--- 115,125 ----
  				 break;
  
  			 case 't':	/* turn on tracking */
! 				 TRACKING = 1;
  				 break;
  
  			 case 'n':	/* turn off tracking */
! 				 TRACKING = 0;
  				 break;
  					 
  			 default:
***************
*** 192,198 ****
  	{XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof(int),
  		 (Cardinal)&INVERSE, XtRBoolean, (caddr_t)&false},
  	{"trackCursor", "Track", XtRBoolean, sizeof(int),
! 		 (Cardinal)&tracking, XtRBoolean, (caddr_t)&true},
  };
  
  static XrmOptionDescRec options[] =
--- 192,198 ----
  	{XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof(int),
  		 (Cardinal)&INVERSE, XtRBoolean, (caddr_t)&false},
  	{"trackCursor", "Track", XtRBoolean, sizeof(int),
! 		 (Cardinal)&TRACKING, XtRBoolean, (caddr_t)&true},
  };
  
  static XrmOptionDescRec options[] =
***************
*** 247,252 ****
--- 247,283 ----
  	tool_sn = DefaultScreen(tool_d);
  	
  	gc = DefaultGC(tool_d, tool_sn);
+ 
+ 	if( CellsOfScreen(tool_s) == 2 && INVERSE )
+ 	{
+ 		XrmValue    value;
+ 		XrmDatabase newdb = (XrmDatabase) 0;
+ 		extern XrmDatabase XtDefaultDB;
+ 
+ 		value.size = sizeof("White");
+ 		value.addr = "White";
+ 		XrmPutResource(&newdb, "xfig*borderColor", "String",
+ 			       &value);
+ 		value.size = sizeof("White");
+ 		value.addr = "White";
+ 		XrmPutResource(&newdb, "xfig*foreground", "String",
+ 			       &value);
+ 		value.size = sizeof("Black");
+ 		value.addr = "Black";
+ 		XrmPutResource(&newdb, "xfig*background", "String",
+ 			       &value);
+ 		XrmMergeDatabases(newdb, &XtDefaultDB);
+ 
+ 		/* now set the tool part, since its already created */
+ 		XtSetArg(tmp_arg[0], XtNborderColor,
+ 			 WhitePixelOfScreen(tool_s));
+ 		XtSetArg(tmp_arg[1], XtNforeground,
+ 			 WhitePixelOfScreen(tool_s));
+ 		XtSetArg(tmp_arg[2], XtNbackground,
+ 			 BlackPixelOfScreen(tool_s));
+ 		XtSetValues(tool, tmp_arg, 3);
+ 	}
+ 	
  	init_font();
  	init_cursor();
  	form = XtCreateManagedWidget("form", formWidgetClass, tool,
***************
*** 264,270 ****
  		CANVAS_HEIGHT = landscape ? DEF_CANVAS_WIDTH :
  			DEF_CANVAS_HEIGHT;
  	
! 	if( CANVAS_HEIGHT < DEF_CANVAS_HEIGHT )
  		ICON_COLUMN = ICON_COLUMN_LAND;
  		
  	(void)init_panel(form);
--- 295,302 ----
  		CANVAS_HEIGHT = landscape ? DEF_CANVAS_WIDTH :
  			DEF_CANVAS_HEIGHT;
  	
! 	if( (CANVAS_HEIGHT < DEF_CANVAS_HEIGHT) ||
! 	   (HeightOfScreen(tool_s) < DEF_CANVAS_HEIGHT) )
  		ICON_COLUMN = ICON_COLUMN_LAND;
  		
  	(void)init_panel(form);
diff -c /tmp/version.h version.h
*** /tmp/version.h	Fri Aug 26 09:38:57 1988
--- version.h	Wed Aug 24 08:30:22 1988
***************
*** 8,11 ****
  */
  
  #define			FIG_VERSION		"1.4"
! #define			MINOR_VERSION		".2"
--- 8,11 ----
  */
  
  #define			FIG_VERSION		"1.4"
! #define			MINOR_VERSION		".3"
diff -c /tmp/xfig.1 xfig.1
*** /tmp/xfig.1	Fri Aug 26 09:38:59 1988
--- xfig.1	Thu Aug 25 15:34:19 1988
***************
*** 263,269 ****
  Create ellipses using the same procedure as for the drawing of circles.
  .TP
  .I GLUE
! Glue the primitive objects within a bounding box into a compound object
  (the bounding box itself is not part of the figure; 
  it is a visual aid for manipulating the compound). 
  .TP
--- 263,269 ----
  Create ellipses using the same procedure as for the drawing of circles.
  .TP
  .I GLUE
! Glue the objects within a bounding box into a compound object
  (the bounding box itself is not part of the figure; 
  it is a visual aid for manipulating the compound). 
  .TP
***************
*** 302,307 ****
--- 302,309 ----
  Only compound objects can be scaled.  Click the left button
  on a corner of the bounding box, stretch the
  bounding box to the desired size, and click the middle button.
+ Or click the left button on a side of the bounding box, stretch that
+ side to the desired size, and click the middle button.
  .TP
  .I SPLINE
  Create (quadratic spline) spline objects.
***************
*** 313,319 ****
  .I TEXT
  Create text strings. Click the left button at the desired position on
  the canvas window, then enter text from the keyboard.
! Terminate by clicking the middle button or typing the return key.
  .TP
  .I TURN
  Turn \fIPOLYGON\fP into a \fICLOSED INTERPOLATED SPLINE\fP object, or
--- 315,325 ----
  .I TEXT
  Create text strings. Click the left button at the desired position on
  the canvas window, then enter text from the keyboard.
! A DEL or ^H (backspace) will delete a character, while a ^U will kill
! the entire line.
! Terminate by clicking the middle button or typing the return key.  To
! edit text, click on an existing text string with the left button.
! Insertion of characters will take place at that point.  
  .TP
  .I TURN
  Turn \fIPOLYGON\fP into a \fICLOSED INTERPOLATED SPLINE\fP object, or
***************
*** 466,484 ****
  .SH ACKNOWLEDGEMENT
  Many thanks goes to Professor Donald E. Fussell who inspired the
  creation of this tool.
! .SH AUTHOR
  Supoj Sutanthavibul
  .br
  University of Texas at Austin 
  .br
! (supoj@sally.UTEXAS.EDU) 
  .sp
! Manual page modified by R. P. C. Rodgers, UCSF School of Pharmacy,
  San Francisco, CA 94118 
  .sp
! Frank Schmuck of Cornell contributed the LaTeX line drawing modes.
  .sp
! X11 port by Ken Yap (ken@cs.rochester.edu).
  .sp
  Variable window sizes, cleanup of X11 port, right hand side panel
! under X11, X11 manual page provided by Dana Chee (dana@bellcore.com).
--- 472,522 ----
  .SH ACKNOWLEDGEMENT
  Many thanks goes to Professor Donald E. Fussell who inspired the
  creation of this tool.
! .SH AUTHORS
! Original author:
! .br
  Supoj Sutanthavibul
  .br
  University of Texas at Austin 
  .br
! (supoj@sally.utexas.edu) 
  .sp
! Manual page modified by:
! .br
! R. P. C. Rodgers
! .br
! UCSF School of Pharmacy
! .br
  San Francisco, CA 94118 
  .sp
! The LaTeX line drawing modes were contributed by:
! .br
! Frank Schmuck
! .br
! Cornell University
  .sp
! X11 port by:
! .br
! Ken Yap
! .br
! Rochester
! .br
! (ken@cs.rochester.edu)
  .sp
  Variable window sizes, cleanup of X11 port, right hand side panel
! under X11, X11 manual page provided by:
! .br
! Dana Chee
! .br
! Bellcore
! .br
! (dana@bellcore.com)
! .sp
! Cleanup of color port to X11 by:
! .br
! John T. Kohl
! .br
! MIT
! .br
! (jtkohl@athena.mit.edu)
! 
diff -c /tmp/scale.c scale.c
*** /tmp/scale.c	Fri Aug 26 09:39:02 1988
--- scale.c	Thu Aug 25 15:51:04 1988
***************
*** 21,27 ****
  extern int		fix_x, fix_y, cur_x, cur_y;
  extern F_pos		last_position, new_position;  /* used in undo */
  
! extern F_compound	*compound_point_search();
  extern			(*canvas_kbd_proc)();
  extern			(*canvas_locmove_proc)();
  extern			(*canvas_leftbut_proc)();
--- 21,27 ----
  extern int		fix_x, fix_y, cur_x, cur_y;
  extern F_pos		last_position, new_position;  /* used in undo */
  
! extern F_compound	*compound_point_search(), *compound_search();
  extern			(*canvas_kbd_proc)();
  extern			(*canvas_locmove_proc)();
  extern			(*canvas_leftbut_proc)();
***************
*** 32,41 ****
  
  			prescale_compound(), elastic_compoundbox();
  
  static F_compound	*compound;
  static double		cosa, sina;
  static int		fromx, fromy;
- 
  			init_scale_compound();
  
  scale_compound_selected()
--- 32,42 ----
  
  			prescale_compound(), elastic_compoundbox();
  
+ static enum		{WEST, NORTH, EAST, SOUTH, CORNER} side;
+ static int		save_coord;
  static F_compound	*compound;
  static double		cosa, sina;
  static int		fromx, fromy;
  			init_scale_compound();
  
  scale_compound_selected()
***************
*** 53,89 ****
  int	x, y;
  {
  	double	dx, dy, l;
! 
! 	if ((compound = compound_point_search(x, y, TOLERANCE, &cur_x, &cur_y)) 
! 		== NULL) {
! 	    return;
! 	    }
! 	if (compound->nwcorner.x == cur_x) 
! 	    fix_x = compound->secorner.x;
! 	else
! 	    fix_x = compound->nwcorner.x;
! 	if (compound->nwcorner.y == cur_y) 
! 	    fix_y = compound->secorner.y;
! 	else
! 	    fix_y = compound->nwcorner.y;
! 
! 	dx = cur_x - fix_x;  dy = cur_y - fix_y;
! 	l = sqrt(dx*dx + dy*dy);
! 	cosa = fabs(dx / l);  sina = fabs(dy / l);
! 
! 	fromx = cur_x;  fromy = cur_y;
! 	win_setmouseposition(canvas_swfd, cur_x, cur_y);
! 	draw_compoundbox(compound, INV_PAINT);
! 	draw_rectbox(fix_x, fix_y, cur_x, cur_y, INV_PAINT);
! 	set_latestcompound(compound);
! 	canvas_locmove_proc = elastic_compoundbox;
! 	canvas_middlebut_proc = prescale_compound;
! 	canvas_leftbut_proc = canvas_rightbut_proc = null_proc;
! 	set_action_on();
! 	set_temp_cursor(&null_cursor);
! 	win_setmouseposition(canvas_swfd, x, y);
  	}
  
  elastic_compoundbox(x, y)
  int	x, y;
  {
--- 54,149 ----
  int	x, y;
  {
  	double	dx, dy, l;
! 	
! 	if ((compound = compound_point_search(x, y, TOLERANCE, &cur_x,
! 					      &cur_y)) != NULL)
! 	{
! 		if (compound->nwcorner.x == cur_x) 
! 			fix_x = compound->secorner.x;
! 		else
! 			fix_x = compound->nwcorner.x;
! 		if (compound->nwcorner.y == cur_y) 
! 			fix_y = compound->secorner.y;
! 		else
! 			fix_y = compound->nwcorner.y;
! 		
! 		side = CORNER;
! 		dx = cur_x - fix_x;  dy = cur_y - fix_y;
! 		l = sqrt(dx*dx + dy*dy);
! 		cosa = fabs(dx / l);  sina = fabs(dy / l);
! 		
! 		fromx = cur_x;  fromy = cur_y;
! 		win_setmouseposition(canvas_swfd, cur_x, cur_y);
! 		draw_compoundbox(compound, INV_PAINT);
! 		draw_rectbox(fix_x, fix_y, cur_x, cur_y, INV_PAINT);
! 		set_latestcompound(compound);
! 		canvas_locmove_proc = elastic_compoundbox;
! 		canvas_middlebut_proc = prescale_compound;
! 		canvas_leftbut_proc = canvas_rightbut_proc = null_proc;
! 		set_action_on();
! 		set_temp_cursor(&null_cursor);
! 		win_setmouseposition(canvas_swfd, x, y);
  	}
+ 	else if ((compound = compound_search(x, y, TOLERANCE, &cur_x, &cur_y))
+ 		 != NULL )
+ 	{
+ 		/* figure out which side the cursor is close to. */
+ 		if (compound->nwcorner.x == cur_x)
+ 			side = WEST;
+ 		else if (compound->nwcorner.y == cur_y)
+ 			side = NORTH;
+ 		else if (compound->secorner.x == cur_x)
+ 			side = EAST;
+ 		else if (compound->secorner.y == cur_y)
+ 			side = SOUTH;
+ 		else
+ 			return;
+ 		
+ 		/* figure out a fixed point of the compound for scaling */
+ 		switch (side) {
+ 		case WEST:
+ 		case NORTH:
+ 			fix_x = compound->secorner.x;
+ 			fix_y = compound->secorner.y;
+ 			cur_x = compound->nwcorner.x;
+ 			cur_y = compound->nwcorner.y;
+ 			break;
+ 		case EAST:
+ 		case SOUTH:
+ 			fix_x = compound->nwcorner.x;
+ 			fix_y = compound->nwcorner.y;
+ 			cur_x = compound->secorner.x;
+ 			cur_y = compound->secorner.y;
+ 			break;
+ 		}
+ 		
+ 		/* save initial corner position */
+ 		fromx = cur_x;  fromy = cur_y;
+ 		/* save x or y coordinate for restoring the cursor */
+ 		/* at the end of the scaling */
+ 		switch (side) {
+ 		case NORTH: case SOUTH:
+ 			save_coord = x;
+ 			break;
+ 		case EAST: case WEST:
+ 			save_coord = y;
+ 			break;
+ 		}
+ 		/*  erase the compound box. */
+ 		win_setmouseposition(canvas_swfd, cur_x, cur_y);
+ 		draw_compoundbox(compound, INV_PAINT);
+ 		draw_rectbox(fix_x, fix_y, cur_x, cur_y, INV_PAINT);
+ 		set_latestcompound(compound);
+ 		canvas_locmove_proc = elastic_compoundbox;
+ 		canvas_middlebut_proc = prescale_compound;
+ 		canvas_leftbut_proc = canvas_rightbut_proc = null_proc;
+ 		set_action_on();
+ 		set_temp_cursor(&null_cursor);
+ 		win_setmouseposition(canvas_swfd, x, y);
+ 	}
+ }
  
+ 
  elastic_compoundbox(x, y)
  int	x, y;
  {
***************
*** 98,115 ****
  {
  	double	xx, yy, d;
  
! 	xx = x - fix_x;
! 	yy = y - fix_y;
! 	d = sqrt(xx*xx + yy*yy);
! 	if (xx < 0)
! 	    cur_x = fix_x - round(d * cosa);
! 	else
! 	    cur_x = fix_x + round(d * cosa);
! 	if (yy < 0)
! 	    cur_y = fix_y - round(d * sina);
! 	else
! 	    cur_y = fix_y + round(d * sina);
  	}
  
  prescale_compound(x, y)
  int	x, y;
--- 158,187 ----
  {
  	double	xx, yy, d;
  
! 	switch(side) {
! 	case CORNER:
! 		xx = x - fix_x;
! 		yy = y - fix_y;
! 		d = sqrt(xx*xx + yy*yy);
! 		if (xx < 0)
! 			cur_x = fix_x - round(d * cosa);
! 		else
! 			cur_x = fix_x + round(d * cosa);
! 		if (yy < 0)
! 			cur_y = fix_y - round(d * sina);
! 		else
! 			cur_y = fix_y + round(d * sina);
! 		break;
! 	case NORTH:
! 	case SOUTH:
! 		cur_y = y;
! 		break;
! 	case EAST:
! 	case WEST:
! 		cur_x = x;
! 		break;
  	}
+ }
  
  prescale_compound(x, y)
  int	x, y;
***************
*** 130,135 ****
--- 202,218 ----
  	last_position.y = fromy;
  	new_position.x = cur_x;
  	new_position.y = cur_y;
+ 	/* update cursor position for single axis scaling. */
+ 	switch (side) {
+ 	case NORTH: case SOUTH:
+ 		/* maintain old horiz. pos. */
+ 		cur_x = save_coord;
+ 		break;
+ 	case EAST: case WEST:
+ 		/* maintain old vert. pos. */
+ 		cur_y = save_coord;
+ 		break;
+ 	}
  	clean_up();
  	set_action_object(F_SCALE, O_COMPOUND);
  	set_latestcompound(compound);
***************
*** 147,152 ****
--- 230,236 ----
  	F_ellipse	*e;
  	F_text		*t;
  	F_arc		*a;
+ 	F_compound	*c1;
  	int		x1, y1, x2, y2;
  
  	x1 = round(refx + (c->nwcorner.x - refx) * sx);
***************
*** 172,177 ****
--- 256,264 ----
  	    }
  	for (t = c->texts; t != NULL; t = t->next) {
  	    scale_text(t, sx, sy, refx, refy);
+ 	    }
+ 	for (c1 = c->compounds; c1 != NULL; c1 = c1->next) {
+ 	    scale_compound(c1, sx, sy, refx, refy);
  	    }
  	}
  
diff -c /tmp/canvas.c canvas.c
*** /tmp/canvas.c	Fri Aug 26 09:39:05 1988
--- canvas.c	Fri Aug 26 08:51:04 1988
***************
*** 150,155 ****
--- 150,156 ----
  	{ XtNhorizDistance, (XtArgVal)0 },
  	{ XtNfromVert, (XtArgVal)NULL },
  	{ XtNvertDistance, (XtArgVal)0 },
+ 	{ XtNtop, (XtArgVal)XtChainTop },
  };
  
  static void canvas_exposed(tool, event, params, nparams)
***************
*** 161,166 ****
--- 162,168 ----
  	if (((XExposeEvent *)event)->count > 0)
  		return;
  	redisplay_canvas();
+ 	redisplay_rulers();
  }
  
  static void set_pos(tool, event, params, nparams)
***************
*** 193,201 ****
--- 195,210 ----
  	<Key>:Event()\n\
  	<Expose>:Expose()\n";
  
+ static	Arg	canvas_color_args[] = {
+ 	{ XtNforeground, (XtArgVal) &x_fg_color.pixel },
+ 	{ XtNbackground, (XtArgVal) &x_bg_color.pixel },
+ };
+ 
  int init_canvas(tool)
  	TOOL		tool;
  {
+ 	XColor	fixcolors[2];
+ 	
  	canvas_args[3].value = CANVAS_WIDTH;
  	canvas_args[4].value = CANVAS_HEIGHT;
  	canvas_args[5].value = (XtArgVal)panel_sw;
***************
*** 202,207 ****
--- 211,233 ----
  	canvas_args[7].value = (XtArgVal)topruler_sw;
  	canvas_sw = XtCreateWidget("canvas", labelWidgetClass, tool,
  		canvas_args, XtNumber(canvas_args));
+ 	XtGetValues(canvas_sw, canvas_color_args, XtNumber(canvas_color_args));
+ 
+ 	/* get the RGB values for recolor cursor use -- may want to have
+ 	   cursor color resource */
+ 	fixcolors[0] = x_fg_color;
+ 	fixcolors[1] = x_bg_color;
+ 	XQueryColors(tool_d, DefaultColormapOfScreen(tool_s), fixcolors, 2);
+ 	x_fg_color = fixcolors[0];
+ 	x_bg_color = fixcolors[1];
+ 	
+ 	/* now fix the global GC */
+ 	XSetState(tool_d, gc, x_fg_color.pixel, x_bg_color.pixel, GXcopy,
+ 		  AllPlanes);
+ 	
+ 	/* and recolor the cursors */
+ 	recolor_cursors();
+ 	
  	canvas_leftbut_proc = null_proc;
  	canvas_middlebut_proc = null_proc;
  	canvas_rightbut_proc = null_proc;
***************
*** 240,245 ****
--- 266,286 ----
  	switch (event->type)
  	{
  	case MotionNotify:
+ 		{
+ 			Window rw, cw;
+ 			static int sx = -10000, sy = -10000;
+ 			int rx, ry, cx, cy;
+ 			unsigned int mask;
+ 
+ 			XQueryPointer(event->display, event->window,
+ 				      &rw, &cw,
+ 				      &rx, &ry,
+ 				      &cx, &cy,
+ 				      &mask);
+ 			if(cx == sx && cy == sy) break;
+ 			x = sx = cx;
+ 			y = sy = cy;
+ 		}
  		set_rulermark(x, y);
  		(*canvas_locmove_proc)(x, y);
  		break;
diff -c /tmp/cursor.c cursor.c
*** /tmp/cursor.c	Fri Aug 26 09:39:07 1988
--- cursor.c	Wed Aug 24 15:37:56 1988
***************
*** 106,109 ****
--- 106,128 ----
  	vbar_cursor.bitmap = (XImage *)XCreateFontCursor(d, XC_xterm);
  	wait_cursor.bitmap = (XImage *)XCreateFontCursor(d, XC_watch);
  }
+ recolor_cursors()
+ {
+ 	register Display  *d = tool_d;
+ 	
+ 	XRecolorCursor(d, (Cursor)arrow_cursor.bitmap, &x_fg_color, &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)bull_cursor.bitmap, &x_fg_color, &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)buster_cursor.bitmap, &x_fg_color, &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)char_cursor.bitmap, &x_fg_color, &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)crosshair_cursor.bitmap, &x_fg_color,
+ 		       &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)null_cursor.bitmap, &x_fg_color, &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)magnifier_cursor.bitmap, &x_fg_color,
+ 		       &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)pencil_cursor.bitmap, &x_fg_color, &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)pick15_cursor.bitmap, &x_fg_color, &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)pick9_cursor.bitmap, &x_fg_color, &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)vbar_cursor.bitmap, &x_fg_color, &x_bg_color);
+ 	XRecolorCursor(d, (Cursor)wait_cursor.bitmap, &x_fg_color, &x_bg_color);
+ }
  #endif	X11
diff -c /tmp/xtra.c xtra.c
*** /tmp/xtra.c	Fri Aug 26 09:39:09 1988
--- xtra.c	Fri Aug 26 08:51:07 1988
***************
*** 12,17 ****
--- 12,24 ----
  #include "paintop.h"
  #include "font.h"
  
+ #define	CTRL_H	8
+ #define	NL	10
+ #define	CR	13
+ #define	CTRL_U	21
+ #define	CTRL_X	24
+ #define	DEL	127
+ 
  pr_size pf_textwidth(n, f, s)
  	int		n;
  	XFontStruct	*f;
***************
*** 27,50 ****
  	return (ret);
  }
  
! static GC makegc(op)
  {
  	register GC	ngc;
  	XGCValues	gcv;
  
! 	ngc = XCreateGC(tool_d, XtWindow(canvas_sw), 0, &gcv);
! 	XCopyGC(tool_d, gc, ~0, ngc);
! 	XSetFunction(tool_d, ngc, op);
! 	XSetFont(tool_d, ngc, roman_font->fid);
  	return (ngc);
  }
  
  init_gc()
  {
! 	gccache[PAINT] = makegc(PAINT);
! 	gccache[ERASE] = makegc(ERASE);
! 	gccache[INV_PAINT] = makegc(INV_PAINT);
! 	gccache[MERGE] = makegc(MERGE);
  }
  
  /*
--- 34,110 ----
  	return (ret);
  }
  
! static GC makegc(op, fg, bg)
! int	op;
! Pixel	fg;
! Pixel	bg;
  {
  	register GC	ngc;
  	XGCValues	gcv;
+ 	int		gcmask;
  
! 	gcv.font = roman_font->fid;
! 	gcmask = GCFunction|GCForeground|GCBackground|GCFont;
! 	switch (op) {
! 	case PAINT:
! 		gcv.foreground = fg;
! 		gcv.background = bg;
! 		gcv.function = GXcopy;
! 		break;
! 	case ERASE:
! 		gcv.foreground = bg;
! 		gcv.background = bg;
! 		gcv.function = GXcopy;
! 		break;
! 	case INV_PAINT:
! 		gcv.foreground = fg ^ bg;
! 		gcv.background = bg;
! 		gcv.function = GXxor;
! 		break;
! 	case MERGE:
! 		gcv.foreground = fg;
! 		gcv.background = bg;
! 		gcv.function = GXor;
! 		break;
! 	}
! 	
! 	ngc = XCreateGC(tool_d, XtWindow(canvas_sw), gcmask, &gcv);
! 	XCopyGC(tool_d, gc, ~(gcmask), ngc);
  	return (ngc);
  }
  
+ static GC	msg_gccache[0x10];
+ 
  init_gc()
  {
! 	Pixel	bg, fg;
! 	Arg	tmp_arg[2];
! 	
! 	gccache[PAINT] = makegc(PAINT, x_fg_color.pixel, x_bg_color.pixel);
! 	gccache[ERASE] = makegc(ERASE, x_fg_color.pixel, x_bg_color.pixel);
! 	gccache[INV_PAINT] = makegc(INV_PAINT, x_fg_color.pixel,
! 				    x_bg_color.pixel);
! 	gccache[MERGE] = makegc(MERGE, x_fg_color.pixel, x_bg_color.pixel);
! 
! 	/* Need to get the values so we can make GC's which XOR correctly */
! 	XtSetArg(tmp_arg[0], XtNforeground, &fg);
! 	XtSetArg(tmp_arg[1], XtNbackground, &bg);
! 	XtGetValues(msg_sw, tmp_arg, 2);
! 
! 	msg_gccache[PAINT] = makegc(PAINT, fg, bg);
! 	msg_gccache[ERASE] = makegc(ERASE, fg, bg);
! 	
! 	XtSetArg(tmp_arg[0], XtNforeground, &fg);
! 	XtSetArg(tmp_arg[1], XtNbackground, &bg);
! 	XtGetValues(topruler_sw, tmp_arg, 2);
! 
! 	topgc = makegc(INV_PAINT, fg, bg);
! 	
! 	XtSetArg(tmp_arg[0], XtNforeground, &fg);
! 	XtSetArg(tmp_arg[1], XtNbackground, &bg);
! 	XtGetValues(sideruler_sw, tmp_arg, 2);
! 	
! 	sidegc = makegc(INV_PAINT, fg, bg);
  }
  
  /*
***************
*** 117,127 ****
  	XWindowAttributes	attr;
  
  	XClearArea(tool_d, msgswfd, 0, 0, 0, 0, False);
! 	/* uses knowledge that gccache[PAINT] uses roman_font - tsk */
  	len = strlen(prompt);
  	width = char_width(roman_font);
  	y = char_height(roman_font) + 2;
! 	XDrawString(tool_d, msgswfd, gccache[PAINT], 2, y, prompt, len);
  	x = width * len + 4;
  	XGetWindowAttributes(tool_d, msgswfd, &attr);
  	XSelectInput(tool_d, msgswfd, attr.your_event_mask | KeyPressMask);
--- 177,187 ----
  	XWindowAttributes	attr;
  
  	XClearArea(tool_d, msgswfd, 0, 0, 0, 0, False);
! 	/* uses knowledge that msg_gccache[PAINT] uses roman_font - tsk */
  	len = strlen(prompt);
  	width = char_width(roman_font);
  	y = char_height(roman_font) + 2;
! 	XDrawString(tool_d, msgswfd, msg_gccache[PAINT], 2, y, prompt, len);
  	x = width * len + 4;
  	XGetWindowAttributes(tool_d, msgswfd, &attr);
  	XSelectInput(tool_d, msgswfd, attr.your_event_mask | KeyPressMask);
***************
*** 134,161 ****
  			continue;
  		switch (buf[0])
  		{
! 		case '\b':
! 		case '\0177':
  			if (r != reply)
  			{
  				x -= width;
  				--r;
! 				XDrawString(tool_d, msgswfd, gccache[ERASE],
  					x, y, r, 1);
  			}
  			break;
! 		case 'U' & 0x1f:
! 		case 'X' & 0x1f:
  			while (r != reply)
  			{
  				x -= width;
  				--r;
! 				XDrawString(tool_d, msgswfd, gccache[ERASE],
  					x, y, r, 1);
  			}
  			break;
! 		case '\n':
! 		case '\r':
  			*r = '\0';
  			XClearArea(tool_d, msgswfd, 0, 0, 0, 0, False);
  			return;
--- 194,221 ----
  			continue;
  		switch (buf[0])
  		{
! 		case CTRL_H:
! 		case DEL:
  			if (r != reply)
  			{
  				x -= width;
  				--r;
! 				XDrawString(tool_d, msgswfd, msg_gccache[ERASE],
  					x, y, r, 1);
  			}
  			break;
! 		case CTRL_U:
! 		case CTRL_X:
  			while (r != reply)
  			{
  				x -= width;
  				--r;
! 				XDrawString(tool_d, msgswfd, msg_gccache[ERASE],
  					x, y, r, 1);
  			}
  			break;
! 		case CR:
! 		case NL:
  			*r = '\0';
  			XClearArea(tool_d, msgswfd, 0, 0, 0, 0, False);
  			return;
***************
*** 162,168 ****
  		default:
  			if (buf[0] < ' ' || buf[0] > '~')
  				continue;
! 			XDrawString(tool_d, msgswfd, gccache[PAINT],
  				x, y, buf, 1);
  			x += width;
  			*r++ = buf[0];
--- 222,228 ----
  		default:
  			if (buf[0] < ' ' || buf[0] > '~')
  				continue;
! 			XDrawString(tool_d, msgswfd, msg_gccache[PAINT],
  				x, y, buf, 1);
  			x += width;
  			*r++ = buf[0];
diff -c /tmp/glue.c glue.c
*** /tmp/glue.c	Fri Aug 26 09:39:11 1988
--- glue.c	Thu Aug 25 12:08:44 1988
***************
*** 106,111 ****
--- 106,113 ----
  		c->secorner.x, c->secorner.y);
  	get_arc(&c->arcs, c->nwcorner.x, c->nwcorner.y,
  		c->secorner.x, c->secorner.y);
+ 	get_compound(&c->compounds, c->nwcorner.x, c->nwcorner.y,
+ 		     c->secorner.x, c->secorner.y);
  	/*  get rid of point-marker  */
  	if (pointmarker_shown) toggle_compoundpointmarker(c);
  	if (c->ellipses != NULL) return(1);
***************
*** 113,118 ****
--- 115,121 ----
  	if (c->lines != NULL) return(1);
  	if (c->texts != NULL) return(1);
  	if (c->arcs != NULL) return(1);
+ 	if (c->compounds != NULL) return(1);
  	return(0);
  	}
  
***************
*** 269,274 ****
--- 272,318 ----
  	    }
  	}
  
+ get_compound(list, xmin, ymin, xmax, ymax)
+ F_compound	**list;
+ int	xmin, ymin, xmax, ymax;
+ {
+ 	F_compound	*compd, *c, *cc;
+ 	for (c = objects.compounds; c != NULL;)
+ 	{
+ 		if (xmin > c->nwcorner.x)
+ 		{
+ 			cc = c;
+ 			c = c->next;
+ 			continue;
+ 		}
+ 		if (xmax < c->secorner.x)
+ 		{
+ 			cc = c;
+ 			c = c->next;
+ 			continue;
+ 		}
+ 		if (ymin > c->nwcorner.y)
+ 		{
+ 			cc = c;
+ 			c = c->next;
+ 			continue;
+ 		}
+ 		if (ymax < c->secorner.y)
+ 		{
+ 			cc = c;
+ 			c = c->next;
+ 			continue;
+ 		}
+ 		compd = c;
+ 		if (c == objects.compounds) 
+ 			c = objects.compounds = objects.compounds->next;
+ 		else
+ 			c = cc->next = c->next;
+ 		compd->next = *list;
+ 		*list = compd;
+ 	}
+ }
+ 
  F_compound *
  compound_point_search(x, y, tol, px, py)
  int	x, y, tol, *px, *py;
***************
*** 308,314 ****
  F_compound	*c;
  {
  	draw_compoundelements(c, foreground_color, foreground_color,
! 				PAINT, PAINT, PAINT);
  	}
  
  erase_compound(c)
--- 352,358 ----
  F_compound	*c;
  {
  	draw_compoundelements(c, foreground_color, foreground_color,
! 				PAINT, PAINT, PAINT, PAINT);
  	}
  
  erase_compound(c)
***************
*** 315,326 ****
  F_compound	*c;
  {
  	draw_compoundelements(c, background_color, background_color,
! 				ERASE, ERASE, INV_PAINT);
  	}
  
! draw_compoundelements(c, arcop, ellipseop, lineop, splineop, textop)
  F_compound	*c;
! int		arcop, ellipseop, lineop, splineop, textop;
  {
  	F_line		*l;
  	F_spline	*s;
--- 359,370 ----
  F_compound	*c;
  {
  	draw_compoundelements(c, background_color, background_color,
! 				ERASE, ERASE, INV_PAINT, ERASE);
  	}
  
! draw_compoundelements(c, arcop, ellipseop, lineop, splineop, textop, compop)
  F_compound	*c;
! int		arcop, ellipseop, lineop, splineop, textop, compop;
  {
  	F_line		*l;
  	F_spline	*s;
***************
*** 327,333 ****
  	F_ellipse	*e;
  	F_text		*t;
  	F_arc		*a;
! 
  	pw_batch_on(canvas_pixwin);
  	for (l = c->lines; l != NULL; l = l->next) {
  	    draw_line(l, lineop);
--- 371,378 ----
  	F_ellipse	*e;
  	F_text		*t;
  	F_arc		*a;
! 	F_compound	*c1;
! 	
  	pw_batch_on(canvas_pixwin);
  	for (l = c->lines; l != NULL; l = l->next) {
  	    draw_line(l, lineop);
***************
*** 344,349 ****
--- 389,398 ----
  	for (t = c->texts; t != NULL; t = t->next) {
  	    draw_text(t, textop);
  	    }
+ 	for (c1 = c->compounds; c1 != NULL; c1 = c1->next) {
+ 	    draw_compoundbox(c1, INV_PAINT);
+ 	    compop == ERASE ? erase_compound(c1) : draw_compound(c1);
+ 	    }
  	pw_batch_off(canvas_pixwin);
  	}
  
***************
*** 414,416 ****
--- 463,468 ----
  	for (c = objects.compounds; c != NULL; c = c->next) 
  	    draw_compoundbox(c, INV_PAINT);
  	}
+ 
+ 
+ 
diff -c /tmp/resources.h resources.h
*** /tmp/resources.h	Fri Aug 26 09:39:14 1988
--- resources.h	Thu Aug 25 13:27:17 1988
***************
*** 146,152 ****
  EXTERN Display		*tool_d;
  EXTERN Screen		*tool_s;
  EXTERN int		tool_sn;
! EXTERN GC		gc, gccache[0x10];
  
  struct icon {
  	short	 	ic_width, ic_height;	/* overall icon dimensions */
--- 146,153 ----
  EXTERN Display		*tool_d;
  EXTERN Screen		*tool_s;
  EXTERN int		tool_sn;
! EXTERN GC		gc, gccache[0x10], topgc, sidegc;
! EXTERN XColor		x_fg_color, x_bg_color;
  
  struct icon {
  	short	 	ic_width, ic_height;	/* overall icon dimensions */
diff -c /tmp/global.c global.c
*** /tmp/global.c	Fri Aug 26 09:39:16 1988
--- global.c	Thu Aug 25 11:21:04 1988
***************
*** 115,120 ****
--- 115,121 ----
  int			DEBUG = 0;
  int			RHS_PANEL = 0;
  int			INVERSE = 0;
+ int			TRACKING = 1;
  
  /************************  Status  ****************************/
  
diff -c /tmp/popup.c popup.c
*** /tmp/popup.c	Fri Aug 26 09:39:18 1988
--- popup.c	Thu Aug 25 14:17:11 1988
***************
*** 96,102 ****
  	XtTranslations		popdown_actions, pane_actions;
  
  	menu = XtCreatePopupShell("popup_menu", overrideShellWidgetClass, tool,
! 		menu_args, 0);
  	popdown_actions = XtParseTranslationTable(
  		"<Btn3Up>:MenuPopdown()\n\
  		<LeaveWindow>:MenuPopdown()\n");
--- 96,102 ----
  	XtTranslations		popdown_actions, pane_actions;
  
  	menu = XtCreatePopupShell("popup_menu", overrideShellWidgetClass, tool,
! 		menu_args, XtNumber(menu_args));
  	popdown_actions = XtParseTranslationTable(
  		"<Btn3Up>:MenuPopdown()\n\
  		<LeaveWindow>:MenuPopdown()\n");
diff -c /tmp/flip.c flip.c
*** /tmp/flip.c	Fri Aug 26 09:39:21 1988
--- flip.c	Thu Aug 25 15:54:51 1988
***************
*** 371,376 ****
--- 371,377 ----
  	F_ellipse	*e;
  	F_spline	*s;
  	F_text		*t;
+ 	F_compound	*c1;
  	int		p, q;
  	
  	switch(flip_axis) {
***************
*** 397,400 ****
--- 398,403 ----
  	    flip_spline(s, x, y, flip_axis);
  	for (t = c->texts; t != NULL; t = t->next)
  	    flip_text(t, x, y, flip_axis);
+ 	for (c1 = c->compounds; c1 != NULL; c1 = c1->next)
+ 	    flip_compound(c1, x, y, flip_axis);
  	}
diff -c /tmp/rotate.c rotate.c
*** /tmp/rotate.c	Fri Aug 26 09:39:24 1988
--- rotate.c	Thu Aug 25 15:59:51 1988
***************
*** 441,446 ****
--- 441,447 ----
  	F_ellipse	*e;
  	F_spline	*s;
  	F_text		*t;
+ 	F_compound	*c1;
  	int		x1, y1, x2, y2;
  
  	switch(rotate_angle) {
***************
*** 471,474 ****
--- 472,477 ----
  	    rotate_spline(s, x, y, rotate_angle);
  	for (t = c->texts; t != NULL; t = t->next)
  	    rotate_text(t, x, y, rotate_angle);
+ 	for (c1 = c->compounds; c1 != NULL; c1 = c1->next)
+ 	    rotate_compound(c1, x, y, rotate_angle);
  	}
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330