home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
programming
/
tcl
/
tclsrc
/
c
/
WimpInit
< prev
next >
Wrap
Text File
|
1996-03-21
|
25KB
|
1,019 lines
/* Wimp commands for tcl */
/* (c) C.T.Stretch */
/* Sat,25 Jun 1994 */
#include "h.WInt"
#include "h.osbyte"
#include "h.taskwindow"
#include "h.taskmanager"
#include "h.RISCOSint"
/* Return value from catch if a send script returns an error */
#define TCL_REMOTEERROR 5
/* Message numbers for the Tcl w_send protocol */
#define message_TCL_SCRIPT 0x4cd40
#define message_TCL_RESULT 0x4cd41
/* The content of the messsages */
typedef struct wimp_message_tcl
{ char *source;
int len;
int resultcode;
} wimp_message_tcl;
/* A list of these holds the scripts to be run on null events */
typedef struct nullscript
{ struct nullscript *next;
os_t when;
char *name;
char *script;
} nullscript;
char progname[PNSIZE+1]; /* Program name passed to w_Init */
Tcl_Interp *w_Interp; /* The interpreter used by all w_ commands */
wimp_block block; /* Block used when calling wimp SWIs */
char *substr[26]; /* Points to the % substitution strings*/
char subbuffer[128]; /* Holds the values of % substitutions*/
int current_ex,current_ey; /* Mode information */
wimp_t taskhandle;
static int wimpmessages[]={ message_DATA_LOAD,
message_DATA_SAVE_ACK,
message_MENU_WARNING,
message_TASK_WINDOW_OUTPUT,
message_TASK_WINDOW_EGO,
message_TASK_WINDOW_MORIO,
message_TASK_WINDOW_NEW_TASK,
message_MODE_CHANGE,
message_PALETTE_CHANGE,
message_TCL_SCRIPT,
message_TCL_RESULT,
0 };
static bits mask=wimp_MASK_NULL;
static char *iconbar_clickproc,*iconbar_dragproc; /* tcl scripts */
static int fontcount[256]; /* usage count of fonts */
static osspriteop_area *userarea;
static nullscript* nullscripts; /* The list of nullscripts */
static os_t nulltime; /* Time for next null event */
/*
* msg --
*
* Reports an error consisting of at most three strings in a wimp
* error box. The strings are concatenated and truncated to 250
* characters.
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
void msg(char *s1,char *s2,char *s3)
{ os_error e;
int n=0;
e.errnum=0;
if(s1&&n<250) n+=sprintf(e.errmess,"%.*s",250-n,s1);
if(s2&&n<250) n+=sprintf(e.errmess+n,"%.*s",250-n,s2);
if(s2&&n<250) n+=sprintf(e.errmess+n,"%.*s",250-n,s3);
wimp_report_error(&e,wimp_ERROR_BOX_OK_ICON,progname);
}
/*
* wrong --
*
* Appends one or two strings to the result
*
* Results:
* Returns TCL_ERROR.
*
* Side effects:
* Changes w_Interp->result
*
*/
int wrong(char *m1,char *m2)
{ Tcl_AppendResult(w_Interp,m1,m2,0);
return TCL_ERROR;
}
/*
* wrong0 --
*
* Appends one or two strings to the result
*
* Results:
* Returns 0.
*
* Side effects:
* Changes w_Interp->result
*
*/
void *wrong0(char *m1,char *m2)
{ Tcl_AppendResult(w_Interp,m1,m2,0);
return 0;
}
/*
* spriteinfo --
* Finds the sprite area and size of a named sprite
* in os units if os is TRUE, otherwise pixels.
*
* Results:
* Copies the size into xx and yy.
* Returns a sprite area pointer, 1 for the wimp area, 0 for not found.
*
* Side effects:
* None.
*
*/
osspriteop_area *spriteinfo(char *s,int *xx,int *yy,bool os)
{ int x=68,y=68,ex=0,ey=0;
os_mode m;
osspriteop_area *area=0;
if(userarea&&
!xosspriteop_read_sprite_size(
osspriteop_USER_AREA,userarea,(osspriteop_id)s,&x,&y,0,&m))
area=userarea;
else
if(!xwimpspriteop_read_sprite_size(s,&x,&y,0,&m)) area=(osspriteop_area*)1;
if(area&&os)
{ os_read_mode_variable(m,os_MODEVAR_XEIG_FACTOR,&ex);
os_read_mode_variable(m,os_MODEVAR_YEIG_FACTOR,&ey);
*xx=x<<ex;
*yy=y<<ey;
}
else
{ *xx=x;
*yy=y;
}
return area;
}
/*
* modeinfo --
* Reads mode iformation for the currrent mode.
*
* Results:
* Sets current_ex and current_ey.
*
* Side effects:
* None.
*
*/
void modeinfo(void)
{ os_read_mode_variable(os_CURRENT_MODE,os_MODEVAR_XEIG_FACTOR,¤t_ex);
os_read_mode_variable(os_CURRENT_MODE,os_MODEVAR_YEIG_FACTOR,¤t_ey);
}
/*
* find_font --
*
* Searches for a font. The name is given in the form
* <font> = f<name>?@<length>? or F<fontname>?@<length>?
* If the length is not given the size is taken from the
* variable size in 16ths of a point.
* If the font cannot be found Trinity.Medium is used at the
* required size. If this cannot be found 0 is returned.
* The boolean table t records the fonts used in a particular document
* or drawfile, so that they can be lost when it is closed.
* The array fontcount holds the number of such tables keeping
* a particular font.
*
* Results:
* Returns a font handle or 0.
*
* Side effects:
* May open a font. If it does and t->used[handle] is zero it sets
* t->used[handle] to 1 and increments fontcount[handle]. Otherwise
* it loses the font again, so that the program only contributes
* use 1 to the *fontlist table.
*
*/
font_f find_font(char *name,int size,font_table *t)
{ font_f fontf;
char *fname;
char *p=strchr(name,'@');
if(p)
{ size=getsize(p+1,16*72);
*p=0; /* Terminates the font name temporarily */
}
switch(*name)
{ case 'f':fname=Tcl_GetVar2(w_Interp,"fonts",name+1,TCL_GLOBAL_ONLY);
break;
case 'F':fname=name+1;
break;
default:fname=0;
}
if(!fname||xfont_find_font(fname,size,size,0,0,&fontf,0,0))
{ if(xfont_find_font("Trinity.Medium",size,size,0,0,&fontf,0,0))
fontf=0;
}
if(fontf)
{ if(t->used[fontf]) font_lose_font(fontf);
else
{ t->used[fontf]=1;
if(fontcount[fontf]>0) font_lose_font(fontf);
fontcount[fontf]++;
}
}
if(p) *p='@'; /* Restores the size part of the name */
return fontf;
}
/*
* wimp_losefont --
*
* Reduces the number of documents using a font.
* If it becomes zero lose the font.
*
* Results:
* None.
*
* Side effects:
* Decrements fontcount[fontf]. May lose a font.
*
*/
static void wimp_losefont(font_f fontf)
{ fontcount[fontf]--;
if(fontcount[fontf]==0) font_lose_font(fontf);
}
/*
* release_fonts --
*
* Lose all the fonts from a document.
*
* Results:
* None.
*
* Side effects:
* Decrements fontcounts. May lose fonts.
* Does not zero ft->usage. It is called when the document is closed!
*
*/
extern void release_fonts(font_table *ft)
{ int i;
for(i=1;i<256;i++) if(ft->used[i]) wimp_losefont(i);
}
/*
* lose_all_fonts --
*
* Closes all fonts when the program exits. (called by an atexit procedure)
*
* Results:
* None.
*
* Side effects:
* Closes all fonts.
*
*/
static void lose_all_fonts(void)
{ font_f i;
for(i=1;i<255;i++) if(fontcount[i]>0) font_lose_font(i);
}
/*
* getcolour --
*
* Translates a textual description of a colour
* "none" gives -1 (transparent)
*
* Results:
* returns a colour (may have odd bottom byte if the text is incorrect)
*
* Side effects:
* None.
*
*/
os_colour getcolour(char *s)
{ int r=0,g=0,b=0;
if(!strcmp(s,"none")) return os_COLOUR_TRANSPARENT;
if(*s<'0'||*s>'9')
{ s=Tcl_GetVar2(w_Interp,"colours",s,TCL_GLOBAL_ONLY);
if(!s) return 0;
}
r=strtol(s,&s,10);
if(*s==':') g=strtol(++s,&s,10);
if(*s==':') b=strtol(++s,&s,10);
return r<<8|g<<16|b<<24;
}
/*
* getconstant --
*
* Reads a small integer constant, possiby given as a name.
*
* Results:
* returns an integer (-1 for unknown)
*
* Side effects:
* None.
*
*/
int getconstant(char *s)
{ switch(s[0])
{ case 0:return 0;
case '0':case'1':case'2':case'3':return s[0]-'0';
case 'c':if(!strcmp(s,"close")) return 0;
case 'o':if(!strcmp(s,"off")) return 0;
if(!strcmp(s,"on")) return 1;
break;
case 'f':if(!strcmp(s,"failclose")) return 2;
if(!strcmp(s,"failshow")) return 3;
break;
case 's':if(!strcmp(s,"show")) return 1;
break;
case 'h':if(!strcmp(s,"hide")) return 2;
break;
}
return -1;
}
/*
* unlink --
*
* Removes an object from a linked list.
* The first field of the list structure must be the next pointer.
* The list must be terminated with a zero pointer.
* l points to a place holding a pointer to the first object in the list
* v points to the object to be removed.
*
* Results:
* None.
*
* Side effects:
* Object removed from list - error if object not on list
*
*/
void unlink(void *l,void *v)
{ view *w;
for(w=l;w->next;w=w->next) if(w->next==v)
{ w->next=((view*)v)->next;
return;
}
msg("unlink failed",0,0);
}
/*
* screensize --
*
* Places the screen size in os units in x and y
*
* Results:
* None.
*
* Side effects:
* Changes the contents of x and y.
*
*/
void screensize(int *x,int *y)
{ int ib[]={ os_MODEVAR_XEIG_FACTOR,os_MODEVAR_YEIG_FACTOR,
os_MODEVAR_XWIND_LIMIT,os_MODEVAR_YWIND_LIMIT,-1
};
int ob[4];
os_read_vdu_variables((os_vdu_var_list*)ib,ob);
*x=(ob[2]+1)<<ob[0];
*y=(ob[3]+1)<<ob[1];
}
/*
* W_Error --
*
* Sets the tcl global variable "where" to the input string.
* Interpets the script pointed to by errorproc if there is
* one. Otherwise exits.
* If the errorproc script gives an error it displays a wimp error box
* and then exits.
*
* Results:
* None.
*
* Side effects:
* May interpret a script or exit.
*
*/
void W_Error(char *where)
{ char *errorproc;
Tcl_SetVar2(w_Interp,"w_where",0,where,TCL_GLOBAL_ONLY);
errorproc=Tcl_GetVar2(w_Interp,"w_debug",0,TCL_GLOBAL_ONLY);
if(errorproc)
{ if(Tcl_Eval(w_Interp,errorproc))
{ msg("Quitting after error in w_debug:- ",w_Interp->result,0);
exit(0);
}
}
else exit(0);
}
/*
* checkEval --
*
* Performs % substitution on the tcl script "s". Then evaluates it.
* calls W_Error with "where" passed on if it fails.
*
* Results:
* None.
*
* Side effects:
* Interprets a script
*
*/
void checkEval(char *s,char *where)
{ int code;
char *p,*q=0,*r;
int c;
int n=0,m=0;
for(p=s;*p;p++) if(*p=='%') /* find the length of the sustituted string */
{ c=*++p;
m++;
if(c==0) break;
c-='a';
if((c>=0&&c<26)&&substr[c]) n+=strlen(substr[c]);
}
if(m) /* copy s with substitution if needed */
{ q=ckalloc(strlen(s)+1+n-m); /* space for new s */
p=s;r=q;
for(p=s;*p;p++) if(*p=='%')
{ c=p[1]-'a';
if(c>=0&&c<26)
{ p++;
if(substr[c])
{ n=strlen(substr[c]);
strcpy(r,substr[c]);
r+=n;
}
}
}
else *r++=*p;
*r=0;
s=q;
} /* script pointed to by s in either case */
code=Tcl_Eval(w_Interp,s);
if(code!=TCL_OK&&code!=TCL_RETURN) W_Error(where);
ckfree(q); /* q may be zero! */
}
/*
* scopy --
*
* make a new string identical to the input
*
* Results:
* Returns the new string
*
* Side effects:
* Calls malloc.
*
*/
char *scopy(char *in)
{ char *out=ckalloc(strlen(in)+1);
strcpy(out,in);
return out;
}
/*
* gettime --
*
* Reads a time in centiseconds from a string.
*
* Results:
* Returns the time or -1 for a bad time.
*
* Side effects:
* None.
*
*/
static os_t gettime(char *s)
{ double d;
if(!*s) return -1;
d=strtod(s,&s);
switch(*s)
{ case 'c':break;
case 's':d=d*100;break;
case 'm':d=d*6000;break;
case 'h':d=d*360000;break;
case 'd':d=d*360000*24;break;
default:return -1;
}
return (os_t)d;
}
/*
* addnull --
*
* Insert an entry in the null scripts list .
*
* Results:
* None.
*
* Side effects:
* Adjusts the nullscript list.
*
*/
static void freenull(nullscript *n)
{ ckfree(n->name);ckfree(n->script);
ckfree(n);
nulltime=(nullscripts)?(nullscripts->when):0;
if(!nullscripts) mask|=wimp_MASK_NULL;
}
static void addnull(os_t when,nullscript* n)
{ nullscript **s=(nullscript**)&nullscripts;
when+=os_read_monotonic_time();
for(;*s&&(*s)->when<=when;s=&((*s)->next));
n->next=*s;
*s=n;
n->when=when;
nulltime=(nullscripts)?(nullscripts->when):0;
}
/*
* null --
*
* Called on a null event.
*
* Results:
* None.
*
* Side effects:
* Runs a script. Adjusts the nullscript list.
*
*/
static void null(void)
{ if(nullscripts)
{ nullscript *now=nullscripts;
os_t again;
nullscripts=now->next;
checkEval(now->script,now->name);
again=gettime(w_Interp->result);
if(again<0) freenull(now);
else addnull(again,now);
}
}
/*
* setbutton --
*
* Sets the %b substitution string according to the state of the mouse
* buttons and the modifier keys.
*
* Results:
* None.
*
* Side effects:
* Changes substr[1].
*
*/
void setbutton(void)
{ char *p=substr['b'-'a'];
int k=osbyte_read(osbyte_VAR_KEYBOARD_STATE);
if(block.pointer.buttons&wimp_CLICK_ADJUST) *p++='a';
if(block.pointer.buttons&wimp_CLICK_SELECT) *p++='s';
if(k&8) *p++='S';
if(k&64) *p++='C';
*p=0;
}
/*
* mouse --
*
* Deals with mouse click events from wimp_poll.
* Calls menu_open for a menu click.
* Otherwise calls box_click. If this returns
* FALSE it calls diagram_click. If this also returns FALSE it
* checks for an iconbar click, sets the %b substitution
* and interprets the iconbar-click script.
*
* Results:
* None.
*
* Side effects:
* May interpret a script, or change substr[1] via setbutton.
*
*/
static void mouse(void)
{ if(block.pointer.buttons==wimp_CLICK_MENU) {menu_open();return;}
if(box_click()) return;
if(diagram_click()) return;
if(block.pointer.w==wimp_ICON_BAR)
{ if(iconbar_clickproc)
{ setbutton();
checkEval(iconbar_clickproc,"iconbar click");
}
return;
}
}
/*
* runs a script sent by another application with send --
*
* Results:
* None.
*
* Side effects:
* Interprets a script
*
*/
static void runscript(wimp_message *m)
{ wimp_message_tcl *t=(wimp_message_tcl *)&(m->data.data_request);
wimp_t sender=m->sender;
int your_ref=m->my_ref;
char *s=ckalloc(t->len);
int code;
xwimp_transfer_block(sender,(byte*)(t->source),taskhandle,(byte*)s,t->len);
code=Tcl_GlobalEval(w_Interp,s);
ckfree(s);
m->size=32;
m->your_ref=your_ref;
m->action=message_TCL_RESULT;
t->source=w_Interp->result;
t->len=strlen(w_Interp->result)+1;
t->resultcode=code;
xwimp_send_message(wimp_USER_MESSAGE,m,sender);
}
/*
* message --
* Deals with wimp message events from wimp poll, mainly by
* calling the relevant procedure.
* Handles drags to the iconbar by setting the w_file variable
* and the %t substitution before evaluating the script.
*
* Results:
* None.
*
* Side effects:
* May interpret a script
*
*/
static void message(void)
{ wimp_message *m=&(block.message);
switch(m->action)
{ case message_QUIT:exit(0);
case message_DATA_LOAD:
{ wimp_message_data_request *dr=&(m->data.data_request);
if(dr->w==wimp_ICON_BAR)
{ if(iconbar_dragproc);
{ Tcl_SetVar2(w_Interp,"w_file",0,
(char*)(dr->file_types+1),TCL_GLOBAL_ONLY);
sprintf(substr['t'-'a'],"%d",dr->file_types[0]);
checkEval(iconbar_dragproc,"file drag");
}
break;
}
if(box_dragload(m)) break;
}
break;
case message_MENU_WARNING:
{ wimp_message_menu_warning *mw=(void*)&(m->data.reserved);
box_submenu(mw->sub_menu,substr['w'-'a'],mw->pos.x,mw->pos.y);
}
break;
case message_DATA_SAVE_ACK:box_dragsave(m);break;
case message_TASK_WINDOW_OUTPUT:
case message_TASK_WINDOW_EGO:
case message_TASK_WINDOW_MORIO:
case message_TASK_WINDOW_NEW_TASK:task_message(m);break;
case message_MODE_CHANGE:diagram_modechange();break;
case message_PALETTE_CHANGE:diagram_palettechange();break;
case message_TCL_SCRIPT:runscript(m);break;
}
}
/*
* W_Poll --
* Calls wimp poll and calls a suitable procedure to handle the
* result.
*
* Results:
* None.
*
* Side effects:
* Various.
*
*/
void W_Poll(void)
{ int e;
if(!w_Interp) return;
for(;;)
{ e=wimp_poll_idle(mask,&block,nulltime,0);
switch(e)
{ case wimp_NULL_REASON_CODE:null();break;
case wimp_REDRAW_WINDOW_REQUEST:if(document_redraw()) break;
if(diagram_redraw()) break;
break;
case wimp_OPEN_WINDOW_REQUEST:wimp_open_window(&block.open);break;
case wimp_CLOSE_WINDOW_REQUEST:if(diagram_close()) break;
if(document_close()) break;
if(box_close()) break;
wimp_close_window(block.close.w);
break;
case wimp_MOUSE_CLICK:mouse();break;
case wimp_USER_DRAG_BOX:box_dragged();break;
case wimp_KEY_PRESSED:if(box_key()) break;
wimp_process_key(block.key.c);
break;
case wimp_MENU_SELECTION:menu_select();break;
case wimp_USER_MESSAGE:
case wimp_USER_MESSAGE_RECORDED:message();break;
}
}
}
/*
* w_SendCmd --
* Implements the w_send command
*
* Results:
* A standard Tcl result.
*
* Side effects:
*
*
*/
static int w_SendCmd(ClientData dummy,Tcl_Interp *interp,int argc,char **argv)
{ taskmanager_task tk;
wimp_message *m=&(block.message);
wimp_message_tcl *t=(wimp_message_tcl *)&(m->data.data_request);
int more=0;
int e;
if(argc!=3) return wrong(WNA,"w_send <taskname> <script>");
for(;;)
{ xtaskmanager_enumerate_tasks(more,&tk,sizeof(taskmanager_task),&more,0);
if(!strcmp(tk.name,argv[1])) break;
if(more<0) return wrong("Can't find task named ",argv[1]);
}
m->size=28;
m->your_ref=0;
m->action=message_TCL_SCRIPT;
t->source=argv[2];
t->len=strlen(argv[2])+1;
xwimp_send_message(wimp_USER_MESSAGE,m,tk.task);
for(;;)
{ e=wimp_poll(0x2173,&block,0);
if(e==wimp_USER_MESSAGE||e==wimp_USER_MESSAGE_RECORDED)
{ m=&(block.message);
if(m->action==message_TCL_RESULT)
{ wimp_message_tcl *t=(wimp_message_tcl *)&(m->data.data_request);
char *res=ckalloc(t->len);
xwimp_transfer_block(tk.task,(byte*)(t->source),taskhandle,
(byte*)res,t->len);
Tcl_SetResult(w_Interp,res,TCL_DYNAMIC);
if(t->resultcode==TCL_ERROR) return TCL_REMOTEERROR;
return t->resultcode;
}
message();continue;
}
switch(e)
{ case wimp_LOSE_CARET:/* Deliberate fall through */
case wimp_GAIN_CARET:continue;
case wimp_OPEN_WINDOW_REQUEST:wimp_open_window(&block.open);break;
case wimp_CLOSE_WINDOW_REQUEST:if(diagram_close()) break;
if(document_close()) break;
if(box_close()) break;
wimp_close_window(block.close.w);
break;
case wimp_USER_DRAG_BOX:box_dragged();break;
case wimp_MENU_SELECTION:menu_select();break;
}
return wrong("No reply to send from ",argv[1]);
}
}
/*
* w_BarCmd --
* Implements the w_bar command
*
* Results:
* A standard Tcl result.
*
* Side effects:
* May make a menu or set iconbar_clickproc or iconbar_dragproc.
* Puts an icon on the bar.
*
*/
static int w_BarCmd(ClientData dummy,Tcl_Interp *interp,int argc,char **argv)
{ wimp_icon_create ic;
int i;
int x=68,y=68,ex=0,ey=0;
os_mode m;
for(i=1;i<argc-1;i++)
{ if(!strcmp(argv[i],"-menu"))
{ tcl_menu *tm;
tm=menu_make(argv[++i],"bar");
if(!tm) return TCL_ERROR;
menu_bar(tm);
continue;
}
if(!strcmp(argv[i],"-click"))
{ iconbar_clickproc=scopy(argv[++i]);
continue;
}
if(!strcmp(argv[i],"-drag"))
{ iconbar_dragproc=scopy(argv[++i]);
continue;
}
return wrong("Unknown w_bar option: ",argv[i]);
}
sprintf(ic.icon.data.text,"!%s",progname);
if(!xwimpspriteop_read_sprite_size(ic.icon.data.text,&x,&y,0,&m))
{ os_read_mode_variable(m,os_MODEVAR_XEIG_FACTOR,&ex);
os_read_mode_variable(m,os_MODEVAR_YEIG_FACTOR,&ey);
}
ic.w=wimp_ICON_BAR_RIGHT;
ic.icon.extent.x0=0;ic.icon.extent.y0=0;
ic.icon.extent.x1=x<<ex;ic.icon.extent.y1=y<<ey;
ic.icon.flags=wimp_ICON_SPRITE|
(wimp_BUTTON_CLICK<<wimp_ICON_BUTTON_TYPE_SHIFT);
wimp_create_icon(&ic);
return TCL_OK;
}
/*
* w_NullCmd --
* Implements the w_null command
*
* Results:
* A standard Tcl result.
*
* Side effects:
* May insert or remove an entry in the nullscript list.
* Can change the wimp mask.
*
*/
static int w_NullCmd(ClientData dummy,Tcl_Interp *interp,int argc,char **argv)
{ if(argc<2||argc>4) return wrong(WNA,"w_null <name> ?<script> ?<time>??");
if(argc==2)
{ nullscript *w=(nullscript*)&nullscripts;
for(;w->next;w=w->next) if(!strcmp(w->next->name,argv[1]))
{ nullscript *n=w->next;
w->next=(w->next)->next;
freenull(n);
break;
}
}
else
{ os_t when=100;
nullscript *n;
if(argc==4) when=gettime(argv[3]);
if(when<0) return wrong("Bad time ",argv[3]);
n=ckalloc(sizeof(nullscript));
n->name=scopy(argv[1]);
n->script=scopy(argv[2]);
addnull(when,n);
mask&=~wimp_MASK_NULL;
}
return TCL_OK;
}
/*
* w_ErrorCmd --
* Implements the w_error command.
*
* Results:
* A standard tcl result.
*
* Side effects:
* Displays an error box.
*
*/
static int w_ErrorCmd(ClientData dummy,Tcl_Interp *interp,int argc,char **argv)
{ os_error e;
bits flags=0;
int i;
e.errnum=0;
if(argc>1) sprintf(e.errmess,"%.200s",argv[1]);
else e.errmess[0]=0;
for(i=2;i<argc;i++)
{ if(!strcmp(argv[i],"-ok")) { flags|=wimp_ERROR_BOX_OK_ICON;continue;}
if(!strcmp(argv[i],"-cancel")) flags|=wimp_ERROR_BOX_CANCEL_ICON;
}
flags=wimp_report_error(&e,flags,progname);
sprintf(interp->result,"%u",2-flags);
return TCL_OK;
}
/*
* getsprites --
* Load a sprite file into the user area
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
static void getsprites(char *name)
{ char buf[256];
int n;
os_error *e;
sprintf(buf,"<%s$Dir>.%.200s",progname,name);
n=flen(buf);
if(n<0) { msg("Couldn't find ",buf,0); return;}
userarea=ckalloc(n+4);
userarea->size=n+4;
userarea->sprite_count=0;
userarea->first=sizeof(osspriteop_area);
userarea->used=sizeof(osspriteop_area);
e=xosspriteop_load_sprite_file(osspriteop_USER_AREA,userarea,buf);
if(e) wimp_report_error(e,wimp_ERROR_BOX_OK_ICON,progname);
}
/*
* w_InitCmd --
* Implements the w_init command.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Sets w_Interp, progname,taskhandle.
* Creates the other w_ commands.
* Sets up the buffers to hold % substitutions.
* Sets up exit handlers to lose fonts and kill any tasks still running.
* Initialises variables w_debug and w_version
*
*/
int W_InitCmd(ClientData dummy,Tcl_Interp *interp,int argc,char **argv)
{ int version;
if(argc<2||argc>3) return wrong(WNA,"w_init name ?sprites?");
if(w_Interp) return wrong("w_init may only be called once",0);
w_Interp=interp;
strncpy(progname,argv[1],PNSIZE);progname[PNSIZE]=0;
Tcl_InitHashTable(&documentTable,TCL_STRING_KEYS);
Tcl_InitHashTable(&diagramTable,TCL_STRING_KEYS);
Tcl_InitHashTable(&boxTable,TCL_STRING_KEYS);
Tcl_InitHashTable(&taskTable,TCL_STRING_KEYS);
Tcl_CreateCommand(interp,"w_bar",w_BarCmd,NULL,NULL);
Tcl_CreateCommand(interp,"w_error",w_ErrorCmd,NULL,NULL);
Tcl_CreateCommand(interp,"w_text",w_TextCmd,NULL,NULL);
Tcl_CreateCommand(interp,"w_draw",w_DrawCmd,NULL,NULL);
Tcl_CreateCommand(interp,"w_box",w_BoxCmd,NULL,NULL);
Tcl_CreateCommand(interp,"w_task",w_TaskCmd,NULL,NULL);
Tcl_CreateCommand(interp,"system",w_SystemCmd,NULL,NULL);
Tcl_CreateCommand(interp,"w_send",w_SendCmd,NULL,NULL);
Tcl_CreateCommand(interp,"w_null",w_NullCmd,NULL,NULL);
Tcl_CreateCommand(interp,"w_info",w_InfoCmd,NULL,NULL);
taskhandle=wimp_initialise(wimp_VERSION_RO3,progname,
(wimp_message_list*)wimpmessages,&version);
sprintf(interp->result,progname);
substr['x'-'a']=subbuffer;
substr['y'-'a']=subbuffer+12;
substr['t'-'a']=subbuffer+24;
substr['b'-'a']=subbuffer+36;
atexit(lose_all_fonts);
atexit(task_killall);
modeinfo();
Tcl_SetVar2(w_Interp,"w_debug",0,
"if {![w_error \"Error in $w_where :- $errorInfo\" -ok -cancel]} exit",
TCL_GLOBAL_ONLY);
Tcl_SetVar2(w_Interp,"w_version",0,W_VERSION,TCL_GLOBAL_ONLY);
if(argc==3) getsprites(argv[2]);
return TCL_OK;
}