[comp.sources.x] v12i019: tgif, Part03/23

william@CS.UCLA.EDU (William Cheng) (03/11/91)

Submitted-by: william@CS.UCLA.EDU (William Cheng)
Posting-number: Volume 12, Issue 19
Archive-name: tgif/part03

---------------------------------> cut here <---------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 23)."
# Contents:  drawing.c dup.c edit.c
# Wrapped by william@oahu on Wed Mar  6 09:57:03 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'drawing.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'drawing.c'\"
else
echo shar: Extracting \"'drawing.c'\" \(24657 characters\)
sed "s/^X//" >'drawing.c' <<'END_OF_FILE'
X/*
X * Author:	William Chia-Wei Cheng (william@cs.ucla.edu)
X *
X * Copyright (C) 1990, 1991, William Cheng.
X */
X#ifndef lint
Xstatic char RCSid[] =
X      "@(#)$Header: /tmp_mnt/n/kona/tangram/u/william/X11/TGIF2/RCS/drawing.c,v 2.0 91/03/05 15:26:27 william Exp $";
X#endif
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include "const.h"
X#include "types.h"
X
X#include "align.e"
X#include "animate.e"
X#include "arc.e"
X#include "attr.e"
X#include "box.e"
X#include "choice.e"
X#include "copypaste.e"
X#include "cursor.e"
X#include "dialog.e"
X#include "dup.e"
X#include "edit.e"
X#include "file.e"
X#include "font.e"
X#include "grid.e"
X#include "group.e"
X#include "mark.e"
X#include "menu.e"
X#include "msg.e"
X#include "obj.e"
X#include "oval.e"
X#include "pattern.e"
X#include "poly.e"
X#include "polygon.e"
X#include "raster.e"
X#include "rcbox.e"
X#include "rect.e"
X#include "ruler.e"
X#include "scroll.e"
X#include "select.e"
X#include "setup.e"
X#include "special.e"
X#include "stk.e"
X#include "stretch.e"
X#include "text.e"
X#include "xbitmap.e"
X
X#define O_VIS 4
X#define O_INVIS 4
X#define O_GRID (O_VIS+O_INVIS)
X
Xvoid SetDefaultDrawWinClipRecs ()
X{
X   XRectangle	recs[1];
X
X   SetRecVals (recs[0], 0, 0, drawWinW, drawWinH);
X   XSetClipRectangles (mainDisplay, drawGC, 0, 0, recs, 1, YXBanded);
X}
X
Xvoid SetDefaultIconWinClipRecs ()
X{
X   XRectangle	recs[1];
X
X   SetRecVals (recs[0], 0, 0, iconWindowW, iconWindowH);
X   XSetClipRectangles (mainDisplay, drawGC, 0, 0, recs, 1, YXBanded);
X}
X
Xstatic
Xvoid DrawHorizOutline (Win, Y, X1, X2, XStart, XEnd, Pixel)
X   Window	Win;
X   int		Y, X1, X2, XStart, XEnd, Pixel;
X   /* XStart and XEnd are the real place, X1 and X2 are on outline grid */
X{
X   register int	i;
X
X   if (XStart-X1 < O_VIS)
X      XDrawLine (mainDisplay, Win, defaultGC, XStart, Y, X1+O_VIS-1, Y);
X   for (i = X1+O_GRID; i < X2-O_GRID; i+= O_GRID)
X      XDrawLine (mainDisplay, Win, defaultGC, i, Y, i+O_VIS-1, Y);
X   if (X2-XEnd < O_VIS)
X      XDrawLine (mainDisplay, Win, defaultGC, X2-O_GRID, Y, XEnd, Y);
X   else
X      XDrawLine (mainDisplay, Win, defaultGC, X2-O_GRID, Y, X2-O_INVIS-1, Y);
X}
X
Xstatic
Xvoid DrawVertOutline (Win, X, Y1, Y2, YStart, YEnd, Pixel)
X   Window	Win;
X   int		X, Y1, Y2, YStart, YEnd, Pixel;
X   /* YStart and YEnd are the real place, Y1 and Y2 are on outline grid */
X{
X   register int	i;
X
X   if (YStart-Y1 < O_VIS)
X      XDrawLine (mainDisplay, Win, defaultGC, X, YStart, X, Y1+O_VIS-1);
X   for (i = Y1+O_GRID; i < Y2-O_GRID; i+= O_GRID)
X      XDrawLine (mainDisplay, Win, defaultGC, X, i, X, i+O_VIS-1);
X   if (Y2-YEnd < O_VIS)
X      XDrawLine (mainDisplay, Win, defaultGC, X, Y2-O_GRID, X, YEnd);
X   else
X      XDrawLine (mainDisplay, Win, defaultGC, X, Y2-O_GRID, X, Y2-O_INVIS-1);
X}
X
Xstatic
Xvoid DrawSymOutline (Win, XOff, YOff, ObjPtr)
X   Window		Win;
X   int			XOff, YOff;
X   struct ObjRec	* ObjPtr;
X{
X   int	ltx, lty, rbx, rby, x_start, x_end, y_start, y_end, pixel;
X
X   pixel = myFgPixel;
X
X   ltx = ((ObjPtr->obbox.ltx - XOff - QUARTER_INCH) >> zoomScale) + 1;
X   lty = ((ObjPtr->obbox.lty - YOff - QUARTER_INCH) >> zoomScale) + 1;
X   rbx = ((ObjPtr->obbox.rbx - XOff + QUARTER_INCH) >> zoomScale) - 1;
X   rby = ((ObjPtr->obbox.rby - YOff + QUARTER_INCH) >> zoomScale) - 1;
X
X   x_start = (ltx % O_GRID == 0) ? ltx : (int)(ltx / O_GRID) * O_GRID;
X   x_end = (rbx % O_GRID == 0) ? rbx : ((int)(rbx / O_GRID) + 1) * O_GRID;
X   DrawHorizOutline (Win, lty, x_start, x_end, ltx, rbx, pixel);
X   DrawHorizOutline (Win, rby, x_start, x_end, ltx, rbx, pixel);
X   y_start = (lty % O_GRID == 0) ? lty : (int)(lty / O_GRID) * O_GRID;
X   y_end = (rby % O_GRID == 0) ? rby : ((int)(rby / O_GRID) + 1) * O_GRID;
X   DrawVertOutline (Win, ltx, y_start, y_end, lty, rby, pixel);
X   DrawVertOutline (Win, rbx, y_start, y_end, lty, rby, pixel);
X}
X
Xvoid DrawObj (Win, ObjPtr)
X   Window			Win;
X   register struct ObjRec	* ObjPtr;
X{
X   register struct ObjRec	* obj_ptr;
X   register struct AttrRec	* attr_ptr;
X
X   switch (ObjPtr->type)
X   {
X      case OBJ_POLY:
X         DrawPolyObj (Win, drawOrigX, drawOrigY, ObjPtr); 
X         DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
X         break;
X      case OBJ_BOX:
X         DrawBoxObj (Win, drawOrigX, drawOrigY, ObjPtr);
X         DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
X         break;
X      case OBJ_OVAL:
X         DrawOvalObj (Win, drawOrigX, drawOrigY, ObjPtr);
X         DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
X         break;
X      case OBJ_TEXT: DrawTextObj (Win, drawOrigX, drawOrigY, ObjPtr); break;
X      case OBJ_POLYGON:
X         DrawPolygonObj (Win, drawOrigX, drawOrigY, ObjPtr);
X         DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
X         break;
X      case OBJ_ARC:
X         DrawArcObj (Win, drawOrigX, drawOrigY, ObjPtr);
X         DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
X         break;
X      case OBJ_RCBOX:
X         DrawRCBoxObj (Win, drawOrigX, drawOrigY, ObjPtr);
X         DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
X         break;
X      case OBJ_XBM:
X         DrawXBmObj (Win, drawOrigX, drawOrigY, ObjPtr);
X         DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
X         break;
X
X      case OBJ_SYM:
X      case OBJ_ICON:
X      case OBJ_GROUP:
X         obj_ptr = ObjPtr->detail.r->last;
X         for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->prev)
X            if (BBoxIntersect (obj_ptr->bbox, drawWinBBox))
X               DrawObj (Win, obj_ptr);
X         if (ObjPtr->type == OBJ_ICON && ObjPtr->dirty)
X         {
X            attr_ptr = ObjPtr->fattr;
X            for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X               UpdTextBBox (attr_ptr->obj);
X            AdjObjBBox (ObjPtr);
X            UpdSelBBox ();
X            ObjPtr->dirty = FALSE;
X         }
X         DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
X         if (ObjPtr->type == OBJ_SYM) DrawSymOutline (Win, drawOrigX, drawOrigY,
X               ObjPtr);
X         break;
X   }
X}
X
Xvoid DrawPaperBoundary ()
X{
X   register int	x_end, y_end;
X
X   if (drawOrigX+drawWinW > paperWidth)
X   {
X      x_end = OFFSET_X(paperWidth);
X      if (drawOrigY+drawWinH > paperHeight)
X      {
X         y_end = OFFSET_Y(paperHeight);
X         XDrawLine (mainDisplay, drawWindow, defaultGC, x_end, 0, x_end, y_end);
X         XDrawLine (mainDisplay, drawWindow, defaultGC, 0, y_end, x_end, y_end);
X      }
X      else
X         XDrawLine (mainDisplay, drawWindow, defaultGC, x_end, 0, x_end,
X               drawWinH>>zoomScale);
X   }
X   else if (drawOrigY+drawWinH > paperHeight)
X   {
X      y_end = OFFSET_Y(paperHeight);
X      XDrawLine (mainDisplay, drawWindow, defaultGC, 0, y_end,
X            drawWinW>>zoomScale, y_end);
X   }
X}
X
Xvoid RedrawAnArea (BotObj, LtX, LtY, RbX, RbY)
X   struct ObjRec	* BotObj;
X   int			LtX, LtY, RbX, RbY;
X   /* LtX, LtY, RbX, RbY are absolute coordinates */
X{
X   register struct ObjRec	* obj_ptr;
X   struct BBRec			bbox;
X   XRectangle			recs[1];
X
X   bbox.ltx = LtX; bbox.lty = LtY;
X   bbox.rbx = min(RbX, paperWidth);
X   bbox.rby = min(RbY, paperHeight);
X
X   SetRecVals (recs[0], OFFSET_X(LtX), OFFSET_Y(LtY), ((RbX-LtX)>>zoomScale)+1,
X         ((RbY-LtY)>>zoomScale)+1);
X   XSetClipRectangles (mainDisplay, drawGC, 0, 0, recs, 1, YXBanded);
X
X   XClearArea (mainDisplay, drawWindow, OFFSET_X(LtX), OFFSET_Y(LtY),
X         ((RbX-LtX)>>zoomScale)+1, ((RbY-LtY)>>zoomScale)+1, FALSE);
X
X   if (paperWidth >= LtX && paperWidth < RbX ||
X         paperHeight >= LtY && paperHeight < RbY)
X      DrawPaperBoundary ();
X
X   DrawGridLines (drawWindow, LtX, LtY, RbX+(1<<zoomScale), RbY+(1<<zoomScale));
X
X   for (obj_ptr = BotObj; obj_ptr != NULL; obj_ptr = obj_ptr->prev)
X      if (BBoxIntersect (obj_ptr->bbox, bbox) &&
X            BBoxIntersect (obj_ptr->bbox, drawWinBBox))
X         DrawObj (drawWindow, obj_ptr);
X
X   SetDefaultDrawWinClipRecs ();
X}
X
Xstatic
Xint Inside (BBox1, BBox2)
X   struct BBRec	BBox1, BBox2;
X{
X   return (BBox1.ltx >= BBox2.ltx && BBox1.lty >= BBox2.lty &&
X         BBox1.rbx <= BBox2.rbx && BBox1.rby <= BBox2.rby);
X}
X
Xvoid RedrawAreas (BotObj, LtX1, LtY1, RbX1, RbY1, LtX2, LtY2, RbX2, RbY2)
X   struct ObjRec	* BotObj;
X   int			LtX1, LtY1, RbX1, RbY1, LtX2, LtY2, RbX2, RbY2;
X   /* note:  these coordinates are absolute */
X{
X   register struct ObjRec	* obj_ptr;
X   int				ltx, lty, rbx, rby, rec1_slot, num;
X   struct BBRec			bbox1, bbox2;
X   XRectangle			recs[4];
X
X   bbox1.ltx = LtX1; bbox1.lty = LtY1;
X   bbox1.rbx = min(RbX1, paperWidth);
X   bbox1.rby = min(RbY1, paperHeight);
X   bbox2.ltx = LtX2; bbox2.lty = LtY2;
X   bbox2.rbx = min(RbX2, paperWidth);
X   bbox2.rby = min(RbY2, paperHeight);
X
X   if (Inside (bbox1, bbox2))
X   {
X      RedrawAnArea (BotObj, LtX2, LtY2, RbX2, RbY2);
X      return;
X   }
X   else if (Inside (bbox2, bbox1))
X   {
X      RedrawAnArea (BotObj, LtX1, LtY1, RbX1, RbY1);
X      return;
X   }
X
X   XClearArea (mainDisplay, drawWindow, OFFSET_X(LtX1), OFFSET_Y(LtY1),
X         ((RbX1-LtX1)>>zoomScale)+1, ((RbY1-LtY1)>>zoomScale)+1, FALSE);
X
X   if (BBoxIntersect (bbox1, bbox2))
X   {
X      ltx = min(LtX1,LtX2); lty = min(LtY1,LtY2);
X      rbx = max(RbX1,RbX2); rby = max(RbY1,RbY2);
X      RedrawAnArea (BotObj, ltx, lty, rbx, rby);
X      return;
X   }
X
X   if (LtY1 == LtY2)
X   {
X      rec1_slot = (LtX1 <= LtX2) ? 0 : 1;
X      SetRecVals (recs[rec1_slot], OFFSET_X(LtX1), OFFSET_Y(LtY1),
X            ((RbX1-LtX1)>>zoomScale)+1, ((RbY1-LtY1)>>zoomScale)+1);
X      SetRecVals (recs[!rec1_slot], OFFSET_X(LtX2), OFFSET_Y(LtY2),
X            ((RbX2-LtX2)>>zoomScale)+1, ((RbY2-LtY2)>>zoomScale)+1);
X      num = 2;
X   }
X   else
X   {
X      if (LtY1 < LtY2)
X      {
X         if (RbY1 <= LtY2)
X         {  /* y-extents do not intersect */
X            SetRecVals (recs[0], OFFSET_X(LtX1), OFFSET_Y(LtY1),
X                  ((RbX1-LtX1)>>zoomScale)+1, ((RbY1-LtY1)>>zoomScale)+1);
X            SetRecVals (recs[1], OFFSET_X(LtX2), OFFSET_Y(LtY2),
X                  ((RbX2-LtX2)>>zoomScale)+1, ((RbY2-LtY2)>>zoomScale)+1);
X            num = 2;
X         }
X         else if (RbY1 >= RbY2)
X         {  /* box 2's y-extents is inside box 1's y-extents */
X            rec1_slot = (LtX1 < LtX2) ? 0 : 1;  
X            SetRecVals (recs[rec1_slot], OFFSET_X(LtX1), OFFSET_Y(LtY1),
X                  ((RbX1-LtX1)>>zoomScale)+1, ((RbY1-LtY1)>>zoomScale)+1);
X            SetRecVals (recs[!rec1_slot], OFFSET_X(LtX2), OFFSET_Y(LtY2),
X                  ((RbX2-LtX2)>>zoomScale)+1, ((RbY2-LtY2)>>zoomScale)+1);
X            num = 2;
X         }
X         else
X         {  
X            SetRecVals (recs[0], OFFSET_X(LtX1), OFFSET_Y(LtY1),
X                  ((RbX1-LtX1)>>zoomScale)+1, ((LtY2-LtY1)>>zoomScale)+1);
X            if (LtX1 < LtX2)
X            {
X               SetRecVals (recs[1], OFFSET_X(LtX1), OFFSET_Y(LtY2),
X                     ((RbX1-LtX1)>>zoomScale)+1, ((RbY1-LtY2)>>zoomScale)+1);
X               SetRecVals (recs[2], OFFSET_X(LtX2), OFFSET_Y(LtY2),
X                     ((RbX2-LtX2)>>zoomScale)+1, ((RbY1-LtY2)>>zoomScale)+1);
X            }
X            else
X            {
X               SetRecVals (recs[1], OFFSET_X(LtX2), OFFSET_Y(LtY2),
X                     ((RbX2-LtX2)>>zoomScale)+1, ((RbY1-LtY2)>>zoomScale)+1);
X               SetRecVals (recs[2], OFFSET_X(LtX1), OFFSET_Y(LtY2),
X                     ((RbX1-LtX1)>>zoomScale)+1, ((RbY1-LtY2)>>zoomScale)+1);
X            }
X            SetRecVals (recs[3], OFFSET_X(LtX2), OFFSET_Y(RbY1),
X                  ((RbX2-LtX2)>>zoomScale)+1, ((RbY2-RbY1)>>zoomScale)+1);
X            num = 4;
X         }
X      }
X      else
X      {
X         if (RbY2 <= LtY1)
X         {  /* y-extents do not intersect */
X            SetRecVals (recs[0], OFFSET_X(LtX2), OFFSET_Y(LtY2),
X                  ((RbX2-LtX2)>>zoomScale)+1, ((RbY2-LtY2)>>zoomScale)+1);
X            SetRecVals (recs[1], OFFSET_X(LtX1), OFFSET_Y(LtY1),
X                  ((RbX1-LtX1)>>zoomScale)+1, ((RbY1-LtY1)>>zoomScale)+1);
X            num = 2;
X         }
X         else if (RbY2 >= RbY1)
X         {  /* box 1's y-extents is inside box 2's y-extents */
X            rec1_slot = (LtX1 < LtX2) ? 0 : 1;  
X            SetRecVals (recs[rec1_slot], OFFSET_X(LtX1), OFFSET_Y(LtY1),
X                  ((RbX1-LtX1)>>zoomScale)+1, ((RbY1-LtY1)>>zoomScale)+1);
X            SetRecVals (recs[!rec1_slot], OFFSET_X(LtX2), OFFSET_Y(LtY2),
X                  ((RbX2-LtX2)>>zoomScale)+1, ((RbY2-LtY2)>>zoomScale)+1);
X            num = 2;
X         }
X         else
X         {  
X            SetRecVals (recs[0], OFFSET_X(LtX2), OFFSET_Y(LtY2),
X                  ((RbX2-LtX2)>>zoomScale)+1, ((LtY1-LtY2)>>zoomScale)+1);
X            if (LtX1 < LtX2)
X            {
X               SetRecVals (recs[1], OFFSET_X(LtX1), OFFSET_Y(LtY1),
X                     ((RbX1-LtX1)>>zoomScale)+1, ((RbY2-LtY1)>>zoomScale)+1);
X               SetRecVals (recs[2], OFFSET_X(LtX2), OFFSET_Y(LtY1),
X                     ((RbX2-LtX2)>>zoomScale)+1, ((RbY2-LtY1)>>zoomScale)+1);
X            }
X            else
X            {
X               SetRecVals (recs[1], OFFSET_X(LtX2), OFFSET_Y(LtY1),
X                     ((RbX2-LtX2)>>zoomScale)+1, ((RbY2-LtY1)>>zoomScale)+1);
X               SetRecVals (recs[2], OFFSET_X(LtX1), OFFSET_Y(LtY1),
X                     ((RbX1-LtX1)>>zoomScale)+1, ((RbY2-LtY1)>>zoomScale)+1);
X            }
X            SetRecVals (recs[3], OFFSET_X(LtX1), OFFSET_Y(RbY2),
X                  ((RbX1-LtX1)>>zoomScale)+1, ((RbY1-RbY2)>>zoomScale)+1);
X            num = 4;
X         }
X      }
X   }
X   XSetClipRectangles (mainDisplay, drawGC, 0, 0, recs, num, YXSorted);
X
X   if (paperWidth >= LtX1 && paperWidth < RbX1 ||
X         paperHeight >= LtY1 && paperHeight < RbY1 ||
X         paperWidth >= LtX2 && paperWidth < RbX2 ||
X         paperHeight >= LtY2 && paperHeight < RbY2)
X      DrawPaperBoundary ();
X
X   DrawGridLines (drawWindow, LtX1, LtY1, RbX1+(1<<zoomScale),
X         RbY1+(1<<zoomScale));
X   DrawGridLines (drawWindow, LtX2, LtY2, RbX2+(1<<zoomScale),
X         RbY2+(1<<zoomScale));
X
X   for (obj_ptr = BotObj; obj_ptr != NULL; obj_ptr = obj_ptr->prev)
X   {
X      if (BBoxIntersect (obj_ptr->bbox, drawWinBBox) &&
X            (BBoxIntersect (obj_ptr->bbox, bbox1) ||
X            BBoxIntersect (obj_ptr->bbox, bbox2)))
X         DrawObj (drawWindow, obj_ptr);
X   }
X
X   SetDefaultDrawWinClipRecs ();
X}
X
XPixmap DrawAllOnPixmap (LtX, LtY, W, H)
X   int	*LtX, *LtY, *W, *H;
X{
X   register int			i;
X   register struct ObjRec	* obj_ptr;
X   int				len, ltx, lty, rbx, rby, w, h;
X   int				saved_draw_orig_x, saved_draw_orig_y;
X   int				saved_draw_win_w, saved_draw_win_h;
X   int                          saved_zoom_scale;
X   char				msg[MAXSTRING];
X   Pixmap			pixmap;
X   XGCValues			values;
X
X   ltx = botObj->bbox.ltx; lty = botObj->bbox.lty;
X   rbx = botObj->bbox.rbx; rby = botObj->bbox.rby;
X   for (obj_ptr = botObj->prev; obj_ptr != NULL; obj_ptr = obj_ptr->prev)
X   {
X      if (obj_ptr->bbox.ltx < ltx) ltx = obj_ptr->bbox.ltx;
X      if (obj_ptr->bbox.lty < lty) lty = obj_ptr->bbox.lty;
X      if (obj_ptr->bbox.rbx > rbx) rbx = obj_ptr->bbox.rbx;
X      if (obj_ptr->bbox.rby > rby) rby = obj_ptr->bbox.rby;
X   }
X   *W = w = rbx - ltx;
X   *H = h = rby - lty;
X   *LtX = ltx;
X   *LtY = lty;
X
X   saved_draw_orig_x = drawOrigX; saved_draw_orig_y = drawOrigY;
X   saved_draw_win_w = drawWinW; saved_draw_win_h = drawWinH;
X   saved_zoom_scale = zoomScale;
X
X   drawOrigX = ltx; drawOrigY = lty;
X   drawWinW = w; drawWinH = h;
X   zoomScale = 0;
X
X   pixmap = XCreatePixmap (mainDisplay, mainWindow, w, h, mainDepth);
X
X   if (pixmap == None)
X   {
X      sprintf (msg, "Can not allocate pixmap of size %1dx%1d.", w, h);
X      Msg (msg);
X      return (None);
X   }
X
X   values.foreground = myBgPixel;
X   values.function = GXcopy;
X   values.fill_style = FillSolid;
X   XChangeGC (mainDisplay, drawGC,
X         GCForeground | GCFunction | GCFillStyle, &values);
X   XFillRectangle (mainDisplay, pixmap, drawGC, 0, 0, w, h);
X
X   AdjSplineVs ();
X
X   for (obj_ptr = botObj; obj_ptr != NULL; obj_ptr = obj_ptr->prev)
X      DrawObj (pixmap, obj_ptr);
X
X   drawOrigX = saved_draw_orig_x; drawOrigY = saved_draw_orig_y;
X   drawWinW = saved_draw_win_w; drawWinH = saved_draw_win_h;
X   zoomScale = saved_zoom_scale;
X
X   AdjSplineVs ();
X
X   return (pixmap);
X}
X
Xvoid RedrawDrawWindow (BotObj)
X   struct ObjRec	* BotObj;
X{
X   register struct ObjRec	* obj_ptr;
X
X   DrawPaperBoundary ();
X   RedrawGridLines ();
X
X   for (obj_ptr = BotObj; obj_ptr != NULL; obj_ptr = obj_ptr->prev)
X      if (PointInBBox (obj_ptr->x, obj_ptr->y, drawWinBBox) ||
X            BBoxIntersect (obj_ptr->bbox, drawWinBBox))
X         DrawObj (drawWindow, obj_ptr);
X}
X
Xvoid ClearAndRedrawDrawWindow ()
X{
X   XClearWindow (mainDisplay, drawWindow);
X   RedrawDrawWindow (botObj);
X   RedrawCurText ();
X   HighLightForward ();
X}
X
Xvoid CleanUpDrawingWindow ()
X{
X   HighLightReverse ();
X   RemoveAllSel ();
X   DelAllObj ();
X   ClearCurText ();
X   SetCurChoice (NOTHING);
X}
X
Xint ShortHand (input)
X   XEvent	* input;
X   /* returns BAD if the character is a <CONTROL> or a <META> character */
X   /* returns INVALID if the character is a normal character */
X   /* otherwise, returns the value of sub-functions, such as QuitProc () */
X{
X   int			x, y;
X   char			buf[80];
X   KeySym		key_sym;
X   XComposeStatus	c_stat;
X   XKeyEvent		* key_ev;
X
X   key_ev = &(input->xkey);
X   XLookupString (key_ev, buf, 80, &key_sym, &c_stat);
X   if ((key_sym>='\040' && key_sym<='\177' ||
X         key_sym>='\240' && key_sym<='\377') &&
X         (key_ev->state & (ControlMask | Mod1Mask)))
X   {
X      Msg ("");
X      if ((key_ev->state & ControlMask) && (!(key_ev->state & Mod1Mask)))
X      {
X         switch (buf[0])
X         {
X            case '\001': /*^A*/ SelAllObj (); break;
X            case '\002': /*^B*/ BackProc (); break;
X            case '\003': /*^C*/ ChangeDomain (); break;
X            case '\004': /*^D*/ DupSelObj (); break;
X            case '\005': /*^E*/ break;
X            case '\006': /*^F*/ FrontProc (); break;
X            case '\007': /*^G*/ GroupSelObj (); break;
X            case '\010': /*^H*/ return (INVALID);
X            case '\011': /*^I*/ Instantiate (); break;
X            case '\012': /*^J*/ return (INVALID);
X            case '\013': /*^K*/ PopIcon (); break;
X            case '\014': /*^L*/ AlignSelObjs (); break;
X            case '\015': /*^M*/ return (INVALID);
X            case '\016': /*^N*/ NewProc (); break;
X            case '\017': /*^O*/ OpenProc (); break;
X            case '\020': /*^P*/ Dump (FALSE, ""); break;
X            case '\021': /*^Q*/ return (QuitProc ());
X            case '\022': /*^R*/ ClearAndRedrawDrawWindow (); break;
X            case '\023': /*^S*/ SaveFile (); break;
X            case '\024': /*^T*/ AlignSelToGrid (); break;
X            case '\025': /*^U*/ UngroupSelObj (); break;
X            case '\026': /*^V*/ PushIcon (); break;
X            case '\027': /*^W*/ SetCurChoice (DRAWTEXT); break;
X            case '\030': /*^X*/ DelAllSelObj (); break;
X            case '\031': /*^Y*/ CopyToCutBuffer (); break;
X            case '\032': /*^Z*/ return (AnimateProc ());
X            case ',': /*^,*/ ScrollLeft (); break;
X            case '.': /*^.*/ ScrollRight (); break;
X            case '-': /*^-*/ PrintWithCommand (FALSE, ""); break;
X         }
X      }
X      else if ((key_ev->state & Mod1Mask) && (!(key_ev->state & ControlMask)))
X      {
X         switch (buf[0])
X         {
X            case 'a': /*#A*/ AddAttrs (); break;
X            case 'b': /*#B*/ return (ProbeProc ());
X            case 'c': /*#C*/ RotateCounter (); break;
X            case 'd': /*#D*/ DecGrid (); break;
X            case 'e': /*#E*/ AnimateSel (); break;
X            case 'f': /*#F*/ FlashSelColor (); break;
X            case 'g': /*#G*/ ToggleGridShown (); break;
X            case 'h': /*#H*/ FlipHorizontal (); break;
X            case 'i': /*#I*/ IncGrid (); break;
X            case 'j': /*#J*/ HideAllAttrNames (); break;
X            case 'k': /*#K*/ SetCurChoice (NOTHING); break;
X            case 'l': /*#L*/ CornerLoop (&x, &y); LineStyleMenu (x, y); break;
X            case 'm': /*#M*/ MoveAttr (); break;
X            case 'n': /*#N*/ ShowAllAttrNames (); break;
X            case 'o': /*#O*/ ZoomOut (); break;
X            case 'p': /*#P*/ ImportFile (); break;
X            case 'q': /*#Q*/ SetCurChoice (DRAWPOLY); break;
X            case 'r': /*#R*/ SetCurChoice (DRAWBOX); break;
X            case 's': /*#S*/ return (SolveProc ());
X            case 't': /*#T*/ DetachAttrs (); break;
X            case 'u': /*#U*/ UndoDelete (); break;
X            case 'v': /*#V*/ FlipVertical (); break;
X            case 'w': /*#W*/ RotateClockWise (); break;
X            case 'x': /*#X*/ return (EscapeProc ());
X            case 'y': /*#Y*/ return (SimulateProc ());
X            case 'z': /*#Z*/ ZoomIn (); break;
X            case '0': /*#0*/ ChangeFontSize (0); break;
X            case '1': /*#1*/ ChangeFontSize (1); break;
X            case '2': /*#2*/ ChangeFontSize (2); break;
X            case '3': /*#3*/ ChangeFontSize (3); break;
X            case '4': /*#4*/ ChangeFontSize (4); break;
X            case '5': /*#5*/ ChangeFontSize (5); break;
X            case ',': /*#,*/ ScrollUp (); break;
X            case '.': /*#.*/ ScrollDown (); break;
X         }
X      }
X      else if ((key_ev->state & Mod1Mask) && (key_ev->state & ControlMask))
X      {
X         switch (buf[0])
X         {
X            case '\001': /*^#A*/ AddPoint (); break;
X            case '\002': /*^#B*/ ChangeFontStyle (STYLE_BR); break;
X            case '\003': /*^#C*/ ChangeFontJust (JUST_C); break;
X            case '\004': /*^#D*/ DeletePoint (); break;
X            case '\005': /*^#E*/ SetCurChoice (DRAWRCBOX); break;
X            case '\006': /*^#F*/ InvertXBitmaps (); break;
X            case '\007': /*^#G*/ ToggleSnapOn (); break;
X            case '\010': /*^#H*/ break;
X            case '\011': /*^#I*/ MakeIconic (); break;
X            case '\012': /*^#J*/ UnMakeIconic (); break;
X            case '\013': /*^#K*/ ToggleColorPostScript (); break;
X            case '\014': /*^#L*/ ChangeFontJust (JUST_L); break;
X            case '\015': /*^#M*/ MakeSymbolic (); break;
X            case '\016': /*^#N*/ UnMakeSymbolic (); break;
X            case '\017': /*^#O*/ ChangeFontStyle (STYLE_NR); break;
X            case '\020': /*^#P*/ ChangeFontStyle (STYLE_BI); break;
X            case '\021': /*^#Q*/ SetCurChoice (DRAWPOLYGON); break;
X            case '\022': /*^#R*/ ChangeFontJust (JUST_R); break;
X            case '\023': /*^#S*/ SaveNewFile (); break;
X            case '\024': /*^#T*/ ChangeFontStyle (STYLE_NI); break;
X            case '\025': /*^#U*/ UpdateSymbols (); break;
X            case '\026': /*^#V*/ SetCurChoice (DRAWCIRCLE); break;
X            case '\027': /*^#W*/ ToggleAllSelLineType (); break;
X            case '\030': /*^#X*/ ToggleWhereToPrint (); break;
X            case '\031': /*^#Y*/ PasteFromCutBuffer (); break;
X            case '\032': /*^#Z*/ SetCurChoice (DRAWARC); break;
X            case '.': /*^#.*/ ImportXBitmapFile (); break;
X         }
X      }
X      return (BAD);
X   }
X   return (INVALID);
X}
X
Xstatic
Xint SomethingDirty ()
X{
X   register struct ObjRec	* obj_ptr = topObj;
X
X   for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->next)
X      if (obj_ptr->dirty)
X         return (TRUE);
X   return (FALSE);
X}
X
Xint DrawingEventHandler (input)
X   XEvent	* input;
X{
X   int		mouse_x, mouse_y, grid_x, grid_y;
X   XEvent	ev;
X   XButtonEvent	* button_ev;
X
X   if (input->type == Expose)
X   {
X      XSync (mainDisplay, FALSE);
X      while (XCheckWindowEvent (mainDisplay, drawWindow, ExposureMask, &ev)) ;
X
X      if (topSel != NULL || SomethingDirty ())
X         ClearAndRedrawDrawWindow ();
X      else
X      {
X         RedrawDrawWindow (botObj);
X         RedrawCurText ();
X      }
X      return (INVALID);
X   }
X   else if (input->type == MotionNotify)
X   {
X      while (XCheckWindowEvent (mainDisplay,drawWindow,PointerMotionMask,&ev)) ;
X
X      mouse_x = (input->xmotion).x;
X      mouse_y = (input->xmotion).y;
X      GridXY (mouse_x, mouse_y, &grid_x, &grid_y);
X      MarkRulers (grid_x, grid_y);
X      return (INVALID);
X   }
X
X   if (input->type == ButtonPress)
X   {
X      button_ev = &(input->xbutton);
X      if ((button_ev->button == Button3) && (button_ev->state & ShiftMask))
X      {
X         SetCurChoice (NOTHING);
X         return (INVALID);
X      }
X      else if (button_ev->button == Button3)
X         return (MainMenu (button_ev));
X   }
X
X   Msg ("");
X   switch(curChoice)
X   {
X      case NOTHING: Select (input); break;
X      case DRAWTEXT: DrawText (input); break;
X      case DRAWBOX: DrawBox (input); break;
X      case DRAWCIRCLE: DrawOval (input); break;
X      case DRAWPOLY: DrawPoly (input); break;
X      case DRAWPOLYGON: DrawPolygon (input); break;
X      case DRAWARC: DrawArc (input); break;
X      case DRAWRCBOX: DrawRCBox (input); break;
X   }
X   return (INVALID);
X}
END_OF_FILE
if test 24657 -ne `wc -c <'drawing.c'`; then
    echo shar: \"'drawing.c'\" unpacked with wrong size!
