ncurses 6.2 - patch 20210227
[ncurses.git] / test / insdelln.c
1 /****************************************************************************
2  * Copyright 2019,2020 Thomas E. Dickey                                     *
3  * Copyright 2008-2014,2017 Free Software Foundation, Inc.                  *
4  *                                                                          *
5  * Permission is hereby granted, free of charge, to any person obtaining a  *
6  * copy of this software and associated documentation files (the            *
7  * "Software"), to deal in the Software without restriction, including      *
8  * without limitation the rights to use, copy, modify, merge, publish,      *
9  * distribute, distribute with modifications, sublicense, and/or sell       *
10  * copies of the Software, and to permit persons to whom the Software is    *
11  * furnished to do so, subject to the following conditions:                 *
12  *                                                                          *
13  * The above copyright notice and this permission notice shall be included  *
14  * in all copies or substantial portions of the Software.                   *
15  *                                                                          *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23  *                                                                          *
24  * Except as contained in this notice, the name(s) of the above copyright   *
25  * holders shall not be used in advertising or otherwise to promote the     *
26  * sale, use or other dealings in this Software without prior written       *
27  * authorization.                                                           *
28  ****************************************************************************/
29 /*
30  * $Id: insdelln.c,v 1.14 2020/02/02 23:34:34 tom Exp $
31  *
32  * test-driver for deleteln, wdeleteln, insdelln, winsdelln, insertln, winsertln
33  */
34
35 #include <test.priv.h>
36
37 #if HAVE_WINSDELLN
38
39 #include <popup_msg.h>
40
41 #define SHOW(n) ((n) == ERR ? "ERR" : "OK")
42 #define COLOR_DEFAULT (-1)
43
44 typedef struct {
45     unsigned c;
46     unsigned v;
47     int pair;
48     unsigned attr;
49     int count;
50     int ch;
51     const char *c_msg;
52     const char *v_msg;
53     int y_val;
54     int x_val;
55     int y_beg, x_beg;
56     int y_max, x_max;
57 } STATUS;
58
59 static const char *
60 color_params(unsigned state, int *pair)
61 {
62     /* *INDENT-OFF* */
63     static struct {
64         short pair;
65         short fg, bg;
66         const char *msg;
67     } table[] = {
68         { 0, COLOR_DEFAULT, COLOR_DEFAULT, "default" },
69         { 1, COLOR_RED,     COLOR_BLACK,   "red/black" },
70         { 2, COLOR_WHITE,   COLOR_BLUE,    "white/blue" },
71     };
72     /* *INDENT-ON* */
73
74     const char *result = 0;
75
76     if (has_colors()) {
77         static bool first = TRUE;
78         if (first) {
79             unsigned n;
80
81             start_color();
82             for (n = 0; n < SIZEOF(table); ++n) {
83                 init_pair(table[n].pair, table[n].fg, table[n].bg);
84             }
85         }
86         if (state < SIZEOF(table)) {
87             *pair = table[state].pair;
88             result = table[state].msg;
89         }
90     }
91     return result;
92 }
93
94 static const char *
95 video_params(unsigned state, unsigned *attr)
96 {
97     /* *INDENT-OFF* */
98     static struct {
99         unsigned attr;
100         const char *msg;
101     } table[] = {
102         { A_NORMAL,     "normal" },
103         { A_BOLD,       "bold" },
104         { A_REVERSE,    "reverse" },
105         { A_UNDERLINE,  "underline" },
106         { A_BLINK,      "blink" },
107     };
108     /* *INDENT-ON* */
109
110     const char *result = 0;
111
112     if (state < SIZEOF(table)) {
113         *attr = table[state].attr;
114         result = table[state].msg;
115     }
116     return result;
117 }
118
119 /* fill the window with a test-pattern */
120 static void
121 fill_window(WINDOW *win)
122 {
123     int y, x;
124     int y0 = -1, x0 = -1;
125
126     getyx(win, y, x);
127     wmove(win, 0, 0);
128     while (waddstr(win, "0123456789 abcdefghijklmnopqrstuvwxyz ") != ERR) {
129         int y1, x1;
130         getyx(win, y1, x1);
131         if (y1 == y0 && x1 == x0)
132             break;
133         x0 = x1;
134         y0 = y1;
135     }
136     wmove(win, y, x);
137 }
138
139 static void
140 show_status(WINDOW *win, STATUS * sp)
141 {
142     int y, x;
143
144     getyx(win, y, x);
145     wmove(win, 0, 0);
146     wprintw(win, "Count %d", sp->count);
147     if (sp->v_msg != 0)
148         wprintw(win, " Video %s", sp->v_msg);
149     if (sp->c_msg != 0)
150         wprintw(win, " Color %s", sp->c_msg);
151     wclrtoeol(win);
152     wmove(win, y, x);
153 }
154
155 static void
156 reshow_status(WINDOW *win, STATUS * sp)
157 {
158     fill_window(win);
159     show_status(win, sp);
160 }
161
162 static void
163 do_subwindow(WINDOW *win, STATUS * sp, void func(WINDOW *))
164 {
165     WINDOW *win1 = newwin(sp->y_max - 2, sp->x_max - 2,
166                           sp->y_beg + 1, sp->x_beg + 1);
167
168     if (win1 != 0 && sp->y_max > 4 && sp->x_max > 4) {
169         WINDOW *win2 = derwin(win1, sp->y_max - 4, sp->x_max - 4, 1, 1);
170
171         if (win2 != 0) {
172             box(win1, 0, 0);
173             wrefresh(win1);
174             func(win2);
175
176             delwin(win2);
177         } else {
178             beep();
179         }
180         delwin(win1);
181         touchwin(win);
182     } else {
183         if (win1)
184             delwin(win1);
185         beep();
186     }
187 }
188
189 static void
190 init_status(WINDOW *win, STATUS * sp)
191 {
192     memset(sp, 0, sizeof(*sp));
193     sp->c = 99;
194     sp->v = 99;
195     sp->ch = ' ';
196
197     keypad(win, TRUE);
198     fill_window(win);
199
200     getbegyx(win, sp->y_beg, sp->x_beg);
201     getmaxyx(win, sp->y_max, sp->x_max);
202 }
203
204 static void
205 show_help(WINDOW *win)
206 {
207     static const char *table[] =
208     {
209         "Basic commands:"
210         ,"Use h/j/k/l or arrow keys to move the cursor."
211         ,"Set the count parameter for insert/delete by entering digits 0-9."
212         ,""
213         ,"Other commands:"
214         ,"space toggles through the set of video attributes and colors."
215         ,"t     touches (forces repaint) of the current line."
216         ,"i     calls insertln at the current position with the given count."
217         ,"d     calls deleteln at the window beginning with the given count."
218         ,"I     calls insdelln at the window beginning with the given count."
219         ,"D     calls insdelln at the window beginning with the given -count."
220         ,"f     refills the window with test-pattern using current attributes."
221         ,"w     recur to test windows other than stdscr"
222         ,"q     quit"
223         ,"=     resets count to zero."
224         ,"?     shows this help-window"
225         ,0
226     };
227
228     popup_msg(win, table);
229 }
230
231 static void
232 update_status(WINDOW *win, STATUS * sp)
233 {
234     switch (sp->ch) {
235     case ' ':                   /* next test-iteration */
236         if (has_colors()) {
237             if ((sp->c_msg = color_params(++(sp->c), &(sp->pair))) == 0) {
238                 sp->c_msg = color_params(sp->c = 0, &(sp->pair));
239                 if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) {
240                     sp->v_msg = video_params(sp->v = 0, &(sp->attr));
241                 }
242             }
243         } else {
244             if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) {
245                 sp->v_msg = video_params(sp->v = 0, &(sp->attr));
246             }
247         }
248         sp->count = 0;
249         show_status(win, sp);
250         break;
251     case KEY_LEFT:
252     case 'h':
253         if (sp->x_val > 0)
254             wmove(win, sp->y_val, --(sp->x_val));
255         break;
256     case KEY_DOWN:
257     case 'j':
258         if (sp->y_val < sp->y_max)
259             wmove(win, ++(sp->y_val), sp->x_val);
260         break;
261     case KEY_UP:
262     case 'k':
263         if (sp->y_val > 0)
264             wmove(win, --(sp->y_val), sp->x_val);
265         break;
266     case KEY_RIGHT:
267     case 'l':
268         if (sp->x_val < sp->x_max)
269             wmove(win, sp->y_val, ++(sp->x_val));
270         break;
271     case 't':
272         touchline(win, sp->y_val, 1);
273         break;
274     case '=':
275         sp->count = 0;
276         show_status(win, sp);
277         break;
278     case HELP_KEY_1:
279         show_help(win);
280         break;
281     default:
282         if (isdigit(sp->ch)) {
283             sp->count = (sp->count * 10) + (sp->ch - '0');
284             show_status(win, sp);
285         } else {
286             beep();
287         }
288         break;
289     }
290 }
291
292 static void
293 test_winsdelln(WINDOW *win)
294 {
295     STATUS st;
296     int n;
297
298     init_status(win, &st);
299
300     do {
301         (void) wattrset(win, AttrArg(COLOR_PAIR(st.pair), st.attr));
302         switch (st.ch) {
303         case 'i':
304             for (n = 0; n < st.count; ++n)
305                 winsertln(win);
306             break;
307         case 'd':
308             for (n = 0; n < st.count; ++n)
309                 wdeleteln(win);
310             break;
311         case 'I':
312             winsdelln(win, st.count);
313             break;
314         case 'D':
315             winsdelln(win, -st.count);
316             break;
317         case 'f':
318             fill_window(win);
319             reshow_status(win, &st);
320             break;
321         case 'w':
322             do_subwindow(win, &st, test_winsdelln);
323             break;
324         case 'q':
325             return;
326         default:
327             update_status(win, &st);
328             break;
329         }
330     } while ((st.ch = wgetch(win)) != ERR);
331 }
332
333 static void
334 test_insdelln(void)
335 {
336     STATUS st;
337     int n;
338
339     init_status(stdscr, &st);
340
341     do {
342         (void) attrset(AttrArg(COLOR_PAIR(st.pair), st.attr));
343         switch (st.ch) {
344         case 'i':
345             for (n = 0; n < st.count; ++n)
346                 insertln();
347             break;
348         case 'd':
349             for (n = 0; n < st.count; ++n)
350                 deleteln();
351             break;
352         case 'I':
353             insdelln(st.count);
354             break;
355         case 'D':
356             insdelln(-st.count);
357             break;
358         case 'f':
359             fill_window(stdscr);
360             reshow_status(stdscr, &st);
361             break;
362         case 'w':
363             do_subwindow(stdscr, &st, test_winsdelln);
364             break;
365         case 'q':
366             return;
367         default:
368             update_status(stdscr, &st);
369             break;
370         }
371     } while ((st.ch = getch()) != ERR);
372 }
373
374 int
375 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
376 {
377     initscr();
378     cbreak();
379     noecho();
380
381     test_insdelln();
382     endwin();
383
384     ExitProgram(EXIT_SUCCESS);
385 }
386
387 #else
388 int
389 main(void)
390 {
391     printf("This program requires the curses winsdelln function\n");
392     ExitProgram(EXIT_FAILURE);
393 }
394 #endif