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