[geany/geany] 593b9d: Merge branch 'single-line-regex'

Colomban Wendling git-noreply at xxxxx
Sat Aug 9 23:51:48 UTC 2014


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Sat, 09 Aug 2014 23:51:48 UTC
Commit:      593b9dd2c9345c381a8929c8aaabbba968b2e472
             https://github.com/geany/geany/commit/593b9dd2c9345c381a8929c8aaabbba968b2e472

Log Message:
-----------
Merge branch 'single-line-regex'


Modified Paths:
--------------
    doc/geany.txt
    src/callbacks.c
    src/document.c
    src/keybindings.c
    src/search.c
    src/search.h

Modified: doc/geany.txt
35 lines changed, 35 insertions(+), 0 deletions(-)
===================================================================
@@ -1231,6 +1231,10 @@ The syntax for the *Use regular expressions* option is shown in
 .. note::
     *Use escape sequences* is implied for regular expressions.
 
+The *Use multi-line matching* option enables multi-line regular
+expressions instead of single-line ones.  See `Regular expressions`_ for
+more details on the differences between the two modes.
+
 The *Use escape sequences* option will transform any escaped characters
 into their UTF-8 equivalent. For example, \\t will be transformed into
 a tab character. Other recognized symbols are: \\\\, \\n, \\r, \\uXXXX
