10bbfda8aSnia/* 20bbfda8aSnia * Colormap handling 30bbfda8aSnia */ 40bbfda8aSnia 50bbfda8aSnia#include "ctwm.h" 60bbfda8aSnia 70bbfda8aSnia#include <stdio.h> 80bbfda8aSnia#include <stdlib.h> 90bbfda8aSnia 100bbfda8aSnia#include "colormaps.h" 110bbfda8aSnia#include "screen.h" 120bbfda8aSnia 130bbfda8aSnia 140bbfda8aSnia/* 150bbfda8aSnia * From events.c; imported manually since I'm not listing it in events.h 160bbfda8aSnia * because nowhere but here needs it. 170bbfda8aSnia */ 180bbfda8aSniaextern bool ColortableThrashing; 190bbfda8aSnia 200bbfda8aSniastatic Bool UninstallRootColormapQScanner(Display *display, XEvent *ev, 210bbfda8aSnia char *args); 220bbfda8aSnia 230bbfda8aSnia 240bbfda8aSnia/*********************************************************************** 250bbfda8aSnia * 260bbfda8aSnia * Procedure: 270bbfda8aSnia * InstallWindowColormaps - install the colormaps for one twm window 280bbfda8aSnia * 290bbfda8aSnia * Inputs: 300bbfda8aSnia * type - type of event that caused the installation 310bbfda8aSnia * tmp - for a subset of event types, the address of the 320bbfda8aSnia * window structure, whose colormaps are to be installed. 330bbfda8aSnia * 340bbfda8aSnia *********************************************************************** 350bbfda8aSnia * 360bbfda8aSnia * Previously in events.c 370bbfda8aSnia */ 380bbfda8aSniabool 390bbfda8aSniaInstallWindowColormaps(int type, TwmWindow *tmp) 400bbfda8aSnia{ 410bbfda8aSnia if(tmp) { 420bbfda8aSnia return InstallColormaps(type, &tmp->cmaps); 430bbfda8aSnia } 440bbfda8aSnia else { 450bbfda8aSnia return InstallColormaps(type, NULL); 460bbfda8aSnia } 470bbfda8aSnia} 480bbfda8aSnia 490bbfda8aSnia 500bbfda8aSniabool 510bbfda8aSniaInstallColormaps(int type, Colormaps *cmaps) 520bbfda8aSnia{ 530bbfda8aSnia int i, j, n, number_cwins, state; 540bbfda8aSnia ColormapWindow **cwins, *cwin, **maxcwin = NULL; 550bbfda8aSnia TwmColormap *cmap; 560bbfda8aSnia char *row, *scoreboard; 570bbfda8aSnia 580bbfda8aSnia switch(type) { 590bbfda8aSnia case EnterNotify: 600bbfda8aSnia case LeaveNotify: 610bbfda8aSnia case DestroyNotify: 620bbfda8aSnia default: 630bbfda8aSnia /* Save the colormap to be loaded for when force loading of 640bbfda8aSnia * root colormap(s) ends. 650bbfda8aSnia */ 660bbfda8aSnia Scr->cmapInfo.pushed_cmaps = cmaps; 670bbfda8aSnia /* Don't load any new colormap if root colormap(s) has been 680bbfda8aSnia * force loaded. 690bbfda8aSnia */ 700bbfda8aSnia if(Scr->cmapInfo.root_pushes) { 710bbfda8aSnia return false; 720bbfda8aSnia } 730bbfda8aSnia /* Don't reload the current window colormap list. 740bbfda8aSnia if (Scr->cmapInfo.cmaps == cmaps) 750bbfda8aSnia return false; 760bbfda8aSnia */ 770bbfda8aSnia if(Scr->cmapInfo.cmaps) { 780bbfda8aSnia for(i = Scr->cmapInfo.cmaps->number_cwins, 790bbfda8aSnia cwins = Scr->cmapInfo.cmaps->cwins; i-- > 0; cwins++) { 800bbfda8aSnia (*cwins)->colormap->state &= ~CM_INSTALLABLE; 810bbfda8aSnia } 820bbfda8aSnia } 830bbfda8aSnia Scr->cmapInfo.cmaps = cmaps; 840bbfda8aSnia break; 850bbfda8aSnia 860bbfda8aSnia case PropertyNotify: 870bbfda8aSnia case VisibilityNotify: 880bbfda8aSnia case ColormapNotify: 890bbfda8aSnia break; 900bbfda8aSnia } 910bbfda8aSnia 920bbfda8aSnia number_cwins = Scr->cmapInfo.cmaps->number_cwins; 930bbfda8aSnia cwins = Scr->cmapInfo.cmaps->cwins; 940bbfda8aSnia scoreboard = Scr->cmapInfo.cmaps->scoreboard; 950bbfda8aSnia 960bbfda8aSnia ColortableThrashing = false; /* in case installation aborted */ 970bbfda8aSnia 980bbfda8aSnia state = CM_INSTALLED; 990bbfda8aSnia 100b18c2d1eSnia for(i = 0; i < number_cwins; i++) { 1010bbfda8aSnia cwins[i]->colormap->state &= ~CM_INSTALL; 1020bbfda8aSnia } 1030bbfda8aSnia for(i = n = 0; i < number_cwins && n < Scr->cmapInfo.maxCmaps; i++) { 1040bbfda8aSnia cwin = cwins[i]; 1050bbfda8aSnia cmap = cwin->colormap; 1060bbfda8aSnia if(cmap->state & CM_INSTALL) { 1070bbfda8aSnia continue; 1080bbfda8aSnia } 1090bbfda8aSnia cmap->state |= CM_INSTALLABLE; 1100bbfda8aSnia cmap->w = cwin->w; 1110bbfda8aSnia if(cwin->visibility != VisibilityFullyObscured) { 1120bbfda8aSnia row = scoreboard + (i * (i - 1) / 2); 1130bbfda8aSnia for(j = 0; j < i; j++) 1140bbfda8aSnia if(row[j] && (cwins[j]->colormap->state & CM_INSTALL)) { 1150bbfda8aSnia break; 1160bbfda8aSnia } 1170bbfda8aSnia if(j != i) { 1180bbfda8aSnia continue; 1190bbfda8aSnia } 1200bbfda8aSnia n++; 1210bbfda8aSnia maxcwin = &cwins[i]; 1220bbfda8aSnia state &= (cmap->state & CM_INSTALLED); 1230bbfda8aSnia cmap->state |= CM_INSTALL; 1240bbfda8aSnia } 1250bbfda8aSnia } 126b18c2d1eSnia 127b18c2d1eSnia // Hack: special-case startup 128b18c2d1eSnia if(!dpy) { 129b18c2d1eSnia return true; 130b18c2d1eSnia } 131b18c2d1eSnia 1320bbfda8aSnia Scr->cmapInfo.first_req = NextRequest(dpy); 1330bbfda8aSnia 1340bbfda8aSnia for(; n > 0 && maxcwin >= &cwins[0]; maxcwin--) { 1350bbfda8aSnia cmap = (*maxcwin)->colormap; 1360bbfda8aSnia if(cmap->state & CM_INSTALL) { 1370bbfda8aSnia cmap->state &= ~CM_INSTALL; 1380bbfda8aSnia if(!(state & CM_INSTALLED)) { 1390bbfda8aSnia cmap->install_req = NextRequest(dpy); 1400bbfda8aSnia /* printf ("XInstallColormap : %x, %x\n", cmap, cmap->c); */ 1410bbfda8aSnia XInstallColormap(dpy, cmap->c); 1420bbfda8aSnia } 1430bbfda8aSnia cmap->state |= CM_INSTALLED; 1440bbfda8aSnia n--; 1450bbfda8aSnia } 1460bbfda8aSnia } 1470bbfda8aSnia return true; 1480bbfda8aSnia} 1490bbfda8aSnia 1500bbfda8aSnia 1510bbfda8aSnia 1520bbfda8aSnia/*********************************************************************** 1530bbfda8aSnia * 1540bbfda8aSnia * Procedures: 1550bbfda8aSnia * <Uni/I>nstallRootColormap - Force (un)loads root colormap(s) 1560bbfda8aSnia * 1570bbfda8aSnia * These matching routines provide a mechanism to insure that 1580bbfda8aSnia * the root colormap(s) is installed during operations like 1590bbfda8aSnia * rubber banding or menu display that require colors from 1600bbfda8aSnia * that colormap. Calls may be nested arbitrarily deeply, 1610bbfda8aSnia * as long as there is one UninstallRootColormap call per 1620bbfda8aSnia * InstallRootColormap call. 1630bbfda8aSnia * 1640bbfda8aSnia * The final UninstallRootColormap will cause the colormap list 1650bbfda8aSnia * which would otherwise have be loaded to be loaded, unless 1660bbfda8aSnia * Enter or Leave Notify events are queued, indicating some 1670bbfda8aSnia * other colormap list would potentially be loaded anyway. 1680bbfda8aSnia *********************************************************************** 1690bbfda8aSnia * 1700bbfda8aSnia * Previously in events.c 1710bbfda8aSnia */ 1720bbfda8aSniavoid 1730bbfda8aSniaInstallRootColormap(void) 1740bbfda8aSnia{ 1750bbfda8aSnia Colormaps *tmp; 1760bbfda8aSnia if(Scr->cmapInfo.root_pushes == 0) { 1770bbfda8aSnia /* 1780bbfda8aSnia * The saving and restoring of cmapInfo.pushed_window here 1790bbfda8aSnia * is a slimy way to remember the actual pushed list and 1800bbfda8aSnia * not that of the root window. 1810bbfda8aSnia */ 1820bbfda8aSnia tmp = Scr->cmapInfo.pushed_cmaps; 1830bbfda8aSnia InstallColormaps(0, &Scr->RootColormaps); 1840bbfda8aSnia Scr->cmapInfo.pushed_cmaps = tmp; 1850bbfda8aSnia } 1860bbfda8aSnia Scr->cmapInfo.root_pushes++; 1870bbfda8aSnia} 1880bbfda8aSnia 1890bbfda8aSnia 1900bbfda8aSnia/* ARGSUSED*/ 1910bbfda8aSniastatic Bool 1920bbfda8aSniaUninstallRootColormapQScanner(Display *display, XEvent *ev, 1930bbfda8aSnia char *args) 1940bbfda8aSnia{ 1950bbfda8aSnia if(!*args) { 1960bbfda8aSnia if(ev->type == EnterNotify) { 1970bbfda8aSnia if(ev->xcrossing.mode != NotifyGrab) { 1980bbfda8aSnia *args = 1; 1990bbfda8aSnia } 2000bbfda8aSnia } 2010bbfda8aSnia else if(ev->type == LeaveNotify) { 2020bbfda8aSnia if(ev->xcrossing.mode == NotifyNormal) { 2030bbfda8aSnia *args = 1; 2040bbfda8aSnia } 2050bbfda8aSnia } 2060bbfda8aSnia } 2070bbfda8aSnia 2080bbfda8aSnia return (False); 2090bbfda8aSnia} 2100bbfda8aSnia 2110bbfda8aSnia 2120bbfda8aSniavoid 2130bbfda8aSniaUninstallRootColormap(void) 2140bbfda8aSnia{ 2150bbfda8aSnia char args; 2160bbfda8aSnia XEvent dummy; 2170bbfda8aSnia 2180bbfda8aSnia if(Scr->cmapInfo.root_pushes) { 2190bbfda8aSnia Scr->cmapInfo.root_pushes--; 2200bbfda8aSnia } 2210bbfda8aSnia 2220bbfda8aSnia if(!Scr->cmapInfo.root_pushes) { 2230bbfda8aSnia /* 2240bbfda8aSnia * If we have subsequent Enter or Leave Notify events, 2250bbfda8aSnia * we can skip the reload of pushed colormaps. 2260bbfda8aSnia */ 2270bbfda8aSnia XSync(dpy, 0); 2280bbfda8aSnia args = 0; 2290bbfda8aSnia XCheckIfEvent(dpy, &dummy, UninstallRootColormapQScanner, &args); 2300bbfda8aSnia 2310bbfda8aSnia if(!args) { 2320bbfda8aSnia InstallColormaps(0, Scr->cmapInfo.pushed_cmaps); 2330bbfda8aSnia } 2340bbfda8aSnia } 2350bbfda8aSnia} 2360bbfda8aSnia 2370bbfda8aSnia 2380bbfda8aSnia/* 2390bbfda8aSnia * Create a TwmColormap struct and tie it to an [X] Colormap. Places 2400bbfda8aSnia * that need to mess with colormaps and look up the metainfo we hang off 2410bbfda8aSnia * them need to look this up and find it via the X Context. 2420bbfda8aSnia * 2430bbfda8aSnia * Previously in add_window.c 2440bbfda8aSnia */ 2450bbfda8aSniaTwmColormap * 2460bbfda8aSniaCreateTwmColormap(Colormap c) 2470bbfda8aSnia{ 2480bbfda8aSnia TwmColormap *cmap; 2490bbfda8aSnia cmap = malloc(sizeof(TwmColormap)); 250b18c2d1eSnia if(!cmap) { 251b18c2d1eSnia return NULL; 2520bbfda8aSnia } 2530bbfda8aSnia cmap->c = c; 2540bbfda8aSnia cmap->state = 0; 2550bbfda8aSnia cmap->install_req = 0; 2560bbfda8aSnia cmap->w = None; 2570bbfda8aSnia cmap->refcnt = 1; 258b18c2d1eSnia 259b18c2d1eSnia if(XSaveContext(dpy, c, ColormapContext, (XPointer) cmap)) { 260b18c2d1eSnia free(cmap); 261b18c2d1eSnia return NULL; 262b18c2d1eSnia } 2630bbfda8aSnia return (cmap); 2640bbfda8aSnia} 2650bbfda8aSnia 2660bbfda8aSnia 2670bbfda8aSnia/* 2680bbfda8aSnia * Put together a ColormapWindow struct. This is a thing we hang off a 2690bbfda8aSnia * TwmWindow for some colormap tracking stuff. 2700bbfda8aSnia * 2710bbfda8aSnia * Previously in add_window.c 2720bbfda8aSnia */ 2730bbfda8aSniaColormapWindow * 2740bbfda8aSniaCreateColormapWindow(Window w, bool creating_parent, bool property_window) 2750bbfda8aSnia{ 2760bbfda8aSnia ColormapWindow *cwin; 2770bbfda8aSnia TwmColormap *cmap; 2780bbfda8aSnia XWindowAttributes attributes; 2790bbfda8aSnia 2800bbfda8aSnia cwin = malloc(sizeof(ColormapWindow)); 281b18c2d1eSnia if(cwin == NULL) { 282b18c2d1eSnia return NULL; 283b18c2d1eSnia } 2840bbfda8aSnia 285b18c2d1eSnia // Common 286b18c2d1eSnia cwin->w = w; 2870bbfda8aSnia 288b18c2d1eSnia /* 289b18c2d1eSnia * Assume that windows in colormap list are 290b18c2d1eSnia * obscured if we are creating the parent window. 291b18c2d1eSnia * Otherwise, we assume they are unobscured. 292b18c2d1eSnia */ 293b18c2d1eSnia cwin->visibility = creating_parent ? 294b18c2d1eSnia VisibilityPartiallyObscured : VisibilityUnobscured; 295b18c2d1eSnia cwin->refcnt = 1; 2960bbfda8aSnia 297b18c2d1eSnia 298b18c2d1eSnia // Stub for special cases 299b18c2d1eSnia if(dpy == NULL) { 300b18c2d1eSnia cwin->colormap = NULL; 301b18c2d1eSnia cwin->colormap = calloc(1, sizeof(TwmColormap)); 302b18c2d1eSnia cwin->colormap->refcnt = 1; 303b18c2d1eSnia 304b18c2d1eSnia return cwin; 305b18c2d1eSnia } 306b18c2d1eSnia 307b18c2d1eSnia 308b18c2d1eSnia if(!XGetWindowAttributes(dpy, w, &attributes) || 309b18c2d1eSnia XSaveContext(dpy, w, ColormapContext, (XPointer) cwin)) { 310b18c2d1eSnia free(cwin); 311b18c2d1eSnia return (NULL); 312b18c2d1eSnia } 313b18c2d1eSnia 314b18c2d1eSnia if(XFindContext(dpy, attributes.colormap, ColormapContext, 315b18c2d1eSnia (XPointer *)&cwin->colormap) == XCNOENT) { 316b18c2d1eSnia cwin->colormap = cmap = CreateTwmColormap(attributes.colormap); 317b18c2d1eSnia if(!cmap) { 318b18c2d1eSnia XDeleteContext(dpy, w, ColormapContext); 319b18c2d1eSnia free(cwin); 320b18c2d1eSnia return (NULL); 3210bbfda8aSnia } 3220bbfda8aSnia } 323b18c2d1eSnia else { 324b18c2d1eSnia cwin->colormap->refcnt++; 325b18c2d1eSnia } 326b18c2d1eSnia 327b18c2d1eSnia /* 328b18c2d1eSnia * If this is a ColormapWindow property window and we 329b18c2d1eSnia * are not monitoring ColormapNotify or VisibilityNotify 330b18c2d1eSnia * events, we need to. 331b18c2d1eSnia */ 332b18c2d1eSnia if(property_window && 333b18c2d1eSnia (attributes.your_event_mask & 334b18c2d1eSnia (ColormapChangeMask | VisibilityChangeMask)) != 335b18c2d1eSnia (ColormapChangeMask | VisibilityChangeMask)) { 336b18c2d1eSnia XSelectInput(dpy, w, attributes.your_event_mask | 337b18c2d1eSnia (ColormapChangeMask | VisibilityChangeMask)); 338b18c2d1eSnia } 3390bbfda8aSnia 3400bbfda8aSnia return (cwin); 3410bbfda8aSnia} 3420bbfda8aSnia 3430bbfda8aSnia 3440bbfda8aSnia/* 3450bbfda8aSnia * Do something with looking up stuff from WM_COLORMAPS_WINDOWS (relating 3460bbfda8aSnia * to windows with their own colormap) and finding or putting this window 3470bbfda8aSnia * into it. 3480bbfda8aSnia * 3490bbfda8aSnia * XXX Someone should figure it out better than that... 3500bbfda8aSnia * 3510bbfda8aSnia * Previously in add_window.c 3520bbfda8aSnia */ 3530bbfda8aSniavoid 3540bbfda8aSniaFetchWmColormapWindows(TwmWindow *tmp) 3550bbfda8aSnia{ 3560bbfda8aSnia int i, j; 3570bbfda8aSnia Window *cmap_windows = NULL; 3580bbfda8aSnia bool can_free_cmap_windows = false; 3590bbfda8aSnia int number_cmap_windows = 0; 3600bbfda8aSnia ColormapWindow **cwins = NULL; 3610bbfda8aSnia bool previnst; 3620bbfda8aSnia 3630bbfda8aSnia number_cmap_windows = 0; 3640bbfda8aSnia 3650bbfda8aSnia previnst = (Scr->cmapInfo.cmaps == &tmp->cmaps && tmp->cmaps.number_cwins); 3660bbfda8aSnia if(previnst) { 3670bbfda8aSnia cwins = tmp->cmaps.cwins; 3680bbfda8aSnia for(i = 0; i < tmp->cmaps.number_cwins; i++) { 3690bbfda8aSnia cwins[i]->colormap->state = 0; 3700bbfda8aSnia } 3710bbfda8aSnia } 3720bbfda8aSnia 3730bbfda8aSnia if(XGetWMColormapWindows(dpy, tmp->w, &cmap_windows, 3740bbfda8aSnia &number_cmap_windows) && 3750bbfda8aSnia number_cmap_windows > 0) { 3760bbfda8aSnia 3770bbfda8aSnia /* 3780bbfda8aSnia * check if the top level is in the list, add to front if not 3790bbfda8aSnia */ 3800bbfda8aSnia for(i = 0; i < number_cmap_windows; i++) { 3810bbfda8aSnia if(cmap_windows[i] == tmp->w) { 3820bbfda8aSnia break; 3830bbfda8aSnia } 3840bbfda8aSnia } 3850bbfda8aSnia if(i == number_cmap_windows) { /* not in list */ 3860bbfda8aSnia Window *new_cmap_windows = 3870bbfda8aSnia calloc((number_cmap_windows + 1), sizeof(Window)); 3880bbfda8aSnia 3890bbfda8aSnia if(!new_cmap_windows) { 3900bbfda8aSnia fprintf(stderr, 3910bbfda8aSnia "%s: unable to allocate %d element colormap window array\n", 3920bbfda8aSnia ProgramName, number_cmap_windows + 1); 3930bbfda8aSnia goto done; 3940bbfda8aSnia } 3950bbfda8aSnia new_cmap_windows[0] = tmp->w; /* add to front */ 3960bbfda8aSnia for(i = 0; i < number_cmap_windows; i++) { /* append rest */ 3970bbfda8aSnia new_cmap_windows[i + 1] = cmap_windows[i]; 3980bbfda8aSnia } 3990bbfda8aSnia XFree(cmap_windows); 4000bbfda8aSnia can_free_cmap_windows = true; /* do not use XFree any more */ 4010bbfda8aSnia cmap_windows = new_cmap_windows; 4020bbfda8aSnia number_cmap_windows++; 4030bbfda8aSnia } 4040bbfda8aSnia 4050bbfda8aSnia cwins = calloc(number_cmap_windows, sizeof(ColormapWindow *)); 4060bbfda8aSnia if(cwins) { 4070bbfda8aSnia for(i = 0; i < number_cmap_windows; i++) { 4080bbfda8aSnia 4090bbfda8aSnia /* 4100bbfda8aSnia * Copy any existing entries into new list. 4110bbfda8aSnia */ 4120bbfda8aSnia for(j = 0; j < tmp->cmaps.number_cwins; j++) { 4130bbfda8aSnia if(tmp->cmaps.cwins[j]->w == cmap_windows[i]) { 4140bbfda8aSnia cwins[i] = tmp->cmaps.cwins[j]; 4150bbfda8aSnia cwins[i]->refcnt++; 4160bbfda8aSnia break; 4170bbfda8aSnia } 4180bbfda8aSnia } 4190bbfda8aSnia 4200bbfda8aSnia /* 4210bbfda8aSnia * If the colormap window is not being pointed by 4220bbfda8aSnia * some other applications colormap window list, 4230bbfda8aSnia * create a new entry. 4240bbfda8aSnia */ 4250bbfda8aSnia if(j == tmp->cmaps.number_cwins) { 4260bbfda8aSnia if(XFindContext(dpy, cmap_windows[i], ColormapContext, 4270bbfda8aSnia (XPointer *)&cwins[i]) == XCNOENT) { 4280bbfda8aSnia if((cwins[i] = CreateColormapWindow(cmap_windows[i], 4290bbfda8aSnia tmp->cmaps.number_cwins == 0, 4300bbfda8aSnia true)) == NULL) { 4310bbfda8aSnia int k; 4320bbfda8aSnia for(k = i + 1; k < number_cmap_windows; k++) { 4330bbfda8aSnia cmap_windows[k - 1] = cmap_windows[k]; 4340bbfda8aSnia } 4350bbfda8aSnia i--; 4360bbfda8aSnia number_cmap_windows--; 4370bbfda8aSnia } 4380bbfda8aSnia } 4390bbfda8aSnia else { 4400bbfda8aSnia cwins[i]->refcnt++; 4410bbfda8aSnia } 4420bbfda8aSnia } 4430bbfda8aSnia } 4440bbfda8aSnia } 4450bbfda8aSnia } 4460bbfda8aSnia 4470bbfda8aSnia /* No else here, in case we bailed out of clause above. 4480bbfda8aSnia */ 4490bbfda8aSnia if(number_cmap_windows == 0) { 4500bbfda8aSnia 4510bbfda8aSnia number_cmap_windows = 1; 4520bbfda8aSnia 4530bbfda8aSnia cwins = malloc(sizeof(ColormapWindow *)); 4540bbfda8aSnia if(XFindContext(dpy, tmp->w, ColormapContext, (XPointer *)&cwins[0]) == 4550bbfda8aSnia XCNOENT) 4560bbfda8aSnia cwins[0] = CreateColormapWindow(tmp->w, 4570bbfda8aSnia tmp->cmaps.number_cwins == 0, false); 4580bbfda8aSnia else { 4590bbfda8aSnia cwins[0]->refcnt++; 4600bbfda8aSnia } 4610bbfda8aSnia } 4620bbfda8aSnia 4630bbfda8aSnia if(tmp->cmaps.number_cwins) { 4640bbfda8aSnia free_cwins(tmp); 4650bbfda8aSnia } 4660bbfda8aSnia 4670bbfda8aSnia tmp->cmaps.cwins = cwins; 4680bbfda8aSnia tmp->cmaps.number_cwins = number_cmap_windows; 4690bbfda8aSnia if(number_cmap_windows > 1) 4700bbfda8aSnia tmp->cmaps.scoreboard = 4710bbfda8aSnia calloc(1, ColormapsScoreboardLength(&tmp->cmaps)); 4720bbfda8aSnia 4730bbfda8aSnia if(previnst) { 4740bbfda8aSnia InstallColormaps(PropertyNotify, NULL); 4750bbfda8aSnia } 4760bbfda8aSnia 4770bbfda8aSniadone: 4780bbfda8aSnia if(cmap_windows) { 4790bbfda8aSnia if(can_free_cmap_windows) { 4800bbfda8aSnia free(cmap_windows); 4810bbfda8aSnia } 4820bbfda8aSnia else { 4830bbfda8aSnia XFree(cmap_windows); 4840bbfda8aSnia } 4850bbfda8aSnia } 4860bbfda8aSnia} 4870bbfda8aSnia 4880bbfda8aSnia 4890bbfda8aSnia/* 4900bbfda8aSnia * BumpWindowColormap - rotate our internal copy of WM_COLORMAP_WINDOWS. 4910bbfda8aSnia * This is the backend for f.colormap. 4920bbfda8aSnia * 4930bbfda8aSnia * Previously in functions.c 4940bbfda8aSnia */ 4950bbfda8aSniavoid 4960bbfda8aSniaBumpWindowColormap(TwmWindow *tmp, int inc) 4970bbfda8aSnia{ 4980bbfda8aSnia int i, j; 4990bbfda8aSnia bool previously_installed; 5000bbfda8aSnia ColormapWindow **cwins; 5010bbfda8aSnia 5020bbfda8aSnia if(!tmp) { 5030bbfda8aSnia return; 5040bbfda8aSnia } 5050bbfda8aSnia 5060bbfda8aSnia if(inc && tmp->cmaps.number_cwins > 0) { 5070bbfda8aSnia cwins = calloc(tmp->cmaps.number_cwins, sizeof(ColormapWindow *)); 5080bbfda8aSnia if(cwins) { 5090bbfda8aSnia previously_installed = (Scr->cmapInfo.cmaps == &tmp->cmaps && 5100bbfda8aSnia tmp->cmaps.number_cwins); 5110bbfda8aSnia if(previously_installed) { 5120bbfda8aSnia for(i = tmp->cmaps.number_cwins; i-- > 0;) { 5130bbfda8aSnia tmp->cmaps.cwins[i]->colormap->state = 0; 5140bbfda8aSnia } 5150bbfda8aSnia } 5160bbfda8aSnia 5170bbfda8aSnia for(i = 0; i < tmp->cmaps.number_cwins; i++) { 5180bbfda8aSnia j = i - inc; 5190bbfda8aSnia if(j >= tmp->cmaps.number_cwins) { 5200bbfda8aSnia j -= tmp->cmaps.number_cwins; 5210bbfda8aSnia } 5220bbfda8aSnia else if(j < 0) { 5230bbfda8aSnia j += tmp->cmaps.number_cwins; 5240bbfda8aSnia } 5250bbfda8aSnia cwins[j] = tmp->cmaps.cwins[i]; 5260bbfda8aSnia } 5270bbfda8aSnia 5280bbfda8aSnia free(tmp->cmaps.cwins); 5290bbfda8aSnia 5300bbfda8aSnia tmp->cmaps.cwins = cwins; 5310bbfda8aSnia 5320bbfda8aSnia if(tmp->cmaps.number_cwins > 1) 5330bbfda8aSnia memset(tmp->cmaps.scoreboard, 0, 5340bbfda8aSnia ColormapsScoreboardLength(&tmp->cmaps)); 5350bbfda8aSnia 5360bbfda8aSnia if(previously_installed) { 5370bbfda8aSnia InstallColormaps(PropertyNotify, NULL); 5380bbfda8aSnia } 5390bbfda8aSnia } 5400bbfda8aSnia } 5410bbfda8aSnia else { 5420bbfda8aSnia FetchWmColormapWindows(tmp); 5430bbfda8aSnia } 5440bbfda8aSnia return; 5450bbfda8aSnia} 5460bbfda8aSnia 5470bbfda8aSnia 5480bbfda8aSnia/* 5490bbfda8aSnia * Handlers for creating and linkin in, as well as deleting, a StdCmap 5500bbfda8aSnia * for a given XStandardColormap. 5510bbfda8aSnia * 5520bbfda8aSnia * Previously in util.c 5530bbfda8aSnia */ 5540bbfda8aSniavoid 5550bbfda8aSniaInsertRGBColormap(Atom a, XStandardColormap *maps, int nmaps, 5560bbfda8aSnia bool replace) 5570bbfda8aSnia{ 5580bbfda8aSnia StdCmap *sc = NULL; 5590bbfda8aSnia 5600bbfda8aSnia if(replace) { /* locate existing entry */ 5610bbfda8aSnia for(sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 5620bbfda8aSnia if(sc->atom == a) { 5630bbfda8aSnia break; 5640bbfda8aSnia } 5650bbfda8aSnia } 5660bbfda8aSnia } 5670bbfda8aSnia 5680bbfda8aSnia if(!sc) { /* no existing, allocate new */ 5690bbfda8aSnia sc = calloc(1, sizeof(StdCmap)); 5700bbfda8aSnia if(!sc) { 5710bbfda8aSnia fprintf(stderr, "%s: unable to allocate %lu bytes for StdCmap\n", 5720bbfda8aSnia ProgramName, (unsigned long) sizeof(StdCmap)); 5730bbfda8aSnia return; 5740bbfda8aSnia } 575b18c2d1eSnia replace = false; // Didn't find one, can't replace 5760bbfda8aSnia } 5770bbfda8aSnia 5780bbfda8aSnia if(replace) { /* just update contents */ 5790bbfda8aSnia if(sc->maps) { 580b18c2d1eSnia XFree(sc->maps); 5810bbfda8aSnia } 5820bbfda8aSnia if(sc == Scr->StdCmapInfo.mru) { 5830bbfda8aSnia Scr->StdCmapInfo.mru = NULL; 5840bbfda8aSnia } 5850bbfda8aSnia } 5860bbfda8aSnia else { /* else appending */ 5870bbfda8aSnia sc->next = NULL; 5880bbfda8aSnia sc->atom = a; 5890bbfda8aSnia if(Scr->StdCmapInfo.tail) { 5900bbfda8aSnia Scr->StdCmapInfo.tail->next = sc; 5910bbfda8aSnia } 5920bbfda8aSnia else { 5930bbfda8aSnia Scr->StdCmapInfo.head = sc; 5940bbfda8aSnia } 5950bbfda8aSnia Scr->StdCmapInfo.tail = sc; 5960bbfda8aSnia } 5970bbfda8aSnia sc->nmaps = nmaps; 5980bbfda8aSnia sc->maps = maps; 5990bbfda8aSnia 6000bbfda8aSnia return; 6010bbfda8aSnia} 6020bbfda8aSnia 6030bbfda8aSnia 6040bbfda8aSniavoid 6050bbfda8aSniaRemoveRGBColormap(Atom a) 6060bbfda8aSnia{ 6070bbfda8aSnia StdCmap *sc, *prev; 6080bbfda8aSnia 6090bbfda8aSnia prev = NULL; 6100bbfda8aSnia for(sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 6110bbfda8aSnia if(sc->atom == a) { 6120bbfda8aSnia break; 6130bbfda8aSnia } 6140bbfda8aSnia prev = sc; 6150bbfda8aSnia } 6160bbfda8aSnia if(sc) { /* found one */ 6170bbfda8aSnia if(sc->maps) { 6180bbfda8aSnia XFree(sc->maps); 6190bbfda8aSnia } 6200bbfda8aSnia if(prev) { 6210bbfda8aSnia prev->next = sc->next; 6220bbfda8aSnia } 6230bbfda8aSnia if(Scr->StdCmapInfo.head == sc) { 6240bbfda8aSnia Scr->StdCmapInfo.head = sc->next; 6250bbfda8aSnia } 6260bbfda8aSnia if(Scr->StdCmapInfo.tail == sc) { 6270bbfda8aSnia Scr->StdCmapInfo.tail = prev; 6280bbfda8aSnia } 6290bbfda8aSnia if(Scr->StdCmapInfo.mru == sc) { 6300bbfda8aSnia Scr->StdCmapInfo.mru = NULL; 6310bbfda8aSnia } 6320bbfda8aSnia } 6330bbfda8aSnia return; 6340bbfda8aSnia} 6350bbfda8aSnia 6360bbfda8aSnia 6370bbfda8aSnia/* 6380bbfda8aSnia * Go through all the properties of the root window and setup 6390bbfda8aSnia * XStandardColormap's and our StdCmap's for any of them that are 6400bbfda8aSnia * actually RGB_COLORMAP types. We're not actually _checking_ the types, 6410bbfda8aSnia * just letting XGetRGBColormaps() refuse to handle probably most of 6420bbfda8aSnia * them. Called during startup. 6430bbfda8aSnia * 6440bbfda8aSnia * Previouly in util.c 6450bbfda8aSnia */ 6460bbfda8aSniavoid 6470bbfda8aSniaLocateStandardColormaps(void) 6480bbfda8aSnia{ 6490bbfda8aSnia Atom *atoms; 6500bbfda8aSnia int natoms; 6510bbfda8aSnia int i; 6520bbfda8aSnia 6530bbfda8aSnia atoms = XListProperties(dpy, Scr->Root, &natoms); 6540bbfda8aSnia for(i = 0; i < natoms; i++) { 6550bbfda8aSnia XStandardColormap *maps = NULL; 6560bbfda8aSnia int nmaps; 6570bbfda8aSnia 6580bbfda8aSnia if(XGetRGBColormaps(dpy, Scr->Root, &maps, &nmaps, atoms[i])) { 6590bbfda8aSnia /* if got one, then append to current list */ 6600bbfda8aSnia InsertRGBColormap(atoms[i], maps, nmaps, false); 6610bbfda8aSnia } 6620bbfda8aSnia } 6630bbfda8aSnia if(atoms) { 6640bbfda8aSnia XFree(atoms); 6650bbfda8aSnia } 6660bbfda8aSnia return; 6670bbfda8aSnia} 6680bbfda8aSnia 6690bbfda8aSnia 6700bbfda8aSnia/* 6710bbfda8aSnia * Clear out and free TwmWindow.cmaps (struct Colormaps) bits for a window. 6720bbfda8aSnia * 6730bbfda8aSnia * Previously in events.c 6740bbfda8aSnia */ 6750bbfda8aSniavoid 6760bbfda8aSniafree_cwins(TwmWindow *tmp) 6770bbfda8aSnia{ 6780bbfda8aSnia int i; 6790bbfda8aSnia TwmColormap *cmap; 6800bbfda8aSnia 6810bbfda8aSnia if(tmp->cmaps.number_cwins) { 6820bbfda8aSnia for(i = 0; i < tmp->cmaps.number_cwins; i++) { 6830bbfda8aSnia if(--tmp->cmaps.cwins[i]->refcnt == 0) { 6840bbfda8aSnia cmap = tmp->cmaps.cwins[i]->colormap; 6850bbfda8aSnia if(--cmap->refcnt == 0) { 6860bbfda8aSnia XDeleteContext(dpy, cmap->c, ColormapContext); 6870bbfda8aSnia free(cmap); 6880bbfda8aSnia } 6890bbfda8aSnia XDeleteContext(dpy, tmp->cmaps.cwins[i]->w, ColormapContext); 6900bbfda8aSnia free(tmp->cmaps.cwins[i]); 6910bbfda8aSnia } 6920bbfda8aSnia } 6930bbfda8aSnia free(tmp->cmaps.cwins); 6940bbfda8aSnia if(tmp->cmaps.number_cwins > 1) { 6950bbfda8aSnia free(tmp->cmaps.scoreboard); 6960bbfda8aSnia tmp->cmaps.scoreboard = NULL; 6970bbfda8aSnia } 6980bbfda8aSnia tmp->cmaps.number_cwins = 0; 6990bbfda8aSnia } 7000bbfda8aSnia} 701