ncurses 5.6 - patch 20070414
[ncurses.git] / test / demo_defkey.c
1 /****************************************************************************
2  * Copyright (c) 2002-2006,2007 Free Software Foundation, Inc.              *
3  *                                                                          *
4  * Permission is hereby granted, free of charge, to any person obtaining a  *
5  * copy of this software and associated documentation files (the            *
6  * "Software"), to deal in the Software without restriction, including      *
7  * without limitation the rights to use, copy, modify, merge, publish,      *
8  * distribute, distribute with modifications, sublicense, and/or sell       *
9  * copies of the Software, and to permit persons to whom the Software is    *
10  * furnished to do so, subject to the following conditions:                 *
11  *                                                                          *
12  * The above copyright notice and this permission notice shall be included  *
13  * in all copies or substantial portions of the Software.                   *
14  *                                                                          *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22  *                                                                          *
23  * Except as contained in this notice, the name(s) of the above copyright   *
24  * holders shall not be used in advertising or otherwise to promote the     *
25  * sale, use or other dealings in this Software without prior written       *
26  * authorization.                                                           *
27  ****************************************************************************/
28 /*
29  * $Id: demo_defkey.c,v 1.17 2007/04/07 17:13:03 tom Exp $
30  *
31  * Demonstrate the define_key() function.
32  * Thomas Dickey - 2002/11/23
33  */
34
35 #include <test.priv.h>
36
37 #if defined(NCURSES_VERSION) && NCURSES_EXT_FUNCS
38
39 #define MY_LOGFILE "demo_defkey.log"
40
41 /*
42  * Log the most recently-written line to our logfile
43  */
44 static void
45 log_last_line(WINDOW *win)
46 {
47     FILE *fp;
48     int y, x, n;
49     char temp[256];
50
51     if ((fp = fopen(MY_LOGFILE, "a")) != 0) {
52         int need = sizeof(temp) - 1;
53         if (need > COLS)
54             need = COLS;
55         getyx(win, y, x);
56         wmove(win, y - 1, 0);
57         n = winnstr(win, temp, need);
58         while (n-- > 0) {
59             if (isspace(UChar(temp[n])))
60                 temp[n] = '\0';
61             else
62                 break;
63         }
64         wmove(win, y, x);
65         fprintf(fp, "%s\n", temp);
66         fclose(fp);
67     }
68 }
69
70 /*
71  * Convert a character to visible form.
72  */
73 static char *
74 visichar(int ch)
75 {
76     static char temp[10];
77
78     ch = UChar(ch);
79     if (ch == '\\') {
80         strcpy(temp, "\\\\");
81     } else if (ch == '\033') {
82         strcpy(temp, "\\E");
83     } else if (ch < ' ') {
84         sprintf(temp, "\\%03o", ch);
85     } else if (ch >= 127) {
86         sprintf(temp, "\\%03o", ch);
87     } else {
88         sprintf(temp, "%c", ch);
89     }
90     return temp;
91 }
92
93 /*
94  * Convert a string to visible form.
95  */
96 static char *
97 visible(const char *string)
98 {
99     char *result = 0;
100     unsigned need = 1;
101     int pass;
102     int n;
103
104     if (string != 0 && *string != '\0') {
105         for (pass = 0; pass < 2; ++pass) {
106             for (n = 0; string[n] != '\0'; ++n) {
107                 char temp[80];
108                 strcpy(temp, visichar(string[n]));
109                 if (pass)
110                     strcat(result, temp);
111                 else
112                     need += strlen(temp);
113             }
114             if (!pass)
115                 result = (char *) calloc(need, 1);
116         }
117     } else {
118         result = (char *) calloc(1, 1);
119     }
120     return result;
121 }
122
123 static void
124 really_define_key(WINDOW *win, const char *new_string, int code)
125 {
126     int rc;
127     const char *code_name = keyname(code);
128     char *old_string;
129     char *vis_string = 0;
130     char temp[80];
131
132     if (code_name == 0) {
133         sprintf(temp, "Keycode %d", code);
134         code_name = temp;
135     }
136
137     if ((old_string = keybound(code, 0)) != 0) {
138         wprintw(win, "%s is %s\n",
139                 code_name,
140                 vis_string = visible(old_string));
141     } else {
142         wprintw(win, "%s is not bound\n",
143                 code_name);
144     }
145     log_last_line(win);
146
147     if (vis_string != 0) {
148         free(vis_string);
149         vis_string = 0;
150     }
151
152     vis_string = visible(new_string);
153     if ((rc = key_defined(new_string)) > 0) {
154         wprintw(win, "%s was bound to %s\n", vis_string, keyname(rc));
155         log_last_line(win);
156     } else if (new_string != 0 && rc < 0) {
157         wprintw(win, "%s conflicts with longer strings\n", vis_string);
158         log_last_line(win);
159     }
160     rc = define_key(new_string, code);
161     if (rc == ERR) {
162         wprintw(win, "%s unchanged\n", code_name);
163         log_last_line(win);
164     } else if (new_string != 0) {
165         wprintw(win, "%s is now bound to %s\n",
166                 vis_string,
167                 code_name);
168         log_last_line(win);
169     } else if (old_string != 0) {
170         wprintw(win, "%s deleted\n", code_name);
171         log_last_line(win);
172     }
173     if (vis_string != 0)
174         free(vis_string);
175     if (old_string != 0)
176         free(old_string);
177 }
178
179 static void
180 duplicate(WINDOW *win, NCURSES_CONST char *name, int code)
181 {
182     char *value = tigetstr(name);
183
184     if (value != 0) {
185         const char *prefix = 0;
186         char temp[BUFSIZ];
187
188         if (!strncmp(value, "\033[", 2)) {
189             prefix = "\033O";
190         } else if (!strncmp(value, "\033O", 2)) {
191             prefix = "\033[";
192         }
193         if (prefix != 0) {
194             sprintf(temp, "%s%s", prefix, value + 2);
195             really_define_key(win, temp, code);
196         }
197     }
198 }
199
200 static void
201 redefine(WINDOW *win, char *string, int code)
202 {
203     really_define_key(win, string, code);
204 }
205
206 static void
207 remove_definition(WINDOW *win, int code)
208 {
209     really_define_key(win, 0, code);
210 }
211
212 int
213 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
214 {
215     char *fkeys[12];
216     int n;
217     int ch;
218     WINDOW *win;
219
220     unlink(MY_LOGFILE);
221
222     initscr();
223     (void) cbreak();            /* take input chars one at a time, no wait for \n */
224     (void) noecho();            /* don't echo input */
225
226     printw("This demo is best on xterm: it reverses the definitions for f1-f12,\n");
227     printw("adds duplicate definitions for cursor application and normal modes,\n");
228     printw("and removes any definitions for the mini keypad.  Type any of those:\n");
229     refresh();
230
231     win = newwin(LINES - 3, COLS, 3, 0);
232     scrollok(win, TRUE);
233     keypad(win, TRUE);
234     wmove(win, 0, 0);
235
236     /* we do the define_key() calls after keypad(), since the first call to
237      * keypad() initializes the corresponding data.
238      */
239     for (n = 0; n < 12; ++n) {
240         char name[10];
241         sprintf(name, "kf%d", n + 1);
242         fkeys[n] = tigetstr(name);
243     }
244     for (n = 0; n < 12; ++n) {
245         redefine(win, fkeys[11 - n], KEY_F(n + 1));
246     }
247
248     duplicate(win, "kcub1", KEY_LEFT);
249     duplicate(win, "kcuu1", KEY_UP);
250     duplicate(win, "kcud1", KEY_DOWN);
251     duplicate(win, "kcuf1", KEY_RIGHT);
252
253     remove_definition(win, KEY_A1);
254     remove_definition(win, KEY_A3);
255     remove_definition(win, KEY_B2);
256     remove_definition(win, KEY_C1);
257     remove_definition(win, KEY_C3);
258
259     really_define_key(win, "\033O", 1023);
260
261     while ((ch = wgetch(win)) != ERR) {
262         const char *name = keyname(ch);
263         wprintw(win, "Keycode %d, name %s\n",
264                 ch,
265                 name != 0 ? name : "<null>");
266         log_last_line(win);
267         wclrtoeol(win);
268         if (ch == 'q')
269             break;
270     }
271     endwin();
272     ExitProgram(EXIT_FAILURE);
273 }
274 #else
275 int
276 main(void)
277 {
278     printf("This program requires the ncurses library\n");
279     ExitProgram(EXIT_FAILURE);
280 }
281 #endif