/mcs/class/System.Drawing/System.Drawing.Printing/PrintingServicesUnix.cs
C# | 990 lines | 720 code | 146 blank | 124 comment | 219 complexity | ea5c95e3275308b1836c612d096ccf39 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
- //#define PrintDebug
- //
- // Copyright (C) 2005, 2007 Novell, Inc. http://www.novell.com
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- // Author:
- //
- // Jordi Mas i Hernandez, jordimash@gmail.com
- //
- using System.Runtime.InteropServices;
- using System.Collections;
- using System.Collections.Specialized;
- using System.Drawing.Printing;
- using System.ComponentModel;
- using System.Drawing.Imaging;
- using System.Text;
- using System.IO;
- namespace System.Drawing.Printing
- {
- internal class PrintingServicesUnix : PrintingServices
- {
- #region Private Fields
-
- private static Hashtable doc_info = new Hashtable ();
- private static bool cups_installed;
-
- //private string printer_name;
-
- private static Hashtable installed_printers;
- private static string default_printer = String.Empty;
-
- #endregion
- #region Constructor
- internal PrintingServicesUnix () {
- }
-
- static PrintingServicesUnix () {
- installed_printers = new Hashtable ();
- CheckCupsInstalled ();
- }
-
- #endregion
- #region Properties
- internal static PrinterSettings.StringCollection InstalledPrinters {
- get {
- LoadPrinters();
- PrinterSettings.StringCollection list = new PrinterSettings.StringCollection (new string[] {});
- foreach (object key in installed_printers.Keys) {
- list.Add (key.ToString());
- }
- return list;
- }
- }
- internal override string DefaultPrinter {
- get {
- if (installed_printers.Count == 0)
- LoadPrinters();
- return default_printer;
- }
- }
-
- #endregion
- #region Methods
- /// <summary>
- /// Do a cups call to check if it is installed
- /// </summary>
- private static void CheckCupsInstalled ()
- {
- try {
- cupsGetDefault ();
- }
- catch (DllNotFoundException) {
- Console.WriteLine("libcups not found. To have printing support, you need cups installed");
- cups_installed = false;
- return;
- }
- cups_installed = true;
- }
- /// <summary>
- /// Open the printer's PPD file
- /// </summary>
- /// <param name="printer">Printer name, returned from cupsGetDests</param>
- private IntPtr OpenPrinter (string printer)
- {
- try {
- IntPtr ptr = cupsGetPPD (printer);
- string ppd_filename = Marshal.PtrToStringAnsi (ptr);
- IntPtr ppd_handle = ppdOpenFile (ppd_filename);
- return ppd_handle;
- }
- catch (Exception) {
- Console.WriteLine ("There was an error opening the printer {0}. Please check your cups installation.");
- }
- return IntPtr.Zero;
- }
- /// <summary>
- /// Close the printer file
- /// </summary>
- /// <param name="handle">PPD handle</param>
- private void ClosePrinter (ref IntPtr handle)
- {
- try {
- if (handle != IntPtr.Zero)
- ppdClose (handle);
- }
- finally {
- handle = IntPtr.Zero;
- }
- }
- private static int OpenDests (ref IntPtr ptr) {
- try {
- return cupsGetDests (ref ptr);
- }
- catch {
- ptr = IntPtr.Zero;
- }
- return 0;
- }
- private static void CloseDests (ref IntPtr ptr, int count) {
- try {
- if (ptr != IntPtr.Zero)
- cupsFreeDests (count, ptr);
- }
- finally {
- ptr = IntPtr.Zero;
- }
- }
- /// <summary>
- /// Checks if a printer has a valid PPD file. Caches the result unless force is true
- /// </summary>
- /// <param name="force">Does the check disregarding the last cached value if true</param>
- internal override bool IsPrinterValid(string printer)
- {
- if (!cups_installed || printer == null | printer == String.Empty)
- return false;
-
- return installed_printers.Contains (printer);
- /*
- if (!force && this.printer_name != null && String.Intern(this.printer_name).Equals(printer))
- return is_printer_valid;
- IntPtr ptr = cupsGetPPD (printer);
- string ppd_filename = Marshal.PtrToStringAnsi (ptr);
- is_printer_valid = ppd_filename != null;
- this.printer_name = printer;
- return is_printer_valid;
- */
- }
-
- /// <summary>
- /// Loads the printer settings and initializes the PrinterSettings and PageSettings fields
- /// </summary>
- /// <param name="printer">Printer name</param>
- /// <param name="settings">PrinterSettings object to initialize</param>
- internal override void LoadPrinterSettings (string printer, PrinterSettings settings)
- {
- if (cups_installed == false || (printer == null) || (printer == String.Empty))
- return;
- if (installed_printers.Count == 0)
- LoadPrinters ();
- if (((SysPrn.Printer)installed_printers[printer]).Settings != null) {
- SysPrn.Printer p = (SysPrn.Printer) installed_printers[printer];
- settings.can_duplex = p.Settings.can_duplex;
- settings.is_plotter = p.Settings.is_plotter;
- settings.landscape_angle = p.Settings.landscape_angle;
- settings.maximum_copies = p.Settings.maximum_copies;
- settings.paper_sizes = p.Settings.paper_sizes;
- settings.paper_sources = p.Settings.paper_sources;
- settings.printer_capabilities = p.Settings.printer_capabilities;
- settings.printer_resolutions = p.Settings.printer_resolutions;
- settings.supports_color = p.Settings.supports_color;
- return;
- }
- settings.PrinterCapabilities.Clear ();
- IntPtr dests = IntPtr.Zero, ptr = IntPtr.Zero, ptr_printer, ppd_handle = IntPtr.Zero;
- string name = String.Empty;
- CUPS_DESTS printer_dest;
- PPD_FILE ppd;
- int ret = 0, cups_dests_size;
- NameValueCollection options, paper_names, paper_sources;
- try {
- ret = OpenDests (ref dests);
- if (ret == 0)
- return;
- cups_dests_size = Marshal.SizeOf (typeof(CUPS_DESTS));
- ptr = dests;
- for (int i = 0; i < ret; i++) {
- ptr_printer = (IntPtr) Marshal.ReadIntPtr (ptr);
- if (Marshal.PtrToStringAnsi (ptr_printer).Equals(printer)) {
- name = printer;
- break;
- }
- ptr = (IntPtr) ((long)ptr + cups_dests_size);
- }
-
- if (!name.Equals(printer)) {
- return;
- }
- ppd_handle = OpenPrinter (printer);
- if (ppd_handle == IntPtr.Zero)
- return;
- printer_dest = (CUPS_DESTS) Marshal.PtrToStructure (ptr, typeof (CUPS_DESTS));
- options = new NameValueCollection();
- paper_names = new NameValueCollection();
- paper_sources = new NameValueCollection();
- LoadPrinterOptions(printer_dest.options, printer_dest.num_options, ppd_handle, options, paper_names, paper_sources);
-
- if (settings.paper_sizes == null)
- settings.paper_sizes = new PrinterSettings.PaperSizeCollection (new PaperSize [] {});
- else
- settings.paper_sizes.Clear();
-
- if (settings.paper_sources == null)
- settings.paper_sources = new PrinterSettings.PaperSourceCollection (new PaperSource [] {});
- else
- settings.paper_sources.Clear();
-
- string defsource = options["InputSlot"];
- string defsize = options["PageSize"];
-
- settings.DefaultPageSettings.PaperSource = LoadPrinterPaperSources (settings, defsource, paper_sources);
- settings.DefaultPageSettings.PaperSize = LoadPrinterPaperSizes (ppd_handle, settings, defsize, paper_names);
-
- ppd = (PPD_FILE) Marshal.PtrToStructure (ppd_handle, typeof (PPD_FILE));
- settings.landscape_angle = ppd.landscape;
- settings.supports_color = (ppd.color_device == 0) ? false : true;
- settings.can_duplex = options["Duplex"] != null;
-
- ClosePrinter (ref ppd_handle);
-
- ((SysPrn.Printer)installed_printers[printer]).Settings = settings;
- }
- finally {
- CloseDests (ref dests, ret);
- }
- }
-
- /// <summary>
- /// Loads the global options of a printer plus the paper types and trays supported.
- /// </summary>
- /// <param name="options">The options field of a printer's CUPS_DESTS structure</param>
- /// <param name="numOptions">The number of options of the printer</param>
- /// <param name="ppd">A ppd handle for the printer, returned by ppdOpen</param>
- /// <param name="list">The list of options</param>
- /// <param name="paper_names">A list of types of paper (PageSize)</param>
- /// <param name="paper_sources">A list of trays(InputSlot) </param>
- private static void LoadPrinterOptions(IntPtr options, int numOptions, IntPtr ppd,
- NameValueCollection list,
- NameValueCollection paper_names,
- NameValueCollection paper_sources)
- {
- CUPS_OPTIONS cups_options;
- string option_name, option_value;
- int cups_size = Marshal.SizeOf(typeof(CUPS_OPTIONS));
-
- for (int j = 0; j < numOptions; j++)
- {
- cups_options = (CUPS_OPTIONS) Marshal.PtrToStructure(options, typeof(CUPS_OPTIONS));
- option_name = Marshal.PtrToStringAnsi(cups_options.name);
- option_value = Marshal.PtrToStringAnsi(cups_options.val);
- #if PrintDebug
- Console.WriteLine("{0} = {1}", option_name, option_value);
- #endif
-
- list.Add(option_name, option_value);
- options = (IntPtr) ((long)options + cups_size);
- }
-
- LoadOptionList (ppd, "PageSize", paper_names);
- LoadOptionList (ppd, "InputSlot", paper_sources);
- }
-
- /// <summary>
- /// Loads the global options of a printer.
- /// </summary>
- /// <param name="options">The options field of a printer's CUPS_DESTS structure</param>
- /// <param name="numOptions">The number of options of the printer</param>
- private static NameValueCollection LoadPrinterOptions(IntPtr options, int numOptions)
- {
- CUPS_OPTIONS cups_options;
- string option_name, option_value;
- int cups_size = Marshal.SizeOf (typeof(CUPS_OPTIONS));
- NameValueCollection list = new NameValueCollection ();
- for (int j = 0; j < numOptions; j++)
- {
- cups_options = (CUPS_OPTIONS) Marshal.PtrToStructure(options, typeof(CUPS_OPTIONS));
- option_name = Marshal.PtrToStringAnsi (cups_options.name);
- option_value = Marshal.PtrToStringAnsi (cups_options.val);
-
- #if PrintDebug
- Console.WriteLine("{0} = {1}", option_name, option_value);
- #endif
-
- list.Add (option_name, option_value);
- options = (IntPtr) ((long)options + cups_size);
- }
- return list;
- }
- /// <summary>
- /// Loads a printer's options (selection of paper sizes, paper sources, etc)
- /// </summary>
- /// <param name="ppd">Printer ppd file handle</param>
- /// <param name="option_name">Name of the option group to load</param>
- /// <param name="list">List of loaded options</param>
- private static void LoadOptionList(IntPtr ppd, string option_name, NameValueCollection list) {
- IntPtr ptr = IntPtr.Zero;
- PPD_OPTION ppd_option;
- PPD_CHOICE choice;
- int choice_size = Marshal.SizeOf(typeof(PPD_CHOICE));
-
- ptr = ppdFindOption (ppd, option_name);
- if (ptr != IntPtr.Zero)
- {
- ppd_option = (PPD_OPTION) Marshal.PtrToStructure (ptr, typeof (PPD_OPTION));
- #if PrintDebug
- Console.WriteLine (" OPTION key:{0} def:{1} text: {2}", ppd_option.keyword, ppd_option.defchoice, ppd_option.text);
- #endif
- ptr = ppd_option.choices;
- for (int c = 0; c < ppd_option.num_choices; c++) {
- choice = (PPD_CHOICE) Marshal.PtrToStructure (ptr, typeof (PPD_CHOICE));
- list.Add(choice.choice, choice.text);
- #if PrintDebug
- Console.WriteLine (" choice:{0} - text: {1}", choice.choice, choice.text);
- #endif
- ptr = (IntPtr) ((long)ptr + choice_size);
- }
- }
- }
- /// <summary>
- /// Loads a printer's available resolutions
- /// </summary>
- /// <param name="printer">Printer name</param>
- /// <param name="settings">PrinterSettings object to fill</param>
- internal override void LoadPrinterResolutions (string printer, PrinterSettings settings)
- {
- settings.PrinterResolutions.Clear ();
- LoadDefaultResolutions (settings.PrinterResolutions);
- }
- /// <summary>
- /// Loads a printer's paper sizes. Returns the default PaperSize, and fills a list of paper_names for use in dialogues
- /// </summary>
- /// <param name="ppd_handle">PPD printer file handle</param>
- /// <param name="settings">PrinterSettings object to fill</param>
- /// <param name="def_size">Default paper size, from the global options of the printer</param>
- /// <param name="paper_names">List of available paper sizes that gets filled</param>
- private PaperSize LoadPrinterPaperSizes(IntPtr ppd_handle, PrinterSettings settings,
- string def_size, NameValueCollection paper_names)
- {
- IntPtr ptr;
- string real_name;
- PPD_FILE ppd;
- PPD_SIZE size;
- PaperSize ps;
- PaperSize defsize = null;
- ppd = (PPD_FILE) Marshal.PtrToStructure (ppd_handle, typeof (PPD_FILE));
- ptr = ppd.sizes;
- float w, h;
- for (int i = 0; i < ppd.num_sizes; i++) {
- size = (PPD_SIZE) Marshal.PtrToStructure (ptr, typeof (PPD_SIZE));
- real_name = paper_names[size.name];
- w = size.width * 100 / 72;
- h = size.length * 100 / 72;
- ps = new PaperSize (real_name, (int) w, (int) h, GetPaperKind ((int) w, (int) h), def_size == real_name);
- if (def_size == real_name)
- defsize = ps;
- ps.SetKind (GetPaperKind ((int) w, (int) h));
- settings.paper_sizes.Add (ps);
- ptr = (IntPtr) ((long)ptr + Marshal.SizeOf (size));
- }
-
- return defsize;
- }
-
- /// <summary>
- /// Loads a printer's paper sources (trays). Returns the default PaperSource, and fills a list of paper_sources for use in dialogues
- /// </summary>
- /// <param name="settings">PrinterSettings object to fill</param>
- /// <param name="def_source">Default paper source, from the global options of the printer</param>
- /// <param name="paper_sources">List of available paper sizes that gets filled</param>
- private PaperSource LoadPrinterPaperSources (PrinterSettings settings, string def_source,
- NameValueCollection paper_sources)
- {
- PaperSourceKind kind;
- PaperSource defsource = null;
- foreach(string source in paper_sources) {
- switch (source)
- {
- case "Tray":
- kind = PaperSourceKind.AutomaticFeed;
- break;
- case "Envelope":
- kind = PaperSourceKind.Envelope;
- break;
- case "Manual":
- kind = PaperSourceKind.Manual;
- break;
- default:
- kind = PaperSourceKind.Custom;
- break;
- }
- settings.paper_sources.Add (new PaperSource (paper_sources[source], kind, def_source == source));
- if (def_source == source)
- defsource = settings.paper_sources[settings.paper_sources.Count-1];
- }
-
- if (defsource == null && settings.paper_sources.Count > 0)
- return settings.paper_sources[0];
- return defsource;
- }
- /// <summary>
- /// </summary>
- /// <param name="load"></param>
- /// <param name="def_printer"></param>
- private static void LoadPrinters()
- {
- installed_printers.Clear ();
- if (cups_installed == false)
- return;
-
- IntPtr dests = IntPtr.Zero, ptr_printers;
- CUPS_DESTS printer;
- int n_printers = 0;
- int cups_dests_size = Marshal.SizeOf(typeof(CUPS_DESTS));
- string name, first, type, status, comment;
- first = type = status = comment = String.Empty;
- int state = 0;
-
- try {
- n_printers = OpenDests (ref dests);
- ptr_printers = dests;
- for (int i = 0; i < n_printers; i++) {
- printer = (CUPS_DESTS) Marshal.PtrToStructure (ptr_printers, typeof (CUPS_DESTS));
- name = Marshal.PtrToStringAnsi (printer.name);
- if (printer.is_default == 1)
- default_printer = name;
-
- if (first.Equals (String.Empty))
- first = name;
-
- NameValueCollection options = LoadPrinterOptions(printer.options, printer.num_options);
-
- if (options["printer-state"] != null)
- state = Int32.Parse(options["printer-state"]);
-
- if (options["printer-comment"] != null)
- comment = options["printer-state"];
- switch(state) {
- case 4:
- status = "Printing";
- break;
- case 5:
- status = "Stopped";
- break;
- default:
- status = "Ready";
- break;
- }
-
- installed_printers.Add (name, new SysPrn.Printer (String.Empty, type, status, comment));
- ptr_printers = (IntPtr) ((long)ptr_printers + cups_dests_size);
- }
-
- }
- finally {
- CloseDests (ref dests, n_printers);
- }
-
- if (default_printer.Equals (String.Empty))
- default_printer = first;
- }
- /// <summary>
- /// Gets a printer's settings for use in the print dialogue
- /// </summary>
- /// <param name="printer"></param>
- /// <param name="port"></param>
- /// <param name="type"></param>
- /// <param name="status"></param>
- /// <param name="comment"></param>
- internal override void GetPrintDialogInfo (string printer, ref string port, ref string type, ref string status, ref string comment) {
- int count = 0, state = -1;
- bool found = false;
- CUPS_DESTS cups_dests;
- IntPtr dests = IntPtr.Zero, ptr_printers, ptr_printer;
- int cups_dests_size = Marshal.SizeOf(typeof(CUPS_DESTS));
-
- if (cups_installed == false)
- return;
- try {
- count = OpenDests (ref dests);
- if (count == 0)
- return;
- ptr_printers = dests;
- for (int i = 0; i < count; i++) {
- ptr_printer = (IntPtr) Marshal.ReadIntPtr (ptr_printers);
- if (Marshal.PtrToStringAnsi (ptr_printer).Equals(printer)) {
- found = true;
- break;
- }
- ptr_printers = (IntPtr) ((long)ptr_printers + cups_dests_size);
- }
-
- if (!found)
- return;
-
- cups_dests = (CUPS_DESTS) Marshal.PtrToStructure (ptr_printers, typeof (CUPS_DESTS));
-
- NameValueCollection options = LoadPrinterOptions(cups_dests.options, cups_dests.num_options);
- if (options["printer-state"] != null)
- state = Int32.Parse(options["printer-state"]);
-
- if (options["printer-comment"] != null)
- comment = options["printer-state"];
- switch(state) {
- case 4:
- status = "Printing";
- break;
- case 5:
- status = "Stopped";
- break;
- default:
- status = "Ready";
- break;
- }
- }
- finally {
- CloseDests (ref dests, count);
- }
- }
- /// <summary>
- /// Returns the appropriate PaperKind for the width and height
- /// </summary>
- /// <param name="width"></param>
- /// <param name="height"></param>
- private PaperKind GetPaperKind (int width, int height)
- {
- if (width == 827 && height == 1169)
- return PaperKind.A4;
- if (width == 583 && height == 827)
- return PaperKind.A5;
- if (width == 717 && height == 1012)
- return PaperKind.B5;
- if (width == 693 && height == 984)
- return PaperKind.B5Envelope;
- if (width == 638 && height == 902)
- return PaperKind.C5Envelope;
- if (width == 449 && height == 638)
- return PaperKind.C6Envelope;
- if (width == 1700 && height == 2200)
- return PaperKind.CSheet;
- if (width == 433 && height == 866)
- return PaperKind.DLEnvelope;
- if (width == 2200 && height == 3400)
- return PaperKind.DSheet;
- if (width == 3400 && height == 4400)
- return PaperKind.ESheet;
- if (width == 725 && height == 1050)
- return PaperKind.Executive;
- if (width == 850 && height == 1300)
- return PaperKind.Folio;
- if (width == 850 && height == 1200)
- return PaperKind.GermanStandardFanfold;
- if (width == 1700 && height == 1100)
- return PaperKind.Ledger;
- if (width == 850 && height == 1400)
- return PaperKind.Legal;
- if (width == 927 && height == 1500)
- return PaperKind.LegalExtra;
- if (width == 850 && height == 1100)
- return PaperKind.Letter;
- if (width == 927 && height == 1200)
- return PaperKind.LetterExtra;
- if (width == 850 && height == 1269)
- return PaperKind.LetterPlus;
- if (width == 387 && height == 750)
- return PaperKind.MonarchEnvelope;
- if (width == 387 && height == 887)
- return PaperKind.Number9Envelope;
- if (width == 413 && height == 950)
- return PaperKind.Number10Envelope;
- if (width == 450 && height == 1037)
- return PaperKind.Number11Envelope;
- if (width == 475 && height == 1100)
- return PaperKind.Number12Envelope;
- if (width == 500 && height == 1150)
- return PaperKind.Number14Envelope;
- if (width == 363 && height == 650)
- return PaperKind.PersonalEnvelope;
- if (width == 1000 && height == 1100)
- return PaperKind.Standard10x11;
- if (width == 1000 && height == 1400)
- return PaperKind.Standard10x14;
- if (width == 1100 && height == 1700)
- return PaperKind.Standard11x17;
- if (width == 1200 && height == 1100)
- return PaperKind.Standard12x11;
- if (width == 1500 && height == 1100)
- return PaperKind.Standard15x11;
- if (width == 900 && height == 1100)
- return PaperKind.Standard9x11;
- if (width == 550 && height == 850)
- return PaperKind.Statement;
- if (width == 1100 && height == 1700)
- return PaperKind.Tabloid;
- if (width == 1487 && height == 1100)
- return PaperKind.USStandardFanfold;
- return PaperKind.Custom;
- }
- #endregion
- #region Print job methods
- static string tmpfile;
- /// <summary>
- /// Gets a pointer to an options list parsed from the printer's current settings, to use when setting up the printing job
- /// </summary>
- /// <param name="printer_settings"></param>
- /// <param name="page_settings"></param>
- /// <param name="options"></param>
- internal static int GetCupsOptions (PrinterSettings printer_settings, PageSettings page_settings, out IntPtr options)
- {
- options = IntPtr.Zero;
- PaperSize size = page_settings.PaperSize;
- int width = size.Width * 72 / 100;
- int height = size.Height * 72 / 100;
- StringBuilder sb = new StringBuilder();
- sb.Append(
- "copies=" + printer_settings.Copies + " " +
- "Collate=" + printer_settings.Collate + " " +
- "ColorModel=" + (page_settings.Color ? "Color" : "Black") + " " +
- "PageSize=" + String.Format ("Custom.{0}x{1}", width, height) + " " +
- "landscape=" + page_settings.Landscape
- );
-
- if (printer_settings.CanDuplex)
- {
- if (printer_settings.Duplex == Duplex.Simplex)
- sb.Append(" Duplex=None");
- else
- sb.Append(" Duplex=DuplexNoTumble");
- }
- return cupsParseOptions (sb.ToString(), 0, ref options);
- }
- internal static bool StartDoc (GraphicsPrinter gr, string doc_name, string output_file)
- {
- DOCINFO doc = (DOCINFO) doc_info[gr.Hdc];
- doc.title = doc_name;
- return true;
- }
- internal static bool EndDoc (GraphicsPrinter gr)
- {
- DOCINFO doc = (DOCINFO) doc_info[gr.Hdc];
- gr.Graphics.Dispose (); // Dispose object to force surface finish
-
- IntPtr options;
- int options_count = GetCupsOptions (doc.settings, doc.default_page_settings, out options);
- cupsPrintFile (doc.settings.PrinterName, doc.filename, doc.title, options_count, options);
- cupsFreeOptions (options_count, options);
- doc_info.Remove (gr.Hdc);
- if (tmpfile != null) {
- try { File.Delete (tmpfile); }
- catch { }
- }
- return true;
- }
- internal static bool StartPage (GraphicsPrinter gr)
- {
- return true;
- }
- internal static bool EndPage (GraphicsPrinter gr)
- {
- GdipGetPostScriptSavePage (gr.Hdc);
- return true;
- }
- // Unfortunately, PrinterSettings and PageSettings couldn't be referencing each other,
- // thus we need to pass them separately
- internal static IntPtr CreateGraphicsContext (PrinterSettings settings, PageSettings default_page_settings)
- {
- IntPtr graphics = IntPtr.Zero;
- string name;
- if (!settings.PrintToFile) {
- StringBuilder sb = new StringBuilder (1024);
- int length = sb.Capacity;
- cupsTempFile (sb, length);
- name = sb.ToString ();
- tmpfile = name;
- }
- else
- name = settings.PrintFileName;
- PaperSize psize = default_page_settings.PaperSize;
- int width, height;
- if (default_page_settings.Landscape) { // Swap in case of landscape
- width = psize.Height;
- height = psize.Width;
- } else {
- width = psize.Width;
- height = psize.Height;
- }
- GdipGetPostScriptGraphicsContext (name,
- width * 72 / 100,
- height * 72 / 100,
- default_page_settings.PrinterResolution.X,
- default_page_settings.PrinterResolution.Y, ref graphics);
- DOCINFO doc = new DOCINFO ();
- doc.filename = name;
- doc.settings = settings;
- doc.default_page_settings = default_page_settings;
- doc_info.Add (graphics, doc);
- return graphics;
- }
- #endregion
- #region DllImports
- [DllImport("libcups", CharSet=CharSet.Ansi)]
- static extern int cupsGetDests (ref IntPtr dests);
- // [DllImport("libcups", CharSet=CharSet.Ansi)]
- // static extern void cupsGetDest (string name, string instance, int num_dests, ref IntPtr dests);
- [DllImport("libcups")]
- static extern void cupsFreeDests (int num_dests, IntPtr dests);
- [DllImport("libcups", CharSet=CharSet.Ansi)]
- static extern IntPtr cupsTempFile (StringBuilder sb, int len);
- [DllImport("libcups", CharSet=CharSet.Ansi)]
- static extern IntPtr cupsGetDefault ();
- [DllImport("libcups", CharSet=CharSet.Ansi)]
- static extern int cupsPrintFile (string printer, string filename, string title, int num_options, IntPtr options);
- [DllImport("libcups", CharSet=CharSet.Ansi)]
- static extern IntPtr cupsGetPPD (string printer);
- [DllImport("libcups", CharSet=CharSet.Ansi)]
- static extern IntPtr ppdOpenFile (string filename);
- [DllImport("libcups", CharSet=CharSet.Ansi)]
- static extern IntPtr ppdFindOption (IntPtr ppd_file, string keyword);
- [DllImport("libcups")]
- static extern void ppdClose (IntPtr ppd);
- [DllImport ("libcups", CharSet=CharSet.Ansi)]
- static extern int cupsParseOptions (string arg, int number_of_options, ref IntPtr options);
- [DllImport("libcups")]
- static extern void cupsFreeOptions (int number_options, IntPtr options);
- [DllImport("gdiplus.dll", CharSet=CharSet.Ansi)]
- static extern int GdipGetPostScriptGraphicsContext (string filename, int with, int height, double dpix, double dpiy, ref IntPtr graphics);
- [DllImport("gdiplus.dll")]
- static extern int GdipGetPostScriptSavePage (IntPtr graphics);
- #endregion
- #region Struct
- public struct DOCINFO
- {
- public PrinterSettings settings;
- public PageSettings default_page_settings;
- public string title;
- public string filename;
- }
- public struct PPD_SIZE
- {
- public int marked;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst=42)]
- public string name;
- public float width;
- public float length;
- public float left;
- public float bottom;
- public float right;
- public float top;
- }
- public struct PPD_GROUP
- {
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst=40)]
- public string text;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst=42)]
- public string name;
- public int num_options;
- public IntPtr options;
- public int num_subgroups;
- public IntPtr subgrups;
- }
- public struct PPD_OPTION
- {
- public byte conflicted;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
- public string keyword;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
- public string defchoice;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst=81)]
- public string text;
- public int ui;
- public int section;
- public float order;
- public int num_choices;
- public IntPtr choices;
- }
- public struct PPD_CHOICE
- {
- public byte marked;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
- public string choice;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst=81)]
- public string text;
- public IntPtr code;
- public IntPtr option;
- }
- public struct PPD_FILE
- {
- public int language_level;
- public int color_device;
- public int variable_sizes;
- public int accurate_screens;
- public int contone_only;
- public int landscape;
- public int model_number;
- public int manual_copies;
- public int throughput;
- public int colorspace;
- public IntPtr patches;
- public int num_emulations;
- public IntPtr emulations;
- public IntPtr jcl_begin;
- public IntPtr jcl_ps;
- public IntPtr jcl_end;
- public IntPtr lang_encoding;
- public IntPtr lang_version;
- public IntPtr modelname;
- public IntPtr ttrasterizer;
- public IntPtr manufacturer;
- public IntPtr product;
- public IntPtr nickname;
- public IntPtr shortnickname;
- public int num_groups;
- public IntPtr groups;
- public int num_sizes;
- public IntPtr sizes;
- /* There is more data after this that we are not using*/
- }
- public struct CUPS_OPTIONS
- {
- public IntPtr name;
- public IntPtr val;
- }
-
- public struct CUPS_DESTS
- {
- public IntPtr name;
- public IntPtr instance;
- public int is_default;
- public int num_options;
- public IntPtr options;
- }
-
- #endregion
- }
- class GlobalPrintingServicesUnix : GlobalPrintingServices
- {
- internal override PrinterSettings.StringCollection InstalledPrinters {
- get {
- return PrintingServicesUnix.InstalledPrinters;
- }
- }
- internal override IntPtr CreateGraphicsContext (PrinterSettings settings, PageSettings default_page_settings)
- {
- return PrintingServicesUnix.CreateGraphicsContext (settings, default_page_settings);
- }
- internal override bool StartDoc (GraphicsPrinter gr, string doc_name, string output_file)
- {
- return PrintingServicesUnix.StartDoc (gr, doc_name, output_file);
- }
- internal override bool EndDoc (GraphicsPrinter gr)
- {
- return PrintingServicesUnix.EndDoc (gr);
- }
- internal override bool StartPage (GraphicsPrinter gr)
- {
- return PrintingServicesUnix.StartPage (gr);
- }
- internal override bool EndPage (GraphicsPrinter gr)
- {
- return PrintingServicesUnix.EndPage (gr);
- }
- }
- }