fi
# end of 'drawing.c'
fi
if test -f 'dup.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dup.c'\"
else
echo shar: Extracting \"'dup.c'\" \(11685 characters\)
sed "s/^X//" >'dup.c' <<'END_OF_FILE'
X/*
X * Author:	William Chia-Wei Cheng (william@cs.ucla.edu)
X *
X * Copyright (C) 1990, 1991, William Cheng.
X */
X#ifndef lint
Xstatic char RCSid[] =
X      "@(#)$Header: /tmp_mnt/n/kona/tangram/u/william/X11/TGIF2/RCS/dup.c,v 2.0 91/03/05 12:47:04 william Exp $";
X#endif
X
X#include <X11/Xlib.h>
X#include "const.h"
X#include "types.h"
X
X#include "attr.e"
X#include "drawing.e"
X#include "grid.e"
X#include "obj.e"
X#include "raster.e"
X#include "select.e"
X#include "setup.e"
X#include "xbitmap.e"
X
Xextern struct ObjRec	* DupObj ();
X
Xint	justDupped = FALSE;
Xint	dupDx = INVALID, dupDy = INVALID;
X
Xvoid DupObjBasics (FromObjPtr, ToObjPtr)
X   register struct ObjRec	* FromObjPtr, * ToObjPtr;
X{
X   ToObjPtr->x = FromObjPtr->x;
X   ToObjPtr->y = FromObjPtr->y;
X   ToObjPtr->color = FromObjPtr->color;
X   ToObjPtr->id = objId++;
X   ToObjPtr->dirty = FALSE;
X   ToObjPtr->type = FromObjPtr->type;
X   ToObjPtr->bbox.ltx = FromObjPtr->bbox.ltx;
X   ToObjPtr->bbox.lty = FromObjPtr->bbox.lty;
X   ToObjPtr->bbox.rbx = FromObjPtr->bbox.rbx;
X   ToObjPtr->bbox.rby = FromObjPtr->bbox.rby;
X   ToObjPtr->obbox.ltx = FromObjPtr->obbox.ltx;
X   ToObjPtr->obbox.lty = FromObjPtr->obbox.lty;
X   ToObjPtr->obbox.rbx = FromObjPtr->obbox.rbx;
X   ToObjPtr->obbox.rby = FromObjPtr->obbox.rby;
X}
X
Xstatic
Xvoid DupPolyObj (PolyPtr, ObjPtr)
X   struct PolyRec	* PolyPtr;
X   struct ObjRec	* ObjPtr;
X{
X   register int			i, num_pts;
X   register struct PolyRec	* poly_ptr;
X   register XPoint		* v;
X
X   poly_ptr = (struct PolyRec *) calloc (1, sizeof(struct PolyRec));
X   num_pts = poly_ptr->n = PolyPtr->n;
X   v = (XPoint *) calloc (num_pts+1, sizeof(XPoint));
X   for (i = 0; i < num_pts; i++)
X   {
X      v[i].x = PolyPtr->vlist[i].x;
X      v[i].y = PolyPtr->vlist[i].y;
X   }
X   poly_ptr->vlist = v;
X   poly_ptr->style = PolyPtr->style;
X   poly_ptr->width = PolyPtr->width;
X   poly_ptr->pen = PolyPtr->pen;
X   poly_ptr->fill = PolyPtr->fill;
X   if ((poly_ptr->curved = PolyPtr->curved) == LT_SPLINE)
X   {
X      poly_ptr->sn = num_pts = PolyPtr->sn;
X      v = (XPoint *) calloc (num_pts+1, sizeof(XPoint));
X      for (i = 0; i < num_pts; i++)
X      {
X         v[i].x = PolyPtr->svlist[i].x;
X         v[i].y = PolyPtr->svlist[i].y;
X      }
X      poly_ptr->svlist = v;
X   }
X   poly_ptr->dash = PolyPtr->dash;
X
X   ObjPtr->detail.p = poly_ptr;
X}
X
Xstatic
Xvoid DupPolygonObj (PolygonPtr, ObjPtr)
X   struct PolygonRec	* PolygonPtr;
X   struct ObjRec	* ObjPtr;
X{
X   register int			i, num_pts;
X   register struct PolygonRec	* polygon_ptr;
X   XPoint			* v;
X
X   polygon_ptr = (struct PolygonRec *) calloc (1, sizeof(struct PolygonRec));
X   num_pts = polygon_ptr->n = PolygonPtr->n;
X   v = (XPoint *) calloc (num_pts+1, sizeof(XPoint));
X   for (i = 0; i < num_pts; i++)
X   {
X      v[i].x = PolygonPtr->vlist[i].x;
X      v[i].y = PolygonPtr->vlist[i].y;
X   }
X   polygon_ptr->vlist = v;
X   polygon_ptr->fill = PolygonPtr->fill;
X   polygon_ptr->width = PolygonPtr->width;
X   polygon_ptr->pen = PolygonPtr->pen;
X   if ((polygon_ptr->curved = PolygonPtr->curved) == LT_SPLINE)
X   {
X      polygon_ptr->sn = num_pts = PolygonPtr->sn;
X      v = (XPoint *) calloc (num_pts, sizeof(XPoint));
X      for (i = 0; i < num_pts; i++)
X      {
X         v[i].x = PolygonPtr->svlist[i].x;
X         v[i].y = PolygonPtr->svlist[i].y;
X      }
X      polygon_ptr->svlist = v;
X   }
X   polygon_ptr->dash = PolygonPtr->dash;
X
X   ObjPtr->detail.g = polygon_ptr;
X}
X
Xstatic
Xvoid DupOvalObj (OvalPtr, ObjPtr)
X   struct OvalRec	* OvalPtr;
X   struct ObjRec	* ObjPtr;
X{
X   register struct OvalRec	* oval_ptr;
X
X   oval_ptr = (struct OvalRec *) calloc (1, sizeof(struct OvalRec));
X   oval_ptr->fill = OvalPtr->fill;
X   oval_ptr->width = OvalPtr->width;
X   oval_ptr->pen = OvalPtr->pen;
X   oval_ptr->dash = OvalPtr->dash;
X
X   ObjPtr->detail.o = oval_ptr;
X}
X
Xstatic
Xvoid DupBoxObj (BoxPtr, ObjPtr)
X   struct BoxRec	* BoxPtr;
X   struct ObjRec	* ObjPtr;
X{
X   register struct BoxRec	* box_ptr;
X
X   box_ptr = (struct BoxRec *) calloc (1, sizeof(struct BoxRec));
X   box_ptr->fill = BoxPtr->fill;
X   box_ptr->width = BoxPtr->width;
X   box_ptr->pen = BoxPtr->pen;
X   box_ptr->dash = BoxPtr->dash;
X
X   ObjPtr->detail.b = box_ptr;
X}
X
Xstatic
Xvoid DupRCBoxObj (RCBoxPtr, ObjPtr)
X   struct RCBoxRec	* RCBoxPtr;
X   struct ObjRec	* ObjPtr;
X{
X   register struct RCBoxRec	* rcbox_ptr;
X
X   rcbox_ptr = (struct RCBoxRec *) calloc (1, sizeof(struct RCBoxRec));
X   rcbox_ptr->fill = RCBoxPtr->fill;
X   rcbox_ptr->width = RCBoxPtr->width;
X   rcbox_ptr->pen = RCBoxPtr->pen;
X   rcbox_ptr->dash = RCBoxPtr->dash;
X   rcbox_ptr->radius = RCBoxPtr->radius;
X
X   ObjPtr->detail.rcb = rcbox_ptr;
X}
X
Xstatic
Xvoid DupArcObj (ArcPtr, ObjPtr)
X   struct ArcRec	* ArcPtr;
X   struct ObjRec	* ObjPtr;
X{
X   register struct ArcRec	* arc_ptr;
X
X   arc_ptr = (struct ArcRec *) calloc (1, sizeof(struct ArcRec));
X   arc_ptr->fill = ArcPtr->fill;
X   arc_ptr->width = ArcPtr->width;
X   arc_ptr->pen = ArcPtr->pen;
X   arc_ptr->dash = ArcPtr->dash;
X
X   arc_ptr->xc = ArcPtr->xc;         arc_ptr->yc = ArcPtr->yc;
X   arc_ptr->x1 = ArcPtr->x1;         arc_ptr->y1 = ArcPtr->y1;
X   arc_ptr->x2 = ArcPtr->x2;         arc_ptr->y2 = ArcPtr->y2;
X   arc_ptr->dir = ArcPtr->dir;
X   arc_ptr->ltx = ArcPtr->ltx;       arc_ptr->lty = ArcPtr->lty;
X   arc_ptr->w = ArcPtr->w;           arc_ptr->h = ArcPtr->h;
X   arc_ptr->angle1 = ArcPtr->angle1; arc_ptr->angle2 = ArcPtr->angle2;
X
X   ObjPtr->detail.a = arc_ptr;
X}
X
Xstatic
Xvoid DupXBmObj (XBmPtr, ObjPtr)
X   struct XBmRec	* XBmPtr;
X   struct ObjRec	* ObjPtr;
X{
X   register struct XBmRec	* xbm_ptr;
X   Pixmap			bitmap;
X   int				w, h;
X
X   w = ObjPtr->obbox.rbx - ObjPtr->obbox.ltx;
X   h = ObjPtr->obbox.rby - ObjPtr->obbox.lty;
X
X   bitmap = XCreatePixmap (mainDisplay, mainWindow, w, h, 1);
X   XCopyArea (mainDisplay, XBmPtr->bitmap, bitmap, xbmGC, 0, 0, w, h, 0, 0);
X
X   xbm_ptr = (struct XBmRec *) calloc (1, sizeof(struct XBmRec));
X   xbm_ptr->bitmap = bitmap;
X   xbm_ptr->data = NULL;
X   xbm_ptr->fill = XBmPtr->fill;
X   ObjPtr->detail.xbm = xbm_ptr;
X}
X
Xvoid DupTextObj (TextPtr, ObjPtr)
X   struct TextRec	* TextPtr;
X   struct ObjRec	* ObjPtr;
X{
X   register int			i, num_lines;
X   register struct TextRec	* text_ptr;
X   struct StrRec		* first_str;
X   struct StrRec		* from_str_ptr, * to_str_ptr;
X
X   text_ptr = (struct TextRec *) calloc (1, sizeof(struct TextRec));
X   text_ptr->just = TextPtr->just;
X   num_lines = text_ptr->lines = TextPtr->lines;
X   from_str_ptr = TextPtr->last;
X   first_str = NULL;
X   for (i = 0; i < num_lines; i++, from_str_ptr = from_str_ptr->prev)
X   {
X      to_str_ptr = (struct StrRec *) calloc (1, sizeof(struct StrRec));
X      strcpy (to_str_ptr->s, from_str_ptr->s);
X      to_str_ptr->next = first_str;
X      if (first_str == NULL)
X         text_ptr->last = to_str_ptr;
X      else
X         first_str->prev = to_str_ptr;
X      first_str = to_str_ptr;
X   }
X   first_str->prev = NULL;
X   text_ptr->first = first_str;
X
X   text_ptr->font = TextPtr->font;
X   text_ptr->dpi = TextPtr->dpi;
X   text_ptr->style = TextPtr->style;
X   text_ptr->size = TextPtr->size;
X   text_ptr->rotate = TextPtr->rotate;
X   text_ptr->pen = TextPtr->pen;
X   text_ptr->asc = TextPtr->asc;
X   text_ptr->des = TextPtr->des;
X
X   ObjPtr->detail.t = text_ptr;
X}
X
Xstatic
Xvoid DupGroupObj (GroupPtr, ObjPtr)
X   struct GroupRec	* GroupPtr;
X   struct ObjRec	* ObjPtr;
X{
X   register struct GroupRec	* group_ptr;
X   struct ObjRec		* top_obj, * bot_obj;
X   struct ObjRec		* from_obj_ptr, * to_obj_ptr;
X
X   group_ptr = (struct GroupRec *) calloc (1, sizeof(struct GroupRec));
X   top_obj = bot_obj = NULL;
X   from_obj_ptr = GroupPtr->last;
X   for ( ; from_obj_ptr != NULL; from_obj_ptr = from_obj_ptr->prev)
X   {
X      to_obj_ptr = DupObj (from_obj_ptr);
X      to_obj_ptr->next = top_obj;
X      if (top_obj == NULL)
X         group_ptr->last = to_obj_ptr;
X      else
X         top_obj->prev = to_obj_ptr;
X      top_obj = to_obj_ptr;
X   }
X   top_obj->prev = NULL;
X   group_ptr->first = top_obj;
X
X   ObjPtr->detail.r = group_ptr;
X}
X
Xstruct ObjRec * DupObj (ObjPtr)
X   struct ObjRec	* ObjPtr;
X{
X   struct ObjRec	* obj_ptr;
X
X   obj_ptr = (struct ObjRec *) calloc (1, sizeof(struct ObjRec));
X   DupObjBasics (ObjPtr, obj_ptr);
X
X   switch (ObjPtr->type)
X   {
X      case OBJ_POLY:
X         DupPolyObj (ObjPtr->detail.p, obj_ptr);
X         DupAttrs (ObjPtr, obj_ptr);
X         break;
X      case OBJ_BOX:
X         DupBoxObj (ObjPtr->detail.b, obj_ptr);
X         DupAttrs (ObjPtr, obj_ptr);
X         break;
X      case OBJ_OVAL:
X         DupOvalObj (ObjPtr->detail.o, obj_ptr);
X         DupAttrs (ObjPtr, obj_ptr);
X         break;
X      case OBJ_TEXT: DupTextObj (ObjPtr->detail.t, obj_ptr); break;
X      case OBJ_POLYGON:
X         DupPolygonObj (ObjPtr->detail.g, obj_ptr);
X         DupAttrs (ObjPtr, obj_ptr);
X         break;
X      case OBJ_ARC:
X         DupArcObj (ObjPtr->detail.a, obj_ptr);
X         DupAttrs (ObjPtr, obj_ptr);
X         break;
X      case OBJ_RCBOX:
X         DupRCBoxObj (ObjPtr->detail.rcb, obj_ptr);
X         DupAttrs (ObjPtr, obj_ptr);
X         break;
X      case OBJ_XBM:
X         DupXBmObj (ObjPtr->detail.xbm, obj_ptr);
X         DupAttrs (ObjPtr, obj_ptr);
X         break;
X      case OBJ_SYM:
X      case OBJ_GROUP:
X      case OBJ_ICON:
X         DupGroupObj (ObjPtr->detail.r, obj_ptr);
X         DupAttrs (ObjPtr, obj_ptr);
X         if (obj_ptr->type == OBJ_ICON)
X            strcpy (obj_ptr->detail.r->s, ObjPtr->detail.r->s);
X         break;
X   }
X   return (obj_ptr);
X}
X
Xvoid DupSelObj ()
X{
X   struct SelRec	* sel_ptr, * sel_ptr1;
X   struct ObjRec	* obj_ptr, * top_obj, * bot_obj;
X   int			dx, dy;
X
X   if (topSel == NULL) return;
X
X   top_obj = bot_obj = NULL;
X   for (sel_ptr = botSel; sel_ptr != NULL; sel_ptr = sel_ptr->prev)
X   {
X      obj_ptr = DupObj (sel_ptr->obj);
X      obj_ptr->next = top_obj;
X      if (top_obj == NULL)
X         bot_obj = obj_ptr;
X      else
X         top_obj->prev = obj_ptr;
X      top_obj = obj_ptr;
X   }
X   top_obj->prev = NULL;
X
X   HighLightReverse ();
X
X   sel_ptr = botSel;
X   sel_ptr1 = sel_ptr->prev;
X   for (obj_ptr = bot_obj; sel_ptr1 != NULL; obj_ptr = obj_ptr->prev)
X   {
X      sel_ptr->obj = obj_ptr;
X      sel_ptr = sel_ptr1;
X      sel_ptr1 = sel_ptr1->prev;
X   }
X   sel_ptr->obj = obj_ptr;
X
X   bot_obj->next = topObj;
X   topObj->prev = bot_obj;
X   topObj = top_obj;
X
X   if (justDupped)
X   {
X      dx = dupDx;
X      dy = dupDy;
X   }
X   else
X   {
X      if (gridOn)
X         dupDx = dupDy = dx = dy = xyGrid << zoomScale;
X      else
X         dupDx = dupDy = dx = dy = DEFAULT_GRID << zoomScale;
X      justDupped = TRUE;
X   }
X
X   selLtX += dx; selLtY += dy; selRbX += dx; selRbY += dy;
X   selObjLtX += dx; selObjLtY += dy; selObjRbX += dx; selObjRbY += dy;
X
X   MoveAllSel (dx, dy);
X   RedrawAnArea (botObj, selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
X         selRbX+(1<<zoomScale), selRbY+(1<<zoomScale));
X   HighLightForward ();
X   SetFileModified (TRUE);
X}
X
Xvoid JustDupSelObj (NewTopSel, NewBotSel)
X   struct SelRec	* * NewTopSel, * * NewBotSel;
X{
X   struct SelRec	* sel_ptr, * new_sel_ptr;
X   struct ObjRec	* obj_ptr, * top_obj, * bot_obj;
X
X   *NewTopSel = *NewBotSel = NULL;
X   if (topSel == NULL) return;
X
X   top_obj = bot_obj = NULL;
X   for (sel_ptr = botSel; sel_ptr != NULL; sel_ptr = sel_ptr->prev)
X   {
X      obj_ptr = DupObj (sel_ptr->obj);
X      obj_ptr->next = top_obj;
X      new_sel_ptr = (struct SelRec *) calloc (1, sizeof (struct SelRec));
X      new_sel_ptr->next = *NewTopSel;
X      new_sel_ptr->obj = obj_ptr;
X      if (top_obj == NULL)
X      {
X         bot_obj = obj_ptr;
X         *NewBotSel = new_sel_ptr;
X      }
X      else
X      {
X         top_obj->prev = obj_ptr;
X         (*NewTopSel)->prev = new_sel_ptr;
X      }
X      top_obj = obj_ptr;
X      *NewTopSel = new_sel_ptr;
X   }
X   top_obj->prev = NULL;
X   (*NewTopSel)->prev = NULL;
X}
END_OF_FILE
if test 11685 -ne `wc -c <'dup.c'`; then
    echo shar: \"'dup.c'\" unpacked with wrong size!
