[geany/geany-plugins] e6ad68: git-ui: Properly handle buffer encoding
Colomban Wendling
git-noreply at xxxxx
Wed Feb 18 08:38:06 UTC 2015
Branch: refs/heads/master
Author: Colomban Wendling <ban at herbesfolles.org>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Sun, 28 Dec 2014 16:06:09 UTC
Commit: e6ad6862c3213cfe35a5add39b4283b2a0e84088
https://github.com/geany/geany-plugins/commit/e6ad6862c3213cfe35a5add39b4283b2a0e84088
Log Message:
-----------
git-ui: Properly handle buffer encoding
If the file encoding is different than the buffer encoding (as Geany
will always have the buffer in UTF-8 but for encoding None) we need to
convert it to get proper binary representation and then proper diff.
Modified Paths:
--------------
git-ui/src/ggu-plugin.c
Modified: git-ui/src/ggu-plugin.c
105 lines changed, 93 insertions(+), 12 deletions(-)
===================================================================
@@ -359,27 +359,93 @@ release_resources (ScintillaObject *sci)
}
}
+/* checks whether @encoding needs to be converted to UTF-8 */
+static gboolean
+encoding_needs_coversion (const gchar *encoding)
+{
+ return (encoding &&
+ ! utils_str_equal (encoding, "UTF-8") &&
+ ! utils_str_equal (encoding, "None"));
+}
+
+/*
+ * @brief Converts encoding
+ * @param buffer Input and output buffer
+ * @param length Input and output buffer length
+ * @param to Target encoding
+ * @param from Source encoding
+ * @param error Return location for errors, or @c NULL
+ * @returns @c TRUE if the conversion succeeded and the buffer has been
+ * replaced and should be freed, or @c FALSE otherwise.
+ *
+ * @warning This function has a very weird API, but it is practical for
+ * how it's used.
+ *
+ * Converts between encodings (using g_convert()) in-place.
+ *
+ * The @p buffer is both an input and output parameter. As an input
+ * parameter, it is used as a constant buffer pointer and is never
+ * modified nor freed. As an output parameter, it is an allocated chunk
+ * of memory that should be freed with @c g_free().
+ * If the conversion succeeds, it replaces @p buffer and @p length with
+ * the converted values and returns @c TRUE. If it fails, it does not
+ * modify the values and returns @c FALSE so that the passed-in
+ * variables can be used as a fallback if the conversion was optional.
+ */
+static gboolean
+convert_encoding_inplace (gchar **buffer,
+ gsize *length,
+ const gchar *to,
+ const gchar *from,
+ GError **error)
+{
+ gsize tmp_len;
+ gchar *tmp_buf = g_convert (*buffer, (gssize) *length, to, from,
+ NULL, &tmp_len, error);
+
+ if (tmp_buf) {
+ *buffer = tmp_buf;
+ *length = tmp_len;
+ }
+
+ return tmp_buf != NULL;
+}
+
static int
-diff_blob_to_sci (const git_blob *old_blob,
- ScintillaObject *sci,
+diff_blob_to_doc (const git_blob *old_blob,
+ GeanyDocument *doc,
git_diff_hunk_cb hunk_cb,
void *payload)
{
+ ScintillaObject *sci = doc->editor->sci;
git_diff_options opts;
- const gchar *buf;
+ gchar *buf;
size_t len;
+ gboolean free_buf = FALSE;
+ int ret;
- buf = (const gchar *) scintilla_send_message (sci, SCI_GETCHARACTERPOINTER,
- 0, 0);
+ buf = (gchar *) scintilla_send_message (sci, SCI_GETCHARACTERPOINTER, 0, 0);
len = sci_get_length (sci);
+ /* convert the buffer back to in-file encoding if necessary */
+ if (encoding_needs_coversion (doc->encoding)) {
+ free_buf = convert_encoding_inplace (&buf, &len, doc->encoding, "UTF-8",
+ NULL);
+ }
+
/* no context lines, and no need to bother about binary checks */
git_diff_init_options (&opts, GIT_DIFF_OPTIONS_VERSION);
opts.context_lines = 0;
opts.flags = GIT_DIFF_FORCE_TEXT;
- return git_diff_blob_to_buffer (old_blob, NULL, buf, len, NULL, &opts,
- NULL, hunk_cb, NULL, payload);
+ ret = git_diff_blob_to_buffer (old_blob, NULL, buf, len, NULL, &opts,
+ NULL, hunk_cb, NULL, payload);
+
+ if (free_buf) {
+ g_free (buf);
+ }
+
+ return ret;
}
static int
@@ -416,6 +482,9 @@ get_widget_for_blob_range (GeanyDocument *doc,
gint height = 0;
gint i;
GtkAllocation alloc;
+ gchar *buf;
+ gsize buf_len;
+ gboolean free_buf = FALSE;
gtk_widget_get_allocation (GTK_WIDGET (doc->editor->sci), &alloc);
@@ -434,9 +503,21 @@ get_widget_for_blob_range (GeanyDocument *doc,
scintilla_send_message (sci, SCI_SETMARGINWIDTHN, i, 0);
}
- scintilla_send_message (sci, SCI_ADDTEXT,
- (gulong) git_blob_rawsize (blob),
- (glong) git_blob_rawcontent (blob));
+ buf_len = git_blob_rawsize (blob);
+ buf = (gchar *) git_blob_rawcontent (blob);
+
+ /* convert the buffer to UTF-8 if necessary */
+ if (encoding_needs_coversion (doc->encoding)) {
+ free_buf = convert_encoding_inplace (&buf, &buf_len, "UTF-8", doc->encoding,
+ NULL);
+ }
+
+ scintilla_send_message (sci, SCI_ADDTEXT, buf_len, (glong) buf);
+
+ if (free_buf) {
+ g_free (buf);
+ }
+
scintilla_send_message (sci, SCI_SETFIRSTVISIBLELINE, line_start, 0);
/* compute the size of the area we want to see */
@@ -512,7 +593,7 @@ on_sci_query_tooltip (GtkWidget *widget,
TooltipHunkData thd = TOOLTIP_HUNK_DATA_INIT (line + 1, doc, G_file_blob,
tooltip);
- diff_blob_to_sci (G_file_blob, sci, tooltip_diff_hunk_cb, &thd);
+ diff_blob_to_doc (G_file_blob, doc, tooltip_diff_hunk_cb, &thd);
has_tooltip = thd.found;
}
}
@@ -537,7 +618,7 @@ update_diff (const gchar *path,
scintilla_send_message (sci, SCI_MARKERDELETEALL, G_markers[i].num, 0);
}
- diff_blob_to_sci (blob, sci, diff_hunk_cb, sci);
+ diff_blob_to_doc (blob, doc, diff_hunk_cb, sci);
}
}
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Plugins-Commits
mailing list