xref: /openbsd/lib/libcurses/trace/visbuf.c (revision 73471bf0)
1 /* $OpenBSD: visbuf.c,v 1.1 2010/01/12 23:22:07 nicm Exp $ */
2 
3 /****************************************************************************
4  * Copyright (c) 2001-2007,2008 Free Software Foundation, Inc.              *
5  *                                                                          *
6  * Permission is hereby granted, free of charge, to any person obtaining a  *
7  * copy of this software and associated documentation files (the            *
8  * "Software"), to deal in the Software without restriction, including      *
9  * without limitation the rights to use, copy, modify, merge, publish,      *
10  * distribute, distribute with modifications, sublicense, and/or sell       *
11  * copies of the Software, and to permit persons to whom the Software is    *
12  * furnished to do so, subject to the following conditions:                 *
13  *                                                                          *
14  * The above copyright notice and this permission notice shall be included  *
15  * in all copies or substantial portions of the Software.                   *
16  *                                                                          *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
20  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
23  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
24  *                                                                          *
25  * Except as contained in this notice, the name(s) of the above copyright   *
26  * holders shall not be used in advertising or otherwise to promote the     *
27  * sale, use or other dealings in this Software without prior written       *
28  * authorization.                                                           *
29  ****************************************************************************/
30 
31 /****************************************************************************
32  *  Author: Thomas E. Dickey                        1996-on                 *
33  *     and: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
34  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
35  ****************************************************************************/
36 
37 /*
38  *	visbuf.c - Tracing/Debugging support routines
39  */
40 
41 #define NEED_NCURSES_CH_T
42 #include <curses.priv.h>
43 
44 #include <tic.h>
45 #include <ctype.h>
46 
47 MODULE_ID("$Id: visbuf.c,v 1.1 2010/01/12 23:22:07 nicm Exp $")
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, size_t tl, 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 	snprintf(tp, tl, "\\%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;
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[4];
114 	mybuf[bufnum] = typeRealloc(char, NormalLen(len), mybuf[bufnum]);
115 	vbuf = tp = mybuf[bufnum];
116     }
117 #endif
118     if (tp != 0) {
119 	*tp++ = D_QUOTE;
120 	while ((--len >= 0) && (c = *buf++) != '\0') {
121 	    tp = _nc_vischar(tp, NormalLen(len) - (tp - vbuf), UChar(c));
122 	}
123 	*tp++ = D_QUOTE;
124 	*tp++ = '\0';
125     } else {
126 	vbuf = ("(_nc_visbuf2n failed)");
127     }
128     return (vbuf);
129 }
130 
131 NCURSES_EXPORT(const char *)
132 _nc_visbuf2(int bufnum, const char *buf)
133 {
134     return _nc_visbuf2n(bufnum, buf, -1);
135 }
136 
137 NCURSES_EXPORT(const char *)
138 _nc_visbuf(const char *buf)
139 {
140     return _nc_visbuf2(0, buf);
141 }
142 
143 NCURSES_EXPORT(const char *)
144 _nc_visbufn(const char *buf, int len)
145 {
146     return _nc_visbuf2n(0, buf, len);
147 }
148 
149 #ifdef TRACE
150 #if USE_WIDEC_SUPPORT
151 
152 #if defined(USE_TERMLIB)
153 #define _nc_wchstrlen _my_wchstrlen
154 static int
155 _nc_wchstrlen(const cchar_t *s)
156 {
157     int result = 0;
158     while (CharOf(s[result]) != L'\0') {
159 	result++;
160     }
161     return result;
162 }
163 #endif
164 
165 static const char *
166 _nc_viswbuf2n(int bufnum, const wchar_t *buf, int len)
167 {
168     const char *vbuf;
169     char *tp;
170     wchar_t c;
171 
172     if (buf == 0)
173 	return ("(null)");
174 
175     if (len < 0)
176 	len = (int) wcslen(buf);
177 
178 #ifdef TRACE
179     vbuf = tp = _nc_trace_buf(bufnum, WideLen(len));
180 #else
181     {
182 	static char *mybuf[2];
183 	mybuf[bufnum] = typeRealloc(char, WideLen(len), mybuf[bufnum]);
184 	vbuf = tp = mybuf[bufnum];
185     }
186 #endif
187     if (tp != 0) {
188 	*tp++ = D_QUOTE;
189 	while ((--len >= 0) && (c = *buf++) != '\0') {
190 	    char temp[CCHARW_MAX + 80];
191 	    int j = wctomb(temp, c), k;
192 	    if (j <= 0) {
193 		snprintf(temp, sizeof temp, "\\u%08X", (unsigned) c);
194 		j = (int) strlen(temp);
195 	    }
196 	    for (k = 0; k < j; ++k) {
197 		tp = _nc_vischar(tp, WideLen(len) - (tp - vbuf), UChar(temp[k]));
198 	    }
199 	}
200 	*tp++ = D_QUOTE;
201 	*tp++ = '\0';
202     } else {
203 	vbuf = ("(_nc_viswbuf2n failed)");
204     }
205     return (vbuf);
206 }
207 
208 NCURSES_EXPORT(const char *)
209 _nc_viswbuf2(int bufnum, const wchar_t *buf)
210 {
211     return _nc_viswbuf2n(bufnum, buf, -1);
212 }
213 
214 NCURSES_EXPORT(const char *)
215 _nc_viswbuf(const wchar_t *buf)
216 {
217     return _nc_viswbuf2(0, buf);
218 }
219 
220 NCURSES_EXPORT(const char *)
221 _nc_viswbufn(const wchar_t *buf, int len)
222 {
223     return _nc_viswbuf2n(0, buf, len);
224 }
225 
226 /* this special case is used for wget_wstr() */
227 NCURSES_EXPORT(const char *)
228 _nc_viswibuf(const wint_t *buf)
229 {
230     static wchar_t *mybuf;
231     static unsigned mylen;
232     unsigned n;
233 
234     for (n = 0; buf[n] != 0; ++n) ;
235     if (mylen < ++n) {
236 	mylen = n + 80;
237 	if (mybuf != 0)
238 	    mybuf = typeRealloc(wchar_t, mylen, mybuf);
239 	else
240 	    mybuf = typeMalloc(wchar_t, mylen);
241     }
242     for (n = 0; buf[n] != 0; ++n)
243 	mybuf[n] = (wchar_t) buf[n];
244 
245     return _nc_viswbuf2(0, mybuf);
246 }
247 #endif /* USE_WIDEC_SUPPORT */
248 
249 /* use these functions for displaying parts of a line within a window */
250 NCURSES_EXPORT(const char *)
251 _nc_viscbuf2(int bufnum, const NCURSES_CH_T * buf, int len)
252 {
253     char *result = _nc_trace_buf(bufnum, BUFSIZ);
254     int first;
255     const char *found;
256 
257     if (result != 0) {
258 #if USE_WIDEC_SUPPORT
259 	if (len < 0)
260 	    len = _nc_wchstrlen(buf);
261 #endif /* USE_WIDEC_SUPPORT */
262 
263 	/*
264 	 * Display one or more strings followed by attributes.
265 	 */
266 	first = 0;
267 	while (first < len) {
268 	    attr_t attr = AttrOf(buf[first]);
269 	    int last = len - 1;
270 	    int j;
271 
272 	    for (j = first + 1; j < len; ++j) {
273 		if (!SameAttrOf(buf[j], buf[first])) {
274 		    last = j - 1;
275 		    break;
276 		}
277 	    }
278 
279 	    result = _nc_trace_bufcat(bufnum, l_brace);
280 	    result = _nc_trace_bufcat(bufnum, d_quote);
281 	    for (j = first; j <= last; ++j) {
282 		found = _nc_altcharset_name(attr, (chtype) CharOf(buf[j]));
283 		if (found != 0) {
284 		    result = _nc_trace_bufcat(bufnum, found);
285 		    attr &= ~A_ALTCHARSET;
286 		} else
287 #if USE_WIDEC_SUPPORT
288 		if (!isWidecExt(buf[j])) {
289 		    PUTC_DATA;
290 
291 		    PUTC_INIT;
292 		    for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) {
293 			int k;
294 
295 			PUTC_ch = buf[j].chars[PUTC_i];
296 			if (PUTC_ch == L'\0')
297 			    break;
298 			PUTC_n = (int) wcrtomb(PUTC_buf, buf[j].chars[PUTC_i], &PUT_st);
299 			if (PUTC_n <= 0)
300 			    break;
301 			for (k = 0; k < PUTC_n; k++) {
302 			    char temp[80];
303 			    _nc_vischar(temp, sizeof(temp), UChar(PUTC_buf[k]));
304 			    result = _nc_trace_bufcat(bufnum, temp);
305 			}
306 		    }
307 		}
308 #else
309 		{
310 		    char temp[80];
311 		    _nc_vischar(temp, sizeof(temp), UChar(buf[j]));
312 		    result = _nc_trace_bufcat(bufnum, temp);
313 		}
314 #endif /* USE_WIDEC_SUPPORT */
315 	    }
316 	    result = _nc_trace_bufcat(bufnum, d_quote);
317 	    if (attr != A_NORMAL) {
318 		result = _nc_trace_bufcat(bufnum, " | ");
319 		result = _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr));
320 	    }
321 	    result = _nc_trace_bufcat(bufnum, r_brace);
322 	    first = last + 1;
323 	}
324     }
325     return result;
326 }
327 
328 NCURSES_EXPORT(const char *)
329 _nc_viscbuf(const NCURSES_CH_T * buf, int len)
330 {
331     return _nc_viscbuf2(0, buf, len);
332 }
333 #endif /* TRACE */
334