1 /**************************************************************************** 2 * Copyright (c) 2001-2009,2010 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 E. Dickey 1996-on * 31 * and: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 32 * and: Eric S. Raymond <esr@snark.thyrsus.com> * 33 ****************************************************************************/ 34 35 /* 36 * visbuf.c - Tracing/Debugging support routines 37 */ 38 39 #define NEED_NCURSES_CH_T 40 #include <curses.priv.h> 41 42 #include <tic.h> 43 #include <ctype.h> 44 45 MODULE_ID("$Id: visbuf.c,v 1.37 2010/05/29 18:51:41 tom Exp $") 46 47 #define NUM_VISBUFS 4 48 49 #define NormalLen(len) (size_t) (((size_t)(len) + 1) * 4) 50 #define WideLen(len) (size_t) (((size_t)(len) + 1) * 4 * MB_CUR_MAX) 51 52 #ifdef TRACE 53 static const char d_quote[] = StringOf(D_QUOTE); 54 static const char l_brace[] = StringOf(L_BRACE); 55 static const char r_brace[] = StringOf(R_BRACE); 56 #endif 57 58 static char * 59 _nc_vischar(char *tp, unsigned c) 60 { 61 if (c == '"' || c == '\\') { 62 *tp++ = '\\'; 63 *tp++ = (char) c; 64 } else if (is7bits(c) && (isgraph(c) || c == ' ')) { 65 *tp++ = (char) c; 66 } else if (c == '\n') { 67 *tp++ = '\\'; 68 *tp++ = 'n'; 69 } else if (c == '\r') { 70 *tp++ = '\\'; 71 *tp++ = 'r'; 72 } else if (c == '\b') { 73 *tp++ = '\\'; 74 *tp++ = 'b'; 75 } else if (c == '\033') { 76 *tp++ = '\\'; 77 *tp++ = 'e'; 78 } else if (UChar(c) == 0x7f) { 79 *tp++ = '\\'; 80 *tp++ = '^'; 81 *tp++ = '?'; 82 } else if (is7bits(c) && iscntrl(UChar(c))) { 83 *tp++ = '\\'; 84 *tp++ = '^'; 85 *tp++ = (char) ('@' + c); 86 } else { 87 sprintf(tp, "\\%03lo", (unsigned long) ChCharOf(c)); 88 tp += strlen(tp); 89 } 90 *tp = 0; 91 return tp; 92 } 93 94 static const char * 95 _nc_visbuf2n(int bufnum, const char *buf, int len) 96 { 97 const char *vbuf = 0; 98 char *tp; 99 int c; 100 101 if (buf == 0) 102 return ("(null)"); 103 if (buf == CANCELLED_STRING) 104 return ("(cancelled)"); 105 106 if (len < 0) 107 len = (int) strlen(buf); 108 109 #ifdef TRACE 110 vbuf = tp = _nc_trace_buf(bufnum, NormalLen(len)); 111 #else 112 { 113 static char *mybuf[NUM_VISBUFS]; 114 if (bufnum < 0) { 115 for (c = 0; c < NUM_VISBUFS; ++c) { 116 FreeAndNull(mybuf[c]); 117 } 118 tp = 0; 119 } else { 120 mybuf[bufnum] = typeRealloc(char, NormalLen(len), mybuf[bufnum]); 121 vbuf = tp = mybuf[bufnum]; 122 } 123 } 124 #endif 125 if (tp != 0) { 126 *tp++ = D_QUOTE; 127 while ((--len >= 0) && (c = *buf++) != '\0') { 128 tp = _nc_vischar(tp, UChar(c)); 129 } 130 *tp++ = D_QUOTE; 131 *tp = '\0'; 132 } else { 133 vbuf = ("(_nc_visbuf2n failed)"); 134 } 135 return (vbuf); 136 } 137 138 NCURSES_EXPORT(const char *) 139 _nc_visbuf2(int bufnum, const char *buf) 140 { 141 return _nc_visbuf2n(bufnum, buf, -1); 142 } 143 144 NCURSES_EXPORT(const char *) 145 _nc_visbuf(const char *buf) 146 { 147 return _nc_visbuf2(0, buf); 148 } 149 150 NCURSES_EXPORT(const char *) 151 _nc_visbufn(const char *buf, int len) 152 { 153 return _nc_visbuf2n(0, buf, len); 154 } 155 156 #ifdef TRACE 157 #if USE_WIDEC_SUPPORT 158 159 #if defined(USE_TERMLIB) 160 #define _nc_wchstrlen _my_wchstrlen 161 static int 162 _nc_wchstrlen(const cchar_t *s) 163 { 164 int result = 0; 165 while (CharOf(s[result]) != L'\0') { 166 result++; 167 } 168 return result; 169 } 170 #endif 171 172 static const char * 173 _nc_viswbuf2n(int bufnum, const wchar_t *buf, int len) 174 { 175 const char *vbuf; 176 char *tp; 177 wchar_t c; 178 179 if (buf == 0) 180 return ("(null)"); 181 182 if (len < 0) 183 len = (int) wcslen(buf); 184 185 #ifdef TRACE 186 vbuf = tp = _nc_trace_buf(bufnum, WideLen(len)); 187 #else 188 { 189 static char *mybuf[NUM_VISBUFS]; 190 mybuf[bufnum] = typeRealloc(char, WideLen(len), mybuf[bufnum]); 191 vbuf = tp = mybuf[bufnum]; 192 } 193 #endif 194 if (tp != 0) { 195 *tp++ = D_QUOTE; 196 while ((--len >= 0) && (c = *buf++) != '\0') { 197 char temp[CCHARW_MAX + 80]; 198 int j = wctomb(temp, c), k; 199 if (j <= 0) { 200 sprintf(temp, "\\u%08X", (unsigned) c); 201 j = (int) strlen(temp); 202 } 203 for (k = 0; k < j; ++k) { 204 tp = _nc_vischar(tp, UChar(temp[k])); 205 } 206 } 207 *tp++ = D_QUOTE; 208 *tp = '\0'; 209 } else { 210 vbuf = ("(_nc_viswbuf2n failed)"); 211 } 212 return (vbuf); 213 } 214 215 NCURSES_EXPORT(const char *) 216 _nc_viswbuf2(int bufnum, const wchar_t *buf) 217 { 218 return _nc_viswbuf2n(bufnum, buf, -1); 219 } 220 221 NCURSES_EXPORT(const char *) 222 _nc_viswbuf(const wchar_t *buf) 223 { 224 return _nc_viswbuf2(0, buf); 225 } 226 227 NCURSES_EXPORT(const char *) 228 _nc_viswbufn(const wchar_t *buf, int len) 229 { 230 return _nc_viswbuf2n(0, buf, len); 231 } 232 233 /* this special case is used for wget_wstr() */ 234 NCURSES_EXPORT(const char *) 235 _nc_viswibuf(const wint_t *buf) 236 { 237 static wchar_t *mybuf; 238 static unsigned mylen; 239 unsigned n; 240 241 for (n = 0; buf[n] != 0; ++n) { 242 ; /* empty */ 243 } 244 if (mylen < ++n) { 245 mylen = n + 80; 246 if (mybuf != 0) 247 mybuf = typeRealloc(wchar_t, mylen, mybuf); 248 else 249 mybuf = typeMalloc(wchar_t, mylen); 250 } 251 for (n = 0; buf[n] != 0; ++n) { 252 mybuf[n] = (wchar_t) buf[n]; 253 } 254 mybuf[n] = L'\0'; 255 256 return _nc_viswbuf2(0, mybuf); 257 } 258 #endif /* USE_WIDEC_SUPPORT */ 259 260 /* use these functions for displaying parts of a line within a window */ 261 NCURSES_EXPORT(const char *) 262 _nc_viscbuf2(int bufnum, const NCURSES_CH_T * buf, int len) 263 { 264 char *result = _nc_trace_buf(bufnum, BUFSIZ); 265 int first; 266 const char *found; 267 268 if (result != 0) { 269 #if USE_WIDEC_SUPPORT 270 if (len < 0) 271 len = _nc_wchstrlen(buf); 272 #endif /* USE_WIDEC_SUPPORT */ 273 274 /* 275 * Display one or more strings followed by attributes. 276 */ 277 first = 0; 278 while (first < len) { 279 attr_t attr = AttrOf(buf[first]); 280 int last = len - 1; 281 int j; 282 283 for (j = first + 1; j < len; ++j) { 284 if (!SameAttrOf(buf[j], buf[first])) { 285 last = j - 1; 286 break; 287 } 288 } 289 290 (void) _nc_trace_bufcat(bufnum, l_brace); 291 (void) _nc_trace_bufcat(bufnum, d_quote); 292 for (j = first; j <= last; ++j) { 293 found = _nc_altcharset_name(attr, (chtype) CharOf(buf[j])); 294 if (found != 0) { 295 (void) _nc_trace_bufcat(bufnum, found); 296 attr &= ~A_ALTCHARSET; 297 } else 298 #if USE_WIDEC_SUPPORT 299 if (!isWidecExt(buf[j])) { 300 PUTC_DATA; 301 302 PUTC_INIT; 303 for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { 304 int k; 305 306 PUTC_ch = buf[j].chars[PUTC_i]; 307 if (PUTC_ch == L'\0') { 308 if (PUTC_i == 0) 309 (void) _nc_trace_bufcat(bufnum, "\\000"); 310 break; 311 } 312 PUTC_n = (int) wcrtomb(PUTC_buf, 313 buf[j].chars[PUTC_i], &PUT_st); 314 if (PUTC_n <= 0) 315 break; 316 for (k = 0; k < PUTC_n; k++) { 317 char temp[80]; 318 _nc_vischar(temp, UChar(PUTC_buf[k])); 319 (void) _nc_trace_bufcat(bufnum, temp); 320 } 321 } 322 } 323 #else 324 { 325 char temp[80]; 326 _nc_vischar(temp, UChar(buf[j])); 327 result = _nc_trace_bufcat(bufnum, temp); 328 } 329 #endif /* USE_WIDEC_SUPPORT */ 330 } 331 (void) _nc_trace_bufcat(bufnum, d_quote); 332 if (attr != A_NORMAL) { 333 (void) _nc_trace_bufcat(bufnum, " | "); 334 (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr)); 335 } 336 result = _nc_trace_bufcat(bufnum, r_brace); 337 first = last + 1; 338 } 339 } 340 return result; 341 } 342 343 NCURSES_EXPORT(const char *) 344 _nc_viscbuf(const NCURSES_CH_T * buf, int len) 345 { 346 return _nc_viscbuf2(0, buf, len); 347 } 348 #endif /* TRACE */ 349