Another major revision...

This commit is contained in:
xolatile 2024-09-09 19:20:05 -04:00
parent b49c7ffd60
commit 61d4aa356e
9 changed files with 255 additions and 317 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
xurses.o

View File

@ -1,7 +0,0 @@
#!/bin/bash
set -xe
gcc -g -ansi -Wall -Wextra -Wpedantic -Werror -c -o xurses.o xurses.c
exit

View File

@ -1,4 +1,4 @@
#include <xolatile/xurses.c>
#include <xolatile/xurses.h>
int main (void) {
xurses_configure ();

View File

@ -1,4 +1,4 @@
#include <xolatile/xurses.c>
#include <xolatile/xurses.h>
int main (void) {
xurses_configure ();

View File

@ -1,4 +1,4 @@
#include <xolatile/xurses.c>
#include <xolatile/xurses.h>
static int player_x = 1;
static int player_y = 1;

View File

@ -1,24 +0,0 @@
#include <xolatile/xurses.c>
int main (void) {
xurses_configure ();
while (xurses_active == true) {
int x, y;
for (y = 0; y < xurses_screen_height; ++y) {
for (x = 0; x < xurses_screen_width; ++x) {
xurses_render_character ('.', randomize (colour_green, colour_white), effect_bold, x, y);
}
}
xurses_render_number (xurses_screen_width, colour_red, effect_bold, 0, 0);
xurses_render_number (xurses_screen_height, colour_red, effect_bold, 0, 1);
xurses_render_character ('#', randomize (colour_grey, colour_white), effect_bold, -1, 10000);
xurses_synchronize ();
}
return (log_success);
}

View File

@ -5,7 +5,5 @@ set -xe
mkdir -p /usr/local/include/xolatile
cp xurses.h /usr/local/include/xolatile/xurses.h
cp xurses.c /usr/local/include/xolatile/xurses.c
cp xurses.o /usr/local/include/xolatile/xurses.o
exit

262
xurses.c
View File

@ -1,262 +0,0 @@
#ifndef xurses_source
#define xurses_source
#include <xolatile/xtandard.c>
#include <xolatile/xurses.h>
#include <termios.h>
#include <sys/ioctl.h>
#define xurses_format_length ((int) sizeof ("\033[-;3-m-\033[0m") - 1)
#define xurses_revert_length ((int) sizeof ("\033[H") - 1)
#define xurses_cursor_length ((int) sizeof ("\033[---;---H") - 1)
static char xurses_format [xurses_format_length + 1] = "\033[-;3-m-\033[0m";
static char xurses_cursor [xurses_cursor_length + 1] = "\033[---;---H";
static char * xurses_screen = null;
static void (* xurses_action [signal_count]) (void) = { null };
static struct termios xurses_old_terminal;
static struct termios xurses_new_terminal;
static void xurses (void) {
xurses_screen = deallocate (xurses_screen);
terminal_clear ();
fatal_failure (tcsetattr (STDIN_FILENO, TCSAFLUSH, & xurses_old_terminal) == -1, "tcsetattr: Failed to set default attributes.");
}
static char * xurses_screen_offset (int x, int y) {
limit (& x, 0, xurses_screen_width - 1);
limit (& y, 0, xurses_screen_height - 1);
return (& xurses_screen [xurses_revert_length + xurses_format_length * (y * xurses_screen_width + x) + 2 * y]);
}
static int xurses_screen_length (void) {
int constant, variable, new_line;
constant = xurses_revert_length + xurses_cursor_length + 1;
variable = xurses_format_length * xurses_screen_height * xurses_screen_width;
new_line = xurses_screen_height - 1;
return (constant + variable + 2 * new_line);
}
static void xurses_screen_dimensions (void) {
int index, old_width, old_height;
struct winsize screen_dimension;
old_width = xurses_screen_width;
old_height = xurses_screen_height;
fatal_failure (ioctl (STDOUT_FILENO, TIOCGWINSZ, & screen_dimension) == -1, "ioctl: Failed to get dimensions.");
xurses_screen_width = (int) screen_dimension.ws_col;
xurses_screen_height = (int) screen_dimension.ws_row;
if ((old_width != xurses_screen_width) || (old_height != xurses_screen_height)) {
xurses_screen = deallocate (xurses_screen);
xurses_screen = allocate (xurses_screen_length ());
}
string_copy (& xurses_screen [0], "\033[H");
for (index = 0; index < xurses_screen_height - 1; ++index) {
string_copy (& xurses_screen [xurses_revert_length + index * xurses_format_length * xurses_screen_width], "\r\n");
}
}
static char * xurses_format_character (char character, int colour, int effect) {
if (character_is_invisible (character) != 0) {
character = ' ';
}
colour %= colour_count;
effect %= effect_count;
switch (effect) {
case effect_normal: effect = 0; break;
case effect_bold: effect = 1; break;
case effect_italic: effect = 3; break;
case effect_underline: effect = 4; break;
case effect_blink: effect = 5; break;
case effect_reverse: effect = 7; break;
default: effect = 0; break;
}
xurses_format [2] = (char) effect + '0';
xurses_format [5] = (char) colour + '0';
xurses_format [7] = character;
return (xurses_format);
}
static void xurses_idle (void) {
return;
}
static void xurses_exit (void) {
xurses_active = false;
}
int xurses_screen_width = 0;
int xurses_screen_height = 0;
int xurses_active = false;
void xurses_configure (void) {
int index;
if (xurses_active == true) {
return;
} else {
clean_up (xurses);
}
xurses_screen_dimensions ();
fatal_failure (tcgetattr (STDIN_FILENO, & xurses_old_terminal) == -1, "tcgetattr: Failed to get default attributes.");
xurses_new_terminal = xurses_old_terminal;
xurses_new_terminal.c_cc [VMIN] = (unsigned char) 0;
xurses_new_terminal.c_cc [VTIME] = (unsigned char) 1;
xurses_new_terminal.c_iflag &= (unsigned int) ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
xurses_new_terminal.c_oflag &= (unsigned int) ~(OPOST);
xurses_new_terminal.c_cflag |= (unsigned int) (CS8);
xurses_new_terminal.c_lflag &= (unsigned int) ~(ECHO | ICANON | IEXTEN | ISIG);
fatal_failure (tcsetattr (STDIN_FILENO, TCSAFLUSH, & xurses_new_terminal) == -1, "tcsetattr: Failed to set reverse attributes.");
for (index = 0; index < signal_count; ++index) {
xurses_bind (index, xurses_idle);
}
xurses_bind (signal_escape, xurses_exit);
terminal_clear ();
xurses_active = true;
}
void xurses_synchronize (void) {
char character = '\0';
int signal = signal_none;
in (& character, (int) sizeof (character));
out (xurses_screen, xurses_screen_length ());
xurses_screen_dimensions ();
if (character == '\033') {
signal = signal_escape;
} else if (character_is_digit (character) == true) {
signal = signal_0 + (int) character - '0';
} else if (character_is_lowercase (character) == true) {
signal = signal_a + (int) character - 'a';
} else if (character_is_uppercase (character) == true) {
signal = signal_a + (int) character - 'A';
} else {
signal = signal_none;
}
xurses_action [signal % signal_count] ();
}
void xurses_bind (int signal, void (* action) (void)) {
xurses_action [signal % signal_count] = action;
}
void xurses_unbind (int signal) {
xurses_action [signal % signal_count] = xurses_idle;
}
void xurses_render_cursor (int x, int y) { /* BROKE IT INTENTIONALLY */
string_copy_limit (xurses_cursor + 2, string_realign (number_to_string (y % 1000 + 1), 3, '0'), 3);
string_copy_limit (xurses_cursor + 6, string_realign (number_to_string (x % 1000 + 1), 3, '0'), 3);
string_copy_limit (& xurses_screen [xurses_screen_length () - xurses_cursor_length - 1], xurses_cursor, xurses_cursor_length);
}
void xurses_render_character (char character, int colour, int effect, int x, int y) {
limit (& x, 0, xurses_screen_width - 1);
limit (& y, 0, xurses_screen_height - 1);
string_copy_limit (xurses_screen_offset (x, y), xurses_format_character (character, colour, effect), xurses_format_length);
}
void xurses_render_string (char * string, int colour, int effect, int x, int y) {
int index;
for (index = 0; string [index] != '\0'; ++index) {
xurses_render_character (string [index], colour, effect, x + index, y);
}
}
void xurses_render_number (int number, int colour, int effect, int x, int y) {
xurses_render_string (number_to_string (number), colour, effect, x, y);
}
void xurses_render_string_crop (char * string, int colour, int effect, int x, int y, int crop) {
int index;
for (index = 0; (string [index] != '\0') && (index < crop); ++index) {
xurses_render_character (string [index], colour, effect, x + index, y);
}
}
void xurses_render_number_crop (int number, int colour, int effect, int x, int y, int crop) {
xurses_render_string_crop (number_to_string (number), colour, effect, x, y, crop);
}
void xurses_render_vertical_line (char character, int colour, int effect, int x, int y, int height) {
int offset;
for (offset = 0; offset != height; ++offset) {
xurses_render_character (character, colour, effect, x, y + offset);
}
}
void xurses_render_horizontal_line (char character, int colour, int effect, int x, int y, int width) {
int offset;
for (offset = 0; offset != width; ++offset) {
xurses_render_character (character, colour, effect, x + offset, y);
}
}
void xurses_render_rectangle_line (char character, int colour, int effect, int x, int y, int width, int height) {
xurses_render_vertical_line (character, colour, effect, x + 0, y + 0, height + 0);
xurses_render_vertical_line (character, colour, effect, x + width - 1, y + 0, height + 0);
xurses_render_horizontal_line (character, colour, effect, x + 1, y + 0, width - 1);
xurses_render_horizontal_line (character, colour, effect, x + 1, y + height - 1, width - 1);
}
void xurses_render_rectangle_fill (char character, int colour, int effect, int x, int y, int width, int height) {
int offset_x, offset_y;
for (offset_y = 0; offset_y != height; ++offset_y) {
for (offset_x = 0; offset_x != width; ++offset_x) {
xurses_render_character (character, colour, effect, x + offset_x, y + offset_y);
}
}
}
void xurses_render_background (char character, int colour, int effect) {
int x, y;
for (y = 0; y != xurses_screen_height; ++y) {
for (x = 0; x != xurses_screen_width; ++x) {
xurses_render_character (character, colour, effect, x, y);
}
}
}
#endif

270
xurses.h
View File

@ -1,27 +1,261 @@
#ifndef xurses_header
#define xurses_header
extern int xurses_active;
extern int xurses_screen_width;
extern int xurses_screen_height;
#include <xolatile/xtandard.h>
extern void xurses_configure (void);
extern void xurses_synchronize (void);
#include <termios.h>
#include <sys/ioctl.h>
extern void xurses_bind (int signal, void (* action) (void));
extern void xurses_unbind (int signal);
#define xurses_format_length ((int) sizeof ("\033[-;3-m-\033[0m") - 1)
#define xurses_revert_length ((int) sizeof ("\033[H") - 1)
#define xurses_cursor_length ((int) sizeof ("\033[---;---H") - 1)
extern void xurses_render_cursor (int x, int y);
static char xurses_format [xurses_format_length + 1] = "\033[-;3-m-\033[0m";
static char xurses_cursor [xurses_cursor_length + 1] = "\033[---;---H";
extern void xurses_render_character (char character, int colour, int effect, int x, int y);
extern void xurses_render_string (char * string, int colour, int effect, int x, int y);
extern void xurses_render_number (int number, int colour, int effect, int x, int y);
extern void xurses_render_string_crop (char * string, int colour, int effect, int x, int y, int crop);
extern void xurses_render_number_crop (int number, int colour, int effect, int x, int y, int crop);
extern void xurses_render_vertical_line (char character, int colour, int effect, int x, int y, int height);
extern void xurses_render_horizontal_line (char character, int colour, int effect, int x, int y, int width);
extern void xurses_render_rectangle_line (char character, int colour, int effect, int x, int y, int width, int height);
extern void xurses_render_rectangle_fill (char character, int colour, int effect, int x, int y, int width, int height);
extern void xurses_render_background (char character, int colour, int effect);
static char * xurses_screen = null;
static void (* xurses_action [signal_count]) (void) = { null };
static struct termios xurses_old_terminal;
static struct termios xurses_new_terminal;
static int xurses_screen_width = 0;
static int xurses_screen_height = 0;
static int xurses_active = false;
static void xurses (void) {
xurses_screen = deallocate (xurses_screen);
terminal_clear ();
fatal_failure (tcsetattr (STDIN_FILENO, TCSAFLUSH, & xurses_old_terminal) == -1, "tcsetattr: Failed to set default attributes.");
}
static char * xurses_screen_offset (int x, int y) {
limit (& x, 0, xurses_screen_width - 1);
limit (& y, 0, xurses_screen_height - 1);
return (& xurses_screen [xurses_revert_length + xurses_format_length * (y * xurses_screen_width + x) + 2 * y]);
}
static int xurses_screen_length (void) {
int constant, variable, new_line;
constant = xurses_revert_length + xurses_cursor_length + 1;
variable = xurses_format_length * xurses_screen_height * xurses_screen_width;
new_line = xurses_screen_height - 1;
return (constant + variable + 2 * new_line);
}
static void xurses_screen_dimensions (void) {
int index, old_width, old_height;
struct winsize screen_dimension;
old_width = xurses_screen_width;
old_height = xurses_screen_height;
fatal_failure (ioctl (STDOUT_FILENO, TIOCGWINSZ, & screen_dimension) == -1, "ioctl: Failed to get dimensions.");
xurses_screen_width = (int) screen_dimension.ws_col;
xurses_screen_height = (int) screen_dimension.ws_row;
if ((old_width != xurses_screen_width) || (old_height != xurses_screen_height)) {
xurses_screen = deallocate (xurses_screen);
xurses_screen = allocate (xurses_screen_length ());
}
string_copy (& xurses_screen [0], "\033[H");
for (index = 0; index < xurses_screen_height - 1; ++index) {
string_copy (& xurses_screen [xurses_revert_length + index * xurses_format_length * xurses_screen_width], "\r\n");
}
}
static char * xurses_format_character (char character, int colour, int effect) {
if (character_is_invisible (character) != 0) {
character = ' ';
}
colour %= colour_count;
effect %= effect_count;
switch (effect) {
case effect_normal: effect = 0; break;
case effect_bold: effect = 1; break;
case effect_italic: effect = 3; break;
case effect_underline: effect = 4; break;
case effect_blink: effect = 5; break;
case effect_reverse: effect = 7; break;
default: effect = 0; break;
}
xurses_format [2] = (char) effect + '0';
xurses_format [5] = (char) colour + '0';
xurses_format [7] = character;
return (xurses_format);
}
static void xurses_idle (void) {
return;
}
static void xurses_exit (void) {
xurses_active = false;
}
static void xurses_bind (int signal, void (* action) (void)) {
xurses_action [signal % signal_count] = action;
}
static void xurses_unbind (int signal) {
xurses_action [signal % signal_count] = xurses_idle;
}
static void xurses_configure (void) {
int index;
if (xurses_active == true) {
return;
} else {
clean_up (xurses);
}
xurses_screen_dimensions ();
fatal_failure (tcgetattr (STDIN_FILENO, & xurses_old_terminal) == -1, "tcgetattr: Failed to get default attributes.");
xurses_new_terminal = xurses_old_terminal;
xurses_new_terminal.c_cc [VMIN] = (unsigned char) 0;
xurses_new_terminal.c_cc [VTIME] = (unsigned char) 1;
xurses_new_terminal.c_iflag &= (unsigned int) ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
xurses_new_terminal.c_oflag &= (unsigned int) ~(OPOST);
xurses_new_terminal.c_cflag |= (unsigned int) (CS8);
xurses_new_terminal.c_lflag &= (unsigned int) ~(ECHO | ICANON | IEXTEN | ISIG);
fatal_failure (tcsetattr (STDIN_FILENO, TCSAFLUSH, & xurses_new_terminal) == -1, "tcsetattr: Failed to set reverse attributes.");
for (index = 0; index < signal_count; ++index) {
xurses_bind (index, xurses_idle);
}
xurses_bind (signal_escape, xurses_exit);
terminal_clear ();
xurses_active = true;
}
static void xurses_synchronize (void) {
char character = '\0';
int signal = signal_none;
in (& character, (int) sizeof (character));
out (xurses_screen, xurses_screen_length ());
xurses_screen_dimensions ();
if (character == '\033') {
signal = signal_escape;
} else if (character_is_digit (character) == true) {
signal = signal_0 + (int) character - '0';
} else if (character_is_lowercase (character) == true) {
signal = signal_a + (int) character - 'a';
} else if (character_is_uppercase (character) == true) {
signal = signal_a + (int) character - 'A';
} else {
signal = signal_none;
}
xurses_action [signal % signal_count] ();
}
static void xurses_render_cursor (int x, int y) { /* BROKE IT INTENTIONALLY */
string_copy_limit (xurses_cursor + 2, string_realign (number_to_string (y % 1000 + 1), 3, '0'), 3);
string_copy_limit (xurses_cursor + 6, string_realign (number_to_string (x % 1000 + 1), 3, '0'), 3);
string_copy_limit (& xurses_screen [xurses_screen_length () - xurses_cursor_length - 1], xurses_cursor, xurses_cursor_length);
}
static void xurses_render_character (char character, int colour, int effect, int x, int y) {
limit (& x, 0, xurses_screen_width - 1);
limit (& y, 0, xurses_screen_height - 1);
string_copy_limit (xurses_screen_offset (x, y), xurses_format_character (character, colour, effect), xurses_format_length);
}
static void xurses_render_string (char * string, int colour, int effect, int x, int y) {
int index;
for (index = 0; string [index] != '\0'; ++index) {
xurses_render_character (string [index], colour, effect, x + index, y);
}
}
static void xurses_render_number (int number, int colour, int effect, int x, int y) {
xurses_render_string (number_to_string (number), colour, effect, x, y);
}
static void xurses_render_string_crop (char * string, int colour, int effect, int x, int y, int crop) {
int index;
for (index = 0; (string [index] != '\0') && (index < crop); ++index) {
xurses_render_character (string [index], colour, effect, x + index, y);
}
}
static void xurses_render_number_crop (int number, int colour, int effect, int x, int y, int crop) {
xurses_render_string_crop (number_to_string (number), colour, effect, x, y, crop);
}
static void xurses_render_vertical_line (char character, int colour, int effect, int x, int y, int height) {
int offset;
for (offset = 0; offset != height; ++offset) {
xurses_render_character (character, colour, effect, x, y + offset);
}
}
static void xurses_render_horizontal_line (char character, int colour, int effect, int x, int y, int width) {
int offset;
for (offset = 0; offset != width; ++offset) {
xurses_render_character (character, colour, effect, x + offset, y);
}
}
static void xurses_render_rectangle_line (char character, int colour, int effect, int x, int y, int width, int height) {
xurses_render_vertical_line (character, colour, effect, x + 0, y + 0, height + 0);
xurses_render_vertical_line (character, colour, effect, x + width - 1, y + 0, height + 0);
xurses_render_horizontal_line (character, colour, effect, x + 1, y + 0, width - 1);
xurses_render_horizontal_line (character, colour, effect, x + 1, y + height - 1, width - 1);
}
static void xurses_render_rectangle_fill (char character, int colour, int effect, int x, int y, int width, int height) {
int offset_x, offset_y;
for (offset_y = 0; offset_y != height; ++offset_y) {
for (offset_x = 0; offset_x != width; ++offset_x) {
xurses_render_character (character, colour, effect, x + offset_x, y + offset_y);
}
}
}
static void xurses_render_background (char character, int colour, int effect) {
int x, y;
for (y = 0; y != xurses_screen_height; ++y) {
for (x = 0; x != xurses_screen_width; ++x) {
xurses_render_character (character, colour, effect, x, y);
}
}
}
#endif