a08e4fa32b4e78ebe0b800b1cab318e5a8a2a12a
[unix-history] / usr / src / local / ditroff / ditroff.old.okeeffe / gremlin.aed / gremlin / short.c
\f
/* short.c -
*
* Copyright -C- 1982 Barry S. Roitblat
*
*
* This file contains routines to implement the short commands
* of the gremlin picture editor.
*
*/
#include "gremlin.h"
#include "grem2.h"
#include <signal.h>
#include <sgtty.h>
/* imports from graphics files */
extern GRVector(), GRPutText();
extern GRCurve();
extern GRClear();
extern int GRArc();
extern charxsize, charysize;
/* imports from display.c */
extern DISScreenAdd(), DISScreenErase();
extern DISDisplaySet(), DISEraseSet(), DISClearSetDisplay();
/* imports from database files */
extern ELT *DBInit(), *DBCreateElt();
extern DBDelete(), DBGravitate(), DBClearElt();
extern ELT *DBCopy();
extern DBXform(), DBBounded();
extern DBAddSet(), DBClearSet();
extern POINT *PTInit(), *PTMakePoint();
extern PTDeletePoint();
/* imports from long.c */
extern LGIncludeSet();
/* imports from menu.c */
extern MNHighLt(), MNUnHighLt();
extern HiMen[], HiFont[], HiBrush[], HiMode[];
int adj[4] = { 0, 0, 1, 2 };
/* imports from textio.c */
extern TxMsgOK(), TxPutString(), TxGetLine(), TxRedisplay(), TxPutMsg();
extern char TxGetChar();
extern TXFIELD TAlign, TAdjust, TBrush, TFont, TGravity, TCSize;
extern TXFIELD TEdit, TJustmode;
/* imports from c */
extern char *malloc();
extern char *sprintf();
/* imports from main.c */
extern globinit(); /* global initialization routine */
extern ELT *PICTURE; /* current PICTURE database */
extern ELT *cset; /* current set database */
extern CBRUSH, CSIZE, CFONT; /* current brush, size, font */
extern CJUST; /* text justification mode */
extern Gridon; /* grid mode flag */
extern Orientation; /* orientation of workspace */
extern Alignment; /* point alignment indicator */
extern float PX, PY; /* cursor coordinates */
extern float Lastx, Lasty; /* previous cursor coordinates */
extern SEQ; /* point sequence number */
extern char *Editfile; /* current edit file */
extern POINT *POINTLIST; /* accumulated point list */
extern Adjustment; /* point adjustment mode */
extern GravityOn; /* gravity mode flag */
extern Consume; /* point clear flag */
extern CHANGED; /* PICTURE changed flag */
extern ELT *MEN[]; /* pointers for user symbols */
extern POINT MENPOINT[]; /* pointers used fo user symbols */
extern cmdbuf[]; /* line buffer for commands */
extern ELT arhead; /* arrow head template */
extern char *textpos[], *dispmode[];/* text positioning modes */
extern int textmode[]; /* text positioning */
\f
extern SHUpdate(), SHDrawArc(), SHDrawCurve(), SHCopy(), SHRedis(),
SHDefineSet(), SHErase(), SHSetArea(), SHGravity(),
SHGrid(), SHRotate(), SHScale(), SHTranslate(), SHShellEsc(),
SHDrawVector(), SHMAdjust(), SHBox(), SHArrow(),
SHSave1(), SHSave2(), SHSave3(), SHSave4();
/* The following two arrays define the short commands and the routines
* that process them.
*/
static char shcmds[] = { '\14', '!', '1', '2', '3', '4', 'a', 'b',
'c', 'd', 'e', 'f', 'g', 'l', 'q', 'r',
's', 't', 'v', 'w', 'x', 'z', '\0'};
static (*(shrtns[]))() = {
SHUpdate, /* redraw screen */
SHShellEsc, /* shell escape */
SHSave1, /* save user symbol */
SHSave2, /* save user symbol */
SHSave3, /* save user symbol */
SHSave4, /* save user symbol */
SHDrawArc, /* draw arc */
SHDrawCurve, /* draw curve */
SHCopy, /* copy current set */
SHDefineSet, /* define current set */
SHErase, /* erase elements */
SHSetArea, /* select area for current set */
SHGravity, /* gravity */
SHRedis, /* text screen redisplay */
SHGrid, /* toggle grid display */
SHRotate, /* rotate current set */
SHScale, /* scale current set */
SHTranslate, /* translate current set */
SHDrawVector, /* draw vectors */
SHArrow, /* arrowhead */
SHBox, /* rectangle from two points */
SHMAdjust}; /* manhattan adjust */
\f
int
SHLookup(c, table)
char c; /* Pointer to a char to be looked up */
char table[]; /* Pointer to an array of characters
* which are the valid commands. The array
* must be sorted by ascii value.
*/
/*---------------------------------------------------------
* SHLookup searches a table of characters to find one that matches a
* the given character.
*
* Results: If c is a valid command character, its index is
* returned, otherwise, if c is the null command, -2 is returned
* else -1 is returned.
*
* Side Effects: None.
*
* (Modified from software written by John Ousterhout for the caesar
* program)
*---------------------------------------------------------
*/
{
int index;
if ((c == ' ') || (c == '\0')) return(-2);
for (index=0; table[index] != '\0'; index++)
{
if (table[index] == c) return(index);
if (table[index] > c) return(-1);
}
return(-1);
} /* end SHLookup */
\f
SHCommand(command)
char *command;
/*---------------------------------------------------------
* This routine reads in, looks up, and executes a long command.
*
* Results: None.
*
* Side Effects:
* Depends on the command that is invoked.
*---------------------------------------------------------
*/
{
int index;
index = SHLookup(*command, shcmds);
if (index == -2) return;
if (index >= 0)
{
(*(shrtns[index]))();
}
else
{
error("no such command");
}
} /* end SHCommand */
\f
static char nopnt[18] = "not enough points";
static char noset[15] = "no current set";
SHDrawVector()
/*
* This routine creates and displays a VECTOR element from the
* points previously specified.
*/
{
ELT *e1;
POINT *plist, *p1, *p2;
char *txt;
if (SEQ < 2) /* not enough points */
{
error(nopnt);
return;
}
DBClearSet(); /* Clear current set in preparation */
DISClearSetDisplay(); /* for making this the new one */
GRsetwmask(linemask | setmask);
plist = PTInit();
p1 = POINTLIST;
(void) PTMakePoint(p1->x, p1->y, &plist);
p2 = PTNextPoint(p1);
while ( !Nullpoint(p2) )
{
(void) PTMakePoint(p2->x, p2->y, &plist);
GRVector(p1, p2, CBRUSH);
p1 = p2;
p2 = PTNextPoint(p1);
} /* end while */;
txt = malloc(1);
*txt = '\0';
e1 = DBCreateElt(VECTOR, plist, CBRUSH, 0, txt, &PICTURE);
DBAddSet(e1);
CHANGED = TRUE;
} /* end SHDrawVector */
#define twoPi 6.2832
SHDrawArc()
/*
* This routine creates and displays an ARC element based on the
* points previously defined. If 3 or more points are defined, the
* extent of the arc is calculated as the angle formed by the
* respective lines through the second and third points and the first
* point. If only 2 points are specified, a full circle is drawn.
*/
{
ELT *e1;
POINT *plist, *p1, *p2;
char *txt;
double a1, a2, angle, radius;
int stat;
if (SEQ < 2) /* not enough points */
{
error(nopnt);
return;
}
plist = PTInit();
p1 = POINTLIST;
p2 = PTNextPoint(p1);
radius = sqrt( pow((p2->x - p1->x), 2.0)
+ pow((p2->y - p1->y), 2.0));
if (SEQ == 2) /* draw full circle */
{
angle = 0;
/* Add extra positioning points */
(void) PTMakePoint(p1->x, p1->y, &plist);
(void) PTMakePoint(p2->x, p2->y, &plist);
(void) PTMakePoint(p1->x, p1->y + radius, &plist);
(void) PTMakePoint(p1->x, p1->y - radius, &plist);
(void) PTMakePoint(p1->x + radius, p1->y, &plist);
(void) PTMakePoint(p1->x - radius, p1->y, &plist);
} /* end if */
else
{
(void) PTMakePoint(POINTLIST->x, POINTLIST->y, &plist);
p1 = PTNextPoint(POINTLIST);
(void) PTMakePoint(p1->x, p1->y, &plist);
p2 = PTNextPoint(p1);
a1 = atan2((p1->x - POINTLIST->x), (p1->y - POINTLIST->y));
a2 = atan2((p2->x - POINTLIST->x), (p2->y - POINTLIST->y));
angle = a1 - a2;
if (angle < 0.0) angle += twoPi;
/* Set second point to lie on arc */
(void) PTMakePoint((radius * sin(a2) + POINTLIST->x),
(radius * cos(a2) + POINTLIST->y),
&plist);
angle *= 360.0/twoPi; /* convert to degrees */
};
p1 = PTNextPoint(POINTLIST);
DBClearSet(); /* Clear current set, this element becomes */
DISClearSetDisplay(); /* the new current set */
GRsetwmask(linemask | setmask);
stat = GRArc(POINTLIST, p1, angle, CBRUSH);
if (stat > -1)
{
txt = malloc(1);
*txt = '\0';
e1 = DBCreateElt(ARC, plist, CBRUSH, (int) (angle + 0.5),
txt, &PICTURE);
DBAddSet(e1);
CHANGED = TRUE;
}
} /* end SHDrawARc */
\f
SHDrawCurve()
/*
* This routine creates and displays a curve using points previously
* defined. This is dependent on DISCurve which is not yet implemented.
*/
{
ELT *e1;
char *txt;
POINT *p1, *p2, *plist;
int stat;
stat = 0;
if (SEQ < 2) /* not enough points */
{
error("need at least 2 points");
return;
}
plist = PTInit();
p1 = POINTLIST;
(void) PTMakePoint(p1->x, p1->y, &plist);
p2 = PTNextPoint(p1);
while ( !Nullpoint(p2) )
{
(void) PTMakePoint(p2->x, p2->y, &plist);
p1 = p2;
p2 = PTNextPoint(p1);
} /* end while */;
DBClearSet(); /* Clear current set, this element */
DISClearSetDisplay(); /* the new current set */
GRsetwmask(linemask | setmask);
stat = GRCurve(plist, CBRUSH);
if (stat != 0) /* bad knots */
{
error("too many consecutive knots at same place");
return;
}
txt = malloc(1);
*txt = '\0';
e1 = DBCreateElt(CURVE, plist, CBRUSH, 0, txt, &PICTURE);
DBAddSet(e1);
CHANGED = TRUE;
} /* end SHDrawCurve */
SHErase()
/*
* This routine erases selected elements from the screen and deletes
* them from the picture database.
*/
{
ELT *e1;
while ( !DBNullelt(cset) ) /* delete elements in current set */
{
DISScreenErase(cset, (linemask | setmask));
e1 = DBNextofSet(cset);
DBDelete(cset, &PICTURE);
cset = e1;
};
CHANGED = TRUE;
} /* end SHErase */
\f
SHGravity()
/*
* This routine toggles the gravity mode.
*/
{
if (GravityOn)
{
MNUnHighLt(HiMode[3]);
GravityOn = FALSE;
TxPutString(&TGravity, "OFF");
}
else
{
MNHighLt(HiMode[3], hicolor);
GravityOn = TRUE;
TxPutString(&TGravity, " ON");
}
Consume = FALSE;
} /* End GravityOn */
SHGrid()
/*
* This routine toggles the display of the grid
*/
{
if (Gridon)
{
Gridon = FALSE;
GRBlankGrid();
}
else
{
Gridon = TRUE;
GRDisplayGrid();
}
Consume = FALSE;
} /* end SHGrid */
\f
SHMAdjust()
/*
* Manhattan Adjust -
* This routine toggles the adjustment mode.
*/
{
if (Adjustment == MAN)
{
MNUnHighLt(HiMode[adj[MAN]]);
Adjustment = NOADJ;
TxPutString(&TAdjust, "NO ADJUSTMENT");
}
else
{
MNUnHighLt(HiMode[adj[Adjustment]]);
MNHighLt(HiMode[adj[MAN]], hicolor);
Adjustment = MAN;
TxPutString(&TAdjust, " MANHATTAN ");
}
Consume = FALSE;
}
\f
SHDefineSet()
/*
* This routine defines the current set based upon previously
* defined points to select elements. The action is performed by
* clearing the current set and calling LGIncludeSet.
*/
{
DBClearSet();
DISClearSetDisplay();
LGIncludeSet("");
} /* end SHDefineSet */
SHSetArea()
/*
* This routine defines the current set by selecting all elements
* bounded by a rectangle whose diagonal is defined by specifed points.
*/
{
ELT *e1;
POINT *p1;
float x1, y1, x2, y2;
if (SEQ < 2)
{
error(nopnt);
return;
}
DBClearSet();
DISClearSetDisplay();
x1 = POINTLIST->x;
y1 = POINTLIST->y;
p1 = PTNextPoint(POINTLIST);
x2 = p1->x;
y2 = p1->y;
e1 = PICTURE;
while ( !DBNullelt(e1) )
{
if ( DBBounded(e1, x1, y1, x2, y2) )
{
DBAddSet(e1);
DISDisplaySet(e1);
} /* end if */
e1 = DBNextElt(e1);
} /* end while */
} /* end SHSetArea */
\f
SHTranslate()
/*
* This routine translates the elements in the current set as defined
* by points. The translation is accomplished by defining a transformation
* matrix and calling DBXform.
*/
{
ELT *e1;
POINT *p1;
float xmat[3][2];
if (SEQ < 2) /* not enough points */
{
error(nopnt);
return;
}
if (DBNullelt(cset))
{
error(noset);
return;
}
p1 = PTNextPoint(POINTLIST);
xmat[0][0] = xmat[1][1] = 1; /* set up translation matrix */
xmat[1][0] = xmat[0][1] = 0;
xmat[2][0] = p1->x - POINTLIST->x;
xmat[2][1] = p1->y - POINTLIST->y;
e1 = cset;
while ( !DBNullelt(e1) )
{
DISScreenErase(e1, (linemask | setmask));
TxMsgOK();
DBXform(e1, xmat, &PICTURE);
DISScreenAdd(e1, (linemask | setmask));
e1 = DBNextofSet(e1);
} /* end while */
CHANGED = TRUE;
} /* end SHTranslate */
\f
SHCopy()
/*
* This routine copies the elements in the current set as defined
* by points. To copy, the current set pointer is cleared so that new
* elements as added by DBCopy can be used to comprise the new current
* set. A pointer is maintained to the old current set which is traversed
* to determine the elements to be copied. This process continues for all
* points specified.
*
* NOTE: This assumes that the DBClearSet routine does not alter the
* pointers between elements in the set (which is currently true),
* and must be changed it this does not hold.
*/
{
ELT *e1, *e2;
POINT *p1, *p2;
float xmat[3][2];
if (SEQ < 2) /* not enough points */
{
error(nopnt);
return;
}
if (DBNullelt(cset))
{
error(noset);
return;
}
p1 = POINTLIST;
p2 = PTNextPoint(POINTLIST);
while ( !Nullpoint(p2) )
{
xmat[0][0] = xmat[1][1] = 1; /* set up translation matrix */
xmat[1][0] = xmat[0][1] = 0;
xmat[2][0] = p2->x - p1->x;
xmat[2][1] = p2->y - p1->y;
DISClearSetDisplay();
e1 = cset;
DBClearSet(); /* Dependent on Clearset preserving pointers */
while ( !DBNullelt(e1) )
{
e2 = DBCopy(e1, xmat, &PICTURE);
DBAddSet(e2);
DISScreenAdd(e2, (linemask | setmask));
e1 = DBNextofSet(e1);
} /* end while ! null elt */
p1 = p2;
p2 = PTNextPoint(p2);
} /* end while ! null point */
CHANGED = TRUE;
} /* end SHCopy */
\f
SHRotate()
/*
* This routine rotates the elements in the current set as defined
* by points. The rotation is accomplished by defining a transformation
* matrix and calling DBXform.
*/
{
ELT *e1;
POINT pos, *p1, *p2;
float xmat[3][2], angle, s, c;
int i, j;
if (SEQ < 3) /* not enough points */
{
error(nopnt);
return;
}
if (DBNullelt(cset))
{
error(noset);
return;
}
p1 = PTNextPoint(POINTLIST); /* calculate rotation angle */
p2 = PTNextPoint(p1);
angle = (float) atan2((p2->x - POINTLIST->x),(p2->y - POINTLIST->y))
-(float) atan2((p1->x - POINTLIST->x),(p1->y - POINTLIST->y));
s = (float) sin(angle);
c = (float) cos(angle);
/* Define transformation matrix to translate set to origin, rotate,
and translate back. */
xmat[0][0] = c;
xmat[0][1] = -s;
xmat[1][0] = s;
xmat[1][1] = c;
xmat[2][0] = (-c) * POINTLIST->x - s * POINTLIST->y + POINTLIST->x;
xmat[2][1] = (-c) * POINTLIST->y + s * POINTLIST->x + POINTLIST->y;
e1 = cset;
while ( !DBNullelt(e1) )
{
DISScreenErase(e1, (linemask | setmask));
TxMsgOK();
DBXform(e1, xmat, &PICTURE);
if (TEXT(e1->type))
{
GRsetwmask(textmask | setmask);
p1 = e1->ptlist;
GRPutText(e1->type, p1, e1->brushf,
e1->size,e1->textpt, &pos);
i= strlen(e1->textpt);
p2 = PTInit();
(void) PTMakePoint(p1->x, p1->y, &p2);
/* add extra positioning points */
(void) PTMakePoint(pos.x, pos.y, &p2);
(void) PTMakePoint(pos.x + i * charxsize / 2,
pos.y, &p2);
(void) PTMakePoint(pos.x + i * charxsize,
pos.y, &p2);
e1->ptlist = p2;
} /* end if TEXT */
else
DISScreenAdd(e1, (linemask | setmask));
e1 = DBNextofSet(e1);
} /* end while */
CHANGED = TRUE;
} /* end SHRotate */
\f
SHScale()
/*
* This routine scales the elements in the current set as defined
* by points. The scaling is accomplished by defining a transformation
* matrix and calling DBXform.
*/
{
ELT *e1;
POINT pos, *p1, *p2;
float xmat[3][2], d1, d2, scalex, scaley;
int i, j;
if (SEQ < 3) /* not enough points */
{
error(nopnt);
return;
}
if (DBNullelt(cset))
{
error(noset);
return;
}
p1 = PTNextPoint(POINTLIST);
p2 = PTNextPoint(p1);
d1 = sqrt( pow((p1->x - POINTLIST->x), 2.0)
+ pow((p1->y - POINTLIST->y), 2.0));
d2 = sqrt( pow((p2->x - POINTLIST->x), 2.0)
+ pow((p2->y - POINTLIST->y), 2.0));
if (d1 == 0)
{
error("infinite scale");
return;
}
scalex = scaley = d2 / d1;
/* create transformation matrix to translate set to origin,
performaing the scaling and translating back */
xmat[0][0] = scalex;
xmat[1][1] = scaley;
xmat[1][0] = xmat[0][1] = 0;
xmat[2][0] = - POINTLIST->x * (scalex - 1.0);
xmat[2][1] = - POINTLIST->y * (scaley - 1.0);
e1 = cset;
while ( !DBNullelt(e1) )
{
DISScreenErase(e1, (linemask | setmask));
TxMsgOK();
DBXform(e1, xmat, &PICTURE);
if (TEXT(e1->type))
{
GRsetwmask(textmask | setmask);
p1 = e1->ptlist;
GRPutText(e1->type, p1, e1->brushf,
e1->size,e1->textpt, &pos);
i= strlen(e1->textpt);
p2 = PTInit();
(void) PTMakePoint(p1->x, p1->y, &p2);
/* add extra positioning points */
(void) PTMakePoint(pos.x, pos.y, &p2);
(void) PTMakePoint(pos.x + i * charxsize / 2,
pos.y, &p2);
(void) PTMakePoint(pos.x + i * charxsize,
pos.y, &p2);
e1->ptlist = p2;
} /* end if TEXT */
else
DISScreenAdd(e1, (linemask | setmask));
e1 = DBNextofSet(e1);
} /* end while */
CHANGED = TRUE;
} /* end SHScale */
\f
SHUpdate()
/*
* This routine redraws the graphics screen by clearing the screen ,
* redisplaying the menu and adding each element back to the display.
*/
{
ELT *e1;
int i;
GRClear(linemask | setmask | textmask);
MNDisplayMenu();
e1 = PICTURE;
while ( !DBNullelt(e1) )
{
DISScreenAdd(e1, linemask);
e1 = DBNextElt(e1);
};
e1 = cset;
while ( !DBNullelt(e1) )
{
DISScreenAdd(e1, setmask);
e1 = DBNextofSet(e1);
};
if ( Adjustment != NOADJ) MNHighLt(HiMode[adj[Adjustment]], hicolor);
if (GravityOn) MNHighLt(HiMode[3], hicolor); /* re highlight */
MNHighLt(HiFont[CFONT-1], hicolor); /* selected menu */
MNHighLt(HiBrush[CBRUSH-1], hicolor); /* menu attributes */
for (i = 0; i < NUSER; ++i)
if ( !DBNullelt(MEN[i]) ) MNHighLt(HiMen[i], hicolor);
Consume = FALSE;
} /* end SHUpdate */
\f
SHRedis()
/*
* This routine is used to redisplay the text screen.
* It clears the screen, then redisplays the text and each of the
* defined fields.
*/
{
char string[4];
TxRedisplay();
TxPutString(&TEdit, Editfile);
(void) sprintf(string,"%1d",CBRUSH);
TxPutString(&TBrush,string);
(void) sprintf(string, "%1d",CFONT);
TxPutString(&TFont,string);
(void) sprintf(string, "%1d",CSIZE);
TxPutString(&TCSize,string);
TxPutString(&TJustmode,dispmode[CJUST]);
(void) sprintf(string, "%3d",Alignment);
TxPutString(&TAlign,string);
(void) sprintf(string,"%1d",CBRUSH);
TxPutString(&TBrush,string);
if (GravityOn) TxPutString(&TGravity, " ON");
else TxPutString(&TGravity, "OFF");
switch(Adjustment)
{
case NOADJ: TxPutString(&TAdjust, "NO ADJUSTMENT");
break;
case HORZ: TxPutString(&TAdjust, " HORIZONTAL ");
break;
case VERT: TxPutString(&TAdjust, " VERTICAL ");
break;
case MAN: TxPutString(&TAdjust, " MANHATTAN ");
break;
} /* end switch */;
Consume = FALSE;
} /* end SHRedis */
\f
SHShellEsc()
/*
* This routine performs a shell escape through the c 'system'
* function. It first retrieves the command line through TxGetLine.
*/
{
char line[80];
TxGetLine("!",line,80);
TxClose(); /* Restore text terminal to 'normal' state */
(void) system(line); /* do command */
/* allow time for user to digest command */
printf("Type <cr> to continue");
(void) fflush(stdout);
line[1] = TxGetChar();
SHRedis(); /* reclaim terminal */
} /* end ShellEsc */
\f
static savemen(sym)
int sym;
/*
* This local routine stores the current set in the specified
* user symbol.
*/
{
ELT *elist;
float xmat[3][2];
xmat[0][0] = xmat[1][1] = 1; /* set up copy transformation */
xmat[0][1] = xmat[1][0] = 0; /* matrix for no */
xmat[2][0] = xmat[2][1] = 0; /* transformation */
while ( !DBNullelt(MEN[sym]) )
{ /* clear out existing symbol */
elist = DBNextElt(MEN[sym]);
DBClearElt(MEN[sym]);
MEN[sym] = elist;
};
elist = cset; /* copy current set to symbol */
while ( !DBNullelt(elist) )
{
(void) DBCopy(elist, xmat, &(MEN[sym]));
elist = DBNextofSet(elist);
} /* end while */;
if (SEQ = 0) /* no positioning points */
{
MENPOINT[sym].x = 0;
MENPOINT[sym].y = 0;
}
else
{
MENPOINT[sym].x = POINTLIST->x;
MENPOINT[sym].y = POINTLIST->y;
}
if ( !DBNullelt(MEN[sym]) ) MNHighLt(HiMen[sym], hicolor);
else MNUnHighLt(HiMen[sym]);
CHANGED = TRUE;
} /* end savemen */
SHSave1()
/*
* This routine saves the current set in user symbol 1 by
* calling savemen.
*/
{
savemen(0);
}
SHSave2()
/*
* This routine saves the current set in user symbol 2 by
* calling savemen.
*/
{
savemen(1);
}
SHSave3()
/*
* This routine saves the current set in user symbol 3 by
* calling savemen.
*/
{
savemen(2);
}
SHSave4()
/*
* This routine saves the current set in user symbol 4 by
* calling savemen.
*/
{
savemen(3);
}
\f
SHBox()
/*
* This routine creates and displays a rectangle whose diagonal is
* defined by two points. The routine uses the coordinates of these
* points to define a VECTOR element with the appropriate vertices.
*/
{
POINT *plist, *p1, *p2;
char *txt;
ELT *e1;
if (SEQ < 2)
{
error("not enough points");
return;
}
p1 = POINTLIST;
p2 = PTNextPoint(p1);
plist = PTInit(); /* create points for vector element which defines
the rectangle */
(void) PTMakePoint(p1->x, p1->y, &plist);
(void) PTMakePoint(p1->x, p2->y, &plist);
(void) PTMakePoint(p2->x, p2->y, &plist);
(void) PTMakePoint(p2->x, p1->y, &plist);
(void) PTMakePoint(p1->x, p1->y, &plist); /* close rectangle */
txt = malloc(1);
*txt = '\0';
DBClearSet(); /* clear old set in preparation to make */
DISClearSetDisplay(); /* the new current set */
e1 = DBCreateElt(VECTOR, plist, CBRUSH, 0, txt, &PICTURE);
DBAddSet(e1);
DISScreenAdd(e1, (linemask | setmask));
CHANGED = TRUE;
} /* end LGBox */
SHArrow()
/*
* This routine draws arrow heads by 'copying' the arrow head template
* into the picture appropriately transformed.
*/
{
ELT *e1;
POINT p1, *p2;
float xmat[3][2], angle, s, c;
if (SEQ < 2) /* not enough points */
{
error(nopnt);
return;
}
p1.x = POINTLIST->x - 1;
p1.y = POINTLIST->y;
p2 = PTNextPoint(POINTLIST);
angle = (float) atan2((p2->x - POINTLIST->x),(p2->y - POINTLIST->y))
-(float) atan2((p1.x - POINTLIST->x),(p1.y - POINTLIST->y));
s = (float) sin(angle);
c = (float) cos(angle);
/* Define transformation matrix to translate element from origin
and rotate. */
xmat[0][0] = c;
xmat[0][1] = -s;
xmat[1][0] = s;
xmat[1][1] = c;
xmat[2][0] = POINTLIST->x;
xmat[2][1] = POINTLIST->y;
DBClearSet(); /* clear old set in preparation to make */
DISClearSetDisplay(); /* the new current set */
arhead.brushf = CBRUSH;
e1 = DBCopy(&arhead, xmat, &PICTURE);
DBAddSet(e1);
DISScreenAdd(e1, (linemask | setmask));
CHANGED = TRUE;
} /* end SHArrow */