Hi Robert,

I'm not very sure about this, but it seems the OSG_USE_UTF8_FILENAME option was 
designed for Windows builds. Am I wrong?
Anyway, A recent build reported that it doesn't compile under Linux. Here are 
the changes that are supposed to make it work.

Can you confirm that it looks correct to you?
(Changes trunk rev 12264)

Cheers,

Sukender
PVLE - Lightweight cross-platform game engine - http://pvle.sourceforge.net/
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/

// handle TCHAR type on various platforms
// #ifndef is inspired by https://svn.apache.org/repos/asf/logging/log4cxx/tags/v0_9_4/include/log4cxx/helpers/tchar.h
// defining type as plain char is from unzip.h, line 64

#ifndef TCHAR
typedef char TCHAR;
#endif


// currently this impl is for _all_ platforms, except as defined.
// the mac version will change soon to reflect the path scheme under osx, but
// for now, the above include is commented out, and the below code takes precedence.

#if defined(WIN32) && !defined(__CYGWIN__)
    #include <io.h>
    #define WINBASE_DECLARE_GET_MODULE_HANDLE_EX
    #include <windows.h>
    #include <winbase.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <direct.h> // for _mkdir
    
    #define mkdir(x,y) _mkdir((x))
    #define stat64 _stati64

    // set up for windows so acts just like unix access().
#ifndef F_OK
    #define F_OK 4
#endif

#else // unix

#if defined( __APPLE__ )
    // I'm not sure how we would handle this in raw Darwin
    // without the AvailablilityMacros.
    #include <AvailabilityMacros.h>

    //>OSG_IOS
    //IOS includes
    #include "TargetConditionals.h"
    
    #if (TARGET_OS_IPHONE) 
        #include <Availability.h>
        // workaround a bug which appears when compiling for SDK < 4.0 and for the simulator
        #ifdef __IPHONE_4_0 && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0)
            #define stat64 stat
        #else 
            #if !TARGET_IPHONE_SIMULATOR
                #define stat64 stat
            #endif
        #endif
    #endif
    //<OSG_IPHONE

    // 10.5 defines stat64 so we can't use this #define
    // By default, MAC_OS_X_VERSION_MAX_ALLOWED is set to the latest
    // system the headers know about. So I will use this as the control
    // variable. (MIN_ALLOWED is set low by default so it is 
    // unhelpful in this case.) 
    // Unfortunately, we can't use the label MAC_OS_X_VERSION_10_4
    // for older OS's like Jaguar, Panther since they are not defined,
    // so I am going to hardcode the number.
    #if (MAC_OS_X_VERSION_MAX_ALLOWED <= 1040)
        #define stat64 stat
    #endif
#elif defined(__CYGWIN__) || defined(__FreeBSD__) || (defined(__hpux) && !defined(_LARGEFILE64_SOURCE))
    #define stat64 stat
#endif

    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
#endif

    // set up _S_ISDIR()
#if !defined(S_ISDIR)
#  if defined( _S_IFDIR) && !defined( __S_IFDIR)
#    define __S_IFDIR _S_IFDIR
#  endif
#  define S_ISDIR(mode)    (mode&__S_IFDIR)
#endif

#include <osg/Config>
#include <osgDB/ConvertUTF>
#include <osg/Notify>

#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>

#include <errno.h>
#include <string.h>

#include <stack>

namespace osgDB
{
#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
#define OSGDB_STRING_TO_FILENAME(s) osgDB::convertUTF8toUTF16(s)
#define OSGDB_FILENAME_TO_STRING(s) osgDB::convertUTF16toUTF8(s)
#define OSGDB_FILENAME_TEXT(x) L ## x
#define OSGDB_WINDOWS_FUNCT(x) x ## W
#define OSGDB_WINDOWS_FUNCT_STRING(x) #x "W"
typedef wchar_t filenamechar;
typedef std::wstring filenamestring;
#else
#define OSGDB_STRING_TO_FILENAME(s) s
#define OSGDB_FILENAME_TO_STRING(s) s
#define OSGDB_FILENAME_TEXT(x) x
#define OSGDB_WINDOWS_FUNCT(x) x ## A
#define OSGDB_WINDOWS_FUNCT_STRING(x) #x "A"
typedef char filenamechar;
typedef std::string filenamestring;
#endif
}

FILE* osgDB::fopen(const char* filename, const char* mode)
{
#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
    return ::_wfopen(convertUTF8toUTF16(filename).c_str(), convertUTF8toUTF16(mode).c_str());
#else
    return ::fopen(filename, mode);
#endif
}

