~ctwm/ctwm/trunk

518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
1
/*
2
 * Colormap handling
3
 */
4
5
#include "ctwm.h"
6
521.1.23 by Matthew Fuller
Move free_cwins() over to colormaps.c since it's a colormap handling
7
#include <stdio.h>
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
8
#include <stdlib.h>
9
10
#include "colormaps.h"
11
#include "screen.h"
12
13
14
/*
15
 * From events.c; imported manually since I'm not listing it in events.h
16
 * because nowhere but here needs it.
17
 */
18
extern bool ColortableThrashing;
19
20
static Bool UninstallRootColormapQScanner(Display *display, XEvent *ev,
21
                char *args);
22
23
24
/***********************************************************************
25
 *
26
 *  Procedure:
27
 *      InstallWindowColormaps - install the colormaps for one twm window
28
 *
29
 *  Inputs:
30
 *      type    - type of event that caused the installation
31
 *      tmp     - for a subset of event types, the address of the
32
 *                window structure, whose colormaps are to be installed.
33
 *
34
 ***********************************************************************
518.1.32 by Matthew Fuller
Might as well mention the provenant of these funcs too.
35
 *
36
 * Previously in events.c
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
37
 */
604.1.9 by Matthew Fuller
These funcs are really returning a boolean value, so make them bool,
38
bool
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
39
InstallWindowColormaps(int type, TwmWindow *tmp)
40
{
41
	if(tmp) {
42
		return InstallColormaps(type, &tmp->cmaps);
43
	}
44
	else {
45
		return InstallColormaps(type, NULL);
46
	}
47
}
48
49
604.1.9 by Matthew Fuller
These funcs are really returning a boolean value, so make them bool,
50
bool
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
51
InstallColormaps(int type, Colormaps *cmaps)
52
{
53
	int i, j, n, number_cwins, state;
54
	ColormapWindow **cwins, *cwin, **maxcwin = NULL;
55
	TwmColormap *cmap;
56
	char *row, *scoreboard;
57
58
	switch(type) {
59
		case EnterNotify:
60
		case LeaveNotify:
61
		case DestroyNotify:
62
		default:
63
			/* Save the colormap to be loaded for when force loading of
64
			 * root colormap(s) ends.
65
			 */
66
			Scr->cmapInfo.pushed_cmaps = cmaps;
67
			/* Don't load any new colormap if root colormap(s) has been
68
			 * force loaded.
69
			 */
70
			if(Scr->cmapInfo.root_pushes) {
604.1.9 by Matthew Fuller
These funcs are really returning a boolean value, so make them bool,
71
				return false;
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
72
			}
73
			/* Don't reload the current window colormap list.
74
			if (Scr->cmapInfo.cmaps == cmaps)
604.1.9 by Matthew Fuller
These funcs are really returning a boolean value, so make them bool,
75
			    return false;
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
76
			 */
77
			if(Scr->cmapInfo.cmaps) {
78
				for(i = Scr->cmapInfo.cmaps->number_cwins,
79
				                cwins = Scr->cmapInfo.cmaps->cwins; i-- > 0; cwins++) {
80
					(*cwins)->colormap->state &= ~CM_INSTALLABLE;
81
				}
82
			}
83
			Scr->cmapInfo.cmaps = cmaps;
84
			break;
85
86
		case PropertyNotify:
87
		case VisibilityNotify:
88
		case ColormapNotify:
89
			break;
90
	}
91
92
	number_cwins = Scr->cmapInfo.cmaps->number_cwins;
93
	cwins = Scr->cmapInfo.cmaps->cwins;
94
	scoreboard = Scr->cmapInfo.cmaps->scoreboard;
95
96
	ColortableThrashing = false; /* in case installation aborted */
97
98
	state = CM_INSTALLED;
99
685.1.17 by Matthew Fuller
n isn't used in this loop, so drop it.
100
	for(i = 0; i < number_cwins; i++) {
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
101
		cwins[i]->colormap->state &= ~CM_INSTALL;
102
	}
103
	for(i = n = 0; i < number_cwins && n < Scr->cmapInfo.maxCmaps; i++) {
104
		cwin = cwins[i];
105
		cmap = cwin->colormap;
106
		if(cmap->state & CM_INSTALL) {
107
			continue;
108
		}
109
		cmap->state |= CM_INSTALLABLE;
110
		cmap->w = cwin->w;
111
		if(cwin->visibility != VisibilityFullyObscured) {
112
			row = scoreboard + (i * (i - 1) / 2);
113
			for(j = 0; j < i; j++)
114
				if(row[j] && (cwins[j]->colormap->state & CM_INSTALL)) {
115
					break;
116
				}
117
			if(j != i) {
118
				continue;
119
			}
120
			n++;
121
			maxcwin = &cwins[i];
122
			state &= (cmap->state & CM_INSTALLED);
123
			cmap->state |= CM_INSTALL;
124
		}
125
	}
644.2.32 by Matthew Fuller
Do necessary dpy conditionalization in the colormap stuff used in
126
127
	// Hack: special-case startup
128
	if(!dpy) {
129
		return true;
130
	}
131
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
132
	Scr->cmapInfo.first_req = NextRequest(dpy);
133
134
	for(; n > 0 && maxcwin >= &cwins[0]; maxcwin--) {
135
		cmap = (*maxcwin)->colormap;
136
		if(cmap->state & CM_INSTALL) {
137
			cmap->state &= ~CM_INSTALL;
138
			if(!(state & CM_INSTALLED)) {
139
				cmap->install_req = NextRequest(dpy);
140
				/* printf ("XInstallColormap : %x, %x\n", cmap, cmap->c); */
141
				XInstallColormap(dpy, cmap->c);
142
			}
143
			cmap->state |= CM_INSTALLED;
144
			n--;
145
		}
146
	}
604.1.9 by Matthew Fuller
These funcs are really returning a boolean value, so make them bool,
147
	return true;
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
148
}
149
150
151
152
/***********************************************************************
153
 *
154
 *  Procedures:
155
 *      <Uni/I>nstallRootColormap - Force (un)loads root colormap(s)
156
 *
157
 *         These matching routines provide a mechanism to insure that
158
 *         the root colormap(s) is installed during operations like
159
 *         rubber banding or menu display that require colors from
160
 *         that colormap.  Calls may be nested arbitrarily deeply,
161
 *         as long as there is one UninstallRootColormap call per
162
 *         InstallRootColormap call.
163
 *
164
 *         The final UninstallRootColormap will cause the colormap list
165
 *         which would otherwise have be loaded to be loaded, unless
166
 *         Enter or Leave Notify events are queued, indicating some
167
 *         other colormap list would potentially be loaded anyway.
168
 ***********************************************************************
518.1.32 by Matthew Fuller
Might as well mention the provenant of these funcs too.
169
 *
170
 * Previously in events.c
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
171
 */
