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