cachedGCs.c revision 0bd37d32
1/* $XTermId: cachedGCs.c,v 1.61 2011/09/11 14:59:38 tom Exp $ */ 2 3/* 4 * Copyright 2007-2010,2011 by Thomas E. Dickey 5 * 6 * All Rights Reserved 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sublicense, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * Except as contained in this notice, the name(s) of the above copyright 28 * holders shall not be used in advertising or otherwise to promote the 29 * sale, use or other dealings in this Software without prior written 30 * authorization. 31 */ 32 33#include <data.h> 34#include <xstrings.h> 35 36#include <X11/Xmu/Drawing.h> 37 38#include <stdio.h> 39 40/* 41 * hide (or eliminate) calls to 42 * XCreateGC() 43 * XFreeGC() 44 * XGetGCValues() 45 * XSetBackground() 46 * XSetFont() 47 * XSetForeground() 48 * XtGetGC() 49 * XtReleaseGC() 50 * by associating an integer with each GC, maintaining a cache which 51 * reflects frequency of use rather than most recent usage. 52 * 53 * FIXME: XTermFonts should hold gc, font, fs. 54 */ 55typedef struct { 56 GC gc; 57 unsigned used; 58 unsigned cset; 59 XTermFonts *font; 60 Pixel tile; 61 Pixel fg; 62 Pixel bg; 63} CgsCacheData; 64 65#define DEPTH 8 66#define ITEM() (int) (me->data - me->list) 67#define LIST(item) me->list[item] 68#define LINK(item) me->data = (me->list + (item)) 69#define THIS(field) me->data->field 70#define NEXT(field) me->next.field 71 72#define HaveFont(font) (Boolean) ((font) != 0 && (font)->fs != 0) 73 74#define GC_CSet GCFunction 75 76typedef struct { 77 CgsCacheData list[DEPTH]; 78 CgsCacheData *data; /* points to current list[] entry */ 79 XtGCMask mask; /* changes since the last getCgsGC() */ 80 CgsCacheData next; /* updated values, apply in getCgsGC() */ 81} CgsCache; 82 83#if OPT_TRACE 84#define CASE(name) case gc##name: result = #name; break 85static const char * 86traceCgsEnum(CgsEnum value) 87{ 88 const char *result = "?"; 89 switch (value) { 90 CASE(Norm); 91 CASE(Bold); 92 CASE(NormReverse); 93 CASE(BoldReverse); 94#if OPT_BOX_CHARS 95 CASE(Line); 96 CASE(Dots); 97#endif 98#if OPT_DEC_CHRSET 99 CASE(CNorm); 100 CASE(CBold); 101#endif 102#if OPT_WIDE_CHARS 103 CASE(Wide); 104 CASE(WBold); 105 CASE(WideReverse); 106 CASE(WBoldReverse); 107#endif 108 CASE(VTcursNormal); 109 CASE(VTcursFilled); 110 CASE(VTcursReverse); 111 CASE(VTcursOutline); 112#if OPT_TEK4014 113 CASE(TKcurs); 114#endif 115 CASE(MAX); 116 } 117 return result; 118} 119 120#undef CASE 121 122static const char * 123traceVTwin(XtermWidget xw, VTwin * value) 124{ 125 const char *result = "?"; 126 if (value == 0) 127 result = "null"; 128 else if (value == &(TScreenOf(xw)->fullVwin)) 129 result = "fullVwin"; 130#ifndef NO_ACTIVE_ICON 131 else if (value == &(TScreenOf(xw)->iconVwin)) 132 result = "iconVwin"; 133#endif 134 return result; 135} 136 137#if OPT_TRACE > 1 138static String 139traceCSet(unsigned cset) 140{ 141 static char result[80]; 142 switch (cset) { 143 case CSET_SWL: 144 strcpy(result, "SWL"); 145 break; 146 case CSET_DHL_TOP: 147 strcpy(result, "DHL_TOP"); 148 break; 149 case CSET_DHL_BOT: 150 strcpy(result, "DHL_BOT"); 151 break; 152 case CSET_DWL: 153 strcpy(result, "DWL"); 154 break; 155 default: 156 sprintf(result, "%#x", cset); 157 break; 158 } 159 return result; 160} 161 162static String 163traceFont(XTermFonts * font) 164{ 165 static char result[80]; 166 167 if (HaveFont(font)) { 168 XFontStruct *fs = font->fs; 169 sprintf(result, "%p(%dx%d %d %#lx)", 170 fs, 171 fs->max_bounds.width, 172 fs->max_bounds.ascent + fs->max_bounds.descent, 173 fs->max_bounds.descent, 174 (unsigned long) (fs->fid)); 175 } else { 176 strcpy(result, "null"); 177 } 178 return result; 179} 180 181static String 182tracePixel(XtermWidget xw, Pixel value) 183{ 184#define CASE(name) { name, #name } 185 static struct { 186 TermColors code; 187 String name; 188 } t_colors[] = { 189 CASE(TEXT_FG), 190 CASE(TEXT_BG), 191 CASE(TEXT_CURSOR), 192 CASE(MOUSE_FG), 193 CASE(MOUSE_BG), 194#if OPT_TEK4014 195 CASE(TEK_FG), 196 CASE(TEK_BG), 197#endif 198#if OPT_HIGHLIGHT_COLOR 199 CASE(HIGHLIGHT_BG), 200 CASE(HIGHLIGHT_FG), 201#endif 202#if OPT_TEK4014 203 CASE(TEK_CURSOR), 204#endif 205 }; 206 TScreen *screen = TScreenOf(xw); 207 String result = 0; 208 int n; 209 210 for (n = 0; n < NCOLORS; ++n) { 211 if (value == T_COLOR(screen, t_colors[n].code)) { 212 result = t_colors[n].name; 213 break; 214 } 215 } 216 217 if (result == 0) { 218 for (n = 0; n < MAXCOLORS; ++n) { 219#if OPT_COLOR_RES 220 if (screen->Acolors[n].mode > 0 221 && value == screen->Acolors[n].value) { 222 result = screen->Acolors[n].resource; 223 break; 224 } 225#else 226 if (value == screen->Acolors[n]) { 227 char temp[80]; 228 sprintf(temp, "Acolors[%d]", n); 229 result = x_strdup(temp); 230 break; 231 } 232#endif 233 } 234 } 235 236 if (result == 0) { 237 char temp[80]; 238 sprintf(temp, "%#lx", value); 239 result = x_strdup(temp); 240 } 241 242 return result; 243} 244 245#undef CASE 246 247#endif /* OPT_TRACE > 1 */ 248#endif /* OPT_TRACE */ 249 250static CgsCache * 251allocCache(void **cache_pointer) 252{ 253 if (*cache_pointer == 0) { 254 *cache_pointer = TypeCallocN(CgsCache, gcMAX); 255 TRACE(("allocCache %p\n", *cache_pointer)); 256 } 257 return *((CgsCache **) cache_pointer); 258} 259 260static int 261dataIndex(CgsCache * me) 262{ 263 return ITEM(); 264} 265 266static void 267relinkData(CgsCache * me, int item) 268{ 269 LINK(item); 270} 271 272/* 273 * Returns the appropriate cache pointer. 274 */ 275static CgsCache * 276myCache(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId) 277{ 278 CgsCache *result = 0; 279 280 if ((int) cgsId >= 0 && cgsId < gcMAX) { 281#ifdef NO_ACTIVE_ICON 282 (void) xw; 283 (void) cgsWin; 284#else 285 if (cgsWin == &(TScreenOf(xw)->iconVwin)) 286 result = allocCache(&(TScreenOf(xw)->icon_cgs_cache)); 287 else 288#endif 289 result = allocCache(&(TScreenOf(xw)->main_cgs_cache)); 290 291 result += cgsId; 292 if (result->data == 0) { 293 result->data = result->list; 294 } 295 } 296 297 return result; 298} 299 300static Display * 301myDisplay(XtermWidget xw) 302{ 303 return TScreenOf(xw)->display; 304} 305 306static Drawable 307myDrawable(XtermWidget xw, VTwin * cgsWin) 308{ 309 Drawable drawable = 0; 310 311 if (cgsWin != 0 && cgsWin->window != 0) 312 drawable = cgsWin->window; 313 if (drawable == 0) 314 drawable = RootWindowOfScreen(XtScreen(xw)); 315 return drawable; 316} 317 318static GC 319newCache(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, CgsCache * me) 320{ 321 XGCValues xgcv; 322 XtGCMask mask; 323 324 THIS(font) = NEXT(font); 325 THIS(cset) = NEXT(cset); 326 THIS(fg) = NEXT(fg); 327 THIS(bg) = NEXT(bg); 328 329 memset(&xgcv, 0, sizeof(xgcv)); 330 xgcv.font = NEXT(font)->fs->fid; 331 mask = (GCForeground | GCBackground | GCFont); 332 333 switch (cgsId) { 334 case gcNorm: 335 case gcBold: 336 case gcNormReverse: 337 case gcBoldReverse: 338#if OPT_WIDE_CHARS 339 case gcWide: 340 case gcWBold: 341 case gcWideReverse: 342 case gcWBoldReverse: 343#endif 344 mask |= (GCGraphicsExposures | GCFunction); 345 xgcv.graphics_exposures = True; /* default */ 346 xgcv.function = GXcopy; 347 break; 348#if OPT_BOX_CHARS 349 case gcLine: 350 mask |= (GCGraphicsExposures | GCFunction); 351 xgcv.graphics_exposures = True; /* default */ 352 xgcv.function = GXcopy; 353 break; 354 case gcDots: 355 xgcv.fill_style = FillTiled; 356 xgcv.tile = 357 XmuCreateStippledPixmap(XtScreen((Widget) xw), 358 THIS(fg), 359 THIS(bg), 360 xw->core.depth); 361 THIS(tile) = xgcv.tile; 362 mask = (GCForeground | GCBackground); 363 mask |= (GCGraphicsExposures | GCFunction | GCTile | GCFillStyle); 364 xgcv.graphics_exposures = True; /* default */ 365 xgcv.function = GXcopy; 366 break; 367#endif 368#if OPT_DEC_CHRSET 369 case gcCNorm: 370 case gcCBold: 371 break; 372#endif 373 case gcVTcursNormal: /* FALLTHRU */ 374 case gcVTcursFilled: /* FALLTHRU */ 375 case gcVTcursReverse: /* FALLTHRU */ 376 case gcVTcursOutline: /* FALLTHRU */ 377 break; 378#if OPT_TEK4014 379 case gcTKcurs: /* FALLTHRU */ 380 /* FIXME */ 381#endif 382 case gcMAX: /* should not happen */ 383 return 0; 384 } 385 xgcv.foreground = NEXT(fg); 386 xgcv.background = NEXT(bg); 387 388 THIS(gc) = XCreateGC(myDisplay(xw), myDrawable(xw, cgsWin), mask, &xgcv); 389 TRACE(("getCgsGC(%s) created gc %p(%d)\n", 390 traceCgsEnum(cgsId), (void *) THIS(gc), ITEM())); 391 392 THIS(used) = 0; 393 return THIS(gc); 394} 395 396static Boolean 397SameFont(XTermFonts * a, XTermFonts * b) 398{ 399 return (Boolean) (HaveFont(a) 400 && HaveFont(b) 401 && ((a->fs == b->fs) 402 || !memcmp(a->fs, b->fs, sizeof(*(a->fs))))); 403} 404 405#define SameColor(a,b) ((a) == (b)) 406#define SameCSet(a,b) ((a) == (b)) 407 408static GC 409chgCache(XtermWidget xw, CgsEnum cgsId GCC_UNUSED, CgsCache * me, Bool both) 410{ 411 XGCValues xgcv; 412 XtGCMask mask = (GCForeground | GCBackground | GCFont); 413 414 memset(&xgcv, 0, sizeof(xgcv)); 415 416 TRACE2(("chgCache(%s) old data fg=%s, bg=%s, font=%s cset %s\n", 417 traceCgsEnum(cgsId), 418 tracePixel(xw, THIS(fg)), 419 tracePixel(xw, THIS(bg)), 420 traceFont(THIS(font)), 421 traceCSet(THIS(cset)))); 422#if OPT_TRACE > 1 423 if (!SameFont(THIS(font), NEXT(font))) 424 TRACE2(("...chgCache new font=%s\n", traceFont(NEXT(font)))); 425 if (!SameCSet(THIS(cset), NEXT(cset))) 426 TRACE2(("...chgCache new cset=%s\n", traceCSet(NEXT(cset)))); 427 if (!SameColor(THIS(fg), NEXT(fg))) 428 TRACE2(("...chgCache new fg=%s\n", tracePixel(xw, NEXT(fg)))); 429 if (!SameColor(THIS(bg), NEXT(bg))) 430 TRACE2(("...chgCache new bg=%s\n", tracePixel(xw, NEXT(bg)))); 431#endif 432 433 if (both) { 434 THIS(font) = NEXT(font); 435 THIS(cset) = NEXT(cset); 436 } 437 THIS(fg) = NEXT(fg); 438 THIS(bg) = NEXT(bg); 439 440 xgcv.font = THIS(font)->fs->fid; 441 xgcv.foreground = THIS(fg); 442 xgcv.background = THIS(bg); 443 444 XChangeGC(myDisplay(xw), THIS(gc), mask, &xgcv); 445 TRACE2(("...chgCache(%s) updated gc %p(%d)\n", 446 traceCgsEnum(cgsId), THIS(gc), ITEM())); 447 448 THIS(used) = 0; 449 return THIS(gc); 450} 451/* 452 * Use the "setCgsXXXX()" calls to initialize parameters for a new GC. 453 */ 454void 455setCgsFore(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, Pixel fg) 456{ 457 CgsCache *me; 458 459 if ((me = myCache(xw, cgsWin, cgsId)) != 0) { 460 NEXT(fg) = fg; 461 me->mask |= GCForeground; 462 } 463} 464 465void 466setCgsBack(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, Pixel bg) 467{ 468 CgsCache *me; 469 470 if ((me = myCache(xw, cgsWin, cgsId)) != 0) { 471 NEXT(bg) = bg; 472 me->mask |= GCBackground; 473 } 474} 475 476#if OPT_DEC_CHRSET 477void 478setCgsCSet(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, unsigned cset) 479{ 480 CgsCache *me; 481 482 if ((me = myCache(xw, cgsWin, cgsId)) != 0) { 483 NEXT(cset) = cset; 484 me->mask |= GC_CSet; 485 } 486} 487#else 488#define setCgsCSet(xw, cgsWin, dstCgsId, cset) /* nothing */ 489#endif 490 491void 492setCgsFont(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId, XTermFonts * font) 493{ 494 CgsCache *me; 495 496 if ((me = myCache(xw, cgsWin, cgsId)) != 0) { 497 if (!HaveFont(font)) { 498 if (cgsId != gcNorm) 499 (void) getCgsGC(xw, cgsWin, gcNorm); 500#ifndef NO_ACTIVE_ICON 501 if (cgsWin == &(TScreenOf(xw)->iconVwin)) 502 font = &(TScreenOf(xw)->fnt_icon); 503 else 504#endif 505 font = &(TScreenOf(xw)->fnts[fNorm]); 506 } 507 if (HaveFont(font) && okFont(font->fs)) { 508 TRACE2(("...updated next font in %p for %s to %s\n", 509 me, traceCgsEnum(cgsId), traceFont(font))); 510 TRACE2(("...next font was %s\n", traceFont(NEXT(font)))); 511 NEXT(font) = font; 512 me->mask |= GCFont; 513 } else { 514 /* EMPTY */ 515 TRACE2(("...NOT updated font for %s\n", 516 traceCgsEnum(cgsId))); 517 } 518 } 519} 520 521/* 522 * Discard all of the font information, e.g., we are resizing the font. 523 * Keep the GC's so we can simply change them rather than creating new ones. 524 */ 525void 526clrCgsFonts(XtermWidget xw, VTwin * cgsWin, XTermFonts * font) 527{ 528 CgsCache *me; 529 int j, k; 530 531 if (HaveFont(font)) { 532 for_each_gc(j) { 533 if ((me = myCache(xw, cgsWin, (CgsEnum) j)) != 0) { 534 for (k = 0; k < DEPTH; ++k) { 535 if (SameFont(LIST(k).font, font)) { 536 TRACE2(("clrCgsFonts %s gc %p(%d) %s\n", 537 traceCgsEnum((CgsEnum) j), 538 LIST(k).gc, 539 k, 540 traceFont(font))); 541 LIST(k).font = 0; 542 LIST(k).cset = 0; 543 } 544 } 545 if (SameFont(NEXT(font), font)) { 546 TRACE2(("clrCgsFonts %s next %s\n", 547 traceCgsEnum((CgsEnum) j), 548 traceFont(font))); 549 NEXT(font) = 0; 550 NEXT(cset) = 0; 551 me->mask &= (unsigned) ~(GCFont | GC_CSet); 552 } 553 } 554 } 555 } 556} 557 558/* 559 * Return a GC associated with the given id, allocating if needed. 560 */ 561GC 562getCgsGC(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId) 563{ 564 CgsCache *me; 565 GC result = 0; 566 int j, k; 567 unsigned used = 0; 568 569 if ((me = myCache(xw, cgsWin, cgsId)) != 0) { 570 TRACE2(("getCgsGC(%s, %s)\n", 571 traceVTwin(xw, cgsWin), traceCgsEnum(cgsId))); 572 if (me->mask != 0) { 573 574 /* fill in the unchanged fields */ 575 if (!(me->mask & GC_CSet)) 576 NEXT(cset) = 0; /* OPT_DEC_CHRSET */ 577 if (!(me->mask & GCFont)) 578 NEXT(font) = THIS(font); 579 if (!(me->mask & GCForeground)) 580 NEXT(fg) = THIS(fg); 581 if (!(me->mask & GCBackground)) 582 NEXT(bg) = THIS(bg); 583 584 if (NEXT(font) == 0) { 585 setCgsFont(xw, cgsWin, cgsId, 0); 586 } 587 588 TRACE2(("...Cgs new data fg=%s, bg=%s, font=%s cset %s\n", 589 tracePixel(xw, NEXT(fg)), 590 tracePixel(xw, NEXT(bg)), 591 traceFont(NEXT(font)), 592 traceCSet(NEXT(cset)))); 593 594 /* try to find the given data in an already-created GC */ 595 for (j = 0; j < DEPTH; ++j) { 596 if (LIST(j).gc != 0 597 && SameFont(LIST(j).font, NEXT(font)) 598 && SameCSet(LIST(j).cset, NEXT(cset)) 599 && SameColor(LIST(j).fg, NEXT(fg)) 600 && SameColor(LIST(j).bg, NEXT(bg))) { 601 LINK(j); 602 result = THIS(gc); 603 TRACE2(("getCgsGC existing %p(%d)\n", result, ITEM())); 604 break; 605 } 606 } 607 608 if (result == 0) { 609 /* try to find an empty slot, to create a new GC */ 610 used = 0; 611 for (j = 0; j < DEPTH; ++j) { 612 if (LIST(j).gc == 0) { 613 LINK(j); 614 result = newCache(xw, cgsWin, cgsId, me); 615 break; 616 } 617 if (used < LIST(j).used) 618 used = LIST(j).used; 619 } 620 } 621 622 if (result == 0) { 623 /* if none were empty, pick the least-used slot, to modify */ 624 for (j = 0, k = -1; j < DEPTH; ++j) { 625 if (used >= LIST(j).used) { 626 used = LIST(j).used; 627 k = j; 628 } 629 } 630 LINK(k); 631 TRACE2(("...getCgsGC least-used(%d) was %d\n", k, THIS(used))); 632 result = chgCache(xw, cgsId, me, True); 633 } 634 me->next = *(me->data); 635 } else { 636 result = THIS(gc); 637 } 638 me->mask = 0; 639 THIS(used) += 1; 640 TRACE2(("...getCgsGC(%s, %s) gc %p(%d), used %d\n", 641 traceVTwin(xw, cgsWin), 642 traceCgsEnum(cgsId), result, ITEM(), THIS(used))); 643 } 644 return result; 645} 646 647/* 648 * Return the font for the given GC. 649 */ 650CgsEnum 651getCgsId(XtermWidget xw, VTwin * cgsWin, GC gc) 652{ 653 int n; 654 CgsEnum result = gcNorm; 655 656 for_each_gc(n) { 657 CgsCache *me; 658 659 if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) { 660 if (THIS(gc) == gc) { 661 result = (CgsEnum) n; 662 break; 663 } 664 } 665 } 666 return result; 667} 668 669/* 670 * Return the font for the given GC. 671 */ 672XTermFonts * 673getCgsFont(XtermWidget xw, VTwin * cgsWin, GC gc) 674{ 675 int n; 676 XTermFonts *result = 0; 677 678 for_each_gc(n) { 679 CgsCache *me; 680 681 if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) { 682 if (THIS(gc) == gc) { 683 result = THIS(font); 684 break; 685 } 686 } 687 } 688 return result; 689} 690 691/* 692 * Return the foreground color for the given GC. 693 */ 694Pixel 695getCgsFore(XtermWidget xw, VTwin * cgsWin, GC gc) 696{ 697 int n; 698 Pixel result = 0; 699 700 for_each_gc(n) { 701 CgsCache *me; 702 703 if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) { 704 if (THIS(gc) == gc) { 705 result = THIS(fg); 706 break; 707 } 708 } 709 } 710 return result; 711} 712 713/* 714 * Return the background color for the given GC. 715 */ 716Pixel 717getCgsBack(XtermWidget xw, VTwin * cgsWin, GC gc) 718{ 719 int n; 720 Pixel result = 0; 721 722 for_each_gc(n) { 723 CgsCache *me; 724 725 if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) { 726 if (THIS(gc) == gc) { 727 result = THIS(bg); 728 break; 729 } 730 } 731 } 732 return result; 733} 734 735/* 736 * Copy the parameters (except GC of course) from one cache record to another. 737 */ 738void 739copyCgs(XtermWidget xw, VTwin * cgsWin, CgsEnum dstCgsId, CgsEnum srcCgsId) 740{ 741 if (dstCgsId != srcCgsId) { 742 CgsCache *me; 743 744 if ((me = myCache(xw, cgsWin, srcCgsId)) != 0) { 745 TRACE(("copyCgs from %s to %s\n", 746 traceCgsEnum(srcCgsId), 747 traceCgsEnum(dstCgsId))); 748 TRACE2(("copyCgs from %s (me %p, fg %s, bg %s, cset %s) to %s {{\n", 749 traceCgsEnum(srcCgsId), 750 me, 751 tracePixel(xw, THIS(fg)), 752 tracePixel(xw, THIS(bg)), 753 traceCSet(THIS(cset)), 754 traceCgsEnum(dstCgsId))); 755 setCgsCSet(xw, cgsWin, dstCgsId, THIS(cset)); 756 setCgsFore(xw, cgsWin, dstCgsId, THIS(fg)); 757 setCgsBack(xw, cgsWin, dstCgsId, THIS(bg)); 758 setCgsFont(xw, cgsWin, dstCgsId, THIS(font)); 759 TRACE2(("...copyCgs }}\n")); 760 } 761 } 762} 763 764/* 765 * Interchange colors in the cache, e.g., for reverse-video. 766 */ 767void 768redoCgs(XtermWidget xw, Pixel fg, Pixel bg, CgsEnum cgsId) 769{ 770 int n; 771 VTwin *cgsWin = WhichVWin(TScreenOf(xw)); 772 CgsCache *me = myCache(xw, cgsWin, cgsId); 773 774 if (me != 0) { 775 CgsCacheData *save_data = me->data; 776 777 for (n = 0; n < DEPTH; ++n) { 778 if (LIST(n).gc != 0 && HaveFont(LIST(n).font)) { 779 LINK(n); 780 781 if (LIST(n).fg == fg 782 && LIST(n).bg == bg) { 783 setCgsFore(xw, cgsWin, cgsId, bg); 784 setCgsBack(xw, cgsWin, cgsId, fg); 785 } else if (LIST(n).fg == bg 786 && LIST(n).bg == fg) { 787 setCgsFore(xw, cgsWin, cgsId, fg); 788 setCgsBack(xw, cgsWin, cgsId, bg); 789 } else { 790 continue; 791 } 792 793 (void) chgCache(xw, cgsId, me, False); 794 } 795 } 796 me->data = save_data; 797 } 798} 799 800/* 801 * Swap the cache records, e.g., when doing reverse-video. 802 */ 803void 804swapCgs(XtermWidget xw, VTwin * cgsWin, CgsEnum dstCgsId, CgsEnum srcCgsId) 805{ 806 if (dstCgsId != srcCgsId) { 807 CgsCache *dst; 808 CgsCache *src; 809 CgsCache tmp; 810 811 if ((src = myCache(xw, cgsWin, srcCgsId)) != 0) { 812 if ((dst = myCache(xw, cgsWin, dstCgsId)) != 0) { 813 int srcIndex = dataIndex(src); 814 int dstIndex = dataIndex(dst); 815 816 EXCHANGE(*src, *dst, tmp); 817 818 relinkData(src, dstIndex); 819 relinkData(dst, srcIndex); 820 } 821 } 822 } 823} 824 825/* 826 * Free any GC associated with the given id. 827 */ 828GC 829freeCgs(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId) 830{ 831 CgsCache *me; 832 int j; 833 834 if ((me = myCache(xw, cgsWin, cgsId)) != 0) { 835 for (j = 0; j < DEPTH; ++j) { 836 if (LIST(j).gc != 0) { 837 TRACE(("freeCgs(%s, %s) gc %p(%d)\n", 838 traceVTwin(xw, cgsWin), 839 traceCgsEnum(cgsId), (void *) LIST(j).gc, j)); 840 clrCgsFonts(xw, cgsWin, LIST(j).font); 841#if OPT_BOX_CHARS 842 if (cgsId == gcDots) { 843 XmuReleaseStippledPixmap(XtScreen((Widget) xw), LIST(j).tile); 844 } 845#endif 846 XFreeGC(TScreenOf(xw)->display, LIST(j).gc); 847 memset(&LIST(j), 0, sizeof(LIST(j))); 848 } 849 LINK(0); 850 } 851 } 852 return 0; 853} 854 855#ifdef NO_LEAKS 856void 857noleaks_cachedCgs(XtermWidget xw) 858{ 859#ifndef NO_ACTIVE_ICON 860 free(TScreenOf(xw)->icon_cgs_cache); 861#endif 862 free(TScreenOf(xw)->main_cgs_cache); 863} 864#endif 865