[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: gEDA-dev: [RFC][PATCH] Making libgeda load from buffers
On Saturday 05 May 2007 14:22:01 Peter TB Brett wrote:
> What I've done in the attached patches is the following: I've added a new
> text buffer system (s_textbuffer.c) that basically lets you iterate over
> the lines of a string in memory, doing appropriate bounds checking. I've
> then modified all of the commands used when parsing schematics/symbols to
> use this API.
These new patches are less messy and have full Doxygen updates, i.e. they
don't suck.
Peter
--
Fisher Society committee http://tinyurl.com/o39w2
CUSBC novices, match and league secretary http://tinyurl.com/mwrc9
CU Spaceflight http://tinyurl.com/ognu2
09f911029d74e35bd84156c5635688c0 peter-b.co.uk
PGP signature
Add managed text buffers to libgeda.
From: Peter TB Brett <peter@peter-b.co.uk>
In order to facilitate loading symbols & schematics from
memory without an extensive rewrite, this patch adds an API
for reading memory arrays a bit like a file.
Using memory streams & fgets would be nicer, but unfortunately
memory streams are a GNU libc extension.
---
libgeda/include/prototype.h | 6 +
libgeda/include/struct.h | 5 +
libgeda/src/Makefile.am | 2
libgeda/src/s_textbuffer.c | 218 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 230 insertions(+), 1 deletions(-)
diff --git a/libgeda/include/prototype.h b/libgeda/include/prototype.h
index 0aacafc..b105588 100644
--- a/libgeda/include/prototype.h
+++ b/libgeda/include/prototype.h
@@ -635,3 +635,9 @@ char *u_basic_breakup_string(char *string, char delimiter, int count);
void u_basic_strip_trailing(char *string, char c);
int u_basic_has_trailing(char *string, char c);
int u_basic_count_char(const char *string, char character);
+
+/* s_textbuffer.c */
+TextBuffer *s_textbuffer_new (gchar *data, const gint size);
+TextBuffer *s_textbuffer_free (TextBuffer *tb);
+void s_textbuffer_seek (TextBuffer *tb, const gint offset);
+const gchar *s_textbuffer_next (TextBuffer *tb, const gsize count);
diff --git a/libgeda/include/struct.h b/libgeda/include/struct.h
index 8b4e9c8..47b9062 100644
--- a/libgeda/include/struct.h
+++ b/libgeda/include/struct.h
@@ -952,4 +952,9 @@ struct st_page_smob {
PAGE *page;
};
+/* Managed text buffers
+ * ==================== */
+
+typedef struct _TextBuffer TextBuffer;
+
#endif
diff --git a/libgeda/src/Makefile.am b/libgeda/src/Makefile.am
index af773ab..ed03681 100644
--- a/libgeda/src/Makefile.am
+++ b/libgeda/src/Makefile.am
@@ -20,7 +20,7 @@ libgeda_la_SOURCES = \
o_pin_basic.c o_image.c o_embed.c \
u_basic.c s_attrib.c s_basic.c \
s_clib.c s_encoding.c s_hierarchy.c s_papersizes.c s_stretch.c \
- s_log.c \
+ s_log.c s_textbuffer.c \
s_page.c s_slib.c s_color.c s_undo.c s_conn.c \
s_cue.c s_tile.c s_menu.c s_toplevel.c g_smob.c libgeda.c \
g_register.c g_rc.c i_vars.c o_picture.c gdk-pixbuf-hacks.c
diff --git a/libgeda/src/s_textbuffer.c b/libgeda/src/s_textbuffer.c
new file mode 100644
index 0000000..7b05953
--- /dev/null
+++ b/libgeda/src/s_textbuffer.c
@@ -0,0 +1,218 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+#include "i_vars.h"
+#include "prototype.h"
+
+struct _TextBuffer
+{
+ gchar *buffer;
+ gsize size;
+
+ gchar *line;
+ gsize linesize;
+
+ gsize offset;
+};
+
+#define TEXT_BUFFER_LINE_SIZE 1024
+
+/*! \brief Create a new managed text buffer.
+ *
+ * \par Function description
+ * Allocates and initialises a new TextBuffer to manage the given data
+ * buffer.
+ *
+ * If the size argument is negative, assumes that data is
+ * null-terminated.
+ *
+ * \param data The address of the buffer to be managed.
+ * \param size The length of the buffer.
+ * \retval Pointer to a new TextBuffer struct.
+ */
+TextBuffer *s_textbuffer_new (gchar *data, const gint size)
+{
+ TextBuffer *result;
+ gsize realsize;
+
+ g_assert (data != NULL);
+
+ if (size < 0)
+ realsize = strlen(data);
+ else
+ realsize = size;
+
+ result = g_new0(TextBuffer, 1);
+
+ result->buffer = data;
+ result->size = realsize;
+
+ result->linesize = TEXT_BUFFER_LINE_SIZE;
+ result->line = g_malloc(result->linesize);
+
+ return result;
+}
+
+/*! \brief Clean up a managed text buffer
+ *
+ * \par Function description
+ * Cleans up all of the resources associated with a given TextBuffer.
+ *
+ * Should be called thus:
+ *
+ * \code
+ * tb = s_textbuffer_free (tb);
+ * \endcode
+ */
+TextBuffer *s_textbuffer_free (TextBuffer *tb)
+{
+ if (tb == NULL) return NULL;
+
+ g_free (tb->line);
+ tb->line = NULL;
+ g_free (tb);
+ return NULL;
+}
+
+/*! \brief Change the current position within a text buffer
+ *
+ * \par Function description
+ * Changes where the next call to s_textbuffer_next() will start
+ * reading. If offset is negative, it is considered as a distance
+ * from the end of the buffer.
+ *
+ * \param tb A TextBuffer to seek within.
+ * \param offset A new position within the buffer.
+ */
+void s_textbuffer_seek (TextBuffer *tb, const gint offset)
+{
+ gint ofs;
+ gsize realoffset;
+
+ if (tb == NULL) return;
+
+ ofs = offset;
+ if (ofs > tb->size)
+ ofs = tb->size;
+
+ if (ofs < -tb->size)
+ ofs = 0;
+
+ if (ofs < 0)
+ realoffset = tb->size - ofs;
+ else
+ realoffset = ofs;
+
+ tb->offset = realoffset;
+}
+
+/*! \brief Fetch a number of characters from a text buffer
+ *
+ * \par Function description
+ * Get some number of characters from a TextBuffer, starting at the
+ * current position. If the end of the buffer has been reached (and
+ * thus no more characters remain) returns null.
+ *
+ * The returned character array should be considered highly volatile,
+ * and is only valid until the next call to s_textbuffer_next() or
+ * s_textbuffer_next_line().
+ *
+ * \param tb TextBuffer to read from.
+ * \param count Maximum number of characters to read.
+ * \retval Character array, or NULL if no characters left.
+ */
+gchar *s_textbuffer_next (TextBuffer *tb, const gsize count)
+{
+ gsize len = count;
+ gsize maxlen = tb->size - tb->offset;
+
+ if (tb == NULL) return NULL;
+
+ if (count == 0) return NULL;
+
+ if (tb->offset >= tb->size)
+ return NULL;
+
+ if (len > maxlen)
+ len = maxlen;
+
+ if (tb->linesize < len + 1) {
+ tb->line = g_realloc(tb->line, len + 1);
+ tb->linesize = len + 1;
+ }
+
+ strncpy (tb->line, tb->buffer + tb->offset, len);
+
+ tb->line[len] = 0;
+ tb->offset += len;
+
+ return tb->line;
+}
+/*! \brief Fetch the next line from a text buffer
+ *
+ * \par Function description
+ * Get the next line of characters from a TextBuffer, starting from
+ * the current position. If the end of the buffer has been reached
+ * (and thus no more characters remain) returns null.
+ *
+ * The returned character array should be considered highly volatile,
+ * and is only valid until the next call to s_textbuffer_next() or
+ * s_textbuffer_next_line().
+ *
+ * \param tb TextBuffer to read from.
+ * \retval Character array, or NULL if no characters left.
+ */
+gchar *s_textbuffer_next_line (TextBuffer *tb)
+{
+ int len = 0;
+
+ if (tb == NULL) return NULL;
+
+ if (tb->offset >= tb->size)
+ return NULL;
+
+ while ((tb->buffer[tb->offset + len] != '\n')
+ && (len < tb->size - tb->offset - 1)) {
+ len++;
+ }
+
+ len++;
+
+ return s_textbuffer_next (tb, len);
+}
Make libgeda parse schematics from buffered data.
From: Peter TB Brett <peter@peter-b.co.uk>
In order to support more complex methods of acquiring symbol
data, libgeda needs to be able to load schematics and symbols
directly from a memory buffer as well as from files.
---
libgeda/include/prototype.h | 25 +++++++--
libgeda/src/a_basic.c | 125 ++++++++++++++++++++++++++++++++-----------
libgeda/src/o_attrib.c | 42 ++++++++------
libgeda/src/o_picture.c | 44 ++++++++-------
libgeda/src/o_text_basic.c | 23 +++++---
5 files changed, 173 insertions(+), 86 deletions(-)
diff --git a/libgeda/include/prototype.h b/libgeda/include/prototype.h
index b105588..400378a 100644
--- a/libgeda/include/prototype.h
+++ b/libgeda/include/prototype.h
@@ -2,6 +2,7 @@
void o_save_embedded(TOPLEVEL *w_current, OBJECT *object_list, FILE *fp);
void o_save_write_header(FILE *fp);
int o_save(TOPLEVEL *w_current, const char *filename);
+OBJECT *o_read_buffer(TOPLEVEL *w_current, OBJECT *object_list, char *buffer, const int size, const char *name);
OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename);
void o_scale(TOPLEVEL *w_current, OBJECT *list, int x_scale, int y_scale);
@@ -162,7 +163,11 @@ ATTRIB *o_attrib_copy(ATTRIB *list);
void o_attrib_delete(ATTRIB *a_current);
void o_attrib_remove(ATTRIB *list, ATTRIB *remove);
void o_attrib_detach_all(TOPLEVEL *w_current, OBJECT *object_list, OBJECT *main_head);
-OBJECT *o_read_attribs(TOPLEVEL *w_current, FILE *fp, OBJECT *object_to_get_attribs, unsigned int release_ver, unsigned int fileformat_ver);
+OBJECT *o_read_attribs(TOPLEVEL *w_current,
+ OBJECT *object_to_get_attribs,
+ TextBuffer *tb,
+ unsigned int release_ver,
+ unsigned int fileformat_ver);
void o_save_attribs(FILE *fp, ATTRIB *attribs);
int o_attrib_get_name_value(char *string, char **name, char **value);
void o_attrib_free_current(TOPLEVEL *w_current);
@@ -370,8 +375,11 @@ void o_net_consolidate(TOPLEVEL *w_current);
void o_net_modify(TOPLEVEL *w_current, OBJECT *object, int x, int y, int whichone);
/* o_picture.c */
-OBJECT *o_picture_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
- FILE *fp, unsigned int release_ver, unsigned int fileformat_ver);
+OBJECT *o_picture_read(TOPLEVEL *w_current, OBJECT *object_list,
+ const char *first_line,
+ TextBuffer *tb,
+ unsigned int release_ver,
+ unsigned int fileformat_ver);
char *o_picture_save(OBJECT *object);
void o_picture_set_pixbuf(TOPLEVEL *w_current, GdkPixbuf *pixbuf, char *filename);
OBJECT *o_picture_add(TOPLEVEL *w_current, OBJECT *object_list,
@@ -426,7 +434,12 @@ int o_text_width(TOPLEVEL *w_current, char *string, int size);
OBJECT *o_text_create_string(TOPLEVEL *w_current, OBJECT *object_list, char *string, int size, int color, int x, int y, int alignment, int angle);
OBJECT *o_text_add(TOPLEVEL *w_current, OBJECT *object_list, char type, int color, int x, int y, int alignment, int angle, char *string, int size, int visibility, int show_name_value);
void o_text_recalc(TOPLEVEL *w_current, OBJECT *o_current);
-OBJECT *o_text_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[], FILE *fp, unsigned int release_ver, unsigned int fileformat_ver);
+OBJECT *o_text_read(TOPLEVEL *w_current,
+ OBJECT *object_list,
+ const char *first_line,
+ TextBuffer *tb,
+ unsigned int release_ver,
+ unsigned int fileformat_ver);
void o_text_set_info_font(char buf[]);
char *o_text_save(OBJECT *object);
void o_text_recreate(TOPLEVEL *w_current, OBJECT *o_current);
@@ -472,6 +485,7 @@ char *remove_nl(char *string);
char *remove_last_nl(char *string);
char *remove_string(char *string, int start, int end);
char *insert_string(char *string, int start, char *insert_string);
+char *buffer_next_line(const char *buffer, const size_t size, size_t *offset);
char *expand_env_variables(char *string);
/* s_clib.c */
@@ -640,4 +654,5 @@ int u_basic_count_char(const char *string, char character);
TextBuffer *s_textbuffer_new (gchar *data, const gint size);
TextBuffer *s_textbuffer_free (TextBuffer *tb);
void s_textbuffer_seek (TextBuffer *tb, const gint offset);
-const gchar *s_textbuffer_next (TextBuffer *tb, const gsize count);
+gchar *s_textbuffer_next (TextBuffer *tb, const gsize count);
+gchar *s_textbuffer_next_line (TextBuffer *tb);
diff --git a/libgeda/src/a_basic.c b/libgeda/src/a_basic.c
index 1b0e8e5..a3387fa 100644
--- a/libgeda/src/a_basic.c
+++ b/libgeda/src/a_basic.c
@@ -288,19 +288,30 @@ int o_save(TOPLEVEL *w_current, const char *filename)
return 1;
}
-/*! \brief Read a file
+/*! \brief Read a memory buffer
* \par Function Description
- * This function reads a file in libgead format.
+ * This function reads data in libgeda format from a memory buffer.
+ *
+ * If the size argument is negative, the buffer is assumed to be
+ * null-terminated.
+ *
+ * The name argument is used for debugging, and should be set to a
+ * meaningful string (e.g. the name of the file the data is from).
*
* \param [in,out] w_current The current TOPLEVEL structure.
* \param [in] object_list The object_list to read data to.
- * \param [in] filename The filename to read from.
+ * \param [in] buffer The memory buffer to read from.
+ * \param [in] size The size of the buffer.
+ * \param [in] name The name to describe the data with.
* \return object_list if successful read, or NULL on error.
*/
-OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
+OBJECT *o_read_buffer(TOPLEVEL *w_current, OBJECT *object_list,
+ char *buffer, const int size,
+ const char *name)
{
- FILE *fp;
- char buf[1024];
+ char *line = NULL;
+ TextBuffer *tb = NULL;
+
char objtype;
OBJECT *object_list_save=NULL;
OBJECT *temp_tail=NULL;
@@ -315,19 +326,24 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
int embedded_level = 0;
+
/* fill version with default file format version (the current one) */
current_fileformat_ver = FILEFORMAT_VERSION;
- fp = fopen(filename, "r");
-
- if (fp == NULL) {
- s_log_message("o_read: Could not open [%s]\n", filename);
+ if (buffer == NULL) {
+ s_log_message("o_read_buffer: Received NULL buffer\n");
return(NULL);
}
- while ( fgets(buf, 1024, fp) != NULL) {
+ tb = s_textbuffer_new (buffer, size);
+ g_assert (tb != NULL);
+
+ while (1) {
- sscanf(buf, "%c", &objtype);
+ line = s_textbuffer_next_line(tb);
+ if (line == NULL) break;
+
+ sscanf(line, "%c", &objtype);
/* Do we need to check the symbol version? Yes, but only if */
/* 1) the last object read was a complex and */
@@ -346,40 +362,42 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
switch (objtype) {
case(OBJ_LINE):
- object_list = (OBJECT *) o_line_read(w_current, object_list, buf,
+ object_list = (OBJECT *) o_line_read(w_current, object_list, line,
release_ver, fileformat_ver);
break;
case(OBJ_NET):
- object_list = (OBJECT *) o_net_read(w_current, object_list, buf,
+ object_list = (OBJECT *) o_net_read(w_current, object_list, line,
release_ver, fileformat_ver);
break;
case(OBJ_BUS):
- object_list = (OBJECT *) o_bus_read(w_current, object_list, buf,
+ object_list = (OBJECT *) o_bus_read(w_current, object_list, line,
release_ver, fileformat_ver);
break;
case(OBJ_BOX):
- object_list = (OBJECT *) o_box_read(w_current, object_list, buf,
+ object_list = (OBJECT *) o_box_read(w_current, object_list, line,
release_ver, fileformat_ver);
break;
case(OBJ_PICTURE):
- object_list = (OBJECT *) o_picture_read(w_current, object_list, buf,
- fp,
+ line = g_strdup(line);
+ object_list = (OBJECT *) o_picture_read(w_current, object_list,
+ line, tb,
release_ver, fileformat_ver);
+ g_free (line);
break;
case(OBJ_CIRCLE):
- object_list = (OBJECT *) o_circle_read(w_current, object_list, buf,
+ object_list = (OBJECT *) o_circle_read(w_current, object_list, line,
release_ver, fileformat_ver);
break;
case(OBJ_COMPLEX):
case(OBJ_PLACEHOLDER):
- object_list = (OBJECT *) o_complex_read(w_current, object_list, buf,
+ object_list = (OBJECT *) o_complex_read(w_current, object_list, line,
release_ver, fileformat_ver);
/* this is necessary because complex may add attributes which float */
@@ -391,20 +409,21 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
break;
case(OBJ_TEXT):
- /* fgets(string, 1024, fp); string lines are now read inside: */
- object_list = (OBJECT *) o_text_read(w_current, object_list, buf,
- fp,
+ line = g_strdup(line);
+ object_list = (OBJECT *) o_text_read(w_current, object_list,
+ line, tb,
release_ver, fileformat_ver);
+ g_free(line);
break;
case(OBJ_PIN):
- object_list = (OBJECT *) o_pin_read(w_current, object_list, buf,
+ object_list = (OBJECT *) o_pin_read(w_current, object_list, line,
release_ver, fileformat_ver);
found_pin++;
break;
case(OBJ_ARC):
- object_list = (OBJECT *) o_arc_read(w_current, object_list, buf,
+ object_list = (OBJECT *) o_arc_read(w_current, object_list, line,
release_ver, fileformat_ver);
break;
@@ -412,7 +431,8 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
object_before_attr = object_list;
/* first is the fp */
/* 2nd is the object to get the attributes */
- object_list = (OBJECT *) o_read_attribs(w_current, fp, object_list,
+ object_list = (OBJECT *) o_read_attribs(w_current, object_list,
+ tb,
release_ver, fileformat_ver);
/* by now we have finished reading all the attributes */
@@ -452,7 +472,7 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
} else {
fprintf(stderr, "Read unexpected embedded "
"symbol start marker in [%s] :\n>>\n%s<<\n",
- filename, buf);
+ name, line);
}
break;
@@ -472,7 +492,7 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
} else {
fprintf(stderr, "Read unexpected embedded "
"symbol end marker in [%s] :\n>>\n%s<<\n",
- filename, buf);
+ name, line);
}
break;
@@ -482,7 +502,7 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
break;
case(INFO_FONT):
- o_text_set_info_font(buf);
+ o_text_set_info_font(line);
break;
case(COMMENT):
@@ -490,7 +510,7 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
break;
case(VERSION_CHAR):
- itemsread = sscanf(buf, "v %u %u\n", &release_ver, &fileformat_ver);
+ itemsread = sscanf(line, "v %u %u\n", &release_ver, &fileformat_ver);
/* 20030921 was the last version which did not have a fileformat */
/* version. The below latter test should not happen, but it is here */
@@ -503,18 +523,17 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
if (fileformat_ver < current_fileformat_ver)
{
s_log_message("Read an old format sym/sch file!\n"
- "Please run g[sym|sch]update on:\n[%s]\n", filename);
+ "Please run g[sym|sch]update on:\n[%s]\n", name);
}
break;
default:
fprintf(stderr, "Read garbage in [%s] :\n>>\n%s<<\n",
- filename, buf);
+ name, line);
break;
}
}
- fclose(fp);
/* Was the very last thing we read a complex and has it not been checked */
/* yet? This would happen if the complex is at the very end of the file */
@@ -530,8 +549,48 @@ OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
o_pin_update_whichend(w_current, return_head(object_list), found_pin);
}
}
+
+ tb = s_textbuffer_free(tb);
return(object_list);
+
+}
+
+/*! \brief Read a file
+ * \par Function Description
+ * This function reads a file in libgead format.
+ *
+ * \param [in,out] w_current The current TOPLEVEL structure.
+ * \param [in] object_list The object_list to read data to.
+ * \param [in] filename The filename to read from.
+ * \return object_list if successful read, or NULL on error.
+ */
+OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
+{
+ GError *err = NULL;
+ char *buffer = NULL;
+ size_t size;
+ OBJECT *result = NULL;
+
+ g_file_get_contents(filename, &buffer, &size, &err);
+
+ g_assert ((buffer == NULL && err != NULL)
+ || (buffer != NULL && err == NULL));
+
+ if (err != NULL)
+ {
+ /* Report error to user, and free error */
+ g_assert (buffer == NULL);
+ fprintf (stderr, "o_read: Unable to read file: [%s]\n", err->message);
+ g_error_free (err);
+ return NULL;
+ }
+
+ /* Parse file contents */
+ g_assert (buffer != NULL);
+ result = o_read_buffer (w_current, object_list, buffer, size, filename);
+ g_free (buffer);
+ return result;
}
/*! \brief Scale a set of lines.
diff --git a/libgeda/src/o_attrib.c b/libgeda/src/o_attrib.c
index 49cb79c..a0380ab 100644
--- a/libgeda/src/o_attrib.c
+++ b/libgeda/src/o_attrib.c
@@ -647,37 +647,42 @@ void o_attrib_detach_all(TOPLEVEL *w_current, OBJECT *object_list, OBJECT *main_
#endif
}
-/*! \brief Read attributes from a file.
+/*! \brief Read attributes from a buffer.
* \par Function Description
- * Read attributes from a file.
+ * Read attributes from a TextBuffer.
*
* \param [in] w_current The TOPLEVEL object.
- * \param [in] fp FILE pointer to read from.
* \param [out] object_to_get_attribs Storage for attributes.
+ * \param [in] tb The text buffer to read from.
* \param [in] release_ver libgeda release version number.
* \param [in] fileformat_ver file format version number.
* \return Pointer to object_to_get_attribs.
*/
-OBJECT *o_read_attribs(TOPLEVEL *w_current, FILE *fp, OBJECT *object_to_get_attribs,
+OBJECT *o_read_attribs(TOPLEVEL *w_current,
+ OBJECT *object_to_get_attribs,
+ TextBuffer *tb,
unsigned int release_ver, unsigned int fileformat_ver)
{
OBJECT *object_list=NULL;
- char buf[1024];
+ char *line = NULL;
char objtype;
int ATTACH=FALSE;
int saved_color = -1;
object_list = object_to_get_attribs;
- while ( fgets(buf, 1024, fp) != NULL) {
+ while (1) {
- sscanf(buf, "%c", &objtype);
+ line = s_textbuffer_next_line (tb);
+ if (line == NULL) break;
+
+ sscanf(line, "%c", &objtype);
switch (objtype) {
case(OBJ_LINE):
object_list = (OBJECT *) o_line_read(w_current,
object_list,
- buf,
+ line,
release_ver, fileformat_ver);
break;
@@ -685,21 +690,21 @@ OBJECT *o_read_attribs(TOPLEVEL *w_current, FILE *fp, OBJECT *object_to_get_attr
case(OBJ_NET):
object_list = (OBJECT *) o_net_read(w_current,
object_list,
- buf,
+ line,
release_ver, fileformat_ver);
break;
case(OBJ_BUS):
object_list = (OBJECT *) o_bus_read(w_current,
object_list,
- buf,
+ line,
release_ver, fileformat_ver);
break;
case(OBJ_BOX):
object_list = (OBJECT *) o_box_read(w_current,
object_list,
- buf,
+ line,
release_ver, fileformat_ver);
break;
@@ -707,7 +712,7 @@ OBJECT *o_read_attribs(TOPLEVEL *w_current, FILE *fp, OBJECT *object_to_get_attr
object_list = (OBJECT *) o_circle_read(
w_current,
object_list,
- buf,
+ line,
release_ver, fileformat_ver);
break;
@@ -717,7 +722,7 @@ OBJECT *o_read_attribs(TOPLEVEL *w_current, FILE *fp, OBJECT *object_to_get_attr
object_list = (OBJECT *) o_complex_read(
w_current,
object_list,
- buf,
+ line,
release_ver, fileformat_ver);
/* this is necessary because complex may add
@@ -730,24 +735,25 @@ OBJECT *o_read_attribs(TOPLEVEL *w_current, FILE *fp, OBJECT *object_to_get_attr
case(OBJ_PIN):
object_list = (OBJECT *) o_pin_read(w_current,
object_list,
- buf,
+ line,
release_ver, fileformat_ver);
break;
case(OBJ_ARC):
object_list = (OBJECT *) o_arc_read(w_current,
object_list,
- buf,
+ line,
release_ver, fileformat_ver);
break;
case(OBJ_TEXT):
- /* fgets(string, 1024, fp); text strings are now read inside: */
+ line = g_strdup (line);
object_list = (OBJECT *) o_text_read(w_current,
object_list,
- buf,
- fp,
+ line,
+ tb,
release_ver, fileformat_ver);
+ g_free (line);
saved_color = object_list->color;
ATTACH=TRUE;
diff --git a/libgeda/src/o_picture.c b/libgeda/src/o_picture.c
index e803ef5..91fa9d7 100644
--- a/libgeda/src/o_picture.c
+++ b/libgeda/src/o_picture.c
@@ -43,30 +43,32 @@
/*! \brief Create picture OBJECT from character string.
* \par Function Description
- * This function will get the description of a picture from the character
- * string <B>*buf</B>. The new picture is then added to the list of object of
- * which <B>*object_list</B> is the last element before the call.
- * The function returns the new last element, that is the added
- * picture object.
+ * This function will get the description of a picture from the
+ * character string <B>*first_line</B>. The new picture is then added
+ * to the list of object of which <B>*object_list</B> is the last
+ * element before the call. The function returns the new last
+ * element, that is the added picture object.
*
* \param [in] w_current The TOPLEVEL object.
* \param [out] object_list OBJECT list to create picture in.
- * \param [in] buf Character string with picture description.
- * \param [in] fp Picture file to read.
+ * \param [in] first_line Character string with picture description.
+ * \param [in] tb Text buffer to load embedded data from.
* \param [in] release_ver libgeda release version number.
* \param [in] fileformat_ver libgeda file format version number.
* \return A pointer to the new picture object.
*/
OBJECT *o_picture_read(TOPLEVEL *w_current, OBJECT *object_list,
- char buf[], FILE *fp,
- unsigned int release_ver,unsigned int fileformat_ver)
+ const char *first_line,
+ TextBuffer *tb,
+ unsigned int release_ver,
+ unsigned int fileformat_ver)
{
int x1, y1;
int width, height, angle;
gchar mirrored, embedded;
int num_conv;
gchar type;
- gchar buffer[MAX_TEXT_LINE_LENGTH];
+ gchar *line = NULL;
gchar *filename;
GdkPixbuf *pixbuf;
static char gdk_initialized=0;
@@ -79,12 +81,12 @@ OBJECT *o_picture_read(TOPLEVEL *w_current, OBJECT *object_list,
gdk_initialized = 1;
}
- num_conv = sscanf(buf, "%c %d %d %d %d %d %c %c\n",
+ num_conv = sscanf(first_line, "%c %d %d %d %d %d %c %c\n",
&type, &x1, &y1, &width, &height, &angle, &mirrored, &embedded);
if (num_conv != 8) {
- fprintf(stderr, "Error reading picture definition line: %s.\n", buf);
- s_log_message ("Error reading picture definition line: %s.\n", buf);
+ fprintf(stderr, "Error reading picture definition line: %s.\n", first_line);
+ s_log_message ("Error reading picture definition line: %s.\n", first_line);
}
/* Convert from ascii character to number */
@@ -137,11 +139,9 @@ OBJECT *o_picture_read(TOPLEVEL *w_current, OBJECT *object_list,
}
- fgets(buffer, 1024, fp);
-
- filename = g_strdup (buffer);
+ filename = g_strdup(s_textbuffer_next_line(tb));
filename = remove_last_nl(filename);
-
+
pixbuf = NULL;
if (embedded == 0) {
@@ -160,10 +160,12 @@ OBJECT *o_picture_read(TOPLEVEL *w_current, OBJECT *object_list,
/* Read the encoded picture */
do {
- finished = 0;
- fgets(buffer, 1024, fp);
- if (g_strcasecmp(buffer, ".\n") != 0) {
- encoded_picture=g_string_append (encoded_picture, buffer);
+
+ line = s_textbuffer_next_line(tb);
+ if (line == NULL) break;
+
+ if (g_strcasecmp(line, ".\n") != 0) {
+ encoded_picture=g_string_append (encoded_picture, line);
encoded_picture=g_string_append (encoded_picture, "\n");
}
else {
diff --git a/libgeda/src/o_text_basic.c b/libgeda/src/o_text_basic.c
index cd5eff2..85a26d7 100644
--- a/libgeda/src/o_text_basic.c
+++ b/libgeda/src/o_text_basic.c
@@ -1013,7 +1013,9 @@ void o_text_recalc(TOPLEVEL *w_current, OBJECT *o_current)
*
*/
OBJECT *o_text_read(TOPLEVEL *w_current, OBJECT *object_list,
- char buf[], FILE *fp, unsigned int release_ver,
+ const char *first_line,
+ TextBuffer *tb,
+ unsigned int release_ver,
unsigned int fileformat_ver)
{
char type;
@@ -1030,21 +1032,21 @@ OBJECT *o_text_read(TOPLEVEL *w_current, OBJECT *object_list,
GString *textstr;
if (fileformat_ver == 1) {
- sscanf(buf, "%c %d %d %d %d %d %d %d %d %d\n", &type, &x, &y,
+ sscanf(first_line, "%c %d %d %d %d %d %d %d %d %d\n", &type, &x, &y,
&color, &size,
&visibility, &show_name_value,
&angle, &alignment, &num_lines);
} else if (release_ver < VERSION_20000220) {
/* yes, above less than (not less than and equal) is correct. The format */
/* change occurred in 20000220 */
- sscanf(buf, "%c %d %d %d %d %d %d %d\n", &type, &x, &y,
+ sscanf(first_line, "%c %d %d %d %d %d %d %d\n", &type, &x, &y,
&color, &size,
&visibility, &show_name_value,
&angle);
alignment = LOWER_LEFT; /* older versions didn't have this */
num_lines = 1; /* only support a single line */
} else {
- sscanf(buf, "%c %d %d %d %d %d %d %d %d\n", &type, &x, &y,
+ sscanf(first_line, "%c %d %d %d %d %d %d %d %d\n", &type, &x, &y,
&color, &size,
&visibility, &show_name_value,
&angle, &alignment);
@@ -1095,8 +1097,8 @@ OBJECT *o_text_read(TOPLEVEL *w_current, OBJECT *object_list,
}
if (color < 0 || color > MAX_COLORS) {
- fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
- s_log_message("Found an invalid color [ %s ]\n", buf);
+ fprintf(stderr, "Found an invalid color [ %s ]\n", first_line);
+ s_log_message("Found an invalid color [ %s ]\n", first_line);
s_log_message("Setting color to WHITE\n");
color = WHITE;
}
@@ -1105,11 +1107,14 @@ OBJECT *o_text_read(TOPLEVEL *w_current, OBJECT *object_list,
textstr = g_string_new ("");
for (i = 0; i < num_lines; i++) {
- gchar buffer[MAX_TEXT_LINE_LENGTH];
+ gchar *line;
- fgets (buffer, MAX_TEXT_LINE_LENGTH, fp);
+ line = s_textbuffer_next_line (tb);
- textstr = g_string_append (textstr, buffer);
+ if (line != NULL)
+ {
+ textstr = g_string_append (textstr, line);
+ }
}
/* retrieve the character string from the GString */
string = g_string_free (textstr, FALSE);
_______________________________________________
geda-dev mailing list
geda-dev@moria.seul.org
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev