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 *
28f66df612Smrg * Icon related 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 "parse.h"
393e747e6dSmrg#include "util.h"
403e747e6dSmrg
41f66df612Smrg#define iconWidth(w)    (Scr->IconBorderWidth * 2 + w->icon_w_width)
42f66df612Smrg#define iconHeight(w)   (Scr->IconBorderWidth * 2 + w->icon_w_height)
433e747e6dSmrg
44f66df612Smrgstatic void splitEntry(IconEntry *ie, int grav1, int grav2, int w, int h);
45f66df612Smrgstatic IconEntry *FindIconEntry(TwmWindow *tmp_win, IconRegion **irp);
46f66df612Smrgstatic IconEntry *prevIconEntry(IconEntry *ie, IconRegion *ir);
47f66df612Smrgstatic void mergeEntries(IconEntry *old, IconEntry *ie);
483e747e6dSmrg
493e747e6dSmrgstatic void
50f66df612SmrgsplitEntry(IconEntry *ie, int grav1, int grav2, int w, int h)
513e747e6dSmrg{
526d8e82c3Smrg    IconEntry *entry;
533e747e6dSmrg
543e747e6dSmrg    switch (grav1) {
553e747e6dSmrg    case D_NORTH:
563e747e6dSmrg    case D_SOUTH:
57f66df612Smrg        if (w != ie->w)
58f66df612Smrg            splitEntry(ie, grav2, grav1, w, ie->h);
59f66df612Smrg        if (h != ie->h) {
606d8e82c3Smrg            entry = (IconEntry *) malloc(sizeof(IconEntry));
616d8e82c3Smrg            entry->twm_win = NULL;
626d8e82c3Smrg            entry->used = 0;
636d8e82c3Smrg            entry->next = ie->next;
646d8e82c3Smrg            ie->next = entry;
656d8e82c3Smrg            entry->x = ie->x;
666d8e82c3Smrg            entry->h = (ie->h - h);
676d8e82c3Smrg            entry->w = ie->w;
68f66df612Smrg            ie->h = h;
69f66df612Smrg            if (grav1 == D_SOUTH) {
706d8e82c3Smrg                entry->y = ie->y;
716d8e82c3Smrg                ie->y = entry->y + entry->h;
72f66df612Smrg            }
73f66df612Smrg            else
746d8e82c3Smrg                entry->y = ie->y + ie->h;
75f66df612Smrg        }
76f66df612Smrg        break;
773e747e6dSmrg    case D_EAST:
783e747e6dSmrg    case D_WEST:
79f66df612Smrg        if (h != ie->h)
80f66df612Smrg            splitEntry(ie, grav2, grav1, ie->w, h);
81f66df612Smrg        if (w != ie->w) {
826d8e82c3Smrg            entry = (IconEntry *) malloc(sizeof(IconEntry));
836d8e82c3Smrg            entry->twm_win = NULL;
846d8e82c3Smrg            entry->used = 0;
856d8e82c3Smrg            entry->next = ie->next;
866d8e82c3Smrg            ie->next = entry;
876d8e82c3Smrg            entry->y = ie->y;
886d8e82c3Smrg            entry->w = (ie->w - w);
896d8e82c3Smrg            entry->h = ie->h;
90f66df612Smrg            ie->w = w;
91f66df612Smrg            if (grav1 == D_EAST) {
926d8e82c3Smrg                entry->x = ie->x;
936d8e82c3Smrg                ie->x = entry->x + entry->w;
94f66df612Smrg            }
95f66df612Smrg            else
966d8e82c3Smrg                entry->x = ie->x + ie->w;
97f66df612Smrg        }
98f66df612Smrg        break;
993e747e6dSmrg    }
1003e747e6dSmrg}
1013e747e6dSmrg
102c2535118Smrgstatic inline int
103f66df612SmrgroundUp(int v, int multiple)
1043e747e6dSmrg{
1053e747e6dSmrg    return ((v + multiple - 1) / multiple) * multiple;
1063e747e6dSmrg}
1073e747e6dSmrg
108c2535118Smrgstatic void
1093e747e6dSmrgPlaceIcon(TwmWindow *tmp_win, int def_x, int def_y, int *final_x, int *final_y)
1103e747e6dSmrg{
111f66df612Smrg    IconRegion *ir;
112f66df612Smrg    IconEntry *ie;
113f66df612Smrg    int w = 0, h = 0;
1143e747e6dSmrg
1156d8e82c3Smrg    ie = NULL;
1163e747e6dSmrg    for (ir = Scr->FirstRegion; ir; ir = ir->next) {
117f66df612Smrg        w = roundUp(iconWidth(tmp_win), ir->stepx);
118f66df612Smrg        h = roundUp(iconHeight(tmp_win), ir->stepy);
119f66df612Smrg        for (ie = ir->entries; ie; ie = ie->next) {
120f66df612Smrg            if (ie->used)
121f66df612Smrg                continue;
122f66df612Smrg            if (ie->w >= w && ie->h >= h)
123f66df612Smrg                break;
124f66df612Smrg        }
125f66df612Smrg        if (ie)
126f66df612Smrg            break;
1273e747e6dSmrg    }
1283e747e6dSmrg    if (ie) {
129f66df612Smrg        splitEntry(ie, ir->grav1, ir->grav2, w, h);
130f66df612Smrg        ie->used = 1;
131f66df612Smrg        ie->twm_win = tmp_win;
132f66df612Smrg        *final_x = ie->x + (ie->w - iconWidth(tmp_win)) / 2;
133f66df612Smrg        *final_y = ie->y + (ie->h - iconHeight(tmp_win)) / 2;
134f66df612Smrg    }
135f66df612Smrg    else {
136f66df612Smrg        *final_x = def_x;
137f66df612Smrg        *final_y = def_y;
1383e747e6dSmrg    }
1393e747e6dSmrg    return;
1403e747e6dSmrg}
1413e747e6dSmrg
1423e747e6dSmrgstatic IconEntry *
143f66df612SmrgFindIconEntry(TwmWindow *tmp_win, IconRegion **irp)
1443e747e6dSmrg{
145f66df612Smrg    IconRegion *ir;
146f66df612Smrg    IconEntry *ie;
1473e747e6dSmrg
1483e747e6dSmrg    for (ir = Scr->FirstRegion; ir; ir = ir->next) {
149f66df612Smrg        for (ie = ir->entries; ie; ie = ie->next)
150f66df612Smrg            if (ie->twm_win == tmp_win) {
151f66df612Smrg                if (irp)
152f66df612Smrg                    *irp = ir;
153f66df612Smrg                return ie;
154f66df612Smrg            }
1553e747e6dSmrg    }
1566d8e82c3Smrg    return NULL;
1573e747e6dSmrg}
1583e747e6dSmrg
1593e747e6dSmrgvoid
160f66df612SmrgIconUp(TwmWindow *tmp_win)
1613e747e6dSmrg{
162f66df612Smrg    int x, y;
163f66df612Smrg    int defx, defy;
1643e747e6dSmrg    struct IconRegion *ir;
1656d8e82c3Smrg    unsigned udummy = 0;
1666d8e82c3Smrg    Window wdummy = None;
1673e747e6dSmrg
1683e747e6dSmrg    /*
1693e747e6dSmrg     * If the client specified a particular location, let's use it (this might
1703e747e6dSmrg     * want to be an option at some point).  Otherwise, try to fit within the
1713e747e6dSmrg     * icon region.
1723e747e6dSmrg     */
1733e747e6dSmrg    if (tmp_win->wmhints && (tmp_win->wmhints->flags & IconPositionHint))
174f66df612Smrg        return;
1753e747e6dSmrg
1763e747e6dSmrg    if (tmp_win->icon_moved) {
1776d8e82c3Smrg        unsigned width = 0;
1786d8e82c3Smrg        unsigned height = 0;
1796d8e82c3Smrg
1806d8e82c3Smrg        if (!XGetGeometry(dpy, tmp_win->icon_w, &wdummy, &defx, &defy,
1816d8e82c3Smrg                          &width, &height, &udummy, &udummy))
182f66df612Smrg            return;
183f66df612Smrg
1846d8e82c3Smrg        x = defx + ((int) width) / 2;
1856d8e82c3Smrg        y = defy + ((int) height) / 2;
186f66df612Smrg
187f66df612Smrg        for (ir = Scr->FirstRegion; ir; ir = ir->next) {
188f66df612Smrg            if (x >= ir->x && x < (ir->x + ir->w) &&
189f66df612Smrg                y >= ir->y && y < (ir->y + ir->h))
190f66df612Smrg                break;
191f66df612Smrg        }
192f66df612Smrg        if (!ir)
193f66df612Smrg            return;             /* outside icon regions, leave alone */
1943e747e6dSmrg    }
1953e747e6dSmrg
1963e747e6dSmrg    defx = -100;
1973e747e6dSmrg    defy = -100;
1983e747e6dSmrg    PlaceIcon(tmp_win, defx, defy, &x, &y);
1993e747e6dSmrg    if (x != defx || y != defy) {
200f66df612Smrg        XMoveWindow(dpy, tmp_win->icon_w, x, y);
201f66df612Smrg        tmp_win->icon_moved = FALSE;    /* since we've restored it */
2023e747e6dSmrg    }
2033e747e6dSmrg}
2043e747e6dSmrg
2053e747e6dSmrgstatic IconEntry *
206f66df612SmrgprevIconEntry(IconEntry *ie, IconRegion *ir)
2073e747e6dSmrg{
208f66df612Smrg    IconEntry *ip;
2093e747e6dSmrg
2103e747e6dSmrg    if (ie == ir->entries)
2116d8e82c3Smrg        return NULL;
212f66df612Smrg    for (ip = ir->entries; ip->next != ie; ip = ip->next);
2133e747e6dSmrg    return ip;
2143e747e6dSmrg}
2153e747e6dSmrg
2163e747e6dSmrg/**
2173e747e6dSmrg * old is being freed; and is adjacent to ie.  Merge
2183e747e6dSmrg * regions together
2193e747e6dSmrg */
2203e747e6dSmrgstatic void
221f66df612SmrgmergeEntries(IconEntry *old, IconEntry *ie)
2223e747e6dSmrg{
2233e747e6dSmrg    if (old->y == ie->y) {
224f66df612Smrg        ie->w = old->w + ie->w;
225f66df612Smrg        if (old->x < ie->x)
226f66df612Smrg            ie->x = old->x;
227f66df612Smrg    }
228f66df612Smrg    else {
229f66df612Smrg        ie->h = old->h + ie->h;
230f66df612Smrg        if (old->y < ie->y)
231f66df612Smrg            ie->y = old->y;
2323e747e6dSmrg    }
2333e747e6dSmrg}
2343e747e6dSmrg
2353e747e6dSmrgvoid
236f66df612SmrgIconDown(TwmWindow *tmp_win)
2373e747e6dSmrg{
238f66df612Smrg    IconEntry *ie, *ip, *in;
239f66df612Smrg    IconRegion *ir;
2403e747e6dSmrg
241f66df612Smrg    ie = FindIconEntry(tmp_win, &ir);
2423e747e6dSmrg    if (ie) {
2436d8e82c3Smrg        ie->twm_win = NULL;
244f66df612Smrg        ie->used = 0;
245f66df612Smrg        ip = prevIconEntry(ie, ir);
246f66df612Smrg        in = ie->next;
247f66df612Smrg        for (;;) {
248f66df612Smrg            if (ip && ip->used == 0 &&
249f66df612Smrg                ((ip->x == ie->x && ip->w == ie->w) ||
250f66df612Smrg                 (ip->y == ie->y && ip->h == ie->h))) {
251f66df612Smrg                ip->next = ie->next;
252f66df612Smrg                mergeEntries(ie, ip);
253f66df612Smrg                free(ie);
254f66df612Smrg                ie = ip;
255f66df612Smrg                ip = prevIconEntry(ip, ir);
256f66df612Smrg            }
257f66df612Smrg            else if (in && in->used == 0 &&
258f66df612Smrg                     ((in->x == ie->x && in->w == ie->w) ||
259f66df612Smrg                      (in->y == ie->y && in->h == ie->h))) {
260f66df612Smrg                ie->next = in->next;
261f66df612Smrg                mergeEntries(in, ie);
262f66df612Smrg                free(in);
263f66df612Smrg                in = ie->next;
264f66df612Smrg            }
265f66df612Smrg            else
266f66df612Smrg                break;
267f66df612Smrg        }
2683e747e6dSmrg    }
2693e747e6dSmrg}
2703e747e6dSmrg
2713e747e6dSmrgvoid
2723e747e6dSmrgAddIconRegion(char *geom, int grav1, int grav2, int stepx, int stepy)
2733e747e6dSmrg{
2743e747e6dSmrg    IconRegion *ir;
2753e747e6dSmrg    int mask;
2763e747e6dSmrg
2776d8e82c3Smrg    ir = (IconRegion *) malloc(sizeof(IconRegion));
2783e747e6dSmrg    ir->next = NULL;
2793e747e6dSmrg    if (Scr->LastRegion)
280f66df612Smrg        Scr->LastRegion->next = ir;
2813e747e6dSmrg    Scr->LastRegion = ir;
2823e747e6dSmrg    if (!Scr->FirstRegion)
283f66df612Smrg        Scr->FirstRegion = ir;
2843e747e6dSmrg
2853e747e6dSmrg    ir->entries = NULL;
2863e747e6dSmrg    ir->grav1 = grav1;
2873e747e6dSmrg    ir->grav2 = grav2;
2883e747e6dSmrg    if (stepx <= 0)
289f66df612Smrg        stepx = 1;
2903e747e6dSmrg    if (stepy <= 0)
291f66df612Smrg        stepy = 1;
2923e747e6dSmrg    ir->stepx = stepx;
2933e747e6dSmrg    ir->stepy = stepy;
2943e747e6dSmrg    ir->x = ir->y = ir->w = ir->h = 0;
2953e747e6dSmrg
296f66df612Smrg    mask =
297f66df612Smrg        XParseGeometry(geom, &ir->x, &ir->y, (unsigned int *) &ir->w,
298f66df612Smrg                       (unsigned int *) &ir->h);
2993e747e6dSmrg
3003e747e6dSmrg    if (mask & XNegative)
301f66df612Smrg        ir->x += Scr->MyDisplayWidth - ir->w;
3023e747e6dSmrg
3033e747e6dSmrg    if (mask & YNegative)
304f66df612Smrg        ir->y += Scr->MyDisplayHeight - ir->h;
3056d8e82c3Smrg    ir->entries = (IconEntry *) malloc(sizeof(IconEntry));
3066d8e82c3Smrg    ir->entries->next = NULL;
3073e747e6dSmrg    ir->entries->x = ir->x;
3083e747e6dSmrg    ir->entries->y = ir->y;
3093e747e6dSmrg    ir->entries->w = ir->w;
3103e747e6dSmrg    ir->entries->h = ir->h;
3116d8e82c3Smrg    ir->entries->twm_win = NULL;
3123e747e6dSmrg    ir->entries->used = 0;
3133e747e6dSmrg}
3143e747e6dSmrg
3153e747e6dSmrgvoid
3163e747e6dSmrgCreateIconWindow(TwmWindow *tmp_win, int def_x, int def_y)
3173e747e6dSmrg{
3183e747e6dSmrg    unsigned long event_mask;
319f66df612Smrg    unsigned long valuemask;    /* mask for create windows */
320f66df612Smrg    XSetWindowAttributes attributes;    /* attributes for create windows */
321f66df612Smrg    Pixmap pm = None;           /* tmp pixmap variable */
3223e747e6dSmrg    int final_x, final_y;
3236d8e82c3Smrg    int dummy = 0;
3246d8e82c3Smrg    unsigned udummy = 0;
3256d8e82c3Smrg    Window wdummy = None;
3263e747e6dSmrg
3273e747e6dSmrg    FB(tmp_win->iconc.fore, tmp_win->iconc.back);
3283e747e6dSmrg
3293e747e6dSmrg    tmp_win->forced = FALSE;
3303e747e6dSmrg    tmp_win->icon_not_ours = FALSE;
3313e747e6dSmrg
332ffd25bcaSmrg    /* now go through the steps to get an icon window,  if ForceIcon is
3333e747e6dSmrg     * set, then no matter what else is defined, the bitmap from the
3343e747e6dSmrg     * .twmrc file is used
3353e747e6dSmrg     */
336f66df612Smrg    if (Scr->ForceIcon) {
337f66df612Smrg        char *icon_name;
338f66df612Smrg        Pixmap bm;
3393e747e6dSmrg
340f66df612Smrg        icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
3413e747e6dSmrg        if (icon_name == NULL)
342f66df612Smrg            icon_name = LookInList(Scr->IconNames, tmp_win->full_name,
3436d8e82c3Smrg                                   &tmp_win->xclass);
344f66df612Smrg
345f66df612Smrg        bm = None;
346f66df612Smrg        if (icon_name != NULL) {
347f66df612Smrg            if ((bm =
348f66df612Smrg                 (Pixmap) (void *) LookInNameList(Scr->Icons,
349f66df612Smrg                                                  icon_name)) == None) {
350f66df612Smrg                if ((bm = GetBitmap(icon_name)) != None)
351f66df612Smrg                    AddToList(&Scr->Icons, icon_name, (char *) bm);
352f66df612Smrg            }
353f66df612Smrg        }
354f66df612Smrg
355f66df612Smrg        if (bm != None) {
3566d8e82c3Smrg            XGetGeometry(dpy, bm, &wdummy, &dummy, &dummy,
357f66df612Smrg                         (unsigned int *) &tmp_win->icon_width,
3586d8e82c3Smrg                         (unsigned int *) &tmp_win->icon_height, &udummy,
3596d8e82c3Smrg                         &udummy);
360f66df612Smrg
361f66df612Smrg            pm = XCreatePixmap(dpy, Scr->Root, (unsigned) tmp_win->icon_width,
362f66df612Smrg                               (unsigned) tmp_win->icon_height,
363f66df612Smrg                               (unsigned) Scr->d_depth);
364f66df612Smrg
365f66df612Smrg            /* the copy plane works on color ! */
366f66df612Smrg            XCopyPlane(dpy, bm, pm, Scr->NormalGC,
367f66df612Smrg                       0, 0, (unsigned) tmp_win->icon_width,
368f66df612Smrg                       (unsigned) tmp_win->icon_height, 0, 0, 1);
369f66df612Smrg
370f66df612Smrg            tmp_win->forced = TRUE;
371f66df612Smrg        }
3723e747e6dSmrg    }
3733e747e6dSmrg
3743e747e6dSmrg    /* if the pixmap is still NULL, we didn't get one from the above code,
3753e747e6dSmrg     * that could mean that ForceIcon was not set, or that the window
3763e747e6dSmrg     * was not in the Icons list, now check the WM hints for an icon
3773e747e6dSmrg     */
3783e747e6dSmrg    if (pm == None && tmp_win->wmhints &&
379f66df612Smrg        tmp_win->wmhints->flags & IconPixmapHint) {
380f66df612Smrg
381f66df612Smrg        XGetGeometry(dpy, tmp_win->wmhints->icon_pixmap,
3826d8e82c3Smrg                     &wdummy, &dummy, &dummy,
383f66df612Smrg                     (unsigned int *) &tmp_win->icon_width,
3846d8e82c3Smrg                     (unsigned int *) &tmp_win->icon_height, &udummy,
3856d8e82c3Smrg                     &udummy);
386f66df612Smrg
387f66df612Smrg        pm = XCreatePixmap(dpy, Scr->Root,
388f66df612Smrg                           (unsigned) tmp_win->icon_width,
389f66df612Smrg                           (unsigned) tmp_win->icon_height,
390f66df612Smrg                           (unsigned) Scr->d_depth);
391f66df612Smrg
392f66df612Smrg        XCopyPlane(dpy, tmp_win->wmhints->icon_pixmap, pm, Scr->NormalGC,
393f66df612Smrg                   0, 0, (unsigned) tmp_win->icon_width,
394f66df612Smrg                   (unsigned) tmp_win->icon_height, 0, 0, 1);
3953e747e6dSmrg    }
3963e747e6dSmrg
397ffd25bcaSmrg    /* if we still haven't got an icon, let's look in the Icon list
3983e747e6dSmrg     * if ForceIcon is not set
3993e747e6dSmrg     */
400f66df612Smrg    if (pm == None && !Scr->ForceIcon) {
401f66df612Smrg        char *icon_name;
402f66df612Smrg        Pixmap bm;
4033e747e6dSmrg
404f66df612Smrg        icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
4053e747e6dSmrg        if (icon_name == NULL)
406f66df612Smrg            icon_name = LookInList(Scr->IconNames, tmp_win->full_name,
4076d8e82c3Smrg                                   &tmp_win->xclass);
408f66df612Smrg
409f66df612Smrg        bm = None;
410f66df612Smrg        if (icon_name != NULL) {
411f66df612Smrg            if ((bm =
412f66df612Smrg                 (Pixmap) (void *) LookInNameList(Scr->Icons,
413f66df612Smrg                                                  icon_name)) == None) {
414f66df612Smrg                if ((bm = GetBitmap(icon_name)) != None)
415f66df612Smrg                    AddToList(&Scr->Icons, icon_name, (char *) bm);
416f66df612Smrg            }
417f66df612Smrg        }
418f66df612Smrg
419f66df612Smrg        if (bm != None) {
4206d8e82c3Smrg            XGetGeometry(dpy, bm, &wdummy, &dummy, &dummy,
421f66df612Smrg                         (unsigned int *) &tmp_win->icon_width,
4226d8e82c3Smrg                         (unsigned int *) &tmp_win->icon_height, &udummy,
4236d8e82c3Smrg                         &udummy);
424f66df612Smrg
425f66df612Smrg            pm = XCreatePixmap(dpy, Scr->Root, (unsigned) tmp_win->icon_width,
426f66df612Smrg                               (unsigned) tmp_win->icon_height,
427f66df612Smrg                               (unsigned) Scr->d_depth);
428f66df612Smrg
429f66df612Smrg            /* the copy plane works on color ! */
430f66df612Smrg            XCopyPlane(dpy, bm, pm, Scr->NormalGC,
431f66df612Smrg                       0, 0, (unsigned) tmp_win->icon_width,
432f66df612Smrg                       (unsigned) tmp_win->icon_height, 0, 0, 1);
433f66df612Smrg        }
4343e747e6dSmrg    }
4353e747e6dSmrg
4363e747e6dSmrg    /* if we still don't have an icon, assign the UnknownIcon */
4373e747e6dSmrg
438f66df612Smrg    if (pm == None && Scr->UnknownPm != None) {
439f66df612Smrg        tmp_win->icon_width = Scr->UnknownWidth;
440f66df612Smrg        tmp_win->icon_height = Scr->UnknownHeight;
4413e747e6dSmrg
442f66df612Smrg        pm = XCreatePixmap(dpy, Scr->Root, (unsigned) tmp_win->icon_width,
443f66df612Smrg                           (unsigned) tmp_win->icon_height,
444f66df612Smrg                           (unsigned) Scr->d_depth);
4453e747e6dSmrg
446f66df612Smrg        /* the copy plane works on color ! */
447f66df612Smrg        XCopyPlane(dpy, Scr->UnknownPm, pm, Scr->NormalGC,
448f66df612Smrg                   0, 0, (unsigned) tmp_win->icon_width,
449f66df612Smrg                   (unsigned) tmp_win->icon_height, 0, 0, 1);
4503e747e6dSmrg    }
4513e747e6dSmrg
452f66df612Smrg    if (pm == None) {
453f66df612Smrg        tmp_win->icon_height = 0;
454f66df612Smrg        tmp_win->icon_width = 0;
455f66df612Smrg        valuemask = 0;
4563e747e6dSmrg    }
457f66df612Smrg    else {
458f66df612Smrg        valuemask = CWBackPixmap;
459f66df612Smrg        attributes.background_pixmap = pm;
4603e747e6dSmrg    }
4613e747e6dSmrg
4623e747e6dSmrg    tmp_win->icon_w_width = MyFont_TextWidth(&Scr->IconFont,
463f66df612Smrg                                             tmp_win->icon_name,
464f66df612Smrg                                             (int) strlen(tmp_win->icon_name));
4653e747e6dSmrg
4663e747e6dSmrg    tmp_win->icon_w_width += 6;
467f66df612Smrg    if (tmp_win->icon_w_width < tmp_win->icon_width) {
468f66df612Smrg        tmp_win->icon_x = (tmp_win->icon_width - tmp_win->icon_w_width) / 2;
469f66df612Smrg        tmp_win->icon_x += 3;
470f66df612Smrg        tmp_win->icon_w_width = tmp_win->icon_width;
4713e747e6dSmrg    }
472f66df612Smrg    else {
473f66df612Smrg        tmp_win->icon_x = 3;
4743e747e6dSmrg    }
4753e747e6dSmrg    tmp_win->icon_y = tmp_win->icon_height + Scr->IconFont.height;
4763e747e6dSmrg    tmp_win->icon_w_height = tmp_win->icon_height + Scr->IconFont.height + 4;
4773e747e6dSmrg
4783e747e6dSmrg    event_mask = 0;
479f66df612Smrg    if (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint) {
480f66df612Smrg        tmp_win->icon_w = tmp_win->wmhints->icon_window;
481f66df612Smrg        if (tmp_win->forced ||
4826d8e82c3Smrg            XGetGeometry(dpy, tmp_win->icon_w, &wdummy, &dummy, &dummy,
483f66df612Smrg                         (unsigned int *) &tmp_win->icon_w_width,
4846d8e82c3Smrg                         (unsigned int *) &tmp_win->icon_w_height, &udummy,
4856d8e82c3Smrg                         &udummy) == 0) {
486f66df612Smrg            tmp_win->icon_w = None;
487f66df612Smrg            tmp_win->wmhints->flags &= ~IconWindowHint;
488f66df612Smrg        }
489f66df612Smrg        else {
490f66df612Smrg            tmp_win->icon_not_ours = TRUE;
491f66df612Smrg            event_mask = EnterWindowMask | LeaveWindowMask;
492f66df612Smrg        }
4933e747e6dSmrg    }
494f66df612Smrg    else {
495f66df612Smrg        tmp_win->icon_w = None;
4963e747e6dSmrg    }
4973e747e6dSmrg
498f66df612Smrg    if (tmp_win->icon_w == None) {
499f66df612Smrg        tmp_win->icon_w = XCreateSimpleWindow(dpy, Scr->Root,
500f66df612Smrg                                              0, 0,
501f66df612Smrg                                              (unsigned) tmp_win->icon_w_width,
502f66df612Smrg                                              (unsigned) tmp_win->icon_w_height,
503f66df612Smrg                                              (unsigned) Scr->IconBorderWidth,
504f66df612Smrg                                              tmp_win->icon_border,
505f66df612Smrg                                              tmp_win->iconc.back);
506f66df612Smrg        event_mask = ExposureMask;
5073e747e6dSmrg    }
5083e747e6dSmrg
509f66df612Smrg    XSelectInput(dpy, tmp_win->icon_w,
510f66df612Smrg                 (long) (KeyPressMask | ButtonPressMask | ButtonReleaseMask |
511f66df612Smrg                         event_mask));
5123e747e6dSmrg
5133e747e6dSmrg    tmp_win->icon_bm_w = None;
5143e747e6dSmrg    if (pm != None &&
515f66df612Smrg        (!(tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint))) {
516f66df612Smrg        int y;
517f66df612Smrg        int x;
518f66df612Smrg
519f66df612Smrg        y = 0;
520f66df612Smrg        if (tmp_win->icon_w_width == tmp_win->icon_width)
521f66df612Smrg            x = 0;
522f66df612Smrg        else
523f66df612Smrg            x = (tmp_win->icon_w_width - tmp_win->icon_width) / 2;
524f66df612Smrg
525f66df612Smrg        tmp_win->icon_bm_w = XCreateWindow(dpy, tmp_win->icon_w, x, y,
526f66df612Smrg                                           (unsigned int) tmp_win->icon_width,
527f66df612Smrg                                           (unsigned int) tmp_win->icon_height,
528f66df612Smrg                                           (unsigned int) 0, Scr->d_depth,
529f66df612Smrg                                           (unsigned int) CopyFromParent,
530f66df612Smrg                                           Scr->d_visual, valuemask,
531f66df612Smrg                                           &attributes);
5323e747e6dSmrg    }
5333e747e6dSmrg
534ffd25bcaSmrg    /* I need to figure out where to put the icon window now, because
5353e747e6dSmrg     * getting here means that I am going to make the icon visible
5363e747e6dSmrg     */
537f66df612Smrg    if (tmp_win->wmhints && tmp_win->wmhints->flags & IconPositionHint) {
538f66df612Smrg        final_x = tmp_win->wmhints->icon_x;
539f66df612Smrg        final_y = tmp_win->wmhints->icon_y;
5403e747e6dSmrg    }
541f66df612Smrg    else {
542f66df612Smrg        PlaceIcon(tmp_win, def_x, def_y, &final_x, &final_y);
5433e747e6dSmrg    }
5443e747e6dSmrg
5453e747e6dSmrg    if (final_x > Scr->MyDisplayWidth)
546f66df612Smrg        final_x = Scr->MyDisplayWidth - tmp_win->icon_w_width -
547f66df612Smrg            (2 * Scr->IconBorderWidth);
5483e747e6dSmrg
5493e747e6dSmrg    if (final_y > Scr->MyDisplayHeight)
550f66df612Smrg        final_y = Scr->MyDisplayHeight - tmp_win->icon_height -
551f66df612Smrg            Scr->IconFont.height - 4 - (2 * Scr->IconBorderWidth);
5523e747e6dSmrg
5533e747e6dSmrg    XMoveWindow(dpy, tmp_win->icon_w, final_x, final_y);
5543e747e6dSmrg    tmp_win->iconified = TRUE;
5553e747e6dSmrg
5563e747e6dSmrg    XMapSubwindows(dpy, tmp_win->icon_w);
557f66df612Smrg    XSaveContext(dpy, tmp_win->icon_w, TwmContext, (XPointer) tmp_win);
558f66df612Smrg    XSaveContext(dpy, tmp_win->icon_w, ScreenContext, (XPointer) Scr);
5593e747e6dSmrg    XDefineCursor(dpy, tmp_win->icon_w, Scr->IconCursor);
560f66df612Smrg    if (pm)
561f66df612Smrg        XFreePixmap(dpy, pm);
5623e747e6dSmrg    return;
5633e747e6dSmrg}
564