2 * gEDA - GNU Electronic Design Automation
3 * This file is a part of gerbv.
5 * Copyright (C) 2000-2003 Stefan Petersen (spe@stacken.kth.se)
6 * Copyright (c) 2008 Dan McMahill
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
26 \brief routines for loading and saving project files
46 #ifdef HAVE_SYS_TYPES_H
47 #include <sys/types.h>
50 #ifdef HAVE_SYS_STAT_H
62 #include "gerb_file.h"
63 #include "lrealpath.h"
65 #include "scheme-private.h"
67 #include "interface.h"
72 * update this if the project file format changes.
74 * The format *must* be major.minor[A-Z]
76 * Do *not* update this simply because we have a new gerbv
79 * If you bump this version, then you must also bump the
80 * version of gerbv. For example, supplse the file version
81 * is 2.0A and gerbv has 2.4B in configure.ac. If you change
82 * the file format version, you should change both the version
83 * here *and* configure.ac to 2.4C.
86 #define GERBV_PROJECT_FILE_VERSION "2.0A"
88 /* default version for project files that do not specify a version.
89 * This is assumed for all older project files.
91 #define GERBV_DEFAULT_PROJECT_FILE_VERSION "1.9A"
94 * List of versions that we can load with this version of
97 static const char * known_versions
[] = {
103 /* DEBUG printing. #define DEBUG 1 in config.h to use this fcn. */
104 #define dprintf if(DEBUG) printf
106 static project_list_t
*plist_top
= NULL
;
109 /* When a project file is loaded, this variable is set to the
110 * version of the project file. That can be used by various
111 * functions which may need to do something different.
113 static int current_file_version
= 0;
117 * Converts a string like "2.1A" "2.12C" or "3.2ZA" to the int
121 version_str_to_int( const char * str
)
124 gchar
*dup
, *tmps
, *ptr
;
129 dprintf("%s(\"%s\")\n", __FUNCTION__
, str
);
133 * Extract out the major number (versions are strings like 2.1A)
134 * and we want the "2" here.
136 tmps
= g_strdup(str
);
138 while(*ptr
!= '\0' && *ptr
!= '.') { ptr
++; }
140 /* this should not have happened */
145 r
= 10000 * atoi(tmps
);
146 dprintf("%s(): Converted \"%s\" to r = %d\n", __FUNCTION__
, tmps
, r
);
151 * Extract out the minor number (versions are strings like 2.1A)
152 * and we want the "1" here.
158 while(*ptr
!= '\0' && *ptr
!= '.') { ptr
++; }
160 /* this should not have happened */
166 while(*ptr
!= '\0' && isdigit( (int) *ptr
)) { ptr
++; }
168 /* this should not have happened */
173 r
+= 100 * atoi(tmps
);
174 dprintf("%s(): Converted \"%s\" to r = %d\n", __FUNCTION__
, tmps
, r
);
179 * Extract out the revision letter(s) (versions are strings like 2.1A)
180 * and we want the "A" here.
187 while(*ptr
!= '\0' && (isdigit( (int) *ptr
) || *ptr
== '.') ) { ptr
++; }
189 /* this should not have happened */
194 dprintf("%s(): Processing \"%s\"\n", __FUNCTION__
, tmps
);
196 if( strlen(tmps
) == 1) {
197 r
+= *tmps
- 'A' + 1;
198 dprintf( "%s(): Converted \"%s\" to r = %d\n", __FUNCTION__
, tmps
, r
);
199 } else if( strlen(tmps
) == 2 ) {
203 r
+= *tmps
- 'A' + 1;
205 /* this should not have happened */
209 /* this should not have happened */
221 * convert the internal int we use for version numbers
222 * to the string that users can deal with
225 version_int_to_str( int ver
)
227 int major
, minor
, teeny
;
236 minor
= (ver
- 10000*major
) / 100;
237 teeny
= (ver
- 10000*major
- 100*minor
);
238 if(teeny
>= 1 && teeny
<= 26) {
239 l
[0] = 'A' + teeny
- 1;
240 } else if(teeny
> 26 && teeny
<= 52) {
242 l
[1] = 'A' + teeny
- 26 - 1;
245 str
= g_strdup_printf("%d.%d%s", major
, minor
, l
);
250 get_color(scheme
*sc
, pointer value
, int *color
)
255 if (!sc
->vptr
->is_vector(value
)) {
256 GERB_MESSAGE("Color parameter not a vector\n");
259 if (sc
->vptr
->vector_length(value
) != 3) {
260 GERB_MESSAGE("Color vector of incorrect length\n");
264 for (i
= 0; i
< 3; i
++) {
265 elem
= sc
->vptr
->vector_elem(value
, i
);
266 if (sc
->vptr
->is_integer(elem
) && sc
->vptr
->is_number(elem
))
267 color
[i
] = sc
->vptr
->ivalue(elem
);
270 GERB_MESSAGE("Illegal color in projectfile\n");
277 /* ----------------------------------------------------------------------
278 * Figure out the canonical name of the executed program
279 * and fix up the defaults for various paths. This is largely
280 * taken from InitPaths() in main.c from pcb.
282 static char *bindir
= NULL
;
283 static char *exec_prefix
= NULL
;
284 static char *pkgdatadir
= NULL
;
285 static gchar
*scmdatadir
= NULL
;
287 /* this really should not be needed but it could
288 * be hooked in to appease malloc debuggers as
289 * we don't otherwise free these variables. However,
290 * they only get malloc-ed once ever so this
291 * is a fixed leak of a small size.
297 if (bindir
!= NULL
) {
302 if (exec_prefix
!= NULL
) {
307 if (pkgdatadir
!= NULL
) {
312 if (scmdatadir
!= NULL
) {
322 init_paths (char *argv0
)
328 int found_bindir
= 0;
330 /* Only do this stuff once */
334 /* see if argv0 has enough of a path to let lrealpath give the
335 * real path. This should be the case if you invoke gerbv with
336 * something like /usr/local/bin/gerbv or ./gerbv or ./foo/gerbv
337 * but if you just use gerbv and it exists in your path, you'll
338 * just get back gerbv again.
342 for (i
= 0; i
< strlen (argv0
) ; i
++)
344 if (argv0
[i
] == GERBV_DIR_SEPARATOR_C
)
348 dprintf("%s (%s): haspath = %d\n", __FUNCTION__
, argv0
, haspath
);
351 bindir
= strdup (lrealpath (argv0
));
356 char *path
, *p
, *tmps
;
360 tmps
= getenv ("PATH");
364 path
= strdup (tmps
);
366 /* search through the font path for a font file */
367 for (p
= strtok (path
, GERBV_PATH_DELIMETER
); p
&& *p
;
368 p
= strtok (NULL
, GERBV_PATH_DELIMETER
))
370 dprintf ("Looking for %s in %s\n", argv0
, p
);
371 if ( (tmps
= malloc ( (strlen (argv0
) + strlen (p
) + 2) * sizeof (char))) == NULL
)
373 fprintf (stderr
, "%s(): malloc failed\n", __FUNCTION__
);
376 sprintf (tmps
, "%s%s%s", p
, GERBV_DIR_SEPARATOR_S
, argv0
);
377 r
= stat (tmps
, &sb
);
380 dprintf ("Found it: \"%s\"\n", tmps
);
381 bindir
= lrealpath (tmps
);
391 dprintf ("%s(): bindir = \"%s\"\n", __FUNCTION__
, bindir
);
396 /* strip off the executible name leaving only the path */
398 t1
= strchr (bindir
, GERBV_DIR_SEPARATOR_C
);
399 while (t1
!= NULL
&& *t1
!= '\0')
402 t1
= strchr (t2
+ 1, GERBV_DIR_SEPARATOR_C
);
406 dprintf ("After stripping off the executible name, we found\n");
407 dprintf ("bindir = \"%s\"\n", bindir
);
412 /* we have failed to find out anything from argv[0] so fall back to the original
415 bindir
= strdup (BINDIR
);
418 /* now find the path to exec_prefix */
419 l
= strlen (bindir
) + 1 + strlen (BINDIR_TO_EXECPREFIX
) + 1;
420 if ( (exec_prefix
= (char *) malloc (l
* sizeof (char) )) == NULL
)
422 fprintf (stderr
, "%s(): malloc failed\n", __FUNCTION__
);
425 sprintf (exec_prefix
, "%s%s%s", bindir
, GERBV_DIR_SEPARATOR_S
,
426 BINDIR_TO_EXECPREFIX
);
428 /* now find the path to PKGDATADIR */
429 l
= strlen (bindir
) + 1 + strlen (BINDIR_TO_PKGDATADIR
) + 1;
430 if ( (pkgdatadir
= (char *) malloc (l
* sizeof (char) )) == NULL
)
432 fprintf (stderr
, "%s(): malloc failed\n", __FUNCTION__
);
435 sprintf (pkgdatadir
, "%s%s%s", bindir
, GERBV_DIR_SEPARATOR_S
,
436 BINDIR_TO_PKGDATADIR
);
438 scmdatadir
= g_strdup_printf ("%s%s%s", pkgdatadir
, GERBV_DIR_SEPARATOR_S
, SCMSUBDIR
);
440 dprintf ("%s(): bindir = %s\n", __FUNCTION__
, bindir
);
441 dprintf ("%s(): exec_prefix = %s\n", __FUNCTION__
, exec_prefix
);
442 dprintf ("%s(): pkgdatadir = %s\n", __FUNCTION__
, pkgdatadir
);
443 dprintf ("%s(): scmdatadir = %s\n", __FUNCTION__
, scmdatadir
);
449 get_value_string(scheme
*sc
, pointer value
)
451 if (!sc
->vptr
->is_string(value
))
454 return sc
->vptr
->string_value(value
);
455 } /* get_value_string */
458 /** Conversion of '\' into '/' and vice versa for compatibility under WIN32
461 convert_path_separators(char* path
, int conv_flag
)
463 #if defined (__MINGW32__)
469 while ((hit_in_path
= strchr(path
, '\\'))) {
474 while ((hit_in_path
= strchr(path
, '/'))) {
482 }/* convert_path_separators */
486 define_layer(scheme
*sc
, pointer args
)
488 pointer car_el
, cdr_el
, name
, value
;
490 project_list_t
*plist_tmp
= NULL
;
492 dprintf("--> entering project.c:define_layer\n");
494 if (!sc
->vptr
->is_pair(args
)){
495 GERB_MESSAGE("define-layer!: Too few arguments\n");
499 car_el
= sc
->vptr
->pair_car(args
);
500 cdr_el
= sc
->vptr
->pair_cdr(args
);
502 if (!sc
->vptr
->is_integer(car_el
) || !sc
->vptr
->is_number(car_el
)) {
503 GERB_MESSAGE("define-layer!: Layer number missing/incorrect\n");
507 layerno
= sc
->vptr
->ivalue(car_el
);
508 dprintf(" layerno = %d\n", layerno
);
510 car_el
= sc
->vptr
->pair_car(cdr_el
);
511 cdr_el
= sc
->vptr
->pair_cdr(cdr_el
);
513 plist_tmp
= (project_list_t
*)g_malloc(sizeof(project_list_t
));
514 memset(plist_tmp
, 0, sizeof(project_list_t
));
515 plist_tmp
->next
= plist_top
;
516 plist_top
= plist_tmp
;
517 plist_top
->layerno
= layerno
;
518 plist_top
->visible
= 1;
519 plist_top
->n_attr
= 0;
520 plist_top
->attr_list
= NULL
;
522 while (sc
->vptr
->is_pair(car_el
)) {
524 name
= sc
->vptr
->pair_car(car_el
);
525 value
= sc
->vptr
->pair_cdr(car_el
);
527 if (!sc
->vptr
->is_symbol(name
)) {
528 GERB_MESSAGE("define-layer!:non-symbol found, ignoring\n");
529 goto end_name_value_parse
;
532 if (strcmp(sc
->vptr
->symname(name
), "color") == 0) {
533 get_color(sc
, value
, plist_top
->rgb
);
534 } else if (strcmp(sc
->vptr
->symname(name
), "filename") == 0) {
536 plist_top
->filename
= g_strdup(get_value_string(sc
, value
));
537 plist_top
->filename
= convert_path_separators(plist_top
->filename
,
539 plist_top
->is_pnp
= 0;
540 } else if (strcmp(sc
->vptr
->symname(name
), "pick_and_place") == 0) {
542 plist_top
->filename
= g_strdup(get_value_string(sc
, value
));
543 plist_top
->filename
= convert_path_separators(plist_top
->filename
,
545 plist_top
->is_pnp
= 1;
546 } else if (strcmp(sc
->vptr
->symname(name
), "inverted") == 0) {
547 if (value
== sc
->F
) {
548 plist_top
->inverted
= 0;
549 } else if (value
== sc
->T
) {
550 plist_top
->inverted
= 1;
552 GERB_MESSAGE("Argument to inverted must be #t or #f\n");
554 } else if (strcmp(sc
->vptr
->symname(name
), "visible") == 0) {
555 if (value
== sc
->F
) {
556 plist_top
->visible
= 0;
557 } else if (value
== sc
->T
) {
558 plist_top
->visible
= 1;
560 GERB_MESSAGE("Argument to visible must be #t or #f\n");
562 } else if (strcmp(sc
->vptr
->symname(name
), "attribs") == 0) {
563 pointer attr_car_el
, attr_cdr_el
;
564 pointer attr_name
, attr_type
, attr_value
;
567 dprintf ("Parsing file attributes\n");
569 attr_car_el
= sc
->vptr
->pair_car (value
);
570 attr_cdr_el
= sc
->vptr
->pair_cdr (value
);
571 while (sc
->vptr
->is_pair(attr_car_el
)) {
572 int p
= plist_top
->n_attr
;
574 plist_top
->attr_list
= (gerbv_HID_Attribute
*)
575 realloc (plist_top
->attr_list
,
576 plist_top
->n_attr
* sizeof (gerbv_HID_Attribute
));
577 if (plist_top
->attr_list
== NULL
) {
578 fprintf (stderr
, "%s(): realloc failed\n", __FUNCTION__
);
583 attr_name
= sc
->vptr
->pair_car(attr_car_el
);
586 attr_type
= sc
->vptr
->pair_cdr (attr_car_el
);
587 attr_type
= sc
->vptr
->pair_car (attr_type
);
590 attr_value
= sc
->vptr
->pair_cdr (attr_car_el
);
591 attr_value
= sc
->vptr
->pair_cdr (attr_value
);
592 attr_value
= sc
->vptr
->pair_car (attr_value
);
594 dprintf (" attribute %s, type is %s, value is ",
595 sc
->vptr
->symname(attr_name
),
596 sc
->vptr
->symname(attr_type
));
598 plist_top
->attr_list
[p
].name
= strdup (sc
->vptr
->symname (attr_name
));
600 type
= sc
->vptr
->symname (attr_type
);
602 if (strcmp (type
, "label") == 0) {
603 dprintf ("%s", sc
->vptr
->string_value (attr_value
));
604 plist_top
->attr_list
[p
].type
= HID_Label
;
605 plist_top
->attr_list
[p
].default_val
.str_value
=
606 strdup (sc
->vptr
->string_value (attr_value
));
608 } else if (strcmp (type
, "integer") == 0) {
609 dprintf ("%ld", sc
->vptr
->ivalue (attr_value
));
610 plist_top
->attr_list
[p
].type
= HID_Integer
;
611 plist_top
->attr_list
[p
].default_val
.int_value
=
612 sc
->vptr
->ivalue (attr_value
);
614 } else if (strcmp (type
, "real") == 0) {
615 dprintf ("%g", sc
->vptr
->rvalue (attr_value
));
616 plist_top
->attr_list
[p
].type
= HID_Real
;
617 plist_top
->attr_list
[p
].default_val
.real_value
=
618 sc
->vptr
->rvalue (attr_value
);
620 } else if (strcmp (type
, "string") == 0) {
621 dprintf ("%s", sc
->vptr
->string_value (attr_value
));
622 plist_top
->attr_list
[p
].type
= HID_String
;
623 plist_top
->attr_list
[p
].default_val
.str_value
=
624 strdup (sc
->vptr
->string_value (attr_value
));
626 } else if (strcmp (type
, "boolean") == 0) {
627 dprintf ("%ld", sc
->vptr
->ivalue (attr_value
));
628 plist_top
->attr_list
[p
].type
= HID_Boolean
;
629 plist_top
->attr_list
[p
].default_val
.int_value
=
630 sc
->vptr
->ivalue (attr_value
);
632 } else if (strcmp (type
, "enum") == 0) {
633 dprintf ("%ld", sc
->vptr
->ivalue (attr_value
));
634 plist_top
->attr_list
[p
].type
= HID_Enum
;
635 plist_top
->attr_list
[p
].default_val
.int_value
=
636 sc
->vptr
->ivalue (attr_value
);
638 } else if (strcmp (type
, "mixed") == 0) {
639 plist_top
->attr_list
[p
].type
= HID_Mixed
;
640 plist_top
->attr_list
[p
].default_val
.str_value
= NULL
;
641 fprintf (stderr
, "%s(): WARNING: HID_Mixed is not yet supported\n",
644 } else if (strcmp (type
, "path") == 0) {
645 dprintf ("%s", sc
->vptr
->string_value (attr_value
));
646 plist_top
->attr_list
[p
].type
= HID_Path
;
647 plist_top
->attr_list
[p
].default_val
.str_value
=
648 strdup (sc
->vptr
->string_value (attr_value
));
650 fprintf (stderr
, "%s(): Unknown attribute type: \"%s\"\n",
655 attr_car_el
= sc
->vptr
->pair_car(attr_cdr_el
);
656 attr_cdr_el
= sc
->vptr
->pair_cdr(attr_cdr_el
);
661 end_name_value_parse
:
662 car_el
= sc
->vptr
->pair_car(cdr_el
);
663 cdr_el
= sc
->vptr
->pair_cdr(cdr_el
);
670 set_render_type(scheme
*sc
, pointer args
)
672 pointer car_el
, cdr_el
;
675 dprintf("--> entering project.c:%s()\n", __FUNCTION__
);
677 if (!sc
->vptr
->is_pair(args
)){
678 GERB_MESSAGE("set-render-type!: Too few arguments\n");
682 car_el
= sc
->vptr
->pair_car(args
);
683 cdr_el
= sc
->vptr
->pair_cdr(args
);
685 r
= sc
->vptr
->ivalue (car_el
);
686 dprintf ("%s(): Setting render type to %d\n", __FUNCTION__
, r
);
687 interface_set_render_type (r
);
690 } /* set_render_type */
693 gerbv_file_version(scheme
*sc
, pointer args
)
695 pointer car_el
, cdr_el
;
700 dprintf("--> entering project.c:%s()\n", __FUNCTION__
);
702 if (!sc
->vptr
->is_pair(args
)){
703 GERB_MESSAGE("gerbv-file-version!: Too few arguments\n");
707 car_el
= sc
->vptr
->pair_car(args
);
708 cdr_el
= sc
->vptr
->pair_cdr(args
);
709 vstr
= get_value_string(sc
, car_el
);
711 /* find our internal integer code */
712 r
= version_str_to_int( vstr
);
715 r
= version_str_to_int( GERBV_DEFAULT_PROJECT_FILE_VERSION
);
716 GERB_MESSAGE("The project file you are attempting to load has specified that it\n"
717 "uses project file version \"%s\" but this string is not\n"
718 "a valid version. Gerbv will attempt to load the file using\n"
719 "version \"%s\". You may experience unexpected results.\n",
720 vstr
, version_int_to_str( r
));
721 vstr
= GERBV_DEFAULT_PROJECT_FILE_VERSION
;
724 tmps
= version_int_to_str( r
);
725 printf ("%s(): Read a project file version of %s (%d)\n", __FUNCTION__
, vstr
, r
);
726 printf (" Translated back to \"%s\"\n", tmps
);
730 dprintf ("%s(): Read a project file version of %s (%d)\n", __FUNCTION__
, vstr
, r
);
732 if ( r
> version_str_to_int( GERBV_PROJECT_FILE_VERSION
)) {
733 /* The project file we're trying to load is too new for this version of gerbv */
734 GERB_MESSAGE("The project file you are attempting to load is version \"%s\"\n"
735 "but this copy of gerbv is only capable of loading project files\n"
736 "using version \"%s\" or older. You may experience unexpected results.",
737 vstr
, GERBV_PROJECT_FILE_VERSION
);
742 while( known_versions
[i
] != NULL
) {
743 if( strcmp( known_versions
[i
], vstr
) == 0 ) {
750 /* The project file we're trying to load is not too new
751 * but it is unknown to us
753 GERB_MESSAGE("The project file you are attempting to load is version \"%s\"\n"
754 "which is an unknown version.\n"
755 "You may experience unexpected results.",
762 * store the version of the file we're currently loading. This variable is used
763 * by the different functions called by the project file to do anything which is
766 current_file_version
= r
;
769 } /* set_render_type */
772 /** Reads the content of a project file.
774 * Background color,\n
776 * corresponding pick and place file: labelled 'picknplace'\n
782 read_project_file(char const* filename
)
784 struct stat stat_info
;
787 /* always let the environment variable win so one can force
788 * a particular init.scm. Then we use the default installed
789 * directory based on where the binary has been installed to
790 * (including the possibility of relocation). Then use the
791 * default compiled in directory. After that try the directory
792 * where the binary lives and finally the current directory.
794 char *initdirs
[] = {"$GERBV_SCHEMEINIT","", BACKEND_DIR
,
795 mainProject
->execpath
, ".",
801 * Figure out some directories so we can find init.scm
803 init_paths(mainProject
->execname
);
804 initdirs
[1] = scmdatadir
;
811 while(initdirs
[i
] != NULL
) {
812 printf("%s(): initdirs[%d] = \"%s\"\n", __FUNCTION__
, i
, initdirs
[i
]);
819 * set the current version of the project file to 1 day before we started adding
820 * versioning to the files. While the file is being loaded, this will
821 * be set to the correct version on newer files and ignored on older files
823 current_file_version
= version_str_to_int( GERBV_DEFAULT_PROJECT_FILE_VERSION
);
825 if (stat(filename
, &stat_info
)) {
826 GERB_MESSAGE("Failed to read %s\n", filename
);
830 if (!S_ISREG(stat_info
.st_mode
)) {
831 GERB_MESSAGE("Failed to read %s\n", filename
);
835 sc
= scheme_init_new();
836 scheme_set_output_port_file(sc
, stdout
);
839 GERB_FATAL_ERROR("Couldn't init scheme\n");
844 initfile
= gerb_find_file("init.scm", initdirs
);
845 if (initfile
== NULL
) {
847 GERB_MESSAGE("Problem loading init.scm (%s)\n", strerror(errno
));
850 dprintf("%s(): initfile = \"%s\"\n", __FUNCTION__
, initfile
);
852 if ((fd
= fopen(initfile
, "r")) == NULL
) {
854 GERB_MESSAGE("Couldn't open %s (%s)\n", initfile
, strerror(errno
));
857 sc
->vptr
->load_file(sc
, fd
);
860 sc
->vptr
->scheme_define(sc
, sc
->global_env
,
861 sc
->vptr
->mk_symbol(sc
, "define-layer!"),
862 sc
->vptr
->mk_foreign_func(sc
, define_layer
));
864 sc
->vptr
->scheme_define(sc
, sc
->global_env
,
865 sc
->vptr
->mk_symbol(sc
, "set-render-type!"),
866 sc
->vptr
->mk_foreign_func(sc
, set_render_type
));
868 sc
->vptr
->scheme_define(sc
, sc
->global_env
,
869 sc
->vptr
->mk_symbol(sc
, "gerbv-file-version!"),
870 sc
->vptr
->mk_foreign_func(sc
, gerbv_file_version
));
872 if ((fd
= fopen(filename
, "r")) == NULL
) {
874 GERB_MESSAGE("Couldn't open project file %s (%s)\n", filename
,
881 scheme_load_file(sc
, fd
);
891 project_destroy_project_list (project_list_t
*projectList
){
892 project_list_t
*tempP
,*tempP2
;
894 for (tempP
= projectList
; tempP
!= NULL
; ){
895 tempP2
= tempP
->next
;
897 g_free (tempP
->filename
);
898 gerbv_attribute_destroy_HID_attribute (tempP
->attr_list
, tempP
->n_attr
);
899 tempP
->attr_list
= NULL
;
905 * Writes a description of a project to a file
906 * that can be parsed by read_project above
909 write_project_file(gerbv_project_t
*gerbvProject
, char const* filename
, project_list_t
*project
)
912 project_list_t
*p
= project
;
914 gerbv_HID_Attribute
*attr_list
= NULL
;
917 if ((fd
= fopen(filename
, "w")) == NULL
) {
918 GERB_MESSAGE("Couldn't save project %s\n", filename
);
921 fprintf(fd
, "(gerbv-file-version! \"%s\")\n", GERBV_PROJECT_FILE_VERSION
);
923 fprintf(fd
, "(define-layer! %d ", p
->layerno
);
925 #if defined (__MINGW32__)
926 fprintf(fd
, "(cons 'filename \"%s\")", convert_path_separators(p
->filename
, MINGW_UNIX
));
928 fprintf(fd
, "(cons 'filename \"%s\")", p
->filename
);
932 fprintf(fd
, "(cons 'inverted #t)");
934 fprintf(fd
, "(cons 'visible #t)");
936 fprintf(fd
, "(cons 'visible #f)");
938 fprintf(fd
, "(cons 'color #(%d %d %d))", p
->rgb
[0], p
->rgb
[1], p
->rgb
[2]);
940 /* now write out the attribute list which specifies the
943 if (p
->layerno
< 0) {
947 attr_list
= gerbvProject
->file
[p
->layerno
]->image
->info
->attr_list
;
948 n_attr
= gerbvProject
->file
[p
->layerno
]->image
->info
->n_attr
;
952 fprintf (fd
, "(cons 'attribs (list");
954 for (i
= 0; i
< n_attr
; i
++) {
955 switch (attr_list
[i
].type
) {
957 fprintf(fd
, " (list '%s 'Label \"%s\")", attr_list
[i
].name
,
958 attr_list
[i
].default_val
.str_value
);
962 fprintf(fd
, " (list '%s 'Integer %d)", attr_list
[i
].name
,
963 attr_list
[i
].default_val
.int_value
);
967 fprintf(fd
, " (list '%s 'Real %g)", attr_list
[i
].name
,
968 attr_list
[i
].default_val
.real_value
);
972 fprintf(fd
, " (list '%s 'String \"%s\")", attr_list
[i
].name
,
973 attr_list
[i
].default_val
.str_value
);
977 fprintf(fd
, " (list '%s 'Boolean %d)", attr_list
[i
].name
,
978 attr_list
[i
].default_val
.int_value
);
982 fprintf(fd
, " (list '%s 'Enum %d)", attr_list
[i
].name
,
983 attr_list
[i
].default_val
.int_value
);
987 dprintf ("HID_Mixed\n");
988 fprintf (stderr
, "%s(): WARNING: HID_Mixed is not yet supported.\n",
993 fprintf(fd
, " (list '%s 'Path \"%s\")", attr_list
[i
].name
,
994 attr_list
[i
].default_val
.str_value
);
998 fprintf (stderr
, "%s: unknown type of HID attribute (%d)\n",
999 __FUNCTION__
, attr_list
[i
].type
);
1011 fprintf (fd
, "(set-render-type! %d)\n", screenRenderInfo
.renderType
);
1016 } /* write_project */