diff --git a/legacy/elm_code/src/lib/elm_code_file.c b/legacy/elm_code/src/lib/elm_code_file.c index 41a7e8f1c7..8848b95a70 100644 --- a/legacy/elm_code/src/lib/elm_code_file.c +++ b/legacy/elm_code/src/lib/elm_code_file.c @@ -52,7 +52,6 @@ static void _elm_code_file_line_insert_data(Elm_Code_File *file, const char *con line->modified[length] = 0; line->length = length; } - line->unicode_length = elm_code_text_unicode_strlen(content, length); if (row == 1) file->lines = eina_list_prepend(file->lines, line); diff --git a/legacy/elm_code/src/lib/elm_code_line.c b/legacy/elm_code/src/lib/elm_code_line.c index d7d9ee6b2e..dfddb67231 100644 --- a/legacy/elm_code/src/lib/elm_code_line.c +++ b/legacy/elm_code/src/lib/elm_code_line.c @@ -20,12 +20,6 @@ elm_code_line_free(Elm_Code_Line *line) free(line); } -EAPI unsigned int -elm_code_line_utf8_length_get(Elm_Code_Line *line) -{ - return line->unicode_length; -} - EAPI void elm_code_line_status_set(Elm_Code_Line *line, Elm_Code_Status_Type status) { if (!line) diff --git a/legacy/elm_code/src/lib/elm_code_line.h b/legacy/elm_code/src/lib/elm_code_line.h index 3cb1baf7e0..d2f7968e89 100644 --- a/legacy/elm_code/src/lib/elm_code_line.h +++ b/legacy/elm_code/src/lib/elm_code_line.h @@ -24,7 +24,7 @@ typedef struct _Elm_Code_Line Elm_Code_File *file; const char *content; - unsigned int length, unicode_length; + unsigned int length; unsigned int number; char *modified; @@ -37,8 +37,6 @@ typedef struct _Elm_Code_Line EAPI void elm_code_line_free(Elm_Code_Line *line); -EAPI unsigned int elm_code_line_utf8_length_get(Elm_Code_Line *line); - /** * @brief Line markup functions. * @defgroup Line highlighting and status manipulation diff --git a/legacy/elm_code/src/lib/elm_code_parse.c b/legacy/elm_code/src/lib/elm_code_parse.c index 912cbaac2c..9146e46f6d 100644 --- a/legacy/elm_code/src/lib/elm_code_parse.c +++ b/legacy/elm_code/src/lib/elm_code_parse.c @@ -106,7 +106,6 @@ _elm_code_parser_diff_trim_leading(Elm_Code_Line *line, unsigned int count) } line->length -= count; - line->unicode_length -= count; } static void diff --git a/legacy/elm_code/src/lib/elm_code_private.h b/legacy/elm_code/src/lib/elm_code_private.h index b37a3fffe0..260d3ffc2d 100644 --- a/legacy/elm_code/src/lib/elm_code_private.h +++ b/legacy/elm_code/src/lib/elm_code_private.h @@ -46,7 +46,7 @@ typedef struct unsigned int cursor_line, cursor_col; Eina_Bool editable, focussed; Eina_Bool show_line_numbers; - unsigned int line_width_marker; + unsigned int line_width_marker, tabstop; Eina_Bool show_whitespace; Elm_Code_Widget_Selection_Data *selection; diff --git a/legacy/elm_code/src/lib/elm_code_text.c b/legacy/elm_code/src/lib/elm_code_text.c index a9e86be57a..8460f90f0d 100644 --- a/legacy/elm_code/src/lib/elm_code_text.c +++ b/legacy/elm_code/src/lib/elm_code_text.c @@ -36,7 +36,6 @@ elm_code_line_text_set(Elm_Code_Line *line, const char *chars, unsigned int leng strncpy(newtext, chars, length); line->modified = newtext; line->length = length; - line->unicode_length = elm_code_text_unicode_strlen(line->modified, line->length); file = line->file; elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line); @@ -158,7 +157,6 @@ elm_code_line_text_insert(Elm_Code_Line *line, unsigned int position, const char line->modified = inserted; line->length += length; - line->unicode_length = elm_code_text_unicode_strlen(line->modified, line->length); file = line->file; elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line); @@ -196,7 +194,6 @@ elm_code_line_text_remove(Elm_Code_Line *line, unsigned int position, int length line->modified = removed; line->length -= length; - line->unicode_length = elm_code_text_unicode_strlen(line->modified, line->length); file = line->file; elm_code_callback_fire(file->parent, &ELM_CODE_EVENT_LINE_LOAD_DONE, line); @@ -204,24 +201,47 @@ elm_code_line_text_remove(Elm_Code_Line *line, unsigned int position, int length /* generic text functions */ +unsigned int +elm_code_text_tabwidth_at_position(unsigned int position, unsigned int tabstop) +{ + return tabstop - (position % tabstop); +} + EAPI unsigned int -elm_code_text_unicode_strlen(const char *chars, unsigned int length) +elm_code_line_text_column_width_to_position(Elm_Code_Line *line, unsigned int position, unsigned int tabstop) { Eina_Unicode unicode; unsigned int count = 0; int index = 0; + const char *chars; - if (chars == NULL) + if (line->length == 0) return 0; - while ((unsigned int) index < length) + if (line->modified) + chars = line->modified; + else + chars = line->content; + if (position > line->length) + position = line->length; + + while ((unsigned int) index < position) { unicode = eina_unicode_utf8_next_get(chars, &index); if (unicode == 0) break; - count++; + if (unicode == '\t') + count += elm_code_text_tabwidth_at_position(count, tabstop); + else + count++; } return count; } + +EAPI unsigned int +elm_code_line_text_column_width(Elm_Code_Line *line, unsigned int tabstop) +{ + return elm_code_line_text_column_width_to_position(line, line->length, tabstop); +} diff --git a/legacy/elm_code/src/lib/elm_code_text.h b/legacy/elm_code/src/lib/elm_code_text.h index 3df2ff6774..1deb1ab5b0 100644 --- a/legacy/elm_code/src/lib/elm_code_text.h +++ b/legacy/elm_code/src/lib/elm_code_text.h @@ -48,7 +48,11 @@ EAPI void elm_code_line_text_remove(Elm_Code_Line *line, unsigned int position, * */ -EAPI unsigned int elm_code_text_unicode_strlen(const char *chars, unsigned int length); +EAPI unsigned int elm_code_text_tabwidth_at_position(unsigned int position, unsigned int tabstop); + +EAPI unsigned int elm_code_line_text_column_width_to_position(Elm_Code_Line *line, unsigned int length, unsigned int tabstop); + +EAPI unsigned int elm_code_line_text_column_width(Elm_Code_Line *line, unsigned int tabstop); /** * @} diff --git a/legacy/elm_code/src/lib/elm_code_widget.c b/legacy/elm_code/src/lib/elm_code_widget.c index 6911f95519..caf6af9311 100644 --- a/legacy/elm_code/src/lib/elm_code_widget.c +++ b/legacy/elm_code/src/lib/elm_code_widget.c @@ -51,6 +51,8 @@ _elm_code_widget_eo_base_constructor(Eo *obj, Elm_Code_Widget_Data *pd) pd->cursor_line = 1; pd->cursor_col = 1; + + pd->tabstop = 8; } EOLIAN static Eo * @@ -92,6 +94,7 @@ _elm_code_widget_resize(Elm_Code_Widget *widget) Eina_List *item; Evas_Coord ww, wh, old_width, old_height; int w, h, cw, ch, gutter; + unsigned int line_width; Elm_Code_Widget_Data *pd; pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); @@ -108,8 +111,11 @@ _elm_code_widget_resize(Elm_Code_Widget *widget) w = 0; h = elm_code_file_lines_get(pd->code->file); EINA_LIST_FOREACH(pd->code->file->lines, item, line) - if ((int) line->unicode_length + gutter + 1 > w) - w = (int) line->unicode_length + gutter + 1; + { + line_width = elm_code_line_text_column_width(line, pd->tabstop); + if ((int) column_length + gutter + 1 > w) + w = (int) column_length + gutter + 1; + } if (w*cw > ww) ww = w*cw; @@ -156,21 +162,21 @@ static void _elm_code_widget_fill_line_tokens(Elm_Code_Widget *widget, Evas_Textgrid_Cell *cells, unsigned int count, Elm_Code_Line *line) { + Elm_Code_Widget_Data *pd; Eina_List *item; Elm_Code_Token *token; - const char *content; unsigned int start, end, length, offset; unsigned int token_start_col, token_end_col; + pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); offset = elm_code_widget_text_left_gutter_width_get(widget); start = offset; - content = elm_code_line_text_get(line, NULL); - length = line->unicode_length + offset; + length = elm_code_line_text_column_width(line, pd->tabstop) + offset; EINA_LIST_FOREACH(line->tokens, item, token) { - token_start_col = elm_code_text_unicode_strlen(content, token->start - 1) + offset; - token_end_col = elm_code_text_unicode_strlen(content, token->end - 1) + offset; + token_start_col = elm_code_line_text_column_width_to_position(line, token->start - 1, pd->tabstop) + offset; + token_end_col = elm_code_line_text_column_width_to_position(line, token->end - 1, pd->tabstop) + offset; if (token_start_col > start) _elm_code_widget_fill_line_token(cells, count, start, token_start_col, ELM_CODE_TOKEN_TYPE_DEFAULT); @@ -235,7 +241,11 @@ _elm_code_widget_fill_whitespace(Elm_Code_Widget *widget, Eina_Unicode character pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); if (!pd->show_whitespace) - return; + { + if (character== '\t') + cell->codepoint = 0; + return; + } switch (character) { @@ -301,7 +311,7 @@ _elm_code_widget_fill_line(Elm_Code_Widget *widget, Elm_Code_Line *line) { char *chr; Eina_Unicode unichr; - unsigned int length, x; + unsigned int length, x, charwidth, i; int w, chrpos, gutter; Evas_Textgrid_Cell *cells; Elm_Code_Widget_Data *pd; @@ -315,17 +325,26 @@ _elm_code_widget_fill_line(Elm_Code_Widget *widget, Elm_Code_Line *line) _elm_code_widget_fill_gutter(widget, cells, line->status, line->number); _elm_code_widget_fill_line_tokens(widget, cells, w, line); - length = elm_code_line_utf8_length_get(line); + length = elm_code_line_text_column_width(line, pd->tabstop); chrpos = 0; chr = (char *)elm_code_line_text_get(line, NULL); - for (x = gutter; x < (unsigned int) w && x < length + gutter; x++) + for (x = gutter; x < (unsigned int) w && x < length + gutter; x+=charwidth) { unichr = eina_unicode_utf8_next_get(chr, &chrpos); cells[x].codepoint = unichr; cells[x].bg = _elm_code_widget_status_type_get(widget, line->status, x - gutter + 1); + charwidth = 1; + if (unichr == '\t') + charwidth = elm_code_text_tabwidth_at_position(x - gutter, pd->tabstop); + for (i = x + 1; i < x + charwidth; i++) + { + cells[i].codepoint = 0; + cells[i].bg = _elm_code_widget_status_type_get(widget, line->status, x - gutter + 1); + } + _elm_code_widget_fill_whitespace(widget, unichr, &cells[x]); } for (; x < (unsigned int) w; x++) @@ -459,7 +478,7 @@ _elm_code_widget_cursor_key_will_move(Elm_Code_Widget *widget, const char *key) else if (!strcmp(key, "Left")) return pd->cursor_col > 1; else if (!strcmp(key, "Right")) - return pd->cursor_col < (unsigned int) line->unicode_length + 1; + return pd->cursor_col < elm_code_line_text_column_width(line, pd->tabstop) + 1; else return EINA_FALSE; } @@ -586,15 +605,17 @@ _elm_code_widget_clicked_editable_cb(Elm_Code_Widget *widget, unsigned int row, { Elm_Code_Widget_Data *pd; Elm_Code_Line *line; + unsigned int column_width; pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); line = elm_code_file_line_get(pd->code->file, row); if (!line) return; + column_width = elm_code_line_text_column_width(line, pd->tabstop); - if (col > line->unicode_length + 1) - col = line->unicode_length + 1; + if (col > column_width + 1) + col = column_width + 1; else if (col <= 0) col = 1; @@ -704,7 +725,7 @@ _elm_code_widget_cursor_move_up(Elm_Code_Widget *widget) { Elm_Code_Widget_Data *pd; Elm_Code_Line *line; - unsigned int row, col; + unsigned int row, col, column_width; pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); row = pd->cursor_line; @@ -715,8 +736,9 @@ _elm_code_widget_cursor_move_up(Elm_Code_Widget *widget) row--; line = elm_code_file_line_get(pd->code->file, row); - if (col > (unsigned int) line->unicode_length + 1) - col = line->unicode_length + 1; + column_width = elm_code_line_text_column_width(line, pd->tabstop); + if (col > column_width + 1) + col = column_width + 1; _elm_code_widget_cursor_move(widget, pd, col, row, EINA_TRUE); } @@ -726,7 +748,7 @@ _elm_code_widget_cursor_move_down(Elm_Code_Widget *widget) { Elm_Code_Widget_Data *pd; Elm_Code_Line *line; - unsigned int row, col; + unsigned int row, col, column_width; pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); row = pd->cursor_line; @@ -737,8 +759,9 @@ _elm_code_widget_cursor_move_down(Elm_Code_Widget *widget) row++; line = elm_code_file_line_get(pd->code->file, row); - if (col > (unsigned int) line->unicode_length + 1) - col = line->unicode_length + 1; + column_width = elm_code_line_text_column_width(line, pd->tabstop); + if (col > column_width + 1) + col = column_width + 1; _elm_code_widget_cursor_move(widget, pd, col, row, EINA_TRUE); } @@ -765,7 +788,7 @@ _elm_code_widget_cursor_move_right(Elm_Code_Widget *widget) pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); line = elm_code_file_line_get(pd->code->file, pd->cursor_line); - if (pd->cursor_col > (unsigned int) line->unicode_length) + if (pd->cursor_col > elm_code_line_text_column_width(line, pd->tabstop)) return; _elm_code_widget_cursor_move(widget, pd, pd->cursor_col+1, pd->cursor_line, EINA_TRUE); @@ -918,6 +941,9 @@ _elm_code_widget_delete(Elm_Code_Widget *widget) Elm_Code *code; Elm_Code_Line *line; unsigned int row, col; + Elm_Code_Widget_Data *pd; + + pd = eo_data_scope_get(widget, ELM_CODE_WIDGET_CLASS); if (_elm_code_widget_delete_selection(widget)) return; @@ -926,7 +952,7 @@ _elm_code_widget_delete(Elm_Code_Widget *widget) code = elm_code_widget_code_get(), elm_code_widget_cursor_position_get(&col, &row)); line = elm_code_file_line_get(code->file, row); - if (col > line->unicode_length) + if (col > elm_code_line_text_column_width(line, pd->tabstop)) { if (row == elm_code_file_lines_get(code->file)) return; @@ -1111,6 +1137,19 @@ _elm_code_widget_gravity_get(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd, doub *y = pd->gravity_y; } +EOLIAN static void +_elm_code_widget_tabstop_set(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd, unsigned int tabstop) +{ + pd->tabstop = tabstop; + _elm_code_widget_fill(obj); +} + +EOLIAN static unsigned int +_elm_code_widget_tabstop_get(Eo *obj EINA_UNUSED, Elm_Code_Widget_Data *pd) +{ + return pd->tabstop; +} + EOLIAN static void _elm_code_widget_editable_set(Eo *obj, Elm_Code_Widget_Data *pd, Eina_Bool editable) { diff --git a/legacy/elm_code/src/lib/elm_code_widget.eo b/legacy/elm_code/src/lib/elm_code_widget.eo index 98b35cc012..f8b8c6cda3 100644 --- a/legacy/elm_code/src/lib/elm_code_widget.eo +++ b/legacy/elm_code/src/lib/elm_code_widget.eo @@ -59,6 +59,26 @@ class Elm_Code_Widget (Elm_Layout, Elm_Interface_Atspi_Text) double y; /*@ The vertical gravity of the widget's scroller - valid values are 0.0 and 1.0 */ } } + tabstop { + set { + /*@ + Set the width of a tab stop, used purely for visual layout of tab characters. + + Recommended value is between 2 and 8. + + @ingroup Layout */ + } + get { + /*@ + Get the current width of a tab stop. + This is used to determine where characters after a tab should appear in the line.. + + @ingroup Layout */ + } + values { + uint tabstop; /*@ Maximum width of a tab character */ + } + } editable { set { /*@ diff --git a/legacy/elm_code/src/lib/elm_code_widget_selection.c b/legacy/elm_code/src/lib/elm_code_widget_selection.c index 115a7a051c..e1b388fb40 100644 --- a/legacy/elm_code/src/lib/elm_code_widget_selection.c +++ b/legacy/elm_code/src/lib/elm_code_widget_selection.c @@ -22,6 +22,7 @@ _elm_code_widget_selection_limit(Evas_Object *widget EINA_UNUSED, Elm_Code_Widge { Elm_Code_Line *line; Elm_Code_File *file; + unsigned int width; file = pd->code->file; @@ -29,9 +30,10 @@ _elm_code_widget_selection_limit(Evas_Object *widget EINA_UNUSED, Elm_Code_Widge *row = elm_code_file_lines_get(file); line = elm_code_file_line_get(file, *row); + width = elm_code_line_text_column_width(line, pd->tabstop); - if (*col > line->unicode_length + 1) - *col = line->unicode_length + 1; + if (*col > width + 1) + *col = width + 1; if (*col < 1) *col = 1; }