QUOTE: Life is a journey, not a destination.

feat: Added install script - libterm - An easy-to-use terminal library

libterm

An easy-to-use terminal library
git clone git://192.168.2.2/libterm
Log | Files | Refs | README

commit 24731bcb5c6d3bf9c4ed6e3ee1bbcde3d797df67
parent 1b85f56e68ab878b749032a4533601bb38b9cfcc
Author: typable <contact@typable.dev>
Date:   Sun, 24 Mar 2024 15:24:03 +0100

feat: Added install script

Diffstat:
AMakefile | 18++++++++++++++++++
MREADME.md | 6++++++
Alibterm.c | 196+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rterm.h -> libterm.h | 0
Dterm.c | 196-------------------------------------------------------------------------------
5 files changed, 220 insertions(+), 196 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,18 @@ +default: build + +build: + cc -o libterm.so -shared -fPIC -Wall -Wextra libterm.c + +install: + cc -o libterm.so -shared -fPIC libterm.c + sudo cp libterm.h /usr/local/include/ + sudo cp libterm.so /usr/local/lib/ + sudo ldconfig + rm libterm.so + +uninstall: + sudo rm /usr/local/include/libterm.h + sudo rm /usr/local/lib/libterm.so + +clean: + rm libterm.so diff --git a/README.md b/README.md @@ -1,3 +1,9 @@ # libterm An easy-to-use terminal library + +## Installation + +``` +sudo make install +``` diff --git a/libterm.c b/libterm.c @@ -0,0 +1,196 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <termios.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <stdarg.h> +#include <poll.h> + +#include "libterm.h" + +struct termios termios; +term_t term = { NULL, 0 }; + +void term_panic(const char *str) { + write(STDOUT_FILENO, "\x1b[2J", 4); + write(STDOUT_FILENO, "\x1b[H", 3); + write(STDOUT_FILENO, "\x1b[?25h", 6); + perror(str); + exit(EXIT_FAILURE); +} + +void term_disable_raw_mode() { + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios) == -1) { + term_panic("tcsetattr"); + } +} + +void term_enable_raw_mode() { + if (tcgetattr(STDIN_FILENO, &termios) == -1) { + term_panic("tcgetattr"); + } + atexit(term_disable_raw_mode); + struct termios raw = termios; + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + raw.c_oflag &= ~(OPOST); + raw.c_cflag |= (CS8); + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + raw.c_cc[VMIN] = 0; + raw.c_cc[VTIME] = 1; + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) { + term_panic("tcsetattr"); + } +} + +int term_read_cursor_pos(int *rows, int *cols) { + char buf[32]; + unsigned int i = 0; + if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4) { + return -1; + } + while (i < sizeof(buf) - 1) { + if (read(STDIN_FILENO, &buf[i], 1) != 1) { + break; + } + if (buf[i] == 'R') { + break; + } + i++; + } + buf[i] = '\0'; + if (buf[0] != '\x1b' || buf[1] != '[') { + return -1; + } + if (sscanf(&buf[2], "%d;%d", rows, cols) != 2) { + return -1; + } + return -0; +} + +int term_read_window_size(int *rows, int *cols) { + struct winsize ws; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) { + if (write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12) { + return -1; + } + return term_read_cursor_pos(rows, cols); + } + else { + *cols = ws.ws_col; + *rows = ws.ws_row; + return 0; + } +} + +int term_poll_key(int timeout) { + struct pollfd fds[1]; + fds[0].fd = STDIN_FILENO; + fds[0].events = POLLIN | POLLPRI; + if (poll(fds, 1, timeout)) { + return term_read_key(); + } + return 0; +} + +int term_read_key(void) { + int len; + char c; + while ((len = read(STDIN_FILENO, &c, 1)) != 1) { + if (len == -1 && errno != EAGAIN) { + term_panic("read"); + } + } + if (c == '\x1b') { + char seq[3]; + if (read(STDIN_FILENO, &seq[0], 1) != 1) { + return '\x1b'; + } + if (read(STDIN_FILENO, &seq[1], 1) != 1) { + return '\x1b'; + } + if (seq[0] == '[') { + if (seq[1] >= '0' && seq[1] <= '9') { + if (read(STDIN_FILENO, &seq[2], 1) != 1) { + return '\x1b'; + } + if (seq[2] == '~') { + switch (seq[1]) { + case '1': + return HOME_KEY; + case '3': + return DEL_KEY; + case '4': + return END_KEY; + case '5': + return PAGE_UP; + case '6': + return PAGE_DOWN; + case '7': + return HOME_KEY; + case '8': + return END_KEY; + } + } + } + else { + switch (seq[1]) { + case 'A': + return ARROW_UP; + case 'B': + return ARROW_DOWN; + case 'C': + return ARROW_RIGHT; + case 'D': + return ARROW_LEFT; + case 'H': + return HOME_KEY; + case 'F': + return END_KEY; + } + return '\x1b'; + } + } + else if (seq[0] == 'O') { + switch (seq[1]) { + case 'H': + return HOME_KEY; + case 'F': + return END_KEY; + } + } + } + return c; +} + +void term_write(char *str) { + int str_len = strlen(str); + char *new_buffer = realloc(term.buffer, sizeof(char) * (term.len + str_len + 1)); + if (new_buffer == NULL) { + fprintf(stderr, "Cannot realloc memory!\n"); + return; + } + term.buffer = new_buffer; + memcpy(term.buffer + term.len, str, str_len); + term.len += str_len; + term.buffer[term.len] = '\0'; +} + +void term_writef(const char *format, ...) { + va_list args; + va_start(args, format); + char str[1000]; + vsnprintf(str, sizeof(str), format, args); + term_write(str); + va_end(args); +} + +void term_flush(void) { + if (term.len > 0) { + write(STDOUT_FILENO, term.buffer, term.len); + free(term.buffer); + term.buffer = NULL; + term.len = 0; + } +} diff --git a/term.h b/libterm.h diff --git a/term.c b/term.c @@ -1,196 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <termios.h> -#include <sys/ioctl.h> -#include <errno.h> -#include <stdarg.h> -#include <poll.h> - -#include "term.h" - -struct termios termios; -term_t term = { NULL, 0 }; - -void term_panic(const char *str) { - write(STDOUT_FILENO, "\x1b[2J", 4); - write(STDOUT_FILENO, "\x1b[H", 3); - write(STDOUT_FILENO, "\x1b[?25h", 6); - perror(str); - exit(EXIT_FAILURE); -} - -void term_disable_raw_mode() { - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios) == -1) { - term_panic("tcsetattr"); - } -} - -void term_enable_raw_mode() { - if (tcgetattr(STDIN_FILENO, &termios) == -1) { - term_panic("tcgetattr"); - } - atexit(term_disable_raw_mode); - struct termios raw = termios; - raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - raw.c_oflag &= ~(OPOST); - raw.c_cflag |= (CS8); - raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - raw.c_cc[VMIN] = 0; - raw.c_cc[VTIME] = 1; - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) { - term_panic("tcsetattr"); - } -} - -int term_read_cursor_pos(int *rows, int *cols) { - char buf[32]; - unsigned int i = 0; - if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4) { - return -1; - } - while (i < sizeof(buf) - 1) { - if (read(STDIN_FILENO, &buf[i], 1) != 1) { - break; - } - if (buf[i] == 'R') { - break; - } - i++; - } - buf[i] = '\0'; - if (buf[0] != '\x1b' || buf[1] != '[') { - return -1; - } - if (sscanf(&buf[2], "%d;%d", rows, cols) != 2) { - return -1; - } - return -0; -} - -int term_read_window_size(int *rows, int *cols) { - struct winsize ws; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) { - if (write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12) { - return -1; - } - return term_read_cursor_pos(rows, cols); - } - else { - *cols = ws.ws_col; - *rows = ws.ws_row; - return 0; - } -} - -int term_poll_key(int timeout) { - struct pollfd fds[1]; - fds[0].fd = STDIN_FILENO; - fds[0].events = POLLIN | POLLPRI; - if (poll(fds, 1, timeout)) { - return term_read_key(); - } - return 0; -} - -int term_read_key(void) { - int len; - char c; - while ((len = read(STDIN_FILENO, &c, 1)) != 1) { - if (len == -1 && errno != EAGAIN) { - term_panic("read"); - } - } - if (c == '\x1b') { - char seq[3]; - if (read(STDIN_FILENO, &seq[0], 1) != 1) { - return '\x1b'; - } - if (read(STDIN_FILENO, &seq[1], 1) != 1) { - return '\x1b'; - } - if (seq[0] == '[') { - if (seq[1] >= '0' && seq[1] <= '9') { - if (read(STDIN_FILENO, &seq[2], 1) != 1) { - return '\x1b'; - } - if (seq[2] == '~') { - switch (seq[1]) { - case '1': - return HOME_KEY; - case '3': - return DEL_KEY; - case '4': - return END_KEY; - case '5': - return PAGE_UP; - case '6': - return PAGE_DOWN; - case '7': - return HOME_KEY; - case '8': - return END_KEY; - } - } - } - else { - switch (seq[1]) { - case 'A': - return ARROW_UP; - case 'B': - return ARROW_DOWN; - case 'C': - return ARROW_RIGHT; - case 'D': - return ARROW_LEFT; - case 'H': - return HOME_KEY; - case 'F': - return END_KEY; - } - return '\x1b'; - } - } - else if (seq[0] == 'O') { - switch (seq[1]) { - case 'H': - return HOME_KEY; - case 'F': - return END_KEY; - } - } - } - return c; -} - -void term_write(char *str) { - int str_len = strlen(str); - char *new_buffer = realloc(term.buffer, sizeof(char) * (term.len + str_len + 1)); - if (new_buffer == NULL) { - fprintf(stderr, "Cannot realloc memory!\n"); - return; - } - term.buffer = new_buffer; - memcpy(term.buffer + term.len, str, str_len); - term.len += str_len; - term.buffer[term.len] = '\0'; -} - -void term_writef(const char *format, ...) { - va_list args; - va_start(args, format); - char str[1000]; - vsnprintf(str, sizeof(str), format, args); - term_write(str); - va_end(args); -} - -void term_flush(void) { - if (term.len > 0) { - write(STDOUT_FILENO, term.buffer, term.len); - free(term.buffer); - term.buffer = NULL; - term.len = 0; - } -}