ncurses 5.7 - patch 20081220
[ncurses.git] / test / clip_printw.c
1 /****************************************************************************
2  * Copyright (c) 2008 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: clip_printw.c,v 1.1 2008/12/20 21:03:06 tom Exp $
30  *
31  * demonstrate how to use printw without wrapping.
32  */
33
34 #include <test.priv.h>
35
36 #define SHOW(n) ((n) == ERR ? "ERR" : "OK")
37 #define COLOR_DEFAULT (-1)
38
39 typedef struct {
40     unsigned c;
41     unsigned v;
42     int status;
43     int pair;
44     unsigned attr;
45     int count;
46     int ch;
47     const char *c_msg;
48     const char *v_msg;
49     int y_val;
50     int x_val;
51     int y_beg, x_beg;
52     int y_max, x_max;
53 } STATUS;
54
55 static int
56 clip_wprintw(WINDOW *win, const char *fmt,...)
57 {
58     int y0, x0, y1, x1, width;
59     WINDOW *sub;
60     va_list ap;
61     int rc;
62
63     /*
64      * Allocate a single-line derived window extending from the current
65      * cursor position to the end of the current line in the given window.
66      * Disable scrolling in the derived window.
67      */
68     getyx(win, y0, x0);
69     width = getmaxx(win) - x0;
70     sub = derwin(win, 1, width, y0, x0);
71     scrollok(sub, FALSE);
72
73     /*
74      * Print the text.
75      */
76     va_start(ap, fmt);
77     rc = vw_printw(sub, fmt, ap);
78     va_end(ap);
79
80     getyx(sub, y1, x1);
81     delwin(sub);
82
83     wmove(win, y1 + y0, x1 + x0);
84
85     return rc;
86 }
87
88 static const char *
89 color_params(unsigned state, int *pair)
90 {
91     /* *INDENT-OFF* */
92     static struct {
93         int pair;
94         int fg, bg;
95         const char *msg;
96     } table[] = {
97         { 0, COLOR_DEFAULT, COLOR_DEFAULT, "default" },
98         { 1, COLOR_RED,     COLOR_BLACK,   "red/black" },
99         { 2, COLOR_WHITE,   COLOR_BLUE,    "white/blue" },
100     };
101     /* *INDENT-ON* */
102
103     static bool first = TRUE;
104     const char *result = 0;
105
106     if (has_colors()) {
107         if (first) {
108             unsigned n;
109
110             start_color();
111             for (n = 0; n < SIZEOF(table); ++n) {
112                 init_pair(table[n].pair, table[n].fg, table[n].bg);
113             }
114         }
115         if (state < SIZEOF(table)) {
116             *pair = table[state].pair;
117             result = table[state].msg;
118         }
119     }
120     return result;
121 }
122
123 static const char *
124 video_params(unsigned state, unsigned *attr)
125 {
126     /* *INDENT-OFF* */
127     static struct {
128         unsigned attr;
129         const char *msg;
130     } table[] = {
131         { A_NORMAL,     "normal" },
132         { A_BOLD,       "bold" },
133         { A_REVERSE,    "reverse" },
134         { A_UNDERLINE,  "underline" },
135         { A_BLINK,      "blink" },
136     };
137     /* *INDENT-ON* */
138
139     const char *result = 0;
140
141     if (state < SIZEOF(table)) {
142         *attr = table[state].attr;
143         result = table[state].msg;
144     }
145     return result;
146 }
147
148 /* fill the window with a test-pattern */
149 static void
150 fill_window(WINDOW *win)
151 {
152     int y, x;
153
154     getyx(win, y, x);
155     wmove(win, 0, 0);
156     while (waddstr(win, "0123456789 abcdefghijklmnopqrstuvwxyz ") != ERR) {
157     }
158     wmove(win, y, x);
159 }
160
161 static void
162 show_status(WINDOW *win, STATUS * sp)
163 {
164     int y, x;
165
166     getyx(win, y, x);
167     wmove(win, 0, 0);
168     wprintw(win, "Count %d", sp->count);
169     if (sp->v_msg != 0)
170         wprintw(win, " Video %s", sp->v_msg);
171     if (sp->c_msg != 0)
172         wprintw(win, " Color %s", sp->c_msg);
173     wprintw(win, " (%d)", sp->status);
174     wclrtoeol(win);
175     wmove(win, y, x);
176 }
177
178 static void
179 do_subwindow(WINDOW *win, STATUS * sp, void func(WINDOW *))
180 {
181     WINDOW *win1 = newwin(sp->y_max - 2, sp->x_max - 2,
182                           sp->y_beg + 1, sp->x_beg + 1);
183
184     if (win1 != 0 && sp->y_max > 4 && sp->x_max > 4) {
185         WINDOW *win2 = derwin(win1, sp->y_max - 4, sp->x_max - 4, 1, 1);
186
187         if (win2 != 0) {
188             box(win1, 0, 0);
189             wrefresh(win1);
190             func(win2);
191
192             delwin(win2);
193         } else {
194             beep();
195         }
196         delwin(win1);
197         touchwin(win);
198     } else {
199         beep();
200     }
201 }
202
203 static void
204 init_status(WINDOW *win, STATUS * sp)
205 {
206     memset(sp, 0, sizeof(*sp));
207     sp->c = 99;
208     sp->v = 99;
209     sp->ch = ' ';
210
211     keypad(win, TRUE);
212     fill_window(win);
213
214     getbegyx(win, sp->y_beg, sp->x_beg);
215     getmaxyx(win, sp->y_max, sp->x_max);
216 }
217
218 static void
219 show_help(WINDOW *win)
220 {
221     static const char *table[] =
222     {
223         "Basic commands:"
224         ,"Use h/j/k/l or arrow keys to move the cursor."
225         ,"Set the count parameter for clip_wprintw by entering digits 0-9."
226         ,""
227         ,"Other commands:"
228         ,"space toggles through the set of video attributes and colors."
229         ,"t     touches (forces repaint) of the current line."
230         ,".     calls clip_wprintw at the current position with the given count."
231         ,"=     resets count to zero."
232         ,"?     shows this help-window"
233         ,""
234     };
235
236     int y_max, x_max;
237     int row;
238
239     getmaxyx(win, y_max, x_max);
240     for (row = 0; row < (int) SIZEOF(table) && row < y_max; ++row) {
241         mvwprintw(win, row, 0, "%.*s", x_max, table[row]);
242     }
243     while (wgetch(win) != 'q')
244         beep();
245 }
246
247 static void
248 update_status(WINDOW *win, STATUS * sp)
249 {
250     switch (sp->ch) {
251     case ' ':                   /* next test-iteration */
252         if (has_colors()) {
253             if ((sp->c_msg = color_params(++(sp->c), &(sp->pair))) == 0) {
254                 sp->c_msg = color_params(sp->c = 0, &(sp->pair));
255                 if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) {
256                     sp->v_msg = video_params(sp->v = 0, &(sp->attr));
257                 }
258             }
259         } else {
260             if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) {
261                 sp->v_msg = video_params(sp->v = 0, &(sp->attr));
262             }
263         }
264         sp->count = 0;
265         show_status(win, sp);
266         break;
267     case KEY_LEFT:
268     case 'h':
269         if (sp->x_val > 0)
270             wmove(win, sp->y_val, --(sp->x_val));
271         break;
272     case KEY_DOWN:
273     case 'j':
274         if (sp->y_val < sp->y_max)
275             wmove(win, ++(sp->y_val), sp->x_val);
276         break;
277     case KEY_UP:
278     case 'k':
279         if (sp->y_val > 0)
280             wmove(win, --(sp->y_val), sp->x_val);
281         break;
282     case KEY_RIGHT:
283     case 'l':
284         if (sp->x_val < sp->x_max)
285             wmove(win, sp->y_val, ++(sp->x_val));
286         break;
287     case 't':
288         touchline(win, sp->y_val, 1);
289         break;
290     case '=':
291         sp->count = 0;
292         show_status(win, sp);
293         break;
294     case '?':
295         do_subwindow(win, sp, show_help);
296         break;
297     default:
298         if (isdigit(sp->ch)) {
299             sp->count = (sp->count * 10) + (sp->ch - '0');
300             show_status(win, sp);
301         } else {
302             beep();
303         }
304         break;
305     }
306 }
307
308 static void
309 test_clipping(WINDOW *win)
310 {
311     STATUS st;
312     char fmt[80];
313     char *buffer;
314     unsigned j, need;
315
316     init_status(win, &st);
317
318     do {
319         switch (st.ch) {
320         case '.':               /* change from current position */
321             wattrset(win, st.attr | COLOR_PAIR(st.pair));
322             if (st.count > 0) {
323                 need = st.count + 1;
324                 sprintf(fmt, "%%c%%%ds%%c", st.count);
325             } else {
326                 need = getmaxx(win) - 1;
327                 strcpy(fmt, "%c%s%c");
328             }
329             if ((buffer = typeMalloc(char, need)) != 0) {
330                 for (j = 0; j < need; ++j) {
331                     buffer[j] = 'A' + (j % 26);
332                 }
333                 buffer[need - 1] = '\0';
334                 st.status = clip_wprintw(win, fmt, '[', buffer, ']');
335             }
336             break;
337         case 'w':
338             do_subwindow(win, &st, test_clipping);
339             break;
340         case 'q':
341             return;
342         default:
343             update_status(win, &st);
344             break;
345         }
346     } while ((st.ch = wgetch(win)) != ERR);
347 }
348
349 int
350 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
351 {
352     initscr();
353     cbreak();
354     noecho();
355
356     test_clipping(stdscr);
357     endwin();
358
359     ExitProgram(EXIT_SUCCESS);
360 }