#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gimp-print/gimp-print-intl-internal.h>
#include <gimp-print/gimp-print.h>
#include <gimp-print-ui/gimp-print-ui.h>
#include "gimp-print-ui-internal.h"
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <locale.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
typedef enum
{
PRINTERS_NONE,
PRINTERS_LPC,
PRINTERS_LPSTAT
} printer_system_t;
static int compare_printers (stpui_plist_t *p1, stpui_plist_t *p2);
int stpui_plist_current = 0,
stpui_plist_count = 0;
stpui_plist_t *stpui_plist;
int stpui_show_all_paper_sizes = 0;
static char *printrc_name = NULL;
static char *image_type;
static gint image_raw_channels = 0;
static gint image_channel_depth = 8;
static stp_string_list_t *default_parameters = NULL;
stp_string_list_t *stpui_system_print_queues;
#define SAFE_FREE(x) \
do \
{ \
if ((x)) \
g_free((char *)(x)); \
((x)) = NULL; \
} while (0)
typedef struct
{
const char *printing_system_name;
const char *printing_system_text;
const char *print_command;
const char *queue_select;
const char *raw_flag;
const char *key_file;
const char *scan_command;
} print_system_t;
static const print_system_t default_printing_system =
{ "SysV", N_("System V lp"), "lp -s", "-d", "-oraw", "/usr/bin/lp",
"/usr/bin/lpstat -v | grep -i '^device for ' | awk '{print $3}' | sed 's/://'" };
static print_system_t known_printing_systems[] =
{
{ "CUPS", N_("CUPS"), "lp -s", "-d", "-oraw", "/usr/sbin/cupsd",
"/usr/bin/lpstat -v | grep -i '^device for ' | awk '{print $3}' | sed 's/://'" },
{ "SysV", N_("System V lp"), "lp -s", "-d", "-oraw", "/usr/bin/lp",
"/usr/bin/lpstat -v | grep -i '^device for ' | awk '{print $3}' | sed 's/://'" },
{ "lpd", N_("Berkeley lpd (/etc/lpc)"), "lpr", "-P", "-l", "/etc/lpc",
"/etc/lpc status | grep '^...*:' | sed 's/:.*//'" },
{ "lpd", N_("Berkeley lpd (/usr/bsd/lpc)"), "lpr", "-P", "-l", "/usr/bsd/lpc",
"/usr/bsd/lpc status | grep '^...*:' | sed 's/:.*//'" },
{ "lpd", N_("Berkeley lpd (/usr/etc/lpc"), "lpr", "-P", "-l", "/usr/etc/lpc",
"/usr/etc/lpc status | grep '^...*:' | sed 's/:.*//'" },
{ "lpd", N_("Berkeley lpd (/usr/libexec/lpc)"), "lpr", "-P", "-l", "/usr/libexec/lpc",
"/usr/libexec/lpc status | grep '^...*:' | sed 's/:.*//'" },
{ "lpd", N_("Berkeley lpd (/usr/sbin/lpc)"), "lpr", "-P", "-l", "/usr/sbin/lpc",
"/usr/sbin/lpc status | grep '^...*:' | sed 's/:.*//'" },
};
static unsigned print_system_count = sizeof(known_printing_systems) / sizeof(print_system_t);
static const print_system_t *global_printing_system = NULL;
static void
initialize_default_parameters(void)
{
default_parameters = stp_string_list_create();
stp_string_list_add_string(default_parameters, "PrintingSystem", "Autodetect");
stp_string_list_add_string(default_parameters, "PrintCommand", "");
stp_string_list_add_string(default_parameters, "QueueSelect", "");
stp_string_list_add_string(default_parameters, "RawOutputFlag", "");
stp_string_list_add_string(default_parameters, "ScanOnStartup", "False");
stp_string_list_add_string(default_parameters, "ScanPrintersCommand", "");
}
void
stpui_set_global_parameter(const char *param, const char *value)
{
stp_string_list_remove_string(default_parameters, param);
stp_string_list_add_string(default_parameters, param, value);
}
const char *
stpui_get_global_parameter(const char *param)
{
stp_param_string_t *ps = stp_string_list_find(default_parameters, param);
if (ps)
return ps->text;
else
return NULL;
}
static const print_system_t *
identify_print_system(void)
{
int i;
if (!global_printing_system)
{
for (i = 0; i < print_system_count; i++)
{
if (!access(known_printing_systems[i].key_file, R_OK))
{
global_printing_system = &(known_printing_systems[i]);
break;
}
}
if (!global_printing_system)
global_printing_system = &default_printing_system;
}
return global_printing_system;
}
char *
stpui_build_standard_print_command(const stpui_plist_t *plist,
const stp_printer_t *printer)
{
const char *queue_name = stpui_plist_get_queue_name(plist);
const char *extra_options = stpui_plist_get_extra_printer_options(plist);
const char *family = stp_printer_get_family(printer);
int raw = 0;
char *print_cmd;
if (!queue_name)
queue_name = "";
identify_print_system();
if (strcmp(family, "ps") == 0)
raw = 0;
else
raw = 1;
stp_asprintf(&print_cmd, "%s %s %s %s%s%s",
global_printing_system->print_command,
queue_name[0] ? global_printing_system->queue_select : "",
queue_name[0] ? queue_name : "",
raw ? global_printing_system->raw_flag : "",
extra_options ? " " : "",
extra_options ? extra_options : "");
return print_cmd;
}
void
stpui_set_printrc_file(const char *name)
{
if (name && name == printrc_name)
return;
SAFE_FREE(printrc_name);
if (name)
printrc_name = g_strdup(name);
else
{
const char *where = getenv("HOME");
if (where)
printrc_name = g_strconcat(where, "/.gimpprintrc");
}
}
const char *
stpui_get_printrc_file(void)
{
if (!printrc_name)
stpui_set_printrc_file(NULL);
return printrc_name;
}
#define PLIST_ACCESSORS(name) \
void \
stpui_plist_set_##name(stpui_plist_t *p, const char *val) \
{ \
if (p->name == val) \
return; \
SAFE_FREE(p->name); \
p->name = g_strdup(val); \
} \
\
void \
stpui_plist_set_##name##_n(stpui_plist_t *p, const char *val, int n) \
{ \
if (p->name == val) \
return; \
SAFE_FREE(p->name); \
p->name = g_strndup(val, n); \
} \
\
const char * \
stpui_plist_get_##name(const stpui_plist_t *p) \
{ \
return p->name; \
}
PLIST_ACCESSORS(output_filename)
PLIST_ACCESSORS(name)
PLIST_ACCESSORS(queue_name)
PLIST_ACCESSORS(extra_printer_options)
PLIST_ACCESSORS(custom_command)
PLIST_ACCESSORS(current_standard_command)
void
stpui_plist_set_command_type(stpui_plist_t *p, command_t val)
{
switch (val)
{
case COMMAND_TYPE_DEFAULT:
case COMMAND_TYPE_CUSTOM:
case COMMAND_TYPE_FILE:
p->command_type = val;
break;
default:
p->command_type = COMMAND_TYPE_DEFAULT;
}
}
command_t
stpui_plist_get_command_type(const stpui_plist_t *p)
{
return p->command_type;
}
void
stpui_set_image_type(const char *itype)
{
image_type = g_strdup(itype);
}
void
stpui_set_image_raw_channels(gint channels)
{
image_raw_channels = channels;
}
void
stpui_set_image_channel_depth(gint depth)
{
image_channel_depth = depth;
}
void
stpui_printer_initialize(stpui_plist_t *printer)
{
char tmp[32];
stpui_plist_set_name(printer, "");
stpui_plist_set_output_filename(printer, "");
stpui_plist_set_queue_name(printer, "");
stpui_plist_set_extra_printer_options(printer, "");
stpui_plist_set_custom_command(printer, "");
stpui_plist_set_current_standard_command(printer, "");
printer->command_type = COMMAND_TYPE_DEFAULT;
printer->scaling = 100.0;
printer->orientation = ORIENT_AUTO;
printer->auto_size_roll_feed_paper = 0;
printer->unit = 0;
printer->v = stp_vars_create();
stp_set_string_parameter(printer->v, "InputImageType", image_type);
if (image_raw_channels)
{
(void) sprintf(tmp, "%d", image_raw_channels);
stp_set_string_parameter(printer->v, "RawChannels", tmp);
}
if (image_channel_depth)
{
(void) sprintf(tmp, "%d", image_channel_depth);
stp_set_string_parameter(printer->v, "ChannelBitDepth", tmp);
}
printer->invalid_mask = INVALID_TOP | INVALID_LEFT;
}
static void
stpui_plist_destroy(stpui_plist_t *printer)
{
SAFE_FREE(printer->name);
SAFE_FREE(printer->queue_name);
SAFE_FREE(printer->extra_printer_options);
SAFE_FREE(printer->custom_command);
SAFE_FREE(printer->current_standard_command);
SAFE_FREE(printer->output_filename);
stp_vars_destroy(printer->v);
}
void
stpui_plist_copy(stpui_plist_t *vd, const stpui_plist_t *vs)
{
if (vs == vd)
return;
stp_vars_copy(vd->v, vs->v);
vd->scaling = vs->scaling;
vd->orientation = vs->orientation;
vd->auto_size_roll_feed_paper = vs->auto_size_roll_feed_paper;
vd->unit = vs->unit;
vd->invalid_mask = vs->invalid_mask;
vd->command_type = vs->command_type;
stpui_plist_set_name(vd, stpui_plist_get_name(vs));
stpui_plist_set_queue_name(vd, stpui_plist_get_queue_name(vs));
stpui_plist_set_extra_printer_options(vd, stpui_plist_get_extra_printer_options(vs));
stpui_plist_set_custom_command(vd, stpui_plist_get_custom_command(vs));
stpui_plist_set_current_standard_command(vd, stpui_plist_get_current_standard_command(vs));
stpui_plist_set_output_filename(vd, stpui_plist_get_output_filename(vs));
}
static stpui_plist_t *
allocate_stpui_plist_copy(const stpui_plist_t *vs)
{
stpui_plist_t *rep = g_malloc(sizeof(stpui_plist_t));
memset(rep, 0, sizeof(stpui_plist_t));
rep->v = stp_vars_create();
stpui_plist_copy(rep, vs);
return rep;
}
static void
check_plist(int count)
{
static int current_plist_size = 0;
int i;
if (count <= current_plist_size)
return;
else if (current_plist_size == 0)
{
current_plist_size = count;
stpui_plist = g_malloc(current_plist_size * sizeof(stpui_plist_t));
for (i = 0; i < current_plist_size; i++)
{
memset(&(stpui_plist[i]), 0, sizeof(stpui_plist_t));
stpui_printer_initialize(&(stpui_plist[i]));
}
}
else
{
int old_plist_size = current_plist_size;
current_plist_size *= 2;
if (current_plist_size < count)
current_plist_size = count;
stpui_plist = g_realloc(stpui_plist, current_plist_size * sizeof(stpui_plist_t));
for (i = old_plist_size; i < current_plist_size; i++)
{
memset(&(stpui_plist[i]), 0, sizeof(stpui_plist_t));
stpui_printer_initialize(&(stpui_plist[i]));
}
}
}
#define GET_MANDATORY_INTERNAL_STRING_PARAM(param) \
do { \
if ((commaptr = strchr(lineptr, ',')) == NULL) \
continue; \
stpui_plist_set_##param##_n(&key, lineptr, commaptr - line); \
lineptr = commaptr + 1; \
} while (0)
#define GET_MANDATORY_STRING_PARAM(param) \
do { \
if ((commaptr = strchr(lineptr, ',')) == NULL) \
continue; \
stp_set_##param##_n(key.v, lineptr, commaptr - line); \
lineptr = commaptr + 1; \
} while (0)
static int
get_mandatory_string_param(stp_vars_t *v, const char *param, char **lineptr)
{
char *commaptr = strchr(*lineptr, ',');
if (commaptr == NULL)
return 0;
stp_set_string_parameter_n(v, param, *lineptr, commaptr - *lineptr);
*lineptr = commaptr + 1;
return 1;
}
static int
get_mandatory_file_param(stp_vars_t *v, const char *param, char **lineptr)
{
char *commaptr = strchr(*lineptr, ',');
if (commaptr == NULL)
return 0;
stp_set_file_parameter_n(v, param, *lineptr, commaptr - *lineptr);
*lineptr = commaptr + 1;
return 1;
}
#define GET_MANDATORY_INT_PARAM(param) \
do { \
if ((commaptr = strchr(lineptr, ',')) == NULL) \
continue; \
stp_set_##param(key.v, atoi(lineptr)); \
lineptr = commaptr + 1; \
} while (0)
#define GET_MANDATORY_INTERNAL_INT_PARAM(param) \
do { \
if ((commaptr = strchr(lineptr, ',')) == NULL) \
continue; \
key.param = atoi(lineptr); \
lineptr = commaptr + 1; \
} while (0)
static void
get_optional_string_param(stp_vars_t *v, const char *param,
char **lineptr, int *keepgoing)
{
if (*keepgoing)
{
char *commaptr = strchr(*lineptr, ',');
if (commaptr == NULL)
{
stp_set_string_parameter(v, param, *lineptr);
*keepgoing = 0;
}
else
{
stp_set_string_parameter_n(v, param, *lineptr, commaptr - *lineptr);
*lineptr = commaptr + 1;
}
}
}
#define GET_OPTIONAL_INT_PARAM(param) \
do { \
if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL)) \
{ \
keepgoing = 0; \
} \
else \
{ \
stp_set_##param(key.v, atoi(lineptr)); \
lineptr = commaptr + 1; \
} \
} while (0)
#define GET_OPTIONAL_INTERNAL_INT_PARAM(param) \
do { \
if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL)) \
{ \
keepgoing = 0; \
} \
else \
{ \
key.param = atoi(lineptr); \
lineptr = commaptr + 1; \
} \
} while (0)
#define IGNORE_OPTIONAL_PARAM(param) \
do { \
if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL)) \
{ \
keepgoing = 0; \
} \
else \
{ \
lineptr = commaptr + 1; \
} \
} while (0)
static void
get_optional_float_param(stp_vars_t *v, const char *param,
char **lineptr, int *keepgoing)
{
if (*keepgoing)
{
char *commaptr = strchr(*lineptr, ',');
if (commaptr == NULL)
{
stp_set_float_parameter(v, param, atof(*lineptr));
*keepgoing = 0;
}
else
{
stp_set_float_parameter(v, param, atof(*lineptr));
*lineptr = commaptr + 1;
}
}
}
#define GET_OPTIONAL_INTERNAL_FLOAT_PARAM(param) \
do { \
if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL)) \
{ \
keepgoing = 0; \
} \
else \
{ \
key.param = atof(lineptr); \
} \
} 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;
}
stpui_plist_t *
stpui_plist_create(const char *name, const char *driver)
{
stpui_plist_t key;
stpui_plist_t *answer = NULL;
memset(&key, 0, sizeof(key));
stpui_printer_initialize(&key);
key.invalid_mask = 0;
stpui_plist_set_name(&key, name);
stp_set_driver(key.v, driver);
if (stpui_plist_add(&key, 0))
answer = psearch(&key, stpui_plist, stpui_plist_count,
sizeof(stpui_plist_t),
(int (*)(const void *, const void *)) compare_printers);
SAFE_FREE(key.name);
SAFE_FREE(key.queue_name);
SAFE_FREE(key.extra_printer_options);
SAFE_FREE(key.custom_command);
SAFE_FREE(key.current_standard_command);
SAFE_FREE(key.output_filename);
stp_vars_destroy(key.v);
return answer;
}
int
stpui_plist_add(const stpui_plist_t *key, int add_only)
{
stpui_plist_t *p;
if (stp_get_printer(key->v))
{
p = psearch(key, stpui_plist, stpui_plist_count,
sizeof(stpui_plist_t),
(int (*)(const void *, const void *)) compare_printers);
if (p == NULL)
{
#ifdef DEBUG
fprintf(stderr, "Adding new printer from printrc file: %s\n",
key->name);
#endif
check_plist(stpui_plist_count + 1);
p = stpui_plist + stpui_plist_count;
stpui_plist_count++;
stpui_plist_copy(p, key);
if (strlen(stpui_plist_get_queue_name(p)) == 0 &&
stp_string_list_is_present(stpui_system_print_queues,
stpui_plist_get_name(p)))
stpui_plist_set_queue_name(p, stpui_plist_get_name(p));
}
else
{
if (add_only)
return 0;
#ifdef DEBUG
fprintf(stderr, "Updating printer %s.\n", key->name);
#endif
stpui_plist_copy(p, key);
}
}
return 1;
}
static void
stpui_printrc_load_v0(FILE *fp)
{
char line[1024];
char *lineptr;
char *commaptr;
stpui_plist_t key;
int keepgoing = 1;
(void) memset(line, 0, 1024);
(void) memset(&key, 0, sizeof(stpui_plist_t));
stpui_printer_initialize(&key);
key.name = g_strdup(_("File"));
while (fgets(line, sizeof(line), fp) != NULL)
{
stpui_printer_initialize(&key);
key.invalid_mask = 0;
lineptr = line;
GET_MANDATORY_INTERNAL_STRING_PARAM(name);
GET_MANDATORY_INTERNAL_STRING_PARAM(custom_command);
GET_MANDATORY_STRING_PARAM(driver);
if (! stp_get_printer(key.v))
continue;
if (!get_mandatory_file_param(key.v, "PPDFile", &lineptr))
continue;
if ((commaptr = strchr(lineptr, ',')) != NULL)
{
switch (atoi(lineptr))
{
case 1:
stp_set_string_parameter(key.v, "PrintingMode", "Color");
break;
case 0:
default:
stp_set_string_parameter(key.v, "PrintingMode", "BW");
break;
}
}
else
continue;
if (!get_mandatory_string_param(key.v, "Resolution", &lineptr))
continue;
if (!get_mandatory_string_param(key.v, "PageSize", &lineptr))
continue;
if (!get_mandatory_string_param(key.v, "MediaType", &lineptr))
continue;
get_optional_string_param(key.v, "InputSlot", &lineptr, &keepgoing);
get_optional_float_param(key.v, "Brightness", &lineptr, &keepgoing);
GET_OPTIONAL_INTERNAL_FLOAT_PARAM(scaling);
GET_OPTIONAL_INTERNAL_INT_PARAM(orientation);
GET_OPTIONAL_INT_PARAM(left);
GET_OPTIONAL_INT_PARAM(top);
get_optional_float_param(key.v, "Gamma", &lineptr, &keepgoing);
get_optional_float_param(key.v, "Contrast", &lineptr, &keepgoing);
get_optional_float_param(key.v, "Cyan", &lineptr, &keepgoing);
get_optional_float_param(key.v, "Magenta", &lineptr, &keepgoing);
get_optional_float_param(key.v, "Yellow", &lineptr, &keepgoing);
IGNORE_OPTIONAL_PARAM(linear);
IGNORE_OPTIONAL_PARAM(image_type);
get_optional_float_param(key.v, "Saturation", &lineptr, &keepgoing);
get_optional_float_param(key.v, "Density", &lineptr, &keepgoing);
get_optional_string_param(key.v, "InkType", &lineptr, &keepgoing);
get_optional_string_param(key.v,"DitherAlgorithm",&lineptr,&keepgoing);
GET_OPTIONAL_INTERNAL_INT_PARAM(unit);
stpui_plist_add(&key, 0);
g_free(key.name);
stp_vars_destroy(key.v);
}
stpui_plist_current = 0;
}
static void
stpui_printrc_load_v1(FILE *fp)
{
char line[1024];
stpui_plist_t key;
char * current_printer = 0;
(void) memset(line, 0, 1024);
(void) memset(&key, 0, sizeof(stpui_plist_t));
stpui_printer_initialize(&key);
key.name = g_strdup(_("File"));
while (fgets(line, sizeof(line), fp) != NULL)
{
char *keyword, *end, *value;
keyword = line;
for (keyword = line; isspace(*keyword); keyword++)
{
}
if (!isalpha(*keyword))
continue;
for (end = keyword; isalnum(*end) || *end == '-'; end++)
{
}
value = end;
while (isspace(*value))
{
value++;
}
if (*value != ':')
continue;
value++;
*end = '\0';
while (isspace(*value))
{
value++;
}
for (end = value; *end && *end != '\n'; end++)
{
}
*end = '\0';
#ifdef DEBUG
fprintf(stderr, "Keyword = `%s', value = `%s'\n", keyword, value);
#endif
if (strcasecmp("current-printer", keyword) == 0)
{
if (current_printer)
g_free (current_printer);
current_printer = g_strdup(value);
}
else if (strcasecmp("printer", keyword) == 0)
{
stpui_plist_add(&key, 0);
#ifdef DEBUG
fprintf(stderr,
"output_to is now %s\n", stpui_plist_get_output_to(&key));
#endif
stp_vars_destroy(key.v);
stpui_printer_initialize(&key);
key.invalid_mask = 0;
stpui_plist_set_name(&key, value);
}
else if (strcasecmp("destination", keyword) == 0)
stpui_plist_set_custom_command(&key, value);
else if (strcasecmp("driver", keyword) == 0)
stp_set_driver(key.v, value);
else if (strcasecmp("ppd-file", keyword) == 0)
stp_set_file_parameter(key.v, "PPDFile", value);
else if (strcasecmp("output-type", keyword) == 0)
{
switch (atoi(value))
{
case 1:
stp_set_string_parameter(key.v, "PrintingMode", "Color");
break;
case 0:
default:
stp_set_string_parameter(key.v, "PrintingMode", "BW");
break;
}
}
else if (strcasecmp("media-size", keyword) == 0)
stp_set_string_parameter(key.v, "PageSize", value);
else if (strcasecmp("media-type", keyword) == 0)
stp_set_string_parameter(key.v, "MediaType", value);
else if (strcasecmp("media-source", keyword) == 0)
stp_set_float_parameter(key.v, "Brightness", atof(value));
else if (strcasecmp("scaling", keyword) == 0)
key.scaling = atof(value);
else if (strcasecmp("orientation", keyword) == 0)
key.orientation = atoi(value);
else if (strcasecmp("left", keyword) == 0)
stp_set_left(key.v, atoi(value));
else if (strcasecmp("top", keyword) == 0)
stp_set_top(key.v, atoi(value));
else if (strcasecmp("linear", keyword) == 0)
;
else if (strcasecmp("image-type", keyword) == 0)
;
else if (strcasecmp("unit", keyword) == 0)
key.unit = atoi(value);
else if (strcasecmp("custom-page-width", keyword) == 0)
stp_set_page_width(key.v, atoi(value));
else if (strcasecmp("custom-page-height", keyword) == 0)
stp_set_page_height(key.v, atoi(value));
else if (strcasecmp("ink-type", keyword) == 0)
stp_set_string_parameter(key.v, "InkType", value);
else if (strcasecmp("dither-algorithm", keyword) == 0)
stp_set_string_parameter(key.v, "DitherAlgorithm", value);
else
{
stp_parameter_t desc;
stp_curve_t *curve;
stp_describe_parameter(key.v, keyword, &desc);
switch (desc.p_type)
{
case STP_PARAMETER_TYPE_STRING_LIST:
stp_set_string_parameter(key.v, keyword, value);
break;
case STP_PARAMETER_TYPE_FILE:
stp_set_file_parameter(key.v, keyword, value);
break;
case STP_PARAMETER_TYPE_DOUBLE:
stp_set_float_parameter(key.v, keyword, atof(value));
break;
case STP_PARAMETER_TYPE_INT:
stp_set_int_parameter(key.v, keyword, atoi(value));
break;
case STP_PARAMETER_TYPE_BOOLEAN:
stp_set_boolean_parameter(key.v, keyword, atoi(value));
break;
case STP_PARAMETER_TYPE_CURVE:
curve = stp_curve_create_from_string(value);
if (curve)
{
stp_set_curve_parameter(key.v, keyword, curve);
stp_curve_destroy(curve);
}
break;
default:
if (strlen(value))
{
char buf[1024];
snprintf(buf, sizeof(buf),
"Unrecognized keyword `%s' in printrc; value `%s' (%d)\n",
keyword, value, desc.p_type);
}
}
stp_parameter_description_destroy(&desc);
}
}
if (strlen(key.name) > 0)
{
stpui_plist_add(&key, 0);
stp_vars_destroy(key.v);
g_free(key.name);
}
if (current_printer)
{
int i;
for (i = 0; i < stpui_plist_count; i ++)
if (strcmp(current_printer, stpui_plist[i].name) == 0)
stpui_plist_current = i;
}
}
const char *stpui_printrc_current_printer = NULL;
extern FILE *yyin;
extern int yyparse(void);
static void
stpui_printrc_load_v2(FILE *fp)
{
int retval;
yyin = fp;
stpui_printrc_current_printer = NULL;
retval = yyparse();
if (stpui_printrc_current_printer)
{
int i;
for (i = 0; i < stpui_plist_count; i ++)
{
if (strcmp(stpui_printrc_current_printer, stpui_plist[i].name) == 0)
stpui_plist_current = i;
if (!stp_check_boolean_parameter(stpui_plist[i].v,
"PageSizeExtended",
STP_PARAMETER_ACTIVE))
stp_set_boolean_parameter(stpui_plist[i].v, "PageSizeExtended", 0);
}
SAFE_FREE(stpui_printrc_current_printer);
}
}
void
stpui_printrc_load(void)
{
FILE *fp;
char line[1024];
int format = 0;
const char *filename = stpui_get_printrc_file();
initialize_default_parameters();
check_plist(1);
stpui_get_system_printers();
if ((fp = fopen(filename, "r")) != NULL)
{
(void) memset(line, 0, 1024);
if (fgets(line, sizeof(line), fp) != NULL)
{
setlocale(LC_ALL, "C");
if (strncmp("#PRINTRCv", line, 9) == 0)
{
#ifdef DEBUG
fprintf(stderr, "Found printrc version tag: `%s'\n", line);
fprintf(stderr, "Version number: `%s'\n", &(line[9]));
#endif
(void) sscanf(&(line[9]), "%d", &format);
}
setlocale(LC_ALL, "");
}
rewind(fp);
switch (format)
{
case 0:
stpui_printrc_load_v0(fp);
break;
case 1:
stpui_printrc_load_v1(fp);
break;
case 2:
case 3:
case 4:
stpui_printrc_load_v2(fp);
break;
}
(void) fclose(fp);
}
if (stpui_plist_count == 0)
stpui_plist_create(_("Printer"), "ps2");
}
void
stpui_printrc_save(void)
{
FILE *fp;
int i;
size_t global_settings_count = stp_string_list_count(default_parameters);
stpui_plist_t *p;
const char *filename = stpui_get_printrc_file();
if ((fp = fopen(filename, "w")) != NULL)
{
setlocale(LC_ALL, "C");
#ifdef DEBUG
fprintf(stderr, "Number of printers: %d\n", stpui_plist_count);
#endif
fputs("#PRINTRCv4 written by Gimp-Print " PLUG_IN_VERSION "\n\n", fp);
fprintf(fp, "Global-Settings:\n");
fprintf(fp, " Current-Printer: \"%s\"\n",
stpui_plist[stpui_plist_current].name);
fprintf(fp, " Show-All-Paper-Sizes: %s\n",
stpui_show_all_paper_sizes ? "True" : "False");
for (i = 0; i < global_settings_count; i++)
{
stp_param_string_t *ps = stp_string_list_param(default_parameters, i);
fprintf(fp, " %s \"%s\"\n", ps->name, ps->text);
}
fprintf(fp, "End-Global-Settings:\n");
for (i = 0, p = stpui_plist; i < stpui_plist_count; i ++, p ++)
{
int count;
int j;
stp_parameter_list_t *params = stp_get_parameter_list(p->v);
count = stp_parameter_list_count(params);
fprintf(fp, "\nPrinter: \"%s\" \"%s\"\n",
p->name, stp_get_driver(p->v));
fprintf(fp, " Command-Type: %d\n", p->command_type);
fprintf(fp, " Queue-Name: \"%s\"\n", p->queue_name);
fprintf(fp, " Output-Filename: \"%s\"\n", p->output_filename);
fprintf(fp, " Extra-Printer-Options: \"%s\"\n", p->extra_printer_options);
fprintf(fp, " Custom-Command: \"%s\"\n", p->custom_command);
fprintf(fp, " Scaling: %.3f\n", p->scaling);
fprintf(fp, " Orientation: %d\n", p->orientation);
fprintf(fp, " Autosize-Roll-Paper: %d\n", p->auto_size_roll_feed_paper);
fprintf(fp, " Unit: %d\n", p->unit);
fprintf(fp, " Left: %d\n", stp_get_left(p->v));
fprintf(fp, " Top: %d\n", stp_get_top(p->v));
fprintf(fp, " Custom_Page_Width: %d\n", stp_get_page_width(p->v));
fprintf(fp, " Custom_Page_Height: %d\n", stp_get_page_height(p->v));
for (j = 0; j < count; j++)
{
const stp_parameter_t *param = stp_parameter_list_param(params, j);
if (strcmp(param->name, "AppGamma") == 0)
continue;
switch (param->p_type)
{
case STP_PARAMETER_TYPE_STRING_LIST:
if (stp_check_string_parameter(p->v, param->name,
STP_PARAMETER_INACTIVE))
fprintf(fp, " Parameter %s String %s \"%s\"\n",
param->name,
((stp_get_string_parameter_active
(p->v, param->name) == STP_PARAMETER_ACTIVE) ?
"True" : "False"),
stp_get_string_parameter(p->v, param->name));
break;
case STP_PARAMETER_TYPE_FILE:
if (stp_check_file_parameter(p->v, param->name,
STP_PARAMETER_INACTIVE))
fprintf(fp, " Parameter %s File %s \"%s\"\n", param->name,
((stp_get_file_parameter_active
(p->v, param->name) == STP_PARAMETER_ACTIVE) ?
"True" : "False"),
stp_get_file_parameter(p->v, param->name));
break;
case STP_PARAMETER_TYPE_DOUBLE:
if (stp_check_float_parameter(p->v, param->name,
STP_PARAMETER_INACTIVE))
fprintf(fp, " Parameter %s Double %s %f\n", param->name,
((stp_get_float_parameter_active
(p->v, param->name) == STP_PARAMETER_ACTIVE) ?
"True" : "False"),
stp_get_float_parameter(p->v, param->name));
break;
case STP_PARAMETER_TYPE_DIMENSION:
if (stp_check_dimension_parameter(p->v, param->name,
STP_PARAMETER_INACTIVE))
fprintf(fp, " Parameter %s Dimension %s %d\n", param->name,
((stp_get_dimension_parameter_active
(p->v, param->name) == STP_PARAMETER_ACTIVE) ?
"True" : "False"),
stp_get_dimension_parameter(p->v, param->name));
break;
case STP_PARAMETER_TYPE_INT:
if (stp_check_int_parameter(p->v, param->name,
STP_PARAMETER_INACTIVE))
fprintf(fp, " Parameter %s Int %s %d\n", param->name,
((stp_get_int_parameter_active
(p->v, param->name) == STP_PARAMETER_ACTIVE) ?
"True" : "False"),
stp_get_int_parameter(p->v, param->name));
break;
case STP_PARAMETER_TYPE_BOOLEAN:
if (stp_check_boolean_parameter(p->v, param->name,
STP_PARAMETER_INACTIVE))
fprintf(fp, " Parameter %s Boolean %s %s\n", param->name,
((stp_get_boolean_parameter_active
(p->v, param->name) == STP_PARAMETER_ACTIVE) ?
"True" : "False"),
(stp_get_boolean_parameter(p->v, param->name) ?
"True" : "False"));
break;
case STP_PARAMETER_TYPE_CURVE:
if (stp_check_curve_parameter(p->v, param->name,
STP_PARAMETER_INACTIVE))
{
const stp_curve_t *curve =
stp_get_curve_parameter(p->v, param->name);
if (curve)
{
fprintf(fp, " Parameter %s Curve %s '",
param->name,
((stp_get_curve_parameter_active
(p->v, param->name) ==
STP_PARAMETER_ACTIVE) ?
"True" : "False"));
stp_curve_write(fp, curve);
fprintf(fp, "'\n");
}
}
break;
default:
break;
}
}
stp_parameter_list_destroy(params);
#ifdef DEBUG
fprintf(stderr, "Wrote printer %d: %s\n", i, p->name);
#endif
}
setlocale(LC_ALL, "");
fclose(fp);
}
else
fprintf(stderr, "could not open printrc file \"%s\"\n",filename);
}
static int
compare_printers(stpui_plist_t *p1, stpui_plist_t *p2)
{
return (strcmp(p1->name, p2->name));
}
void
stpui_get_system_printers(void)
{
FILE *pfile;
char line[1025];
stpui_system_print_queues = stp_string_list_create();
stp_string_list_add_string(stpui_system_print_queues, "",
_("(Default Printer)"));
identify_print_system();
if (global_printing_system)
{
if ((pfile = popen(global_printing_system->scan_command, "r")) != NULL)
{
while (fgets(line, sizeof(line), pfile) != NULL)
{
char *tmp_ptr;
if ((tmp_ptr = strchr(line, '\n')))
tmp_ptr[0] = '\0';
if ((tmp_ptr = strchr(line, '\r')))
tmp_ptr[0] = '\0';
if (strlen(line) > 0)
{
if (!stp_string_list_is_present(stpui_system_print_queues, line))
stp_string_list_add_string(stpui_system_print_queues,
line, line);
}
}
pclose(pfile);
}
}
}
const stpui_plist_t *
stpui_get_current_printer(void)
{
return &(stpui_plist[stpui_plist_current]);
}
static volatile int usr1_interrupt;
static void
usr1_handler (int sig)
{
usr1_interrupt = 1;
}
static void
writefunc(void *file, const char *buf, size_t bytes)
{
FILE *prn = (FILE *)file;
fwrite(buf, 1, bytes, prn);
}
static void
stpui_errfunc(void *file, const char *buf, size_t bytes)
{
g_message(buf);
}
int
stpui_print(const stpui_plist_t *printer, stpui_image_t *image)
{
int ppid = getpid (),
opid,
cpid = 0,
pipefd[2],
errfd[2],
syncfd[2];
FILE *prn = NULL;
int do_sync = 0;
int print_status = 0;
int dummy;
if (stpui_plist_get_command_type(printer) == COMMAND_TYPE_DEFAULT ||
stpui_plist_get_command_type(printer) == COMMAND_TYPE_CUSTOM)
{
do_sync = 1;
usr1_interrupt = 0;
signal (SIGUSR1, usr1_handler);
if (pipe (syncfd) != 0)
{
do_sync = 0;
}
if (pipe (pipefd) != 0)
{
prn = NULL;
}
else
{
cpid = fork ();
if (cpid < 0)
{
do_sync = 0;
prn = NULL;
}
else if (cpid == 0)
{
close(syncfd[0]);
opid = fork ();
if (opid < 0)
{
exit (1);
}
else if (opid == 0)
{
dup2 (pipefd[0], 0);
close (pipefd[0]);
close (pipefd[1]);
if (pipe(errfd) == 0)
{
opid = fork();
if (opid < 0)
_exit(1);
else if (opid == 0)
{
stp_outfunc_t errfunc = stpui_get_errfunc();
void *errdata = stpui_get_errdata();
char buf[4096];
close (pipefd[0]);
close (pipefd[1]);
close (0);
close (1);
close (2);
close (errfd[1]);
while (1)
{
ssize_t bytes = read(errfd[0], buf, 4095);
if (bytes > 0)
{
buf[bytes] = '\0';
(*errfunc)(errdata, buf, bytes);
}
else
{
if (bytes < 0)
{
snprintf(buf, 4095,
"Read messages failed: %s\n",
strerror(errno));
(*errfunc)(errdata, buf, strlen(buf));
}
write(syncfd[1], "Done", 5);
_exit(0);
}
}
write(syncfd[1], "Done", 5);
_exit(0);
}
else
{
const char *command;
if (stpui_plist_get_command_type(printer) ==
COMMAND_TYPE_DEFAULT)
command =
stpui_build_standard_print_command
(printer, stp_get_printer(printer->v));
else
command = stpui_plist_get_custom_command(printer);
(void) close(2);
(void) close(1);
dup2 (errfd[1], 2);
dup2 (errfd[1], 1);
close(errfd[1]);
close (pipefd[0]);
close (pipefd[1]);
close(syncfd[1]);
execl("/bin/sh", "/bin/sh", "-c", command, NULL);
_exit (1);
}
_exit(1);
}
else
{
_exit(1);
}
}
else
{
close (0);
close (1);
close (2);
close (syncfd[1]);
close (pipefd[0]);
while (usr1_interrupt == 0)
{
if (kill (ppid, 0) < 0)
{
kill (opid, SIGTERM);
waitpid (opid, &dummy, 0);
close (pipefd[1]);
_exit (0);
}
sleep (5);
}
close (pipefd[1]);
_exit (0);
}
}
else
{
close (syncfd[1]);
close (pipefd[0]);
prn = fdopen (pipefd[1], "w");
}
}
}
else
prn = fopen (stpui_plist_get_output_filename(printer), "wb");
if (prn != NULL)
{
char tmp[32];
stpui_plist_t *np = allocate_stpui_plist_copy(printer);
const stp_vars_t *current_vars =
stp_printer_get_defaults(stp_get_printer(np->v));
int orientation;
stp_merge_printvars(np->v, current_vars);
stp_set_string_parameter(np->v, "InputImageType", image_type);
if (image_raw_channels)
{
sprintf(tmp, "%d", image_raw_channels);
stp_set_string_parameter(np->v, "RawChannels", tmp);
}
sprintf(tmp, "%d", image_channel_depth);
stp_set_string_parameter(np->v, "ChannelBitDepth", tmp);
orientation = np->orientation;
if (orientation == ORIENT_AUTO)
orientation = stpui_compute_orientation();
switch (orientation)
{
case ORIENT_PORTRAIT:
break;
case ORIENT_LANDSCAPE:
if (image->rotate_cw)
(image->rotate_cw)(image);
break;
case ORIENT_UPSIDEDOWN:
if (image->rotate_180)
(image->rotate_180)(image);
break;
case ORIENT_SEASCAPE:
if (image->rotate_ccw)
(image->rotate_ccw)(image);
break;
}
stp_set_outfunc(np->v, writefunc);
stp_set_errfunc(np->v, stpui_get_errfunc());
stp_set_outdata(np->v, prn);
stp_set_errdata(np->v, stpui_get_errdata());
print_status = stp_print(np->v, &(image->im));
(void) fclose(prn);
if (stpui_plist_get_command_type(printer) == COMMAND_TYPE_DEFAULT ||
stpui_plist_get_command_type(printer) == COMMAND_TYPE_CUSTOM)
{
kill (cpid, SIGUSR1);
waitpid (cpid, &dummy, 0);
}
if (do_sync)
{
char buf[8];
(void) read(syncfd[0], buf, 8);
(void) close(syncfd[0]);
}
stpui_plist_destroy(np);
g_free(np);
return 1;
}
return 0;
}