home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v92.tgz
/
v92.tar
/
v92
/
src
/
runtime
/
rxrsc.ri
< prev
next >
Wrap
Text File
|
1996-03-22
|
23KB
|
915 lines
/*
* File: rxrsc.ri - X Window specific resource allocation/deallocation
*
* Resources are allocated through a layer of internal management
* routines in order to handle aliasing and resource sharing.
*/
wdp wdsplys;
wfp findfont Params((wbp w, char *fam, int size, int flags));
/*
* Allocate a color given linear r, g, b. Colors are shared on a
* per-display basis, but they are often freed on a per-window basis,
* so they are remembered in two structures.
*/
wclrp alc_rgb(w,s,r,g,b,is_iconcolor)
wbp w;
char *s;
unsigned int r,g,b;
int is_iconcolor;
{
LinearColor lc;
XColor color;
int i;
int *numColors;
short *theColors;
STDLOCALS(w);
/*
* handle black and white specially (no allocation)
*/
if ((r == 0) && (g == 0) && (b == 0))
return &(wd->colors[0]);
if ((r == 65535) && (g == 65535) && (b == 65535))
return &(wd->colors[1]);
if (is_iconcolor) {
if (ws->iconColors == NULL) {
ws->iconColors = (short *)calloc(WMAXCOLORS, sizeof(short));
if (ws->iconColors == NULL) return NULL;
}
numColors = &(ws->numiColors);
theColors = ws->iconColors;
}
else {
if (ws->theColors == NULL) {
ws->theColors = (short *)calloc(WMAXCOLORS, sizeof(short));
if (ws->theColors == NULL) return NULL;
}
numColors = &(ws->numColors);
theColors = ws->theColors;
}
/*
* Change into server-dependent R G B
*/
lc.red = r;
lc.green = g;
lc.blue = b;
color = xcolor(w, lc);
r = color.red;
g = color.green;
b = color.blue;
/*
* Search for the color in w's display
*/
for (i = 2; i < wd->numColors; i++) {
if (wd->colors[i].refcount>0 &&
wd->colors[i].type == SHARED &&
color.red == wd->colors[i].r &&
color.green == wd->colors[i].g &&
color.blue == wd->colors[i].b)
break;
}
if (i >= wd->numColors) {
int j;
/*
* color not found, must allocate
* first verify there is room in window color table.
*/
if (*numColors == WMAXCOLORS) {
return NULL;
}
if (!XAllocColor(stddpy, wd->cmap, &color)) {
/* try again with a virtual colormap (but not for an icon) */
if (is_iconcolor || !go_virtual(w) ||
!XAllocColor(stddpy, wd->cmap, &color))
return NULL;
}
j = alc_centry(wd);
if (j == 0)
return NULL;
strcpy(wd->colors[j].name, s);
/*
* Store server color as requested in color table.
*/
wd->colors[j].r = r;
wd->colors[j].g = g;
wd->colors[j].b = b;
wd->colors[j].c = color.pixel;
wd->colors[j].type = SHARED;
theColors[(*numColors)++] = j;
return &(wd->colors[j]);
}
else {
/* color is found, alias it and put it in the window color table */
int k;
for(k=0; k < *numColors; k++){
if (theColors[k] == i) {
/* already there, no further action needed */
return &(wd->colors[i]);
}
}
wd->colors[i].refcount++;
theColors[(*numColors)++] = i;
return &(wd->colors[i]);
}
}
/*
* allocate a color entry, return index (or 0 if table is full)
*/
int alc_centry(wd)
wdp wd;
{
int j;
for (j = 2; j < DMAXCOLORS; j++)
if (wd->colors[j].refcount == 0)
break;
if (j == DMAXCOLORS)
return 0;
if (j == wd->numColors)
wd->numColors++;
else if (j > wd->numColors)
return 0; /* internal confusion */
wd->colors[j].refcount = 1;
return j;
}
/*
* allocate by named color and return Icon color pointer.
* This is used by setfg and setbg.
*/
wclrp alc_color(w,s)
wbp w;
char *s;
{
wclrp rv;
wsp ws = w->window;
long r, g, b;
/*
* convert color to an r,g,b triple
*/
if (parsecolor(w, s, &r, &g, &b) != Succeeded)
return 0;
/*
* return Icon color structure, allocated & reference counted in display
*/
Protect(rv = alc_rgb(w, s, r, g, b, 0), return 0);
return rv;
}
/*
* copy color entries to reflect pixel transmission via CopyArea()
* (assumes w1 and w2 are on the same display)
*/
novalue copy_colors(w1, w2)
wbp w1, w2;
{
wsp ws1 = w1->window, ws2 = w2 -> window;
wdp wd = ws1->display;
int i1, i2, j;
for (i1 = 0; i1 < ws1->numColors; i1++) {
j = ws1->theColors[i1];
if (wd->colors[j].refcount > 0 && wd->colors[j].type != MUTABLE) {
for (i2 = 0; i2 < ws2->numColors; i2++) {
if (j == ws2->theColors[i2])
break;
}
if (i2 >= ws2->numColors) {
/* need to add this color */
wd->colors[j].refcount++;
if (ws2->numColors < WMAXCOLORS) {
if (ws2->theColors == NULL)
ws2->theColors = (short *)calloc(WMAXCOLORS, sizeof(short));
if (ws2->theColors == NULL)
break; /* unlikely bug; should fail or something */
ws2->theColors[ws2->numColors++] = j;
}
/* else cannot record it -- table full */
}
}
}
}
/*
* free a single color allocated by a given window
*/
novalue free_xcolor(w,c)
wbp w;
unsigned long c;
{
int i;
STDLOCALS(w);
for (i = 0; i < ws->numColors; i++) {
if (wd->colors[ws->theColors[i]].c == c) break;
}
if (i >= ws->numColors) {
/* "free_xcolor couldn't find the color in the window\n" */
}
else {
if (--(wd->colors[ws->theColors[i]].refcount) == 0) {
XFreeColors(stddpy, wd->cmap, &c, 1, 0);
ws->numColors--;
if (ws->numColors != i)
ws->theColors[i] = ws->theColors[ws->numColors];
}
}
}
/*
* free the colors allocated by a given window. extent indicates how much
* to free. extent == 0 implies window colors except black, white,
* fg, bg, wbg, and mutable colors. extent == 1 implies free icon colors.
* extent == 2 implies free window AND fg/bg/wbg (window is closed)
*/
novalue free_xcolors(w, extent)
wbp w;
int extent;
{
int i;
unsigned long toFree[DMAXCOLORS];
int freed = 0;
int *numColors;
int numSaved;
short *theColors;
STDLOCALS(w);
numColors = (extent==1 ? &(ws->numiColors) : &(ws->numColors));
theColors = (extent==1 ? ws->iconColors : ws->theColors);
numSaved = 0;
for (i = *numColors-1; i >= 0; i--) {
int j = theColors[i];
if (j < 2) /* black & white are permanent residents */
continue;
/*
* don't free fg, bg, or mutable color
*/
if (((extent==0) && (&(wd->colors[j]) == w->context->fg)) ||
((extent==0) && (&(wd->colors[j]) == w->context->bg)) ||
(wd->colors[j].type == MUTABLE)) {
theColors[numSaved++] = j;
continue;
}
if (--(wd->colors[j].refcount) == 0) {
toFree[freed++] = wd->colors[j].c;
}
}
if (freed>0)
XFreeColors(stddpy, wd->cmap, toFree, freed,0);
*numColors = numSaved;
}
/*
* Allocate a virtual colormap with all colors used by the client copied from
* the default colormap to new colormap, and set all windows to use this new
* colormap. Returns 0 on failure.
*/
int go_virtual(w)
wbp w;
{
wsp win;
STDLOCALS(w);
if (wd->cmap != DefaultColormap(stddpy,wd->screen))
return 0; /* already using a virtual colormap */
wd->cmap = XCopyColormapAndFree(stddpy,wd->cmap);
/* set the colormap for all the windows to the new colormap */
for (win = wstates; win; win = win->next)
if ((win->display->display == stddpy) & (win->win != (Window)NULL))
XSetWindowColormap(stddpy, win->win, wd->cmap);
return 1;
}
/*
* allocate a display on machine s
*/
wdp alc_display(s)
char *s;
{
int i;
double g;
wdp wd;
XColor color;
if (s == NULL) s = getenv("DISPLAY");
if (s == NULL) s = "";
for(wd = wdsplys; wd; wd = wd->next)
if (!strcmp(wd->name,s)) {
wd->refcount++;
return wd;
}
GRFX_ALLOC(wd, _wdisplay);
strcpy(wd->name,s);
wd->display = XOpenDisplay((*s=='\0') ? NULL : s);
if (wd->display == NULL) {
wd->refcount = 0;
free(wd);
return NULL;
}
wd->screen = DefaultScreen(wd->display);
wd->cmap = DefaultColormap(wd->display, wd->screen);
/*
* Color slots 0 and 1 are permanently reserved for black and white
* respectively. Allocate them explicitly so that they're preserved
* if we later switch to a virtual colormap.
*/
strcpy(wd->colors[0].name,"black");
wd->colors[0].refcount = 1;
wd->colors[0].type = SHARED;
wd->colors[0].r = wd->colors[0].g = wd->colors[0].b = 0;
color.red = color.green = color.blue = 0;
if (XAllocColor(wd->display, wd->cmap, &color))
wd->colors[0].c = color.pixel;
else
wd->colors[0].c = BlackPixel(wd->display,wd->screen);
strcpy(wd->colors[1].name,"white");
wd->colors[1].refcount = 1;
wd->colors[1].type = SHARED;
wd->colors[1].r = wd->colors[1].g = wd->colors[1].b = 65535;
color.red = color.green = color.blue = 65535;
if (XAllocColor(wd->display, wd->cmap, &color))
wd->colors[1].c = color.pixel;
else
wd->colors[1].c = WhitePixel(wd->display,wd->screen);
wd->numColors = 2;
for (i=2; i < DMAXCOLORS; i++) wd->colors[i].refcount = 0;
/*
* Set the default gamma correction value for windows that are
* opened on this display. Start with configuration default,
* but if we can get an interpretation of "RGBi:.5/.5/.5",
* calculate a gamma value from that instead.
*/
wd->gamma = GammaCorrection;
if (XParseColor(wd->display, wd->cmap, "RGBi:.5/.5/.5", &color)) {
g = .299 * color.red + .587 * color.green + .114 * color.blue;
g /= 65535;
if (g >= 0.1 && g <= 0.9) /* sanity check */
wd->gamma = log(0.5) / log(g);
}
/*
* Initialize fonts and other things.
*/
wd->numFonts = 1;
wd->fonts = (wfp)malloc(sizeof(struct _wfont));
if (wd->fonts == NULL) {
free(wd);
return NULL;
}
wd->fonts->refcount = 1;
wd->fonts->next = wd->fonts->previous = NULL;
wd->fonts->name = malloc(6);
if (wd->fonts->name == NULL) {
free(wd);
return NULL;
}
strcpy(wd->fonts->name,"fixed");
wd->fonts->fsp = XLoadQueryFont(wd->display, "fixed");
if (wd->fonts->fsp == NULL) { /* couldn't load "fixed"! */
free(wd);
return NULL;
}
{
XGCValues gcv;
Display *stddpy = wd->display;
gcv.font = wd->fonts->fsp->fid;
gcv.foreground = wd->colors[0].c;
gcv.background = wd->colors[1].c;
gcv.fill_style = FillSolid;
gcv.cap_style = CapProjecting;
wd->icongc = XCreateGC(stddpy, DefaultRootWindow(stddpy),
GCFont | GCForeground | GCBackground | GCFillStyle | GCCapStyle, &gcv);
if (wd->icongc == NULL) {
free(wd);
return NULL;
}
}
wd->fonts->height = wd->fonts->fsp->ascent + wd->fonts->fsp->descent;
GRFX_LINK(wd, wdsplys);
return wd;
}
/*
* allocate font s in the display attached to w
*/
wfp alc_font(w,s)
wbp w;
char **s;
{
int i, j, k, n, pass, flags, size;
wfp rv;
char family[MAXFONTWORD+1];
char sizestr[8];
char *stdfam;
if (strcmp(*s, "fixed") != 0 && parsefont(*s, family, &flags, &size)) {
/*
* This is a legal Icon font spec (and it's not an unadorned "fixed").
* Check first for special "standard" family names.
*/
if (!strcmp(family, "mono")) {
stdfam = "lucidatypewriter";
flags |= FONTFLAG_MONO + FONTFLAG_SANS;
}
else if (!strcmp(family, "typewriter")) {
stdfam = "courier";
flags |= FONTFLAG_MONO + FONTFLAG_SERIF;
}
else if (!strcmp(family, "sans")) {
stdfam = "helvetica";
flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SANS;
}
else if (!strcmp(family, "serif")) {
stdfam = "times";
flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SERIF;
}
else stdfam = NULL;
if (stdfam) {
/*
* Standard name: first try preferred family, then generalize.
*/
rv = findfont(w, stdfam, size, flags);
if (!rv)
rv = findfont(w, "*", size, flags);
}
else {
/*
* Any other name: must match as specified.
*/
rv = findfont(w, family, size, flags);
}
if (rv != NULL)
return rv;
}
/*
* Not found as an Icon name; may be an X font name.
*/
return tryfont(w, *s);
}
/*
* return pointer to field i inside XLFD (X Logical Font Description) s.
*/
char *xlfd_field(s, i)
char *s;
int i;
{
int j = 0;
while (j < i) {
if (*s == '\0') return ""; /* if no such field */
if (*s++ == '-') j++;
}
return s;
}
/*
* return size of font, treating a scalable font as having size n
*/
int xlfd_size(s, n)
char *s;
int n;
{
char *f;
int z;
f = xlfd_field(s, XLFD_Size);
if (!*f)
return 0;
z = atoi(f);
if (z != 0)
return z;
else
return n;
}
/*
* Find the best font matching a set of specifications.
*/
wfp findfont(w, family, size, flags)
wbp w;
char *family;
int size, flags;
{
char fontspec[MAXFONTWORD+100];
char *p, *weight, *slant, *width, *spacing, **fontlist;
int n, champ, challenger, bestsize;
/*
* Construct a font specification that enforces any stated requirements
* of size, weight, slant, set width, or proportionality.
*/
if (size > 0)
bestsize = size;
else
bestsize = DEFAULTFONTSIZE;
if (flags & FONTFLAG_MEDIUM)
weight = "medium";
else if ((flags & FONTFLAG_DEMI) && (flags & FONTFLAG_BOLD))
weight = "demibold";
else if (flags & FONTFLAG_BOLD)
weight = "bold";
else if (flags & FONTFLAG_DEMI)
weight = "demi";
else if (flags & FONTFLAG_LIGHT)
weight = "light";
else
weight = "*";
if (flags & FONTFLAG_ITALIC)
slant = "i";
else if (flags & FONTFLAG_OBLIQUE)
slant = "o";
else if (flags & FONTFLAG_ROMAN)
slant = "r";
else
slant = "*";
if (flags & FONTFLAG_NARROW)
width = "narrow";
else if (flags & FONTFLAG_CONDENSED)
width = "condensed";
else if (flags & FONTFLAG_NORMAL)
width = "normal";
else if (flags & FONTFLAG_WIDE)
width = "wide";
else if (flags & FONTFLAG_EXTENDED)
width = "extended";
else
width = "*";
if (flags & FONTFLAG_PROPORTIONAL)
spacing = "p";
else
spacing = "*"; /* can't specify {m or c} to X */
sprintf(fontspec, "-*-%s-%s-%s-%s-*-*-*-*-*-%s-*-*-*",
family, weight, slant, width, spacing);
/*
* Get a list of matching fonts from the X server and find the best one.
*/
fontlist = XListFonts(w->window->display->display, fontspec, 2500, &n);
champ = 0;
while (champ < n && !okfont(fontlist[champ], size, flags))
champ++;
if (champ >= n) {
XFreeFontNames(fontlist);
return NULL; /* nothing acceptable */
}
for (challenger = champ + 1; challenger < n; challenger++)
if (okfont(fontlist[challenger], size, flags)
&& fontcmp(fontlist[challenger], fontlist[champ], bestsize, flags) < 0)
champ = challenger;
/*
* Set the scaling field, if needed, and load the font.
*/
p = xlfd_field(fontlist[champ], XLFD_Size);
if (p[0] == '0' && p[1] == '-')
sprintf(fontspec, "%.*s%d%s", p - fontlist[champ],
fontlist[champ], bestsize, p + 1);
else
strcpy(fontspec, fontlist[champ]);
XFreeFontNames(fontlist);
return tryfont(w, fontspec);
}
/*
* check for minimum acceptability of a font
* (things that couldn't be filtered by the XLFD pattern):
* -- size wrong (there's a bug in OpenWindows 3.3 else X could do it)
* -- not monospaced (can't set pattern to match m or c but not p)
*/
int okfont(spec, size, flags)
char *spec;
int size, flags;
{
if (size > 0 && xlfd_size(spec, size) != size)
return 0; /* can't match explicit size request */
if ((flags & FONTFLAG_MONO) && xlfd_field(spec, XLFD_Spacing)[0] == 'p')
return 0; /* requested mono, but this isn't */
return 1;
}
/*
* rank two fonts based on whether XLFD field n matches a preferred value.
* returns <0 if font1 is better, >0 if font2 is better, else 0.
*/
int fieldcmp(font1, font2, value, field)
char *font1, *font2, *value;
int field;
{
int len, r1, r2;
len = strlen(value);
r1 = (strncmp(xlfd_field(font1, field), value, len) == 0);
r2 = (strncmp(xlfd_field(font2, field), value, len) == 0);
return r2 - r1; /* -1, 0, or 1 */
}
/*
* rank two fonts.
* returns <0 if font1 is better, >0 if font2 is better, else 0.
*
* Note that explicit requests for size, slant, weight, and width caused
* earlier filtering in findfont(), so all those flags aren't checked
* again here; normal values are just favored in case nothing was specified.
*/
int fontcmp(font1, font2, size, flags)
char *font1, *font2;
int size, flags;
{
int n;
/* return if exactly one of the fonts matches value s in field n */
#define PREFER(s,n) \
do { int r = fieldcmp(font1, font2, s, n); if (r != 0) return r; } while (0)
/* return if exactly one of the fonts does NOT match value s in field n */
#define SPURN(s,n) \
do { int r = fieldcmp(font1, font2, s, n); if (r != 0) return -r; } while (0)
/*
* Prefer the font that is closest to the desired size.
*/
n = abs(size - xlfd_size(font1, size)) - abs(size - xlfd_size(font2, size));
if (n != 0)
return n;
/*
* try to check serifs (though not always indicated in X font description)
*/
if (flags & FONTFLAG_SANS) {
PREFER("sans", XLFD_AddStyle);
SPURN("serif", XLFD_AddStyle);
}
else if (flags & FONTFLAG_SERIF) {
PREFER("serif", XLFD_AddStyle);
SPURN("sans", XLFD_AddStyle);
}
/*
* prefer normal values for other fields. These only have an effect
* for fields that were wildcarded when requesting the font list.
*/
PREFER("r", XLFD_Slant); /* prefer roman slant */
PREFER("medium", XLFD_Weight); /* prefer medium weight */
SPURN("demi", XLFD_Weight); /* prefer non-demi if no medium */
PREFER("normal", XLFD_SetWidth); /* prefer normal width */
PREFER("iso8859", XLFD_CharSet); /* prefer font of ASCII chars */
SPURN("0", XLFD_PointSize); /* prefer tuned font to scaled */
PREFER("adobe", XLFD_Foundry); /* these look better than others */
/* no significant difference */
return 0;
}
/*
* load a font and return a font structure.
*/
wfp tryfont(w,s)
wbp w;
char *s;
{
wdp wd = w->window->display;
wfp rv;
/*
* see if the font is already loaded on this display
*/
for(rv = wd->fonts; rv != NULL; rv = rv->next) {
if (!strcmp(s,rv->name)) break;
}
if (rv != NULL) {
rv->refcount++;
return rv;
}
/*
* load a new font
*/
GRFX_ALLOC(rv, _wfont);
rv->name = (char *)malloc((int)strlen(s)+1);
if (rv->name == NULL) ReturnErrNum(305, NULL);
strcpy(rv->name, s);
rv->fsp = XLoadQueryFont(wd->display, rv->name);
if (rv->fsp == NULL){
free(rv->name);
free(rv);
return NULL;
}
rv->height = rv->fsp->ascent + rv->fsp->descent;
w->context->leading = rv->height;
/*
* link the font into this displays fontlist (but not at the head!)
*/
rv->next = wd->fonts->next;
rv->previous = wd->fonts;
if (wd->fonts->next) wd->fonts->next->previous = rv;
wd->fonts->next = rv;
return rv;
}
/*
* allocate a context. Can't be called until w has a display and window.
*/
wcp alc_context(w)
wbp w;
{
int i;
wcp wc;
wdp wd = w->window->display;
GRFX_ALLOC(wc, _wcontext);
wc->serial = ++context_serial;
wc->display = wd;
wd->refcount++;
wc->fg = &(wd->colors[0]);
wc->fg->refcount++;
wc->bg = &(wd->colors[1]);
wc->bg->refcount++;
wc->font = wd->fonts;
wc->leading = wd->fonts->height;
wc->drawop = GXcopy;
wc->gamma = wd->gamma;
wc->clipx = wc->clipy = 0;
wc->clipw = wc->cliph = -1;
wc->linewidth = 1;
GRFX_LINK(wc, wcntxts);
return wc;
}
/*
* allocate a context, cloning attributes from an existing context
*/
wcp clone_context(w)
wbp w;
{
wcp wc, rv;
XGCValues gcv;
XRectangle rec;
unsigned long gcmask = GCFont | GCForeground | GCBackground |
GCFillStyle | GCCapStyle | GCLineWidth | GCLineStyle;
wc = w->context;
Protect(rv = alc_context(w), return NULL);
rv->dx = wc->dx;
rv->dy = wc->dy;
rv->clipx = wc->clipx;
rv->clipy = wc->clipy;
rv->clipw = wc->clipw;
rv->cliph = wc->cliph;
rv->fg = wc->fg;
rv->fg->refcount++;
rv->bg = wc->bg;
rv->bg->refcount++;
rv->font = wc->font;
rv->font->refcount++;
rv->fillstyle = wc->fillstyle;
rv->linestyle = wc->linestyle;
rv->linewidth = wc->linewidth;
rv->drawop = wc->drawop;
rv->gamma = wc->gamma;
rv->bits = wc->bits;
if (ISXORREVERSE(w))
gcv.foreground = rv->fg->c ^ rv->bg->c;
else
gcv.foreground = rv->fg->c;
gcv.background = rv->bg->c;
gcv.font = rv->font->fsp->fid;
gcv.line_style = rv->linestyle;
gcv.line_width = rv->linewidth;
if (rv->linewidth > 1) {
gcv.dashes = 3 * rv->linewidth;
gcmask |= GCDashList;
}
gcv.fill_style = rv->fillstyle;
gcv.cap_style = CapProjecting;
rv->gc = XCreateGC(w->window->display->display,w->window->pix,gcmask,&gcv);
if (rv->gc == NULL) {
free(rv);
return NULL;
}
if (rv->clipw >= 0) {
rec.x = rv->clipx;
rec.y = rv->clipy;
rec.width = rv->clipw;
rec.height = rv->cliph;
XSetClipRectangles(rv->display->display, rv->gc, 0, 0, &rec, 1,Unsorted);
}
return rv;
}
/*
* allocate a window state structure
*/
wsp alc_winstate()
{
int i;
wsp ws;
GRFX_ALLOC(ws, _wstate);
ws->serial = ++canvas_serial;
ws->bits = 1024; /* echo ON; others OFF */
ws->filep = nulldesc;
ws->listp = nulldesc;
ws->theCursor = si_s2i(cursorsyms, "left ptr") >> 1;
ws->iconic = NormalState;
ws->posx = ws->posy = -(MaxInt);
GRFX_LINK(ws, wstates);
return ws;
}
/*
* free a window state
*/
int free_window(ws)
wsp ws;
{
ws->refcount--;
if(ws->refcount == 0) {
ws->bits |= 1; /* SETZOMBIE */
if (ws->win != (Window) NULL) {
XDestroyWindow(ws->display->display, ws->win);
XFlush(ws->display->display);
while (ws->win != (Window) NULL)
if (pollevent() == -1) return -1;
}
GRFX_UNLINK(ws, wstates);
}
return 0;
}
/*
* free a window context
*/
novalue free_context(wc)
wcp wc;
{
wc->refcount--;
if(wc->refcount == 0) {
if (wc->gc != NULL)
XFreeGC(wc->display->display, wc->gc);
free_display(wc->display);
GRFX_UNLINK(wc, wcntxts);
}
}
/*
* free a display
*/
novalue free_display(wd)
wdp wd;
{
wd->refcount--;
if(wd->refcount == 0) {
if (wd->cmap != DefaultColormap(wd->display, wd->screen))
XFreeColormap(wd->display, wd->cmap);
XCloseDisplay(wd->display);
if (wd->previous) wd->previous->next = wd->next;
else wdsplys = wd->next;
if (wd->next) wd->next->previous = wd->previous;
free(wd);
}
}