msg_sys.def revision 1.12 1 /* $NetBSD: msg_sys.def,v 1.12 1999/07/04 10:13:12 cgd 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 static int do_echo = 1;
43
44 static int last_i_was_nl, last_i_was_space;
45 static int last_o_was_punct, last_o_was_space;
46
47 static int _msg_vprintf(int auto_fill, char *fmt, va_list ap);
48 static void _msg_vprompt(char *msg, char *def, char *val, int max_chars,
49 va_list ap);
50
51 /* Routines */
52
53 void msg_beep (void)
54 {
55 fprintf (stderr, "\a");
56 }
57
58 int msg_window(WINDOW *window)
59 {
60 size_t ncbuffersize;
61 char *ncbuffer;
62
63 msg_win = window;
64
65 ncbuffersize = getmaxx(window) * getmaxy(window) + 1;
66 if (ncbuffersize > cbuffersize) {
67 ncbuffer = malloc(ncbuffersize);
68 if (ncbuffer == NULL)
69 return 1;
70 if (cbuffer != NULL)
71 free(cbuffer);
72 cbuffer = ncbuffer;
73 cbuffersize = ncbuffersize;
74 }
75 return 0;
76 }
77
78 char *msg_string (int msg_no)
79 {
80 return msg_list[msg_no];
81 }
82
83 void msg_clear(void)
84 {
85 wclear (msg_win);
86 wrefresh (msg_win);
87 last_o_was_punct = 0;
88 last_o_was_space = 1;
89 }
90
91 void msg_standout(void)
92 {
93 wstandout(msg_win);
94 }
95
96 void msg_standend(void)
97 {
98 wstandend(msg_win);
99 }
100
101 static int
102 _msg_vprintf(int auto_fill, char *fmt, va_list ap)
103 {
104 const char *wstart, *afterw;
105 int wordlen, nspaces;
106 int ret;
107
108 ret = vsnprintf (cbuffer, cbuffersize, fmt, ap);
109
110 if (!auto_fill) {
111 waddstr(msg_win, cbuffer);
112
113 /*
114 * nothing is perfect if they flow text after a table,
115 * but this may be decent.
116 */
117 last_i_was_nl = last_i_was_space = 1;
118 last_o_was_punct = 0;
119 last_o_was_space = 1;
120 goto out;
121 }
122
123 for (wstart = afterw = cbuffer; *wstart; wstart = afterw) {
124
125 /* eat one space, or a whole word of non-spaces */
126 if (isspace(*afterw))
127 afterw++;
128 else
129 while (*afterw && !isspace(*afterw))
130 afterw++;
131
132 /* this is an nl: special formatting necessary */
133 if (*wstart == '\n') {
134 if (last_i_was_nl || last_i_was_space) {
135
136 if (getcurx(msg_win) != 0)
137 waddch(msg_win, '\n');
138 if (last_i_was_nl) {
139 /* last was an nl: paragraph break */
140 waddch(msg_win, '\n');
141 } else {
142 /* last was space: line break */
143 }
144 last_o_was_punct = 0;
145 last_o_was_space = 1;
146 } else {
147 /* last_o_was_punct unchanged */
148 /* last_o_was_space unchanged */
149 }
150 last_i_was_space = 1;
151 last_i_was_nl = 1;
152 continue;
153 }
154
155 /* this is a tab: special formatting necessary. */
156 if (*wstart == '\t') {
157 if (last_i_was_nl) {
158 /* last was an nl: list indent */
159 if (getcurx(msg_win) != 0)
160 waddch(msg_win, '\n');
161 } else {
162 /* last was not an nl: columns */
163 }
164 waddch(msg_win, '\t');
165 last_i_was_nl = 0;
166 last_i_was_space = 1;
167 last_o_was_punct = 0;
168 last_o_was_space = 1;
169 continue;
170 }
171
172 /* this is a space: ignore it but set flags */
173 last_i_was_nl = 0; /* all newlines handled above */
174 last_i_was_space = isspace(*wstart);
175 if (last_i_was_space)
176 continue;
177
178 /*
179 * we have a real "word," i.e. a sequence of non-space
180 * characters. wstart is now the start of the word,
181 * afterw is the next character after the end.
182 */
183 wordlen = afterw - wstart;
184 nspaces = last_o_was_space ? 0 : (last_o_was_punct ? 2 : 1);
185 if ((getcurx(msg_win) + nspaces + wordlen) >=
186 getmaxx(msg_win) &&
187 wordlen < (getmaxx(msg_win) / 3)) {
188 /* wrap the line */
189 waddch(msg_win, '\n');
190 nspaces = 0;
191 }
192
193 /* output the word, preceded by spaces if necessary */
194 while (nspaces-- > 0)
195 waddch(msg_win, ' ');
196 waddbytes(msg_win, wstart, wordlen);
197
198 /* set up the 'last' state for the next time around */
199 switch (afterw[-1]) {
200 case '.':
201 case '?':
202 case '!':
203 last_o_was_punct = 1;
204 break;
205 default:
206 last_o_was_punct = 0;
207 break;
208 }
209 last_o_was_space = 0;
210
211 /* ... and do it all again! */
212 }
213
214 /* String ended with a newline. They really want a line break. */
215 if (last_i_was_nl) {
216 if (getcurx(msg_win) != 0)
217 waddch(msg_win, '\n');
218 last_o_was_punct = 0;
219 last_o_was_space = 1;
220 }
221
222 out:
223 wrefresh (msg_win);
224 return ret;
225 }
226
227 void msg_display(int msg_no, ...)
228 {
229 va_list ap;
230
231 msg_clear();
232
233 va_start(ap, msg_no);
234 (void)_msg_vprintf(1, msg_list[msg_no], ap);
235 va_end(ap);
236 }
237
238 void msg_display_add(int msg_no, ...)
239 {
240 va_list ap;
241
242 va_start (ap, msg_no);
243 (void)_msg_vprintf(1, msg_list[msg_no], ap);
244 va_end (ap);
245 }
246
247 int msg_printf (char *fmt, ...)
248 {
249 va_list ap;
250 int res;
251
252 msg_clear();
253
254 va_start (ap, fmt);
255 res = _msg_vprintf(1, fmt, ap);
256 va_end (ap);
257 return res;
258 }
259
260 int msg_printf_add (char *fmt, ...)
261 {
262 va_list ap;
263 int res;
264
265 va_start (ap, fmt);
266 res = _msg_vprintf(1, fmt, ap);
267 va_end (ap);
268 return res;
269 }
270
271
272 static void
273 _msg_vprompt(char *msg, char *def, char *val, int max_chars, va_list ap)
274 {
275 int ch;
276 int count = 0;
277 int y,x;
278 char *ibuf = alloca(max_chars);
279
280 _msg_vprintf(0, msg, ap);
281 if (def != NULL && *def) {
282 waddstr (msg_win, " [");
283 waddstr (msg_win, def);
284 waddstr (msg_win, "]");
285 }
286 waddstr (msg_win, ": ");
287 wrefresh (msg_win);
288
289 while ((ch = wgetch(msg_win)) != '\n') {
290 if (ch == 0x08 || ch == 0x7f) { /* bs or del */
291 if (count > 0) {
292 count--;
293 if (do_echo) {
294 getyx(msg_win, y, x);
295 x--;
296 wmove(msg_win, y, x);
297 wdelch(msg_win);
298 }
299 } else
300 msg_beep ();
301 } else if (ch == 0x15) { /* ^U; line kill */
302 while (count > 0) {
303 count--;
304 if (do_echo) {
305 getyx(msg_win, y, x);
306 x--;
307 wmove(msg_win, y, x);
308 wdelch(msg_win);
309 }
310 }
311 } else if (ch == 0x17) { /* ^W; word kill */
312 /*
313 * word kill kills the spaces and the 'word'
314 * (non-spaces) last typed. the spaces before
315 * the 'word' aren't killed.
316 */
317 while (count > 0 && isspace(ibuf[count - 1])) {
318 count--;
319 if (do_echo) {
320 getyx(msg_win, y, x);
321 x--;
322 wmove(msg_win, y, x);
323 wdelch(msg_win);
324 }
325 }
326 while (count > 0 && !isspace(ibuf[count - 1])) {
327 count--;
328 if (do_echo) {
329 getyx(msg_win, y, x);
330 x--;
331 wmove(msg_win, y, x);
332 wdelch(msg_win);
333 }
334 }
335 } else if (count < (max_chars - 1) && isprint(ch)) {
336 if (do_echo)
337 waddch (msg_win, ch);
338 ibuf[count++] = ch;
339 } else
340 msg_beep ();
341 if (do_echo)
342 wrefresh(msg_win);
343 }
344 if (do_echo) {
345 waddch(msg_win, '\n');
346 last_o_was_punct = 0;
347 last_o_was_space = 1;
348 }
349
350 /* copy the appropriate string to the output */
351 if (count != 0) {
352 ibuf[count] = '\0';
353 strcpy(val, ibuf); /* size known to be OK */
354 } else if (def != NULL && val != def) {
355 strncpy(val, def, max_chars);
356 val[max_chars - 1] = '\0';
357 }
358 }
359
360 void msg_prompt_add (int msg_no, char *def, char *val, int max_chars, ...)
361 {
362 va_list ap;
363
364 va_start (ap, max_chars);
365 _msg_vprompt(msg_list[msg_no], def, val, max_chars, ap);
366 va_end(ap);
367 }
368
369 void msg_prompt (int msg_no, char *def, char *val, int max_chars, ...)
370 {
371 va_list ap;
372
373 msg_clear();
374
375 va_start (ap, max_chars);
376 _msg_vprompt(msg_list[msg_no], def, val, max_chars, ap);
377 va_end (ap);
378 }
379
380 void msg_noecho()
381 {
382 do_echo = 0;
383 }
384
385 void msg_echo()
386 {
387 do_echo = 1;
388 }
389
390 void msg_table_add(int msg_no, ...)
391 {
392 va_list ap;
393
394 va_start (ap, msg_no);
395 (void)_msg_vprintf(0, msg_list[msg_no], ap);
396 va_end (ap);
397 }
398
399