232c2da0c43bee219f5436053747a813e657403c
[unix-history] / usr / src / local / ditroff / ditroff.old.okeeffe / gremlin.aed / gremlin / long2.c
\f
/* long2.c -
*
* Copyright -C- 1982 Barry S. Roitblat
*
*
* This file contains routines to implement the long text commands
* of the gremlin PICTURE editor.
*
*/
#include "gremlin.h"
#include "grem2.h"
#include <ctype.h>
/* imports from graphics files */
extern GRVector(), GRArc(), GRPutText(), GRClose();
extern GRDisplayPoint(), GRDeletePoint(), GRBlankPoints();
extern charxsize, charysize, GrXMax, GrYMax;
/* import from path.c */
extern int PSetPath(), PConvertTilde();
extern char *PGetPath();
/* imports from display.c */
extern DISScreenAdd(), DISScreenErase();
extern DISDisplaySet(), DISEraseSet(), DISClearSetDisplay();
/* imports from database files */
extern ELT *DBInit(), *DBCreateElt(), *DBRead();
extern DBDelete(), DBGravitate(), DBClearElt();
extern ELT *DBCopy();
extern DBXform(), DBChangeBrush();
extern DBAddSet(), DBClearSet();
extern POINT *PTInit(), *PTMakePoint();
extern PTDeletePoint();
/* imports from undodb.c */
extern UNELT *unlist, *unback;
extern UNForget();
/* imports from short.c */
extern SHUpdate();
extern int adj[];
/* imports from textio.c */
extern TxPutString(), TxPutMsg(), TxMsgOK(), TxClose();
extern TXFIELD TAlign, TAdjust, TBrush, TFont, TGravity, TCSize;
extern TEdit, TJustmode;
/* imports from menu.c */
extern MNHighLt(), MNUnHighLt();
extern HiMen[], HiFont[], HiBrush[], HiMode[];
/* imports from c */
extern char *malloc();
extern char *strcpy(), *sprintf();
/* imports from main.c */
extern ELT *PICTURE; /* current PICTURE database */
extern ELT *cset; /* current set database */
extern CBRUSH, CSIZE, CFONT; /* current brush, size, font */
extern CJUST; /* current text justification */
extern Gridon; /* grid mode flag */
extern Orientation; /* orientation of workspace */
extern SEARCH; /* flag for path search */
extern Alignment; /* point alignment indicator */
extern float PX, PY; /* cursor coordinates */
extern float Lastx, Lasty; /* previous cursor coordinates */
extern SEQ; /* point sequence number */
extern POINT *POINTLIST, *BACKPOINT;/* accumulated point list */
extern Gridsize; /* grid spacing */
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 char *textpos[], *dispmode[];/* text positioning modes */
extern int textmode[]; /* text positioning */
extern char *lines[], *fonts[]; /* line and character styles */
extern int jmodes, lnum[], fnum[];
/* imports from long1.c */
extern bang;
extern GetNumParm();
extern LGLookup();
extern SetOrient();
char *Editfile;
#define BADNUM -1
#define NONUM -2
#define Delimiter(c) ((c == '\0') || (c == ' ') || (c == ','))
static char badarg[10] = "bad args";
\f
LGFont(line)
char *line;
/*
* This routine looks at the command line for parameters to set
* the current Font.
*/
{
int new, index;
char string[2];
Consume = FALSE;
index = 0;
if (isalpha(*(++line)))
{
new = LGLookup(line, fonts, &index);
if ( new >= 0) new = fnum[new];
else new = BADNUM;
}
else new = GetNumParm(line, &index);
if ( (new == BADNUM) || (new > NFONTS) )
{
error(badarg);
return;
}
if (new != NONUM)
{
MNUnHighLt(HiFont[CFONT-1]);
MNHighLt(HiFont[new-1], hicolor);
CFONT = new;
(void) sprintf(string, "%1d",new);
TxPutString(&TFont,string);
}
} /* end LGFont */
\f
LGJust(line)
char *line;
/*
* This routine looks at the command line for parameters to set
* the current text justification mode.
*/
{
int new, index;
Consume = FALSE;
index = 0;
if (isalpha(*(++line)))
{
/* make sure mode is in lower case, and look up in table */
if (isupper(*line))
{
*line = tolower(*line);
*(line+1) = tolower(*(line+1));
}
for (new = 0; (strcmp(line, textpos[new]) != 0); ++new)
if (new > jmodes)
{
error("no such mode");
return;
}
if ( new < 0) new = BADNUM;
}
else new = GetNumParm(line, &index) - 1;
if ( (new <= BADNUM) || (new > jmodes) )
{
error(badarg);
return;
}
if (new != NONUM)
{
new = textmode[new];
CJUST = new;
TxPutString(&TJustmode,dispmode[new]);
}
} /* end LGJust */
\f
LGSize(line)
char *line;
/*
* This routine changes the current character size.
*/
{
int new, index;
char string[2];
index = 1;
new = GetNumParm(line, &index);
if ( (new == BADNUM) || (new > NSIZES) )
{
error(badarg);
return;
}
if (new != NONUM)
{
CSIZE = new;
(void) sprintf(string, "%1d",new);
TxPutString(&TCSize,string);
}
Consume = FALSE;
} /* end LGSize */
LGAlign(line)
char *line;
/*
* This routine sets the point alignment indicator
*/
{
int newalign, index;
char string[4];
index = 1;
newalign = GetNumParm(line, &index);
if (newalign == NONUM)
if (Alignment == 1) Alignment = Gridsize;
else Alignment = 1;
else
{
if ((newalign < 1) || (newalign > GrYMax/2) )
{
error(badarg);
return;
}
Alignment = newalign;
}
(void) sprintf(string, "%3d",Alignment);
TxPutString(&TAlign,string);
Consume = FALSE;
} /* end LGAlign */
\f
LGIncludeSet(line)
char *line;
/*
* This routine adds all elements selected by points in POINTLIST
* to the current set. It does not remove previously selected elements.
*
*/
{
POINT *p1, *p2;
ELT *e1;
float n1, n2;
if (DBNullelt(PICTURE)) return;
if (SEQ == 0) /* no points: entire picture becomes */
{ /* current set */
e1 = PICTURE;
while ( !DBNullelt(e1) )
{
DBAddSet(e1);
DISDisplaySet(e1);
e1 = DBNextElt(e1);
}
} /* end if */
else
{
p1 = POINTLIST;
while ( !Nullpoint(p1) )
{
DBGravitate(p1->x, p1->y, &n1, &n2, &p2, &e1, PICTURE);
if ( !DBNullelt(e1) )
{
DBAddSet(e1);
DISDisplaySet(e1);
}
p1 = PTNextPoint(p1);
} /* end while */;
} /* end else */
} /* end LGIncludeSet */
\f
LGMenu(line)
char *line;
/*
* This routine implements the menu command. The contents of
* the specified user menu item is copied into the PICTURE transformed
* to the positioning point.
*/
{
ELT *elist, *e1;
POINT *plist;
int symbol, index;
float xmat[3][2];
if (SEQ < 1)
{
error("no positioning point");
return;
}
index = 1;
symbol = GetNumParm(line, &index);
if ( (symbol <= 0) || (symbol > NUSER) )
{
error(badarg);
return;
}
symbol--; /* users inputs number between 1 and N, actual
symbol number is between 0 and N-1 */
xmat[0][0] = xmat[1][1] = 1; /* create transformation matrix */
xmat[0][1] = xmat[1][0] = 0; /* for copy into PICTURE */
plist = POINTLIST;
while ( !Nullpoint(plist) )
{
DISClearSetDisplay(); /* Clear old current set */
DBClearSet();
xmat[2][0] = plist->x - (MENPOINT[symbol]).x;
xmat[2][1] = plist->y - (MENPOINT[symbol]).y;
elist = MEN[symbol];
while ( !DBNullelt(elist) ) /* copy buffer to picture */
{
e1 = DBCopy(elist, xmat, &PICTURE);
DBAddSet(e1);
DISScreenAdd(e1, (linemask | setmask));
elist = DBNextElt(elist);
} /* end while */
plist = PTNextPoint(plist);
} /* end while */
CHANGED = TRUE;
} /* end LGMenu */
\f
LGRead(line)
char *line;
/*
* This routine reads in the specified filename (command line) to the
* selected user symbol or current set if no user symbol is selected. If
* no filename is specified, the current set is copied to the user symbol;
*/
{
POINT pos, ppos;
ELT *elist, *e1;
char tname[50], filename[100];
float xmat[3][2];
int i, orient;
if ( *line == '\0' ) /* no arguments */
{
error(badarg);
return;
}
++line;
(void) sscanf(line, "%s", tname);
elist = DBRead(tname, &orient, &pos); /* read file */
UNForget(); /* forget changes registered by DBRead */
if (SEQ < 1) /* no positioning point */
{
ppos.x = pos.x;
ppos.y = pos.y;
}
else
{
ppos.x = POINTLIST->x;
ppos.y = POINTLIST->y;
}
xmat[0][0] = xmat[1][1] = 1; /* set up matrix to copy to */
xmat[0][1] = xmat[1][0] = 0; /* appropriate place in */
xmat[2][0] = ppos.x - pos.x; /* picture as current set */
xmat[2][1] = ppos.y - pos.y;
DBClearSet();
DISClearSetDisplay();
while ( !DBNullelt(elist) )
{
e1 = DBCopy(elist, xmat, &PICTURE);
DISScreenAdd(e1, (linemask | setmask));
DBAddSet(e1);
e1 = DBNextElt(elist);
DBClearElt(elist);
elist = e1;
}
CHANGED = TRUE;
} /* end LGRead */
\f
LGEdit(line)
char *line;
/*
* This routine reads in a new PICTURE for editing
*/
{
FILE *fp, *POpen();
POINT pos;
ELT *e1;
char *tn, tname[50];
int i;
if (!bang) /* no ! */
{
if (CHANGED)
{
error("no write");
return;
}
} /* end if !bang */;
DBClearSet();
while ( !DBNullelt(PICTURE) ) /* clear current PICTURE */
{
e1 = DBNextElt(PICTURE);
DBClearElt(PICTURE);
PICTURE = e1;
};
++line;
tn = tname;
(void) sscanf(line, "%s", tname);
POINTLIST = PTInit(); /* Initialize globals */
SEQ = 0;
CHANGED = FALSE;
i = strlen(tname);
if (i > 0) /* filename present */
{
fp = POpen(tname, (char **) NULL, SEARCH);
TxPutString(&TEdit, tname);
if (fp == NULL)
{
PICTURE = DBInit();
error(" (creating new file)");
}
else
{
PICTURE = DBRead(tname, &Orientation, &pos);
SetOrient(Orientation); /* Set appropriate picture area
* orientation */
}
(void) strcpy (Editfile, tname);
}
else
{
TxPutString(&TEdit, "");
(void) strcpy(Editfile, "");
}
unlist = unback = nullun;
CP();
SHUpdate(); /* display new picture */
} /* end LGEdit */
static restorepoints()
/* This routine (re) displays the points in the back-up pointlist
*/
{
int i;
POINT *plist, *pl1, *pl2;
GRBlankPoints();
plist = BACKPOINT;
for (i=0; !Nullpoint(plist); ++i)
{
Lastx = plist->x;
Lasty = plist->y;
GRDisplayPoint( (int) plist->x, (int) plist->y, i, pointstyle );
plist = PTNextPoint(plist);
}
pl1 = POINTLIST;
POINTLIST = BACKPOINT;
SEQ = i;
BACKPOINT = pl1;
} /* end restorepoints */
\f
LGUndo(line)
char *line;
/*
* This routine uses the information in the undo database to reconstruct
* the PICTURE as it was before the last command. The undo database is set
* so that the next undo would nullify this one.
* An undo of an Add is to delete the new element.
* Add the old element back to undo a delete.
* Modified elements are undone by copying the old element into the database
* in place of the modified element.
*/
{
UNELT *fix, *temp;
ELT *(*e1);
fix = unlist; /* initialize unlist so that undo-ing can */
unlist = nullun; /* add items to properly undo the undo */
if (fix == nullun)
{
fix = unback;
unback = nullun;
}
DBClearSet();
DISClearSetDisplay();
GRBlankPoints();
while (fix != nullun)
{
switch (fix->action)
{
case ADD: DISScreenErase(fix->newelt, linemask);
TxMsgOK();
restorepoints();
DBDelete(fix->newelt, fix->dbase);
temp = fix->nextun;
free((char *) fix);
fix = temp;
break;
case DELETE: fix->action = ADD; /* create undo unelt */
fix->newelt = fix->oldelt;
fix->oldelt = NULL;
fix->newelt->nextelt = PICTURE;
restorepoints();
DBAddSet(fix->newelt);
DISScreenAdd(fix->newelt,(linemask|setmask));
PICTURE = fix->newelt; /* put in database */
temp = fix->nextun;
fix->nextun = unlist; /* link into unlist */
unlist = fix;
fix = temp;
break;
case MOD: DISScreenErase(fix->newelt, linemask);
TxMsgOK();
restorepoints();
DISScreenAdd(fix->oldelt, (setmask | linemask));
DBAddSet(fix->oldelt);
e1 = fix->dbase;
while ( *e1 != fix->newelt )
{ /* find elt to replace */
e1 = &(DBNextElt((*e1)));
}
fix->oldelt->nextelt = DBNextElt((*e1));
*e1 = fix->oldelt;
fix->oldelt = fix->newelt;
fix->newelt = *e1; /* create undo unelt */
temp = fix->nextun;
fix->nextun = unlist;
unlist = fix; /* link into unlist */
fix = temp;
break;
} /* end switch */;
} /* end while */
Consume = FALSE;
} /* LGUndo */
\f
LGWrite(line)
char *line;
/*
* This routine writes the current PICTURE into the specified filename
* or to the current Editfile
*/
{
FILE *fp, *fopen();
char tname[50], filename[100], string[100], *tn, *fn, *wfile;
ELT *elist;
POINT *plist, pos;
int i, space, stat;
space = 100;
++line;
tn = tname; fn = filename;
(void) sscanf(line, "%s", tname);
i = strlen(tname);
if (i == 0) /* no filename */
{
if ( *Editfile == '\0' )
{
error("write to where?");
return;
}
fp = fopen(Editfile, "w");
wfile = Editfile;
}
else
{
stat = PConvertTilde(&tn, &fn, &space);
*fn = '\0';
if (stat == FALSE)
{
sprintf(string, "unknown path %s", tname);
error(string);
return;
}
if ( !bang ) /* user doesn't insist */
{
fp = fopen(filename, "r");
if ( fp != NULL )
{
error("file already exists");
return;
}
}
fp = fopen(filename, "w");
wfile = filename;
};
if (fp == NULL) /* file error */
{
(void) sprintf(string,"can't open %s", wfile);
error(string);
return;
};
TxPutMsg("writing file...");
CHANGED = FALSE;
if (SEQ > 0) /* specified a positioning point */
{
pos.x = POINTLIST->x;
pos.y = POINTLIST->y;
}
else
{
if ( !DBNullelt(PICTURE) )
{
pos.x = PICTURE->ptlist->x;
pos.y = PICTURE->ptlist->y;
}
else
{
pos.x = pos.y = 0;
};
}
fprintf(fp,"gremlinfile\n"); /* write header */
fprintf(fp, "%d %1.2f %1.2f\n", Orientation, pos.x, pos.y);
elist = PICTURE;
while ( !DBNullelt(elist) ) /* write each element */
{
fprintf(fp, "%d\n", elist->type);
plist = elist->ptlist;
while ( !Nullpoint(plist) ) /* write each point */
{
fprintf(fp, "%1.2f %1.2f\n",plist->x, plist->y);
plist = PTNextPoint(plist);
} /* end while plist */
fprintf(fp, "%1.2f %1.2f\n", -1.0, -1.0); /* end pointlist */
fprintf(fp, "%d %d\n",elist->brushf, elist->size);
fprintf(fp,"%d %s\n ", strlen(elist->textpt), elist->textpt);
elist = DBNextElt(elist);
} /* end while */
fprintf(fp,"%d\n",-1); /* end of element list */
TxMsgOK();
(void) fclose(fp);
} /* end LGWrite */;
\f
LGQuit(line)
char *line;
/*
* This routine terminates the editor. The terminal states for the text
* terminal and the graphics display are restored and an EXIT is performed.
*/
{
if (!bang)
{
if (CHANGED)
{
error("no write");
return;
}
} /* end if */;
GRClose();
TxClose();
exit(0);
} /* end LGQuit */
LGHAdjust()
/*
* Horizontal adjust -
* This routine toggles the adjustment mode.
*/
{
if (Adjustment == HORZ)
{
MNUnHighLt(HiMode[adj[HORZ]]);
Adjustment = NOADJ;
TxPutString(&TAdjust, "NO ADJUSTMENT");
}
else
{
MNUnHighLt(HiMode[adj[Adjustment]]);
MNHighLt(HiMode[adj[HORZ]], hicolor);
Adjustment = HORZ;
TxPutString(&TAdjust, " HORIZONTAL ");
}
Consume = FALSE;
}
\f
LGVAdjust()
/*
* Vertical adjust -
* This routine toggles the adjustment mode.
*/
{
if (Adjustment == VERT)
{
MNUnHighLt(HiMode[adj[VERT]]);
Adjustment = NOADJ;
TxPutString(&TAdjust, "NO ADJUSTMENT");
}
else
{
MNUnHighLt(HiMode[adj[Adjustment]]);
MNHighLt(HiMode[adj[VERT]], hicolor);
Adjustment = VERT;
TxPutString(&TAdjust, " VERTICAL ");
}
Consume = FALSE;
}
\f
static sign(x)
float x;
/*
* This local routine returns 1 if x >= 0
* otherwise returns 0;
*/
{
if (x >= 0) return(1);
else return(0);
}
LGMirror(line)
char *line;
/*
* This routine mirrors the elements in the current set as defined
* by points. The mirroring is accomplished by defining a transformation
* matrix and calling DBXform.
*/
{
ELT *e1;
POINT pt, pos, *p1, *p2;
float xmat[3][2], scalex, scaley;
int i, j;
if (SEQ < 3) /* not enough points */
{
error("not enough points");
return;
}
if (DBNullelt(cset))
{
error("no current set");
return;
}
p1 = PTNextPoint(POINTLIST);
p2 = PTNextPoint(p1);
scalex = scaley = 1;
if (sign(p1->x - POINTLIST->x) != sign(p2->x - POINTLIST->x))
scalex = -scalex;
if (sign(p1->y - POINTLIST->y) != sign(p2->y - POINTLIST->y))
scaley = -scaley;
/* create transformation matrix to translate set to origin,
performing the mirroring 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
{
if (e1->type == ARC) /* arcs require special handling */
if (e1->size > 0) /* circles are OK */
if (scalex * scaley < 0) /* both directions OK */
{ /* swap starting and ending points of arc */
p1 = PTNextPoint(e1->ptlist);
p2 = PTNextPoint(p1);
pt.x = p1->x;
pt.y = p1->y;
p1->x = p2->x;
p1->y = p2->y;
p2->x = pt.x;
p2->y = pt.y;
}
DISScreenAdd(e1, (linemask | setmask));
} /* end else */
e1 = DBNextofSet(e1);
} /* end while */
CHANGED = TRUE;
} /* end LGMirror */
\f
LGPath(line)
char *line;
/*
* This routine looks at the command line for parameters to set
* the current search path.
*/
{
char path[100];
if ( *line == '\0' ) TxPutMsg(PGetPath()); /* no arguments */
else
{
SEARCH = TRUE;
(void) sscanf(line, "%s", path);
PSetPath(path);
}
Consume = FALSE;
} /* end LGFont */