diff options
author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-12-28 09:35:59 +0330 |
---|---|---|
committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-12-28 09:35:59 +0330 |
commit | 5a94037a19cee399d951b0e54937cffa82edecc2 (patch) | |
tree | 39b2a9aa3002a28d30f9b98d8b1ca5123b88b87f /src/ui/tui.c | |
parent | d7802371b56734446a16962363322282ba772257 (diff) |
Diffstat (limited to 'src/ui/tui.c')
-rw-r--r-- | src/ui/tui.c | 94 |
1 files changed, 54 insertions, 40 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) { |