home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
programming
/
tcl
/
tclsrc
/
c
/
WimpBox
< prev
next >
Wrap
Text File
|
1996-03-10
|
30KB
|
1,054 lines
/* Dialog box commands for tcl */
/* (c) C.T.Stretch */
/* Mon,08 Aug 1994 */
#include "tclInt.h"
#undef UCHAR
#include "h.wimp"
#include "h.WInt"
#include "h.RISCOSint"
#include "h.dragasprite"
enum ictypes { IHLIST,IVLIST,IBOX,ISPRITE,ISAVE,IACTION,IDEFAULT,
IINFO,IDISPLAY,IWATCH,IOPTION,IRADIO,IWRITE,ILAST};
/*Note ictypes>ISAVE are equalised*/
/*Note ictypes>IDEFAULT have 4? parameters*/
typedef struct icdata
{ char *t; /*Name*/
int w,h,n; /*Width, height, no. of icons*/
} icdata;
icdata icd[ILAST]=
{ {"hlist", 0 ,0 ,0},
{"vlist", 0 ,0 ,0},
{"box", 0 ,0 ,2},
{"sprite", 100,100,1},
{"save", 192,176,2},
{"action", 28 ,60 ,1},
{"default",44 ,76 ,1},
{"info", 80 ,60 ,2},
{"display",80 ,60 ,2},
{"watch" ,80 ,60 ,2},
{"option", 60 ,52 ,1},
{"radio", 60 ,52 ,1},
{"write", 80 ,68 ,2}
};
#define GAP 8
#define HALFGAP (GAP/2)
#define CHWIDTH 16
enum actions { ANONE,AACTION,ADISPLAY,AWATCH,
AOPTION,ARADIO1,ARADIO2,AWRITE,ADRAG};
static wimp_window progInfo=
{ {0,0,0,0},
0, 0, (wimp_w)-1, 0x84000012,
0x7, 0x2, 0x7, 0x1,
0xc, 0xe, 0xc, 0x0,
{0,0,0,0},
0x13d, 0x0, (osspriteop_area*)0x1, 0, 0,
"",
0
};
#define TRACEFLAGS TCL_TRACE_WRITES|TCL_GLOBAL_ONLY
#define BSIZE(n) ((int)sizeof(boxnode)+(n-1)*(int)sizeof(boxnode*))
#define WSIZE(n) ((int)sizeof(wimp_window)+(n-1)*(int)sizeof(wimp_icon))
typedef struct boxnode /* A node of the tree used to parse dbox descriptions */
{ int type; /* object type from enum ictypes */
int w,h; /* width and height in os units */
int n1,n2,n3,n4; /* integers describing object */
char *s1,*s2,*s3; /* strings describing object */
struct boxnode *blist[UNKNOWN]; /* subobjects */
} boxnode;
typedef struct dbox /* A permanent object describing a dbox */
{ wimp_window *ww; /* window template */
int *t; /* list of action types */
char **s; /* list of script strings */
char *d; /* script for default icon */
char *e; /* script for Cancel icon */
bool tagged; /* TRUE for tagged dbox*/
int c; /* icon to place caret (-1 for none)*/
} dbox;
typedef struct openbox /* A list of these describes the open dboxes */
{ struct openbox *next; /* linkedlist pointer */
wimp_w w; /* window handle */
char *tag; /* dbox tag */
dbox *db; /* the dbox that this is an instance of */
} openbox;
typedef struct watchdata
{ struct watchdata *next;
openbox *ob;
int ic;
} watchdata;
Tcl_HashTable boxTable;
static openbox *openboxlist;
static watchdata *watchdatalist;
/* variables that hold information about an icon drag */
static char *dragleaf,*dragscript;
static int dragtype;
static openbox *dragopenbox;
/* vertical position to open a permanent dbox. */
static int offset=600;
/*The remaining variables are used temporarily during dbox creation */
static int nicons,inum;
static int *dbt;
static char **dbs;
static char *dd,*ee;
static char *esg[16];
static int esg_first;
static wimp_icon *nexticon;
static int careticon;
#define USFLAGS osspriteop_USER_AREA|osspriteop_NAME
#define SSFLAGS osspriteop_NAME
static char *update(ClientData,Tcl_Interp*,char*,char*,int);
/*static void ckpfree(void *p) { fprintf(stderr,"free p=%p\n",p);ckfree(p);}*/
/*
* box_find --
* Looks up the name of a dbox in the hash table.
* Returns 0 if not found or a pointer to the structure.
* Result is void* so the dbox structures need not be defined
* outside this file.
*
* Results:
* Returns a pointer to a dbox or 0.
*
* Side effects:
* None.
*
*/
extern void *box_find(char *name)
{ Tcl_HashEntry *p;
p=Tcl_FindHashEntry(&boxTable,name);
if(!p) return 0;
return Tcl_GetHashValue(p);
}
static void freebox(openbox *ob)
{ dbox *db=ob->db;
int ni=db->ww->icon_count;
int i;
wimp_window *ww=db->ww;
for(i=0;i<ni;i++) switch(db->t[i])
{ case AWATCH:{ watchdata *wd;
for(wd=watchdatalist;wd;wd=wd->next) if(wd->ob==ob&&wd->ic==i)
{ Tcl_UntraceVar2(w_Interp,db->s[i],ob->tag,TRACEFLAGS,
update,(ClientData)wd);
unlink(&watchdatalist,wd);
ckfree(wd);
break; /* from for loop */
}
}
/*Deliberate fall through*/
case ADISPLAY:case AWRITE:
ckfree(ww->icons[i].data.indirected_text.text);
}
wimp_delete_window(ob->w);
unlink(&openboxlist,ob);
ckfree(ob->tag);
ckfree(ob);
substr['d'-'a']=0;
}
/*
* box_close --
* Called after a close event is returned from wimp_poll.
* If the window is a dialog box it is deleted and the openbox
* structure is removed from the list.
* Results:
* Returns true if the window was a dialog box.
*
* Side effects:
* None.
*
*/
bool box_close(void)
{ openbox *ob;
for(ob=openboxlist;ob;ob=ob->next)
if(ob->w==block.close.w)
{ freebox(ob);
return TRUE;
}
return FALSE;
}
/*
* closebox --
* Deletes a dialog box after a user selection.
* Removes it from the openbox list.
* Disposes of any open menu.
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
static void closebox(openbox *ob)
{ wimp_create_menu((wimp_menu*)-1,0,0);
freebox(ob);
}
/*
* getvars --
* Scans the objects of an open dialog box and sets the corresponding
* Tcl variables.
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
static void getvars(openbox *ob)
{ int i,j;
dbox *db=ob->db;
int ni=db->ww->icon_count;
wimp_window *ww=db->ww;
substr['d'-'a']=ob->tag;
for(i=0;i<ni;i++) switch(db->t[i])
{ case AOPTION:{ wimp_icon_state *wis=(wimp_icon_state*)█
bool b;
wis->w=ob->w;
wis->i=i;
wimp_get_icon_state(wis);
b=wis->icon.flags&wimp_ICON_SELECTED;
Tcl_SetVar2(w_Interp,db->s[i],ob->tag,
(b)?"1":"0",TCL_GLOBAL_ONLY);
break;
}
case ARADIO1:{ wimp_i *wi=(wimp_i*)█
wimp_which_icon(ob->w,wi,0x003f0000,
0x00200000|(ww->icons[i].flags&0x000f0000));
j=wi[0];
if(j>0)
Tcl_SetVar2(w_Interp,db->s[i],ob->tag,
ww->icons[j].data.indirected_text.text,TCL_GLOBAL_ONLY);
break;
}
case AWRITE:{ wimp_icon_state *wis=(wimp_icon_state*)█
wis->w=ob->w;
wis->i=i;
wimp_get_icon_state(wis);
Tcl_SetVar2(w_Interp,db->s[i],ob->tag,
wis->icon.data.indirected_text.text,TCL_GLOBAL_ONLY);
break;
}
}
}
/*
* box_key --
* Called after a key event is returned by wimp_poll.
* If the window is an open dialog box it takes the relevant action.
*
* Results:
* Returns TRUE if the window was a dbox and key dealt with.
*
* Side effects:
* None.
*
*/
bool box_key(void)
{ openbox *ob;
char *s;
for(ob=openboxlist;ob;ob=ob->next)
if(ob->w==block.key.w) switch(block.key.c)
{ case 13:s=ob->db->d;goto run ;
case 27:s=ob->db->e;goto run;
default:return FALSE;
}
run:if(s)
{ getvars(ob);
sprintf(substr['b'-'a'],"s");
checkEval(s,"key action");
if(!strcmp(w_Interp->result,"0")) closebox(ob);
}
return TRUE;
}
/*
* box_click --
* Called after a mouse (except menu) event is returned by wimp_poll.
* If the window is an open dialog box it takes the relevant action.
* For a drag event is starts a sprite drag, it sets the variables
* dragtype, dragscript, dragleaf and dragopenbox.
*
* Results:
* Returns TRUE if the window was a dbox.
*
* Side effects:
* None.
*
*/
extern bool box_click(void)
{ openbox *ob;
dbox *db;
for(ob=openboxlist;ob;ob=ob->next)
if(ob->w==block.pointer.w)
{ wimp_i ic=block.pointer.i;
wimp_window *ww;
db=ob->db;
if(block.pointer.buttons==wimp_DRAG_SELECT) switch(db->t[ic])
{ case ADRAG:{ os_box sbox;
wimp_window_state state[1];
wimp_icon_state *wis=(wimp_icon_state*)█
char *s;
ww=db->ww;
state->w=ob->w;
wimp_get_window_state(state);
sbox.x0=state->visible.x0+ww->icons[ic].extent.x0;
sbox.x1=sbox.x0+68;
sbox.y0=state->visible.y1+ww->icons[ic].extent.y0;
sbox.y1=sbox.y0+68;
dragasprite_start(
dragasprite_HPOS_CENTRE|dragasprite_VPOS_CENTRE|
dragasprite_BOUND_POINTER|dragasprite_DROP_SHADOW,
(osspriteop_area*)1,
ww->icons[ic].data.indirected_text.text,&sbox,0);
wis->w=ob->w;
wis->i=ic;
wimp_get_icon_state(wis);
dragtype=
(int)strtol(wis->icon.data.indirected_text.text+5,0,16);
wis->w=ob->w;
wis->i=ic+1;
wimp_get_icon_state(wis);
dragleaf=wis->icon.data.indirected_text.text;
s=strrchr(dragleaf,'.');
if(s) dragleaf=s+1;
dragscript=db->s[ic];
dragopenbox=ob;
}
}
else switch(db->t[ic])
{ case AACTION:if(db->s[ic]==0) closebox(ob);
else
{ setbutton();
getvars(ob);
checkEval(db->s[ic],"action button");
if(getconstant(w_Interp->result)==0) closebox(ob);
}
break;
}
return TRUE;
}
return FALSE;
}
/*
* box_dragged --
* Called after a user_drag_box event is returned from wimp_poll
* sends a data_save message to the window under the ponter.
* Stops the sprite drag.
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
void box_dragged(void)
{ wimp_pointer wp[1];
wimp_message wm;
if(!dragscript) return;
dragasprite_stop();
wimp_get_pointer_info(wp);
if(!wp->w) return;
wm.size=256;
wm.your_ref=0;
wm.action=message_DATA_SAVE;
wm.data.data_xfer.w=wp->w;
wm.data.data_xfer.i=wp->i;
wm.data.data_xfer.pos=wp->pos;
wm.data.data_xfer.est_size=0;
wm.data.data_xfer.file_type=dragtype;
sprintf(wm.data.data_xfer.file_name,dragleaf);
wimp_send_message_to_window(wimp_USER_MESSAGE_RECORDED,&wm,wp->w,wp->i);
}
/*
* box_dragsave --
* Called after the receipt of a data_save_acknowledge message.
* Sets the variables from dragopenbox.
* Sets w_file and the %t substitution.
* Evaluates dragscript.
* If dragscript indicates success returns a data_load message.
* If the script indicates closes the dbox
* Zeros dragopenbox and dragscript to avoid possible confusion
* from spurious messages.
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
void box_dragsave(wimp_message *m)
{ wimp_message_data_xfer *dx=&(m->data.data_xfer);
wimp_message wm;
wimp_t from=m->sender;
int res;
wm.size=256;
wm.your_ref=m->my_ref;
wm.action=message_DATA_LOAD;
wm.data.data_xfer=m->data.data_xfer;
if(!dragscript) return;
if(dragopenbox) getvars(dragopenbox);
Tcl_SetVar2(w_Interp,"w_file",0,dx->file_name,TCL_GLOBAL_ONLY);
sprintf(substr['t'-'a'],"%d",dx->file_type);
checkEval(dragscript,"save drag");
dragscript=0;
res=getconstant(w_Interp->result);
if(res<'2') wimp_send_message(wimp_USER_MESSAGE_RECORDED,&wm,from);
if(!(res&1)&&dragopenbox) closebox(dragopenbox);
dragopenbox=0;
}
/*
* box_dragload --
* Called in response to a wimp_dataload message.
* If the message is to a writeable icon in a dbox it copies the
* file name into the icon if it fits.
*
* Results:
* TRUE if the message was to a dbox.
*
* Side effects:
* None.
*
*/
bool box_dragload(wimp_message *m)
{ openbox *ob;
wimp_message_data_xfer *dx=&(m->data.data_xfer);
for(ob=openboxlist;ob;ob=ob->next)
if(ob->w==dx->w)
{ wimp_i ic=dx->i;
dbox *db=ob->db;
wimp_window *ww=db->ww;
if(ic>=0&&db->t[ic]==AWRITE)
{ int n=ww->icons[ic].data.indirected_text.size;
char *t=ww->icons[ic].data.indirected_text.text;
if(n>strlen(dx->file_name))
{ strcpy(t,dx->file_name);
wimp_set_icon_state(dx->w,ic,0,0);
}
}
return TRUE;
}
return FALSE;
}
/*
* freeboxtree --
* Frees the boxtree after a dbox has been created.
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
static void freeboxtree(boxnode *bn)
{ int i;
switch(bn->type)
{ case IHLIST:
case IVLIST:for(i=0;i<bn->n1;i++) freeboxtree(bn->blist[i]);
break;
case IBOX:freeboxtree(bn->blist[0]);
break;
}
ckfree(bn);
}
/*
* equalize --
* Scans a vertical or horizontal list node in the box tree.
* If consecutive objects of the same type are found their sizes
* are set to the maximum. Objects of type HLIST VLIST BOX and SPRITE
* are not considered, and are ignored when considering consecutiveness.
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
static void equalize(boxnode *bn,int n)
{ int i,j,k,gtype,n1,n2,n3=-1;
boxnode *gn;
for(i=0;i<n;i++)
{ gn=bn->blist[i];
if(gn->type>ISAVE)
{ if(gn->type==gtype)
{ if(gn->n1>n1) { n1=gn->n1;for(j=k;j<i;j++) bn->blist[j]->n1=n1;}
else gn->n1=n1;
if(gn->n2>n2) { n2=gn->n2;for(j=k;j<i;j++) bn->blist[j]->n2=n2;}
else gn->n2=n2;
if(gn->n3>n3) { n3=gn->n3;for(j=k;j<i;j++) bn->blist[j]->n3=n3;}
else gn->n2=n2;
}
else
{ gtype=gn->type;
n1=gn->n1;n2=gn->n2;n3=gn->n3;
k=i;
}
}
}
}
/*
* getboxtree --
* The construction of a dbox from a textual description proceeds
* in two stages. First a tree structure is constructed from the
* text. This is then used to make a dbox structure, including a
* window template with icon descriptions. This recursive procedure
* creates the boxtree.
*
* Results:
* Returns a node of a box tree or zero for error.
*
* Side effects:
* Uses some temporary global variables.
*
*/
static boxnode *getboxtree(char *desc)
{ boxnode *bn,*gn;
int nargs,i,type;
char **args;
if(Tcl_SplitList(w_Interp,desc,&nargs,&args)) return 0;
if(nargs<2) return wrong0(WNA,"<component> ...");
for(type=0;type<ILAST;type++) if(!strcmp(args[0],icd[type].t))break;
if(type>=ILAST) return wrong0("Unknown dbox component: ",args[0]);
switch(type)
{ case IHLIST:
case IVLIST:bn=ckalloc(BSIZE(nargs-1));
bn->n1=nargs-1;
for(i=0;i<nargs-1;i++)
{ bn->blist[i]=getboxtree(args[i+1]);
if(bn->blist[i]==0) return wrong0("empty vlist",0);
bn->w=0;bn->h=0;
}
break;
case IBOX:if(nargs!=3) return wrong0(WNA,"box <name> <component>");
bn=ckalloc(BSIZE(1));
bn->s1=scopy(args[1]);
bn->n1=strlen(bn->s1);
bn->blist[0]=getboxtree(args[2]);
if(bn->blist[0]==0) return wrong0("empty hlist",0);
bn->w=64+bn->blist[0]->w;
bn->h=72+bn->blist[0]->h;
if(bn->n1*CHWIDTH+80>bn->w) bn->w=bn->n1*CHWIDTH+80;
break;
case ISPRITE:bn=ckalloc(BSIZE(0));
bn->s1=scopy(args[1]);
bn->n1=(int)spriteinfo(bn->s1,&(bn->w),&(bn->h),TRUE);
if(bn->n1==0) bn->n1=1;
bn->w+=GAP;
bn->h+=GAP;
break;
case ISAVE:if(nargs!=4)
return wrong0(WNA,"save <filetype> <variable> <script>");
bn=ckalloc(BSIZE(0));
bn->n1=typenumber(args[1]);
if(bn->n1>=0&&bn->n1<4096)
{ bn->s1=ckalloc(9);
sprintf(bn->s1,"file_%03.3x",bn->n1);
}
else
{ char *s="file_xxx";
if(bn->n1==0x1000) s="directory";
if(bn->n1==0x2000) s="application";
bn->s1=scopy(s);
}
bn->s2=scopy(args[2]);
bn->s3=scopy(args[3]);
bn->w=192;
bn->h=176;
break;
default:bn=ckalloc(BSIZE(0));
if(nargs<3&&type>IDEFAULT)
return wrong0("Component requires more arguments: ",args[0]);
bn->n1=strlen(args[1]);
bn->n2=0;bn->n3=0;bn->n4=0;
bn->s1=scopy(args[1]);
bn->s2=(nargs==2)?0:scopy(args[2]);
bn->s3=0;
bn->h=icd[type].h;
}
nicons+=icd[type].n;
bn->type=type;
switch(type)
{ case IHLIST:equalize(bn,nargs-1);
for(i=0;i<nargs-1;i++)
{ gn=bn->blist[i];
if(gn->type>ISAVE)
gn->w=icd[gn->type].w+(gn->n1+gn->n2+gn->n3)*CHWIDTH;
bn->w+=gn->w;
if(gn->h>bn->h) bn->h=gn->h;
}
break;
case IVLIST:equalize(bn,nargs-1);
for(i=0;i<nargs-1;i++)
{ gn=bn->blist[i];
if(gn->type>ISAVE)
gn->w=icd[gn->type].w+(gn->n1+gn->n2+gn->n3)*CHWIDTH;
bn->h+=gn->h;
if(gn->w>bn->w) bn->w=gn->w;
}
break;
case IINFO:bn->n2=strlen(args[2]);
break;
case IDISPLAY:if(nargs>3) bn->n2=atoi(args[3]);
if(bn->n2<1) bn->n2=20;
break;
case IWRITE:case IWATCH:
if(nargs>3) bn->n2=atoi(args[3]);
if(nargs>4) bn->n4=atoi(args[4]);
if(bn->n2<1) bn->n2=20;
if(bn->n4<1) bn->n4=256;
break;
}
if(type>ISAVE) bn->w=icd[type].w+(bn->n1+bn->n2+bn->n3)*CHWIDTH;
return bn;
}
/*
* puticon --
* Sets the size and flags of an icon. Increments nexticon to point
* to the space for the next icon's data. Increments the count of
* icons in the box.
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
static void puticon(bits flags,int x0,int x1,int y0,int y1)
{ nexticon->extent.x0=x0;
nexticon->extent.x1=x1;
nexticon->extent.y1=-y1;
nexticon->extent.y0=-y0;
nexticon->flags=flags;
nexticon++;inum++;
}
/*
* setind --
* Sets the indirected icon data
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
static void setind(char *t,char *v,int s)
{ nexticon->data.indirected_text.text=t;
nexticon->data.indirected_text.validation=v;
nexticon->data.indirected_text.size=s;
}
/*
* group --
* Determines the esg of a radio button icon from its variable name
*
* Results:
* An esg number.
*
* Side effects:
* If this is the first use of this radio button variable name
* in this dbox the name is stored in esg[esgnumber]. The fact
* that this was first is stored in esg_first.
*
*/
static bits group(char *s)
{ bits i;
for(i=1;i<16;i++)
{ if(esg[i]==0) { esg[i]=s;esg_first=ARADIO1;break;}
if(!strcmp(s,esg[i])) { esg_first=ARADIO2;break;}
}
if(i>15) i=15;
return i<<wimp_ICON_ESG_SHIFT;
}
/*
* seticons --
* Adds the icon definitions to a dbox template.
* adds the action data for the icons to dbt and dbs.
*
* Results:
* None.
*
* Side effects:
* Uses some temporary global variables.
*
*/
static void seticons(boxnode *bn,int w,int h,int in,int dn)
{ int i,xg,yg,out,type=bn->type;
bits g;
xg=w-bn->w;
yg=h-bn->h;
switch(type)
{ case IHLIST:xg=xg/(bn->n1+1);
for(i=0;i<bn->n1;i++)
{ in+=xg;
seticons(bn->blist[i],bn->blist[i]->w,h,in,dn);
in+=bn->blist[i]->w;
}
break;
case IVLIST:yg=yg/(bn->n1+1);
for(i=0;i<bn->n1;i++)
{ dn+=yg;
seticons(bn->blist[i],w,bn->blist[i]->h,in,dn);
dn+=bn->blist[i]->h;
}
break;
case IBOX:in+=xg/2+16;dn+=yg/2+24;
setind("","R4",0);
out=in+bn->w-32;
puticon(0x1700011D,in,out,dn+bn->h-32,dn);
setind(bn->s1,(char*)-1,bn->n1);
out=in+48+CHWIDTH*bn->n1;
puticon(0x17000139,in+32,out,dn+24,dn-20);
seticons(bn->blist[0],bn->w-64,bn->h-72,in+16,dn+32);
break;
case ISPRITE:in+=xg/2;dn+=yg/2;
setind(bn->s1,(char*)(bn->n1),strlen(bn->s1));
puticon(0x1700013a,in,in+bn->w,dn+bn->h,dn);
break;
case ISAVE:in+=xg/2;dn+=yg/2;
dbt[inum]=ADRAG;dbs[inum]=bn->s3;
setind(bn->s1,(char*)1,strlen(bn->s1)+1);
puticon(0x1700613a,in+62,in+130,dn+76,dn+8);
dbt[inum]=AWRITE;dbs[inum]=bn->s2;
if(careticon<0) careticon=inum;
setind(0,"A~ ;Kta;Pptr_write",256);
puticon(0x0700f13d,in+8,in+184,dn+144,dn+92);
break;
case IINFO:case IDISPLAY:case IWATCH:
in+=xg/2+HALFGAP;dn+=yg/2+HALFGAP;
setind(bn->s1,0,bn->n1);
out=in+CHWIDTH*bn->n1+32;
puticon(0x17000311,in,out,dn+icd[type].h-GAP,dn);
in=out+GAP;
if(type==IDISPLAY) {dbt[inum]=ADISPLAY;dbs[inum]=bn->s2;}
if(type==IWATCH) {dbt[inum]=AWATCH;dbs[inum]=bn->s2;}
setind(bn->s2,"R2",(type==IWATCH)?bn->n4:bn->n2);
out=in+CHWIDTH*bn->n2+32;
puticon(0x1700013d,in,out,dn+icd[type].h-GAP,dn);
break;
case IDEFAULT:dd=bn->s2;/*Deliberate fall through*/
case IACTION:if(!strcmp(bn->s1,"Cancel")) ee=bn->s2;
in+=xg/2+HALFGAP;dn+=yg/2+HALFGAP;
setind(bn->s1,(type==IACTION)?"R5.3":"R6,3",bn->n1);
dbt[inum]=AACTION;dbs[inum]=bn->s2;
out=in+CHWIDTH*bn->n1+32;
puticon((type==IACTION)?0x1702313d:0x170f313d,
in,out,dn+icd[type].h-GAP,dn);
break;
case IOPTION:in+=xg/2+HALFGAP;dn+=yg/2+HALFGAP;
setind(bn->s1,"soptoff,opton",bn->n1);
dbt[inum]=AOPTION;dbs[inum]=bn->s2;
out=in+CHWIDTH*bn->n1+52;
puticon(0x1720b113,in,out,dn+icd[type].h-GAP,dn);
break;
case IRADIO:in+=xg/2+HALFGAP;dn+=yg/2+HALFGAP;
setind(bn->s1,"sradiooff,radioon",bn->n1);
g=group(bn->s2);
dbt[inum]=esg_first;dbs[inum]=bn->s2;
out=in+CHWIDTH*bn->n1+52;
puticon(0x1720b113|g,in,out,dn+icd[type].h-GAP,dn);
break;
case IWRITE:in+=xg/2+HALFGAP;dn+=yg/2+HALFGAP;
setind(bn->s1,0,bn->n1);
out=in+CHWIDTH*bn->n1+32;
puticon(0x17000311,in,out,dn+icd[type].h-GAP,dn);
in=out+GAP;
dbt[inum]=AWRITE;dbs[inum]=bn->s2;
if(careticon<0) careticon=inum;
setind(0,"Kta;Pptr_write",bn->n4);
out=in+CHWIDTH*bn->n2+32;
puticon(0x0700f13d,in,out,dn+icd[type].h-GAP,dn);
break;
}
}
/*
* makedbox --
* Creates a dbox structure from a box tree.
*
* Results:
* Returns a dbox pointer or zero for error
*
* Side effects:
* Uses some temporary global variables.
*
*/
static dbox *makedbox(boxnode *bn)
{ dbox *db=ckcalloc(sizeof(dbox));
wimp_window *ww=ckalloc(WSIZE(nicons));
int x,y;
screensize(&x,&y);
db->t=ckcalloc(nicons*sizeof(int));
db->s=ckcalloc(nicons*sizeof(char*));
dbt=db->t;dbs=db->s;dd=0;ee=0;
careticon=-1;
inum=0;
*ww=progInfo;
if(bn->w>1600||bn->h>1200)
{ sprintf(w_Interp->result,
"dbox too large %d x %d",bn->w,bn->h);
return 0;
}
ww->visible.x0=(x-bn->w)/2;
if(offset>y-INSET) offset=y-INSET;
offset-=bn->h+40;
if(offset<INSET) offset=y-INSET-bn->h;
ww->visible.y0=offset;
ww->visible.x1=ww->visible.x0+bn->w;
ww->visible.y1=ww->visible.y0+bn->h;
ww->extent.x1=bn->w;
ww->extent.y0=-bn->h;
ww->icon_count=nicons;
db->ww=ww;
nexticon=db->ww->icons;
seticons(bn,bn->w,bn->h,0,0);
db->d=dd;db->e=ee;db->c=careticon;
return db;
}
/*
* update --
* Called by a variable trace to update a watch icon
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
static char *update(ClientData d,Tcl_Interp *interp,char *n1,char *n2,int flags)
{ char *v=Tcl_GetVar2(interp,n1,n2,flags&TCL_GLOBAL_ONLY);
char *t;
int n;
wimp_icon_state *wis=(wimp_icon_state*)█
wis->w=((watchdata*)d)->ob->w;
wis->i=((watchdata*)d)->ic;
wimp_get_icon_state(wis);
t=wis->icon.data.indirected_text.text;
n=wis->icon.data.indirected_text.size;
if(v) strncpy(t,v,n);else t[0]=0;
t[n-1]=0;
wimp_set_icon_state(wis->w,wis->i,0,0);
return 0;
}
/*
* box_fillin --
* Sets the dialog box fields corresponding to Tcl variables
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
static void box_fillin(dbox *db,char *tag,openbox *ob)
{ wimp_window *ww=db->ww;
int ni=ww->icon_count;
int i,n;
bool truth;
char *s,*t;
for(i=0;i<ni;i++) switch(db->t[i])
{ case ADISPLAY:s=Tcl_GetVar2(w_Interp,db->s[i],tag,TCL_GLOBAL_ONLY);
if(!s) s="";
ww->icons[i].data.indirected_text.text=scopy(s);
break;
case AOPTION:s=Tcl_GetVar2(w_Interp,db->s[i],tag,TCL_GLOBAL_ONLY);
if(!s) truth=FALSE;
else truth=strcmp(s,"0");
if(truth) ww->icons[i].flags|=wimp_ICON_SELECTED;
else ww->icons[i].flags&=~wimp_ICON_SELECTED;
break;
case ARADIO1:case ARADIO2:
s=Tcl_GetVar2(w_Interp,db->s[i],tag,TCL_GLOBAL_ONLY);
if(!s) truth=FALSE;
else truth=!strcmp(s,ww->icons[i].data.indirected_text.text);
if(truth) ww->icons[i].flags|=wimp_ICON_SELECTED;
else ww->icons[i].flags&=~wimp_ICON_SELECTED;
break;
case AWATCH:{ watchdata *wd=ckalloc(sizeof(struct watchdata));
wd->next=watchdatalist;
watchdatalist=wd;
wd->ob=ob;
wd->ic=i;
Tcl_TraceVar2(w_Interp,db->s[i],tag,
TRACEFLAGS,update,(ClientData)wd);
}
/*Deliberate fall through*/
case AWRITE:n=ww->icons[i].data.indirected_text.size;
t=ckalloc(n);
ww->icons[i].data.indirected_text.text=t;
s=Tcl_GetVar2(w_Interp,db->s[i],tag,TCL_GLOBAL_ONLY);
if(s) strncpy(t,s,n);else t[0]=0;
t[n-1]=0;
break;
}
}
/*
* box_submenu --
* Opens a transient dbox
*
* Results:
* None.
*
* Side effects:
* None.
*
*/
extern void box_submenu(void *d,char *tag,int x,int y)
{ openbox *ob=ckalloc(sizeof(openbox));
dbox *db=d;
if(!db->tagged) tag=0;
if(tag) tag=scopy(tag);
box_fillin(db,tag,ob);
if(xwimp_create_window(db->ww,&(ob->w))) return;
ob->tag=tag;
ob->db=db;
ob->next=openboxlist;
openboxlist=ob;
block.open.w=ob->w;
wimp_create_sub_menu((wimp_menu*)ob->w,x,y);
}
/*
* box_open --
* Implements the w_box <name> open command
*
* Results:
* A standard Tcl result
*
* Side effects:
* None.
*
*/
static int box_open(void *d,char *tag)
{ openbox *ob=ckalloc(sizeof(openbox));
dbox* db=d;
box_fillin(db,tag,ob);
if(xwimp_create_window(db->ww,&(ob->w)))
return wrong("Unable to create window",0);
ob->tag=tag;
ob->db=db;
ob->next=openboxlist;
openboxlist=ob;
block.open.w=ob->w;
wimp_get_window_state((wimp_window_state*)&block);
wimp_open_window((wimp_open*)&block);
if(db->c>=0) wimp_set_caret_position(ob->w,db->c,0,0,-1,1000);
return TCL_OK;
}
/*
* w_BoxCmd --
* Implements the Tcl w_box command
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Creating a box uses various temporary global variables
*
*/
int w_BoxCmd(ClientData dummy,Tcl_Interp *interp,int argc,char **argv)
{ dbox *db;
Tcl_HashEntry *p;
if(argc<3) return wrong(WNA,"w_box <name> <command> ...");
/* *********** create a dbox *************** */
if(!strcmp(argv[2],"create"))
{ boxnode *bn;
int new;
if(argc!=5&&(argc!=6||strcmp(argv[5],"-tag")))
return wrong(WNA,"w_box <name> create <title> <component> ?-tag?");
nicons=0;
for(new=0;new<16;new++) esg[new]=0;
bn=getboxtree(argv[4]);
if(nicons==0) return wrong("dbox has no icons",0);
if(!bn) return TCL_ERROR;
db=makedbox(bn);
if(db==0) return TCL_ERROR;
freeboxtree(bn);
db->tagged=(argc==6);
db->ww->title_data.indirected_text.text=scopy(argv[3]);
db->ww->title_data.indirected_text.validation=(char*)-1;
db->ww->title_data.indirected_text.size=strlen(argv[3]);
p=Tcl_CreateHashEntry(&boxTable,argv[1],&new);
if(!new)
{ Tcl_AppendResult(interp,"box already exists ",argv[1],0);
return TCL_ERROR;
}
Tcl_SetHashValue(p,db);
return TCL_OK;
}
p=Tcl_FindHashEntry(&boxTable,argv[1]);
if(!p) return wrong("No such dbox",argv[1]);
db=(dbox*)Tcl_GetHashValue(p);
/* *********** open a persistent dbox *************** */
if(!strcmp(argv[2],"open")) return box_open(db,(argc>3)?scopy(argv[3]):0);
return wrong("unknown w_box command",argv[2]);
}