[comp.sources.x] v12i031: tgif, Part15/23

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

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

---------------------------------> 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 15 (of 23)."
# Contents:  stk.c stretch.c
# Wrapped by william@oahu on Wed Mar  6 09:57:48 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'stk.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stk.c'\"
else
echo shar: Extracting \"'stk.c'\" \(6069 characters\)
sed "s/^X//" >'stk.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/stk.c,v 2.0 91/03/05 12:48:31 william Exp $";
X#endif
X
X#include <stdio.h>
X#include <X11/Xlib.h>
X#include "const.h"
X#include "types.h"
X
X#include "align.e"
X#include "button.e"
X#include "choice.e"
X#include "color.e"
X#include "dup.e"
X#include "file.e"
X#include "font.e"
X#include "grid.e"
X#include "mark.e"
X#include "menu.e"
X#include "msg.e"
X#include "names.e"
X#include "obj.e"
X#include "pattern.e"
X#include "ruler.e"
X#include "scroll.e"
X#include "select.e"
X#include "setup.e"
X#include "text.e"
X
Xstatic struct StkRec	* topStk = NULL;
X
Xint AncesterModified ()
X{
X   struct StkRec	* stk_ptr;
X
X   for (stk_ptr = topStk; stk_ptr != NULL; stk_ptr = stk_ptr->next)
X      if (stk_ptr->file_mod) return (TRUE);
X   return (FALSE);
X}
X
Xvoid InitStk ()
X{
X   curSymDir[0] = '\0';
X}
X
Xvoid PushIcon ()
X{
X   struct StkRec	* stk_ptr;
X   struct ObjRec	* obj_ptr;
X   char			sym_name[MAXPATHLENGTH], path_name[MAXPATHLENGTH];
X   char			file_name[MAXPATHLENGTH], s[MAXPATHLENGTH];
X   FILE			* fp;
X
X   if (topSel == NULL || topSel != botSel || topSel->obj->type != OBJ_ICON)
X   {
X      Msg ("Please select one ICON object to push into.");
X      return;
X   }
X
X   strcpy (sym_name, topSel->obj->detail.r->s);
X   if (!GetSymbolPath (sym_name, path_name))
X   {
X      sprintf (s, "Can not find '%s.sym' in %s", sym_name, curDomainPath);
X      Msg (s);
X      return;
X   }
X
X   strcat (sym_name, ".sym");
X   sprintf (file_name, "%s/%s", path_name, sym_name);
X
X   if ((fp = fopen (file_name, "r")) == NULL)
X   {
X      sprintf (s, "Can not open '%s', icon not pushed into.", file_name);
X      Msg (s);
X      return;
X   }
X
X   HighLightReverse ();
X
X   stk_ptr = (struct StkRec *) calloc (1, sizeof(struct StkRec));
X   stk_ptr->next = topStk;
X   stk_ptr->sel = topSel->obj;
X   stk_ptr->first = topObj;
X   stk_ptr->last = botObj;
X   stk_ptr->file_mod = fileModified;
X   stk_ptr->id = objId;
X   stk_ptr->page_style = pageStyle;
X
X   stk_ptr->orig_x = drawOrigX;
X   stk_ptr->orig_y = drawOrigY;
X   stk_ptr->zoom = zoomScale;
X   stk_ptr->grid = xyGrid;
X   stk_ptr->grid_on = gridOn;
X   stk_ptr->color = colorIndex;
X   stk_ptr->h_align = horiAlign;
X   stk_ptr->v_align = vertAlign;
X   stk_ptr->line_w = lineWidth;
X   stk_ptr->line_s = lineStyle;
X   stk_ptr->fill = objFill;
X   stk_ptr->pen = penPat;
X   stk_ptr->just = textJust;
X   stk_ptr->font = curFont;
X   stk_ptr->f_style = curStyle;
X   stk_ptr->f_size = curSize;
X   stk_ptr->f_dpi = curFontDPI;
X
X   topObj = botObj = NULL;
X
X   strcpy (stk_ptr->dir, curDir);
X   if (stk_ptr->name_valid = curFileDefined)
X      strcat (stk_ptr->name, curFileName);
X   strcpy (stk_ptr->sym_dir, curSymDir);
X   strcpy (stk_ptr->domain, curDomainName);
X
X   topStk = stk_ptr;
X
X   sprintf (s, "Pushing into '%s' ...", file_name);
X   Msg (s);
X   CleanUpDrawingWindow ();
X   XClearWindow (mainDisplay, drawWindow);
X   SetFileModified (FALSE);
X
X   while (ReadObj (fp, &obj_ptr, FALSE))
X      if (obj_ptr != NULL)
X      {
X         AddObj (NULL, topObj, obj_ptr);
X         if (PointInBBox (obj_ptr->x, obj_ptr->y, drawWinBBox) ||
X               BBoxIntersect (obj_ptr->bbox, drawWinBBox))
X            DrawObj (drawWindow, obj_ptr);
X      }
X
X   if (topObj == NULL)
X   {
X      DrawPaperBoundary ();
X      RedrawGridLines ();
X   }
X
X   fclose (fp);
X   strcpy (curFileName, sym_name);
X   strcpy (curSymDir, path_name);
X   curFileDefined = TRUE;
X
X   sprintf (s, "Current file is '%s'.", file_name);
X   Msg (s);
X
X   RedrawTitleWindow ();
X}
X
Xvoid PopIcon ()
X{
X   char	dummy[MAXPATHLENGTH];
X
X   if (topStk == NULL)
X   {
X      Msg ("Already at top level.");
X      return;
X   }
X   if (fileModified)
X   {
X      switch (YesNoCancel ("File modified, save file before quit? [ync](y)"))
X      {
X         case CONFIRM_YES: SaveFile (); break;
X         case CONFIRM_NO: break;
X         case CONFIRM_CANCEL: return;
X      }
X   }
X   fileModified = topStk->file_mod;
X   objId = topStk->id;
X
X   CleanUpDrawingWindow ();
X
X   drawOrigX = topStk->orig_x;
X   drawOrigY = topStk->orig_y;
X   zoomScale = topStk->zoom;
X   xyGrid = topStk->grid;
X   gridOn = topStk->grid_on;
X   colorIndex = topStk->color;
X   horiAlign = topStk->h_align;
X   vertAlign = topStk->v_align;
X   lineWidth = topStk->line_w;
X   lineStyle = topStk->line_s;
X   objFill = topStk->fill;
X   penPat = topStk->pen;
X   textJust = topStk->just;
X   curFont = topStk->font;
X   curStyle = topStk->f_style;
X   curFontDPI = topStk->f_dpi;
X
X   topObj = topStk->first;
X   botObj = topStk->last;
X   strcpy (curDomainName, topStk->domain);
X   strcpy (curSymDir, topStk->sym_dir);
X   if (curFileDefined = topStk->name_valid)
X   {
X      strcpy (curFileName, topStk->name);
X      if (*curSymDir == '\0')
X         sprintf (dummy, "Poping back to '%s/%s'.", topStk->dir, curFileName);
X      else
X         sprintf (dummy, "Poping back to '%s/%s'.", curSymDir, curFileName);
X      Msg (dummy);
X   }
X   else
X   {
X      sprintf (dummy, "Poping back to parent level.  Current file undefined.");
X      Msg (dummy);
X   }
X   if (strcmp (curDir, topStk->dir) != 0)
X   {
X      strcpy (curDir, topStk->dir);
X      UpdateDirInfo ();
X   }
X   else
X      strcpy (curDir, topStk->dir);
X
X   topSel = botSel = (struct SelRec *) calloc (1, sizeof(struct SelRec));
X   topSel->next = NULL;
X   topSel->prev = NULL;
X   topSel->obj = topStk->sel;
X   UpdSelBBox ();
X
X   if (pageStyle != topStk->page_style) UpdPageStyle (topStk->page_style);
X   UpdDrawWinWH ();
X   SetCanvasFont ();
X   RedrawRulers ();
X   if (pageStyle == topStk->page_style) RedrawScrollBars ();
X   RedrawChoiceWindow ();
X   RedrawTitleWindow ();
X   UpdDrawWinBBox ();
X
X   cfree (topStk);
X   topStk = topStk->next;
X   ClearAndRedrawDrawWindow ();
X   XSync (mainDisplay, TRUE);
X   justDupped = FALSE;
X}
X
Xvoid CleanUpStk ()
X{
X   for ( ; topStk != NULL; topStk = topStk->next)
X   {
X      topObj = topStk->first;
X      botObj = topStk->last;
X      DelAllObj ();
X      cfree (topStk);
X   }
X   curSymDir[0] = '\0';
X}
END_OF_FILE
if test 6069 -ne `wc -c <'stk.c'`; then
    echo shar: \"'stk.c'\" unpacked with wrong size!
