Evolution of the CharsetConverterManager in order to pair the new Charset Menu. r=erik

This commit is contained in:
cata%netscape.com 1999-12-02 08:05:59 +00:00
parent 835790a98b
commit 5760e40e40
3 changed files with 407 additions and 407 deletions

View File

@ -29,123 +29,70 @@
#include "nsIUnicodeEncoder.h"
#include "nsIUnicodeDecoder.h"
// Interface ID for our ConverterManager interface
// {1E3F79F0-6B6B-11d2-8A86-00600811A836}
// NS_DECLARE_ID(kICharsetConverterManagerIID,
// 0x1e3f79f0, 0x6b6b, 0x11d2, 0x8a, 0x86, 0x0, 0x60, 0x8, 0x11, 0xa8, 0x36);
#define NS_ICHARSETCONVERTERMANAGER_IID \
{0x3c1c0161, 0x9bd0, 0x11d3, { 0x9d, 0x9, 0x0, 0x50, 0x4, 0x0, 0x7, 0xb2}}
#define NS_ICHARSETCONVERTERMANAGER_IID \
{ /* 1E3F79F0-6B6B-11d2-8A86-00600811A836 */ \
0x1e3f79f0, \
0x6b6b, \
0x11d2, \
{0x8a, 0x86, 0x00, 0x60, 0x08, 0x11, 0xa8, 0x36} \
}
// XXX change to NS_CHARSETCONVERTERMANAGER_CID
#define NS_ICHARSETCONVERTERMANAGER_CID \
{0x3c1c0163, 0x9bd0, 0x11d3, { 0x9d, 0x9, 0x0, 0x50, 0x4, 0x0, 0x7, 0xb2}}
// Class ID for our ConverterManager implementation
// {1E3F79F1-6B6B-11d2-8A86-00600811A836}
// NS_DECLARE_ID(kCharsetConverterManagerCID,
// 0x1e3f79f1, 0x6b6b, 0x11d2, 0x8a, 0x86, 0x0, 0x60, 0x8, 0x11, 0xa8, 0x36);
// XXX change to NS_CHARSETCONVERTERMANAGER_PID
#define NS_CHARSETCONVERTERMANAGER_PROGID "charset-converter-manager"
#define NS_ICHARSETCONVERTERMANAGER_CID \
{ /* 1E3F79F1-6B6B-11d2-8A86-00600811A836 */ \
0x1e3f79f1, \
0x6b6b, \
0x11d2, \
{0x8a, 0x86, 0x00, 0x60, 0x08, 0x11, 0xa8, 0x36} \
}
#define NS_CHARSETCONVERTERMANAGER_PROGID "component://netscape/intl/charsetconvertermanager"
#define NS_REGISTRY_UCONV_BASE "software/netscape/intl/uconv/"
#define NS_ERROR_UCONV_NOCONV \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_UCONV,1)
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_UCONV, 0x01)
#define SET_FOR_BROWSER(_val) (_val |= 0x00000001)
#define SET_NOT_FOR_BROWSER(_val) (_val |= (!0x00000001))
#define GET_FOR_BROWSER(_val) ((_val &= 0x00000001) != 0)
#define SET_FOR_EDITOR(_val) (_val |= 0x00000001)
#define SET_NOT_FOR_EDITOR(_val) (_val |= (!0x00000001))
#define GET_FOR_EDITOR(_val) ((_val &= 0x00000001) != 0)
#define SET_FOR_MAILNEWS(_val) (_val |= 0x00000002)
#define SET_NOT_FOR_MAILNEWS(_val) (_val |= (!0x00000002))
#define GET_FOR_MAILNEWS(_val) ((_val &= 0x00000002) != 0)
#define SET_FOR_MAILNEWSEDITOR(_val) (_val |= 0x00000002)
#define SET_NOT_FOR_MAILNEWSEDITOR(_val) (_val |= (!0x00000002))
#define GET_FOR_MAILNEWSEDITOR(_val) ((_val &= 0x00000002) != 0)
/**
* Interface for a Manager of Charset Converters.
*
*
* This Manager's data is a caching of Registry available stuff. But the access
* methods are also doing all the work to get it and provide it.
*
* Note: The term "Charset" used in the classes, interfaces and file names
* should be read as "Coded Character Set". I am saying "charset" only for
* length considerations: it is a much shorter word. This convention is for
* source-code only, in the attached documents I will be either using the
* full expression or I'll specify a different convetion.
* full expression or I'll specify a different convention.
*
* XXX Move the ICharsetManager methods (the last 2 methods in the interface)
* into a separate interface. They are conceptually independent. I left them
* here only for easier implementation.
* A DECODER converts from a random encoding into Unicode.
* An ENCODER converts from Unicode into a random encoding.
* All our data structures and APIs are divided like that.
*
* XXX Add HasUnicodeEncoder() and HasUnicodeDecoder() methods.
*
* @created 17/Nov/1998
* @created 15/Nov/1999
* @author Catalin Rotaru [CATA]
*/
class nsICharsetConverterManager : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICHARSETCONVERTERMANAGER_IID)
static const nsIID& GetIID() { static nsIID iid = NS_ICHARSETCONVERTERMANAGER_IID; return iid; }
/**
* Find and instantiate a Converter able to encode from Unicode into the
* destination charset.
*
* @param aDest [IN] the known name/alias of the destination charset
* @param aResult [OUT] the charset converter
* @return NS_ERROR_UCONV_NOCONV if no converter was found for
* this charset
*/
NS_IMETHOD GetUnicodeEncoder(const nsString * aDest,
nsIUnicodeEncoder ** aResult) = 0;
/**
* Find and instantiate a Converter able to decode from the source charset
* into Unicode.
*
* @param aSrc [IN] the known name/alias of the source charset
* @param aResult [OUT] the charset converter
* @return NS_ERROR_UCONV_NOCONV if no converter was found for
* this charset
*/
NS_IMETHOD GetUnicodeDecoder(const nsString * aSrc,
nsIUnicodeDecoder ** aResult) = 0;
/**
* Returns a list of charsets for which we have converters from Unicode.
*
* @param aResult [OUT] an array of pointers to Strings (charset names)
* @param aCount [OUT] the size (number of elements) of that array
*/
NS_IMETHOD GetEncodableCharsets(nsString *** aResult, PRInt32 * aCount) = 0;
/**
* Returns a list of charsets for which we have converters into Unicode.
*
* @param aResult [OUT] an array of pointers to Strings (charset names)
* @param aCount [OUT] the size (number of elements) of that array
*/
NS_IMETHOD GetDecodableCharsets(nsString *** aResult, PRInt32 * aCount) = 0;
/**
* Resolves the canonical name of a charset. If the given name is unknown
* to the resolver, a new identical string will be returned! This way,
* new & unknown charsets are not rejected and they are treated as any other
* charset except they can't have aliases.
*
* @param aCharset [IN] the known name/alias of the character set
* @param aResult [OUT] the canonical name of the character set
*/
NS_IMETHOD GetCharsetName(const nsString * aCharset,
nsString ** aResult) = 0;
/**
* Returns a list containing all the legal names for a given charset. The
* list will allways have at least 1 element: the cannonical name for that
* charset.
*
* @param aCharset [IN] a known name/alias of the character set
* @param aResult [OUT] the list; in the first position is the
* cannonical name, then the other aliases
*/
NS_IMETHOD GetCharsetNames(const nsString * aCharset,
nsString *** aResult, PRInt32 * aCount) = 0;
NS_IMETHOD GetDecoderList(nsString *** aResult, PRInt32 * aCount) = 0;
NS_IMETHOD GetEncoderList(nsString *** aResult, PRInt32 * aCount) = 0;
NS_IMETHOD GetDecoderFlags(nsString * aName, PRInt32 * aFlags) = 0;
NS_IMETHOD GetEncoderFlags(nsString * aName, PRInt32 * aFlags) = 0;
};
#endif /* nsICharsetConverterManager_h___ */

