ncurses 6.0 - patch 20171223
[ncurses.git] / test / insdelln.c
1 /****************************************************************************
2  * Copyright (c) 2008-2014,2017 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: insdelln.c,v 1.12 2017/09/07 08:24:24 tom Exp $
30  *
31  * test-driver for deleteln, wdeleteln, insdelln, winsdelln, insertln, winsertln
32  */
33
34 #include <test.priv.h>
35
36 #if HAVE_WINSDELLN
37
38 #include <popup_msg.h>
39
40 #define SHOW(n) ((n) == ERR ? "ERR" : "OK")
41 #define COLOR_DEFAULT (-1)
42
43 typedef struct {
44     unsigned c;
45     unsigned v;
46     int pair;
47     unsigned attr;
48     int count;
49     int ch;
50     const char *c_msg;
51     const char *v_msg;
52     int y_val;
53     int x_val;
54     int y_beg, x_beg;
55     int y_max, x_max;
56 } STATUS;
57
58 static const char *
59 color_params(unsigned state, int *pair)
60 {
61     /* *INDENT-OFF* */
62     static struct {
63         short pair;
64         short fg, bg;
65         const char *msg;
66     } table[] = {
67         { 0, COLOR_DEFAULT, COLOR_DEFAULT, "default" },
68         { 1, COLOR_RED,     COLOR_BLACK,   "red/black" },
69         { 2, COLOR_WHITE,   COLOR_BLUE,    "white/blue" },
70     };
71     /* *INDENT-ON* */
72
73     static bool first = TRUE;
74     const char *result = 0;
75
76     if (has_colors()) {
77         if (first) {
78             unsigned n;
79
80             start_color();
81             for (n = 0; n < SIZEOF(table); ++n) {
82                 init_pair(table[n].pair, table[n].fg, table[n].bg);
83             }
84         }
85         if (state < SIZEOF(table)) {
86             *pair = table[state].pair;
87             result = table[state].msg;
88         }
89     }
90     return result;
91 }
92
93 static const char *
94 video_params(unsigned state, unsigned *attr)
95 {
96     /* *INDENT-OFF* */
97     static struct {
98         unsigned attr;
99         const char *msg;
100     } table[] = {
101         { A_NORMAL,     "normal" },
102         { A_BOLD,       "bold" },
103         { A_REVERSE,    "reverse" },
104         { A_UNDERLINE,  "underline" },
105         { A_BLINK,      "blink" },
106     };
107     /* *INDENT-ON* */
108
109     const char *result = 0;
110
111     if (state < SIZEOF(table)) {
112         *attr = table[state].attr;
113         result = table[state].msg;
114     }
115     return result;
116 }
117
118 /* fill the window with a test-pattern */
119 static void
120 fill_window(WINDOW *win)
121 {
122     int y, x;
123     int y0 = -1, x0 = -1;
124
125     getyx(win, y, x);
126     wmove(win, 0, 0);
127     while (waddstr(win, "0123456789 abcdefghijklmnopqrstuvwxyz ") != ERR) {
128         int y1, x1;
129         getyx(win, y1, x1);
130         if (y1 == y0 && x1 == x0)
131             break;
132         x0 = x1;
133         y0 = y1;
134     }
135     wmove(win, y, x);
136 }
137
138 static void
139 show_status(WINDOW *win, STATUS * sp)
140 {
141     int y, x;
142
143     getyx(win, y, x);
144     wmove(win, 0, 0);
145     wprintw(win, "Count %d", sp->count);
146     if (sp->v_msg != 0)
147         wprintw(win, " Video %s", sp->v_msg);
148     if (sp->c_msg != 0)
149         wprintw(win, " Color %s", sp->c_msg);
150     wclrtoeol(win);
151     wmove(win, y, x);
152 }
153
154 static void
155 reshow_status(WINDOW *win, STATUS * sp)
156 {
157     fill_window(win);
158     show_status(win, sp);
159 }
160
161 static void
162 do_subwindow(WINDOW *win, STATUS * sp, void func(WINDOW *))
163 {
164     WINDOW *win1 = newwin(sp->y_max - 2, sp->x_max - 2,
165                           sp->y_beg + 1, sp->x_beg + 1);
166
167     if (win1 != 0 && sp->y_max > 4 && sp->x_max > 4) {
168         WINDOW *win2 = derwin(win1, sp->y_max - 4, sp->x_max - 4, 1, 1);
169
170         if (win2 != 0) {
171             box(win1, 0, 0);
172             wrefresh(win1);
173             func(win2);
174
175             delwin(win2);
176         } else {
177             beep();
178         }
179         delwin(win1);
180         touchwin(win);
181     } else {
182         if (win1)
183             delwin(win1);
184         beep();
185     }
186 }
187
188 static void
189 init_status(WINDOW *win, STATUS * sp)
190 {
191     memset(sp, 0, sizeof(*sp));
192     sp->c = 99;
193     sp->v = 99;
194     sp->ch = ' ';
195
196     keypad(win, TRUE);
197     fill_window(win);
198
199     getbegyx(win, sp->y_beg, sp->x_beg);
200     getmaxyx(win, sp->y_max, sp->x_max);
201 }
202
203 static void
204 show_help(WINDOW *win)
205 {
206     static const char *table[] =
207     {
208         "Basic commands:"
209         ,"Use h/j/k/l or arrow keys to move the cursor."
210         ,"Set the count parameter for insert/delete by entering digits 0-9."
211         ,""
212         ,"Other commands:"
213         ,"space toggles through the set of video attributes and colors."
214         ,"t     touches (forces repaint) of the current line."
215         ,"i     calls insertln at the current position with the given count."
216         ,"d     calls deleteln at the window beginning with the given count."
217         ,"I     calls insdelln at the window beginning with the given count."
218         ,"D     calls insdelln at the window beginning with the given -count."
219         ,"f     refills the window with test-pattern using current attributes."
220         ,"w     recur to test windows other than stdscr"
221         ,"q     quit"
222         ,"=     resets count to zero."
223         ,"?     shows this help-window"
224         ,0
225     };
226
227     popup_msg(win, table);
228 }
229
230 static void
231 update_status(WINDOW *win, STATUS * sp)
232 {
233     switch (sp->ch) {
234     case ' ':                   /* next test-iteration */
235         if (has_colors()) {
236             if ((sp->c_msg = color_params(++(sp->c), &(sp->pair))) == 0) {
237                 sp->c_msg = color_params(sp->c = 0, &(sp->pair));
238                 if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) {
239                     sp->v_msg = video_params(sp->v = 0, &(sp->attr));
240                 }
241             }
242         } else {
243             if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) {
244                 sp->v_msg = video_params(sp->v = 0, &(sp->attr));
245             }
246         }
247         sp->count = 0;
248         show_status(win, sp);
249         break;
250     case KEY_LEFT:
251     case 'h':
252         if (sp->x_val > 0)
253             wmove(win, sp->y_val, --(sp->x_val));
254         break;
255     case KEY_DOWN:
256     case 'j':
257         if (sp->y_val < sp->y_max)
258             wmove(win, ++(sp->y_val), sp->x_val);
259         break;
260     case KEY_UP:
261     case 'k':
262         if (sp->y_val > 0)
263             wmove(win, --(sp->y_val), sp->x_val);
264         break;
265     case KEY_RIGHT:
266     case 'l':
267         if (sp->x_val < sp->x_max)
268             wmove(win, sp->y_val, ++(sp->x_val));
269         break;
270     case 't':
271         touchline(win, sp->y_val, 1);
272         break;
273     case '=':
274         sp->count = 0;
275         show_status(win, sp);
276         break;
277     case HELP_KEY_1:
278         show_help(win);
279         break;
280     default:
281         if (isdigit(sp->ch)) {
282             sp->count = (sp->count * 10) + (sp->ch - '0');
283             show_status(win, sp);
284         } else {
285             beep();
286         }
287         break;
288     }
289 }
290
291 static void
292 test_winsdelln(WINDOW *win)
293 {
294     STATUS st;
295     int n;
296
297     init_status(win, &st);
298
299     do {
300         (void) wattrset(win, AttrArg(COLOR_PAIR(st.pair), st.attr));
301         switch (st.ch) {
302         case 'i':
303             for (n = 0; n < st.count; ++n)
304                 winsertln(win);
305             break;
306         case 'd':
307             for (n = 0; n < st.count; ++n)
308                 wdeleteln(win);
309             break;
310         case 'I':
311             winsdelln(win, st.count);
312             break;
313         case 'D':
314             winsdelln(win, -st.count);
315             break;
316         case 'f':
317             fill_window(win);
318             reshow_status(win, &st);
319             break;
320         case 'w':
321             do_subwindow(win, &st, test_winsdelln);
322             break;
323         case 'q':
324             return;
325         default:
326             update_status(win, &st);
327             break;
328         }
329     } while ((st.ch = wgetch(win)) != ERR);
330 }
331
332 static void
333 test_insdelln(void)
334 {
335     STATUS st;
336     int n;
337
338     init_status(stdscr, &st);
339
340     do {
341         (void) attrset(AttrArg(COLOR_PAIR(st.pair), st.attr));
342         switch (st.ch) {
343         case 'i':
344             for (n = 0; n < st.count; ++n)
345                 insertln();
346             break;
347         case 'd':
348             for (n = 0; n < st.count; ++n)
349                 deleteln();
350             break;
351         case 'I':
352             insdelln(st.count);
353             break;
354         case 'D':
355             insdelln(-st.count);
356             break;
357         case 'f':
358             fill_window(stdscr);
359             reshow_status(stdscr, &st);
360             break;
361         case 'w':
362             do_subwindow(stdscr, &st, test_winsdelln);
363             break;
364         case 'q':
365             return;
366         default:
367             update_status(stdscr, &st);
368             break;
369         }
370     } while ((st.ch = getch()) != ERR);
371 }
372
373 int
374 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
375 {
376     initscr();
377     cbreak();
378     noecho();
379
380     test_insdelln();
381     endwin();
382
383     ExitProgram(EXIT_SUCCESS);
384 }
385
386 #else
387 int
388 main(void)
389 {
390     printf("This program requires the curses winsdelln function\n");
391     ExitProgram(EXIT_FAILURE);
392 }
393 #endif