Commits

Anonymous committed 5621b0f

Patch from the go-oo applied, and all conflicts resolved. However, this is not yet build-tested.

Comments (0)

Files changed (34)

 #include "formula/grammar.hxx"
 #include "tokenarray.hxx"
 #include "formularesult.hxx"
+#include "phonetic.hxx"
 #include <rtl/ustrbuf.hxx>
 #include <vcl/fontcvt.hxx>
 #include "scdllapi.h"
 class ScCodeArray;
 class ScProgress;
 class ScPostIt;
+class ScPhonetic;
 
 // ============================================================================
 
     inline void		GetString( String& rString ) const { rString = maString; }
 	inline const String& GetString() const { return maString; }
 
+    virtual bool    HasPhonetic() const;
+
 private:
 	String		    maString;
 };
 
 // ============================================================================
 
+/**
+ * A class for representing of Asian phonetic guide.
+ */
+class SC_DLLPUBLIC ScAsianStringCell : public ScStringCell
+{
+private:
+    ScPhonetic      aPhonetic;
+
+public:
+
+#ifdef USE_MEMPOOL
+    DECL_FIXEDMEMPOOL_NEWDEL( ScAsianStringCell )
+#endif
+#ifdef DBG_UTIL
+    ~ScAsianStringCell();
+#endif
+
+    ScAsianStringCell();
+
+    /**
+     * A constructor of ScAsianStringCell
+     * @param rString the text of the cell.
+     * @param rPhonetic a reference of ScPhonetic.
+     */
+    ScAsianStringCell( const String& rString, const ScPhonetic& rPhonetic );
+
+    /**
+     * A constructor of ScAsianStringCell
+     * @param rStream a reference of SvStream.
+     * @param nVer the number of vesion.
+     */
+    ScAsianStringCell( SvStream& rStream, USHORT nVer );
+
+    /**
+     * Sets ScPhonetic:
+     * @param rPhonetic a reference of ScPhonetic.
+     */
+    void            SetPhonetic( const ScPhonetic& rPhonetic );
+
+    /**
+     * Gets ScPhonetic:
+     * @param rPhonetic a reference of ScPhonetic.
+     */
+    void            GetPhonetic( ScPhonetic& rPhonetic ) const;
+
+    virtual bool    HasPhonetic() const;
+};
+
+// ============================================================================
+
 class SC_DLLPUBLIC ScEditCell : public ScBaseCell
 {
 private:
 	void			GetData( const EditTextObject*& rpObject ) const;
 	void			GetString( String& rString ) const;
 
+    virtual bool    HasPhonetic() const;
+
 	const EditTextObject* GetData() const	{ return pData; }
 };
 
 // ============================================================================
 
+
+/**
+ * A class for representing of Asian phonetic guide.
+ * It is derived from ScStringCell.
+ */
+class SC_DLLPUBLIC ScAsianEditCell : public ScEditCell
+{
+private:
+    ScPhonetic      aPhonetic;
+
+public:
+
+#ifdef USE_MEMPOOL
+    DECL_FIXEDMEMPOOL_NEWDEL( ScAsianStringCell )
+#endif
+#ifdef DBG_UTIL
+    ~ScAsianEditCell();
+#endif
+
+    /**
+     * A constructor of ScAsianEditCell
+     * @param rEditCell a reference of ScEditCell.
+     * @param pDoc a pointer of ScDocument.
+     * @param rPhonetic a reference of ScPhonetic.
+     */
+    ScAsianEditCell( const ScEditCell& rEditCell, ScDocument& rDoc, const ScPhonetic& rPhonetic );
+
+    /**
+     * A constructor of ScAsianEditCell
+     * @param pObject a pointer of EditTextObject.
+     * @param pDoc a pointer of ScDocument.
+     * @param pFromPool a pointer of SfxItemPool.
+     * @param rPhonetic a reference of ScPhonetic.
+     */
+    ScAsianEditCell( const EditTextObject* pObject, ScDocument* pDoc,
+                     const SfxItemPool* pFromPool, const ScPhonetic& rPhonetic );
+
+    /**
+     * Sets ScPhonetic:
+     * @param rPhonetic a reference of ScPhonetic.
+     */
+    void            SetPhonetic( const ScPhonetic& rPhonetic );
+
+    /**
+     * Gets ScPhonetic:
+     * @param rPhonetic a reference of ScPhonetic.
+     */
+    void            GetPhonetic( ScPhonetic& rPhonetic ) const;
+
+    virtual bool    HasPhonetic() const;
+};
+
+// ----------------------------------------------------------------------------
+
 enum ScMatrixMode {
     MM_NONE      = 0,                   // No matrix formula
     MM_FORMULA   = 1,                   // Upper left matrix formula cell
 
 // ============================================================================
 
+// ScAsianStringCell
+
+inline ScAsianStringCell::ScAsianStringCell()
+{
+}
+
+inline ScAsianStringCell::ScAsianStringCell( const String& rString, const ScPhonetic& rPhonetic ) :
+    ScStringCell ( rString ),
+    aPhonetic ( rPhonetic )
+{
+}
+
+inline void ScAsianStringCell::GetPhonetic( ScPhonetic& rPhonetic ) const
+{
+    rPhonetic = aPhonetic;
+}
+
+inline bool ScAsianStringCell::HasPhonetic() const
+{
+    return true;
+}
+
+inline void ScAsianStringCell::SetPhonetic( const ScPhonetic& rPhonetic )
+{
+    aPhonetic = rPhonetic;
+}
+
+//      ScAsianEditCell
+
+inline ScAsianEditCell::ScAsianEditCell( const ScEditCell& rEditCell, ScDocument& rDoc, const ScPhonetic& rPhonetic ) :
+    ScEditCell( rEditCell, rDoc ),
+    aPhonetic( rPhonetic )
+{
+}
+
+inline ScAsianEditCell::ScAsianEditCell( const EditTextObject* pObject, ScDocument* pDocP,
+                                         const SfxItemPool* pFromPool, const ScPhonetic& rPhonetic ) :
+    ScEditCell( pObject, pDocP, pFromPool ),
+    aPhonetic( rPhonetic )
+{
+}
+
+inline void ScAsianEditCell::GetPhonetic( ScPhonetic& rPhonetic ) const
+{
+    rPhonetic = aPhonetic;
+}
+
+inline void ScAsianEditCell::SetPhonetic( const ScPhonetic& rPhonetic )
+{
+    aPhonetic = rPhonetic;
+}
+
+inline bool ScAsianEditCell::HasPhonetic() const
+{
+    return true;
+}
+
 #endif
 

sc/inc/cellsuno.hxx

 	virtual sal_Int16 SAL_CALL resetActionLocks() throw(::com::sun::star::uno::RuntimeException);
 
 	static String		GetOutputString_Impl(ScDocument* pDoc, const ScAddress& aPos);
+
+    /**
+     * Gets phonetic text from a cell. 
+     *  
+     * @param pDoc A pointer of ScDocument.
+     * @param aPos A reference of ScAdress.
+     */
+    static String GetOutputPhoneticString_Impl(ScDocument* pDoc, const ScAddress& aPos);
 };
 
 

sc/inc/scfuncs.hrc

 #define HID_FUNC_UNICODE            (HID_SC_FUNC_DUMMY+(ID_FUNCTION_GRP_TEXT*ID_FUNCTION_OFFSET)+31)
 #define HID_FUNC_UNICHAR            (HID_SC_FUNC_DUMMY+(ID_FUNCTION_GRP_TEXT*ID_FUNCTION_OFFSET)+32)
 #define HID_FUNC_NUMBERVALUE        (HID_SC_FUNC_DUMMY+(ID_FUNCTION_GRP_TEXT*ID_FUNCTION_OFFSET)+33)
+#define HID_FUNC_PHONETIC           (HID_SC_FUNC_DUMMY+(ID_FUNCTION_GRP_TEXT*ID_FUNCTION_OFFSET)+34)

sc/source/core/data/cell.cxx

 const USHORT nMemPoolFormulaCell = (0x8000 - 64) / sizeof(ScFormulaCell);
 const USHORT nMemPoolStringCell = (0x4000 - 64) / sizeof(ScStringCell);
 const USHORT nMemPoolNoteCell = (0x1000 - 64) / sizeof(ScNoteCell);
+const USHORT nMemPoolAsianStringCell = (0x4000 - 64) / sizeof(ScAsianStringCell);
+const USHORT nMemPoolAsianEditCell = (0x4000 - 64) / sizeof(ScAsianEditCell);
 IMPL_FIXEDMEMPOOL_NEWDEL( ScValueCell,   nMemPoolValueCell, nMemPoolValueCell )
 IMPL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell, nMemPoolFormulaCell, nMemPoolFormulaCell )
 IMPL_FIXEDMEMPOOL_NEWDEL( ScStringCell,  nMemPoolStringCell, nMemPoolStringCell )
 IMPL_FIXEDMEMPOOL_NEWDEL( ScNoteCell,	 nMemPoolNoteCell, nMemPoolNoteCell )
+IMPL_FIXEDMEMPOOL_NEWDEL( ScAsianStringCell, nMemPoolAsianStringCell, nMemPoolAsianStringCell )
+IMPL_FIXEDMEMPOOL_NEWDEL( ScAsianEditCell, nMemPoolAsianEditCell, nMemPoolAsianEditCell )
 #endif
 
 // ============================================================================
 			return ( ((const ScValueCell*)pCell1)->GetValue() ==
 					 ((const ScValueCell*)pCell2)->GetValue() );
 		case CELLTYPE_STRING:		// String oder Edit
