1///////////////////////////////////////////////////////////////////////////// 2// Name: src/os2/mimetype.cpp 3// Purpose: classes and functions to manage MIME types 4// Author: David Webster 5// Modified by: 6// Created: 01.21.00 7// RCS-ID: $Id: mimetype.cpp 38920 2006-04-26 08:21:31Z ABX $ 8// Copyright: Adopted from msw port --(c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 9// Licence: wxWindows licence (part of wxExtra library) 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#if wxUSE_MIMETYPE 16 17#include "wx/os2/mimetype.h" 18 19#ifndef WX_PRECOMP 20 #include "wx/dynarray.h" 21 #include "wx/string.h" 22 #include "wx/intl.h" 23 #include "wx/log.h" 24 #if wxUSE_GUI 25 #include "wx/icon.h" 26 #endif 27#endif //WX_PRECOMP 28 29#define INCL_DOS 30#define INCL_GPI 31#define INCL_WIN 32#include <os2.h> 33 34#include "wx/file.h" 35#include "wx/iconloc.h" 36#include "wx/confbase.h" 37 38// other standard headers 39#include <ctype.h> 40 41// in case we're compiling in non-GUI mode 42class WXDLLEXPORT wxIcon; 43 44// These classes use Windows registry to retrieve the required information. 45// 46// Keys used (not all of them are documented, so it might actually stop working 47// in futur versions of Windows...): 48// 1. "HKCR\MIME\Database\Content Type" contains subkeys for all known MIME 49// types, each key has a string value "Extension" which gives (dot preceded) 50// extension for the files of this MIME type. 51// 52// 2. "HKCR\.ext" contains 53// a) unnamed value containing the "filetype" 54// b) value "Content Type" containing the MIME type 55// 56// 3. "HKCR\filetype" contains 57// a) unnamed value containing the description 58// b) subkey "DefaultIcon" with single unnamed value giving the icon index in 59// an icon file 60// c) shell\open\command and shell\open\print subkeys containing the commands 61// to open/print the file (the positional parameters are introduced by %1, 62// %2, ... in these strings, we change them to %s ourselves) 63 64// although I don't know of any official documentation which mentions this 65// location, uses it, so it isn't likely to change 66static const wxChar *MIME_DATABASE_KEY = wxT("MIME\\Database\\Content Type\\"); 67 68wxString wxFileTypeImpl::GetCommand(const wxChar *WXUNUSED(verb)) const 69{ 70// TODO: OS/2 doesn't have a registry but uses Prf 71/* 72 // suppress possible error messages 73 wxLogNull nolog; 74 wxString strKey; 75 76 if ( wxRegKey(wxRegKey::HKCR, m_ext + _T("\\shell")).Exists() ) 77 strKey = m_ext; 78 if ( wxRegKey(wxRegKey::HKCR, m_strFileType + _T("\\shell")).Exists() ) 79 strKey = m_strFileType; 80 81 if ( !strKey ) 82 { 83 // no info 84 return wxEmptyString; 85 } 86 87 strKey << wxT("\\shell\\") << verb; 88 wxRegKey key(wxRegKey::HKCR, strKey + _T("\\command")); 89 wxString command; 90 if ( key.Open() ) { 91 // it's the default value of the key 92 if ( key.QueryValue(wxT(""), command) ) { 93 // transform it from '%1' to '%s' style format string (now also 94 // test for %L - apparently MS started using it as well for the 95 // same purpose) 96 97 // NB: we don't make any attempt to verify that the string is valid, 98 // i.e. doesn't contain %2, or second %1 or .... But we do make 99 // sure that we return a string with _exactly_ one '%s'! 100 bool foundFilename = false; 101 size_t len = command.Len(); 102 for ( size_t n = 0; (n < len) && !foundFilename; n++ ) { 103 if ( command[n] == wxT('%') && 104 (n + 1 < len) && 105 (command[n + 1] == wxT('1') || 106 command[n + 1] == wxT('L')) ) { 107 // replace it with '%s' 108 command[n + 1] = wxT('s'); 109 110 foundFilename = true; 111 } 112 } 113 114#if wxUSE_DDE 115 // look whether we must issue some DDE requests to the application 116 // (and not just launch it) 117 strKey += _T("\\DDEExec"); 118 wxRegKey keyDDE(wxRegKey::HKCR, strKey); 119 if ( keyDDE.Open() ) { 120 wxString ddeCommand, ddeServer, ddeTopic; 121 keyDDE.QueryValue(_T(""), ddeCommand); 122 ddeCommand.Replace(_T("%1"), _T("%s")); 123 124 wxRegKey(wxRegKey::HKCR, strKey + _T("\\Application")). 125 QueryValue(_T(""), ddeServer); 126 wxRegKey(wxRegKey::HKCR, strKey + _T("\\Topic")). 127 QueryValue(_T(""), ddeTopic); 128 129 // HACK: we use a special feature of wxExecute which exists 130 // just because we need it here: it will establish DDE 131 // conversation with the program it just launched 132 command.Prepend(_T("WX_DDE#")); 133 command << _T('#') << ddeServer 134 << _T('#') << ddeTopic 135 << _T('#') << ddeCommand; 136 } 137 else 138#endif // wxUSE_DDE 139 if ( !foundFilename ) { 140 // we didn't find any '%1' - the application doesn't know which 141 // file to open (note that we only do it if there is no DDEExec 142 // subkey) 143 // 144 // HACK: append the filename at the end, hope that it will do 145 command << wxT(" %s"); 146 } 147 } 148 } 149 //else: no such file type or no value, will return empty string 150 151 return command; 152*/ 153 return wxEmptyString; 154} 155 156bool 157wxFileTypeImpl::GetOpenCommand(wxString *openCmd, 158 const wxFileType::MessageParameters& params) 159 const 160{ 161 wxString cmd; 162 if ( m_info ) { 163 cmd = m_info->GetOpenCommand(); 164 } 165 else { 166 cmd = GetCommand(wxT("open")); 167 } 168 169 *openCmd = wxFileType::ExpandCommand(cmd, params); 170 171 return !openCmd->empty(); 172} 173 174bool 175wxFileTypeImpl::GetPrintCommand(wxString *printCmd, 176 const wxFileType::MessageParameters& params) 177 const 178{ 179 wxString cmd; 180 if ( m_info ) { 181 cmd = m_info->GetPrintCommand(); 182 } 183 else { 184 cmd = GetCommand(wxT("print")); 185 } 186 187 *printCmd = wxFileType::ExpandCommand(cmd, params); 188 189 return !printCmd->empty(); 190} 191 192// TODO this function is half implemented 193bool wxFileTypeImpl::GetExtensions(wxArrayString& extensions) 194{ 195 if ( m_info ) { 196 extensions = m_info->GetExtensions(); 197 198 return true; 199 } 200 else if ( m_ext.empty() ) { 201 // the only way to get the list of extensions from the file type is to 202 // scan through all extensions in the registry - too slow... 203 return false; 204 } 205 else { 206 extensions.Empty(); 207 extensions.Add(m_ext); 208 209 // it's a lie too, we don't return _all_ extensions... 210 return true; 211 } 212} 213 214bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const 215{ 216 if ( m_info ) { 217 // we already have it 218 *mimeType = m_info->GetMimeType(); 219 220 return true; 221 } 222 223 // suppress possible error messages 224 wxLogNull nolog; 225// TODO: substitue reg key stuff (maybe make a Prf class for OS/2??) 226/* 227 wxRegKey key(wxRegKey::HKCR, wxT(".") + m_ext); 228 if ( key.Open() && key.QueryValue(wxT("Content Type"), *mimeType) ) { 229 return true; 230 } 231 else { 232 return false; 233 } 234*/ 235 return false; 236} 237 238bool wxFileTypeImpl::GetMimeTypes(wxArrayString& mimeTypes) const 239{ 240 wxString s; 241 242 if (GetMimeType(&s)) 243 { 244 mimeTypes.Clear(); 245 mimeTypes.Add(s); 246 return true; 247 } 248 else 249 return false; 250} 251 252bool wxFileTypeImpl::GetIcon(wxIconLocation *WXUNUSED(iconLoc)) const 253{ 254 if ( m_info ) { 255 // we don't have icons in the fallback resources 256 return false; 257 } 258 259 wxString strIconKey; 260 strIconKey << m_strFileType << wxT("\\DefaultIcon"); 261 262 // suppress possible error messages 263 wxLogNull nolog; 264//TODO: 265/* 266 wxRegKey key(wxRegKey::HKCR, strIconKey); 267 268 if ( key.Open() ) { 269 wxString strIcon; 270 // it's the default value of the key 271 if ( key.QueryValue(wxEmptyString, strIcon) ) { 272 // the format is the following: <full path to file>, <icon index> 273 // NB: icon index may be negative as well as positive and the full 274 // path may contain the environment variables inside '%' 275 wxString strFullPath = strIcon.BeforeLast(wxT(',')), 276 strIndex = strIcon.AfterLast(wxT(',')); 277 278 // index may be omitted, in which case BeforeLast(',') is empty and 279 // AfterLast(',') is the whole string 280 if ( strFullPath.empty() ) { 281 strFullPath = strIndex; 282 strIndex = wxT("0"); 283 } 284 285 if ( iconLoc ) 286 { 287 iconLoc->SetFileName(wxExpandEnvVars(strFullPath)); 288 289 iconLoc->SetIndex(wxAtoi(strIndex)); 290 } 291 292 return true; 293 } 294 } 295 296 // no such file type or no value or incorrect icon entry 297*/ 298 return false; 299} 300 301bool wxFileTypeImpl::GetDescription(wxString *desc) const 302{ 303 if ( m_info ) { 304 // we already have it 305 *desc = m_info->GetDescription(); 306 307 return true; 308 } 309 310 // suppress possible error messages 311 wxLogNull nolog; 312// TODO: 313/* 314 wxRegKey key(wxRegKey::HKCR, m_strFileType); 315 316 if ( key.Open() ) { 317 // it's the default value of the key 318 if ( key.QueryValue(wxT(""), *desc) ) { 319 return true; 320 } 321 } 322*/ 323 return false; 324} 325 326// extension -> file type 327wxFileType * 328wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext) 329{ 330 // add the leading point if necessary 331 wxString str; 332 if ( ext[(size_t) 0] != wxT('.') ) { 333 str = wxT('.'); 334 } 335 str << ext; 336 337 // suppress possible error messages 338 wxLogNull nolog; 339 340 bool knownExtension = false; 341 342 wxString strFileType; 343// TODO: 344/* 345 wxRegKey key(wxRegKey::HKCR, str); 346 if ( key.Open() ) { 347 // it's the default value of the key 348 if ( key.QueryValue(wxT(""), strFileType) ) { 349 // create the new wxFileType object 350 wxFileType *fileType = new wxFileType; 351 fileType->m_impl->Init(strFileType, ext); 352 353 return fileType; 354 } 355 else { 356 // this extension doesn't have a filetype, but it's known to the 357 // system and may be has some other useful keys (open command or 358 // content-type), so still return a file type object for it 359 knownExtension = true; 360 } 361 } 362*/ 363 // check the fallbacks 364 // TODO linear search is potentially slow, perhaps we should use a sorted 365 // array? 366 size_t count = m_fallbacks.GetCount(); 367 for ( size_t n = 0; n < count; n++ ) { 368 if ( m_fallbacks[n].GetExtensions().Index(ext) != wxNOT_FOUND ) { 369 wxFileType *fileType = new wxFileType; 370 fileType->m_impl->Init(m_fallbacks[n]); 371 372 return fileType; 373 } 374 } 375 376 if ( knownExtension ) 377 { 378 wxFileType *fileType = new wxFileType; 379 fileType->m_impl->Init(wxEmptyString, ext); 380 381 return fileType; 382 } 383 else 384 { 385 // unknown extension 386 return NULL; 387 } 388} 389 390// MIME type -> extension -> file type 391wxFileType * 392wxMimeTypesManagerImpl::GetFileTypeFromMimeType(const wxString& mimeType) 393{ 394 wxString strKey = MIME_DATABASE_KEY; 395 strKey << mimeType; 396 397 // suppress possible error messages 398 wxLogNull nolog; 399 400 wxString ext; 401// TODO: 402/* 403 wxRegKey key(wxRegKey::HKCR, strKey); 404 if ( key.Open() ) { 405 if ( key.QueryValue(wxT("Extension"), ext) ) { 406 return GetFileTypeFromExtension(ext); 407 } 408 } 409 410 // check the fallbacks 411 // TODO linear search is potentially slow, perhaps we should use a sorted 412 // array? 413 size_t count = m_fallbacks.GetCount(); 414 for ( size_t n = 0; n < count; n++ ) { 415 if ( wxMimeTypesManager::IsOfType(mimeType, 416 m_fallbacks[n].GetMimeType()) ) { 417 wxFileType *fileType = new wxFileType; 418 fileType->m_impl->Init(m_fallbacks[n]); 419 420 return fileType; 421 } 422 } 423*/ 424 // unknown MIME type 425 return NULL; 426} 427 428size_t wxMimeTypesManagerImpl::EnumAllFileTypes(wxArrayString& WXUNUSED(mimetypes)) 429{ 430 // enumerate all keys under MIME_DATABASE_KEY 431// TODO: 432/* 433 wxRegKey key(wxRegKey::HKCR, MIME_DATABASE_KEY); 434 435 wxString type; 436 long cookie; 437 bool cont = key.GetFirstKey(type, cookie); 438 while ( cont ) 439 { 440 mimetypes.Add(type); 441 442 cont = key.GetNextKey(type, cookie); 443 } 444 445 return mimetypes.GetCount(); 446*/ 447 return 0; 448} 449 450#endif //wxUSE_MIMETYPE 451