bool osgDB::makeDirectory( const std::string &path )
{
    if (path.empty())
    {
        OSG_DEBUG << "osgDB::makeDirectory(): cannot create an empty directory" << std::endl;
        return false;
    }
    
    struct stat64 stbuf;
#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
    if( _wstat64( OSGDB_STRING_TO_FILENAME(path).c_str(), &stbuf ) == 0 )
#else
    if( stat64( path.c_str(), &stbuf ) == 0 )
#endif
    {
        if( S_ISDIR(stbuf.st_mode))
            return true;
        else
        {
            OSG_DEBUG << "osgDB::makeDirectory(): "  <<
                    path << " already exists and is not a directory!" << std::endl;
            return false;
        }
    }

    std::string dir = path;
    std::stack<std::string> paths;
    while( true )
    {
        if( dir.empty() )
            break;
 
#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
        if( _wstat64( OSGDB_STRING_TO_FILENAME(dir).c_str(), &stbuf ) < 0 )
#else
        if( stat64( dir.c_str(), &stbuf ) < 0 )
#endif
        {
            switch( errno )
            {
                case ENOENT:
                case ENOTDIR:
                    paths.push( dir );
                    break;
 
                default:
                    OSG_DEBUG << "osgDB::makeDirectory(): "  << strerror(errno) << std::endl;
                    return false;
            }
        }
        dir = getFilePath(std::string(dir));
    }

    while( !paths.empty() )
    {
        std::string dir = paths.top();
 
        #if defined(WIN32)
            //catch drive name
            if (dir.size() == 2 && dir.c_str()[1] == ':') {
                paths.pop();
                continue;
            }
        #endif

#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
        if ( _wmkdir(OSGDB_STRING_TO_FILENAME(dir).c_str())< 0 )
#else
        if( mkdir( dir.c_str(), 0755 )< 0 )
#endif
        {
            OSG_DEBUG << "osgDB::makeDirectory(): "  << strerror(errno) << std::endl;
            return false;
        } 
        paths.pop();
    }
    return true;
}

bool osgDB::makeDirectoryForFile( const std::string &path )
{
    return makeDirectory( getFilePath( path ));
}


std::string osgDB::getCurrentWorkingDirectory( void )
{
    // MAX_PATH/cwd inspired by unzip.cpp
#ifndef MAX_PATH
    #define MAX_PATH 1024
#endif
    TCHAR rootdir[MAX_PATH];
    if(getcwd(rootdir,MAX_PATH-1))
    {
        return(rootdir);
    }
    return("");
}// osgDB::getCurrentWorkingDirectory



bool osgDB::setCurrentWorkingDirectory( const std::string &newCurrentWorkingDirectory )
{
    if (newCurrentWorkingDirectory.empty())
    {
        OSG_DEBUG << "osgDB::setCurrentWorkingDirectory(): called with empty string." << std::endl;
        return false;
    }
    
#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
    return _wchdir( OSGDB_STRING_TO_FILENAME(newCurrentWorkingDirectory).c_str()) == 0;
#else
    return chdir( newCurrentWorkingDirectory.c_str()) == 0;
#endif

    return true;
} // osgDB::setCurrentWorkingDirectory



void osgDB::convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath)
{
#if defined(WIN32) && !defined(__CYGWIN__)
    char delimitor = ';';
#else
    char delimitor = ':';
#endif

    if (!paths.empty())
    {
        std::string::size_type start = 0;
        std::string::size_type end;
        while ((end = paths.find_first_of(delimitor,start))!=std::string::npos)
        {
            filepath.push_back(std::string(paths,start,end-start));
            start = end+1;
        }

        std::string lastPath(paths,start,std::string::npos);
        if (!lastPath.empty())
            filepath.push_back(lastPath);
    }
 
}

bool osgDB::fileExists(const std::string& filename)
{
#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
    return _waccess( OSGDB_STRING_TO_FILENAME(filename).c_str(), F_OK ) == 0;
#else
    return access( filename.c_str(), F_OK ) == 0;
#endif
}

osgDB::FileType osgDB::fileType(const std::string& filename)
{
    struct stat64 fileStat;
#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
    if ( _wstat64(OSGDB_STRING_TO_FILENAME(filename).c_str(), &fileStat) != 0 )
#else
    if ( stat64(filename.c_str(), &fileStat) != 0 )
#endif
    {
        return FILE_NOT_FOUND;
    } // end if

    if ( fileStat.st_mode & S_IFDIR )
        return DIRECTORY;
    else if ( fileStat.st_mode & S_IFREG )
        return REGULAR_FILE;

    return FILE_NOT_FOUND;
}

std::string osgDB::findFileInPath(const std::string& filename, const FilePathList& filepath,CaseSensitivity caseSensitivity)
{
    if (filename.empty()) 
        return filename;

    if (!isFileNameNativeStyle(filename)) 
        return findFileInPath(convertFileNameToNativeStyle(filename), filepath, caseSensitivity);


    for(FilePathList::const_iterator itr=filepath.begin();
        itr!=filepath.end();
        ++itr)
    {
        OSG_DEBUG << "itr='" <<*itr<< "'\n";
        std::string path = itr->empty() ? filename : concatPaths(*itr, filename);
        
        path = getRealPath(path);

        OSG_DEBUG << "FindFileInPath() : trying " << path << " ...\n";
        if(fileExists(path)) 
        {
            OSG_DEBUG << "FindFileInPath() : USING " << path << "\n";
            return path;
        }
#ifndef WIN32 
// windows already case insensitive so no need to retry..
        else if (caseSensitivity==CASE_INSENSITIVE) 
        {
            std::string foundfile = findFileInDirectory(filename,*itr,CASE_INSENSITIVE);
            if (!foundfile.empty()) return foundfile;
        }
#endif
            
    }

    return std::string();
}


