PrintingServicesUnix.cs :  » 2.6.4-mono-.net-core » System.Drawing » System » Drawing » Printing » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Drawing 
System.Drawing » System » Drawing » Printing » PrintingServicesUnix.cs
//#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);
    }
  }
}

www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.