-			{
-				String aText1;
-				if ( pCell1->GetCellType() == CELLTYPE_STRING )
-					((const ScStringCell*)pCell1)->GetString(aText1);
-				else
-					((const ScEditCell*)pCell1)->GetString(aText1);
-				String aText2;
-				if ( pCell2->GetCellType() == CELLTYPE_STRING )
-					((const ScStringCell*)pCell2)->GetString(aText2);
-				else
-					((const ScEditCell*)pCell2)->GetString(aText2);
-				return ( aText1 == aText2 );
-			}
+        {
+            String aText1, aText2;
+            const ScStringCell* pStrCell1 = static_cast<const ScStringCell*>(pCell1);
+            const ScStringCell* pStrCell2 = static_cast<const ScStringCell*>(pCell2);
+            pStrCell1->GetString( aText1 );
+            pStrCell2->GetString( aText2 );
+            if (aText1 != aText2)
+                return false;
+
+            ScPhonetic aPhonetic1, aPhonetic2;
+            if (pStrCell1->HasPhonetic())
+            {
+                const ScAsianStringCell* pPhoCell1 = 
+                    static_cast<const ScAsianStringCell*>(pStrCell1);
+                pPhoCell1->GetPhonetic(aPhonetic1);
+            }
+            if (pStrCell2->HasPhonetic())
+            {
+                const ScAsianStringCell* pPhoCell2 = 
+                    static_cast<const ScAsianStringCell*>(pStrCell2);
+                pPhoCell2->GetPhonetic(aPhonetic2);
+            }
+
+            return aPhonetic1 == aPhonetic2;
+        }
 		case CELLTYPE_FORMULA:
 			{
 				//!	eingefuegte Zeilen / Spalten beruecksichtigen !!!!!
 }
 #endif
 
+bool ScStringCell::HasPhonetic() const
+{
+    return false;
+}
+
 // ============================================================================
 
 //

sc/source/core/data/cell2.cxx

         rString.Erase();
 }
 
+bool ScEditCell::HasPhonetic() const
+{
+    return false;
+}
+
+
 void ScEditCell::SetTextObject( const EditTextObject* pObject,
             const SfxItemPool* pFromPool )
 {

sc/source/core/data/makefile.mk

 	$(SLO)$/patattr.obj \
 	$(SLO)$/pivot.obj \
 	$(SLO)$/pivot2.obj \
+	$(SLO)$/phonetic.obj \
 	$(SLO)$/poolhelp.obj \
 	$(SLO)$/scimpexpmsg.obj \
 	$(SLO)$/sortparam.obj \

sc/source/core/inc/interpre.hxx

 ScBaseCell* GetCell( const ScAddress& rPos )
     { return pDok->GetCell( rPos ); }
 void GetCellString( String& rStr, const ScBaseCell* pCell );
+void GetCellPhoneticString( String& rStr, const ScBaseCell* pCell );
 inline USHORT GetCellErrCode( const ScBaseCell* pCell )
     { return pCell ? pCell->GetErrorCode() : 0; }
 inline CellType GetCellType( const ScBaseCell* pCell )
 void ScGetPivotData();
 void ScHyperLink();
 void ScBahtText();
+void ScPhoneticString();
 void ScCalcTeam();
 void ScAnswer();
 void ScTTT();

sc/source/core/tool/interpr2.cxx

 
 // ============================================================================
 
+void ScInterpreter::ScPhoneticString()
+{
+    BYTE nParamCount = GetByte();
+    if ( MustHaveParamCountMin( nParamCount, 1 ) )
+    {
+        String aPhoneticText;
+        while( nParamCount-- )
+        {
+            if ( nGlobalError )
+            {
+                PushError(nGlobalError);
+                return;
+            }
+
+            switch ( GetStackType() )
+            {
+                case svSingleRef :
+                {
+                    ScAddress aAdr;
+                    PopSingleRef( aAdr );
+                    if (nGlobalError)
+                    {
+                        PushError(nGlobalError);
+                        return;
+                    }
+
+                    ScBaseCell* pCell = GetCell( aAdr );
+                    if ( HasCellStringData( pCell ) )
+                    {
+                        String aStr;
+                        GetCellPhoneticString( aStr, pCell );
+                        aPhoneticText += aStr;
+                    }
+                }
+                break;
+                case svDoubleRef:
+                {
+                    ScRange aRange;
+                    PopDoubleRef( aRange );
+                    if (nGlobalError)
+                    {
+                        PushError(nGlobalError);
+                        return;
+                    }
+
+                    ScCellIterator aIter( pDok, aRange );
+                    ScBaseCell *pCell = aIter.GetFirst();
+                    while ( pCell )
+                    {
+                        if ( HasCellStringData( pCell ) )
+                        {
+                            String aStr;
+                            GetCellPhoneticString( aStr, pCell );
+                            aPhoneticText += aStr;
+                        }
+                        pCell = aIter.GetNext();
+                    }
+                }
+                break;
+                default:
+                    PushError(errIllegalParameter);
+                    return;
+            }
+        }
+        PushString( aPhoneticText );
+    }
+}
+
+// ============================================================================
+
 void ScInterpreter::ScGetPivotData()
 {
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetPivotData" );

sc/source/core/tool/interpr4.cxx

     SetError(nErr);
 }
 
+static sal_Bool lcl_IsHalfWidthKatakana ( const String& rString )
+{
+    sal_Int32 nLen = rString.Len();
+
+    for ( sal_Int32 i = 0; i < nLen; ++i )
+    {
+        if ( rString.GetChar(i) < 0xFF00 || rString.GetChar(i) > 0xFFEF )
+            return sal_False;
+    }
+
+    return sal_True;
+}
+
+static sal_Bool lcl_IsFullWidthKatakana ( const String& rString )
+{
+    sal_Int32 nLen = rString.Len();
+
+    for ( sal_Int32 i = 0; i < nLen; ++i )
+    {
+        if ( rString.GetChar(i) < 0x30A0 || rString.GetChar(i) > 0x30FF )
+            return sal_False;
+    }
+
+    return sal_True;
+}
+
+static sal_Bool lcl_IsFullWidthHiragana ( const String& rString )
+{
+    sal_Int32 nLen = rString.Len();
+
+    for ( sal_Int32 i = 0; i < nLen; ++i )
+    {
+        if ( rString.GetChar(i) < 0x3040 || rString.GetChar(i) > 0x309F )
+            return sal_False;
+    }
+
+    return sal_True;
+}
+
+static sal_uInt16 lcl_GetKanaType ( const String rText )
+{
+    sal_uInt16 aKanaType = 0;
+
+    if ( lcl_IsHalfWidthKatakana ( rText ) )
+        aKanaType = 0x00;
+    else if ( lcl_IsFullWidthKatakana ( rText ) )
+        aKanaType = 0x01;
+    else if ( lcl_IsFullWidthHiragana ( rText ) )
+        aKanaType = 0x02;
+
+    return aKanaType;
+}
+
+static void lcl_ConvertToKatakana( ScDocument* pDoc, String& rStr )
+{
+    sal_uInt16 nKanaType = lcl_GetKanaType(rStr);
+    sal_Int32 nType = com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
+    switch (nKanaType)
+    {
+        case 0x00:
+            // half-width katakana or full-width alphabet.
+            nType = com::sun::star::i18n::TransliterationModules_HALFWIDTH_FULLWIDTH;
+        break;
+        case 0x02:
+            // full-width hiragana.
+            nType = com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
+        break;
+        case 0x01:
+        default:
+            // full-width katakana.  no need to convert this.
+            return;
+    }
+    utl::TransliterationWrapper aTranslitarationWrapper( pDoc->GetServiceManager(), nType );
+    com::sun::star::uno::Sequence<sal_Int32> aOffsets;
+    rStr = aTranslitarationWrapper.transliterate( rStr, LANGUAGE_JAPANESE, 0, rStr.Len(), &aOffsets );
+}
+
+static void lcl_GetPhoneticString ( ScDocument *pDoc, String& rStr, const ScBaseCell* pCell )
+{
+    ScPhonetic aPhonetic;
+    String aBaseString;
+    switch (pCell->GetCellType())
+    {
+        case CELLTYPE_STRING:
+            static_cast<const ScStringCell*>(pCell)->GetString(aBaseString);
+            static_cast<const ScAsianStringCell*>(pCell)->GetPhonetic(aPhonetic);
+        break;
+        case CELLTYPE_EDIT:
+            static_cast<const ScEditCell*>(pCell)->GetString(aBaseString);
+            static_cast<const ScAsianEditCell*>(pCell)->GetPhonetic(aPhonetic);
+        break;
+        default:
+            // Not a supported cell type.
+            return;
+    }
+    
+    if (aPhonetic.IsEmpty())
+        // No phonetic string exists.  Bail out.
+        return;
+
+    const String& rPhoneticString = aPhonetic.GetString();
+    PhoneticPortionVec portions = aPhonetic.GetPortions();
+    sal_uInt16 nPortionCount = portions.size();
+
+    String tmpString;
+    if ( nPortionCount > 0 )
+    {
+        sal_uInt16 pos = 0;
+        for ( sal_uInt16 idx = 0; idx < nPortionCount; ++idx )
+        {
+            const PhoneticPortion& portion = portions[idx];
+
+            // Get the end position in the phonetic text.
+            sal_uInt16 nPhEndPos = idx < nPortionCount-1 ? portions[idx+1].mncpa : rPhoneticString.Len();
+
+            tmpString += aBaseString.Copy(pos, portion.mncpm - pos);
+            pos = portion.mncpm + portion.mnccm;
+            tmpString += rPhoneticString.Copy(portion.mncpa, nPhEndPos - portion.mncpa);
+        }
+        if ( pos < aBaseString.Len() )
+            tmpString += aBaseString.Copy(pos, aBaseString.Len() - pos);
+    }
+    else
+    {
+        tmpString = rPhoneticString;
+    }
+
+    sal_Int32 nType;
+    switch ( lcl_GetKanaType ( rPhoneticString ))
+    {
+        case 0x00:
+            nType = com::sun::star::i18n::TransliterationModules_FULLWIDTH_HALFWIDTH;
+            break;
+        case 0x01:
+            nType = com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
+            break;
+        case 0x02:
+            nType = com::sun::star::i18n::TransliterationModules_KATAKANA_HIRAGANA;
+            break;
+        default:
+            nType = com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
+            break;
+    }
+
+    utl::TransliterationWrapper aTranslitarationWrapper( pDoc->GetServiceManager(), nType );
+    com::sun::star::uno::Sequence<sal_Int32> aOffsets;
+    rStr = aTranslitarationWrapper.transliterate( tmpString, LANGUAGE_JAPANESE, 0, tmpString.Len(), &aOffsets );
+}
+
+void ScInterpreter::GetCellPhoneticString( String& rStr, const ScBaseCell* pCell )
+{
+    USHORT nErr = 0;
+    if ( pCell )
+    {
+        switch ( pCell->GetCellType() )
+        {
+            case CELLTYPE_STRING:
+                if ( static_cast<const ScStringCell*>(pCell)->HasPhonetic() )
+                    lcl_GetPhoneticString(pDok, rStr, pCell);
+                else
+                {    
+                    static_cast<const ScStringCell*>(pCell)->GetString(rStr);
+                    lcl_ConvertToKatakana(pDok, rStr);
+                }
+            break;
+            case CELLTYPE_EDIT:
+                if ( static_cast<const ScEditCell*>(pCell)->HasPhonetic() )
+                    lcl_GetPhoneticString(pDok, rStr, pCell);
+                else
+                {    
+                    static_cast<const ScEditCell*>(pCell)->GetString(rStr);
+                    lcl_ConvertToKatakana(pDok, rStr);
+                }
+            break;
+            default:
+                rStr = ScGlobal::GetEmptyString();
+            break;
+        }
+    }
+    else
+        rStr = ScGlobal::GetEmptyString();
+    SetError(nErr);
+}
 
 BOOL ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
                             SCCOL nCol2, SCROW nRow2, SCTAB nTab2, BYTE* pCellArr)
                 case ocInfo             : ScInfo();                     break;
                 case ocHyperLink        : ScHyperLink();                break;
                 case ocBahtText         : ScBahtText();                 break;