std::string osgDB::findDataFile(const std::string& filename,CaseSensitivity caseSensitivity)
{
    return findDataFile(filename,static_cast<Options*>(0),caseSensitivity);
}

OSGDB_EXPORT std::string osgDB::findDataFile(const std::string& filename,const Options* options, CaseSensitivity caseSensitivity)
{
    return Registry::instance()->findDataFile(filename, options, caseSensitivity);
}

std::string osgDB::findLibraryFile(const std::string& filename,CaseSensitivity caseSensitivity)
{
    return Registry::instance()->findLibraryFile(filename, osgDB::Registry::instance()->getOptions(), caseSensitivity);
}

std::string osgDB::findFileInDirectory(const std::string& fileName,const std::string& dirName,CaseSensitivity caseSensitivity)
{
    bool needFollowingBackslash = false;
    bool needDirectoryName = true;
    osgDB::DirectoryContents dc;

    std::string realDirName = dirName;
    std::string realFileName = fileName;

    // Skip case-insensitive recursion if on Windows
    #ifdef WIN32
        bool win32 = true;
    #else
        bool win32 = false;
    #endif
    
    // If the fileName contains extra path information, make that part of the
    // directory name instead
    if (fileName != getSimpleFileName(fileName))
    {
        // See if we need to add a slash between the directory and file
        if (realDirName.empty())
        {
            realDirName = getFilePath(fileName);
        }
        else if (realDirName=="." || realDirName=="./" || realDirName==".\\")
        {
            realDirName = "./" + getFilePath(fileName);
        }
        else
        {
            char lastChar = dirName[dirName.size()-1];
            if ((lastChar == '/') || (lastChar == '\\'))
                realDirName = dirName + getFilePath(fileName);
            else
                realDirName = dirName + "/" + getFilePath(fileName);
        }

        // Simplify the file name
        realFileName = getSimpleFileName(fileName);
    }

    OSG_DEBUG << "findFileInDirectory() : looking for " << realFileName << " in " << realDirName << "...\n";

    if (realDirName.empty())
    {
        dc = osgDB::getDirectoryContents(".");
        needFollowingBackslash = false;
        needDirectoryName = false;
    }
    else if (realDirName=="." || realDirName=="./" || realDirName==".\\")
    {
        dc = osgDB::getDirectoryContents(".");
        needFollowingBackslash = false;
        needDirectoryName = false;
    }
    else if (realDirName=="/")
    {
        dc = osgDB::getDirectoryContents("/");
        needFollowingBackslash = false;
        needDirectoryName = true;
    }
    else
    {
        // See if we're working in case insensitive mode, and that we're not
        // using Windows (the recursive search is not needed in these
        // cases)
        if ((caseSensitivity == CASE_INSENSITIVE) && (!win32))
        {
            // Split the last path element from the directory name
            std::string parentPath = getFilePath(realDirName);
            std::string lastElement = getSimpleFileName(realDirName);

            // See if we're already at the top level of the filesystem
            if ((parentPath.empty()) && (!lastElement.empty()))
            {
                std::string directoryStringToUse = (realDirName[0]=='/' || realDirName[0]=='\\') ? std::string("/") : std::string(".");

                // Search for the first path element (ignoring case) in
                // the top-level directory
                realDirName = findFileInDirectory(lastElement, directoryStringToUse,
                                                  CASE_INSENSITIVE);

                dc = osgDB::getDirectoryContents(realDirName);
                needFollowingBackslash = true;
                needDirectoryName = true;
            }
            else
            {
                // Recursively search for the last path element (ignoring case)
                // in the parent path
                realDirName = findFileInDirectory(lastElement, parentPath,
                                                  CASE_INSENSITIVE);
      
                dc = osgDB::getDirectoryContents(realDirName);
                char lastChar = realDirName[realDirName.size()-1];
                if (lastChar=='/') needFollowingBackslash = false;
                else if (lastChar=='\\') needFollowingBackslash = false;
                else needFollowingBackslash = true;
                needDirectoryName = true;
            }
        }
        else
        {
            // No need for recursive search if we're doing an exact comparison
            dc = osgDB::getDirectoryContents(realDirName);
            char lastChar = realDirName[realDirName.size()-1];
            if (lastChar=='/') needFollowingBackslash = false;
            else if (lastChar=='\\') needFollowingBackslash = false;
            else needFollowingBackslash = true;
            needDirectoryName = true;
        }
    }

    for(osgDB::DirectoryContents::iterator itr=dc.begin();
        itr!=dc.end();
        ++itr)
    {
        if ((caseSensitivity==CASE_INSENSITIVE && osgDB::equalCaseInsensitive(realFileName,*itr)) ||
            (realFileName==*itr))
        {
            if (!needDirectoryName) return *itr;
            else if (needFollowingBackslash) return realDirName+'/'+*itr;
            else return realDirName+*itr;
        }
    }
    return "";
}

static void appendInstallationLibraryFilePaths(osgDB::FilePathList& filepath)
{
#ifdef OSG_DEFAULT_LIBRARY_PATH

    // Append the install prefix path to the library search path if configured
    filepath.push_back(ADDQUOTES(OSG_DEFAULT_LIBRARY_PATH));
#endif
}

