mirror of https://github.com/GNOME/gimp.git
1486 lines
38 KiB
C
1486 lines
38 KiB
C
/*
|
|
* "$Id$"
|
|
*
|
|
* Print plug-in for the GIMP.
|
|
*
|
|
* Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
|
|
* Robert Krawitz (rlk@alum.mit.edu)
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "print_gimp.h"
|
|
|
|
#ifdef GIMP_1_0
|
|
#include <math.h>
|
|
#endif
|
|
|
|
#include <signal.h>
|
|
#include <ctype.h>
|
|
#include <sys/wait.h>
|
|
#ifdef __EMX__
|
|
#define INCL_DOSDEVICES
|
|
#define INCL_DOSERRORS
|
|
#include <os2.h>
|
|
#endif
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "print-intl.h"
|
|
|
|
/*
|
|
* Local functions...
|
|
*/
|
|
|
|
static void printrc_load(void);
|
|
void printrc_save(void);
|
|
static int compare_printers(plist_t *p1, plist_t *p2);
|
|
static void get_system_printers(void);
|
|
|
|
static void query (void);
|
|
static void run (char *, int, GimpParam *, int *, GimpParam **);
|
|
static int do_print_dialog (char *proc_name);
|
|
|
|
#ifndef GIMP_1_0
|
|
extern void gimp_create_main_window (void);
|
|
#endif
|
|
#ifndef NEW_UI_ONLY
|
|
extern void gtk_create_main_window (void);
|
|
#endif
|
|
|
|
#if 0
|
|
static void cleanupfunc(void);
|
|
#endif
|
|
|
|
/*
|
|
* Globals...
|
|
*/
|
|
|
|
GimpPlugInInfo PLUG_IN_INFO = /* Plug-in information */
|
|
{
|
|
NULL, /* init_proc */
|
|
NULL, /* quit_proc */
|
|
query, /* query_proc */
|
|
run, /* run_proc */
|
|
};
|
|
|
|
vars_t vars =
|
|
{
|
|
"", /* Name of file or command to print to */
|
|
"ps2", /* Name of printer "driver" */
|
|
"", /* Name of PPD file */
|
|
OUTPUT_COLOR, /* Color or grayscale output */
|
|
"", /* Output resolution */
|
|
"", /* Size of output media */
|
|
"", /* Type of output media */
|
|
"", /* Source of output media */
|
|
"", /* Ink type */
|
|
"", /* Dither algorithm */
|
|
1.0, /* Output brightness */
|
|
100.0, /* Scaling (100% means entire printable area, */
|
|
/* -XXX means scale by PPI) */
|
|
-1, /* Orientation (-1 = automatic) */
|
|
-1, /* X offset (-1 = center) */
|
|
-1, /* Y offset (-1 = center) */
|
|
1.0, /* Screen gamma */
|
|
1.0, /* Contrast */
|
|
1.0, /* Cyan */
|
|
1.0, /* Magenta */
|
|
1.0, /* Yellow */
|
|
0, /* Linear */
|
|
1.0, /* Output saturation */
|
|
1.0, /* Density */
|
|
IMAGE_CONTINUOUS, /* Image type */
|
|
0, /* Unit 0=Inch */
|
|
1.0, /* Application gamma placeholder */
|
|
0, /* Page width */
|
|
0 /* Page height */
|
|
};
|
|
|
|
int plist_current = 0, /* Current system printer */
|
|
plist_count = 0; /* Number of system printers */
|
|
plist_t *plist; /* System printers */
|
|
|
|
int saveme = FALSE; /* True if print should proceed */
|
|
int runme = FALSE; /* True if print should proceed */
|
|
const printer_t *current_printer = 0; /* Current printer index */
|
|
gint32 image_ID; /* image ID */
|
|
|
|
const char *image_filename;
|
|
int image_width;
|
|
int image_height;
|
|
|
|
static void
|
|
check_plist(int count)
|
|
{
|
|
static int current_plist_size = 0;
|
|
if (count <= current_plist_size)
|
|
return;
|
|
else if (current_plist_size == 0)
|
|
{
|
|
current_plist_size = count;
|
|
plist = malloc(current_plist_size * sizeof(plist_t));
|
|
}
|
|
else
|
|
{
|
|
current_plist_size *= 2;
|
|
if (current_plist_size < count)
|
|
current_plist_size = count;
|
|
plist = realloc(plist, current_plist_size * sizeof(plist_t));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 'main()' - Main entry - just call gimp_main()...
|
|
*/
|
|
|
|
#if 0
|
|
int
|
|
main(int argc, /* I - Number of command-line args */
|
|
char *argv[]) /* I - Command-line args */
|
|
{
|
|
return (gimp_main(argc, argv));
|
|
}
|
|
#else
|
|
MAIN()
|
|
#endif
|
|
|
|
static int print_finished = 0;
|
|
|
|
#if 0
|
|
void
|
|
cleanupfunc(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* 'query()' - Respond to a plug-in query...
|
|
*/
|
|
|
|
static void
|
|
query (void)
|
|
{
|
|
static GimpParamDef args[] =
|
|
{
|
|
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
|
|
{ GIMP_PDB_IMAGE, "image", "Input image" },
|
|
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
|
|
{ GIMP_PDB_STRING, "output_to", "Print command or filename (| to pipe to command)" },
|
|
{ GIMP_PDB_STRING, "driver", "Printer driver short name" },
|
|
{ GIMP_PDB_STRING, "ppd_file", "PPD file" },
|
|
{ GIMP_PDB_INT32, "output_type", "Output type (0 = gray, 1 = color)" },
|
|
{ GIMP_PDB_STRING, "resolution", "Resolution (\"300\", \"720\", etc.)" },
|
|
{ GIMP_PDB_STRING, "media_size", "Media size (\"Letter\", \"A4\", etc.)" },
|
|
{ GIMP_PDB_STRING, "media_type", "Media type (\"Plain\", \"Glossy\", etc.)" },
|
|
{ GIMP_PDB_STRING, "media_source", "Media source (\"Tray1\", \"Manual\", etc.)" },
|
|
{ GIMP_PDB_FLOAT, "brightness", "Brightness (0-400%)" },
|
|
{ GIMP_PDB_FLOAT, "scaling", "Output scaling (0-100%, -PPI)" },
|
|
{ GIMP_PDB_INT32, "orientation", "Output orientation (-1 = auto, 0 = portrait, 1 = landscape)" },
|
|
{ GIMP_PDB_INT32, "left", "Left offset (points, -1 = centered)" },
|
|
{ GIMP_PDB_INT32, "top", "Top offset (points, -1 = centered)" },
|
|
{ GIMP_PDB_FLOAT, "gamma", "Output gamma (0.1 - 3.0)" },
|
|
{ GIMP_PDB_FLOAT, "contrast", "Contrast" },
|
|
{ GIMP_PDB_FLOAT, "cyan", "Cyan level" },
|
|
{ GIMP_PDB_FLOAT, "magenta", "Magenta level" },
|
|
{ GIMP_PDB_FLOAT, "yellow", "Yellow level" },
|
|
{ GIMP_PDB_INT32, "linear", "Linear output (0 = normal, 1 = linear)" },
|
|
{ GIMP_PDB_INT32, "image_type", "Image type (0 = line art, 1 = solid tones, 2 = continuous tone, 3 = monochrome)"},
|
|
{ GIMP_PDB_FLOAT, "saturation", "Saturation (0-1000%)" },
|
|
{ GIMP_PDB_FLOAT, "density", "Density (0-200%)" },
|
|
{ GIMP_PDB_STRING, "ink_type", "Type of ink or cartridge" },
|
|
{ GIMP_PDB_STRING, "dither_algorithm", "Dither algorithm" },
|
|
{ GIMP_PDB_INT32, "unit", "Unit 0=Inches 1=Metric" },
|
|
};
|
|
|
|
static gchar *blurb = "This plug-in prints images from The GIMP.";
|
|
static gchar *help = "Prints images to PostScript, PCL, or ESC/P2 printers.";
|
|
static gchar *auth = "Michael Sweet <mike@easysw.com> and Robert Krawitz <rlk@alum.mit.edu>";
|
|
static gchar *copy = "Copyright 1997-2000 by Michael Sweet and Robert Krawitz";
|
|
static gchar *types = "RGB*,GRAY*,INDEXED*";
|
|
|
|
gimp_install_procedure ("file_print_gimp",
|
|
blurb, help, auth, copy,
|
|
PLUG_IN_VERSION,
|
|
N_("<Image>/File/Print..."),
|
|
types,
|
|
GIMP_PLUGIN,
|
|
G_N_ELEMENTS (args), 0,
|
|
args, NULL);
|
|
}
|
|
|
|
|
|
#ifdef __EMX__
|
|
static char *
|
|
get_tmp_filename()
|
|
{
|
|
char *tmp_path, *s, filename[80];
|
|
|
|
tmp_path = getenv("TMP");
|
|
if (tmp_path == NULL)
|
|
tmp_path = "";
|
|
|
|
sprintf(filename, "gimp_print_tmp.%d", getpid());
|
|
s = tmp_path = g_strconcat(tmp_path, "\\", filename, NULL);
|
|
if (!s)
|
|
return NULL;
|
|
for ( ; *s; s++)
|
|
if (*s == '/') *s = '\\';
|
|
return tmp_path;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* 'usr1_handler()' - Make a note when we receive SIGUSR1.
|
|
*/
|
|
|
|
static volatile int usr1_interrupt;
|
|
|
|
static void
|
|
usr1_handler (int signal)
|
|
{
|
|
usr1_interrupt = 1;
|
|
}
|
|
|
|
/*
|
|
* 'run()' - Run the plug-in...
|
|
*/
|
|
|
|
/* #define DEBUG_STARTUP */
|
|
|
|
|
|
#ifdef DEBUG_STARTUP
|
|
volatile int SDEBUG = 1;
|
|
#endif
|
|
|
|
static void
|
|
run (char *name, /* I - Name of print program. */
|
|
int nparams, /* I - Number of parameters passed in */
|
|
GimpParam *param, /* I - Parameter values */
|
|
int *nreturn_vals, /* O - Number of return values */
|
|
GimpParam **return_vals) /* O - Return values */
|
|
{
|
|
GimpDrawable *drawable; /* Drawable for image */
|
|
GimpRunMode run_mode; /* Current run mode */
|
|
FILE *prn; /* Print file/command */
|
|
int ncolors; /* Number of colors in colormap */
|
|
GimpParam *values; /* Return values */
|
|
#ifdef __EMX__
|
|
char *tmpfile; /* temp filename */
|
|
#endif
|
|
gint32 drawable_ID; /* drawable ID */
|
|
#ifndef GIMP_1_0
|
|
GimpExportReturnType export = GIMP_EXPORT_CANCEL; /* return value of gimp_export_image() */
|
|
#endif
|
|
int ppid = getpid (), /* PID of plugin */
|
|
opid, /* PID of output process */
|
|
cpid = 0, /* PID of control/monitor process */
|
|
pipefd[2]; /* Fds of the pipe connecting all the above */
|
|
int dummy;
|
|
#ifdef DEBUG_STARTUP
|
|
while (SDEBUG)
|
|
;
|
|
#endif
|
|
|
|
#ifdef INIT_I18N_UI
|
|
INIT_I18N_UI();
|
|
#else
|
|
INIT_LOCALE ("gimp-print");
|
|
#endif
|
|
|
|
/*
|
|
* Initialize parameter data...
|
|
*/
|
|
|
|
current_printer = get_printer_by_index (0);
|
|
run_mode = (GimpRunMode)param[0].data.d_int32;
|
|
|
|
values = g_new (GimpParam, 1);
|
|
|
|
values[0].type = GIMP_PDB_STATUS;
|
|
values[0].data.d_status = GIMP_PDB_SUCCESS;
|
|
|
|
*nreturn_vals = 1;
|
|
*return_vals = values;
|
|
|
|
image_ID = param[1].data.d_int32;
|
|
drawable_ID = param[2].data.d_int32;
|
|
|
|
image_filename = gimp_image_get_filename (image_ID);
|
|
if (strchr(image_filename, '/'))
|
|
image_filename = strrchr(image_filename, '/') + 1;
|
|
|
|
#ifndef GIMP_1_0
|
|
/* eventually export the image */
|
|
switch (run_mode)
|
|
{
|
|
case GIMP_RUN_INTERACTIVE:
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
|
gimp_ui_init ("print", TRUE);
|
|
export = gimp_export_image (&image_ID, &drawable_ID, "Print",
|
|
(GIMP_EXPORT_CAN_HANDLE_RGB |
|
|
GIMP_EXPORT_CAN_HANDLE_GRAY |
|
|
GIMP_EXPORT_CAN_HANDLE_INDEXED |
|
|
GIMP_EXPORT_CAN_HANDLE_ALPHA));
|
|
if (export == GIMP_EXPORT_CANCEL)
|
|
{
|
|
*nreturn_vals = 1;
|
|
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Get drawable...
|
|
*/
|
|
|
|
drawable = gimp_drawable_get (drawable_ID);
|
|
|
|
image_width = drawable->width;
|
|
image_height = drawable->height;
|
|
|
|
/*
|
|
* See how we will run
|
|
*/
|
|
|
|
switch (run_mode)
|
|
{
|
|
case GIMP_RUN_INTERACTIVE:
|
|
/*
|
|
* Get information from the dialog...
|
|
*/
|
|
|
|
if (!do_print_dialog (name))
|
|
goto cleanup;
|
|
break;
|
|
|
|
case GIMP_RUN_NONINTERACTIVE:
|
|
/*
|
|
* Make sure all the arguments are present...
|
|
*/
|
|
if (nparams < 11)
|
|
values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
|
|
else
|
|
{
|
|
strcpy (vars.output_to, param[3].data.d_string);
|
|
strcpy (vars.driver, param[4].data.d_string);
|
|
strcpy (vars.ppd_file, param[5].data.d_string);
|
|
vars.output_type = param[6].data.d_int32;
|
|
strcpy (vars.resolution, param[7].data.d_string);
|
|
strcpy (vars.media_size, param[8].data.d_string);
|
|
strcpy (vars.media_type, param[9].data.d_string);
|
|
strcpy (vars.media_source, param[10].data.d_string);
|
|
|
|
if (nparams > 11)
|
|
vars.brightness = param[11].data.d_int32;
|
|
else
|
|
vars.brightness = 100;
|
|
|
|
if (nparams > 12)
|
|
vars.scaling = param[12].data.d_float;
|
|
else
|
|
vars.scaling = 100.0;
|
|
|
|
if (nparams > 13)
|
|
vars.orientation = param[13].data.d_int32;
|
|
else
|
|
vars.orientation = -1;
|
|
|
|
if (nparams > 14)
|
|
vars.left = param[14].data.d_int32;
|
|
else
|
|
vars.left = -1;
|
|
|
|
if (nparams > 15)
|
|
vars.top = param[15].data.d_int32;
|
|
else
|
|
vars.top = -1;
|
|
|
|
if (nparams > 16)
|
|
vars.gamma = param[16].data.d_float;
|
|
else
|
|
vars.gamma = 1.0;
|
|
|
|
if (nparams > 17)
|
|
vars.contrast = param[17].data.d_int32;
|
|
else
|
|
vars.contrast = 100;
|
|
|
|
if (nparams > 18)
|
|
vars.cyan = param[18].data.d_int32;
|
|
else
|
|
vars.cyan = 100;
|
|
|
|
if (nparams > 19)
|
|
vars.magenta = param[19].data.d_int32;
|
|
else
|
|
vars.magenta = 100;
|
|
|
|
if (nparams > 20)
|
|
vars.yellow = param[20].data.d_int32;
|
|
else
|
|
vars.yellow = 100;
|
|
|
|
if (nparams > 21)
|
|
vars.linear = param[21].data.d_int32;
|
|
else
|
|
vars.linear = 0;
|
|
|
|
if (nparams > 22)
|
|
vars.image_type = param[22].data.d_int32;
|
|
else
|
|
vars.image_type = IMAGE_CONTINUOUS;
|
|
|
|
if (nparams > 23)
|
|
vars.saturation = param[23].data.d_float;
|
|
else
|
|
vars.saturation = 1.0;
|
|
|
|
if (nparams > 24)
|
|
vars.density = param[24].data.d_float;
|
|
else
|
|
vars.density = 1.0;
|
|
|
|
if (nparams > 25)
|
|
strcpy (vars.ink_type, param[25].data.d_string);
|
|
else
|
|
memset (vars.ink_type, 0, 64);
|
|
|
|
if (nparams > 26)
|
|
strcpy (vars.dither_algorithm, param[26].data.d_string);
|
|
else
|
|
memset (vars.dither_algorithm, 0, 64);
|
|
|
|
if (nparams > 27)
|
|
vars.unit = param[27].data.d_int32;
|
|
else
|
|
vars.unit = 0;
|
|
}
|
|
|
|
current_printer = get_printer_by_driver (vars.driver);
|
|
break;
|
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
|
/*
|
|
* Possibly retrieve data...
|
|
*/
|
|
gimp_get_data (PLUG_IN_NAME, &vars);
|
|
vars.page_width = 0;
|
|
vars.page_height = 0;
|
|
|
|
current_printer = get_printer_by_driver (vars.driver);
|
|
break;
|
|
|
|
default:
|
|
values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
|
|
break;;
|
|
}
|
|
|
|
/*
|
|
* Print the image...
|
|
*/
|
|
if (values[0].data.d_status == GIMP_PDB_SUCCESS)
|
|
{
|
|
/*
|
|
* Set the tile cache size...
|
|
*/
|
|
|
|
if (drawable->height > drawable->width)
|
|
gimp_tile_cache_ntiles ((drawable->height + gimp_tile_width () - 1) /
|
|
gimp_tile_width () + 1);
|
|
else
|
|
gimp_tile_cache_ntiles ((drawable->width + gimp_tile_width () - 1) /
|
|
gimp_tile_width () + 1);
|
|
|
|
/*
|
|
* Open the file/execute the print command...
|
|
*/
|
|
|
|
if (plist_current > 0)
|
|
#ifndef __EMX__
|
|
{
|
|
/*
|
|
* The following IPC code is only necessary because the GIMP kills
|
|
* plugins with SIGKILL if its "Cancel" button is pressed; this
|
|
* gives the plugin no chance whatsoever to clean up after itself.
|
|
*/
|
|
usr1_interrupt = 0;
|
|
signal (SIGUSR1, usr1_handler);
|
|
if (pipe (pipefd) != 0) {
|
|
prn = NULL;
|
|
} else {
|
|
cpid = fork ();
|
|
if (cpid < 0) {
|
|
prn = NULL;
|
|
} else if (cpid == 0) {
|
|
/* LPR monitor process. Printer output is piped to us. */
|
|
opid = fork ();
|
|
if (opid < 0) {
|
|
/* Errors will cause the plugin to get a SIGPIPE. */
|
|
exit (1);
|
|
} else if (opid == 0) {
|
|
dup2 (pipefd[0], 0);
|
|
close (pipefd[0]);
|
|
close (pipefd[1]);
|
|
execl("/bin/sh", "/bin/sh", "-c", vars.output_to, NULL);
|
|
/* NOTREACHED */
|
|
exit (1);
|
|
} else {
|
|
/*
|
|
* If the print plugin gets SIGKILLed by gimp, we kill lpr
|
|
* in turn. If the plugin signals us with SIGUSR1 that it's
|
|
* finished printing normally, we close our end of the pipe,
|
|
* and go away.
|
|
*/
|
|
close (pipefd[0]);
|
|
while (usr1_interrupt == 0) {
|
|
if (kill (ppid, 0) < 0) {
|
|
/* The print plugin has been killed! */
|
|
kill (opid, SIGTERM);
|
|
waitpid (opid, &dummy, 0);
|
|
close (pipefd[1]);
|
|
/*
|
|
* We do not want to allow cleanup before exiting.
|
|
* The exiting parent has already closed the connection
|
|
* to the X server; if we try to clean up, we'll notice
|
|
* that fact and complain.
|
|
*/
|
|
_exit (0);
|
|
}
|
|
sleep (5);
|
|
}
|
|
/* We got SIGUSR1. */
|
|
close (pipefd[1]);
|
|
/*
|
|
* We do not want to allow cleanup before exiting.
|
|
* The exiting parent has already closed the connection
|
|
* to the X server; if we try to clean up, we'll notice
|
|
* that fact and complain.
|
|
*/
|
|
_exit (0);
|
|
}
|
|
} else {
|
|
close (pipefd[0]);
|
|
/* Parent process. We generate the printer output. */
|
|
prn = fdopen (pipefd[1], "w");
|
|
/* and fall through... */
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
/* OS/2 PRINT command doesn't support print from stdin, use temp file */
|
|
prn = (tmpfile = get_tmp_filename ()) ? fopen (tmpfile, "w") : NULL;
|
|
#endif
|
|
else
|
|
prn = fopen (vars.output_to, "wb");
|
|
|
|
if (prn != NULL)
|
|
{
|
|
Image image = Image_GDrawable_new(drawable);
|
|
vars.app_gamma = gimp_gamma();
|
|
merge_printvars(&vars, &(current_printer->printvars));
|
|
|
|
/*
|
|
* Is the image an Indexed type? If so we need the colormap...
|
|
*/
|
|
|
|
if (gimp_image_base_type (image_ID) == GIMP_INDEXED)
|
|
vars.cmap = gimp_image_get_cmap (image_ID, &ncolors);
|
|
else
|
|
vars.cmap = NULL;
|
|
|
|
/*
|
|
* Finally, call the print driver to send the image to the printer
|
|
* and close the output file/command...
|
|
*/
|
|
|
|
if (verify_printer_params(current_printer, &vars))
|
|
(*current_printer->print) (current_printer, 1, prn, image, &vars);
|
|
else
|
|
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
if (plist_current > 0)
|
|
#ifndef __EMX__
|
|
{
|
|
fclose (prn);
|
|
kill (cpid, SIGUSR1);
|
|
waitpid (cpid, &dummy, 0);
|
|
}
|
|
#else
|
|
{ /* PRINT temp file */
|
|
char *s;
|
|
fclose (prn);
|
|
s = g_strconcat (vars.output_to, tmpfile, NULL);
|
|
if (system(s) != 0)
|
|
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
|
|
g_free (s);
|
|
remove (tmpfile);
|
|
g_free( tmpfile);
|
|
}
|
|
#endif
|
|
else
|
|
fclose (prn);
|
|
print_finished = 1;
|
|
}
|
|
else
|
|
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
|
|
|
|
/*
|
|
* Store data...
|
|
*/
|
|
|
|
if (run_mode == GIMP_RUN_INTERACTIVE)
|
|
gimp_set_data (PLUG_IN_NAME, &vars, sizeof (vars));
|
|
}
|
|
|
|
/*
|
|
* Detach from the drawable...
|
|
*/
|
|
gimp_drawable_detach (drawable);
|
|
|
|
|
|
cleanup:
|
|
#ifndef GIMP_1_0
|
|
if (export == GIMP_EXPORT_EXPORT)
|
|
gimp_image_delete (image_ID);
|
|
#else
|
|
; /* MRS: empty statement to suppress compiler warning */
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* 'do_print_dialog()' - Pop up the print dialog...
|
|
*/
|
|
|
|
static gint
|
|
do_print_dialog (gchar *proc_name)
|
|
{
|
|
#ifdef GIMP_1_0
|
|
gchar **argv;
|
|
gint argc;
|
|
|
|
argc = 1;
|
|
argv = g_new (gchar *, 1);
|
|
argv[0] = g_strdup ("print");
|
|
|
|
gtk_init (&argc, &argv);
|
|
gtk_rc_parse (gimp_gtkrc ());
|
|
|
|
gdk_set_use_xshm (gimp_use_xshm());
|
|
#endif
|
|
|
|
/*
|
|
* Get printrc options...
|
|
*/
|
|
printrc_load ();
|
|
|
|
/*
|
|
* Print dialog window...
|
|
*/
|
|
#ifdef NEW_UI_ONLY
|
|
gimp_create_main_window();
|
|
#elif defined(GIMP_1_0)
|
|
gtk_create_main_window ();
|
|
#else
|
|
if (!strcmp (proc_name, "file_print_gimp"))
|
|
gimp_create_main_window ();
|
|
else
|
|
gtk_create_main_window ();
|
|
#endif
|
|
|
|
gtk_main ();
|
|
gdk_flush ();
|
|
|
|
/*
|
|
* Set printrc options...
|
|
*/
|
|
if (saveme)
|
|
printrc_save ();
|
|
|
|
/*
|
|
* Return ok/cancel...
|
|
*/
|
|
return (runme);
|
|
}
|
|
|
|
static void
|
|
initialize_printer(plist_t *printer)
|
|
{
|
|
const vars_t *def = print_default_settings();
|
|
printer->name[0] = '\0';
|
|
printer->active=0;
|
|
memcpy(&(printer->v), def, sizeof(vars_t));
|
|
}
|
|
|
|
#define GET_MANDATORY_STRING_PARAM(param) \
|
|
do { \
|
|
if ((commaptr = strchr(lineptr, ',')) == NULL) \
|
|
continue; \
|
|
strncpy(key.param, lineptr, commaptr - line); \
|
|
key.param[commaptr - lineptr] = '\0'; \
|
|
lineptr = commaptr + 1; \
|
|
} while (0)
|
|
|
|
#define GET_MANDATORY_INT_PARAM(param) \
|
|
do { \
|
|
if ((commaptr = strchr(lineptr, ',')) == NULL) \
|
|
continue; \
|
|
key.param = atoi(lineptr); \
|
|
lineptr = commaptr + 1; \
|
|
} while (0)
|
|
|
|
#define GET_OPTIONAL_STRING_PARAM(param) \
|
|
do { \
|
|
if ((commaptr = strchr(lineptr, ',')) == NULL) \
|
|
{ \
|
|
strcpy(key.v.param, lineptr); \
|
|
keepgoing = 0; \
|
|
key.v.param[strlen(key.v.param) - 1] = '\0'; \
|
|
} \
|
|
else \
|
|
{ \
|
|
strncpy(key.v.param, lineptr, commaptr - lineptr); \
|
|
key.v.param[commaptr - lineptr] = '\0'; \
|
|
lineptr = commaptr + 1; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define GET_OPTIONAL_INT_PARAM(param) \
|
|
do { \
|
|
if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL)) \
|
|
{ \
|
|
keepgoing = 0; \
|
|
} \
|
|
else \
|
|
{ \
|
|
key.v.param = atoi(lineptr); \
|
|
lineptr = commaptr + 1; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define GET_OPTIONAL_FLOAT_PARAM(param) \
|
|
do { \
|
|
if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL)) \
|
|
{ \
|
|
keepgoing = 0; \
|
|
} \
|
|
else \
|
|
{ \
|
|
const vars_t *maxvars = print_maximum_settings(); \
|
|
const vars_t *minvars = print_minimum_settings(); \
|
|
const vars_t *defvars = print_default_settings(); \
|
|
key.v.param = atof(lineptr); \
|
|
if (key.v.param > 0 && \
|
|
(key.v.param > 2 * maxvars->param || \
|
|
key.v.param < minvars->param)) \
|
|
key.v.param = defvars->param; \
|
|
lineptr = commaptr + 1; \
|
|
} \
|
|
} while (0)
|
|
|
|
static void *
|
|
psearch(const void *key, const void *base, size_t nmemb, size_t size,
|
|
int (*compar)(const void *, const void *))
|
|
{
|
|
int i;
|
|
const char *cbase = (const char *) base;
|
|
for (i = 0; i < nmemb; i++)
|
|
{
|
|
if ((*compar)(key, (const void *) cbase) == 0)
|
|
return (void *) cbase;
|
|
cbase += size;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* 'printrc_load()' - Load the printer resource configuration file.
|
|
*/
|
|
void
|
|
printrc_load(void)
|
|
{
|
|
int i; /* Looping var */
|
|
FILE *fp; /* Printrc file */
|
|
char *filename; /* Its name */
|
|
char line[1024], /* Line in printrc file */
|
|
*lineptr, /* Pointer in line */
|
|
*commaptr; /* Pointer to next comma */
|
|
plist_t *p = 0, /* Current printer */
|
|
key; /* Search key */
|
|
#if (GIMP_MINOR_VERSION == 0)
|
|
char *home; /* Home dir */
|
|
#endif
|
|
int format = 0; /* rc file format version */
|
|
int system_printers; /* printer count before reading printrc */
|
|
char * current_printer = 0; /* printer to select */
|
|
|
|
check_plist(1);
|
|
|
|
/*
|
|
* Get the printer list...
|
|
*/
|
|
|
|
get_system_printers();
|
|
|
|
system_printers = plist_count - 1;
|
|
|
|
/*
|
|
* Generate the filename for the current user...
|
|
*/
|
|
|
|
#if (GIMP_MINOR_VERSION == 0)
|
|
home = getenv("HOME");
|
|
if (home == NULL)
|
|
filename=g_strdup("/.gimp/printrc");
|
|
else
|
|
filename = malloc(strlen(home) + 15);
|
|
sprintf(filename, "%s/.gimp/printrc", home);
|
|
#else
|
|
filename = gimp_personal_rc_file ("printrc");
|
|
#endif
|
|
|
|
#ifdef __EMX__
|
|
_fnslashify(filename);
|
|
#endif
|
|
|
|
#ifndef __EMX__
|
|
if ((fp = fopen(filename, "r")) != NULL)
|
|
#else
|
|
if ((fp = fopen(filename, "rt")) != NULL)
|
|
#endif
|
|
{
|
|
/*
|
|
* File exists - read the contents and update the printer list...
|
|
*/
|
|
|
|
(void) memset(&key, 0, sizeof(plist_t));
|
|
(void) memset(line, 0, 1024);
|
|
while (fgets(line, sizeof(line), fp) != NULL)
|
|
{
|
|
int keepgoing = 1;
|
|
if (line[0] == '#')
|
|
{
|
|
if (strncmp("#PRINTRCv", line, 9) == 0)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Found printrc version tag: `%s'\n", line);
|
|
printf("Version number: `%s'\n", &(line[9]));
|
|
#endif
|
|
(void) sscanf(&(line[9]), "%d", &format);
|
|
}
|
|
continue; /* Comment */
|
|
}
|
|
if (format == 0)
|
|
{
|
|
/*
|
|
* Read old format printrc lines...
|
|
*/
|
|
|
|
initialize_printer(&key);
|
|
lineptr = line;
|
|
|
|
/*
|
|
* Read the command-delimited printer definition data. Note that
|
|
* we can't use sscanf because %[^,] fails if the string is empty...
|
|
*/
|
|
|
|
GET_MANDATORY_STRING_PARAM(name);
|
|
GET_MANDATORY_STRING_PARAM(v.output_to);
|
|
GET_MANDATORY_STRING_PARAM(v.driver);
|
|
|
|
if (! get_printer_by_driver(key.v.driver))
|
|
continue;
|
|
|
|
GET_MANDATORY_STRING_PARAM(v.ppd_file);
|
|
GET_MANDATORY_INT_PARAM(v.output_type);
|
|
GET_MANDATORY_STRING_PARAM(v.resolution);
|
|
GET_MANDATORY_STRING_PARAM(v.media_size);
|
|
GET_MANDATORY_STRING_PARAM(v.media_type);
|
|
|
|
GET_OPTIONAL_STRING_PARAM(media_source);
|
|
GET_OPTIONAL_FLOAT_PARAM(brightness);
|
|
GET_OPTIONAL_FLOAT_PARAM(scaling);
|
|
GET_OPTIONAL_INT_PARAM(orientation);
|
|
GET_OPTIONAL_INT_PARAM(left);
|
|
GET_OPTIONAL_INT_PARAM(top);
|
|
GET_OPTIONAL_FLOAT_PARAM(gamma);
|
|
GET_OPTIONAL_FLOAT_PARAM(contrast);
|
|
GET_OPTIONAL_FLOAT_PARAM(cyan);
|
|
GET_OPTIONAL_FLOAT_PARAM(magenta);
|
|
GET_OPTIONAL_FLOAT_PARAM(yellow);
|
|
GET_OPTIONAL_INT_PARAM(linear);
|
|
GET_OPTIONAL_INT_PARAM(image_type);
|
|
GET_OPTIONAL_FLOAT_PARAM(saturation);
|
|
GET_OPTIONAL_FLOAT_PARAM(density);
|
|
GET_OPTIONAL_STRING_PARAM(ink_type);
|
|
GET_OPTIONAL_STRING_PARAM(dither_algorithm);
|
|
GET_OPTIONAL_INT_PARAM(unit);
|
|
|
|
/*
|
|
* The format of the list is the File printer followed by a qsort'ed list
|
|
* of system printers. So, if we want to update the file printer, it is
|
|
* always first in the list, else call psearch.
|
|
*/
|
|
if ((strcmp(key.name, _("File")) == 0) && (strcmp(plist[0].name,
|
|
_("File")) == 0))
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Updated File printer directly\n");
|
|
#endif
|
|
p = &plist[0];
|
|
memcpy(p, &key, sizeof(plist_t));
|
|
p->active = 1;
|
|
}
|
|
else
|
|
{
|
|
if ((p = psearch(&key, plist + 1, plist_count - 1, sizeof(plist_t),
|
|
(int (*)(const void *, const void *))compare_printers))
|
|
!= NULL)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Updating printer %s.\n", key.name);
|
|
#endif
|
|
memcpy(p, &key, sizeof(plist_t));
|
|
p->active = 1;
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "Adding new printer from printrc file: %s\n",
|
|
key.name);
|
|
#endif
|
|
check_plist(plist_count + 1);
|
|
p = plist + plist_count;
|
|
memcpy(p, &key, sizeof(plist_t));
|
|
p->active = 0;
|
|
plist_count++;
|
|
}
|
|
}
|
|
}
|
|
else if (format == 1)
|
|
{
|
|
/*
|
|
* Read new format printrc lines...
|
|
*/
|
|
|
|
char *keyword, *end, *value;
|
|
|
|
keyword = line;
|
|
for (keyword = line; isspace(*keyword); keyword++)
|
|
{
|
|
/* skip initial spaces... */
|
|
}
|
|
if (!isalpha(*keyword))
|
|
continue;
|
|
for (end = keyword; isalnum(*end) || *end == '-'; end++)
|
|
{
|
|
/* find end of keyword... */
|
|
}
|
|
value = end;
|
|
while (isspace(*value)) {
|
|
/* skip over white space... */
|
|
value++;
|
|
}
|
|
if (*value != ':')
|
|
continue;
|
|
value++;
|
|
*end = '\0';
|
|
while (isspace(*value)) {
|
|
/* skip over white space... */
|
|
value++;
|
|
}
|
|
for (end = value; *end && *end != '\n'; end++)
|
|
{
|
|
/* find end of line... */
|
|
}
|
|
*end = '\0';
|
|
#ifdef DEBUG
|
|
printf("Keyword = `%s', value = `%s'\n", keyword, value);
|
|
#endif
|
|
if (strcasecmp("current-printer", keyword) == 0) {
|
|
if (current_printer)
|
|
free (current_printer);
|
|
current_printer = strdup(value);
|
|
} else if (strcasecmp("printer", keyword) == 0) {
|
|
/* Switch to printer named VALUE */
|
|
if (strcmp(_("File"), key.name) == 0
|
|
&& strcmp(plist[0].name, _("File")) == 0)
|
|
{
|
|
if (get_printer_by_driver(key.v.driver))
|
|
{
|
|
p = &plist[0];
|
|
memcpy(p, &key, sizeof(plist_t));
|
|
p->active = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (get_printer_by_driver(key.v.driver))
|
|
{
|
|
p = psearch(&key, plist + 1, plist_count - 1,
|
|
sizeof(plist_t),
|
|
(int (*)(const void *, const void *)) compare_printers);
|
|
if (p == NULL)
|
|
{
|
|
check_plist(plist_count + 1);
|
|
p = plist + plist_count;
|
|
plist_count++;
|
|
memcpy(p, &key, sizeof(plist_t));
|
|
p->active = 0;
|
|
}
|
|
else
|
|
{
|
|
memcpy(p, &key, sizeof(plist_t));
|
|
p->active = 1;
|
|
}
|
|
}
|
|
}
|
|
initialize_printer(&key);
|
|
strncpy(key.name, value, 127);
|
|
} else if (strcasecmp("destination", keyword) == 0) {
|
|
strncpy(key.v.output_to, value, 255);
|
|
} else if (strcasecmp("driver", keyword) == 0) {
|
|
strncpy(key.v.driver, value, 63);
|
|
} else if (strcasecmp("ppd-file", keyword) == 0) {
|
|
strncpy(key.v.ppd_file, value, 256);
|
|
} else if (strcasecmp("output-type", keyword) == 0) {
|
|
key.v.output_type = atoi(value);
|
|
} else if (strcasecmp("resolution", keyword) == 0) {
|
|
strncpy(key.v.resolution, value, 63);
|
|
} else if (strcasecmp("media-size", keyword) == 0) {
|
|
strncpy(key.v.media_size, value, 63);
|
|
} else if (strcasecmp("media-type", keyword) == 0) {
|
|
strncpy(key.v.media_type, value, 63);
|
|
} else if (strcasecmp("media-source", keyword) == 0) {
|
|
strncpy(key.v.media_source, value, 63);
|
|
} else if (strcasecmp("brightness", keyword) == 0) {
|
|
key.v.brightness = atof(value);
|
|
} else if (strcasecmp("scaling", keyword) == 0) {
|
|
key.v.scaling = atof(value);
|
|
} else if (strcasecmp("orientation", keyword) == 0) {
|
|
key.v.orientation = atoi(value);
|
|
} else if (strcasecmp("left", keyword) == 0) {
|
|
key.v.left = atoi(value);
|
|
} else if (strcasecmp("top", keyword) == 0) {
|
|
key.v.top = atoi(value);
|
|
} else if (strcasecmp("gamma", keyword) == 0) {
|
|
key.v.gamma = atof(value);
|
|
} else if (strcasecmp("contrast", keyword) == 0) {
|
|
key.v.contrast = atof(value);
|
|
} else if (strcasecmp("cyan", keyword) == 0) {
|
|
key.v.cyan = atof(value);
|
|
} else if (strcasecmp("magenta", keyword) == 0) {
|
|
key.v.magenta = atof(value);
|
|
} else if (strcasecmp("yellow", keyword) == 0) {
|
|
key.v.yellow = atof(value);
|
|
} else if (strcasecmp("linear", keyword) == 0) {
|
|
key.v.linear = atoi(value);
|
|
} else if (strcasecmp("image-type", keyword) == 0) {
|
|
key.v.image_type = atoi(value);
|
|
} else if (strcasecmp("saturation", keyword) == 0) {
|
|
key.v.saturation = atof(value);
|
|
} else if (strcasecmp("density", keyword) == 0) {
|
|
key.v.density = atof(value);
|
|
} else if (strcasecmp("ink-type", keyword) == 0) {
|
|
strncpy(key.v.ink_type, value, 63);
|
|
} else if (strcasecmp("dither-algorithm", keyword) == 0) {
|
|
strncpy(key.v.dither_algorithm, value, 63);
|
|
} else if (strcasecmp("unit", keyword) == 0) {
|
|
key.v.unit = atoi(value);
|
|
} else {
|
|
/* Unrecognised keyword; ignore it... */
|
|
#if 1
|
|
printf("Unrecognised keyword `%s' in printrc; value `%s'\n", keyword, value);
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* We cannot read this file format...
|
|
*/
|
|
}
|
|
}
|
|
if (format > 0)
|
|
{
|
|
if (strcmp(_("File"), key.name) == 0
|
|
&& strcmp(plist[0].name, _("File")) == 0)
|
|
{
|
|
if (get_printer_by_driver(key.v.driver))
|
|
{
|
|
p = &plist[0];
|
|
memcpy(p, &key, sizeof(plist_t));
|
|
p->active = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (get_printer_by_driver(key.v.driver))
|
|
{
|
|
p = psearch(&key, plist + 1, plist_count - 1,
|
|
sizeof(plist_t),
|
|
(int (*)(const void *, const void *)) compare_printers);
|
|
if (p == NULL)
|
|
{
|
|
check_plist(plist_count + 1);
|
|
p = plist + plist_count;
|
|
plist_count++;
|
|
memcpy(p, &key, sizeof(plist_t));
|
|
p->active = 0;
|
|
}
|
|
else
|
|
{
|
|
memcpy(p, &key, sizeof(plist_t));
|
|
p->active = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fclose(fp);
|
|
}
|
|
|
|
g_free (filename);
|
|
|
|
/*
|
|
* Select the current printer as necessary...
|
|
*/
|
|
|
|
if (format == 1)
|
|
{
|
|
if (current_printer)
|
|
{
|
|
for (i = 0; i < plist_count; i ++)
|
|
if (strcmp(current_printer, plist[i].name) == 0)
|
|
plist_current = i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (vars.output_to[0] != '\0')
|
|
{
|
|
for (i = 0; i < plist_count; i ++)
|
|
if (strcmp(vars.output_to, plist[i].v.output_to) == 0)
|
|
break;
|
|
|
|
if (i < plist_count)
|
|
plist_current = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* 'printrc_save()' - Save the current printer resource configuration.
|
|
*/
|
|
void
|
|
printrc_save(void)
|
|
{
|
|
FILE *fp; /* Printrc file */
|
|
char *filename; /* Printrc filename */
|
|
int i; /* Looping var */
|
|
plist_t *p; /* Current printer */
|
|
#if (GIMP_MINOR_VERSION == 0)
|
|
char *home; /* Home dir */
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Generate the filename for the current user...
|
|
*/
|
|
|
|
#if (GIMP_MINOR_VERSION == 0)
|
|
home = getenv("HOME");
|
|
if (home == NULL)
|
|
filename=g_strdup("/.gimp/printrc");
|
|
else
|
|
filename = malloc(strlen(home) + 15);
|
|
sprintf(filename, "%s/.gimp/printrc", home);
|
|
#else
|
|
filename = gimp_personal_rc_file ("printrc");
|
|
#endif
|
|
|
|
#ifdef __EMX__
|
|
_fnslashify(filename);
|
|
#endif
|
|
|
|
#ifndef __EMX__
|
|
if ((fp = fopen(filename, "w")) != NULL)
|
|
#else
|
|
if ((fp = fopen(filename, "wt")) != NULL)
|
|
#endif
|
|
{
|
|
/*
|
|
* Write the contents of the printer list...
|
|
*/
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "Number of printers: %d\n", plist_count);
|
|
#endif
|
|
|
|
#if 0
|
|
fputs("#PRINTRC " PLUG_IN_VERSION "\n", fp);
|
|
|
|
for (i = 0, p = plist; i < plist_count; i ++, p ++)
|
|
{
|
|
fprintf(fp, "%s,%s,%s,%s,%d,%s,%s,%s,%s,",
|
|
p->name, p->v.output_to, p->v.driver, p->v.ppd_file,
|
|
p->v.output_type, p->v.resolution, p->v.media_size,
|
|
p->v.media_type, p->v.media_source);
|
|
fprintf(fp, "%.3f,%.3f,%d,%d,%d,%.3f,",
|
|
p->v.brightness, p->v.scaling, p->v.orientation, p->v.left,
|
|
p->v.top, p->v.gamma);
|
|
fprintf(fp, "%.3f,%.3f,%.3f,%.3f,%d,%d,%.3f,%.3f,%s,%s,%d,\n",
|
|
p->v.contrast, p->v.cyan, p->v.magenta, p->v.yellow,
|
|
p->v.linear, p->v.image_type, p->v.saturation, p->v.density,
|
|
p->v.ink_type, p->v.dither_algorithm, p->v.unit);
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "Wrote printer %d: %s\n", i, p->name);
|
|
#endif
|
|
|
|
}
|
|
#else
|
|
fputs("#PRINTRCv1 written by GIMP-PRINT " PLUG_IN_VERSION "\n", fp);
|
|
|
|
fprintf(fp, "Current-Printer: %s\n", plist[plist_current].name);
|
|
|
|
for (i = 0, p = plist; i < plist_count; i ++, p ++)
|
|
{
|
|
fprintf(fp, "\nPrinter: %s\n", p->name);
|
|
fprintf(fp, "Destination: %s\n", p->v.output_to);
|
|
fprintf(fp, "Driver: %s\n", p->v.driver);
|
|
fprintf(fp, "PPD-File: %s\n", p->v.ppd_file);
|
|
fprintf(fp, "Output-Type: %d\n", p->v.output_type);
|
|
fprintf(fp, "Resolution: %s\n", p->v.resolution);
|
|
fprintf(fp, "Media-Size: %s\n", p->v.media_size);
|
|
fprintf(fp, "Media-Type: %s\n", p->v.media_type);
|
|
fprintf(fp, "Media-Source: %s\n", p->v.media_source);
|
|
fprintf(fp, "Brightness: %.3f\n", p->v.brightness);
|
|
fprintf(fp, "Scaling: %.3f\n", p->v.scaling);
|
|
fprintf(fp, "Orientation: %d\n", p->v.orientation);
|
|
fprintf(fp, "Left: %d\n", p->v.left);
|
|
fprintf(fp, "Top: %d\n", p->v.top);
|
|
fprintf(fp, "Gamma: %.3f\n", p->v.gamma);
|
|
fprintf(fp, "Contrast: %.3f\n", p->v.contrast);
|
|
fprintf(fp, "Cyan: %.3f\n", p->v.cyan);
|
|
fprintf(fp, "Magenta: %.3f\n", p->v.magenta);
|
|
fprintf(fp, "Yellow: %.3f\n", p->v.yellow);
|
|
fprintf(fp, "Linear: %d\n", p->v.linear);
|
|
fprintf(fp, "Image-Type: %d\n", p->v.image_type);
|
|
fprintf(fp, "Saturation: %.3f\n", p->v.saturation);
|
|
fprintf(fp, "Density: %.3f\n", p->v.density);
|
|
fprintf(fp, "Ink-Type: %s\n", p->v.ink_type);
|
|
fprintf(fp, "Dither-Algorithm: %s\n", p->v.dither_algorithm);
|
|
fprintf(fp, "Unit: %d\n", p->v.unit);
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "Wrote printer %d: %s\n", i, p->name);
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
fclose(fp);
|
|
} else {
|
|
fprintf(stderr,"could not open printrc file \"%s\"\n",filename);
|
|
}
|
|
g_free (filename);
|
|
}
|
|
|
|
|
|
/*
|
|
* 'compare_printers()' - Compare system printer names for qsort().
|
|
*/
|
|
|
|
static int
|
|
compare_printers(plist_t *p1, /* I - First printer to compare */
|
|
plist_t *p2) /* I - Second printer to compare */
|
|
{
|
|
return (strcmp(p1->name, p2->name));
|
|
}
|
|
|
|
|
|
/*
|
|
* 'get_system_printers()' - Get a complete list of printers from the spooler.
|
|
*/
|
|
|
|
#define PRINTERS_NONE 0
|
|
#define PRINTERS_LPC 1
|
|
#define PRINTERS_LPSTAT 2
|
|
|
|
static void
|
|
get_system_printers(void)
|
|
{
|
|
int i; /* Looping var */
|
|
int type; /* 0 = none, 1 = lpc, 2 = lpstat */
|
|
char command[255]; /* Command to run */
|
|
char defname[128]; /* Default printer name */
|
|
FILE *pfile; /* Pipe to status command */
|
|
char line[255]; /* Line from status command */
|
|
char *ptr; /* Pointer into line */
|
|
char name[128]; /* Printer name from status command */
|
|
#ifdef __EMX__
|
|
BYTE pnum;
|
|
#endif
|
|
static char *lpcs[] = /* Possible locations of LPC... */
|
|
{
|
|
"/etc"
|
|
"/usr/bsd",
|
|
"/usr/etc",
|
|
"/usr/libexec",
|
|
"/usr/sbin"
|
|
};
|
|
|
|
|
|
/*
|
|
* Setup defaults...
|
|
*/
|
|
|
|
defname[0] = '\0';
|
|
|
|
check_plist(1);
|
|
plist_count = 1;
|
|
initialize_printer(&plist[0]);
|
|
strcpy(plist[0].name, _("File"));
|
|
plist[0].v.output_to[0] = '\0';
|
|
strcpy(plist[0].v.driver, "ps2");
|
|
plist[0].v.output_type = OUTPUT_COLOR;
|
|
|
|
/*
|
|
* Figure out what command to run... We use lpstat if it is available over
|
|
* lpc since Solaris, CUPS, etc. provide both commands. No need to list
|
|
* each printer twice...
|
|
*/
|
|
|
|
if (!access("/usr/bin/lpstat", X_OK))
|
|
{
|
|
strcpy(command, "/usr/bin/lpstat -d -p");
|
|
type = PRINTERS_LPSTAT;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < G_N_ELEMENTS (lpcs); i ++)
|
|
{
|
|
sprintf(command, "%s/lpc", lpcs[i]);
|
|
|
|
if (!access(command, X_OK))
|
|
break;
|
|
}
|
|
|
|
if (i < G_N_ELEMENTS (lpcs))
|
|
{
|
|
strcat(command, " status < /dev/null");
|
|
type = PRINTERS_LPC;
|
|
}
|
|
else
|
|
type = PRINTERS_NONE;
|
|
}
|
|
|
|
/*
|
|
* Run the command, if any, to get the available printers...
|
|
*/
|
|
|
|
if (type > PRINTERS_NONE)
|
|
{
|
|
if ((pfile = popen(command, "r")) != NULL)
|
|
{
|
|
/*
|
|
* Read input as needed...
|
|
*/
|
|
|
|
while (fgets(line, sizeof(line), pfile) != NULL)
|
|
switch (type)
|
|
{
|
|
case PRINTERS_LPC :
|
|
if (!strncmp(line, "Press RETURN to continue", 24) &&
|
|
(ptr = strchr(line, ':')) != NULL &&
|
|
(strlen(ptr) - 2) < (ptr - line))
|
|
strcpy(line, ptr + 2);
|
|
|
|
if ((ptr = strchr(line, ':')) != NULL &&
|
|
line[0] != ' ' && line[0] != '\t')
|
|
{
|
|
check_plist(plist_count + 1);
|
|
*ptr = '\0';
|
|
initialize_printer(&plist[plist_count]);
|
|
strncpy(plist[plist_count].name, line, sizeof(plist[0].name) - 1);
|
|
plist[plist_count].name[sizeof(plist[0].name) - 1] = '\0';
|
|
sprintf(plist[plist_count].v.output_to, "lpr -P%s -l", line);
|
|
strcpy(plist[plist_count].v.driver, "ps2");
|
|
plist_count ++;
|
|
}
|
|
break;
|
|
|
|
case PRINTERS_LPSTAT :
|
|
if ((sscanf(line, "printer %127s", name) == 1) ||
|
|
(sscanf(line, "Printer: %127s", name) == 1))
|
|
{
|
|
check_plist(plist_count + 1);
|
|
initialize_printer(&plist[plist_count]);
|
|
strcpy(plist[plist_count].name, name);
|
|
sprintf(plist[plist_count].v.output_to, "lp -s -d%s -oraw", name);
|
|
strcpy(plist[plist_count].v.driver, "ps2");
|
|
plist_count ++;
|
|
}
|
|
else
|
|
sscanf(line, "system default destination: %127s", defname);
|
|
break;
|
|
}
|
|
|
|
pclose(pfile);
|
|
}
|
|
}
|
|
|
|
#ifdef __EMX__
|
|
if (DosDevConfig(&pnum, DEVINFO_PRINTER) == NO_ERROR)
|
|
{
|
|
for (i = 1; i <= pnum; i++)
|
|
{
|
|
check_plist(plist_count + 1);
|
|
initialize_printer(&plist[plist_count]);
|
|
sprintf(plist[plist_count].name, "LPT%d:", i);
|
|
sprintf(plist[plist_count].v.output_to, "PRINT /D:LPT%d /B ", i);
|
|
strcpy(plist[plist_count].v.driver, "ps2");
|
|
plist_count ++;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (plist_count > 2)
|
|
qsort(plist + 1, plist_count - 1, sizeof(plist_t),
|
|
(int (*)(const void *, const void *))compare_printers);
|
|
|
|
if (defname[0] != '\0' && vars.output_to[0] == '\0')
|
|
{
|
|
for (i = 0; i < plist_count; i ++)
|
|
if (strcmp(defname, plist[i].name) == 0)
|
|
break;
|
|
|
|
if (i < plist_count)
|
|
plist_current = i;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* End of "$Id$".
|
|
*/
|