1 /**************************************************************************** 2 * Copyright 2018-2019,2020 Thomas E. Dickey * 3 * Copyright 1998-2017,2018 Free Software Foundation, Inc. * 4 * * 5 * Permission is hereby granted, free of charge, to any person obtaining a * 6 * copy of this software and associated documentation files (the * 7 * "Software"), to deal in the Software without restriction, including * 8 * without limitation the rights to use, copy, modify, merge, publish, * 9 * distribute, distribute with modifications, sublicense, and/or sell * 10 * copies of the Software, and to permit persons to whom the Software is * 11 * furnished to do so, subject to the following conditions: * 12 * * 13 * The above copyright notice and this permission notice shall be included * 14 * in all copies or substantial portions of the Software. * 15 * * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 23 * * 24 * Except as contained in this notice, the name(s) of the above copyright * 25 * holders shall not be used in advertising or otherwise to promote the * 26 * sale, use or other dealings in this Software without prior written * 27 * authorization. * 28 ****************************************************************************/ 29 30 /**************************************************************************** 31 * Author: Thomas Dickey 1996-on * 32 * and: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 33 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 34 * and: Juergen Pfeifer * 35 ****************************************************************************/ 36 37 /* 38 * lib_traceatr.c - Tracing/Debugging routines (attributes) 39 */ 40 41 #include <curses.priv.h> 42 43 #ifndef CUR 44 #define CUR SP_TERMTYPE 45 #endif 46 47 MODULE_ID("$Id: lib_traceatr.c,v 1.94 2020/02/02 23:34:34 tom Exp $") 48 49 #define COLOR_OF(c) ((c < 0) ? "default" : (c > 7 ? color_of(c) : colors[c].name)) 50 51 #define TRACE_BUF_SIZE(num) (_nc_globals.tracebuf_ptr[num].size) 52 #define COLOR_BUF_SIZE(num) (sizeof(my_buffer[num])) 53 54 #ifdef TRACE 55 56 static const char l_brace[] = StringOf(L_BRACE); 57 static const char r_brace[] = StringOf(R_BRACE); 58 59 #ifndef USE_TERMLIB 60 61 #define my_buffer _nc_globals.traceatr_color_buf 62 #define my_select _nc_globals.traceatr_color_sel 63 #define my_cached _nc_globals.traceatr_color_last 64 65 static char * 66 color_of(int c) 67 { 68 if (c != my_cached) { 69 my_cached = c; 70 my_select = !my_select; 71 if (isDefaultColor(c)) 72 _nc_STRCPY(my_buffer[my_select], "default", 73 COLOR_BUF_SIZE(my_select)); 74 else 75 _nc_SPRINTF(my_buffer[my_select], 76 _nc_SLIMIT(COLOR_BUF_SIZE(my_select)) 77 "color%d", c); 78 } 79 return my_buffer[my_select]; 80 } 81 82 #undef my_buffer 83 #undef my_select 84 #endif /* !USE_TERMLIB */ 85 86 NCURSES_EXPORT(char *) 87 _traceattr2(int bufnum, chtype newmode) 88 { 89 #define DATA(name) { name, { #name } } 90 static const struct { 91 unsigned int val; 92 const char name[14]; 93 } names[] = 94 { 95 DATA(A_STANDOUT), 96 DATA(A_UNDERLINE), 97 DATA(A_REVERSE), 98 DATA(A_BLINK), 99 DATA(A_DIM), 100 DATA(A_BOLD), 101 DATA(A_ALTCHARSET), 102 DATA(A_INVIS), 103 DATA(A_PROTECT), 104 DATA(A_CHARTEXT), 105 DATA(A_NORMAL), 106 DATA(A_COLOR), 107 #if USE_ITALIC 108 DATA(A_ITALIC), 109 #endif 110 } 111 #ifndef USE_TERMLIB 112 , 113 colors[] = 114 { 115 DATA(COLOR_BLACK), 116 DATA(COLOR_RED), 117 DATA(COLOR_GREEN), 118 DATA(COLOR_YELLOW), 119 DATA(COLOR_BLUE), 120 DATA(COLOR_MAGENTA), 121 DATA(COLOR_CYAN), 122 DATA(COLOR_WHITE), 123 } 124 #endif /* !USE_TERMLIB */ 125 ; 126 #undef DATA 127 char *result = _nc_trace_buf(bufnum, (size_t) BUFSIZ); 128 129 if (result != 0) { 130 size_t n; 131 unsigned save_nc_tracing = _nc_tracing; 132 133 _nc_tracing = 0; 134 135 _nc_STRCPY(result, l_brace, TRACE_BUF_SIZE(bufnum)); 136 137 for (n = 0; n < SIZEOF(names); n++) { 138 139 if ((newmode & names[n].val) != 0) { 140 if (result[1] != '\0') 141 (void) _nc_trace_bufcat(bufnum, "|"); 142 result = _nc_trace_bufcat(bufnum, names[n].name); 143 144 if (names[n].val == A_COLOR) { 145 char temp[80]; 146 short pairnum = (short) PairNumber(newmode); 147 #ifdef USE_TERMLIB 148 /* pair_content lives in libncurses */ 149 _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) 150 "{%d}", pairnum); 151 #else 152 NCURSES_COLOR_T fg, bg; 153 154 if (pair_content(pairnum, &fg, &bg) == OK) { 155 _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) 156 "{%d = {%s, %s}}", 157 pairnum, 158 COLOR_OF(fg), 159 COLOR_OF(bg)); 160 } else { 161 _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) 162 "{%d}", pairnum); 163 } 164 #endif 165 result = _nc_trace_bufcat(bufnum, temp); 166 } 167 } 168 } 169 if (ChAttrOf(newmode) == A_NORMAL) { 170 if (result != 0 && result[1] != '\0') 171 (void) _nc_trace_bufcat(bufnum, "|"); 172 (void) _nc_trace_bufcat(bufnum, "A_NORMAL"); 173 } 174 175 _nc_tracing = save_nc_tracing; 176 result = _nc_trace_bufcat(bufnum, r_brace); 177 } 178 return result; 179 } 180 181 NCURSES_EXPORT(char *) 182 _traceattr(attr_t newmode) 183 { 184 return _traceattr2(0, newmode); 185 } 186 187 /* Trace 'int' return-values */ 188 NCURSES_EXPORT(int) 189 _nc_retrace_int_attr_t(attr_t code) 190 { 191 T((T_RETURN("%s"), _traceattr(code))); 192 return (int) code; 193 } 194 195 /* Trace 'attr_t' return-values */ 196 NCURSES_EXPORT(attr_t) 197 _nc_retrace_attr_t(attr_t code) 198 { 199 T((T_RETURN("%s"), _traceattr(code))); 200 return code; 201 } 202 203 const char * 204 _nc_altcharset_name(attr_t attr, chtype ch) 205 { 206 #define DATA(code, name) { code, { #name } } 207 typedef struct { 208 unsigned int val; 209 const char name[13]; 210 } ALT_NAMES; 211 #if NCURSES_SP_FUNCS 212 SCREEN *sp = CURRENT_SCREEN; 213 #endif 214 static const ALT_NAMES names[] = 215 { 216 DATA('l', ACS_ULCORNER), /* upper left corner */ 217 DATA('m', ACS_LLCORNER), /* lower left corner */ 218 DATA('k', ACS_URCORNER), /* upper right corner */ 219 DATA('j', ACS_LRCORNER), /* lower right corner */ 220 DATA('t', ACS_LTEE), /* tee pointing right */ 221 DATA('u', ACS_RTEE), /* tee pointing left */ 222 DATA('v', ACS_BTEE), /* tee pointing up */ 223 DATA('w', ACS_TTEE), /* tee pointing down */ 224 DATA('q', ACS_HLINE), /* horizontal line */ 225 DATA('x', ACS_VLINE), /* vertical line */ 226 DATA('n', ACS_PLUS), /* large plus or crossover */ 227 DATA('o', ACS_S1), /* scan line 1 */ 228 DATA('s', ACS_S9), /* scan line 9 */ 229 DATA('`', ACS_DIAMOND), /* diamond */ 230 DATA('a', ACS_CKBOARD), /* checker board (stipple) */ 231 DATA('f', ACS_DEGREE), /* degree symbol */ 232 DATA('g', ACS_PLMINUS), /* plus/minus */ 233 DATA('~', ACS_BULLET), /* bullet */ 234 DATA(',', ACS_LARROW), /* arrow pointing left */ 235 DATA('+', ACS_RARROW), /* arrow pointing right */ 236 DATA('.', ACS_DARROW), /* arrow pointing down */ 237 DATA('-', ACS_UARROW), /* arrow pointing up */ 238 DATA('h', ACS_BOARD), /* board of squares */ 239 DATA('i', ACS_LANTERN), /* lantern symbol */ 240 DATA('0', ACS_BLOCK), /* solid square block */ 241 DATA('p', ACS_S3), /* scan line 3 */ 242 DATA('r', ACS_S7), /* scan line 7 */ 243 DATA('y', ACS_LEQUAL), /* less/equal */ 244 DATA('z', ACS_GEQUAL), /* greater/equal */ 245 DATA('{', ACS_PI), /* Pi */ 246 DATA('|', ACS_NEQUAL), /* not equal */ 247 DATA('}', ACS_STERLING), /* UK pound sign */ 248 }; 249 #undef DATA 250 251 const char *result = 0; 252 253 #if NCURSES_SP_FUNCS 254 (void) sp; 255 #endif 256 if (SP_PARM != 0 && (attr & A_ALTCHARSET) && (acs_chars != 0)) { 257 char *cp; 258 char *found = 0; 259 260 for (cp = acs_chars; cp[0] && cp[1]; cp += 2) { 261 if (ChCharOf(UChar(cp[1])) == ChCharOf(ch)) { 262 found = cp; 263 /* don't exit from loop - there may be redefinitions */ 264 } 265 } 266 267 if (found != 0) { 268 size_t n; 269 270 ch = ChCharOf(UChar(*found)); 271 for (n = 0; n < SIZEOF(names); ++n) { 272 if (names[n].val == ch) { 273 result = names[n].name; 274 break; 275 } 276 } 277 } 278 } 279 return result; 280 } 281 282 NCURSES_EXPORT(char *) 283 _tracechtype2(int bufnum, chtype ch) 284 { 285 char *result = _nc_trace_buf(bufnum, (size_t) BUFSIZ); 286 287 if (result != 0) { 288 const char *found; 289 attr_t attr = ChAttrOf(ch); 290 291 _nc_STRCPY(result, l_brace, TRACE_BUF_SIZE(bufnum)); 292 if ((found = _nc_altcharset_name(attr, ch)) != 0) { 293 (void) _nc_trace_bufcat(bufnum, found); 294 attr &= ~A_ALTCHARSET; 295 } else 296 (void) _nc_trace_bufcat(bufnum, 297 _nc_tracechar(CURRENT_SCREEN, 298 (int) ChCharOf(ch))); 299 300 if (attr != A_NORMAL) { 301 (void) _nc_trace_bufcat(bufnum, " | "); 302 (void) _nc_trace_bufcat(bufnum, 303 _traceattr2(bufnum + 20, attr)); 304 } 305 306 result = _nc_trace_bufcat(bufnum, r_brace); 307 } 308 return result; 309 } 310 311 NCURSES_EXPORT(char *) 312 _tracechtype(chtype ch) 313 { 314 return _tracechtype2(0, ch); 315 } 316 317 /* Trace 'chtype' return-values */ 318 NCURSES_EXPORT(chtype) 319 _nc_retrace_chtype(chtype code) 320 { 321 T((T_RETURN("%s"), _tracechtype(code))); 322 return code; 323 } 324 325 #if USE_WIDEC_SUPPORT 326 NCURSES_EXPORT(char *) 327 _tracecchar_t2(int bufnum, const cchar_t *ch) 328 { 329 char *result = _nc_trace_buf(bufnum, (size_t) BUFSIZ); 330 331 if (result != 0) { 332 _nc_STRCPY(result, l_brace, TRACE_BUF_SIZE(bufnum)); 333 if (ch != 0) { 334 const char *found; 335 attr_t attr = AttrOfD(ch); 336 337 if ((found = _nc_altcharset_name(attr, (chtype) CharOfD(ch))) != 0) { 338 (void) _nc_trace_bufcat(bufnum, found); 339 attr &= ~A_ALTCHARSET; 340 } else if (isWidecExt(CHDEREF(ch))) { 341 (void) _nc_trace_bufcat(bufnum, "{NAC}"); 342 attr &= ~A_CHARTEXT; 343 } else { 344 PUTC_DATA; 345 int n; 346 347 (void) _nc_trace_bufcat(bufnum, "{ "); 348 for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { 349 PUTC_ch = ch->chars[PUTC_i]; 350 if (PUTC_ch == L'\0') { 351 if (PUTC_i == 0) 352 (void) _nc_trace_bufcat(bufnum, "\\000"); 353 break; 354 } 355 PUTC_INIT; 356 PUTC_n = (int) wcrtomb(PUTC_buf, ch->chars[PUTC_i], &PUT_st); 357 if (PUTC_n <= 0) { 358 if (PUTC_ch != L'\0') { 359 /* it could not be a multibyte sequence */ 360 (void) _nc_trace_bufcat(bufnum, 361 _nc_tracechar(CURRENT_SCREEN, 362 UChar(ch->chars[PUTC_i]))); 363 } 364 break; 365 } else if (ch->chars[PUTC_i] > 255) { 366 char temp[80]; 367 _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) 368 "{%d:\\u%lx}", 369 _nc_wacs_width(ch->chars[PUTC_i]), 370 (unsigned long) ch->chars[PUTC_i]); 371 (void) _nc_trace_bufcat(bufnum, temp); 372 break; 373 } 374 for (n = 0; n < PUTC_n; n++) { 375 if (n) 376 (void) _nc_trace_bufcat(bufnum, ", "); 377 (void) _nc_trace_bufcat(bufnum, 378 _nc_tracechar(CURRENT_SCREEN, 379 UChar(PUTC_buf[n]))); 380 } 381 } 382 (void) _nc_trace_bufcat(bufnum, " }"); 383 } 384 if (attr != A_NORMAL) { 385 (void) _nc_trace_bufcat(bufnum, " | "); 386 (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr)); 387 } 388 #if NCURSES_EXT_COLORS 389 /* 390 * Just in case the extended color is different from the chtype 391 * value, trace both. 392 */ 393 if (ch->ext_color != PairNumber(attr)) { 394 char temp[80]; 395 _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) 396 " X_COLOR{%d:%d}", ch->ext_color, PairNumber(attr)); 397 (void) _nc_trace_bufcat(bufnum, temp); 398 } 399 #endif 400 } 401 402 result = _nc_trace_bufcat(bufnum, r_brace); 403 } 404 return result; 405 } 406 407 NCURSES_EXPORT(char *) 408 _tracecchar_t(const cchar_t *ch) 409 { 410 return _tracecchar_t2(0, ch); 411 } 412 #endif 413 414 #else 415 EMPTY_MODULE(_nc_lib_traceatr) 416 #endif /* TRACE */ 417