#if defined(WIN32) && !defined(__CYGWIN__)
    #include <io.h>
    #include <direct.h>

    osgDB::DirectoryContents osgDB::getDirectoryContents(const std::string& dirName)
    {
        osgDB::DirectoryContents contents;

        OSGDB_WINDOWS_FUNCT(WIN32_FIND_DATA) data;
        HANDLE handle = OSGDB_WINDOWS_FUNCT(FindFirstFile)((OSGDB_STRING_TO_FILENAME(dirName) + OSGDB_FILENAME_TEXT("\\*")).c_str(), &data);
        if (handle != INVALID_HANDLE_VALUE)
        {
            do
            {
                contents.push_back(OSGDB_FILENAME_TO_STRING(data.cFileName));
            }
            while (OSGDB_WINDOWS_FUNCT(FindNextFile)(handle, &data) != 0);

            FindClose(handle);
        }
        return contents;
    }

#else

    #include <dirent.h>
    osgDB::DirectoryContents osgDB::getDirectoryContents(const std::string& dirName)
    {
        osgDB::DirectoryContents contents;

        DIR *handle = opendir(dirName.c_str());
        if (handle)
        {
            dirent *rc;
            while((rc = readdir(handle))!=NULL)
            {
                contents.push_back(rc->d_name);
            }
            closedir(handle);
        }

        return contents;
    }

#endif // unix getDirectoryContexts


osgDB::DirectoryContents osgDB::expandWildcardsInFilename(const std::string& filename)
{
    osgDB::DirectoryContents contents;

    std::string dir = osgDB::getFilePath(filename);
    std::string filenameOnly = filename.substr(dir.length(), std::string::npos);
    std::string left = filenameOnly.substr(0, filenameOnly.find('*'));
    std::string right = filenameOnly.substr(filenameOnly.find('*')+1, std::string::npos);

    if (dir.empty())
        dir = osgDB::getCurrentWorkingDirectory();

    osgDB::DirectoryContents dirContents = osgDB::getDirectoryContents(dir);
    for (unsigned int i = 0; i < dirContents.size(); ++i)
    {
        std::string filenameInDir = dirContents[i];

        if (filenameInDir == "." ||
            filenameInDir == "..")
        {
            continue;
        }

        if ((filenameInDir.find(left) == 0 || left.empty()) &&
            (filenameInDir.find(right) == filenameInDir.length() - right.length() || right.empty()))
        {
            contents.push_back( dir + osgDB::getNativePathSeparator() + filenameInDir );
        }
    }

    return contents;
}