+                case ocPhonetic         : ScPhoneticString();           break;
                 case ocGetPivotData     : ScGetPivotData();             break;
                 case ocJis              : ScJis();                      break;
                 case ocAsc              : ScAsc();                      break;

sc/source/filter/excel/xehelper.cxx

 {
     String aCellText;
     rStringCell.GetString( aCellText );
-    return lclCreateFormattedString( rRoot, aCellText, pCellAttr, nFlags, nMaxLen );
+    XclExpStringRef xString = lclCreateFormattedString( rRoot, aCellText, pCellAttr, nFlags, nMaxLen );
+    if (rStringCell.HasPhonetic())
+    {
+        ScPhonetic aPhonetic;
+        static_cast<const ScAsianStringCell&>(rStringCell).GetPhonetic(aPhonetic);
+        if ( !aPhonetic.IsEmpty() )
+            xString->SetPhoneticSettings(aPhonetic);
+    }
+
+    return xString;
 }
 
 XclExpStringRef XclExpStringHelper::CreateCellString(
         rEditCell.GetString( aCellText );
         xString = lclCreateFormattedString( rRoot, aCellText, pCellAttr, nFlags, nMaxLen );
     }
+
+    if (rEditCell.HasPhonetic())
+    {
+        ScPhonetic aPhonetic;
+        static_cast<const ScAsianEditCell&>(rEditCell).GetPhonetic(aPhonetic);
+        if ( !aPhonetic.IsEmpty() )
+            xString->SetPhoneticSettings(aPhonetic);
+    }
+
     return xString;
 }
 

sc/source/filter/excel/xestring.cxx

             ( mbIsBiff8 && (maUniBuffer  == rCmp.maUniBuffer)) ||
             (!mbIsBiff8 && (maCharBuffer == rCmp.maCharBuffer))
         ) &&
-        (maFormats      == rCmp.maFormats);
+        (maFormats   == rCmp.maFormats)      &&
+        (maPhonetic  == rCmp.maPhonetic);
 }
 
 bool XclExpString::IsLessThan( const XclExpString& rCmp ) const
     return (nResult != 0) ? (nResult < 0) : (maFormats < rCmp.maFormats);
 }
 
+bool XclExpString::HasPhonetic() const
+{
+    return !maPhonetic.IsEmpty();
+}
+
+// formatting runs ------------------------------------------------------------
+
+void XclExpString::SetPhoneticSettings( const ScPhonetic& rPhonetic )
+{
+    maPhonetic = rPhonetic;
+}
+
 // get data -------------------------------------------------------------------
 
 sal_uInt16 XclExpString::GetFormatsCount() const
     return static_cast< sal_uInt16 >( maFormats.size() );
 }
 
+sal_uInt32 XclExpString::GetPhoneticSettingsCount() const
+{
+    return maPhonetic.GetSize();
+}
+
 sal_uInt8 XclExpString::GetFlagField() const
 {
-    return (mbIsUnicode ? EXC_STRF_16BIT : 0) | (IsWriteFormats() ? EXC_STRF_RICH : 0);
+    return (mbIsUnicode ? EXC_STRF_16BIT : 0) |
+           (IsWritePhoneticSettings() ? EXC_STRF_FAREAST : 0 ) |
+           (IsWriteFormats() ? EXC_STRF_RICH : 0);
 }
 
 sal_uInt16 XclExpString::GetHeaderSize() const
 {
     return
-        (mb8BitLen ? 1 : 2) +           // length field
-        (IsWriteFlags() ? 1 : 0) +      // flag field
-        (IsWriteFormats() ? 2 : 0);     // richtext formattting count
+        (mb8BitLen ? 1 : 2) +                   // length field
+        (IsWriteFlags() ? 1 : 0) +              // flag field
+        (IsWriteFormats() ? 2 : 0) +            // richtext formattting count
+        (IsWritePhoneticSettings() ? 4 : 0);    // phonetic settings  count
 }
 
 sal_Size XclExpString::GetBufferSize() const
 sal_Size XclExpString::GetSize() const
 {
     return
-        GetHeaderSize() +                                   // header
-        GetBufferSize() +                                   // character buffer
-        (IsWriteFormats() ? (4 * GetFormatsCount()) : 0);   // richtext formattting
+        GetHeaderSize() +                                              // header
+        GetBufferSize() +                                              // character buffer
+        (IsWriteFormats() ? (4 * GetFormatsCount()) : 0) +             // richtext formattting
+        (IsWritePhoneticSettings() ? GetPhoneticSettingsCount() : 0);  // phonetic settings
 }
 
 sal_uInt16 XclExpString::GetChar( sal_uInt16 nCharIdx ) const
     // format run count
     if( IsWriteFormats() )
         rStrm << GetFormatsCount();
+    // format phonetic settings
+    if( IsWritePhoneticSettings() )
+        rStrm << GetPhoneticSettingsCount();
+
     rStrm.SetSliceSize( 0 );
 }
 
     }
 }
 
+void XclExpString::WritePhoneticSettings( XclExpStream& rStrm ) const
+{
+    if( HasPhonetic() )
+    {
+        sal_uInt16 nLen = maPhonetic.GetString().Len();
+        sal_uInt16 nPortions = maPhonetic.GetPortions().size();
+        rStrm << static_cast< sal_uInt16 > ( 1 );
+        rStrm << static_cast< sal_uInt16 > ( 10 + 2 * nLen + 6 * nPortions );
+        rStrm << static_cast< sal_uInt16 > ( maPhonetic.GetFontIndex() );
+        rStrm << static_cast< sal_uInt16 > ( maPhonetic.GetAdditionalSettings() );
+        rStrm << static_cast< sal_uInt16 > ( nPortions );
+        rStrm << static_cast< sal_uInt16 > ( nLen );
+        rStrm << static_cast< sal_uInt16 > ( maPhonetic.GetRepeatedTotalLength() );
+
+        if ( nLen > 0 )
+        {
+            ScfUInt16Vec buffer ( nLen );
+            ScfUInt16Vec::iterator aBeg = buffer.begin();
+            ScfUInt16Vec::iterator aEnd = aBeg + nLen;
+            const sal_Unicode* pcSrcChar = maPhonetic.GetString().GetBuffer();
+            for( ScfUInt16Vec::iterator aIt = aBeg; aIt != aEnd; ++aIt, ++pcSrcChar )
+            {
+                *aIt = static_cast< sal_uInt16 >( *pcSrcChar );
+            }
+            rStrm.WriteUnicodeBuffer( buffer, EXC_STRF_16BIT);
+        }
+        else
+        {
+            rStrm << static_cast< sal_uInt16 > ( 0 );
+        }
+
+        PhoneticPortionVec portions = maPhonetic.GetPortions();
+        for ( sal_uInt16 idx = 0; idx < nPortions; ++idx)
+        {
+            PhoneticPortion portion = portions[idx];
+            rStrm << portion.mncpa << portion.mncpm << portion.mnccm;
+        }
+    }
+}
+
 void XclExpString::Write( XclExpStream& rStrm ) const
 {
     WriteHeader( rStrm );
     WriteBuffer( rStrm );
     if( IsWriteFormats() )      // only in BIFF8 included in string
         WriteFormats( rStrm );
+    if( IsWritePhoneticSettings() )
+        WritePhoneticSettings( rStrm );
 }
 
 void XclExpString::WriteHeaderToMem( sal_uInt8* pnMem ) const
     return mbIsBiff8 && !mbSkipFormats && IsRich();
 }
 
