diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..46430ae --- /dev/null +++ b/install.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -xe + +sudo cp xurses.h /usr/include/xolatile/xurses.h +sudo cp xurses.c /usr/include/xolatile/xurses.c + +exit diff --git a/xurses.c b/xurses.c new file mode 100644 index 0000000..55668b2 --- /dev/null +++ b/xurses.c @@ -0,0 +1,139 @@ +/* + * 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 + +#include + +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; + +void (* curses_action ['~' - ' ']) (void) = { 0 }; + +struct termios curses_old_terminal; +struct termios curses_new_terminal; + +void curses_initialize (void) { + char key; + + struct winsize screen_dimension; + + fatal_failure (ioctl (STDOUT_FILENO, TIOCGWINSZ, & screen_dimension) == -1, "[!] ioctl: Failed to get terminal size."); + + curses_screen_width = (int) screen_dimension.ws_col; + curses_screen_height = (int) screen_dimension.ws_row; + + fatal_failure (tcgetattr (STDIN_FILENO, & curses_old_terminal) == -1, "[!] tcgetattr: Failed to get terminal attributes."); + + curses_new_terminal = curses_old_terminal; + + curses_new_terminal.c_cc [VMIN] = (unsigned char) 0; + curses_new_terminal.c_cc [VTIME] = (unsigned char) 1; + + curses_new_terminal.c_iflag &= (unsigned int) ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + curses_new_terminal.c_oflag &= (unsigned int) ~(OPOST); + curses_new_terminal.c_cflag |= (unsigned int) (CS8); + curses_new_terminal.c_lflag &= (unsigned int) ~(ECHO | ICANON | IEXTEN | ISIG); + + fatal_failure (tcsetattr (STDIN_FILENO, TCSAFLUSH, & curses_new_terminal) == -1, "[!] tcsetattr: Failed to set raw terminal attributes."); + + curses_screen = allocate (12 * curses_screen_width * curses_screen_height + 8); + + string_copy_limit (& curses_screen [0], "\033[2J\033[H", 7); + + for (key = ' '; key != '~'; ++key) { + curses_unbind (key); + } + + //~write (STDOUT_FILENO, "\033[25h", sizeof ("\033[25h")); +} + +void curses_deinitialize (void) { + free (curses_screen); + + out ("\033[2J\033[H", 7); + + fatal_failure (tcsetattr (STDIN_FILENO, TCSAFLUSH, & curses_old_terminal) == -1, "[!] tcsetattr: Failed to set terminal attributes."); +} + +void curses_synchronize (void) { + curses_signal = 0; + + out (curses_screen, 12 * curses_screen_width * curses_screen_height + 8); + + in (& curses_signal, 1); + + if ((curses_signal < ' ') || (curses_signal > '~')) { + return; + } else { + curses_action [curses_signal - ' '] (); + } +} + +void curses_character (char character, int effect, int colour, int x, int y) { + char format [12] = "\033[ ;3 m \033[0m"; + + format [2] = (char) effect + '0'; + format [5] = (char) colour + '0'; + format [7] = character; + + string_copy_limit (& curses_screen [(y * curses_screen_width + x) * 12 + 7], format, 12); +} + +void curses_style (int effect, int colour) { + char format [8] = "\033[ ;3 m"; + + if ((effect == -1) || (colour == -1)) { + out ("\033[0m", 4); + } else { + format [2] = (char) effect + '0'; + format [5] = (char) colour + '0'; + + out (format, 7); + } +} + +void curses_clear (void) { + out ("\033[2J", 4); +} + +void curses_show_cursor (int show) { + if (show != 0) { + out ("\033[?25h", 6); + } else { + out ("\033[?25l", 6); + } +} + +void curses_move_cursor (int x, int y) { + out ("\033[H", 4); /* yx */ +} + +void curses_bind (char key, void (* action) (void)) { + curses_action [key - ' '] = action; +} + +void curses_unbind (char key) { + curses_action [key - ' '] = curses_idle; +} + +void curses_idle (void) { + return; +} + +void curses_exit (void) { + curses_active = 0; +} + +#endif diff --git a/xurses.h b/xurses.h new file mode 100644 index 0000000..0db47f8 --- /dev/null +++ b/xurses.h @@ -0,0 +1,50 @@ +/* + * 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 + +#include +#include + +#include +#include +#include +#include +#include + +extern int curses_active; +extern int curses_cursor; +extern char curses_signal; +extern int curses_screen_width; +extern int curses_screen_height; +extern int curses_screen_size; +extern char * curses_screen; + +extern void (* curses_action ['~' - ' ']) (void); + +extern struct termios curses_old_terminal; +extern struct termios curses_new_terminal; + +extern void curses_initialize (void); +extern void curses_deinitialize (void); +extern void curses_synchronize (void); + +extern void curses_character (char, int, int, int, int); +extern void curses_style (int, int); +extern void curses_clear (void); +extern void curses_show_cursor (int); +extern void curses_move_cursor (int, int); + +extern void curses_bind (char, void (*) (void)); +extern void curses_unbind (char); + +extern void curses_idle (void); +extern void curses_exit (void); + +#endif