summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.ccls12
-rwxr-xr-x.clang-format4
-rw-r--r--src/main.c21
-rw-r--r--src/ui/tui.c195
-rw-r--r--src/ui/tui.h68
5 files changed, 217 insertions, 83 deletions
diff --git a/.ccls b/.ccls
new file mode 100755
index 0000000..f3137a2
--- /dev/null
+++ b/.ccls
@@ -0,0 +1,12 @@
+gcc
+# compiler driver
+
+%c -std=c23
+# %cpp -std=c++23
+
+# add this to support `.hpp` files as C++ headers
+# %hpp -x
+# %hpp c++-header
+
+%h -x
+%h c-header
diff --git a/.clang-format b/.clang-format
new file mode 100755
index 0000000..5af5a7a
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,4 @@
+# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+# To disable for a line use `// clang-format off`
+BasedOnStyle: Google # https://google.github.io/styleguide/cppguide.html
+IndentPPDirectives: BeforeHash
diff --git a/src/main.c b/src/main.c
index 1a4ce8a..c1a2563 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,10 +1,13 @@
-#include "ui/tui.h"
#include <stdio.h>
#include <unistd.h>
+#include "ui/tui.h"
+
bool is_clicked = false;
-void on_button_click(MOUSE_ACTION mouse_action) { is_clicked = !is_clicked; }
+void on_button_click(const MOUSE_ACTION *mouse_action) {
+ is_clicked = !is_clicked;
+}
WIDGET *ui_build(TUI *tui) {
if (is_clicked) {
@@ -17,10 +20,7 @@ WIDGET *ui_build(TUI *tui) {
tui_make_box(
20, 3,
tui_make_column(tui_make_widget_array(
- 2,
- tui_make_text(
- "This is the second page",
- COLOR_BLUE),
+ 2, tui_make_text("This is the second page", COLOR_BLUE),
tui_make_button(tui_make_text(" Back", COLOR_RED),
on_button_click))),
@@ -34,10 +34,9 @@ WIDGET *ui_build(TUI *tui) {
tui_make_row(tui_make_widget_array(
2, tui_make_box(50, 0, NULL, COLOR_NO_COLOR),
tui_make_button(
- tui_make_box(
- 16, 3,
- tui_make_text("\nClick here", COLOR_BLUE),
- COLOR_WHITE),
+ tui_make_box(16, 3,
+ tui_make_text("\nClick here", COLOR_BLUE),
+ COLOR_WHITE),
on_button_click))))),
COLOR_MAGENTA);
}
@@ -46,7 +45,7 @@ WIDGET *ui_build(TUI *tui) {
int main() {
TUI *tui = tui_init();
- tui_start_app(tui, ui_build);
+ tui_start_app(tui, ui_build, 144);
tui_delete(tui);
diff --git a/src/ui/tui.c b/src/ui/tui.c
index 7e044c2..e7336bf 100644
--- a/src/ui/tui.c
+++ b/src/ui/tui.c
@@ -7,12 +7,18 @@
#include <time.h>
#include <unistd.h>
+const int MAX_WIDTH = -1;
+const int MAX_HEIGHT = -1;
+
+const int MIN_WIDTH = -2;
+const int MIN_HEIGHT = -2;
+
void _tui_clear_cells(TUI *tui) {
const TERMINAL_CELL empty = {.c = ' ',
.color = COLOR_NO_COLOR,
.background_color = COLOR_NO_COLOR,
.on_click_callback = NULL};
- for (int i = 0; i < tui->cells_length; ++i) {
+ for (size_t i = 0; i < tui->cells_length; ++i) {
tui->cells[i] = empty;
}
}
@@ -56,9 +62,7 @@ TUI *tui_init() {
return tui;
}
-void tui_delete(TUI *tui) {
- const int width = tui_get_width(tui);
-
+void tui_delete(TUI *restrict tui) {
// Revert the terminal back to its original state
write(STDOUT_FILENO, "\e[?9l", 5);
write(STDOUT_FILENO, "\e[?47l", 6);
@@ -111,8 +115,8 @@ void tui_get_cursor_pos(TUI *tui, int *x, int *y) {
read(STDIN_FILENO, buf, sizeof(buf));
sscanf(buf, "\033[%d;%dR", y, x);
- --x;
- --y;
+ --*x;
+ --*y;
}
tcsetattr(0, TCSANOW, &tui->raw);
}
@@ -154,9 +158,9 @@ void _tui_set_cell_on_click_callback(TUI *tui, int x, int y,
on_click_callback;
}
-void tui_handle_mouse_action(TUI *tui, MOUSE_ACTION mouse_action) {
+void tui_handle_mouse_action(TUI *tui, const MOUSE_ACTION *mouse_action) {
const ON_CLICK_CALLBACK callback =
- tui->cells[_tui_get_cell_index(tui, mouse_action.x, mouse_action.y)]
+ tui->cells[_tui_get_cell_index(tui, mouse_action->x, mouse_action->y)]
.on_click_callback;
if (callback != NULL) {
callback(mouse_action);
@@ -191,12 +195,12 @@ bool handle_input(TUI *tui) {
read(STDIN_FILENO, &buff, 5);
switch (buff[1]) {
case 77: {
- MOUSE_ACTION mouse_action = {
+ const MOUSE_ACTION mouse_action = {
.button = buff[2],
.x = buff[3] - 32 - 1, // starts at 0
.y = buff[4] - 32 - 1, // starts at 0
};
- tui_handle_mouse_action(tui, mouse_action);
+ tui_handle_mouse_action(tui, &mouse_action);
/*printf("button:%u\n\rx:%u\n\ry:%u\n\n\r", mouse_action.button,*/
/* mouse_action.x, mouse_action.y);*/
} break;
@@ -215,22 +219,33 @@ bool handle_input(TUI *tui) {
case 'l':
tui_move_right(1);
break;
- case 'q':
+ case 'q':
return true;
+ case '\r': { // <ENTER>
+ int x, y;
+ tui_get_cursor_pos(tui, &x, &y);
+ const MOUSE_ACTION mouse_action = {
+ .button = MOUSE_BUTTON_LEFT_CLICK,
+ .x = x,
+ .y = y,
+ };
+ tui_handle_mouse_action(tui, &mouse_action);
+ } break;
case '\b':
case 127: // back space
tui_delete_before();
break;
default:
/*printf("unknown:%c,%d\n\r", buff[0], buff[0]);*/
+ /*sleep(1);*/
break;
}
}
return false;
}
-void tui_start_app(TUI *tui, WIDGET_BUILDER widget_builder) {
- tui_main_loop(tui, widget_builder);
+void tui_start_app(TUI *tui, WIDGET_BUILDER widget_builder, int fps) {
+ tui_main_loop(tui, widget_builder, fps);
}
void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
@@ -240,12 +255,10 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
case WIDGET_TYPE_TEXT: {
const TEXT_METADATA *metadata = widget->metadata;
const int width_diff = width_end - width_begin;
- const int text_len = strlen(metadata->text);
- int inserted_index = 0;
+ const size_t text_len = strlen(metadata->text);
+ size_t inserted_index = 0;
int height = height_begin;
for (; height < height_end; ++height) {
- const int begin = (height - height_begin) * width_diff;
-
for (int j = 0; j < width_diff; ++j) {
const int x = width_begin + j;
const int y = height;
@@ -286,7 +299,7 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
const COLUMN_METADATA *metadata = widget->metadata;
*child_width = width_begin;
*child_height = height_begin;
- for (int i = 0; i < metadata->children->size; ++i) {
+ for (size_t i = 0; i < metadata->children->size; ++i) {
const WIDGET *child = metadata->children->widgets[i];
int width_temp;
_tui_draw_widget_to_cells(tui, child, width_begin, width_end,
@@ -301,7 +314,7 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
const ROW_METADATA *metadata = widget->metadata;
*child_width = width_begin;
*child_height = height_begin;
- for (int i = 0; i < metadata->children->size; ++i) {
+ for (size_t i = 0; i < metadata->children->size; ++i) {
const WIDGET *child = metadata->children->widgets[i];
int height_temp;
_tui_draw_widget_to_cells(tui, child, *child_width, width_end,
@@ -315,12 +328,12 @@ void _tui_draw_widget_to_cells(TUI *tui, const WIDGET *widget, int width_begin,
case WIDGET_TYPE_BOX: {
const BOX_METADATA *metadata = widget->metadata;
- if (metadata->width != -1) {
+ if (metadata->width != MAX_WIDTH) {
width_end = metadata->width + width_begin >= width_end
? width_end
: metadata->width + width_begin;
}
- if (metadata->height != -1) {
+ if (metadata->height != MAX_HEIGHT) {
height_end = metadata->height + height_begin >= height_end
? height_end
: metadata->height + height_begin;
@@ -372,7 +385,7 @@ void _tui_draw_cells_to_terminal(TUI *tui) {
COLOR last_color = COLOR_NO_COLOR;
COLOR last_background_color = COLOR_NO_COLOR;
- for (int i = 0; i < tui->cells_length; ++i) {
+ for (size_t i = 0; i < tui->cells_length; ++i) {
const TERMINAL_CELL cell = tui->cells[i];
if (last_color != cell.color ||
@@ -403,11 +416,94 @@ void _tui_draw_cells_to_terminal(TUI *tui) {
write(STDOUT_FILENO, str, len);
}
-void tui_main_loop(TUI *tui, WIDGET_BUILDER widget_builder) {
+int kbhit() {
+ struct timeval tv = {0L, 0L};
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ return select(1, &fds, NULL, NULL, &tv) > 0;
+}
+
+bool widget_array_eqauls(const WIDGET_ARRAY *restrict left, const WIDGET_ARRAY *restrict right) {
+ if (left->size != right->size) {
+ return false;
+ }
+ for (size_t i = 0; i < left->size; ++i) {
+ if (!widget_eqauls(left->widgets[i], right->widgets[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool widget_eqauls(const WIDGET *restrict left, const WIDGET *restrict right) {
+ if (left == NULL || right == NULL) {
+ return left == NULL && right == NULL;
+ }
+ if (left->type != right->type) {
+ return false;
+ }
+
+ switch (left->type) {
+ case WIDGET_TYPE_TEXT: {
+ const TEXT_METADATA *left_data = left->metadata;
+ const TEXT_METADATA *right_data = right->metadata;
+ return left_data->color == right_data->color &&
+ strcmp(left_data->text, right_data->text) == 0;
+ } break;
+ case WIDGET_TYPE_BUTTON: {
+ const BUTTON_METADATA *left_data = left->metadata;
+ const BUTTON_METADATA *right_data = right->metadata;
+ return left_data->callback == right_data->callback &&
+ widget_eqauls(left_data->child, right_data->child);
+ } break;
+ case WIDGET_TYPE_COLUMN: {
+ const COLUMN_METADATA *left_data = left->metadata;
+ const COLUMN_METADATA *right_data = right->metadata;
+ return widget_array_eqauls(left_data->children, right_data->children);
+ } break;
+ case WIDGET_TYPE_ROW: {
+ const ROW_METADATA *left_data = left->metadata;
+ const ROW_METADATA *right_data = right->metadata;
+ return widget_array_eqauls(left_data->children, right_data->children);
+ } break;
+ case WIDGET_TYPE_BOX: {
+ const BOX_METADATA *left_data = left->metadata;
+ const BOX_METADATA *right_data = right->metadata;
+ return left_data->width == right_data->width &&
+ left_data->height == right_data->height &&
+ left_data->color == right_data->color &&
+ widget_eqauls(left_data->child, right_data->child);
+ } break;
+ default:
+ fprintf(stderr, "Type error '%d' in tui_delete_widget\n", left->type);
+ exit(1);
+ }
+
+ return true;
+}
+
+const int NANO_TO_SECOND = 1000000000;
+
+void nano_sleep(long int nano_seconds) {
+ struct timespec remaining,
+ request = {nano_seconds / NANO_TO_SECOND, nano_seconds % NANO_TO_SECOND};
+ nanosleep(&request, &remaining);
+}
+
+long int nano_time() {
+ struct timespec t = {0, 0}, tend = {0, 0};
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ return t.tv_sec * NANO_TO_SECOND + t.tv_nsec;
+}
+
+void tui_main_loop(TUI *tui, WIDGET_BUILDER widget_builder, int fps) {
+ const long int frame_nano = NANO_TO_SECOND / fps;
while (1) {
+ const long int start = nano_time();
+ tui_save_cursor();
tui_refresh(tui);
WIDGET *root_widget = widget_builder(tui);
- tui_save_cursor();
_tui_clear_cells(tui);
int width, height;
@@ -416,9 +512,17 @@ void tui_main_loop(TUI *tui, WIDGET_BUILDER widget_builder) {
_tui_draw_cells_to_terminal(tui);
tui_delete_widget(root_widget);
+ /*tui_move_to(0, 0);*/
+ /*printf("%ld\t%ld", last_frame_time, frame_nano);*/
tui_restore_cursor();
- if (handle_input(tui)) {
- return;
+ if (fps != -1) {
+ const long int diff = nano_time() - start;
+ nano_sleep(frame_nano-diff);
+ }
+ if (kbhit()) {
+ if (handle_input(tui)) {
+ return;
+ }
}
}
}
@@ -430,7 +534,7 @@ WIDGET *tui_new_widget(WIDGET_TYPE type, void *metadata) {
return widget;
}
-void tui_delete_widget(WIDGET *widget) {
+void tui_delete_widget(WIDGET *restrict widget) {
if (widget == NULL) {
return;
}
@@ -457,11 +561,11 @@ void tui_delete_widget(WIDGET *widget) {
free(widget);
}
-WIDGET *tui_make_text(char *text, COLOR color) {
+WIDGET *tui_make_text(char *restrict text, COLOR color) {
return tui_new_widget(WIDGET_TYPE_TEXT, _tui_make_text_metadata(text, color));
}
-TEXT_METADATA *_tui_make_text_metadata(char *text, COLOR color) {
+TEXT_METADATA *_tui_make_text_metadata(char *restrict text, COLOR color) {
TEXT_METADATA *metadata = malloc(sizeof(TEXT_METADATA));
metadata->text = malloc(strlen(text) + 1);
strcpy(metadata->text, text);
@@ -469,17 +573,17 @@ TEXT_METADATA *_tui_make_text_metadata(char *text, COLOR color) {
return metadata;
}
-void _tui_delete_text(WIDGET *text) {
+void _tui_delete_text(WIDGET *restrict text) {
free(((TEXT_METADATA *)text->metadata)->text);
free(text->metadata);
}
-WIDGET *tui_make_button(WIDGET *child, ON_CLICK_CALLBACK callback) {
+WIDGET *tui_make_button(WIDGET *restrict child, ON_CLICK_CALLBACK callback) {
return tui_new_widget(WIDGET_TYPE_BUTTON,
_tui_make_button_metadata(child, callback));
}
-BUTTON_METADATA *_tui_make_button_metadata(WIDGET *child,
+BUTTON_METADATA *_tui_make_button_metadata(WIDGET *restrict child,
ON_CLICK_CALLBACK callback) {
BUTTON_METADATA *metadata = malloc(sizeof(BUTTON_METADATA));
metadata->child = child;
@@ -487,51 +591,52 @@ BUTTON_METADATA *_tui_make_button_metadata(WIDGET *child,
return metadata;
}
-void _tui_delete_button(WIDGET *button) {
+void _tui_delete_button(WIDGET *restrict button) {
tui_delete_widget(((BUTTON_METADATA *)button->metadata)->child);
free(button->metadata);
}
-WIDGET *tui_make_column(WIDGET_ARRAY *children) {
+WIDGET *tui_make_column(WIDGET_ARRAY *restrict children) {
return tui_new_widget(WIDGET_TYPE_COLUMN,
_tui_make_column_metadata(children));
}
-COLUMN_METADATA *_tui_make_column_metadata(WIDGET_ARRAY *children) {
+COLUMN_METADATA *_tui_make_column_metadata(WIDGET_ARRAY *restrict children) {
COLUMN_METADATA *metadata = malloc(sizeof(COLUMN_METADATA));
metadata->children = children;
return metadata;
}
-void _tui_delete_column(WIDGET *column) {
+void _tui_delete_column(WIDGET *restrict column) {
COLUMN_METADATA *metadata = column->metadata;
_tui_delete_widget_array(metadata->children);
free(column->metadata);
}
-WIDGET *tui_make_row(WIDGET_ARRAY *children) {
+WIDGET *tui_make_row(WIDGET_ARRAY *restrict children) {
return tui_new_widget(WIDGET_TYPE_ROW, _tui_make_row_metadata(children));
}
-ROW_METADATA *_tui_make_row_metadata(WIDGET_ARRAY *children) {
+ROW_METADATA *_tui_make_row_metadata(WIDGET_ARRAY *restrict children) {
ROW_METADATA *metadata = malloc(sizeof(ROW_METADATA));
metadata->children = children;
return metadata;
}
-void _tui_delete_row(WIDGET *row) {
+void _tui_delete_row(WIDGET *restrict row) {
ROW_METADATA *metadata = row->metadata;
_tui_delete_widget_array(metadata->children);
free(row->metadata);
}
-WIDGET *tui_make_box(int width, int height, WIDGET *child, COLOR color) {
+WIDGET *tui_make_box(int width, int height, WIDGET *restrict child,
+ COLOR color) {
return tui_new_widget(WIDGET_TYPE_BOX,
_tui_make_box_metadata(child, width, height, color));
}
-BOX_METADATA *_tui_make_box_metadata(WIDGET *child, int width, int height,
- COLOR color) {
+BOX_METADATA *_tui_make_box_metadata(WIDGET *restrict child, int width,
+ int height, COLOR color) {
BOX_METADATA *metadata = malloc(sizeof(BOX_METADATA));
metadata->width = width;
metadata->height = height;
@@ -545,13 +650,13 @@ void _tui_delete_box(WIDGET *box) {
free(box->metadata);
}
-WIDGET_ARRAY *tui_make_widget_array(int size, ...) {
+WIDGET_ARRAY *tui_make_widget_array(size_t size, ...) {
va_list arg_pointer;
va_start(arg_pointer, size);
WIDGET **widgets = malloc(size * sizeof(WIDGET **));
- for (int i = 0; i < size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
widgets[i] = va_arg(arg_pointer, WIDGET *);
}
va_end(arg_pointer);
@@ -563,7 +668,7 @@ WIDGET_ARRAY *tui_make_widget_array(int size, ...) {
return widget_array;
}
-void _tui_delete_widget_array(WIDGET_ARRAY *widget_array) {
+void _tui_delete_widget_array(WIDGET_ARRAY *restrict widget_array) {
for (size_t i = 0; i < widget_array->size; ++i) {
tui_delete_widget(widget_array->widgets[i]);
}
diff --git a/src/ui/tui.h b/src/ui/tui.h
index b21395a..0de4adb 100644
--- a/src/ui/tui.h
+++ b/src/ui/tui.h
@@ -1,17 +1,23 @@
#ifndef A404M_UI_TUI
#define A404M_UI_TUI 1
+#include <stdint.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <termios.h>
-#include <stdint.h>
+
+extern const int MAX_WIDTH;
+extern const int MAX_HEIGHT;
+
+extern const int MIN_WIDTH;
+extern const int MIN_HEIGHT;
typedef enum MOUSE_BUTTON {
MOUSE_BUTTON_LEFT_CLICK = 32,
MOUSE_BUTTON_MIDDLE_CLICK = 33,
MOUSE_BUTTON_RIGHT_CLICK = 34,
MOUSE_BUTTON_SCROLL_UP = 96,
- MOUSE_BUTTON_SCROLL_DOWN = 97
+ MOUSE_BUTTON_SCROLL_DOWN = 97,
} MOUSE_BUTTON;
typedef struct MOUSE_ACTION {
@@ -20,7 +26,7 @@ typedef struct MOUSE_ACTION {
unsigned int y;
} MOUSE_ACTION;
-typedef void (*ON_CLICK_CALLBACK)(MOUSE_ACTION mouse_action);
+typedef void (*ON_CLICK_CALLBACK)(const MOUSE_ACTION *mouse_action);
#ifndef __cplusplus
typedef enum bool : uint8_t { false = 0, true = 1 } bool;
@@ -99,7 +105,7 @@ typedef struct BOX_METADATA {
typedef WIDGET *(*WIDGET_BUILDER)(TUI *tui);
extern TUI *tui_init();
-extern void tui_delete(TUI *tui);
+extern void tui_delete(TUI *restrict tui);
extern void tui_refresh(TUI *tui);
extern int tui_get_width(TUI *tui);
@@ -110,38 +116,46 @@ 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);
-extern 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 *childHeight);
-extern void tui_main_loop(TUI *tui, WIDGET_BUILDER widget_builder);
+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,
+ int width_begin, int width_end,
+ int height_begin, int height_end,
+ int *child_width, int *childHeight);
+
+extern bool widget_eqauls(const WIDGET *restrict left, const WIDGET *restrict right);
+extern bool 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 WIDGET *tui_new_widget(WIDGET_TYPE type, void *metadata);
-extern void tui_delete_widget(WIDGET *widget);
+extern void tui_delete_widget(WIDGET *restrict widget);
-extern WIDGET *tui_make_text(char *text, COLOR color);
-extern TEXT_METADATA *_tui_make_text_metadata(char *text, COLOR color);
-extern void _tui_delete_text(WIDGET *text);
+extern WIDGET *tui_make_text(char *restrict text, COLOR color);
+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 *child, ON_CLICK_CALLBACK callback);
-extern BUTTON_METADATA *_tui_make_button_metadata(WIDGET *child,
+extern WIDGET *tui_make_button(WIDGET *restrict child,
+ ON_CLICK_CALLBACK callback);
+extern BUTTON_METADATA *_tui_make_button_metadata(WIDGET *restrict child,
ON_CLICK_CALLBACK callback);
-extern void _tui_delete_button(WIDGET *button);
+extern void _tui_delete_button(WIDGET *restrict button);
-extern WIDGET *tui_make_column(WIDGET_ARRAY *children);
-extern COLUMN_METADATA *_tui_make_column_metadata(WIDGET_ARRAY *children);
-extern void _tui_delete_column(WIDGET *column);
+extern WIDGET *tui_make_column(WIDGET_ARRAY *restrict children);
+extern COLUMN_METADATA *
+_tui_make_column_metadata(WIDGET_ARRAY *restrict children);
+extern void _tui_delete_column(WIDGET *restrict column);
-extern WIDGET *tui_make_row(WIDGET_ARRAY *children);
-extern ROW_METADATA *_tui_make_row_metadata(WIDGET_ARRAY *children);
-extern void _tui_delete_row(WIDGET *row);
+extern WIDGET *tui_make_row(WIDGET_ARRAY *restrict children);
+extern ROW_METADATA *_tui_make_row_metadata(WIDGET_ARRAY *restrict children);
+extern void _tui_delete_row(WIDGET *restrict row);
-extern WIDGET *tui_make_box(int width, int height, WIDGET *child, COLOR color);
-extern BOX_METADATA *_tui_make_box_metadata(WIDGET *child, int width,
+extern WIDGET *tui_make_box(int width, int height, WIDGET *restrict child,
+ COLOR color);
+extern BOX_METADATA *_tui_make_box_metadata(WIDGET *restrict child, int width,
int height, COLOR color);
-extern void _tui_delete_box(WIDGET *box);
+extern void _tui_delete_box(WIDGET *restrict box);
-extern WIDGET_ARRAY *tui_make_widget_array(int size, ...);
-extern void _tui_delete_widget_array(WIDGET_ARRAY *widget_array);
+extern WIDGET_ARRAY *tui_make_widget_array(size_t size, ...);
+extern void _tui_delete_widget_array(WIDGET_ARRAY *restrict widget_array);
#endif