2018-01-17 19:22:57 +01:00
|
|
|
#include "cell.h"
|
2018-11-03 21:50:30 +01:00
|
|
|
#include "properties.h"
|
2018-01-17 19:22:57 +01:00
|
|
|
#include "string_buffer.h"
|
2018-05-06 12:12:28 +02:00
|
|
|
#include <assert.h>
|
2018-01-17 19:22:57 +01:00
|
|
|
|
2019-08-27 14:04:54 +02:00
|
|
|
struct f_cell {
|
|
|
|
f_string_buffer_t *str_buffer;
|
|
|
|
enum f_cell_type cell_type;
|
2018-01-17 19:22:57 +01:00
|
|
|
};
|
|
|
|
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
f_cell_t *create_cell(void)
|
2018-01-17 19:22:57 +01:00
|
|
|
{
|
2019-08-27 14:04:54 +02:00
|
|
|
f_cell_t *cell = (f_cell_t *)F_CALLOC(sizeof(f_cell_t), 1);
|
2018-01-17 19:22:57 +01:00
|
|
|
if (cell == NULL)
|
|
|
|
return NULL;
|
2019-08-14 21:01:57 +02:00
|
|
|
cell->str_buffer = create_string_buffer(DEFAULT_STR_BUF_SIZE, CHAR_BUF);
|
2018-01-17 19:22:57 +01:00
|
|
|
if (cell->str_buffer == NULL) {
|
|
|
|
F_FREE(cell);
|
|
|
|
return NULL;
|
|
|
|
}
|
2019-08-27 14:04:54 +02:00
|
|
|
cell->cell_type = COMMON_CELL;
|
2018-01-17 19:22:57 +01:00
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
void destroy_cell(f_cell_t *cell)
|
2018-01-17 19:22:57 +01:00
|
|
|
{
|
|
|
|
if (cell == NULL)
|
|
|
|
return;
|
|
|
|
destroy_string_buffer(cell->str_buffer);
|
|
|
|
F_FREE(cell);
|
|
|
|
}
|
|
|
|
|
2018-11-02 22:16:20 +01:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
f_cell_t *copy_cell(f_cell_t *cell)
|
2018-11-02 22:16:20 +01:00
|
|
|
{
|
|
|
|
assert(cell);
|
|
|
|
|
2019-08-27 14:04:54 +02:00
|
|
|
f_cell_t *result = create_cell();
|
2019-01-02 07:52:31 +01:00
|
|
|
if (result == NULL)
|
|
|
|
return NULL;
|
2018-11-02 22:16:20 +01:00
|
|
|
destroy_string_buffer(result->str_buffer);
|
|
|
|
result->str_buffer = copy_string_buffer(cell->str_buffer);
|
|
|
|
if (result->str_buffer == NULL) {
|
|
|
|
destroy_cell(result);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
result->cell_type = cell->cell_type;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
void set_cell_type(f_cell_t *cell, enum f_cell_type type)
|
2018-05-02 16:55:29 +02:00
|
|
|
{
|
|
|
|
assert(cell);
|
|
|
|
cell->cell_type = type;
|
|
|
|
}
|
|
|
|
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
enum f_cell_type get_cell_type(const f_cell_t *cell)
|
2018-05-02 16:55:29 +02:00
|
|
|
{
|
|
|
|
assert(cell);
|
|
|
|
return cell->cell_type;
|
|
|
|
}
|
|
|
|
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
size_t hint_width_cell(const f_cell_t *cell, const f_context_t *context, enum f_geometry_type geom)
|
2018-01-17 19:22:57 +01:00
|
|
|
{
|
2018-02-26 19:47:19 +01:00
|
|
|
/* todo:
|
|
|
|
* At the moment min width includes paddings. Maybe it is better that min width weren't include
|
|
|
|
* paddings but be min width of the cell content without padding
|
|
|
|
*/
|
|
|
|
|
2018-01-17 19:22:57 +01:00
|
|
|
assert(cell);
|
|
|
|
assert(context);
|
2019-08-27 09:21:06 +02:00
|
|
|
|
2019-08-27 14:04:54 +02:00
|
|
|
f_table_properties_t *properties = context->table_properties;
|
2019-08-27 09:21:06 +02:00
|
|
|
size_t row = context->row;
|
|
|
|
size_t column = context->column;
|
|
|
|
|
2019-08-27 14:04:54 +02:00
|
|
|
size_t padding_left = get_cell_property_hierarchically(properties, row, column, FT_CPROP_LEFT_PADDING);
|
|
|
|
size_t padding_right = get_cell_property_hierarchically(properties, row, column, FT_CPROP_RIGHT_PADDING);
|
2019-08-27 09:21:06 +02:00
|
|
|
size_t result = padding_left + padding_right;
|
2018-03-17 19:53:38 +01:00
|
|
|
if (cell->str_buffer && cell->str_buffer->str.data) {
|
2019-08-14 21:01:57 +02:00
|
|
|
result += buffer_text_visible_width(cell->str_buffer);
|
2018-01-17 19:22:57 +01:00
|
|
|
}
|
2019-08-27 14:04:54 +02:00
|
|
|
result = MAX(result, (size_t)get_cell_property_hierarchically(properties, row, column, FT_CPROP_MIN_WIDTH));
|
2018-11-10 07:58:21 +01:00
|
|
|
|
|
|
|
if (geom == INTERN_REPR_GEOMETRY) {
|
|
|
|
char cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE];
|
2019-08-27 09:21:06 +02:00
|
|
|
get_style_tag_for_cell(properties, row, column, cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE);
|
2018-11-10 07:58:21 +01:00
|
|
|
result += strlen(cell_style_tag);
|
|
|
|
|
|
|
|
char reset_cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE];
|
2019-08-27 09:21:06 +02:00
|
|
|
get_reset_style_tag_for_cell(properties, row, column, reset_cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE);
|
2018-11-10 07:58:21 +01:00
|
|
|
result += strlen(reset_cell_style_tag);
|
|
|
|
|
|
|
|
char content_style_tag[TEXT_STYLE_TAG_MAX_SIZE];
|
2019-08-27 09:21:06 +02:00
|
|
|
get_style_tag_for_content(properties, row, column, content_style_tag, TEXT_STYLE_TAG_MAX_SIZE);
|
2018-11-10 07:58:21 +01:00
|
|
|
result += strlen(content_style_tag);
|
|
|
|
|
|
|
|
char reset_content_style_tag[TEXT_STYLE_TAG_MAX_SIZE];
|
2019-08-27 09:21:06 +02:00
|
|
|
get_reset_style_tag_for_content(properties, row, column, reset_content_style_tag, TEXT_STYLE_TAG_MAX_SIZE);
|
2018-11-10 07:58:21 +01:00
|
|
|
result += strlen(reset_content_style_tag);
|
|
|
|
}
|
|
|
|
|
2018-01-17 19:22:57 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
size_t hint_height_cell(const f_cell_t *cell, const f_context_t *context)
|
2018-01-17 19:22:57 +01:00
|
|
|
{
|
|
|
|
assert(cell);
|
|
|
|
assert(context);
|
2019-08-27 14:04:54 +02:00
|
|
|
f_table_properties_t *properties = context->table_properties;
|
2019-08-27 09:21:06 +02:00
|
|
|
size_t row = context->row;
|
|
|
|
size_t column = context->column;
|
|
|
|
|
2019-08-27 14:04:54 +02:00
|
|
|
size_t padding_top = get_cell_property_hierarchically(properties, row, column, FT_CPROP_TOP_PADDING);
|
|
|
|
size_t padding_bottom = get_cell_property_hierarchically(properties, row, column, FT_CPROP_BOTTOM_PADDING);
|
|
|
|
size_t empty_string_height = get_cell_property_hierarchically(properties, row, column, FT_CPROP_EMPTY_STR_HEIGHT);
|
2019-08-27 09:21:06 +02:00
|
|
|
|
|
|
|
size_t result = padding_top + padding_bottom;
|
2018-03-17 19:53:38 +01:00
|
|
|
if (cell->str_buffer && cell->str_buffer->str.data) {
|
2019-08-14 21:01:57 +02:00
|
|
|
size_t text_height = buffer_text_visible_height(cell->str_buffer);
|
2019-08-27 09:21:06 +02:00
|
|
|
result += text_height == 0 ? empty_string_height : text_height;
|
2018-01-17 19:22:57 +01:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
int cell_printf(f_cell_t *cell, size_t row, f_conv_context_t *cntx, size_t vis_width)
|
2018-01-17 19:22:57 +01:00
|
|
|
{
|
2019-08-27 14:04:54 +02:00
|
|
|
const f_context_t *context = cntx->cntx;
|
2019-08-14 21:01:57 +02:00
|
|
|
size_t buf_len = vis_width;
|
2018-05-02 20:16:41 +02:00
|
|
|
|
2019-08-14 21:01:57 +02:00
|
|
|
if (cell == NULL || (vis_width < hint_width_cell(cell, context, VISIBLE_GEOMETRY))) {
|
2018-01-17 19:22:57 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-08-27 14:04:54 +02:00
|
|
|
f_table_properties_t *properties = context->table_properties;
|
|
|
|
unsigned int padding_top = get_cell_property_hierarchically(properties, context->row, context->column, FT_CPROP_TOP_PADDING);
|
|
|
|
unsigned int padding_left = get_cell_property_hierarchically(properties, context->row, context->column, FT_CPROP_LEFT_PADDING);
|
|
|
|
unsigned int padding_right = get_cell_property_hierarchically(properties, context->row, context->column, FT_CPROP_RIGHT_PADDING);
|
2018-02-27 19:41:58 +01:00
|
|
|
|
2019-01-01 17:55:00 +01:00
|
|
|
size_t written = 0;
|
|
|
|
size_t invisible_written = 0;
|
2018-11-10 07:58:21 +01:00
|
|
|
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];
|
2019-08-27 09:21:06 +02:00
|
|
|
get_style_tag_for_cell(properties, context->row, context->column, cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE);
|
2018-11-10 07:58:21 +01:00
|
|
|
buf_len += strlen(cell_style_tag);
|
|
|
|
|
|
|
|
char reset_cell_style_tag[TEXT_STYLE_TAG_MAX_SIZE];
|
2019-08-27 09:21:06 +02:00
|
|
|
get_reset_style_tag_for_cell(properties, context->row, context->column, reset_cell_style_tag, TEXT_STYLE_TAG_MAX_SIZE);
|
2018-11-10 07:58:21 +01:00
|
|
|
buf_len += strlen(reset_cell_style_tag);
|
|
|
|
|
|
|
|
char content_style_tag[TEXT_STYLE_TAG_MAX_SIZE];
|
2019-08-27 09:21:06 +02:00
|
|
|
get_style_tag_for_content(properties, context->row, context->column, content_style_tag, TEXT_STYLE_TAG_MAX_SIZE);
|
2018-11-10 07:58:21 +01:00
|
|
|
buf_len += strlen(content_style_tag);
|
|
|
|
|
|
|
|
char reset_content_style_tag[TEXT_STYLE_TAG_MAX_SIZE];
|
2019-08-27 09:21:06 +02:00
|
|
|
get_reset_style_tag_for_content(properties, context->row, context->column, reset_content_style_tag, TEXT_STYLE_TAG_MAX_SIZE);
|
2018-11-10 07:58:21 +01:00
|
|
|
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
|
|
|
|
*/
|
|
|
|
|
2019-08-27 09:21:06 +02:00
|
|
|
size_t L2 = padding_left;
|
2018-11-10 07:58:21 +01:00
|
|
|
|
2019-08-27 09:21:06 +02:00
|
|
|
size_t R2 = padding_right;
|
2018-11-10 07:58:21 +01:00
|
|
|
size_t R3 = strlen(reset_cell_style_tag);
|
|
|
|
|
|
|
|
#define TOTAL_WRITTEN (written + invisible_written)
|
2019-08-27 09:21:06 +02:00
|
|
|
#define RIGHT (padding_right + extra_right)
|
2018-11-10 07:58:21 +01:00
|
|
|
|
2019-08-14 21:01:57 +02:00
|
|
|
#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))
|
2018-11-10 07:58:21 +01:00
|
|
|
|
2018-01-21 09:19:18 +01:00
|
|
|
if (row >= hint_height_cell(cell, context)
|
2019-08-27 09:21:06 +02:00
|
|
|
|| row < padding_top
|
|
|
|
|| row >= (padding_top + buffer_text_visible_height(cell->str_buffer))) {
|
2018-11-10 07:58:21 +01:00
|
|
|
WRITE_CELL_STYLE_TAG;
|
|
|
|
WRITE_CONTENT_STYLE_TAG;
|
|
|
|
WRITE_RESET_CONTENT_STYLE_TAG;
|
2019-08-14 21:01:57 +02:00
|
|
|
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, buf_len - TOTAL_WRITTEN - R3, FT_SPACE));
|
2018-11-10 07:58:21 +01:00
|
|
|
WRITE_RESET_CELL_STYLE_TAG;
|
2018-03-29 21:18:49 +02:00
|
|
|
|
2019-01-01 17:55:00 +01:00
|
|
|
return (int)TOTAL_WRITTEN;
|
2018-03-05 19:08:14 +01:00
|
|
|
}
|
2018-03-29 21:18:49 +02:00
|
|
|
|
2018-11-10 07:58:21 +01:00
|
|
|
WRITE_CELL_STYLE_TAG;
|
2019-08-14 21:01:57 +02:00
|
|
|
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, L2, FT_SPACE));
|
2018-11-10 07:58:21 +01:00
|
|
|
if (cell->str_buffer) {
|
2019-08-27 09:21:06 +02:00
|
|
|
CHCK_RSLT_ADD_TO_WRITTEN(buffer_printf(cell->str_buffer, row - padding_top, cntx, vis_width - L2 - R2, content_style_tag, reset_content_style_tag));
|
2018-11-10 07:58:21 +01:00
|
|
|
} else {
|
|
|
|
WRITE_CONTENT_STYLE_TAG;
|
|
|
|
WRITE_RESET_CONTENT_STYLE_TAG;
|
2019-08-14 21:01:57 +02:00
|
|
|
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, vis_width - L2 - R2, FT_SPACE));
|
2018-11-10 07:58:21 +01:00
|
|
|
}
|
2019-08-14 21:01:57 +02:00
|
|
|
CHCK_RSLT_ADD_TO_WRITTEN(print_n_strings(cntx, R2, FT_SPACE));
|
2018-11-10 07:58:21 +01:00
|
|
|
WRITE_RESET_CELL_STYLE_TAG;
|
2018-03-29 21:18:49 +02:00
|
|
|
|
2019-01-01 17:55:00 +01:00
|
|
|
return (int)TOTAL_WRITTEN;
|
2018-03-29 21:18:49 +02:00
|
|
|
|
|
|
|
clear:
|
|
|
|
return -1;
|
2018-11-10 07:58:21 +01:00
|
|
|
#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
|
2018-03-05 19:08:14 +01:00
|
|
|
}
|
2018-01-17 19:22:57 +01:00
|
|
|
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
f_status fill_cell_from_string(f_cell_t *cell, const char *str)
|
2018-01-17 19:22:57 +01:00
|
|
|
{
|
|
|
|
assert(str);
|
|
|
|
assert(cell);
|
|
|
|
|
|
|
|
return fill_buffer_from_string(cell->str_buffer, str);
|
|
|
|
}
|
|
|
|
|
2018-04-24 20:36:07 +02:00
|
|
|
#ifdef FT_HAVE_WCHAR
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
f_status fill_cell_from_wstring(f_cell_t *cell, const wchar_t *str)
|
2018-04-24 20:36:07 +02:00
|
|
|
{
|
|
|
|
assert(str);
|
|
|
|
assert(cell);
|
|
|
|
|
|
|
|
return fill_buffer_from_wstring(cell->str_buffer, str);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-08-26 11:24:09 +02:00
|
|
|
#ifdef FT_HAVE_UTF8
|
|
|
|
static
|
2019-08-27 14:04:54 +02:00
|
|
|
f_status fill_cell_from_u8string(f_cell_t *cell, const void *str)
|
2019-08-26 11:24:09 +02:00
|
|
|
{
|
|
|
|
assert(str);
|
|
|
|
assert(cell);
|
|
|
|
return fill_buffer_from_u8string(cell->str_buffer, str);
|
|
|
|
}
|
|
|
|
#endif /* FT_HAVE_UTF8 */
|
|
|
|
|
2018-08-28 21:25:43 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
f_string_buffer_t *cell_get_string_buffer(f_cell_t *cell)
|
2018-01-17 19:22:57 +01:00
|
|
|
{
|
|
|
|
assert(cell);
|
|
|
|
assert(cell->str_buffer);
|
|
|
|
return cell->str_buffer;
|
|
|
|
}
|
2018-03-17 19:53:38 +01:00
|
|
|
|
2019-08-26 11:24:09 +02:00
|
|
|
FT_INTERNAL
|
2019-08-27 14:04:54 +02:00
|
|
|
f_status fill_cell_from_buffer(f_cell_t *cell, const f_string_buffer_t *buffer)
|
2019-08-26 11:24:09 +02:00
|
|
|
{
|
|
|
|
assert(cell);
|
|
|
|
assert(buffer);
|
|
|
|
switch (buffer->type) {
|
|
|
|
case CHAR_BUF:
|
|
|
|
return fill_cell_from_string(cell, buffer->str.cstr);
|
|
|
|
#ifdef FT_HAVE_WCHAR
|
|
|
|
case W_CHAR_BUF:
|
|
|
|
return fill_cell_from_wstring(cell, buffer->str.wstr);
|
|
|
|
#endif /* FT_HAVE_WCHAR */
|
|
|
|
#ifdef FT_HAVE_UTF8
|
|
|
|
case UTF8_BUF:
|
|
|
|
return fill_cell_from_u8string(cell, buffer->str.u8str);
|
|
|
|
#endif /* FT_HAVE_UTF8 */
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
return FT_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|