ncurses 5.9 - patch 20150307
[ncurses.git] / test / demo_defkey.c
1 /****************************************************************************
2  * Copyright (c) 2002-2012,2013 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.22 2013/09/28 22:02:17 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     assert(ch >= 0 && ch < 256);
80     if (ch == '\\') {
81         strcpy(temp, "\\\\");
82     } else if (ch == '\033') {
83         strcpy(temp, "\\E");
84     } else if (ch < ' ') {
85         sprintf(temp, "\\%03o", ch);
86     } else if (ch >= 127) {
87         sprintf(temp, "\\%03o", ch);
88     } else {
89         sprintf(temp, "%c", ch);
90     }
91     return temp;
92 }
93
94 /*
95  * Convert a string to visible form.
96  */
97 static char *
98 visible(const char *string)
99 {
100     char *result = 0;
101     size_t need = 1;
102     int pass;
103     int n;
104
105     if (string != 0 && *string != '\0') {
106         for (pass = 0; pass < 2; ++pass) {
107             for (n = 0; string[n] != '\0'; ++n) {
108                 char temp[80];
109                 strncpy(temp, visichar(string[n]), sizeof(temp) - 2);
110                 if (pass)
111                     strcat(result, temp);
112                 else
113                     need += strlen(temp);
114             }
115             if (!pass)
116                 result = typeCalloc(char, need);
117         }
118     } else {
119         result = typeCalloc(char, (size_t) 1);
120     }
121     return result;
122 }
123
124 static void
125 really_define_key(WINDOW *win, const char *new_string, int code)
126 {
127     int rc;
128     const char *code_name = keyname(code);
129     char *old_string;
130     char *vis_string = 0;
131     char temp[80];
132
133     if (code_name == 0) {
134         sprintf(temp, "Keycode %d", code);
135         code_name = temp;
136     }
137
138     if ((old_string = keybound(code, 0)) != 0) {
139         wprintw(win, "%s is %s\n",
140                 code_name,
141                 vis_string = visible(old_string));
142     } else {
143         wprintw(win, "%s is not bound\n",
144                 code_name);
145     }
146     log_last_line(win);
147
148     if (vis_string != 0) {
149         free(vis_string);
150         vis_string = 0;
151     }
152
153     vis_string = visible(new_string);
154     if ((rc = key_defined(new_string)) > 0) {
155         wprintw(win, "%s was bound to %s\n", vis_string, keyname(rc));
156         log_last_line(win);
157     } else if (new_string != 0 && rc < 0) {
158         wprintw(win, "%s conflicts with longer strings\n", vis_string);
159         log_last_line(win);
160     }
161     rc = define_key(new_string, code);
162     if (rc == ERR) {
163         wprintw(win, "%s unchanged\n", code_name);
164         log_last_line(win);
165     } else if (new_string != 0) {
166         wprintw(win, "%s is now bound to %s\n",
167                 vis_string,
168                 code_name);
169         log_last_line(win);
170     } else if (old_string != 0) {
171         wprintw(win, "%s deleted\n", code_name);
172         log_last_line(win);
173     }
174     if (vis_string != 0)
175         free(vis_string);
176     if (old_string != 0)
177         free(old_string);
178 }
179
180 static void
181 duplicate(WINDOW *win, NCURSES_CONST char *name, int code)
182 {
183     char *value = tigetstr(name);
184
185     if (value != 0) {
186         const char *prefix = 0;
187         char temp[BUFSIZ];
188
189         if (!strncmp(value, "\033[", (size_t) 2)) {
190             prefix = "\033O";
191         } else if (!strncmp(value, "\033O", (size_t) 2)) {
192             prefix = "\033[";
193         }
194         if (prefix != 0) {
195             sprintf(temp, "%s%s", prefix, value + 2);
196             really_define_key(win, temp, code);
197         }
198     }
199 }
200
201 static void
202 redefine(WINDOW *win, char *string, int code)
203 {
204     really_define_key(win, string, code);
205 }
206
207 static void
208 remove_definition(WINDOW *win, int code)
209 {
210     really_define_key(win, 0, code);
211 }
212
213 int
214 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
215 {
216     char *fkeys[12];
217     int n;
218     int ch;
219     WINDOW *win;
220
221     unlink(MY_LOGFILE);
222
223     initscr();
224     (void) cbreak();            /* take input chars one at a time, no wait for \n */
225     (void) noecho();            /* don't echo input */
226
227     printw("This demo is best on xterm: it reverses the definitions for f1-f12,\n");
228     printw("adds duplicate definitions for cursor application and normal modes,\n");
229     printw("and removes any definitions for the mini keypad.  Type any of those:\n");
230     refresh();
231
232     win = newwin(LINES - 3, COLS, 3, 0);
233     scrollok(win, TRUE);
234     keypad(win, TRUE);
235     wmove(win, 0, 0);
236
237     /* we do the define_key() calls after keypad(), since the first call to
238      * keypad() initializes the corresponding data.
239      */
240     for (n = 0; n < 12; ++n) {
241         char name[10];
242         sprintf(name, "kf%d", n + 1);
243         fkeys[n] = tigetstr(name);
244     }
245     for (n = 0; n < 12; ++n) {
246         redefine(win, fkeys[11 - n], KEY_F(n + 1));
247     }
248
249     duplicate(win, "kcub1", KEY_LEFT);
250     duplicate(win, "kcuu1", KEY_UP);
251     duplicate(win, "kcud1", KEY_DOWN);
252     duplicate(win, "kcuf1", KEY_RIGHT);
253
254     remove_definition(win, KEY_A1);
255     remove_definition(win, KEY_A3);
256     remove_definition(win, KEY_B2);
257     remove_definition(win, KEY_C1);
258     remove_definition(win, KEY_C3);
259
260     really_define_key(win, "\033O", 1023);
261
262     while ((ch = wgetch(win)) != ERR) {
263         const char *name = keyname(ch);
264         wprintw(win, "Keycode %d, name %s\n",
265                 ch,
266                 name != 0 ? name : "<null>");
267         log_last_line(win);
268         wclrtoeol(win);
269         if (ch == 'q')
270             break;
271     }
272     endwin();
273     ExitProgram(EXIT_FAILURE);
274 }
275 #else
276 int
277 main(void)
278 {
279     printf("This program requires the ncurses library\n");
280     ExitProgram(EXIT_FAILURE);
281 }
282 #endif