Files
2026-02-02 04:50:13 +01:00

238 lines
6.0 KiB
C++

/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "glk/alan3/glkio.h"
#include "glk/alan3/acode.h"
#include "glk/alan3/current.h"
#include "glk/alan3/instance.h"
#include "glk/alan3/options.h"
#include "glk/alan3/output.h"
#include "common/config-manager.h"
namespace Glk {
namespace Alan3 {
GlkIO *g_io;
GlkIO::GlkIO(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
glkMainWin(nullptr), glkStatusWin(nullptr), onStatusLine(false), _saveSlot(-1),
_soundChannel(nullptr) {
g_io = this;
}
bool GlkIO::initialize() {
// first, open a window for error output
glkMainWin = glk_window_open(nullptr, 0, 0, wintype_TextBuffer, 0);
if (glkMainWin == nullptr)
return false;
glk_stylehint_set(wintype_TextGrid, style_User1, stylehint_ReverseColor, 1);
glkStatusWin = glk_window_open(glkMainWin, winmethod_Above |
winmethod_Fixed, 1, wintype_TextGrid, 0);
glk_set_window(glkMainWin);
// Check for a save being loaded directly from the launcher
_saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
return true;
}
void GlkIO::print(const char *fmt, ...) {
// If there's a savegame being loaded from the launcher, ignore any text out
if (_saveSlot != -1)
return;
va_list argp;
va_start(argp, fmt);
Common::String str = Common::String::vformat(fmt, argp);
va_end(argp);
if (glkMainWin) {
glk_put_string(str.c_str());
} else {
// assume stdio is available in this case only
warning("%s", str.c_str());
}
}
void GlkIO::showImage(int image, int align) {
uint ecode;
if (_saveSlot != -1)
return;
if ((glk_gestalt(gestalt_Graphics, 0) == 1) &&
(glk_gestalt(gestalt_DrawImage, wintype_TextBuffer) == 1)) {
glk_window_flow_break(glkMainWin);
printf("\n");
ecode = glk_image_draw(glkMainWin, image, imagealign_MarginLeft, 0);
(void)ecode;
}
}
void GlkIO::playSound(int sound) {
if (_saveSlot != -1)
return;
#ifdef GLK_MODULE_SOUND
if (glk_gestalt(gestalt_Sound, 0) == 1) {
if (_soundChannel == nullptr)
_soundChannel = glk_schannel_create(0);
if (_soundChannel) {
glk_schannel_stop(_soundChannel);
(void)glk_schannel_play(_soundChannel, sound);
}
}
#endif
}
void GlkIO::setStyle(int style) {
switch (style) {
case NORMAL_STYLE:
glk_set_style(style_Normal);
break;
case EMPHASIZED_STYLE:
glk_set_style(style_Emphasized);
break;
case PREFORMATTED_STYLE:
glk_set_style(style_Preformatted);
break;
case ALERT_STYLE:
glk_set_style(style_Alert);
break;
case QUOTE_STYLE:
glk_set_style(style_BlockQuote);
break;
default:
break;
}
}
void GlkIO::statusLine(CONTEXT) {
uint glkWidth;
char line[100];
int pcol = col;
if (!statusLineOption || _saveSlot != -1 || glkStatusWin == nullptr)
return;
glk_set_window(glkStatusWin);
glk_window_clear(glkStatusWin);
glk_window_get_size(glkStatusWin, &glkWidth, nullptr);
onStatusLine = TRUE;
col = 1;
glk_window_move_cursor(glkStatusWin, 1, 0);
CALL1(sayInstance, where(HERO, /*TRUE*/ TRANSITIVE))
// TODO Add status message1 & 2 as author customizable messages
if (header->maximumScore > 0)
Common::sprintf_s(line, "Score %d(%d)/%d moves", current.score, (int)header->maximumScore, current.tick);
else
Common::sprintf_s(line, "%d moves", current.tick);
glk_window_move_cursor(glkStatusWin, glkWidth - strlen(line) - 1, 0);
glk_put_string(line);
needSpace = FALSE;
col = pcol;
onStatusLine = FALSE;
glk_set_window(glkMainWin);
}
/*======================================================================
readline()
Read a line from the user, with history and editing
*/
/* TODO - length of user buffer should be used */
bool GlkIO::readLine(CONTEXT, char *buffer, size_t maxLen) {
event_t event;
static bool readingCommands = FALSE;
static frefid_t commandFileRef;
static strid_t commandFile;
if (_saveSlot != -1) {
// Return a "restore" command
forcePrint("> ");
forcePrint("restore\n");
Common::strcpy_s(buffer, maxLen, "restore");
} else if (readingCommands) {
if (glk_get_line_stream(commandFile, buffer, maxLen) == 0) {
glk_stream_close(commandFile, nullptr);
readingCommands = FALSE;
} else {
glk_set_style(style_Input);
printf(buffer);
glk_set_style(style_Normal);
}
} else {
glk_request_line_event(glkMainWin, buffer, maxLen, 0);
do {
glk_select(&event);
if (shouldQuit())
LONG_JUMP0
switch (event.type) {
case evtype_Arrange:
R0CALL0(g_io->statusLine)
break;
default:
break;
}
} while (event.type != evtype_LineInput);
if (buffer[0] == '@') {
buffer[event.val1] = 0;
commandFileRef = glk_fileref_create_by_name(fileusage_InputRecord + fileusage_TextMode, &buffer[1], 0);
commandFile = glk_stream_open_file(commandFileRef, filemode_Read, 0);
if (commandFile != nullptr)
if (glk_get_line_stream(commandFile, buffer, maxLen) != 0) {
readingCommands = TRUE;
glk_set_style(style_Input);
printf(buffer);
glk_set_style(style_Normal);
}
} else
buffer[event.val1] = 0;
}
return TRUE;
}
Common::Error GlkIO::loadGame() {
if (_saveSlot != -1) {
int saveSlot = _saveSlot;
_saveSlot = -1;
return loadGameState(saveSlot);
} else {
return GlkAPI::loadGame();
}
}
} // End of namespace Alan3
} // End of namespace Glk