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