Index: Plug.tmpasm =================================================================== --- Plug.tmpasm (revision 36321) +++ Plug.tmpasm (revision 36322) @@ -1,5 +1,8 @@ put /local/pcb/mod {export_lpr} -put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_lpr/lpr.o @] +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/export_lpr/lpr.o + $(PLUGDIR)/export_lpr/lpr_hid.o +@] put /local/pcb/mod/CONF {$(PLUGDIR)/export_lpr/export_lpr_conf.h} switch /local/pcb/export_lpr/controls Index: lpr.c =================================================================== --- lpr.c (revision 36321) +++ lpr.c (revision 36322) @@ -1,201 +1,38 @@ /* - This file is part of pcb-rnd and was part of gEDA/PCB but lacked proper - copyright banner at the fork. It probably has the same copyright as - gEDA/PCB as a whole in 2011. -*/ + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2022 Tibor 'Igor2' Palinkas + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ #include "config.h" #include -#include -#include -#include -#include - -#include -#include -#include - #include -#include -#include -#include -#include -const char *lpr_cookie = "lpr HID"; -static rnd_hid_t lpr_hid; - - - -static const rnd_export_opt_t base_lpr_options[] = { - -/* %start-doc options "98 lpr Printing Options" -@ftable @code -@item --lprcommand -Command to use for printing. Defaults to @code{lpr}. This can be used to produce -PDF output with a virtual PDF printer. Example: @* -@code{--lprcommand "lp -d CUPS-PDF-Printer"}. -@end ftable -@noindent In addition, all @ref{Postscript Export} options are valid. -%end-doc -*/ - {"lprcommand", "Command to use for printing", - RND_HATT_STRING, 0, 0, {0, "lpr", 0}, 0} -#define HA_lprcommand 0 -}; - -#define NUM_OPTIONS (sizeof(base_lpr_options)/sizeof(base_lpr_options[0])) - -static rnd_export_opt_t *lpr_options = 0; -static int num_lpr_options = 0; -static rnd_hid_attr_val_t *lpr_values; - -static void lpr_maybe_set_value(const char *name, double new_val) -{ - int n; - - if (new_val <= 0) - return; - - for(n = 0; n < num_lpr_options; n++) { - if (strcmp(name, lpr_options[n].name) == 0) { - lpr_values[n].dbl = new_val; - break; - } - } -} - -static const double *lpr_xcalib, *lpr_ycalib; -static void lpr_ps_init(rnd_hid_t *ps_hid) -{ - if (lpr_options == 0) { - const rnd_export_opt_t *ps_opts = ps_hid->get_export_options(ps_hid, &num_lpr_options); - lpr_options = calloc(num_lpr_options, sizeof(rnd_hid_attribute_t)); - memcpy(lpr_options, ps_opts, num_lpr_options * sizeof(rnd_hid_attribute_t)); - memcpy(lpr_options, base_lpr_options, sizeof(base_lpr_options)); - if (lpr_hid.argument_array == NULL) { - lpr_values = calloc(num_lpr_options, sizeof(rnd_hid_attr_val_t)); - lpr_hid.argument_array = lpr_values; - } - - rnd_hid_load_defaults(&lpr_hid, lpr_options, num_lpr_options); - - lpr_maybe_set_value("xcalib", (lpr_xcalib != NULL) ? *lpr_xcalib : 1.0); - lpr_maybe_set_value("ycalib", (lpr_ycalib != NULL) ? *lpr_ycalib : 1.0); - } -} - -static const rnd_export_opt_t *lpr_get_export_options(rnd_hid_t *hid, int *n) -{ - const char *val; - - - - /* - * We initialize the default value in this manner because the GUI - * HID's may want to free() this string value and replace it with a - * new one based on how a user fills out a print dialog. - */ - val = lpr_values[HA_lprcommand].str; - if ((val == NULL) || (*val == '\0')) { - free((char *)lpr_values[HA_lprcommand].str); - lpr_values[HA_lprcommand].str = rnd_strdup("lpr"); - } - - if (n) - *n = num_lpr_options; - return lpr_options; -} - - -static void (*rnd_lpr_hid_export_to_file)(FILE *, rnd_hid_attr_val_t *, rnd_xform_t *) = NULL; -static void lpr_do_export(rnd_hid_t *hid, rnd_hid_attr_val_t *options) -{ - FILE *f; - const char *filename; - - if (!options) { - lpr_get_export_options(hid, 0); - options = lpr_values; - } - - filename = options[HA_lprcommand].str; - - rnd_trace("LPR: open %s\n", filename); - f = rnd_popen(NULL, filename, "w"); - if (!f) { - perror(filename); - return; - } - - rnd_lpr_hid_export_to_file(f, options, NULL); - - rnd_pclose(f); -} - -static int lpr_parse_arguments(rnd_hid_t *hid, int *argc, char ***argv) -{ - lpr_get_export_options(hid, 0); - rnd_export_register_opts2(hid, lpr_options, num_lpr_options, lpr_cookie, 0); - return rnd_hid_parse_command_line(argc, argv); -} - -static int lpr_usage(rnd_hid_t *hid, const char *topic) -{ - fprintf(stderr, "\nlpr exporter command line arguments:\n\n"); - rnd_hid_usage(base_lpr_options, sizeof(base_lpr_options) / sizeof(base_lpr_options[0])); - fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x lpr [lpr options] foo.pcb\n\n"); - return 0; -} - - -void rnd_lpr_uninit(void) -{ - rnd_remove_actions_by_cookie(lpr_cookie); - rnd_hid_remove_hid(&lpr_hid); - free(lpr_hid.argument_array); - lpr_hid.argument_array = NULL; -} - -int rnd_lpr_init(rnd_hid_t *ps_hid, void (*ps_ps_init)(rnd_hid_t *), void (*hid_export_to_file)(FILE *, rnd_hid_attr_val_t *, rnd_xform_t *), const double *xcalib, const double *ycalib) -{ - RND_API_CHK_VER; - - rnd_lpr_hid_export_to_file = hid_export_to_file; - lpr_xcalib = xcalib; - lpr_ycalib = ycalib; - - memset(&lpr_hid, 0, sizeof(rnd_hid_t)); - - rnd_hid_nogui_init(&lpr_hid); - ps_ps_init(&lpr_hid); - - lpr_hid.struct_size = sizeof(rnd_hid_t); - lpr_hid.name = "lpr"; - lpr_hid.description = "Postscript print"; - lpr_hid.printer = 1; - - lpr_hid.get_export_options = lpr_get_export_options; - lpr_hid.do_export = lpr_do_export; - lpr_hid.parse_arguments = lpr_parse_arguments; - lpr_hid.argument_array = NULL; - - lpr_hid.usage = lpr_usage; - - lpr_ps_init(ps_hid); - - rnd_hid_register_hid(&lpr_hid); - rnd_hid_load_defaults(&lpr_hid, base_lpr_options, NUM_OPTIONS); - - return 0; -} - - -/*********/ - #include "../export_ps/ps.h" #include "export_lpr_conf.h" +#include "lpr_hid.h" conf_export_lpr_t conf_export_lpr; Index: lpr_hid.c =================================================================== --- lpr_hid.c (nonexistent) +++ lpr_hid.c (revision 36322) @@ -0,0 +1,196 @@ +/* + This file is part of pcb-rnd and was part of gEDA/PCB but lacked proper + copyright banner at the fork. It probably has the same copyright as + gEDA/PCB as a whole in 2011. +*/ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "lpr_hid.h" + +const char *lpr_cookie = "lpr HID"; +static rnd_hid_t lpr_hid; + + + + +static const rnd_export_opt_t base_lpr_options[] = { + +/* %start-doc options "98 lpr Printing Options" +@ftable @code +@item --lprcommand +Command to use for printing. Defaults to @code{lpr}. This can be used to produce +PDF output with a virtual PDF printer. Example: @* +@code{--lprcommand "lp -d CUPS-PDF-Printer"}. +@end ftable +@noindent In addition, all @ref{Postscript Export} options are valid. +%end-doc +*/ + {"lprcommand", "Command to use for printing", + RND_HATT_STRING, 0, 0, {0, "lpr", 0}, 0} +#define HA_lprcommand 0 +}; + +#define NUM_OPTIONS (sizeof(base_lpr_options)/sizeof(base_lpr_options[0])) + +static rnd_export_opt_t *lpr_options = 0; +static int num_lpr_options = 0; +static rnd_hid_attr_val_t *lpr_values; + +static void lpr_maybe_set_value(const char *name, double new_val) +{ + int n; + + if (new_val <= 0) + return; + + for(n = 0; n < num_lpr_options; n++) { + if (strcmp(name, lpr_options[n].name) == 0) { + lpr_values[n].dbl = new_val; + break; + } + } +} + +static const double *lpr_xcalib, *lpr_ycalib; +static void lpr_ps_init(rnd_hid_t *ps_hid) +{ + if (lpr_options == 0) { + const rnd_export_opt_t *ps_opts = ps_hid->get_export_options(ps_hid, &num_lpr_options); + lpr_options = calloc(num_lpr_options, sizeof(rnd_hid_attribute_t)); + memcpy(lpr_options, ps_opts, num_lpr_options * sizeof(rnd_hid_attribute_t)); + memcpy(lpr_options, base_lpr_options, sizeof(base_lpr_options)); + if (lpr_hid.argument_array == NULL) { + lpr_values = calloc(num_lpr_options, sizeof(rnd_hid_attr_val_t)); + lpr_hid.argument_array = lpr_values; + } + + rnd_hid_load_defaults(&lpr_hid, lpr_options, num_lpr_options); + + lpr_maybe_set_value("xcalib", (lpr_xcalib != NULL) ? *lpr_xcalib : 1.0); + lpr_maybe_set_value("ycalib", (lpr_ycalib != NULL) ? *lpr_ycalib : 1.0); + } +} + +static const rnd_export_opt_t *lpr_get_export_options(rnd_hid_t *hid, int *n) +{ + const char *val; + + + + /* + * We initialize the default value in this manner because the GUI + * HID's may want to free() this string value and replace it with a + * new one based on how a user fills out a print dialog. + */ + val = lpr_values[HA_lprcommand].str; + if ((val == NULL) || (*val == '\0')) { + free((char *)lpr_values[HA_lprcommand].str); + lpr_values[HA_lprcommand].str = rnd_strdup("lpr"); + } + + if (n) + *n = num_lpr_options; + return lpr_options; +} + + +static void (*rnd_lpr_hid_export_to_file)(FILE *, rnd_hid_attr_val_t *, rnd_xform_t *) = NULL; +static void lpr_do_export(rnd_hid_t *hid, rnd_hid_attr_val_t *options) +{ + FILE *f; + const char *filename; + + if (!options) { + lpr_get_export_options(hid, 0); + options = lpr_values; + } + + filename = options[HA_lprcommand].str; + + rnd_trace("LPR: open %s\n", filename); + f = rnd_popen(NULL, filename, "w"); + if (!f) { + perror(filename); + return; + } + + rnd_lpr_hid_export_to_file(f, options, NULL); + + rnd_pclose(f); +} + +static int lpr_parse_arguments(rnd_hid_t *hid, int *argc, char ***argv) +{ + lpr_get_export_options(hid, 0); + rnd_export_register_opts2(hid, lpr_options, num_lpr_options, lpr_cookie, 0); + return rnd_hid_parse_command_line(argc, argv); +} + +static int lpr_usage(rnd_hid_t *hid, const char *topic) +{ + fprintf(stderr, "\nlpr exporter command line arguments:\n\n"); + rnd_hid_usage(base_lpr_options, sizeof(base_lpr_options) / sizeof(base_lpr_options[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x lpr [lpr options] foo.pcb\n\n"); + return 0; +} + + +void rnd_lpr_uninit(void) +{ + rnd_remove_actions_by_cookie(lpr_cookie); + rnd_hid_remove_hid(&lpr_hid); + free(lpr_hid.argument_array); + lpr_hid.argument_array = NULL; +} + +int rnd_lpr_init(rnd_hid_t *ps_hid, void (*ps_ps_init)(rnd_hid_t *), void (*hid_export_to_file)(FILE *, rnd_hid_attr_val_t *, rnd_xform_t *), const double *xcalib, const double *ycalib) +{ + RND_API_CHK_VER; + + rnd_lpr_hid_export_to_file = hid_export_to_file; + lpr_xcalib = xcalib; + lpr_ycalib = ycalib; + + memset(&lpr_hid, 0, sizeof(rnd_hid_t)); + + rnd_hid_nogui_init(&lpr_hid); + ps_ps_init(&lpr_hid); + + lpr_hid.struct_size = sizeof(rnd_hid_t); + lpr_hid.name = "lpr"; + lpr_hid.description = "Postscript print"; + lpr_hid.printer = 1; + + lpr_hid.get_export_options = lpr_get_export_options; + lpr_hid.do_export = lpr_do_export; + lpr_hid.parse_arguments = lpr_parse_arguments; + lpr_hid.argument_array = NULL; + + lpr_hid.usage = lpr_usage; + + lpr_ps_init(ps_hid); + + rnd_hid_register_hid(&lpr_hid); + rnd_hid_load_defaults(&lpr_hid, base_lpr_options, NUM_OPTIONS); + + return 0; +} + + Index: lpr_hid.h =================================================================== --- lpr_hid.h (nonexistent) +++ lpr_hid.h (revision 36322) @@ -0,0 +1,16 @@ +/* Instantiate exactly one global lpr HID. The actual plugin is a thing wrapper + implemented by the app: it needs to glue an export hid (e.g. ps) to lpr. */ + +/* Call this from pplg_uninit_export_lpr() */ +void rnd_lpr_uninit(void); + +/* Call this from pplg_init_export_lpr(); glue arguments: + - ps_hid: target HID used for the export; typically ps + - ps_ps_init: callback that fills in the draw calls of the HID struct + - hid_export_to_file: direct call to export the current design + - [xy]calib: optional, pointing to conf values used as initial/default calib + fields in the target hid; when NULL, initialize these to 1.0 + (the user can change these later as exporter options) + (ignored if the target HID doesn't have xcalib/ycalib options) +*/ +int rnd_lpr_init(rnd_hid_t *ps_hid, void (*ps_ps_init)(rnd_hid_t *), void (*hid_export_to_file)(FILE *, rnd_hid_attr_val_t *, rnd_xform_t *), const double *xcalib, const double *ycalib);