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