X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fdata%2Fgnumeric-reader.c;h=69dd23689fc6b979d54540c23ae65511b46a885f;hb=8f5194875a0a3d41fef91825fd8378bb004d6f51;hp=c083721f39ebc498ac909f8556489f58eb814236;hpb=69d9ffe0d82f468b541d04508999eced384fef10;p=pspp diff --git a/src/data/gnumeric-reader.c b/src/data/gnumeric-reader.c index c083721f39..69dd23689f 100644 --- a/src/data/gnumeric-reader.c +++ b/src/data/gnumeric-reader.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 2007, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -81,18 +81,34 @@ enum reader_state STATE_SHEET_START, /* Found the start of a sheet */ STATE_SHEET_NAME, /* Found the sheet name */ STATE_MAXROW, + STATE_MAXCOL, STATE_SHEET_FOUND, /* Found the sheet that we actually want */ STATE_CELLS_START, /* Found the start of the cell array */ STATE_CELL /* Found a cell */ }; +struct sheet_detail +{ + xmlChar *name; + + int start_col; + int stop_col; + int start_row; + int stop_row; + + int maxcol; + int maxrow; +}; + struct gnumeric_reader { struct spreadsheet spreadsheet; + /* The libxml reader for this instance */ xmlTextReaderPtr xtr; + /* An internal state variable */ enum reader_state state; int row; @@ -100,17 +116,17 @@ struct gnumeric_reader int min_col; int node_type; int sheet_index; + + int start_col; + int stop_col; + int start_row; + int stop_row; - xmlChar **sheet_names; + struct sheet_detail *sheets; const xmlChar *target_sheet; int target_sheet_index; - int start_row; - int start_col; - int stop_row; - int stop_col; - struct caseproto *proto; struct dictionary *dict; struct ccase *first_case; @@ -124,20 +140,37 @@ gnumeric_get_sheet_name (struct spreadsheet *s, int n) struct gnumeric_reader *gr = (struct gnumeric_reader *) s; assert (n < s->sheets); - return gr->sheet_names[n]; + return gr->sheets[n].name; } -const char * + +static void process_node (struct gnumeric_reader *r); + + +char * gnumeric_get_sheet_range (struct spreadsheet *s, int n) { + int ret; struct gnumeric_reader *gr = (struct gnumeric_reader *) s; + assert (n < s->sheets); - return "I havent the fogiest idea"; -} + while ( + (gr->sheets[n].stop_col == -1) + && + (1 == (ret = xmlTextReaderRead (gr->xtr))) + ) + { + process_node (gr); + } -static void process_node (struct gnumeric_reader *r); + return create_cell_ref ( + gr->sheets[n].start_col, + gr->sheets[n].start_row, + gr->sheets[n].stop_col, + gr->sheets[n].stop_row); +} static void @@ -158,10 +191,10 @@ gnm_file_casereader_destroy (struct casereader *reader UNUSED, void *r_) for (i = 0; i < r->spreadsheet.sheets; ++i) { - xmlFree (r->sheet_names[i]); + xmlFree (r->sheets[i].name); } - free (r->sheet_names); + free (r->sheets); free (r); } @@ -179,6 +212,7 @@ process_node (struct gnumeric_reader *r) switch ( r->state) { case STATE_PRE_INIT: + r->sheet_index = -1; if (0 == xmlStrcasecmp (name, _xml("gnm:SheetNameIndex")) && XML_READER_TYPE_ELEMENT == r->node_type) { @@ -191,8 +225,11 @@ process_node (struct gnumeric_reader *r) if (0 == xmlStrcasecmp (name, _xml("gnm:SheetName")) && XML_READER_TYPE_ELEMENT == r->node_type) { + struct sheet_detail *sd ; r->spreadsheet.sheets++; - r->sheet_names = xrealloc (r->sheet_names, r->spreadsheet.sheets * sizeof *r->sheet_names); + r->sheets = xrealloc (r->sheets, r->spreadsheet.sheets * sizeof *r->sheets); + sd = &r->sheets[r->spreadsheet.sheets - 1]; + sd->start_col = sd->stop_col = sd->start_row = sd->stop_row = -1; } else if (0 == xmlStrcasecmp (name, _xml("gnm:SheetNameIndex")) && XML_READER_TYPE_END_ELEMENT == r->node_type) @@ -201,7 +238,7 @@ process_node (struct gnumeric_reader *r) } else if (XML_READER_TYPE_TEXT == r->node_type) { - r->sheet_names [r->spreadsheet.sheets - 1] = xmlTextReaderValue (r->xtr); + r->sheets [r->spreadsheet.sheets - 1].name = xmlTextReaderValue (r->xtr); } break; @@ -226,16 +263,25 @@ process_node (struct gnumeric_reader *r) { r->state = STATE_INIT; } + else if (0 == xmlStrcasecmp (name, _xml("gnm:Sheet")) && + XML_READER_TYPE_END_ELEMENT == r->node_type) + { + r->state = STATE_INIT; + } else if (XML_READER_TYPE_TEXT == r->node_type) { - if ( r->target_sheet != NULL) + if ( r->target_sheet != NULL) { xmlChar *value = xmlTextReaderValue (r->xtr); if ( 0 == xmlStrcmp (value, r->target_sheet)) r->state = STATE_SHEET_FOUND; free (value); } - else if (r->target_sheet_index == r->sheet_index) + else if (r->target_sheet_index == r->sheet_index + 1) + { + r->state = STATE_SHEET_FOUND; + } + else if (r->target_sheet_index == -1) { r->state = STATE_SHEET_FOUND; } @@ -254,10 +300,15 @@ process_node (struct gnumeric_reader *r) { r->state = STATE_MAXROW; } + else if (0 == xmlStrcasecmp (name, _xml("gnm:MaxCol")) && + XML_READER_TYPE_ELEMENT == r->node_type) + { + r->state = STATE_MAXCOL; + } else if (0 == xmlStrcasecmp (name, _xml("gnm:Sheet")) && XML_READER_TYPE_END_ELEMENT == r->node_type) { - r->state = STATE_INIT; + r->state = STATE_INIT; } break; case STATE_MAXROW: @@ -266,6 +317,26 @@ process_node (struct gnumeric_reader *r) { r->state = STATE_SHEET_FOUND; } + else if (r->node_type == XML_READER_TYPE_TEXT) + { + xmlChar *value = xmlTextReaderValue (r->xtr); + r->sheets[r->sheet_index].maxrow = _xmlchar_to_int (value); + xmlFree (value); + } + break; + case STATE_MAXCOL: + if (0 == xmlStrcasecmp (name, _xml("gnm:MaxCol")) && + XML_READER_TYPE_END_ELEMENT == r->node_type) + { + r->state = STATE_SHEET_FOUND; + } + else if (r->node_type == XML_READER_TYPE_TEXT) + { + xmlChar *value = xmlTextReaderValue (r->xtr); + r->sheets[r->sheet_index].maxcol = _xmlchar_to_int (value); + xmlFree (value); + } + break; case STATE_CELLS_START: if (0 == xmlStrcasecmp (name, _xml ("gnm:Cell")) && XML_READER_TYPE_ELEMENT == r->node_type) @@ -283,11 +354,23 @@ process_node (struct gnumeric_reader *r) attr = xmlTextReaderGetAttribute (r->xtr, _xml ("Row")); r->row = _xmlchar_to_int (attr); free (attr); + if (r->sheets[r->sheet_index].start_row == -1) + { + r->sheets[r->sheet_index].start_row = r->row; + } + + if (r->sheets[r->sheet_index].start_col == -1) + { + r->sheets[r->sheet_index].start_col = r->col; + } } else if (0 == xmlStrcasecmp (name, _xml("gnm:Cells")) && XML_READER_TYPE_END_ELEMENT == r->node_type) - r->state = STATE_SHEET_NAME; - + { + r->sheets[r->sheet_index].stop_col = r->col; + r->sheets[r->sheet_index].stop_row = r->row; + r->state = STATE_SHEET_NAME; + } break; case STATE_CELL: if (0 == xmlStrcasecmp (name, _xml("gnm:Cell")) && @@ -340,18 +423,28 @@ struct var_spec void gnumeric_destroy (struct spreadsheet *s) { - struct gnumeric_reader *r = s; - gnm_file_casereader_destroy (NULL, s); + struct gnumeric_reader *r = (struct gnumeric *) s; + gnm_file_casereader_destroy (NULL, s); } -struct spreadsheet * -gnumeric_probe (const char *filename) -{ + +static struct gnumeric_reader * +gnumeric_reopen (struct gnumeric_reader *r, const char *filename) +{ int ret; - struct gnumeric_reader *r = NULL; + xmlTextReaderPtr xtr; + gzFile gz; - gzFile gz = gzopen (filename, "r"); + assert (r == NULL || filename == NULL); + + if (r && r->xtr) + xmlFreeTextReader (r->xtr); + + if (filename) + gz = gzopen (filename, "r"); + else + gz = gzopen ( r->spreadsheet.file_name, "r"); if (NULL == gz) return NULL; @@ -361,14 +454,24 @@ gnumeric_probe (const char *filename) NULL, NULL, 0); if (xtr == NULL) - return NULL; + { + gzclose (gz); + return NULL; + } - r = xzalloc (sizeof *r); - - r->xtr = xtr; - r->spreadsheet.sheets = -1; - r->state = STATE_PRE_INIT; + if (r == NULL) + { + r = xzalloc (sizeof *r); + r->spreadsheet.sheets = -1; + r->spreadsheet.file_name = filename; + } + r->target_sheet = NULL; + r->target_sheet_index = -1; + + r->row = r->col = -1; + r->state = STATE_PRE_INIT; + r->xtr = xtr; /* Advance to the start of the workbook. This gives us some confidence that we are actually dealing with a gnumeric @@ -380,17 +483,17 @@ gnumeric_probe (const char *filename) process_node (r); } - if (ret != 1) - { - /* Not a gnumeric spreadsheet */ - free (r); - gzclose (gz); - return NULL; - } - r->spreadsheet.type = SPREADSHEET_GNUMERIC; - r->spreadsheet.file_name = filename; - + + return r; +} + + +struct spreadsheet * +gnumeric_probe (const char *filename) +{ + struct gnumeric_reader *r = gnumeric_reopen (NULL, filename); + return &r->spreadsheet; } @@ -410,6 +513,9 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, r = (struct gnumeric_reader *) (spreadsheet); + if (r->row != -1) + r = gnumeric_reopen (r, NULL); + if ( opts->cell_range ) { if ( ! convert_cell_ref (opts->cell_range, @@ -429,11 +535,10 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, r->stop_row = -1; } - r->target_sheet = BAD_CAST opts->sheet_name; r->target_sheet_index = opts->sheet_index; r->row = r->col = -1; - r->sheet_index = 0; + r->sheet_index = -1; /* Advance to the start of the cells for the target sheet */ while ( (r->state != STATE_CELL || r->row < r->start_row ) @@ -450,7 +555,6 @@ gnumeric_make_reader (struct spreadsheet *spreadsheet, free (value); } - /* If a range has been given, then use that to calculate the number of cases */ if ( opts->cell_range)