Bug 393356. Spellchecker should not use private copy(ies) of the Unicode category tables. r=smontagu,a=damon
authorroc+@cs.cmu.edu
Tue, 28 Aug 2007 19:03:31 -0700
changeset 5409 3a3ab650edbd76ed5474ecc4ed1423b3356c37a7
parent 5408 938b730dc225317d86f03a28c9245e7692ecda88
child 5410 46513f1a2baec0f044511772e97908b1594b2539
push idunknown
push userunknown
push dateunknown
reviewerssmontagu, damon
bugs393356
milestone1.9a8pre
Bug 393356. Spellchecker should not use private copy(ies) of the Unicode category tables. r=smontagu,a=damon
extensions/spellcheck/src/mozEnglishWordUtils.cpp
extensions/spellcheck/src/mozEnglishWordUtils.h
extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
extensions/spellcheck/src/mozInlineSpellWordUtil.h
intl/build/nsI18nModule.cpp
intl/unicharutil/public/Makefile.in
intl/unicharutil/public/nsIUGenCategory.h
intl/unicharutil/public/nsUnicharUtilCIID.h
intl/unicharutil/src/Makefile.in
intl/unicharutil/src/nsCategoryImp.cpp
intl/unicharutil/src/nsCategoryImp.h
intl/unicharutil/src/nsUcharUtilConstructors.h
--- a/extensions/spellcheck/src/mozEnglishWordUtils.cpp
+++ b/extensions/spellcheck/src/mozEnglishWordUtils.cpp
@@ -36,26 +36,27 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozEnglishWordUtils.h"
 #include "nsICharsetAlias.h"
 #include "nsReadableUtils.h"
 #include "nsIServiceManager.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsCRT.h"
-#include "cattable.h"
 
 NS_IMPL_ISUPPORTS1(mozEnglishWordUtils, mozISpellI18NUtil)
 
 mozEnglishWordUtils::mozEnglishWordUtils()
 {
   mLanguage.AssignLiteral("en");
 
   nsresult rv;
   mURLDetector = do_CreateInstance(MOZ_TXTTOHTMLCONV_CONTRACTID, &rv);
+  mCaseConv = do_GetService(NS_UNICHARUTIL_CONTRACTID);
+  mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID);
 }
 
 mozEnglishWordUtils::~mozEnglishWordUtils()
 {
 }
 
 /* attribute wstring language; */
 NS_IMETHODIMP mozEnglishWordUtils::GetLanguage(PRUnichar * *aLanguage)
@@ -73,22 +74,16 @@ NS_IMETHODIMP mozEnglishWordUtils::GetLa
 NS_IMETHODIMP mozEnglishWordUtils::GetRootForm(const PRUnichar *aWord, PRUint32 type, PRUnichar ***words, PRUint32 *count)
 {
   nsAutoString word(aWord);
   PRUnichar **tmpPtr;
   PRInt32 length = word.Length();
 
   *count = 0;
 
-  if (!mCaseConv) {
-    mCaseConv = do_GetService(NS_UNICHARUTIL_CONTRACTID);
-    if (!mCaseConv)
-      return NS_ERROR_FAILURE;
-  }
-
   mozEnglishWordUtils::myspCapitalization ct = captype(word);
   switch (ct)
     {
     case HuhCap:
     case NoCap: 
       tmpPtr = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *));
       if (!tmpPtr)
         return NS_ERROR_OUT_OF_MEMORY;
@@ -154,20 +149,20 @@ NS_IMETHODIMP mozEnglishWordUtils::GetRo
       break;
     default:
       return NS_ERROR_FAILURE; // should never get here;
     }
   return NS_OK;
 }
 
 // This needs vast improvement