@@ -1451,10 +1455,17 @@ options`_). The syntax is Perl compatible. Basic syntax is described
 in the table below. For full details, see
 http://www.geany.org/manual/gtk/glib/glib-regex-syntax.html.
 
+By default regular expressions are matched on a line-by-line basis.
+If you are interested in multi-line regular expressions, matched against
+the whole buffer at once, see the section `Multi-line regular expressions`_
+below.
+
 .. note::
     1. The *Use escape sequences* dialog option always applies for regular
        expressions.
     2. Searching backwards with regular expressions is not supported.
+    3. The *Use multi-line matching* dialog option to select single or
+       multi-line matching.
 
 **In a regular expression, the following characters are interpreted:**
 
@@ -1531,6 +1542,30 @@ $       This matches the end of a line.
     distributed under the `License for Scintilla and SciTE`_.
 
 
+Multi-line regular expressions
+``````````````````````````````
+
+.. note::
+    The *Use multi-line matching* dialog option enables multi-line
+    regular expressions.
+
+Multi-line regular expressions work just like single-line ones but a
+match can span several lines.
+
+While the syntax is the same, a few practical differences applies:
+
+======= ============================================================
+.       Matches any character but newlines.  This behavior can be changed
+        to also match newlines using the (?s) option, see
+        http://www.geany.org/manual/gtk/glib/glib-regex-syntax.html#idp5671632
+
+[^...]  A negative range (see above) *will* match newlines if they are
+        not explicitly listed in that negative range.  For example, range
+        [^a-z] will match newlines, while range [^a-z\\r\\n] won't.
+        While this is the expected behavior, it can lead to tricky
+        problems if one doesn't think about it when writing an expression.
+======= ============================================================
+
 
 View menu
 ---------


Modified: src/callbacks.c
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -837,14 +837,14 @@ static void find_usage(gboolean in_session)
 	if (sci_has_selection(doc->editor->sci))
 	{	/* take selected text if there is a selection */
 		search_text = sci_get_selection_contents(doc->editor->sci);
-		flags = SCFIND_MATCHCASE;
+		flags = GEANY_FIND_MATCHCASE;
 	}
 	else
 	{
 		editor_find_current_word_sciwc(doc->editor, -1,
 			editor_info.current_word, GEANY_MAX_WORD_LENGTH);
 		search_text = g_strdup(editor_info.current_word);
-		flags = SCFIND_MATCHCASE | SCFIND_WHOLEWORD;
+		flags = GEANY_FIND_MATCHCASE | GEANY_FIND_WHOLEWORD;
 	}
 
 	search_find_usage(search_text, search_text, flags, in_session);
@@ -934,7 +934,7 @@ G_MODULE_EXPORT void on_find_next1_activate(GtkMenuItem *menuitem, gpointer user
 
 G_MODULE_EXPORT void on_find_previous1_activate(GtkMenuItem *menuitem, gpointer user_data)
 {
-	if (search_data.flags & SCFIND_REGEXP)
+	if (search_data.flags & GEANY_FIND_REGEXP)
 		/* Can't reverse search order for a regex (find next ignores search backwards) */
 		utils_beep();
 	else


Modified: src/document.c
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -1491,7 +1491,7 @@ static void replace_header_filename(GeanyDocument *doc)
 	ttf.chrg.cpMax = sci_get_position_from_line(doc->editor->sci, 4);
 	ttf.lpstrText = filebase;
 
-	if (search_find_text(doc->editor->sci, SCFIND_MATCHCASE | SCFIND_REGEXP, &ttf, NULL) != -1)
+	if (search_find_text(doc->editor->sci, GEANY_FIND_MATCHCASE | GEANY_FIND_REGEXP, &ttf, NULL) != -1)
 	{
 		sci_set_target_start(doc->editor->sci, ttf.chrgText.cpMin);
 		sci_set_target_end(doc->editor->sci, ttf.chrgText.cpMax);
@@ -2043,7 +2043,7 @@ gint document_find_text(GeanyDocument *doc, const gchar *text, const gchar *orig
 		return -1;
 
 	/* Sci doesn't support searching backwards with a regex */
-	if (flags & SCFIND_REGEXP)
+	if (flags & GEANY_FIND_REGEXP)
 		search_backwards = FALSE;
 
 	if (!original_text)
@@ -2124,7 +2124,7 @@ gint document_replace_text(GeanyDocument *doc, const gchar *find_text, const gch
 		return -1;
 
 	/* Sci doesn't support searching backwards with a regex */
-	if (flags & SCFIND_REGEXP)
+	if (flags & GEANY_FIND_REGEXP)
 		search_backwards = FALSE;
 
 	if (!original_find_text)


Modified: src/keybindings.c
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -1466,9 +1466,9 @@ static gboolean cb_func_search_action(guint key_id)
 				text = get_current_word_or_sel(doc, TRUE);
 
 			if (sci_has_selection(sci))
-				search_mark_all(doc, text, SCFIND_MATCHCASE);
+				search_mark_all(doc, text, GEANY_FIND_MATCHCASE);
 			else
-				search_mark_all(doc, text, SCFIND_MATCHCASE | SCFIND_WHOLEWORD);
+				search_mark_all(doc, text, GEANY_FIND_MATCHCASE | GEANY_FIND_WHOLEWORD);
 
 			g_free(text);
 			break;


Modified: src/search.c
151 lines changed, 104 insertions(+), 47 deletions(-)
===================================================================
@@ -95,12 +95,14 @@ static struct
 	gint fif_files_mode;
 	gchar *fif_files;
 	gboolean find_regexp;
+	gboolean find_regexp_multiline;
 	gboolean find_escape_sequences;
 	gboolean find_case_sensitive;
 	gboolean find_match_whole_word;
 	gboolean find_match_word_start;
 	gboolean find_close_dialog;
 	gboolean replace_regexp;
+	gboolean replace_regexp_multiline;
 	gboolean replace_escape_sequences;
 	gboolean replace_case_sensitive;
 	gboolean replace_match_whole_word;
@@ -237,6 +239,8 @@ static void init_prefs(void)
 	configuration_add_pref_group(group, FALSE);
 	stash_group_add_toggle_button(group, &settings.find_regexp,
 		"find_regexp", FALSE, "check_regexp");
+	stash_group_add_toggle_button(group, &settings.find_regexp_multiline,
+		"find_regexp_multiline", FALSE, "check_multiline");
 	stash_group_add_toggle_button(group, &settings.find_case_sensitive,
 		"find_case_sensitive", FALSE, "check_case");
 	stash_group_add_toggle_button(group, &settings.find_escape_sequences,
@@ -253,6 +257,8 @@ static void init_prefs(void)
 	configuration_add_pref_group(group, FALSE);
 	stash_group_add_toggle_button(group, &settings.replace_regexp,
 		"replace_regexp", FALSE, "check_regexp");
+	stash_group_add_toggle_button(group, &settings.replace_regexp_multiline,
+		"replace_regexp_multiline", FALSE, "check_multiline");
 	stash_group_add_toggle_button(group, &settings.replace_case_sensitive,
 		"replace_case_sensitive", FALSE, "check_case");
 	stash_group_add_toggle_button(group, &settings.replace_escape_sequences,
@@ -300,7 +306,7 @@ static void on_widget_toggled_set_insensitive(
 static GtkWidget *add_find_checkboxes(GtkDialog *dialog)
 {
 	GtkWidget *checkbox1, *checkbox2, *check_regexp, *check_back, *checkbox5,
-			  *checkbox7, *hbox, *fbox, *mbox;
+			  *checkbox7, *check_multiline, *hbox, *fbox, *mbox;
 
 	check_regexp = gtk_check_button_new_with_mnemonic(_("_Use regular expressions"));
 	ui_hookup_widget(dialog, check_regexp, "check_regexp");
@@ -310,33 +316,36 @@ static GtkWidget *add_find_checkboxes(GtkDialog *dialog)
 	g_signal_connect(check_regexp, "toggled",
 		G_CALLBACK(on_find_replace_checkbutton_toggled), dialog);
 
-	if (dialog != GTK_DIALOG(find_dlg.dialog))
-	{
-		check_back = gtk_check_button_new_with_mnemonic(_("Search _backwards"));
-		ui_hookup_widget(dialog, check_back, "check_back");
-		gtk_button_set_focus_on_click(GTK_BUTTON(check_back), FALSE);
-	}
-	else
-	{	/* align the two checkboxes at the top of the hbox */
-		GtkSizeGroup *label_size;
-		check_back = gtk_label_new(NULL);
-		label_size = gtk_size_group_new(GTK_SIZE_GROUP_VERTICAL);
-		gtk_size_group_add_widget(GTK_SIZE_GROUP(label_size), check_back);
-		gtk_size_group_add_widget(GTK_SIZE_GROUP(label_size), check_regexp);
-		g_object_unref(label_size);
-	}
 	checkbox7 = gtk_check_button_new_with_mnemonic(_("Use _escape sequences"));
 	ui_hookup_widget(dialog, checkbox7, "check_escape");
 	gtk_button_set_focus_on_click(GTK_BUTTON(checkbox7), FALSE);
 	gtk_widget_set_tooltip_text(checkbox7,
-		_("Replace \\\\, \\t, \\n, \\r and \\uXXXX (Unicode chararacters) with the "
+		_("Replace \\\\, \\t, \\n, \\r and \\uXXXX (Unicode characters) with the "
 		  "corresponding control characters"));
 
+	check_multiline = gtk_check_button_new_with_mnemonic(_("Use multi-_line matching"));
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_multiline), FALSE);
+	gtk_widget_set_sensitive(check_multiline, FALSE);
+	ui_hookup_widget(dialog, check_multiline, "check_multiline");
+	gtk_button_set_focus_on_click(GTK_BUTTON(check_multiline), FALSE);
+	gtk_widget_set_tooltip_text(check_multiline, _("Perform regular expression "
+		"matching on the whole buffer at once rather than line by line, allowing "
+		"matches to span multiple lines.  In this mode, newline characters are part "
+		"of the input and can be captured as normal characters by the pattern."));
+
 	/* Search features */
 	fbox = gtk_vbox_new(FALSE, 0);
-	gtk_container_add(GTK_CONTAINER(fbox), check_regexp);
-	gtk_container_add(GTK_CONTAINER(fbox), checkbox7);
-	gtk_container_add(GTK_CONTAINER(fbox), check_back);
+	gtk_box_pack_start(GTK_BOX(fbox), check_regexp, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(fbox), check_multiline, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(fbox), checkbox7, FALSE, FALSE, 0);
+
+	if (dialog != GTK_DIALOG(find_dlg.dialog))
+	{
+		check_back = gtk_check_button_new_with_mnemonic(_("Search _backwards"));
+		ui_hookup_widget(dialog, check_back, "check_back");
+		gtk_button_set_focus_on_click(GTK_BUTTON(check_back), FALSE);
+		gtk_container_add(GTK_CONTAINER(fbox), check_back);
+	}
 
 	checkbox1 = gtk_check_button_new_with_mnemonic(_("C_ase sensitive"));
 	ui_hookup_widget(dialog, checkbox1, "check_case");
@@ -356,9 +365,9 @@ static GtkWidget *add_find_checkboxes(GtkDialog *dialog)
 
 	/* Matching options */
 	mbox = gtk_vbox_new(FALSE, 0);
-	gtk_container_add(GTK_CONTAINER(mbox), checkbox1);
-	gtk_container_add(GTK_CONTAINER(mbox), checkbox2);
-	gtk_container_add(GTK_CONTAINER(mbox), checkbox5);
+	gtk_box_pack_start(GTK_BOX(mbox), checkbox1, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(mbox), checkbox2, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(mbox), checkbox5, FALSE, FALSE, 0);
 
 	hbox = gtk_hbox_new(TRUE, 6);
 	gtk_container_add(GTK_CONTAINER(hbox), fbox);
@@ -1142,6 +1151,7 @@ on_find_replace_checkbutton_toggled(GtkToggleButton *togglebutton, gpointer user
 		GtkWidget *check_word = ui_lookup_widget(dialog, "check_word");
 		GtkWidget *check_wordstart = ui_lookup_widget(dialog, "check_wordstart");
 		GtkWidget *check_escape = ui_lookup_widget(dialog, "check_escape");
+		GtkWidget *check_multiline = ui_lookup_widget(dialog, "check_multiline");
 		gboolean replace = (dialog != find_dlg.dialog);
 		const char *back_button[2] = { "btn_previous" , "check_back" };
 
@@ -1150,6 +1160,7 @@ on_find_replace_checkbutton_toggled(GtkToggleButton *togglebutton, gpointer user
 		gtk_widget_set_sensitive(ui_lookup_widget(dialog, back_button[replace]), ! regex_set);
 		gtk_widget_set_sensitive(check_word, ! regex_set);
 		gtk_widget_set_sensitive(check_wordstart, ! regex_set);
+		gtk_widget_set_sensitive(check_multiline, regex_set);
 	}
 }
 
@@ -1259,20 +1270,21 @@ static void
 on_find_entry_activate_backward(GtkEntry *entry, gpointer user_data)
 {
 	/* can't search backwards with a regexp */
-	if (search_data.flags & SCFIND_REGEXP)
+	if (search_data.flags & GEANY_FIND_REGEXP)
 		utils_beep();
 	else
 		on_find_dialog_response(NULL, GEANY_RESPONSE_FIND_PREVIOUS, user_data);
 }
 
 
-static gboolean int_search_flags(gint match_case, gint whole_word, gint regexp, gint word_start)
+static gboolean int_search_flags(gint match_case, gint whole_word, gint regexp, gint multiline, gint word_start)
 {
-	return (match_case ? SCFIND_MATCHCASE : 0) |
-		(regexp ? SCFIND_REGEXP | SCFIND_POSIX : 0) |
-		(whole_word ? SCFIND_WHOLEWORD : 0) |
+	return (match_case ? GEANY_FIND_MATCHCASE : 0) |
+		(regexp ? GEANY_FIND_REGEXP : 0) |
+		(whole_word ? GEANY_FIND_WHOLEWORD : 0) |
+		(multiline ? GEANY_FIND_MULTILINE : 0) |
 		/* SCFIND_WORDSTART overrides SCFIND_WHOLEWORD, but we want the opposite */
-		(word_start && !whole_word ? SCFIND_WORDSTART : 0);
+		(word_start && !whole_word ? GEANY_FIND_WORDSTART : 0);
 }
 
 
@@ -1302,7 +1314,8 @@ on_find_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
 		search_data.text = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(user_data)))));
 		search_data.original_text = g_strdup(search_data.text);
 		search_data.flags = int_search_flags(settings.find_case_sensitive,
-			settings.find_match_whole_word, settings.find_regexp, settings.find_match_word_start);
+			settings.find_match_whole_word, settings.find_regexp, settings.find_regexp_multiline,
+			settings.find_match_word_start);
 
 		if (EMPTY(search_data.text))
 		{
@@ -1311,7 +1324,7 @@ on_find_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
 			gtk_widget_grab_focus(find_dlg.entry);
 			return;
 		}
-		if (search_data.flags & SCFIND_REGEXP)
+		if (search_data.flags & GEANY_FIND_REGEXP)
 		{
 			GRegex *regex = compile_regex(search_data.text, search_data.flags);
 			if (!regex)
@@ -1443,16 +1456,16 @@ on_replace_dialog_response(GtkDialog *dialog, gint response, gpointer user_data)
 
 	search_flags_re = int_search_flags(settings.replace_case_sensitive,
 		settings.replace_match_whole_word, settings.replace_regexp,
-		settings.replace_match_word_start);
+		settings.replace_regexp_multiline, settings.replace_match_word_start);
 
-	if ((response != GEANY_RESPONSE_FIND) && (search_flags_re & SCFIND_MATCHCASE)
+	if ((response != GEANY_RESPONSE_FIND) && (search_flags_re & GEANY_FIND_MATCHCASE)
 		&& (strcmp(find, replace) == 0))
 		goto fail;
 
 	original_find = g_strdup(find);
 	original_replace = g_strdup(replace);
 
-	if (search_flags_re & SCFIND_REGEXP)
+	if (search_flags_re & GEANY_FIND_REGEXP)
 	{
 		GRegex *regex = compile_regex(find, search_flags_re);
 		if (regex)
@@ -1919,11 +1932,13 @@ static GRegex *compile_regex(const gchar *str, gint sflags)
 {
 	GRegex *regex;
 	GError *error = NULL;
-	gint rflags = G_REGEX_MULTILINE;
+	gint rflags = 0;
 
-	if (~sflags & SCFIND_MATCHCASE)
+	if (sflags & GEANY_FIND_MULTILINE)
+		rflags |= G_REGEX_MULTILINE;
+	if (~sflags & GEANY_FIND_MATCHCASE)
 		rflags |= G_REGEX_CASELESS;
-	if (sflags & (SCFIND_WHOLEWORD | SCFIND_WORDSTART))
+	if (sflags & (GEANY_FIND_WHOLEWORD | GEANY_FIND_WORDSTART))
 	{
 		geany_debug("%s: Unsupported regex flags found!", G_STRFUNC);
 	}
@@ -1952,14 +1967,45 @@ static gint find_regex(ScintillaObject *sci, guint pos, GRegex *regex, GeanyMatc
 	const gchar *text;
 	GMatchInfo *minfo;
 	gint ret = -1;
+	gint offset = 0;
 
 	g_return_val_if_fail(pos <= (guint)sci_get_length(sci), -1);
 
-	/* Warning: any SCI calls will invalidate 'text' after calling SCI_GETCHARACTERPOINTER */
-	text = (void*)scintilla_send_message(sci, SCI_GETCHARACTERPOINTER, 0, 0);
+	if (g_regex_get_compile_flags(regex) & G_REGEX_MULTILINE)
+	{
+		/* Warning: any SCI calls will invalidate 'text' after calling SCI_GETCHARACTERPOINTER */
+		text = (void*)scintilla_send_message(sci, SCI_GETCHARACTERPOINTER, 0, 0);
+		g_regex_match_full(regex, text, -1, pos, 0, &minfo, NULL);
+	}
+	else /* single-line mode, manually match against each line */
+	{
+		gint line = sci_get_line_from_position(sci, pos);
+
+		for (;;)
+		{
+			gint start = sci_get_position_from_line(sci, line);
+			gint end = sci_get_line_end_position(sci, line);
+
+			text = (void*)scintilla_send_message(sci, SCI_GETRANGEPOINTER, start, end - start);
+			if (g_regex_match_full(regex, text, end - start, pos - start, 0, &minfo, NULL))
+			{
+				offset = start;
+				break;
+			}
+			else /* not found, try next line */
+			{
+				line ++;
+				if (line >= sci_get_line_count(sci))
+					break;
+				pos = sci_get_position_from_line(sci, line);
+				/* don't free last info, it's freed below */
+				g_match_info_free(minfo);
+			}
+		}
+	}
 
 	/* Warning: minfo will become invalid when 'text' does! */
-	if (g_regex_match_full(regex, text, -1, pos, 0, &minfo, NULL))
+	if (g_match_info_matches(minfo))
 	{
 		guint i;
 
@@ -1971,8 +2017,8 @@ static gint find_regex(ScintillaObject *sci, guint pos, GRegex *regex, GeanyMatc
 			gint start = -1, end = -1;
 
 			g_match_info_fetch_pos(minfo, (gint)i, &start, &end);
-			match->matches[i].start = start;
-			match->matches[i].end = end;
+			match->matches[i].start = offset + start;
+			match->matches[i].end = offset + end;
 		}
 		match->start = match->matches[0].start;
 		match->end = match->matches[0].end;
@@ -1987,7 +2033,7 @@ gint search_find_prev(ScintillaObject *sci, const gchar *str, gint flags, GeanyM
 {
 	gint ret;
 
-	g_return_val_if_fail(! (flags & SCFIND_REGEXP), -1);
+	g_return_val_if_fail(! (flags & GEANY_FIND_REGEXP), -1);
 
 	ret = sci_search_prev(sci, flags, str);
 	if (ret != -1 && match_)
@@ -1996,6 +2042,17 @@ gint search_find_prev(ScintillaObject *sci, const gchar *str, gint flags, GeanyM
 }
 
 
+static gint geany_find_flags_to_sci_flags(gint flags)
+{
+	g_warn_if_fail(! (flags & GEANY_FIND_MULTILINE));
+
+	return ((flags & GEANY_FIND_MATCHCASE) ? SCFIND_MATCHCASE : 0) |
+		((flags & GEANY_FIND_WHOLEWORD) ? SCFIND_WHOLEWORD : 0) |
+		((flags & GEANY_FIND_REGEXP) ? SCFIND_REGEXP | SCFIND_POSIX : 0) |
+		((flags & GEANY_FIND_WORDSTART) ? SCFIND_WORDSTART : 0);
+}
+
+
 gint search_find_next(ScintillaObject *sci, const gchar *str, gint flags, GeanyMatchInfo **match_)
 {
 	GeanyMatchInfo *match;
@@ -2003,9 +2060,9 @@ gint search_find_next(ScintillaObject *sci, const gchar *str, gint flags, GeanyM
 	gint ret = -1;
 	gint pos;
 
-	if (~flags & SCFIND_REGEXP)
+	if (~flags & GEANY_FIND_REGEXP)
 	{
-		ret = sci_search_next(sci, flags, str);
+		ret = sci_search_next(sci, geany_find_flags_to_sci_flags(flags), str);
 		if (ret != -1 && match_)
 			*match_ = match_info_new(flags, ret, ret + strlen(str));
 		return ret;
@@ -2087,9 +2144,9 @@ gint search_find_text(ScintillaObject *sci, gint flags, struct Sci_TextToFind *t
 	GRegex *regex;
 	gint ret;
 
-	if (~flags & SCFIND_REGEXP)
+	if (~flags & GEANY_FIND_REGEXP)
 	{
-		ret = sci_find_text(sci, flags, ttf);
+		ret = sci_find_text(sci, geany_find_flags_to_sci_flags(flags), ttf);
 		if (ret != -1 && match_)
 			*match_ = match_info_new(flags, ttf->chrgText.cpMin, ttf->chrgText.cpMax);
 		return ret;


Modified: src/search.h
9 lines changed, 9 insertions(+), 0 deletions(-)
===================================================================
@@ -61,6 +61,15 @@ enum GeanyFindSelOptions
 	GEANY_FIND_SEL_AGAIN
 };
 
+enum GeanyFindFlags
+{
+	GEANY_FIND_MATCHCASE = 1 << 0,
+	GEANY_FIND_WHOLEWORD = 1 << 1,
+	GEANY_FIND_WORDSTART = 1 << 2,
+	GEANY_FIND_REGEXP    = 1 << 3,
+	GEANY_FIND_MULTILINE = 1 << 4
+};
+
 /** Search preferences */
 typedef struct GeanySearchPrefs
 {



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list