ncurses 5.6 - patch 20080329
[ncurses.git] / test / inserts.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: inserts.c,v 1.18 2007/07/21 17:41:55 tom Exp $
30  *
31  * Demonstrate the winsstr() and winsch functions.
32  * Thomas Dickey - 2002/10/19
33  */
34
35 #include <test.priv.h>
36
37 #if HAVE_WINSSTR
38
39 #define InsNStr    insnstr
40 #define InsStr     insstr
41 #define MvInsNStr  mvinsnstr
42 #define MvInsStr   mvinsstr
43 #define MvWInsNStr mvwinsnstr
44 #define MvWInsStr  mvwinsstr
45 #define WInsNStr   winsnstr
46 #define WInsStr    winsstr
47
48 #define InsCh      insch
49 #define MvInsCh    mvinsch
50 #define MvWInsCh   mvwinsch
51 #define WInsCh     winsch
52
53 #define MY_TABSIZE 8
54
55 typedef enum {
56     oDefault = 0,
57     oMove = 1,
58     oWindow = 2,
59     oMoveWindow = 3
60 } Options;
61
62 static bool m_opt = FALSE;
63 static bool w_opt = FALSE;
64 static int n_opt = -1;
65
66 static void
67 legend(WINDOW *win, int level, Options state, char *buffer, int length)
68 {
69     NCURSES_CONST char *showstate;
70
71     switch (state) {
72     default:
73     case oDefault:
74         showstate = "";
75         break;
76     case oMove:
77         showstate = " (mvXXX)";
78         break;
79     case oWindow:
80         showstate = " (winXXX)";
81         break;
82     case oMoveWindow:
83         showstate = " (mvwinXXX)";
84         break;
85     }
86
87     wmove(win, 0, 0);
88     wprintw(win,
89             "The Strings/Chars displays should match.  Enter any characters, except:\n");
90     wprintw(win,
91             "down-arrow or ^N to repeat on next line, 'w' for inner window, 'q' to exit.\n");
92     wclrtoeol(win);
93     wprintw(win, "Level %d,%s inserted %d characters <%s>", level,
94             showstate, length, buffer);
95 }
96
97 static int
98 ColOf(char *buffer, int length, int margin)
99 {
100     int n;
101     int result;
102
103     for (n = 0, result = margin + 1; n < length; ++n) {
104         int ch = UChar(buffer[n]);
105         switch (ch) {
106         case '\n':
107             /* actually newline should clear the remainder of the line
108              * and move to the next line - but that seems a little awkward
109              * in this example.
110              */
111         case '\r':
112             result = 0;
113             break;
114         case '\b':
115             if (result > 0)
116                 --result;
117             break;
118         case '\t':
119             result += (MY_TABSIZE - (result % MY_TABSIZE));
120             break;
121         case '\177':
122             result += 2;
123             break;
124         default:
125             ++result;
126             if (ch < 32)
127                 ++result;
128             break;
129         }
130     }
131     return result;
132 }
133
134 #define LEN(n) ((length - (n) > n_opt) ? n_opt : (length - (n)))
135 static void
136 test_inserts(int level)
137 {
138     static bool first = TRUE;
139
140     int ch;
141     int limit;
142     int row = 1;
143     int col;
144     int row2, col2;
145     int length;
146     char buffer[BUFSIZ];
147     WINDOW *look = 0;
148     WINDOW *work = 0;
149     WINDOW *show = 0;
150     int margin = (2 * MY_TABSIZE) - 1;
151     Options option = (Options) ((unsigned) (m_opt
152                                             ? oMove
153                                             : oDefault)
154                                 | (unsigned) ((w_opt || (level > 0))
155                                               ? oWindow
156                                               : oDefault));
157
158     if (first) {
159         static char cmd[80];
160         setlocale(LC_ALL, "");
161
162         putenv(strcpy(cmd, "TABSIZE=8"));
163
164         initscr();
165         (void) cbreak();        /* take input chars one at a time, no wait for \n */
166         (void) noecho();        /* don't echo input */
167         keypad(stdscr, TRUE);
168     }
169
170     limit = LINES - 5;
171     if (level > 0) {
172         look = newwin(limit, COLS - (2 * (level - 1)), 0, level - 1);
173         work = newwin(limit - 2, COLS - (2 * level), 1, level);
174         show = newwin(4, COLS, limit + 1, 0);
175         box(look, 0, 0);
176         wnoutrefresh(look);
177         limit -= 2;
178     } else {
179         work = stdscr;
180         show = derwin(stdscr, 4, COLS, limit + 1, 0);
181     }
182     keypad(work, TRUE);
183
184     for (col = margin + 1; col < COLS; col += MY_TABSIZE)
185         mvwvline(work, row, col, '.', limit - 2);
186
187     mvwvline(work, row, margin, ACS_VLINE, limit - 2);
188     mvwvline(work, row, margin + 1, ACS_VLINE, limit - 2);
189     limit /= 2;
190
191     mvwaddstr(work, 1, 2, "String");
192     mvwaddstr(work, limit + 1, 2, "Chars");
193     wnoutrefresh(work);
194
195     buffer[length = 0] = '\0';
196     legend(show, level, option, buffer, length);
197     wnoutrefresh(show);
198
199     doupdate();
200
201     /*
202      * Show the characters inserted in color, to distinguish from those that
203      * are shifted.
204      */
205     if (has_colors()) {
206         start_color();
207         init_pair(1, COLOR_WHITE, COLOR_BLUE);
208         wbkgdset(work, COLOR_PAIR(1) | ' ');
209     }
210
211     while ((ch = wgetch(work)) != 'q') {
212         if (ch == ERR) {
213             beep();
214             break;
215         }
216         wmove(work, row, margin + 1);
217         switch (ch) {
218         case 'w':
219             test_inserts(level + 1);
220
221             touchwin(look);
222             touchwin(work);
223             touchwin(show);
224
225             wnoutrefresh(look);
226             wnoutrefresh(work);
227             wnoutrefresh(show);
228
229             doupdate();
230             break;
231         case CTRL('N'):
232         case KEY_DOWN:
233             if (row < limit) {
234                 ++row;
235                 /* put the whole string in, all at once */
236                 col2 = margin + 1;
237                 switch (option) {
238                 case oDefault:
239                     if (n_opt > 1) {
240                         for (col = 0; col < length; col += n_opt) {
241                             col2 = ColOf(buffer, col, margin);
242                             if (move(row, col2) != ERR) {
243                                 InsNStr(buffer + col, LEN(col));
244                             }
245                         }
246                     } else {
247                         if (move(row, col2) != ERR) {
248                             InsStr(buffer);
249                         }
250                     }
251                     break;
252                 case oMove:
253                     if (n_opt > 1) {
254                         for (col = 0; col < length; col += n_opt) {
255                             col2 = ColOf(buffer, col, margin);
256                             MvInsNStr(row, col2, buffer + col, LEN(col));
257                         }
258                     } else {
259                         MvInsStr(row, col2, buffer);
260                     }
261                     break;
262                 case oWindow:
263                     if (n_opt > 1) {
264                         for (col = 0; col < length; col += n_opt) {
265                             col2 = ColOf(buffer, col, margin);
266                             if (wmove(work, row, col2) != ERR) {
267                                 WInsNStr(work, buffer + col, LEN(col));
268                             }
269                         }
270                     } else {
271                         if (wmove(work, row, col2) != ERR) {
272                             WInsStr(work, buffer);
273                         }
274                     }
275                     break;
276                 case oMoveWindow:
277                     if (n_opt > 1) {
278                         for (col = 0; col < length; col += n_opt) {
279                             col2 = ColOf(buffer, col, margin);
280                             MvWInsNStr(work, row, col2, buffer + col, LEN(col));
281                         }
282                     } else {
283                         MvWInsStr(work, row, col2, buffer);
284                     }
285                     break;
286                 }
287
288                 /* do the corresponding single-character insertion */
289                 row2 = limit + row;
290                 for (col = 0; col < length; ++col) {
291                     col2 = ColOf(buffer, col, margin);
292                     switch (option) {
293                     case oDefault:
294                         if (move(row2, col2) != ERR) {
295                             InsCh(UChar(buffer[col]));
296                         }
297                         break;
298                     case oMove:
299                         MvInsCh(row2, col2, UChar(buffer[col]));
300                         break;
301                     case oWindow:
302                         if (wmove(work, row2, col2) != ERR) {
303                             WInsCh(work, UChar(buffer[col]));
304                         }
305                         break;
306                     case oMoveWindow:
307                         MvWInsCh(work, row2, col2, UChar(buffer[col]));
308                         break;
309                     }
310                 }
311             } else {
312                 beep();
313             }
314             break;
315         case KEY_BACKSPACE:
316             ch = '\b';
317             /* FALLTHRU */
318         default:
319             if (ch <= 0 || ch > 255) {
320                 beep();
321                 break;
322             }
323             buffer[length++] = ch;
324             buffer[length] = '\0';
325
326             /* put the string in, one character at a time */
327             col = ColOf(buffer, length - 1, margin);
328             switch (option) {
329             case oDefault:
330                 if (move(row, col) != ERR) {
331                     InsStr(buffer + length - 1);
332                 }
333                 break;
334             case oMove:
335                 MvInsStr(row, col, buffer + length - 1);
336                 break;
337             case oWindow:
338                 if (wmove(work, row, col) != ERR) {
339                     WInsStr(work, buffer + length - 1);
340                 }
341                 break;
342             case oMoveWindow:
343                 MvWInsStr(work, row, col, buffer + length - 1);
344                 break;
345             }
346
347             /* do the corresponding single-character insertion */
348             switch (option) {
349             case oDefault:
350                 if (move(limit + row, col) != ERR) {
351                     InsCh(UChar(ch));
352                 }
353                 break;
354             case oMove:
355                 MvInsCh(limit + row, col, UChar(ch));
356                 break;
357             case oWindow:
358                 if (wmove(work, limit + row, col) != ERR) {
359                     WInsCh(work, UChar(ch));
360                 }
361                 break;
362             case oMoveWindow:
363                 MvWInsCh(work, limit + row, col, UChar(ch));
364                 break;
365             }
366
367             wnoutrefresh(work);
368
369             legend(show, level, option, buffer, length);
370             wnoutrefresh(show);
371
372             doupdate();
373             break;
374         }
375     }
376     if (level > 0) {
377         delwin(show);
378         delwin(work);
379         delwin(look);
380     }
381 }
382
383 static void
384 usage(void)
385 {
386     static const char *tbl[] =
387     {
388         "Usage: inserts [options]"
389         ,""
390         ,"Options:"
391         ,"  -n NUM  limit string-inserts to NUM bytes on ^N replay"
392         ,"  -m      perform wmove/move separately from insert-functions"
393         ,"  -w      use window-parameter even when stdscr would be implied"
394     };
395     unsigned n;
396     for (n = 0; n < SIZEOF(tbl); ++n)
397         fprintf(stderr, "%s\n", tbl[n]);
398     ExitProgram(EXIT_FAILURE);
399 }
400
401 int
402 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
403 {
404     int ch;
405
406     setlocale(LC_ALL, "");
407
408     while ((ch = getopt(argc, argv, "mn:w")) != -1) {
409         switch (ch) {
410         case 'm':
411             m_opt = TRUE;
412             break;
413         case 'n':
414             n_opt = atoi(optarg);
415             if (n_opt == 0)
416                 n_opt = -1;
417             break;
418         case 'w':
419             w_opt = TRUE;
420             break;
421         default:
422             usage();
423             break;
424         }
425     }
426     if (optind < argc)
427         usage();
428
429     test_inserts(0);
430     endwin();
431     ExitProgram(EXIT_SUCCESS);
432 }
433 #else
434 int
435 main(void)
436 {
437     printf("This program requires the winsstr function\n");
438     ExitProgram(EXIT_FAILURE);
439 }
440 #endif /* HAVE_WINSSTR */