osgDB::FileOpResult::Value osgDB::copyFile(const std::string & source, const std::string & destination)
{
    if (source.empty() || destination.empty())
    {
        OSG_INFO << "copyFile(): Empty file name." << std::endl;
        return FileOpResult::BAD_ARGUMENT;
    }

    // Check if source and destination are the same
    if (source == destination || osgDB::getRealPath(source) == osgDB::getRealPath(destination))
    {
        OSG_INFO << "copyFile(): Source and destination point to the same file: source=" << source << ", destination=" << destination << std::endl;
        return FileOpResult::SOURCE_EQUALS_DESTINATION;
    }

    // Check if source file exists
    if (!osgDB::fileExists(source))
    {
        OSG_INFO << "copyFile(): Source file does not exist: " << source << std::endl;
        return FileOpResult::SOURCE_MISSING;
    }

    // Open source file
    osgDB::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
    if (!fin)
    {
        OSG_NOTICE << "copyFile(): Can't read source file: " << source << std::endl;
        return FileOpResult::SOURCE_NOT_OPENED;        // Return success since it's not an output error.
    }

    // Ensure the directory exists or else the FBX SDK will fail
    if (!osgDB::makeDirectoryForFile(destination))
    {
        OSG_INFO << "Can't create directory for file '" << destination << "'. Copy may fail creating the file." << std::endl;
    }

    // Open destination file
    osgDB::ofstream fout(destination.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
    if (!fout)
    {
        OSG_NOTICE << "copyFile(): Can't write destination file: " << destination << std::endl;
        return FileOpResult::DESTINATION_NOT_OPENED;
    }

    // Copy file
    const unsigned int BUFFER_SIZE = 10240;
    osgDB::ifstream::char_type buffer[BUFFER_SIZE];
    for(; fin.good() && fout.good() && !fin.eof(); )
    {
        fin.read(buffer, BUFFER_SIZE);
        fout.write(buffer, fin.gcount());
    }

    if (!fout.good())
    {
        OSG_NOTICE << "copyFile(): Error writing destination file: " << destination << std::endl;
        return FileOpResult::WRITE_ERROR;
    }

    if (!fin.eof())
    {
        OSG_NOTICE << "copyFile(): Error reading source file: " << source << std::endl;
        return FileOpResult::READ_ERROR;
    }

    return FileOpResult::OK;
}


/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Implementation of appendPlatformSpecificLibraryFilePaths(..)
//
#ifdef __sgi

    void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
    {
        convertStringPathIntoFilePathList("/usr/lib32/:/usr/local/lib32/",filepath);

        // bloody mess see rld(1) man page
        char* ptr;

        #if (_MIPS_SIM == _MIPS_SIM_ABI32)
        if( (ptr = getenv( "LD_LIBRARY_PATH" )))
        {
            convertStringPathIntoFilePathList(ptr,filepath);
        }

        #elif (_MIPS_SIM == _MIPS_SIM_NABI32)

        if( !(ptr = getenv( "LD_LIBRARYN32_PATH" )))
            ptr = getenv( "LD_LIBRARY_PATH" );

        if( ptr )
        {
            convertStringPathIntoFilePathList(ptr,filepath);
        }

        #elif (_MIPS_SIM == _MIPS_SIM_ABI64)

        if( !(ptr = getenv( "LD_LIBRARY64_PATH" )))
            ptr = getenv( "LD_LIBRARY_PATH" );

        if( ptr )
        {
            convertStringPathIntoFilePathList(ptr,filepath);
        }
        #endif

        appendInstallationLibraryFilePaths(filepath);
    }


#elif defined(__CYGWIN__)

    void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
    {
        char* ptr;
        if ((ptr = getenv( "PATH" )))
        {
            convertStringPathIntoFilePathList(ptr,filepath);
        }

        appendInstallationLibraryFilePaths(filepath);

        convertStringPathIntoFilePathList("/usr/bin/:/usr/local/bin/",filepath);
    }
    
#elif defined(WIN32)

    void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
    {
        // See http://msdn2.microsoft.com/en-us/library/ms682586.aspx

        // Safe DLL search mode changes the DLL search order to search for 
        // DLLs in the current directory after the system directories, instead
        // of right after the application's directory. According to the article 
        // linked above, on Windows XP and Windows 2000, Safe DLL search mode 
        // is disabled by default. However, it is a good idea to enable it. We 
        // will search as if it was enabled.

        // So if SafeDllSearchMode is enabled, the search order is as follows:

        //   1. The directory from which the application loaded.
        DWORD retval = 0;
        const DWORD size = MAX_PATH;
        filenamechar path[size];
        retval = OSGDB_WINDOWS_FUNCT(GetModuleFileName)(NULL, path, size);
        if (retval != 0 && retval < size)
        {
            filenamestring pathstr(path);
            filenamestring executableDir(pathstr, 0, 
                                      pathstr.find_last_of(OSGDB_FILENAME_TEXT("\\/")));
            convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(executableDir), filepath);
        }
        else
        {
            OSG_WARN << "Could not get application directory "
                "using Win32 API. It will not be searched." << std::endl;
        }

        //   2. The directory that the dll that contains this function is in.
        // For static builds, this will be the executable directory.

        #if defined(_MSC_VER)
            // Requires use of the GetModuleHandleEx() function which is available only on Windows XP or higher.
            // In order to allow execution on older versions, we load the function dynamically from the library and
            // use it only if it's available.
            OSGDB_WINDOWS_FUNCT(PGET_MODULE_HANDLE_EX) pGetModuleHandleEx = reinterpret_cast<OSGDB_WINDOWS_FUNCT(PGET_MODULE_HANDLE_EX)>
                (GetProcAddress( GetModuleHandleA("kernel32.dll"), OSGDB_WINDOWS_FUNCT_STRING(GetModuleHandleEx)));
            if( pGetModuleHandleEx )
            {
                HMODULE thisModule = 0;
                static filenamechar static_variable = 0;    // Variable that is located in DLL address space.

                if( pGetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, &static_variable, &thisModule) )
                {
                    retval = OSGDB_WINDOWS_FUNCT(GetModuleFileName)(thisModule, path, size);
                    if (retval != 0 && retval < size)
                    {
                        filenamestring pathstr(path);
                        filenamestring dllDir(pathstr, 0,
                                                pathstr.find_last_of(OSGDB_FILENAME_TEXT("\\/")));
                        convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(dllDir), filepath);
                    }
                    else
                    {
                        OSG_WARN << "Could not get dll directory "
                            "using Win32 API. It will not be searched." << std::endl;
                    }
                    FreeLibrary(thisModule);
                }
                else
                {
                    OSG_WARN << "Could not get dll module handle "
                        "using Win32 API. Dll directory will not be searched." << std::endl;
                }
            }
        #endif

        //   3. The system directory. Use the GetSystemDirectory function to 
        //      get the path of this directory.
        filenamechar systemDir[(UINT)size];
        retval = OSGDB_WINDOWS_FUNCT(GetSystemDirectory)(systemDir, (UINT)size);

        if (retval != 0 && retval < size)
        {
            convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(systemDir), 
                                              filepath);
        }
        else
        {
            OSG_WARN << "Could not get system directory using "
                "Win32 API, using default directory." << std::endl;
            convertStringPathIntoFilePathList("C:\\Windows\\System32", 
                                              filepath);
        }

        //   4. The 16-bit system directory. There is no function that obtains 
        //      the path of this directory, but it is searched.
        //   5. The Windows directory. Use the GetWindowsDirectory function to 
        //      get the path of this directory.
        filenamechar windowsDir[(UINT)size];
        retval = OSGDB_WINDOWS_FUNCT(GetWindowsDirectory)(windowsDir, (UINT)size);
        if (retval != 0 && retval < size)
        {
            convertStringPathIntoFilePathList(std::string(OSGDB_FILENAME_TO_STRING(windowsDir)) + 
                                              "\\System", filepath);
            convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(windowsDir), 
                                              filepath);
        }
        else
        {
            OSG_WARN << "Could not get Windows directory using "
                "Win32 API, using default directory." << std::endl;
            convertStringPathIntoFilePathList("C:\\Windows", filepath);
            convertStringPathIntoFilePathList("C:\\Windows\\System", filepath);
        }


        //   6. The current directory.
        convertStringPathIntoFilePathList(".", filepath);

        //   7. The directories that are listed in the PATH environment 
        //      variable. Note that this does not include the per-application 
        //      path specified by the App Paths registry key.
        filenamechar* ptr;