fi
# end of 'dup.c'
fi
if test -f 'edit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'edit.c'\"
else
echo shar: Extracting \"'edit.c'\" \(29266 characters\)
sed "s/^X//" >'edit.c' <<'END_OF_FILE'
X/*
X * Author:	William Chia-Wei Cheng (william@cs.ucla.edu)
X *
X * Copyright (C) 1990, 1991, William Cheng.
X */
X#ifndef lint
Xstatic char RCSid[] =
X      "@(#)$Header: /tmp_mnt/n/kona/tangram/u/william/X11/TGIF2/RCS/edit.c,v 2.0 91/03/05 12:47:06 william Exp $";
X#endif
X
X#include <stdio.h>
X#include <math.h>
X#include <X11/Xlib.h>
X#include "const.h"
X#include "types.h"
X
X#include "align.e"
X#include "color.e"
X#include "copypaste.e"
X#include "cursor.e"
X#include "drawing.e"
X#include "dup.e"
X#include "font.e"
X#include "group.e"
X#include "mark.e"
X#include "obj.e"
X#include "poly.e"
X#include "raster.e"
X#include "select.e"
X#include "setup.e"
X#include "special.e"
X#include "spline.e"
X#include "stretch.e"
X#include "xbitmap.e"
X
X#ifndef M_PI
X#define M_PI 3.14159265358979323846
X#endif
X
X#define MARK(X,Y) \
X      XFillRectangle(mainDisplay,drawWindow,revDefaultGC,(X)-2,(Y)-2,5,5)
X#define MyDashedLine(W,GC,V,N) XDrawLines (mainDisplay, W, GC, V, N, \
X      CoordModeOrigin)
X
X#define EDIT_REDRAW 0
X#define EDIT_DUP 1
X#define EDIT_DELETE 2
X#define EDIT_SELALL 3
X#define EDIT_UNDODEL 4
X#define EDIT_DEL_POINT 5
X#define EDIT_ADD_POINT 6
X#define EDIT_COPY 7
X#define EDIT_PASTE 8
X#define EDIT_INV_XBM 9
X
X#define MAXEDITMENUS 10
X
Xstatic char * editMenuStr[] =
X      { "Redraw         ^R",
X        "Duplicate      ^D",
X        "Delete         ^X",
X        "SelectAll      ^A",
X        "UndoDelete     #U",
X        "DeletePoint   ^#D",
X        "AddPoint      ^#A",
X        "Copy           ^Y",
X        "Paste         ^#Y",
X        "InvertXBitmap ^#F"
X      };
X
Xvoid DeletePoint ()
X{
X   register int			i;
X   register struct ObjRec	* obj_ptr;
X   struct PolyRec		* poly_ptr = NULL;
X   struct PolygonRec		* polygon_ptr = NULL;
X   int				index, n, point_deleted, deleting = TRUE;
X   int				root_x, root_y, old_x, old_y;
X   unsigned int			status;
X   Window			root_win, child_win;
X   XEvent			input, ev;
X
X   if (!(topSel != NULL && topSel == botSel &&
X         (topSel->obj->type == OBJ_POLY || topSel->obj->type == OBJ_POLYGON)))
X   {
X      Msg ("Please select only one POLY or POLYGON object.");
X      return;
X   }
X
X   obj_ptr = topSel->obj;
X   switch (obj_ptr->type)
X   {
X      case OBJ_POLY: poly_ptr = obj_ptr->detail.p; break;
X      case OBJ_POLYGON: polygon_ptr = obj_ptr->detail.g; break;
X   }
X   TwoLineMsg ("Click left mouse button to DELETE points.",
X         "Click other buttons to quit.");
X
X   XGrabPointer (mainDisplay, drawWindow, False,
X         PointerMotionMask | ButtonPressMask,
X         GrabModeAsync, GrabModeAsync, None, defaultCursor, CurrentTime);
X   XQueryPointer (mainDisplay, drawWindow, &root_win, &child_win,
X         &root_x, &root_y, &old_x, &old_y, &status);
X   XSetFont (mainDisplay, revDefaultGC, defaultFontPtr->fid);
X   XDrawString (mainDisplay, drawWindow, revDefaultGC,
X         old_x+4, old_y+defaultFontAsc, "DEL", 3);
X   MarkRulers (old_x, old_y);
X
X   while (deleting)
X   {
X      XNextEvent (mainDisplay, &input);
X      if (input.type == ButtonPress)
X      {
X         if (input.xbutton.button == Button1)
X         {
X            point_deleted = FALSE;
X            if (obj_ptr->type == OBJ_POLY &&
X                  PtInPolyMark (input.xbutton.x, input.xbutton.y,
X                  poly_ptr->n, poly_ptr->vlist, &index) ||
X                  obj_ptr->type == OBJ_POLYGON &&
X                  PtInPolyMark (input.xbutton.x, input.xbutton.y,
X                  polygon_ptr->n-1, polygon_ptr->vlist, &index))
X            {
X               point_deleted = TRUE;
X               HighLightReverse ();
X               if (obj_ptr->type == OBJ_POLY && poly_ptr->n == 2 ||
X                     obj_ptr->type == OBJ_POLYGON && polygon_ptr->n == 4)
X               {
X                  CopySelToCut ();
X                  DelObj (obj_ptr);
X                  deleting = FALSE;
X                  obj_ptr = NULL;
X                  cfree (topSel);
X                  topSel = botSel = NULL;
X               }
X               else
X               {
X                  switch (obj_ptr->type)
X                  {
X                     case OBJ_POLY:
X                        n = poly_ptr->n;
X                        for (i = index+1; i < n; i++)
X                           poly_ptr->vlist[i-1] = poly_ptr->vlist[i];
X                        poly_ptr->n--;
X                        if (poly_ptr->curved)
X                        {
X                           cfree (poly_ptr->svlist);
X                           poly_ptr->svlist = MakeSplinePolyVertex (
X                                 &(poly_ptr->sn), drawOrigX, drawOrigY,
X                                 poly_ptr->n, poly_ptr->vlist);
X                        }
X                        UpdPolyBBox (obj_ptr, poly_ptr->n, poly_ptr->vlist);
X                        break;
X                     case OBJ_POLYGON:
X                        n = polygon_ptr->n;
X                        for (i = index+1; i < n; i++)
X                           polygon_ptr->vlist[i-1] = polygon_ptr->vlist[i];
X                        polygon_ptr->n--;
X                        n--;
X                        if (index == 0)
X                           polygon_ptr->vlist[n-1] = polygon_ptr->vlist[0];
X                        if (polygon_ptr->curved)
X                        {
X                           cfree (polygon_ptr->svlist);
X                           polygon_ptr->svlist = MakeSplinePolygonVertex (
X                                 &(polygon_ptr->sn), drawOrigX, drawOrigY,
X                                 polygon_ptr->n, polygon_ptr->vlist);
X                        }
X                        UpdPolyBBox (obj_ptr, polygon_ptr->n,
X                              polygon_ptr->vlist);
X                        break;
X                  }
X                  AdjObjBBox (obj_ptr);
X               }
X            }
X            if (point_deleted)
X            {
X               XDrawString (mainDisplay, drawWindow, revDefaultGC, old_x+4,
X                     old_y+defaultFontAsc, "DEL", 3);
X               old_x = input.xbutton.x;
X               old_y = input.xbutton.y;
X               RedrawAnArea (botObj,
X                     selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
X                     selRbX+(1<<zoomScale), selRbY+(1<<zoomScale));
X               HighLightForward ();
X               if (obj_ptr != NULL)
X                  XDrawString (mainDisplay, drawWindow, revDefaultGC, old_x+4,
X                        old_y+defaultFontAsc, "DEL", 3);
X               UpdSelBBox ();
X               SetFileModified (TRUE);
X            }
X         }
X         else
X         {
X            deleting = FALSE;
X            XDrawString (mainDisplay, drawWindow, revDefaultGC,
X                  old_x+4, old_y+defaultFontAsc, "DEL", 3);
X         }
X      }
X      else if (input.type == MotionNotify)
X      {
X         XDrawString (mainDisplay, drawWindow, revDefaultGC,
X               old_x+4, old_y+defaultFontAsc, "DEL", 3);
X         old_x = input.xmotion.x;
X         old_y = input.xmotion.y;
X         XDrawString (mainDisplay, drawWindow, revDefaultGC,
X               old_x+4, old_y+defaultFontAsc, "DEL", 3);
X         MarkRulers (old_x, old_y);
X         while (XCheckMaskEvent (mainDisplay, PointerMotionMask, &ev)) ;
X      }
X   }
X   XUngrabPointer (mainDisplay, CurrentTime);
X   Msg ("");
X}
X
Xstatic
Xvoid ContinueAddPolyPoint (ObjPtr, MouseX, MouseY, Index, PolyPtr,
X      LastMouseX, LastMouseY)
X   struct ObjRec	* ObjPtr;
X   int			MouseX, MouseY, Index;
X   struct PolyRec	* PolyPtr;
X   int			* LastMouseX, * LastMouseY;
X   /* (MouseX,MouseY) is the mouse's origin in screen offsets */
X{
X   int		n = PolyPtr->n;
X   int		already_moved = FALSE, done = FALSE, before = FALSE;
X   XPoint	* vs = PolyPtr->vlist, v[3];
X   int		prev_x, prev_y, x, y, next_x, next_y, new_x, new_y;
X   int		orig_x, orig_y, grid_x, grid_y, new_mouse_x, new_mouse_y;
X   int		sel_ltx, sel_lty, sel_rbx, sel_rby, num = 0, i;
X   double	prev_angle, next_angle, new_angle, theta_1, theta_2;
X   XEvent	input, ev;
X
X   MARK(OFFSET_X(vs[Index].x), OFFSET_Y(vs[Index].y));
X
X   sel_ltx =  selLtX; sel_lty = selLtY;
X   sel_rbx =  selRbX; sel_rby = selRbY;
X
X   x = vs[Index].x;
X   y = vs[Index].y;
X
X   if (Index == 0)
X   {
X      next_x = vs[1].x;    next_y = vs[1].y;
X      prev_x = 2*x-next_x; prev_y = 2*y-next_y;
X   }
X   else if (Index == n-1)
X   {
X      prev_x = vs[n-2].x;  prev_y = vs[n-2].y;
X      next_x = 2*x-prev_x; next_y = 2*y-prev_y;
X   }
X   else
X   {
X      prev_x = vs[Index-1].x; prev_y = vs[Index-1].y;
X      next_x = vs[Index+1].x; next_y = vs[Index+1].y;
X   }
X   prev_angle = atan2 ((double)(prev_y-y), (double)(prev_x-x));
X   next_angle = atan2 ((double)(next_y-y), (double)(next_x-x));
X
X   GridXY (MouseX, MouseY, &orig_x, &orig_y);
X   new_mouse_x = MouseX; new_mouse_y = MouseY;
X   XDrawString (mainDisplay, drawWindow, revDefaultGC, new_mouse_x+4,
X         new_mouse_y+defaultFontAsc, "ADD", 3);
X
X   while (!done)
X   {
X      XNextEvent (mainDisplay, &input);
X      if (input.type == MotionNotify)
X      {
X         XDrawString (mainDisplay, drawWindow, revDefaultGC, new_mouse_x+4,
X               new_mouse_y+defaultFontAsc, "ADD", 3);
X         new_mouse_x = input.xmotion.x;
X         new_mouse_y = input.xmotion.y;
X         XDrawString (mainDisplay, drawWindow, revDefaultGC, new_mouse_x+4,
X               new_mouse_y+defaultFontAsc, "ADD", 3);
X
X         GridXY (new_mouse_x, new_mouse_y, &grid_x, &grid_y);
X         new_x = ((new_mouse_x-MouseX)<<zoomScale) + x;
X         new_y = ((new_mouse_y-MouseY)<<zoomScale) + y;
X         if (!already_moved)
X         {
X            already_moved = TRUE;
X
X            new_angle = atan2 ((double)(new_y-y), (double)(new_x-x));
X            theta_1 = fabs (prev_angle - new_angle);
X            theta_2 = fabs (next_angle - new_angle);
X            if (theta_1 > M_PI) theta_1 = 2*M_PI-theta_1;
X            if (theta_2 > M_PI) theta_2 = 2*M_PI-theta_2;
X            before = (theta_1 <= theta_2);
X
X            if (before)
X            {  /* Add a point between the current and the previous point */
X               if (Index == 0)
X               {
X                  num = 2;
X                  v[0].x = OFFSET_X(x); v[0].y = OFFSET_Y(y);
X                  v[1].x = OFFSET_X(x); v[1].y = OFFSET_Y(y);
X               }
X               else
X               {
X                  num = 3;
X                  v[0].x = OFFSET_X(prev_x); v[0].y = OFFSET_Y(prev_y);
X                  v[1].x = OFFSET_X(x);      v[1].y = OFFSET_Y(y);
X                  v[2].x = OFFSET_X(x);      v[2].y = OFFSET_Y(y);
X               }
X            }
X            else
X            {  /* Add a point between the current and the next point */
X               if (Index == n-1)
X               {
X                  num = 2;
X                  v[0].x = OFFSET_X(x);      v[0].y = OFFSET_Y(y);
X                  v[1].x = OFFSET_X(x);      v[1].y = OFFSET_Y(y);
X               }
X               else
X               {
X                  num = 3;
X                  v[0].x = OFFSET_X(x);      v[0].y = OFFSET_Y(y);
X                  v[1].x = OFFSET_X(x);      v[1].y = OFFSET_Y(y);
X                  v[2].x = OFFSET_X(next_x); v[2].y = OFFSET_Y(next_y);
X               }
X            }
X            MyDashedLine (drawWindow, revDefaultGC, v, num);
X         }
X         else
X         {
X            MyDashedLine (drawWindow, revDefaultGC, v, num);
X            v[1].x = OFFSET_X(x) + grid_x - orig_x;
X            v[1].y = OFFSET_Y(y) + grid_y - orig_y;
X            MyDashedLine (drawWindow, revDefaultGC, v, num);
X            MarkRulers (grid_x, grid_y);
X         }
X         while (XCheckMaskEvent (mainDisplay, PointerMotionMask, &ev)) ;
X      }
X      else if (input.type == ButtonRelease)
X      {
X         done = TRUE;
X         *LastMouseX = new_mouse_x; *LastMouseY = new_mouse_y;
X         MARK(OFFSET_X(vs[Index].x), OFFSET_Y(vs[Index].y));
X         XDrawString (mainDisplay, drawWindow, revDefaultGC, new_mouse_x+4,
X               new_mouse_y+defaultFontAsc, "ADD", 3);
X
X         if (!already_moved)
X            continue;
X         else
X         {
X            MyDashedLine (drawWindow, revDefaultGC, v, num);
X            if (grid_x == orig_x && grid_y == orig_y)
X               continue;
X         }
X
X         HighLightReverse ();
X         vs = (XPoint *) realloc (vs, (n+2)*sizeof(XPoint));
X         if (vs == NULL)
X         {
X            printf ("Can not realloc () in ContinueAddPolyPoint ().\n");
X            exit (-1);
X         }
X         PolyPtr->vlist = vs;
X         if (before)
X         {
X            for (i = n-1; i >= Index; i--) vs[i+1] = vs[i];
X            vs[Index].x = x + ((grid_x-orig_x)<<zoomScale);
X            vs[Index].y = y + ((grid_y-orig_y)<<zoomScale);
X         }
X         else
X         {
X            for (i = n-1; i > Index; i--) vs[i+1] = vs[i];
X            vs[Index+1].x = x + ((grid_x-orig_x)<<zoomScale);
X            vs[Index+1].y = y + ((grid_y-orig_y)<<zoomScale);
X         }
X         PolyPtr->n++;
X         n++;
X         if (PolyPtr->curved)
X         {
X            cfree (PolyPtr->svlist);
X            PolyPtr->svlist = MakeSplinePolyVertex (&(PolyPtr->sn),
X                  drawOrigX, drawOrigY, PolyPtr->n, PolyPtr->vlist);
X         }
X         UpdPolyBBox (ObjPtr, PolyPtr->n, PolyPtr->vlist);
X         AdjObjBBox (ObjPtr);
X
X         UpdSelBBox ();
X         RedrawAreas (botObj,
X               sel_ltx-(1<<zoomScale), sel_lty-(1<<zoomScale),
X               sel_rbx+(1<<zoomScale), sel_rby+(1<<zoomScale),
X               selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
X               selRbX+(1<<zoomScale), selRbY+(1<<zoomScale));
X         HighLightForward ();
X         SetFileModified (TRUE);
X      }
X   }
X}
X
Xstatic
Xvoid ContinueAddPolygonPoint (ObjPtr, MouseX, MouseY, Index, PolygonPtr,
X      LastMouseX, LastMouseY)
X   struct ObjRec	* ObjPtr;
X   int			MouseX, MouseY, Index;
X   struct PolygonRec	* PolygonPtr;
X   int			* LastMouseX, * LastMouseY;
X   /* (MouseX,MouseY) is the mouse's origin in screen offsets */
X{
X   int		n = PolygonPtr->n;
X   int		already_moved = FALSE, done = FALSE, before = FALSE;
X   XPoint	* vs = PolygonPtr->vlist, v[3];
X   int		prev_x, prev_y, x, y, next_x, next_y, new_x, new_y;
X   int		orig_x, orig_y, grid_x, grid_y, new_mouse_x, new_mouse_y;
X   int		sel_ltx, sel_lty, sel_rbx, sel_rby, i;
X   double	prev_angle, next_angle, new_angle, theta_1, theta_2;
X   XEvent	input, ev;
X
X   MARK(OFFSET_X(vs[Index].x), OFFSET_Y(vs[Index].y));
X
X   sel_ltx =  selLtX; sel_lty = selLtY;
X   sel_rbx =  selRbX; sel_rby = selRbY;
X
X   x = vs[Index].x;
X   y = vs[Index].y;
X
X   if (Index == 0 || Index == n-1)
X   {
X      next_x = vs[1].x;   next_y = vs[1].y;
X      prev_x = vs[n-2].x; prev_y = vs[n-2].y;
X   }
X   else
X   {
X      prev_x = vs[Index-1].x; prev_y = vs[Index-1].y;
X      next_x = vs[Index+1].x; next_y = vs[Index+1].y;
X   }
X   prev_angle = atan2 ((double)(prev_y-y), (double)(prev_x-x));
X   next_angle = atan2 ((double)(next_y-y), (double)(next_x-x));
X
X   GridXY (MouseX, MouseY, &orig_x, &orig_y);
X   new_mouse_x = MouseX; new_mouse_y = MouseY;
X   XDrawString (mainDisplay, drawWindow, revDefaultGC, new_mouse_x+4,
X         new_mouse_y+defaultFontAsc, "ADD", 3);
X
X   while (!done)
X   {
X      XNextEvent (mainDisplay, &input);
X      if (input.type == MotionNotify)
X      {
X         XDrawString (mainDisplay, drawWindow, revDefaultGC, new_mouse_x+4,
X               new_mouse_y+defaultFontAsc, "ADD", 3);
X         new_mouse_x = input.xmotion.x;
X         new_mouse_y = input.xmotion.y;
X         XDrawString (mainDisplay, drawWindow, revDefaultGC, new_mouse_x+4,
X               new_mouse_y+defaultFontAsc, "ADD", 3);
X
X         GridXY (new_mouse_x, new_mouse_y, &grid_x, &grid_y);
X         new_x = ((new_mouse_x-MouseX)<<zoomScale) + x;
X         new_y = ((new_mouse_y-MouseY)<<zoomScale) + y;
X         if (!already_moved)
X         {
X            already_moved = TRUE;
X
X            new_angle = atan2 ((double)(new_y-y), (double)(new_x-x));
X            theta_1 = fabs (prev_angle - new_angle);
X            theta_2 = fabs (next_angle - new_angle);
X            if (theta_1 > M_PI) theta_1 = 2*M_PI-theta_1;
X            if (theta_2 > M_PI) theta_2 = 2*M_PI-theta_2;
X            before = (theta_1 <= theta_2);
X
X            if (before)
X            {  /* Add a point between the current and the previous point */
X               v[0].x = OFFSET_X(prev_x); v[0].y = OFFSET_Y(prev_y);
X               v[1].x = OFFSET_X(x);      v[1].y = OFFSET_Y(y);
X               v[2].x = OFFSET_X(x);      v[2].y = OFFSET_Y(y);
X            }
X            else
X            {  /* Add a point between the current and the next point */
X               v[0].x = OFFSET_X(x);      v[0].y = OFFSET_Y(y);
X               v[1].x = OFFSET_X(x);      v[1].y = OFFSET_Y(y);
X               v[2].x = OFFSET_X(next_x); v[2].y = OFFSET_Y(next_y);
X            }
X            MyDashedLine (drawWindow, revDefaultGC, v, 3);
X         }
X         else
X         {
X            MyDashedLine (drawWindow, revDefaultGC, v, 3);
X            v[1].x = OFFSET_X(x) + grid_x - orig_x;
X            v[1].y = OFFSET_Y(y) + grid_y - orig_y;
X            MyDashedLine (drawWindow, revDefaultGC, v, 3);
X            MarkRulers (grid_x, grid_y);
X         }
X         while (XCheckMaskEvent (mainDisplay, PointerMotionMask, &ev)) ;
X      }
X      else if (input.type == ButtonRelease)
X      {
X         done = TRUE;
X         *LastMouseX = new_mouse_x; *LastMouseY = new_mouse_y;
X         MARK(OFFSET_X(vs[Index].x), OFFSET_Y(vs[Index].y));
X         XDrawString (mainDisplay, drawWindow, revDefaultGC, new_mouse_x+4,
X               new_mouse_y+defaultFontAsc, "ADD", 3);
X
X         if (!already_moved)
X            continue;
X         else
X         {
X            MyDashedLine (drawWindow, revDefaultGC, v, 3);
X            if (grid_x == orig_x && grid_y == orig_y)
X               continue;
X         }
X
X         HighLightReverse ();
X         vs = (XPoint *) realloc (vs, (n+2)*sizeof(XPoint));
X         if (vs == NULL)
X         {
X            printf ("Can not realloc () in ContinueAddPolygonPoint ().\n");
X            exit (-1);
X         }
X         PolygonPtr->vlist = vs;
X         if (Index == 0 || Index == n-1)
X         {
X            if (before)
X            {
X               vs[n].x = vs[n-1].x;
X               vs[n].y = vs[n-1].y;
X               vs[n-1].x = x + ((grid_x-orig_x)<<zoomScale);
X               vs[n-1].y = y + ((grid_y-orig_y)<<zoomScale);
X            }
X            else
X            {
X               for (i = n-1; i > 0; i--) vs[i+1] = vs[i];
X               vs[1].x = x + ((grid_x-orig_x)<<zoomScale);
X               vs[1].y = y + ((grid_y-orig_y)<<zoomScale);
X            }
X         }
X         else
X         {
X            if (before)
X            {
X               for (i = n-1; i >= Index; i--) vs[i+1] = vs[i];
X               vs[Index].x = x + ((grid_x-orig_x)<<zoomScale);
X               vs[Index].y = y + ((grid_y-orig_y)<<zoomScale);
X            }
X            else
X            {
X               for (i = n-1; i > Index; i--) vs[i+1] = vs[i];
X               vs[Index+1].x = x + ((grid_x-orig_x)<<zoomScale);
X               vs[Index+1].y = y + ((grid_y-orig_y)<<zoomScale);
X            }
X         }
X         PolygonPtr->n++;
X         n++;
X         if (PolygonPtr->curved)
X         {
X            cfree (PolygonPtr->svlist);
X            PolygonPtr->svlist = MakeSplinePolygonVertex (&(PolygonPtr->sn),
X                  drawOrigX, drawOrigY, PolygonPtr->n, PolygonPtr->vlist);
X         }
X         UpdPolyBBox (ObjPtr, PolygonPtr->n, PolygonPtr->vlist);
X         AdjObjBBox (ObjPtr);
X
X         UpdSelBBox ();
X         RedrawAreas (botObj,
X               sel_ltx-(1<<zoomScale), sel_lty-(1<<zoomScale),
X               sel_rbx+(1<<zoomScale), sel_rby+(1<<zoomScale),
X               selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
X               selRbX+(1<<zoomScale), selRbY+(1<<zoomScale));
X         HighLightForward ();
X         SetFileModified (TRUE);
X      }
X   }
X}
X
Xvoid AddPoint ()
X{
X   register struct ObjRec	* obj_ptr;
X   struct PolyRec		* poly_ptr = NULL;
X   struct PolygonRec		* polygon_ptr = NULL;
X   int				index, adding = TRUE;
X   int				root_x, root_y, old_x, old_y;
X   unsigned int			status;
X   Window			root_win, child_win;
X   XEvent			input, ev;
X
X   if (!(topSel != NULL && topSel == botSel &&
X         (topSel->obj->type == OBJ_POLY || topSel->obj->type == OBJ_POLYGON)))
X   {
X      Msg ("Please select only one POLY or POLYGON object.");
X      return;
X   }
X
X   obj_ptr = topSel->obj;
X   switch (obj_ptr->type)
X   {
X      case OBJ_POLY: poly_ptr = obj_ptr->detail.p; break;
X      case OBJ_POLYGON: polygon_ptr = obj_ptr->detail.g; break;
X   }
X   TwoLineMsg ("Drag left mouse button to ADD points.",
X         "Click other buttons to quit.");
X
X   XGrabPointer (mainDisplay, drawWindow, False,
X         PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
X         GrabModeAsync, GrabModeAsync, None, defaultCursor, CurrentTime);
X   XQueryPointer (mainDisplay, drawWindow, &root_win, &child_win,
X         &root_x, &root_y, &old_x, &old_y, &status);
X   XSetFont (mainDisplay, revDefaultGC, defaultFontPtr->fid);
X   XDrawString (mainDisplay, drawWindow, revDefaultGC,
X         old_x+4, old_y+defaultFontAsc, "ADD", 3);
X   MarkRulers (old_x, old_y);
X
X   while (adding)
X   {
X      XNextEvent (mainDisplay, &input);
X      if (input.type == ButtonPress)
X      {
X         if (input.xbutton.button == Button1)
X         {
X            XDrawString (mainDisplay, drawWindow, revDefaultGC,
X                  old_x+4, old_y+defaultFontAsc, "ADD", 3);
X            if (obj_ptr->type == OBJ_POLY &&
X                  PtInPolyMark (input.xbutton.x, input.xbutton.y,
X                  poly_ptr->n, poly_ptr->vlist, &index))
X               ContinueAddPolyPoint (obj_ptr, input.xbutton.x, input.xbutton.y,
X                     index, poly_ptr, &old_x, &old_y);
X            else if (obj_ptr->type == OBJ_POLYGON &&
X                  PtInPolyMark (input.xbutton.x, input.xbutton.y,
X                  polygon_ptr->n-1, polygon_ptr->vlist, &index))
X               ContinueAddPolygonPoint (obj_ptr, input.xbutton.x,
X                     input.xbutton.y, index, polygon_ptr, &old_x, &old_y);
X            XDrawString (mainDisplay, drawWindow, revDefaultGC,
X                  old_x+4, old_y+defaultFontAsc, "ADD", 3);
X         }
X         else
X         {
X            adding = FALSE;
X            XDrawString (mainDisplay, drawWindow, revDefaultGC,
X                  old_x+4, old_y+defaultFontAsc, "ADD", 3);
X         }
X      }
X      else if (input.type == MotionNotify)
X      {
X         XDrawString (mainDisplay, drawWindow, revDefaultGC,
X               old_x+4, old_y+defaultFontAsc, "ADD", 3);
X         old_x = input.xmotion.x;
X         old_y = input.xmotion.y;
X         XDrawString (mainDisplay, drawWindow, revDefaultGC,
X               old_x+4, old_y+defaultFontAsc, "ADD", 3);
X         MarkRulers (old_x, old_y);
X         while (XCheckMaskEvent (mainDisplay, PointerMotionMask, &ev)) ;
X      }
X   }
X   XUngrabPointer (mainDisplay, CurrentTime);
X   Msg ("");
X}
X
Xvoid EditMenu (X, Y)
X   int	X, Y;
X{
X   int		index, * fore_colors, * valid;
X
X   DefaultColorArrays (MAXEDITMENUS, &fore_colors, &valid);
X   index = TextMenuLoop (X, Y, editMenuStr, MAXEDITMENUS, fore_colors, valid,
X         SINGLECOLOR);
X
X   switch (index)
X   {
X      case EDIT_REDRAW: ClearAndRedrawDrawWindow (); break;
X      case EDIT_DUP: DupSelObj (); break;
X      case EDIT_DELETE: DelAllSelObj (); break;
X      case EDIT_SELALL: SelAllObj (); break;
X      case EDIT_UNDODEL: UndoDelete (); break;
X      case EDIT_DEL_POINT: DeletePoint (); break;
X      case EDIT_ADD_POINT: AddPoint (); break;
X      case EDIT_COPY: CopyToCutBuffer (); break;
X      case EDIT_PASTE: PasteFromCutBuffer (); break;
X      case EDIT_INV_XBM: InvertXBitmaps (); break;
X   }
X}
X
Xvoid FrontProc ()
X{
X   if (topSel != NULL)
X   {
X      HighLightReverse ();
X      MoveSelToTop ();
X      RedrawAnArea (botObj, selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
X            selRbX+(1<<zoomScale), selRbY+(1<<zoomScale));
X      HighLightForward ();
X      SetFileModified (TRUE);
X   }
X}
X
Xvoid BackProc ()
X{
X   if (topSel != NULL)
X   {
X      HighLightReverse ();
X      MoveSelToBot ();
X      RedrawAnArea (botObj, selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
X            selRbX+(1<<zoomScale), selRbY+(1<<zoomScale));
X      HighLightForward ();
X      SetFileModified (TRUE);
X   }
X}
X
X#define ARRANGE_FRONT 0
X#define ARRANGE_BACK 1
X#define ARRANGE_GROUP 2
X#define ARRANGE_UNGROUP 3
X#define ARRANGE_ALIGNOBJ 4
X#define ARRANGE_ALIGNGRID 5
X#define FLIP_HORIZONTAL 6
X#define FLIP_VERTICAL 7
X#define ROTATE_CLOCKWISE 8
X#define ROTATE_COUNTER 9
X#define MAXARRANGEMENUS 10
X
Xstatic char * arrangeMenuStr[] =
X      { "Front           ^F",
X        "Back            ^B",
X        "Group           ^G",
X        "UnGroup         ^U",
X        "AlignObjs       ^L",
X        "AlignToGrid     ^T",
X        "FlipHorizontal  #H",
X        "FlipVertical    #V",
X        "RotateClockWise #W",
X        "RotateCounter   #C",
X      };
X
Xvoid ArrangeMenu (X, Y)
X   int	X, Y;
X{
X   int		index, * fore_colors, * valid;
X
X   DefaultColorArrays (MAXARRANGEMENUS, &fore_colors, &valid);
X   index = TextMenuLoop (X, Y, arrangeMenuStr, MAXARRANGEMENUS, fore_colors,
X         valid, SINGLECOLOR);
X   switch (index)
X   {
X      case ARRANGE_FRONT: FrontProc (); break;
X      case ARRANGE_BACK: BackProc (); break;
X      case ARRANGE_GROUP: GroupSelObj (); break;
X      case ARRANGE_UNGROUP: UngroupSelObj (); break;
X      case ARRANGE_ALIGNOBJ: AlignSelObjs (); break;
X      case ARRANGE_ALIGNGRID: AlignSelToGrid (); break;
X      case FLIP_HORIZONTAL: FlipHorizontal (); break;
X      case FLIP_VERTICAL: FlipVertical (); break;
X      case ROTATE_CLOCKWISE: RotateClockWise (); break;
X      case ROTATE_COUNTER: RotateCounter (); break;
X   }
X}
X
Xstatic struct ObjRec	* tmpTopObj, * tmpBotObj;
Xstatic struct SelRec	* tmpTopSel, * tmpBotSel;
X
Xstatic
Xvoid PushTmpSel (ObjPtr)
X   struct ObjRec	* ObjPtr;
X{
X   struct SelRec	* sel_ptr;
X
X   ObjPtr->next = tmpTopObj;
X   ObjPtr->prev = NULL;
X
X   sel_ptr = (struct SelRec *) calloc (1, sizeof (struct SelRec));
X   sel_ptr->next = tmpTopSel;
X   sel_ptr->prev = NULL;
X   sel_ptr->obj = ObjPtr;
X
X   if (tmpTopObj == NULL)
X   {
X      tmpBotObj = ObjPtr;
X      tmpBotSel = sel_ptr;
X   }
X   else
X   {
X      tmpTopObj->prev = ObjPtr;
X      tmpTopSel->prev = sel_ptr;
X   }
X   tmpTopObj = ObjPtr;
X   tmpTopSel = sel_ptr;
X}
X
Xvoid UpdateSymbols ()
X{
X   int			dx = 0, dy = 0, changed = FALSE;
X   char			path_name[MAXPATHLENGTH], sym_name[MAXPATHLENGTH];
X   struct ObjRec	* obj_ptr, * new_obj_ptr;
X   struct SelRec	* sel_ptr;
X
X   if (topSel == NULL) return;
X
X   tmpTopObj = tmpBotObj = NULL;
X   tmpTopSel = tmpBotSel = NULL;
X
X   HighLightReverse ();
X
X   for (sel_ptr = botSel; sel_ptr != NULL; sel_ptr = sel_ptr->prev)
X   {
X      obj_ptr = sel_ptr->obj;
X      if (obj_ptr->type != OBJ_ICON) continue;
X
X      strcpy (sym_name, obj_ptr->detail.r->s);
X      if (GetSymbolPath (obj_ptr->detail.r->s, path_name))
X      {
X         if ((new_obj_ptr = GetObjRepresentation (path_name, sym_name)) != NULL)
X         {
X            switch (horiAlign)
X            {
X               case ALIGN_L:
X                  dx = obj_ptr->obbox.ltx - new_obj_ptr->obbox.ltx;
X                  break;
X               case ALIGN_N:
X               case ALIGN_C:
X                  dx = (int)(((obj_ptr->obbox.ltx+obj_ptr->obbox.rbx) -
X                        (new_obj_ptr->obbox.ltx+new_obj_ptr->obbox.rbx))/2);
X                  break;
X               case ALIGN_R:
X                  dx = obj_ptr->obbox.rbx - new_obj_ptr->obbox.rbx;
X                  break;
X            }
X            switch (vertAlign)
X            {
X               case ALIGN_T:
X                  dy = obj_ptr->obbox.lty - new_obj_ptr->obbox.lty;
X                  break;
X               case ALIGN_N:
X               case ALIGN_M:
X                  dy = (int)(((obj_ptr->obbox.lty+obj_ptr->obbox.rby) -
X                        (new_obj_ptr->obbox.lty+new_obj_ptr->obbox.rby))/2);
X                  break;
X               case ALIGN_B:
X                  dy = obj_ptr->obbox.rby - new_obj_ptr->obbox.rby;
X                  break;
X            }
X            MoveObj (new_obj_ptr, dx, dy);
X
X            changed = TRUE;
X
X            UnlinkObj (obj_ptr);
X            PushTmpSel (obj_ptr);
X            CopyAndUpdateAttrs (new_obj_ptr, obj_ptr);
X
X            if (new_obj_ptr->bbox.ltx < selLtX) selLtX = new_obj_ptr->bbox.ltx;
X            if (new_obj_ptr->bbox.lty < selLtY) selLtY = new_obj_ptr->bbox.lty;
X            if (new_obj_ptr->bbox.rbx < selRbX) selRbX = new_obj_ptr->bbox.rbx;
X            if (new_obj_ptr->bbox.rby < selRbY) selRbY = new_obj_ptr->bbox.rby;
X            if (new_obj_ptr->obbox.ltx < selObjLtX)
X                  selObjLtX = new_obj_ptr->obbox.ltx;
X            if (new_obj_ptr->obbox.lty < selObjLtY)
X                  selObjLtY = new_obj_ptr->obbox.lty;
X            if (new_obj_ptr->obbox.rbx < selObjRbX)
X                  selObjRbX = new_obj_ptr->obbox.rbx;
X            if (new_obj_ptr->obbox.rby < selObjRbY)
X                  selObjRbY = new_obj_ptr->obbox.rby;
X
X            sel_ptr->obj = new_obj_ptr;
X            AddObj (NULL, topObj, new_obj_ptr);
X         }
X      }
X   }
X
X   PushToCutBuffer (tmpTopSel, tmpBotSel);
X
X   if (changed)
X   {
X      RedrawAnArea (botObj, selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
X            selRbX+(1<<zoomScale), selRbY+(1<<zoomScale));
X      UpdSelBBox ();
X      SetFileModified (TRUE);
X      justDupped = FALSE;
X   }
X   HighLightForward ();
X}
END_OF_FILE
if test 29266 -ne `wc -c <'edit.c'`; then
    echo shar: \"'edit.c'\" unpacked with wrong size!
fi
# end of 'edit.c'
fi
echo shar: End of archive 3 \(of 23\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 23 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
---------------------------------> cut here <---------------------------------
-- 
Bill Cheng // UCLA Computer Science Department // (213) 206-7135
3277 Boelter Hall // Los Angeles, California 90024 // USA
william@CS.UCLA.EDU      ...!{uunet|ucbvax}!cs.ucla.edu!william