gimp/plug-ins/print/print.c

1455 lines
40 KiB
C
Raw Normal View History

1997-11-25 06:05:25 +08:00
/*
* "$Id$"
*
* Print plug-in for the GIMP.
*
* Copyright 1997-1998 Michael Sweet (mike@easysw.com)
1997-11-25 06:05:25 +08:00
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Contents:
*
* main() - Main entry - just call gimp_main()...
* query() - Respond to a plug-in query...
* run() - Run the plug-in...
* print_dialog() - Pop up the print dialog...
* dialog_create_ivalue() - Create an integer value control...
* dialog_iscale_update() - Update the value field using the scale.
* dialog_ientry_update() - Update the value field using the text entry.
* print_driver_callback() - Update the current printer driver...
* media_size_callback() - Update the current media size...
* print_command_callback() - Update the print command...
* output_type_callback() - Update the current output type...
* print_callback() - Start the print...
* cancel_callback() - Cancel the print...
* close_callback() - Exit the print dialog application.
*
* Revision History:
*
* $Log$
* Revision 1.3 1998/03/19 02:11:42 adrian
* *AlienMap/AlienMap.c CEL/CEL.c CML_explorer/CML_explorer.c
* align_layers/align_layers.c animationplay/animationplay.c
* bmp/bmpwrite.c dbbrowser/dbbrowser.c emboss/emboss.c
* exchange/exchange.c faxg3/faxg3.c faxg3/g3.c gbr/gbr.c
* gif/gif.c gqbist/gqbist.c hot/hot.c ifscompose/ifscompose.c
* iwarp/iwarp.c max_rgb/max_rgb.c maze/maze_face.c
* megawidget/megawidget.c mpeg/mpeg.c nlfilt/nlfilt.c pcx/pcx.c
* plasma/plasma.c pnm/pnm.c print/print-escp2.c
* print/print-pcl.c print/print.c scatter_hsv/scatter_hsv.c
* script-fu/script-fu-scripts.c script-fu/script-fu.c
* sinus/sinus.c tga/tga.c tileit/tileit.c
* vpropagate/vpropagate.c xpm/xpm.c: More picky picky ansi type
* stuff from gimp-hpux-980316.patch.
*
* isnt big patches fun?
*
* -adrian
*
* Revision 1.2 1998/01/25 09:29:27 yosh
* Plugin updates
* Properly generated aa Makefile (still not built by default)
* Sven's no args script patch
1997-11-25 06:05:25 +08:00
*
* -Yosh
1997-11-25 06:05:25 +08:00
*
* Revision 1.13 1998/01/22 15:06:31 mike
* Added "file" printer for printing to file.
* Now you don't need the "|" in front of print commands.
* Now "remembers" last selected printer.
1997-11-25 06:05:25 +08:00
*
* Revision 1.12 1998/01/21 21:33:47 mike
* Added Level 2 PostScript driver.
* Fixed bug in dialog - didn't display correct output file/command
* and driver for the default printer.
1997-11-25 06:05:25 +08:00
*
* Revision 1.11 1997/11/14 17:17:59 mike
* Updated to dynamically allocate return params in the run() function.
*
* Revision 1.10 1997/11/12 15:57:48 mike
* Minor changes for clean compiles under Digital UNIX.
*
* Revision 1.9 1997/10/22 13:07:20 mike
* Fixed typo in run() return status (thanks Michael Schubart!)
*
* Revision 1.8 1997/10/02 17:57:26 mike
* Added printrc support.
* Added printer list (spooler support).
* Added gamma/dot gain correction values for all printers.
*
* Revision 1.8 1997/10/02 17:57:26 mike
* Added printrc support.
* Added printer list (spooler support).
* Added gamma/dot gain correction values for all printers.
*
* Revision 1.7 1997/07/30 20:33:05 mike
* Final changes for 1.1 release.
*
* Revision 1.6 1997/07/30 18:47:39 mike
* Added scaling, orientation, and offset options.
* Added first cut at preview window.
*
* Revision 1.5 1997/07/26 18:38:23 mike
* Whoops - wasn't grabbing the colormap for indexed images properly...
*
* Revision 1.4 1997/07/03 13:13:26 mike
* Updated documentation for 1.0 release.
*
* Revision 1.3 1997/07/03 13:07:05 mike
* Updated EPSON driver short names.
* Changed brightness lut formula for better control.
*
* Revision 1.2 1997/07/02 15:22:17 mike
* Added GUI with printer/media/output selection controls.
*
* Revision 1.1 1997/07/02 13:51:53 mike
* Initial revision
*/
#include "print.h"
#include <math.h>
#include <signal.h>
/*
* Constants for GUI...
*/
#define SCALE_WIDTH 64
#define ENTRY_WIDTH 64
#define PREVIEW_SIZE 180 /* Assuming max media size of 18" */
#define MAX_PLIST 100
/*
* Types...
*/
typedef struct /**** Printer List ****/
{
char name[17], /* Name of printer */
command[255], /* Printer command */
driver[33]; /* Short name of printer driver */
int output_type; /* Color/B&W */
} plist_t;
/*
* Local functions...
*/
static void printrc_load(void);
static void printrc_save(void);
static int compare_printers(plist_t *p1, plist_t *p2);
static void get_printers(void);
static void query(void);
static void run(char *, int, GParam *, int *, GParam **);
static int print_dialog(void);
static void dialog_create_ivalue(char *, GtkTable *, int, gint *, int, int);
static void dialog_iscale_update(GtkAdjustment *, gint *);
static void dialog_ientry_update(GtkWidget *, gint *);
static void plist_callback(GtkWidget *, gint);
static void print_driver_callback(GtkWidget *, gint);
static void media_size_callback(GtkWidget *, gint);
static void print_command_callback(GtkWidget *, gpointer);
static void output_type_callback(GtkWidget *, gint);
static void orientation_callback(GtkWidget *, gint);
static void print_callback(GtkWidget *, gpointer);
static void cancel_callback(GtkWidget *, gpointer);
static void close_callback(GtkWidget *, gpointer);
static void preview_update(void);
static void preview_button_callback(GtkWidget *, GdkEventButton *);
static void preview_motion_callback(GtkWidget *, GdkEventMotion *);
/*
* Globals...
*/
GPlugInInfo PLUG_IN_INFO = /* Plug-in information */
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
struct /* Plug-in variables */
{
char output_to[255], /* Name of file or command to print to */
short_name[33]; /* Name of printer "driver" */
gint media_size, /* Size of output media */
output_type, /* Color or grayscale output */
brightness, /* Output brightness */
scaling, /* Scaling, percent of printable area */
orientation, /* Orientation - 0 = port., 1 = land., -1 = auto */
left, /* Offset from lower-lefthand corner, 10ths */
top; /* ... */
} vars =
{
"", /* Name of file or command to print to */
"ps2", /* Name of printer "driver" */
1997-11-25 06:05:25 +08:00
MEDIA_LETTER, /* Size of output media */
OUTPUT_COLOR, /* Color or grayscale output */
100, /* Output brightness */
100, /* Scaling (100% means entire printable area */
-1, /* Orientation (-1 = automatic) */
-1, /* X offset (-1 = center) */
-1 /* Y offset (-1 = center) */
};
GtkWidget *printer_driver, /* Printer driver widget */
*output_gray, /* Output type toggle, black */
*output_color, /* Output type toggle, color */
*output_to; /* Output file/command text entry */
GtkDrawingArea *preview; /* Preview drawing area widget */
int mouse_x, /* Last mouse X */
mouse_y; /* Last mouse Y */
int image_width, /* Width of image */
image_height, /* Height of image */
page_left, /* Left pixel column of page */
page_top, /* Top pixel row of page */
page_width, /* Width of page on screen */
page_height, /* Height of page on screen */
print_width, /* Printed width of image */
print_height; /* Printed height of image */
int plist_current = 0, /* Current system printer */
plist_count = 0; /* Number of system printers */
plist_t plist[MAX_PLIST]; /* System printers */
int runme = FALSE, /* True if print should proceed */
current_printer = 0; /* Current printer index */
printer_t printers[] = /* List of supported printer types */
{
{ "PostScript Printer", "ps", 72, 72, 1, 1, 0, 1.000, 1.000, ps_print },
{ "PostScript Printer (Level 2)", "ps2", 72, 72, 1, 1, 1, 1.000, 1.000, ps_print },
1997-11-25 06:05:25 +08:00
{ "HP DeskJet 500, 520", "pcl-500", 300, 300, 0, 0, 500, 0.541, 0.548, pcl_print },
{ "HP DeskJet 500C, 540C", "pcl-501", 300, 300, 0, 1, 501, 0.541, 0.548, pcl_print },
{ "HP DeskJet 550C, 560C", "pcl-550", 300, 300, 0, 1, 550, 0.541, 0.548, pcl_print },
{ "HP DeskJet 600 series", "pcl-600", 600, 300, 0, 1, 600, 0.541, 0.548, pcl_print },
{ "HP DeskJet 800 series", "pcl-800", 600, 600, 0, 1, 800, 0.541, 0.548, pcl_print },
{ "HP DeskJet 1200C, 1600C", "pcl-1200", 300, 300, 0, 1, 1200, 0.541, 0.548, pcl_print },
{ "HP LaserJet II series", "pcl-2", 300, 300, 0, 0, 2, 0.563, 0.596, pcl_print },
{ "HP LaserJet III series", "pcl-3", 300, 300, 0, 0, 3, 0.563, 0.596, pcl_print },
{ "HP LaserJet 4 series", "pcl-4", 600, 600, 1, 0, 4, 0.599, 0.615, pcl_print },
{ "HP LaserJet 5 series", "pcl-5", 600, 600, 1, 0, 4, 0.599, 0.615, pcl_print },
{ "HP LaserJet 6 series", "pcl-6", 600, 600, 1, 0, 4, 0.599, 0.615, pcl_print },
{ "EPSON Stylus Color", "escp2", 720, 720, 0, 1, 0, 0.325, 0.478, escp2_print },
{ "EPSON Stylus Color Pro", "escp2-pro", 720, 720, 0, 1, 1, 0.325, 0.478, escp2_print },
{ "EPSON Stylus Color Pro XL","escp2-proxl", 720, 720, 1, 1, 1, 0.325, 0.478, escp2_print },
{ "EPSON Stylus Color 1500", "escp2-1500", 720, 720, 1, 1, 2, 0.325, 0.478, escp2_print },
{ "EPSON Stylus Color 400", "escp2-400", 720, 720, 0, 1, 1, 0.530, 0.482, escp2_print },
{ "EPSON Stylus Color 500", "escp2-500", 720, 720, 0, 1, 1, 0.530, 0.482, escp2_print },
{ "EPSON Stylus Color 600", "escp2-600", 720, 720, 0, 1, 3, 0.530, 0.482, escp2_print },
{ "EPSON Stylus Color 800", "escp2-800", 720, 720, 0, 1, 4, 0.530, 0.482, escp2_print },
{ "EPSON Stylus Color 1520", "escp2-1520", 720, 720, 1, 1, 4, 0.530, 0.482, escp2_print },
{ "EPSON Stylus Color 3000", "escp2-3000", 720, 720, 1, 1, 4, 0.530, 0.482, escp2_print }
};
/*
* 'main()' - Main entry - just call gimp_main()...
*/
int
main(int argc, /* I - Number of command-line args */
char *argv[]) /* I - Command-line args */
{
return (gimp_main(argc, argv));
}
/*
* 'query()' - Respond to a plug-in query...
*/
static void
query(void)
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_STRING, "output_to", "Print command or filename (| to pipe to command)" },
{ PARAM_STRING, "driver", "Printer driver short name" },
{ PARAM_INT32, "media_size", "Media size (0 = A/letter, 1 = legal, 2 = B/tabloid, 3 = A4, 4 = A3)" },
{ PARAM_INT32, "output_type", "Output type (0 = gray, 1 = color)" },
{ PARAM_INT32, "brightness", "Brightness (0-200%)" },
{ PARAM_INT32, "scaling", "Output scaling (0-100%)" },
{ PARAM_INT32, "orientation", "Output orientation (-1 = auto, 0 = portrait, 1 = landscape)" },
{ PARAM_INT32, "left", "Left offset (10ths inches, -1 = centered)" },
{ PARAM_INT32, "top", "Top offset (10ths inches, -1 = centered)" }
};
static int nargs = sizeof(args) / sizeof(args[0]);
gimp_install_procedure(
"file_print",
"This plug-in prints images from The GIMP.",
"Prints images to PostScript, PCL, or ESC/P2 printers.",
"Michael Sweet <mike@easysw.com>",
"Copyright 1997 by Michael Sweet",
PLUG_IN_VERSION,
"<Image>/File/Print...",
"RGB*,GRAY*INDEXED*",
PROC_PLUG_IN,
nargs,
0,
args,
NULL);
}
/*
* 'run()' - Run the plug-in...
*/
static void
run(char *name, /* I - Name of print program. */
int nparams, /* I - Number of parameters passed in */
GParam *param, /* I - Parameter values */
int *nreturn_vals, /* O - Number of return values */
GParam **return_vals) /* O - Return values */
{
GDrawable *drawable; /* Drawable for image */
GRunModeType run_mode; /* Current run mode */
FILE *prn; /* Print file/command */
printer_t *printer; /* Printer driver entry */
int i, j; /* Looping vars */
float brightness; /* Computed brightness */
guchar lut[256]; /* Lookup table for brightness */
guchar *cmap; /* Colormap (indexed images only) */
int ncolors; /* Number of colors in colormap */
GParam *values; /* Return values */
/*
* Initialize parameter data...
*/
run_mode = param[0].data.d_int32;
values = g_new(GParam, 1);
values[0].type = PARAM_STATUS;
values[0].data.d_status = STATUS_SUCCESS;
*nreturn_vals = 1;
*return_vals = values;
/*
* Get drawable...
*/
drawable = gimp_drawable_get(param[2].data.d_drawable);
image_width = drawable->width;
image_height = drawable->height;
/*
* See how we will run
*/
switch (run_mode)
{
case RUN_INTERACTIVE :
/*
* Possibly retrieve data...
*/
gimp_get_data(PLUG_IN_NAME, &vars);
for (i = 0; i < (sizeof(printers) / sizeof(printers[0])); i ++)
if (strcmp(printers[i].short_name, vars.short_name) == 0)
current_printer = i;
/*
* Get information from the dialog...
*/
if (!print_dialog())
return;
break;
case RUN_NONINTERACTIVE :
/*
* Make sure all the arguments are present...
*/
if (nparams < 8)
values[0].data.d_status = STATUS_CALLING_ERROR;
else
{
strcpy(vars.output_to, param[3].data.d_string);
strcpy(vars.short_name, param[4].data.d_string);
vars.media_size = param[5].data.d_int32;
vars.output_type = param[6].data.d_int32;
vars.brightness = param[7].data.d_int32;
if (nparams > 8)
vars.scaling = param[8].data.d_int32;
else
vars.scaling = 100;
if (nparams > 9)
vars.orientation = param[9].data.d_int32;
else
vars.orientation = -1;
if (nparams > 10)
vars.left = param[10].data.d_int32;
else
vars.left = -1;
if (nparams > 11)
vars.top = param[11].data.d_int32;
else
vars.top = -1;
for (i = 0; i < (sizeof(printers) / sizeof(printers[0])); i ++)
if (strcmp(printers[i].short_name, vars.short_name) == 0)
current_printer = i;
};
break;
case RUN_WITH_LAST_VALS :
/*
* Possibly retrieve data...
*/
gimp_get_data(PLUG_IN_NAME, &vars);
for (i = 0; i < (sizeof(printers) / sizeof(printers[0])); i ++)
if (strcmp(printers[i].short_name, vars.short_name) == 0)
current_printer = i;
break;
default :
values[0].data.d_status = STATUS_CALLING_ERROR;
break;;
};
/*
* Print the image...
*/
signal(SIGBUS, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
if (values[0].data.d_status == STATUS_SUCCESS)
{
/*
* Set the tile cache size...
*/
gimp_tile_cache_ntiles((drawable->width + gimp_tile_width() - 1) /
gimp_tile_width());
/*
* Open the file/execute the print command...
*/
if (plist_current > 0)
prn = popen(vars.output_to, "w");
1997-11-25 06:05:25 +08:00
else
prn = fopen(vars.output_to, "w");
if (prn != NULL)
{
/*
* Got an output file/command, now compute a brightness lookup table...
*/
printer = printers + current_printer;
brightness = 25500.0 * printer->density / vars.brightness;
for (i = 0; i < 256; i ++)
{
j = 255.5 - brightness * (1.0 - pow((float)i / 255.0, printer->gamma));
if (j < 0)
lut[i] = 0;
else if (j < 255)
lut[i] = j;
else
lut[i] = 255;
};
/*
* Is the image an Indexed type? If so we need the colormap...
*/
if (gimp_image_base_type(param[1].data.d_image) == INDEXED)
cmap = gimp_image_get_cmap(param[1].data.d_image, &ncolors);
else
{
cmap = NULL;
ncolors = 0;
};
/*
* Finally, call the print driver to send the image to the printer and
* close the output file/command...
*/
(*printer->print)(prn, drawable, vars.media_size, printer->xdpi, printer->ydpi,
vars.output_type, printer->model, lut, cmap,
vars.orientation, vars.scaling, vars.left, vars.top);
if (plist_current > 0)
1997-11-25 06:05:25 +08:00
pclose(prn);
else
fclose(prn);
}
else
values[0].data.d_status = STATUS_EXECUTION_ERROR;
/*
* Store data...
*/
if (run_mode == RUN_INTERACTIVE)
gimp_set_data(PLUG_IN_NAME, &vars, sizeof(vars));
};
/*
* Detach from the drawable...
*/
gimp_drawable_detach(drawable);
}
/*
* 'print_dialog()' - Pop up the print dialog...
*/
static int
1997-11-25 06:05:25 +08:00
print_dialog(void)
{
int i; /* Looping var */
GtkWidget *dialog, /* Dialog window */
*table, /* Table "container" for controls */
*label, /* Label string */
*button, /* OK/Cancel buttons */
*entry, /* Print file/command text entry */
*menu, /* Menu of drivers/sizes */
*item, /* Menu item */
*option; /* Option menu button */
GSList *group; /* Grouping for output type */
gint argc; /* Fake argc for GUI */
gchar **argv; /* Fake argv for GUI */
static char *sizes[] = /* Size strings */
{
"A/Letter (8.5x11\")",
"Legal (8.5x14\")",
"B/Tabloid (11x17\")",
"A4 (210x297mm)",
"A3 (297x420mm)"
};
static char *orients[] = /* Orientation strings */
{
"Auto",
"Portrait",
"Landscape"
};
/*
* Initialize the program's display...
*/
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());
/*
* Get printrc options...
*/
printrc_load();
/*
* Dialog window...
*/
dialog = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dialog), "Print " PLUG_IN_VERSION);
1997-11-25 06:05:25 +08:00
gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
gtk_container_border_width(GTK_CONTAINER(dialog), 0);
gtk_signal_connect(GTK_OBJECT(dialog), "destroy",
(GtkSignalFunc) close_callback,
NULL);
/*
* Top-level table for dialog...
*/
table = gtk_table_new(13, 3, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 6);
gtk_table_set_row_spacings(GTK_TABLE(table), 4);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table, FALSE, FALSE, 0);
gtk_widget_show(table);
/*
* Drawing area for page preview...
*/
preview = (GtkDrawingArea *)gtk_drawing_area_new();
gtk_drawing_area_size(preview, PREVIEW_SIZE, PREVIEW_SIZE);
gtk_table_attach(GTK_TABLE(table), (GtkWidget *)preview, 0, 3, 0, 4, 0, 0, 0, 0);
gtk_signal_connect(GTK_OBJECT((GtkWidget *)preview), "expose_event",
(GtkSignalFunc)preview_update,
NULL);
gtk_signal_connect(GTK_OBJECT((GtkWidget *)preview), "button_press_event",
(GtkSignalFunc)preview_button_callback,
NULL);
gtk_signal_connect(GTK_OBJECT((GtkWidget *)preview), "button_release_event",
(GtkSignalFunc)preview_button_callback,
NULL);
gtk_signal_connect(GTK_OBJECT((GtkWidget *)preview), "motion_notify_event",
(GtkSignalFunc)preview_motion_callback,
NULL);
gtk_widget_show((GtkWidget *)preview);
gtk_widget_set_events((GtkWidget *)preview,
GDK_EXPOSURE_MASK | GDK_BUTTON_MOTION_MASK |
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
/*
* Printer option menu...
*/
label = gtk_label_new("Printer:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
menu = gtk_menu_new();
for (i = 0; i < plist_count; i ++)
{
item = gtk_menu_item_new_with_label(plist[i].name);
gtk_menu_append(GTK_MENU(menu), item);
gtk_signal_connect(GTK_OBJECT(item), "activate",
(GtkSignalFunc)plist_callback,
(gpointer)i);
gtk_widget_show(item);
};
option = gtk_option_menu_new();
gtk_table_attach(GTK_TABLE(table), option, 1, 3, 4, 5,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_option_menu_set_menu(GTK_OPTION_MENU(option), menu);
gtk_option_menu_set_history(GTK_OPTION_MENU(option), plist_current);
gtk_widget_show(option);
/*
* Printer driver option menu...
*/
label = gtk_label_new("Driver:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
menu = gtk_menu_new();
for (i = 0; i < (int)(sizeof(printers) / sizeof(printers[0])); i ++)
{
item = gtk_menu_item_new_with_label(printers[i].long_name);
gtk_menu_append(GTK_MENU(menu), item);
gtk_signal_connect(GTK_OBJECT(item), "activate",
(GtkSignalFunc)print_driver_callback,
(gpointer)i);
gtk_widget_show(item);
};
printer_driver = option = gtk_option_menu_new();
gtk_table_attach(GTK_TABLE(table), option, 1, 3, 5, 6,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_option_menu_set_menu(GTK_OPTION_MENU(option), menu);
gtk_option_menu_set_history(GTK_OPTION_MENU(option), current_printer);
gtk_widget_show(option);
/*
* Output type toggles...
*/
label = gtk_label_new("Output Type:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 6, 7, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
output_gray = button = gtk_radio_button_new_with_label(NULL, "B&W");
group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
gtk_signal_connect(GTK_OBJECT(button), "toggled",
(GtkSignalFunc)output_type_callback,
(gpointer)OUTPUT_GRAY);
gtk_table_attach(GTK_TABLE(table), button, 1, 2, 6, 7, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(button);
if (vars.output_type == 0)
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
output_color = button = gtk_radio_button_new_with_label(group, "Color");
gtk_signal_connect(GTK_OBJECT(button), "toggled",
(GtkSignalFunc)output_type_callback,
(gpointer)OUTPUT_COLOR);
gtk_table_attach(GTK_TABLE(table), button, 2, 3, 6, 7, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(button);
if (vars.output_type == 1)
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
/*
* Media size option menu...
*/
label = gtk_label_new("Media Size:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 7, 8, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
menu = gtk_menu_new();
for (i = 0; i < (int)(sizeof(sizes) / sizeof(sizes[0])); i ++)
{
item = gtk_menu_item_new_with_label(sizes[i]);
gtk_menu_append(GTK_MENU(menu), item);
gtk_signal_connect(GTK_OBJECT(item), "activate",
(GtkSignalFunc)media_size_callback,
(gpointer)i);
gtk_widget_show(item);
};
option = gtk_option_menu_new();
gtk_table_attach(GTK_TABLE(table), option, 1, 3, 7, 8,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_option_menu_set_menu(GTK_OPTION_MENU(option), menu);
gtk_option_menu_set_history(GTK_OPTION_MENU(option), vars.media_size);
gtk_widget_show(option);
/*
* Orientation option menu...
*/
label = gtk_label_new("Orientation:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 8, 9, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
menu = gtk_menu_new();
for (i = 0; i < (int)(sizeof(orients) / sizeof(orients[0])); i ++)
{
item = gtk_menu_item_new_with_label(orients[i]);
gtk_menu_append(GTK_MENU(menu), item);
gtk_signal_connect(GTK_OBJECT(item), "activate",
(GtkSignalFunc)orientation_callback,
(gpointer)(i - 1));
gtk_widget_show(item);
};
option = gtk_option_menu_new();
gtk_table_attach(GTK_TABLE(table), option, 1, 3, 8, 9,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_option_menu_set_menu(GTK_OPTION_MENU(option), menu);
gtk_option_menu_set_history(GTK_OPTION_MENU(option), vars.orientation + 1);
gtk_widget_show(option);
/*
* Scaling slider...
*/
dialog_create_ivalue("Scaling:", GTK_TABLE(table), 9, &(vars.scaling), 1, 101);
/*
* Brightness slider...
*/
dialog_create_ivalue("Brightness:", GTK_TABLE(table), 10, &(vars.brightness), 50, 201);
/*
* Print file/command...
*/
label = gtk_label_new("File/Command:");
1997-11-25 06:05:25 +08:00
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 11, 12, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
output_to = entry = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(entry), vars.output_to);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
(GtkSignalFunc)print_command_callback, NULL);
gtk_table_attach(GTK_TABLE(table), entry, 1, 3, 11, 12, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(entry);
/*
* Print, cancel buttons...
*/
gtk_container_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), 6);
button = gtk_button_new_with_label("Print");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc)print_callback,
dialog);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default(button);
gtk_widget_show(button);
button = gtk_button_new_with_label("Cancel");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc)cancel_callback,
dialog);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show(button);
/*
* Show it and wait for the user to do something...
*/
plist_callback(NULL, plist_current);
1997-11-25 06:05:25 +08:00
gtk_widget_show(dialog);
gtk_main();
gdk_flush();
/*
* Set printrc options...
*/
printrc_save();
/*
* Return ok/cancel...
*/
return (runme);
}
/*
* 'dialog_create_ivalue()' - Create an integer value control...
*/
static void
dialog_create_ivalue(char *title, /* I - Label for control */
GtkTable *table, /* I - Table container to use */
int row, /* I - Row # for container */
gint *value, /* I - Value holder */
int left, /* I - Minimum value for slider */
int right) /* I - Maximum value for slider */
{
GtkWidget *label, /* Control label */
*scale, /* Scale widget */
*entry; /* Text widget */
GtkObject *scale_data; /* Scale data */
char buf[256]; /* String buffer */
/*
* Label...
*/
label = gtk_label_new(title);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 1.0);
gtk_table_attach(table, label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
/*
* Scale...
*/
scale_data = gtk_adjustment_new(*value, left, right, 1.0, 1.0, 1.0);
gtk_signal_connect(GTK_OBJECT(scale_data), "value_changed",
(GtkSignalFunc) dialog_iscale_update,
value);
scale = gtk_hscale_new(GTK_ADJUSTMENT(scale_data));
gtk_widget_set_usize(scale, SCALE_WIDTH, 0);
gtk_table_attach(table, scale, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE);
gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS);
gtk_widget_show(scale);
/*
* Text entry...
*/
entry = gtk_entry_new();
gtk_object_set_user_data(GTK_OBJECT(entry), scale_data);
gtk_object_set_user_data(scale_data, entry);
gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
sprintf(buf, "%d", *value);
gtk_entry_set_text(GTK_ENTRY(entry), buf);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
(GtkSignalFunc) dialog_ientry_update,
value);
gtk_table_attach(GTK_TABLE(table), entry, 2, 3, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(entry);
}
/*
* 'dialog_iscale_update()' - Update the value field using the scale.
*/
static void
dialog_iscale_update(GtkAdjustment *adjustment, /* I - New value */
gint *value) /* I - Current value */
{
GtkWidget *entry; /* Text entry widget */
char buf[256]; /* Text buffer */
if (*value != adjustment->value)
{
*value = adjustment->value;
entry = gtk_object_get_user_data(GTK_OBJECT(adjustment));
sprintf(buf, "%d", *value);
gtk_signal_handler_block_by_data(GTK_OBJECT(entry), value);
gtk_entry_set_text(GTK_ENTRY(entry), buf);
gtk_signal_handler_unblock_by_data(GTK_OBJECT(entry), value);
if (value == &(vars.scaling))
preview_update();
};
}
/*
* 'dialog_ientry_update()' - Update the value field using the text entry.
*/
static void
dialog_ientry_update(GtkWidget *widget, /* I - Entry widget */
gint *value) /* I - Current value */
{
GtkAdjustment *adjustment;
gint new_value;
new_value = atoi(gtk_entry_get_text(GTK_ENTRY(widget)));
if (*value != new_value)
{
adjustment = gtk_object_get_user_data(GTK_OBJECT(widget));
if ((new_value >= adjustment->lower) &&
(new_value <= adjustment->upper))
{
*value = new_value;
adjustment->value = new_value;
gtk_signal_emit_by_name(GTK_OBJECT(adjustment), "value_changed");
};
};
}
/*
* 'plist_callback()' - Update the current system printer...
*/
static void
plist_callback(GtkWidget *widget, /* I - Driver option menu */
gint data) /* I - Data */
{
int i;
plist_current = data;
if (plist[plist_current].driver[0] != '\0')
{
strcpy(vars.short_name, plist[plist_current].driver);
for (i = 0; i < (sizeof(printers) / sizeof(printers[0])); i ++)
if (strcmp(printers[i].short_name, vars.short_name) == 0)
{
current_printer = i;
break;
};
gtk_option_menu_set_history(GTK_OPTION_MENU(printer_driver), current_printer);
};
if (plist[plist_current].command[0] != '\0')
{
strcpy(vars.output_to, plist[plist_current].command);
gtk_entry_set_text(GTK_ENTRY(output_to), vars.output_to);
};
if (plist[plist_current].output_type == OUTPUT_GRAY)
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(output_gray), TRUE);
else
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(output_color), TRUE);
}
/*
* 'print_driver_callback()' - Update the current printer driver...
*/
static void
print_driver_callback(GtkWidget *widget, /* I - Driver option menu */
gint data) /* I - Data */
{
current_printer = data;
strcpy(vars.short_name, printers[current_printer].short_name);
strcpy(plist[plist_current].driver, printers[current_printer].short_name);
}
/*
* 'media_size_callback()' - Update the current media size...
*/
static void
media_size_callback(GtkWidget *widget, /* I - Media size option menu */
gint data) /* I - Data */
{
vars.media_size = data;
vars.left = -1;
vars.top = -1;
preview_update();
}
/*
* 'orientation_callback()' - Update the current media size...
*/
static void
orientation_callback(GtkWidget *widget, /* I - Orientation option menu */
gint data) /* I - Data */
{
vars.orientation = data;
vars.left = -1;
vars.top = -1;
preview_update();
}
/*
* 'print_command_callback()' - Update the print command...
*/
static void
print_command_callback(GtkWidget *widget, /* I - Command text field */
gpointer data) /* I - Data */
{
strcpy(vars.output_to, gtk_entry_get_text(GTK_ENTRY(widget)));
strcpy(plist[plist_current].command, vars.output_to);
}
/*
* 'output_type_callback()' - Update the current output type...
*/
static void
output_type_callback(GtkWidget *widget, /* I - Output type button */
gint data) /* I - Data */
{
if (GTK_TOGGLE_BUTTON(widget)->active)
{
vars.output_type = data;
plist[plist_current].output_type = data;
};
}
/*
* 'print_callback()' - Start the print...
*/
static void
print_callback(GtkWidget *widget, /* I - OK button widget */
gpointer data) /* I - Dialog window */
{
runme = TRUE;
gtk_widget_destroy(GTK_WIDGET(data));
}
/*
* 'cancel_callback()' - Cancel the print...
*/
static void
cancel_callback(GtkWidget *widget, /* I - Cancel button widget */
gpointer data) /* I - Dialog window */
{
gtk_widget_destroy(GTK_WIDGET(data));
}
/*
* 'close_callback()' - Exit the print dialog application.
*/
static void
close_callback(GtkWidget *widget, /* I - Dialog window */
gpointer data) /* I - Dialog window */
{
gtk_main_quit();
}
static void
preview_update(void)
{
int orient, /* True orientation of page */
tw0, tw1, /* Temporary page_widths */
th0, th1, /* Temporary page_heights */
ta0, ta1; /* Temporary areas */
static GdkGC *gc = NULL;
gdk_window_clear(preview->widget.window);
if (gc == NULL)
gc = gdk_gc_new(preview->widget.window);
page_width = media_width(vars.media_size, 10);
page_height = media_height(vars.media_size, 10);
if (vars.orientation == ORIENT_AUTO)
{
tw0 = page_width * vars.scaling / 100;
th0 = tw0 * image_height / image_width;
if (th0 > page_height)
{
th0 = page_height;
tw0 = th0 * image_width / image_height;
};
ta0 = tw0 * th0;
tw1 = page_height * vars.scaling / 100;
th1 = tw1 * image_height / image_width;
if (th1 > page_width)
{
th1 = page_width;
tw1 = th1 * image_width / image_height;
};
ta1 = tw1 * th1;
if (ta0 >= ta1)
orient = ORIENT_PORTRAIT;
else
orient = ORIENT_LANDSCAPE;
}
else
orient = vars.orientation;
if (orient == ORIENT_LANDSCAPE)
{
page_width = media_height(vars.media_size, 10);
page_height = media_width(vars.media_size, 10);
};
page_left = (PREVIEW_SIZE - page_width) / 2;
page_top = (PREVIEW_SIZE - page_height) / 2;
gdk_draw_rectangle(preview->widget.window, gc, 0,
(PREVIEW_SIZE - page_width - 5) / 2,
(PREVIEW_SIZE - page_height - 10) / 2,
page_width + 5, page_height + 10);
print_width = page_width * vars.scaling / 100;
print_height = print_width * image_height / image_width;
if (print_height > page_height)
{
print_height = page_height;
print_width = print_height * image_width / image_height;
};
if (vars.left < 0 || vars.top < 0)
gdk_draw_rectangle(preview->widget.window, gc, 1,
(PREVIEW_SIZE - print_width) / 2,
(PREVIEW_SIZE - print_height) / 2,
print_width, print_height);
else
{
if (vars.left > (page_width - print_width))
vars.left = page_width - print_width;
if (vars.top > (page_height - print_height))
vars.top = page_height - print_height;
gdk_draw_rectangle(preview->widget.window, gc, 1,
page_left + vars.left,
page_top + vars.top,
print_width, print_height);
};
gdk_flush();
}
static void
preview_button_callback(GtkWidget *w,
GdkEventButton *event)
{
mouse_x = event->x;
mouse_y = event->y;
}
static void
preview_motion_callback(GtkWidget *w,
GdkEventMotion *event)
{
if (vars.left < 0 || vars.top < 0)
{
vars.left = (page_width - print_width) / 2;
vars.top = (page_height - print_height) / 2;
};
vars.left += event->x - mouse_x;
vars.top += event->y - mouse_y;
if (vars.left < 0)
vars.left = 0;
if (vars.top < 0)
vars.top = 0;
preview_update();
mouse_x = event->x;
mouse_y = event->y;
}
/*
* 'printrc_load()' - Load the printer resource configuration file.
*/
static void
printrc_load(void)
{
FILE *fp; /* Printrc file */
char line[1024]; /* Line in printrc file */
plist_t *p, /* Current printer */
key; /* Search key */
/*
* Get the printer list...
*/
get_printers();
/*
* Generate the filename for the current user...
*/
if (getenv("HOME") == NULL)
strcpy(line, "/.gimp/printrc");
else
sprintf(line, "%s/.gimp/printrc", getenv("HOME"));
if ((fp = fopen(line, "r")) != NULL)
{
/*
* File exists - read the contents and update the printer list...
*/
while (fgets(line, sizeof(line), fp) != NULL)
{
if (line[0] == '#')
continue; /* Comment */
if (sscanf(line, "%s%s%d%*[ \t]%[^\n]", key.name, key.driver,
&(key.output_type), key.command) == 4)
{
/*
* Check to see if this is an old printrc file...
*/
if (key.command[0] == '|')
strcpy(key.command, key.command + 1);
if ((p = bsearch(&key, plist + 1, plist_count - 1, sizeof(plist_t),
1997-11-25 06:05:25 +08:00
(int (*)(const void *, const void *))compare_printers)) != NULL)
memcpy(p, &key, sizeof(plist_t));
};
1997-11-25 06:05:25 +08:00
};
fclose(fp);
};
}
/*
* 'printrc_save()' - Save the current printer resource configuration.
*/
static void
printrc_save(void)
{
FILE *fp; /* Printrc file */
char filename[1024]; /* Printrc filename */
int i; /* Looping var */
plist_t *p; /* Current printer */
/*
* Generate the filename for the current user...
*/
if (getenv("HOME") == NULL)
strcpy(filename, "/.gimp/printrc");
else
sprintf(filename, "%s/.gimp/printrc", getenv("HOME"));
if ((fp = fopen(filename, "w")) != NULL)
{
/*
* Write the contents of the printer list...
*/
fputs("#PRINTRC " PLUG_IN_VERSION "\n", fp);
for (i = 1, p = plist + 1; i < plist_count; i ++, p ++)
1997-11-25 06:05:25 +08:00
fprintf(fp, "%s %s %d %s\n", p->name, p->driver, p->output_type, p->command);
fclose(fp);
};
}
/*
* '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_printers()' - Get a complete list of printers from the spooler.
*/
static void
get_printers(void)
{
int i;
FILE *pfile;
char line[129],
name[17],
defname[17];
defname[0] = '\0';
memset(plist, 0, sizeof(plist));
plist_count = 1;
strcpy(plist[0].name, "File");
sprintf(plist[0].command, "file.ps", line);
strcpy(plist[0].driver, "ps2");
plist[0].output_type = OUTPUT_COLOR;
1997-11-25 06:05:25 +08:00
#ifndef sun /* Sun Solaris merges LPR and LP queues */
if ((pfile = popen("lpc status", "r")) != NULL)
1997-11-25 06:05:25 +08:00
{
while (fgets(line, sizeof(line), pfile) != NULL &&
plist_count < MAX_PLIST)
if (strchr(line, ':') != NULL)
{
*strchr(line, ':') = '\0';
strcpy(plist[plist_count].name, line);
sprintf(plist[plist_count].command, "lpr -P%s -l", line);
strcpy(plist[plist_count].driver, "ps2");
1997-11-25 06:05:25 +08:00
plist[plist_count].output_type = OUTPUT_COLOR;
plist_count ++;
};
pclose(pfile);
};
#endif /* !sun */
if ((pfile = popen("lpstat -d -p", "r")) != NULL)
1997-11-25 06:05:25 +08:00
{
while (fgets(line, sizeof(line), pfile) != NULL &&
plist_count < MAX_PLIST)
{
if (sscanf(line, "printer %s", name) == 1)
{
strcpy(plist[plist_count].name, name);
#ifdef __sgi /* SGI still uses the SVR3 spooler */
sprintf(plist[plist_count].command, "lp -s -d%s", name);
1997-11-25 06:05:25 +08:00
#else
sprintf(plist[plist_count].command, "lp -s -d %s", name);
1997-11-25 06:05:25 +08:00
#endif /* __sgi */
strcpy(plist[plist_count].driver, "ps2");
1997-11-25 06:05:25 +08:00
plist[plist_count].output_type = OUTPUT_COLOR;
plist_count ++;
}
else
sscanf(line, "system default destination: %s", defname);
};
pclose(pfile);
};
if (plist_count > 2)
qsort(plist + 1, plist_count - 1, sizeof(plist_t),
1997-11-25 06:05:25 +08:00
(int (*)(const void *, const void *))compare_printers);
if (defname[0] != '\0' && vars.output_to[0] == '\0')
1997-11-25 06:05:25 +08:00
{
for (i = 0; i < plist_count; i ++)
if (strcmp(defname, plist[i].name) == 0)
break;
if (i < plist_count)
plist_current = i;
}
else if (vars.output_to[0] != '\0')
{
for (i = 0; i < plist_count; i ++)
if (strcmp(vars.output_to, plist[i].command) == 0)
break;
1997-11-25 06:05:25 +08:00
if (i < plist_count)
plist_current = i;
};
}
/*
* End of "$Id$".
*/