diff --git a/widget/src/os2/nsClipboard.cpp b/widget/src/os2/nsClipboard.cpp index aa10191748dc..a1d862177ec8 100644 --- a/widget/src/os2/nsClipboard.cpp +++ b/widget/src/os2/nsClipboard.cpp @@ -32,40 +32,28 @@ #include // for UniStrlen -// The relation between mozilla's mime formats and those understood by the -// clipboard is a little hazy, mostly in the areas of images. -// -// Could be a lot cleverer & use delayed rendering or something to provide -// a consumer with text when what we've got is unicode, or whatever. - -struct FormatEntry +inline ULONG RegisterClipboardFormat(PCSZ pcszFormat) { - const char *szMimeType; - ULONG ulClipboardFmt; - const char *szFmtName; -}; + ATOM atom = WinFindAtom(WinQuerySystemAtomTable(), pcszFormat); + if (!atom) { + atom = WinAddAtom(WinQuerySystemAtomTable(), pcszFormat); + } + return atom; +} -FormatEntry formatEntries[] = -{ - { kTextMime, CF_TEXT, 0 }, - { kUnicodeMime, 0, "CF_UNICODE" }, - { kHTMLMime, 0, "CF_HTML" }, - { kPNGImageMime, 0, "CF_PNG" }, - { kGIFImageMime, 0, "CF_GIF" }, - { kJPEGImageMime, 0, "CF_JPEG" }, - { kAOLMailMime, 0, "CF_AOLMAIL" }, - { kFileMime, 0, "CF_FILE" }, - { kURLMime, 0, "CF_URL" } -}; - -// scaffolding nsClipboard::nsClipboard() : nsBaseClipboard() { - for (int cnt=0 ; cnt < sizeof(formatEntries) / sizeof(formatEntries[0]) ; cnt++) - { - if (formatEntries[cnt].ulClipboardFmt == 0) // Not yet registered - formatEntries[cnt].ulClipboardFmt = gWidgetModuleData->GetAtom( formatEntries[cnt].szFmtName ); - } + RegisterClipboardFormat(kTextMime); + RegisterClipboardFormat(kUnicodeMime); + RegisterClipboardFormat(kHTMLMime); + RegisterClipboardFormat(kAOLMailMime); + RegisterClipboardFormat(kPNGImageMime); + RegisterClipboardFormat(kJPEGImageMime); + RegisterClipboardFormat(kGIFImageMime); + RegisterClipboardFormat(kFileMime); + RegisterClipboardFormat(kURLMime); + RegisterClipboardFormat(kNativeImageMime); + RegisterClipboardFormat(kNativeHTMLMime); } nsClipboard::~nsClipboard() @@ -349,15 +337,10 @@ nsresult nsClipboard::DoClipboardAction(ClipboardAction aAction) // get the format ID for a given mimetype ULONG nsClipboard::GetFormatID(const char *aMimeStr) { - for (int cnt=0 ; cnt < sizeof(formatEntries) / sizeof(formatEntries[0]) ; cnt++) - { - if (!strcmp( aMimeStr, formatEntries[cnt].szMimeType )) - { - return formatEntries[cnt].ulClipboardFmt; // Found the known flavor - } - } - - return gWidgetModuleData->GetAtom( aMimeStr ); // Unknown flavor. Register it in OS/2 atom table as is + if (strcmp(aMimeStr, kTextMime) == 0) + return CF_TEXT; + + return RegisterClipboardFormat(aMimeStr); } NS_IMETHODIMP nsClipboard::ForceDataToClipboard(PRInt32 aWhichClipboard) diff --git a/widget/src/os2/nsFilePicker.cpp b/widget/src/os2/nsFilePicker.cpp index 1b77a483065f..6643dbf5d7d4 100644 --- a/widget/src/os2/nsFilePicker.cpp +++ b/widget/src/os2/nsFilePicker.cpp @@ -165,7 +165,7 @@ NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval) const nsString& typeWide = *mTitles[i]; PRInt32 l = (typeWide.Length()+2)*2; char *filterBuffer = (char*) nsMemory::Alloc(l); - int len = gWidgetModuleData->WideCharToMultiByte(0, + int len = WideCharToMultiByte(0, typeWide.get(), typeWide.Length(), filterBuffer, diff --git a/widget/src/os2/nsModule.cpp b/widget/src/os2/nsModule.cpp index 839beda90631..209de9a44bc5 100644 --- a/widget/src/os2/nsModule.cpp +++ b/widget/src/os2/nsModule.cpp @@ -135,12 +135,7 @@ nsWidgetModuleData::~nsWidgetModuleData() NS_IF_RELEASE(dragService); - PRInt32 cAtoms = atoms.Count(); - HATOMTBL systbl = WinQuerySystemAtomTable(); - for( PRInt32 i = 0; i < cAtoms; i++) - WinDeleteAtom( systbl, (ATOM) atoms.ElementAt(i)); - - for (i=0;i<=16;i++ ) { + for (int i=0;i<=16;i++ ) { WinDestroyPointer(hptrArray[i]); } @@ -359,18 +354,6 @@ const char *nsWidgetModuleData::ConvertFromUcs( const nsString &aString) return ConvertFromUcs( aString.get()); } -ATOM nsWidgetModuleData::GetAtom( const char *atomname) -{ - ATOM atom = WinAddAtom( WinQuerySystemAtomTable(), atomname); - atoms.AppendElement( (void*) atom); - return atom; -} - -ATOM nsWidgetModuleData::GetAtom( const nsString &atomname) -{ - return GetAtom( ConvertFromUcs( atomname)); -} - // Printing stuff -- need to be able to generate a window of a given // flavour and then do stuff to it in nsWindow::Paint() @@ -414,49 +397,6 @@ HWND nsWidgetModuleData::GetWindowForPrinting( PCSZ pszClass, ULONG ulStyle) #endif -int nsWidgetModuleData::WideCharToMultiByte( int CodePage, const PRUnichar *pText, ULONG ulLength, char* szBuffer, ULONG ulSize ) -{ - UconvObject* pConverter = 0; - /* Free any converters that were created */ - for (int i=0; i < 15 /* eCharSet_COUNT from nsFontMetricsOS2.cpp */ ; i++ ) { - if (gUconvInfo[i].mCodePage == CodePage) { - if (!gUconvInfo[i].mConverter) { - UniChar codepage[20]; - int unirc = UniMapCpToUcsCp( CodePage, codepage, 20); - UniCreateUconvObject( codepage, &gUconvInfo[i].mConverter); - break; - } /* endif */ - pConverter = &gUconvInfo[i].mConverter; - } /* endif */ - } /* endfor */ - if (!pConverter) { - pConverter = &gUconvInfo[0].mConverter; - } /* endif */ - - UniChar *ucsString = (UniChar*) pText; - size_t ucsLen = ulLength; - size_t cplen = ulSize; - size_t cSubs = 0; - - char *tmp = szBuffer; // function alters the out pointer - - int unirc = UniUconvFromUcs( *pConverter, &ucsString, &ucsLen, - (void**) &tmp, &cplen, &cSubs); - - if( unirc == UCONV_E2BIG) // k3w1 - { - // terminate output string (truncating) - *(szBuffer + ulSize - 1) = '\0'; - } -#ifdef DEBUG - else if( unirc != ULS_SUCCESS) - { - printf("very bad"); - } -#endif - return ulSize - cplen; -} - const char *nsWidgetModuleData::DBCSstrchr( const char *string, int c ) { const char* p = string; @@ -484,3 +424,98 @@ const char *nsWidgetModuleData::DBCSstrrchr( const char *string, int c ) } nsWidgetModuleData *gWidgetModuleData = nsnull; + +int WideCharToMultiByte( int CodePage, const PRUnichar *pText, ULONG ulLength, char* szBuffer, ULONG ulSize ) +{ + UconvObject Converter = OS2Uni::GetUconvObject(CodePage); + + UniChar *ucsString = (UniChar*) pText; + size_t ucsLen = ulLength; + size_t cplen = ulSize; + size_t cSubs = 0; + + char *tmp = szBuffer; // function alters the out pointer + + int unirc = ::UniUconvFromUcs( Converter, &ucsString, &ucsLen, + (void**) &tmp, &cplen, &cSubs); + + if( unirc != ULS_SUCCESS ) + return 0; + + if( unirc == UCONV_E2BIG) + { + // terminate output string (truncating) + *(szBuffer + ulSize - 1) = '\0'; + } + + return ulSize - cplen; +} + +int MultiByteToWideChar( int CodePage, const char*pText, ULONG ulLength, PRUnichar *szBuffer, ULONG ulSize ) +{ + UconvObject Converter = OS2Uni::GetUconvObject(CodePage); + + char *ucsString = (char*) pText; + size_t ucsLen = ulLength; + size_t cplen = ulSize; + size_t cSubs = 0; + + PRUnichar *tmp = szBuffer; // function alters the out pointer + + int unirc = ::UniUconvToUcs( Converter, (void**)&ucsString, &ucsLen, + NS_REINTERPRET_CAST(UniChar**, &tmp), + &cplen, &cSubs); + + if( unirc != ULS_SUCCESS ) + return 0; + + if( unirc == UCONV_E2BIG) + { + // terminate output string (truncating) + *(szBuffer + ulSize - 1) = '\0'; + } + + return ulSize - cplen; +} + +nsHashtable OS2Uni::gUconvObjects; + +UconvObject +OS2Uni::GetUconvObject(int CodePage) +{ + nsPRUint32Key key(CodePage); + UconvObject uco = OS2Uni::gUconvObjects.Get(&key); + if (!uco) { + UniChar codepage[20]; + int unirc = ::UniMapCpToUcsCp(CodePage, codepage, 20); + if (unirc == ULS_SUCCESS) { + unirc = ::UniCreateUconvObject(codepage, &uco); + if (unirc == ULS_SUCCESS) { + uconv_attribute_t attr; + + ::UniQueryUconvObject(uco, &attr, sizeof(uconv_attribute_t), + NULL, NULL, NULL); + attr.options = UCONV_OPTION_SUBSTITUTE_BOTH; + attr.subchar_len=1; + attr.subchar[0]='?'; + ::UniSetUconvObject(uco, &attr); + OS2Uni::gUconvObjects.Put(&key, uco); + } + } + } + return uco; +} + +PR_STATIC_CALLBACK(PRIntn) +UconvObjectEnum(nsHashKey* hashKey, void *aData, void* closure) +{ + UniFreeUconvObject((UconvObject)aData); + return kHashEnumerateRemove; +} + +OS2Uni::FreeUconvObjects() +{ + if (gUconvObjects.Count()) { + gUconvObjects.Enumerate(UconvObjectEnum, nsnull); + } +} diff --git a/widget/src/os2/nsModule.h b/widget/src/os2/nsModule.h index 730bd7e4055d..4b63c99e613a 100644 --- a/widget/src/os2/nsModule.h +++ b/widget/src/os2/nsModule.h @@ -36,6 +36,7 @@ #include "nsISupports.h" #include "nsDragService.h" #include "nsWidgetDefs.h" +#include "nsHashtable.h" #define NS_MODULEDATAOS2_CID \ { 0xa506d27e, 0x1dd1, 0x11b2, \ @@ -77,11 +78,6 @@ class nsWidgetModuleData : public nsISupports const char *ConvertFromUcs( const PRUnichar *pText); const char *ConvertFromUcs( const nsString &aStr); - // Atom service; clients don't need to bother about freeing them. - ATOM GetAtom( const char *atomname); - ATOM GetAtom( const nsString &atomname); - - int WideCharToMultiByte( int CodePage, const PRUnichar *pText, ULONG ulLength, char* szBuffer, ULONG ulSize ); const char *DBCSstrchr( const char *string, int c ); const char *DBCSstrrchr( const char *string, int c ); @@ -107,8 +103,6 @@ class nsWidgetModuleData : public nsISupports UconvObject converter; BOOL supplantConverter; - - nsVoidArray atoms; }; #endif diff --git a/widget/src/os2/nsWidgetDefs.h b/widget/src/os2/nsWidgetDefs.h index 88f2c4efc71e..9b988bd6c58d 100644 --- a/widget/src/os2/nsWidgetDefs.h +++ b/widget/src/os2/nsWidgetDefs.h @@ -94,32 +94,6 @@ extern "C" BOOL APIENTRY DaxOpenSave(BOOL, LONG *, LPOPENFILENAME, PFNWP); #define SUPPORT_NON_XPFE /* support for viewer.exe */ -struct nsUconvInfo -{ - char* mCharset; - PRUint16 mCodePage; - UconvObject mConverter; -}; - -static nsUconvInfo gUconvInfo[15 /* eCharSet_COUNT from nsFontMetricsOS2.cpp */ ] = -{ - { "DEFAULT", 0, NULL }, - { "ANSI", 1252, NULL }, - { "EASTEUROPE", 1250, NULL }, - { "RUSSIAN", 1251, NULL }, - { "GREEK", 1253, NULL }, - { "TURKISH", 1254, NULL }, - { "HEBREW", 1255, NULL }, - { "ARABIC", 1256, NULL }, - { "BALTIC", 1257, NULL }, - { "THAI", 874, NULL }, - { "SHIFTJIS", 932, NULL }, - { "GB2312", 936, NULL }, - { "HANGEUL", 949, NULL }, - { "CHINESEBIG5", 950, NULL }, - { "JOHAB", 1361, NULL } -}; - class nsDragService; class nsIAppShell; @@ -220,5 +194,22 @@ typedef struct _WZDROPXFER // can be used as an lvalue too. #define lastchar(s) *((s) + strlen((s)) - 1) +struct nsUconvInfo +{ + PRUint16 mCodePage; + UconvObject mConverter; + nsUconvInfo* pNext; +}; + +class OS2Uni { +public: + static UconvObject GetUconvObject(int CodePage); + static FreeUconvObjects(); +private: + static nsHashtable gUconvObjects; +}; + +int WideCharToMultiByte( int CodePage, const PRUnichar *pText, ULONG ulLength, char* szBuffer, ULONG ulSize ); +int MultiByteToWideChar( int CodePage, const char*pText, ULONG ulLength, PRUnichar *szBuffer, ULONG ulSize ); #endif diff --git a/widget/src/os2/nsWidgetFactory.cpp b/widget/src/os2/nsWidgetFactory.cpp index f8e5833df511..fd94c1691f04 100644 --- a/widget/src/os2/nsWidgetFactory.cpp +++ b/widget/src/os2/nsWidgetFactory.cpp @@ -284,7 +284,7 @@ static const nsModuleComponentInfo components[] = PR_STATIC_CALLBACK(void) nsWidgetOS2ModuleDtor(nsIModule *self) { - // what shall we do here? + OS2Uni::FreeUconvObjects(); } NS_IMPL_NSGETMODULE_WITH_DTOR(nsWidgetOS2Module,