#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
        if ((ptr = _wgetenv(OSGDB_FILENAME_TEXT("PATH"))))
#else
        if ((ptr = getenv("PATH")))
#endif
        {
            // Note that on any sane Windows system, some of the paths above
            // will also be on the PATH (the values gotten in systemDir and
            // windowsDir), but the DLL search goes sequentially and stops
            // when a DLL is found, so I see no point in removing duplicates.
            convertStringPathIntoFilePathList(OSGDB_FILENAME_TO_STRING(ptr), filepath);
        }

        appendInstallationLibraryFilePaths(filepath);
    }
    
#elif defined(__APPLE__)
#if (TARGET_OS_IPHONE)
    #define COMPILE_COCOA_VERSION
#else
     #define COMPILE_CARBON_VERSION
#endif
    // WARNING: Cocoa version is currently untested.
    #ifdef COMPILE_COCOA_VERSION
        #include <Foundation/Foundation.h>
    #endif
    #ifdef COMPILE_CARBON_VERSION
        #include <CoreServices/CoreServices.h>
        #include <CoreFoundation/CoreFoundation.h>
        #include <Carbon/Carbon.h>
    #endif
    #include <iostream>
    
    // These functions are local to FileUtils.cpp and not exposed to the API
    // returns the path string except for numToShorten directories stripped off the end
    std::string GetShortenedPath(std::string path, int numToShorten)
    {
        unsigned int i = path.length() - 1;
        if(path[i] == '/') i--;
        while(i > 1 && numToShorten)
        {
            if(path[i] == '/')
                numToShorten--;
            i--;
        }
        return path.substr(0,i + 1);
    }

    // returns an absolute (POSIX on MacOS X) path from a CFURLRef
    std::string GetPathFromCFURLRef(CFURLRef urlRef)
    {
        char buffer[1024];
        std::string path;
        if(CFURLGetFileSystemRepresentation(urlRef, true, (UInt8*)buffer, 1024))
            path = std::string(buffer);
        return path;
    }

    // returns the absolute path to the main bundle
    std::string GetApplicationBundlePath(CFBundleRef mainBundle)
    {
        std::string path;
        CFURLRef urlRef = CFBundleCopyBundleURL(mainBundle);
        if(urlRef)
        {
            path = GetPathFromCFURLRef(urlRef);
            CFRelease(urlRef); // docs say we are responsible for releasing CFURLRef
        }
        return path;
        
    }

    std::string GetApplicationParentPath(CFBundleRef mainBundle)
    {
        return GetShortenedPath(GetApplicationBundlePath(mainBundle), 1);
    }

    std::string GetApplicationPluginsPath(CFBundleRef mainBundle)
    {
        std::string path;
        CFURLRef urlRef = CFBundleCopyBuiltInPlugInsURL(mainBundle);
        if(urlRef)
        {
            path = GetPathFromCFURLRef(urlRef);
            CFRelease(urlRef);
        }
        return path;
        
    }

    std::string GetApplicationResourcesPath(CFBundleRef mainBundle)
    {
        std::string path;
        CFURLRef urlRef = CFBundleCopyResourcesDirectoryURL(mainBundle);
        if(urlRef)
        {
            path = GetPathFromCFURLRef(urlRef);
            CFRelease(urlRef);
        }
        return path;
    }

    // The Cocoa version is about 10 lines of code.
    // The Carbon version is noticably longer.
    // Unfortunately, the Cocoa version requires -lobjc to be 
    // linked in when creating an executable. 
    // Rumor is that this will be done autmatically in gcc 3.5/Tiger,
    // but for now, this will cause a lot of headaches for people
    // who aren't familiar with this concept, so the Carbon version 
    // is preferable.
    // But for the curious, both implementations are here.
    // Note that if the Cocoa version is used, the file should be 
    // renamed to use the .mm extension to denote Objective-C++.
    // And of course, you will need to link against Cocoa
    // Update: There is a bug in the Cocoa version. Advanced users can remap 
    // their systems so these paths go somewhere else. The Carbon calls
    // will catch this, but the hardcoded Cocoa code below will not.

    #ifdef COMPILE_COCOA_VERSION
    // OS X has preferred locations for where PlugIns should be located.
    // This function will set this as the order to search:
    // YourProgram.app/Contents/PlugIns
    // ~/Library/Application Support/OpenSceneGraph/PlugIns
    // /Library/Application Support/OpenSceneGraph/PlugIns
    // /Network/Library/Application Support/OpenSceneGraph/PlugIns
    // 
    // As a side effect of this function, if the application is not a 
    // bundle, the first place searched becomes
    // YourProgram/PlugIns
    //
    // In principle, these other directories should be searched:
    // ~/Library/Application Support/YourProgram/PlugIns
    // /Library/Application Support/YourProgram/PlugIns
    // /Network/Library/Application Support/TheProgram/PlugIns 
    // But I'm not going to worry about it for now because the 
    // bundle's PlugIns directory is supposed to be the preferred 
    // place for this anyway.
    //
    // Another directory that might be worth considering is
    // the directory the program resides in,
    // but I'm worried about multiplatform distribution.
    // Because .so is used by other platforms like Linux, we 
    // could end up loading the wrong binary.
    // I'm not sure how robust the current code is for this case.
    // Assuming the program doesn't crash, will OSG move on to the 
    // next search directory, or just give up?
    void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
    {
        char* ptr;
        if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) )
        {
            convertStringPathIntoFilePathList(ptr, filepath);
        }

        appendInstallationLibraryFilePaths(filepath);

        // Since this is currently the only Objective-C code in the
        // library, we need an autoreleasepool for obj-c memory management.
        // If more Obj-C is added, we might move this pool to another 
        // location so it can be shared. Pools seem to be stackable,
        // so I don't think there will be a problem if multiple pools
        // exist at a time.
        NSAutoreleasePool* mypool = [[NSAutoreleasePool alloc] init];

        NSString* myBundlePlugInPath;
        NSString* userSupportDir;

        // This will grab the "official" bundle plug in path.
        // It will be YourProgram.app/Contents/PlugIns (for App bundles)
        // or YourProgram/PlugIns (for Unix executables)
        myBundlePlugInPath = [[NSBundle mainBundle] builtInPlugInsPath];

        // Now setup the other search paths
        // Cocoa has a nice method for tilde expansion.
        // There's probably a better way of getting this directory, but I 
        // can't find the call.
        userSupportDir = [@"~/Library/Application Support/OpenSceneGraph/PlugIns" stringByExpandingTildeInPath];

        // Can setup the remaining directories directly in C++

        // Since Obj-C and C++ objects don't understand each other,
        // the Obj-C strings must be converted down to C strings so
        // C++ can make them into C++ strings.
        filepath.push_back( [myBundlePlugInPath UTF8String] );
        filepath.push_back( [userSupportDir UTF8String] );

        filepath.push_back( "/Library/Application Support/OpenSceneGraph/PlugIns" );
        filepath.push_back( "/Network/Library/Application Support/OpenSceneGraph/PlugIns" );

        // Clean up the autorelease pool
        [mypool release];
    }

    #elif defined(COMPILE_CARBON_VERSION)

    // OS X has preferred locations for where PlugIns should be located.
    // This function will set this as the order to search:
    // YourProgram.app/Contents/PlugIns
    // ~/Library/Application Support/OpenSceneGraph/PlugIns
    // /Library/Application Support/OpenSceneGraph/PlugIns
    // /Network/Library/Application Support/OpenSceneGraph/PlugIns
    //
    // In principle, these other directories should be searched:
    // ~/Library/Application Support/YourProgram/PlugIns
    // /Library/Application Support/YourProgram/PlugIns
    // /Network/Library/Application Support/TheProgram/PlugIns 
    // But I'm not going to worry about it for now because the 
    // bundle's PlugIns directory is supposed to be the preferred 
    // place for this anyway.
    //
    // Another directory that might be worth considering is
    // the directory the program resides in,
    // but I'm worried about multiplatform distribution.
    // Because .so is used by other platforms like Linux, we 
    // could end up loading the wrong binary.
    // I'm not sure how robust the current code is for this case.
    // Assuming the program doesn't crash, will OSG move on to the 
    // next search directory, or just give up?
    void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
    {
        char* ptr;
        if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) )
        {
            convertStringPathIntoFilePathList(ptr, filepath);
        }

        appendInstallationLibraryFilePaths(filepath);

        const std::string OSG_PLUGIN_PATH("/OpenSceneGraph/PlugIns");
        CFURLRef  url;
        CFBundleRef myBundle;
        FSRef     f;
        OSErr    errCode;

        // Start with the the Bundle PlugIns directory.

        // Get the main bundle first. No need to retain or release it since
        //  we are not keeping a reference
        myBundle = CFBundleGetMainBundle();
        
        if(myBundle != NULL)
        {
            // CFBundleGetMainBundle will return a bundle ref even if 
            //  the application isn't part of a bundle, so we need to check
            //  if the path to the bundle ends in ".app" to see if it is a
            //  proper application bundle. If it is, the plugins path is added
            std::string bundlePath = GetApplicationBundlePath(myBundle);
            if( bundlePath.substr(bundlePath.length() - 4, 4) == std::string(".app") )
                filepath.push_back(GetApplicationPluginsPath(myBundle));
        }
        else
        {
            OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the Application Bundle" << std::endl;
        }

        // Next, check the User's Application Support folder
        errCode = FSFindFolder( kUserDomain, kApplicationSupportFolderType, kDontCreateFolder, &f );
        if(noErr == errCode)
        {
            // Get the URL
            url = CFURLCreateFromFSRef( 0, &f );
            if(url)
            {
                filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH);
                CFRelease( url );
            }
            else
                OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for User's application support Path" << std::endl;

            url = NULL;
        }
        else
        {
            OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the User's Application Support Path" << std::endl;
        }

        // Next, check the Local System's Application Support Folder
        errCode = FSFindFolder( kLocalDomain, kApplicationSupportFolderType, kDontCreateFolder, &f );
        if(noErr == errCode)
        {
            // Get the URL
            url = CFURLCreateFromFSRef( 0, &f );
            
            if(url)
            {
                filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH);
                CFRelease( url );
            }
            else
                OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for local System's ApplicationSupport Path" << std::endl;

            url = NULL;
        }
        else
        {
            OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the Local System's Application Support Path" << std::endl;
        }

        // Finally, check the Network Application Support Folder
        // This one has a likely chance of not existing so an error
        // may be returned. Don't panic.
        errCode = FSFindFolder( kNetworkDomain, kApplicationSupportFolderType, kDontCreateFolder, &f );
        if(noErr == errCode)
        {
            // Get the URL
            url = CFURLCreateFromFSRef( 0, &f );
            
            if(url)
            {
                filepath.push_back(GetPathFromCFURLRef(url) + OSG_PLUGIN_PATH);
                CFRelease( url );
            }
            else
                OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't create CFURLRef for network Application Support Path" << std::endl;

            url = NULL;
        }
        else
        {
        // had to comment out as it segfauls the OSX app otherwise
            // OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the Network Application Support Path" << std::endl;
        }
    }
    #else
    void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
    {
        char* ptr;
        if ((ptr = getenv( "DYLD_LIBRARY_PATH" )) )
        {
            convertStringPathIntoFilePathList(ptr, filepath);
        }

        appendInstallationLibraryFilePaths(filepath);
    }
    #endif
    