172
void
173
InstallRootColormap(void)
174
{
175
	Colormaps *tmp;
176
	if(Scr->cmapInfo.root_pushes == 0) {
177
		/*
178
		 * The saving and restoring of cmapInfo.pushed_window here
179
		 * is a slimy way to remember the actual pushed list and
180
		 * not that of the root window.
181
		 */
182
		tmp = Scr->cmapInfo.pushed_cmaps;
183
		InstallColormaps(0, &Scr->RootColormaps);
184
		Scr->cmapInfo.pushed_cmaps = tmp;
185
	}
186
	Scr->cmapInfo.root_pushes++;
187
}
188
189
190
/* ARGSUSED*/
191
static Bool
192
UninstallRootColormapQScanner(Display *display, XEvent *ev,
193
                              char *args)
194
{
195
	if(!*args) {
196
		if(ev->type == EnterNotify) {
197
			if(ev->xcrossing.mode != NotifyGrab) {
198
				*args = 1;
199
			}
200
		}
201
		else if(ev->type == LeaveNotify) {
202
			if(ev->xcrossing.mode == NotifyNormal) {
203
				*args = 1;
204
			}
205
		}
206
	}
207
208
	return (False);
209
}
210
211
212
void
213
UninstallRootColormap(void)
214
{
215
	char args;
216
	XEvent dummy;
217
218
	if(Scr->cmapInfo.root_pushes) {
219
		Scr->cmapInfo.root_pushes--;
220
	}
221
222
	if(!Scr->cmapInfo.root_pushes) {
223
		/*
224
		 * If we have subsequent Enter or Leave Notify events,
225
		 * we can skip the reload of pushed colormaps.
226
		 */
227
		XSync(dpy, 0);
228
		args = 0;
522.1.1 by Matthew Fuller
Eliminate most (void) casts; they don't really add anything, and just
229
		XCheckIfEvent(dpy, &dummy, UninstallRootColormapQScanner, &args);
518.1.28 by Matthew Fuller
Inagurate a colormaps.c by pulling the colormap functions out of
230
231
		if(!args) {
232
			InstallColormaps(0, Scr->cmapInfo.pushed_cmaps);
233
		}
234
	}
235
}
518.1.31 by Matthew Fuller
Move these colormap-handling funcs from add_window.c to colormaps.c
236
237
238
/*
239
 * Create a TwmColormap struct and tie it to an [X] Colormap.  Places
240
 * that need to mess with colormaps and look up the metainfo we hang off
241
 * them need to look this up and find it via the X Context.
242
 *
243
 * Previously in add_window.c
244
 */
