* This file contains routines for database manipulation for the
* SUN Gremlin picture editor.
* Mark Opperman (opcode@monet.BERKELEY)
/* imports from undodb */
/* imports from point.c */
extern PTModifyTextPoints();
extern POINT
*PTMakePoint();
/* imports from text.c */
extern SEARCH
; /* Search the path for filename */
/* cset is a pointer to the current set available to the outside world. */
* This routine returns a pointer to an initialized database element
* which would be the only element in an empty list.
* This routine creates a new element with the specified attributes and
* links it into database db.
DBCreateElt(type
, pointlist
, brush
, size
, text
, db
)
temp
= (ELT
*) malloc(sizeof(ELT
));
temp
->ptlist
= pointlist
;
* This routine deletes the specified element by searching the database
* for its predecessor and deleting the pointer to the element.
* Flag indicates whether or not the element was in the current set
* and is passed along for use by the undo routines.
register ELT
*elt
, *(*db
);
error("no such element");
temp
= &(DBNextElt((*temp
)));
#define highval 100000 /* arbitrary value greater than any
* This routine searches the database for the point closest to
* (Euclidean distance) point1. This point is returned as point2
* and the element which contained the point is also returned.
* The point must be closer than some predefined maximum distance
* in order to be gravitated.
* If setonly == TRUE the element's "setnext" pointer is used to
* find the elements in the list, otherwise "nextelt" is used.
DBGravitate(x1
, y1
, x2
, y2
, point
, elt
, db
, setonly
)
register distance
= highval
;
while (!DBNullelt(temp
)) {
while (!Nullpoint(holdpt
)) {
/* Calculate the distance between the point in the data
base and the specified point. Use Euclidean distance
except that, since we only need relative distance and
not an absolute number, it is not necessary to take the
square root. The equation for the distance was broken up
as below in order to allow integer arithmetic wherever
possible to increase efficiency when it was discovered
that this routine was too slow. */
if ((t
< distance
) && (t
< MAXGDIST
)) {
temp
= setonly
? DBNextofSet(temp
) : DBNextElt(temp
);
* This routine returns all storage associated with the element to
register POINT
*pt
, *pt2
;
* This routine reads the specified file into a database and
* returns a pointer to that database. Orient and pos are also set
* The format of a file written by gremlin is:
* the string: "gremlinfile" followed by a carriage return.
* the orientation (integer) and the x and y coordinates of a positioning
* point (float) followed by another carriage return.
* The output of 0 or more elements (see below).
* a -1 (integer) indicating end of data.
* The format of each element is:
* The element type (integer) followed by a carriage return.
* a list of 0 or more pairs of point coordinates (float) each on separate
* lines and terminated by the coordinates -1.0 -1.0.
* the brush (font) and size (integer) the element was defined with then <cr>
* the length (integer) of the string followed by the string terminated with
* All numbers are printed using standard C output conversion (ascii).
* +++ NEW FORMAT FOR SUN +++
* "sungremlinfile" is keyword in place of "gremlinfile"
* Point lists are terminated by a line containing a single asterik ('*')
* to allow the legal point (-1.00 -1.00) in the point list. All negative
* coordinates are now legal. Element types are indicated by ascii text,
* eg, POLYGON, VECTOR, ARC, BOTLEFT, TOPCENT, etc.
DBRead(filename
, orient
, pos
)
char string
[128], *txt
, *prealname
;
int len
, type
, i
, brush
, size
, done
, lastpoint
, sunfile
;
fp
= POpen(filename
, &prealname
, SEARCH
);
(void) sprintf(string
, "can't open %s",filename
);
if (TOOLINSTALLED
) /* no message if reading startup edit file */
TxPutMsg("reading file...");
(void) fscanf(fp
, "%s\n", string
);
if (strcmp(string
, "gremlinfile")) {
if (strcmp(string
, "sungremlinfile")) {
error("not gremlin file");
(void) fscanf(fp
, "%d%f%f\n", orient
, &x
, &y
);
if (fscanf(fp
,"%s\n", string
) == EOF
) { /* element type */
error("error in file format");
if ((type
= DBGetType(string
)) < 0) { /* no more data */
(void) fscanf(fp
, "%f%f\n", &x
, &y
); /* read first point */
/* Files created on the SUN have point lists terminated
* by a line containing only an asterik ('*'). Files
* created on the AED have point lists terminated by the
* coordinate pair (-1.00 -1.00).
(void) PTMakePoint(x
, y
, &plist
);
if (string
[0] == '*') { /* SUN gremlin file */
(void) sscanf(string
, "%f%f", &x
, &y
);
if ((x
== -1.00 && y
== -1.00) && (!sunfile
))
while ((x
!= -1) && (y
!= -1)) { /* plist terminated by -1, -1 */
(void) PTMakePoint(x
, y
, &plist
);
(void) fscanf(fp
, "%f%f\n", &x
, &y
);
(void) fscanf(fp
, "%d%d\n", &brush
, &size
);
(void) fscanf(fp
, "%d", &len
);
(void) getc(fp
); /* eat blank */
txt
= malloc((unsigned) len
+ 1);
elt
= DBCreateElt(type
, plist
, brush
, size
, txt
, &elist
);
if (TEXT(elt
->type
)) /* recompute text reference points */
* Interpret element type in string s.
* Old file format consisted of integer element types.
* New file format has literal names for element types.
if (isdigit(s
[0]) || (s
[0] == '-')) /* old element format or EOF */
error("unknown element type");
error("unknown element type");
error("unknown element type");
error("unknown element type");
* This routine returns true if all points in elt are bounded by
* the rectangle who diagonal is formed by (x1, y1) and (x2, y2).
DBBounded(elt
, x1
, y1
, x2
, y2
)
register float x1
, y1
, x2
, y2
;
register float lox
, loy
, hix
, hiy
; /* OK to compare register floats */
lox
= (x1
< x2
) ? x1
: x2
;
loy
= (y1
< y2
) ? y1
: y2
;
hix
= (x1
> x2
) ? x1
: x2
;
hiy
= (y1
> y2
) ? y1
: y2
;
if ((p1
->x
< lox
) || (p1
->x
> hix
) || (p1
->y
< loy
) || (p1
->y
> hiy
))
* This routine creates a copy of the the element transformed by
* the transformation matrix and adds the new copy to the database.
DBCopy(elt
, transform
, db
)
while (!Nullpoint(pt
)) { /* matrix multiply */
(void) PTMakePoint((((pt
->x
) * transform
[0][0]) +
((pt
->y
) * transform
[1][0]) +
(((pt
->x
) * transform
[0][1]) +
((pt
->y
) * transform
[1][1]) +
transform
[2][1]), &newlist
);
newtext
= malloc((unsigned) strlen(elt
->textpt
) + 1);
(void) strcpy(newtext
, elt
->textpt
);
return( DBCreateElt(elt
->type
, newlist
, elt
->brushf
,
elt
->size
, newtext
, db
) );
* This routine transforms the element by multiplying the
* coordinates of each of the points in the element by the
DBXform(elt
, transform
, db
)
px
= ((pt
->x
) * transform
[0][0]) +
((pt
->y
) * transform
[1][0]) + transform
[2][0];
py
= ((pt
->x
) * transform
[0][1]) +
((pt
->y
) * transform
[1][1]) + transform
[2][1];
* This routine changes the brush attribute of the element.
DBChangeBrush(elt
, brush
, db
)
} /* end DBChangeBrush */
* This routine changes the justify attribute of the element.
DBChangeJustify(elt
, justmode
, db
)
register POINT
*pos
, *point
;
} /* end DBChangeJustify */
* This routine changes the font attribute of the given element.
DBChangeFont(elt
, font
, db
)
* This routine changes the size attribute of the given element.
DBChangeSize(elt
, size
, db
)
* This routine changes the stipple attribute of the given element.
DBChangeStipple(elt
, stipple
, db
)
} /* end DBChangeStipple */
* This routine changes the text attribute of the given element.
DBChangeText(elt
, text
, db
)
new = malloc((unsigned) strlen(text
) + 1);
(void) strcpy(new, text
);
* This routine changes the type attribute of the given element.
DBChangeType(elt
, newtype
, db
)
* This routine changes the type and stipple attributes of the given element.
DBChangeTypeStipple(elt
, newtype
, newstipple
, db
)
* This routine changes the type, brush and stipple attributes
DBChangeTypeBrushStipple(elt
, newtype
, newbrush
, newstipple
, db
)
int newtype
, newbrush
, newstipple
;
* This routine adds the element to the current set database.
while (!DBNullelt(elist
)) { /* makes sure element not already in list */
elist
= DBNextofSet(elist
);
* Return TRUE if element in current set, else FALSE.
while (!DBNullelt(elist
)) { /* makes sure element not already in list */
elist
= DBNextofSet(elist
);
* This routine clears the current set by setting the pointer
cset
= DBNextofSet(cset
);