59
65
#include "keybindings.h"
60
66
#include "project.h"
61
67
#include "projectprivate.h"
65
/* Note: Avoid using SSM in files not related to scintilla, use sciwrappers.h instead. */
71
/* Note: use sciwrappers.h instead where possible.
72
* Do not use SSM in files unrelated to scintilla. */
66
73
#define SSM(s, m, w, l) scintilla_send_message(s, m, w, l)
69
static GeanyQueue *snippet_queue = NULL;
76
static GHashTable *snippet_hash = NULL;
77
static GQueue *snippet_offsets = NULL;
70
78
static gint snippet_cursor_insert_pos;
72
80
/* holds word under the mouse or keyboard cursor */
100
116
static void auto_table(GeanyEditor *editor, gint pos);
101
117
static void close_block(GeanyEditor *editor, gint pos);
102
118
static void editor_highlight_braces(GeanyEditor *editor, gint cur_pos);
103
static void editor_auto_latex(GeanyEditor *editor, gint pos);
119
static void read_current_word(GeanyEditor *editor, gint pos, gchar *word, size_t wordlen,
120
const gchar *wc, gboolean stem);
121
static gsize count_indent_size(GeanyEditor *editor, const gchar *base_indent);
106
124
void editor_snippets_free(void)
108
g_hash_table_destroy(editor_prefs.snippets);
109
queue_destroy(snippet_queue);
126
g_hash_table_destroy(snippet_hash);
127
g_queue_free(snippet_offsets);
146
164
keys_sys = g_key_file_get_keys(sysconfig, groups_sys[i], &len_keys, NULL);
147
165
/* create new hash table for the read section (=> filetype) */
148
166
tmp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
149
g_hash_table_insert(editor_prefs.snippets, g_strdup(groups_sys[i]), tmp);
167
g_hash_table_insert(snippet_hash, g_strdup(groups_sys[i]), tmp);
151
169
for (j = 0; j < len_keys; j++)
163
181
keys_user = g_key_file_get_keys(userconfig, groups_user[i], &len_keys, NULL);
165
tmp = g_hash_table_lookup(editor_prefs.snippets, groups_user[i]);
183
tmp = g_hash_table_lookup(snippet_hash, groups_user[i]);
167
185
{ /* new key found, create hash table */
168
186
tmp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
169
g_hash_table_insert(editor_prefs.snippets, g_strdup(groups_user[i]), tmp);
187
g_hash_table_insert(snippet_hash, g_strdup(groups_user[i]), tmp);
171
189
for (j = 0; j < len_keys; j++)
291
gint editor_get_long_line_type(void)
294
switch (app->project->long_line_behaviour)
296
case 0: /* marker disabled */
298
case 1: /* use global settings */
300
case 2: /* custom (enabled) */
301
return editor_prefs.long_line_global_type;
304
if (!editor_prefs.long_line_global_enabled)
307
return editor_prefs.long_line_global_type;
311
gint editor_get_long_line_column(void)
313
if (app->project && app->project->long_line_behaviour != 1 /* use global settings */)
314
return app->project->long_line_column;
316
return editor_prefs.long_line_global_column;
273
320
void editor_toggle_fold(GeanyEditor *editor, gint line, gint modifiers)
275
322
ScintillaObject *sci;
517
555
/* we use the position where the calltip was previously started as SCI_GETCURRENTPOS
518
556
* may be completely wrong in case the user cancelled the auto completion with the mouse */
519
557
SSM(calltip.sci, SCI_CALLTIPSHOW, calltip.pos, (sptr_t) calltip.text);
521
/* now autocompletion has been cancelled by SCI_CALLTIPSHOW, so do it manually */
522
if (cri->message == SCN_AUTOCSELECTION)
524
gint pos = SSM(calltip.sci, SCI_GETCURRENTPOS, 0, 0);
526
sci_set_selection_start(calltip.sci, cri->pos);
527
sci_set_selection_end(calltip.sci, pos);
528
sci_replace_sel(calltip.sci, ""); /* clear root of word */
529
SSM(calltip.sci, SCI_INSERTTEXT, cri->pos, (sptr_t) cri->text);
530
sci_goto_pos(calltip.sci, cri->pos + strlen(cri->text), FALSE);
544
CalltipReshowInfo *cri = g_new0(CalltipReshowInfo, 1);
545
cri->message = nt->nmhdr.code;
546
cri->message = nt->lParam;
547
cri->text = g_strdup(nt->text);
548
567
/* delay the reshow of the calltip window to make sure it is actually displayed,
549
568
* without it might be not visible on SCN_AUTOCCANCEL */
550
g_idle_add(reshow_calltip, cri);
569
g_idle_add(reshow_calltip, NULL);
554
574
static void autocomplete_scope(GeanyEditor *editor)
556
576
ScintillaObject *sci = editor->sci;
752
775
((levelPrev & SC_FOLDLEVELNUMBERMASK) > (levelNow & SC_FOLDLEVELNUMBERMASK)))
754
777
/* See if should still be hidden */
755
gint parentLine = SSM(sci, SCI_GETFOLDPARENT, line, 0);
778
gint parentLine = sci_get_fold_parent(sci, line);
756
779
if (parentLine < 0)
758
781
SSM(sci, SCI_SHOWLINES, line, line);
760
else if (SSM(sci, SCI_GETFOLDEXPANDED, parentLine, 0) &&
761
SSM(sci, SCI_GETLINEVISIBLE, parentLine, 0))
783
else if (sci_get_fold_expanded(sci, parentLine) &&
784
sci_get_line_is_visible(sci, parentLine))
763
786
SSM(sci, SCI_SHOWLINES, line, line);
823
static void partial_complete(ScintillaObject *sci, const gchar *text)
825
gint pos = sci_get_current_position(sci);
827
sci_insert_text(sci, pos, text);
828
sci_set_current_position(sci, pos + strlen(text), TRUE);
832
/* Complete the next word part from @a entry */
833
static gboolean check_partial_completion(GeanyEditor *editor, const gchar *entry)
835
gchar *stem, *ptr, *text = utils_strdupa(entry);
837
read_current_word(editor, -1, current_word, sizeof current_word, NULL, TRUE);
839
if (strstr(text, stem) != text)
840
return FALSE; /* shouldn't happen */
841
if (strlen(text) <= strlen(stem))
844
text += strlen(stem); /* skip stem */
845
ptr = strstr(text + 1, "_");
849
partial_complete(editor->sci, text);
855
foreach_str(ptr, text + 1)
859
if (g_ascii_isupper(*ptr) && g_ascii_islower(ptr[1]))
862
partial_complete(editor->sci, text);
800
871
/* Callback for the "sci-notify" signal to emit a "editor-notify" signal.
801
872
* Plugins can connect to the "editor-notify" signal. */
802
873
void editor_sci_notify_cb(G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gint scn,
861
927
fold_changed(sci, nt->line, nt->foldLevelNow, nt->foldLevelPrev);
865
931
case SCN_CHARADDED:
866
932
on_char_added(editor, nt);
869
935
case SCN_USERLISTSELECTION:
871
936
if (nt->listType == 1)
873
SSM(sci, SCI_ADDTEXT, strlen(nt->text), (sptr_t) nt->text);
938
sci_add_text(sci, nt->text);
877
942
case SCN_AUTOCSELECTION:
878
943
if (g_str_equal(nt->text, "..."))
1298
1356
line = sci_get_line_from_position(sci, pos);
1299
1357
line_len = sci_get_line_length(sci, line);
1300
1358
/* set eol_char_len to 0 if on last line, because there is no EOL char */
1301
eol_char_len = (line == (SSM(sci, SCI_GETLINECOUNT, 0, 0) - 1)) ? 0 :
1359
eol_char_len = (line == (sci_get_line_count(sci) - 1)) ? 0 :
1302
1360
editor_get_eol_char_len(editor);
1304
1362
/* check that the line is empty, to not kill text in the line */
1354
1412
* position can be -1, then the current position is used.
1355
1413
* wc are the wordchars to use, if NULL, GEANY_WORDCHARS will be used */
1356
1414
static void read_current_word(GeanyEditor *editor, gint pos, gchar *word, size_t wordlen,
1357
const gchar *wc, gboolean stem)
1415
const gchar *wc, gboolean stem)
1359
1417
gint line, line_start, startword, endword;
1459
1517
gint orig_pos = pos;
1461
c = SSM(sci, SCI_GETCHARAT, pos, 0);
1519
c = sci_get_char_at(sci, pos);
1462
1520
while (pos >= 0 && pos > orig_pos - 300)
1464
c = SSM(sci, SCI_GETCHARAT, pos, 0);
1522
c = sci_get_char_at(sci, pos);
1466
1524
if (utils_is_opening_brace(c, editor_prefs.brace_match_ltgt))
1476
1534
gint brackets = 0;
1477
1535
gint orig_pos = pos;
1479
c = SSM(sci, SCI_GETCHARAT, pos, 0);
1537
c = sci_get_char_at(sci, pos);
1480
1538
while (pos > 0 && pos > orig_pos - 300)
1482
c = SSM(sci, SCI_GETCHARAT, pos, 0);
1540
c = sci_get_char_at(sci, pos);
1483
1541
if (c == ')') brackets++;
1484
1542
else if (c == '(') brackets--;
1637
1695
sci = editor->sci;
1639
lexer = SSM(sci, SCI_GETLEXER, 0, 0);
1697
lexer = sci_get_lexer(sci);
1643
1701
/* position of '(' is unknown, so go backwards from current position to find it */
1644
pos = SSM(sci, SCI_GETCURRENTPOS, 0, 0);
1702
pos = sci_get_current_position(sci);
1646
1704
orig_pos = pos;
1647
1705
pos = (lexer == SCLEX_LATEX) ? find_previous_brace(sci, pos) :
1836
1891
g_strdelimit(words->str, " ", '\n');
1837
1892
words->str[words->len - 1] = '\0'; /* remove the trailing '\n' */
1838
show_autocomplete(sci, rootlen, words->str + 1);
1895
g_string_free(words, TRUE);
1900
static gboolean autocomplete_doc_word(GeanyEditor *editor, gchar *root, gsize rootlen)
1902
ScintillaObject *sci = editor->sci;
1906
GSList *node, *list = NULL;
1908
words = get_doc_words(sci, root, rootlen);
1842
1911
scintilla_send_message(sci, SCI_AUTOCCANCEL, 0, 0);
1912
autocompletion_mode = AUTOC_CANCELLED;
1916
/* words are unsorted, make list of words */
1917
foreach_str(ptr, words->str)
1921
list = g_slist_prepend(list, ptr + 1);
1922
/* terminate previous string in list */
1927
list = g_slist_sort(list, (GCompareFunc)utils_str_casecmp);
1929
str = g_string_sized_new(words->len);
1930
foreach_slist(node, list)
1932
g_string_append(str, node->data);
1934
g_string_append_c(str, '\n');
1936
if (g_slist_length(list) >= editor_prefs.autocompletion_max_entries)
1937
g_string_append(str, "\n...");
1844
1940
g_string_free(words, TRUE);
1942
autocompletion_mode = AUTOC_DOC_WORDS;
1943
show_autocomplete(sci, rootlen, str->str);
1944
g_string_free(str, TRUE);
1874
1974
line_pos = pos - line_start - 1;
1875
1975
current = pos - line_start;
1876
1976
startword = current;
1877
lexer = SSM(sci, SCI_GETLEXER, 0, 0);
1878
style = SSM(sci, SCI_GETSTYLEAT, pos - 2, 0);
1977
lexer = sci_get_lexer(sci);
1978
style = sci_get_style_at(sci, pos - 2);
1880
1980
/* don't autocomplete in comments and strings */
1881
1981
if (!force && !is_code_style(lexer, style))
1941
static void editor_auto_latex(GeanyEditor *editor, gint pos)
1943
ScintillaObject *sci;
1945
g_return_if_fail(editor != NULL);
1947
if (editor->document->file_type->id != GEANY_FILETYPES_LATEX)
1952
if (sci_get_char_at(sci, pos - 1 - editor_get_eol_char_len(editor)) == '}')
1954
gchar *eol, *buf, *construct;
1956
gint line = sci_get_line_from_position(sci, pos - 2);
1957
gint line_len = sci_get_line_length(sci, line);
1961
buf = sci_get_line(sci, line);
1963
/* get to the first non-blank char (some kind of ltrim()) */
1965
while (isspace(buf[start]) && buf[start] != '\0')
1968
/* check for begin */
1969
if (strncmp(buf + start, "\\begin", 6) == 0)
1974
/* take also "\begingroup" (or whatever there can be) and
1975
* append "\endgroup" and so on. */
1977
while (i < line_len && buf[i] != '{' && j < (sizeof(full_cmd) - 1))
1978
{ /* copy all between "\begin" and "{" to full_cmd */
1979
full_cmd[j] = buf[i];
1985
/* go through the line and get the environment */
1986
for (i = start + j; i < line_len; i++)
1992
while (buf[i] != '}' && j < (sizeof(env) - 1))
1993
{ /* this could be done in a shorter way, but so it remains readable ;-) */
2003
/* Search whether the environment is closed within the next
2004
* lines. We assume, no \end is needed in such cases */
2005
/* TODO using sci_find_text() should be way faster than getting
2006
* the line buffer and performing string comparisons */
2007
for (i = 1; i < 5; i++)
2010
gchar *end_construct;
2011
tmp = sci_get_line(sci, line + i);
2012
/* Again get to the first non-blank char */
2014
while (isspace(buf[start]) && buf[start] != '\0')
2016
end_construct = g_strdup_printf("\\end%s{%s}", full_cmd, env);
2017
if (strstr(tmp, end_construct) != NULL)
2019
utils_free_pointers(3, tmp, buf, end_construct, NULL);
2025
/* get the indentation */
2026
if (editor->auto_indent)
2027
read_indent(editor, pos);
2028
eol = g_strconcat(editor_get_eol_char(editor), indent, NULL);
2030
construct = g_strdup_printf("%s\\end%s{%s}", eol, full_cmd, env);
2032
SSM(sci, SCI_INSERTTEXT, pos, (sptr_t) construct);
2033
sci_goto_pos(sci,pos, TRUE);
2037
/* later there could be some else ifs for other keywords */
2044
static gchar *snippets_find_completion_by_name(const gchar *type, const gchar *name)
2041
static const gchar *snippets_find_completion_by_name(const gchar *type, const gchar *name)
2046
2043
gchar *result = NULL;
2047
2044
GHashTable *tmp;
2049
2046
g_return_val_if_fail(type != NULL && name != NULL, NULL);
2051
tmp = g_hash_table_lookup(editor_prefs.snippets, type);
2048
tmp = g_hash_table_lookup(snippet_hash, type);
2052
2049
if (tmp != NULL)
2054
2051
result = g_hash_table_lookup(tmp, name);
2093
static void snippets_replace_wildcards(GeanyEditor *editor, GString *text)
2095
gchar *year = utils_get_date_time(template_prefs.year_format, NULL);
2096
gchar *date = utils_get_date_time(template_prefs.date_format, NULL);
2097
gchar *datetime = utils_get_date_time(template_prefs.datetime_format, NULL);
2098
gchar *basename = g_path_get_basename(DOC_FILENAME(editor->document));
2100
templates_replace_all(text, year, date, datetime);
2101
utils_string_replace_all(text, "{filename}", basename);
2103
utils_free_pointers(4, year, date, datetime, basename, NULL);
2107
2090
/* this only works with spaces only indentation on the lines */
2108
2091
static void fix_line_indents(GeanyEditor *editor, gint line_start, gint line_end)
2131
/* Insert text, replacing \t tab chars with the correct indent width, and \n newline
2132
* chars with the correct line ending string.
2133
* @param text Intended as e.g. "if (1)\n\tdo_something();"
2114
static void replace_leading_tabs(GString *str, const gchar *whitespace)
2118
regmatch_t matches[2];
2121
if (regcomp(®ex, "^ *(\t)", 0) != 0)
2123
g_return_if_fail(FALSE);
2128
if (regexec(®ex, ptr,
2129
G_N_ELEMENTS(matches), matches, 0) != 0)
2132
pos = matches[1].rm_so;
2133
g_return_if_fail(pos >= 0);
2134
pos += ptr - str->str;
2135
g_string_erase(str, pos, 1);
2136
g_string_insert(str, pos, whitespace);
2137
ptr = str->str + pos + strlen(whitespace);
2143
/** Inserts text, replacing \\t tab chars (@c 0x9) and \\n newline chars (@c 0xA)
2144
* accordingly for the document.
2145
* - Leading tabs are replaced with the correct indentation.
2146
* - Non-leading tabs are replaced with spaces (except when using 'Tabs' indent type).
2147
* - Newline chars are replaced with the correct line ending string.
2148
* This is very useful for inserting code without having to handle the indent
2149
* type yourself (Tabs & Spaces mode can be tricky).
2150
* @param editor Editor.
2151
* @param text Intended as e.g. @c "if (foo)\n\tbar();".
2152
* @param insert_pos Document position to insert text at.
2134
2153
* @param cursor_index If >= 0, the index into @a text to place the cursor.
2135
2154
* @param newline_indent_size Indentation size (in spaces) to insert for each newline; use
2136
2155
* -1 to read the indent size from the line with @a insert_pos on it.
2137
* @param replace_newlines Whether to replace newlines in text or not. If
2138
* newlines have been replaced before, this should be false, to avoid multiple
2139
* replacements of newlines, which is error prone on Windows.
2140
* @warning Make sure all \t tab chars in @a text are intended as indent widths,
2141
* NOT any hard tabs (you get those when copying document text with the Tabs
2142
* & Spaces indent mode set).
2143
* @note This doesn't scroll the cursor in view afterwards. */
2144
static void editor_insert_text_block(GeanyEditor *editor, const gchar *text, gint insert_pos,
2156
* @param replace_newlines Whether to replace newlines. If
2157
* newlines have been replaced already, this should be false, to avoid errors e.g. on Windows.
2158
* @warning Make sure all \\t tab chars in @a text are intended as indent widths or alignment,
2159
* not hard tabs, as those won't be preserved.
2160
* @note This doesn't scroll the cursor in view afterwards. **/
2161
void editor_insert_text_block(GeanyEditor *editor, const gchar *text, gint insert_pos,
2145
2162
gint cursor_index, gint newline_indent_size, gboolean replace_newlines)
2147
2164
ScintillaObject *sci = editor->sci;
2150
2167
gchar *whitespace;
2152
2169
const gchar cur_marker[] = "__GEANY_CURSOR_MARKER__";
2170
const gchar *eol = editor_get_eol_char(editor);
2171
const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(editor);
2154
2173
g_return_if_fail(text);
2174
g_return_if_fail(editor != NULL);
2175
g_return_if_fail(insert_pos >= 0);
2156
2177
buf = g_string_new(text);
2158
2179
if (cursor_index >= 0)
2159
2180
g_string_insert(buf, cursor_index, cur_marker); /* remember cursor pos */
2182
if (newline_indent_size == -1)
2184
/* count indent size up to insert_pos instead of asking sci
2185
* because there may be spaces after it */
2186
gchar *tmp = sci_get_line(sci, line_start);
2187
gint idx = insert_pos - sci_get_position_from_line(sci, line_start);
2189
newline_indent_size = count_indent_size(editor, tmp);
2161
2193
/* Add line indents (in spaces) */
2163
if (newline_indent_size == -1)
2164
newline_indent_size = sci_get_line_indentation(sci, line_start);
2166
2194
if (newline_indent_size > 0)
2168
2196
whitespace = g_strnfill(newline_indent_size, ' ');
2169
setptr(whitespace, g_strconcat("\n", whitespace, NULL));
2170
utils_string_replace_all(buf, "\n", whitespace);
2197
setptr(whitespace, g_strconcat(eol, whitespace, NULL));
2198
utils_string_replace_all(buf, eol, whitespace);
2171
2199
g_free(whitespace);
2174
2202
/* transform line endings */
2175
2203
if (replace_newlines)
2176
utils_string_replace_all(buf, "\n", editor_get_eol_char(editor));
2204
utils_string_replace_all(buf, "\n", eol);
2178
/* transform tabs into indent widths (in spaces) */
2179
whitespace = g_strnfill(editor_get_indent_prefs(editor)->width, ' ');
2180
utils_string_replace_all(buf, "\t", whitespace);
2206
/* transform leading tabs into indent widths (in spaces) */
2207
whitespace = g_strnfill(iprefs->width, ' ');
2208
replace_leading_tabs(buf, whitespace);
2209
/* remaining tabs are for alignment */
2210
if (iprefs->type != GEANY_INDENT_TYPE_TABS)
2211
utils_string_replace_all(buf, "\t", whitespace);
2181
2212
g_free(whitespace);
2214
sci_start_undo_action(sci);
2183
2216
if (cursor_index >= 0)
2185
2218
gint idx = utils_strpos(buf->str, cur_marker);
2197
2230
fix_line_indents(editor, line_start, line_end);
2198
2231
snippet_cursor_insert_pos = sci_get_current_position(sci);
2233
sci_end_undo_action(sci);
2200
2234
g_string_free(buf, TRUE);
2204
2238
/* Move the cursor to the next specified cursor position in an inserted snippet.
2205
2239
* Can, and should, be optimized to give better results */
2206
void snippet_goto_next_cursor(ScintillaObject *sci, gint current_pos)
2240
void editor_goto_next_snippet_cursor(GeanyEditor *editor)
2242
ScintillaObject *sci = editor->sci;
2243
gint current_pos = sci_get_current_position(sci);
2245
if (snippet_offsets && !g_queue_is_empty(snippet_offsets))
2212
snippet_queue = queue_delete(snippet_queue, &offset, FALSE);
2249
offset = GPOINTER_TO_INT(g_queue_pop_head(snippet_offsets));
2213
2250
if (current_pos > snippet_cursor_insert_pos)
2214
snippet_cursor_insert_pos = GPOINTER_TO_INT(offset) + current_pos;
2251
snippet_cursor_insert_pos = offset + current_pos;
2216
snippet_cursor_insert_pos += GPOINTER_TO_INT(offset);
2253
snippet_cursor_insert_pos += offset;
2218
2255
sci_set_current_position(sci, snippet_cursor_insert_pos, FALSE);
2223
static gboolean snippets_complete_constructs(GeanyEditor *editor, gint pos, const gchar *word)
2264
static gssize snippets_make_replacements(GeanyEditor *editor, GString *pattern,
2225
ScintillaObject *sci = editor->sci;
2226
gchar *str, *whitespace;
2228
gint i, str_len, tmp_pos, whitespace_len, nl_count = 0;
2229
2267
gssize cur_index = -1;
2230
gint ft_id = FILETYPE_ID(editor->document->file_type);
2269
gint i, tmp_pos, whitespace_len, nl_count = 0;
2231
2270
GHashTable *specials;
2232
GeanyQueue *temp_list;
2233
const GeanyIndentPrefs *iprefs;
2271
GList *temp_list = NULL;
2272
const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(editor);
2235
2273
gint cursor_steps, old_cursor = 0;
2237
str = g_strdup(word);
2239
pattern = g_string_new(snippets_find_completion_by_name(filetypes[ft_id]->name, str));
2240
if (pattern == NULL || pattern->len == 0)
2243
g_string_free(pattern, TRUE);
2247
temp_list = queue_init();
2248
iprefs = editor_get_indent_prefs(editor);
2249
read_indent(editor, pos);
2250
indent_size = strlen(indent);
2252
/* remove the typed word, it will be added again by the used auto completion
2253
* (not really necessary but this makes the auto completion more flexible,
2254
* e.g. with a completion like hi=hello, so typing "hi<TAB>" will result in "hello") */
2255
str_len = strlen(str);
2256
sci_set_selection_start(sci, pos - str_len);
2257
sci_set_selection_end(sci, pos);
2258
sci_replace_sel(sci, "");
2259
pos -= str_len; /* pos has changed while deleting */
2261
2275
/* replace 'special' completions */
2262
specials = g_hash_table_lookup(editor_prefs.snippets, "Special");
2276
specials = g_hash_table_lookup(snippet_hash, "Special");
2263
2277
if (G_LIKELY(specials != NULL))
2265
2279
/* ugly hack using global_pattern */
2267
2281
g_hash_table_foreach(specials, snippets_replace_specials, NULL);
2270
/* replace any %template% wildcards */
2271
snippets_replace_wildcards(editor, pattern);
2284
/* replace any template {foo} wildcards */
2285
templates_replace_common(pattern, editor->document->file_name, editor->document->file_type, NULL);
2273
2287
/* transform other wildcards */
2274
2288
/* convert to %newlines%, else we get endless loops */
2310
2324
/* modify cursor_steps to take indentation count and type into account */
2312
2326
/* We're saving the relative offset to each cursor position in a simple
2313
* linked list, including intendations between them. */
2327
* linked list, including indentations between them. */
2316
2330
cursor_steps += (nl_count * indent_size);
2317
queue_append(temp_list, GINT_TO_POINTER(cursor_steps - old_cursor));
2331
temp_list = g_list_append(temp_list, GINT_TO_POINTER(cursor_steps - old_cursor));
2327
2341
utils_string_replace_all(pattern, "%newline%", editor_get_eol_char(editor));
2328
2342
utils_string_replace_all(pattern, "%ws%", whitespace);
2329
2343
g_free(whitespace);
2330
/* We create a new list, where the cursor positions for the most recent
2331
* parsed snipped come first, followed by the remaining positions */
2332
if (temp_list->data)
2333
snippet_queue = queue_concat_copy(temp_list, snippet_queue);
2346
/* Bug: {ob}pc{cb} will be replaced by % too */
2347
templates_replace_valist(pattern, "{pc}", "%", NULL);
2349
/* We put the cursor positions for the most recent
2350
* parsed snippet first, followed by any remaining positions */
2356
foreach_list(node, temp_list)
2357
g_queue_push_nth(snippet_offsets, node->data, i++);
2359
/* limit length of queue */
2360
while (g_queue_get_length(snippet_offsets) > 20)
2361
g_queue_pop_tail(snippet_offsets);
2363
g_list_free(temp_list);
2334
2365
if (cur_index < 0)
2335
2366
cur_index = pattern->len;
2372
static gboolean snippets_complete_constructs(GeanyEditor *editor, gint pos, const gchar *word)
2374
ScintillaObject *sci = editor->sci;
2377
gssize cur_index = -1;
2379
gint ft_id = FILETYPE_ID(editor->document->file_type);
2381
str = g_strdup(word);
2383
pattern = g_string_new(snippets_find_completion_by_name(filetypes[ft_id]->name, str));
2384
if (pattern == NULL || pattern->len == 0)
2387
g_string_free(pattern, TRUE);
2391
read_indent(editor, pos);
2393
/* remove the typed word, it will be added again by the used auto completion
2394
* (not really necessary but this makes the auto completion more flexible,
2395
* e.g. with a completion like hi=hello, so typing "hi<TAB>" will result in "hello") */
2396
str_len = strlen(str);
2397
sci_set_selection_start(sci, pos - str_len);
2398
sci_set_selection_end(sci, pos);
2399
sci_replace_sel(sci, "");
2400
pos -= str_len; /* pos has changed while deleting */
2402
cur_index = snippets_make_replacements(editor, pattern, strlen(indent));
2337
2404
/* finally insert the text and set the cursor */
2338
2405
editor_insert_text_block(editor, pattern->str, pos, cur_index, -1, FALSE);
2339
2406
sci_scroll_caret(sci);
2342
2409
g_string_free(pattern, TRUE);
2367
2433
gboolean editor_complete_snippet(GeanyEditor *editor, gint pos)
2369
2435
gboolean result = FALSE;
2372
2437
const gchar *word;
2373
2438
ScintillaObject *sci;
2375
2440
g_return_val_if_fail(editor != NULL, FALSE);
2377
2442
sci = editor->sci;
2443
if (sci_has_selection(sci))
2378
2445
/* return if we are editing an existing line (chars on right of cursor) */
2379
2446
if (keybindings_lookup_item(GEANY_KEY_GROUP_EDITOR,
2380
2447
GEANY_KEYS_EDITOR_COMPLETESNIPPET)->key == GDK_space &&
2381
2448
! editor_prefs.complete_snippets_whilst_editing && ! at_eol(sci, pos))
2384
lexer = SSM(sci, SCI_GETLEXER, 0, 0);
2385
style = SSM(sci, SCI_GETSTYLEAT, pos - 2, 0);
2387
2451
wc = snippets_find_completion_by_name("Special", "wordchars");
2388
2452
word = editor_read_word_stem(editor, pos, wc);
2954
3016
gint eol_len = editor_get_eol_char_len(editor);
2955
3017
if (count_uncommented > 0)
2957
sci_set_selection_start(editor->sci, sel_start - co_len - eol_len);
2958
sci_set_selection_end(editor->sci, sel_end - co_len - eol_len);
3019
sci_set_selection_start(editor->sci, sel_start - co_len + eol_len);
3020
sci_set_selection_end(editor->sci, sel_end - co_len + eol_len);
3022
else if (count_commented > 0)
2962
sci_set_selection_start(editor->sci, sel_start + co_len + eol_len);
2963
sci_set_selection_end(editor->sci, sel_end + co_len + eol_len);
3024
sci_set_selection_start(editor->sci, sel_start + co_len - eol_len);
3025
sci_set_selection_end(editor->sci, sel_end + co_len - eol_len);
2967
3029
else if (count_uncommented > 0)
2969
sci_set_current_position(editor->sci, sel_start - co_len, TRUE);
3031
gint eol_len = single_line ? 0: editor_get_eol_char_len(editor);
3032
sci_set_current_position(editor->sci, sel_start - co_len + eol_len, TRUE);
3034
else if (count_commented > 0)
3036
gint eol_len = single_line ? 0: editor_get_eol_char_len(editor);
3037
sci_set_current_position(editor->sci, sel_start + co_len - eol_len, TRUE);
3221
3289
/* Use the start of the line enter was pressed on, to avoid any doc keyword styles */
3222
3290
indent_pos = sci_get_line_indent_position(sci, cur_line - 1);
3223
3291
style = sci_get_style_at(sci, indent_pos);
3292
if (!in_block_comment(lexer, style))
3225
if (in_block_comment(lexer, style))
3295
/* Check whether the comment block continues on this line */
3296
indent_pos = sci_get_line_indent_position(sci, cur_line);
3297
if (sci_get_style_at(sci, indent_pos) == style)
3227
3299
gchar *previous_line = sci_get_line(sci, cur_line - 1);
3228
3300
/* the type of comment, '*' (C/C++/Java), '+' and the others (D) */
4270
* Retrieves the localized name (for displaying) of the used end of line characters
4271
* (LF, CR/LF, CR) in the given editor.
4272
* If @a editor is @c NULL, the default end of line characters are used.
4274
* @param editor The editor to operate on, or @c NULL to query the default value.
4275
* @return The name of the end of line characters.
4194
4279
const gchar *editor_get_eol_char_name(GeanyEditor *editor)
4196
4281
gint mode = file_prefs.default_eol_character;
4205
/* returns the end-of-line character(s) length of the specified editor */
4291
* Retrieves the length of the used end of line characters (LF, CR/LF, CR) in the given editor.
4292
* If @a editor is @c NULL, the default end of line characters are used.
4293
* The returned value is 1 for CR and LF and 2 for CR/LF.
4295
* @param editor The editor to operate on, or @c NULL to query the default value.
4296
* @return The length of the end of line characters.
4206
4300
gint editor_get_eol_char_len(GeanyEditor *editor)
4208
4302
gint mode = file_prefs.default_eol_character;
4221
/* returns the end-of-line character(s) of the specified editor */
4316
* Retrieves the used end of line characters (LF, CR/LF, CR) in the given editor.
4317
* If @a editor is @c NULL, the default end of line characters are used.
4318
* The returned value is either "\n", "\r\n" or "\r".
4320
* @param editor The editor to operate on, or @c NULL to query the default value.
4321
* @return The end of line characters.
4222
4325
const gchar *editor_get_eol_char(GeanyEditor *editor)
4224
4327
gint mode = file_prefs.default_eol_character;
4467
4571
sci_set_use_tabs(sci, use_tabs);
4469
4573
if (type == GEANY_INDENT_TYPE_BOTH)
4470
4575
sci_set_tab_width(sci, iprefs->hard_tab_width);
4576
if (iprefs->hard_tab_width != 8)
4578
static gboolean warn = TRUE;
4580
ui_set_statusbar(TRUE, _("Warning: non-standard hard tab width: %d != 8!"),
4581
iprefs->hard_tab_width);
4472
4586
sci_set_tab_width(sci, iprefs->width);
4473
4588
SSM(sci, SCI_SETINDENT, iprefs->width, 0);
4475
4590
/* remove indent spaces on backspace, if using any spaces to indent */
4480
4595
/* Convenience function for editor_goto_pos() to pass in a line number. */
4481
gboolean editor_goto_line(GeanyEditor *editor, gint line)
4596
gboolean editor_goto_line(GeanyEditor *editor, gint line_no, gint offset)
4485
4600
g_return_val_if_fail(editor, FALSE);
4486
if (line < 0 || line >= sci_get_line_count(editor->sci))
4601
if (line_no < 0 || line_no >= sci_get_line_count(editor->sci))
4489
pos = sci_get_position_from_line(editor->sci, line);
4606
gint current_line = sci_get_current_line(editor->sci);
4608
line_no = current_line + line_no;
4611
pos = sci_get_position_from_line(editor->sci, line_no);
4490
4612
return editor_goto_pos(editor, pos, TRUE);
4603
4725
sci_clear_cmdkey(sci, '\\' | (SCMOD_CTRL << 16)); /* Next word part */
4604
4726
sci_clear_cmdkey(sci, SCK_UP | (SCMOD_CTRL << 16)); /* scroll line up */
4605
4727
sci_clear_cmdkey(sci, SCK_DOWN | (SCMOD_CTRL << 16)); /* scroll line down */
4606
sci_clear_cmdkey(sci, SCK_HOME); /* line start */
4728
sci_clear_cmdkey(sci, SCK_HOME); /* line start */
4607
4729
sci_clear_cmdkey(sci, SCK_END); /* line end */
4608
4730
sci_clear_cmdkey(sci, SCK_END | (SCMOD_ALT << 16)); /* visual line end */
4657
4779
SSM(sci, SCI_REGISTERIMAGE, 1, (sptr_t)classviewer_var);
4658
4780
SSM(sci, SCI_REGISTERIMAGE, 2, (sptr_t)classviewer_method);
4782
/* necessary for column mode editing, implemented in Scintilla since 2.0 */
4783
SSM(sci, SCI_SETADDITIONALSELECTIONTYPING, 1, 0);
4786
SSM(sci, SCI_SETVIRTUALSPACEOPTIONS, editor_prefs.show_virtual_space, 0);
4660
4788
/* only connect signals if this is for the document notebook, not split window */
4661
4789
if (editor->sci == NULL)
4867
gboolean editor_complete_word_part(GeanyEditor *editor)
4871
g_return_val_if_fail(editor, FALSE);
4873
if (!SSM(editor->sci, SCI_AUTOCACTIVE, 0, 0))
4876
entry = sci_get_string(editor->sci, SCI_AUTOCGETCURRENTTEXT, 0);
4878
/* if no word part, complete normally */
4879
if (!check_partial_completion(editor, entry))
4880
SSM(editor->sci, SCI_AUTOCCOMPLETE, 0, 0);
4738
4887
void editor_init(void)
4740
4889
static GeanyIndentPrefs indent_prefs;
4828
4977
g_return_if_fail(editor != NULL);
4979
if (main_status.quitting)
4830
4982
sci = editor->sci;
4832
sci_set_mark_long_lines(sci, editor_prefs.long_line_type,
4833
editor_prefs.long_line_column, editor_prefs.long_line_color);
4984
sci_set_mark_long_lines(sci, editor_get_long_line_type(),
4985
editor_get_long_line_column(), editor_prefs.long_line_color);
4835
4987
/* update indent width, tab width */
4836
4988
editor_set_indent_type(editor, editor->indent_type);