gnumeric r16435 - trunk/plugins/paradox



Author: jody
Date: Sun Mar  2 14:51:55 2008
New Revision: 16435
URL: http://svn.gnome.org/viewvc/gnumeric?rev=16435&view=rev

Log:
Merge in ancient patch to support export.


Modified:
   trunk/plugins/paradox/paradox.c
   trunk/plugins/paradox/plugin.xml.in
   trunk/plugins/paradox/px.h

Modified: trunk/plugins/paradox/paradox.c
==============================================================================
--- trunk/plugins/paradox/paradox.c	(original)
+++ trunk/plugins/paradox/paradox.c	Sun Mar  2 14:51:55 2008
@@ -8,50 +8,40 @@
 #include <gnumeric-config.h>
 #include <glib/gi18n-lib.h>
 #include <gnumeric.h>
-#include <string.h>
 #include "px.h"
 
 #include <workbook-view.h>
 #include <workbook.h>
 #include <cell.h>
 #include <value.h>
-#include <goffice/app/go-plugin.h>
 #include <gnm-plugin.h>
 #include <sheet.h>
 #include <ranges.h>
 #include <mstyle.h>
 #include <sheet-style.h>
+
+#include <goffice/app/go-plugin.h>
 #include <goffice/app/io-context.h>
 #include <goffice/utils/datetime.h>
+#include <goffice/utils/go-format.h>
 #include <goffice/app/error-info.h>
 
+#include <string.h>
+#include <unistd.h>
+
 GNM_PLUGIN_MODULE_HEADER;
 
+#ifdef PX_MEMORY_DEBUGGING
+static void gn_errorhandler(pxdoc_t *p, int error, const char *str, void *data) { g_warning(str); }
+#else
+static void *gn_malloc	(pxdoc_t *p, size_t len, const char *caller)		{ return((void *) g_malloc(len)); }
+static void *gn_realloc (pxdoc_t *p, void *mem, size_t len, const char *caller)	{ return((void *) g_realloc((gpointer) mem, len)); }
+static void  gn_free	(pxdoc_t *p, void *ptr)					{ g_free((gpointer) ptr); ptr = NULL; }
+#endif
+
 void paradox_file_open (GOFileOpener const *fo, IOContext *io_context,
                         WorkbookView *wb_view, GsfInput *input);
-
-gboolean
-paradox_file_probe (GOFileOpener const *fo, GsfInput *input,
-                    FileProbeLevel pl);
-
-static void *gn_malloc(pxdoc_t *p, size_t len, const char *caller) {
-	return((void *) g_malloc(len));
-}
-
-static void *gn_realloc(pxdoc_t *p, void *mem, size_t len, const char *caller) {
-	return((void *) g_realloc((gpointer) mem, len));
-}
-
-static void gn_free(pxdoc_t *p, void *ptr) {
-	g_free((gpointer) ptr);
-	ptr = NULL;
-}
-
-static void gn_errorhandler(pxdoc_t *p, int error, const char *str, void *data) {
-				g_warning(str);
-}
-
-void
+G_MODULE_EXPORT void
 paradox_file_open (GOFileOpener const *fo, IOContext *io_context,
                    WorkbookView *wb_view, GsfInput *input)
 {
@@ -67,17 +57,23 @@
 	ErrorInfo *open_error = NULL;
 	guint row, i, j, offset;
 
+#ifdef PX_MEMORY_DEBUGGING
+	PX_mp_init();
+#endif
+
+#ifdef PX_MEMORY_DEBUGGING
+	pxdoc = PX_new2(gn_errorhandler, PX_mp_malloc, PX_mp_realloc, PX_mp_free);
+#else
 	pxdoc = PX_new2(gn_errorhandler, gn_malloc, gn_realloc, gn_free);
+#endif
 	if (PX_open_gsf (pxdoc, input) < 0) {
 		gnumeric_io_error_info_set (io_context, error_info_new_str_with_details (
-		                            _("Error while opening Paradox file."),
-		                            open_error));
+					    _("Error while opening Paradox file."),
+					    open_error));
 		return;
 	}
 	pxh = pxdoc->px_head;
 
-	fprintf(stderr, "Paradox %2.1f file, %d records, %d columns\n", pxh->px_fileversion/10.0, pxh->px_numrecords, pxh->px_numfields);
-
 	PX_set_targetencoding(pxdoc, "UTF-8");
 
 	wb = wb_view_get_workbook (wb_view);
