Index: framework/source/services/urltransformer.cxx
===================================================================
RCS file: /cvs/framework/framework/source/services/urltransformer.cxx,v
retrieving revision 1.14
retrieving revision 1.14.88.1
diff -u -p -u -p -r1.14 -r1.14.88.1
--- framework/source/services/urltransformer.cxx	16 Sep 2006 14:12:58 -0000	1.14
+++ framework/source/services/urltransformer.cxx	8 Feb 2007 14:17:11 -0000	1.14.88.1
@@ -229,6 +229,7 @@ sal_Bool SAL_CALL URLTransformer::parseS
 				// INetURLObject supports only an intelligent method of parsing URL's. So write
 				// back Complete to have a valid encoded URL in all cases!
 				aURL.Complete	= aParser.GetMainURL( INetURLObject::NO_DECODE           );
+                aURL.Complete   = aURL.Complete.intern();
 
 				aParser.SetMark	( OUString() );
 				aParser.SetParam( OUString() );
Index: framework/source/xml/acceleratorconfigurationreader.cxx
===================================================================
RCS file: /cvs/framework/framework/source/xml/acceleratorconfigurationreader.cxx,v
retrieving revision 1.5
retrieving revision 1.5.88.1
diff -u -p -u -p -r1.5 -r1.5.88.1
--- framework/source/xml/acceleratorconfigurationreader.cxx	16 Sep 2006 14:28:52 -0000	1.5
+++ framework/source/xml/acceleratorconfigurationreader.cxx	8 Feb 2007 14:17:11 -0000	1.5.88.1
@@ -185,7 +185,7 @@ void SAL_CALL AcceleratorConfigurationRe
             switch(eAttribute)
             {
                 case E_ATTRIBUTE_URL :
-                    sCommand = sValue;
+                    sCommand = sValue.intern();
                     break;
                 
                 case E_ATTRIBUTE_KEYCODE :
Index: framework/source/xml/menudocumenthandler.cxx
===================================================================
RCS file: /cvs/framework/framework/source/xml/menudocumenthandler.cxx,v
retrieving revision 1.10
retrieving revision 1.10.82.1
diff -u -p -u -p -r1.10 -r1.10.82.1
--- framework/source/xml/menudocumenthandler.cxx	13 Oct 2006 09:43:38 -0000	1.10
+++ framework/source/xml/menudocumenthandler.cxx	8 Feb 2007 14:17:11 -0000	1.10.82.1
@@ -163,6 +163,7 @@ static void ExtractMenuParameters( const
         if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL ))
         {
             rProp[i].Value >>= rCommandURL;
+            rCommandURL = rCommandURL.intern();
         }
         else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL ))
         {
@@ -258,7 +259,7 @@ void ReadMenuDocumentHandlerBase::initPr
 	rProps[4].Name = m_aType;
 
 	// Common values
-	rProps[0].Value <<= rCommandURL;
+	rProps[0].Value <<= rCommandURL.intern();
 	rProps[1].Value <<= rHelpId;
 	rProps[2].Value <<= Reference< XIndexContainer >();
 	rProps[3].Value <<= rLabel;
Index: framework/source/xml/statusbardocumenthandler.cxx
===================================================================
RCS file: /cvs/framework/framework/source/xml/statusbardocumenthandler.cxx,v
retrieving revision 1.9
retrieving revision 1.9.82.1
diff -u -p -u -p -r1.9 -r1.9.82.1
--- framework/source/xml/statusbardocumenthandler.cxx	12 Oct 2006 10:44:56 -0000	1.9
+++ framework/source/xml/statusbardocumenthandler.cxx	8 Feb 2007 14:17:12 -0000	1.9.82.1
@@ -151,6 +151,7 @@ static void ExtractStatusbarItemParamete
         if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL ))
         {
             rProp[i].Value >>= rCommandURL;
+            rCommandURL = rCommandURL.intern();
         }
         else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL ))
         {
Index: framework/source/xml/toolboxdocumenthandler.cxx
===================================================================
RCS file: /cvs/framework/framework/source/xml/toolboxdocumenthandler.cxx,v
retrieving revision 1.12
retrieving revision 1.12.82.1
diff -u -p -u -p -r1.12 -r1.12.82.1
--- framework/source/xml/toolboxdocumenthandler.cxx	13 Oct 2006 09:43:49 -0000	1.12
+++ framework/source/xml/toolboxdocumenthandler.cxx	8 Feb 2007 14:17:12 -0000	1.12.82.1
@@ -122,7 +122,10 @@ static void ExtractToolbarParameters( co
     for ( sal_Int32 i = 0; i < rProp.getLength(); i++ )
     {
         if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL ))
+        {
             rProp[i].Value >>= rCommandURL;
+            rCommandURL = rCommandURL.intern();
+        }
         else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL ))
             rProp[i].Value >>= rHelpURL;
         else if ( rProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL ))
@@ -362,7 +365,7 @@ throw(	SAXException, RuntimeException )
 							case TB_ATTRIBUTE_URL:
 							{
 								bAttributeURL	= sal_True;
-								aCommandURL		= xAttribs->getValueByIndex( n );
+								aCommandURL		= xAttribs->getValueByIndex( n ).intern();
 							}
 							break;
 
Index: tools/inc/string.hxx
===================================================================
RCS file: /cvs/util/tools/inc/string.hxx,v
retrieving revision 1.11
retrieving revision 1.11.102.1
diff -u -p -u -p -r1.11 -r1.11.102.1
--- tools/inc/string.hxx	19 Jun 2006 13:30:16 -0000	1.11
+++ tools/inc/string.hxx	8 Feb 2007 14:54:42 -0000	1.11.102.1
@@ -516,6 +516,8 @@ public:
 		return rtl::OUString (reinterpret_cast<rtl_uString*>(mpData));
 	}
 
+    UniString           intern() const;
+
 	static UniString	CreateFromAscii( const sal_Char* pAsciiStr );
 	static UniString	CreateFromAscii( const sal_Char* pAsciiStr, xub_StrLen nLen );
 
Index: tools/source/string/strucvt.cxx
===================================================================
RCS file: /cvs/util/tools/source/string/strucvt.cxx,v
retrieving revision 1.10
retrieving revision 1.10.62.1
diff -u -p -u -p -r1.10 -r1.10.62.1
--- tools/source/string/strucvt.cxx	17 Sep 2006 01:03:58 -0000	1.10
+++ tools/source/string/strucvt.cxx	8 Feb 2007 14:54:42 -0000	1.10.62.1
@@ -167,6 +167,16 @@ UniString& UniString::Assign( const rtl:
 	return *this;
 }
 
