[gnumeric] Conditional formats: handle diagonal borders for xls



commit c5d6389e769d7c65e389949f5cef2e4066d04228
Author: Morten Welinder <terra gnome org>
Date:   Mon Mar 17 13:04:45 2014 -0400

    Conditional formats: handle diagonal borders for xls
    
    Excel seems to ignore these even though MS has defined them in the format.

 plugins/excel/ms-excel-read.c      |   40 ++++++++++++++++-----------
 plugins/excel/ms-excel-write.c     |   52 ++++++++++++++++++++++-------------
 samples/cond-format-tests.gnumeric |  Bin 4947 -> 5034 bytes
 3 files changed, 57 insertions(+), 35 deletions(-)
---
diff --git a/plugins/excel/ms-excel-read.c b/plugins/excel/ms-excel-read.c
index f78fee7..8a99cc7 100644
--- a/plugins/excel/ms-excel-read.c
+++ b/plugins/excel/ms-excel-read.c
@@ -5132,7 +5132,8 @@ excel_read_CF_border (GnmStyle *style, ExcelReadSheet *esheet,
                      GnmStyleBorderLocation type,
                      unsigned xl_pat_index, unsigned xl_color_index)
 {
-       gnm_style_set_border (style, GNM_STYLE_BORDER_LOCATION_TO_STYLE_ELEMENT (type),
+       GnmStyleElement elem = GNM_STYLE_BORDER_LOCATION_TO_STYLE_ELEMENT (type);
+       gnm_style_set_border (style, elem,
                              gnm_style_border_fetch (biff_xf_map_border (xl_pat_index),
                                                      excel_palette_get (esheet->container.importer,
                                                                         xl_color_index),
@@ -5248,10 +5249,10 @@ excel_read_CF (BiffQuery *q, ExcelReadSheet *esheet, GnmStyleConditions *sc,
        offset =  6  /* CF record header */ + 6; /* format header */
 
        if (flags & 0x02000000) { /* number format */
-               XL_CHECK_CONDITION (q->length >= offset + 2);
-
                gboolean ignore = (flags & 0x00080000) != 0;
 
+               XL_CHECK_CONDITION (q->length >= offset + 2);
+
                if (flags2 & 1) {
                        /* Format as string */
                        guint bytes = GSF_LE_GET_GUINT16 (q->data + offset);
@@ -5382,31 +5383,38 @@ excel_read_CF (BiffQuery *q, ExcelReadSheet *esheet, GnmStyleConditions *sc,
        }
 
        if (flags & 0x10000000) { /* borders */
-               guint16 patterns;
-               guint32 colours;
+               guint32 d0, d1;
 
                XL_CHECK_CONDITION (q->length >= offset + 8);
-               patterns = GSF_LE_GET_GUINT16 (q->data + offset);
-               colours  = GSF_LE_GET_GUINT32 (q->data + offset + 2);
+               d0 = GSF_LE_GET_GUINT32 (q->data + offset);
+               d1 = GSF_LE_GET_GUINT32 (q->data + offset + 4);
 
                if (0 == (flags & 0x0400))
                        excel_read_CF_border (overlay, esheet, GNM_STYLE_BORDER_LEFT,
-                                             (patterns >>  0) & 0xf,
-                                             (colours  >>  0) & 0x7f);
+                                             (d0 >>  0) & 0xf,
+                                             (d0 >> 16) & 0x7f);
                if (0 == (flags & 0x0800))
                        excel_read_CF_border (overlay, esheet, GNM_STYLE_BORDER_RIGHT,
-                                             (patterns >>  4) & 0xf,
-                                             (colours  >>  7) & 0x7f);
+                                             (d0 >>  4) & 0xf,
+                                             (d0 >> 23) & 0x7f);
                if (0 == (flags & 0x1000))
                        excel_read_CF_border (overlay, esheet, GNM_STYLE_BORDER_TOP,
-                                             (patterns >>  8) & 0xf,
-                                             (colours  >> 16) & 0x7f);
+                                             (d0 >>  8) & 0xf,
+                                             (d1 >>  0) & 0x7f);
                if (0 == (flags & 0x2000))
                        excel_read_CF_border (overlay, esheet, GNM_STYLE_BORDER_BOTTOM,
-                                             (patterns >> 12) & 0xf,
-                                             (colours  >> 23) & 0x7f);
+                                             (d0 >> 12) & 0xf,
+                                             (d1 >>  7) & 0x7f);
+               if (0 == (flags & 0x4000) && (d0 & 0x80000000)) {
+                       excel_read_CF_border (overlay, esheet, GNM_STYLE_BORDER_DIAG,
+                                             (d1 >> 21) & 0xf,
+                                             (d1 >> 14) & 0x7f);
+               }
+               if (0 == (flags & 0x8000) && (d0 & 0x40000000))
+                       excel_read_CF_border (overlay, esheet, GNM_STYLE_BORDER_REV_DIAG,
+                                             (d1 >> 21) & 0xf,
+                                             (d1 >> 14) & 0x7f);
 
-               /* I wonder what the last two bytes are.  future growth ? */
                offset += 8;
        }
 
diff --git a/plugins/excel/ms-excel-write.c b/plugins/excel/ms-excel-write.c
index 01aa158..65c76a2 100644
--- a/plugins/excel/ms-excel-write.c
+++ b/plugins/excel/ms-excel-write.c
@@ -930,22 +930,23 @@ typedef struct {
 static gboolean
 write_border (ExcelWriteSheet const *esheet,
              GnmStyle const *s, GnmStyleElement elem,
-             guint16 *patterns, guint32 *colours,
+             guint32 d[2],
              unsigned pat_offset, unsigned colour_offset)
 {
-       unsigned   c;
+       unsigned c;
        GnmBorder *b;
 
        if (!gnm_style_is_element_set (s, elem) ||
            NULL == (b = gnm_style_get_border(s, elem)))
                return TRUE;
 
-       *patterns |= (map_border_to_xl (b->line_type, esheet->ewb->bp->version)
-                    << pat_offset);
+       d[pat_offset / 32] |=
+               (map_border_to_xl (b->line_type, esheet->ewb->bp->version)
+                << (pat_offset & 31));
 
        c = map_color_to_palette (&esheet->ewb->base,
-               b->color, PALETTE_AUTO_PATTERN);
-       *colours |= (c << colour_offset);
+                                 b->color, PALETTE_AUTO_PATTERN);
+       d[colour_offset / 32] |= (c << (colour_offset & 31));
 
        return FALSE;
 }
@@ -1107,7 +1108,7 @@ cb_write_condition (GnmStyleConditions const *sc, CondDetails *cd,
                GnmStyleCond const *cond = g_ptr_array_index (details, i);
                GnmStyle const *s = cond->overlay;
                GnmExprTop const *alt_texpr;
-               guint32 flags = 0x0030C380; /* these are always true */
+               guint32 flags = 0x00300380; /* these are always true */
                guint16 flags2 = 0x02; /* these are always true */
 
                ms_biff_put_var_next (bp, BIFF_CF);
@@ -1291,25 +1292,38 @@ cb_write_condition (GnmStyleConditions const *sc, CondDetails *cd,
                if (gnm_style_is_element_set (s, MSTYLE_BORDER_LEFT) ||
                    gnm_style_is_element_set (s, MSTYLE_BORDER_RIGHT) ||
                    gnm_style_is_element_set (s, MSTYLE_BORDER_TOP) ||
-                   gnm_style_is_element_set (s, MSTYLE_BORDER_BOTTOM)) {
-                       guint16 p = 0;
-                       guint32 c = 0;
-                       if (write_border (esheet, s, MSTYLE_BORDER_LEFT,   &p, &c,  0,  0))
+                   gnm_style_is_element_set (s, MSTYLE_BORDER_BOTTOM) ||
+                   gnm_style_is_element_set (s, MSTYLE_BORDER_DIAGONAL) ||
+                   gnm_style_is_element_set (s, MSTYLE_BORDER_REV_DIAGONAL)) {
+                       guint32 d[2] = { 0, 0 };
+                       if (write_border (esheet, s, MSTYLE_BORDER_LEFT,         d,  0, 16))
                                flags |= 0x0400;
-                       if (write_border (esheet, s, MSTYLE_BORDER_RIGHT,  &p, &c,  4,  7))
+                       if (write_border (esheet, s, MSTYLE_BORDER_RIGHT,        d,  4, 23))
                                flags |= 0x0800;
-                       if (write_border (esheet, s, MSTYLE_BORDER_TOP,    &p, &c,  8, 16))
+                       if (write_border (esheet, s, MSTYLE_BORDER_TOP,          d,  8, 32))
                                flags |= 0x1000;
-                       if (write_border (esheet, s, MSTYLE_BORDER_BOTTOM, &p, &c, 12, 23))
+                       if (write_border (esheet, s, MSTYLE_BORDER_BOTTOM,       d, 12, 39))
                                flags |= 0x2000;
 
-                       GSF_LE_SET_GUINT16 (buf+0, p);
-                       GSF_LE_SET_GUINT32 (buf+2, c);
-                       GSF_LE_SET_GUINT16 (buf+6, 0);
+                       /*
+                        * MS-XLS defines fields for diagonals, but Excel does not seem to
+                        * read them, not does the GUI allows creating them.
+                        */
+                       if (write_border (esheet, s, MSTYLE_BORDER_DIAGONAL,     d, 53, 46))
+                               flags |= 0x4000;
+                       else
+                               d[0] |= 0x80000000;
+                       if (write_border (esheet, s, MSTYLE_BORDER_REV_DIAGONAL, d, 53, 46))
+                               flags |= 0x8000;
+                       else
+                               d[0] |= 0x40000000;
+
+                       GSF_LE_SET_GUINT32 (buf+0, d[0]);
+                       GSF_LE_SET_GUINT32 (buf+4, d[1]);
                        ms_biff_put_var_write (bp, buf, 8);
                        flags |= 0x10000000;
                } else
-                       flags |= 0x3C00;
+                       flags |= 0xFC00;
 
                if (gnm_style_is_element_set (s, MSTYLE_PATTERN) ||
                    gnm_style_is_element_set (s, MSTYLE_COLOR_BACK) ||
@@ -2098,7 +2112,7 @@ put_colors (ExcelStyleVariant const *esv, gpointer dummy, XLExportBase *ewb)
 
        /* Borders */
        for (i = STYLE_TOP; i < STYLE_ORIENT_MAX; i++) {
-               b = gnm_style_get_border (st, MSTYLE_BORDER_TOP + i);
+               GnmBorder const *b = gnm_style_get_border (st, MSTYLE_BORDER_TOP + i);
                if (b && b->color)
                        put_color_gnm (ewb, b->color);
        }
diff --git a/samples/cond-format-tests.gnumeric b/samples/cond-format-tests.gnumeric
index 6510b1b..cd9a0db 100644
Binary files a/samples/cond-format-tests.gnumeric and b/samples/cond-format-tests.gnumeric differ


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]