[gnumeric] ssdiff: Introduce --highlight mode.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] ssdiff: Introduce --highlight mode.
- Date: Mon, 31 Dec 2012 20:35:18 +0000 (UTC)
commit c089784e69bb4a353776d418b8e336ef22d05ddf
Author: Morten Welinder <terra gnome org>
Date: Mon Dec 31 15:33:49 2012 -0500
ssdiff: Introduce --highlight mode.
This mode applies a highlighter to cells with differences and saves
a copy of the new file.
ChangeLog | 4 +
src/ssdiff.c | 271 +++++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 216 insertions(+), 59 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 21eab1a..a3911b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2012-12-31 Morten Welinder <terra gnome org>
+
+ * src/ssdiff.c: Introduce --highlight mode.
+
2012-12-30 Morten Welinder <terra gnome org>
* src/ssdiff.c (main): Add option to send output to a file.
diff --git a/src/ssdiff.c b/src/ssdiff.c
index 04014a3..6eb58da 100644
--- a/src/ssdiff.c
+++ b/src/ssdiff.c
@@ -30,11 +30,13 @@
#include "xml-sax.h"
#include <gsf/gsf-libxml.h>
#include <gsf/gsf-output-stdio.h>
+#include <gsf/gsf-input.h>
/* FIXME: Namespace? */
#define DIFF "ssdiff:"
static gboolean ssdiff_show_version = FALSE;
+static gboolean ssdiff_highlight = FALSE;
static gboolean ssdiff_xml = FALSE;
static char *ssdiff_output = NULL;
@@ -54,6 +56,13 @@ static const GOptionEntry ssdiff_options [] = {
},
{
+ "highlight", 'h',
+ 0, G_OPTION_ARG_NONE, &ssdiff_highlight,
+ N_("Output copy highlighting differences"),
+ NULL
+ },
+
+ {
"xml", 'x',
0, G_OPTION_ARG_NONE, &ssdiff_xml,
N_("Output in xml format"),
@@ -71,7 +80,7 @@ typedef struct GnmDiffState_ GnmDiffState;
typedef struct {
/* Start comparison of two workbooks. */
- void (*diff_start) (GnmDiffState *state);
+ gboolean (*diff_start) (GnmDiffState *state);
/* Finish comparison started with above. */
void (*diff_end) (GnmDiffState *state);
@@ -102,43 +111,114 @@ typedef struct {
/* The style of an area was changed. */
void (*style_changed) (GnmDiffState *state, GnmRange const *r,
+ Sheet const *osh, Sheet const *nsh,
GnmStyle const *os, GnmStyle const *ns);
} GnmDiffActions;
struct GnmDiffState_ {
GOIOContext *ioc;
- struct {
+ struct GnmDiffStateFile_ {
char *url;
+ GsfInput *input;
Workbook *wb;
WorkbookView *wbv;
} old, new;
const GnmDiffActions *actions;
- GnmConventions *convs;
-
GsfOutput *output;
/* The following for xml mode. */
GsfXMLOut *xml;
gboolean cells_open;
gboolean styles_open;
+ GnmConventions *convs;
+
+ /* The following for highlight mode. */
+ struct GnmDiffStateFile_ highlight;
+ GOFileSaver const *highlight_fs;
+ GnmStyle *highlight_style;
};
-/* -------------------------------------------------------------------------- */
+static gboolean
+null_diff_start (G_GNUC_UNUSED GnmDiffState *state)
+{
+ return FALSE;
+}
static void
-def_diff_start (GnmDiffState *state)
+null_diff_end (G_GNUC_UNUSED GnmDiffState *state)
+{
+}
+
+static void
+null_sheet_start (G_GNUC_UNUSED GnmDiffState *state,
+ G_GNUC_UNUSED Sheet const *os,
+ G_GNUC_UNUSED Sheet const *ns)
+{
+}
+
+static void
+null_sheet_end (G_GNUC_UNUSED GnmDiffState *state)
+{
+}
+
+static void
+null_sheet_order_changed (G_GNUC_UNUSED GnmDiffState *state)
+{
+}
+
+static void
+null_sheet_attr_int_changed (G_GNUC_UNUSED GnmDiffState *state,
+ G_GNUC_UNUSED const char *name,
+ G_GNUC_UNUSED int o,
+ G_GNUC_UNUSED int n)
{
- (void)state;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static gboolean
+read_file (struct GnmDiffStateFile_ *dsf, const char *filename,
+ GOIOContext *ioc)
+{
+ GError *err = NULL;
+
+ dsf->url = go_shell_arg_to_uri (filename);
+
+ if (!dsf->input)
+ dsf->input = go_file_open (dsf->url, &err);
+
+ if (!dsf->input) {
+ g_printerr (_("%s: Failed to read %s: %s\n"),
+ g_get_prgname (),
+ filename,
+ err ? err->message : "?");
+ if (err)
+ g_error_free (err);
+ return TRUE;
+ }
+
+ dsf->wbv = workbook_view_new_from_input (dsf->input,
+ dsf->url, NULL,
+ ioc, NULL);
+ if (!dsf->wbv)
+ return TRUE;
+ dsf->wb = wb_view_get_workbook (dsf->wbv);
+
+ return FALSE;
}
static void
-def_diff_end (GnmDiffState *state)
+clear_file_state (struct GnmDiffStateFile_ *dsf)
{
- (void)state;
+ g_free (dsf->url);
+ g_clear_object (&dsf->wb);
+ g_clear_object (&dsf->input);
}
+/* -------------------------------------------------------------------------- */
+
static const char *
def_cell_name (GnmCell const *oc)
{
@@ -167,12 +247,6 @@ def_sheet_start (GnmDiffState *state, Sheet const *os, Sheet const *ns)
}
static void
-def_sheet_end (GnmDiffState *state)
-{
- (void)state;
-}
-
-static void
def_sheet_order_changed (GnmDiffState *state)
{
gsf_output_printf (state->output, _("Sheet order changed.\n"));
@@ -201,6 +275,8 @@ def_cell_changed (GnmDiffState *state, GnmCell const *oc, GnmCell const *nc)
static void
def_style_changed (GnmDiffState *state, GnmRange const *r,
+ G_GNUC_UNUSED Sheet const *osh,
+ G_GNUC_UNUSED Sheet const *nsh,
G_GNUC_UNUSED GnmStyle const *os,
G_GNUC_UNUSED GnmStyle const *ns)
{
@@ -209,10 +285,10 @@ def_style_changed (GnmDiffState *state, GnmRange const *r,
}
static const GnmDiffActions default_actions = {
- def_diff_start,
- def_diff_end,
+ null_diff_start,
+ null_diff_end,
def_sheet_start,
- def_sheet_end,
+ null_sheet_end,
def_sheet_order_changed,
def_sheet_attr_int_changed,
def_cell_changed,
@@ -221,10 +297,15 @@ static const GnmDiffActions default_actions = {
/* -------------------------------------------------------------------------- */
-static void
+static gboolean
xml_diff_start (GnmDiffState *state)
{
+ state->xml = gsf_xml_out_new (state->output);
+ state->convs = gnm_xml_io_conventions ();
+
gsf_xml_out_start_element (state->xml, DIFF "Diff");
+
+ return FALSE;
}
static void
@@ -272,12 +353,6 @@ xml_sheet_end (GnmDiffState *state)
gsf_xml_out_end_element (state->xml); /* </Sheet> */
}
-static void
-xml_sheet_order_changed (GnmDiffState *state)
-{
- /* We signal this in the Sheet headers. */
-}
-
static void
xml_sheet_attr_int_changed (GnmDiffState *state, const char *name,
int o, int n)
@@ -357,6 +432,8 @@ xml_cell_changed (GnmDiffState *state, GnmCell const *oc, GnmCell const *nc)
static void
xml_style_changed (GnmDiffState *state, GnmRange const *r,
+ G_GNUC_UNUSED Sheet const *osh,
+ G_GNUC_UNUSED Sheet const *nsh,
GnmStyle const *os, GnmStyle const *ns)
{
unsigned int conflicts;
@@ -539,7 +616,7 @@ static const GnmDiffActions xml_actions = {
xml_diff_end,
xml_sheet_start,
xml_sheet_end,
- xml_sheet_order_changed,
+ null_sheet_order_changed,
xml_sheet_attr_int_changed,
xml_cell_changed,
xml_style_changed,
@@ -548,6 +625,89 @@ static const GnmDiffActions xml_actions = {
/* -------------------------------------------------------------------------- */
static gboolean
+highlight_diff_start (GnmDiffState *state)
+{
+ const char *dst = state->new.url;
+
+ state->highlight_fs = go_file_saver_for_file_name (dst);
+ if (!state->highlight_fs) {
+ g_printerr (_("%s: Unable to guess exporter to use for %s.\n"),
+ g_get_prgname (),
+ dst);
+
+ return TRUE;
+ }
+
+ /* We need a copy of one of the files. Rereading is easy. */
+ g_object_ref ((state->highlight.input = state->new.input));
+ gsf_input_seek (state->highlight.input, 0, G_SEEK_SET);
+ if (read_file (&state->highlight, dst, state->ioc))
+ return TRUE;
+
+ /* We apply a solid #F3F315 to changed cells. */
+ state->highlight_style = gnm_style_new ();
+ gnm_style_set_back_color (state->highlight_style,
+ gnm_color_new_rgb8 (0xf3, 0xf3, 0x15));
+ gnm_style_set_pattern (state->highlight_style, 1);
+
+ return FALSE;
+}
+
+static void
+highlight_diff_end (GnmDiffState *state)
+{
+ wbv_save_to_output (state->highlight.wbv, state->highlight_fs,
+ state->output, state->ioc);
+}
+
+static void
+highlight_apply (GnmDiffState *state, const char *sheetname,
+ const GnmRange *r)
+{
+ Sheet *sheet = workbook_sheet_by_name (state->highlight.wb,
+ sheetname);
+ if (!sheet)
+ return;
+
+ gnm_style_ref (state->highlight_style);
+ sheet_style_apply_range (sheet, r, state->highlight_style);
+}
+
+static void
+highlight_cell_changed (GnmDiffState *state,
+ GnmCell const *oc, GnmCell const *nc)
+{
+ GnmRange r;
+ r.start = nc->pos;
+ r.end = nc->pos;
+ highlight_apply (state, nc->base.sheet->name_unquoted, &r);
+}
+
+static void
+highlight_style_changed (GnmDiffState *state, GnmRange const *r,
+ G_GNUC_UNUSED Sheet const *osh,
+ Sheet const *nsh,
+ G_GNUC_UNUSED GnmStyle const *os,
+ G_GNUC_UNUSED GnmStyle const *ns)
+{
+ highlight_apply (state, nsh->name_unquoted, r);
+}
+
+
+static const GnmDiffActions highlight_actions = {
+ highlight_diff_start,
+ highlight_diff_end,
+ null_sheet_start,
+ null_sheet_end,
+ null_sheet_order_changed,
+ null_sheet_attr_int_changed,
+ highlight_cell_changed,
+ highlight_style_changed,
+};
+
+/* -------------------------------------------------------------------------- */
+
+static gboolean
compare_corresponding_cells (GnmCell const *co, GnmCell const *cn)
{
gboolean has_expr = gnm_cell_has_expr (co);
@@ -666,6 +826,7 @@ cb_diff_sheets_styles_2 (G_GNUC_UNUSED gpointer key,
return;
data->state->actions->style_changed (data->state, &r,
+ data->old_sheet, data->new_sheet,
data->old_style, sr->style);
}
@@ -729,31 +890,17 @@ diff (char const *oldfilename, char const *newfilename,
memset (&state, 0, sizeof (state));
state.actions = actions;
state.ioc = ioc;
-
state.output = output;
- if (ssdiff_xml)
- state.xml = gsf_xml_out_new (output);
- state.old.url = go_shell_arg_to_uri (oldfilename);
- state.new.url = go_shell_arg_to_uri (newfilename);
-
- state.old.wbv = workbook_view_new_from_uri (state.old.url, NULL,
- ioc, NULL);
- if (!state.old.wbv)
+ if (read_file (&state.old, oldfilename, ioc))
goto error;
- state.old.wb = wb_view_get_workbook (state.old.wbv);
-
- state.new.wbv = workbook_view_new_from_uri (state.new.url, NULL,
- ioc, NULL);
- if (!state.new.wbv)
+ if (read_file (&state.new, newfilename, ioc))
goto error;
- state.new.wb = wb_view_get_workbook (state.new.wbv);
-
- state.convs = gnm_xml_io_conventions ();
/* ---------------------------------------- */
-
- state.actions->diff_start (&state);
+
+ if (state.actions->diff_start (&state))
+ goto error;
/*
* This doesn't handle sheet renames very well, but simply considers
@@ -797,16 +944,14 @@ diff (char const *oldfilename, char const *newfilename,
state.actions->diff_end (&state);
out:
- g_free (state.old.url);
- g_free (state.new.url);
- if (state.old.wb)
- g_object_unref (state.old.wb);
- if (state.new.wb)
- g_object_unref (state.new.wb);
- if (state.xml)
- g_object_unref (state.xml);
+ clear_file_state (&state.old);
+ clear_file_state (&state.new);
+ clear_file_state (&state.highlight);
+ g_clear_object (&state.xml);
if (state.convs)
gnm_conventions_unref (state.convs);
+ if (state.highlight_style)
+ gnm_style_unref (state.highlight_style);
gnm_pop_C_locale (locale);
@@ -851,6 +996,20 @@ main (int argc, char const **argv)
return 0;
}
+ if (ssdiff_xml + ssdiff_highlight > 1) {
+ g_printerr (_("%s: Only one output format output may be specified.\n"),
+ g_get_prgname ());
+ return 1;
+ }
+
+ if (ssdiff_highlight) {
+ actions = &highlight_actions;
+ } else if (ssdiff_xml) {
+ actions = &xml_actions;
+ } else {
+ actions = &default_actions;
+ }
+
if (!ssdiff_output)
ssdiff_output = g_strdup ("fd://1");
output_uri = go_shell_arg_to_uri (ssdiff_output);
@@ -865,12 +1024,6 @@ main (int argc, char const **argv)
return 1;
}
- if (ssdiff_xml) {
- actions = &xml_actions;
- } else {
- actions = &default_actions;
- }
-
gnm_init ();
cc = cmd_context_stderr_new ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]