home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-03-27 | 29.7 KB | 1,212 lines |
- /* Wimp draw window commands for tcl */
- /* (c) C.T.Stretch */
- /* Mon,25 Jul 1994 */
-
- #include "h.WInt"
- #include "h.colourtrans"
- #include "h.draw"
- #include "h.osfile"
- #include <math.h>
-
- #define tag_TEXT 1
- #define tag_PATH 2
- #define tag_SPRITE 5
- #define tag_GROUP 6
-
- #define NEWTEXT ckalloc(28+sizeof(struct text_data))
- #define NEWPATH ckalloc(28+sizeof(struct path_data))
- #define NEWSPRITE(n) ckalloc(28+sizeof(struct sprite_data)+n)
- #define NEWGROUP ckalloc(28+sizeof(object*))
- #define BOUNDINGBOX(x) (draw_path*)((1u<<31)|(unsigned int)((char*)(x)))
- #define NEXTPE(e,n) e=(draw_path_element*)((char*)e+4*n)
- #define SFLAGS osspriteop_USER_AREA|osspriteop_NAME
- #define DFS (draw_FILL_EXTERIOR_BOUNDARY|draw_FILL_FULL_INTERIOR|\
- draw_FILL_INTERIOR_BOUNDARY)
-
- typedef struct text_data
- { char *text;
- os_coord xy;
- os_colour fg,bg;
- font_f f;
- } text_data;
-
- typedef struct path_data
- { os_colour fc,oc;
- int thickness;
- draw_path *path;
- draw_line_style *line_style;
- draw_dash_pattern *dash_pattern;
- } path_data;
-
- typedef struct sprite_data
- { char *name;
- osspriteop_area *area;
- int sx,sy; /* size of sprite in pixels */
- os_factors factors;
- osspriteop_trans_tab trans;
- } sprite_data;
-
- typedef struct object
- { struct object *next;
- int tag,n; /* object type, object number*/
- os_box bb; /* os units */
- union
- { struct text_data t;
- struct path_data p;
- struct sprite_data s;
- struct object *g; /* linked list for group */
- } data;
- } object;
-
- typedef struct diagram
- { struct diagram *next;
- struct view *viewlist;
- struct object *objects;
- char *name,*title,*close,*click;
- tcl_menu *menu;
- int x,y,n;
- os_colour bg;
- double xscale,yscale;
- font_table ft;
- } diagram;
-
- Tcl_HashTable diagramTable;
-
- static diagram *diagramlist,*thisdiagram;
- static int bx,by,cx0,cx1,cy0,cy1; /*offsets and clipping rectangle for render*/
- static int overlap;
- static os_trfm trfm={{{1<<16,0},{0,1<<16},{0,0}}};
- static draw_line_style defstyle={0,0,0,0,0x40000,0x100,0x100,0x100,0x100};
- #define MITRE 0x10100000
- static draw_line_style roundstyle={1,1,1,0,0x40000,0x100,0x100,0x100,0x100};
- #define ROUND 0x10100015
- static os_box empty={INT_MAX,INT_MAX,INT_MIN,INT_MIN};
- static int esize[]={1,0,3,0,0,1,7,0,3};
- static char *savenumbers;
- static wimp_window dw=
- { {200,200,1200,1200},
- 0, 0, (wimp_w)-1, 0x7f01000f,
- 0x7, 0x2, 0x7, 0xFF,
- 0x3, 0x1, 0xc, 0x0,
- {0,0,320,256},
- 0x13d, 0x3000, (osspriteop_area*)0x1, 64, 512,
- "",
- 0
- };
-
- /*
- * dispose --
- * Dispose of an object!
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- static void dispose(object *obj) /* more to do */
- { ckfree(obj);
- }
-
- /*
- * findobj --
- *
- * Loacte an object in a diagram from its object number.
- *
- * Results:
- * Returns the object or 0 if not found.
- *
- * Side effects:
- * None.
- *
- */
-
- static object *findobj(diagram *d,int n)
- { object *obj;
- for(obj=d->objects;obj;obj=obj->next) if(obj->n==n) return obj;
- return 0;
- }
-
- /*
- * enlarge --
- *
- * enlarge a bounding box to include another.
- *
- * Results:
- * Box old is enlarged to contain box new.
- *
- * Side effects:
- * None.
- *
- */
-
- static void enlarge(os_box *old,os_box *new)
- { if(new->x0<old->x0) old->x0=new->x0;
- if(new->y0<old->y0) old->y0=new->y0;
- if(new->x1>old->x1) old->x1=new->x1;
- if(new->y1>old->y1) old->y1=new->y1;
- }
-
- /*
- * to_os --
- *
- * Converts a box in draw units to os units.
- *
- * Results:
- * Changes contents of box b.
- *
- * Side effects:
- * None.
- *
- */
-
- static void to_os(os_box *b)
- { b->x0=b->x0/draw_OS_UNIT;
- b->y0=b->y0/draw_OS_UNIT;
- b->x1=(b->x1+draw_OS_UNIT-1)/draw_OS_UNIT+4;
- b->y1=(b->y1+draw_OS_UNIT-1)/draw_OS_UNIT+4;
- }
-
- /*
- * mp_to_os --
- *
- * Converts a box from millipoints to os units.
- *
- * Results:
- * Changes content of box b.
- *
- * Side effects:
- * None.
- *
- */
-
- void mp_to_os(os_box *b)
- { b->x0=b->x0/font_OS_UNIT;
- b->y0=b->y0/font_OS_UNIT;
- b->x1=(b->x1+font_OS_UNIT-1)/font_OS_UNIT;
- b->y1=(b->y1+font_OS_UNIT-1)/font_OS_UNIT;
- }
-
- /*
- * render --
- *
- * Render an object if it intersects the box given by cx0 to cy1.
- * Uses offsets held in bx and by.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- static void render(object *b)
- { int i;
- object *g;
- if((cx0<=b->bb.x1)&&(cx1>=b->bb.x0)&&(cy0<=b->bb.y1)&&(cy1>=b->bb.y0))
- switch(b->tag)
- { case tag_TEXT:colourtrans_set_font_colours(b->data.t.f,b->data.t.bg,
- b->data.t.fg,14,0,0,0);
- font_paint(b->data.t.f,b->data.t.text,font_OS_UNITS,
- bx+b->data.t.xy.x,by+b->data.t.xy.y,0,0,0);
- break;
- case tag_PATH:if(b->data.p.fc!=os_COLOUR_TRANSPARENT)
- { colourtrans_set_gcol(b->data.p.fc,
- colourtrans_SET_FG,os_ACTION_OVERWRITE,&i);
- draw_fill(b->data.p.path,0,&trfm,0);
- }
- if(b->data.p.oc!=os_COLOUR_TRANSPARENT)
- { colourtrans_set_gcol(b->data.p.oc,
- colourtrans_SET_FG,os_ACTION_OVERWRITE,&i);
- draw_stroke(b->data.p.path,DFS,&trfm,0,b->data.p.thickness,
- b->data.p.line_style,b->data.p.dash_pattern);
- }
- break;
- case tag_SPRITE:xosspriteop_put_sprite_scaled(SFLAGS,
- b->data.s.area,(osspriteop_id)b->data.s.name,
- bx+b->bb.x0,by+b->bb.y0,os_ACTION_USE_MASK,
- &(b->data.s.factors),&(b->data.s.trans));
- break;
- case tag_GROUP:for(g=b->data.g;g;g=g->next) render(g);
- break;
- }
- }
-
- /*
- * diagram_redraw --
- *
- * Called in response to a redraw request.
- * If the window is a draw window it renders the required part of
- * the diagram.
- *
- * Results:
- * Return TRUE for a draw window.
- *
- * Side effects:
- * Uses variable bx,by,cx0-cy1 to pass infomation to render.
- *
- */
-
- bool diagram_redraw(void)
- { diagram *d;
- view *v;
- object *b;
- wimp_draw *wd=(wimp_draw*)█
- for(d=diagramlist;d;d=d->next) for(v=d->viewlist;v;v=v->next)
- if(v->w==block.redraw.w)
- { int more=wimp_redraw_window(wd);
- int i;
- bx=wd->box.x0-wd->xscroll;
- by=wd->box.y1-wd->yscroll;
- trfm.entries[2][0]=bx*draw_OS_UNIT;trfm.entries[2][1]=by*draw_OS_UNIT;
- while(more)
- { colourtrans_set_gcol(d->bg,colourtrans_SET_BG,os_ACTION_OVERWRITE,&i);
- os_writec(os_VDU_CLG);
- cx0=wd->clip.x0-bx;cx1=wd->clip.x1-bx;
- cy0=wd->clip.y0-by;cy1=wd->clip.y1-by;
- for(b=d->objects;b;b=b->next) render(b);
- more=wimp_get_rectangle(wd);
- }
- return TRUE;
- }
- return FALSE;
- }
-
- /*
- * force_redraw --
- *
- * Forces part of all windows of a diagram to be redrawn.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- static void force_redraw(diagram *d,os_box *bb)
- { view *v;
- for(v=d->viewlist;v;v=v->next)
- wimp_force_redraw(v->w,bb->x0,bb->y0,bb->x1,bb->y1);
- }
-
- /*
- * diagram_click --
- *
- * Called in response to a mouse click from wimp_poll
- * (not a menu click)
- * If the click was in a draw window it sets the %b %w %x and %y
- substitution and calls any attached script.
- *
- * Results:
- * Returns TRUE if the click was in a draw window.
- *
- * Side effects:
- * None.
- *
- */
-
- bool diagram_click(void)
- { diagram *d;
- view *v;
- for(d=diagramlist;d;d=d->next) for(v=d->viewlist;v;v=v->next)
- if(v->w==block.pointer.w)
- { if(d->click)
- { wimp_window_state ws;
- setbutton();
- ws.w=v->w;
- wimp_get_window_state(&ws);
- sprintf(substr['x'-'a'],"%g",
- (block.pointer.pos.x-ws.visible.x0+ws.xscroll)/d->xscale*draw_OS_UNIT);
- sprintf(substr['y'-'a'],"%g",
- (block.pointer.pos.y-ws.visible.y1+ws.yscroll)/d->yscale*draw_OS_UNIT);
- substr['w'-'a']=d->name;
- checkEval(d->click,"diagram click");
- }
- return TRUE;
- }
- return FALSE;
- }
-
- /*
- * diagram_menu --
- *
- * Called after a menu click is returned from wimp_poll
- * If the click was in a draw window it sets the %w
- * substitution and returns the menu.
- *
- * Results:
- * Returns FALSE if the click was not in a draw window.
- * Returns menu_NONE if the window does not have a menu.
- * Otherwise return the menu.
- *
- * Side effects:
- * None.
- *
- */
-
- tcl_menu *diagram_menu(void)
- { diagram *d;
- view *v;
- for(d=diagramlist;d;d=d->next) for(v=d->viewlist;v;v=v->next)
- if(v->w==block.pointer.w)
- { substr['w'-'a']=d->name;
- return d->menu;
- }
- return FALSE;
- }
-
- /*
- * dropview --
- *
- * Deletes a window open on a diagram. Removes it from the list
- * of open windows for the diagram.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- static void dropview(view *v,diagram *d)
- { wimp_delete_window(v->w);
- unlink(&(d->viewlist),v);
- ckfree(v);
- }
-
- /*
- * object_free --
- *
- * Free the memory used by a list of objects.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- static void object_free(object *obj)
- { object *next;
- for(;obj;obj=next)
- { next=obj->next;
- switch(obj->tag)
- { case tag_TEXT:ckfree(obj->data.t.text);
- break;
- case tag_PATH:ckfree(obj->data.p.path);
- break;
- case tag_SPRITE:break;
- case tag_GROUP:object_free(obj->data.g);
- break;
- }
- ckfree(obj);
- }
- }
-
- /*
- * diagram_free --
- *
- * Free the memory used by a diagram.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- static void diagram_free(diagram *d)
- { ckfree(d->name);
- object_free(d->objects);
- if(d->title!=progname) ckfree(d->title);
- ckfree(d->close);ckfree(d->click);
- if(d->menu!=menu_NONE) menu_free(d->menu);
- release_fonts(&(d->ft));
- ckfree(d);
- substr['w'-'a']=0;
- }
-
- /*
- * diagram_close --
- *
- * Called after a close event from wimp_poll.
- * If it is for a draw window it closes the window.
- * If it is the last window open on the diagram it disposes
- * of the diagram.
- *
- * Results:
- * True for a draw window.
- *
- * Side effects:
- * None.
- *
- */
-
- bool diagram_close(void)
- { diagram *d;
- view *v;
- Tcl_HashEntry *p;
- int n;
- for(d=diagramlist;d;d=d->next) for(v=d->viewlist;v;v=v->next)
- if(v->w==block.close.w)
- { if(d->viewlist->next) { dropview(v,d);return TRUE; }
- else
- { if(d->close)
- { substr['w'-'a']=d->name;
- checkEval(d->close,"diagram close");
- substr['w'-'a']=0;
- n=getconstant(w_Interp->result);
- if(n==1) return TRUE;
- if(n!=0) {dropview(v,d);return TRUE;}
- }
- dropview(v,d);
- p=Tcl_FindHashEntry(&diagramTable,d->name);
- if(!p)
- { msg("Odd close request",0,0);
- return TRUE;
- }
- Tcl_DeleteHashEntry(p);
- unlink(&diagramlist,d);
- diagram_free(d);
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /*
- * object_size --
- *
- * Returns the size in bytes of a draw object.
- * Used to fill in the size field when converting an object
- * tree to a draw file for saving.
- *
- * Results:
- * The size.
- *
- * Side effects:
- * None.
- *
- */
-
- int object_size(object *obj)
- { int m=24,n;
- osspriteop_header *hdr;
- switch(obj->tag)
- { case tag_TEXT:m+=(strlen(obj->data.t.text)/4)*4+32;
- break;
- case tag_PATH:{ path_data *p=&obj->data.p;
- draw_path_element *e;
- m+=20;
- for(e=p->path->elements;e->tag;NEXTPE(e,n))
- { n=esize[e->tag];
- m+=4*n;
- }
- }
- break;
- case tag_SPRITE:hdr=osspriteop_select_sprite(osspriteop_USER_AREA,
- obj->data.s.area,
- (osspriteop_id)obj->data.s.name);
- m+=hdr->size;
- break;
- case tag_GROUP:m+=12;
- for(obj=obj->data.g;obj;obj=obj->next) m+=object_size(obj);
- break;
- }
- return m;
- }
-
- /*
- * object_save--
- *
- * Writes the draw file representation of obj to file f.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- void object_save(object *obj,FILE *f)
- { int n=object_size(obj);
- int size[2];
- os_box box;
- osspriteop_header *hdr;
- fwrite(&obj->tag,4,1,f);
- fwrite(&n,4,1,f);
- box.x0=obj->bb.x0<<8;
- box.x1=obj->bb.x1<<8;
- box.y0=obj->bb.y0<<8;
- box.y1=obj->bb.y1<<8;
- fwrite(&box,4,4,f);
- switch(obj->tag)
- { case tag_TEXT:{ text_data *t=&obj->data.t;
- fwrite(&t->fg,4,2,f);
- n=savenumbers[t->f];
- fwrite(&n,4,1,f);
- font_read_defn(t->f,size,size+1,0,0,0,0);
- size[0]*=40;size[1]*=40;
- fwrite(size,4,2,f);
- size[0]=t->xy.x*256;;size[1]=t->xy.y*256;
- fwrite(size,4,2,f);
- fputs(t->text,f);
- n=strlen(t->text);
- do {fputc(0,f);n++;} while(n%4);
- }
- break;
- case tag_PATH:{ path_data *p=&obj->data.p;
- draw_path_element *e;
- fwrite(&p->fc,4,3,f);
- n=(p->line_style->join_style)?ROUND:MITRE;
- fwrite(&n,4,1,f);
- for(e=p->path->elements;e->tag;NEXTPE(e,n))
- { n=esize[e->tag];
- fwrite(e,4,n,f);
- }
- fwrite(e,4,1,f);
- }
- break;
- case tag_SPRITE:hdr=osspriteop_select_sprite(osspriteop_USER_AREA,
- obj->data.s.area,
- (osspriteop_id)obj->data.s.name);
- fwrite(hdr,hdr->size,1,f);
- break;
- case tag_GROUP:fputs(" ",f);
- for(obj=obj->data.g;obj;obj=obj->next) object_save(obj,f);
- break;
- }
- }
-
- /*
- * diagram_save --
- *
- * Save a draw object to a named file.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- void diagram_save(diagram *d,char *fname)
- { FILE *f=fopen(fname,"wb");
- int header[]={0x77617244,201,0};
- int i,j,used,ftsize=0;
- os_box bb=empty;
- object *obj;
- char buf[256];
- char *names[256];
- char numbers[256];
- int nextname=1;
- if(!f) return;
- fwrite(header,4,3,f);
- fprintf(f,"%-12.12s",progname);
- for(obj=d->objects;obj;obj=obj->next) enlarge(&bb,&obj->bb);
- fwrite(&bb,4,4,f);
- for(i=1;i<256;i++) if(d->ft.used[i])
- { xfont_read_identifier(i,0,&used);
- if(used>256) strcpy(buf,"Trinity.Medium");
- else xfont_read_identifier(i,(byte*)buf,0);
- for(j=1;j<nextname;j++) if(!strcmp(buf,names[j])) break;
- if(j==nextname)
- { names[nextname++]=scopy(buf);
- ftsize+=((1+strlen(buf))/4)*4+4;
- }
- numbers[i]=j;
- }
- savenumbers=numbers;
- if(ftsize>0)
- { i=0;ftsize+=8;
- fwrite(&i,4,1,f);
- fwrite(&ftsize,4,1,f);
- for(i=1;i<nextname;i++)
- { fputc(i,f);
- fputs(names[i],f);
- j=1+strlen(names[i]);
- do {fputc(0,f);j++;} while(j%4);
- ckfree(names[i]);
- }
- }
- for(obj=d->objects;obj;obj=obj->next) object_save(obj,f);
- sprintf(w_Interp->result,"1");
- fclose(f);
- xosfile_set_type(fname,0xAFF);
- }
-
- /*
- * getdbl --
- *
- * Converts a shade string representation of a length to
- * double (in inches).
- *
- * Results:
- * The length in inches.
- *
- * Side effects:
- * None.
- *
- */
-
- static double getdbl(char *s,double f)
- { double d=strtod(s,&s);
- switch(*s)
- { case 'i':break;
- case 'm':d=d/25.4;break;
- case 'c':d=d/2.54;break;
- case 'p':d=d/72;break;
- case 'd':d=d/draw_INCH;break;
- default:d=d/os_INCH;
- }
- return d*f;
- }
-
- /*
- * getsize --
- *
- * Converts a shade length to int (in inches).
- *
- * Results:
- * Length in inches.
- *
- * Side effects:
- * None.
- *
- */
-
- int getsize(char *s,double f) {return (int)getdbl(s,f);}
-
- /*
- * setpagesize --
- *
- * Sets the page size of diagram d from the string p.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- static void setpagesize(diagram *d,char *p)
- { if(!p) p="A4";
- if(p[0]=='A'||p[0]=='a')
- { char *q;
- double n=strtod(p+1,&q);
- d->x=(int)(pow(2,-.25-0.5*n)*(18000/2.54));
- d->y=(int)(pow(2,.25-0.5*n)*(18000/2.54));
- if(*q=='l') { int t; t=d->x;d->x=d->y;d->y=t; }
- }
- else
- { char *q=strchr(p,'x');
- if(q) { d->x=getsize(p,180);d->y=getsize(q+1,180);}
- }
- if(d->x<100) d->x=100;
- if(d->y<100) d->y=100;
- }
-
- /*
- * getpoint --
- *
- * Reads a shade point (number,number) and sets xy.
- * The numbers in diagram units, and are converted
- * to draw units.
- *
- *
- * Results:
- * Return TRUE if the point parses correctly.
- * points p to the character after the end ).
- *
- * Side effects:
- * None.
- *
- */
-
- static bool getpoint( char **p,os_coord *xy)
- { char *q=*p;
- if(*q++!='(') return FALSE;
- xy->x=(int)(strtod(q,&q)*thisdiagram->xscale);
- if(*q++!=',') return FALSE;
- xy->y=(int)(strtod(q,&q)*thisdiagram->yscale);
- if(*q++!=')') return FALSE;
- *p=q;
- return TRUE;
- }
-
- /*
- * getmpoint --
- * Reads a shade point (number,number) and sets xy.
- * The numbers in diagram units, and are converted
- * to millipoints.
- *
- * Results:
- * Return TRUE if the point parses correctly.
- * points p to the character after the end ).
- *
- * Side effects:
- * None.
- *
- */
-
- static bool getmpoint( char **p,os_coord *xy)
- { char *q=*p;
- if(*q++!='(') return FALSE;
- xy->x=(int)(strtod(q,&q)*thisdiagram->xscale*font_OS_UNIT/draw_OS_UNIT);
- if(*q++!=',') return FALSE;
- xy->y=(int)(strtod(q,&q)*thisdiagram->yscale*font_OS_UNIT/draw_OS_UNIT);
- if(*q++!=')') return FALSE;
- *p=q;
- return TRUE;
- }
-
- /*
- * getpath --
- *
- * Constructs a draw_path from a w textual description
- *
- * Results:
- * A draw path or 0 for a bad description.
- *
- * Side effects:
- * None.
- *
- */
-
- #define TAG(x) *((int*)&(e->tag))=x /* set tag and reserved bytes */
-
- static draw_path *getpath(char *p)
- { char *q;
- int n=2;
- draw_path *dp;
- draw_path_element *e;
- bool started=TRUE;
- for(q=p;*q;q++) switch(*q)
- { case '(': n+=3;break;
- case '<': n-=2;break;
- case '.': n++;break;
- }
- if(n<=2) goto badpath;
- dp=ckalloc(n*sizeof(int));
- e=dp->elements;
- q=p;
- TAG(draw_MOVE_TO);
- if(!getpoint(&q,&(e->data.move_to))) goto badpath;
- NEXTPE(e,3);
- for(;*q;) switch(*q)
- { case '(':TAG(draw_MOVE_TO);
- if(!getpoint(&q,&(e->data.move_to))) goto badpath;
- NEXTPE(e,3);started=TRUE;
- break;
- case '-':if(!started) goto badpath;
- TAG(draw_LINE_TO);q++;
- if(!getpoint(&q,&(e->data.line_to))) goto badpath;
- NEXTPE(e,3);
- break;
- case '<':if(!started) goto badpath;
- TAG(draw_BEZIER_TO);q++;
- if(!getpoint(&q,&(e->data.bezier_to[0]))) goto badpath;
- if(!getpoint(&q,&(e->data.bezier_to[1]))) goto badpath;
- if(*q++!='>') goto badpath;
- if(!getpoint(&q,&(e->data.bezier_to[2]))) goto badpath;
- NEXTPE(e,7);
- break;
- case '.':TAG(draw_CLOSE_LINE);q++;
- NEXTPE(e,1);started=FALSE;
- break;
- default:goto badpath;
- }
- TAG(draw_END_PATH);
- e->data.end_path=4*n;
- return dp;
- badpath:return wrong0("bad path description: ",p);
- }
-
- /*
- * setfactors --
- *
- * Set the scaling factors for a sprite object
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- */
-
- static void setfactors(object *obj)
- { obj->data.s.factors.xdiv=obj->data.s.sx<<current_ex;
- obj->data.s.factors.ydiv=obj->data.s.sy<<current_ey;
- }
-
- /*
- * settrans --
- *
- * Set the pixel translation table for a sprite
- *
- * Results:
- * TRUE if OK
- *
- * Side effects:
- * None.
- *
- */
-
- bool settrans(object *obj)
- { os_error *e;
- os_mode mode;
- int log2bpp;
- int psize;
- e=xosspriteop_read_palette_size(SFLAGS,
- obj->data.s.area,(osspriteop_id)obj->data.s.name,&psize,0,&mode);
- if(e) return 0;
- if(!psize) xos_read_mode_variable(mode,os_MODEVAR_LOG2_BPP,&log2bpp,0);
- if(!psize&&log2bpp<3)
- { int i,p[20];
- xwimp_read_palette((os_palette*)p);
- for(i=0;i<16;i++) p[i]=p[i]|(p[i]>>4);
- e=xcolourtrans_generate_table(mode,
- (os_palette*)p,(os_mode)-1,(os_palette*)-1,&(obj->data.s.trans),0,0,0,0);
- }
- else
- e=xcolourtrans_generate_table_for_sprite(obj->data.s.area,
- (osspriteop_id)obj->data.s.name,
- (os_mode)-1,(os_palette*)-1,&(obj->data.s.trans),0,0,0,0);
- return !e;
- }
-
- static void modechange(object *obj)
- { for(;obj;obj=obj->next) switch (obj->tag)
- { case tag_SPRITE:settrans(obj);setfactors(obj);break;
- case tag_GROUP:modechange(obj->data.g);
- }
- }
-
- void diagram_modechange(void)
- { diagram *d;
- modeinfo();
- for(d=diagramlist;d;d=d->next) modechange(d->objects);
- }
-
- static void palettechange(object *obj)
- { for(;obj;obj=obj->next) switch (obj->tag)
- { case tag_SPRITE:settrans(obj);break;
- case tag_GROUP:palettechange(obj->data.g);
- }
- }
-
- void diagram_palettechange(void)
- { diagram *d;
- for(d=diagramlist;d;d=d->next) palettechange(d->objects);
- }
-
- /*
- * getobject --
- *
- * Construct a draw object from a textual description
- *
- * Results:
- * An object or 0 for a bad description.
- *
- * Side effects:
- * None.
- *
- */
-
- static object *getobject(int nargs,char **argv)
- { object *obj;
- int i;
- /* *********** get text *************** */
- if(!strcmp(argv[0],"text"))
- { char *p;
- font_scan_block fsb[1];
- char *place=0;
- if(nargs<3) {return 0;}
- obj=NEWTEXT;
- obj->tag=tag_TEXT;
- obj->data.t.f=0;
- obj->data.t.bg=thisdiagram->bg;
- obj->data.t.fg=os_COLOUR_BLACK;
- p=argv[1];
- if(!getmpoint(&p,&(obj->data.t.xy))) return wrong0("bad point: ",p);
- obj->data.t.text=scopy(argv[2]);
- for(i=3;i<nargs;i++)
- { if(argv[i][0]=='-') switch(argv[i][1])
- { case 'f':obj->data.t.f=find_font(argv[i]+1,16*72,&(thisdiagram->ft));
- continue;
- case 'c':obj->data.t.fg=getcolour(argv[i]+2);continue;
- case 'b':obj->data.t.bg=getcolour(argv[i]+2);continue;
- case 'o':place=argv[i]+2;continue;
- }
- return wrong0("bad path parameter: ",argv[i]);
- }
- if(!obj->data.t.f) obj->data.t.f=find_font("fn",320,&(thisdiagram->ft));
- fsb->space.x=0;fsb->space.y=0;fsb->letter.x=0;fsb->letter.y=0;
- fsb->split_char=-1;
- font_scan_string(obj->data.t.f,obj->data.t.text,
- font_RETURN_BBOX|font_GIVEN_BLOCK|font_GIVEN_FONT,
- INT_MAX,INT_MAX,fsb,0,0,0,0,0,0);
- obj->bb=fsb->bbox;
- if(place) for(;*place;place++) switch(*place)
- { case 't':obj->data.t.xy.y-=obj->bb.y1;break;
- case 'm':obj->data.t.xy.y-=(obj->bb.y0+obj->bb.y1)/2;break;
- case 'b':obj->data.t.xy.y-=obj->bb.y0;break;
- case 'r':obj->data.t.xy.x-=obj->bb.x1;break;
- case 'c':obj->data.t.xy.x-=(obj->bb.x0+obj->bb.x1)/2;break;
- case 'l':obj->data.t.xy.x-=obj->bb.x0;break;
- }
- mp_to_os(&(obj->bb));
- obj->data.t.xy.x/=font_OS_UNIT;obj->data.t.xy.y/=font_OS_UNIT;
- obj->bb.x0+=obj->data.t.xy.x;
- obj->bb.y0+=obj->data.t.xy.y;
- obj->bb.x1+=obj->data.t.xy.x;
- obj->bb.y1+=obj->data.t.xy.y;
- return obj;
- }
- /* *********** get a path *************** */
- if(!strcmp(argv[0],"path"))
- { draw_path *dp;
- if(nargs<2) {return 0;}
- dp=getpath(argv[1]);
- if(!dp) return 0;
- obj=NEWPATH;
- obj->tag=tag_PATH;
- obj->data.p.path=dp;
- obj->data.p.fc=os_COLOUR_TRANSPARENT;obj->data.p.oc=os_COLOUR_BLACK;
- obj->data.p.thickness=0;
- obj->data.p.line_style=0;
- obj->data.p.dash_pattern=0;
- for(i=2;i<nargs;i++)
- { if(argv[i][0]=='-') switch(argv[i][1])
- { case 'i':obj->data.p.fc=getcolour(argv[i]+2);continue;
- case 'c':obj->data.p.oc=getcolour(argv[i]+2);continue;
- case 't':obj->data.p.thickness=getsize(argv[i]+2,draw_INCH);continue;
- case 'r':obj->data.p.line_style=&roundstyle;continue;
- }
- return wrong0("bad path parameter: ",argv[i]);
- }
- if(obj->data.p.thickness&&!obj->data.p.line_style)
- obj->data.p.line_style=&defstyle;
- draw_process_path(dp,
- DFS|draw_FILL_FLATTEN|draw_FILL_THICKEN|draw_FILL_REFLATTEN,
- 0,0,obj->data.p.thickness,obj->data.p.line_style,
- obj->data.p.dash_pattern,BOUNDINGBOX(&(obj->bb)));
- to_os(&(obj->bb));
- return obj;
- }
- /* *********** get a sprite *************** */
- if(!strcmp(argv[0],"sprite"))
- { char *p;
- int x,y;
- int size;
- osspriteop_area *a;
- if(nargs<3)
- return wrong0(WNA,"w_draw <name> sprite <name> <point> ?<point>? ");
- p=scopy(argv[1]);
- a=spriteinfo(p,&x,&y,TRUE);
- if((int)a<=1) return wrong0("Sprite not found: ",p);
- xcolourtrans_generate_table_for_sprite(a,(osspriteop_id)p,
- (os_mode)-1,(os_palette*)-1,0,0,0,0,&size);
- obj=NEWSPRITE(size);
- obj->tag=tag_SPRITE;
- obj->data.s.name=p;
- obj->data.s.area=a;
- if(!settrans(obj)) return 0;
- p=argv[2];
- if(!getpoint(&p,(os_coord*)&(obj->bb)))
- return wrong0("bad point ",argv[2]);
- if(nargs==3)
- { to_os(&(obj->bb));
- obj->bb.x1=obj->bb.x0+x;
- obj->bb.y1=obj->bb.y0+y;
- }
- else
- { p=argv[3];
- if(!getpoint(&p,(os_coord*)&(obj->bb.x1)))
- return wrong0("bad point ",argv[3]);
- to_os(&(obj->bb));
- }
- a=spriteinfo(argv[1],&x,&y,FALSE);
- obj->data.s.sx=x;obj->data.s.sy=y;
- obj->data.s.factors.xmul=obj->bb.x1-obj->bb.x0;
- obj->data.s.factors.ymul=obj->bb.y1-obj->bb.y0;
- setfactors(obj);
- return obj;
- }
- /* *********** get a group **************** */
- if(!strcmp(argv[0],"group"))
- { object *gobj;
- obj=NEWGROUP;
- obj->tag=tag_GROUP;
- obj->data.g=0;
- obj->bb=empty;
- for(i=1;i<nargs;i++)
- { int nitems;
- char **items;
- if(Tcl_SplitList(w_Interp,argv[i],&nitems,&items)) return 0;
- gobj=getobject(nitems,items);
- ckfree(items);
- if(!gobj) { ckfree(obj);return 0;}
- gobj->next=obj->data.g;
- obj->data.g=gobj;
- enlarge(&(obj->bb),&(gobj->bb));
- }
- return obj;
- }
- return wrong0("unknown w_draw command: ",argv[0]);
- }
-
- /*
- * w_DrawCmd --
- *
- * Implements the w_draw command.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * None.
- *
- */
-
- int w_DrawCmd(ClientData dummy,Tcl_Interp *interp,int argc,char **argv)
- { diagram *d;
- Tcl_HashEntry *p;
- object *obj;
- if(argc<3) return wrong(WNA,"w_draw <name> <command> ...");
- /* *********** create a diagram *************** */
- if(!strcmp(argv[2],"create"))
- { int new=0,m;
- char *page=0;
- p=Tcl_CreateHashEntry(&diagramTable,argv[1],&new);
- if(!new) return wrong("diagram already exists: ",argv[1]);
- d=ckcalloc(sizeof(diagram));
- d->name=scopy(argv[1]);
- d->title=progname;
- d->bg=os_COLOUR_WHITE;
- d->menu=menu_NONE;
- d->xscale=draw_INCH;d->yscale=draw_INCH;
- for(m=3;m<argc-1;m++)
- { if(!strcmp(argv[m],"-bg"))
- { d->bg=getcolour(argv[++m]);
- continue;
- }
- if(!strcmp(argv[m],"-title")) { d->title=scopy(argv[++m]);continue;}
- if(!strcmp(argv[m],"-close")) { d->close=scopy(argv[++m]);continue;}
- if(!strcmp(argv[m],"-click")) { d->click=scopy(argv[++m]);continue;}
- if(!strcmp(argv[m],"-page")) { page=argv[++m];continue;}
- if(!strcmp(argv[m],"-xscale"))
- { d->xscale=getdbl(argv[++m],draw_INCH);
- continue;
- }
- if(!strcmp(argv[m],"-yscale"))
- { d->yscale=getdbl(argv[++m],draw_INCH);
- continue;
- }
- if(!strcmp(argv[m],"-menu"))
- { d->menu=menu_make(argv[++m],d->name);
- if(d->menu==0)
- { d->menu=menu_NONE;
- return TCL_ERROR;
- }
- continue;
- }
- return wrong("unknown w_draw <name> create option: ",argv[m]);
- }
- setpagesize(d,page);
- d->next=diagramlist;
- diagramlist=d;
- Tcl_SetHashValue(p,d);
- return TCL_OK;
- }
- p=Tcl_FindHashEntry(&diagramTable,argv[1]);
- if(!p) return wrong("no such diagram: ",argv[1]);
- d=(diagram*)Tcl_GetHashValue(p);
- /* *********** open a window *************** */
- if(!strcmp(argv[2],"open"))
- { view *v=ckalloc(sizeof(view));
- int x,y;
- screensize(&x,&y);
- if(overlap>y/2-INSET) overlap=0;
- dw.title_data.indirected_text.text=d->title;
- dw.title_data.indirected_text.validation=(char*)-1;
- dw.title_data.indirected_text.size=strlen(d->title);
- dw.extent.x1=d->x;
- dw.extent.y1=d->y;
- dw.visible.y1=y-INSET-overlap;
- dw.visible.y0=dw.visible.y1-(dw.extent.y1-dw.extent.y0);
- if(dw.visible.y0<INSET) dw.visible.y0=INSET;
- dw.yscroll=dw.extent.y1;
- dw.visible.x1=x-INSET-overlap/2;
- dw.visible.x0=dw.visible.x1-d->x;
- if(dw.visible.x0<INSET) dw.visible.x0=INSET;
- v->w=wimp_create_window(&dw);
- v->next=d->viewlist;
- d->viewlist=v;
- block.open.w=v->w;
- wimp_get_window_state((wimp_window_state*)&block);
- wimp_open_window((wimp_open*)&block);
- overlap+=40;
- return TCL_OK;
- }
- /* *********** save a diagram *************** */
- if(!strcmp(argv[2],"save"))
- { if(argc!=4) return wrong(WNA,"w_draw <name> <save> <filename>");
- diagram_save(d,argv[3]);
- return TCL_OK;
- }
- /* *********** delete an object *************** */
- if(!strcmp(argv[2],"delete"))
- { os_box bb=empty;
- int m;
- for(m=3;m<argc;m++)
- { obj=findobj(d,atoi(argv[m]));
- if(obj)
- { unlink(&(d->objects),obj);
- enlarge(&bb,&(obj->bb));
- dispose(obj);
- }
- force_redraw(d,&bb);
- }
- return TCL_OK;
- }
- thisdiagram=d;
- /* *********** add new object above object n *************** */
- if(!strcmp(argv[2],"above"))
- { object *obj1;
- if(argc<5) return wrong(WNA,"w_draw <name> after <n> <object>");
- obj=getobject(argc-4,argv+4);
- if(!obj) return TCL_ERROR;
- obj1=findobj(d,atoi(argv[3]));
- if(!obj1)
- { if(!d->objects) goto firstobj;
- for(obj1=d->objects;obj1->next;obj1=obj1->next);
- }
- obj->next=obj1->next;
- obj1->next=obj;
- goto newobj;
- }
- /* *********** add new object *************** */
- obj=getobject(argc-2,argv+2);
- if(!obj) return TCL_ERROR;
- firstobj:obj->next=d->objects;
- d->objects=obj;
- newobj:force_redraw(d,&(obj->bb));
- obj->n=d->n;
- sprintf(interp->result,"%d",d->n++);
- return TCL_OK;
- }
-
-