245
TwmColormap *
246
CreateTwmColormap(Colormap c)
247
{
248
	TwmColormap *cmap;
249
	cmap = malloc(sizeof(TwmColormap));
685.1.13 by Matthew Fuller
Work around spurious-ish gcc11 warning.
250
	if(!cmap) {
251
		return NULL;
518.1.31 by Matthew Fuller
Move these colormap-handling funcs from add_window.c to colormaps.c
252
	}
253
	cmap->c = c;
254
	cmap->state = 0;
255
	cmap->install_req = 0;
256
	cmap->w = None;
257
	cmap->refcnt = 1;
685.1.13 by Matthew Fuller
Work around spurious-ish gcc11 warning.
258
259
	if(XSaveContext(dpy, c, ColormapContext, (XPointer) cmap)) {
260
		free(cmap);
261
		return NULL;
262
	}
518.1.31 by Matthew Fuller
Move these colormap-handling funcs from add_window.c to colormaps.c
263
	return (cmap);
264
}
265
266
267
/*
268
 * Put together a ColormapWindow struct.  This is a thing we hang off a
269
 * TwmWindow for some colormap tracking stuff.
270
 *
271
 * Previously in add_window.c
272
 */
273
ColormapWindow *
274
CreateColormapWindow(Window w, bool creating_parent, bool property_window)
275
{
276
	ColormapWindow *cwin;
277
	TwmColormap *cmap;
278
	XWindowAttributes attributes;
279
280
	cwin = malloc(sizeof(ColormapWindow));
644.2.29 by Matthew Fuller
Invert conditional.
281
	if(cwin == NULL) {
282
		return NULL;
283
	}
284
644.2.31 by Matthew Fuller
Rearrange func slightly and stub in values for non-dpy case.
285
	// Common
286
	cwin->w = w;
287
288
	/*
289
	 * Assume that windows in colormap list are
290
	 * obscured if we are creating the parent window.
291
	 * Otherwise, we assume they are unobscured.
292
	 */
293
	cwin->visibility = creating_parent ?
294
	                   VisibilityPartiallyObscured : VisibilityUnobscured;
295
	cwin->refcnt = 1;
296
297
298
	// Stub for special cases
299
	if(dpy == NULL) {
300
		cwin->colormap = NULL;
301
		cwin->colormap = calloc(1, sizeof(TwmColormap));
302
		cwin->colormap->refcnt = 1;
303
304
		return cwin;
305
	}
306
307
644.2.30 by Matthew Fuller
make indent
308
	if(!XGetWindowAttributes(dpy, w, &attributes) ||
309
	                XSaveContext(dpy, w, ColormapContext, (XPointer) cwin)) {
310
		free(cwin);
311
		return (NULL);
312
	}
313
314
	if(XFindContext(dpy, attributes.colormap,  ColormapContext,
315
	                (XPointer *)&cwin->colormap) == XCNOENT) {
316
		cwin->colormap = cmap = CreateTwmColormap(attributes.colormap);
317
		if(!cmap) {
318
			XDeleteContext(dpy, w, ColormapContext);
518.1.31 by Matthew Fuller
Move these colormap-handling funcs from add_window.c to colormaps.c
319
			free(cwin);
320
			return (NULL);
321
		}
644.2.30 by Matthew Fuller
make indent
322
	}
323
	else {
324
		cwin->colormap->refcnt++;
325
	}
326
327
	/*
328
	 * If this is a ColormapWindow property window and we
329
	 * are not monitoring ColormapNotify or VisibilityNotify
330
	 * events, we need to.
331
	 */
332
	if(property_window &&
333
	                (attributes.your_event_mask &
334
	                 (ColormapChangeMask | VisibilityChangeMask)) !=
335
	                (ColormapChangeMask | VisibilityChangeMask)) {
336
		XSelectInput(dpy, w, attributes.your_event_mask |
337
		             (ColormapChangeMask | VisibilityChangeMask));
338
	}
518.1.31 by Matthew Fuller
Move these colormap-handling funcs from add_window.c to colormaps.c
339
340
	return (cwin);
341
}
342
343
344
/*
345
 * Do something with looking up stuff from WM_COLORMAPS_WINDOWS (relating
346
 * to windows with their own colormap) and finding or putting this window
347
 * into it.
348
 *
349
 * XXX Someone should figure it out better than that...
350
 *
351
 * Previously in add_window.c
352
 */
