[comp.sources.x] v01i008: xfig: a MacDraw style line editor

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

Submitted-by: ken@cs.rochester.edu
Posting-number: Volume 1, Issue 8
Archive-name: xfig/part07

#! /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 7 (of 11)."
# Contents:  f2p.c fig.1 undo.c
# Wrapped by mikew@wyse on Tue Aug 16 13:14:39 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f f2p.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"f2p.c\"
else
echo shar: Extracting \"f2p.c\" \(12807 characters\)
sed "s/^X//" >f2p.c <<'END_OF_f2p.c'
X/* 
X *	F2p : Fig-to-pic translator
X *
X *	Copyright (c) 1985, 1988 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
X *	January 1985.
X *	1st revision : October 1985.
X *	2nd revision : March 1988 - read fig 1.4
X *
X *	%W%	%G%
X*/
X#include "fig.h"
X#include "object.h"
X
Xchar		Usage[] = "Usage: f2p [ -s font_size ] [ input_file [ output_file ] ]\n";
Xchar		*from = NULL, *to = NULL;
XFILE		*ffp = NULL, *tfp = NULL;
Xint		font_size = 11;		/* points */
Xchar		Err_incomp[] = "Incomplete %s object at line %d.";
Xchar		Err_mem[] = "Running out of memory.";
X
Xput_msg(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
Xchar   *format, *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *arg8;
X{
X	fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
X	}
X
Xget_args(argc, argv)
Xint	 argc;
Xchar	*argv[];
X{
X	char	*a;
X	int	first = 1;
X
X	while (--argc) {
X	    a = *++argv;
X	    if (*a == '-') {
X		if (*++a == 's') {	/* Font size followed */
X		    if (--argc) {
X			font_size = atoi(*++argv);
X			if (font_size <= 0 || font_size > 30) {
X			    fprintf(stderr, Usage);
X			    exit(0);
X			    }
X			}
X		    else {
X			fprintf(stderr, Usage);
X			exit(0);
X			}
X		    }
X		else {
X		    fprintf(stderr, Usage);
X		    exit(0);
X		    }
X		}
X	    else if (first) {
X		from = a;	/*  from file  */
X		first = 0;
X		}
X	    else if (first == 0) {
X		to = a;		/*  to file  */
X		first = -1;
X		}
X	    else
X		fprintf(stderr, Usage);
X	    }
X	}
X
Xmain(argc, argv)
Xint	 argc;
Xchar	*argv[];
X{
X	F_compound	objects;
X	int		status;
X	char		c;
X
X	get_args(argc, argv);
X	if (to == NULL)
X	    tfp = stdout;
X	else if ((tfp = fopen(to, "w")) == NULL) {
X	    fprintf(stderr, "Couldn't open %s\n", to);
X	    fprintf(stderr, Usage);
X	    exit(0);
X	    }
X
X	if (from)
X	    status = read_fig(from, &objects);
X	else 	/* read from stdin */
X	    status = readfp_fig(stdin, &objects);
X
X	if (status != 0) {
X	    if (from) read_fail_message(from, status);
X	    exit(0);
X	    }
X	genpic_objects(&objects);
X	if (tfp != stdout) fclose(tfp);
X	}
X
X#define			TOP	10.5	/* top of page is 10.5 inch */
Xstatic double		ppi;
Xstatic int		CONV = 0;
X
Xdouble
Xconvy(a)
Xdouble	a;
X{
X	return((double)(CONV ? TOP-a : a));
X	}
X
Xgenpic_objects(objects)
XF_compound	*objects;
X{
X	int		coord_system;
X	F_arc		*a;
X	F_compound	*c;
X	F_ellipse	*e;
X	F_line		*l;
X	F_spline	*s;
X	F_text		*t;
X
X	if (0 == (ppi = (double)objects->nwcorner.x)) {
X	    fprintf(stderr, "Resolution is zero!! default to 80 ppi\n");
X	    ppi = 80.0;
X	    }
X	coord_system = objects->nwcorner.y;
X	if (coord_system != 1 && coord_system != 2) {
X	    fprintf(stderr, "Wrong coordinate system; cannot continue\n");
X	    return;
X	    }
X	if (coord_system == 2) CONV = 1;
X
X	fprintf(tfp, ".PS\n");	/* PostScript magic strings */
X
X	for (a = objects->arcs; a != NULL; a = a->next) genpic_arc(a);
X	for (c = objects->compounds; c != NULL; c = c->next) genpic_compound(c);
X	for (e = objects->ellipses; e != NULL; e = e->next) genpic_ellipse(e);
X	for (l = objects->lines; l != NULL; l = l->next) genpic_line(l);
X	for (s = objects->splines; s != NULL; s = s->next) genpic_spline(s);
X	for (t = objects->texts; t != NULL; t = t->next) genpic_text(t);
X	fprintf(tfp, ".PE\n");
X	}
X
X/*
XThe line thickness is, unfortunately, multiple of pixel.
XOne pixel thickness is a little too thick on the hard copy
Xso I scale it with 0.7; i.e., it's a kludge.  The best way is
Xto allow thickness in fraction of pixel.
X
XNote that the current version of psdit (a ditroff to postcript filter)
Xwon't take the legitimate line thickness command.
X*/
Xset_linewidth(w)
Xint	w;
X{
X	static int	cur_thickness = -1;
X
X	/*
X	if (w == 0) return;
X	if (w != cur_thickness) {
X	    cur_thickness = w;
X	    fprintf(tfp, "\"\\D't %.5fi'\"\n", 0.7 * cur_thickness / ppi);
X	    }
X	*/
X	}
X
Xset_style(s, v)
Xint	s;
Xfloat	v;
X{
X	static float	style_val = -1;
X
X	if (s == DASH_LINE || s == DOTTED_LINE) {
X	    if (v == style_val) return;
X	    if (v == 0.0) return;
X	    style_val = v;
X	    fprintf(tfp, "dashwid = %.3fi\n", style_val/ppi);
X	    }
X	}
X
Xgenpic_compound(com)
XF_compound	*com;
X{
X	F_arc		*a;
X	F_compound	*c;
X	F_ellipse	*e;
X	F_line		*l;
X	F_spline	*s;
X	F_text		*t;
X
X	for (a = com->arcs; a != NULL; a = a->next) genpic_arc(a);
X	for (c = com->compounds; c != NULL; c = c->next) genpic_compound(c);
X	for (e = com->ellipses; e != NULL; e = e->next) genpic_ellipse(e);
X	for (l = com->lines; l != NULL; l = l->next) genpic_line(l);
X	for (s = com->splines; s != NULL; s = s->next) genpic_spline(s);
X	for (t = com->texts; t != NULL; t = t->next) genpic_text(t);
X	}
X
Xgenpic_line(l)
XF_line	*l;
X{
X	F_point		*p, *q;
X
X	set_linewidth(l->thickness);
X	set_style(l->style, l->style_val);
X	p = l->points;
X	q = p->next;
X	if (q == NULL) { /* A single point line */
X	    fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f\n",
X			p->x/ppi, convy(p->y/ppi), p->x/ppi, convy(p->y/ppi));
X	    return;
X	    }
X	if (l->back_arrow)
X	    draw_arrow_head(q->x/ppi, convy(q->y/ppi), p->x/ppi,
X		convy(p->y/ppi), l->back_arrow->ht/ppi, l->back_arrow->wid/ppi);
X	if (l->style == DASH_LINE && l->style_val > 0.0)
X	    fprintf(tfp, "line dashed from");
X	else if (l->style == DOTTED_LINE && l->style_val > 0.0)
X	    fprintf(tfp, "line dotted from");
X	else
X	    fprintf(tfp, "line from");
X	fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
X	while (q->next != NULL) {
X	    p = q;
X	    q = q->next;
X	    fprintf(tfp, " %.3f,%.3f to", p->x/ppi, convy(p->y/ppi));
X	    }
X	fprintf(tfp, " %.3f,%.3f\n", q->x/ppi, convy(q->y/ppi));
X	if (l->for_arrow)
X	    draw_arrow_head(p->x/ppi, convy(p->y/ppi), q->x/ppi,
X		convy(q->y/ppi), l->for_arrow->ht/ppi, l->for_arrow->wid/ppi);
X	}
X
Xgenpic_spline(s)
XF_spline	*s;
X{
X	if (int_spline(s))
X	    genpic_itp_spline(s);
X	else
X	    genpic_ctl_spline(s);
X	}
X
Xgenpic_ctl_spline(s)
XF_spline	*s;
X{
X	if (closed_spline(s))
X	    genpic_closed_spline(s);
X	else
X	    genpic_open_spline(s);
X	}
X
Xgenpic_open_spline(s)
XF_spline	*s;
X{
X	double		x1, y1, x2, y2;
X	F_point		*p, *q;
X
X	p = s->points;
X	x1 = p->x/ppi; y1 = convy(p->y/ppi);
X	p = p->next;
X	x2 = p->x/ppi; y2 = convy(p->y/ppi);
X
X	if (s->back_arrow)
X	    draw_arrow_head(x2, y2, x1, y1,
X		s->back_arrow->ht/ppi, s->back_arrow->wid/ppi);
X
X	/* Pic's spline supports only solid line style */
X	/* set_linewidth(s->thickness); */
X
X	if (p->next == NULL) {
X	    fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f\n", x1, y1, x2, y2);
X	    if (s->for_arrow)
X		draw_arrow_head(x1, y1, x2, y2, s->for_arrow->ht/ppi,
X				s->for_arrow->wid/ppi);
X	    return;
X	    }
X
X	fprintf(tfp, "spline from %.3f,%.3f to %.3f,%.3f", x1, y1, x2, y2);
X
X	for (q = p->next; q->next != NULL; p = q, q = q->next)
X	    fprintf(tfp, " to %.3f,%.3f", q->x/ppi, convy(q->y/ppi));
X	fprintf(tfp, " to %.3f,%.3f\n", (x2=q->x/ppi), (y2=convy(q->y/ppi)));
X
X	if (s->for_arrow)
X	    draw_arrow_head(p->x/ppi, convy(p->y/ppi), x2, y2,
X		s->for_arrow->ht/ppi, s->for_arrow->wid/ppi);
X	}
X
Xgenpic_ellipse(e)
XF_ellipse	*e;
X{
X	set_linewidth(e->thickness);
X	fprintf(tfp, "ellipse at %.3f,%.3f wid %.3f ht %.3f\n",
X		e->center.x/ppi, convy(e->center.y/ppi),
X		2 * e->radiuses.x/ppi, 2 * e->radiuses.y/ppi);
X	}
X
X/*
XText is display on the screen with the base line starting at
X(base_x, base_y); some characters extend below this line.
XPic displays the center of the height of text at the given
Xcoordinate. HT_OFFSET is use to compensate all the above factors
Xso text position in fig 1.4 should be at the same position on
Xthe screen as on the hard copy.
X*/
X#define			HT_OFFSET	(0.2 / 72.0)
X
Xgenpic_text(t)
XF_text	*t;
X{
X	float	y;
X	int	first = 1;
X
X	if (first) {
X	    first = 0;
X	    fprintf(tfp, ".ps %d\n", font_size);
X	    }
X
X	y = convy(t->base_y/ppi) + font_size * HT_OFFSET;
X	fprintf(tfp, "\"%s\" at %.3f,%.3f ljust\n",
X		t->cstring, t->base_x/ppi, y);
X	}
X
Xgenpic_arc(a)
XF_arc	*a;
X{
X	double		x, y;
X	double		cx, cy, sx, sy, ex, ey;
X
X	cx = a->center.x/ppi; cy = convy(a->center.y/ppi);
X	sx = a->point[0].x/ppi; sy = convy(a->point[0].y/ppi);
X	ex = a->point[2].x/ppi; ey = convy(a->point[2].y/ppi);
X
X	set_linewidth(a->thickness);
X
X	if (a->for_arrow) {
X	    arc_tangent(cx, cy, ex, ey, a->direction, &x, &y);
X	    draw_arrow_head(x, y, ex, ey,
X			a->for_arrow->ht/ppi, a->for_arrow->wid/ppi);
X	    }
X	if (a->back_arrow) {
X	    arc_tangent(cx, cy, sx, sy, !a->direction, &x, &y);
X	    draw_arrow_head(x, y, sx, sy,
X			a->back_arrow->ht/ppi, a->back_arrow->wid/ppi);
X	    }
X
X	if (a->direction)
X	    fprintf(tfp, "arc at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f\n",
X			cx, cy, sx, sy, ex, ey);
X	else
X	    fprintf(tfp, "arc at %.3f,%.3f from %.3f,%.3f to %.3f,%.3f cw\n",
X			cx, cy, sx, sy, ex, ey);
X
X	}
X
Xarc_tangent(x1, y1, x2, y2, direction, x, y)
Xdouble	x1, y1, x2, y2, *x, *y;
Xint	direction;
X{
X	if (direction) { /* counter clockwise  */
X	    *x = x2 + (y2 - y1);
X	    *y = y2 - (x2 - x1);
X	    }
X	else {
X	    *x = x2 - (y2 - y1);
X	    *y = y2 + (x2 - x1);
X	    }
X	}
X
X/*	draw arrow heading from (x1, y1) to (x2, y2)	*/
X
Xdraw_arrow_head(x1, y1, x2, y2, arrowht, arrowwid)
Xdouble	x1, y1, x2, y2, arrowht, arrowwid;
X{
X	double	x, y, xb, yb, dx, dy, l, sina, cosa;
X	double	xc, yc, xd, yd;
X
X	dx = x2 - x1;  dy = y1 - y2;
X	l = sqrt((dx*dx + dy*dy));
X	sina = dy / l;  cosa = dx / l;
X	xb = x2*cosa - y2*sina;
X	yb = x2*sina + y2*cosa;
X	x = xb - arrowht;
X	y = yb - arrowwid / 2;
X	xc = x*cosa + y*sina;
X	yc = -x*sina + y*cosa;
X	y = yb + arrowwid / 2;
X	xd = x*cosa + y*sina;
X	yd = -x*sina + y*cosa;
X	fprintf(tfp, "line from %.3f,%.3f to %.3f,%.3f to %.3f,%.3f\n",
X		xc, yc, x2, y2, xd, yd);
X	}
X
X#define		THRESHOLD	.05	/* inch */
X
Xquadratic_spline(a1, b1, a2, b2, a3, b3, a4, b4)
Xdouble	a1, b1, a2, b2, a3, b3, a4, b4;
X{
X	double	x1, y1, x4, y4;
X	double	xmid, ymid;
X
X	x1 = a1; y1 = b1;
X	x4 = a4; y4 = b4;
X
X	xmid = (a2 + a3) / 2;
X	ymid = (b2 + b3) / 2;
X	if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD) {
X	    fprintf(tfp, "\tto %.3f,%.3f\\\n", xmid, ymid);
X	    }
X	else {
X	    quadratic_spline(x1, y1, ((x1+a2)/2), ((y1+b2)/2),
X			((3*a2+a3)/4), ((3*b2+b3)/4), xmid, ymid);
X	    }
X
X	if (fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
X	    fprintf(tfp, "\tto %.3f,%.3f\\\n", x4, y4);
X	    }
X	else {
X	    quadratic_spline(xmid, ymid, ((a2+3*a3)/4), ((b2+3*b3)/4),
X			((a3+x4)/2), ((b3+y4)/2), x4, y4);
X	    }
X	}
X
Xgenpic_closed_spline(s)
XF_spline	*s;
X{
X	F_point	*p;
X	double	cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
X	double	x1, y1, x2, y2;
X
X	p = s->points;
X	x1 = p->x/ppi;  y1 = convy(p->y/ppi);
X	p = p->next;
X	x2 = p->x/ppi;  y2 = convy(p->y/ppi);
X	cx1 = (x1 + x2) / 2;      cy1 = (y1 + y2) / 2;
X	cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
X
X	for (p = p->next; p != NULL; p = p->next) {
X	    fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1);
X	    x1 = x2;  y1 = y2;
X	    x2 = p->x/ppi;  y2 = convy(p->y/ppi);
X	    cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
X	    cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
X	    quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
X	    fprintf(tfp, "\n");
X	    cx1 = cx4;  cy1 = cy4;
X	    cx2 = (x1 + 3 * x2) / 4;  cy2 = (y1 + 3 * y2) / 4;
X	    }
X	x1 = x2;  y1 = y2;
X	p = s->points->next;
X	x2 = p->x/ppi;  y2 = convy(p->y/ppi);
X	cx3 = (3 * x1 + x2) / 4;  cy3 = (3 * y1 + y2) / 4;
X	cx4 = (x1 + x2) / 2;      cy4 = (y1 + y2) / 2;
X	fprintf(tfp, "line from %.3f,%.3f ", cx1, cy1);
X	quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
X	fprintf(tfp, "\n");
X	}
X
Xgenpic_itp_spline(s)
XF_spline	*s;
X{
X	F_point		*p1, *p2;
X	F_control	*cp1, *cp2;
X	double		x1, x2, y1, y2;
X
X	p1 = s->points;
X	cp1 = s->controls;
X	x2 = p1->x/ppi; y2 = convy(p1->y/ppi);
X
X	if (s->for_arrow)
X	    draw_arrow_head(cp1->rx/ppi, convy(cp1->ry/ppi), x2, y2,
X		s->for_arrow->ht/ppi, s->for_arrow->wid/ppi);
X
X	for (p2 = p1->next, cp2 = cp1->next; p2 != NULL;
X		p1 = p2, cp1 = cp2, p2 = p2->next, cp2 = cp2->next) {
X	    fprintf(tfp, "line from %.3f,%.3f ", x2, y2);
X	    x1 = x2; y1 = y2;
X	    x2 = p2->x/ppi; y2 = convy(p2->y/ppi);
X	    bezier_spline(x1, y1, (double)cp1->rx/ppi, convy(cp1->ry/ppi),
X		(double)cp2->lx/ppi, convy(cp2->ly/ppi), x2, y2);
X	    fprintf(tfp, "\n");
X	    }
X
X	if (s->back_arrow)
X	    draw_arrow_head(cp1->lx/ppi, convy(cp1->ly/ppi), x2, y2,
X		s->back_arrow->ht/ppi, s->back_arrow->wid/ppi);
X	}
X
Xbezier_spline(a0, b0, a1, b1, a2, b2, a3, b3)
Xdouble	a0, b0, a1, b1, a2, b2, a3, b3;
X{
X	double	x0, y0, x3, y3;
X	double	sx1, sy1, sx2, sy2, tx, ty, tx1, ty1, tx2, ty2, xmid, ymid;
X
X	x0 = a0; y0 = b0;
X	x3 = a3; y3 = b3;
X	if (fabs(x0 - x3) < THRESHOLD && fabs(y0 - y3) < THRESHOLD) {
X	    fprintf(tfp, "\tto %.3f,%.3f\\\n", x3, y3);
X	    }
X	else {
X	    tx = (a1 + a2) / 2;		ty = (b1 + b2) / 2;
X	    sx1 = (x0 + a1) / 2;	sy1 = (y0 + b1) / 2;
X	    sx2 = (sx1 + tx) / 2;	sy2 = (sy1 + ty) / 2;
X	    tx2 = (a2 + x3) / 2;	ty2 = (b2 + y3) / 2;
X	    tx1 = (tx2 + tx) / 2;	ty1 = (ty2 + ty) / 2;
X	    xmid = (sx2 + tx1) / 2;	ymid = (sy2 + ty1) / 2;
X
X	    bezier_spline(x0, y0, sx1, sy1, sx2, sy2, xmid, ymid);
X	    bezier_spline(xmid, ymid, tx1, ty1, tx2, ty2, x3, y3);
X	    }
X	}
END_OF_f2p.c
if test 12807 -ne `wc -c <f2p.c`; then
    echo shar: \"f2p.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f fig.1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"fig.1\"
