cachedGCs.c revision a1f3da82
1/* $XTermId: cachedGCs.c,v 1.60 2011/02/09 10:11:44 tom Exp $ */ 2 3/************************************************************ 4 5Copyright 2007-2010,2011 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 /* 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 CgsCache *me; 531 int j, k; 532 533 if (HaveFont(font)) { 534 for_each_gc(j) { 535 if ((me = myCache(xw, cgsWin, (CgsEnum) j)) != 0) { 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 int j, k; 569 unsigned used = 0; 570 571 if ((me = myCache(xw, cgsWin, cgsId)) != 0) { 572 TRACE2(("getCgsGC(%s, %s)\n", 573 traceVTwin(xw, cgsWin), traceCgsEnum(cgsId))); 574 if (me->mask != 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 /* if none were empty, pick the least-used slot, to modify */ 626 for (j = 0, k = -1; j < DEPTH; ++j) { 627 if (used >= LIST(j).used) { 628 used = LIST(j).used; 629 k = j; 630 } 631 } 632 LINK(k); 633 TRACE2(("...getCgsGC least-used(%d) was %d\n", k, THIS(used))); 634 result = chgCache(xw, cgsId, me, True); 635 } 636 me->next = *(me->data); 637 } else { 638 result = THIS(gc); 639 } 640 me->mask = 0; 641 THIS(used) += 1; 642 TRACE2(("...getCgsGC(%s, %s) gc %p(%d), used %d\n", 643 traceVTwin(xw, cgsWin), 644 traceCgsEnum(cgsId), result, ITEM(), THIS(used))); 645 } 646 return result; 647} 648 649/* 650 * Return the font for the given GC. 651 */ 652CgsEnum 653getCgsId(XtermWidget xw, VTwin * cgsWin, GC gc) 654{ 655 int n; 656 CgsEnum result = gcNorm; 657 658 for_each_gc(n) { 659 CgsCache *me; 660 661 if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) { 662 if (THIS(gc) == gc) { 663 result = (CgsEnum) n; 664 break; 665 } 666 } 667 } 668 return result; 669} 670 671/* 672 * Return the font for the given GC. 673 */ 674XTermFonts * 675getCgsFont(XtermWidget xw, VTwin * cgsWin, GC gc) 676{ 677 int n; 678 XTermFonts *result = 0; 679 680 for_each_gc(n) { 681 CgsCache *me; 682 683 if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) { 684 if (THIS(gc) == gc) { 685 result = THIS(font); 686 break; 687 } 688 } 689 } 690 return result; 691} 692 693/* 694 * Return the foreground color for the given GC. 695 */ 696Pixel 697getCgsFore(XtermWidget xw, VTwin * cgsWin, GC gc) 698{ 699 int n; 700 Pixel result = 0; 701 702 for_each_gc(n) { 703 CgsCache *me; 704 705 if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) { 706 if (THIS(gc) == gc) { 707 result = THIS(fg); 708 break; 709 } 710 } 711 } 712 return result; 713} 714 715/* 716 * Return the background color for the given GC. 717 */ 718Pixel 719getCgsBack(XtermWidget xw, VTwin * cgsWin, GC gc) 720{ 721 int n; 722 Pixel result = 0; 723 724 for_each_gc(n) { 725 CgsCache *me; 726 727 if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) { 728 if (THIS(gc) == gc) { 729 result = THIS(bg); 730 break; 731 } 732 } 733 } 734 return result; 735} 736 737/* 738 * Copy the parameters (except GC of course) from one cache record to another. 739 */ 740void 741copyCgs(XtermWidget xw, VTwin * cgsWin, CgsEnum dstCgsId, CgsEnum srcCgsId) 742{ 743 if (dstCgsId != srcCgsId) { 744 CgsCache *me; 745 746 if ((me = myCache(xw, cgsWin, srcCgsId)) != 0) { 747 TRACE(("copyCgs from %s to %s\n", 748 traceCgsEnum(srcCgsId), 749 traceCgsEnum(dstCgsId))); 750 TRACE2(("copyCgs from %s (me %p, fg %s, bg %s, cset %s) to %s {{\n", 751 traceCgsEnum(srcCgsId), 752 me, 753 tracePixel(xw, THIS(fg)), 754 tracePixel(xw, THIS(bg)), 755 traceCSet(THIS(cset)), 756 traceCgsEnum(dstCgsId))); 757 setCgsCSet(xw, cgsWin, dstCgsId, THIS(cset)); 758 setCgsFore(xw, cgsWin, dstCgsId, THIS(fg)); 759 setCgsBack(xw, cgsWin, dstCgsId, THIS(bg)); 760 setCgsFont(xw, cgsWin, dstCgsId, THIS(font)); 761 TRACE2(("...copyCgs }}\n")); 762 } 763 } 764} 765 766/* 767 * Interchange colors in the cache, e.g., for reverse-video. 768 */ 769void 770redoCgs(XtermWidget xw, Pixel fg, Pixel bg, CgsEnum cgsId) 771{ 772 int n; 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 779 for (n = 0; n < DEPTH; ++n) { 780 if (LIST(n).gc != 0 && HaveFont(LIST(n).font)) { 781 LINK(n); 782 783 if (LIST(n).fg == fg 784 && LIST(n).bg == bg) { 785 setCgsFore(xw, cgsWin, cgsId, bg); 786 setCgsBack(xw, cgsWin, cgsId, fg); 787 } else if (LIST(n).fg == bg 788 && LIST(n).bg == fg) { 789 setCgsFore(xw, cgsWin, cgsId, fg); 790 setCgsBack(xw, cgsWin, cgsId, bg); 791 } else { 792 continue; 793 } 794 795 (void) chgCache(xw, cgsId, me, False); 796 } 797 } 798 me->data = save_data; 799 } 800} 801 802/* 803 * Swap the cache records, e.g., when doing reverse-video. 804 */ 805void 806swapCgs(XtermWidget xw, VTwin * cgsWin, CgsEnum dstCgsId, CgsEnum srcCgsId) 807{ 808 if (dstCgsId != srcCgsId) { 809 CgsCache *dst; 810 CgsCache *src; 811 CgsCache tmp; 812 813 if ((src = myCache(xw, cgsWin, srcCgsId)) != 0) { 814 if ((dst = myCache(xw, cgsWin, dstCgsId)) != 0) { 815 int srcIndex = dataIndex(src); 816 int dstIndex = dataIndex(dst); 817 818 EXCHANGE(*src, *dst, tmp); 819 820 relinkData(src, dstIndex); 821 relinkData(dst, srcIndex); 822 } 823 } 824 } 825} 826 827/* 828 * Free any GC associated with the given id. 829 */ 830GC 831freeCgs(XtermWidget xw, VTwin * cgsWin, CgsEnum cgsId) 832{ 833 CgsCache *me; 834 int j; 835 836 if ((me = myCache(xw, cgsWin, cgsId)) != 0) { 837 for (j = 0; j < DEPTH; ++j) { 838 if (LIST(j).gc != 0) { 839 TRACE(("freeCgs(%s, %s) gc %p(%d)\n", 840 traceVTwin(xw, cgsWin), 841 traceCgsEnum(cgsId), (void *) LIST(j).gc, j)); 842 clrCgsFonts(xw, cgsWin, LIST(j).font); 843#if OPT_BOX_CHARS 844 if (cgsId == gcDots) { 845 XmuReleaseStippledPixmap(XtScreen((Widget) xw), LIST(j).tile); 846 } 847#endif 848 XFreeGC(TScreenOf(xw)->display, LIST(j).gc); 849 memset(&LIST(j), 0, sizeof(LIST(j))); 850 } 851 LINK(0); 852 } 853 } 854 return 0; 855} 856 857#ifdef NO_LEAKS 858void 859noleaks_cachedCgs(XtermWidget xw) 860{ 861#ifndef NO_ACTIVE_ICON 862 free(TScreenOf(xw)->icon_cgs_cache); 863#endif 864 free(TScreenOf(xw)->main_cgs_cache); 865} 866#endif 867