@@ -90,20 +86,23 @@
 	for (i = 0 ; i < (guint) pxh->px_numfields; i++) {
 		char str[30], *str2;
 		char ctypes[26] = {'?',
-		                   'A', 'D', 'S', 'I', '$', 'N', '?', '?',
-		                   'L', '?', '?', 'M', 'B', 'F', 'O', 'G',
-		                   '?', '?', '?', 'T', '@', '+', '#', 'Y',
-		                   };
+				   'A', 'D', 'S', 'I', '$', 'N', '?', '?',
+				   'L', '?', '?', 'M', 'B', 'F', 'O', 'G',
+				   '?', '?', '?', 'T', '@', '+', '#', 'Y',
+				   };
 		cell = sheet_cell_fetch (sheet, i, 0);
-		snprintf (str, 30, "%s,%c,%d", pxf->px_fname, ctypes[(int)pxf->px_ftype], pxf->px_flen);
+		if(pxf->px_ftype == pxfBCD)
+			snprintf (str, 30, "%s,%c,%d", pxf->px_fname, ctypes[(int)pxf->px_ftype], pxf->px_fdc);
+		else
+			snprintf (str, 30, "%s,%c,%d", pxf->px_fname, ctypes[(int)pxf->px_ftype], pxf->px_flen);
 #if PXLIB_MAJOR_VERSION == 0 && (PXLIB_MINOR_VERION < 3 || (PXLIB_MAJOR_VERSION == 3 && PXLIB_MICRO_VERSION == 0))
 		/* Convert the field names to utf-8. This is actually in pxlib
 		 * responsibility, but hasn't been implemented yet. For the mean time
 		 * we *misuse* PX_get_data_alpha()
 		 */
 		PX_get_data_alpha(pxdoc, str, strlen(str), &str2);
-		fprintf(stderr, "%s\n", str2);
 		gnm_cell_set_text (cell, str2);
+		pxdoc->free(pxdoc, str2);
 #else
 		gnm_cell_set_text (cell, str);
 #endif
@@ -119,8 +118,8 @@
 
 	if((data = (char *) pxdoc->malloc(pxdoc, pxh->px_recordsize, _("Could not allocate memory for record."))) == NULL) {
 		gnumeric_io_error_info_set (io_context, error_info_new_str_with_details (
-		                            _("Error while opening Paradox file."),
-		                            open_error));
+					    _("Error while opening Paradox file."),
+					    open_error));
 		return;
 	}
 	row = 1;
@@ -162,6 +161,8 @@
 						double value;
 						if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
 							val = value_new_float (value);
+							if(pxf->px_ftype == pxfCurrency)
+								value_set_fmt (val, go_format_default_money ());
 						}
 						break;
 					}
@@ -169,9 +170,10 @@
 						double value;
 						if(0 < PX_get_data_double(pxdoc, &data[offset], pxf->px_flen, &value)) {
 							value = value / 86400000.0;
-							/* 693595 = number of days up to 31.12.1899 */
-							value -= 693595;
+							/* 693594 = number of days up to 31.12.1899 */
+							value -= 693594;
 							val = value_new_float (value);
+							value_set_fmt (val, go_format_default_date_time());
 						}
 						break;
 					}
@@ -190,6 +192,7 @@
 							PX_SdnToGregorian(value+1721425, &year, &month, &day);
 							date = g_date_new_dmy (day, month, year);
 							val = value_new_int (datetime_g_to_serial (date, NULL));
+							value_set_fmt (val, go_format_default_date());
 							g_date_free (date);
 						}
 						break;
@@ -198,6 +201,7 @@
 						long value;
 						if(0 < PX_get_data_long(pxdoc, &data[offset], pxf->px_flen, &value)) {
 							val = value_new_float (value/86400000.0);
+							value_set_fmt (val, go_format_default_time());
 						}
 						break;
 					}
@@ -260,11 +264,17 @@
 	sheet_flag_recompute_spans (sheet);
 }
 
+/*****************************************************************************/
+
 gboolean
 paradox_file_probe (GOFileOpener const *fo, GsfInput *input,
+                    FileProbeLevel pl);
+
+G_MODULE_EXPORT gboolean
+paradox_file_probe (GOFileOpener const *fo, GsfInput *input,
                     FileProbeLevel pl)
 {
-	pxdoc_t	  *pxdoc;
+	pxdoc_t		*pxdoc;
 	pxhead_t	*pxh;
 
 	pxdoc = PX_new();
@@ -277,5 +287,332 @@
 	PX_close (pxdoc);
 	PX_delete (pxdoc);
 
+#ifdef PX_MEMORY_DEBUGGING
+	PX_mp_list_unfreed();
+#endif
+
 	return TRUE;
 }
