/* returns 1 if save successful */ int dosave0(boolean emergency) { int fd; struct memfile mf; boolean log_disabled = iflags.disable_log; mnew(&mf, NULL); fd = logfile; /* when we leave via nh_exit, logging is disabled. It needs to be enabled briefly so that log_finish will update the log header. */ iflags.disable_log = FALSE; log_finish(LS_SAVED); iflags.disable_log = log_disabled; vision_recalc(2); /* shut down vision to prevent problems in the event of an impossible() call */ savegame(&mf); store_mf(fd, &mf); /* also frees mf */ freedynamicdata(); return TRUE; }
boolean nh_exit_game(int exit_type) { boolean log_disabled = iflags.disable_log; if (!api_entry_checkpoint()) { /* not sure anything in here can actually call panic */ iflags.disable_log = log_disabled; return TRUE; /* terminate was called, so exit is successful */ } program_state.forced_exit = TRUE; /* clean up after viewing a game replay */ if (program_state.viewing) nh_view_replay_finish(); xmalloc_cleanup(); iflags.disable_log = TRUE; if (program_state.game_running) { switch (exit_type) { case EXIT_REQUEST_SAVE: dosave(); /* will ask "really save?" and, if 'y', eventually call terminate. */ break; case EXIT_FORCE_SAVE: dosave0(TRUE); terminate(); break; case EXIT_REQUEST_QUIT: done2(); break; case EXIT_FORCE_QUIT: done(QUIT); break; /* not reached */ case EXIT_PANIC: /* freeing things should be safe */ freedynamicdata(); dlb_cleanup(); panic("UI problem."); break; } iflags.disable_log = log_disabled; api_exit(); return FALSE; } iflags.disable_log = log_disabled; /* calling terminate() will get us out of nested contexts safely, eg: * UI_cmdloop -> nh_command -> UI_update_screen (problem happens here) -> nh_exit_game * will jump all the way back to UI_cmdloop */ terminate(); api_exit(); /* not reached */ return TRUE; }