filein.c File Reference


Detailed Description

Read data from supported file formats.

Author:
Copyright 2006-2007 Neil Williams <linux@codehelp.co.uk>

Copyright 1999 Robert Lissner

Definition in file filein.c.

#include "config.h"
#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gtkextra/gtksheet.h>
#include <libgnomevfs/gnome-vfs.h>
#include "types.h"
#include "dialog_initial.h"
#include "dim_list_menu.h"
#include "filein.h"
#include "main.h"
#include "report.h"

Go to the source code of this file.

Defines

#define ENUM_BODY(name, value)   name value,
#define DEFINE_ENUM_NON_TYPEDEF(name, list)
#define FROM_STRING_DEC_NON_TYPEDEF(name, list)
#define FROM_STRING_CASE_NON_TYPEDEF(name, value)   if (strcmp(str, #name) == 0) { *type = name; }
#define FROM_STRING_FUNC_NON_TYPEDEF(name, list)
#define AS_STRING_DEC_NON_TYPEDEF(name, list)   const gchar* name##asString(enum name n);
#define AS_STRING_FUNC_NON_TYPEDEF(name, list)
#define AS_STRING_CASE_NON_TYPEDEF(name, value)   case name: { return #name; }
#define QL_ERRORS(_)
 Inherited error codes.

Functions

static void define_last_field (QlTabData *tab)
static void add1field (QlTabData *tab)
 Add 1 column to sheet.
static enum QlErrorVal read_comma_file (QlTabData *tab)
static enum QlErrorVal read_ql_file (QlTabData *tab)
static enum QlErrorVal read_tab_file (QlTabData *tab)
static void report_error (QlTabData *tab, enum QlErrorVal err_number)
void actually_open (const gchar *filename, QlDialogMode G_GNUC_UNUSED open_mode, QlFileType file_type, QlContext *qlc)
static gchar * check_last_path (QlContext *qlc)
static void any_open (QlDialogMode open_mode, QlFileType file_type, QlContext *qlc)
static void set_sheet_column_cb (gpointer G_GNUC_UNUSED field_index, gpointer field_ptr, gpointer user_data)
void build_basic_list_mode (QlTabData *tab)
void file_import (GtkAction G_GNUC_UNUSED *action, gpointer data)
void file_type_menu (QlTabData *tab, GtkWidget *chooser)
void open_file (GtkAction G_GNUC_UNUSED *action, gpointer data)
void open_recent (GtkRecentChooser *c, gpointer data)


Define Documentation

#define AS_STRING_FUNC_NON_TYPEDEF ( name,
list   ) 

Value:

const gchar* name##asString(enum name n) {     \
       switch (n) {                               \
           list(AS_STRING_CASE_NON_TYPEDEF)       \
           default: return ""; } }

Definition at line 69 of file filein.c.

#define DEFINE_ENUM_NON_TYPEDEF ( name,
list   ) 

Value:

enum name {                               \
        list(ENUM_BODY)                       \
    };

Definition at line 48 of file filein.c.

#define ENUM_BODY ( name,
value   )     name value,

Todo:
remove if quicklist uses QOF directly.

Definition at line 45 of file filein.c.

#define FROM_STRING_DEC_NON_TYPEDEF ( name,
list   ) 

Value:

void name##fromString                          \
    (const gchar* str, enum name *type);

Definition at line 53 of file filein.c.

#define FROM_STRING_FUNC_NON_TYPEDEF ( name,
list   ) 

Value:

void name##fromString                          \
    (const gchar* str, enum name *type) {          \
    if(str == NULL) { return; }                    \
    list(FROM_STRING_CASE_NON_TYPEDEF) }

Definition at line 60 of file filein.c.

#define QL_ERRORS (  ) 

Value:

