icons.c revision c2535118
13e747e6dSmrg/*
2ffd25bcaSmrg *
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
263e747e6dSmrg/**********************************************************************
273e747e6dSmrg *
283e747e6dSmrg * Icon releated routines
293e747e6dSmrg *
303e747e6dSmrg * 10-Apr-89 Tom LaStrange        Initial Version.
313e747e6dSmrg *
323e747e6dSmrg **********************************************************************/
333e747e6dSmrg
343e747e6dSmrg#include <stdio.h>
353e747e6dSmrg#include "twm.h"
363e747e6dSmrg#include "screen.h"
373e747e6dSmrg#include "icons.h"
383e747e6dSmrg#include "gram.h"
393e747e6dSmrg#include "parse.h"
403e747e6dSmrg#include "util.h"
413e747e6dSmrg
423e747e6dSmrg#define iconWidth(w)	(Scr->IconBorderWidth * 2 + w->icon_w_width)
433e747e6dSmrg#define iconHeight(w)	(Scr->IconBorderWidth * 2 + w->icon_w_height)
443e747e6dSmrg
453e747e6dSmrgstatic void splitEntry ( IconEntry *ie, int grav1, int grav2, int w, int h );
463e747e6dSmrgstatic IconEntry * FindIconEntry ( TwmWindow *tmp_win, IconRegion **irp );
473e747e6dSmrgstatic IconEntry * prevIconEntry ( IconEntry *ie, IconRegion *ir );
483e747e6dSmrgstatic void mergeEntries ( IconEntry *old, IconEntry *ie );
493e747e6dSmrg
503e747e6dSmrgstatic void
513e747e6dSmrgsplitEntry (IconEntry *ie, int grav1, int grav2, int w, int h)
523e747e6dSmrg{
533e747e6dSmrg    IconEntry	*new;
543e747e6dSmrg
553e747e6dSmrg    switch (grav1) {
563e747e6dSmrg    case D_NORTH:
573e747e6dSmrg    case D_SOUTH:
583e747e6dSmrg	if (w != ie->w)
593e747e6dSmrg	    splitEntry (ie, grav2, grav1, w, ie->h);
603e747e6dSmrg	if (h != ie->h) {
61c2535118Smrg	    new = malloc (sizeof (IconEntry));
623e747e6dSmrg	    new->twm_win = 0;
633e747e6dSmrg	    new->used = 0;
643e747e6dSmrg	    new->next = ie->next;
653e747e6dSmrg	    ie->next = new;
663e747e6dSmrg	    new->x = ie->x;
673e747e6dSmrg	    new->h = (ie->h - h);
683e747e6dSmrg	    new->w = ie->w;
693e747e6dSmrg	    ie->h = h;
703e747e6dSmrg	    if (grav1 == D_SOUTH) {
713e747e6dSmrg		new->y = ie->y;
723e747e6dSmrg		ie->y = new->y + new->h;
733e747e6dSmrg	    } else
743e747e6dSmrg		new->y = ie->y + ie->h;
753e747e6dSmrg	}
763e747e6dSmrg	break;
773e747e6dSmrg    case D_EAST:
783e747e6dSmrg    case D_WEST:
793e747e6dSmrg	if (h != ie->h)
803e747e6dSmrg	    splitEntry (ie, grav2, grav1, ie->w, h);
813e747e6dSmrg	if (w != ie->w) {
82c2535118Smrg	    new = malloc (sizeof (IconEntry));
833e747e6dSmrg	    new->twm_win = 0;
843e747e6dSmrg	    new->used = 0;
853e747e6dSmrg	    new->next = ie->next;
863e747e6dSmrg	    ie->next = new;
873e747e6dSmrg	    new->y = ie->y;
883e747e6dSmrg	    new->w = (ie->w - w);
893e747e6dSmrg	    new->h = ie->h;
903e747e6dSmrg	    ie->w = w;
913e747e6dSmrg	    if (grav1 == D_EAST) {
923e747e6dSmrg		new->x = ie->x;
933e747e6dSmrg		ie->x = new->x + new->w;
943e747e6dSmrg	    } else
953e747e6dSmrg		new->x = ie->x + ie->w;
963e747e6dSmrg	}
973e747e6dSmrg	break;
983e747e6dSmrg    }
993e747e6dSmrg}
1003e747e6dSmrg
101c2535118Smrgstatic inline int
1023e747e6dSmrgroundUp (int v, int multiple)
1033e747e6dSmrg{
1043e747e6dSmrg    return ((v + multiple - 1) / multiple) * multiple;
1053e747e6dSmrg}
1063e747e6dSmrg
107c2535118Smrgstatic void
1083e747e6dSmrgPlaceIcon(TwmWindow *tmp_win, int def_x, int def_y, int *final_x, int *final_y)
1093e747e6dSmrg{
1103e747e6dSmrg    IconRegion	*ir;
1113e747e6dSmrg    IconEntry	*ie;
1123e747e6dSmrg    int		w = 0, h = 0;
1133e747e6dSmrg
1143e747e6dSmrg    ie = 0;
1153e747e6dSmrg    for (ir = Scr->FirstRegion; ir; ir = ir->next) {
1163e747e6dSmrg	w = roundUp (iconWidth (tmp_win), ir->stepx);
1173e747e6dSmrg	h = roundUp (iconHeight (tmp_win), ir->stepy);
1183e747e6dSmrg	for (ie = ir->entries; ie; ie=ie->next) {
1193e747e6dSmrg	    if (ie->used)
1203e747e6dSmrg		continue;
1213e747e6dSmrg	    if (ie->w >= w && ie->h >= h)
1223e747e6dSmrg		break;
1233e747e6dSmrg	}
1243e747e6dSmrg	if (ie)
1253e747e6dSmrg	    break;
1263e747e6dSmrg    }
1273e747e6dSmrg    if (ie) {
1283e747e6dSmrg	splitEntry (ie, ir->grav1, ir->grav2, w, h);
1293e747e6dSmrg	ie->used = 1;
1303e747e6dSmrg	ie->twm_win = tmp_win;
1313e747e6dSmrg	*final_x = ie->x + (ie->w - iconWidth (tmp_win)) / 2;
1323e747e6dSmrg	*final_y = ie->y + (ie->h - iconHeight (tmp_win)) / 2;
1333e747e6dSmrg    } else {
1343e747e6dSmrg	*final_x = def_x;
1353e747e6dSmrg	*final_y = def_y;
1363e747e6dSmrg    }
1373e747e6dSmrg    return;
1383e747e6dSmrg}
1393e747e6dSmrg
1403e747e6dSmrgstatic IconEntry *
1413e747e6dSmrgFindIconEntry (TwmWindow *tmp_win, IconRegion **irp)
1423e747e6dSmrg{
1433e747e6dSmrg    IconRegion	*ir;
1443e747e6dSmrg    IconEntry	*ie;
1453e747e6dSmrg
1463e747e6dSmrg    for (ir = Scr->FirstRegion; ir; ir = ir->next) {
1473e747e6dSmrg	for (ie = ir->entries; ie; ie=ie->next)
1483e747e6dSmrg	    if (ie->twm_win == tmp_win) {
1493e747e6dSmrg		if (irp)
1503e747e6dSmrg		    *irp = ir;
1513e747e6dSmrg		return ie;
1523e747e6dSmrg	    }
1533e747e6dSmrg    }
1543e747e6dSmrg    return 0;
1553e747e6dSmrg}
1563e747e6dSmrg
1573e747e6dSmrgvoid
1583e747e6dSmrgIconUp (TwmWindow *tmp_win)
1593e747e6dSmrg{
1603e747e6dSmrg    int		x, y;
1613e747e6dSmrg    int		defx, defy;
1623e747e6dSmrg    struct IconRegion *ir;
1633e747e6dSmrg
1643e747e6dSmrg    /*
1653e747e6dSmrg     * If the client specified a particular location, let's use it (this might
1663e747e6dSmrg     * want to be an option at some point).  Otherwise, try to fit within the
1673e747e6dSmrg     * icon region.
1683e747e6dSmrg     */
1693e747e6dSmrg    if (tmp_win->wmhints && (tmp_win->wmhints->flags & IconPositionHint))
1703e747e6dSmrg      return;
1713e747e6dSmrg
1723e747e6dSmrg    if (tmp_win->icon_moved) {
1733e747e6dSmrg	if (!XGetGeometry (dpy, tmp_win->icon_w, &JunkRoot, &defx, &defy,
1743e747e6dSmrg			   &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth))
1753e747e6dSmrg	  return;
1763e747e6dSmrg
1773e747e6dSmrg	x = defx + ((int) JunkWidth) / 2;
1783e747e6dSmrg	y = defy + ((int) JunkHeight) / 2;
1793e747e6dSmrg
1803e747e6dSmrg	for (ir = Scr->FirstRegion; ir; ir = ir->next) {
1813e747e6dSmrg	    if (x >= ir->x && x < (ir->x + ir->w) &&
1823e747e6dSmrg		y >= ir->y && y < (ir->y + ir->h))
1833e747e6dSmrg	      break;
1843e747e6dSmrg	}
1853e747e6dSmrg	if (!ir) return;		/* outside icon regions, leave alone */
1863e747e6dSmrg    }
1873e747e6dSmrg
1883e747e6dSmrg    defx = -100;
1893e747e6dSmrg    defy = -100;
1903e747e6dSmrg    PlaceIcon(tmp_win, defx, defy, &x, &y);
1913e747e6dSmrg    if (x != defx || y != defy) {
1923e747e6dSmrg	XMoveWindow (dpy, tmp_win->icon_w, x, y);
1933e747e6dSmrg	tmp_win->icon_moved = FALSE;	/* since we've restored it */
1943e747e6dSmrg    }
1953e747e6dSmrg}
1963e747e6dSmrg
1973e747e6dSmrgstatic IconEntry *
1983e747e6dSmrgprevIconEntry (IconEntry *ie, IconRegion *ir)
1993e747e6dSmrg{
2003e747e6dSmrg    IconEntry	*ip;
2013e747e6dSmrg
2023e747e6dSmrg    if (ie == ir->entries)
2033e747e6dSmrg	return 0;
2043e747e6dSmrg    for (ip = ir->entries; ip->next != ie; ip=ip->next)
2053e747e6dSmrg	;
2063e747e6dSmrg    return ip;
2073e747e6dSmrg}
2083e747e6dSmrg
2093e747e6dSmrg/**
2103e747e6dSmrg * old is being freed; and is adjacent to ie.  Merge
2113e747e6dSmrg * regions together
2123e747e6dSmrg */
2133e747e6dSmrgstatic void
2143e747e6dSmrgmergeEntries (IconEntry *old, IconEntry *ie)
2153e747e6dSmrg{
2163e747e6dSmrg    if (old->y == ie->y) {
2173e747e6dSmrg	ie->w = old->w + ie->w;
2183e747e6dSmrg	if (old->x < ie->x)
2193e747e6dSmrg	    ie->x = old->x;
2203e747e6dSmrg    } else {
2213e747e6dSmrg	ie->h = old->h + ie->h;
2223e747e6dSmrg	if (old->y < ie->y)
2233e747e6dSmrg	    ie->y = old->y;
2243e747e6dSmrg    }
2253e747e6dSmrg}
2263e747e6dSmrg
2273e747e6dSmrgvoid
2283e747e6dSmrgIconDown (TwmWindow *tmp_win)
2293e747e6dSmrg{
2303e747e6dSmrg    IconEntry	*ie, *ip, *in;
2313e747e6dSmrg    IconRegion	*ir;
2323e747e6dSmrg
2333e747e6dSmrg    ie = FindIconEntry (tmp_win, &ir);
2343e747e6dSmrg    if (ie) {
2353e747e6dSmrg	ie->twm_win = 0;
2363e747e6dSmrg	ie->used = 0;
2373e747e6dSmrg	ip = prevIconEntry (ie, ir);
2383e747e6dSmrg	in = ie->next;
2393e747e6dSmrg	for (;;) {
2403e747e6dSmrg	    if (ip && ip->used == 0 &&
2413e747e6dSmrg	       ((ip->x == ie->x && ip->w == ie->w) ||
2423e747e6dSmrg	        (ip->y == ie->y && ip->h == ie->h)))
2433e747e6dSmrg	    {
2443e747e6dSmrg	    	ip->next = ie->next;
2453e747e6dSmrg	    	mergeEntries (ie, ip);
246c2535118Smrg		free (ie);
2473e747e6dSmrg		ie = ip;
2483e747e6dSmrg	    	ip = prevIconEntry (ip, ir);
2493e747e6dSmrg	    } else if (in && in->used == 0 &&
2503e747e6dSmrg	       ((in->x == ie->x && in->w == ie->w) ||
2513e747e6dSmrg	        (in->y == ie->y && in->h == ie->h)))
2523e747e6dSmrg	    {
2533e747e6dSmrg	    	ie->next = in->next;
2543e747e6dSmrg	    	mergeEntries (in, ie);
255c2535118Smrg		free (in);
2563e747e6dSmrg	    	in = ie->next;
2573e747e6dSmrg	    } else
2583e747e6dSmrg		break;
2593e747e6dSmrg	}
2603e747e6dSmrg    }
2613e747e6dSmrg}
2623e747e6dSmrg
2633e747e6dSmrgvoid
2643e747e6dSmrgAddIconRegion(char *geom, int grav1, int grav2, int stepx, int stepy)
2653e747e6dSmrg{
2663e747e6dSmrg    IconRegion *ir;
2673e747e6dSmrg    int mask;
2683e747e6dSmrg
269c2535118Smrg    ir = malloc(sizeof(IconRegion));
2703e747e6dSmrg    ir->next = NULL;
2713e747e6dSmrg    if (Scr->LastRegion)
2723e747e6dSmrg	Scr->LastRegion->next = ir;
2733e747e6dSmrg    Scr->LastRegion = ir;
2743e747e6dSmrg    if (!Scr->FirstRegion)
2753e747e6dSmrg	Scr->FirstRegion = ir;
2763e747e6dSmrg
2773e747e6dSmrg    ir->entries = NULL;
2783e747e6dSmrg    ir->grav1 = grav1;
2793e747e6dSmrg    ir->grav2 = grav2;
2803e747e6dSmrg    if (stepx <= 0)
2813e747e6dSmrg	stepx = 1;
2823e747e6dSmrg    if (stepy <= 0)
2833e747e6dSmrg	stepy = 1;
2843e747e6dSmrg    ir->stepx = stepx;
2853e747e6dSmrg    ir->stepy = stepy;
2863e747e6dSmrg    ir->x = ir->y = ir->w = ir->h = 0;
2873e747e6dSmrg
2883e747e6dSmrg    mask = XParseGeometry(geom, &ir->x, &ir->y, (unsigned int *)&ir->w, (unsigned int *)&ir->h);
2893e747e6dSmrg
2903e747e6dSmrg    if (mask & XNegative)
2913e747e6dSmrg	ir->x += Scr->MyDisplayWidth - ir->w;
2923e747e6dSmrg
2933e747e6dSmrg    if (mask & YNegative)
2943e747e6dSmrg	ir->y += Scr->MyDisplayHeight - ir->h;
295c2535118Smrg    ir->entries = malloc(sizeof(IconEntry));
2963e747e6dSmrg    ir->entries->next = 0;
2973e747e6dSmrg    ir->entries->x = ir->x;
2983e747e6dSmrg    ir->entries->y = ir->y;
2993e747e6dSmrg    ir->entries->w = ir->w;
3003e747e6dSmrg    ir->entries->h = ir->h;
3013e747e6dSmrg    ir->entries->twm_win = 0;
3023e747e6dSmrg    ir->entries->used = 0;
3033e747e6dSmrg}
3043e747e6dSmrg
3053e747e6dSmrg#ifdef comment
3063e747e6dSmrgvoid
3073e747e6dSmrgFreeIconEntries (IconRegion *ir)
3083e747e6dSmrg{
3093e747e6dSmrg    IconEntry	*ie, *tmp;
3103e747e6dSmrg
3113e747e6dSmrg    for (ie = ir->entries; ie; ie=tmp)
3123e747e6dSmrg    {
3133e747e6dSmrg	tmp = ie->next;
314c2535118Smrg	free (ie);
3153e747e6dSmrg    }
3163e747e6dSmrg}
3173e747e6dSmrg
3183e747e6dSmrgvoid
319c2535118SmrgFreeIconRegions(void)
3203e747e6dSmrg{
3213e747e6dSmrg    IconRegion *ir, *tmp;
3223e747e6dSmrg
3233e747e6dSmrg    for (ir = Scr->FirstRegion; ir != NULL;)
3243e747e6dSmrg    {
3253e747e6dSmrg	tmp = ir;
3263e747e6dSmrg	FreeIconEntries (ir);
3273e747e6dSmrg	ir = ir->next;
328c2535118Smrg	free(tmp);
3293e747e6dSmrg    }
3303e747e6dSmrg    Scr->FirstRegion = NULL;
3313e747e6dSmrg    Scr->LastRegion = NULL;
3323e747e6dSmrg}
3333e747e6dSmrg#endif
3343e747e6dSmrg
3353e747e6dSmrgvoid
3363e747e6dSmrgCreateIconWindow(TwmWindow *tmp_win, int def_x, int def_y)
3373e747e6dSmrg{
3383e747e6dSmrg    unsigned long event_mask;
3393e747e6dSmrg    unsigned long valuemask;		/* mask for create windows */
3403e747e6dSmrg    XSetWindowAttributes attributes;	/* attributes for create windows */
3413e747e6dSmrg    Pixmap pm = None;			/* tmp pixmap variable */
3423e747e6dSmrg    int final_x, final_y;
3433e747e6dSmrg    int x;
3443e747e6dSmrg
3453e747e6dSmrg
3463e747e6dSmrg    FB(tmp_win->iconc.fore, tmp_win->iconc.back);
3473e747e6dSmrg
3483e747e6dSmrg    tmp_win->forced = FALSE;
3493e747e6dSmrg    tmp_win->icon_not_ours = FALSE;
3503e747e6dSmrg
351ffd25bcaSmrg    /* now go through the steps to get an icon window,  if ForceIcon is
3523e747e6dSmrg     * set, then no matter what else is defined, the bitmap from the
3533e747e6dSmrg     * .twmrc file is used
3543e747e6dSmrg     */
3553e747e6dSmrg    if (Scr->ForceIcon)
3563e747e6dSmrg    {
3573e747e6dSmrg	char *icon_name;
3583e747e6dSmrg	Pixmap bm;
3593e747e6dSmrg
3603e747e6dSmrg	icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
3613e747e6dSmrg        if (icon_name == NULL)
3623e747e6dSmrg	    icon_name = LookInList(Scr->IconNames, tmp_win->full_name,
3633e747e6dSmrg				   &tmp_win->class);
3643e747e6dSmrg
3653e747e6dSmrg	bm = None;
3663e747e6dSmrg	if (icon_name != NULL)
3673e747e6dSmrg	{
3683e747e6dSmrg	    if ((bm = (Pixmap)LookInNameList(Scr->Icons, icon_name)) == None)
3693e747e6dSmrg	    {
3703e747e6dSmrg		if ((bm = GetBitmap (icon_name)) != None)
3713e747e6dSmrg		    AddToList(&Scr->Icons, icon_name, (char *)bm);
3723e747e6dSmrg	    }
3733e747e6dSmrg	}
3743e747e6dSmrg
3753e747e6dSmrg	if (bm != None)
3763e747e6dSmrg	{
3773e747e6dSmrg	    XGetGeometry(dpy, bm, &JunkRoot, &JunkX, &JunkY,
3783e747e6dSmrg		(unsigned int *) &tmp_win->icon_width, (unsigned int *)&tmp_win->icon_height,
3793e747e6dSmrg		&JunkBW, &JunkDepth);
3803e747e6dSmrg
3813e747e6dSmrg	    pm = XCreatePixmap(dpy, Scr->Root, tmp_win->icon_width,
3823e747e6dSmrg		tmp_win->icon_height, Scr->d_depth);
3833e747e6dSmrg
3843e747e6dSmrg	    /* the copy plane works on color ! */
3853e747e6dSmrg	    XCopyPlane(dpy, bm, pm, Scr->NormalGC,
3863e747e6dSmrg		0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
3873e747e6dSmrg
3883e747e6dSmrg	    tmp_win->forced = TRUE;
3893e747e6dSmrg	}
3903e747e6dSmrg    }
3913e747e6dSmrg
3923e747e6dSmrg    /* if the pixmap is still NULL, we didn't get one from the above code,
3933e747e6dSmrg     * that could mean that ForceIcon was not set, or that the window
3943e747e6dSmrg     * was not in the Icons list, now check the WM hints for an icon
3953e747e6dSmrg     */
3963e747e6dSmrg    if (pm == None && tmp_win->wmhints &&
3973e747e6dSmrg	tmp_win->wmhints->flags & IconPixmapHint)
3983e747e6dSmrg    {
399ffd25bcaSmrg
4003e747e6dSmrg	XGetGeometry(dpy,   tmp_win->wmhints->icon_pixmap,
4013e747e6dSmrg             &JunkRoot, &JunkX, &JunkY,
4023e747e6dSmrg	     (unsigned int *)&tmp_win->icon_width, (unsigned int *)&tmp_win->icon_height, &JunkBW, &JunkDepth);
4033e747e6dSmrg
4043e747e6dSmrg	pm = XCreatePixmap(dpy, Scr->Root,
4053e747e6dSmrg			   tmp_win->icon_width, tmp_win->icon_height,
4063e747e6dSmrg			   Scr->d_depth);
4073e747e6dSmrg
4083e747e6dSmrg	XCopyPlane(dpy, tmp_win->wmhints->icon_pixmap, pm, Scr->NormalGC,
4093e747e6dSmrg	    0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
4103e747e6dSmrg    }
4113e747e6dSmrg
412ffd25bcaSmrg    /* if we still haven't got an icon, let's look in the Icon list
4133e747e6dSmrg     * if ForceIcon is not set
4143e747e6dSmrg     */
4153e747e6dSmrg    if (pm == None && !Scr->ForceIcon)
4163e747e6dSmrg    {
4173e747e6dSmrg	char *icon_name;
4183e747e6dSmrg	Pixmap bm;
4193e747e6dSmrg
4203e747e6dSmrg	icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
4213e747e6dSmrg        if (icon_name == NULL)
4223e747e6dSmrg	    icon_name = LookInList(Scr->IconNames, tmp_win->full_name,
4233e747e6dSmrg				   &tmp_win->class);
4243e747e6dSmrg
4253e747e6dSmrg	bm = None;
4263e747e6dSmrg	if (icon_name != NULL)
4273e747e6dSmrg	{
4283e747e6dSmrg	    if ((bm = (Pixmap)LookInNameList(Scr->Icons, icon_name)) == None)
4293e747e6dSmrg	    {
4303e747e6dSmrg		if ((bm = GetBitmap (icon_name)) != None)
4313e747e6dSmrg		    AddToList(&Scr->Icons, icon_name, (char *)bm);
4323e747e6dSmrg	    }
4333e747e6dSmrg	}
4343e747e6dSmrg
4353e747e6dSmrg	if (bm != None)
4363e747e6dSmrg	{
4373e747e6dSmrg	    XGetGeometry(dpy, bm, &JunkRoot, &JunkX, &JunkY,
4383e747e6dSmrg		(unsigned int *)&tmp_win->icon_width, (unsigned int *)&tmp_win->icon_height,
4393e747e6dSmrg		&JunkBW, &JunkDepth);
4403e747e6dSmrg
4413e747e6dSmrg	    pm = XCreatePixmap(dpy, Scr->Root, tmp_win->icon_width,
4423e747e6dSmrg		tmp_win->icon_height, Scr->d_depth);
4433e747e6dSmrg
4443e747e6dSmrg	    /* the copy plane works on color ! */
4453e747e6dSmrg	    XCopyPlane(dpy, bm, pm, Scr->NormalGC,
4463e747e6dSmrg		0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
4473e747e6dSmrg	}
4483e747e6dSmrg    }
4493e747e6dSmrg
4503e747e6dSmrg    /* if we still don't have an icon, assign the UnknownIcon */
4513e747e6dSmrg
4523e747e6dSmrg    if (pm == None && Scr->UnknownPm != None)
4533e747e6dSmrg    {
4543e747e6dSmrg	tmp_win->icon_width = Scr->UnknownWidth;
4553e747e6dSmrg	tmp_win->icon_height = Scr->UnknownHeight;
4563e747e6dSmrg
4573e747e6dSmrg	pm = XCreatePixmap(dpy, Scr->Root, tmp_win->icon_width,
4583e747e6dSmrg	    tmp_win->icon_height, Scr->d_depth);
4593e747e6dSmrg
4603e747e6dSmrg	/* the copy plane works on color ! */
4613e747e6dSmrg	XCopyPlane(dpy, Scr->UnknownPm, pm, Scr->NormalGC,
4623e747e6dSmrg	    0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
4633e747e6dSmrg    }
4643e747e6dSmrg
4653e747e6dSmrg    if (pm == None)
4663e747e6dSmrg    {
4673e747e6dSmrg	tmp_win->icon_height = 0;
4683e747e6dSmrg	tmp_win->icon_width = 0;
4693e747e6dSmrg	valuemask = 0;
4703e747e6dSmrg    }
4713e747e6dSmrg    else
4723e747e6dSmrg    {
4733e747e6dSmrg	valuemask = CWBackPixmap;
4743e747e6dSmrg	attributes.background_pixmap = pm;
4753e747e6dSmrg    }
4763e747e6dSmrg
4773e747e6dSmrg    tmp_win->icon_w_width = MyFont_TextWidth(&Scr->IconFont,
4783e747e6dSmrg	tmp_win->icon_name, strlen(tmp_win->icon_name));
4793e747e6dSmrg
4803e747e6dSmrg    tmp_win->icon_w_width += 6;
4813e747e6dSmrg    if (tmp_win->icon_w_width < tmp_win->icon_width)
4823e747e6dSmrg    {
4833e747e6dSmrg	tmp_win->icon_x = (tmp_win->icon_width - tmp_win->icon_w_width)/2;
4843e747e6dSmrg	tmp_win->icon_x += 3;
4853e747e6dSmrg	tmp_win->icon_w_width = tmp_win->icon_width;
4863e747e6dSmrg    }
4873e747e6dSmrg    else
4883e747e6dSmrg    {
4893e747e6dSmrg	tmp_win->icon_x = 3;
4903e747e6dSmrg    }
4913e747e6dSmrg    tmp_win->icon_y = tmp_win->icon_height + Scr->IconFont.height;
4923e747e6dSmrg    tmp_win->icon_w_height = tmp_win->icon_height + Scr->IconFont.height + 4;
4933e747e6dSmrg
4943e747e6dSmrg    event_mask = 0;
4953e747e6dSmrg    if (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint)
4963e747e6dSmrg    {
4973e747e6dSmrg	tmp_win->icon_w = tmp_win->wmhints->icon_window;
4983e747e6dSmrg	if (tmp_win->forced ||
4993e747e6dSmrg	    XGetGeometry(dpy, tmp_win->icon_w, &JunkRoot, &JunkX, &JunkY,
5003e747e6dSmrg		     (unsigned int *)&tmp_win->icon_w_width, (unsigned int *)&tmp_win->icon_w_height,
5013e747e6dSmrg		     &JunkBW, &JunkDepth) == 0)
5023e747e6dSmrg	{
5033e747e6dSmrg	    tmp_win->icon_w = None;
5043e747e6dSmrg	    tmp_win->wmhints->flags &= ~IconWindowHint;
5053e747e6dSmrg	}
5063e747e6dSmrg	else
5073e747e6dSmrg	{
5083e747e6dSmrg	    tmp_win->icon_not_ours = TRUE;
5093e747e6dSmrg	    event_mask = EnterWindowMask | LeaveWindowMask;
5103e747e6dSmrg	}
5113e747e6dSmrg    }
5123e747e6dSmrg    else
5133e747e6dSmrg    {
5143e747e6dSmrg	tmp_win->icon_w = None;
5153e747e6dSmrg    }
5163e747e6dSmrg
5173e747e6dSmrg    if (tmp_win->icon_w == None)
5183e747e6dSmrg    {
5193e747e6dSmrg	tmp_win->icon_w = XCreateSimpleWindow(dpy, Scr->Root,
5203e747e6dSmrg	    0,0,
5213e747e6dSmrg	    tmp_win->icon_w_width, tmp_win->icon_w_height,
5223e747e6dSmrg	    Scr->IconBorderWidth, tmp_win->icon_border, tmp_win->iconc.back);
5233e747e6dSmrg	event_mask = ExposureMask;
5243e747e6dSmrg    }
5253e747e6dSmrg
5263e747e6dSmrg    XSelectInput (dpy, tmp_win->icon_w,
5273e747e6dSmrg		  KeyPressMask | ButtonPressMask | ButtonReleaseMask |
5283e747e6dSmrg		  event_mask);
5293e747e6dSmrg
5303e747e6dSmrg    tmp_win->icon_bm_w = None;
5313e747e6dSmrg    if (pm != None &&
5323e747e6dSmrg	(! (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint)))
5333e747e6dSmrg    {
5343e747e6dSmrg	int y;
5353e747e6dSmrg
5363e747e6dSmrg	y = 0;
5373e747e6dSmrg	if (tmp_win->icon_w_width == tmp_win->icon_width)
5383e747e6dSmrg	    x = 0;
5393e747e6dSmrg	else
5403e747e6dSmrg	    x = (tmp_win->icon_w_width - tmp_win->icon_width)/2;
5413e747e6dSmrg
5423e747e6dSmrg	tmp_win->icon_bm_w = XCreateWindow (dpy, tmp_win->icon_w, x, y,
5433e747e6dSmrg					    (unsigned int)tmp_win->icon_width,
5443e747e6dSmrg					    (unsigned int)tmp_win->icon_height,
5453e747e6dSmrg					    (unsigned int) 0, Scr->d_depth,
5463e747e6dSmrg					    (unsigned int) CopyFromParent,
5473e747e6dSmrg					    Scr->d_visual, valuemask,
5483e747e6dSmrg					    &attributes);
5493e747e6dSmrg    }
5503e747e6dSmrg
551ffd25bcaSmrg    /* I need to figure out where to put the icon window now, because
5523e747e6dSmrg     * getting here means that I am going to make the icon visible
5533e747e6dSmrg     */
5543e747e6dSmrg    if (tmp_win->wmhints &&
5553e747e6dSmrg	tmp_win->wmhints->flags & IconPositionHint)
5563e747e6dSmrg    {
5573e747e6dSmrg	final_x = tmp_win->wmhints->icon_x;
5583e747e6dSmrg	final_y = tmp_win->wmhints->icon_y;
5593e747e6dSmrg    }
5603e747e6dSmrg    else
5613e747e6dSmrg    {
5623e747e6dSmrg	PlaceIcon(tmp_win, def_x, def_y, &final_x, &final_y);
5633e747e6dSmrg    }
5643e747e6dSmrg
5653e747e6dSmrg    if (final_x > Scr->MyDisplayWidth)
5663e747e6dSmrg	final_x = Scr->MyDisplayWidth - tmp_win->icon_w_width -
5673e747e6dSmrg	    (2 * Scr->IconBorderWidth);
5683e747e6dSmrg
5693e747e6dSmrg    if (final_y > Scr->MyDisplayHeight)
5703e747e6dSmrg	final_y = Scr->MyDisplayHeight - tmp_win->icon_height -
5713e747e6dSmrg	    Scr->IconFont.height - 4 - (2 * Scr->IconBorderWidth);
5723e747e6dSmrg
5733e747e6dSmrg    XMoveWindow(dpy, tmp_win->icon_w, final_x, final_y);
5743e747e6dSmrg    tmp_win->iconified = TRUE;
5753e747e6dSmrg
5763e747e6dSmrg    XMapSubwindows(dpy, tmp_win->icon_w);
5773e747e6dSmrg    XSaveContext(dpy, tmp_win->icon_w, TwmContext, (caddr_t)tmp_win);
5783e747e6dSmrg    XSaveContext(dpy, tmp_win->icon_w, ScreenContext, (caddr_t)Scr);
5793e747e6dSmrg    XDefineCursor(dpy, tmp_win->icon_w, Scr->IconCursor);
5803e747e6dSmrg    if (pm) XFreePixmap (dpy, pm);
5813e747e6dSmrg    return;
5823e747e6dSmrg}
583