diff --git a/btk/btk-config.h b/btk/btk-config.h new file mode 100644 index 0000000..b6a5f4a --- /dev/null +++ b/btk/btk-config.h @@ -0,0 +1,58 @@ +#include "btk-utils.h" + +/* interaction */ +static const char btk_scroll_speed = 20; /* put negative value to invert direction */ +static const unsigned int btk_click_speed = 200; /* max time between double clicks, in ms */ + +/* font */ +/* only works well with monospace fonts */ +static const char btk_font_name[] = "Terminus"; +static const unsigned int btk_font_size = 16; +static const unsigned int btk_tab_size = 4; +static const unsigned int btk_text_spacing = 7; +static const unsigned int btk_caret_offset = 4; +static const btk_pos_t btk_text_offset_tweak = {0 , -0}; + +/* geometry */ +static const btk_size_t btk_cp = {72, 45}; /* pixel dimensions of one cell unit */ +static const unsigned int btk_frame = 2; /* thickness of the frame between cells */ +static const unsigned int btk_padding = 11; /* for elements inside the cells */ + +/* generic colors */ +static const btk_rgb_t btk_cl[] = { + {0.651f, 0.604f, 0.494f}, + {0.557f, 0.753f, 0.486f}, + {0.694f, 0.384f, 0.525f}, + {0.984f, 0.286f, 0.204f}, + {0.941f, 0.761f, 0.357f} +}; + +/* special colors */ +static const btk_rgb_t btk_cl_frame = {0.000f, 0.000f, 0.000f}; +static const btk_rgb_t btk_cl_frame_focus = {0.627f, 0.627f, 0.627f}; +static const btk_rgb_t btk_cl_frame_in = {0.427f, 0.827f, 0.427f}; +static const btk_rgb_t btk_cl_empty = {0.133f, 0.133f, 0.133f}; +static const btk_rgb_t btk_cl_field = {0.157f, 0.157f, 0.157f}; +static const btk_rgb_t btk_cl_select = {0.741f, 0.561f, 0.157f}; +static const btk_rgb_t btk_cl_bell = {0.984f, 0.286f, 0.204f}; +static const btk_rgb_t btk_cl_dyn_idle = {0.455f, 0.318f, 0.000f}; +static const btk_rgb_t btk_cl_dyn_pressed = {0.996f, 0.502f, 0.100f}; +static const btk_rgb_t btk_cl_dyn_disabled = {0.302f, 0.208f, 0.000f}; +static const btk_rgb_t btk_cl_pass_off = {0.235f, 0.220f, 0.212f}; +static const btk_rgb_t btk_cl_pass_on = {0.741f, 0.561f, 0.157f}; +static const btk_rgb_t btk_cl_text_normal = {0.922f, 0.859f, 0.824f}; +static const btk_rgb_t btk_cl_text_hilight = {0.114f, 0.125f, 0.129f}; +static const btk_rgb_t btk_cl_text_lolight = {0.326f, 0.302f, 0.247f}; +static const btk_rgb_t btk_cl_text_disabled = {0.651f, 0.604f, 0.494f}; +static const btk_rgb_t btk_cl_text_select = {0.114f, 0.125f, 0.129f}; +static const btk_rgb_t btk_cl_text_bell = {0.114f, 0.125f, 0.129f}; +static const btk_rgb_t btk_cl_text_spot = {0.557f, 0.753f, 0.486f}; + +static const btk_rgba_t btk_cl_window_overlay = {0.000f, 0.000f, 0.000f, 0.200f}; + +/* log + * 0 -> no logs at all + * 1 -> only errors + * 2 -> errors + warnings + * 3 -> errors + warnings + activity */ +static const int btk_log_level = 2; diff --git a/btk/btk-log.c b/btk/btk-log.c new file mode 100644 index 0000000..4147b6f --- /dev/null +++ b/btk/btk-log.c @@ -0,0 +1,142 @@ +#include +#include + +#include "btk-log.h" +#include "btk-config.h" + +void +btk_log(unsigned int log_id) +{ + if (btk_log_level < 3) + return; + + printf("BTK -> LOG -> "); + switch (log_id) + { + case BTK_LOG_SESSION_CLOSE: + printf("closed btk session"); + break; + case BTK_LOG_SESSION_OPEN: + printf("opened new btk session"); + break; + case BTK_LOG_GENERIC_EVENT_NOTIFY: + printf("generic x event received"); + break; + case BTK_LOG_EVENT_LOOP_IN: + printf("entered event loop"); + break; + case BTK_LOG_EVENT_LOOP_OUT: + printf("exited event loop"); + break; + case BTK_LOG_WINDOW_MAP: + printf("mapped window"); + break; + case BTK_LOG_WINDOW_UNMAP: + printf("unmapped window"); + break; + case BTK_LOG_WINDOW_CREATE: + printf("created new window"); + break; + case BTK_LOG_WINDOW_DESTROY: + printf("destroyed window"); + break; + case BTK_LOG_WINDOW_RENAME: + printf("renamed window"); + break; + case BTK_LOG_WINDOW_RESIZE: + printf("resized window"); + break; + case BTK_LOG_EVENT_EXPOSE: + printf("expose x event received"); + break; + case BTK_LOG_EVENT_BUTTON_PRESS: + printf("button press x event received"); + break; + case BTK_LOG_EVENT_BUTTON_RELEASE: + printf("button release x event received"); + break; + case BTK_LOG_EVENT_BUTTON_COMBO: + printf("button combo"); + break; + case BTK_LOG_EVENT_BUTTON_COMBO_BREAK: + printf("button combo broken"); + break; + case BTK_LOG_EVENT_KEY_PRESS: + printf("key press x event received"); + break; + case BTK_LOG_EVENT_POINTER_MOTION: + printf("pointer motion x event received"); + break; + case BTK_LOG_EVENT_WINDOW_ENTER: + printf("pointer entered new window"); + break; + case BTK_LOG_EVENT_WINDOW_LEAVE: + printf("pointer left window"); + break; + case BTK_LOG_EVENT_CLIENT_MESSAGE: + printf("x client message received"); + break; + default: + break; + } + putchar('\n'); +} + +void +btk_log_error(unsigned int error_id) +{ + if (btk_log_level < 1) + return; + + printf("BTK -> \033[1;31mERROR\033[0m -> "); + switch (error_id) + { + case BTK_ERROR_X_CONNECTION: + printf("failed to connect to X"); + break; + case BTK_ERROR_X_SCREEN: + printf("failed to get display"); + break; + case BTK_ERROR_X_KEYSYMS: + printf("failed to get keysym table"); + break; + case BTK_ERROR_X_VISUAL: + printf("failed to get visual type"); + break; + default: + printf("generid error"); + break; + } + putchar('\n'); + exit(1); +} + +void +btk_log_warning(unsigned int warning_id) +{ + if (btk_log_level < 2) + return; + + printf("BTK -> \033[1;33mWARNING\033[0m -> "); + switch (warning_id) + { + case BTK_WARNING_WINDOW_GET: + printf("couldn't match x window id to btk window"); + break; + case BTK_WARNING_EMPTY_LOOP: + printf("no windows in the event loop"); + break; + case BTK_WARNING_DRAW_NO_FIELD: + printf("attempted to draw a field type without a field"); + break; + case BTK_WARNING_OUT_OF_BOUND_CELL: + printf("attempted to draw a non exisiting cell"); + break; + case BTK_WARNING_WINDOW_DESTROY: + printf("attempted to destroy NULL window"); + break; + default: + break; + } + putchar('\n'); +} diff --git a/btk/btk-log.h b/btk/btk-log.h new file mode 100644 index 0000000..99e44b6 --- /dev/null +++ b/btk/btk-log.h @@ -0,0 +1,42 @@ +enum btk_error { + BTK_ERROR_X_CONNECTION, + BTK_ERROR_X_SCREEN, + BTK_ERROR_X_KEYSYMS, + BTK_ERROR_X_VISUAL +}; + +enum btk_warning { + BTK_WARNING_WINDOW_GET, + BTK_WARNING_EMPTY_LOOP, + BTK_WARNING_DRAW_NO_FIELD, + BTK_WARNING_OUT_OF_BOUND_CELL, + BTK_WARNING_WINDOW_DESTROY +}; + +enum btk_log { + BTK_LOG_SESSION_CLOSE, + BTK_LOG_SESSION_OPEN, + BTK_LOG_GENERIC_EVENT_NOTIFY , + BTK_LOG_EVENT_LOOP_IN, + BTK_LOG_EVENT_LOOP_OUT, + BTK_LOG_WINDOW_MAP, + BTK_LOG_WINDOW_UNMAP, + BTK_LOG_WINDOW_CREATE, + BTK_LOG_WINDOW_DESTROY, + BTK_LOG_WINDOW_RENAME, + BTK_LOG_WINDOW_RESIZE, + BTK_LOG_EVENT_EXPOSE, + BTK_LOG_EVENT_BUTTON_PRESS, + BTK_LOG_EVENT_BUTTON_RELEASE, + BTK_LOG_EVENT_BUTTON_COMBO, + BTK_LOG_EVENT_BUTTON_COMBO_BREAK, + BTK_LOG_EVENT_KEY_PRESS, + BTK_LOG_EVENT_POINTER_MOTION, + BTK_LOG_EVENT_WINDOW_ENTER, + BTK_LOG_EVENT_WINDOW_LEAVE, + BTK_LOG_EVENT_CLIENT_MESSAGE +}; + +void btk_log (unsigned int); +void btk_log_error (unsigned int); +void btk_log_warning (unsigned int); diff --git a/btk/btk-text.c b/btk/btk-text.c new file mode 100644 index 0000000..ded017c --- /dev/null +++ b/btk/btk-text.c @@ -0,0 +1,300 @@ +#include +#include +#include + +#include "btk-text.h" + +/* mode for difference between backspace and del */ +/* mode == 0 : backspace; mode == 1 : del */ +int +btk_text_del_char(char *dest, int pos, int mode) +{ + int dest_n = strlen(dest); + + if (mode && !(dest_n - pos)) + return 0; + if (!mode && !pos) + return 0; + + for (int i = pos - 1 + mode; i < dest_n; i++) + dest[i] = dest [i + 1]; + + return 1; +} + +int +btk_text_insert_char(char *dest, char src, int pos, int max_w) +{ + int dest_n = strlen(dest); + + if (dest_n >= max_w - 1) + return 0; + + for (int i = dest_n; i >= pos; i--) + dest[i + 1] = dest[i]; + dest[pos] = src; + + return 1; +} + +/***************************************************************************************/ + +btk_pos_t +btk_text_caret_1dto2d(btk_par_t *par, int caret) +{ + int c = caret; + btk_pos_t pos = {0, 0}; + + if (caret <= 0) + return pos; + + /* add previous rows qtt */ + for (int i = 0; i < par->rows_n; i++) { + if (c >= par->rows_w[i]) { + c -= par->rows_w[i]; + } else { + pos.y = i; + break; + } + } + + /* compensation for indentation at the beginning of row*/ + if (*(par->rows_shadow + pos.y * par->rows_max_w) == 's') + while (*(par->rows_shadow + pos.y * par->rows_max_w + pos.x) == 's') + pos.x++; + + /* add current row qtt */ + for (int i = 0; i < c; i++) { + pos.x++; + while (*(par->rows_shadow + pos.y * par->rows_max_w + pos.x) == 's') + pos.x++; + } + + return pos; +} + +int +btk_text_caret_2dto1d(btk_par_t *par, btk_pos_t pos) +{ + int caret = 0; + + for (int i = 0; i < pos.y; i++) + caret += par->rows_w[i]; + + for (int i = 0; i < pos.x; i++) + if (*(par->rows_shadow + pos.y * par->rows_max_w + i) != 's') + caret++; + + return caret; +} + +void +btk_text_destroy_par(btk_par_t *par) +{ + if (!par) + return; + + free(par->rows); + free(par->rows_shadow); + free(par->rows_spot); + free(par->rows_w); + free(par); +} + +btk_par_t* +btk_text_get_par(char *text, unsigned int rows_max_w) +{ + if (!text || !rows_max_w) { + return NULL; + } + + int text_n = strlen(text); + int buffer_n = 1; + + btk_par_t *par = malloc(sizeof(btk_par_t)); + par->rows_n = 0; + par->rows_max_w = rows_max_w; + par->rows = malloc(buffer_n * rows_max_w); + par->rows_shadow = malloc(buffer_n * rows_max_w); + par->rows_spot = malloc(buffer_n * sizeof(int)); + par->rows_w = malloc(buffer_n * sizeof(int)); + + par->rows_w[0] = 0; + + int pos = 0; + int a = 0, b = 0; + int first = 1; + int indent = 0; + int cl = 0, cr = 0; + for (int i = 0;; i++) { + + /* set base row indentation level */ + if (!pos) { + b = indent >= rows_max_w ? rows_max_w : indent; + for (int j = 0; j < b; j++, pos++) { + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; + } + } + + par->rows_w[par->rows_n]++; + switch(text[i]) { + + case '\0': + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 'e'; + pos++; + cr = 1; + goto row_end; + + case '\n': + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 'n'; + pos++; + cr = 1; + goto row_end; + + case '\t': + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 't'; + a = btk_tab_size - pos % (btk_tab_size); + b = pos + a >= rows_max_w - 1 ? rows_max_w - 1 : pos + a; + pos++; + for (int j = pos; j < b; j++, pos++) { + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; + } + if (first) + indent += btk_tab_size; + if (b == rows_max_w - 1) + goto row_end; + break; + + case '>': + if (!first) + goto char_input; + cl = 1; + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = '>'; + pos++; + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; + pos++; + par->rows[pos + par->rows_n * rows_max_w] = '>'; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; + pos++; + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; + pos++; + indent += 4; + first = 0; + break; + + case '-': + if (!first) + goto char_input; + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = '-'; + pos++; + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; + pos++; + par->rows[pos + par->rows_n * rows_max_w] = '-'; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; + pos++; + par->rows[pos + par->rows_n * rows_max_w] = ' '; + par->rows_shadow[pos + par->rows_n * rows_max_w] = 's'; + pos++; + indent += 4; + first = 0; + break; + + case '#': + cl = first ? 2 : cl; + goto char_input; + + case '!': + cl = first ? 4 : cl; + goto char_input; + + default: +char_input: + par->rows[pos + par->rows_n * rows_max_w] = text[i]; + par->rows_shadow[pos + par->rows_n * rows_max_w] = '_'; + pos++; + first = 0; + break; + } + + if (pos >= rows_max_w - 1 || i == text_n) { +row_end: + par->rows[pos + par->rows_n * rows_max_w] = '\0'; + par->rows_shadow[pos + par->rows_n * rows_max_w] = '\0'; + par->rows_spot[par->rows_n] = cl; + par->rows_n++; + pos = 0; + if (cr) { + cr = 0; + cl = 0; + indent = 0; + first = 1; + } + par->rows_w[par->rows_n] = 0; + if (text[i] == '\0') + break; + } + + if (par->rows_n >= buffer_n - 1) { + buffer_n += 1; + par->rows = realloc(par->rows, buffer_n * rows_max_w); + par->rows_shadow = realloc(par->rows_shadow, buffer_n * rows_max_w); + par->rows_spot = realloc(par->rows_spot, buffer_n * sizeof(int)); + par->rows_w = realloc(par->rows_w, buffer_n * sizeof(int)); + } + } + + /* + printf("%i rows :\n", par->rows_n); + for (int i = 0; i < par->rows_n; i++) + printf("row %i\n", par->rows_w[i]); + printf("\n"); + */ + + return par; +} + +int +btk_text_guard_1d_caret(char *text, int caret) +{ + int new_caret = caret; + int text_n = strlen(text); + + if (new_caret < 0) + new_caret = 0; + if (new_caret > text_n) + new_caret = text_n; + + return new_caret; +} + + +btk_pos_t +btk_text_guard_2d_caret(btk_par_t *par, btk_pos_t pos) +{ + btk_pos_t new_pos = pos; + if (new_pos.y <= 0) + new_pos.y = 0; + if (new_pos.y >= par->rows_n) + new_pos.y = par->rows_n - 1; + + if (new_pos.x < 0) + new_pos.x = 0; + if (new_pos.x > strlen(par->rows + new_pos.y * par->rows_max_w) - 1) + new_pos.x = strlen(par->rows + new_pos.y * par->rows_max_w) - 1; + /*if (new_pos.x > par->rows_w[new_pos.y] - 1) + new_pos.x = par->rows_w[new_pos.y] - 1;*/ + while (*(par->rows_shadow + pos.y * par->rows_max_w + new_pos.x) == 's') + new_pos.x++; + + return new_pos; +} diff --git a/btk/btk-text.h b/btk/btk-text.h new file mode 100644 index 0000000..8e23216 --- /dev/null +++ b/btk/btk-text.h @@ -0,0 +1,20 @@ +#include "btk-config.h" + +typedef struct { + int rows_n; + int rows_max_w; + char *rows; + char *rows_shadow; + int *rows_spot; + int *rows_w; +} btk_par_t; + +int btk_text_del_char (char *, int, int); +int btk_text_insert_char (char *, char, int, int); + +btk_pos_t btk_text_caret_1dto2d (btk_par_t *, int); +int btk_text_caret_2dto1d (btk_par_t *, btk_pos_t); +void btk_text_destroy_par (btk_par_t *); +btk_par_t* btk_text_get_par (char *, unsigned int); +int btk_text_guard_1d_caret (char *, int); +btk_pos_t btk_text_guard_2d_caret (btk_par_t *, btk_pos_t);