+
+/*****************************************************************************/
+
+void paradox_file_save (GOFileSaver const *fs, IOContext *io_context,
+			WorkbookView const *wb_view, GsfOutput *output);
+G_MODULE_EXPORT void
+paradox_file_save (GOFileSaver const *fs, IOContext *io_context,
+		   WorkbookView const *wb_view, GsfOutput *output)
+{
+	Sheet *sheet;
+	GnmRange r;
+	gint row, col, i;
+
+	pxdoc_t *pxdoc = NULL;
+	pxfield_t *pxf;
+	char *data;
+	char *tmpfilename;
+
+	sheet = wb_view_cur_sheet (wb_view);
+	if (sheet == NULL) {
+		gnumeric_io_error_string (io_context, _("Cannot get default sheet."));
+		return;
+	}
+
+	r = sheet_get_extent (sheet, FALSE);
+
+#ifdef PX_MEMORY_DEBUGGING
+	pxdoc = PX_new2(gn_errorhandler, PX_mp_malloc, PX_mp_realloc, PX_mp_free);
+#else
+	pxdoc = PX_new2(gn_errorhandler, gn_malloc, gn_realloc, gn_free);
+#endif
+
+	/* Read the field specification and build the field array for
+	 * PX_create_fp(). The memory is freed by PX_delete() including
+	 * the memory for the field name. */
+	if((pxf = (pxfield_t *) pxdoc->malloc(pxdoc, (r.end.col+1)*sizeof(pxfield_t), _("Allocate memory for field definitions."))) == NULL){
+		gnumeric_io_error_string (io_context, _("Cannot allocate memory for field definitions."));
+		PX_delete(pxdoc);
+		return;
+	}
+
+	for (col = r.start.col; col <= r.end.col; col++) {
+		GnmCell *cell = sheet_cell_get (sheet, col, 0);
+		if (gnm_cell_is_empty (cell)) {
+			gnumeric_io_error_string (io_context, _("First line of sheet must contain database specification."));
+			PX_delete(pxdoc);
+			return;
+		} else {
+			gchar *fieldstr, *tmp;
+			int len, needsize, needprecision;
+
+			i = col;
+			fieldstr = gnm_cell_get_rendered_text (cell);
+			needsize = 0;
+			needprecision = 0;
+
+			/* Search for the first comma which is the end of the field name. */
+			tmp = strchr(fieldstr, ',');
+			if(NULL == tmp) {
+				g_warning(_("Field specification must be a comma separated value (Name,Type,Size,Prec)."));
+				PX_delete(pxdoc);
+				return;
+			}
+			len = tmp-fieldstr;
+			if(NULL == (pxf[i].px_fname = pxdoc->malloc(pxdoc, len+1, _("Allocate memory for column name.")))) {
+				g_warning(_("Could not allocate memory for %d. field name."), i);
+				PX_delete(pxdoc);
+				return;
+			}
+			strncpy(pxf[i].px_fname, fieldstr, len);
+			pxf[i].px_fname[len] = '\0';
+
+			/* Get the field Type */
+			fieldstr = tmp+1;
+			if(*fieldstr == '\0') {
+				g_warning(_("%d. field specification ended unexpectetly."), i);
+				PX_delete(pxdoc);
+				return;
+			}
+			if(*fieldstr == ',') {
+				g_warning(_("%d. field specification misses type."), i);
+				PX_delete(pxdoc);
+				return;
+			}
+			switch((int) *fieldstr) {
+			case 'S':
+			pxf[i].px_ftype = pxfShort;
+			pxf[i].px_flen = 2;
+			break;
+			case 'I':
+			pxf[i].px_ftype = pxfLong;
+			pxf[i].px_flen = 4;
+			break;
+			case 'A':
+			case 'C':
+			pxf[i].px_ftype = pxfAlpha;
+			needsize = 1;
+			break;
+			case 'N':
+			pxf[i].px_ftype = pxfNumber;
+			pxf[i].px_flen = 8;
+			break;
+			case '$':
+			pxf[i].px_ftype = pxfCurrency;
+			pxf[i].px_flen = 8;
+			break;
+			case 'L':
+			pxf[i].px_ftype = pxfLogical;
+			pxf[i].px_flen = 1;
+			break;
+			case 'D':
+			pxf[i].px_ftype = pxfDate;
+			pxf[i].px_flen = 4;
+			break;
+			case '+':
+			pxf[i].px_ftype = pxfAutoInc;
+			pxf[i].px_flen = 4;
+			break;
+			case '@':
+			pxf[i].px_ftype = pxfTimestamp;
+			pxf[i].px_flen = 8;
+			break;
+			case 'T':
+			pxf[i].px_ftype = pxfTime;
+			pxf[i].px_flen = 4;
+			break;
+			case '#':
+			pxf[i].px_ftype = pxfBCD;
+			pxf[i].px_flen = 17;
+			needprecision = 1;
+			break;
+			case 'M':
+			pxf[i].px_ftype = pxfMemoBLOb;
+			needsize = 1;
+			break;
+			case 'B':
+			pxf[i].px_ftype = pxfBLOb;
+			needsize = 1;
+			break;
+			case 'F':
+			pxf[i].px_ftype = pxfFmtMemoBLOb;
+			needsize = 1;
+			break;
+			case 'Y':
+			pxf[i].px_ftype = pxfBytes;
+			needsize = 1;
+			break;
+			default:
+			g_warning(_("%d. field type '%c' is unknown."), i, *fieldstr);
+			pxdoc->free(pxdoc, pxf);
+			PX_delete(pxdoc);
+			return;
+			}
+
+			if(needsize || needprecision) {
+				char *endptr;
+				/* find end of type definition */
+				tmp = strchr(fieldstr, ',');
+				if(NULL == tmp || *(tmp+1) == '\0') {
+					g_warning(_("Field specification misses the column size."));
+					PX_delete(pxdoc);
+					return;
+				}
+				fieldstr = tmp+1;
+				if(needsize)
+					pxf[i].px_flen = strtol(fieldstr, &endptr, 10);
+				else
+					pxf[i].px_fdc = strtol(fieldstr, &endptr, 10);
+				if((endptr == NULL) || (fieldstr == endptr)) {
+					g_warning(_("Field specification misses the column size."));
+					PX_delete(pxdoc);
+					return;
+				}
+				if(*endptr != '\0') {
+					/* There is also precision which we do not care about. */
+					fieldstr = endptr+1;
+					g_warning(_("The remainder '%s' of the specification for field %d is being disregarded."), fieldstr, i+1);
+				} 
+			}
+		}
+	}
+
+	/* Create the paradox file */
+	tmpfilename = tempnam("/tmp", NULL);
+	if(0 > PX_create_file(pxdoc, pxf, r.end.col+1, tmpfilename, pxfFileTypNonIndexDB)) {
+		g_warning(_("Could not create output file."));
+		PX_delete(pxdoc);
+		return;
+	}
+
+	PX_set_inputencoding(pxdoc, "UTF-8");
+	PX_set_parameter(pxdoc, "targetencoding", "CP1252");
+	PX_set_tablename(pxdoc, sheet->name_unquoted);
+
+	if((data = (char *) pxdoc->malloc(pxdoc, pxdoc->px_head->px_recordsize, _("Allocate memory for record data."))) == NULL) {
+		g_warning(_("Could not allocate memory for record data."));
+		PX_close(pxdoc);
+		PX_delete(pxdoc);
+		return;
+	}
+	/* Process all cells */
+	for (row = r.start.row+1; row <= r.end.row; row++) {
+		int i;
+		int offset;
+		offset = 0;
+		memset(data, 0, pxdoc->px_head->px_recordsize);
+		for (col = r.start.col, i = 0; col <= r.end.col; col++) {
+			GnmCell *cell = sheet_cell_get (sheet, col, row);
+			if (!gnm_cell_is_empty (cell)) {
+				char *fieldstr = gnm_cell_get_rendered_text (cell);
+				switch(pxf[i].px_ftype) {
+				case pxfShort: {
+					int value = value_get_as_int(cell->value);
+					PX_put_data_short(pxdoc, &data[offset], 2, (short int) value);
+					break;
+				}
+				case pxfLong:
+				case pxfAutoInc: {
+					int value = value_get_as_int (cell->value);
+					PX_put_data_long(pxdoc, &data[offset], 4, value);
+					break;
+				}
+				case pxfTimestamp: {
+					double value = value_get_as_float (cell->value);
+					/* 60 would be 29.2.1900 which didn't exist. */
+					if (value < 60)
+						value += 1.0;
+					value += 693594;
+					value *= 86400000.0;
+					PX_put_data_double(pxdoc, &data[offset], 8, value);
+					break;
+				}
+				case pxfCurrency:
+				case pxfNumber: {
+					double value = value_get_as_float (cell->value);
+					PX_put_data_double(pxdoc, &data[offset], 8, value);
+					break;
+				}
+				case pxfAlpha: {
+					char *value = fieldstr;
+					if ((int)strlen (value) > pxf[i].px_flen) {
+					       g_warning(_("Field %d in line %d has possibly been cut off. Data has %d chars."), i+1, row+1, strlen(value));
+					}
+					PX_put_data_alpha(pxdoc, &data[offset], pxf[i].px_flen, value);
+					break;
+				}
+				case pxfMemoBLOb:
+				case pxfFmtMemoBLOb: {
+					char *value = fieldstr;
+					if(0 > PX_put_data_blob(pxdoc, &data[offset], pxf[i].px_flen, value, strlen(value))) {
+						g_warning(_("Field %d in row %d could not be written."), i+1, row+1);
+					}
+					break;
+				}
+				case pxfDate: {
+					long value = value_get_as_int (cell->value);
+					/* 60 would be 29.2.1900 which didn't exist. */
+					if(value < 60)
+						value++;
+					value += 693594;
+					PX_put_data_long(pxdoc, &data[offset], 4, value);
+					break;
+				}
+				case pxfTime: {
+					double dtmp;
+					int value;
+					dtmp = value_get_as_float(cell->value);
+					dtmp -= ((int) dtmp);
+					value = (int) (dtmp * 86400000.0);
+					PX_put_data_long(pxdoc, &data[offset], 4, value);
+					break;
+				}
+				case pxfLogical: {
+					gboolean err; /* Ignored */
+					gboolean value = value_get_as_bool (cell->value, &err);
+					if(!value) {
+					PX_put_data_byte(pxdoc, &data[offset], 1, 0);
+					} else {
+					PX_put_data_byte(pxdoc, &data[offset], 1, 1);
+					}
+					break;
+				}
+				case pxfBCD: 
+					PX_put_data_bcd(pxdoc, &data[offset], pxf[i].px_fdc, fieldstr);
+					break;
+				}
+			}
+			offset += pxf[i].px_flen;
+			i++;
+		}
+		if((i > 0) && (0 > PX_put_record(pxdoc, data))) {
+			g_warning(_("Could not write record number %d."), i+1);
+			pxdoc->free(pxdoc, data);
+			PX_close(pxdoc);
+			PX_delete(pxdoc);
+			return;
+		}
+	}
+	pxdoc->free(pxdoc, data);
+	PX_close(pxdoc);
+	PX_delete(pxdoc);
+
+#ifdef PX_MEMORY_DEBUGGING
+	PX_mp_list_unfreed();
+#endif
+
+	{
+		FILE *fp;
+		size_t size;
+		fp = fopen (tmpfilename, "r");
+		if(fp) {
+			data = g_malloc (8192);
+			while(0 != (size = fread(data, 1, 8192, fp)))
+				gsf_output_write(output, size, data);
+			fclose(fp);
+			g_free(data);
+		} else
+			g_warning("Cannot open %s\n", tmpfilename);
+
+		unlink(tmpfilename);
+	}
+}
+