353
void
354
FetchWmColormapWindows(TwmWindow *tmp)
355
{
356
	int i, j;
357
	Window *cmap_windows = NULL;
358
	bool can_free_cmap_windows = false;
359
	int number_cmap_windows = 0;
360
	ColormapWindow **cwins = NULL;
518.1.37 by Matthew Fuller
bool-ify these boolean vars, break their definitions out of the if()
361
	bool previnst;
518.1.31 by Matthew Fuller
Move these colormap-handling funcs from add_window.c to colormaps.c
362
363
	number_cmap_windows = 0;
364
518.1.37 by Matthew Fuller
bool-ify these boolean vars, break their definitions out of the if()
365
	previnst = (Scr->cmapInfo.cmaps == &tmp->cmaps && tmp->cmaps.number_cwins);
366
	if(previnst) {
518.1.31 by Matthew Fuller
Move these colormap-handling funcs from add_window.c to colormaps.c
367
		cwins = tmp->cmaps.cwins;
368
		for(i = 0; i < tmp->cmaps.number_cwins; i++) {
369
			cwins[i]->colormap->state = 0;
370
		}
371
	}
372
373
	if(XGetWMColormapWindows(dpy, tmp->w, &cmap_windows,
374
	                         &number_cmap_windows) &&
375
	                number_cmap_windows > 0) {
376
377
		/*
378
		 * check if the top level is in the list, add to front if not
379
		 */
380
		for(i = 0; i < number_cmap_windows; i++) {
381
			if(cmap_windows[i] == tmp->w) {
382
				break;
383
			}
384
		}
385
		if(i == number_cmap_windows) {   /* not in list */
386
			Window *new_cmap_windows =
387
			        calloc((number_cmap_windows + 1), sizeof(Window));
388
389
			if(!new_cmap_windows) {
390
				fprintf(stderr,
391
				        "%s:  unable to allocate %d element colormap window array\n",
392
				        ProgramName, number_cmap_windows + 1);
393
				goto done;
394
			}
395
			new_cmap_windows[0] = tmp->w;  /* add to front */
396
			for(i = 0; i < number_cmap_windows; i++) {   /* append rest */
397
				new_cmap_windows[i + 1] = cmap_windows[i];
398
			}
399
			XFree(cmap_windows);
400
			can_free_cmap_windows = true;  /* do not use XFree any more */
401
			cmap_windows = new_cmap_windows;
402
			number_cmap_windows++;
403
		}
404
405
		cwins = calloc(number_cmap_windows, sizeof(ColormapWindow *));
406
		if(cwins) {
407
			for(i = 0; i < number_cmap_windows; i++) {
408
409
				/*
410
				 * Copy any existing entries into new list.
411
				 */
412
				for(j = 0; j < tmp->cmaps.number_cwins; j++) {
413
					if(tmp->cmaps.cwins[j]->w == cmap_windows[i]) {
414
						cwins[i] = tmp->cmaps.cwins[j];
415
						cwins[i]->refcnt++;
416
						break;
417
					}
418
				}
419
420
				/*
421
				 * If the colormap window is not being pointed by
422
				 * some other applications colormap window list,
423
				 * create a new entry.
424
				 */
425
				if(j == tmp->cmaps.number_cwins) {
426
					if(XFindContext(dpy, cmap_windows[i], ColormapContext,
427
					                (XPointer *)&cwins[i]) == XCNOENT) {
428
						if((cwins[i] = CreateColormapWindow(cmap_windows[i],
429
						                                    tmp->cmaps.number_cwins == 0,
430
						                                    true)) == NULL) {
431
							int k;
432
							for(k = i + 1; k < number_cmap_windows; k++) {
433
								cmap_windows[k - 1] = cmap_windows[k];
434
							}
435
							i--;
436
							number_cmap_windows--;
437
						}
438
					}
439
					else {
440
						cwins[i]->refcnt++;
441
					}
442
				}
443
			}
444
		}
445
	}
446
447
	/* No else here, in case we bailed out of clause above.
448
	 */
449
	if(number_cmap_windows == 0) {
450
451
		number_cmap_windows = 1;
452
453
		cwins = malloc(sizeof(ColormapWindow *));
454
		if(XFindContext(dpy, tmp->w, ColormapContext, (XPointer *)&cwins[0]) ==
455
		                XCNOENT)
456
			cwins[0] = CreateColormapWindow(tmp->w,
457
			                                tmp->cmaps.number_cwins == 0, false);
458
		else {
459
			cwins[0]->refcnt++;
460
		}
461
	}
462
463
	if(tmp->cmaps.number_cwins) {
464
		free_cwins(tmp);
465
	}
466
467
	tmp->cmaps.cwins = cwins;
468
	tmp->cmaps.number_cwins = number_cmap_windows;
469
	if(number_cmap_windows > 1)
470
		tmp->cmaps.scoreboard =
471
		        calloc(1, ColormapsScoreboardLength(&tmp->cmaps));
472
518.1.37 by Matthew Fuller
bool-ify these boolean vars, break their definitions out of the if()
473
	if(previnst) {
518.1.31 by Matthew Fuller
Move these colormap-handling funcs from add_window.c to colormaps.c
474
		InstallColormaps(PropertyNotify, NULL);
475
	}
476
477
done:
478
	if(cmap_windows) {
479
		if(can_free_cmap_windows) {
480
			free(cmap_windows);
481
		}
482
		else {
483
			XFree(cmap_windows);
484
		}
485
	}
486
}
518.1.33 by Matthew Fuller
Move BumpWindowColormap() into colormaps.c.
487
488
489
/*
518.1.34 by Matthew Fuller
Little more doc.
490
 * BumpWindowColormap - rotate our internal copy of WM_COLORMAP_WINDOWS.
491
 * This is the backend for f.colormap.
518.1.33 by Matthew Fuller
Move BumpWindowColormap() into colormaps.c.
492
 *
493
 * Previously in functions.c
494
 */
