removed exec attribute
[mono.git] / mcs / class / System.Drawing / System.Drawing.Printing / PrintingServicesUnix.cs
1 //
2 // Copyright (C) 2005 Novell, Inc. http://www.novell.com
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Author:
24 //
25 //      Jordi Mas i Hernandez, jordimash@gmail.com
26 //
27
28 using System.Runtime.InteropServices;
29 using System.Collections;
30 using System.Drawing.Printing;
31 using System.ComponentModel;
32 using System.Drawing.Imaging;
33 using System.Text;
34
35 namespace System.Drawing.Printing
36 {
37         internal class PrintingServicesUnix : PrintingServices
38         {
39                 private Hashtable doc_info = new Hashtable ();
40
41                 internal PrintingServicesUnix ()
42                 {
43
44                 }
45
46                 // Methods
47                 internal override void LoadPrinterSettings (string printer, PrinterSettings settings)
48                 {
49                         IntPtr ptr, ppd_handle;
50                         string ppd_filename;
51                         PPD_FILE ppd;
52
53                         if ((printer == null) || (printer == String.Empty)) {
54                                 return;
55                         }
56
57                         ptr = cupsGetPPD (printer);
58                         ppd_filename = Marshal.PtrToStringAnsi (ptr);
59                         ppd_handle = ppdOpenFile (ppd_filename);
60                         //Console.WriteLine ("File: {0}", ppd_filename);
61
62                         ppd = (PPD_FILE) Marshal.PtrToStructure (ppd_handle, typeof (PPD_FILE));
63                         settings.landscape_angle = ppd.landscape;
64                         settings.supports_color = (ppd.color_device == 0) ? false : true;
65                         ppdClose (ppd_handle);
66                 }
67
68                 internal override void LoadPrinterResolutions (string printer, PrinterSettings settings)
69                 {
70                         settings.PrinterResolutions.Clear ();
71                         LoadDefaultResolutions (settings.PrinterResolutions);
72                 }
73
74                 internal override void LoadPrinterPaperSizes (string printer, PrinterSettings settings)
75                 {
76                         IntPtr ptr, ppd_handle;
77                         string ppd_filename, real_name;
78                         PPD_FILE ppd;
79                         PPD_SIZE size;
80                         PaperSize ps;
81                         PaperKind kind = PaperKind.Custom;
82
83                         settings.PaperSizes.Clear ();
84
85                         ptr = cupsGetPPD (printer);
86                         ppd_filename = Marshal.PtrToStringAnsi (ptr);
87                         ppd_handle = ppdOpenFile (ppd_filename);
88
89                         ppd = (PPD_FILE) Marshal.PtrToStructure (ppd_handle, typeof (PPD_FILE));
90                         ptr = ppd.sizes;
91                         float w, h;
92                         for (int i = 0; i < ppd.num_sizes; i++) {
93                                 size = (PPD_SIZE) Marshal.PtrToStructure (ptr, typeof (PPD_SIZE));
94                                 real_name = GetPaperSizeName (ppd, size.name);
95                                 ptr = new IntPtr (ptr.ToInt64 () + Marshal.SizeOf (size));
96
97                                 w = size.width * 100 / 72;
98                                 h = size.length * 100 / 72;
99                                 ps = new PaperSize (real_name, (int) w, (int) h);
100                                 // TODO: Convert from name to paper kind enum
101                                 ps.SetKind (kind);
102                                 settings.PaperSizes.Add (ps);
103                         }
104
105                         ppdClose (ppd_handle);
106                 }
107
108                 internal override bool StartPage (GraphicsPrinter gr)
109                 {
110                         return true;
111                 }
112
113                 internal override bool EndPage (GraphicsPrinter gr)
114                 {
115                         GdipGetPostScriptSavePage (gr.Hdc);
116                         return true;
117                 }
118
119                 internal override bool EndDoc (GraphicsPrinter gr)
120                 {
121                         DOCINFO doc = (DOCINFO) doc_info[gr.Hdc];
122
123                         gr.Graphics.Dispose (); // Dispose object to force surface finish
124                         cupsPrintFile (doc.settings.PrinterName, doc.filename, doc.title, 0, IntPtr.Zero);
125                         doc_info.Remove (gr.Hdc);
126                         //TODO: Delete temporary file created
127                         return true;
128                 }
129
130                 internal override bool StartDoc (GraphicsPrinter gr, string doc_name, string output_file)
131                 {
132                         DOCINFO doc = (DOCINFO) doc_info[gr.Hdc];
133                         doc.title = doc_name;
134                         return true;
135                 }
136
137                 internal override IntPtr CreateGraphicsContext (PrinterSettings settings)
138                 {
139                         IntPtr graphics = IntPtr.Zero;
140                         StringBuilder name = new StringBuilder (1024);
141                         int length = name.Capacity;
142                         cupsTempFile (name, length);
143                 
144                         GdipGetPostScriptGraphicsContext (name.ToString(),
145                                 settings.DefaultPageSettings.PaperSize.Width / 100 * 72,
146                                 settings.DefaultPageSettings.PaperSize.Height / 100 * 72, 
147                                 // Harcoded dpy's
148                                 300, 300, ref graphics);
149
150                         DOCINFO doc = new DOCINFO ();
151                         doc.filename = name.ToString();
152                         doc.settings = settings;
153                         doc_info.Add (graphics, doc);
154
155                         return graphics;
156                 }
157
158                 // Properties
159
160                 internal override PrinterSettings.StringCollection InstalledPrinters {
161                         get {
162                                 int n_printers;
163                                 IntPtr printers = IntPtr.Zero, ptr_printers, ptr_printer;
164                                 string str;
165                                 PrinterSettings.StringCollection col = new PrinterSettings.StringCollection (new string[] {});
166
167                                 /* FIXME: call is deprecated */
168                                 n_printers = cupsGetPrinters (ref printers);
169
170                                 ptr_printers = printers;
171                                 for (int i = 0; i < n_printers; i++) {
172                                         ptr_printer = (IntPtr) Marshal.ReadInt32 (ptr_printers);
173                                         str = Marshal.PtrToStringAnsi (ptr_printer);
174                                         Marshal.FreeHGlobal (ptr_printer);
175                                         ptr_printers = new IntPtr (ptr_printers.ToInt64 () + 4);
176                                         col.Add (str);
177                                 }
178                                 Marshal.FreeHGlobal (printers);
179                                 return col;
180                         }
181                 }
182
183                 internal override string DefaultPrinter {
184                         get {
185                                 IntPtr str;
186                                 str = cupsGetDefault ();
187                                 return Marshal.PtrToStringAnsi (str);
188                         }
189                 }
190
191                 // Private functions
192
193                 private string GetPaperSizeName (PPD_FILE ppd, string name)
194                 {
195                         string rslt = name;
196                         PPD_GROUP group;
197                         PPD_OPTION option;
198                         PPD_CHOICE choice;
199                         IntPtr ptr, ptr_opt, ptr_choice;
200
201                         ptr = ppd.groups;
202                         for (int i = 0; i < ppd.num_groups; i++) {
203                                 group = (PPD_GROUP) Marshal.PtrToStructure (ptr, typeof (PPD_GROUP));
204                                 //Console.WriteLine ("Size text:{0} name:{1} opts {2}", group.text, group.name, group.num_options);
205                                 ptr = new IntPtr (ptr.ToInt64 () + Marshal.SizeOf (group));
206
207                                 ptr_opt = group.options;
208                                 for (int n = 0; n < group.num_options; n++) {
209                                         option = (PPD_OPTION) Marshal.PtrToStructure (ptr_opt, typeof (PPD_OPTION));
210                                         ptr_opt = new IntPtr (ptr_opt.ToInt64 () + Marshal.SizeOf (option));
211                                         //Console.WriteLine ("   key:{0} def:{1} text: {2}", option.keyword, option.defchoice, option.text);
212
213                                         if (!option.keyword.Equals ("PageSize"))
214                                                 continue;
215
216                                         ptr_choice = option.choices;
217                                         for (int c = 0; c < option.num_choices; c++) {
218                                                 choice = (PPD_CHOICE) Marshal.PtrToStructure (ptr_choice, typeof (PPD_CHOICE));
219                                                 ptr_choice = new IntPtr (ptr_choice.ToInt64 () + Marshal.SizeOf (choice));
220                                                 //Console.WriteLine ("       choice:{0} - text: {1}", choice.choice, choice.text);
221                                                 if (name.Equals (choice.choice)) {
222                                                         rslt = choice.text;
223                                                         break;
224                                                 }
225                                         }
226                                 }
227                         }
228
229                         return rslt;
230                 }
231
232
233                 //
234                 // DllImports
235                 //
236
237                 [DllImport("libcups", CharSet=CharSet.Ansi)]
238                 static extern int cupsGetPrinters (ref IntPtr printers);
239
240                 [DllImport("libcups", CharSet=CharSet.Ansi)]
241                 static extern IntPtr cupsTempFile (StringBuilder sb, int len);
242
243                 [DllImport("libcups", CharSet=CharSet.Ansi)]
244                 static extern IntPtr cupsGetDefault ();
245
246                 [DllImport("libcups", CharSet=CharSet.Ansi)]
247                 static extern int cupsPrintFile (string printer, string filename, string title, int num_options, IntPtr options);
248
249                 [DllImport("libcups", CharSet=CharSet.Ansi)]
250                 static extern IntPtr cupsGetPPD (string printer);
251
252                 [DllImport("libcups", CharSet=CharSet.Ansi)]
253                 static extern IntPtr ppdOpenFile (string filename);
254
255                 [DllImport("libcups")]
256                 static extern void ppdClose (IntPtr ppd);
257
258                 [DllImport("libgdiplus", CharSet=CharSet.Ansi)]
259                 static extern int GdipGetPostScriptGraphicsContext (string filename, int with, int height, double dpix, double dpiy, ref IntPtr graphics);
260
261                 [DllImport("libgdiplus")]
262                 static extern int GdipGetPostScriptSavePage (IntPtr graphics);
263
264
265                 //Struct
266                 public struct DOCINFO
267                 {
268                         public PrinterSettings settings;
269                         public string title;
270                         public string filename;
271                 }
272
273                 public struct PPD_SIZE
274                 {
275                         public  int marked;
276                         [MarshalAs(UnmanagedType.ByValTStr, SizeConst=42)]
277                         public  string name;
278                         public  float width;
279                         public  float length;
280                         public  float left;
281                         public  float bottom;
282                         public  float right;
283                         public  float top;
284                 }
285
286                 public struct PPD_GROUP
287                 {
288                         [MarshalAs(UnmanagedType.ByValTStr, SizeConst=40)]
289                         public string text;
290                         [MarshalAs(UnmanagedType.ByValTStr, SizeConst=42)]
291                         public string name;
292                         public int num_options;
293                         public IntPtr options;
294                         public int num_subgroups;
295                         public IntPtr subgrups;
296                 }
297
298                 public struct PPD_OPTION
299                 {
300                         public byte     conflicted;
301                         [MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
302                         public string   keyword;
303                         [MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
304                         public string   defchoice;
305                         [MarshalAs(UnmanagedType.ByValTStr, SizeConst=81)]
306                         public string   text;
307                         public int      ui;
308                         public int      section;
309                         public float    order;
310                         public int      num_choices;
311                         public IntPtr   choices;
312                 }
313
314                 public struct PPD_CHOICE
315                 {
316                         public byte     marked;
317                         [MarshalAs(UnmanagedType.ByValTStr, SizeConst=41)]
318                         public string   choice;
319                         [MarshalAs(UnmanagedType.ByValTStr, SizeConst=81)]
320                         public string   text;
321                         public IntPtr   code;
322                         public IntPtr   option;
323                 }
324
325                 public struct PPD_FILE
326                 {
327                         public int      language_level;
328                         public int      color_device;
329                         public int      variable_sizes;
330                         public int      accurate_screens;
331                         public int      contone_only;
332                         public int      landscape;
333                         public int      model_number;
334                         public int      manual_copies;
335                         public int      throughput;
336                         public int      colorspace;
337                         public IntPtr   patches;
338                         public int      num_emulations;
339                         public IntPtr   emulations;
340                         public IntPtr   jcl_begin;
341                         public IntPtr   jcl_ps;
342                         public IntPtr   jcl_end;
343                         public IntPtr   lang_encoding;
344                         public IntPtr   lang_version;
345                         public IntPtr   modelname;
346                         public IntPtr   ttrasterizer;
347                         public IntPtr   manufacturer;
348                         public IntPtr   product;
349                         public IntPtr   nickname;
350                         public IntPtr   shortnickname;
351                         public int      num_groups;
352                         public IntPtr   groups;
353                         public int      num_sizes;
354                         public IntPtr   sizes;
355
356                         /* There is more data after this that we are not using*/
357                 }
358         }
359 }
360