-static PRBool ucIsAlpha(PRUnichar c)
+PRBool mozEnglishWordUtils::ucIsAlpha(PRUnichar aChar)
 {
   // XXX we have to fix callers to handle the full Unicode range
-  return (5 == GetCat(PRUint32(c)));
+  return nsIUGenCategory::kLetter == mCategories->Get(PRUint32(aChar));
 }
 
 /* void FindNextWord (in wstring word, in PRUint32 length, in PRUint32 offset, out PRUint32 begin, out PRUint32 end); */
 NS_IMETHODIMP mozEnglishWordUtils::FindNextWord(const PRUnichar *word, PRUint32 length, PRUint32 offset, PRInt32 *begin, PRInt32 *end)
 {
   const PRUnichar *p = word + offset;
   const PRUnichar *endbuf = word + length;
   const PRUnichar *startWord=p;
--- a/extensions/spellcheck/src/mozEnglishWordUtils.h
+++ b/extensions/spellcheck/src/mozEnglishWordUtils.h
@@ -39,16 +39,17 @@
 #define mozEnglishWordUtils_h__
 
 #include "nsCOMPtr.h"
 #include "mozISpellI18NUtil.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsString.h"
 #include "nsICaseConversion.h"
+#include "nsIUGenCategory.h"
 
 #include "mozITXTToHTMLConv.h" 
 
 class mozEnglishWordUtils : public mozISpellI18NUtil
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_MOZISPELLI18NUTIL
@@ -57,16 +58,18 @@ public:
   virtual ~mozEnglishWordUtils();
   /* additional members */
   enum myspCapitalization{
     NoCap,InitCap,AllCap,HuhCap
   };  
 
 protected:
   mozEnglishWordUtils::myspCapitalization captype(const nsString &word);
+  PRBool ucIsAlpha(PRUnichar aChar);
 
   nsString mLanguage;
   nsString mCharset;
   nsCOMPtr<nsICaseConversion> mCaseConv;
+  nsCOMPtr<nsIUGenCategory>   mCategories;
   nsCOMPtr<mozITXTToHTMLConv> mURLDetector; // used to detect urls so the spell checker can skip them.
 };
 
 #endif
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -31,37 +31,30 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "cattable.h"
 #include "mozInlineSpellWordUtil.h"
 #include "nsDebug.h"
 #include "nsIAtom.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMDocumentView.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNSRange.h"
 #include "nsIDOMRange.h"
 #include "nsIEditor.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMHTMLBRElement.h"
