/* * ibicon * * proper icon bar mangement (multiple icons, etc.) * * © 1993-1998 Straylight */ /*----- Licensing note ----------------------------------------------------* * * This file is part of Straylight's Steel library. * * Steel is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Steel is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Steel. If not, write to the Free Software Foundation, * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "wimp.h" #include "wimpt.h" #include "os.h" #include "swis.h" #include "bbc.h" #include "win.h" #include "werr.h" #include "ibicon.h" #include "msgs.h" #include "event.h" #include "mem.h" #include "swiv.h" #include #include #include "dll.h" #ifndef _dll_NODLL extern void _dllEntry(ibicon__events)(wimp_eventstr *e,void *handle); extern menu _dllEntry(ibicon__menumaker)(void *handle); extern void _dllEntry(ibicon__menuhandler)(int hits[],void *handle); extern void _dllEntry(ibicon__menuhelphandler)(int hits[],void *handle); #endif typedef struct ibicon__ibiconstr { struct ibicon__ibiconstr *next; struct ibicon__ibiconstr *prev; wimp_i icon; char *data; char *valid; menu mnu; event_menu_maker maker; menu_selectProc menusel; menu_helpProc menuhelp; void *menuHandle; ibicon_handler handler; void *handle; ibicon_rawHandler raw; void *rawHandle; } ibicon__ibiconstr; static ibicon ibicon__anchor; static BOOL ibicon__eventHandler; /* Do we have an event handler? */ static ibicon ibicon__menuicon; /* The last icon to open a menu */ static int ibicon__priority; /* Icon priorities (RISC OS 3) */ /* * os_error *ibicon__spriteOp * ( * int op, * sprite_area *a, * char *name, * _kernel_swi_regs *r * ) * * Use * Does an OS_SpriteOp call. It's designed for calls that return more than * they receive. * * Parameters * int op == the operation number to perform * sprite_area *a == the sprite area to do the op on. May be 1 for the * WIMP area or 0 for the system area * char *name == the name of the sprite * os_regset *r == a regiser set to return inforation in * * Returns * An error block if anything went wrong */ static os_error *ibicon__spriteOp ( int op, sprite_area *a, char *name, os_regset *r ) { int swinum; if ((int)a==1) swinum=XWimp_SpriteOp; else { swinum=XOS_SpriteOp; if (a!=0) op+=256; } r->r[0]=op; r->r[1]=(int)a; r->r[2]=(int)name; return (os_swix(swinum,r)); } /* * void ibicon__spriteSize(char *name,sprite_area *a,wimp_box *b,BOOL centre) * * Use * Returns the size of the sprite specified. If requested, it also * centres the result given within a 68 OS unit vertical area. * * Parameters * char *name == the name of the sprite of which to return the size * sprite_area *a == the sprite area (same conventions as above) * wimp_box *b == a box structure to fill in * BOOL centre == whether to centre the icon vertically */ static void ibicon__spriteSize ( char *name, sprite_area *a, wimp_box *b, BOOL centre ) { os_regset r; int height; b->x0=0; wimpt_noerr(ibicon__spriteOp(40,a,name,&r)); b->x1=r.r[3]<y0=(68-height)>>1; b->y1=68-b->y0; } else { b->y0=0; b->y1=height; } } /* * ibicon ibicon_find(wimp_i icon) * * Use * Return the ibicon handle of an icon. * * Parameters * wimp_i icon == the icon to find */ ibicon ibicon_find(wimp_i icon) { ibicon i; for (i=ibicon__anchor;i;i=i->next) { if (i->icon==icon) return (i); if (i->icon>icon) return (0); } return (0); } /* * wimp_i ibicon_syshandle(ibicon i) * * Use * Returns the low-level WIMP handle for the icon concerned. * * Parameters * ibicon i == the icon whose handle is desired * * Returns * The WIMP icon handle for the icon */ wimp_i ibicon_syshandle(ibicon i) { return (i->icon); } /* * void ibicon__menuhandler(int hit[],void *handle) * * Use * Handles clicks on icon bar menus. It acts an event_menu_proc and passes * the information on the relevant icon. * * Parameters * int hit[] == the hit string to be processed. * void *handle == not worth the effort of worrying about */ _dll_static void ibicon__menuhandler(int hit[],void *handle) { handle=handle; if (ibicon__menuicon) { if (ibicon__menuicon->menusel) (ibicon__menuicon->menusel)(hit,ibicon__menuicon->menuHandle); } } /* * void ibicon__menuhelphandler(int hit[],void *handle) * * Use * Handles help request for icon bar menus. It acts a menu_helpProc or * whatever and passes the information on the relevant icon. * * Parameters * int hit[] == the hit string to be processed. * void *handle == not worth the effort of worrying about */ _dll_static void ibicon__menuhelphandler(int hit[],void *handle) { handle=handle; if (ibicon__menuicon) { if (ibicon__menuicon->menuhelp) (ibicon__menuicon->menuhelp)(hit,ibicon__menuicon->menuHandle); } } /* * menu ibicon__menumaker(void *handle) * * Use * Handles menus and things for the icon bar. Acts as an event_menu_maker * and passes the request on to the icon concerned. * * Parameters * void *handle == nothing worth worrying about * * Returns * The menu to display */ _dll_static menu ibicon__menumaker(void *handle) { wimp_eventstr *e=wimpt_last_event(); handle=handle; if (e->e==wimp_EBUT) ibicon__menuicon=ibicon_find(e->data.but.m.i); if (ibicon__menuicon) { if (ibicon__menuicon->mnu) return (ibicon__menuicon->mnu); else if (ibicon__menuicon->maker) return ((ibicon__menuicon->maker)(ibicon__menuicon->menuHandle)); } return (0); /* menu is dead - icon disappeared */ } /* * void ibicon__events(wimp_eventstr *e,void *handle) * * Purpose * Event handler installed for both win_ICONBAR and win_ICONBARLOAD. * * Parameters * wimp_eventstr *e == the event * void *handle == nothing interesting */ _dll_static void ibicon__events(wimp_eventstr *e,void *handle) { wimp_i icn=-1; ibicon i; ibicon_eventType type=ibicon_NOTHING; handle=handle; switch (e->e) { case wimp_EBUT: icn=e->data.but.m.i; switch (e->data.but.m.bbits) { case wimp_BLEFT: type=ibicon_LEFTCLICK; break; case wimp_BRIGHT: type=ibicon_RIGHTCLICK; break; } break; case wimp_ESEND: case wimp_ESENDWANTACK: switch (e->data.msg.hdr.action) { case wimp_MDATASAVE: type=ibicon_SAVE; icn=e->data.msg.data.datasave.i; break; case wimp_MDATALOAD: type=ibicon_LOAD; icn=e->data.msg.data.dataload.i; break; case wimp_MHELPREQUEST: type=ibicon_HELP; icn=e->data.msg.data.helprequest.m.i; break; } } if (i=ibicon_find(icn),!i) return; if (i->raw) { if ((i->raw)(i,e,i->rawHandle)) type=ibicon_NOTHING; } if (type!=ibicon_NOTHING) { if (i->handler) (i->handler)(i,type,i->handle); } } /* * void ibicon_setPriority(int priority) * * Use * Sets the priority with which to create icons under RISC OS 3. * * Parameters * int priority == the new setting */ void ibicon_setPriority(int priority) { ibicon__priority=priority; } /* * ibicon ibicon_create * ( * int where, * char *spritename, * sprite_area *sprarea, * char *text, * int maxtext * ) * * Use * Creates an icon in the icon bar. Where is up to you. Specify a * sprite-only icon by passing 0 for text. Use the macros to define where * and what area you want the sprite from. * * Parameters * int where == what part of the icon bar you want to put the icon in. * Macros are defined for the RISC OS 2 possibilities. Wait for the * RISC OS 3 macros, or just pass a window handle. * char *spritename == the name of the sprite to display * sprite_area *sprarea == the area from which the sprite area comes. Use * the macros provided for odd things like the WIMP area. If you have * text as well, then this will be ignored anyway. * char *text == the text for the icon. May be a NULL pointer, for no * text. * int maxtext == the max length the text entry can be. If 0 then the * length of the text given will be used. * * Returns * A handle to the icon if successful, or 0 if not. */ ibicon ibicon_create ( int where, char *spritename, sprite_area *sprarea, char *text, int maxtext ) { wimp_icreate i; ibicon new=mem_alloc(sizeof(ibicon__ibiconstr)); ibicon c; if (!new) { werr(FALSE,msgs_lookup("ibicnNEM:Not enough memory for icon.")); return (0); } if (!ibicon__eventHandler) { win_register_event_handler(win_ICONBAR,_dllEntry(ibicon__events),0); win_register_event_handler(win_ICONBARLOAD,_dllEntry(ibicon__events),0); menu_attachMaker ( win_ICONBAR, _dllEntry(ibicon__menumaker), _dllEntry(ibicon__menuhandler), _dllEntry(ibicon__menuhelphandler), 0 ); ibicon__eventHandler=TRUE; } if (text) { if (!maxtext) maxtext=strlen(text); if (new->data=mem_alloc(maxtext+1),!new->data) { mem_free(new); werr(FALSE,msgs_lookup("ibicnNEM:Not enough memory for icon.")); return (0); } if (new->valid=mem_alloc(15),!new->valid) { mem_free(new); mem_free(new->data); werr(FALSE,msgs_lookup("ibicnNEM:Not enough memory for icon.")); return (0); } strcpy(new->data,text); sprintf(new->valid,"S%s",spritename); i.i.data.indirecttext.buffer=new->data; i.i.data.indirecttext.validstring=new->valid; i.i.data.indirecttext.bufflen=maxtext+1; ibicon__spriteSize(spritename,sprarea,&i.i.box,FALSE); i.i.box.y0-=16; i.i.box.y1+=20; if (i.i.box.x1<16*maxtext) i.i.box.x1=16*maxtext; } else { if (new->data=mem_alloc(15),!new->data) { mem_free(new); werr(FALSE,msgs_lookup("ibicnNEM:Not enough memory for icon.")); return (0); } strcpy(new->data,spritename); new->valid=0; i.i.data.indirectsprite.name=new->data; i.i.data.indirectsprite.spritearea=(void *)sprarea; i.i.data.indirectsprite.nameisname=TRUE; ibicon__spriteSize(spritename,sprarea,&i.i.box,TRUE); } switch (where) { case ibicon_LEFTSEARCHLEFT: case ibicon_LEFTSEARCHRIGHT: if (wimpt_getVersion()<300) where=ibicon_LEFT; break; case ibicon_RIGHTSEARCHLEFT: case ibicon_RIGHTSEARCHRIGHT: if (wimpt_getVersion()<300) where=ibicon_RIGHT; break; } i.w=where; i.i.flags= ( wimp_ISPRITE | (text ? wimp_ITEXT : 0) | wimp_IHCENTRE | (text ? 0 : wimp_IVCENTRE) | wimp_INDIRECT | wimp_IBTYPE * wimp_BCLICKDEBOUNCE | wimp_IFORECOL * 7 | wimp_IBACKCOL * 1 ); wimpt_noerr(_swix(XWimp_CreateIcon,_inr(0,1)+_out(0), ibicon__priority,(int)&i, &new->icon)); win_activeinc(); for (c=(ibicon)&ibicon__anchor;c->next;c=c->next) { if (c->next->icon>new->icon) break; } new->next=c->next; if (ibicon__anchor) new->prev=c; else new->prev=0; if (c->next) c->next->prev=new; c->next=new; new->mnu=0; new->maker=0; new->menusel=0; new->menuhelp=0; new->menuHandle=0; new->handler=0; new->handle=0; new->raw=0; new->rawHandle=0; win_activeinc(); return (new); } /* * void ibicon_changeSprite(ibicon i,char *newsprite) * * Use * Chnage the sprite displayed in an icon * * Parameters * ibicon i == the icon to change * char *newsprite == the new name */ void ibicon_changeSprite(ibicon i,char *newsprite) { if (i->valid) sprintf(i->valid,"S%s",newsprite); else strcpy(i->data,newsprite); wimpt_noerr(wimp_set_icon_state(-2,i->icon,0,0)); } /* * void ibicon_changeText(ibicon i,char *newtext) * * Use * Change the text of an icon. * * Parameters * ibicon i == the icon to change * char *text == the new text to display */ void ibicon_changeText(ibicon i,char *newtext) { if (i->valid) strcpy(i->data,newtext); else werr(TRUE,msgs_lookup("ibicnCCT:(ibicon_changeText, caller fault): " "Attempt to write text to sprite-only ibicon.")); wimpt_noerr(wimp_set_icon_state(-2,i->icon,0,0)); } /* * void ibicon_attachMenu * ( * ibicon i, * menu m, * menu_selectProc sel, * menu_helpProc help, * void *handle * ) * * Use * Attaches a menu to an icon in the icon bar * * Parameters * ibicon i == the icon to attach to * menu m == the menu to attach * menu_selectProc sel == a handler function for the menu * menu_helpProc help == a help processor for the menu * void *handle == a handle passed to the handler */ void ibicon_attachMenu ( ibicon i, menu m, menu_selectProc sel, menu_helpProc help, void *handle ) { i->mnu=m; i->maker=0; i->menusel=sel; i->menuhelp=help; i->menuHandle=handle; } /* * void ibicon_attachMenuMaker * ( * ibicon i, * event_menu_maker m, * menu_selectProc sel, * menu_helpProc help, * void *handle * ) * * Use * Attaches a menu maker to an icon in the icon bar * * Parameters * ibicon i == the icon to attach to * event_menu_maker m == the menu maker to attach * menu_selectProc sel == a handler function for the menu * menu_helpProc help == a help processor for the menu * void *handle == a handle passed to the handler */ void ibicon_attachMenuMaker ( ibicon i, event_menu_maker m, menu_selectProc sel, menu_helpProc help, void *handle ) { i->mnu=0; i->maker=m; i->menusel=sel; i->menuhelp=help; i->menuHandle=handle; } /* * void ibicon_removeIcon(ibicon i) * * Use * Removes an icon totally from the icon bar. * * Parameters * ibicon i == the icon to vape */ void ibicon_removeIcon(ibicon i) { wimpt_noerr(wimp_delete_icon(-2,i->icon)); if (i->prev) i->prev->next=i->next; else ibicon__anchor=i->next; if (i->next) i->next->prev=i->prev; mem_free(i); win_activedec(); } /* * void ibicon_eventHandler(ibicon i,ibicon_handler p,void *handle) * * Use * Attaches the handler to an icon. * * Parameters * ibicon i == the icon to attach * ibicon_handler p == the handler * void *handle == a pointer to pass to the handler */ void ibicon_eventHandler(ibicon i,ibicon_handler p,void *handle) { i->handler=p; i->handle=handle; } /* * void ibicon_rawEventHandler(ibicon i,ibicon_rawHandler p,void *handle) * * Use * Attaches a raw event handler. This can 'vet' events before ibicon gets * it mucky mits on them. * * Parameters * ibicon i == the icon to attach * ibicon_rawHandler p == the handler * void *handle == a pointer to pass to the handler */ void ibicon_rawEventHandler(ibicon i,ibicon_rawHandler p,void *handle) { i->raw=p; i->rawHandle=handle; }