blob: 33dafe4fcd05d8117d72e20566a16d3c135a037a [file] [log] [blame]
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05301/****************************************************************************
2 * Copyright (c) 2002-2006,2007 Free Software Foundation, Inc. *
3 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
28/*
29 * $Id: ins_wide.c,v 1.9 2007/07/21 17:41:55 tom Exp $
30 *
31 * Demonstrate the wins_wstr() and wins_wch functions.
32 * Thomas Dickey - 2002/11/23
33 *
34 * Note: to provide inputs for *ins_wch(), we use setcchar(). A quirk of the
35 * X/Open definition for that function is that the string contains no
36 * characters with negative width. Any control character (such as tab) falls
37 * into that category. So it follows that *ins_wch() cannot render a tab
38 * character because there is no legal way to construct a cchar_t containing
39 * one. X/Open does not document this, and it would be logical to assume that
40 * *ins_wstr() has the same limitation, but it uses a wchar_t string directly,
41 * and does not document how tabs are handled.
42 */
43
44#include <test.priv.h>
45
46#if USE_WIDEC_SUPPORT
47
48/* definitions to make it simpler to compare with inserts.c */
49#define InsNStr ins_nwstr
50#define InsStr ins_wstr
51#define MvInsNStr mvins_nwstr
52#define MvInsStr mvins_wstr
53#define MvWInsNStr mvwins_nwstr
54#define MvWInsStr mvwins_wstr
55#define WInsNStr wins_nwstr
56#define WInsStr wins_wstr
57
58#define MY_TABSIZE 8
59
60typedef enum {
61 oDefault = 0,
62 oMove = 1,
63 oWindow = 2,
64 oMoveWindow = 3
65} Options;
66
67static bool m_opt = FALSE;
68static bool w_opt = FALSE;
69static int n_opt = -1;
70
71static void
72legend(WINDOW *win, int level, Options state, wchar_t *buffer, int length)
73{
74 NCURSES_CONST char *showstate;
75
76 switch (state) {
77 default:
78 case oDefault:
79 showstate = "";
80 break;
81 case oMove:
82 showstate = " (mvXXX)";
83 break;
84 case oWindow:
85 showstate = " (winXXX)";
86 break;
87 case oMoveWindow:
88 showstate = " (mvwinXXX)";
89 break;
90 }
91
92 wmove(win, 0, 0);
93 wprintw(win,
94 "The Strings/Chars displays should match. Enter any characters, except:\n");
95 wprintw(win,
96 "down-arrow or ^N to repeat on next line, 'w' for inner window, 'q' to exit.\n");
97 wclrtoeol(win);
98 wprintw(win, "Level %d,%s inserted %d characters <", level,
99 showstate, length);
100 waddwstr(win, buffer);
101 waddstr(win, ">");
102}
103
104static int
105ColOf(wchar_t *buffer, int length, int margin)
106{
107 int n;
108 int result;
109
110 for (n = 0, result = margin + 1; n < length; ++n) {
111 int ch = buffer[n];
112 switch (ch) {
113 case '\n':
114 /* actually newline should clear the remainder of the line
115 * and move to the next line - but that seems a little awkward
116 * in this example.
117 */
118 case '\r':
119 result = 0;
120 break;
121 case '\b':
122 if (result > 0)
123 --result;
124 break;
125 case '\t':
126 result += (MY_TABSIZE - (result % MY_TABSIZE));
127 break;
128 case '\177':
129 result += 2;
130 break;
131 default:
132 result += wcwidth(ch);
133 if (ch < 32)
134 ++result;
135 break;
136 }
137 }
138 return result;
139}
140
141static int
142ConvertCh(chtype source, cchar_t *target)
143{
144 wchar_t tmp_wchar[2];
145
146 tmp_wchar[0] = source;
147 tmp_wchar[1] = 0;
148 if (setcchar(target, tmp_wchar, A_NORMAL, 0, (void *) 0) == ERR) {
149 beep();
150 return FALSE;
151 }
152 return TRUE;
153}
154
155static int
156MvWInsCh(WINDOW *win, int y, int x, chtype ch)
157{
158 int code;
159 cchar_t tmp_cchar;
160
161 if (ConvertCh(ch, &tmp_cchar)) {
162 code = mvwins_wch(win, y, x, &tmp_cchar);
163 } else {
164 code = mvwinsch(win, y, x, ch);
165 }
166 return code;
167}
168
169static int
170MvInsCh(int y, int x, chtype ch)
171{
172 int code;
173 cchar_t tmp_cchar;
174
175 if (ConvertCh(ch, &tmp_cchar)) {
176 code = mvins_wch(y, x, &tmp_cchar);
177 } else {
178 code = mvinsch(y, x, ch);
179 }
180 return code;
181}
182
183static int
184WInsCh(WINDOW *win, chtype ch)
185{
186 int code;
187 cchar_t tmp_cchar;
188
189 if (ConvertCh(ch, &tmp_cchar)) {
190 code = wins_wch(win, &tmp_cchar);
191 } else {
192 code = winsch(win, ch);
193 }
194 return code;
195}
196
197static int
198InsCh(chtype ch)
199{
200 int code;
201 cchar_t tmp_cchar;
202
203 if (ConvertCh(ch, &tmp_cchar)) {
204 code = ins_wch(&tmp_cchar);
205 } else {
206 code = insch(ch);
207 }
208 return code;
209}
210
211#define LEN(n) ((length - (n) > n_opt) ? n_opt : (length - (n)))
212static void
213test_inserts(int level)
214{
215 static bool first = TRUE;
216
217 wint_t ch;
218 int code;
219 int limit;
220 int row = 1;
221 int col;
222 int row2, col2;
223 int length;
224 wchar_t buffer[BUFSIZ];
225 WINDOW *look = 0;
226 WINDOW *work = 0;
227 WINDOW *show = 0;
228 int margin = (2 * MY_TABSIZE) - 1;
229 Options option = ((m_opt ? oMove : oDefault)
230 | ((w_opt || (level > 0)) ? oWindow : oDefault));
231
232 if (first) {
233 static char cmd[80];
234 setlocale(LC_ALL, "");
235
236 putenv(strcpy(cmd, "TABSIZE=8"));
237
238 initscr();
239 (void) cbreak(); /* take input chars one at a time, no wait for \n */
240 (void) noecho(); /* don't echo input */
241 keypad(stdscr, TRUE);
242 }
243
244 limit = LINES - 5;
245 if (level > 0) {
246 look = newwin(limit, COLS - (2 * (level - 1)), 0, level - 1);
247 work = newwin(limit - 2, COLS - (2 * level), 1, level);
248 show = newwin(4, COLS, limit + 1, 0);
249 box(look, 0, 0);
250 wnoutrefresh(look);
251 limit -= 2;
252 } else {
253 work = stdscr;
254 show = derwin(stdscr, 4, COLS, limit + 1, 0);
255 }
256 keypad(work, TRUE);
257
258 for (col = margin + 1; col < COLS; col += MY_TABSIZE)
259 mvwvline(work, row, col, '.', limit - 2);
260
261 mvwvline(work, row, margin, ACS_VLINE, limit - 2);
262 mvwvline(work, row, margin + 1, ACS_VLINE, limit - 2);
263 limit /= 2;
264
265 mvwaddstr(work, 1, 2, "String");
266 mvwaddstr(work, limit + 1, 2, "Chars");
267 wnoutrefresh(work);
268
269 buffer[length = 0] = '\0';
270 legend(show, level, option, buffer, length);
271 wnoutrefresh(show);
272
273 doupdate();
274
275 /*
276 * Show the characters inserted in color, to distinguish from those that
277 * are shifted.
278 */
279 if (has_colors()) {
280 start_color();
281 init_pair(1, COLOR_WHITE, COLOR_BLUE);
282 wbkgdset(work, COLOR_PAIR(1) | ' ');
283 }
284
285 while ((code = wget_wch(work, &ch)) != ERR) {
286
287 if (code == KEY_CODE_YES) {
288 switch (ch) {
289 case KEY_DOWN:
290 ch = CTRL('N');
291 break;
292 case KEY_BACKSPACE:
293 ch = '\b';
294 break;
295 default:
296 beep();
297 continue;
298 }
299 } else if (code == ERR) {
300 beep();
301 break;
302 }
303 if (ch == 'q')
304 break;
305
306 wmove(work, row, margin + 1);
307 switch (ch) {
308 case 'w':
309 test_inserts(level + 1);
310
311 touchwin(look);
312 touchwin(work);
313 touchwin(show);
314
315 wnoutrefresh(look);
316 wnoutrefresh(work);
317 wnoutrefresh(show);
318
319 doupdate();
320 break;
321 case CTRL('N'):
322 if (row < limit) {
323 ++row;
324 /* put the whole string in, all at once */
325 col2 = margin + 1;
326 switch (option) {
327 case oDefault:
328 if (n_opt > 1) {
329 for (col = 0; col < length; col += n_opt) {
330 col2 = ColOf(buffer, col, margin);
331 if (move(row, col2) != ERR) {
332 InsNStr(buffer + col, LEN(col));
333 }
334 }
335 } else {
336 if (move(row, col2) != ERR) {
337 InsStr(buffer);
338 }
339 }
340 break;
341 case oMove:
342 if (n_opt > 1) {
343 for (col = 0; col < length; col += n_opt) {
344 col2 = ColOf(buffer, col, margin);
345 MvInsNStr(row, col2, buffer + col, LEN(col));
346 }
347 } else {
348 MvInsStr(row, col2, buffer);
349 }
350 break;
351 case oWindow:
352 if (n_opt > 1) {
353 for (col = 0; col < length; col += n_opt) {
354 col2 = ColOf(buffer, col, margin);
355 if (wmove(work, row, col2) != ERR) {
356 WInsNStr(work, buffer + col, LEN(col));
357 }
358 }
359 } else {
360 if (wmove(work, row, col2) != ERR) {
361 WInsStr(work, buffer);
362 }
363 }
364 break;
365 case oMoveWindow:
366 if (n_opt > 1) {
367 for (col = 0; col < length; col += n_opt) {
368 col2 = ColOf(buffer, col, margin);
369 MvWInsNStr(work, row, col2, buffer + col, LEN(col));
370 }
371 } else {
372 MvWInsStr(work, row, col2, buffer);
373 }
374 break;
375 }
376
377 /* do the corresponding single-character insertion */
378 row2 = limit + row;
379 for (col = 0; col < length; ++col) {
380 col2 = ColOf(buffer, col, margin);
381 switch (option) {
382 case oDefault:
383 if (move(row2, col2) != ERR) {
384 InsCh((chtype) buffer[col]);
385 }
386 break;
387 case oMove:
388 MvInsCh(row2, col2, (chtype) buffer[col]);
389 break;
390 case oWindow:
391 if (wmove(work, row2, col2) != ERR) {
392 WInsCh(work, (chtype) buffer[col]);
393 }
394 break;
395 case oMoveWindow:
396 MvWInsCh(work, row2, col2, (chtype) buffer[col]);
397 break;
398 }
399 }
400 } else {
401 beep();
402 }
403 break;
404 case KEY_BACKSPACE:
405 ch = '\b';
406 /* FALLTHRU */
407 default:
408 buffer[length++] = ch;
409 buffer[length] = '\0';
410
411 /* put the string in, one character at a time */
412 col = ColOf(buffer, length - 1, margin);
413 switch (option) {
414 case oDefault:
415 if (move(row, col) != ERR) {
416 InsStr(buffer + length - 1);
417 }
418 break;
419 case oMove:
420 MvInsStr(row, col, buffer + length - 1);
421 break;
422 case oWindow:
423 if (wmove(work, row, col) != ERR) {
424 WInsStr(work, buffer + length - 1);
425 }
426 break;
427 case oMoveWindow:
428 MvWInsStr(work, row, col, buffer + length - 1);
429 break;
430 }
431
432 /* do the corresponding single-character insertion */
433 switch (option) {
434 case oDefault:
435 if (move(limit + row, col) != ERR) {
436 InsCh(ch);
437 }
438 break;
439 case oMove:
440 MvInsCh(limit + row, col, ch);
441 break;
442 case oWindow:
443 if (wmove(work, limit + row, col) != ERR) {
444 WInsCh(work, ch);
445 }
446 break;
447 case oMoveWindow:
448 MvWInsCh(work, limit + row, col, ch);
449 break;
450 }
451
452 wnoutrefresh(work);
453
454 legend(show, level, option, buffer, length);
455 wnoutrefresh(show);
456
457 doupdate();
458 break;
459 }
460 }
461 if (level > 0) {
462 delwin(show);
463 delwin(work);
464 delwin(look);
465 }
466}
467
468static void
469usage(void)
470{
471 static const char *tbl[] =
472 {
473 "Usage: inserts [options]"
474 ,""
475 ,"Options:"
476 ," -n NUM limit string-inserts to NUM bytes on ^N replay"
477 ," -m perform wmove/move separately from insert-functions"
478 ," -w use window-parameter even when stdscr would be implied"
479 };
480 unsigned n;
481 for (n = 0; n < SIZEOF(tbl); ++n)
482 fprintf(stderr, "%s\n", tbl[n]);
483 ExitProgram(EXIT_FAILURE);
484}
485
486int
487main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
488{
489 int ch;
490
491 setlocale(LC_ALL, "");
492
493 while ((ch = getopt(argc, argv, "mn:w")) != -1) {
494 switch (ch) {
495 case 'm':
496 m_opt = TRUE;
497 break;
498 case 'n':
499 n_opt = atoi(optarg);
500 if (n_opt == 0)
501 n_opt = -1;
502 break;
503 case 'w':
504 w_opt = TRUE;
505 break;
506 default:
507 usage();
508 break;
509 }
510 }
511 if (optind < argc)
512 usage();
513
514 test_inserts(0);
515 endwin();
516 ExitProgram(EXIT_SUCCESS);
517}
518#else
519int
520main(void)
521{
522 printf("This program requires the wide-ncurses library\n");
523 ExitProgram(EXIT_FAILURE);
524}
525#endif