tSupport highlighting entire words when searching and replacing - ledit - Text … | |
git clone git://lumidify.org/ledit.git (fast, but not encrypted) | |
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow) | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit b7f7a516c405f90fb1294a6b7cf4463373294cb0 | |
parent 4e39cee7c2670c566dd05abc926f01aa8444e018 | |
Author: lumidify <[email protected]> | |
Date: Sat, 22 Oct 2022 11:47:14 +0200 | |
Support highlighting entire words when searching and replacing | |
Diffstat: | |
M buffer.c | 1 + | |
M configparser.c | 29 +++++++++++++++++++++++++++++ | |
M configparser.h | 1 + | |
M keys_basic.c | 14 ++++++++------ | |
M keys_command.c | 65 ++++++++++++++++++++++++-----… | |
M ledit.1 | 2 -- | |
M leditrc.5 | 16 +++++++++++----- | |
M leditrc.example | 5 +++-- | |
M search.c | 21 +++++++++++++-------- | |
M search.h | 4 ++-- | |
M theme_config.h | 3 +++ | |
M util.c | 2 +- | |
M util.h | 2 +- | |
M view.c | 14 +++++++++++--- | |
14 files changed, 134 insertions(+), 45 deletions(-) | |
--- | |
diff --git a/buffer.c b/buffer.c | |
t@@ -274,6 +274,7 @@ buffer_set_hard_line_based(ledit_buffer *buffer, int hl) { | |
buffer->hard_line_based = hl; | |
} | |
+/* FIXME: lock view if others are locked! */ | |
void | |
buffer_add_view(ledit_buffer *buffer, ledit_mode mode, size_t line, size_t pos… | |
size_t new_num = add_sz(buffer->views_num, 1); | |
diff --git a/configparser.c b/configparser.c | |
t@@ -522,6 +522,34 @@ destroy_theme_string(ledit_common *common, void *obj) { | |
free(*obj_str); | |
} | |
+static int | |
+parse_theme_bool( | |
+ ledit_common *common, | |
+ void *obj, const char *val, size_t val_len, char *key, | |
+ char *filename, size_t line, size_t line_offset, char **errstr) { | |
+ (void)common; | |
+ int *num = (int *)obj; | |
+ if (str_array_equal("true", val, val_len)) { | |
+ *num = 1; | |
+ return 0; | |
+ } else if (str_array_equal("false", val, val_len)) { | |
+ *num = 0; | |
+ return 0; | |
+ } | |
+ *errstr = print_fmt( | |
+ "%s: Invalid boolean '%.*s' " | |
+ "for '%s' at line %zu, position %zu", | |
+ filename, val_len, val, key, line, line_offset | |
+ ); | |
+ return 1; | |
+} | |
+ | |
+static void | |
+destroy_theme_bool(ledit_common *common, void *obj) { | |
+ (void)common; | |
+ (void)obj; | |
+} | |
+ | |
/* FIXME: This interface is absolutely horrible - it's mainly this way to reus… | |
theme array for the destroy function */ | |
/* If theme is NULL, a new theme is loaded, else it is destroyed */ | |
t@@ -560,6 +588,7 @@ load_destroy_theme(ledit_common *common, ast_list *theme_l… | |
{"bar-fmt", &theme->bar_fmt, &parse_theme_string, &destroy_the… | |
{"scrollbar-fg", &theme->scrollbar_fg, &parse_theme_color, &de… | |
{"scrollbar-bg", &theme->scrollbar_bg, &parse_theme_color, &de… | |
+ {"highlight-search", &theme->highlight_search, &parse_theme_bo… | |
}; | |
if (default_init) | |
diff --git a/configparser.h b/configparser.h | |
t@@ -10,6 +10,7 @@ typedef struct { | |
int scrollbar_width; | |
int scrollbar_step; | |
int text_size; | |
+ int highlight_search; | |
XftColor text_fg; | |
XftColor text_bg; | |
XftColor cursor_fg; | |
diff --git a/keys_basic.c b/keys_basic.c | |
t@@ -1,3 +1,4 @@ | |
+/* FIXME: all movement commands that modify the selection should first check i… | |
/* FIXME: should motion callbacks be ignored in visual mode as they currently … | |
/* FIXME: check allowed modes at beginning of functions */ | |
/* FIXME: the stacks here are shared for all views which can cause weird | |
t@@ -180,8 +181,8 @@ static struct basic_key_cb basic_key_cb_map[] = { | |
{"delete-to-eol", &delete_to_eol, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSE… | |
{"enter-commandedit", &enter_commandedit, KEY_FLAG_NONE|KEY_FLAG_LOCK_… | |
{"enter-insert", &enter_insert, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|VISUAL… | |
- {"enter-searchedit-backwards", &enter_searchedit_backward, KEY_FLAG_NO… | |
- {"enter-searchedit-forwards", &enter_searchedit_forward, KEY_FLAG_NONE… | |
+ {"enter-searchedit-backwards", &enter_searchedit_backward, KEY_FLAG_NO… | |
+ {"enter-searchedit-forwards", &enter_searchedit_forward, KEY_FLAG_NONE… | |
{"enter-visual", &enter_visual, KEY_FLAG_JUMP_TO_CURSOR, NORMAL|INSERT… | |
{"return-to-normal", &return_to_normal, KEY_FLAG_JUMP_TO_CURSOR|KEY_FL… | |
{"find-char-backwards", &find_char_backwards, KEY_FLAG_JUMP_TO_CURSOR|… | |
t@@ -224,8 +225,8 @@ static struct basic_key_cb basic_key_cb_map[] = { | |
{"scroll-lines-up", &scroll_lines_up, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG… | |
{"scroll-with-cursor-down", &scroll_with_cursor_down, KEY_FLAG_JUMP_TO… | |
{"scroll-with-cursor-up", &scroll_with_cursor_up, KEY_FLAG_JUMP_TO_CUR… | |
- {"search-next", &key_search_next, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOC… | |
- {"search-previous", &key_search_prev, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG… | |
+ {"search-next", &key_search_next, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG_LOC… | |
+ {"search-previous", &key_search_prev, KEY_FLAG_JUMP_TO_CURSOR|KEY_FLAG… | |
{"show-line", &show_line, KEY_FLAG_LOCK_ALLOWED, NORMAL|VISUAL|INSERT}, | |
{"switch-selection-end", &switch_selection_end, KEY_FLAG_JUMP_TO_CURSO… | |
{"toggle-hard-line-based", &toggle_hard_line_based, KEY_FLAG_NONE|KEY_… | |
t@@ -695,8 +696,8 @@ delete_selection(ledit_view *view) { | |
); | |
paste_buffer_line_based = 0; | |
view->sel_valid = 0; | |
- view->sel.line1 = view->sel.line2 = 0; | |
- view->sel.byte1 = view->sel.byte2 = 0; | |
+ view->sel.line1 = view->sel.line2 = view->cur_line; | |
+ view->sel.byte1 = view->sel.byte2 = view->cur_index; | |
view_wipe_line_cursor_attrs(view, view->cur_line); | |
return 1; | |
} | |
t@@ -1797,6 +1798,7 @@ move_cursor_left_right(ledit_view *view, int dir, int al… | |
} else { | |
view->cur_index = new_index; | |
if (view->mode == VISUAL) { | |
+ /* FIXME: check if view->sel_valid and only use it the… | |
view_set_selection(view, view->sel.line1, view->sel.by… | |
} else if (view->mode == INSERT && view->sel_valid) { | |
/* FIXME: I guess this is unnecessary now that no | |
diff --git a/keys_command.c b/keys_command.c | |
t@@ -355,20 +355,36 @@ next_replace_pos( | |
/* returns whether keys should continue being captured */ | |
static int | |
move_to_next_substitution(ledit_view *view) { | |
- view_wipe_line_cursor_attrs(view, view->cur_line); | |
+ ledit_theme *theme = config_get_theme(); | |
+ if (view->mode == NORMAL) | |
+ view_wipe_line_cursor_attrs(view, view->cur_line); | |
+ else if (view->mode == VISUAL) | |
+ view_wipe_selection(view); | |
if (!next_replace_pos(view, sub_state.line, sub_state.byte, sub_state.… | |
+ /* FIXME: why are these set here? */ | |
view->cur_line = sub_state.line; | |
view->cur_index = sub_state.byte; | |
- if (view->mode == NORMAL) | |
+ if (view->mode == NORMAL) { | |
+ view->cur_index = view_get_legal_normal_pos(view, view… | |
view_set_line_cursor_attrs(view, view->cur_line, view-… | |
+ } else if (view->mode == VISUAL) { | |
+ view_set_selection(view, view->cur_line, view->cur_ind… | |
+ } | |
window_show_message(view->window, "No more matches", -1); | |
buffer_unlock_all_views(view->buffer); | |
return 0; | |
} | |
+ if (theme->highlight_search && view->mode != VISUAL) { | |
+ view_wipe_line_cursor_attrs(view, view->cur_line); | |
+ view_set_mode(view, VISUAL); | |
+ } | |
view->cur_line = sub_state.line; | |
view->cur_index = sub_state.byte; | |
- if (view->mode == NORMAL) | |
+ if (view->mode == NORMAL) { | |
view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind… | |
+ } else if (view->mode == VISUAL && theme->highlight_search) { | |
+ view_set_selection(view, view->cur_line, view->cur_index, view… | |
+ } | |
window_show_message(view->window, "Replace? (y/Y/n/N)", -1); | |
view_ensure_cursor_shown(view); | |
return 1; | |
t@@ -402,7 +418,10 @@ substitute_single(ledit_view *view) { | |
static void | |
substitute_all_remaining(ledit_view *view) { | |
- view_wipe_line_cursor_attrs(view, view->cur_line); | |
+ if (view->mode == NORMAL) | |
+ view_wipe_line_cursor_attrs(view, view->cur_line); | |
+ else if (view->mode == VISUAL) | |
+ view_wipe_selection(view); | |
size_t min_line = SIZE_MAX; | |
while (next_replace_pos(view, sub_state.line, sub_state.byte, sub_stat… | |
if (sub_state.line < min_line) | |
t@@ -424,6 +443,8 @@ substitute_all_remaining(ledit_view *view) { | |
/* this doesn't need to be added to the undo stack since it's … | |
view->cur_index = view_get_legal_normal_pos(view, view->cur_li… | |
view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind… | |
+ } else if (view->mode == VISUAL) { | |
+ view_set_selection(view, view->cur_line, view->cur_index, view… | |
} | |
view_ensure_cursor_shown(view); | |
buffer_unlock_all_views(view->buffer); | |
t@@ -462,6 +483,8 @@ handle_substitute(ledit_view *view, char *cmd, size_t l1, … | |
} | |
c++; | |
} | |
+ free(sep); | |
+ sep = NULL; | |
free(sub_state.search); | |
free(sub_state.replace); | |
sub_state.search = ledit_strdup(cmd); | |
t@@ -477,12 +500,6 @@ handle_substitute(ledit_view *view, char *cmd, size_t l1,… | |
sub_state.num = 0; | |
sub_state.start_group = 1; | |
- /* trying to perform substitution in visual mode would make | |
- it unnecessarily complicated */ | |
- if (view->mode == VISUAL) { | |
- view_wipe_selection(view); | |
- view_set_mode(view, NORMAL); | |
- } | |
if (confirm) { | |
buffer_lock_all_views_except(view->buffer, view, "Ongoing subs… | |
view->cur_command_type = CMD_SUBSTITUTE; | |
t@@ -490,7 +507,6 @@ handle_substitute(ledit_view *view, char *cmd, size_t l1, … | |
} else { | |
substitute_all_remaining(view); | |
} | |
- free(sep); | |
return 0; | |
error: | |
window_show_message(view->window, "Invalid command", -1); | |
t@@ -871,13 +887,24 @@ edit_nextsearch(ledit_view *view, char *key_text, size_t… | |
return 1; | |
} | |
+/* FIXME: the current "highlight_search" support is a bit weird and will proba… | |
+ in some way if other support for visual mode (e.g. only search in selection… | |
/* FIXME: support visual mode, i.e. change selection to new place? */ | |
void | |
search_next(ledit_view *view) { | |
view_wipe_line_cursor_attrs(view, view->cur_line); | |
- search_state ret = ledit_search_next(view, &view->cur_line, &view->cur… | |
- if (view->mode == NORMAL) | |
+ size_t len = 0; | |
+ search_state ret = ledit_search_next(view, &view->cur_line, &view->cur… | |
+ ledit_theme *theme = config_get_theme(); | |
+ /* FIXME: figure out key stack handling when modes are also changed he… | |
+ if (theme->highlight_search && len > 0 && (ret == SEARCH_NORMAL || ret… | |
+ view_set_mode(view, VISUAL); | |
+ view_set_selection(view, view->cur_line, view->cur_index, view… | |
+ } else if (view->mode == VISUAL) { | |
+ view_set_selection(view, view->cur_line, view->cur_index, view… | |
+ } else if (view->mode == NORMAL) { | |
view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind… | |
+ } | |
view_ensure_cursor_shown(view); | |
if (ret != SEARCH_NORMAL) | |
window_show_message(view->window, search_state_to_str(ret), -1… | |
t@@ -886,9 +913,17 @@ search_next(ledit_view *view) { | |
void | |
search_prev(ledit_view *view) { | |
view_wipe_line_cursor_attrs(view, view->cur_line); | |
- search_state ret = ledit_search_prev(view, &view->cur_line, &view->cur… | |
- if (view->mode == NORMAL) | |
+ size_t len = 0; | |
+ search_state ret = ledit_search_prev(view, &view->cur_line, &view->cur… | |
+ ledit_theme *theme = config_get_theme(); | |
+ if (theme->highlight_search && len > 0 && (ret == SEARCH_NORMAL || ret… | |
+ view_set_mode(view, VISUAL); | |
+ view_set_selection(view, view->cur_line, view->cur_index, view… | |
+ } else if (view->mode == VISUAL) { | |
+ view_set_selection(view, view->cur_line, view->cur_index, view… | |
+ } if (view->mode == NORMAL) { | |
view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind… | |
+ } | |
view_ensure_cursor_shown(view); | |
if (ret != SEARCH_NORMAL) | |
window_show_message(view->window, search_state_to_str(ret), -1… | |
diff --git a/ledit.1 b/ledit.1 | |
t@@ -1,5 +1,3 @@ | |
-.\" WARNING: Some parts of this are stolen shamelessly from OpenBSD's | |
-.\" vi(1) manpage! | |
.Dd May 27, 2022 | |
.Dt LEDIT 1 | |
.Os | |
diff --git a/leditrc.5 b/leditrc.5 | |
t@@ -1,4 +1,4 @@ | |
-.Dd September 2, 2022 | |
+.Dd October 22, 2022 | |
.Dt LEDITRC 5 | |
.Os | |
.Sh NAME | |
t@@ -169,6 +169,12 @@ Default: #CCCCCC | |
.It Ar scrollbar-fg | |
Color of scrollbar handle. | |
Default: #000000 | |
+.It Ar highlight-search | |
+Whether entire words should be highlighted when searching or replacing with co… | |
+Note that the mode is automatically switched to visual when this is set and a … | |
+This is a bit weird, but in order to keep everything a bit more consistent, se… | |
+only allowed in visual mode. | |
+Default: true | |
.El | |
.Sh BINDINGS | |
The key bindings may be configured by assigning | |
t@@ -423,10 +429,10 @@ In visual mode, the selection range is automatically pas… | |
so commands can be performed on it. | |
.It Ar enter-insert Op normal, visual | |
Enter insert mode. | |
-.It Ar enter-searchedit-backwards Op normal, insert | |
+.It Ar enter-searchedit-backwards Op normal, insert, visual | |
Open the line editor for searching backwards. | |
Note that no regex is currently supported. | |
-.It Ar enter-searchedit-forwards Op normal, insert | |
+.It Ar enter-searchedit-forwards Op normal, insert, visual | |
Open the line editor for searching forwards. | |
Note that no regex is currently supported. | |
.It Ar enter-visual Op normal, insert | |
t@@ -652,9 +658,9 @@ Move | |
.Ar num | |
lines up, attempting to leave the cursor in its current line and character pos… | |
Note that this command works with soft lines, regardless of the current mode. | |
-.It Ar search-next Op normal, insert | |
+.It Ar search-next Op normal, insert, visual | |
Move to the next search result. | |
-.It Ar search-previous Op normal, insert | |
+.It Ar search-previous Op normal, insert, visual | |
Move to the previous search result. | |
.It Ar show-line Op normal, visual, insert | |
Show the current file name, whether the buffer has been modified since the last | |
diff --git a/leditrc.example b/leditrc.example | |
t@@ -18,6 +18,7 @@ theme = { | |
scrollbar-step = 20 | |
scrollbar-bg = CCCCCC | |
scrollbar-fg = 000000 | |
+ highlight-search = true | |
} | |
bindings = { | |
t@@ -66,8 +67,8 @@ bindings = { | |
bind enter-commandedit text ":" modes normal|visual | |
bind enter-searchedit-backwards text "?" modes normal | |
bind enter-searchedit-forwards text "/" modes normal | |
- bind search-next text "n" modes normal | |
- bind search-previous text "N" modes normal | |
+ bind search-next text "n" modes normal|visual | |
+ bind search-previous text "N" modes normal|visual | |
bind undo text "u" modes normal | |
bind redo text "U" modes normal | |
bind repeat-command text "." modes normal | |
diff --git a/search.c b/search.c | |
t@@ -7,6 +7,7 @@ | |
/* FIXME: make sure only whole utf8 chars are matched */ | |
static char *last_search = NULL; | |
+static size_t last_search_len = 0; | |
enum { | |
FORWARD, | |
BACKWARD | |
t@@ -22,6 +23,7 @@ set_search_forward(char *pattern) { | |
last_dir = FORWARD; | |
free(last_search); | |
last_search = ledit_strdup(pattern); | |
+ last_search_len = strlen(last_search); | |
} | |
void | |
t@@ -29,12 +31,14 @@ set_search_backward(char *pattern) { | |
last_dir = BACKWARD; | |
free(last_search); | |
last_search = ledit_strdup(pattern); | |
+ last_search_len = strlen(last_search); | |
} | |
static search_state | |
-search_forward(ledit_view *view, size_t *line_ret, size_t *byte_ret) { | |
+search_forward(ledit_view *view, size_t *line_ret, size_t *byte_ret, size_t *l… | |
*line_ret = view->cur_line; | |
*byte_ret = view->cur_index; | |
+ *len_ret = last_search_len; | |
/* if last_search is empty, strstr will find the ending '\0' */ | |
if (last_search == NULL || last_search[0] == '\0') | |
return SEARCH_NO_PATTERN; | |
t@@ -81,9 +85,10 @@ search_forward(ledit_view *view, size_t *line_ret, size_t *… | |
/* FIXME: this is insanely inefficient */ | |
/* FIXME: just go backwards char-by-char and compare */ | |
static search_state | |
-search_backward(ledit_view *view, size_t *line_ret, size_t *byte_ret) { | |
+search_backward(ledit_view *view, size_t *line_ret, size_t *byte_ret, size_t *… | |
*line_ret = view->cur_line; | |
*byte_ret = view->cur_index; | |
+ *len_ret = last_search_len; | |
if (last_search == NULL || last_search[0] == '\0') | |
return SEARCH_NO_PATTERN; | |
size_t line = view->cur_line; | |
t@@ -145,19 +150,19 @@ search_backward(ledit_view *view, size_t *line_ret, size… | |
} | |
search_state | |
-ledit_search_next(ledit_view *view, size_t *line_ret, size_t *byte_ret) { | |
+ledit_search_next(ledit_view *view, size_t *line_ret, size_t *byte_ret, size_t… | |
if (last_dir == FORWARD) | |
- return search_forward(view, line_ret, byte_ret); | |
+ return search_forward(view, line_ret, byte_ret, len_ret); | |
else | |
- return search_backward(view, line_ret, byte_ret); | |
+ return search_backward(view, line_ret, byte_ret, len_ret); | |
} | |
search_state | |
-ledit_search_prev(ledit_view *view, size_t *line_ret, size_t *byte_ret) { | |
+ledit_search_prev(ledit_view *view, size_t *line_ret, size_t *byte_ret, size_t… | |
if (last_dir == FORWARD) | |
- return search_backward(view, line_ret, byte_ret); | |
+ return search_backward(view, line_ret, byte_ret, len_ret); | |
else | |
- return search_forward(view, line_ret, byte_ret); | |
+ return search_forward(view, line_ret, byte_ret, len_ret); | |
} | |
char * | |
diff --git a/search.h b/search.h | |
t@@ -13,8 +13,8 @@ typedef enum { | |
void search_cleanup(void); | |
void set_search_forward(char *pattern); | |
void set_search_backward(char *pattern); | |
-search_state ledit_search_next(ledit_view *view, size_t *line_ret, size_t *byt… | |
-search_state ledit_search_prev(ledit_view *view, size_t *line_ret, size_t *byt… | |
+search_state ledit_search_next(ledit_view *view, size_t *line_ret, size_t *byt… | |
+search_state ledit_search_prev(ledit_view *view, size_t *line_ret, size_t *byt… | |
/* | |
* Get a string corresponding to a search_state. | |
diff --git a/theme_config.h b/theme_config.h | |
t@@ -45,5 +45,8 @@ static const char *SCROLLBAR_STEP = "20"; | |
static const char *SCROLLBAR_BG = "#CCCCCC"; | |
/* color of scrollbar handle */ | |
static const char *SCROLLBAR_FG = "#000000"; | |
+/* whether to highlight entire words when searching/replacing */ | |
+/* FIXME: this should maybe be in a separate "general config" section */ | |
+static const char *HIGHLIGHT_SEARCH = "true"; | |
#endif /* _THEME_CONFIG_H_ */ | |
diff --git a/util.c b/util.c | |
t@@ -50,7 +50,7 @@ sort_range(size_t *l1, size_t *b1, size_t *l2, size_t *b2) { | |
} | |
int | |
-str_array_equal(char *terminated, char *array, size_t len) { | |
+str_array_equal(const char *terminated, const char *array, size_t len) { | |
if (!strncmp(terminated, array, len)) { | |
/* this is kind of inefficient, but there's no way to know | |
otherwise if strncmp just stopped comparing after a '\0' */ | |
diff --git a/util.h b/util.h | |
t@@ -32,7 +32,7 @@ void sort_range(size_t *l1, size_t *b1, size_t *l2, size_t *… | |
* Returns non-zero if they are equal, 0 otherwise. | |
*/ | |
/* Note: this doesn't work if array contains '\0'. */ | |
-int str_array_equal(char *terminated, char *array, size_t len); | |
+int str_array_equal(const char *terminated, const char *array, size_t len); | |
#define LEDIT_MIN(x, y) ((x) < (y) ? (x) : (y)) | |
#define LEDIT_MAX(x, y) ((x) > (y) ? (x) : (y)) | |
diff --git a/view.c b/view.c | |
t@@ -24,6 +24,9 @@ | |
#include "assert.h" | |
#include "configparser.h" | |
+/* FIXME: handle selections better - it can happen that the cursor is moved in… | |
+ the selection, leading to weird "jumping selection" - this should be made i… | |
+ | |
/* Basic attributes set for all text. */ | |
static PangoAttrList *basic_attrs = NULL; | |
t@@ -1746,9 +1749,14 @@ view_wipe_selection(ledit_view *view) { | |
} | |
} | |
view->sel_valid = 0; | |
- view->sel.line1 = view->sel.line2 = 0; | |
- view->sel.byte1 = view->sel.byte2 = 0; | |
- view_set_line_cursor_attrs(view, view->cur_line, view->cur_index); | |
+ /* FIXME: check what makes most sense here - this used to be set to 0,… | |
+ caused "jumping effects" because some functions (cursor movement) u… | |
+ values without checking view->sel_valid before (which should actual… | |
+ changed because it is an error) */ | |
+ view->sel.line1 = view->sel.line2 = view->cur_line; | |
+ view->sel.byte1 = view->sel.byte2 = view->cur_index; | |
+ if (view->mode == NORMAL) | |
+ view_set_line_cursor_attrs(view, view->cur_line, view->cur_ind… | |
} | |
void |