⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mimetmac.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        src/mac/carbon/mimetype.cpp
// Purpose:     Mac Carbon implementation for wx MIME-related classes
// Author:      Ryan Norton
// Modified by:
// Created:     04/16/2005
// RCS-ID:      $Id: mimetmac.cpp,v 1.38 2006/05/03 04:12:42 PC Exp $
// Copyright:   (c) 2005 Ryan Norton (<wxprojects@comcast.net>)
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

//
//  TODO: Search Info[-macos](classic).plist dictionary in addition
//  to Internet Config database.
//
//  Maybe try a brainstorm a way to change the wxMimeTypesManager API
//  to get info from a file instead/addition to current get all stuff
//  API so that we can use Launch Services to get MIME type info.
//
//  Implement GetIcon from one of the FinderInfo functions - or
//  use Launch Services and search that app's plist for the icon.
//
//  Put some special juice in for the print command.
//

// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#if wxUSE_MIMETYPE

#include "wx/mac/mimetype.h"

#ifndef WX_PRECOMP
    #include "wx/dynarray.h"
    #include "wx/string.h"
    #include "wx/intl.h"
    #include "wx/log.h"

    #if wxUSE_GUI
        #include "wx/icon.h"
    #endif
#endif

#include "wx/file.h"
#include "wx/confbase.h"

#include "wx/mac/private.h"

// other standard headers
#include <ctype.h>

#ifndef __DARWIN__
    #include <InternetConfig.h>
    #include <CoreServices.h>
#endif


//   START CODE SAMPLE FROM TECHNOTE 1002 (http://developer.apple.com/technotes/tn/tn1002.html)

// IsRemoteVolume can be used to find out if the
// volume referred to by vRefNum is a remote volume
// located somewhere on a network. the volume's attribute
// flags (copied from the GetVolParmsInfoBuffer structure)
// are returned in the longword pointed to by vMAttrib.
OSErr IsRemoteVolume(short vRefNum, Boolean *isRemote, long *vMAttrib)
{
    HParamBlockRec volPB;
    GetVolParmsInfoBuffer volinfo;
    OSErr err;

    volPB.ioParam.ioVRefNum = vRefNum;
    volPB.ioParam.ioNamePtr = NULL;
    volPB.ioParam.ioBuffer = (Ptr)&volinfo;
    volPB.ioParam.ioReqCount = sizeof(volinfo);
    err = PBHGetVolParmsSync( &volPB );
    if (err == noErr)
    {
        *isRemote = (volinfo.vMServerAdr != 0);
        *vMAttrib = volinfo.vMAttrib;
    }

    return err;
}

// BuildVolumeList fills the array pointed to by vols with
// a list of the currently mounted volumes.  If includeRemote
// is true, then remote server volumes will be included in
// the list.  When remote server volumes are included in the
// list, they will be added to the end of the list.  On entry,
// *count should contain the size of the array pointed to by
// vols.  On exit, *count will be set to the number of id numbers
// placed in the array. If vMAttribMask is non-zero, then
// only volumes with matching attributes are added to the
// list of volumes. bits in the vMAttribMask should use the
// same encoding as bits in the vMAttrib field of
// the GetVolParmsInfoBuffer structure.
OSErr BuildVolumeList(Boolean includeRemote, short *vols,
        long *count, long vMAttribMask)
{
    HParamBlockRec volPB;
    Boolean isRemote;
    OSErr err = noErr;
    long nlocal, nremote;
    long vMAttrib;

    // set up and check parameters
    volPB.volumeParam.ioNamePtr = NULL;
    nlocal = nremote = 0;
    if (*count == 0)
        return noErr;

    // iterate through volumes
    for (volPB.volumeParam.ioVolIndex = 1;
        PBHGetVInfoSync(&volPB) == noErr;
        volPB.volumeParam.ioVolIndex++)
    {
        // skip remote volumes, if necessary
        err = IsRemoteVolume(volPB.volumeParam.ioVRefNum, &isRemote, &vMAttrib);
        if (err != noErr)
            goto bail;

        if ((includeRemote || !isRemote) && ((vMAttrib & vMAttribMask) == vMAttribMask))
        {
            // add local volumes at the front; remote volumes at the end
            if (isRemote)
                vols[nlocal + nremote++] = volPB.volumeParam.ioVRefNum;
            else
            {
                if (nremote > 0)
                    BlockMoveData(
                        vols + nlocal,
                        vols + nlocal + 1,
                        nremote * sizeof(short) );
                vols[nlocal++] = volPB.volumeParam.ioVRefNum;
            }

            // list full?
            if ((nlocal + nremote) >= *count)
                break;
        }
    }

bail:
    *count = (nlocal + nremote);

    return err;
}