+bool XclExpString::IsWritePhoneticSettings() const
+{
+    return mbIsBiff8 && !mbSkipFormats && HasPhonetic();
+}
+
 void XclExpString::SetStrLen( sal_Int32 nNewLen )
 {
     sal_uInt16 nAllowedLen = (mb8BitLen && (mnMaxLen > 255)) ? 255 : mnMaxLen;

sc/source/filter/excel/xihelper.cxx

         ScDocument& rDoc = rRoot.GetDoc();
 
         if( pTextObj.get() )
-            // ScEditCell creates own copy of text object
-            pCell = new ScEditCell( pTextObj.get(), &rDoc, rRoot.GetEditEngine().GetEditTextObjectPool() );
+        {
+            if ( rString.HasPhonetic() )
+                pCell = new ScAsianEditCell( pTextObj.get(), &rDoc, rRoot.GetEditEngine().GetEditTextObjectPool(), rString.GetPhonetic() );
+            else
+                // ScEditCell creates own copy of text object
+                pCell = new ScEditCell( pTextObj.get(), &rDoc, rRoot.GetEditEngine().GetEditTextObjectPool() );
+        }
         else
-            pCell = ScBaseCell::CreateTextCell( rString.GetText(), &rDoc );
+        {
+            if ( rString.HasPhonetic() )
+                pCell = new ScAsianStringCell( rString.GetText(), rString.GetPhonetic() );
+            else
+                pCell = ScBaseCell::CreateTextCell( rString.GetText(), &rDoc );
+        }
     }
 
     return pCell;

sc/source/filter/excel/xistring.cxx

                 ReadFormats( rStrm, nRunCount );
 
             // --- extended (FarEast) information ---
-            rStrm.Ignore( nExtInf );
+            if( nExtInf > 0 )
+                ReadPhoneticSettings( rStrm, nExtInf );
         }
         break;
 
     }
 }
 
+void XclImpString::ReadPhoneticSettings( XclImpStream& rStrm, sal_uInt32 /*nExtInf*/ )
+{
+    PhoneticPortionVec xPortions;
+
+    rStrm.Ignore( 2 ); // Unknown indentifier 0001
+
+    sal_uInt16 nSize, nFontIdx, nAdditional, nPortions, nLength, nRepeatedLength;
+    rStrm >> nSize >> nFontIdx >> nAdditional >> nPortions >> nLength >> nRepeatedLength;
+
+    if ( nLength == 0 )
+        rStrm.Ignore( 2 );
+    else
+        maPhoneticString = rStrm.ReadRawUniString( nLength, true );
+    
+    for ( sal_uInt16 nIdx = 0; nIdx < nPortions; ++nIdx )
+    {
+        sal_uInt16 ncpa, ncpm, nccm;
+        rStrm >> ncpa >> ncpm >> nccm;
+        xPortions.push_back ( PhoneticPortion( ncpa, ncpm, nccm ) );
+    }
+
+    maPhonetic = ScPhonetic ( nFontIdx, nAdditional, nRepeatedLength,
+                              maPhoneticString, xPortions );
+}
+
 // String iterator ============================================================
 
 XclImpStringIterator::XclImpStringIterator( const XclImpString& rString ) :

sc/source/filter/excel/xlformula.cxx

 
 const sal_Char* const EXC_FUNCNAME_BAHTTEXT = EXC_FUNCNAME_PREFIX "BAHTTEXT";
 
-/** Functions new in BIFF8. Unsupported functions: PHONETIC. */
+/** Functions new in BIFF8. */
 static const XclFunctionInfo saFuncTable_8[] =
 {
     { ocGetPivotData,       358,    2,  30, V, { RR, RR, VR }, 0, 0 },
     { ocHyperLink,          359,    1,  2,  V, { VV, VO }, 0, 0 },
-    { ocNoName,             360,    1,  1,  V, { RO }, EXC_FUNCFLAG_IMPORTONLY, 0 },    // PHONETIC
+    { ocPhonetic,           360,    1,  1,  V, { R }, 0, 0 },
     { ocAverageA,           361,    1,  30, V, { RX }, 0, 0 },
     { ocMaxA,               362,    1,  30, V, { RX }, 0, 0 },
     { ocMinA,               363,    1,  30, V, { RX }, 0, 0 },

sc/source/filter/inc/xestring.hxx

 #define SC_XESTRING_HXX
 
 #include "xlstring.hxx"
+#include "phonetic.hxx"
 
 // ============================================================================
 
 class ScEditCell;
 class ScPatternAttr;
+class ScPhonetic;
 class EditTextObject;
 class XclExpStream;
 class XclExpXmlStream;
     /** Removes and returns the font index for the first char from the formatting runs, otherwise EXC_FONT_NOTFOUND. */
     sal_uInt16          RemoveLeadingFont();
 
+    // phonetic settings --------------------------------------------------------
+
+    /** Sets new phonetic settings for the current text.
+        @param rPhonetic a reference of ScPhonetic.*/
+    void                SetPhoneticSettings( const ScPhonetic& rPhonetic );
+
     // get data ---------------------------------------------------------------
 
     /** Returns the character count of the string. */
     /** Returns the vector with all formatting runs. */
     inline const XclFormatRunVec& GetFormats() const { return maFormats; }
 
+    /** Returns the current count of phonetic settings */
+    sal_uInt32          GetPhoneticSettingsCount() const;
+    /** Returns true, if the string contains phonetic information. */
+    inline bool         HasPhonetic() const;
+
     /** Returns the current string flags field to export. */
     sal_uInt8           GetFlagField() const;
     /** Returns the byte count the header will take on export. */
     void                WriteBuffer( XclExpStream& rStrm ) const;
     /** Writes the raw formatting run buffer. */
     void                WriteFormats( XclExpStream& rStrm, bool bWriteSize = false ) const;
+    /** Writes the raw phonetic settings. */
+    void                WritePhoneticSettings( XclExpStream& rStrm ) const;
     /** Writes the complete Unicode string. */
     void                Write( XclExpStream& rStrm ) const;
 
     bool                IsWriteFlags() const;
     /** Returns true, if the formatting run vector should be written. */
     bool                IsWriteFormats() const;
+    /** Returns true, if phonetic settings of the text should be written. */
+    bool                IsWritePhoneticSettings() const;
 
     /** Sets the string length but regards the limit given in mnMaxLen. */
     void                SetStrLen( sal_Int32 nNewLen );
     ScfUInt16Vec        maUniBuffer;    /// The Unicode character buffer.
     ScfUInt8Vec         maCharBuffer;   /// The byte character buffer.
     XclFormatRunVec     maFormats;      /// All formatting runs.
+    ScPhonetic          maPhonetic;
     sal_uInt16          mnLen;          /// Character count to export.
     sal_uInt16          mnMaxLen;       /// Maximum allowed number of characters.
     bool                mbIsBiff8;      /// true = BIFF8 Unicode string, false = BIFF2-7 bytestring.

sc/source/filter/inc/xistring.hxx

 #define SC_XISTRING_HXX
 
 #include "xlstring.hxx"
+#include "phonetic.hxx"
 
 // Byte/Unicode strings =======================================================
 
     /** Reads and appends formatting runs from an OBJ or TXO record. */
     static void         ReadObjFormats( XclImpStream& rStrm, XclFormatRunVec& rFormats, sal_uInt16 nFormatSize );
 
+    /** Returns true, if the string has phonetic information. */
+    inline bool         HasPhonetic() const { return !maPhonetic.IsEmpty(); }
+    /** Returns the text for phonetic information. */
+    inline const ScPhonetic& GetPhonetic() const { return maPhonetic; }
+
+    /** Reads phonetic settings from stream. */
+    void                ReadPhoneticSettings( XclImpStream& rStrm, sal_uInt32 nExtInf );
+
 private:
     String              maString;       /// The text data of the string.
     XclFormatRunVec     maFormats;      /// All formatting runs.
+    String              maPhoneticString;
+    ScPhonetic          maPhonetic;
 };
 
 // String iterator ============================================================

sc/source/filter/inc/xlstring.hxx

 /** A vector with all formatting runs for a rich-string. */
 typedef ::std::vector< XclFormatRun > XclFormatRunVec;
 
