From c2c887f6c6cd7dbdbce04ed63576c1f20aae3c27 Mon Sep 17 00:00:00 2001 From: seleznevae Date: Sat, 10 Nov 2018 09:58:21 +0300 Subject: [PATCH] [A] Added text styles --- lib/fort.c | 626 ++++++++++++++++++++++--- lib/fort.h | 41 ++ src/cell.c | 197 ++++++-- src/cell.h | 2 +- src/fort_impl.c | 4 +- src/fort_utils.c | 40 +- src/fort_utils.h | 16 +- src/properties.c | 298 +++++++++++- src/properties.h | 18 + src/string_buffer.c | 32 +- src/string_buffer.h | 6 +- src/table.c | 9 +- src/table.h | 4 +- tests/bb_tests/test_table_properties.c | 357 ++++++++++++++ tests/main_test.c | 146 +++++- tests/tests.h | 1 + 16 files changed, 1648 insertions(+), 149 deletions(-) diff --git a/lib/fort.c b/lib/fort.c index b597f83..e9f7e19 100644 --- a/lib/fort.c +++ b/lib/fort.c @@ -142,15 +142,16 @@ typedef struct fort_row fort_row_t; /*typedef struct ft_table ft_table_t;*/ typedef struct separator separator_t; - - - enum CellType { CommonCell, GroupMasterCell, GroupSlaveCell }; +enum request_geom_type { + VISIBLE_GEOMETRY, + INTERN_REPR_GEOMETRY +}; /***************************************************************************** * LIBFORT helpers @@ -182,6 +183,15 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str); written += tmp; \ } while(0) +#define CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(statement) \ + do { \ + tmp = statement; \ + if (tmp < 0) {\ + goto clear; \ + } \ + invisible_written += tmp; \ + } while(0) + #define CHECK_NOT_NEGATIVE(x) \ do { if (x < 0) goto fort_fail; } while (0) @@ -339,11 +349,13 @@ FT_INTERNAL size_t buffer_text_width(string_buffer_t *buffer); FT_INTERNAL -int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t buf_len, const context_t *context); +int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t total_buf_len, + const context_t *context, const char *content_style_tag, const char *reset_content_style_tag); #ifdef FT_HAVE_WCHAR FT_INTERNAL -int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t buf_len, const context_t *context); +int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t total_buf_len, + const context_t *context, const char *content_style_tag, const char *reset_content_style_tag); #endif /* FT_HAVE_WCHAR */ #endif /* STRING_BUFFER_H */ @@ -368,6 +380,19 @@ int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, siz #define PROP_SET(ft_props, property) ((ft_props) |=(property)) #define PROP_UNSET(ft_props, property) ((ft_props) &= ~((uint32_t)property)) +#define TEXT_STYLE_TAG_MAX_SIZE 64 + +void get_style_tag_for_cell(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz); +void get_reset_style_tag_for_cell(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz); + +void get_style_tag_for_content(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz); +void get_reset_style_tag_for_content(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz); + + struct fort_cell_props { size_t cell_row; size_t cell_col; @@ -380,6 +405,11 @@ struct fort_cell_props { unsigned int cell_padding_right; unsigned int cell_empty_string_height; enum ft_row_type row_type; + unsigned int content_fg_color_number; + unsigned int content_bg_color_number; + unsigned int cell_bg_color_number; + unsigned int cell_text_style; + unsigned int content_text_style; }; typedef struct fort_cell_props fort_cell_props_t; @@ -561,7 +591,7 @@ FT_INTERNAL fort_cell_t *copy_cell(fort_cell_t *cell); FT_INTERNAL -size_t hint_width_cell(const fort_cell_t *cell, const context_t *context); +size_t hint_width_cell(const fort_cell_t *cell, const context_t *context, enum request_geom_type geom); FT_INTERNAL size_t hint_height_cell(const fort_cell_t *cell, const context_t *context); @@ -730,10 +760,12 @@ fort_row_t *get_row_and_create_if_not_exists(ft_table_t *table, size_t row); FT_INTERNAL string_buffer_t *get_cur_str_buffer_and_create_if_not_exists(ft_table_t *table); + FT_INTERNAL fort_status_t table_rows_and_cols_geometry(const ft_table_t *table, size_t **col_width_arr_p, size_t *col_width_arr_sz, - size_t **row_height_arr_p, size_t *row_height_arr_sz); + size_t **row_height_arr_p, size_t *row_height_arr_sz, + enum request_geom_type geom); FT_INTERNAL fort_status_t table_geometry(const ft_table_t *table, size_t *height, size_t *width); @@ -749,11 +781,258 @@ fort_status_t table_geometry(const ft_table_t *table, size_t *height, size_t *wi Begin of file "properties.c" ********************************************************/ +/* #include "fort_utils.h" */ /* Commented by amalgamation script */ #include /* #include "properties.h" */ /* Commented by amalgamation script */ -/* #include "fort_utils.h" */ /* Commented by amalgamation script */ /* #include "vector.h" */ /* Commented by amalgamation script */ +#define FT_RESET_COLOR "\033[0m" + +const char *fg_colors[] = { + "", + "\033[30m", + "\033[31m", + "\033[32m", + "\033[33m", + "\033[34m", + "\033[35m", + "\033[36m", + "\033[37m", + "\033[90m", + "\033[91m", + "\033[92m", + "\033[93m", + "\033[94m", + "\033[95m", + "\033[96m", + "\033[97m", +}; + +const char *reset_fg_colors[] = { + "", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", +}; + +const char *bg_colors[] = { + "", + "\033[40m", + "\033[41m", + "\033[42m", + "\033[43m", + "\033[44m", + "\033[45m", + "\033[46m", + "\033[47m", + "\033[100m", + "\033[101m", + "\033[102m", + "\033[103m", + "\033[104m", + "\033[105m", + "\033[106m", + "\033[107m", +}; + +const char *reset_bg_colors[] = { + "", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", +}; + + +const char *text_styles[] = { + "", + "\033[1m", + "\033[2m", + "\033[4m", + "\033[5m", + "\033[7m", + "\033[8m", +}; + +const char *reset_text_styles[] = { + "", + "\033[21m", + "\033[22m", + "\033[24m", + "\033[25m", + "\033[27m", + "\033[28m", +}; + + +static const size_t n_fg_colors = sizeof(fg_colors) / sizeof(fg_colors[0]); +static const size_t n_bg_colors = sizeof(bg_colors) / sizeof(bg_colors[0]); +static const size_t n_styles = sizeof(text_styles) / sizeof(text_styles[0]); + +void get_style_tag_for_cell(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz) +{ + (void)sz; + + unsigned bg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CELL_BG_COLOR); + unsigned text_style = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CELL_TEXT_STYLE); + + style_tag[0] = '\0'; + + if (text_style < n_styles) { + strcat(style_tag, text_styles[text_style]); + } else { + goto error; + } + + if (bg_color_number < n_bg_colors) { + strcat(style_tag, bg_colors[bg_color_number]); + } else { + goto error; + } + + return; + +error: + // shouldn't be here + assert(0); + style_tag[0] = '\0'; + return; +} + +void get_reset_style_tag_for_cell(const fort_table_properties_t *props, + size_t row, size_t col, char *reset_style_tag, size_t sz) +{ + (void)sz; + + unsigned bg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CELL_BG_COLOR); + unsigned text_style = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CELL_TEXT_STYLE); + + reset_style_tag[0] = '\0'; + + if (text_style < n_styles) { + strcat(reset_style_tag, reset_text_styles[text_style]); + } else { + goto error; + } + + if (bg_color_number < n_bg_colors) { + strcat(reset_style_tag, reset_bg_colors[bg_color_number]); + } else { + goto error; + } + + return; + +error: + // shouldn't be here + assert(0); + reset_style_tag[0] = '\0'; + return; +} + + +void get_style_tag_for_content(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz) +{ + (void)sz; + + unsigned text_style = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_TEXT_STYLE); + unsigned fg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_FG_COLOR); + unsigned bg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_BG_COLOR); + + style_tag[0] = '\0'; + + if (text_style < n_styles) { + strcat(style_tag, text_styles[text_style]); + } else { + goto error; + } + + if (fg_color_number < n_fg_colors) { + strcat(style_tag, fg_colors[fg_color_number]); + } else { + goto error; + } + + if (bg_color_number < n_bg_colors) { + strcat(style_tag, bg_colors[bg_color_number]); + } else { + goto error; + } + + return; + +error: + // shouldn't be here + assert(0); + style_tag[0] = '\0'; + return; +} + +void get_reset_style_tag_for_content(const fort_table_properties_t *props, + size_t row, size_t col, char *reset_style_tag, size_t sz) +{ + (void)sz; + + unsigned text_style = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_TEXT_STYLE); + unsigned fg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_FG_COLOR); + unsigned bg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_BG_COLOR); + + reset_style_tag[0] = '\0'; + + if (text_style < n_styles) { + strcat(reset_style_tag, reset_text_styles[text_style]); + } else { + goto error; + } + + if (fg_color_number < n_fg_colors) { + strcat(reset_style_tag, reset_fg_colors[fg_color_number]); + } else { + goto error; + } + + if (bg_color_number < n_bg_colors) { + strcat(reset_style_tag, reset_bg_colors[bg_color_number]); + } else { + goto error; + } + + return; + +error: + // shouldn't be here + assert(0); + reset_style_tag[0] = '\0'; + return; +} + /***************************************************************************** * COLUMN PROPERTIES * ***************************************************************************/ @@ -765,7 +1044,8 @@ struct fort_cell_props g_default_cell_properties = { /* properties */ FT_CPROP_MIN_WIDTH | FT_CPROP_TEXT_ALIGN | FT_CPROP_TOP_PADDING | FT_CPROP_BOTTOM_PADDING | FT_CPROP_LEFT_PADDING | FT_CPROP_RIGHT_PADDING - | FT_CPROP_EMPTY_STR_HEIGHT, + | FT_CPROP_EMPTY_STR_HEIGHT | FT_CPROP_CONT_FG_COLOR | FT_CPROP_CELL_BG_COLOR + | FT_CPROP_CONT_BG_COLOR | FT_CPROP_CELL_TEXT_STYLE | FT_CPROP_CONT_TEXT_STYLE, 0, /* col_min_width */ FT_ALIGNED_LEFT, /* align */ @@ -776,6 +1056,11 @@ struct fort_cell_props g_default_cell_properties = { 1, /* cell_empty_string_height */ FT_ROW_COMMON, /* row_type */ + FT_COLOR_DEFAULT, /* content_fg_color_number */ + FT_COLOR_DEFAULT, /* content_bg_color_number */ + FT_COLOR_DEFAULT, /* cell_bg_color_number */ + FT_TSTYLE_DEFAULT, /* cell_text_style */ + FT_TSTYLE_DEFAULT, /* content_text_style */ }; static int get_prop_value_if_exists_otherwise_default(const struct fort_cell_props *cell_opts, uint32_t property) @@ -801,6 +1086,16 @@ static int get_prop_value_if_exists_otherwise_default(const struct fort_cell_pro return cell_opts->cell_empty_string_height; case FT_CPROP_ROW_TYPE: return cell_opts->row_type; + case FT_CPROP_CONT_FG_COLOR: + return cell_opts->content_fg_color_number; + case FT_CPROP_CONT_BG_COLOR: + return cell_opts->content_bg_color_number; + case FT_CPROP_CELL_BG_COLOR: + return cell_opts->cell_bg_color_number; + case FT_CPROP_CELL_TEXT_STYLE: + return cell_opts->cell_text_style; + case FT_CPROP_CONT_TEXT_STYLE: + return cell_opts->content_text_style; default: /* todo: implement later */ exit(333); @@ -871,6 +1166,7 @@ FT_INTERNAL int get_cell_property_value_hierarcial(const fort_table_properties_t *propertiess, size_t row, size_t column, uint32_t property) { assert(propertiess); + size_t row_origin = row; const fort_cell_props_t *opt = NULL; if (propertiess->cell_properties != NULL) { @@ -878,15 +1174,29 @@ int get_cell_property_value_hierarcial(const fort_table_properties_t *properties opt = cget_cell_prop(propertiess->cell_properties, row, column); if (opt != NULL && PROP_IS_SET(opt->properties, property)) break; - if (row != FT_ANY_ROW) { + + if (row != FT_ANY_ROW && column != FT_ANY_COLUMN) { row = FT_ANY_ROW; continue; - } - if (column != FT_ANY_COLUMN) { + } else if (row == FT_ANY_ROW && column != FT_ANY_COLUMN) { + row = row_origin; + column = FT_ANY_COLUMN; + continue; + } else if (row != FT_ANY_ROW && column == FT_ANY_COLUMN) { + row = FT_ANY_ROW; column = FT_ANY_COLUMN; continue; } +// if (row != FT_ANY_ROW) { +// row = FT_ANY_ROW; +// continue; +// } +// if (column != FT_ANY_COLUMN) { +// column = FT_ANY_COLUMN; +// continue; +// } + opt = NULL; break; } @@ -923,6 +1233,16 @@ static fort_status_t set_cell_property_impl(fort_cell_props_t *opt, uint32_t pro opt->cell_empty_string_height = value; } else if (PROP_IS_SET(property, FT_CPROP_ROW_TYPE)) { opt->row_type = (enum ft_row_type)value; + } else if (PROP_IS_SET(property, FT_CPROP_CONT_FG_COLOR)) { + opt->content_fg_color_number = value; + } else if (PROP_IS_SET(property, FT_CPROP_CONT_BG_COLOR)) { + opt->content_bg_color_number = value; + } else if (PROP_IS_SET(property, FT_CPROP_CELL_BG_COLOR)) { + opt->cell_bg_color_number = value; + } else if (PROP_IS_SET(property, FT_CPROP_CELL_TEXT_STYLE)) { + opt->cell_text_style = value; + } else if (PROP_IS_SET(property, FT_CPROP_CONT_TEXT_STYLE)) { + opt->content_text_style = value; } return FT_SUCCESS; @@ -1569,7 +1889,8 @@ fort_status_t get_table_sizes(const ft_table_t *table, size_t *rows, size_t *col FT_INTERNAL fort_status_t table_rows_and_cols_geometry(const ft_table_t *table, size_t **col_width_arr_p, size_t *col_width_arr_sz, - size_t **row_height_arr_p, size_t *row_height_arr_sz) + size_t **row_height_arr_p, size_t *row_height_arr_sz, + enum request_geom_type geom) { if (table == NULL) { return FT_ERROR; @@ -1606,7 +1927,7 @@ fort_status_t table_rows_and_cols_geometry(const ft_table_t *table, if (cell) { switch (get_cell_type(cell)) { case CommonCell: - col_width_arr[col] = MAX(col_width_arr[col], hint_width_cell(cell, &context)); + col_width_arr[col] = MAX(col_width_arr[col], hint_width_cell(cell, &context, geom)); break; case GroupMasterCell: combined_cells_found = 1; @@ -1631,7 +1952,7 @@ fort_status_t table_rows_and_cols_geometry(const ft_table_t *table, context.row = row; if (cell) { if (get_cell_type(cell) == GroupMasterCell) { - size_t hint_width = hint_width_cell(cell, &context); + size_t hint_width = hint_width_cell(cell, &context, geom); size_t slave_col = col + group_cell_number(row_p, col); size_t cur_adj_col = col; size_t group_width = col_width_arr[col]; @@ -1690,7 +2011,7 @@ fort_status_t table_geometry(const ft_table_t *table, size_t *height, size_t *wi size_t *col_width_arr = NULL; size_t *row_height_arr = NULL; - int status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); + int status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows, INTERN_REPR_GEOMETRY); if (FT_IS_ERROR(status)) return status; @@ -2347,7 +2668,7 @@ const char *ft_to_string(const ft_table_t *table) size_t rows = 0; size_t *col_width_arr = NULL; size_t *row_height_arr = NULL; - status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); + status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows, VISIBLE_GEOMETRY); if (FT_IS_ERROR(status)) return NULL; @@ -2451,7 +2772,7 @@ const wchar_t *ft_to_wstring(const ft_table_t *table) size_t rows = 0; size_t *col_width_arr = NULL; size_t *row_height_arr = NULL; - status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); + status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows, VISIBLE_GEOMETRY); if (rows == 0) return EMPTY_STRING; @@ -3353,7 +3674,8 @@ size_t buffer_text_width(string_buffer_t *buffer) FT_INTERNAL -int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t buf_len, const context_t *context) +int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t total_buf_len, + const context_t *context, const char *content_style_tag, const char *reset_content_style_tag) { #define CHAR_TYPE char #define NULL_CHAR '\0' @@ -3367,6 +3689,8 @@ int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t #define STR_N_SUBSTRING str_n_substring #define STR_ITER_WIDTH str_iter_width + size_t buf_len = total_buf_len - strlen(content_style_tag) - strlen(reset_content_style_tag); + if (buffer == NULL || buffer->str.data == NULL || buffer_row >= buffer_text_height(buffer) || buf_len == 0) { return -1; @@ -3404,7 +3728,7 @@ int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t const CHAR_TYPE *end = NULL; CHAR_TYPE old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, left, SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, left, SPACE_CHAR)); STR_N_SUBSTRING(buffer->BUFFER_STR, NEWLINE_CHAR, buffer_row, &beg, &end); if (beg == NULL || end == NULL) @@ -3416,10 +3740,13 @@ int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t if (str_it_width < 0 || content_width < (size_t)str_it_width) return - 1; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, 1, content_style_tag)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, total_buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, 1, reset_content_style_tag)); + *(CHAR_TYPE *)end = old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, right, SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, right, SPACE_CHAR)); return written; clear: @@ -3441,7 +3768,8 @@ clear: #ifdef FT_HAVE_WCHAR FT_INTERNAL -int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t buf_len, const context_t *context) +int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t total_buf_len, + const context_t *context, const char *content_style_tag, const char *reset_content_style_tag) { #define CHAR_TYPE wchar_t #define NULL_CHAR L'\0' @@ -3455,6 +3783,8 @@ int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, siz #define STR_N_SUBSTRING wstr_n_substring #define STR_ITER_WIDTH wcs_iter_width + size_t buf_len = total_buf_len - strlen(content_style_tag) - strlen(reset_content_style_tag); + if (buffer == NULL || buffer->str.data == NULL || buffer_row >= buffer_text_height(buffer) || buf_len == 0) { return -1; @@ -3492,7 +3822,7 @@ int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, siz const CHAR_TYPE *end = NULL; CHAR_TYPE old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, left, SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, left, SPACE_CHAR)); STR_N_SUBSTRING(buffer->BUFFER_STR, NEWLINE_CHAR, buffer_row, &beg, &end); if (beg == NULL || end == NULL) @@ -3504,10 +3834,13 @@ int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, siz if (str_it_width < 0 || content_width < (size_t)str_it_width) return - 1; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, 1, content_style_tag)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, total_buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, 1, reset_content_style_tag)); + *(CHAR_TYPE *)end = old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, right, SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, right, SPACE_CHAR)); return written; clear: @@ -3752,6 +4085,9 @@ int snprint_n_strings(char *buf, size_t length, size_t n, const char *str) if (n * str_len > INT_MAX) return -1; + if (str_len == 0) + return 0; + int status = snprintf(buf, length, "%0*d", (int)(n * str_len), 0); if (status < 0) return status; @@ -3797,8 +4133,36 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str) /* This function doesn't work properly with multibyte characters * so it is better return an error in this case */ - if (str_len > 1) - return -1; + if (str_len > 1) { + const unsigned char *p = (const unsigned char *)str; + while (*p) { + if (*p <= 127) + p++; + else { + const int SIZE = 64; + wchar_t wcs[SIZE]; + const char *ptr = str; + int length; + length = mbsrtowcs(wcs, (const char **)&ptr, SIZE, NULL); + wcs[length] = L'\0'; + if (length > 1) { + return -1; + } else { + swprintf(buf, length, L"%0*d", (int)(n * str_len), 0); + int k = n; + while (k) { + *buf = *wcs; + ++buf; + --k; + } + buf[n] = L'\0'; + return n; + } + +// return -1; + } + } + } if (length <= n * str_len) return -1; @@ -3806,12 +4170,13 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str) if (n == 0) return 0; - - /* To ensure valid return value it is safely not print such big strings */ if (n * str_len > INT_MAX) return -1; + if (str_len == 0) + return 0; + int status = swprintf(buf, length, L"%0*d", (int)(n * str_len), 0); if (status < 0) return status; @@ -5245,9 +5610,8 @@ enum CellType get_cell_type(const fort_cell_t *cell) return cell->cell_type; } - FT_INTERNAL -size_t hint_width_cell(const fort_cell_t *cell, const context_t *context) +size_t hint_width_cell(const fort_cell_t *cell, const context_t *context, enum request_geom_type geom) { /* todo: * At the moment min width includes paddings. Maybe it is better that min width weren't include @@ -5263,6 +5627,25 @@ size_t hint_width_cell(const fort_cell_t *cell, const context_t *context) result += buffer_text_width(cell->str_buffer); } result = MAX(result, (size_t)get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_MIN_WIDTH)); + + if (geom == INTERN_REPR_GEOMETRY) { + char cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_cell(context->table_properties, context->row, context->column, cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + result += strlen(cell_style_tag); + + char reset_cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_cell(context->table_properties, context->row, context->column, reset_cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + result += strlen(reset_cell_style_tag); + + char content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_content(context->table_properties, context->row, context->column, content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + result += strlen(content_style_tag); + + char reset_content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_content(context->table_properties, context->row, context->column, reset_content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + result += strlen(reset_content_style_tag); + } + return result; } @@ -5287,14 +5670,12 @@ FT_INTERNAL int cell_printf(fort_cell_t *cell, size_t row, char *buf, size_t buf_len, const context_t *context) { const char *space_char = " "; - int (*buffer_printf_)(string_buffer_t *, size_t, char *, size_t, const context_t *) = buffer_printf; + int (*buffer_printf_)(string_buffer_t *, size_t, char *, size_t, const context_t *, const char *, const char *) = buffer_printf; // int (*snprint_n_chars_)(char *, size_t, size_t, char) = snprint_n_chars; int (*snprint_n_strings_)(char *, size_t, size_t, const char *) = snprint_n_strings; - - if (cell == NULL || buf_len == 0 - || (buf_len <= hint_width_cell(cell, context))) { + || (buf_len <= hint_width_cell(cell, context, VISIBLE_GEOMETRY))) { return -1; } @@ -5302,30 +5683,83 @@ int cell_printf(fort_cell_t *cell, size_t row, char *buf, size_t buf_len, const unsigned int cell_padding_left = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_LEFT_PADDING); unsigned int cell_padding_right = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_RIGHT_PADDING); + int written = 0; + int invisible_written = 0; + int tmp = 0; +// int left = cell_padding_left; +// int right = cell_padding_right; + + /* todo: Dirty hack with changing buf_len! need refactoring. */ + /* Also maybe it is better to move all struff with colors to buffers? */ + char cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_cell(context->table_properties, context->row, context->column, cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(cell_style_tag); + + char reset_cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_cell(context->table_properties, context->row, context->column, reset_cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(reset_cell_style_tag); + + char content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_content(context->table_properties, context->row, context->column, content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(content_style_tag); + + char reset_content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_content(context->table_properties, context->row, context->column, reset_content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(reset_content_style_tag); + + /* CELL_STYLE_T LEFT_PADDING CONTENT_STYLE_T CONTENT RESET_CONTENT_STYLE_T RIGHT_PADDING RESET_CELL_STYLE_T + * | | | | | | | | + * L1 R1 + * L2 R2 + * L3 R3 + */ + + size_t L2 = cell_padding_left; + + size_t R2 = cell_padding_right; + size_t R3 = strlen(reset_cell_style_tag); + +#define TOTAL_WRITTEN (written + invisible_written) +#define RIGHT (cell_padding_right + extra_right) + +#define WRITE_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, cell_style_tag)) +#define WRITE_RESET_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, reset_cell_style_tag)) +#define WRITE_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, content_style_tag)) +#define WRITE_RESET_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, reset_content_style_tag)) + if (row >= hint_height_cell(cell, context) || row < cell_padding_top || row >= (cell_padding_top + buffer_text_height(cell->str_buffer))) { - return snprint_n_strings_(buf, buf_len, buf_len - 1, space_char); + WRITE_CELL_STYLE_TAG; + WRITE_CONTENT_STYLE_TAG; + WRITE_RESET_CONTENT_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len, buf_len - 1 - TOTAL_WRITTEN - R3, space_char)); + WRITE_RESET_CELL_STYLE_TAG; + return TOTAL_WRITTEN; } + WRITE_CELL_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, L2, space_char)); + if (cell->str_buffer) { + CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf_(cell->str_buffer, row - cell_padding_top, buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN - R2 - R3, context, content_style_tag, reset_content_style_tag)); + } else { + WRITE_CONTENT_STYLE_TAG; + WRITE_RESET_CONTENT_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN - R2 - R3, space_char)); + } + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, R2, space_char)); + WRITE_RESET_CELL_STYLE_TAG; - int written = 0; - int tmp = 0; - int left = cell_padding_left; - int right = cell_padding_right; - - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, left, space_char)); - - if (cell->str_buffer) - CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf_(cell->str_buffer, row - cell_padding_top, buf + written, buf_len - written - right, context)); - else - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, buf_len - written - right, space_char)); - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, right, space_char)); - - return written; + return TOTAL_WRITTEN; clear: return -1; +#undef WRITE_CELL_STYLE_TAG +#undef WRITE_RESET_CELL_STYLE_TAG +#undef WRITE_CONTENT_STYLE_TAG +#undef WRITE_RESET_CONTENT_STYLE_TAG +#undef TOTAL_WRITTEN +#undef RIGHT } #ifdef FT_HAVE_WCHAR @@ -5333,14 +5767,12 @@ FT_INTERNAL int cell_wprintf(fort_cell_t *cell, size_t row, wchar_t *buf, size_t buf_len, const context_t *context) { const char *space_char = " "; - int (*buffer_printf_)(string_buffer_t *, size_t, wchar_t *, size_t, const context_t *) = buffer_wprintf; + int (*buffer_printf_)(string_buffer_t *, size_t, wchar_t *, size_t, const context_t *, const char *, const char *) = buffer_wprintf; // int (*snprint_n_chars_)(wchar_t *, size_t, size_t, wchar_t) = wsnprint_n_chars; int (*snprint_n_strings_)(wchar_t *, size_t, size_t, const char *) = wsnprint_n_string; - - if (cell == NULL || buf_len == 0 - || (buf_len <= hint_width_cell(cell, context))) { + || (buf_len <= hint_width_cell(cell, context, VISIBLE_GEOMETRY))) { return -1; } @@ -5348,29 +5780,81 @@ int cell_wprintf(fort_cell_t *cell, size_t row, wchar_t *buf, size_t buf_len, co unsigned int cell_padding_left = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_LEFT_PADDING); unsigned int cell_padding_right = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_RIGHT_PADDING); + int written = 0; + int invisible_written = 0; + int tmp = 0; + + /* todo: Dirty hack with changing buf_len! need refactoring. */ + /* Also maybe it is better to move all struff with colors to buffers? */ + char cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_cell(context->table_properties, context->row, context->column, cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(cell_style_tag); + + char reset_cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_cell(context->table_properties, context->row, context->column, reset_cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(reset_cell_style_tag); + + char content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_content(context->table_properties, context->row, context->column, content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(content_style_tag); + + char reset_content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_content(context->table_properties, context->row, context->column, reset_content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(reset_content_style_tag); + + /* CELL_STYLE_T LEFT_PADDING CONTENT_STYLE_T CONTENT RESET_CONTENT_STYLE_T RIGHT_PADDING RESET_CELL_STYLE_T + * | | | | | | | | + * L1 R1 + * L2 R2 + * L3 R3 + */ + + size_t L2 = cell_padding_left; + + size_t R2 = cell_padding_right; + size_t R3 = strlen(reset_cell_style_tag); + +#define TOTAL_WRITTEN (written + invisible_written) +#define RIGHT (right + extra_right) + +#define WRITE_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, cell_style_tag)) +#define WRITE_RESET_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, reset_cell_style_tag)) +#define WRITE_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, content_style_tag)) +#define WRITE_RESET_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, reset_content_style_tag)) + if (row >= hint_height_cell(cell, context) || row < cell_padding_top || row >= (cell_padding_top + buffer_text_height(cell->str_buffer))) { - return snprint_n_strings_(buf, buf_len, buf_len - 1, space_char); + WRITE_CELL_STYLE_TAG; + WRITE_CONTENT_STYLE_TAG; + WRITE_RESET_CONTENT_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len, buf_len - 1 - TOTAL_WRITTEN - R3, space_char)); + WRITE_RESET_CELL_STYLE_TAG; + return TOTAL_WRITTEN; } - int written = 0; - int tmp = 0; - int left = cell_padding_left; - int right = cell_padding_right; + WRITE_CELL_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, L2, space_char)); + if (cell->str_buffer) { + CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf_(cell->str_buffer, row - cell_padding_top, buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN - R2 - R3, context, content_style_tag, reset_content_style_tag)); + } else { + WRITE_CONTENT_STYLE_TAG; + WRITE_RESET_CONTENT_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN - R2 - R3, space_char)); + } + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, R2, space_char)); + WRITE_RESET_CELL_STYLE_TAG; - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, left, space_char)); - - if (cell->str_buffer) - CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf_(cell->str_buffer, row - cell_padding_top, buf + written, buf_len - written - right, context)); - else - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, buf_len - written - right, space_char)); - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, right, space_char)); - - return written; + return TOTAL_WRITTEN; clear: return -1; +#undef WRITE_CELL_STYLE_TAG +#undef WRITE_RESET_CELL_STYLE_TAG +#undef WRITE_CONTENT_STYLE_TAG +#undef WRITE_RESET_CONTENT_STYLE_TAG +#undef TOTAL_WRITTEN +#undef RIGHT } #endif diff --git a/lib/fort.h b/lib/fort.h index 7a93662..b83011f 100644 --- a/lib/fort.h +++ b/lib/fort.h @@ -683,9 +683,50 @@ int ft_set_border_style(ft_table_t *table, const struct ft_border_style *style); #define FT_CPROP_RIGHT_PADDING (0x01U << 5) /**< Right padding for cell content */ #define FT_CPROP_EMPTY_STR_HEIGHT (0x01U << 6) /**< Height of empty cell */ #define FT_CPROP_ROW_TYPE (0x01U << 7) /**< Row type */ +#define FT_CPROP_CONT_FG_COLOR (0x01U << 8) /**< Cell content foreground text color */ +#define FT_CPROP_CELL_BG_COLOR (0x01U << 9) /**< Cell background color */ +#define FT_CPROP_CONT_BG_COLOR (0x01U << 10) /**< Cell content background color */ +#define FT_CPROP_CELL_TEXT_STYLE (0x01U << 11) /**< Cell text style */ +#define FT_CPROP_CONT_TEXT_STYLE (0x01U << 12) /**< Cell content text style */ /** @} */ +/** + * @name Colors. + * @{ + */ +#define FT_COLOR_DEFAULT 0 +#define FT_COLOR_BLACK 1 +#define FT_COLOR_RED 2 +#define FT_COLOR_GREEN 3 +#define FT_COLOR_YELLOW 4 +#define FT_COLOR_BLUE 5 +#define FT_COLOR_MAGENTA 6 +#define FT_COLOR_CYAN 7 +#define FT_COLOR_LIGHT_GRAY 8 +#define FT_COLOR_DARK_GRAY 9 +#define FT_COLOR_LIGHT_RED 10 +#define FT_COLOR_LIGHT_GREEN 11 +#define FT_COLOR_LIGHT_YELLOW 12 +#define FT_COLOR_LIGHT_BLUE 13 +#define FT_COLOR_LIGHT_MAGENTA 15 +#define FT_COLOR_LIGHT_CYAN 16 +#define FT_COLOR_LIGHT_WHYTE 17 +/** @} */ + +/** + * @name Text styles. + * @{ + */ +#define FT_TSTYLE_DEFAULT 0 +#define FT_TSTYLE_BOLD 1 +#define FT_TSTYLE_DIM 2 +#define FT_TSTYLE_UNDERLINED 3 +#define FT_TSTYLE_BLINK 4 +#define FT_TSTYLE_INVERTED 5 +#define FT_TSTYLE_HIDDEN 6 +/** @} */ + /** * Alignment of cell content. diff --git a/src/cell.c b/src/cell.c index 9477630..8a06237 100644 --- a/src/cell.c +++ b/src/cell.c @@ -62,9 +62,8 @@ enum CellType get_cell_type(const fort_cell_t *cell) return cell->cell_type; } - FT_INTERNAL -size_t hint_width_cell(const fort_cell_t *cell, const context_t *context) +size_t hint_width_cell(const fort_cell_t *cell, const context_t *context, enum request_geom_type geom) { /* todo: * At the moment min width includes paddings. Maybe it is better that min width weren't include @@ -80,6 +79,25 @@ size_t hint_width_cell(const fort_cell_t *cell, const context_t *context) result += buffer_text_width(cell->str_buffer); } result = MAX(result, (size_t)get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_MIN_WIDTH)); + + if (geom == INTERN_REPR_GEOMETRY) { + char cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_cell(context->table_properties, context->row, context->column, cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + result += strlen(cell_style_tag); + + char reset_cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_cell(context->table_properties, context->row, context->column, reset_cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + result += strlen(reset_cell_style_tag); + + char content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_content(context->table_properties, context->row, context->column, content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + result += strlen(content_style_tag); + + char reset_content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_content(context->table_properties, context->row, context->column, reset_content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + result += strlen(reset_content_style_tag); + } + return result; } @@ -104,14 +122,12 @@ FT_INTERNAL int cell_printf(fort_cell_t *cell, size_t row, char *buf, size_t buf_len, const context_t *context) { const char *space_char = " "; - int (*buffer_printf_)(string_buffer_t *, size_t, char *, size_t, const context_t *) = buffer_printf; + int (*buffer_printf_)(string_buffer_t *, size_t, char *, size_t, const context_t *, const char *, const char *) = buffer_printf; // int (*snprint_n_chars_)(char *, size_t, size_t, char) = snprint_n_chars; int (*snprint_n_strings_)(char *, size_t, size_t, const char *) = snprint_n_strings; - - if (cell == NULL || buf_len == 0 - || (buf_len <= hint_width_cell(cell, context))) { + || (buf_len <= hint_width_cell(cell, context, VISIBLE_GEOMETRY))) { return -1; } @@ -119,30 +135,83 @@ int cell_printf(fort_cell_t *cell, size_t row, char *buf, size_t buf_len, const unsigned int cell_padding_left = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_LEFT_PADDING); unsigned int cell_padding_right = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_RIGHT_PADDING); + int written = 0; + int invisible_written = 0; + int tmp = 0; +// int left = cell_padding_left; +// int right = cell_padding_right; + + /* todo: Dirty hack with changing buf_len! need refactoring. */ + /* Also maybe it is better to move all struff with colors to buffers? */ + char cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_cell(context->table_properties, context->row, context->column, cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(cell_style_tag); + + char reset_cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_cell(context->table_properties, context->row, context->column, reset_cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(reset_cell_style_tag); + + char content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_content(context->table_properties, context->row, context->column, content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(content_style_tag); + + char reset_content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_content(context->table_properties, context->row, context->column, reset_content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(reset_content_style_tag); + + /* CELL_STYLE_T LEFT_PADDING CONTENT_STYLE_T CONTENT RESET_CONTENT_STYLE_T RIGHT_PADDING RESET_CELL_STYLE_T + * | | | | | | | | + * L1 R1 + * L2 R2 + * L3 R3 + */ + + size_t L2 = cell_padding_left; + + size_t R2 = cell_padding_right; + size_t R3 = strlen(reset_cell_style_tag); + +#define TOTAL_WRITTEN (written + invisible_written) +#define RIGHT (cell_padding_right + extra_right) + +#define WRITE_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, cell_style_tag)) +#define WRITE_RESET_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, reset_cell_style_tag)) +#define WRITE_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, content_style_tag)) +#define WRITE_RESET_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, reset_content_style_tag)) + if (row >= hint_height_cell(cell, context) || row < cell_padding_top || row >= (cell_padding_top + buffer_text_height(cell->str_buffer))) { - return snprint_n_strings_(buf, buf_len, buf_len - 1, space_char); + WRITE_CELL_STYLE_TAG; + WRITE_CONTENT_STYLE_TAG; + WRITE_RESET_CONTENT_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len, buf_len - 1 - TOTAL_WRITTEN - R3, space_char)); + WRITE_RESET_CELL_STYLE_TAG; + return TOTAL_WRITTEN; } + WRITE_CELL_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, L2, space_char)); + if (cell->str_buffer) { + CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf_(cell->str_buffer, row - cell_padding_top, buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN - R2 - R3, context, content_style_tag, reset_content_style_tag)); + } else { + WRITE_CONTENT_STYLE_TAG; + WRITE_RESET_CONTENT_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN - R2 - R3, space_char)); + } + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, R2, space_char)); + WRITE_RESET_CELL_STYLE_TAG; - int written = 0; - int tmp = 0; - int left = cell_padding_left; - int right = cell_padding_right; - - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, left, space_char)); - - if (cell->str_buffer) - CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf_(cell->str_buffer, row - cell_padding_top, buf + written, buf_len - written - right, context)); - else - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, buf_len - written - right, space_char)); - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, right, space_char)); - - return written; + return TOTAL_WRITTEN; clear: return -1; +#undef WRITE_CELL_STYLE_TAG +#undef WRITE_RESET_CELL_STYLE_TAG +#undef WRITE_CONTENT_STYLE_TAG +#undef WRITE_RESET_CONTENT_STYLE_TAG +#undef TOTAL_WRITTEN +#undef RIGHT } #ifdef FT_HAVE_WCHAR @@ -150,14 +219,12 @@ FT_INTERNAL int cell_wprintf(fort_cell_t *cell, size_t row, wchar_t *buf, size_t buf_len, const context_t *context) { const char *space_char = " "; - int (*buffer_printf_)(string_buffer_t *, size_t, wchar_t *, size_t, const context_t *) = buffer_wprintf; + int (*buffer_printf_)(string_buffer_t *, size_t, wchar_t *, size_t, const context_t *, const char *, const char *) = buffer_wprintf; // int (*snprint_n_chars_)(wchar_t *, size_t, size_t, wchar_t) = wsnprint_n_chars; int (*snprint_n_strings_)(wchar_t *, size_t, size_t, const char *) = wsnprint_n_string; - - if (cell == NULL || buf_len == 0 - || (buf_len <= hint_width_cell(cell, context))) { + || (buf_len <= hint_width_cell(cell, context, VISIBLE_GEOMETRY))) { return -1; } @@ -165,29 +232,81 @@ int cell_wprintf(fort_cell_t *cell, size_t row, wchar_t *buf, size_t buf_len, co unsigned int cell_padding_left = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_LEFT_PADDING); unsigned int cell_padding_right = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_RIGHT_PADDING); + int written = 0; + int invisible_written = 0; + int tmp = 0; + + /* todo: Dirty hack with changing buf_len! need refactoring. */ + /* Also maybe it is better to move all struff with colors to buffers? */ + char cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_cell(context->table_properties, context->row, context->column, cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(cell_style_tag); + + char reset_cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_cell(context->table_properties, context->row, context->column, reset_cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(reset_cell_style_tag); + + char content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_style_tag_for_content(context->table_properties, context->row, context->column, content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(content_style_tag); + + char reset_content_style_tag[TEXT_STYLE_TAG_MAX_SIZE]; + get_reset_style_tag_for_content(context->table_properties, context->row, context->column, reset_content_style_tag, TEXT_STYLE_TAG_MAX_SIZE); + buf_len += strlen(reset_content_style_tag); + + /* CELL_STYLE_T LEFT_PADDING CONTENT_STYLE_T CONTENT RESET_CONTENT_STYLE_T RIGHT_PADDING RESET_CELL_STYLE_T + * | | | | | | | | + * L1 R1 + * L2 R2 + * L3 R3 + */ + + size_t L2 = cell_padding_left; + + size_t R2 = cell_padding_right; + size_t R3 = strlen(reset_cell_style_tag); + +#define TOTAL_WRITTEN (written + invisible_written) +#define RIGHT (right + extra_right) + +#define WRITE_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, cell_style_tag)) +#define WRITE_RESET_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, reset_cell_style_tag)) +#define WRITE_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, content_style_tag)) +#define WRITE_RESET_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, 1, reset_content_style_tag)) + if (row >= hint_height_cell(cell, context) || row < cell_padding_top || row >= (cell_padding_top + buffer_text_height(cell->str_buffer))) { - return snprint_n_strings_(buf, buf_len, buf_len - 1, space_char); + WRITE_CELL_STYLE_TAG; + WRITE_CONTENT_STYLE_TAG; + WRITE_RESET_CONTENT_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len, buf_len - 1 - TOTAL_WRITTEN - R3, space_char)); + WRITE_RESET_CELL_STYLE_TAG; + return TOTAL_WRITTEN; } - int written = 0; - int tmp = 0; - int left = cell_padding_left; - int right = cell_padding_right; + WRITE_CELL_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, L2, space_char)); + if (cell->str_buffer) { + CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf_(cell->str_buffer, row - cell_padding_top, buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN - R2 - R3, context, content_style_tag, reset_content_style_tag)); + } else { + WRITE_CONTENT_STYLE_TAG; + WRITE_RESET_CONTENT_STYLE_TAG; + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN - R2 - R3, space_char)); + } + CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, R2, space_char)); + WRITE_RESET_CELL_STYLE_TAG; - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, left, space_char)); - - if (cell->str_buffer) - CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf_(cell->str_buffer, row - cell_padding_top, buf + written, buf_len - written - right, context)); - else - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, buf_len - written - right, space_char)); - CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + written, buf_len - written, right, space_char)); - - return written; + return TOTAL_WRITTEN; clear: return -1; +#undef WRITE_CELL_STYLE_TAG +#undef WRITE_RESET_CELL_STYLE_TAG +#undef WRITE_CONTENT_STYLE_TAG +#undef WRITE_RESET_CONTENT_STYLE_TAG +#undef TOTAL_WRITTEN +#undef RIGHT } #endif diff --git a/src/cell.h b/src/cell.h index b0f4abe..7daa3bb 100644 --- a/src/cell.h +++ b/src/cell.h @@ -13,7 +13,7 @@ FT_INTERNAL fort_cell_t *copy_cell(fort_cell_t *cell); FT_INTERNAL -size_t hint_width_cell(const fort_cell_t *cell, const context_t *context); +size_t hint_width_cell(const fort_cell_t *cell, const context_t *context, enum request_geom_type geom); FT_INTERNAL size_t hint_height_cell(const fort_cell_t *cell, const context_t *context); diff --git a/src/fort_impl.c b/src/fort_impl.c index de92dff..6893217 100644 --- a/src/fort_impl.c +++ b/src/fort_impl.c @@ -611,7 +611,7 @@ const char *ft_to_string(const ft_table_t *table) size_t rows = 0; size_t *col_width_arr = NULL; size_t *row_height_arr = NULL; - status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); + status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows, VISIBLE_GEOMETRY); if (FT_IS_ERROR(status)) return NULL; @@ -715,7 +715,7 @@ const wchar_t *ft_to_wstring(const ft_table_t *table) size_t rows = 0; size_t *col_width_arr = NULL; size_t *row_height_arr = NULL; - status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); + status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows, VISIBLE_GEOMETRY); if (rows == 0) return EMPTY_STRING; diff --git a/src/fort_utils.c b/src/fort_utils.c index 1a8cfea..193a634 100644 --- a/src/fort_utils.c +++ b/src/fort_utils.c @@ -195,6 +195,9 @@ int snprint_n_strings(char *buf, size_t length, size_t n, const char *str) if (n * str_len > INT_MAX) return -1; + if (str_len == 0) + return 0; + int status = snprintf(buf, length, "%0*d", (int)(n * str_len), 0); if (status < 0) return status; @@ -240,8 +243,36 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str) /* This function doesn't work properly with multibyte characters * so it is better return an error in this case */ - if (str_len > 1) - return -1; + if (str_len > 1) { + const unsigned char *p = (const unsigned char *)str; + while (*p) { + if (*p <= 127) + p++; + else { + const int SIZE = 64; + wchar_t wcs[SIZE]; + const char *ptr = str; + int length; + length = mbsrtowcs(wcs, (const char **)&ptr, SIZE, NULL); + wcs[length] = L'\0'; + if (length > 1) { + return -1; + } else { + swprintf(buf, length, L"%0*d", (int)(n * str_len), 0); + int k = n; + while (k) { + *buf = *wcs; + ++buf; + --k; + } + buf[n] = L'\0'; + return n; + } + +// return -1; + } + } + } if (length <= n * str_len) return -1; @@ -249,12 +280,13 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str) if (n == 0) return 0; - - /* To ensure valid return value it is safely not print such big strings */ if (n * str_len > INT_MAX) return -1; + if (str_len == 0) + return 0; + int status = swprintf(buf, length, L"%0*d", (int)(n * str_len), 0); if (status < 0) return status; diff --git a/src/fort_utils.h b/src/fort_utils.h index f2bd320..e4eb278 100644 --- a/src/fort_utils.h +++ b/src/fort_utils.h @@ -105,15 +105,16 @@ typedef struct fort_row fort_row_t; /*typedef struct ft_table ft_table_t;*/ typedef struct separator separator_t; - - - enum CellType { CommonCell, GroupMasterCell, GroupSlaveCell }; +enum request_geom_type { + VISIBLE_GEOMETRY, + INTERN_REPR_GEOMETRY +}; /***************************************************************************** * LIBFORT helpers @@ -145,6 +146,15 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str); written += tmp; \ } while(0) +#define CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(statement) \ + do { \ + tmp = statement; \ + if (tmp < 0) {\ + goto clear; \ + } \ + invisible_written += tmp; \ + } while(0) + #define CHECK_NOT_NEGATIVE(x) \ do { if (x < 0) goto fort_fail; } while (0) diff --git a/src/properties.c b/src/properties.c index c0bb607..3d794ac 100644 --- a/src/properties.c +++ b/src/properties.c @@ -1,8 +1,255 @@ +#include "fort_utils.h" #include #include "properties.h" -#include "fort_utils.h" #include "vector.h" +#define FT_RESET_COLOR "\033[0m" + +const char *fg_colors[] = { + "", + "\033[30m", + "\033[31m", + "\033[32m", + "\033[33m", + "\033[34m", + "\033[35m", + "\033[36m", + "\033[37m", + "\033[90m", + "\033[91m", + "\033[92m", + "\033[93m", + "\033[94m", + "\033[95m", + "\033[96m", + "\033[97m", +}; + +const char *reset_fg_colors[] = { + "", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", + "\033[39m", +}; + +const char *bg_colors[] = { + "", + "\033[40m", + "\033[41m", + "\033[42m", + "\033[43m", + "\033[44m", + "\033[45m", + "\033[46m", + "\033[47m", + "\033[100m", + "\033[101m", + "\033[102m", + "\033[103m", + "\033[104m", + "\033[105m", + "\033[106m", + "\033[107m", +}; + +const char *reset_bg_colors[] = { + "", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", + "\033[49m", +}; + + +const char *text_styles[] = { + "", + "\033[1m", + "\033[2m", + "\033[4m", + "\033[5m", + "\033[7m", + "\033[8m", +}; + +const char *reset_text_styles[] = { + "", + "\033[21m", + "\033[22m", + "\033[24m", + "\033[25m", + "\033[27m", + "\033[28m", +}; + + +static const size_t n_fg_colors = sizeof(fg_colors) / sizeof(fg_colors[0]); +static const size_t n_bg_colors = sizeof(bg_colors) / sizeof(bg_colors[0]); +static const size_t n_styles = sizeof(text_styles) / sizeof(text_styles[0]); + +void get_style_tag_for_cell(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz) +{ + (void)sz; + + unsigned bg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CELL_BG_COLOR); + unsigned text_style = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CELL_TEXT_STYLE); + + style_tag[0] = '\0'; + + if (text_style < n_styles) { + strcat(style_tag, text_styles[text_style]); + } else { + goto error; + } + + if (bg_color_number < n_bg_colors) { + strcat(style_tag, bg_colors[bg_color_number]); + } else { + goto error; + } + + return; + +error: + // shouldn't be here + assert(0); + style_tag[0] = '\0'; + return; +} + +void get_reset_style_tag_for_cell(const fort_table_properties_t *props, + size_t row, size_t col, char *reset_style_tag, size_t sz) +{ + (void)sz; + + unsigned bg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CELL_BG_COLOR); + unsigned text_style = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CELL_TEXT_STYLE); + + reset_style_tag[0] = '\0'; + + if (text_style < n_styles) { + strcat(reset_style_tag, reset_text_styles[text_style]); + } else { + goto error; + } + + if (bg_color_number < n_bg_colors) { + strcat(reset_style_tag, reset_bg_colors[bg_color_number]); + } else { + goto error; + } + + return; + +error: + // shouldn't be here + assert(0); + reset_style_tag[0] = '\0'; + return; +} + + +void get_style_tag_for_content(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz) +{ + (void)sz; + + unsigned text_style = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_TEXT_STYLE); + unsigned fg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_FG_COLOR); + unsigned bg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_BG_COLOR); + + style_tag[0] = '\0'; + + if (text_style < n_styles) { + strcat(style_tag, text_styles[text_style]); + } else { + goto error; + } + + if (fg_color_number < n_fg_colors) { + strcat(style_tag, fg_colors[fg_color_number]); + } else { + goto error; + } + + if (bg_color_number < n_bg_colors) { + strcat(style_tag, bg_colors[bg_color_number]); + } else { + goto error; + } + + return; + +error: + // shouldn't be here + assert(0); + style_tag[0] = '\0'; + return; +} + +void get_reset_style_tag_for_content(const fort_table_properties_t *props, + size_t row, size_t col, char *reset_style_tag, size_t sz) +{ + (void)sz; + + unsigned text_style = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_TEXT_STYLE); + unsigned fg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_FG_COLOR); + unsigned bg_color_number = get_cell_property_value_hierarcial(props, row, col, FT_CPROP_CONT_BG_COLOR); + + reset_style_tag[0] = '\0'; + + if (text_style < n_styles) { + strcat(reset_style_tag, reset_text_styles[text_style]); + } else { + goto error; + } + + if (fg_color_number < n_fg_colors) { + strcat(reset_style_tag, reset_fg_colors[fg_color_number]); + } else { + goto error; + } + + if (bg_color_number < n_bg_colors) { + strcat(reset_style_tag, reset_bg_colors[bg_color_number]); + } else { + goto error; + } + + return; + +error: + // shouldn't be here + assert(0); + reset_style_tag[0] = '\0'; + return; +} + /***************************************************************************** * COLUMN PROPERTIES * ***************************************************************************/ @@ -14,7 +261,8 @@ struct fort_cell_props g_default_cell_properties = { /* properties */ FT_CPROP_MIN_WIDTH | FT_CPROP_TEXT_ALIGN | FT_CPROP_TOP_PADDING | FT_CPROP_BOTTOM_PADDING | FT_CPROP_LEFT_PADDING | FT_CPROP_RIGHT_PADDING - | FT_CPROP_EMPTY_STR_HEIGHT, + | FT_CPROP_EMPTY_STR_HEIGHT | FT_CPROP_CONT_FG_COLOR | FT_CPROP_CELL_BG_COLOR + | FT_CPROP_CONT_BG_COLOR | FT_CPROP_CELL_TEXT_STYLE | FT_CPROP_CONT_TEXT_STYLE, 0, /* col_min_width */ FT_ALIGNED_LEFT, /* align */ @@ -25,6 +273,11 @@ struct fort_cell_props g_default_cell_properties = { 1, /* cell_empty_string_height */ FT_ROW_COMMON, /* row_type */ + FT_COLOR_DEFAULT, /* content_fg_color_number */ + FT_COLOR_DEFAULT, /* content_bg_color_number */ + FT_COLOR_DEFAULT, /* cell_bg_color_number */ + FT_TSTYLE_DEFAULT, /* cell_text_style */ + FT_TSTYLE_DEFAULT, /* content_text_style */ }; static int get_prop_value_if_exists_otherwise_default(const struct fort_cell_props *cell_opts, uint32_t property) @@ -50,6 +303,16 @@ static int get_prop_value_if_exists_otherwise_default(const struct fort_cell_pro return cell_opts->cell_empty_string_height; case FT_CPROP_ROW_TYPE: return cell_opts->row_type; + case FT_CPROP_CONT_FG_COLOR: + return cell_opts->content_fg_color_number; + case FT_CPROP_CONT_BG_COLOR: + return cell_opts->content_bg_color_number; + case FT_CPROP_CELL_BG_COLOR: + return cell_opts->cell_bg_color_number; + case FT_CPROP_CELL_TEXT_STYLE: + return cell_opts->cell_text_style; + case FT_CPROP_CONT_TEXT_STYLE: + return cell_opts->content_text_style; default: /* todo: implement later */ exit(333); @@ -120,6 +383,7 @@ FT_INTERNAL int get_cell_property_value_hierarcial(const fort_table_properties_t *propertiess, size_t row, size_t column, uint32_t property) { assert(propertiess); + size_t row_origin = row; const fort_cell_props_t *opt = NULL; if (propertiess->cell_properties != NULL) { @@ -127,15 +391,29 @@ int get_cell_property_value_hierarcial(const fort_table_properties_t *properties opt = cget_cell_prop(propertiess->cell_properties, row, column); if (opt != NULL && PROP_IS_SET(opt->properties, property)) break; - if (row != FT_ANY_ROW) { + + if (row != FT_ANY_ROW && column != FT_ANY_COLUMN) { row = FT_ANY_ROW; continue; - } - if (column != FT_ANY_COLUMN) { + } else if (row == FT_ANY_ROW && column != FT_ANY_COLUMN) { + row = row_origin; + column = FT_ANY_COLUMN; + continue; + } else if (row != FT_ANY_ROW && column == FT_ANY_COLUMN) { + row = FT_ANY_ROW; column = FT_ANY_COLUMN; continue; } +// if (row != FT_ANY_ROW) { +// row = FT_ANY_ROW; +// continue; +// } +// if (column != FT_ANY_COLUMN) { +// column = FT_ANY_COLUMN; +// continue; +// } + opt = NULL; break; } @@ -172,6 +450,16 @@ static fort_status_t set_cell_property_impl(fort_cell_props_t *opt, uint32_t pro opt->cell_empty_string_height = value; } else if (PROP_IS_SET(property, FT_CPROP_ROW_TYPE)) { opt->row_type = (enum ft_row_type)value; + } else if (PROP_IS_SET(property, FT_CPROP_CONT_FG_COLOR)) { + opt->content_fg_color_number = value; + } else if (PROP_IS_SET(property, FT_CPROP_CONT_BG_COLOR)) { + opt->content_bg_color_number = value; + } else if (PROP_IS_SET(property, FT_CPROP_CELL_BG_COLOR)) { + opt->cell_bg_color_number = value; + } else if (PROP_IS_SET(property, FT_CPROP_CELL_TEXT_STYLE)) { + opt->cell_text_style = value; + } else if (PROP_IS_SET(property, FT_CPROP_CONT_TEXT_STYLE)) { + opt->content_text_style = value; } return FT_SUCCESS; diff --git a/src/properties.h b/src/properties.h index 0aa6881..2535ab0 100644 --- a/src/properties.h +++ b/src/properties.h @@ -9,6 +9,19 @@ #define PROP_SET(ft_props, property) ((ft_props) |=(property)) #define PROP_UNSET(ft_props, property) ((ft_props) &= ~((uint32_t)property)) +#define TEXT_STYLE_TAG_MAX_SIZE 64 + +void get_style_tag_for_cell(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz); +void get_reset_style_tag_for_cell(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz); + +void get_style_tag_for_content(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz); +void get_reset_style_tag_for_content(const fort_table_properties_t *props, + size_t row, size_t col, char *style_tag, size_t sz); + + struct fort_cell_props { size_t cell_row; size_t cell_col; @@ -21,6 +34,11 @@ struct fort_cell_props { unsigned int cell_padding_right; unsigned int cell_empty_string_height; enum ft_row_type row_type; + unsigned int content_fg_color_number; + unsigned int content_bg_color_number; + unsigned int cell_bg_color_number; + unsigned int cell_text_style; + unsigned int content_text_style; }; typedef struct fort_cell_props fort_cell_props_t; diff --git a/src/string_buffer.c b/src/string_buffer.c index efa9b95..8888fff 100644 --- a/src/string_buffer.c +++ b/src/string_buffer.c @@ -341,7 +341,8 @@ size_t buffer_text_width(string_buffer_t *buffer) FT_INTERNAL -int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t buf_len, const context_t *context) +int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t total_buf_len, + const context_t *context, const char *content_style_tag, const char *reset_content_style_tag) { #define CHAR_TYPE char #define NULL_CHAR '\0' @@ -355,6 +356,8 @@ int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t #define STR_N_SUBSTRING str_n_substring #define STR_ITER_WIDTH str_iter_width + size_t buf_len = total_buf_len - strlen(content_style_tag) - strlen(reset_content_style_tag); + if (buffer == NULL || buffer->str.data == NULL || buffer_row >= buffer_text_height(buffer) || buf_len == 0) { return -1; @@ -392,7 +395,7 @@ int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t const CHAR_TYPE *end = NULL; CHAR_TYPE old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, left, SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, left, SPACE_CHAR)); STR_N_SUBSTRING(buffer->BUFFER_STR, NEWLINE_CHAR, buffer_row, &beg, &end); if (beg == NULL || end == NULL) @@ -404,10 +407,13 @@ int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t if (str_it_width < 0 || content_width < (size_t)str_it_width) return - 1; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, 1, content_style_tag)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, total_buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, 1, reset_content_style_tag)); + *(CHAR_TYPE *)end = old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, right, SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, right, SPACE_CHAR)); return written; clear: @@ -429,7 +435,8 @@ clear: #ifdef FT_HAVE_WCHAR FT_INTERNAL -int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t buf_len, const context_t *context) +int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t total_buf_len, + const context_t *context, const char *content_style_tag, const char *reset_content_style_tag) { #define CHAR_TYPE wchar_t #define NULL_CHAR L'\0' @@ -443,6 +450,8 @@ int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, siz #define STR_N_SUBSTRING wstr_n_substring #define STR_ITER_WIDTH wcs_iter_width + size_t buf_len = total_buf_len - strlen(content_style_tag) - strlen(reset_content_style_tag); + if (buffer == NULL || buffer->str.data == NULL || buffer_row >= buffer_text_height(buffer) || buf_len == 0) { return -1; @@ -480,7 +489,7 @@ int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, siz const CHAR_TYPE *end = NULL; CHAR_TYPE old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, left, SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, left, SPACE_CHAR)); STR_N_SUBSTRING(buffer->BUFFER_STR, NEWLINE_CHAR, buffer_row, &beg, &end); if (beg == NULL || end == NULL) @@ -492,10 +501,13 @@ int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, siz if (str_it_width < 0 || content_width < (size_t)str_it_width) return - 1; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, 1, content_style_tag)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINTF(buf + written, total_buf_len - written, SNPRINTF_FMT_STR, (int)(end - beg), beg)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, 1, reset_content_style_tag)); + *(CHAR_TYPE *)end = old_value; - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); - CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, buf_len - written, right, SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, (content_width - (size_t)str_it_width), SPACE_CHAR)); + CHCK_RSLT_ADD_TO_WRITTEN(SNPRINT_N_STRINGS(buf + written, total_buf_len - written, right, SPACE_CHAR)); return written; clear: diff --git a/src/string_buffer.h b/src/string_buffer.h index e700916..4fd1385 100644 --- a/src/string_buffer.h +++ b/src/string_buffer.h @@ -57,11 +57,13 @@ FT_INTERNAL size_t buffer_text_width(string_buffer_t *buffer); FT_INTERNAL -int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t buf_len, const context_t *context); +int buffer_printf(string_buffer_t *buffer, size_t buffer_row, char *buf, size_t total_buf_len, + const context_t *context, const char *content_style_tag, const char *reset_content_style_tag); #ifdef FT_HAVE_WCHAR FT_INTERNAL -int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t buf_len, const context_t *context); +int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, size_t total_buf_len, + const context_t *context, const char *content_style_tag, const char *reset_content_style_tag); #endif /* FT_HAVE_WCHAR */ #endif /* STRING_BUFFER_H */ diff --git a/src/table.c b/src/table.c index 9d7040e..12a4bb3 100644 --- a/src/table.c +++ b/src/table.c @@ -122,7 +122,8 @@ fort_status_t get_table_sizes(const ft_table_t *table, size_t *rows, size_t *col FT_INTERNAL fort_status_t table_rows_and_cols_geometry(const ft_table_t *table, size_t **col_width_arr_p, size_t *col_width_arr_sz, - size_t **row_height_arr_p, size_t *row_height_arr_sz) + size_t **row_height_arr_p, size_t *row_height_arr_sz, + enum request_geom_type geom) { if (table == NULL) { return FT_ERROR; @@ -159,7 +160,7 @@ fort_status_t table_rows_and_cols_geometry(const ft_table_t *table, if (cell) { switch (get_cell_type(cell)) { case CommonCell: - col_width_arr[col] = MAX(col_width_arr[col], hint_width_cell(cell, &context)); + col_width_arr[col] = MAX(col_width_arr[col], hint_width_cell(cell, &context, geom)); break; case GroupMasterCell: combined_cells_found = 1; @@ -184,7 +185,7 @@ fort_status_t table_rows_and_cols_geometry(const ft_table_t *table, context.row = row; if (cell) { if (get_cell_type(cell) == GroupMasterCell) { - size_t hint_width = hint_width_cell(cell, &context); + size_t hint_width = hint_width_cell(cell, &context, geom); size_t slave_col = col + group_cell_number(row_p, col); size_t cur_adj_col = col; size_t group_width = col_width_arr[col]; @@ -243,7 +244,7 @@ fort_status_t table_geometry(const ft_table_t *table, size_t *height, size_t *wi size_t *col_width_arr = NULL; size_t *row_height_arr = NULL; - int status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows); + int status = table_rows_and_cols_geometry(table, &col_width_arr, &cols, &row_height_arr, &rows, INTERN_REPR_GEOMETRY); if (FT_IS_ERROR(status)) return status; diff --git a/src/table.h b/src/table.h index 5c1ebfa..0af96aa 100644 --- a/src/table.h +++ b/src/table.h @@ -36,10 +36,12 @@ fort_row_t *get_row_and_create_if_not_exists(ft_table_t *table, size_t row); FT_INTERNAL string_buffer_t *get_cur_str_buffer_and_create_if_not_exists(ft_table_t *table); + FT_INTERNAL fort_status_t table_rows_and_cols_geometry(const ft_table_t *table, size_t **col_width_arr_p, size_t *col_width_arr_sz, - size_t **row_height_arr_p, size_t *row_height_arr_sz); + size_t **row_height_arr_p, size_t *row_height_arr_sz, + enum request_geom_type geom); FT_INTERNAL fort_status_t table_geometry(const ft_table_t *table, size_t *height, size_t *width); diff --git a/tests/bb_tests/test_table_properties.c b/tests/bb_tests/test_table_properties.c index 2018b7c..41c4bcf 100644 --- a/tests/bb_tests/test_table_properties.c +++ b/tests/bb_tests/test_table_properties.c @@ -137,6 +137,118 @@ void test_table_cell_properties(void) ft_table_t *table = NULL; + WHEN("Setting property for one cell") { + set_test_properties_as_default(); + + table = create_test_int_table(0); + ft_set_cell_prop(table, 1, 1, FT_CPROP_TOP_PADDING, 2); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+---+---+----+----+\n" + "| | | | |\n" + "| 3 | 4 | 55 | 67 |\n" + "| | | | |\n" + "+---+---+----+----+\n" + "| | | | |\n" + "| 3 | | 55 | 67 |\n" + "| | 4 | | |\n" + "| | | | |\n" + "+---+---+----+----+\n" + "| | | | |\n" + "| 3 | 4 | 55 | 67 |\n" + "| | | | |\n" + "+---+---+----+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + + WHEN("Setting property for the row") { + set_test_properties_as_default(); + + table = create_test_int_table(0); + ft_set_cell_prop(table, 1, FT_ANY_COLUMN, FT_CPROP_TOP_PADDING, 2); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+---+---+----+----+\n" + "| | | | |\n" + "| 3 | 4 | 55 | 67 |\n" + "| | | | |\n" + "+---+---+----+----+\n" + "| | | | |\n" + "| | | | |\n" + "| 3 | 4 | 55 | 67 |\n" + "| | | | |\n" + "+---+---+----+----+\n" + "| | | | |\n" + "| 3 | 4 | 55 | 67 |\n" + "| | | | |\n" + "+---+---+----+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + + WHEN("Setting property for the column") { + set_test_properties_as_default(); + + table = create_test_int_table(0); + ft_set_cell_prop(table, FT_ANY_ROW, 1, FT_CPROP_TOP_PADDING, 2); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+---+---+----+----+\n" + "| | | | |\n" + "| 3 | | 55 | 67 |\n" + "| | 4 | | |\n" + "| | | | |\n" + "+---+---+----+----+\n" + "| | | | |\n" + "| 3 | | 55 | 67 |\n" + "| | 4 | | |\n" + "| | | | |\n" + "+---+---+----+----+\n" + "| | | | |\n" + "| 3 | | 55 | 67 |\n" + "| | 4 | | |\n" + "| | | | |\n" + "+---+---+----+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + + WHEN("Setting property for all cells in the table") { + set_test_properties_as_default(); + + table = create_test_int_table(0); + ft_set_cell_prop(table, FT_ANY_ROW, FT_ANY_COLUMN, FT_CPROP_TOP_PADDING, 2); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+---+---+----+----+\n" + "| | | | |\n" + "| | | | |\n" + "| 3 | 4 | 55 | 67 |\n" + "| | | | |\n" + "+---+---+----+----+\n" + "| | | | |\n" + "| | | | |\n" + "| 3 | 4 | 55 | 67 |\n" + "| | | | |\n" + "+---+---+----+----+\n" + "| | | | |\n" + "| | | | |\n" + "| 3 | 4 | 55 | 67 |\n" + "| | | | |\n" + "+---+---+----+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + WHEN("All paddings = 1") { set_test_properties_as_default(); @@ -553,3 +665,248 @@ void test_table_cell_properties(void) ft_destroy_table(table); } } + + + +void test_table_text_styles(void) +{ + ft_table_t *table = NULL; + set_test_properties_as_default(); + + WHEN("Simple table with one cell and foreground content color") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_FG_COLOR, FT_COLOR_YELLOW) == FT_SUCCESS); + assert(ft_write(table, "42") == FT_SUCCESS); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+----+\n" + "|\033[33m\033[39m |\n" + "| \033[33m42\033[39m |\n" + "|\033[33m\033[39m |\n" + "+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + +#ifdef FT_HAVE_WCHAR + WHEN("Simple table with one cell and foreground color(wide strings case)") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_FG_COLOR, FT_COLOR_YELLOW) == FT_SUCCESS); + assert(ft_wwrite(table, L"42") == FT_SUCCESS); + + const wchar_t *table_str = ft_to_wstring(table); + assert_true(table_str != NULL); + const wchar_t *table_str_etalon = + L"+----+\n" + L"|\033[33m\033[39m |\n" + L"| \033[33m42\033[39m |\n" + L"|\033[33m\033[39m |\n" + L"+----+\n"; + assert_wcs_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } +#endif + + WHEN("Simple table with one cell and background content color") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_BG_COLOR, FT_COLOR_YELLOW) == FT_SUCCESS); + assert(ft_write(table, "42") == FT_SUCCESS); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+----+\n" + "|\033[43m\033[49m |\n" + "| \033[43m42\033[49m |\n" + "|\033[43m\033[49m |\n" + "+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + +#ifdef FT_HAVE_WCHAR + WHEN("Simple table with one cell and background content color(wide strings case)") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_BG_COLOR, FT_COLOR_YELLOW) == FT_SUCCESS); + assert(ft_wwrite(table, L"42") == FT_SUCCESS); + + const wchar_t *table_str = ft_to_wstring(table); + assert_true(table_str != NULL); + const wchar_t *table_str_etalon = + L"+----+\n" + L"|\033[43m\033[49m |\n" + L"| \033[43m42\033[49m |\n" + L"|\033[43m\033[49m |\n" + L"+----+\n"; + assert_wcs_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } +#endif + + WHEN("Simple table with one cell and background cell color") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CELL_BG_COLOR, FT_COLOR_YELLOW) == FT_SUCCESS); + assert(ft_write(table, "42") == FT_SUCCESS); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+----+\n" + "|\033[43m \033[49m|\n" + "|\033[43m 42 \033[49m|\n" + "|\033[43m \033[49m|\n" + "+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + +#ifdef FT_HAVE_WCHAR + WHEN("Simple table with one cell and background cell color(wide strings case)") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CELL_BG_COLOR, FT_COLOR_YELLOW) == FT_SUCCESS); + assert(ft_wwrite(table, L"42") == FT_SUCCESS); + + const wchar_t *table_str = ft_to_wstring(table); + assert_true(table_str != NULL); + const wchar_t *table_str_etalon = + L"+----+\n" + L"|\033[43m \033[49m|\n" + L"|\033[43m 42 \033[49m|\n" + L"|\033[43m \033[49m|\n" + L"+----+\n"; + assert_wcs_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } +#endif + + WHEN("Simple table with one cell and content style") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED) == FT_SUCCESS); + assert(ft_write(table, "42") == FT_SUCCESS); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+----+\n" + "|\033[4m\033[24m |\n" + "| \033[4m42\033[24m |\n" + "|\033[4m\033[24m |\n" + "+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + +#ifdef FT_HAVE_WCHAR + WHEN("Simple table with one cell and content style(wide strings case)") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED) == FT_SUCCESS); + assert(ft_wwrite(table, L"42") == FT_SUCCESS); + + const wchar_t *table_str = ft_to_wstring(table); + assert_true(table_str != NULL); + const wchar_t *table_str_etalon = + L"+----+\n" + L"|\033[4m\033[24m |\n" + L"| \033[4m42\033[24m |\n" + L"|\033[4m\033[24m |\n" + L"+----+\n"; + assert_wcs_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } +#endif + + WHEN("Simple table with one cell and cell style") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CELL_TEXT_STYLE, FT_TSTYLE_UNDERLINED) == FT_SUCCESS); + assert(ft_write(table, "42") == FT_SUCCESS); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+----+\n" + "|\033[4m \033[24m|\n" + "|\033[4m 42 \033[24m|\n" + "|\033[4m \033[24m|\n" + "+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + +#ifdef FT_HAVE_WCHAR + WHEN("Simple table with one cell and cell style(wide strings case)") { + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CELL_TEXT_STYLE, FT_TSTYLE_UNDERLINED) == FT_SUCCESS); + assert(ft_wwrite(table, L"42") == FT_SUCCESS); + + const wchar_t *table_str = ft_to_wstring(table); + assert_true(table_str != NULL); + const wchar_t *table_str_etalon = + L"+----+\n" + L"|\033[4m \033[24m|\n" + L"|\033[4m 42 \033[24m|\n" + L"|\033[4m \033[24m|\n" + L"+----+\n"; + assert_wcs_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } +#endif + + WHEN("Simple table with one cell background color, content foreground color and style.") { + set_test_properties_as_default(); + + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_FG_COLOR, FT_COLOR_YELLOW) == FT_SUCCESS); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CELL_BG_COLOR, FT_COLOR_RED) == FT_SUCCESS); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED) == FT_SUCCESS); + assert(ft_write(table, "42") == FT_SUCCESS); + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+----+\n" + "|\033[41m\033[4m\033[33m\033[24m\033[39m \033[49m|\n" + "|\033[41m \033[4m\033[33m42\033[24m\033[39m \033[49m|\n" + "|\033[41m\033[4m\033[33m\033[24m\033[39m \033[49m|\n" + "+----+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } + +#ifdef FT_HAVE_WCHAR + WHEN("Simple table with one cell background color, content foreground color and style.") { + set_test_properties_as_default(); + + table = ft_create_table(); + assert(table); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_FG_COLOR, FT_COLOR_YELLOW) == FT_SUCCESS); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CELL_BG_COLOR, FT_COLOR_RED) == FT_SUCCESS); + assert(ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED) == FT_SUCCESS); + assert(ft_wwrite(table, L"42") == FT_SUCCESS); + + const wchar_t *table_str = ft_to_wstring(table); + assert_true(table_str != NULL); + const wchar_t *table_str_etalon = + L"+----+\n" + L"|\033[41m\033[4m\033[33m\033[24m\033[39m \033[49m|\n" + L"|\033[41m \033[4m\033[33m42\033[24m\033[39m \033[49m|\n" + L"|\033[41m\033[4m\033[33m\033[24m\033[39m \033[49m|\n" + L"+----+\n"; + assert_wcs_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } +#endif +} + diff --git a/tests/main_test.c b/tests/main_test.c index ef822a8..93faed0 100644 --- a/tests/main_test.c +++ b/tests/main_test.c @@ -24,6 +24,7 @@ struct test_case bb_test_suit [] = { {"test_table_builtin_border_styles", test_table_builtin_border_styles}, {"test_table_cell_properties", test_table_cell_properties}, {"test_table_tbl_properties", test_table_tbl_properties}, + {"test_table_text_styles", test_table_text_styles}, {"test_memory_errors", test_memory_errors}, }; @@ -52,15 +53,146 @@ int main(void) * Essential for OSX, because swprintf can fail in case of real unicode * chars. */ -#if defined(FT_HAVE_WCHAR) +//#if defined(FT_HAVE_WCHAR) +// setlocale(LC_CTYPE, ""); +//#endif + +//#ifdef FORT_WB_TESTING_ENABLED +// status |= run_wb_test_suit(); +// fprintf(stderr, "\n"); +//#endif +// status |= run_bb_test_suit(); + + setlocale(LC_CTYPE, ""); -#endif -#ifdef FORT_WB_TESTING_ENABLED - status |= run_wb_test_suit(); - fprintf(stderr, "\n"); -#endif - status |= run_bb_test_suit(); + ft_table_t *table = NULL; + table = ft_create_table(); + ft_set_border_style(table, FT_DOUBLE2_STYLE); + ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER); + ft_wwrite_ln(table, L"some", L"some3333", L"11111"); + ft_wwrite_ln(table, L"s", L"some333377777", L"1111111111"); + ft_wwrite_ln(table, L"some", L"some3333", L"111111"); + ft_wwrite_ln(table, L"✖", L"☑", L"✔"); + + + ft_set_cell_prop(table, FT_ANY_ROW, 0, FT_CPROP_TEXT_ALIGN, FT_ALIGNED_CENTER); + ft_set_cell_prop(table, 0, 1, FT_CPROP_CELL_TEXT_STYLE, FT_TSTYLE_UNDERLINED); + ft_set_cell_prop(table, 0, 2, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED); + ft_set_cell_prop(table, 2, 1, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED); + + ft_set_cell_prop(table, 0, 1, FT_CPROP_CONT_FG_COLOR, FT_COLOR_YELLOW); + ft_set_cell_prop(table, 0, 1, FT_CPROP_CELL_BG_COLOR, FT_COLOR_MAGENTA); + ft_set_cell_prop(table, 0, 1, FT_CPROP_CELL_TEXT_STYLE, FT_TSTYLE_UNDERLINED); + + ft_set_cell_prop(table, 1, 1, FT_CPROP_CONT_BG_COLOR, FT_COLOR_RED); + ft_set_cell_prop(table, 0, 2, FT_CPROP_CONT_BG_COLOR, FT_COLOR_RED); + + ft_set_cell_prop(table, 3, FT_ANY_COLUMN, FT_CPROP_CONT_FG_COLOR, FT_COLOR_GREEN); + ft_set_cell_prop(table, 3, FT_ANY_COLUMN, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_BOLD); + + const wchar_t *table_wstr = ft_to_wstring(table); + if (table_wstr) { + fwprintf(stdout, L"Table:\n%ls\n ", table_wstr); + } else { + fwprintf(stdout, L"Table conversion failed !!!\n "); + } + + ft_destroy_table(table); + + + + // ///////////////////////// + + + table = ft_create_table(); + ft_set_border_style(table, FT_DOUBLE_STYLE); + ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER); + + ft_wwrite_ln(table, L"Test", L"Iterations", L"ms/op", L"Passed"); + ft_wwrite_ln(table, L"n-body", L"1000", L"1.629"); + ft_wwrite_ln(table, L"", L"2500", L"6.3", L"✔"); + ft_wwrite_ln(table, L"", L"10000", L"10.5"); + ft_add_separator(table); + ft_wwrite_ln(table, L"regex-redux", L"1000", L"1.629"); + ft_wwrite_ln(table, L"", L"2500", L"6.3", L"✖"); + ft_wwrite_ln(table, L"", L"10000", L"10.5"); + ft_add_separator(table); + ft_wwrite_ln(table, L"mandelbrot", L"1000", L"1.629"); + ft_wwrite_ln(table, L"", L"2500", L"6.3", L"✔"); + ft_wwrite_ln(table, L"", L"10000", L"10.5"); + ft_add_separator(table); + ft_set_cell_span(table, 10, 0, 3); + ft_wwrite_ln(table, L"Total result", L"", L"", L"✖"); + + + ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_BOLD); + ft_set_cell_prop(table, FT_ANY_ROW, 0, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_BOLD); + + ft_set_cell_prop(table, FT_ANY_ROW, 1, FT_CPROP_TEXT_ALIGN, FT_ALIGNED_RIGHT); + ft_set_cell_prop(table, FT_ANY_ROW, 3, FT_CPROP_TEXT_ALIGN, FT_ALIGNED_CENTER); + ft_set_cell_prop(table, 10, 0, FT_CPROP_TEXT_ALIGN, FT_ALIGNED_CENTER); + + ft_set_cell_prop(table, 2, 3, FT_CPROP_CONT_FG_COLOR, FT_COLOR_GREEN); + ft_set_cell_prop(table, 5, 3, FT_CPROP_CONT_FG_COLOR, FT_COLOR_RED); + ft_set_cell_prop(table, 8, 3, FT_CPROP_CONT_FG_COLOR, FT_COLOR_GREEN); + + +// ft_set_cell_prop(table, FT_ANY_ROW, 0, FT_CPROP_TEXT_ALIGN, FT_ALIGNED_CENTER); +// ft_set_cell_prop(table, 0, 1, FT_CPROP_CELL_TEXT_STYLE, FT_TSTYLE_UNDERLINED); +// ft_set_cell_prop(table, 0, 2, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED); +// ft_set_cell_prop(table, 2, 1, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED); + +// ft_set_cell_prop(table, 0, 1, FT_CPROP_CONT_FG_COLOR, FT_COLOR_YELLOW); +// ft_set_cell_prop(table, 0, 1, FT_CPROP_CELL_BG_COLOR, FT_COLOR_MAGENTA); +// ft_set_cell_prop(table, 0, 1, FT_CPROP_CELL_TEXT_STYLE, FT_TSTYLE_UNDERLINED); + +// ft_set_cell_prop(table, 1, 1, FT_CPROP_CONT_BG_COLOR, FT_COLOR_RED); +// ft_set_cell_prop(table, 0, 2, FT_CPROP_CONT_BG_COLOR, FT_COLOR_RED); + +// ft_set_cell_prop(table, 3, FT_ANY_COLUMN, FT_CPROP_CONT_FG_COLOR, FT_COLOR_GREEN); +// ft_set_cell_prop(table, 3, FT_ANY_COLUMN, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_BOLD); + + table_wstr = ft_to_wstring(table); + if (table_wstr) { + fwprintf(stdout, L"Table:\n%ls\n ", table_wstr); + } else { + fwprintf(stdout, L"Table conversion failed !!!\n "); + } + + ft_destroy_table(table); + + +// printf("\n\n------ Some debug stuff delete later --------\n\n\n"); + + +// ft_table_t *table = ft_create_table(); +// ft_set_cell_prop(table, 0, 0, FT_CPROP_CONT_FG_COLOR, FT_COLOR_RED); +// ft_set_cell_prop(table, 1, 1, FT_CPROP_CONT_FG_COLOR, FT_COLOR_GREEN); +// ft_set_cell_prop(table, FT_ANY_ROW, 2, FT_CPROP_CONT_FG_COLOR, FT_COLOR_MAGENTA); +// ft_set_cell_prop(table, FT_ANY_ROW, 2, FT_CPROP_CONT_BG_COLOR, FT_COLOR_YELLOW); + +// ft_set_cell_prop(table, 0, 1, FT_CPROP_CONT_FG_COLOR, FT_COLOR_YELLOW); +// ft_set_cell_prop(table, 0, 1, FT_CPROP_CELL_BG_COLOR, FT_COLOR_MAGENTA); +// ft_set_cell_prop(table, 0, 1, FT_CPROP_CELL_TEXT_STYLE, FT_TSTYLE_UNDERLINED); + +// ft_set_cell_prop(table, 2, FT_ANY_COLUMN, FT_CPROP_CELL_TEXT_STYLE, FT_TSTYLE_BOLD); +// ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER); +// ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_TEXT_ALIGN, FT_ALIGNED_CENTER); +// ft_set_cell_prop(table, FT_ANY_ROW, 0, FT_CPROP_TEXT_ALIGN, FT_ALIGNED_CENTER); +// ft_set_cell_prop(table, 0, 1, FT_CPROP_CELL_TEXT_STYLE, FT_TSTYLE_UNDERLINED); +// ft_set_cell_prop(table, 0, 2, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED); +// ft_set_cell_prop(table, 2, 1, FT_CPROP_CONT_TEXT_STYLE, FT_TSTYLE_UNDERLINED); + + +// ft_write_ln(table, "some", "some3333", "11111"); +// ft_write_ln(table, "s", "some333377777", "1111111111"); +// ft_write_ln(table, "some", "some3333", "111111"); +// const char *str_repr = ft_to_string(table); +// printf("%s\n", str_repr ? str_repr : "NULL"); +// ft_destroy_table(table); + +// printf("aa \033[42m 11 \033[4m 222 \033[49m 123 \033[24m 666\n"); return status; } diff --git a/tests/tests.h b/tests/tests.h index 8d3a317..5a53ea7 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -33,6 +33,7 @@ void test_table_write(void); void test_table_border_style(void); void test_table_builtin_border_styles(void); void test_table_cell_properties(void); +void test_table_text_styles(void); void test_table_tbl_properties(void); void test_memory_errors(void);