#include #include #include #include #ifdef MSWPC #include #endif #ifndef MSWPC #ifdef SYS5 #include #else #include #endif #endif /* #include #include #include */ #include "vogle.h" extern void polyobj(int n, Token dp[]); typedef struct o { int obno; TokList *tlist; struct o *next; } Object; static Object *object_table[MAXENTS]; static int obno = -1, omax = 0; /******************************************************************************/ /* * @(#) makeobj - start a new object. */ void makeobj(int n){ Object *o; if (!vdevice.initialised) verror("makeobj: vogle not initialised"); for (o = object_table[n % MAXENTS]; o != (Object *)NULL; o = o->next) if (o->obno == n) { delobj(n); break; } obno = n; vdevice.tokens = (TokList *)NULL; vdevice.inobject = 1; if (omax <= n) omax = n + 1; } /******************************************************************************/ /* * @(#) closeobj - close an object */ void closeobj(void){ Object *o; if (!vdevice.inobject) verror("closeobj: not in an object"); vdevice.inobject = 0; o = (Object *)vallocate(sizeof(Object),"from closeobj"); o->obno = obno; o->tlist = vdevice.tokens; o->next = object_table[obno % MAXENTS]; object_table[obno % MAXENTS] = o; obno = -1; } /******************************************************************************/ /* * @(#) delobj - deletes an object, freeing its memory */ void delobj(int n){ Object *o, *lo; TokList *tl, *ntl; for (lo = o = object_table[n % MAXENTS]; o != (Object *)NULL; lo = o, o = o->next) if (o->obno == n) break; if (o != (Object *)NULL) { for (tl = o->tlist; tl != (TokList *)NULL; tl = ntl) { ntl = tl->next; if (tl->toks){ vfree(tl->toks,"from delobj 1"); } vfree(tl,"from delobj 2"); } if (lo == object_table[n % MAXENTS]){ object_table[n % MAXENTS] = (Object *)NULL; }else{ lo->next = o->next; } vfree(o,"from delobj 3"); } } /******************************************************************************/ /* * @(#) genobj - generates a unique object identifier */ int genobj(void){ return(omax++); } /******************************************************************************/ /* * @(#) getopenobj - returns the object currently being edited, -1 if none. */ int getopenobj(void){ return(obno); } /******************************************************************************/ /* * @(#) loadobj - reads in object file file and makes it the object referred to by n. */ void loadobj(int n, char *file){ int objfd; TokList *tl; Object *o; if ((objfd = open(file, O_RDONLY)) == EOF) { fprintf(stderr, "loadobject: unable to open object file %s", file); return; } o = (Object *)vallocate(sizeof(Object),"from loadobj 1"); o->obno = n; o->next = object_table[n % MAXENTS]; object_table[n % MAXENTS] = o; o->tlist = tl = (TokList *)vallocate(sizeof(TokList),"from loadobj 2"); read(objfd, &tl->count, sizeof(tl->count)); tl->toks = (Token *)vallocate(tl->count * sizeof(Token),"from loadobj 3"); tl->next = (TokList *)NULL; read(objfd, tl->toks, tl->count * sizeof(Token)); close(objfd); } /******************************************************************************/ /* * @(#) saveobj - saves the object n into file file. */ void saveobj(int n, char *file){ int objfd, count; Object *o; TokList *tl; if ((objfd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0664)) == EOF) { fprintf(stderr, "saveobject: unable to open object file %s", file); return; } for (o = object_table[n % MAXENTS]; o != (Object *)NULL; o = o->next) if (o->obno == n) break; if (o == (Object *)NULL) return; count = 0; for (tl = o->tlist; tl != (TokList *)NULL; tl = tl->next) count += tl->count; write(objfd, &count, sizeof(count)); for (tl = o->tlist; tl != (TokList *)NULL; tl = tl->next) write(objfd, tl->toks, tl->count * sizeof(Token)); close(objfd); } /******************************************************************************/ /* * @(#) doarc - draw an arc or circle. */ static void doarc(float x, float y, float xoff, float yoff, float cosine, float sine, int nsegs){ float cx, cy, dx, dy; int i; cx = x + xoff; cy = y + yoff; move2(cx, cy); for (i = 0; i < nsegs; i++) { dx = cx - x; dy = cy - y; cx = x + dx * cosine - dy * sine; cy = y + dx * sine + dy * cosine; draw2(cx, cy); } } /******************************************************************************/ /* * @(#) callobj - draws an object */ void callobj(int n){ Object *o; TokList *tl; Matrix prod, tmpmat; Tensor S; int sync, i, j, inpoly; float cx, cy, cz, *m; register Token *t, *et, *pt; if (!vdevice.initialised) verror("callobj: vogle not initialised"); if (vdevice.inobject) { t = newtokens(2); t[0].i = OBJ_CALLOBJ; t[1].i = n; return; } for (o = object_table[n % MAXENTS]; o != (Object *)NULL; o = o->next) if (o->obno == n) break; if (o == (Object *)NULL) return; if ((sync = vdevice.sync)) vdevice.sync = 0; for (tl = o->tlist; tl != (TokList *)NULL; tl = tl->next) { t = tl->toks; et = &tl->toks[tl->count]; while (t != et) { switch (t->i) { case OBJ_ARC: doarc(t[1].f, t[2].f, t[3].f, t[4].f, t[5].f, t[6].f, t[7].i); t += 8; break; case OBJ_BACKBUFFER: backbuffer(); t++; break; case OBJ_BACKFACING: backface(t[1].i); t += 2; break; case OBJ_BOXTEXT: boxtext(t[1].f, t[2].f, t[3].f, t[4].f, (char *)&t[5]); t += 6 + (int)strlen((char *)&t[5]) / sizeof(Token); break; case OBJ_CALLOBJ: callobj(t[1].i); t += 2; break; case OBJ_TEXTSLANT: textslant(t[1].f); t += 2; break; case OBJ_CENTERTEXT: centertext(t[1].i); t += 2; break; case OBJ_TEXTJUSTIFY: textjustify(t[1].i); t += 2; break; case OBJ_RIGHTJUSTIFY: rightjustify(); t += 1; break; case OBJ_LEFTJUSTIFY: leftjustify(); t += 1; break; case OBJ_XCENTERTEXT: xcentertext(); t += 1; break; case OBJ_YCENTERTEXT: ycentertext(); t += 1; break; case OBJ_TOPJUSTIFY: topjustify(); t += 1; break; case OBJ_BOTTOMJUSTIFY: bottomjustify(); t += 1; break; case OBJ_CIRCLE: inpoly = vdevice.inpolygon; if ((vdevice.attr->a.fill || vdevice.attr->a.hatch) && !inpoly) makepoly(); doarc(t[1].f, t[2].f, t[3].f, 0.0, t[4].f, t[5].f, t[6].i); if ((vdevice.attr->a.fill || vdevice.attr->a.hatch) && !inpoly) closepoly(); else draw2(t[1].f + t[3].f, t[2].f); t += 7; break; case OBJ_CLEAR: (*vdevice.dev.Vclear)(); t++; break; case OBJ_COLOR: color(t[1].i); t += 2; break; case OBJ_LINEWIDTH: linewidth(t[1].i); t += 2; break; case OBJ_DRAW: draw(t[1].f, t[2].f, t[3].f); t += 4; break; case OBJ_DRAWCHAR: drawchar(t[1].i); t += 2; break; case OBJ_DRAWSTR: drawstr((char *)&t[1]); t += 2 + (int)strlen((char *)&t[1]) / sizeof(Token); break; case OBJ_FIXEDWIDTH: fixedwidth(t[1].i); t += 2; break; case OBJ_FONT: font((char *)&t[1]); t += 2 + (int)strlen((char *)&t[1]) / sizeof(Token); break; case OBJ_HATCHANG: vdevice.attr->a.hatchcos = t[1].f; vdevice.attr->a.hatchsin = t[2].f; t += 3; break; case OBJ_HATCHPITCH: vdevice.attr->a.hatchpitch = t[1].f; t += 2; break; case OBJ_LOADMATRIX: m = (float *)vdevice.transmat->m; for (i = 0; i < 16; i++) *m++ = (++t)->f; /* may have changed mapping from world to device coords */ vdevice.cpVvalid = 0; t++; break; case OBJ_MAPCOLOR: mapcolor(t[1].i, t[2].i, t[3].i, t[4].i); t += 5; break; case OBJ_MOVE: move(t[1].f, t[2].f, t[3].f); t += 4; break; case OBJ_MULTMATRIX: m = (float *)tmpmat; for (i = 0; i < 16; i++) *m++ = (++t)->f; mult4x4(prod, tmpmat, vdevice.transmat->m); loadmatrix(prod); t++; break; case OBJ_POLY: polyobj(t[1].i, &t[2]); t += 2 + 3 * t[1].i; break; case OBJ_POLYFILL: polyfill(t[1].i); t += 2; break; case OBJ_POLYHATCH: polyhatch(t[1].i); t += 2; break; case OBJ_POPATTRIBUTES: popattributes(); t++; break; case OBJ_POPMATRIX: popmatrix(); t++; break; case OBJ_POPVIEWPORT: popviewport(); t++; break; case OBJ_PUSHATTRIBUTES: pushattributes(); t++; break; case OBJ_PUSHMATRIX: pushmatrix(); t++; break; case OBJ_PUSHVIEWPORT: pushviewport(); t++; break; case OBJ_RCURVE: i = (++t)->i; cx = (++t)->f; cy = (++t)->f; cz = (++t)->f; m = (float *)tmpmat; for (j = 0; j < 16; j++) *m++ = (++t)->f; mult4x4(prod, tmpmat, vdevice.transmat->m); drcurve(i, prod); vdevice.cpW[V_X] = cx; vdevice.cpW[V_Y] = cy; vdevice.cpW[V_Z] = cz; t++; break; case OBJ_RPATCH: pt = t + 10; cx = (++t)->f; cy = (++t)->f; cz = (++t)->f; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { S[0][i][j] = (pt++)->f; S[1][i][j] = (pt++)->f; S[2][i][j] = (pt++)->f; S[3][i][j] = (pt++)->f; } transformtensor(S, vdevice.transmat->m); drpatch(S, t[1].i, t[2].i, t[3].i, t[4].i, t[5].i, t[6].i); vdevice.cpW[V_X] = cx; vdevice.cpW[V_Y] = cy; vdevice.cpW[V_Z] = cz; t = pt; break; case OBJ_SECTOR: inpoly = vdevice.inpolygon; if ((vdevice.attr->a.fill || vdevice.attr->a.hatch) && !inpoly) makepoly(); doarc(t[1].f, t[2].f, t[3].f, t[4].f, t[5].f, t[6].f, t[7].i); draw(t[1].f, t[2].f, 0.0); if ((vdevice.attr->a.fill || vdevice.attr->a.hatch) && !inpoly) closepoly(); else draw2(t[1].f + t[3].f, t[2].f + t[4].f); t += 8; break; case OBJ_TEXTANG: vdevice.attr->a.textcos = t[1].f; vdevice.attr->a.textsin = t[2].f; t += 3; break; case OBJ_TEXTSIZE: textsize(t[1].f, t[2].f); t += 3; break; case OBJ_VIEWPORT: viewport(t[1].f, t[2].f, t[3].f, t[4].f); t += 5; break; case OBJ_TRANSLATE: translate(t[1].f, t[2].f, t[3].f); t += 4; break; case OBJ_SCALE: /* * Do the operations directly on the top matrix of * the stack to speed things up. */ vdevice.transmat->m[0][0] *= t[1].f; vdevice.transmat->m[0][1] *= t[1].f; vdevice.transmat->m[0][2] *= t[1].f; vdevice.transmat->m[0][3] *= t[1].f; vdevice.transmat->m[1][0] *= t[2].f; vdevice.transmat->m[1][1] *= t[2].f; vdevice.transmat->m[1][2] *= t[2].f; vdevice.transmat->m[1][3] *= t[2].f; vdevice.transmat->m[2][0] *= t[3].f; vdevice.transmat->m[2][1] *= t[3].f; vdevice.transmat->m[2][2] *= t[3].f; vdevice.transmat->m[2][3] *= t[3].f; t += 4; break; case OBJ_ROTATE: rotate(t[1].f, (char)t[2].i); t += 3; break; case OBJ_VFLUSH: /* JSU: ADDED THIS Sun Jun 4 22:47:05 EDT 1995 */ t++; break; case OBJ_RECT: /* JSU: ADDED THIS Sun May 8 2004 */ rect(t[1].f, t[2].f, t[3].f, t[4].f); t += 5; break; default: fprintf(stderr,"UNEXPECTED OBJECT %d\n",t->i); verror("vogle: internal error in callobj"); exit(1); } } } if (sync) { vdevice.sync = 1; (*vdevice.dev.Vsync)(); } } /******************************************************************************/ /* * @(#) isobj - returns 1 if there is an object n, 0 otherwise. */ int isobj(int n){ Object *o; for (o = object_table[n % MAXENTS]; o != (Object *)NULL; o = o->next) if (o->obno == n) break; return(o != (Object *)NULL); } /******************************************************************************/