_(QL_SUCCESS, =0) \
    _(QL_CANNOT_OPEN_FILE, ) \
    _(QL_NO_CONTENT_FOUND, ) \
    _(QL_BAD_QUICKLIST_DATA, ) \
    _(QL_BAD_FIELD_DATA, ) \
    _(QL_NO_FIELD_TYPE, ) \
    _(QL_UNABLE_TO_PARSE_FIELD_TYPE, ) \
    _(QL_UNABLE_TO_PARSE_FIELD, ) \
    _(QL_FIELD_NAME_IS_TOO_LONG, ) \
    _(QL_BAD_SORT_VALUE, ) \
    _(QL_TOO_FEW_SORT_LEVELS, ) \
    _(QL_INVALID_FIELD_NAME, ) \
    _(QL_SORT_NESTING_TOO_DEEP, ) \
    _(QL_BAD_FILTER_VALUE, ) \
    _(QL_CANNOT_PARSE_FILTER_DATA, ) \
    _(QL_INVALID_FILTER_NAME, ) \
    _(QL_TOO_FEW_FILTER_FIELDS, ) \
    _(QL_INVALID_FIELD_TYPE, ) \
    _(QL_TOO_MANY_FILTER_COMPARISONS, =19) \
    _(QL_INVALID_CHAR_IN_FILTER, ) \
    _(QL_FILTER_NESTING_TOO_DEEP, ) \
    _(QL_TOO_MANY_COLUMNS, ) \
    _(QL_INVALID_COLUMN_DATA, ) \
    _(QL_UNRECOGNISED_COLUMN_TYPE, ) \
    _(QL_NO_COLUMNS_IN_REPORT, ) \
    _(QL_INVALID_REPORT_DATA, ) \
    _(QL_REPORT_FIELD_NAME_TOO_LONG, ) \
    _(QL_INVALID_DATA, ) \
    _(QL_TOO_MANY_FIELDS, =30) \
    _(QL_LINE_IS_TOO_BIG, =45)
Inherited error codes.

Previous error codes have been expanded into more descriptive enum values that are then mapped as strings.

Todo:
rationalise the error codes.

Definition at line 88 of file filein.c.


Function Documentation

void actually_open ( const gchar *  filename,
QlDialogMode G_GNUC_UNUSED  open_mode,
QlFileType  file_type,
QlContext qlc 
)

This callback is when someone clicks OK on a file selection dialog box

Definition at line 640 of file filein.c.

00642 {
00643     QlTabData * tab;
00644     enum QlErrorVal temp;
00645 
00646     tab = ql_new_tabdata(qlc);
00647     /* 0,0 is valid, so can't use initial values. */
00648     tab->view->activate_row = tab->view->activate_col = -5;
00649     tab->file->file_path = g_strdup (filename);
00650     tab->file->file_name = g_path_get_basename (filename);
00651 
00652     temp = -1;                  /* default error */
00653     if (file_type == QL_OLD_QLF)    /* .qlf */
00654         temp = read_ql_file (tab);
00655     else if (file_type == QL_CSV)   /* .csv */
00656         temp = read_comma_file (tab);
00657     else
00658         temp = read_tab_file (tab);
00659     if (temp)
00660     {
00661         report_error (tab, temp);
00662         return;
00663     }
00664     tab->view->display_mode = DISPLAY_LIST;
00665     tab->file->changed = FALSE;
00666     gtk_recent_manager_add_item (qlc->recent_manager, filename);
00667     dim_all_menus (qlc);
00668     gtk_widget_show_all (qlc->parent);
00669     connect_signals (tab);
00670     tab->view->dialog_mode = MODE_SAVE;
00671 }                               /* end of actual open */

static void add1field ( QlTabData tab  )  [static]

Add 1 column to sheet.

This is necessary for reading unspecified input files such as comma, html and tab

Definition at line 146 of file filein.c.

00147 {
00148     QlFieldInfo * field;
00149     gint fieldx = ++tab->file->last_field;
00150     define_last_field (tab);
00151     gtk_sheet_add_column (tab->view->sheet, 1);
00152     gtk_sheet_set_column_width (tab->view->sheet, fieldx, 80);
00153     field = ql_get_fieldinfo (tab, fieldx);
00154     gtk_sheet_column_button_add_label (tab->view->sheet, fieldx,
00155         field->name);
00156     gtk_sheet_set_column_title (tab->view->sheet,
00157         fieldx, field->name);
00158 }                               /* end of add1field */

static void any_open ( QlDialogMode  open_mode,
QlFileType  file_type,
QlContext qlc 
) [static]

allow the user to choose the file to open.

Definition at line 688 of file filein.c.

