msg_sys.def revision 1.19 1 /* $NetBSD: msg_sys.def,v 1.19 2003/06/04 19:00:26 dsl Exp $ */
2
3 /*
4 * Copyright 1997 Piermont Information Systems Inc.
5 * All rights reserved.
6 *
7 * Written by Philip A. Nelson for Piermont Information Systems Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software develooped for the NetBSD Project by
20 * Piermont Information Systems Inc.
21 * 4. The name of Piermont Information Systems Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35 * THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 */
38
39 static WINDOW *msg_win = NULL;
40 static char *cbuffer;
41 static size_t cbuffersize;
42
43 static int last_i_was_nl, last_i_was_space;
44 static int last_o_was_punct, last_o_was_space;
45
46 static void _msg_beep(void);
47 static int _msg_vprintf(int auto_fill, const char *fmt, va_list ap);
48 static void _msg_vprompt(const char *msg, int do_echo, const char *def,
49 char *val, size_t max_chars, va_list ap);
50
51 /* Routines */
52
53 static void
54 _msg_beep(void)
55 {
56 fprintf(stderr, "\a");
57 }
58
59 int msg_window(WINDOW *window)
60 {
61 size_t ncbuffersize;
62 char *ncbuffer;
63
64 msg_win = window;
65
66 ncbuffersize = getmaxx(window) * getmaxy(window) + 1;
67 if (ncbuffersize > cbuffersize) {
68 ncbuffer = malloc(ncbuffersize);
69 if (ncbuffer == NULL)
70 return 1;
71 if (cbuffer != NULL)
72 free(cbuffer);
73 cbuffer = ncbuffer;
74 cbuffersize = ncbuffersize;
75 }
76 return 0;
77 }
78
79 const char *msg_string (msg msg_no)
80 {
81 int m = (intptr_t)msg_no;
82
83 if (m > sizeof msg_list / sizeof msg_list[0])
84 /* guess that we were passed a text string */
85 return msg_no;
86 return msg_list[m];
87 }
88
89 void msg_clear(void)
90 {
91 wclear (msg_win);
92 wrefresh (msg_win);
93 last_o_was_punct = 0;
94 last_o_was_space = 1;
95 }
96
97 void msg_standout(void)
98 {
99 wstandout(msg_win);
100 }
101
102 void msg_standend(void)
103 {
104 wstandend(msg_win);
105 }
106
107 static int
108 _msg_vprintf(int auto_fill, const char *fmt, va_list ap)
109 {
110 const char *wstart, *afterw;
111 int wordlen, nspaces;
112 int ret;
113
114 ret = vsnprintf (cbuffer, cbuffersize, fmt, ap);
115
116 if (!auto_fill) {
117 waddstr(msg_win, cbuffer);
118
119 /*
120 * nothing is perfect if they flow text after a table,
121 * but this may be decent.
122 */
123 last_i_was_nl = last_i_was_space = 1;
124 last_o_was_punct = 0;
125 last_o_was_space = 1;
126 goto out;
127 }
128
129 for (wstart = afterw = cbuffer; *wstart; wstart = afterw) {
130
131 /* eat one space, or a whole word of non-spaces */
132 if (isspace(*afterw))
133 afterw++;
134 else
135 while (*afterw && !isspace(*afterw))
136 afterw++;
137
138 /* this is an nl: special formatting necessary */
139 if (*wstart == '\n') {
140 if (last_i_was_nl || last_i_was_space) {
141
142 if (getcurx(msg_win) != 0)
143 waddch(msg_win, '\n');
144 if (last_i_was_nl) {
145 /* last was an nl: paragraph break */
146 waddch(msg_win, '\n');
147 } else {
148 /* last was space: line break */
149 }
150 last_o_was_punct = 0;
151 last_o_was_space = 1;
152 } else {
153 /* last_o_was_punct unchanged */
154 /* last_o_was_space unchanged */
155 }
156 last_i_was_space = 1;
157 last_i_was_nl = 1;
158 continue;
159 }
160
161 /* this is a tab: special formatting necessary. */
162 if (*wstart == '\t') {
163 if (last_i_was_nl) {
164 /* last was an nl: list indent */
165 if (getcurx(msg_win) != 0)
166 waddch(msg_win, '\n');
167 } else {
168 /* last was not an nl: columns */
169 }
170 waddch(msg_win, '\t');
171 last_i_was_nl = 0;
172 last_i_was_space = 1;
173 last_o_was_punct = 0;
174 last_o_was_space = 1;
175 continue;
176 }
177
178 /* this is a space: ignore it but set flags */
179 last_i_was_nl = 0; /* all newlines handled above */
180 last_i_was_space = isspace(*wstart);
181 if (last_i_was_space)
182 continue;
183
184 /*
185 * we have a real "word," i.e. a sequence of non-space
186 * characters. wstart is now the start of the word,
187 * afterw is the next character after the end.
188 */
189 wordlen = afterw - wstart;
190 nspaces = last_o_was_space ? 0 : (last_o_was_punct ? 2 : 1);
191 if ((getcurx(msg_win) + nspaces + wordlen) >=
192 getmaxx(msg_win) &&
193 wordlen < (getmaxx(msg_win) / 3)) {
194 /* wrap the line */
195 waddch(msg_win, '\n');
196 nspaces = 0;
197 }
198
199 /* output the word, preceded by spaces if necessary */
200 while (nspaces-- > 0)
201 waddch(msg_win, ' ');
202 waddbytes(msg_win, wstart, wordlen);
203
204 /* set up the 'last' state for the next time around */
205 switch (afterw[-1]) {
206 case '.':
207 case '?':
208 case '!':
209 last_o_was_punct = 1;
210 break;
211 default:
212 last_o_was_punct = 0;
213 break;
214 }
215 last_o_was_space = 0;
216
217 /* ... and do it all again! */
218 }
219
220 /* String ended with a newline. They really want a line break. */
221 if (last_i_was_nl) {
222 if (getcurx(msg_win) != 0)
223 waddch(msg_win, '\n');
224 last_o_was_punct = 0;
225 last_o_was_space = 1;
226 }
227
228 out:
229 wrefresh (msg_win);
230 return ret;
231 }
232
233 void msg_display(msg msg_no, ...)
234 {
235 va_list ap;
236
237 msg_clear();
238
239 va_start(ap, msg_no);
240 (void)_msg_vprintf(1, msg_string(msg_no), ap);
241 va_end(ap);
242 }
243
244 void msg_display_add(msg msg_no, ...)
245 {
246 va_list ap;
247
248 va_start (ap, msg_no);
249 (void)_msg_vprintf(1, msg_string(msg_no), ap);
250 va_end (ap);
251 }
252
253 static void
254 _erase_ch(void)
255 {
256 int y, x;
257
258 getyx(msg_win, y, x);
259 x--;
260 wmove(msg_win, y, x);
261 waddch(msg_win, ' ');
262 wmove(msg_win, y, x);
263 }
264
265 static void
266 _msg_vprompt(const char *msg, int do_echo, const char *def, char *val,
267 size_t max_chars, va_list ap)
268 {
269 int ch;
270 int count = 0;
271 char *ibuf = alloca(max_chars);
272
273 _msg_vprintf(0, msg, ap);
274 if (def != NULL && *def) {
275 waddstr (msg_win, " [");
276 waddstr (msg_win, def);
277 waddstr (msg_win, "]");
278 }
279 waddstr (msg_win, ": ");
280 wrefresh (msg_win);
281
282 while ((ch = wgetch(msg_win)) != '\n') {
283 if (ch == 0x08 || ch == 0x7f) { /* bs or del */
284 if (count > 0) {
285 count--;
286 if (do_echo)
287 _erase_ch();
288 } else
289 _msg_beep();
290 } else if (ch == 0x15) { /* ^U; line kill */
291 while (count > 0) {
292 count--;
293 if (do_echo)
294 _erase_ch();
295 }
296 } else if (ch == 0x17) { /* ^W; word kill */
297 /*
298 * word kill kills the spaces and the 'word'
299 * (non-spaces) last typed. the spaces before
300 * the 'word' aren't killed.
301 */
302 while (count > 0 && isspace(ibuf[count - 1])) {
303 count--;
304 if (do_echo)
305 _erase_ch();
306 }
307 while (count > 0 && !isspace(ibuf[count - 1])) {
308 count--;
309 if (do_echo)
310 _erase_ch();
311 }
312 } else if (count < (max_chars - 1) && isprint(ch)) {
313 if (do_echo)
314 waddch (msg_win, ch);
315 ibuf[count++] = ch;
316 } else
317 _msg_beep();
318 if (do_echo)
319 wrefresh(msg_win);
320 }
321 if (do_echo) {
322 waddch(msg_win, '\n');
323 last_o_was_punct = 0;
324 last_o_was_space = 1;
325 }
326
327 /* copy the appropriate string to the output */
328 if (count != 0) {
329 ibuf[count] = '\0';
330 strcpy(val, ibuf); /* size known to be OK */
331 } else if (def != NULL && val != def) {
332 strlcpy(val, def, max_chars);
333 }
334 }
335
336 void
337 msg_prompt(msg msg_no, const char *def, char *val, size_t max_chars, ...)
338 {
339 va_list ap;
340
341 msg_clear();
342
343 va_start (ap, max_chars);
344 _msg_vprompt(msg_string(msg_no), 1, def, val, max_chars, ap);
345 va_end (ap);
346 }
347
348 void
349 msg_prompt_win(msg msg_no, WINDOW *win,
350 const char *def, char *val, size_t max_chars, ...)
351 {
352 va_list ap;
353 WINDOW *sv_win;
354
355 sv_win = msg_win;
356
357 msg_window(win);
358
359 msg_clear();
360
361 if (getmaxy(win) >= 3) {
362 box(win, 0, 0);
363 wmove(win, 1, 1);
364 }
365
366 va_start (ap, max_chars);
367 _msg_vprompt(msg_string(msg_no), 1, def, val, max_chars, ap);
368 va_end (ap);
369
370 msg_clear();
371 msg_window(sv_win);
372 }
373
374 void
375 msg_prompt_add(msg msg_no, const char *def, char *val, size_t max_chars, ...)
376 {
377 va_list ap;
378
379 va_start (ap, max_chars);
380 _msg_vprompt(msg_string(msg_no), 1, def, val, max_chars, ap);
381 va_end(ap);
382 }
383
384 void
385 msg_prompt_noecho(msg msg_no, const char *def, char *val, size_t max_chars, ...)
386 {
387 va_list ap;
388
389 msg_clear();
390
391 va_start (ap, max_chars);
392 _msg_vprompt(msg_string(msg_no), 0, def, val, max_chars, ap);
393 va_end (ap);
394 }
395
396 void msg_table_add(msg msg_no, ...)
397 {
398 va_list ap;
399
400 va_start (ap, msg_no);
401 (void)_msg_vprintf(0, msg_string(msg_no), ap);
402 va_end (ap);
403 }
404
405