curses message recall, memory leaks

Using ^P right after resize or 'O' of align_message, align_status,
statuslines, or windowborders would result in
'curses_display_nhmenu: attempt to display empty menu'
because some memory cleanup I added several weeks back was being
executed when the curses interface tore down and recreated its
internal windows.

This fixes ^P handling by making sure that that menu (which is just
text but uses a menu to support '>'/'<'/'^'/'|' scrolling) will never
be empty and it also fixes the window deletion to not throw away
message history until it's final deletion at exit time.

^P uses a popup window to display previous messages and it was never
deleting that window, just creating a new one each time.  Same with
the routine which displays an external help file.  Using either or
combination of both close to 5000 times would probably make internal
window creation get stuck in an infinite loop.  Delete those windows
after they're used so it'll never be put to the test.

The memory cleanup I added for map/status/messages/invent was only
being preformed at end of game, not when saving.  Fix that too.
This commit is contained in:
PatR
2019-03-24 17:50:26 -07:00
parent 804a4f1846
commit ee53a9fea6
11 changed files with 103 additions and 64 deletions
+20 -20
View File
@@ -147,7 +147,7 @@ curses_create_window(int width, int height, orient orientation)
/* Erase and delete curses window, and refresh standard windows */
void
curses_destroy_win(WINDOW * win)
curses_destroy_win(WINDOW *win)
{
werase(win);
wrefresh(win);
@@ -303,8 +303,11 @@ void
curses_del_nhwin(winid wid)
{
if (curses_is_menu(wid) || curses_is_text(wid)) {
curses_del_menu(wid);
curses_del_menu(wid, TRUE);
return;
} else if (wid == INV_WIN) {
curses_del_menu(wid, TRUE);
/* don't return yet */
}
if (!is_main_window(wid)) {
@@ -312,9 +315,6 @@ curses_del_nhwin(winid wid)
wid);
return;
}
if (wid == MESSAGE_WIN) {
curses_teardown_messages();
}
nhwins[wid].curwin = NULL;
nhwins[wid].nhwin = -1;
}
@@ -326,31 +326,35 @@ void
curses_del_wid(winid wid)
{
nethack_wid *tmpwid;
nethack_wid *widptr = nhwids;
nethack_wid *widptr;
if (curses_is_menu(wid) || curses_is_text(wid)) {
curses_del_menu(wid);
curses_del_menu(wid, FALSE);
}
while (widptr != NULL) {
for (widptr = nhwids; widptr; widptr = widptr->next_wid) {
if (widptr->nhwid == wid) {
if (widptr->prev_wid != NULL) {
tmpwid = widptr->prev_wid;
if ((tmpwid = widptr->prev_wid) != NULL) {
tmpwid->next_wid = widptr->next_wid;
} else {
nhwids = widptr->next_wid; /* New head mode, or NULL */
}
if (widptr->next_wid != NULL) {
tmpwid = widptr->next_wid;
if ((tmpwid = widptr->next_wid) != NULL) {
tmpwid->prev_wid = widptr->prev_wid;
}
free(widptr);
break;
}
widptr = widptr->next_wid;
}
}
/* called by destroy_nhwindows() prior to exit */
void
curs_destroy_all_wins()
{
while (nhwids)
curses_del_wid(nhwids->nhwid);
}
/* Print a single character in the given window at the given coordinates */
@@ -439,15 +443,11 @@ curses_window_has_border(winid wid)
boolean
curses_window_exists(winid wid)
{
nethack_wid *widptr = nhwids;
nethack_wid *widptr;
while (widptr != NULL) {
if (widptr->nhwid == wid) {
for (widptr = nhwids; widptr; widptr = widptr->next_wid)
if (widptr->nhwid == wid)
return TRUE;
}
widptr = widptr->next_wid;
}
return FALSE;
}