-// ============================================================================
+// Phonetic settings for Asian text ===========================================
+
+struct XclPhoneticPortion
+{
+    sal_uInt16          mncpa;
+    sal_uInt16          mncpm;
+    sal_uInt16          mnccm;
+    explicit inline     XclPhoneticPortion() : mncpa( 0 ), mncpm( 0 ), mnccm( 0 ) {}
+    explicit inline     XclPhoneticPortion( sal_uInt16 ncpa, sal_uInt16 ncpm, sal_uInt16 nccm ) :
+                            mncpa( ncpa ), mncpm( ncpm ), mnccm ( nccm ) {}
+};
+
+inline bool operator==( const XclPhoneticPortion& rLeft, const XclPhoneticPortion& rRight )
+{
+    return
+        ( rLeft.mncpa == rRight.mncpa ) &&
+        ( rLeft.mncpm == rRight.mncpm ) &&
+        ( rLeft.mnccm == rRight.mnccm );
+}
+
+typedef ::std::vector< XclPhoneticPortion > XclPhoneticPortionVec;
+
+class XclPhoneticSettings
+{
+public:
+    explicit inline     XclPhoneticSettings() : mnFontIdx( 0 ), mnAdditionalSettings( 0 ), mnRepeatedTotalLength ( 0 ) {}
+    explicit inline     XclPhoneticSettings( sal_uInt16 nFontIdx, sal_uInt16 nAdditionalSettings,
+                                             sal_uInt16 nRepeatedTotalLength, const String& rPhoneticString,
+                                             const XclPhoneticPortionVec& rPhoneticPortions) : 
+                                             mnFontIdx( nFontIdx ), mnAdditionalSettings( nAdditionalSettings ),
+                                             mnRepeatedTotalLength ( nRepeatedTotalLength ),
+                                             maPhoneticString ( rPhoneticString ), maPhoneticPortions ( rPhoneticPortions ) {}
+
+    /** Returns the text for phonetic information. */
+    inline const String& GetString() const { return maPhoneticString; }
+    /** Returns the portion for phonetic information. */
+    inline const XclPhoneticPortionVec& GetPortions() const { return maPhoneticPortions; }
+    /** Returns font index of phonetic information. */
+    inline sal_uInt16 GetFontIndex() const { return mnFontIdx; }
+    /** Returns additional settings of phonetic information. */
+    inline sal_uInt16 GetAdditionalSettings() const { return mnAdditionalSettings; }
+    /** Returns repeated length of phonetic information. */
+    inline sal_uInt16 GetRepeatedTotalLength() const { return mnRepeatedTotalLength; }
+    /** Returns the size of phonetic information. */
+    inline sal_uInt32 GetSize() const { return 14 + ( maPhoneticString.Len() ? maPhoneticString.Len() * 2 : 2 ) + maPhoneticPortions.size() * 6; }
+
+private:
+    sal_uInt16            mnFontIdx;          /// Index to FONT record
+    sal_uInt16            mnAdditionalSettings; /// Additional settings for the Asian phonetic text
+    sal_uInt16            mnRepeatedTotalLength;
+    String                maPhoneticString;
+    XclPhoneticPortionVec maPhoneticPortions;
+};
+inline bool operator==( const XclPhoneticSettings& rLeft, const XclPhoneticSettings& rRight )
+{
+    return 
+        ( rLeft.GetString() == rRight.GetString() )                         &&
+        ( rLeft.GetPortions() == rRight.GetPortions() )                     && 
+        ( rLeft.GetFontIndex() == rRight.GetFontIndex() )                   && 
+        ( rLeft.GetAdditionalSettings() == rRight.GetAdditionalSettings() ) && 
+        ( rLeft.GetRepeatedTotalLength() == rRight.GetRepeatedTotalLength() );
+}
 
 #endif
 

sc/source/filter/xml/XMLExportIterator.cxx

 	bHasXText( sal_False ),
 	bIsMatrixBase( sal_False ),
 	bIsMatrixCovered( sal_False ),
-	bHasAnnotation( sal_False )
+    bHasAnnotation( sal_False ),
+    bHasPhonetic( sal_False )
 {
 }
 

sc/source/filter/xml/XMLExportIterator.hxx

 
 	rtl::OUString				sStringValue;
 	rtl::OUString				sAnnotationText;
+    rtl::OUString               sPhoneticText;
 
 	ScMyAreaLink				aAreaLink;
 	ScMyShapeList				aShapeList;
 	sal_Bool					bIsMatrixBase;
 	sal_Bool					bIsMatrixCovered;
 	sal_Bool					bHasAnnotation;
+    sal_Bool                    bHasPhonetic;
 
 								ScMyCell();
 								~ScMyCell();

sc/source/filter/xml/XMLTextPContext.cxx

 #include "XMLTextPContext.hxx"
 #include "xmlimprt.hxx"
 #include "xmlcelli.hxx"
+#include "xmlrubyi.hxx"
 #include <xmloff/xmlnmspe.hxx>
 #include <xmloff/xmltoken.hxx>
 #include <xmloff/nmspmap.hxx>
 									  	::com::sun::star::xml::sax::XAttributeList>& xTempAttrList )
 {
 	SvXMLImportContext *pContext(NULL);
-	if (!pTextPContext &&
-		(nTempPrefix == XML_NAMESPACE_TEXT) &&
-		IsXMLToken(rLName, XML_S))
-		pContext = new ScXMLTextTContext( GetScImport(), nTempPrefix, rLName, xTempAttrList, this);
-	else
+
+    if ( !pTextPContext )
 	{
-		if (!pTextPContext)
+        const SvXMLTokenMap& rTokenMap = GetScImport().GetTableRowCellElemTextTokenMap();
+        switch( rTokenMap.Get( nTempPrefix, rLName ) )
 		{
-            rtl::OUString sSetString;
-            if ( pContentBuffer )
-                sSetString = pContentBuffer->makeStringAndClear();
-            else
-                sSetString = sSimpleContent;
+        case XML_TOK_TABLE_ROW_CELL_TEXT_S:
+            pContext = new ScXMLTextTContext( GetScImport(), nTempPrefix, rLName, xTempAttrList, this);
+            break;
+        case XML_TOK_TABLE_ROW_CELL_TEXT_RUBY:
+            pContext = new ScXMLRubyContext( GetScImport(), nTempPrefix, rLName, xTempAttrList, this );
+            break;
+        default:
+            {
+                rtl::OUString sSetString;
+                if ( pContentBuffer )
+                    sSetString = pContentBuffer->makeStringAndClear();
+                else
+                    sSetString = sSimpleContent;
 
-            sal_Unicode cNonSpace(0);
-            
-            sal_Int32 nLength = sSetString.getLength();
-            if ( nLength > 0 )
-            {
-                sal_Unicode cLast = sSetString.getStr()[ nLength - 1 ];
-                if ( cLast != (sal_Unicode)' ' )
+                sal_Unicode cNonSpace(0);
+
+                sal_Int32 nLength = sSetString.getLength();
+                if ( nLength > 0 )
                 {
-                    // #i53253# To keep XMLParaContext's whitespace handling in sync,
-                    // if there's a non-space character at the end of the existing string,
-                    // it has to be processed by XMLParaContext.
+                    sal_Unicode cLast = sSetString.getStr()[ nLength - 1 ];
+                    if ( cLast != (sal_Unicode)' ' )
+                    {
+                        // #i53253# To keep XMLParaContext's whitespace handling in sync,
+                        // if there's a non-space character at the end of the existing string,
+                        // it has to be processed by XMLParaContext.
 
-                    cNonSpace = cLast;
-                    sSetString = sSetString.copy( 0, nLength - 1 );  // remove from the string for SetCursorOnTextImport
+                        cNonSpace = cLast;
+                        sSetString = sSetString.copy( 0, nLength - 1 );  // remove from the string for SetCursorOnTextImport
+                    }
+                }
+
+                pCellContext->SetCursorOnTextImport( sSetString );
+
+                pTextPContext = GetScImport().GetTextImport()->CreateTextChildContext(
+                        GetScImport(), nPrefix, sLName, xAttrList);
+
+                if ( cNonSpace != 0 )
+                {
+                    // pass non-space character through XMLParaContext, so a following space isn't ignored
+                    pTextPContext->Characters( rtl::OUString( cNonSpace ) );
                 }
             }
+            break;
+		}
+	}
 
-            pCellContext->SetCursorOnTextImport( sSetString );
-
-			pTextPContext = GetScImport().GetTextImport()->CreateTextChildContext(
-									GetScImport(), nPrefix, sLName, xAttrList);
-
-            if ( cNonSpace != 0 )
-            {
-                // pass non-space character through XMLParaContext, so a following space isn't ignored
-                pTextPContext->Characters( rtl::OUString( cNonSpace ) );
-            }
-		}
-		if (pTextPContext)
-			pContext = pTextPContext->CreateChildContext(nTempPrefix, rLName, xTempAttrList);
-	}
+    if ( pTextPContext )
+        pContext = pTextPContext->CreateChildContext(nTempPrefix, rLName, xTempAttrList);
 
 	if( !pContext )
 		pContext = new SvXMLImportContext( GetScImport(), nTempPrefix, rLName );
 		pTextPContext->EndElement();
 		GetScImport().SetRemoveLastChar(sal_True);
 	}
+    if ( sOURubyText )
+        pCellContext->SetPhoneticText( sOURubyText.makeStringAndClear() );
 }
 
+void ScXMLTextPContext::GetContent( rtl::OUString& rContent )
+{
+    if (!pTextPContext)
+    {
+        if ( pContentBuffer )
+        {
+            rtl::OUStringBuffer tmpBuffer( *pContentBuffer );
+            rContent = tmpBuffer.makeStringAndClear();
+        }
+        else
+        {
+            rContent = sSimpleContent;
+        }
+    }
+}
+
+void ScXMLTextPContext::AddRubyText( const ::rtl::OUString &rBaseText, const ::rtl::OUString& rRubyText )
+{
+    rtl::OUString aContent;
+    GetContent( aContent );
+
+    sal_uInt16 startIdx = aContent.getLength();
+    sal_uInt16 endIdx = rBaseText.getLength();
+
+    PhoneticPortion portion( sOURubyText.getLength(), startIdx, endIdx );
+    sOURubyText.append( rRubyText );
+    aPhoneticPortions.push_back( portion );
+
+    Characters ( rBaseText );
+}
+

sc/source/filter/xml/XMLTextPContext.hxx

 #include <xmloff/xmlictxt.hxx>
 #include <rtl/ustrbuf.hxx>
 
+#include "phonetic.hxx"
+
 class ScXMLImport;
 class ScXMLTableRowCellContext;
 
     rtl::OUStringBuffer*        pContentBuffer;     // used if there's more than one string
 	USHORT						nPrefix;
 	sal_Bool					bIsOwn;