495
void
496
BumpWindowColormap(TwmWindow *tmp, int inc)
497
{
518.1.37 by Matthew Fuller
bool-ify these boolean vars, break their definitions out of the if()
498
	int i, j;
499
	bool previously_installed;
518.1.33 by Matthew Fuller
Move BumpWindowColormap() into colormaps.c.
500
	ColormapWindow **cwins;
501
502
	if(!tmp) {
503
		return;
504
	}
505
506
	if(inc && tmp->cmaps.number_cwins > 0) {
507
		cwins = calloc(tmp->cmaps.number_cwins, sizeof(ColormapWindow *));
508
		if(cwins) {
518.1.37 by Matthew Fuller
bool-ify these boolean vars, break their definitions out of the if()
509
			previously_installed = (Scr->cmapInfo.cmaps == &tmp->cmaps &&
518.1.38 by Matthew Fuller
make indent
510
			                        tmp->cmaps.number_cwins);
518.1.37 by Matthew Fuller
bool-ify these boolean vars, break their definitions out of the if()
511
			if(previously_installed) {
518.1.33 by Matthew Fuller
Move BumpWindowColormap() into colormaps.c.
512
				for(i = tmp->cmaps.number_cwins; i-- > 0;) {
513
					tmp->cmaps.cwins[i]->colormap->state = 0;
514
				}
515
			}
516
517
			for(i = 0; i < tmp->cmaps.number_cwins; i++) {
518
				j = i - inc;
519
				if(j >= tmp->cmaps.number_cwins) {
520
					j -= tmp->cmaps.number_cwins;
521
				}
522
				else if(j < 0) {
523
					j += tmp->cmaps.number_cwins;
524
				}
525
				cwins[j] = tmp->cmaps.cwins[i];
526
			}
527
528
			free(tmp->cmaps.cwins);
529
530
			tmp->cmaps.cwins = cwins;
531
532
			if(tmp->cmaps.number_cwins > 1)
533
				memset(tmp->cmaps.scoreboard, 0,
534
				       ColormapsScoreboardLength(&tmp->cmaps));
535
536
			if(previously_installed) {
537
				InstallColormaps(PropertyNotify, NULL);
538
			}
539
		}
540
	}
541
	else {
542
		FetchWmColormapWindows(tmp);
543
	}
544
	return;
545
}
518.1.35 by Matthew Fuller
Move more colormap funcs out of util.c into colormaps.c.
546
547
548
/*
549
 * Handlers for creating and linkin in, as well as deleting, a StdCmap
550
 * for a given XStandardColormap.
551
 *
552
 * Previously in util.c
553
 */
