OSDN Git Service

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