else
echo shar: Extracting \"fig.1\" \(13718 characters\)
sed "s/^X//" >fig.1 <<'END_OF_fig.1'
X.TH FIG 1 "28 March 1988"
X.SH NAME
Xfig \- Facility for Interactive Generation of figures
X.SH SYNOPSIS
X.B fig
X\fB[ -r ]\fP 
X\fB[\fP \fIfile\fP \fB]\fP
X.SH DESCRIPTION
X.I Fig 
Xis a menu-driven tool that allows the user to draw and manipulate objects
Xinteractively on the screen of a Sun Workstation. 
XIt can only be run within the SunWindows environment and requires a 
Xthree-button mouse.
X.I File 
Xspecifies the name of a file to be edited. The description of objects in
Xthe file will be read at the start of \fIfig\fP. 
X.PP
XThe output from \fIfig\fP can be printed by first using 
X.I f2p
X(\fIfig\fP to \fIpic\fP(1) translator, also known by its previous
Xname \fIftop\fP(1L)) to translate it into 
X.IR pic (1)
Xlanguage.
XThe \fIpic\fP(1) file can be saved and edited like ordinary text file.
XTo print the file one should issue the command:
X.br
X\fCpic file | troff\fP
X.br
Xadding any required options to the invocation of \fItroff\fP(1).
XThe file may be used in conjunction with any other \fItroff\fP(1) preprocessors.
X.PP
XAnother way to produce a hrad copy is to use \fIf2ps\fP (the fig to postscript
Xtranslator) to produce a postscript file from \fIfig\fP file.
XThe postscript file can be sent directly to a postscript printer
Xvia
X.IR lpr (1).
X.SH OPTIONS
X.TP
X.B \-r
XChange the position of the panel window to the right of the canvas window
X(default: left).
X.SH "GRAPHICAL OBJECTS"
XThe objects in \fIfig\fP are divided into \fBprimitive objects\fP and
X\fBcompound object\fP. The primitive objects are: \fIARC\fP, \fICIRCLE\fP,
X\fICLOSED SPLINE\fP, \fIELLIPSE\fP, \fIPOLYLINE\fP, \fIPOLYGON\fP,
X\fISPLINE\fP, and \fITEXT\fP.  A primitive can be moved, rotated,
Xflipped, copied or erased.
XA compound object is composed of primitive objects. The primitive objects
Xthat constitute a compound can not be individually modified, but they can
Xbe manipulated as an entity; a compound can be moved, rotated, flipped,
Xcopied or erased.  An extra function that can be applied to a compound
Xobject is \fBscaling\fP, which is not available for primitive objects.
X.SH "DISPLAY WINDOWS"
XThree windows comprise the display area of \fIfig\fP: the 
Xpanel window the message window, and the canvas window. 
XThe message window always appears below the others;
Xit is the area in which messages are sent and received. from the
XThe menu window can be placed to the left or right of the
Xthe canvas window (default: left).
X.SH "POP-UP MENU"
XThe pop-up menu appears when the right mouse button is pressed with the
Xcursor positioned within the canvas window.
XPositioning the cursor over the desired menu entry and releasing the
Xbutton selects a menu entry.
X.PP
XThere are a number of file accessing functions in the pop-up menu.
XMost of the time when one of these functions is selected, the user
Xwill be asked for a file name.  If the specified file can be located
Xand the access permission are granted, \fIfig\fP will carry out
Xthe function.  However in case things go wrong, \fIfig\fP will
Xabort the function and printed the causes on the message window.
X.TP
X.I Undo
XUndo the last object creation or modification.
X.TP
X.I Redisplay
XRedraw the canvas.
X.TP
X.I Remove all
XRemove all objects on the canvas window (can be undone).
X.TP
X.I Edit file ...
XThe current contents of the canvas are cleared and objects
Xare read from the specified file.
XThe user will be asked for a file name.
XThis file will become the current file.
X.TP
X.I Save
XSave the current contents of the canvas in the current file.
XIf no file is being edited, the user will be asked for a file
Xname as in the "Save in ..." function.
X.TP
X.I Read file ...
XRead objects from the specified file and merge them with objects already
Xshown on the canvas.
X(The user will be asked for a file name.)
X.TP
X.I Save as ...
XSave objects on the screen into a file specified by the user.
X(The user will be asked for a file name.)
X.TP
X.I Status
XShow the name of the current file and directory.
X.TP
X.I Change Directory
XChange the working directory.  Any file name without a full path name
Xwill employ the current working directory.
X.TP
X.I Save & Exit
XSave the objects in the current file and exit from \fIfig\fP.
XIf there is no current file, the user will be asked for a file name.
XNo confirmation will be asked.
X.TP
X.I Quit
XExit from \fIfig\fP, discarding all objects. The user will be asked to 
Xconfirm the action, by clicking the left button.
X.TP
X.I Save as BITMAP ...
XCreate a bitmap picture of the drawings for use with other tools (for example,
Xfor use as an icon).  The smallest rectangular area of pixels
Xthat encompasses the figure is written to the named file 
X(the user will be asked for a file name) from
Xtop row to bottom and left to right (in Sun raster format).
XOnly \fITEXT\fP objects that are parts of compound objects will be
Xtreated as parts of the picture; other texts are saved as objects in
X\fIfig\fP format following the bitmap data.
XThe coordinates of these text objects can be used
Xto identify locations on the bitmap.
X.SH "MENU WINDOW MANIPULATION FUNCTIONS"
XIcons in the menu window represent object manipulation functions,
Xmodes and other drawing or modification aids.
XManipulation functions are selected by positioning the cursor over it and
Xclicking the left mouse button.  The selected icon is highlighted, and
Xa message describing its function appears in the message window.
X.PP
XThe left and middle buttons are used to creat and modify objects in the canvas
Xwindow.  Most actions start with clicking of the left button
Xand end with clicking of the right button.
XThere is no need to hold down a button while positioning
Xthe cursor.
X.SH "MENU WINDOW COMMAND DESCRIPTIONS"
XEntries in the panel window can be classified into two categories:
Xobject creation/modification/removal commands (only one of which may be active
Xat any one time), and drawing aids (which act as toggle switches).
XThere are two ways for drawing circles, two for ellipses, two for splines
Xand two for closed splines.
XThere are two basic splines.  One is the interpolated spline
Xin which the spline pass thorough the entered points (knots).
XThe other is the normal spline in which on control points are
Xpassed by the spline (except for the two end points in the open spline).
X.SH "OBJECT CREATION/MODIFICATION/REMOVAL"
XMultiple commands are grouped thematically in the following
Xdescriptions (which is listed alphabetically).
X.TP
X.I ADD/DELETE ARROWS
XAdd or delete arrow heads for \fIPOLYLINE\fP, \fIPOLYGON\fP, \fISPLINE\fP
Xor \fICLOSED SPLINE\fP objects (points of a \fIBOX\fP can not be added or
Xdeleted).
X.TP
X.I ADD/DELETE POINTS
XAdd or delete points for \fIPOLYLINE\fP, \fIPOLYGON\fP, \fISPLINE\fP
Xor \fICLOSED SPLINE\fP objects (points of a \fIBOX\fP can not be added
Xor deleted).
X.TP
X.I ARC
XCreate an arc.  Specify three points using the left button.
X.TP
X.I BOX
XCreate rectangular boxes.  Start with the left button and terminate with
Xthe right button.
X.TP
X.I BREAK COMPOUND
XBreak  a compound object to allow manipulation of its component parts.
XClick the left button on the bounding box of
Xthe compound object.
X.TP
X.I CIRCLE 
XCreate circles by specifying their radii or diameters.
XClick the left button on the canvas window, move the cursor until the
Xdesired radius or diameter is reached, then click the middle button to
Xterminate. The circle will be drawn after the pressing of the middle button.
X.TP
X.I CLOSED INTERPOLATED SPLINE
XCreate closed or periodic splines.  The function is similar
Xto \fIPOLYGON\fP except that a closed interpolated spline is drawn.
XThe spline will pass through the points (knots).
X.TP
X.I CLOSED SPLINE
XCreate closed or periodic spline objects.
XThe function is similar to \fIPOLYGON\fP
Xexcept that a closed spline will be drawn instead of polygon.
XThe entered points are just control points; i.e., the spline will
Xnot pass any of these points.
X.TP
X.I COPY
XCopy object.  Click the left button over part of the object to be
Xcopied (for \fICIRCLE\fP and \fIELLIPSE\fP
Xobjects, position on their circumferences).  Drag the object to the desired
Xposition and click the middle button.
XThis function as well as the following three functions 
X(\fIMOVE\fP, \fIMOVE POINT\fP, \fIREMOVE\fP)
Xwill cause point markers (manipulation aids) to be shown on the canvas window.
XThere are no markers for \fICIRCLE\fP or \fIELLIPSE\fP objects.
X.TP
X.I ELLIPSE
XCreate ellipses using the same procedure as for the drawing of circles.
X.TP
X.I GLUE
XGlue the primitive objects within a bounding box into a compound object
X(the bounding box itself is not part of the figure; 
Xit is a visual aid for manipulating the compound). 
X.TP
X.I INTERPOLATED SPLINE
XCreate (cubic spline) spline objects.
XEnter control vectors in the same way as for creation of a
X\fIPOLYLINE\fP object.
XAt least three points (two control vectors) must be entered.
XThe spline will pass through the entered points.
X.TP
X.I MOVE
XMove objects in the same way as in \fICOPY\fP.
X.TP
X.I MOVE POINT
XModify the position of points of \fIPOLYLINE, \fIBOX\fP, \fIPOLYGON\fP,
X\fIELLIPSE\fP, \fIARC\fP and \fISPLINE\fP
Xobjects.  Click the left button over the desired point, reposition the point,
Xand click the middle button.  Note that \fIBOX\fP and \fIPOLYGON\fP 
Xobjects are internally stored as \fIPOLYLINE\fP
Xobjects, and therefore moving certain points may open these objects.
X.TP
X.I POLYGON
XSame as \fIPOLYLINE\fP
Xexcept that a line segment is drawn connecting the first and last
Xpoints entered.
X.TP
X.I POLYLINE
XCreate polylines (line segments connecting a sequence of points).
XEnter points by clicking the left button at the desired positions on the
Xcanvas window.  Click the middle button to terminate.
X.TP
X.I REMOVE
XRemove (or delete) objects.
X.TP
X.I SCALE COMPOUND
XOnly compound objects can be scaled.  Click the left button
Xon a corner of the bounding box, stretch the
Xbounding box to the desired size, and click the middle button.
X.TP
X.I SPLINE
XCreate (quadratic spline) spline objects.
XEnter control vectors in the same way as for creation of a
X\fIPOLYLINE\fP object.
XAt least three points (two control vectors) must be entered.
XThe spline will pass only the two end points.
X.TP
X.I TEXT
XCreate text strings. Click the left button at the desired position on
Xthe canvas window, then enter text from the keyboard.
XTerminate by clicking the middle button or typing the return key.
X.TP
X.I TURN
XTurn \fIPOLYGON\fP into a \fICLOSED INTERPOLATED SPLINE\fP object, or
Xturn \fIPOLYLINE\fP into a \fIINTERPOLATED SPLINE\fP object.
X.SH "DRAWING AIDS"
XDrawing aids act as toggle switches. More than one can be selected at a time
X(except for \fIGRID\fP and the line drawing modes).
X.TP
X.I AUTO FORWARD/BACKWARD ARROW
XAutomatically add forward/backward arrow heads to \fIPOLYLINE\fP, \fISPLINE\fP
Xor \fIARC\fP objects.
X.TP
X.I FLIP
XInvert the object (middle button) or produce a mirror-image copy of an
Xobject (left button). Point to part of the object ("the handle"), click
Xthe appropriate button.
X.TP
X.I GRID
XDisplay either the quarter- or half-inch grids (left button).
X.TP
X.I MAGNET
XRound points to the nearest 1/16 of an inch.
XThis affects every function, and is provided as an alignment aid.
X.TP
X.I UNRESTRICTED
XAllow lines to be drawn with any slope.
X.TP
X.I MANHATTAN
XEnforce drawing of lines in the horizontal and vertical direction only.
XBoth \fIMANHATTAN\fP and \fIMOUNTAIN\fP can be turned on simultaneously. The
Xcreations of \fIPOLYGON\fP, \fIPOLYLINE\fP and \fISPLINE\fP objects are
Xaffected by these two modes.
X.TP
X.I MOUNTAIN
XEnforce drawing of only diagonal lines.  Both \fIMANHATTAN\fP
Xand \fIMOUNTAIN\fP can be turned on simultaneously. The creations
Xof \fIPOLYGON\fP, \fIPOLYLINE\fP and \fISPLINE\fP objects are affected
Xby these two modes.
X.TP
X.I MANHATTAN MOUNTAIN
XAllow lines to be drawn at any slope allowed when in
XMOUNTIAIN or MANHATTAN modes.
X.TP
X.I LATEX LINE
XAllow lines to be drawn only at slopes which can be handled by LaTeX picture
Xenvironment lines: slope = x/y, where x,y are integers in the range [-6,6].
X.TP
X.I LATEX VECTOR
XAllow lines to be drawn only at slopes which can be handled by LaTeX picture
Xenvironment vectors: slope = x/y, where x,y are integers in the range [-4,4].
X.TP
X.I ROTATE
XRotate the object (middle button) or copy (left button) +90 degrees.
X.TP
X.I SOLID/DASHED LINE STYLE
XToggle between solid and dashed line styles. The dash length
Xis fixed at 0.05 inch.
X.SH BUGS
XText strings will appear differently on hard copy, because the display
Xfonts are fixed-width fonts while the fonts used by \fIpic\fP(1) are
Xvariable-width fonts.
X.PP
XA double quote in a text string should be preceded by a back slash if the
Xit is to be printed through 
X.IR pic (1).
X.PP
XObjects that extend beyond the canvas window may cause image shrinkage in
Xhard copy printed by
X.IR pic (1),
Xsince it will try to fit every object onto a single 8.5" x 11" page.
X.PP
XEllipses which are too narrow may cause \fIfig\fP to loop forever.
X.PP
XObjects which are created while one of the 
X.I grids
Xis on may appear ragged. This can be corrected by selecting \fIRedisplay\fP
Xfrom the pop-up menu.
X.PP
XThe X11 cursors are not the original ones but chosen from
XX11's cursor font.
X.PP
XRighthand panel is not supported. It should be possible to do
Xthat but Ken was too lazy.
X.SH "SEE ALSO"
XBrian W. Kernighan
X.I "PIC - A Graphics Language for Typesetting User Manual"
X.br
Xcol(1) ditroff(1), eqn(1), f2p(1), f2ps(1), man(7), me(7), ms(7),
Xpic(1), tbl(1), troff(1),
X.SH ACKNOWLEDGEMENT
XMany thanks goes to Professor Donald E. Fussell who inspired the
Xcreation of this tool.
X.SH AUTHOR
XSupoj Sutanthavibul
X.br
XUniversity of Texas at Austin 
X.br
X(supoj@sally.UTEXAS.EDU) 
X.br
XManual page modified by R. P. C. Rodgers, UCSF School of Pharmacy,
XSan Francisco, CA 94118 
X.br
XFrank Schmuck of Cornell contributed the LaTeX line drawing modes.
END_OF_fig.1
if test 13718 -ne `wc -c <fig.1`; then
    echo shar: \"fig.1\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f undo.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"undo.c\"