+    rtl::OUStringBuffer         sOURubyText;
+    PhoneticPortionVec          aPhoneticPortions;
 
 	const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
 	ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
+    void GetContent( rtl::OUString& rContent );
 
 public:
 	ScXMLTextPContext( ScXMLImport& rImport, USHORT nPrfx,
 	virtual void EndElement();
 
 	void AddSpaces(sal_Int32 nSpaceCount);
+
+    /**
+     * Add phonetic and base text into cell. 
+     *  
+     * @param rBaseText the base string.
+     * @param rRubyText the phonetic text.
+     */
+    void AddRubyText( const ::rtl::OUString& rBaseText, const ::rtl::OUString& rRubyText );
 };
 
 #endif

sc/source/filter/xml/makefile.mk

 		$(SLO)$/xmlannoi.obj \
 		$(SLO)$/xmlsceni.obj \
 		$(SLO)$/xmlcvali.obj \
+		$(SLO)$/xmlrubyi.obj \
 		$(SLO)$/XMLTableMasterPageExport.obj \
 		$(SLO)$/xmllabri.obj \
 		$(SLO)$/XMLTableHeaderFooterContext.obj \

sc/source/filter/xml/xmlcelli.cxx

 #include "xmltabi.hxx"
 #include "xmlstyli.hxx"
 #include "xmlannoi.hxx"
+#include "xmlrubyi.hxx"
 #include "global.hxx"
 #include "document.hxx"
 #include "cellsuno.hxx"
 				rXMLImport, nPrefix, rLName, xAttrList, pCellRangeSource );
 		}
 		break;
+    case XML_TOK_TABLE_ROW_CELL_RUBY:
+        {
+            bIsEmpty = sal_False;
+            pContext = new ScXMLRubyContext( rXMLImport, nPrefix, rLName, xAttrList, this );
+        }
+        break;
 	}
 
 	if (!pContext && !bTextP)
     return ( !pCell || pCell->GetCellType() == CELLTYPE_NOTE );
 }
 
+static sal_Bool lcl_IsHalfWidthKatakana ( const ::rtl::OUString& rString )
+{
+    const sal_Unicode *pString = rString.getStr();
+    sal_Int32 nLen = rString.getLength();
+
+    for ( sal_Int32 i = 0; i < nLen; ++i )
+    {
+        if ( pString[i] < 0xFF00 || pString[i] > 0xFFEF )
+            return sal_False;
+    }
+
+    return sal_True;
+}
+
+static sal_Bool lcl_IsFullWidthKatakana ( const ::rtl::OUString& rString )
+{
+    const sal_Unicode *pString = rString.getStr();
+    sal_Int32 nLen = rString.getLength();
+
+    for ( sal_Int32 i = 0; i < nLen; ++i )
+    {
+        if ( pString[i] < 0x30A0 || pString[i] > 0x30FF )
+            return sal_False;
+    }
+
+    return sal_True;
+}
+
+static sal_Bool lcl_IsFullWidthHiragana ( const ::rtl::OUString& rString )
+{
+    const sal_Unicode *pString = rString.getStr();
+    sal_Int32 nLen = rString.getLength();
+
+    for ( sal_Int32 i = 0; i < nLen; ++i )
+    {
+        if ( pString[i] < 0x3040 || pString[i] > 0x309F )
+            return sal_False;
+    }
+
+    return sal_True;
+}
+
+static sal_uInt16 lcl_GetKanaType ( const ::boost::optional< ::rtl::OUString >& pText )
+{
+    sal_uInt16 aKanaType = 0;
+
+    if ( lcl_IsHalfWidthKatakana ( *pText ) )
+        aKanaType = 0x00;
+    else if ( lcl_IsFullWidthKatakana ( *pText ) )
+        aKanaType = 0x01;
+    else if ( lcl_IsFullWidthHiragana ( *pText ) )
+        aKanaType = 0x02;
+
+    return aKanaType;
+}
+
+static ScBaseCell* lcl_CreateTextCell ( const String& rString, ScDocument* pDoc, 
+                                        const ::boost::optional< ::rtl::OUString >& pPhoneticText )
+{
+    ScBaseCell *pCell = 0;
+
+    if ( pPhoneticText && pPhoneticText->getLength() )
+    {
+        PhoneticPortionVec xPortions;
+        sal_uInt16 aKanaType = lcl_GetKanaType ( pPhoneticText );
+        ScPhonetic aPhonetic ( 0, 0x30 | aKanaType , 0, *pPhoneticText, xPortions );
+        pCell = new ScAsianStringCell( rString, aPhonetic );
+    }
+    else
+    {
+        pCell = ScBaseCell::CreateTextCell( rString, pDoc );
+    }
+
+    return pCell;
+}
+
 void ScXMLTableRowCellContext::EndElement()
 {
 	if (!bHasSubTable)
                                                 ScBaseCell* pNewCell = NULL;
                                                 ScDocument* pDoc = rXMLImport.GetDocument();
                                                 if (pOUTextValue && pOUTextValue->getLength())
-                                                    pNewCell = ScBaseCell::CreateTextCell( *pOUTextValue, pDoc );
+                                                    pNewCell = lcl_CreateTextCell( *pOUTextValue, pDoc, pOUPhoneticText );
                                                 else if (pOUTextContent && pOUTextContent->getLength())
-                                                    pNewCell = ScBaseCell::CreateTextCell( *pOUTextContent, pDoc );
+                                                    pNewCell = lcl_CreateTextCell( *pOUTextContent, pDoc, pOUPhoneticText );
                                                 else if ( i > 0 && pOUText && pOUText->getLength() )
-                                                    pNewCell = ScBaseCell::CreateTextCell( *pOUText, pDoc );
+                                                    pNewCell = lcl_CreateTextCell( *pOUText, pDoc, pOUPhoneticText );
 
                                                 bDoIncrement = pNewCell != NULL;
                                                 if ( bDoIncrement )
 					}
 					else
 					{
+                        if ( pOUPhoneticText && pOUPhoneticText->getLength() )
+                        {
+                            ScAddress aScAddress;
+                            ScDocument* pDoc = rXMLImport.GetDocument();
+                            ScUnoConversion::FillScAddress( aScAddress, aCurrentPos );
+                            ScBaseCell *pBaseCell = pDoc->GetCell( aScAddress );
+                            PhoneticPortionVec xPortions;
+                            sal_uInt16 aKanaType = lcl_GetKanaType ( pOUPhoneticText );
+                            ScPhonetic aPhonetic ( 0, 0x30 | aKanaType , 0, *pOUPhoneticText, xPortions );
+                            ScBaseCell *pNewCell = new ScAsianEditCell( (const ScEditCell&) *pBaseCell, *pDoc, aPhonetic );
+                            pDoc->PutCell( aScAddress, pNewCell );
+                        }
                         // #i56027# If the child context put formatted text into the cell,
                         // bIsEmpty is TRUE and ProgressBarIncrement has to be called
                         // with bEditCell = TRUE.
 	nMergedRows = 1;
 	nCellsRepeated = 1;
 }
+
+void ScXMLTableRowCellContext::SetPhoneticText(const rtl::OUString& rOUPhoneticText)
+{
+    pOUPhoneticText.reset(rOUPhoneticText);
+}
+

sc/source/filter/xml/xmlcelli.hxx

 	::boost::optional< rtl::OUString > pOUTextValue;
 	::boost::optional< rtl::OUString > pOUTextContent;
     ::boost::optional< FormulaWithNamespace > pOUFormula;
+	::boost::optional< rtl::OUString > pOUPhoneticText;
 	rtl::OUString* pContentValidationName;
     ::std::auto_ptr< ScXMLAnnotationData > mxAnnotationData;
 	ScMyImpDetectiveObjVec*	pDetectiveObjVec;
 	void SetCellRangeSource( const ::com::sun::star::table::CellAddress& rPosition );
 
 	virtual void EndElement();
+
+    /**
+     * Set phonetic text. 
+     *  
+     * @param rOUPhoneticText the phonetic text
+     */
+    void SetPhoneticText(const rtl::OUString& rOUPhoneticText);
 };
 
 #endif

sc/source/filter/xml/xmlexprt.cxx

 //		{
             rMyCell.sStringValue = ScCellObj::GetOutputString_Impl(pDoc, aPos);
 			rMyCell.bHasStringValue = sal_True;
+            rMyCell.sPhoneticText = ScCellObj::GetOutputPhoneticString_Impl(pDoc, aPos);
+            rMyCell.bHasPhonetic = sal_True;
 			return sal_True;
 //		}
 	}
 }
 