#else   

    void osgDB::appendPlatformSpecificLibraryFilePaths(FilePathList& filepath)
    {

       char* ptr;
       if( (ptr = getenv( "LD_LIBRARY_PATH" )) )
        {
            convertStringPathIntoFilePathList(ptr,filepath);
        }

        appendInstallationLibraryFilePaths(filepath);

#if defined(__ia64__) || defined(__x86_64__)
        convertStringPathIntoFilePathList("/usr/lib/:/usr/lib64/:/usr/local/lib/:/usr/local/lib64/",filepath);
#else
        convertStringPathIntoFilePathList("/usr/lib/:/usr/local/lib/",filepath);
#endif

    }

#endif




#ifdef __APPLE__
    void osgDB::appendPlatformSpecificResourceFilePaths(FilePathList& filepath)
    {
        // Get the main application bundle
        CFBundleRef mainBundle = CFBundleGetMainBundle();
        
        if (mainBundle != NULL) {
            // Get the parent directory and the resources directory
            std::string bundlePath = GetApplicationBundlePath(mainBundle);
            std::string resourcesPath = GetApplicationResourcesPath(mainBundle);
            
            // check if application is really part of a .app bundle
            if(bundlePath.substr(bundlePath.length() - 4, 4) == std::string(".app"))
            {
                if(resourcesPath != std::string(""))
                    filepath.push_back( resourcesPath );
                
                std::string parentPath = GetShortenedPath(bundlePath, 1);
                if(parentPath != std::string(""))
                    filepath.push_back( parentPath );
            }
        }
        else
        {
            OSG_NOTIFY( osg::DEBUG_INFO ) << "Couldn't find the Application Bundle." << std::endl;
        }
    }