+UniString UniString::intern() const
+{
+    UniString aStr;
+
+    rtl_uString_intern( reinterpret_cast<rtl_uString **>(&aStr.mpData),
+                        (rtl_uString *)(&mpData) );
+
+    return aStr;
+}
+
 // =======================================================================
 
 #ifndef _TOOLS_RC_HXX
Index: psprint/source/fontmanager/fontcache.cxx
===================================================================
RCS file: /cvs/gsl/psprint/source/fontmanager/fontcache.cxx,v
retrieving revision 1.23
retrieving revision 1.23.40.1
diff -u -p -u -p -r1.23 -r1.23.40.1
--- psprint/source/fontmanager/fontcache.cxx	16 Sep 2006 12:33:32 -0000	1.23
+++ psprint/source/fontmanager/fontcache.cxx	8 Feb 2007 14:29:15 -0000	1.23.40.1
@@ -464,7 +464,9 @@ void FontCache::read()
                     default: break;
                 }
                 if( nTokens > nStyleTokenNr )
-                    pFont->m_aStyleName = OUString( pLine + nTokenPos[nStyleTokenNr], nLen - nTokenPos[nStyleTokenNr], RTL_TEXTENCODING_UTF8 );
+                    pFont->m_aStyleName = OUString::intern( pLine + nTokenPos[nStyleTokenNr],
+                                                            nLen - nTokenPos[nStyleTokenNr],
+                                                            RTL_TEXTENCODING_UTF8 );
 
                 bool bObsolete = false;
                 if( bKeepOnlyUserOverridden )
Index: configmgr/source/backend/binaryreader.cxx
===================================================================
RCS file: /cvs/util/configmgr/source/backend/binaryreader.cxx,v
retrieving revision 1.7
retrieving revision 1.7.32.2
diff -u -p -u -p -r1.7 -r1.7.32.2
--- configmgr/source/backend/binaryreader.cxx	16 Sep 2006 15:02:54 -0000	1.7
+++ configmgr/source/backend/binaryreader.cxx	8 Feb 2007 17:33:15 -0000	1.7.32.2
@@ -542,8 +542,8 @@ namespace configmgr
 
                 rtl_TextEncoding const enc = bIsAscii ? RTL_TEXTENCODING_ASCII_US : RTL_TEXTENCODING_UTF8;
 
-                rtl_string2UString( &result.pData, pUTF, nStrLength, 
-					                enc, OSTRING_TO_OUSTRING_CVTFLAGS);
+                rtl_uString_internConvert(&result.pData, pUTF, nStrLength, enc,
+                                          OSTRING_TO_OUSTRING_CVTFLAGS, NULL);
 			}
 
 			return result;
Index: configmgr/source/backend/binaryreadhandler.cxx
===================================================================
RCS file: /cvs/util/configmgr/source/backend/binaryreadhandler.cxx,v
retrieving revision 1.9
retrieving revision 1.9.22.1
diff -u -p -u -p -r1.9 -r1.9.22.1
--- configmgr/source/backend/binaryreadhandler.cxx	6 Nov 2006 14:46:33 -0000	1.9
+++ configmgr/source/backend/binaryreadhandler.cxx	8 Feb 2007 15:06:11 -0000	1.9.22.1
@@ -81,8 +81,6 @@ namespace configmgr
         , m_aNodeFactory()
         , m_aComponentName(_aComponentName)
 		{
-			for (int i = 0; i < LastEntry; i++)
-				m_nInsert[i] = 0;
 		}
 		// -----------------------------------------------------------------------------
 		BinaryReadHandler::~BinaryReadHandler()
@@ -288,19 +286,10 @@ namespace configmgr
 			m_BinaryReader.read (_aString);
 		}
 
-		void BinaryReadHandler::readName(rtl::OUString &_aString, NamePool ePool)
+		void BinaryReadHandler::readName(rtl::OUString &_aString)
 			SAL_THROW( (io::IOException, uno::RuntimeException) )
 		{
 			m_BinaryReader.read (_aString);
-			const int nElems = (sizeof (m_aPreviousName[0])
-								/ sizeof (m_aPreviousName[0][0]));
-			for (int i = 0; i < nElems; i++)
-			{
-				if (m_aPreviousName[ePool][i] == _aString)
-					_aString = m_aPreviousName[ePool][i];
-			}
-			m_aPreviousName[ePool][m_nInsert[ePool]++] = _aString;
-			m_nInsert[ePool] %= nElems;
 		}
 
 		// -----------------------------------------------------------------------------
@@ -331,7 +320,7 @@ namespace configmgr
 			SAL_THROW( (io::IOException, uno::RuntimeException) )
 		{
 			readAttributes(_aAttributes);
-			readName(_aName, GroupName);
+			readName(_aName);
 		}
 		// -----------------------------------------------------------------------------	
 		void BinaryReadHandler::readSet(rtl::OUString &_aName, node::Attributes &_aAttributes,
@@ -339,9 +328,9 @@ namespace configmgr
 			SAL_THROW( (io::IOException, uno::RuntimeException) )
 		{
 			readAttributes(_aAttributes);
-			readName(_aName, SetName);
-			readName(_sInstanceName, InstanceName);
-			readName(_sInstanceModule, InstanceModule);
+			readName(_aName);
+			readName(_sInstanceName);
+			readName(_sInstanceModule);
 		}
 			
 		// -----------------------------------------------------------------------------
@@ -441,7 +430,7 @@ namespace configmgr
 
 			ValueFlags::Type eBasicType = readValueFlags(bSeq, bHasValue, bHasDefault);
 			readAttributes(_aAttributes);
-			readName(_aName, ValueName);
+			readName(_aName);
 			
 			if (!bSeq && (bHasValue || bHasDefault))
 			{
Index: configmgr/source/backend/binaryreadhandler.hxx
===================================================================
RCS file: /cvs/util/configmgr/source/backend/binaryreadhandler.hxx,v
retrieving revision 1.8
retrieving revision 1.8.22.1
diff -u -p -u -p -r1.8 -r1.8.22.1
--- configmgr/source/backend/binaryreadhandler.hxx	6 Nov 2006 14:46:59 -0000	1.8
+++ configmgr/source/backend/binaryreadhandler.hxx	8 Feb 2007 15:06:11 -0000	1.8.22.1
@@ -96,17 +96,6 @@ namespace configmgr
             ComponentDataFactory m_aNodeFactory;
             rtl::OUString        m_aComponentName;
 
-			// pool recent strings for re-use
-			enum NamePool {
-					GroupName,
-					SetName,
-					InstanceName,
-					InstanceModule,
-					ValueName,
-					LastEntry
-			};
-			int           m_nInsert[LastEntry];
-			rtl::OUString m_aPreviousName[LastEntry][8];
 		public:
 			BinaryReadHandler(rtl::OUString const & _aFileURL, rtl::OUString const & _aComponentName, MultiServiceFactory const & _aFactory);
 			~BinaryReadHandler();
@@ -167,7 +156,7 @@ namespace configmgr
 											  uno::Any& _aValue, uno::Any& _aDefaultValue,uno::Type& _aType)
 			    SAL_THROW( (io::IOException, uno::RuntimeException) );
 
-			void readName(rtl::OUString &_aString, NamePool ePool)
+			void readName(rtl::OUString &_aString)
 				SAL_THROW( (io::IOException, uno::RuntimeException) );
 		};
 	// ---------------------------------------------------------------------------