00689 {
00690     GtkWidget * chooser;
00691     GtkFileFilter * filter;
00692     gchar * filename, * last_path;
00693     QlTabData * tab;
00694 
00695     tab = ql_get_tabdata (qlc);
00696     filename = NULL;
00697     last_path = check_last_path (qlc);
00698     filter = gtk_file_filter_new ();
00699     if (open_mode == MODE_OPEN)
00700     {
00701         gtk_file_filter_set_name (filter, _("QuickList files *.qlf"));
00702         gtk_file_filter_add_mime_type (filter, "application-x-quicklist");
00703         gtk_file_filter_add_pattern (filter, "*.qlf");
00704         chooser = gtk_file_chooser_dialog_new
00705             ((_("Open a list")),
00706             NULL, GTK_FILE_CHOOSER_ACTION_OPEN,
00707             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00708             GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
00709         gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(chooser),
00710             filter);
00711     }
00712     else
00713     {
00714         chooser = gtk_file_chooser_dialog_new
00715             ((_("Import a file")),
00716             NULL, GTK_FILE_CHOOSER_ACTION_OPEN,
00717             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00718             GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
00719         file_type_menu (tab, chooser);
00720     }
00721     filter = gtk_file_filter_new ();
00722     gtk_file_filter_set_name (filter, _("All files *"));
00723     gtk_file_filter_add_pattern (filter, "*");
00724     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(chooser),
00725         filter);
00726     /* need tab index */
00727     if (last_path)
00728         gtk_file_chooser_set_current_folder (
00729             GTK_FILE_CHOOSER(chooser), last_path);
00730     if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
00731         filename = gtk_file_chooser_get_filename
00732             (GTK_FILE_CHOOSER (chooser));
00733     gtk_widget_destroy (chooser);
00734     if (filename)
00735         actually_open (filename, open_mode, file_type, qlc);
00736 }                               /* end of any_open callback */

void build_basic_list_mode ( QlTabData tab  ) 

window initialiser

Definition at line 753 of file filein.c.

00754 {
00755     GtkSheet *sheet;
00756     GtkWidget *scrolled_window;
00757     gint colx, fieldx, tbindex;
00758 
00759     colx = 0;
00760     fieldx = 0;
00761     tab->view->sheet = GTK_SHEET (gtk_sheet_new (1, tab->file->last_field + 1,
00762         tab->file->file_name));
00763     sheet = (tab->view->sheet);
00764     gtk_sheet_row_button_add_label (sheet, 0, " ");
00765     gtk_sheet_set_autoscroll (sheet, TRUE);
00766     gtk_sheet_set_autoresize (sheet, TRUE);
00767 
00768     gtk_sheet_set_row_titles_width (sheet, 20);
00769     tab->file->last_row = 0;
00770     gtk_container_set_border_width (GTK_CONTAINER (sheet), 4);
00771 
00772     /* set sensitivity for all column and row buttons */
00773     gtk_sheet_columns_set_sensitivity (sheet, TRUE);
00774     gtk_sheet_show_row_titles (sheet);
00775     gtk_sheet_show_column_titles (sheet);
00776     gtk_sheet_rows_set_sensitivity (sheet, TRUE);
00777     ql_fieldinfo_foreach (tab, set_sheet_column_cb, sheet);
00778 /*  for (fieldx = 0; fieldx <= tab->file->last_field; fieldx++)
00779     {
00780         colx = tab->file->fields[fieldx]->sheet_column;
00781         gtk_sheet_set_column_width (sheet, colx,
00782             tab->file->fields[fieldx]->width * 8);
00783         gtk_sheet_column_button_add_label (sheet, colx,
00784             tab->file->fields[fieldx]->name);
00785         gtk_sheet_column_set_justification (sheet, colx,
00786             tab->file->fields[fieldx]->justification);
00787     }*/
00788     gtk_sheet_show_column_titles (sheet);
00789 
00790     /* create a new scrolled window. */
00791     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
00792 
00793     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 3);
00794     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW
00795         (scrolled_window), GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
00796 
00797     gtk_container_add (GTK_CONTAINER (scrolled_window),
00798         GTK_WIDGET (sheet));
00799     gtk_notebook_append_page(tab->qlc->notebook,
00800         GTK_WIDGET(scrolled_window),
00801         tab_label_box (tab, tab->file->file_name));
00802     gtk_widget_show (scrolled_window);
00803     tbindex = gtk_notebook_get_current_page (tab->qlc->notebook);
00804     tbindex++;
00805     gtk_notebook_set_tab_reorderable (tab->qlc->notebook, scrolled_window, TRUE);
00806     gtk_notebook_set_current_page (tab->qlc->notebook, tbindex);
00807 }                               /* end of build_basic_list_mode */

