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