+void ScXMLExport::WriteRubyText (ScMyCell& rMyCell)
+{
+    if ( !rMyCell.sPhoneticText.getLength() )
+        return;
+    StartElement( XML_NAMESPACE_TEXT, XML_RUBY, sal_False);
+    StartElement( XML_NAMESPACE_TEXT, XML_RUBY_BASE, sal_False );
+    Characters( rMyCell.sStringValue );
+    EndElement( XML_NAMESPACE_TEXT, XML_RUBY_BASE, sal_False );
+    StartElement( XML_NAMESPACE_TEXT, XML_RUBY_TEXT, sal_False );
+    Characters( rMyCell.sPhoneticText );
+    EndElement( XML_NAMESPACE_TEXT, XML_RUBY_TEXT, sal_False );
+    EndElement( XML_NAMESPACE_TEXT, XML_RUBY, sal_False);
+}
+
 void ScXMLExport::WriteCell (ScMyCell& aCell)
 {
     ScAddress aCellPos;
             uno::Reference<text::XText> xText(xCurrentTableCellRange->getCellByPosition(aCell.aCellAddress.Column, aCell.aCellAddress.Row), uno::UNO_QUERY);
 			if ( xText.is())
 				GetTextParagraphExport()->exportText(xText, sal_False, sal_False);
+            if (GetCellText( aCell, aCellPos ) && aCell.sPhoneticText.getLength())
+                WriteRubyText( aCell );
 		}
 		else
 		{
 			SvXMLElementExport aElemP(*this, sElemP, sal_True, sal_False);
 			sal_Bool bPrevCharWasSpace(sal_True);
 	  		if (GetCellText(aCell, aCellPos))
-				GetTextParagraphExport()->exportText(aCell.sStringValue, bPrevCharWasSpace);
+            {
+                if ( aCell.sPhoneticText.getLength() )
+                    WriteRubyText( aCell );
+                else 
+                    GetTextParagraphExport()->exportText( aCell.sStringValue, bPrevCharWasSpace );
+           }
 		}
 	}
 	WriteShapes(aCell);

sc/source/filter/xml/xmlexprt.hxx

 	void ExportShape(const com::sun::star::uno::Reference < com::sun::star::drawing::XShape >& xShape, com::sun::star::awt::Point* pPoint);
 	void WriteShapes(const ScMyCell& rMyCell);
 	void WriteTableShapes();
+
+    /**
+     * Write phonetic text
+     * @param aCell the cell reference which has phonetic text.
+     */
+    void WriteRubyText (ScMyCell& aCell);
 	void SetRepeatAttribute (const sal_Int32 nEqualCellCount);
 
 	sal_Bool IsCellTypeEqual (const ScMyCell& aCell1, const ScMyCell& aCell2) const;

sc/source/filter/xml/xmlimprt.cxx

     return *pTableRowCellElemTokenMap;
 }
 
+    SvXMLTokenMap           *pTableRowCellElemTextRubyAttrTokenMap;
+
+const SvXMLTokenMap& ScXMLImport::GetTableRowCellElemTextTokenMap()
+{
+    if (!pTableRowCellElemTextTokenMap)
+    {
+        static __FAR_DATA SvXMLTokenMapEntry aTableRowCellTextTokenMap[] =
+        {
+            { XML_NAMESPACE_TEXT, XML_S,    XML_TOK_TABLE_ROW_CELL_TEXT_S    },
+            { XML_NAMESPACE_TEXT, XML_RUBY, XML_TOK_TABLE_ROW_CELL_TEXT_RUBY },
+            XML_TOKEN_MAP_END
+        };
+        pTableRowCellElemTextTokenMap = new SvXMLTokenMap(aTableRowCellTextTokenMap);
+    }
+
+    return *pTableRowCellElemTextTokenMap;
+}
+
+const SvXMLTokenMap& ScXMLImport::GetTableRowCellElemTextRubyTokenMap()
+{
+    if (!pTableRowCellElemTextRubyTokenMap)
+    {
+        static __FAR_DATA SvXMLTokenMapEntry aTableRowCellTextRubyAttrTokenMap[] =
+        {
+            { XML_NAMESPACE_TEXT, XML_STYLE_NAME, XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_ATTR_STYLE_NAME },
+            XML_TOKEN_MAP_END
+        };
+        pTableRowCellElemTextRubyTokenMap = new SvXMLTokenMap(aTableRowCellTextRubyAttrTokenMap);
+    }
+
+    return *pTableRowCellElemTextRubyTokenMap;
+}
+
+const SvXMLTokenMap& ScXMLImport::GetTableRowCellElemTextRubyAttrTokenMap()
+{
+    if (!pTableRowCellElemTextRubyAttrTokenMap)
+    {
+        static __FAR_DATA SvXMLTokenMapEntry aTableRowCellTextRubyTokenMap[] =
+        {
+            { XML_NAMESPACE_TEXT, XML_RUBY_BASE, XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_BASE },
+            { XML_NAMESPACE_TEXT, XML_RUBY_TEXT, XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_TEXT },
+            XML_TOKEN_MAP_END
+        }; 
+        pTableRowCellElemTextRubyAttrTokenMap = new SvXMLTokenMap(aTableRowCellTextRubyTokenMap);
+    }
+
+    return *pTableRowCellElemTextRubyAttrTokenMap;
+}
+
 const SvXMLTokenMap& ScXMLImport::GetTableAnnotationAttrTokenMap()
 {
     if( !pTableAnnotationAttrTokenMap )
 	pTableRowElemTokenMap( 0 ),
 	pTableRowAttrTokenMap( 0 ),
 	pTableRowCellElemTokenMap( 0 ),
+	pTableRowCellElemTextTokenMap( 0 ),
+	pTableRowCellElemTextRubyTokenMap( 0 ),
+	pTableRowCellElemTextRubyAttrTokenMap( 0 ),
 	pTableRowCellAttrTokenMap( 0 ),
 	pTableAnnotationAttrTokenMap( 0 ),
 	pDetectiveElemTokenMap( 0 ),
     delete pTableRowElemTokenMap;
     delete pTableRowAttrTokenMap;
     delete pTableRowCellElemTokenMap;
+    delete pTableRowCellElemTextTokenMap;
+    delete pTableRowCellElemTextRubyTokenMap;
+    delete pTableRowCellElemTextRubyAttrTokenMap;
     delete pTableRowCellAttrTokenMap;
     delete pTableAnnotationAttrTokenMap;
     delete pDetectiveElemTokenMap;

sc/source/filter/xml/xmlimprt.hxx

 	XML_TOK_TABLE_ROW_CELL_TABLE,
 	XML_TOK_TABLE_ROW_CELL_ANNOTATION,
 	XML_TOK_TABLE_ROW_CELL_DETECTIVE,
-	XML_TOK_TABLE_ROW_CELL_CELL_RANGE_SOURCE
+    XML_TOK_TABLE_ROW_CELL_CELL_RANGE_SOURCE,
+    XML_TOK_TABLE_ROW_CELL_RUBY
+};
+
+enum ScXMLTableRowCellTextTokens
+{
+    XML_TOK_TABLE_ROW_CELL_TEXT_S,
+    XML_TOK_TABLE_ROW_CELL_TEXT_RUBY
+};
+
+enum ScXMLTableRowCellTextRubyTokens
+{
+    XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_BASE,
+    XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_TEXT
+};
+
+enum ScXMLTableRowCellTextRubyAttrTokens
+{
+    XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_ATTR_STYLE_NAME
 };
 
 enum ScXMLTableRowCellAttrTokens
 	SvXMLTokenMap			*pTableRowElemTokenMap;
 	SvXMLTokenMap			*pTableRowAttrTokenMap;
 	SvXMLTokenMap			*pTableRowCellElemTokenMap;
+    SvXMLTokenMap           *pTableRowCellElemTextTokenMap;
+    SvXMLTokenMap           *pTableRowCellElemTextRubyTokenMap;
+    SvXMLTokenMap           *pTableRowCellElemTextRubyAttrTokenMap;
 	SvXMLTokenMap			*pTableRowCellAttrTokenMap;
 	SvXMLTokenMap			*pTableAnnotationAttrTokenMap;
 	SvXMLTokenMap			*pDetectiveElemTokenMap;
 	const SvXMLTokenMap& GetTableRowElemTokenMap();
 	const SvXMLTokenMap& GetTableRowAttrTokenMap();
 	const SvXMLTokenMap& GetTableRowCellElemTokenMap();
+    const SvXMLTokenMap& GetTableRowCellElemTextTokenMap();
+    const SvXMLTokenMap& GetTableRowCellElemTextRubyTokenMap();
+    const SvXMLTokenMap& GetTableRowCellElemTextRubyAttrTokenMap();
     const SvXMLTokenMap& GetTableRowCellAttrTokenMap();
 	const SvXMLTokenMap& GetTableAnnotationAttrTokenMap();
 	const SvXMLTokenMap& GetDetectiveElemTokenMap();

sc/source/filter/xml/xmlstyle.cxx

     MAP( "IsCellBackgroundTransparent", XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_PROP_TABLE_ROW|XML_TYPE_ISTRANSPARENT|MID_FLAG_MULTI_PROPERTY|MID_FLAG_MERGE_ATTRIBUTE, 0 ),
     MAP( "IsManualPageBreak", XML_NAMESPACE_FO, XML_BREAK_BEFORE, XML_TYPE_PROP_TABLE_ROW|XML_SC_TYPE_BREAKBEFORE, CTF_SC_ROWBREAKBEFORE),
     MAP( "OptimalHeight", XML_NAMESPACE_STYLE, XML_USE_OPTIMAL_ROW_HEIGHT, XML_TYPE_PROP_TABLE_ROW|XML_TYPE_BOOL, CTF_SC_ROWOPTIMALHEIGHT),
+    MAP( "RubyText", XML_NAMESPACE_TEXT, XML_RUBY_TEXT, XML_TYPE_PROP_RUBY, 0 ),
     MAP_END()
 };
 

sc/source/filter/xml/xmlstyli.cxx

 #define XML_LINE_BLTR 1
 
 using ::rtl::OUString;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::Reference;
 using namespace ::com::sun::star;
-using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::xml::sax;
 using namespace ::com::sun::star::style;
 using namespace ::com::sun::star::frame;
     if (nFamily == XML_STYLE_FAMILY_TEXT_PARAGRAPH || nFamily == XML_STYLE_FAMILY_TEXT_TEXT)
         pStyle = new ScCellTextStyleContext( GetImport(), nPrefix, rLocalName,
                                             xAttrList, *this, nFamily );
