diff options
author | Niklas Nebel <nn@openoffice.org> | 2001-11-23 17:57:36 +0000 |
---|---|---|
committer | Niklas Nebel <nn@openoffice.org> | 2001-11-23 17:57:36 +0000 |
commit | 9cc24c70262d39fbc8e01a0169490d9a2667421a (patch) | |
tree | 7d620702ed61c0a76be6b58a5f96264f1b385342 | |
parent | 610a2cd97bb7f31296b5de93a9a11a0e91054e80 (diff) |
#93768# support for number:embedded-text
-rw-r--r-- | xmloff/dtd/datastyl.mod | 7 | ||||
-rw-r--r-- | xmloff/source/style/xmlnumfe.cxx | 119 | ||||
-rw-r--r-- | xmloff/source/style/xmlnumfi.cxx | 220 |
3 files changed, 314 insertions, 32 deletions
diff --git a/xmloff/dtd/datastyl.mod b/xmloff/dtd/datastyl.mod index 02318a918216..80edbe78c197 100644 --- a/xmloff/dtd/datastyl.mod +++ b/xmloff/dtd/datastyl.mod @@ -1,6 +1,6 @@ <!-- - $Id: datastyl.mod,v 1.8 2001-07-24 15:01:42 dvo Exp $ + $Id: datastyl.mod,v 1.9 2001-11-23 18:57:36 nn Exp $ The Contents of this file are made available subject to the terms of either of the following licenses @@ -58,10 +58,13 @@ <!ENTITY % any-number "( number:number | number:scientific-number | number:fraction )"> <!ENTITY % number-style-content "( (number:text,(%any-number;,number:text?)?) | (%any-number;,number:text?) )"> <!ELEMENT number:number-style ( style:properties?, %number-style-content;, style:map* )> -<!ELEMENT number:number EMPTY> +<!ELEMENT number:number ( number:embedded-text* )> <!ELEMENT number:scientific-number EMPTY> <!ELEMENT number:fraction EMPTY> +<!ELEMENT number:embedded-text (#PCDATA)> +<!ATTLIST number:embedded-text number:position %integer; #REQUIRED> + <!ENTITY % currency-symbol-and-text "number:currency-symbol,number:text?"> <!ENTITY % number-and-text "number:number,number:text?"> <!ENTITY % currency-symbol-and-number "((%number-and-text;),(%currency-symbol-and-text;)?) | ((%currency-symbol-and-text;),(%number-and-text;)?)"> diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx index f3bc54cac940..545853623064 100644 --- a/xmloff/source/style/xmlnumfe.cxx +++ b/xmloff/source/style/xmlnumfe.cxx @@ -2,9 +2,9 @@ * * $RCSfile: xmlnumfe.cxx,v $ * - * $Revision: 1.25 $ + * $Revision: 1.26 $ * - * last change: $Author: nn $ $Date: 2001-10-25 17:27:23 $ + * last change: $Author: nn $ $Date: 2001-11-23 18:55:46 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -166,6 +166,25 @@ public: //------------------------------------------------------------------------- +struct SvXMLEmbeddedTextEntry +{ + sal_uInt16 nSourcePos; // position in NumberFormat (to skip later) + sal_Int32 nFormatPos; // resulting position in embedded-text element + rtl::OUString aText; + + SvXMLEmbeddedTextEntry( sal_uInt16 nSP, sal_Int32 nFP, const rtl::OUString& rT ) : + nSourcePos(nSP), nFormatPos(nFP), aText(rT) {} +}; + +typedef SvXMLEmbeddedTextEntry* SvXMLEmbeddedTextEntryPtr; +SV_DECL_PTRARR_DEL( SvXMLEmbeddedTextEntryArr, SvXMLEmbeddedTextEntryPtr, 4, 4 ); + +//------------------------------------------------------------------------- + +SV_IMPL_PTRARR( SvXMLEmbeddedTextEntryArr, SvXMLEmbeddedTextEntryPtr ); + +//------------------------------------------------------------------------- + // //! SvXMLNumUsedList_Impl should be optimized! // @@ -612,7 +631,8 @@ void SvXMLNumFmtExport::WriteAMPMElement_Impl() void SvXMLNumFmtExport::WriteNumberElement_Impl( sal_Int32 nDecimals, sal_Int32 nInteger, - const OUString& rDashStr, sal_Bool bGrouping ) + const OUString& rDashStr, sal_Bool bGrouping, + const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries ) { FinishTextElement_Impl(); @@ -644,7 +664,24 @@ void SvXMLNumFmtExport::WriteNumberElement_Impl( } SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_NUMBER, - sal_True, sal_False ); + sal_True, sal_True ); + + // number:embedded-text as child elements + + sal_uInt16 nEntryCount = rEmbeddedEntries.Count(); + for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++) + { + SvXMLEmbeddedTextEntry* pObj = rEmbeddedEntries[nEntry]; + + // position attribute + rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_POSITION, + OUString::valueOf( pObj->nFormatPos ) ); + SvXMLElementExport aChildElem( rExport, XML_NAMESPACE_NUMBER, XML_EMBEDDED_TEXT, + sal_True, sal_False ); + + // text as element content + rExport.Characters( pObj->aText ); + } } void SvXMLNumFmtExport::WriteScientificElement_Impl( @@ -977,6 +1014,16 @@ OUString lcl_GetDefaultCalendar( SvNumberFormatter* pFormatter, LanguageType nLa //------------------------------------------------------------------------- +sal_Bool lcl_IsInEmbedded( const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries, sal_uInt16 nPos ) +{ + sal_uInt16 nCount = rEmbeddedEntries.Count(); + for (sal_uInt16 i=0; i<nCount; i++) + if ( rEmbeddedEntries[i]->nSourcePos == nPos ) + return sal_True; + + return sal_False; // not found +} + // // export one part (condition) // @@ -1139,10 +1186,11 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt // format elements // + SvXMLEmbeddedTextEntryArr aEmbeddedEntries(0); if ( eBuiltIn == NF_NUMBER_STANDARD ) { // default number format contains just one number element - WriteNumberElement_Impl( -1, 1, OUString(), sal_False ); + WriteNumberElement_Impl( -1, 1, OUString(), sal_False, aEmbeddedEntries ); bAnyContent = sal_True; } else if ( eBuiltIn == NF_BOOLEAN ) @@ -1158,7 +1206,9 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt sal_Bool bDecDashes = sal_False; sal_Bool bExpFound = sal_False; sal_Bool bCurrFound = sal_False; + sal_Bool bInInteger = sal_True; sal_Int32 nExpDigits = 0; + sal_Int32 nIntegerSymbols = 0; // for embedded-text, including "#" OUString sCurrExt; OUString aCalendar; sal_uInt16 nPos = 0; @@ -1178,9 +1228,15 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt nExpDigits += pElemStr->Len(); else if ( !bDecDashes && pElemStr && pElemStr->GetChar(0) == '-' ) bDecDashes = TRUE; + if ( bInInteger && pElemStr ) + nIntegerSymbols += pElemStr->Len(); + break; + case XMLNUM_SYMBOLTYPE_DECSEP: + bInInteger = sal_False; break; case XMLNUM_SYMBOLTYPE_EXP: - bExpFound = TRUE; // following digits are exponent digits + bExpFound = sal_True; // following digits are exponent digits + bInInteger = sal_False; break; case XMLNUM_SYMBOLTYPE_CURRENCY: bCurrFound = TRUE; @@ -1203,7 +1259,47 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt ++nPos; } - // second loop to write elements + // collect strings for embedded-text (must be known before number element is written) + + sal_Bool bAllowEmbedded = ( nFmtType == 0 || nFmtType == NUMBERFORMAT_NUMBER || + nFmtType == NUMBERFORMAT_CURRENCY || + nFmtType == NUMBERFORMAT_PERCENT ); + if ( bAllowEmbedded ) + { + sal_Int32 nDigitsPassed = 0; + nPos = 0; + bEnd = sal_False; + while (!bEnd) + { + short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False ); + const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False ); + + switch ( nElemType ) + { + case 0: + bEnd = sal_True; // end of format reached + break; + case XMLNUM_SYMBOLTYPE_DIGIT: + if ( pElemStr ) + nDigitsPassed += pElemStr->Len(); + break; + case XMLNUM_SYMBOLTYPE_STRING: + if ( nDigitsPassed > 0 && nDigitsPassed < nIntegerSymbols && pElemStr ) + { + // text within the integer part of a number:number element + + sal_Int32 nEmbedPos = nIntegerSymbols - nDigitsPassed; + + SvXMLEmbeddedTextEntry* pObj = new SvXMLEmbeddedTextEntry( nPos, nEmbedPos, *pElemStr ); + aEmbeddedEntries.Insert( pObj, aEmbeddedEntries.Count() ); + } + break; + } + ++nPos; + } + } + + // final loop to write elements sal_Bool bNumWritten = sal_False; sal_Bool bCurrencyWritten = sal_False; @@ -1232,6 +1328,11 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt // as text element //! difference between '.' and ',' is lost here } + else if ( lcl_IsInEmbedded( aEmbeddedEntries, nPos ) ) + { + // text is written as embedded-text child of the number, + // don't create a text element + } else if ( nFmtType == NUMBERFORMAT_CURRENCY && !bCurrFound && !bCurrencyWritten ) { // automatic currency symbol is implemented as part of @@ -1245,7 +1346,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt } break; case NF_KEY_GENERAL : - WriteNumberElement_Impl( -1, 1, OUString(), sal_False ); + WriteNumberElement_Impl( -1, 1, OUString(), sal_False, aEmbeddedEntries ); break; case NF_KEY_CCC: if (pElemStr) @@ -1312,7 +1413,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt if ( bDecDashes && nPrecision > 0 ) sDashStr.Fill( nPrecision, '-' ); - WriteNumberElement_Impl( nDecimals, nInteger, sDashStr, bThousand ); + WriteNumberElement_Impl( nDecimals, nInteger, sDashStr, bThousand, aEmbeddedEntries ); bAnyContent = sal_True; } break; diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx index dfa7eb03eb25..abd179493c45 100644 --- a/xmloff/source/style/xmlnumfi.cxx +++ b/xmloff/source/style/xmlnumfi.cxx @@ -2,9 +2,9 @@ * * $RCSfile: xmlnumfi.cxx,v $ * - * $Revision: 1.19 $ + * $Revision: 1.20 $ * - * last change: $Author: nn $ $Date: 2001-11-05 14:42:29 $ + * last change: $Author: nn $ $Date: 2001-11-23 18:55:46 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -101,6 +101,22 @@ struct SvXMLNumFmtEntry typedef SvXMLNumFmtEntry* SvXMLNumFmtEntryPtr; SV_DECL_PTRARR_DEL( SvXMLNumFmtEntryArr, SvXMLNumFmtEntryPtr, 4, 4 ); +struct SvXMLEmbeddedElement +{ + sal_Int32 nFormatPos; + rtl::OUString aText; + + SvXMLEmbeddedElement( sal_Int32 nFP, const rtl::OUString& rT ) : + nFormatPos(nFP), aText(rT) {} + + // comparison operators for PTRARR sorting - sorted by position + BOOL operator ==( const SvXMLEmbeddedElement& r ) const { return nFormatPos == r.nFormatPos; } + BOOL operator < ( const SvXMLEmbeddedElement& r ) const { return nFormatPos < r.nFormatPos; } +}; + +typedef SvXMLEmbeddedElement* SvXMLEmbeddedElementPtr; +SV_DECL_PTRARR_SORT_DEL( SvXMLEmbeddedElementArr, SvXMLEmbeddedElementPtr, 0, 4 ); + //------------------------------------------------------------------------- class SvXMLNumImpData @@ -139,6 +155,7 @@ struct SvXMLNumberInfo sal_Int32 nDenomDigits; sal_Bool bGrouping; sal_Bool bDecReplace; + SvXMLEmbeddedElementArr aEmbeddedElements; SvXMLNumberInfo() { @@ -172,6 +189,31 @@ public: ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); virtual void Characters( const rtl::OUString& rChars ); virtual void EndElement(); + + void AddEmbeddedElement( sal_Int32 nFormatPos, const rtl::OUString& rContent ); +}; + + +class SvXMLNumFmtEmbeddedTextContext : public SvXMLImportContext +{ + SvXMLNumFmtElementContext& rParent; + rtl::OUStringBuffer aContent; + sal_Int32 nTextPosition; + +public: + SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport, USHORT nPrfx, + const rtl::OUString& rLName, + SvXMLNumFmtElementContext& rParentContext, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); + virtual ~SvXMLNumFmtEmbeddedTextContext(); + + virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix, + const rtl::OUString& rLocalName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); + virtual void Characters( const rtl::OUString& rChars ); + virtual void EndElement(); }; @@ -402,6 +444,7 @@ static __FAR_DATA SvXMLEnumMapEntry aFormatSourceMap[] = //------------------------------------------------------------------------- SV_IMPL_PTRARR( SvXMLNumFmtEntryArr, SvXMLNumFmtEntryPtr ); +SV_IMPL_OP_PTRARR_SORT( SvXMLEmbeddedElementArr, SvXMLEmbeddedElementPtr ); //------------------------------------------------------------------------- @@ -644,6 +687,59 @@ void SvXMLNumFmtPropContext::EndElement() //------------------------------------------------------------------------- +// +// SvXMLNumFmtEmbeddedTextContext +// + +SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport, + USHORT nPrfx, const rtl::OUString& rLName, + SvXMLNumFmtElementContext& rParentContext, + const uno::Reference<xml::sax::XAttributeList>& xAttrList ) : + SvXMLImportContext( rImport, nPrfx, rLName ), + rParent( rParentContext ), + nTextPosition( 0 ) +{ + sal_Int32 nAttrVal; + + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + OUString sAttrName = xAttrList->getNameByIndex( i ); + OUString sValue = xAttrList->getValueByIndex( i ); + OUString aLocalName; + sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); + if ( nPrefix == XML_NAMESPACE_NUMBER && IsXMLToken( aLocalName, XML_POSITION ) ) + { + if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) ) + nTextPosition = nAttrVal; + } + } +} + +SvXMLNumFmtEmbeddedTextContext::~SvXMLNumFmtEmbeddedTextContext() +{ +} + +SvXMLImportContext* SvXMLNumFmtEmbeddedTextContext::CreateChildContext( + USHORT nPrfx, const rtl::OUString& rLName, + const uno::Reference<xml::sax::XAttributeList>& xAttrList ) +{ + // no elements supported - use default context + return new SvXMLImportContext( GetImport(), nPrfx, rLName ); +} + +void SvXMLNumFmtEmbeddedTextContext::Characters( const rtl::OUString& rChars ) +{ + aContent.append( rChars ); +} + +void SvXMLNumFmtEmbeddedTextContext::EndElement() +{ + rParent.AddEmbeddedElement( nTextPosition, aContent.makeStringAndClear() ); +} + +//------------------------------------------------------------------------- + sal_Bool lcl_ValidChar( sal_Unicode cChar, sal_uInt16 nFormatType ) { // see ImpSvNumberformatScan::Next_Symbol @@ -670,6 +766,26 @@ sal_Bool lcl_ValidChar( sal_Unicode cChar, sal_uInt16 nFormatType ) return sal_False; } +void lcl_EnquoteIfNecessary( rtl::OUStringBuffer& rContent, sal_uInt16 nFormatType ) +{ + if ( ( rContent.getLength() == 1 && + lcl_ValidChar( rContent.charAt(0), nFormatType ) ) || + ( rContent.getLength() == 2 && + lcl_ValidChar( rContent.charAt(0), nFormatType ) && + rContent.charAt(1) == ' ' ) ) + { + // don't quote single separator characters like space or percent, + // or separator characters followed by space (used in date formats) + } + else + { + // quote string literals + //! escape quotes in string + rContent.insert( 0, (sal_Unicode) '"' ); + rContent.append( (sal_Unicode) '"' ); + } +} + // // SvXMLNumFmtElementContext // @@ -767,8 +883,15 @@ SvXMLImportContext* SvXMLNumFmtElementContext::CreateChildContext( USHORT nPrfx, const rtl::OUString& rLName, const uno::Reference<xml::sax::XAttributeList>& xAttrList ) { - // no elements supported - use default context - return new SvXMLImportContext( GetImport(), nPrfx, rLName ); + // only number:number supports number:embedded-text child element + + if ( nType == XML_TOK_STYLE_NUMBER && + nPrfx == XML_NAMESPACE_NUMBER && IsXMLToken( rLName, XML_EMBEDDED_TEXT ) ) + { + return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nPrfx, rLName, *this, xAttrList ); + } + else + return new SvXMLImportContext( GetImport(), nPrfx, rLName ); } void SvXMLNumFmtElementContext::Characters( const rtl::OUString& rChars ) @@ -776,6 +899,30 @@ void SvXMLNumFmtElementContext::Characters( const rtl::OUString& rChars ) aContent.append( rChars ); } +void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos, const rtl::OUString& rContent ) +{ + if ( rContent.getLength() ) + { + SvXMLEmbeddedElement* pObj = new SvXMLEmbeddedElement( nFormatPos, rContent ); + if ( !aNumInfo.aEmbeddedElements.Insert( pObj ) ) + { + // there's already an element at this position - append text to existing element + + delete pObj; + USHORT nElementCount = aNumInfo.aEmbeddedElements.Count(); + for (USHORT i=0; i<nElementCount; i++) + { + pObj = aNumInfo.aEmbeddedElements[i]; + if ( pObj->nFormatPos == nFormatPos ) + { + pObj->aText += rContent; + break; + } + } + } + } +} + void SvXMLNumFmtElementContext::EndElement() { sal_Bool bEffLong = bLong; @@ -799,22 +946,7 @@ void SvXMLNumFmtElementContext::EndElement() } if ( aContent.getLength() ) { - if ( ( aContent.getLength() == 1 && - lcl_ValidChar( aContent.charAt(0), rParent.GetType() ) ) || - ( aContent.getLength() == 2 && - lcl_ValidChar( aContent.charAt(0), rParent.GetType() ) && - aContent.charAt(1) == ' ' ) ) - { - // don't quote single separator characters like space or percent, - // or separator characters followed by space (used in date formats) - } - else - { - // quote string literals - //! escape quotes in string - aContent.insert( 0, (sal_Unicode) '"' ); - aContent.append( (sal_Unicode) '"' ); - } + lcl_EnquoteIfNecessary( aContent, rParent.GetType() ); rParent.AddToCode( aContent.makeStringAndClear() ); } break; @@ -1462,10 +1594,56 @@ void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo ) if ( rInfo.bDecReplace ) nGenPrec = 0; // generate format without decimals... + sal_Bool bGrouping = rInfo.bGrouping; + USHORT nEmbeddedCount = rInfo.aEmbeddedElements.Count(); + if ( nEmbeddedCount ) + bGrouping = sal_False; // grouping and embedded characters can't be used together + String aNumStr; sal_uInt32 nStdIndex = pFormatter->GetStandardIndex( nFormatLang ); pFormatter->GenerateFormat( aNumStr, nStdIndex, nFormatLang, - rInfo.bGrouping, sal_False, nGenPrec, nLeading ); + bGrouping, sal_False, nGenPrec, nLeading ); + + if ( nEmbeddedCount ) + { + // insert embedded strings into number string + // only the integer part is supported + // nZeroPos is the string position where format position 0 is inserted + + xub_StrLen nZeroPos = aNumStr.Search( pData->GetLocaleData( nFormatLang ).getNumDecimalSep() ); + if ( nZeroPos == STRING_NOTFOUND ) + nZeroPos = aNumStr.Len(); + + // aEmbeddedElements is sorted - last entry has the largest position (leftmost) + const SvXMLEmbeddedElement* pLastObj = rInfo.aEmbeddedElements[nEmbeddedCount - 1]; + sal_Int32 nLastFormatPos = pLastObj->nFormatPos; + if ( nLastFormatPos >= nZeroPos ) + { + // add '#' characters so all embedded texts are really embedded in digits + // (there always has to be a digit before the leftmost embedded text) + + xub_StrLen nAddCount = (xub_StrLen)nLastFormatPos + 1 - nZeroPos; + String aDigitStr; + aDigitStr.Fill( nAddCount, (sal_Unicode)'#' ); + aNumStr.Insert( aDigitStr, 0 ); + nZeroPos += nAddCount; + } + + // aEmbeddedElements is sorted with ascending positions - loop is from right to left + for (USHORT nElement = 0; nElement < nEmbeddedCount; nElement++) + { + const SvXMLEmbeddedElement* pObj = rInfo.aEmbeddedElements[nElement]; + sal_Int32 nFormatPos = pObj->nFormatPos; + sal_Int32 nInsertPos = nZeroPos - nFormatPos; + if ( nFormatPos >= 0 && nInsertPos >= 0 ) + { + rtl::OUStringBuffer aContent( pObj->aText ); + lcl_EnquoteIfNecessary( aContent, nType ); + + aNumStr.Insert( String( aContent.makeStringAndClear() ), (xub_StrLen)nInsertPos ); + } + } + } aFormatCode.append( aNumStr ); |