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