]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/dialog/trace.c
bc: upgrade to version 3.3.4
[FreeBSD/FreeBSD.git] / contrib / dialog / trace.c
1 /*
2  *  $Id: trace.c,v 1.33 2020/11/23 23:32:43 tom Exp $
3  *
4  *  trace.c -- implements screen-dump and keystroke-logging
5  *
6  *  Copyright 2007-2019,2020    Thomas E. Dickey
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU Lesser General Public License, version 2.1
10  *  as published by the Free Software Foundation.
11  *
12  *  This program is distributed in the hope that it will be useful, but
13  *  WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this program; if not, write to
19  *      Free Software Foundation, Inc.
20  *      51 Franklin St., Fifth Floor
21  *      Boston, MA 02110, USA.
22  */
23
24 #include <dialog.h>
25
26 #ifdef HAVE_DLG_TRACE
27
28 #ifdef NEED_WCHAR_H
29 #include <wchar.h>
30 #endif
31
32 #include <dlg_keys.h>
33 #include <time.h>
34
35 #define myFP dialog_state.trace_output
36
37 static void
38 dlg_trace_time(const char *tag)
39 {
40     time_t now = time((time_t *) 0);
41     fprintf(myFP, "%s %s", tag, ctime(&now));
42 }
43
44 void
45 dlg_trace_msg(const char *fmt, ...)
46 {
47     if (myFP != 0) {
48         va_list ap;
49         va_start(ap, fmt);
50         vfprintf(myFP, fmt, ap);
51         va_end(ap);
52         fflush(myFP);
53     }
54 }
55
56 void
57 dlg_trace_va_msg(const char *fmt, va_list ap)
58 {
59     if (myFP != 0) {
60         vfprintf(myFP, fmt, ap);
61         fflush(myFP);
62     }
63 }
64
65 void
66 dlg_trace_2s(const char *name, const char *value)
67 {
68     bool first = TRUE;
69     int left, right = 0;
70
71     if (value == 0)
72         value = "<NULL>";
73
74     while (value[right] != '\0') {
75         const char *next;
76
77         value += right;
78         if ((next = strchr(value, '\n')) != 0) {
79             left = (int) (next - value);
80             right = left + 1;
81         } else {
82             left = (int) strlen(value);
83             right = left;
84         }
85         if (first) {
86             first = FALSE;
87             dlg_trace_msg("#%14s = %.*s\n", name, left, value);
88         } else {
89             dlg_trace_msg("#+%13s%.*s\n", " ", left, value);
90         }
91     }
92 }
93
94 void
95 dlg_trace_2n(const char *name, int value)
96 {
97     dlg_trace_msg("#%14s = %d\n", name, value);
98 }
99
100 void
101 dlg_trace_win(WINDOW *win)
102 {
103     if (myFP != 0) {
104         WINDOW *top = wgetparent(win);
105
106         while (top != 0 && top != stdscr) {
107             win = top;
108             top = wgetparent(win);
109         }
110
111         if (win != 0) {
112             int rc = getmaxy(win);
113             int cc = getmaxx(win);
114             chtype ch, c2;
115             int y, x;
116             int j, k;
117
118             fprintf(myFP, "window %dx%d at %d,%d\n",
119                     rc, cc, getbegy(win), getbegx(win));
120
121             getyx(win, y, x);
122             for (j = 0; j < rc; ++j) {
123                 fprintf(myFP, "%3d:", j);
124                 for (k = 0; k < cc; ++k) {
125 #ifdef USE_WIDE_CURSES
126                     char buffer[80];
127
128                     ch = mvwinch(win, j, k) & (A_CHARTEXT | A_ALTCHARSET);
129                     if (ch & A_ALTCHARSET) {
130                         c2 = dlg_asciibox(ch);
131                         if (c2 != 0) {
132                             ch = c2;
133                         }
134                         buffer[0] = (char) ch;
135                         buffer[1] = '\0';
136                     } else {
137                         cchar_t cch;
138                         const wchar_t *uc;
139
140                         if (win_wch(win, &cch) == ERR
141                             || (uc = wunctrl((&cch))) == 0
142                             || uc[1] != 0
143                             || wcwidth(uc[0]) <= 0) {
144                             buffer[0] = '.';
145                             buffer[1] = '\0';
146                         } else {
147                             mbstate_t state;
148                             const wchar_t *ucp = uc;
149
150                             memset(&state, 0, sizeof(state));
151                             wcsrtombs(buffer, &ucp, sizeof(buffer), &state);
152                             k += wcwidth(uc[0]) - 1;
153                         }
154                     }
155                     fputs(buffer, myFP);
156 #else
157                     ch = mvwinch(win, j, k) & (A_CHARTEXT | A_ALTCHARSET);
158                     c2 = dlg_asciibox(ch);
159                     if (c2 != 0) {
160                         ch = c2;
161                     } else if (unctrl(ch) == 0 || strlen(unctrl(ch)) > 1) {
162                         ch = '.';
163                     }
164                     fputc((int) (ch & 0xff), myFP);
165 #endif
166                 }
167                 fputc('\n', myFP);
168             }
169             wmove(win, y, x);
170             fflush(myFP);
171         }
172     }
173 }
174
175 void
176 dlg_trace_chr(int ch, int fkey)
177 {
178     static int last_err = 0;
179
180     /*
181      * Do not bother to trace ERR's indefinitely, since those are usually due
182      * to relatively short polling timeouts.
183      */
184     if (last_err && !fkey && ch == ERR) {
185         ++last_err;
186     } else if (myFP != 0) {
187         const char *fkey_name = "?";
188
189         if (last_err) {
190             fprintf(myFP, "skipped %d ERR's\n", last_err);
191             last_err = 0;
192         }
193
194         if (fkey) {
195             if (fkey > KEY_MAX || (fkey_name = keyname(fkey)) == 0) {
196 #define CASE(name) case name: fkey_name = #name; break
197                 switch ((DLG_KEYS_ENUM) fkey) {
198                     CASE(DLGK_MIN);
199                     CASE(DLGK_OK);
200                     CASE(DLGK_CANCEL);
201                     CASE(DLGK_EXTRA);
202                     CASE(DLGK_HELP);
203                     CASE(DLGK_ESC);
204                     CASE(DLGK_PAGE_FIRST);
205                     CASE(DLGK_PAGE_LAST);
206                     CASE(DLGK_PAGE_NEXT);
207                     CASE(DLGK_PAGE_PREV);
208                     CASE(DLGK_ITEM_FIRST);
209                     CASE(DLGK_ITEM_LAST);
210                     CASE(DLGK_ITEM_NEXT);
211                     CASE(DLGK_ITEM_PREV);
212                     CASE(DLGK_FIELD_FIRST);
213                     CASE(DLGK_FIELD_LAST);
214                     CASE(DLGK_FIELD_NEXT);
215                     CASE(DLGK_FIELD_PREV);
216                     CASE(DLGK_FORM_FIRST);
217                     CASE(DLGK_FORM_LAST);
218                     CASE(DLGK_FORM_NEXT);
219                     CASE(DLGK_FORM_PREV);
220                     CASE(DLGK_GRID_UP);
221                     CASE(DLGK_GRID_DOWN);
222                     CASE(DLGK_GRID_LEFT);
223                     CASE(DLGK_GRID_RIGHT);
224                     CASE(DLGK_DELETE_LEFT);
225                     CASE(DLGK_DELETE_RIGHT);
226                     CASE(DLGK_DELETE_ALL);
227                     CASE(DLGK_ENTER);
228                     CASE(DLGK_BEGIN);
229                     CASE(DLGK_FINAL);
230                     CASE(DLGK_SELECT);
231                     CASE(DLGK_HELPFILE);
232                     CASE(DLGK_TRACE);
233                     CASE(DLGK_TOGGLE);
234                     CASE(DLGK_LEAVE);
235                 }
236             }
237         } else if (ch == ERR) {
238             fkey_name = "ERR";
239             last_err = 1;
240         } else {
241             fkey_name = unctrl((chtype) ch);
242             if (fkey_name == 0)
243                 fkey_name = "UNKNOWN";
244         }
245         if (ch >= 0) {
246             fprintf(myFP, "chr %s (ch=%#x, fkey=%d)\n", fkey_name, ch, fkey);
247         } else {
248             fprintf(myFP, "chr %s (ch=%d, fkey=%d)\n", fkey_name, ch, fkey);
249         }
250         fflush(myFP);
251     }
252 }
253
254 void
255 dlg_trace(const char *fname)
256 {
257     if (fname != 0) {
258         if (myFP == 0) {
259             myFP = fopen(fname, "a");
260             if (myFP != 0) {
261                 dlg_trace_time("## opened at");
262                 DLG_TRACE(("## dialog %s\n", dialog_version()));
263                 DLG_TRACE(("## vile: confmode\n"));
264             }
265         }
266     } else if (myFP != 0) {
267         dlg_trace_time("## closed at");
268         fclose(myFP);
269         myFP = 0;
270     }
271 }
272 #else
273 #undef dlg_trace
274 extern void dlg_trace(const char *);
275 void
276 dlg_trace(const char *fname)
277 {
278     (void) fname;
279 }
280 #endif