chiark / gitweb /
Initial revision
[ssr] / StraySrc / Glass / !Glass / c / align
1 /*
2  * align.c
3  *
4  * The alignment 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 <stdlib.h>
35 #include <stdio.h>
36
37 /*
38  * Steel headers
39  */
40
41 #define _STDAPP
42 #include "steel/Steel.h"
43
44 /*
45  * Glass headers
46  */
47
48 #include "gIcons.h"
49
50 #include "glass.h"
51 #include "window.h"
52 #include "align.h"
53 #include "tfile.h"
54
55 /*----- Type definitions --------------------------------------------------*/
56
57 typedef struct
58 {
59   wimp_box box;
60   int i;
61 }
62 align__iconstr;
63
64 typedef enum
65 {
66   align__MIN,
67   align__CENTRE,
68   align__MAX
69 }
70 align__order;
71
72 /*----- Static global variables -------------------------------------------*/
73
74 static dbox align__dbox;
75 static align__order align__sortOrder;
76
77 /*----- Support routines --------------------------------------------------*/
78
79 /*
80  * int align__horizCompare(const void *a,const void *b)
81  *
82  * Use
83  *  Compares two icons for horizontal alignment.  Used as a compare for
84  *  qsort.
85  */
86
87 static int align__horizCompare(const void *a,const void *b)
88 {
89   const align__iconstr *x=a;
90   const align__iconstr *y=b;
91   int result=0;
92   switch (align__sortOrder)
93   {
94     case align__MIN:
95       result=x->box.x0-y->box.x0;
96       break;
97     case align__MAX:
98       result=x->box.x1-y->box.x1;
99       break;
100     case align__CENTRE:
101       result=x->box.x1+x->box.x0-y->box.x0-y->box.x1;
102       break;
103     default:
104       werr(TRUE,msgs_lookup("alBATH"));
105       break;
106   }
107   return (result);
108 }
109
110 /*
111  * int align__vertCompare(const void *a,const void *b)
112  *
113  * Use
114  *  Compares two icons for vertical alignment.  Used as a compare for
115  *  qsort.
116  */
117
118 static int align__vertCompare(const void *a,const void *b)
119 {
120   const align__iconstr *x=a;
121   const align__iconstr *y=b;
122   int result=0;
123   switch (align__sortOrder)
124   {
125     case align__MIN:
126       result=x->box.y0-y->box.y0;
127       break;
128     case align__MAX:
129       result=x->box.y1-y->box.y1;
130       break;
131     case align__CENTRE:
132       result=x->box.y1+x->box.y0-y->box.y0-y->box.y1;
133       break;
134     default:
135       werr(TRUE,msgs_lookup("alBATV"));
136       break;
137   }
138   return (result);
139 }
140
141 /*
142  * void align__doAlign(void)
143  *
144  * Use
145  *  Does an align on the currently selected icons, wherever they may be.
146  *  The settings are read from the dialogue box, and processed.
147  */
148
149 static void align__doAlign(void)
150 {
151   align__iconstr *a;                 /* Array of icons to align            */
152   glass_windPointer *w=window_selectionOwner(); /* Window containing icons */
153   wimp_box bound;                    /* Bounding box of the selection      */
154   int width=0;                       /* Total width of all the icons       */
155   int height=0;                      /* Total height of all the icons      */
156
157   int xcont=-1;                      /* Index/icon of horizontal container */
158   int ycont=-1;                      /* Index/icon of vertical container   */
159
160   int num;                           /* Number of selected icons           */
161
162   /* --- Loop variables --- */
163
164   int i;
165   int j;
166
167   /* --- Ensure that we have something to do --- */
168
169   if (!w)
170     return;
171   if (!w->selno)
172     return;
173
174   num=w->selno;
175
176   /* --- Put the icons into an array for sorting etc. --- *
177    *
178    * We also keep track of the bounding box of the selected icons, their
179    * total width and their total height, and which, if any, are containers.
180    */
181
182   {
183     BOOL started=FALSE;
184
185     /* --- Allocate memory for the array --- */
186
187     if (a=mem_alloc(num*sizeof(align__iconstr)),!a)
188     {
189       werr(FALSE,msgs_lookup("alNEM"));
190       return;
191     }
192
193     j=0;
194     for (i=0;i<w->def->desc.w.nicons;i++)
195     {
196       if (w->def->i[i].selected)
197       {
198         a[j].i=i;
199         window_boundingBox(w,i,&a[j].box);
200         width+=a[j].box.x1-a[j].box.x0;
201         height+=a[j].box.y1-a[j].box.y0;
202         if (!started)
203         {
204           bound=a[j].box;
205           started=TRUE;
206           xcont=ycont=j;
207         }
208         else
209         {
210           if (bound.x0>a[j].box.x0)
211           {
212             bound.x0=a[j].box.x0;
213             if (bound.x1<a[j].box.x1)
214             {
215               bound.x1=a[j].box.x1;
216               xcont=j;
217             }
218             else
219               xcont=-1;
220           }
221           else if (bound.x1<a[j].box.x1)
222           {
223             bound.x1=a[j].box.x1;
224             xcont=-1;
225           }
226
227           if (bound.y0>a[j].box.y0)
228           {
229             bound.y0=a[j].box.y0;
230             if (bound.y1<a[j].box.y1)
231             {
232               bound.y1=a[j].box.y1;
233               ycont=j;
234             }
235             else
236               ycont=-1;
237           }
238           else if (bound.y1<a[j].box.y1)
239           {
240             bound.y1=a[j].box.y1;
241             ycont=-1;
242           }
243         }
244         j++;
245       }
246     }
247
248   }
249
250   if (xcont!=-1)
251     xcont=a[xcont].i;
252   if (ycont!=-1)
253     ycont=a[ycont].i;
254
255   /* --- Now to do the job properly --- *
256    *
257    * Aligning is easy.  Just find the align position and Bob's your uncle.
258    * Distributing the icons is more difficult.  I'll come to that when
259    * it's a better time.
260    */
261
262   /* --- First do horizontal movement --- */
263
264   if (dbox_selecticon(align__dbox,glass_AHALIGN,dbox_READSTATE))
265   {
266
267     /* --- Right.  Just aligning to do.  This is really easy --- */
268
269     if (dbox_selecticon(align__dbox,glass_AHLEFT,dbox_READSTATE))
270     {
271       for (i=0;i<num;i++)
272       {
273         a[i].box.x1+=bound.x0-a[i].box.x0;
274         a[i].box.x0=bound.x0;
275       }
276     }
277     else if (dbox_selecticon(align__dbox,glass_AHRIGHT,dbox_READSTATE))
278     {
279       for (i=0;i<num;i++)
280       {
281         a[i].box.x0+=bound.x1-a[i].box.x1;
282         a[i].box.x1=bound.x1;
283       }
284     }
285     else
286     {
287       int centre;
288       int icwidth;
289
290       /* --- Centring is complicated by the two bounding boxes --- */
291
292       if (dbox_selecticon(align__dbox,glass_AHBOUND,dbox_READSTATE))
293         centre=(bound.x1+bound.x0)/2;
294       else
295       {
296         centre=w->def->desc.w.scx+
297                (w->def->desc.w.box.x1-w->def->desc.w.box.x0)/2;
298       }
299
300       for (i=0;i<num;i++)
301       {
302         icwidth=a[i].box.x1-a[i].box.x0;
303         a[i].box.x0=centre-icwidth/2;
304         a[i].box.x1=centre+icwidth/2;
305       }
306     }
307   }
308   else if (dbox_selecticon(align__dbox,glass_AHDISTRIB,dbox_READSTATE))
309   {
310
311     /* --- Hmm... right.  Got to distribute these --- *
312      *
313      * First of all, we've got to put them in some sort of order.
314      */
315
316     if (dbox_selecticon(align__dbox,glass_AHLEFT,dbox_READSTATE))
317       align__sortOrder=align__MIN;
318     else if (dbox_selecticon(align__dbox,glass_AHCENTRE,dbox_READSTATE) ||
319              dbox_selecticon(align__dbox,glass_AHWIDTH,dbox_READSTATE))
320       align__sortOrder=align__CENTRE;
321     else
322       align__sortOrder=align__MAX;
323
324     qsort(a,w->selno,sizeof(align__iconstr),align__horizCompare);
325
326     if (dbox_selecticon(align__dbox,glass_AHLEFT,dbox_READSTATE))
327     {
328       int space=a[num-1].box.x0-a[0].box.x0;
329       int anchor=a[0].box.x0;
330       int thisBit;
331
332       for (i=0;i<num;i++)
333       {
334         thisBit=anchor + ( (space*i)/(num-1) & ~(wimpt_dx()-1) );
335         a[i].box.x1+=thisBit-a[i].box.x0;
336         a[i].box.x0=thisBit;
337       }
338     }
339     else if (dbox_selecticon(align__dbox,glass_AHRIGHT,dbox_READSTATE))
340     {
341       int space=a[num-1].box.x1-a[0].box.x1;
342       int anchor=a[0].box.x1;
343       int thisBit;
344
345       for (i=0;i<num;i++)
346       {
347         thisBit=anchor + ( (space*i)/(num-1) & ~(wimpt_dx()-1) );
348         a[i].box.x0+=thisBit-a[i].box.x1;
349         a[i].box.x1=thisBit;
350       }
351     }
352     else if (dbox_selecticon(align__dbox,glass_AHCENTRE,dbox_READSTATE))
353     {
354       int space=(a[num-1].box.x1+a[num-1].box.x0)/2-
355                 (a[0].box.x1+a[0].box.x0)/2;
356       int anchor=(a[0].box.x1+a[0].box.x0)/2;
357       int icwidth;
358       int thisBit;
359
360       for (i=0;i<num;i++)
361       {
362         thisBit=anchor + ( (space*i)/(num-1) & ~(wimpt_dx()-1) );
363         icwidth=a[i].box.x1-a[i].box.x0;
364         a[i].box.x0=thisBit-icwidth/2;
365         a[i].box.x1=thisBit+icwidth/2;
366       }
367     }
368     else if (dbox_selecticon(align__dbox,glass_AHBOUND,dbox_READSTATE))
369     {
370       int space=bound.x1-bound.x0-width;
371       int icwidth;
372       int thisBit;
373       int anchor=bound.x0; /* This anchor moves, unlike the last lot */
374
375       for (i=0;i<num;i++)
376       {
377         icwidth=a[i].box.x1-a[i].box.x0;
378         thisBit=anchor + ( (space*i)/(num-1) & ~(wimpt_dx()-1) );
379         a[i].box.x0=thisBit;
380         a[i].box.x1=thisBit+icwidth;
381         anchor+=icwidth;
382       }
383     }
384     else if (dbox_selecticon(align__dbox,glass_AHVISAREA,dbox_READSTATE))
385     {
386       int space=w->def->desc.w.box.x1-w->def->desc.w.box.x0-width;
387       int icwidth;
388       int thisBit;
389       int anchor=w->def->desc.w.scx; /* This anchor also moves */
390
391       for (i=0;i<num;i++)
392       {
393         icwidth=a[i].box.x1-a[i].box.x0;
394         thisBit=anchor + ( ( space*(i+1) )/(num+1) & ~(wimpt_dx()-1) );
395         a[i].box.x0=thisBit;
396         a[i].box.x1=thisBit+icwidth;
397         anchor+=icwidth;
398       }
399     }
400     else if (xcont!=-1)
401     {
402       int space=2*(bound.x1-bound.x0)-width;
403       int icwidth;
404       int thisBit;
405       int anchor=bound.x0; /* This anchor also moves */
406       int done=1;
407
408       for (i=0;i<num;i++)
409       {
410         if (a[i].i==xcont)
411           continue; /* Don't move the container icon at all */
412         icwidth=a[i].box.x1-a[i].box.x0;
413         thisBit=anchor + ( (space*done)/num & ~(wimpt_dx()-1) );
414         a[i].box.x0=thisBit;
415         a[i].box.x1=thisBit+icwidth;
416         anchor+=icwidth;
417         done++;
418       }
419     }
420     else
421     {
422       note(msgs_lookup("alNOHC"));
423     }
424   }
425
426   /* --- Now do the vertical bit (just a case'n'paste of above) --- */
427
428   if (dbox_selecticon(align__dbox,glass_AVALIGN,dbox_READSTATE))
429   {
430
431     /* --- Right.  Just aligning to do.  This is really easy --- */
432
433     if (dbox_selecticon(align__dbox,glass_AVBOTTOM,dbox_READSTATE))
434     {
435       for (i=0;i<num;i++)
436       {
437         a[i].box.y1+=bound.y0-a[i].box.y0;
438         a[i].box.y0=bound.y0;
439       }
440     }
441     else if (dbox_selecticon(align__dbox,glass_AVTOP,dbox_READSTATE))
442     {
443       for (i=0;i<num;i++)
444       {
445         a[i].box.y0+=bound.y1-a[i].box.y1;
446         a[i].box.y1=bound.y1;
447       }
448     }
449     else
450     {
451       int centre;
452       int icheight;
453
454       /* --- Centring is complicated by the two bounding boxes --- */
455
456       if (dbox_selecticon(align__dbox,glass_AVBOUND,dbox_READSTATE))
457         centre=(bound.y1+bound.y0)/2;
458       else
459       {
460         centre=w->def->desc.w.scy-
461                (w->def->desc.w.box.y1-w->def->desc.w.box.y0)/2;
462       }
463
464       for (i=0;i<num;i++)
465       {
466         icheight=a[i].box.y1-a[i].box.y0;
467         a[i].box.y0=centre-icheight/2;
468         a[i].box.y1=centre+icheight/2;
469       }
470     }
471   }
472   else if (dbox_selecticon(align__dbox,glass_AVDISTRIB,dbox_READSTATE))
473   {
474
475     /* --- Hmm... right.  Got to distribute these --- *
476      *
477      * First of all, we've got to put them in some sort of order.
478      */
479
480     if (dbox_selecticon(align__dbox,glass_AVBOTTOM,dbox_READSTATE))
481       align__sortOrder=align__MIN;
482     else if (dbox_selecticon(align__dbox,glass_AVCENTRE,dbox_READSTATE) ||
483              dbox_selecticon(align__dbox,glass_AVHEIGHT,dbox_READSTATE))
484       align__sortOrder=align__CENTRE;
485     else
486       align__sortOrder=align__MAX;
487
488     qsort(a,w->selno,sizeof(align__iconstr),align__vertCompare);
489
490     if (dbox_selecticon(align__dbox,glass_AVBOTTOM,dbox_READSTATE))
491     {
492       int space=a[num-1].box.y0-a[0].box.y0;
493       int anchor=a[0].box.y0;
494       int thisBit;
495
496       for (i=0;i<num;i++)
497       {
498         thisBit=anchor + ( (space*i)/(num-1) & ~(wimpt_dy()-1) );
499         a[i].box.y1+=thisBit-a[i].box.y0;
500         a[i].box.y0=thisBit;
501       }
502     }
503     else if (dbox_selecticon(align__dbox,glass_AVTOP,dbox_READSTATE))
504     {
505       int space=a[num-1].box.y1-a[0].box.y1;
506       int anchor=a[0].box.y1;
507       int thisBit;
508
509       for (i=0;i<num;i++)
510       {
511         thisBit=anchor + ( (space*i)/(num-1) & ~(wimpt_dy()-1) );
512         a[i].box.y0+=thisBit-a[i].box.y1;
513         a[i].box.y1=thisBit;
514       }
515     }
516     else if (dbox_selecticon(align__dbox,glass_AVCENTRE,dbox_READSTATE))
517     {
518       int space=(a[num-1].box.y1+a[num-1].box.y0)/2-
519                 (a[0].box.y1+a[0].box.y0)/2;
520       int anchor=(a[0].box.y1+a[0].box.y0)/2;
521       int icheight;
522       int thisBit;
523
524       for (i=0;i<num;i++)
525       {
526         thisBit=anchor + ( (space*i)/(num-1) & ~(wimpt_dy()-1) );
527         icheight=a[i].box.y1-a[i].box.y0;
528         a[i].box.y0=thisBit-icheight/2;
529         a[i].box.y1=thisBit+icheight/2;
530       }
531     }
532     else if (dbox_selecticon(align__dbox,glass_AVBOUND,dbox_READSTATE))
533     {
534       int space=bound.y1-bound.y0-height;
535       int icheight;
536       int thisBit;
537       int anchor=bound.y0; /* This anchor moves, unlike the last lot */
538
539       for (i=0;i<num;i++)
540       {
541         icheight=a[i].box.y1-a[i].box.y0;
542         thisBit=anchor + ( (space*i)/(num-1) & ~(wimpt_dy()-1) );
543         a[i].box.y0=thisBit;
544         a[i].box.y1=thisBit+icheight;
545         anchor+=icheight;
546       }
547     }
548     else if (dbox_selecticon(align__dbox,glass_AVVISAREA,dbox_READSTATE))
549     {
550       int space=w->def->desc.w.box.y1-w->def->desc.w.box.y0;
551       int icheight;
552       int thisBit;
553       int anchor=w->def->desc.w.scy-space; /* This anchor also moves */
554       space-=height;
555
556       for (i=0;i<num;i++)
557       {
558         icheight=a[i].box.y1-a[i].box.y0;
559         thisBit=anchor + ( ( space*(i+1) )/(num+1) & ~(wimpt_dy()-1) );
560         a[i].box.y0=thisBit;
561         a[i].box.y1=thisBit+icheight;
562         anchor+=icheight;
563       }
564     }
565     else if (ycont!=-1)
566     {
567       int space=2*(bound.y1-bound.y0)-height;
568       int icheight;
569       int thisBit;
570       int anchor=bound.y0; /* This anchor also moves */
571       int done=1;
572
573       for (i=0;i<num;i++)
574       {
575         if (a[i].i==ycont)
576           continue; /* Don't move the container icon at all */
577         icheight=a[i].box.y1-a[i].box.y0;
578         thisBit=anchor + ( (space*done)/num & ~(wimpt_dy()-1) );
579         a[i].box.y0=thisBit;
580         a[i].box.y1=thisBit+icheight;
581         anchor+=icheight;
582         done++;
583       }
584     }
585     else
586     {
587       note(msgs_lookup("alNOVC"));
588     }
589   }
590
591   tfile_markAsAltered(w->t);
592
593   for (i=0;i<w->selno;i++)
594     window_setBox(w,a[i].i,&a[i].box);
595
596   mem_free(a);
597 }
598
599 /*----- Event handlers ----------------------------------------------------*/
600
601 /*
602  * void align__dboxHandler(dbox d,dbox_field f,void *handle)
603  *
604  * Use
605  *  Handles events for the Alignment dialogue box.
606  *
607  * Parameters
608  *  dbox d == the dbox handle (align__dbox)
609  *  dbox_field f == what happened (usually a mouse click)
610  *  void *handle == a pointer (ignored)
611  */
612
613 static void align__dboxHandler(dbox d,dbox_field f,void *handle)
614 {
615   BOOL shadeBox;
616   unused(handle);
617   switch (f)
618   {
619     case dbox_CLOSE:
620       dbox_delete(d);
621       align__dbox=0;
622       break;
623     case glass_AOK:
624       dbox_clickicon(d,f);
625       align__doAlign();
626       if (!dbox_wasAdjustClick())
627         dbox_hide(d);
628       dbox_unclick();
629       if (!dbox_wasAdjustClick())
630       {
631         dbox_delete(d);
632         align__dbox=0;
633       }
634       break;
635     case glass_ACANCEL:
636       dbox_clickicon(d,f);
637       dbox_hide(d);
638       dbox_unclick();
639       dbox_delete(d);
640       align__dbox=0;
641       break;
642     case glass_AHNONE:
643       dbox_clickicon(d,f);
644       dbox_shadeicon(d,glass_AHLEFT,TRUE);
645       dbox_shadeicon(d,glass_AHRIGHT,TRUE);
646       dbox_shadeicon(d,glass_AHCENTRE,TRUE);
647       dbox_shadeicon(d,glass_AHWIDTH,TRUE);
648       dbox_shadeicon(d,glass_AHBOUND,TRUE);
649       dbox_shadeicon(d,glass_AHVISAREA,TRUE);
650       dbox_shadeicon(d,glass_AHCONTAIN,TRUE);
651       dbox_unclick();
652       break;
653     case glass_AHALIGN:
654       dbox_clickicon(d,f);
655       dbox_shadeicon(d,glass_AHLEFT,FALSE);
656       dbox_shadeicon(d,glass_AHRIGHT,FALSE);
657       dbox_shadeicon(d,glass_AHCENTRE,FALSE);
658       dbox_shadeicon(d,glass_AHWIDTH,TRUE);
659       if (dbox_selecticon(d,glass_AHWIDTH,dbox_READSTATE))
660       {
661         dbox_selecticon(d,glass_AHWIDTH,FALSE);
662         dbox_selecticon(d,glass_AHCENTRE,TRUE);
663       }
664       shadeBox=!dbox_selecticon(d,glass_AHCENTRE,dbox_READSTATE);
665       dbox_shadeicon(d,glass_AHBOUND,shadeBox);
666       dbox_shadeicon(d,glass_AHVISAREA,shadeBox);
667       dbox_shadeicon(d,glass_AHCONTAIN,TRUE);
668       if (dbox_selecticon(d,glass_AHCONTAIN,dbox_READSTATE))
669       {
670         dbox_selecticon(d,glass_AHCONTAIN,FALSE);
671         dbox_selecticon(d,glass_AHBOUND,TRUE);
672       }
673       dbox_unclick();
674       break;
675     case glass_AHDISTRIB:
676       dbox_clickicon(d,f);
677       dbox_shadeicon(d,glass_AHLEFT,FALSE);
678       dbox_shadeicon(d,glass_AHRIGHT,FALSE);
679       dbox_shadeicon(d,glass_AHCENTRE,FALSE);
680       dbox_shadeicon(d,glass_AHWIDTH,FALSE);
681       shadeBox=!dbox_selecticon(d,glass_AHWIDTH,dbox_READSTATE);
682       dbox_shadeicon(d,glass_AHBOUND,shadeBox);
683       dbox_shadeicon(d,glass_AHVISAREA,shadeBox);
684       dbox_shadeicon(d,glass_AHCONTAIN,shadeBox);
685       dbox_unclick();
686       break;
687     case glass_AVNONE:
688       dbox_clickicon(d,f);
689       dbox_shadeicon(d,glass_AVTOP,TRUE);
690       dbox_shadeicon(d,glass_AVBOTTOM,TRUE);
691       dbox_shadeicon(d,glass_AVCENTRE,TRUE);
692       dbox_shadeicon(d,glass_AVHEIGHT,TRUE);
693       dbox_shadeicon(d,glass_AVBOUND,TRUE);
694       dbox_shadeicon(d,glass_AVVISAREA,TRUE);
695       dbox_shadeicon(d,glass_AVCONTAIN,TRUE);
696       dbox_unclick();
697       break;
698     case glass_AVALIGN:
699       dbox_clickicon(d,f);
700       dbox_shadeicon(d,glass_AVTOP,FALSE);
701       dbox_shadeicon(d,glass_AVBOTTOM,FALSE);
702       dbox_shadeicon(d,glass_AVCENTRE,FALSE);
703       dbox_shadeicon(d,glass_AVHEIGHT,TRUE);
704       if (dbox_selecticon(d,glass_AVHEIGHT,dbox_READSTATE))
705       {
706         dbox_selecticon(d,glass_AVHEIGHT,FALSE);
707         dbox_selecticon(d,glass_AVCENTRE,TRUE);
708       }
709       shadeBox=!dbox_selecticon(d,glass_AVCENTRE,dbox_READSTATE);
710       dbox_shadeicon(d,glass_AVBOUND,shadeBox);
711       dbox_shadeicon(d,glass_AVVISAREA,shadeBox);
712       dbox_shadeicon(d,glass_AVCONTAIN,TRUE);
713       if (dbox_selecticon(d,glass_AVCONTAIN,dbox_READSTATE))
714       {
715         dbox_selecticon(d,glass_AVCONTAIN,FALSE);
716         dbox_selecticon(d,glass_AVBOUND,TRUE);
717       }
718       dbox_unclick();
719       break;
720     case glass_AVDISTRIB:
721       dbox_clickicon(d,f);
722       dbox_shadeicon(d,glass_AVTOP,FALSE);
723       dbox_shadeicon(d,glass_AVBOTTOM,FALSE);
724       dbox_shadeicon(d,glass_AVCENTRE,FALSE);
725       dbox_shadeicon(d,glass_AVHEIGHT,FALSE);
726       shadeBox=!dbox_selecticon(d,glass_AVHEIGHT,dbox_READSTATE);
727       dbox_shadeicon(d,glass_AVBOUND,shadeBox);
728       dbox_shadeicon(d,glass_AVVISAREA,shadeBox);
729       dbox_shadeicon(d,glass_AVCONTAIN,shadeBox);
730       dbox_unclick();
731       break;
732     case glass_AHLEFT:
733     case glass_AHRIGHT:
734     case glass_AHCENTRE:
735     case glass_AHWIDTH:
736     case glass_AHBOUND:
737     case glass_AHVISAREA:
738     case glass_AHCONTAIN:
739       dbox_clickicon(d,f);
740       if (dbox_selecticon(d,glass_AHALIGN,dbox_READSTATE))
741         shadeBox=!dbox_selecticon(d,glass_AHCENTRE,dbox_READSTATE);
742       else
743         shadeBox=!dbox_selecticon(d,glass_AHWIDTH,dbox_READSTATE);
744       dbox_shadeicon(d,glass_AHBOUND,shadeBox);
745       dbox_shadeicon(d,glass_AHVISAREA,shadeBox);
746       dbox_shadeicon(d,
747                      glass_AHCONTAIN,
748                      !dbox_selecticon(d,glass_AHWIDTH,dbox_READSTATE));
749       dbox_unclick();
750       break;
751     case glass_AVTOP:
752     case glass_AVBOTTOM:
753     case glass_AVCENTRE:
754     case glass_AVHEIGHT:
755     case glass_AVBOUND:
756     case glass_AVVISAREA:
757     case glass_AVCONTAIN:
758       dbox_clickicon(d,f);
759       if (dbox_selecticon(d,glass_AVALIGN,dbox_READSTATE))
760         shadeBox=!dbox_selecticon(d,glass_AVCENTRE,dbox_READSTATE);
761       else
762         shadeBox=!dbox_selecticon(d,glass_AVHEIGHT,dbox_READSTATE);
763       dbox_shadeicon(d,glass_AVBOUND,shadeBox);
764       dbox_shadeicon(d,glass_AVVISAREA,shadeBox);
765       dbox_shadeicon(d,
766                      glass_AVCONTAIN,
767                      !dbox_selecticon(d,glass_AVHEIGHT,dbox_READSTATE));
768       dbox_unclick();
769       break;
770   }
771 }
772
773 /*----- External routines -------------------------------------------------*/
774
775 /*
776  * void align(void)
777  *
778  * Use
779  *  Opens the align dialogue box.  There can only be one selection, ergo
780  *  there can only be one align box.
781  */
782
783 void align(void)
784 {
785   if (!align__dbox)
786   {
787     align__dbox=dbox_create("align");
788     if (!align__dbox)
789       return;
790
791     dbox_shadeicon(align__dbox,glass_AHLEFT,TRUE);
792     dbox_shadeicon(align__dbox,glass_AHRIGHT,TRUE);
793     dbox_shadeicon(align__dbox,glass_AHCENTRE,TRUE);
794     dbox_shadeicon(align__dbox,glass_AHWIDTH,TRUE);
795     dbox_shadeicon(align__dbox,glass_AHBOUND,TRUE);
796     dbox_shadeicon(align__dbox,glass_AHVISAREA,TRUE);
797     dbox_shadeicon(align__dbox,glass_AHCONTAIN,TRUE);
798
799     dbox_shadeicon(align__dbox,glass_AVTOP,TRUE);
800     dbox_shadeicon(align__dbox,glass_AVBOTTOM,TRUE);
801     dbox_shadeicon(align__dbox,glass_AVCENTRE,TRUE);
802     dbox_shadeicon(align__dbox,glass_AVHEIGHT,TRUE);
803     dbox_shadeicon(align__dbox,glass_AVBOUND,TRUE);
804     dbox_shadeicon(align__dbox,glass_AVVISAREA,TRUE);
805     dbox_shadeicon(align__dbox,glass_AVCONTAIN,TRUE);
806
807     dbox_eventHandler(align__dbox,align__dboxHandler,0);
808   }
809   dbox_display(align__dbox,dbox_STATIC_LASTPOS);
810 }