ooo-build r14430 - in trunk: . patches/dev300



Author: kyoshida
Date: Wed Oct 29 20:21:37 2008
New Revision: 14430
URL: http://svn.gnome.org/viewvc/ooo-build?rev=14430&view=rev

Log:
2008-10-29  Kohei Yoshida  <kyoshida novell com>

	* patches/dev300/calc-formula-asian-phonetic.diff: support PHONETIC
	function that displays Asian phonetic guide from Japanese strings.  
	Adopted from patch written by Hiroyoki Ikezoe (ikezoe clear-code com)
	as part of the Japanese Seagull Development Project 2007 (i#80764, 
	i#80765, i#80766).

	* patches/dev300/apply: apply this new patch in CalcExperimental.  This
	patch is disabled by default.


Added:
   trunk/patches/dev300/calc-formula-asian-phonetic.diff
Modified:
   trunk/ChangeLog
   trunk/patches/dev300/apply

Modified: trunk/patches/dev300/apply
==============================================================================
--- trunk/patches/dev300/apply	(original)
+++ trunk/patches/dev300/apply	Wed Oct 29 20:21:37 2008
@@ -1833,6 +1833,9 @@
 # faster file load.
 calc-xls-disable-adjust-row-height.diff, kohei
 
+# Support PHONETIC function to display asian phonetic guide.
+calc-formula-asian-phonetic.diff, i#80764, i#80765, i#80766, kohei
+
 [ CalcSolver ]
 SectionOwner => kohei
 

Added: trunk/patches/dev300/calc-formula-asian-phonetic.diff
==============================================================================
--- (empty file)
+++ trunk/patches/dev300/calc-formula-asian-phonetic.diff	Wed Oct 29 20:21:37 2008
@@ -0,0 +1,2776 @@
+diff --git sc/inc/cell.hxx sc/inc/cell.hxx
+index a5aa3cf..816104c 100644
+--- sc/inc/cell.hxx
++++ sc/inc/cell.hxx
+@@ -43,6 +43,7 @@
+ #include "tokenarray.hxx"
+ #include "grammar.hxx"
+ #include "formularesult.hxx"
++#include "phonetic.hxx"
+ #include <rtl/ustrbuf.hxx>
+ #include <vcl/fontcvt.hxx>
+ 
+@@ -62,6 +63,7 @@ class ScTokenArray;
+ class ScProgress;
+ class ScPostIt;
+ class ScPatternAttr;
++class ScPhonetic;
+ 
+ class ScMultipleReadHeader;
+ class ScMultipleWriteHeader;
+@@ -169,6 +171,69 @@ public:
+ 
+ 	void			SetString( const String& rString );
+ 	void			GetString( String& rString ) const;
++
++    virtual bool    HasPhonetic() const;
++};
++
++/**
++ * A class for representing of Asian phonetic guide.
++ */
++class 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 rAsianStringCell a reference of ScAsianStringCell.
++     * @param pDoc a pointer of ScDocument.
++     */
++    ScAsianStringCell( const ScAsianStringCell& rScAsianStringCell, ScDocument* pDoc );
++
++    /**
++     * A constructor of ScAsianStringCell
++     * @param rStream a reference of SvStream.
++     * @param nVer the number of vesion.
++     */
++    ScAsianStringCell( SvStream& rStream, USHORT nVer );
++
++    /**
++     * Creates a new ScAsianStringCell.
++     * @return a pointer of the ScBaseCell.
++     */
++    ScBaseCell*     Clone(ScDocument* pDoc) const;
++
++    /**
++     * 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;
+ };
+ 
+ 
+@@ -206,6 +271,8 @@ public:
+ 	void			GetData( const EditTextObject*& rpObject ) const;
+ 	void			GetString( String& rString ) const;
+ 
++    virtual bool    HasPhonetic() const;
++
+ 	const EditTextObject* GetData() const	{ return pData; }
+ 
+     /** Removes character attribute based on new pattern attributes. */
+@@ -258,6 +325,73 @@ private:
+ 
+ // ----------------------------------------------------------------------------
+ 
++
++/**
++ * A class for representing of Asian phonetic guide.
++ * It is derived from ScStringCell.
++ */
++class 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 SCAsianEditCell.
++     * @param pDoc a pointer of ScDocument.
++     */
++    ScAsianEditCell( const ScAsianEditCell& rEditCell, ScDocument* pDoc );
++
++    /**
++     * 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 *pDoc, 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 );
++
++    /**
++     * Creates a new ScAsianStringCell.
++     * @return a pointer of the ScBaseCell.
++     */
++    ScBaseCell*     Clone(ScDocument* pDoc) const;
++
++    /**
++     * 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
+@@ -589,6 +723,91 @@ inline void ScStringCell::SetString( const String& rString )
+ 	aString = rString;
+ }
+ 
++inline bool ScStringCell::HasPhonetic() const
++{
++    return false;
++}
++
++// ScAsianStringCell
++
++inline ScAsianStringCell::ScAsianStringCell() :
++    ScStringCell( CELLTYPE_STRING )
++{
++}
++
++inline ScAsianStringCell::ScAsianStringCell( const ScAsianStringCell& rScAsianStringCell, ScDocument* pDoc ) :
++    ScStringCell( rScAsianStringCell, pDoc ),
++    aPhonetic ( rScAsianStringCell.aPhonetic )
++{
++}
++
++inline ScAsianStringCell::ScAsianStringCell( const String& rString, const ScPhonetic& rPhonetic ) :
++    ScStringCell ( rString ),
++    aPhonetic ( rPhonetic )
++{
++}
++
++inline ScBaseCell* ScAsianStringCell::Clone(ScDocument* pDoc) const
++{
++    return new ScAsianStringCell(*this, pDoc);
++}
++
++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 ScAsianEditCell& rEditCell, ScDocument* pDocP) :
++    ScEditCell( (const ScEditCell&)rEditCell, pDocP ),
++    aPhonetic( rEditCell.aPhonetic )
++{
++}
++
++inline ScAsianEditCell::ScAsianEditCell( const ScEditCell& rEditCell, ScDocument* pDocP, const ScPhonetic& rPhonetic ) :
++    ScEditCell( rEditCell, pDocP ),
++    aPhonetic( rPhonetic )
++{
++}
++
++inline ScAsianEditCell::ScAsianEditCell( const EditTextObject* pObject, ScDocument* pDocP,
++                                         const SfxItemPool* pFromPool, const ScPhonetic& rPhonetic ) :
++    ScEditCell( pObject, pDocP, pFromPool ),
++    aPhonetic( rPhonetic )
++{
++}
++
++inline ScBaseCell* ScAsianEditCell::Clone(ScDocument* pDocP) const
++{
++    return new ScAsianEditCell(*this, pDocP);
++}
++
++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;
++}
++
+ 
+ /*
+ 
+diff --git sc/inc/cellsuno.hxx sc/inc/cellsuno.hxx
+index 99b32c4..e89bd77 100644
+--- sc/inc/cellsuno.hxx
++++ sc/inc/cellsuno.hxx
+@@ -976,6 +976,14 @@ public:
+ 
+ 	static String		GetInputString_Impl(ScDocument* pDoc, const ScAddress& aPos, BOOL bEnglish);
+ 	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);
+ };
+ 
+ 
+diff --git sc/inc/compiler.hrc sc/inc/compiler.hrc
+index ec67599..a8a9d78 100644
+--- sc/inc/compiler.hrc
++++ sc/inc/compiler.hrc
+@@ -192,7 +192,8 @@
+ #define SC_OPCODE_ASC               154
+ #define SC_OPCODE_UNICODE           155
+ #define SC_OPCODE_UNICHAR           156
+-#define SC_OPCODE_STOP_1_PAR        157
++#define SC_OPCODE_PHONETIC          157
++#define SC_OPCODE_STOP_1_PAR        158
+ 
+ /*** Functions with more than one parameters ***/
+ #define SC_OPCODE_START_2_PAR       201
+diff --git sc/inc/opcode.hxx sc/inc/opcode.hxx
+index e0940f7..a98fb5b 100644
+--- sc/inc/opcode.hxx
++++ sc/inc/opcode.hxx
+@@ -187,6 +187,7 @@ enum OpCodeEnum
+         ocAsc               = SC_OPCODE_ASC,
+         ocUnicode           = SC_OPCODE_UNICODE,
+         ocUnichar           = SC_OPCODE_UNICHAR,
++        ocPhonetic          = SC_OPCODE_PHONETIC,
+ 	// Functions with more than one parameters
+ 		ocArcTan2			= SC_OPCODE_ARC_TAN_2,
+ 		ocCeil				= SC_OPCODE_CEIL,
+diff --git sc/inc/phonetic.hxx sc/inc/phonetic.hxx
+new file mode 100644
+index 0000000..9a369d8
+--- /dev/null
++++ sc/inc/phonetic.hxx
+@@ -0,0 +1,107 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: global.hxx,v $
++ * $Revision: 1.53 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifndef SC_PHONETIC_HXX
++#define SC_PHONETIC_HXX
++
++#include <vector>
++
++#ifndef _STRING_HXX
++#include <tools/string.hxx>
++#endif
++
++struct PhoneticPortion
++{
++    sal_uInt16          mncpa;  /// position of the first character in the phonetic text
++    sal_uInt16          mncpm;  /// position of the first character in the base text
++    sal_uInt16          mnccm;  /// length of the characters in the base text
++    explicit inline     PhoneticPortion() : mncpa( 0 ), mncpm( 0 ), mnccm( 0 ) {}
++    explicit inline     PhoneticPortion( sal_uInt16 ncpa, sal_uInt16 ncpm, sal_uInt16 nccm ) :
++                            mncpa( ncpa ), mncpm( ncpm ), mnccm ( nccm ) {}
++};
++
++inline bool operator==( const PhoneticPortion& rLeft, const PhoneticPortion& rRight )
++{
++    return
++        ( rLeft.mncpa == rRight.mncpa ) &&
++        ( rLeft.mncpm == rRight.mncpm ) &&
++        ( rLeft.mnccm == rRight.mnccm );
++}
++
++typedef ::std::vector< PhoneticPortion > PhoneticPortionVec;
++
++/*
++ * A class for store Asian phonetic guide information.
++ */
++class ScPhonetic
++{
++public:
++	ScPhonetic() : mnFontIdx( 0 ), mnAdditionalSettings( 0 ), mnRepeatedTotalLength ( 0 ) {}
++	/** A constructor of ScPhonetic.
++	 * @param nFontIdx font index.
++	 * @param nAdditionalSettings an additional settings.
++	 * @param nRepeatedTotalLength the number of repeated total length.
++	 * @param rPhoneticString phonetic text.
++	 * @param rPhoneticPortions the portion of phonetic text.
++	 */
++	ScPhonetic( sal_uInt16 nFontIdx, sal_uInt16 nAdditionalSettings,
++					sal_uInt16 nRepeatedTotalLength, const String& rPhoneticString,
++					const PhoneticPortionVec& rPhoneticPortions) :
++		mnFontIdx( nFontIdx ), mnAdditionalSettings( nAdditionalSettings ),
++		mnRepeatedTotalLength ( nRepeatedTotalLength ),
++		maPhoneticString ( rPhoneticString ), maPhoneticPortions ( rPhoneticPortions ) {}
++	virtual ~ScPhonetic();
++
++	virtual int             operator==( const ScPhonetic& ) const;
++
++	/** Returns True if no phonetic information. */
++	inline BOOL IsEmpty() const { return maPhoneticString.Len() == 0; }
++	/** Returns the text for phonetic information. */
++	inline const String& GetString() const { return maPhoneticString; }
++    /** Returns the portion for phonetic information. */
++	inline const PhoneticPortionVec& 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;
++	PhoneticPortionVec maPhoneticPortions;
++};
++
++#endif
+diff --git sc/inc/scfuncs.hrc sc/inc/scfuncs.hrc
+index 37e62f6..5d34782 100644
+--- sc/inc/scfuncs.hrc
++++ sc/inc/scfuncs.hrc
+@@ -330,3 +330,4 @@
+ #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)
+diff --git sc/source/core/data/cell.cxx sc/source/core/data/cell.cxx
+index c330826..df5e777 100644
+--- sc/source/core/data/cell.cxx
++++ sc/source/core/data/cell.cxx
+@@ -75,10 +75,14 @@ const USHORT nMemPoolValueCell = (0x8000 - 64) / sizeof(ScValueCell);
+ 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
+ 
+ #ifndef PRODUCT
+@@ -483,19 +487,31 @@ BOOL ScBaseCell::CellEqual( const ScBaseCell* pCell1, const ScBaseCell* pCell2 )
+ 			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 !!!!!
+diff --git sc/source/core/data/cell2.cxx sc/source/core/data/cell2.cxx
+index f770a60..91dd93a 100644
+--- sc/source/core/data/cell2.cxx
++++ sc/source/core/data/cell2.cxx
+@@ -143,6 +143,11 @@ void ScEditCell::GetString( String& rString ) const
+         rString.Erase();
+ }
+ 
++bool ScEditCell::HasPhonetic() const
++{
++    return false;
++}
++
+ void ScEditCell::RemoveCharAttribs( const ScPatternAttr& rAttr )
+ {
+     const struct {
+diff --git sc/source/core/data/makefile.mk sc/source/core/data/makefile.mk
+index 1cad27e..b6c8269 100644
+--- sc/source/core/data/makefile.mk
++++ sc/source/core/data/makefile.mk
+@@ -97,6 +97,7 @@ SLOFILES =  \
+ 	$(SLO)$/patattr.obj \
+ 	$(SLO)$/pivot.obj \
+ 	$(SLO)$/pivot2.obj \
++	$(SLO)$/phonetic.obj \
+ 	$(SLO)$/poolhelp.obj \
+ 	$(SLO)$/scimpexpmsg.obj \
+ 	$(SLO)$/sortparam.obj \
+diff --git sc/source/core/data/phonetic.cxx sc/source/core/data/phonetic.cxx
+new file mode 100644
+index 0000000..1bd10fa
+--- /dev/null
++++ sc/source/core/data/phonetic.cxx
+@@ -0,0 +1,72 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: global.hxx,v $
++ * $Revision: 1.53 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_sc.hxx"
++
++// INCLUDE ---------------------------------------------------------------
++
++#if 1
++#ifndef _COM_SUN_STAR_UTIL_CELLPROTECTION_HPP_
++#include <com/sun/star/util/CellProtection.hpp>
++#endif
++#ifndef _COM_SUN_STAR_UTIL_XPROTECTABLE_HPP_
++#include <com/sun/star/util/XProtectable.hpp>
++#endif
++#ifndef _COM_SUN_STAR_TEXT_XTEXT_HPP_
++#include <com/sun/star/text/XText.hpp>
++#endif
++#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
++#include <com/sun/star/beans/XPropertySet.hpp>
++#endif
++#endif
++
++#include "phonetic.hxx"
++
++using namespace com::sun::star;
++
++
++//------------------------------------------------------------------------
++
++ScPhonetic::~ScPhonetic()
++{
++}
++
++//------------------------------------------------------------------------
++
++int ScPhonetic::operator==( const ScPhonetic& rItem ) const
++{
++	return ((mnFontIdx == rItem.mnFontIdx)
++			 && (mnAdditionalSettings == rItem.mnAdditionalSettings)
++			 && (mnRepeatedTotalLength == rItem.mnRepeatedTotalLength)
++			 && (maPhoneticString == rItem.maPhoneticString)
++			 && (maPhoneticPortions == rItem.maPhoneticPortions));
++}
++
+diff --git sc/source/core/inc/interpre.hxx sc/source/core/inc/interpre.hxx
+index f9c5df5..ae73a6f 100644
+--- sc/source/core/inc/interpre.hxx
++++ sc/source/core/inc/interpre.hxx
+@@ -179,6 +179,7 @@ double GetValueCellValue( const ScAddress&, const ScValueCell* );
+ 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 )
+@@ -508,6 +509,7 @@ void ScExternalRef();
+ void ScGetPivotData();
+ void ScHyperLink();
+ void ScBahtText();
++void ScPhoneticString();
+ void ScCalcTeam();
+ void ScAnswer();
+ void ScTTT();
+diff --git sc/source/core/src/compiler.src sc/source/core/src/compiler.src
+index adf9402..579f2f8 100644
+--- sc/source/core/src/compiler.src
++++ sc/source/core/src/compiler.src
+@@ -1167,6 +1167,10 @@ Resource RID_SC_FUNCTION_NAMES
+     {
+         Text [ en-US ] = "BAHTTEXT";
+     };
++    String SC_OPCODE_PHONETIC
++    {
++        Text [ en-US ] = "PHONETIC";
++    };
+     String SC_OPCODE_GET_PIVOT_DATA
+     {
+         Text [ en-US ] = "GETPIVOTDATA";
+@@ -1526,6 +1530,7 @@ Resource RID_SC_FUNCTION_NAMES_ENGLISH
+ 	String SC_OPCODE_HYPERLINK { Text = "HYPERLINK" ; };
+     String SC_OPCODE_INFO { Text = "INFO" ; };
+     String SC_OPCODE_BAHTTEXT { Text = "BAHTTEXT" ; };
++    String SC_OPCODE_PHONETIC { Text = "PHONETIC" ; };
+     String SC_OPCODE_GET_PIVOT_DATA { Text = "GETPIVOTDATA" ; };
+ 	String SC_OPCODE_EUROCONVERT { Text = "EUROCONVERT" ; };
+ 	String SC_OPCODE_NUMBERVALUE { Text = "NUMBERVALUE" ; };
+@@ -1847,6 +1852,7 @@ Resource RID_SC_FUNCTION_NAMES_ENGLISH_ODFF
+ 	String SC_OPCODE_HYPERLINK { Text = "HYPERLINK" ; };
+     String SC_OPCODE_INFO { Text = "INFO" ; };
+     String SC_OPCODE_BAHTTEXT { Text = "COM.MICROSOFT.BAHTTEXT" ; };
++    String SC_OPCODE_PHONETIC { Text = "PHONETIC" ; };
+     String SC_OPCODE_GET_PIVOT_DATA { Text = "GETPIVOTDATA" ; };
+ 	String SC_OPCODE_EUROCONVERT { Text = "EUROCONVERT" ; };
+ 	String SC_OPCODE_NUMBERVALUE { Text = "NUMBERVALUE" ; };
+diff --git sc/source/core/tool/interpr2.cxx sc/source/core/tool/interpr2.cxx
+index 17ee3a4..30bf04b 100644
+--- sc/source/core/tool/interpr2.cxx
++++ sc/source/core/tool/interpr2.cxx
+@@ -2667,6 +2667,76 @@ void ScInterpreter::ScBahtText()
+ 
+ // ============================================================================
+ 
++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()
+ {
+     BYTE nParamCount = GetByte();
+diff --git sc/source/core/tool/interpr4.cxx sc/source/core/tool/interpr4.cxx
+index 9350576..64359c8 100644
+--- sc/source/core/tool/interpr4.cxx
++++ sc/source/core/tool/interpr4.cxx
+@@ -341,6 +341,189 @@ void ScInterpreter::GetCellString( String& rStr, const ScBaseCell* pCell )
+     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)
+@@ -3779,6 +3962,7 @@ StackVar ScInterpreter::Interpret()
+                 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;
+diff --git sc/source/filter/excel/xehelper.cxx sc/source/filter/excel/xehelper.cxx
+index 37bab79..6159835 100644
+--- sc/source/filter/excel/xehelper.cxx
++++ sc/source/filter/excel/xehelper.cxx
+@@ -587,7 +587,16 @@ XclExpStringRef XclExpStringHelper::CreateCellString(
+ {
+     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(
+@@ -618,6 +627,15 @@ 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;
+ }
+ 
+diff --git sc/source/filter/excel/xestring.cxx sc/source/filter/excel/xestring.cxx
+index a367647..78bca3e 100644
+--- sc/source/filter/excel/xestring.cxx
++++ sc/source/filter/excel/xestring.cxx
+@@ -253,7 +253,8 @@ bool XclExpString::IsEqual( const XclExpString& rCmp ) const
+             ( mbIsBiff8 && (maUniBuffer  == rCmp.maUniBuffer)) ||
+             (!mbIsBiff8 && (maCharBuffer == rCmp.maCharBuffer))
+         ) &&
+-        (maFormats      == rCmp.maFormats);
++        (maFormats   == rCmp.maFormats)      &&
++        (maPhonetic  == rCmp.maPhonetic);
+ }
+ 
+ bool XclExpString::IsLessThan( const XclExpString& rCmp ) const
+@@ -264,6 +265,18 @@ 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
+@@ -271,17 +284,25 @@ 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
+@@ -292,9 +313,10 @@ 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
+@@ -342,6 +364,10 @@ void XclExpString::WriteHeader( XclExpStream& rStrm ) const
+     // format run count
+     if( IsWriteFormats() )
+         rStrm << GetFormatsCount();
++    // format phonetic settings
++    if( IsWritePhoneticSettings() )
++        rStrm << GetPhoneticSettingsCount();
++
+     rStrm.SetSliceSize( 0 );
+ }
+ 
+@@ -378,12 +404,54 @@ void XclExpString::WriteFormats( XclExpStream& rStrm, bool bWriteSize ) const
+     }
+ }
+ 
++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
+@@ -449,6 +517,11 @@ bool XclExpString::IsWriteFormats() 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;
+diff --git sc/source/filter/excel/xihelper.cxx sc/source/filter/excel/xihelper.cxx
+index 1a38697..0e44ba6 100644
+--- sc/source/filter/excel/xihelper.cxx
++++ sc/source/filter/excel/xihelper.cxx
+@@ -271,10 +271,20 @@ ScBaseCell* XclImpStringHelper::CreateCell(
+         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;
+diff --git sc/source/filter/excel/xistring.cxx sc/source/filter/excel/xistring.cxx
+index 3d77ae0..48f8e87 100644
+--- sc/source/filter/excel/xistring.cxx
++++ sc/source/filter/excel/xistring.cxx
+@@ -94,7 +94,8 @@ void XclImpString::Read( XclImpStream& rStrm, XclStrFlags nFlags )
+                 ReadFormats( rStrm, nRunCount );
+ 
+             // --- extended (FarEast) information ---
+-            rStrm.Ignore( nExtInf );
++            if( nExtInf > 0 )
++                ReadPhoneticSettings( rStrm, nExtInf );
+         }
+         break;
+ 
+@@ -146,6 +147,31 @@ void XclImpString::ReadFormats( XclImpStream& rStrm, XclFormatRunVec& rFormats,
+     }
+ }
+ 
++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 ) :
+diff --git sc/source/filter/excel/xlformula.cxx sc/source/filter/excel/xlformula.cxx
+index 8912407..3e0bc20 100644
+--- sc/source/filter/excel/xlformula.cxx
++++ sc/source/filter/excel/xlformula.cxx
+@@ -324,12 +324,12 @@ static const XclFunctionInfo saFuncTable_5[] =
+ 
+ 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, { V, R, V }, 0, 0 },
+     { ocHyperLink,          359,    1,  2,  V, { V }, 0, 0 },
+-    { ocNoName,             360,    1,  1,  V, { R }, EXC_FUNCFLAG_IMPORTONLY, 0 },    // PHONETIC
++    { ocPhonetic,           360,    1,  1,  V, { R }, 0, 0 },    // PHONETIC
+     { ocAverageA,           361,    1,  30, V, { R }, 0, 0 },
+     { ocMaxA,               362,    1,  30, V, { R }, 0, 0 },
+     { ocMinA,               363,    1,  30, V, { R }, 0, 0 },
+diff --git sc/source/filter/inc/xestring.hxx sc/source/filter/inc/xestring.hxx
+index d4ce93d..ac80cf6 100644
+--- sc/source/filter/inc/xestring.hxx
++++ sc/source/filter/inc/xestring.hxx
+@@ -32,11 +32,13 @@
+ #define SC_XESTRING_HXX
+ 
+ #include "xlstring.hxx"
++#include "phonetic.hxx"
+ 
+ // ============================================================================
+ 
+ class ScEditCell;
+ class ScPatternAttr;
++class ScPhonetic;
+ class EditTextObject;
+ class XclExpStream;
+ 
+@@ -161,6 +163,12 @@ public:
+     /** 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. */
+@@ -181,6 +189,11 @@ public:
+     /** 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. */
+@@ -207,6 +220,8 @@ public:
+     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;
+ 
+@@ -223,6 +238,8 @@ private:
+     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 );
+@@ -277,6 +294,7 @@ private:
+     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.
+diff --git sc/source/filter/inc/xistring.hxx sc/source/filter/inc/xistring.hxx
+index 1be9886..046121f 100644
+--- sc/source/filter/inc/xistring.hxx
++++ sc/source/filter/inc/xistring.hxx
+@@ -32,6 +32,7 @@
+ #define SC_XISTRING_HXX
+ 
+ #include "xlstring.hxx"
++#include "phonetic.hxx"
+ 
+ // Byte/Unicode strings =======================================================
+ 
+@@ -79,9 +80,19 @@ public:
+     /** Reads and appends nRunCount formatting runs from stream. */
+     static void         ReadFormats( XclImpStream& rStrm, XclFormatRunVec& rFormats, sal_uInt16 nRunCount );
+ 
++    /** 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 ============================================================
+diff --git sc/source/filter/inc/xlstring.hxx sc/source/filter/inc/xlstring.hxx
+index 626b11b..0b30049 100644
+--- sc/source/filter/inc/xlstring.hxx
++++ sc/source/filter/inc/xlstring.hxx
+@@ -93,7 +93,68 @@ inline bool operator<( const XclFormatRun& rLeft, const XclFormatRun& rRight )
+ /** 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
+ 
+diff --git sc/source/filter/xml/XMLExportIterator.cxx sc/source/filter/xml/XMLExportIterator.cxx
+index 8a7e52b..29a2e2c 100644
+--- sc/source/filter/xml/XMLExportIterator.cxx
++++ sc/source/filter/xml/XMLExportIterator.cxx
+@@ -584,7 +584,8 @@ ScMyCell::ScMyCell() :
+ 	bHasXText( sal_False ),
+ 	bIsMatrixBase( sal_False ),
+ 	bIsMatrixCovered( sal_False ),
+-	bHasAnnotation( sal_False )
++    bHasAnnotation( sal_False ),
++    bHasPhonetic( sal_False )
+ {
+ }
+ 
+diff --git sc/source/filter/xml/XMLExportIterator.hxx sc/source/filter/xml/XMLExportIterator.hxx
+index 0b0d51c..9d1834c 100644
+--- sc/source/filter/xml/XMLExportIterator.hxx
++++ sc/source/filter/xml/XMLExportIterator.hxx
+@@ -301,6 +301,7 @@ struct ScMyCell
+ 
+ 	rtl::OUString				sStringValue;
+ 	rtl::OUString				sAnnotationText;
++    rtl::OUString               sPhoneticText;
+ 
+ 	ScMyAreaLink				aAreaLink;
+ 	ScMyShapeList				aShapeList;
+@@ -334,6 +335,7 @@ struct ScMyCell
+ 	sal_Bool					bIsMatrixBase;
+ 	sal_Bool					bIsMatrixCovered;
+ 	sal_Bool					bHasAnnotation;
++    sal_Bool                    bHasPhonetic;
+ 
+ 								ScMyCell();
+ 								~ScMyCell();
+diff --git sc/source/filter/xml/XMLTextPContext.cxx sc/source/filter/xml/XMLTextPContext.cxx
+index c4464b3..40f5e0b 100644
+--- sc/source/filter/xml/XMLTextPContext.cxx
++++ sc/source/filter/xml/XMLTextPContext.cxx
+@@ -37,6 +37,7 @@
+ #include "XMLTextPContext.hxx"
+ #include "xmlimprt.hxx"
+ #include "xmlcelli.hxx"
++#include "xmlrubyi.hxx"
+ #include <xmloff/xmlnmspe.hxx>
+ #include <xmloff/xmltoken.hxx>
+ #include <xmloff/nmspmap.hxx>
+@@ -137,52 +138,61 @@ SvXMLImportContext *ScXMLTextPContext::CreateChildContext( USHORT nTempPrefix,
+ 									  	::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;
+-
+-            sal_Unicode cNonSpace(0);
+-            
+-            sal_Int32 nLength = sSetString.getLength();
+-            if ( nLength > 0 )
++        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:
+             {
+-                sal_Unicode cLast = sSetString.getStr()[ nLength - 1 ];
+-                if ( cLast != (sal_Unicode)' ' )
++                rtl::OUString sSetString;
++                if ( pContentBuffer )
++                    sSetString = pContentBuffer->makeStringAndClear();
++                else
++                    sSetString = sSimpleContent;
++
++                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 );
++                pCellContext->SetCursorOnTextImport( sSetString );
+ 
+-			pTextPContext = GetScImport().GetTextImport()->CreateTextChildContext(
+-									GetScImport(), nPrefix, sLName, xAttrList);
++                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 ( cNonSpace != 0 )
++                {
++                    // pass non-space character through XMLParaContext, so a following space isn't ignored
++                    pTextPContext->Characters( rtl::OUString( cNonSpace ) );
++                }
+             }
++            break;
+ 		}
+-		if (pTextPContext)
+-			pContext = pTextPContext->CreateChildContext(nTempPrefix, rLName, xTempAttrList);
+ 	}
+ 
++    if ( pTextPContext )
++        pContext = pTextPContext->CreateChildContext(nTempPrefix, rLName, xTempAttrList);
++
+ 	if( !pContext )
+ 		pContext = new SvXMLImportContext( GetScImport(), nTempPrefix, rLName );
+ 
+@@ -223,5 +233,38 @@ void ScXMLTextPContext::EndElement()
+ 		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 );
+ }
+ 
+diff --git sc/source/filter/xml/XMLTextPContext.hxx sc/source/filter/xml/XMLTextPContext.hxx
+index eb759e7..3235159 100644
+--- sc/source/filter/xml/XMLTextPContext.hxx
++++ sc/source/filter/xml/XMLTextPContext.hxx
+@@ -34,6 +34,8 @@
+ #include <xmloff/xmlictxt.hxx>
+ #include <rtl/ustrbuf.hxx>
+ 
++#include "phonetic.hxx"
++
+ class ScXMLImport;
+ class ScXMLTableRowCellContext;
+ 
+@@ -47,9 +49,12 @@ class ScXMLTextPContext : public SvXMLImportContext
+     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,
+@@ -70,6 +75,14 @@ public:
+ 	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
+diff --git sc/source/filter/xml/makefile.mk sc/source/filter/xml/makefile.mk
+index d44da6b..b0f31f8 100644
+--- sc/source/filter/xml/makefile.mk
++++ sc/source/filter/xml/makefile.mk
+@@ -73,6 +73,7 @@ CXXFILES = \
+ 		xmlannoi.cxx \
+ 		xmlsceni.cxx \
+ 		xmlcvali.cxx \
++		xmlrubyi.cxx \
+ 		XMLTableMasterPageExport.cxx \
+ 		xmllabri.cxx \
+ 		XMLTableHeaderFooterContext.cxx \
+@@ -123,6 +124,7 @@ SLOFILES =  \
+ 		$(SLO)$/xmlannoi.obj \
+ 		$(SLO)$/xmlsceni.obj \
+ 		$(SLO)$/xmlcvali.obj \
++		$(SLO)$/xmlrubyi.obj \
+ 		$(SLO)$/XMLTableMasterPageExport.obj \
+ 		$(SLO)$/xmllabri.obj \
+ 		$(SLO)$/XMLTableHeaderFooterContext.obj \
+diff --git sc/source/filter/xml/xmlcelli.cxx sc/source/filter/xml/xmlcelli.cxx
+index a990e54..7ae6ee0 100644
+--- sc/source/filter/xml/xmlcelli.cxx
++++ sc/source/filter/xml/xmlcelli.cxx
+@@ -38,6 +38,7 @@
+ #include "xmltabi.hxx"
+ #include "xmlstyli.hxx"
+ #include "xmlannoi.hxx"
++#include "xmlrubyi.hxx"
+ #include "global.hxx"
+ #include "document.hxx"
+ #include "cellsuno.hxx"
+@@ -117,6 +118,7 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
+ 	pOUTextValue(NULL),
+ 	pOUTextContent(NULL),
+ 	pOUFormula(NULL),
++    pOUPhoneticText(NULL),
+ 	pContentValidationName(NULL),
+ 	pMyAnnotation(NULL),
+ 	pDetectiveObjVec(NULL),
+@@ -297,6 +299,9 @@ ScXMLTableRowCellContext::~ScXMLTableRowCellContext()
+ 		delete pDetectiveObjVec;
+ 	if (pCellRangeSource)
+ 		delete pCellRangeSource;
++
++    // no need to check for NULL-ness when 'delete'-ing a pointer.
++    delete pOUPhoneticText;
+ }
+ 
+ void ScXMLTableRowCellContext::LockSolarMutex()
+@@ -459,6 +464,12 @@ SvXMLImportContext *ScXMLTableRowCellContext::CreateChildContext( USHORT nPrefix
+ 				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)
+@@ -755,6 +766,81 @@ bool lcl_IsEmptyOrNote( ScDocument* pDoc, const table::CellAddress& rCurrentPos
+     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 ::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 ::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)
+@@ -925,11 +1011,11 @@ void ScXMLTableRowCellContext::EndElement()
+                                                 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 );
+                                                 if ( pNewCell )
+                                                 {
+                                                     ScAddress aScAddress;
+@@ -1016,6 +1102,18 @@ void ScXMLTableRowCellContext::EndElement()
+ 					}
+ 					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.
+@@ -1122,3 +1220,10 @@ void ScXMLTableRowCellContext::EndElement()
+ 	nMergedRows = 1;
+ 	nCellsRepeated = 1;
+ }
++
++void ScXMLTableRowCellContext::SetPhoneticText(const rtl::OUString& rOUPhoneticText)
++{
++    delete pOUPhoneticText;
++    pOUPhoneticText = new ::rtl::OUString(rOUPhoneticText);
++}
++
+diff --git sc/source/filter/xml/xmlcelli.hxx sc/source/filter/xml/xmlcelli.hxx
+index 589077d..192637d 100644
+--- sc/source/filter/xml/xmlcelli.hxx
++++ sc/source/filter/xml/xmlcelli.hxx
+@@ -71,6 +71,7 @@ class ScXMLTableRowCellContext : public SvXMLImportContext
+ 	rtl::OUString* pOUTextContent;
+ 	rtl::OUString* pOUFormula;
+ 	rtl::OUString* pContentValidationName;
++    rtl::OUString* pOUPhoneticText;
+ 	ScMyImportAnnotation*	pMyAnnotation;
+ 	ScMyImpDetectiveObjVec*	pDetectiveObjVec;
+ 	ScMyImpCellRangeSource*	pCellRangeSource;
+@@ -142,6 +143,13 @@ public:
+ 	virtual void EndElement();
+ 
+ 	void AddAnnotation(ScMyImportAnnotation* pValue) { pMyAnnotation = pValue; }
++
++    /**
++     * Set phonetic text. 
++     *  
++     * @param rOUPhoneticText the phonetic text
++     */
++    void SetPhoneticText(const rtl::OUString& rOUPhoneticText);
+ };
+ 
+ #endif
+diff --git sc/source/filter/xml/xmlexprt.cxx sc/source/filter/xml/xmlexprt.cxx
+index 2baaac4..e286f06 100644
+--- sc/source/filter/xml/xmlexprt.cxx
++++ sc/source/filter/xml/xmlexprt.cxx
+@@ -2270,11 +2270,27 @@ sal_Bool ScXMLExport::GetCellText (ScMyCell& rMyCell, const ScAddress& aPos) con
+ //		{
+             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;
+@@ -2418,13 +2434,20 @@ void ScXMLExport::WriteCell (ScMyCell& aCell)
+             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);
+diff --git sc/source/filter/xml/xmlexprt.hxx sc/source/filter/xml/xmlexprt.hxx
+index 03e3469..119c79a 100644
+--- sc/source/filter/xml/xmlexprt.hxx
++++ sc/source/filter/xml/xmlexprt.hxx
+@@ -183,6 +183,12 @@ class ScXMLExport : public SvXMLExport
+ 	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;
+diff --git sc/source/filter/xml/xmlimprt.cxx sc/source/filter/xml/xmlimprt.cxx
+index 6d4bc86..095d7f0 100644
+--- sc/source/filter/xml/xmlimprt.cxx
++++ sc/source/filter/xml/xmlimprt.cxx
+@@ -415,7 +415,28 @@ static __FAR_DATA SvXMLTokenMapEntry aTableRowCellTokenMap[] =
+ 	{ XML_NAMESPACE_OFFICE,	XML_ANNOTATION, 		XML_TOK_TABLE_ROW_CELL_ANNOTATION			},
+ 	{ XML_NAMESPACE_TABLE,	XML_DETECTIVE,			XML_TOK_TABLE_ROW_CELL_DETECTIVE			},
+ 	{ XML_NAMESPACE_TABLE,	XML_CELL_RANGE_SOURCE,	XML_TOK_TABLE_ROW_CELL_CELL_RANGE_SOURCE	},
+-	XML_TOKEN_MAP_END
++    { XML_NAMESPACE_TEXT,   XML_RUBY,               XML_TOK_TABLE_ROW_CELL_RUBY                 },
++    XML_TOKEN_MAP_END
++};
++
++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
++};
++
++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
++};
++
++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
+ };
+ 
+ static __FAR_DATA SvXMLTokenMapEntry aTableRowCellAttrTokenMap[] =
+@@ -1097,6 +1118,27 @@ const SvXMLTokenMap& ScXMLImport::GetTableRowCellElemTokenMap()
+ 	return *pTableRowCellElemTokenMap;
+ }
+ 
++const SvXMLTokenMap& ScXMLImport::GetTableRowCellElemTextTokenMap()
++{
++    if( !pTableRowCellElemTextTokenMap )
++        pTableRowCellElemTextTokenMap = new SvXMLTokenMap( aTableRowCellTextTokenMap );
++    return *pTableRowCellElemTextTokenMap;
++}
++
++const SvXMLTokenMap& ScXMLImport::GetTableRowCellElemTextRubyTokenMap()
++{
++    if( !pTableRowCellElemTextRubyTokenMap )
++        pTableRowCellElemTextRubyTokenMap = new SvXMLTokenMap( aTableRowCellTextRubyTokenMap );
++    return *pTableRowCellElemTextRubyTokenMap;
++}
++
++const SvXMLTokenMap& ScXMLImport::GetTableRowCellElemTextRubyAttrTokenMap()
++{
++    if( !pTableRowCellElemTextRubyAttrTokenMap )
++        pTableRowCellElemTextRubyAttrTokenMap = new SvXMLTokenMap( aTableRowCellTextRubyAttrTokenMap );
++    return *pTableRowCellElemTextRubyAttrTokenMap;
++}
++
+ const SvXMLTokenMap& ScXMLImport::GetTableRowCellAttrTokenMap()
+ {
+ 	if( !pTableRowCellAttrTokenMap )
+@@ -1464,6 +1506,9 @@ ScXMLImport::ScXMLImport(
+ 	pTableRowElemTokenMap( 0 ),
+ 	pTableRowAttrTokenMap( 0 ),
+ 	pTableRowCellElemTokenMap( 0 ),
++    pTableRowCellElemTextTokenMap( 0 ),
++    pTableRowCellElemTextRubyTokenMap( 0 ),
++    pTableRowCellElemTextRubyAttrTokenMap( 0 ),
+ 	pTableRowCellAttrTokenMap( 0 ),
+ 	pTableAnnotationAttrTokenMap( 0 ),
+ 	pDetectiveElemTokenMap( 0 ),
+@@ -1590,6 +1635,9 @@ ScXMLImport::~ScXMLImport() throw()
+ 	delete pTableRowElemTokenMap;
+ 	delete pTableRowAttrTokenMap;
+ 	delete pTableRowCellElemTokenMap;
++    delete pTableRowCellElemTextTokenMap;
++    delete pTableRowCellElemTextRubyTokenMap;
++    delete pTableRowCellElemTextRubyAttrTokenMap;
+ 	delete pTableRowCellAttrTokenMap;
+ 	delete pTableAnnotationAttrTokenMap;
+ 	delete pDetectiveElemTokenMap;
+diff --git sc/source/filter/xml/xmlimprt.hxx sc/source/filter/xml/xmlimprt.hxx
+index be0bc22..f9bdcf1 100644
+--- sc/source/filter/xml/xmlimprt.hxx
++++ sc/source/filter/xml/xmlimprt.hxx
+@@ -248,7 +248,25 @@ enum ScXMLTableRowCellTokens
+ 	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
+@@ -690,6 +708,9 @@ class ScXMLImport: public SvXMLImport
+ 	SvXMLTokenMap			*pTableRowElemTokenMap;
+ 	SvXMLTokenMap			*pTableRowAttrTokenMap;
+ 	SvXMLTokenMap			*pTableRowCellElemTokenMap;
++    SvXMLTokenMap           *pTableRowCellElemTextTokenMap;
++    SvXMLTokenMap           *pTableRowCellElemTextRubyTokenMap;
++    SvXMLTokenMap           *pTableRowCellElemTextRubyAttrTokenMap;
+ 	SvXMLTokenMap			*pTableRowCellAttrTokenMap;
+ 	SvXMLTokenMap			*pTableAnnotationAttrTokenMap;
+ 	SvXMLTokenMap			*pDetectiveElemTokenMap;
+@@ -851,6 +872,9 @@ public:
+ 	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();
+diff --git sc/source/filter/xml/xmlrubyi.cxx sc/source/filter/xml/xmlrubyi.cxx
+new file mode 100644
+index 0000000..98414d5
+--- /dev/null
++++ sc/source/filter/xml/xmlrubyi.cxx
+@@ -0,0 +1,207 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: global.hxx,v $
++ * $Revision: 1.53 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_sc.hxx"
++
++
++
++// INCLUDE ---------------------------------------------------------------
++
++#ifndef _SC_XMLRUBYI_HXX
++#include "xmlrubyi.hxx"
++#endif
++#ifndef SC_XMLIMPRT_HXX
++#include "xmlimprt.hxx"
++#endif
++#ifndef SC_XMLCELLI_HXX
++#include "xmlcelli.hxx"
++#endif
++#ifndef _SC_XMLTEXTPCONTEXT_HXX
++#include "XMLTextPContext.hxx"
++#endif
++#ifndef _XMLSTYLI_HXX
++#include "xmlstyli.hxx"
++#endif
++
++#ifndef _XMLOFF_XMLNMSPE_HXX
++#include <xmloff/xmlnmspe.hxx>
++#endif
++#ifndef _XMLOFF_XMLTOKEN_HXX
++#include <xmloff/xmltoken.hxx>
++#endif
++#ifndef _XMLOFF_NMSPMAP_HXX
++#include <xmloff/nmspmap.hxx>
++#endif
++#ifndef _TOOLS_DEBUG_HXX
++#include <tools/debug.hxx>
++#endif
++#ifndef _COM_SUN_STAR_TEXT_XTEXT_HPP_
++#include <com/sun/star/text/XText.hpp>
++#endif
++
++using namespace com::sun::star;
++using namespace xmloff::token;
++
++ScXMLRubyContext::ScXMLRubyContext( ScXMLImport& rImport,
++									  USHORT nPrfx,
++									  const ::rtl::OUString& rLName,
++									  const ::com::sun::star::uno::Reference<
++									  ::com::sun::star::xml::sax::XAttributeList>& xTempAttrList,
++									  ScXMLTextPContext* pTempTextContext) :
++	SvXMLImportContext( rImport, nPrfx, rLName ),
++	pCellContext( NULL ),
++	pTextContext( pTempTextContext )
++{
++	sal_Int16 nAttrCount(xTempAttrList.is() ? xTempAttrList->getLength() : 0);
++	const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableRowCellElemTextRubyAttrTokenMap();
++	for( sal_Int16 i=0; i < nAttrCount; ++i )
++	{
++		const rtl::OUString& sAttrName(xTempAttrList->getNameByIndex( i ));
++		rtl::OUString aLocalName;
++		USHORT nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
++					   sAttrName, &aLocalName ));
++		const rtl::OUString& sValue(xTempAttrList->getValueByIndex( i ));
++
++		switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
++		{
++		case XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_ATTR_STYLE_NAME:
++			sStyleName = sValue;
++			break;
++		}
++	}
++}
++
++ScXMLRubyContext::ScXMLRubyContext( ScXMLImport& rImport,
++									  USHORT nPrfx,
++									  const ::rtl::OUString& rLName,
++									  const ::com::sun::star::uno::Reference<
++									  ::com::sun::star::xml::sax::XAttributeList>& xTempAttrList,
++									  ScXMLTableRowCellContext* pTempContext) :
++	SvXMLImportContext( rImport, nPrfx, rLName ),
++	pCellContext( pTempContext ),
++	pTextContext( NULL )
++{
++	sal_Int16 nAttrCount(xTempAttrList.is() ? xTempAttrList->getLength() : 0);
++	const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableRowCellElemTextRubyAttrTokenMap();
++	for( sal_Int16 i=0; i < nAttrCount; ++i )
++	{
++		const rtl::OUString& sAttrName(xTempAttrList->getNameByIndex( i ));
++		rtl::OUString aLocalName;
++		USHORT nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
++					   sAttrName, &aLocalName ));
++		const rtl::OUString& sValue(xTempAttrList->getValueByIndex( i ));
++
++		switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
++		{
++		case XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_ATTR_STYLE_NAME:
++			sStyleName = sValue;
++			break;
++		}
++	}
++}
++
++SvXMLImportContext *ScXMLRubyContext::CreateChildContext( USHORT nPrefix,
++											const ::rtl::OUString& rLName,
++											const ::com::sun::star::uno::Reference<
++									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
++{
++	SvXMLImportContext *pContext(NULL);
++
++	const SvXMLTokenMap& rTokenMap = GetScImport().GetTableRowCellElemTextRubyTokenMap();
++	switch( rTokenMap.Get( nPrefix, rLName ) )
++	{
++	case XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_BASE:
++		pContext = new ScXMLRubyBaseContext( GetScImport(), nPrefix, rLName, xAttrList, this);
++		break;
++	case XML_TOK_TABLE_ROW_CELL_TEXT_RUBY_TEXT:
++		pContext = new ScXMLRubyTextContext( GetScImport(), nPrefix, rLName, xAttrList, this);
++		break;
++	}
++
++	if( !pContext )
++		pContext = new SvXMLImportContext( GetScImport(), nPrefix, rLName );
++
++	return pContext;
++}
++
++void ScXMLRubyContext::EndElement()
++{
++	if ( pTextContext )
++		pTextContext->AddRubyText( sBaseText.makeStringAndClear(), sRubyText.makeStringAndClear() );
++	else if ( pCellContext )
++		pCellContext->SetPhoneticText( sRubyText.makeStringAndClear() );
++}
++
++void ScXMLRubyContext::AddBaseText( const ::rtl::OUString& rText )
++{
++	sBaseText.append( rText );
++}
++
++void ScXMLRubyContext::AddRubyText( const ::rtl::OUString& rText )
++{
++	sRubyText.append( rText );
++}
++
++ScXMLRubyBaseContext::ScXMLRubyBaseContext( ScXMLImport& rImport,
++									  USHORT nPrfx,
++									  const ::rtl::OUString& rLName,
++									  const ::com::sun::star::uno::Reference<
++									  ::com::sun::star::xml::sax::XAttributeList>& xTempAttrList,
++									  ScXMLRubyContext* pTempRubyContext) :
++	SvXMLImportContext( rImport, nPrfx, rLName ),
++	pRubyContext( pTempRubyContext )
++{
++	// here are no attributes
++}
++
++void ScXMLRubyBaseContext::Characters( const ::rtl::OUString& rChars )
++{
++	pRubyContext->AddBaseText( rChars );
++}
++
++ScXMLRubyTextContext::ScXMLRubyTextContext( ScXMLImport& rImport,
++									  USHORT nPrfx,
++									  const ::rtl::OUString& rLName,
++									  const ::com::sun::star::uno::Reference<
++									  ::com::sun::star::xml::sax::XAttributeList>& xTempAttrList,
++									  ScXMLRubyContext* pTempRubyContext) :
++	SvXMLImportContext( rImport, nPrfx, rLName ),
++	pRubyContext( pTempRubyContext )
++{
++	// here are no attributes
++}
++
++void ScXMLRubyTextContext::Characters( const ::rtl::OUString& rChars )
++{
++	pRubyContext->AddRubyText( rChars );
++}
++
++
+diff --git sc/source/filter/xml/xmlrubyi.hxx sc/source/filter/xml/xmlrubyi.hxx
+new file mode 100644
+index 0000000..5af457e
+--- /dev/null
++++ sc/source/filter/xml/xmlrubyi.hxx
+@@ -0,0 +1,191 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: global.hxx,v $
++ * $Revision: 1.53 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifndef _SC_XMLRUBYI_HXX
++#define _SC_XMLRUBYI_HXX
++
++#ifndef _XMLOFF_XMLICTXT_HXX
++#include <xmloff/xmlictxt.hxx>
++#endif
++#ifndef _RTL_USTRBUF_HXX_
++#include <rtl/ustrbuf.hxx>
++#endif
++
++class ScXMLImport;
++class ScXMLTextPContext;
++class ScXMLTableRowCellContext;
++
++/**
++ * A class for representing Asian phonetic guide information while loading ODF file.
++ */
++class ScXMLRubyContext : public SvXMLImportContext
++{
++	rtl::OUString		sStyleName;
++	rtl::OUStringBuffer	sBaseText;
++	rtl::OUStringBuffer	sRubyText;
++	ScXMLTextPContext*	pTextContext;
++	ScXMLTableRowCellContext*	pCellContext;
++
++	const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
++	ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
++
++public:
++
++	/**
++	 * A constructor of ScXMLRubyContext.
++	 * @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 pContext a pointer of ScXMLTextPContext.
++	 */
++	ScXMLRubyContext( ScXMLImport& rImport, USHORT nPrfx,
++						const ::rtl::OUString& rLName,
++						const ::com::sun::star::uno::Reference<
++										::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++						ScXMLTextPContext* pContext);
++	/**
++	 * A constructor of ScXMLRubyContext.
++	 * @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 pContext a pointer of ScXMLTableRowCellContext.
++	 */
++	ScXMLRubyContext( ScXMLImport& rImport, USHORT nPrfx,
++						const ::rtl::OUString& rLName,
++						const ::com::sun::star::uno::Reference<
++										::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++						ScXMLTableRowCellContext* pContext);
++
++	virtual ~ScXMLRubyContext() {};
++
++	/**
++	 * Create a childs element context. By default, the import's
++	 * CreateContext method is called to create a new default context.
++	 * @return a new default context.
++	 */
++	virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
++									 const ::rtl::OUString& rLocalName,
++									 const ::com::sun::star::uno::Reference<
++									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList );
++	/**
++	 * EndElement is called before a context will be destructed, but
++	 * after a elements context has been parsed. It may be used for actions
++	 * that require virtual methods. The default is to do nothing.
++	 */
++	virtual void EndElement();
++
++	/**
++	 * Adds string into cell string as base string of phonetic infrmation
++	 * @param rText the base string.
++	 */
++	void AddBaseText(const ::rtl::OUString& rText);
++	/**
++	 * Adds string into cell string as phonetic text
++	 * @param rText the phonetic text.
++	 */
++	void AddRubyText(const ::rtl::OUString& rText);
++};
++
++/**
++ * A class for representing base text of phonetic guide information while loading ODF file.
++ */
++class ScXMLRubyBaseContext : public SvXMLImportContext
++{
++	ScXMLRubyContext*	pRubyContext;
++
++	const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
++	ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
++
++public:
++
++	/**
++	 * A constructor of ScXMLRubyBaseContext.
++	 * @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 pContext a pointer of ScXMLRubyContext.
++	 */
++	ScXMLRubyBaseContext( ScXMLImport& rImport, USHORT nPrfx,
++						const ::rtl::OUString& rLName,
++						const ::com::sun::star::uno::Reference<
++										::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++						ScXMLRubyContext* pContext);
++
++	virtual ~ScXMLRubyBaseContext() {};
++
++	/**
++	 * This method is called for all characters that are contained in the
++	 * current element. The default is to ignore them.
++	 * @param rChars the character reference
++	 */ 
++	virtual void Characters( const ::rtl::OUString& rChars );
++};
++
++
++/**
++ * A class for representing phonetic text of phonetic guide information while loading ODF file.
++ */
++class ScXMLRubyTextContext : public SvXMLImportContext
++{
++	ScXMLRubyContext*	pRubyContext;
++
++	const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
++	ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
++
++public:
++
++	/**
++	 * A constructor of ScXMLRubyTextContext.
++	 * @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 pContext a pointer of ScXMLRubyContext.
++	 */
++	ScXMLRubyTextContext( ScXMLImport& rImport, USHORT nPrfx,
++						const ::rtl::OUString& rLName,
++						const ::com::sun::star::uno::Reference<
++										::com::sun::star::xml::sax::XAttributeList>& xAttrList,
++						ScXMLRubyContext* pContext);
++
++	virtual ~ScXMLRubyTextContext() {};
++
++	/**
++	 * This method is called for all characters that are contained in the
++	 * current element. The default is to ignore them.
++	 * @param rChars the character reference
++	 */ 
++	virtual void Characters( const ::rtl::OUString& rChars );
++};
++
++#endif
+diff --git sc/source/filter/xml/xmlstyle.cxx sc/source/filter/xml/xmlstyle.cxx
+index 863e82c..56e92b8 100644
+--- sc/source/filter/xml/xmlstyle.cxx
++++ sc/source/filter/xml/xmlstyle.cxx
+@@ -140,6 +140,7 @@ const XMLPropertyMapEntry aXMLScRowStylesImportProperties[] =
+     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()
+ };
+ 
+diff --git sc/source/filter/xml/xmlstyli.cxx sc/source/filter/xml/xmlstyli.cxx
+index 9624740..87584b1 100644
+--- sc/source/filter/xml/xmlstyli.cxx
++++ sc/source/filter/xml/xmlstyli.cxx
+@@ -64,8 +64,9 @@
+ #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;
+@@ -695,22 +696,30 @@ SvXMLStyleContext *XMLTableStylesContext::CreateStyleStyleChildContext(
+ 		sal_uInt16 nFamily, sal_uInt16 nPrefix, const OUString& rLocalName,
+ 		const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+ {
+-	SvXMLStyleContext *pStyle(SvXMLStylesContext::CreateStyleStyleChildContext( nFamily, nPrefix,
+-															rLocalName,
+-															xAttrList ));
+-	if (!pStyle)
+-	{
+-		switch( nFamily )
+-		{
+-		case XML_STYLE_FAMILY_TABLE_CELL:
+-		case XML_STYLE_FAMILY_TABLE_COLUMN:
+-		case XML_STYLE_FAMILY_TABLE_ROW:
+-		case XML_STYLE_FAMILY_TABLE_TABLE:
+-			pStyle = new XMLTableStyleContext( GetScImport(), nPrefix, rLocalName,
+-			   								xAttrList, *this, nFamily );
+-			break;
+-		}
+-	}
++    SvXMLStyleContext *pStyle(NULL);
++    if ( nFamily == XML_STYLE_FAMILY_TEXT_RUBY )
++    {
++        pStyle = new XMLRubyStyleContext ( GetScImport(), nPrefix, rLocalName,
++                                           xAttrList, *this, nFamily );
++    }
++    else 
++    {
++        pStyle = SvXMLStylesContext::CreateStyleStyleChildContext( 
++            nFamily, nPrefix, rLocalName, xAttrList );
++        if (!pStyle)
++        {
++            switch( nFamily )
++            {
++                case XML_STYLE_FAMILY_TABLE_CELL:
++                case XML_STYLE_FAMILY_TABLE_COLUMN:
++                case XML_STYLE_FAMILY_TABLE_ROW:
++                case XML_STYLE_FAMILY_TABLE_TABLE:
++                    pStyle = new XMLTableStyleContext( GetScImport(), nPrefix, rLocalName,
++                                                       xAttrList, *this, nFamily );
++                    break;
++            }
++        }
++    }
+ 
+ 	return pStyle;
+ }
+@@ -1081,3 +1090,102 @@ void ScMasterPageContext::Finish( sal_Bool bOverwrite )
+ 	if (!bContainsRightHeader)
+ 		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);
++        }
++    }
++}
++
+diff --git sc/source/filter/xml/xmlstyli.hxx sc/source/filter/xml/xmlstyli.hxx
+index 237e8e3..ead1581 100644
+--- sc/source/filter/xml/xmlstyli.hxx
++++ sc/source/filter/xml/xmlstyli.hxx
+@@ -258,6 +258,59 @@ public:
+ 	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; }
+ } } }
+diff --git sc/source/ui/src/scfuncs.src sc/source/ui/src/scfuncs.src
+index 27e6868..fd230d3 100644
+--- sc/source/ui/src/scfuncs.src
++++ sc/source/ui/src/scfuncs.src
+@@ -7884,6 +7884,33 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2
+             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
+ 	{
+diff --git sc/source/ui/unoobj/cellsuno.cxx sc/source/ui/unoobj/cellsuno.cxx
+index 7c0e769..d3e5576 100644
+--- sc/source/ui/unoobj/cellsuno.cxx
++++ sc/source/ui/unoobj/cellsuno.cxx
+@@ -6235,6 +6235,32 @@ String ScCellObj::GetOutputString_Impl(ScDocument* pDoc, const ScAddress& aCellP
+ 	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();
+diff --git sc/util/hidother.src sc/util/hidother.src
+index 9d7ec65..3a9cbf7 100644
+--- sc/util/hidother.src
++++ sc/util/hidother.src
+@@ -389,6 +389,7 @@ hidspecial HID_FUNC_UNICODE         { HelpID = HID_FUNC_UNICODE; };
+ hidspecial HID_FUNC_UNICHAR         { HelpID = HID_FUNC_UNICHAR; };
+ hidspecial HID_FUNC_EUROCONVERT     { HelpID = HID_FUNC_EUROCONVERT; };
+ hidspecial HID_FUNC_NUMBERVALUE     { HelpID = HID_FUNC_NUMBERVALUE; };
++hidspecial HID_FUNC_PHONETIC        { HelpID = HID_FUNC_PHONETIC; };
+ 
+ // ... and from Analysis Addin
+ 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]