View File

@ -22,16 +22,10 @@
#define NS_IMPL_IDS
#include "pratom.h"
#include "nsString.h"
#include "nsIComponentManager.h"
#include "nsIRegistry.h"
#include "nsIEnumerator.h"
#include "nsIServiceManager.h"
#include "nsICharsetConverterManager.h"
#include "nsICharsetConverterInfo.h"
#include "nsIUnicodeEncoder.h"
#include "nsIUnicodeDecoder.h"
#include "nsUConvDll.h"
// just for CIDs
@ -42,52 +36,62 @@
#include "nsIUnicodeDecodeUtil.h"
#include "nsUnicodeDecodeUtil.h"
//----------------------------------------------------------------------
// Global functions and data [declaration]
static NS_DEFINE_IID(kRegistryNodeIID, NS_IREGISTRYNODE_IID);
struct ConverterInfo
//----------------------------------------------------------------------------
// Class nsObject [declaration]
class nsObject
{
nsString * mCharset;
const nsCID * mCID;
PRBool mFreeCID;
ConverterInfo()
: mCharset(nsnull), mCID(nsnull), mFreeCID(PR_FALSE) {}
~ConverterInfo()
{
if (mCharset != NULL) delete mCharset;
if (mFreeCID) delete (nsCID*)mCID;
}
public:
virtual ~nsObject();
};
//----------------------------------------------------------------------
//----------------------------------------------------------------------------
// Class nsObjectArray [declaration]
class nsObjectArray
{
private:
nsObject ** mArray;
PRInt32 mCapacity;
PRInt32 mUsage;
void Init(PRInt32 aCapacity);
public:
nsObjectArray();
nsObjectArray(PRInt32 aCapacity);
~nsObjectArray();
nsObject ** GetArray();
PRInt32 GetUsage();
nsresult InsureCapacity(PRInt32 aCapacity);
nsresult AddObject(nsObject * aObject);
};
//----------------------------------------------------------------------------
// Class nsConverterInfo [declaration]
class nsConverterInfo : public nsObject
{
public:
nsString * mName;
nsCID mCID;
PRInt32 mFlags;
nsConverterInfo();
~nsConverterInfo();
};
//----------------------------------------------------------------------------
// Class nsCharsetConverterManager [declaration]
/**
* The actual implementation of the nsICharsetConverterManager interface.
*
* Requirements for a Manager:
* - singleton
* - special lifetime (survive even if it's not used, die only under memory
* pressure conditions or app termination)
*
* Ways of implementing it & fulfill those requirements:
* + simple xpcom object (current implementation model)
* - xpcom service (best, but no support available yet)
* - global class with static methods (ie part of the platform)
*
* Interesting observation: the NS_IMPL_IDS macros suck! In a given file, one
* can only declare OR define IDs, not both. Considering the unique-per-dll
* implementation, the headers inclusion and IDs declaration vs. definition
* becomes quite tricky.
*
* XXX make this component thread safe
*
* XXX Use the more general xpcom extensibility model when it will be ready.
* That means: Component Categories + Monikers. Better performance!
*
* @created 17/Nov/1998
* @created 15/Nov/1999
* @author Catalin Rotaru [CATA]
*/
class nsCharsetConverterManager : public nsICharsetConverterManager
@ -96,196 +100,219 @@ class nsCharsetConverterManager : public nsICharsetConverterManager
private:
/**
* Pointer to the unique instance of this class.
*/
static nsICharsetConverterManager * mInstance;
nsObjectArray mDecoderArray;
nsObjectArray mEncoderArray;
/**
* The Mapping data structures.
* Takes charset information from Registry and puts it into those arrays.
*/
ConverterInfo mEncArray[100];
PRInt32 mEncSize;
ConverterInfo mDecArray[100];
PRInt32 mDecSize;
PRBool mMappingDone;
void FillInfoArrays();
void FillConverterProperties(nsObjectArray * aArray);
/**
* Class constructor.
* Returns NULL if charset could not be found.
*/
nsCharsetConverterManager();
nsConverterInfo * GetConverterInfo(nsObjectArray * aArray,
nsString * aName);
/**
* Creates some sort of mapping (Charset, Charset) -> Converter.
*/
nsresult CreateMapping();
/**
* Gathers the necessary informations about each Converter.
*/
nsresult GatherConvertersInfo();
/**
* Attempts to return a ICharsetConverterInfo reference for the given charset
* in the array. If errors, the converter will be eliminated from the array.
*/
nsICharsetConverterInfo * GetICharsetConverterInfo(ConverterInfo * ci,
PRInt32 aIndex, PRInt32 * aSize);
nsresult GetConverterList(nsObjectArray * aArray, nsString *** aResult,
PRInt32 * aCount);
static nsresult RegisterConverterPresenceData(char * aRegistryPath,
PRBool aPresence);
public:
/**
* Class destructor.
*/
nsCharsetConverterManager();
virtual ~nsCharsetConverterManager();
static nsresult RegisterConverterManagerData();
/**
* Unique factory method for this class (the constructor is private).
*
* @return a singleton object, instance of this class
*/
static nsICharsetConverterManager * GetInstance();
//--------------------------------------------------------------------
//--------------------------------------------------------------------------
// Interface nsICharsetConverterManager [declaration]
NS_IMETHOD GetUnicodeEncoder(const nsString * aDest,
nsIUnicodeEncoder ** aResult);
NS_IMETHOD GetUnicodeDecoder(const nsString * aSrc,
nsIUnicodeDecoder ** aResult);
NS_IMETHOD GetEncodableCharsets(nsString *** aResult, PRInt32 * aCount);
NS_IMETHOD GetDecodableCharsets(nsString *** aResult, PRInt32 * aCount);
NS_IMETHOD GetCharsetName(const nsString * aCharset, nsString ** aResult);
NS_IMETHOD GetCharsetNames(const nsString * aCharset, nsString *** aResult,
PRInt32 * aCount);
NS_IMETHOD GetDecoderList(nsString *** aResult, PRInt32 * aCount);
NS_IMETHOD GetEncoderList(nsString *** aResult, PRInt32 * aCount);
NS_IMETHOD GetDecoderFlags(nsString * aName, PRInt32 * aFlags);
NS_IMETHOD GetEncoderFlags(nsString * aName, PRInt32 * aFlags);
};
//----------------------------------------------------------------------
//----------------------------------------------------------------------------
// Global functions and data [implementation]
NS_IMETHODIMP NS_NewCharsetConverterManager(nsISupports* aOuter,
const nsIID& aIID,
void** aResult)
{
if (!aResult) {
return NS_ERROR_NULL_POINTER;
}
if (aOuter) {
*aResult = nsnull;
return NS_ERROR_NO_AGGREGATION;
}
nsCharsetConverterManager * inst = new nsCharsetConverterManager();
if (!inst) {
*aResult = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = inst->QueryInterface(aIID, aResult);
if (NS_FAILED(res)) {
*aResult = nsnull;
delete inst;
}
return res;
}
//----------------------------------------------------------------------------
// Class nsObject [implementation]
// XXX clarify why I can't have this method as a pure virtual one?!
nsObject::~nsObject()
{
}
//----------------------------------------------------------------------------
// Class nsObjectsArray [implementation]
nsObjectArray::nsObjectArray(PRInt32 aCapacity)
{
Init(aCapacity);
}
nsObjectArray::nsObjectArray()
{
Init(64);
}
nsObjectArray::~nsObjectArray()
{
for (PRInt32 i = 0; i < mUsage; i++) delete mArray[i];
if (mArray != NULL) delete [] mArray;
}
nsObject ** nsObjectArray::GetArray()
{
return mArray;
}
PRInt32 nsObjectArray::GetUsage()
{
return mUsage;
}
void nsObjectArray::Init(PRInt32 aCapacity)
{
mCapacity = aCapacity;
mUsage = 0;
mArray = NULL;
}
nsresult nsObjectArray::InsureCapacity(PRInt32 aCapacity)
{
PRInt32 i;
if (mArray == NULL) {
mArray = new nsObject * [mCapacity];
if (mArray == NULL) return NS_ERROR_OUT_OF_MEMORY;
}
if (aCapacity > mCapacity) {
while (aCapacity > mCapacity) mCapacity *= 2;
nsObject ** newArray = new nsObject * [mCapacity];
if (newArray == NULL) return NS_ERROR_OUT_OF_MEMORY;
for (i = 0; i < mUsage; i++) newArray[i] = mArray[i];
delete [] mArray;
mArray = newArray;
}
return NS_OK;
}
nsresult nsObjectArray::AddObject(nsObject * aObject)
{
nsresult res;
res = InsureCapacity(mUsage + 1);
if (NS_FAILED(res)) return res;
(mArray)[mUsage++] = aObject;
return NS_OK;
}
//----------------------------------------------------------------------------
// Class nsConverterInfo [implementation]
nsConverterInfo::nsConverterInfo()
{
mName = NULL;
}
nsConverterInfo::~nsConverterInfo()
{
if (mName != NULL) delete mName;
}
//----------------------------------------------------------------------------
// Class nsCharsetConverterManager [implementation]
NS_IMPL_ISUPPORTS(nsCharsetConverterManager, nsCOMTypeInfo<nsICharsetConverterManager>::GetIID());
nsICharsetConverterManager * nsCharsetConverterManager::mInstance = NULL;
NS_IMPL_ISUPPORTS(nsCharsetConverterManager, nsICharsetConverterManager::GetIID());
nsCharsetConverterManager::nsCharsetConverterManager()
{
mEncSize = 0;
mDecSize = 0;
mMappingDone = PR_FALSE;
NS_INIT_REFCNT();
PR_AtomicIncrement(&g_InstanceCount);
CreateMapping();
FillInfoArrays();
FillConverterProperties(&mDecoderArray);
FillConverterProperties(&mEncoderArray);
}
nsCharsetConverterManager::~nsCharsetConverterManager()
{
mInstance = NULL;
PR_AtomicDecrement(&g_InstanceCount);
}
nsICharsetConverterManager * nsCharsetConverterManager::GetInstance()
nsresult nsCharsetConverterManager::RegisterConverterManagerData()
{
if (mInstance == NULL) mInstance = new nsCharsetConverterManager();
return mInstance;
// XXX take these konstants out of here
// XXX change "xuconv" to "uconv" when the new enc&dec trees are in place
RegisterConverterPresenceData("software/netscape/intl/xuconv/not-for-browser", PR_FALSE);
return NS_OK;
}
nsresult nsCharsetConverterManager::CreateMapping()
nsresult nsCharsetConverterManager::RegisterConverterPresenceData(
char * aRegistryPath,
PRBool aPresence)
{
mMappingDone = PR_TRUE;
nsresult res = NS_OK;
nsresult res;
nsIRegistry * registry = NULL;
nsIEnumerator * components = NULL;
nsRegistryKey uconvKey, key;
// XXX hack; make these dynamic
mEncSize = mDecSize = 0;
nsRegistryKey key;
// get the registry
res = nsServiceManager::GetService(NS_REGISTRY_PROGID,
nsIRegistry::GetIID(),
(nsISupports**)&registry);
nsIRegistry::GetIID(), (nsISupports**)&registry);
if (NS_FAILED(res)) goto done;
// open the registry
res = registry->OpenWellKnownRegistry(
nsIRegistry::ApplicationComponentRegistry);
nsIRegistry::ApplicationComponentRegistry);
if (NS_FAILED(res)) goto done;
// get subtree
res = registry -> GetSubtree(nsIRegistry::Common,
"software/netscape/intl/uconv",
&uconvKey);
res = registry -> AddSubtree(nsIRegistry::Common, aRegistryPath, &key);
if (NS_FAILED(res)) goto done;
// enumerate subtrees
res = registry -> EnumerateSubtrees(uconvKey, &components);
// XXX instead of these hardcoded values, I should read from a property file
res = registry -> SetInt(key, "x-fake-1999", 1);
if (NS_FAILED(res)) goto done;
res = components -> First();
res = registry -> SetInt(key, "x-fake-2000", 1);
if (NS_FAILED(res)) goto done;
res = registry -> SetInt(key, "X-EUC-TW", 1);
if (NS_FAILED(res)) goto done;
// XXX take these KONSTANTS out of here
// XXX check return values, free stuff
// XXX bit hacky, clean me up
while (NS_OK != components -> IsDone()) {
nsISupports * base;
res = components -> CurrentItem(&base);
if (NS_SUCCEEDED(res)) {
nsIRegistryNode * node;
nsIID nodeIID = NS_IREGISTRYNODE_IID;
res = base->QueryInterface (nodeIID, (void**)&node);
if (NS_FAILED(res)) continue;
char *name;
res = node->GetName(&name);
if (NS_FAILED(res)) continue;
nsCID * cid = new nsCID();
char * src;
char * dest;
if (!cid->Parse(name)) continue;
res = node->GetKey(&key);
if (NS_FAILED(res)) continue;
res = registry->GetString(key, "source", &src);
if (NS_FAILED(res)) continue;
res = registry->GetString(key, "destination", &dest);
if (NS_FAILED(res)) {
nsCRT::free(src);
continue;
}
nsAutoString str;
if (!strcmp(src, "Unicode")) {
str.Assign(dest);
GetCharsetName(&str,&mEncArray[mEncSize].mCharset);
mEncArray[mEncSize].mCID = cid;
mEncArray[mEncSize].mFreeCID = PR_TRUE;
mEncSize++;
} else if (!strcmp(dest, "Unicode")) {
str.Assign(src);
GetCharsetName(&str,&mDecArray[mDecSize].mCharset);
mDecArray[mDecSize].mCID = cid;
mDecArray[mDecSize].mFreeCID = PR_TRUE;
mDecSize++;
}
nsCRT::free(src);
nsCRT::free(dest);
nsCRT::free(name);
NS_RELEASE(node);
NS_RELEASE(base);
}
res = components->Next();
}
done:
if (registry != NULL) {
@ -293,91 +320,163 @@ done:
nsServiceManager::ReleaseService(NS_REGISTRY_PROGID, registry);
}
NS_IF_RELEASE(components);
return res;
}
nsresult nsCharsetConverterManager::GatherConvertersInfo()
// XXX rethink the registry structure(tree) for these converters
// The idea is to have two trees:
// .../uconv/decoder/(CID/name)
// .../uconv/encoder/(CID/name)
// XXX take the registry strings out and make them macros
void nsCharsetConverterManager::FillInfoArrays()
{
nsICharsetConverterInfo * info;
nsString * str;
PRInt32 i;
nsresult res = NS_OK;
nsIEnumerator * components = NULL;
nsIRegistry * registry = NULL;
nsRegistryKey uconvKey, key;
for (i=0;i<mEncSize;) {
info = GetICharsetConverterInfo(mEncArray, i, &mEncSize);
if (info == NULL) continue;
// get the registry
res = nsServiceManager::GetService(NS_REGISTRY_PROGID,
nsIRegistry::GetIID(), (nsISupports**)&registry);
if (NS_FAILED(res)) goto done;
char *charset;
info->GetCharsetDest(&charset);
str = new nsString(charset);
GetCharsetName(str,&mEncArray[i].mCharset);
delete str;
i++;
NS_RELEASE(info);
// open the registry
res = registry->OpenWellKnownRegistry(
nsIRegistry::ApplicationComponentRegistry);
if (NS_FAILED(res)) goto done;
// get subtree
res = registry->GetSubtree(nsIRegistry::Common,
"software/netscape/intl/uconv", &uconvKey);
if (NS_FAILED(res)) goto done;
// enumerate subtrees
res = registry->EnumerateSubtrees(uconvKey, &components);
if (NS_FAILED(res)) goto done;
res = components->First();
if (NS_FAILED(res)) goto done;
while (NS_OK != components->IsDone()) {
nsISupports * base = NULL;
nsIRegistryNode * node = NULL;
char * name = NULL;
char * src = NULL;
char * dest = NULL;
nsConverterInfo * ci = NULL;
res = components->CurrentItem(&base);
if (NS_FAILED(res)) goto done1;
res = base->QueryInterface(kRegistryNodeIID, (void**)&node);
if (NS_FAILED(res)) goto done1;
res = node->GetName(&name);
if (NS_FAILED(res)) goto done1;
ci = new nsConverterInfo();
if (ci == NULL) goto done1;
if (!(ci->mCID.Parse(name))) goto done1;
res = node->GetKey(&key);
if (NS_FAILED(res)) goto done1;
res = registry->GetString(key, "source", &src);
if (NS_FAILED(res)) goto done1;
res = registry->GetString(key, "destination", &dest);
if (NS_FAILED(res)) goto done1;
if (!strcmp(src, "Unicode")) {
ci->mName = new nsString(dest);
mEncoderArray.AddObject(ci);
} else if (!strcmp(dest, "Unicode")) {
ci->mName = new nsString(src);
mDecoderArray.AddObject(ci);
} else goto done1;
ci = NULL;
done1:
NS_IF_RELEASE(base);
NS_IF_RELEASE(node);
if (name != NULL) nsCRT::free(name);
if (src != NULL) nsCRT::free(src);
if (dest != NULL) nsCRT::free(dest);
if (ci != NULL) delete ci;
res = components->Next();
if (NS_FAILED(res)) break; // this is NOT supposed to fail!
}
for (i=0;i<mDecSize;) {
info = GetICharsetConverterInfo(mDecArray, i, &mDecSize);
if (info == NULL) continue;
char *charset;
info->GetCharsetSrc(&charset);
str = new nsString(charset);
GetCharsetName(str,&mDecArray[i].mCharset);
delete str;
i++;
NS_RELEASE(info);
// finish and clean up
done:
if (registry != NULL) {
registry->Close();
nsServiceManager::ReleaseService(NS_REGISTRY_PROGID, registry);
}
return NS_OK;
NS_IF_RELEASE(components);
}
nsICharsetConverterInfo *
nsCharsetConverterManager::GetICharsetConverterInfo(ConverterInfo * aArray,
PRInt32 aIndex,
PRInt32 * aSize)
void nsCharsetConverterManager::FillConverterProperties(
nsObjectArray * aArray)
{
nsresult res;
nsIFactory * factory;
nsICharsetConverterInfo * info;
PRInt32 size = aArray->GetUsage();
nsConverterInfo ** array = (nsConverterInfo **)aArray->GetArray();
if ((size == 0) || (array == NULL)) return;
res=nsComponentManager::FindFactory(*(aArray[aIndex].mCID), &factory);
if (NS_FAILED(res)) {
#if 1
printf(" get charset info FindFactory failed %d %x", aIndex, res);
#endif
goto reduceArray;
for (PRInt32 i = 0; i < size; i++) {
int val = 0;
SET_FOR_BROWSER(val);
SET_FOR_MAILNEWSEDITOR(val);
array[i]->mFlags = val;
}
res=factory->QueryInterface(kICharsetConverterInfoIID, (void ** )&info);
NS_RELEASE(factory);
if (NS_FAILED(res)) {
#if 1
printf(" get charset info QI failed %d %x", aIndex, res);
#endif
goto reduceArray;
}
// XXX get these properties from registry, not from your stomach
}
return info;
// XXX optimise this method - use some hash tables for God's sake!
// That could also mean taking the name out of the data structure. Maybe.
nsConverterInfo * nsCharsetConverterManager::GetConverterInfo(
nsObjectArray * aArray,
nsString * aName)
{
PRInt32 size = aArray->GetUsage();
nsConverterInfo ** array = (nsConverterInfo **)aArray->GetArray();
if ((size == 0) || (array == NULL)) return NULL;
reduceArray:
PRInt32 i;
(*aSize)--;
for (i=aIndex; i<*aSize;) aArray[i] = aArray[++i];
if (i>=0) {
aArray[i].mCharset = NULL;
aArray[i].mCID = NULL;
}
for (PRInt32 i = 0; i < size; i++) if (aName->Equals(*(array[i]->mName)))
return array[i];
return NULL;
}
nsresult nsCharsetConverterManager::GetConverterList(
nsObjectArray * aArray,
nsString *** aResult,
PRInt32 * aCount)
{
*aResult = NULL;
*aCount = 0;
//----------------------------------------------------------------------
PRInt32 size = aArray->GetUsage();
nsConverterInfo ** array = (nsConverterInfo **)aArray->GetArray();
if ((size == 0) || (array == NULL)) return NS_OK;
*aResult = new nsString * [size];
if (*aResult == NULL) return NS_ERROR_OUT_OF_MEMORY;
*aCount = size;
for (PRInt32 i=0;i<size;i++) (*aResult)[i] = array[i]->mName;
return NS_OK;
// XXX also create new Strings here, as opposed to just providing pointers
// to the existing ones
}
//----------------------------------------------------------------------------
// Interface nsICharsetConverterManager [implementation]
NS_IMETHODIMP nsCharsetConverterManager::GetUnicodeEncoder(
@ -422,84 +521,38 @@ NS_IMETHODIMP nsCharsetConverterManager::GetUnicodeDecoder(
return res;
}
NS_IMETHODIMP nsCharsetConverterManager::GetEncodableCharsets(
nsString *** aResult,
PRInt32 * aCount)
NS_IMETHODIMP nsCharsetConverterManager::GetDecoderList(nsString *** aResult,
PRInt32 * aCount)
{
nsresult res;
if (!mMappingDone) {
res = CreateMapping();
if NS_FAILED(res) return res;
}
return GetConverterList(&mDecoderArray, aResult, aCount);
}
*aResult = NULL;
*aCount = 0;
if (mEncSize != 0) {
*aResult = new nsString * [mEncSize];
*aCount = mEncSize;
for (PRInt32 i=0;i<mEncSize;i++) (*aResult)[i]=mEncArray[i].mCharset;
}
NS_IMETHODIMP nsCharsetConverterManager::GetEncoderList(nsString *** aResult,
PRInt32 * aCount)
{
return GetConverterList(&mEncoderArray, aResult, aCount);
}
NS_IMETHODIMP nsCharsetConverterManager::GetDecoderFlags(nsString * aName,
PRInt32 * aFlags)
{
*aFlags = 0;
nsConverterInfo * info = GetConverterInfo(&mDecoderArray, aName);
if (info == NULL) return NS_ERROR_UCONV_NOCONV;
*aFlags = info->mFlags;
return NS_OK;
}
NS_IMETHODIMP nsCharsetConverterManager::GetDecodableCharsets(
nsString *** aResult,
PRInt32 * aCount)
NS_IMETHODIMP nsCharsetConverterManager::GetEncoderFlags(nsString * aName,
PRInt32 * aFlags)
{
nsresult res;
if (!mMappingDone) {
res = CreateMapping();
if NS_FAILED(res) return res;
}
*aFlags = 0;
*aResult = NULL;
*aCount = 0;
if (mDecSize != 0) {
*aResult = new nsString * [mDecSize];
*aCount = mDecSize;
for (PRInt32 i=0;i<mDecSize;i++) (*aResult)[i]=mDecArray[i].mCharset;
}
nsConverterInfo * info = GetConverterInfo(&mEncoderArray, aName);
if (info == NULL) return NS_ERROR_UCONV_NOCONV;
*aFlags = info->mFlags;
return NS_OK;
}
NS_IMETHODIMP nsCharsetConverterManager::GetCharsetName(
const nsString * aCharset,
nsString ** aResult)
{
// XXX add aliases capability here
*aResult = new nsString(*aCharset);
return NS_OK;
}
NS_IMETHODIMP nsCharsetConverterManager::GetCharsetNames(
const nsString * aCharset,
nsString *** aResult,
PRInt32 * aCount)
{
// XXX write me
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP
NS_NewCharsetConverterManager(nsISupports* aOuter, const nsIID& aIID,
void** aResult)
{
if (!aResult) {
return NS_ERROR_INVALID_POINTER;
}
if (aOuter) {
*aResult = nsnull;
return NS_ERROR_NO_AGGREGATION;
}
nsICharsetConverterManager* inst = nsCharsetConverterManager::GetInstance();
if (!inst) {
*aResult = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
return inst->QueryInterface(aIID, aResult);
}

View File

@ -116,9 +116,9 @@ nsresult testCharsetConverterManager()
nsString ** cs;
PRInt32 ct;
res = ccMan->GetDecodableCharsets(&cs, &ct);
res = ccMan->GetDecoderList(&cs, &ct);
if (NS_FAILED(res)) {
printf("ERROR at GetDecodableCharsets() code=0x%x.\n", res);
printf("ERROR at GetDecoderList() code=0x%x.\n", res);
} else {
printf("UDecoders (%d): ", ct);
for (int i=0;i<ct;i++) {
@ -130,9 +130,9 @@ nsresult testCharsetConverterManager()
}
delete [] cs;
res = ccMan->GetEncodableCharsets(&cs, &ct);
res = ccMan->GetEncoderList(&cs, &ct);
if (NS_FAILED(res)) {
printf("ERROR at GetEncodableCharsets() code=0x%x.\n", res);
printf("ERROR at GetEncoderList() code=0x%x.\n", res);
} else {
printf("UEncoders (%d): ", ct);
for (int i=0;i<ct;i++) {