566e75454cf5e7c2e0f1dd211f00e383b665a523
[ncurses.git] / ncurses / trace / lib_traceatr.c
1 /****************************************************************************
2  * Copyright (c) 1998-2007,2008 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  ****************************************************************************/
34
35 /*
36  *      lib_traceatr.c - Tracing/Debugging routines (attributes)
37  */
38
39 #include <curses.priv.h>
40 #include <term.h>               /* acs_chars */
41
42 MODULE_ID("$Id: lib_traceatr.c,v 1.60 2008/05/31 16:53:15 tom Exp $")
43
44 #define COLOR_OF(c) ((c < 0) ? "default" : (c > 7 ? color_of(c) : colors[c].name))
45
46 #ifdef TRACE
47
48 static const char l_brace[] = StringOf(L_BRACE);
49 static const char r_brace[] = StringOf(R_BRACE);
50
51 #ifndef USE_TERMLIB
52
53 #define my_buffer _nc_globals.traceatr_color_buf
54 #define my_select _nc_globals.traceatr_color_sel
55 #define my_cached _nc_globals.traceatr_color_last
56
57 static char *
58 color_of(int c)
59 {
60     if (c != my_cached) {
61         my_cached = c;
62         my_select = !my_select;
63         if (c == COLOR_DEFAULT)
64             strcpy(my_buffer[my_select], "default");
65         else
66             sprintf(my_buffer[my_select], "color%d", c);
67     }
68     return my_buffer[my_select];
69 }
70
71 #undef my_buffer
72 #undef my_select
73 #endif /* !USE_TERMLIB */
74
75 NCURSES_EXPORT(char *)
76 _traceattr2(int bufnum, chtype newmode)
77 {
78     char *buf = _nc_trace_buf(bufnum, BUFSIZ);
79     char temp[80];
80     static const struct {
81         unsigned int val;
82         const char *name;
83     } names[] =
84     {
85         /* *INDENT-OFF* */
86         { A_STANDOUT,           "A_STANDOUT" },
87         { A_UNDERLINE,          "A_UNDERLINE" },
88         { A_REVERSE,            "A_REVERSE" },
89         { A_BLINK,              "A_BLINK" },
90         { A_DIM,                "A_DIM" },
91         { A_BOLD,               "A_BOLD" },
92         { A_ALTCHARSET,         "A_ALTCHARSET" },
93         { A_INVIS,              "A_INVIS" },
94         { A_PROTECT,            "A_PROTECT" },
95         { A_CHARTEXT,           "A_CHARTEXT" },
96         { A_NORMAL,             "A_NORMAL" },
97         { A_COLOR,              "A_COLOR" },
98         /* *INDENT-ON* */
99
100     }
101 #ifndef USE_TERMLIB
102     ,
103         colors[] =
104     {
105         /* *INDENT-OFF* */
106         { COLOR_BLACK,          "COLOR_BLACK" },
107         { COLOR_RED,            "COLOR_RED" },
108         { COLOR_GREEN,          "COLOR_GREEN" },
109         { COLOR_YELLOW,         "COLOR_YELLOW" },
110         { COLOR_BLUE,           "COLOR_BLUE" },
111         { COLOR_MAGENTA,        "COLOR_MAGENTA" },
112         { COLOR_CYAN,           "COLOR_CYAN" },
113         { COLOR_WHITE,          "COLOR_WHITE" },
114         /* *INDENT-ON* */
115
116     }
117 #endif /* !USE_TERMLIB */
118     ;
119     size_t n;
120     unsigned save_nc_tracing = _nc_tracing;
121     _nc_tracing = 0;
122
123     strcpy(buf, l_brace);
124
125     for (n = 0; n < SIZEOF(names); n++) {
126         if ((newmode & names[n].val) != 0) {
127             if (buf[1] != '\0')
128                 buf = _nc_trace_bufcat(bufnum, "|");
129             buf = _nc_trace_bufcat(bufnum, names[n].name);
130
131             if (names[n].val == A_COLOR) {
132                 short pairnum = PAIR_NUMBER(newmode);
133 #ifdef USE_TERMLIB
134                 /* pair_content lives in libncurses */
135                 (void) sprintf(temp, "{%d}", pairnum);
136 #else
137                 short fg, bg;
138
139                 if (pair_content(pairnum, &fg, &bg) == OK) {
140                     (void) sprintf(temp,
141                                    "{%d = {%s, %s}}",
142                                    pairnum,
143                                    COLOR_OF(fg),
144                                    COLOR_OF(bg));
145                 } else {
146                     (void) sprintf(temp, "{%d}", pairnum);
147                 }
148 #endif
149                 buf = _nc_trace_bufcat(bufnum, temp);
150             }
151         }
152     }
153     if (ChAttrOf(newmode) == A_NORMAL) {
154         if (buf[1] != '\0')
155             (void) _nc_trace_bufcat(bufnum, "|");
156         (void) _nc_trace_bufcat(bufnum, "A_NORMAL");
157     }
158
159     _nc_tracing = save_nc_tracing;
160     return (_nc_trace_bufcat(bufnum, r_brace));
161 }
162
163 NCURSES_EXPORT(char *)
164 _traceattr(attr_t newmode)
165 {
166     return _traceattr2(0, newmode);
167 }
168
169 /* Trace 'int' return-values */
170 NCURSES_EXPORT(attr_t)
171 _nc_retrace_attr_t(attr_t code)
172 {
173     T((T_RETURN("%s"), _traceattr(code)));
174     return code;
175 }
176
177 const char *
178 _nc_altcharset_name(attr_t attr, chtype ch)
179 {
180     typedef struct {
181         unsigned int val;
182         const char *name;
183     } ALT_NAMES;
184
185     const char *result = 0;
186
187     if ((attr & A_ALTCHARSET) && (acs_chars != 0)) {
188         char *cp;
189         char *found = 0;
190         /* *INDENT-OFF* */
191         static const ALT_NAMES names[] =
192         {
193             { 'l', "ACS_ULCORNER" },    /* upper left corner */
194             { 'm', "ACS_LLCORNER" },    /* lower left corner */
195             { 'k', "ACS_URCORNER" },    /* upper right corner */
196             { 'j', "ACS_LRCORNER" },    /* lower right corner */
197             { 't', "ACS_LTEE" },        /* tee pointing right */
198             { 'u', "ACS_RTEE" },        /* tee pointing left */
199             { 'v', "ACS_BTEE" },        /* tee pointing up */
200             { 'w', "ACS_TTEE" },        /* tee pointing down */
201             { 'q', "ACS_HLINE" },       /* horizontal line */
202             { 'x', "ACS_VLINE" },       /* vertical line */
203             { 'n', "ACS_PLUS" },        /* large plus or crossover */
204             { 'o', "ACS_S1" },          /* scan line 1 */
205             { 's', "ACS_S9" },          /* scan line 9 */
206             { '`', "ACS_DIAMOND" },     /* diamond */
207             { 'a', "ACS_CKBOARD" },     /* checker board (stipple) */
208             { 'f', "ACS_DEGREE" },      /* degree symbol */
209             { 'g', "ACS_PLMINUS" },     /* plus/minus */
210             { '~', "ACS_BULLET" },      /* bullet */
211             { ',', "ACS_LARROW" },      /* arrow pointing left */
212             { '+', "ACS_RARROW" },      /* arrow pointing right */
213             { '.', "ACS_DARROW" },      /* arrow pointing down */
214             { '-', "ACS_UARROW" },      /* arrow pointing up */
215             { 'h', "ACS_BOARD" },       /* board of squares */
216             { 'i', "ACS_LANTERN" },     /* lantern symbol */
217             { '0', "ACS_BLOCK" },       /* solid square block */
218             { 'p', "ACS_S3" },          /* scan line 3 */
219             { 'r', "ACS_S7" },          /* scan line 7 */
220             { 'y', "ACS_LEQUAL" },      /* less/equal */
221             { 'z', "ACS_GEQUAL" },      /* greater/equal */
222             { '{', "ACS_PI" },          /* Pi */
223             { '|', "ACS_NEQUAL" },      /* not equal */
224             { '}', "ACS_STERLING" },    /* UK pound sign */
225             { '\0', (char *) 0 }
226         };
227         /* *INDENT-OFF* */
228         const ALT_NAMES *sp;
229
230         for (cp = acs_chars; cp[0] && cp[1]; cp += 2) {
231             if (ChCharOf(cp[1]) == ChCharOf(ch)) {
232                 found = cp;
233                 /* don't exit from loop - there may be redefinitions */
234             }
235         }
236
237         if (found != 0) {
238             ch = ChCharOf(*found);
239             for (sp = names; sp->val; sp++)
240                 if (sp->val == ch) {
241                     result = sp->name;
242                     break;
243                 }
244         }
245     }
246     return result;
247 }
248
249 NCURSES_EXPORT(char *)
250 _tracechtype2(int bufnum, chtype ch)
251 {
252     const char *found;
253
254     strcpy(_nc_trace_buf(bufnum, BUFSIZ), l_brace);
255     if ((found = _nc_altcharset_name(ChAttrOf(ch), ch)) != 0) {
256         (void) _nc_trace_bufcat(bufnum, found);
257     } else
258         (void) _nc_trace_bufcat(bufnum, _nc_tracechar(SP, (int)ChCharOf(ch)));
259
260     if (ChAttrOf(ch) != A_NORMAL) {
261         (void) _nc_trace_bufcat(bufnum, " | ");
262         (void) _nc_trace_bufcat(bufnum,
263                 _traceattr2(bufnum + 20, ChAttrOf(ch)));
264     }
265
266     return (_nc_trace_bufcat(bufnum, r_brace));
267 }
268
269 NCURSES_EXPORT(char *)
270 _tracechtype (chtype ch)
271 {
272     return _tracechtype2(0, ch);
273 }
274
275 /* Trace 'chtype' return-values */
276 NCURSES_EXPORT(chtype)
277 _nc_retrace_chtype (chtype code)
278 {
279     T((T_RETURN("%s"), _tracechtype(code)));
280     return code;
281 }
282
283 #if USE_WIDEC_SUPPORT
284 NCURSES_EXPORT(char *)
285 _tracecchar_t2 (int bufnum, const cchar_t *ch)
286 {
287     char *buf = _nc_trace_buf(bufnum, BUFSIZ);
288     attr_t attr;
289     const char *found;
290
291     strcpy(buf, l_brace);
292     if (ch != 0) {
293         attr = AttrOfD(ch);
294         if ((found = _nc_altcharset_name(attr, (chtype) CharOfD(ch))) != 0) {
295             (void) _nc_trace_bufcat(bufnum, found);
296             attr &= ~A_ALTCHARSET;
297         } else if (isWidecExt(CHDEREF(ch))) {
298             (void) _nc_trace_bufcat(bufnum, "{NAC}");
299             attr &= ~A_CHARTEXT;
300         } else {
301             PUTC_DATA;
302             int n;
303
304             PUTC_INIT;
305             (void) _nc_trace_bufcat(bufnum, "{ ");
306             for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) {
307                 PUTC_ch = ch->chars[PUTC_i];
308                 if (PUTC_ch == L'\0')
309                     break;
310                 PUTC_n = wcrtomb(PUTC_buf, ch->chars[PUTC_i], &PUT_st);
311                 if (PUTC_n <= 0) {
312                     if (PUTC_ch != L'\0') {
313                         /* it could not be a multibyte sequence */
314                         (void) _nc_trace_bufcat(bufnum, _nc_tracechar(SP, UChar(ch->chars[PUTC_i])));
315                     }
316                     break;
317                 }
318                 for (n = 0; n < PUTC_n; n++) {
319                     if (n)
320                         (void) _nc_trace_bufcat(bufnum, ", ");
321                     (void) _nc_trace_bufcat(bufnum, _nc_tracechar(SP, UChar(PUTC_buf[n])));
322                 }
323             }
324             (void) _nc_trace_bufcat(bufnum, " }");
325         }
326         if (attr != A_NORMAL) {
327             (void) _nc_trace_bufcat(bufnum, " | ");
328             (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr));
329         }
330     }
331
332     return (_nc_trace_bufcat(bufnum, r_brace));
333 }
334
335 NCURSES_EXPORT(char *)
336 _tracecchar_t (const cchar_t *ch)
337 {
338     return _tracecchar_t2(0, ch);
339 }
340 #endif
341
342 #else
343 empty_module(_nc_lib_traceatr)
344 #endif /* TRACE */