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 id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
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