1 /* $NetBSD: message.c,v 1.14 2009/08/12 08:44:45 dholland Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Timothy C. Stoehr. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)message.c 8.1 (Berkeley) 5/31/93"; 39 #else 40 __RCSID("$NetBSD: message.c,v 1.14 2009/08/12 08:44:45 dholland Exp $"); 41 #endif 42 #endif /* not lint */ 43 44 /* 45 * message.c 46 * 47 * This source herein may be modified and/or distributed by anybody who 48 * so desires, with the following restrictions: 49 * 1.) No portion of this notice shall be removed. 50 * 2.) Credit shall not be taken for the creation of this source. 51 * 3.) This code is not to be traded, sold, or used for personal 52 * gain or profit. 53 * 54 */ 55 56 #include <signal.h> 57 #include <termios.h> 58 #include <stdarg.h> 59 #include "rogue.h" 60 #include "pathnames.h" 61 62 static char msgs[NMESSAGES][DCOLS] = {"", "", "", "", ""}; 63 static short msg_col = 0, imsg = -1; 64 static boolean rmsg = 0; 65 66 boolean msg_cleared = 1; 67 char hunger_str[HUNGER_STR_LEN] = ""; 68 const char *more = "-more-"; 69 70 static void save_screen(void); 71 72 static 73 void 74 message(const char *msg, boolean intrpt) 75 { 76 cant_int = 1; 77 78 if (!save_is_interactive) { 79 return; 80 } 81 if (intrpt) { 82 interrupted = 1; 83 md_slurp(); 84 } 85 86 if (!msg_cleared) { 87 mvaddstr(MIN_ROW-1, msg_col, more); 88 refresh(); 89 wait_for_ack(); 90 check_message(); 91 } 92 if (!rmsg) { 93 imsg = (imsg + 1) % NMESSAGES; 94 (void)strlcpy(msgs[imsg], msg, sizeof(msgs[imsg])); 95 } 96 mvaddstr(MIN_ROW-1, 0, msg); 97 addch(' '); 98 refresh(); 99 msg_cleared = 0; 100 msg_col = strlen(msg); 101 102 cant_int = 0; 103 104 if (did_int) { 105 did_int = 0; 106 onintr(0); 107 } 108 } 109 110 void 111 messagef(boolean intrpt, const char *fmt, ...) 112 { 113 va_list ap; 114 char buf[DCOLS]; 115 116 va_start(ap, fmt); 117 vsnprintf(buf, sizeof(buf), fmt, ap); 118 va_end(ap); 119 120 message(buf, intrpt); 121 } 122 123 void 124 remessage(short c) 125 { 126 if (imsg != -1) { 127 check_message(); 128 rmsg = 1; 129 while (c > imsg) { 130 c -= NMESSAGES; 131 } 132 message(msgs[((imsg - c) % NMESSAGES)], 0); 133 rmsg = 0; 134 move(rogue.row, rogue.col); 135 refresh(); 136 } 137 } 138 139 void 140 check_message(void) 141 { 142 if (msg_cleared) { 143 return; 144 } 145 move(MIN_ROW-1, 0); 146 clrtoeol(); 147 refresh(); 148 msg_cleared = 1; 149 } 150 151 int 152 get_input_line(const char *prompt, const char *insert, 153 char *buf, size_t buflen, 154 const char *if_cancelled, 155 boolean add_blank, boolean do_echo) 156 { 157 short ch; 158 size_t i = 0, n; 159 160 message(prompt, 0); 161 n = strlen(prompt); 162 163 if (insert[0]) { 164 mvaddstr(0, n + 1, insert); 165 (void)strlcpy(buf, insert, buflen); 166 i = strlen(buf); 167 move(0, (n + i + 1)); 168 refresh(); 169 } 170 171 while (((ch = rgetchar()) != '\r') && (ch != '\n') && (ch != CANCEL)) { 172 if ((ch >= ' ') && (ch <= '~') && (i < buflen-2)) { 173 if ((ch != ' ') || (i > 0)) { 174 buf[i++] = ch; 175 if (do_echo) { 176 addch(ch); 177 } 178 } 179 } 180 if ((ch == '\b') && (i > 0)) { 181 if (do_echo) { 182 mvaddch(0, i + n, ' '); 183 move(MIN_ROW-1, i+n); 184 } 185 i--; 186 } 187 refresh(); 188 } 189 check_message(); 190 if (add_blank) { 191 buf[i++] = ' '; 192 } else { 193 while ((i > 0) && (buf[i-1] == ' ')) { 194 i--; 195 } 196 } 197 198 buf[i] = 0; 199 200 if ((ch == CANCEL) || (i == 0) || ((i == 1) && add_blank)) { 201 if (if_cancelled) { 202 message(if_cancelled, 0); 203 } 204 return(0); 205 } 206 return(i); 207 } 208 209 int 210 rgetchar(void) 211 { 212 int ch; 213 214 for(;;) { 215 ch = getchar(); 216 217 switch(ch) { 218 case '\022': /* ^R */ 219 wrefresh(curscr); 220 break; 221 #ifdef UNIX_BSD4_2 222 case '\032': /* ^Z */ 223 printf("%s", CL); 224 fflush(stdout); 225 tstp(); 226 break; 227 #endif 228 case '&': 229 save_screen(); 230 break; 231 default: 232 return(ch); 233 } 234 } 235 } 236 237 /* 238 Level: 99 Gold: 999999 Hp: 999(999) Str: 99(99) Arm: 99 Exp: 21/10000000 Hungry 239 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 240 */ 241 242 void 243 print_stats(int stat_mask) 244 { 245 char buf[16]; 246 boolean label; 247 int row = DROWS - 1; 248 249 label = (stat_mask & STAT_LABEL) ? 1 : 0; 250 251 if (stat_mask & STAT_LEVEL) { 252 if (label) { 253 mvaddstr(row, 0, "Level: "); 254 } 255 /* max level taken care of in make_level() */ 256 mvprintw(row, 7, "%-2d", cur_level); 257 } 258 if (stat_mask & STAT_GOLD) { 259 if (label) { 260 mvaddstr(row, 10, "Gold: "); 261 } 262 if (rogue.gold > MAX_GOLD) { 263 rogue.gold = MAX_GOLD; 264 } 265 mvprintw(row, 16, "%-6ld", rogue.gold); 266 } 267 if (stat_mask & STAT_HP) { 268 if (label) { 269 mvaddstr(row, 23, "Hp: "); 270 } 271 if (rogue.hp_max > MAX_HP) { 272 rogue.hp_current -= (rogue.hp_max - MAX_HP); 273 rogue.hp_max = MAX_HP; 274 } 275 snprintf(buf, sizeof(buf), "%d(%d)", 276 rogue.hp_current, rogue.hp_max); 277 mvprintw(row, 27, "%-8s", buf); 278 } 279 if (stat_mask & STAT_STRENGTH) { 280 if (label) { 281 mvaddstr(row, 36, "Str: "); 282 } 283 if (rogue.str_max > MAX_STRENGTH) { 284 rogue.str_current -= (rogue.str_max - MAX_STRENGTH); 285 rogue.str_max = MAX_STRENGTH; 286 } 287 snprintf(buf, sizeof(buf), "%d(%d)", 288 (rogue.str_current + add_strength), rogue.str_max); 289 mvprintw(row, 41, "%-6s", buf); 290 } 291 if (stat_mask & STAT_ARMOR) { 292 if (label) { 293 mvaddstr(row, 48, "Arm: "); 294 } 295 if (rogue.armor && (rogue.armor->d_enchant > MAX_ARMOR)) { 296 rogue.armor->d_enchant = MAX_ARMOR; 297 } 298 mvprintw(row, 53, "%-2d", get_armor_class(rogue.armor)); 299 } 300 if (stat_mask & STAT_EXP) { 301 if (label) { 302 mvaddstr(row, 56, "Exp: "); 303 } 304 if (rogue.exp_points > MAX_EXP) { 305 rogue.exp_points = MAX_EXP; 306 } 307 if (rogue.exp > MAX_EXP_LEVEL) { 308 rogue.exp = MAX_EXP_LEVEL; 309 } 310 snprintf(buf, sizeof(buf), "%d/%ld", 311 rogue.exp, rogue.exp_points); 312 mvprintw(row, 61, "%-11s", buf); 313 } 314 if (stat_mask & STAT_HUNGER) { 315 mvaddstr(row, 73, hunger_str); 316 clrtoeol(); 317 } 318 refresh(); 319 } 320 321 static void 322 save_screen(void) 323 { 324 FILE *fp; 325 short i, j; 326 char buf[DCOLS+2]; 327 328 if ((fp = fopen(_PATH_SCREENDUMP, "w")) != NULL) { 329 for (i = 0; i < DROWS; i++) { 330 for (j=0; j<DCOLS; j++) { 331 buf[j] = mvinch(i, j); 332 } 333 /*buf[DCOLS] = 0; -- redundant */ 334 for (j=DCOLS; j>0 && buf[j-1]==' '; j--); 335 buf[j] = 0; 336 337 fputs(buf, fp); 338 putc('\n', fp); 339 } 340 fclose(fp); 341 } else { 342 sound_bell(); 343 } 344 } 345 346 void 347 sound_bell(void) 348 { 349 putchar(7); 350 fflush(stdout); 351 } 352 353 boolean 354 is_digit(int ch) 355 { 356 return((ch >= '0') && (ch <= '9')); 357 } 358 359 int 360 r_index(const char *str, int ch, boolean last) 361 { 362 int i = 0; 363 364 if (last) { 365 for (i = strlen(str) - 1; i >= 0; i--) { 366 if (str[i] == ch) { 367 return(i); 368 } 369 } 370 } else { 371 for (i = 0; str[i]; i++) { 372 if (str[i] == ch) { 373 return(i); 374 } 375 } 376 } 377 return(-1); 378 } 379