1 /* $NetBSD: color.c,v 1.48 2024/07/11 07:13:41 blymn Exp $ */ 2 3 /* 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Julian Coleman. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __RCSID("$NetBSD: color.c,v 1.48 2024/07/11 07:13:41 blymn Exp $"); 35 #endif /* not lint */ 36 37 #include "curses.h" 38 #include "curses_private.h" 39 40 /* Have we initialised colours? */ 41 int __using_color = 0; 42 int __do_color_init = 0; /* force refresh to init color in all cells */ 43 44 /* Default colour number */ 45 attr_t __default_color = 0; 46 47 /* Default colour pair values - white on black. */ 48 struct __pair __default_pair = {COLOR_WHITE, COLOR_BLACK, 0}; 49 50 /* Default colour values */ 51 /* Flags for colours and pairs */ 52 #define __USED 0x01 53 54 static void 55 __change_pair(short); 56 57 static int 58 init_color_value(short, short, short, short); 59 60 /* 61 * has_colors -- 62 * Check if terminal has colours. 63 */ 64 bool 65 has_colors(void) 66 { 67 if (max_colors > 0 && max_pairs > 0 && 68 ((set_a_foreground != NULL && set_a_background != NULL) || 69 initialize_pair != NULL || initialize_color != NULL || 70 (set_background != NULL && set_foreground != NULL))) 71 return true; 72 else 73 return false; 74 } 75 76 /* 77 * can_change_color -- 78 * Check if terminal can change colours. 79 */ 80 bool 81 can_change_color(void) 82 { 83 return can_change ? true : false; 84 } 85 86 /* 87 * start_color -- 88 * Initialise colour support. 89 */ 90 int 91 start_color(void) 92 { 93 int i; 94 attr_t temp_nc; 95 struct __winlist *wlp; 96 WINDOW *win; 97 int y, x; 98 99 if (has_colors() == FALSE) 100 return ERR; 101 102 /* Max colours and colour pairs */ 103 if (max_colors == -1) 104 COLORS = 0; 105 else { 106 COLORS = max_colors > MAX_COLORS ? MAX_COLORS : max_colors; 107 if (max_pairs == -1) { 108 COLOR_PAIRS = 0; 109 COLORS = 0; 110 } else { 111 COLOR_PAIRS = (max_pairs > MAX_PAIRS - 1 ? 112 MAX_PAIRS - 1 : max_pairs); 113 /* Use the last colour pair for curses default. */ 114 #ifdef __OLD_DEFAULT_COLOR 115 __default_color = COLOR_PAIR(MAX_PAIRS - 1); 116 #else 117 __default_color = COLOR_PAIR(0); 118 #endif 119 } 120 } 121 if (!COLORS) 122 return ERR; 123 124 _cursesi_screen->COLORS = COLORS; 125 _cursesi_screen->COLOR_PAIRS = COLOR_PAIRS; 126 _cursesi_screen->curpair = -1; 127 128 /* Reset terminal colour and colour pairs. */ 129 if (orig_colors != NULL) 130 tputs(orig_colors, 0, __cputchar); 131 if (orig_pair != NULL) { 132 tputs(orig_pair, 0, __cputchar); 133 curscr->wattr &= _cursesi_screen->mask_op; 134 } 135 136 /* Type of colour manipulation - ANSI/TEK/HP/other */ 137 if (set_a_foreground != NULL && set_a_background != NULL) 138 _cursesi_screen->color_type = COLOR_ANSI; 139 else if (initialize_pair != NULL) 140 _cursesi_screen->color_type = COLOR_HP; 141 else if (initialize_color != NULL) 142 _cursesi_screen->color_type = COLOR_TEK; 143 else if (set_foreground != NULL && set_background != NULL) 144 _cursesi_screen->color_type = COLOR_OTHER; 145 else 146 return(ERR); /* Unsupported colour method */ 147 148 #ifdef DEBUG 149 __CTRACE(__CTRACE_COLOR, "start_color: COLORS = %d, COLOR_PAIRS = %d", 150 COLORS, COLOR_PAIRS); 151 switch (_cursesi_screen->color_type) { 152 case COLOR_ANSI: 153 __CTRACE(__CTRACE_COLOR, " (ANSI style)\n"); 154 break; 155 case COLOR_HP: 156 __CTRACE(__CTRACE_COLOR, " (HP style)\n"); 157 break; 158 case COLOR_TEK: 159 __CTRACE(__CTRACE_COLOR, " (Tektronics style)\n"); 160 break; 161 case COLOR_OTHER: 162 __CTRACE(__CTRACE_COLOR, " (Other style)\n"); 163 break; 164 } 165 #endif 166 167 /* 168 * Attributes that cannot be used with color. 169 * Store these in an attr_t for wattrset()/wattron(). 170 */ 171 _cursesi_screen->nca = __NORMAL; 172 if (no_color_video != -1) { 173 temp_nc = (attr_t)t_no_color_video(_cursesi_screen->term); 174 if (temp_nc & 0x0001) 175 _cursesi_screen->nca |= __STANDOUT; 176 if (temp_nc & 0x0002) 177 _cursesi_screen->nca |= __UNDERSCORE; 178 if (temp_nc & 0x0004) 179 _cursesi_screen->nca |= __REVERSE; 180 if (temp_nc & 0x0008) 181 _cursesi_screen->nca |= __BLINK; 182 if (temp_nc & 0x0010) 183 _cursesi_screen->nca |= __DIM; 184 if (temp_nc & 0x0020) 185 _cursesi_screen->nca |= __BOLD; 186 if (temp_nc & 0x0040) 187 _cursesi_screen->nca |= __BLANK; 188 if (temp_nc & 0x0080) 189 _cursesi_screen->nca |= __PROTECT; 190 if (temp_nc & 0x0100) 191 _cursesi_screen->nca |= __ALTCHARSET; 192 } 193 __CTRACE(__CTRACE_COLOR, "start_color: _cursesi_screen->nca = %08x\n", 194 _cursesi_screen->nca); 195 196 /* Set up initial 8 colours */ 197 #define RGB_ON 680 /* Allow for bright colours */ 198 if (COLORS >= COLOR_BLACK) 199 (void)init_color_value(COLOR_BLACK, 0, 0, 0); 200 if (COLORS >= COLOR_RED) 201 (void)init_color_value(COLOR_RED, RGB_ON, 0, 0); 202 if (COLORS >= COLOR_GREEN) 203 (void)init_color_value(COLOR_GREEN, 0, RGB_ON, 0); 204 if (COLORS >= COLOR_YELLOW) 205 (void)init_color_value(COLOR_YELLOW, RGB_ON, RGB_ON, 0); 206 if (COLORS >= COLOR_BLUE) 207 (void)init_color_value(COLOR_BLUE, 0, 0, RGB_ON); 208 if (COLORS >= COLOR_MAGENTA) 209 (void)init_color_value(COLOR_MAGENTA, RGB_ON, 0, RGB_ON); 210 if (COLORS >= COLOR_CYAN) 211 (void)init_color_value(COLOR_CYAN, 0, RGB_ON, RGB_ON); 212 if (COLORS >= COLOR_WHITE) 213 (void)init_color_value(COLOR_WHITE, RGB_ON, RGB_ON, RGB_ON); 214 215 /* Initialise other colours */ 216 for (i = 8; i < COLORS; i++) { 217 _cursesi_screen->colours[i].red = 0; 218 _cursesi_screen->colours[i].green = 0; 219 _cursesi_screen->colours[i].blue = 0; 220 _cursesi_screen->colours[i].flags = 0; 221 } 222 223 /* Initialise pair 0 to default colours. */ 224 _cursesi_screen->colour_pairs[0].fore = -1; 225 _cursesi_screen->colour_pairs[0].back = -1; 226 _cursesi_screen->colour_pairs[0].flags = 0; 227 228 /* Initialise user colour pairs to default (white on black) */ 229 for (i = 0; i < COLOR_PAIRS; i++) { 230 _cursesi_screen->colour_pairs[i].fore = COLOR_WHITE; 231 _cursesi_screen->colour_pairs[i].back = COLOR_BLACK; 232 _cursesi_screen->colour_pairs[i].flags = 0; 233 } 234 235 /* Initialise default colour pair. */ 236 _cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].fore = 237 __default_pair.fore; 238 _cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].back = 239 __default_pair.back; 240 _cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].flags = 241 __default_pair.flags; 242 243 __using_color = 1; 244 __do_color_init = 1; 245 246 /* Set all positions on all windows to curses default colours. */ 247 for (wlp = _cursesi_screen->winlistp; wlp != NULL; wlp = wlp->nextp) { 248 win = wlp->winp; 249 if (wlp->winp != __virtscr && wlp->winp != curscr) { 250 /* Set color attribute on other windows */ 251 win->battr |= __default_color; 252 for (y = 0; y < win->maxy; y++) { 253 win->alines[y]->flags |= __ISFORCED; 254 for (x = 0; x < win->maxx; x++) { 255 win->alines[y]->line[x].attr &= ~__COLOR; 256 win->alines[y]->line[x].attr |= __default_color; 257 } 258 } 259 __touchwin(win, 0); 260 } 261 } 262 263 return(OK); 264 } 265 266 /* 267 * init_pair -- 268 * Set pair foreground and background colors. 269 * Our default colour ordering is ANSI - 1 = red, 4 = blue, 3 = yellow, 270 * 6 = cyan. The older style (Sb/Sf) uses 1 = blue, 4 = red, 3 = cyan, 271 * 6 = yellow, so we swap them here and in pair_content(). 272 */ 273 int 274 init_pair(short pair, short fore, short back) 275 { 276 int changed; 277 278 __CTRACE(__CTRACE_COLOR, "init_pair: %d, %d, %d\n", pair, fore, back); 279 280 if (pair < 0 || pair >= COLOR_PAIRS) 281 return ERR; 282 283 if (pair == 0) /* Ignore request for pair 0, it is default. */ 284 return OK; 285 286 if (fore >= COLORS) 287 return ERR; 288 if (back >= COLORS) 289 return ERR; 290 291 /* Swap red/blue and yellow/cyan */ 292 if (_cursesi_screen->color_type == COLOR_OTHER) { 293 switch (fore) { 294 case COLOR_RED: 295 fore = COLOR_BLUE; 296 break; 297 case COLOR_BLUE: 298 fore = COLOR_RED; 299 break; 300 case COLOR_YELLOW: 301 fore = COLOR_CYAN; 302 break; 303 case COLOR_CYAN: 304 fore = COLOR_YELLOW; 305 break; 306 } 307 switch (back) { 308 case COLOR_RED: 309 back = COLOR_BLUE; 310 break; 311 case COLOR_BLUE: 312 back = COLOR_RED; 313 break; 314 case COLOR_YELLOW: 315 back = COLOR_CYAN; 316 break; 317 case COLOR_CYAN: 318 back = COLOR_YELLOW; 319 break; 320 } 321 } 322 323 if ((_cursesi_screen->colour_pairs[pair].flags & __USED) && 324 (fore != _cursesi_screen->colour_pairs[pair].fore || 325 back != _cursesi_screen->colour_pairs[pair].back)) 326 changed = 1; 327 else 328 changed = 0; 329 330 _cursesi_screen->colour_pairs[pair].flags |= __USED; 331 _cursesi_screen->colour_pairs[pair].fore = fore; 332 _cursesi_screen->colour_pairs[pair].back = back; 333 334 /* XXX: need to initialise HP style (Ip) */ 335 336 if (changed) 337 __change_pair(pair); 338 return OK; 339 } 340 341 /* 342 * pair_content -- 343 * Get pair foreground and background colours. 344 */ 345 int 346 pair_content(short pair, short *forep, short *backp) 347 { 348 if (pair < 0 || pair > _cursesi_screen->COLOR_PAIRS) 349 return ERR; 350 351 *forep = _cursesi_screen->colour_pairs[pair].fore; 352 *backp = _cursesi_screen->colour_pairs[pair].back; 353 354 /* Swap red/blue and yellow/cyan */ 355 if (_cursesi_screen->color_type == COLOR_OTHER) { 356 switch (*forep) { 357 case COLOR_RED: 358 *forep = COLOR_BLUE; 359 break; 360 case COLOR_BLUE: 361 *forep = COLOR_RED; 362 break; 363 case COLOR_YELLOW: 364 *forep = COLOR_CYAN; 365 break; 366 case COLOR_CYAN: 367 *forep = COLOR_YELLOW; 368 break; 369 } 370 switch (*backp) { 371 case COLOR_RED: 372 *backp = COLOR_BLUE; 373 break; 374 case COLOR_BLUE: 375 *backp = COLOR_RED; 376 break; 377 case COLOR_YELLOW: 378 *backp = COLOR_CYAN; 379 break; 380 case COLOR_CYAN: 381 *backp = COLOR_YELLOW; 382 break; 383 } 384 } 385 return OK; 386 } 387 388 /* 389 * init_color_Value -- 390 * Set colour red, green and blue values. 391 */ 392 static int 393 init_color_value(short color, short red, short green, short blue) 394 { 395 if (color < 0 || color >= _cursesi_screen->COLORS) 396 return ERR; 397 398 _cursesi_screen->colours[color].red = red; 399 _cursesi_screen->colours[color].green = green; 400 _cursesi_screen->colours[color].blue = blue; 401 return OK; 402 } 403 404 /* 405 * init_color -- 406 * Set colour red, green and blue values. 407 * Change color on screen. 408 */ 409 int 410 init_color(short color, short red, short green, short blue) 411 { 412 __CTRACE(__CTRACE_COLOR, "init_color: %d, %d, %d, %d\n", 413 color, red, green, blue); 414 if (init_color_value(color, red, green, blue) == ERR) 415 return ERR; 416 if (!can_change || t_initialize_color(_cursesi_screen->term) == NULL) 417 return ERR; 418 tputs(tiparm(t_initialize_color(_cursesi_screen->term), 419 color, red, green, blue), 0, __cputchar); 420 return OK; 421 } 422 423 /* 424 * color_content -- 425 * Get colour red, green and blue values. 426 */ 427 int 428 color_content(short color, short *redp, short *greenp, short *bluep) 429 { 430 if (color < 0 || color >= _cursesi_screen->COLORS) 431 return ERR; 432 433 *redp = _cursesi_screen->colours[color].red; 434 *greenp = _cursesi_screen->colours[color].green; 435 *bluep = _cursesi_screen->colours[color].blue; 436 return OK; 437 } 438 439 /* 440 * use_default_colors -- 441 * Use terminal default colours instead of curses default colour. 442 */ 443 int 444 use_default_colors(void) 445 { 446 __CTRACE(__CTRACE_COLOR, "use_default_colors\n"); 447 448 return (assume_default_colors(-1, -1)); 449 } 450 451 /* 452 * assume_default_colors -- 453 * Set the default foreground and background colours. 454 */ 455 int 456 assume_default_colors(short fore, short back) 457 { 458 __CTRACE(__CTRACE_COLOR, "assume_default_colors: %d, %d\n", 459 fore, back); 460 __CTRACE(__CTRACE_COLOR, 461 "assume_default_colors: default_colour = %d, pair_number = %d\n", 462 __default_color, PAIR_NUMBER(__default_color)); 463 464 /* Swap red/blue and yellow/cyan */ 465 if (_cursesi_screen->color_type == COLOR_OTHER) { 466 switch (fore) { 467 case COLOR_RED: 468 fore = COLOR_BLUE; 469 break; 470 case COLOR_BLUE: 471 fore = COLOR_RED; 472 break; 473 case COLOR_YELLOW: 474 fore = COLOR_CYAN; 475 break; 476 case COLOR_CYAN: 477 fore = COLOR_YELLOW; 478 break; 479 } 480 switch (back) { 481 case COLOR_RED: 482 back = COLOR_BLUE; 483 break; 484 case COLOR_BLUE: 485 back = COLOR_RED; 486 break; 487 case COLOR_YELLOW: 488 back = COLOR_CYAN; 489 break; 490 case COLOR_CYAN: 491 back = COLOR_YELLOW; 492 break; 493 } 494 } 495 __default_pair.fore = fore; 496 __default_pair.back = back; 497 __default_pair.flags = __USED; 498 499 if (COLOR_PAIRS) { 500 _cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].fore = fore; 501 _cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].back = back; 502 _cursesi_screen->colour_pairs[PAIR_NUMBER(__default_color)].flags = __USED; 503 } 504 505 /* 506 * If we've already called start_color(), make sure all instances 507 * of the curses default colour pair are dirty. 508 */ 509 if (__using_color) 510 __change_pair(PAIR_NUMBER(__default_color)); 511 512 return(OK); 513 } 514 515 /* no_color_video is a terminfo macro, but we need to retain binary compat */ 516 #ifdef __strong_alias 517 #undef no_color_video 518 __strong_alias(no_color_video, no_color_attributes) 519 #endif 520 /* 521 * no_color_attributes -- 522 * Return attributes that cannot be combined with color. 523 */ 524 attr_t 525 no_color_attributes(void) 526 { 527 return(_cursesi_screen->nca); 528 } 529 530 /* 531 * __set_color -- 532 * Set terminal foreground and background colours. 533 */ 534 void 535 __set_color( /*ARGSUSED*/ WINDOW *win, attr_t attr) 536 { 537 short pair; 538 539 if ((__do_color_init != 1) && 540 ((curscr->wattr & __COLOR) == (attr & __COLOR))) 541 return; 542 543 pair = PAIR_NUMBER((uint32_t)attr); 544 545 if (pair == _cursesi_screen->curpair) 546 return; 547 548 __CTRACE(__CTRACE_COLOR, "__set_color: %d, %d, %d\n", pair, 549 _cursesi_screen->colour_pairs[pair].fore, 550 _cursesi_screen->colour_pairs[pair].back); 551 switch (_cursesi_screen->color_type) { 552 /* Set ANSI foreground and background colours */ 553 case COLOR_ANSI: 554 if (_cursesi_screen->colour_pairs[pair].fore < 0 || 555 _cursesi_screen->colour_pairs[pair].back < 0) 556 __unset_color(curscr); 557 if (_cursesi_screen->colour_pairs[pair].fore >= 0) 558 tputs(tiparm(t_set_a_foreground(_cursesi_screen->term), 559 (int)_cursesi_screen->colour_pairs[pair].fore), 560 0, __cputchar); 561 if (_cursesi_screen->colour_pairs[pair].back >= 0) 562 tputs(tiparm(t_set_a_background(_cursesi_screen->term), 563 (int)_cursesi_screen->colour_pairs[pair].back), 564 0, __cputchar); 565 break; 566 case COLOR_HP: 567 /* XXX: need to support HP style */ 568 break; 569 case COLOR_TEK: 570 /* XXX: need to support Tek style */ 571 break; 572 case COLOR_OTHER: 573 if (_cursesi_screen->colour_pairs[pair].fore < 0 || 574 _cursesi_screen->colour_pairs[pair].back < 0) 575 __unset_color(curscr); 576 if (_cursesi_screen->colour_pairs[pair].fore >= 0) 577 tputs(tiparm(t_set_foreground(_cursesi_screen->term), 578 (int)_cursesi_screen->colour_pairs[pair].fore), 579 0, __cputchar); 580 if (_cursesi_screen->colour_pairs[pair].back >= 0) 581 tputs(tiparm(t_set_background(_cursesi_screen->term), 582 (int)_cursesi_screen->colour_pairs[pair].back), 583 0, __cputchar); 584 break; 585 } 586 587 _cursesi_screen->curpair = pair; 588 curscr->wattr &= ~__COLOR; 589 curscr->wattr |= attr & __COLOR; 590 } 591 592 /* 593 * __unset_color -- 594 * Clear terminal foreground and background colours. 595 */ 596 void 597 __unset_color(WINDOW *win) 598 { 599 __CTRACE(__CTRACE_COLOR, "__unset_color\n"); 600 switch (_cursesi_screen->color_type) { 601 /* Clear ANSI foreground and background colours */ 602 case COLOR_ANSI: 603 if (orig_pair != NULL) { 604 tputs(orig_pair, 0, __cputchar); 605 win->wattr &= __mask_op; 606 } 607 break; 608 case COLOR_HP: 609 /* XXX: need to support HP style */ 610 break; 611 case COLOR_TEK: 612 /* XXX: need to support Tek style */ 613 break; 614 case COLOR_OTHER: 615 if (orig_pair != NULL) { 616 tputs(orig_pair, 0, __cputchar); 617 win->wattr &= __mask_op; 618 } 619 break; 620 } 621 622 _cursesi_screen->curpair = -1; 623 } 624 625 /* 626 * __restore_colors -- 627 * Redo color definitions after restarting 'curses' mode. 628 */ 629 void 630 __restore_colors(void) 631 { 632 /* 633 * forget foreground/background colour just in case it was 634 * changed. We will reset them if required. 635 */ 636 _cursesi_screen->curpair = -1; 637 638 if (can_change != 0) 639 switch (_cursesi_screen->color_type) { 640 case COLOR_HP: 641 /* XXX: need to re-initialise HP style (Ip) */ 642 break; 643 case COLOR_TEK: 644 /* XXX: need to re-initialise Tek style (Ic) */ 645 break; 646 } 647 } 648 649 /* 650 * __change_pair -- 651 * Mark dirty all positions using pair. 652 */ 653 void 654 __change_pair(short pair) 655 { 656 struct __winlist *wlp; 657 WINDOW *win; 658 int y, x; 659 __LINE *lp; 660 uint32_t cl = COLOR_PAIR(pair); 661 662 663 for (wlp = _cursesi_screen->winlistp; wlp != NULL; wlp = wlp->nextp) { 664 __CTRACE(__CTRACE_COLOR, "__change_pair: win = %p\n", 665 wlp->winp); 666 win = wlp->winp; 667 if (win == __virtscr) 668 continue; 669 else if (win == curscr) { 670 /* Reset colour attribute on curscr */ 671 __CTRACE(__CTRACE_COLOR, 672 "__change_pair: win == curscr\n"); 673 for (y = 0; y < curscr->maxy; y++) { 674 lp = curscr->alines[y]; 675 for (x = 0; x < curscr->maxx; x++) { 676 if ((lp->line[x].attr & __COLOR) == cl) 677 lp->line[x].attr &= ~__COLOR; 678 } 679 } 680 } else { 681 /* Mark dirty those positions with colour pair "pair" */ 682 for (y = 0; y < win->maxy; y++) { 683 lp = win->alines[y]; 684 for (x = 0; x < win->maxx; x++) 685 if ((lp->line[x].attr & 686 __COLOR) == cl) { 687 if (!(lp->flags & __ISDIRTY)) 688 lp->flags |= __ISDIRTY; 689 /* 690 * firstchp/lastchp are shared 691 * between parent window and 692 * sub-window. 693 */ 694 if (*lp->firstchp > x) 695 *lp->firstchp = x; 696 697 if (*lp->lastchp < x) 698 *lp->lastchp = x; 699 } 700 #ifdef DEBUG 701 if ((win->alines[y]->flags & __ISDIRTY)) 702 __CTRACE(__CTRACE_COLOR, 703 "__change_pair: first = %d, " 704 "last = %d\n", 705 *win->alines[y]->firstchp, 706 *win->alines[y]->lastchp); 707 #endif 708 } 709 } 710 } 711 } 712