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