• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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