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