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