Index: vcl/source/gdi/impimagetree.cxx
===================================================================
RCS file: /cvs/gsl/vcl/source/gdi/impimagetree.cxx,v
retrieving revision 1.12
retrieving revision 1.12.160.1
diff -u -p -u -p -r1.12 -r1.12.160.1
--- vcl/source/gdi/impimagetree.cxx	17 Sep 2006 12:03:34 -0000	1.12
+++ vcl/source/gdi/impimagetree.cxx	8 Feb 2007 14:26:16 -0000	1.12.160.1
@@ -594,7 +594,7 @@ bool ImplImageTree::loadImage( const ::r
 	}
 
 	if( !rReturn.IsEmpty() )
-		aBmpExHashMap[ rName ] = rReturn;
+		aBmpExHashMap[ rName.intern() ] = rReturn;
 	
 	return( !rReturn.IsEmpty() );
 }
Index: sal/inc/rtl/string.h
===================================================================
RCS file: /cvs/porting/sal/inc/rtl/string.h,v
retrieving revision 1.14
retrieving revision 1.14.94.2
diff -u -p -u -p -r1.14 -r1.14.94.2
--- sal/inc/rtl/string.h	20 Jun 2006 04:14:27 -0000	1.14
+++ sal/inc/rtl/string.h	8 Feb 2007 15:19:19 -0000	1.14.94.2
@@ -39,6 +39,9 @@
 #ifndef _SAL_TYPES_H_
 #include <sal/types.h>
 #endif
+#ifndef _OSL_INTERLOCK_H_
+#include <osl/interlck.h>
+#endif
 #ifndef _RTL_TEXTCVT_H
 #include <rtl/textcvt.h>
 #endif
