1/*
2 * $Id: demo_defkey.c,v 1.13 2004/01/04 00:01:13 tom Exp $
3 *
4 * Demonstrate the define_key() function.
5 * Thomas Dickey - 2002/11/23
6 */
7
8#include <test.priv.h>
9
10#if defined(NCURSES_VERSION) && NCURSES_EXT_FUNCS
11
12#include <term.h>
13
14#define MY_LOGFILE "demo_defkey.log"
15
16/*
17 * Log the most recently-written line to our logfile
18 */
19static void
20log_last_line(WINDOW *win)
21{
22    FILE *fp;
23    int y, x, n;
24    char temp[256];
25
26    if ((fp = fopen(MY_LOGFILE, "a")) != 0) {
27	getyx(win, y, x);
28	wmove(win, y - 1, 0);
29	n = winnstr(win, temp, sizeof(temp));
30	while (n-- > 0) {
31	    if (isspace(UChar(temp[n])))
32		temp[n] = '\0';
33	    else
34		break;
35	}
36	wmove(win, y, x);
37	fprintf(fp, "%s\n", temp);
38	fclose(fp);
39    }
40}
41
42/*
43 * Convert a character to visible form.
44 */
45static char *
46visichar(int ch)
47{
48    static char temp[10];
49
50    ch = UChar(ch);
51    if (ch == '\\') {
52	strcpy(temp, "\\\\");
53    } else if (ch == '\033') {
54	strcpy(temp, "\\E");
55    } else if (ch < ' ') {
56	sprintf(temp, "\\%03o", ch);
57    } else if (ch >= 127) {
58	sprintf(temp, "\\%03o", ch);
59    } else {
60	sprintf(temp, "%c", ch);
61    }
62    return temp;
63}
64
65/*
66 * Convert a string to visible form.
67 */
68static char *
69visible(const char *string)
70{
71    char *result = 0;
72    unsigned need = 1;
73    int pass;
74    int n;
75
76    if (string != 0 && *string != '\0') {
77	for (pass = 0; pass < 2; ++pass) {
78	    for (n = 0; string[n] != '\0'; ++n) {
79		char temp[80];
80		strcpy(temp, visichar(string[n]));
81		if (pass)
82		    strcat(result, temp);
83		else
84		    need += strlen(temp);
85	    }
86	    if (!pass)
87		result = (char *) calloc(need, 1);
88	}
89    } else {
90	result = (char *) calloc(1, 1);
91    }
92    return result;
93}
94
95static void
96really_define_key(WINDOW *win, const char *new_string, int code)
97{
98    int rc;
99    const char *code_name = keyname(code);
100    char *old_string;
101    char *vis_string = 0;
102    char temp[80];
103
104    if (code_name == 0) {
105	sprintf(temp, "Keycode %d", code);
106	code_name = temp;
107    }
108
109    if ((old_string = keybound(code, 0)) != 0) {
110	wprintw(win, "%s is %s\n",
111		code_name,
112		vis_string = visible(old_string));
113    } else {
114	wprintw(win, "%s is not bound\n",
115		code_name);
116    }
117    log_last_line(win);
118    if (vis_string != 0) {
119	free(vis_string);
120	vis_string = 0;
121    }
122
123    vis_string = visible(new_string);
124    if ((rc = key_defined(new_string)) > 0) {
125	wprintw(win, "%s was bound to %s\n", vis_string, keyname(rc));
126	log_last_line(win);
127    } else if (new_string != 0 && rc < 0) {
128	wprintw(win, "%s conflicts with longer strings\n", vis_string);
129	log_last_line(win);
130    }
131    rc = define_key(new_string, code);
132    if (rc == ERR) {
133	wprintw(win, "%s unchanged\n", code_name);
134	log_last_line(win);
135    } else if (new_string != 0) {
136	wprintw(win, "%s is now bound to %s\n",
137		vis_string,
138		code_name);
139	log_last_line(win);
140    } else if (old_string != 0) {
141	wprintw(win, "%s deleted\n", code_name);
142	log_last_line(win);
143    }
144    if (vis_string != 0 && *vis_string != 0)
145	free(vis_string);
146    if (old_string != 0)
147	free(old_string);
148}
149
150static void
151duplicate(WINDOW *win, NCURSES_CONST char *name, int code)
152{
153    char *value = tigetstr(name);
154
155    if (value != 0) {
156	const char *prefix = 0;
157	char temp[BUFSIZ];
158
159	if (!strncmp(value, "\033[", 2)) {
160	    prefix = "\033O";
161	} else if (!strncmp(value, "\033O", 2)) {
162	    prefix = "\033[";
163	}
164	if (prefix != 0) {
165	    sprintf(temp, "%s%s", prefix, value + 2);
166	    really_define_key(win, temp, code);
167	}
168    }
169}
170
171static void
172redefine(WINDOW *win, char *string, int code)
173{
174    really_define_key(win, string, code);
175}
176
177static void
178remove_definition(WINDOW *win, int code)
179{
180    really_define_key(win, 0, code);
181}
182
183int
184main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
185{
186    char *fkeys[12];
187    int n;
188    int ch;
189    WINDOW *win;
190
191    unlink(MY_LOGFILE);
192
193    initscr();
194    (void) cbreak();		/* take input chars one at a time, no wait for \n */
195    (void) noecho();		/* don't echo input */
196
197    printw("This demo is best on xterm: it reverses the definitions for f1-f12,\n");
198    printw("adds duplicate definitions for cursor application and normal modes,\n");
199    printw("and removes any definitions for the mini keypad.  Type any of those:\n");
200    refresh();
201
202    win = newwin(LINES - 3, COLS, 3, 0);
203    scrollok(win, TRUE);
204    keypad(win, TRUE);
205    wmove(win, 0, 0);
206
207    /* we do the define_key() calls after keypad(), since the first call to
208     * keypad() initializes the corresponding data.
209     */
210    for (n = 0; n < 12; ++n) {
211	char name[10];
212	sprintf(name, "kf%d", n + 1);
213	fkeys[n] = tigetstr(name);
214    }
215    for (n = 0; n < 12; ++n) {
216	redefine(win, fkeys[11 - n], KEY_F(n + 1));
217    }
218
219    duplicate(win, "kcub1", KEY_LEFT);
220    duplicate(win, "kcuu1", KEY_UP);
221    duplicate(win, "kcud1", KEY_DOWN);
222    duplicate(win, "kcuf1", KEY_RIGHT);
223
224    remove_definition(win, KEY_A1);
225    remove_definition(win, KEY_A3);
226    remove_definition(win, KEY_B2);
227    remove_definition(win, KEY_C1);
228    remove_definition(win, KEY_C3);
229
230    really_define_key(win, "\033O", 1023);
231
232    while ((ch = wgetch(win)) != ERR) {
233	const char *name = keyname(ch);
234	wprintw(win, "Keycode %d, name %s\n",
235		ch,
236		name != 0 ? name : "<null>");
237	log_last_line(win);
238	wclrtoeol(win);
239    }
240    endwin();
241    return EXIT_SUCCESS;
242}
243#else
244int
245main(void)
246{
247    printf("This program requires the ncurses library\n");
248    ExitProgram(EXIT_FAILURE);
249}
250#endif
251