static gchar* check_last_path ( QlContext qlc  )  [static]

retrieve path from the filename of the current tab, if any.

Definition at line 676 of file filein.c.

00677 {
00678     QlFileData * file;
00679 
00680     file = ql_get_filedata (qlc);
00681     if (!file)
00682         return NULL;
00683     return g_path_get_dirname (file->file_path);
00684 }

static void define_last_field ( QlTabData tab  )  [static]

setup a new text field as a standard text field.

Definition at line 126 of file filein.c.

00127 {
00128     QlFieldInfo * field;
00129     gint temp = tab->file->last_field;
00130     field = ql_get_fieldinfo (tab, tab->file->last_field);
00131     field->name = g_strdup_printf ("Column %u", temp + 1);
00132     field->sheet_column = temp;
00133     field->type = FIELD_TYPE_TEXT;
00134     field->formatting = 0;
00135     field->decimal_places = 0;
00136     field->justification = GTK_JUSTIFY_LEFT;
00137     field->width = 10;
00138     tab->file->col_to_field[temp] = temp;
00139 }

void file_type_menu ( QlTabData tab,
GtkWidget *  chooser 
)

Build the menu button for the file selection box, allowing choice of file types. Works for input and output

Definition at line 822 of file filein.c.

00823 {
00824     GtkFileFilter * filter;
00825 
00826     if (tab->view->dialog_mode == MODE_EXPORT)
00827     {
00828         filter = gtk_file_filter_new ();
00829         gtk_file_filter_set_name (filter, _("HTML document, *.html"));
00830         gtk_file_filter_add_pattern (filter, "*.html");
00831         gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(chooser), filter);
00832     }
00833     filter = gtk_file_filter_new ();
00834     gtk_file_filter_set_name (filter, _("Comma delimited, *.csv"));
00835     gtk_file_filter_add_pattern (filter, "*.csv");
00836     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(chooser), filter);
00837     filter = gtk_file_filter_new ();
00838     gtk_file_filter_set_name (filter, _("Tab delimited, *.tsv"));
00839     gtk_file_filter_add_pattern (filter, "*.csv");
00840     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(chooser), filter);
00841 }

void open_file ( GtkAction G_GNUC_UNUSED *  action,
gpointer  data 
)

This is a callback that handles open file from various places

Definition at line 845 of file filein.c.

00846 {
00847     QlContext * qlc;
00848 
00849     qlc = ql_get_context (GTK_WIDGET(data));
00850     g_return_if_fail (qlc);
00851     any_open (MODE_OPEN, QL_OLD_QLF, qlc);
00852 }

static enum QlErrorVal read_comma_file ( QlTabData tab  )  [static]

The file selection dialog box has returned a file name. It is supposed to be a comma delimited file (CSV)

Bug:
remove need for linebuf using g_strsplit ?

Definition at line 164 of file filein.c.

00165 {
00169     gchar linebuf[256];
00170     gchar *linebufp;
00171     gchar *beginp;
00172     gchar *endp;
00173     gint16 fieldx = 0;
00174     gint rowx, c;
00175     gboolean got_data;
00176     FILE * f;
00177 
00178     /* Make Column 1 in field [0] */
00179     if (!(f = fopen (tab->file->file_path, "r")))
00180         return QL_CANNOT_OPEN_FILE;
00181     build_basic_list_mode (tab);
00182     define_last_field (tab);
00183     linebufp = beginp = linebuf;
00184     rowx = fieldx = 0;
00185     endp = linebufp + 253;;
00186     got_data = FALSE;
00187 
00188     while ((c = getc (f)) != EOF)
00189     {
00190         if (c >= ' ' && c != ',')
00191         {
00192             *linebufp++ = c;
00193             if (linebufp >= endp)
00194                 return QL_LINE_IS_TOO_BIG;
00195         }
00196         else if (c == '\n' || c == '\r' || c == ',')
00197         {
00198             if (linebufp != beginp)
00199             {
00200                 got_data = TRUE;
00201                 *linebufp = '\0';
00202                 while (fieldx > tab->file->last_field)
00203                 {
00204                     if (fieldx >= MAX_FIELDS - 1)
00205                         return QL_TOO_MANY_FIELDS;
00206                     else
00207                         add1field (tab);
00208                 }
00209                 gtk_sheet_set_cell_text
00210                     (tab->view->sheet, rowx,
00211                     fieldx, linebuf);
00212                 linebufp = beginp;
00213             }
00214 
00215             fieldx++;
00216             if (c != ',')
00217             {
00218                 if (got_data)
00219                 {
00220                     rowx++;
00221                     add1row (tab);
00222                 }
00223                 fieldx = 0;
00224                 got_data = FALSE;
00225             }
00226         }
00227     }
00228     fclose (f);
00229     return QL_SUCCESS;
00230 }                               /* end of read_comma_file */

