3 // Copyright (C) 2005, 2007 Novell, Inc. http://www.novell.com
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 // Jordi Mas i Hernandez, jordimash@gmail.com
29 using System.Runtime.InteropServices;
30 using System.Collections;
31 using System.Collections.Specialized;
32 using System.Drawing.Printing;
33 using System.ComponentModel;
34 using System.Drawing.Imaging;
38 namespace System.Drawing.Printing
40 internal class PrintingServicesUnix : PrintingServices
42 #region Private Fields
44 private static Hashtable doc_info = new Hashtable ();
45 private static bool cups_installed;
47 private string printer_name;
49 private static Hashtable installed_printers;
50 private static string default_printer = String.Empty;
56 internal PrintingServicesUnix () {
59 static PrintingServicesUnix () {
60 installed_printers = new Hashtable ();
61 CheckCupsInstalled ();
68 internal static PrinterSettings.StringCollection InstalledPrinters {
71 PrinterSettings.StringCollection list = new PrinterSettings.StringCollection (new string[] {});
72 foreach (object key in installed_printers.Keys) {
73 list.Add (key.ToString());
79 internal override string DefaultPrinter {
81 if (installed_printers.Count == 0)
83 return default_printer;
93 /// Do a cups call to check if it is installed
95 private static void CheckCupsInstalled ()
100 catch (DllNotFoundException) {
101 Console.WriteLine("libcups not found. To have printing support, you need cups installed");
102 cups_installed = false;
106 cups_installed = true;
110 /// Open the printer's PPD file
112 /// <param name="printer">Printer name, returned from cupsGetDests</param>
113 private IntPtr OpenPrinter (string printer)
116 IntPtr ptr = cupsGetPPD (printer);
117 string ppd_filename = Marshal.PtrToStringAnsi (ptr);
118 IntPtr ppd_handle = ppdOpenFile (ppd_filename);
121 catch (Exception ex) {
122 Console.WriteLine ("There was an error opening the printer {0}. Please check your cups installation.");
124 Console.WriteLine (ex.Message);
131 /// Close the printer file
133 /// <param name="handle">PPD handle</param>
134 private void ClosePrinter (ref IntPtr handle)
137 if (handle != IntPtr.Zero)
141 handle = IntPtr.Zero;
145 private static int OpenDests (ref IntPtr ptr) {
147 return cupsGetDests (ref ptr);
155 private static void CloseDests (ref IntPtr ptr, int count) {
157 if (ptr != IntPtr.Zero)
158 cupsFreeDests (count, ptr);
166 /// Checks if a printer has a valid PPD file. Caches the result unless force is true
168 /// <param name="force">Does the check disregarding the last cached value if true</param>
169 internal override bool IsPrinterValid(string printer)
171 if (!cups_installed || printer == null | printer == String.Empty)
174 return installed_printers.Contains (printer);
176 if (!force && this.printer_name != null && String.Intern(this.printer_name).Equals(printer))
177 return is_printer_valid;
179 IntPtr ptr = cupsGetPPD (printer);
180 string ppd_filename = Marshal.PtrToStringAnsi (ptr);
181 is_printer_valid = ppd_filename != null;
182 this.printer_name = printer;
183 return is_printer_valid;
188 /// Loads the printer settings and initializes the PrinterSettings and PageSettings fields
190 /// <param name="printer">Printer name</param>
191 /// <param name="settings">PrinterSettings object to initialize</param>
192 internal override void LoadPrinterSettings (string printer, PrinterSettings settings)
194 if (cups_installed == false || (printer == null) || (printer == String.Empty))
197 if (installed_printers.Count == 0)
200 if (((SysPrn.Printer)installed_printers[printer]).Settings != null) {
201 SysPrn.Printer p = (SysPrn.Printer) installed_printers[printer];
202 settings.can_duplex = p.Settings.can_duplex;
203 settings.is_plotter = p.Settings.is_plotter;
204 settings.landscape_angle = p.Settings.landscape_angle;
205 settings.maximum_copies = p.Settings.maximum_copies;
206 settings.paper_sizes = p.Settings.paper_sizes;
207 settings.paper_sources = p.Settings.paper_sources;
208 settings.printer_capabilities = p.Settings.printer_capabilities;
209 settings.printer_resolutions = p.Settings.printer_resolutions;
210 settings.supports_color = p.Settings.supports_color;
214 settings.PrinterCapabilities.Clear ();
216 IntPtr dests = IntPtr.Zero, ptr = IntPtr.Zero, ptr_printer, ppd_handle = IntPtr.Zero;
217 string name = String.Empty;
218 CUPS_DESTS printer_dest;
220 int ret = 0, cups_dests_size;
221 NameValueCollection options, paper_names, paper_sources;
224 ret = OpenDests (ref dests);
228 cups_dests_size = Marshal.SizeOf (typeof(CUPS_DESTS));
230 for (int i = 0; i < ret; i++) {
231 ptr_printer = (IntPtr) Marshal.ReadInt32 (ptr);
232 if (Marshal.PtrToStringAnsi (ptr_printer).Equals(printer)) {
236 ptr = (IntPtr) ((long)ptr + cups_dests_size);
239 if (!name.Equals(printer)) {
243 ppd_handle = OpenPrinter (printer);
244 if (ppd_handle == IntPtr.Zero)
247 printer_dest = (CUPS_DESTS) Marshal.PtrToStructure (ptr, typeof (CUPS_DESTS));
248 options = new NameValueCollection();
249 paper_names = new NameValueCollection();
250 paper_sources = new NameValueCollection();
251 LoadPrinterOptions(printer_dest.options, printer_dest.num_options, ppd_handle, options, paper_names, paper_sources);
253 if (settings.paper_sizes == null)
254 settings.paper_sizes = new PrinterSettings.PaperSizeCollection (new PaperSize [] {});
256 settings.paper_sizes.Clear();
258 if (settings.paper_sources == null)
259 settings.paper_sources = new PrinterSettings.PaperSourceCollection (new PaperSource [] {});
261 settings.paper_sources.Clear();
263 string defsource = options["InputSlot"];
264 string defsize = options["PageSize"];
266 settings.DefaultPageSettings.PaperSource = LoadPrinterPaperSources (settings, defsource, paper_sources);
267 settings.DefaultPageSettings.PaperSize = LoadPrinterPaperSizes (ppd_handle, settings, defsize, paper_names);
269 ppd = (PPD_FILE) Marshal.PtrToStructure (ppd_handle, typeof (PPD_FILE));
270 settings.landscape_angle = ppd.landscape;
271 settings.supports_color = (ppd.color_device == 0) ? false : true;
272 settings.can_duplex = options["Duplex"] != null;
274 ClosePrinter (ref ppd_handle);
276 ((SysPrn.Printer)installed_printers[printer]).Settings = settings;
279 CloseDests (ref dests, ret);
284 /// Loads the global options of a printer plus the paper types and trays supported.
286 /// <param name="options">The options field of a printer's CUPS_DESTS structure</param>
287 /// <param name="numOptions">The number of options of the printer</param>
288 /// <param name="ppd">A ppd handle for the printer, returned by ppdOpen</param>
289 /// <param name="list">The list of options</param>
290 /// <param name="paper_names">A list of types of paper (PageSize)</param>
291 /// <param name="paper_sources">A list of trays(InputSlot) </param>
292 private static void LoadPrinterOptions(IntPtr options, int numOptions, IntPtr ppd,
293 NameValueCollection list,
294 NameValueCollection paper_names,
295 NameValueCollection paper_sources)
297 CUPS_OPTIONS cups_options;
298 string option_name, option_value;
299 int cups_size = Marshal.SizeOf(typeof(CUPS_OPTIONS));
301 for (int j = 0; j < numOptions; j++)
303 cups_options = (CUPS_OPTIONS) Marshal.PtrToStructure(options, typeof(CUPS_OPTIONS));
304 option_name = Marshal.PtrToStringAnsi(cups_options.name);
305 option_value = Marshal.PtrToStringAnsi(cups_options.val);
308 Console.WriteLine("{0} = {1}", option_name, option_value);
311 list.Add(option_name, option_value);
313 options = (IntPtr) ((long)options + cups_size);
316 LoadOptionList (ppd, "PageSize", paper_names);
317 LoadOptionList (ppd, "InputSlot", paper_sources);
321 /// Loads the global options of a printer.
323 /// <param name="options">The options field of a printer's CUPS_DESTS structure</param>
324 /// <param name="numOptions">The number of options of the printer</param>
325 private static NameValueCollection LoadPrinterOptions(IntPtr options, int numOptions)
327 CUPS_OPTIONS cups_options;
328 string option_name, option_value;
329 int cups_size = Marshal.SizeOf (typeof(CUPS_OPTIONS));
330 NameValueCollection list = new NameValueCollection ();
331 for (int j = 0; j < numOptions; j++)
333 cups_options = (CUPS_OPTIONS) Marshal.PtrToStructure(options, typeof(CUPS_OPTIONS));
334 option_name = Marshal.PtrToStringAnsi (cups_options.name);
335 option_value = Marshal.PtrToStringAnsi (cups_options.val);
338 Console.WriteLine("{0} = {1}", option_name, option_value);
341 list.Add (option_name, option_value);
343 options = (IntPtr) ((long)options + cups_size);
349 /// Loads a printer's options (selection of paper sizes, paper sources, etc)
351 /// <param name="ppd">Printer ppd file handle</param>
352 /// <param name="option_name">Name of the option group to load</param>
353 /// <param name="list">List of loaded options</param>
354 private static void LoadOptionList(IntPtr ppd, string option_name, NameValueCollection list) {
356 IntPtr ptr = IntPtr.Zero;
357 PPD_OPTION ppd_option;
359 int choice_size = Marshal.SizeOf(typeof(PPD_CHOICE));
361 ptr = ppdFindOption (ppd, option_name);
362 if (ptr != IntPtr.Zero)
364 ppd_option = (PPD_OPTION) Marshal.PtrToStructure (ptr, typeof (PPD_OPTION));
366 Console.WriteLine (" OPTION key:{0} def:{1} text: {2}", ppd_option.keyword, ppd_option.defchoice, ppd_option.text);
369 ptr = ppd_option.choices;
370 for (int c = 0; c < ppd_option.num_choices; c++) {
371 choice = (PPD_CHOICE) Marshal.PtrToStructure (ptr, typeof (PPD_CHOICE));
372 list.Add(choice.choice, choice.text);
374 Console.WriteLine (" choice:{0} - text: {1}", choice.choice, choice.text);
377 ptr = (IntPtr) ((long)ptr + choice_size);
383 /// Loads a printer's available resolutions
385 /// <param name="printer">Printer name</param>
386 /// <param name="settings">PrinterSettings object to fill</param>
387 internal override void LoadPrinterResolutions (string printer, PrinterSettings settings)
389 settings.PrinterResolutions.Clear ();
390 LoadDefaultResolutions (settings.PrinterResolutions);
394 /// Loads a printer's paper sizes. Returns the default PaperSize, and fills a list of paper_names for use in dialogues
396 /// <param name="ppd_handle">PPD printer file handle</param>
397 /// <param name="settings">PrinterSettings object to fill</param>
398 /// <param name="def_size">Default paper size, from the global options of the printer</param>
399 /// <param name="paper_names">List of available paper sizes that gets filled</param>
400 private PaperSize LoadPrinterPaperSizes(IntPtr ppd_handle, PrinterSettings settings,
401 string def_size, NameValueCollection paper_names)
409 PaperSize defsize = null;
410 ppd = (PPD_FILE) Marshal.PtrToStructure (ppd_handle, typeof (PPD_FILE));
413 for (int i = 0; i < ppd.num_sizes; i++) {
414 size = (PPD_SIZE) Marshal.PtrToStructure (ptr, typeof (PPD_SIZE));
415 real_name = paper_names[size.name];
416 w = size.width * 100 / 72;
417 h = size.length * 100 / 72;
418 ps = new PaperSize (real_name, (int) w, (int) h, GetPaperKind ((int) w, (int) h), def_size == real_name);
419 if (def_size == real_name)
421 ps.SetKind (GetPaperKind ((int) w, (int) h));
422 settings.paper_sizes.Add (ps);
423 ptr = (IntPtr) ((long)ptr + Marshal.SizeOf (size));
431 /// Loads a printer's paper sources (trays). Returns the default PaperSource, and fills a list of paper_sources for use in dialogues
433 /// <param name="settings">PrinterSettings object to fill</param>
434 /// <param name="def_source">Default paper source, from the global options of the printer</param>
435 /// <param name="paper_sources">List of available paper sizes that gets filled</param>
436 private PaperSource LoadPrinterPaperSources (PrinterSettings settings, string def_source,
437 NameValueCollection paper_sources)
439 PaperSourceKind kind;
440 PaperSource defsource = null;
441 foreach(string source in paper_sources) {
445 kind = PaperSourceKind.AutomaticFeed;
448 kind = PaperSourceKind.Envelope;
451 kind = PaperSourceKind.Manual;
454 kind = PaperSourceKind.Custom;
457 settings.paper_sources.Add (new PaperSource (paper_sources[source], kind, def_source == source));
458 if (def_source == source)
459 defsource = settings.paper_sources[settings.paper_sources.Count-1];
462 if (defsource == null && settings.paper_sources.Count > 0)
463 return settings.paper_sources[0];
469 /// <param name="load"></param>
470 /// <param name="def_printer"></param>
471 private static void LoadPrinters()
473 installed_printers.Clear ();
474 if (cups_installed == false)
477 IntPtr dests = IntPtr.Zero, ptr_printers;
480 int cups_dests_size = Marshal.SizeOf(typeof(CUPS_DESTS));
481 string name, first, type, status, comment;
482 first = type = status = comment = String.Empty;
486 n_printers = OpenDests (ref dests);
488 ptr_printers = dests;
489 for (int i = 0; i < n_printers; i++) {
490 printer = (CUPS_DESTS) Marshal.PtrToStructure (ptr_printers, typeof (CUPS_DESTS));
491 name = Marshal.PtrToStringAnsi (printer.name);
493 if (printer.is_default == 1)
494 default_printer = name;
496 if (first.Equals (String.Empty))
499 NameValueCollection options = LoadPrinterOptions(printer.options, printer.num_options);
501 if (options["printer-state"] != null)
502 state = Int32.Parse(options["printer-state"]);
504 if (options["printer-comment"] != null)
505 comment = options["printer-state"];
519 installed_printers.Add (name, new SysPrn.Printer (String.Empty, type, status, comment));
521 ptr_printers = (IntPtr) ((long)ptr_printers + cups_dests_size);
526 CloseDests (ref dests, n_printers);
529 if (default_printer.Equals (String.Empty))
530 default_printer = first;
534 /// Gets a printer's settings for use in the print dialogue
536 /// <param name="printer"></param>
537 /// <param name="port"></param>
538 /// <param name="type"></param>
539 /// <param name="status"></param>
540 /// <param name="comment"></param>
541 internal override void GetPrintDialogInfo (string printer, ref string port, ref string type, ref string status, ref string comment) {
542 int count = 0, state = -1;
544 CUPS_DESTS cups_dests;
545 IntPtr dests = IntPtr.Zero, ptr_printers, ptr_printer;
546 int cups_dests_size = Marshal.SizeOf(typeof(CUPS_DESTS));
548 if (cups_installed == false)
552 count = OpenDests (ref dests);
557 ptr_printers = dests;
559 for (int i = 0; i < count; i++) {
560 ptr_printer = (IntPtr) Marshal.ReadInt32 (ptr_printers);
561 if (Marshal.PtrToStringAnsi (ptr_printer).Equals(printer)) {
565 ptr_printers = (IntPtr) ((long)ptr_printers + cups_dests_size);
571 cups_dests = (CUPS_DESTS) Marshal.PtrToStructure (ptr_printers, typeof (CUPS_DESTS));
573 NameValueCollection options = LoadPrinterOptions(cups_dests.options, cups_dests.num_options);
575 if (options["printer-state"] != null)
576 state = Int32.Parse(options["printer-state"]);
578 if (options["printer-comment"] != null)
579 comment = options["printer-state"];
594 CloseDests (ref dests, count);
599 /// Returns the appropriate PaperKind for the width and height
601 /// <param name="width"></param>
602 /// <param name="height"></param>
603 private PaperKind GetPaperKind (int width, int height)
605 if (width == 827 && height == 1169)
607 if (width == 583 && height == 827)
609 if (width == 717 && height == 1012)
611 if (width == 693 && height == 984)
612 return PaperKind.B5Envelope;
613 if (width == 638 && height == 902)
614 return PaperKind.C5Envelope;
615 if (width == 449 && height == 638)
616 return PaperKind.C6Envelope;
617 if (width == 1700 && height == 2200)
618 return PaperKind.CSheet;
619 if (width == 433 && height == 866)
620 return PaperKind.DLEnvelope;
621 if (width == 2200 && height == 3400)
622 return PaperKind.DSheet;
623 if (width == 3400 && height == 4400)
624 return PaperKind.ESheet;
625 if (width == 725 && height == 1050)
626 return PaperKind.Executive;
627 if (width == 850 && height == 1300)
628 return PaperKind.Folio;
629 if (width == 850 && height == 1200)
630 return PaperKind.GermanStandardFanfold;
631 if (width == 1700 && height == 1100)
632 return PaperKind.Ledger;
633 if (width == 850 && height == 1400)
634 return PaperKind.Legal;
635 if (width == 927 && height == 1500)
636 return PaperKind.LegalExtra;
637 if (width == 850 && height == 1100)
638 return PaperKind.Letter;
639 if (width == 927 && height == 1200)
640 return PaperKind.LetterExtra;
641 if (width == 850 && height == 1269)
642 return PaperKind.LetterPlus;
643 if (width == 387 && height == 750)
644 return PaperKind.MonarchEnvelope;
645 if (width == 387 && height == 887)
646 return PaperKind.Number9Envelope;
647 if (width == 413 && height == 950)
648 return PaperKind.Number10Envelope;
649 if (width == 450 && height == 1037)
650 return PaperKind.Number11Envelope;
651 if (width == 475 && height == 1100)
652 return PaperKind.Number12Envelope;
653 if (width == 500 && height == 1150)
654 return PaperKind.Number14Envelope;
655 if (width == 363 && height == 650)
656 return PaperKind.PersonalEnvelope;
657 if (width == 1000 && height == 1100)
658 return PaperKind.Standard10x11;
659 if (width == 1000 && height == 1400)
660 return PaperKind.Standard10x14;
661 if (width == 1100 && height == 1700)
662 return PaperKind.Standard11x17;
663 if (width == 1200 && height == 1100)
664 return PaperKind.Standard12x11;
665 if (width == 1500 && height == 1100)
666 return PaperKind.Standard15x11;
667 if (width == 900 && height == 1100)
668 return PaperKind.Standard9x11;
669 if (width == 550 && height == 850)
670 return PaperKind.Statement;
671 if (width == 1100 && height == 1700)
672 return PaperKind.Tabloid;
673 if (width == 1487 && height == 1100)
674 return PaperKind.USStandardFanfold;
676 return PaperKind.Custom;
681 #region Print job methods
683 static string tmpfile;
686 /// Gets a pointer to an options list parsed from the printer's current settings, to use when setting up the printing job
688 /// <param name="printer_settings"></param>
689 /// <param name="page_settings"></param>
690 /// <param name="options"></param>
691 internal static int GetCupsOptions (PrinterSettings printer_settings, PageSettings page_settings, out IntPtr options)
693 options = IntPtr.Zero;
695 PaperSize size = page_settings.PaperSize;
696 int width = size.Width * 72 / 100;
697 int height = size.Height * 72 / 100;
699 StringBuilder sb = new StringBuilder();
701 "copies=" + printer_settings.Copies + " " +
702 "Collate=" + printer_settings.Collate + " " +
703 "ColorModel=" + (page_settings.Color ? "Color" : "Black") + " " +
704 "PageSize=" + String.Format ("Custom.{0}x{1}", width, height) + " " +
705 "landscape=" + page_settings.Landscape
708 if (printer_settings.CanDuplex)
710 if (printer_settings.Duplex == Duplex.Simplex)
711 sb.Append(" Duplex=None");
713 sb.Append(" Duplex=DuplexNoTumble");
716 return cupsParseOptions (sb.ToString(), 0, ref options);
719 internal static bool StartDoc (GraphicsPrinter gr, string doc_name, string output_file)
721 DOCINFO doc = (DOCINFO) doc_info[gr.Hdc];
722 doc.title = doc_name;
726 internal static bool EndDoc (GraphicsPrinter gr)
728 DOCINFO doc = (DOCINFO) doc_info[gr.Hdc];
730 gr.Graphics.Dispose (); // Dispose object to force surface finish
733 int options_count = GetCupsOptions (doc.settings, doc.default_page_settings, out options);
735 cupsPrintFile (doc.settings.PrinterName, doc.filename, doc.title, options_count, options);
736 cupsFreeOptions (options_count, options);
737 doc_info.Remove (gr.Hdc);
738 if (tmpfile != null) {
739 try { File.Delete (tmpfile); }
745 internal static bool StartPage (GraphicsPrinter gr)
750 internal static bool EndPage (GraphicsPrinter gr)
752 GdipGetPostScriptSavePage (gr.Hdc);
756 // Unfortunately, PrinterSettings and PageSettings couldn't be referencing each other,
757 // thus we need to pass them separately
758 internal static IntPtr CreateGraphicsContext (PrinterSettings settings, PageSettings default_page_settings)
760 IntPtr graphics = IntPtr.Zero;
762 if (!settings.PrintToFile) {
763 StringBuilder sb = new StringBuilder (1024);
764 int length = sb.Capacity;
765 cupsTempFile (sb, length);
766 name = sb.ToString ();
770 name = settings.PrintFileName;
772 PaperSize psize = default_page_settings.PaperSize;
774 if (default_page_settings.Landscape) { // Swap in case of landscape
775 width = psize.Height;
776 height = psize.Width;
779 height = psize.Height;
782 GdipGetPostScriptGraphicsContext (name,
785 default_page_settings.PrinterResolution.X,
786 default_page_settings.PrinterResolution.Y, ref graphics);
788 DOCINFO doc = new DOCINFO ();
790 doc.settings = settings;
791 doc.default_page_settings = default_page_settings;
792 doc_info.Add (graphics, doc);
801 [DllImport("libcups", CharSet=CharSet.Ansi)]
802 static extern int cupsGetDests (ref IntPtr dests);
804 [DllImport("libcups", CharSet=CharSet.Ansi)]
805 static extern void cupsGetDest (string name, string instance, int num_dests, ref IntPtr dests);
807 [DllImport("libcups")]
808 static extern void cupsFreeDests (int num_dests, IntPtr dests);
810 [DllImport("libcups", CharSet=CharSet.Ansi)]
811 static extern IntPtr cupsTempFile (StringBuilder sb, int len);
813 [DllImport("libcups", CharSet=CharSet.Ansi)]
814 static extern IntPtr cupsGetDefault ();
816 [DllImport("libcups", CharSet=CharSet.Ansi)]
817 static extern int cupsPrintFile (string printer, string filename, string title, int num_options, IntPtr options);
819 [DllImport("libcups", CharSet=CharSet.Ansi)]
820 static extern IntPtr cupsGetPPD (string printer);
822 [DllImport("libcups", CharSet=CharSet.Ansi)]
823 static extern IntPtr ppdOpenFile (string filename);
825 [DllImport("libcups", CharSet=CharSet.Ansi)]
826 static extern IntPtr ppdFindOption (IntPtr ppd_file, string keyword);
828 [DllImport("libcups")]
829 static extern void ppdClose (IntPtr ppd);
831 [DllImport ("libcups", CharSet=CharSet.Ansi)]
832 static extern int cupsParseOptions (string arg, int number_of_options, ref IntPtr options);
834 [DllImport("libcups")]
835 static extern void cupsFreeOptions (int number_options, IntPtr options);
837 [DllImport("gdiplus.dll", CharSet=CharSet.Ansi)]
838 static extern int GdipGetPostScriptGraphicsContext (string filename, int with, int height, double dpix, double dpiy, ref IntPtr graphics);
840 [DllImport("gdiplus.dll")]
841 static extern int GdipGetPostScriptSavePage (IntPtr graphics);
846 public struct DOCINFO
848 public PrinterSettings settings;
849 public PageSettings default_page_settings;
851 public string filename;
854 public struct PPD_SIZE
857 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=42)]
867 public struct PPD_GROUP
869 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=40)]
871 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=42)]
873 public int num_options;
874 public IntPtr options;
875 public int num_subgroups;
876 public IntPtr subgrups;
879 public struct PPD_OPTION
881 public byte conflicted;
882 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
883 public string keyword;
884 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
885 public string defchoice;
886 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=81)]
891 public int num_choices;
892 public IntPtr choices;
895 public struct PPD_CHOICE
898 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
899 public string choice;
900 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=81)]
903 public IntPtr option;
906 public struct PPD_FILE
908 public int language_level;
909 public int color_device;
910 public int variable_sizes;
911 public int accurate_screens;
912 public int contone_only;
913 public int landscape;
914 public int model_number;
915 public int manual_copies;
916 public int throughput;
917 public int colorspace;
918 public IntPtr patches;
919 public int num_emulations;
920 public IntPtr emulations;
921 public IntPtr jcl_begin;
922 public IntPtr jcl_ps;
923 public IntPtr jcl_end;
924 public IntPtr lang_encoding;
925 public IntPtr lang_version;
926 public IntPtr modelname;
927 public IntPtr ttrasterizer;
928 public IntPtr manufacturer;
929 public IntPtr product;
930 public IntPtr nickname;
931 public IntPtr shortnickname;
932 public int num_groups;
933 public IntPtr groups;
934 public int num_sizes;
937 /* There is more data after this that we are not using*/
941 public struct CUPS_OPTIONS
947 public struct CUPS_DESTS
950 public IntPtr instance;
951 public int is_default;
952 public int num_options;
953 public IntPtr options;
959 class GlobalPrintingServicesUnix : GlobalPrintingServices
\r
961 internal override PrinterSettings.StringCollection InstalledPrinters {
\r
963 return PrintingServicesUnix.InstalledPrinters;
\r
967 internal override IntPtr CreateGraphicsContext (PrinterSettings settings, PageSettings default_page_settings)
\r
969 return PrintingServicesUnix.CreateGraphicsContext (settings, default_page_settings);
\r
972 internal override bool StartDoc (GraphicsPrinter gr, string doc_name, string output_file)
\r
974 return PrintingServicesUnix.StartDoc (gr, doc_name, output_file);
\r
977 internal override bool EndDoc (GraphicsPrinter gr)
\r
979 return PrintingServicesUnix.EndDoc (gr);
\r
982 internal override bool StartPage (GraphicsPrinter gr)
\r
984 return PrintingServicesUnix.StartPage (gr);
\r
987 internal override bool EndPage (GraphicsPrinter gr)
\r
989 return PrintingServicesUnix.EndPage (gr);
\r