|
|
@@ -11,27 +11,79 @@ |
|
|
|
|
|
|
|
#include <xolatile/xurses.h> |
|
|
|
|
|
|
|
int curses_active = 1; |
|
|
|
int curses_cursor = 0; |
|
|
|
char curses_signal = '\0'; |
|
|
|
int curses_screen_width = 0; |
|
|
|
int curses_screen_height = 0; |
|
|
|
int curses_screen_size = 0; |
|
|
|
char * curses_screen = NULL; |
|
|
|
#include <termios.h> |
|
|
|
#include <sys/ioctl.h> |
|
|
|
#include <sys/types.h> |
|
|
|
#include <sys/stat.h> |
|
|
|
|
|
|
|
char curses_format [CURSES_LENGTH + 1] = "\033[-;3-m-\033[0m"; |
|
|
|
#define CURSES_LENGTH ((int) sizeof ("\033[-;3-m-\033[0m") - 1) |
|
|
|
#define CURSES_OFFSET ((int) sizeof ("\033[H") - 1) |
|
|
|
#define CURSES_RETURN ((int) sizeof ("\r\n") - 1) |
|
|
|
|
|
|
|
void (* curses_action [SIGNAL_COUNT]) (void) = { 0 }; |
|
|
|
static int curses_stop = SIGNAL_Q; |
|
|
|
static int curses_signal = SIGNAL_NONE; |
|
|
|
static int curses_screen_width = 0; |
|
|
|
static int curses_screen_height = 0; |
|
|
|
static int curses_screen_size = 0; |
|
|
|
static char * curses_screen = NULL; |
|
|
|
|
|
|
|
struct termios curses_old_terminal; |
|
|
|
struct termios curses_new_terminal; |
|
|
|
static char curses_format [CURSES_LENGTH + 1] = "\033[-;3-m-\033[0m"; |
|
|
|
|
|
|
|
void curses_initialize (void) { |
|
|
|
static void (* curses_action [SIGNAL_COUNT]) (void) = { 0 }; |
|
|
|
|
|
|
|
static struct termios curses_old_terminal; |
|
|
|
static struct termios curses_new_terminal; |
|
|
|
|
|
|
|
int curses_active = 0; |
|
|
|
|
|
|
|
static void curses_free (void) { |
|
|
|
curses_screen = deallocate (curses_screen); |
|
|
|
|
|
|
|
terminal_clear (); |
|
|
|
|
|
|
|
fatal_failure (tcsetattr (STDIN_FILENO, TCSAFLUSH, & curses_old_terminal) == -1, "tcsetattr: Failed to set default terminal attributes."); |
|
|
|
} |
|
|
|
|
|
|
|
static void curses_screen_offset (void) { |
|
|
|
string_copy (& curses_screen [0], "\033[H"); |
|
|
|
curses_screen_size = CURSES_OFFSET; |
|
|
|
} |
|
|
|
|
|
|
|
static char * curses_screen_position (int x, int y) { |
|
|
|
fatal_failure (x <= -1, "curses_screen_position: X position is below the lower bound."); |
|
|
|
fatal_failure (y <= -1, "curses_screen_position: Y position is below the lower bound."); |
|
|
|
fatal_failure (x >= curses_screen_width, "curses_screen_position: X position is above the upper bound."); |
|
|
|
fatal_failure (y >= curses_screen_height, "curses_screen_position: Y position is above the upper bound."); |
|
|
|
|
|
|
|
return (& curses_screen [CURSES_LENGTH * (y * curses_screen_width + x) + y * CURSES_RETURN + CURSES_OFFSET]); |
|
|
|
} |
|
|
|
|
|
|
|
static char * curses_format_character (char character, int colour, int effect) { |
|
|
|
log_in (LOG_WARNING, character_is_invisible (character), "curses_format_character: Can not format invisible characters."); |
|
|
|
log_in (LOG_FAILURE, colour >= COLOUR_COUNT, "curses_format_character: Colour is invalid enumeration value."); |
|
|
|
log_in (LOG_FAILURE, effect >= EFFECT_COUNT, "curses_format_character: Effect is invalid enumeration value."); |
|
|
|
|
|
|
|
curses_format [2] = (char) (effect % EFFECT_COUNT) + '0'; |
|
|
|
curses_format [5] = (char) (colour % COLOUR_COUNT) + '0'; |
|
|
|
curses_format [7] = character; |
|
|
|
|
|
|
|
log_out ("curses.log"); |
|
|
|
|
|
|
|
return (curses_format); |
|
|
|
} |
|
|
|
|
|
|
|
static void curses_idle (void) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
void curses_configure (void) { |
|
|
|
struct winsize screen_dimension; |
|
|
|
|
|
|
|
char signal = 0; |
|
|
|
char offset = 0; |
|
|
|
|
|
|
|
atexit (curses_free); |
|
|
|
|
|
|
|
fatal_failure (ioctl (STDOUT_FILENO, TIOCGWINSZ, & screen_dimension) == -1, "ioctl: Failed to get terminal dimensions."); |
|
|
|
|
|
|
|
curses_screen_width = (int) screen_dimension.ws_col; |
|
|
@@ -64,21 +116,13 @@ void curses_initialize (void) { |
|
|
|
for (offset = 0; offset != curses_screen_height - 1; ++offset) { |
|
|
|
string_copy (& curses_screen [CURSES_LENGTH * curses_screen_width * offset + CURSES_OFFSET], "\r\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void curses_deinitialize (void) { |
|
|
|
curses_screen = deallocate (curses_screen); |
|
|
|
|
|
|
|
terminal_clear (); |
|
|
|
|
|
|
|
fatal_failure (tcsetattr (STDIN_FILENO, TCSAFLUSH, & curses_old_terminal) == -1, "tcsetattr: Failed to set default terminal attributes."); |
|
|
|
curses_active = 1; |
|
|
|
} |
|
|
|
|
|
|
|
void curses_synchronize (void) { |
|
|
|
curses_signal = '\0'; |
|
|
|
/* |
|
|
|
out (curses_screen, curses_screen_size); |
|
|
|
*/ |
|
|
|
|
|
|
|
out (curses_screen, CURSES_OFFSET + CURSES_LENGTH * curses_screen_width * curses_screen_height/* + curses_screen_height * CURSES_RETURN*/); |
|
|
|
|
|
|
|
in (& curses_signal, 1); |
|
|
@@ -90,6 +134,11 @@ void curses_synchronize (void) { |
|
|
|
default: curses_signal = SIGNAL_NONE; break; |
|
|
|
} |
|
|
|
|
|
|
|
if (curses_signal == curses_stop) { |
|
|
|
curses_active = 0; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if ((curses_signal > SIGNAL_ANY) && (curses_signal < SIGNAL_COUNT)) { |
|
|
|
curses_action [curses_signal] (); |
|
|
|
} |
|
|
@@ -97,92 +146,18 @@ void curses_synchronize (void) { |
|
|
|
curses_screen_offset (); |
|
|
|
} |
|
|
|
|
|
|
|
void curses_configure (void) { |
|
|
|
atexit (curses_deinitialize); |
|
|
|
|
|
|
|
curses_initialize (); |
|
|
|
} |
|
|
|
|
|
|
|
void curses_screen_offset (void) { |
|
|
|
string_copy (& curses_screen [0], "\033[H"); |
|
|
|
curses_screen_size = CURSES_OFFSET; |
|
|
|
} |
|
|
|
|
|
|
|
char * curses_screen_position (int x, int y) { |
|
|
|
fatal_failure (x <= -1, "curses_screen_position: X position is below the lower bound."); |
|
|
|
fatal_failure (y <= -1, "curses_screen_position: Y position is below the lower bound."); |
|
|
|
fatal_failure (x >= curses_screen_width, "curses_screen_position: X position is above the upper bound."); |
|
|
|
fatal_failure (y >= curses_screen_height, "curses_screen_position: Y position is above the upper bound."); |
|
|
|
|
|
|
|
return (& curses_screen [CURSES_LENGTH * (y * curses_screen_width + x) + y * CURSES_RETURN + CURSES_OFFSET]); |
|
|
|
} |
|
|
|
|
|
|
|
char * curses_format_character (char character, int colour, int effect) { |
|
|
|
log_in (LOG_WARNING, character_is_invisible (character), "curses_format_character: Can not format invisible characters."); |
|
|
|
log_in (LOG_FAILURE, colour >= COLOUR_COUNT, "curses_format_character: Colour is invalid enumeration value."); |
|
|
|
log_in (LOG_FAILURE, effect >= EFFECT_COUNT, "curses_format_character: Effect is invalid enumeration value."); |
|
|
|
|
|
|
|
curses_format [2] = (char) (effect % EFFECT_COUNT) + '0'; |
|
|
|
curses_format [5] = (char) (colour % COLOUR_COUNT) + '0'; |
|
|
|
curses_format [7] = character; |
|
|
|
|
|
|
|
log_out ("curses.log"); |
|
|
|
|
|
|
|
return (curses_format); |
|
|
|
} |
|
|
|
|
|
|
|
void curses_output_character (char character, int colour, int effect) { |
|
|
|
out (curses_format_character (character, colour, effect), CURSES_LENGTH); |
|
|
|
} |
|
|
|
|
|
|
|
void curses_render_character (char character, int x, int y, int colour, int effect) { |
|
|
|
void curses_render_character (char character, int colour, int effect, int x, int y) { |
|
|
|
string_copy (curses_screen_position (x, y), curses_format_character (character, colour, effect)); |
|
|
|
|
|
|
|
curses_screen_size += CURSES_LENGTH; |
|
|
|
} |
|
|
|
/* |
|
|
|
void curses_output_string (char * string, int colour, int effect) { |
|
|
|
char format [8] = "\033[ ;3 m"; |
|
|
|
|
|
|
|
format [2] = (char) effect + '0'; |
|
|
|
format [5] = (char) colour + '0'; |
|
|
|
|
|
|
|
string_copy_limit (& curses_screen [curses_screen_size], format, 7); |
|
|
|
string_copy_limit (& curses_screen [curses_screen_size], string, string_length (string)); |
|
|
|
string_copy_limit (& curses_screen [curses_screen_size], "\033[0m", 4); |
|
|
|
|
|
|
|
curses_screen_size += 7 + string_length (string) + 4; |
|
|
|
} |
|
|
|
|
|
|
|
void curses_render_string (char * string, int colour, int effect, int x, int y) { |
|
|
|
int offset = 0; |
|
|
|
int length = string_length (string); |
|
|
|
|
|
|
|
for (offset = 0; offset != length; (++offset, ++x)) { |
|
|
|
curses_render_character (string [offset], colour, effect, x, y); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void curses_append_cursor (int cursor_x, int cursor_y) { |
|
|
|
char format [11] = "\033[000;000H"; |
|
|
|
void curses_render_background (char character, int colour, int effect) { |
|
|
|
int x, y; |
|
|
|
|
|
|
|
format [4] = (char) (cursor_y / 1) % 10 + '0'; |
|
|
|
format [3] = (char) (cursor_y / 10) % 10 + '0'; |
|
|
|
format [2] = (char) (cursor_y / 100) % 10 + '0'; |
|
|
|
format [8] = (char) (cursor_x / 1) % 10 + '0'; |
|
|
|
format [7] = (char) (cursor_x / 10) % 10 + '0'; |
|
|
|
format [6] = (char) (cursor_x / 100) % 10 + '0'; |
|
|
|
|
|
|
|
string_copy_limit (& curses_screen [curses_screen_size], format, 10); |
|
|
|
curses_screen_size += 10; |
|
|
|
} |
|
|
|
*/ |
|
|
|
void curses_blank (void) { |
|
|
|
int i, j; |
|
|
|
|
|
|
|
for (i = 0; i != curses_screen_height; ++i) { |
|
|
|
for (j = 0; j != curses_screen_width; ++j) { |
|
|
|
curses_render_character (' ', EFFECT_NORMAL, COLOUR_WHITE, j, i); |
|
|
|
for (y = 0; y != curses_screen_height; ++y) { |
|
|
|
for (x = 0; x != curses_screen_width; ++x) { |
|
|
|
curses_render_character (character, colour, effect, x, y); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@@ -195,12 +170,8 @@ void curses_unbind (int signal) { |
|
|
|
curses_action [signal] = curses_idle; |
|
|
|
} |
|
|
|
|
|
|
|
void curses_idle (void) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
void curses_exit (void) { |
|
|
|
curses_active = 0; |
|
|
|
void curses_exit (int signal) { |
|
|
|
curses_stop = signal; |
|
|
|
} |
|
|
|
|
|
|
|
#endif |