tty messge history restore (trunk only)

This commit is contained in:
nethack.rankin
2009-04-06 01:06:26 +00:00
parent d961d89714
commit 47dad80337
3 changed files with 146 additions and 62 deletions
+1
View File
@@ -48,6 +48,7 @@ struct WinDesc {
/* window flags */ /* window flags */
#define WIN_CANCELLED 1 #define WIN_CANCELLED 1
#define WIN_STOP 1 /* for NHW_MESSAGE; stops output */ #define WIN_STOP 1 /* for NHW_MESSAGE; stops output */
#define WIN_LOCKHISTORY 2 /* for NHW_MESSAGE; suppress history updates */
/* descriptor for tty-based displays -- all the per-display data */ /* descriptor for tty-based displays -- all the per-display data */
struct DisplayDesc { struct DisplayDesc {
+1
View File
@@ -1155,6 +1155,7 @@ register int fd;
putmsghistory(msg); putmsghistory(msg);
++msgcount; ++msgcount;
} }
if (msgcount) putmsghistory((char *)0);
#ifdef DEBUG_MSGCOUNT #ifdef DEBUG_MSGCOUNT
pline("Read %d messages from savefile.", msgcount); pline("Read %d messages from savefile.", msgcount);
#endif #endif
+144 -62
View File
@@ -18,6 +18,8 @@ STATIC_DCL void FDECL(redotoplin, (const nhwchar*));
STATIC_DCL void FDECL(topl_putsym, (NHWCHAR_P)); STATIC_DCL void FDECL(topl_putsym, (NHWCHAR_P));
STATIC_DCL void NDECL(remember_topl); STATIC_DCL void NDECL(remember_topl);
STATIC_DCL void FDECL(removetopl, (int)); STATIC_DCL void FDECL(removetopl, (int));
STATIC_DCL void FDECL(msghistory_snapshot, (BOOLEAN_P));
STATIC_DCL void FDECL(free_msghistory_snapshot, (BOOLEAN_P));
extern nhwchar emptysym[]; extern nhwchar emptysym[];
@@ -185,12 +187,15 @@ remember_topl()
{ {
register struct WinDesc *cw = wins[WIN_MESSAGE]; register struct WinDesc *cw = wins[WIN_MESSAGE];
int idx = cw->maxrow; int idx = cw->maxrow;
#ifdef UNICODE_WIDEWINPORT unsigned len;
unsigned len = nhwlen(toplines) + 1;
#else
unsigned len = strlen(toplines) + 1;
#endif
if ((cw->flags & WIN_LOCKHISTORY) || !*toplines) return;
#ifdef UNICODE_WIDEWINPORT
len = nhwlen(toplines) + 1;
#else
len = strlen(toplines) + 1;
#endif
if (len > (unsigned)cw->datlen[idx]) { if (len > (unsigned)cw->datlen[idx]) {
if (cw->data[idx]) free(cw->data[idx]); if (cw->data[idx]) free(cw->data[idx]);
len += (8 - (len & 7)); /* pad up to next multiple of 8 */ len += (8 - (len & 7)); /* pad up to next multiple of 8 */
@@ -202,6 +207,7 @@ remember_topl()
#else #else
Strcpy(cw->data[idx], toplines); Strcpy(cw->data[idx], toplines);
#endif #endif
*toplines = '\0';
cw->maxcol = cw->maxrow = (idx + 1) % cw->rows; cw->maxcol = cw->maxrow = (idx + 1) % cw->rows;
} }
@@ -575,63 +581,113 @@ char def;
return q; return q;
} }
/* shared by tty_getmsghistory() and tty_putmsghistory() */
static nhwchar **snapshot_mesgs = 0;
/* collect currently available message history data into a sequential array;
optionally, purge that data from the active circular buffer set as we go */
STATIC_OVL void
msghistory_snapshot(purge)
boolean purge; /* clear message history buffer as we copy it */
{
nhwchar *mesg;
unsigned ln;
int i, inidx, outidx;
struct WinDesc *cw;
/* paranoia (too early or too late panic save attempt?) */
if (WIN_MESSAGE == WIN_ERR || !wins[WIN_MESSAGE]) return;
cw = wins[WIN_MESSAGE];
/* flush toplines[], moving most recent message to history */
remember_topl();
/* for a passive snapshot, we just copy pointers, so can't allow further
history updating to take place because that could clobber them */
if (!purge) cw->flags |= WIN_LOCKHISTORY;
snapshot_mesgs = (nhwchar **)alloc((cw->rows + 1) * sizeof (nhwchar *));
outidx = 0;
inidx = cw->maxrow;
for (i = 0; i < cw->rows; ++i) {
snapshot_mesgs[i] = (nhwchar *)0;
mesg = cw->data[inidx];
if (mesg && *mesg) {
snapshot_mesgs[outidx++] = mesg;
if (purge) {
/* we're taking this pointer away; subsequest history
updates will eventually allocate a new one to replace it */
cw->data[inidx] = (nhwchar *)0;
cw->datlen[inidx] = 0;
}
}
inidx = (inidx + 1) % cw->rows;
}
snapshot_mesgs[cw->rows] = (nhwchar *)0; /* sentinel */
/* for a destructive snapshot, history is now completely empty */
if (purge) cw->maxcol = cw->maxrow = 0;
}
/* release memory allocated to message history snapshot */
STATIC_OVL void
free_msghistory_snapshot(purged)
boolean purged; /* True: took history's pointers, False: just cloned them */
{
if (snapshot_mesgs) {
/* snapshot pointers are no longer in use */
if (purged) {
int i;
for (i = 0; snapshot_mesgs[i]; ++i)
free((genericptr_t)snapshot_mesgs[i]);
}
free((genericptr_t)snapshot_mesgs), snapshot_mesgs = (nhwchar **)0;
/* history can resume being updated at will now... */
if (!purged) wins[WIN_MESSAGE]->flags &= ~WIN_LOCKHISTORY;
}
}
/* /*
* This is called by the core save routines. * This is called by the core save routines.
* Each time we are called, we return one string from the * Each time we are called, we return one string from the
* message history starting with the oldest message first. each time * message history starting with the oldest message first.
* we are called. Each time after that, we return a more recent message, * When none are left, we return a final null string.
* until there are no more messages to return. Then we return a final *
* null string. * History is collected at the time of the first call.
* Any new messages issued after that point will not be
* included among the output of the subsequent calls.
*/ */
char * char *
tty_getmsghistory(init) tty_getmsghistory(init)
boolean init; boolean init;
{ {
static int idx = 0, state = 0; static int nxtidx;
static boolean doneinit = FALSE; nhwchar *nextmesg;
register struct WinDesc *cw = wins[WIN_MESSAGE]; char *result = 0;
char *retstr = (char *)0;
#ifdef UNICODE_WIDEWINPORT
static char buf[BUFSZ];
#endif
if (!cw) return (char *)0; /* bail */ if (init) {
/* msghistory_snapshot(FALSE);
* state 0 = normal return with string from msg history. nxtidx = 0;
* state 1 = finished with recall data, return toplines. }
* state 2 = completely finished, return null string.
*/
if (init) {
doneinit = TRUE;
state = 0;
idx = cw->maxrow;
}
if (doneinit && state < 2) {
if (state == 1) {
++state;
#ifdef UNICODE_WIDEWINPORT
strnhwcpy(buf,toplines);
return buf;
#else
return toplines;
#endif
}
do {
#ifdef UNICODE_WIDEWINPORT
if(cw->data[idx] && nhwcmp(cw->data[idx], emptysym) ) {
strnhwcpy(buf, cw->data[idx]);
retstr = buf;
}
#else
if(cw->data[idx] && strcmp(cw->data[idx], "") )
retstr = cw->data[idx];
if (snapshot_mesgs) {
nextmesg = snapshot_mesgs[nxtidx++];
if (nextmesg) {
#ifdef UNICODE_WIDEWINPORT
static char histbuf[BUFSZ];
result = strnhwcpy(histbuf, nextmesg);
#else
result = (char *)nextmesg;
#endif #endif
idx = (idx + 1) % cw->rows; } else {
} while (idx != cw->maxrow && !retstr); free_msghistory_snapshot(FALSE);
if (idx == cw->maxrow) ++state;
} }
return retstr; }
return result;
} }
/* /*
@@ -640,28 +696,54 @@ boolean init;
* history recall buffer. The core will send the oldest message * history recall buffer. The core will send the oldest message
* first (actually it sends them in the order they exist in the * first (actually it sends them in the order they exist in the
* save file, but that is supposed to be the oldest first). * save file, but that is supposed to be the oldest first).
* These messages get pushed behind any which have been issued
* since this session with the program has been started, since
* they come from a previous session and logically precede
* anything (like "Restoring save file...") that's happened now.
*
* Called with a null pointer to finish up.
*/ */
void void
tty_putmsghistory(msg) tty_putmsghistory(msg)
const char *msg; const char *msg;
{ {
register struct WinDesc *cw = wins[WIN_MESSAGE]; static boolean initd = FALSE;
int idx = cw->maxrow; int idx;
unsigned len = strlen(msg) + 1;
if (len > (unsigned)cw->datlen[idx]) { if (!initd) {
if (cw->data[idx]) free(cw->data[idx]); /* we're restoring history from the previous session, but new
len += (8 - (len & 7)); /* pad up to next multiple of 8 */ messages have already been issued this session ("Restoring...",
cw->data[idx] = (nhwchar *)alloc(sizeof(nhwchar) * len); for instance); collect current history (ie, those new messages),
cw->datlen[idx] = (short)len; and also clear it out so that nothing will be present when the
} restored ones are being put into place */
msghistory_snapshot(TRUE);
initd = TRUE;
}
if (msg) {
/* move most recent message to history, make this become most recent */
remember_topl();
#ifdef UNICODE_WIDEWINPORT #ifdef UNICODE_WIDEWINPORT
(void)nhwstrcpy(cw->data[idx], msg); (void)nhwstrcpy(toplines, msg);
#else #else
Strcpy(cw->data[idx], msg); Strcpy(toplines, msg);
#endif #endif
cw->maxcol = cw->maxrow = (idx + 1) % cw->rows; } else if (snapshot_mesgs) {
/* done putting arbitrary messages in; put the snapshot ones back */
for (idx = 0; snapshot_mesgs[idx]; ++idx) {
remember_topl();
#ifdef UNICODE_WIDEWINPORT
(void)nhwcpy(toplines, snapshot_mesgs[idx]);
#else
Strcpy(toplines, snapshot_mesgs[idx]);
#endif
}
/* now release the snapshot */
free_msghistory_snapshot(TRUE);
initd = FALSE; /* reset */
}
} }
#endif /* TTY_GRAPHICS */ #endif /* TTY_GRAPHICS */
/*topl.c*/ /*topl.c*/