1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/core/mimetype.cpp
3 // Purpose: Mac OS X implementation for wx MIME-related classes
4 // Author: Neil Perkins
5 // Modified by:
6 // Created: 2010-05-15
7 // Copyright: (C) 2010 Neil Perkins
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11
12 #include "wx/wxprec.h"
13
14 #ifndef WX_PRECOMP
15 #include "wx/defs.h"
16 #endif
17
18 #if wxUSE_MIMETYPE
19
20 #include "wx/osx/mimetype.h"
21 #include "wx/osx/private.h"
22
23 /////////////////////////////////////////////////////////////////////////////
24 // Helper functions
25 /////////////////////////////////////////////////////////////////////////////
26
27
28 // Read a string or array of strings from a CFDictionary for a given key
29 // Return an empty list on error
ReadStringListFromCFDict(CFDictionaryRef dictionary,CFStringRef key)30 wxArrayString ReadStringListFromCFDict( CFDictionaryRef dictionary, CFStringRef key )
31 {
32 // Create an empty list
33 wxArrayString results;
34
35 // Look up the requested key
36 CFTypeRef valueData = CFDictionaryGetValue( dictionary, key );
37
38 if( valueData )
39 {
40 // Value is an array
41 if( CFGetTypeID( valueData ) == CFArrayGetTypeID() )
42 {
43 CFArrayRef valueList = reinterpret_cast< CFArrayRef >( valueData );
44
45 CFTypeRef itemData;
46 wxCFStringRef item;
47
48 // Look at each item in the array
49 for( CFIndex i = 0, n = CFArrayGetCount( valueList ); i < n; i++ )
50 {
51 itemData = CFArrayGetValueAtIndex( valueList, i );
52
53 // Make sure the item is a string
54 if( CFGetTypeID( itemData ) == CFStringGetTypeID() )
55 {
56 // wxCFStringRef will automatically CFRelease, so an extra CFRetain is needed
57 item = reinterpret_cast< CFStringRef >( itemData );
58 wxCFRetain( item.get() );
59
60 // Add the string to the list
61 results.Add( item.AsString() );
62 }
63 }
64 }
65
66 // Value is a single string - return a list of one item
67 else if( CFGetTypeID( valueData ) == CFStringGetTypeID() )
68 {
69 // wxCFStringRef will automatically CFRelease, so an extra CFRetain is needed
70 wxCFStringRef value = reinterpret_cast< CFStringRef >( valueData );
71 wxCFRetain( value.get() );
72
73 // Add the string to the list
74 results.Add( value.AsString() );
75 }
76 }
77
78 // Return the list. If the dictionary did not contain key,
79 // or contained the wrong data type, the list will be empty
80 return results;
81 }
82
83
84 // Given a single CFDictionary representing document type data, check whether
85 // it matches a particular file extension. Return true for a match, false otherwise
CheckDocTypeMatchesExt(CFDictionaryRef docType,CFStringRef requiredExt)86 bool CheckDocTypeMatchesExt( CFDictionaryRef docType, CFStringRef requiredExt )
87 {
88 const static wxCFStringRef extKey( "CFBundleTypeExtensions" );
89
90 CFTypeRef extData = CFDictionaryGetValue( docType, extKey );
91
92 if( !extData )
93 return false;
94
95 if( CFGetTypeID( extData ) == CFArrayGetTypeID() )
96 {
97 CFArrayRef extList = reinterpret_cast< CFArrayRef >( extData );
98 CFTypeRef extItem;
99
100 for( CFIndex i = 0, n = CFArrayGetCount( extList ); i < n; i++ )
101 {
102 extItem = CFArrayGetValueAtIndex( extList, i );
103
104 if( CFGetTypeID( extItem ) == CFStringGetTypeID() )
105 {
106 CFStringRef ext = reinterpret_cast< CFStringRef >( extItem );
107
108 if( CFStringCompare( ext, requiredExt, kCFCompareCaseInsensitive ) == kCFCompareEqualTo )
109 return true;
110 }
111 }
112 }
113
114 if( CFGetTypeID( extData ) == CFStringGetTypeID() )
115 {
116 CFStringRef ext = reinterpret_cast< CFStringRef >( extData );
117
118 if( CFStringCompare( ext, requiredExt, kCFCompareCaseInsensitive ) == kCFCompareEqualTo )
119 return true;
120 }
121
122 return false;
123 }
124
125
126 // Given a data structure representing document type data, or a list of such
127 // structures, find the one which matches a particular file extension
128 // The result will be a CFDictionary containining document type data
129 // if a match is found, or null otherwise
GetDocTypeForExt(CFTypeRef docTypeData,CFStringRef requiredExt)130 CFDictionaryRef GetDocTypeForExt( CFTypeRef docTypeData, CFStringRef requiredExt )
131 {
132 if( !docTypeData )
133 return NULL;
134
135 if( CFGetTypeID( docTypeData ) == CFArrayGetTypeID() )
136 {
137 CFTypeRef item;
138 CFArrayRef docTypes;
139 docTypes = reinterpret_cast< CFArrayRef >( docTypeData );
140
141 for( CFIndex i = 0, n = CFArrayGetCount( docTypes ); i < n; i++ )
142 {
143 item = CFArrayGetValueAtIndex( docTypes, i );
144
145 if( CFGetTypeID( item ) == CFDictionaryGetTypeID() )
146 {
147 CFDictionaryRef docType;
148 docType = reinterpret_cast< CFDictionaryRef >( item );
149
150 if( CheckDocTypeMatchesExt( docType, requiredExt ) )
151 return docType;
152 }
153 }
154 }
155
156 if( CFGetTypeID( docTypeData ) == CFDictionaryGetTypeID() )
157 {
158 CFDictionaryRef docType = reinterpret_cast< CFDictionaryRef >( docTypeData );
159
160 if( CheckDocTypeMatchesExt( docType, requiredExt ) )
161 return docType;
162 }
163
164 return NULL;
165 }
166
167
168 // Given an application bundle reference and the name of an icon file
169 // which is a resource in that bundle, look up the full (posix style)
170 // path to that icon. Returns the path, or an empty wxString on failure
GetPathForIconFile(CFBundleRef bundle,CFStringRef iconFile)171 wxString GetPathForIconFile( CFBundleRef bundle, CFStringRef iconFile )
172 {
173 // If either parameter is NULL there is no hope of success
174 if( !bundle || !iconFile )
175 return wxEmptyString;
176
177 // Create a range object representing the whole string
178 CFRange wholeString;
179 wholeString.location = 0;
180 wholeString.length = CFStringGetLength( iconFile );
181
182 // Index of the period in the file name for iconFile
183 UniCharCount periodIndex;
184
185 // In order to locate the period delimiting the extension,
186 // iconFile must be represented as UniChar[]
187 {
188 // Allocate a buffer and copy in the iconFile string
189 UniChar* buffer = new UniChar[ wholeString.length ];
190 CFStringGetCharacters( iconFile, wholeString, buffer );
191
192 // Locate the period character
193 OSStatus status = LSGetExtensionInfo( wholeString.length, buffer, &periodIndex );
194
195 // Deallocate the buffer
196 delete [] buffer;
197
198 // If the period could not be located it will not be possible to get the URL
199 if( status != noErr || periodIndex == kLSInvalidExtensionIndex )
200 return wxEmptyString;
201 }
202
203 // Range representing the name part of iconFile
204 CFRange iconNameRange;
205 iconNameRange.location = 0;
206 iconNameRange.length = periodIndex - 1;
207
208 // Range representing the extension part of iconFile
209 CFRange iconExtRange;
210 iconExtRange.location = periodIndex;
211 iconExtRange.length = wholeString.length - periodIndex;
212
213 // Get the name and extension strings
214 wxCFStringRef iconName = CFStringCreateWithSubstring( kCFAllocatorDefault, iconFile, iconNameRange );
215 wxCFStringRef iconExt = CFStringCreateWithSubstring( kCFAllocatorDefault, iconFile, iconExtRange );
216
217 // Now it is possible to query the URL for the icon as a resource
218 wxCFRef< CFURLRef > iconUrl = wxCFRef< CFURLRef >( CFBundleCopyResourceURL( bundle, iconName, iconExt, NULL ) );
219
220 if( !iconUrl.get() )
221 return wxEmptyString;
222
223 // All being well, return the icon path
224 return wxCFStringRef( CFURLCopyFileSystemPath( iconUrl, kCFURLPOSIXPathStyle ) ).AsString();
225 }
226
227
wxMimeTypesManagerImpl()228 wxMimeTypesManagerImpl::wxMimeTypesManagerImpl()
229 {
230 }
231
~wxMimeTypesManagerImpl()232 wxMimeTypesManagerImpl::~wxMimeTypesManagerImpl()
233 {
234 }
235
236
237 /////////////////////////////////////////////////////////////////////////////
238 // Init / shutdown functions
239 //
240 // The Launch Services / UTI API provides no helpful way of getting a list
241 // of all registered types. Instead the API is focused around looking up
242 // information for a particular file type once you already have some
243 // identifying piece of information. In order to get a list of registered
244 // types it would first be necessary to get a list of all bundles exporting
245 // type information (all application bundles may be sufficient) then look at
246 // the Info.plist file for those bundles and store the type information. As
247 // this would require trawling the hard disk when a wxWidgets program starts
248 // up it was decided instead to load the information lazily.
249 //
250 // If this behaviour really messes up your app, please feel free to implement
251 // the trawling approach (perhaps with a configure switch?). A good place to
252 // start would be CFBundleCreateBundlesFromDirectory( NULL, "/Applications", "app" )
253 /////////////////////////////////////////////////////////////////////////////
254
255
Initialize(int WXUNUSED (mailcapStyles),const wxString & WXUNUSED (extraDir))256 void wxMimeTypesManagerImpl::Initialize(int WXUNUSED(mailcapStyles), const wxString& WXUNUSED(extraDir))
257 {
258 // NO-OP
259 }
260
ClearData()261 void wxMimeTypesManagerImpl::ClearData()
262 {
263 // NO-OP
264 }
265
266
267 /////////////////////////////////////////////////////////////////////////////
268 // Lookup functions
269 //
270 // Apple uses a number of different systems for file type information.
271 // As of Spring 2010, these include:
272 //
273 // OS Types / OS Creators
274 // File Extensions
275 // Mime Types
276 // Uniform Type Identifiers (UTI)
277 //
278 // This implementation of the type manager for Mac supports all except OS
279 // Type / OS Creator codes, which have been deprecated for some time with
280 // less and less support in recent versions of OS X.
281 //
282 // The UTI system is the internal system used by OS X, as such it offers a
283 // one-to-one mapping with file types understood by Mac OS X and is the
284 // easiest way to convert between type systems. However, UTI meta-data is
285 // not stored with data files (as of OS X 10.6), instead the OS looks at
286 // the file extension and uses this to determine the UTI. Simillarly, most
287 // applications do not yet advertise the file types they can handle by UTI.
288 //
289 // The result is that no one typing system is suitable for all tasks. Further,
290 // as there is not a one-to-one mapping between type systems for the
291 // description of any given type, it follows that ambiguity cannot be precluded,
292 // whichever system is taken to be the "master".
293 //
294 // In the implementation below I have used UTI as the master key for looking
295 // up file types. Extensions and mime types are mapped to UTIs and the data
296 // for each UTI contains a list of all associated extensions and mime types.
297 // This has the advantage that unknown types will still be assigned a unique
298 // ID, while using any other system as the master could result in conflicts
299 // if there were no mime type assigned to an extension or vice versa. However
300 // there is still plenty of room for ambiguity if two or more applications
301 // are fighting over ownership of a particular type or group of types.
302 //
303 // If this proves to be serious issue it may be helpful to add some slightly
304 // more cleve logic to the code so that the key used to look up a file type is
305 // always first in the list in the resulting wxFileType object. I.e, if you
306 // look up .mpeg3 the list you get back could be .mpeg3, mp3, .mpg3, while
307 // looking up .mp3 would give .mp3, .mpg3, .mpeg3. The simplest way to do
308 // this would probably to keep two separate sets of data, one for lookup
309 // by extetnsion and one for lookup by mime type.
310 //
311 // One other point which may require consideration is handling of unrecognised
312 // types. Using UTI these will be assigned a unique ID of dyn.xxx. This will
313 // result in a wxFileType object being returned, although querying properties
314 // on that object will fail. If it would be more helpful to return NULL in this
315 // case a suitable check can be added.
316 /////////////////////////////////////////////////////////////////////////////
317
318 // Look up a file type by extension
319 // The extensions if mapped to a UTI
320 // If the requested extension is not know the OS is querried and the results saved
GetFileTypeFromExtension(const wxString & ext)321 wxFileType *wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext)
322 {
323 wxString uti;
324
325 const TagMap::const_iterator extItr = m_extMap.find( ext );
326
327 if( extItr == m_extMap.end() )
328 {
329 wxCFStringRef utiRef = UTTypeCreatePreferredIdentifierForTag( kUTTagClassFilenameExtension, wxCFStringRef( ext ), NULL );
330 m_extMap[ ext ] = uti = utiRef.AsString();
331 }
332 else
333 uti = extItr->second;
334
335 return GetFileTypeFromUti( uti );
336 }
337
338 // Look up a file type by mime type
339 // The mime type is mapped to a UTI
340 // If the requested extension is not know the OS is querried and the results saved
GetFileTypeFromMimeType(const wxString & mimeType)341 wxFileType *wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType)
342 {
343 wxString uti;
344
345 const TagMap::const_iterator mimeItr = m_mimeMap.find( mimeType );
346
347 if( mimeItr == m_mimeMap.end() )
348 {
349 wxCFStringRef utiRef = UTTypeCreatePreferredIdentifierForTag( kUTTagClassFilenameExtension, wxCFStringRef( mimeType ), NULL );
350 m_mimeMap[ mimeType ] = uti = utiRef.AsString();
351 }
352 else
353 uti = mimeItr->second;
354
355 return GetFileTypeFromUti( uti );
356 }
357
358 // Look up a file type by UTI
359 // If the requested extension is not know the OS is querried and the results saved
GetFileTypeFromUti(const wxString & uti)360 wxFileType *wxMimeTypesManagerImpl::GetFileTypeFromUti(const wxString& uti)
361 {
362 UtiMap::const_iterator utiItr = m_utiMap.find( uti );
363
364 if( utiItr == m_utiMap.end() )
365 {
366 LoadTypeDataForUti( uti );
367 LoadDisplayDataForUti( uti );
368 }
369
370 wxFileType* const ft = new wxFileType;
371 ft->m_impl->m_uti = uti;
372 ft->m_impl->m_manager = this;
373
374 return ft;
375 }
376
377
378 /////////////////////////////////////////////////////////////////////////////
379 // Load functions
380 //
381 // These functions query the OS for information on a particular file type
382 /////////////////////////////////////////////////////////////////////////////
383
384
385 // Look up all extensions and mime types associated with a UTI
LoadTypeDataForUti(const wxString & uti)386 void wxMimeTypesManagerImpl::LoadTypeDataForUti(const wxString& uti)
387 {
388 // Keys in to the UTI declaration plist
389 const static wxCFStringRef tagsKey( "UTTypeTagSpecification" );
390 const static wxCFStringRef extKey( "public.filename-extension" );
391 const static wxCFStringRef mimeKey( "public.mime-type" );
392
393 // Get the UTI as a CFString
394 wxCFStringRef utiRef( uti );
395
396 // Get a copy of the UTI declaration
397 wxCFRef< CFDictionaryRef > utiDecl;
398 utiDecl = wxCFRef< CFDictionaryRef >( UTTypeCopyDeclaration( utiRef ) );
399
400 if( !utiDecl )
401 return;
402
403 // Get the tags spec (the section of a UTI declaration containing mappings to other type systems)
404 CFTypeRef tagsData = CFDictionaryGetValue( utiDecl, tagsKey );
405
406 if( CFGetTypeID( tagsData ) != CFDictionaryGetTypeID() )
407 return;
408
409 CFDictionaryRef tags = reinterpret_cast< CFDictionaryRef >( tagsData );
410
411 // Read tags for extensions and mime types
412 m_utiMap[ uti ].extensions = ReadStringListFromCFDict( tags, extKey );
413 m_utiMap[ uti ].mimeTypes = ReadStringListFromCFDict( tags, mimeKey );
414 }
415
416
417 // Look up the (locale) display name and icon file associated with a UTI
LoadDisplayDataForUti(const wxString & uti)418 void wxMimeTypesManagerImpl::LoadDisplayDataForUti(const wxString& uti)
419 {
420 // Keys in to Info.plist
421 const static wxCFStringRef docTypesKey( "CFBundleDocumentTypes" );
422 const static wxCFStringRef descKey( "CFBundleTypeName" );
423 const static wxCFStringRef iconKey( "CFBundleTypeIconFile" );
424
425 wxCFStringRef cfuti(uti);
426
427 wxCFStringRef ext = UTTypeCopyPreferredTagWithClass( cfuti, kUTTagClassFilenameExtension );
428
429 // Look up the preferred application
430 wxCFRef<CFURLRef> appUrl = LSCopyDefaultApplicationURLForContentType( cfuti, kLSRolesAll, NULL);
431
432 if( !appUrl )
433 return;
434
435 // Create a bundle object for that application
436 wxCFRef< CFBundleRef > bundle;
437 bundle = wxCFRef< CFBundleRef >( CFBundleCreate( kCFAllocatorDefault, appUrl ) );
438
439 if( !bundle )
440 return;
441
442 // Also get the open command while we have the bundle
443 wxCFStringRef cfsAppPath(CFURLCopyFileSystemPath(appUrl, kCFURLPOSIXPathStyle));
444 m_utiMap[ uti ].application = cfsAppPath.AsString();
445
446 // Get all the document type data in this bundle
447 CFTypeRef docTypeData;
448 docTypeData = CFBundleGetValueForInfoDictionaryKey( bundle, docTypesKey );
449
450 if( !docTypeData )
451 return;
452
453 // Find the document type entry that matches ext
454 CFDictionaryRef docType;
455 docType = GetDocTypeForExt( docTypeData, ext );
456
457 if( !docType )
458 return;
459
460 // Get the display name for docType
461 wxCFStringRef description = reinterpret_cast< CFStringRef >( CFDictionaryGetValue( docType, descKey ) );
462 wxCFRetain( description.get() );
463 m_utiMap[ uti ].description = description.AsString();
464
465 // Get the icon path for docType
466 CFStringRef iconFile = reinterpret_cast< CFStringRef > ( CFDictionaryGetValue( docType, iconKey ) );
467 m_utiMap[ uti ].iconLoc.SetFileName( GetPathForIconFile( bundle, iconFile ) );
468 }
469
470
471
472 /////////////////////////////////////////////////////////////////////////////
473 // The remaining functionality from the public interface of
474 // wxMimeTypesManagerImpl is not implemented.
475 //
476 // Please see the note further up this file on Initialise/Clear to explain why
477 // EnumAllFileTypes is not available.
478 //
479 // Some thought will be needed before implementing Associate / Unassociate
480 // for OS X to ensure proper integration with the many file type and
481 // association mechanisms already used by the OS. Leaving these methods as
482 // NO-OP on OS X and asking client apps to put suitable entries in their
483 // Info.plist files when building their OS X bundle may well be the
484 // correct solution.
485 /////////////////////////////////////////////////////////////////////////////
486
487
EnumAllFileTypes(wxArrayString & WXUNUSED (mimetypes))488 size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& WXUNUSED(mimetypes))
489 {
490 return 0;
491 }
492
Associate(const wxFileTypeInfo & WXUNUSED (ftInfo))493 wxFileType *wxMimeTypesManagerImpl::Associate(const wxFileTypeInfo& WXUNUSED(ftInfo))
494 {
495 return 0;
496 }
497
Unassociate(wxFileType * WXUNUSED (ft))498 bool wxMimeTypesManagerImpl::Unassociate(wxFileType *WXUNUSED(ft))
499 {
500 return false;
501 }
502
503
504 /////////////////////////////////////////////////////////////////////////////
505 // Getter methods
506 //
507 // These methods are private and should only ever be called by wxFileTypeImpl
508 // after the required information has been loaded. It should not be possible
509 // to get a wxFileTypeImpl for a UTI without information for that UTI being
510 // querried, however it is possible that some information may not have been
511 // found.
512 /////////////////////////////////////////////////////////////////////////////
513
514
515
GetExtensions(const wxString & uti,wxArrayString & extensions)516 bool wxMimeTypesManagerImpl::GetExtensions(const wxString& uti, wxArrayString& extensions)
517 {
518 const UtiMap::const_iterator itr = m_utiMap.find( uti );
519
520 if( itr == m_utiMap.end() || itr->second.extensions.GetCount() < 1 )
521 {
522 extensions.Clear();
523 return false;
524 }
525
526 extensions = itr->second.extensions;
527 return true;
528 }
529
GetMimeType(const wxString & uti,wxString * mimeType)530 bool wxMimeTypesManagerImpl::GetMimeType(const wxString& uti, wxString *mimeType)
531 {
532 const UtiMap::const_iterator itr = m_utiMap.find( uti );
533
534 if( itr == m_utiMap.end() || itr->second.mimeTypes.GetCount() < 1 )
535 {
536 mimeType->clear();
537 return false;
538 }
539
540 *mimeType = itr->second.mimeTypes[ 0 ];
541 return true;
542 }
543
GetMimeTypes(const wxString & uti,wxArrayString & mimeTypes)544 bool wxMimeTypesManagerImpl::GetMimeTypes(const wxString& uti, wxArrayString& mimeTypes)
545 {
546 const UtiMap::const_iterator itr = m_utiMap.find( uti );
547
548 if( itr == m_utiMap.end() || itr->second.mimeTypes.GetCount() < 1 )
549 {
550 mimeTypes.Clear();
551 return false;
552 }
553
554 mimeTypes = itr->second.mimeTypes;
555 return true;
556 }
557
GetIcon(const wxString & uti,wxIconLocation * iconLoc)558 bool wxMimeTypesManagerImpl::GetIcon(const wxString& uti, wxIconLocation *iconLoc)
559 {
560 const UtiMap::const_iterator itr = m_utiMap.find( uti );
561
562 if( itr == m_utiMap.end() || !itr->second.iconLoc.IsOk() )
563 {
564 *iconLoc = wxIconLocation();
565 return false;
566 }
567
568 *iconLoc = itr->second.iconLoc;
569 return true;
570 }
571
GetDescription(const wxString & uti,wxString * desc)572 bool wxMimeTypesManagerImpl::GetDescription(const wxString& uti, wxString *desc)
573 {
574 const UtiMap::const_iterator itr = m_utiMap.find( uti );
575
576 if( itr == m_utiMap.end() || itr->second.description.empty() )
577 {
578 desc->clear();
579 return false;
580 }
581
582 *desc = itr->second.description;
583 return true;
584 }
585
GetApplication(const wxString & uti,wxString * command)586 bool wxMimeTypesManagerImpl::GetApplication(const wxString& uti, wxString *command)
587 {
588 const UtiMap::const_iterator itr = m_utiMap.find( uti );
589
590 if( itr == m_utiMap.end() )
591 {
592 command->clear();
593 return false;
594 }
595
596 *command = itr->second.application;
597 return true;
598 }
599
600 /////////////////////////////////////////////////////////////////////////////
601 // The remaining functionality has not yet been implemented for OS X
602 /////////////////////////////////////////////////////////////////////////////
603
wxFileTypeImpl()604 wxFileTypeImpl::wxFileTypeImpl()
605 {
606 }
607
~wxFileTypeImpl()608 wxFileTypeImpl::~wxFileTypeImpl()
609 {
610 }
611
612 // Query wxMimeTypesManagerImple to get real information for a file type
GetExtensions(wxArrayString & extensions) const613 bool wxFileTypeImpl::GetExtensions(wxArrayString& extensions) const
614 {
615 return m_manager->GetExtensions( m_uti, extensions );
616 }
617
GetMimeType(wxString * mimeType) const618 bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const
619 {
620 return m_manager->GetMimeType( m_uti, mimeType );
621 }
622
GetMimeTypes(wxArrayString & mimeTypes) const623 bool wxFileTypeImpl::GetMimeTypes(wxArrayString& mimeTypes) const
624 {
625 return m_manager->GetMimeTypes( m_uti, mimeTypes );
626 }
627
GetIcon(wxIconLocation * iconLoc) const628 bool wxFileTypeImpl::GetIcon(wxIconLocation *iconLoc) const
629 {
630 return m_manager->GetIcon( m_uti, iconLoc );
631 }
632
GetDescription(wxString * desc) const633 bool wxFileTypeImpl::GetDescription(wxString *desc) const
634 {
635 return m_manager->GetDescription( m_uti, desc );
636 }
637
638 namespace
639 {
640
641 // Helper function for GetOpenCommand(): returns the string surrounded by
642 // (singly) quotes if it contains spaces.
QuoteIfNecessary(const wxString & path)643 wxString QuoteIfNecessary(const wxString& path)
644 {
645 wxString result(path);
646
647 if ( path.find(' ') != wxString::npos )
648 {
649 result.insert(0, "'");
650 result.append("'");
651 }
652
653 return result;
654 }
655
656 } // anonymous namespace
657
GetOpenCommand(wxString * openCmd,const wxFileType::MessageParameters & params) const658 bool wxFileTypeImpl::GetOpenCommand(wxString *openCmd, const wxFileType::MessageParameters& params) const
659 {
660 wxString application;
661 if ( !m_manager->GetApplication(m_uti, &application) )
662 return false;
663
664 *openCmd << QuoteIfNecessary(application)
665 << ' ' << QuoteIfNecessary(params.GetFileName());
666
667 return true;
668 }
669
GetPrintCommand(wxString * WXUNUSED (printCmd),const wxFileType::MessageParameters & WXUNUSED (params)) const670 bool wxFileTypeImpl::GetPrintCommand(wxString *WXUNUSED(printCmd), const wxFileType::MessageParameters& WXUNUSED(params)) const
671 {
672 return false;
673 }
674
GetAllCommands(wxArrayString * WXUNUSED (verbs),wxArrayString * WXUNUSED (commands),const wxFileType::MessageParameters & WXUNUSED (params)) const675 size_t wxFileTypeImpl::GetAllCommands(wxArrayString *WXUNUSED(verbs), wxArrayString *WXUNUSED(commands), const wxFileType::MessageParameters& WXUNUSED(params)) const
676 {
677 return false;
678 }
679
SetCommand(const wxString & WXUNUSED (cmd),const wxString & WXUNUSED (verb),bool WXUNUSED (overwriteprompt))680 bool wxFileTypeImpl::SetCommand(const wxString& WXUNUSED(cmd), const wxString& WXUNUSED(verb), bool WXUNUSED(overwriteprompt))
681 {
682 return false;
683 }
684
SetDefaultIcon(const wxString & WXUNUSED (strIcon),int WXUNUSED (index))685 bool wxFileTypeImpl::SetDefaultIcon(const wxString& WXUNUSED(strIcon), int WXUNUSED(index))
686 {
687 return false;
688 }
689
Unassociate(wxFileType * WXUNUSED (ft))690 bool wxFileTypeImpl::Unassociate(wxFileType *WXUNUSED(ft))
691 {
692 return false;
693 }
694
695 wxString
GetExpandedCommand(const wxString & WXUNUSED (verb),const wxFileType::MessageParameters & WXUNUSED (params)) const696 wxFileTypeImpl::GetExpandedCommand(const wxString& WXUNUSED(verb),
697 const wxFileType::MessageParameters& WXUNUSED(params)) const
698 {
699 return wxString();
700 }
701
702 #endif // wxUSE_MIMETYPE
703
704
705