-
-// some character categories we care about from GetCat()
-#define CHAR_CAT_NUMBER 2
-#define CHAR_CAT_SPACE 3
-#define CHAR_CAT_CONTROL 4
-#define CHAR_CAT_WORD 5
-#define CHAR_CAT_PUNCTUATION1 6
-#define CHAR_CAT_PUNCTUATION2 7
+#include "nsUnicharUtilCIID.h"
+#include "nsServiceManagerUtils.h"
 
 // IsIgnorableCharacter
 //
 //    These characters are ones that we should ignore in input.
 
 inline PRBool IsIgnorableCharacter(PRUnichar ch)
 {
   return (ch == 0x200D || // ZERO-WIDTH JOINER
@@ -82,16 +75,20 @@ inline PRBool IsConditionalPunctuation(P
 
 // mozInlineSpellWordUtil::Init
 
 nsresult
 mozInlineSpellWordUtil::Init(nsWeakPtr aWeakEditor)
 {
   nsresult rv;
 
+  mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID, &rv);
+  if (NS_FAILED(rv))
+    return rv;
+  
   // getting the editor can fail commonly because the editor was detached, so
   // don't assert
   nsCOMPtr<nsIEditor> editor = do_QueryReferent(aWeakEditor, &rv);
   if (NS_FAILED(rv))
     return rv;
 
   nsCOMPtr<nsIDOMDocument> domDoc;
   rv = editor->GetDocument(getter_AddRefs(domDoc));
@@ -836,18 +833,19 @@ WordSplitState::ClassifyCharacter(PRInt3
 {
   NS_ASSERTION(aIndex >= 0 && aIndex <= PRInt32(mDOMWordText.Length()),
                "Index out of range");
   if (aIndex == PRInt32(mDOMWordText.Length()))
     return CHAR_CLASS_SEPARATOR;
 
   // this will classify the character, we want to treat "ignorable" characters
   // such as soft hyphens as word characters.
-  PRInt32 charCategory = GetCat(mDOMWordText[aIndex]);
-  if (charCategory == CHAR_CAT_WORD ||
+  nsIUGenCategory::nsUGenCategory
+    charCategory = mWordUtil->GetCategories()->Get(PRUint32(mDOMWordText[aIndex]));
+  if (charCategory == nsIUGenCategory::kLetter ||
       IsIgnorableCharacter(mDOMWordText[aIndex]))
     return CHAR_CLASS_WORD;
 
   // If conditional punctuation is surrounded immediately on both sides by word
   // characters it also counts as a word character.
   if (IsConditionalPunctuation(mDOMWordText[aIndex])) {
     if (!aRecurse) {
       // not allowed to look around, this punctuation counts like a separator
@@ -866,20 +864,20 @@ WordSplitState::ClassifyCharacter(PRInt3
     if (ClassifyCharacter(aIndex + 1, false) != CHAR_CLASS_WORD)
       return CHAR_CLASS_SEPARATOR;
 
     // char on either side is a word, this counts as a word
     return CHAR_CLASS_WORD;
   }
 
   // all other punctuation
-  if (charCategory == CHAR_CAT_SPACE ||
-      charCategory == CHAR_CAT_CONTROL ||
-      charCategory == CHAR_CAT_PUNCTUATION1 ||
-      charCategory == CHAR_CAT_PUNCTUATION2)
+  if (charCategory == nsIUGenCategory::kSeparator ||
+      charCategory == nsIUGenCategory::kOther ||
+      charCategory == nsIUGenCategory::kPunctuation ||
+      charCategory == nsIUGenCategory::kSymbol)
     return CHAR_CLASS_SEPARATOR;
 
   // any other character counts as a word
   return CHAR_CLASS_WORD;
 }
 
 
 // WordSplitState::Advance
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.h
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.h
@@ -37,16 +37,17 @@
 
 #include "nsCOMPtr.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentRange.h"
 #include "nsIDOMViewCSS.h"
 #include "nsIDocument.h"
 #include "nsString.h"
 #include "nsTArray.h"
+#include "nsIUGenCategory.h"
 
 //#define DEBUG_SPELLCHECK
 
 class nsIDOMRange;
 class nsIDOMNode;
 
 /**
  *    This class extracts text from the DOM and builds it into a single string.
@@ -113,23 +114,25 @@ public:
 
   // Call to normalize some punctuation. This function takes an autostring
   // so we can access characters directly.
   static void NormalizeWord(nsSubstring& aWord);
 
   nsIDOMDocumentRange* GetDocumentRange() const { return mDOMDocumentRange; }
   nsIDocument* GetDocument() const { return mDocument; }
   nsIDOMNode* GetRootNode() { return mRootNode; }
-
+  nsIUGenCategory* GetCategories() { return mCategories; }
+  
 private:
 
   // cached stuff for the editor, set by Init
   nsCOMPtr<nsIDOMDocumentRange> mDOMDocumentRange;
   nsCOMPtr<nsIDocument>         mDocument;
   nsCOMPtr<nsIDOMViewCSS>       mCSSView;
+  nsCOMPtr<nsIUGenCategory>     mCategories;
 
   // range to check, see SetRange
   nsIDOMNode* mRootNode;
   NodeOffset  mSoftBegin;
   NodeOffset  mSoftEnd;
 
   // DOM text covering the soft range, with newlines added at block boundaries
   nsString mSoftText;
--- a/intl/build/nsI18nModule.cpp
+++ b/intl/build/nsI18nModule.cpp
@@ -64,16 +64,18 @@ static nsModuleComponentInfo components[
   { "Word Breaker", NS_WBRK_CID,
     NS_WBRK_CONTRACTID, nsSampleWordBreakerConstructor},
   { "Semantic Unit Scanner", NS_SEMANTICUNITSCANNER_CID,
     NS_SEMANTICUNITSCANNER_CONTRACTID, nsSemanticUnitScannerConstructor},
 
  // unicharutil
   { "Unichar Utility", NS_UNICHARUTIL_CID, 
       NS_UNICHARUTIL_CONTRACTID, nsCaseConversionImp2Constructor},
+  { "Unichar Category Table", NS_UNICHARCATEGORY_CID, 
+      NS_UNICHARCATEGORY_CONTRACTID, nsCategoryImpConstructor},
   { "Unicode To Entity Converter", NS_ENTITYCONVERTER_CID, 
       NS_ENTITYCONVERTER_CONTRACTID, nsEntityConverterConstructor },
   { "Unicode To Charset Converter", NS_SAVEASCHARSET_CID, 
       NS_SAVEASCHARSET_CONTRACTID, nsSaveAsCharsetConstructor},
   { "Japanese Hankaku To Zenkaku", NS_HANKAKUTOZENKAKU_CID, 
       NS_HANKAKUTOZENKAKU_CONTRACTID, CreateNewHankakuToZenkaku},
   { "Unicode Normlization", NS_UNICODE_NORMALIZER_CID, 
       NS_UNICODE_NORMALIZER_CONTRACTID,  nsUnicodeNormalizerConstructor},
--- a/intl/unicharutil/public/Makefile.in
+++ b/intl/unicharutil/public/Makefile.in
@@ -43,15 +43,15 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= unicharutil
 
 EXPORTS		= \
 		nsICaseConversion.h \
 		nsIOrderIdFormater.h \
 		nsITextTransform.h \
-		nsIUGenDetailCategory.h \
+		nsIUGenCategory.h \
 		nsUnicharUtilCIID.h \
 		nsHankakuToZenkakuCID.h \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/intl/unicharutil/public/nsIUGenCategory.h
+++ b/intl/unicharutil/public/nsIUGenCategory.h
@@ -36,51 +36,44 @@
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsIUGenCategory_h__
 #define nsIUGenCategory_h__
 
 
 #include "nsISupports.h"
 #include "nscore.h"
 
-// {E86B3371-BF89-11d2-B3AF-00805F8A6670}
+// {671fea05-fcee-4b1c-82a3-6eb03eda8ddc}
 #define NS_IUGENCATEGORY_IID \
-{ 0xe86b3371, 0xbf89, 0x11d2, \
-    { 0xb3, 0xaf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70 } }
+{ 0x671fea05, 0xfcee, 0x4b1c, \
+    { 0x82, 0xa3, 0x6e, 0xb0, 0x3e, 0xda, 0x8d, 0xdc } }
 
 
 class nsIUGenCategory : public nsISupports {
 
 public: 
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IUGENCATEGORY_IID)
 
    /**
-    *  Read ftp://ftp.unicode.org/Public/UNIDATA/ReadMe-Latest.txt
-    *  section GENERAL CATEGORY
-    *  for the detail defintation of the following categories
+    *  Read http://www.unicode.org/Public/UNIDATA/UCD.html#General_Category_Values
+    *  for the detailed definition of the following categories
     */
    typedef enum {
-     kUGenCategory_Mark         = 1, // Mn, Mc, and Me
-     kUGenCategory_Number       = 2, // Nd, Nl, and No 
-     kUGenCategory_Separator    = 3, // Zs, Zl, and Zp
-     kUGenCategory_Other        = 4, // Cc, Cf, Cs, Co, and Cn
-     kUGenCategory_Letter       = 5, // Lu, Ll, Lt, Lm, and Lo
-     kUGenCategory_Punctuation  = 6, // Pc, Pd, Ps, Pe, Pi, Pf, and Po
-     kUGenCategory_Symbol       = 7  // Sm, Sc, Sk, and So
+     kUndefined    = 0,
+     kMark         = 1, // Mn, Mc, and Me
+     kNumber       = 2, // Nd, Nl, and No 
+     kSeparator    = 3, // Zs, Zl, and Zp
+     kOther        = 4, // Cc, Cf, Cs, Co, and Cn
+     kLetter       = 5, // Lu, Ll, Lt, Lm, and Lo
+     kPunctuation  = 6, // Pc, Pd, Ps, Pe, Pi, Pf, and Po
+     kSymbol       = 7  // Sm, Sc, Sk, and So
    } nsUGenCategory;
 
    /**
     * Give a Unichar, return a nsUGenCategory
     */
-   NS_IMETHOD Get( PRUnichar aChar, nsUGenCategory* oResult) = 0 ;
-    
-   /**
-    * Give a Unichar, and a nsUGenCategory, 
-    * return PR_TRUE if the Unichar is in that category, 
-    * return PR_FALSE, otherwise
-    */
-   NS_IMETHOD Is( PRUnichar aChar, nsUGenCategory aCategory, PRBool* oResult) = 0;
+   virtual nsUGenCategory Get(PRUint32 aChar) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIUGenCategory, NS_IUGENCATEGORY_IID)
 
 #endif  /* nsIUGenCategory_h__ */
--- a/intl/unicharutil/public/nsUnicharUtilCIID.h
+++ b/intl/unicharutil/public/nsUnicharUtilCIID.h
@@ -41,9 +41,16 @@
 #include "nsISupports.h"
 #include "nscore.h"
 
 #define NS_UNICHARUTIL_CID \
 { 0xcc10c750, 0x9ec3, 0x11d2, \
   { 0xb3, 0xae, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70 } }
 
 #define NS_UNICHARUTIL_CONTRACTID "@mozilla.org/intl/unicharutil;1"
+
+#define NS_UNICHARCATEGORY_CID \
+{ 0x748a1132, 0x671a, 0x409a, \
+  { 0x8d, 0x1d, 0xf1, 0xcd, 0xf6, 0xb3, 0xa6, 0xb4 } }
+
+#define NS_UNICHARCATEGORY_CONTRACTID "@mozilla.org/intl/unicharcategory;1"
+
 #endif
--- a/intl/unicharutil/src/Makefile.in
+++ b/intl/unicharutil/src/Makefile.in
@@ -52,15 +52,16 @@ REQUIRES	= xpcom \
 		  uconv \
 		  intl \
 		  $(NULL)
 
 EXPORTS = cattable.h
 
 CPPSRCS		= \
 		nsCaseConversionImp2.cpp \
+		nsCategoryImp.cpp \
 		nsHankakuToZenkaku.cpp \
 		nsEntityConverter.cpp \
 		nsSaveAsCharset.cpp \
 		nsUnicodeNormalizer.cpp \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/intl/unicharutil/src/nsCategoryImp.cpp
+++ b/intl/unicharutil/src/nsCategoryImp.cpp
@@ -37,41 +37,31 @@
 
 #include "nscore.h"
 #include "pratom.h"
 #include "nsUUDll.h"
 #include "nsISupports.h"
 #include "nsCategoryImp.h"
 #include "cattable.h"
 
-NS_IMPL_ISUPPORTS1(nsCategoryImp, nsIUGenCategory)
+static nsCategoryImp gCategoryImp;
 
+NS_IMPL_THREADSAFE_QUERY_INTERFACE1(nsCategoryImp, nsIUGenCategory)
 
-nsCategoryImp::nsCategoryImp()
+NS_IMETHODIMP_(nsrefcnt) nsCategoryImp::AddRef(void)
 {
-}
-
-nsCategoryImp::~nsCategoryImp()
-{
+  return nsrefcnt(1);
 }
 
-nsresult nsCategoryImp::Get( PRUnichar aChar, nsUGenCategory* oResult)
+NS_IMETHODIMP_(nsrefcnt) nsCategoryImp::Release(void)
 {
-   PRUint8 ret = GetCat(aChar);
-   if( 0 == ret)
-      *oResult = kUGenCategory_Other; // treat it as Cn - Other, Not Assigned
-   else 
-      *oResult = (nsUGenCategory)ret;
-   return NS_OK;
+  return nsrefcnt(1);
 }
-    
-nsresult nsCategoryImp::Is( PRUnichar aChar, nsUGenCategory aCategory, PRBool* oResult)
 
+nsCategoryImp* nsCategoryImp::GetInstance()
 {
-   nsUGenCategory cat ;
-   PRUint8 ret = GetCat(aChar);
-   if( 0 == ret)
-      cat = kUGenCategory_Other; // treat it as Cn - Other, Not Assigned
-   else 
-      cat = (nsUGenCategory)ret;
-   *oResult = (aCategory == cat );
-   return NS_OK;
+  return &gCategoryImp;
 }
+
+nsIUGenCategory::nsUGenCategory nsCategoryImp::Get(PRUint32 aChar)
+{
+  return nsUGenCategory(GetCat(aChar));
+}
--- a/intl/unicharutil/src/nsCategoryImp.h
+++ b/intl/unicharutil/src/nsCategoryImp.h
@@ -32,34 +32,23 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsCategoryImp_h__
 #define nsCategoryImp_h__
 
-#include "nscore.h"
-#include "nsISupports.h"
 #include "nsIUGenCategory.h"
 
 class nsCategoryImp : public nsIUGenCategory {
    NS_DECL_ISUPPORTS
    
-public: 
-   nsCategoryImp();
-   virtual ~nsCategoryImp();
-
-
+public:
+   static nsCategoryImp* GetInstance();
+    
    /**
     * Give a Unichar, return a nsUGenCategory
     */
-   NS_IMETHOD Get( PRUnichar aChar, nsUGenCategory* oResult);
-    
-   /**
-    * Give a Unichar, and a nsUGenCategory, 
-    * return PR_TRUE if the Unichar is in that category, 
-    * return PR_FALSE, otherwise
-    */
-   NS_IMETHOD Is( PRUnichar aChar, nsUGenCategory aCategory, PRBool* oResult);
+   virtual nsUGenCategory Get(PRUint32 aChar);
 };
 
 #endif  /* nsCategoryImp_h__ */
--- a/intl/unicharutil/src/nsUcharUtilConstructors.h
+++ b/intl/unicharutil/src/nsUcharUtilConstructors.h
@@ -35,16 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsUcharUtilConstructors_h__
 #define nsUcharUtilConstructors_h__
 
 #include "nsUnicharUtilCIID.h"
 #include "nsCaseConversionImp2.h"
+#include "nsCategoryImp.h"
 #include "nsHankakuToZenkakuCID.h"
 #include "nsTextTransformFactory.h"
 #include "nsICaseConversion.h"
 #include "nsEntityConverter.h"
 #include "nsSaveAsCharset.h"
 #include "nsUUDll.h"
 #include "nsIFile.h"
 #include "nsUnicodeNormalizer.h"
@@ -77,13 +78,15 @@ CreateNew##_name(nsISupports* aOuter, RE
     return rv;                                                       \
 }
 
 
 UNICHARUTIL_MAKE_CTOR(HankakuToZenkaku)
 
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsCaseConversionImp2,
                                          nsCaseConversionImp2::GetInstance)
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsCategoryImp,
+                                         nsCategoryImp::GetInstance)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsEntityConverter)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSaveAsCharset)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUnicodeNormalizer)
 
 #endif