#else
    void osgDB::appendPlatformSpecificResourceFilePaths(FilePathList& /*filepath*/)
    {
    }
#endif






/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/

#include <osgDB/fstream>
#include <osgDB/ConvertUTF>

#include <osg/Config>

namespace osgDB
{

#if defined(OSG_USE_UTF8_FILENAME) && defined(WIN32) && !defined(__CYGWIN__)
#define OSGDB_CONVERT_UTF8_FILENAME(s) convertUTF8toUTF16(s).c_str()
#else
#define OSGDB_CONVERT_UTF8_FILENAME(s) s
#endif

    fstream::fstream(){}
    fstream::fstream(const char* filename,
        std::ios_base::openmode mode) : std::fstream(OSGDB_CONVERT_UTF8_FILENAME(filename), mode)
    {}
    fstream::~fstream(){}
    void fstream::open(const char* filename,
        std::ios_base::openmode mode)
    {
        std::fstream::open(OSGDB_CONVERT_UTF8_FILENAME(filename), mode);
    }

    ifstream::ifstream(){}
    ifstream::ifstream(const char* filename,
        std::ios_base::openmode mode) : std::ifstream(OSGDB_CONVERT_UTF8_FILENAME(filename), mode)
    {}
    ifstream::~ifstream(){}
    void ifstream::open(const char* filename,
        std::ios_base::openmode mode)
    {
        std::ifstream::open(OSGDB_CONVERT_UTF8_FILENAME(filename), mode);
    }

    ofstream::ofstream(){}
    ofstream::ofstream(const char* filename,
        std::ios_base::openmode mode) : std::ofstream(OSGDB_CONVERT_UTF8_FILENAME(filename), mode)
    {}
    ofstream::~ofstream(){}
    void ofstream::open(const char* filename,
        std::ios_base::openmode mode)
    {
        std::ofstream::open(OSGDB_CONVERT_UTF8_FILENAME(filename), mode);
    }

}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to