X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=modules%2Fprintbackends%2Fcups%2Fgtkprintbackendcups.c;h=f26214af6a17c5cc6abf5dc2cbf62140e47b85fc;hb=60969ff9515d516ada21467bffa7149401526392;hp=5bb14eb9f4116f17b42bc59c2ddc4ca436eed799;hpb=920e8b434367f9aa8aab306721cc024e66892e2e;p=~andy%2Fgtk diff --git a/modules/printbackends/cups/gtkprintbackendcups.c b/modules/printbackends/cups/gtkprintbackendcups.c index 5bb14eb9f..f26214af6 100644 --- a/modules/printbackends/cups/gtkprintbackendcups.c +++ b/modules/printbackends/cups/gtkprintbackendcups.c @@ -14,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #ifdef __linux__ @@ -30,6 +28,13 @@ #include #include #include +/* Cups 1.6 deprecates ppdFindAttr(), ppdFindCustomOption(), + * ppdFirstCustomParam(), and ppdNextCustomParam() among others. This + * turns off the warning so that it will compile. + */ +#ifdef HAVE_CUPS_API_1_6 +# define _PPD_DEPRECATED +#endif #include #include @@ -54,6 +59,9 @@ #include "gtkcupsutils.h" +#ifdef HAVE_COLORD +#include +#endif typedef struct _GtkPrintBackendCupsClass GtkPrintBackendCupsClass; @@ -92,6 +100,7 @@ typedef struct http_t *http; GtkCupsRequest *request; + GtkCupsPollState poll_state; GPollFD *data_poll; GtkPrintBackendCups *backend; GtkPrintCupsResponseCallbackFunc callback; @@ -125,6 +134,9 @@ struct _GtkPrintBackendCups GHashTable *auth; gchar *username; gboolean authentication_lock; +#ifdef HAVE_COLORD + CdClient *colord_client; +#endif }; static GObjectClass *backend_parent_class; @@ -234,7 +246,22 @@ pb_module_create (void) { return gtk_print_backend_cups_new (); } - +/* CUPS 1.6 Getter/Setter Functions CUPS 1.6 makes private most of the + * IPP structures and enforces access via new getter functions, which + * are unfortunately not available in earlier versions. We define + * below those getter functions as macros for use when building + * against earlier CUPS versions. + */ +#ifndef HAVE_CUPS_API_1_6 +#define ippGetOperation(ipp_request) ipp_request->request.op.operation_id +#define ippGetInteger(attr, index) attr->values[index].integer +#define ippGetBoolean(attr, index) attr->values[index].boolean +#define ippGetString(attr, index, foo) attr->values[index].string.text +#define ippGetValueTag(attr) attr->value_tag +#define ippGetName(attr) attr->name +#define ippGetCount(attr) attr->num_values +#define ippGetGroupTag(attr) attr->group_tag +#endif /* * GtkPrintBackendCups */ @@ -462,7 +489,7 @@ cups_print_cb (GtkPrintBackendCups *print_backend, ipp_t *response = gtk_cups_result_get_response (result); if ((attr = ippFindAttribute (response, "job-id", IPP_TAG_INTEGER)) != NULL) - job_id = attr->values[0].integer; + job_id = ippGetInteger (attr, 0); if (!gtk_print_job_get_track_print_status (ps->job) || job_id == 0) gtk_print_job_set_status (ps->job, GTK_PRINT_STATUS_FINISHED); @@ -482,22 +509,68 @@ cups_print_cb (GtkPrintBackendCups *print_backend, GDK_THREADS_LEAVE (); } +typedef struct { + GtkCupsRequest *request; + GtkPrinterCups *printer; +} CupsOptionsData; + static void add_cups_options (const gchar *key, const gchar *value, gpointer user_data) { - GtkCupsRequest *request = user_data; + CupsOptionsData *data = (CupsOptionsData *) user_data; + GtkCupsRequest *request = data->request; + GtkPrinterCups *printer = data->printer; + gboolean custom_value = FALSE; + gchar *new_value = NULL; + gint i; + + if (!key || !value) + return; if (!g_str_has_prefix (key, "cups-")) return; if (strcmp (value, "gtk-ignore-value") == 0) return; - + key = key + strlen ("cups-"); - gtk_cups_request_encode_option (request, key, value); + if (printer && printer->ppd_file) + { + ppd_coption_t *coption; + gboolean found = FALSE; + gboolean custom_values_enabled = FALSE; + + coption = ppdFindCustomOption (printer->ppd_file, key); + if (coption && coption->option) + { + for (i = 0; i < coption->option->num_choices; i++) + { + /* Are custom values enabled ? */ + if (g_str_equal (coption->option->choices[i].choice, "Custom")) + custom_values_enabled = TRUE; + + /* Is the value among available choices ? */ + if (g_str_equal (coption->option->choices[i].choice, value)) + found = TRUE; + } + + if (custom_values_enabled && !found) + custom_value = TRUE; + } + } + + /* Add "Custom." prefix to custom values. */ + if (custom_value) + { + new_value = g_strdup_printf ("Custom.%s", value); + gtk_cups_request_encode_option (request, key, new_value); + g_free (new_value); + } + else + gtk_cups_request_encode_option (request, key, value); } static void @@ -510,6 +583,7 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend, { GtkPrinterCups *cups_printer; CupsPrintStreamData *ps; + CupsOptionsData *options_data; GtkCupsRequest *request; GtkPrintSettings *settings; const gchar *title; @@ -557,8 +631,12 @@ gtk_print_backend_cups_print_stream (GtkPrintBackend *print_backend, IPP_TAG_NAME, "job-name", NULL, title); - gtk_print_settings_foreach (settings, add_cups_options, request); - + options_data = g_new0 (CupsOptionsData, 1); + options_data->request = request; + options_data->printer = cups_printer; + gtk_print_settings_foreach (settings, add_cups_options, options_data); + g_free (options_data); + ps = g_new0 (CupsPrintStreamData, 1); ps->callback = callback; ps->user_data = user_data; @@ -607,6 +685,10 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups) backend_cups->username = NULL; +#ifdef HAVE_COLORD + backend_cups->colord_client = cd_client_new (); +#endif + cups_get_local_default_printer (backend_cups); } @@ -633,6 +715,10 @@ gtk_print_backend_cups_finalize (GObject *object) g_free (backend_cups->username); +#ifdef HAVE_COLORD + g_object_unref (backend_cups->colord_client); +#endif + backend_parent_class->finalize (object); } @@ -669,40 +755,6 @@ is_address_local (const gchar *address) return FALSE; } -#ifndef HAVE_CUPS_API_1_2 -/* Included from CUPS library because of backward compatibility */ -const char * -httpGetHostname(http_t *http, - char *s, - int slen) -{ - struct hostent *host; - - if (!s || slen <= 1) - return (NULL); - - if (http) - { - if (http->hostname[0] == '/') - g_strlcpy (s, "localhost", slen); - else - g_strlcpy (s, http->hostname, slen); - } - else - { - if (gethostname (s, slen) < 0) - g_strlcpy (s, "localhost", slen); - - if (!strchr (s, '.')) - { - if ((host = gethostbyname (s)) != NULL && host->h_name) - g_strlcpy (s, host->h_name, slen); - } - } - return (s); -} -#endif - static void gtk_print_backend_cups_set_password (GtkPrintBackend *backend, gchar **auth_info_required, @@ -790,7 +842,7 @@ request_password (gpointer data) gint i; if (dispatch->backend->authentication_lock) - return FALSE; + return G_SOURCE_REMOVE; httpGetHostname (dispatch->request->http, hostname, sizeof (hostname)); if (is_address_local (hostname)) @@ -847,7 +899,7 @@ request_password (gpointer data) dispatch->backend->authentication_lock = TRUE; - switch (dispatch->request->ipp_request->request.op.operation_id) + switch (ippGetOperation (dispatch->request->ipp_request)) { case IPP_PRINT_JOB: if (job_title != NULL && printer_name != NULL) @@ -875,7 +927,7 @@ request_password (gpointer data) break; default: /* work around gcc warning about 0 not being a value for this enum */ - if (dispatch->request->ipp_request->request.op.operation_id == 0) + if (ippGetOperation (dispatch->request->ipp_request) == 0) prompt = g_strdup_printf ( _("Authentication is required to get a file from %s"), hostname); else prompt = g_strdup_printf ( _("Authentication is required on %s"), hostname); @@ -903,7 +955,7 @@ request_password (gpointer data) g_free (auth_info_visible); g_free (key); - return FALSE; + return G_SOURCE_REMOVE; } static void @@ -916,11 +968,20 @@ cups_dispatch_add_poll (GSource *source) poll_state = gtk_cups_request_get_poll_state (dispatch->request); + /* Remove the old source if the poll state changed. */ + if (poll_state != dispatch->poll_state && dispatch->data_poll != NULL) + { + g_source_remove_poll (source, dispatch->data_poll); + g_free (dispatch->data_poll); + dispatch->data_poll = NULL; + } + if (dispatch->request->http != NULL) { if (dispatch->data_poll == NULL) { dispatch->data_poll = g_new0 (GPollFD, 1); + dispatch->poll_state = poll_state; if (poll_state == GTK_CUPS_HTTP_READ) dispatch->data_poll->events = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI; @@ -929,11 +990,7 @@ cups_dispatch_add_poll (GSource *source) else dispatch->data_poll->events = 0; -#ifdef HAVE_CUPS_API_1_2 dispatch->data_poll->fd = httpGetFd (dispatch->request->http); -#else - dispatch->data_poll->fd = dispatch->request->http->fd; -#endif g_source_add_poll (source, dispatch->data_poll); } } @@ -978,10 +1035,10 @@ check_auth_info (gpointer user_data) dispatch->request->auth_info = NULL; } - return FALSE; + return G_SOURCE_REMOVE; } - return TRUE; + return G_SOURCE_CONTINUE; } static gboolean @@ -1092,13 +1149,11 @@ cups_dispatch_watch_check (GSource *source) poll_state = gtk_cups_request_get_poll_state (dispatch->request); - cups_dispatch_add_poll (source); - if (poll_state != GTK_CUPS_HTTP_IDLE && !dispatch->request->need_password) if (!(dispatch->data_poll->revents & dispatch->data_poll->events)) return FALSE; - result = gtk_cups_request_read_write (dispatch->request); + result = gtk_cups_request_read_write (dispatch->request, FALSE); if (result && dispatch->data_poll != NULL) { g_source_remove_poll (source, dispatch->data_poll); @@ -1129,8 +1184,8 @@ cups_dispatch_watch_prepare (GSource *source, g_print ("CUPS Backend: %s \n", G_STRFUNC, source)); *timeout_ = -1; - - result = gtk_cups_request_read_write (dispatch->request); + + result = gtk_cups_request_read_write (dispatch->request, TRUE); cups_dispatch_add_poll (source); @@ -1230,7 +1285,12 @@ cups_dispatch_watch_finalize (GSource *source) dispatch->backend = NULL; } - g_free (dispatch->data_poll); + if (dispatch->data_poll) + { + g_source_remove_poll (source, dispatch->data_poll); + g_free (dispatch->data_poll); + dispatch->data_poll = NULL; + } } static GSourceFuncs _cups_dispatch_watch_funcs = { @@ -1259,6 +1319,7 @@ cups_request_execute (GtkPrintBackendCups *print_backend, dispatch->request = request; dispatch->backend = g_object_ref (print_backend); + dispatch->poll_state = GTK_CUPS_HTTP_IDLE; dispatch->data_poll = NULL; dispatch->callback = NULL; dispatch->callback_data = NULL; @@ -1450,10 +1511,15 @@ cups_request_job_info_cb (GtkPrintBackendCups *print_backend, } data->counter++; - + response = gtk_cups_result_get_response (result); state = 0; + +#ifdef HAVE_CUPS_API_1_6 + attr = ippFindAttribute (response, "job-state", IPP_TAG_INTEGER); + state = ippGetInteger (attr, 0); +#else for (attr = response->attrs; attr != NULL; attr = attr->next) { if (!attr->name) @@ -1461,7 +1527,8 @@ cups_request_job_info_cb (GtkPrintBackendCups *print_backend, _CUPS_MAP_ATTR_INT (attr, state, "job-state"); } - +#endif + done = FALSE; switch (state) { @@ -1546,7 +1613,7 @@ cups_job_info_poll_timeout (gpointer user_data) else cups_request_job_info (data); - return FALSE; + return G_SOURCE_REMOVE; } static void @@ -1585,6 +1652,42 @@ find_printer (GtkPrinter *printer, printer_name = gtk_printer_get_name (printer); return g_ascii_strcasecmp (printer_name, find_name); } +/* Printer messages we're interested in */ +static const char * const printer_messages[] = + { + "toner-low", + "toner-empty", + "developer-low", + "developer-empty", + "marker-supply-low", + "marker-supply-empty", + "cover-open", + "door-open", + "media-low", + "media-empty", + "offline", + "other" + }; +/* Our translatable versions of the printer messages */ +static const char * printer_strings[] = + { + N_("Printer '%s' is low on toner."), + N_("Printer '%s' has no toner left."), + /* Translators: "Developer" like on photo development context */ + N_("Printer '%s' is low on developer."), + /* Translators: "Developer" like on photo development context */ + N_("Printer '%s' is out of developer."), + /* Translators: "marker" is one color bin of the printer */ + N_("Printer '%s' is low on at least one marker supply."), + /* Translators: "marker" is one color bin of the printer */ + N_("Printer '%s' is out of at least one marker supply."), + N_("The cover is open on printer '%s'."), + N_("The door is open on printer '%s'."), + N_("Printer '%s' is low on paper."), + N_("Printer '%s' is out of paper."), + N_("Printer '%s' is currently offline."), + N_("There is a problem on printer '%s'.") + }; static void cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend, @@ -1656,91 +1759,58 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend, gint printer_state_reason_level = 0; /* 0 - none, 1 - report, 2 - warning, 3 - error */ gboolean interested_in = FALSE; gboolean found = FALSE; - static const char * const reasons[] = /* Reasons we're interested in */ - { - "toner-low", - "toner-empty", - "developer-low", - "developer-empty", - "marker-supply-low", - "marker-supply-empty", - "cover-open", - "door-open", - "media-low", - "media-empty", - "offline", - "other" - }; - static const char * reasons_descs[] = - { - N_("Printer '%s' is low on toner."), - N_("Printer '%s' has no toner left."), - /* Translators: "Developer" like on photo development context */ - N_("Printer '%s' is low on developer."), - /* Translators: "Developer" like on photo development context */ - N_("Printer '%s' is out of developer."), - /* Translators: "marker" is one color bin of the printer */ - N_("Printer '%s' is low on at least one marker supply."), - /* Translators: "marker" is one color bin of the printer */ - N_("Printer '%s' is out of at least one marker supply."), - N_("The cover is open on printer '%s'."), - N_("The door is open on printer '%s'."), - N_("Printer '%s' is low on paper."), - N_("Printer '%s' is out of paper."), - N_("Printer '%s' is currently offline."), - N_("There is a problem on printer '%s'.") - }; gboolean is_paused = FALSE; gboolean is_accepting_jobs = TRUE; gboolean default_printer = FALSE; gboolean got_printer_type = FALSE; - gchar *default_cover_before = NULL; - gchar *default_cover_after = NULL; + const gchar *default_cover_before = NULL; + const gchar *default_cover_after = NULL; gboolean remote_printer = FALSE; gchar **auth_info_required = NULL; - + gint default_number_up = 1; + /* Skip leading attributes until we hit a printer... */ - while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) + while (attr != NULL && ippGetGroupTag (attr) != IPP_TAG_PRINTER) attr = attr->next; if (attr == NULL) break; - while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) + while (attr != NULL && ippGetGroupTag (attr) == IPP_TAG_PRINTER) { - if (strcmp (attr->name, "printer-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - printer_name = attr->values[0].string.text; - else if (strcmp (attr->name, "printer-uri-supported") == 0 && - attr->value_tag == IPP_TAG_URI) - printer_uri = attr->values[0].string.text; - else if (strcmp (attr->name, "member-uris") == 0 && - attr->value_tag == IPP_TAG_URI) - member_uris = attr->values[0].string.text; - else if (strcmp (attr->name, "printer-location") == 0) - location = attr->values[0].string.text; - else if (strcmp (attr->name, "printer-info") == 0) - description = attr->values[0].string.text; - else if (strcmp (attr->name, "printer-state-message") == 0) - state_msg = attr->values[0].string.text; - else if (strcmp (attr->name, "printer-state-reasons") == 0) + if (strcmp (ippGetName (attr), "printer-name") == 0 && + ippGetValueTag (attr) == IPP_TAG_NAME) + printer_name = ippGetString (attr, 0, NULL); + else if (strcmp (ippGetName (attr), "printer-uri-supported") == 0 && + ippGetValueTag (attr) == IPP_TAG_URI) + printer_uri = ippGetString (attr, 0, NULL); + else if (strcmp (ippGetName (attr), "member-uris") == 0 && + ippGetValueTag (attr) == IPP_TAG_URI) + member_uris = ippGetString (attr, 0, NULL); + else if (strcmp (ippGetName (attr), "printer-location") == 0) + location = ippGetString (attr, 0, NULL); + else if (strcmp (ippGetName (attr), "printer-info") == 0) + description = ippGetString (attr, 0, NULL); + else if (strcmp (ippGetName (attr), "printer-state-message") == 0) + state_msg = ippGetString (attr, 0, NULL); + else if (strcmp (ippGetName (attr), "printer-state-reasons") == 0) /* Store most important reason to reason_msg and set its importance at printer_state_reason_level */ { - for (i = 0; i < attr->num_values; i++) + for (i = 0; i < ippGetCount (attr); i++) { - if (strcmp (attr->values[i].string.text, "none") != 0) + if (strcmp (ippGetString (attr, i, NULL), "none") != 0) { /* Sets is_paused flag for paused printer. */ - if (strcmp (attr->values[i].string.text, "paused") == 0) + if (strcmp (ippGetString (attr, i, NULL), "paused") == 0) { is_paused = TRUE; } interested_in = FALSE; for (j = 0; j < G_N_ELEMENTS (reasons); j++) - if (strncmp (attr->values[i].string.text, reasons[j], strlen (reasons[j])) == 0) + if (strncmp (ippGetString (attr, i, NULL), reasons[j], strlen (reasons[j])) == 0) { interested_in = TRUE; break; @@ -1748,87 +1818,91 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend, if (interested_in) { - if (g_str_has_suffix (attr->values[i].string.text, "-report")) + if (g_str_has_suffix (ippGetString (attr, i, NULL), "-report")) { if (printer_state_reason_level <= 1) { - reason_msg = attr->values[i].string.text; + reason_msg = ippGetString (attr, i, NULL); printer_state_reason_level = 1; } } - else if (g_str_has_suffix (attr->values[i].string.text, "-warning")) + else if (g_str_has_suffix (ippGetString (attr, i, NULL), "-warning")) { if (printer_state_reason_level <= 2) { - reason_msg = attr->values[i].string.text; + reason_msg = ippGetString (attr, i, NULL); printer_state_reason_level = 2; - } + } } else /* It is error in the case of no suffix. */ { - reason_msg = attr->values[i].string.text; + reason_msg = ippGetString (attr, i, NULL); printer_state_reason_level = 3; } } } } } - else if (strcmp (attr->name, "printer-state") == 0) - state = attr->values[0].integer; - else if (strcmp (attr->name, "queued-job-count") == 0) - job_count = attr->values[0].integer; - else if (strcmp (attr->name, "printer-is-accepting-jobs") == 0) + else if (strcmp (ippGetName (attr), "printer-state") == 0) + state = ippGetInteger (attr, 0); + else if (strcmp (ippGetName (attr), "queued-job-count") == 0) + job_count = ippGetInteger (attr, 0); + else if (strcmp (ippGetName (attr), "printer-is-accepting-jobs") == 0) { - if (attr->values[0].boolean == 1) + if (ippGetBoolean (attr, 0) == 1) is_accepting_jobs = TRUE; else is_accepting_jobs = FALSE; } - else if (strcmp (attr->name, "job-sheets-supported") == 0) + else if (strcmp (ippGetName (attr), "job-sheets-supported") == 0) { if (cups_backend->covers == NULL) { - cups_backend->number_of_covers = attr->num_values; + cups_backend->number_of_covers = ippGetCount (attr); cups_backend->covers = g_new (char *, cups_backend->number_of_covers + 1); for (i = 0; i < cups_backend->number_of_covers; i++) - cups_backend->covers[i] = g_strdup (attr->values[i].string.text); + cups_backend->covers[i] = g_strdup (ippGetString (attr, i, NULL)); cups_backend->covers[cups_backend->number_of_covers] = NULL; } } - else if (strcmp (attr->name, "job-sheets-default") == 0) + else if (strcmp (ippGetName (attr), "job-sheets-default") == 0) { - if (attr->num_values == 2) + if (ippGetCount (attr) == 2) { - default_cover_before = attr->values[0].string.text; - default_cover_after = attr->values[1].string.text; + default_cover_before = ippGetString (attr, 0, NULL); + default_cover_after = ippGetString (attr, 1, NULL); } } - else if (strcmp (attr->name, "printer-type") == 0) + else if (strcmp (ippGetName (attr), "printer-type") == 0) { got_printer_type = TRUE; - if (attr->values[0].integer & 0x00020000) + if (ippGetInteger (attr, 0) & 0x00020000) default_printer = TRUE; else default_printer = FALSE; - if (attr->values[0].integer & 0x00000002) + if (ippGetInteger (attr, 0) & 0x00000002) remote_printer = TRUE; else remote_printer = FALSE; } - else if (strcmp (attr->name, "auth-info-required") == 0) + else if (strcmp (ippGetName (attr), "auth-info-required") == 0) { - if (strcmp (attr->values[0].string.text, "none") != 0) + if (strcmp (ippGetString (attr, 0, NULL), "none") != 0) { - auth_info_required = g_new0 (gchar *, attr->num_values + 1); - for (i = 0; i < attr->num_values; i++) - auth_info_required[i] = g_strdup (attr->values[i].string.text); + auth_info_required = g_new0 (gchar *, ippGetCount (attr) + 1); + for (i = 0; i < ippGetCount (attr); i++) + auth_info_required[i] = g_strdup (ippGetString (attr, i, NULL)); } } + else if (strcmp (attr->name, "number-up-default") == 0) + { + default_number_up = attr->values[0].integer; + } else { GTK_NOTE (PRINTING, - g_print ("CUPS Backend: Attribute %s ignored", attr->name)); + g_print ("CUPS Backend: Attribute %s ignored", ippGetName (attr))); } attr = attr->next; @@ -1882,7 +1956,13 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend, char *cups_server; /* CUPS server */ list_has_changed = TRUE; - cups_printer = gtk_printer_cups_new (printer_name, backend); +#ifdef HAVE_COLORD + cups_printer = gtk_printer_cups_new (printer_name, + backend, + cups_backend->colord_client); +#else + cups_printer = gtk_printer_cups_new (printer_name, backend, NULL); +#endif cups_printer->device_uri = g_strdup_printf ("/printers/%s", printer_name); @@ -1943,6 +2023,8 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend, cups_printer->default_cover_before = g_strdup (default_cover_before); cups_printer->default_cover_after = g_strdup (default_cover_after); + cups_printer->default_number_up = default_number_up; + cups_printer->hostname = g_strdup (hostname); cups_printer->port = port; @@ -2074,8 +2156,7 @@ cups_request_printer_list_cb (GtkPrintBackendCups *cups_backend, as inactive if it is in the list, emitting a printer_removed signal */ if (removed_printer_checklist != NULL) { - g_list_foreach (removed_printer_checklist, (GFunc) mark_printer_inactive, backend); - g_list_free (removed_printer_checklist); + g_list_free_full (removed_printer_checklist, (GDestroyNotify) mark_printer_inactive); list_has_changed = TRUE; } @@ -2144,7 +2225,8 @@ cups_request_printer_list (GtkPrintBackendCups *cups_backend) "job-sheets-supported", "job-sheets-default", "printer-type", - "auth-info-required" + "auth-info-required", + "number-up-default" }; if (cups_backend->reading_ppds > 0 || cups_backend->list_printers_pending) @@ -2235,7 +2317,6 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend, GtkCupsResult *result, GetPPDData *data) { - ipp_t *response; GtkPrinter *printer; GDK_THREADS_ENTER (); @@ -2264,11 +2345,12 @@ cups_request_ppd_cb (GtkPrintBackendCups *print_backend, goto done; } - response = gtk_cups_result_get_response (result); - /* let ppdOpenFd take over the ownership of the open file */ g_io_channel_seek_position (data->ppd_io, 0, G_SEEK_SET, NULL); data->printer->ppd_file = ppdOpenFd (dup (g_io_channel_unix_get_fd (data->ppd_io))); +#if (CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2) || CUPS_VERSION_MAJOR > 1 + ppdLocalize (data->printer->ppd_file); +#endif ppdMarkDefaults (data->printer->ppd_file); @@ -2641,7 +2723,7 @@ cups_request_default_printer_cb (GtkPrintBackendCups *print_backend, response = gtk_cups_result_get_response (result); if ((attr = ippFindAttribute (response, "printer-name", IPP_TAG_NAME)) != NULL) - print_backend->default_printer = g_strdup (attr->values[0].string.text); + print_backend->default_printer = g_strdup (ippGetString (attr, 0, NULL)); print_backend->got_default_printer = TRUE; @@ -3221,9 +3303,7 @@ create_pickone_option (ppd_file_t *ppd_file, char *label; int n_choices; int i; -#ifdef HAVE_CUPS_API_1_2 ppd_coption_t *coption; -#endif g_assert (ppd_option->ui == PPD_UI_PICKONE); @@ -3239,7 +3319,6 @@ create_pickone_option (ppd_file_t *ppd_file, label = get_option_text (ppd_file, ppd_option); -#ifdef HAVE_CUPS_API_1_2 coption = ppdFindCustomOption (ppd_file, ppd_option->keyword); if (coption) @@ -3292,7 +3371,6 @@ create_pickone_option (ppd_file_t *ppd_file, g_warning ("CUPS Backend: Multi-parameter PPD Custom Option not supported"); #endif } -#endif /* HAVE_CUPS_API_1_2 */ if (!option) option = gtk_printer_option_new (gtk_name, label, @@ -3314,7 +3392,18 @@ create_pickone_option (ppd_file_t *ppd_file, option->choices_display[i] = get_choice_text (ppd_file, available[i]); } } - gtk_printer_option_set (option, ppd_option->defchoice); + + if (option->type != GTK_PRINTER_OPTION_TYPE_PICKONE) + { + if (g_str_has_prefix (ppd_option->defchoice, "Custom.")) + gtk_printer_option_set (option, ppd_option->defchoice + 7); + else + gtk_printer_option_set (option, ppd_option->defchoice); + } + else + { + gtk_printer_option_set (option, ppd_option->defchoice); + } } #ifdef PRINT_IGNORED_OPTIONS else @@ -3514,6 +3603,23 @@ handle_group (GtkPrinterOptionSet *set, } +#ifdef HAVE_COLORD + +typedef struct { + GtkPrintSettings *settings; + GtkPrinter *printer; +} GtkPrintBackendCupsColordHelper; + +static void +colord_printer_option_set_changed_cb (GtkPrinterOptionSet *set, + GtkPrintBackendCupsColordHelper *helper) +{ + gtk_printer_cups_update_settings (GTK_PRINTER_CUPS (helper->printer), + helper->settings, + set); +} +#endif + static GtkPrinterOptionSet * cups_printer_get_options (GtkPrinter *printer, GtkPrintSettings *settings, @@ -3545,46 +3651,15 @@ cups_printer_get_options (GtkPrinter *printer, GtkPrintBackendCups *backend; GtkTextDirection text_direction; GtkPrinterCups *cups_printer = NULL; - +#ifdef HAVE_COLORD + GtkPrintBackendCupsColordHelper *helper; +#endif + char *default_number_up; set = gtk_printer_option_set_new (); /* Cups specific, non-ppd related settings */ - /* Translators, this string is used to label the pages-per-sheet option - * in the print dialog - */ - option = gtk_printer_option_new ("gtk-n-up", _("Pages per Sheet"), GTK_PRINTER_OPTION_TYPE_PICKONE); - gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up), - n_up, n_up); - gtk_printer_option_set (option, "1"); - set_option_from_settings (option, settings); - gtk_printer_option_set_add (set, option); - g_object_unref (option); - - if (cups_printer_get_capabilities (printer) & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) - { - for (i = 0; i < G_N_ELEMENTS (n_up_layout_display); i++) - n_up_layout_display[i] = _(n_up_layout_display[i]); - - /* Translators, this string is used to label the option in the print - * dialog that controls in what order multiple pages are arranged - */ - option = gtk_printer_option_new ("gtk-n-up-layout", _("Page Ordering"), GTK_PRINTER_OPTION_TYPE_PICKONE); - gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up_layout), - n_up_layout, n_up_layout_display); - - text_direction = gtk_widget_get_default_direction (); - if (text_direction == GTK_TEXT_DIR_LTR) - gtk_printer_option_set (option, "lrtb"); - else - gtk_printer_option_set (option, "rltb"); - - set_option_from_settings (option, settings); - gtk_printer_option_set_add (set, option); - g_object_unref (option); - } - for (i = 0; i < G_N_ELEMENTS(prio_display); i++) prio_display[i] = _(prio_display[i]); @@ -3625,6 +3700,42 @@ cups_printer_get_options (GtkPrinter *printer, gpointer value; gint j; + /* Translators, this string is used to label the pages-per-sheet option + * in the print dialog + */ + option = gtk_printer_option_new ("gtk-n-up", _("Pages per Sheet"), GTK_PRINTER_OPTION_TYPE_PICKONE); + gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up), + n_up, n_up); + default_number_up = g_strdup_printf ("%d", cups_printer->default_number_up); + gtk_printer_option_set (option, default_number_up); + g_free (default_number_up); + set_option_from_settings (option, settings); + gtk_printer_option_set_add (set, option); + g_object_unref (option); + + if (cups_printer_get_capabilities (printer) & GTK_PRINT_CAPABILITY_NUMBER_UP_LAYOUT) + { + for (i = 0; i < G_N_ELEMENTS (n_up_layout_display); i++) + n_up_layout_display[i] = _(n_up_layout_display[i]); + + /* Translators, this string is used to label the option in the print + * dialog that controls in what order multiple pages are arranged + */ + option = gtk_printer_option_new ("gtk-n-up-layout", _("Page Ordering"), GTK_PRINTER_OPTION_TYPE_PICKONE); + gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up_layout), + n_up_layout, n_up_layout_display); + + text_direction = gtk_widget_get_default_direction (); + if (text_direction == GTK_TEXT_DIR_LTR) + gtk_printer_option_set (option, "lrtb"); + else + gtk_printer_option_set (option, "rltb"); + + set_option_from_settings (option, settings); + gtk_printer_option_set_add (set, option); + g_object_unref (option); + } + num_of_covers = backend->number_of_covers; cover = g_new (char *, num_of_covers + 1); cover[num_of_covers] = NULL; @@ -3811,6 +3922,38 @@ cups_printer_get_options (GtkPrinter *printer, cupsFreeOptions (num_opts, opts); +#ifdef HAVE_COLORD + /* TRANSLATORS: this this the ICC color profile to use for this job */ + option = gtk_printer_option_new ("colord-profile", + _("Printer Profile"), + GTK_PRINTER_OPTION_TYPE_INFO); + + /* assign it to the color page */ + option->group = g_strdup ("ColorPage"); + + /* TRANSLATORS: this is when color profile information is unavailable */ + gtk_printer_option_set (option, _("Unavailable")); + gtk_printer_option_set_add (set, option); + + /* watch to see if the user changed the options */ + helper = g_new (GtkPrintBackendCupsColordHelper, 1); + helper->printer = printer; + helper->settings = settings; + g_signal_connect_data (set, "changed", + G_CALLBACK (colord_printer_option_set_changed_cb), + helper, + (GClosureNotify) g_free, + 0); + + /* initial coldplug */ + gtk_printer_cups_update_settings (GTK_PRINTER_CUPS (printer), + settings, set); + g_object_bind_property (printer, "profile-title", + option, "value", + G_BINDING_DEFAULT); + +#endif + return set; } @@ -4094,23 +4237,29 @@ set_option_from_settings (GtkPrinterOption *option, gtk_printer_option_set (option, cups_value); else { - int res = gtk_print_settings_get_resolution (settings); - int res_x = gtk_print_settings_get_resolution_x (settings); - int res_y = gtk_print_settings_get_resolution_y (settings); + if (gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_RESOLUTION, -1) != -1 || + gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_RESOLUTION_X, -1) != -1 || + gtk_print_settings_get_int_with_default (settings, GTK_PRINT_SETTINGS_RESOLUTION_Y, -1) != -1 || + option->value == NULL || option->value[0] == '\0') + { + int res = gtk_print_settings_get_resolution (settings); + int res_x = gtk_print_settings_get_resolution_x (settings); + int res_y = gtk_print_settings_get_resolution_y (settings); - if (res_x != res_y) - { - value = g_strdup_printf ("%dx%ddpi", res_x, res_y); - gtk_printer_option_set (option, value); - g_free (value); + if (res_x != res_y) + { + value = g_strdup_printf ("%dx%ddpi", res_x, res_y); + gtk_printer_option_set (option, value); + g_free (value); + } + else if (res != 0) + { + value = g_strdup_printf ("%ddpi", res); + gtk_printer_option_set (option, value); + g_free (value); + } } - else if (res != 0) - { - value = g_strdup_printf ("%ddpi", res); - gtk_printer_option_set (option, value); - g_free (value); - } - } + } } else if (strcmp (option->name, "gtk-paper-type") == 0) map_settings_to_option (option, media_type_map, G_N_ELEMENTS (media_type_map), @@ -4547,7 +4696,12 @@ cups_printer_get_default_page_size (GtkPrinter *printer) return NULL; option = ppdFindOption (ppd_file, "PageSize"); + if (option == NULL) + return NULL; + size = ppdPageSize (ppd_file, option->defchoice); + if (size == NULL) + return NULL; return create_page_setup (ppd_file, size); }