static enum QlErrorVal read_ql_file ( QlTabData tab  )  [static]

The file selection dialog box has returned a file name. Get it, open it, open the window. Build all window window components, but do not assemble them. That is done by build_file_win ()

Returns:
0 on success, otherwise negative.

storing width, height, x and y in the file is outmoded but needs to be retained for compatibility.

remove leading spaces

Bug:
replace with glib functions.

remove leading spaces

Bug:
replace with glib functions.

Bug:
remove leading spaces: replace with glib functions.

Bug:
Really ought to check file parameters about right here

Definition at line 240 of file filein.c.

00241 {
00242     gchar linebuf[4096];
00243     gchar tokbuf[256];
00244     gchar *tokbufp;
00245     gchar *linebufp;
00246     gchar *prevbufp;
00247     gint16 fieldx = 0;
00248     gint16 sortx = 0;
00249     gint16 filterx = 0;
00250     gint16 subx = 0;
00251     gint rowx;
00252     gboolean got_data;
00253     gint16 reportx = 0;
00254     gint16 colx = 0;            /* indexes into array */
00255     gint16 thislen, i, count;
00256     FILE * f;
00257     gchar singlechar;
00258     gint16 temp_field, temp_type;
00259 
00260     if (!(f = fopen (tab->file->file_path, "r")))
00261         return QL_CANNOT_OPEN_FILE;
00262     while (fgets (linebuf, sizeof (linebuf), f))
00263     {
00264         linebufp = linebuf;
00265         if (sscanf (linebuf, "%s", tokbuf) != 1)
00266             return QL_NO_CONTENT_FOUND;
00267 
00268         /* process QUICKLIST header record */
00269         if (g_ascii_strcasecmp (tokbuf, "QUICKLIST") == 0)
00270         {
00273             if (sscanf (linebuf, "%*s%*s%*s%hu%hu%hu%hu%hu%hu%hu%hu",
00274                     &tab->file->last_field,
00275                     &tab->file->sort_ct,
00276                     &tab->file->filter_ct,
00277                     &tab->file->report_ct,
00278                     &tab->view->width,
00279                     &tab->view->height,
00280                     &tab->view->x,
00281                     &tab->view->y) < 6)
00282                 return QL_BAD_QUICKLIST_DATA;
00283             tab->file->last_field--;
00284             if (tab->file->last_field < 0
00285                 || tab->file->last_field >= MAX_FIELDS
00286                 || tab->file->sort_ct > MAX_SORTS
00287                 || tab->file->filter_ct > MAX_FILTERS
00288                 || tab->file->report_ct > MAX_REPORTS)
00289                 return QL_BAD_FIELD_DATA;
00290         }
00291         /* process FIELD input header record */
00292         else if (g_ascii_strcasecmp (tokbuf, "FIELD") == 0)
00293         {
00294             QlFieldInfo * field;
00295             guint16 field_type;
00296             if (fieldx > tab->file->last_field)
00297                 return QL_NO_FIELD_TYPE;
00298             field = g_new0(QlFieldInfo, 1);
00299             if (sscanf (linebuf, "%*s%hu%hu%hu%hu%hu%hu%hu%hu%40[^\n\\]",
00300                     &field_type,
00301                     &field->formatting,
00302                     &field->decimal_places,
00303                     &field->justification,
00304                     &field->sheet_column,
00305                     &field->width,
00306                     &field->unused1,
00307                     &field->unused2, tokbuf) != 9)
00308                 return QL_UNABLE_TO_PARSE_FIELD_TYPE;
00309             else
00310                 field->type = field_type;
00311             ql_add_fieldinfo (tab, field);
00312             tokbufp = tokbuf;
00317             while (*tokbufp == ' ')
00318                 tokbufp++;
00319             if (field->type < FIELD_TYPE_TEXT
00320                 || field->type > FIELD_TYPE_TIME
00321                 || field->formatting > 12
00322                 || field->decimal_places > 6
00323                 || field->justification > GTK_JUSTIFY_CENTER
00324                 || field->sheet_column > tab->file->last_field
00325                 || field->width > 80)
00326                 return QL_UNABLE_TO_PARSE_FIELD;
00327 
00328             thislen = strlen (tokbufp);
00329             if (thislen < 1 || thislen > MAX_FIELD_NAME)
00330                 return QL_FIELD_NAME_IS_TOO_LONG;
00331             field->name = g_strdup(tokbufp);
00332             fieldx++;
00333         }
00334         /* convert the SORT record to memory */
00335 
00336         else if (g_ascii_strcasecmp (tokbuf, "SORT") == 0)
00337         {
00338             if (sortx >= tab->file->sort_ct)
00339                 return QL_BAD_SORT_VALUE;
00340             count = sscanf (linebuf,
00341                 "%*s%hu%hu%40[^\n\\]%c%hu%u%hu%u%hu%u%hu%u%hu%u%hu%u",
00342                 &tab->file->sorts[sortx].unused1,
00343                 &tab->file->sorts[sortx].unused2,
00344                 tokbuf,
00345                 &singlechar,
00346                 &tab->file->sorts[sortx].line[0].field,
00347                 &tab->file->sorts[sortx].line[0].ascending,
00348                 &tab->file->sorts[sortx].line[1].field,
00349                 &tab->file->sorts[sortx].line[1].ascending,
00350                 &tab->file->sorts[sortx].line[2].field,
00351                 &tab->file->sorts[sortx].line[2].ascending,
00352                 &tab->file->sorts[sortx].line[3].field,
00353                 &tab->file->sorts[sortx].line[3].ascending,
00354                 &tab->file->sorts[sortx].line[4].field,
00355                 &tab->file->sorts[sortx].line[4].ascending,
00356                 &tab->file->sorts[sortx].line[5].field,
00357                 &tab->file->sorts[sortx].line[5].ascending);
00358             if (count < 6)
00359                 return QL_TOO_FEW_SORT_LEVELS;
00360             tab->file->sorts[sortx].line_ct = (count - 4) / 2;
00361             /* number of sort lines read */
00362             tokbufp = tokbuf;
00367             while (*tokbufp == ' ')
00368                 tokbufp++;
00369             thislen = strlen (tokbufp);
00370             if (thislen < 1
00371                 || thislen > MAX_FIELD_NAME || singlechar != '\\')
00372                 return QL_INVALID_FIELD_NAME;
00373             tab->file->sorts[sortx].name = g_strdup(tokbufp);
00374             for (i = 0; i < MAX_SORT_NESTING; i++)
00375                 if (tab->file->sorts[sortx].line[i].field >=
00376                     tab->file->last_field + 1)
00377                     return QL_SORT_NESTING_TOO_DEEP;
00378             sortx++;
00379         }
00380         /* now store a FILTER record, the most complicated record */
00381         else if (strcmp (tokbuf, "FILTER") == 0)
00382         {
00383             if (filterx >= tab->file->filter_ct)
00384                 return QL_BAD_FILTER_VALUE;
00385             if (sscanf (linebuf, "%*s%d%d%40[^\n\\]%c%hn",
00386                     &tab->file->filters[filterx].by_and,
00387                     &tab->file->filters[filterx].use_nocase,
00388                     tokbuf, &singlechar, &count) != 4)
00389             {
00390                 return QL_CANNOT_PARSE_FILTER_DATA;
00391             }
00392             tokbufp = tokbuf;
00396             while (*tokbufp == ' ')
00397                 tokbufp++;
00398             thislen = strlen (tokbufp);
00399             if (thislen < 1
00400                 || thislen > MAX_FIELD_NAME || singlechar != '\\')
00401                 return QL_INVALID_FILTER_NAME;
00402             strcpy (tab->file->filters[filterx].name, tokbufp);
00403             subx = 0;
00404 
00405             /* now loop through the lines of the filter */
00406             linebufp = linebuf + count;
00407             while (TRUE)
00408             {
00409                 if (sscanf (linebufp, "%hu%hu%hn", &temp_field,
00410                         &temp_type, &count) < 2)
00411                     return QL_TOO_FEW_FILTER_FIELDS;
00412                 linebufp += count;
00413                 tokbuf[0] = '\0';
00414 
00415                 while (*linebufp == ' ')
00416                     linebufp++;
00417                 if (*linebufp != '\n' && *linebufp != '\\' &&
00418                     *linebufp != '\0')
00419                 {
00420                     sscanf (linebufp, "%40[^\\\n]%hn", tokbuf, &count);
00421                     linebufp += count;
00422                 }
00423 
00424                 if (temp_field > tab->file->last_field || temp_type < 0 || temp_type > 7)   /* read and verify field and type */
00425                     return QL_INVALID_FIELD_TYPE;
00426                 tab->file->filters[filterx].line[subx].field = temp_field;
00427                 tab->file->filters[filterx].line[subx].type = temp_type;
00428 /* what happened to 18 ? */
00429                 tokbufp = tokbuf;
00430                 if (strlen (tokbufp) > MAX_FILTER_COMPARE)
00431                     return QL_TOO_MANY_FILTER_COMPARISONS;
00432                 strcpy (tab->file->filters[filterx].line[subx].compare,
00433                     tokbufp);
00434                 subx++;
00435 
00436                 /* now look for \ before next rule, or \n to end it */
00437                 sscanf (linebufp, "%c", &singlechar);
00438                 if (singlechar == '\n' || !singlechar)
00439                     break;      /* no more data */
00440                 if (singlechar != '\\')
00441                     return QL_INVALID_CHAR_IN_FILTER;
00442                 linebufp++;
00443                 if (subx >= MAX_FILTER_NESTING)
00444                     return QL_FILTER_NESTING_TOO_DEEP;
00445 
00446             }                   /* End of loop that scans filter lines */
00447 
00448             /* Break comes here */
00449             tab->file->filters[filterx].line_ct = subx;
00450             filterx++;
00451         }
00452 
00453         /* store a report column */
00454         else if (strcmp (tokbuf, "COLUMN") == 0)
00455         {
00456             if (colx >= tab->file->last_field + 1)
00457                 return QL_TOO_MANY_COLUMNS;
00458             if (sscanf (linebuf,
00459                     "%*s%hu%hu%hu%hu%hu%hu",
00460                     &tab->file->reports[reportx].column[colx].field,
00461                     &tab->file->reports[reportx].column[colx].width,
00462                     &tab->file->reports[reportx].column[colx].group,
00463                     &tab->file->reports[reportx].column[colx].total,
00464                     &tab->file->reports[reportx].column[colx].unused1,
00465                     &tab->file->reports[reportx].column[colx].unused2) < 6)
00466                 return QL_INVALID_COLUMN_DATA;
00467             if (tab->file->reports[reportx].column[colx].field >=
00468                 tab->file->last_field + 1)
00469                 return QL_UNRECOGNISED_COLUMN_TYPE;
00470             colx++;
00471         }
00472         /* store a report record */
00473         else if (strcmp (tokbuf, "REPORT") == 0)
00474         {
00475             if (reportx >= tab->file->report_ct || colx == 0)   /* never got any column records */
00476                 return QL_NO_COLUMNS_IN_REPORT;
00477             if (sscanf (linebuf,
00478                     "%*s%hd%hd%hd%hd%40[^\n\\]%c",
00479                     &tab->file->reports[reportx].sort,
00480                     &tab->file->reports[reportx].filter,
00481                     &tab->file->reports[reportx].width,
00482                     &tab->file->reports[reportx].height,
00483                     tokbuf, &singlechar) < 6)
00484                 return QL_INVALID_REPORT_DATA;
00485             tokbufp = tokbuf;
00486             while (*tokbufp == ' ') /* remove leading spaces */
00487                 tokbufp++;
00488             thislen = strlen (tokbufp);
00489             if (thislen < 1 || thislen > MAX_FIELD_NAME)
00490                 return QL_REPORT_FIELD_NAME_TOO_LONG;
00491             tab->file->reports[reportx].name = g_strdup(tokbufp);
00492             tab->file->reports[reportx].last_column = colx - 1;
00493             reportx++;
00494             colx = 0;           /* reset the report column indicator */
00495         }
00496 
00497         else if (strcmp (tokbuf, "DATA") == 0)
00498             break;
00499         else
00500             return QL_LINE_IS_TOO_BIG;
00501     }
00502 
00504     if (colx != 0
00505         || fieldx != tab->file->last_field + 1
00506         || sortx != tab->file->sort_ct
00507         || filterx != tab->file->filter_ct || reportx != tab->file->report_ct)
00508         return QL_INVALID_DATA;
00509 
00510     /* fields are all OK so go build the basic window and sheet */
00511     reset_col_to_field (tab);
00512     build_basic_list_mode (tab);
00513     tab->file->last_field = fieldx;
00514 
00515     /* The file is already open, now read it in.
00516        Make some effort to not load entirely blank records */
00517     while (fgets (linebuf, sizeof (linebuf), f))
00518     {
00519         fieldx = 0;
00520         got_data = FALSE;
00521         linebufp = linebuf;
00522         prevbufp = linebuf;
00523         rowx = tab->file->last_row;
00524         singlechar = ' ';
00525 
00526         while (singlechar != '\n')
00527         {
00528             while (*linebufp != '\n' && *linebufp != '\\')
00529                 linebufp++;
00530 
00531             singlechar = *linebufp;
00532             if (linebufp != prevbufp)
00533             {                   /* ie, not a zero length field */
00534                 QlFieldInfo * field;
00535                 if (fieldx > tab->file->last_field)
00536                     return QL_TOO_MANY_FIELDS;
00537                 field = ql_get_fieldinfo (tab, fieldx);
00538                 if (!field)
00539                 {
00540                     fieldx++;
00541                     continue;
00542                 }
00543                 *linebufp = '\0';   /* to terminate string move */
00544                 got_data = TRUE;
00545                 gtk_sheet_set_cell_text (tab->view->sheet, rowx,
00546                     field->sheet_column, prevbufp);
00547             }
00548             prevbufp = ++linebufp;
00549             fieldx++;
00550         }
00551         if (got_data)
00552             add1row (tab);
00553     }
00554     fclose (f);
00555     tab->file->current_file = QL_OLD_QLF;
00556     return QL_SUCCESS;
00557 }                               /* end of read_ql_file */

