chiark / gitweb /
Initial revision
[ssr] / StraySrc / Glass / !Glass / c / editIcon
1 /*
2  * editIcon.c
3  *
4  * Edit icon dialogue box
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 headers
40  */
41
42 #define _STDAPP
43 #define _LOWLVL
44 #include "steel/Steel.h"
45
46 #include "steel/buttons.h"
47 #include "steel/fontMenu.h"
48 #include "steel/akbd.h"
49 #include "steel/bbc.h"
50 #include "steel/buffer.h"
51 #include "steel/font.h"
52
53 /*
54  * Glass headers
55  */
56
57 #include "gStruct.h"
58 #include "gMenus.h"
59 #include "gIcons.h"
60
61 #include "glass.h"
62 #include "tfile.h"
63 #include "window.h"
64 #include "intMsgs.h"
65 #include "editIcon.h"
66 #include "colSelect.h"
67 #include "indir.h"
68 #include "gPrefs.h"
69
70 /*----- Static variables --------------------------------------------------*/
71
72 static char *editIcon__panels[]=
73 {
74   "iconData",
75   "iconAppear",
76   "iconActions",
77   "iconColours",
78   "iconPos",
79   "iconSize",
80 };
81
82 /*----- Support routines --------------------------------------------------*/
83
84 #define max2(a,b) ((a)>(b) ? (a) : (b))
85 #define min2(a,b) ((a)<(b) ? (a) : (b))
86
87 /*
88  * void editIcon__setupPanel(glass_editIcon *ed)
89  *
90  * Use
91  *  Sets up a panel from the icon description given.
92  *
93  * Parameters
94  *  glass_editIcon *ed == the edit to handle.
95  */
96
97 static void editIcon__setupPanel(glass_editIcon *ed)
98 {
99   char *p;
100
101   switch (ed->e.panel)
102   {
103     case glass_EIDATA:
104       dbox_setfield(ed->e.pd,glass_EIDVALSTRING,"%s",ed->valid);
105       dbox_setfield(ed->e.pd,glass_EIDDATA,"%s",ed->data);
106       if (!(ed->idef.flags&3))
107       {
108         dbox_shadeicon(ed->e.pd,glass_EIDINDIR,TRUE);
109         dbox_shadeicon(ed->e.pd,glass_EIDDATA,TRUE);
110         dbox_selecticon(ed->e.pd,glass_EIDINDIR,FALSE);
111         dbox_selecticon(ed->e.pd,glass_EIDVALID,FALSE);
112         dbox_shadeicon(ed->e.pd,glass_EIDVALSTRING,TRUE);
113         dbox_shadeicon(ed->e.pd,glass_EIDVALID,TRUE);
114         dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,TRUE);
115         dbox_shadeicon(ed->e.pd,glass_EIDINDUP,TRUE);
116         dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,TRUE);
117         dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,TRUE);
118         dbox_shadeicon(ed->e.pd,glass_EIDINDPART,TRUE);
119         dbox_setfield(ed->e.pd,glass_EIDINDSIZE,"%i",12);
120       }
121       else if (ed->idef.flags & wimp_INDIRECT)
122       {
123         dbox_shadeicon(ed->e.pd,glass_EIDINDIR,FALSE);
124         dbox_shadeicon(ed->e.pd,glass_EIDDATA,FALSE);
125         dbox_selecticon(ed->e.pd,glass_EIDINDIR,TRUE);
126         dbox_selecticon(ed->e.pd,glass_EIDVALID,ed->hasValid);
127         dbox_shadeicon(ed->e.pd,glass_EIDVALSTRING,!ed->hasValid);
128         dbox_shadeicon(ed->e.pd,glass_EIDVALID,
129                                                !(ed->idef.flags&wimp_ITEXT));
130         dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,FALSE);
131         dbox_shadeicon(ed->e.pd,glass_EIDINDUP,FALSE);
132         dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,FALSE);
133         dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,FALSE);
134         dbox_shadeicon(ed->e.pd,glass_EIDINDPART,FALSE);
135         dbox_setfield(ed->e.pd,glass_EIDINDSIZE,"%i",ed->indLen);
136       }
137       else
138       {
139         dbox_shadeicon(ed->e.pd,glass_EIDINDIR,FALSE);
140         dbox_shadeicon(ed->e.pd,glass_EIDDATA,FALSE);
141         dbox_selecticon(ed->e.pd,glass_EIDINDIR,FALSE);
142         dbox_selecticon(ed->e.pd,glass_EIDVALID,FALSE);
143         dbox_shadeicon(ed->e.pd,glass_EIDVALSTRING,TRUE);
144         dbox_shadeicon(ed->e.pd,glass_EIDVALID,TRUE);
145         dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,TRUE);
146         dbox_shadeicon(ed->e.pd,glass_EIDINDUP,TRUE);
147         dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,TRUE);
148         dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,TRUE);
149         dbox_shadeicon(ed->e.pd,glass_EIDINDPART,TRUE);
150         dbox_setfield(ed->e.pd,glass_EIDINDSIZE,"%i",12);
151       }
152       dbox_selecticon(ed->e.pd,glass_EIDTEXT,
153                                               !!(ed->idef.flags&wimp_ITEXT));
154       dbox_selecticon(ed->e.pd,glass_EIDSPRITE,
155                                             !!(ed->idef.flags&wimp_ISPRITE));
156       break;
157     case glass_EIAPPEARANCE:
158       dbox_setfield(ed->e.pd,glass_EIAFONTNAME,"%.%s",ed->font);
159       dbox_setfield(ed->e.pd,glass_EIAFSIZEWRITE,"%i",ed->fontSize);
160       if (ed->idef.flags & wimp_ITEXT)
161       {
162         if (ed->idef.flags & wimp_IFONT)
163         {
164           dbox_selecticon(ed->e.pd,glass_EIAFONT,TRUE);
165           dbox_shadeicon(ed->e.pd,glass_EIAFONTNAME,FALSE);
166           dbox_shadeicon(ed->e.pd,glass_EIAFONTMENU,FALSE);
167           dbox_shadeicon(ed->e.pd,glass_EIAFONT,FALSE);
168           dbox_shadeicon(ed->e.pd,glass_EIAFSIZEUP,FALSE);
169           dbox_shadeicon(ed->e.pd,glass_EIAFSIZEDOWN,FALSE);
170           dbox_shadeicon(ed->e.pd,glass_EIAFSIZEWRITE,FALSE);
171         }
172         else
173         {
174           dbox_selecticon(ed->e.pd,glass_EIAFONT,FALSE);
175           dbox_shadeicon(ed->e.pd,glass_EIAFONT,FALSE);
176           dbox_shadeicon(ed->e.pd,glass_EIAFONTNAME,TRUE);
177           dbox_shadeicon(ed->e.pd,glass_EIAFONTMENU,TRUE);
178           dbox_shadeicon(ed->e.pd,glass_EIAFSIZEUP,TRUE);
179           dbox_shadeicon(ed->e.pd,glass_EIAFSIZEDOWN,TRUE);
180           dbox_shadeicon(ed->e.pd,glass_EIAFSIZEWRITE,TRUE);
181         }
182       }
183       else
184       {
185         dbox_selecticon(ed->e.pd,glass_EIAFONT,FALSE);
186         dbox_shadeicon(ed->e.pd,glass_EIAFONT,TRUE);
187         dbox_shadeicon(ed->e.pd,glass_EIAFONTNAME,TRUE);
188         dbox_shadeicon(ed->e.pd,glass_EIAFONTMENU,TRUE);
189         dbox_shadeicon(ed->e.pd,glass_EIAFSIZEUP,TRUE);
190         dbox_shadeicon(ed->e.pd,glass_EIAFSIZEDOWN,TRUE);
191         dbox_shadeicon(ed->e.pd,glass_EIAFSIZEWRITE,TRUE);
192       }
193       dbox_selecticon(ed->e.pd,glass_EIAHCENTRE,
194                                          !!(ed->idef.flags & wimp_IHCENTRE));
195       dbox_selecticon(ed->e.pd,glass_EIAVCENTRE,
196                                          !!(ed->idef.flags & wimp_IVCENTRE));
197       dbox_selecticon(ed->e.pd,glass_EIARALIGN,
198                                            !!(ed->idef.flags & wimp_IRJUST));
199       dbox_selecticon(ed->e.pd,glass_EIABORDER,
200                                           !!(ed->idef.flags & wimp_IBORDER));
201       dbox_selecticon(ed->e.pd,glass_EIAFILL,
202                                           !!(ed->idef.flags & wimp_IFILLED));
203       if (ed->idef.flags & wimp_ISPRITE)
204       {
205         dbox_selecticon(ed->e.pd,glass_EIAHALFSIZE,
206                                      !!(ed->idef.flags & wimp_IHALVESPRITE));
207         dbox_shadeicon(ed->e.pd,glass_EIAHALFSIZE,FALSE);
208       }
209       else
210       {
211         dbox_selecticon(ed->e.pd,glass_EIAHALFSIZE,FALSE);
212         dbox_shadeicon(ed->e.pd,glass_EIAHALFSIZE,TRUE);
213       }
214       dbox_selecticon(ed->e.pd,glass_EIANEEDSHELP,
215                                           !!(ed->idef.flags & wimp_IREDRAW));
216       break;
217     case glass_EIACTIONS:
218       p=buffer_find();
219       sprintf(p,"eiBTYPE%i",(ed->idef.flags>>12) & 0x0f);
220       dbox_setfield(ed->e.pd,glass_EIABTYPE,"%s",msgs_lookup(p));
221       dbox_setfield(ed->e.pd,glass_EIAESGWRITE,"%i",
222                                                 (ed->idef.flags>>16) & 0x1f);
223       dbox_selecticon(ed->e.pd,glass_EIAADJUST,
224                                          !!(ed->idef.flags & wimp_IESG_NOC));
225       dbox_selecticon(ed->e.pd,glass_EIASELECT,
226                                         !!(ed->idef.flags & wimp_ISELECTED));
227       dbox_selecticon(ed->e.pd,glass_EIASHADE,
228                                         !!(ed->idef.flags & wimp_INOSELECT));
229       break;
230     case glass_EICOLOURS:
231       colSelect_setColourButton(ed->e.pd,glass_EICFORE,
232                                                   (ed->idef.flags>>24) & 15);
233       colSelect_setColourButton(ed->e.pd,glass_EICBACK,
234                                                   (ed->idef.flags>>28) & 15);
235       break;
236     case glass_EISIZE:
237       dbox_setfield(ed->e.pd,
238                     glass_EIPWRITE,
239                     "%i,%i",
240                     ed->idef.box.x1-ed->idef.box.x0,
241                     ed->idef.box.y1-ed->idef.box.y0);
242       dbox_shadeicon(ed->e.pd,glass_EIPSETSIZE,!(ed->idef.flags & 3));
243       break;
244     case glass_EIPOSITION:
245       dbox_setfield(ed->e.pd,
246                     glass_EIPWRITE,
247                     "%i,%i",
248                     ed->idef.box.x0,
249                     ed->idef.box.y0);
250       break;
251   }
252 }
253
254 /*
255  * BOOL editIcon__getSpriteSize(char *name,sprite_area *a,int *x,int *y)
256  *
257  * Use
258  *  Attempts to read the size of a sprite in OS units.
259  *
260  * Returns
261  *  TRUE if it really worked
262  */
263
264 static BOOL editIcon__getSpriteSize(char *name,sprite_area *a,int *x,int *y)
265 {
266   os_error *e;
267   os_regset r;
268
269   /* --- First look in the given area --- */
270
271   e=os_swivr(OS_SpriteOp,&r,40+256,a,name);
272
273   /* --- Now, OS version permitting, look in the WIMP area --- */
274
275   if (e && wimpt_getVersion()>=300)
276     e=os_swivr(Wimp_SpriteOp,&r,40,0,name);
277
278   /* --- If it worked, read out all the info and return it --- */
279
280   if (!e)
281   {
282     *x=r.r[3]<<bbc_modevar(r.r[6],bbc_XEigFactor);
283     *y=r.r[4]<<bbc_modevar(r.r[6],bbc_YEigFactor);
284   }
285
286   /* --- Return the success value --- */
287
288   return (!e);
289 }
290
291 /*
292  * void editIcon__setSize(glass_editIcon *ed)
293  *
294  * Use
295  *  Reads the size of the icon correctly from the definition, assuming
296  *  various things:
297  *
298  *  1. The icon isn't word-wrapped
299  *  2. Both selected and unselected versions of the sprite to use are the
300  *     same size
301  *  3. Size is independent of things like button type
302  */
303
304 static void editIcon__setSize(glass_editIcon *ed)
305 {
306   int w,h;
307   int sw,sh;
308   char sname[15];
309   static int posns[]={1,1,2,2,1,1,3,2};
310   int f;
311   char *sprname;
312
313   /* --- Read the current width and height from dbox --- */
314
315   dbox_scanfield(ed->e.pd,glass_EIPWRITE,"%d,%d",&w,&h);
316
317   /* --- Find out if this is going to be easy --- */
318
319   switch (ed->idef.flags & 3)
320   {
321     /* --- No icon data -- ignore this operation --- */
322
323     case 0:
324       break;
325
326     /* --- Only text -- work it out (assuming system font size) --- */
327
328     case 1:
329       h=48;
330       w=16*(strlen(ed->data)+1);
331       break;
332
333     /* --- Only a sprite -- use the size of the sprite --- */
334
335     case 2:
336       if (!editIcon__getSpriteSize(ed->data,ed->w->t->s,&w,&h))
337         note(msgs_lookup("eiSPRGONE"),ed->data);
338       break;
339
340     /* --- Text and sprite together --- */
341
342     case 3:
343       sprname=ed->data;
344
345       if ((ed->idef.flags & 0x100) && ed->hasValid)
346       {
347         /* --- Parse the validation string to find the sprite name --- */
348
349         int state=1;
350         char *p=ed->valid;
351         char *q=sname;
352
353         for (;*p>31 && state!=3;p++)
354         {
355           switch (*p)
356           {
357             case '\\':
358               if (p[1]>31)
359                 p++;
360               if (state==1)
361                 state=0;
362               else if (state==2)
363                 *q++=*p;
364               break;
365             case ';':
366               if (state>1)
367               {
368                 *q++=0;
369                 state=3;
370               }
371               else
372                 state=1;
373               break;
374             case 'S':
375             case 's':
376               if (state==1)
377                 state=2;
378               else if (state==2)
379                 *q++=*p;
380               break;
381             case ',':
382               switch (state)
383               {
384                 case 2:
385                   *q++=0;
386                   state++;
387               }
388               break;
389             default:
390               switch (state)
391               {
392                 case 1:
393                   state=0;
394                   break;
395                 case 2:
396                   *q++=*p;
397                   break;
398               }
399               break;
400           }
401         }
402
403         if (state==2)
404         {
405           *q++=0;
406           state=3;
407         }
408
409         if (state==3)
410           sprname=sname;
411       }
412
413       if (editIcon__getSpriteSize(sprname,ed->w->t->s,&sw,&sh))
414       {
415         if (ed->data[0])
416         {
417           h=48;
418           w=16*(strlen(ed->data)+1);
419
420           f=posns[(tst(ed->idef.flags,3)<<2) |
421                   (tst(ed->idef.flags,4)<<1) |
422                   (tst(ed->idef.flags,9)<<0)];
423
424           if (f & 2)
425             h=max2(h,sh);
426           else
427             h+=sh;
428
429           if (f & 1)
430             w=max2(w,sw);
431           else
432             w+=sw;
433         }
434         else
435         {
436           h=sh;
437           w=sw;
438         }
439       }
440       else
441         note(msgs_lookup("eiSPRGONE"),sprname);
442       break;
443   }
444
445   dbox_setfield(ed->e.pd,glass_EIPWRITE,"%i,%i",w,h);
446 }
447
448 /*
449  * void editIcon__closePanel(glass_editIcon *ed)
450  *
451  * Use
452  *  Records the settings in a panel for future reference, for example when
453  *  the panel is being replaced by a different one.
454  *
455  * Parameters
456  *  glass_editIcon *ed == the edit box we're talking about
457  */
458
459 #define Q dbox_READSTATE
460
461 static void editIcon__closePanel(glass_editIcon *ed)
462 {
463   int esg;
464   int x,y;
465   switch (ed->e.panel)
466   {
467     case glass_EIDATA:
468       dbox_getfield(ed->e.pd,glass_EIDDATA,ed->data,256);
469       dbox_getfield(ed->e.pd,glass_EIDVALSTRING,ed->valid,256);
470       dbox_scanfield(ed->e.pd,glass_EIDINDSIZE,"%d",&ed->indLen);
471       ed->hasValid=dbox_selecticon(ed->e.pd,glass_EIDVALID,Q);
472       ed->idef.flags&=~0x00000103;
473       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIDTEXT,Q)<<0;
474       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIDSPRITE,Q)<<1;
475       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIDINDIR,Q)<<8;
476       break;
477     case glass_EIAPPEARANCE:
478       ed->idef.flags&=~0x00000afc;
479       dbox_scanfield(ed->e.pd,glass_EIAFSIZEWRITE,"%d",&ed->fontSize);
480       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIAHCENTRE,Q)<<3;
481       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIAVCENTRE,Q)<<4;
482       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIABORDER,Q)<<2;
483       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIAFILL,Q)<<5;
484       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIAFONT,Q)<<6;
485       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIANEEDSHELP,Q)<<7;
486       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIARALIGN,Q)<<9;
487       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIAHALFSIZE,Q)<<11;
488       break;
489     case glass_EIACTIONS:
490       ed->idef.flags&=~0x007f0400;
491       dbox_scanfield(ed->e.pd,glass_EIAESGWRITE,"%d",&esg);
492       ed->idef.flags|=esg<<16;
493       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIAADJUST,Q)<<10;
494       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIASELECT,Q)<<21;
495       ed->idef.flags|=dbox_selecticon(ed->e.pd,glass_EIASHADE,Q)<<22;
496       break;
497     case glass_EISIZE:
498       dbox_scanfield(ed->e.pd,glass_EIPWRITE,"%d,%d",&x,&y);
499       ed->idef.box.x1=ed->idef.box.x0+x;
500       ed->idef.box.y1=ed->idef.box.y0+y;
501       break;
502     case glass_EIPOSITION:
503       dbox_scanfield(ed->e.pd,glass_EIPWRITE,"%d,%d",&x,&y);
504       ed->idef.box.x1+=x-ed->idef.box.x0;
505       ed->idef.box.y1+=y-ed->idef.box.y0;
506       ed->idef.box.x0=x;
507       ed->idef.box.y0=y;
508       break;
509   }
510 }
511
512 #undef Q
513
514 /*
515  * void editIcon__setPanel(glass_editIcon *ed,dbox_field f)
516  *
517  * Use
518  *  Creates a new panel based on a radio button click or some-such.
519  *
520  * Parameters
521  *  glass_editIcon *ed == the edit window to change panel
522  *  dbox_field f == the radio button associated with the desired panel
523  */
524
525 static void editIcon__panelHandler(dbox d,dbox_field f,void *handle);
526 static BOOL editIcon__panelRaw(dbox d,wimp_eventstr *e,void *handle);
527
528 static void editIcon__setPanel(glass_editIcon *ed,dbox_field f)
529 {
530   dbox d;
531   wimp_wstate s;
532   wimp_icon i;
533   int width,height;
534   int ox,oy;
535   wimp_w behind;
536   wimp_caretstr c;
537   BOOL ownCaret=TRUE;
538   if (f==ed->e.panel)
539     return;
540   editIcon__closePanel(ed);
541   wimpt_noerr(wimp_get_wind_state(dbox_syshandle(ed->e.d),&s));
542   wimpt_noerr(wimp_get_icon_info(dbox_syshandle(ed->e.d),
543                                                         glass_EIPOSN,&i));
544   ox=s.o.box.x0-s.o.x;
545   oy=s.o.box.y1-s.o.y;
546   mem_useUser(indir_alloc,indir_free);
547   if (f==-1)
548     d=dbox_create("iconNowt");
549   else
550     d=dbox_create(editIcon__panels[f-glass_EIDATA]);
551   if (!d)
552   {
553     mem_useMalloc();
554     return;
555   }
556   dbox_eventHandler(d,editIcon__panelHandler,ed);
557   dbox_rawEventHandler(d,editIcon__panelRaw,ed);
558   if (ed->e.panel)
559   {
560     wimpt_noerr(wimp_get_caret_pos(&c));
561     ownCaret=(c.w==dbox_syshandle(ed->e.pd));
562     dbox_selecticon(ed->e.d,ed->e.panel,dbox_RESETSTATE);
563     wimpt_noerr(wimp_get_wind_state(dbox_syshandle(ed->e.pd),&s));
564     pane_removePane(ed->e.p,dbox_syshandle(ed->e.pd));
565     dbox_delete(ed->e.pd);
566   }
567   dbox_selecticon(ed->e.d,f,dbox_SETSTATE);
568   behind=s.o.behind;
569   wimpt_noerr(wimp_get_wind_state(dbox_syshandle(d),&s));
570   width=s.o.box.x1-s.o.box.x0;
571   height=s.o.box.y1-s.o.box.y0;
572   s.o.box.x0=i.box.x0+ox+wimpt_dx();
573   s.o.box.y0=i.box.y0+oy+wimpt_dy();
574   s.o.box.x1=s.o.box.x0+width;
575   s.o.box.y1=s.o.box.y0+height;
576   s.o.y=10000;
577   s.o.behind=behind;
578   ed->e.pd=d;
579   ed->e.panel=f;
580   editIcon__setupPanel(ed);
581   wimpt_noerr(wimp_open_wind(&s.o));
582   if (ownCaret)
583   {
584     c.w=dbox_syshandle(d);
585     c.i=-1;
586     c.x=-500000;
587     c.y=0;
588     c.height=0x02000000;
589     wimpt_noerr(wimp_set_caret_pos(&c));
590   }
591   pane_addPane(ed->e.p,dbox_syshandle(d));
592   mem_useMalloc();
593 }
594
595 /*
596  * void editIcon__recreate(glass_editIcon *ed)
597  *
598  * Use
599  *  Recreates the icon from the dialogue box settings
600  *
601  * Parameters
602  *  glass_editIcon *ed == info about the edit
603  */
604
605 static void editIcon__recreate(glass_editIcon *ed)
606 {
607   char *p=0;
608   char *q=0;
609   int inum;
610   int fhandle;
611   ed->w->def->i[ed->i].edit=0;   /* Delink temporarily                     */
612   window_redrawIcon(ed->w,ed->i); /* Force redraw of old icon              */
613
614   if (!(ed->idef.flags & wimp_INDIRECT))
615   {
616     ed->indLen=12;
617     ed->hasValid=FALSE;
618   }
619   if (strlen(ed->data)>=ed->indLen)
620   {
621     ed->idef.flags|=wimp_INDIRECT;
622     ed->indLen=strlen(ed->data)+1;
623   }
624   if (ed->idef.flags & wimp_INDIRECT)
625   {
626     if (p=indir_alloc(ed->indLen),!p)
627     {
628       werr(FALSE,msgs_lookup("eiNEMUI"));
629       return;
630     }
631     if (ed->hasValid && (ed->idef.flags & wimp_ITEXT))
632     {
633       if (q=indir_alloc(strlen(ed->valid)+1),!q)
634       {
635         indir_free(p);
636         werr(FALSE,msgs_lookup("eiNEMUI"));
637         return;
638       }
639       strcpy(q,ed->valid);
640       ed->w->size+=strlen(ed->valid)+1;
641     }
642     strcpy(p,ed->data);
643     ed->w->size+=ed->indLen;
644   }
645
646   if (ed->w->def->i[ed->i].i.flags & wimp_IFONT) /* Was old anti?          */
647   {
648     fhandle=(ed->w->def->i[ed->i].i.flags >> 24) & 255;
649     wimpt_noerr(font_lose(fhandle));
650     ed->w->fonts[fhandle]--;
651   }
652   if (ed->idef.flags & wimp_IFONT) /* Is new icon antialiased?             */
653   {
654     if (font_find(ed->font,ed->fontSize*16,ed->fontSize*16,0,0,&fhandle))
655     {
656       werr(FALSE,msgs_lookup("eiCFF"),ed->font);
657       ed->idef.flags&=~wimp_IFONT;
658     }
659     else
660     {
661       ed->w->antiAliased=TRUE;
662       ed->w->fonts[fhandle]++;
663       ed->idef.flags=(ed->idef.flags & 0x00ffffff) | (fhandle<<24);
664     }
665   }
666
667   if (ed->w->def->i[ed->i].i.flags & wimp_INDIRECT)
668   {
669     indir_free(ed->w->def->i[ed->i].i.data.indirecttext.buffer);
670     ed->w->size-=ed->w->def->i[ed->i].i.data.indirecttext.bufflen;
671     if ((ed->w->def->i[ed->i].i.flags & wimp_ITEXT) &&
672           (ed->w->def->i[ed->i].i.data.indirecttext.validstring!=(char *)-1))
673     {
674       utils_ctermToNterm(ed->w->def->i[ed->i].
675                          i.data.indirecttext.validstring);
676       ed->w->size-=
677               strlen(ed->w->def->i[ed->i].i.data.indirecttext.validstring)+1;
678       indir_free(ed->w->def->i[ed->i].i.data.indirecttext.validstring);
679     }
680   }
681
682   if (p)
683   {
684     ed->idef.data.indirecttext.buffer=p;
685     ed->idef.data.indirecttext.bufflen=ed->indLen;
686     if (q)
687       ed->idef.data.indirecttext.validstring=q;
688     else if (ed->idef.flags & wimp_ITEXT)
689       ed->idef.data.indirecttext.validstring=(char *)-1;
690     else
691       ed->idef.data.indirectsprite.spritearea=ed->w->t->s;
692   }
693   else
694     memcpy(ed->idef.data.text,ed->data,12);
695
696   ed->w->def->i[ed->i].i=ed->idef;
697   dbox_scanfield(ed->e.d,glass_EINUMWRITE,"%d",&inum);
698   if (!window_renumber(ed->w,ed->i,inum))
699     dbox_setfield(ed->e.d,glass_EINUMWRITE,"%i",ed->i);
700   else
701     ed->i=inum;
702
703   window_redrawIcon(ed->w,ed->i); /* Force redraw of new icon              */
704   ed->w->def->i[ed->i].edit=ed;  /* Relink again                           */
705   tfile_markAsAltered(ed->w->t);
706 }
707
708 /*
709  * void editIcon__nextPanel(glass_editIcon *ed,int dir)
710  *
711  * Use
712  *  Changes panel to the next one in the given direction.  Skips shaded
713  *  panels and handles everything nicely.
714  *
715  * Parameters
716  *  glass_editIcon *ed == the edit dialogue box to move about in
717  *  int dir == the direction (-1 for up, 1 for down)
718  */
719
720 static void editIcon__nextPanel(glass_editIcon *ed,int dir)
721 {
722   int i=ed->e.panel;
723
724   if (i==-1)
725     i=(dir==1 ? glass_EIDATA : glass_EISIZE);
726   else
727     i+=dir;
728
729   for (;i>=glass_EIDATA && i<=glass_EISIZE;i+=dir)
730   {
731     if (!dbox_shadeicon(ed->e.d,i,dbox_READSTATE))
732     {
733       editIcon__setPanel(ed,i);
734       break;
735     }
736   }
737 }
738
739 /*----- Event handlers ----------------------------------------------------*/
740
741 /*
742  * void editIcon__dboxHandler(dbox d,dbox_field f,void *handle)
743  *
744  * Use
745  *  Handles any and all events directed at the dbox.  Well, almost all...
746  *
747  * Parameters
748  *  dbox d == the dbox handle
749  *  dbox_field f == the event that happened
750  *  void *handle == pointer to the dialogue box control info
751  */
752
753 static void editIcon__dboxHandler(dbox d,dbox_field f,void *handle)
754 {
755   glass_editIcon *ed=handle;
756   buttons_simpleArrow sa={0,9999,FALSE};
757
758   switch (f)
759   {
760     case dbox_CLOSE:
761       if (ed->e.pd)
762         dbox_deleteNoUpdate(ed->e.pd);
763       pane_delete(ed->e.p);
764       dbox_delete(ed->e.d);
765       ed->w->def->i[ed->i].edit=0;
766       mem_free(ed);
767       break;
768     case dbox_HELP:
769       help_startHelp();
770       help_addLine(msgs_lookup("eihEIDB"));
771       help_readFromIcon();
772       help_endHelp();
773       break;
774     case glass_EICAN:
775       dbox_clickicon(d,f);
776       if (!dbox_wasAdjustClick())
777         pane_close(ed->e.p);
778       else
779       {
780         /* --- set up for old icon --- */
781         ed->idef=ed->w->def->i[ed->i].i;
782         editIcon_readData(ed->w,ed->i);
783         dbox_setfield(ed->e.d,glass_EINUMWRITE,"%i",ed->i);
784         editIcon__setupPanel(ed);
785       }
786       dbox_unclick();
787       if (!dbox_wasAdjustClick())
788         editIcon_close(ed->w,ed->i);
789       break;
790     case glass_EIOK:
791       dbox_clickicon(d,f);
792       editIcon__closePanel(ed);
793       if (!dbox_wasAdjustClick())
794       {
795         pane_close(ed->e.p);
796         editIcon__recreate(ed);
797         dbox_unclick();
798         editIcon_close(ed->w,ed->i);
799       }
800       else
801       {
802         editIcon__recreate(ed);
803         editIcon_readData(ed->w,ed->i);
804         editIcon__setupPanel(ed);
805         dbox_unclick();
806       }
807       break;
808     case glass_EIDELETE:
809       dbox_clickicon(d,f);
810       if (gPrefs_current()->cDelIcon)
811       {
812         if (!warning(msgs_lookup("eiCDIP"),
813            msgs_lookup("eiCDI")))
814         {
815           dbox_unclick();
816           return;
817         }
818       }
819       pane_close(ed->e.p);
820       dbox_unclick();
821       window_deleteIcon(ed->w,ed->i); /* Closes the edit for us            */
822       break;
823     case glass_EIDATA:
824     case glass_EIAPPEARANCE:
825     case glass_EIACTIONS:
826     case glass_EICOLOURS:
827     case glass_EIPOSITION:
828     case glass_EISIZE:
829       editIcon__setPanel(ed,f);
830       break;
831     case glass_EINUMUP:
832       buttons_arrow(d,f,d,glass_EINUMWRITE,0,+1,&sa);
833       break;
834     case glass_EINUMDOWN:
835       buttons_arrow(d,f,d,glass_EINUMWRITE,0,-1,&sa);
836       break;
837   }
838 }
839
840 /*
841  * BOOL editIcon__dboxRaw(dbox d,wimp_eventstr *e,void *handle)
842  *
843  * Use
844  *  Handles open window requests and things for the main Preferences dbox.
845  *
846  * Parameters
847  *  dbox d == the dbox handle
848  *  wimp_eventstr *e == the event that happened
849  *  void *handle == a unused pointer
850  *
851  * Returns
852  *  TRUE if the event has been handled;
853  */
854
855 static BOOL editIcon__dboxRaw(dbox d,wimp_eventstr *e,void *handle)
856 {
857   BOOL handled=FALSE;
858   glass_editIcon *ed=handle;
859   glass_intMsgstr *m;
860   unused(d);
861   switch (e->e)
862   {
863     case wimp_EOPEN:
864       pane_moved(ed->e.p);
865       handled=TRUE;
866       break;
867     case wimp_EKEY:
868       switch (e->data.key.chcode)
869       {
870         case akbd_UpK+akbd_Sh:
871           editIcon__nextPanel(ed,-1);
872           handled=TRUE;
873           break;
874         case akbd_DownK+akbd_Sh:
875           editIcon__nextPanel(ed,+1);
876           handled=TRUE;
877           break;
878       }
879       break;
880     case wimp_ESEND:
881     case wimp_ESENDWANTACK:
882       switch (e->data.msg.hdr.action)
883       {
884         case wimp_MINTERNAL:
885           m=intMsgs_receive(e);
886           switch(e->data.msg.data.words[0])
887           {
888             case glass_DELETEFILE:
889               if (m->df.t==ed->w->t)
890                 editIcon_close(ed->w,ed->i);
891               break;
892             case glass_DELETEWINDOW:
893               if (m->dw.w==ed->w)
894                 editIcon_close(ed->w,ed->i);
895               break;
896             case glass_RENAME:
897               if (m->rn.w==ed->w)
898                 dbox_setfield(ed->e.d,glass_EIWINDISP,"%s",ed->w->id);
899               break;
900           }
901           break;
902       }
903       break;
904   }
905   return (handled);
906 }
907
908 /*
909  * menu editIcon__fontMaker(void *handle)
910  *
911  * Use
912  *  Sets up the font menu.
913  *
914  * Parameters
915  *  void *handle == pointer to this edit
916  *
917  * Returns
918  *  A menu to display
919  */
920
921 static menu editIcon__fontMaker(void *handle)
922 {
923   glass_editIcon *ed=handle;
924   menu m=fontMenu_createFontMenu(FALSE);
925   fontMenu_tickGivenName(ed->font);
926   return (m);
927 }
928
929 /*
930  * void editIcon__fontHandler(int hit[],void *handle)
931  *
932  * Use
933  *  Gets the font chosen from the font menu.
934  *
935  * Parameters
936  *  int hit[] == the hit string
937  *  void *handle == pointer to this edit
938  */
939
940 static void editIcon__fontHandler(int hit[],void *handle)
941 {
942   glass_editIcon *ed=handle;
943   if (hit[0])
944   {
945     strcpy(ed->font,fontMenu_fontname(hit[0],hit[1]));
946     dbox_setfield(ed->e.pd,glass_EIAFONTNAME,"%.%s",ed->font);
947   }
948 }
949
950 /*
951  * void editIcon__fontHelp(int hit[],void *handle)
952  *
953  * Use
954  *  Gives help on a font menu item
955  *
956  * Parameters
957  *  int hit[] == the hit string
958  *  void *handle == pointer to this edit
959  */
960
961 static void editIcon__fontHelp(int hit[],void *handle)
962 {
963   unused(handle);
964   if (hit[0])
965   {
966     help_startHelp();
967     help_addLine(msgs_lookup("eimhFONT"),fontMenu_fontname(hit[0],hit[1]));
968     help_endHelp();
969   }
970 }
971
972 /*
973  * menu editIcon__btypeMaker(void *handle)
974  *
975  * Use
976  *  Generates and sets up a button type menu for an edit dialogue box
977  *
978  * Parameters
979  *  void *handle == pointer to the edit
980  *
981  * Returns
982  *  The menu to use
983  */
984
985 static menu editIcon__btypeMaker(void *handle)
986 {
987   static menu m;
988   static int ticked;
989   glass_editIcon *ed=handle;
990   int i;
991   char *buf=buffer_find();
992   if (!m)
993   {
994     m=menu_new(msgs_lookup("eiBTMT"),msgs_lookup("eiBTYPE0"));
995     for (i=1;i<=15;i++)
996     {
997       sprintf(buf,"eiBTYPE%i",i);
998       menu_extend(m,msgs_lookup(buf));
999     }
1000   }
1001   if (ticked)
1002     menu_setflags(m,ticked,FALSE,FALSE);
1003   ticked=((ed->idef.flags>>12)&0x0f)+1;
1004   menu_setflags(m,ticked,TRUE,FALSE);
1005   return (m);
1006 }
1007
1008 /*
1009  * void editIcon__btypeHandler(int hit[],void *handle)
1010  *
1011  * Use
1012  *  Handles a click on the button type menu.
1013  *
1014  * Parameters
1015  *  int hit[] == the mouse click info
1016  *  void *handle == pointer to edit information
1017  */
1018
1019 static void editIcon__btypeHandler(int hit[],void *handle)
1020 {
1021   glass_editIcon *ed=handle;
1022   char *buf=buffer_find();
1023   if (hit[0])
1024   {
1025     ed->idef.flags&=~0x0000f000;
1026     ed->idef.flags+=(hit[0]-1)<<12;
1027     sprintf(buf,"eiBTYPE%i",hit[0]-1);
1028     dbox_setfield(ed->e.pd,glass_EIABTYPE,"%s",msgs_lookup(buf));
1029   }
1030 }
1031
1032 /*
1033  * void editIcon__colProc(dbox d,dbox_field f,int colour, void *handle)
1034  *
1035  * Use
1036  *  This routine is called when a colour is selected in the colours panel.
1037  *
1038  * Parameters
1039  *  dbox d == the panel's handle
1040  *  dbox_field f == the colour button that has changed
1041  *  int colour == the new colour for the button
1042  *  void *handle == pointer to this edit
1043  */
1044
1045 static void editIcon__colProc(dbox d,dbox_field f,int colour,void *handle)
1046 {
1047   glass_editIcon *ed=handle;
1048   unused(d);
1049   switch (f)
1050   {
1051     case glass_EICFORE:
1052       ed->idef.flags=(ed->idef.flags & ~0x0f000000)+(colour<<24);
1053       break;
1054     case glass_EICBACK:
1055       ed->idef.flags=(ed->idef.flags & ~0xf0000000)+(colour<<28);
1056       break;
1057   }
1058 }
1059
1060 /*
1061  * void editIcon__btypeHelp(int hit[],void *handle)
1062  *
1063  * Use
1064  *  Handles a help request for the button type menu.
1065  *
1066  * Parameters
1067  *  int hit[] == the helpq info
1068  *  void *handle == pointer to edit information
1069  */
1070
1071 static void editIcon__btypeHelp(int hit[],void *handle)
1072 {
1073   char *buf=buffer_find();
1074   unused(handle);
1075   if (hit[0])
1076   {
1077     help_startHelp();
1078     sprintf(buf,"eiBTYPE%i",hit[0]-1);
1079     help_addLine(msgs_lookup("eimhBTYPE"),msgs_lookup(buf));
1080     help_endHelp();
1081   }
1082 }
1083
1084 /*
1085  * void editIcon__posSizeArrows(dbox d,dbox_field f,int diff,void *handle)
1086  *
1087  * Use
1088  *  Handles a click event on one of the position or size arrow buttons in
1089  *  the dialogue box.  See the structure definition below for a description
1090  *  of the data structure required.
1091  */
1092
1093 typedef struct
1094 {
1095   BOOL xOrY;
1096   BOOL sizing;
1097 }
1098 editIcon__posSizeArrowstr;
1099
1100 static void editIcon__posSizeArrows(dbox d,
1101                                     dbox_field f,
1102                                     int diff,
1103                                     void *handle)
1104 {
1105   editIcon__posSizeArrowstr *s=handle;
1106   int x,y;
1107   int *v;
1108
1109   dbox_scanfield(d,f,"%d,%d",&x,&y);
1110   v=s->xOrY ? &x : &y;
1111   *v+=diff;
1112   if (s->sizing && *v<0)
1113     *v=0;
1114   dbox_setfield(d,f,"%i,%i",x,y);
1115 }
1116
1117 /*
1118  * void editIcon__panelHandler(dbox d,dbox_field f,void *handle)
1119  *
1120  * Use
1121  *  Handles simple click events for the current panel in an edit dbox
1122  *
1123  * Parameters
1124  *  dbox d == the panel's dbox handle
1125  *  dbox_field f == the icon that was clicked
1126  *  void *handle == pointer to edit information
1127  */
1128
1129 static void editIcon__panelHandler(dbox d,dbox_field f,void *handle)
1130 {
1131   glass_editIcon *ed=handle;
1132   buttons_simpleArrow sa={0,9999,FALSE};
1133   buttons_simpleArrow esga={0,31,FALSE};
1134   editIcon__posSizeArrowstr psa={0,FALSE};
1135   BOOL indon;
1136
1137   switch (f)
1138   {
1139     case dbox_CLOSE:
1140     case dbox_HELP:
1141     case glass_EIOK:
1142     case glass_EICAN:
1143       editIcon__dboxHandler(ed->e.d,f,ed);
1144       return;
1145       break;
1146   }
1147   switch (ed->e.panel)
1148   {
1149     case glass_EIDATA:
1150       switch (f)
1151       {
1152         case glass_EIDINDIR:
1153           if (dbox_selecticon(d,f,dbox_READSTATE))
1154           {
1155             if (dbox_selecticon(ed->e.pd,glass_EIDTEXT,dbox_READSTATE))
1156             {
1157               dbox_shadeicon(ed->e.pd,glass_EIDVALID,FALSE);
1158               dbox_shadeicon(ed->e.pd,
1159                              glass_EIDVALSTRING,
1160                              !dbox_selecticon(ed->e.pd,
1161                                               glass_EIDVALID,
1162                                               dbox_READSTATE));
1163             }
1164             dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,FALSE);
1165             dbox_shadeicon(ed->e.pd,glass_EIDINDUP,FALSE);
1166             dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,FALSE);
1167             dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,FALSE);
1168             dbox_shadeicon(ed->e.pd,glass_EIDINDPART,FALSE);
1169           }
1170           else
1171           {
1172             dbox_shadeicon(ed->e.pd,glass_EIDVALSTRING,TRUE);
1173             dbox_shadeicon(ed->e.pd,glass_EIDVALID,TRUE);
1174             dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,TRUE);
1175             dbox_shadeicon(ed->e.pd,glass_EIDINDUP,TRUE);
1176             dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,TRUE);
1177             dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,TRUE);
1178             dbox_shadeicon(ed->e.pd,glass_EIDINDPART,TRUE);
1179           }
1180           break;
1181         case glass_EIDINDUP:
1182           buttons_arrow(ed->e.pd,f,ed->e.pd,glass_EIDINDSIZE,0,+1,&sa);
1183           break;
1184         case glass_EIDINDDOWN:
1185           buttons_arrow(ed->e.pd,f,ed->e.pd,glass_EIDINDSIZE,0,-1,&sa);
1186           break;
1187         case glass_EIDVALID:
1188           dbox_shadeicon(ed->e.pd,glass_EIDVALSTRING,dbox_TOGGLESTATE);
1189           break;
1190         case glass_EIDMINIMISE:
1191           dbox_clickicon(d,f);
1192           dbox_getfield(d,glass_EIDDATA,ed->data,256);
1193           dbox_setfield(d,glass_EIDINDSIZE,"%i",strlen(ed->data)+1);
1194           dbox_unclick();
1195           break;
1196         case glass_EIDTEXT:
1197           if (dbox_selecticon(ed->e.pd,glass_EIDTEXT,dbox_READSTATE))
1198           {
1199             dbox_shadeicon(ed->e.pd,glass_EIDDATA,FALSE);
1200             dbox_shadeicon(ed->e.pd,glass_EIDINDIR,FALSE);
1201             if (dbox_selecticon(d,glass_EIDINDIR,dbox_READSTATE))
1202             {
1203               dbox_shadeicon(ed->e.pd,glass_EIDVALID,FALSE);
1204               dbox_shadeicon(ed->e.pd,glass_EIDVALSTRING,
1205                 !dbox_selecticon(ed->e.pd,glass_EIDVALID,dbox_READSTATE));
1206               dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,FALSE);
1207               dbox_shadeicon(ed->e.pd,glass_EIDINDUP,FALSE);
1208               dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,FALSE);
1209               dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,FALSE);
1210               dbox_shadeicon(ed->e.pd,glass_EIDINDPART,FALSE);
1211             }
1212             else
1213             {
1214               dbox_shadeicon(ed->e.pd,glass_EIDVALID,TRUE);
1215               dbox_shadeicon(ed->e.pd,glass_EIDVALSTRING,TRUE);
1216               dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,TRUE);
1217               dbox_shadeicon(ed->e.pd,glass_EIDINDUP,TRUE);
1218               dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,TRUE);
1219               dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,TRUE);
1220               dbox_shadeicon(ed->e.pd,glass_EIDINDPART,TRUE);
1221             }
1222             dbox_shadeicon(ed->e.d,glass_EICOLOURS,
1223                                             !!(ed->idef.flags & wimp_IFONT));
1224           }
1225           else
1226           {
1227             dbox_shadeicon(ed->e.pd,glass_EIDVALID,TRUE);
1228             dbox_shadeicon(ed->e.pd,glass_EIDVALSTRING,TRUE);
1229             if (dbox_selecticon(d,glass_EIDSPRITE,dbox_READSTATE))
1230             {
1231               dbox_shadeicon(ed->e.pd,glass_EIDDATA,FALSE);
1232               dbox_shadeicon(ed->e.pd,glass_EIDINDIR,FALSE);
1233               indon=dbox_selecticon(d,glass_EIDINDIR,dbox_READSTATE);
1234               dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,!indon);
1235               dbox_shadeicon(ed->e.pd,glass_EIDINDUP,!indon);
1236               dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,!indon);
1237               dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,!indon);
1238               dbox_shadeicon(ed->e.pd,glass_EIDINDPART,!indon);
1239             }
1240             else
1241             {
1242               dbox_shadeicon(ed->e.pd,glass_EIDDATA,TRUE);
1243               dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,TRUE);
1244               dbox_shadeicon(ed->e.pd,glass_EIDINDUP,TRUE);
1245               dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,TRUE);
1246               dbox_shadeicon(ed->e.pd,glass_EIDINDPART,TRUE);
1247               dbox_shadeicon(ed->e.pd,glass_EIDINDIR,TRUE);
1248               dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,TRUE);
1249             }
1250             dbox_shadeicon(ed->e.d,glass_EICOLOURS,FALSE);
1251           }
1252           break;
1253         case glass_EIDSPRITE:
1254           if (dbox_selecticon(ed->e.pd,glass_EIDSPRITE,dbox_READSTATE))
1255           {
1256             dbox_shadeicon(ed->e.pd,glass_EIDDATA,FALSE);
1257             dbox_shadeicon(ed->e.pd,glass_EIDINDIR,FALSE);
1258             indon=dbox_selecticon(d,glass_EIDINDIR,dbox_READSTATE);
1259             dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,!indon);
1260             dbox_shadeicon(ed->e.pd,glass_EIDINDUP,!indon);
1261             dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,!indon);
1262             dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,!indon);
1263             dbox_shadeicon(ed->e.pd,glass_EIDINDPART,!indon);
1264           }
1265          else if (!dbox_selecticon(ed->e.pd,glass_EIDTEXT,dbox_READSTATE))
1266           {
1267             dbox_shadeicon(ed->e.pd,glass_EIDDATA,TRUE);
1268             dbox_shadeicon(ed->e.pd,glass_EIDINDIR,TRUE);
1269             dbox_shadeicon(ed->e.pd,glass_EIDINDSIZE,TRUE);
1270             dbox_shadeicon(ed->e.pd,glass_EIDINDUP,TRUE);
1271             dbox_shadeicon(ed->e.pd,glass_EIDINDDOWN,TRUE);
1272             dbox_shadeicon(ed->e.pd,glass_EIDMINIMISE,TRUE);
1273             dbox_shadeicon(ed->e.pd,glass_EIDINDPART,TRUE);
1274           }
1275           break;
1276       }
1277       break;
1278     case glass_EIAPPEARANCE:
1279       switch (f)
1280       {
1281         case glass_EIAFONT:
1282           if (dbox_selecticon(d,f,dbox_READSTATE) ||
1283               fontMenu_createFontMenu(FALSE))
1284           {
1285             dbox_selecticon(d,f,dbox_TOGGLESTATE);
1286             dbox_shadeicon(d,glass_EIAFONTNAME,dbox_TOGGLESTATE);
1287             dbox_shadeicon(d,glass_EIAFONTMENU,dbox_TOGGLESTATE);
1288             dbox_shadeicon(d,glass_EIAFSIZEUP,dbox_TOGGLESTATE);
1289             dbox_shadeicon(d,glass_EIAFSIZEDOWN,dbox_TOGGLESTATE);
1290             dbox_shadeicon(d,glass_EIAFSIZEWRITE,dbox_TOGGLESTATE);
1291             dbox_shadeicon(ed->e.d,glass_EICOLOURS,dbox_TOGGLESTATE);
1292           }
1293           break;
1294         case glass_EIAFSIZEUP:
1295           buttons_arrow(ed->e.pd,f,ed->e.pd,glass_EIAFSIZEWRITE,0,+1,&sa);
1296           break;
1297         case glass_EIAFSIZEDOWN:
1298           buttons_arrow(ed->e.pd,f,ed->e.pd,glass_EIAFSIZEWRITE,0,-1,&sa);
1299           break;
1300       }
1301       break;
1302     case glass_EIACTIONS:
1303       switch (f)
1304       {
1305         case glass_EIAESGUP:
1306           buttons_arrow(d,f,d,glass_EIAESGWRITE,0,+1,&esga);
1307           break;
1308         case glass_EIAESGDOWN:
1309           buttons_arrow(d,f,d,glass_EIAESGWRITE,0,-1,&esga);
1310           break;
1311       }
1312       break;
1313     case glass_EICOLOURS:
1314       /* Nothin' doing */
1315       break;
1316     case glass_EISIZE:
1317       psa.sizing=TRUE;
1318       /* Drop through */
1319     case glass_EIPOSITION:
1320       switch (f)
1321       {
1322         case glass_EIPUP:
1323           psa.xOrY=FALSE;
1324           buttons_arrow(d,f,d,glass_EIPWRITE,
1325                         editIcon__posSizeArrows,
1326                         +wimpt_dy(),
1327                         &psa);
1328           break;
1329         case glass_EIPDOWN:
1330           psa.xOrY=FALSE;
1331           buttons_arrow(d,f,d,glass_EIPWRITE,
1332                         editIcon__posSizeArrows,
1333                         -wimpt_dy(),
1334                         &psa);
1335           break;
1336         case glass_EIPLEFT:
1337           psa.xOrY=TRUE;
1338           buttons_arrow(d,f,d,glass_EIPWRITE,
1339                         editIcon__posSizeArrows,
1340                         -wimpt_dx(),
1341                         &psa);
1342           break;
1343         case glass_EIPRIGHT:
1344           psa.xOrY=TRUE;
1345           buttons_arrow(d,f,d,glass_EIPWRITE,
1346                         editIcon__posSizeArrows,
1347                         +wimpt_dx(),
1348                         &psa);
1349           break;
1350         case glass_EIPSETSIZE:
1351           dbox_clickicon(d,f);
1352           editIcon__setSize(ed);
1353           dbox_unclick();
1354           break;
1355       }
1356       break;
1357   }
1358 }
1359
1360 /*
1361  * BOOL editIcon__panelRaw(dbox d,wimp_eventstr *e,void *handle)
1362  *
1363  * Use
1364  *  Handles the more wierd events for a particular panel.
1365  *
1366  * Parameters
1367  *  dbox d == the dbox handle of the panel
1368  *  wimp_eventstr *e == the event to look at
1369  *  void *handle == pointer to the current edit
1370  *
1371  * Returns
1372  *  TRUE if the event is dead (long live the event...)
1373  */
1374
1375 static BOOL editIcon__panelRaw(dbox d,wimp_eventstr *e,void *handle)
1376 {
1377   BOOL handled=FALSE;
1378   glass_editIcon *ed=handle;
1379   BOOL cursor=FALSE;
1380   if (e->e==wimp_EKEY)
1381   {
1382     switch (e->data.key.chcode)
1383     {
1384       case akbd_UpK+akbd_Sh:
1385         editIcon__nextPanel(ed,-1);
1386         handled=TRUE;
1387         break;
1388       case akbd_DownK+akbd_Sh:
1389         editIcon__nextPanel(ed,+1);
1390         handled=TRUE;
1391         break;
1392     }
1393   }
1394   if (!handled) switch (ed->e.panel)
1395   {
1396     case glass_EIDATA:
1397       /* Nothin' doing */
1398       break;
1399     case glass_EIAPPEARANCE:
1400       switch (e->e)
1401       {
1402         case wimp_EBUT:
1403           switch (e->data.but.m.i)
1404           {
1405             case glass_EIAFONTNAME:
1406               menu_make(editIcon__fontMaker,editIcon__fontHandler,
1407                                                       editIcon__fontHelp,ed);
1408               handled=TRUE;
1409               break;
1410             case glass_EIAFONTMENU:
1411               dbox_clickicon(d,glass_EIAFONTMENU);
1412               menu_make(editIcon__fontMaker,editIcon__fontHandler,
1413                                                       editIcon__fontHelp,ed);
1414               dbox_unclick();
1415               handled=TRUE;
1416               break;
1417           }
1418           break;
1419       }
1420       break;
1421     case glass_EIACTIONS:
1422       switch (e->e)
1423       {
1424         case wimp_EBUT:
1425           switch (e->data.but.m.i)
1426           {
1427             case glass_EIABTYPE:
1428               menu_make(editIcon__btypeMaker,editIcon__btypeHandler,
1429                                                      editIcon__btypeHelp,ed);
1430               handled=TRUE;
1431               break;
1432             case glass_EIABTMENU:
1433               dbox_clickicon(d,glass_EIABTMENU);
1434               menu_make(editIcon__btypeMaker,editIcon__btypeHandler,
1435                                                      editIcon__btypeHelp,ed);
1436               dbox_unclick();
1437               handled=TRUE;
1438               break;
1439           }
1440           break;
1441         case wimp_EKEY:
1442           switch (e->data.key.c.i)
1443           {
1444             case glass_EIAESGWRITE:
1445               switch (e->data.key.chcode)
1446               {
1447                 case akbd_DownK:
1448                 case akbd_UpK:
1449                 case akbd_TabK:
1450                 case akbd_TabK+akbd_Sh:
1451                 case akbd_UpK+akbd_Ctl:
1452                 case akbd_DownK+akbd_Ctl:
1453                   cursor=TRUE;
1454                   break;
1455               }
1456               handled=buttons_insertChar(d,e->data.key.chcode,'0','9');
1457               if (handled || cursor)
1458                 buttons_arrowClick(d,glass_EIAESGWRITE,0,31,0,FALSE);
1459               break;
1460           }
1461           break;
1462       }
1463       break;
1464     case glass_EICOLOURS:
1465       switch (e->e)
1466       {
1467         case wimp_EBUT:
1468           switch (e->data.but.m.i)
1469           {
1470             case glass_EICFORE:
1471               colSelect(ed->e.pd,glass_EICFORE,e->data.but.m.bbits,
1472                                   msgs_lookup("eiFGC"),FALSE,
1473                                                        editIcon__colProc,ed);
1474               break;
1475             case glass_EICBACK:
1476               colSelect(ed->e.pd,glass_EICBACK,e->data.but.m.bbits,
1477                                   msgs_lookup("eiBGC"),FALSE,
1478                                                        editIcon__colProc,ed);
1479               break;
1480           }
1481           break;
1482       }
1483       break;
1484     case glass_EISIZE:
1485     case glass_EIPOSITION:
1486       /* Nothin' doin' */
1487       break;
1488   }
1489   return (FALSE);
1490 }
1491
1492 /*----- External routines -------------------------------------------------*/
1493
1494 /*
1495  * void editIcon_renumber(glass_windPointer *w,int icon,int new)
1496  *
1497  * Use
1498  *  Informs an edit dialogue that an icon has been renumbered.
1499  *
1500  * Parameters
1501  *  glass_windPointer *w == the window containing the icon
1502  *  int icon == the icon number
1503  *  int new == the new number for the icon
1504  */
1505
1506 void editIcon_renumber(glass_windPointer *w,int icon,int new)
1507 {
1508   glass_editIcon *ed=w->def->i[icon].edit;
1509   if (!ed)
1510     return;
1511   ed->i=new;
1512   dbox_setfield(ed->e.d,glass_EINUMWRITE,"%i",new);
1513 }
1514
1515 /*
1516  * void editIcon_iconMoved(glass_windPointer *w,int icon)
1517  *
1518  * Use
1519  *  Informs an edit dialogue that an icon has been moved.
1520  *
1521  * Parameters
1522  *  glass_windPointer *w == the window containing the icon
1523  *  int icon == the icon number.  This may not be the same during the edit...
1524  */
1525
1526 void editIcon_iconMoved(glass_windPointer *w,int icon)
1527 {
1528   glass_editIcon *ed=w->def->i[icon].edit;
1529   if (!ed)
1530     return;
1531   ed->idef.box=ed->w->def->i[ed->i].i.box;
1532   if (ed->e.panel==glass_EIPOSITION || ed->e.panel==glass_EISIZE)
1533     editIcon__setupPanel(ed);
1534 }
1535
1536 /*
1537  * void editIcon_readData(glass_windPointer *w,int icon)
1538  *
1539  * Use
1540  *  Forces a re-read of the icon data for the given icon edit
1541  *
1542  * Parameters
1543  *  glass_windPointer *w == the window containing the icon
1544  *  int icon == the icon number.  This may not be the same during the edit...
1545  */
1546
1547 void editIcon_readData(glass_windPointer *w,int icon)
1548 {
1549   glass_editIcon *ed=w->def->i[icon].edit;
1550   if (!ed)
1551     return;
1552   ed->idef.data=ed->w->def->i[ed->i].i.data;
1553   if (ed->idef.flags & wimp_INDIRECT)
1554   {
1555     utils_ctermToNterm(ed->idef.data.indirecttext.buffer);
1556     strcpy(ed->data,ed->idef.data.indirecttext.buffer);
1557     ed->indLen=ed->idef.data.indirecttext.bufflen;
1558     if (ed->idef.flags & wimp_ITEXT &&
1559                           ed->idef.data.indirecttext.validstring!=(char *)-1)
1560     {
1561       utils_ctermToNterm(ed->idef.data.indirecttext.validstring);
1562       strcpy(ed->valid,ed->idef.data.indirecttext.validstring);
1563       ed->hasValid=TRUE;
1564     }
1565     else
1566     {
1567       ed->valid[0]=0;
1568       ed->hasValid=FALSE;
1569     }
1570   }
1571   else
1572   {
1573     ed->data[12]=0;
1574     memcpy(ed->data,ed->idef.data.text,12);
1575     utils_ctermToNterm(ed->data);
1576     ed->valid[0]=0;
1577     ed->indLen=12;
1578   }
1579   if (ed->e.panel==glass_EIDATA)
1580     editIcon__setupPanel(ed);
1581   if (ed->idef.flags & wimp_IFONT)
1582   {
1583     if (ed->e.panel==glass_EICOLOURS)
1584       editIcon__setPanel(ed,-1);
1585     dbox_shadeicon(ed->e.d,glass_EICOLOURS,TRUE);
1586   }
1587   else
1588     dbox_shadeicon(ed->e.d,glass_EICOLOURS,FALSE);
1589 }
1590
1591 /*
1592  * void editIcon_close(glass_windPointer *w,int icon)
1593  *
1594  * Use
1595  *  Closes an edit window
1596  *
1597  * Parameters
1598  *  glass_windPointer *w == the window containing the icon
1599  *  int icon == the icon number.  This may not be the same during the edit...
1600  */
1601
1602 void editIcon_close(glass_windPointer *w,int icon)
1603 {
1604   glass_editIcon *ed=w->def->i[icon].edit;
1605   if (ed)
1606   {
1607     if (ed->e.pd)
1608       dbox_deleteNoUpdate(ed->e.pd);
1609     pane_delete(ed->e.p);
1610     dbox_deleteNoUpdate(ed->e.d);
1611     ed->w->def->i[ed->i].edit=0;
1612     mem_free(ed);
1613   }
1614 }
1615
1616 /*
1617  * void editIcon(glass_windPointer *w,int icon)
1618  *
1619  * Use
1620  *  Edits the given icon in a dialogue box.
1621  *
1622  * Parameters
1623  *  glass_windPointer *w == the window containing the icon
1624  *  int icon == the icon number.  This may not be the same during the edit...
1625  */
1626
1627 void editIcon(glass_windPointer *w,int icon)
1628 {
1629   glass_editIcon *ed;
1630   os_regset r;
1631   if (w->def->i[icon].edit)
1632   {
1633     dbox_display(w->def->i[icon].edit->e.d,TRUE);
1634     pane_front(w->def->i[icon].edit->e.p);
1635     return;
1636   }
1637   mem_useUser(indir_alloc,indir_free);
1638   ed=mem_alloc(sizeof(glass_editIcon));
1639   if (!ed)
1640   {
1641     werr(FALSE,msgs_lookup("eiNEM"));
1642     mem_useMalloc();
1643     return;
1644   }
1645   if (ed->e.d=dbox_create("editIcon"),!ed->e.d)
1646   {
1647     mem_free(ed);
1648     mem_useMalloc();
1649     return;
1650   }
1651   if (ed->e.p=pane_create(dbox_syshandle(ed->e.d)),!ed->e.p)
1652   {
1653     dbox_delete(ed->e.d);
1654     mem_free(ed);
1655     mem_useMalloc();
1656     return;
1657   }
1658   mem_useMalloc();
1659   ed->w=w;
1660   ed->i=icon;
1661   ed->idef=w->def->i[icon].i;
1662   w->def->i[icon].edit=ed;
1663   ed->e.panel=0;
1664
1665   /* --- Set up icon data now --- */
1666   editIcon_readData(w,icon);
1667   if (ed->idef.flags & wimp_IFONT)
1668   {
1669     r.r[0]=ed->idef.flags >> 24;
1670     r.r[1]=(int)(ed->font);
1671     wimpt_noerr(os_swix(XFont_ReadDefn,&r));
1672     utils_ctermToNterm(ed->font);
1673     ed->fontSize=r.r[2]/16;
1674     dbox_shadeicon(ed->e.d,glass_EICOLOURS,TRUE);
1675   }
1676   else
1677   {
1678     strcpy(ed->font,"Homerton.Medium");
1679     ed->fontSize=12;
1680     dbox_shadeicon(ed->e.d,glass_EICOLOURS,FALSE);
1681   }
1682
1683   /* --- Now do handlers, and final setting up --- */
1684   dbox_setfield(ed->e.d,glass_EINUMWRITE,"%i",icon);
1685   dbox_setfield(ed->e.d,glass_EIWINDISP,"%s",w->id);
1686   dbox_eventHandler(ed->e.d,editIcon__dboxHandler,ed);
1687   dbox_rawEventHandler(ed->e.d,editIcon__dboxRaw,ed);
1688   dbox_openDisplaced(ed->e.d);
1689   editIcon__setPanel(ed,glass_EIDATA);
1690 }