else
echo shar: Extracting \"undo.c\" \(13275 characters\)
sed "s/^X//" >undo.c <<'END_OF_undo.c'
X/* 
X *	FIG : Facility for Interactive Generation of figures
X *
X *	Copyright (c) 1985, 1988 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
X *	January 1985.
X *	1st revision : August 1985.
X *	2nd revision : March 1988.
X *
X *	%W%	%G%
X*/
X#include "fig.h"
X#include "resources.h"
X#include "func.h"
X#include "object.h"
X#include "paintop.h"
X
Xextern int		pointmarker_shown, compoundbox_shown;
X
Xextern int		foreground_color, background_color;
Xextern int		last_action, last_object;
Xextern int		last_axis, last_rotateangle;
Xextern int		movedpoint_num;
Xextern int		fix_x, fix_y;
Xextern F_pos		last_position, new_position;
X
Xextern F_compound	objects;
Xextern F_compound	saved_objects;
Xextern F_compound	object_tails;
X
Xextern F_point		*left_point; 
Xextern F_point		*moved_point;
Xextern F_point		*deleted_point;
Xextern F_point		*added_point;
X
Xundo()
X{
X	switch(last_action) {
X	    case F_CREATE :
X		undo_create();
X		break;
X	    case F_REMOVE :
X		undo_remove();
X		break;
X	    case F_MOVE :
X		undo_move();
X		break;
X	    case F_MOVE_POINT :
X		undo_movepoint();
X		break;
X	    case F_FLIP :
X		undo_flip();
X		break;
X	    case F_ROTATE :
X		undo_rotate();
X		break;
X	    case F_GLUE :
X		undo_glue();
X		break;
X	    case F_BREAK :
X		undo_break();
X		break;
X	    case F_SCALE :
X		undo_scale();
X		break;
X	    case F_ADD_POINT :
X		undo_addpoint();
X		break;
X	    case F_DELETE_POINT :
X		undo_deletepoint();
X		break;
X	    default :
X		return;
X	    }	
X	}
X
Xundo_addpoint()
X{
X	if (last_object == O_POLYLINE)
X	    linepoint_deleting(saved_objects.lines);
X	else
X	    splinepoint_deleting(saved_objects.splines);
X	last_action = F_DELETE_POINT;
X	deleted_point = added_point;
X	}
X
Xundo_deletepoint()
X{
X	if (last_object == O_POLYLINE) 
X	    linepoint_adding(saved_objects.lines, deleted_point);
X	else
X	    splinepoint_adding(saved_objects.splines, deleted_point);
X	last_action = F_ADD_POINT;
X	added_point = deleted_point;
X	}
X
Xundo_break()
X{
X	if (compoundbox_shown)
X	    draw_compoundbox(saved_objects.compounds, INV_PAINT);
X	cut_objects(&objects, &object_tails);
X	insert_compound(&objects.compounds, saved_objects.compounds);
X	last_action = F_GLUE;
X	}
X
Xundo_glue()
X{
X	if (compoundbox_shown)
X	    draw_compoundbox(saved_objects.compounds, INV_PAINT);
X	delete_compound(&objects.compounds, saved_objects.compounds);
X	append_objects(&objects, saved_objects.compounds, &object_tails);
X	last_action = F_BREAK;
X	}
X
X/* 
XWhen a single object is created, it is inserted as the first object in
Xthe appropriate list in objects.  It is also placed in the appropriate
Xlist in saved_objects.
X
XHowever when a number of objects are created (usually by reading them
Xin from a file or undoing a remove-all action), they are appended to
Xthe lists in objects and also saved in saved_objects.  The pointers
Xin object_tails will be set to point to the last members of the lists
Xin objects prior to the appending.
X
XNote: The read operation will set the pointers in object_tails
Xwhile the remove-all operation will zero pointers in objects.
X*/
X
Xundo_create()
X{
X	switch(last_object) {
X	    case O_POLYLINE :
X		objects.lines = saved_objects.lines->next;
X		saved_objects.lines->next = NULL;
X		erase_lines(saved_objects.lines);
X		break;
X	    case O_ELLIPSE :
X		objects.ellipses = saved_objects.ellipses->next;
X		saved_objects.ellipses->next = NULL;
X		erase_ellipses(saved_objects.ellipses);
X		break;
X	    case O_TEXT :
X		objects.texts = saved_objects.texts->next;
X		saved_objects.texts->next = NULL;
X		erase_texts(saved_objects.texts);
X		break;
X	    case O_SPLINE :
X	        objects.splines = saved_objects.splines->next;
X	        saved_objects.splines->next = NULL;
X		erase_splines(saved_objects.splines);
X		break;
X	    case O_ARC :
X		objects.arcs = saved_objects.arcs->next;
X		saved_objects.arcs->next = NULL;
X		erase_arcs(saved_objects.arcs);
X		break;
X	    case O_COMPOUND :
X		objects.compounds = saved_objects.compounds->next;
X		saved_objects.compounds->next = NULL;
X		erase_compounds(saved_objects.compounds);
X		break;
X	    case O_ALL_OBJECT :
X		cut_objects(&objects, &object_tails);
X		redisplay_canvas();
X		break;
X	    }
X	last_action = F_REMOVE;
X	}
X
Xundo_remove()
X{
X	switch (last_object) {
X	    case O_POLYLINE :
X		draw_lines(saved_objects.lines);
X		insert_line(&objects.lines, saved_objects.lines);
X		break;
X	    case O_ELLIPSE :
X		draw_ellipses(saved_objects.ellipses);
X		insert_ellipse(&objects.ellipses, saved_objects.ellipses);
X		break;
X	    case O_TEXT :
X		draw_texts(saved_objects.texts);
X		insert_text(&objects.texts, saved_objects.texts);
X		break;
X	    case O_SPLINE :
X		draw_splines(saved_objects.splines);
X		insert_spline(&objects.splines, saved_objects.splines);
X		break;
X	    case O_ARC :
X		draw_arcs(saved_objects.arcs);
X		insert_arc(&objects.arcs, saved_objects.arcs);
X		break;
X	    case O_COMPOUND :
X		draw_compounds(saved_objects.compounds);
X		insert_compound(&objects.compounds, saved_objects.compounds);
X		break;
X	    case O_ALL_OBJECT :
X		append_objects(&objects, &saved_objects, &object_tails);
X		redisplay_canvas();
X		break;
X	    }
X	last_action = F_CREATE;
X	}
X
Xundo_flip()
X{
X	switch (last_object) {
X	    case O_POLYLINE :
X		if (pointmarker_shown)
X		    toggle_linepointmarker(saved_objects.lines);
X		draw_line(saved_objects.lines, ERASE);
X		flip_line(saved_objects.lines, 
X			last_position.x, last_position.y,
X			last_axis);
X		draw_line(saved_objects.lines, PAINT);
X		if (pointmarker_shown)
X		    toggle_linepointmarker(saved_objects.lines);
X		break;
X	    case O_ELLIPSE :
X		if (pointmarker_shown)
X		    toggle_ellipsepointmarker(saved_objects.ellipses);
X		pw_batch_on(canvas_pixwin);
X		draw_ellipse(saved_objects.ellipses, background_color);
X		flip_ellipse(saved_objects.ellipses, 
X			last_position.x, last_position.y,
X			last_axis);
X		draw_ellipse(saved_objects.ellipses, foreground_color);
X		pw_batch_off(canvas_pixwin);
X		if (pointmarker_shown)
X		    toggle_ellipsepointmarker(saved_objects.ellipses);
X		break;
X	    case O_SPLINE :
X		if (pointmarker_shown)
X		    toggle_splinepointmarker(saved_objects.splines);
X		pw_batch_on(canvas_pixwin);
X		draw_spline(saved_objects.splines, ERASE);
X		flip_spline(saved_objects.splines,
X			last_position.x, last_position.y,
X			last_axis);
X		draw_spline(saved_objects.splines, PAINT);
X		pw_batch_off(canvas_pixwin);
X		if (pointmarker_shown)
X		    toggle_splinepointmarker(saved_objects.splines);
X		break;
X	    case O_ARC :
X		if (pointmarker_shown)
X		    toggle_arcpointmarker(saved_objects.arcs);
X		pw_batch_on(canvas_pixwin);
X		draw_arc(saved_objects.arcs, background_color);
X		flip_arc(saved_objects.arcs, 
X			last_position.x, last_position.y,
X			last_axis);
X		draw_arc(saved_objects.arcs, foreground_color);
X		pw_batch_off(canvas_pixwin);
X		if (pointmarker_shown)
X		    toggle_arcpointmarker(saved_objects.arcs);
X		break;
X	    case O_COMPOUND :
X		if (compoundbox_shown) 
X		    draw_compoundbox(saved_objects.compounds, INV_PAINT);
X		erase_compound(saved_objects.compounds);
X		flip_compound(saved_objects.compounds, 
X			last_position.x, last_position.y,
X			last_axis);
X		draw_compound(saved_objects.compounds);
X		if (compoundbox_shown) 
X		    draw_compoundbox(saved_objects.compounds, INV_PAINT);
X		break;
X	    }
X	}
X
Xundo_move()
X{
X	int	dx, dy;
X
X	dx = last_position.x - new_position.x;
X	dy = last_position.y - new_position.y;
X	switch (last_object) {
X	    case O_POLYLINE :
X		if (pointmarker_shown)
X		    toggle_linepointmarker(saved_objects.lines);
X		draw_line(saved_objects.lines, ERASE);
X		translate_line(saved_objects.lines, dx, dy);
X		draw_line(saved_objects.lines, PAINT);
X		if (pointmarker_shown)
X		    toggle_linepointmarker(saved_objects.lines);
X		break;
X	    case O_ELLIPSE :
X		if (pointmarker_shown)
X		    toggle_ellipsepointmarker(saved_objects.ellipses);
X		pw_batch_on(canvas_pixwin);
X		draw_ellipse(saved_objects.ellipses, background_color);
X		translate_ellipse(saved_objects.ellipses, dx, dy);
X		draw_ellipse(saved_objects.ellipses, foreground_color);
X		pw_batch_off(canvas_pixwin);
X		if (pointmarker_shown)
X		    toggle_ellipsepointmarker(saved_objects.ellipses);
X		break;
X	    case O_TEXT :
X		draw_text(saved_objects.texts, INV_PAINT);
X		translate_text(saved_objects.texts, dx, dy);
X		draw_text(saved_objects.texts, PAINT);
X		break;
X	    case O_SPLINE :
X		if (pointmarker_shown)
X		    toggle_splinepointmarker(saved_objects.splines);
X		pw_batch_on(canvas_pixwin);
X		draw_spline(saved_objects.splines, ERASE);
X		translate_spline(saved_objects.splines, dx, dy);
X		draw_spline(saved_objects.splines, PAINT);
X		pw_batch_off(canvas_pixwin);
X		if (pointmarker_shown)
X		    toggle_splinepointmarker(saved_objects.splines);
X		break;
X	    case O_ARC :
X		if (pointmarker_shown)
X		    toggle_arcpointmarker(saved_objects.arcs);
X		pw_batch_on(canvas_pixwin);
X		draw_arc(saved_objects.arcs, background_color);
X		translate_arc(saved_objects.arcs, dx, dy);
X		draw_arc(saved_objects.arcs, foreground_color);
X		pw_batch_off(canvas_pixwin);
X		if (pointmarker_shown)
X		    toggle_arcpointmarker(saved_objects.arcs);
X		break;
X	    case O_COMPOUND :
X		if (compoundbox_shown) 
X		    draw_compoundbox(saved_objects.compounds, INV_PAINT);
X		erase_compound(saved_objects.compounds);
X		translate_compound(saved_objects.compounds, dx, dy);
X		draw_compound(saved_objects.compounds);
X		if (compoundbox_shown) 
X		    draw_compoundbox(saved_objects.compounds, INV_PAINT);
X		break;
X	    }
X	swap_newp_lastp();
X	}
X
Xundo_movepoint()
X{
X	switch (last_object) {
X	    case O_POLYLINE :
X		relocate_linepoint(saved_objects.lines, 
X			last_position.x, last_position.y, 
X			saved_objects.lines->points->x,
X			saved_objects.lines->points->y, 
X			moved_point, left_point);
X		break;
X	    case O_SPLINE :
X		relocate_splinepoint(saved_objects.splines, last_position.x,
X			last_position.y, moved_point);
X		break;
X	    case O_ARC :
X		relocate_arcpoint(saved_objects.arcs, last_position.x, 
X			last_position.y, movedpoint_num);
X		break;
X	    case O_ELLIPSE :
X		relocate_ellipsepoint(saved_objects.ellipses, last_position.x,
X			last_position.y, movedpoint_num);
X		break;
X	    }
X	swap_newp_lastp();
X	}
X
Xundo_rotate()
X{
X	switch (last_object) {
X	    case O_POLYLINE :
X		if (pointmarker_shown)
X		    toggle_linepointmarker(saved_objects.lines);
X		draw_line(saved_objects.lines, ERASE);
X		if (last_rotateangle == 90) last_rotateangle = 270;
X		else last_rotateangle = 90;
X		rotate_line(saved_objects.lines, 
X			last_position.x, last_position.y,
X			last_rotateangle);
X		draw_line(saved_objects.lines, PAINT);
X		if (pointmarker_shown)
X		    toggle_linepointmarker(saved_objects.lines);
X		break;
X	    case O_ELLIPSE :
X		if (pointmarker_shown)
X		    toggle_ellipsepointmarker(saved_objects.ellipses);
X		pw_batch_on(canvas_pixwin);
X		draw_ellipse(saved_objects.ellipses, background_color);
X		if (last_rotateangle == 90) last_rotateangle = 270;
X		else last_rotateangle = 90;
X		rotate_ellipse(saved_objects.ellipses, 
X			last_position.x, last_position.y,
X			last_rotateangle);
X		draw_ellipse(saved_objects.ellipses, foreground_color);
X		pw_batch_off(canvas_pixwin);
X		if (pointmarker_shown)
X		    toggle_ellipsepointmarker(saved_objects.ellipses);
X		break;
X	    case O_SPLINE :
X		if (pointmarker_shown)
X		    toggle_splinepointmarker(saved_objects.splines);
X		pw_batch_on(canvas_pixwin);
X		draw_spline(saved_objects.splines, ERASE);
X		if (last_rotateangle == 90) last_rotateangle = 270;
X		else last_rotateangle = 90;
X		rotate_spline(saved_objects.splines,
X			last_position.x, last_position.y,
X			last_rotateangle);
X		draw_spline(saved_objects.splines, PAINT);
X		pw_batch_off(canvas_pixwin);
X		if (pointmarker_shown)
X		    toggle_splinepointmarker(saved_objects.splines);
X		break;
X	    case O_ARC :
X		if (pointmarker_shown)
X		    toggle_arcpointmarker(saved_objects.arcs);
X		pw_batch_on(canvas_pixwin);
X		draw_arc(saved_objects.arcs, background_color);
X		if (last_rotateangle == 90) last_rotateangle = 270;
X		else last_rotateangle = 90;
X		rotate_arc(saved_objects.arcs, 
X			last_position.x, last_position.y,
X			last_rotateangle);
X		draw_arc(saved_objects.arcs, foreground_color);
X		pw_batch_off(canvas_pixwin);
X		if (pointmarker_shown)
X		    toggle_arcpointmarker(saved_objects.arcs);
X		break;
X	    case O_COMPOUND :
X		if (compoundbox_shown)
X		    draw_compoundbox(saved_objects.compounds, INV_PAINT);
X		erase_compound(saved_objects.compounds);
X		if (last_rotateangle == 90) last_rotateangle = 270;
X		else last_rotateangle = 90;
X		rotate_compound(saved_objects.compounds, 
X			last_position.x, last_position.y,
X			last_rotateangle);
X		draw_compound(saved_objects.compounds);
X		if (compoundbox_shown)
X		    draw_compoundbox(saved_objects.compounds, INV_PAINT);
X		break;
X	    }
X	}
X
Xundo_scale()
X{
X	float	scalex, scaley;
X
X	if (compoundbox_shown)
X	    draw_compoundbox(saved_objects.compounds, INV_PAINT);
X	erase_compound(saved_objects.compounds);
X	scalex = ((float)(last_position.x-fix_x)) / (new_position.x-fix_x);
X	scaley = ((float)(last_position.y-fix_y)) / (new_position.y-fix_y);
X	scale_compound(saved_objects.compounds, scalex, scaley, fix_x, fix_y);
X	draw_compound(saved_objects.compounds);
X	if (compoundbox_shown) draw_compoundbox(saved_objects.compounds, INV_PAINT);
X	swap_newp_lastp();
X	}
X
Xswap_newp_lastp()
X{
X	int	t;  /*  swap new_position and last_position  */
X
X	t = new_position.x; 
X	new_position.x = last_position.x;
X	last_position.x = t;
X	t = new_position.y; 
X	new_position.y = last_position.y;
X	last_position.y = t;
X	}
END_OF_undo.c
if test 13275 -ne `wc -c <undo.c`; then
    echo shar: \"undo.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 7 \(of 11\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 11 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
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330