Initial revision
[ssr] / StraySrc / Glass / !Glass / c / tearEdit
1 /*
2 * tearEdit.c
3 *
4 * Editing icons in tearoff menus
5 *
6 * © 1994-1998 Straylight
7 */
8
9 /*----- Licensing note ----------------------------------------------------*
10 *
11 * This file is part of Straylight's Glass.
12 *
13 * Glass is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * Glass is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Glass. If not, write to the Free Software Foundation,
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 /*
31 * ANSI standard headers
32 */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 /*
39 * Steel and RISC_OSLib headers
40 */
41
42 #define _STDAPP
43 #include "steel/Steel.h"
44
45 #include "steel/buttons.h"
46 #include "steel/akbd.h"
47 #include "steel/buffer.h"
48 #include "steel/colourtran.h"
49 #include "steel/tearoff.h"
50
51 /*
52 * Glass headers
53 */
54
55 #include "gStruct.h"
56
57 #include "glass.h"
58 #include "window.h"
59 #include "tfile.h"
60 #include "indir.h"
61 #include "tearEdit.h"
62
63 /*----- Static variables --------------------------------------------------*/
64
65 static glass_windPointer *tearEdit__window; /* The window with the icon */
66 static int tearEdit__icon=-1; /* The icon we're editing */
67
68 static tearoff tearEdit__main; /* The main tearoff edit menu */
69 static tearoff tearEdit__data;
70 static tearoff tearEdit__appear;
71 static tearoff tearEdit__actions;
72 static tearoff tearEdit__btype;
73 static tearoff tearEdit__colours;
74
75 /*----- Menu structure ----------------------------------------------------*
76 *
77 * Icon data => Data => [dbox]
78 * Indirected => [dbox]
79 * Text
80 * Sprite
81 * Appearance => Anti-aliased => Font => [font menu]
82 * Size => [dbox]
83 * Horizontally centred
84 * Vertically centred
85 * Right aligned
86 * Border
87 * Filled background
88 * Half-size sprite
89 * Needs help
90 * Actions => Button type => [type menu]
91 * ESG => [dbox]
92 * Adjust toggles
93 * Selected
94 * Shaded
95 * Colours => Foreground => [dbox]
96 * Background => [dbox]
97 * Position => [dbox]
98 * Size => [dbox]
99 */
100
101 /*----- Icon numbers for dialogues ----------------------------------------*/
102
103 #define tearEdit__DATAOK 0
104 #define tearEdit__DATAWRITE 1
105
106 #define tearEdit__ESGOK 0
107 #define tearEdit__ESGUP 1
108 #define tearEdit__ESGDOWN 2
109 #define tearEdit__ESGWRITE 3
110
111 #define tearEdit__INDOK 0
112 #define tearEdit__INDINDIR 2
113 #define tearEdit__INDSWRITE 4
114 #define tearEdit__INDSUP 5
115 #define tearEdit__INDSDOWN 6
116 #define tearEdit__INDMINIMISE 7
117 #define tearEdit__INDPART 8
118 #define tearEdit__INDVALID 9
119 #define tearEdit__INDVALSTRING 10
120
121 #define tearEdit__COLOUROK 0
122 #define tearEdit__COLOURCOLS 2
123
124 #define tearEdit__POSOK 0
125 #define tearEdit__POSUP 2
126 #define tearEdit__POSDOWN 3
127 #define tearEdit__POSLEFT 4
128 #define tearEdit__POSRIGHT 5
129 #define tearEdit__POSWRITE 6
130
131 /*----- Item numbers for menus --------------------------------------------*/
132
133 enum
134 {
135 tearEdit__MAINDATA=1,
136 tearEdit__MAINAPPEAR,
137 tearEdit__MAINACTIONS,
138 tearEdit__MAINCOLOURS,
139 tearEdit__MAINPOS,
140 tearEdit__MAINSIZE
141 };
142
143 enum
144 {
145 tearEdit__DATADATA=1,
146 tearEdit__DATAINDIR,
147 tearEdit__DATATEXT,
148 tearEdit__DATASPRITE
149 };
150
151 enum
152 {
153 tearEdit__APPEARHCENTRE=1,
154 tearEdit__APPEARVCENTRE,
155 tearEdit__APPEARRALIGN,
156 tearEdit__APPEARBORDER,
157 tearEdit__APPEARFILLED,
158 tearEdit__APPEARHALF,
159 tearEdit__APPEARHELP
160 };
161
162 enum
163 {
164 tearEdit__ACTIONSBTYPE=1,
165 tearEdit__ACTIONSESG,
166 tearEdit__ACTIONSADJUST,
167 tearEdit__ACTIONSSELECT,
168 tearEdit__ACTIONSSHADE
169 };
170
171 enum
172 {
173 tearEdit__COLOURSFORE=1,
174 tearEdit__COLOURSBACK
175 };
176
177 /*----- Messing about with indirected data --------------------------------*/
178
179 /*
180 * void tearEdit__setData(wimp_icon *icn,
181 * char *data,
182 * char *valid,
183 * int newsize)
184 *
185 * Use
186 * Sets an icon's data as required, possibly extending the data buffer and
187 * indirecting if required. Old buffers are freed and new ones allocated
188 * etc.
189 *
190 * Parameters
191 * wimp_icon *icn == the icon to edit in this way
192 * char *data == pointer to the new data string, or 0 to leave it alone
193 * char *valid == pointer to the new validation string, or 0 to leave it
194 * alone, or tearEdit__NOVALID to delete it
195 * int newsize == the size of the new indirection buffer, or
196 * tearEdit__NOINDIR to not indirect the string
197 */
198
199 #define tearEdit__NOVALID ((char *)(-1))
200 #define tearEdit__NOINDIR (-1)
201 #define tearEdit__NOCHANGE (-2)
202
203 static void tearEdit__setData(wimp_icon *icn,
204 char *data,
205 char *valid,
206 int newsize)
207 {
208 char nonind[13];
209 int maxlen=newsize;
210 wimp_iconflags nf=icn->flags;
211 char *p=0,*q;
212
213 /* --- Fill in default arguments --- */
214
215 if (!data)
216 {
217 if (tst(icn->flags,8))
218 {
219 data=icn->data.indirecttext.buffer;
220 utils_ctermToNterm(data);
221 }
222 else
223 {
224 memcpy(nonind,icn->data.text,12);
225 nonind[12]=0;
226 utils_ctermToNterm(nonind);
227 data=nonind;
228 }
229 }
230
231 if (!valid)
232 {
233 if (tst(icn->flags,0) && tst(icn->flags,8))
234 {
235 valid=icn->data.indirecttext.validstring;
236 if (valid!=tearEdit__NOVALID)
237 utils_ctermToNterm(valid);
238 }
239 else
240 valid=tearEdit__NOVALID;
241 }
242
243 if (maxlen==tearEdit__NOCHANGE)
244 {
245 if (tst(icn->flags,8))
246 maxlen=icn->data.indirecttext.bufflen;
247 else
248 maxlen=tearEdit__NOINDIR;
249 }
250
251 /* --- Set up new icon flags --- */
252
253 if (maxlen==tearEdit__NOINDIR)
254 {
255 maxlen=12;
256 reset(nf,8);
257 }
258 else
259 set(nf,8);
260
261 if (strlen(data)>=maxlen)
262 {
263 set(nf,8);
264 maxlen=strlen(data)+1;
265 }
266
267 /* --- Set up new buffers for data --- */
268
269 if (tst(nf,8))
270 {
271 if (p=indir_alloc(maxlen),!p)
272 {
273 werr(FALSE,msgs_lookup("teNEMUI"));
274 return;
275 }
276 if (tst(nf,0) && valid!=tearEdit__NOVALID)
277 {
278 if (q=indir_alloc(strlen(valid)+1),!q)
279 {
280 indir_free(p);
281 werr(FALSE,msgs_lookup("teNEMUI"));
282 return;
283 }
284 window_redrawIcon(tearEdit__window,tearEdit__icon);
285 strcpy(q,valid);
286 valid=q;
287 tearEdit__window->size+=strlen(valid)+1;
288 }
289 strcpy(p,data);
290 tearEdit__window->size+=maxlen;
291 }
292
293 /* --- Clear out the old buffers now --- */
294
295 if (tst(icn->flags,8))
296 {
297 tearEdit__window->size-=icn->data.indirecttext.bufflen;
298 if (tst(icn->flags,0) &&
299 icn->data.indirecttext.validstring!=tearEdit__NOVALID)
300 {
301 utils_ctermToNterm(icn->data.indirecttext.validstring);
302 tearEdit__window->size-=strlen(icn->data.indirecttext.validstring)+1;
303 }
304 }
305
306 /* --- Now copy the new data across --- */
307
308 if (tst(nf,8))
309 {
310 icn->data.indirecttext.bufflen=maxlen;
311 icn->data.indirecttext.buffer=p;
312 if ((nf & 3)==2)
313 icn->data.indirectsprite.spritearea=tearEdit__window->t->s;
314 else
315 icn->data.indirecttext.validstring=valid;
316 }
317 else
318 memcpy(icn->data.text,data,12);
319
320 icn->flags=nf;
321
322 /* --- That's it (phew!) --- */
323
324 window_redrawIcon(tearEdit__window,tearEdit__icon);
325 tfile_markAsAltered(tearEdit__window->t);
326 }
327
328 /*----- Icon data dialogue boxes ------------------------------------------*/
329
330 /* --- Alter data --- */
331
332 /*
333 * void tearEdit__dataBox(void)
334 *
335 * Use
336 * Displays a dialogue box allowing the user to change an icon's data.
337 */
338
339 static void tearEdit__dataBox(void)
340 {
341 dbox d;
342 wimp_icon *icn;
343 char nonind[256];
344 char *data;
345 BOOL done=FALSE;
346
347 if (!tearEdit__window || tearEdit__icon==-1)
348 return;
349 icn=&tearEdit__window->def->i[tearEdit__icon].i;
350 if (!(icn->flags & 3))
351 return;
352
353 if (tst(icn->flags,8))
354 data=icn->data.indirecttext.buffer;
355 else
356 {
357 memcpy(nonind,icn->data.text,12);
358 nonind[13]=0;
359 data=nonind;
360 }
361 utils_ctermToNterm(data);
362
363 d=dbox_create("teditData");
364 if (!d)
365 return;
366
367 dbox_setfield(d,tearEdit__DATAWRITE,"%s",data);
368 dbox_display(d,dbox_MENU_OVERPTR);
369
370 while (!done)
371 {
372 switch (dbox_fillin(d))
373 {
374 case dbox_CLOSE:
375 done=TRUE;
376 break;
377 case tearEdit__DATAOK:
378 dbox_clickicon(d,tearEdit__DATAOK);
379 dbox_getfield(d,tearEdit__DATAWRITE,nonind,256);
380 tearEdit__setData(icn,nonind,0,tearEdit__NOCHANGE);
381 if (dbox_wasAdjustClick())
382 dbox_unclick();
383 else
384 {
385 dbox_hide(d);
386 dbox_unclick();
387 done=TRUE;
388 }
389 break;
390 }
391 }
392
393 dbox_delete(d);
394 }
395
396 /* --- Alter indirection --- */
397
398 /*
399 * void tearEdit__setupIndBox(dbox d,wimp_icon *icn,BOOL *ind,BOOL *val)
400 *
401 * Use
402 * Sets up the icons in an indirection dialogue box.
403 *
404 * Parameters
405 * dbox d == the dialogue box's handle
406 * wimp_icon *icn == the icon to read the definition from
407 * BOOL *ind == (output) whether the icon is indirected
408 * BOOL *val == (output) whether the icon has a validation string
409 */
410
411 static void tearEdit__setupIndBox(dbox d,wimp_icon *icn,BOOL *ind,BOOL *val)
412 {
413 if (tst(icn->flags,8))
414 {
415 *ind=TRUE;
416 dbox_selecticon(d,tearEdit__INDINDIR,TRUE);
417 dbox_shadeicon(d,tearEdit__INDSUP,FALSE);
418 dbox_shadeicon(d,tearEdit__INDSDOWN,FALSE);
419 dbox_shadeicon(d,tearEdit__INDSWRITE,FALSE);
420 dbox_shadeicon(d,tearEdit__INDMINIMISE,FALSE);
421 dbox_shadeicon(d,tearEdit__INDPART,FALSE);
422 dbox_setfield(d,tearEdit__INDSWRITE,"%i",icn->data.indirecttext.bufflen);
423 if (tst(icn->flags,0))
424 {
425 if (icn->data.indirecttext.validstring!=tearEdit__NOVALID)
426 {
427 *val=TRUE;
428 dbox_selecticon(d,tearEdit__INDVALID,TRUE);
429 dbox_shadeicon(d,tearEdit__INDVALSTRING,FALSE);
430 utils_ctermToNterm(icn->data.indirecttext.validstring);
431 dbox_setfield(d,
432 tearEdit__INDVALSTRING,
433 "%s",
434 icn->data.indirecttext.validstring);
435 }
436 else
437 {
438 *val=FALSE;
439 dbox_selecticon(d,tearEdit__INDVALID,FALSE);
440 dbox_shadeicon(d,tearEdit__INDVALID,FALSE);
441 dbox_shadeicon(d,tearEdit__INDVALSTRING,TRUE);
442 dbox_setfield(d,tearEdit__INDVALSTRING,"");
443 }
444 }
445 else
446 {
447 *val=FALSE;
448 dbox_selecticon(d,tearEdit__INDVALID,FALSE);
449 dbox_shadeicon(d,tearEdit__INDVALID,TRUE);
450 dbox_shadeicon(d,tearEdit__INDVALSTRING,TRUE);
451 dbox_setfield(d,tearEdit__INDVALSTRING,"");
452 }
453 }
454 else
455 {
456 *ind=FALSE;
457 dbox_selecticon(d,tearEdit__INDINDIR,FALSE);
458 dbox_shadeicon(d,tearEdit__INDSUP,TRUE);
459 dbox_shadeicon(d,tearEdit__INDSDOWN,TRUE);
460 dbox_shadeicon(d,tearEdit__INDSWRITE,TRUE);
461 dbox_shadeicon(d,tearEdit__INDMINIMISE,TRUE);
462 dbox_shadeicon(d,tearEdit__INDPART,TRUE);
463 dbox_setfield(d,tearEdit__INDSWRITE,"12");
464 *val=FALSE;
465 dbox_selecticon(d,tearEdit__INDVALID,FALSE);
466 dbox_shadeicon(d,tearEdit__INDVALID,TRUE);
467 dbox_shadeicon(d,tearEdit__INDVALSTRING,TRUE);
468 dbox_setfield(d,tearEdit__INDVALSTRING,"");
469 }
470 }
471
472 /*
473 * void tearEdit__indirBox(void)
474 *
475 * Use
476 * Displays and handles an indirection dialogue box.
477 */
478
479 static void tearEdit__indirBox(void)
480 {
481 dbox d;
482 char buff[256];
483 wimp_icon *icn;
484 int size;
485 BOOL done=FALSE;
486 BOOL ind;
487 BOOL val;
488 buttons_simpleArrow sa={0,9999,FALSE};
489 dbox_field f;
490
491 if (!tearEdit__window || tearEdit__icon==-1)
492 return;
493
494 icn=&tearEdit__window->def->i[tearEdit__icon].i;
495 if (!(icn->flags & 3))
496 return;
497
498 d=dbox_create("teditIndir");
499 if (!d)
500 return;
501
502 tearEdit__setupIndBox(d,icn,&ind,&val);
503
504 dbox_display(d,dbox_MENU_OVERPTR);
505 while (!done)
506 {
507 switch (f=dbox_fillin(d),f)
508 {
509 case dbox_CLOSE:
510 done=TRUE;
511 break;
512 case tearEdit__INDINDIR:
513 ind=!ind;
514 dbox_shadeicon(d,tearEdit__INDSUP,!ind);
515 dbox_shadeicon(d,tearEdit__INDSDOWN,!ind);
516 dbox_shadeicon(d,tearEdit__INDSWRITE,!ind);
517 dbox_shadeicon(d,tearEdit__INDMINIMISE,!ind);
518 dbox_shadeicon(d,tearEdit__INDPART,!ind);
519 if (tst(icn->flags,0))
520 {
521 dbox_shadeicon(d,tearEdit__INDVALID,!ind);
522 dbox_shadeicon(d,tearEdit__INDVALSTRING,!(ind && val));
523 }
524 break;
525 case tearEdit__INDSUP:
526 buttons_arrow(d,f,d,tearEdit__INDSWRITE,0,+1,&sa);
527 break;
528 case tearEdit__INDSDOWN:
529 buttons_arrow(d,f,d,tearEdit__INDSWRITE,0,-1,&sa);
530 break;
531 case tearEdit__INDMINIMISE:
532 dbox_clickicon(d,f);
533 if (icn->flags & wimp_INDIRECT)
534 {
535 dbox_setfield(d,tearEdit__INDSWRITE,"%i",
536 strlen(icn->data.indirecttext.buffer)+1);
537 }
538 else
539 {
540 char buff[15];
541 memcpy(buff,icn->data.text,12);
542 buff[12]=0;
543 utils_ctermToNterm(buff);
544 dbox_setfield(d,tearEdit__INDSWRITE,"%i",strlen(buff)+1);
545 }
546 dbox_unclick();
547 break;
548 case tearEdit__INDVALID:
549 val=!val;
550 dbox_shadeicon(d,tearEdit__INDVALSTRING,!val);
551 break;
552 case tearEdit__INDOK:
553 dbox_clickicon(d,tearEdit__INDOK);
554 if (ind)
555 {
556 dbox_scanfield(d,tearEdit__INDSWRITE,"%d",&size);
557 if (val)
558 {
559 dbox_getfield(d,tearEdit__INDVALSTRING,buff,256);
560 tearEdit__setData(icn,0,buff,size);
561 }
562 else
563 tearEdit__setData(icn,0,tearEdit__NOVALID,size);
564 }
565 else
566 tearEdit__setData(icn,0,tearEdit__NOVALID,tearEdit__NOINDIR);
567 if (dbox_wasAdjustClick())
568 {
569 tearEdit__setupIndBox(d,icn,&ind,&val);
570 dbox_unclick();
571 }
572 else
573 {
574 dbox_hide(d);
575 dbox_unclick();
576 done=TRUE;
577 }
578 break;
579 }
580 }
581
582 dbox_delete(d);
583 }
584
585 /*----- ESG dialogue box --------------------------------------------------*/
586
587 /*
588 * BOOL tearEdit__esgRaw(dbox d,wimp_eventstr *e,void *handle)
589 *
590 * Use
591 * Handles raw events for the ESG dialogue box (basically, it forces the
592 * ESG number to be in the correct range when you type it in.
593 *
594 * Parameters
595 * dbox d == the dialogue box handle for the ESG dbox
596 * wimp_eventstr *e == the event wot happened
597 * void *handle == a handle wot we ignore
598 */
599
600 static BOOL tearEdit__esgRaw(dbox d,wimp_eventstr *e,void *handle)
601 {
602 BOOL handled=FALSE;
603 BOOL cursor=FALSE;
604 unused(handle);
605
606 switch (e->e)
607 {
608 case wimp_EKEY:
609 switch (e->data.key.c.i)
610 {
611 case tearEdit__ESGWRITE:
612 switch (e->data.key.chcode)
613 {
614 case akbd_DownK:
615 case akbd_UpK:
616 case akbd_TabK:
617 case akbd_TabK+akbd_Sh:
618 case akbd_UpK+akbd_Ctl:
619 case akbd_DownK+akbd_Ctl:
620 cursor=TRUE;
621 break;
622 }
623 handled=buttons_insertChar(d,e->data.key.chcode,'0','9');
624 if (handled || cursor)
625 buttons_arrowClick(d,tearEdit__ESGWRITE,0,31,0,FALSE);
626 break;
627 }
628 break;
629 }
630 return (handled);
631 }
632
633 /*
634 * void tearEdit__esgBox(void)
635 *
636 * Use
637 * Allows the user to choose an exclusive selection group for an icon.
638 */
639
640 static void tearEdit__esgBox(void)
641 {
642 dbox d;
643 BOOL done=FALSE;
644 wimp_icon *icn;
645 int esg;
646 buttons_simpleArrow sa={0,31,FALSE};
647 dbox_field f;
648
649 if (!tearEdit__window || tearEdit__icon==-1)
650 return;
651
652 d=dbox_create("teditESG");
653 if (!d)
654 return;
655
656 icn=&tearEdit__window->def->i[tearEdit__icon].i;
657
658 dbox_setfield(d,tearEdit__ESGWRITE,"%i",(icn->flags & 0x001F0000)>>16);
659 dbox_rawEventHandler(d,tearEdit__esgRaw,0);
660
661 dbox_display(d,dbox_MENU_OVERPTR);
662 while (!done)
663 {
664 switch (f=dbox_fillin(d),f)
665 {
666 case dbox_CLOSE:
667 done=TRUE;
668 break;
669 case tearEdit__ESGUP:
670 buttons_arrow(d,f,d,tearEdit__ESGWRITE,0,+1,&sa);
671 break;
672 case tearEdit__ESGDOWN:
673 buttons_arrow(d,f,d,tearEdit__ESGWRITE,0,-1,&sa);
674 break;
675 case tearEdit__ESGOK:
676 dbox_clickicon(d,tearEdit__ESGOK);
677 dbox_scanfield(d,tearEdit__ESGWRITE,"%d",&esg);
678 icn->flags &= ~0x001F0000;
679 icn->flags |= esg<<16;
680 window_redrawIcon(tearEdit__window,tearEdit__icon);
681 tfile_markAsAltered(tearEdit__window->t);
682 if (dbox_wasAdjustClick())
683 dbox_unclick();
684 else
685 {
686 dbox_hide(d);
687 dbox_unclick();
688 done=TRUE;
689 }
690 break;
691 }
692 }
693
694 dbox_delete(d);
695 }
696
697 /*----- Colour dialogue boxes ---------------------------------------------*/
698
699 /*
700 * void tearEdit__addBorder(dbox d,int colour)
701 *
702 * Use
703 * Adds a border around the specified colour.
704 *
705 * Parameters
706 * dbox d == the colour dialogue box's handle
707 * int colour == the number of the colour to select
708 */
709
710 static void tearEdit__addBorder(dbox d,int colour)
711 {
712 static wimp_paletteword blacknwhite[]={0,0,0,0, 0,255,255,255,};
713 static wimp_palettestr wimppal;
714 int col;
715
716 wimpt_noerr(wimp_readpalette(&wimppal));
717 wimpt_noerr(colourtran_return_Oppcolourformode(wimppal.c[colour],
718 0,
719 blacknwhite,
720 &col));
721 wimpt_noerr(colourtran_return_colourformode(blacknwhite[col],
722 12,
723 wimppal.c,
724 &col));
725
726 /* --- We now have the correctly contrasting colour in col --- */
727
728 wimpt_noerr(wimp_set_icon_state(dbox_syshandle(d),
729 colour+tearEdit__COLOURCOLS,
730 5 | (col<<24),
731 0x0F000005));
732 }
733
734 #define tearEdit__removeBorder(d,colour) \
735 wimpt_noerr(wimp_set_icon_state(dbox_syshandle(d), \
736 colour+tearEdit__COLOURCOLS, \
737 0x00000000, \
738 0x0F000005)); \
739
740 /*
741 * void tearEdit__colourBox(BOOL fore)
742 *
743 * Use
744 * Displays a dialogue box from which the user may choose an icon colour.
745 *
746 * Parameters
747 * BOOL fore == whether this is the foreground or background we're editing
748 */
749
750 static void tearEdit__colourBox(BOOL fore)
751 {
752 dbox d;
753 wimp_icon *icn;
754 BOOL done=FALSE;
755 int colour;
756 dbox_field f;
757
758 if (!tearEdit__window || tearEdit__icon==-1)
759 return;
760
761 icn=&tearEdit__window->def->i[tearEdit__icon].i;
762
763 if (tst(icn->flags,6))
764 return;
765
766 d=dbox_create("teditColour");
767 if (!d)
768 return;
769
770 if (fore)
771 colour=(icn->flags & 0x0F000000)>>24;
772 else
773 colour=(icn->flags & 0xF0000000)>>28;
774
775 win_settitle(dbox_syshandle(d),msgs_lookup(fore ? "teFG" : "teBG"));
776
777 tearEdit__addBorder(d,colour);
778
779 dbox_display(d,dbox_MENU_OVERPTR);
780 while (!done)
781 {
782 switch (f=dbox_fillin(d),f)
783 {
784 case dbox_CLOSE:
785 done=TRUE;
786 break;
787 case tearEdit__COLOUROK:
788 dbox_clickicon(d,tearEdit__COLOUROK);
789 if (fore)
790 {
791 icn->flags &= ~0x0F000000;
792 icn->flags |= colour<<24;
793 }
794 else
795 {
796 icn->flags &= ~0xF0000000;
797 icn->flags |= colour<<28;
798 }
799 window_redrawIcon(tearEdit__window,tearEdit__icon);
800 tfile_markAsAltered(tearEdit__window->t);
801 if (dbox_wasAdjustClick())
802 dbox_unclick();
803 else
804 {
805 dbox_hide(d);
806 dbox_unclick();
807 done=TRUE;
808 }
809 break;
810 default:
811 if (f>=tearEdit__COLOURCOLS &&
812 f<tearEdit__COLOURCOLS+16 &&
813 f!=colour+tearEdit__COLOURCOLS)
814 {
815 tearEdit__removeBorder(d,colour);
816 colour=f-tearEdit__COLOURCOLS;
817 tearEdit__addBorder(d,colour);
818 }
819 break;
820 }
821 }
822
823 dbox_delete(d);
824 }
825
826 /*----- Size and position dialogue boxes ----------------------------------*/
827
828 /*
829 * void tearEdit__coordsArrows(dbox d,dbox_field f,int diff,void *handle)
830 *
831 * Use
832 * Handles a click event on one of the position or size arrow buttons in
833 * the dialogue box. See the structure definition below for a description
834 * of the data structure required.
835 */
836
837 typedef struct
838 {
839 BOOL xOrY;
840 BOOL sizing;
841 }
842 tearEdit__coordsArrowstr;
843
844 static void tearEdit__coordsArrows(dbox d,
845 dbox_field f,
846 int diff,
847 void *handle)
848 {
849 tearEdit__coordsArrowstr *s=handle;
850 int x,y;
851 int *v;
852
853 dbox_scanfield(d,f,"%d,%d",&x,&y);
854 v=s->xOrY ? &x : &y;
855 *v+=diff;
856 if (s->sizing && *v<0)
857 *v=0;
858 dbox_setfield(d,f,"%i,%i",x,y);
859 }
860
861 /*
862 * void tearEdit__coordsBox(BOOL size)
863 *
864 * Use
865 * Displays a dialogue box and allows the user to alter either the size or
866 * position of an icon.
867 *
868 * Parameters
869 * BOOL size == whether to alter the size or position
870 */
871
872 static void tearEdit__coordsBox(BOOL size)
873 {
874 dbox d;
875 BOOL done=FALSE;
876 dbox_field f;
877 wimp_icon *icn;
878 int x,y;
879 tearEdit__coordsArrowstr ca;
880
881 if (!tearEdit__window || tearEdit__icon==-1)
882 return;
883
884 d=dbox_create(size ? "teditSize" : "teditPos");
885 if (!d)
886 return;
887
888 icn=&tearEdit__window->def->i[tearEdit__icon].i;
889 if (size)
890 {
891 x=icn->box.x1-icn->box.x0;
892 y=icn->box.y1-icn->box.y0;
893 }
894 else
895 {
896 x=icn->box.x0;
897 y=icn->box.y0;
898 }
899 ca.sizing=size;
900
901 dbox_setfield(d,tearEdit__POSWRITE,"%i,%i",x,y);
902 dbox_display(d,dbox_MENU_OVERPTR);
903
904 while (!done)
905 {
906 f=dbox_fillin(d);
907 switch (f)
908 {
909 case dbox_CLOSE:
910 done=TRUE;
911 break;
912 case tearEdit__POSUP:
913 ca.xOrY=FALSE;
914 buttons_arrow(d,f,d,tearEdit__POSWRITE,
915 tearEdit__coordsArrows,+wimpt_dy(),&ca);
916 break;
917 case tearEdit__POSDOWN:
918 ca.xOrY=FALSE;
919 buttons_arrow(d,f,d,tearEdit__POSWRITE,
920 tearEdit__coordsArrows,-wimpt_dy(),&ca);
921 break;
922 case tearEdit__POSLEFT:
923 ca.xOrY=TRUE;
924 buttons_arrow(d,f,d,tearEdit__POSWRITE,
925 tearEdit__coordsArrows,-wimpt_dx(),&ca);
926 break;
927 case tearEdit__POSRIGHT:
928 ca.xOrY=TRUE;
929 buttons_arrow(d,f,d,tearEdit__POSWRITE,
930 tearEdit__coordsArrows,+wimpt_dx(),&ca);
931 break;
932 case tearEdit__POSOK:
933 dbox_clickicon(d,f);
934 dbox_scanfield(d,tearEdit__POSWRITE,"%d,%d",&x,&y);
935 window_redrawIcon(tearEdit__window,tearEdit__icon);
936 if (size)
937 {
938 icn->box.x1=icn->box.x0+x;
939 icn->box.y1=icn->box.y0+y;
940 }
941 else
942 {
943 icn->box.x1+=x-icn->box.x0;
944 icn->box.y1+=y-icn->box.y0;
945 icn->box.x0=x;
946 icn->box.y0=y;
947 }
948 window_redrawIcon(tearEdit__window,tearEdit__icon);
949 tfile_markAsAltered(tearEdit__window->t);
950 if (dbox_wasAdjustClick())
951 dbox_unclick();
952 else
953 {
954 dbox_hide(d);
955 dbox_unclick();
956 done=TRUE;
957 }
958 break;
959 }
960 }
961 dbox_delete(d);
962 }
963
964 /*----- Menu handling -----------------------------------------------------*/
965
966 /*
967 * void tearEdit__mainHits(tearoff_message m,int hit,void *handle)
968 * etc.
969 *
970 * Use
971 * Handles menu events for the main edit icon menu level
972 *
973 * Parameters
974 * tearoff_message m == the type of event that happened
975 * int hit == the item it happened to
976 * void *handle == a waste of a good argument register
977 */
978
979 static void tearEdit__mainHits(tearoff_message m,int hit,void *handle)
980 {
981 unused(handle);
982 switch (m)
983 {
984 case tearoff_SELECTION:
985 case tearoff_SUBMENU:
986 switch (hit)
987 {
988 case tearEdit__MAINPOS:
989 tearEdit__coordsBox(FALSE);
990 break;
991 case tearEdit__MAINSIZE:
992 tearEdit__coordsBox(TRUE);
993 break;
994 }
995 break;
996 }
997 }
998
999 static void tearEdit__dataHits(tearoff_message m,int hit,void *handle)
1000 {
1001 unused(handle);
1002 switch (m)
1003 {
1004 case tearoff_SELECTION:
1005 case tearoff_SUBMENU:
1006 switch (hit)
1007 {
1008 case tearEdit__DATADATA:
1009 tearEdit__dataBox();
1010 break;
1011 case tearEdit__DATAINDIR:
1012 tearEdit__indirBox();
1013 break;
1014 case tearEdit__DATATEXT:
1015 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_ITEXT;
1016 tearEdit__setData(&tearEdit__window->def->i[tearEdit__icon].i,
1017 0,
1018 tearEdit__NOVALID,
1019 tearEdit__NOCHANGE);
1020 break;
1021 case tearEdit__DATASPRITE:
1022 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_ISPRITE;
1023 tearEdit__setData(&tearEdit__window->def->i[tearEdit__icon].i,
1024 0,
1025 0,
1026 tearEdit__NOCHANGE);
1027 break;
1028 }
1029 break;
1030 }
1031 }
1032
1033 static void tearEdit__appearHits(tearoff_message m,int hit,void *handle)
1034 {
1035 unused(handle);
1036 switch (m)
1037 {
1038 case tearoff_SELECTION:
1039 case tearoff_SUBMENU:
1040 switch (hit)
1041 {
1042 case tearEdit__APPEARHCENTRE:
1043 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_IHCENTRE;
1044 window_redrawIcon(tearEdit__window,tearEdit__icon);
1045 tfile_markAsAltered(tearEdit__window->t);
1046 break;
1047 case tearEdit__APPEARVCENTRE:
1048 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_IVCENTRE;
1049 window_redrawIcon(tearEdit__window,tearEdit__icon);
1050 tfile_markAsAltered(tearEdit__window->t);
1051 break;
1052 case tearEdit__APPEARRALIGN:
1053 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_IRJUST;
1054 window_redrawIcon(tearEdit__window,tearEdit__icon);
1055 tfile_markAsAltered(tearEdit__window->t);
1056 break;
1057 case tearEdit__APPEARBORDER:
1058 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_IBORDER;
1059 window_redrawIcon(tearEdit__window,tearEdit__icon);
1060 tfile_markAsAltered(tearEdit__window->t);
1061 break;
1062 case tearEdit__APPEARFILLED:
1063 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_IFILLED;
1064 window_redrawIcon(tearEdit__window,tearEdit__icon);
1065 tfile_markAsAltered(tearEdit__window->t);
1066 break;
1067 case tearEdit__APPEARHALF:
1068 tearEdit__window->def->i[tearEdit__icon].i.flags ^=
1069 wimp_IHALVESPRITE;
1070 window_redrawIcon(tearEdit__window,tearEdit__icon);
1071 tfile_markAsAltered(tearEdit__window->t);
1072 break;
1073 case tearEdit__APPEARHELP:
1074 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_IREDRAW;
1075 window_redrawIcon(tearEdit__window,tearEdit__icon);
1076 tfile_markAsAltered(tearEdit__window->t);
1077 break;
1078 }
1079 break;
1080 }
1081 }
1082
1083 static void tearEdit__actionsHits(tearoff_message m,int hit,void *handle)
1084 {
1085 unused(handle);
1086 switch (m)
1087 {
1088 case tearoff_SELECTION:
1089 case tearoff_SUBMENU:
1090 switch (hit)
1091 {
1092 case tearEdit__ACTIONSESG:
1093 tearEdit__esgBox();
1094 break;
1095 case tearEdit__ACTIONSADJUST:
1096 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_IESG_NOC;
1097 window_redrawIcon(tearEdit__window,tearEdit__icon);
1098 tfile_markAsAltered(tearEdit__window->t);
1099 break;
1100 case tearEdit__ACTIONSSELECT:
1101 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_ISELECTED;
1102 window_redrawIcon(tearEdit__window,tearEdit__icon);
1103 tfile_markAsAltered(tearEdit__window->t);
1104 break;
1105 case tearEdit__ACTIONSSHADE:
1106 tearEdit__window->def->i[tearEdit__icon].i.flags ^= wimp_INOSELECT;
1107 window_redrawIcon(tearEdit__window,tearEdit__icon);
1108 tfile_markAsAltered(tearEdit__window->t);
1109 break;
1110 }
1111 break;
1112 }
1113 }
1114
1115 static void tearEdit__btypeHits(tearoff_message m,int hit,void *handle)
1116 {
1117 unused(handle);
1118 if (m==tearoff_SELECTION && hit>=1 && hit<=16)
1119 {
1120 tearEdit__window->def->i[tearEdit__icon].i.flags &= ~0x0000F000;
1121 tearEdit__window->def->i[tearEdit__icon].i.flags |= (hit-1)<<12;
1122 window_redrawIcon(tearEdit__window,tearEdit__icon);
1123 tfile_markAsAltered(tearEdit__window->t);
1124 }
1125 }
1126
1127 static void tearEdit__coloursHits(tearoff_message m,int hit,void *handle)
1128 {
1129 unused(handle);
1130 switch (m)
1131 {
1132 case tearoff_SELECTION:
1133 case tearoff_SUBMENU:
1134 switch (hit)
1135 {
1136 case tearEdit__COLOURSFORE:
1137 tearEdit__colourBox(TRUE);
1138 break;
1139 case tearEdit__COLOURSBACK:
1140 tearEdit__colourBox(FALSE);
1141 break;
1142 }
1143 break;
1144 }
1145 }
1146
1147 /*----- External functions ------------------------------------------------*/
1148
1149 /*
1150 * void tearEdit_open(void)
1151 *
1152 * Use
1153 * Opens the edit icon menu, as a submenu if appropriate, otherwise as a
1154 * full menu.
1155 */
1156
1157 void tearEdit_open(void)
1158 {
1159 tearoff_displayMenu(tearEdit__main,0);
1160 }
1161
1162 /*
1163 * void tearEdit_update(glass_windPointer *w,int icon)
1164 *
1165 * Use
1166 * Updates the edit icon menu from the specified window and icon. If the
1167 * window handle is 0, or the icon is -1 then the menu is made unavailable
1168 * (i.e. its items are shaded). Otherwise, the menu is updated to reflect
1169 * the state of the icon.
1170 *
1171 * Parameters
1172 * glass_windPointer *w == the window containing the icon to edit
1173 * int icon == the icon to be editing in the menu
1174 */
1175
1176 void tearEdit_update(glass_windPointer *w,int icon)
1177 {
1178 int i;
1179 wimp_iconflags f;
1180 int b;
1181
1182 /* --- Remember the new magic icon --- */
1183
1184 tearEdit__window=w;
1185 tearEdit__icon=icon;
1186
1187 /* --- If there isn't an icon any more, shade the menu --- */
1188
1189 if (!w || icon==-1)
1190 {
1191 for (i=tearEdit__MAINDATA;i<=tearEdit__MAINSIZE;i++)
1192 {
1193 tearoff_shadeItem(tearEdit__main,i,TRUE);
1194 tearoff_selectItem(tearEdit__main,i,FALSE);
1195 }
1196 for (i=tearEdit__DATADATA;i<=tearEdit__DATASPRITE;i++)
1197 {
1198 tearoff_shadeItem(tearEdit__data,i,TRUE);
1199 tearoff_selectItem(tearEdit__data,i,FALSE);
1200 }
1201 for (i=tearEdit__APPEARHCENTRE;i<=tearEdit__APPEARHELP;i++)
1202 {
1203 tearoff_shadeItem(tearEdit__appear,i,TRUE);
1204 tearoff_selectItem(tearEdit__appear,i,FALSE);
1205 }
1206 for (i=tearEdit__ACTIONSBTYPE;i<=tearEdit__ACTIONSSHADE;i++)
1207 {
1208 tearoff_shadeItem(tearEdit__actions,i,TRUE);
1209 tearoff_selectItem(tearEdit__actions,i,FALSE);
1210 }
1211 for (i=1;i<=16;i++)
1212 {
1213 tearoff_shadeItem(tearEdit__btype,i,TRUE);
1214 tearoff_selectItem(tearEdit__btype,i,FALSE);
1215 }
1216 for (i=tearEdit__COLOURSFORE;i<=tearEdit__COLOURSBACK;i++)
1217 tearoff_shadeItem(tearEdit__colours,i,TRUE);
1218 }
1219 else
1220 {
1221 /* --- Read information about the icon --- */
1222
1223 f=w->def->i[icon].i.flags;
1224
1225 /* --- Unshade the main menu --- */
1226
1227 tearoff_shadeItem(tearEdit__main,tearEdit__MAINDATA,FALSE);
1228 tearoff_shadeItem(tearEdit__main,tearEdit__MAINAPPEAR,FALSE);
1229 tearoff_shadeItem(tearEdit__main,tearEdit__MAINACTIONS,FALSE);
1230 tearoff_shadeItem(tearEdit__main,tearEdit__MAINCOLOURS,tst(f,6));
1231 tearoff_shadeItem(tearEdit__main,tearEdit__MAINPOS,FALSE);
1232 tearoff_shadeItem(tearEdit__main,tearEdit__MAINSIZE,FALSE);
1233
1234 /* --- Handle data things --- */
1235
1236 tearoff_shadeItem(tearEdit__data,tearEdit__DATADATA,!(f & 3));
1237 tearoff_shadeItem(tearEdit__data,tearEdit__DATAINDIR,!(f & 3));
1238 tearoff_selectItem(tearEdit__data,tearEdit__DATAINDIR,tst(f,8));
1239 tearoff_shadeItem(tearEdit__data,tearEdit__DATATEXT,FALSE);
1240 tearoff_selectItem(tearEdit__data,tearEdit__DATATEXT,tst(f,0));
1241 tearoff_shadeItem(tearEdit__data,tearEdit__DATASPRITE,FALSE);
1242 tearoff_selectItem(tearEdit__data,tearEdit__DATASPRITE,tst(f,1));
1243
1244 /* --- Handle appearance things --- */
1245
1246 tearoff_shadeItem(tearEdit__appear,tearEdit__APPEARHCENTRE,FALSE);
1247 tearoff_selectItem(tearEdit__appear,tearEdit__APPEARHCENTRE,tst(f,3));
1248 tearoff_shadeItem(tearEdit__appear,tearEdit__APPEARVCENTRE,FALSE);
1249 tearoff_selectItem(tearEdit__appear,tearEdit__APPEARVCENTRE,tst(f,4));
1250 tearoff_shadeItem(tearEdit__appear,tearEdit__APPEARRALIGN,FALSE);
1251 tearoff_selectItem(tearEdit__appear,tearEdit__APPEARRALIGN,tst(f,9));
1252
1253 tearoff_shadeItem(tearEdit__appear,tearEdit__APPEARBORDER,FALSE);
1254 tearoff_selectItem(tearEdit__appear,tearEdit__APPEARBORDER,tst(f,2));
1255 tearoff_shadeItem(tearEdit__appear,tearEdit__APPEARFILLED,FALSE);
1256 tearoff_selectItem(tearEdit__appear,tearEdit__APPEARFILLED,tst(f,5));
1257 tearoff_shadeItem(tearEdit__appear,tearEdit__APPEARHALF,!tst(f,1));
1258 tearoff_selectItem(tearEdit__appear,tearEdit__APPEARHALF,tst(f,11));
1259 tearoff_shadeItem(tearEdit__appear,tearEdit__APPEARHELP,FALSE);
1260 tearoff_selectItem(tearEdit__appear,tearEdit__APPEARHELP,tst(f,7));
1261
1262 /* --- Handle actions things --- */
1263
1264 tearoff_shadeItem(tearEdit__actions,tearEdit__ACTIONSBTYPE,FALSE);
1265 tearoff_shadeItem(tearEdit__actions,tearEdit__ACTIONSESG,FALSE);
1266 tearoff_shadeItem(tearEdit__actions,tearEdit__ACTIONSADJUST,FALSE);
1267 tearoff_selectItem(tearEdit__actions,tearEdit__ACTIONSADJUST,tst(f,10));
1268 tearoff_shadeItem(tearEdit__actions,tearEdit__ACTIONSSELECT,FALSE);
1269 tearoff_selectItem(tearEdit__actions,tearEdit__ACTIONSSELECT,tst(f,21));
1270 tearoff_shadeItem(tearEdit__actions,tearEdit__ACTIONSSHADE,FALSE);
1271 tearoff_selectItem(tearEdit__actions,tearEdit__ACTIONSSHADE,tst(f,22));
1272
1273 /* --- Handle button type --- */
1274
1275 b=(f & 0x0000F000)>>12;
1276 for (i=1;i<=16;i++)
1277 {
1278 tearoff_shadeItem(tearEdit__btype,i,FALSE);
1279 tearoff_selectItem(tearEdit__btype,i,(i-1==b) ?
1280 tearoff_RADIOED :
1281 FALSE);
1282 }
1283
1284 /* --- Handle colours --- */
1285
1286 tearoff_shadeItem(tearEdit__colours,tearEdit__COLOURSFORE,tst(f,6));
1287 tearoff_shadeItem(tearEdit__colours,tearEdit__COLOURSBACK,tst(f,6));
1288 }
1289 }
1290
1291 /*
1292 * void tearEdit_init(void)
1293 *
1294 * Use
1295 * Initialises the tearoff menus for editing icons and starts up the tearoff
1296 * menu manager.
1297 */
1298
1299 void tearEdit_init(void)
1300 {
1301 char *buf=buffer_find();
1302 int i;
1303
1304 /* --- If we're already up and running, then someone's stupid --- */
1305
1306 if (tearEdit__main)
1307 return;
1308
1309 tearoff_init();
1310
1311 tearEdit__main=tearoff_create(msgs_lookup("teEIMT"),
1312 msgs_lookup("teEIM"),
1313 TRUE,
1314 tearEdit__mainHits,
1315 0,
1316 0);
1317
1318 tearEdit__data=tearoff_create(msgs_lookup("teEIDT"),
1319 msgs_lookup("teEID"),
1320 TRUE,
1321 tearEdit__dataHits,
1322 0,
1323 0);
1324
1325 tearEdit__appear=tearoff_create(msgs_lookup("teAPMT"),
1326 msgs_lookup("teAPM"),
1327 TRUE,
1328 tearEdit__appearHits,
1329 0,
1330 0);
1331
1332 tearEdit__actions=tearoff_create(msgs_lookup("teACMT"),
1333 msgs_lookup("teACM"),
1334 TRUE,
1335 tearEdit__actionsHits,
1336 0,
1337 0);
1338
1339 tearEdit__colours=tearoff_create(msgs_lookup("teCMT"),
1340 msgs_lookup("teCM"),
1341 TRUE,
1342 tearEdit__coloursHits,
1343 0,
1344 0);
1345
1346 /* --- Change this code to use Edit Icon messages --- */
1347
1348 tearEdit__btype=tearoff_create(msgs_lookup("eiBTMT"),
1349 msgs_lookup("eiBTYPE0"),
1350 TRUE,
1351 tearEdit__btypeHits,
1352 0,
1353 0);
1354 for (i=1;i<=15;i++)
1355 {
1356 sprintf(buf,"eiBTYPE%i",i);
1357 tearEdit__btype=tearoff_extendMenu(tearEdit__btype,msgs_lookup(buf));
1358 }
1359 tearoff_shadeItem(tearEdit__btype,13,TRUE);
1360 tearoff_shadeItem(tearEdit__btype,14,TRUE);
1361
1362 if (!tearEdit__main ||
1363 !tearEdit__data ||
1364 !tearEdit__appear ||
1365 !tearEdit__actions ||
1366 !tearEdit__colours ||
1367 !tearEdit__btype)
1368 exit(1);
1369
1370 tearoff_attachSubMenu(tearEdit__main,
1371 tearEdit__MAINDATA,
1372 tearEdit__data);
1373 tearoff_attachSubMenu(tearEdit__main,
1374 tearEdit__MAINAPPEAR,
1375 tearEdit__appear);
1376 tearoff_attachSubMenu(tearEdit__main,
1377 tearEdit__MAINACTIONS,
1378 tearEdit__actions);
1379 tearoff_attachSubMenu(tearEdit__main,
1380 tearEdit__MAINCOLOURS,
1381 tearEdit__colours);
1382 tearoff_attachSubMenu(tearEdit__actions,
1383 tearEdit__ACTIONSBTYPE,
1384 tearEdit__btype);
1385
1386 tearEdit_update(0,-1);
1387 }