[C] Refactoring for utf-8
This commit is contained in:
134
src/cell.c
134
src/cell.c
@@ -14,7 +14,7 @@ fort_cell_t *create_cell(void)
|
||||
fort_cell_t *cell = (fort_cell_t *)F_CALLOC(sizeof(fort_cell_t), 1);
|
||||
if (cell == NULL)
|
||||
return NULL;
|
||||
cell->str_buffer = create_string_buffer(DEFAULT_STR_BUF_SIZE, CharBuf);
|
||||
cell->str_buffer = create_string_buffer(DEFAULT_STR_BUF_SIZE, CHAR_BUF);
|
||||
if (cell->str_buffer == NULL) {
|
||||
F_FREE(cell);
|
||||
return NULL;
|
||||
@@ -78,7 +78,7 @@ size_t hint_width_cell(const fort_cell_t *cell, const context_t *context, enum r
|
||||
size_t cell_padding_right = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_RIGHT_PADDING);
|
||||
size_t result = cell_padding_left + cell_padding_right;
|
||||
if (cell->str_buffer && cell->str_buffer->str.data) {
|
||||
result += buffer_text_width(cell->str_buffer);
|
||||
result += buffer_text_visible_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));
|
||||
|
||||
@@ -113,7 +113,7 @@ size_t hint_height_cell(const fort_cell_t *cell, const context_t *context)
|
||||
size_t cell_empty_string_height = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_EMPTY_STR_HEIGHT);
|
||||
size_t result = cell_padding_top + cell_padding_bottom;
|
||||
if (cell->str_buffer && cell->str_buffer->str.data) {
|
||||
size_t text_height = buffer_text_height(cell->str_buffer);
|
||||
size_t text_height = buffer_text_visible_height(cell->str_buffer);
|
||||
result += text_height == 0 ? cell_empty_string_height : text_height;
|
||||
}
|
||||
return result;
|
||||
@@ -121,14 +121,12 @@ size_t hint_height_cell(const fort_cell_t *cell, const context_t *context)
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
int cell_printf(fort_cell_t *cell, size_t row, char *buf, size_t buf_len, const context_t *context)
|
||||
int cell_printf(fort_cell_t *cell, size_t row, conv_context_t *cntx, size_t vis_width)
|
||||
{
|
||||
const char *space_char = " ";
|
||||
int (*buffer_printf_)(string_buffer_t *, size_t, char *, size_t, const context_t *, const char *, const char *) = buffer_printf;
|
||||
int (*snprint_n_strings_)(char *, size_t, size_t, const char *) = snprint_n_strings;
|
||||
const context_t *context = cntx->cntx;
|
||||
size_t buf_len = vis_width;
|
||||
|
||||
if (cell == NULL || buf_len == 0
|
||||
|| (buf_len <= hint_width_cell(cell, context, VISIBLE_GEOMETRY))) {
|
||||
if (cell == NULL || (vis_width < hint_width_cell(cell, context, VISIBLE_GEOMETRY))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -173,32 +171,35 @@ int cell_printf(fort_cell_t *cell, size_t row, char *buf, size_t buf_len, const
|
||||
#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))
|
||||
#define WRITE_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(print_n_strings(cntx, 1, cell_style_tag))
|
||||
#define WRITE_RESET_CELL_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(print_n_strings(cntx, 1, reset_cell_style_tag))
|
||||
#define WRITE_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(print_n_strings(cntx, 1, content_style_tag))
|
||||
#define WRITE_RESET_CONTENT_STYLE_TAG CHCK_RSLT_ADD_TO_INVISIBLE_WRITTEN(print_n_strings(cntx, 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))) {
|
||||
|| row >= (cell_padding_top + buffer_text_visible_height(cell->str_buffer))) {
|
||||
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));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, buf_len - TOTAL_WRITTEN - R3, FT_SPACE));
|
||||
WRITE_RESET_CELL_STYLE_TAG;
|
||||
|
||||
return (int)TOTAL_WRITTEN;
|
||||
}
|
||||
|
||||
WRITE_CELL_STYLE_TAG;
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, L2, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, L2, FT_SPACE));
|
||||
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));
|
||||
// CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf2_(cell->str_buffer, row - cell_padding_top, cntx, buf_len - TOTAL_WRITTEN - R2 - R3, content_style_tag, reset_content_style_tag));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf(cell->str_buffer, row - cell_padding_top, cntx, vis_width - L2 - R2 , 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_strings2_(cntx, buf_len - TOTAL_WRITTEN - R2 - R3, FT_SPACE));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, vis_width - L2 - R2, FT_SPACE));
|
||||
}
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buf + TOTAL_WRITTEN, buf_len - TOTAL_WRITTEN, R2, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, R2, FT_SPACE));
|
||||
WRITE_RESET_CELL_STYLE_TAG;
|
||||
|
||||
return (int)TOTAL_WRITTEN;
|
||||
@@ -213,101 +214,6 @@ clear:
|
||||
#undef RIGHT
|
||||
}
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
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 *, const char *, const char *) = buffer_wprintf;
|
||||
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, VISIBLE_GEOMETRY))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int cell_padding_top = get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_TOP_PADDING);
|
||||
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);
|
||||
|
||||
size_t written = 0;
|
||||
size_t 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))) {
|
||||
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 (int)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;
|
||||
|
||||
return (int)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
|
||||
|
||||
FT_INTERNAL
|
||||
fort_status_t fill_cell_from_string(fort_cell_t *cell, const char *str)
|
||||
{
|
||||
|
@@ -25,15 +25,12 @@ FT_INTERNAL
|
||||
enum CellType get_cell_type(const fort_cell_t *cell);
|
||||
|
||||
FT_INTERNAL
|
||||
int cell_printf(fort_cell_t *cell, size_t row, char *buf, size_t buf_len, const context_t *context);
|
||||
int cell_printf(fort_cell_t *cell, size_t row, conv_context_t *cntx, size_t cod_width);
|
||||
|
||||
FT_INTERNAL
|
||||
fort_status_t fill_cell_from_string(fort_cell_t *cell, const char *str);
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
FT_INTERNAL
|
||||
int cell_wprintf(fort_cell_t *cell, size_t row, wchar_t *buf, size_t buf_len, const context_t *context);
|
||||
|
||||
FT_INTERNAL
|
||||
fort_status_t fill_cell_from_wstring(fort_cell_t *cell, const wchar_t *str);
|
||||
#endif
|
||||
|
18
src/fort.h
18
src/fort.h
@@ -63,6 +63,10 @@ SOFTWARE.
|
||||
#define FT_HAVE_WCHAR
|
||||
#endif
|
||||
|
||||
#define FT_CONGIG_HAVE_UTF8
|
||||
#if defined(FT_CONGIG_HAVE_UTF8)
|
||||
#define FT_HAVE_UTF8
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* RETURN CODES
|
||||
@@ -483,8 +487,6 @@ int ft_nwrite_ln(ft_table_t *table, size_t count, const char *cell_content, ...)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Write strings from the array to the table.
|
||||
*
|
||||
@@ -899,6 +901,18 @@ const wchar_t *ft_to_wstring(const ft_table_t *table);
|
||||
|
||||
|
||||
|
||||
#ifdef FT_HAVE_UTF8
|
||||
#define ft_u8write(table, ...)\
|
||||
(ft_nu8write(table, FT_PP_NARG_(__VA_ARGS__), __VA_ARGS__))
|
||||
#define ft_u8write_ln(table, ...)\
|
||||
(ft_nu8write_ln(table, FT_PP_NARG_(__VA_ARGS__), __VA_ARGS__))
|
||||
int ft_nu8write(ft_table_t *table, size_t n, const void *cell_content, ...);
|
||||
int ft_nu8write_ln(ft_table_t *table, size_t n, const void *cell_content, ...);
|
||||
const void *ft_to_u8string(const ft_table_t *table);
|
||||
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
|
||||
|
||||
FT_END_DECLS
|
||||
|
||||
#endif /* LIBFORT_H */
|
||||
|
366
src/fort_impl.c
366
src/fort_impl.c
@@ -344,6 +344,23 @@ static int ft_write_impl(ft_table_t *table, const char *cell_content)
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef FT_HAVE_UTF8
|
||||
static int ft_u8write_impl(ft_table_t *table, const void *cell_content)
|
||||
{
|
||||
assert(table);
|
||||
string_buffer_t *str_buffer = get_cur_str_buffer_and_create_if_not_exists(table);
|
||||
if (str_buffer == NULL)
|
||||
return FT_ERROR;
|
||||
|
||||
int status = fill_buffer_from_u8string(str_buffer, cell_content);
|
||||
if (FT_IS_SUCCESS(status)) {
|
||||
table->cur_col++;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
|
||||
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
|
||||
@@ -412,6 +429,9 @@ int ft_nwrite_ln(ft_table_t *table, size_t count, const char *cell_content, ...)
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
|
||||
int ft_nwwrite(ft_table_t *table, size_t n, const wchar_t *cell_content, ...)
|
||||
@@ -577,209 +597,111 @@ int ft_table_wwrite_ln(ft_table_t *table, size_t rows, size_t cols, const wchar_
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
const char * empty_str_arr[] = {"", (const char *)L"", ""};
|
||||
|
||||
static
|
||||
const char *ft_to_string_impl(const ft_table_t *table, enum str_buf_type b_type)
|
||||
{
|
||||
assert(table);
|
||||
|
||||
const char *result = NULL;
|
||||
|
||||
/* Determing size of table string representation */
|
||||
size_t cod_height = 0;
|
||||
size_t cod_width = 0;
|
||||
int status = table_internal_codepoints_geometry(table, &cod_height, &cod_width);
|
||||
if (FT_IS_ERROR(status)) {
|
||||
return NULL;
|
||||
}
|
||||
size_t n_codepoints = cod_height * cod_width + 1;
|
||||
|
||||
/* Allocate string buffer for string representation */
|
||||
if (table->conv_buffer == NULL) {
|
||||
((ft_table_t *)table)->conv_buffer = create_string_buffer(n_codepoints, b_type);
|
||||
if (table->conv_buffer == NULL)
|
||||
return NULL;
|
||||
}
|
||||
while (string_buffer_cod_width_capacity(table->conv_buffer) < n_codepoints) {
|
||||
if (FT_IS_ERROR(realloc_string_buffer_without_copy(table->conv_buffer))) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
char *buffer = (char *)buffer_get_data(table->conv_buffer);
|
||||
|
||||
size_t cols = 0;
|
||||
size_t rows = 0;
|
||||
size_t *col_vis_width_arr = NULL;
|
||||
size_t *row_vis_height_arr = NULL;
|
||||
status = table_rows_and_cols_geometry(table, &col_vis_width_arr, &cols, &row_vis_height_arr, &rows, VISIBLE_GEOMETRY);
|
||||
if (FT_IS_ERROR(status))
|
||||
return NULL;
|
||||
|
||||
if (rows == 0) {
|
||||
result = empty_str_arr[b_type];
|
||||
goto clear;
|
||||
}
|
||||
|
||||
int tmp = 0;
|
||||
size_t i = 0;
|
||||
context_t context;
|
||||
context.table_properties = (table->properties ? table->properties : &g_table_properties);
|
||||
fort_row_t *prev_row = NULL;
|
||||
fort_row_t *cur_row = NULL;
|
||||
separator_t *cur_sep = NULL;
|
||||
size_t sep_size = vector_size(table->separators);
|
||||
|
||||
conv_context_t cntx;
|
||||
cntx.buf_origin = buffer;
|
||||
cntx.buf = buffer;
|
||||
cntx.raw_avail = string_buffer_raw_capacity(table->conv_buffer);
|
||||
cntx.cntx = &context;
|
||||
cntx.b_type = b_type;
|
||||
|
||||
/* Print top margin */
|
||||
for (i = 0; i < context.table_properties->entire_table_properties.top_margin; ++i) {
|
||||
FT_CHECK(print_n_strings(&cntx, cod_width - 1/* minus new_line*/, FT_SPACE));
|
||||
FT_CHECK(print_n_strings(&cntx, 1, FT_NEWLINE));
|
||||
}
|
||||
|
||||
for (i = 0; i < rows; ++i) {
|
||||
cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL;
|
||||
cur_row = *(fort_row_t **)vector_at(table->rows, i);
|
||||
enum HorSeparatorPos separatorPos = (i == 0) ? TopSeparator : InsideSeparator;
|
||||
context.row = i;
|
||||
FT_CHECK(print_row_separator(&cntx, col_vis_width_arr, cols, prev_row, cur_row, separatorPos, cur_sep));
|
||||
FT_CHECK(snprintf_row(cur_row, &cntx, col_vis_width_arr, cols, row_vis_height_arr[i]));
|
||||
prev_row = cur_row;
|
||||
}
|
||||
cur_row = NULL;
|
||||
cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL;
|
||||
context.row = i;
|
||||
FT_CHECK(print_row_separator(&cntx, col_vis_width_arr, cols, prev_row, cur_row, BottomSeparator, cur_sep));
|
||||
|
||||
/* Print bottom margin */
|
||||
for (i = 0; i < context.table_properties->entire_table_properties.bottom_margin; ++i) {
|
||||
FT_CHECK(print_n_strings(&cntx, cod_width - 1/* minus new_line*/, FT_SPACE));
|
||||
FT_CHECK(print_n_strings(&cntx, 1, FT_NEWLINE));
|
||||
}
|
||||
|
||||
result = buffer;
|
||||
|
||||
clear:
|
||||
F_FREE(col_vis_width_arr);
|
||||
F_FREE(row_vis_height_arr);
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *ft_to_string(const ft_table_t *table)
|
||||
{
|
||||
typedef char char_type;
|
||||
const enum str_buf_type buf_type = CharBuf;
|
||||
const char *space_char = " ";
|
||||
const char *new_line_char = "\n";
|
||||
#define EMPTY_STRING ""
|
||||
int (*snprintf_row_)(const fort_row_t *, char *, size_t, size_t *, size_t, size_t, const context_t *) = snprintf_row;
|
||||
int (*print_row_separator_)(char *, size_t,
|
||||
const size_t *, size_t,
|
||||
const fort_row_t *, const fort_row_t *,
|
||||
enum HorSeparatorPos, const separator_t *,
|
||||
const context_t *) = print_row_separator;
|
||||
int (*snprint_n_strings_)(char *, size_t, size_t, const char *) = snprint_n_strings;
|
||||
assert(table);
|
||||
|
||||
/* Determing size of table string representation */
|
||||
size_t height = 0;
|
||||
size_t width = 0;
|
||||
int status = table_geometry(table, &height, &width);
|
||||
if (FT_IS_ERROR(status)) {
|
||||
return NULL;
|
||||
}
|
||||
size_t sz = height * width + 1;
|
||||
|
||||
/* Allocate string buffer for string representation */
|
||||
if (table->conv_buffer == NULL) {
|
||||
((ft_table_t *)table)->conv_buffer = create_string_buffer(sz, buf_type);
|
||||
if (table->conv_buffer == NULL)
|
||||
return NULL;
|
||||
}
|
||||
while (string_buffer_capacity(table->conv_buffer) < sz) {
|
||||
if (FT_IS_ERROR(realloc_string_buffer_without_copy(table->conv_buffer))) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
char_type *buffer = (char_type *)buffer_get_data(table->conv_buffer);
|
||||
|
||||
|
||||
size_t cols = 0;
|
||||
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, VISIBLE_GEOMETRY);
|
||||
if (FT_IS_ERROR(status))
|
||||
return NULL;
|
||||
|
||||
if (rows == 0)
|
||||
return EMPTY_STRING;
|
||||
|
||||
size_t written = 0;
|
||||
int tmp = 0;
|
||||
size_t i = 0;
|
||||
context_t context;
|
||||
context.table_properties = (table->properties ? table->properties : &g_table_properties);
|
||||
fort_row_t *prev_row = NULL;
|
||||
fort_row_t *cur_row = NULL;
|
||||
separator_t *cur_sep = NULL;
|
||||
size_t sep_size = vector_size(table->separators);
|
||||
|
||||
/* Print top margin */
|
||||
for (i = 0; i < context.table_properties->entire_table_properties.top_margin; ++i) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char));
|
||||
}
|
||||
|
||||
for (i = 0; i < rows; ++i) {
|
||||
cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL;
|
||||
cur_row = *(fort_row_t **)vector_at(table->rows, i);
|
||||
enum HorSeparatorPos separatorPos = (i == 0) ? TopSeparator : InsideSeparator;
|
||||
context.row = i;
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, separatorPos, cur_sep, &context));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprintf_row_(cur_row, buffer + written, sz - written, col_width_arr, cols, row_height_arr[i], &context));
|
||||
prev_row = cur_row;
|
||||
}
|
||||
cur_row = NULL;
|
||||
cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL;
|
||||
context.row = i;
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, BottomSeparator, cur_sep, &context));
|
||||
|
||||
/* Print bottom margin */
|
||||
for (i = 0; i < context.table_properties->entire_table_properties.bottom_margin; ++i) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char));
|
||||
}
|
||||
|
||||
|
||||
F_FREE(col_width_arr);
|
||||
F_FREE(row_height_arr);
|
||||
return buffer;
|
||||
|
||||
clear:
|
||||
F_FREE(col_width_arr);
|
||||
F_FREE(row_height_arr);
|
||||
return NULL;
|
||||
#undef EMPTY_STRING
|
||||
return ft_to_string_impl(table, CHAR_BUF);
|
||||
}
|
||||
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
|
||||
const wchar_t *ft_to_wstring(const ft_table_t *table)
|
||||
{
|
||||
typedef wchar_t char_type;
|
||||
const enum str_buf_type buf_type = WCharBuf;
|
||||
const char *space_char = " ";
|
||||
const char *new_line_char = "\n";
|
||||
#define EMPTY_STRING L""
|
||||
int (*snprintf_row_)(const fort_row_t *, wchar_t *, size_t, size_t *, size_t, size_t, const context_t *) = wsnprintf_row;
|
||||
int (*print_row_separator_)(wchar_t *, size_t,
|
||||
const size_t *, size_t,
|
||||
const fort_row_t *, const fort_row_t *,
|
||||
enum HorSeparatorPos, const separator_t *,
|
||||
const context_t *) = wprint_row_separator;
|
||||
int (*snprint_n_strings_)(wchar_t *, size_t, size_t, const char *) = wsnprint_n_string;
|
||||
|
||||
|
||||
assert(table);
|
||||
|
||||
/* Determing size of table string representation */
|
||||
size_t height = 0;
|
||||
size_t width = 0;
|
||||
int status = table_geometry(table, &height, &width);
|
||||
if (FT_IS_ERROR(status)) {
|
||||
return NULL;
|
||||
}
|
||||
size_t sz = height * width + 1;
|
||||
|
||||
/* Allocate string buffer for string representation */
|
||||
if (table->conv_buffer == NULL) {
|
||||
((ft_table_t *)table)->conv_buffer = create_string_buffer(sz, buf_type);
|
||||
if (table->conv_buffer == NULL)
|
||||
return NULL;
|
||||
}
|
||||
while (string_buffer_capacity(table->conv_buffer) < sz) {
|
||||
if (FT_IS_ERROR(realloc_string_buffer_without_copy(table->conv_buffer))) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
char_type *buffer = (char_type *)buffer_get_data(table->conv_buffer);
|
||||
|
||||
|
||||
size_t cols = 0;
|
||||
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, VISIBLE_GEOMETRY);
|
||||
|
||||
if (rows == 0)
|
||||
return EMPTY_STRING;
|
||||
|
||||
if (FT_IS_ERROR(status))
|
||||
return NULL;
|
||||
|
||||
size_t written = 0;
|
||||
int tmp = 0;
|
||||
size_t i = 0;
|
||||
context_t context;
|
||||
context.table_properties = (table->properties ? table->properties : &g_table_properties);
|
||||
fort_row_t *prev_row = NULL;
|
||||
fort_row_t *cur_row = NULL;
|
||||
separator_t *cur_sep = NULL;
|
||||
size_t sep_size = vector_size(table->separators);
|
||||
|
||||
/* Print top margin */
|
||||
for (i = 0; i < context.table_properties->entire_table_properties.top_margin; ++i) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char));
|
||||
}
|
||||
|
||||
for (i = 0; i < rows; ++i) {
|
||||
cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL;
|
||||
cur_row = *(fort_row_t **)vector_at(table->rows, i);
|
||||
enum HorSeparatorPos separatorPos = (i == 0) ? TopSeparator : InsideSeparator;
|
||||
context.row = i;
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, separatorPos, cur_sep, &context));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprintf_row_(cur_row, buffer + written, sz - written, col_width_arr, cols, row_height_arr[i], &context));
|
||||
prev_row = cur_row;
|
||||
}
|
||||
cur_row = NULL;
|
||||
cur_sep = (i < sep_size) ? (*(separator_t **)vector_at(table->separators, i)) : NULL;
|
||||
context.row = i;
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_row_separator_(buffer + written, sz - written, col_width_arr, cols, prev_row, cur_row, BottomSeparator, cur_sep, &context));
|
||||
|
||||
/* Print bottom margin */
|
||||
for (i = 0; i < context.table_properties->entire_table_properties.bottom_margin; ++i) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, width - 1/* minus new_line*/, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, sz - written, 1, new_line_char));
|
||||
}
|
||||
|
||||
F_FREE(col_width_arr);
|
||||
F_FREE(row_height_arr);
|
||||
return buffer;
|
||||
|
||||
clear:
|
||||
F_FREE(col_width_arr);
|
||||
F_FREE(row_height_arr);
|
||||
return NULL;
|
||||
#undef EMPTY_STRING
|
||||
return (const wchar_t *)ft_to_string_impl(table, W_CHAR_BUF);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -999,3 +921,61 @@ int ft_set_cell_span(ft_table_t *table, size_t row, size_t col, size_t hor_span)
|
||||
|
||||
return row_set_cell_span(row_p, col, hor_span);
|
||||
}
|
||||
|
||||
#ifdef FT_HAVE_UTF8
|
||||
|
||||
int ft_nu8write(ft_table_t *table, size_t n, const void *cell_content, ...)
|
||||
{
|
||||
size_t i = 0;
|
||||
assert(table);
|
||||
int status = ft_u8write_impl(table, cell_content);
|
||||
if (FT_IS_ERROR(status))
|
||||
return status;
|
||||
|
||||
va_list va;
|
||||
va_start(va, cell_content);
|
||||
--n;
|
||||
for (i = 0; i < n; ++i) {
|
||||
const void *cell = va_arg(va, const void *);
|
||||
status = ft_u8write_impl(table, cell);
|
||||
if (FT_IS_ERROR(status)) {
|
||||
va_end(va);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
ft_ln(table);
|
||||
return status;
|
||||
}
|
||||
|
||||
int ft_nu8write_ln(ft_table_t *table, size_t n, const void *cell_content, ...)
|
||||
{
|
||||
size_t i = 0;
|
||||
assert(table);
|
||||
int status = ft_u8write_impl(table, cell_content);
|
||||
if (FT_IS_ERROR(status))
|
||||
return status;
|
||||
|
||||
va_list va;
|
||||
va_start(va, cell_content);
|
||||
--n;
|
||||
for (i = 0; i < n; ++i) {
|
||||
const void *cell = va_arg(va, const void *);
|
||||
status = ft_u8write_impl(table, cell);
|
||||
if (FT_IS_ERROR(status)) {
|
||||
va_end(va);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
va_end(va);
|
||||
|
||||
ft_ln(table);
|
||||
return status;
|
||||
}
|
||||
|
||||
const void *ft_to_u8string(const ft_table_t *table)
|
||||
{
|
||||
return (const void *)ft_to_string_impl(table, UTF8_BUF);
|
||||
}
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
|
164
src/fort_utils.c
164
src/fort_utils.c
@@ -2,6 +2,9 @@
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
#if defined(FT_HAVE_UTF8)
|
||||
#include "utf8.h"
|
||||
#endif
|
||||
|
||||
|
||||
char g_col_separator = FORT_DEFAULT_COL_SEPARATOR;
|
||||
@@ -169,9 +172,26 @@ size_t number_of_columns_in_format_wstring(const wchar_t *fmt)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(FT_HAVE_UTF8)
|
||||
FT_INTERNAL
|
||||
int snprint_n_strings(char *buf, size_t length, size_t n, const char *str)
|
||||
size_t number_of_columns_in_format_u8string(const void *fmt)
|
||||
{
|
||||
size_t separator_counter = 0;
|
||||
const char *pos = fmt;
|
||||
while (1) {
|
||||
pos = utf8chr(pos, g_col_separator);
|
||||
if (pos == NULL)
|
||||
break;
|
||||
|
||||
separator_counter++;
|
||||
++pos;
|
||||
}
|
||||
return separator_counter + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
int snprint_n_strings_impl(char *buf, size_t length, size_t n, const char *str)
|
||||
{
|
||||
size_t str_len = strlen(str);
|
||||
if (length <= n * str_len)
|
||||
@@ -200,17 +220,123 @@ int snprint_n_strings(char *buf, size_t length, size_t n, const char *str)
|
||||
return (int)(n * str_len);
|
||||
}
|
||||
|
||||
static
|
||||
int snprint_n_strings(conv_context_t *cntx, size_t n, const char *str)
|
||||
{
|
||||
int w = snprint_n_strings_impl(cntx->buf, cntx->raw_avail, n, str);
|
||||
if (w >= 0) {
|
||||
cntx->buf += w;
|
||||
cntx->raw_avail -= w;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
#if defined(FT_HAVE_WCHAR)
|
||||
static
|
||||
int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str);
|
||||
#endif
|
||||
|
||||
#if defined(FT_HAVE_UTF8)
|
||||
static
|
||||
int u8nprint_n_strings(void *buf, size_t length, size_t n, const void *str);
|
||||
#endif
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
int print_n_strings(conv_context_t *cntx, size_t n, const char *str)
|
||||
{
|
||||
int cod_w;
|
||||
int raw_written;
|
||||
|
||||
switch (cntx->b_type) {
|
||||
case CHAR_BUF:
|
||||
return snprint_n_strings(cntx, n, str);
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
case W_CHAR_BUF:
|
||||
cod_w = wsnprint_n_string((wchar_t *)cntx->buf, cntx->raw_avail, n, str);
|
||||
if (cod_w < 0)
|
||||
return cod_w;
|
||||
raw_written = sizeof(wchar_t) * cod_w;
|
||||
|
||||
cntx->buf += raw_written;
|
||||
cntx->raw_avail -= raw_written;
|
||||
return cod_w;
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
#ifdef FT_HAVE_UTF8
|
||||
case UTF8_BUF:
|
||||
/* Everying is very strange and differs with W_CHAR_BUF */
|
||||
raw_written = u8nprint_n_strings(cntx->buf, cntx->raw_avail, n, str);
|
||||
if (raw_written < 0) {
|
||||
fprintf(stderr, " raw_written = %d\n", raw_written);
|
||||
return raw_written;
|
||||
}
|
||||
|
||||
cntx->buf += raw_written;
|
||||
cntx->raw_avail -= raw_written;
|
||||
return utf8len(str) * n;
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
default:
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
FT_INTERNAL
|
||||
int ft_nprint(conv_context_t *cntx, const char *str, size_t strlen)
|
||||
{
|
||||
if (cntx->raw_avail + 1/* for 0 */ < strlen)
|
||||
return -1;
|
||||
|
||||
memcpy(cntx->buf, str, strlen);
|
||||
cntx->buf += strlen;
|
||||
cntx->raw_avail -= strlen;
|
||||
*cntx->buf = '\0'; /* Do we need this ? */
|
||||
return strlen;
|
||||
}
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
int ft_nwprint(conv_context_t *cntx, const wchar_t *str, size_t strlen)
|
||||
{
|
||||
if (cntx->raw_avail + 1/* for 0 */ < strlen)
|
||||
return -1;
|
||||
|
||||
size_t raw_len = strlen * sizeof(wchar_t);
|
||||
|
||||
memcpy(cntx->buf, str, raw_len);
|
||||
cntx->buf += raw_len;
|
||||
cntx->raw_avail -= raw_len;
|
||||
*(wchar_t *)cntx->buf = L'\0'; /* Do we need this ? */
|
||||
return strlen;
|
||||
}
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
|
||||
#ifdef FT_HAVE_UTF8
|
||||
FT_INTERNAL
|
||||
int ft_nu8print(conv_context_t *cntx, const void *beg, const void *end)
|
||||
{
|
||||
const char *bc = beg;
|
||||
const char *ec = end;
|
||||
size_t raw_len = ec - bc;
|
||||
if (cntx->raw_avail + 1 < raw_len)
|
||||
return -1;
|
||||
|
||||
memcpy(cntx->buf, beg, raw_len);
|
||||
cntx->buf += raw_len;
|
||||
cntx->raw_avail -= raw_len;
|
||||
*(char *)cntx->buf = '\0'; /* Do we need this ? */
|
||||
return raw_len; /* what return here ? */
|
||||
}
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
|
||||
#if defined(FT_HAVE_WCHAR)
|
||||
#define WCS_SIZE 64
|
||||
|
||||
FT_INTERNAL
|
||||
static
|
||||
int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str)
|
||||
{
|
||||
size_t str_len = strlen(str);
|
||||
|
||||
/* note: baybe it's, better to return -1 in case of multibyte character
|
||||
/* note: maybe it's, better to return -1 in case of multibyte character
|
||||
* strings (not sure this case is done correctly).
|
||||
*/
|
||||
if (str_len > 1) {
|
||||
@@ -269,3 +395,33 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str)
|
||||
return (int)(n * str_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(FT_HAVE_UTF8)
|
||||
static
|
||||
int u8nprint_n_strings(void *buf, size_t length, size_t n, const void *str)
|
||||
{
|
||||
size_t str_size = utf8size(str) - 1; /* str_size - raw size in bytes, excluding \0 */
|
||||
if (length <= n * str_size)
|
||||
return -1;
|
||||
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
/* To ensure valid return value it is safely not print such big strings */
|
||||
if (n * str_size > INT_MAX)
|
||||
return -1;
|
||||
|
||||
if (str_size == 0)
|
||||
return 0;
|
||||
|
||||
size_t i = n;
|
||||
while (i) {
|
||||
memcpy(buf, str, str_size);
|
||||
buf = (char *)buf + str_size;
|
||||
--i;
|
||||
}
|
||||
*(char *)buf = '\0';
|
||||
return (int)(n * str_size);
|
||||
}
|
||||
#endif
|
||||
|
@@ -35,12 +35,16 @@ extern char g_col_separator;
|
||||
#define F_REALLOC fort_realloc
|
||||
#define F_STRDUP fort_strdup
|
||||
#define F_WCSDUP fort_wcsdup
|
||||
/* @todo: replace with custom impl !!!*/
|
||||
#define F_UTF8DUP utf8dup
|
||||
|
||||
#define F_CREATE(type) ((type *)F_CALLOC(sizeof(type), 1))
|
||||
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define FT_NEWLINE "\n"
|
||||
#define FT_SPACE " "
|
||||
|
||||
enum PolicyOnNull {
|
||||
Create,
|
||||
@@ -53,6 +57,20 @@ enum F_BOOL {
|
||||
F_TRUE = 1
|
||||
};
|
||||
|
||||
enum str_buf_type {
|
||||
CHAR_BUF,
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
W_CHAR_BUF,
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
#ifdef FT_HAVE_UTF8
|
||||
UTF8_BUF,
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
TYPE_END
|
||||
};
|
||||
|
||||
|
||||
typedef const char ** str_arr;
|
||||
|
||||
|
||||
#define FT_STR_2_CAT_(arg1, arg2) \
|
||||
arg1##arg2
|
||||
@@ -117,6 +135,16 @@ enum request_geom_type {
|
||||
INTERN_REPR_GEOMETRY
|
||||
};
|
||||
|
||||
struct conv_context {
|
||||
char *buf_origin;
|
||||
char *buf;
|
||||
size_t raw_avail;
|
||||
struct fort_context *cntx;
|
||||
enum str_buf_type b_type;
|
||||
};
|
||||
typedef struct conv_context conv_context_t;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* LIBFORT helpers
|
||||
*****************************************************************************/
|
||||
@@ -144,18 +172,38 @@ size_t number_of_columns_in_format_wstring(const wchar_t *fmt);
|
||||
#endif
|
||||
|
||||
FT_INTERNAL
|
||||
int snprint_n_strings(char *buf, size_t length, size_t n, const char *str);
|
||||
int print_n_strings(conv_context_t *cntx, size_t n, const char *str);
|
||||
|
||||
|
||||
#if defined(FT_HAVE_WCHAR)
|
||||
FT_INTERNAL
|
||||
int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str);
|
||||
#endif
|
||||
int ft_nprint(conv_context_t *cntx, const char *str, size_t strlen);
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
FT_INTERNAL
|
||||
int ft_nwprint(conv_context_t *cntx, const wchar_t *str, size_t strlen);
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
#ifdef FT_HAVE_UTF8
|
||||
FT_INTERNAL
|
||||
int ft_nu8print(conv_context_t *cntx, const void *beg, const void *end);
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
|
||||
|
||||
/*#define PRINT_DEBUG_INFO fprintf(stderr, "error in %s(%s:%d)\n", __FUNCTION__, __FILE__, __LINE__);*/
|
||||
#define PRINT_DEBUG_INFO
|
||||
|
||||
#define FT_CHECK(statement) \
|
||||
do { \
|
||||
tmp = statement; \
|
||||
if (tmp < 0) {\
|
||||
PRINT_DEBUG_INFO \
|
||||
goto clear; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define CHCK_RSLT_ADD_TO_WRITTEN(statement) \
|
||||
do { \
|
||||
tmp = statement; \
|
||||
if (tmp < 0) {\
|
||||
PRINT_DEBUG_INFO \
|
||||
goto clear; \
|
||||
} \
|
||||
written += (size_t)tmp; \
|
||||
@@ -165,6 +213,7 @@ int wsnprint_n_string(wchar_t *buf, size_t length, size_t n, const char *str);
|
||||
do { \
|
||||
tmp = statement; \
|
||||
if (tmp < 0) {\
|
||||
PRINT_DEBUG_INFO \
|
||||
goto clear; \
|
||||
} \
|
||||
invisible_written += (size_t)tmp; \
|
||||
|
357
src/row.c
357
src/row.c
@@ -225,22 +225,20 @@ fort_status_t row_set_cell_span(fort_row_t *row, size_t cell_column, size_t hor_
|
||||
return FT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
int print_row_separator(char *buffer, size_t buffer_sz,
|
||||
int print_row_separator_impl(conv_context_t *cntx,
|
||||
const size_t *col_width_arr, size_t cols,
|
||||
const fort_row_t *upper_row, const fort_row_t *lower_row,
|
||||
enum HorSeparatorPos separatorPos,
|
||||
const separator_t *sep, const context_t *context)
|
||||
const separator_t *sep)
|
||||
{
|
||||
int (*snprint_n_strings_)(char *, size_t, size_t, const char *) = snprint_n_strings;
|
||||
|
||||
assert(buffer);
|
||||
assert(context);
|
||||
assert(cntx);
|
||||
|
||||
const char *space_char = " ";
|
||||
int status = -1;
|
||||
|
||||
const context_t *context = cntx->cntx;
|
||||
|
||||
/* Get cell types
|
||||
*
|
||||
* Regions above top row and below bottom row areconsidered full of virtual
|
||||
@@ -378,31 +376,31 @@ int print_row_separator(char *buffer, size_t buffer_sz,
|
||||
}
|
||||
|
||||
/* Print left margin */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, context->table_properties->entire_table_properties.left_margin, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, context->table_properties->entire_table_properties.left_margin, space_char));
|
||||
|
||||
for (i = 0; i < cols; ++i) {
|
||||
if (i == 0) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *L));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, *L));
|
||||
} else {
|
||||
if ((top_row_types[i] == CommonCell || top_row_types[i] == GroupMasterCell)
|
||||
&& (bottom_row_types[i] == CommonCell || bottom_row_types[i] == GroupMasterCell)) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *IV));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, *IV));
|
||||
} else if (top_row_types[i] == GroupSlaveCell && bottom_row_types[i] == GroupSlaveCell) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *II));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, *II));
|
||||
} else if (top_row_types[i] == GroupSlaveCell) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *IT));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, *IT));
|
||||
} else {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *IB));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, *IB));
|
||||
}
|
||||
}
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, col_width_arr[i], *I));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, col_width_arr[i], *I));
|
||||
}
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *R));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, *R));
|
||||
|
||||
/* Print right margin */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, context->table_properties->entire_table_properties.right_margin, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, context->table_properties->entire_table_properties.right_margin, space_char));
|
||||
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, "\n"));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, "\n"));
|
||||
|
||||
status = (int)written;
|
||||
|
||||
@@ -411,195 +409,16 @@ clear:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
FT_INTERNAL
|
||||
int wprint_row_separator(wchar_t *buffer, size_t buffer_sz,
|
||||
const size_t *col_width_arr, size_t cols,
|
||||
const fort_row_t *upper_row, const fort_row_t *lower_row,
|
||||
enum HorSeparatorPos separatorPos, const separator_t *sep,
|
||||
const context_t *context)
|
||||
int print_row_separator(conv_context_t *cntx,
|
||||
const size_t *col_width_arr, size_t cols,
|
||||
const fort_row_t *upper_row, const fort_row_t *lower_row,
|
||||
enum HorSeparatorPos separatorPos, const separator_t *sep)
|
||||
{
|
||||
int (*snprint_n_strings_)(wchar_t *, size_t, size_t, const char *) = wsnprint_n_string;
|
||||
|
||||
assert(buffer);
|
||||
assert(context);
|
||||
|
||||
const char *space_char = " ";
|
||||
int status = -1;
|
||||
|
||||
/* Get cell types
|
||||
*
|
||||
* Regions above top row and below bottom row areconsidered full of virtual
|
||||
* GroupSlaveCell cells
|
||||
*/
|
||||
enum CellType *top_row_types = (enum CellType *)F_MALLOC(sizeof(enum CellType) * cols * 2);
|
||||
if (top_row_types == NULL) {
|
||||
return FT_MEMORY_ERROR;
|
||||
}
|
||||
enum CellType *bottom_row_types = top_row_types + cols;
|
||||
if (upper_row) {
|
||||
get_row_cell_types(upper_row, top_row_types, cols);
|
||||
} else {
|
||||
size_t i = 0;
|
||||
for (i = 0; i < cols; ++i)
|
||||
top_row_types[i] = GroupSlaveCell;
|
||||
}
|
||||
if (lower_row) {
|
||||
get_row_cell_types(lower_row, bottom_row_types, cols);
|
||||
} else {
|
||||
size_t i = 0;
|
||||
for (i = 0; i < cols; ++i)
|
||||
bottom_row_types[i] = GroupSlaveCell;
|
||||
}
|
||||
|
||||
|
||||
size_t written = 0;
|
||||
int tmp = 0;
|
||||
|
||||
enum ft_row_type lower_row_type = FT_ROW_COMMON;
|
||||
if (lower_row != NULL) {
|
||||
lower_row_type = (enum ft_row_type)get_cell_property_value_hierarcial(context->table_properties, context->row, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE);
|
||||
}
|
||||
enum ft_row_type upper_row_type = FT_ROW_COMMON;
|
||||
if (upper_row != NULL) {
|
||||
upper_row_type = (enum ft_row_type)get_cell_property_value_hierarcial(context->table_properties, context->row - 1, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE);
|
||||
}
|
||||
|
||||
/* Row separator anatomy
|
||||
*
|
||||
* | C11 | C12 C13 | C14 C15 |
|
||||
* L I I I IV I I IT I I I IB I I II I I R
|
||||
* | C21 | C22 | C23 C24 C25 |
|
||||
*/
|
||||
const char **L = NULL;
|
||||
const char **I = NULL;
|
||||
const char **IV = NULL;
|
||||
const char **R = NULL;
|
||||
const char **IT = NULL;
|
||||
const char **IB = NULL;
|
||||
const char **II = NULL;
|
||||
|
||||
|
||||
typedef const char *(*border_chars_point_t)[BorderItemPosSize];
|
||||
const char *(*border_chars)[BorderItemPosSize] = NULL;
|
||||
border_chars = (border_chars_point_t)&context->table_properties->border_style.border_chars;
|
||||
if (upper_row_type == FT_ROW_HEADER || lower_row_type == FT_ROW_HEADER) {
|
||||
border_chars = (border_chars_point_t)&context->table_properties->border_style.header_border_chars;
|
||||
}
|
||||
|
||||
if (sep && sep->enabled) {
|
||||
L = &(context->table_properties->border_style.separator_chars[LH_sip]);
|
||||
I = &(context->table_properties->border_style.separator_chars[IH_sip]);
|
||||
IV = &(context->table_properties->border_style.separator_chars[II_sip]);
|
||||
R = &(context->table_properties->border_style.separator_chars[RH_sip]);
|
||||
|
||||
IT = &(context->table_properties->border_style.separator_chars[TI_sip]);
|
||||
IB = &(context->table_properties->border_style.separator_chars[BI_sip]);
|
||||
II = &(context->table_properties->border_style.separator_chars[IH_sip]);
|
||||
|
||||
if (lower_row == NULL) {
|
||||
L = &(*border_chars)[BL_bip];
|
||||
R = &(*border_chars)[BR_bip];
|
||||
} else if (upper_row == NULL) {
|
||||
L = &(*border_chars)[TL_bip];
|
||||
R = &(*border_chars)[TR_bip];
|
||||
}
|
||||
} else {
|
||||
switch (separatorPos) {
|
||||
case TopSeparator:
|
||||
L = &(*border_chars)[TL_bip];
|
||||
I = &(*border_chars)[TT_bip];
|
||||
IV = &(*border_chars)[TV_bip];
|
||||
R = &(*border_chars)[TR_bip];
|
||||
|
||||
IT = &(*border_chars)[TV_bip];
|
||||
IB = &(*border_chars)[TV_bip];
|
||||
II = &(*border_chars)[TT_bip];
|
||||
break;
|
||||
case InsideSeparator:
|
||||
L = &(*border_chars)[LH_bip];
|
||||
I = &(*border_chars)[IH_bip];
|
||||
IV = &(*border_chars)[II_bip];
|
||||
R = &(*border_chars)[RH_bip];
|
||||
|
||||
/*
|
||||
IT = &(*border_chars)[TV_bip];
|
||||
IB = &(*border_chars)[BV_bip];
|
||||
*/
|
||||
IT = &(*border_chars)[TI_bip];
|
||||
IB = &(*border_chars)[BI_bip];
|
||||
II = &(*border_chars)[IH_bip];
|
||||
break;
|
||||
case BottomSeparator:
|
||||
L = &(*border_chars)[BL_bip];
|
||||
I = &(*border_chars)[BB_bip];
|
||||
IV = &(*border_chars)[BV_bip];
|
||||
R = &(*border_chars)[BR_bip];
|
||||
|
||||
IT = &(*border_chars)[BV_bip];
|
||||
IB = &(*border_chars)[BV_bip];
|
||||
II = &(*border_chars)[BB_bip];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
/* If all chars are not printable, skip line separator */
|
||||
/* todo: add processing for wchar_t */
|
||||
/*
|
||||
if (!isprint(*L) && !isprint(*I) && !isprint(*IV) && !isprint(*R)) {
|
||||
status = 0;
|
||||
goto clear;
|
||||
}
|
||||
*/
|
||||
if ((strlen(*L) == 0 || (strlen(*L) == 1 && !isprint(**L)))
|
||||
&& (strlen(*I) == 0 || (strlen(*I) == 1 && !isprint(**I)))
|
||||
&& (strlen(*IV) == 0 || (strlen(*IV) == 1 && !isprint(**IV)))
|
||||
&& (strlen(*R) == 0 || (strlen(*R) == 1 && !isprint(**R)))) {
|
||||
status = 0;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
/* Print left margin */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, context->table_properties->entire_table_properties.left_margin, space_char));
|
||||
|
||||
for (i = 0; i < cols; ++i) {
|
||||
if (i == 0) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *L));
|
||||
} else {
|
||||
if ((top_row_types[i] == CommonCell || top_row_types[i] == GroupMasterCell)
|
||||
&& (bottom_row_types[i] == CommonCell || bottom_row_types[i] == GroupMasterCell)) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *IV));
|
||||
} else if (top_row_types[i] == GroupSlaveCell && bottom_row_types[i] == GroupSlaveCell) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *II));
|
||||
} else if (top_row_types[i] == GroupSlaveCell) {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *IT));
|
||||
} else {
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *IB));
|
||||
}
|
||||
}
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, col_width_arr[i], *I));
|
||||
}
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, *R));
|
||||
|
||||
/* Print right margin */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, context->table_properties->entire_table_properties.right_margin, space_char));
|
||||
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buffer_sz - written, 1, "\n"));
|
||||
|
||||
status = (int)written;
|
||||
|
||||
clear:
|
||||
F_FREE(top_row_types);
|
||||
return status;
|
||||
return print_row_separator_impl(cntx, col_width_arr, cols, upper_row, lower_row,
|
||||
separatorPos, sep);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FT_INTERNAL
|
||||
fort_row_t *create_row_from_string(const char *str)
|
||||
{
|
||||
@@ -784,7 +603,7 @@ fort_row_t *create_row_from_fmt_string(const char *fmt, va_list *va_args)
|
||||
#define CREATE_ROW_FROM_STRING create_row_from_string
|
||||
#define NUMBER_OF_COLUMNS_IN_FORMAT_STRING number_of_columns_in_format_string
|
||||
#define FILL_CELL_FROM_STRING fill_cell_from_string
|
||||
#define STR_BUF_TYPE CharBuf
|
||||
#define STR_BUF_TYPE CHAR_BUF
|
||||
|
||||
string_buffer_t *buffer = create_string_buffer(DEFAULT_STR_BUF_SIZE, STR_BUF_TYPE);
|
||||
if (buffer == NULL)
|
||||
@@ -796,14 +615,14 @@ fort_row_t *create_row_from_fmt_string(const char *fmt, va_list *va_args)
|
||||
while (1) {
|
||||
va_list va;
|
||||
va_copy(va, *va_args);
|
||||
int virtual_sz = VSNPRINTF(buffer->str.STR_FILED, string_buffer_capacity(buffer), fmt, va);
|
||||
int virtual_sz = VSNPRINTF(buffer->str.STR_FILED, string_buffer_width_capacity(buffer), fmt, va);
|
||||
va_end(va);
|
||||
/* If error encountered */
|
||||
if (virtual_sz < 0)
|
||||
goto clear;
|
||||
|
||||
/* Successful write */
|
||||
if ((size_t)virtual_sz < string_buffer_capacity(buffer))
|
||||
if ((size_t)virtual_sz < string_buffer_width_capacity(buffer))
|
||||
break;
|
||||
|
||||
/* Otherwise buffer was too small, so incr. buffer size ant try again. */
|
||||
@@ -870,7 +689,7 @@ fort_row_t *create_row_from_fmt_wstring(const wchar_t *fmt, va_list *va_args)
|
||||
#define CREATE_ROW_FROM_STRING create_row_from_wstring
|
||||
#define NUMBER_OF_COLUMNS_IN_FORMAT_STRING number_of_columns_in_format_wstring
|
||||
#define FILL_CELL_FROM_STRING fill_cell_from_wstring
|
||||
#define STR_BUF_TYPE WCharBuf
|
||||
#define STR_BUF_TYPE W_CHAR_BUF
|
||||
|
||||
string_buffer_t *buffer = create_string_buffer(DEFAULT_STR_BUF_SIZE, STR_BUF_TYPE);
|
||||
if (buffer == NULL)
|
||||
@@ -882,14 +701,14 @@ fort_row_t *create_row_from_fmt_wstring(const wchar_t *fmt, va_list *va_args)
|
||||
while (1) {
|
||||
va_list va;
|
||||
va_copy(va, *va_args);
|
||||
int virtual_sz = VSNPRINTF(buffer->str.STR_FILED, string_buffer_capacity(buffer), fmt, va);
|
||||
int virtual_sz = VSNPRINTF(buffer->str.STR_FILED, string_buffer_width_capacity(buffer), fmt, va);
|
||||
va_end(va);
|
||||
/* If error encountered */
|
||||
if (virtual_sz < 0)
|
||||
goto clear;
|
||||
|
||||
/* Successful write */
|
||||
if ((size_t)virtual_sz < string_buffer_capacity(buffer))
|
||||
if ((size_t)virtual_sz < string_buffer_width_capacity(buffer))
|
||||
break;
|
||||
|
||||
/* Otherwise buffer was too small, so incr. buffer size ant try again. */
|
||||
@@ -950,12 +769,10 @@ clear:
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
int snprintf_row(const fort_row_t *row, char *buffer, size_t buf_sz, size_t *col_width_arr, size_t col_width_arr_sz,
|
||||
size_t row_height, const context_t *context)
|
||||
int snprintf_row(const fort_row_t *row, conv_context_t *cntx, size_t *col_width_arr, size_t col_width_arr_sz,
|
||||
size_t row_height)
|
||||
{
|
||||
int (*snprint_n_strings_)(char *, size_t, size_t, const char *) = snprint_n_strings;
|
||||
int (*cell_printf_)(fort_cell_t *, size_t, char *, size_t, const context_t *) = cell_printf;
|
||||
|
||||
const context_t *context = cntx->cntx;
|
||||
assert(context);
|
||||
const char *space_char = " ";
|
||||
const char *new_line_char = "\n";
|
||||
@@ -987,142 +804,50 @@ int snprintf_row(const fort_row_t *row, char *buffer, size_t buf_sz, size_t *col
|
||||
size_t i = 0;
|
||||
for (i = 0; i < row_height; ++i) {
|
||||
/* Print left margin */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, context->table_properties->entire_table_properties.left_margin, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, context->table_properties->entire_table_properties.left_margin, space_char));
|
||||
|
||||
/* Print left table boundary */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, 1, *L));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, *L));
|
||||
size_t j = 0;
|
||||
while (j < col_width_arr_sz) {
|
||||
if (j < cols_in_row) {
|
||||
((context_t *)context)->column = j;
|
||||
fort_cell_t *cell = *(fort_cell_t **)vector_at(row->cells, j);
|
||||
size_t cell_width = 0;
|
||||
size_t cell_vis_width = 0;
|
||||
|
||||
size_t group_slave_sz = group_cell_number(row, j);
|
||||
cell_width = col_width_arr[j];
|
||||
cell_vis_width = col_width_arr[j];
|
||||
size_t slave_j = 0;
|
||||
size_t master_j = j;
|
||||
for (slave_j = master_j + 1; slave_j < (master_j + group_slave_sz); ++slave_j) {
|
||||
cell_width += col_width_arr[slave_j] + FORT_COL_SEPARATOR_LENGTH;
|
||||
cell_vis_width += col_width_arr[slave_j] + FORT_COL_SEPARATOR_LENGTH;
|
||||
++j;
|
||||
}
|
||||
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(cell_printf_(cell, i, buffer + written, cell_width + 1, context));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(cell_printf(cell, i, cntx, cell_vis_width));
|
||||
} else {
|
||||
/* Print empty cell */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, col_width_arr[j], space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, col_width_arr[j], space_char));
|
||||
}
|
||||
|
||||
/* Print boundary between cells */
|
||||
if (j < col_width_arr_sz - 1)
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, 1, *IV));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, *IV));
|
||||
|
||||
++j;
|
||||
}
|
||||
|
||||
/* Print right table boundary */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, 1, *R));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, *R));
|
||||
|
||||
/* Print right margin */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, context->table_properties->entire_table_properties.right_margin, space_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, context->table_properties->entire_table_properties.right_margin, space_char));
|
||||
|
||||
/* Print new line character */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, 1, new_line_char));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, new_line_char));
|
||||
}
|
||||
return (int)written;
|
||||
|
||||
clear:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
FT_INTERNAL
|
||||
int wsnprintf_row(const fort_row_t *row, wchar_t *buffer, size_t buf_sz, size_t *col_width_arr, size_t col_width_arr_sz,
|
||||
size_t row_height, const context_t *context)
|
||||
{
|
||||
int (*snprint_n_strings_)(wchar_t *, size_t, size_t, const char *) = wsnprint_n_string;
|
||||
int (*cell_printf_)(fort_cell_t *, size_t, wchar_t *, size_t, const context_t *) = cell_wprintf;
|
||||
|
||||
assert(context);
|
||||
const char *space_char = " ";
|
||||
const char *new_line_char = "\n";
|
||||
|
||||
if (row == NULL)
|
||||
return -1;
|
||||
|
||||
size_t cols_in_row = columns_in_row(row);
|
||||
if (cols_in_row > col_width_arr_sz)
|
||||
return -1;
|
||||
|
||||
/* Row separator anatomy
|
||||
*
|
||||
* L data IV data IV data R
|
||||
*/
|
||||
|
||||
typedef const char *(*border_chars_point_t)[BorderItemPosSize];
|
||||
enum ft_row_type row_type = (enum ft_row_type)get_cell_property_value_hierarcial(context->table_properties, context->row, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE);
|
||||
const char *(*bord_chars)[BorderItemPosSize] = (row_type == FT_ROW_HEADER)
|
||||
? (border_chars_point_t)(&context->table_properties->border_style.header_border_chars)
|
||||
: (border_chars_point_t)(&context->table_properties->border_style.border_chars);
|
||||
const char **L = &(*bord_chars)[LL_bip];
|
||||
const char **IV = &(*bord_chars)[IV_bip];
|
||||
const char **R = &(*bord_chars)[RR_bip];
|
||||
|
||||
|
||||
size_t written = 0;
|
||||
int tmp = 0;
|
||||
size_t i = 0;
|
||||
for (i = 0; i < row_height; ++i) {
|
||||
/* Print left margin */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, context->table_properties->entire_table_properties.left_margin, space_char));
|
||||
|
||||
/* Print left table boundary */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, 1, *L));
|
||||
size_t j = 0;
|
||||
while (j < col_width_arr_sz) {
|
||||
if (j < cols_in_row) {
|
||||
((context_t *)context)->column = j;
|
||||
fort_cell_t *cell = *(fort_cell_t **)vector_at(row->cells, j);
|
||||
size_t cell_width = 0;
|
||||
|
||||
size_t group_slave_sz = group_cell_number(row, j);
|
||||
cell_width = col_width_arr[j];
|
||||
size_t slave_j = 0;
|
||||
size_t master_j = j;
|
||||
for (slave_j = master_j + 1; slave_j < (master_j + group_slave_sz); ++slave_j) {
|
||||
cell_width += col_width_arr[slave_j] + FORT_COL_SEPARATOR_LENGTH;
|
||||
++j;
|
||||
}
|
||||
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(cell_printf_(cell, i, buffer + written, cell_width + 1, context));
|
||||
} else {
|
||||
/* Print empty cell */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, col_width_arr[j], space_char));
|
||||
}
|
||||
|
||||
/* Print boundary between cells */
|
||||
if (j < col_width_arr_sz - 1)
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, 1, *IV));
|
||||
|
||||
++j;
|
||||
}
|
||||
|
||||
/* Print right table boundary */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, 1, *R));
|
||||
|
||||
/* Print right margin */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, context->table_properties->entire_table_properties.right_margin, space_char));
|
||||
|
||||
/* Print new line character */
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(snprint_n_strings_(buffer + written, buf_sz - written, 1, new_line_char));
|
||||
}
|
||||
return (int)written;
|
||||
|
||||
clear:
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
20
src/row.h
20
src/row.h
@@ -50,15 +50,14 @@ FT_INTERNAL
|
||||
fort_status_t row_set_cell_span(fort_row_t *row, size_t cell_column, size_t hor_span);
|
||||
|
||||
FT_INTERNAL
|
||||
int print_row_separator(char *buffer, size_t buffer_sz,
|
||||
int print_row_separator(conv_context_t *cntx,
|
||||
const size_t *col_width_arr, size_t cols,
|
||||
const fort_row_t *upper_row, const fort_row_t *lower_row,
|
||||
enum HorSeparatorPos separatorPos, const separator_t *sep,
|
||||
const context_t *context);
|
||||
enum HorSeparatorPos separatorPos, const separator_t *sep);
|
||||
|
||||
FT_INTERNAL
|
||||
int snprintf_row(const fort_row_t *row, char *buffer, size_t buf_sz, size_t *col_width_arr, size_t col_width_arr_sz,
|
||||
size_t row_height, const context_t *context);
|
||||
int snprintf_row(const fort_row_t *row, conv_context_t *cntx, size_t *col_width_arr, size_t col_width_arr_sz,
|
||||
size_t row_height);
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
FT_INTERNAL
|
||||
@@ -66,17 +65,6 @@ fort_row_t *create_row_from_wstring(const wchar_t *str);
|
||||
|
||||
FT_INTERNAL
|
||||
fort_row_t *create_row_from_fmt_wstring(const wchar_t *fmt, va_list *va_args);
|
||||
|
||||
FT_INTERNAL
|
||||
int wprint_row_separator(wchar_t *buffer, size_t buffer_sz,
|
||||
const size_t *col_width_arr, size_t cols,
|
||||
const fort_row_t *upper_row, const fort_row_t *lower_row,
|
||||
enum HorSeparatorPos separatorPos, const separator_t *sep,
|
||||
const context_t *context);
|
||||
|
||||
FT_INTERNAL
|
||||
int wsnprintf_row(const fort_row_t *row, wchar_t *buffer, size_t buf_sz, size_t *col_width_arr, size_t col_width_arr_sz,
|
||||
size_t row_height, const context_t *context);
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -3,8 +3,12 @@
|
||||
#include "wcwidth.h"
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
#include <wchar.h>
|
||||
|
||||
#endif
|
||||
#if defined(FT_HAVE_UTF8)
|
||||
#include "utf8.h"
|
||||
#endif
|
||||
|
||||
static ptrdiff_t str_iter_width(const char *beg, const char *end)
|
||||
{
|
||||
@@ -25,11 +29,22 @@ static ptrdiff_t wcs_iter_width(const wchar_t *beg, const wchar_t *end)
|
||||
static size_t buf_str_len(const string_buffer_t *buf)
|
||||
{
|
||||
assert(buf);
|
||||
if (buf->type == CharBuf) {
|
||||
return strlen(buf->str.cstr);
|
||||
} else {
|
||||
return wcslen(buf->str.wstr);
|
||||
|
||||
switch (buf->type) {
|
||||
case CHAR_BUF:
|
||||
return strlen(buf->str.cstr);
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
case W_CHAR_BUF:
|
||||
return wcslen(buf->str.wstr);
|
||||
#endif
|
||||
#ifdef FT_HAVE_UTF8
|
||||
case UTF8_BUF:
|
||||
return utf8len(buf->str.u8str);
|
||||
#endif
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +64,7 @@ size_t strchr_count(const char *str, char ch)
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
FT_INTERNAL
|
||||
size_t wstrchr_count(const wchar_t *str, wchar_t ch)
|
||||
{
|
||||
@@ -65,6 +80,34 @@ size_t wstrchr_count(const wchar_t *str, wchar_t ch)
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(FT_HAVE_UTF8)
|
||||
/* todo: do something with code below!!! */
|
||||
FT_INTERNAL
|
||||
void *ut8next(const void *str)
|
||||
{
|
||||
utf8_int32_t out_codepoint;
|
||||
return utf8codepoint(str, &out_codepoint);
|
||||
}
|
||||
|
||||
FT_INTERNAL
|
||||
size_t utf8chr_count(const void *str, utf8_int32_t ch)
|
||||
{
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
|
||||
size_t count = 0;
|
||||
str = utf8chr(str, ch);
|
||||
while (str) {
|
||||
count++;
|
||||
str = ut8next(str);
|
||||
str = utf8chr(str, ch);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
@@ -112,6 +155,29 @@ const wchar_t *wstr_n_substring_beg(const wchar_t *str, wchar_t ch_separator, si
|
||||
}
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
|
||||
#if defined(FT_HAVE_UTF8)
|
||||
FT_INTERNAL
|
||||
const void *utf8_n_substring_beg(const void *str, utf8_int32_t ch_separator, size_t n)
|
||||
{
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
if (n == 0)
|
||||
return str;
|
||||
|
||||
str = utf8chr(str, ch_separator);
|
||||
--n;
|
||||
while (n > 0) {
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
--n;
|
||||
str = ut8next(str);
|
||||
str = utf8chr(str, ch_separator);
|
||||
}
|
||||
return str ? (ut8next(str)) : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
void str_n_substring(const char *str, char ch_separator, size_t n, const char **begin, const char **end)
|
||||
@@ -156,11 +222,34 @@ void wstr_n_substring(const wchar_t *str, wchar_t ch_separator, size_t n, const
|
||||
}
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
|
||||
#if defined(FT_HAVE_UTF8)
|
||||
FT_INTERNAL
|
||||
void utf8_n_substring(const void *str, utf8_int32_t ch_separator, size_t n, const void **begin, const void **end)
|
||||
{
|
||||
const char *beg = utf8_n_substring_beg(str, ch_separator, n);
|
||||
if (beg == NULL) {
|
||||
*begin = NULL;
|
||||
*end = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
const char *en = utf8chr(beg, ch_separator);
|
||||
if (en == NULL) {
|
||||
en = (const char *)str + strlen(str);
|
||||
}
|
||||
|
||||
*begin = beg;
|
||||
*end = en;
|
||||
return;
|
||||
}
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
string_buffer_t *create_string_buffer(size_t number_of_chars, enum str_buf_type type)
|
||||
{
|
||||
size_t sz = (number_of_chars) * (type == CharBuf ? sizeof(char) : sizeof(wchar_t));
|
||||
size_t sz = (number_of_chars) * (type == CHAR_BUF ? sizeof(char) : sizeof(wchar_t));
|
||||
string_buffer_t *result = (string_buffer_t *)F_MALLOC(sizeof(string_buffer_t));
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
@@ -172,10 +261,10 @@ 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) {
|
||||
if (sz && type == CHAR_BUF) {
|
||||
result->str.cstr[0] = '\0';
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
} else if (sz && type == WCharBuf) {
|
||||
} else if (sz && type == W_CHAR_BUF) {
|
||||
result->str.wstr[0] = L'\0';
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
}
|
||||
@@ -202,14 +291,14 @@ string_buffer_t *copy_string_buffer(const string_buffer_t *buffer)
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
switch (buffer->type) {
|
||||
case CharBuf:
|
||||
case CHAR_BUF:
|
||||
if (FT_IS_ERROR(fill_buffer_from_string(result, buffer->str.cstr))) {
|
||||
destroy_string_buffer(result);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
case WCharBuf:
|
||||
case W_CHAR_BUF:
|
||||
if (FT_IS_ERROR(fill_buffer_from_wstring(result, buffer->str.wstr))) {
|
||||
destroy_string_buffer(result);
|
||||
return NULL;
|
||||
@@ -250,7 +339,7 @@ fort_status_t fill_buffer_from_string(string_buffer_t *buffer, const char *str)
|
||||
|
||||
F_FREE(buffer->str.data);
|
||||
buffer->str.cstr = copy;
|
||||
buffer->type = CharBuf;
|
||||
buffer->type = CHAR_BUF;
|
||||
|
||||
return FT_SUCCESS;
|
||||
}
|
||||
@@ -269,31 +358,86 @@ fort_status_t fill_buffer_from_wstring(string_buffer_t *buffer, const wchar_t *s
|
||||
|
||||
F_FREE(buffer->str.data);
|
||||
buffer->str.wstr = copy;
|
||||
buffer->type = WCharBuf;
|
||||
buffer->type = W_CHAR_BUF;
|
||||
|
||||
return FT_SUCCESS;
|
||||
}
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
|
||||
#ifdef FT_HAVE_UTF8
|
||||
FT_INTERNAL
|
||||
fort_status_t fill_buffer_from_u8string(string_buffer_t *buffer, const void *str)
|
||||
{
|
||||
assert(buffer);
|
||||
assert(str);
|
||||
|
||||
void *copy = F_UTF8DUP(str);
|
||||
if (copy == NULL)
|
||||
return FT_MEMORY_ERROR;
|
||||
|
||||
F_FREE(buffer->str.u8str);
|
||||
buffer->str.u8str = copy;
|
||||
buffer->type = UTF8_BUF;
|
||||
|
||||
return FT_SUCCESS;
|
||||
}
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
|
||||
FT_INTERNAL
|
||||
size_t buffer_text_height(const string_buffer_t *buffer)
|
||||
size_t buffer_text_visible_height(const string_buffer_t *buffer)
|
||||
{
|
||||
if (buffer == NULL || buffer->str.data == NULL || buf_str_len(buffer) == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (buffer->type == CharBuf)
|
||||
if (buffer->type == CHAR_BUF)
|
||||
return 1 + strchr_count(buffer->str.cstr, '\n');
|
||||
else
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
else if (buffer->type == W_CHAR_BUF)
|
||||
return 1 + wstrchr_count(buffer->str.wstr, L'\n');
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
#ifdef FT_HAVE_UTF8
|
||||
else if (buffer->type == UTF8_BUF)
|
||||
return 1 + utf8chr_count(buffer->str.u8str, '\n');
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FT_INTERNAL
|
||||
size_t string_buffer_cod_width_capacity(const string_buffer_t *buffer)
|
||||
{
|
||||
return string_buffer_width_capacity(buffer);
|
||||
}
|
||||
|
||||
FT_INTERNAL
|
||||
size_t buffer_text_width(const string_buffer_t *buffer)
|
||||
size_t string_buffer_raw_capacity(const string_buffer_t *buffer)
|
||||
{
|
||||
return buffer->data_sz;
|
||||
}
|
||||
|
||||
#ifdef FT_HAVE_UTF8
|
||||
FT_INTERNAL
|
||||
size_t ut8_width(const void *beg, const void *end)
|
||||
{
|
||||
size_t sz = (size_t)((const char *)end - (const char *)beg);
|
||||
char *tmp = F_MALLOC(sizeof(char) * (sz + 1));
|
||||
// @todo: add check to tmp
|
||||
assert(tmp);
|
||||
|
||||
memcpy(tmp, beg, sz);
|
||||
tmp[sz] = '\0';
|
||||
size_t result = utf8len(tmp);
|
||||
F_FREE(tmp);
|
||||
return result;
|
||||
}
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
|
||||
FT_INTERNAL
|
||||
size_t buffer_text_visible_width(const string_buffer_t *buffer)
|
||||
{
|
||||
size_t max_length = 0;
|
||||
if (buffer->type == CharBuf) {
|
||||
if (buffer->type == CHAR_BUF) {
|
||||
size_t n = 0;
|
||||
while (1) {
|
||||
const char *beg = NULL;
|
||||
@@ -306,7 +450,7 @@ size_t buffer_text_width(const string_buffer_t *buffer)
|
||||
++n;
|
||||
}
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
} else {
|
||||
} else if (buffer->type == W_CHAR_BUF) {
|
||||
size_t n = 0;
|
||||
while (1) {
|
||||
const wchar_t *beg = NULL;
|
||||
@@ -323,149 +467,110 @@ size_t buffer_text_width(const string_buffer_t *buffer)
|
||||
++n;
|
||||
}
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
#ifdef FT_HAVE_UTF8
|
||||
} else if (buffer->type == UTF8_BUF) {
|
||||
size_t n = 0;
|
||||
while (1) {
|
||||
const void *beg = NULL;
|
||||
const void *end = NULL;
|
||||
utf8_n_substring(buffer->str.u8str, '\n', n, &beg, &end);
|
||||
if (beg == NULL || end == NULL)
|
||||
return max_length;
|
||||
|
||||
max_length = MAX(max_length, (size_t)ut8_width(beg, end));
|
||||
++n;
|
||||
}
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
}
|
||||
|
||||
return max_length; /* shouldn't be here */
|
||||
}
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
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)
|
||||
static void
|
||||
buffer_substring(const string_buffer_t *buffer, size_t buffer_row, void **begin, void **end, ptrdiff_t *str_it_width)
|
||||
{
|
||||
#define CHAR_TYPE char
|
||||
#define NULL_CHAR '\0'
|
||||
#define NEWLINE_CHAR '\n'
|
||||
#define SPACE_CHAR " "
|
||||
#define SNPRINTF_FMT_STR "%*s"
|
||||
#define SNPRINTF snprintf
|
||||
#define BUFFER_STR str.cstr
|
||||
#define SNPRINT_N_STRINGS snprint_n_strings
|
||||
#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;
|
||||
}
|
||||
|
||||
size_t content_width = buffer_text_width(buffer);
|
||||
if ((buf_len - 1) < content_width)
|
||||
return -1;
|
||||
|
||||
size_t left = 0;
|
||||
size_t right = 0;
|
||||
|
||||
switch (get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_TEXT_ALIGN)) {
|
||||
case FT_ALIGNED_LEFT:
|
||||
left = 0;
|
||||
right = (buf_len - 1) - content_width;
|
||||
switch (buffer->type) {
|
||||
case CHAR_BUF:
|
||||
str_n_substring(buffer->str.cstr, '\n', buffer_row, (const char **)begin, (const char **)end);
|
||||
if ((*(const char **)begin) && (*(const char **)end))
|
||||
*str_it_width = str_iter_width(*(const char **)begin, *(const char **)end);
|
||||
break;
|
||||
case FT_ALIGNED_CENTER:
|
||||
left = ((buf_len - 1) - content_width) / 2;
|
||||
right = ((buf_len - 1) - content_width) - left;
|
||||
break;
|
||||
case FT_ALIGNED_RIGHT:
|
||||
left = (buf_len - 1) - content_width;
|
||||
right = 0;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
int set_old_value = 0;
|
||||
size_t written = 0;
|
||||
int tmp = 0;
|
||||
ptrdiff_t str_it_width = 0;
|
||||
const CHAR_TYPE *beg = NULL;
|
||||
const CHAR_TYPE *end = NULL;
|
||||
CHAR_TYPE old_value = (CHAR_TYPE)0;
|
||||
|
||||
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)
|
||||
return -1;
|
||||
old_value = *end;
|
||||
*(CHAR_TYPE *)end = NULL_CHAR;
|
||||
set_old_value = 1;
|
||||
|
||||
str_it_width = STR_ITER_WIDTH(beg, end);
|
||||
if (str_it_width < 0 || content_width < (size_t)str_it_width)
|
||||
goto clear;
|
||||
|
||||
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;
|
||||
set_old_value = 0;
|
||||
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 (int)written;
|
||||
|
||||
clear:
|
||||
if (set_old_value)
|
||||
*(CHAR_TYPE *)end = old_value;
|
||||
return -1;
|
||||
|
||||
#undef CHAR_TYPE
|
||||
#undef NULL_CHAR
|
||||
#undef NEWLINE_CHAR
|
||||
#undef SPACE_CHAR
|
||||
#undef SNPRINTF_FMT_STR
|
||||
#undef SNPRINTF
|
||||
#undef BUFFER_STR
|
||||
#undef SNPRINT_N_STRINGS
|
||||
#undef STR_N_SUBSTRING
|
||||
#undef STR_ITER_WIDTH
|
||||
}
|
||||
|
||||
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
FT_INTERNAL
|
||||
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'
|
||||
#define NEWLINE_CHAR L'\n'
|
||||
#define SPACE_CHAR " "
|
||||
#define SNPRINTF_FMT_STR L"%*ls"
|
||||
#define SNPRINTF swprintf
|
||||
#define BUFFER_STR str.wstr
|
||||
#define SNPRINT_N_STRINGS wsnprint_n_string
|
||||
#define STR_N_SUBSTRING wstr_n_substring
|
||||
#define STR_ITER_WIDTH wcs_iter_width
|
||||
case W_CHAR_BUF:
|
||||
wstr_n_substring(buffer->str.wstr, L'\n', buffer_row, (const wchar_t **)begin, (const wchar_t **)end);
|
||||
if ((*(const wchar_t **)begin) && (*(const wchar_t **)end))
|
||||
*str_it_width = wcs_iter_width(*(const wchar_t **)begin, *(const wchar_t **)end);
|
||||
break;
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
#ifdef FT_HAVE_UTF8
|
||||
case UTF8_BUF:
|
||||
utf8_n_substring(buffer->str.wstr, '\n', buffer_row, begin, end);
|
||||
if ((*(const char **)begin) && (*(const char **)end))
|
||||
*str_it_width = ut8_width(*begin, *end);
|
||||
break;
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
size_t buf_len = total_buf_len - strlen(content_style_tag) - strlen(reset_content_style_tag);
|
||||
|
||||
static int
|
||||
buffer_print_range(conv_context_t *cntx, const void *beg, const void *end)
|
||||
{
|
||||
size_t len;
|
||||
switch (cntx->b_type) {
|
||||
case CHAR_BUF:
|
||||
len = (size_t)((const char *)end - (const char *)beg);
|
||||
return ft_nprint(cntx, (const char *)beg, len);
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
case W_CHAR_BUF:
|
||||
len = (size_t)((const wchar_t *)end - (const wchar_t *)beg);
|
||||
return ft_nwprint(cntx, (const wchar_t *)beg, len);
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
#ifdef FT_HAVE_UTF8
|
||||
case UTF8_BUF:
|
||||
return ft_nu8print(cntx, beg, end);
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
default:
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
int buffer_printf(string_buffer_t *buffer, size_t buffer_row, conv_context_t *cntx, size_t vis_width,
|
||||
const char *content_style_tag, const char *reset_content_style_tag)
|
||||
{
|
||||
const context_t *context = cntx->cntx;
|
||||
fort_table_properties_t *props = context->table_properties;
|
||||
size_t row = context->row;
|
||||
size_t column = context->column;
|
||||
|
||||
if (buffer == NULL || buffer->str.data == NULL
|
||||
|| buffer_row >= buffer_text_height(buffer) || buf_len == 0) {
|
||||
|| buffer_row >= buffer_text_visible_height(buffer)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t content_width = buffer_text_width(buffer);
|
||||
if ((buf_len - 1) < content_width)
|
||||
size_t content_width = buffer_text_visible_width(buffer);
|
||||
if (vis_width < content_width)
|
||||
return -1;
|
||||
|
||||
size_t left = 0;
|
||||
size_t right = 0;
|
||||
|
||||
switch (get_cell_property_value_hierarcial(context->table_properties, context->row, context->column, FT_CPROP_TEXT_ALIGN)) {
|
||||
switch (get_cell_property_value_hierarcial(props, row, column, FT_CPROP_TEXT_ALIGN)) {
|
||||
case FT_ALIGNED_LEFT:
|
||||
left = 0;
|
||||
right = (buf_len - 1) - content_width;
|
||||
right = (vis_width) - content_width;
|
||||
break;
|
||||
case FT_ALIGNED_CENTER:
|
||||
left = ((buf_len - 1) - content_width) / 2;
|
||||
right = ((buf_len - 1) - content_width) - left;
|
||||
left = ((vis_width) - content_width) / 2;
|
||||
right = ((vis_width) - content_width) - left;
|
||||
break;
|
||||
case FT_ALIGNED_RIGHT:
|
||||
left = (buf_len - 1) - content_width;
|
||||
left = (vis_width) - content_width;
|
||||
right = 0;
|
||||
break;
|
||||
default:
|
||||
@@ -473,64 +578,41 @@ int buffer_wprintf(string_buffer_t *buffer, size_t buffer_row, wchar_t *buf, siz
|
||||
break;
|
||||
}
|
||||
|
||||
int set_old_value = 0;
|
||||
size_t written = 0;
|
||||
int tmp = 0;
|
||||
ptrdiff_t str_it_width = 0;
|
||||
const CHAR_TYPE *beg = NULL;
|
||||
const CHAR_TYPE *end = NULL;
|
||||
CHAR_TYPE old_value = (CHAR_TYPE)0;
|
||||
|
||||
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);
|
||||
const void *beg = NULL;
|
||||
const void *end = NULL;
|
||||
buffer_substring(buffer, buffer_row, (void **)&beg, (void **)&end, &str_it_width);
|
||||
if (beg == NULL || end == NULL)
|
||||
return -1;
|
||||
old_value = *end;
|
||||
*(CHAR_TYPE *)end = NULL_CHAR;
|
||||
set_old_value = 1;
|
||||
|
||||
str_it_width = STR_ITER_WIDTH(beg, end);
|
||||
if (str_it_width < 0 || content_width < (size_t)str_it_width)
|
||||
goto clear;
|
||||
return -1;
|
||||
|
||||
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));
|
||||
size_t padding = content_width - (size_t)str_it_width;
|
||||
|
||||
*(CHAR_TYPE *)end = old_value;
|
||||
set_old_value = 0;
|
||||
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));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, left, FT_SPACE));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, content_style_tag));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(buffer_print_range(cntx, beg, end));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, 1, reset_content_style_tag));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, padding, FT_SPACE));
|
||||
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, right, FT_SPACE));
|
||||
return (int)written;
|
||||
|
||||
clear:
|
||||
if (set_old_value)
|
||||
*(CHAR_TYPE *)end = old_value;
|
||||
return -1;
|
||||
|
||||
#undef CHAR_TYPE
|
||||
#undef NULL_CHAR
|
||||
#undef NEWLINE_CHAR
|
||||
#undef SPACE_CHAR
|
||||
#undef SNPRINTF_FMT_STR
|
||||
#undef SNPRINTF
|
||||
#undef BUFFER_STR
|
||||
#undef SNPRINT_N_STRINGS
|
||||
#undef STR_N_SUBSTRING
|
||||
#undef STR_ITER_WIDTH
|
||||
}
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
|
||||
|
||||
FT_INTERNAL
|
||||
size_t string_buffer_capacity(const string_buffer_t *buffer)
|
||||
size_t string_buffer_width_capacity(const string_buffer_t *buffer)
|
||||
{
|
||||
assert(buffer);
|
||||
if (buffer->type == CharBuf)
|
||||
if (buffer->type == CHAR_BUF)
|
||||
return buffer->data_sz;
|
||||
else
|
||||
else if (buffer->type == W_CHAR_BUF)
|
||||
return buffer->data_sz / sizeof(wchar_t);
|
||||
else if (buffer->type == UTF8_BUF)
|
||||
return buffer->data_sz / 4;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -7,17 +7,16 @@
|
||||
/*****************************************************************************
|
||||
* STRING BUFFER
|
||||
* ***************************************************************************/
|
||||
enum str_buf_type {
|
||||
CharBuf,
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
WCharBuf
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
};
|
||||
|
||||
struct string_buffer {
|
||||
union {
|
||||
char *cstr;
|
||||
#ifdef FT_HAVE_WCHAR
|
||||
wchar_t *wstr;
|
||||
#endif
|
||||
#ifdef FT_HAVE_UTF8
|
||||
void *u8str;
|
||||
#endif
|
||||
void *data;
|
||||
} str;
|
||||
size_t data_sz;
|
||||
@@ -44,26 +43,31 @@ FT_INTERNAL
|
||||
fort_status_t fill_buffer_from_wstring(string_buffer_t *buffer, const wchar_t *str);
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
|
||||
#ifdef FT_HAVE_UTF8
|
||||
FT_INTERNAL
|
||||
size_t buffer_text_height(const string_buffer_t *buffer);
|
||||
fort_status_t fill_buffer_from_u8string(string_buffer_t *buffer, const void *str);
|
||||
#endif /* FT_HAVE_UTF8 */
|
||||
|
||||
FT_INTERNAL
|
||||
size_t string_buffer_capacity(const string_buffer_t *buffer);
|
||||
size_t buffer_text_visible_width(const string_buffer_t *buffer);
|
||||
|
||||
FT_INTERNAL
|
||||
size_t buffer_text_visible_height(const string_buffer_t *buffer);
|
||||
|
||||
FT_INTERNAL
|
||||
size_t string_buffer_cod_width_capacity(const string_buffer_t *buffer);
|
||||
|
||||
FT_INTERNAL
|
||||
size_t string_buffer_raw_capacity(const string_buffer_t *buffer);
|
||||
|
||||
FT_INTERNAL
|
||||
size_t string_buffer_width_capacity(const string_buffer_t *buffer);
|
||||
|
||||
FT_INTERNAL
|
||||
void *buffer_get_data(string_buffer_t *buffer);
|
||||
|
||||
FT_INTERNAL
|
||||
size_t buffer_text_width(const string_buffer_t *buffer);
|
||||
|
||||
FT_INTERNAL
|
||||
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 total_buf_len,
|
||||
const context_t *context, const char *content_style_tag, const char *reset_content_style_tag);
|
||||
#endif /* FT_HAVE_WCHAR */
|
||||
int buffer_printf(string_buffer_t *buffer, size_t buffer_row, conv_context_t *cntx, size_t cod_width,
|
||||
const char *content_style_tag, const char *reset_content_style_tag);
|
||||
|
||||
#endif /* STRING_BUFFER_H */
|
||||
|
@@ -294,3 +294,8 @@ fort_status_t table_geometry(const ft_table_t *table, size_t *height, size_t *wi
|
||||
|
||||
}
|
||||
|
||||
FT_INTERNAL
|
||||
fort_status_t table_internal_codepoints_geometry(const ft_table_t *table, size_t *height, size_t *width)
|
||||
{
|
||||
return table_geometry(table, height, width);
|
||||
}
|
||||
|
@@ -46,4 +46,11 @@ fort_status_t table_rows_and_cols_geometry(const ft_table_t *table,
|
||||
FT_INTERNAL
|
||||
fort_status_t table_geometry(const ft_table_t *table, size_t *height, size_t *width);
|
||||
|
||||
/*
|
||||
* Returns geometry in codepoints(characters) (include codepoints of invisible
|
||||
* elements: e.g. styles tags).
|
||||
*/
|
||||
FT_INTERNAL
|
||||
fort_status_t table_internal_codepoints_geometry(const ft_table_t *table, size_t *height, size_t *width);
|
||||
|
||||
#endif /* TABLE_H */
|
||||
|
Reference in New Issue
Block a user