OSDN Git Service

patch races
[jnethack/source.git] / win / tty / topl.c
1 /* NetHack 3.6  topl.c  $NHDT-Date: 1431192777 2015/05/09 17:32:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.32 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6
7 #ifdef TTY_GRAPHICS
8
9 #include "tcap.h"
10 #include "wintty.h"
11 #include <ctype.h>
12
13 #ifndef C /* this matches src/cmd.c */
14 #define C(c) (0x1f & (c))
15 #endif
16
17 STATIC_DCL void FDECL(redotoplin, (const char *));
18 STATIC_DCL void FDECL(topl_putsym, (CHAR_P));
19 STATIC_DCL void NDECL(remember_topl);
20 STATIC_DCL void FDECL(removetopl, (int));
21 STATIC_DCL void FDECL(msghistory_snapshot, (BOOLEAN_P));
22 STATIC_DCL void FDECL(free_msghistory_snapshot, (BOOLEAN_P));
23
24 int
25 tty_doprev_message()
26 {
27     register struct WinDesc *cw = wins[WIN_MESSAGE];
28
29     winid prevmsg_win;
30     int i;
31     if ((iflags.prevmsg_window != 's')
32         && !ttyDisplay->inread) {           /* not single */
33         if (iflags.prevmsg_window == 'f') { /* full */
34             prevmsg_win = create_nhwindow(NHW_MENU);
35             putstr(prevmsg_win, 0, "Message History");
36             putstr(prevmsg_win, 0, "");
37             cw->maxcol = cw->maxrow;
38             i = cw->maxcol;
39             do {
40                 if (cw->data[i] && strcmp(cw->data[i], ""))
41                     putstr(prevmsg_win, 0, cw->data[i]);
42                 i = (i + 1) % cw->rows;
43             } while (i != cw->maxcol);
44             putstr(prevmsg_win, 0, toplines);
45             display_nhwindow(prevmsg_win, TRUE);
46             destroy_nhwindow(prevmsg_win);
47         } else if (iflags.prevmsg_window == 'c') { /* combination */
48             do {
49                 morc = 0;
50                 if (cw->maxcol == cw->maxrow) {
51                     ttyDisplay->dismiss_more =
52                         C('p'); /* <ctrl/P> allowed at --More-- */
53                     redotoplin(toplines);
54                     cw->maxcol--;
55                     if (cw->maxcol < 0)
56                         cw->maxcol = cw->rows - 1;
57                     if (!cw->data[cw->maxcol])
58                         cw->maxcol = cw->maxrow;
59                 } else if (cw->maxcol == (cw->maxrow - 1)) {
60                     ttyDisplay->dismiss_more =
61                         C('p'); /* <ctrl/P> allowed at --More-- */
62                     redotoplin(cw->data[cw->maxcol]);
63                     cw->maxcol--;
64                     if (cw->maxcol < 0)
65                         cw->maxcol = cw->rows - 1;
66                     if (!cw->data[cw->maxcol])
67                         cw->maxcol = cw->maxrow;
68                 } else {
69                     prevmsg_win = create_nhwindow(NHW_MENU);
70                     putstr(prevmsg_win, 0, "Message History");
71                     putstr(prevmsg_win, 0, "");
72                     cw->maxcol = cw->maxrow;
73                     i = cw->maxcol;
74                     do {
75                         if (cw->data[i] && strcmp(cw->data[i], ""))
76                             putstr(prevmsg_win, 0, cw->data[i]);
77                         i = (i + 1) % cw->rows;
78                     } while (i != cw->maxcol);
79                     putstr(prevmsg_win, 0, toplines);
80                     display_nhwindow(prevmsg_win, TRUE);
81                     destroy_nhwindow(prevmsg_win);
82                 }
83
84             } while (morc == C('p'));
85             ttyDisplay->dismiss_more = 0;
86         } else { /* reversed */
87             morc = 0;
88             prevmsg_win = create_nhwindow(NHW_MENU);
89             putstr(prevmsg_win, 0, "Message History");
90             putstr(prevmsg_win, 0, "");
91             putstr(prevmsg_win, 0, toplines);
92             cw->maxcol = cw->maxrow - 1;
93             if (cw->maxcol < 0)
94                 cw->maxcol = cw->rows - 1;
95             do {
96                 putstr(prevmsg_win, 0, cw->data[cw->maxcol]);
97                 cw->maxcol--;
98                 if (cw->maxcol < 0)
99                     cw->maxcol = cw->rows - 1;
100                 if (!cw->data[cw->maxcol])
101                     cw->maxcol = cw->maxrow;
102             } while (cw->maxcol != cw->maxrow);
103
104             display_nhwindow(prevmsg_win, TRUE);
105             destroy_nhwindow(prevmsg_win);
106             cw->maxcol = cw->maxrow;
107             ttyDisplay->dismiss_more = 0;
108         }
109     } else if (iflags.prevmsg_window == 's') { /* single */
110         ttyDisplay->dismiss_more = C('p'); /* <ctrl/P> allowed at --More-- */
111         do {
112             morc = 0;
113             if (cw->maxcol == cw->maxrow)
114                 redotoplin(toplines);
115             else if (cw->data[cw->maxcol])
116                 redotoplin(cw->data[cw->maxcol]);
117             cw->maxcol--;
118             if (cw->maxcol < 0)
119                 cw->maxcol = cw->rows - 1;
120             if (!cw->data[cw->maxcol])
121                 cw->maxcol = cw->maxrow;
122         } while (morc == C('p'));
123         ttyDisplay->dismiss_more = 0;
124     }
125     return 0;
126 }
127
128 STATIC_OVL void
129 redotoplin(str)
130 const char *str;
131 {
132     int otoplin = ttyDisplay->toplin;
133     home();
134 #if 0 /*JP*/
135     if (*str & 0x80) {
136         /* kludge for the / command, the only time we ever want a */
137         /* graphics character on the top line */
138         g_putch((int) *str++);
139         ttyDisplay->curx++;
140     }
141 #endif
142     end_glyphout(); /* in case message printed during graphics output */
143     putsyms(str);
144     cl_end();
145     ttyDisplay->toplin = 1;
146     if (ttyDisplay->cury && otoplin != 3)
147         more();
148 }
149
150 STATIC_OVL void
151 remember_topl()
152 {
153     register struct WinDesc *cw = wins[WIN_MESSAGE];
154     int idx = cw->maxrow;
155     unsigned len = strlen(toplines) + 1;
156
157     if ((cw->flags & WIN_LOCKHISTORY) || !*toplines)
158         return;
159
160     if (len > (unsigned) cw->datlen[idx]) {
161         if (cw->data[idx])
162             free(cw->data[idx]);
163         len += (8 - (len & 7)); /* pad up to next multiple of 8 */
164         cw->data[idx] = (char *) alloc(len);
165         cw->datlen[idx] = (short) len;
166     }
167     Strcpy(cw->data[idx], toplines);
168     *toplines = '\0';
169     cw->maxcol = cw->maxrow = (idx + 1) % cw->rows;
170 }
171
172 void
173 addtopl(s)
174 const char *s;
175 {
176     register struct WinDesc *cw = wins[WIN_MESSAGE];
177
178     tty_curs(BASE_WINDOW, cw->curx + 1, cw->cury);
179     putsyms(s);
180     cl_end();
181     ttyDisplay->toplin = 1;
182 }
183
184 void
185 more()
186 {
187     struct WinDesc *cw = wins[WIN_MESSAGE];
188
189     /* avoid recursion -- only happens from interrupts */
190     if (ttyDisplay->inmore++)
191         return;
192
193     if (ttyDisplay->toplin) {
194         tty_curs(BASE_WINDOW, cw->curx + 1, cw->cury);
195         if (cw->curx >= CO - 8)
196             topl_putsym('\n');
197     }
198
199     if (flags.standout)
200         standoutbeg();
201     putsyms(defmorestr);
202     if (flags.standout)
203         standoutend();
204
205     xwaitforspace("\033 ");
206
207     if (morc == '\033')
208         cw->flags |= WIN_STOP;
209
210     if (ttyDisplay->toplin && cw->cury) {
211         docorner(1, cw->cury + 1);
212         cw->curx = cw->cury = 0;
213         home();
214     } else if (morc == '\033') {
215         cw->curx = cw->cury = 0;
216         home();
217         cl_end();
218     }
219     ttyDisplay->toplin = 0;
220     ttyDisplay->inmore = 0;
221 }
222 #if 1 /*JP*/
223 static char *
224 folding_japanese( str, pos )
225      const char *str;
226      int pos;
227 {
228   char ss[1024],s1[1024],s2[1024];
229   static char newstr[1024];             /* may be enough */
230
231   newstr[0] = '\0';
232   Strcpy(ss, str);
233   while(1){
234     split_japanese(ss, s1, s2, pos);
235     Strcat(newstr, s1);
236     if(!*s2)
237       break;
238     Strcat(newstr, "\n");
239     Strcpy(ss,s2);
240   }
241
242   return newstr;
243 }
244 #endif
245
246 void
247 update_topl(bp)
248 register const char *bp;
249 {
250 #if 0 /*JP*/
251     register char *tl, *otl;
252 #endif
253     register int n0;
254     int notdied = 1;
255     struct WinDesc *cw = wins[WIN_MESSAGE];
256
257     /* If there is room on the line, print message on same line */
258     /* But messages like "You die..." deserve their own line */
259     n0 = strlen(bp);
260     if ((ttyDisplay->toplin == 1 || (cw->flags & WIN_STOP)) && cw->cury == 0
261         && n0 + (int) strlen(toplines) + 3 < CO - 8 && /* room for --More-- */
262         (notdied = strncmp(bp, "You die", 7))) {
263         Strcat(toplines, "  ");
264         Strcat(toplines, bp);
265         cw->curx += 2;
266         if (!(cw->flags & WIN_STOP))
267             addtopl(bp);
268         return;
269     } else if (!(cw->flags & WIN_STOP)) {
270         if (ttyDisplay->toplin == 1)
271             more();
272         else if (cw->cury) { /* for when flags.toplin == 2 && cury > 1 */
273             docorner(1, cw->cury + 1); /* reset cury = 0 if redraw screen */
274             cw->curx = cw->cury = 0;   /* from home--cls() & docorner(1,n) */
275         }
276     }
277     remember_topl();
278 #if 1 /*JP*/
279     if( n0<CO )
280       Strcpy(toplines, bp);
281     else
282       Strcpy(toplines,folding_japanese(bp, CO-2));
283 #else
284     (void) strncpy(toplines, bp, TBUFSZ);
285     toplines[TBUFSZ - 1] = 0;
286
287     for (tl = toplines; n0 >= CO;) {
288         otl = tl;
289         for (tl += CO - 1; tl != otl && !isspace(*tl); --tl)
290             ;
291         if (tl == otl) {
292             /* Eek!  A huge token.  Try splitting after it. */
293             tl = index(otl, ' ');
294             if (!tl)
295                 break; /* No choice but to spit it out whole. */
296         }
297         *tl++ = '\n';
298         n0 = strlen(tl);
299     }
300 #endif
301     if (!notdied)
302         cw->flags &= ~WIN_STOP;
303     if (!(cw->flags & WIN_STOP))
304         redotoplin(toplines);
305 }
306
307 STATIC_OVL
308 void
309 topl_putsym(c)
310 char c;
311 {
312     register struct WinDesc *cw = wins[WIN_MESSAGE];
313 #if 1 /*JP*/
314     unsigned char uc = *((unsigned char *)(&c));
315 #endif
316
317     if (cw == (struct WinDesc *) 0)
318         panic("Putsym window MESSAGE nonexistant");
319
320     switch (c) {
321     case '\b':
322         if (ttyDisplay->curx == 0 && ttyDisplay->cury > 0)
323             tty_curs(BASE_WINDOW, CO, (int) ttyDisplay->cury - 1);
324         backsp();
325         ttyDisplay->curx--;
326         cw->curx = ttyDisplay->curx;
327         return;
328     case '\n':
329         cl_end();
330 #if 1 /*JP*/
331         (void) jputchar('\r'); /* raw mode \82Ã…\95K\97v? */
332         (void) jputchar('\n');
333 #endif
334         ttyDisplay->curx = 0;
335         ttyDisplay->cury++;
336         cw->cury = ttyDisplay->cury;
337 #if 0 /*JP*/
338 #ifdef WIN32CON
339         (void) putchar(c);
340 #endif
341 #endif
342         break;
343     default:
344         if (ttyDisplay->curx == CO - 1)
345             topl_putsym('\n'); /* 1 <= curx <= CO; avoid CO */
346 #if 0 /*JP*/
347 #ifdef WIN32CON
348         (void) putchar(c);
349 #endif
350 #endif
351 #if 1 /*JP*/
352         cw->curx = ttyDisplay->curx;
353         if(cw->curx == 0) cl_end();
354         (void) jputchar((unsigned char)uc);
355         cw->curx++;
356 #endif
357         ttyDisplay->curx++;
358     }
359 #if 0 /*JP*/
360     cw->curx = ttyDisplay->curx;
361     if (cw->curx == 0)
362         cl_end();
363 #ifndef WIN32CON
364     (void) putchar(c);
365 #endif
366 #endif
367 }
368
369 void
370 putsyms(str)
371 const char *str;
372 {
373     while (*str)
374         topl_putsym(*str++);
375 }
376
377 /* JP
378 ** do not translate kcode this function(see topl_putsym)
379 */
380 STATIC_OVL
381 void
382 raw_topl_putsym(c)
383     char c;
384 {
385     register struct WinDesc *cw = wins[WIN_MESSAGE];
386
387     if(cw == (struct WinDesc *) 0) panic("Putsym window MESSAGE nonexistant");
388         
389     switch(c) {
390     case '\b':
391         if(ttyDisplay->curx == 0 && ttyDisplay->cury > 0)
392             tty_curs(BASE_WINDOW, CO, (int)ttyDisplay->cury-1);
393         backsp();
394         ttyDisplay->curx--;
395         cw->curx = ttyDisplay->curx;
396         return;
397     case '\n':
398         cl_end();
399 #if 1 /*JP*/
400         (void) cputchar('\r'); /* raw mode \82Ã…\95K\97v? */
401         (void) cputchar('\n');
402 #endif
403         ttyDisplay->curx = 0;
404         ttyDisplay->cury++;
405         cw->cury = ttyDisplay->cury;
406         break;
407     default:
408         if(ttyDisplay->curx == CO-1)
409             topl_putsym('\n'); /* 1 <= curx <= CO; avoid CO */
410 #if 0 /*JP*/
411         ttyDisplay->curx++;
412 #else
413     cw->curx = ttyDisplay->curx;
414     if(cw->curx == 0) cl_end();
415         (void) cputchar(c);
416         ++cw->curx;
417         ++ttyDisplay->curx;
418 #endif
419     }
420 }
421 /* JP
422 ** do not translate kcode this function(see putsym)
423 */
424 void
425 raw_putsyms(str)
426     const char *str;
427 {
428     while(*str)
429         raw_topl_putsym(*str++);
430 }
431
432 STATIC_OVL void
433 removetopl(n)
434 register int n;
435 {
436     /* assume addtopl() has been done, so ttyDisplay->toplin is already set */
437     while (n-- > 0)
438         putsyms("\b \b");
439 }
440
441 extern char erase_char; /* from xxxtty.c; don't need kill_char */
442
443 char
444 tty_yn_function(query, resp, def)
445 const char *query, *resp;
446 char def;
447 /*
448  *   Generic yes/no function. 'def' is the default (returned by space or
449  *   return; 'esc' returns 'q', or 'n', or the default, depending on
450  *   what's in the string. The 'query' string is printed before the user
451  *   is asked about the string.
452  *   If resp is NULL, any single character is accepted and returned.
453  *   If not-NULL, only characters in it are allowed (exceptions:  the
454  *   quitchars are always allowed, and if it contains '#' then digits
455  *   are allowed); if it includes an <esc>, anything beyond that won't
456  *   be shown in the prompt to the user but will be acceptable as input.
457  */
458 {
459     register char q;
460     char rtmp[40];
461     boolean digit_ok, allow_num, preserve_case = FALSE;
462     struct WinDesc *cw = wins[WIN_MESSAGE];
463     boolean doprev = 0;
464     char prompt[BUFSZ];
465
466     if (ttyDisplay->toplin == 1 && !(cw->flags & WIN_STOP))
467         more();
468     cw->flags &= ~WIN_STOP;
469     ttyDisplay->toplin = 3; /* special prompt state */
470     ttyDisplay->inread++;
471     if (resp) {
472         char *rb, respbuf[QBUFSZ];
473
474         allow_num = (index(resp, '#') != 0);
475         Strcpy(respbuf, resp);
476         /* normally we force lowercase, but if any uppercase letters
477            are present in the allowed response, preserve case;
478            check this before stripping the hidden choices */
479         for (rb = respbuf; *rb; ++rb)
480             if ('A' <= *rb && *rb <= 'Z') {
481                 preserve_case = TRUE;
482                 break;
483             }
484         /* any acceptable responses that follow <esc> aren't displayed */
485         if ((rb = index(respbuf, '\033')) != 0)
486             *rb = '\0';
487         (void) strncpy(prompt, query, QBUFSZ - 1);
488         prompt[QBUFSZ - 1] = '\0';
489         Sprintf(eos(prompt), " [%s]", respbuf);
490         if (def)
491             Sprintf(eos(prompt), " (%c)", def);
492         /* not pline("%s ", prompt);
493            trailing space is wanted here in case of reprompt */
494         Strcat(prompt, " ");
495         pline("%s", prompt);
496     } else {
497         /* no restriction on allowed response, so always preserve case */
498         /* preserve_case = TRUE; -- moot since we're jumping to the end */
499         pline("%s ", query);
500         q = readchar();
501         goto clean_up;
502     }
503
504     do { /* loop until we get valid input */
505         q = readchar();
506         if (!preserve_case)
507             q = lowc(q);
508         if (q == '\020') { /* ctrl-P */
509             if (iflags.prevmsg_window != 's') {
510                 int sav = ttyDisplay->inread;
511                 ttyDisplay->inread = 0;
512                 (void) tty_doprev_message();
513                 ttyDisplay->inread = sav;
514                 tty_clear_nhwindow(WIN_MESSAGE);
515                 cw->maxcol = cw->maxrow;
516                 addtopl(prompt);
517             } else {
518                 if (!doprev)
519                     (void) tty_doprev_message(); /* need two initially */
520                 (void) tty_doprev_message();
521                 doprev = 1;
522             }
523             q = '\0'; /* force another loop iteration */
524             continue;
525         } else if (doprev) {
526             /* BUG[?]: this probably ought to check whether the
527                character which has just been read is an acceptable
528                response; if so, skip the reprompt and use it. */
529             tty_clear_nhwindow(WIN_MESSAGE);
530             cw->maxcol = cw->maxrow;
531             doprev = 0;
532             addtopl(prompt);
533             q = '\0'; /* force another loop iteration */
534             continue;
535         }
536         digit_ok = allow_num && digit(q);
537         if (q == '\033') {
538             if (index(resp, 'q'))
539                 q = 'q';
540             else if (index(resp, 'n'))
541                 q = 'n';
542             else
543                 q = def;
544             break;
545         } else if (index(quitchars, q)) {
546             q = def;
547             break;
548         }
549         if (!index(resp, q) && !digit_ok) {
550             tty_nhbell();
551             q = (char) 0;
552         } else if (q == '#' || digit_ok) {
553             char z, digit_string[2];
554             int n_len = 0;
555             long value = 0;
556             addtopl("#"), n_len++;
557             digit_string[1] = '\0';
558             if (q != '#') {
559                 digit_string[0] = q;
560                 addtopl(digit_string), n_len++;
561                 value = q - '0';
562                 q = '#';
563             }
564             do { /* loop until we get a non-digit */
565                 z = readchar();
566                 if (!preserve_case)
567                     z = lowc(z);
568                 if (digit(z)) {
569                     value = (10 * value) + (z - '0');
570                     if (value < 0)
571                         break; /* overflow: try again */
572                     digit_string[0] = z;
573                     addtopl(digit_string), n_len++;
574                 } else if (z == 'y' || index(quitchars, z)) {
575                     if (z == '\033')
576                         value = -1; /* abort */
577                     z = '\n';       /* break */
578                 } else if (z == erase_char || z == '\b') {
579                     if (n_len <= 1) {
580                         value = -1;
581                         break;
582                     } else {
583                         value /= 10;
584                         removetopl(1), n_len--;
585                     }
586                 } else {
587                     value = -1; /* abort */
588                     tty_nhbell();
589                     break;
590                 }
591             } while (z != '\n');
592             if (value > 0)
593                 yn_number = value;
594             else if (value == 0)
595                 q = 'n'; /* 0 => "no" */
596             else {       /* remove number from top line, then try again */
597                 removetopl(n_len), n_len = 0;
598                 q = '\0';
599             }
600         }
601     } while (!q);
602
603     if (q != '#') {
604         Sprintf(rtmp, "%c", q);
605         addtopl(rtmp);
606     }
607 clean_up:
608     ttyDisplay->inread--;
609     ttyDisplay->toplin = 2;
610     if (ttyDisplay->intr)
611         ttyDisplay->intr--;
612     if (wins[WIN_MESSAGE]->cury)
613         tty_clear_nhwindow(WIN_MESSAGE);
614
615     return q;
616 }
617
618 /* shared by tty_getmsghistory() and tty_putmsghistory() */
619 static char **snapshot_mesgs = 0;
620
621 /* collect currently available message history data into a sequential array;
622    optionally, purge that data from the active circular buffer set as we go */
623 STATIC_OVL void
624 msghistory_snapshot(purge)
625 boolean purge; /* clear message history buffer as we copy it */
626 {
627     char *mesg;
628     int i, inidx, outidx;
629     struct WinDesc *cw;
630
631     /* paranoia (too early or too late panic save attempt?) */
632     if (WIN_MESSAGE == WIN_ERR || !wins[WIN_MESSAGE])
633         return;
634     cw = wins[WIN_MESSAGE];
635
636     /* flush toplines[], moving most recent message to history */
637     remember_topl();
638
639     /* for a passive snapshot, we just copy pointers, so can't allow further
640        history updating to take place because that could clobber them */
641     if (!purge)
642         cw->flags |= WIN_LOCKHISTORY;
643
644     snapshot_mesgs = (char **) alloc((cw->rows + 1) * sizeof(char *));
645     outidx = 0;
646     inidx = cw->maxrow;
647     for (i = 0; i < cw->rows; ++i) {
648         snapshot_mesgs[i] = (char *) 0;
649         mesg = cw->data[inidx];
650         if (mesg && *mesg) {
651             snapshot_mesgs[outidx++] = mesg;
652             if (purge) {
653                 /* we're taking this pointer away; subsequest history
654                    updates will eventually allocate a new one to replace it */
655                 cw->data[inidx] = (char *) 0;
656                 cw->datlen[inidx] = 0;
657             }
658         }
659         inidx = (inidx + 1) % cw->rows;
660     }
661     snapshot_mesgs[cw->rows] = (char *) 0; /* sentinel */
662
663     /* for a destructive snapshot, history is now completely empty */
664     if (purge)
665         cw->maxcol = cw->maxrow = 0;
666 }
667
668 /* release memory allocated to message history snapshot */
669 STATIC_OVL void
670 free_msghistory_snapshot(purged)
671 boolean purged; /* True: took history's pointers, False: just cloned them */
672 {
673     if (snapshot_mesgs) {
674         /* snapshot pointers are no longer in use */
675         if (purged) {
676             int i;
677
678             for (i = 0; snapshot_mesgs[i]; ++i)
679                 free((genericptr_t) snapshot_mesgs[i]);
680         }
681
682         free((genericptr_t) snapshot_mesgs), snapshot_mesgs = (char **) 0;
683
684         /* history can resume being updated at will now... */
685         if (!purged)
686             wins[WIN_MESSAGE]->flags &= ~WIN_LOCKHISTORY;
687     }
688 }
689
690 /*
691  * This is called by the core save routines.
692  * Each time we are called, we return one string from the
693  * message history starting with the oldest message first.
694  * When none are left, we return a final null string.
695  *
696  * History is collected at the time of the first call.
697  * Any new messages issued after that point will not be
698  * included among the output of the subsequent calls.
699  */
700 char *
701 tty_getmsghistory(init)
702 boolean init;
703 {
704     static int nxtidx;
705     char *nextmesg;
706     char *result = 0;
707
708     if (init) {
709         msghistory_snapshot(FALSE);
710         nxtidx = 0;
711     }
712
713     if (snapshot_mesgs) {
714         nextmesg = snapshot_mesgs[nxtidx++];
715         if (nextmesg) {
716             result = (char *) nextmesg;
717         } else {
718             free_msghistory_snapshot(FALSE);
719         }
720     }
721     return result;
722 }
723
724 /*
725  * This is called by the core savefile restore routines.
726  * Each time we are called, we stuff the string into our message
727  * history recall buffer. The core will send the oldest message
728  * first (actually it sends them in the order they exist in the
729  * save file, but that is supposed to be the oldest first).
730  * These messages get pushed behind any which have been issued
731  * since this session with the program has been started, since
732  * they come from a previous session and logically precede
733  * anything (like "Restoring save file...") that's happened now.
734  *
735  * Called with a null pointer to finish up restoration.
736  *
737  * It's also called by the quest pager code when a block message
738  * has a one-line summary specified.  We put that line directly
739  * message history for ^P recall without having displayed it.
740  */
741 void
742 tty_putmsghistory(msg, restoring_msghist)
743 const char *msg;
744 boolean restoring_msghist;
745 {
746     static boolean initd = FALSE;
747     int idx;
748
749     if (restoring_msghist && !initd) {
750         /* we're restoring history from the previous session, but new
751            messages have already been issued this session ("Restoring...",
752            for instance); collect current history (ie, those new messages),
753            and also clear it out so that nothing will be present when the
754            restored ones are being put into place */
755         msghistory_snapshot(TRUE);
756         initd = TRUE;
757     }
758
759     if (msg) {
760         /* move most recent message to history, make this become most recent
761          */
762         remember_topl();
763         Strcpy(toplines, msg);
764     } else if (snapshot_mesgs) {
765         /* done putting arbitrary messages in; put the snapshot ones back */
766         for (idx = 0; snapshot_mesgs[idx]; ++idx) {
767             remember_topl();
768             Strcpy(toplines, snapshot_mesgs[idx]);
769         }
770         /* now release the snapshot */
771         free_msghistory_snapshot(TRUE);
772         initd = FALSE; /* reset */
773     }
774 }
775
776 #endif /* TTY_GRAPHICS */
777
778 /*topl.c*/