Hi.

If anyone has some free time for me, please take a look at a message I
sent in November [1].  There I attached two patches for Geany which
were (and still are) necessary for XML Snippets plugin that was
discussed in that thread.  You can also read at [1] about what the
patches do.

Now I attach the updated patches.  Hope they will become a part of
Geany and the plugin (not yet released anywhere) will no longer depend
on these «third-party» patches.

[1] <http://lists.uvena.de/pipermail/geany/2010-November/006210.html>

--
Best regards,
Eugene.
diff --git a/ChangeLog b/ChangeLog
index 79a8519..461936a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-03-29  Eugene Arshinov  <earshinov(at)gmail(dot)com>
+
+ * src/editor.c, src/templates.c, src/templates.h:
+   Fix a bug in editor.c:snippets_make_replacements() with handling of
+   {ob} and {cb}. Function template_replace_common() now takes an
+   argument that controls if {ob} and {cb} should be replaced.
+
+
 2011-03-28  Colomban Wendling  <colomban(at)geany(dot)org>
 
  * src/document.c, src/document.h, src/editor.c, src/keybindings.c:
diff --git a/src/editor.c b/src/editor.c
index c093e9c..1c0a11e 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -2475,12 +2475,13 @@ static gssize snippets_make_replacements(GeanyEditor *editor, GString *pattern,
 		gsize indent_size)
 {
 	gssize cur_index = -1;
-	gchar *whitespace;
-	gint i, tmp_pos, whitespace_len, nl_count = 0;
+	gchar *whitespace, *ptr;
+	gint i, pos, whitespace_len, nl_count = 0, offset;
 	GHashTable *specials;
-	GList *temp_list = NULL;
+	GList *temp_list = NULL, *node;
 	const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(editor);
 	gint cursor_steps, old_cursor = 0;
+	gboolean cur_index_handled;
 
 	/* replace 'special' completions */
 	specials = g_hash_table_lookup(snippet_hash, "Special");
@@ -2491,8 +2492,8 @@ static gssize snippets_make_replacements(GeanyEditor *editor, GString *pattern,
 		g_hash_table_foreach(specials, snippets_replace_specials, NULL);
 	}
 
-	/* replace any template {foo} wildcards */
-	templates_replace_common(pattern, editor->document->file_name, editor->document->file_type, NULL);
+	/* replace any template {foo} wildcards except braces {ob} and {cb}  */
+	templates_replace_common(pattern, editor->document->file_name, editor->document->file_type, NULL, FALSE);
 
 	/* transform other wildcards */
 	/* convert to %newlines%, else we get endless loops */
@@ -2515,7 +2516,7 @@ static gssize snippets_make_replacements(GeanyEditor *editor, GString *pattern,
 	{
 		/* replace every %newline% (up to next %cursor%) with EOL,
 		 * and update cursor_steps after */
-		while ((tmp_pos = utils_strpos(pattern->str, "%newline%")) < cursor_steps && tmp_pos != -1)
+		while ((pos = utils_strpos(pattern->str, "%newline%")) < cursor_steps && pos != -1)
 		{
 			nl_count++;
 			utils_string_replace_first(pattern, "%newline%", editor_get_eol_char(editor));
@@ -2523,7 +2524,7 @@ static gssize snippets_make_replacements(GeanyEditor *editor, GString *pattern,
 		}
 		/* replace every %ws% (up to next %cursor%) with whitespaces,
 		 * and update cursor_steps after */
-		while ((tmp_pos = utils_strpos(pattern->str, "%ws%")) < cursor_steps && tmp_pos != -1)
+		while ((pos = utils_strpos(pattern->str, "%ws%")) < cursor_steps && pos != -1)
 		{
 			utils_string_replace_first(pattern, "%ws%", whitespace);
 			cursor_steps = utils_strpos(pattern->str, "%cursor%");
@@ -2553,16 +2554,61 @@ static gssize snippets_make_replacements(GeanyEditor *editor, GString *pattern,
 	g_free(whitespace);
 
 	/* escape % last */
-	/* Bug: {ob}pc{cb} will be replaced by % too */
-	templates_replace_valist(pattern, "{pc}", "%", NULL);
+	pos = 0;
+	offset = 0;
+	node = temp_list;
+	cur_index_handled = FALSE;
+	while ((ptr = strchr(pattern->str + pos, '{')) != NULL)
+	{
+		pos = ptr - pattern->str;
+
+		/* synchronously iterate the list of cursor positions, applying current offset
+		 * remember to handle cur_index separately */
+		if (!cur_index_handled && cur_index + offset <= pos)
+		{
+			cur_index += offset;
+			cur_index_handled = TRUE;
+		}
+		while (node && GPOINTER_TO_INT(node->data) + offset <= pos)
+		{
+			node->data += offset;
+			node = node->next;
+		}
+
+		if (strncmp(pattern->str + pos + 1, "pc}", 3) == 0)
+		{
+			g_string_erase(pattern, pos + 1, 3);
+			pattern->str[pos] = '%';
+			pos++; /* one char inserted */
+			offset -= 3; /* pattern became 3 chars shorter */
+		}
+		else if (strncmp(pattern->str + pos + 1, "ob}", 3) == 0)
+		{
+			g_string_erase(pattern, pos + 1, 3);
+			pattern->str[pos] = '{';
+			pos++; /* one char inserted */
+			offset -= 3; /* pattern became 3 chars shorter */
+		}
+		else if (strncmp(pattern->str + pos + 1, "cb}", 3) == 0)
+		{
+			g_string_erase(pattern, pos + 1, 3);
+			pattern->str[pos] = '}';
+			pos++; /* one char inserted */
+			offset -= 3; /* pattern became 3 chars shorter */
+		}
+		else
+			pos++; /* skip the brace */
+	}
+	if (!cur_index_handled)
+		cur_index += offset;
+	for (; node; node = node->next)
+		node->data += offset;
 
 	/* We put the cursor positions for the most recent
 	 * parsed snippet first, followed by any remaining positions */
 	i = 0;
 	if (temp_list)
 	{
-		GList *node;
-
 		temp_list = g_list_reverse(temp_list);
 		foreach_list(node, temp_list)
 			g_queue_push_nth(snippet_offsets, node->data, i++);
diff --git a/src/templates.c b/src/templates.c
index 160aa04..062c0d6 100644
--- a/src/templates.c
+++ b/src/templates.c
@@ -232,7 +232,7 @@ static gboolean create_new_filetype_items(void)
 
 
 void templates_replace_common(GString *template, const gchar *fname,
-							  GeanyFiletype *ft, const gchar *func_name)
+							  GeanyFiletype *ft, const gchar *func_name, gboolean replace_braces)
 {
 	gchar *shortname;
 
@@ -256,11 +256,15 @@ void templates_replace_common(GString *template, const gchar *fname,
 	templates_replace_default_dates(template);
 	templates_replace_command(template, fname, ft->name, func_name);
 	/* Bug: command results could have {ob} {cb} strings in! */
-	/* replace braces last */
-	templates_replace_valist(template,
-		"{ob}", "{",
-		"{cb}", "}",
-		NULL);
+
+	if (replace_braces)
+	{
+		/* replace braces last */
+		templates_replace_valist(template,
+			"{ob}", "{",
+			"{cb}", "}",
+			NULL);
+	}
 }
 
 
@@ -282,7 +286,7 @@ static gchar *get_template_from_file(const gchar *locale_fname, const gchar *doc
 		templates_replace_valist(template,
 			"{fileheader}", file_header,
 			NULL);
-		templates_replace_common(template, doc_filename, ft, NULL);
+		templates_replace_common(template, doc_filename, ft, NULL, TRUE);
 
 		utils_free_pointers(2, file_header, content, NULL);
 		return g_string_free(template, FALSE);
@@ -601,7 +605,7 @@ gchar *templates_get_template_fileheader(gint filetype_idx, const gchar *fname)
 	GString *template = g_string_new(str);
 
 	g_free(str);
-	templates_replace_common(template, fname, ft, NULL);
+	templates_replace_common(template, fname, ft, NULL, TRUE);
 	convert_eol_characters(template, NULL);
 	return g_string_free(template, FALSE);
 }
@@ -626,7 +630,7 @@ gchar *templates_get_template_new_file(GeanyFiletype *ft)
 		file_header = get_template_fileheader(ft);
 		templates_replace_valist(ft_template, "{fileheader}", file_header, NULL);
 	}
-	templates_replace_common(ft_template, NULL, ft, NULL);
+	templates_replace_common(ft_template, NULL, ft, NULL, TRUE);
 	convert_eol_characters(ft_template, NULL);
 
 	g_free(file_header);
diff --git a/src/templates.h b/src/templates.h
index 4b1ac58..8b657d4 100644
--- a/src/templates.h
+++ b/src/templates.h
@@ -75,7 +75,7 @@ gchar *templates_get_template_function(GeanyDocument *doc, const gchar *func_nam
 gchar *templates_get_template_licence(GeanyDocument *doc, gint licence_type);
 
 void templates_replace_common(GString *template, const gchar *fname,
-	GeanyFiletype *ft, const gchar *func_name);
+	GeanyFiletype *ft, const gchar *func_name, gboolean replace_braces);
 
 void templates_replace_valist(GString *text,
 	const gchar *first_wildcard, ...) G_GNUC_NULL_TERMINATED;
diff --git a/ChangeLog b/ChangeLog
index 461936a..8d7063c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,10 @@
    Fix a bug in editor.c:snippets_make_replacements() with handling of
    {ob} and {cb}. Function template_replace_common() now takes an
    argument that controls if {ob} and {cb} should be replaced.
+ * plugins/geanyfunctions.h, src/plugindata.h, src/plugins.c,
+   src/utils.c, src/utils.h:
+   Add utils_find_open_xml_tag_pos() function which was previously a
+   part of utils_find_open_xml_tag(). Add the new function to API.
 
 
 2011-03-28  Colomban Wendling  <colomban(at)geany(dot)org>
diff --git a/plugins/geanyfunctions.h b/plugins/geanyfunctions.h
index 8699f6b..35a6fbe 100644
--- a/plugins/geanyfunctions.h
+++ b/plugins/geanyfunctions.h
@@ -250,6 +250,8 @@
 	geany_functions->p_utils->utils_copy_environment
 #define utils_find_open_xml_tag \
 	geany_functions->p_utils->utils_find_open_xml_tag
+#define utils_find_open_xml_tag_pos \
+	geany_functions->p_utils->utils_find_open_xml_tag_pos
 #define ui_dialog_vbox_new \
 	geany_functions->p_ui->ui_dialog_vbox_new
 #define ui_frame_new_with_alignment \
diff --git a/src/plugindata.h b/src/plugindata.h
index 6f1ccd8..107a2a3 100644
--- a/src/plugindata.h
+++ b/src/plugindata.h
@@ -54,7 +54,7 @@
  * @warning You should not test for values below 200 as previously
  * @c GEANY_API_VERSION was defined as an enum value, not a macro.
  */
-#define GEANY_API_VERSION 203
+#define GEANY_API_VERSION 204
 
 /** The Application Binary Interface (ABI) version, incremented whenever
  * existing fields in the plugin data types have to be changed or reordered.
@@ -436,6 +436,7 @@ typedef struct UtilsFuncs
 				GError **error);
 	gchar**		(*utils_copy_environment)(const gchar **exclude_vars, const gchar *first_varname, ...);
 	gchar*		(*utils_find_open_xml_tag) (const gchar sel[], gint size);
+	const gchar*	(*utils_find_open_xml_tag_pos) (const gchar sel[], gint size);
 }
 UtilsFuncs;
 
@@ -626,6 +627,8 @@ typedef struct EditorFuncs
 
 	const gchar* (*editor_find_snippet) (struct GeanyEditor *editor, const gchar *snippet_name);
 	void	(*editor_insert_snippet) (struct GeanyEditor *editor, gint pos, const gchar *snippet);
+	gssize (*editor_snippets_make_replacements)(GeanyEditor *editor, GString *pattern,
+		gsize indent_size);
 }
 EditorFuncs;
 
diff --git a/src/plugins.c b/src/plugins.c
index bcf7060..add14ef 100644
--- a/src/plugins.c
+++ b/src/plugins.c
@@ -219,7 +219,8 @@ static UtilsFuncs utils_funcs = {
 	&utils_str_remove_chars,
 	&utils_get_file_list_full,
 	&utils_copy_environment,
-	&utils_find_open_xml_tag
+	&utils_find_open_xml_tag,
+	&utils_find_open_xml_tag_pos
 };
 
 static UIUtilsFuncs uiutils_funcs = {
diff --git a/src/utils.c b/src/utils.c
index 1ca9495..a6b2a4d 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -285,13 +285,34 @@ gint utils_write_file(const gchar *filename, const gchar *text)
 }
 
 
-/** Searches backward through @a size bytes looking for a '<', then returns the tag, if any.
+/** Searches backward through @a size bytes looking for a '<'
  * @param sel .
  * @param size .
- * @return The tag name.
+ * @return The tag name (newly allocated) or @c NULL if no opening tag was found
  */
 gchar *utils_find_open_xml_tag(const gchar sel[], gint size)
 {
+	const gchar *cur, *begin;
+
+	cur = utils_find_open_xml_tag_pos(sel, size);
+	if (cur == NULL)
+		return NULL;
+
+	cur++; /* skip the bracket */
+	begin = cur;
+	while (strchr(":_-.", *cur) || isalnum(*cur))
+		cur++;
+	return g_strndup(begin, cur-begin);
+}
+
+
+/** Searches backward through @a size bytes looking for a '<'
+ * @param sel .
+ * @param size .
+ * @return pointer to '<' of the found opening tag within @a sel, or @c NULL if no opening tag was found
+ */
+const gchar *utils_find_open_xml_tag_pos(const gchar sel[], gint size)
+{
 	/* stolen from anjuta and modified */
 	const gchar *begin, *cur;
 
@@ -319,27 +340,15 @@ gchar *utils_find_open_xml_tag(const gchar sel[], gint size)
 	{
 		if (*cur == '<')
 			break;
+		/* exit immediately if such non-valid XML/HTML is detected, e.g. "<script>if a >" */
 		else if (*cur == '>')
 			break;
 		--cur;
 	}
 
-	if (*cur == '<')
-	{
-		GString *result;
-
-		cur++;
-		if (*cur == '/')
-			return NULL; /* we found a closing tag */
-
-		result = g_string_sized_new(64);
-		while (strchr(":_-.", *cur) || isalnum(*cur))
-		{
-			g_string_append_c(result, *cur);
-			cur++;
-		}
-		return g_string_free(result, FALSE);
-	}
+	if (*cur == '<' && *(cur+1) != '/')
+		/* if the found tag is an opening, not a closing tag */
+		return cur;
 
 	return NULL;
 }
diff --git a/src/utils.h b/src/utils.h
index 94207c0..39ec2db 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -142,6 +142,8 @@ gint utils_write_file(const gchar *filename, const gchar *text);
 
 gchar *utils_find_open_xml_tag(const gchar sel[], gint size);
 
+const gchar *utils_find_open_xml_tag_pos(const gchar sel[], gint size);
+
 gboolean utils_is_short_html_tag(const gchar *tag_name);
 
 void utils_ensure_same_eol_characters(GString *string, gint target_eol_mode);
_______________________________________________
Geany-devel mailing list
[email protected]
https://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel

Reply via email to