1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
36 #include "../include/prototype.h"
38 #ifdef HAVE_LIBDMALLOC
42 /*! \brief Current version string */
43 #define VERSION_20020825 20020825
45 /*! \brief Save embedded attributes to current file
46 * \par Function Description
47 * This function will save all embedded attributes to a file.
49 * \param [in,out] w_current
50 * \param [in] object_list The list of attributes to write to file
51 * \param [in] fp The file to write to.
53 void o_save_embedded(TOPLEVEL
*w_current
, OBJECT
*object_list
, FILE *fp
)
55 OBJECT
*o_current
=NULL
;
58 /* make sure you init net_consolide to false (default) in all */
60 if (w_current
->net_consolidate
== TRUE
) {
61 o_net_consolidate(w_current
);
64 o_current
= object_list
;
66 while ( o_current
!= NULL
) {
68 if (o_current
->type
!= OBJ_HEAD
) {
70 if (o_current
->attribute
== 0) {
72 switch (o_current
->type
) {
75 out
= (char *) o_line_save(o_current
);
79 out
= (char *) o_net_save(o_current
);
83 out
= (char *) o_bus_save(o_current
);
87 out
= (char *) o_box_save(o_current
);
91 out
= (char *) o_circle_save(o_current
);
95 out
= (char *) o_complex_save(o_current
);
96 if (o_complex_is_embedded(o_current
)) {
109 case(OBJ_PLACEHOLDER
): /* new type by SDB 1.20.2005 */
110 out
= (char *) o_complex_save(o_current
);
114 out
= (char *) o_text_save(o_current
);
118 out
= (char *) o_pin_save(o_current
);
122 out
= (char *) o_arc_save(o_current
);
126 out
= (char *) o_picture_save(o_current
);
130 fprintf(stderr
, "Error type!\n");
135 /* output the line */
136 fprintf(fp
, "%s\n", out
);
139 /* save those attributes */
140 if (o_current
->attribs
!= NULL
) {
141 if (o_current
->attribs
->next
!= NULL
) {
142 o_save_attribs(fp
, o_current
->attribs
->next
);
148 o_current
= o_current
->next
;
152 /*! \brief Write libgeda file header
153 * \par Function Description
154 * This function simply prints the DATE_VERSION and FILEFORMAT_VERSION
155 * definitions to the file.
157 * \param [in] fp The file to write the header to.
159 void o_save_write_header(FILE *fp
)
161 fprintf(fp
, "v %s %u\n", DATE_VERSION
, FILEFORMAT_VERSION
);
164 /*! \brief Save a file
165 * \par Function Description
166 * This function saves the data in a libgeda format to a file
167 * \param [in] w_current The data to save to file.
168 * \param [in] filename The filename to save the data to.
169 * \return 1 on success, 0 on failure.
171 int o_save(TOPLEVEL
*w_current
, const char *filename
)
173 OBJECT
*o_current
=NULL
;
178 fp
= fopen(filename
, "wb");
181 s_log_message("o_save: Could not open [%s]\n", filename
);
186 o_current
= w_current
->page_current
->object_head
;
188 /* make sure you init net_consolide to false (default) in all */
190 if (w_current
->net_consolidate
== TRUE
) {
191 o_net_consolidate(w_current
);
194 o_save_write_header(fp
);
196 while ( o_current
!= NULL
) {
198 if (o_current
->type
!= OBJ_HEAD
) {
200 if (o_current
->attribute
== 0) {
202 switch (o_current
->type
) {
205 out
= (char *) o_line_save(o_current
);
209 out
= (char *) o_net_save(o_current
);
213 out
= (char *) o_bus_save(o_current
);
217 out
= (char *) o_box_save(o_current
);
221 out
= (char *) o_circle_save(o_current
);
225 out
= (char *) o_complex_save(o_current
);
226 fprintf(fp
, "%s\n", out
);
228 g_free(out
); /* need to free here because of the above flag */
229 if (o_complex_is_embedded(o_current
)) {
242 case(OBJ_PLACEHOLDER
): /* new type by SDB 1.20.2005 */
243 out
= (char *) o_complex_save(o_current
);
247 out
= (char *) o_text_save(o_current
);
251 out
= (char *) o_pin_save(o_current
);
255 out
= (char *) o_arc_save(o_current
);
259 out
= (char *) o_picture_save(o_current
);
263 fprintf(stderr
, "Error type!\n");
268 /* output the line */
269 if (!already_wrote
) {
270 fprintf(fp
, "%s\n", out
);
276 /* save those attributes */
277 if (o_current
->attribs
!= NULL
) {
278 if (o_current
->attribs
->next
!= NULL
) {
279 o_save_attribs(fp
, o_current
->attribs
->next
);
285 o_current
= o_current
->next
;
292 /*! \brief Read a memory buffer
293 * \par Function Description
294 * This function reads data in libgeda format from a memory buffer.
296 * If the size argument is negative, the buffer is assumed to be
299 * The name argument is used for debugging, and should be set to a
300 * meaningful string (e.g. the name of the file the data is from).
302 * \param [in,out] w_current The current TOPLEVEL structure.
303 * \param [in] object_list The object_list to read data to.
304 * \param [in] buffer The memory buffer to read from.
305 * \param [in] size The size of the buffer.
306 * \param [in] name The name to describe the data with.
307 * \return object_list if successful read, or NULL on error.
309 OBJECT
*o_read_buffer(TOPLEVEL
*w_current
, OBJECT
*object_list
,
310 char *buffer
, const int size
,
314 TextBuffer
*tb
= NULL
;
317 OBJECT
*object_list_save
=NULL
;
318 OBJECT
*temp_tail
=NULL
;
319 OBJECT
*temp_parent
=NULL
;
320 OBJECT
*object_before_attr
=NULL
;
321 unsigned int release_ver
;
322 unsigned int fileformat_ver
;
323 unsigned int current_fileformat_ver
;
325 OBJECT
* last_complex
= NULL
;
328 int embedded_level
= 0;
331 /* fill version with default file format version (the current one) */
332 current_fileformat_ver
= FILEFORMAT_VERSION
;
334 if (buffer
== NULL
) {
335 s_log_message("o_read_buffer: Received NULL buffer\n");
339 tb
= s_textbuffer_new (buffer
, size
);
340 g_assert (tb
!= NULL
);
344 line
= s_textbuffer_next_line(tb
);
345 if (line
== NULL
) break;
347 sscanf(line
, "%c", &objtype
);
349 /* Do we need to check the symbol version? Yes, but only if */
350 /* 1) the last object read was a complex and */
351 /* 2) the next object isn't the start of attributes. */
352 /* If the next object is the start of attributes, then check the */
353 /* symbol version after the attributes have been read in, see the */
354 /* STARTATTACH_ATTR case */
355 if (last_complex
&& objtype
!= STARTATTACH_ATTR
)
358 /* verify symbol version (not file format but rather contents) */
359 o_complex_check_symversion(w_current
, last_complex
);
360 last_complex
= NULL
; /* no longer need to check */
366 object_list
= (OBJECT
*) o_line_read(w_current
, object_list
, line
,
367 release_ver
, fileformat_ver
);
372 object_list
= (OBJECT
*) o_net_read(w_current
, object_list
, line
,
373 release_ver
, fileformat_ver
);
377 object_list
= (OBJECT
*) o_bus_read(w_current
, object_list
, line
,
378 release_ver
, fileformat_ver
);
382 object_list
= (OBJECT
*) o_box_read(w_current
, object_list
, line
,
383 release_ver
, fileformat_ver
);
387 line
= g_strdup(line
);
388 object_list
= (OBJECT
*) o_picture_read(w_current
, object_list
,
390 release_ver
, fileformat_ver
);
395 object_list
= (OBJECT
*) o_circle_read(w_current
, object_list
, line
,
396 release_ver
, fileformat_ver
);
400 case(OBJ_PLACEHOLDER
):
401 object_list
= (OBJECT
*) o_complex_read(w_current
, object_list
, line
,
402 release_ver
, fileformat_ver
);
404 /* this is necessary because complex may add attributes which float */
406 object_list
= (OBJECT
*) return_tail(object_list
);
408 /* last_complex is used for verifying symversion attribute */
409 last_complex
= object_list
;
413 line
= g_strdup(line
);
414 object_list
= (OBJECT
*) o_text_read(w_current
, object_list
,
416 release_ver
, fileformat_ver
);
421 object_list
= (OBJECT
*) o_pin_read(w_current
, object_list
, line
,
422 release_ver
, fileformat_ver
);
427 object_list
= (OBJECT
*) o_arc_read(w_current
, object_list
, line
,
428 release_ver
, fileformat_ver
);
431 case(STARTATTACH_ATTR
):
432 object_before_attr
= object_list
;
433 /* first is the fp */
434 /* 2nd is the object to get the attributes */
435 object_list
= (OBJECT
*) o_read_attribs(w_current
, object_list
,
437 release_ver
, fileformat_ver
);
439 /* by now we have finished reading all the attributes */
440 /* did we just finish attaching to a complex object? */
444 /* verify symbol version (not file format but rather contents) */
445 o_complex_check_symversion(w_current
, last_complex
);
449 /* slots only apply to complex objects */
450 if (object_before_attr
->type
== OBJ_COMPLEX
||
451 object_before_attr
->type
== OBJ_PLACEHOLDER
) {
452 o_attrib_slot_update(w_current
, object_before_attr
);
455 /* need this? nope */
456 /*object_list = return_tail(object_list);*/
457 object_before_attr
= NULL
;
460 case(START_EMBEDDED
):
462 if(object_list
->type
== OBJ_COMPLEX
||
463 object_list
->type
== OBJ_PLACEHOLDER
) {
465 object_list_save
= object_list
;
466 object_list
= object_list_save
->complex->prim_objs
;
468 temp_tail
= w_current
->page_current
->object_tail
;
469 temp_parent
= w_current
->page_current
->object_parent
;
470 w_current
->page_current
->object_parent
= object_list
;
474 fprintf(stderr
, "Read unexpected embedded "
475 "symbol start marker in [%s] :\n>>\n%s<<\n",
481 if(embedded_level
>0) {
482 object_list
= object_list_save
;
483 /* don't do this since objects are already
484 * stored/read translated
485 * o_complex_world_translate(w_current, object_list->x,
486 * object_list->y, object_list->complex);
488 w_current
->page_current
->object_tail
= temp_tail
;
489 w_current
->page_current
->object_parent
= temp_parent
;
491 o_complex_recalc( w_current
, object_list
);
494 fprintf(stderr
, "Read unexpected embedded "
495 "symbol end marker in [%s] :\n>>\n%s<<\n",
501 case(ENDATTACH_ATTR
):
502 /* this case is never hit, since the } is consumed by o_read_attribs */
506 o_text_set_info_font(line
);
514 itemsread
= sscanf(line
, "v %u %u\n", &release_ver
, &fileformat_ver
);
516 /* 20030921 was the last version which did not have a fileformat */
517 /* version. The below latter test should not happen, but it is here */
518 /* just in in case. */
519 if (release_ver
<= VERSION_20030921
|| itemsread
== 1)
524 if (fileformat_ver
< current_fileformat_ver
)
526 s_log_message("Read an old format sym/sch file!\n"
527 "Please run g[sym|sch]update on:\n[%s]\n", name
);
532 fprintf(stderr
, "Read garbage in [%s] :\n>>\n%s<<\n",
539 /* Was the very last thing we read a complex and has it not been checked */
540 /* yet? This would happen if the complex is at the very end of the file */
541 /* and had no attached attributes */
544 o_complex_check_symversion(w_current
, last_complex
);
545 last_complex
= NULL
; /* no longer need to check */
549 if (release_ver
<= VERSION_20020825
) {
550 o_pin_update_whichend(w_current
, return_head(object_list
), found_pin
);
554 tb
= s_textbuffer_free(tb
);
560 /*! \brief Read a file
561 * \par Function Description
562 * This function reads a file in libgeda format.
564 * \param [in,out] w_current The current TOPLEVEL structure.
565 * \param [in] object_list The object_list to read data to.
566 * \param [in] filename The filename to read from.
567 * \return object_list if successful read, or NULL on error.
569 OBJECT
*o_read(TOPLEVEL
*w_current
, OBJECT
*object_list
, char *filename
)
574 OBJECT
*result
= NULL
;
576 g_file_get_contents(filename
, &buffer
, &size
, &err
);
578 g_assert ((buffer
== NULL
&& err
!= NULL
)
579 || (buffer
!= NULL
&& err
== NULL
));
583 /* Report error to user, and free error */
584 g_assert (buffer
== NULL
);
585 fprintf (stderr
, "o_read: Unable to read file: [%s]\n", err
->message
);
590 /* Parse file contents */
591 g_assert (buffer
!= NULL
);
592 result
= o_read_buffer (w_current
, object_list
, buffer
, size
, filename
);
597 /*! \brief Scale a set of lines.
598 * \par Function Description
599 * This function takes a list of lines and scales them
600 * by the values of x_scale and y_scale.
602 * \param [in] w_current The current TOPLEVEL object.
603 * \param [in,out] list The list with lines to scale.
604 * \param [in] x_scale The x scale value for the lines.
605 * \param [in] y_scale The y scale value for the lines.
607 * \todo this really doesn't belong here. you need more of a core routine
608 * first. yes.. this is the core routine, just strip out the drawing
610 * move it to o_complex_scale
612 void o_scale(TOPLEVEL
*w_current
, OBJECT
*list
, int x_scale
, int y_scale
)
616 /* this is okay if you just hit scale and have nothing selected */
618 /* w_current->event_state = SELECT;*/
619 /* i_update_status(w_current, "Select Mode"); not here */
620 /* w_current->inside_action = 0;*/
628 while (o_current
!= NULL
) {
630 switch(o_current
->type
) {
633 /* erase the current selection */
634 w_current
->override_color
=
635 w_current
->background_color
;
636 o_redraw_single(w_current
, o_current
);
637 /* o_line_draw(w_current, o_current);*/
638 w_current
->override_color
= -1;
640 o_line_scale_world(w_current
,
641 x_scale
, y_scale
, o_current
);
645 o_current
= o_current
->next
;
648 /* don't do this at this level */
649 /* w_current->page_current->CHANGED=1;*/