1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * \brief basic libgeda read and write functions
32 #include "libgeda_priv.h"
34 #ifdef HAVE_LIBDMALLOC
38 /*! \brief Get the file header string.
39 * \par Function Description
40 * This function simply returns the DATE_VERSION and
41 * FILEFORMAT_VERSION formatted as a gEDA file header.
43 * \warning <em>Do not</em> free the returned string.
45 const gchar
*o_file_format_header()
47 static gchar
*header
= NULL
;
50 header
= g_strdup_printf("v %s %u\n", PACKAGE_DATE_VERSION
,
56 /*! \brief "Save" a file into a string buffer
57 * \par Function Description
58 * This function saves a whole schematic into a buffer in libgeda
59 * format. The buffer should be freed when no longer needed.
61 * \param [in] toplevel The current TOPLEVEL.
62 * \param [in] object_list The head of a GList of OBJECTs to save.
63 * \returns a buffer containing schematic data or NULL on failure.
65 gchar
*o_save_buffer (TOPLEVEL
*toplevel
, const GList
*object_list
)
70 if (toplevel
== NULL
) return NULL
;
72 acc
= g_string_new (o_file_format_header());
74 buffer
= o_save_objects (toplevel
, object_list
, FALSE
);
75 g_string_append (acc
, buffer
);
78 return g_string_free (acc
, FALSE
);
81 /*! \brief Save a series of objects into a string buffer
82 * \par Function Description
83 * This function recursively saves a set of objects into a buffer in
84 * libgeda format. User code should not normally call this function;
85 * they should call o_save_buffer() instead.
87 * With save_attribs passed as FALSE, attribute objects are skipped over,
88 * and saved separately - after the objects they are attached to. When
89 * we recurse for saving out those attributes, the function must be called
90 * with save_attribs passed as TRUE.
92 * \param [in] toplevel A TOPLEVEL structure.
93 * \param [in] object_list The head of a GList of objects to save.
94 * \param [in] save_attribs Should attribute objects encounterd be saved?
95 * \returns a buffer containing schematic data or NULL on failure.
97 gchar
*o_save_objects (TOPLEVEL
*toplevel
, const GList
*object_list
, gboolean save_attribs
)
103 gboolean already_wrote
= FALSE
;
105 acc
= g_string_new("");
109 while ( iter
!= NULL
) {
110 o_current
= (OBJECT
*)iter
->data
;
112 if (save_attribs
|| o_current
->attached_to
== NULL
) {
114 switch (o_current
->type
) {
117 out
= o_line_save(toplevel
, o_current
);
121 out
= o_net_save(toplevel
, o_current
);
125 out
= o_bus_save(toplevel
, o_current
);
129 out
= o_box_save(toplevel
, o_current
);
133 out
= o_circle_save(toplevel
, o_current
);
137 out
= o_complex_save(toplevel
, o_current
);
138 g_string_append_printf(acc
, "%s\n", out
);
139 already_wrote
= TRUE
;
140 g_free(out
); /* need to free here because of the above flag */
142 if (o_complex_is_embedded(o_current
)) {
143 g_string_append(acc
, "[\n");
145 out
= o_save_objects(toplevel
, o_current
->complex->prim_objs
, FALSE
);
146 g_string_append (acc
, out
);
149 g_string_append(acc
, "]\n");
153 case(OBJ_PLACEHOLDER
): /* new type by SDB 1.20.2005 */
154 out
= o_complex_save(toplevel
, o_current
);
158 out
= o_text_save(toplevel
, o_current
);
162 out
= o_path_save(toplevel
, o_current
);
166 out
= o_pin_save(toplevel
, o_current
);
170 out
= o_arc_save(toplevel
, o_current
);
174 out
= o_picture_save(toplevel
, o_current
);
178 /*! \todo Maybe we can continue instead of just failing
179 * completely? In any case, failing gracefully is better
180 * than killing the program, which is what this used to
182 g_critical (_("o_save_objects: object %p has unknown type '%c'\n"),
183 o_current
, o_current
->type
);
184 /* Dump string built so far */
185 g_string_free (acc
, TRUE
);
189 /* output the line */
190 if (!already_wrote
) {
191 g_string_append_printf(acc
, "%s\n", out
);
194 already_wrote
= FALSE
;
197 /* save any attributes */
198 if (o_current
->attribs
!= NULL
) {
199 g_string_append (acc
, "{\n");
201 out
= o_save_objects (toplevel
, o_current
->attribs
, TRUE
);
202 g_string_append (acc
, out
);
205 g_string_append (acc
, "}\n");
209 iter
= g_list_next (iter
);
212 return g_string_free (acc
, FALSE
);
215 /*! \brief Save a file
216 * \par Function Description
217 * This function saves the data in a libgeda format to a file
219 * \bug g_access introduces a race condition in certain cases, but
220 * solves bug #698565 in the normal use-case
222 * \param [in] toplevel The current TOPLEVEL.
223 * \param [in] object_list The head of a GList of OBJECTs to save.
224 * \param [in] filename The filename to save the data to.
225 * \param [in,out] err #GError structure for error reporting.
226 * \return 1 on success, 0 on failure.
228 int o_save (TOPLEVEL
*toplevel
, const GList
*object_list
,
229 const char *filename
, GError
**err
)
233 /* Check to see if real filename is writable; if file doesn't exists
234 we assume all is well */
235 if (g_file_test(filename
, G_FILE_TEST_EXISTS
) &&
236 g_access(filename
, W_OK
) != 0) {
237 g_set_error (err
, G_FILE_ERROR
, G_FILE_ERROR_PERM
,
238 _("File %s is read-only"), filename
);
242 buffer
= o_save_buffer (toplevel
, object_list
);
243 if (!g_file_set_contents (filename
, buffer
, strlen(buffer
), err
)) {
252 /*! \brief Read a memory buffer
253 * \par Function Description
254 * This function reads data in libgeda format from a memory buffer.
256 * If the size argument is negative, the buffer is assumed to be
259 * The name argument is used for debugging, and should be set to a
260 * meaningful string (e.g. the name of the file the data is from).
262 * \param [in,out] toplevel The current TOPLEVEL structure.
263 * \param [in] object_list The object_list to read data to.
264 * \param [in] buffer The memory buffer to read from.
265 * \param [in] size The size of the buffer.
266 * \param [in] name The name to describe the data with.
267 * \return GList of objects if successful read, or NULL on error.
269 GList
*o_read_buffer (TOPLEVEL
*toplevel
, GList
*object_list
,
270 char *buffer
, const int size
,
274 TextBuffer
*tb
= NULL
;
277 GList
*object_list_save
=NULL
;
278 OBJECT
*new_obj
=NULL
;
281 unsigned int release_ver
;
282 unsigned int fileformat_ver
;
283 unsigned int current_fileformat_ver
;
285 OBJECT
* last_complex
= NULL
;
288 int embedded_level
= 0;
291 /* fill version with default file format version (the current one) */
292 current_fileformat_ver
= FILEFORMAT_VERSION
;
294 g_return_val_if_fail ((buffer
!= NULL
), NULL
);
296 tb
= s_textbuffer_new (buffer
, size
);
298 object_list
= g_list_reverse (object_list
);
302 line
= s_textbuffer_next_line(tb
);
303 if (line
== NULL
) break;
305 sscanf(line
, "%c", &objtype
);
307 /* Do we need to check the symbol version? Yes, but only if */
308 /* 1) the last object read was a complex and */
309 /* 2) the next object isn't the start of attributes. */
310 /* If the next object is the start of attributes, then check the */
311 /* symbol version after the attributes have been read in, see the */
312 /* STARTATTACH_ATTR case */
313 if (last_complex
&& objtype
!= STARTATTACH_ATTR
)
316 /* verify symbol version (not file format but rather contents) */
317 o_complex_check_symversion(toplevel
, last_complex
);
318 last_complex
= NULL
; /* no longer need to check */
324 new_obj
= o_line_read (toplevel
, line
, release_ver
, fileformat_ver
);
325 object_list
= g_list_prepend (object_list
, new_obj
);
330 new_obj
= o_net_read (toplevel
, line
, release_ver
, fileformat_ver
);
331 object_list
= g_list_prepend (object_list
, new_obj
);
335 new_obj
= o_bus_read (toplevel
, line
, release_ver
, fileformat_ver
);
336 object_list
= g_list_prepend (object_list
, new_obj
);
340 new_obj
= o_box_read (toplevel
, line
, release_ver
, fileformat_ver
);
341 object_list
= g_list_prepend (object_list
, new_obj
);
345 line
= g_strdup (line
);
346 new_obj
= o_picture_read (toplevel
, line
, tb
, release_ver
, fileformat_ver
);
348 object_list
= g_list_prepend (object_list
, new_obj
);
352 new_obj
= o_circle_read (toplevel
, line
, release_ver
, fileformat_ver
);
353 object_list
= g_list_prepend (object_list
, new_obj
);
357 case(OBJ_PLACEHOLDER
):
358 new_obj
= o_complex_read (toplevel
, line
, release_ver
, fileformat_ver
);
359 object_list
= g_list_prepend (object_list
, new_obj
);
361 /* last_complex is used for verifying symversion attribute */
362 last_complex
= new_obj
;
366 line
= g_strdup (line
);
367 new_obj
= o_text_read (toplevel
, line
, tb
, release_ver
, fileformat_ver
);
369 object_list
= g_list_prepend (object_list
, new_obj
);
373 line
= g_strdup(line
);
374 new_obj
= o_path_read (toplevel
, line
, tb
, release_ver
, fileformat_ver
);
376 object_list
= g_list_prepend (object_list
, new_obj
);
380 new_obj
= o_pin_read (toplevel
, line
, release_ver
, fileformat_ver
);
381 object_list
= g_list_prepend (object_list
, new_obj
);
386 new_obj
= o_arc_read (toplevel
, line
, release_ver
, fileformat_ver
);
387 object_list
= g_list_prepend (object_list
, new_obj
);
390 case(STARTATTACH_ATTR
):
391 /* first is the fp */
392 /* 2nd is the object to get the attributes */
393 new_obj_list
= o_read_attribs (toplevel
, NULL
, new_obj
, tb
, release_ver
, fileformat_ver
);
394 new_obj_list
= g_list_reverse (new_obj_list
);
395 object_list
= g_list_concat (new_obj_list
, object_list
);
397 /* by now we have finished reading all the attributes */
398 /* did we just finish attaching to a complex object? */
402 /* verify symbol version (not file format but rather contents) */
403 o_complex_check_symversion(toplevel
, last_complex
);
407 /* slots only apply to complex objects */
408 if (new_obj
!= NULL
&&
409 (new_obj
->type
== OBJ_COMPLEX
||
410 new_obj
->type
== OBJ_PLACEHOLDER
)) {
411 s_slot_update_object (toplevel
, new_obj
);
417 case(START_EMBEDDED
):
418 new_obj
= object_list
->data
;
420 if (new_obj
!= NULL
&&
421 (new_obj
->type
== OBJ_COMPLEX
||
422 new_obj
->type
== OBJ_PLACEHOLDER
)) {
424 object_list_save
= object_list
;
425 object_list
= new_obj
->complex->prim_objs
;
429 fprintf(stderr
, _("Read unexpected embedded "
430 "symbol start marker in [%s] :\n>>\n%s<<\n"),
436 if (embedded_level
>0) {
437 /* don't do this since objects are already
438 * stored/read translated
439 * o_complex_translate_world (toplevel, object_list->x,
440 * object_list->y, object_list->complex);
442 object_list
= g_list_reverse (object_list
);
444 new_obj
= object_list_save
->data
;
445 new_obj
->complex->prim_objs
= object_list
;
446 object_list
= object_list_save
;
448 /* set the parent field now */
449 for (iter
= new_obj
->complex->prim_objs
;
450 iter
!= NULL
; iter
= g_list_next (iter
)) {
451 OBJECT
*tmp
= iter
->data
;
452 tmp
->parent
= new_obj
;
455 o_recalc_single_object (toplevel
, new_obj
);
459 fprintf(stderr
, _("Read unexpected embedded "
460 "symbol end marker in [%s] :\n>>\n%s<<\n"),
465 case(ENDATTACH_ATTR
):
466 /* this case is never hit, since the } is consumed by o_read_attribs */
478 itemsread
= sscanf(line
, "v %u %u\n", &release_ver
, &fileformat_ver
);
480 /* 20030921 was the last version which did not have a fileformat */
481 /* version. The below latter test should not happen, but it is here */
482 /* just in in case. */
483 if (release_ver
<= VERSION_20030921
|| itemsread
== 1) {
487 if (fileformat_ver
== 0) {
488 s_log_message(_("Read an old format sym/sch file!\n"
489 "Please run g[sym|sch]update on:\n[%s]\n"), name
);
494 fprintf(stderr
, _("Read garbage in [%s] :\n>>\n%s<<\n"),
502 /* Was the very last thing we read a complex and has it not been checked */
503 /* yet? This would happen if the complex is at the very end of the file */
504 /* and had no attached attributes */
507 o_complex_check_symversion(toplevel
, last_complex
);
508 last_complex
= NULL
; /* no longer need to check */
512 if (release_ver
<= VERSION_20020825
) {
513 o_pin_update_whichend (toplevel
, object_list
, found_pin
);
517 tb
= s_textbuffer_free(tb
);
519 object_list
= g_list_reverse (object_list
);
525 /*! \brief Read a file
526 * \par Function Description
527 * This function reads a file in libgeda format.
529 * \param [in,out] toplevel The current TOPLEVEL structure.
530 * \param [in] object_list The object_list to read data to.
531 * \param [in] filename The filename to read from.
532 * \param [in,out] err #GError structure for error reporting, or
533 * NULL to disable error reporting
534 * \return object_list if successful read, or NULL on error.
536 GList
*o_read (TOPLEVEL
*toplevel
, GList
*object_list
, char *filename
,
543 /* Return NULL if error reporting is enabled and the return location
544 * for an error isn't NULL. */
545 g_return_val_if_fail (err
== NULL
|| *err
== NULL
, NULL
);
547 if (!g_file_get_contents(filename
, &buffer
, &size
, err
)) {
551 /* Parse file contents */
552 result
= o_read_buffer (toplevel
, object_list
, buffer
, size
, filename
);
557 /*! \brief Scale a set of lines.
558 * \par Function Description
559 * This function takes a list of lines and scales them
560 * by the values of x_scale and y_scale.
562 * \param [in] toplevel The current TOPLEVEL object.
563 * \param [in,out] list The list with lines to scale.
564 * \param [in] x_scale The x scale value for the lines.
565 * \param [in] y_scale The y scale value for the lines.
567 * \todo this really doesn't belong here. you need more of a core routine
568 * first. yes.. this is the core routine, just strip out the drawing
570 * move it to o_complex_scale
572 void o_scale (TOPLEVEL
*toplevel
, GList
*list
, int x_scale
, int y_scale
)
577 /* this is okay if you just hit scale and have nothing selected */
583 while (iter
!= NULL
) {
584 o_current
= (OBJECT
*)iter
->data
;
585 switch(o_current
->type
) {
587 o_line_scale_world(toplevel
, x_scale
, y_scale
, o_current
);
590 iter
= g_list_next (iter
);