chiark / gitweb /
debian/changelog: start -4~
[vtwm.git] / iconmgr.c
1 /*
2  * Copyright 1989 Massachusetts Institute of Technology
3  *
4  * Permission to use, copy, modify, and distribute this software and its
5  * documentation for any purpose and without fee is hereby granted, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of M.I.T. not be used in advertising
9  * or publicity pertaining to distribution of the software without specific,
10  * written prior permission.  M.I.T. makes no representations about the
11  * suitability of this software for any purpose.  It is provided "as is"
12  * without express or implied warranty.
13  *
14  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
16  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
19  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21
22 /***********************************************************************
23  *
24  * $XConsortium: iconmgr.c,v 1.48 91/09/10 15:27:07 dave Exp $
25  *
26  * Icon Manager routines
27  *
28  * 09-Mar-89 Tom LaStrange              File Created
29  *
30  ***********************************************************************/
31
32 #include <stdio.h>
33 #include "twm.h"
34 #include "util.h"
35 #include "menus.h"
36 #include "desktop.h"
37 #include "parse.h"
38 #include "screen.h"
39 #include "resize.h"
40 #include "add_window.h"
41 #include <X11/Xos.h>
42 #include <X11/Xmu/CharSet.h>
43
44 #ifdef macII
45 int strcmp(); /* missing from string.h in AUX 2.0 */
46 #endif
47
48 /* djhjr - 5/2/98 */
49 static int ComputeIconMgrWindowHeight();
50
51 /* see AddIconManager() - djhjr - 5/5/98
52 int iconmgr_textx = siconify_width+11;
53 */
54 int iconmgr_iconx = 0, iconmgr_textx = 0;
55
56 WList *Active = NULL;
57 WList *DownIconManager = NULL;
58
59 /* was an external file - djhjr - 10/30/02 */
60 #define siconify_width 11
61 #define siconify_height 11
62 /*
63 static unsigned char siconify_bits[] = {
64    0xff, 0x07, 0x01, 0x04, 0x0d, 0x05, 0x9d, 0x05, 0xb9, 0x04, 0x51, 0x04,
65    0xe9, 0x04, 0xcd, 0x05, 0x85, 0x05, 0x01, 0x04, 0xff, 0x07};
66 */
67
68 int iconifybox_width = siconify_width;
69 int iconifybox_height = siconify_height;
70
71 /* djhjr - 10/30/02 */
72 void SetIconMgrPixmap(filename)
73 char *filename;
74 {
75         Scr->iconMgrIconName = filename;
76 }
77
78 /***********************************************************************
79  *
80  *  Procedure:
81  *      CreateIconManagers - creat all the icon manager windows
82  *              for this screen.
83  *
84  *  Returned Value:
85  *      none
86  *
87  *  Inputs:
88  *      none
89  *
90  ***********************************************************************
91  */
92
93 struct Colori {
94     Pixel color;
95     Pixmap pix;
96     struct Colori *next;
97 };
98
99 #if 0
100 Pixmap Create3DIconManagerIcon (cp)
101 ColorPair cp;
102 {
103     unsigned int w, h;
104     struct Colori *col;
105     static struct Colori *colori = NULL;
106
107     w = (unsigned int) siconify_width;
108     h = (unsigned int) siconify_height;
109
110     for (col = colori; col; col = col->next) {
111         if (col->color == cp.back) break;
112     }
113     if (col != NULL) return (col->pix);
114     col = (struct Colori*) malloc (sizeof (struct Colori));
115     col->color = cp.back;
116     col->pix   = XCreatePixmap (dpy, Scr->Root, w, h, Scr->d_depth);
117 #ifdef ORIGINAL_ICONMGRPIXMAP
118     Draw3DBorder (col->pix, 0, 0, w, h, 4, cp, off, True, False);
119 #else
120     Draw3DBorder (col->pix, 0, 0, w, h, 1, cp, off, True, False);
121 #ifdef DO_DOT
122     Draw3DBorder (col->pix, (w / 2) - 1, (h / 2) - 1, 3, 3, 1, cp, off, True, False);
123 #endif
124 #endif
125     col->next = colori;
126     colori = col;
127
128     return (colori->pix);
129 }
130 #endif
131
132 void CreateIconManagers()
133 {
134         XClassHint *class; /* djhjr - 2/28/99 */
135     IconMgr *p;
136     int mask;
137     char str[100];
138     char str1[100];
139     Pixel background;
140     char *icon_name;
141
142     if (Scr->NoIconManagers)
143         return;
144
145 /* djhjr - 10/30/02
146     if (Scr->siconifyPm == None)
147     {
148         Scr->siconifyPm->pixmap = XCreatePixmapFromBitmapData(dpy, Scr->Root,
149             (char *)siconify_bits, siconify_width, siconify_height, 1, 0, 1);
150     }
151 */
152
153     for (p = &Scr->iconmgr; p != NULL; p = p->next)
154     {
155         mask = XParseGeometry(p->geometry, &JunkX, &JunkY,
156                               (unsigned int *) &p->width, (unsigned int *)&p->height);
157
158         /* djhjr - 3/1/99 */
159         if (p->width > Scr->MyDisplayWidth) p->width = Scr->MyDisplayWidth;
160
161         if (mask & XNegative)
162 /* djhjr - 4/19/96
163             JunkX = Scr->MyDisplayWidth - p->width - 
164               (2 * Scr->BorderWidth) + JunkX;
165 */
166 /* djhjr - 8/11/98
167             JunkX += Scr->MyDisplayWidth - p->width - 
168               (2 * (Scr->ThreeDBorderWidth ? Scr->ThreeDBorderWidth : Scr->BorderWidth));
169 */
170             JunkX += Scr->MyDisplayWidth - p->width - 
171               (2 * Scr->BorderWidth);
172
173         if (mask & YNegative)
174 /* djhjr - 4/19/96
175             JunkY = Scr->MyDisplayHeight - p->height -
176               (2 * Scr->BorderWidth) + JunkY;
177 */
178 /* djhjr - 8/11/98
179             JunkY += Scr->MyDisplayHeight - p->height -
180               (2 * (Scr->ThreeDBorderWidth ? Scr->ThreeDBorderWidth : Scr->BorderWidth));
181 */
182             JunkY += Scr->MyDisplayHeight - p->height -
183               (2 * Scr->BorderWidth);
184
185         /* djhjr - 9/10/98 */
186         if (p->width  < 1) p->width  = 1;
187         if (p->height < 1) p->height = 1;
188
189         background = Scr->IconManagerC.back;
190         GetColorFromList(Scr->IconManagerBL, p->name, (XClassHint *)NULL,
191                          &background);
192
193         p->w = XCreateSimpleWindow(dpy, Scr->Root,
194             JunkX, JunkY, p->width, p->height,
195             
196             0,  /* was '1' - submitted by Rolf Neugebauer */
197
198             Scr->Black, background);
199
200         sprintf(str, "%s Icon Manager", p->name);
201         sprintf(str1, "%s Icons", p->name);
202         if (p->icon_name)
203             icon_name = p->icon_name;
204         else
205             icon_name = str1;
206
207         /* djhjr - 5/19/98 */
208         /* was setting for the TwmWindow after AddWindow() - djhjr - 2/28/99 */
209         class = XAllocClassHint();
210         class->res_name = strdup(str);
211         class->res_class = strdup(VTWM_ICONMGR_CLASS);
212         XSetClassHint(dpy, p->w, class);
213
214         XSetStandardProperties(dpy, p->w, str, icon_name, None, NULL, 0, NULL);
215
216         p->twm_win = AddWindow(p->w, TRUE, p);
217
218         SetMapStateProp (p->twm_win, WithdrawnState);
219     }
220     for (p = &Scr->iconmgr; p != NULL; p = p->next)
221     {
222         GrabButtons(p->twm_win);
223         GrabKeys(p->twm_win);
224     }
225 }
226
227 /***********************************************************************
228  *
229  *  Procedure:
230  *      AllocateIconManager - allocate a new icon manager
231  *
232  *  Inputs:
233  *      name    - the name of this icon manager
234  *      icon_name - the name of the associated icon
235  *      geom    - a geometry string to eventually parse
236  *      columns - the number of columns this icon manager has
237  *
238  ***********************************************************************
239  */
240
241 IconMgr *AllocateIconManager(name, icon_name, geom, columns)
242     char *name;
243     char *geom;
244     char *icon_name;
245     int columns;
246 {
247     IconMgr *p;
248
249 #ifdef DEBUG_ICONMGR
250     fprintf(stderr, "AllocateIconManager\n");
251     fprintf(stderr, "  name=\"%s\" icon_name=\"%s\", geom=\"%s\", col=%d\n",
252         name, icon_name, geom, columns);
253 #endif
254
255     if (Scr->NoIconManagers)
256         return NULL;
257
258     p = (IconMgr *)malloc(sizeof(IconMgr));
259     p->name = name;
260     p->icon_name = icon_name;
261     p->geometry = geom;
262     p->columns = columns;
263     p->first = NULL;
264     p->last = NULL;
265     p->active = NULL;
266     p->scr = Scr;
267     p->count = 0;
268     p->x = 0;
269     p->y = 0;
270     p->width = 150;
271     p->height = 10;
272
273     Scr->iconmgr.lasti->next = p;
274     p->prev = Scr->iconmgr.lasti;
275     Scr->iconmgr.lasti = p;
276     p->next = NULL;
277
278     return(p);
279 }
280
281 /***********************************************************************
282  *
283  *  Procedure:
284  *      MoveIconManager - move the pointer around in an icon manager
285  *
286  *  Inputs:
287  *      dir     - one of the following:
288  *                      F_FORWICONMGR   - forward in the window list
289  *                      F_BACKICONMGR   - backward in the window list
290  *                      F_UPICONMGR     - up one row
291  *                      F_DOWNICONMGR   - down one row
292  *                      F_LEFTICONMGR   - left one column
293  *                      F_RIGHTICONMGR  - right one column
294  *
295  *  Special Considerations:
296  *      none
297  *
298  ***********************************************************************
299  */
300
301 void MoveIconManager(dir)
302     int dir;
303 {
304     IconMgr *ip;
305     WList *tmp = NULL;
306     int cur_row, cur_col, new_row, new_col;
307     int row_inc, col_inc;
308     int got_it;
309
310     if (!Active) return;
311
312     cur_row = Active->row;
313     cur_col = Active->col;
314     ip = Active->iconmgr;
315
316     row_inc = 0;
317     col_inc = 0;
318     got_it = FALSE;
319
320     switch (dir)
321     {
322         case F_FORWICONMGR:
323             if ((tmp = Active->next) == NULL)
324                 tmp = ip->first;
325             got_it = TRUE;
326             break;
327
328         case F_BACKICONMGR:
329             if ((tmp = Active->prev) == NULL)
330                 tmp = ip->last;
331             got_it = TRUE;
332             break;
333
334         case F_UPICONMGR:
335             row_inc = -1;
336             break;
337
338         case F_DOWNICONMGR:
339             row_inc = 1;
340             break;
341
342         case F_LEFTICONMGR:
343             col_inc = -1;
344             break;
345
346         case F_RIGHTICONMGR:
347             col_inc = 1;
348             break;
349     }
350
351     /* If got_it is FALSE ast this point then we got a left, right,
352      * up, or down, command.  We will enter this loop until we find
353      * a window to warp to.
354      */
355     new_row = cur_row;
356     new_col = cur_col;
357
358     while (!got_it)
359     {
360         new_row += row_inc;
361         new_col += col_inc;
362         if (new_row < 0)
363             new_row = ip->cur_rows - 1;
364         if (new_col < 0)
365             new_col = ip->cur_columns - 1;
366         if (new_row >= ip->cur_rows)
367             new_row = 0;
368         if (new_col >= ip->cur_columns)
369             new_col = 0;
370             
371         /* Now let's go through the list to see if there is an entry with this
372          * new position
373          */
374         for (tmp = ip->first; tmp != NULL; tmp = tmp->next)
375         {
376             if (tmp->row == new_row && tmp->col == new_col)
377             {
378                 got_it = TRUE;
379                 break;
380             }
381         }
382     }
383
384     if (!got_it)
385     {
386         fprintf (stderr, 
387                  "%s:  unable to find window (%d, %d) in icon manager\n", 
388                  ProgramName, new_row, new_col);
389         return;
390     }
391
392     if (tmp == NULL)
393       return;
394
395     /* raise the frame so the icon manager is visible */
396     if (ip->twm_win->mapped) {
397         XRaiseWindow(dpy, ip->twm_win->frame);
398
399 /* djhjr - 5/30/00
400         RaiseStickyAbove();
401         RaiseAutoPan();
402
403         XWarpPointer(dpy, None, tmp->icon, 0,0,0,0, 5, 5);
404 */
405         WarpInIconMgr(tmp, ip->twm_win);
406     } else {
407 /* djhjr - 5/30/00
408         if (tmp->twm->title_height) {
409             int tbx = Scr->TBInfo.titlex;
410             int x = tmp->twm->highlightx;
411             XWarpPointer (dpy, None, tmp->twm->title_w, 0, 0, 0, 0,
412                           tbx + (x - tbx) / 2,
413                           Scr->TitleHeight / 4);
414         } else {
415             XWarpPointer (dpy, None, tmp->twm->w, 0, 0, 0, 0, 5, 5);
416         }
417 */
418         RaiseStickyAbove(); /* DSE */
419         RaiseAutoPan();
420
421         WarpToWindow(tmp->twm);
422     }
423 }
424
425 /***********************************************************************
426  *
427  *  Procedure:
428  *      JumpIconManager - jump from one icon manager to another,
429  *              possibly even on another screen
430  *
431  *  Inputs:
432  *      dir     - one of the following:
433  *                      F_NEXTICONMGR   - go to the next icon manager 
434  *                      F_PREVICONMGR   - go to the previous one
435  *
436  ***********************************************************************
437  */
438
439 void JumpIconManager(dir)
440     register int dir;
441 {
442     IconMgr *ip, *tmp_ip = NULL;
443     int got_it = FALSE;
444     ScreenInfo *sp;
445     int screen;
446
447     if (!Active) return;
448
449
450 #define ITER(i) (dir == F_NEXTICONMGR ? (i)->next : (i)->prev)
451 #define IPOFSP(sp) (dir == F_NEXTICONMGR ? &(sp->iconmgr) : sp->iconmgr.lasti)
452 #define TEST(ip) if ((ip)->count != 0 && (ip)->twm_win->mapped) \
453                  { got_it = TRUE; break; }
454
455     ip = Active->iconmgr;
456     for (tmp_ip = ITER(ip); tmp_ip; tmp_ip = ITER(tmp_ip)) {
457         TEST (tmp_ip);
458     }
459
460     if (!got_it) {
461         int origscreen = ip->scr->screen;
462         int inc = (dir == F_NEXTICONMGR ? 1 : -1);
463
464         for (screen = origscreen + inc; ; screen += inc) {
465             if (screen >= NumScreens)
466               screen = 0;
467             else if (screen < 0)
468               screen = NumScreens - 1;
469
470             sp = ScreenList[screen];
471             if (sp) {
472                 for (tmp_ip = IPOFSP (sp); tmp_ip; tmp_ip = ITER(tmp_ip)) {
473                     TEST (tmp_ip);
474                 }
475             }
476             if (got_it || screen == origscreen) break;
477         }
478     }
479
480 #undef ITER
481 #undef IPOFSP
482 #undef TEST
483
484     if (!got_it) {
485         DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */
486         return;
487     }
488
489     /* raise the frame so it is visible */
490     XRaiseWindow(dpy, tmp_ip->twm_win->frame);
491     
492 /* djhjr - 5/30/00
493     RaiseStickyAbove(); * DSE *
494     RaiseAutoPan();
495 */
496
497     if (tmp_ip->active)
498 /* djhjr - 5/30/00
499         XWarpPointer(dpy, None, tmp_ip->active->icon, 0,0,0,0, 5, 5);
500 */
501         WarpInIconMgr(tmp_ip->active, tmp_ip->twm_win);
502     else
503 /* djhjr - 5/30/00
504         XWarpPointer(dpy, None, tmp_ip->w, 0,0,0,0, 5, 5);
505 */
506     {
507         RaiseStickyAbove(); /* DSE */
508         RaiseAutoPan();
509
510         WarpToWindow(tmp_ip->twm_win);
511     }
512 }
513
514 /***********************************************************************
515  *
516  *  Procedure:
517  *      AddIconManager - add a window to an icon manager
518  *
519  *  Inputs:
520  *      tmp_win - the TwmWindow structure
521  *
522  ***********************************************************************
523  */
524
525 WList *AddIconManager(tmp_win)
526     TwmWindow *tmp_win;
527 {
528     WList *tmp;
529     int h;
530     unsigned long valuemask;            /* mask for create windows */
531     XSetWindowAttributes attributes;    /* attributes for create windows */
532     IconMgr *ip;
533
534     tmp_win->list = NULL;
535
536     /* djhjr - 10/2/01 */
537     if (Scr->StrictIconManager)
538     {
539         if (tmp_win->icon || (!tmp_win->iconified &&
540                 (tmp_win->wmhints &&
541                 (tmp_win->wmhints->flags & StateHint) &&
542                 tmp_win->wmhints->initial_state == IconicState)))
543             ;
544         else
545             return NULL;
546     }
547
548     if (tmp_win->iconmgr || tmp_win->transient || Scr->NoIconManagers)
549         return NULL;
550
551     if (LookInList(Scr->IconMgrNoShow, tmp_win->full_name, &tmp_win->class))
552         return NULL;
553     if (Scr->IconManagerDontShow &&
554         !LookInList(Scr->IconMgrShow, tmp_win->full_name, &tmp_win->class))
555         return NULL;
556     if ((ip = (IconMgr *)LookInList(Scr->IconMgrs, tmp_win->full_name,
557             &tmp_win->class)) == NULL)
558         ip = &Scr->iconmgr;
559
560     tmp = (WList *) malloc(sizeof(WList));
561     tmp->iconmgr = ip;
562     tmp->next = NULL;
563     tmp->active = FALSE;
564     tmp->down = FALSE;
565
566     InsertInIconManager(ip, tmp, tmp_win);
567
568     tmp->twm = tmp_win;
569
570 /* djhjr - 4/19/96
571     tmp->fore = Scr->IconManagerC.fore;
572     tmp->back = Scr->IconManagerC.back;
573 */
574     tmp->cp.fore = Scr->IconManagerC.fore;
575     tmp->cp.back = Scr->IconManagerC.back;
576
577     tmp->highlight = Scr->IconManagerHighlight;
578
579 /* djhjr - 4/19/96
580     GetColorFromList(Scr->IconManagerFL, tmp_win->full_name, &tmp_win->class,
581         &tmp->fore);
582     GetColorFromList(Scr->IconManagerBL, tmp_win->full_name, &tmp_win->class,
583         &tmp->back);
584 */
585     GetColorFromList(Scr->IconManagerFL, tmp_win->full_name, &tmp_win->class,
586         &tmp->cp.fore);
587     GetColorFromList(Scr->IconManagerBL, tmp_win->full_name, &tmp_win->class,
588         &tmp->cp.back);
589
590     GetColorFromList(Scr->IconManagerHighlightL, tmp_win->full_name,
591         &tmp_win->class, &tmp->highlight);
592
593     /* djhjr - 4/19/96 */
594         /* was 'Scr->use3Diconmanagers' - djhjr - 8/11/98 */
595 /* djhjr - 10/30/02
596     if (Scr->IconMgrBevelWidth > 0)
597 */
598     {
599         if (!Scr->BeNiceToColormap) GetShadeColors (&tmp->cp);
600 /* djhjr - 10/30/02
601         tmp->iconifypm = Create3DIconManagerIcon (tmp->cp);
602 */
603         tmp->iconifypm = GetImage(Scr->iconMgrIconName,
604                                 iconifybox_width, iconifybox_height,
605                                 0, tmp->cp);
606     }
607
608         /* djhjr - 5/2/98 */
609         h = ComputeIconMgrWindowHeight();
610
611     ip->height = h * ip->count;
612     tmp->me = ip->count;
613     tmp->x = -1;
614     tmp->y = -1;
615     
616     valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor);
617
618 /* djhjr - 4/19/96
619     attributes.background_pixel = tmp->back;
620     attributes.border_pixel = tmp->back;
621 */
622     attributes.background_pixel = tmp->cp.back;
623     attributes.border_pixel = tmp->cp.back;
624
625     attributes.event_mask = (KeyPressMask | ButtonPressMask |
626                              ButtonReleaseMask | ExposureMask |
627                              EnterWindowMask | LeaveWindowMask);
628     attributes.cursor = Scr->IconMgrCursor;
629
630         /* djhjr - 9/17/96 */
631         if (Scr->BackingStore)
632         {
633                 attributes.backing_store = WhenMapped;
634                 valuemask |= CWBackingStore;
635         }
636
637     tmp->w = XCreateWindow (dpy, ip->w, 0, 0, (unsigned int) 1, 
638                             (unsigned int) h, (unsigned int) 0, 
639                             CopyFromParent, (unsigned int) CopyFromParent,
640                             (Visual *) CopyFromParent, valuemask, &attributes);
641
642
643     valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor);
644
645 /* djhjr - 4/19/96
646     attributes.background_pixel = tmp->back;
647 */
648     attributes.background_pixel = tmp->cp.back;
649
650     attributes.border_pixel = Scr->Black;
651     attributes.event_mask = (ButtonReleaseMask| ButtonPressMask |
652                              ExposureMask);
653     attributes.cursor = Scr->ButtonCursor;
654
655         /* djhjr - 5/5/98 */
656         if (!iconmgr_iconx)
657         {
658                 /* was 'Scr->use3Diconmanagers' - djhjr - 8/11/98 */
659                 if (Scr->IconMgrBevelWidth > 0)
660                         iconmgr_iconx = Scr->IconMgrBevelWidth + 5;
661                 else
662                         iconmgr_iconx = Scr->BorderWidth + 5;
663                 iconmgr_textx = iconmgr_iconx + siconify_width + 5;
664         }
665
666         /* 'iconmgr_iconx' was '5' - djhjr - 5/5/98 */
667     tmp->icon = XCreateWindow (dpy, tmp->w, iconmgr_iconx, (int) (h - siconify_height)/2,
668                                (unsigned int) siconify_width,
669                                (unsigned int) siconify_height,
670                                (unsigned int) 0, CopyFromParent,
671                                (unsigned int) CopyFromParent,
672                                (Visual *) CopyFromParent,
673                                valuemask, &attributes);
674
675     ip->count += 1;
676     PackIconManager(ip);
677     XMapWindow(dpy, tmp->w);
678
679     XSaveContext(dpy, tmp->w, IconManagerContext, (caddr_t) tmp);
680     XSaveContext(dpy, tmp->w, TwmContext, (caddr_t) tmp_win);
681     XSaveContext(dpy, tmp->w, ScreenContext, (caddr_t) Scr);
682     XSaveContext(dpy, tmp->icon, TwmContext, (caddr_t) tmp_win);
683     XSaveContext(dpy, tmp->icon, ScreenContext, (caddr_t) Scr);
684     tmp_win->list = tmp;
685
686     if (!ip->twm_win->icon)
687     {
688         XMapWindow(dpy, ip->w);
689         XMapWindow(dpy, ip->twm_win->frame);
690     }
691
692         /* djhjr - 9/21/99 */
693         else
694                 XMapWindow(dpy, ip->twm_win->icon_w);
695
696     return (tmp);
697 }
698
699 /***********************************************************************
700  *
701  *  Procedure:
702  *      InsertInIconManager - put an allocated entry into an icon 
703  *              manager
704  *
705  *  Inputs:
706  *      ip      - the icon manager pointer
707  *      tmp     - the entry to insert
708  *
709  ***********************************************************************
710  */
711
712 void InsertInIconManager(ip, tmp, tmp_win)
713     IconMgr *ip;
714     WList *tmp;
715     TwmWindow *tmp_win;
716 {
717     WList *tmp1;
718     int added;
719     int (*compar)() = (Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1);
720
721     added = FALSE;
722     if (ip->first == NULL)
723     {
724         ip->first = tmp;
725         tmp->prev = NULL;
726         ip->last = tmp;
727         added = TRUE;
728     }
729     else if (Scr->SortIconMgr)
730     {
731         for (tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next)
732         {
733             if ((*compar)(tmp_win->icon_name, tmp1->twm->icon_name) < 0)
734             {
735                 tmp->next = tmp1;
736                 tmp->prev = tmp1->prev;
737                 tmp1->prev = tmp;
738                 if (tmp->prev == NULL)
739                     ip->first = tmp;
740                 else
741                     tmp->prev->next = tmp;
742                 added = TRUE;
743                 break;
744             }
745         }
746     }
747
748     if (!added)
749     {
750         ip->last->next = tmp;
751         tmp->prev = ip->last;
752         ip->last = tmp;
753     }
754 }
755
756 void RemoveFromIconManager(ip, tmp)
757     IconMgr *ip;
758     WList *tmp;
759 {
760     if (tmp->prev == NULL)
761         ip->first = tmp->next;
762     else
763         tmp->prev->next = tmp->next;
764
765     if (tmp->next == NULL)
766         ip->last = tmp->prev;
767     else
768         tmp->next->prev = tmp->prev;
769 }
770
771 /***********************************************************************
772  *
773  *  Procedure:
774  *      RemoveIconManager - remove a window from the icon manager
775  *
776  *  Inputs:
777  *      tmp_win - the TwmWindow structure
778  *
779  ***********************************************************************
780  */
781
782 void RemoveIconManager(tmp_win)
783     TwmWindow *tmp_win;
784 {
785     IconMgr *ip;
786     WList *tmp;
787
788     if (tmp_win->list == NULL)
789         return;
790
791     tmp = tmp_win->list;
792
793     /* submitted by Jonathan Paisley - 11/11/02 */
794     if (Active == tmp)
795         Active = NULL;
796
797         /*
798          * Believe it or not, the kludge in events.c:HandleKeyPress() needs
799          * this, or a window that's been destroyed still registers there,
800          * even though the whole mess gets freed in just a few microseconds!
801          *
802          * djhjr - 6/5/98
803          */
804         /*
805          * Somehwere alone the line, whatever it was got fixed, and this is
806          * needed again - djhjr - 5/27/03
807          */
808 /*#ifdef NEVER*/ /* warps to icon managers uniquely handled in menus.c:WarpToWindow() */
809         tmp->active = FALSE;
810         tmp->iconmgr->active = NULL;
811 /*#endif*/
812
813     tmp_win->list = NULL;
814     ip = tmp->iconmgr;
815
816     RemoveFromIconManager(ip, tmp);
817     
818     XDeleteContext(dpy, tmp->icon, TwmContext);
819     XDeleteContext(dpy, tmp->icon, ScreenContext);
820     XDestroyWindow(dpy, tmp->icon);
821     XDeleteContext(dpy, tmp->w, IconManagerContext);
822     XDeleteContext(dpy, tmp->w, TwmContext);
823     XDeleteContext(dpy, tmp->w, ScreenContext);
824     XDestroyWindow(dpy, tmp->w);
825     ip->count -= 1;
826
827 #ifdef NEVER /* can't do this, else we lose the button entirely! */
828         /* about damn time I did this! - djhjr - 6/5/98 */
829         XFreePixmap(dpy, tmp->iconifypm);
830 #endif
831
832     free((char *) tmp);
833
834     PackIconManager(ip);
835
836     if (ip->count == 0)
837     {
838         /* djhjr - 9/21/99 */
839         if (ip->twm_win->icon)
840                 XUnmapWindow(dpy, ip->twm_win->icon_w);
841         else
842
843         XUnmapWindow(dpy, ip->twm_win->frame);
844     }
845
846 }
847
848 void ActiveIconManager(active)
849     WList *active;
850 {
851     active->active = TRUE;
852     Active = active;
853     Active->iconmgr->active = active;
854
855 /* djhjr - 4/19/96
856     DrawIconManagerBorder(active);
857 */
858     DrawIconManagerBorder(active, False);
859 }
860
861 void NotActiveIconManager(active)
862     WList *active;
863 {
864     active->active = FALSE;
865
866 /* djhjr - 4/19/96
867     DrawIconManagerBorder(active);
868 */
869     DrawIconManagerBorder(active, False);
870 }
871
872 /* djhjr - 4/19/96
873 void DrawIconManagerBorder(tmp)
874     WList *tmp;
875 */
876 void DrawIconManagerBorder(tmp, fill)
877     WList *tmp;
878     int fill;
879 {
880         /* was 'Scr->use3Diconmanagers' - djhjr - 8/11/98 */
881     if (Scr->IconMgrBevelWidth > 0) {
882         int shadow_width;
883
884 /* djhjr - 4/28/98
885         shadow_width = 2;
886 */
887         shadow_width = Scr->IconMgrBevelWidth;
888
889 /* djhjr - 1/27/98
890         if (tmp->active && Scr->Highlight)
891 */
892         if (tmp->active && Scr->IconMgrHighlight)
893             Draw3DBorder (tmp->w, 0, 0, tmp->width, tmp->height, shadow_width,
894                                 tmp->cp, on, fill, False);
895         else
896             Draw3DBorder (tmp->w, 0, 0, tmp->width, tmp->height, shadow_width,
897                                 tmp->cp, off, fill, False);
898     }
899     else {
900 /*
901         XSetForeground(dpy, Scr->NormalGC, tmp->fore);
902 */
903         XSetForeground(dpy, Scr->NormalGC, tmp->cp.fore);
904             XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 2, 2,
905                 tmp->width-5, tmp->height-5);
906
907 /* djhjr - 1/27/98
908         if (tmp->active && Scr->Highlight)
909 */
910         if (tmp->active && Scr->IconMgrHighlight)
911             XSetForeground(dpy, Scr->NormalGC, tmp->highlight);
912         else
913 /*
914             XSetForeground(dpy, Scr->NormalGC, tmp->back);
915 */
916             XSetForeground(dpy, Scr->NormalGC, tmp->cp.back);
917
918         XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 0, 0,
919             tmp->width-1, tmp->height-1);
920         XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 1, 1,
921             tmp->width-3, tmp->height-3);
922     }
923 }
924
925 /***********************************************************************
926  *
927  *  Procedure:
928  *      SortIconManager - sort the dude
929  *
930  *  Inputs:
931  *      ip      - a pointer to the icon manager struture
932  *
933  ***********************************************************************
934  */
935
936 void SortIconManager(ip)
937     IconMgr *ip;
938 {
939     WList *tmp1, *tmp2;
940     int done;
941     int (*compar)() = (Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1);
942
943     if (ip == NULL)
944         ip = Active->iconmgr;
945
946     done = FALSE;
947     do
948     {
949         for (tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next)
950         {
951             if ((tmp2 = tmp1->next) == NULL)
952             {
953                 done = TRUE;
954                 break;
955             }
956             if ((*compar)(tmp1->twm->icon_name, tmp2->twm->icon_name) > 0)
957             {
958                 /* take it out and put it back in */
959                 RemoveFromIconManager(ip, tmp2);
960                 InsertInIconManager(ip, tmp2, tmp2->twm);
961                 break;
962             }
963         }
964     }
965     while (!done);
966     PackIconManager(ip);
967 }
968
969 /***********************************************************************
970  *
971  *  Procedure:
972  *      PackIconManager - pack the icon manager windows following
973  *              an addition or deletion
974  *
975  *  Inputs:
976  *      ip      - a pointer to the icon manager struture
977  *
978  ***********************************************************************
979  */
980
981 void PackIconManager(ip)
982     IconMgr *ip;
983 {
984     int newwidth, i, row, col, maxcol,  colinc, rowinc, wheight, wwidth;
985     int new_x, new_y;
986     int savewidth;
987     WList *tmp;
988
989         /* djhjr - 5/2/98 */
990         wheight = ComputeIconMgrWindowHeight();
991
992     wwidth = ip->width / ip->columns;
993
994     rowinc = wheight;
995     colinc = wwidth;
996
997     row = 0;
998     col = ip->columns;
999     maxcol = 0;
1000     for (i = 0, tmp = ip->first; tmp != NULL; i++, tmp = tmp->next)
1001     {
1002         tmp->me = i;
1003         if (++col >= ip->columns)
1004         {
1005             col = 0;
1006             row += 1;
1007         }
1008         if (col > maxcol)
1009             maxcol = col;
1010
1011         new_x = col * colinc;
1012         new_y = (row-1) * rowinc;
1013
1014         /* if the position or size has not changed, don't touch it */
1015         if (tmp->x != new_x || tmp->y != new_y ||
1016             tmp->width != wwidth || tmp->height != wheight)
1017         {
1018             XMoveResizeWindow(dpy, tmp->w, new_x, new_y, wwidth, wheight);
1019
1020             tmp->row = row-1;
1021             tmp->col = col;
1022             tmp->x = new_x;
1023             tmp->y = new_y;
1024             tmp->width = wwidth;
1025             tmp->height = wheight;
1026         }
1027     }
1028     maxcol += 1;
1029
1030     ip->cur_rows = row;
1031     ip->cur_columns = maxcol;
1032     ip->height = row * rowinc;
1033     if (ip->height == 0)
1034         ip->height = rowinc;
1035     newwidth = maxcol * colinc;
1036     if (newwidth == 0)
1037         newwidth = colinc;
1038
1039     XResizeWindow(dpy, ip->w, newwidth, ip->height);
1040
1041     savewidth = ip->width;
1042     if (ip->twm_win)
1043     {
1044
1045       /* limit the min and max sizes of an icon manager - djhjr - 3/1/99 */
1046       ip->twm_win->hints.flags |= (PMinSize | PMaxSize);
1047       ip->twm_win->hints.min_width = maxcol * (2 * iconmgr_iconx + siconify_width);
1048       ip->twm_win->hints.min_height = ip->height;
1049       ip->twm_win->hints.max_width = Scr->MyDisplayWidth;
1050       ip->twm_win->hints.max_height = ip->height;
1051
1052 /* djhjr - 4/19/96     
1053       SetupWindow (ip->twm_win,
1054                    ip->twm_win->frame_x, ip->twm_win->frame_y,
1055                    newwidth, ip->height + ip->twm_win->title_height, -1);
1056 */
1057       SetupWindow (ip->twm_win,
1058             ip->twm_win->frame_x, ip->twm_win->frame_y,
1059             newwidth + 2 * ip->twm_win->frame_bw3D,
1060             ip->height + ip->twm_win->title_height + 2 * ip->twm_win->frame_bw3D, -1);
1061     }
1062
1063     ip->width = savewidth;
1064 }
1065
1066 /*
1067  * ComputeIconMgrWindowHeight()
1068  * scale the icon manager window height to the font used
1069  *
1070  * djhjr - 5/2/98
1071  */
1072 static int ComputeIconMgrWindowHeight()
1073 {
1074         int h;
1075
1076         /* was 'Scr->use3Diconmanagers' - djhjr - 8/11/98 */
1077         if (Scr->IconMgrBevelWidth > 0)
1078         {
1079                 h = Scr->IconManagerFont.height + 2 * Scr->IconMgrBevelWidth + 4;
1080                 if (h < (siconify_height + 2 * Scr->IconMgrBevelWidth + 4))
1081                         h = siconify_height + 2 * Scr->IconMgrBevelWidth + 4;
1082         }
1083         else
1084         {
1085                 h = Scr->IconManagerFont.height + 10;
1086                 if (h < (siconify_height + 4))
1087                         h = siconify_height + 4;
1088         }
1089
1090         /* make height be odd so buttons look nice and centered */
1091         if (!(h & 1)) h++;
1092
1093         return (h);
1094 }
1095