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