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