554
void
555
InsertRGBColormap(Atom a, XStandardColormap *maps, int nmaps,
556
                  bool replace)
557
{
558
	StdCmap *sc = NULL;
559
560
	if(replace) {                       /* locate existing entry */
561
		for(sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
562
			if(sc->atom == a) {
563
				break;
564
			}
565
		}
566
	}
567
568
	if(!sc) {                           /* no existing, allocate new */
569
		sc = calloc(1, sizeof(StdCmap));
570
		if(!sc) {
571
			fprintf(stderr, "%s:  unable to allocate %lu bytes for StdCmap\n",
572
			        ProgramName, (unsigned long) sizeof(StdCmap));
573
			return;
574
		}
647 by Matthew Fuller
Fix some possible leaks/use-after-free in InsertRGBColormap().
575
		replace = false;  // Didn't find one, can't replace
518.1.35 by Matthew Fuller
Move more colormap funcs out of util.c into colormaps.c.
576
	}
577
578
	if(replace) {                       /* just update contents */
579
		if(sc->maps) {
647 by Matthew Fuller
Fix some possible leaks/use-after-free in InsertRGBColormap().
580
			XFree(sc->maps);
518.1.35 by Matthew Fuller
Move more colormap funcs out of util.c into colormaps.c.
581
		}
582
		if(sc == Scr->StdCmapInfo.mru) {
583
			Scr->StdCmapInfo.mru = NULL;
584
		}
585
	}
586
	else {                              /* else appending */
587
		sc->next = NULL;
588
		sc->atom = a;
589
		if(Scr->StdCmapInfo.tail) {
590
			Scr->StdCmapInfo.tail->next = sc;
591
		}
592
		else {
593
			Scr->StdCmapInfo.head = sc;
594
		}
595
		Scr->StdCmapInfo.tail = sc;
596
	}
597
	sc->nmaps = nmaps;
598
	sc->maps = maps;
599
600
	return;
601
}
602
603
604
void
605
RemoveRGBColormap(Atom a)
606
{
607
	StdCmap *sc, *prev;
608
609
	prev = NULL;
610
	for(sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
611
		if(sc->atom == a) {
612
			break;
613
		}
614
		prev = sc;
615
	}
616
	if(sc) {                            /* found one */
617
		if(sc->maps) {
618
			XFree(sc->maps);
619
		}
620
		if(prev) {
621
			prev->next = sc->next;
622
		}
623
		if(Scr->StdCmapInfo.head == sc) {
624
			Scr->StdCmapInfo.head = sc->next;
625
		}
626
		if(Scr->StdCmapInfo.tail == sc) {
627
			Scr->StdCmapInfo.tail = prev;
628
		}
629
		if(Scr->StdCmapInfo.mru == sc) {
630
			Scr->StdCmapInfo.mru = NULL;
631
		}
632
	}
633
	return;
634
}
635
636
637
/*
638
 * Go through all the properties of the root window and setup
639
 * XStandardColormap's and our StdCmap's for any of them that are
640
 * actually RGB_COLORMAP types.  We're not actually _checking_ the types,
641
 * just letting XGetRGBColormaps() refuse to handle probably most of
642
 * them.  Called during startup.
643
 *
644
 * Previouly in util.c
645
 */
