1217309Snwhitehorn/*
2251843Sbapt *  $Id: trace.c,v 1.20 2011/10/18 10:47:26 tom Exp $
3217309Snwhitehorn *
4217309Snwhitehorn *  trace.c -- implements screen-dump and keystroke-logging
5217309Snwhitehorn *
6220749Snwhitehorn *  Copyright 2007-2010,2011	Thomas E. Dickey
7217309Snwhitehorn *
8217309Snwhitehorn *  This program is free software; you can redistribute it and/or modify
9217309Snwhitehorn *  it under the terms of the GNU Lesser General Public License, version 2.1
10217309Snwhitehorn *
11217309Snwhitehorn *  This program is distributed in the hope that it will be useful, but
12217309Snwhitehorn *  WITHOUT ANY WARRANTY; without even the implied warranty of
13217309Snwhitehorn *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14217309Snwhitehorn *  Lesser General Public License for more details.
15217309Snwhitehorn *
16217309Snwhitehorn *  You should have received a copy of the GNU Lesser General Public
17217309Snwhitehorn *  License along with this program; if not, write to
18217309Snwhitehorn *	Free Software Foundation, Inc.
19217309Snwhitehorn *	51 Franklin St., Fifth Floor
20217309Snwhitehorn *	Boston, MA 02110, USA.
21217309Snwhitehorn */
22217309Snwhitehorn
23217309Snwhitehorn#include <dialog.h>
24217309Snwhitehorn
25217309Snwhitehorn#ifdef HAVE_DLG_TRACE
26217309Snwhitehorn
27251843Sbapt#ifdef NEED_WCHAR_H
28251843Sbapt#include <wchar.h>
29251843Sbapt#endif
30251843Sbapt
31217309Snwhitehorn#include <dlg_keys.h>
32217309Snwhitehorn#include <time.h>
33217309Snwhitehorn
34217309Snwhitehorn#define myFP dialog_state.trace_output
35217309Snwhitehorn
36220749Snwhitehornstatic void
37220749Snwhitehorndlg_trace_time(const char *tag)
38220749Snwhitehorn{
39220749Snwhitehorn    time_t now = time((time_t *) 0);
40220749Snwhitehorn    fprintf(myFP, "%s %s", tag, ctime(&now));
41220749Snwhitehorn}
42220749Snwhitehorn
43217309Snwhitehornvoid
44217309Snwhitehorndlg_trace_msg(const char *fmt,...)
45217309Snwhitehorn{
46217309Snwhitehorn    if (myFP != 0) {
47217309Snwhitehorn	va_list ap;
48217309Snwhitehorn	va_start(ap, fmt);
49217309Snwhitehorn	vfprintf(myFP, fmt, ap);
50217309Snwhitehorn	va_end(ap);
51217309Snwhitehorn	fflush(myFP);
52217309Snwhitehorn    }
53217309Snwhitehorn}
54217309Snwhitehorn
55217309Snwhitehornvoid
56217309Snwhitehorndlg_trace_win(WINDOW *win)
57217309Snwhitehorn{
58217309Snwhitehorn    if (myFP != 0) {
59217309Snwhitehorn	int y, x;
60217309Snwhitehorn	int j, k;
61251843Sbapt	WINDOW *top = wgetparent(win);
62217309Snwhitehorn
63251843Sbapt	while (top != 0 && top != stdscr) {
64251843Sbapt	    win = top;
65251843Sbapt	    top = wgetparent(win);
66251843Sbapt	}
67217309Snwhitehorn
68251843Sbapt	if (win != 0) {
69251843Sbapt	    int rc = getmaxy(win);
70251843Sbapt	    int cc = getmaxx(win);
71251843Sbapt	    chtype ch, c2;
72251843Sbapt
73251843Sbapt	    fprintf(myFP, "window %dx%d at %d,%d\n",
74251843Sbapt		    rc, cc, getbegy(win), getbegx(win));
75251843Sbapt
76251843Sbapt	    getyx(win, y, x);
77251843Sbapt	    for (j = 0; j < rc; ++j) {
78251843Sbapt		fprintf(myFP, "%3d:", j);
79251843Sbapt		for (k = 0; k < cc; ++k) {
80251843Sbapt#ifdef USE_WIDE_CURSES
81251843Sbapt		    char buffer[80];
82251843Sbapt
83251843Sbapt		    ch = mvwinch(win, j, k) & (A_CHARTEXT | A_ALTCHARSET);
84251843Sbapt		    if (ch & A_ALTCHARSET) {
85251843Sbapt			c2 = dlg_asciibox(ch);
86251843Sbapt			if (c2 != 0) {
87251843Sbapt			    ch = c2;
88251843Sbapt			}
89251843Sbapt			buffer[0] = (char) ch;
90251843Sbapt			buffer[1] = '\0';
91251843Sbapt		    } else {
92251843Sbapt			cchar_t cch;
93251843Sbapt			wchar_t *uc;
94251843Sbapt
95251843Sbapt			if (win_wch(win, &cch) == ERR
96251843Sbapt			    || (uc = wunctrl(&cch)) == 0
97251843Sbapt			    || uc[1] != 0
98251843Sbapt			    || wcwidth(uc[0]) <= 0) {
99251843Sbapt			    buffer[0] = '.';
100251843Sbapt			    buffer[1] = '\0';
101251843Sbapt			} else {
102251843Sbapt			    mbstate_t state;
103251843Sbapt			    const wchar_t *ucp = uc;
104251843Sbapt
105251843Sbapt			    memset(&state, 0, sizeof(state));
106251843Sbapt			    wcsrtombs(buffer, &ucp, sizeof(buffer), &state);
107251843Sbapt			    k += wcwidth(uc[0]) - 1;
108251843Sbapt			}
109251843Sbapt		    }
110251843Sbapt		    fputs(buffer, myFP);
111251843Sbapt#else
112251843Sbapt		    ch = mvwinch(win, j, k) & (A_CHARTEXT | A_ALTCHARSET);
113251843Sbapt		    c2 = dlg_asciibox(ch);
114251843Sbapt		    if (c2 != 0) {
115251843Sbapt			ch = c2;
116251843Sbapt		    } else if (unctrl(ch) == 0 || strlen(unctrl(ch)) > 1) {
117251843Sbapt			ch = '.';
118251843Sbapt		    }
119251843Sbapt		    fputc((int) (ch & 0xff), myFP);
120251843Sbapt#endif
121217309Snwhitehorn		}
122251843Sbapt		fputc('\n', myFP);
123217309Snwhitehorn	    }
124251843Sbapt	    wmove(win, y, x);
125251843Sbapt	    fflush(myFP);
126217309Snwhitehorn	}
127217309Snwhitehorn    }
128217309Snwhitehorn}
129217309Snwhitehorn
130217309Snwhitehornvoid
131217309Snwhitehorndlg_trace_chr(int ch, int fkey)
132217309Snwhitehorn{
133251843Sbapt    static int last_err = 0;
134251843Sbapt
135251843Sbapt    /*
136251843Sbapt     * Do not bother to trace ERR's indefinitely, since those are usually due
137251843Sbapt     * to relatively short polling timeouts.
138251843Sbapt     */
139251843Sbapt    if (last_err && !fkey && ch == ERR) {
140251843Sbapt	++last_err;
141251843Sbapt    } else if (myFP != 0) {
142217309Snwhitehorn	const char *fkey_name = "?";
143251843Sbapt
144251843Sbapt	if (last_err) {
145251843Sbapt	    fprintf(myFP, "skipped %d ERR's\n", last_err);
146251843Sbapt	    last_err = 0;
147251843Sbapt	}
148251843Sbapt
149217309Snwhitehorn	if (fkey) {
150217309Snwhitehorn	    if (fkey > KEY_MAX || (fkey_name = keyname(fkey)) == 0) {
151217309Snwhitehorn#define CASE(name) case name: fkey_name = #name; break
152217309Snwhitehorn		switch ((DLG_KEYS_ENUM) fkey) {
153217309Snwhitehorn		    CASE(DLGK_MIN);
154217309Snwhitehorn		    CASE(DLGK_OK);
155217309Snwhitehorn		    CASE(DLGK_CANCEL);
156217309Snwhitehorn		    CASE(DLGK_EXTRA);
157217309Snwhitehorn		    CASE(DLGK_HELP);
158217309Snwhitehorn		    CASE(DLGK_ESC);
159217309Snwhitehorn		    CASE(DLGK_PAGE_FIRST);
160217309Snwhitehorn		    CASE(DLGK_PAGE_LAST);
161217309Snwhitehorn		    CASE(DLGK_PAGE_NEXT);
162217309Snwhitehorn		    CASE(DLGK_PAGE_PREV);
163217309Snwhitehorn		    CASE(DLGK_ITEM_FIRST);
164217309Snwhitehorn		    CASE(DLGK_ITEM_LAST);
165217309Snwhitehorn		    CASE(DLGK_ITEM_NEXT);
166217309Snwhitehorn		    CASE(DLGK_ITEM_PREV);
167217309Snwhitehorn		    CASE(DLGK_FIELD_FIRST);
168217309Snwhitehorn		    CASE(DLGK_FIELD_LAST);
169217309Snwhitehorn		    CASE(DLGK_FIELD_NEXT);
170217309Snwhitehorn		    CASE(DLGK_FIELD_PREV);
171251843Sbapt		    CASE(DLGK_FORM_FIRST);
172251843Sbapt		    CASE(DLGK_FORM_LAST);
173251843Sbapt		    CASE(DLGK_FORM_NEXT);
174251843Sbapt		    CASE(DLGK_FORM_PREV);
175217309Snwhitehorn		    CASE(DLGK_GRID_UP);
176217309Snwhitehorn		    CASE(DLGK_GRID_DOWN);
177217309Snwhitehorn		    CASE(DLGK_GRID_LEFT);
178217309Snwhitehorn		    CASE(DLGK_GRID_RIGHT);
179217309Snwhitehorn		    CASE(DLGK_DELETE_LEFT);
180217309Snwhitehorn		    CASE(DLGK_DELETE_RIGHT);
181217309Snwhitehorn		    CASE(DLGK_DELETE_ALL);
182217309Snwhitehorn		    CASE(DLGK_ENTER);
183217309Snwhitehorn		    CASE(DLGK_BEGIN);
184217309Snwhitehorn		    CASE(DLGK_FINAL);
185217309Snwhitehorn		    CASE(DLGK_SELECT);
186224014Snwhitehorn		    CASE(DLGK_HELPFILE);
187217309Snwhitehorn		    CASE(DLGK_TRACE);
188217309Snwhitehorn		}
189217309Snwhitehorn	    }
190220749Snwhitehorn	} else if (ch == ERR) {
191220749Snwhitehorn	    fkey_name = "ERR";
192251843Sbapt	    last_err = 1;
193217309Snwhitehorn	} else {
194217309Snwhitehorn	    fkey_name = unctrl((chtype) ch);
195217309Snwhitehorn	    if (fkey_name == 0)
196217309Snwhitehorn		fkey_name = "UNKNOWN";
197217309Snwhitehorn	}
198217309Snwhitehorn	fprintf(myFP, "chr %s (ch=%#x, fkey=%d)\n",
199217309Snwhitehorn		fkey_name,
200217309Snwhitehorn		ch, fkey);
201217309Snwhitehorn	fflush(myFP);
202217309Snwhitehorn    }
203217309Snwhitehorn}
204217309Snwhitehorn
205217309Snwhitehornvoid
206217309Snwhitehorndlg_trace(const char *fname)
207217309Snwhitehorn{
208217309Snwhitehorn    if (fname != 0) {
209217309Snwhitehorn	if (myFP == 0) {
210217309Snwhitehorn	    myFP = fopen(fname, "a");
211217309Snwhitehorn	    if (myFP != 0) {
212220749Snwhitehorn		dlg_trace_time("** opened at");
213224014Snwhitehorn		dlg_trace_msg("** dialog %s\n", dialog_version());
214217309Snwhitehorn	    }
215217309Snwhitehorn	}
216217309Snwhitehorn    } else if (myFP != 0) {
217220749Snwhitehorn	dlg_trace_time("** closed at");
218217309Snwhitehorn	fclose(myFP);
219217309Snwhitehorn	myFP = 0;
220217309Snwhitehorn    }
221217309Snwhitehorn}
222217309Snwhitehorn#else
223217309Snwhitehorn#undef dlg_trace
224217309Snwhitehornextern void dlg_trace(const char *);
225217309Snwhitehornvoid
226217309Snwhitehorndlg_trace(const char *fname)
227217309Snwhitehorn{
228217309Snwhitehorn    (void) fname;
229217309Snwhitehorn}
230217309Snwhitehorn#endif
231