From d0afbbaf0e4d06ef91ecef3705fba9f9e9d5f442 Mon Sep 17 00:00:00 2001 From: "darin%netscape.com" Date: Sun, 6 Oct 2002 00:29:46 +0000 Subject: [PATCH] fixes bug 166612 "implement NS_CopyNativeToUnicode / NS_CopyUnicodeToNative on all platforms" r=dougt sr=alecf git-svn-id: svn://10.0.0.236/trunk@131251 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/xpcom/io/nsLocalFileMac.cpp | 193 +--------- mozilla/xpcom/io/nsLocalFileOS2.cpp | 137 ++----- mozilla/xpcom/io/nsLocalFileWin.cpp | 111 ++---- mozilla/xpcom/io/nsNativeCharsetUtils.cpp | 450 +++++++++++++++++++++- mozilla/xpcom/io/nsNativeCharsetUtils.h | 10 +- mozilla/xpcom/macbuild/xpcomPPC.xml | 30 ++ 6 files changed, 536 insertions(+), 395 deletions(-) diff --git a/mozilla/xpcom/io/nsLocalFileMac.cpp b/mozilla/xpcom/io/nsLocalFileMac.cpp index 7d35a969e02..8f702df72af 100644 --- a/mozilla/xpcom/io/nsLocalFileMac.cpp +++ b/mozilla/xpcom/io/nsLocalFileMac.cpp @@ -29,6 +29,7 @@ #include "nsXPIDLString.h" #include "nsLocalFileMac.h" +#include "nsNativeCharsetUtils.h" #include "nsISimpleEnumerator.h" #include "nsIComponentManager.h" #include "nsIInternetConfigService.h" @@ -62,7 +63,6 @@ #include #include #include -#include #include #include @@ -149,168 +149,6 @@ nsPathParser::nsPathParser(const nsACString &inPath) : mBuffer[offset] = '\0'; } -#pragma mark - -#pragma mark [nsFSStringConversionMac] - -class nsFSStringConversionMac { -public: - static nsresult UCSToFS(const nsAString& aIn, nsACString& aOut); - static nsresult FSToUCS(const nsACString& ain, nsAString& aOut); - - static void CleanUp(); - -private: - static TextEncoding GetSystemEncoding(); - static nsresult PrepareEncoder(); - static nsresult PrepareDecoder(); - - static UnicodeToTextInfo sEncoderInfo; - static TextToUnicodeInfo sDecoderInfo; -}; - -UnicodeToTextInfo nsFSStringConversionMac::sEncoderInfo = nsnull; -TextToUnicodeInfo nsFSStringConversionMac::sDecoderInfo = nsnull; - -nsresult nsFSStringConversionMac::UCSToFS(const nsAString& aIn, nsACString& aOut) -{ - nsresult rv = PrepareEncoder(); - if (NS_FAILED(rv)) return rv; - - OSStatus err = noErr; - char stackBuffer[512]; - - aOut.Truncate(0); - nsReadingIterator done_reading; - aIn.EndReading(done_reading); - - // for each chunk of |aIn|... - PRUint32 fragmentLength = 0; - nsReadingIterator iter; - for (aIn.BeginReading(iter); iter != done_reading && err == noErr; iter.advance(PRInt32(fragmentLength))) - { - fragmentLength = PRUint32(iter.size_forward()); - UInt32 bytesLeft = fragmentLength * sizeof(UniChar); - nsReadingIterator sub_iter(iter); - - do { - UInt32 bytesRead = 0, bytesWritten = 0; - err = ::ConvertFromUnicodeToText(sEncoderInfo, - bytesLeft, - (const UniChar*)sub_iter.get(), - kUnicodeUseFallbacksMask | kUnicodeLooseMappingsMask, - 0, nsnull, nsnull, nsnull, - sizeof(stackBuffer), - &bytesRead, - &bytesWritten, - stackBuffer); - if (err == kTECUsedFallbacksStatus) - err = noErr; - else if (err == kTECOutputBufferFullStatus) { - bytesLeft -= bytesRead; - sub_iter.advance(bytesRead / sizeof(UniChar)); - } - aOut.Append(stackBuffer, bytesWritten); - } - while (err == kTECOutputBufferFullStatus); - } - return (err == noErr) ? NS_OK : NS_ERROR_FAILURE; -} - -nsresult nsFSStringConversionMac::FSToUCS(const nsACString& aIn, nsAString& aOut) -{ - nsresult rv = PrepareDecoder(); - if (NS_FAILED(rv)) return rv; - - OSStatus err = noErr; - UniChar stackBuffer[512]; - - aOut.Truncate(0); - nsReadingIterator done_reading; - aIn.EndReading(done_reading); - - // for each chunk of |aIn|... - PRUint32 fragmentLength = 0; - nsReadingIterator iter; - for (aIn.BeginReading(iter); iter != done_reading && err == noErr; iter.advance(PRInt32(fragmentLength))) - { - fragmentLength = PRUint32(iter.size_forward()); - UInt32 bytesLeft = fragmentLength; - nsReadingIterator sub_iter(iter); - - do { - UInt32 bytesRead = 0, bytesWritten = 0; - err = ::ConvertFromTextToUnicode(sDecoderInfo, - bytesLeft, - sub_iter.get(), - kUnicodeUseFallbacksMask | kUnicodeLooseMappingsMask, - 0, nsnull, nsnull, nsnull, - sizeof(stackBuffer), - &bytesRead, - &bytesWritten, - stackBuffer); - if (err == kTECUsedFallbacksStatus) - err = noErr; - else if (err == kTECOutputBufferFullStatus) { - bytesLeft -= bytesRead; - sub_iter.advance(bytesRead); - } - aOut.Append((PRUnichar *)stackBuffer, bytesWritten / sizeof(PRUnichar)); - } - while (err == kTECOutputBufferFullStatus); - } - return (err == noErr) ? NS_OK : NS_ERROR_FAILURE; -} - -void nsFSStringConversionMac::CleanUp() -{ - if (sDecoderInfo) { - ::DisposeTextToUnicodeInfo(&sDecoderInfo); - sDecoderInfo = nsnull; - } - if (sEncoderInfo) { - ::DisposeUnicodeToTextInfo(&sEncoderInfo); - sEncoderInfo = nsnull; - } -} - -TextEncoding nsFSStringConversionMac::GetSystemEncoding() -{ - OSStatus err; - TextEncoding theEncoding; - - err = ::UpgradeScriptInfoToTextEncoding(smSystemScript, kTextLanguageDontCare, - kTextRegionDontCare, NULL, &theEncoding); - - if (err != noErr) - theEncoding = kTextEncodingMacRoman; - - return theEncoding; -} - -nsresult nsFSStringConversionMac::PrepareEncoder() -{ - nsresult rv = NS_OK; - if (!sEncoderInfo) { - OSStatus err; - err = ::CreateUnicodeToTextInfoByEncoding(GetSystemEncoding(), &sEncoderInfo); - if (err) - rv = NS_ERROR_FAILURE; - } - return rv; -} - -nsresult nsFSStringConversionMac::PrepareDecoder() -{ - nsresult rv = NS_OK; - if (!sDecoderInfo) { - OSStatus err; - err = ::CreateTextToUnicodeInfoByEncoding(GetSystemEncoding(), &sDecoderInfo); - if (err) - rv = NS_ERROR_FAILURE; - } - return rv; -} - #pragma mark - #pragma mark [static util funcs] @@ -768,7 +606,7 @@ static OSErr HFSPlusGetRawPath(const FSSpec& inSpec, nsAString& outStr) err = GetParentFolderSpec(inSpec, parentDirSpec); if (err == noErr) { const char *startPtr = (const char*)&inSpec.name[1]; - nsFSStringConversionMac::FSToUCS(Substring(startPtr, startPtr + PRUint32(inSpec.name[0])), outStr); + NS_CopyNativeToUnicode(Substring(startPtr, startPtr + PRUint32(inSpec.name[0])), outStr); err = ::FSpMakeFSRef(&parentDirSpec, &nodeRef); } } @@ -1322,7 +1160,7 @@ nsLocalFile::InitWithPath(const nsAString &filePath) nsresult rv; nsCAutoString fsStr; - if (NS_SUCCEEDED(rv = nsFSStringConversionMac::UCSToFS(filePath, fsStr))) + if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(filePath, fsStr))) rv = InitWithNativePath(fsStr); return rv; @@ -1550,7 +1388,7 @@ nsLocalFile::Append(const nsAString &node) nsresult rv; nsCAutoString fsStr; - if (NS_SUCCEEDED(rv = nsFSStringConversionMac::UCSToFS(node, fsStr))) + if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(node, fsStr))) rv = AppendNative(fsStr); return rv; @@ -1582,7 +1420,7 @@ nsLocalFile::AppendRelativePath(const nsAString &relPath) nsresult rv; nsCAutoString fsStr; - if (NS_SUCCEEDED(rv = nsFSStringConversionMac::UCSToFS(relPath, fsStr))) + if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(relPath, fsStr))) rv = AppendRelativeNativePath(fsStr); return rv; @@ -1633,7 +1471,7 @@ nsLocalFile::GetLeafName(nsAString &aLeafName) nsCAutoString fsStr; if (NS_SUCCEEDED(rv = GetNativeLeafName(fsStr))) - rv = nsFSStringConversionMac::FSToUCS(fsStr, aLeafName); + rv = NS_CopyNativeToUnicode(fsStr, aLeafName); return rv; } @@ -1672,7 +1510,7 @@ nsLocalFile::SetLeafName(const nsAString &aLeafName) nsresult rv; nsCAutoString fsStr; - if (NS_SUCCEEDED(rv = nsFSStringConversionMac::UCSToFS(aLeafName, fsStr))) + if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(aLeafName, fsStr))) rv = SetNativeLeafName(fsStr); return rv; @@ -1694,7 +1532,7 @@ nsLocalFile::GetNativePath(nsACString &_retval) if ((err = HFSPlusGetRawPath(mSpec, ucPathString)) != noErr) return MacErrorMapper(err); - rv = nsFSStringConversionMac::UCSToFS(ucPathString, fsCharSetPathStr); + rv = NS_CopyUnicodeToNative(ucPathString, fsCharSetPathStr); if (NS_FAILED(rv)) return rv; } @@ -1757,7 +1595,7 @@ nsLocalFile::GetPath(nsAString &_retval) nsAutoString ucAppendage; if (mAppendedPath.First() != ':') ucPathString.Append(PRUnichar(':')); - rv = nsFSStringConversionMac::FSToUCS(mAppendedPath, ucAppendage); + rv = NS_CopyNativeToUnicode(mAppendedPath, ucAppendage); if (NS_FAILED(rv)) return rv; ucPathString.Append(ucAppendage); @@ -1771,7 +1609,7 @@ nsLocalFile::GetPath(nsAString &_retval) nsCAutoString fsStr; if (NS_SUCCEEDED(rv = GetNativePath(fsStr))) { - rv = nsFSStringConversionMac::FSToUCS(fsStr, _retval); + rv = NS_CopyNativeToUnicode(fsStr, _retval); } } return rv; @@ -1871,7 +1709,7 @@ nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName) nsresult rv; nsCAutoString fsStr; - if (NS_SUCCEEDED(rv = nsFSStringConversionMac::UCSToFS(newName, fsStr))) + if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(newName, fsStr))) rv = CopyToNative(newParentDir, fsStr); return rv; } @@ -1890,7 +1728,7 @@ nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newNam nsresult rv; nsCAutoString fsStr; - if (NS_SUCCEEDED(rv = nsFSStringConversionMac::UCSToFS(newName, fsStr))) + if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(newName, fsStr))) rv = CopyToFollowingLinksNative(newParentDir, fsStr); return rv; } @@ -1909,7 +1747,7 @@ nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName) nsresult rv; nsCAutoString fsStr; - if (NS_SUCCEEDED(rv = nsFSStringConversionMac::UCSToFS(newName, fsStr))) + if (NS_SUCCEEDED(rv = NS_CopyUnicodeToNative(newName, fsStr))) rv = MoveToNative(newParentDir, fsStr); return rv; } @@ -2543,7 +2381,7 @@ nsLocalFile::GetTarget(nsAString &_retval) nsCAutoString fsStr; if (NS_SUCCEEDED(rv = GetNativeTarget(fsStr))) { - rv = nsFSStringConversionMac::FSToUCS(fsStr, _retval); + rv = NS_CopyNativeToUnicode(fsStr, _retval); } return rv; } @@ -3641,7 +3479,7 @@ nsresult NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result) { nsCAutoString fsCharSetStr; - nsresult rv = nsFSStringConversionMac::UCSToFS(path, fsCharSetStr); + nsresult rv = NS_CopyUnicodeToNative(path, fsCharSetStr); if (NS_FAILED(rv)) return rv; return NS_NewNativeLocalFile(fsCharSetStr, followLinks, result); @@ -3674,5 +3512,4 @@ nsLocalFile::GlobalInit() void nsLocalFile::GlobalShutdown() { - nsFSStringConversionMac::CleanUp(); } diff --git a/mozilla/xpcom/io/nsLocalFileOS2.cpp b/mozilla/xpcom/io/nsLocalFileOS2.cpp index 3f622afabbd..1878a1951ee 100644 --- a/mozilla/xpcom/io/nsLocalFileOS2.cpp +++ b/mozilla/xpcom/io/nsLocalFileOS2.cpp @@ -28,8 +28,7 @@ #include "nsMemory.h" #include "nsLocalFileOS2.h" - -#include +#include "nsNativeCharsetUtils.h" #include "nsISimpleEnumerator.h" #include "nsIComponentManager.h" @@ -2155,92 +2154,14 @@ static int isleadbyte(int c) return retval; } -static UconvObject UnicodeConverter = NULL; - -static nsresult NS_CreateUnicodeConverters() -{ - ULONG ulLength; - ULONG ulCodePage; - DosQueryCp(sizeof(ULONG), &ulCodePage, &ulLength); - - UniChar codepage[20]; - int unirc = ::UniMapCpToUcsCp(ulCodePage, codepage, 20); - if (unirc == ULS_SUCCESS) { - unirc = ::UniCreateUconvObject(codepage, &UnicodeConverter); - if (unirc == ULS_SUCCESS) { - uconv_attribute_t attr; - ::UniQueryUconvObject(UnicodeConverter, &attr, sizeof(uconv_attribute_t), - NULL, NULL, NULL); - attr.options = UCONV_OPTION_SUBSTITUTE_BOTH; - attr.subchar_len=1; - attr.subchar[0]='_'; - ::UniSetUconvObject(UnicodeConverter, &attr); - } - } -} - -static void NS_DestroyUnicodeConverters() -{ - ::UniFreeUconvObject(UnicodeConverter); -} - -static nsresult -UCS2toFS(const PRUnichar *aBuffer, char **aResult) -{ - size_t inLength = UniStrlen(aBuffer)+1; - size_t outLength = CCHMAXPATH; - UniChar *inString = (UniChar*)aBuffer; - char *outString = (char*)nsMemory::Alloc(outLength); - size_t cSubs = 0; - - char *tempString = outString; - - int unirc = ::UniUconvFromUcs(UnicodeConverter, &inString, &inLength, - (void**)&tempString, &outLength, &cSubs); - - NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big"); - - if( unirc != ULS_SUCCESS ) - return NS_ERROR_FAILURE; - - *aResult = outString; - - return NS_OK; -} - -static nsresult -FStoUCS2(const char* aBuffer, PRUnichar **aResult) -{ - size_t inLength = strlen(aBuffer)+1; - size_t outLength = CCHMAXPATH; - char *inString = (char*)aBuffer; - UniChar *outString = (UniChar*)nsMemory::Alloc(outLength); - - size_t cSubs = 0; - - UniChar *tempString = outString; - - int unirc = ::UniUconvToUcs(UnicodeConverter, (void**)&inString, &inLength, - &tempString, &outLength, &cSubs); - - NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big"); - - if( unirc != ULS_SUCCESS ) - return NS_ERROR_FAILURE; - - *aResult = (PRUnichar*)outString; - - return NS_OK; -} - NS_IMETHODIMP nsLocalFile::InitWithPath(const nsAString &filePath) { if (filePath.IsEmpty()) return InitWithNativePath(nsCString()); - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(filePath).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(filePath, tmp); if (NS_SUCCEEDED(rv)) return InitWithNativePath(tmp); @@ -2254,8 +2175,8 @@ nsLocalFile::Append(const nsAString &node) if (node.IsEmpty()) return NS_OK; - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(node).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(node, tmp); if (NS_SUCCEEDED(rv)) return AppendNative(tmp); @@ -2269,8 +2190,8 @@ nsLocalFile::AppendRelativePath(const nsAString &node) if (node.IsEmpty()) return NS_OK; - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(node).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(node, tmp); if (NS_SUCCEEDED(rv)) return AppendRelativeNativePath(tmp); @@ -2284,12 +2205,8 @@ nsLocalFile::GetLeafName(nsAString &aLeafName) nsCAutoString tmp; nsresult rv = GetNativeLeafName(tmp); - if (NS_SUCCEEDED(rv)) { - nsXPIDLString ucsBuf; - rv = FStoUCS2(tmp.get(), getter_Copies(ucsBuf)); - if (NS_SUCCEEDED(rv)) - aLeafName = ucsBuf; - } + if (NS_SUCCEEDED(rv)) + rv = NS_CopyNativeToUnicode(tmp, aLeafName); return rv; } @@ -2300,8 +2217,8 @@ nsLocalFile::SetLeafName(const nsAString &aLeafName) if (aLeafName.IsEmpty()) return SetNativeLeafName(nsCString()); - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(aLeafName).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(aLeafName, tmp); if (NS_SUCCEEDED(rv)) return SetNativeLeafName(tmp); @@ -2312,11 +2229,7 @@ nsLocalFile::SetLeafName(const nsAString &aLeafName) NS_IMETHODIMP nsLocalFile::GetPath(nsAString &_retval) { - nsXPIDLString ucsBuf; - nsresult rv = FStoUCS2(mWorkingPath.get(), getter_Copies(ucsBuf)); - if (NS_SUCCEEDED(rv)) - _retval = ucsBuf; - return rv; + return NS_CopyNativeToUnicode(mWorkingPath, _retval); } NS_IMETHODIMP @@ -2325,8 +2238,8 @@ nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName) if (newName.IsEmpty()) return CopyToNative(newParentDir, nsCString()); - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(newName).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(newName, tmp); if (NS_SUCCEEDED(rv)) return CopyToNative(newParentDir, tmp); @@ -2340,8 +2253,8 @@ nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newNam if (newName.IsEmpty()) return CopyToFollowingLinksNative(newParentDir, nsCString()); - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(newName).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(newName, tmp); if (NS_SUCCEEDED(rv)) return CopyToFollowingLinksNative(newParentDir, tmp); @@ -2355,8 +2268,8 @@ nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName) if (newName.IsEmpty()) return MoveToNative(newParentDir, nsCString()); - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(newName).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(newName, tmp); if (NS_SUCCEEDED(rv)) return MoveToNative(newParentDir, tmp); @@ -2370,12 +2283,8 @@ nsLocalFile::GetTarget(nsAString &_retval) nsCAutoString tmp; nsresult rv = GetNativeTarget(tmp); - if (NS_SUCCEEDED(rv)) { - nsXPIDLString ucsBuf; - rv = FStoUCS2(tmp.get(), getter_Copies(ucsBuf)); - if (NS_SUCCEEDED(rv)) - _retval = ucsBuf; - } + if (NS_SUCCEEDED(rv)) + rv = NS_CopyNativeToUnicode(tmp, _retval); return rv; } @@ -2386,8 +2295,8 @@ NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result if (path.IsEmpty()) return NS_NewNativeLocalFile(nsCString(), followLinks, result); - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(path).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(path, tmp); if (NS_SUCCEEDED(rv)) return NS_NewNativeLocalFile(tmp, followLinks, result); @@ -2402,11 +2311,9 @@ NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result void nsLocalFile::GlobalInit() { - NS_CreateUnicodeConverters(); } void nsLocalFile::GlobalShutdown() { - NS_DestroyUnicodeConverters(); } diff --git a/mozilla/xpcom/io/nsLocalFileWin.cpp b/mozilla/xpcom/io/nsLocalFileWin.cpp index c6b637cd61f..e894bd6c39c 100644 --- a/mozilla/xpcom/io/nsLocalFileWin.cpp +++ b/mozilla/xpcom/io/nsLocalFileWin.cpp @@ -27,6 +27,7 @@ #include "nsMemory.h" #include "nsLocalFileWin.h" +#include "nsNativeCharsetUtils.h" #include "nsISimpleEnumerator.h" #include "nsIComponentManager.h" @@ -2167,67 +2168,11 @@ NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* // UCS2 interface //----------------------------------------------------------------------------- -static nsresult UCS2toFS(const PRUnichar *aBuffer, char **aResult) -{ - NS_ENSURE_ARG_POINTER(aBuffer); - - // includes null termination - size_t chars = ::WideCharToMultiByte(CP_ACP, 0, - aBuffer, -1, - NULL, 0, NULL, NULL); - if (chars == 0) - return NS_ERROR_FAILURE; - - *aResult = (char*)nsMemory::Alloc(chars * sizeof(char)); - if (!*aResult) - return NS_ERROR_OUT_OF_MEMORY; - - // default "defaultChar" is '?', which is an illegal character on windows file system. - // That will cause file uncreatable. Change it to '_' - const char defaultChar = '_'; - chars = ::WideCharToMultiByte(CP_ACP, 0, - aBuffer, -1, - *aResult, chars, &defaultChar, NULL); - if (chars == 0) - { - nsMemory::Free(*aResult); - *aResult = nsnull; - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -static nsresult FStoUCS2(const char* aBuffer, PRUnichar **aResult) -{ - NS_ENSURE_ARG_POINTER(aBuffer); - - // includes null termination - size_t chars = ::MultiByteToWideChar(CP_ACP, 0, aBuffer, -1, NULL, 0); - - if (chars == 0) - return NS_ERROR_FAILURE; - - *aResult = (PRUnichar*)nsMemory::Alloc(chars * sizeof(PRUnichar)); - if (!*aResult) - return NS_ERROR_OUT_OF_MEMORY; - - chars = ::MultiByteToWideChar(CP_ACP, 0, - aBuffer, -1, - *aResult, chars); - if (chars == 0) { - nsMemory::Free(*aResult); - *aResult = nsnull; - return NS_ERROR_FAILURE; - } - return NS_OK; -} - nsresult nsLocalFile::InitWithPath(const nsAString &filePath) { - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(filePath).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(filePath, tmp); if (NS_SUCCEEDED(rv)) return InitWithNativePath(tmp); @@ -2237,8 +2182,8 @@ nsLocalFile::InitWithPath(const nsAString &filePath) nsresult nsLocalFile::Append(const nsAString &node) { - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(node).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(node, tmp); if (NS_SUCCEEDED(rv)) return AppendNative(tmp); @@ -2248,8 +2193,8 @@ nsLocalFile::Append(const nsAString &node) nsresult nsLocalFile::AppendRelativePath(const nsAString &node) { - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(node).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(node, tmp); if (NS_SUCCEEDED(rv)) return AppendRelativeNativePath(tmp); return rv; @@ -2260,12 +2205,8 @@ nsLocalFile::GetLeafName(nsAString &aLeafName) { nsCAutoString tmp; nsresult rv = GetNativeLeafName(tmp); - if (NS_SUCCEEDED(rv)) { - nsXPIDLString ucsBuf; - rv = FStoUCS2(tmp.get(), getter_Copies(ucsBuf)); - if (NS_SUCCEEDED(rv)) - aLeafName = ucsBuf; - } + if (NS_SUCCEEDED(rv)) + rv = NS_CopyNativeToUnicode(tmp, aLeafName); return rv; } @@ -2273,8 +2214,8 @@ nsLocalFile::GetLeafName(nsAString &aLeafName) nsresult nsLocalFile::SetLeafName(const nsAString &aLeafName) { - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(aLeafName).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(aLeafName, tmp); if (NS_SUCCEEDED(rv)) return SetNativeLeafName(tmp); @@ -2284,11 +2225,7 @@ nsLocalFile::SetLeafName(const nsAString &aLeafName) nsresult nsLocalFile::GetPath(nsAString &_retval) { - nsXPIDLString ucsBuf; - nsresult rv = FStoUCS2(mWorkingPath.get(), getter_Copies(ucsBuf)); - if (NS_SUCCEEDED(rv)) - _retval = ucsBuf; - return rv; + return NS_CopyNativeToUnicode(mWorkingPath, _retval); } nsresult @@ -2297,8 +2234,8 @@ nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName) if (newName.IsEmpty()) return CopyToNative(newParentDir, nsCString()); - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(newName).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(newName, tmp); if (NS_SUCCEEDED(rv)) return CopyToNative(newParentDir, tmp); @@ -2311,8 +2248,8 @@ nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newNam if (newName.IsEmpty()) return CopyToFollowingLinksNative(newParentDir, nsCString()); - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(newName).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(newName, tmp); if (NS_SUCCEEDED(rv)) return CopyToFollowingLinksNative(newParentDir, tmp); @@ -2325,8 +2262,8 @@ nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName) if (newName.IsEmpty()) return MoveToNative(newParentDir, nsCString()); - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(newName).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(newName, tmp); if (NS_SUCCEEDED(rv)) return MoveToNative(newParentDir, tmp); @@ -2338,12 +2275,8 @@ nsLocalFile::GetTarget(nsAString &_retval) { nsCAutoString tmp; nsresult rv = GetNativeTarget(tmp); - if (NS_SUCCEEDED(rv)) { - nsXPIDLString ucsBuf; - rv = FStoUCS2(tmp.get(), getter_Copies(ucsBuf)); - if (NS_SUCCEEDED(rv)) - _retval = ucsBuf; - } + if (NS_SUCCEEDED(rv)) + rv = NS_CopyNativeToUnicode(tmp, _retval); return rv; } @@ -2351,8 +2284,8 @@ nsLocalFile::GetTarget(nsAString &_retval) nsresult NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result) { - nsXPIDLCString tmp; - nsresult rv = UCS2toFS(PromiseFlatString(path).get(), getter_Copies(tmp)); + nsCAutoString tmp; + nsresult rv = NS_CopyUnicodeToNative(path, tmp); if (NS_SUCCEEDED(rv)) return NS_NewNativeLocalFile(tmp, followLinks, result); diff --git a/mozilla/xpcom/io/nsNativeCharsetUtils.cpp b/mozilla/xpcom/io/nsNativeCharsetUtils.cpp index fdf1878ed79..2fa76a7e0ff 100644 --- a/mozilla/xpcom/io/nsNativeCharsetUtils.cpp +++ b/mozilla/xpcom/io/nsNativeCharsetUtils.cpp @@ -39,6 +39,9 @@ * * ***** END LICENSE BLOCK ***** */ +//----------------------------------------------------------------------------- +// XP_UNIX +//----------------------------------------------------------------------------- #if defined(XP_UNIX) #include // mbtowc, wctomb @@ -789,6 +792,9 @@ NS_ShutdownNativeCharsetUtils() nsNativeCharsetConverter::GlobalShutdown(); } +//----------------------------------------------------------------------------- +// XP_BEOS +//----------------------------------------------------------------------------- #elif defined(XP_BEOS) #include "nsAString.h" @@ -818,23 +824,455 @@ NS_ShutdownNativeCharsetUtils() { } -#else // non XP_UNIX implementations go here... +//----------------------------------------------------------------------------- +// XP_WIN +//----------------------------------------------------------------------------- +#elif defined(XP_WIN) -#include "nsDebug.h" +#include #include "nsAString.h" NS_COM nsresult NS_CopyNativeToUnicode(const nsACString &input, nsAString &output) { - NS_NOTREACHED("NS_CopyNativeToUnicode"); - return NS_ERROR_NOT_IMPLEMENTED; + nsresult rv; + + PRUint32 inputLen = input.Length(); + + output.Truncate(); + + nsACString::const_iterator iter, end; + input.BeginReading(iter); + input.EndReading(end); + + // determine length of result + PRUint32 size, resultLen = 0; + for (; iter != end; iter.advance(size)) { + const char *buf = iter.get(); + size = iter.size_forward(); + + int n = ::MultiByteToWideChar(CP_ACP, 0, buf, size, NULL, 0); + if (n > 0) + resultLen += n; + else + break; + } + + output.SetLength(resultLen); // allocate sufficient space + nsAString::iterator out_iter; + output.BeginWriting(out_iter); + + PRUnichar *result = out_iter.get(); + + input.BeginReading(iter); + for (; iter != end; iter.advance(size)) { + const char *buf = iter.get(); + size = iter.size_forward(); + + int n = ::MultiByteToWideChar(CP_ACP, 0, buf, size, result, resultLen); + if (n > 0) { + result += n; + resultLen -= n; + } + else + break; + } + return NS_OK; } NS_COM nsresult NS_CopyUnicodeToNative(const nsAString &input, nsACString &output) { - NS_NOTREACHED("NS_CopyUnicodeToNative"); - return NS_ERROR_NOT_IMPLEMENTED; + nsresult rv; + + PRUint32 inputLen = input.Length(); + + output.Truncate(); + + nsAString::const_iterator iter, end; + input.BeginReading(iter); + input.EndReading(end); + + // determine length of result + PRUint32 size, resultLen = 0; + for (; iter != end; iter.advance(size)) { + const PRUnichar *buf = iter.get(); + size = iter.size_forward(); + + int n = ::WideCharToMultiByte(CP_ACP, 0, buf, size, NULL, 0, + NULL, NULL); + if (n > 0) + resultLen += n; + else + break; + } + + output.SetLength(resultLen); // allocate sufficient space + nsACString::iterator out_iter; + output.BeginWriting(out_iter); + + // default "defaultChar" is '?', which is an illegal character on windows + // file system. That will cause file uncreatable. Change it to '_' + const char defaultChar = '_'; + + char *result = out_iter.get(); + + input.BeginReading(iter); + for (; iter != end; iter.advance(size)) { + const PRUnichar *buf = iter.get(); + size = iter.size_forward(); + + int n = ::WideCharToMultiByte(CP_ACP, 0, buf, size, result, resultLen, + &defaultChar, NULL); + if (n > 0) { + result += n; + resultLen -= n; + } + else + break; + } + return NS_OK; +} + +void +NS_StartupNativeCharsetUtils() +{ +} + +void +NS_ShutdownNativeCharsetUtils() +{ +} + +//----------------------------------------------------------------------------- +// XP_OS2 +//----------------------------------------------------------------------------- +#elif defined(XP_OS2) + +#include +#include "nsPromiseFlatString.h" + +static UconvObject UnicodeConverter = NULL; + +NS_COM nsresult +NS_CopyNativeToUnicode(const nsACString &input, nsAString &output) +{ + nsresult rv; + + // XXX not the most efficient algorithm here + + const nsPromiseFlatCString &flat = PromiseFlatCString(input); + char *inputStr = (char*)flat.get(); + size_t inputLen = flat.Length() + 1; // include null char + + // assume worst case allocation + size_t resultLen = CCHMAXPATH; + + output.Truncate(); + output.SetLength(resultLen); + nsAString::iterator out_iter; + output.BeginWriting(out_iter); + UniChar *result = (UniChar*)out_iter.get(); + + size_t cSubs = 0; + size_t resultLeft = resultLen; + + int unirc = ::UniUconvToUcs(UnicodeConverter, &inputStr, &inputLen, + (void**)&result, &resultLeft, &cSubs); + + NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big"); + + if (unirc != ULS_SUCCESS) { + output.Truncate(); + return NS_ERROR_FAILURE; + } + + // need to update string length to reflect how many bytes were actually + // written. note: conversion wrote null byte. + output.SetLength(resultLen - (resultLeft + 1)); + return NS_OK; +} + +NS_COM nsresult +NS_CopyUnicodeToNative(const nsAString &input, nsACString &output) +{ + nsresult rv; + + // XXX not the most efficient algorithm here + + const nsPromiseFlatString &flat = PromiseFlatString(input); + UniChar *inputStr = (UniChar*)flat.get(); + size_t inputLen = flat.Length() + 1; // include null char + + // assume worst case allocation + size_t resultLen = CCHMAXPATH; + + output.Truncate(); + output.SetLength(resultLen); + nsACString::iterator out_iter; + output.BeginWriting(out_iter); + char *result = out_iter.get(); + + size_t cSubs = 0; + size_t resultLeft = resultLen; + + int unirc = ::UniUconvFromUcs(UnicodeConverter, &inputStr, &inputLen, + (void**)&result, &resultLeft, &cSubs); + + NS_ASSERTION(unirc != UCONV_E2BIG, "Path too big"); + + if (unirc != ULS_SUCCESS) { + output.Truncate(); + return NS_ERROR_FAILURE; + } + + // need to update string length to reflect how many bytes were actually + // written. note: conversion wrote null byte. + output.SetLength(resultLen - (resultLeft + 1)); + return NS_OK; +} + +void +NS_StartupNativeCharsetUtils() +{ + ULONG ulLength; + ULONG ulCodePage; + DosQueryCp(sizeof(ULONG), &ulCodePage, &ulLength); + + UniChar codepage[20]; + int unirc = ::UniMapCpToUcsCp(ulCodePage, codepage, 20); + if (unirc == ULS_SUCCESS) { + unirc = ::UniCreateUconvObject(codepage, &UnicodeConverter); + if (unirc == ULS_SUCCESS) { + uconv_attribute_t attr; + ::UniQueryUconvObject(UnicodeConverter, &attr, sizeof(uconv_attribute_t), + NULL, NULL, NULL); + attr.options = UCONV_OPTION_SUBSTITUTE_BOTH; + attr.subchar_len=1; + attr.subchar[0]='_'; + ::UniSetUconvObject(UnicodeConverter, &attr); + } + } +} + +void +NS_ShutdownNativeCharsetUtils() +{ + ::UniFreeUconvObject(UnicodeConverter); +} + +//----------------------------------------------------------------------------- +// XP_MAC +//----------------------------------------------------------------------------- +#elif defined(XP_MAC) + +#include +#include +#include +#include +#include "nsAString.h" + +class nsFSStringConversionMac { +public: + static nsresult UCSToFS(const nsAString& aIn, nsACString& aOut); + static nsresult FSToUCS(const nsACString& ain, nsAString& aOut); + + static void CleanUp(); + +private: + static TextEncoding GetSystemEncoding(); + static nsresult PrepareEncoder(); + static nsresult PrepareDecoder(); + + static UnicodeToTextInfo sEncoderInfo; + static TextToUnicodeInfo sDecoderInfo; +}; + +UnicodeToTextInfo nsFSStringConversionMac::sEncoderInfo = nsnull; +TextToUnicodeInfo nsFSStringConversionMac::sDecoderInfo = nsnull; + +nsresult nsFSStringConversionMac::UCSToFS(const nsAString& aIn, nsACString& aOut) +{ + nsresult rv = PrepareEncoder(); + if (NS_FAILED(rv)) return rv; + + OSStatus err = noErr; + char stackBuffer[512]; + + aOut.Truncate(0); + nsReadingIterator done_reading; + aIn.EndReading(done_reading); + + // for each chunk of |aIn|... + PRUint32 fragmentLength = 0; + nsReadingIterator iter; + for (aIn.BeginReading(iter); iter != done_reading && err == noErr; iter.advance(PRInt32(fragmentLength))) + { + fragmentLength = PRUint32(iter.size_forward()); + UInt32 bytesLeft = fragmentLength * sizeof(UniChar); + nsReadingIterator sub_iter(iter); + + do { + UInt32 bytesRead = 0, bytesWritten = 0; + err = ::ConvertFromUnicodeToText(sEncoderInfo, + bytesLeft, + (const UniChar*)sub_iter.get(), + kUnicodeUseFallbacksMask | kUnicodeLooseMappingsMask, + 0, nsnull, nsnull, nsnull, + sizeof(stackBuffer), + &bytesRead, + &bytesWritten, + stackBuffer); + if (err == kTECUsedFallbacksStatus) + err = noErr; + else if (err == kTECOutputBufferFullStatus) { + bytesLeft -= bytesRead; + sub_iter.advance(bytesRead / sizeof(UniChar)); + } + aOut.Append(stackBuffer, bytesWritten); + } + while (err == kTECOutputBufferFullStatus); + } + return (err == noErr) ? NS_OK : NS_ERROR_FAILURE; +} + +nsresult nsFSStringConversionMac::FSToUCS(const nsACString& aIn, nsAString& aOut) +{ + nsresult rv = PrepareDecoder(); + if (NS_FAILED(rv)) return rv; + + OSStatus err = noErr; + UniChar stackBuffer[512]; + + aOut.Truncate(0); + nsReadingIterator done_reading; + aIn.EndReading(done_reading); + + // for each chunk of |aIn|... + PRUint32 fragmentLength = 0; + nsReadingIterator iter; + for (aIn.BeginReading(iter); iter != done_reading && err == noErr; iter.advance(PRInt32(fragmentLength))) + { + fragmentLength = PRUint32(iter.size_forward()); + UInt32 bytesLeft = fragmentLength; + nsReadingIterator sub_iter(iter); + + do { + UInt32 bytesRead = 0, bytesWritten = 0; + err = ::ConvertFromTextToUnicode(sDecoderInfo, + bytesLeft, + sub_iter.get(), + kUnicodeUseFallbacksMask | kUnicodeLooseMappingsMask, + 0, nsnull, nsnull, nsnull, + sizeof(stackBuffer), + &bytesRead, + &bytesWritten, + stackBuffer); + if (err == kTECUsedFallbacksStatus) + err = noErr; + else if (err == kTECOutputBufferFullStatus) { + bytesLeft -= bytesRead; + sub_iter.advance(bytesRead); + } + aOut.Append((PRUnichar *)stackBuffer, bytesWritten / sizeof(PRUnichar)); + } + while (err == kTECOutputBufferFullStatus); + } + return (err == noErr) ? NS_OK : NS_ERROR_FAILURE; +} + +void nsFSStringConversionMac::CleanUp() +{ + if (sDecoderInfo) { + ::DisposeTextToUnicodeInfo(&sDecoderInfo); + sDecoderInfo = nsnull; + } + if (sEncoderInfo) { + ::DisposeUnicodeToTextInfo(&sEncoderInfo); + sEncoderInfo = nsnull; + } +} + +TextEncoding nsFSStringConversionMac::GetSystemEncoding() +{ + OSStatus err; + TextEncoding theEncoding; + + err = ::UpgradeScriptInfoToTextEncoding(smSystemScript, kTextLanguageDontCare, + kTextRegionDontCare, NULL, &theEncoding); + + if (err != noErr) + theEncoding = kTextEncodingMacRoman; + + return theEncoding; +} + +nsresult nsFSStringConversionMac::PrepareEncoder() +{ + nsresult rv = NS_OK; + if (!sEncoderInfo) { + OSStatus err; + err = ::CreateUnicodeToTextInfoByEncoding(GetSystemEncoding(), &sEncoderInfo); + if (err) + rv = NS_ERROR_FAILURE; + } + return rv; +} + +nsresult nsFSStringConversionMac::PrepareDecoder() +{ + nsresult rv = NS_OK; + if (!sDecoderInfo) { + OSStatus err; + err = ::CreateTextToUnicodeInfoByEncoding(GetSystemEncoding(), &sDecoderInfo); + if (err) + rv = NS_ERROR_FAILURE; + } + return rv; +} + +NS_COM nsresult +NS_CopyNativeToUnicode(const nsACString &input, nsAString &output) +{ + return nsFSStringConversionMac::FSToUCS(input, output); +} + +NS_COM nsresult +NS_CopyUnicodeToNative(const nsAString &input, nsACString &output) +{ + return nsFSStringConversionMac::UCSToFS(input, output); +} + +void +NS_StartupNativeCharsetUtils() +{ +} + +void +NS_ShutdownNativeCharsetUtils() +{ + nsFSStringConversionMac::CleanUp(); +} + +//----------------------------------------------------------------------------- +// default : truncate/zeropad +//----------------------------------------------------------------------------- +#else + +#include "nsReadableUtils.h" + +NS_COM nsresult +NS_CopyNativeToUnicode(const nsACString &input, nsAString &output) +{ + CopyASCIItoUCS2(input, output); + return NS_OK; +} + +NS_COM nsresult +NS_CopyUnicodeToNative(const nsAString &input, nsACString &output) +{ + CopyUCS2toASCII(input, output); + return NS_OK; } void diff --git a/mozilla/xpcom/io/nsNativeCharsetUtils.h b/mozilla/xpcom/io/nsNativeCharsetUtils.h index 691c6a79e20..539fa37f05e 100644 --- a/mozilla/xpcom/io/nsNativeCharsetUtils.h +++ b/mozilla/xpcom/io/nsNativeCharsetUtils.h @@ -45,16 +45,12 @@ * * * *** THESE ARE NOT GENERAL PURPOSE CONVERTERS *** * * * - * NS_CopyNativeToUnicode / NS_CopyUnicodeToNative should only be used * - * by XPCOM for converting *FILENAMES* between native and unicode. They * - * are not designed or tested for general encoding converter use. * + * NS_CopyNativeToUnicode / NS_CopyUnicodeToNative should only be used * + * for converting *FILENAMES* between native and unicode. They are not * + * designed or tested for general encoding converter use. * * * \*****************************************************************************/ - -// XXX XXX XXX XXX only implemented for XP_UNIX XXX XXX XXX XXX - - /** * thread-safe conversion routines that do not depend on uconv libraries. */ diff --git a/mozilla/xpcom/macbuild/xpcomPPC.xml b/mozilla/xpcom/macbuild/xpcomPPC.xml index 619abe50f51..6e4c8eef9e7 100644 --- a/mozilla/xpcom/macbuild/xpcomPPC.xml +++ b/mozilla/xpcom/macbuild/xpcomPPC.xml @@ -1583,6 +1583,13 @@ Text Debug + + Name + nsNativeCharsetUtils.cpp + MacOS + Text + Debug + Name nsDirectoryService.cpp @@ -2295,6 +2302,11 @@ nsLocalFileMac.cpp MacOS + + Name + nsNativeCharsetUtils.cpp + MacOS + Name nsDirectoryService.cpp @@ -4059,6 +4071,13 @@ Text Debug + + Name + nsNativeCharsetUtils.cpp + MacOS + Text + Debug + Name nsDirectoryService.cpp @@ -4776,6 +4795,11 @@ nsLocalFileMac.cpp MacOS + + Name + nsNativeCharsetUtils.cpp + MacOS + Name nsDirectoryService.cpp @@ -5502,6 +5526,12 @@ nsLocalFileMac.cpp MacOS + + xpcom.shlb + Name + nsNativeCharsetUtils.cpp + MacOS + xpcom.shlb Name