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