iconmgr.c revision 3e747e6d
13e747e6dSmrg/*
23e747e6dSmrg *
33e747e6dSmrgCopyright 1989,1998  The Open Group
43e747e6dSmrg
53e747e6dSmrgPermission to use, copy, modify, distribute, and sell this software and its
63e747e6dSmrgdocumentation for any purpose is hereby granted without fee, provided that
73e747e6dSmrgthe above copyright notice appear in all copies and that both that
83e747e6dSmrgcopyright notice and this permission notice appear in supporting
93e747e6dSmrgdocumentation.
103e747e6dSmrg
113e747e6dSmrgThe above copyright notice and this permission notice shall be included in
123e747e6dSmrgall copies or substantial portions of the Software.
133e747e6dSmrg
143e747e6dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
153e747e6dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
163e747e6dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
173e747e6dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
183e747e6dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
193e747e6dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
203e747e6dSmrg
213e747e6dSmrgExcept as contained in this notice, the name of The Open Group shall not be
223e747e6dSmrgused in advertising or otherwise to promote the sale, use or other dealings
233e747e6dSmrgin this Software without prior written authorization from The Open Group.
243e747e6dSmrg * */
253e747e6dSmrg/* $XFree86: xc/programs/twm/iconmgr.c,v 1.5 2001/01/17 23:45:06 dawes Exp $ */
263e747e6dSmrg
273e747e6dSmrg/***********************************************************************
283e747e6dSmrg *
293e747e6dSmrg * $Xorg: iconmgr.c,v 1.4 2001/02/09 02:05:36 xorgcvs Exp $
303e747e6dSmrg *
313e747e6dSmrg * Icon Manager routines
323e747e6dSmrg *
333e747e6dSmrg * 09-Mar-89 Tom LaStrange		File Created
343e747e6dSmrg *
353e747e6dSmrg ***********************************************************************/
363e747e6dSmrg/* $XFree86: xc/programs/twm/iconmgr.c,v 1.5 2001/01/17 23:45:06 dawes Exp $ */
373e747e6dSmrg
383e747e6dSmrg#include <stdio.h>
393e747e6dSmrg#include "twm.h"
403e747e6dSmrg#include "util.h"
413e747e6dSmrg#include "parse.h"
423e747e6dSmrg#include "screen.h"
433e747e6dSmrg#include "resize.h"
443e747e6dSmrg#include "add_window.h"
453e747e6dSmrg#include "siconify.bm"
463e747e6dSmrg#include <X11/Xos.h>
473e747e6dSmrg#include <X11/Xmu/CharSet.h>
483e747e6dSmrg#ifdef macII
493e747e6dSmrgint strcmp(); /* missing from string.h in AUX 2.0 */
503e747e6dSmrg#endif
513e747e6dSmrg
523e747e6dSmrgint iconmgr_textx = siconify_width+11;
533e747e6dSmrgWList *Active = NULL;
543e747e6dSmrgWList *DownIconManager = NULL;
553e747e6dSmrgint iconifybox_width = siconify_width;
563e747e6dSmrgint iconifybox_height = siconify_height;
573e747e6dSmrg
583e747e6dSmrg/**
593e747e6dSmrg * create all the icon manager windows for this screen.
603e747e6dSmrg */
613e747e6dSmrgvoid CreateIconManagers()
623e747e6dSmrg{
633e747e6dSmrg    IconMgr *p;
643e747e6dSmrg    int mask;
653e747e6dSmrg    char str[100];
663e747e6dSmrg    char str1[100];
673e747e6dSmrg    Pixel background;
683e747e6dSmrg    char *icon_name;
693e747e6dSmrg
703e747e6dSmrg    if (Scr->NoIconManagers)
713e747e6dSmrg	return;
723e747e6dSmrg
733e747e6dSmrg    if (Scr->siconifyPm == None)
743e747e6dSmrg    {
753e747e6dSmrg	Scr->siconifyPm = XCreatePixmapFromBitmapData(dpy, Scr->Root,
763e747e6dSmrg	    (char *)siconify_bits, siconify_width, siconify_height, 1, 0, 1);
773e747e6dSmrg    }
783e747e6dSmrg
793e747e6dSmrg    for (p = &Scr->iconmgr; p != NULL; p = p->next)
803e747e6dSmrg    {
813e747e6dSmrg	mask = XParseGeometry(p->geometry, &JunkX, &JunkY,
823e747e6dSmrg			      (unsigned int *) &p->width, (unsigned int *)&p->height);
833e747e6dSmrg
843e747e6dSmrg	if (mask & XNegative)
853e747e6dSmrg	    JunkX = Scr->MyDisplayWidth - p->width -
863e747e6dSmrg	      (2 * Scr->BorderWidth) + JunkX;
873e747e6dSmrg
883e747e6dSmrg	if (mask & YNegative)
893e747e6dSmrg	    JunkY = Scr->MyDisplayHeight - p->height -
903e747e6dSmrg	      (2 * Scr->BorderWidth) + JunkY;
913e747e6dSmrg
923e747e6dSmrg	background = Scr->IconManagerC.back;
933e747e6dSmrg	GetColorFromList(Scr->IconManagerBL, p->name, (XClassHint *)NULL,
943e747e6dSmrg			 &background);
953e747e6dSmrg
963e747e6dSmrg	p->w = XCreateSimpleWindow(dpy, Scr->Root,
973e747e6dSmrg	    JunkX, JunkY, p->width, p->height, 1,
983e747e6dSmrg	    Scr->Black, background);
993e747e6dSmrg
1003e747e6dSmrg	sprintf(str, "%s Icon Manager", p->name);
1013e747e6dSmrg	sprintf(str1, "%s Icons", p->name);
1023e747e6dSmrg	if (p->icon_name)
1033e747e6dSmrg	    icon_name = p->icon_name;
1043e747e6dSmrg	else
1053e747e6dSmrg	    icon_name = str1;
1063e747e6dSmrg
1073e747e6dSmrg	XSetStandardProperties(dpy, p->w, str, icon_name, None, NULL, 0, NULL);
1083e747e6dSmrg
1093e747e6dSmrg	p->twm_win = AddWindow(p->w, TRUE, p);
1103e747e6dSmrg	SetMapStateProp (p->twm_win, WithdrawnState);
1113e747e6dSmrg    }
1123e747e6dSmrg    for (p = &Scr->iconmgr; p != NULL; p = p->next)
1133e747e6dSmrg    {
1143e747e6dSmrg	GrabButtons(p->twm_win);
1153e747e6dSmrg	GrabKeys(p->twm_win);
1163e747e6dSmrg    }
1173e747e6dSmrg}
1183e747e6dSmrg
1193e747e6dSmrg/**
1203e747e6dSmrg * allocate a new icon manager
1213e747e6dSmrg *
1223e747e6dSmrg *  \param name     the name of this icon manager
1233e747e6dSmrg *  \param con_name the name of the associated icon
1243e747e6dSmrg *  \param geom	    a geometry string to eventually parse
1253e747e6dSmrg *	\param columns  the number of columns this icon manager has
1263e747e6dSmrg */
1273e747e6dSmrgIconMgr *AllocateIconManager(char *name, char *icon_name, char *geom, int columns)
1283e747e6dSmrg{
1293e747e6dSmrg    IconMgr *p;
1303e747e6dSmrg
1313e747e6dSmrg#ifdef DEBUG_ICONMGR
1323e747e6dSmrg    fprintf(stderr, "AllocateIconManager\n");
1333e747e6dSmrg    fprintf(stderr, "  name=\"%s\" icon_name=\"%s\", geom=\"%s\", col=%d\n",
1343e747e6dSmrg	name, icon_name, geom, columns);
1353e747e6dSmrg#endif
1363e747e6dSmrg
1373e747e6dSmrg    if (Scr->NoIconManagers)
1383e747e6dSmrg	return NULL;
1393e747e6dSmrg
1403e747e6dSmrg    p = (IconMgr *)malloc(sizeof(IconMgr));
1413e747e6dSmrg    p->name = name;
1423e747e6dSmrg    p->icon_name = icon_name;
1433e747e6dSmrg    p->geometry = geom;
1443e747e6dSmrg    p->columns = columns;
1453e747e6dSmrg    p->first = NULL;
1463e747e6dSmrg    p->last = NULL;
1473e747e6dSmrg    p->active = NULL;
1483e747e6dSmrg    p->scr = Scr;
1493e747e6dSmrg    p->count = 0;
1503e747e6dSmrg    p->x = 0;
1513e747e6dSmrg    p->y = 0;
1523e747e6dSmrg    p->width = 150;
1533e747e6dSmrg    p->height = 10;
1543e747e6dSmrg
1553e747e6dSmrg    Scr->iconmgr.lasti->next = p;
1563e747e6dSmrg    p->prev = Scr->iconmgr.lasti;
1573e747e6dSmrg    Scr->iconmgr.lasti = p;
1583e747e6dSmrg    p->next = NULL;
1593e747e6dSmrg
1603e747e6dSmrg    return(p);
1613e747e6dSmrg}
1623e747e6dSmrg
1633e747e6dSmrg/**
1643e747e6dSmrg * move the pointer around in an icon manager
1653e747e6dSmrg *
1663e747e6dSmrg *  \param dir one of the following:
1673e747e6dSmrg *    - F_FORWICONMGR:  forward in the window list
1683e747e6dSmrg *    - F_BACKICONMGR:  backward in the window list
1693e747e6dSmrg *    - F_UPICONMGR:    up one row
1703e747e6dSmrg *    - F_DOWNICONMG:   down one row
1713e747e6dSmrg *    - F_LEFTICONMGR:  left one column
1723e747e6dSmrg *    - F_RIGHTICONMGR: right one column
1733e747e6dSmrg */
1743e747e6dSmrgvoid MoveIconManager(int dir)
1753e747e6dSmrg{
1763e747e6dSmrg    IconMgr *ip;
1773e747e6dSmrg    WList *tmp = NULL;
1783e747e6dSmrg    int cur_row, cur_col, new_row, new_col;
1793e747e6dSmrg    int row_inc, col_inc;
1803e747e6dSmrg    int got_it;
1813e747e6dSmrg
1823e747e6dSmrg    if (!Active) return;
1833e747e6dSmrg
1843e747e6dSmrg    cur_row = Active->row;
1853e747e6dSmrg    cur_col = Active->col;
1863e747e6dSmrg    ip = Active->iconmgr;
1873e747e6dSmrg
1883e747e6dSmrg    row_inc = 0;
1893e747e6dSmrg    col_inc = 0;
1903e747e6dSmrg    got_it = FALSE;
1913e747e6dSmrg
1923e747e6dSmrg    switch (dir)
1933e747e6dSmrg    {
1943e747e6dSmrg	case F_FORWICONMGR:
1953e747e6dSmrg	    if ((tmp = Active->next) == NULL)
1963e747e6dSmrg		tmp = ip->first;
1973e747e6dSmrg	    got_it = TRUE;
1983e747e6dSmrg	    break;
1993e747e6dSmrg
2003e747e6dSmrg	case F_BACKICONMGR:
2013e747e6dSmrg	    if ((tmp = Active->prev) == NULL)
2023e747e6dSmrg		tmp = ip->last;
2033e747e6dSmrg	    got_it = TRUE;
2043e747e6dSmrg	    break;
2053e747e6dSmrg
2063e747e6dSmrg	case F_UPICONMGR:
2073e747e6dSmrg	    row_inc = -1;
2083e747e6dSmrg	    break;
2093e747e6dSmrg
2103e747e6dSmrg	case F_DOWNICONMGR:
2113e747e6dSmrg	    row_inc = 1;
2123e747e6dSmrg	    break;
2133e747e6dSmrg
2143e747e6dSmrg	case F_LEFTICONMGR:
2153e747e6dSmrg	    col_inc = -1;
2163e747e6dSmrg	    break;
2173e747e6dSmrg
2183e747e6dSmrg	case F_RIGHTICONMGR:
2193e747e6dSmrg	    col_inc = 1;
2203e747e6dSmrg	    break;
2213e747e6dSmrg    }
2223e747e6dSmrg
2233e747e6dSmrg    /* If got_it is FALSE ast this point then we got a left, right,
2243e747e6dSmrg     * up, or down, command.  We will enter this loop until we find
2253e747e6dSmrg     * a window to warp to.
2263e747e6dSmrg     */
2273e747e6dSmrg    new_row = cur_row;
2283e747e6dSmrg    new_col = cur_col;
2293e747e6dSmrg
2303e747e6dSmrg    while (!got_it)
2313e747e6dSmrg    {
2323e747e6dSmrg	new_row += row_inc;
2333e747e6dSmrg	new_col += col_inc;
2343e747e6dSmrg	if (new_row < 0)
2353e747e6dSmrg	    new_row = ip->cur_rows - 1;
2363e747e6dSmrg	if (new_col < 0)
2373e747e6dSmrg	    new_col = ip->cur_columns - 1;
2383e747e6dSmrg	if (new_row >= ip->cur_rows)
2393e747e6dSmrg	    new_row = 0;
2403e747e6dSmrg	if (new_col >= ip->cur_columns)
2413e747e6dSmrg	    new_col = 0;
2423e747e6dSmrg
2433e747e6dSmrg	/* Now let's go through the list to see if there is an entry with this
2443e747e6dSmrg	 * new position
2453e747e6dSmrg	 */
2463e747e6dSmrg	for (tmp = ip->first; tmp != NULL; tmp = tmp->next)
2473e747e6dSmrg	{
2483e747e6dSmrg	    if (tmp->row == new_row && tmp->col == new_col)
2493e747e6dSmrg	    {
2503e747e6dSmrg		got_it = TRUE;
2513e747e6dSmrg		break;
2523e747e6dSmrg	    }
2533e747e6dSmrg	}
2543e747e6dSmrg    }
2553e747e6dSmrg
2563e747e6dSmrg    if (!got_it)
2573e747e6dSmrg    {
2583e747e6dSmrg	fprintf (stderr,
2593e747e6dSmrg		 "%s:  unable to find window (%d, %d) in icon manager\n",
2603e747e6dSmrg		 ProgramName, new_row, new_col);
2613e747e6dSmrg	return;
2623e747e6dSmrg    }
2633e747e6dSmrg
2643e747e6dSmrg    if (tmp == NULL)
2653e747e6dSmrg      return;
2663e747e6dSmrg
2673e747e6dSmrg    /* raise the frame so the icon manager is visible */
2683e747e6dSmrg    if (ip->twm_win->mapped) {
2693e747e6dSmrg	XRaiseWindow(dpy, ip->twm_win->frame);
2703e747e6dSmrg	XWarpPointer(dpy, None, tmp->icon, 0,0,0,0, 5, 5);
2713e747e6dSmrg    } else {
2723e747e6dSmrg	if (tmp->twm->title_height) {
2733e747e6dSmrg	    int tbx = Scr->TBInfo.titlex;
2743e747e6dSmrg	    int x = tmp->twm->highlightx;
2753e747e6dSmrg	    XWarpPointer (dpy, None, tmp->twm->title_w, 0, 0, 0, 0,
2763e747e6dSmrg			  tbx + (x - tbx) / 2,
2773e747e6dSmrg			  Scr->TitleHeight / 4);
2783e747e6dSmrg	} else {
2793e747e6dSmrg	    XWarpPointer (dpy, None, tmp->twm->w, 0, 0, 0, 0, 5, 5);
2803e747e6dSmrg	}
2813e747e6dSmrg    }
2823e747e6dSmrg}
2833e747e6dSmrg
2843e747e6dSmrg/**
2853e747e6dSmrg * jump from one icon manager to another, possibly even on another screen
2863e747e6dSmrg *  \param dir one of the following:
2873e747e6dSmrg *    - F_NEXTICONMGR - go to the next icon manager
2883e747e6dSmrg *    - F_PREVICONMGR - go to the previous one
2893e747e6dSmrg */
2903e747e6dSmrg
2913e747e6dSmrgvoid JumpIconManager(int dir)
2923e747e6dSmrg{
2933e747e6dSmrg    IconMgr *ip, *tmp_ip = NULL;
2943e747e6dSmrg    int got_it = FALSE;
2953e747e6dSmrg    ScreenInfo *sp;
2963e747e6dSmrg    int screen;
2973e747e6dSmrg
2983e747e6dSmrg    if (!Active) return;
2993e747e6dSmrg
3003e747e6dSmrg
3013e747e6dSmrg#define ITER(i) (dir == F_NEXTICONMGR ? (i)->next : (i)->prev)
3023e747e6dSmrg#define IPOFSP(sp) (dir == F_NEXTICONMGR ? &(sp->iconmgr) : sp->iconmgr.lasti)
3033e747e6dSmrg#define TEST(ip) if ((ip)->count != 0 && (ip)->twm_win->mapped) \
3043e747e6dSmrg		 { got_it = TRUE; break; }
3053e747e6dSmrg
3063e747e6dSmrg    ip = Active->iconmgr;
3073e747e6dSmrg    for (tmp_ip = ITER(ip); tmp_ip; tmp_ip = ITER(tmp_ip)) {
3083e747e6dSmrg	TEST (tmp_ip);
3093e747e6dSmrg    }
3103e747e6dSmrg
3113e747e6dSmrg    if (!got_it) {
3123e747e6dSmrg	int origscreen = ip->scr->screen;
3133e747e6dSmrg	int inc = (dir == F_NEXTICONMGR ? 1 : -1);
3143e747e6dSmrg
3153e747e6dSmrg	for (screen = origscreen + inc; ; screen += inc) {
3163e747e6dSmrg	    if (screen >= NumScreens)
3173e747e6dSmrg	      screen = 0;
3183e747e6dSmrg	    else if (screen < 0)
3193e747e6dSmrg	      screen = NumScreens - 1;
3203e747e6dSmrg
3213e747e6dSmrg	    sp = ScreenList[screen];
3223e747e6dSmrg	    if (sp) {
3233e747e6dSmrg		for (tmp_ip = IPOFSP (sp); tmp_ip; tmp_ip = ITER(tmp_ip)) {
3243e747e6dSmrg		    TEST (tmp_ip);
3253e747e6dSmrg		}
3263e747e6dSmrg	    }
3273e747e6dSmrg	    if (got_it || screen == origscreen) break;
3283e747e6dSmrg	}
3293e747e6dSmrg    }
3303e747e6dSmrg
3313e747e6dSmrg#undef ITER
3323e747e6dSmrg#undef IPOFSP
3333e747e6dSmrg#undef TEST
3343e747e6dSmrg
3353e747e6dSmrg    if (!got_it) {
3363e747e6dSmrg	Bell(XkbBI_MinorError,0,None);
3373e747e6dSmrg	return;
3383e747e6dSmrg    }
3393e747e6dSmrg
3403e747e6dSmrg    /* raise the frame so it is visible */
3413e747e6dSmrg    XRaiseWindow(dpy, tmp_ip->twm_win->frame);
3423e747e6dSmrg    if (tmp_ip->active)
3433e747e6dSmrg	XWarpPointer(dpy, None, tmp_ip->active->icon, 0,0,0,0, 5, 5);
3443e747e6dSmrg    else
3453e747e6dSmrg	XWarpPointer(dpy, None, tmp_ip->w, 0,0,0,0, 5, 5);
3463e747e6dSmrg}
3473e747e6dSmrg
3483e747e6dSmrg/**
3493e747e6dSmrg * add a window to an icon manager
3503e747e6dSmrg *
3513e747e6dSmrg *  \param tmp_win the TwmWindow structure
3523e747e6dSmrg */
3533e747e6dSmrgWList *AddIconManager(TwmWindow *tmp_win)
3543e747e6dSmrg{
3553e747e6dSmrg    WList *tmp;
3563e747e6dSmrg    int h;
3573e747e6dSmrg    unsigned long valuemask;		/* mask for create windows */
3583e747e6dSmrg    XSetWindowAttributes attributes;	/* attributes for create windows */
3593e747e6dSmrg    IconMgr *ip;
3603e747e6dSmrg
3613e747e6dSmrg    tmp_win->list = NULL;
3623e747e6dSmrg
3633e747e6dSmrg    if (tmp_win->iconmgr || tmp_win->transient || Scr->NoIconManagers)
3643e747e6dSmrg	return NULL;
3653e747e6dSmrg
3663e747e6dSmrg    if (LookInList(Scr->IconMgrNoShow, tmp_win->full_name, &tmp_win->class))
3673e747e6dSmrg	return NULL;
3683e747e6dSmrg    if (Scr->IconManagerDontShow &&
3693e747e6dSmrg	!LookInList(Scr->IconMgrShow, tmp_win->full_name, &tmp_win->class))
3703e747e6dSmrg	return NULL;
3713e747e6dSmrg    if ((ip = (IconMgr *)LookInList(Scr->IconMgrs, tmp_win->full_name,
3723e747e6dSmrg	    &tmp_win->class)) == NULL)
3733e747e6dSmrg	ip = &Scr->iconmgr;
3743e747e6dSmrg
3753e747e6dSmrg    tmp = (WList *) malloc(sizeof(WList));
3763e747e6dSmrg    tmp->iconmgr = ip;
3773e747e6dSmrg    tmp->next = NULL;
3783e747e6dSmrg    tmp->active = FALSE;
3793e747e6dSmrg    tmp->down = FALSE;
3803e747e6dSmrg
3813e747e6dSmrg    InsertInIconManager(ip, tmp, tmp_win);
3823e747e6dSmrg
3833e747e6dSmrg    tmp->twm = tmp_win;
3843e747e6dSmrg
3853e747e6dSmrg    tmp->fore = Scr->IconManagerC.fore;
3863e747e6dSmrg    tmp->back = Scr->IconManagerC.back;
3873e747e6dSmrg    tmp->highlight = Scr->IconManagerHighlight;
3883e747e6dSmrg
3893e747e6dSmrg    GetColorFromList(Scr->IconManagerFL, tmp_win->full_name, &tmp_win->class,
3903e747e6dSmrg	&tmp->fore);
3913e747e6dSmrg    GetColorFromList(Scr->IconManagerBL, tmp_win->full_name, &tmp_win->class,
3923e747e6dSmrg	&tmp->back);
3933e747e6dSmrg    GetColorFromList(Scr->IconManagerHighlightL, tmp_win->full_name,
3943e747e6dSmrg	&tmp_win->class, &tmp->highlight);
3953e747e6dSmrg
3963e747e6dSmrg    h = Scr->IconManagerFont.height + 10;
3973e747e6dSmrg    if (h < (siconify_height + 4))
3983e747e6dSmrg	h = siconify_height + 4;
3993e747e6dSmrg
4003e747e6dSmrg    ip->height = h * ip->count;
4013e747e6dSmrg    tmp->me = ip->count;
4023e747e6dSmrg    tmp->x = -1;
4033e747e6dSmrg    tmp->y = -1;
4043e747e6dSmrg
4053e747e6dSmrg    valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor);
4063e747e6dSmrg    attributes.background_pixel = tmp->back;
4073e747e6dSmrg    attributes.border_pixel = tmp->back;
4083e747e6dSmrg    attributes.event_mask = (KeyPressMask | ButtonPressMask |
4093e747e6dSmrg			     ButtonReleaseMask | ExposureMask |
4103e747e6dSmrg			     EnterWindowMask | LeaveWindowMask);
4113e747e6dSmrg    attributes.cursor = Scr->IconMgrCursor;
4123e747e6dSmrg    tmp->w = XCreateWindow (dpy, ip->w, 0, 0, (unsigned int) 1,
4133e747e6dSmrg			    (unsigned int) h, (unsigned int) 0,
4143e747e6dSmrg			    CopyFromParent, (unsigned int) CopyFromParent,
4153e747e6dSmrg			    (Visual *) CopyFromParent, valuemask, &attributes);
4163e747e6dSmrg
4173e747e6dSmrg
4183e747e6dSmrg    valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor);
4193e747e6dSmrg    attributes.background_pixel = tmp->back;
4203e747e6dSmrg    attributes.border_pixel = Scr->Black;
4213e747e6dSmrg    attributes.event_mask = (ButtonReleaseMask| ButtonPressMask |
4223e747e6dSmrg			     ExposureMask);
4233e747e6dSmrg    attributes.cursor = Scr->ButtonCursor;
4243e747e6dSmrg    tmp->icon = XCreateWindow (dpy, tmp->w, 5, (int) (h - siconify_height)/2,
4253e747e6dSmrg			       (unsigned int) siconify_width,
4263e747e6dSmrg			       (unsigned int) siconify_height,
4273e747e6dSmrg			       (unsigned int) 0, CopyFromParent,
4283e747e6dSmrg			       (unsigned int) CopyFromParent,
4293e747e6dSmrg			       (Visual *) CopyFromParent,
4303e747e6dSmrg			       valuemask, &attributes);
4313e747e6dSmrg
4323e747e6dSmrg    ip->count += 1;
4333e747e6dSmrg    PackIconManager(ip);
4343e747e6dSmrg    XMapWindow(dpy, tmp->w);
4353e747e6dSmrg
4363e747e6dSmrg    XSaveContext(dpy, tmp->w, IconManagerContext, (caddr_t) tmp);
4373e747e6dSmrg    XSaveContext(dpy, tmp->w, TwmContext, (caddr_t) tmp_win);
4383e747e6dSmrg    XSaveContext(dpy, tmp->w, ScreenContext, (caddr_t) Scr);
4393e747e6dSmrg    XSaveContext(dpy, tmp->icon, TwmContext, (caddr_t) tmp_win);
4403e747e6dSmrg    XSaveContext(dpy, tmp->icon, ScreenContext, (caddr_t) Scr);
4413e747e6dSmrg    tmp_win->list = tmp;
4423e747e6dSmrg
4433e747e6dSmrg    if (!ip->twm_win->icon)
4443e747e6dSmrg    {
4453e747e6dSmrg	XMapWindow(dpy, ip->w);
4463e747e6dSmrg	XMapWindow(dpy, ip->twm_win->frame);
4473e747e6dSmrg    }
4483e747e6dSmrg
4493e747e6dSmrg    if (Active == NULL) Active = tmp;
4503e747e6dSmrg
4513e747e6dSmrg    return (tmp);
4523e747e6dSmrg}
4533e747e6dSmrg
4543e747e6dSmrg/**
4553e747e6dSmrg * put an allocated entry into an icon manager
4563e747e6dSmrg *
4573e747e6dSmrg *  \param ip  the icon manager pointer
4583e747e6dSmrg *  \param tmp the entry to insert
4593e747e6dSmrg */
4603e747e6dSmrgvoid InsertInIconManager(IconMgr *ip, WList *tmp, TwmWindow *tmp_win)
4613e747e6dSmrg{
4623e747e6dSmrg    WList *tmp1;
4633e747e6dSmrg    int added;
4643e747e6dSmrg    int (*compar)(const char *, const char *)
4653e747e6dSmrg	= (Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1);
4663e747e6dSmrg
4673e747e6dSmrg    added = FALSE;
4683e747e6dSmrg    if (ip->first == NULL)
4693e747e6dSmrg    {
4703e747e6dSmrg	ip->first = tmp;
4713e747e6dSmrg	tmp->prev = NULL;
4723e747e6dSmrg	ip->last = tmp;
4733e747e6dSmrg	added = TRUE;
4743e747e6dSmrg    }
4753e747e6dSmrg    else if (Scr->SortIconMgr)
4763e747e6dSmrg    {
4773e747e6dSmrg	for (tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next)
4783e747e6dSmrg	{
4793e747e6dSmrg	    if ((*compar)(tmp_win->icon_name, tmp1->twm->icon_name) < 0)
4803e747e6dSmrg	    {
4813e747e6dSmrg		tmp->next = tmp1;
4823e747e6dSmrg		tmp->prev = tmp1->prev;
4833e747e6dSmrg		tmp1->prev = tmp;
4843e747e6dSmrg		if (tmp->prev == NULL)
4853e747e6dSmrg		    ip->first = tmp;
4863e747e6dSmrg		else
4873e747e6dSmrg		    tmp->prev->next = tmp;
4883e747e6dSmrg		added = TRUE;
4893e747e6dSmrg		break;
4903e747e6dSmrg	    }
4913e747e6dSmrg	}
4923e747e6dSmrg    }
4933e747e6dSmrg
4943e747e6dSmrg    if (!added)
4953e747e6dSmrg    {
4963e747e6dSmrg	ip->last->next = tmp;
4973e747e6dSmrg	tmp->prev = ip->last;
4983e747e6dSmrg	ip->last = tmp;
4993e747e6dSmrg    }
5003e747e6dSmrg}
5013e747e6dSmrg
5023e747e6dSmrgvoid RemoveFromIconManager(IconMgr *ip, WList *tmp)
5033e747e6dSmrg{
5043e747e6dSmrg    if (tmp->prev == NULL)
5053e747e6dSmrg	ip->first = tmp->next;
5063e747e6dSmrg    else
5073e747e6dSmrg	tmp->prev->next = tmp->next;
5083e747e6dSmrg
5093e747e6dSmrg    if (tmp->next == NULL)
5103e747e6dSmrg	ip->last = tmp->prev;
5113e747e6dSmrg    else
5123e747e6dSmrg	tmp->next->prev = tmp->prev;
5133e747e6dSmrg}
5143e747e6dSmrg
5153e747e6dSmrg/**
5163e747e6dSmrg * remove a window from the icon manager
5173e747e6dSmrg *  \param tmp_win the TwmWindow structure
5183e747e6dSmrg */
5193e747e6dSmrgvoid RemoveIconManager(TwmWindow *tmp_win)
5203e747e6dSmrg{
5213e747e6dSmrg    IconMgr *ip;
5223e747e6dSmrg    WList *tmp;
5233e747e6dSmrg
5243e747e6dSmrg    if (tmp_win->list == NULL)
5253e747e6dSmrg	return;
5263e747e6dSmrg
5273e747e6dSmrg    tmp = tmp_win->list;
5283e747e6dSmrg    tmp_win->list = NULL;
5293e747e6dSmrg    ip = tmp->iconmgr;
5303e747e6dSmrg
5313e747e6dSmrg    RemoveFromIconManager(ip, tmp);
5323e747e6dSmrg
5333e747e6dSmrg    XDeleteContext(dpy, tmp->icon, TwmContext);
5343e747e6dSmrg    XDeleteContext(dpy, tmp->icon, ScreenContext);
5353e747e6dSmrg    XDestroyWindow(dpy, tmp->icon);
5363e747e6dSmrg    XDeleteContext(dpy, tmp->w, IconManagerContext);
5373e747e6dSmrg    XDeleteContext(dpy, tmp->w, TwmContext);
5383e747e6dSmrg    XDeleteContext(dpy, tmp->w, ScreenContext);
5393e747e6dSmrg    XDestroyWindow(dpy, tmp->w);
5403e747e6dSmrg    ip->count -= 1;
5413e747e6dSmrg    free((char *) tmp);
5423e747e6dSmrg
5433e747e6dSmrg    PackIconManager(ip);
5443e747e6dSmrg
5453e747e6dSmrg    if (ip->count == 0)
5463e747e6dSmrg    {
5473e747e6dSmrg	XUnmapWindow(dpy, ip->twm_win->frame);
5483e747e6dSmrg    }
5493e747e6dSmrg
5503e747e6dSmrg}
5513e747e6dSmrg
5523e747e6dSmrgvoid ActiveIconManager(WList *active)
5533e747e6dSmrg{
5543e747e6dSmrg    active->active = TRUE;
5553e747e6dSmrg    Active = active;
5563e747e6dSmrg    Active->iconmgr->active = active;
5573e747e6dSmrg    DrawIconManagerBorder(active);
5583e747e6dSmrg}
5593e747e6dSmrg
5603e747e6dSmrgvoid NotActiveIconManager(WList *active)
5613e747e6dSmrg{
5623e747e6dSmrg    active->active = FALSE;
5633e747e6dSmrg    DrawIconManagerBorder(active);
5643e747e6dSmrg}
5653e747e6dSmrg
5663e747e6dSmrgvoid DrawIconManagerBorder(WList *tmp)
5673e747e6dSmrg{
5683e747e6dSmrg    {
5693e747e6dSmrg	XSetForeground(dpy, Scr->NormalGC, tmp->fore);
5703e747e6dSmrg	    XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 2, 2,
5713e747e6dSmrg		tmp->width-5, tmp->height-5);
5723e747e6dSmrg
5733e747e6dSmrg	if (tmp->active && Scr->Highlight)
5743e747e6dSmrg	    XSetForeground(dpy, Scr->NormalGC, tmp->highlight);
5753e747e6dSmrg	else
5763e747e6dSmrg	    XSetForeground(dpy, Scr->NormalGC, tmp->back);
5773e747e6dSmrg
5783e747e6dSmrg	XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 0, 0,
5793e747e6dSmrg	    tmp->width-1, tmp->height-1);
5803e747e6dSmrg	XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 1, 1,
5813e747e6dSmrg	    tmp->width-3, tmp->height-3);
5823e747e6dSmrg    }
5833e747e6dSmrg}
5843e747e6dSmrg
5853e747e6dSmrg/**
5863e747e6dSmrg * sort The Dude
5873e747e6dSmrg *
5883e747e6dSmrg *  \param ip a pointer to the icon manager struture
5893e747e6dSmrg */
5903e747e6dSmrgvoid SortIconManager(IconMgr *ip)
5913e747e6dSmrg{
5923e747e6dSmrg    WList *tmp1, *tmp2;
5933e747e6dSmrg    int done;
5943e747e6dSmrg    int (*compar)(const char *, const char *)
5953e747e6dSmrg	= (Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1);
5963e747e6dSmrg
5973e747e6dSmrg    if (ip == NULL)
5983e747e6dSmrg	ip = Active->iconmgr;
5993e747e6dSmrg
6003e747e6dSmrg    done = FALSE;
6013e747e6dSmrg    do
6023e747e6dSmrg    {
6033e747e6dSmrg	for (tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next)
6043e747e6dSmrg	{
6053e747e6dSmrg	    if ((tmp2 = tmp1->next) == NULL)
6063e747e6dSmrg	    {
6073e747e6dSmrg		done = TRUE;
6083e747e6dSmrg		break;
6093e747e6dSmrg	    }
6103e747e6dSmrg	    if ((*compar)(tmp1->twm->icon_name, tmp2->twm->icon_name) > 0)
6113e747e6dSmrg	    {
6123e747e6dSmrg		/* take it out and put it back in */
6133e747e6dSmrg		RemoveFromIconManager(ip, tmp2);
6143e747e6dSmrg		InsertInIconManager(ip, tmp2, tmp2->twm);
6153e747e6dSmrg		break;
6163e747e6dSmrg	    }
6173e747e6dSmrg	}
6183e747e6dSmrg    }
6193e747e6dSmrg    while (!done);
6203e747e6dSmrg    PackIconManager(ip);
6213e747e6dSmrg}
6223e747e6dSmrg
6233e747e6dSmrg/**
6243e747e6dSmrg * pack the icon manager windows following
6253e747e6dSmrg *		an addition or deletion
6263e747e6dSmrg *
6273e747e6dSmrg *  \param ip a pointer to the icon manager struture
6283e747e6dSmrg */
6293e747e6dSmrgvoid PackIconManager(IconMgr *ip)
6303e747e6dSmrg{
6313e747e6dSmrg    int newwidth, i, row, col, maxcol,  colinc, rowinc, wheight, wwidth;
6323e747e6dSmrg    int new_x, new_y;
6333e747e6dSmrg    int savewidth;
6343e747e6dSmrg    WList *tmp;
6353e747e6dSmrg
6363e747e6dSmrg    wheight = Scr->IconManagerFont.height + 10;
6373e747e6dSmrg    if (wheight < (siconify_height + 4))
6383e747e6dSmrg	wheight = siconify_height + 4;
6393e747e6dSmrg
6403e747e6dSmrg    wwidth = ip->width / ip->columns;
6413e747e6dSmrg
6423e747e6dSmrg    rowinc = wheight;
6433e747e6dSmrg    colinc = wwidth;
6443e747e6dSmrg
6453e747e6dSmrg    row = 0;
6463e747e6dSmrg    col = ip->columns;
6473e747e6dSmrg    maxcol = 0;
6483e747e6dSmrg    for (i = 0, tmp = ip->first; tmp != NULL; i++, tmp = tmp->next)
6493e747e6dSmrg    {
6503e747e6dSmrg	tmp->me = i;
6513e747e6dSmrg	if (++col >= ip->columns)
6523e747e6dSmrg	{
6533e747e6dSmrg	    col = 0;
6543e747e6dSmrg	    row += 1;
6553e747e6dSmrg	}
6563e747e6dSmrg	if (col > maxcol)
6573e747e6dSmrg	    maxcol = col;
6583e747e6dSmrg
6593e747e6dSmrg	new_x = col * colinc;
6603e747e6dSmrg	new_y = (row-1) * rowinc;
6613e747e6dSmrg
6623e747e6dSmrg	/* if the position or size has not changed, don't touch it */
6633e747e6dSmrg	if (tmp->x != new_x || tmp->y != new_y ||
6643e747e6dSmrg	    tmp->width != wwidth || tmp->height != wheight)
6653e747e6dSmrg	{
6663e747e6dSmrg	    XMoveResizeWindow(dpy, tmp->w, new_x, new_y, wwidth, wheight);
6673e747e6dSmrg
6683e747e6dSmrg	    tmp->row = row-1;
6693e747e6dSmrg	    tmp->col = col;
6703e747e6dSmrg	    tmp->x = new_x;
6713e747e6dSmrg	    tmp->y = new_y;
6723e747e6dSmrg	    tmp->width = wwidth;
6733e747e6dSmrg	    tmp->height = wheight;
6743e747e6dSmrg	}
6753e747e6dSmrg    }
6763e747e6dSmrg    maxcol += 1;
6773e747e6dSmrg
6783e747e6dSmrg    ip->cur_rows = row;
6793e747e6dSmrg    ip->cur_columns = maxcol;
6803e747e6dSmrg    ip->height = row * rowinc;
6813e747e6dSmrg    if (ip->height == 0)
6823e747e6dSmrg    	ip->height = rowinc;
6833e747e6dSmrg    newwidth = maxcol * colinc;
6843e747e6dSmrg    if (newwidth == 0)
6853e747e6dSmrg	newwidth = colinc;
6863e747e6dSmrg
6873e747e6dSmrg    XResizeWindow(dpy, ip->w, newwidth, ip->height);
6883e747e6dSmrg
6893e747e6dSmrg    savewidth = ip->width;
6903e747e6dSmrg    if (ip->twm_win)
6913e747e6dSmrg      SetupWindow (ip->twm_win,
6923e747e6dSmrg		   ip->twm_win->frame_x, ip->twm_win->frame_y,
6933e747e6dSmrg		   newwidth, ip->height + ip->twm_win->title_height, -1);
6943e747e6dSmrg    ip->width = savewidth;
6953e747e6dSmrg}
696