1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * sc.c - file import of SC/xspread files
4 * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>
5 * Copyright (C) 2010 Andreas J. Guelzow <aguelzow@pyrshep.ca> All Rights Reserved
7 * With some code from sylk.c
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) version 3.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
24 #include <gnumeric-config.h>
25 #include <glib/gi18n-lib.h>
28 #include <goffice/goffice.h>
29 #include <gnm-plugin.h>
30 #include "sheet-style.h"
31 #include "workbook-view.h"
33 #include "parse-util.h"
40 #include "expr-name.h"
42 #include "sheet-view.h"
43 #include "selection.h"
44 #include "rendered-value.h"
45 #include "gnm-style-impl.h"
47 #include <gsf/gsf-input.h>
48 #include <gsf/gsf-input-textline.h>
53 GNM_PLUGIN_MODULE_HEADER
;
55 gboolean
sc_file_probe (GOFileOpener
const *fo
, GsfInput
*input
,
57 void sc_file_open (GOFileOpener
const *fo
, GOIOContext
*io_context
,
58 WorkbookView
*wb_view
, GsfInput
*input
);
61 GsfInputTextline
*textline
;
64 GnmConventions
*convs
;
65 GOIOContext
*context
; /* The IOcontext managing things */
78 static GOErrorInfo
*sc_go_error_info_new_vprintf (GOSeverity severity
,
79 char const *msg_format
, ...)
83 sc_go_error_info_new_vprintf (GOSeverity severity
,
84 char const *msg_format
, ...)
89 va_start (args
, msg_format
);
90 ei
= go_error_info_new_vprintf (severity
, msg_format
, args
);
96 static gboolean
sc_warning (ScParseState
*state
, char const *fmt
, ...)
100 sc_warning (ScParseState
*state
, char const *fmt
, ...)
106 va_start (args
, fmt
);
107 detail
= g_strdup_vprintf (fmt
, args
);
110 if (IS_SHEET (state
->sheet
))
111 msg
= g_strdup_printf (_("On worksheet %s:"),state
->sheet
->name_quoted
);
113 msg
= g_strdup (_("General SC import error"));
115 if (0 != go_str_compare (msg
, state
->last_error
)) {
116 GOErrorInfo
*ei
= sc_go_error_info_new_vprintf
117 (GO_WARNING
, "%s", msg
);
119 go_io_error_info_set (state
->context
, ei
);
120 g_free (state
->last_error
);
121 state
->last_error
= msg
;
125 go_error_info_add_details
126 (state
->context
->info
->data
,
127 sc_go_error_info_new_vprintf (GO_WARNING
, "%s", detail
));
131 return FALSE
; /* convenience */
135 enlarge (ScParseState
*state
, int col
, int row
)
137 GnmSheetSize
const *size
= gnm_sheet_get_size (state
->sheet
);
138 gboolean err
= FALSE
;
140 if (col
>= size
->max_cols
141 || row
>= size
->max_rows
) {
143 int cols_needed
= (col
>= size
->max_cols
) ? col
+ 1
145 int rows_needed
= (row
>= size
->max_rows
) ? row
+ 1
147 gnm_sheet_suggest_size (&cols_needed
, &rows_needed
);
149 goundo
= gnm_sheet_resize
150 (state
->sheet
, cols_needed
, rows_needed
, NULL
, &err
);
151 if (goundo
) g_object_unref (goundo
);
159 sc_sheet_cell_fetch (ScParseState
*state
, int col
, int row
)
161 gboolean err
= enlarge (state
, col
, row
);
164 sc_warning (state
, _("The cell in row %i and column %i is beyond "
165 "Gnumeric's maximum sheet size."),
170 return sheet_cell_fetch (state
->sheet
, col
, row
);
174 sc_colname_to_coords (char const *colname
, gint
*m
)
179 g_return_val_if_fail (colname
, 0);
181 if (!colname
|| !*colname
|| !g_ascii_isalpha (*colname
))
184 mult
= g_ascii_toupper (*colname
) - 'A';
185 if (mult
< 0 || mult
> 25)
190 if (g_ascii_isalpha (*colname
)) {
191 int ofs
= g_ascii_toupper (*colname
) - 'A';
192 if (ofs
< 0 || ofs
> 25)
194 mult
= ((mult
+ 1) * 26) + ofs
;
204 /* we can't use cellpos_parse b/c it doesn't support 0 bases (A0, B0, ...) */
206 sc_cellname_to_coords (char const *cellname
, GnmCellPos
*pos
)
210 g_return_val_if_fail (cellname
, FALSE
);
212 digits
= sc_colname_to_coords (cellname
, &mult
);
219 /* XXX need to replace this block with strtol+error checking */
221 if (!g_ascii_isdigit (*cellname
))
224 pos
->row
= atoi (cellname
);
227 g_return_val_if_fail (pos
->col
> -1, FALSE
);
228 g_return_val_if_fail (pos
->row
> -1, FALSE
);
232 pos
->col
= pos
->row
= -1;
239 sc_parse_coord_real (ScParseState
*state
, char const *strdata
, GnmCellPos
*pos
,
247 g_return_val_if_fail (strdata
, FALSE
);
249 tmpstr
= g_strndup (strdata
, tmplen
);
251 /* It ought to be a cellref. */
252 if (sc_cellname_to_coords (tmpstr
, pos
)) {
253 g_return_val_if_fail (pos
->col
>= 0, FALSE
);
254 g_return_val_if_fail (pos
->row
>= 0, FALSE
);
259 /* But it could be a named expression of the same kind. */
261 parse_pos_init (&pp
, NULL
, state
->sheet
, 0, 0);
262 nexpr
= expr_name_lookup (&pp
, tmpstr
);
263 if (nexpr
&& (v
= gnm_expr_top_get_range (nexpr
->texpr
))) {
264 if (VALUE_IS_CELLRANGE (v
)) {
266 const GnmCellRef
*cr
= &v
->v_range
.cell
.a
;
268 eval_pos_init_sheet (&ep
, state
->sheet
);
269 pos
->col
= gnm_cellref_get_col (cr
, &ep
);
270 pos
->row
= gnm_cellref_get_row (cr
, &ep
);
283 sc_parse_coord (ScParseState
*state
, char const **strdata
, GnmCellPos
*pos
)
288 g_return_val_if_fail (strdata
, FALSE
);
289 g_return_val_if_fail (*strdata
, FALSE
);
293 eq
= strstr (s
, " = ");
297 res
= sc_parse_coord_real (state
, s
, pos
, eq
- s
);
300 if ((eq
- s
+ 1 + 3) > (int) strlen (s
))
309 set_h_align (Sheet
*sheet
, GnmCellPos
const *pos
, GnmHAlign ha
)
312 GnmStyle
*style
= gnm_style_new ();
313 gnm_style_set_align_h (style
, ha
);
314 r
.start
= r
.end
= *pos
;
315 sheet_style_apply_range (sheet
, &r
, style
);
319 sc_parse_set_handle_option (ScParseState
*state
, char const *option
)
321 if (g_str_has_prefix (option
, "iterations=")) {
322 int it
= atoi (option
+ 11);
324 workbook_iteration_enabled (state
->sheet
->workbook
, TRUE
);
325 workbook_iteration_max_number (state
->sheet
->workbook
, it
);
327 } else if (g_str_has_prefix (option
, "autocalc"))
328 workbook_set_recalcmode (state
->sheet
->workbook
, TRUE
);
329 else if (g_str_has_prefix (option
, "!autocalc"))
330 workbook_set_recalcmode (state
->sheet
->workbook
, FALSE
);
334 sc_parse_set (ScParseState
*state
, char const *cmd
, char const *str
,
335 GnmCellPos
const *cpos
)
337 gchar
** options
= g_strsplit (str
, " ", -1), **tmp
;
340 for (tmp
= options
; *tmp
!= NULL
; tmp
++)
341 sc_parse_set_handle_option (state
, *tmp
);
344 /* Most of these settings are not applicable to Gnumeric */
349 sc_parse_goto (ScParseState
*state
, char const *cmd
, char const *str
,
350 GnmCellPos
const *cpos
)
352 GnmCellPos pos
= { -1, -1 };
355 res
= sc_parse_coord_real (state
, str
, &pos
, strlen (str
));
359 SHEET_FOREACH_VIEW(state
->sheet
, sv
,
361 (sv
, &pos
, pos
.col
, pos
.row
, pos
.col
, pos
.row
););
367 sc_parse_format_definition (ScParseState
*state
, char const *cmd
, char const *str
)
369 sc_warning (state
, "Ignoring column format definition: %s", str
);
374 sc_parse_format_set_width (ScParseState
*state
, int len
, int col_from
, int col_to
)
385 err
= enlarge (state
, col_to
, 0);
387 sc_warning (state
, _("The sheet is wider than "
388 "Gnumeric can handle."));
392 mstyle
= gnm_style_new_default ();
393 style_font
= gnm_style_get_font
394 (mstyle
, state
->sheet
->rendered_values
->context
);
395 width
= PANGO_PIXELS (len
* style_font
->go
.metrics
->avg_digit_width
) + 4;
396 gnm_style_unref (mstyle
);
398 for (col
= col_from
; col
<= col_to
; col
++)
399 sheet_col_set_size_pixels (state
->sheet
, col
, width
, TRUE
);
403 sc_parse_format_free_precision (ScParseState
*state
)
405 if (state
->precision
!= NULL
)
406 g_array_free (state
->precision
, TRUE
);
410 sc_parse_format_get_precision (ScParseState
*state
, int col
)
412 if (state
->precision
!= NULL
&&
413 col
< (int)state
->precision
->len
) {
414 return (g_array_index(state
->precision
, int, col
) - 1 );
419 sc_parse_format_save_precision (ScParseState
*state
, int precision
,
420 int col_from
, int col_to
)
424 if (state
->precision
== NULL
)
425 state
->precision
= g_array_new (FALSE
, TRUE
, sizeof (int));
427 if (!(col_to
< (int)state
->precision
->len
))
428 state
->precision
= g_array_set_size (state
->precision
, col_to
+ 1);
430 for (col
= col_from
; col
<= col_to
; col
++)
431 g_array_index(state
->precision
, int, col
) = precision
+ 1;
435 sc_parse_format_apply_precision (ScParseState
*state
, char *format
, int col
)
437 if (strchr (format
, '&')) {
438 GString
* str
= g_string_new (format
);
439 char *amp
= str
->str
;
443 while (NULL
!= (amp
= strchr (str
->str
+ off
, '&'))) {
444 off
= amp
- str
->str
+ 1;
445 if (amp
== str
->str
|| *(amp
- 1) != '\\') {
446 int p
= sc_parse_format_get_precision (state
, col
);
450 sc_warning (state
, _("Encountered precision dependent format without set precision."));
453 g_string_erase (str
, off
, 1);
454 for (i
= 0; i
< p
; i
++)
455 g_string_insert_c (str
, off
, '0');
459 format
= g_string_free (str
, FALSE
);
465 sc_parse_format_set_type (ScParseState
*state
, int type
, int col_from
, int col_to
)
467 char const *o_format
= type
>= 0 && (size_t)type
< state
->formats
->len
468 ? g_ptr_array_index(state
->formats
, type
)
472 if (o_format
== NULL
) {
473 sc_warning (state
, _("Column format %i is undefined."), type
);
476 for (col
= col_from
; col
<= col_to
; col
++) {
477 char *fmt
= g_strdup (o_format
);
481 range_init_cols (&range
, state
->sheet
, col
, col
);
482 fmt
= sc_parse_format_apply_precision (state
, fmt
, col
);
483 gfmt
= go_format_new_from_XL (fmt
);
484 style
= gnm_style_new_default ();
485 gnm_style_set_format (style
, gfmt
);
486 sheet_style_apply_range (state
->sheet
, &range
, style
);
487 /* gnm_style_unref (style); reference has been absorbed */
488 go_format_unref (gfmt
);
495 sc_parse_format (ScParseState
*state
, char const *cmd
, char const *str
,
496 GnmCellPos
const *cpos
)
499 int col_from
= -1, col_to
= -1, d
;
500 int len
= 0, precision
= 0, format_type
= 0;
502 if (g_ascii_isdigit ((gchar
) *str
))
503 return sc_parse_format_definition (state
, cmd
, str
);
505 d
= sc_colname_to_coords (s
, &col_from
);
513 d
= sc_colname_to_coords (s
, &col_to
);
522 d
= sscanf(s
, "%i %i %i", &len
, &precision
, &format_type
);
528 sc_parse_format_set_width (state
, len
, col_from
, col_to
);
529 sc_parse_format_save_precision (state
, precision
, col_from
, col_to
);
530 sc_parse_format_set_type (state
, format_type
, col_from
, col_to
);
534 sc_warning (state
, "Unable to parse: %s %s", cmd
, str
);
539 sc_parse_fmt (ScParseState
*state
, char const *cmd
, char const *str
,
540 GnmCellPos
const *cpos
)
542 char const *s
= str
, *space
;
547 GnmCellPos pos
= { -1, -1 };
549 space
= strstr (s
, "\"");
554 res
= sc_parse_coord_real (state
, s
, &pos
, space
- s
);
558 space
= strstr (s
, "\"");
561 fmt
= g_strndup (s
, space
- s
);
562 fmt
= sc_parse_format_apply_precision (state
, fmt
, pos
.col
);
563 gfmt
= go_format_new_from_XL (fmt
);
564 style
= gnm_style_new_default ();
565 gnm_style_set_format (style
, gfmt
);
567 sheet_style_apply_pos (state
->sheet
, pos
.col
, pos
.row
, style
);
568 /* gnm_style_unref (style); reference has been absorbed */
569 go_format_unref (gfmt
);
576 sc_parse_label (ScParseState
*state
, char const *cmd
, char const *str
,
577 GnmCellPos
const *pos
)
580 char *s
= NULL
, *tmpout
;
582 gboolean result
= FALSE
;
584 g_return_val_if_fail (str
, FALSE
);
586 if (*str
!= '"' || str
[1] == 0)
589 s
= tmpout
= g_strdup (str
);
593 tmpstr
= str
+ 1; /* skip leading " */
595 if (*tmpstr
!= '\\') {
601 if (*(tmpstr
- 1) != '"')
606 cell
= sc_sheet_cell_fetch (state
, pos
->col
, pos
->row
);
610 gnm_cell_set_text (cell
, s
);
612 if (strcmp (cmd
, "leftstring") == 0)
613 set_h_align (state
->sheet
, pos
, GNM_HALIGN_LEFT
);
614 else if (strcmp (cmd
, "rightstring") == 0)
615 set_h_align (state
->sheet
, pos
, GNM_HALIGN_RIGHT
);
632 sc_parse_cell_name_list (ScParseState
*state
, char const *cell_name_str
,
636 GSList
*cells
= NULL
;
641 g_return_val_if_fail (state
->sheet
!= NULL
, NULL
);
642 g_return_val_if_fail (IS_SHEET (state
->sheet
), NULL
);
643 g_return_val_if_fail (cell_name_str
!= NULL
, NULL
);
644 g_return_val_if_fail (error_flag
!= NULL
, NULL
);
646 buf
= g_malloc (strlen (cell_name_str
) + 1);
647 for (i
= n
= 0; cell_name_str
[i
]; i
++) {
649 if ((cell_name_str
[i
] == ',') ||
650 (!cell_name_str
[i
])){
653 if (!cellpos_parse (buf
, &pos
)){
656 g_slist_free (cells
);
660 cell
= sc_sheet_cell_fetch (state
, pos
.col
, pos
.row
);
662 cells
= g_slist_append (cells
, (gpointer
) cell
);
665 buf
[n
++] = cell_name_str
[i
];
676 sc_row_parse (char const *str
, Sheet
*sheet
, int *res
, unsigned char *relative
)
678 char const *end
, *ptr
= str
;
681 if (!(*relative
= (*ptr
!= '$')))
684 if (*ptr
< '0' || *ptr
> '9')
688 * Do not allow letters after the row number. If we did, then
689 * the name "K3P" would lex as the reference K3 followed by the
692 row
= strtol (ptr
, (char **)&end
, 10);
694 !g_unichar_isalnum (g_utf8_get_char (end
)) && *end
!= '_' &&
695 0 <= row
&& row
< gnm_sheet_get_max_rows (sheet
)) {
704 sc_rangeref_parse (GnmRangeRef
*res
, char const *start
, GnmParsePos
const *pp
,
705 G_GNUC_UNUSED GnmConventions
const *convs
)
707 char const *ptr
= start
, *tmp1
, *tmp2
;
708 GnmSheetSize
const *ss
;
710 g_return_val_if_fail (start
!= NULL
, start
);
711 g_return_val_if_fail (pp
!= NULL
, start
);
713 ss
= gnm_sheet_get_size (pp
->sheet
);
716 tmp1
= col_parse (ptr
, ss
, &res
->a
.col
, &res
->a
.col_relative
);
719 tmp2
= sc_row_parse (tmp1
, pp
->sheet
, &res
->a
.row
, &res
->a
.row_relative
);
722 if (res
->a
.col_relative
)
723 res
->a
.col
-= pp
->eval
.col
;
724 if (res
->a
.row_relative
)
725 res
->a
.row
-= pp
->eval
.row
;
727 /* prepare as if it's a singleton, in case we want to fall back */
733 tmp1
= col_parse (start
+1, ss
, &res
->b
.col
, &res
->b
.col_relative
);
736 tmp2
= sc_row_parse (tmp1
, pp
->sheet
, &res
->b
.row
, &res
->b
.row_relative
);
739 if (res
->b
.col_relative
)
740 res
->b
.col
-= pp
->eval
.col
;
741 if (res
->b
.row_relative
)
742 res
->b
.row
-= pp
->eval
.row
;
746 static GnmExprTop
const *
747 sc_parse_expr (ScParseState
*state
, const char *str
, GnmParsePos
*pp
)
749 GnmExprTop
const *texpr
;
751 gboolean infunc
= FALSE
;
754 exprstr
= g_string_sized_new (500);
755 for (p1
= str
; *p1
; p1
++) {
758 infunc
= g_ascii_isalpha (c
);
759 if (!infunc
&& *p1
!= '(')
760 g_string_append_len (exprstr
, "()", 2);
761 g_string_append_c (exprstr
, c
);
762 } else if (*p1
== '@')
765 g_string_append_c (exprstr
, c
);
768 g_string_append_len (exprstr
, "()", 2);
770 texpr
= gnm_expr_parse_str (exprstr
->str
, pp
,
771 GNM_EXPR_PARSE_DEFAULT
,
773 g_string_free (exprstr
, TRUE
);
780 sc_parse_let (ScParseState
*state
, char const *cmd
, char const *str
,
781 GnmCellPos
const *pos
)
783 GnmExprTop
const *texpr
;
788 g_return_val_if_fail (cmd
, FALSE
);
789 g_return_val_if_fail (str
, FALSE
);
791 cell
= sc_sheet_cell_fetch (state
, pos
->col
, pos
->row
);
795 texpr
= sc_parse_expr (state
, str
,
796 parse_pos_init_cell (&pp
, cell
));
799 sc_warning (state
, _("Unable to parse cmd='%s', str='%s', col=%d, row=%d."),
800 cmd
, str
, pos
->col
, pos
->row
);
804 v
= gnm_expr_top_get_constant (texpr
);
805 if (v
&& VALUE_IS_NUMBER (v
)) {
806 gnm_cell_set_value (cell
, value_dup (v
));
808 gnm_cell_set_expr (cell
, texpr
);
809 cell_queue_recalc (cell
);
812 if (texpr
) gnm_expr_top_unref (texpr
);
817 sc_parse_define (ScParseState
*state
, char const *cmd
, char const *str
,
818 GnmCellPos
const *dummy_pos
)
821 GString
*name
= g_string_new (NULL
);
824 gboolean res
= FALSE
;
825 GnmExprTop
const *texpr
;
827 str
= go_strunescape (name
, str
);
830 while (g_ascii_isspace (*str
))
832 texpr
= sc_parse_expr (state
, str
,
833 parse_pos_init (&pp
, NULL
, state
->sheet
, 0, 0));
835 sc_warning (state
, "Unable to parse cmd='%s', str='%s'.", cmd
, str
);
839 nexpr
= expr_name_add (&pp
, name
->str
, texpr
, &errstr
, TRUE
, NULL
);
846 g_string_free (name
, TRUE
);
854 gboolean (*handler
) (ScParseState
*state
, char const *name
,
855 char const *str
, GnmCellPos
const *pos
);
859 static sc_cmd_t
const sc_cmd_list
[] = {
860 { "leftstring", 10, sc_parse_label
, TRUE
},
861 { "rightstring", 11, sc_parse_label
, TRUE
},
862 { "label", 5, sc_parse_label
, TRUE
},
863 { "let", 3, sc_parse_let
, TRUE
},
864 { "define", 6, sc_parse_define
, FALSE
},
865 { "fmt", 3, sc_parse_fmt
, FALSE
},
866 { "format", 6, sc_parse_format
, FALSE
},
867 { "set", 3, sc_parse_set
, FALSE
},
868 { "goto", 4, sc_parse_goto
, FALSE
},
869 { NULL
, 0, NULL
, 0 },
874 sc_parse_line (ScParseState
*state
, char *buf
)
880 g_return_val_if_fail (state
, FALSE
);
881 g_return_val_if_fail (state
->sheet
, FALSE
);
882 g_return_val_if_fail (buf
, FALSE
);
884 for (space
= buf
; g_ascii_isalnum (*space
) || *space
== '_'; space
++)
888 cmdlen
= space
- buf
;
889 while (*space
== ' ')
892 for (i
= 0 ; sc_cmd_list
[i
].name
!= NULL
; ++i
) {
893 cmd
= &sc_cmd_list
[i
];
894 if (cmd
->namelen
== cmdlen
&&
895 strncmp (cmd
->name
, buf
, cmdlen
) == 0) {
896 GnmCellPos pos
= { -1, -1 };
897 char const *strdata
= space
;
899 if (cmd
->have_coord
) {
900 if (!sc_parse_coord (state
, &strdata
, &pos
)) {
901 sc_warning (state
, "Cannot parse %s\n",
907 cmd
->handler (state
, cmd
->name
, strdata
, &pos
);
912 sc_warning (state
, "Unhandled directive: '%-.*s'",
919 sc_parse_sheet (ScParseState
*state
)
922 GOErrorInfo
*res
= NULL
;
924 while ((data
= gsf_input_textline_ascii_gets (state
->textline
)) != NULL
) {
928 utf8data
= g_convert_with_iconv (data
, -1, state
->converter
,
931 if (g_ascii_isalpha (*data
) && !sc_parse_line (state
, utf8data
)) {
933 res
= go_error_info_new_str
934 (_("Error parsing line"));
943 static GnmExpr
const *
944 sc_func_map_in (GnmConventions
const *conv
, Workbook
*scope
,
945 char const *name
, GnmExprList
*args
)
949 char const *gnm_name
;
950 } const sc_func_renames
[] = {
951 { "AVG", "AVERAGE" },
952 { "DTR", "RADIANS" },
954 { "COLS", "COLUMNS" },
955 { "AVG", "AVERAGE" },
957 { "PROD", "PRODUCT" },
959 { "RTD", "DEGREES" },
960 { "STDDEV", "STDEV" },
965 static GHashTable
*namemap
= NULL
;
968 char const *new_name
;
971 if (NULL
== namemap
) {
972 namemap
= g_hash_table_new (go_ascii_strcase_hash
,
973 go_ascii_strcase_equal
);
974 for (i
= 0; sc_func_renames
[i
].sc_name
; i
++)
975 g_hash_table_insert (namemap
,
976 (gchar
*) sc_func_renames
[i
].sc_name
,
977 (gchar
*) sc_func_renames
[i
].gnm_name
);
980 if (NULL
!= namemap
&&
981 NULL
!= (new_name
= g_hash_table_lookup (namemap
, name
)))
983 if (NULL
== (f
= gnm_func_lookup (name
, scope
)))
984 f
= gnm_func_add_placeholder (scope
, name
, "");
985 return gnm_expr_new_funcall (f
, args
);
988 static GnmConventions
*
989 sc_conventions (void)
991 GnmConventions
*conv
= gnm_conventions_new ();
993 conv
->decimal_sep_dot
= TRUE
;
994 conv
->range_sep_colon
= TRUE
;
995 conv
->input
.range_ref
= sc_rangeref_parse
;
996 conv
->input
.func
= sc_func_map_in
;
1002 sc_format_free (gpointer data
, gpointer user_data
)
1008 sc_file_open (GOFileOpener
const *fo
, GOIOContext
*io_context
,
1009 WorkbookView
*wb_view
, GsfInput
*input
)
1016 wb
= wb_view_get_workbook (wb_view
);
1017 name
= workbook_sheet_get_free_name (wb
, "SC", FALSE
, TRUE
);
1018 state
.sheet
= sheet_new (wb
, name
, 256, 65536);
1020 workbook_sheet_attach (wb
, state
.sheet
);
1022 /* This should probably come from import dialog. */
1023 state
.converter
= g_iconv_open ("UTF-8", "ISO-8859-1");
1025 state
.convs
= sc_conventions ();
1026 state
.context
= io_context
;
1027 state
.last_error
= NULL
;
1028 state
.precision
= NULL
;
1029 state
.formats
= g_ptr_array_sized_new (10);
1030 g_ptr_array_add (state
.formats
, g_strdup ("#.&")); /* 0 */
1031 g_ptr_array_add (state
.formats
, g_strdup ("0.&E+00")); /* 1 */
1032 g_ptr_array_add (state
.formats
, g_strdup ("##0.&E+00")); /* 2 */
1033 g_ptr_array_add (state
.formats
, g_strdup ("[$-f8f2]m/d/yy")); /* 3 */
1034 g_ptr_array_add (state
.formats
, g_strdup ("[$-f800]dddd, mmmm dd, yyyy")); /* 4 */
1035 g_ptr_array_set_size (state
.formats
, 10);
1037 state
.textline
= (GsfInputTextline
*) gsf_input_textline_new (input
);
1038 error
= sc_parse_sheet (&state
);
1039 if (error
!= NULL
) {
1040 workbook_sheet_delete (state
.sheet
);
1041 go_io_error_info_set (io_context
, error
);
1043 g_object_unref (state
.textline
);
1044 g_iconv_close (state
.converter
);
1045 gnm_conventions_unref (state
.convs
);
1046 g_free (state
.last_error
);
1047 sc_parse_format_free_precision (&state
);
1049 /*In glib 2.22 or later we could use g_ptr_array_set_free_func */
1050 g_ptr_array_foreach (state
.formats
, (GFunc
) sc_format_free
, NULL
);
1051 g_ptr_array_unref (state
.formats
);
1055 static guint8
const signature
[] =
1056 "# This data file was generated by the Spreadsheet Calculator.";
1059 sc_file_probe (GOFileOpener
const *fo
, GsfInput
*input
,
1060 GOFileProbeLevel pl
)
1062 char const *header
= NULL
;
1064 if (!gsf_input_seek (input
, 0, G_SEEK_SET
))
1065 header
= gsf_input_read (input
, sizeof (signature
)-1, NULL
);
1066 return header
!= NULL
&&
1067 memcmp (header
, signature
, sizeof (signature
)-1) == 0;
1072 * http://www.thule.no/haynie/cpumods/a2620/docs/commrc.sc.txt:
1075 * http://www.mcs.kent.edu/system/documentation/xspread/demo_func