1 /* $NetBSD
: msg_sys.def
,v
1.37 2006/12/03 01:18:34 christos Exp $
*/
4 * Copyright
1997 Piermont Information Systems Inc.
7 * Written by Philip A. Nelson for Piermont Information Systems Inc.
9 * Redistribution and use in source and binary forms
, with or without
10 * modification
, are permitted provided that the following conditions
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
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.
39 static WINDOW
*msg_win
= NULL
;
41 static size_t cbuffersize
;
43 static int last_i_was_nl
, last_i_was_space
;
44 static int last_o_was_punct
, last_o_was_space
;
46 static void
_msg_beep(void
);
47 static int
_msg_vprintf(int
, const char
*, va_list
);
48 #define MSG_PROMPT_ECHO
1
49 #define MSG_PROMPT_HIDE_DFLT
2
50 static void
_msg_vprompt(const char
*, int
, const char
*, char
*,
53 static char
*msgmap
= MAP_FAILED
;
54 static size_t msgmapsz
;
55 static unsigned int msgmapcount
;
63 fprintf(stderr
, "\a");
67 msg_window(WINDOW
*window
)
78 ncbuffersize
= getmaxx(window
) * getmaxy(window
) + 1;
79 while (ncbuffersize
> cbuffersize
) {
80 ncbuffer
= malloc(ncbuffersize
);
81 if (ncbuffer
== NULL
) {
82 /* we might get truncated messages...
*/
89 cbuffersize
= ncbuffersize
;
98 msg_file(const char
*file
)
102 if (msgmap
!= MAP_FAILED
)
103 munmap(msgmap
, msgmapsz
);
107 fd
= open(file
, O_RDONLY
, 0);
110 msgmapsz
= lseek(fd
, 0, SEEK_END
);
111 msgmap
= mmap(0, msgmapsz
, PROT_READ
, MAP_SHARED
, fd
, 0);
113 if (msgmap
== MAP_FAILED
)
116 if (strcmp(msgmap
, "MSGTXTS") != 0) {
120 msgmapcount
= atoi(msgmap
+ 8);
125 msg_string(msg msg_no
)
127 uintptr_t m
= (uintptr_t
)msg_no
;
129 if (m
> sizeof msg_list
/ sizeof msg_list
[0])
130 /* guess that we were passed a text string
*/
133 if (msgmap
!= MAP_FAILED
&& m
!= 0 && m
<= msgmapcount
) {
134 unsigned int offset
= atoi(msgmap
+ 8 + 8 * m
);
135 if (offset
!= 0 && offset
< msgmapsz
)
136 return msgmap
+ offset
;
147 last_o_was_punct
= 0;
148 last_o_was_space
= 1;
166 _msg_vprintf(int auto_fill
, const char
*fmt
, va_list ap
)
168 const char
*wstart
, *afterw
;
169 int wordlen
, nspaces
;
172 ret
= vsnprintf(cbuffer
, cbuffersize
, fmt
, ap
);
175 waddstr(msg_win
, cbuffer
);
178 * nothing is perfect if they flow text after a table
,
179 * but this may be decent.
181 last_i_was_nl
= last_i_was_space
= 1;
182 last_o_was_punct
= 0;
183 last_o_was_space
= 1;
187 for (wstart
= afterw
= cbuffer
; *wstart
; wstart
= afterw
) {
189 /* eat one space
, or a whole word of non
-spaces
*/
190 if (isspace((unsigned char
)*afterw
))
193 while (*afterw && !isspace((unsigned char)*afterw))
196 /* this is an nl: special formatting necessary */
197 if (*wstart == '\n') {
198 if (last_i_was_nl || last_i_was_space) {
200 if (getcurx(msg_win) != 0)
201 waddch(msg_win, '\n');
203 /* last was an nl: paragraph break */
204 waddch(msg_win, '\n');
206 /* last was space: line break */
208 last_o_was_punct = 0;
209 last_o_was_space = 1;
211 /* last_o_was_punct unchanged */
212 /* last_o_was_space unchanged */
214 last_i_was_space = 1;
219 /* this is a tab: special formatting necessary. */
220 if (*wstart == '\t') {
222 /* last was an nl: list indent */
223 if (getcurx(msg_win) != 0)
224 waddch(msg_win, '\n');
226 /* last was not an nl: columns */
228 waddch(msg_win, '\t');
230 last_i_was_space = 1;
231 last_o_was_punct = 0;
232 last_o_was_space = 1;
236 /* this is a space: ignore it but set flags */
237 last_i_was_nl = 0; /* all newlines handled above */
238 last_i_was_space = isspace((unsigned char)*wstart);
239 if (last_i_was_space)
243 * we have a real "word," i.e. a sequence of non-space
244 * characters. wstart is now the start of the word,
245 * afterw is the next character after the end.
247 wordlen = afterw - wstart;
248 nspaces = last_o_was_space ? 0 : (last_o_was_punct ? 2 : 1);
249 if ((getcurx(msg_win) + nspaces + wordlen) >=
251 wordlen < (getmaxx(msg_win) / 3)) {
253 waddch(msg_win, '\n');
257 /* output the word, preceded by spaces if necessary */
258 while (nspaces-- > 0)
259 waddch(msg_win, ' ');
260 waddbytes(msg_win, wstart, wordlen);
262 /* set up the 'last' state for the next time around */
263 switch (afterw[-1]) {
267 last_o_was_punct = 1;
270 last_o_was_punct = 0;
273 last_o_was_space = 0;
275 /* ... and do it all again! */
278 /* String ended with a newline. They really want a line break. */
280 if (getcurx(msg_win) != 0)
281 waddch(msg_win, '\n');
282 last_o_was_punct = 0;
283 last_o_was_space = 1;
292 msg_display(msg msg_no, ...)
298 va_start(ap, msg_no);
299 (void)_msg_vprintf(1, msg_string(msg_no), ap);
304 msg_display_add(msg msg_no, ...)
308 va_start(ap, msg_no);
309 (void)_msg_vprintf(1, msg_string(msg_no), ap);
314 _msg_vprompt(const char *fmt, int flags, const char *def, char *val,
315 size_t val_buf_len, va_list ap)
318 int len, pos, npos, off;
324 if (val == NULL || val_buf_len == 0) {
325 /* No answer wanted */
330 ibuf = malloc(val_buf_len);
332 keypad(msg_win, TRUE);
333 _msg_vprintf(0, fmt, ap);
335 if (def != NULL && *def) {
336 if (flags & MSG_PROMPT_HIDE_DFLT)
337 strlcpy(ibuf, def, val_buf_len);
339 waddstr(msg_win, " [");
340 waddstr(msg_win, def);
341 waddstr(msg_win, "]");
344 waddstr(msg_win, ": ");
347 getyx(msg_win, txt_y, txt_x);
348 maxx = getmaxx(msg_win) - txt_x - 1;
351 for (first = 1; ; first = 0) {
353 if (flags & MSG_PROMPT_ECHO) {
354 /* shift text right as we near the buffer start */
357 /* keep offset to a minimum if we are at the end */
360 if (off < 0 || len <= maxx)
362 /* shift text left as we near the buffer end */
366 if (npos - off > maxx)
368 /* calc. length to display */
372 mvwaddnstr(msg_win, txt_y, txt_x, ibuf + off, npos);
375 mvwaddstr(msg_win, txt_y, txt_x, "+");
376 wmove(msg_win, txt_y, txt_x + pos - off);
380 ch = wgetch(msg_win);
386 case 'h' & 0x1f: case 0x7f: /* bs or del - delete left */
388 /* delete all of default string */
393 memmove(ibuf + pos - 1, ibuf + pos, len - pos);
399 case 'u' & 0x1f: /* ^U; line kill */
403 case 'w' & 0x1f: /* ^W; word kill */
405 * word kill kills the spaces and the 'word'
406 * (non-spaces) last typed. the spaces before
407 * the 'word' aren't killed.
410 while (npos > 0 && isspace((unsigned char)ibuf[npos - 1]))
412 while (npos > 0 && !isspace((unsigned char)ibuf[npos - 1]))
414 memmove(ibuf + npos, ibuf + pos, len - pos);
423 if (len == 0 && pos == 0 && def != NULL) {
424 /* restore default! */
425 strlcpy(ibuf, def, val_buf_len);
426 len = pos = strlen(ibuf);
433 if (len < (int)(val_buf_len - 1) && isprint(ch)) {
434 memmove(ibuf + pos + 1, ibuf + pos, len - pos);
443 if (flags & MSG_PROMPT_ECHO) {
444 mvwaddch(msg_win, txt_y, txt_x + len - off, '\n');
445 last_o_was_punct = 0;
446 last_o_was_space = 1;
450 /* copy the appropriate string to the output */
451 if (len != 0 || flags & MSG_PROMPT_HIDE_DFLT) {
453 strlcpy(val, ibuf, val_buf_len);
454 } else if (def != NULL && val != def) {
455 strlcpy(val, def, val_buf_len);
462 msg_prompt(msg msg_no, const char *def, char *val, size_t val_buf_len, ...)
468 va_start(ap, val_buf_len);
469 _msg_vprompt(msg_string(msg_no), MSG_PROMPT_ECHO,
470 def, val, val_buf_len, ap);
475 msg_prompt_win(msg msg_no, int x, int y, int w, int h,
476 const char *def, char *val, size_t val_buf_len, ...)
480 WINDOW *svmsg = NULL, *sv_win = NULL; /* XXX -Wuninitialized [many] */
482 int msg_flags = MSG_PROMPT_ECHO | MSG_PROMPT_HIDE_DFLT;
484 maxx = getmaxx(msg_win);
485 maxy = getmaxy(msg_win);
487 va_start(ap, val_buf_len);
488 w = vsnprintf(NULL, 0, msg_string(msg_no), ap);
490 if (def != NULL && *def != 0 && w + (int)val_buf_len * 2 < maxx) {
491 w += 2 + strlen(def) + 1;
492 msg_flags &= ~MSG_PROMPT_HIDE_DFLT;
494 w += 1 + 2 + val_buf_len + 1;
496 if (!(msg_flags & MSG_PROMPT_HIDE_DFLT)) {
497 w -= 2 + strlen(def) + 1;
498 msg_flags |= MSG_PROMPT_HIDE_DFLT;
505 x = (maxx - w) / 2 + 1;
513 win = subwin(msg_win, h, w, y, x);
515 wprintw(msg_win, "msg_prompt_win: "
516 "newwin(%d, %d, %d, %d) failed\n",
520 * Save screen contents from under our window
521 * Due to a mis-feature of NetBSD curses, curscr contains
522 * the data processed by doupdate() not that by wnoutrefresh().
523 * We must call doupdate() here to ensure we save the correct
527 sv_win = dupwin(win);
529 overwrite(curscr, sv_win);
530 wbkgd(win, getbkgd(msg_win));
531 wattrset(win, getattrs(msg_win));
535 /* Change message window to be our little box */
536 svmsg = msg_window(subwin(msg_win, h - 2, w - 2, y + 1, x + 1));
537 wbkgd(msg_win, getbkgd(win));
538 wattrset(msg_win, getattrs(win));
543 va_start(ap, val_buf_len);
544 _msg_vprompt(msg_string(msg_no), msg_flags, def, val, val_buf_len, ap);
550 /* Restore original screen contents */
551 overwrite(sv_win, win);
555 /* Restore normal message window */
556 delwin(msg_window(svmsg));
562 msg_prompt_add(msg msg_no, const char *def, char *val, size_t val_buf_len, ...)
566 va_start(ap, val_buf_len);
567 _msg_vprompt(msg_string(msg_no), MSG_PROMPT_ECHO, def, val, val_buf_len, ap);
572 msg_prompt_noecho(msg msg_no, const char *def, char *val, size_t val_buf_len, ...)
578 va_start(ap, val_buf_len);
579 _msg_vprompt(msg_string(msg_no), 0, def, val, val_buf_len, ap);
584 msg_table_add(msg msg_no, ...)
588 va_start(ap, msg_no);
589 (void)_msg_vprintf(0, msg_string(msg_no), ap);
597 return getcury(msg_win) + getbegy(msg_win);