ifengine/joeyio.c
2018-09-10 20:22:34 -05:00

350 lines
6.7 KiB
C

#include "joey.h"
#include "ansiterm.h"
#include "ztypes.h"
#define DISPLAY_MIXED_SIZE 5
#define COMMAND_BUFFER_SIZE 32
typedef enum {
DISPLAY_MODE_TEXT = 0,
DISPLAY_MODE_GRAPHICS,
DISPLAY_MODE_MIXED,
DISPLAY_MODE_LAST
} DModeT;
static jlVecT *_vectorImage = NULL;
static jlStaT *_graphicsPage = NULL;
static jlSoundT *_soundEffect = NULL;
static DModeT _displayMode = DISPLAY_MODE_TEXT;
static byte _bufferCount = 0;
static char _buffer[COMMAND_BUFFER_SIZE];
static bool _inCommand = false;
static byte _cursorIndex = 0;
static byte _cursorSize = 9;
static unsigned int _cursorTime = 0;
static byte _cursor[] = { 32, 176, 177, 178, 219, 178, 177, 176, 32 };
void set_next_display_mode(void);
void clear_line(void) {
termPrint("\33[K");
}
void clear_screen(void) {
termClearScreen();
termMoveCursor(1, (byte)screen_rows);
jlDisplayPresent();
}
void clear_status_window(void) {
int i;
int row;
int col;
get_cursor_position(&row, &col);
for (i=status_size; i; i--) {
move_cursor(i, 1);
clear_line();
}
move_cursor(row, col);
}
void clear_text_window(void) {
int i;
int row;
int col;
get_cursor_position(&row, &col);
for (i=status_size + 1; i<=screen_rows; i++) {
move_cursor(i, 1);
clear_line();
}
move_cursor(row, col);
}
void create_status_window(void) {
printf("Create Status Window\n");
}
void delete_status_window(void) {
printf("Delete Status Window\n");
}
void display_char(int c) {
char command;
char *token;
int x;
int y;
// This also handles processing of embedded media commands:
// {I name x y} - Display Image "name" @ x, y
// {M name} - Play Music "name"
// {S name} - Play Sound "name"
// {Q} - Quiet!
if (_inCommand) {
if ((char) c == '}') {
// Exit command mode.
if (_bufferCount > 0) {
// Did we get a command we understand?
command = (char)toupper(_buffer[0]);
_buffer[_bufferCount] = 0;
(void)strtok(_buffer, " ");
switch (command) {
case 'I':
token = strtok(NULL, " ");
if (jlVecLoad(_vectorImage, token)) {
x = y = 0;
token = strtok(NULL, " ");
if (token != NULL) {
x = atoi(token);
token = strtok(NULL, " ");
if (token != NULL) {
y = atoi(token);
}
}
// Put user into GRAPHICS mode if they aren't.
_displayMode = DISPLAY_MODE_GRAPHICS - 1;
set_next_display_mode();
// Render the image.
jlVecDisplay(_vectorImage, x, y);
// Save it to the graphics page.
jlStaCreate(_graphicsPage);
}
break;
case 'M':
token = strtok(NULL, " ");
jlSoundMusicPlay(token);
break;
case 'S':
token = strtok(NULL, " ");
if (jlSoundLoad(_soundEffect, token)) {
jlSoundPlay(_soundEffect);
}
break;
case 'Q':
jlSoundMusicStop();
break;
}
}
// Exit command mode
_bufferCount = 0;
_inCommand = false;
} else {
if (_bufferCount < COMMAND_BUFFER_SIZE - 1) {
// Add character to command buffer.
_buffer[_bufferCount++] = (char)c;
} else {
// Overflowed buffer - exit command mode
_bufferCount = 0;
_inCommand = false;
}
}
} else {
if ((char)c == '{') {
// Switch to embedded command mode.
_inCommand = true;
} else {
// Display game text.
termPrintChar((char)c);
}
}
}
void get_cursor_position(int *row, int *col) {
byte x;
byte y;
termGetCursor(&x, &y);
*col = (int)x;
*row = (int)y;
}
void initialize_screen(void) {
// Also handled in main
// Create initial empty graphics image.
jlDrawColor(0);
jlDrawClear();
jlDrawColor(15);
jlDisplayPresent();
jlStaCreate(_graphicsPage);
}
int input_character(int timeout) {
char k = 0;
(void)timeout; // In 1/10ths of a second
if (!jlKeyPressed()) {
while (!jlKeyPressed() && !jlUtilMustExit()) {
// Animate cursor
if (_cursorTime != jlUtilTimer()) {
display_char(_cursor[_cursorIndex++]);
display_char(8);
if (_cursorIndex >= _cursorSize) {
_cursorIndex = 0;
}
_cursorTime = jlUtilTimer();
}
}
display_char(32);
display_char(8);
}
while (jlKeyPressed() && !jlUtilMustExit()) {
// Wait for key to be released
}
k = jlKeyRead();
if (jlUtilMustExit() && (interpreter_state == RUN)) {
interpreter_state = STOP;
}
return (int)k;
}
int input_line(int buflen, char *buffer, int timeout, int *read_size) {
int c = 0;
int curr_char_pos = 0;
(void)timeout;
while (!jlUtilMustExit()) {
c = input_character(0);
if (c > 0) {
if (c == 8) {
// Backspace
if (*read_size == 0) {
//***TODO*** Flash border or ding or something
} else {
--*read_size;
--curr_char_pos;
display_char(8);
display_char(32);
display_char(8);
}
} else {
// Normal Key
if (*read_size == (buflen - 1)) {
//***TODO*** Flash border or ding or something
} else {
if (c == 13) {
if (curr_char_pos == 0) {
set_next_display_mode();
} else {
scroll_line();
return c;
}
} else {
buffer[curr_char_pos++] = (char)c;
if (*read_size < curr_char_pos) {
*read_size = curr_char_pos;
}
display_char(c);
}
}
}
}
}
return c;
}
void move_cursor(int row, int col) {
termMoveCursor((byte)col, (byte)row);
}
void reset_screen(void) {
// Also handled in main
jlStaFree(_graphicsPage);
jlVecFree(_vectorImage);
jlSoundFree(_soundEffect);
}
void restart_screen(void) {
// I don't think we need this.
}
void restore_cursor_position(void) {
termRestoreCursor();
}
void save_cursor_position(void) {
termSaveCursor();
}
void scroll_line(void) {
//***TODO*** Should really not clobber the status window.
termPrintChar(13);
termPrintChar(10);
}
void select_status_window(void) {
save_cursor_position();
}
void select_text_window(void) {
restore_cursor_position();
}
void set_attribute(int attribute) {
if (attribute == NORMAL) {
termPrint("\33[0m");
}
if (attribute & REVERSE) {
termPrint("\33[7m");
}
}
void set_next_display_mode(void) {
_displayMode++;
if (_displayMode >= DISPLAY_MODE_LAST) {
_displayMode = DISPLAY_MODE_TEXT;
}
switch (_displayMode) {
case DISPLAY_MODE_TEXT:
printf("Terminal now TEXT\n");
termHideTopLines(0);
termRepaint();
break;
case DISPLAY_MODE_GRAPHICS:
printf("Terminal now GRAPHICS\n");
termHideTopLines((byte)screen_rows);
jlStaDisplay(_graphicsPage);
break;
case DISPLAY_MODE_MIXED:
printf("Terminal now MIXED\n");
termHideTopLines((byte)screen_rows - DISPLAY_MIXED_SIZE);
jlStaDisplay(_graphicsPage);
termRepaint();
break;
case DISPLAY_MODE_LAST:
// Won't happen. Silences a warning.
break;
}
}