1*d44a5ed1SThomas Cort/* $NetBSD: msg_sys.def,v 1.41 2012/03/06 16:26:01 mbalmer Exp $ */ 2*d44a5ed1SThomas Cort 3*d44a5ed1SThomas Cort/* 4*d44a5ed1SThomas Cort * Copyright 1997 Piermont Information Systems Inc. 5*d44a5ed1SThomas Cort * All rights reserved. 6*d44a5ed1SThomas Cort * 7*d44a5ed1SThomas Cort * Written by Philip A. Nelson for Piermont Information Systems Inc. 8*d44a5ed1SThomas Cort * 9*d44a5ed1SThomas Cort * Redistribution and use in source and binary forms, with or without 10*d44a5ed1SThomas Cort * modification, are permitted provided that the following conditions 11*d44a5ed1SThomas Cort * are met: 12*d44a5ed1SThomas Cort * 1. Redistributions of source code must retain the above copyright 13*d44a5ed1SThomas Cort * notice, this list of conditions and the following disclaimer. 14*d44a5ed1SThomas Cort * 2. Redistributions in binary form must reproduce the above copyright 15*d44a5ed1SThomas Cort * notice, this list of conditions and the following disclaimer in the 16*d44a5ed1SThomas Cort * documentation and/or other materials provided with the distribution. 17*d44a5ed1SThomas Cort * 3. The name of Piermont Information Systems Inc. may not be used to endorse 18*d44a5ed1SThomas Cort * or promote products derived from this software without specific prior 19*d44a5ed1SThomas Cort * written permission. 20*d44a5ed1SThomas Cort * 21*d44a5ed1SThomas Cort * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 22*d44a5ed1SThomas Cort * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23*d44a5ed1SThomas Cort * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24*d44a5ed1SThomas Cort * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 25*d44a5ed1SThomas Cort * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26*d44a5ed1SThomas Cort * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27*d44a5ed1SThomas Cort * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28*d44a5ed1SThomas Cort * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29*d44a5ed1SThomas Cort * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30*d44a5ed1SThomas Cort * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31*d44a5ed1SThomas Cort * THE POSSIBILITY OF SUCH DAMAGE. 32*d44a5ed1SThomas Cort * 33*d44a5ed1SThomas Cort */ 34*d44a5ed1SThomas Cort 35*d44a5ed1SThomas Cortstatic WINDOW *msg_win = NULL; 36*d44a5ed1SThomas Cortstatic char *cbuffer; 37*d44a5ed1SThomas Cortstatic size_t cbuffersize; 38*d44a5ed1SThomas Cort 39*d44a5ed1SThomas Cortstatic int last_i_was_nl, last_i_was_space; 40*d44a5ed1SThomas Cortstatic int last_o_was_punct, last_o_was_space; 41*d44a5ed1SThomas Cort 42*d44a5ed1SThomas Cortstatic void _msg_beep(void); 43*d44a5ed1SThomas Cortstatic int _msg_vprintf(int, const char *, va_list); 44*d44a5ed1SThomas Cort#define MSG_PROMPT_ECHO 1 45*d44a5ed1SThomas Cort#define MSG_PROMPT_HIDE_DFLT 2 46*d44a5ed1SThomas Cortstatic void _msg_vprompt(const char *, int, const char *, char *, 47*d44a5ed1SThomas Cort size_t, va_list); 48*d44a5ed1SThomas Cort 49*d44a5ed1SThomas Cortstatic char *msgmap = MAP_FAILED; 50*d44a5ed1SThomas Cortstatic size_t msgmapsz; 51*d44a5ed1SThomas Cortstatic unsigned int msgmapcount; 52*d44a5ed1SThomas Cort 53*d44a5ed1SThomas Cort/* Routines */ 54*d44a5ed1SThomas Cort 55*d44a5ed1SThomas Cortstatic void 56*d44a5ed1SThomas Cort_msg_beep(void) 57*d44a5ed1SThomas Cort{ 58*d44a5ed1SThomas Cort 59*d44a5ed1SThomas Cort fprintf(stderr, "\a"); 60*d44a5ed1SThomas Cort} 61*d44a5ed1SThomas Cort 62*d44a5ed1SThomas CortWINDOW * 63*d44a5ed1SThomas Cortmsg_window(WINDOW *window) 64*d44a5ed1SThomas Cort{ 65*d44a5ed1SThomas Cort size_t ncbuffersize; 66*d44a5ed1SThomas Cort char *ncbuffer; 67*d44a5ed1SThomas Cort WINDOW *old; 68*d44a5ed1SThomas Cort 69*d44a5ed1SThomas Cort old = msg_win; 70*d44a5ed1SThomas Cort if (!window) 71*d44a5ed1SThomas Cort return old; 72*d44a5ed1SThomas Cort msg_win = window; 73*d44a5ed1SThomas Cort 74*d44a5ed1SThomas Cort ncbuffersize = getmaxx(window) * getmaxy(window) + 1; 75*d44a5ed1SThomas Cort while (ncbuffersize > cbuffersize) { 76*d44a5ed1SThomas Cort ncbuffer = malloc(ncbuffersize); 77*d44a5ed1SThomas Cort if (ncbuffer == NULL) { 78*d44a5ed1SThomas Cort /* we might get truncated messages... */ 79*d44a5ed1SThomas Cort ncbuffersize <<= 1; 80*d44a5ed1SThomas Cort continue; 81*d44a5ed1SThomas Cort } 82*d44a5ed1SThomas Cort if (cbuffer != NULL) 83*d44a5ed1SThomas Cort free(cbuffer); 84*d44a5ed1SThomas Cort cbuffer = ncbuffer; 85*d44a5ed1SThomas Cort cbuffersize = ncbuffersize; 86*d44a5ed1SThomas Cort break; 87*d44a5ed1SThomas Cort } 88*d44a5ed1SThomas Cort last_o_was_punct = 0; 89*d44a5ed1SThomas Cort last_o_was_space = 1; 90*d44a5ed1SThomas Cort return old; 91*d44a5ed1SThomas Cort} 92*d44a5ed1SThomas Cort 93*d44a5ed1SThomas Cortint 94*d44a5ed1SThomas Cortmsg_file(const char *file) 95*d44a5ed1SThomas Cort{ 96*d44a5ed1SThomas Cort int fd; 97*d44a5ed1SThomas Cort 98*d44a5ed1SThomas Cort if (msgmap != MAP_FAILED) 99*d44a5ed1SThomas Cort munmap(msgmap, msgmapsz); 100*d44a5ed1SThomas Cort msgmap = MAP_FAILED; 101*d44a5ed1SThomas Cort if (!file) 102*d44a5ed1SThomas Cort return 0; 103*d44a5ed1SThomas Cort fd = open(file, O_RDONLY, 0); 104*d44a5ed1SThomas Cort if (fd == -1) 105*d44a5ed1SThomas Cort return -1; 106*d44a5ed1SThomas Cort msgmapsz = lseek(fd, 0, SEEK_END); 107*d44a5ed1SThomas Cort msgmap = mmap(0, msgmapsz, PROT_READ, MAP_SHARED, fd, 0); 108*d44a5ed1SThomas Cort close(fd); 109*d44a5ed1SThomas Cort if (msgmap == MAP_FAILED) 110*d44a5ed1SThomas Cort return -1; 111*d44a5ed1SThomas Cort /* check_magic */ 112*d44a5ed1SThomas Cort if (strcmp(msgmap, "MSGTXTS") != 0) { 113*d44a5ed1SThomas Cort msg_file(NULL); 114*d44a5ed1SThomas Cort return -1; 115*d44a5ed1SThomas Cort } 116*d44a5ed1SThomas Cort msgmapcount = atoi(msgmap + 8); 117*d44a5ed1SThomas Cort return 0; 118*d44a5ed1SThomas Cort} 119*d44a5ed1SThomas Cort 120*d44a5ed1SThomas Cortconst char * 121*d44a5ed1SThomas Cortmsg_string(msg msg_no) 122*d44a5ed1SThomas Cort{ 123*d44a5ed1SThomas Cort uintptr_t m = (uintptr_t)msg_no; 124*d44a5ed1SThomas Cort 125*d44a5ed1SThomas Cort if (m > sizeof msg_list / sizeof msg_list[0]) 126*d44a5ed1SThomas Cort /* guess that we were passed a text string */ 127*d44a5ed1SThomas Cort return msg_no; 128*d44a5ed1SThomas Cort 129*d44a5ed1SThomas Cort if (msgmap != MAP_FAILED && m != 0 && m <= msgmapcount) { 130*d44a5ed1SThomas Cort unsigned int offset = atoi(msgmap + 8 + 8 * m); 131*d44a5ed1SThomas Cort if (offset != 0 && offset < msgmapsz) 132*d44a5ed1SThomas Cort return msgmap + offset; 133*d44a5ed1SThomas Cort } 134*d44a5ed1SThomas Cort 135*d44a5ed1SThomas Cort return msg_list[m]; 136*d44a5ed1SThomas Cort} 137*d44a5ed1SThomas Cort 138*d44a5ed1SThomas Cortvoid 139*d44a5ed1SThomas Cortmsg_clear(void) 140*d44a5ed1SThomas Cort{ 141*d44a5ed1SThomas Cort 142*d44a5ed1SThomas Cort wclear(msg_win); 143*d44a5ed1SThomas Cort last_o_was_punct = 0; 144*d44a5ed1SThomas Cort last_o_was_space = 1; 145*d44a5ed1SThomas Cort} 146*d44a5ed1SThomas Cort 147*d44a5ed1SThomas Cortvoid 148*d44a5ed1SThomas Cortmsg_standout(void) 149*d44a5ed1SThomas Cort{ 150*d44a5ed1SThomas Cort 151*d44a5ed1SThomas Cort wstandout(msg_win); 152*d44a5ed1SThomas Cort} 153*d44a5ed1SThomas Cort 154*d44a5ed1SThomas Cortvoid 155*d44a5ed1SThomas Cortmsg_standend(void) 156*d44a5ed1SThomas Cort{ 157*d44a5ed1SThomas Cort 158*d44a5ed1SThomas Cort wstandend(msg_win); 159*d44a5ed1SThomas Cort} 160*d44a5ed1SThomas Cort 161*d44a5ed1SThomas Cortstatic int 162*d44a5ed1SThomas Cort_msg_vprintf(int auto_fill, const char *fmt, va_list ap) 163*d44a5ed1SThomas Cort{ 164*d44a5ed1SThomas Cort const char *wstart, *afterw; 165*d44a5ed1SThomas Cort int wordlen, nspaces; 166*d44a5ed1SThomas Cort int ret; 167*d44a5ed1SThomas Cort 168*d44a5ed1SThomas Cort ret = vsnprintf(cbuffer, cbuffersize, fmt, ap); 169*d44a5ed1SThomas Cort 170*d44a5ed1SThomas Cort if (!auto_fill) { 171*d44a5ed1SThomas Cort waddstr(msg_win, cbuffer); 172*d44a5ed1SThomas Cort 173*d44a5ed1SThomas Cort /* 174*d44a5ed1SThomas Cort * nothing is perfect if they flow text after a table, 175*d44a5ed1SThomas Cort * but this may be decent. 176*d44a5ed1SThomas Cort */ 177*d44a5ed1SThomas Cort last_i_was_nl = last_i_was_space = 1; 178*d44a5ed1SThomas Cort last_o_was_punct = 0; 179*d44a5ed1SThomas Cort last_o_was_space = 1; 180*d44a5ed1SThomas Cort goto out; 181*d44a5ed1SThomas Cort } 182*d44a5ed1SThomas Cort 183*d44a5ed1SThomas Cort for (wstart = afterw = cbuffer; *wstart; wstart = afterw) { 184*d44a5ed1SThomas Cort 185*d44a5ed1SThomas Cort /* eat one space, or a whole word of non-spaces */ 186*d44a5ed1SThomas Cort if (isspace((unsigned char)*afterw)) 187*d44a5ed1SThomas Cort afterw++; 188*d44a5ed1SThomas Cort else 189*d44a5ed1SThomas Cort while (*afterw && !isspace((unsigned char)*afterw)) 190*d44a5ed1SThomas Cort afterw++; 191*d44a5ed1SThomas Cort 192*d44a5ed1SThomas Cort /* this is an nl: special formatting necessary */ 193*d44a5ed1SThomas Cort if (*wstart == '\n') { 194*d44a5ed1SThomas Cort if (last_i_was_nl || last_i_was_space) { 195*d44a5ed1SThomas Cort 196*d44a5ed1SThomas Cort if (getcurx(msg_win) != 0) 197*d44a5ed1SThomas Cort waddch(msg_win, '\n'); 198*d44a5ed1SThomas Cort if (last_i_was_nl) { 199*d44a5ed1SThomas Cort /* last was an nl: paragraph break */ 200*d44a5ed1SThomas Cort waddch(msg_win, '\n'); 201*d44a5ed1SThomas Cort } else { 202*d44a5ed1SThomas Cort /* last was space: line break */ 203*d44a5ed1SThomas Cort } 204*d44a5ed1SThomas Cort last_o_was_punct = 0; 205*d44a5ed1SThomas Cort last_o_was_space = 1; 206*d44a5ed1SThomas Cort } else { 207*d44a5ed1SThomas Cort /* last_o_was_punct unchanged */ 208*d44a5ed1SThomas Cort /* last_o_was_space unchanged */ 209*d44a5ed1SThomas Cort } 210*d44a5ed1SThomas Cort last_i_was_space = 1; 211*d44a5ed1SThomas Cort last_i_was_nl = 1; 212*d44a5ed1SThomas Cort continue; 213*d44a5ed1SThomas Cort } 214*d44a5ed1SThomas Cort 215*d44a5ed1SThomas Cort /* this is a tab: special formatting necessary. */ 216*d44a5ed1SThomas Cort if (*wstart == '\t') { 217*d44a5ed1SThomas Cort if (last_i_was_nl) { 218*d44a5ed1SThomas Cort /* last was an nl: list indent */ 219*d44a5ed1SThomas Cort if (getcurx(msg_win) != 0) 220*d44a5ed1SThomas Cort waddch(msg_win, '\n'); 221*d44a5ed1SThomas Cort } else { 222*d44a5ed1SThomas Cort /* last was not an nl: columns */ 223*d44a5ed1SThomas Cort } 224*d44a5ed1SThomas Cort waddch(msg_win, '\t'); 225*d44a5ed1SThomas Cort last_i_was_nl = 0; 226*d44a5ed1SThomas Cort last_i_was_space = 1; 227*d44a5ed1SThomas Cort last_o_was_punct = 0; 228*d44a5ed1SThomas Cort last_o_was_space = 1; 229*d44a5ed1SThomas Cort continue; 230*d44a5ed1SThomas Cort } 231*d44a5ed1SThomas Cort 232*d44a5ed1SThomas Cort /* this is a space: ignore it but set flags */ 233*d44a5ed1SThomas Cort last_i_was_nl = 0; /* all newlines handled above */ 234*d44a5ed1SThomas Cort last_i_was_space = isspace((unsigned char)*wstart); 235*d44a5ed1SThomas Cort if (last_i_was_space) 236*d44a5ed1SThomas Cort continue; 237*d44a5ed1SThomas Cort 238*d44a5ed1SThomas Cort /* 239*d44a5ed1SThomas Cort * we have a real "word," i.e. a sequence of non-space 240*d44a5ed1SThomas Cort * characters. wstart is now the start of the word, 241*d44a5ed1SThomas Cort * afterw is the next character after the end. 242*d44a5ed1SThomas Cort */ 243*d44a5ed1SThomas Cort wordlen = afterw - wstart; 244*d44a5ed1SThomas Cort nspaces = last_o_was_space ? 0 : (last_o_was_punct ? 2 : 1); 245*d44a5ed1SThomas Cort if ((getcurx(msg_win) + nspaces + wordlen) >= 246*d44a5ed1SThomas Cort getmaxx(msg_win) && 247*d44a5ed1SThomas Cort wordlen < (getmaxx(msg_win) / 3)) { 248*d44a5ed1SThomas Cort /* wrap the line */ 249*d44a5ed1SThomas Cort waddch(msg_win, '\n'); 250*d44a5ed1SThomas Cort nspaces = 0; 251*d44a5ed1SThomas Cort } 252*d44a5ed1SThomas Cort 253*d44a5ed1SThomas Cort /* output the word, preceded by spaces if necessary */ 254*d44a5ed1SThomas Cort while (nspaces-- > 0) 255*d44a5ed1SThomas Cort waddch(msg_win, ' '); 256*d44a5ed1SThomas Cort waddbytes(msg_win, wstart, wordlen); 257*d44a5ed1SThomas Cort 258*d44a5ed1SThomas Cort /* set up the 'last' state for the next time around */ 259*d44a5ed1SThomas Cort switch (afterw[-1]) { 260*d44a5ed1SThomas Cort case '.': 261*d44a5ed1SThomas Cort case '?': 262*d44a5ed1SThomas Cort case '!': 263*d44a5ed1SThomas Cort last_o_was_punct = 1; 264*d44a5ed1SThomas Cort break; 265*d44a5ed1SThomas Cort default: 266*d44a5ed1SThomas Cort last_o_was_punct = 0; 267*d44a5ed1SThomas Cort break; 268*d44a5ed1SThomas Cort } 269*d44a5ed1SThomas Cort last_o_was_space = 0; 270*d44a5ed1SThomas Cort 271*d44a5ed1SThomas Cort /* ... and do it all again! */ 272*d44a5ed1SThomas Cort } 273*d44a5ed1SThomas Cort 274*d44a5ed1SThomas Cort /* String ended with a newline. They really want a line break. */ 275*d44a5ed1SThomas Cort if (last_i_was_nl) { 276*d44a5ed1SThomas Cort if (getcurx(msg_win) != 0) 277*d44a5ed1SThomas Cort waddch(msg_win, '\n'); 278*d44a5ed1SThomas Cort last_o_was_punct = 0; 279*d44a5ed1SThomas Cort last_o_was_space = 1; 280*d44a5ed1SThomas Cort } 281*d44a5ed1SThomas Cort 282*d44a5ed1SThomas Cortout: 283*d44a5ed1SThomas Cort wrefresh(msg_win); 284*d44a5ed1SThomas Cort return ret; 285*d44a5ed1SThomas Cort} 286*d44a5ed1SThomas Cort 287*d44a5ed1SThomas Cortvoid 288*d44a5ed1SThomas Cortmsg_display(msg msg_no, ...) 289*d44a5ed1SThomas Cort{ 290*d44a5ed1SThomas Cort va_list ap; 291*d44a5ed1SThomas Cort 292*d44a5ed1SThomas Cort msg_clear(); 293*d44a5ed1SThomas Cort 294*d44a5ed1SThomas Cort va_start(ap, msg_no); 295*d44a5ed1SThomas Cort (void)_msg_vprintf(1, msg_string(msg_no), ap); 296*d44a5ed1SThomas Cort va_end(ap); 297*d44a5ed1SThomas Cort} 298*d44a5ed1SThomas Cort 299*d44a5ed1SThomas Cortvoid 300*d44a5ed1SThomas Cortmsg_display_add(msg msg_no, ...) 301*d44a5ed1SThomas Cort{ 302*d44a5ed1SThomas Cort va_list ap; 303*d44a5ed1SThomas Cort 304*d44a5ed1SThomas Cort va_start(ap, msg_no); 305*d44a5ed1SThomas Cort (void)_msg_vprintf(1, msg_string(msg_no), ap); 306*d44a5ed1SThomas Cort va_end(ap); 307*d44a5ed1SThomas Cort} 308*d44a5ed1SThomas Cort 309*d44a5ed1SThomas Cortvoid 310*d44a5ed1SThomas Cortmsg_printf(const char *fmt, ...) 311*d44a5ed1SThomas Cort{ 312*d44a5ed1SThomas Cort va_list ap; 313*d44a5ed1SThomas Cort 314*d44a5ed1SThomas Cort va_start(ap, fmt); 315*d44a5ed1SThomas Cort (void)_msg_vprintf(1, fmt, ap); 316*d44a5ed1SThomas Cort va_end(ap); 317*d44a5ed1SThomas Cort} 318*d44a5ed1SThomas Cort 319*d44a5ed1SThomas Cortstatic void 320*d44a5ed1SThomas Cort_msg_vprompt(const char *fmt, int flags, const char *def, char *val, 321*d44a5ed1SThomas Cort size_t val_buf_len, va_list ap) 322*d44a5ed1SThomas Cort{ 323*d44a5ed1SThomas Cort int ch; 324*d44a5ed1SThomas Cort int len, pos, npos, off; 325*d44a5ed1SThomas Cort int first; 326*d44a5ed1SThomas Cort int txt_y, txt_x; 327*d44a5ed1SThomas Cort char *ibuf; 328*d44a5ed1SThomas Cort int maxx; 329*d44a5ed1SThomas Cort 330*d44a5ed1SThomas Cort if (val == NULL || val_buf_len == 0) { 331*d44a5ed1SThomas Cort /* No answer wanted */ 332*d44a5ed1SThomas Cort val = NULL; 333*d44a5ed1SThomas Cort val_buf_len = 1; 334*d44a5ed1SThomas Cort } 335*d44a5ed1SThomas Cort 336*d44a5ed1SThomas Cort ibuf = malloc(val_buf_len); 337*d44a5ed1SThomas Cort 338*d44a5ed1SThomas Cort keypad(msg_win, TRUE); 339*d44a5ed1SThomas Cort _msg_vprintf(0, fmt, ap); 340*d44a5ed1SThomas Cort ibuf[0] = 0; 341*d44a5ed1SThomas Cort if (def != NULL && *def) { 342*d44a5ed1SThomas Cort if (flags & MSG_PROMPT_HIDE_DFLT) 343*d44a5ed1SThomas Cort strlcpy(ibuf, def, val_buf_len); 344*d44a5ed1SThomas Cort else { 345*d44a5ed1SThomas Cort waddstr(msg_win, " ["); 346*d44a5ed1SThomas Cort waddstr(msg_win, def); 347*d44a5ed1SThomas Cort waddstr(msg_win, "]"); 348*d44a5ed1SThomas Cort } 349*d44a5ed1SThomas Cort } 350*d44a5ed1SThomas Cort waddstr(msg_win, ": "); 351*d44a5ed1SThomas Cort len = strlen(ibuf); 352*d44a5ed1SThomas Cort pos = len; 353*d44a5ed1SThomas Cort getyx(msg_win, txt_y, txt_x); 354*d44a5ed1SThomas Cort maxx = getmaxx(msg_win) - txt_x - 1; 355*d44a5ed1SThomas Cort off = 0; 356*d44a5ed1SThomas Cort 357*d44a5ed1SThomas Cort for (first = 1; ; first = 0) { 358*d44a5ed1SThomas Cort 359*d44a5ed1SThomas Cort if (flags & MSG_PROMPT_ECHO) { 360*d44a5ed1SThomas Cort /* shift text right as we near the buffer start */ 361*d44a5ed1SThomas Cort if (pos - off < 4) 362*d44a5ed1SThomas Cort off = pos - 4; 363*d44a5ed1SThomas Cort /* keep offset to a minimum if we are at the end */ 364*d44a5ed1SThomas Cort if (pos == len) 365*d44a5ed1SThomas Cort off = pos - maxx; 366*d44a5ed1SThomas Cort if (off < 0 || len <= maxx) 367*d44a5ed1SThomas Cort off = 0; 368*d44a5ed1SThomas Cort /* shift text left as we near the buffer end */ 369*d44a5ed1SThomas Cort npos = pos + 4; 370*d44a5ed1SThomas Cort if (npos > len) 371*d44a5ed1SThomas Cort npos = len; 372*d44a5ed1SThomas Cort if (npos - off > maxx) 373*d44a5ed1SThomas Cort off = npos - maxx; 374*d44a5ed1SThomas Cort /* calc. length to display */ 375*d44a5ed1SThomas Cort npos = len - off; 376*d44a5ed1SThomas Cort if (npos > maxx) 377*d44a5ed1SThomas Cort npos = maxx; 378*d44a5ed1SThomas Cort mvwaddnstr(msg_win, txt_y, txt_x, ibuf + off, npos); 379*d44a5ed1SThomas Cort wclrtoeol(msg_win); 380*d44a5ed1SThomas Cort if (off != 0) 381*d44a5ed1SThomas Cort mvwaddstr(msg_win, txt_y, txt_x, "+"); 382*d44a5ed1SThomas Cort wmove(msg_win, txt_y, txt_x + pos - off); 383*d44a5ed1SThomas Cort wrefresh(msg_win); 384*d44a5ed1SThomas Cort } 385*d44a5ed1SThomas Cort 386*d44a5ed1SThomas Cort ch = wgetch(msg_win); 387*d44a5ed1SThomas Cort if (ch == '\n') 388*d44a5ed1SThomas Cort break; 389*d44a5ed1SThomas Cort 390*d44a5ed1SThomas Cort switch (ch) { 391*d44a5ed1SThomas Cort case KEY_BACKSPACE: 392*d44a5ed1SThomas Cort case 'h' & 0x1f: case 0x7f: /* bs or del - delete left */ 393*d44a5ed1SThomas Cort if (first) { 394*d44a5ed1SThomas Cort /* delete all of default string */ 395*d44a5ed1SThomas Cort len = pos = 0; 396*d44a5ed1SThomas Cort break; 397*d44a5ed1SThomas Cort } 398*d44a5ed1SThomas Cort if (pos > 0) { 399*d44a5ed1SThomas Cort memmove(ibuf + pos - 1, ibuf + pos, len - pos); 400*d44a5ed1SThomas Cort len--; 401*d44a5ed1SThomas Cort pos--; 402*d44a5ed1SThomas Cort } else 403*d44a5ed1SThomas Cort _msg_beep(); 404*d44a5ed1SThomas Cort break; 405*d44a5ed1SThomas Cort case 'u' & 0x1f: /* ^U; line kill */ 406*d44a5ed1SThomas Cort /* kill line */ 407*d44a5ed1SThomas Cort len = pos = 0; 408*d44a5ed1SThomas Cort break; 409*d44a5ed1SThomas Cort case 'w' & 0x1f: /* ^W; word kill */ 410*d44a5ed1SThomas Cort /* 411*d44a5ed1SThomas Cort * word kill kills the spaces and the 'word' 412*d44a5ed1SThomas Cort * (non-spaces) last typed. the spaces before 413*d44a5ed1SThomas Cort * the 'word' aren't killed. 414*d44a5ed1SThomas Cort */ 415*d44a5ed1SThomas Cort npos = pos; 416*d44a5ed1SThomas Cort while (npos > 0 && isspace((unsigned char)ibuf[npos - 1])) 417*d44a5ed1SThomas Cort npos--; 418*d44a5ed1SThomas Cort while (npos > 0 && !isspace((unsigned char)ibuf[npos - 1])) 419*d44a5ed1SThomas Cort npos--; 420*d44a5ed1SThomas Cort memmove(ibuf + npos, ibuf + pos, len - pos); 421*d44a5ed1SThomas Cort len -= pos - npos; 422*d44a5ed1SThomas Cort pos = npos; 423*d44a5ed1SThomas Cort break; 424*d44a5ed1SThomas Cort case KEY_LEFT: 425*d44a5ed1SThomas Cort if (pos > 0) 426*d44a5ed1SThomas Cort pos--; 427*d44a5ed1SThomas Cort break; 428*d44a5ed1SThomas Cort case KEY_RIGHT: 429*d44a5ed1SThomas Cort if (len == 0 && pos == 0 && def != NULL) { 430*d44a5ed1SThomas Cort /* restore default! */ 431*d44a5ed1SThomas Cort strlcpy(ibuf, def, val_buf_len); 432*d44a5ed1SThomas Cort len = pos = strlen(ibuf); 433*d44a5ed1SThomas Cort break; 434*d44a5ed1SThomas Cort } 435*d44a5ed1SThomas Cort if (pos < len) 436*d44a5ed1SThomas Cort pos++; 437*d44a5ed1SThomas Cort break; 438*d44a5ed1SThomas Cort default: 439*d44a5ed1SThomas Cort if (len < (int)(val_buf_len - 1) && isprint(ch)) { 440*d44a5ed1SThomas Cort memmove(ibuf + pos + 1, ibuf + pos, len - pos); 441*d44a5ed1SThomas Cort ibuf[pos++] = ch; 442*d44a5ed1SThomas Cort len++; 443*d44a5ed1SThomas Cort } else 444*d44a5ed1SThomas Cort _msg_beep(); 445*d44a5ed1SThomas Cort break; 446*d44a5ed1SThomas Cort } 447*d44a5ed1SThomas Cort } 448*d44a5ed1SThomas Cort 449*d44a5ed1SThomas Cort if (flags & MSG_PROMPT_ECHO) { 450*d44a5ed1SThomas Cort mvwaddch(msg_win, txt_y, txt_x + len - off, '\n'); 451*d44a5ed1SThomas Cort last_o_was_punct = 0; 452*d44a5ed1SThomas Cort last_o_was_space = 1; 453*d44a5ed1SThomas Cort } 454*d44a5ed1SThomas Cort 455*d44a5ed1SThomas Cort if (val != NULL) { 456*d44a5ed1SThomas Cort /* copy the appropriate string to the output */ 457*d44a5ed1SThomas Cort if (len != 0 || flags & MSG_PROMPT_HIDE_DFLT) { 458*d44a5ed1SThomas Cort ibuf[len] = '\0'; 459*d44a5ed1SThomas Cort strlcpy(val, ibuf, val_buf_len); 460*d44a5ed1SThomas Cort } else if (def != NULL && val != def) { 461*d44a5ed1SThomas Cort strlcpy(val, def, val_buf_len); 462*d44a5ed1SThomas Cort } 463*d44a5ed1SThomas Cort } 464*d44a5ed1SThomas Cort free(ibuf); 465*d44a5ed1SThomas Cort} 466*d44a5ed1SThomas Cort 467*d44a5ed1SThomas Cortvoid 468*d44a5ed1SThomas Cortmsg_prompt(msg msg_no, const char *def, char *val, size_t val_buf_len, ...) 469*d44a5ed1SThomas Cort{ 470*d44a5ed1SThomas Cort va_list ap; 471*d44a5ed1SThomas Cort 472*d44a5ed1SThomas Cort msg_clear(); 473*d44a5ed1SThomas Cort 474*d44a5ed1SThomas Cort va_start(ap, val_buf_len); 475*d44a5ed1SThomas Cort _msg_vprompt(msg_string(msg_no), MSG_PROMPT_ECHO, 476*d44a5ed1SThomas Cort def, val, val_buf_len, ap); 477*d44a5ed1SThomas Cort va_end(ap); 478*d44a5ed1SThomas Cort} 479*d44a5ed1SThomas Cort 480*d44a5ed1SThomas Cortvoid 481*d44a5ed1SThomas Cortmsg_prompt_win(msg msg_no, int x, int y, int w, int h, 482*d44a5ed1SThomas Cort const char *def, char *val, size_t val_buf_len, ...) 483*d44a5ed1SThomas Cort{ 484*d44a5ed1SThomas Cort va_list ap; 485*d44a5ed1SThomas Cort WINDOW *win; 486*d44a5ed1SThomas Cort WINDOW *svmsg = NULL, *sv_win = NULL; /* XXX -Wuninitialized [many] */ 487*d44a5ed1SThomas Cort int maxx, maxy; 488*d44a5ed1SThomas Cort int msg_flags = MSG_PROMPT_ECHO | MSG_PROMPT_HIDE_DFLT; 489*d44a5ed1SThomas Cort 490*d44a5ed1SThomas Cort maxx = getmaxx(msg_win); 491*d44a5ed1SThomas Cort maxy = getmaxy(msg_win); 492*d44a5ed1SThomas Cort if (w == 0) { 493*d44a5ed1SThomas Cort va_start(ap, val_buf_len); 494*d44a5ed1SThomas Cort w = vsnprintf(NULL, 0, msg_string(msg_no), ap); 495*d44a5ed1SThomas Cort va_end(ap); 496*d44a5ed1SThomas Cort if (def != NULL && *def != 0 && w + (int)val_buf_len * 2 < maxx) { 497*d44a5ed1SThomas Cort w += 2 + strlen(def) + 1; 498*d44a5ed1SThomas Cort msg_flags &= ~MSG_PROMPT_HIDE_DFLT; 499*d44a5ed1SThomas Cort } 500*d44a5ed1SThomas Cort w += 1 + 2 + val_buf_len + 1; 501*d44a5ed1SThomas Cort if (w > maxx) { 502*d44a5ed1SThomas Cort if (!(msg_flags & MSG_PROMPT_HIDE_DFLT)) { 503*d44a5ed1SThomas Cort w -= 2 + strlen(def) + 1; 504*d44a5ed1SThomas Cort msg_flags |= MSG_PROMPT_HIDE_DFLT; 505*d44a5ed1SThomas Cort } 506*d44a5ed1SThomas Cort w = maxx; 507*d44a5ed1SThomas Cort } 508*d44a5ed1SThomas Cort } 509*d44a5ed1SThomas Cort 510*d44a5ed1SThomas Cort if (x == -1) 511*d44a5ed1SThomas Cort x = (maxx - w) / 2 + 1; 512*d44a5ed1SThomas Cort if (h < 3) 513*d44a5ed1SThomas Cort h = 3; 514*d44a5ed1SThomas Cort if (y < 3) 515*d44a5ed1SThomas Cort y = (maxy - h) / 2; 516*d44a5ed1SThomas Cort if (y + h > maxy) 517*d44a5ed1SThomas Cort y = maxy - h; 518*d44a5ed1SThomas Cort 519*d44a5ed1SThomas Cort win = subwin(msg_win, h, w, y, x); 520*d44a5ed1SThomas Cort if (win == NULL) 521*d44a5ed1SThomas Cort wprintw(msg_win, "msg_prompt_win: " 522*d44a5ed1SThomas Cort "newwin(%d, %d, %d, %d) failed\n", 523*d44a5ed1SThomas Cort h, w, y, x); 524*d44a5ed1SThomas Cort else { 525*d44a5ed1SThomas Cort /* 526*d44a5ed1SThomas Cort * Save screen contents from under our window 527*d44a5ed1SThomas Cort * Due to a mis-feature of NetBSD curses, curscr contains 528*d44a5ed1SThomas Cort * the data processed by doupdate() not that by wnoutrefresh(). 529*d44a5ed1SThomas Cort * We must call doupdate() here to ensure we save the correct 530*d44a5ed1SThomas Cort * data. See PR 26660 531*d44a5ed1SThomas Cort */ 532*d44a5ed1SThomas Cort doupdate(); 533*d44a5ed1SThomas Cort sv_win = dupwin(win); 534*d44a5ed1SThomas Cort if (sv_win) 535*d44a5ed1SThomas Cort overwrite(curscr, sv_win); 536*d44a5ed1SThomas Cort wbkgd(win, getbkgd(msg_win)); 537*d44a5ed1SThomas Cort wattrset(win, getattrs(msg_win)); 538*d44a5ed1SThomas Cort box(win, 0, 0); 539*d44a5ed1SThomas Cort wrefresh(win); 540*d44a5ed1SThomas Cort 541*d44a5ed1SThomas Cort /* Change message window to be our little box */ 542*d44a5ed1SThomas Cort svmsg = msg_window(subwin(msg_win, h - 2, w - 2, y + 1, x + 1)); 543*d44a5ed1SThomas Cort wbkgd(msg_win, getbkgd(win)); 544*d44a5ed1SThomas Cort wattrset(msg_win, getattrs(win)); 545*d44a5ed1SThomas Cort 546*d44a5ed1SThomas Cort msg_clear(); 547*d44a5ed1SThomas Cort } 548*d44a5ed1SThomas Cort 549*d44a5ed1SThomas Cort va_start(ap, val_buf_len); 550*d44a5ed1SThomas Cort _msg_vprompt(msg_string(msg_no), msg_flags, def, val, val_buf_len, ap); 551*d44a5ed1SThomas Cort va_end(ap); 552*d44a5ed1SThomas Cort 553*d44a5ed1SThomas Cort if (win != NULL) { 554*d44a5ed1SThomas Cort wclear(win); 555*d44a5ed1SThomas Cort if (sv_win) { 556*d44a5ed1SThomas Cort /* Restore original screen contents */ 557*d44a5ed1SThomas Cort overwrite(sv_win, win); 558*d44a5ed1SThomas Cort delwin(sv_win); 559*d44a5ed1SThomas Cort } 560*d44a5ed1SThomas Cort wnoutrefresh(win); 561*d44a5ed1SThomas Cort /* Restore normal message window */ 562*d44a5ed1SThomas Cort delwin(msg_window(svmsg)); 563*d44a5ed1SThomas Cort delwin(win); 564*d44a5ed1SThomas Cort } 565*d44a5ed1SThomas Cort} 566*d44a5ed1SThomas Cort 567*d44a5ed1SThomas Cortvoid 568*d44a5ed1SThomas Cortmsg_prompt_add(msg msg_no, const char *def, char *val, size_t val_buf_len, ...) 569*d44a5ed1SThomas Cort{ 570*d44a5ed1SThomas Cort va_list ap; 571*d44a5ed1SThomas Cort 572*d44a5ed1SThomas Cort va_start(ap, val_buf_len); 573*d44a5ed1SThomas Cort _msg_vprompt(msg_string(msg_no), MSG_PROMPT_ECHO, def, val, val_buf_len, ap); 574*d44a5ed1SThomas Cort va_end(ap); 575*d44a5ed1SThomas Cort} 576*d44a5ed1SThomas Cort 577*d44a5ed1SThomas Cortvoid 578*d44a5ed1SThomas Cortmsg_prompt_noecho(msg msg_no, const char *def, char *val, size_t val_buf_len, ...) 579*d44a5ed1SThomas Cort{ 580*d44a5ed1SThomas Cort va_list ap; 581*d44a5ed1SThomas Cort 582*d44a5ed1SThomas Cort msg_clear(); 583*d44a5ed1SThomas Cort 584*d44a5ed1SThomas Cort va_start(ap, val_buf_len); 585*d44a5ed1SThomas Cort _msg_vprompt(msg_string(msg_no), 0, def, val, val_buf_len, ap); 586*d44a5ed1SThomas Cort va_end(ap); 587*d44a5ed1SThomas Cort} 588*d44a5ed1SThomas Cort 589*d44a5ed1SThomas Cortvoid 590*d44a5ed1SThomas Cortmsg_table_add(msg msg_no, ...) 591*d44a5ed1SThomas Cort{ 592*d44a5ed1SThomas Cort va_list ap; 593*d44a5ed1SThomas Cort 594*d44a5ed1SThomas Cort va_start(ap, msg_no); 595*d44a5ed1SThomas Cort (void)_msg_vprintf(0, msg_string(msg_no), ap); 596*d44a5ed1SThomas Cort va_end(ap); 597*d44a5ed1SThomas Cort} 598*d44a5ed1SThomas Cort 599*d44a5ed1SThomas Cortint 600*d44a5ed1SThomas Cortmsg_row(void) 601*d44a5ed1SThomas Cort{ 602*d44a5ed1SThomas Cort 603*d44a5ed1SThomas Cort return getcury(msg_win) + getbegy(msg_win); 604*d44a5ed1SThomas Cort} 605