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