// FindApplication iterates through mounted volumes
// searching for an application with the given creator
// type.  If includeRemote is true, then remote volumes
// will be searched (after local ones) for an application
// with the creator type.
//
// Hacked to output to appName
//
#define kMaxVols 20

OSErr FindApplication(OSType appCreator, Boolean includeRemote, Str255 appName, FSSpec* appSpec)
{
    short rRefNums[kMaxVols];
    long i, volCount;
    DTPBRec desktopPB;
    OSErr err;

    // get a list of volumes - with desktop files
    volCount = kMaxVols;
    err = BuildVolumeList(includeRemote, rRefNums, &volCount, (1 << bHasDesktopMgr) );
    if (err != noErr)
        return err;

    // iterate through the list
    for (i=0; i<volCount; i++)
    {
        // has a desktop file?
        desktopPB.ioCompletion = NULL;
        desktopPB.ioVRefNum = rRefNums[i];
        desktopPB.ioNamePtr = NULL;
        desktopPB.ioIndex = 0;
        err = PBDTGetPath( &desktopPB );
        if (err != noErr)
            continue;

        // has the correct app??
        desktopPB.ioFileCreator = appCreator;
        desktopPB.ioNamePtr = appName;
        err = PBDTGetAPPLSync( &desktopPB );
        if (err != noErr)
            continue;

        // make a file spec referring to it
        err = FSMakeFSSpec( rRefNums[i], desktopPB.ioAPPLParID, appName, appSpec );
        if (err != noErr)
            continue;

        // found it!
        return noErr;
    }

    return fnfErr;
}

// END CODE SAMPLE FROM TECHNOTE 1002 (http://developer.apple.com/technotes/tn/tn1002.html)

