diff --git a/xurses.c b/xurses.c index ddfe69d..83358f8 100644 --- a/xurses.c +++ b/xurses.c @@ -1,10 +1,10 @@ /* - * Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic - * - * Xurses is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. - * And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. - * It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. - */ +Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic + +Xurses is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. +And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. +It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. +*/ #ifndef XURSES_SOURCE #define XURSES_SOURCE @@ -16,25 +16,24 @@ #include #include -#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) +/* Internal constant definitions. */ + +#define CURSES_OFFSET ((int) sizeof ("\033[-;3-m-\033[0m") - 1) +#define CURSES_REVERT ((int) sizeof ("\033[H") - 1) + +/* Internal variable definitions. */ -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; -static char curses_format [CURSES_LENGTH + 1] = "\033[-;3-m-\033[0m"; - static void (* curses_action [SIGNAL_COUNT]) (void) = { 0 }; static struct termios curses_old_terminal; static struct termios curses_new_terminal; -int curses_active = 0; +/* Internal function definitions. */ static void curses_free (void) { curses_screen = deallocate (curses_screen); @@ -44,25 +43,30 @@ static void curses_free (void) { 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; -} +/* Return offset of variable 'curses_screen' according to X and Y coordinates. */ +static char * curses_screen_offset (int x, int y) { + log_in (LOG_FAILURE, x <= -1, "curses_screen_offset: X position is below the lower bound."); + log_in (LOG_FAILURE, y <= -1, "curses_screen_offset: Y position is below the lower bound."); + log_in (LOG_FAILURE, x >= curses_screen_width, "curses_screen_offset: X position is above the upper bound."); + log_in (LOG_FAILURE, y >= curses_screen_height, "curses_screen_offset: Y position is above the upper bound."); -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."); + limit (& x, 0, curses_screen_width - 1); + limit (& y, 0, curses_screen_height - 1); - return (& curses_screen [CURSES_LENGTH * (y * curses_screen_width + x) + y * CURSES_RETURN + CURSES_OFFSET]); + return (& curses_screen [CURSES_REVERT + CURSES_OFFSET * (y * curses_screen_width + x)]); } static char * curses_format_character (char character, int colour, int effect) { + static char curses_format [CURSES_OFFSET + 1] = "\033[-;3-m-\033[0m"; + 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."); + if (character_is_invisible (character) != 0) { + character = ' '; + } + curses_format [2] = (char) (effect % EFFECT_COUNT) + '0'; curses_format [5] = (char) (colour % COLOUR_COUNT) + '0'; curses_format [7] = character; @@ -76,11 +80,16 @@ static void curses_idle (void) { return; } +/* External variable definitions. */ + +int curses_active = 1; + +/* External function definitions. */ + void curses_configure (void) { struct winsize screen_dimension; char signal = 0; - char offset = 0; atexit (curses_free); @@ -103,7 +112,7 @@ void curses_configure (void) { fatal_failure (tcsetattr (STDIN_FILENO, TCSAFLUSH, & curses_new_terminal) == -1, "tcsetattr: Failed to set reverse terminal attributes."); - curses_screen = allocate (CURSES_OFFSET + CURSES_LENGTH * curses_screen_width * curses_screen_height + (curses_screen_height - 1) * CURSES_RETURN + 1); + curses_screen = allocate (CURSES_REVERT + CURSES_OFFSET * curses_screen_width * curses_screen_height + 1); for (signal = SIGNAL_NONE; signal != SIGNAL_COUNT; ++signal) { curses_unbind ((char) signal); @@ -111,30 +120,29 @@ void curses_configure (void) { terminal_clear (); - curses_screen_offset (); - - for (offset = 0; offset != curses_screen_height - 1; ++offset) { - string_copy (& curses_screen [CURSES_LENGTH * curses_screen_width * offset + CURSES_OFFSET], "\r\n"); - } - - curses_active = 1; + string_copy (& curses_screen [0], "\033[H"); } void curses_synchronize (void) { curses_signal = '\0'; - out (curses_screen, CURSES_OFFSET + CURSES_LENGTH * curses_screen_width * curses_screen_height/* + curses_screen_height * CURSES_RETURN*/); + out (curses_screen, CURSES_REVERT + CURSES_OFFSET * curses_screen_width * curses_screen_height); - in (& curses_signal, 1); + in (& curses_signal, 4); switch (curses_signal) { - case '0': curses_signal = SIGNAL_0; break; - case 'Q': curses_signal = SIGNAL_Q | SIGNAL_SHIFT; break; - case 'q': curses_signal = SIGNAL_Q; break; - default: curses_signal = SIGNAL_NONE; break; + case '\033': curses_signal = SIGNAL_ESCAPE; break; + case '0': curses_signal = SIGNAL_0; break; + case 'q': curses_signal = SIGNAL_Q; break; + case 'Q': curses_signal = SIGNAL_Q | SIGNAL_SHIFT; break; + case 'w': curses_signal = SIGNAL_W; break; + case 's': curses_signal = SIGNAL_S; break; + case 'a': curses_signal = SIGNAL_A; break; + case 'd': curses_signal = SIGNAL_D; break; + default: curses_signal = SIGNAL_NONE; break; } - if (curses_signal == curses_stop) { + if (curses_signal == SIGNAL_ESCAPE) { curses_active = 0; return; } @@ -142,14 +150,10 @@ void curses_synchronize (void) { if ((curses_signal > SIGNAL_ANY) && (curses_signal < SIGNAL_COUNT)) { curses_action [curses_signal] (); } - - curses_screen_offset (); } 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; + string_copy_limit (curses_screen_offset (x, y), curses_format_character (character, colour, effect), CURSES_OFFSET); } void curses_render_background (char character, int colour, int effect) { @@ -170,8 +174,4 @@ void curses_unbind (int signal) { curses_action [signal] = curses_idle; } -void curses_exit (int signal) { - curses_stop = signal; -} - #endif diff --git a/xurses.h b/xurses.h index 2c72383..de41632 100644 --- a/xurses.h +++ b/xurses.h @@ -1,10 +1,10 @@ /* - * Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic - * - * Xurses is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. - * And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. - * It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. - */ +Copyright (c) 2023 : Ognjen 'xolatile' Milan Robovic + +Xurses is free software! You will redistribute it or modify it under the terms of the GNU General Public License by Free Software Foundation. +And when you do redistribute it or modify it, it will use either version 3 of the License, or (at yours truly opinion) any later version. +It is distributed in the hope that it will be useful or harmful, it really depends... But no warranty what so ever, seriously. See GNU/GPLv3. +*/ #ifndef XURSES_HEADER #define XURSES_HEADER