1 /****************************************************************************
2 * Copyright 2019-2020,2022 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.15 2022/12/10 23:31:31 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 *
color_params(unsigned state,int * pair)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 *
video_params(unsigned state,unsigned * attr)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
fill_window(WINDOW * win)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
show_status(WINDOW * win,STATUS * sp)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
reshow_status(WINDOW * win,STATUS * sp)156 reshow_status(WINDOW *win, STATUS * sp)
157 {
158 fill_window(win);
159 show_status(win, sp);
160 }
161
162 static void
do_subwindow(WINDOW * win,STATUS * sp,void func (WINDOW *))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
init_status(WINDOW * win,STATUS * sp)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
show_help(WINDOW * win)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
update_status(WINDOW * win,STATUS * sp)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
test_winsdelln(WINDOW * win)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
test_insdelln(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 static void
usage(int ok)375 usage(int ok)
376 {
377 static const char *msg[] =
378 {
379 "Usage: insdelln [options]"
380 ,""
381 ,USAGE_COMMON
382 };
383 size_t n;
384
385 for (n = 0; n < SIZEOF(msg); n++)
386 fprintf(stderr, "%s\n", msg[n]);
387
388 ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE);
389 }
390 /* *INDENT-OFF* */
VERSION_COMMON()391 VERSION_COMMON()
392 /* *INDENT-ON* */
393
394 int
395 main(int argc, char *argv[])
396 {
397 int ch;
398
399 while ((ch = getopt(argc, argv, OPTS_COMMON)) != -1) {
400 switch (ch) {
401 case OPTS_VERSION:
402 show_version(argv);
403 ExitProgram(EXIT_SUCCESS);
404 default:
405 usage(ch == OPTS_USAGE);
406 /* NOTREACHED */
407 }
408 }
409 if (optind < argc)
410 usage(FALSE);
411
412 initscr();
413 cbreak();
414 noecho();
415
416 test_insdelln();
417 endwin();
418
419 ExitProgram(EXIT_SUCCESS);
420 }
421
422 #else
423 int
main(void)424 main(void)
425 {
426 printf("This program requires the curses winsdelln function\n");
427 ExitProgram(EXIT_FAILURE);
428 }
429 #endif
430