Modified: trunk/plugins/paradox/plugin.xml.in
==============================================================================
--- trunk/plugins/paradox/plugin.xml.in	(original)
+++ trunk/plugins/paradox/plugin.xml.in	Sun Mar  2 14:51:55 2008
@@ -10,12 +10,17 @@
 	<services>
 		<service type="file_opener" id="paradox" priority="100" probe="FALSE">
 			<information>
-				<_description>Paradox database or primary index file</_description>
+				<_description>Paradox database or primary index file (*.db, *.px)</_description>
 			</information>
 			<suffixes>
 				<suffix>db</suffix>
 				<suffix>px</suffix>
 			</suffixes>
 		</service>
+		<service type="file_saver" id="paradox" format_level="write_only" file_extension="db">
+			<information>
+				<_description>Paradox database (*.db)</_description>
+			</information>
+		</service>
 	</services>
 </plugin>

Modified: trunk/plugins/paradox/px.h
==============================================================================
--- trunk/plugins/paradox/px.h	(original)
+++ trunk/plugins/paradox/px.h	Sun Mar  2 14:51:55 2008
@@ -3,9 +3,12 @@
 
 #include <gnumeric.h>
 #include <gsf/gsf.h>
-#if PXLIB_MAJOR_VERSION == 0 && (PXLIB_MINOR_VERION < 3 || (PXLIB_MAJOR_VERSION == 3 && PXLIB_MICRO_VERSION == 0))
 #include <pxversion.h>
-#endif
 #include <paradox-gsf.h>
 
+#define PX_MEMORY_DEBUGGING
+#ifdef PX_MEMORY_DEBUGGING
+#include <paradox-mp.h>
+#endif
+
 #endif



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