static enum QlErrorVal read_tab_file ( QlTabData tab  )  [static]

Read tab delimited files

Definition at line 561 of file filein.c.

00562 {
00563     gchar linebuf[256];
00564     gchar *linebufp;
00565     gchar *beginp;
00566     gchar *endp;
00567     gint16 fieldx = 0;
00568     gint rowx, c;
00569     gboolean got_data;
00570     FILE *  f;
00571 
00572     /* Make Column 1 in field [0] */
00573     if (!(f = fopen (tab->file->file_path, "r")))
00574         return QL_CANNOT_OPEN_FILE;
00575     define_last_field (tab);
00576     build_basic_list_mode (tab);
00577     linebufp = beginp = linebuf;
00578     rowx = fieldx = 0;
00579     endp = linebufp + 253;;
00580     got_data = FALSE;
00581 
00582     while ((c = getc (f)) != EOF)
00583     {
00584         if (c >= ' ')
00585         {
00586             *linebufp++ = c;
00587             if (linebufp >= endp)   /* line is too big */
00588                 return QL_LINE_IS_TOO_BIG;
00589         }
00590         else if (c == '\n' || c == '\r' || c == '\t')
00591         {
00592             if (linebufp != beginp)
00593             {                   /* ie, there was data */
00594                 got_data = TRUE;
00595                 *linebufp = '\0';
00596                 while (fieldx > tab->file->last_field)
00597                 {
00598                     if (fieldx >= MAX_FIELDS - 1)
00599                         return QL_TOO_MANY_FIELDS;
00600                     else
00601                         add1field (tab);
00602                 }
00603                 gtk_sheet_set_cell_text (tab->view->sheet, rowx,
00604                     fieldx, linebuf);
00605                 linebufp = beginp;
00606             }                   /* end of storing data */
00607 
00608             fieldx++;
00609             if (c != '\t')
00610             {                   /* process end of line or return */
00611                 if (got_data)
00612                 {
00613                     rowx++;
00614                     add1row (tab);
00615                 }
00616                 fieldx = 0;
00617                 got_data = FALSE;
00618             }
00619         }
00620     }
00621     fclose (f);
00622     return QL_SUCCESS;
00623 }                               /* end of read_tab_file */


Generated on Mon Jan 28 22:02:10 2008 for quicklist by  doxygen 1.5.4