xref: /freebsd-src/contrib/dialog/trace.c (revision a96ef4501919d7ac08e94e98dc34b0bdd744802b)
14c8945a0SNathan Whitehorn /*
2*a96ef450SBaptiste Daroussin  *  $Id: trace.c,v 1.33 2020/11/23 23:32:43 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  trace.c -- implements screen-dump and keystroke-logging
54c8945a0SNathan Whitehorn  *
6*a96ef450SBaptiste Daroussin  *  Copyright 2007-2019,2020	Thomas E. Dickey
74c8945a0SNathan Whitehorn  *
84c8945a0SNathan Whitehorn  *  This program is free software; you can redistribute it and/or modify
94c8945a0SNathan Whitehorn  *  it under the terms of the GNU Lesser General Public License, version 2.1
10*a96ef450SBaptiste Daroussin  *  as published by the Free Software Foundation.
114c8945a0SNathan Whitehorn  *
124c8945a0SNathan Whitehorn  *  This program is distributed in the hope that it will be useful, but
134c8945a0SNathan Whitehorn  *  WITHOUT ANY WARRANTY; without even the implied warranty of
144c8945a0SNathan Whitehorn  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
154c8945a0SNathan Whitehorn  *  Lesser General Public License for more details.
164c8945a0SNathan Whitehorn  *
174c8945a0SNathan Whitehorn  *  You should have received a copy of the GNU Lesser General Public
184c8945a0SNathan Whitehorn  *  License along with this program; if not, write to
194c8945a0SNathan Whitehorn  *	Free Software Foundation, Inc.
204c8945a0SNathan Whitehorn  *	51 Franklin St., Fifth Floor
214c8945a0SNathan Whitehorn  *	Boston, MA 02110, USA.
224c8945a0SNathan Whitehorn  */
234c8945a0SNathan Whitehorn 
244c8945a0SNathan Whitehorn #include <dialog.h>
254c8945a0SNathan Whitehorn 
264c8945a0SNathan Whitehorn #ifdef HAVE_DLG_TRACE
274c8945a0SNathan Whitehorn 
282a3e3873SBaptiste Daroussin #ifdef NEED_WCHAR_H
292a3e3873SBaptiste Daroussin #include <wchar.h>
302a3e3873SBaptiste Daroussin #endif
312a3e3873SBaptiste Daroussin 
324c8945a0SNathan Whitehorn #include <dlg_keys.h>
334c8945a0SNathan Whitehorn #include <time.h>
344c8945a0SNathan Whitehorn 
354c8945a0SNathan Whitehorn #define myFP dialog_state.trace_output
364c8945a0SNathan Whitehorn 
377a1c0d96SNathan Whitehorn static void
dlg_trace_time(const char * tag)387a1c0d96SNathan Whitehorn dlg_trace_time(const char *tag)
397a1c0d96SNathan Whitehorn {
407a1c0d96SNathan Whitehorn     time_t now = time((time_t *) 0);
417a1c0d96SNathan Whitehorn     fprintf(myFP, "%s %s", tag, ctime(&now));
427a1c0d96SNathan Whitehorn }
437a1c0d96SNathan Whitehorn 
444c8945a0SNathan Whitehorn void
dlg_trace_msg(const char * fmt,...)454c8945a0SNathan Whitehorn dlg_trace_msg(const char *fmt, ...)
464c8945a0SNathan Whitehorn {
474c8945a0SNathan Whitehorn     if (myFP != 0) {
484c8945a0SNathan Whitehorn 	va_list ap;
494c8945a0SNathan Whitehorn 	va_start(ap, fmt);
504c8945a0SNathan Whitehorn 	vfprintf(myFP, fmt, ap);
514c8945a0SNathan Whitehorn 	va_end(ap);
524c8945a0SNathan Whitehorn 	fflush(myFP);
534c8945a0SNathan Whitehorn     }
544c8945a0SNathan Whitehorn }
554c8945a0SNathan Whitehorn 
564c8945a0SNathan Whitehorn void
dlg_trace_va_msg(const char * fmt,va_list ap)57*a96ef450SBaptiste Daroussin dlg_trace_va_msg(const char *fmt, va_list ap)
58*a96ef450SBaptiste Daroussin {
59*a96ef450SBaptiste Daroussin     if (myFP != 0) {
60*a96ef450SBaptiste Daroussin 	vfprintf(myFP, fmt, ap);
61*a96ef450SBaptiste Daroussin 	fflush(myFP);
62*a96ef450SBaptiste Daroussin     }
63*a96ef450SBaptiste Daroussin }
64*a96ef450SBaptiste Daroussin 
65*a96ef450SBaptiste Daroussin void
dlg_trace_2s(const char * name,const char * value)66f4f33ea0SBaptiste Daroussin dlg_trace_2s(const char *name, const char *value)
67f4f33ea0SBaptiste Daroussin {
68f4f33ea0SBaptiste Daroussin     bool first = TRUE;
69f4f33ea0SBaptiste Daroussin     int left, right = 0;
70f4f33ea0SBaptiste Daroussin 
71f4f33ea0SBaptiste Daroussin     if (value == 0)
72f4f33ea0SBaptiste Daroussin 	value = "<NULL>";
73f4f33ea0SBaptiste Daroussin 
74f4f33ea0SBaptiste Daroussin     while (value[right] != '\0') {
75*a96ef450SBaptiste Daroussin 	const char *next;
76*a96ef450SBaptiste Daroussin 
77f4f33ea0SBaptiste Daroussin 	value += right;
78f4f33ea0SBaptiste Daroussin 	if ((next = strchr(value, '\n')) != 0) {
79f4f33ea0SBaptiste Daroussin 	    left = (int) (next - value);
80f4f33ea0SBaptiste Daroussin 	    right = left + 1;
81f4f33ea0SBaptiste Daroussin 	} else {
82f4f33ea0SBaptiste Daroussin 	    left = (int) strlen(value);
83f4f33ea0SBaptiste Daroussin 	    right = left;
84f4f33ea0SBaptiste Daroussin 	}
85f4f33ea0SBaptiste Daroussin 	if (first) {
86f4f33ea0SBaptiste Daroussin 	    first = FALSE;
87f4f33ea0SBaptiste Daroussin 	    dlg_trace_msg("#%14s = %.*s\n", name, left, value);
88f4f33ea0SBaptiste Daroussin 	} else {
89*a96ef450SBaptiste Daroussin 	    dlg_trace_msg("#+%13s%.*s\n", " ", left, value);
90f4f33ea0SBaptiste Daroussin 	}
91f4f33ea0SBaptiste Daroussin     }
92f4f33ea0SBaptiste Daroussin }
93f4f33ea0SBaptiste Daroussin 
94f4f33ea0SBaptiste Daroussin void
dlg_trace_2n(const char * name,int value)95f4f33ea0SBaptiste Daroussin dlg_trace_2n(const char *name, int value)
96f4f33ea0SBaptiste Daroussin {
97*a96ef450SBaptiste Daroussin     dlg_trace_msg("#%14s = %d\n", name, value);
98f4f33ea0SBaptiste Daroussin }
99f4f33ea0SBaptiste Daroussin 
100f4f33ea0SBaptiste Daroussin void
dlg_trace_win(WINDOW * win)1014c8945a0SNathan Whitehorn dlg_trace_win(WINDOW *win)
1024c8945a0SNathan Whitehorn {
1034c8945a0SNathan Whitehorn     if (myFP != 0) {
1042a3e3873SBaptiste Daroussin 	WINDOW *top = wgetparent(win);
1052a3e3873SBaptiste Daroussin 
1062a3e3873SBaptiste Daroussin 	while (top != 0 && top != stdscr) {
1072a3e3873SBaptiste Daroussin 	    win = top;
1082a3e3873SBaptiste Daroussin 	    top = wgetparent(win);
1092a3e3873SBaptiste Daroussin 	}
1102a3e3873SBaptiste Daroussin 
1112a3e3873SBaptiste Daroussin 	if (win != 0) {
1124c8945a0SNathan Whitehorn 	    int rc = getmaxy(win);
1134c8945a0SNathan Whitehorn 	    int cc = getmaxx(win);
1144c8945a0SNathan Whitehorn 	    chtype ch, c2;
115*a96ef450SBaptiste Daroussin 	    int y, x;
116*a96ef450SBaptiste Daroussin 	    int j, k;
1174c8945a0SNathan Whitehorn 
1184c8945a0SNathan Whitehorn 	    fprintf(myFP, "window %dx%d at %d,%d\n",
1194c8945a0SNathan Whitehorn 		    rc, cc, getbegy(win), getbegx(win));
1204c8945a0SNathan Whitehorn 
1214c8945a0SNathan Whitehorn 	    getyx(win, y, x);
1224c8945a0SNathan Whitehorn 	    for (j = 0; j < rc; ++j) {
1234c8945a0SNathan Whitehorn 		fprintf(myFP, "%3d:", j);
1244c8945a0SNathan Whitehorn 		for (k = 0; k < cc; ++k) {
1252a3e3873SBaptiste Daroussin #ifdef USE_WIDE_CURSES
1262a3e3873SBaptiste Daroussin 		    char buffer[80];
1272a3e3873SBaptiste Daroussin 
1282a3e3873SBaptiste Daroussin 		    ch = mvwinch(win, j, k) & (A_CHARTEXT | A_ALTCHARSET);
1292a3e3873SBaptiste Daroussin 		    if (ch & A_ALTCHARSET) {
1302a3e3873SBaptiste Daroussin 			c2 = dlg_asciibox(ch);
1312a3e3873SBaptiste Daroussin 			if (c2 != 0) {
1322a3e3873SBaptiste Daroussin 			    ch = c2;
1332a3e3873SBaptiste Daroussin 			}
1342a3e3873SBaptiste Daroussin 			buffer[0] = (char) ch;
1352a3e3873SBaptiste Daroussin 			buffer[1] = '\0';
1362a3e3873SBaptiste Daroussin 		    } else {
1372a3e3873SBaptiste Daroussin 			cchar_t cch;
138*a96ef450SBaptiste Daroussin 			const wchar_t *uc;
1392a3e3873SBaptiste Daroussin 
1402a3e3873SBaptiste Daroussin 			if (win_wch(win, &cch) == ERR
141f4f33ea0SBaptiste Daroussin 			    || (uc = wunctrl((&cch))) == 0
1422a3e3873SBaptiste Daroussin 			    || uc[1] != 0
1432a3e3873SBaptiste Daroussin 			    || wcwidth(uc[0]) <= 0) {
1442a3e3873SBaptiste Daroussin 			    buffer[0] = '.';
1452a3e3873SBaptiste Daroussin 			    buffer[1] = '\0';
1462a3e3873SBaptiste Daroussin 			} else {
1472a3e3873SBaptiste Daroussin 			    mbstate_t state;
1482a3e3873SBaptiste Daroussin 			    const wchar_t *ucp = uc;
1492a3e3873SBaptiste Daroussin 
1502a3e3873SBaptiste Daroussin 			    memset(&state, 0, sizeof(state));
1512a3e3873SBaptiste Daroussin 			    wcsrtombs(buffer, &ucp, sizeof(buffer), &state);
1522a3e3873SBaptiste Daroussin 			    k += wcwidth(uc[0]) - 1;
1532a3e3873SBaptiste Daroussin 			}
1542a3e3873SBaptiste Daroussin 		    }
1552a3e3873SBaptiste Daroussin 		    fputs(buffer, myFP);
1562a3e3873SBaptiste Daroussin #else
1574c8945a0SNathan Whitehorn 		    ch = mvwinch(win, j, k) & (A_CHARTEXT | A_ALTCHARSET);
1584c8945a0SNathan Whitehorn 		    c2 = dlg_asciibox(ch);
1594c8945a0SNathan Whitehorn 		    if (c2 != 0) {
1604c8945a0SNathan Whitehorn 			ch = c2;
1614c8945a0SNathan Whitehorn 		    } else if (unctrl(ch) == 0 || strlen(unctrl(ch)) > 1) {
1624c8945a0SNathan Whitehorn 			ch = '.';
1634c8945a0SNathan Whitehorn 		    }
1644c8945a0SNathan Whitehorn 		    fputc((int) (ch & 0xff), myFP);
1652a3e3873SBaptiste Daroussin #endif
1664c8945a0SNathan Whitehorn 		}
1674c8945a0SNathan Whitehorn 		fputc('\n', myFP);
1684c8945a0SNathan Whitehorn 	    }
1694c8945a0SNathan Whitehorn 	    wmove(win, y, x);
1704c8945a0SNathan Whitehorn 	    fflush(myFP);
1714c8945a0SNathan Whitehorn 	}
1724c8945a0SNathan Whitehorn     }
1732a3e3873SBaptiste Daroussin }
1744c8945a0SNathan Whitehorn 
1754c8945a0SNathan Whitehorn void
dlg_trace_chr(int ch,int fkey)1764c8945a0SNathan Whitehorn dlg_trace_chr(int ch, int fkey)
1774c8945a0SNathan Whitehorn {
1782a3e3873SBaptiste Daroussin     static int last_err = 0;
1792a3e3873SBaptiste Daroussin 
1802a3e3873SBaptiste Daroussin     /*
1812a3e3873SBaptiste Daroussin      * Do not bother to trace ERR's indefinitely, since those are usually due
1822a3e3873SBaptiste Daroussin      * to relatively short polling timeouts.
1832a3e3873SBaptiste Daroussin      */
1842a3e3873SBaptiste Daroussin     if (last_err && !fkey && ch == ERR) {
1852a3e3873SBaptiste Daroussin 	++last_err;
1862a3e3873SBaptiste Daroussin     } else if (myFP != 0) {
1874c8945a0SNathan Whitehorn 	const char *fkey_name = "?";
1882a3e3873SBaptiste Daroussin 
1892a3e3873SBaptiste Daroussin 	if (last_err) {
1902a3e3873SBaptiste Daroussin 	    fprintf(myFP, "skipped %d ERR's\n", last_err);
1912a3e3873SBaptiste Daroussin 	    last_err = 0;
1922a3e3873SBaptiste Daroussin 	}
1932a3e3873SBaptiste Daroussin 
1944c8945a0SNathan Whitehorn 	if (fkey) {
1954c8945a0SNathan Whitehorn 	    if (fkey > KEY_MAX || (fkey_name = keyname(fkey)) == 0) {
1964c8945a0SNathan Whitehorn #define CASE(name) case name: fkey_name = #name; break
1974c8945a0SNathan Whitehorn 		switch ((DLG_KEYS_ENUM) fkey) {
1984c8945a0SNathan Whitehorn 		    CASE(DLGK_MIN);
1994c8945a0SNathan Whitehorn 		    CASE(DLGK_OK);
2004c8945a0SNathan Whitehorn 		    CASE(DLGK_CANCEL);
2014c8945a0SNathan Whitehorn 		    CASE(DLGK_EXTRA);
2024c8945a0SNathan Whitehorn 		    CASE(DLGK_HELP);
2034c8945a0SNathan Whitehorn 		    CASE(DLGK_ESC);
2044c8945a0SNathan Whitehorn 		    CASE(DLGK_PAGE_FIRST);
2054c8945a0SNathan Whitehorn 		    CASE(DLGK_PAGE_LAST);
2064c8945a0SNathan Whitehorn 		    CASE(DLGK_PAGE_NEXT);
2074c8945a0SNathan Whitehorn 		    CASE(DLGK_PAGE_PREV);
2084c8945a0SNathan Whitehorn 		    CASE(DLGK_ITEM_FIRST);
2094c8945a0SNathan Whitehorn 		    CASE(DLGK_ITEM_LAST);
2104c8945a0SNathan Whitehorn 		    CASE(DLGK_ITEM_NEXT);
2114c8945a0SNathan Whitehorn 		    CASE(DLGK_ITEM_PREV);
2124c8945a0SNathan Whitehorn 		    CASE(DLGK_FIELD_FIRST);
2134c8945a0SNathan Whitehorn 		    CASE(DLGK_FIELD_LAST);
2144c8945a0SNathan Whitehorn 		    CASE(DLGK_FIELD_NEXT);
2154c8945a0SNathan Whitehorn 		    CASE(DLGK_FIELD_PREV);
2162a3e3873SBaptiste Daroussin 		    CASE(DLGK_FORM_FIRST);
2172a3e3873SBaptiste Daroussin 		    CASE(DLGK_FORM_LAST);
2182a3e3873SBaptiste Daroussin 		    CASE(DLGK_FORM_NEXT);
2192a3e3873SBaptiste Daroussin 		    CASE(DLGK_FORM_PREV);
2204c8945a0SNathan Whitehorn 		    CASE(DLGK_GRID_UP);
2214c8945a0SNathan Whitehorn 		    CASE(DLGK_GRID_DOWN);
2224c8945a0SNathan Whitehorn 		    CASE(DLGK_GRID_LEFT);
2234c8945a0SNathan Whitehorn 		    CASE(DLGK_GRID_RIGHT);
2244c8945a0SNathan Whitehorn 		    CASE(DLGK_DELETE_LEFT);
2254c8945a0SNathan Whitehorn 		    CASE(DLGK_DELETE_RIGHT);
2264c8945a0SNathan Whitehorn 		    CASE(DLGK_DELETE_ALL);
2274c8945a0SNathan Whitehorn 		    CASE(DLGK_ENTER);
2284c8945a0SNathan Whitehorn 		    CASE(DLGK_BEGIN);
2294c8945a0SNathan Whitehorn 		    CASE(DLGK_FINAL);
2304c8945a0SNathan Whitehorn 		    CASE(DLGK_SELECT);
231682c9e0fSNathan Whitehorn 		    CASE(DLGK_HELPFILE);
2324c8945a0SNathan Whitehorn 		    CASE(DLGK_TRACE);
233f4f33ea0SBaptiste Daroussin 		    CASE(DLGK_TOGGLE);
234*a96ef450SBaptiste Daroussin 		    CASE(DLGK_LEAVE);
2354c8945a0SNathan Whitehorn 		}
2364c8945a0SNathan Whitehorn 	    }
2377a1c0d96SNathan Whitehorn 	} else if (ch == ERR) {
2387a1c0d96SNathan Whitehorn 	    fkey_name = "ERR";
2392a3e3873SBaptiste Daroussin 	    last_err = 1;
2404c8945a0SNathan Whitehorn 	} else {
2414c8945a0SNathan Whitehorn 	    fkey_name = unctrl((chtype) ch);
2424c8945a0SNathan Whitehorn 	    if (fkey_name == 0)
2434c8945a0SNathan Whitehorn 		fkey_name = "UNKNOWN";
2444c8945a0SNathan Whitehorn 	}
245f4f33ea0SBaptiste Daroussin 	if (ch >= 0) {
246f4f33ea0SBaptiste Daroussin 	    fprintf(myFP, "chr %s (ch=%#x, fkey=%d)\n", fkey_name, ch, fkey);
247f4f33ea0SBaptiste Daroussin 	} else {
248f4f33ea0SBaptiste Daroussin 	    fprintf(myFP, "chr %s (ch=%d, fkey=%d)\n", fkey_name, ch, fkey);
249f4f33ea0SBaptiste Daroussin 	}
2504c8945a0SNathan Whitehorn 	fflush(myFP);
2514c8945a0SNathan Whitehorn     }
2524c8945a0SNathan Whitehorn }
2534c8945a0SNathan Whitehorn 
2544c8945a0SNathan Whitehorn void
dlg_trace(const char * fname)2554c8945a0SNathan Whitehorn dlg_trace(const char *fname)
2564c8945a0SNathan Whitehorn {
2574c8945a0SNathan Whitehorn     if (fname != 0) {
2584c8945a0SNathan Whitehorn 	if (myFP == 0) {
2594c8945a0SNathan Whitehorn 	    myFP = fopen(fname, "a");
2604c8945a0SNathan Whitehorn 	    if (myFP != 0) {
261f4f33ea0SBaptiste Daroussin 		dlg_trace_time("## opened at");
262f4f33ea0SBaptiste Daroussin 		DLG_TRACE(("## dialog %s\n", dialog_version()));
263f4f33ea0SBaptiste Daroussin 		DLG_TRACE(("## vile: confmode\n"));
2644c8945a0SNathan Whitehorn 	    }
2654c8945a0SNathan Whitehorn 	}
2664c8945a0SNathan Whitehorn     } else if (myFP != 0) {
267f4f33ea0SBaptiste Daroussin 	dlg_trace_time("## closed at");
2684c8945a0SNathan Whitehorn 	fclose(myFP);
2694c8945a0SNathan Whitehorn 	myFP = 0;
2704c8945a0SNathan Whitehorn     }
2714c8945a0SNathan Whitehorn }
2724c8945a0SNathan Whitehorn #else
2734c8945a0SNathan Whitehorn #undef dlg_trace
2744c8945a0SNathan Whitehorn extern void dlg_trace(const char *);
2754c8945a0SNathan Whitehorn void
dlg_trace(const char * fname)2764c8945a0SNathan Whitehorn dlg_trace(const char *fname)
2774c8945a0SNathan Whitehorn {
2784c8945a0SNathan Whitehorn     (void) fname;
2794c8945a0SNathan Whitehorn }
2804c8945a0SNathan Whitehorn #endif
281