blob: ba8a90e5cd82e4e295b75202f5b9bf50af7824ba [file] [log] [blame]
Steve Kondikae271bc2015-11-15 02:50:53 +01001/****************************************************************************
micky3879b9f5e72025-07-08 18:04:53 -04002 * Copyright 2020,2022 Thomas E. Dickey *
3 * Copyright 2009-2016,2017 Free Software Foundation, Inc. *
Steve Kondikae271bc2015-11-15 02:50:53 +01004 * *
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/*
micky3879b9f5e72025-07-08 18:04:53 -040030 * $Id: test_addstr.c,v 1.20 2022/12/10 22:28:50 tom Exp $
Steve Kondikae271bc2015-11-15 02:50:53 +010031 *
32 * Demonstrate the waddstr() and waddch functions.
33 * Thomas Dickey - 2009/9/12
34 */
35
36#include <test.priv.h>
Steve Kondikae271bc2015-11-15 02:50:53 +010037#include <linedata.h>
38
micky3879b9f5e72025-07-08 18:04:53 -040039/*
40 * redefinitions to simplify comparison between test_*str programs
41 */
Steve Kondikae271bc2015-11-15 02:50:53 +010042#define AddNStr addnstr
43#define AddStr addstr
44#define MvAddNStr (void) mvaddnstr
45#define MvWAddNStr (void) mvwaddnstr
46#define WAddNStr waddnstr
47#define WAddStr waddstr
48
Steve Kondikae271bc2015-11-15 02:50:53 +010049#define MY_TABSIZE 8
50
51typedef enum {
52 oDefault = 0,
53 oMove = 1,
54 oWindow = 2,
55 oMoveWindow = 3
56} Options;
57
58static bool m_opt = FALSE;
59static bool w_opt = FALSE;
60static int n_opt = -1;
61
62static void
63legend(WINDOW *win, int level, Options state, char *buffer, int length)
64{
65 const char *showstate;
66
67 switch (state) {
68 default:
69 case oDefault:
70 showstate = "";
71 break;
72 case oMove:
73 showstate = " (mvXXX)";
74 break;
75 case oWindow:
76 showstate = " (winXXX)";
77 break;
78 case oMoveWindow:
79 showstate = " (mvwinXXX)";
80 break;
81 }
82
83 wmove(win, 0, 0);
84 wprintw(win,
85 "The Strings/Chars displays should match. Enter any characters, except:\n");
86 wprintw(win,
87 "down-arrow or ^N to repeat on next line, ^W for inner window, ESC to exit.\n");
88 wclrtoeol(win);
89 wprintw(win, "Level %d,%s added %d characters <%s>", level,
90 showstate, length, buffer);
91}
92
93static int
94ColOf(char *buffer, int length, int margin)
95{
96 int n;
97 int result;
98
99 for (n = 0, result = margin + 1; n < length; ++n) {
100 int ch = UChar(buffer[n]);
101 switch (ch) {
102 case '\n':
103 /* actually newline should clear the remainder of the line
104 * and move to the next line - but that seems a little awkward
105 * in this example.
106 */
107 case '\r':
108 result = 0;
109 break;
110 case '\b':
111 if (result > 0)
112 --result;
113 break;
114 case '\t':
115 result += (MY_TABSIZE - (result % MY_TABSIZE));
116 break;
117 case '\177':
118 result += 2;
119 break;
120 default:
121 ++result;
122 if (ch < 32)
123 ++result;
124 break;
125 }
126 }
127 return result;
128}
129
130#define LEN(n) ((length - (n) > n_opt) ? n_opt : (length - (n)))
131static void
micky3879b9f5e72025-07-08 18:04:53 -0400132recursive_test(int level)
Steve Kondikae271bc2015-11-15 02:50:53 +0100133{
134 static bool first = TRUE;
135
136 int ch;
137 int limit;
138 int row = 1;
139 int col;
140 int row2, col2;
141 int length;
142 char buffer[BUFSIZ];
143 WINDOW *look = 0;
144 WINDOW *work = 0;
145 WINDOW *show = 0;
146 int margin = (2 * MY_TABSIZE) - 1;
147 Options option = (Options) ((unsigned) (m_opt
148 ? oMove
149 : oDefault)
150 | (unsigned) ((w_opt || (level > 0))
151 ? oWindow
152 : oDefault));
153
154 if (first) {
155 static char cmd[80];
156 setlocale(LC_ALL, "");
157
micky3879b9f5e72025-07-08 18:04:53 -0400158 _nc_STRCPY(cmd, "TABSIZE=8", sizeof(cmd));
159 putenv(cmd);
Steve Kondikae271bc2015-11-15 02:50:53 +0100160
161 initscr();
162 (void) cbreak(); /* take input chars one at a time, no wait for \n */
163 (void) noecho(); /* don't echo input */
164 keypad(stdscr, TRUE);
165
166 /*
167 * Show the characters added in color, to distinguish from those that
168 * are shifted.
169 */
170 if (has_colors()) {
171 start_color();
172 init_pair(1, COLOR_WHITE, COLOR_BLUE);
173 }
174 }
175
176 limit = LINES - 5;
177 if (level > 0) {
178 look = newwin(limit, COLS - (2 * (level - 1)), 0, level - 1);
179 work = newwin(limit - 2, COLS - (2 * level), 1, level);
180 show = newwin(4, COLS, limit + 1, 0);
181 box(look, 0, 0);
182 wnoutrefresh(look);
183 limit -= 2;
184 } else {
185 work = stdscr;
186 show = derwin(stdscr, 4, COLS, limit + 1, 0);
187 }
188 keypad(work, TRUE);
189
190 for (col = margin + 1; col < COLS; col += MY_TABSIZE)
191 MvWVLine(work, row, col, '.', limit - 2);
192
193 MvWVLine(work, row, margin, ACS_VLINE, limit - 2);
194 MvWVLine(work, row, margin + 1, ACS_VLINE, limit - 2);
195 limit /= 2;
196
197 MvWAddStr(work, 1, 2, "String");
198 MvWAddStr(work, limit + 1, 2, "Chars");
199 wnoutrefresh(work);
200
201 buffer[length = 0] = '\0';
202 legend(show, level, option, buffer, length);
203 wnoutrefresh(show);
204
205 doupdate();
206
207 if (has_colors()) {
208 wbkgdset(work, (chtype) (COLOR_PAIR(1) | ' '));
209 }
210
211 while ((ch = read_linedata(work)) != ERR && !isQUIT(ch)) {
212 wmove(work, row, margin + 1);
213 switch (ch) {
214 case key_RECUR:
micky3879b9f5e72025-07-08 18:04:53 -0400215 recursive_test(level + 1);
Steve Kondikae271bc2015-11-15 02:50:53 +0100216
217 if (look)
218 touchwin(look);
219 touchwin(work);
220 touchwin(show);
221
222 if (look)
223 wnoutrefresh(look);
224 wnoutrefresh(work);
225 wnoutrefresh(show);
226
227 doupdate();
228 break;
229 case key_NEWLINE:
230 if (row < limit) {
231 ++row;
232 /* put the whole string in, all at once */
233 col2 = margin + 1;
234 switch (option) {
235 case oDefault:
236 if (n_opt > 1) {
237 for (col = 0; col < length; col += n_opt) {
238 col2 = ColOf(buffer, col, margin);
239 if (move(row, col2) != ERR) {
240 AddNStr(buffer + col, LEN(col));
241 }
242 }
243 } else {
244 if (move(row, col2) != ERR) {
245 AddStr(buffer);
246 }
247 }
248 break;
249 case oMove:
250 if (n_opt > 1) {
251 for (col = 0; col < length; col += n_opt) {
252 col2 = ColOf(buffer, col, margin);
253 MvAddNStr(row, col2, buffer + col, LEN(col));
254 }
255 } else {
256 MvAddStr(row, col2, buffer);
257 }
258 break;
259 case oWindow:
260 if (n_opt > 1) {
261 for (col = 0; col < length; col += n_opt) {
262 col2 = ColOf(buffer, col, margin);
263 if (wmove(work, row, col2) != ERR) {
264 WAddNStr(work, buffer + col, LEN(col));
265 }
266 }
267 } else {
268 if (wmove(work, row, col2) != ERR) {
269 WAddStr(work, buffer);
270 }
271 }
272 break;
273 case oMoveWindow:
274 if (n_opt > 1) {
275 for (col = 0; col < length; col += n_opt) {
276 col2 = ColOf(buffer, col, margin);
277 MvWAddNStr(work, row, col2, buffer + col, LEN(col));
278 }
279 } else {
280 MvWAddStr(work, row, col2, buffer);
281 }
282 break;
283 }
284
285 /* do the corresponding single-character add */
286 row2 = limit + row;
287 for (col = 0; col < length; ++col) {
288 col2 = ColOf(buffer, col, margin);
289 switch (option) {
290 case oDefault:
291 if (move(row2, col2) != ERR) {
292 AddCh(UChar(buffer[col]));
293 }
294 break;
295 case oMove:
296 MvAddCh(row2, col2, UChar(buffer[col]));
297 break;
298 case oWindow:
299 if (wmove(work, row2, col2) != ERR) {
300 WAddCh(work, UChar(buffer[col]));
301 }
302 break;
303 case oMoveWindow:
304 MvWAddCh(work, row2, col2, UChar(buffer[col]));
305 break;
306 }
307 }
308 } else {
309 beep();
310 }
311 break;
312 default:
313 if (ch <= 0 || ch > 255) {
314 beep();
315 break;
316 }
317 buffer[length++] = (char) ch;
318 buffer[length] = '\0';
319
320 /* put the string in, one character at a time */
321 col = ColOf(buffer, length - 1, margin);
322 switch (option) {
323 case oDefault:
324 if (move(row, col) != ERR) {
325 AddStr(buffer + length - 1);
326 }
327 break;
328 case oMove:
329 MvAddStr(row, col, buffer + length - 1);
330 break;
331 case oWindow:
332 if (wmove(work, row, col) != ERR) {
333 WAddStr(work, buffer + length - 1);
334 }
335 break;
336 case oMoveWindow:
337 MvWAddStr(work, row, col, buffer + length - 1);
338 break;
339 }
340
341 /* do the corresponding single-character add */
342 switch (option) {
343 case oDefault:
344 if (move(limit + row, col) != ERR) {
345 AddCh(UChar(ch));
346 }
347 break;
348 case oMove:
349 MvAddCh(limit + row, col, UChar(ch));
350 break;
351 case oWindow:
352 if (wmove(work, limit + row, col) != ERR) {
353 WAddCh(work, UChar(ch));
354 }
355 break;
356 case oMoveWindow:
357 MvWAddCh(work, limit + row, col, UChar(ch));
358 break;
359 }
360
361 wnoutrefresh(work);
362
363 legend(show, level, option, buffer, length);
364 wnoutrefresh(show);
365
366 doupdate();
367 break;
368 }
369 }
370 delwin(show);
371 if (level > 0) {
372 delwin(work);
373 delwin(look);
374 }
375}
376
377static void
micky3879b9f5e72025-07-08 18:04:53 -0400378usage(int ok)
Steve Kondikae271bc2015-11-15 02:50:53 +0100379{
380 static const char *tbl[] =
381 {
382 "Usage: test_addstr [options]"
383 ,""
micky3879b9f5e72025-07-08 18:04:53 -0400384 ,USAGE_COMMON
Steve Kondikae271bc2015-11-15 02:50:53 +0100385 ,"Options:"
micky3879b9f5e72025-07-08 18:04:53 -0400386 ," -f FILE read data from given file"
387 ," -n NUM limit string-adds to NUM bytes on ^N replay"
388 ," -m perform wmove/move separately from add-functions"
389 ," -w use window-parameter even when stdscr would be implied"
Steve Kondikae271bc2015-11-15 02:50:53 +0100390 };
391 unsigned n;
392 for (n = 0; n < SIZEOF(tbl); ++n)
393 fprintf(stderr, "%s\n", tbl[n]);
micky3879b9f5e72025-07-08 18:04:53 -0400394 ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE);
Steve Kondikae271bc2015-11-15 02:50:53 +0100395}
micky3879b9f5e72025-07-08 18:04:53 -0400396/* *INDENT-OFF* */
397VERSION_COMMON()
398/* *INDENT-ON* */
Steve Kondikae271bc2015-11-15 02:50:53 +0100399
400int
micky3879b9f5e72025-07-08 18:04:53 -0400401main(int argc, char *argv[])
Steve Kondikae271bc2015-11-15 02:50:53 +0100402{
403 int ch;
404
405 setlocale(LC_ALL, "");
406
micky3879b9f5e72025-07-08 18:04:53 -0400407 while ((ch = getopt(argc, argv, OPTS_COMMON "f:mn:w")) != -1) {
Steve Kondikae271bc2015-11-15 02:50:53 +0100408 switch (ch) {
409 case 'f':
410 init_linedata(optarg);
411 break;
412 case 'm':
413 m_opt = TRUE;
414 break;
415 case 'n':
416 n_opt = atoi(optarg);
417 if (n_opt == 0)
418 n_opt = -1;
419 break;
420 case 'w':
421 w_opt = TRUE;
422 break;
micky3879b9f5e72025-07-08 18:04:53 -0400423 case OPTS_VERSION:
424 show_version(argv);
425 ExitProgram(EXIT_SUCCESS);
Steve Kondikae271bc2015-11-15 02:50:53 +0100426 default:
micky3879b9f5e72025-07-08 18:04:53 -0400427 usage(ch == OPTS_USAGE);
428 /* NOTREACHED */
Steve Kondikae271bc2015-11-15 02:50:53 +0100429 }
430 }
431 if (optind < argc)
micky3879b9f5e72025-07-08 18:04:53 -0400432 usage(FALSE);
Steve Kondikae271bc2015-11-15 02:50:53 +0100433
micky3879b9f5e72025-07-08 18:04:53 -0400434 recursive_test(0);
Steve Kondikae271bc2015-11-15 02:50:53 +0100435 endwin();
436 ExitProgram(EXIT_SUCCESS);
437}