* MimeIcon.cs: Added internal class SVGUtil.
[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.Drawing;
47 using System.Collections;
48 using System.Collections.Specialized;
49 using System.IO;
50 using System.Text;
51 using System.Runtime.InteropServices;
52
53 namespace System.Windows.Forms
54 {
55         internal enum MimeExtensionHandlerStatus
56         {
57                 OK,
58                 NO_KDEGLOBALS,
59                 NO_GNOMECONFIG,
60                 NO_ICONS,
61                 NO_MIMELNK
62         }
63         
64         internal enum EPlatformHandler
65         {
66                 Default,
67                 KDE,
68                 GNOME
69                 // Win, Mac OSX...
70         }
71         
72         internal class MimeIconEngine
73         {
74                 public static ImageList SmallIcons = new ImageList();
75                 public static ImageList LargeIcons = new ImageList();
76                 
77                 private static PlatformMimeIconHandler platformMimeHandler = null;
78                 
79                 private static EPlatformHandler platform = EPlatformHandler.Default;
80                 
81                 private static Hashtable MimeTypeIconIndexHash = new Hashtable();
82                 
83                 private static NameValueCollection IconNameMimeTypeNameValueCollection = new NameValueCollection();
84                 
85                 private static StringCollection added_icons = new StringCollection();
86                 
87                 private static object lock_object = new Object();
88                 
89                 static MimeIconEngine( )
90                 {
91                         // add some more aliases, kde for example uses other mime type names for some mime types...
92                         MimeGenerated.Aliases.Add( "application/x-compressed-tar", "application/x-tgz" );
93                         MimeGenerated.Aliases.Add( "application/x-bzip-compressed-tar", "application/x-tbz" );
94                         MimeGenerated.Aliases.Add( "application/zip", "application/x-zip" );
95                         MimeGenerated.Aliases.Add( "text/x-patch", "text/x-diff" );
96                         
97                         SmallIcons.ColorDepth = ColorDepth.Depth32Bit;
98                         SmallIcons.TransparentColor = Color.Transparent;
99                         LargeIcons.ColorDepth = ColorDepth.Depth32Bit;
100                         LargeIcons.TransparentColor = Color.Transparent;
101                         
102                         string session =  Environment.GetEnvironmentVariable( "DESKTOP_SESSION" );
103                         
104                         if ( session != null )
105                         {
106                                 session = session.ToUpper( );
107                                 
108                                 if ( session == "DEFAULT" )
109                                 {
110                                         string helper = Environment.GetEnvironmentVariable( "KDE_FULL_SESSION" );
111                                         
112                                         if ( helper != null )
113                                                 session = "KDE";
114                                         else
115                                         {
116                                                 helper = Environment.GetEnvironmentVariable( "GNOME_DESKTOP_SESSION_ID" );
117                                                 
118                                                 if ( helper != null )
119                                                         session = "GNOME";
120                                         }
121                                 }
122                         }
123                         else
124                                 session = "";
125                         
126                         //Console.WriteLine( "Desktop session is: " + session ); 
127                         
128                         if ( session == "KDE" )
129                         {
130                                 SmallIcons.ImageSize = new Size( 24, 24 );
131                                 LargeIcons.ImageSize = new Size( 48, 48 );
132                                 
133                                 platformMimeHandler = new KdeHandler( );
134                                 if ( platformMimeHandler.Start( ) == MimeExtensionHandlerStatus.OK )
135                                 {
136                                         Console.WriteLine( "Kde icons ready..." );
137                                         platform = EPlatformHandler.KDE;
138                                 }
139                                 else // fallback to default
140                                 {
141                                         MimeIconEngine.LargeIcons.Images.Clear( );
142                                         MimeIconEngine.SmallIcons.Images.Clear( );
143                                         platformMimeHandler = new PlatformDefaultHandler( );
144                                         platformMimeHandler.Start( );
145                                 }
146                         }
147                         else
148                         if ( session == "GNOME" )
149                         {
150                                 SmallIcons.ImageSize = new Size( 24, 24 );
151                                 LargeIcons.ImageSize = new Size( 48, 48 );
152                                 
153                                 platformMimeHandler = new GnomeHandler( );
154                                 if ( platformMimeHandler.Start( ) == MimeExtensionHandlerStatus.OK )
155                                 {
156                                         Console.WriteLine( "Gnome icons ready..." );
157                                         platform = EPlatformHandler.GNOME;
158                                 }
159                                 else // fallback to default
160                                 {
161                                         MimeIconEngine.LargeIcons.Images.Clear( );
162                                         MimeIconEngine.SmallIcons.Images.Clear( );
163                                         platformMimeHandler = new PlatformDefaultHandler( );
164                                         platformMimeHandler.Start( );
165                                 }
166                         }
167                         else
168                         {
169                                 SmallIcons.ImageSize = new Size( 16, 16 );
170                                 LargeIcons.ImageSize = new Size( 48, 48 );
171                                 
172                                 platformMimeHandler = new PlatformDefaultHandler( );
173                                 platformMimeHandler.Start( );
174                         }
175                         
176                         IconNameMimeTypeNameValueCollection = null;
177                         added_icons = null;
178                 }
179                 
180                 public static int GetIconIndexForFile( string full_filename )
181                 {
182                         lock ( lock_object )
183                         {
184                                 string mime_type = Mime.GetMimeTypeForFile( full_filename );
185                                 
186                                 if ( platform == EPlatformHandler.Default )
187                                 {
188                                         if ( mime_type == "inode/directory" )
189                                         {
190                                                 return (int)MimeTypeIconIndexHash[ "inode/directory" ];
191                                         }
192                                         else
193                                         {
194                                                 return (int)MimeTypeIconIndexHash[ "unknown/unknown" ];
195                                         }
196                                 }
197                                 
198                                 object oindex = GetIconIndex( mime_type );
199                                 
200                                 if ( oindex == null )
201                                         oindex = MimeTypeIconIndexHash[ "unknown/unknown" ];
202                                 
203                                 return (int)oindex;
204                         }
205                 }
206                 
207                 public static int GetIconIndexForMimeType( string mime_type )
208                 {
209                         lock ( lock_object )
210                         {
211                                 if ( platform == EPlatformHandler.Default )
212                                 {
213                                         if ( mime_type == "inode/directory" )
214                                         {
215                                                 return (int)MimeTypeIconIndexHash[ "inode/directory" ];
216                                         }
217                                         else
218                                         {
219                                                 return (int)MimeTypeIconIndexHash[ "unknown/unknown" ];
220                                         }
221                                 }
222                                 
223                                 object oindex = GetIconIndex( mime_type );
224                                 
225                                 if ( oindex == null )
226                                         oindex = MimeTypeIconIndexHash[ "unknown/unknown" ];
227                                 
228                                 return (int)oindex;
229                         }
230                 }
231                 
232                 public static Image GetIconForMimeTypeAndSize( string mime_type, Size size )
233                 {
234                         lock ( lock_object )
235                         {
236                                 object oindex = GetIconIndex( mime_type );
237                                 
238                                 if ( oindex == null )
239                                         oindex = MimeTypeIconIndexHash[ "unknown/unknown" ];
240                                 
241                                 Bitmap bmp = new Bitmap( LargeIcons.Images[ (int)oindex ], size );
242                                 
243                                 return bmp;
244                         }
245                 }
246                 
247                 internal static void AddIcon( string name, string fullname )
248                 {
249                         if ( !CheckIfIconIsNeeded( name ) )
250                                 return;
251                         
252                         if ( added_icons.Contains( name ) )
253                                 return;
254                         
255                         added_icons.Add( name );
256                         
257                         Bitmap bmp = new Bitmap( fullname );
258                         
259                         int index = SmallIcons.Images.Add( bmp, Color.Transparent );
260                         LargeIcons.Images.Add( bmp, Color.Transparent );
261                         
262                         AddMimeTypeIconIndexHash( name, index );
263                 }
264                 
265                 internal static void AddSVGIcon( string name, string fullname )
266                 {
267                         if ( !CheckIfIconIsNeeded( name ) )
268                                 return;
269                         
270                         if ( added_icons.Contains( name ) )
271                                 return;
272                         
273                         added_icons.Add( name );
274                         
275                         Image image = SVGUtil.GetSVGasImage (fullname, 24, 24);
276                         
277                         int index = SmallIcons.Images.Add( image, Color.Transparent );
278                         image = SVGUtil.GetSVGasImage (fullname, 48, 48);
279                         LargeIcons.Images.Add( image, Color.Transparent );
280                         
281                         AddMimeTypeIconIndexHash( name, index );
282                 }
283                 
284                 private static bool CheckIfIconIsNeeded( string name )
285                 {
286                         string mime_types = IconNameMimeTypeNameValueCollection[ name ];
287                         
288                         if ( mime_types != null )
289                                 return true;
290                         
291                         return false;
292                 }
293                 
294                 internal static void AddMimeTypeIconIndexHash( string name, int index )
295                 {
296                         string mime_type = IconNameMimeTypeNameValueCollection[ name ];
297                         
298                         if ( mime_type == null )
299                                 return;
300                         
301                         string[] split = mime_type.Split( new char[] { ',' } );
302                         
303                         foreach ( string s in split )
304                         {
305                                 if ( MimeTypeIconIndexHash.ContainsKey( s ) )
306                                         continue;
307                                 
308                                 MimeTypeIconIndexHash.Add( s, index );
309                         }
310                 }
311                 
312                 internal static void AddIconByImage( string name, Image image )
313                 {
314                         int index = SmallIcons.Images.Add( image, Color.Transparent );
315                         LargeIcons.Images.Add( image, Color.Transparent );
316                         
317                         AddMimeTypeIconIndexHash( name, index );
318                 }
319                 
320                 internal static void AddMimeTypeAndIconName( string mimetype, string iconname )
321                 {
322                         if ( iconname.Equals( String.Empty ) )
323                                 return;
324                         
325                         IconNameMimeTypeNameValueCollection.Add( iconname, mimetype );
326                 }
327                 
328                 private static object GetIconIndex( string mime_type )
329                 {
330                         object oindex = null;
331                         
332                         if ( mime_type != null )
333                         {
334                                 // first check if mime_type is available in the mimetype/icon hashtable
335                                 oindex = MimeTypeIconIndexHash[ mime_type ];
336                                 
337                                 if ( oindex == null )
338                                 {
339                                         // it is not available, check if an alias exist for mime_type
340                                         string alias = Mime.GetMimeAlias( mime_type );
341                                         
342                                         if ( alias != null )
343                                         {
344                                                 string[] split = alias.Split( new char[] { ',' } );
345                                                 
346                                                 foreach ( string s in split )
347                                                 {
348                                                         oindex = MimeTypeIconIndexHash[ s ];
349                                                         
350                                                         if ( oindex != null )
351                                                                 return oindex;
352                                                 }
353                                         }
354                                         
355                                         // if oindex is still null check if mime_type is a sub class of an other mime type
356                                         string sub_class = MimeGenerated.SubClasses[ mime_type ];
357                                         
358                                         if ( sub_class != null )
359                                                 return MimeTypeIconIndexHash[ sub_class ];
360                                         
361                                         // last check, see if we find an entry for the main mime type class
362                                         string mime_class_main = mime_type.Substring( 0, mime_type.IndexOf( '/' ) );
363                                         return MimeTypeIconIndexHash[ mime_class_main ];
364                                 }
365                         }
366                         
367                         return oindex;
368                 }
369         }
370         
371         internal abstract class PlatformMimeIconHandler
372         {
373                 protected StringCollection mime_paths = new StringCollection();
374                 
375                 protected StringCollection icon_paths = new StringCollection();
376                 
377                 protected string icon_theme = "";
378                 
379                 protected MimeExtensionHandlerStatus mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.OK;
380                 
381                 public MimeExtensionHandlerStatus MimeExtensionHandlerStatus
382                 {
383                         get {
384                                 return mimeExtensionHandlerStatus;
385                         }
386                 }
387                 
388                 public abstract MimeExtensionHandlerStatus Start( );
389                 
390                 // check, if icon, mime, etc., directories exist
391                 protected virtual bool CheckPlatformDirectories( )
392                 {
393                         return true;
394                 }
395         }
396         
397         internal class PlatformDefaultHandler : PlatformMimeIconHandler
398         {
399                 public override MimeExtensionHandlerStatus Start( )
400                 {
401                         MimeIconEngine.AddMimeTypeAndIconName( "unknown/unknown", "paper" );
402                         MimeIconEngine.AddMimeTypeAndIconName( "inode/directory", "folder" );
403                         MimeIconEngine.AddMimeTypeAndIconName( "desktop/desktop", "desktop" );
404                         MimeIconEngine.AddMimeTypeAndIconName( "directory/home", "folder_with_paper" );
405                         MimeIconEngine.AddMimeTypeAndIconName( "network/network", "monitor-planet" );
406                         MimeIconEngine.AddMimeTypeAndIconName( "recently/recently", "last_open" );
407                         MimeIconEngine.AddMimeTypeAndIconName( "workplace/workplace", "monitor-computer" );
408                         
409                         MimeIconEngine.AddIconByImage( "folder",  (Image)Locale.GetResource( "folder" ) );
410                         MimeIconEngine.AddIconByImage( "paper",  (Image)Locale.GetResource( "paper" ) );
411                         MimeIconEngine.AddIconByImage( "desktop",  (Image)Locale.GetResource( "desktop" ) );
412                         MimeIconEngine.AddIconByImage( "folder_with_paper",  (Image)Locale.GetResource( "folder_with_paper" ) );
413                         MimeIconEngine.AddIconByImage( "monitor-planet",  (Image)Locale.GetResource( "monitor-planet" ) );
414                         MimeIconEngine.AddIconByImage( "last_open",  (Image)Locale.GetResource( "last_open" ) );
415                         MimeIconEngine.AddIconByImage( "monitor-computer",  (Image)Locale.GetResource( "monitor-computer" ) );
416                         
417                         return MimeExtensionHandlerStatus.OK; // return always ok
418                 }
419         }
420         
421         internal class KdeHandler : PlatformMimeIconHandler
422         {
423                 string full_kdegloabals_filename = Environment.GetFolderPath( Environment.SpecialFolder.Personal )
424                 + "/"
425                 + ".kde/share/config/kdeglobals";
426                 
427                 public override MimeExtensionHandlerStatus Start( )
428                 {
429                         if ( !ReadKdeglobals( ) )
430                                 return mimeExtensionHandlerStatus;
431                         
432                         if ( !CheckPlatformDirectories( ) )
433                                 return mimeExtensionHandlerStatus;
434                         
435                         // check if the theme is svg only
436                         // if true, use theme "default.kde"
437                         // don't know if that is available in every linux distribution
438                         // MWF has no svg support yet (cairo's libsvg!?!)
439                         if ( SVGOnly( ) )
440                                 icon_theme = "default.kde";
441                         else
442                         // check if there is a /48x48 directory
443                         if( No48x48( ) )
444                                 icon_theme = "default.kde";
445                         
446                         ReadMimetypes( );
447                         
448                         ReadIcons( );
449                         
450                         return mimeExtensionHandlerStatus;
451                 }
452                 
453                 private bool SVGOnly( )
454                 {
455                         // check only the first path in icon_paths
456                         if ( icon_paths.Count > 0 )
457                         {
458                                 string icon_path = icon_paths[ 0 ] + icon_theme;
459                                 string[] dirs = Directory.GetDirectories( icon_path );
460                                 
461                                 if ( dirs.Length == 1 && dirs[ 0 ] == "scalable" )
462                                         return true;
463                         }
464                         
465                         return false;
466                 }
467                 
468                 private bool No48x48( )
469                 {
470                         // check only the first path in icon_paths
471                         if ( icon_paths.Count > 0 )
472                         {
473                                 string icon_path = icon_paths[ 0 ] + icon_theme;
474                                 string[] dirs = Directory.GetDirectories( icon_path );
475                                 
476                                 foreach( string path in dirs )
477                                 {
478                                         if ( path.EndsWith( "48x48" ) )
479                                                 return false;
480                                 }
481                         }
482                         
483                         return true;
484                 }
485                 
486                 protected override bool CheckPlatformDirectories( )
487                 {
488                         bool icons_found = false;
489                         
490                         // default icon dirs
491                         if ( Directory.Exists( "/opt/kde3/share/icons/default.kde" ) )
492                         {
493                                 icon_paths.Add( "/opt/kde3/share/icons" + "/" );
494                                 icons_found = true;
495                         }
496                         else
497                         if ( Directory.Exists( "/usr/share/icons/default.kde" ) )
498                         {
499                                 icon_paths.Add( "/usr/share/icons" + "/" );
500                                 icons_found = true;
501                         }
502                         else
503                         if ( Directory.Exists( "/usr/local/share/icons/default.kde" ) )
504                         {
505                                 icon_paths.Add( "/usr/local/share/icons"  + "/" );
506                                 icons_found = true;
507                         }
508                         else
509                         if ( !icons_found )
510                         {
511                                 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_ICONS;
512                                 return false;
513                         }
514                         
515                         bool mimelnk_found = false;
516                         
517                         if ( Directory.Exists( "/usr/share/mimelnk" ) )
518                         {
519                                 mime_paths.Add( "/usr/share/mimelnk" + "/" );
520                                 mimelnk_found = true;
521                         }
522                         
523                         if ( Directory.Exists( "/usr/local/share/mimelnk" ) )
524                         {
525                                 mime_paths.Add( "/usr/local/share/mimelnk" + "/" );
526                                 mimelnk_found = true;
527                         }
528                         
529                         if ( Directory.Exists( "/opt/kde3/share/mimelnk" ) )
530                         {
531                                 mime_paths.Add( "/opt/kde3/share/mimelnk" + "/" );
532                                 mimelnk_found = true;
533                         }
534                         
535                         if ( !mimelnk_found )
536                         {
537                                 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_MIMELNK;
538                                 return false;
539                         }
540                         
541                         return true;
542                 }
543                 
544                 private void ReadIcons( )
545                 {
546                         foreach ( string icon_path_in in icon_paths )
547                         {
548                                 string icon_path = icon_path_in + icon_theme + "/48x48";
549                                 
550                                 string[] directories = Directory.GetDirectories( icon_path );
551                                 
552                                 foreach ( string d in directories )
553                                 {
554                                         DirectoryInfo di = new DirectoryInfo( d );
555                                         
556                                         FileInfo[] fileinfo = di.GetFiles( );
557                                         
558                                         foreach ( FileInfo fi in fileinfo )
559                                         {
560                                                 string name = Path.GetFileNameWithoutExtension( fi.Name );
561                                                 
562                                                 MimeIconEngine.AddIcon( name, fi.FullName );
563                                         }
564                                 }
565                         }
566                 }
567                 
568                 private void ReadMimetypes( )
569                 {
570                         MimeIconEngine.AddMimeTypeAndIconName( "unknown/unknown", "unknown" );
571                         MimeIconEngine.AddMimeTypeAndIconName( "desktop/desktop", "desktop" );
572                         MimeIconEngine.AddMimeTypeAndIconName( "directory/home", "folder_home" );
573                         MimeIconEngine.AddMimeTypeAndIconName( "network/network", "network" );
574                         MimeIconEngine.AddMimeTypeAndIconName( "recently/recently", "folder_man" );
575                         MimeIconEngine.AddMimeTypeAndIconName( "workplace/workplace", "system" );
576                         
577                         foreach ( string mime_path in mime_paths )
578                         {
579                                 string[] directories = Directory.GetDirectories( mime_path );
580                                 
581                                 foreach ( string d in directories )
582                                 {
583                                         string[] files = Directory.GetFiles( d );
584                                         
585                                         foreach ( string f in files )
586                                         {
587                                             try {
588                                                 ReadDotDesktop( f );
589                                             } catch {
590                                                 // Ignore errors if the file can not be read.
591                                             }
592                                         }
593                                 }
594                         }
595                 }
596                 
597                 private void ReadDotDesktop( string filename )
598                 {
599                         StreamReader sr = new StreamReader( filename );
600                         
601                         string line = sr.ReadLine( );
602                         
603                         string icon_name = "";
604                         
605                         string mime_type = "";
606                         
607                         bool have_icon = false;
608                         bool have_mimetype = false;
609                         
610                         while ( line != null )
611                         {
612                                 line = line.Trim( );
613                                 
614                                 if ( line.StartsWith( "Icon" ) )
615                                 {
616                                         icon_name = line.Substring( line.IndexOf( '=' ) + 1 );
617                                         icon_name = icon_name.Trim( );
618                                         if ( have_mimetype )
619                                                 break;
620                                         have_icon = true;
621                                 }
622                                 else
623                                 if ( line.StartsWith( "MimeType" ) )
624                                 {
625                                         mime_type = line.Substring( line.IndexOf( '=' ) + 1 );
626                                         mime_type = mime_type.Trim( );
627                                         if ( have_icon )
628                                                 break;
629                                         have_mimetype = true;
630                                 }
631                                 
632                                 line = sr.ReadLine( );
633                         }
634                         
635                         sr.Close( );
636                         
637                         MimeIconEngine.AddMimeTypeAndIconName( mime_type, icon_name );
638                 }
639                 
640                 private bool ReadKdeglobals( )
641                 {
642                         if ( !File.Exists( full_kdegloabals_filename ) )
643                         {
644                                 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_KDEGLOBALS;
645                                 
646                                 return false;
647                         }
648                         
649                         StreamReader sr = new StreamReader( full_kdegloabals_filename );
650                         
651                         string line = sr.ReadLine( );
652                         
653                         while ( line != null )
654                         {
655                                 if ( line.IndexOf( "[Icons]" ) != -1 )
656                                 {
657                                         line = sr.ReadLine( );
658                                         
659                                         if ( line != null && line.IndexOf( "Theme" ) != -1 )
660                                         {
661                                                 line = line.Trim( );
662                                                 
663                                                 icon_theme = line.Substring( line.IndexOf( '=' ) + 1 );
664                                                 
665                                                 icon_theme = icon_theme.Trim( );
666                                                 
667                                                 break;
668                                         }
669                                 }
670                                 
671                                 line = sr.ReadLine( );
672                         }
673                         
674                         sr.Close( );
675                         
676                         return true;
677                 }
678         }
679         
680         // GnomeHandler uses the default gnome icon theme (many others are svg only)
681         internal class GnomeHandler : PlatformMimeIconHandler
682         {
683                 public override MimeExtensionHandlerStatus Start( )
684                 {
685                         if ( !CheckPlatformDirectories( ) )
686                                 return mimeExtensionHandlerStatus;
687                         
688                         CreateMimeTypeFromIconName( );
689                         
690                         ReadIcons( );
691                         
692                         return MimeExtensionHandlerStatus.OK;
693                 }
694                 
695                 protected override bool CheckPlatformDirectories( )
696                 {
697                         // add more directories ???
698                         if ( Directory.Exists( "/opt/gnome/share/icons/gnome/48x48" ) )
699                         {
700                                 icon_paths.Add( "/opt/gnome/share/icons/gnome/48x48/" );
701                         }
702                         else
703                         if ( Directory.Exists( "/usr/share/icons/gnome/48x48" ) )
704                         {
705                                 icon_paths.Add( "/usr/share/icons/gnome/48x48/" );
706                         }
707                         else
708                         if ( Directory.Exists( "/usr/local/share/icons/gnome/48x48" ) )
709                         {
710                                 icon_paths.Add( "/usr/local/share/icons/gnome/48x48/" );
711                         }
712                         else
713                         {
714                                 mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.NO_ICONS;
715                                 return false;
716                         }
717                         
718                         return true;
719                 }
720                 
721                 private void CreateMimeTypeFromIconName( )
722                 {
723                         MimeIconEngine.AddMimeTypeAndIconName( "inode/directory", "gnome-fs-directory" );
724                         MimeIconEngine.AddMimeTypeAndIconName( "unknown/unknown", "gnome-fs-regular" );
725                         MimeIconEngine.AddMimeTypeAndIconName( "desktop/desktop", "gnome-fs-desktop" );
726                         MimeIconEngine.AddMimeTypeAndIconName( "directory/home", "gnome-fs-home" );
727                         MimeIconEngine.AddMimeTypeAndIconName( "network/network", "gnome-fs-network" );
728                         MimeIconEngine.AddMimeTypeAndIconName( "recently/recently", "gnome-fs-directory-accept" );
729                         MimeIconEngine.AddMimeTypeAndIconName( "workplace/workplace", "gnome-fs-client" );
730                         
731                         foreach ( string ip in icon_paths )
732                         {
733                                 string[] files = Directory.GetFiles( ip + "mimetypes" );
734                                 
735                                 foreach ( string file in files )
736                                 {
737                                         string extension = Path.GetExtension( file );
738                                         
739                                         if ( extension != ".png" )
740                                                 continue;
741                                         
742                                         string file_name = Path.GetFileNameWithoutExtension( file );
743                                         
744                                         if ( !file_name.StartsWith( "gnome-mime-" ) )
745                                                 continue;
746                                         
747                                         StringBuilder mime_type = new StringBuilder( file_name.Replace( "gnome-mime-", "" ) );
748                                         
749                                         for ( int i = 0; i < mime_type.Length; i++ )
750                                                 if ( mime_type[ i ] == '-' )
751                                                 {
752                                                         mime_type[ i ] = '/';
753                                                         break;
754                                                 }
755                                         
756                                         MimeIconEngine.AddMimeTypeAndIconName( mime_type.ToString( ), file_name );
757                                 }
758                         }
759                 }
760                 
761                 private void ReadIcons( )
762                 {
763                         foreach ( string icon_path in icon_paths )
764                         {
765                                 string[] directories = Directory.GetDirectories( icon_path );
766                                 
767                                 foreach ( string directory in directories )
768                                 {
769                                         DirectoryInfo di = new DirectoryInfo( directory );
770                                         
771                                         FileInfo[] fileinfo = di.GetFiles( );
772                                         
773                                         foreach ( FileInfo fi in fileinfo )
774                                         {
775                                                 if ( fi.Extension != ".png" )
776                                                         continue;
777                                                 
778                                                 string name = Path.GetFileNameWithoutExtension( fi.Name );
779                                                 
780                                                 MimeIconEngine.AddIcon( name, fi.FullName );
781                                         }
782                                 }
783                         }
784                 }
785         }
786         
787         internal class SVGUtil {
788                 [DllImport("librsvg-2.so")]
789                 static extern IntPtr rsvg_pixbuf_from_file_at_size (string file_name, int  width, int  height, out IntPtr error);
790                 
791                 [DllImport("libgdk-x11-2.0.so")]
792                 static extern bool gdk_pixbuf_save_to_buffer (IntPtr pixbuf, out IntPtr buffer, out uint buffer_size, string type, out IntPtr error, IntPtr option_dummy);
793                 
794                 [DllImport("libglib-2.0.so")]
795                 static extern void g_free (IntPtr mem);
796                 
797                 [DllImport("libgdk-x11-2.0.so")]
798                 static extern bool gdk_init_check(out int argc, string argv);
799                 
800                 [DllImport("libgobject-2.0.so")]
801                 static extern void g_object_unref (IntPtr nativeObject);
802                 
803                 static bool inited = false;
804                 
805                 static void Init () {
806                         int argc = 0;
807                         string argv = "";
808                         
809                         gdk_init_check (out argc, argv);
810                         
811                         inited = true;
812                 }
813                 
814                 public static Image GetSVGasImage (string filename, int width, int height) {
815                         if (!inited)
816                                 Init ();
817                         
818                         if (!File.Exists (filename))
819                                 return null;
820                         IntPtr error = IntPtr.Zero;
821                         IntPtr pixbuf = rsvg_pixbuf_from_file_at_size (filename, width, height, out error);
822                         
823                         if (error != IntPtr.Zero)
824                                 return null;
825                         
826                         error = IntPtr.Zero;
827                         IntPtr buffer;
828                         uint buffer_size;
829                         string type = "png";
830                         
831                         bool saved = gdk_pixbuf_save_to_buffer (pixbuf, out buffer, out buffer_size, type, out error, IntPtr.Zero);
832                         
833                         if (!saved)
834                                 return null;
835                         
836                         byte[] result = new byte [buffer_size];
837                         Marshal.Copy (buffer, result, 0, (int) buffer_size);
838                         g_free (buffer);
839                         g_object_unref (pixbuf);
840                         
841                         Image image = null;
842                         using (MemoryStream s = new MemoryStream (result))
843                                 image = Image.FromStream (s);
844                         
845                         return image;
846                 }
847         }
848 }
849