Mercurial > molko
view libadventure/adventure/state/panic.c @ 162:629f55f3961e
core: rework states
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 18 Oct 2020 12:01:59 +0200 |
parents | libadventure/adventure/panic_state.c@c577c15df07f |
children | 6992085d47fd |
line wrap: on
line source
/* * panic_state.c -- panic state * * Copyright (c) 2020 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <stdnoreturn.h> #include <string.h> #include <core/error.h> #include <core/event.h> #include <core/font.h> #include <core/game.h> #include <core/painter.h> #include <core/panic.h> #include <core/state.h> #include <core/sys.h> #include <core/texture.h> #include <core/util.h> #include <core/window.h> #include <ui/align.h> #include <ui/theme.h> #include <rpg/map_state.h> #include "panic.h" #define BACKGROUND 0x4f5070ff #define FOREGROUND 0xffffffff #define OUT "molko-adventure.txt" struct view { struct { struct texture tex; int x; int y; } texts[4]; }; static noreturn void die(const char *fmt, ...) { assert(fmt); va_list ap; va_start(ap, fmt); fprintf(stderr, "abort: "); vfprintf(stderr, fmt, ap); va_end(ap); abort(); exit(1); } static noreturn void stop(void) { die("%s", error()); } static void dump(void) { FILE *fp; if ((fp = fopen(OUT, "w"))) { /* TODO: add more info here. */ fprintf(fp, "Molko's Adventure crash dump report\n"); fclose(fp); } abort(); } static struct view * init(void) { struct theme *theme; struct view *view; struct font font; theme = theme_default(); view = ecalloc(1, sizeof (*view)); /* Generate the texts. */ font_shallow(&font, theme->fonts[THEME_FONT_INTERFACE]); font.style = FONT_STYLE_ANTIALIASED, font.color = FOREGROUND; if (!font_render(&font, &view->texts[0].tex, "An unrecoverable error occured and the game cannot continue.") || !font_render(&font, &view->texts[1].tex, "Please report the detailed error as provided below.") || !font_render(&font, &view->texts[2].tex, "Press <s> to save information and generate a core dump.") || !font_render(&font, &view->texts[3].tex, "Press <q> to quit without saving information.")) die("%s", error()); /* All align x the same. */ for (size_t i = 0; i < NELEM(view->texts); ++i) view->texts[i].x = theme->padding; /* Header (0-1). */ view->texts[0].y = theme->padding; view->texts[1].y = view->texts[0].y + view->texts[0].tex.h + theme->padding; /* Footer. (2-3). */ view->texts[3].y = window.h - view->texts[2].tex.h - theme->padding; view->texts[2].y = view->texts[3].y - view->texts[3].tex.h - theme->padding; return view; } static void handle_keydown(const struct event_key *ev) { assert(ev); switch (ev->key) { case KEY_q: game_quit(); break; case KEY_s: dump(); break; default: break; } } static void start(struct state *state) { (void)state; /* We remove the panic handler to avoid infinite recursion. */ panic_handler = stop; } static void handle(struct state *state, const union event *ev) { assert(ev); (void)state; switch (ev->type) { case EVENT_KEYDOWN: handle_keydown(&ev->key); break; default: break; } } static void draw(struct state *state) { struct theme *theme = theme_default(); struct view *view = state->data; struct texture tex; struct font font; int x, y; painter_set_color(BACKGROUND); painter_clear(); for (size_t i = 0; i < NELEM(view->texts); ++i) texture_draw(&view->texts[i].tex, view->texts[i].x, view->texts[i].y); /* The error is only available here. */ font_shallow(&font, theme->fonts[THEME_FONT_INTERFACE]); font.color = FOREGROUND; font.style = FONT_STYLE_ANTIALIASED; if (!font_render(&font, &tex, error())) die("%s\n", error()); align(ALIGN_LEFT, &x, &y, tex.w, tex.h, 0, 0, window.w, window.h); texture_draw(&tex, x + theme->padding, y); texture_finish(&tex); } static void finish(struct state *state) { struct view *view = state->data; if (!view) return; for (size_t i = 0; i < NELEM(view->texts); ++i) texture_finish(&view->texts[i].tex); free(view); memset(state, 0, sizeof (*state)); } void panic_state(struct state *state) { assert(state); memset(state, 0, sizeof (*state)); state->data = init(); state->start = start; state->handle = handle; state->draw = draw; state->finish = finish; }