/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "glk/hugo/hugo.h" namespace Glk { namespace Hugo { void Hugo::hugo_init_screen() { // Open the main window... mainwin = currentwin = glk_window_open(0, 0, 0, wintype_TextBuffer, 1); assert(mainwin); // ...and set it up for default output glk_set_window(mainwin); // By setting the width and height so high, we're basically forcing the Glk library // to deal with text-wrapping and page ends SCREENWIDTH = 0x7fff; SCREENHEIGHT = 0x7fff; FIXEDCHARWIDTH = 1; FIXEDLINEHEIGHT = 1; hugo_settextwindow(1, 1, SCREENWIDTH/FIXEDCHARWIDTH, SCREENHEIGHT/FIXEDLINEHEIGHT); } void Hugo::hugo_getline(const char *prmpt) { event_t ev; char gotline = 0; /* Just in case we try to get line input from a Glk-illegal window that hasn't been created, switch as a failsafe to mainwin */ if (currentwin == nullptr) glk_set_window(currentwin = mainwin); /* Print prompt */ glk_put_string(prmpt); /* Request line input */ glk_request_line_event(currentwin, buffer, MAXBUFFER, 0); while (!gotline) { if (shouldQuit()) return; /* Grab an event */ glk_select(&ev); switch (ev.type) { case evtype_LineInput: /* (Will always be currentwin, but anyway) */ if (ev.window == currentwin) { gotline = true; } break; default: break; } } /* The line we have received in commandbuf is not null-terminated */ buffer[ev.val1] = '\0'; /* i.e., the length */ /* Copy the input to the script file (if open) */ if (script) { Common::String text = Common::String::format("%s%s\n", prmpt, buffer); script->putBuffer(text.c_str(), text.size()); } } int Hugo::hugo_waitforkey() { event_t ev; char gotchar = 0; /* Just in case we try to get key input from a Glk-illegal window that hasn't been created, switch as a failsafe to mainwin */ if (currentwin == nullptr) glk_set_window(currentwin = mainwin); #if defined (NO_KEYPRESS_CURSOR) if (currentwin != mainwin) { glk_window_move_cursor(currentwin, currentpos / CHARWIDTH, currentline - 1); hugo_print("*"); glk_window_move_cursor(currentwin, currentpos / CHARWIDTH, currentline - 1); } #endif glk_request_char_event(currentwin); while (!gotchar) { /* Grab an event */ glk_select(&ev); switch (ev.type) { case evtype_CharInput: /* (Will always be mainwin, but anyway) */ if (ev.window == currentwin) { gotchar = true; } break; default: break; } } /* Convert Glk special keycodes: */ switch (ev.val1) { case keycode_Left: ev.val1 = 8; break; case keycode_Right: ev.val1 = 21; break; case keycode_Up: ev.val1 = 11; break; case keycode_Down: ev.val1 = 10; break; case keycode_Return: ev.val1 = 13; break; case keycode_Escape: ev.val1 = 27; break; } #if defined (NO_KEYPRESS_CURSOR) if (currentwin != mainwin) { glk_window_move_cursor(currentwin, currentpos / CHARWIDTH, currentline - 1); hugo_print(" "); glk_window_move_cursor(currentwin, currentpos / CHARWIDTH, currentline - 1); } #endif return ev.val1; } int Hugo::hugo_iskeywaiting() { var[system_status] = STAT_UNAVAILABLE; return 0; } int Hugo::hugo_timewait(int n) { uint32 millisecs; event_t ev; if (!glk_gestalt(gestalt_Timer, 0)) return false; if (n == 0) return true; millisecs = 1000 / n; if (millisecs == 0) millisecs = 1; // For the time being, we're going to disallow // millisecond delays in Glk (1) because there's no // point, and (2) so that we can tell we're running // under Glk. if (millisecs < 1000) return false; glk_request_timer_events(millisecs); while (1) { glk_select(&ev); if (ev.type == evtype_Timer) break; } glk_request_timer_events(0); return true; } void Hugo::hugo_clearfullscreen() { glk_window_clear(mainwin); if (secondwin) glk_window_clear(secondwin); if (auxwin) glk_window_clear(auxwin); /* See hugo_print() for the need for this */ if (currentwin == mainwin) mainwin_bgcolor = glk_bgcolor; /* Must be set: */ currentpos = 0; currentline = 1; if (!inwindow) just_cleared_screen = true; } void Hugo::hugo_clearwindow() { /* Clears the currently defined window, moving the cursor to the top-left corner of the window */ /* If the engine thinks we're in a window, but Glk was unable to comply, don't clear the window, because it's not really a window */ if (inwindow && currentwin == mainwin) return; if (currentwin == nullptr) return; glk_window_clear(currentwin); /* See hugo_print() for the need for this */ if (currentwin == mainwin) mainwin_bgcolor = glk_bgcolor; /* If we're in a fixed-font (i.e., textgrid) auxiliary window when we call for a clear, close auxwin and reset the current window to mainwin */ if (auxwin) { stream_result_t sr; glk_window_close(auxwin, &sr); auxwin = nullptr; glk_set_window(currentwin = mainwin); } /* Must be set: */ currentpos = 0; currentline = 1; if (!inwindow) just_cleared_screen = true; } void Hugo::hugo_settextmode() { charwidth = FIXEDCHARWIDTH; lineheight = FIXEDLINEHEIGHT; } void Hugo::hugo_settextwindow(int left, int top, int right, int bottom) { /* Hugo's arbitrarily positioned windows don't currently mesh with what Glk has to offer, so we have to ignore any non-Glk-ish Windows and just maintain the current parameters */ if ((top != 1 || bottom >= physical_windowbottom / FIXEDLINEHEIGHT + 1) /* Pre-v2.4 didn't support proper windowing */ && (game_version >= 24 || !inwindow)) { in_valid_window = false; /* Glk-illegal floating window; setting currentwin to nullptr will tell hugo_print() not to print in it: */ if (bottom= ' ') /* alphanumeric characters */ return CHARWIDTH; /* for non-proportional */ return 0; } int Hugo::hugo_textwidth(const char *a) const { int i, slen, len = 0; slen = (int)strlen(a); for (i = 0; i