// yeah, duplicated code
pascal OSErr FSpGetFullPath( const FSSpec *spec,
    short *fullPathLength,
    Handle *fullPath )
{
    OSErr result, realResult;
    FSSpec tempSpec;
    CInfoPBRec pb;

    *fullPathLength = 0;
    *fullPath = NULL;

    // default to noErr
    realResult = result = noErr;

  // work around Nav Services "bug" (it returns invalid FSSpecs with empty names)
#if 0
    if ( spec->name[0] == 0 )
    {
        result = FSMakeFSSpecCompat(spec->vRefNum, spec->parID, spec->name, &tempSpec);
    }
    else
    {
#endif

    // Make a copy of the input FSSpec that can be modified
    BlockMoveData( spec, &tempSpec, sizeof(FSSpec) );

    if ( result == noErr )
    {
        if ( tempSpec.parID == fsRtParID )
        {
            // object is a volume
            // Add a colon to make it a full pathname
            ++tempSpec.name[0];
            tempSpec.name[tempSpec.name[0]] = ':';

            // We're done
            result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
        }
        else
        {
            // object isn't a volume

            // Is the object a file or a directory?
            pb.dirInfo.ioNamePtr = tempSpec.name;
            pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
            pb.dirInfo.ioDrDirID = tempSpec.parID;
            pb.dirInfo.ioFDirIndex = 0;
            result = PBGetCatInfoSync( &pb );

            // Allow file/directory name at end of path to not exist.
            realResult = result;
            if ((result == noErr) || (result == fnfErr))
            {
                // if the object is a directory, append a colon so full pathname ends with colon
                if ((result == noErr) && (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0)
                {
                    ++tempSpec.name[0];
                    tempSpec.name[tempSpec.name[0]] = ':';
                }

                // Put the object name in first
                result = PtrToHand( &tempSpec.name[1], fullPath, tempSpec.name[0] );
                if ( result == noErr )
                {
                    // Get the ancestor directory names
                    pb.dirInfo.ioNamePtr = tempSpec.name;
                    pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
                    pb.dirInfo.ioDrParID = tempSpec.parID;

                    // loop until we have an error or find the root directory
                    do
                    {
                        pb.dirInfo.ioFDirIndex = -1;
                        pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
                        result = PBGetCatInfoSync(&pb);
                        if ( result == noErr )
                        {
                            // Append colon to directory name
                            ++tempSpec.name[0];
                            tempSpec.name[tempSpec.name[0]] = ':';

                            // Add directory name to beginning of fullPath
                            (void)Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
                            result = MemError();
                        }
                    }
                    while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
                }
            }
        }
    }

    if ( result == noErr )
    {
        // Return the length
        *fullPathLength = GetHandleSize( *fullPath );
        result = realResult;  // return realResult in case it was fnfErr
    }
    else
    {
        // Dispose of the handle and return NULL and zero length
        if ( *fullPath != NULL )
        {
            DisposeHandle( *fullPath );
           *fullPath = NULL;
        }
        *fullPathLength = 0;
    }

    return result;
}

//
// On the mac there are two ways to open a file - one is through apple events and the
// finder, another is through mime types.
//
// So, really there are two ways to implement wxFileType...
//
// Mime types are only available on OS 8.1+ through the InternetConfig API
//
// Much like the old-style file manager, it has 3 levels of flexibility for its methods -
// Low - which means you have to iterate yourself through the mime database
// Medium - which lets you sort of cache the database if you want to use lowlevel functions
// High - which requires access to the database every time
//
// We want to be efficient (i.e. professional :) ) about it, so we use a combo of low
// and mid-level functions
//
// TODO: Should we call ICBegin/ICEnd?  Then where?
//

// debug helper
inline void wxLogMimeDebug(const wxChar* szMsg, OSStatus status)
{
    wxLogDebug(wxString::Format(wxT("%s  LINE:%i  OSERROR:%i"), szMsg, __LINE__, (int)status));
}

// in case we're compiling in non-GUI mode
class WXDLLEXPORT wxIcon;

bool wxFileTypeImpl::SetCommand(const wxString& cmd, const wxString& verb, bool overwriteprompt)
{
    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );

    return false;
}

bool wxFileTypeImpl::SetDefaultIcon(const wxString& strIcon, int index)
{
    wxASSERT_MSG( m_manager != NULL , wxT("Bad wxFileType") );

    return false;
}

bool wxFileTypeImpl::GetOpenCommand(wxString *openCmd,
                               const wxFileType::MessageParameters& params) const
{
    wxString cmd = GetCommand(wxT("open"));

    *openCmd = wxFileType::ExpandCommand(cmd, params);

    return !openCmd->empty();
}

bool
wxFileTypeImpl::GetPrintCommand(
    wxString *printCmd,
    const wxFileType::MessageParameters& params) const
{
    wxString cmd = GetCommand(wxT("print"));

    *printCmd = wxFileType::ExpandCommand(cmd, params);

    return !printCmd->empty();
}

//
// Internet Config vs. Launch Services
//
// From OS 8 on there was internet config...
// However, OSX and its finder does not use info
// from Internet Config at all - the Internet Config
// database ONLY CONTAINS APPS THAT ARE CLASSIC APPS
// OR REGISTERED THROUGH INTERNET CONFIG
//
// Therefore on OSX in order for the open command to be useful
// we need to go straight to launch services
//

#if defined(__DARWIN__)

//on darwin, use launch services

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -