merge -r 61110:61111
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / MimeIcon.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //
24 //  Alexander Olk       xenomorph2@onlinehome.de
25 //
26
27 // short "how to" if you want to add an other platform handler, etc:
28 // - first add mime type names and icon names (best is without extension) to MimeIconEngine, for example:
29 //   MimeIconEngine.AddMimeTypeAndIconName( "inode/directory", "gnome-fs-directory" );
30 // - next add the icon name (the same as used in AddMimeTypeAndIconName) and the full filename, for example:
31 //   MimeIconEngine.AddIcon( "gnome-fs-directory", "/opt/gnome/share/icons/gnome/48x48/filesystems/gnome-fs-directory.png" );
32 //   AddIcon adds the icon to the image lists SmallIconList and LargeIconList
33 // - provide always a "unknown/unknown" 'mime type' with a default icon for unkown mime types,
34 //   "desktop/desktop" 'mime type' for the desktop icon, "directory/home" 'mime type for the home dir of the user and so on
35 //   (look at the default platform handler)
36 //
37 // use
38 // public static int GetIconIndexForFile( string full_filename )
39 // public static int GetIconIndexForMimeType( string mime_type )
40 // to get the image index in MimeIconEngine.SmallIcons and MimeIconEngine.LargeIcons
41 // use
42 // public static Image GetIconForMimeTypeAndSize( string mime_type, Size size )
43 // to get the image itself for a mime type with a specific size
44
45 using System;
46 using System.Reflection;
47 using System.Drawing;
48 using System.Collections;
49 using System.Collections.Specialized;
50 using System.IO;
51 using System.Text;
52 using System.Runtime.InteropServices;
53 using System.Xml;
54
55 namespace System.Windows.Forms
56 {
57         internal enum MimeExtensionHandlerStatus
58         {
59                 OK,
60                 NO_KDEGLOBALS,
61                 NO_GNOMECONFIG,
62                 NO_ICONS,
63                 NO_MIMELNK
64         }
65         
66         internal enum EPlatformHandler
67         {
68                 Default,
69                 KDE,
70                 GNOME
71                 // Win, Mac OSX...
72         }
73
74         internal class ResourceImageLoader {
75                 static Assembly assembly = typeof (ResourceImageLoader).Assembly;
76                 
77                 static internal Bitmap Get (string name)
78                 {
79                         using (Stream stream = assembly.GetManifestResourceStream (name)){
80                                 if (stream == null){
81                                         Console.WriteLine ("Failed to read {0}", name);
82                                         return null;
83                                 }
84                                 
85                                 return new Bitmap (stream);
86                         }
87                 }
88         }
89         
90         internal class MimeIconEngine
91         {
92                 public static ImageList SmallIcons = new ImageList();
93                 public static ImageList LargeIcons = new ImageList();
94                 
95                 private static EPlatformHandler platform = EPlatformHandler.Default;
96                 
97                 private static IconIndexHash MimeTypeIconIndexHash = new IconIndexHash();
98                 
99                 struct IconPath { 
100                         public string Fullname; 
101                         public IconPath (string path)
102                         {
103                                 Fullname = path;
104                         }
105                 }
106
107                 struct SvgIconPath { 
108                         public string Fullname; 
109                         public SvgIconPath (string path)
110                         {
111                                 Fullname = path;
112                         }
113                 }
114
115                 private class IconIndexHash {
116
117                         Hashtable hash = new Hashtable ();
118
119                         private int LoadIcon (IconPath path)
120                         {
121                                 Bitmap bmp = new Bitmap (path.Fullname);
122                         
123                                 int index = SmallIcons.Images.Add (bmp, Color.Transparent);
124                                 LargeIcons.Images.Add (bmp, Color.Transparent);
125                                 return index;
126                         }
127
128                         private int LoadSvgIcon (SvgIconPath path)
129                         {
130                                 Image image = SVGUtil.GetSVGasImage (path.Fullname, 48, 48);
131                         
132                                 int index = SmallIcons.Images.Add (image, Color.Transparent);
133                                 LargeIcons.Images.Add (image, Color.Transparent);
134                                 return index;
135                         }
136
137                         private int LoadIcon (object path)
138                         {
139                                 if (path is SvgIconPath)
140                                         return LoadSvgIcon ((SvgIconPath) path);
141                                 else
142                                         return LoadIcon ((IconPath) path);
143                         }
144
145                         public object this [object key] {
146                                 get {
147                                         if (hash [key] == null)
148                                                 return null;
149                                         else if (hash [key] is int)
150                                                 return hash [key];
151
152                                         hash [key] = LoadIcon (hash [key]);
153                                         return hash [key];
154                                 }
155                         }
156
157                         public void Add (string name, object path)
158                         {
159                                 hash [name] = path;
160                         }
161
162                         public bool ContainsKey (string s)
163                         {
164                                 return hash.ContainsKey (s);
165                         }
166                 }
167
168                 private static NameValueCollection IconNameMimeTypeNameValueCollection = new NameValueCollection();
169                 
170                 private static StringCollection added_icons = new StringCollection();
171                 
172                 private static object lock_object = new Object();
173                 
174                 static MimeIconEngine( )
175                 {
176                         // add some more aliases, kde for example uses other mime type names for some mime types...
177                         Mime.Aliases.Add( "application/x-compressed-tar", "application/x-tgz" );
178                         Mime.Aliases.Add( "application/x-bzip-compressed-tar", "application/x-tbz" );
179                         Mime.Aliases.Add( "application/zip", "application/x-zip" );
180                         Mime.Aliases.Add( "text/x-patch", "text/x-diff" );
181                         
182                         SmallIcons.ColorDepth = ColorDepth.Depth32Bit;
183                         SmallIcons.TransparentColor = Color.Transparent;
184                         LargeIcons.ColorDepth = ColorDepth.Depth32Bit;
185                         LargeIcons.TransparentColor = Color.Transparent;
186                         
187                         string session =  Environment.GetEnvironmentVariable( "DESKTOP_SESSION" );
188                         
189                         if ( session != null )
190                         {
191                                 session = session.ToUpper( );
192                                 
193                                 if ( session == "DEFAULT" )
194                                 {
195                                         string helper = Environment.GetEnvironmentVariable( "KDE_FULL_SESSION" );
196                                         
197                                         if ( helper != null )
198                                                 session = "KDE";
199                                         else
200                                         {
201                                                 helper = Environment.GetEnvironmentVariable( "GNOME_DESKTOP_SESSION_ID" );
202                                                 
203                                                 if ( helper != null )
204                                                         session = "GNOME";
205                                         }
206                                 }
207                         }
208                         else
209                                 session = "";
210                         
211                         //Console.WriteLine( "Desktop session is: " + session ); 
212                         
213                         PlatformMimeIconHandler platformMimeHandler = null;
214                         
215                         if ( session == "KDE" )
216                         {
217                                 SmallIcons.ImageSize = new Size( 24, 24 );
218                                 LargeIcons.ImageSize = new Size( 48, 48 );
219                                 
220                                 platformMimeHandler = new KdeHandler( );
221                                 if ( platformMimeHandler.Start( ) == MimeExtensionHandlerStatus.OK )
222                                 {
223                                         platform = EPlatformHandler.KDE;
224                                 }
225                                 else // fallback to default
226                                 {
227                                         MimeIconEngine.LargeIcons.Images.Clear( );
228                                         MimeIconEngine.SmallIcons.Images.Clear( );
229                                         platformMimeHandler = new PlatformDefaultHandler( );
230                                         platformMimeHandler.Start( );
231                                 }
232                         }
233                         else
234                         if ( session == "GNOME" )
235                         {
236                                 SmallIcons.ImageSize = new Size( 24, 24 );
237                                 LargeIcons.ImageSize = new Size( 48, 48 );
238                                 
239                                 platformMimeHandler = new GnomeHandler( );
240                                 if ( platformMimeHandler.Start( ) == MimeExtensionHandlerStatus.OK )
241                                 {
242                                         platform = EPlatformHandler.GNOME;
243                                 }
244                                 else // fallback to default
245                                 {
246                                         MimeIconEngine.LargeIcons.Images.Clear( );
247                                         MimeIconEngine.SmallIcons.Images.Clear( );
248                                         platformMimeHandler = new PlatformDefaultHandler( );
249                                         platformMimeHandler.Start( );
250                                 }
251                         }
252                         else
253                         {
254                                 SmallIcons.ImageSize = new Size( 16, 16 );
255                                 LargeIcons.ImageSize = new Size( 48, 48 );
256                                 
257                                 platformMimeHandler = new PlatformDefaultHandler( );
258                                 platformMimeHandler.Start( );
259                         }
260                         
261                         IconNameMimeTypeNameValueCollection = null;
262                         added_icons = null;
263                 }
264                 
265                 public static int GetIconIndexForFile( string full_filename )
266                 {
267                         lock ( lock_object )
268                         {
269                                 string mime_type = Mime.GetMimeTypeForFile( full_filename );
270                                 
271                                 if ( platform == EPlatformHandler.Default )
272                                 {
273                                         if ( mime_type == "inode/directory" )
274                                         {
275                                                 return (int)MimeTypeIconIndexHash[ "inode/directory" ];
276                                         }
277                                         else
278                                         {
279                                                 return (int)MimeTypeIconIndexHash[ "unknown/unknown" ];
280                                         }
281                                 }
282                                 
283                                 object oindex = GetIconIndex( mime_type );
284                                 
285                                 if ( oindex == null )
286                                         oindex = MimeTypeIconIndexHash[ "unknown/unknown" ];
287                                 
288                                 return (int)oindex;
289                         }
290                 }
291                 
292                 public static int GetIconIndexForMimeType( string mime_type )
293                 {
294                         lock ( lock_object )
295                         {
296                                 if ( platform == EPlatformHandler.Default )
297                                 {
298                                         if (mime_type =="inode/directory")
299                                         {
300                                                 return (int)MimeTypeIconIndexHash[ "inode/directory" ];
301                                         }
302                                         else
303                                         {
304                                                 return (int)MimeTypeIconIndexHash[ "unknown/unknown" ];
305                                         }
306                                 }
307                                 
308                                 object oindex = GetIconIndex( mime_type );
309                                 
310                                 if ( oindex == null )
311                                         oindex = MimeTypeIconIndexHash[ "unknown/unknown" ];
312                                 
313                                 return (int)oindex;
314                         }
315                 }
316                 
317                 public static Image GetIconForMimeTypeAndSize( string mime_type, Size size )
318                 {
319                         lock ( lock_object )
320                         {
321                                 object oindex = GetIconIndex( mime_type );
322                                 
323                                 if ( oindex == null )
324                                         oindex = MimeTypeIconIndexHash[ "unknown/unknown" ];
325                                 
326                                 Bitmap bmp = new Bitmap( LargeIcons.Images[ (int)oindex ], size );
327                                 
328                                 return bmp;
329                         }
330                 }
331                 
332                 internal static void AddIcon( string name, string fullname )
333                 {
334                         if ( !CheckIfIconIsNeeded( name ) )
335                                 return;
336                         
337                         if ( added_icons.Contains( name ) )
338                                 return;
339                         
340                         added_icons.Add( name );
341                         
342                         AddMimeTypeIconIndexHash( name, new IconPath (fullname) );
343                 }
344                 
345                 internal static void AddSVGIcon( string name, string fullname )
346                 {
347                         if ( !CheckIfIconIsNeeded( name ) )
348                                 return;
349                         
350                         if ( added_icons.Contains( name ) )
351                                 return;
352                         
353                         added_icons.Add( name );
354                         
355                         AddMimeTypeIconIndexHash( name, new SvgIconPath (fullname) );
356                 }
357                 
358                 private static bool CheckIfIconIsNeeded( string name )
359                 {
360                         string mime_types = IconNameMimeTypeNameValueCollection[ name ];
361                         
362                         if ( mime_types != null )
363                                 return true;
364                         
365                         return false;
366                 }
367                 
368                 internal static void AddMimeTypeIconIndexHash( string name, object path_or_index )
369                 {
370                         string mime_type = IconNameMimeTypeNameValueCollection[ name ];
371                         
372                         if ( mime_type == null )
373                                 return;
374                         
375                         string[] split = mime_type.Split( new char[] { ',' } );
376                         
377                         for (int i = 0; i < split.Length; i++)
378                         {
379                                 if ( MimeTypeIconIndexHash.ContainsKey( split[i] ) )
380                                         continue;
381                                 
382                                 MimeTypeIconIndexHash.Add( split[i], path_or_index );
383                         }
384                 }
385                 
386                 internal static void AddIconByImage( string name, Image image )
387                 {
388                         int index = SmallIcons.Images.Add( image, Color.Transparent );
389                         LargeIcons.Images.Add( image, Color.Transparent );
390                         
391                         AddMimeTypeIconIndexHash( name, index );
392                 }
393                 
394                 internal static void AddMimeTypeAndIconName( string mimetype, string iconname )
395                 {
396                         if ( iconname.Equals( String.Empty ) )
397                                 return;
398                         
399                         IconNameMimeTypeNameValueCollection.Add( iconname, mimetype );
400                 }
401                 
402                 private static object GetIconIndex( string mime_type )
403                 {
404                         object oindex = null;
405                         
406                         if ( mime_type != null )
407                         {
408                                 // first check if mime_type is available in the mimetype/icon hashtable
409                                 oindex = MimeTypeIconIndexHash[ mime_type ];
410                                 
411                                 if ( oindex == null )
412                                 {
413                                         // it is not available, check if an alias exist for mime_type
414                                         string alias = Mime.GetMimeAlias( mime_type );
415                                         
416                                         if ( alias != null )
417                                         {
418                                                 string[] split = alias.Split( new char[] { ',' } );
419                                                 
420                                                 for (int i = 0; i < split.Length; i++)
421                                                 {
422                                                         oindex = MimeTypeIconIndexHash[ split[i] ];
423                                                         
424                                                         if ( oindex != null )
425                                                                 return oindex;
426                                                 }
427                                         }
428                                         
429                                         // if oindex is still null check if mime_type is a sub class of an other mime type
430                                         string sub_class = Mime.SubClasses[ mime_type ];
431                                         
432                                         if ( sub_class != null ) {
433                                                 oindex = MimeTypeIconIndexHash[ sub_class ];
434                                                 
435                                                 if ( oindex != null )
436                                                         return oindex;
437                                         }
438                                         
439                                         // last check, see if we find an entry for the main mime type class
440                                         string mime_class_main = mime_type.Substring( 0, mime_type.IndexOf( '/' ) );
441                                         return MimeTypeIconIndexHash[ mime_class_main ];
442                                 }
443                         }
444                         
445                         return oindex;
446                 }
447         }
448         
449         internal abstract class PlatformMimeIconHandler
450         {
451                 protected StringCollection mime_paths = new StringCollection();
452                 
453                 protected StringCollection icon_paths = new StringCollection();
454                 
455                 protected string icon_theme = "";
456                 
457                 protected MimeExtensionHandlerStatus mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.OK;
458                 
459                 public MimeExtensionHandlerStatus MimeExtensionHandlerStatus
460                 {
461                         get {
462                                 return mimeExtensionHandlerStatus;
463                         }
464                 }
465                 
466                 public abstract MimeExtensionHandlerStatus Start( );
467                 
468                 // check, if icon, mime, etc., directories exist
469                 protected virtual bool CheckPlatformDirectories( )
470                 {
471                         return true;
472                 }
473         }
474         
475         internal class PlatformDefaultHandler : PlatformMimeIconHandler
476         {
477                 
478                 public override MimeExtensionHandlerStatus Start( )
479                 {
480                         MimeIconEngine.AddMimeTypeAndIconName( "unknown/unknown", "paper" );
481                         MimeIconEngine.AddMimeTypeAndIconName( "inode/directory", "folder" );
482                         MimeIconEngine.AddMimeTypeAndIconName( "desktop/desktop", "desktop" );
483                         MimeIconEngine.AddMimeTypeAndIconName( "directory/home", "folder_with_paper" );
484                         MimeIconEngine.AddMimeTypeAndIconName( "network/network", "monitor-planet" );
485                         MimeIconEngine.AddMimeTypeAndIconName( "recently/recently", "last_open" );
486                         MimeIconEngine.AddMimeTypeAndIconName( "workplace/workplace", "monitor-computer" );
487                         
488                         MimeIconEngine.AddIconByImage( "folder",  ResourceImageLoader.Get ("folder.png") );
489                         MimeIconEngine.AddIconByImage( "paper",  ResourceImageLoader.Get("text-x-generic.png") );
490                         MimeIconEngine.AddIconByImage( "desktop",  ResourceImageLoader.Get( "user-desktop.png" ) );
491                         MimeIconEngine.AddIconByImage( "folder_with_paper",  ResourceImageLoader.Get( "document-open.png" ) );
492
493                         // fix
494                         MimeIconEngine.AddIconByImage( "monitor-planet",  ResourceImageLoader.Get( "document-open.png" ) );
495                         MimeIconEngine.AddIconByImage( "last_open",  ResourceImageLoader.Get( "document-open.png" ) );
496                         MimeIconEngine.AddIconByImage( "monitor-computer",  ResourceImageLoader.Get( "document-open.png" ) );
497                         
498                         return MimeExtensionHandlerStatus.OK; // return always ok
499                 }
500         }
501         
502         internal class KdeHandler : PlatformMimeIconHandler
503         {
504                 string full_kdegloabals_filename = Environment.GetFolderPath( Environment.SpecialFolder.Personal )
505                 + "/"
506                 + ".kde/share/config/kdeglobals";
507                 
508                 public override MimeExtensionHandlerStatus Start( )
509                 {
510                         if ( !ReadKdeglobals( ) )
511                                 return mimeExtensionHandlerStatus;
512                         
513                         if ( !CheckPlatformDirectories( ) )
514                                 return mimeExtensionHandlerStatus;
515                         
516                         // check if the theme is svg only
517                         // if true, use theme "default.kde"
518                         // don't know if that is available in every linux distribution
519                         if ( SVGOnly( ) )
520                                 icon_theme = "default.kde";
521                         else
522                         // check if there is a /48x48 directory
523                         if( No48x48( ) )
524                                 icon_theme = "default.kde";
525                         
526                         ReadMimetypes( );
527                         
528                         ReadIcons( );
529                         
530                         return mimeExtensionHandlerStatus;
531                 }
532                 
533                 private bool SVGOnly( )
534                 {
535                         // check only the first path in icon_paths
536                         if ( icon_paths.Count > 0 )
537                         {
538                                 string icon_path = icon_paths[ 0 ] + icon_theme;
539                                 string[] dirs = Directory.GetDirectories( icon_path );
540                                 
541                                 if ( dirs.Length == 1 && dirs[ 0 ] == "scalable" )
542                                         return true;
543                         }
544                         
545                         return false;
546                 }
547                 
548                 private bool No48x48( )
549                 {
550                         // check only the first path in icon_paths
551                         if ( icon_paths.Count > 0 )
552                         {
553                                 string icon_path = icon_paths[ 0 ] + icon_theme;
554                                 string[] dirs = Directory.GetDirectories( icon_path );
555                                 
556                                 for (int i = 0; i < dirs.Length; i++)
557                                 {
558                                         if ( dirs[i].EndsWith( "48x48" ) )
559                                                 return false;
560                                 }
561                         }
562                         
563                         return true;
564                 }
565                 
566                 protected override bool CheckPlatformDirectories( )
567                 {
568                         bool icons_found = false;
569                         
570                         // default icon dirs
571                         if ( Directory.Exists( "/opt/kde3/share/icons/default.kde" ) )
572                         {
573                                 icon_paths.Add( "/opt/kde3/share/icons" + "/" );
574                                 icons_found = true;
575                         }
576                         else
577                         if ( Directory.Exists( "/usr/share/icons/default.kde" ) )
578                         {
579                                 icon_paths.Add( "/usr/share/icons" + "/" );
580                                 icons_found = true;
581                         }
582                         else
583                         if ( Directory.Exists( "/usr/local/share/icons/default.kde" ) )
584                         {
585                                 icon_paths.Add( "/usr/local/share/icons"  + "/" );
586                                 icons_found = true;
587                         }
588                         else
589                         if ( !icons_found )
590                         {
591                                 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_ICONS;
592                                 return false;
593                         }
594                         
595                         bool mimelnk_found = false;
596                         
597                         if ( Directory.Exists( "/usr/share/mimelnk" ) )
598                         {
599                                 mime_paths.Add( "/usr/share/mimelnk" + "/" );
600                                 mimelnk_found = true;
601                         }
602                         
603                         if ( Directory.Exists( "/usr/local/share/mimelnk" ) )
604                         {
605                                 mime_paths.Add( "/usr/local/share/mimelnk" + "/" );
606                                 mimelnk_found = true;
607                         }
608                         
609                         if ( Directory.Exists( "/opt/kde3/share/mimelnk" ) )
610                         {
611                                 mime_paths.Add( "/opt/kde3/share/mimelnk" + "/" );
612                                 mimelnk_found = true;
613                         }
614                         
615                         if ( !mimelnk_found )
616                         {
617                                 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_MIMELNK;
618                                 return false;
619                         }
620                         
621                         return true;
622                 }
623                 
624                 private void ReadIcons( )
625                 {
626                         foreach ( string icon_path_in in icon_paths )
627                         {
628                                 string icon_path = icon_path_in + icon_theme + "/48x48";
629                                 
630                                 string[] directories = Directory.GetDirectories( icon_path );
631                                 
632                                 for (int i = 0; i < directories.Length; i++)
633                                 {
634                                         DirectoryInfo di = new DirectoryInfo( directories [i] );
635                                         
636                                         FileInfo[] fileinfo = di.GetFiles( );
637                                         
638                                         for (int z = 0; z < fileinfo.Length; z++)
639                                         {
640                                                 string name = Path.GetFileNameWithoutExtension( fileinfo [z].Name );
641                                                 
642                                                 MimeIconEngine.AddIcon( name, fileinfo [z].FullName );
643                                         }
644                                 }
645                         }
646                 }
647                 
648                 private void ReadMimetypes( )
649                 {
650                         MimeIconEngine.AddMimeTypeAndIconName( "unknown/unknown", "unknown" );
651                         MimeIconEngine.AddMimeTypeAndIconName( "desktop/desktop", "desktop" );
652                         MimeIconEngine.AddMimeTypeAndIconName( "directory/home", "folder_home" );
653                         MimeIconEngine.AddMimeTypeAndIconName( "network/network", "network" );
654                         MimeIconEngine.AddMimeTypeAndIconName( "recently/recently", "folder_man" );
655                         MimeIconEngine.AddMimeTypeAndIconName( "workplace/workplace", "system" );
656                         
657                         MimeIconEngine.AddMimeTypeAndIconName( "nfs/nfs", "nfs_mount" );
658                         MimeIconEngine.AddMimeTypeAndIconName( "smb/smb", "server" );
659                         
660                         MimeIconEngine.AddMimeTypeAndIconName( "harddisk/harddisk", "hdd_mount" );
661                         MimeIconEngine.AddMimeTypeAndIconName( "cdrom/cdrom", "cdrom_mount" );
662                         MimeIconEngine.AddMimeTypeAndIconName( "removable/removable", "usbpendrive_mount" );
663                         
664                         foreach ( string mime_path in mime_paths )
665                         {
666                                 string[] directories = Directory.GetDirectories( mime_path );
667                                 
668                                 for (int i = 0; i < directories.Length; i++)
669                                 {
670                                         string[] files = Directory.GetFiles( directories [i] );
671                                         
672                                         for (int z = 0; z < files.Length; z++)
673                                         {
674                                             try {
675                                                         ReadDotDesktop( files [z] );
676                                                 } catch {
677                                                 // Ignore errors if the file can not be read.
678                                             }
679                                         }
680                                 }
681                         }
682                 }
683                 
684                 private void ReadDotDesktop( string filename )
685                 {
686                         StreamReader sr = new StreamReader( filename );
687                         
688                         string line = sr.ReadLine( );
689                         
690                         string icon_name = "";
691                         
692                         string mime_type = "";
693                         
694                         bool have_icon = false;
695                         bool have_mimetype = false;
696                         
697                         while ( line != null )
698                         {
699                                 line = line.Trim( );
700                                 
701                                 if ( line.StartsWith( "Icon" ) )
702                                 {
703                                         icon_name = line.Substring( line.IndexOf( '=' ) + 1 );
704                                         icon_name = icon_name.Trim( );
705                                         if ( have_mimetype )
706                                                 break;
707                                         have_icon = true;
708                                 }
709                                 else
710                                 if ( line.StartsWith( "MimeType" ) )
711                                 {
712                                         mime_type = line.Substring( line.IndexOf( '=' ) + 1 );
713                                         mime_type = mime_type.Trim( );
714                                         if ( have_icon )
715                                                 break;
716                                         have_mimetype = true;
717                                 }
718                                 
719                                 line = sr.ReadLine( );
720                         }
721                         
722                         sr.Close( );
723                         
724                         MimeIconEngine.AddMimeTypeAndIconName( mime_type, icon_name );
725                 }
726                 
727                 private bool ReadKdeglobals( )
728                 {
729                         if ( !File.Exists( full_kdegloabals_filename ) )
730                         {
731                                 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_KDEGLOBALS;
732                                 
733                                 return false;
734                         }
735                         
736                         StreamReader sr = new StreamReader( full_kdegloabals_filename );
737                         
738                         string line = sr.ReadLine( );
739                         
740                         while ( line != null )
741                         {
742                                 if ( line.IndexOf( "[Icons]" ) != -1 )
743                                 {
744                                         line = sr.ReadLine( );
745                                         
746                                         if ( line != null && line.IndexOf( "Theme" ) != -1 )
747                                         {
748                                                 line = line.Trim( );
749                                                 
750                                                 icon_theme = line.Substring( line.IndexOf( '=' ) + 1 );
751                                                 
752                                                 icon_theme = icon_theme.Trim( );
753                                                 
754                                                 break;
755                                         }
756                                 }
757                                 
758                                 line = sr.ReadLine( );
759                         }
760                         
761                         sr.Close( );
762                         
763                         return true;
764                 }
765         }
766         
767         internal class GnomeHandler : PlatformMimeIconHandler
768         {
769                 string full_gnome_gconf_tree = Environment.GetFolderPath( Environment.SpecialFolder.Personal )
770                 + "/"
771                 + ".gconf/%gconf-tree.xml";
772                 
773                 bool is_svg_icon_theme = false;
774                 
775                 string main_icon_theme_path;
776                 
777                 StringCollection inherits_path_collection = new StringCollection ();
778                 
779                 public override MimeExtensionHandlerStatus Start( )
780                 {
781                         icon_theme = String.Empty;
782                         
783                         if (!File.Exists (full_gnome_gconf_tree))
784                                 full_gnome_gconf_tree = Environment.GetFolderPath( Environment.SpecialFolder.Personal )
785                                         + "/"
786                                         + ".gconf/desktop/gnome/interface/%gconf.xml";
787                         
788                         GetIconThemeFromGConf ();
789                         
790                         if (!GetIconPaths ())
791                                 return MimeExtensionHandlerStatus.NO_ICONS;
792                         
793                         if (!GetMainIconThemePath ())
794                                 return MimeExtensionHandlerStatus.NO_ICONS;
795
796                         try {
797                                 GetIconThemeInherits ();
798                         
799                                 CreateUIIcons ();
800                         
801                                 CreateMimeTypeIcons( );
802                         } catch (Exception e) {
803                                 Console.Error.WriteLine ("Unable to start GNOME mime engine:");
804                                 Console.Error.WriteLine (e);
805                                 return MimeExtensionHandlerStatus.NO_GNOMECONFIG;
806                         }
807                         
808                         inherits_path_collection = null;
809                         icon_paths = null;
810                         
811                         return MimeExtensionHandlerStatus.OK;
812                 }
813                 
814                 private bool GetIconThemeFromGConf ()
815                 {
816                         if (!File.Exists (full_gnome_gconf_tree))
817                                 return false;
818                         
819                         try {
820                                 bool found_icon_theme_in_xml = false;
821                                 
822                                 XmlTextReader xtr = new XmlTextReader (full_gnome_gconf_tree);
823                                 
824                                 while (xtr.Read ()) {
825                                         if (xtr.NodeType == XmlNodeType.Element && xtr.Name.ToUpper () == "ENTRY" && xtr.GetAttribute ("name") == "icon_theme") {
826                                                 found_icon_theme_in_xml = true;
827                                         } else
828                                         if (xtr.NodeType == XmlNodeType.Element && xtr.Name.ToUpper () == "STRINGVALUE" && found_icon_theme_in_xml) {
829                                                 xtr.Read ();
830                                                 icon_theme = xtr.Value;
831                                                 break;
832                                         }
833                                 }
834                                 xtr.Close ();
835                                 
836                                 if (icon_theme != String.Empty)
837                                         return true;
838                                 else {
839                                         icon_theme = "gnome";
840                                         return false;
841                                 }
842                         } catch (Exception) {
843                                 return false;
844                         }
845                 }
846                 
847                 private bool GetIconPaths () 
848                 {
849                         string global_icon_path = "";
850                         
851                         if (Directory.Exists ("/opt/gnome/share/icons"))
852                                 global_icon_path = "/opt/gnome/share/icons";
853                         else
854                         if (Directory.Exists ("/usr/share/icons"))
855                                 global_icon_path = "/usr/share/icons";
856                         else
857                         if (Directory.Exists ("/usr/local/share/icons"))
858                                 global_icon_path = "/usr/local/share/icons";
859                         
860                         if (global_icon_path.Length > 0)
861                                 icon_paths.Add (global_icon_path);
862                         
863                         if (Directory.Exists (Environment.GetFolderPath (Environment.SpecialFolder.Personal) + "/.icons"))
864                                 icon_paths.Add (Environment.GetFolderPath (Environment.SpecialFolder.Personal) + "/.icons");
865                         
866                         if (icon_paths.Count == 0)
867                                 return false;
868                         
869                         return true;
870                 }
871                 
872                 private bool GetMainIconThemePath ()
873                 {
874                         foreach (string path in icon_paths) {
875                                 if (Directory.Exists (path + "/" + icon_theme)) {
876                                         main_icon_theme_path = path + "/" + icon_theme;
877                                         return true;
878                                 }
879                         }
880                         
881                         return false;
882                 }
883                 
884                 private void GetIconThemeInherits ()
885                 {
886                         inherits_path_collection.Add (main_icon_theme_path);
887                         GetIndexThemeInherits (main_icon_theme_path + "/" + "index.theme");
888                 }
889                 
890                 private void GetIndexThemeInherits (string filename)
891                 {
892                         StringCollection tmp_inherits = new StringCollection ();
893                         
894                         try {
895                                 StreamReader sr = new StreamReader (filename);
896                                 
897                                 string line = sr.ReadLine ();
898                                 
899                                 while (line != null) {
900                                         if (line.IndexOf ("Inherits=") != -1) {
901                                                 line = line.Trim ();
902                                                 line = line.Replace ("Inherits=", "");
903                                                 
904                                                 line = line.Trim ();
905                                                 
906                                                 string[] split = line.Split (new char [] { ',' });
907                                                 
908                                                 tmp_inherits.AddRange (split);
909                                                 break;
910                                         }
911                                         line = sr.ReadLine ();
912                                 }
913                                 
914                                 sr.Close ();
915                         } catch (Exception) {
916                                 
917                         }
918                         
919                         if (tmp_inherits.Count > 0) {
920                                 foreach (string icon_theme in tmp_inherits) {
921                                         foreach (string path in icon_paths) {
922                                                 if (Directory.Exists (path + "/" + icon_theme)) {
923                                                         if (!inherits_path_collection.Contains (path + "/" + icon_theme)) {
924                                                                 inherits_path_collection.Add (path + "/" + icon_theme);
925                                                                 
926                                                                 if (File.Exists (path + "/" + icon_theme + "/" + "index.theme"))
927                                                                         GetIndexThemeInherits (path + "/" + icon_theme + "/" + "index.theme");
928                                                         }
929                                                         break;
930                                                 }
931                                         }
932                                 }
933                         }
934                 }
935                 
936                 private void CreateUIIcons ()
937                 {
938                         string resolv_path = ResolvePath (main_icon_theme_path);
939                         string default_gnome_path = "";
940                         
941                         // get the default gnome icon theme path
942                         foreach (string path in icon_paths)
943                                 if (Directory.Exists (path + "/gnome")) {
944                                         default_gnome_path = path + "/gnome/48x48/";
945                                         break;
946                                 }
947
948                         // use default gnome icon theme if there isn't a "/48x48" or "/scalable" dir
949                         // for the current theme                        
950                         if (resolv_path == String.Empty)
951                                 resolv_path = default_gnome_path;
952                         
953                         Hashtable name_mime_hash = new Hashtable ();
954                         
955                         name_mime_hash ["gnome-fs-directory"] = "inode/directory";
956                         name_mime_hash ["gnome-fs-regular"] = "unknown/unknown";
957                         name_mime_hash ["gnome-fs-desktop"] = "desktop/desktop";
958                         name_mime_hash ["gnome-fs-home"] = "directory/home";
959                         name_mime_hash ["gnome-fs-network"] = "network/network";
960                         name_mime_hash ["gnome-fs-directory-accept"] = "recently/recently";
961                         name_mime_hash ["gnome-fs-client"] = "workplace/workplace";
962                         
963                         name_mime_hash ["gnome-fs-nfs"] = "nfs/nfs";
964                         name_mime_hash ["gnome-fs-smb"] = "smb/smb";
965                         
966                         name_mime_hash ["gnome-dev-cdrom"] = "cdrom/cdrom";
967                         name_mime_hash ["gnome-dev-harddisk"] = "harddisk/harddisk";
968                         name_mime_hash ["gnome-dev-removable"] = "removable/removable";
969                         
970                         int initial_name_mime_hash_count = name_mime_hash.Count;
971                         
972                         // first check the current icon theme path
973                         string[] dirs = Directory.GetDirectories (resolv_path);
974                         ArrayList objects = CheckAndAddUIIcons (dirs, name_mime_hash);
975                         
976                         if (objects.Count != name_mime_hash.Count) {
977                                 // remove found icons
978                                 foreach (object o in objects) {
979                                         name_mime_hash.Remove (o);
980                                 }
981                                 
982                                 // check the default gnome path
983                                 dirs = Directory.GetDirectories (default_gnome_path);
984                                 objects = CheckAndAddUIIcons (dirs, name_mime_hash);
985                                 
986                                 //could be a kde icon theme, so we check kde icon names too
987                                 if (objects.Count == initial_name_mime_hash_count) {
988                                         dirs = Directory.GetDirectories (resolv_path);
989                                         
990                                         name_mime_hash.Clear ();
991                                         name_mime_hash ["folder"] = "inode/directory";
992                                         name_mime_hash ["unknown"] = "unknown/unknown";
993                                         name_mime_hash ["desktop"] = "desktop/desktop";
994                                         name_mime_hash ["folder_home"] = "directory/home";
995                                         name_mime_hash ["network"] = "network/network";
996                                         name_mime_hash ["folder_man"] = "recently/recently";
997                                         name_mime_hash ["system"] = "workplace/workplace";
998                                         
999                                         name_mime_hash ["nfs_mount"] = "nfs/nfs";
1000                                         name_mime_hash ["server"] = "smb/smb";
1001                                         
1002                                         name_mime_hash ["cdrom_mount"] = "cdrom/cdrom";
1003                                         name_mime_hash ["hdd_mount"] = "harddisk/harddisk";
1004                                         name_mime_hash ["usbpendrive_mount"] = "removable/removable";
1005                                         
1006                                         CheckAndAddUIIcons (dirs, name_mime_hash);
1007                                 }
1008                         }
1009                 }
1010                 
1011                 private ArrayList CheckAndAddUIIcons (string[] dirs, Hashtable name_mime_hash)
1012                 {
1013                         ArrayList al = new ArrayList (name_mime_hash.Count);
1014                         
1015                         string extension = is_svg_icon_theme ? "svg" : "png";
1016                         
1017                         for (int i = 0; i < dirs.Length; i++) {
1018                                 foreach (DictionaryEntry entry in name_mime_hash) {
1019                                         string key = (string)entry.Key;
1020                                         if (File.Exists (dirs [i] + "/" + key + "." + extension)) {
1021                                                 string value = (string)entry.Value;
1022                                                 
1023                                                 MimeIconEngine.AddMimeTypeAndIconName (value, key);
1024                                                 
1025                                                 if (!is_svg_icon_theme)
1026                                                         MimeIconEngine.AddIcon (key, dirs [i] + "/" + key + "." + extension);
1027                                                 else
1028                                                         MimeIconEngine.AddSVGIcon (key, dirs [i] + "/" + key + "." + extension);
1029                                                 
1030                                                 al.Add (entry.Key);
1031                                         }
1032                                 }
1033                         }
1034                         
1035                         return al;
1036                 }
1037                 
1038                 private void CreateMimeTypeIcons ()
1039                 {
1040                         foreach (string ip in inherits_path_collection) {
1041                                 string path_to_use = ResolvePath (ip);
1042                                 
1043                                 if (path_to_use == String.Empty)
1044                                         continue;
1045                                 
1046                                 if (!Directory.Exists (path_to_use + "mimetypes"))
1047                                     continue;
1048                                 
1049                                 string[] files = Directory.GetFiles (path_to_use + "mimetypes");
1050                                 
1051                                 for (int z = 0; z < files.Length; z++) {
1052                                         string extension = Path.GetExtension (files [z]);
1053                                         
1054                                         if (!is_svg_icon_theme) {
1055                                                 if (extension != ".png")
1056                                                         continue;
1057                                         } else
1058                                         if (extension != ".svg")
1059                                                 continue;
1060                                         
1061                                         string file_name = Path.GetFileNameWithoutExtension (files [z]);
1062                                         
1063                                         if (!file_name.StartsWith ("gnome-mime-"))
1064                                                 continue;
1065                                         
1066                                         StringBuilder mime_type = new StringBuilder (file_name.Replace ("gnome-mime-", ""));
1067                                         
1068                                         for (int i = 0; i < mime_type.Length; i++)
1069                                                 if (mime_type [i] == '-') {
1070                                                         mime_type [i] = '/';
1071                                                         break;
1072                                                 }
1073                                         
1074                                         MimeIconEngine.AddMimeTypeAndIconName (mime_type.ToString (), file_name);
1075                                         
1076                                         if (!is_svg_icon_theme)
1077                                                 MimeIconEngine.AddIcon (file_name, files [z]);
1078                                         else
1079                                                 MimeIconEngine.AddSVGIcon (file_name, files [z]);
1080                                 }
1081                         }
1082                 }
1083                 
1084                 private string ResolvePath (string path)
1085                 {
1086                         if (Directory.Exists (path + "/48x48")) {
1087                                 is_svg_icon_theme = false;
1088                                 return path + "/48x48/";
1089                         }
1090                         
1091                         if (Directory.Exists (path + "/scalable")) {
1092                                 is_svg_icon_theme = true;
1093                                 return path + "/scalable/";
1094                         }
1095                         
1096                         return String.Empty;
1097                 }
1098         }
1099         
1100         internal class SVGUtil {
1101                 [DllImport("librsvg-2.so")]
1102                 static extern IntPtr rsvg_pixbuf_from_file_at_size (string file_name, int  width, int  height, out IntPtr error);
1103                 
1104                 [DllImport("libgdk-x11-2.0.so")]
1105                 static extern bool gdk_pixbuf_save_to_buffer (IntPtr pixbuf, out IntPtr buffer, out UIntPtr buffer_size, string type, out IntPtr error, IntPtr option_dummy);
1106                 
1107                 [DllImport("libglib-2.0.so")]
1108                 static extern void g_free (IntPtr mem);
1109                 
1110                 [DllImport("libgdk-x11-2.0.so")]
1111                 static extern bool gdk_init_check(out int argc, string argv);
1112                 
1113                 [DllImport("libgobject-2.0.so")]
1114                 static extern void g_object_unref (IntPtr nativeObject);
1115                 
1116                 static bool inited = false;
1117                 
1118                 static void Init () {
1119                         int argc = 0;
1120                         string argv = "";
1121                         
1122                         gdk_init_check (out argc, argv);
1123                         
1124                         inited = true;
1125                 }
1126                 
1127                 public static Image GetSVGasImage (string filename, int width, int height) {
1128                         if (!inited)
1129                                 Init ();
1130                         
1131                         if (!File.Exists (filename))
1132                                 return null;
1133                         IntPtr error = IntPtr.Zero;
1134                         IntPtr pixbuf = rsvg_pixbuf_from_file_at_size (filename, width, height, out error);
1135                         
1136                         if (error != IntPtr.Zero)
1137                                 return null;
1138                         
1139                         error = IntPtr.Zero;
1140                         IntPtr buffer;
1141                         UIntPtr buffer_size_as_ptr;
1142                         string type = "png";
1143                         
1144                         bool saved = gdk_pixbuf_save_to_buffer (pixbuf, out buffer, out buffer_size_as_ptr, type, out error, IntPtr.Zero);
1145                         
1146                         if (!saved)
1147                                 return null;
1148                         
1149                         int buffer_size = (int) (uint) buffer_size_as_ptr;
1150                         byte[] result = new byte [buffer_size];
1151                         Marshal.Copy (buffer, result, 0, (int) buffer_size);
1152                         g_free (buffer);
1153                         g_object_unref (pixbuf);
1154                         
1155                         Image image = null;
1156                         using (MemoryStream s = new MemoryStream (result))
1157                                 image = Image.FromStream (s);
1158                         
1159                         return image;
1160                 }
1161         }
1162 }
1163