@@ -762,9 +765,9 @@ double SAL_CALL rtl_str_toDouble( const 
  */
 typedef struct _rtl_String
 {
-    sal_Int32       refCount;
-    sal_Int32       length;
-    sal_Char        buffer[1];
+    oslInterlockedCount refCount; /* opaque */
+    sal_Int32           length;
+    sal_Char            buffer[1];
 } rtl_String;
 
 #ifdef SAL_W32
Index: sal/inc/rtl/string.hxx
===================================================================
RCS file: /cvs/porting/sal/inc/rtl/string.hxx,v
retrieving revision 1.21
retrieving revision 1.21.94.2
diff -u -p -u -p -r1.21 -r1.21.94.2
Index: sal/inc/rtl/ustring.h
===================================================================
RCS file: /cvs/porting/sal/inc/rtl/ustring.h,v
retrieving revision 1.17
retrieving revision 1.17.94.5
diff -u -p -u -p -r1.17 -r1.17.94.5
--- sal/inc/rtl/ustring.h	20 Jun 2006 04:14:53 -0000	1.17
+++ sal/inc/rtl/ustring.h	8 Feb 2007 17:05:25 -0000	1.17.94.5
@@ -39,6 +39,9 @@
 #ifndef _SAL_TYPES_H_
 #include <sal/types.h>
 #endif
+#ifndef _OSL_INTERLOCK_H_
+#include <osl/interlck.h>
+#endif
 #ifndef _RTL_STRING_H_
 #include <rtl/string.h>
 #endif
@@ -1030,9 +1033,9 @@ double SAL_CALL rtl_ustr_toDouble( const
 */
 typedef struct _rtl_uString
 {
-    sal_Int32       refCount;
-    sal_Int32       length;
-    sal_Unicode     buffer[1];
+    oslInterlockedCount refCount; /* opaque */
+    sal_Int32           length;
+    sal_Unicode         buffer[1];
 } rtl_uString;
 
 #ifdef SAL_W32
@@ -1430,6 +1433,67 @@ sal_Int32 SAL_CALL rtl_uString_getToken(
     details.
  */
 void SAL_CALL rtl_string2UString( rtl_uString ** newStr, const sal_Char * str, sal_Int32 len, rtl_TextEncoding encoding, sal_uInt32 convertFlags ) SAL_THROW_EXTERN_C();
+
+/* ======================================================================= */
+/* Interning methods */
+
+/** Return a canonical representation for a string.
+
+    A pool of strings, initially empty is maintained privately
+    by the string class. On invocation, if present in the pool
+    the original string will be returned. Otherwise this string,
+    or a copy thereof will be added to the pool and returned.
+
+    @param newStr
+    pointer to the new string.  The pointed-to data must be null or a valid
+    string.
+
+    @param str
+    pointer to the string to be interned.
+
+    @since UDK 3.2.7
+ */
+void SAL_CALL rtl_uString_intern( rtl_uString ** newStr,
+                                  rtl_uString  * str) SAL_THROW_EXTERN_C();
+
+/** Return a canonical representation for a string.
+
+    A pool of strings, initially empty is maintained privately
+    by the string class. On invocation, if present in the pool
+    the original string will be returned. Otherwise this string,
+    or a copy thereof will be added to the pool and returned.
+
+    @param newStr
+    pointer to the new string.  The pointed-to data must be null or a valid
+    string.
+
+    @param str
+    a byte character array.  Need not be null-terminated, but must be at
+    least as long as the specified len.
+
+    @param len
+    the length of the byte character array.
+
+    @param encoding
+    the text encoding to use for conversion.
+
+    @param convertFlags
+    flags which control the conversion.  Either use
+    OSTRING_TO_OUSTRING_CVTFLAGS, or see
+    <http://udk.openoffice.org/cpp/man/spec/textconversion.html> for more
+    details.
+
+    @param pInfo
+    pointer to return conversion status in, or NULL.
+
+    @since UDK 3.2.7
+ */
+void SAL_CALL rtl_uString_internConvert( rtl_uString   ** newStr,
+                                         const sal_Char * str,
+                                         sal_Int32        len,
+                                         rtl_TextEncoding encoding,
+                                         sal_uInt32       convertFlags,
+                                         sal_uInt32      *pInfo) SAL_THROW_EXTERN_C();
 
 #ifdef __cplusplus
 }
Index: sal/inc/rtl/ustring.hxx
===================================================================
RCS file: /cvs/porting/sal/inc/rtl/ustring.hxx,v
retrieving revision 1.27
retrieving revision 1.27.52.5
diff -u -p -u -p -r1.27 -r1.27.52.5
--- sal/inc/rtl/ustring.hxx	25 Sep 2006 13:13:38 -0000	1.27
+++ sal/inc/rtl/ustring.hxx	8 Feb 2007 17:10:49 -0000	1.27.52.5
@@ -1082,6 +1082,61 @@ public:
         return rtl_ustr_toDouble( pData->buffer );
     }
 
+
+    /**
+       Return a canonical representation for a string.
+
+       A pool of strings, initially empty is maintained privately
+       by the string class. On invocation, if present in the pool
+       the original string will be returned. Otherwise this string,
+       or a copy thereof will be added to the pool and returned.
+
+       @return
+       a version of the string from the pool.
+
+       @since UDK 3.2.7
+    */
+    OUString intern() const SAL_THROW(())
+    {
+        rtl_uString * pNew = 0;
+        rtl_uString_intern( &pNew, pData );
+        return OUString( pNew, (DO_NOT_ACQUIRE *)0 );
+    }
+
+    /**
+       Return a canonical representation for a converted string.
+
+       A pool of strings, initially empty is maintained privately
+       by the string class. On invocation, if present in the pool
+       the original string will be returned. Otherwise this string,
+       or a copy thereof will be added to the pool and returned.
+
+       @param    value           a 8-Bit character array.
+       @param    length          the number of character which should be converted.
+                                 The 8-Bit character array length must be
+                                 greater or equal than this value.
+       @param    encoding        the text encoding from which the 8-Bit character
+                                 sequence should be converted.
+       @param    convertFlags    flags which controls the conversion.
+                                 see RTL_TEXTTOUNICODE_FLAGS_...
+       @param    pInfo           pointer to return conversion status or NULL.
+
+       @return
+       a version of the converted string from the pool.
+
+       @since UDK 3.2.7
+    */
+    static OUString intern( const sal_Char * value, sal_Int32 length,
+                            rtl_TextEncoding encoding,
+                            sal_uInt32 convertFlags = OSTRING_TO_OUSTRING_CVTFLAGS,
+                            sal_uInt32 *pInfo = NULL ) SAL_THROW(())
+    {
+        rtl_uString * pNew = 0;
+        rtl_uString_internConvert( &pNew, value, length, encoding,
+                                   convertFlags, pInfo );
+        return OUString( pNew, (DO_NOT_ACQUIRE *)0 );
+    }
+
     /**
       Converts to an OString, signalling failure.
 
Index: sal/qa/rtl/oustring/rtl_OUString2.cxx
===================================================================
RCS file: /cvs/porting/sal/qa/rtl/oustring/rtl_OUString2.cxx,v
retrieving revision 1.7
retrieving revision 1.7.58.3
diff -u -p -u -p -r1.7 -r1.7.58.3
--- sal/qa/rtl/oustring/rtl_OUString2.cxx	17 Sep 2006 08:58:11 -0000	1.7
+++ sal/qa/rtl/oustring/rtl_OUString2.cxx	12 Feb 2007 17:56:46 -0000	1.7.58.3
@@ -116,15 +116,6 @@ class valueOf : public CppUnit::TestFixt
         }
 
 public:
-    // initialise your test code values here.
-    void setUp()
-    {
-    }
-
-    void tearDown()
-    {
-    }    
-    
     // insert your test code here.
     void valueOf_float_test_001()
     {
@@ -364,15 +355,6 @@ sal_Int16 SAL_CALL checkPrecisionSize()
     class toDouble : public CppUnit::TestFixture
     {
     public:              
-        // initialise your test code values here.
-        void setUp()
-            {
-            }
-        
-        void tearDown()
-            {
-            }
-
         void toDouble_test_impl(rtl::OString const& _sValue)
             {
             	//t_print("the original str is %s\n", _sValue.getStr());
@@ -510,15 +492,6 @@ sal_Int16 SAL_CALL checkPrecisionSize()
     class toFloat : public CppUnit::TestFixture
     {
     public:       
-        // initialise your test code values here.
-        void setUp()
-            {
-            }
-        
-        void tearDown()
-            {
-            }
-
         void toFloat_test_impl(rtl::OString const& _sValue)
             {
             	//t_print("the original str is %s\n", _sValue.getStr());
@@ -662,18 +635,6 @@ class lastIndexOf : public CppUnit::Test
 {
 
 public:
-        
-    // initialise your test code values here.
-    void setUp()
-        {
-        }
-    
-    void tearDown()
-        {
-        }
-    
-    // -----------------------------------------------------------------------------
-
     void lastIndexOf_oustring(rtl::OUString const& _suStr, rtl::OUString const& _suSearchStr, sal_Int32 _nExpectedResultPos)
         {
             // Algorithm
@@ -889,18 +850,6 @@ class getToken : public CppUnit::TestFix
 {
 
 public:
-        
-    // initialise your test code values here.
-    void setUp()
-        {
-        }
-    
-    void tearDown()
-        {
-        }
-    
-    // -----------------------------------------------------------------------------
-
     void getToken_000()
         {
             rtl::OUString suTokenStr;
@@ -1005,11 +954,92 @@ public:
 }; // class getToken
 
 // -----------------------------------------------------------------------------
+// - string construction & interning (tests)
+// -----------------------------------------------------------------------------
+class construction : public CppUnit::TestFixture
+{
+public:
+    void construct()
+    {
+#ifdef RTL_INLINE_STRINGS
+        ::rtl::OUString aFoo( RTL_CONSTASCII_USTRINGPARAM("foo") );
+        CPPUNIT_ASSERT_MESSAGE("string contents", aFoo[0] == 'f');
+        CPPUNIT_ASSERT_MESSAGE("string contents", aFoo[1] == 'o');
+        CPPUNIT_ASSERT_MESSAGE("string contents", aFoo[2] == 'o');
+        CPPUNIT_ASSERT_MESSAGE("string length", aFoo.getLength() == 3);
+
+        ::rtl::OUString aBaa( RTL_CONSTASCII_USTRINGPARAM("this is a very long string with a lot of long things inside it and it goes on and on and on forever etc.") );
+        CPPUNIT_ASSERT_MESSAGE("string length", aBaa.getLength() == 104);
+        // Dig at the internals ... FIXME: should we have the bit-flag defines public ?
+        CPPUNIT_ASSERT_MESSAGE("string static flags", (aBaa.pData->refCount & 1<<30) != 0);
+#endif
+    }
+
+    void intern()
+    {
+        ::rtl::OUString aFoo( RTL_CONSTASCII_USTRINGPARAM("foo") );
+        ::rtl::OUString aFooIntern = aFoo.intern();
+        CPPUNIT_ASSERT_MESSAGE("string contents", aFooIntern.equalsAscii("foo"));
+        CPPUNIT_ASSERT_MESSAGE("string length", aFooIntern.getLength() == 3);
+        // We have to dup due to no atomic 'intern' bit-set operation
+        CPPUNIT_ASSERT_MESSAGE("intern dups", aFoo.pData != aFooIntern.pData);
+
+        // Test interning lots of things
+        int i;
+        static const int nSequence = 4096;
+        rtl::OUString *pStrs;
+        sal_uIntPtr   *pValues;
+
+        pStrs = new rtl::OUString[nSequence];
+        pValues = new sal_uIntPtr[nSequence];
+        for (i = 0; i < nSequence; i++) 
+        {
+            pStrs[i] = rtl::OUString::valueOf( sqrt( i ) ).intern();
+            pValues[i] = reinterpret_cast<sal_uIntPtr>( pStrs[i].pData );
+        }
+        for (i = 0; i < nSequence; i++) 
+        {
+            rtl::OUString aNew = rtl::OUString::valueOf( sqrt( i ) ).intern();
+            CPPUNIT_ASSERT_MESSAGE("double intern failed",
+                                   aNew.pData == pStrs[i].pData);
+        }
+
+        // Free strings to check for leaks
+        for (i = 0; i < nSequence; i++) 
+        {
+            // Overwrite - hopefully this re-uses the memory
+            pStrs[i] = rtl::OUString();
+            pStrs[i] = rtl::OUString::valueOf( sqrt( i ) );
+        }
+
+        for (i = 0; i < nSequence; i++) 
+        {
+            rtl::OUString aIntern;
+            sal_uIntPtr nValue;
+            aIntern = rtl::OUString::valueOf( sqrt( i ) ).intern();
+
+            nValue = reinterpret_cast<sal_uIntPtr>( aIntern.pData );
+            // This may not be 100% reliable: memory may
+            // have been re-used, but it's worth checking.
+            CPPUNIT_ASSERT_MESSAGE("intern leaking", nValue != pValues[i]);
+        }
+        delete [] pValues;
+        delete [] pStrs;
+    }
+
+    CPPUNIT_TEST_SUITE(construction);
+    CPPUNIT_TEST(construct);
+    CPPUNIT_TEST(intern);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+// -----------------------------------------------------------------------------
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_OUString::valueOf, "rtl_OUString");
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_OUString::toDouble, "rtl_OUString");
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_OUString::toFloat, "rtl_OUString");
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_OUString::lastIndexOf, "rtl_OUString");
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_OUString::getToken, "rtl_OUString");
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_OUString::construction, "rtl_OUString");
 
 } // namespace rtl_OUString
 

Index: sal/rtl/source/hash.cxx
===================================================================
RCS file: sal/rtl/source/hash.cxx
diff -N sal/rtl/source/hash.cxx
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sal/rtl/source/hash.cxx	9 Feb 2007 08:52:58 -0000	1.1.2.3
@@ -0,0 +1,83 @@
+#ifndef INCLUDED_RTL_ALLOCATOR_HXX
+#include "rtl/allocator.hxx"
+#endif
+
+#include "hash.h"
+#include "strimp.h"
+
+
+#include <hash_set>
+
+namespace {
+    struct UStringHash
+    {
+        size_t operator()(rtl_uString * const &rString) const
+            { return (size_t)rtl_ustr_hashCode_WithLength( rString->buffer, rString->length ); }
+    };
+    struct UStringEqual
+    {
+        sal_Bool operator() ( rtl_uString * const &pStringA,
+                              rtl_uString * const &pStringB) const
+        {
+            if (pStringA == pStringB)
+                return true;
+            if (pStringA->length != pStringB->length)
+                return false;
+            return !rtl_ustr_compare_WithLength( pStringA->buffer, pStringA->length,
+                                                 pStringB->buffer, pStringB->length);
+        }
+    };
+}
+
+typedef std::hash_set< rtl_uString *, UStringHash, UStringEqual,
+                       rtl::Allocator<rtl_uString *> > UniqueHash;
+
+struct StringHashTableImpl : public UniqueHash
+{
+    StringHashTableImpl(sal_uInt32 nSize) : UniqueHash( nSize ) {}
+};
+
+StringHashTable *
+rtl_str_hash_new (sal_uInt32 nSize)
+{
+    return new StringHashTableImpl (nSize);
+}
+
+void
+rtl_str_hash_free (StringHashTable *pHash)
+{
+    delete pHash;
+}
+
+rtl_uString *
+rtl_str_hash_intern (StringHashTable   *pHash,
+                     rtl_uString       *pString,
+                     int                can_return)
+{
+    UniqueHash::iterator aIter;
+    aIter = pHash->find(pString);
+    if (aIter != pHash->end())
+    {
+        rtl_uString *pHashStr = *aIter;
+        rtl_uString_acquire (pHashStr);
+        return pHashStr;
+    }
+    if (!can_return)
+    {
+        rtl_uString *pCopy = NULL;
+        rtl_uString_newFromString( &pCopy, pString );
+        pString = pCopy;
+    }
+
+    pString->refCount |= SAL_STRING_INTERN_FLAG;
+    pHash->insert(pString);
+
+    return pString;
+}
+
+void
+rtl_str_hash_remove (StringHashTable   *pHash,
+                     rtl_uString       *pString)
+{
+    pHash->erase(pString);
+}
Index: sal/rtl/source/hash.h
===================================================================
RCS file: sal/rtl/source/hash.h
diff -N sal/rtl/source/hash.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sal/rtl/source/hash.h	7 Feb 2007 14:45:36 -0000	1.1.2.2
@@ -0,0 +1,29 @@
+#ifndef INCLUDED_RTL_SOURCE_HASH_H
+#define INCLUDED_RTL_SOURCE_HASH_H
+
+#ifndef _SAL_TYPES_H_
+#include <sal/types.h>
+#endif
+#ifndef _RTL_USTRING_H_
+#include <rtl/ustring.h>
+#endif
+
+#if defined __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct StringHashTableImpl StringHashTable;
+
+StringHashTable *rtl_str_hash_new    (sal_uInt32         nSize);
+void             rtl_str_hash_free   (StringHashTable   *pHash);
+rtl_uString     *rtl_str_hash_intern (StringHashTable   *pHash,
+                                      rtl_uString       *pString,
+                                      int                can_return);
+void             rtl_str_hash_remove (StringHashTable   *pHash,
+                                      rtl_uString       *pString);
+
+#if defined __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* INCLUDED_RTL_SOURCE_HASH_H */
Index: sal/rtl/source/makefile.mk
===================================================================
RCS file: /cvs/porting/sal/rtl/source/makefile.mk,v
retrieving revision 1.27
retrieving revision 1.26.30.2
diff -u -p -u -p -r1.27 -r1.26.30.2
--- sal/rtl/source/makefile.mk	16 Jan 2007 16:03:17 -0000	1.27
+++ sal/rtl/source/makefile.mk	7 Feb 2007 15:14:34 -0000	1.26.30.2
@@ -76,6 +76,7 @@ SLOFILES=   \
             $(SLO)$/random.obj      \
             $(SLO)$/locale.obj      \
             $(SLO)$/strimp.obj      \
+            $(SLO)$/hash.obj        \
             $(SLO)$/string.obj      \
             $(SLO)$/ustring.obj     \
             $(SLO)$/strbuf.obj      \
@@ -105,6 +106,7 @@ OBJFILES=   \
             $(OBJ)$/random.obj      \
             $(OBJ)$/locale.obj      \
             $(OBJ)$/strimp.obj      \
+            $(OBJ)$/hash.obj        \
             $(OBJ)$/string.obj      \
             $(OBJ)$/ustring.obj     \
             $(OBJ)$/strbuf.obj      \
Index: sal/rtl/source/strimp.h
===================================================================
RCS file: /cvs/porting/sal/rtl/source/strimp.h,v
retrieving revision 1.3
retrieving revision 1.3.204.3
diff -u -p -u -p -r1.3 -r1.3.204.3
--- sal/rtl/source/strimp.h	8 Sep 2005 16:05:25 -0000	1.3
+++ sal/rtl/source/strimp.h	9 Feb 2007 08:52:58 -0000	1.3.204.3
@@ -36,6 +36,10 @@
 #ifndef INCLUDED_RTL_SOURCE_STRIMP_H
 #define INCLUDED_RTL_SOURCE_STRIMP_H
 
+#ifndef _OSL_INTERLOCK_H_
+#include <osl/interlck.h>
+#endif
+
 #include "sal/types.h"
 
 /* ======================================================================= */
@@ -45,6 +49,19 @@
 #if defined __cplusplus
 extern "C" {
 #endif /* __cplusplus */
+
+/*
+ * refCount is opaqueincludes 2 bit-fields;
+ * MSB:   'interned' - is stored in the intern hash
+ * MSB-1: 'static'   - is a const / static string,
+ *                     do no ref counting
+ */
+#define SAL_STRING_INTERN_FLAG 0x80000000
+#define SAL_STRING_STATIC_FLAG 0x40000000
+#define SAL_STRING_REFCOUNT(a) ((a) & 0x3fffffff)
+
+#define SAL_STRING_IS_INTERN(a) ((a)->refCount & SAL_STRING_INTERN_FLAG)
+#define SAL_STRING_IS_STATIC(a) ((a)->refCount & SAL_STRING_STATIC_FLAG)
 
 sal_Int16 rtl_ImplGetDigit( sal_Unicode ch, sal_Int16 nRadix );
 
Index: sal/rtl/source/string.c
===================================================================
RCS file: /cvs/porting/sal/rtl/source/string.c,v
retrieving revision 1.15
retrieving revision 1.15.52.1
diff -u -p -u -p -r1.15 -r1.15.52.1
--- sal/rtl/source/string.c	25 Sep 2006 13:14:24 -0000	1.15
+++ sal/rtl/source/string.c	25 Jan 2007 17:56:37 -0000	1.15.52.1
@@ -71,7 +71,8 @@
 // MT: Should be const, but doesn't work because of #i64835#
 static rtl_String aImplEmpty_rtl_String =
 {
-    1,      /* sal_Int32    refCount;   */
+    SAL_STRING_STATIC_FLAG|1,
+            /* sal_Int32    refCount;   */
     0,      /* sal_Int32    length;     */
     { 0 }   /* sal_Char     buffer[1];  */
 };
Index: sal/rtl/source/strtmpl.c
===================================================================
RCS file: /cvs/porting/sal/rtl/source/strtmpl.c,v
retrieving revision 1.22
retrieving revision 1.22.94.2
diff -u -p -u -p -r1.22 -r1.22.94.2
--- sal/rtl/source/strtmpl.c	20 Jun 2006 04:30:39 -0000	1.22
+++ sal/rtl/source/strtmpl.c	7 Feb 2007 14:45:36 -0000	1.22.94.2
@@ -1025,7 +1025,7 @@ static IMPL_RTL_STRCODE* IMPL_RTL_STRING
 
 #define IMPL_RTL_AQUIRE( pThis )                                \
 {                                                               \
-    if (pThis != &IMPL_RTL_EMPTYSTRING)                         \
+    if (!SAL_STRING_IS_STATIC (pThis))                          \
         osl_incrementInterlockedCount( &((pThis)->refCount) );  \
 }
 
@@ -1040,17 +1040,21 @@ void SAL_CALL IMPL_RTL_STRINGNAME( acqui
 
 void SAL_CALL IMPL_RTL_STRINGNAME( release )( IMPL_RTL_STRINGDATA* pThis )
 {
-	if (pThis == &IMPL_RTL_EMPTYSTRING)
-		return;
+    if (SAL_STRING_IS_STATIC (pThis))
+        return;
 
-    if ( pThis->refCount == 1 )
+/* OString doesn't have an 'intern' */
+#ifdef IMPL_RTL_INTERN
+    if (SAL_STRING_IS_INTERN (pThis))
     {
-        OSL_ENSURE( pThis != &IMPL_RTL_EMPTYSTRING, "static empty string: refCount < 1" );
-        rtl_freeMemory( pThis );
+        internRelease (pThis);
+        return;
     }
-    else if ( !osl_decrementInterlockedCount( &(pThis->refCount) ) )
+#endif
+
+    if ( pThis->refCount == 1 ||
+         !osl_decrementInterlockedCount( &(pThis->refCount) ) )
     {
-        OSL_ENSURE( IMPL_RTL_EMPTYSTRING.refCount >= 1, "static empty string: refCount < 1" );
         rtl_freeMemory( pThis );
     }
 }
Index: sal/rtl/source/ustring.c
===================================================================
RCS file: /cvs/porting/sal/rtl/source/ustring.c,v
retrieving revision 1.24
retrieving revision 1.24.38.7
diff -u -p -u -p -r1.24 -r1.24.38.7
--- sal/rtl/source/ustring.c	27 Oct 2006 12:14:32 -0000	1.24
+++ sal/rtl/source/ustring.c	9 Feb 2007 08:52:58 -0000	1.24.38.7
@@ -49,11 +49,17 @@
 #ifndef _RTL_ALLOC_H_
 #include <rtl/alloc.h>
 #endif
+#include <osl/mutex.h>
+#include <osl/doublecheckedlocking.h>
 
 #ifndef _RTL_TENCINFO_H
 #include <rtl/tencinfo.h>
 #endif
 
+#include <string.h>
+#include <sal/alloca.h>
+
+#include "hash.h"
 #include "strimp.h"
 
 #ifndef _RTL_USTRING_H_
@@ -71,9 +77,9 @@
 // MT: Should be const, but doesn't work because of #i64835#
 static rtl_uString aImplEmpty_rtl_uString =
 {
-    1,      /* sal_Int32    refCount;   */
-    0,      /* sal_Int32    length;     */
-    { 0 }   /* sal_Unicode  buffer[1];  */
+    SAL_STRING_STATIC_FLAG|1, /* sal_Int32    refCount;   */
+    0,                        /* sal_Int32    length;     */
+    { 0 }                     /* sal_Unicode  buffer[1];  */
 };
 
 /* ======================================================================= */
@@ -85,6 +91,8 @@ static rtl_uString aImplEmpty_rtl_uStrin
 #define IMPL_RTL_STRINGNAME( n )    rtl_uString_ ## n
 #define IMPL_RTL_STRINGDATA         rtl_uString
 #define IMPL_RTL_EMPTYSTRING        aImplEmpty_rtl_uString
+#define IMPL_RTL_INTERN
+static void internRelease (rtl_uString *pThis);
 
 /* ======================================================================= */
 
@@ -475,19 +483,25 @@ static int rtl_ImplGetFastUTF8UnicodeLen
 
 /* ----------------------------------------------------------------------- */
 
-void SAL_CALL rtl_string2UString( rtl_uString** ppThis,
-                                  const sal_Char* pStr,
-                                  sal_Int32 nLen,
-                                  rtl_TextEncoding eTextEncoding,
-                                  sal_uInt32 nCvtFlags )
+static void rtl_string2UString_status( rtl_uString** ppThis,
+                                       const sal_Char* pStr,
+                                       sal_Int32 nLen,
+                                       rtl_TextEncoding eTextEncoding,
+                                       sal_uInt32 nCvtFlags,
+                                       sal_uInt32 *pInfo )
 {
     OSL_ENSURE(rtl_isOctetTextEncoding(eTextEncoding),
-               "rtl_string2UString() - Wrong TextEncoding" );
+               "rtl_string2UString_status() - Wrong TextEncoding" );
 
+    if (pInfo)
+        *pInfo = 0;
     if ( !nLen )
         rtl_uString_new( ppThis );
     else
     {
+        if (pInfo)
+            *pInfo = RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR;
+
         if ( *ppThis )
             IMPL_RTL_STRINGNAME( release )( *ppThis );
 
@@ -497,6 +511,8 @@ void SAL_CALL rtl_string2UString( rtl_uS
             IMPL_RTL_STRCODE* pBuffer;
             *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
             if (*ppThis == NULL) {
+                if (pInfo)
+                    *pInfo = RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR;
                 return;
             }
             pBuffer = (*ppThis)->buffer;
@@ -504,7 +520,7 @@ void SAL_CALL rtl_string2UString( rtl_uS
             {
                 /* Check ASCII range */
                 OSL_ENSURE( ((unsigned char)*pStr) <= 127,
-                            "rtl_string2UString() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
+                            "rtl_string2UString_status() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
 
                 *pBuffer = *pStr;
                 pBuffer++;
@@ -534,7 +550,10 @@ void SAL_CALL rtl_string2UString( rtl_uS
                 {
                     IMPL_RTL_STRCODE* pBuffer;
                     *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
-                    if (*ppThis == NULL) {
+                    if (*ppThis == NULL)
+                    {
+                        if (pInfo)
+                            *pInfo = RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR;
                         return;
                     }
                     pBuffer = (*ppThis)->buffer;
@@ -542,7 +561,7 @@ void SAL_CALL rtl_string2UString( rtl_uS
                     {
                         /* Check ASCII range */
                         OSL_ENSURE( ((unsigned char)*pStr) <= 127,
-                                    "rtl_string2UString() - UTF8 test encoding is wrong" );
+                                    "rtl_string2UString_status() - UTF8 test encoding is wrong" );
 
                         *pBuffer = *pStr;
                         pBuffer++;
@@ -560,7 +579,10 @@ void SAL_CALL rtl_string2UString( rtl_uS
             hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
 
             pTemp = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
-            if (pTemp == NULL) {
+            if (pTemp == NULL)
+            {
+                if (pInfo)
+                    *pInfo = RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR;
                 return;
             }
             nDestChars = rtl_convertTextToUnicode( hConverter, 0,
@@ -578,7 +600,10 @@ void SAL_CALL rtl_string2UString( rtl_uS
                 rtl_freeMemory( pTemp );
                 nNewLen += 8;
                 pTemp = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
-                if (pTemp == NULL) {
+                if (pTemp == NULL)
+                {
+                    if (pInfo)
+                        *pInfo = RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR;
                     return;
                 }
                 nDestChars = rtl_convertTextToUnicode( hConverter, 0,
@@ -588,16 +613,27 @@ void SAL_CALL rtl_string2UString( rtl_uS
                                                        &nInfo, &nSrcBytes );
             }
 
-            /* Set the buffer to the correct size or is there to
+            if (pInfo)
+                *pInfo = nInfo;
+
+            /* Set the buffer to the correct size or if there is too
                much overhead, reallocate to the correct size */
             if ( nNewLen > nDestChars+8 )
             {
                 rtl_uString* pTemp2 = IMPL_RTL_STRINGNAME( ImplAlloc )( nDestChars );
-                if (pTemp2 != NULL) {
+                if (pTemp2 != NULL)
+                {
                     rtl_str_ImplCopy(pTemp2->buffer, pTemp->buffer, nDestChars);
                     rtl_freeMemory(pTemp);
                     pTemp = pTemp2;
                 }
+                else
+                {
+                    rtl_freeMemory(pTemp);
+                    if (pInfo)
+                        *pInfo = RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR;
+                    return;
+                }
             }
             else
             {
@@ -614,4 +650,154 @@ void SAL_CALL rtl_string2UString( rtl_uS
                 rtl_uString_new( ppThis );
         }
     }
+}
+
+void SAL_CALL rtl_string2UString( rtl_uString** ppThis,
+                                  const sal_Char* pStr,
+                                  sal_Int32 nLen,
+                                  rtl_TextEncoding eTextEncoding,
+                                  sal_uInt32 nCvtFlags )
+{
+    rtl_string2UString_status( ppThis, pStr, nLen, eTextEncoding,
+                               nCvtFlags, NULL );
+}
+
+/* ----------------------------------------------------------------------- */
+
+typedef enum {
+    CANNOT_RETURN,
+    CAN_RETURN = 1
+} StrLifecycle;
+
+static oslMutex
+getInternMutex()
+{
+    static oslMutex pPoolGuard = NULL;
+    if( !pPoolGuard )
+    {
+        oslMutex pGlobalGuard;
+        pGlobalGuard = *osl_getGlobalMutex();
+        osl_acquireMutex( pGlobalGuard );
+        if( !pPoolGuard )
+        {
+            oslMutex p = osl_createMutex();
+            OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+            pPoolGuard = p;
+        }
+        osl_releaseMutex( pGlobalGuard );
+    }
+    else
+    {
+        OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+    }
+
+    return pPoolGuard;
+}
+
+static StringHashTable *pInternPool = NULL;
+
+/* returns true if we found a dup in the pool */
+static void rtl_ustring_intern_internal( rtl_uString ** newStr,
+                                         rtl_uString  * str,
+                                         StrLifecycle   can_return )
+{
+    oslMutex pPoolMutex;
+
+    pPoolMutex = getInternMutex();
+
+    osl_acquireMutex( pPoolMutex );
+
+    if (!pInternPool)
+        pInternPool = rtl_str_hash_new (1024);
+    *newStr = rtl_str_hash_intern (pInternPool, str, can_return);
+
+    osl_releaseMutex( pPoolMutex );
+
+    if( can_return && *newStr != str )
+    { /* we dupped, then found a match */
+        rtl_freeMemory( str );
+    }
+}
+
+void SAL_CALL rtl_uString_intern( rtl_uString ** newStr,
+                                  rtl_uString  * str)
+{
+    if (SAL_STRING_IS_INTERN(str))
+    {
+        IMPL_RTL_AQUIRE( str );
+        *newStr = str;
+    }
+    else
+        rtl_ustring_intern_internal( newStr, str, CANNOT_RETURN );
+}
+
+void SAL_CALL rtl_uString_internConvert( rtl_uString   ** newStr,
+                                         const sal_Char * str,
+                                         sal_Int32        len,
+                                         rtl_TextEncoding eTextEncoding,
+                                         sal_uInt32       convertFlags,
+                                         sal_uInt32     * pInfo )
+{
+    rtl_uString *scratch;
+
+    if ( len < 256 )
+    { // try various optimisations
+        if ( len < 0 )
+            len = strlen( str );
+        if ( eTextEncoding == RTL_TEXTENCODING_ASCII_US )
+        {
+            int i;
+            rtl_uString *pScratch;
+            pScratch = alloca( sizeof( rtl_uString )
+                               + len * sizeof (IMPL_RTL_STRCODE ) );
+            for (i = 0; i < len; i++)
+            {
+                /* Check ASCII range */
+                OSL_ENSURE( ((unsigned char)str[i]) <= 127,
+                            "rtl_ustring_internConvert() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
+                pScratch->buffer[i] = str[i];
+            }
+            pScratch->length = len;
+            rtl_ustring_intern_internal( newStr, pScratch, CANNOT_RETURN );
+            return;
+        }
+        /* FIXME: we want a nice UTF-8 / alloca shortcut here */
+    }
+
+    scratch = NULL;
+    rtl_string2UString_status( &scratch, str, len, eTextEncoding, convertFlags,
+                               pInfo );
+    rtl_ustring_intern_internal( newStr, scratch, CAN_RETURN );
+}
+
+static void
+internRelease (rtl_uString *pThis)
+{
+    oslMutex pPoolMutex;
+
+    rtl_uString *pFree = NULL;
+    if ( SAL_STRING_REFCOUNT(
+             osl_decrementInterlockedCount( &(pThis->refCount) ) ) == 0)
+    {
+        pPoolMutex = getInternMutex();
+        osl_acquireMutex( pPoolMutex );
+
+        rtl_str_hash_remove (pInternPool, pThis);
+
+        /* May have been separately acquired */
+        if ( SAL_STRING_REFCOUNT(
+                 osl_incrementInterlockedCount( &(pThis->refCount) ) ) == 1 )
+        {
+            /* we got the last ref */
+            pFree = pThis;
+        }
+        else /* very unusual */
+        {
+            internRelease (pThis);
+        }
+
+        osl_releaseMutex( pPoolMutex );
+    }
+    if (pFree)
+        rtl_freeMemory (pFree);
 }
Index: sal/util/sal.map
===================================================================
RCS file: /cvs/porting/sal/util/sal.map,v
retrieving revision 1.57
retrieving revision 1.57.78.2
diff -u -p -u -p -r1.57 -r1.57.78.2
--- sal/util/sal.map	26 Jul 2006 07:46:09 -0000	1.57
+++ sal/util/sal.map	7 Feb 2007 14:45:37 -0000	1.57.78.2
@@ -551,6 +551,12 @@ UDK_3.5 {
 		rtl_cache_free;
 } UDK_3.4;
 
+UDK_3.6 {
+    global:
+		rtl_uString_intern;
+		rtl_uString_internConvert;
+} UDK_3.5;
+
 PRIVATE_1.0 {
     global:
         osl_detail_ObjectRegistry_storeAddresses;
Index: package/source/zipapi/ZipFile.cxx
===================================================================
RCS file: /cvs/xml/package/source/zipapi/ZipFile.cxx,v
retrieving revision 1.45
retrieving revision 1.45.28.1
diff -u -p -u -p -r1.45 -r1.45.28.1
--- package/source/zipapi/ZipFile.cxx	17 Sep 2006 17:28:16 -0000	1.45
+++ package/source/zipapi/ZipFile.cxx	8 Feb 2007 14:23:59 -0000	1.45.28.1
@@ -798,9 +798,9 @@ sal_Int32 ZipFile::readCEN()
 			if ( aEntry.nExtraLen > ZIP_MAXEXTRA )
 				throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "extra header info exceeds ZIP_MAXEXTRA bytes") ), Reference < XInterface > () );
 
-			aEntry.sName = OUString ( (sal_Char *) aMemGrabber.getCurrentPos(), 
-									  aEntry.nNameLen, 
-									  RTL_TEXTENCODING_ASCII_US);
+			aEntry.sName = rtl::OUString::intern ( (sal_Char *) aMemGrabber.getCurrentPos(), 
+                                                   aEntry.nNameLen, 
+                                                   RTL_TEXTENCODING_ASCII_US);
 
 			aMemGrabber.skipBytes( aEntry.nNameLen + aEntry.nExtraLen + nCommentLen );
 			aEntries[aEntry.sName] = aEntry;	
