/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1999 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ #include "nsIServiceManager.h" #include "nsIPlatformCharset.h" #include "nsICharsetConverterManager.h" #include "nsIUnicodeEncoder.h" #include "nsIUnicodeDecoder.h" #include "nsIUnicodeEncoder.h" #include "nsIUnicodeDecoder.h" /* nsFileSpec stuff. put here untill it got obsoleted */ #include "nsFileSpec.h" #ifdef XP_PC #include "nsLocalFileWin.h" #endif #ifdef XP_MAC #include "nsLocalFileMac.h" #endif #if defined(XP_UNIX) || defined(XP_BEOS) #include "nsLocalFileUnix.h" #endif #include "nsString.h" #include "nsCOMPtr.h" class nsFSStringConversion { public: nsFSStringConversion(); virtual ~nsFSStringConversion(){}; NS_IMETHOD UCSToNewFS( const PRUnichar* aIn, char** aOut); NS_IMETHOD FSToNewUCS( const char* aIn, PRUnichar** aOut); private: NS_IMETHOD PrepareFSCharset(); NS_IMETHOD PrepareEncoder(); NS_IMETHOD PrepareDecoder(); nsAutoString mFSCharset; nsCOMPtr mEncoder; nsCOMPtr mDecoder; }; #define GET_UCS( func , arg) \ { \ char* tmp; \ nsresult res; \ if(NS_SUCCEEDED(res = (func)(&tmp))) { \ if(NS_SUCCEEDED(res = gConverter.FSToNewUCS(tmp, (arg)))){ \ nsAllocator::Free(tmp); \ } \ } \ return res; \ } #define VOID_SET_UCS( func , arg, assertion_msg) \ { \ char* tmp; \ nsresult res; \ if(NS_SUCCEEDED(res = gConverter.UCSToNewFS((arg), &tmp))) { \ (func)(tmp); \ nsAllocator::Free(tmp); \ } \ NS_ASSERTION(NS_SUCCEEDED(res), assertion_msg); \ } #define SET_UCS( func , arg) \ { \ char* tmp; \ nsresult res; \ if(NS_SUCCEEDED(res = gConverter.UCSToNewFS((arg), &tmp))) { \ res = (func)(tmp); \ nsAllocator::Free(tmp); \ } \ return res; \ } #define SET_UCS_2ARGS_2( func , arg1, arg2) \ { \ char* tmp; \ nsresult res; \ if(NS_SUCCEEDED(res = gConverter.UCSToNewFS((arg2), &tmp))){ \ res = (func)(arg1, tmp); \ nsAllocator::Free(tmp); \ } \ return res; \ } #define SET_UCS_2ARGS_1( func , arg1, arg2) \ { \ char* tmp; \ nsresult res; \ if(NS_SUCCEEDED(res = gConverter.UCSToNewFS((arg1), &tmp))){ \ res = (func)(tmp, arg2); \ nsAllocator::Free(tmp); \ } \ return res; \ } nsFSStringConversion gConverter; nsFSStringConversion::nsFSStringConversion() : mFSCharset("") { mEncoder = nsnull; mDecoder = nsnull; } NS_IMETHODIMP nsFSStringConversion::PrepareFSCharset() { nsresult res = NS_OK; if(mFSCharset.Length() == 0) { // lazy eval of the file system charset NS_WITH_SERVICE(nsIPlatformCharset, pcharset, NS_PLATFORMCHARSET_PROGID, &res); NS_ASSERTION((NS_SUCCEEDED(res) && (nsnull != pcharset)), "cannot get platform charset"); if(NS_SUCCEEDED(res) && (nsnull != pcharset)) { res = pcharset->GetCharset(kPlatformCharsetSel_FileName, mFSCharset); } } return res; } NS_IMETHODIMP nsFSStringConversion::PrepareEncoder() { nsresult res = NS_OK; if(nsnull == mEncoder) { res = PrepareFSCharset(); if(NS_SUCCEEDED(res)) { NS_WITH_SERVICE(nsICharsetConverterManager, ucmgr, NS_CHARSETCONVERTERMANAGER_PROGID, &res); NS_ASSERTION((NS_SUCCEEDED(res) && (nsnull != ucmgr)), "cannot get charset converter manager "); if(NS_SUCCEEDED(res) && (nsnull != ucmgr)) res = ucmgr->GetUnicodeEncoder( &mFSCharset, getter_AddRefs(mEncoder)); NS_ASSERTION((NS_SUCCEEDED(res) && (nsnull != mEncoder)), "cannot find the unicode encoder"); } } return res; } NS_IMETHODIMP nsFSStringConversion::PrepareDecoder() { nsresult res = NS_OK; if(nsnull == mDecoder) { res = PrepareFSCharset(); if(NS_SUCCEEDED(res)) { NS_WITH_SERVICE(nsICharsetConverterManager, ucmgr, NS_CHARSETCONVERTERMANAGER_PROGID, &res); NS_ASSERTION((NS_SUCCEEDED(res) && (nsnull != ucmgr)), "cannot get charset converter manager "); if(NS_SUCCEEDED(res) && (nsnull != ucmgr)) res = ucmgr->GetUnicodeDecoder( &mFSCharset, getter_AddRefs(mDecoder)); NS_ASSERTION((NS_SUCCEEDED(res) && (nsnull != mDecoder)), "cannot find the unicode decoder"); } } return res; } NS_IMETHODIMP nsFSStringConversion::UCSToNewFS( const PRUnichar* aIn, char** aOut) { nsresult res = PrepareEncoder(); if(NS_SUCCEEDED(res)) { PRInt32 inLength = nsCRT::strlen(aIn); PRInt32 outLength; res= mEncoder->GetMaxLength(aIn, inLength,&outLength); if(NS_SUCCEEDED(res)) { *aOut = (char*)nsAllocator::Alloc(outLength+1); if(nsnull != aOut) { res = mEncoder->Convert(aIn, &inLength, *aOut, &outLength); if(NS_SUCCEEDED(res)) { (*aOut)[outLength] = '\0'; } else { nsAllocator::Free(*aOut); aOut = nsnull; } } else { res = NS_ERROR_OUT_OF_MEMORY; } } } return res; } NS_IMETHODIMP nsFSStringConversion::FSToNewUCS( const char* aIn, PRUnichar** aOut) { nsresult res = PrepareDecoder(); if(NS_SUCCEEDED(res)) { PRInt32 inLength = nsCRT::strlen(aIn); PRInt32 outLength; res= mDecoder->GetMaxLength(aIn, inLength,&outLength); if(NS_SUCCEEDED(res)) { *aOut = (PRUnichar*)nsAllocator::Alloc(2*(outLength+1)); if(nsnull != aOut) { res = mDecoder->Convert(aIn, &inLength, *aOut, &outLength); if(NS_SUCCEEDED(res)) { (*aOut)[outLength] = '\0'; } else { nsAllocator::Free(*aOut); aOut = nsnull; } } else { res = NS_ERROR_OUT_OF_MEMORY; } } } return res; } // Unicode interface Wrapper NS_IMETHODIMP nsLocalFile::InitWithUnicodePath(const PRUnichar *filePath) { SET_UCS(InitWithPath, filePath); } NS_IMETHODIMP nsLocalFile::AppendUnicode(const PRUnichar *node) { SET_UCS( Append , node); } NS_IMETHODIMP nsLocalFile::GetUnicodeLeafName(PRUnichar **aLeafName) { GET_UCS(GetLeafName, aLeafName); } NS_IMETHODIMP nsLocalFile::SetUnicodeLeafName(const PRUnichar * aLeafName) { SET_UCS( SetLeafName , aLeafName); } NS_IMETHODIMP nsLocalFile::GetUnicodePath(PRUnichar **_retval) { GET_UCS(GetPath, _retval); } NS_IMETHODIMP nsLocalFile::CopyToUnicode(nsIFile *newParentDir, const PRUnichar *newName) { SET_UCS_2ARGS_2( CopyTo , newParentDir, newName); } NS_IMETHODIMP nsLocalFile::CopyToFollowingLinksUnicode(nsIFile *newParentDir, const PRUnichar *newName) { SET_UCS_2ARGS_2( CopyToFollowingLinks , newParentDir, newName); } NS_IMETHODIMP nsLocalFile::MoveToUnicode(nsIFile *newParentDir, const PRUnichar *newName) { SET_UCS_2ARGS_2( MoveTo , newParentDir, newName); } NS_IMETHODIMP nsLocalFile::GetUnicodeTarget(PRUnichar **_retval) { GET_UCS(GetTarget, _retval); } nsresult NS_NewUnicodeLocalFile(const PRUnichar* path, nsILocalFile* *result) { SET_UCS_2ARGS_1( NS_NewLocalFile , path, result) } // ================================================================== // nsFileSpec stuff . put here untill nsFileSpec get obsoleted // ================================================================== void nsFileSpec::operator = (const nsString& inNativePath) { char* tmp; nsresult res; if(NS_SUCCEEDED(res = gConverter.UCSToNewFS((inNativePath.GetUnicode()), &tmp))) { *this = tmp; nsAllocator::Free(tmp); } mError = res; NS_ASSERTION(NS_SUCCEEDED(res), "nsFileSpec = filed"); } nsFileSpec nsFileSpec::operator + (const nsString& inRelativeUnixPath) const { nsFileSpec resultSpec; char* tmp; nsresult res; if(NS_SUCCEEDED(res = gConverter.UCSToNewFS((inRelativeUnixPath.GetUnicode()), &tmp))) { resultSpec = *this; resultSpec += tmp; nsAllocator::Free(tmp); } NS_ASSERTION(NS_SUCCEEDED(res), "nsFileSpec + filed"); return resultSpec; } void nsFileSpec::operator += (const nsString& inRelativeUnixPath) { char* tmp; nsresult res; if(NS_SUCCEEDED(res = gConverter.UCSToNewFS((inRelativeUnixPath.GetUnicode()), &tmp))) { *this += tmp; nsAllocator::Free(tmp); } mError = res; NS_ASSERTION(NS_SUCCEEDED(res), "nsFileSpec + filed"); } void nsFileSpec::SetLeafName (const nsString& inLeafName) { VOID_SET_UCS( SetLeafName , inLeafName.GetUnicode(),"nsFileSpec::SetLeafName failed"); } void nsFileSpec::MakeUnique(const nsString& inSuggestedLeafName) { VOID_SET_UCS( MakeUnique,inSuggestedLeafName.GetUnicode(),"nsFileSpec::MakeUnique failed"); } nsresult nsFileSpec::Rename(const nsString& inNewName) { SET_UCS( Rename , inNewName.GetUnicode()); } nsresult nsFileSpec::Execute(const nsString& args) const { SET_UCS( Execute , args.GetUnicode()); }