diff --git a/example/main.c b/example/main.c index da8b22c..53c6cae 100644 --- a/example/main.c +++ b/example/main.c @@ -128,18 +128,43 @@ int main(void) printf("Table:\n%s\n", ft_to_string(table)); ft_destroy_table(table); + ft_set_default_border_style(FT_SOLID_ROUND_STYLE); + table = create_basic_table(); + printf("Table:\n%s\n", ft_to_string(table)); + ft_destroy_table(table); + ft_set_default_border_style(FT_DOUBLE_STYLE); table = create_basic_table(); printf("Table:\n%s\n", ft_to_string(table)); ft_destroy_table(table); + ft_set_default_border_style(FT_DOUBLE2_STYLE); + table = create_basic_table(); + printf("Table:\n%s\n", ft_to_string(table)); + ft_destroy_table(table); + + ft_set_default_border_style(FT_BOLD_STYLE); + table = create_basic_table(); + printf("Table:\n%s\n", ft_to_string(table)); + ft_destroy_table(table); + + ft_set_default_border_style(FT_BOLD2_STYLE); + table = create_basic_table(); + printf("Table:\n%s\n", ft_to_string(table)); + ft_destroy_table(table); + + ft_set_default_border_style(FT_FRAME_STYLE); + table = create_basic_table(); + printf("Table:\n%s\n", ft_to_string(table)); + ft_destroy_table(table); + /* Debug */ ft_set_default_border_style(FT_SOLID_STYLE); table = create_basic_table(); ft_set_cell_option(table, FT_CUR_ROW, FT_ANY_COLUMN, FT_COPT_ROW_TYPE, FT_ROW_HEADER); ft_write_ln(table, "Summary", "", "", "8.7"); - ft_some_api(table, 6, 0, 3); - ft_some_api(table, 0, 0, 3); + ft_set_cell_span(table, 6, 0, 3); + ft_set_cell_span(table, 0, 0, 3); printf("Table:\n%s\n", ft_to_string(table)); ft_destroy_table(table); diff --git a/include/fort.h b/include/fort.h index 4411ade..9bb7351 100644 --- a/include/fort.h +++ b/include/fort.h @@ -444,7 +444,12 @@ extern struct ft_border_style *FT_PLAIN_STYLE; extern struct ft_border_style *FT_DOT_STYLE; extern struct ft_border_style *FT_EMPTY_STYLE; extern struct ft_border_style *FT_SOLID_STYLE; +extern struct ft_border_style *FT_SOLID_ROUND_STYLE; extern struct ft_border_style *FT_DOUBLE_STYLE; +extern struct ft_border_style *FT_DOUBLE2_STYLE; +extern struct ft_border_style *FT_BOLD_STYLE; +extern struct ft_border_style *FT_BOLD2_STYLE; +extern struct ft_border_style *FT_FRAME_STYLE; /** * Set default border style for all new formatted tables. @@ -576,6 +581,24 @@ FT_EXTERN int ft_set_default_tbl_option(uint32_t option, int value); FT_EXTERN int ft_set_tbl_option(FTABLE *table, uint32_t option, int value); +/** + * Set column span for the specified cell of the table. + * + * @param table + * A pointer to the FTABLE structure. + * @param row + * Cell row. + * @param col + * Cell column. + * @param hor_span + * Column span. + * @return + * - 0: Success; default table option was changed. + * - (<0): In case of error + */ +FT_EXTERN int ft_set_cell_span(FTABLE *table, size_t row, size_t col, size_t hor_span); + + /** * Set functions for memory allocation and deallocation to be used instead of * standard ones. @@ -594,7 +617,6 @@ FT_EXTERN void ft_set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free -FT_EXTERN void ft_some_api(FTABLE *table, size_t row, size_t col, size_t group_width); #ifdef FT_HAVE_WCHAR diff --git a/src/fort.c b/src/fort.c index 4e7ee2f..3cb1e23 100644 --- a/src/fort.c +++ b/src/fort.c @@ -798,7 +798,12 @@ struct ft_border_style *FT_PLAIN_STYLE = (struct ft_border_style *) &FORT_PLAIN_ struct ft_border_style *FT_DOT_STYLE = (struct ft_border_style *) &FORT_DOT_STYLE; struct ft_border_style *FT_EMPTY_STYLE = (struct ft_border_style *) &FORT_EMPTY_STYLE; struct ft_border_style *FT_SOLID_STYLE = (struct ft_border_style *) &FORT_SOLID_STYLE; +struct ft_border_style *FT_SOLID_ROUND_STYLE = (struct ft_border_style *) &FORT_SOLID_ROUND_STYLE; struct ft_border_style *FT_DOUBLE_STYLE = (struct ft_border_style *) &FORT_DOUBLE_STYLE; +struct ft_border_style *FT_DOUBLE2_STYLE = (struct ft_border_style *) &FORT_DOUBLE2_STYLE; +struct ft_border_style *FT_BOLD_STYLE = (struct ft_border_style *) &FORT_BOLD_STYLE; +struct ft_border_style *FT_BOLD2_STYLE = (struct ft_border_style *) &FORT_BOLD2_STYLE; +struct ft_border_style *FT_FRAME_STYLE = (struct ft_border_style *) &FORT_FRAME_STYLE; @@ -810,7 +815,12 @@ static void set_border_options_for_options(fort_table_options_t *options, struct || (struct fort_border_style *)style == &FORT_PLAIN_STYLE || (struct fort_border_style *)style == &FORT_EMPTY_STYLE || (struct fort_border_style *)style == &FORT_SOLID_STYLE - || (struct fort_border_style *)style == &FORT_DOUBLE_STYLE) { + || (struct fort_border_style *)style == &FORT_SOLID_ROUND_STYLE + || (struct fort_border_style *)style == &FORT_DOUBLE_STYLE + || (struct fort_border_style *)style == &FORT_DOUBLE2_STYLE + || (struct fort_border_style *)style == &FORT_BOLD_STYLE + || (struct fort_border_style *)style == &FORT_BOLD2_STYLE + || (struct fort_border_style *)style == &FORT_FRAME_STYLE) { memcpy(&(options->border_style), (struct fort_border_style *)style, sizeof(struct fort_border_style)); return; } @@ -951,23 +961,20 @@ FT_EXTERN void ft_set_memory_funcs(void *(*f_malloc)(size_t size), void (*f_free set_memory_funcs(f_malloc, f_free); } -#include "cell.h" -FT_EXTERN void ft_some_api(FTABLE *table, size_t row, size_t col, size_t group_width) +FT_EXTERN int ft_set_cell_span(FTABLE *table, size_t row, size_t col, size_t hor_span) { assert(table); - if (group_width == 0) - return; + if (hor_span < 2) + return FT_EINVAL; - fort_row_t *row_p = get_row(table, row); - fort_cell_t *main_cell = get_cell(row_p, col); - set_cell_type(main_cell, GroupMasterCell); - --group_width; - ++col; + if (row == FT_CUR_ROW) + row = table->cur_row; + if (row == FT_CUR_COLUMN) + col = table->cur_col; - while (group_width) { - fort_cell_t *slave_cell = get_cell(row_p, col); - set_cell_type(slave_cell, GroupSlaveCell); - --group_width; - ++col; - } + fort_row_t *row_p = get_row_and_create_if_not_exists(table, row); + if (row_p == NULL) + return FT_ERROR; + + return row_set_cell_span(row_p, col, hor_span); } diff --git a/src/options.c b/src/options.c index a1efb02..e95e8e5 100644 --- a/src/options.c +++ b/src/options.c @@ -321,27 +321,49 @@ fort_status_t set_default_cell_option(uint32_t option, int value) } -#define SOLID_STYLE { \ +#define SOLID_STYLE { \ /* border_chars */ \ { \ - "┏", "━", "┳", "┓", \ - "┃", "┃", "┃", \ + "┌", "─", "┬", "┐", \ + "│", "│", "│", \ "", "", "", "", \ - "┗", "━", "┻", "┛" \ + "└", "─", "┴", "╯" \ }, \ /* header_border_chars */ \ { \ - "┏", "━", "┳", "┓", \ - "┃", "┃", "┃", \ - "┣", "━", "╋", "┫", \ - "┗", "━", "┻", "┛" \ + "┌", "─", "┬", "┐", \ + "│", "│", "│", \ + "├", "─", "┼", "┤", \ + "└", "─", "┴", "┘" \ }, \ /* separator_chars */ \ { \ - "┣", "━", "╋", "┫", \ + "├", "─", "┼", "┤", \ }, \ } +#define SOLID_ROUND_STYLE { \ + /* border_chars */ \ + { \ + "╭", "─", "┬", "╮", \ + "│", "│", "│", \ + "", "", "", "", \ + "╰", "─", "┴", "╯" \ + }, \ + /* header_border_chars */ \ + { \ + "╭", "─", "┬", "╮", \ + "│", "│", "│", \ + "├", "─", "┼", "┤", \ + "╰", "─", "┴", "╯" \ + }, \ + /* separator_chars */ \ + { \ + "├", "─", "┼", "┤", \ + }, \ +} + + #define DOUBLE_STYLE { \ /* border_chars */ \ { \ @@ -364,13 +386,104 @@ fort_status_t set_default_cell_option(uint32_t option, int value) } +#define DOUBLE2_STYLE { \ + /* border_chars */ \ + { \ + "╔", "═", "╤", "╗", \ + "║", "│", "║", \ + "╟", "─", "┼", "╢", \ + "╚", "═", "╧", "╝" \ + }, \ + /* header_border_chars */ \ + { \ + "╔", "═", "╤", "╗", \ + "║", "│", "║", \ + "╠", "═", "╪", "╣", \ + "╚", "═", "╧", "╝" \ + }, \ + /* separator_chars */ \ + { \ + "╠", "═", "╪", "╣", \ + }, \ +} + + +#define BOLD_STYLE { \ + /* border_chars */ \ + { \ + "┏", "━", "┳", "┓", \ + "┃", "┃", "┃", \ + "", "", "", "", \ + "┗", "━", "┻", "┛" \ + }, \ + /* header_border_chars */ \ + { \ + "┏", "━", "┳", "┓", \ + "┃", "┃", "┃", \ + "┣", "━", "╋", "┫", \ + "┗", "━", "┻", "┛" \ + }, \ + /* separator_chars */ \ + { \ + "┣", "━", "╋", "┫", \ + }, \ +} + +#define BOLD2_STYLE { \ + /* border_chars */ \ + { \ + "┏", "━", "┯", "┓", \ + "┃", "│", "┃", \ + "┠", "─", "┼", "┨", \ + "┗", "━", "┷", "┛" \ + }, \ + /* header_border_chars */ \ + { \ + "┏", "━", "┯", "┓", \ + "┃", "│", "┃", \ + "┣", "━", "┿", "┫", \ + "┗", "━", "┷", "┛" \ + }, \ + /* separator_chars */ \ + { \ + "┣", "━", "┿", "┫", \ + }, \ +} + +#define FRAME_STYLE { \ + /* border_chars */ \ + { \ + "▛", "▀", "▀", "▜", \ + "▌", "┃", "▐", \ + "", "", "", "", \ + "▙", "▄", "▄", "▟" \ + }, \ + /* header_border_chars */ \ + { \ + "▛", "▀", "▀", "▜", \ + "▌", "┃", "▐", \ + "▌", "━", "╋", "▐", \ + "▙", "▄", "▄", "▟" \ + }, \ + /* separator_chars */ \ + { \ + "▌", "━", "╋", "▐", \ + }, \ +} + + struct fort_border_style FORT_BASIC_STYLE = BASIC_STYLE; struct fort_border_style FORT_SIMPLE_STYLE = SIMPLE_STYLE; struct fort_border_style FORT_PLAIN_STYLE = PLAIN_STYLE; struct fort_border_style FORT_DOT_STYLE = DOT_STYLE; struct fort_border_style FORT_EMPTY_STYLE = EMPTY_STYLE; struct fort_border_style FORT_SOLID_STYLE = SOLID_STYLE; +struct fort_border_style FORT_SOLID_ROUND_STYLE = SOLID_ROUND_STYLE; struct fort_border_style FORT_DOUBLE_STYLE = DOUBLE_STYLE; +struct fort_border_style FORT_DOUBLE2_STYLE = DOUBLE2_STYLE; +struct fort_border_style FORT_BOLD_STYLE = BOLD_STYLE; +struct fort_border_style FORT_BOLD2_STYLE = BOLD2_STYLE; +struct fort_border_style FORT_FRAME_STYLE = FRAME_STYLE; diff --git a/src/options.h b/src/options.h index 1f2b463..5d7a95a 100644 --- a/src/options.h +++ b/src/options.h @@ -122,7 +122,12 @@ extern struct fort_border_style FORT_PLAIN_STYLE; extern struct fort_border_style FORT_DOT_STYLE; extern struct fort_border_style FORT_EMPTY_STYLE; extern struct fort_border_style FORT_SOLID_STYLE; +extern struct fort_border_style FORT_SOLID_ROUND_STYLE; extern struct fort_border_style FORT_DOUBLE_STYLE; +extern struct fort_border_style FORT_DOUBLE2_STYLE; +extern struct fort_border_style FORT_BOLD_STYLE; +extern struct fort_border_style FORT_BOLD2_STYLE; +extern struct fort_border_style FORT_FRAME_STYLE; struct fort_entire_table_options diff --git a/src/row.c b/src/row.c index b5da372..ef12ea1 100644 --- a/src/row.c +++ b/src/row.c @@ -158,6 +158,34 @@ int get_row_cell_types(const fort_row_t *row, enum CellType *types, size_t types return FT_SUCCESS; } +fort_status_t row_set_cell_span(fort_row_t *row, size_t cell_column, size_t hor_span) +{ + assert(row); + + if (hor_span < 2) + return FT_EINVAL; + + fort_cell_t *main_cell = get_cell_and_create_if_not_exists(row, cell_column); + if (main_cell == NULL) { + return FT_ERROR; + } + set_cell_type(main_cell, GroupMasterCell); + --hor_span; + ++cell_column; + + while (hor_span) { + fort_cell_t *slave_cell = get_cell_and_create_if_not_exists(row, cell_column); + if (slave_cell == NULL) { + return FT_ERROR; + } + set_cell_type(slave_cell, GroupSlaveCell); + --hor_span; + ++cell_column; + } + + return FT_SUCCESS; +} + @@ -970,3 +998,5 @@ clear: return -1; } + + diff --git a/src/row.h b/src/row.h index f3d8d1e..1660133 100644 --- a/src/row.h +++ b/src/row.h @@ -29,6 +29,7 @@ fort_status_t swap_row(fort_row_t *cur_row, fort_row_t *ins_row, size_t pos); size_t group_cell_number(const fort_row_t *row, size_t master_cell_col); int get_row_cell_types(const fort_row_t *row, enum CellType *types, size_t types_sz); +fort_status_t row_set_cell_span(fort_row_t *row, size_t cell_column, size_t hor_span); int print_row_separator(char *buffer, size_t buffer_sz, const size_t *col_width_arr, size_t cols, diff --git a/src/string_buffer.c b/src/string_buffer.c index bb359df..4aa0e0f 100644 --- a/src/string_buffer.c +++ b/src/string_buffer.c @@ -155,6 +155,12 @@ string_buffer_t *create_string_buffer(size_t number_of_chars, enum str_buf_type result->data_sz = sz; result->type = type; + if (sz && type == CharBuf) { + result->str.cstr[0] = '\0'; + } else if (sz && type == WCharBuf) { + result->str.wstr[0] = L'\0'; + } + return result; } diff --git a/tests/test_table_options.c b/tests/test_table_options.c index b556384..0d93b44 100644 --- a/tests/test_table_options.c +++ b/tests/test_table_options.c @@ -434,4 +434,63 @@ void test_table_cell_options(void) assert_str_equal(table_str, table_str_etalon); ft_destroy_table(table); } + + + WHEN("Cells with spans") { + set_test_options_as_default(); + + table = ft_create_table(); + int n = ft_set_cell_span(table, 0, 0, 5); + assert_true(n == FT_SUCCESS); + n = ft_set_cell_span(table, 1, 1, 3); + assert_true(n == FT_SUCCESS); + + n = ft_set_cell_option(table, 0, FT_ANY_COLUMN, FT_COPT_ROW_TYPE, FT_ROW_HEADER); + assert_true(n == FT_SUCCESS); + n = ft_set_cell_option(table, 1, FT_ANY_COLUMN, FT_COPT_ROW_TYPE, FT_ROW_HEADER); + assert_true(n == FT_SUCCESS); + + n = ft_write_ln(table, "111", "2222", "33333", "444444", "55555555"); + assert_true(n == FT_SUCCESS); + n = ft_write_ln(table, "2222", "33333", "444444", "55555555", "111"); + assert_true(n == FT_SUCCESS); + + n = ft_write_ln(table, "33333", "444444", "55555555", "111", "2222"); + assert_true(n == FT_SUCCESS); + n = ft_write_ln(table, "2222", "33333", "444444", "55555555", "111"); + assert_true(n == FT_SUCCESS); + n = ft_write_ln(table, "2222", "33333", "444444", "55555555", "111"); + assert_true(n == FT_SUCCESS); + + n = ft_set_cell_span(table, 4, 3, 2); + assert_true(n == FT_SUCCESS); + + + const char *table_str = ft_to_string(table); + assert_true(table_str != NULL); + const char *table_str_etalon = + "+---------------------------------------------+\n" + "| |\n" + "| 111 |\n" + "| |\n" + "+-------+------------------------------+------+\n" + "| | | |\n" + "| 2222 | 33333 | 111 |\n" + "| | | |\n" + "+-------+--------+----------+----------+------+\n" + "| | | | | |\n" + "| 33333 | 444444 | 55555555 | 111 | 2222 |\n" + "| | | | | |\n" + "+-------+--------+----------+----------+------+\n" + "| | | | | |\n" + "| 2222 | 33333 | 444444 | 55555555 | 111 |\n" + "| | | | | |\n" + "+-------+--------+----------+----------+------+\n" + "| | | | |\n" + "| 2222 | 33333 | 444444 | 55555555 |\n" + "| | | | |\n" + "+-------+--------+----------+-----------------+\n"; + assert_str_equal(table_str, table_str_etalon); + ft_destroy_table(table); + } }