6f3573f47bf3416e84c03989a88a0e888e9664b6
[ncurses.git] / test / ins_wide.c
1 /*
2  * $Id: ins_wide.c,v 1.3 2003/08/09 22:07:23 tom Exp $
3  *
4  * Demonstrate the wins_wstr() and wins_wch functions.
5  * Thomas Dickey - 2002/11/23
6  *
7  * Note: to provide inputs for *ins_wch(), we use setcchar().  A quirk of the
8  * X/Open definition for that function is that the string contains no
9  * characters with negative width.  Any control character (such as tab) falls
10  * into that category.  So it follows that *ins_wch() cannot render a tab
11  * character because there is no legal way to construct a cchar_t containing
12  * one.  X/Open does not document this, and it would be logical to assume that
13  * *ins_wstr() has the same limitation, but it uses a wchar_t string directly,
14  * and does not document how tabs are handled.
15  */
16
17 #include <test.priv.h>
18
19 #define TABSIZE 8
20
21 #if USE_WIDEC_SUPPORT
22 static int margin = (2 * TABSIZE) - 1;
23
24 static void
25 legend(WINDOW *win, wchar_t * buffer, int length)
26 {
27     wmove(win, 0, 0);
28     wprintw(win,
29             "The Strings/Chars displays should match.  Enter any characters.\n");
30     wprintw(win,
31             "Use down-arrow or ^N to repeat on the next line, 'q' to exit.\n");
32     wclrtoeol(win);
33     wprintw(win, "Inserted %d characters <", length);
34     waddwstr(win, buffer);
35     waddstr(win, ">");
36 }
37
38 static int
39 ColOf(wchar_t * buffer, int length)
40 {
41     int n;
42     int result;
43
44     for (n = 0, result = margin + 1; n < length; ++n) {
45         int ch = buffer[n];
46         switch (ch) {
47         case '\n':
48             /* actually newline should clear the remainder of the line
49              * and move to the next line - but that seems a little awkward
50              * in this example.
51              */
52         case '\r':
53             result = 0;
54             break;
55         case '\b':
56             if (result > 0)
57                 --result;
58             break;
59         case '\t':
60             result += (TABSIZE - (result % TABSIZE));
61             break;
62         case '\177':
63             result += 2;
64             break;
65         default:
66             ++result;
67             if (ch < 32)
68                 ++result;
69             break;
70         }
71     }
72     return result;
73 }
74
75 int
76 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
77 {
78     cchar_t tmp_cchar;
79     wchar_t tmp_wchar[2];
80     wint_t ch;
81     int code;
82     int limit;
83     int row = 1;
84     int col;
85     int length;
86     wchar_t buffer[BUFSIZ];
87     WINDOW *work;
88     WINDOW *show;
89
90     putenv("TABSIZE=8");
91     initscr();
92     (void) cbreak();            /* take input chars one at a time, no wait for \n */
93     (void) noecho();            /* don't echo input */
94     keypad(stdscr, TRUE);
95
96     limit = LINES - 5;
97     work = newwin(limit, COLS, 0, 0);
98     show = newwin(4, COLS, limit + 1, 0);
99     keypad(work, TRUE);
100
101     for (col = margin + 1; col < COLS; col += TABSIZE)
102         mvwvline(work, row, col, '.', limit - 2);
103
104     box(work, 0, 0);
105     mvwvline(work, row, margin, ACS_VLINE, limit - 2);
106     mvwvline(work, row, margin + 1, ACS_VLINE, limit - 2);
107     limit /= 2;
108
109     mvwaddstr(work, 1, 2, "String");
110     mvwaddstr(work, limit + 1, 2, "Chars");
111     wnoutrefresh(work);
112
113     buffer[length = 0] = '\0';
114     legend(show, buffer, length);
115     wnoutrefresh(show);
116
117     doupdate();
118
119     /*
120      * Show the characters inserted in color, to distinguish from those that
121      * are shifted.
122      */
123     if (has_colors()) {
124         start_color();
125         init_pair(1, COLOR_WHITE, COLOR_BLUE);
126         wbkgdset(work, COLOR_PAIR(1) | ' ');
127     }
128
129     while ((code = wget_wch(work, &ch)) != ERR) {
130
131         switch (code) {
132         case KEY_CODE_YES:
133             switch (ch) {
134             case KEY_DOWN:
135                 ch = CTRL('N');
136                 break;
137             case KEY_BACKSPACE:
138                 ch = '\b';
139                 break;
140             default:
141                 beep();
142                 continue;
143             }
144             break;
145         }
146         if (ch == 'q')
147             break;
148
149         wmove(work, row, margin + 1);
150         if (ch == CTRL('N')) {
151             if (row < limit) {
152                 ++row;
153                 /* put the whole string in, all at once */
154                 mvwins_wstr(work, row, margin + 1, buffer);
155
156                 /* do the corresponding single-character insertion */
157                 for (col = 0; col < length; ++col) {
158                     memset(&tmp_cchar, 0, sizeof(tmp_cchar));
159                     if (setcchar(&tmp_cchar,
160                                  &(buffer[col]),
161                                  A_NORMAL,
162                                  0,
163                                  (void *) 0) != ERR) {
164                         mvwins_wch(work, limit + row, ColOf(buffer, col), &tmp_cchar);
165                     } else {
166                         beep(); /* even for tabs! */
167                         mvwinsch(work,
168                                  limit + row,
169                                  ColOf(buffer, col), buffer[col]);
170                     }
171                 }
172             } else {
173                 beep();
174             }
175         } else {
176             buffer[length++] = ch;
177             buffer[length] = '\0';
178             /* put the string in, one character at a time */
179             mvwins_wstr(work,
180                         row,
181                         ColOf(buffer, length - 1), buffer + length - 1);
182
183             /* do the corresponding single-character insertion */
184             tmp_wchar[0] = ch;
185             tmp_wchar[1] = 0;
186             if (setcchar(&tmp_cchar,
187                          tmp_wchar,
188                          A_NORMAL,
189                          0,
190                          (void *) 0) != ERR) {
191                 mvwins_wch(work,
192                            limit + row,
193                            ColOf(buffer, length - 1), &tmp_cchar);
194             } else {
195                 beep();         /* even for tabs! */
196                 mvwinsch(work,
197                          limit + row,
198                          ColOf(buffer, length - 1), ch);
199             }
200             wnoutrefresh(work);
201
202             legend(show, buffer, length);
203             wnoutrefresh(show);
204
205             doupdate();
206         }
207     }
208     endwin();
209     ExitProgram(EXIT_SUCCESS);
210 }
211 #else
212 int
213 main(void)
214 {
215     printf("This program requires the wide-ncurses library\n");
216     ExitProgram(EXIT_FAILURE);
217 }
218 #endif