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