+    else if (nFamily == XML_STYLE_FAMILY_TEXT_RUBY)
+        pStyle = new XMLRubyStyleContext ( GetScImport(), nPrefix, rLocalName,
+                                           xAttrList, *this, nFamily );
     else
         pStyle = SvXMLStylesContext::CreateStyleStyleChildContext(
                     nFamily, nPrefix, rLocalName, xAttrList );
 		ClearContent(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_PAGE_RIGHTHDRCON)));
 }
 
+class ScXMLRubyStyleContext : public SvXMLImportContext
+{
+    rtl::OUString sPosition;
+    rtl::OUString sAlign;
+public:
+
+    ScXMLRubyStyleContext(
+            SvXMLImport& rImport, sal_uInt16 nPrfx,
+            const rtl::OUString& rLName,
+            const Reference< XAttributeList > & xAttrList );
+    virtual ~ScXMLRubyStyleContext();
+
+    const rtl::OUString& GetPosition() const { return sPosition; }
+    const rtl::OUString& GetAlign() const { return sAlign; }
+};
+
+ScXMLRubyStyleContext::ScXMLRubyStyleContext(SvXMLImport& rImport, sal_uInt16 nPrfx,
+            const OUString& rLName, const Reference< XAttributeList > & xAttrList )
+    : SvXMLImportContext( rImport, nPrfx, rLName ),
+    sPosition(),
+    sAlign()
+{
+    sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
+    for( sal_Int16 i=0; i < nAttrCount; ++i )
+    {
+        const OUString& rAttrName(xAttrList->getNameByIndex( i ));
+        OUString aLocalName;
+        sal_uInt16 nPrefix(GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName ));
+        const OUString& rValue(xAttrList->getValueByIndex( i ));
+
+        if( XML_NAMESPACE_STYLE == nPrefix )
+        {
+            if( IsXMLToken(aLocalName, XML_RUBY_ALIGN ) )
+                sPosition = rValue;
+            else if( IsXMLToken(aLocalName, XML_RUBY_POSITION ) )
+                sAlign = rValue;
+        }
+    }
+}
+
+ScXMLRubyStyleContext::~ScXMLRubyStyleContext()
+{
+}
+
+TYPEINIT1( XMLRubyStyleContext, XMLPropStyleContext );
+
+XMLRubyStyleContext::XMLRubyStyleContext( ScXMLImport& rImport,
+        sal_uInt16 nPrfx, const OUString& rLName,
+        const Reference< XAttributeList > & xAttrList,
+        SvXMLStylesContext& rStyles, sal_uInt16 nFamily, sal_Bool bDefaultStyle ) :
+    XMLPropStyleContext( rImport, nPrfx, rLName, xAttrList, rStyles, nFamily, bDefaultStyle ),
+    pStyles(&rStyles)
+{
+}
+
+XMLRubyStyleContext::~XMLRubyStyleContext()
+{
+}
+
+SvXMLImportContext *XMLRubyStyleContext::CreateChildContext(
+        sal_uInt16 nPrefix,
+        const OUString& rLocalName,
+        const Reference< XAttributeList > & xAttrList )
+{
+    SvXMLImportContext *pContext(NULL);
+
+    if( (XML_NAMESPACE_STYLE == nPrefix) &&
+        IsXMLToken(rLocalName, XML_RUBY_PROPERTIES ) )
+    {
+        pContext = new ScXMLRubyStyleContext(GetImport(), nPrefix, rLocalName, xAttrList);
+        sPosition = ((ScXMLRubyStyleContext*)pContext)->GetPosition();
+        sAlign = ((ScXMLRubyStyleContext*)pContext)->GetAlign();
+    }
+    if (!pContext)
+        pContext = XMLPropStyleContext::CreateChildContext( nPrefix, rLocalName,
+                                                           xAttrList );
+    return pContext;
+}
+
+void XMLRubyStyleContext::FillPropertySet( const Reference< XPropertySet > & rPropSet )
+{
+    XMLPropStyleContext::FillPropertySet(rPropSet);
+}
+
+void XMLRubyStyleContext::SetDefaults()
+{
+    if ((GetFamily() == XML_STYLE_FAMILY_TEXT_RUBY) && GetImport().GetModel().is())
+    {
+        uno::Reference <lang::XMultiServiceFactory> xMultiServiceFactory(GetImport().GetModel(), uno::UNO_QUERY);
+        if (xMultiServiceFactory.is())
+        {
+            uno::Reference <beans::XPropertySet> xProperties(xMultiServiceFactory->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.Defaults"))), uno::UNO_QUERY);
+            if (xProperties.is())
+                FillPropertySet(xProperties);
+        }
+    }
+}
+
+
 // ---------------------------------------------------------------------------
 
 ScCellTextStyleContext::ScCellTextStyleContext( SvXMLImport& rImport, sal_uInt16 nPrfx,

sc/source/filter/xml/xmlstyli.hxx

 	virtual void EndElement();
 };
 
+/**
+ * A class for representing ruby style while loading ODF file.
+ */
+class XMLRubyStyleContext : public XMLPropStyleContext
+{
+    SvXMLStylesContext*         pStyles;
+    rtl::OUString sPosition;
+    rtl::OUString sAlign;
+
+    const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
+    ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
+
+public:
+
+    TYPEINFO();
+
+    /**
+     * A constructor of XMLRubyStyleContext.
+     * @param rImport a reference of ScXMLImport.
+     * @param nPrfx the number of the element prefix.
+     * @param rLName the string of the element.
+     * @param xAttrList attribute list of the element.
+     * @param rStyles a reference of SvXMLStylesContext.
+     * @param bDefaultStyle a flag of use of default style.
+     */
+    XMLRubyStyleContext( ScXMLImport& rImport, sal_uInt16 nPrfx,
+            const ::rtl::OUString& rLName,
+            const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
+            SvXMLStylesContext& rStyles, sal_uInt16 nFamily, sal_Bool bDefaultStyle = sal_False );
+    virtual ~XMLRubyStyleContext();
+
+    /**
+     * Create a childs element context. By default, the import's
+     * CreateContext method is called to create a new default context.
+     * @param nPrefix
+     * @param rLocalName
+     * @param xAttrList
+     * @return a new default context.
+     */
+    virtual SvXMLImportContext *CreateChildContext(
+            sal_uInt16 nPrefix,
+            const ::rtl::OUString& rLocalName,
+            const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+
+    virtual void FillPropertySet(const ::com::sun::star::uno::Reference<
+                ::com::sun::star::beans::XPropertySet > & rPropSet );
+
+    virtual void SetDefaults();
+
+private:
+    using XMLPropStyleContext::SetStyle;
+};
+
 namespace com { namespace sun { namespace star {
 	namespace style { class XStyle; }
 } } }

sc/source/ui/src/scfuncs.src

             Text [ en-US ] = "The text to convert.";
         };
     };
+     // -=*# Resource for function PHONETIC #*=-
+    Resource SC_OPCODE_PHONETIC
+    {
+        String 1 // Description
+        {
+            Text [ en-US ] = "Returns a phonetic guide text." ;
+            Text [ ja ] = "ふりがな文字列を返します。" ;
+        };
+        ExtraData =
+        {
+            0;
+            ID_FUNCTION_GRP_TEXT;
+            U2S( HID_FUNC_PHONETIC );
+            1;  0;
+            0;
+        };
+        String 2 // Name of Parameter 1
+        {
+            Text [ en-US ] = "range" ;
+            Text [ ja ] = "範囲" ;
+        };
+        String 3 // Description of Parameter 1
+        {
+            Text [ en-US ] = "The cell range from which phonetic guide texts are retrieved." ;
+            Text [ ja ] = "ふりがな文字列を取り出すセル範囲。" ;
+        };
+    };
 	 // -=*# Resource for function CODE #*=-
 	Resource SC_OPCODE_CODE
 	{

sc/source/ui/unoobj/cellsuno.cxx

 	return aVal;
 }
 
+String ScCellObj::GetOutputPhoneticString_Impl(ScDocument* pDoc, const ScAddress& aCellPos)
+{
+    String aVal;
+    if ( pDoc )
+    {
+        ScBaseCell* pCell = pDoc->GetCell( aCellPos );
+        if ( pCell && pCell->GetCellType() == CELLTYPE_STRING &&
+             static_cast<const ScStringCell*>(pCell)->HasPhonetic() )
+        {
+            ScPhonetic aPhonetic;
+            static_cast<const ScAsianStringCell*>(pCell)->GetPhonetic(aPhonetic);
+            if ( !aPhonetic.IsEmpty() )
+                aVal = aPhonetic.GetString();
+        }
+        else if ( pCell && pCell->GetCellType() == CELLTYPE_EDIT && 
+                  static_cast<const ScEditCell*>(pCell)->HasPhonetic() )
+        {
+            ScPhonetic aPhonetic;
+            static_cast<const ScAsianEditCell*>(pCell)->GetPhonetic(aPhonetic);
+            if ( !aPhonetic.IsEmpty() )
+                aVal = aPhonetic.GetString();
+        }
+    }
+    return aVal;
+}
+
 String ScCellObj::GetOutputString_Impl() const
 {
 	ScDocShell* pDocSh = GetDocShell();

sc/util/hidother.src

 hidspecial HID_FUNC_GAMMA           { HelpID = HID_FUNC_GAMMA; };
 hidspecial HID_FUNC_CHISQDIST       { HelpID = HID_FUNC_CHISQDIST; };
 hidspecial HID_FUNC_CHISQINV        { HelpID = HID_FUNC_CHISQINV; };
+hidspecial HID_FUNC_PHONETIC        { HelpID = HID_FUNC_PHONETIC; };
 
 // ... and from Analysis Addin