355 lines
6.7 KiB
C
355 lines
6.7 KiB
C
#include "joey.h"
|
|
#include "ansiterm.h"
|
|
#include "ztypes.h"
|
|
|
|
|
|
#ifdef JOEY_IIGS
|
|
segment "joeyio";
|
|
#endif
|
|
|
|
|
|
#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;
|
|
}
|
|
}
|