iconmgr.c revision 0bbfda8a
1645f5050Syouri/*
2645f5050Syouri * Copyright 1989 Massachusetts Institute of Technology
30bbfda8aSnia * Copyright 1992 Claude Lecommandeur.
4645f5050Syouri */
5645f5050Syouri
6645f5050Syouri/***********************************************************************
7645f5050Syouri *
8645f5050Syouri * $XConsortium: iconmgr.c,v 1.48 91/09/10 15:27:07 dave Exp $
9645f5050Syouri *
10645f5050Syouri * Icon Manager routines
11645f5050Syouri *
120bbfda8aSnia * 09-Mar-89 Tom LaStrange              File Created
13645f5050Syouri *
14645f5050Syouri * Do the necessary modification to be integrated in ctwm.
15645f5050Syouri * Can no longer be used for the standard twm.
16645f5050Syouri *
17645f5050Syouri * 22-April-92 Claude Lecommandeur.
18645f5050Syouri *
19645f5050Syouri *
20645f5050Syouri ***********************************************************************/
21645f5050Syouri
220bbfda8aSnia#include "ctwm.h"
230bbfda8aSnia
24645f5050Syouri#include <stdio.h>
250bbfda8aSnia#include <stdlib.h>
260bbfda8aSnia#include <string.h>
270bbfda8aSnia#include <strings.h>
280bbfda8aSnia
29645f5050Syouri#include <X11/Xatom.h>
300bbfda8aSnia
31645f5050Syouri#include "util.h"
320bbfda8aSnia#include "iconmgr.h"
330bbfda8aSnia#include "icons_builtin.h"
34645f5050Syouri#include "screen.h"
350bbfda8aSnia#include "drawing.h"
360bbfda8aSnia#include "functions_defs.h"
370bbfda8aSnia#include "list.h"
380bbfda8aSnia#include "occupation.h"
390bbfda8aSnia#include "otp.h"
40645f5050Syouri#include "add_window.h"
410bbfda8aSnia#include "gram.tab.h"
420bbfda8aSnia#include "win_decorations.h"
430bbfda8aSnia#include "win_resize.h"
440bbfda8aSnia#include "win_utils.h"
450bbfda8aSnia
460bbfda8aSnia
470bbfda8aSnia/* Where we start drawing the name in the icon manager */
480bbfda8aSniastatic int iconmgr_textx;
49645f5050Syouri
500bbfda8aSniastatic WList *Active = NULL;
510bbfda8aSniastatic WList *Current = NULL;
52645f5050SyouriWList *DownIconManager = NULL;
53645f5050Syouri
54645f5050Syouri/***********************************************************************
55645f5050Syouri *
56645f5050Syouri *  Procedure:
570bbfda8aSnia *      CreateIconManagers - creat all the icon manager windows
580bbfda8aSnia *              for this screen.
59645f5050Syouri *
60645f5050Syouri *  Returned Value:
610bbfda8aSnia *      none
62645f5050Syouri *
63645f5050Syouri *  Inputs:
640bbfda8aSnia *      none
65645f5050Syouri *
66645f5050Syouri ***********************************************************************
67645f5050Syouri */
68645f5050Syouri
69645f5050Syourivoid CreateIconManagers(void)
70645f5050Syouri{
710bbfda8aSnia	WorkSpace    *ws;
720bbfda8aSnia
730bbfda8aSnia	if(Scr->NoIconManagers) {
740bbfda8aSnia		return;
750bbfda8aSnia	}
760bbfda8aSnia
770bbfda8aSnia	/*
780bbfda8aSnia	 * Move past the iconified icon to start the text.
790bbfda8aSnia	 * XXX Semi-arbitrary magic add'l padding, to deal with various inner
800bbfda8aSnia	 * positioning of the icon subwindow.  Be smarter (or at least
810bbfda8aSnia	 * clearer) about this...
820bbfda8aSnia	 */
830bbfda8aSnia	iconmgr_textx = im_iconified_icon_width + 11;
840bbfda8aSnia	if(Scr->use3Diconmanagers) {
850bbfda8aSnia		iconmgr_textx += Scr->IconManagerShadowDepth;
860bbfda8aSnia	}
870bbfda8aSnia
880bbfda8aSnia	if(Scr->siconifyPm == None) {
890bbfda8aSnia		Scr->siconifyPm = Create2DIconManagerIcon();
900bbfda8aSnia	}
910bbfda8aSnia
920bbfda8aSnia	ws = Scr->workSpaceMgr.workSpaceList;
930bbfda8aSnia	for(IconMgr *q = Scr->iconmgr; q != NULL; q = q->nextv) {
940bbfda8aSnia		for(IconMgr *p = q; p != NULL; p = p->next) {
950bbfda8aSnia			int gx, gy;
960bbfda8aSnia			char imname[100];
970bbfda8aSnia			int mask;
980bbfda8aSnia			int gravity;
990bbfda8aSnia			int bw;
1000bbfda8aSnia			Pixel background;
1010bbfda8aSnia
1020bbfda8aSnia			snprintf(imname, sizeof(imname), "%s Icon Manager", p->name);
1030bbfda8aSnia
1040bbfda8aSnia			if(!p->geometry || !strlen(p->geometry)) {
1050bbfda8aSnia				p->geometry = "+0+0";
1060bbfda8aSnia			}
1070bbfda8aSnia			mask = XParseGeometry(p->geometry, &gx, &gy,
1080bbfda8aSnia			                      (unsigned int *) &p->width, (unsigned int *)&p->height);
1090bbfda8aSnia
1100bbfda8aSnia			bw = LookInList(Scr->NoBorder, imname, NULL) ? 0 :
1110bbfda8aSnia			     (Scr->ThreeDBorderWidth ? Scr->ThreeDBorderWidth : Scr->BorderWidth);
1120bbfda8aSnia
1130bbfda8aSnia			if(mask & XNegative) {
1140bbfda8aSnia				gx += Scr->rootw - p->width - 2 * bw;
1150bbfda8aSnia				gravity = (mask & YNegative) ? SouthEastGravity : NorthEastGravity;
1160bbfda8aSnia			}
1170bbfda8aSnia			else {
1180bbfda8aSnia				gravity = (mask & YNegative) ? SouthWestGravity : NorthWestGravity;
1190bbfda8aSnia			}
1200bbfda8aSnia			if(mask & YNegative) {
1210bbfda8aSnia				gy += Scr->rooth - p->height - 2 * bw;
1220bbfda8aSnia			}
1230bbfda8aSnia
1240bbfda8aSnia			background = Scr->IconManagerC.back;
1250bbfda8aSnia			GetColorFromList(Scr->IconManagerBL, p->name, NULL,
1260bbfda8aSnia			                 &background);
1270bbfda8aSnia
1280bbfda8aSnia			if(p->width  < 1) {
1290bbfda8aSnia				p->width  = 1;
1300bbfda8aSnia			}
1310bbfda8aSnia			if(p->height < 1) {
1320bbfda8aSnia				p->height = 1;
1330bbfda8aSnia			}
1340bbfda8aSnia			p->w = XCreateSimpleWindow(dpy, Scr->Root,
1350bbfda8aSnia			                           gx, gy, p->width, p->height, 1,
1360bbfda8aSnia			                           Scr->Black, background);
1370bbfda8aSnia
1380bbfda8aSnia
1390bbfda8aSnia			/* Scr->workSpaceMgr.activeWSPC = ws; */
1400bbfda8aSnia
1410bbfda8aSnia			/* Setup various WM properties on the iconmgr's window */
1420bbfda8aSnia			{
1430bbfda8aSnia				char *icon_name;
1440bbfda8aSnia				XWMHints wmhints;
1450bbfda8aSnia				XClassHint clhints;
1460bbfda8aSnia
1470bbfda8aSnia				if(p->icon_name) {
1480bbfda8aSnia					icon_name = strdup(p->icon_name);
1490bbfda8aSnia				}
1500bbfda8aSnia				else {
1510bbfda8aSnia					asprintf(&icon_name, "%s Icons", p->name);
1520bbfda8aSnia				}
1530bbfda8aSnia
1540bbfda8aSnia				wmhints.initial_state = NormalState;
1550bbfda8aSnia				wmhints.input         = True;
1560bbfda8aSnia				wmhints.flags         = InputHint | StateHint;
1570bbfda8aSnia
1580bbfda8aSnia				clhints.res_name  = icon_name;
1590bbfda8aSnia				clhints.res_class = "TwmIconManager";
1600bbfda8aSnia
1610bbfda8aSnia				XmbSetWMProperties(dpy, p->w, imname, icon_name, NULL, 0, NULL,
1620bbfda8aSnia				                   &wmhints, &clhints);
1630bbfda8aSnia				free(icon_name);
1640bbfda8aSnia			}
1650bbfda8aSnia
1660bbfda8aSnia
1670bbfda8aSnia			p->twm_win = AddWindow(p->w, AWT_ICON_MANAGER, p, Scr->currentvs);
1680bbfda8aSnia			/*
1690bbfda8aSnia			 * SetupOccupation() called from AddWindow() doesn't setup
1700bbfda8aSnia			 * occupation for icon managers, nor clear vs if occupation lacks.
1710bbfda8aSnia			 *
1720bbfda8aSnia			 * There is no Scr->currentvs->wsw->currentwspc set up this
1730bbfda8aSnia			 * early, so we can't check with that; the best check we can do
1740bbfda8aSnia			 * is use ws->number.  This may be incorrect when re-starting
1750bbfda8aSnia			 * ctwm.
1760bbfda8aSnia			 */
1770bbfda8aSnia			if(ws) {
1780bbfda8aSnia				p->twm_win->occupation = 1 << ws->number;
1790bbfda8aSnia				if(ws->number > 0) {
1800bbfda8aSnia					p->twm_win->vs = NULL;
1810bbfda8aSnia				}
1820bbfda8aSnia			}
1830bbfda8aSnia			else {
1840bbfda8aSnia				p->twm_win->occupation = 1;
1850bbfda8aSnia			}
1860bbfda8aSnia#ifdef DEBUG_ICONMGR
1870bbfda8aSnia			fprintf(stderr,
1880bbfda8aSnia			        "CreateIconManagers: IconMgr %p: x=%d y=%d w=%d h=%d occupation=%x\n",
1890bbfda8aSnia			        p, gx, gy,  p->width, p->height, p->twm_win->occupation);
1900bbfda8aSnia#endif
1910bbfda8aSnia
1920bbfda8aSnia			{
1930bbfda8aSnia				XSizeHints sizehints;
1940bbfda8aSnia
1950bbfda8aSnia				sizehints.flags       = PWinGravity;
1960bbfda8aSnia				sizehints.win_gravity = gravity;
1970bbfda8aSnia				XSetWMSizeHints(dpy, p->w, &sizehints, XA_WM_NORMAL_HINTS);
1980bbfda8aSnia			}
1990bbfda8aSnia
2000bbfda8aSnia			p->twm_win->mapped = false;
2010bbfda8aSnia			SetMapStateProp(p->twm_win, WithdrawnState);
2020bbfda8aSnia			if(p->twm_win && (p->twm_win->wmhints->initial_state == IconicState)) {
2030bbfda8aSnia				p->twm_win->isicon = true;
2040bbfda8aSnia			}
2050bbfda8aSnia			else if(!Scr->NoIconManagers && Scr->ShowIconManager) {
2060bbfda8aSnia				p->twm_win->isicon = false;
2070bbfda8aSnia			}
2080bbfda8aSnia			else {
2090bbfda8aSnia				p->twm_win->isicon = true;
2100bbfda8aSnia			}
2110bbfda8aSnia		}
2120bbfda8aSnia		if(ws != NULL) {
2130bbfda8aSnia			ws = ws->next;
2140bbfda8aSnia		}
2150bbfda8aSnia	}
2160bbfda8aSnia
2170bbfda8aSnia	if(Scr->workSpaceManagerActive) {
2180bbfda8aSnia		Scr->workSpaceMgr.workSpaceList->iconmgr = Scr->iconmgr;
2190bbfda8aSnia	}
2200bbfda8aSnia
2210bbfda8aSnia
2220bbfda8aSnia	/*
2230bbfda8aSnia	 * Grab buttons/keystrokes for icon managers appropriately.
2240bbfda8aSnia	 * Normally, this is done in AddWindow(), but it explicitly skips it
2250bbfda8aSnia	 * for icon managers.  It's not at all clear why GrabButtons() would
2260bbfda8aSnia	 * do so; I don't think it needs to.  GrabKeys() does do some looping
2270bbfda8aSnia	 * over the Scr->iconmgr list at the end though, so it's possible we
2280bbfda8aSnia	 * need to delay calling it until now when the list is all filled up.
2290bbfda8aSnia	 * This needs further investigation; it may be that the special case
2300bbfda8aSnia	 * and this code can be removed.  X-ref comments in add_window.c
2310bbfda8aSnia	 * about it.
2320bbfda8aSnia	 */
2330bbfda8aSnia	for(IconMgr *q = Scr->iconmgr; q != NULL; q = q->nextv) {
2340bbfda8aSnia		for(IconMgr *p = q; p != NULL; p = p->next) {
2350bbfda8aSnia			GrabButtons(p->twm_win);
2360bbfda8aSnia			GrabKeys(p->twm_win);
2370bbfda8aSnia		}
238645f5050Syouri	}
239645f5050Syouri
240645f5050Syouri}
241645f5050Syouri
242645f5050Syouri/***********************************************************************
243645f5050Syouri *
244645f5050Syouri *  Procedure:
2450bbfda8aSnia *      AllocateIconManager - allocate a new icon manager
246645f5050Syouri *
247645f5050Syouri *  Inputs:
2480bbfda8aSnia *      name    - the name of this icon manager
2490bbfda8aSnia *      icon_name - the name of the associated icon
2500bbfda8aSnia *      geom    - a geometry string to eventually parse
2510bbfda8aSnia *      columns - the number of columns this icon manager has
252645f5050Syouri *
253645f5050Syouri ***********************************************************************
254645f5050Syouri */
255645f5050Syouri
256645f5050SyouriIconMgr *AllocateIconManager(char *name, char *icon_name, char *geom,
2570bbfda8aSnia                             int columns)
258645f5050Syouri{
2590bbfda8aSnia	IconMgr *p;
260645f5050Syouri
261645f5050Syouri#ifdef DEBUG_ICONMGR
2620bbfda8aSnia	fprintf(stderr, "AllocateIconManager\n");
2630bbfda8aSnia	fprintf(stderr, "  name=\"%s\" icon_name=\"%s\", geom=\"%s\", col=%d\n",
2640bbfda8aSnia	        name, icon_name, geom, columns);
265645f5050Syouri#endif
266645f5050Syouri
2670bbfda8aSnia	if(Scr->NoIconManagers) {
2680bbfda8aSnia		return NULL;
2690bbfda8aSnia	}
2700bbfda8aSnia
2710bbfda8aSnia	if(columns < 1) {
2720bbfda8aSnia		columns = 1;
2730bbfda8aSnia	}
2740bbfda8aSnia	p = calloc(1, sizeof(IconMgr));
2750bbfda8aSnia	p->name      = name;
2760bbfda8aSnia	p->icon_name = icon_name;
2770bbfda8aSnia	p->geometry  = geom;
2780bbfda8aSnia	p->columns   = columns;
2790bbfda8aSnia	p->scr       = Scr;
2800bbfda8aSnia	p->width     = 150;
2810bbfda8aSnia	p->height    = 10;
2820bbfda8aSnia
2830bbfda8aSnia	if(Scr->iconmgr == NULL) {
2840bbfda8aSnia		Scr->iconmgr = p;
2850bbfda8aSnia		Scr->iconmgr->lasti = p;
2860bbfda8aSnia	}
2870bbfda8aSnia	else {
2880bbfda8aSnia		Scr->iconmgr->lasti->next = p;
2890bbfda8aSnia		p->prev = Scr->iconmgr->lasti;
2900bbfda8aSnia		Scr->iconmgr->lasti = p;
2910bbfda8aSnia	}
2920bbfda8aSnia	return(p);
2930bbfda8aSnia}
2940bbfda8aSnia
2950bbfda8aSnia
2960bbfda8aSnia/*
2970bbfda8aSnia * Each workspace has its own [set of] icon manager[s].  The initial main
2980bbfda8aSnia * one was setup via AllocateIconManager() early in startup.  The others
2990bbfda8aSnia * were setup during parsing the config file.  Then this gets called late
3000bbfda8aSnia * in startup, after all the workspaces are setup, to copy them all into
3010bbfda8aSnia * each one.
3020bbfda8aSnia *
3030bbfda8aSnia * Note this is distinct from CreateIconManagers(); that creates and
3040bbfda8aSnia * draws the windows, this creates and connects up the data structures.
3050bbfda8aSnia */
3060bbfda8aSniavoid AllocateOtherIconManagers(void)
3070bbfda8aSnia{
3080bbfda8aSnia	IconMgr   *imfirst; // First IM on each workspace
3090bbfda8aSnia	WorkSpace *ws;
3100bbfda8aSnia
3110bbfda8aSnia	/* No defined workspaces?  Nothing to do. */
3120bbfda8aSnia	if(! Scr->workSpaceManagerActive) {
3130bbfda8aSnia		return;
3140bbfda8aSnia	}
3150bbfda8aSnia
3160bbfda8aSnia	/* The first workspace just gets the ones we already have */
3170bbfda8aSnia	ws = Scr->workSpaceMgr.workSpaceList;
3180bbfda8aSnia	ws->iconmgr = Scr->iconmgr;
3190bbfda8aSnia
3200bbfda8aSnia	/* From the second on, we start copying */
3210bbfda8aSnia	imfirst = ws->iconmgr;
3220bbfda8aSnia	for(ws = ws->next; ws != NULL; ws = ws->next) {
3230bbfda8aSnia		IconMgr *ip, *previ, *p = NULL;
3240bbfda8aSnia
3250bbfda8aSnia		/* Copy in the first iconmgr */
3260bbfda8aSnia		ws->iconmgr  = malloc(sizeof(IconMgr));
3270bbfda8aSnia		*ws->iconmgr = *imfirst;
3280bbfda8aSnia
3290bbfda8aSnia		/*
3300bbfda8aSnia		 * This first is now the nextv to the first in the previous WS,
3310bbfda8aSnia		 * and we don't [yet] have a nextv of our own.
3320bbfda8aSnia		 * */
3330bbfda8aSnia		imfirst->nextv = ws->iconmgr;
3340bbfda8aSnia		ws->iconmgr->nextv = NULL;
3350bbfda8aSnia
3360bbfda8aSnia		/*
3370bbfda8aSnia		 * Start from the second, and copy them each from the prior
3380bbfda8aSnia		 * workspace we just went through.
3390bbfda8aSnia		 * */
3400bbfda8aSnia		previ = ws->iconmgr;
3410bbfda8aSnia		for(ip = imfirst->next; ip != NULL; ip = ip->next) {
3420bbfda8aSnia			/* Copy the base bits */
3430bbfda8aSnia			p  = malloc(sizeof(IconMgr));
3440bbfda8aSnia			*p = *ip;
3450bbfda8aSnia
3460bbfda8aSnia			/* Link up the double-links, and there's no nextv [yet] */
3470bbfda8aSnia			previ->next = p;
3480bbfda8aSnia			p->prev     = previ;
3490bbfda8aSnia			p->next     = NULL;
3500bbfda8aSnia			p->nextv    = NULL;
3510bbfda8aSnia
3520bbfda8aSnia			/* We're now the nextv to that one in the old workspace */
3530bbfda8aSnia			ip->nextv  = p;
3540bbfda8aSnia
3550bbfda8aSnia			/* And back around to the next one to copy into this WS */
3560bbfda8aSnia			previ = p;
3570bbfda8aSnia		}
3580bbfda8aSnia
3590bbfda8aSnia		/* Each one has a pointer to the last IM in this WS, so save those */
3600bbfda8aSnia		for(ip = ws->iconmgr; ip != NULL; ip = ip->next) {
3610bbfda8aSnia			ip->lasti = p;
3620bbfda8aSnia		}
3630bbfda8aSnia
3640bbfda8aSnia		/*
3650bbfda8aSnia		 * And back around to the next workspace, which works from those
3660bbfda8aSnia		 * we made for this WS.  We go from imfirst rather than
3670bbfda8aSnia		 * Scr->iconmgr so the ip->nextv rewrites are correct above; we
3680bbfda8aSnia		 * have to fill them in on the next loop.
3690bbfda8aSnia		 */
3700bbfda8aSnia		imfirst = ws->iconmgr;
3710bbfda8aSnia	}
372645f5050Syouri}
373645f5050Syouri
3740bbfda8aSnia
375645f5050Syouri/***********************************************************************
376645f5050Syouri *
377645f5050Syouri *  Procedure:
3780bbfda8aSnia *      MoveIconManager - move the pointer around in an icon manager
379645f5050Syouri *
380645f5050Syouri *  Inputs:
3810bbfda8aSnia *      dir     - one of the following:
3820bbfda8aSnia *                      F_FORWICONMGR   - forward in the window list
3830bbfda8aSnia *                      F_BACKICONMGR   - backward in the window list
3840bbfda8aSnia *                      F_UPICONMGR     - up one row
3850bbfda8aSnia *                      F_DOWNICONMGR   - down one row
3860bbfda8aSnia *                      F_LEFTICONMGR   - left one column
3870bbfda8aSnia *                      F_RIGHTICONMGR  - right one column
388645f5050Syouri *
389645f5050Syouri *  Special Considerations:
3900bbfda8aSnia *      none
391645f5050Syouri *
392645f5050Syouri ***********************************************************************
393645f5050Syouri */
394645f5050Syouri
395645f5050Syourivoid MoveIconManager(int dir)
396645f5050Syouri{
3970bbfda8aSnia	IconMgr *ip;
3980bbfda8aSnia	WList *tmp = NULL;
3990bbfda8aSnia	int cur_row, cur_col, new_row, new_col;
4000bbfda8aSnia	int row_inc, col_inc;
4010bbfda8aSnia	bool got_it;
4020bbfda8aSnia
4030bbfda8aSnia	if(!Current) {
4040bbfda8aSnia		return;
4050bbfda8aSnia	}
4060bbfda8aSnia
4070bbfda8aSnia	cur_row = Current->row;
4080bbfda8aSnia	cur_col = Current->col;
4090bbfda8aSnia	ip = Current->iconmgr;
4100bbfda8aSnia
4110bbfda8aSnia	row_inc = 0;
4120bbfda8aSnia	col_inc = 0;
4130bbfda8aSnia	got_it = false;
4140bbfda8aSnia
4150bbfda8aSnia	switch(dir) {
4160bbfda8aSnia		case F_FORWICONMGR:
4170bbfda8aSnia			if((tmp = Current->next) == NULL) {
4180bbfda8aSnia				tmp = ip->first;
4190bbfda8aSnia			}
4200bbfda8aSnia			got_it = true;
4210bbfda8aSnia			break;
4220bbfda8aSnia
4230bbfda8aSnia		case F_BACKICONMGR:
4240bbfda8aSnia			if((tmp = Current->prev) == NULL) {
4250bbfda8aSnia				tmp = ip->last;
4260bbfda8aSnia			}
4270bbfda8aSnia			got_it = true;
4280bbfda8aSnia			break;
4290bbfda8aSnia
4300bbfda8aSnia		case F_UPICONMGR:
4310bbfda8aSnia			row_inc = -1;
4320bbfda8aSnia			break;
4330bbfda8aSnia
4340bbfda8aSnia		case F_DOWNICONMGR:
4350bbfda8aSnia			row_inc = 1;
4360bbfda8aSnia			break;
4370bbfda8aSnia
4380bbfda8aSnia		case F_LEFTICONMGR:
4390bbfda8aSnia			col_inc = -1;
4400bbfda8aSnia			break;
4410bbfda8aSnia
4420bbfda8aSnia		case F_RIGHTICONMGR:
4430bbfda8aSnia			col_inc = 1;
4440bbfda8aSnia			break;
4450bbfda8aSnia	}
4460bbfda8aSnia
4470bbfda8aSnia	/* If got_it is false ast this point then we got a left, right,
4480bbfda8aSnia	 * up, or down, command.  We will enter this loop until we find
4490bbfda8aSnia	 * a window to warp to.
450645f5050Syouri	 */
4510bbfda8aSnia	new_row = cur_row;
4520bbfda8aSnia	new_col = cur_col;
4530bbfda8aSnia
4540bbfda8aSnia	while(!got_it) {
4550bbfda8aSnia		new_row += row_inc;
4560bbfda8aSnia		new_col += col_inc;
4570bbfda8aSnia		if(new_row < 0) {
4580bbfda8aSnia			new_row = ip->cur_rows - 1;
4590bbfda8aSnia		}
4600bbfda8aSnia		if(new_col < 0) {
4610bbfda8aSnia			new_col = ip->cur_columns - 1;
4620bbfda8aSnia		}
4630bbfda8aSnia		if(new_row >= ip->cur_rows) {
4640bbfda8aSnia			new_row = 0;
4650bbfda8aSnia		}
4660bbfda8aSnia		if(new_col >= ip->cur_columns) {
4670bbfda8aSnia			new_col = 0;
4680bbfda8aSnia		}
4690bbfda8aSnia
4700bbfda8aSnia		/* Now let's go through the list to see if there is an entry with this
4710bbfda8aSnia		 * new position
4720bbfda8aSnia		 */
4730bbfda8aSnia		for(tmp = ip->first; tmp != NULL; tmp = tmp->next) {
4740bbfda8aSnia			if(tmp->row == new_row && tmp->col == new_col) {
4750bbfda8aSnia				got_it = true;
4760bbfda8aSnia				break;
4770bbfda8aSnia			}
4780bbfda8aSnia		}
4790bbfda8aSnia	}
4800bbfda8aSnia
4810bbfda8aSnia	if(!got_it) {
4820bbfda8aSnia		fprintf(stderr,
4830bbfda8aSnia		        "%s:  unable to find window (%d, %d) in icon manager\n",
4840bbfda8aSnia		        ProgramName, new_row, new_col);
4850bbfda8aSnia		return;
4860bbfda8aSnia	}
4870bbfda8aSnia
4880bbfda8aSnia	if(tmp == NULL) {
4890bbfda8aSnia		return;
4900bbfda8aSnia	}
4910bbfda8aSnia
4920bbfda8aSnia	/* raise the frame so the icon manager is visible */
4930bbfda8aSnia	if(ip->twm_win->mapped) {
4940bbfda8aSnia		OtpRaise(ip->twm_win, WinWin);
4950bbfda8aSnia		XWarpPointer(dpy, None, tmp->icon, 0, 0, 0, 0, 5, 5);
4960bbfda8aSnia	}
4970bbfda8aSnia	else {
4980bbfda8aSnia		if(tmp->twm->title_height) {
4990bbfda8aSnia			int tbx = Scr->TBInfo.titlex;
5000bbfda8aSnia			int x = tmp->twm->highlightxr;
5010bbfda8aSnia			XWarpPointer(dpy, None, tmp->twm->title_w, 0, 0, 0, 0,
5020bbfda8aSnia			             tbx + (x - tbx) / 2,
5030bbfda8aSnia			             Scr->TitleHeight / 4);
5040bbfda8aSnia		}
5050bbfda8aSnia		else {
5060bbfda8aSnia			XWarpPointer(dpy, None, tmp->twm->w, 0, 0, 0, 0, 5, 5);
5070bbfda8aSnia		}
5080bbfda8aSnia	}
509645f5050Syouri}
510645f5050Syouri
511645f5050Syouri/***********************************************************************
512645f5050Syouri *
513645f5050Syouri *  Procedure:
5140bbfda8aSnia *      MoveMappedIconManager - move the pointer around in an icon manager
515645f5050Syouri *
516645f5050Syouri *  Inputs:
5170bbfda8aSnia *      dir     - one of the following:
5180bbfda8aSnia *                      F_FORWMAPICONMGR        - forward in the window list
5190bbfda8aSnia *                      F_BACKMAPICONMGR        - backward in the window list
520645f5050Syouri *
521645f5050Syouri *  Special Considerations:
5220bbfda8aSnia *      none
523645f5050Syouri *
524645f5050Syouri ***********************************************************************
525645f5050Syouri */
526645f5050Syouri
527645f5050Syourivoid MoveMappedIconManager(int dir)
528645f5050Syouri{
5290bbfda8aSnia	IconMgr *ip;
5300bbfda8aSnia	WList *tmp = NULL;
5310bbfda8aSnia	WList *orig = NULL;
5320bbfda8aSnia	bool got_it;
5330bbfda8aSnia
5340bbfda8aSnia	if(!Current) {
5350bbfda8aSnia		Current = Active;
5360bbfda8aSnia	}
5370bbfda8aSnia	if(!Current) {
5380bbfda8aSnia		return;
5390bbfda8aSnia	}
5400bbfda8aSnia
5410bbfda8aSnia	ip = Current->iconmgr;
5420bbfda8aSnia
5430bbfda8aSnia	got_it = false;
5440bbfda8aSnia	tmp = Current;
5450bbfda8aSnia	orig = Current;
5460bbfda8aSnia
5470bbfda8aSnia	while(!got_it) {
5480bbfda8aSnia		switch(dir) {
5490bbfda8aSnia			case F_FORWMAPICONMGR:
5500bbfda8aSnia				if((tmp = tmp->next) == NULL) {
5510bbfda8aSnia					tmp = ip->first;
5520bbfda8aSnia				}
5530bbfda8aSnia				break;
5540bbfda8aSnia
5550bbfda8aSnia			case F_BACKMAPICONMGR:
5560bbfda8aSnia				if((tmp = tmp->prev) == NULL) {
5570bbfda8aSnia					tmp = ip->last;
5580bbfda8aSnia				}
5590bbfda8aSnia				break;
5600bbfda8aSnia		}
5610bbfda8aSnia		if(tmp->twm->mapped) {
5620bbfda8aSnia			got_it = true;
5630bbfda8aSnia			break;
5640bbfda8aSnia		}
5650bbfda8aSnia		if(tmp == orig) {
5660bbfda8aSnia			break;
5670bbfda8aSnia		}
5680bbfda8aSnia	}
5690bbfda8aSnia
5700bbfda8aSnia	if(!got_it) {
5710bbfda8aSnia		fprintf(stderr, "%s:  unable to find open window in icon manager\n",
5720bbfda8aSnia		        ProgramName);
5730bbfda8aSnia		return;
5740bbfda8aSnia	}
5750bbfda8aSnia
5760bbfda8aSnia	if(tmp == NULL) {
5770bbfda8aSnia		return;
5780bbfda8aSnia	}
5790bbfda8aSnia
5800bbfda8aSnia	/* raise the frame so the icon manager is visible */
5810bbfda8aSnia	if(ip->twm_win->mapped) {
5820bbfda8aSnia		OtpRaise(ip->twm_win, WinWin);
5830bbfda8aSnia		XWarpPointer(dpy, None, tmp->icon, 0, 0, 0, 0, 5, 5);
5840bbfda8aSnia	}
5850bbfda8aSnia	else {
5860bbfda8aSnia		if(tmp->twm->title_height) {
5870bbfda8aSnia			XWarpPointer(dpy, None, tmp->twm->title_w, 0, 0, 0, 0,
5880bbfda8aSnia			             tmp->twm->title_width / 2,
5890bbfda8aSnia			             Scr->TitleHeight / 4);
5900bbfda8aSnia		}
5910bbfda8aSnia		else {
5920bbfda8aSnia			XWarpPointer(dpy, None, tmp->twm->w, 0, 0, 0, 0, 5, 5);
5930bbfda8aSnia		}
5940bbfda8aSnia	}
595645f5050Syouri}
596645f5050Syouri
597645f5050Syouri/***********************************************************************
598645f5050Syouri *
599645f5050Syouri *  Procedure:
6000bbfda8aSnia *      JumpIconManager - jump from one icon manager to another,
6010bbfda8aSnia *              possibly even on another screen
602645f5050Syouri *
603645f5050Syouri *  Inputs:
6040bbfda8aSnia *      dir     - one of the following:
6050bbfda8aSnia *                      F_NEXTICONMGR   - go to the next icon manager
6060bbfda8aSnia *                      F_PREVICONMGR   - go to the previous one
607645f5050Syouri *
608645f5050Syouri ***********************************************************************
609645f5050Syouri */
610645f5050Syouri
6110bbfda8aSniavoid JumpIconManager(int dir)
612645f5050Syouri{
6130bbfda8aSnia	IconMgr *ip, *tmp_ip = NULL;
6140bbfda8aSnia	bool got_it = false;
6150bbfda8aSnia	ScreenInfo *sp;
6160bbfda8aSnia	int screen;
617645f5050Syouri
6180bbfda8aSnia	if(!Current) {
6190bbfda8aSnia		return;
6200bbfda8aSnia	}
621645f5050Syouri
622645f5050Syouri
623645f5050Syouri#define ITER(i) (dir == F_NEXTICONMGR ? (i)->next : (i)->prev)
624645f5050Syouri#define IPOFSP(sp) (dir == F_NEXTICONMGR ? sp->iconmgr : sp->iconmgr->lasti)
625645f5050Syouri#define TEST(ip) if ((ip)->count != 0 && (ip)->twm_win->mapped) \
6260bbfda8aSnia                 { got_it = true; break; }
6270bbfda8aSnia
6280bbfda8aSnia	ip = Current->iconmgr;
6290bbfda8aSnia	for(tmp_ip = ITER(ip); tmp_ip; tmp_ip = ITER(tmp_ip)) {
6300bbfda8aSnia		TEST(tmp_ip);
6310bbfda8aSnia	}
6320bbfda8aSnia
6330bbfda8aSnia	if(!got_it) {
6340bbfda8aSnia		int origscreen = ip->scr->screen;
6350bbfda8aSnia		int inc = (dir == F_NEXTICONMGR ? 1 : -1);
6360bbfda8aSnia
6370bbfda8aSnia		for(screen = origscreen + inc; ; screen += inc) {
6380bbfda8aSnia			if(screen >= NumScreens) {
6390bbfda8aSnia				screen = 0;
6400bbfda8aSnia			}
6410bbfda8aSnia			else if(screen < 0) {
6420bbfda8aSnia				screen = NumScreens - 1;
6430bbfda8aSnia			}
6440bbfda8aSnia
6450bbfda8aSnia			sp = ScreenList[screen];
6460bbfda8aSnia			if(sp) {
6470bbfda8aSnia				for(tmp_ip = IPOFSP(sp); tmp_ip; tmp_ip = ITER(tmp_ip)) {
6480bbfda8aSnia					TEST(tmp_ip);
6490bbfda8aSnia				}
6500bbfda8aSnia			}
6510bbfda8aSnia			if(got_it || screen == origscreen) {
6520bbfda8aSnia				break;
6530bbfda8aSnia			}
654645f5050Syouri		}
655645f5050Syouri	}
656645f5050Syouri
657645f5050Syouri#undef ITER
658645f5050Syouri#undef IPOFSP
659645f5050Syouri#undef TEST
660645f5050Syouri
6610bbfda8aSnia	if(!got_it) {
6620bbfda8aSnia		XBell(dpy, 0);
6630bbfda8aSnia		return;
6640bbfda8aSnia	}
6650bbfda8aSnia
6660bbfda8aSnia	/* raise the frame so it is visible */
6670bbfda8aSnia	OtpRaise(tmp_ip->twm_win, WinWin);
6680bbfda8aSnia	if(tmp_ip->active) {
6690bbfda8aSnia		XWarpPointer(dpy, None, tmp_ip->active->icon, 0, 0, 0, 0, 5, 5);
6700bbfda8aSnia	}
6710bbfda8aSnia	else {
6720bbfda8aSnia		XWarpPointer(dpy, None, tmp_ip->w, 0, 0, 0, 0, 5, 5);
6730bbfda8aSnia	}
674645f5050Syouri}
675645f5050Syouri
676645f5050Syouri/***********************************************************************
677645f5050Syouri *
678645f5050Syouri *  Procedure:
6790bbfda8aSnia *      AddIconManager - add a window to an icon manager
680645f5050Syouri *
681645f5050Syouri *  Inputs:
6820bbfda8aSnia *      tmp_win - the TwmWindow structure
683645f5050Syouri *
684645f5050Syouri ***********************************************************************
685645f5050Syouri */
686645f5050Syouri
687645f5050SyouriWList *AddIconManager(TwmWindow *tmp_win)
688645f5050Syouri{
6890bbfda8aSnia	WList *tmp, *old;
6900bbfda8aSnia	IconMgr *ip;
6910bbfda8aSnia
6920bbfda8aSnia	/* Some window types don't wind up in icon managers ever */
6930bbfda8aSnia	if(tmp_win->isiconmgr || tmp_win->istransient || tmp_win->iswspmgr
6940bbfda8aSnia	                || tmp_win->w == Scr->workSpaceMgr.occupyWindow->w) {
6950bbfda8aSnia		return NULL;
6960bbfda8aSnia	}
6970bbfda8aSnia
6980bbfda8aSnia	/* Icon managers can be shut off wholesale in the config */
6990bbfda8aSnia	if(Scr->NoIconManagers) {
7000bbfda8aSnia		return NULL;
7010bbfda8aSnia	}
7020bbfda8aSnia
7030bbfda8aSnia	/* Config could declare not to IMify this type of window in two ways */
7040bbfda8aSnia	if(LookInList(Scr->IconMgrNoShow, tmp_win->name, &tmp_win->class)) {
7050bbfda8aSnia		return NULL;
7060bbfda8aSnia	}
7070bbfda8aSnia	if(Scr->IconManagerDontShow
7080bbfda8aSnia	                && !LookInList(Scr->IconMgrShow, tmp_win->name, &tmp_win->class)) {
7090bbfda8aSnia		return NULL;
7100bbfda8aSnia	}
7110bbfda8aSnia
7120bbfda8aSnia	/* Dredge up the appropriate IM */
7130bbfda8aSnia	if((ip = (IconMgr *)LookInList(Scr->IconMgrs, tmp_win->name,
7140bbfda8aSnia	                               &tmp_win->class)) == NULL) {
7150bbfda8aSnia		if(Scr->workSpaceManagerActive) {
7160bbfda8aSnia			ip = Scr->workSpaceMgr.workSpaceList->iconmgr;
7170bbfda8aSnia		}
7180bbfda8aSnia		else {
7190bbfda8aSnia			ip = Scr->iconmgr;
7200bbfda8aSnia		}
7210bbfda8aSnia	}
7220bbfda8aSnia
7230bbfda8aSnia	/* IM's exist in all workspaces, so loop through WSen */
7240bbfda8aSnia	tmp = NULL;
7250bbfda8aSnia	old = tmp_win->iconmanagerlist;
7260bbfda8aSnia	while(ip != NULL) {
7270bbfda8aSnia		int h;
7280bbfda8aSnia		unsigned long valuemask;         /* mask for create windows */
7290bbfda8aSnia		XSetWindowAttributes attributes; /* attributes for create windows */
7300bbfda8aSnia
7310bbfda8aSnia		/* Is the window in this workspace? */
7320bbfda8aSnia		if((tmp_win->occupation & ip->twm_win->occupation) == 0) {
7330bbfda8aSnia			/* Nope, skip onward */
7340bbfda8aSnia			ip = ip->nextv;
7350bbfda8aSnia			continue;
7360bbfda8aSnia		}
7370bbfda8aSnia
7380bbfda8aSnia		/* Yep, create entry and stick it in */
7390bbfda8aSnia		tmp = calloc(1, sizeof(WList));
7400bbfda8aSnia		tmp->iconmgr = ip;
7410bbfda8aSnia		tmp->twm = tmp_win;
7420bbfda8aSnia
7430bbfda8aSnia		InsertInIconManager(ip, tmp, tmp_win);
7440bbfda8aSnia
7450bbfda8aSnia		/* IM color settings, shared worldwide */
7460bbfda8aSnia		tmp->cp.fore   = Scr->IconManagerC.fore;
7470bbfda8aSnia		tmp->cp.back   = Scr->IconManagerC.back;
7480bbfda8aSnia		tmp->highlight = Scr->IconManagerHighlight;
7490bbfda8aSnia
7500bbfda8aSnia		GetColorFromList(Scr->IconManagerFL, tmp_win->name,
7510bbfda8aSnia		                 &tmp_win->class, &tmp->cp.fore);
7520bbfda8aSnia		GetColorFromList(Scr->IconManagerBL, tmp_win->name,
7530bbfda8aSnia		                 &tmp_win->class, &tmp->cp.back);
7540bbfda8aSnia		GetColorFromList(Scr->IconManagerHighlightL, tmp_win->name,
7550bbfda8aSnia		                 &tmp_win->class, &tmp->highlight);
7560bbfda8aSnia
7570bbfda8aSnia		/*
7580bbfda8aSnia		 * If we're using 3d icon managers, each line item has its own
7590bbfda8aSnia		 * icon; see comment on creation function for details.  With 2d
7600bbfda8aSnia		 * icon managers, it's the same for all of them, so it's stored
7610bbfda8aSnia		 * screen-wide.
7620bbfda8aSnia		 */
7630bbfda8aSnia		if(Scr->use3Diconmanagers) {
7640bbfda8aSnia			if(!Scr->BeNiceToColormap) {
7650bbfda8aSnia				GetShadeColors(&tmp->cp);
7660bbfda8aSnia			}
7670bbfda8aSnia			tmp->iconifypm = Create3DIconManagerIcon(tmp->cp);
7680bbfda8aSnia		}
7690bbfda8aSnia
7700bbfda8aSnia		/* Refigure the height of the whole IM */
7710bbfda8aSnia		h = Scr->IconManagerFont.avg_height
7720bbfda8aSnia		    + 2 * (ICON_MGR_OBORDER + ICON_MGR_OBORDER);
7730bbfda8aSnia		if(h < (im_iconified_icon_height + 4)) {
7740bbfda8aSnia			h = im_iconified_icon_height + 4;
7750bbfda8aSnia		}
7760bbfda8aSnia
7770bbfda8aSnia		ip->height = h * ip->count;
7780bbfda8aSnia		tmp->me = ip->count;
7790bbfda8aSnia		tmp->x = -1;
7800bbfda8aSnia		tmp->y = -1;
7810bbfda8aSnia		tmp->height = -1;
7820bbfda8aSnia		tmp->width = -1;
7830bbfda8aSnia
7840bbfda8aSnia
7850bbfda8aSnia		/* Make a window for this row in the IM */
7860bbfda8aSnia		valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor);
7870bbfda8aSnia		attributes.background_pixel = tmp->cp.back;
7880bbfda8aSnia		attributes.border_pixel = tmp->cp.back;
7890bbfda8aSnia		attributes.event_mask = (KeyPressMask | ButtonPressMask |
7900bbfda8aSnia		                         ButtonReleaseMask | ExposureMask);
7910bbfda8aSnia		if(Scr->IconManagerFocus) {
7920bbfda8aSnia			attributes.event_mask |= (EnterWindowMask | LeaveWindowMask);
7930bbfda8aSnia		}
7940bbfda8aSnia		attributes.cursor = Scr->IconMgrCursor;
7950bbfda8aSnia		tmp->w = XCreateWindow(dpy, ip->w, 0, 0, 1,
7960bbfda8aSnia		                       h, 0,
7970bbfda8aSnia		                       CopyFromParent, CopyFromParent,
7980bbfda8aSnia		                       CopyFromParent,
7990bbfda8aSnia		                       valuemask, &attributes);
8000bbfda8aSnia
8010bbfda8aSnia
8020bbfda8aSnia		/* Setup the icon for it too */
8030bbfda8aSnia		valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor);
8040bbfda8aSnia		attributes.background_pixel = tmp->cp.back;
8050bbfda8aSnia		attributes.border_pixel = Scr->Black;
8060bbfda8aSnia		attributes.event_mask = (ButtonReleaseMask | ButtonPressMask
8070bbfda8aSnia		                         | ExposureMask);
8080bbfda8aSnia		attributes.cursor = Scr->ButtonCursor;
8090bbfda8aSnia		/* The precise location will be set it in PackIconManager.  */
8100bbfda8aSnia		tmp->icon = XCreateWindow(dpy, tmp->w, 0, 0,
8110bbfda8aSnia		                          im_iconified_icon_width,
8120bbfda8aSnia		                          im_iconified_icon_height,
8130bbfda8aSnia		                          0, CopyFromParent,
8140bbfda8aSnia		                          CopyFromParent,
8150bbfda8aSnia		                          CopyFromParent,
8160bbfda8aSnia		                          valuemask, &attributes);
8170bbfda8aSnia
8180bbfda8aSnia
8190bbfda8aSnia		/* Bump housekeeping for the IM */
8200bbfda8aSnia		ip->count += 1;
8210bbfda8aSnia		PackIconManager(ip);
8220bbfda8aSnia		if(Scr->WindowMask) {
8230bbfda8aSnia			XRaiseWindow(dpy, Scr->WindowMask);
8240bbfda8aSnia		}
8250bbfda8aSnia		XMapWindow(dpy, tmp->w);
8260bbfda8aSnia
8270bbfda8aSnia		XSaveContext(dpy, tmp->w, TwmContext, (XPointer) tmp_win);
8280bbfda8aSnia		XSaveContext(dpy, tmp->w, ScreenContext, (XPointer) Scr);
8290bbfda8aSnia		XSaveContext(dpy, tmp->icon, TwmContext, (XPointer) tmp_win);
8300bbfda8aSnia		XSaveContext(dpy, tmp->icon, ScreenContext, (XPointer) Scr);
8310bbfda8aSnia
8320bbfda8aSnia		if(!ip->twm_win->isicon) {
8330bbfda8aSnia			if(visible(ip->twm_win)) {
8340bbfda8aSnia				SetMapStateProp(ip->twm_win, NormalState);
8350bbfda8aSnia				XMapWindow(dpy, ip->w);
8360bbfda8aSnia				XMapWindow(dpy, ip->twm_win->frame);
8370bbfda8aSnia			}
8380bbfda8aSnia			ip->twm_win->mapped = true;
8390bbfda8aSnia		}
8400bbfda8aSnia
8410bbfda8aSnia
8420bbfda8aSnia		/*
8430bbfda8aSnia		 * Stick this entry on the head of our list of "IM entries we
8440bbfda8aSnia		 * created", and loop around to the next WS for this IM.
8450bbfda8aSnia		 */
8460bbfda8aSnia		tmp->nextv = old;
8470bbfda8aSnia		old = tmp;
8480bbfda8aSnia		ip = ip->nextv;
8490bbfda8aSnia	}
8500bbfda8aSnia
8510bbfda8aSnia	/* If we didn't create at least one thing, we're done here */
8520bbfda8aSnia	if(tmp == NULL) {
8530bbfda8aSnia		return NULL;
8540bbfda8aSnia	}
8550bbfda8aSnia
8560bbfda8aSnia	/* Stash where the window is IM-listed */
8570bbfda8aSnia	tmp_win->iconmanagerlist = tmp;
8580bbfda8aSnia
8590bbfda8aSnia	/* ??? */
8600bbfda8aSnia	if(! visible(tmp->iconmgr->twm_win)) {
8610bbfda8aSnia		old = tmp;
8620bbfda8aSnia		tmp = tmp->nextv;
8630bbfda8aSnia		while(tmp != NULL) {
8640bbfda8aSnia			if(visible(tmp->iconmgr->twm_win)) {
8650bbfda8aSnia				break;
8660bbfda8aSnia			}
8670bbfda8aSnia			old = tmp;
8680bbfda8aSnia			tmp = tmp->nextv;
8690bbfda8aSnia		}
8700bbfda8aSnia		if(tmp != NULL) {
8710bbfda8aSnia			old->nextv = tmp->nextv;
8720bbfda8aSnia			tmp->nextv = tmp_win->iconmanagerlist;
8730bbfda8aSnia			tmp_win->iconmanagerlist = tmp;
8740bbfda8aSnia		}
8750bbfda8aSnia	}
8760bbfda8aSnia
8770bbfda8aSnia	/* Hand back the list places we added */
8780bbfda8aSnia	return tmp_win->iconmanagerlist;
879645f5050Syouri}
880645f5050Syouri
881645f5050Syouri/***********************************************************************
882645f5050Syouri *
883645f5050Syouri *  Procedure:
8840bbfda8aSnia *      InsertInIconManager - put an allocated entry into an icon
8850bbfda8aSnia *              manager
886645f5050Syouri *
887645f5050Syouri *  Inputs:
8880bbfda8aSnia *      ip      - the icon manager pointer
8890bbfda8aSnia *      tmp     - the entry to insert
890645f5050Syouri *
891645f5050Syouri ***********************************************************************
892645f5050Syouri */
893645f5050Syouri
894645f5050Syourivoid InsertInIconManager(IconMgr *ip, WList *tmp, TwmWindow *tmp_win)
895645f5050Syouri{
8960bbfda8aSnia	WList *tmp1;
8970bbfda8aSnia	bool added;
8980bbfda8aSnia
8990bbfda8aSnia	added = false;
9000bbfda8aSnia	if(ip->first == NULL) {
9010bbfda8aSnia		ip->first = tmp;
9020bbfda8aSnia		tmp->prev = NULL;
9030bbfda8aSnia		ip->last = tmp;
9040bbfda8aSnia		added = true;
9050bbfda8aSnia	}
9060bbfda8aSnia	else if(Scr->SortIconMgr) {
9070bbfda8aSnia		for(tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next) {
9080bbfda8aSnia			int compresult;
9090bbfda8aSnia			if(Scr->CaseSensitive) {
9100bbfda8aSnia				compresult = strcmp(tmp_win->icon_name, tmp1->twm->icon_name);
9110bbfda8aSnia			}
9120bbfda8aSnia			else {
9130bbfda8aSnia				compresult = strcasecmp(tmp_win->icon_name, tmp1->twm->icon_name);
9140bbfda8aSnia			}
9150bbfda8aSnia			if(compresult < 0) {
9160bbfda8aSnia				tmp->next = tmp1;
9170bbfda8aSnia				tmp->prev = tmp1->prev;
9180bbfda8aSnia				tmp1->prev = tmp;
9190bbfda8aSnia				if(tmp->prev == NULL) {
9200bbfda8aSnia					ip->first = tmp;
9210bbfda8aSnia				}
9220bbfda8aSnia				else {
9230bbfda8aSnia					tmp->prev->next = tmp;
9240bbfda8aSnia				}
9250bbfda8aSnia				added = true;
9260bbfda8aSnia				break;
9270bbfda8aSnia			}
9280bbfda8aSnia		}
9290bbfda8aSnia	}
9300bbfda8aSnia
9310bbfda8aSnia	if(!added) {
9320bbfda8aSnia		ip->last->next = tmp;
9330bbfda8aSnia		tmp->prev = ip->last;
9340bbfda8aSnia		ip->last = tmp;
9350bbfda8aSnia	}
936645f5050Syouri}
937645f5050Syouri
938645f5050Syourivoid RemoveFromIconManager(IconMgr *ip, WList *tmp)
939645f5050Syouri{
9400bbfda8aSnia	if(tmp->prev == NULL) {
9410bbfda8aSnia		ip->first = tmp->next;
9420bbfda8aSnia	}
9430bbfda8aSnia	else {
9440bbfda8aSnia		tmp->prev->next = tmp->next;
9450bbfda8aSnia	}
9460bbfda8aSnia
9470bbfda8aSnia	if(tmp->next == NULL) {
9480bbfda8aSnia		ip->last = tmp->prev;
9490bbfda8aSnia	}
9500bbfda8aSnia	else {
9510bbfda8aSnia		tmp->next->prev = tmp->prev;
9520bbfda8aSnia	}
9530bbfda8aSnia
9540bbfda8aSnia	/* pebl: If the list was the current and tmp was the last in the list
9550bbfda8aSnia	   reset current list */
9560bbfda8aSnia	if(Current == tmp) {
9570bbfda8aSnia		Current = ip->first;
9580bbfda8aSnia	}
959645f5050Syouri}
960645f5050Syouri
961645f5050Syouri/***********************************************************************
962645f5050Syouri *
963645f5050Syouri *  Procedure:
9640bbfda8aSnia *      RemoveIconManager - remove a window from the icon manager
965645f5050Syouri *
966645f5050Syouri *  Inputs:
9670bbfda8aSnia *      tmp_win - the TwmWindow structure
968645f5050Syouri *
969645f5050Syouri ***********************************************************************
970645f5050Syouri */
971645f5050Syouri
972645f5050Syourivoid RemoveIconManager(TwmWindow *tmp_win)
973645f5050Syouri{
9740bbfda8aSnia	IconMgr *ip;
9750bbfda8aSnia	WList *tmp, *tmp1, *save;
9760bbfda8aSnia
9770bbfda8aSnia	if(tmp_win->iconmanagerlist == NULL) {
9780bbfda8aSnia		return;
9790bbfda8aSnia	}
9800bbfda8aSnia
9810bbfda8aSnia	tmp  = tmp_win->iconmanagerlist;
9820bbfda8aSnia	tmp1 = NULL;
9830bbfda8aSnia
9840bbfda8aSnia	while(tmp != NULL) {
9850bbfda8aSnia		ip = tmp->iconmgr;
9860bbfda8aSnia		if((tmp_win->occupation & ip->twm_win->occupation) != 0) {
9870bbfda8aSnia			tmp1 = tmp;
9880bbfda8aSnia			tmp  = tmp->nextv;
9890bbfda8aSnia			continue;
9900bbfda8aSnia		}
9910bbfda8aSnia		RemoveFromIconManager(ip, tmp);
9920bbfda8aSnia
9930bbfda8aSnia		XDeleteContext(dpy, tmp->icon, TwmContext);
9940bbfda8aSnia		XDeleteContext(dpy, tmp->icon, ScreenContext);
9950bbfda8aSnia		XDestroyWindow(dpy, tmp->icon);
9960bbfda8aSnia		XDeleteContext(dpy, tmp->w, TwmContext);
9970bbfda8aSnia		XDeleteContext(dpy, tmp->w, ScreenContext);
9980bbfda8aSnia		XDestroyWindow(dpy, tmp->w);
9990bbfda8aSnia		ip->count -= 1;
10000bbfda8aSnia
10010bbfda8aSnia		PackIconManager(ip);
10020bbfda8aSnia
10030bbfda8aSnia		if(ip->count == 0) {
10040bbfda8aSnia			XUnmapWindow(dpy, ip->twm_win->frame);
10050bbfda8aSnia			ip->twm_win->mapped = false;
10060bbfda8aSnia		}
10070bbfda8aSnia		if(tmp1 == NULL) {
10080bbfda8aSnia			tmp_win->iconmanagerlist = tmp_win->iconmanagerlist->nextv;
10090bbfda8aSnia		}
10100bbfda8aSnia		else {
10110bbfda8aSnia			tmp1->nextv = tmp->nextv;
10120bbfda8aSnia		}
10130bbfda8aSnia
10140bbfda8aSnia		save = tmp;
10150bbfda8aSnia		tmp = tmp->nextv;
10160bbfda8aSnia		free(save);
10170bbfda8aSnia	}
1018645f5050Syouri}
1019645f5050Syouri
10200bbfda8aSniavoid CurrentIconManagerEntry(WList *current)
1021645f5050Syouri{
10220bbfda8aSnia	Current = current;
1023645f5050Syouri}
1024645f5050Syouri
1025645f5050Syourivoid ActiveIconManager(WList *active)
1026645f5050Syouri{
10270bbfda8aSnia	active->active = true;
10280bbfda8aSnia	Active = active;
10290bbfda8aSnia	Active->iconmgr->active = active;
10300bbfda8aSnia	Current = Active;
10310bbfda8aSnia	DrawIconManagerBorder(active, false);
1032645f5050Syouri}
1033645f5050Syouri
1034645f5050Syourivoid NotActiveIconManager(WList *active)
1035645f5050Syouri{
10360bbfda8aSnia	active->active = false;
10370bbfda8aSnia	DrawIconManagerBorder(active, false);
1038645f5050Syouri}
1039645f5050Syouri
10400bbfda8aSniavoid DrawIconManagerBorder(WList *tmp, bool fill)
1041645f5050Syouri{
10420bbfda8aSnia	if(Scr->use3Diconmanagers) {
10430bbfda8aSnia		Draw3DBorder(tmp->w, 0, 0, tmp->width, tmp->height,
10440bbfda8aSnia		             Scr->IconManagerShadowDepth, tmp->cp,
10450bbfda8aSnia		             (tmp->active && Scr->Highlight ? on : off),
10460bbfda8aSnia		             fill, false);
10470bbfda8aSnia	}
10480bbfda8aSnia	else {
10490bbfda8aSnia		XSetForeground(dpy, Scr->NormalGC, tmp->cp.fore);
10500bbfda8aSnia		XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 2, 2, tmp->width - 5,
10510bbfda8aSnia		               tmp->height - 5);
10520bbfda8aSnia
10530bbfda8aSnia		XSetForeground(dpy, Scr->NormalGC,
10540bbfda8aSnia		               (tmp->active && Scr->Highlight
10550bbfda8aSnia		                ? tmp->highlight : tmp->cp.back));
10560bbfda8aSnia
10570bbfda8aSnia		XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 0, 0, tmp->width - 1,
10580bbfda8aSnia		               tmp->height - 1);
10590bbfda8aSnia		XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 1, 1, tmp->width - 3,
10600bbfda8aSnia		               tmp->height - 3);
10610bbfda8aSnia	}
1062645f5050Syouri}
1063645f5050Syouri
1064645f5050Syouri/***********************************************************************
1065645f5050Syouri *
1066645f5050Syouri *  Procedure:
10670bbfda8aSnia *      SortIconManager - sort the dude
1068645f5050Syouri *
1069645f5050Syouri *  Inputs:
10700bbfda8aSnia *      ip      - a pointer to the icon manager struture
1071645f5050Syouri *
1072645f5050Syouri ***********************************************************************
1073645f5050Syouri */
1074645f5050Syouri
1075645f5050Syourivoid SortIconManager(IconMgr *ip)
1076645f5050Syouri{
10770bbfda8aSnia	WList *tmp1, *tmp2;
10780bbfda8aSnia	int done;
10790bbfda8aSnia
10800bbfda8aSnia	if(ip == NULL) {
10810bbfda8aSnia		ip = Active->iconmgr;
10820bbfda8aSnia	}
10830bbfda8aSnia
10840bbfda8aSnia	done = false;
10850bbfda8aSnia	do {
10860bbfda8aSnia		for(tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next) {
10870bbfda8aSnia			int compresult;
10880bbfda8aSnia			if((tmp2 = tmp1->next) == NULL) {
10890bbfda8aSnia				done = true;
10900bbfda8aSnia				break;
10910bbfda8aSnia			}
10920bbfda8aSnia			if(Scr->CaseSensitive) {
10930bbfda8aSnia				compresult = strcmp(tmp1->twm->icon_name, tmp2->twm->icon_name);
10940bbfda8aSnia			}
10950bbfda8aSnia			else {
10960bbfda8aSnia				compresult = strcasecmp(tmp1->twm->icon_name, tmp2->twm->icon_name);
10970bbfda8aSnia			}
10980bbfda8aSnia			if(compresult > 0) {
10990bbfda8aSnia				/* take it out and put it back in */
11000bbfda8aSnia				RemoveFromIconManager(ip, tmp2);
11010bbfda8aSnia				InsertInIconManager(ip, tmp2, tmp2->twm);
11020bbfda8aSnia				break;
11030bbfda8aSnia			}
11040bbfda8aSnia		}
11050bbfda8aSnia	}
11060bbfda8aSnia	while(!done);
11070bbfda8aSnia	PackIconManager(ip);
1108645f5050Syouri}
1109645f5050Syouri
1110645f5050Syouri/***********************************************************************
1111645f5050Syouri *
1112645f5050Syouri *  Procedure:
11130bbfda8aSnia *      PackIconManager - pack the icon manager windows following
11140bbfda8aSnia *              an addition or deletion
1115645f5050Syouri *
1116645f5050Syouri *  Inputs:
11170bbfda8aSnia *      ip      - a pointer to the icon manager struture
1118645f5050Syouri *
1119645f5050Syouri ***********************************************************************
1120645f5050Syouri */
1121645f5050Syouri
11220bbfda8aSniavoid PackIconManagers(void)
11230bbfda8aSnia{
11240bbfda8aSnia	TwmWindow *twm_win;
11250bbfda8aSnia
11260bbfda8aSnia	for(twm_win = Scr->FirstWindow; twm_win != NULL; twm_win = twm_win->next) {
11270bbfda8aSnia		if(twm_win->iconmgrp) {
11280bbfda8aSnia			PackIconManager(twm_win->iconmgrp);
11290bbfda8aSnia		}
11300bbfda8aSnia	}
11310bbfda8aSnia}
11320bbfda8aSnia
1133645f5050Syourivoid PackIconManager(IconMgr *ip)
1134645f5050Syouri{
11350bbfda8aSnia	int newwidth, i, row, col, maxcol,  colinc, rowinc, wheight, wwidth;
11360bbfda8aSnia	int new_x, new_y;
11370bbfda8aSnia	int savewidth;
11380bbfda8aSnia	WList *tmp;
11390bbfda8aSnia	int mask;
11400bbfda8aSnia
11410bbfda8aSnia	wheight = Scr->IconManagerFont.avg_height
11420bbfda8aSnia	          + 2 * (ICON_MGR_OBORDER + ICON_MGR_IBORDER);
11430bbfda8aSnia	if(wheight < (im_iconified_icon_height + 4)) {
11440bbfda8aSnia		wheight = im_iconified_icon_height + 4;
11450bbfda8aSnia	}
11460bbfda8aSnia
11470bbfda8aSnia	wwidth = ip->width / ip->columns;
11480bbfda8aSnia
11490bbfda8aSnia	rowinc = wheight;
11500bbfda8aSnia	colinc = wwidth;
11510bbfda8aSnia
11520bbfda8aSnia	row = 0;
11530bbfda8aSnia	col = ip->columns;
11540bbfda8aSnia	maxcol = 0;
11550bbfda8aSnia	for(i = 0, tmp = ip->first; tmp != NULL; i++, tmp = tmp->next) {
11560bbfda8aSnia		tmp->me = i;
11570bbfda8aSnia		if(++col >= ip->columns) {
11580bbfda8aSnia			col = 0;
11590bbfda8aSnia			row += 1;
11600bbfda8aSnia		}
11610bbfda8aSnia		if(col > maxcol) {
11620bbfda8aSnia			maxcol = col;
11630bbfda8aSnia		}
11640bbfda8aSnia
11650bbfda8aSnia		new_x = col * colinc;
11660bbfda8aSnia		new_y = (row - 1) * rowinc;
11670bbfda8aSnia
11680bbfda8aSnia		/* if the position or size has not changed, don't touch it */
11690bbfda8aSnia		if(tmp->x != new_x || tmp->y != new_y ||
11700bbfda8aSnia		                tmp->width != wwidth || tmp->height != wheight) {
11710bbfda8aSnia			XMoveResizeWindow(dpy, tmp->w, new_x, new_y, wwidth, wheight);
11720bbfda8aSnia			if(tmp->height != wheight)
11730bbfda8aSnia				XMoveWindow(dpy, tmp->icon, ICON_MGR_OBORDER + ICON_MGR_IBORDER,
11740bbfda8aSnia				            (wheight - im_iconified_icon_height) / 2);
11750bbfda8aSnia
11760bbfda8aSnia			tmp->row = row - 1;
11770bbfda8aSnia			tmp->col = col;
11780bbfda8aSnia			tmp->x = new_x;
11790bbfda8aSnia			tmp->y = new_y;
11800bbfda8aSnia			tmp->width = wwidth;
11810bbfda8aSnia			tmp->height = wheight;
11820bbfda8aSnia		}
11830bbfda8aSnia	}
11840bbfda8aSnia	maxcol += 1;
11850bbfda8aSnia
11860bbfda8aSnia	ip->cur_rows = row;
11870bbfda8aSnia	ip->cur_columns = maxcol;
11880bbfda8aSnia	ip->height = row * rowinc;
11890bbfda8aSnia	if(ip->height == 0) {
11900bbfda8aSnia		ip->height = rowinc;
11910bbfda8aSnia	}
11920bbfda8aSnia	newwidth = maxcol * colinc;
11930bbfda8aSnia	if(newwidth == 0) {
11940bbfda8aSnia		newwidth = colinc;
11950bbfda8aSnia	}
11960bbfda8aSnia
11970bbfda8aSnia	XResizeWindow(dpy, ip->w, newwidth, ip->height);
11980bbfda8aSnia
11990bbfda8aSnia	mask = XParseGeometry(ip->geometry, &JunkX, &JunkY,
12000bbfda8aSnia	                      &JunkWidth, &JunkHeight);
12010bbfda8aSnia	if(mask & XNegative) {
12020bbfda8aSnia		ip->twm_win->frame_x += ip->twm_win->frame_width - newwidth -
12030bbfda8aSnia		                        2 * ip->twm_win->frame_bw3D;
12040bbfda8aSnia	}
12050bbfda8aSnia	if(mask & YNegative) {
12060bbfda8aSnia		ip->twm_win->frame_y += ip->twm_win->frame_height - ip->height -
12070bbfda8aSnia		                        2 * ip->twm_win->frame_bw3D - ip->twm_win->title_height;
12080bbfda8aSnia	}
12090bbfda8aSnia	savewidth = ip->width;
12100bbfda8aSnia	if(ip->twm_win)
12110bbfda8aSnia		SetupWindow(ip->twm_win,
12120bbfda8aSnia		            ip->twm_win->frame_x, ip->twm_win->frame_y,
12130bbfda8aSnia		            newwidth + 2 * ip->twm_win->frame_bw3D,
12140bbfda8aSnia		            ip->height + ip->twm_win->title_height + 2 * ip->twm_win->frame_bw3D, -1);
12150bbfda8aSnia	ip->width = savewidth;
12160bbfda8aSnia}
12170bbfda8aSnia
12180bbfda8aSniavoid dump_iconmanager(IconMgr *mgr, char *label)
12190bbfda8aSnia{
12200bbfda8aSnia	fprintf(stderr, "IconMgr %s %p name='%s' geom='%s'\n",
12210bbfda8aSnia	        label,
12220bbfda8aSnia	        mgr,
12230bbfda8aSnia	        mgr->name,
12240bbfda8aSnia	        mgr->geometry);
12250bbfda8aSnia	fprintf(stderr, "next = %p, prev = %p, lasti = %p, nextv = %p\n",
12260bbfda8aSnia	        mgr->next,
12270bbfda8aSnia	        mgr->prev,
12280bbfda8aSnia	        mgr->lasti,
12290bbfda8aSnia	        mgr->nextv);
12300bbfda8aSnia}
12310bbfda8aSnia
12320bbfda8aSnia
12330bbfda8aSnia/*
12340bbfda8aSnia * Draw the window name into the icon manager line
12350bbfda8aSnia */
12360bbfda8aSniavoid
12370bbfda8aSniaDrawIconManagerIconName(TwmWindow *tmp_win)
12380bbfda8aSnia{
12390bbfda8aSnia	WList *iconmanagerlist = tmp_win->iconmanagerlist;
12400bbfda8aSnia	XRectangle ink_rect, logical_rect;
12410bbfda8aSnia
12420bbfda8aSnia	XmbTextExtents(Scr->IconManagerFont.font_set,
12430bbfda8aSnia	               tmp_win->icon_name, strlen(tmp_win->icon_name),
12440bbfda8aSnia	               &ink_rect, &logical_rect);
12450bbfda8aSnia
12460bbfda8aSnia	if(UpdateFont(&Scr->IconManagerFont, logical_rect.height)) {
12470bbfda8aSnia		PackIconManagers();
12480bbfda8aSnia	}
12490bbfda8aSnia
12500bbfda8aSnia	DrawIconManagerBorder(iconmanagerlist, true);
12510bbfda8aSnia
12520bbfda8aSnia	FB(iconmanagerlist->cp.fore, iconmanagerlist->cp.back);
12530bbfda8aSnia
12540bbfda8aSnia	/* XXX This is a completely absurd way of writing this */
12550bbfda8aSnia	((Scr->use3Diconmanagers && (Scr->Monochrome != COLOR)) ?
12560bbfda8aSnia	 XmbDrawImageString : XmbDrawString)
12570bbfda8aSnia	(dpy,
12580bbfda8aSnia	 iconmanagerlist->w,
12590bbfda8aSnia	 Scr->IconManagerFont.font_set,
12600bbfda8aSnia	 Scr->NormalGC,
12610bbfda8aSnia	 iconmgr_textx,
12620bbfda8aSnia	 (Scr->IconManagerFont.avg_height - logical_rect.height) / 2
12630bbfda8aSnia	 + (- logical_rect.y)
12640bbfda8aSnia	 + ICON_MGR_OBORDER
12650bbfda8aSnia	 + ICON_MGR_IBORDER,
12660bbfda8aSnia	 tmp_win->icon_name,
12670bbfda8aSnia	 strlen(tmp_win->icon_name));
12680bbfda8aSnia}
12690bbfda8aSnia
12700bbfda8aSnia
12710bbfda8aSnia/*
12720bbfda8aSnia * Copy the icon into the icon manager for a window that's iconified.
12730bbfda8aSnia * This is slightly different for the 3d vs 2d case, since the 3d is just
12740bbfda8aSnia * copying a pixmap in, while the 2d is drawing a bitmap in with the
12750bbfda8aSnia * fg/bg colors appropriate to the line.
12760bbfda8aSnia */
12770bbfda8aSniavoid
12780bbfda8aSniaShowIconifiedIcon(TwmWindow *tmp_win)
12790bbfda8aSnia{
12800bbfda8aSnia	WList *iconmanagerlist = tmp_win->iconmanagerlist;
12810bbfda8aSnia
12820bbfda8aSnia	if(Scr->use3Diconmanagers && iconmanagerlist->iconifypm) {
12830bbfda8aSnia		XCopyArea(dpy, iconmanagerlist->iconifypm,
12840bbfda8aSnia		          iconmanagerlist->icon,
12850bbfda8aSnia		          Scr->NormalGC, 0, 0,
12860bbfda8aSnia		          im_iconified_icon_width, im_iconified_icon_height, 0, 0);
12870bbfda8aSnia	}
12880bbfda8aSnia	else {
12890bbfda8aSnia		FB(iconmanagerlist->cp.fore, iconmanagerlist->cp.back);
12900bbfda8aSnia		XCopyPlane(dpy, Scr->siconifyPm, iconmanagerlist->icon,
12910bbfda8aSnia		           Scr->NormalGC, 0, 0,
12920bbfda8aSnia		           im_iconified_icon_width, im_iconified_icon_height, 0, 0, 1);
12930bbfda8aSnia	}
1294645f5050Syouri}
1295