646
void
647
LocateStandardColormaps(void)
648
{
649
	Atom *atoms;
650
	int natoms;
651
	int i;
652
653
	atoms = XListProperties(dpy, Scr->Root, &natoms);
654
	for(i = 0; i < natoms; i++) {
655
		XStandardColormap *maps = NULL;
656
		int nmaps;
657
658
		if(XGetRGBColormaps(dpy, Scr->Root, &maps, &nmaps, atoms[i])) {
659
			/* if got one, then append to current list */
660
			InsertRGBColormap(atoms[i], maps, nmaps, false);
661
		}
662
	}
663
	if(atoms) {
664
		XFree(atoms);
665
	}
666
	return;
667
}
521.1.23 by Matthew Fuller
Move free_cwins() over to colormaps.c since it's a colormap handling
668
669
670
/*
671
 * Clear out and free TwmWindow.cmaps (struct Colormaps) bits for a window.
672
 *
673
 * Previously in events.c
674
 */
675
void
676
free_cwins(TwmWindow *tmp)
677
{
678
	int i;
679
	TwmColormap *cmap;
680
681
	if(tmp->cmaps.number_cwins) {
682
		for(i = 0; i < tmp->cmaps.number_cwins; i++) {
683
			if(--tmp->cmaps.cwins[i]->refcnt == 0) {
684
				cmap = tmp->cmaps.cwins[i]->colormap;
685
				if(--cmap->refcnt == 0) {
686
					XDeleteContext(dpy, cmap->c, ColormapContext);
687
					free(cmap);
688
				}
689
				XDeleteContext(dpy, tmp->cmaps.cwins[i]->w, ColormapContext);
690
				free(tmp->cmaps.cwins[i]);
691
			}
692
		}
693
		free(tmp->cmaps.cwins);
694
		if(tmp->cmaps.number_cwins > 1) {
695
			free(tmp->cmaps.scoreboard);
696
			tmp->cmaps.scoreboard = NULL;
697
		}
698
		tmp->cmaps.number_cwins = 0;
699
	}
700
}