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);
-
+ string defsize;
+ string defsource;
+ LoadPrinterOptions (printer_dest.options, printer_dest.num_options, ppd_handle, options,
+ paper_names, out defsize,
+ paper_sources, out defsource);
+
if (settings.paper_sizes == null)
settings.paper_sizes = new PrinterSettings.PaperSizeCollection (new PaperSize [] {});
else
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);
-
+ LoadPrinterResolutionsAndDefault (printer, settings, ppd_handle);
+
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;
}
/// <summary>
- /// Loads the global options of a printer plus the paper types and trays supported.
+ /// Loads the global options of a printer plus the paper types and trays supported,
+ /// and sets the default paper size and source tray.
/// </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="defsize">The default paper size, set by LoadOptionList</param>
/// <param name="paper_sources">A list of trays(InputSlot) </param>
+ /// <param name="defsource">The default source tray, set by LoadOptionList</param>
private static void LoadPrinterOptions(IntPtr options, int numOptions, IntPtr ppd,
NameValueCollection list,
- NameValueCollection paper_names,
- NameValueCollection paper_sources)
+ NameValueCollection paper_names, out string defsize,
+ NameValueCollection paper_sources, out string defsource)
{
CUPS_OPTIONS cups_options;
string option_name, option_value;
options = (IntPtr) ((long)options + cups_size);
}
- LoadOptionList (ppd, "PageSize", paper_names);
- LoadOptionList (ppd, "InputSlot", paper_sources);
+ LoadOptionList (ppd, "PageSize", paper_names, out defsize);
+ LoadOptionList (ppd, "InputSlot", paper_sources, out defsource);
}
/// <summary>
/// <summary>
/// Loads a printer's options (selection of paper sizes, paper sources, etc)
+ /// and sets the default option from the selected list.
/// </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) {
+ /// <param name="defoption">The default option from the loaded options list</param>
+ private static void LoadOptionList (IntPtr ppd, string option_name, NameValueCollection list, out string defoption) {
IntPtr ptr = IntPtr.Zero;
PPD_OPTION ppd_option;
PPD_CHOICE choice;
int choice_size = Marshal.SizeOf(typeof(PPD_CHOICE));
+ defoption = null;
ptr = ppdFindOption (ppd, option_name);
if (ptr != IntPtr.Zero)
#if PrintDebug
Console.WriteLine (" OPTION key:{0} def:{1} text: {2}", ppd_option.keyword, ppd_option.defchoice, ppd_option.text);
#endif
-
+ defoption = ppd_option.defchoice;
ptr = ppd_option.choices;
for (int c = 0; c < ppd_option.num_choices; c++) {
choice = (PPD_CHOICE) Marshal.PtrToStructure (ptr, typeof (PPD_CHOICE));
/// <param name="settings">PrinterSettings object to fill</param>
internal override void LoadPrinterResolutions (string printer, PrinterSettings settings)
{
- settings.PrinterResolutions.Clear ();
- LoadDefaultResolutions (settings.PrinterResolutions);
+ IntPtr ppd_handle = OpenPrinter (printer);
+ if (ppd_handle == IntPtr.Zero)
+ return;
+
+ LoadPrinterResolutionsAndDefault (printer, settings, ppd_handle);
+
+ ClosePrinter (ref ppd_handle);
+ }
+
+ /// <summary>
+ /// Create a PrinterResolution from a string Resolution that is set in the PPD option.
+ /// An example of Resolution is "600x600dpi" or "600dpi". Returns null if malformed or "Unknown".
+ /// </summary>
+ private PrinterResolution ParseResolution (string resolution)
+ {
+ if (String.IsNullOrEmpty (resolution))
+ return null;
+
+ int dpiIndex = resolution.IndexOf ("dpi");
+ if (dpiIndex == -1)
+ {
+ // Resolution is "Unknown" or unparsable
+ return null;
+ }
+ resolution = resolution.Substring (0, dpiIndex);
+
+ int x_resolution, y_resolution;
+ try {
+ if (resolution.Contains ("x")) {
+ string[] resolutions = resolution.Split (new[] {'x'});
+ x_resolution = Convert.ToInt32 (resolutions [0]);
+ y_resolution = Convert.ToInt32 (resolutions [1]);
+ } else {
+ x_resolution = Convert.ToInt32 (resolution);
+ y_resolution = x_resolution;
+ }
+ } catch (Exception) {
+ return null;
+ }
+
+ return new PrinterResolution (x_resolution, y_resolution, PrinterResolutionKind.Custom);
}
/// <summary>
PPD_SIZE size;
PaperSize ps;
- PaperSize defsize = null;
+ PaperSize defsize = new PaperSize ("A4", 827, 1169, GetPaperKind (827, 1169), true);
ppd = (PPD_FILE) Marshal.PtrToStructure (ppd_handle, typeof (PPD_FILE));
ptr = ppd.sizes;
float w, h;
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)
+ PaperKind kind = GetPaperKind ((int) w, (int) h);
+ ps = new PaperSize (real_name, (int) w, (int) h, kind, def_size == kind.ToString ());
+ ps.SetKind (kind);
+ if (def_size == ps.Kind.ToString ())
defsize = ps;
- ps.SetKind (GetPaperKind ((int) w, (int) h));
settings.paper_sizes.Add (ps);
ptr = (IntPtr) ((long)ptr + Marshal.SizeOf (size));
}
foreach(string source in paper_sources) {
switch (source)
{
+ case "Auto":
+ kind = PaperSourceKind.AutomaticFeed;
+ break;
+ case "Standard":
+ kind = PaperSourceKind.AutomaticFeed;
+ break;
case "Tray":
kind = PaperSourceKind.AutomaticFeed;
break;
return defsource;
}
+ /// <summary>
+ /// Sets the available resolutions and default resolution from a
+ /// printer's PPD file into settings.
+ /// </summary>
+ private void LoadPrinterResolutionsAndDefault (string printer,
+ PrinterSettings settings, IntPtr ppd_handle)
+ {
+ if (settings.printer_resolutions == null)
+ settings.printer_resolutions = new PrinterSettings.PrinterResolutionCollection (new PrinterResolution [] {});
+ else
+ settings.printer_resolutions.Clear ();
+
+ var printer_resolutions = new NameValueCollection ();
+ string defresolution;
+ LoadOptionList (ppd_handle, "Resolution", printer_resolutions, out defresolution);
+ foreach (var resolution in printer_resolutions.Keys) {
+ var new_resolution = ParseResolution (resolution.ToString ());
+ settings.PrinterResolutions.Add (new_resolution);
+ }
+
+ var default_resolution = ParseResolution (defresolution);
+
+ if (default_resolution == null)
+ default_resolution = ParseResolution ("300dpi");
+ if (printer_resolutions.Count == 0)
+ settings.PrinterResolutions.Add (default_resolution);
+
+ settings.DefaultPageSettings.PrinterResolution = default_resolution;
+ }
+
/// <summary>
/// </summary>
/// <param name="load"></param>
//
using System;
+using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
Assert.AreEqual (Status.InvalidParameter, GdipGetPostScriptSavePage (IntPtr.Zero), "Missing printing support");
}
+
+ #region Novell Bug #602934
+
+ #region CUPS methods and structs
+
+ [StructLayout (LayoutKind.Sequential)]
+ struct CUPS_DEST
+ {
+ public string Name;
+ public string Instance;
+ public int IsDefault;
+ public int NumOptions;
+ public IntPtr Options;
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ struct CUPS_OPTION
+ {
+ public string Name;
+ public string Value;
+ }
+
+ readonly IntPtr CUPS_HTTP_DEFAULT = IntPtr.Zero;
+
+ [DllImport ("libcups")]
+ static extern IntPtr cupsGetNamedDest (IntPtr http, string name, string instance);
+
+ [DllImport ("libcups")]
+ static extern void cupsFreeDests (int num_dests, IntPtr dests);
+
+ [DllImport ("libcups")]
+ static extern void cupsFreeDests (int num_dests, ref CUPS_DEST dests);
+
+ #endregion
+
+ Dictionary<string, string> GetOptionsOfFirstPrinterThroughCups ()
+ {
+ var options = new Dictionary<string, string> ();
+
+ var destPtr = cupsGetNamedDest (CUPS_HTTP_DEFAULT, PrinterSettings.InstalledPrinters [0], null);
+ var dest = (CUPS_DEST)Marshal.PtrToStructure (destPtr, typeof(CUPS_DEST));
+ var optionPtr = dest.Options;
+ int cupsOptionSize = Marshal.SizeOf (typeof(CUPS_OPTION));
+ for (int i = 0; i < dest.NumOptions; i++) {
+ var cupsOption = (CUPS_OPTION)Marshal.PtrToStructure (optionPtr, typeof(CUPS_OPTION));
+ options.Add (cupsOption.Name, cupsOption.Value);
+ optionPtr = (IntPtr)((long)optionPtr + cupsOptionSize);
+ }
+ cupsFreeDests (1, destPtr);
+
+ return options;
+ }
+
+ [Test]
+ [Platform (Exclude = "Win", Reason = "Depends on CUPS which is usually not installed on Windows")]
+ public void Bug602934_PrinterSettingsReturnActualValues ()
+ {
+ if (PrinterSettings.InstalledPrinters.Count < 1)
+ Assert.Ignore ("Need at least one printer installed.");
+
+ var options = GetOptionsOfFirstPrinterThroughCups ();
+
+ var settings = new PrinterSettings () { PrinterName = PrinterSettings.InstalledPrinters [0] };
+ Assert.AreEqual (options ["PageSize"], settings.DefaultPageSettings.PaperSize.PaperName,
+ "Bug #602934 (https://bugzilla.novell.com/show_bug.cgi?id=602934) not fixed (PaperSize)");
+ Assert.AreEqual (options ["Resolution"], string.Format ("{0}dpi", settings.DefaultPageSettings.PrinterResolution.X),
+ "Bug #602934 (https://bugzilla.novell.com/show_bug.cgi?id=602934) not fixed (Resolution)");
+ }
+
+ #endregion
+
}
}