summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/tui.c94
-rw-r--r--src/ui/tui.h40
2 files changed, 77 insertions, 57 deletions
diff --git a/src/ui/tui.c b/src/ui/tui.c
index 835e228..0e6a936 100644
--- a/src/ui/tui.c
+++ b/src/ui/tui.c
@@ -21,7 +21,7 @@ const int MIN_HEIGHT = -2;
const int FRAME_UNLIMITED = 0;
-void _tui_clear_cells(TUI *tui) {
+void _tui_clear_cells(TUI *restrict tui) {
constexpr TERMINAL_CELL EMPTY_CELL = {
.c = ' ',
.color = COLOR_NO_COLOR,
@@ -29,19 +29,20 @@ void _tui_clear_cells(TUI *tui) {
.style = TEXT_STYLE_NORMAL,
.on_action_callback.on_raw_input_callback = NULL,
.on_action_callback.metadata = NULL,
+ .on_action_callback.data = NULL,
};
for (size_t i = 0; i < tui->cells_length; ++i) {
tui->cells[i] = EMPTY_CELL;
}
}
-void _tui_init_cells(TUI *tui) {
+void _tui_init_cells(TUI *restrict tui) {
tui->cells_length = tui_get_width(tui) * tui_get_height(tui);
tui->cells = malloc(tui->cells_length * sizeof(*tui->cells));
_tui_clear_cells(tui);
}
-void _tui_delete_cells(TUI *tui) {
+void _tui_delete_cells(TUI *restrict tui) {
tui->cells_length = 0;
free(tui->cells);
tui->cells = NULL;
@@ -50,7 +51,7 @@ void _tui_delete_cells(TUI *tui) {
TUI *tui_init() {
setbuf(stdout, NULL);
- TUI *tui = malloc(sizeof(TUI));
+ TUI *restrict tui = malloc(sizeof(TUI));
constexpr TUI tui_clean = {
.cells = NULL,
@@ -100,7 +101,7 @@ void tui_delete(TUI *restrict tui) {
free(tui);
}
-void tui_refresh(TUI *tui) {
+void tui_refresh(TUI *restrict tui) {
const int width = tui_get_width(tui);
const int height = tui_get_height(tui);
@@ -112,9 +113,9 @@ void tui_refresh(TUI *tui) {
}
}
-int tui_get_width(TUI *tui) { return tui->size.ws_col; }
+uint16_t tui_get_width(TUI *restrict tui) { return tui->size.ws_col; }
-int tui_get_height(TUI *tui) { return tui->size.ws_row; }
+uint16_t tui_get_height(TUI *restrict tui) { return tui->size.ws_row; }
int tui_clear_screen() { return printf("\033[2J\r"); }
@@ -130,7 +131,7 @@ int tui_save_cursor() { return printf("\0337"); }
int tui_restore_cursor() { return printf("\0338"); }
-void tui_get_cursor_pos(TUI *tui, int *x, int *y) {
+void tui_get_cursor_pos(TUI *restrict tui, int *x, int *y) {
char buf[8] = "";
char cmd[] = "\033[6n";
tcgetattr(0, &tui->raw);
@@ -153,54 +154,56 @@ int tui_delete_before() { return printf("\b \b"); }
int tui_delete_under_cursor() { return printf(" \b"); }
-int _tui_get_cell_index(TUI *tui, int x, int y) {
- const int width = tui_get_width(tui);
- return x + width * y;
+size_t _tui_get_cell_index(TUI *restrict tui, size_t x, size_t y) {
+ const size_t width = tui_get_width(tui);
+ const size_t result = x + width * y;
+ return result >= tui->cells_length?0:result; // in resizing it will overflow in some time
}
-void _tui_set_cell_char(TUI *tui, int x, int y, char c) {
+void _tui_set_cell_char(TUI *restrict tui, int x, int y, char c) {
tui->cells[_tui_get_cell_index(tui, x, y)].c = c;
}
-void _tui_set_cell_color(TUI *tui, int x, int y, COLOR color) {
+void _tui_set_cell_color(TUI *restrict tui, int x, int y, COLOR color) {
if (color_equals(color, COLOR_NO_COLOR)) {
return;
}
tui->cells[_tui_get_cell_index(tui, x, y)].color = color;
}
-void _tui_set_cell_style(TUI *tui, int x, int y, TEXT_STYLE style) {
+void _tui_set_cell_style(TUI *restrict tui, int x, int y, TEXT_STYLE style) {
tui->cells[_tui_get_cell_index(tui, x, y)].style = style;
}
-void _tui_set_cell_background_color_if_not_set(TUI *tui, int x, int y,
+void _tui_set_cell_background_color_if_not_set(TUI *restrict tui, int x, int y,
COLOR background_color) {
if (color_equals(background_color, COLOR_NO_COLOR)) {
return;
}
- TERMINAL_CELL *cell = &tui->cells[_tui_get_cell_index(tui, x, y)];
+ TERMINAL_CELL *const cell = &tui->cells[_tui_get_cell_index(tui, x, y)];
if (color_equals(cell->background_color, COLOR_NO_COLOR)) {
cell->background_color = background_color;
}
}
-void _tui_set_cell_on_action_callback(TUI *tui, int x, int y,
+void _tui_set_cell_on_action_callback(TUI *restrict tui, int x, int y,
ON_ACTION_CALLBACK on_action_callback) {
tui->cells[_tui_get_cell_index(tui, x, y)].on_action_callback =
on_action_callback;
}
-void tui_handle_input_action(TUI *tui, INPUT_ACTION input_action) {
+void tui_handle_input_action(TUI *restrict tui, INPUT_ACTION input_action) {
const size_t index = _tui_get_cell_index(tui, input_action.x, input_action.y);
if (index < tui->cells_length) {
const ON_ACTION_CALLBACK callback = tui->cells[index].on_action_callback;
if (callback.on_raw_input_callback != NULL) {
- callback.on_raw_input_callback(input_action, callback.metadata);
+ callback.on_raw_input_callback(input_action, callback.metadata,
+ callback.data);
}
}
}
-bool handle_input(TUI *tui) {
+bool handle_input(TUI *restrict tui) {
unsigned char buff[6];
read(STDIN_FILENO, &buff, 1);
if (buff[0] == 3) { // User pressd Ctr+C
@@ -262,28 +265,30 @@ bool handle_input(TUI *tui) {
return false;
}
-void tui_start_app(TUI *tui, WIDGET_BUILDER widget_builder, int fps) {
+void tui_start_app(TUI *restrict tui, WIDGET_BUILDER widget_builder, int fps) {
tui_main_loop(tui, widget_builder, fps);
}
-void _tui_on_button_click_handler(INPUT_ACTION input_action, void *metadata) {
+void _tui_on_button_click_handler(INPUT_ACTION input_action, void *metadata,
+ void *data) {
if (input_action.type == INPUT_TYPE_MOUSE) {
const MOUSE_ACTION mouse_action = {
.button = input_action.action.mouse_button,
.x = input_action.x,
.y = input_action.y,
};
- ((ON_CLICK_CALLBACK)metadata)(mouse_action);
+ ((ON_CLICK_CALLBACK)metadata)(mouse_action, data);
}
}
-void _tui_on_text_input_handler(INPUT_ACTION input_action, void *metadata) {
+void _tui_on_text_input_handler(INPUT_ACTION input_action, void *metadata,
+ void *data) {
if (input_action.type == INPUT_TYPE_KEYBOARD) {
- ((ON_TEXT_INPUT)metadata)(input_action.action.key);
+ ((ON_TEXT_INPUT)metadata)(input_action.action.key, data);
}
}
-void _tui_draw_text_to_cells(TUI *tui, const char *text, COLOR color,
+void _tui_draw_text_to_cells(TUI *restrict tui, const char *text, COLOR color,
TEXT_STYLE style, int width_begin, int width_end,
int height_begin, int height_end, int *child_width,
int *child_height) {
@@ -322,9 +327,10 @@ END_OF_TEXT:
*child_width = max_width + 1;
}
-void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
- int width_end, int height_begin, int height_end,
- int *child_width, int *child_height) {
+void _tui_draw_widget_to_cells(TUI *restrict tui, const WIDGET *widget,
+ int width_begin, int width_end, int height_begin,
+ int height_end, int *child_width,
+ int *child_height) {
if (widget == NULL) {
return;
}
@@ -345,6 +351,7 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
const ON_ACTION_CALLBACK on_action_callback = {
.on_raw_input_callback = _tui_on_button_click_handler,
.metadata = metadata->callback,
+ .data = metadata->data,
};
for (int i = width_begin; i < *child_width; ++i) {
for (int j = height_begin; j < *child_height; ++j) {
@@ -493,6 +500,7 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
const ON_ACTION_CALLBACK on_action_callback = {
.on_raw_input_callback = _tui_on_text_input_handler,
.metadata = metadata->on_text_input,
+ .data = metadata->data,
};
for (int i = width_begin; i < width_end; ++i) {
for (int j = height_begin; j < height_end; ++j) {
@@ -724,7 +732,7 @@ int _tui_get_background_color_ascii(COLOR color) {
}
*/
-void _tui_draw_cells_to_terminal(TUI *tui) {
+void _tui_draw_cells_to_terminal(TUI *restrict tui) {
const size_t size_of_cell = 30; // TODO: recalc
const size_t size = tui->cells_length * size_of_cell;
char str[(size + 2) * sizeof(char) + 1];
@@ -860,7 +868,7 @@ bool tui_widget_eqauls(const WIDGET *restrict left,
exit(1);
}
-void tui_main_loop(TUI *tui, WIDGET_BUILDER widget_builder, int fps) {
+void tui_main_loop(TUI *restrict tui, WIDGET_BUILDER widget_builder, int fps) {
const uint64_t frame_nano =
(fps == FRAME_UNLIMITED) ? 0 : NANO_TO_SECOND / fps;
int64_t last_remaining = 0;
@@ -944,9 +952,11 @@ WIDGET *tui_make_text(char *restrict text, COLOR color, TEXT_STYLE style) {
TEXT_METADATA *_tui_make_text_metadata(char *restrict text, COLOR color,
TEXT_STYLE style) {
- TEXT_METADATA *metadata = malloc(sizeof(TEXT_METADATA));
- metadata->text = malloc(strlen(text) + 1);
- strcpy(metadata->text, text);
+ TEXT_METADATA *metadata = malloc(sizeof(*metadata));
+ const size_t text_len = strlen(text);
+ metadata->text = malloc(text_len + 1);
+ strncpy(metadata->text, text, text_len);
+ metadata->text[text_len] = '\0';
metadata->color = color;
metadata->style = style;
return metadata;
@@ -957,16 +967,19 @@ void _tui_delete_text(WIDGET *restrict text) {
free(text->metadata);
}
-WIDGET *tui_make_button(WIDGET *restrict child, ON_CLICK_CALLBACK callback) {
+WIDGET *tui_make_button(WIDGET *restrict child, ON_CLICK_CALLBACK callback,
+ void *data) {
return tui_new_widget(WIDGET_TYPE_BUTTON,
- _tui_make_button_metadata(child, callback));
+ _tui_make_button_metadata(child, callback, data));
}
BUTTON_METADATA *_tui_make_button_metadata(WIDGET *restrict child,
- ON_CLICK_CALLBACK callback) {
+ ON_CLICK_CALLBACK callback,
+ void *data) {
BUTTON_METADATA *metadata = malloc(sizeof(BUTTON_METADATA));
metadata->child = child;
metadata->callback = callback;
+ metadata->data = data;
return metadata;
}
@@ -1069,20 +1082,21 @@ void _tui_delete_padding(WIDGET *restrict padding) {
extern WIDGET *tui_make_text_input(char *restrict text, COLOR color,
TEXT_STYLE style,
- ON_TEXT_INPUT on_text_input) {
+ ON_TEXT_INPUT on_text_input, void *data) {
return tui_new_widget(
WIDGET_TYPE_TEXT_INPUT,
- _tui_make_text_input_metadata(text, color, style, on_text_input));
+ _tui_make_text_input_metadata(text, color, style, on_text_input, data));
}
extern TEXT_INPUT_METADATA *_tui_make_text_input_metadata(
char *restrict text, COLOR color, TEXT_STYLE style,
- ON_TEXT_INPUT on_text_input) {
+ ON_TEXT_INPUT on_text_input, void *data) {
TEXT_INPUT_METADATA *metadata = malloc(sizeof(*metadata));
metadata->text = malloc(strlen(text) + 1);
strcpy(metadata->text, text);
metadata->color = color;
metadata->style = style;
metadata->on_text_input = on_text_input;
+ metadata->data = data;
return metadata;
}
extern void _tui_delete_input_text(WIDGET *restrict text_input) {
diff --git a/src/ui/tui.h b/src/ui/tui.h
index 731ec76..83451c8 100644
--- a/src/ui/tui.h
+++ b/src/ui/tui.h
@@ -46,15 +46,16 @@ typedef struct INPUT_ACTION {
uint y;
} INPUT_ACTION;
-typedef void (*ON_TEXT_INPUT)(char c);
-typedef void (*ON_CLICK_CALLBACK)(MOUSE_ACTION mouse_action);
-typedef void (*ON_INPUT_CALLBACK)(INPUT_ACTION input_action);
-typedef void (*ON_RAW_INPUT_CALLBACK)(INPUT_ACTION input_action,
- void *metadata);
+typedef void (*ON_TEXT_INPUT)(char c, void *data);
+typedef void (*ON_CLICK_CALLBACK)(MOUSE_ACTION mouse_action, void *data);
+typedef void (*ON_INPUT_CALLBACK)(INPUT_ACTION input_action, void *data);
+typedef void (*ON_RAW_INPUT_CALLBACK)(INPUT_ACTION input_action, void *metadata,
+ void *data);
typedef struct ON_ACTION_CALLBACK {
ON_RAW_INPUT_CALLBACK on_raw_input_callback;
void *metadata;
+ void *data;
} ON_ACTION_CALLBACK;
#ifndef __cplusplus
@@ -110,6 +111,7 @@ typedef struct TEXT_METADATA {
typedef struct BUTTON_METADATA {
WIDGET *child;
ON_CLICK_CALLBACK callback;
+ void *data;
} BUTTON_METADATA;
typedef struct COLUMN_METADATA {
@@ -142,24 +144,26 @@ typedef struct TEXT_INPUT_METADATA {
COLOR color;
TEXT_STYLE style;
ON_TEXT_INPUT on_text_input;
+ void *data;
} TEXT_INPUT_METADATA;
-typedef WIDGET *(*WIDGET_BUILDER)(TUI *tui);
+typedef WIDGET *(*WIDGET_BUILDER)(TUI *restrict tui);
extern TUI *tui_init();
extern void tui_delete(TUI *restrict tui);
-extern void tui_refresh(TUI *tui);
+extern void tui_refresh(TUI *restrict tui);
-extern int tui_get_width(TUI *tui);
-extern int tui_get_height(TUI *tui);
+extern uint16_t tui_get_width(TUI *restrict tui);
+extern uint16_t tui_get_height(TUI *restrict tui);
-extern void tui_get_cursor_pos(TUI *tui, int *x, int *y);
+extern void tui_get_cursor_pos(TUI *restrict tui, int *x, int *y);
extern int tui_move_to(int x, int y);
extern int tui_clear_screen();
-extern void tui_start_app(TUI *tui, WIDGET_BUILDER widget_builder, int fps);
-extern void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget,
+extern void tui_start_app(TUI *restrict tui, WIDGET_BUILDER widget_builder,
+ int fps);
+extern void _tui_draw_widget_to_cells(TUI *restrict tui, const WIDGET *widget,
int width_begin, int width_end,
int height_begin, int height_end,
int *child_width, int *child_height);
@@ -176,7 +180,8 @@ extern bool tui_widget_eqauls(const WIDGET *restrict left,
extern bool tui_widget_array_eqauls(const WIDGET_ARRAY *restrict left,
const WIDGET_ARRAY *restrict right);
-extern void tui_main_loop(TUI *tui, WIDGET_BUILDER widget_builder, int fps);
+extern void tui_main_loop(TUI *restrict tui, WIDGET_BUILDER widget_builder,
+ int fps);
extern WIDGET *tui_new_widget(WIDGET_TYPE type, void *metadata);
extern void tui_delete_widget(WIDGET *restrict widget);
@@ -188,9 +193,10 @@ extern TEXT_METADATA *_tui_make_text_metadata(char *restrict text, COLOR color,
extern void _tui_delete_text(WIDGET *restrict text);
extern WIDGET *tui_make_button(WIDGET *restrict child,
- ON_CLICK_CALLBACK callback);
+ ON_CLICK_CALLBACK callback, void *data);
extern BUTTON_METADATA *_tui_make_button_metadata(WIDGET *restrict child,
- ON_CLICK_CALLBACK callback);
+ ON_CLICK_CALLBACK callback,
+ void *data);
extern void _tui_delete_button(WIDGET *restrict button);
extern WIDGET *tui_make_column(WIDGET_ARRAY *restrict children);
@@ -214,10 +220,10 @@ extern void _tui_delete_center(WIDGET *restrict center);
extern WIDGET *tui_make_text_input(char *restrict text, COLOR color,
TEXT_STYLE style,
- ON_TEXT_INPUT on_text_input);
+ ON_TEXT_INPUT on_text_input, void *data);
extern TEXT_INPUT_METADATA *_tui_make_text_input_metadata(
char *restrict text, COLOR color, TEXT_STYLE style,
- ON_TEXT_INPUT on_text_input);
+ ON_TEXT_INPUT on_text_input, void *data);
extern void _tui_delete_input_text(WIDGET *restrict text_input);
extern WIDGET *tui_make_padding(WIDGET *restrict child, int padding_top,