3 * further dialogue box routines for Straylight apps
5 * v. 1.02 (10 August 1993)
7 * © 1993-1998 Straylight
10 /*----- Licensing note ----------------------------------------------------*
12 * This file is part of Straylight's Steel library.
14 * Steel is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
19 * Steel is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Steel. If not, write to the Free Software Foundation,
26 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #define dbox__INTERNALS
34 #include "interface.h"
35 #include "sculptrix.h"
57 extern void _dllEntry(dbox__eventhandler)(wimp_eventstr *e,void *handle);
60 wimp_w dbox_menuDboxWindow(void);
63 * The big one - the data needed to manage the dbox system. This IS a dbox.
65 typedef struct dbox__dboxstr
67 wimp_w wind; /* Real window handle */
68 dbox_eventhandler eventProc; /* User event handler procedure */
69 void *eventHandle; /* Pointer to handler information */
70 dbox_raweventhandler rawEventProc; /* Pointer to raw event handler */
71 void *rawEventHandle; /* Pointer to raw handler information */
72 wimp_caretstr oldCaret; /* Where the caret was before this opened */
73 wimp_wind *windDef; /* Pointer to complete window definiton */
74 wimp_wind *temp; /* Pointer to template for this window */
75 char *indirect; /* Pointer to indirected text */
76 int titleIcon; /* Icon for the window title, or -1 */
77 BOOL isOpen :1; /* Is the dbox open? */
78 BOOL isStatic :1; /* Is this a static or menu dbox */
79 BOOL restoreCaret :1; /* Do we return the caret when finished? */
80 BOOL moveDrag :1; /* Click on window starts window move */
85 * A structure for passing to the dbox__fillinHandler() routine to make sure
86 * that the thing runs smoothly.
90 dbox_field f; /* The clicked field, or -2 */
94 #define dbox__CLICKMAX 10 /* Number of clicks which fit in stack */
99 sculptrix_slabDescriptor s;
103 static dbox__cstackstr dbox__clicked[dbox__CLICKMAX];
104 /* Click stack array */
105 static int dbox__click; /* Click stack stack pointer */
106 static dbox dbox__menuDbox; /* Currently open menu dbox (or 0) */
107 static BOOL dbox__closedForUs; /* Is this a 'real' close event? */
108 static BOOL dbox__shiftRet=FALSE; /* Is this a sh-RETURN press for a dbox? */
110 static dbox__mf dbox__tmsmf; /* Where to go to find menu coords */
111 static dbox__esm dbox__tmsesm; /* Are we expecting a submenu */
112 static dbox__ddb dbox__tmsddb; /* How do we display a dialogue box? */
114 /* This routine is for a bodge to get round menu help problems. It is */
115 /* to be used *only* by the event segment for its own processing of help */
117 wimp_w dbox__menuDboxWindow(void)
119 return (dbox__menuDbox->wind);
123 * void dbox__rms(dbox__mf f,dbox__esm esm,dbox__ddb ddb)
126 * Registers support functions for handling an alternative menu handling
130 void dbox__rms(dbox__mf f,dbox__esm esm,dbox__ddb ddb)
138 * BOOL wasAdjustClick(void)
141 * Returns whether the last event was caused by a mouse click with the
142 * adjust mouse button. Useful for deciding whether you want to bump a
143 * value up or down, or for keeping a dbox on-screen.
146 * TRUE if the last event WAS caused by an adjust click.
149 BOOL dbox_wasAdjustClick(void)
151 wimp_eventstr *e=wimpt_last_event();
152 if ((e->e==wimp_EBUT && e->data.but.m.bbits==wimp_BRIGHT)||dbox__shiftRet)
159 * wimp_icon *dbox__idef(dbox d,wimp_i i)
162 * This routine returns a pointer to the icon definition specified.
165 * dbox d == dbox handle
166 * wimp_i i == the icon handle
169 * A pointer to the icon definition.
172 #define dbox__idef(d,i) ((wimp_icon *)((d)->windDef+1)+(i))
175 static wimp_icon *dbox__idef(dbox d,wimp_i i)
177 return ((wimp_icon *)(d->windDef+1)+i);
182 * int dbox__fieldlength(dbox d,dbox_field f)
185 * Returns the length of the text in field specified
188 * dbox d == dbox handle
189 * dbox_field f == field number (icon handle to the uninitiated!)
192 * The length of the field. Why isn't this a size_t?
195 static int dbox__fieldlength(dbox d, dbox_field f)
198 dbox_getfield((dbox) d, f, a, 255);
203 * void dbox__nextWritable(BOOL fromTop,dbox d,BOOL forward)
206 * This call moves the caret around the window it is in. The fromTop
207 * parameter says whether you want to move the caret either to one
208 * extremity or the other, or just move it along. The routine, unlike the
209 * standard RISC_OSlib one, actually scrolls the window to keep the caret
213 * BOOL fromTop == whether you want to move to an extremity, or just up or
215 * dbox d == the dbox you think the caret is in. If it isn't, you're in
217 * BOOL forward == whether you want to search forward or backward from your
221 static void dbox__nextWritable(BOOL fromTop,dbox d,BOOL forwards)
231 wimpt_noerr(wimp_get_caret_pos(&c));
241 i=d->windDef->nicons;
245 for (iterations=0;iterations<d->windDef->nicons;iterations++,i+=dir)
247 if (i>d->windDef->nicons)
255 i=d->windDef->nicons+1;
259 wimpt_noerr(wimp_get_icon_info(d->wind,i,&idef));
260 bt=(((int)idef.flags)>>12) & 15;
263 (bt==15 || bt==14) &&
264 ((idef.flags & wimp_INOSELECT)==0) &&
265 ((idef.flags & wimp_IDELETED)==0)
269 if (iterations==d->windDef->nicons)
274 c.index=dbox__fieldlength(d,i);
275 wimpt_noerr(wimp_set_caret_pos(&c));
276 wimpt_noerr(wimp_get_wind_state(d->wind,&state));
277 sw=state.o.box.x1-state.o.box.x0;
278 sh=state.o.box.y1-state.o.box.y0;
279 ox=state.o.box.x0-state.o.x;
280 oy=state.o.box.y1-state.o.y;
281 if (state.o.box.x0>idef.box.x0+ox)
282 state.o.x=idef.box.x0-24;
283 if (state.o.box.x1<idef.box.x1+ox)
284 state.o.x=idef.box.x1+24-sw;
285 if (state.o.box.y0>idef.box.y0+oy)
286 state.o.y=idef.box.y0-24+sh;
287 if (state.o.box.y1<idef.box.y1+oy)
288 state.o.y=idef.box.y1+24;
289 wimpt_noerr(wimp_open_wind(&state.o));
293 * void dbox__checkRadio(dbox d,dbox_field f)
296 * Checks to see if the specified dbox_field is a radio button (button type
297 * debounced and nonzero ESG) and if so selects it and unselects other
298 * fields with the same ESG number.
301 * dbox d == the dbox containing the clicked field
302 * dbox_field f == the field wot was clicked
305 static void dbox__checkRadio(dbox d,dbox_field f)
307 wimp_icon *idef=dbox__idef(d,f);
310 if ((idef->flags & 0x0000F000) == (wimp_BCLICKDEBOUNCE<<12))
312 esg=idef->flags & 0x001F0000;
315 dbox_selecticon(d,f,TRUE);
316 idef=dbox__idef(d,0);
317 for (i=0;i<d->windDef->nicons;i++,idef++)
319 if (i!=f && (idef->flags & 0x001F0000)==esg)
320 dbox_selecticon(d,i,FALSE);
327 * void dbox__eventhandler(wimp_eventstr *e,void *handle)
330 * Event handler for dboxes. Handles ops as follows:
332 * * Clicks on icons are passed to dbox handler if present
333 * * Key presses are dealt with:
334 * cursor keys move caret
335 * return reports a click on icon 0
336 * escape reports a click on icon 1
337 * a close operation reports a click on icon dbox_CLOSE
338 * * If a menu dbox closes in the backgound (i.e. the WIMP makes off with
339 * it), a close operation is passed to the dbox concerned.
342 * wimp_eventstr *e == a pointer to the current WIMP event
343 * void *handle == the jolly old handle, which is a pointer to the
347 _dll_static void dbox__eventhandler(wimp_eventstr *e,void *handle)
352 dbox__shiftRet=FALSE;
354 handled=(d->rawEventProc)(d,e,(void *)d->rawEventHandle);
360 if (d->titleIcon!=-1)
361 wimpt_redraw(dbox_drawEmbeddedTitle,d);
366 wimpt_noerr(wimp_open_wind(&e->data.o));
370 (d->eventProc)(d,dbox_CLOSE,d->eventHandle);
373 if (e->data.but.m.bbits==wimp_BRIGHT ||
374 e->data.but.m.bbits==wimp_BLEFT)
376 dbox__checkRadio(d,e->data.but.m.i);
377 if (d->eventProc && e->data.but.m.i!=-1)
378 (d->eventProc)(d,e->data.but.m.i,d->eventHandle);
383 dr.type=wimp_MOVE_WIND;
389 switch (akbd_translate(e->data.key.chcode))
394 /* Treat as normal return */
397 if (d->eventProc && !dbox_shadeicon(d,0,dbox_READSTATE))
398 (d->eventProc)(d,0,d->eventHandle);
402 /* Treat as normal Escape */
404 if (d->eventProc && !dbox_shadeicon(d,1,dbox_READSTATE))
405 (d->eventProc)(d,1,d->eventHandle);
409 dbox__nextWritable(FALSE,d,TRUE);
413 dbox__nextWritable(FALSE,d,FALSE);
416 dbox__nextWritable(TRUE,d,FALSE);
419 dbox__nextWritable(TRUE,d,TRUE);
422 wimp_processkey(e->data.key.chcode);
427 case wimp_ESENDWANTACK:
428 switch (e->data.msg.hdr.action)
430 case wimp_MHELPREQUEST:
432 (d->eventProc)(d,dbox_HELP,d->eventHandle);
441 * dbox dbox_create(char *template)
444 * Creates a dbox from a template and returns a handle to it. It calls
445 * werr() sensibly with nice messages if it failed.
448 * char *name == name of template to use
451 * Abstract handle to dbox or NULL if the dbox could not be
455 dbox dbox_create(char *name)
457 template *temp=template_find(name);
458 wimp_wind *w=template_syshandle(name);
459 dbox d=(dbox)mem_alloc(sizeof(dbox__dboxstr));
462 BOOL unshade=wimpt_options() & wimpt_ONOWIMPSHADE;
465 if (d->windDef=(wimp_wind *)mem_alloc
467 sizeof(wimp_wind)+w->nicons*sizeof(wimp_icon)
475 msgs_lookup("dboxNEM:Not enough memory for new dialogue box.")
479 memcpy(d->windDef,w,sizeof(wimp_wind)+w->nicons*sizeof(wimp_icon));
480 if (temp->workspacesize!=0)
482 if (d->indirect=(char *)mem_alloc(temp->workspacesize),d->indirect==0)
484 mem_free(d->windDef);
489 msgs_lookup("dboxNEM:Not enough memory for new dialogue box.")
493 memcpy(d->indirect,temp->workspace,temp->workspacesize);
494 for (i=0;i<d->windDef->nicons;i++)
498 icn->flags &= 0xffbfffff;
499 if ((icn->flags&wimp_INDIRECT)!=0)
501 icn->data.indirecttext.buffer+=d->indirect-temp->workspace;
502 if ((icn->flags&3)==2)
503 icn->data.indirectsprite.spritearea=(void *)1;
506 if (icn->data.indirecttext.validstring!=(char *)-1)
508 icn->data.indirecttext.validstring+=
509 d->indirect-temp->workspace;
514 if (d->windDef->titleflags&wimp_INDIRECT)
516 d->windDef->title.indirecttext.buffer+=d->indirect-temp->workspace;
517 if ((d->windDef->titleflags&3)==2)
518 d->windDef->title.indirectsprite.spritearea=(void *)1;
521 if (d->windDef->title.indirecttext.validstring!=(char *)-1)
523 d->windDef->title.indirecttext.validstring+=
524 d->indirect-temp->workspace;
531 if (wimp_create_wind(d->windDef,&d->wind)==0)
541 win_register_event_handler(d->wind,_dllEntry(dbox__eventhandler),d);
545 mem_free(d->windDef);
546 mem_free(d->indirect);
552 msgs_lookup("dboxTMW:Too many windows - "
553 "%s could not create window/dialogue box."),
562 msgs_lookup("dboxNEM:Not enough memory for new dialogue box.")
568 * void dbox__setMenuDbox(dbox d)
571 * This routine handles the updating of the dbox__menuDbox variable. It
572 * is needed 'cos if the user maniacally starts opening submenus, the thing
573 * can get a bit confused. If there already is one, it gets a wimp_ECLOSE
574 * event faked to it courtesy of a combination of wimpt_fake_event() and
578 * dbox d == the new prospective menu dbox.
581 static void dbox__setMenuDbox(dbox d)
587 * void dbox_display(dbox d,dbox_openType how)
590 * Displays a dbox on the screen. The new dbox_openType is compatible with
591 * the old TRUE/FALSE system. Note that is the event was a submenu, then
592 * the dbox will be opened as a submenu regardless of how you want it done.
594 * If the dbox conatins a writable icon, then the caret is placed within
595 * the first one. This is handled automatically by the WIMP for submenu
596 * dboxes, but not (unfortunately) for static ones.
599 * dbox d == dbox handle
600 * dbox_openType how == how you want the dbox opened
603 void dbox_display(dbox d,dbox_openType how)
606 int scx=wimpt_scwidth();
607 int scy=wimpt_scheight();
615 wimpt_noerr(wimp_get_wind_state(d->wind,&state));
616 state.o.behind=(wimp_w)-1;
617 w=state.o.box.x1-state.o.box.x0;
618 h=state.o.box.y1-state.o.box.y0;
622 case dbox_MENU_OVERPTR:
624 case dbox_STATIC_OVERPTR:
625 bbc_mouse(&x,&y,0,0);
626 state.o.box.x0=x-w/2;
627 state.o.box.x1=x+w/2;
628 state.o.box.y0=y-h/2;
629 state.o.box.y1=y+h/2;
631 case dbox_MENU_LASTPOS:
633 case dbox_STATIC_LASTPOS:
636 case dbox_MENU_CENTRE:
638 case dbox_STATIC_CENTRE:
639 state.o.box.x0=(scx-w)/2;
640 state.o.box.x1=(scx+w)/2;
641 state.o.box.y0=(scy-h)/2;
642 state.o.box.y1=(scy+h)/2;
645 win_adjustBox(&state.o);
648 wimpt_noerr(wimp_open_wind(&state.o));
653 wimpt_noerr(wimp_get_caret_pos(&d->oldCaret));
654 d->restoreCaret=TRUE;
655 dbox__nextWritable(TRUE,d,TRUE);
656 wimpt_noerr(wimp_get_caret_pos(&c));
658 d->restoreCaret=FALSE;
664 wimpt_noerr(wimp_set_caret_pos(&c));
670 if (dbox_wasSubmenu() && (wimpt_last_event()->e==wimp_ESEND ||
671 wimpt_last_event()->e==wimp_ESENDWANTACK))
673 e=wimpt_last_event();
674 x=e->data.msg.data.words[1];
675 y=e->data.msg.data.words[2];
676 wimpt_noerr(wimp_create_submenu((wimp_menustr *)d->wind,x,y));
677 d->restoreCaret=FALSE;
679 else if (dbox__tmsesm && dbox__tmsesm())
686 dbox__tmsddb(&state.o);
687 wimpt_noerr(wimp_get_caret_pos(&d->oldCaret));
688 d->restoreCaret=TRUE;
689 dbox__nextWritable(TRUE,d,TRUE);
693 wimpt_noerr(wimp_create_menu(
694 (wimp_menustr *)d->wind,
698 d->restoreCaret=FALSE;
702 dbox__setMenuDbox(d);
707 * void dbox_openDisplaced(dbox d)
710 * Displaces the dbox from its original height by the statutory 48 OS
711 * units. If it would overlap the icon bar, it gets moved up to a sensible
712 * height. The dbox must be opened by this call once only. It must be
713 * closed using dbox_deleteNoUpdate(). The dbox is opened as a static
720 void dbox_openDisplaced(dbox d)
730 msgs_lookup("dboxCOD:(dbox_openDisplaced): "
731 "failed - dbox already open.")
734 if (d->temp->box.y0-48<132)
736 new=((976-d->temp->box.y1)/48-4)*48+d->temp->box.y1;
737 d->temp->box.y0+=new-d->temp->box.y1;
745 wimpt_noerr(wimp_get_wind_state(d->wind,&s));
746 s.o.box=d->temp->box;
748 wimpt_noerr(wimp_open_wind(&s.o));
751 wimpt_noerr(wimp_get_caret_pos(&d->oldCaret));
752 d->restoreCaret=TRUE;
753 dbox__nextWritable(TRUE,d,TRUE);
754 wimpt_noerr(wimp_get_caret_pos(&c));
756 d->restoreCaret=FALSE;
759 wimpt_noerr(wimp_open_wind(&s.o));
762 wimpt_noerr(wimp_set_caret_pos(&c));
767 * void dbox_hide(dbox d)
770 * Closes the dbox specified in whatever manner necessary to stop it being
771 * seen. The window can still be created real easy.
774 * dbox d == dialogue box handle
777 void dbox_hide(dbox d)
779 if (d==dbox__menuDbox)
781 if (!dbox__closedForUs)
782 event_clear_current_menu();
785 wimpt_noerr(wimp_close_wind(d->wind));
787 wimp_set_caret_pos(&d->oldCaret);
792 * void dbox_deleteNoUpdate(dbox d)
795 * Zaps a dbox without storing the thing's position away, so it reappears
799 * dbox d == the handle
802 void dbox_deleteNoUpdate(dbox d)
806 win_register_event_handler(d->wind,0,0);
808 wimpt_noerr(wimp_delete_wind(d->wind));
809 mem_free(d->indirect);
810 mem_free(d->windDef);
815 * void dbox_updatePosition(dbox d)
818 * Stores the position of the dialogue box away, so that next time a dbox
819 * using the same template is opened, it goes to that place.
822 * dbox d == the dbox handle
825 void dbox_updatePosition(dbox d)
828 wimp_get_wind_state(d->wind,&s);
829 d->temp->box=s.o.box;
833 * void dbox_delete(dbox d)
836 * Utterly zaps the dialogue box specified. Updates the template, so it's
837 * right next time around, though. The window is deleted, and the dbox's
841 * dbox d == dialogue box handle
844 void dbox_delete(dbox d)
847 dbox_updatePosition(d);
848 dbox_deleteNoUpdate(d);
852 * void dbox_eventHandler(dbox d,dbox_eventhandler proc,void *handle)
855 * This routine attaches an event handler to a dbox. Pass 0 as the pointer
856 * to the procedure if you want to remove the handler. Event handers are an
857 * alternative to using dbox_fillin().
860 * dbox d == the dbox you want to attach a handler to.
861 * dbox_eventhandler proc == the hander procedure.
862 * void *handle == up to you. It gets passed to the procedure, though.
865 void dbox_eventHandler(dbox d,dbox_eventhandler proc,void *handle)
868 d->eventHandle=handle;
872 * void dbox_rawEventHandler(dbox d,dbox_raweventhandler proc,void *handle)
875 * This routine attaches a raw event handler to a dbox. Pass 0 as the
876 * pointer to the procedure if you want to remove the handler. A raw event
877 * handler gets passed all the WIMP events received by the dbox. It should
878 * return FALSE if it could not process the event itself, or TRUE if it
882 * dbox d == the dbox you want to attach a handler to.
883 * dbox_eventhandler proc == the hander procedure.
884 * void *handle == up to you. It gets passed to the procedure, though.
887 void dbox_rawEventHandler(dbox d,dbox_raweventhandler proc,void *handle)
889 d->rawEventProc=proc;
890 d->rawEventHandle=handle;
894 * void dbox__fillinHandler(dbox d,dbox_field clicked,void *handle)
897 * This is the dbox handler used by dbox_fillin().
900 * dbox d == the dbox handle
901 * dbox_field == the field that was clicked
902 * void *handle == a pointer to a dbox__fillinstr
905 static void dbox__fillinHandler(dbox d,dbox_field clicked,void *handle)
907 dbox__fillinstr *f=(dbox__fillinstr *)handle;
913 * dbox_field dbox_fillin(dbox d)
916 * This is a nice simple way of handling a dbox. It means you can handle
917 * everything from an in-line point of view. Functions can easily return
918 * the results they need (like dbox_query()). Unfortunately, it will only
919 * work with menu dboxes, and will complain bitterly at you if you try and
920 * do anything different.
923 * dbox d == the dbox handle
926 * The field number that was clicked.
929 dbox_field dbox_fillin(dbox d)
937 msgs_lookup("dboxFRE:(dbox_fillin, caller fault): "
938 "dbox_fillin only works with menu dboxes.")
942 dbox_eventHandler(d,dbox__fillinHandler,&f);
943 while (f.f==dbox_ENDFILLIN)
945 dbox_eventHandler(d,0,0);
950 * void dbox_eventProcess(void)
953 * Part of the private interface between dbox and event for processing
954 * dialogue box events.
957 void dbox__eventProcess(void)
959 static wimp_eventstr real;
964 dbox__closedForUs=FALSE;
967 wimpt_fake_event(&real);
974 wimpt_noerr(wimpt_poll(event_getmask(),&real));
975 wimpt_noerr(wimp_get_wind_state(dbox__menuDbox->wind,&state));
976 if ((((state.flags & wimp_WOPEN)==0) || real.e==wimp_EMENU) &&
977 real.e!=wimp_EREDRAW)
980 fake.data.o.w=dbox__menuDbox->wind;
981 wimpt_fake_event(&fake);
982 dbox__closedForUs=TRUE /* (real.e!=wimp_EMENU) */ ;
986 wimpt_fake_event(&real);
992 * void dbox_setfield(dbox d,dbox_field f,char *string,...)
995 * This routine will write the string into the field specified, if and only
996 * if the field's data is indirected. The icon is checked to make sure
997 * it's been indirected, and if the string is too long, we hack off bits
998 * until it fits. Normally, the end bit is chopped off. However, you can
999 * set the icon's right-aligned bit to indicate that you want the
1000 * *beginning* bit chopped off.
1003 * dbox d == the dbox
1004 * dbox_field f == the field
1005 * char *string == a printf-style format string
1008 void dbox_setfield(dbox d,dbox_field f,char *string,...)
1010 wimp_icon *i=dbox__idef(d,f);
1016 BOOL different=FALSE;
1024 /* --- Construct the string to fill in the buffer --- *
1026 * If the buffer overflows here, we're pretty much stuffed. We can try
1027 * to chop the end off and hope it doesn't damage anything too badly,
1028 * though. If the format string is `%s', we can just use the string given
1029 * in the first variable arg, though, so we're safe there.
1032 va_start(ap,string);
1033 if (string[0]=='%' && string[1]=='.')
1038 if (!strcmp(string,"%s"))
1039 fptr=va_arg(ap,char *);
1042 vsprintf(field,string,ap);
1048 /* --- Make sure the string's indirected --- */
1050 if (!(i->flags & wimp_INDIRECT))
1052 werr(TRUE,msgs_lookup("dboxSFNIND:(dbox_setfield, caller fault): "
1053 "Icon is not indirected."));
1056 /* --- Write the string to the icon, noting differences --- *
1058 * If the string is too long for the buffer, truncate it. Note that if
1059 * it's more than 1K long, we've already died horridly, because sprintf
1060 * will have overflowed our own buffer above.
1063 buff=i->data.indirecttext.buffer;
1064 max=i->data.indirecttext.bufflen-1;
1068 if (rJust=(i->flags & wimp_IRJUST),rJust)
1078 if (max==j || y<' ')
1080 else if (dots && ((rJust && j<3) || (!rJust && max-j<4)))
1095 /* --- If the icon has changed, redraw it, and move the caret --- */
1099 wimpt_noerr(wimp_set_icon_state(d->wind,f,0,0));
1100 wimpt_noerr(wimp_get_caret_pos(&c));
1101 if (c.w==d->wind && c.i==f)
1108 wimpt_noerr(wimp_set_caret_pos(&c));
1114 * void dbox_clickicon(dbox d,dbox_field f)
1117 * Informs a 3D button manager (e.g. Sculptrix) of a click on an icon. Icon
1118 * clicks are stacked, so that unclick calls unslab icons in reverse order
1119 * to slabbing. If any 3D button managers are loaded, it's assumed that
1120 * you will want to use them. Otherwise, icons are selected and unselected
1121 * (which fits in with RISC OS 3's inferior 3D button system)
1124 * dbox d == the dbox
1125 * dbox_field f == the field
1128 void dbox_clickicon(dbox d,dbox_field f)
1132 if (dbox__click==dbox__CLICKMAX)
1135 msgs_lookup("dboxSTK:Only enough stack space for %i icons."),
1140 dbox__clicked[dbox__click].s.w=d->wind;
1141 dbox__clicked[dbox__click].s.i=f;
1142 dbox__clicked[dbox__click].d=d;
1144 if (wimpt_last_event()->e!=wimp_EKEY && !(wimpt_options() & 7))
1146 dbox__clicked[dbox__click].d=0;
1151 if (wimpt_options() & wimpt_OSCULPTRIX)
1152 wimpt_noerr(sculptrix_slabIcon(d->wind,f,&dbox__clicked[dbox__click].s));
1153 if (wimpt_options() & wimpt_OINTERFACE)
1157 m.bbits=(dbox_wasAdjustClick() ? wimp_BRIGHT : wimp_BLEFT);
1159 wimpt_noerr(interface_slabButton(&m));
1161 if (!(wimpt_options() & 7))
1162 dbox_selecticon(d,f,dbox_SETSTATE);
1167 * void dbox_unclick(void)
1170 * This routine declicks the last icon to be 'dbox_clickicon'ed. If you
1171 * intend to delete the dbox after the click, you should use code like
1179 void dbox_unclick(void)
1185 werr(TRUE,msgs_lookup("dboxCSU:(dbox_unclick): Click stack underflow."));
1190 if (dbox__clicked[dbox__click].d)
1192 if (wimpt_options() & wimpt_OSCULPTRIX)
1193 wimpt_noerr(sculptrix_unslabIcon(&dbox__clicked[dbox__click].s));
1194 if (wimpt_options() & wimpt_OINTERFACE)
1196 m.w=dbox__clicked[dbox__click].s.w;
1197 m.i=dbox__clicked[dbox__click].s.i;
1199 wimpt_noerr(interface_slabButton(&m));
1201 if (!(wimpt_options() & 7))
1203 dbox_selecticon(dbox__clicked[dbox__click].d,
1204 dbox__clicked[dbox__click].s.i,
1211 * void dbox_unclickAll(void)
1214 * This call dbox_unclick()s all the 'dbox_clickicon'ed icons in the dbox.
1215 * You shouldn't really need to use it. It's mainly there for consistency
1216 * with Armen's WimpLib v. 3.00 (written ages ago, and only used by the
1217 * author). I've not needed to use it yet.
1220 void dbox_unclickAll(void)
1227 * void dbox_getfield(dbox d,dbox_field f,char *buffer,int size)
1230 * This is the same routine as in RISC_OSlib. It returns the contents of
1231 * the icon text in the buffer.
1234 void dbox_getfield(dbox d, dbox_field f, char *buffer, int size)
1236 wimp_icon *i = dbox__idef(d, f);
1240 if (i->flags & wimp_ITEXT)
1242 if (i->flags & wimp_INDIRECT)
1244 while (i->data.indirecttext.buffer[j] >= 32)
1246 from=i->data.indirecttext.buffer;
1250 while (i->data.text[j] >= 32 && j < 11)
1252 from=&i->data.text[0];
1256 memcpy(buffer,from,j);
1262 * void dbox_scanfield(dbox d,dbox_field f,char *format,...)
1265 * Reads in scanf()-style the contents of a field.
1268 * dbox d == the dbox handle
1269 * dbox_field f == the field number
1270 * char *format == a scanf() style format string
1273 void dbox_scanfield(dbox d,dbox_field f,char *format,...)
1277 va_start(ap,format);
1278 dbox_getfield(d,f,field,1024);
1279 vsscanf(field,format,ap);
1284 * BOOL dbox_selecticon(dbox d,dbox_field f,dbox_action a)
1287 * This call will read the icon's state of selection and return it, and
1288 * optionally alter it as specified in the dbox_action parameter.
1291 * dbox d == the dbox handle
1292 * dbox_field f == the field you're interested in
1293 * dbox_action a == what you want to do with it
1296 BOOL dbox_selecticon(dbox d,dbox_field f,dbox_action a)
1300 wimpt_noerr(wimp_get_icon_info(d->wind,f,&icn));
1302 selected=(icn.flags & wimp_ISELECTED) ? TRUE : FALSE;
1305 case dbox_READSTATE:
1311 icn.flags |= wimp_ISELECTED;
1313 case dbox_RESETSTATE:
1316 icn.flags &= ~wimp_ISELECTED;
1318 case dbox_TOGGLESTATE:
1319 icn.flags ^= wimp_ISELECTED;
1322 wimpt_noerr(wimp_set_icon_state
1326 icn.flags & wimp_ISELECTED,
1333 * BOOL dbox_shadeicon(dbox d,dbox_field f,dbox_action a)
1336 * This call will read the icon's state of shading and return it, and
1337 * optionally alter it as specified in the dbox_action parameter.
1340 * dbox d == the dbox handle
1341 * dbox_field f == the field you're interested in
1342 * dbox_action a == what you want to do with it
1345 BOOL dbox_shadeicon(dbox d,dbox_field f,dbox_action a)
1347 BOOL shaded; /* The old value of the shading */
1348 BOOL shade; /* Whether to shade the icon */
1349 wimp_icon *icn=dbox__idef(d,f); /* Find the icon in the window def */
1353 /* --- Get the current shading state --- */
1355 wimpt_noerr(wimp_get_icon_info(d->wind,f,&real));
1357 if (wimpt_options() & wimpt_ONOWIMPSHADE)
1358 shaded=!!(icn->flags & wimp_INOSELECT);
1360 shaded=!!(real.flags & wimp_INOSELECT);
1362 /* --- Find the new shading state --- */
1369 case dbox_RESETSTATE:
1372 case dbox_TOGGLESTATE:
1375 case dbox_READSTATE:
1381 /* --- If there's nothing to do, then don't do it --- */
1386 /* --- Do appropriate things to the icon --- */
1388 if (wimpt_options() & wimpt_ONOWIMPSHADE)
1400 if (wimp_readsysinfo(wimp_IFONTHANDLE,&fhandle))
1402 if (fhandle && (contents&wimp_ISPRITE))
1403 contents&=~wimp_ITEXT;
1405 if (contents!=wimp_ITEXT)
1406 new=new | 0x00400000;
1407 if (contents & wimp_ITEXT)
1408 new=(new & ~0x0f1ff000) | 0x021f0000;
1409 icn->flags=old | 0x00400000;
1410 wimpt_noerr(wimp_set_icon_state(d->wind,f,new,0xffffffff));
1414 icn->flags = (icn->flags & 0x0f1ff000) | (real.flags & 0xf0a00fff);
1415 wimpt_noerr(wimp_set_icon_state(d->wind,f,icn->flags,0xffffffff));
1417 if (wimpt_options() & wimpt_OSCULPTRIX)
1418 wimpt_noerr(sculptrix_updateIcon(d->wind,f));
1421 wimpt_noerr(wimp_set_icon_state(d->wind,f,shade<<22,0x00400000));
1425 wimpt_noerr(wimp_get_caret_pos(&c));
1426 if (c.w==d->wind && c.i==f)
1430 wimpt_noerr(wimp_set_caret_pos(&c));
1434 /* --- Now return the original value --- */
1440 * wimp_w dbox_syshandle(dbox d)
1443 * Returns the window handle used by the dbox specified, because your poor
1444 * underprivileged code can't access my nice data structure. This is for
1445 * setting up things like calls to event_attachmenu and suchlike, which
1446 * don't know about cunning things like dboxes.
1449 * dbox d == the dbox you're interested in
1452 * The window handle, which is a wimp_w
1455 wimp_w dbox_syshandle(dbox d)
1461 * int dbox_getNumeric(dbox d,dbox_field f)
1464 * Reads an integer from a field. If there is no semblance to a valid
1465 * integer, 0 is returned.
1468 * dbox d == the dbox handle
1469 * dbox_field f == the field to read from
1472 int dbox_getNumeric(dbox d,dbox_field f)
1475 dbox_scanfield(d,f,"%d",&val);
1480 * void dbox_setNumeric(dbox d,dbox_field f,int val)
1483 * Writes the integer value specified into the field.
1486 * dbox d == the dbox handle
1487 * dbox_field f == the field to set
1488 * int val == the integer value to write
1491 void dbox_setNumeric(dbox d,dbox_field f,int val)
1493 dbox_setfield(d,f,"%i",val);
1497 * dbox_field dbox_helpField(void)
1500 * Returns field number that Help is interested in.
1506 dbox_field dbox_helpField(void)
1508 wimp_eventstr *e=wimpt_last_event();
1514 win=e->data.msg.data.helprequest.m.w;
1515 icon=e->data.msg.data.helprequest.m.i;
1516 wimpt_noerr(wimp_get_icon_info(win,icon,&icn));
1517 if ((wimpt_options() & wimpt_ONOWIMPSHADE) &&
1518 (icn.flags & 0x001f0000) == 0x001f0000)
1527 msgs_lookup("dboxHFE:(dbox_helpField, caller fault): "
1528 "Not called on HELPREQUEST event.")
1533 /*----- Routines for Elite-style monologue boxes --------------------------*/
1536 * void dbox_setEmbeddedTitle(dbox d,dbox_field icon,BOOL moveDrag)
1539 * Gives the specified dialogue box an inbuilt title (in a group box, round
1540 * the outside, as seen in Elite). This is drawn automatically normally,
1541 * but raw event handlers might want to do extra drawing, so the entry
1542 * point to the redraw code is also supplied.
1545 * dbox d == the dialogue box to do this to
1546 * dbox_field icon == the icon around which the title is to be drawn
1547 * BOOL moveDrag == allow a click on any of the dialogue box to move it
1550 void dbox_setEmbeddedTitle(dbox d,dbox_field icon,BOOL moveDrag)
1553 d->moveDrag=moveDrag;
1557 * void dbox_drawEmbeddedTitle(wimp_redrawstr *r,void *handle)
1560 * Redraws an embedded title (as seen in Elite). This is for the use of
1561 * raw event handlers, which might want to do this sort of thing, because
1562 * the redraw is normally handled automatically.
1565 * wimp_redrawstr *r == the redraw information I need
1566 * void *handle == a dbox, really. This is for passing to wimpt_redraw.
1569 void dbox_drawEmbeddedTitle(wimp_redrawstr *r,void *handle)
1572 char *t=d->windDef->title.indirecttext.buffer;
1576 if (d->titleIcon==-1)
1578 for (len=0;t[len]>31;len++)
1581 if (wimpt_options() & wimpt_OSCULPTRIX)
1583 /* --- We've got Sculptrix, so do a really good job --- *
1585 * Since Sculptrix can do proper ridge/plinth intersections, we use this
1588 * It now does the whole job in one go.
1591 sculptrix_plotGroupBox(dbox__idef(d,d->titleIcon),r,0,t);
1595 border.box=dbox__idef(d,d->titleIcon)->box;
1596 border.flags=wimp_ITEXT | wimp_INDIRECT;
1598 title.box.x0=border.box.x0+16;
1599 title.box.y0=border.box.y1-20;
1600 title.box.x1=border.box.x0+32+wimpt_stringWidth(t);
1601 title.box.y1=border.box.y1+28;
1602 title.flags=wimp_ITEXT |
1607 title.data.indirecttext.buffer=t;
1608 title.data.indirecttext.bufflen=len+1;
1610 if (wimpt_options() & wimpt_OINTERFACE)
1612 /* --- We can make do with Interface, although it isn't as nice --- *
1614 * Interface makes a passable job at ridge-and-plinth group borders,
1615 * though they're not as nice as Sculptrix's, because the ridged border
1616 * doesn't intersect the title plinth properly.
1619 border.data.indirecttext.validstring="Z1,0,0,4,0";
1620 title.data.indirecttext.validstring="Z0,0,0,4,0";
1622 _swi(XInterface_Plot3dIcon,_inr(0,1),r,&title);
1623 _swi(XInterface_Plot3dIcon,_inr(0,1),r,&border);
1627 /* --- Use RISC OS 3 borders if available --- *
1629 * If not, RISC OS 2 will just plot a black border, which should look OK
1630 * although not as nice. Note that we can't do the STASIS-conforming
1631 * ridge-and-plinth group box, although a channel will do at a pinch.
1638 border.flags |= wimp_IBORDER;
1639 border.data.indirecttext.validstring="r4";
1640 border.data.indirecttext.buffer="";
1641 border.data.indirecttext.bufflen=1;
1642 title.data.indirecttext.validstring=(char *)-1;
1643 wimp_ploticon(&border);
1645 wimp_ploticon(&title);
1649 * BOOL dbox_hasTitle(dbox d)
1652 * Returns TRUE if the given dialogue box has a window title bar.
1655 * dbox d == the dialogue box to check
1658 * TRUE if the dialogue box has a title bar
1661 BOOL dbox_hasTitle(dbox d)
1663 return (!!(d->windDef->flags & wimp_WTITLE));