Initial revision
[ssr] / StraySrc / Libraries / Steel / c / dbox
1 /*
2 * dbox
3 * further dialogue box routines for Straylight apps
4 *
5 * v. 1.02 (10 August 1993)
6 *
7 * © 1993-1998 Straylight
8 */
9
10 /*----- Licensing note ----------------------------------------------------*
11 *
12 * This file is part of Straylight's Steel library.
13 *
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)
17 * any later version.
18 *
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.
23 *
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.
27 */
28
29 #define dbox__INTERNALS
30
31 #include "event.h"
32 #include "wimpt.h"
33 #include "wimp.h"
34 #include "interface.h"
35 #include "sculptrix.h"
36 #include "werr.h"
37 #include "template.h"
38 #include "win.h"
39 #include "dbox.h"
40 #include "msgs.h"
41 #include "bbc.h"
42 #include "mem.h"
43 #include "akbd.h"
44 #include "os.h"
45 #include "swiv.h"
46 #include "swis.h"
47 #include "help.h"
48 #include "vsscanf.h"
49 #include <string.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <stdarg.h>
53
54 #include "dll.h"
55
56 #ifndef _dll_NODLL
57 extern void _dllEntry(dbox__eventhandler)(wimp_eventstr *e,void *handle);
58 #endif
59
60 wimp_w dbox_menuDboxWindow(void);
61
62 /*
63 * The big one - the data needed to manage the dbox system. This IS a dbox.
64 */
65 typedef struct dbox__dboxstr
66 {
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 */
81 }
82 dbox__dboxstr;
83
84 /*
85 * A structure for passing to the dbox__fillinHandler() routine to make sure
86 * that the thing runs smoothly.
87 */
88 typedef struct
89 {
90 dbox_field f; /* The clicked field, or -2 */
91 }
92 dbox__fillinstr;
93
94 #define dbox__CLICKMAX 10 /* Number of clicks which fit in stack */
95
96 typedef struct
97 {
98 dbox d;
99 sculptrix_slabDescriptor s;
100 }
101 dbox__cstackstr;
102
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? */
109
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? */
113
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 */
116 /* requests. */
117 wimp_w dbox__menuDboxWindow(void)
118 {
119 return (dbox__menuDbox->wind);
120 }
121
122 /*
123 * void dbox__rms(dbox__mf f,dbox__esm esm,dbox__ddb ddb)
124 *
125 * Use
126 * Registers support functions for handling an alternative menu handling
127 * system (e.g. TMS).
128 */
129
130 void dbox__rms(dbox__mf f,dbox__esm esm,dbox__ddb ddb)
131 {
132 dbox__tmsmf=f;
133 dbox__tmsesm=esm;
134 dbox__tmsddb=ddb;
135 }
136
137 /*
138 * BOOL wasAdjustClick(void)
139 *
140 * Use
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.
144 *
145 * Returns
146 * TRUE if the last event WAS caused by an adjust click.
147 */
148
149 BOOL dbox_wasAdjustClick(void)
150 {
151 wimp_eventstr *e=wimpt_last_event();
152 if ((e->e==wimp_EBUT && e->data.but.m.bbits==wimp_BRIGHT)||dbox__shiftRet)
153 return (TRUE);
154 else
155 return (FALSE);
156 }
157
158 /*
159 * wimp_icon *dbox__idef(dbox d,wimp_i i)
160 *
161 * Use
162 * This routine returns a pointer to the icon definition specified.
163 *
164 * Parameters
165 * dbox d == dbox handle
166 * wimp_i i == the icon handle
167 *
168 * Returns
169 * A pointer to the icon definition.
170 */
171
172 #define dbox__idef(d,i) ((wimp_icon *)((d)->windDef+1)+(i))
173
174 #ifdef notdef
175 static wimp_icon *dbox__idef(dbox d,wimp_i i)
176 {
177 return ((wimp_icon *)(d->windDef+1)+i);
178 }
179 #endif
180
181 /*
182 * int dbox__fieldlength(dbox d,dbox_field f)
183 *
184 * Use
185 * Returns the length of the text in field specified
186 *
187 * Parameters
188 * dbox d == dbox handle
189 * dbox_field f == field number (icon handle to the uninitiated!)
190 *
191 * Returns
192 * The length of the field. Why isn't this a size_t?
193 */
194
195 static int dbox__fieldlength(dbox d, dbox_field f)
196 {
197 char a[255];
198 dbox_getfield((dbox) d, f, a, 255);
199 return(strlen(a));
200 }
201
202 /*
203 * void dbox__nextWritable(BOOL fromTop,dbox d,BOOL forward)
204 *
205 * Use
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
210 * in view.
211 *
212 * Parameters
213 * BOOL fromTop == whether you want to move to an extremity, or just up or
214 * down one.
215 * dbox d == the dbox you think the caret is in. If it isn't, you're in
216 * deep sh*te.
217 * BOOL forward == whether you want to search forward or backward from your
218 * starting position.
219 */
220
221 static void dbox__nextWritable(BOOL fromTop,dbox d,BOOL forwards)
222 {
223 wimp_caretstr c;
224 wimp_icon idef;
225 wimp_i i;
226 int iterations;
227 int dir;
228 int bt;
229 wimp_wstate state;
230 int sw,sh,ox,oy;
231 wimpt_noerr(wimp_get_caret_pos(&c));
232 if (forwards)
233 dir=1;
234 else
235 dir=-1;
236 if (fromTop)
237 {
238 if (forwards)
239 i=0;
240 else
241 i=d->windDef->nicons;
242 }
243 else
244 i=c.i+dir;
245 for (iterations=0;iterations<d->windDef->nicons;iterations++,i+=dir)
246 {
247 if (i>d->windDef->nicons)
248 {
249 i=-1;
250 iterations--;
251 continue;
252 }
253 if (i<0)
254 {
255 i=d->windDef->nicons+1;
256 iterations--;
257 continue;
258 }
259 wimpt_noerr(wimp_get_icon_info(d->wind,i,&idef));
260 bt=(((int)idef.flags)>>12) & 15;
261 if
262 (
263 (bt==15 || bt==14) &&
264 ((idef.flags & wimp_INOSELECT)==0) &&
265 ((idef.flags & wimp_IDELETED)==0)
266 )
267 break;
268 }
269 if (iterations==d->windDef->nicons)
270 return;
271 c.w=d->wind;
272 c.i=i;
273 c.height=-1;
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));
290 }
291
292 /*
293 * void dbox__checkRadio(dbox d,dbox_field f)
294 *
295 * Use
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.
299 *
300 * Parameters
301 * dbox d == the dbox containing the clicked field
302 * dbox_field f == the field wot was clicked
303 */
304
305 static void dbox__checkRadio(dbox d,dbox_field f)
306 {
307 wimp_icon *idef=dbox__idef(d,f);
308 int esg;
309 int i;
310 if ((idef->flags & 0x0000F000) == (wimp_BCLICKDEBOUNCE<<12))
311 {
312 esg=idef->flags & 0x001F0000;
313 if (esg)
314 {
315 dbox_selecticon(d,f,TRUE);
316 idef=dbox__idef(d,0);
317 for (i=0;i<d->windDef->nicons;i++,idef++)
318 {
319 if (i!=f && (idef->flags & 0x001F0000)==esg)
320 dbox_selecticon(d,i,FALSE);
321 }
322 }
323 }
324 }
325
326 /*
327 * void dbox__eventhandler(wimp_eventstr *e,void *handle)
328 *
329 * Use
330 * Event handler for dboxes. Handles ops as follows:
331 *
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.
340 *
341 * Parameters
342 * wimp_eventstr *e == a pointer to the current WIMP event
343 * void *handle == the jolly old handle, which is a pointer to the
344 * dbox__dboxstr.
345 */
346
347 _dll_static void dbox__eventhandler(wimp_eventstr *e,void *handle)
348 {
349 dbox d=(dbox)handle;
350 BOOL handled=FALSE;
351
352 dbox__shiftRet=FALSE;
353 if (d->rawEventProc)
354 handled=(d->rawEventProc)(d,e,(void *)d->rawEventHandle);
355 if (!handled)
356 {
357 switch (e->e)
358 {
359 case wimp_EREDRAW:
360 if (d->titleIcon!=-1)
361 wimpt_redraw(dbox_drawEmbeddedTitle,d);
362 else
363 wimpt_redraw(0,0);
364 break;
365 case wimp_EOPEN:
366 wimpt_noerr(wimp_open_wind(&e->data.o));
367 break;
368 case wimp_ECLOSE:
369 if (d->eventProc)
370 (d->eventProc)(d,dbox_CLOSE,d->eventHandle);
371 break;
372 case wimp_EBUT:
373 if (e->data.but.m.bbits==wimp_BRIGHT ||
374 e->data.but.m.bbits==wimp_BLEFT)
375 {
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);
379 if (d->moveDrag)
380 {
381 wimp_dragstr dr;
382 dr.window=d->wind;
383 dr.type=wimp_MOVE_WIND;
384 wimp_drag_box(&dr);
385 }
386 }
387 break;
388 case wimp_EKEY:
389 switch (akbd_translate(e->data.key.chcode))
390 {
391 case key_sReturn:
392 case key_skEnter:
393 dbox__shiftRet=TRUE;
394 /* Treat as normal return */
395 case key_Return:
396 case key_kEnter:
397 if (d->eventProc && !dbox_shadeicon(d,0,dbox_READSTATE))
398 (d->eventProc)(d,0,d->eventHandle);
399 break;
400 case key_sEsc:
401 dbox__shiftRet=TRUE;
402 /* Treat as normal Escape */
403 case key_Esc:
404 if (d->eventProc && !dbox_shadeicon(d,1,dbox_READSTATE))
405 (d->eventProc)(d,1,d->eventHandle);
406 break;
407 case key_Down:
408 case key_Tab:
409 dbox__nextWritable(FALSE,d,TRUE);
410 break;
411 case key_sTab:
412 case key_Up:
413 dbox__nextWritable(FALSE,d,FALSE);
414 break;
415 case key_cDown:
416 dbox__nextWritable(TRUE,d,FALSE);
417 break;
418 case key_cUp:
419 dbox__nextWritable(TRUE,d,TRUE);
420 break;
421 default:
422 wimp_processkey(e->data.key.chcode);
423 break;
424 }
425 break;
426 case wimp_ESEND:
427 case wimp_ESENDWANTACK:
428 switch (e->data.msg.hdr.action)
429 {
430 case wimp_MHELPREQUEST:
431 if (d->eventProc)
432 (d->eventProc)(d,dbox_HELP,d->eventHandle);
433 break;
434 }
435 break;
436 }
437 }
438 }
439
440 /*
441 * dbox dbox_create(char *template)
442 *
443 * Use
444 * Creates a dbox from a template and returns a handle to it. It calls
445 * werr() sensibly with nice messages if it failed.
446 *
447 * Parameters
448 * char *name == name of template to use
449 *
450 * Returns
451 * Abstract handle to dbox or NULL if the dbox could not be
452 * created
453 */
454
455 dbox dbox_create(char *name)
456 {
457 template *temp=template_find(name);
458 wimp_wind *w=template_syshandle(name);
459 dbox d=(dbox)mem_alloc(sizeof(dbox__dboxstr));
460 wimp_icon *icn;
461 int i;
462 BOOL unshade=wimpt_options() & wimpt_ONOWIMPSHADE;
463 if (d)
464 {
465 if (d->windDef=(wimp_wind *)mem_alloc
466 (
467 sizeof(wimp_wind)+w->nicons*sizeof(wimp_icon)
468 ),
469 d->windDef==0)
470 {
471 mem_free(d);
472 werr
473 (
474 FALSE,
475 msgs_lookup("dboxNEM:Not enough memory for new dialogue box.")
476 );
477 return (0);
478 }
479 memcpy(d->windDef,w,sizeof(wimp_wind)+w->nicons*sizeof(wimp_icon));
480 if (temp->workspacesize!=0)
481 {
482 if (d->indirect=(char *)mem_alloc(temp->workspacesize),d->indirect==0)
483 {
484 mem_free(d->windDef);
485 mem_free(d);
486 werr
487 (
488 FALSE,
489 msgs_lookup("dboxNEM:Not enough memory for new dialogue box.")
490 );
491 return (0);
492 }
493 memcpy(d->indirect,temp->workspace,temp->workspacesize);
494 for (i=0;i<d->windDef->nicons;i++)
495 {
496 icn=dbox__idef(d,i);
497 if (unshade)
498 icn->flags &= 0xffbfffff;
499 if ((icn->flags&wimp_INDIRECT)!=0)
500 {
501 icn->data.indirecttext.buffer+=d->indirect-temp->workspace;
502 if ((icn->flags&3)==2)
503 icn->data.indirectsprite.spritearea=(void *)1;
504 else
505 {
506 if (icn->data.indirecttext.validstring!=(char *)-1)
507 {
508 icn->data.indirecttext.validstring+=
509 d->indirect-temp->workspace;
510 }
511 }
512 }
513 }
514 if (d->windDef->titleflags&wimp_INDIRECT)
515 {
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;
519 else
520 {
521 if (d->windDef->title.indirecttext.validstring!=(char *)-1)
522 {
523 d->windDef->title.indirecttext.validstring+=
524 d->indirect-temp->workspace;
525 }
526 }
527 }
528 }
529 else
530 d->indirect=0;
531 if (wimp_create_wind(d->windDef,&d->wind)==0)
532 {
533 d->eventProc=0;
534 d->rawEventProc=0;
535 d->isOpen=FALSE;
536 d->isStatic=FALSE;
537 d->titleIcon=-1;
538 d->moveDrag=FALSE;
539 d->temp=w;
540 win_activeinc();
541 win_register_event_handler(d->wind,_dllEntry(dbox__eventhandler),d);
542 }
543 else
544 {
545 mem_free(d->windDef);
546 mem_free(d->indirect);
547 mem_free(d);
548 d=0;
549 werr
550 (
551 FALSE,
552 msgs_lookup("dboxTMW:Too many windows - "
553 "%s could not create window/dialogue box."),
554 wimpt_programname()
555 );
556 }
557 }
558 else
559 werr
560 (
561 FALSE,
562 msgs_lookup("dboxNEM:Not enough memory for new dialogue box.")
563 );
564 return (d);
565 }
566
567 /*
568 * void dbox__setMenuDbox(dbox d)
569 *
570 * Use
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
575 * event_process().
576 *
577 * Parameters
578 * dbox d == the new prospective menu dbox.
579 */
580
581 static void dbox__setMenuDbox(dbox d)
582 {
583 dbox__menuDbox=d;
584 }
585
586 /*
587 * void dbox_display(dbox d,dbox_openType how)
588 *
589 * Use
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.
593 *
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.
597 *
598 * Parameters
599 * dbox d == dbox handle
600 * dbox_openType how == how you want the dbox opened
601 */
602
603 void dbox_display(dbox d,dbox_openType how)
604 {
605 wimp_wstate state;
606 int scx=wimpt_scwidth();
607 int scy=wimpt_scheight();
608 int w;
609 int h;
610 wimp_caretstr c;
611 wimp_eventstr *e;
612 int x;
613 int y;
614
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;
619 d->isStatic=TRUE;
620 switch (how)
621 {
622 case dbox_MENU_OVERPTR:
623 d->isStatic=FALSE;
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;
630 break;
631 case dbox_MENU_LASTPOS:
632 d->isStatic=FALSE;
633 case dbox_STATIC_LASTPOS:
634 /* Nothin' doin' */
635 break;
636 case dbox_MENU_CENTRE:
637 d->isStatic=FALSE;
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;
643 break;
644 }
645 win_adjustBox(&state.o);
646 if (d->isStatic)
647 {
648 wimpt_noerr(wimp_open_wind(&state.o));
649 if (!d->isOpen)
650 {
651 d->isOpen=TRUE;
652 d->isStatic=TRUE;
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));
657 if (c.w!=d->wind)
658 d->restoreCaret=FALSE;
659 else
660 {
661 c.i=-1;
662 c.x=-500000;
663 c.height=0x2000000;
664 wimpt_noerr(wimp_set_caret_pos(&c));
665 }
666 }
667 }
668 else
669 {
670 if (dbox_wasSubmenu() && (wimpt_last_event()->e==wimp_ESEND ||
671 wimpt_last_event()->e==wimp_ESENDWANTACK))
672 {
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;
678 }
679 else if (dbox__tmsesm && dbox__tmsesm())
680 {
681 dbox__tmsmf(&x,&y);
682 state.o.box.x0=x;
683 state.o.box.x1=x+w;
684 state.o.box.y0=y-h;
685 state.o.box.y1=y;
686 dbox__tmsddb(&state.o);
687 wimpt_noerr(wimp_get_caret_pos(&d->oldCaret));
688 d->restoreCaret=TRUE;
689 dbox__nextWritable(TRUE,d,TRUE);
690 }
691 else
692 {
693 wimpt_noerr(wimp_create_menu(
694 (wimp_menustr *)d->wind,
695 state.o.box.x0,
696 state.o.box.y1
697 ));
698 d->restoreCaret=FALSE;
699 }
700 d->isOpen=TRUE;
701 d->isStatic=FALSE;
702 dbox__setMenuDbox(d);
703 }
704 }
705
706 /*
707 * void dbox_openDisplaced(dbox d)
708 *
709 * Use
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
714 * dbox, of course.
715 *
716 * Parameters
717 * dbox d == the dbox
718 */
719
720 void dbox_openDisplaced(dbox d)
721 {
722 int new=0;
723 wimp_wstate s;
724 wimp_caretstr c;
725 if (d->isOpen)
726 {
727 werr
728 (
729 TRUE,
730 msgs_lookup("dboxCOD:(dbox_openDisplaced): "
731 "failed - dbox already open.")
732 );
733 }
734 if (d->temp->box.y0-48<132)
735 {
736 new=((976-d->temp->box.y1)/48-4)*48+d->temp->box.y1;
737 d->temp->box.y0+=new-d->temp->box.y1;
738 d->temp->box.y1=new;
739 }
740 else
741 {
742 d->temp->box.y0-=48;
743 d->temp->box.y1-=48;
744 }
745 wimpt_noerr(wimp_get_wind_state(d->wind,&s));
746 s.o.box=d->temp->box;
747 s.o.behind=-1;
748 wimpt_noerr(wimp_open_wind(&s.o));
749 d->isOpen=TRUE;
750 d->isStatic=TRUE;
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));
755 if (c.w!=d->wind)
756 d->restoreCaret=FALSE;
757 else
758 {
759 wimpt_noerr(wimp_open_wind(&s.o));
760 c.i=-1;
761 c.x=-500000;
762 wimpt_noerr(wimp_set_caret_pos(&c));
763 }
764 }
765
766 /*
767 * void dbox_hide(dbox d)
768 *
769 * Use
770 * Closes the dbox specified in whatever manner necessary to stop it being
771 * seen. The window can still be created real easy.
772 *
773 * Parameters
774 * dbox d == dialogue box handle
775 */
776
777 void dbox_hide(dbox d)
778 {
779 if (d==dbox__menuDbox)
780 {
781 if (!dbox__closedForUs)
782 event_clear_current_menu();
783 dbox__menuDbox=0;
784 }
785 wimpt_noerr(wimp_close_wind(d->wind));
786 if (d->restoreCaret)
787 wimp_set_caret_pos(&d->oldCaret);
788 d->isOpen=FALSE;
789 }
790
791 /*
792 * void dbox_deleteNoUpdate(dbox d)
793 *
794 * Use
795 * Zaps a dbox without storing the thing's position away, so it reappears
796 * where you want it.
797 *
798 * Parameters
799 * dbox d == the handle
800 */
801
802 void dbox_deleteNoUpdate(dbox d)
803 {
804 if (d->isOpen)
805 dbox_hide(d);
806 win_register_event_handler(d->wind,0,0);
807 win_activedec();
808 wimpt_noerr(wimp_delete_wind(d->wind));
809 mem_free(d->indirect);
810 mem_free(d->windDef);
811 mem_free(d);
812 }
813
814 /*
815 * void dbox_updatePosition(dbox d)
816 *
817 * Use
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.
820 *
821 * Parameters
822 * dbox d == the dbox handle
823 */
824
825 void dbox_updatePosition(dbox d)
826 {
827 wimp_wstate s;
828 wimp_get_wind_state(d->wind,&s);
829 d->temp->box=s.o.box;
830 }
831
832 /*
833 * void dbox_delete(dbox d)
834 *
835 * Use
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
838 * space is freed.
839 *
840 * Parameters
841 * dbox d == dialogue box handle
842 */
843
844 void dbox_delete(dbox d)
845 {
846 if (d->isStatic)
847 dbox_updatePosition(d);
848 dbox_deleteNoUpdate(d);
849 }
850
851 /*
852 * void dbox_eventHandler(dbox d,dbox_eventhandler proc,void *handle)
853 *
854 * Use
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().
858 *
859 * Parameters
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.
863 */
864
865 void dbox_eventHandler(dbox d,dbox_eventhandler proc,void *handle)
866 {
867 d->eventProc=proc;
868 d->eventHandle=handle;
869 }
870
871 /*
872 * void dbox_rawEventHandler(dbox d,dbox_raweventhandler proc,void *handle)
873 *
874 * Use
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
879 * did.
880 *
881 * Parameters
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.
885 */
886
887 void dbox_rawEventHandler(dbox d,dbox_raweventhandler proc,void *handle)
888 {
889 d->rawEventProc=proc;
890 d->rawEventHandle=handle;
891 }
892
893 /*
894 * void dbox__fillinHandler(dbox d,dbox_field clicked,void *handle)
895 *
896 * Use
897 * This is the dbox handler used by dbox_fillin().
898 *
899 * Parameters
900 * dbox d == the dbox handle
901 * dbox_field == the field that was clicked
902 * void *handle == a pointer to a dbox__fillinstr
903 */
904
905 static void dbox__fillinHandler(dbox d,dbox_field clicked,void *handle)
906 {
907 dbox__fillinstr *f=(dbox__fillinstr *)handle;
908 d=d;
909 f->f=clicked;
910 }
911
912 /*
913 * dbox_field dbox_fillin(dbox d)
914 *
915 * Use
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.
921 *
922 * Parameters
923 * dbox d == the dbox handle
924 *
925 * Returns
926 * The field number that was clicked.
927 */
928
929 dbox_field dbox_fillin(dbox d)
930 {
931 dbox__fillinstr f;
932 if (d->isStatic)
933 {
934 werr
935 (
936 TRUE,
937 msgs_lookup("dboxFRE:(dbox_fillin, caller fault): "
938 "dbox_fillin only works with menu dboxes.")
939 );
940 }
941 f.f=dbox_ENDFILLIN;
942 dbox_eventHandler(d,dbox__fillinHandler,&f);
943 while (f.f==dbox_ENDFILLIN)
944 event_process();
945 dbox_eventHandler(d,0,0);
946 return (f.f);
947 }
948
949 /*
950 * void dbox_eventProcess(void)
951 *
952 * Use
953 * Part of the private interface between dbox and event for processing
954 * dialogue box events.
955 */
956
957 void dbox__eventProcess(void)
958 {
959 static wimp_eventstr real;
960 static BOOL faking;
961 wimp_eventstr fake;
962 wimp_wstate state;
963
964 dbox__closedForUs=FALSE;
965 if (faking)
966 {
967 wimpt_fake_event(&real);
968 faking=FALSE;
969 event__process();
970 return;
971 }
972 if (dbox__menuDbox)
973 {
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)
978 {
979 fake.e=wimp_ECLOSE;
980 fake.data.o.w=dbox__menuDbox->wind;
981 wimpt_fake_event(&fake);
982 dbox__closedForUs=TRUE /* (real.e!=wimp_EMENU) */ ;
983 faking=TRUE;
984 }
985 else
986 wimpt_fake_event(&real);
987 }
988 event__process();
989 }
990
991 /*
992 * void dbox_setfield(dbox d,dbox_field f,char *string,...)
993 *
994 * Use
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.
1001 *
1002 * Parameters
1003 * dbox d == the dbox
1004 * dbox_field f == the field
1005 * char *string == a printf-style format string
1006 */
1007
1008 void dbox_setfield(dbox d,dbox_field f,char *string,...)
1009 {
1010 wimp_icon *i=dbox__idef(d,f);
1011 wimp_caretstr c;
1012 va_list ap;
1013 char field[1024];
1014 int j;
1015 char *buff;
1016 BOOL different=FALSE;
1017 BOOL stop=FALSE;
1018 int max;
1019 char *fptr;
1020 BOOL dots=FALSE;
1021 char x,y;
1022 BOOL rJust=FALSE;
1023
1024 /* --- Construct the string to fill in the buffer --- *
1025 *
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.
1030 */
1031
1032 va_start(ap,string);
1033 if (string[0]=='%' && string[1]=='.')
1034 {
1035 dots=TRUE;
1036 string+=2;
1037 }
1038 if (!strcmp(string,"%s"))
1039 fptr=va_arg(ap,char *);
1040 else
1041 {
1042 vsprintf(field,string,ap);
1043 field[1023]=0;
1044 fptr=field;
1045 }
1046 va_end(ap);
1047
1048 /* --- Make sure the string's indirected --- */
1049
1050 if (!(i->flags & wimp_INDIRECT))
1051 {
1052 werr(TRUE,msgs_lookup("dboxSFNIND:(dbox_setfield, caller fault): "
1053 "Icon is not indirected."));
1054 }
1055
1056 /* --- Write the string to the icon, noting differences --- *
1057 *
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.
1061 */
1062
1063 buff=i->data.indirecttext.buffer;
1064 max=i->data.indirecttext.bufflen-1;
1065 j=strlen(fptr);
1066 if (j>max)
1067 {
1068 if (rJust=(i->flags & wimp_IRJUST),rJust)
1069 fptr+=j-max;
1070 }
1071 else
1072 dots=FALSE;
1073 j=0;
1074 while (!stop)
1075 {
1076 x=*buff++;
1077 y=*fptr++;
1078 if (max==j || y<' ')
1079 y=0;
1080 else if (dots && ((rJust && j<3) || (!rJust && max-j<4)))
1081 y='.';
1082 if (x<' ')
1083 x=0;
1084 if (x!=y)
1085 {
1086 different=TRUE;
1087 buff[-1]=y;
1088 }
1089 if (y)
1090 j++;
1091 else
1092 stop=TRUE;
1093 }
1094
1095 /* --- If the icon has changed, redraw it, and move the caret --- */
1096
1097 if (different)
1098 {
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)
1102 {
1103 if (c.index>j)
1104 {
1105 c.index=j;
1106 c.height=-1;
1107 }
1108 wimpt_noerr(wimp_set_caret_pos(&c));
1109 }
1110 }
1111 }
1112
1113 /*
1114 * void dbox_clickicon(dbox d,dbox_field f)
1115 *
1116 * Use
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)
1122 *
1123 * Parameters
1124 * dbox d == the dbox
1125 * dbox_field f == the field
1126 */
1127
1128 void dbox_clickicon(dbox d,dbox_field f)
1129 {
1130 wimp_mousestr m;
1131
1132 if (dbox__click==dbox__CLICKMAX)
1133 {
1134 werr(FALSE,
1135 msgs_lookup("dboxSTK:Only enough stack space for %i icons."),
1136 dbox__CLICKMAX);
1137 return;
1138 }
1139
1140 dbox__clicked[dbox__click].s.w=d->wind;
1141 dbox__clicked[dbox__click].s.i=f;
1142 dbox__clicked[dbox__click].d=d;
1143
1144 if (wimpt_last_event()->e!=wimp_EKEY && !(wimpt_options() & 7))
1145 {
1146 dbox__clicked[dbox__click].d=0;
1147 dbox__click++;
1148 return;
1149 }
1150
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)
1154 {
1155 m.w=d->wind;
1156 m.i=f;
1157 m.bbits=(dbox_wasAdjustClick() ? wimp_BRIGHT : wimp_BLEFT);
1158 m.x=m.y=0;
1159 wimpt_noerr(interface_slabButton(&m));
1160 }
1161 if (!(wimpt_options() & 7))
1162 dbox_selecticon(d,f,dbox_SETSTATE);
1163 dbox__click++;
1164 }
1165
1166 /*
1167 * void dbox_unclick(void)
1168 *
1169 * Use
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
1172 * this:
1173 *
1174 * dbox_hide(d);
1175 * dbox_unclick();
1176 * dbox_delete(d);
1177 */
1178
1179 void dbox_unclick(void)
1180 {
1181 wimp_mousestr m;
1182
1183 if (dbox__click==0)
1184 {
1185 werr(TRUE,msgs_lookup("dboxCSU:(dbox_unclick): Click stack underflow."));
1186 return;
1187 }
1188
1189 dbox__click--;
1190 if (dbox__clicked[dbox__click].d)
1191 {
1192 if (wimpt_options() & wimpt_OSCULPTRIX)
1193 wimpt_noerr(sculptrix_unslabIcon(&dbox__clicked[dbox__click].s));
1194 if (wimpt_options() & wimpt_OINTERFACE)
1195 {
1196 m.w=dbox__clicked[dbox__click].s.w;
1197 m.i=dbox__clicked[dbox__click].s.i;
1198 m.bbits=m.x=m.y=0;
1199 wimpt_noerr(interface_slabButton(&m));
1200 }
1201 if (!(wimpt_options() & 7))
1202 {
1203 dbox_selecticon(dbox__clicked[dbox__click].d,
1204 dbox__clicked[dbox__click].s.i,
1205 dbox_RESETSTATE);
1206 }
1207 }
1208 }
1209
1210 /*
1211 * void dbox_unclickAll(void)
1212 *
1213 * Use
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.
1218 */
1219
1220 void dbox_unclickAll(void)
1221 {
1222 while (dbox__click)
1223 dbox_unclick();
1224 }
1225
1226 /*
1227 * void dbox_getfield(dbox d,dbox_field f,char *buffer,int size)
1228 *
1229 * Use
1230 * This is the same routine as in RISC_OSlib. It returns the contents of
1231 * the icon text in the buffer.
1232 */
1233
1234 void dbox_getfield(dbox d, dbox_field f, char *buffer, int size)
1235 {
1236 wimp_icon *i = dbox__idef(d, f);
1237 int j = 0;
1238 char *from;
1239
1240 if (i->flags & wimp_ITEXT)
1241 {
1242 if (i->flags & wimp_INDIRECT)
1243 {
1244 while (i->data.indirecttext.buffer[j] >= 32)
1245 j++;
1246 from=i->data.indirecttext.buffer;
1247 }
1248 else
1249 {
1250 while (i->data.text[j] >= 32 && j < 11)
1251 j++;
1252 from=&i->data.text[0];
1253 }
1254 if (j>size)
1255 j=size;
1256 memcpy(buffer,from,j);
1257 }
1258 buffer[j]=0;
1259 }
1260
1261 /*
1262 * void dbox_scanfield(dbox d,dbox_field f,char *format,...)
1263 *
1264 * Use
1265 * Reads in scanf()-style the contents of a field.
1266 *
1267 * Parameters
1268 * dbox d == the dbox handle
1269 * dbox_field f == the field number
1270 * char *format == a scanf() style format string
1271 */
1272
1273 void dbox_scanfield(dbox d,dbox_field f,char *format,...)
1274 {
1275 char field[1024];
1276 va_list ap;
1277 va_start(ap,format);
1278 dbox_getfield(d,f,field,1024);
1279 vsscanf(field,format,ap);
1280 va_end(ap);
1281 }
1282
1283 /*
1284 * BOOL dbox_selecticon(dbox d,dbox_field f,dbox_action a)
1285 *
1286 * Use
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.
1289 *
1290 * Parameters
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
1294 */
1295
1296 BOOL dbox_selecticon(dbox d,dbox_field f,dbox_action a)
1297 {
1298 wimp_icon icn;
1299 BOOL selected;
1300 wimpt_noerr(wimp_get_icon_info(d->wind,f,&icn));
1301
1302 selected=(icn.flags & wimp_ISELECTED) ? TRUE : FALSE;
1303 switch (a)
1304 {
1305 case dbox_READSTATE:
1306 return (selected);
1307 break;
1308 case dbox_SETSTATE:
1309 if (selected)
1310 return (TRUE);
1311 icn.flags |= wimp_ISELECTED;
1312 break;
1313 case dbox_RESETSTATE:
1314 if (!selected)
1315 return (FALSE);
1316 icn.flags &= ~wimp_ISELECTED;
1317 break;
1318 case dbox_TOGGLESTATE:
1319 icn.flags ^= wimp_ISELECTED;
1320 break;
1321 }
1322 wimpt_noerr(wimp_set_icon_state
1323 (
1324 d->wind,
1325 f,
1326 icn.flags & wimp_ISELECTED,
1327 wimp_ISELECTED
1328 ));
1329 return (selected);
1330 }
1331
1332 /*
1333 * BOOL dbox_shadeicon(dbox d,dbox_field f,dbox_action a)
1334 *
1335 * Use
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.
1338 *
1339 * Parameters
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
1343 */
1344
1345 BOOL dbox_shadeicon(dbox d,dbox_field f,dbox_action a)
1346 {
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 */
1350 wimp_icon real;
1351 wimp_caretstr c;
1352
1353 /* --- Get the current shading state --- */
1354
1355 wimpt_noerr(wimp_get_icon_info(d->wind,f,&real));
1356
1357 if (wimpt_options() & wimpt_ONOWIMPSHADE)
1358 shaded=!!(icn->flags & wimp_INOSELECT);
1359 else
1360 shaded=!!(real.flags & wimp_INOSELECT);
1361
1362 /* --- Find the new shading state --- */
1363
1364 switch (a)
1365 {
1366 case dbox_SETSTATE:
1367 shade=TRUE;
1368 break;
1369 case dbox_RESETSTATE:
1370 shade=FALSE;
1371 break;
1372 case dbox_TOGGLESTATE:
1373 shade=!shaded;
1374 break;
1375 case dbox_READSTATE:
1376 default:
1377 shade=shaded;
1378 break;
1379 }
1380
1381 /* --- If there's nothing to do, then don't do it --- */
1382
1383 if (shade==shaded)
1384 return (shaded);
1385
1386 /* --- Do appropriate things to the icon --- */
1387
1388 if (wimpt_options() & wimpt_ONOWIMPSHADE)
1389 {
1390 wimp_iconflags old;
1391 wimp_iconflags new;
1392 int contents;
1393 int fhandle;
1394
1395 if (shade)
1396 {
1397 old=new=real.flags;
1398 contents=old & 3;
1399
1400 if (wimp_readsysinfo(wimp_IFONTHANDLE,&fhandle))
1401 fhandle=0;
1402 if (fhandle && (contents&wimp_ISPRITE))
1403 contents&=~wimp_ITEXT;
1404
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));
1411 }
1412 else
1413 {
1414 icn->flags = (icn->flags & 0x0f1ff000) | (real.flags & 0xf0a00fff);
1415 wimpt_noerr(wimp_set_icon_state(d->wind,f,icn->flags,0xffffffff));
1416 }
1417 if (wimpt_options() & wimpt_OSCULPTRIX)
1418 wimpt_noerr(sculptrix_updateIcon(d->wind,f));
1419 }
1420 else
1421 wimpt_noerr(wimp_set_icon_state(d->wind,f,shade<<22,0x00400000));
1422
1423 if (shade)
1424 {
1425 wimpt_noerr(wimp_get_caret_pos(&c));
1426 if (c.w==d->wind && c.i==f)
1427 {
1428 c.i=-1;
1429 c.x=-500000;
1430 wimpt_noerr(wimp_set_caret_pos(&c));
1431 }
1432 }
1433
1434 /* --- Now return the original value --- */
1435
1436 return (shaded);
1437 }
1438
1439 /*
1440 * wimp_w dbox_syshandle(dbox d)
1441 *
1442 * Use
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.
1447 *
1448 * Parameters
1449 * dbox d == the dbox you're interested in
1450 *
1451 * Returns
1452 * The window handle, which is a wimp_w
1453 */
1454
1455 wimp_w dbox_syshandle(dbox d)
1456 {
1457 return (d->wind);
1458 }
1459
1460 /*
1461 * int dbox_getNumeric(dbox d,dbox_field f)
1462 *
1463 * Use
1464 * Reads an integer from a field. If there is no semblance to a valid
1465 * integer, 0 is returned.
1466 *
1467 * Parameters
1468 * dbox d == the dbox handle
1469 * dbox_field f == the field to read from
1470 */
1471
1472 int dbox_getNumeric(dbox d,dbox_field f)
1473 {
1474 int val;
1475 dbox_scanfield(d,f,"%d",&val);
1476 return (val);
1477 }
1478
1479 /*
1480 * void dbox_setNumeric(dbox d,dbox_field f,int val)
1481 *
1482 * Use
1483 * Writes the integer value specified into the field.
1484 *
1485 * Parameters
1486 * dbox d == the dbox handle
1487 * dbox_field f == the field to set
1488 * int val == the integer value to write
1489 */
1490
1491 void dbox_setNumeric(dbox d,dbox_field f,int val)
1492 {
1493 dbox_setfield(d,f,"%i",val);
1494 }
1495
1496 /*
1497 * dbox_field dbox_helpField(void)
1498 *
1499 * Use
1500 * Returns field number that Help is interested in.
1501 *
1502 * Returns
1503 * Field number.
1504 */
1505
1506 dbox_field dbox_helpField(void)
1507 {
1508 wimp_eventstr *e=wimpt_last_event();
1509 int icon;
1510 int win;
1511 wimp_icon icn;
1512 if (help_wasHelp())
1513 {
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)
1519 return (-1);
1520 else
1521 return (icon);
1522 }
1523 else
1524 werr
1525 (
1526 TRUE,
1527 msgs_lookup("dboxHFE:(dbox_helpField, caller fault): "
1528 "Not called on HELPREQUEST event.")
1529 );
1530 return (0);
1531 }
1532
1533 /*----- Routines for Elite-style monologue boxes --------------------------*/
1534
1535 /*
1536 * void dbox_setEmbeddedTitle(dbox d,dbox_field icon,BOOL moveDrag)
1537 *
1538 * Use
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.
1543 *
1544 * Parameters
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
1548 */
1549
1550 void dbox_setEmbeddedTitle(dbox d,dbox_field icon,BOOL moveDrag)
1551 {
1552 d->titleIcon=icon;
1553 d->moveDrag=moveDrag;
1554 }
1555
1556 /*
1557 * void dbox_drawEmbeddedTitle(wimp_redrawstr *r,void *handle)
1558 *
1559 * Use
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.
1563 *
1564 * Parameters
1565 * wimp_redrawstr *r == the redraw information I need
1566 * void *handle == a dbox, really. This is for passing to wimpt_redraw.
1567 */
1568
1569 void dbox_drawEmbeddedTitle(wimp_redrawstr *r,void *handle)
1570 {
1571 dbox d=handle;
1572 char *t=d->windDef->title.indirecttext.buffer;
1573 wimp_icon title;
1574 wimp_icon border;
1575 int len;
1576 if (d->titleIcon==-1)
1577 return;
1578 for (len=0;t[len]>31;len++)
1579 /* blank */ ;
1580
1581 if (wimpt_options() & wimpt_OSCULPTRIX)
1582 {
1583 /* --- We've got Sculptrix, so do a really good job --- *
1584 *
1585 * Since Sculptrix can do proper ridge/plinth intersections, we use this
1586 * in preference.
1587 *
1588 * It now does the whole job in one go.
1589 */
1590
1591 sculptrix_plotGroupBox(dbox__idef(d,d->titleIcon),r,0,t);
1592 return;
1593 }
1594
1595 border.box=dbox__idef(d,d->titleIcon)->box;
1596 border.flags=wimp_ITEXT | wimp_INDIRECT;
1597
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 |
1603 wimp_INDIRECT |
1604 wimp_IFILLED |
1605 wimp_IHCENTRE |
1606 0x17000000;
1607 title.data.indirecttext.buffer=t;
1608 title.data.indirecttext.bufflen=len+1;
1609
1610 if (wimpt_options() & wimpt_OINTERFACE)
1611 {
1612 /* --- We can make do with Interface, although it isn't as nice --- *
1613 *
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.
1617 */
1618
1619 border.data.indirecttext.validstring="Z1,0,0,4,0";
1620 title.data.indirecttext.validstring="Z0,0,0,4,0";
1621
1622 _swi(XInterface_Plot3dIcon,_inr(0,1),r,&title);
1623 _swi(XInterface_Plot3dIcon,_inr(0,1),r,&border);
1624 }
1625 else
1626 {
1627 /* --- Use RISC OS 3 borders if available --- *
1628 *
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.
1632 */
1633
1634 border.box.x0-=8;
1635 border.box.y0-=8;
1636 border.box.x1+=8;
1637 border.box.y1+=8;
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);
1644 }
1645 wimp_ploticon(&title);
1646 }
1647
1648 /*
1649 * BOOL dbox_hasTitle(dbox d)
1650 *
1651 * Use
1652 * Returns TRUE if the given dialogue box has a window title bar.
1653 *
1654 * Parameters
1655 * dbox d == the dialogue box to check
1656 *
1657 * Returns
1658 * TRUE if the dialogue box has a title bar
1659 */
1660
1661 BOOL dbox_hasTitle(dbox d)
1662 {
1663 return (!!(d->windDef->flags & wimp_WTITLE));
1664 }