xref: /openbsd-src/lib/libcurses/trace/visbuf.c (revision c7ef0cfc17afcba97172c25e1e3a943e893bc632)
1*c7ef0cfcSnicm /* $OpenBSD: visbuf.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */
281d8c4e1Snicm 
381d8c4e1Snicm /****************************************************************************
4*c7ef0cfcSnicm  * Copyright 2019-2021,2023 Thomas E. Dickey                                *
5*c7ef0cfcSnicm  * Copyright 2001-2016,2017 Free Software Foundation, Inc.                  *
681d8c4e1Snicm  *                                                                          *
781d8c4e1Snicm  * Permission is hereby granted, free of charge, to any person obtaining a  *
881d8c4e1Snicm  * copy of this software and associated documentation files (the            *
981d8c4e1Snicm  * "Software"), to deal in the Software without restriction, including      *
1081d8c4e1Snicm  * without limitation the rights to use, copy, modify, merge, publish,      *
1181d8c4e1Snicm  * distribute, distribute with modifications, sublicense, and/or sell       *
1281d8c4e1Snicm  * copies of the Software, and to permit persons to whom the Software is    *
1381d8c4e1Snicm  * furnished to do so, subject to the following conditions:                 *
1481d8c4e1Snicm  *                                                                          *
1581d8c4e1Snicm  * The above copyright notice and this permission notice shall be included  *
1681d8c4e1Snicm  * in all copies or substantial portions of the Software.                   *
1781d8c4e1Snicm  *                                                                          *
1881d8c4e1Snicm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
1981d8c4e1Snicm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
2081d8c4e1Snicm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
2181d8c4e1Snicm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
2281d8c4e1Snicm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
2381d8c4e1Snicm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
2481d8c4e1Snicm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
2581d8c4e1Snicm  *                                                                          *
2681d8c4e1Snicm  * Except as contained in this notice, the name(s) of the above copyright   *
2781d8c4e1Snicm  * holders shall not be used in advertising or otherwise to promote the     *
2881d8c4e1Snicm  * sale, use or other dealings in this Software without prior written       *
2981d8c4e1Snicm  * authorization.                                                           *
3081d8c4e1Snicm  ****************************************************************************/
3181d8c4e1Snicm 
3281d8c4e1Snicm /****************************************************************************
3381d8c4e1Snicm  *  Author: Thomas E. Dickey                        1996-on                 *
3481d8c4e1Snicm  *     and: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
3581d8c4e1Snicm  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
3681d8c4e1Snicm  ****************************************************************************/
3781d8c4e1Snicm 
3881d8c4e1Snicm /*
3981d8c4e1Snicm  *	visbuf.c - Tracing/Debugging support routines
4081d8c4e1Snicm  */
4181d8c4e1Snicm 
4281d8c4e1Snicm #define NEED_NCURSES_CH_T
4381d8c4e1Snicm #include <curses.priv.h>
4481d8c4e1Snicm 
4581d8c4e1Snicm #include <tic.h>
4681d8c4e1Snicm #include <ctype.h>
4781d8c4e1Snicm 
48*c7ef0cfcSnicm MODULE_ID("$Id: visbuf.c,v 1.2 2023/10/17 09:52:09 nicm Exp $")
49*c7ef0cfcSnicm 
50*c7ef0cfcSnicm #define NUM_VISBUFS 4
5181d8c4e1Snicm 
5281d8c4e1Snicm #define NormalLen(len) (size_t) (((size_t)(len) + 1) * 4)
53*c7ef0cfcSnicm #define WideLen(len)   (size_t) (((size_t)(len) + 1) * 4 * (size_t) MB_CUR_MAX)
5481d8c4e1Snicm 
5581d8c4e1Snicm #ifdef TRACE
5681d8c4e1Snicm static const char d_quote[] = StringOf(D_QUOTE);
5781d8c4e1Snicm static const char l_brace[] = StringOf(L_BRACE);
5881d8c4e1Snicm static const char r_brace[] = StringOf(R_BRACE);
5981d8c4e1Snicm #endif
6081d8c4e1Snicm 
61*c7ef0cfcSnicm #if USE_STRING_HACKS && HAVE_SNPRINTF
62*c7ef0cfcSnicm #define VisChar(tp, chr, limit) _nc_vischar(tp, chr, limit)
63*c7ef0cfcSnicm #define LIMIT_ARG ,size_t limit
64*c7ef0cfcSnicm #else
65*c7ef0cfcSnicm #define VisChar(tp, chr, limit) _nc_vischar(tp, chr)
66*c7ef0cfcSnicm #define LIMIT_ARG		/* nothing */
67*c7ef0cfcSnicm #endif
68*c7ef0cfcSnicm 
6981d8c4e1Snicm static char *
_nc_vischar(char * tp,unsigned c LIMIT_ARG)70*c7ef0cfcSnicm _nc_vischar(char *tp, unsigned c LIMIT_ARG)
7181d8c4e1Snicm {
72*c7ef0cfcSnicm     if (tp == NULL) {
73*c7ef0cfcSnicm 	return NULL;
74*c7ef0cfcSnicm     } else if (c == '"' || c == '\\') {
7581d8c4e1Snicm 	*tp++ = '\\';
7681d8c4e1Snicm 	*tp++ = (char) c;
77*c7ef0cfcSnicm     } else if (is7bits((int) c) && (isgraph((int) c) || c == ' ')) {
7881d8c4e1Snicm 	*tp++ = (char) c;
7981d8c4e1Snicm     } else if (c == '\n') {
8081d8c4e1Snicm 	*tp++ = '\\';
8181d8c4e1Snicm 	*tp++ = 'n';
8281d8c4e1Snicm     } else if (c == '\r') {
8381d8c4e1Snicm 	*tp++ = '\\';
8481d8c4e1Snicm 	*tp++ = 'r';
8581d8c4e1Snicm     } else if (c == '\b') {
8681d8c4e1Snicm 	*tp++ = '\\';
8781d8c4e1Snicm 	*tp++ = 'b';
88*c7ef0cfcSnicm     } else if (c == '\t') {
89*c7ef0cfcSnicm 	*tp++ = '\\';
90*c7ef0cfcSnicm 	*tp++ = 't';
9181d8c4e1Snicm     } else if (c == '\033') {
9281d8c4e1Snicm 	*tp++ = '\\';
9381d8c4e1Snicm 	*tp++ = 'e';
9481d8c4e1Snicm     } else if (UChar(c) == 0x7f) {
9581d8c4e1Snicm 	*tp++ = '\\';
9681d8c4e1Snicm 	*tp++ = '^';
9781d8c4e1Snicm 	*tp++ = '?';
9881d8c4e1Snicm     } else if (is7bits(c) && iscntrl(UChar(c))) {
9981d8c4e1Snicm 	*tp++ = '\\';
10081d8c4e1Snicm 	*tp++ = '^';
10181d8c4e1Snicm 	*tp++ = (char) ('@' + c);
10281d8c4e1Snicm     } else {
103*c7ef0cfcSnicm 	_nc_SPRINTF(tp, _nc_SLIMIT(limit)
104*c7ef0cfcSnicm 		    "\\%03lo", (unsigned long) ChCharOf(c));
10581d8c4e1Snicm 	tp += strlen(tp);
10681d8c4e1Snicm     }
10781d8c4e1Snicm     *tp = 0;
10881d8c4e1Snicm     return tp;
10981d8c4e1Snicm }
11081d8c4e1Snicm 
11181d8c4e1Snicm static const char *
_nc_visbuf2n(int bufnum,const char * buf,int len)11281d8c4e1Snicm _nc_visbuf2n(int bufnum, const char *buf, int len)
11381d8c4e1Snicm {
114*c7ef0cfcSnicm     const char *vbuf = 0;
11581d8c4e1Snicm     char *tp;
116*c7ef0cfcSnicm     int count;
11781d8c4e1Snicm 
11881d8c4e1Snicm     if (buf == 0)
11981d8c4e1Snicm 	return ("(null)");
12081d8c4e1Snicm     if (buf == CANCELLED_STRING)
12181d8c4e1Snicm 	return ("(cancelled)");
12281d8c4e1Snicm 
12381d8c4e1Snicm     if (len < 0)
12481d8c4e1Snicm 	len = (int) strlen(buf);
12581d8c4e1Snicm 
126*c7ef0cfcSnicm     count = len;
12781d8c4e1Snicm #ifdef TRACE
12881d8c4e1Snicm     vbuf = tp = _nc_trace_buf(bufnum, NormalLen(len));
12981d8c4e1Snicm #else
13081d8c4e1Snicm     {
131*c7ef0cfcSnicm 	static char *mybuf[NUM_VISBUFS];
132*c7ef0cfcSnicm 	int c;
133*c7ef0cfcSnicm 
134*c7ef0cfcSnicm 	if (bufnum < 0) {
135*c7ef0cfcSnicm 	    for (c = 0; c < NUM_VISBUFS; ++c) {
136*c7ef0cfcSnicm 		FreeAndNull(mybuf[c]);
137*c7ef0cfcSnicm 	    }
138*c7ef0cfcSnicm 	    tp = 0;
139*c7ef0cfcSnicm 	} else {
14081d8c4e1Snicm 	    mybuf[bufnum] = typeRealloc(char, NormalLen(len), mybuf[bufnum]);
14181d8c4e1Snicm 	    vbuf = tp = mybuf[bufnum];
14281d8c4e1Snicm 	}
143*c7ef0cfcSnicm     }
14481d8c4e1Snicm #endif
14581d8c4e1Snicm     if (tp != 0) {
146*c7ef0cfcSnicm 	int c;
147*c7ef0cfcSnicm 
14881d8c4e1Snicm 	*tp++ = D_QUOTE;
149*c7ef0cfcSnicm 	while ((--count >= 0) && (c = *buf++) != '\0') {
150*c7ef0cfcSnicm 	    tp = VisChar(tp, UChar(c), NormalLen(len));
15181d8c4e1Snicm 	}
15281d8c4e1Snicm 	*tp++ = D_QUOTE;
153*c7ef0cfcSnicm 	*tp = '\0';
15481d8c4e1Snicm     } else {
15581d8c4e1Snicm 	vbuf = ("(_nc_visbuf2n failed)");
15681d8c4e1Snicm     }
15781d8c4e1Snicm     return (vbuf);
15881d8c4e1Snicm }
15981d8c4e1Snicm 
16081d8c4e1Snicm NCURSES_EXPORT(const char *)
_nc_visbuf2(int bufnum,const char * buf)16181d8c4e1Snicm _nc_visbuf2(int bufnum, const char *buf)
16281d8c4e1Snicm {
16381d8c4e1Snicm     return _nc_visbuf2n(bufnum, buf, -1);
16481d8c4e1Snicm }
16581d8c4e1Snicm 
16681d8c4e1Snicm NCURSES_EXPORT(const char *)
_nc_visbuf(const char * buf)16781d8c4e1Snicm _nc_visbuf(const char *buf)
16881d8c4e1Snicm {
16981d8c4e1Snicm     return _nc_visbuf2(0, buf);
17081d8c4e1Snicm }
17181d8c4e1Snicm 
17281d8c4e1Snicm NCURSES_EXPORT(const char *)
_nc_visbufn(const char * buf,int len)17381d8c4e1Snicm _nc_visbufn(const char *buf, int len)
17481d8c4e1Snicm {
17581d8c4e1Snicm     return _nc_visbuf2n(0, buf, len);
17681d8c4e1Snicm }
17781d8c4e1Snicm 
17881d8c4e1Snicm #ifdef TRACE
17981d8c4e1Snicm #if USE_WIDEC_SUPPORT
18081d8c4e1Snicm 
18181d8c4e1Snicm #if defined(USE_TERMLIB)
18281d8c4e1Snicm #define _nc_wchstrlen _my_wchstrlen
18381d8c4e1Snicm static int
_nc_wchstrlen(const cchar_t * s)18481d8c4e1Snicm _nc_wchstrlen(const cchar_t *s)
18581d8c4e1Snicm {
18681d8c4e1Snicm     int result = 0;
18781d8c4e1Snicm     while (CharOf(s[result]) != L'\0') {
18881d8c4e1Snicm 	result++;
18981d8c4e1Snicm     }
19081d8c4e1Snicm     return result;
19181d8c4e1Snicm }
19281d8c4e1Snicm #endif
19381d8c4e1Snicm 
19481d8c4e1Snicm static const char *
_nc_viswbuf2n(int bufnum,const wchar_t * buf,int len)19581d8c4e1Snicm _nc_viswbuf2n(int bufnum, const wchar_t *buf, int len)
19681d8c4e1Snicm {
19781d8c4e1Snicm     const char *vbuf;
19881d8c4e1Snicm     char *tp;
199*c7ef0cfcSnicm     int count;
20081d8c4e1Snicm 
20181d8c4e1Snicm     if (buf == 0)
20281d8c4e1Snicm 	return ("(null)");
20381d8c4e1Snicm 
20481d8c4e1Snicm     if (len < 0)
20581d8c4e1Snicm 	len = (int) wcslen(buf);
20681d8c4e1Snicm 
207*c7ef0cfcSnicm     count = len;
20881d8c4e1Snicm #ifdef TRACE
20981d8c4e1Snicm     vbuf = tp = _nc_trace_buf(bufnum, WideLen(len));
21081d8c4e1Snicm #else
21181d8c4e1Snicm     {
212*c7ef0cfcSnicm 	static char *mybuf[NUM_VISBUFS];
21381d8c4e1Snicm 	mybuf[bufnum] = typeRealloc(char, WideLen(len), mybuf[bufnum]);
21481d8c4e1Snicm 	vbuf = tp = mybuf[bufnum];
21581d8c4e1Snicm     }
21681d8c4e1Snicm #endif
21781d8c4e1Snicm     if (tp != 0) {
218*c7ef0cfcSnicm 	wchar_t c;
219*c7ef0cfcSnicm 
22081d8c4e1Snicm 	*tp++ = D_QUOTE;
221*c7ef0cfcSnicm 	while ((--count >= 0) && (c = *buf++) != '\0') {
22281d8c4e1Snicm 	    char temp[CCHARW_MAX + 80];
22381d8c4e1Snicm 	    int j = wctomb(temp, c), k;
22481d8c4e1Snicm 	    if (j <= 0) {
225*c7ef0cfcSnicm 		_nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
226*c7ef0cfcSnicm 			    "\\u%08X", (unsigned) c);
22781d8c4e1Snicm 		j = (int) strlen(temp);
22881d8c4e1Snicm 	    }
22981d8c4e1Snicm 	    for (k = 0; k < j; ++k) {
230*c7ef0cfcSnicm 		tp = VisChar(tp, UChar(temp[k]), WideLen(len));
23181d8c4e1Snicm 	    }
23281d8c4e1Snicm 	}
23381d8c4e1Snicm 	*tp++ = D_QUOTE;
234*c7ef0cfcSnicm 	*tp = '\0';
23581d8c4e1Snicm     } else {
23681d8c4e1Snicm 	vbuf = ("(_nc_viswbuf2n failed)");
23781d8c4e1Snicm     }
23881d8c4e1Snicm     return (vbuf);
23981d8c4e1Snicm }
24081d8c4e1Snicm 
24181d8c4e1Snicm NCURSES_EXPORT(const char *)
_nc_viswbuf2(int bufnum,const wchar_t * buf)24281d8c4e1Snicm _nc_viswbuf2(int bufnum, const wchar_t *buf)
24381d8c4e1Snicm {
24481d8c4e1Snicm     return _nc_viswbuf2n(bufnum, buf, -1);
24581d8c4e1Snicm }
24681d8c4e1Snicm 
24781d8c4e1Snicm NCURSES_EXPORT(const char *)
_nc_viswbuf(const wchar_t * buf)24881d8c4e1Snicm _nc_viswbuf(const wchar_t *buf)
24981d8c4e1Snicm {
25081d8c4e1Snicm     return _nc_viswbuf2(0, buf);
25181d8c4e1Snicm }
25281d8c4e1Snicm 
25381d8c4e1Snicm NCURSES_EXPORT(const char *)
_nc_viswbufn(const wchar_t * buf,int len)25481d8c4e1Snicm _nc_viswbufn(const wchar_t *buf, int len)
25581d8c4e1Snicm {
25681d8c4e1Snicm     return _nc_viswbuf2n(0, buf, len);
25781d8c4e1Snicm }
25881d8c4e1Snicm 
25981d8c4e1Snicm /* this special case is used for wget_wstr() */
26081d8c4e1Snicm NCURSES_EXPORT(const char *)
_nc_viswibuf(const wint_t * buf)26181d8c4e1Snicm _nc_viswibuf(const wint_t *buf)
26281d8c4e1Snicm {
26381d8c4e1Snicm     static wchar_t *mybuf;
26481d8c4e1Snicm     static unsigned mylen;
26581d8c4e1Snicm     unsigned n;
26681d8c4e1Snicm 
267*c7ef0cfcSnicm     for (n = 0; buf[n] != 0; ++n) {
268*c7ef0cfcSnicm 	;			/* empty */
269*c7ef0cfcSnicm     }
27081d8c4e1Snicm     if (mylen < ++n) {
27181d8c4e1Snicm 	mylen = n + 80;
27281d8c4e1Snicm 	if (mybuf != 0)
27381d8c4e1Snicm 	    mybuf = typeRealloc(wchar_t, mylen, mybuf);
27481d8c4e1Snicm 	else
27581d8c4e1Snicm 	    mybuf = typeMalloc(wchar_t, mylen);
27681d8c4e1Snicm     }
277*c7ef0cfcSnicm     if (mybuf != 0) {
278*c7ef0cfcSnicm 	for (n = 0; buf[n] != 0; ++n) {
27981d8c4e1Snicm 	    mybuf[n] = (wchar_t) buf[n];
280*c7ef0cfcSnicm 	}
281*c7ef0cfcSnicm 	mybuf[n] = L'\0';
282*c7ef0cfcSnicm     }
28381d8c4e1Snicm 
28481d8c4e1Snicm     return _nc_viswbuf2(0, mybuf);
28581d8c4e1Snicm }
28681d8c4e1Snicm #endif /* USE_WIDEC_SUPPORT */
28781d8c4e1Snicm 
28881d8c4e1Snicm /* use these functions for displaying parts of a line within a window */
28981d8c4e1Snicm NCURSES_EXPORT(const char *)
_nc_viscbuf2(int bufnum,const NCURSES_CH_T * buf,int len)29081d8c4e1Snicm _nc_viscbuf2(int bufnum, const NCURSES_CH_T *buf, int len)
29181d8c4e1Snicm {
292*c7ef0cfcSnicm     char *result = _nc_trace_buf(bufnum, (size_t) BUFSIZ);
29381d8c4e1Snicm 
29481d8c4e1Snicm     if (result != 0) {
295*c7ef0cfcSnicm 	int first = 0;
296*c7ef0cfcSnicm 
29781d8c4e1Snicm #if USE_WIDEC_SUPPORT
29881d8c4e1Snicm 	if (len < 0)
29981d8c4e1Snicm 	    len = _nc_wchstrlen(buf);
30081d8c4e1Snicm #endif /* USE_WIDEC_SUPPORT */
30181d8c4e1Snicm 
30281d8c4e1Snicm 	/*
30381d8c4e1Snicm 	 * Display one or more strings followed by attributes.
30481d8c4e1Snicm 	 */
30581d8c4e1Snicm 	while (first < len) {
30681d8c4e1Snicm 	    attr_t attr = AttrOf(buf[first]);
30781d8c4e1Snicm 	    int last = len - 1;
30881d8c4e1Snicm 	    int j;
30981d8c4e1Snicm 
31081d8c4e1Snicm 	    for (j = first + 1; j < len; ++j) {
31181d8c4e1Snicm 		if (!SameAttrOf(buf[j], buf[first])) {
31281d8c4e1Snicm 		    last = j - 1;
31381d8c4e1Snicm 		    break;
31481d8c4e1Snicm 		}
31581d8c4e1Snicm 	    }
31681d8c4e1Snicm 
317*c7ef0cfcSnicm 	    (void) _nc_trace_bufcat(bufnum, l_brace);
318*c7ef0cfcSnicm 	    (void) _nc_trace_bufcat(bufnum, d_quote);
31981d8c4e1Snicm 	    for (j = first; j <= last; ++j) {
320*c7ef0cfcSnicm 		const char *found = _nc_altcharset_name(attr, (chtype)
321*c7ef0cfcSnicm 							CharOf(buf[j]));
32281d8c4e1Snicm 		if (found != 0) {
323*c7ef0cfcSnicm 		    (void) _nc_trace_bufcat(bufnum, found);
32481d8c4e1Snicm 		    attr &= ~A_ALTCHARSET;
32581d8c4e1Snicm 		} else
32681d8c4e1Snicm #if USE_WIDEC_SUPPORT
32781d8c4e1Snicm 		if (!isWidecExt(buf[j])) {
32881d8c4e1Snicm 		    PUTC_DATA;
32981d8c4e1Snicm 
33081d8c4e1Snicm 		    for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) {
33181d8c4e1Snicm 			int k;
332*c7ef0cfcSnicm 			char temp[80];
33381d8c4e1Snicm 
33481d8c4e1Snicm 			PUTC_ch = buf[j].chars[PUTC_i];
335*c7ef0cfcSnicm 			if (PUTC_ch == L'\0') {
336*c7ef0cfcSnicm 			    if (PUTC_i == 0)
337*c7ef0cfcSnicm 				(void) _nc_trace_bufcat(bufnum, "\\000");
33881d8c4e1Snicm 			    break;
339*c7ef0cfcSnicm 			}
340*c7ef0cfcSnicm 			PUTC_INIT;
341*c7ef0cfcSnicm 			PUTC_n = (int) wcrtomb(PUTC_buf,
342*c7ef0cfcSnicm 					       buf[j].chars[PUTC_i], &PUT_st);
343*c7ef0cfcSnicm 			if (PUTC_n <= 0 || buf[j].chars[PUTC_i] > 255) {
344*c7ef0cfcSnicm 			    _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
345*c7ef0cfcSnicm 					"{%d:\\u%lx}",
346*c7ef0cfcSnicm 					_nc_wacs_width(buf[j].chars[PUTC_i]),
347*c7ef0cfcSnicm 					(unsigned long) buf[j].chars[PUTC_i]);
348*c7ef0cfcSnicm 			    (void) _nc_trace_bufcat(bufnum, temp);
34981d8c4e1Snicm 			    break;
350*c7ef0cfcSnicm 			}
35181d8c4e1Snicm 			for (k = 0; k < PUTC_n; k++) {
352*c7ef0cfcSnicm 			    VisChar(temp, UChar(PUTC_buf[k]), sizeof(temp));
353*c7ef0cfcSnicm 			    (void) _nc_trace_bufcat(bufnum, temp);
35481d8c4e1Snicm 			}
35581d8c4e1Snicm 		    }
35681d8c4e1Snicm 		}
35781d8c4e1Snicm #else
35881d8c4e1Snicm 		{
35981d8c4e1Snicm 		    char temp[80];
360*c7ef0cfcSnicm 		    VisChar(temp, UChar(buf[j]), sizeof(temp));
361*c7ef0cfcSnicm 		    (void) _nc_trace_bufcat(bufnum, temp);
36281d8c4e1Snicm 		}
36381d8c4e1Snicm #endif /* USE_WIDEC_SUPPORT */
36481d8c4e1Snicm 	    }
365*c7ef0cfcSnicm 	    (void) _nc_trace_bufcat(bufnum, d_quote);
36681d8c4e1Snicm 	    if (attr != A_NORMAL) {
367*c7ef0cfcSnicm 		(void) _nc_trace_bufcat(bufnum, " | ");
368*c7ef0cfcSnicm 		(void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr));
36981d8c4e1Snicm 	    }
37081d8c4e1Snicm 	    result = _nc_trace_bufcat(bufnum, r_brace);
37181d8c4e1Snicm 	    first = last + 1;
37281d8c4e1Snicm 	}
37381d8c4e1Snicm     }
37481d8c4e1Snicm     return result;
37581d8c4e1Snicm }
37681d8c4e1Snicm 
37781d8c4e1Snicm NCURSES_EXPORT(const char *)
_nc_viscbuf(const NCURSES_CH_T * buf,int len)37881d8c4e1Snicm _nc_viscbuf(const NCURSES_CH_T *buf, int len)
37981d8c4e1Snicm {
38081d8c4e1Snicm     return _nc_viscbuf2(0, buf, len);
38181d8c4e1Snicm }
38281d8c4e1Snicm #endif /* TRACE */
383