mirror of
git://projects.qi-hardware.com/fped.git
synced 2024-11-05 04:35:19 +02:00
- change file save logic to write to a temporary file first, so that we don't
leave an empty/corrupt main file if we crash during saving - started adding Postscript output - renamed "Save as KiCad" to "Write KiCad" - switched from "manual" menu bar creation to GtkItemFactory git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5417 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
parent
6f307d6ae7
commit
1dfb8da99a
2
Makefile
2
Makefile
@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
|
OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
|
||||||
unparse.o dump.o kicad.o meas.o \
|
unparse.o dump.o kicad.o postscript.o meas.o \
|
||||||
cpp.o lex.yy.o y.tab.o \
|
cpp.o lex.yy.o y.tab.o \
|
||||||
gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \
|
gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \
|
||||||
gui_tool.o gui_over.o gui_meas.o gui_frame.o
|
gui_tool.o gui_over.o gui_meas.o gui_frame.o
|
||||||
|
142
gui.c
142
gui.c
@ -22,6 +22,7 @@
|
|||||||
#include "obj.h"
|
#include "obj.h"
|
||||||
#include "dump.h"
|
#include "dump.h"
|
||||||
#include "kicad.h"
|
#include "kicad.h"
|
||||||
|
#include "postscript.h"
|
||||||
#include "gui_util.h"
|
#include "gui_util.h"
|
||||||
#include "gui_style.h"
|
#include "gui_style.h"
|
||||||
#include "gui_status.h"
|
#include "gui_status.h"
|
||||||
@ -48,7 +49,7 @@ static GtkWidget *ev_stuff, *ev_meas;
|
|||||||
static GtkWidget *stuff_image[2], *meas_image[2];
|
static GtkWidget *stuff_image[2], *meas_image[2];
|
||||||
|
|
||||||
|
|
||||||
/* ----- menu bar ---------------------------------------------------------- */
|
/* ----- save/write operations --------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
static char *set_extension(const char *name, const char *ext)
|
static char *set_extension(const char *name, const char *ext)
|
||||||
@ -67,57 +68,93 @@ static char *set_extension(const char *name, const char *ext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void save_with_backup(const char *name, int (*fn)(FILE *file))
|
static int save_to(const char *name, int (*fn)(FILE *file))
|
||||||
{
|
{
|
||||||
FILE *file;
|
FILE *file;
|
||||||
|
|
||||||
|
file = fopen(name, "w");
|
||||||
|
if (!file) {
|
||||||
|
perror(name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!fn(file)) {
|
||||||
|
perror(name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (fclose(file) == EOF) {
|
||||||
|
perror(name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void save_with_backup(const char *name, int (*fn)(FILE *file))
|
||||||
|
{
|
||||||
char *s = stralloc(name);
|
char *s = stralloc(name);
|
||||||
char *slash, *dot, *tmp;
|
char *back, *tmp;
|
||||||
|
char *slash, *dot;
|
||||||
int n;
|
int n;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
|
/* save to temporary file */
|
||||||
|
|
||||||
slash = strrchr(s, '/');
|
slash = strrchr(s, '/');
|
||||||
|
if (!slash)
|
||||||
|
tmp = stralloc_printf("~%s", s);
|
||||||
|
else {
|
||||||
|
*slash = 0;
|
||||||
|
tmp = stralloc_printf("%s/~%s", s, slash+1);
|
||||||
|
*slash = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!save_to(tmp, fn))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* move existing file out of harm's way */
|
||||||
|
|
||||||
dot = strrchr(slash ? slash : s, '.');
|
dot = strrchr(slash ? slash : s, '.');
|
||||||
if (dot)
|
if (dot)
|
||||||
*dot = 0;
|
*dot = 0;
|
||||||
n = 0;
|
n = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
tmp = stralloc_printf("%s~%d%s%s",
|
back = stralloc_printf("%s~%d%s%s",
|
||||||
s, n, dot ? "." : "", dot ? dot+1 : "");
|
s, n, dot ? "." : "", dot ? dot+1 : "");
|
||||||
if (stat(tmp, &st) < 0) {
|
if (stat(back, &st) < 0) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
break;
|
break;
|
||||||
perror(tmp);
|
perror(back);
|
||||||
free(tmp);
|
free(back);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
free(tmp);
|
free(back);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
if (rename(name, tmp) < 0) {
|
if (rename(name, back) < 0) {
|
||||||
if (errno != ENOENT) {
|
if (errno != ENOENT) {
|
||||||
perror(name);
|
perror(name);
|
||||||
free(tmp);
|
free(back);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "renamed %s to %s\n", name, tmp);
|
fprintf(stderr, "renamed %s to %s\n", name, back);
|
||||||
|
}
|
||||||
|
free(back);
|
||||||
|
|
||||||
|
/* rename to final name */
|
||||||
|
|
||||||
|
if (rename(tmp, name) < 0) {
|
||||||
|
perror(name);
|
||||||
|
free(tmp);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
|
||||||
file = fopen(name, "w");
|
|
||||||
if (!file) {
|
|
||||||
perror(name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!fn(file))
|
|
||||||
perror(name);
|
|
||||||
if (fclose(file) == EOF)
|
|
||||||
perror(name);
|
|
||||||
fprintf(stderr, "saved to %s\n", name);
|
fprintf(stderr, "saved to %s\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void menu_save(GtkWidget *widget, gpointer user)
|
static void menu_save(void)
|
||||||
{
|
{
|
||||||
if (save_file)
|
if (save_file)
|
||||||
save_with_backup(save_file, dump);
|
save_with_backup(save_file, dump);
|
||||||
@ -128,13 +165,13 @@ static void menu_save(GtkWidget *widget, gpointer user)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void menu_save_kicad(GtkWidget *widget, gpointer user)
|
static void menu_write_kicad(void)
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (save_file) {
|
if (save_file) {
|
||||||
name = set_extension(save_file, "mod");
|
name = set_extension(save_file, "mod");
|
||||||
save_with_backup(name, kicad);
|
save_to(name, kicad);
|
||||||
free(name);
|
free(name);
|
||||||
} else {
|
} else {
|
||||||
if (!kicad(stdout))
|
if (!kicad(stdout))
|
||||||
@ -143,34 +180,47 @@ static void menu_save_kicad(GtkWidget *widget, gpointer user)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void menu_write_ps(void)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
if (save_file) {
|
||||||
|
name = set_extension(save_file, "ps");
|
||||||
|
save_to(name, postscript);
|
||||||
|
free(name);
|
||||||
|
} else {
|
||||||
|
if (!postscript(stdout))
|
||||||
|
perror("stdout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- menu bar ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
static GtkItemFactoryEntry menu_entries[] = {
|
||||||
|
{ "/File", NULL, NULL, 0, "<Branch>" },
|
||||||
|
{ "/File/Save", NULL, menu_save, 0, "<Item>" },
|
||||||
|
{ "/File/sep0", NULL, NULL, 0, "<Separator>" },
|
||||||
|
{ "/File/Write KiCad", NULL, menu_write_kicad, 0, "<Item>" },
|
||||||
|
{ "/File/Write Postscript",
|
||||||
|
NULL, menu_write_ps, 0, "<Item>" },
|
||||||
|
{ "/File/sep2", NULL, NULL, 0, "<Separator>" },
|
||||||
|
{ "/File/Quit", NULL, gtk_main_quit, 0, "<Item>" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void make_menu_bar(GtkWidget *hbox)
|
static void make_menu_bar(GtkWidget *hbox)
|
||||||
{
|
{
|
||||||
|
GtkItemFactory *factory;
|
||||||
GtkWidget *bar;
|
GtkWidget *bar;
|
||||||
GtkWidget *file_menu, *file, *quit, *save;
|
|
||||||
|
|
||||||
bar = gtk_menu_bar_new();
|
factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<FpedMenu>", NULL);
|
||||||
|
gtk_item_factory_create_items(factory,
|
||||||
|
sizeof(menu_entries)/sizeof(*menu_entries), menu_entries, NULL);
|
||||||
|
|
||||||
|
bar = gtk_item_factory_get_widget(factory, "<FpedMenu>");
|
||||||
gtk_box_pack_start(GTK_BOX(hbox), bar, TRUE, TRUE, 0);
|
gtk_box_pack_start(GTK_BOX(hbox), bar, TRUE, TRUE, 0);
|
||||||
|
|
||||||
file_menu = gtk_menu_new();
|
|
||||||
|
|
||||||
file = gtk_menu_item_new_with_label("File");
|
|
||||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), file_menu);
|
|
||||||
gtk_menu_shell_append(GTK_MENU_SHELL(bar), file);
|
|
||||||
|
|
||||||
save = gtk_menu_item_new_with_label("Save");
|
|
||||||
gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save);
|
|
||||||
g_signal_connect(G_OBJECT(save), "activate",
|
|
||||||
G_CALLBACK(menu_save), NULL);
|
|
||||||
|
|
||||||
save = gtk_menu_item_new_with_label("Save as KiCad");
|
|
||||||
gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save);
|
|
||||||
g_signal_connect(G_OBJECT(save), "activate",
|
|
||||||
G_CALLBACK(menu_save_kicad), NULL);
|
|
||||||
|
|
||||||
quit = gtk_menu_item_new_with_label("Quit");
|
|
||||||
gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), quit);
|
|
||||||
g_signal_connect(G_OBJECT(quit), "activate",
|
|
||||||
G_CALLBACK(gtk_main_quit), NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
201
postscript.c
Normal file
201
postscript.c
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* postscript.c - Dump objects in Postscript
|
||||||
|
*
|
||||||
|
* Written 2009 by Werner Almesberger
|
||||||
|
* Copyright 2009 by Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "coord.h"
|
||||||
|
#include "inst.h"
|
||||||
|
#include "postscript.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DOT_DIST mm_to_units(0.03)
|
||||||
|
#define DOT_DIAM mm_to_units(0.01)
|
||||||
|
#define HATCH mm_to_units(0.1)
|
||||||
|
#define HATCH_LINE mm_to_units(0.02)
|
||||||
|
|
||||||
|
|
||||||
|
struct postscript_params postscript_params = {
|
||||||
|
.zoom = 10.0,
|
||||||
|
.show_pad_names = 0,
|
||||||
|
.show_stuff = 0,
|
||||||
|
.label_vecs = 0,
|
||||||
|
.show_meas = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void ps_pad(FILE *file, const struct inst *inst)
|
||||||
|
{
|
||||||
|
struct coord a = inst->base;
|
||||||
|
struct coord b = inst->u.pad.other;
|
||||||
|
|
||||||
|
fprintf(file, "0 setgray %d setlinewidth\n", HATCH_LINE);
|
||||||
|
fprintf(file, " %d %d moveto\n", a.x, a.y);
|
||||||
|
fprintf(file, " %d %d lineto\n", b.x, a.y);
|
||||||
|
fprintf(file, " %d %d lineto\n", b.x, b.y);
|
||||||
|
fprintf(file, " %d %d lineto\n", a.x, b.y);
|
||||||
|
fprintf(file, " closepath gsave hatchpath grestore stroke\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ps_line(FILE *file, const struct inst *inst)
|
||||||
|
{
|
||||||
|
struct coord a = inst->base;
|
||||||
|
struct coord b = inst->u.pad.other;
|
||||||
|
|
||||||
|
fprintf(file, "1 setlinecap 0.5 setgray %d setlinewidth\n",
|
||||||
|
inst->u.rect.width);
|
||||||
|
fprintf(file, " %d %d moveto %d %d lineto stroke\n",
|
||||||
|
a.x, a.y, b.x, b.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ps_rect(FILE *file, const struct inst *inst)
|
||||||
|
{
|
||||||
|
struct coord a = inst->base;
|
||||||
|
struct coord b = inst->u.rect.end;
|
||||||
|
|
||||||
|
fprintf(file, "1 setlinecap 0.5 setgray %d setlinewidth\n",
|
||||||
|
inst->u.rect.width);
|
||||||
|
fprintf(file, " %d %d moveto\n", a.x, a.y);
|
||||||
|
fprintf(file, " %d %d lineto\n", b.x, a.y);
|
||||||
|
fprintf(file, " %d %d lineto\n", b.x, b.y);
|
||||||
|
fprintf(file, " %d %d lineto\n", a.x, b.y);
|
||||||
|
fprintf(file, " closepath stroke\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ps_arc(FILE *file, const struct inst *inst)
|
||||||
|
{
|
||||||
|
double a1, a2;
|
||||||
|
|
||||||
|
a1 = inst->u.arc.a1;
|
||||||
|
a2 = inst->u.arc.a2;
|
||||||
|
if (a2 <= a1)
|
||||||
|
a2 += 360;
|
||||||
|
|
||||||
|
fprintf(file, "1 setlinecap 0.5 setgray %d setlinewidth\n",
|
||||||
|
inst->u.arc.width);
|
||||||
|
fprintf(file, " newpath %d %d %d %f %f arc stroke\n",
|
||||||
|
inst->base.x, inst->base.y, inst->u.arc.r, a1, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ps_frame(FILE *file, const struct inst *inst)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ps_vec(FILE *file, const struct inst *inst)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ps_meas(FILE *file, const struct inst *inst)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ps_background(FILE *file, enum inst_prio prio,
|
||||||
|
const struct inst *inst)
|
||||||
|
{
|
||||||
|
switch (prio) {
|
||||||
|
case ip_line:
|
||||||
|
ps_line(file, inst);
|
||||||
|
break;
|
||||||
|
case ip_rect:
|
||||||
|
ps_rect(file, inst);
|
||||||
|
break;
|
||||||
|
case ip_circ:
|
||||||
|
case ip_arc:
|
||||||
|
ps_arc(file, inst);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ps_foreground(FILE *file, enum inst_prio prio,
|
||||||
|
const struct inst *inst)
|
||||||
|
{
|
||||||
|
switch (prio) {
|
||||||
|
case ip_pad:
|
||||||
|
ps_pad(file, inst);
|
||||||
|
break;
|
||||||
|
case ip_vec:
|
||||||
|
if (postscript_params.show_stuff)
|
||||||
|
ps_vec(file, inst);
|
||||||
|
break;
|
||||||
|
case ip_frame:
|
||||||
|
if (postscript_params.show_stuff)
|
||||||
|
ps_frame(file, inst);
|
||||||
|
break;
|
||||||
|
case ip_meas:
|
||||||
|
if (postscript_params.show_meas)
|
||||||
|
ps_meas(file, inst);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int postscript(FILE *file)
|
||||||
|
{
|
||||||
|
enum inst_prio prio;
|
||||||
|
const struct inst *inst;
|
||||||
|
|
||||||
|
fprintf(file, "%%!PS\n");
|
||||||
|
|
||||||
|
fprintf(file,
|
||||||
|
"currentpagedevice /PageSize get\n"
|
||||||
|
" aload pop\n"
|
||||||
|
" 2 div exch 2 div exch\n"
|
||||||
|
" translate\n"
|
||||||
|
" %f 72 mul %d div 1000 div dup scale\n",
|
||||||
|
(double) postscript_params.zoom , (int) MIL_UNITS);
|
||||||
|
|
||||||
|
fprintf(file,
|
||||||
|
"/dotpath {\n"
|
||||||
|
" gsave pathbbox clip newpath\n"
|
||||||
|
" 1 setlinecap %d setlinewidth\n"
|
||||||
|
" /ury exch def /urx exch def /lly exch def /llx exch def\n"
|
||||||
|
" llx %d urx {\n"
|
||||||
|
" lly %d ury {\n"
|
||||||
|
" 1 index exch moveto 0 0 rlineto stroke\n"
|
||||||
|
" } for\n"
|
||||||
|
" } for\n"
|
||||||
|
" grestore newpath } def\n", DOT_DIAM, DOT_DIST, DOT_DIST);
|
||||||
|
|
||||||
|
fprintf(file,
|
||||||
|
"/hatchpath {\n"
|
||||||
|
" gsave pathbbox clip newpath\n"
|
||||||
|
" /ury exch def /urx exch def /lly exch def /llx exch def\n"
|
||||||
|
" lly ury sub %d urx llx sub {\n" /* for -(ury-lly) to urx-llx */
|
||||||
|
" llx add dup lly moveto\n"
|
||||||
|
" ury lly sub add ury lineto stroke\n"
|
||||||
|
" } for\n"
|
||||||
|
" grestore newpath } def\n", HATCH);
|
||||||
|
|
||||||
|
FOR_INSTS_UP(prio, inst)
|
||||||
|
ps_background(file, prio, inst);
|
||||||
|
FOR_INSTS_UP(prio, inst)
|
||||||
|
ps_foreground(file, prio, inst);
|
||||||
|
|
||||||
|
fprintf(file, "showpage\n");
|
||||||
|
fprintf(file, "%%%%EOF\n");
|
||||||
|
|
||||||
|
fflush(file);
|
||||||
|
return !ferror(file);
|
||||||
|
}
|
31
postscript.h
Normal file
31
postscript.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* ps.h - Dump objects in Postscript
|
||||||
|
*
|
||||||
|
* Written 2009 by Werner Almesberger
|
||||||
|
* Copyright 2009 by Werner Almesberger
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef POSTSCRIPT_H
|
||||||
|
#define POSTSCRIPT_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct postscript_params {
|
||||||
|
double zoom;
|
||||||
|
int show_pad_names;
|
||||||
|
int show_stuff; /* vecs and frames */
|
||||||
|
int label_vecs;
|
||||||
|
int show_meas;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int postscript(FILE *file);
|
||||||
|
|
||||||
|
#endif /* !POSTSCRIPT_H */
|
Loading…
Reference in New Issue
Block a user