fi
# end of 'stk.c'
fi
if test -f 'stretch.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stretch.c'\"
else
echo shar: Extracting \"'stretch.c'\" \(44036 characters\)
sed "s/^X//" >'stretch.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/stretch.c,v 2.0 91/03/05 12:48:33 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 "arc.e"
X#include "choice.e"
X#include "color.e"
X#include "cursor.e"
X#include "drawing.e"
X#include "dup.e"
X#include "font.e"
X#include "grid.e"
X#include "move.e"
X#include "obj.e"
X#include "poly.e"
X#include "raster.e"
X#include "ruler.e"
X#include "select.e"
X#include "setup.e"
X#include "spline.e"
X#include "text.e"
X#include "xbitmap.e"
X
X#define PtInMark(PtX,PtY,MarkX,MarkY) ((PtX) >= (MarkX)-2 && \
X      (PtY) >= (MarkY)-2 && (PtX) <= (MarkX)+2 && (PtY) <= (MarkY)+2)
X#define MyDashedLine(W,GC,V,N) XDrawLines (mainDisplay, W, GC, V, N, \
X      CoordModeOrigin)
X
Xstatic
Xint PtIn4Corners (XOff, YOff, BBox, Corner)
X   int		XOff, YOff, * Corner;
X   struct BBRec	BBox;
X{
X   if (PtInMark (XOff, YOff, OFFSET_X(BBox.ltx), OFFSET_Y(BBox.lty)))
X   {
X      *Corner = 1;
X      return(TRUE);
X   }
X   if (PtInMark (XOff, YOff, OFFSET_X(BBox.ltx), OFFSET_Y(BBox.rby)))
X   {
X      *Corner = 7;
X      return(TRUE);
X   }
X   if (PtInMark (XOff, YOff, OFFSET_X(BBox.rbx), OFFSET_Y(BBox.lty)))
X   {
X      *Corner = 3;
X      return(TRUE);
X   }
X   if (PtInMark (XOff, YOff, OFFSET_X(BBox.rbx), OFFSET_Y(BBox.rby)))
X   {
X      *Corner = 5;
X      return(TRUE);
X   }
X   return (FALSE);
X}
X
Xstatic
Xint PtIn8Places (XOff, YOff, BBox, Corner)
X   int		XOff, YOff, * Corner;
X   struct BBRec	BBox;
X{
X   register int	xmid, ymid;
X
X   if (BBox.rbx - BBox.ltx >= 10)
X   {
X      xmid = (BBox.ltx+BBox.rbx) / 2;
X      if (PtInMark (XOff, YOff, OFFSET_X(xmid), OFFSET_Y(BBox.lty)))
X      {
X         *Corner = 2;
X         return(TRUE);
X      }
X      if (PtInMark (XOff, YOff, OFFSET_X(xmid), OFFSET_Y(BBox.rby)))
X      {
X         *Corner = 6;
X         return(TRUE);
X      }
X   }
X   if (BBox.rby - BBox.lty >= 10)
X   {
X      ymid = (BBox.lty+BBox.rby) / 2;
X      if (PtInMark (XOff, YOff, OFFSET_X(BBox.ltx), OFFSET_Y(ymid)))
X      {
X         *Corner = 8;
X         return(TRUE);
X      }
X      if (PtInMark (XOff, YOff, OFFSET_X(BBox.rbx), OFFSET_Y(ymid)))
X      {
X         *Corner = 4;
X         return(TRUE);
X      }
X   }
X   return (PtIn4Corners (XOff, YOff, BBox, Corner));
X}
X
Xint PtInPolyMark (XOff, YOff, NumPts, V, Index)
X   int		XOff, YOff, NumPts, * Index;
X   XPoint	* V;
X{
X   register int	i;
X
X   for (i = 0; i < NumPts; i++)
X      if (PtInMark (XOff, YOff, OFFSET_X(V[i].x), OFFSET_Y(V[i].y)))
X      {
X         *Index = i;
X         return (TRUE);
X      }
X   return (FALSE);
X}
X
Xstruct SelRec * PtInSelMark (XOff, YOff, Corner)
X   int	XOff, YOff, * Corner;
X   /* XOff and YOff are screen offsets */
X   /* 1 2 3 */
X   /* 8   4 */
X   /* 7 6 5 */
X{
X   register struct SelRec	* sel_ptr;
X   register struct ObjRec	* obj_ptr;
X
X   for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next)
X   {
X      obj_ptr = sel_ptr->obj;
X      switch (obj_ptr->type)
X      {
X         case OBJ_POLY:
X            if (PtInPolyMark (XOff, YOff, obj_ptr->detail.p->n,
X                  obj_ptr->detail.p->vlist, Corner))
X               return (sel_ptr);
X            break;
X         case OBJ_POLYGON:
X            if (PtInPolyMark (XOff, YOff, obj_ptr->detail.g->n-1,
X                  obj_ptr->detail.g->vlist, Corner))
X               return (sel_ptr);
X            break;
X         case OBJ_BOX:
X         case OBJ_GROUP:
X         case OBJ_SYM:
X         case OBJ_OVAL:
X         case OBJ_ARC:
X         case OBJ_RCBOX:
X            if (PtIn8Places (XOff, YOff, obj_ptr->obbox, Corner))
X               return (sel_ptr);
X            break;
X         case OBJ_TEXT:
X         case OBJ_XBM:
X         case OBJ_ICON:
X            if (PtIn4Corners (XOff, YOff, obj_ptr->obbox, Corner))
X               return (sel_ptr);
X            break;
X      }
X   }
X   return (NULL);
X}
X
Xstatic XPoint v[5];
X
Xstatic
Xvoid StretchPoly (XGridOff, YGridOff, ObjPtr, NumPts, V, Index)
X   int			XGridOff, YGridOff, NumPts, Index;
X   XPoint		* V;
X   struct ObjRec	* ObjPtr;
X{
X   int		x, y, dx, dy, num = 0, stretching = TRUE;
X   int		ltx, lty, rbx, rby, curved;
X   int		grid_x = XGridOff, grid_y = YGridOff;
X   XEvent	input;
X
X   switch (ObjPtr->type)
X   {
X      case OBJ_POLY:
X         curved = ObjPtr->detail.p->curved;
X         if (Index == 0 || Index == NumPts-1)
X         {
X            num = 2;
X            if (Index == 0)
X            {
X               v[0].x = OFFSET_X(V[1].x); v[0].y = OFFSET_Y(V[1].y);
X               v[1].x = OFFSET_X(V[0].x); v[1].y = OFFSET_Y(V[0].y);
X            }
X            else
X            {
X               v[0].x = OFFSET_X(V[NumPts-2].x);
X               v[0].y = OFFSET_Y(V[NumPts-2].y);
X               v[1].x = OFFSET_X(V[NumPts-1].x);
X               v[1].y = OFFSET_Y(V[NumPts-1].y);
X            }
X         }
X         else
X         {
X            num = 3;
X            v[0].x = OFFSET_X(V[Index-1].x); v[0].y = OFFSET_Y(V[Index-1].y);
X            v[1].x = OFFSET_X(V[Index].x);   v[1].y = OFFSET_Y(V[Index].y);
X            v[2].x = OFFSET_X(V[Index+1].x); v[2].y = OFFSET_Y(V[Index+1].y);
X         }
X         break;
X      case OBJ_POLYGON:
X         curved = ObjPtr->detail.g->curved;
X         num = 3;
X         if (Index == 0 || Index == NumPts-1)
X         {
X            v[0].x = OFFSET_X(V[1].x); v[0].y = OFFSET_Y(V[1].y);
X            v[1].x = OFFSET_X(V[0].x); v[1].y = OFFSET_Y(V[0].y);
X            v[2].x = OFFSET_X(V[NumPts-2].x); v[2].y = OFFSET_Y(V[NumPts-2].y);
X         }
X         else
X         {
X            v[0].x = OFFSET_X(V[Index-1].x); v[0].y = OFFSET_Y(V[Index-1].y);
X            v[1].x = OFFSET_X(V[Index].x);   v[1].y = OFFSET_Y(V[Index].y);
X            v[2].x = OFFSET_X(V[Index+1].x); v[2].y = OFFSET_Y(V[Index+1].y);
X         }
X         break;
X   }
X
X   ltx = ObjPtr->bbox.ltx;
X   lty = ObjPtr->bbox.lty;
X   rbx = ObjPtr->bbox.rbx;
X   rby = ObjPtr->bbox.rby;
X
X   XGrabPointer (mainDisplay, drawWindow, FALSE,
X         PointerMotionMask | ButtonReleaseMask,
X         GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
X
X   MyDashedLine (drawWindow, revDefaultGC, v, num);
X   dx = dy = 0;
X   while (stretching)
X   {
X      XNextEvent (mainDisplay, &input);
X      if (input.type == ButtonRelease)
X      {
X         XUngrabPointer (mainDisplay, CurrentTime);
X         stretching = FALSE;
X
X         MyDashedLine (drawWindow, revDefaultGC, v, num);
X         HighLightReverse ();
X
X         if (dx != 0 || dy != 0)
X         {
X            dx <<= zoomScale;
X            dy <<= zoomScale;
X            switch (ObjPtr->type)
X            {
X               case OBJ_POLY:
X                  V[Index].x += dx; V[Index].y += dy;
X                  if (ObjPtr->detail.p->curved)
X                  {
X                     cfree (ObjPtr->detail.p->svlist);
X                     ObjPtr->detail.p->svlist = MakeSplinePolyVertex (
X                           &(ObjPtr->detail.p->sn), drawOrigX, drawOrigY,
X                           ObjPtr->detail.p->n, ObjPtr->detail.p->vlist);
X                  }
X                  break;
X               case OBJ_POLYGON:
X                  V[Index].x += dx; V[Index].y += dy;
X                  if (Index == 0)
X                  {
X                     V[NumPts-1].x += dx; V[NumPts-1].y += dy;
X                  }
X                  else if (Index == NumPts-1)
X                  {
X                     V[0].x += dx; V[0].y += dy;
X                  }
X                  if (ObjPtr->detail.g->curved)
X                  {
X                     cfree (ObjPtr->detail.g->svlist);
X                     ObjPtr->detail.g->svlist = MakeSplinePolygonVertex (
X                           &(ObjPtr->detail.g->sn), drawOrigX, drawOrigY,
X                           ObjPtr->detail.g->n, ObjPtr->detail.g->vlist);
X                  }
X                  break;
X            }
X            UpdPolyBBox (ObjPtr, NumPts, V);
X
X            UpdSelBBox ();
X            RedrawAreas (botObj, ltx-(1<<zoomScale), lty-(1<<zoomScale),
X                  rbx+(1<<zoomScale), rby+(1<<zoomScale),
X                  ObjPtr->bbox.ltx-(1<<zoomScale),
X                  ObjPtr->bbox.lty-(1<<zoomScale),
X                  ObjPtr->bbox.rbx+(1<<zoomScale),
X                  ObjPtr->bbox.rby+(1<<zoomScale));
X            SetFileModified (TRUE);
X         }
X         HighLightForward ();
X      }
X      else if (input.type == MotionNotify)
X      {
X         x = input.xmotion.x;
X         y = input.xmotion.y;
X         GridXY (x, y, &grid_x, &grid_y);
X
X         MyDashedLine (drawWindow, revDefaultGC, v, num);
X
X         dx = grid_x - XGridOff;
X         dy = grid_y - YGridOff;
X         v[1].x = OFFSET_X(V[Index].x) + dx;
X         v[1].y = OFFSET_Y(V[Index].y) + dy;
X         MarkRulers (grid_x, grid_y);
X
X         MyDashedLine (drawWindow, revDefaultGC, v, num);
X      }
X   }
X}
X
Xstatic double	multX, multY;
Xstatic int	pivotX, pivotY, changeX, changeY, moveX, moveY;
X
Xstatic
Xvoid StretchedXY (X, Y, NewX, NewY)
X   int	X, Y, * NewX, * NewY; /* screen offsets */
X{
X   register int	dx, dy;
X
X   dx = round ((double)((double)(X - pivotX) * multX));
X   dy = round ((double)((double)(Y - pivotY) * multY));
X   *NewX = pivotX + dx;
X   *NewY = pivotY + dy;
X}
X
Xstatic
Xvoid SetPivot (Corner, OBBox)
X   int		Corner;
X   struct BBRec OBBox;
X   /* pivotX, pivotY, moveX, moveY will be set to screen offsets */
X{
X   switch (Corner)
X   {
X      case 1:
X         pivotX = OBBox.rbx; pivotY = OBBox.rby;
X         moveX = OBBox.ltx; moveY = OBBox.lty;
X         changeX = changeY = TRUE;
X         break;
X      case 2:
X         pivotX = moveX = (OBBox.ltx+OBBox.rbx)/2; pivotY = OBBox.rby;
X         moveY = OBBox.lty;
X         changeX = FALSE; changeY = TRUE;
X         break;
X      case 3:
X         pivotX = OBBox.ltx; pivotY = OBBox.rby;
X         moveX = OBBox.rbx; moveY = OBBox.lty;
X         changeX = changeY = TRUE;
X         break;
X      case 4:
X         pivotX = OBBox.ltx; pivotY = moveY = (OBBox.ltx+OBBox.rby)/2;
X         moveX = OBBox.rbx;
X         changeX = TRUE; changeY = FALSE;
X         break;
X      case 5:
X         pivotX = OBBox.ltx; pivotY = OBBox.lty;
X         moveX = OBBox.rbx; moveY = OBBox.rby;
X         changeX = changeY = TRUE;
X         break;
X      case 6:
X         pivotX = moveX = (OBBox.ltx+OBBox.rbx)/2; pivotY = OBBox.lty;
X         moveY = OBBox.rby;
X         changeX = FALSE; changeY = TRUE;
X         break;
X      case 7:
X         pivotX = OBBox.rbx; pivotY = OBBox.lty;
X         moveX = OBBox.ltx; moveY = OBBox.rby;
X         changeX = changeY = TRUE;
X         break;
X      case 8:
X         pivotX = OBBox.rbx; pivotY = moveY = (OBBox.lty+OBBox.rby)/2;
X         moveX = OBBox.ltx;
X         changeX = TRUE; changeY = FALSE;
X         break;
X   }
X   multX = 1.0;
X   multY = 1.0;
X   pivotX = OFFSET_X(pivotX);
X   pivotY = OFFSET_Y(pivotY);
X   moveX = OFFSET_X(moveX);
X   moveY = OFFSET_Y(moveY);
X}
X
Xstatic
Xvoid StretchObj (ObjPtr, Corner)
X   struct ObjRec	* ObjPtr;
X   int			Corner;
X{
X   register int			i;
X   register struct ObjRec	* ptr;
X   struct AttrRec		* attr_ptr;
X   struct ArcRec		* arc_ptr;
X   int				x, y, dx, dy, old_x, old_y, w, h;
X   int				ltx, lty, rbx, rby;
X   int				real_ltx, real_lty, real_rbx, real_rby;
X
X   StretchedXY (OFFSET_X(ObjPtr->obbox.ltx), OFFSET_Y(ObjPtr->obbox.lty),
X         &ltx, &lty);
X   StretchedXY (OFFSET_X(ObjPtr->obbox.rbx), OFFSET_Y(ObjPtr->obbox.rby),
X         &rbx, &rby);
X   CalcBBox (ltx, lty, rbx, rby, &real_ltx, &real_lty, &real_rbx, &real_rby);
X
X   StretchedXY (OFFSET_X(ObjPtr->x), OFFSET_Y(ObjPtr->y), &x, &y);
X   w = (ObjPtr->obbox.rbx - ObjPtr->obbox.ltx) << zoomScale;
X   h = (ObjPtr->obbox.rby - ObjPtr->obbox.lty) << zoomScale;
X
X   switch (ObjPtr->type)
X   {
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_POLY:
X      case OBJ_POLYGON:
X      case OBJ_ARC:
X      case OBJ_RCBOX:
X      case OBJ_SYM:
X      case OBJ_GROUP:
X         ObjPtr->obbox.ltx = ObjPtr->x = (real_ltx << zoomScale) + drawOrigX;
X         ObjPtr->obbox.lty = ObjPtr->y = (real_lty << zoomScale) + drawOrigY;
X         ObjPtr->obbox.rbx = (real_rbx << zoomScale) + drawOrigX;
X         ObjPtr->obbox.rby = (real_rby << zoomScale) + drawOrigY;
X         break;
X      case OBJ_TEXT:
X         ObjPtr->x = (x << zoomScale) + drawOrigX;
X         ObjPtr->y = (y << zoomScale) + drawOrigY;
X         if (multX < 0)
X            ObjPtr->detail.t->just = MAXJUSTS - 1 - ObjPtr->detail.t->just;
X         if (multY < 0) ObjPtr->y -= h;
X         UpdTextBBox (ObjPtr);
X         break;
X      case OBJ_ICON:
X      case OBJ_XBM:
X         old_x = ObjPtr->x;
X         old_y = ObjPtr->y;
X         ObjPtr->x = (x << zoomScale) + drawOrigX;
X         ObjPtr->y = (y << zoomScale) + drawOrigY;
X         if (multX < 0) ObjPtr->x -= w;
X         if (multY < 0) ObjPtr->y -= h;
X         dx = ObjPtr->x - old_x;
X         dy = ObjPtr->y - old_y;
X         MoveObj (ObjPtr, dx, dy);
X         break;
X   }
X
X   switch (ObjPtr->type)
X   {
X      case OBJ_POLY:
X         for (i = 0; i < ObjPtr->detail.p->n; i++)
X         {
X            StretchedXY (OFFSET_X(ObjPtr->detail.p->vlist[i].x),
X                  OFFSET_Y(ObjPtr->detail.p->vlist[i].y), &x, &y);
X            ObjPtr->detail.p->vlist[i].x = (x << zoomScale) + drawOrigX;
X            ObjPtr->detail.p->vlist[i].y = (y << zoomScale) + drawOrigY;
X         }
X         if (ObjPtr->detail.p->curved)
X         {
X            cfree (ObjPtr->detail.p->svlist);
X            ObjPtr->detail.p->svlist = MakeSplinePolyVertex (
X                  &(ObjPtr->detail.p->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.p->n, ObjPtr->detail.p->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            StretchObj (attr_ptr->obj, Corner);
X         break;
X      case OBJ_ARC:
X         arc_ptr =  ObjPtr->detail.a;
X
X         StretchedXY (OFFSET_X(arc_ptr->xc), OFFSET_Y(arc_ptr->yc), &x, &y);
X         arc_ptr->xc = ObjPtr->x = (x<<zoomScale)+drawOrigX;
X         arc_ptr->yc = ObjPtr->y = (y<<zoomScale)+drawOrigY;
X         StretchedXY (OFFSET_X(arc_ptr->x1), OFFSET_Y(arc_ptr->y1), &x, &y);
X         arc_ptr->x1 = (x<<zoomScale)+drawOrigX;
X         arc_ptr->y1 = (y<<zoomScale)+drawOrigY;
X         StretchedXY (OFFSET_X(arc_ptr->x2), OFFSET_Y(arc_ptr->y2), &x, &y);
X         arc_ptr->x2 = (x<<zoomScale)+drawOrigX;
X         arc_ptr->y2 = (y<<zoomScale)+drawOrigY;
X         StretchedXY (OFFSET_X(arc_ptr->ltx), OFFSET_Y(arc_ptr->lty), &x, &y);
X         arc_ptr->w = 2*abs((x<<zoomScale)+drawOrigX-arc_ptr->xc);
X         arc_ptr->h = 2*abs((y<<zoomScale)+drawOrigY-arc_ptr->yc);
X         arc_ptr->ltx = arc_ptr->xc-(arc_ptr->w/2);
X         arc_ptr->lty = arc_ptr->yc-(arc_ptr->h/2);
X
X         if (multX < 0)
X         {
X            if (arc_ptr->angle1 > 0)
X               arc_ptr->angle1 = (180*64) - arc_ptr->angle1;
X            else
X               arc_ptr->angle1 = (-180)*64 - arc_ptr->angle1;
X            arc_ptr->angle2 = -(arc_ptr->angle2);
X         }
X         if (multY < 0)
X         {
X            arc_ptr->angle1 = -(arc_ptr->angle1);
X            arc_ptr->angle2 = -(arc_ptr->angle2);
X         }
X
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            StretchObj (attr_ptr->obj, Corner);
X         break;
X      case OBJ_RCBOX:
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            StretchObj (attr_ptr->obj, Corner);
X         break;
X      case OBJ_BOX:
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            StretchObj (attr_ptr->obj, Corner);
X         break;
X      case OBJ_OVAL:
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            StretchObj (attr_ptr->obj, Corner);
X         break;
X      case OBJ_TEXT: break;
X      case OBJ_POLYGON:
X         for (i = 0; i < ObjPtr->detail.g->n; i++)
X         {
X            StretchedXY (OFFSET_X(ObjPtr->detail.g->vlist[i].x),
X                  OFFSET_Y(ObjPtr->detail.g->vlist[i].y), &x, &y);
X            ObjPtr->detail.g->vlist[i].x = (x << zoomScale) + drawOrigX;
X            ObjPtr->detail.g->vlist[i].y = (y << zoomScale) + drawOrigY;
X         }
X         if (ObjPtr->detail.g->curved)
X         {
X            cfree (ObjPtr->detail.g->svlist);
X            ObjPtr->detail.g->svlist = MakeSplinePolygonVertex (
X                  &(ObjPtr->detail.g->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.g->n, ObjPtr->detail.g->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            StretchObj (attr_ptr->obj, Corner);
X         break;
X      case OBJ_SYM:
X      case OBJ_GROUP:
X         for (ptr = ObjPtr->detail.r->first; ptr != NULL; ptr = ptr->next)
X            StretchObj (ptr, Corner);
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            StretchObj (attr_ptr->obj, Corner);
X         break;
X      case OBJ_ICON: break;
X      case OBJ_XBM: break;
X   }
X   AdjObjBBox (ObjPtr);
X}
X
Xstatic
Xvoid StretchAllSel (Corner)
X   int	Corner;
X{
X   struct SelRec	* sel_ptr;
X
X   for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next)
X      StretchObj (sel_ptr->obj, Corner);
X}
X
Xstatic
Xvoid StretchBox (XGridOff, YGridOff, ObjPtr, Corner)
X   int			XGridOff, YGridOff, Corner;
X   struct ObjRec	* ObjPtr;
X{
X   int		x, y, stretching = TRUE;
X   int		ltx, lty, rbx, rby, sel_ltx, sel_lty, sel_rbx, sel_rby;
X   int		stretched_ltx, stretched_lty, stretched_rbx, stretched_rby;
X   int		stretched_sel_ltx, stretched_sel_lty, stretched_sel_rbx;
X   int		stretched_sel_rby;
X   double	obj_w, obj_h;
X   int		grid_x = XGridOff, grid_y = YGridOff;
X   XEvent	input;
X
X   SetPivot (Corner, ObjPtr->obbox);
X
X   stretched_sel_ltx = sel_ltx = OFFSET_X(selLtX);
X   stretched_sel_lty = sel_lty = OFFSET_Y(selLtY);
X   stretched_sel_rbx = sel_rbx = OFFSET_X(selRbX);
X   stretched_sel_rby = sel_rby = OFFSET_Y(selRbY);
X   SelBox (drawWindow, revDefaultGC, stretched_sel_ltx-1, stretched_sel_lty-1,
X         stretched_sel_rbx+1, stretched_sel_rby+1);
X
X   stretched_ltx = ltx = OFFSET_X(ObjPtr->obbox.ltx);
X   stretched_lty = lty = OFFSET_Y(ObjPtr->obbox.lty);
X   stretched_rbx = rbx = OFFSET_X(ObjPtr->obbox.rbx);
X   stretched_rby = rby = OFFSET_Y(ObjPtr->obbox.rby);
X   SelBox (drawWindow, revDefaultGC, stretched_ltx, stretched_lty,
X         stretched_rbx, stretched_rby);
X
X   if (ltx == rbx)
X   {
X      Msg ("Can not stretch!  Object has ZERO width!");
X      SelBox (drawWindow, revDefaultGC, stretched_ltx, stretched_lty,
X            stretched_rbx, stretched_rby);
X      SelBox (drawWindow, revDefaultGC, stretched_sel_ltx-1,
X            stretched_sel_lty-1, stretched_sel_rbx+1, stretched_sel_rby+1);
X      return;
X   }
X   else if (lty == rby)
X   {
X      Msg ("Can not stretch!  Object has ZERO height!");
X      SelBox (drawWindow, revDefaultGC, stretched_ltx, stretched_lty,
X            stretched_rbx, stretched_rby);
X      SelBox (drawWindow, revDefaultGC, stretched_sel_ltx-1,
X            stretched_sel_lty-1, stretched_sel_rbx+1, stretched_sel_rby+1);
X      return;
X   }
X
X   obj_w = (double)(moveX - pivotX);
X   obj_h = (double)(moveY - pivotY);
X
X   XGrabPointer (mainDisplay, drawWindow, FALSE,
X         PointerMotionMask | ButtonReleaseMask,
X         GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
X
X   while (stretching)
X   {
X      XNextEvent (mainDisplay, &input);
X      if (input.type == ButtonRelease)
X      {
X         XUngrabPointer (mainDisplay, CurrentTime);
X         stretching = FALSE;
X
X         SelBox (drawWindow, revDefaultGC, stretched_ltx, stretched_lty,
X               stretched_rbx, stretched_rby);
X         SelBox (drawWindow, revDefaultGC, stretched_sel_ltx-1,
X               stretched_sel_lty-1, stretched_sel_rbx+1, stretched_sel_rby+1);
X
X         if (multX != (double)1.0 || multY != (double)1.0)
X         {
X            HighLightReverse ();
X            StretchAllSel (Corner);
X            CalcBBox (stretched_sel_ltx, stretched_sel_lty, stretched_sel_rbx,
X                  stretched_sel_rby, &ltx, &lty, &rbx, &rby);
X            RedrawAreas (botObj, selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
X                  selRbX+(1<<zoomScale), selRbY+(1<<zoomScale),
X                  ((ltx-1)<<zoomScale)+drawOrigX,
X                  ((lty-1)<<zoomScale)+drawOrigY,
X                  ((rbx+1)<<zoomScale)+drawOrigX,
X                  ((rby+1)<<zoomScale)+drawOrigY);
X            HighLightForward ();
X            UpdSelBBox ();
X            SetFileModified (TRUE);
X         }
X      }
X      else if (input.type == MotionNotify)
X      {
X         x = input.xmotion.x;
X         y = input.xmotion.y;
X         GridXY (x, y, &grid_x, &grid_y);
X         MarkRulers (grid_x, grid_y);
X
X         SelBox (drawWindow, revDefaultGC, stretched_ltx, stretched_lty,
X               stretched_rbx, stretched_rby);
X         SelBox (drawWindow, revDefaultGC, stretched_sel_ltx-1,
X               stretched_sel_lty-1, stretched_sel_rbx+1, stretched_sel_rby+1);
X
X         if (changeX)
X            multX = (double)(moveX + grid_x - XGridOff - pivotX) / obj_w;
X         else
X            multX = (double)1.0;
X         if (changeY)
X            multY = (double)(moveY + grid_y - YGridOff - pivotY) / obj_h;
X         else
X            multY = (double)1.0;
X
X         StretchedXY (sel_ltx, sel_lty, &stretched_sel_ltx, &stretched_sel_lty);
X         StretchedXY (sel_rbx, sel_rby, &stretched_sel_rbx, &stretched_sel_rby);
X         StretchedXY (ltx, lty, &stretched_ltx, &stretched_lty);
X         StretchedXY (rbx, rby, &stretched_rbx, &stretched_rby);
X         SelBox (drawWindow, revDefaultGC, stretched_sel_ltx-1,
X               stretched_sel_lty-1, stretched_sel_rbx+1, stretched_sel_rby+1);
X         SelBox (drawWindow, revDefaultGC, stretched_ltx, stretched_lty,
X               stretched_rbx, stretched_rby);
X      }
X   }
X}
X
Xvoid StretchSel (XGridOff, YGridOff, ObjPtr, Corner)
X   int			XGridOff, YGridOff, Corner;
X   struct ObjRec	* ObjPtr;
X{
X   switch (ObjPtr->type)
X   {
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_GROUP:
X      case OBJ_ARC:
X      case OBJ_RCBOX:
X      case OBJ_SYM:
X      case OBJ_TEXT:
X         StretchBox (XGridOff, YGridOff, ObjPtr, Corner);
X         break;
X      case OBJ_POLY:
X         StretchPoly (XGridOff, YGridOff, ObjPtr, ObjPtr->detail.p->n,
X               ObjPtr->detail.p->vlist, Corner);
X         break;
X      case OBJ_POLYGON:
X         StretchPoly (XGridOff, YGridOff, ObjPtr, ObjPtr->detail.g->n,
X               ObjPtr->detail.g->vlist, Corner);
X         break;
X      case OBJ_ICON: break;
X      case OBJ_XBM: break;
X   }
X}
X
Xstatic
Xvoid FlipObjHorizontal (ObjPtr)
X   struct ObjRec	* ObjPtr;
X{
X   register XPoint	* v;
X   register int		i, two_x_pivot;
X   int			new_obj_ltx, new_obj_rbx, num_pts;
X   struct ObjRec	* obj_ptr;
X   struct AttrRec	* attr_ptr;
X   struct ArcRec	* arc_ptr;
X
X   SetFileModified (TRUE);
X   two_x_pivot = selObjLtX + selObjRbX;
X   new_obj_ltx = two_x_pivot - ObjPtr->obbox.rbx;
X   new_obj_rbx = two_x_pivot - ObjPtr->obbox.ltx;
X   switch (ObjPtr->type)
X   {
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_POLY:
X      case OBJ_POLYGON:
X      case OBJ_ARC:
X      case OBJ_RCBOX:
X      case OBJ_XBM:
X      case OBJ_GROUP:
X      case OBJ_SYM:
X      case OBJ_ICON:
X         if (ObjPtr->type == OBJ_XBM) FlipXBmHorizontal (ObjPtr);
X         ObjPtr->obbox.ltx = ObjPtr->x = new_obj_ltx;
X         ObjPtr->obbox.rbx = new_obj_rbx;
X         break;
X      case OBJ_TEXT:
X         switch (ObjPtr->detail.t->rotate)
X         {
X            case ROTATE0:
X            case ROTATE180:
X               ObjPtr->x = two_x_pivot - ObjPtr->x;
X               ObjPtr->detail.t ->just = MAXJUSTS - 1 - ObjPtr->detail.t->just;
X               break;
X            case ROTATE90: ObjPtr->x = new_obj_rbx; break;
X            case ROTATE270: ObjPtr->x = new_obj_ltx; break;
X         }
X         UpdTextBBox (ObjPtr);
X         break;
X/*    case OBJ_ICON: */
X/*       dx = new_obj_ltx - ObjPtr->x; */
X/*       MoveObj (ObjPtr, dx, 0); */
X/*       break; */
X   }
X   switch (ObjPtr->type)
X   {
X      case OBJ_POLY:
X         num_pts = ObjPtr->detail.p->n;
X         v = ObjPtr->detail.p->vlist;
X         for (i = 0; i < num_pts; i++, v++) (*v).x = two_x_pivot - (*v).x;
X         if (ObjPtr->detail.p->curved)
X         {
X            cfree (ObjPtr->detail.p->svlist);
X            ObjPtr->detail.p->svlist = MakeSplinePolyVertex (
X                  &(ObjPtr->detail.p->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.p->n, ObjPtr->detail.p->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjHorizontal (attr_ptr->obj);
X         break;
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_RCBOX:
X      case OBJ_XBM:
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjHorizontal (attr_ptr->obj);
X         break;
X      case OBJ_TEXT: break;
X      case OBJ_POLYGON:
X         num_pts = ObjPtr->detail.g->n;
X         v = ObjPtr->detail.g->vlist;
X         for (i = 0; i < num_pts; i++, v++) (*v).x = two_x_pivot - (*v).x;
X         if (ObjPtr->detail.g->curved)
X         {
X            cfree (ObjPtr->detail.g->svlist);
X            ObjPtr->detail.g->svlist = MakeSplinePolygonVertex (
X                  &(ObjPtr->detail.g->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.g->n, ObjPtr->detail.g->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjHorizontal (attr_ptr->obj);
X         break;
X      case OBJ_ARC:
X         arc_ptr = ObjPtr->detail.a;
X         arc_ptr->xc = two_x_pivot - arc_ptr->xc;
X         arc_ptr->x1 = two_x_pivot - arc_ptr->x1;
X         arc_ptr->x2 = two_x_pivot - arc_ptr->x2;
X         arc_ptr->dir = !(arc_ptr->dir);
X         arc_ptr->ltx = two_x_pivot - arc_ptr->ltx - arc_ptr->w;
X         if (arc_ptr->angle1 > 0)
X            arc_ptr->angle1 = (180*64) - arc_ptr->angle1;
X         else
X            arc_ptr->angle1 = (-180)*64 - arc_ptr->angle1;
X         arc_ptr->angle2 = -(arc_ptr->angle2);
X         UpdArcBBox (ObjPtr);
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjHorizontal (attr_ptr->obj);
X         break;
X      case OBJ_GROUP:
X      case OBJ_SYM:
X      case OBJ_ICON:
X         obj_ptr = ObjPtr->detail.r->first;
X         for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->next)
X            FlipObjHorizontal (obj_ptr);
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjHorizontal (attr_ptr->obj);
X         break;
X/*    case OBJ_ICON: break; */
X   }
X   AdjObjBBox (ObjPtr);
X}
X
Xstatic
Xvoid FlipObjVertical (ObjPtr)
X   struct ObjRec	* ObjPtr;
X{
X   register XPoint	* v;
X   register int		i, two_x_pivot;
X   int			new_obj_lty, new_obj_rby, num_pts;
X   struct ObjRec	* obj_ptr;
X   struct AttrRec	* attr_ptr;
X   struct ArcRec	* arc_ptr;
X
X   SetFileModified (TRUE);
X   two_x_pivot = selObjLtY + selObjRbY;
X   new_obj_lty = two_x_pivot - ObjPtr->obbox.rby;
X   new_obj_rby = two_x_pivot - ObjPtr->obbox.lty;
X   switch (ObjPtr->type)
X   {
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_POLY:
X      case OBJ_POLYGON:
X      case OBJ_ARC:
X      case OBJ_RCBOX:
X      case OBJ_XBM:
X      case OBJ_GROUP:
X      case OBJ_SYM:
X      case OBJ_ICON:
X         if (ObjPtr->type == OBJ_XBM) FlipXBmVertical (ObjPtr);
X         ObjPtr->obbox.lty = ObjPtr->y = new_obj_lty;
X         ObjPtr->obbox.rby = new_obj_rby;
X         break;
X      case OBJ_TEXT:
X         switch (ObjPtr->detail.t->rotate)
X         {
X            case ROTATE0: ObjPtr->y = new_obj_lty; break;
X            case ROTATE180: ObjPtr->y = new_obj_rby; break;
X            case ROTATE90:
X            case ROTATE270:
X               ObjPtr->y = two_x_pivot - ObjPtr->y;
X               ObjPtr->detail.t ->just = MAXJUSTS - 1 - ObjPtr->detail.t->just;
X               break;
X         }
X         UpdTextBBox (ObjPtr);
X         break;
X/*    case OBJ_ICON: */
X/*       dy = new_obj_lty - ObjPtr->y; */
X/*       MoveObj (ObjPtr, 0, dy); */
X/*       break; */
X   }
X   switch (ObjPtr->type)
X   {
X      case OBJ_POLY:
X         num_pts = ObjPtr->detail.p->n;
X         v = ObjPtr->detail.p->vlist;
X         for (i = 0; i < num_pts; i++, v++) (*v).y = two_x_pivot - (*v).y;
X         if (ObjPtr->detail.p->curved)
X         {
X            cfree (ObjPtr->detail.p->svlist);
X            ObjPtr->detail.p->svlist = MakeSplinePolyVertex (
X                  &(ObjPtr->detail.p->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.p->n, ObjPtr->detail.p->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjVertical (attr_ptr->obj);
X         break;
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_RCBOX:
X      case OBJ_XBM:
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjVertical (attr_ptr->obj);
X         break;
X      case OBJ_TEXT: break;
X      case OBJ_POLYGON:
X         num_pts = ObjPtr->detail.g->n;
X         v = ObjPtr->detail.g->vlist;
X         for (i = 0; i < num_pts; i++, v++) (*v).y = two_x_pivot - (*v).y;
X         if (ObjPtr->detail.g->curved)
X         {
X            cfree (ObjPtr->detail.g->svlist);
X            ObjPtr->detail.g->svlist = MakeSplinePolygonVertex (
X                  &(ObjPtr->detail.g->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.g->n, ObjPtr->detail.g->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjVertical (attr_ptr->obj);
X         break;
X      case OBJ_ARC:
X         arc_ptr = ObjPtr->detail.a;
X         arc_ptr->yc = two_x_pivot - arc_ptr->yc;
X         arc_ptr->y1 = two_x_pivot - arc_ptr->y1;
X         arc_ptr->y2 = two_x_pivot - arc_ptr->y2;
X         arc_ptr->dir = !(arc_ptr->dir);
X         arc_ptr->lty = two_x_pivot - arc_ptr->lty - arc_ptr->h;
X         arc_ptr->angle1 = -(arc_ptr->angle1);
X         arc_ptr->angle2 = -(arc_ptr->angle2);
X         UpdArcBBox (ObjPtr);
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjVertical (attr_ptr->obj);
X         break;
X      case OBJ_GROUP:
X      case OBJ_SYM:
X      case OBJ_ICON:
X         obj_ptr = ObjPtr->detail.r->first;
X         for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->next)
X            FlipObjVertical (obj_ptr);
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            FlipObjVertical (attr_ptr->obj);
X         break;
X/*    case OBJ_ICON: break; */
X   }
X   AdjObjBBox (ObjPtr);
X}
X
Xstatic int	rotatePivotX;
Xstatic int	rotatePivotY;
X
Xstatic
Xvoid SetRotatePivot ()
X{
X   if (topSel != NULL && topSel == botSel && topSel->obj->type == OBJ_TEXT)
X   {
X      rotatePivotX = topSel->obj->x;
X      rotatePivotY = topSel->obj->y;
X   }
X   else
X   {
X      rotatePivotX = (selObjLtX + selObjRbX) / 2;
X      rotatePivotY = (selObjLtY + selObjRbY) / 2;
X   }
X}
X
Xstatic
Xvoid RotatePtClockWise (X, Y, NewX, NewY)
X   int	X, Y, * NewX, * NewY;
X{
X   *NewX = rotatePivotX + rotatePivotY - Y;
X   *NewY = rotatePivotY - rotatePivotX + X;
X}
X
Xstatic
Xvoid RotateObjClockWise (ObjPtr)
X   struct ObjRec	* ObjPtr;
X{
X   register XPoint	* v;
X   register int		i;
X   int			x, y, ltx, lty, rbx, rby, num_pts, new_h;
X   struct ObjRec	* obj_ptr;
X   struct AttrRec	* attr_ptr;
X   struct ArcRec	* arc_ptr;
X
X   SetFileModified (TRUE);
X   switch (ObjPtr->type)
X   {
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_POLY:
X      case OBJ_POLYGON:
X      case OBJ_ARC:
X      case OBJ_RCBOX:
X      case OBJ_XBM:
X      case OBJ_GROUP:
X      case OBJ_SYM:
X      case OBJ_ICON:
X         if (ObjPtr->type == OBJ_XBM) RotateXBmClockWise (ObjPtr);
X         RotatePtClockWise (ObjPtr->obbox.ltx, ObjPtr->obbox.rby, &ltx, &lty);
X         RotatePtClockWise (ObjPtr->obbox.rbx, ObjPtr->obbox.lty, &rbx, &rby);
X         ObjPtr->obbox.ltx = ObjPtr->x = ltx;
X         ObjPtr->obbox.lty = ObjPtr->y = lty;
X         ObjPtr->obbox.rbx = rbx;
X         ObjPtr->obbox.rby = rby;
X         break;
X      case OBJ_TEXT:
X         RotatePtClockWise (ObjPtr->x, ObjPtr->y, &x, &y);
X         ObjPtr->x = x;
X         ObjPtr->y = y;
X         ObjPtr->detail.t->rotate = (ObjPtr->detail.t->rotate+1) & 0x3;
X         UpdTextBBox (ObjPtr);
X         break;
X/*    case OBJ_ICON: */
X/*       RotatePtClockWise (ObjPtr->obbox.ltx, ObjPtr->obbox.lty, &ltx, &lty);*/
X/*       dx = ltx - ObjPtr->obbox.ltx; */
X/*       dy = lty - ObjPtr->obbox.lty; */
X/*       MoveObj (ObjPtr, dx, dy); */
X/*       break; */
X   }
X   switch (ObjPtr->type)
X   {
X      case OBJ_POLY:
X         num_pts = ObjPtr->detail.p->n;
X         v = ObjPtr->detail.p->vlist;
X         for (i = 0; i < num_pts; i++, v++)
X         {
X            RotatePtClockWise ((*v).x, (*v).y, &x, &y);
X            (*v).x = x;
X            (*v).y = y;
X         }
X         if (ObjPtr->detail.p->curved)
X         {
X            cfree (ObjPtr->detail.p->svlist);
X            ObjPtr->detail.p->svlist = MakeSplinePolyVertex (
X                  &(ObjPtr->detail.p->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.p->n, ObjPtr->detail.p->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjClockWise (attr_ptr->obj);
X         break;
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_RCBOX:
X      case OBJ_XBM:
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjClockWise (attr_ptr->obj);
X         break;
X      case OBJ_TEXT: break;
X      case OBJ_POLYGON:
X         num_pts = ObjPtr->detail.g->n;
X         v = ObjPtr->detail.g->vlist;
X         for (i = 0; i < num_pts; i++, v++)
X         {
X            RotatePtClockWise ((*v).x, (*v).y, &x, &y);
X            (*v).x = x;
X            (*v).y = y;
X         }
X         if (ObjPtr->detail.g->curved)
X         {
X            cfree (ObjPtr->detail.g->svlist);
X            ObjPtr->detail.g->svlist = MakeSplinePolygonVertex (
X                  &(ObjPtr->detail.g->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.g->n, ObjPtr->detail.g->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjClockWise (attr_ptr->obj);
X         break;
X      case OBJ_ARC:
X         arc_ptr = ObjPtr->detail.a;
X
X         RotatePtClockWise (arc_ptr->xc, arc_ptr->yc, &x, &y);
X         arc_ptr->xc = ObjPtr->x = x; arc_ptr->yc = ObjPtr->y = y;
X         RotatePtClockWise (arc_ptr->x1, arc_ptr->y1, &x, &y);
X         arc_ptr->x1 = x; arc_ptr->y1 = y;
X         RotatePtClockWise (arc_ptr->x2, arc_ptr->y2, &x, &y);
X         arc_ptr->x2 = x; arc_ptr->y2 = y;
X         RotatePtClockWise (arc_ptr->ltx, arc_ptr->lty+arc_ptr->h, &x, &y);
X         arc_ptr->ltx = x; arc_ptr->lty = y;
X         new_h = arc_ptr->w;
X         arc_ptr->w = arc_ptr->h; arc_ptr->h = new_h;
X         arc_ptr->angle1 -= (arc_ptr->angle1 < (-90*64)) ? (-270*64) : (90*64);
X         UpdArcBBox (ObjPtr);
X
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjClockWise (attr_ptr->obj);
X         break;
X      case OBJ_GROUP:
X      case OBJ_SYM:
X      case OBJ_ICON:
X         obj_ptr = ObjPtr->detail.r->first;
X         for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->next)
X            RotateObjClockWise (obj_ptr);
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjClockWise (attr_ptr->obj);
X         break;
X/*    case OBJ_ICON: break; */
X   }
X   AdjObjBBox (ObjPtr);
X}
X
Xstatic
Xvoid RotatePtCounter (X, Y, NewX, NewY)
X   int	X, Y, * NewX, * NewY;
X{
X   *NewX = rotatePivotX - rotatePivotY + Y;
X   *NewY = rotatePivotY + rotatePivotX - X;
X}
X
Xstatic
Xvoid RotateObjCounter (ObjPtr)
X   struct ObjRec	* ObjPtr;
X{
X   register XPoint	* v;
X   register int		i;
X   int			x, y, ltx, lty, rbx, rby, num_pts, new_h;
X   struct ObjRec	* obj_ptr;
X   struct AttrRec	* attr_ptr;
X   struct ArcRec	* arc_ptr;
X
X   SetFileModified (TRUE);
X   switch (ObjPtr->type)
X   {
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_POLY:
X      case OBJ_POLYGON:
X      case OBJ_ARC:
X      case OBJ_RCBOX:
X      case OBJ_XBM:
X      case OBJ_GROUP:
X      case OBJ_SYM:
X      case OBJ_ICON:
X         if (ObjPtr->type == OBJ_XBM) RotateXBmCounter (ObjPtr);
X         RotatePtCounter (ObjPtr->obbox.rbx, ObjPtr->obbox.lty, &ltx, &lty);
X         RotatePtCounter (ObjPtr->obbox.ltx, ObjPtr->obbox.rby, &rbx, &rby);
X         ObjPtr->obbox.ltx = ObjPtr->x = ltx;
X         ObjPtr->obbox.lty = ObjPtr->y = lty;
X         ObjPtr->obbox.rbx = rbx;
X         ObjPtr->obbox.rby = rby;
X         break;
X      case OBJ_TEXT:
X         RotatePtCounter (ObjPtr->x, ObjPtr->y, &x, &y);
X         ObjPtr->x = x;
X         ObjPtr->y = y;
X         ObjPtr->detail.t->rotate = (ObjPtr->detail.t->rotate+3) & 0x3;
X         UpdTextBBox (ObjPtr);
X         break;
X/*    case OBJ_ICON: */
X/*       RotatePtCounter (ObjPtr->obbox.ltx, ObjPtr->obbox.lty, &ltx, &lty); */
X/*       dx = ltx - ObjPtr->obbox.ltx; */
X/*       dy = lty - ObjPtr->obbox.lty; */
X/*       MoveObj (ObjPtr, dx, dy); */
X/*       break; */
X   }
X   switch (ObjPtr->type)
X   {
X      case OBJ_POLY:
X         num_pts = ObjPtr->detail.p->n;
X         v = ObjPtr->detail.p->vlist;
X         for (i = 0; i < num_pts; i++, v++)
X         {
X            RotatePtCounter ((*v).x, (*v).y, &x, &y);
X            (*v).x = x;
X            (*v).y = y;
X         }
X         if (ObjPtr->detail.p->curved)
X         {
X            cfree (ObjPtr->detail.p->svlist);
X            ObjPtr->detail.p->svlist = MakeSplinePolyVertex (
X                  &(ObjPtr->detail.p->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.p->n, ObjPtr->detail.p->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjCounter (attr_ptr->obj);
X         break;
X      case OBJ_BOX:
X      case OBJ_OVAL:
X      case OBJ_RCBOX:
X      case OBJ_XBM:
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjCounter (attr_ptr->obj);
X         break;
X      case OBJ_TEXT: break;
X      case OBJ_POLYGON:
X         num_pts = ObjPtr->detail.g->n;
X         v = ObjPtr->detail.g->vlist;
X         for (i = 0; i < num_pts; i++, v++)
X         {
X            RotatePtCounter ((*v).x, (*v).y, &x, &y);
X            (*v).x = x;
X            (*v).y = y;
X         }
X         if (ObjPtr->detail.g->curved)
X         {
X            cfree (ObjPtr->detail.g->svlist);
X            ObjPtr->detail.g->svlist = MakeSplinePolygonVertex (
X                  &(ObjPtr->detail.g->sn), drawOrigX,
X                  drawOrigY, ObjPtr->detail.g->n, ObjPtr->detail.g->vlist);
X         }
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjCounter (attr_ptr->obj);
X         break;
X      case OBJ_ARC:
X         arc_ptr = ObjPtr->detail.a;
X
X         RotatePtCounter (arc_ptr->xc, arc_ptr->yc, &x, &y);
X         arc_ptr->xc = ObjPtr->x = x; arc_ptr->yc = ObjPtr->y = y;
X         RotatePtCounter (arc_ptr->x1, arc_ptr->y1, &x, &y);
X         arc_ptr->x1 = x; arc_ptr->y1 = y;
X         RotatePtCounter (arc_ptr->x2, arc_ptr->y2, &x, &y);
X         arc_ptr->x2 = x; arc_ptr->y2 = y;
X         RotatePtCounter (arc_ptr->ltx+arc_ptr->w, arc_ptr->lty, &x, &y);
X         arc_ptr->ltx = x; arc_ptr->lty = y;
X         new_h = arc_ptr->w;
X         arc_ptr->w = arc_ptr->h; arc_ptr->h = new_h;
X         arc_ptr->angle1 += (arc_ptr->angle1 > 90*64) ? (-270*64) : (90*64);
X         UpdArcBBox (ObjPtr);
X
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjCounter (attr_ptr->obj);
X         break;
X      case OBJ_GROUP:
X      case OBJ_SYM:
X      case OBJ_ICON:
X         obj_ptr = ObjPtr->detail.r->first;
X         for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->next)
X            RotateObjCounter (obj_ptr);
X         attr_ptr = ObjPtr->fattr;
X         for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
X            RotateObjCounter (attr_ptr->obj);
X         break;
X/*    case OBJ_ICON: break; */
X   }
X   AdjObjBBox (ObjPtr);
X}
X
Xvoid FlipHorizontal ()
X{
X   register struct SelRec	* sel_ptr;
X   int				saved_ltx, saved_lty, saved_rbx, saved_rby;
X
X   if (topSel == NULL) return;
X
X   saved_ltx = selLtX; saved_lty = selLtY;
X   saved_rbx = selRbX; saved_rby = selRbY;
X   HighLightReverse ();
X   for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next)
X      FlipObjHorizontal (sel_ptr->obj);
X   UpdSelBBox ();
X   RedrawAreas (botObj, saved_ltx-(1<<zoomScale), saved_lty-(1<<zoomScale),
X         saved_rbx+(1<<zoomScale), saved_rby+(1<<zoomScale),
X         selLtX-(1<<zoomScale), selLtY-(1<<zoomScale), selRbX+(1<<zoomScale),
X         selRbY+(1<<zoomScale));
X   HighLightForward ();
X   justDupped = FALSE;
X}
X
Xvoid FlipVertical ()
X{
X   register struct SelRec	* sel_ptr;
X   int				saved_ltx, saved_lty, saved_rbx, saved_rby;
X
X   if (topSel == NULL) return;
X
X   saved_ltx = selLtX; saved_lty = selLtY;
X   saved_rbx = selRbX; saved_rby = selRbY;
X   HighLightReverse ();
X   for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next)
X      FlipObjVertical (sel_ptr->obj);
X   UpdSelBBox ();
X   RedrawAreas (botObj, saved_ltx-(1<<zoomScale), saved_lty-(1<<zoomScale),
X         saved_rbx+(1<<zoomScale), saved_rby+(1<<zoomScale),
X         selLtX-(1<<zoomScale), selLtY-(1<<zoomScale), selRbX+(1<<zoomScale),
X         selRbY+(1<<zoomScale));
X   HighLightForward ();
X   justDupped = FALSE;
X}
X
Xvoid RotateClockWise ()
X{
X   register struct SelRec	* sel_ptr;
X   int				saved_ltx, saved_lty, saved_rbx, saved_rby;
X   int				text_obj_created, text_cursor_shown;
X
X   if  (topSel == NULL)
X   {
X      text_cursor_shown = textCursorShown;
X      text_obj_created = TieLooseEnds ();
X      curRotate = (curRotate+1) & 0x3;
X      ShowRotate ();
X      if (!text_obj_created && curChoice == DRAWTEXT && text_cursor_shown)
X      {
X         NewCurText ();
X         RedrawCurText ();
X      }
X      else
X         textCursorShown = FALSE;
X      return;
X   }
X
X   saved_ltx = selLtX; saved_lty = selLtY;
X   saved_rbx = selRbX; saved_rby = selRbY;
X   HighLightReverse ();
X   SetRotatePivot ();
X   for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next)
X      RotateObjClockWise (sel_ptr->obj);
X   UpdSelBBox ();
X   RedrawAreas (botObj, saved_ltx-(1<<zoomScale), saved_lty-(1<<zoomScale),
X         saved_rbx+(1<<zoomScale), saved_rby+(1<<zoomScale),
X         selLtX-(1<<zoomScale), selLtY-(1<<zoomScale), selRbX+(1<<zoomScale),
X         selRbY+(1<<zoomScale));
X   HighLightForward ();
X   justDupped = FALSE;
X}
X
Xvoid RotateCounter ()
X{
X   register struct SelRec	* sel_ptr;
X   int				saved_ltx, saved_lty, saved_rbx, saved_rby;
X   int				text_obj_created, text_cursor_shown;
X
X   if  (topSel == NULL)
X   {
X      text_cursor_shown = textCursorShown;
X      text_obj_created = TieLooseEnds ();
X      curRotate = (curRotate+3) & 0x3;
X      ShowRotate ();
X      if (!text_obj_created && curChoice == DRAWTEXT && text_cursor_shown)
X      {
X         NewCurText ();
X         RedrawCurText ();
X      }
X      else
X         textCursorShown = FALSE;
X      return;
X   }
X
X   saved_ltx = selLtX; saved_lty = selLtY;
X   saved_rbx = selRbX; saved_rby = selRbY;
X   HighLightReverse ();
X   SetRotatePivot ();
X   for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next)
X      RotateObjCounter (sel_ptr->obj);
X   UpdSelBBox ();
X   RedrawAreas (botObj, saved_ltx-(1<<zoomScale), saved_lty-(1<<zoomScale),
X         saved_rbx+(1<<zoomScale), saved_rby+(1<<zoomScale),
X         selLtX-(1<<zoomScale), selLtY-(1<<zoomScale), selRbX+(1<<zoomScale),
X         selRbY+(1<<zoomScale));
X   HighLightForward ();
X   justDupped = FALSE;
X}
END_OF_FILE
if test 44036 -ne `wc -c <'stretch.c'`; then
    echo shar: \"'stretch.c'\" unpacked with wrong size!
fi
# end of 'stretch.c'
fi
echo shar: End of archive 15 \(of 23\).
cp /dev/null ark15isdone
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

--
Dan Heller
------------------------------------------------
O'Reilly && Associates		 Z-Code Software
Senior Writer			       President
argv@ora.com			argv@zipcode.com
------------------------------------------------
General Email: argv@sun.com
Comp-sources-x stuff: comp-sources.x@uunet.uu.net