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