1 /****************************************************************************
2 * Copyright 2020,2021 Thomas E. Dickey *
3 * Copyright 2006-2012,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: redraw.c,v 1.13 2021/06/17 21:26:02 tom Exp $
31 *
32 * Demonstrate the redrawwin() and wredrawln() functions.
33 * Thomas Dickey - 2006/11/4
34 */
35
36 #include <test.priv.h>
37 #include <popup_msg.h>
38
39 static void
trash(int beg_x,int max_x,int cur_x)40 trash(int beg_x, int max_x, int cur_x)
41 {
42 int x;
43
44 for (x = cur_x; x > beg_x; --x) {
45 putchar('\b');
46 }
47 for (x = beg_x; x < max_x; ++x) {
48 if (x < cur_x)
49 putchar('<');
50 else if (x == cur_x)
51 putchar('=');
52 else if (x > cur_x)
53 putchar('>');
54 }
55 for (x = max_x; x > cur_x; --x) {
56 putchar('\b');
57 }
58 fflush(stdout);
59 }
60
61 static void
test_redraw(WINDOW * win)62 test_redraw(WINDOW *win)
63 {
64 static const char *help[] =
65 {
66 "Commands:",
67 " ^Q/ESC/q - quit",
68 " w - recur in a new window",
69 " ! - overwrite current line using stdio outside curses.",
70 #ifdef NCURSES_VERSION
71 " @ - run \"date\" command, to put its output on screen.",
72 #endif
73 " ^L - call redrawwin() for current window.",
74 " ^W - call wredrawln() for current line/current window.",
75 " arrow-keys - move cursor on the screen",
76 "",
77 "Other control characters are added to the screen in printable form.",
78 "Other printable characters are added to the screen as is.",
79 0
80 };
81
82 WINDOW *win1;
83 WINDOW *win2;
84 bool done = FALSE;
85 int max_y, max_x;
86 int beg_y, beg_x;
87
88 assert(win != 0);
89
90 scrollok(win, TRUE);
91 keypad(win, TRUE);
92 getmaxyx(win, max_y, max_x);
93 getbegyx(win, beg_y, beg_x);
94
95 while (!done) {
96 int ch = wgetch(win);
97 int y, x;
98
99 getyx(win, y, x);
100 switch (ch) {
101 case 'q':
102 /* FALLTHRU */
103 case QUIT:
104 case ESCAPE:
105 done = TRUE;
106 break;
107 case 'w':
108 win1 = newwin(max_y, max_x,
109 beg_y, beg_x);
110 win2 = newwin(max_y - 2, max_x - 2,
111 beg_y + 1, beg_x + 1);
112 box(win1, 0, 0);
113 wrefresh(win1);
114
115 test_redraw(win2);
116
117 delwin(win2);
118 delwin(win1);
119
120 touchwin(win);
121 break;
122
123 case '!':
124 /*
125 * redrawwin() and wredrawln() do not take into account the
126 * possibility that the cursor may have moved. That makes them
127 * cumbersome for using with a shell command. So we simply
128 * trash the current line of the window using backspace/overwrite.
129 */
130 trash(beg_x, max_x, x + beg_x);
131 break;
132
133 #ifdef NCURSES_VERSION
134 case '@':
135 /*
136 * For a shell command, we can work around the problem noted above
137 * using mvcur(). It is ifdef'd for NCURSES, since X/Open does
138 * not define the case where the old location is unknown.
139 */
140 IGNORE_RC(system("date"));
141 mvcur(-1, -1, y, x);
142 break;
143 #endif
144
145 case CTRL('W'):
146 redrawwin(win);
147 break;
148
149 case CTRL('L'):
150 wredrawln(win, y, 1);
151 break;
152
153 case KEY_UP:
154 if (y > 0)
155 wmove(win, y - 1, x);
156 break;
157
158 case KEY_DOWN:
159 if (y < max_y)
160 wmove(win, y + 1, x);
161 break;
162
163 case KEY_LEFT:
164 if (x > 0)
165 wmove(win, y, x - 1);
166 break;
167
168 case KEY_RIGHT:
169 if (x < max_x)
170 wmove(win, y, x + 1);
171 break;
172
173 case HELP_KEY_1:
174 popup_msg(win, help);
175 break;
176
177 default:
178 if (ch > KEY_MIN) {
179 waddstr(win, keyname(ch));
180 waddch(win, '\n');
181 } else {
182 waddstr(win, unctrl(UChar(ch)));
183 }
184 break;
185 }
186 wnoutrefresh(win);
187 doupdate();
188 }
189 }
190
191 static void
usage(void)192 usage(void)
193 {
194 static const char *tbl[] =
195 {
196 "Usage: redraw [options]"
197 ,""
198 ,"Options:"
199 ," -e use stderr (default stdout)"
200 ," -n do not initialize terminal"
201 };
202 unsigned n;
203 for (n = 0; n < SIZEOF(tbl); ++n)
204 fprintf(stderr, "%s\n", tbl[n]);
205 ExitProgram(EXIT_FAILURE);
206 }
207
208 int
main(int argc GCC_UNUSED,char * argv[]GCC_UNUSED)209 main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
210 {
211 int ch;
212 bool no_init = FALSE;
213 FILE *my_fp = stdout;
214
215 while ((ch = getopt(argc, argv, "en")) != -1) {
216 switch (ch) {
217 case 'e':
218 my_fp = stderr;
219 break;
220 case 'n':
221 no_init = TRUE;
222 break;
223 default:
224 usage();
225 break;
226 }
227 }
228 if (optind < argc)
229 usage();
230
231 if (no_init) {
232 START_TRACE();
233 } else {
234 newterm((char *) 0, my_fp, stdin);
235 }
236
237 raw();
238 noecho();
239 test_redraw(stdscr);
240 endwin();
241 ExitProgram(EXIT_SUCCESS);
242 }
243