15382d832SPeter Avalos /*
2*a8e38dc0SAntonio Huete Jimenez * $Id: trace.c,v 1.34 2022/04/03 22:38:16 tom Exp $
35382d832SPeter Avalos *
45382d832SPeter Avalos * trace.c -- implements screen-dump and keystroke-logging
55382d832SPeter Avalos *
6*a8e38dc0SAntonio Huete Jimenez * Copyright 2007-2020,2022 Thomas E. Dickey
75382d832SPeter Avalos *
85382d832SPeter Avalos * This program is free software; you can redistribute it and/or modify
95382d832SPeter Avalos * it under the terms of the GNU Lesser General Public License, version 2.1
105940c9abSDaniel Fojt * as published by the Free Software Foundation.
115382d832SPeter Avalos *
125382d832SPeter Avalos * This program is distributed in the hope that it will be useful, but
135382d832SPeter Avalos * WITHOUT ANY WARRANTY; without even the implied warranty of
145382d832SPeter Avalos * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
155382d832SPeter Avalos * Lesser General Public License for more details.
165382d832SPeter Avalos *
175382d832SPeter Avalos * You should have received a copy of the GNU Lesser General Public
185382d832SPeter Avalos * License along with this program; if not, write to
195382d832SPeter Avalos * Free Software Foundation, Inc.
205382d832SPeter Avalos * 51 Franklin St., Fifth Floor
215382d832SPeter Avalos * Boston, MA 02110, USA.
225382d832SPeter Avalos */
235382d832SPeter Avalos
24*a8e38dc0SAntonio Huete Jimenez #include <dlg_internals.h>
255382d832SPeter Avalos
265382d832SPeter Avalos #ifdef HAVE_DLG_TRACE
275382d832SPeter Avalos
285382d832SPeter Avalos #include <dlg_keys.h>
295382d832SPeter Avalos
305382d832SPeter Avalos #define myFP dialog_state.trace_output
315382d832SPeter Avalos
325382d832SPeter Avalos static void
dlg_trace_time(const char * tag)335382d832SPeter Avalos dlg_trace_time(const char *tag)
345382d832SPeter Avalos {
355382d832SPeter Avalos time_t now = time((time_t *) 0);
365382d832SPeter Avalos fprintf(myFP, "%s %s", tag, ctime(&now));
375382d832SPeter Avalos }
385382d832SPeter Avalos
395382d832SPeter Avalos void
dlg_trace_msg(const char * fmt,...)405382d832SPeter Avalos dlg_trace_msg(const char *fmt, ...)
415382d832SPeter Avalos {
425382d832SPeter Avalos if (myFP != 0) {
435382d832SPeter Avalos va_list ap;
445382d832SPeter Avalos va_start(ap, fmt);
455382d832SPeter Avalos vfprintf(myFP, fmt, ap);
465382d832SPeter Avalos va_end(ap);
475382d832SPeter Avalos fflush(myFP);
485382d832SPeter Avalos }
495382d832SPeter Avalos }
505382d832SPeter Avalos
515382d832SPeter Avalos void
dlg_trace_va_msg(const char * fmt,va_list ap)525940c9abSDaniel Fojt dlg_trace_va_msg(const char *fmt, va_list ap)
535940c9abSDaniel Fojt {
545940c9abSDaniel Fojt if (myFP != 0) {
555940c9abSDaniel Fojt vfprintf(myFP, fmt, ap);
565940c9abSDaniel Fojt fflush(myFP);
575940c9abSDaniel Fojt }
585940c9abSDaniel Fojt }
595940c9abSDaniel Fojt
605940c9abSDaniel Fojt void
dlg_trace_2s(const char * name,const char * value)615940c9abSDaniel Fojt dlg_trace_2s(const char *name, const char *value)
625940c9abSDaniel Fojt {
635940c9abSDaniel Fojt bool first = TRUE;
645940c9abSDaniel Fojt int left, right = 0;
655940c9abSDaniel Fojt
665940c9abSDaniel Fojt if (value == 0)
675940c9abSDaniel Fojt value = "<NULL>";
685940c9abSDaniel Fojt
695940c9abSDaniel Fojt while (value[right] != '\0') {
705940c9abSDaniel Fojt const char *next;
715940c9abSDaniel Fojt
725940c9abSDaniel Fojt value += right;
735940c9abSDaniel Fojt if ((next = strchr(value, '\n')) != 0) {
745940c9abSDaniel Fojt left = (int) (next - value);
755940c9abSDaniel Fojt right = left + 1;
765940c9abSDaniel Fojt } else {
775940c9abSDaniel Fojt left = (int) strlen(value);
785940c9abSDaniel Fojt right = left;
795940c9abSDaniel Fojt }
805940c9abSDaniel Fojt if (first) {
815940c9abSDaniel Fojt first = FALSE;
825940c9abSDaniel Fojt dlg_trace_msg("#%14s = %.*s\n", name, left, value);
835940c9abSDaniel Fojt } else {
84*a8e38dc0SAntonio Huete Jimenez dlg_trace_msg("#+%13s%.*s\n", " ", left, value);
855940c9abSDaniel Fojt }
865940c9abSDaniel Fojt }
875940c9abSDaniel Fojt }
885940c9abSDaniel Fojt
895940c9abSDaniel Fojt void
dlg_trace_2n(const char * name,int value)905940c9abSDaniel Fojt dlg_trace_2n(const char *name, int value)
915940c9abSDaniel Fojt {
92*a8e38dc0SAntonio Huete Jimenez dlg_trace_msg("#%14s = %d\n", name, value);
935940c9abSDaniel Fojt }
945940c9abSDaniel Fojt
955940c9abSDaniel Fojt void
dlg_trace_win(WINDOW * win)965382d832SPeter Avalos dlg_trace_win(WINDOW *win)
975382d832SPeter Avalos {
985382d832SPeter Avalos if (myFP != 0) {
995382d832SPeter Avalos WINDOW *top = wgetparent(win);
1005382d832SPeter Avalos
1015382d832SPeter Avalos while (top != 0 && top != stdscr) {
1025382d832SPeter Avalos win = top;
1035382d832SPeter Avalos top = wgetparent(win);
1045382d832SPeter Avalos }
1055382d832SPeter Avalos
1065382d832SPeter Avalos if (win != 0) {
1075382d832SPeter Avalos int rc = getmaxy(win);
1085382d832SPeter Avalos int cc = getmaxx(win);
1095382d832SPeter Avalos chtype ch, c2;
1105940c9abSDaniel Fojt int y, x;
1115940c9abSDaniel Fojt int j, k;
1125382d832SPeter Avalos
1135382d832SPeter Avalos fprintf(myFP, "window %dx%d at %d,%d\n",
1145382d832SPeter Avalos rc, cc, getbegy(win), getbegx(win));
1155382d832SPeter Avalos
1165382d832SPeter Avalos getyx(win, y, x);
1175382d832SPeter Avalos for (j = 0; j < rc; ++j) {
1185382d832SPeter Avalos fprintf(myFP, "%3d:", j);
1195382d832SPeter Avalos for (k = 0; k < cc; ++k) {
1205382d832SPeter Avalos #ifdef USE_WIDE_CURSES
1215382d832SPeter Avalos char buffer[80];
1225382d832SPeter Avalos
1235382d832SPeter Avalos ch = mvwinch(win, j, k) & (A_CHARTEXT | A_ALTCHARSET);
1245382d832SPeter Avalos if (ch & A_ALTCHARSET) {
1255382d832SPeter Avalos c2 = dlg_asciibox(ch);
1265382d832SPeter Avalos if (c2 != 0) {
1275382d832SPeter Avalos ch = c2;
1285382d832SPeter Avalos }
1295382d832SPeter Avalos buffer[0] = (char) ch;
1305382d832SPeter Avalos buffer[1] = '\0';
1315382d832SPeter Avalos } else {
1325382d832SPeter Avalos cchar_t cch;
1335940c9abSDaniel Fojt const wchar_t *uc;
1345382d832SPeter Avalos
1355382d832SPeter Avalos if (win_wch(win, &cch) == ERR
1361ef6786aSJohn Marino || (uc = wunctrl((&cch))) == 0
1375382d832SPeter Avalos || uc[1] != 0
1385382d832SPeter Avalos || wcwidth(uc[0]) <= 0) {
1395382d832SPeter Avalos buffer[0] = '.';
1405382d832SPeter Avalos buffer[1] = '\0';
1415382d832SPeter Avalos } else {
1425382d832SPeter Avalos mbstate_t state;
1435382d832SPeter Avalos const wchar_t *ucp = uc;
1445382d832SPeter Avalos
1455382d832SPeter Avalos memset(&state, 0, sizeof(state));
1465382d832SPeter Avalos wcsrtombs(buffer, &ucp, sizeof(buffer), &state);
1475382d832SPeter Avalos k += wcwidth(uc[0]) - 1;
1485382d832SPeter Avalos }
1495382d832SPeter Avalos }
1505382d832SPeter Avalos fputs(buffer, myFP);
1515382d832SPeter Avalos #else
1525382d832SPeter Avalos ch = mvwinch(win, j, k) & (A_CHARTEXT | A_ALTCHARSET);
1535382d832SPeter Avalos c2 = dlg_asciibox(ch);
1545382d832SPeter Avalos if (c2 != 0) {
1555382d832SPeter Avalos ch = c2;
1565382d832SPeter Avalos } else if (unctrl(ch) == 0 || strlen(unctrl(ch)) > 1) {
1575382d832SPeter Avalos ch = '.';
1585382d832SPeter Avalos }
1595382d832SPeter Avalos fputc((int) (ch & 0xff), myFP);
1605382d832SPeter Avalos #endif
1615382d832SPeter Avalos }
1625382d832SPeter Avalos fputc('\n', myFP);
1635382d832SPeter Avalos }
1645382d832SPeter Avalos wmove(win, y, x);
1655382d832SPeter Avalos fflush(myFP);
1665382d832SPeter Avalos }
1675382d832SPeter Avalos }
1685382d832SPeter Avalos }
1695382d832SPeter Avalos
1705382d832SPeter Avalos void
dlg_trace_chr(int ch,int fkey)1715382d832SPeter Avalos dlg_trace_chr(int ch, int fkey)
1725382d832SPeter Avalos {
1735382d832SPeter Avalos static int last_err = 0;
1745382d832SPeter Avalos
1755382d832SPeter Avalos /*
1765382d832SPeter Avalos * Do not bother to trace ERR's indefinitely, since those are usually due
1775382d832SPeter Avalos * to relatively short polling timeouts.
1785382d832SPeter Avalos */
1795382d832SPeter Avalos if (last_err && !fkey && ch == ERR) {
1805382d832SPeter Avalos ++last_err;
1815382d832SPeter Avalos } else if (myFP != 0) {
1825382d832SPeter Avalos const char *fkey_name = "?";
1835382d832SPeter Avalos
1845382d832SPeter Avalos if (last_err) {
1855382d832SPeter Avalos fprintf(myFP, "skipped %d ERR's\n", last_err);
1865382d832SPeter Avalos last_err = 0;
1875382d832SPeter Avalos }
1885382d832SPeter Avalos
1895382d832SPeter Avalos if (fkey) {
1905382d832SPeter Avalos if (fkey > KEY_MAX || (fkey_name = keyname(fkey)) == 0) {
1915382d832SPeter Avalos #define CASE(name) case name: fkey_name = #name; break
1925382d832SPeter Avalos switch ((DLG_KEYS_ENUM) fkey) {
1935382d832SPeter Avalos CASE(DLGK_MIN);
1945382d832SPeter Avalos CASE(DLGK_OK);
1955382d832SPeter Avalos CASE(DLGK_CANCEL);
1965382d832SPeter Avalos CASE(DLGK_EXTRA);
1975382d832SPeter Avalos CASE(DLGK_HELP);
1985382d832SPeter Avalos CASE(DLGK_ESC);
1995382d832SPeter Avalos CASE(DLGK_PAGE_FIRST);
2005382d832SPeter Avalos CASE(DLGK_PAGE_LAST);
2015382d832SPeter Avalos CASE(DLGK_PAGE_NEXT);
2025382d832SPeter Avalos CASE(DLGK_PAGE_PREV);
2035382d832SPeter Avalos CASE(DLGK_ITEM_FIRST);
2045382d832SPeter Avalos CASE(DLGK_ITEM_LAST);
2055382d832SPeter Avalos CASE(DLGK_ITEM_NEXT);
2065382d832SPeter Avalos CASE(DLGK_ITEM_PREV);
2075382d832SPeter Avalos CASE(DLGK_FIELD_FIRST);
2085382d832SPeter Avalos CASE(DLGK_FIELD_LAST);
2095382d832SPeter Avalos CASE(DLGK_FIELD_NEXT);
2105382d832SPeter Avalos CASE(DLGK_FIELD_PREV);
2115382d832SPeter Avalos CASE(DLGK_FORM_FIRST);
2125382d832SPeter Avalos CASE(DLGK_FORM_LAST);
2135382d832SPeter Avalos CASE(DLGK_FORM_NEXT);
2145382d832SPeter Avalos CASE(DLGK_FORM_PREV);
2155382d832SPeter Avalos CASE(DLGK_GRID_UP);
2165382d832SPeter Avalos CASE(DLGK_GRID_DOWN);
2175382d832SPeter Avalos CASE(DLGK_GRID_LEFT);
2185382d832SPeter Avalos CASE(DLGK_GRID_RIGHT);
2195382d832SPeter Avalos CASE(DLGK_DELETE_LEFT);
2205382d832SPeter Avalos CASE(DLGK_DELETE_RIGHT);
2215382d832SPeter Avalos CASE(DLGK_DELETE_ALL);
2225382d832SPeter Avalos CASE(DLGK_ENTER);
2235382d832SPeter Avalos CASE(DLGK_BEGIN);
2245382d832SPeter Avalos CASE(DLGK_FINAL);
2255382d832SPeter Avalos CASE(DLGK_SELECT);
2265382d832SPeter Avalos CASE(DLGK_HELPFILE);
2275382d832SPeter Avalos CASE(DLGK_TRACE);
2285940c9abSDaniel Fojt CASE(DLGK_TOGGLE);
229*a8e38dc0SAntonio Huete Jimenez CASE(DLGK_LEAVE);
2305382d832SPeter Avalos }
2315382d832SPeter Avalos }
2325382d832SPeter Avalos } else if (ch == ERR) {
2335382d832SPeter Avalos fkey_name = "ERR";
2345382d832SPeter Avalos last_err = 1;
2355382d832SPeter Avalos } else {
2365382d832SPeter Avalos fkey_name = unctrl((chtype) ch);
2375382d832SPeter Avalos if (fkey_name == 0)
2385382d832SPeter Avalos fkey_name = "UNKNOWN";
2395382d832SPeter Avalos }
2405940c9abSDaniel Fojt if (ch >= 0) {
2415940c9abSDaniel Fojt fprintf(myFP, "chr %s (ch=%#x, fkey=%d)\n", fkey_name, ch, fkey);
2425940c9abSDaniel Fojt } else {
2435940c9abSDaniel Fojt fprintf(myFP, "chr %s (ch=%d, fkey=%d)\n", fkey_name, ch, fkey);
2445940c9abSDaniel Fojt }
2455382d832SPeter Avalos fflush(myFP);
2465382d832SPeter Avalos }
2475382d832SPeter Avalos }
2485382d832SPeter Avalos
2495382d832SPeter Avalos void
dlg_trace(const char * fname)2505382d832SPeter Avalos dlg_trace(const char *fname)
2515382d832SPeter Avalos {
2525382d832SPeter Avalos if (fname != 0) {
2535382d832SPeter Avalos if (myFP == 0) {
2545382d832SPeter Avalos myFP = fopen(fname, "a");
2555382d832SPeter Avalos if (myFP != 0) {
2565940c9abSDaniel Fojt dlg_trace_time("## opened at");
2575940c9abSDaniel Fojt DLG_TRACE(("## dialog %s\n", dialog_version()));
2585940c9abSDaniel Fojt DLG_TRACE(("## vile: confmode\n"));
2595382d832SPeter Avalos }
2605382d832SPeter Avalos }
2615382d832SPeter Avalos } else if (myFP != 0) {
2625940c9abSDaniel Fojt dlg_trace_time("## closed at");
2635382d832SPeter Avalos fclose(myFP);
2645382d832SPeter Avalos myFP = 0;
2655382d832SPeter Avalos }
2665382d832SPeter Avalos }
2675382d832SPeter Avalos #else
2685382d832SPeter Avalos #undef dlg_trace
2695382d832SPeter Avalos extern void dlg_trace(const char *);
2705382d832SPeter Avalos void
dlg_trace(const char * fname)2715382d832SPeter Avalos dlg_trace(const char *fname)
2725382d832SPeter Avalos {
2735382d832SPeter Avalos (void) fname;
2745382d832SPeter Avalos }
2755382d832SPeter Avalos #endif
276