summaryrefslogtreecommitdiff
path: root/cachedGCs.c
diff options
context:
space:
mode:
Diffstat (limited to 'cachedGCs.c')
-rw-r--r--cachedGCs.c864
1 files changed, 864 insertions, 0 deletions
diff --git a/cachedGCs.c b/cachedGCs.c
new file mode 100644
index 0000000..21d3bb7
--- /dev/null
+++ b/cachedGCs.c
@@ -0,0 +1,864 @@
+/* $XTermId: cachedGCs.c,v 1.61 2011/09/11 14:59:38 tom Exp $ */
+
+/*
+ * Copyright 2007-2010,2011 by Thomas E. Dickey
+ *
+ * All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the
+ * sale, use or other dealings in this Software without prior written
+ * authorization.
+ */
+
+#include <data.h>
+#include <xstrings.h>
+
+#include <X11/Xmu/Drawing.h>
+
+#include <stdio.h>
+
+/*
+ * hide (or eliminate) calls to
+ * XCreateGC()
+ * XFreeGC()
+ * XGetGCValues()
+ * XSetBackground()
+ * XSetFont()
+ * XSetForeground()
+ * XtGetGC()
+ * XtReleaseGC()
+ * by associating an integer with each GC, maintaining a cache which
+ * reflects frequency of use rather than most recent usage.
+ *
+ * FIXME: XTermFonts should hold gc, font, fs.
+ */
+typedef struct {
+ GC gc;
+ unsigned used;
+ unsigned cset;
+ XTermFonts *font;
+ Pixel tile;
+ Pixel fg;
+ Pixel bg;
+} CgsCacheData;
+
+#define DEPTH 8
+#define ITEM() (int) (me->data - me->list)
+#define LIST(item) me->list[item]
+#define LINK(item) me->data = (me->list + (item))
+#define THIS(field) me->data->field
+#define NEXT(field) me->next.field
+
+#define HaveFont(font) (Boolean) ((font) != 0 && (font)->fs != 0)
+
+#define GC_CSet GCFunction
+
+typedef struct {
+ CgsCacheData list[DEPTH];
+ CgsCacheData *data; /* points to current list[] entry */
+ XtGCMask mask; /* changes since the last getCgsGC() */
+ CgsCacheData next; /* updated values, apply in getCgsGC() */
+} CgsCache;
+
+#if OPT_TRACE
+#define CASE(name) case gc##name: result = #name; break
+static const char *
+traceCgsEnum(CgsEnum value)
+{
+ const char *result = "?";
+ switch (value) {
+ CASE(Norm);
+ CASE(Bold);
+ CASE(NormReverse);
+ CASE(BoldReverse);
+#if OPT_BOX_CHARS
+ CASE(Line);
+ CASE(Dots);
+#endif
+#if OPT_DEC_CHRSET
+ CASE(CNorm);
+ CASE(CBold);
+#endif
+#if OPT_WIDE_CHARS
+ CASE(Wide);
+ CASE(WBold);
+ CASE(WideReverse);
+ CASE(WBoldReverse);
+#endif
+ CASE(VTcursNormal);
+ CASE(VTcursFilled);
+ CASE(VTcursReverse);
+ CASE(VTcursOutline);
+#if OPT_TEK4014
+ CASE(TKcurs);
+#endif
+ CASE(MAX);
+ }
+ return result;
+}
+
+#undef CASE
+
+static const char *
+traceVTwin(XtermWidget xw, VTwin * value)
+{
+ const char *result = "?";
+ if (value == 0)
+ result = "null";
+ else if (value == &(TScreenOf(xw)->fullVwin))
+ result = "fullVwin";
+#ifndef NO_ACTIVE_ICON
+ else if (value == &(TScreenOf(xw)->iconVwin))
+ result = "iconVwin";
+#endif
+ return result;
+}
+
+#if OPT_TRACE > 1
+static String
+traceCSet(unsigned cset)
+{
+ static char result[80];
+ switch (cset) {
+ case CSET_SWL:
+ strcpy(result, "SWL");
+ break;
+ case CSET_DHL_TOP:
+ strcpy(result, "DHL_TOP");
+ break;
+ case CSET_DHL_BOT:
+ strcpy(result, "DHL_BOT");
+ break;
+ case CSET_DWL:
+ strcpy(result, "DWL");
+ break;
+ default:
+ sprintf(result, "%#x", cset);
+ break;
+ }
+ return result;
+}
+
+static String
+traceFont(XTermFonts * font)
+{
+ static char result[80];
+
+ if (HaveFont(font)) {
+ XFontStruct *fs = font->fs;
+ sprintf(result, "%p(%dx%d %d %#lx)",
+ fs,
+ fs->max_bounds.width,
+ fs->max_bounds.ascent + fs->max_bounds.descent,
+ fs->max_bounds.descent,
+ (unsigned long) (fs->fid));
+ } else {
+ strcpy(result, "null");
+ }
+ return result;
+}
+
+static String
+tracePixel(XtermWidget xw, Pixel value)
+{
+#define CASE(name) { name, #name }
+ static struct {
+ TermColors code;
+ String name;
+ } t_colors[] = {
+ CASE(TEXT_FG),
+ CASE(TEXT_BG),
+ CASE(TEXT_CURSOR),
+ CASE(MOUSE_FG),
+ CASE(MOUSE_BG),
+#if OPT_TEK4014
+ CASE(TEK_FG),
+ CASE(TEK_BG),
+#endif
+#if OPT_HIGHLIGHT_COLOR
+ CASE(HIGHLIGHT_BG),
+ CASE(HIGHLIGHT_FG),
+#endif
+#if OPT_TEK4014
+ CASE(TEK_CURSOR),
+#endif
+ };
+ TScreen *screen = TScreenOf(xw);
+ String result = 0;
+ int n;
+
+ for (n = 0; n < NCOLORS; ++n) {
+ if (value == T_COLOR(screen, t_colors[n].code)) {
+ result = t_colors[n].name;
+ break;
+ }
+ }
+
+ if (result == 0) {
+ for (n = 0; n < MAXCOLORS; ++n) {
+#if OPT_COLOR_RES
+ if (screen->Acolors[n].mode > 0
+ && value == screen->Acolors[n].value) {
+ result = screen->Acolors[n].resource;
+ break;
+ }
+#else
+ if (value == screen->Acolors[n]) {
+ char temp[80];
+ sprintf(temp, "Acolors[%d]", n);
+ result = x_strdup(temp);
+ break;
+ }
+#endif
+ }
+ }
+
+ if (result == 0) {
+ char temp[80];
+ sprintf(temp, "%#lx", value);
+ result = x_strdup(temp);
+ }
+
+ return result;
+}
+
+#undef CASE
+
+#endif /* OPT_TRACE > 1 */
+#endif /* OPT_TRACE */
+
+static CgsCache *
+allocCache(void **cache_pointer)
+{
+ if (*cache_pointer == 0) {
+ *cache_pointer = TypeCallocN(CgsCache, gcMAX);
+ TRACE(("allocCache %p\n", *cache_pointer));
+ }
+ return *((CgsCache **) cache_pointer);
+}
+
+static int
+dataIndex(CgsCache * me)
+{
+ return ITEM();
+}
+
+static void
+relinkData(CgsCache * me, int item)
+{
+ LINK(item);
+}
+
+/*
+ * Returns the appropriate cache pointer.
+ */
+static CgsCache *
+myCache(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId)
+{
+ CgsCache *result = 0;
+
+ if ((int) cgsId >= 0 && cgsId < gcMAX) {
+#ifdef NO_ACTIVE_ICON
+ (void) xw;
+ (void) cgsWin;
+#else
+ if (cgsWin == &(TScreenOf(xw)->iconVwin))
+ result = allocCache(&(TScreenOf(xw)->icon_cgs_cache));
+ else
+#endif
+ result = allocCache(&(TScreenOf(xw)->main_cgs_cache));
+
+ result += cgsId;
+ if (result->data == 0) {
+ result->data = result->list;
+ }
+ }
+
+ return result;
+}
+
+static Display *
+myDisplay(XtermWidget xw)
+{
+ return TScreenOf(xw)->display;
+}
+
+static Drawable
+myDrawable(XtermWidget xw, VTwin * cgsWin)
+{
+ Drawable drawable = 0;
+
+ if (cgsWin != 0 && cgsWin->window != 0)
+ drawable = cgsWin->window;
+ if (drawable == 0)
+ drawable = RootWindowOfScreen(XtScreen(xw));
+ return drawable;
+}
+
+static GC
+newCache(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, CgsCache * me)
+{
+ XGCValues xgcv;
+ XtGCMask mask;
+
+ THIS(font) = NEXT(font);
+ THIS(cset) = NEXT(cset);
+ THIS(fg) = NEXT(fg);
+ THIS(bg) = NEXT(bg);
+
+ memset(&xgcv, 0, sizeof(xgcv));
+ xgcv.font = NEXT(font)->fs->fid;
+ mask = (GCForeground | GCBackground | GCFont);
+
+ switch (cgsId) {
+ case gcNorm:
+ case gcBold:
+ case gcNormReverse:
+ case gcBoldReverse:
+#if OPT_WIDE_CHARS
+ case gcWide:
+ case gcWBold:
+ case gcWideReverse:
+ case gcWBoldReverse:
+#endif
+ mask |= (GCGraphicsExposures | GCFunction);
+ xgcv.graphics_exposures = True; /* default */
+ xgcv.function = GXcopy;
+ break;
+#if OPT_BOX_CHARS
+ case gcLine:
+ mask |= (GCGraphicsExposures | GCFunction);
+ xgcv.graphics_exposures = True; /* default */
+ xgcv.function = GXcopy;
+ break;
+ case gcDots:
+ xgcv.fill_style = FillTiled;
+ xgcv.tile =
+ XmuCreateStippledPixmap(XtScreen((Widget) xw),
+ THIS(fg),
+ THIS(bg),
+ xw->core.depth);
+ THIS(tile) = xgcv.tile;
+ mask = (GCForeground | GCBackground);
+ mask |= (GCGraphicsExposures | GCFunction | GCTile | GCFillStyle);
+ xgcv.graphics_exposures = True; /* default */
+ xgcv.function = GXcopy;
+ break;
+#endif
+#if OPT_DEC_CHRSET
+ case gcCNorm:
+ case gcCBold:
+ break;
+#endif
+ case gcVTcursNormal: /* FALLTHRU */
+ case gcVTcursFilled: /* FALLTHRU */
+ case gcVTcursReverse: /* FALLTHRU */
+ case gcVTcursOutline: /* FALLTHRU */
+ break;
+#if OPT_TEK4014
+ case gcTKcurs: /* FALLTHRU */
+ /* FIXME */
+#endif
+ case gcMAX: /* should not happen */
+ return 0;
+ }
+ xgcv.foreground = NEXT(fg);
+ xgcv.background = NEXT(bg);
+
+ THIS(gc) = XCreateGC(myDisplay(xw), myDrawable(xw, cgsWin), mask, &xgcv);
+ TRACE(("getCgsGC(%s) created gc %p(%d)\n",
+ traceCgsEnum(cgsId), (void *) THIS(gc), ITEM()));
+
+ THIS(used) = 0;
+ return THIS(gc);
+}
+
+static Boolean
+SameFont(XTermFonts * a, XTermFonts * b)
+{
+ return (Boolean) (HaveFont(a)
+ && HaveFont(b)
+ && ((a->fs == b->fs)
+ || !memcmp(a->fs, b->fs, sizeof(*(a->fs)))));
+}
+
+#define SameColor(a,b) ((a) == (b))
+#define SameCSet(a,b) ((a) == (b))
+
+static GC
+chgCache(XtermWidget xw, CgsEnum cgsId GCC_UNUSED, CgsCache * me, Bool both)
+{
+ XGCValues xgcv;
+ XtGCMask mask = (GCForeground | GCBackground | GCFont);
+
+ memset(&xgcv, 0, sizeof(xgcv));
+
+ TRACE2(("chgCache(%s) old data fg=%s, bg=%s, font=%s cset %s\n",
+ traceCgsEnum(cgsId),
+ tracePixel(xw, THIS(fg)),
+ tracePixel(xw, THIS(bg)),
+ traceFont(THIS(font)),
+ traceCSet(THIS(cset))));
+#if OPT_TRACE > 1
+ if (!SameFont(THIS(font), NEXT(font)))
+ TRACE2(("...chgCache new font=%s\n", traceFont(NEXT(font))));
+ if (!SameCSet(THIS(cset), NEXT(cset)))
+ TRACE2(("...chgCache new cset=%s\n", traceCSet(NEXT(cset))));
+ if (!SameColor(THIS(fg), NEXT(fg)))
+ TRACE2(("...chgCache new fg=%s\n", tracePixel(xw, NEXT(fg))));
+ if (!SameColor(THIS(bg), NEXT(bg)))
+ TRACE2(("...chgCache new bg=%s\n", tracePixel(xw, NEXT(bg))));
+#endif
+
+ if (both) {
+ THIS(font) = NEXT(font);
+ THIS(cset) = NEXT(cset);
+ }
+ THIS(fg) = NEXT(fg);
+ THIS(bg) = NEXT(bg);
+
+ xgcv.font = THIS(font)->fs->fid;
+ xgcv.foreground = THIS(fg);
+ xgcv.background = THIS(bg);
+
+ XChangeGC(myDisplay(xw), THIS(gc), mask, &xgcv);
+ TRACE2(("...chgCache(%s) updated gc %p(%d)\n",
+ traceCgsEnum(cgsId), THIS(gc), ITEM()));
+
+ THIS(used) = 0;
+ return THIS(gc);
+}
+/*
+ * Use the "setCgsXXXX()" calls to initialize parameters for a new GC.
+ */
+void
+setCgsFore(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, Pixel fg)
+{
+ CgsCache *me;
+
+ if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
+ NEXT(fg) = fg;
+ me->mask |= GCForeground;
+ }
+}
+
+void
+setCgsBack(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, Pixel bg)
+{
+ CgsCache *me;
+
+ if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
+ NEXT(bg) = bg;
+ me->mask |= GCBackground;
+ }
+}
+
+#if OPT_DEC_CHRSET
+void
+setCgsCSet(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, unsigned cset)
+{
+ CgsCache *me;
+
+ if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
+ NEXT(cset) = cset;
+ me->mask |= GC_CSet;
+ }
+}
+#else
+#define setCgsCSet(xw, cgsWin, dstCgsId, cset) /* nothing */
+#endif
+
+void
+setCgsFont(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, XTermFonts * font)
+{
+ CgsCache *me;
+
+ if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
+ if (!HaveFont(font)) {
+ if (cgsId != gcNorm)
+ (void) getCgsGC(xw, cgsWin, gcNorm);
+#ifndef NO_ACTIVE_ICON
+ if (cgsWin == &(TScreenOf(xw)->iconVwin))
+ font = &(TScreenOf(xw)->fnt_icon);
+ else
+#endif
+ font = &(TScreenOf(xw)->fnts[fNorm]);
+ }
+ if (HaveFont(font) && okFont(font->fs)) {
+ TRACE2(("...updated next font in %p for %s to %s\n",
+ me, traceCgsEnum(cgsId), traceFont(font)));
+ TRACE2(("...next font was %s\n", traceFont(NEXT(font))));
+ NEXT(font) = font;
+ me->mask |= GCFont;
+ } else {
+ /* EMPTY */
+ TRACE2(("...NOT updated font for %s\n",
+ traceCgsEnum(cgsId)));
+ }
+ }
+}
+
+/*
+ * Discard all of the font information, e.g., we are resizing the font.
+ * Keep the GC's so we can simply change them rather than creating new ones.
+ */
+void
+clrCgsFonts(XtermWidget xw, VTwin * cgsWin, XTermFonts * font)
+{
+ CgsCache *me;
+ int j, k;
+
+ if (HaveFont(font)) {
+ for_each_gc(j) {
+ if ((me = myCache(xw, cgsWin, (CgsEnum) j)) != 0) {
+ for (k = 0; k < DEPTH; ++k) {
+ if (SameFont(LIST(k).font, font)) {
+ TRACE2(("clrCgsFonts %s gc %p(%d) %s\n",
+ traceCgsEnum((CgsEnum) j),
+ LIST(k).gc,
+ k,
+ traceFont(font)));
+ LIST(k).font = 0;
+ LIST(k).cset = 0;
+ }
+ }
+ if (SameFont(NEXT(font), font)) {
+ TRACE2(("clrCgsFonts %s next %s\n",
+ traceCgsEnum((CgsEnum) j),
+ traceFont(font)));
+ NEXT(font) = 0;
+ NEXT(cset) = 0;
+ me->mask &= (unsigned) ~(GCFont | GC_CSet);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Return a GC associated with the given id, allocating if needed.
+ */
+GC
+getCgsGC(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId)
+{
+ CgsCache *me;
+ GC result = 0;
+ int j, k;
+ unsigned used = 0;
+
+ if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
+ TRACE2(("getCgsGC(%s, %s)\n",
+ traceVTwin(xw, cgsWin), traceCgsEnum(cgsId)));
+ if (me->mask != 0) {
+
+ /* fill in the unchanged fields */
+ if (!(me->mask & GC_CSet))
+ NEXT(cset) = 0; /* OPT_DEC_CHRSET */
+ if (!(me->mask & GCFont))
+ NEXT(font) = THIS(font);
+ if (!(me->mask & GCForeground))
+ NEXT(fg) = THIS(fg);
+ if (!(me->mask & GCBackground))
+ NEXT(bg) = THIS(bg);
+
+ if (NEXT(font) == 0) {
+ setCgsFont(xw, cgsWin, cgsId, 0);
+ }
+
+ TRACE2(("...Cgs new data fg=%s, bg=%s, font=%s cset %s\n",
+ tracePixel(xw, NEXT(fg)),
+ tracePixel(xw, NEXT(bg)),
+ traceFont(NEXT(font)),
+ traceCSet(NEXT(cset))));
+
+ /* try to find the given data in an already-created GC */
+ for (j = 0; j < DEPTH; ++j) {
+ if (LIST(j).gc != 0
+ && SameFont(LIST(j).font, NEXT(font))
+ && SameCSet(LIST(j).cset, NEXT(cset))
+ && SameColor(LIST(j).fg, NEXT(fg))
+ && SameColor(LIST(j).bg, NEXT(bg))) {
+ LINK(j);
+ result = THIS(gc);
+ TRACE2(("getCgsGC existing %p(%d)\n", result, ITEM()));
+ break;
+ }
+ }
+
+ if (result == 0) {
+ /* try to find an empty slot, to create a new GC */
+ used = 0;
+ for (j = 0; j < DEPTH; ++j) {
+ if (LIST(j).gc == 0) {
+ LINK(j);
+ result = newCache(xw, cgsWin, cgsId, me);
+ break;
+ }
+ if (used < LIST(j).used)
+ used = LIST(j).used;
+ }
+ }
+
+ if (result == 0) {
+ /* if none were empty, pick the least-used slot, to modify */
+ for (j = 0, k = -1; j < DEPTH; ++j) {
+ if (used >= LIST(j).used) {
+ used = LIST(j).used;
+ k = j;
+ }
+ }
+ LINK(k);
+ TRACE2(("...getCgsGC least-used(%d) was %d\n", k, THIS(used)));
+ result = chgCache(xw, cgsId, me, True);
+ }
+ me->next = *(me->data);
+ } else {
+ result = THIS(gc);
+ }
+ me->mask = 0;
+ THIS(used) += 1;
+ TRACE2(("...getCgsGC(%s, %s) gc %p(%d), used %d\n",
+ traceVTwin(xw, cgsWin),
+ traceCgsEnum(cgsId), result, ITEM(), THIS(used)));
+ }
+ return result;
+}
+
+/*
+ * Return the font for the given GC.
+ */
+CgsEnum
+getCgsId(XtermWidget xw, VTwin * cgsWin, GC gc)
+{
+ int n;
+ CgsEnum result = gcNorm;
+
+ for_each_gc(n) {
+ CgsCache *me;
+
+ if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) {
+ if (THIS(gc) == gc) {
+ result = (CgsEnum) n;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ * Return the font for the given GC.
+ */
+XTermFonts *
+getCgsFont(XtermWidget xw, VTwin * cgsWin, GC gc)
+{
+ int n;
+ XTermFonts *result = 0;
+
+ for_each_gc(n) {
+ CgsCache *me;
+
+ if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) {
+ if (THIS(gc) == gc) {
+ result = THIS(font);
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ * Return the foreground color for the given GC.
+ */
+Pixel
+getCgsFore(XtermWidget xw, VTwin * cgsWin, GC gc)
+{
+ int n;
+ Pixel result = 0;
+
+ for_each_gc(n) {
+ CgsCache *me;
+
+ if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) {
+ if (THIS(gc) == gc) {
+ result = THIS(fg);
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ * Return the background color for the given GC.
+ */
+Pixel
+getCgsBack(XtermWidget xw, VTwin * cgsWin, GC gc)
+{
+ int n;
+ Pixel result = 0;
+
+ for_each_gc(n) {
+ CgsCache *me;
+
+ if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) {
+ if (THIS(gc) == gc) {
+ result = THIS(bg);
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ * Copy the parameters (except GC of course) from one cache record to another.
+ */
+void
+copyCgs(XtermWidget xw, VTwin * cgsWin, CgsEnum dstCgsId, CgsEnum srcCgsId)
+{
+ if (dstCgsId != srcCgsId) {
+ CgsCache *me;
+
+ if ((me = myCache(xw, cgsWin, srcCgsId)) != 0) {
+ TRACE(("copyCgs from %s to %s\n",
+ traceCgsEnum(srcCgsId),
+ traceCgsEnum(dstCgsId)));
+ TRACE2(("copyCgs from %s (me %p, fg %s, bg %s, cset %s) to %s {{\n",
+ traceCgsEnum(srcCgsId),
+ me,
+ tracePixel(xw, THIS(fg)),
+ tracePixel(xw, THIS(bg)),
+ traceCSet(THIS(cset)),
+ traceCgsEnum(dstCgsId)));
+ setCgsCSet(xw, cgsWin, dstCgsId, THIS(cset));
+ setCgsFore(xw, cgsWin, dstCgsId, THIS(fg));
+ setCgsBack(xw, cgsWin, dstCgsId, THIS(bg));
+ setCgsFont(xw, cgsWin, dstCgsId, THIS(font));
+ TRACE2(("...copyCgs }}\n"));
+ }
+ }
+}
+
+/*
+ * Interchange colors in the cache, e.g., for reverse-video.
+ */
+void
+redoCgs(XtermWidget xw, Pixel fg, Pixel bg, CgsEnum cgsId)
+{
+ int n;
+ VTwin *cgsWin = WhichVWin(TScreenOf(xw));
+ CgsCache *me = myCache(xw, cgsWin, cgsId);
+
+ if (me != 0) {
+ CgsCacheData *save_data = me->data;
+
+ for (n = 0; n < DEPTH; ++n) {
+ if (LIST(n).gc != 0 && HaveFont(LIST(n).font)) {
+ LINK(n);
+
+ if (LIST(n).fg == fg
+ && LIST(n).bg == bg) {
+ setCgsFore(xw, cgsWin, cgsId, bg);
+ setCgsBack(xw, cgsWin, cgsId, fg);
+ } else if (LIST(n).fg == bg
+ && LIST(n).bg == fg) {
+ setCgsFore(xw, cgsWin, cgsId, fg);
+ setCgsBack(xw, cgsWin, cgsId, bg);
+ } else {
+ continue;
+ }
+
+ (void) chgCache(xw, cgsId, me, False);
+ }
+ }
+ me->data = save_data;
+ }
+}
+
+/*
+ * Swap the cache records, e.g., when doing reverse-video.
+ */
+void
+swapCgs(XtermWidget xw, VTwin * cgsWin, CgsEnum dstCgsId, CgsEnum srcCgsId)
+{
+ if (dstCgsId != srcCgsId) {
+ CgsCache *dst;
+ CgsCache *src;
+ CgsCache tmp;
+
+ if ((src = myCache(xw, cgsWin, srcCgsId)) != 0) {
+ if ((dst = myCache(xw, cgsWin, dstCgsId)) != 0) {
+ int srcIndex = dataIndex(src);
+ int dstIndex = dataIndex(dst);
+
+ EXCHANGE(*src, *dst, tmp);
+
+ relinkData(src, dstIndex);
+ relinkData(dst, srcIndex);
+ }
+ }
+ }
+}
+
+/*
+ * Free any GC associated with the given id.
+ */
+GC
+freeCgs(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId)
+{
+ CgsCache *me;
+ int j;
+
+ if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
+ for (j = 0; j < DEPTH; ++j) {
+ if (LIST(j).gc != 0) {
+ TRACE(("freeCgs(%s, %s) gc %p(%d)\n",
+ traceVTwin(xw, cgsWin),
+ traceCgsEnum(cgsId), (void *) LIST(j).gc, j));
+ clrCgsFonts(xw, cgsWin, LIST(j).font);
+#if OPT_BOX_CHARS
+ if (cgsId == gcDots) {
+ XmuReleaseStippledPixmap(XtScreen((Widget) xw), LIST(j).tile);
+ }
+#endif
+ XFreeGC(TScreenOf(xw)->display, LIST(j).gc);
+ memset(&LIST(j), 0, sizeof(LIST(j)));
+ }
+ LINK(0);
+ }
+ }
+ return 0;
+}
+
+#ifdef NO_LEAKS
+void
+noleaks_cachedCgs(XtermWidget xw)
+{
+#ifndef NO_ACTIVE_ICON
+ free(TScreenOf(xw)->icon_cgs_cache);
+#endif
+ free(TScreenOf(xw)->main_cgs_cache);
+}
+#endif