This commit is contained in:
opFez 2021-03-03 13:11:41 +01:00
commit 0f0892c1a8
3 changed files with 274 additions and 0 deletions

26
Makefile Normal file
View File

@ -0,0 +1,26 @@
CFLAGS=-Wall -Wextra -pedantic -std=c99
CC=gcc
AR=ar
default:
@echo "to make static library: make static"
@echo "to make shared library: make shared"
static: tui.a
shared: tui.so
tui.a: tui_st.o
$(AR) rcs $@ $<
tui_st.o: tui.c tui.h
$(CC) $(CFLAGS) -c -o $@ tui.c
tui.so: tui_sh.o
$(CC) -shared -o $@ $<
tui_sh.o: tui.c tui.h
$(CC) $(CFLAGS) -fPIC -c -o $@ tui.c
.PHONY: clean
clean:
rm -f *.o *.so *.a

156
tui.c Normal file
View File

@ -0,0 +1,156 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#include "tui.h"
static struct termios orig_termios;
static const struct cell empty_cell = {
' ',
TUI_DEFAULT_FG,
TUI_DEFAULT_BG
};
/* global cell buffer */
struct cell_buffer stdscr = {
NULL,
-1, /* uninitialized */
-1
};
static void
die(const char *s)
{
perror(s);
exit(1);
}
static void
tui_disable_raw_mode()
{
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1)
die("tcsetattr");
}
static void
tui_enable_raw_mode()
{
if (tcgetattr(STDIN_FILENO, &orig_termios) == -1)
die("tcgetattr");
struct termios raw = orig_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)
die("tcsetattr");
}
static void
get_window_size(int *height, int *width)
{
struct winsize ws;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
if (height != NULL)
*height = ws.ws_row;
if (width != NULL)
*width = ws.ws_col;
}
static void
init_cell_buffer(struct cell_buffer *cb)
{
long ncells = cb->width * cb->height;
cb->cells = malloc(ncells * sizeof(struct cell));
for (long i = 0; i < ncells; i++)
cb->cells[i] = empty_cell;
}
/****************************************************/
void
tui_init()
{
tui_enable_raw_mode();
get_window_size(&stdscr.height, &stdscr.width);
init_cell_buffer(&stdscr);
struct cell a = {
'#',
TUI_BLACK,
TUI_WHITE
};
tui_clear(&stdscr, empty_cell);
tui_clear(&stdscr, a);
tui_refresh(&stdscr);
}
void
tui_shutdown()
{
tui_disable_raw_mode();
}
int
tui_width()
{
int width;
get_window_size(NULL, &width);
return width;
}
int
tui_height()
{
int height;
get_window_size(&height, NULL);
return height;
}
void
tui_refresh(struct cell_buffer *cb)
{
for (int y = 0; y < cb->height; y++) {
for (int x = 0; x < cb->width; x++) {
// currently doesn't handle cell's fg and bg
long current_cell = x + y * cb->width;
fprintf(stderr,
"\033[mCell number %ld, fg: %d, bg: %d\r\n",
current_cell,
cb->cells[current_cell].fg,
cb->cells[current_cell].bg);
printf("\033[%d;%dm",
cb->cells[current_cell].fg + 29,
cb->cells[current_cell].bg + 39);
byte buffer[1];
buffer[0] = cb->cells[current_cell].ch;
write(STDOUT_FILENO, buffer, 1);
}
write(STDOUT_FILENO, "\r\n", 2);
}
}
void
tui_clear(struct cell_buffer *cb, struct cell clear_cell)
{
long ncells = cb->width * cb->height;
for (long i = 0; i < ncells; i++) {
cb->cells[i] = clear_cell;
}
}
void
tui_set_cell(struct cell_buffer *cb, int x, int y, struct cell c)
{
if (x < 0 || y < 0 || x > cb->width || y > cb->height)
return;
cb->cells[x + y * cb->width] = c;
}

92
tui.h Normal file
View File

@ -0,0 +1,92 @@
#ifndef TUI_H
#define TUI_H
#include <stdint.h>
#define TUI_DEFAULT 0x00
#define TUI_BLACK 0x01
#define TUI_RED 0x02
#define TUI_GREEN 0x03
#define TUI_YELLOW 0x04
#define TUI_BLUE 0x05
#define TUI_MAGENTA 0x06
#define TUI_CYAN 0x07
#define TUI_WHITE 0x08
#define TUI_DEFAULT_FG TUI_DEFAULT
#define TUI_DEFAULT_BG TUI_BLACK
#define TUI_KEY_CTRL_TILDE 0x00
#define TUI_KEY_CTRL_2 0x00
#define TUI_KEY_CTRL_A 0x01
#define TUI_KEY_CTRL_B 0x02
#define TUI_KEY_CTRL_C 0x03
#define TUI_KEY_CTRL_D 0x04
#define TUI_KEY_CTRL_E 0x05
#define TUI_KEY_CTRL_F 0x06
#define TUI_KEY_CTRL_G 0x07
#define TUI_KEY_BACKSPACE 0x08
#define TUI_KEY_CTRL_H 0x08
#define TUI_KEY_TAB 0x09
#define TUI_KEY_CTRL_I 0x09
#define TUI_KEY_CTRL_J 0x0A
#define TUI_KEY_CTRL_K 0x0B
#define TUI_KEY_CTRL_L 0x0C
#define TUI_KEY_ENTER 0x0D
#define TUI_KEY_CTRL_M 0x0D
#define TUI_KEY_CTRL_N 0x0E
#define TUI_KEY_CTRL_O 0x0F
#define TUI_KEY_CTRL_P 0x10
#define TUI_KEY_CTRL_Q 0x11
#define TUI_KEY_CTRL_R 0x12
#define TUI_KEY_CTRL_S 0x13
#define TUI_KEY_CTRL_T 0x14
#define TUI_KEY_CTRL_U 0x15
#define TUI_KEY_CTRL_V 0x16
#define TUI_KEY_CTRL_W 0x17
#define TUI_KEY_CTRL_X 0x18
#define TUI_KEY_CTRL_Y 0x19
#define TUI_KEY_CTRL_Z 0x1A
#define TUI_KEY_ESC 0x1B
#define TUI_KEY_CTRL_LSQ_BRACKET 0x1B
#define TUI_KEY_CTRL_3 0x1B
#define TUI_KEY_CTRL_4 0x1C
#define TUI_KEY_CTRL_BACKSLASH 0x1C
#define TUI_KEY_CTRL_5 0x1D
#define TUI_KEY_CTRL_RSQ_BRACKET 0x1D
#define TUI_KEY_CTRL_6 0x1E
#define TUI_KEY_CTRL_7 0x1F
#define TUI_KEY_CTRL_SLASH 0x1F
#define TUI_KEY_CTRL_UNDERSCORE 0x1F
#define TUI_KEY_SPACE 0x20
#define TUI_KEY_BACKSPACE2 0x7F
#define TUI_KEY_CTRL_8 0x7F
#define TUI_CTRL_KEY(k) ((k) & 0x1f)
typedef unsigned char byte;
struct cell {
byte ch; // ascii only
uint16_t fg;
uint16_t bg;
};
struct cell_buffer {
struct cell *cells;
int height;
int width;
};
void tui_init();
void tui_shutdown();
int tui_width();
int tui_height();
void tui_refresh();
void tui_clear();
void tui_set_cell();
#endif /* TUI_H */