summaryrefslogtreecommitdiff
path: root/sw/source/filter/rtf/rtffld.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/rtf/rtffld.cxx')
-rw-r--r--sw/source/filter/rtf/rtffld.cxx1231
1 files changed, 1231 insertions, 0 deletions
diff --git a/sw/source/filter/rtf/rtffld.cxx b/sw/source/filter/rtf/rtffld.cxx
new file mode 100644
index 000000000000..90bb9e668261
--- /dev/null
+++ b/sw/source/filter/rtf/rtffld.cxx
@@ -0,0 +1,1231 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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_sw.hxx"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+
+#include <ctype.h>
+#include <hintids.hxx>
+
+#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
+#include <com/sun/star/i18n/ScriptType.hdl>
+#endif
+#ifndef _GRAPH_HXX //autogen
+#include <vcl/graph.hxx>
+#endif
+#include <svl/urihelper.hxx>
+#include <svtools/rtftoken.h>
+#include <svl/zforlist.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <fmtfld.hxx>
+#include <fmtinfmt.hxx>
+#include <swtypes.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <shellio.hxx>
+#include <fldbas.hxx>
+#include <swparrtf.hxx>
+#include <txatbase.hxx>
+#include <dbfld.hxx>
+#include <usrfld.hxx>
+#include <docufld.hxx>
+#include <flddat.hxx>
+#include <charfmt.hxx>
+#ifndef _fmtruby_HXX
+#include <fmtruby.hxx>
+#endif
+#include <breakit.hxx>
+#include <reffld.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <editeng/charhiddenitem.hxx>
+
+
+// bestimme, ob es sich um ein IMPORT/TOC - Feld handelt.
+// return: 0 - weder noch,
+// 1 - TOC
+// 2 - IMPORT
+// 3 - INDEX
+enum RTF_FLD_TYPES {
+ RTFFLD_UNKNOWN = 0,
+ RTFFLD_TOC,
+ RTFFLD_IMPORT,
+ RTFFLD_INDEX,
+ RTFFLD_SYMBOL,
+ RTFFLD_PAGE,
+ RTFFLD_NUMPAGES,
+ RTFFLD_DATE,
+ RTFFLD_TIME,
+ RTFFLD_DATA,
+ RTFFLD_MERGEFLD,
+ RTFFLD_HYPERLINK,
+ RTFFLD_REF,
+ RTFFLD_PAGEREF,
+ RTFFLD_EQ,
+ RTFFLD_INCLUDETEXT
+};
+
+static RTF_FLD_TYPES _WhichFld( String& rName, String& rNext )
+{
+ // Strings sind PascalStrings; Laenge steht an 1. Stellen, dadurch wird
+ // sich der Aufruf von strlen erspart!!!
+ sal_Char __READONLY_DATA sTOC[]= "\x03""toc";
+ sal_Char __READONLY_DATA sIMPORT[]= "\x06""import";
+ sal_Char __READONLY_DATA sINDEX[]= "\x05""index";
+ sal_Char __READONLY_DATA sSYMBOL[]= "\x06""symbol";
+ sal_Char __READONLY_DATA sPAGE[]= "\x04""page";
+ sal_Char __READONLY_DATA sNUMPAGES[]= "\x08""numpages";
+ sal_Char __READONLY_DATA sDATE[]= "\x04""date";
+ sal_Char __READONLY_DATA sTIME[]= "\x04""time";
+ sal_Char __READONLY_DATA sDATA[]= "\x04""data";
+ sal_Char __READONLY_DATA sMERGEFLD[]= "\x0A""mergefield";
+ sal_Char __READONLY_DATA sIMPORT2[]= "\x0E""includepicture";
+ sal_Char __READONLY_DATA sHYPERLINK[]= "\x09""hyperlink";
+ sal_Char __READONLY_DATA sREF[]= "\x03""ref";
+ sal_Char __READONLY_DATA sPAGEREF[]= "\x07""pageref";
+ sal_Char __READONLY_DATA sEQ[]= "\x02""eq";
+ sal_Char __READONLY_DATA sINCLUDETEXT[]="\x0B""includetext";
+
+ struct _Dummy_RTF_FLD_TYPES
+ {
+ RTF_FLD_TYPES eFldType;
+ const sal_Char* pFldNm;
+ };
+ __READONLY_DATA _Dummy_RTF_FLD_TYPES aFldNmArr[RTFFLD_INCLUDETEXT + 1] = {
+ {RTFFLD_TOC, sTOC},
+ {RTFFLD_IMPORT, sIMPORT},
+ {RTFFLD_INDEX, sINDEX},
+ {RTFFLD_SYMBOL, sSYMBOL},
+ {RTFFLD_PAGE, sPAGE},
+ {RTFFLD_NUMPAGES, sNUMPAGES},
+ {RTFFLD_DATE, sDATE},
+ {RTFFLD_TIME, sTIME},
+ {RTFFLD_DATA, sDATA},
+ {RTFFLD_MERGEFLD, sMERGEFLD},
+ {RTFFLD_IMPORT, sIMPORT2},
+ {RTFFLD_HYPERLINK, sHYPERLINK},
+ {RTFFLD_REF, sREF},
+ {RTFFLD_PAGEREF, sPAGEREF},
+ {RTFFLD_EQ, sEQ},
+ {RTFFLD_INCLUDETEXT, sINCLUDETEXT}
+ };
+
+
+ if( !rName.Len() )
+ return RTFFLD_UNKNOWN;
+
+ String sNm( rName );
+ sNm = sNm.EraseLeadingChars().GetToken(0, ' ');
+ ASSERT( sNm.Len(), "Feldname hat keine Laenge!" );
+ if( !sNm.Len() )
+ return RTFFLD_UNKNOWN;
+
+ xub_StrLen nTokenStt = rName.Search( sNm );
+ sNm.ToLowerAscii();
+
+ for (size_t n = 0; n < sizeof(aFldNmArr) / sizeof(aFldNmArr[0]); ++n)
+ {
+ const sal_Char* pCmp = aFldNmArr[n].pFldNm;
+ int nLen = *pCmp++;
+ xub_StrLen nFndPos = sNm.SearchAscii( pCmp );
+ if( STRING_NOTFOUND != nFndPos &&
+ ( !nFndPos || !isalpha(sNm.GetChar( static_cast< xub_StrLen >(nFndPos-1) )) ) &&
+ ( nFndPos+nLen == sNm.Len() || !isalpha(sNm.GetChar( static_cast< xub_StrLen >(nFndPos+nLen) ) ) ) )
+ {
+// rName = sNm.Copy( nFndPos, nLen );
+ rName = rName.Copy( nFndPos, static_cast< xub_StrLen >(nLen) );
+ nFndPos += nTokenStt + static_cast< xub_StrLen >(nLen);
+ while( rNext.GetChar( nFndPos ) == ' ' ) ++nFndPos;
+ rNext.Erase( 0, nFndPos );
+ rNext.EraseTrailingChars();
+ return aFldNmArr[n].eFldType;
+ }
+ }
+ return RTFFLD_UNKNOWN; // nichts gefunden.
+}
+
+static USHORT CheckNumberFmtStr( const String& rNStr )
+{
+ const static sal_Char* aNumberTypeTab[] =
+ {
+ "\x0A""ALPHABETIC", /* CHARS_UPPER_LETTER*/
+ "\x0A""alphabetic", /* CHARS_LOWER_LETTER*/
+ "\x05""ROMAN", /* ROMAN_UPPER */
+ "\x05""roman", /* ROMAN_LOWER */
+ "\x06""ARABIC", /* ARABIC */
+ "\x04""NONE", /* NUMBER_NONE */
+ "\x04""CHAR", /* CHAR_SPECIAL */
+ "\x04""PAGE" /* PAGEDESC */
+ };
+
+ ASSERT(sizeof(aNumberTypeTab) / sizeof(sal_Char *)
+ >= SVX_NUM_PAGEDESC - SVX_NUM_CHARS_UPPER_LETTER, "impossible");
+
+ for (USHORT n = SVX_NUM_CHARS_UPPER_LETTER; n <= SVX_NUM_PAGEDESC; ++n)
+ {
+ const sal_Char* pCmp = aNumberTypeTab[n - SVX_NUM_CHARS_UPPER_LETTER];
+ int nLen = *pCmp++;
+ if( rNStr.EqualsAscii( pCmp, 0, static_cast< xub_StrLen >(nLen) ))
+ return static_cast< USHORT >(2 <= n ? n : (n + SVX_NUM_CHARS_UPPER_LETTER_N));
+ }
+ return SVX_NUM_PAGEDESC; // default-Wert
+}
+
+class RtfFieldSwitch
+{
+ String sParam;
+ xub_StrLen nCurPos;
+public:
+ RtfFieldSwitch( const String& rParam );
+ sal_Unicode GetSwitch( String& rParam );
+
+ BOOL IsAtEnd() const { return nCurPos >= sParam.Len(); }
+ xub_StrLen GetCurPos() const { return nCurPos; }
+ void Erase( xub_StrLen nEndPos ) { sParam.Erase( 0, nEndPos ); }
+ void Insert( const String& rIns ) { sParam.Insert( rIns, 0 ); }
+ const String& GetStr() const { return sParam; }
+};
+
+RtfFieldSwitch::RtfFieldSwitch( const String& rParam )
+ : sParam( rParam ), nCurPos( 0 )
+{
+ sParam.EraseTrailingChars().EraseLeadingChars();
+}
+
+sal_Unicode RtfFieldSwitch::GetSwitch( String& rParam )
+{
+ // beginnt ein Schalter?
+ sal_Unicode c, cKey = 0;
+ if( '\\' == (c = sParam.GetChar( nCurPos )) )
+ {
+ if( '\\' == ( c = sParam.GetChar( ++nCurPos )) )
+ c = sParam.GetChar( ++nCurPos );
+
+ cKey = c;
+
+ while( ++nCurPos < sParam.Len() &&
+ ' ' == ( c = sParam.GetChar( nCurPos )) )
+ ;
+ }
+
+ // dann alles in Hochkommatas oder bis zum naechsten // als
+ // Param returnen
+ USHORT nOffset;
+ if( '"' != c && '\'' != c )
+ c = '\\', nOffset = 0;
+ else
+ nOffset = 1;
+
+ sParam.Erase( 0, nCurPos + nOffset );
+ rParam = sParam.GetToken( 0, c );
+ sParam.Erase( 0, rParam.Len() + nOffset ).EraseLeadingChars();
+ if( '\\' == c )
+ rParam.EraseTrailingChars();
+ nCurPos = 0;
+
+ return cKey;
+}
+
+struct RTF_EquationData
+{
+ String sFontName, sUp, sDown, sText;
+ sal_Int32 nJustificationCode, nFontSize, nUp, nDown, nStyleNo;
+
+ inline RTF_EquationData()
+ : nJustificationCode(0), nFontSize(0), nUp(0), nDown(0),
+ nStyleNo( -1 )
+ {}
+};
+
+xub_StrLen lcl_FindEndBracket( const String& rStr )
+{
+ xub_StrLen nEnd = rStr.Len(), nRet = STRING_NOTFOUND, nPos = 0;
+ int nOpenCnt = 1;
+ sal_Unicode cCh;
+ for( ; nPos < nEnd; ++nPos )
+ if( ')' == (cCh = rStr.GetChar( nPos )) && !--nOpenCnt )
+ {
+ nRet = nPos;
+ break;
+ }
+ else if( '(' == cCh )
+ ++nOpenCnt;
+
+ return nRet;
+}
+
+void lcl_ScanEquationField( const String& rStr, RTF_EquationData& rData,
+ sal_Unicode nSttKey )
+{
+ int nSubSupFlag(0);
+ RtfFieldSwitch aRFS( rStr );
+ while( !aRFS.IsAtEnd() )
+ {
+ String sParam;
+ sal_Unicode cKey = aRFS.GetSwitch( sParam );
+ if( 1 == nSubSupFlag )
+ ++nSubSupFlag;
+ else if( 1 < nSubSupFlag )
+ nSubSupFlag = 0;
+
+ BOOL bCheckBracket = FALSE;
+ switch( cKey )
+ {
+ case 0:
+ switch( nSttKey )
+ {
+ case 'u': rData.sUp += sParam; break;
+ case 'd': rData.sDown += sParam; break;
+ default: rData.sText += sParam; break;
+ }
+ break;
+
+ case '*':
+ if( sParam.Len() )
+ {
+ if( sParam.EqualsIgnoreCaseAscii( "jc", 0, 2 ) )
+ rData.nJustificationCode = sParam.Copy( 2 ).ToInt32();
+ else if( sParam.EqualsIgnoreCaseAscii( "hps", 0, 3 ) )
+ rData.nFontSize= sParam.Copy( 3 ).ToInt32();
+ else if( sParam.EqualsIgnoreCaseAscii( "Font:", 0, 5 ) )
+ rData.sFontName = sParam.Copy( 5 );
+ else if( sParam.EqualsIgnoreCaseAscii( "cs", 0, 2 ) )
+ rData.nStyleNo = sParam.Copy( 2 ).ToInt32();
+ }
+ break;
+ case 's' :
+ ++nSubSupFlag;
+ break;
+
+ case 'u':
+ if( sParam.Len() && 'p' == sParam.GetChar( 0 ) &&
+ 2 == nSubSupFlag )
+ {
+ rData.nUp = sParam.Copy( 1 ).ToInt32();
+ bCheckBracket = TRUE;
+ }
+ break;
+
+ case 'd':
+ if( sParam.Len() && 'o' == sParam.GetChar( 0 ) &&
+ 2 == nSubSupFlag )
+ {
+ rData.nDown = sParam.Copy( 1 ).ToInt32();
+ bCheckBracket = TRUE;
+ }
+ break;
+
+ default:
+ bCheckBracket = TRUE;
+ cKey = 0;
+ break;
+ }
+
+ if( bCheckBracket && sParam.Len() )
+ {
+ xub_StrLen nEnd, nStt = sParam.Search( '(' ),
+ nLen = sParam.Len();
+ if( STRING_NOTFOUND != nStt )
+ {
+ sParam.Erase( 0, nStt + 1 ) += aRFS.GetStr();
+ if( STRING_NOTFOUND !=
+ (nEnd = ::lcl_FindEndBracket( sParam )) )
+ {
+ // end in the added string?
+ if( (nLen - nStt - 1 ) < nEnd )
+ aRFS.Erase( nEnd + 1 - (nLen - nStt - 1));
+ else
+ {
+ // not all handled here, so set new into the RFS
+ aRFS.Insert( sParam.Copy( nEnd + 1,
+ nLen - nStt - nEnd - 2 ));
+ sal_Unicode cCh;
+ if( aRFS.GetStr().Len() &&
+ ( ',' == (cCh = aRFS.GetStr().GetChar(0)) ||
+ ';' == cCh ))
+ aRFS.Erase( 1 );
+ }
+
+ ::lcl_ScanEquationField( sParam.Copy( 0, nEnd ),
+ rData, cKey );
+ }
+ }
+ }
+ }
+}
+
+int SwRTFParser::MakeFieldInst( String& rFieldStr )
+{
+ // sicher den Original-String fuer die FeldNamen (User/Datenbank)
+ String aSaveStr( rFieldStr );
+ SwFieldType * pFldType;
+ int nRet = _WhichFld(rFieldStr, aSaveStr);
+
+ //Strip Mergeformat from fields
+ xub_StrLen nPos=0;
+ while (STRING_NOTFOUND != ( nPos = aSaveStr.SearchAscii("\\*", nPos)))
+ {
+ xub_StrLen nStartDel = nPos;
+ nPos += 2;
+ while (aSaveStr.GetChar(nPos) == ' ')
+ ++nPos;
+ if (aSaveStr.EqualsIgnoreCaseAscii("MERGEFORMAT", nPos, 11))
+ {
+ xub_StrLen nNoDel = (nPos + 11 ) - nStartDel;
+ aSaveStr.Erase(nStartDel, nNoDel);
+ nPos -= (nStartDel - nPos);
+ }
+ }
+
+ nPos = 0;
+ switch (nRet)
+ {
+ case RTFFLD_INCLUDETEXT:
+ break;
+ case RTFFLD_IMPORT:
+ {
+//JP 11.03.96: vertraegt sich nicht so ganz mit Internet!
+// if( STRING_NOTFOUND != ( nPos = aSaveStr.Search( '.' )))
+// aSaveStr.Erase( nPos+4 );
+
+ aSaveStr.EraseLeadingAndTrailingChars();
+ if( aSaveStr.Len() )
+ {
+ sal_Unicode c = aSaveStr.GetChar( 0 );
+ if( '"' == c || '\'' == c )
+ {
+ aSaveStr.Erase( 0, 1 );
+ aSaveStr = aSaveStr.GetToken( 0, c );
+ }
+
+ rFieldStr = URIHelper::SmartRel2Abs(
+ INetURLObject(GetBaseURL()), aSaveStr,
+ URIHelper::GetMaybeFileHdl() );
+ }
+// SkipGroup(); // ueberlese den Rest
+ }
+ break;
+
+ case RTFFLD_NUMPAGES:
+ {
+ SwDocStatField aFld( (SwDocStatFieldType*)pDoc->GetSysFldType( RES_DOCSTATFLD ),
+ DS_PAGE, SVX_NUM_ARABIC );
+ if( STRING_NOTFOUND != ( nPos = aSaveStr.SearchAscii( "\\*" )) )
+ {
+ nPos += 2;
+ while( aSaveStr.GetChar(nPos) == ' ' ) nPos++;
+ aSaveStr.Erase( 0, nPos );
+
+ // steht jetzt geanu auf dem Format-Namen
+ aFld.ChangeFormat( CheckNumberFmtStr( aSaveStr ));
+ }
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0 );
+ SkipGroup();
+ }
+ break;
+
+ case RTFFLD_PAGE:
+ {
+ pFldType = pDoc->GetSysFldType( RES_PAGENUMBERFLD );
+ SwPageNumberField aPF( (SwPageNumberFieldType*)pFldType,
+ PG_RANDOM, SVX_NUM_ARABIC);
+ if( STRING_NOTFOUND != ( nPos = aSaveStr.SearchAscii( "\\*" )) )
+ {
+ nPos += 2;
+ while( aSaveStr.GetChar(nPos) == ' ' ) nPos++;
+ aSaveStr.Erase( 0, nPos );
+
+ // steht jetzt geanu auf dem Format-Namen
+ aPF.ChangeFormat( CheckNumberFmtStr( aSaveStr ));
+ }
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( aPF ), 0 );
+ SkipGroup(); // ueberlese den Rest
+ }
+ break;
+ case RTFFLD_DATE:
+ case RTFFLD_TIME:
+ {
+ if( STRING_NOTFOUND == ( nPos = aSaveStr.SearchAscii( "\\@" )) )
+ {
+ // es fehlt die Format - Angabe: defaulten auf Datum
+ pFldType = pDoc->GetSysFldType( RES_DATETIMEFLD );
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( SwDateTimeField(
+ static_cast<SwDateTimeFieldType*>(pFldType), DATEFLD)), 0);
+ }
+ else
+ {
+ // versuche aus dem Formatstring zu erkennen, ob es ein
+ // Datum oder Zeit oder Datum & Zeit Field ist
+ // nur das Format interressiert
+ aSaveStr.Erase( 0, aSaveStr.Search( '\"' )+1 );
+ // alles hinter dem Format interressiert auch nicht mehr.
+ aSaveStr.Erase( aSaveStr.Search( '\"' ) );
+ aSaveStr.SearchAndReplaceAscii( "AM", aEmptyStr );
+ aSaveStr.SearchAndReplaceAscii( "PM", aEmptyStr );
+
+ // #117892# M.M. Put the word date and time formatter stuff in a common area
+ // and get the rtf filter to use it
+ SwField *pFld = 0;
+ short nNumFmtType = NUMBERFORMAT_UNDEFINED;
+ ULONG nFmtIdx = NUMBERFORMAT_UNDEFINED;
+
+ USHORT rLang(0);
+ RES_CHRATR eLang = maPageDefaults.mbRTLdoc ? RES_CHRATR_CTL_LANGUAGE : RES_CHRATR_LANGUAGE;
+ const SvxLanguageItem *pLang = (SvxLanguageItem*)&pDoc->GetAttrPool().GetDefaultItem( static_cast< USHORT >(eLang) );
+ rLang = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
+
+ SvNumberFormatter* pFormatter = pDoc->GetNumberFormatter();
+ bool bHijri = false;
+
+ if( pFormatter )
+ {
+ nFmtIdx = sw::ms::MSDateTimeFormatToSwFormat(aSaveStr, pFormatter, rLang, bHijri);
+ if (nFmtIdx)
+ nNumFmtType = pFormatter->GetType(nFmtIdx);
+ }
+
+ pFldType = pDoc->GetSysFldType( RES_DATETIMEFLD );
+
+ if(nNumFmtType & NUMBERFORMAT_DATE)
+ pFld = new SwDateTimeField( (SwDateTimeFieldType*)pFldType, DATEFLD, nFmtIdx );
+ else if(nNumFmtType == NUMBERFORMAT_TIME)
+ pFld = new SwDateTimeField( (SwDateTimeFieldType*)pFldType, TIMEFLD, nFmtIdx );
+
+ if( pFld )
+ {
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( *pFld ), 0);
+ delete pFld;
+ }
+ }
+ SkipGroup(); // ueberlese den Rest
+ }
+ break;
+
+ case RTFFLD_DATA:
+ {
+ // Datenbank-FileName: nur der Filename interressiert
+ // Zur Zeit werden nur SDF-Files verarbeitet, also suche nach
+ // der Extension
+
+ // im SWG geben die DATA Felder den Namen der Datenbank
+ // an. Dieser kann als Field oder als DBInfo interpretiert
+ // werden:
+ // \\data -> Datenbank-Name als Field
+ // DATA -> Datenbank-Info
+ BOOL bField = rFieldStr.GetChar( 0 ) != 'D';
+
+ // nur der Name interressiert
+ if( STRING_NOTFOUND != (nPos = aSaveStr.Search( '.' )) )
+ aSaveStr.Erase( nPos );
+ SwDBData aData;
+ aData.sDataSource = aSaveStr;
+ if( bField )
+ {
+ pFldType = pDoc->GetSysFldType( RES_DBNAMEFLD );
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( SwDBNameField(
+ static_cast<SwDBNameFieldType*>(pFldType), SwDBData())), 0);
+ }
+ else
+ pDoc->ChgDBData( aData ); // MS: Keine DBInfo verwenden
+ SkipGroup(); // ueberlese den Rest
+ }
+ break;
+ case RTFFLD_MERGEFLD:
+ {
+ // ein Datenbank - Feld: nur der Name interressiert
+ // bis zum Ende vom String ist das der Feldname
+ SwDBFieldType aTmp( pDoc, aSaveStr, SwDBData() ); //
+ SwDBField aDBFld( (SwDBFieldType*)pDoc->InsertFldType( aTmp ));
+
+ aDBFld.ChangeFormat( UF_STRING );
+ pDoc->InsertPoolItem(*pPam, SwFmtFld( aDBFld ), 0);
+ SkipGroup(); // ueberlese den Rest
+ }
+ break;
+
+ case RTFFLD_SYMBOL:
+ {
+ // loesche fuehrende Blanks
+ if( IsNewGroup() )
+ GetAttrSet();
+ SetNewGroup( TRUE );
+
+ SfxItemSet& rSet = GetAttrSet();
+
+ BOOL bCharIns = FALSE;
+ RtfFieldSwitch aRFS( aSaveStr );
+ while( !aRFS.IsAtEnd() )
+ {
+ String sParam;
+ sal_Unicode cKey = aRFS.GetSwitch( sParam );
+ if( sParam.Len() )
+ switch( cKey )
+ {
+ case 0:
+ if( !bCharIns )
+ {
+ sal_Unicode nChar = (sal_Unicode)sParam.ToInt32();
+ if( nChar )
+ {
+ pDoc->InsertString( *pPam, nChar );
+ bCharIns = TRUE;
+ }
+ }
+ break;
+
+ case 'f': case 'F':
+ // Font setzen
+ {
+ SvxRTFFontTbl& rTbl = GetFontTbl();
+ for( Font* pFont = rTbl.First(); pFont;
+ pFont = rTbl.Next() )
+ if( pFont->GetName() == sParam )
+ {
+ rSet.Put( SvxFontItem(
+ pFont->GetFamily(),
+ sParam,
+ pFont->GetStyleName(),
+ pFont->GetPitch(),
+ pFont->GetCharSet(),
+ RES_CHRATR_FONT ));
+ break;
+ }
+ }
+ break;
+ case 'h': case 'H':
+ //??
+ break;
+ case 's': case 'S':
+ // Fontsize setzen
+ {
+ const USHORT nVal = (USHORT)(sParam.ToInt32() * 20);
+ rSet.Put( SvxFontHeightItem( nVal,
+ 100, RES_CHRATR_FONTSIZE ));
+ }
+ break;
+ }
+ }
+
+ if( !IsNewGroup() ) AttrGroupEnd();
+ SetNewGroup( FALSE );
+
+ SkipGroup(); // ueberlese den Rest
+ }
+ break;
+
+ case RTFFLD_HYPERLINK:
+ rFieldStr.Erase();
+ if( aSaveStr.Len() )
+ {
+ // return String ist URL, # Mark, \1 Frame
+ String sMark, sFrame;
+ RtfFieldSwitch aRFS( aSaveStr );
+ while( !aRFS.IsAtEnd() )
+ {
+ String sParam;
+ sal_Unicode cKey = aRFS.GetSwitch( sParam );
+ if( sParam.Len() )
+ switch( cKey )
+ {
+ case 0:
+ if( !rFieldStr.Len() )
+ rFieldStr = URIHelper::SmartRel2Abs(
+ INetURLObject(GetBaseURL()), sParam,
+ URIHelper::GetMaybeFileHdl() );
+ break;
+
+ case 'l': case 'L': sMark = sParam; break;
+ case 't': case 'T': sFrame = sParam; break;
+ }
+ }
+
+ if( sMark.Len() )
+ ( rFieldStr += INET_MARK_TOKEN ) += sMark;
+ if( sFrame.Len() )
+ ( rFieldStr += '\1' ) += sFrame;
+ }
+ break;
+
+ case RTFFLD_EQ:
+ rFieldStr.Erase();
+ if( aSaveStr.Len() )
+ {
+ RTF_EquationData aData;
+ ::lcl_ScanEquationField( aSaveStr, aData, 0 );
+
+ // is it a ruby attr?
+ if( aData.sText.Len() && aData.sFontName.Len() &&
+ aData.nFontSize && aData.sUp.Len() && !aData.sDown.Len() )
+ {
+ //Translate and apply
+ switch( aData.nJustificationCode )
+ {
+ case 0: aData.nJustificationCode = 1; break;
+ case 1: aData.nJustificationCode = 3; break;
+ case 2: aData.nJustificationCode = 4; break;
+ case 4: aData.nJustificationCode = 2; break;
+// case 3:
+ default: aData.nJustificationCode = 0; break;
+ }
+
+ SwFmtRuby aRuby( aData.sUp );
+ SwCharFmt * pCharFmt = -1 != aData.nStyleNo
+ ? aCharFmtTbl.Get( aData.nStyleNo )
+ : 0;
+
+ if( !pCharFmt )
+ {
+ //Make a guess at which of asian of western we should be setting
+ USHORT nScript;
+ if (pBreakIt->GetBreakIter().is())
+ nScript = pBreakIt->GetBreakIter()->getScriptType( aData.sUp, 0);
+ else
+ nScript = i18n::ScriptType::ASIAN;
+
+ USHORT nFntHWhich = GetWhichOfScript( RES_CHRATR_FONTSIZE, nScript ),
+ nFntWhich = GetWhichOfScript( RES_CHRATR_FONT, nScript );
+
+ //Check to see if we already have a ruby charstyle that this fits
+ for(USHORT i=0; i < aRubyCharFmts.Count(); ++i )
+ {
+ SwCharFmt *pFmt = (SwCharFmt *)aRubyCharFmts[i];
+ const SvxFontHeightItem &rF = (const SvxFontHeightItem &)
+ pFmt->GetFmtAttr( nFntHWhich );
+ if( rF.GetHeight() == USHORT(aData.nFontSize * 10 ))
+ {
+ const SvxFontItem &rFI = (const SvxFontItem &)
+ pFmt->GetFmtAttr( nFntWhich );
+ if( rFI.GetFamilyName().Equals( aData.sFontName ))
+ {
+ pCharFmt = pFmt;
+ break;
+ }
+ }
+ }
+
+ //Create a new char style if necessary
+ if( !pCharFmt )
+ {
+ String sNm;
+ //Take this as the base name
+ SwStyleNameMapper::FillUIName( RES_POOLCHR_RUBYTEXT, sNm );
+ sNm += String::CreateFromInt32( aRubyCharFmts.Count() + 1 );
+ pCharFmt = pDoc->MakeCharFmt( sNm,
+ ( SwCharFmt*)pDoc->GetDfltCharFmt() );
+
+ SvxFontHeightItem aHeightItem( aData.nFontSize * 10, 100, RES_CHRATR_FONTSIZE );
+ aHeightItem.SetWhich( nFntHWhich );
+
+ SvxFontItem aFontItem( FAMILY_DONTKNOW, aData.sFontName,
+ aEmptyStr, PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, nFntWhich );
+
+ pCharFmt->SetFmtAttr( aHeightItem );
+ pCharFmt->SetFmtAttr( aFontItem );
+ void* p = pCharFmt;
+ aRubyCharFmts.Insert( p, aRubyCharFmts.Count() );
+ }
+ }
+
+ //Set the charstyle and justification
+ aRuby.SetCharFmtName( pCharFmt->GetName() );
+ aRuby.SetCharFmtId( pCharFmt->GetPoolFmtId() );
+ aRuby.SetAdjustment( (USHORT)aData.nJustificationCode );
+
+ // im FieldStr steht der anzuzeigenden Text, im
+ pDoc->InsertString( *pPam, aData.sText );
+ pPam->SetMark();
+ pPam->GetMark()->nContent -= aData.sText.Len();
+ pDoc->InsertPoolItem( *pPam, aRuby,
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ pPam->DeleteMark();
+ }
+ // or a combined character field?
+ else if( aData.sUp.Len() && aData.sDown.Len() &&
+ !aData.sText.Len() && !aData.sFontName.Len() &&
+ !aData.nFontSize )
+ {
+ String sFld( aData.sUp );
+ sFld += aData.sDown;
+ SwCombinedCharField aFld((SwCombinedCharFieldType*)pDoc->
+ GetSysFldType( RES_COMBINED_CHARS ), sFld );
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0);
+
+ }
+ SkipGroup(); // ueberlese den Rest
+ }
+ break;
+
+ case RTFFLD_PAGEREF:
+ {
+ String sOrigBkmName;
+ RtfFieldSwitch aRFS( aSaveStr );
+ while( !aRFS.IsAtEnd() )
+ {
+ String sParam;
+ sal_Unicode cKey = aRFS.GetSwitch( sParam );
+ switch( cKey )
+ {
+ // In the case of pageref the only parameter we are
+ // interested in, is the name of the bookmark
+ case 0:
+ if( !sOrigBkmName.Len() ) // get name of bookmark
+ sOrigBkmName = sParam;
+ break;
+ }
+ }
+ SwGetRefField aFld(
+ (SwGetRefFieldType*)pDoc->GetSysFldType( RES_GETREFFLD ),
+ sOrigBkmName,REF_BOOKMARK,0,REF_PAGE);
+
+ if(!bNestedField)
+ {
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0 );
+ }
+ else
+ bNestedField = false;
+ }
+ break;
+
+ case RTFFLD_REF:
+ {
+ String sOrigBkmName;
+ bool bChapterNr = false;
+ bool bAboveBelow = false;
+
+ RtfFieldSwitch aRFS( aSaveStr );
+ while( !aRFS.IsAtEnd() )
+ {
+ String sParam;
+ sal_Unicode cKey = aRFS.GetSwitch( sParam );
+ switch( cKey )
+ {
+ case 0:
+ if( !sOrigBkmName.Len() ) // get name of bookmark
+ sOrigBkmName = sParam;
+ break;
+
+ case 'n':
+ case 'r':
+ case 'w':
+ bChapterNr = true; // activate flag 'Chapter Number'
+ break;
+
+ case 'p':
+ bAboveBelow = true;
+ break;
+ }
+ }
+ if (!bAboveBelow || bChapterNr)
+ {
+ if (bChapterNr)
+ {
+ SwGetRefField aFld(
+ (SwGetRefFieldType*)pDoc->GetSysFldType( RES_GETREFFLD ),
+ sOrigBkmName,REF_BOOKMARK,0,REF_CHAPTER);
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0 );
+ }
+ else
+ {
+ SwGetRefField aFld(
+ (SwGetRefFieldType*)pDoc->GetSysFldType( RES_GETREFFLD ),
+ sOrigBkmName,REF_BOOKMARK,0,REF_CONTENT);
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0 );
+ }
+ }
+
+ if( bAboveBelow )
+ {
+ SwGetRefField aFld( (SwGetRefFieldType*)
+ pDoc->GetSysFldType( RES_GETREFFLD ), sOrigBkmName, REF_BOOKMARK, 0,
+ REF_UPDOWN );
+ pDoc->InsertPoolItem(*pPam, SwFmtFld(aFld), 0);
+ }
+ }
+ break;
+
+ case RTFFLD_TOC:
+ case RTFFLD_INDEX:
+ break;
+
+ default:
+ {
+ // keines von den bekannten Feldern, also eine neues UserField
+ aSaveStr.EraseLeadingChars().EraseTrailingChars();
+ SwUserFieldType aTmp( pDoc, aSaveStr );
+ SwUserField aUFld( (SwUserFieldType*)pDoc->InsertFldType( aTmp ));
+ aUFld.ChangeFormat( UF_STRING );
+ pDoc->InsertPoolItem( *pPam, SwFmtFld( aUFld ), 0);
+ nRet = RTFFLD_UNKNOWN;
+ }
+ break;
+ }
+ return nRet;
+}
+
+
+void SwRTFParser::ReadXEField()
+{
+ bReadSwFly = false; //#it may be that any uses of this need to be removed and replaced
+ int nNumOpenBrakets = 1;
+ String sFieldStr;
+ BYTE cCh;
+
+ int nToken;
+ while (nNumOpenBrakets && IsParserWorking())
+ {
+ switch (nToken = GetNextToken())
+ {
+ case '}':
+ {
+ --nNumOpenBrakets;
+
+ if( sFieldStr.Len())
+ {
+ String sXE(sFieldStr);
+ sXE.Insert('\"', 0);
+ sXE.Append('\"');
+
+ // we have to make sure the hidden text flag is not on
+ // otherwise the index will not see this index mark
+ SfxItemSet& rSet = GetAttrSet();
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
+ {
+ SvxCharHiddenItem aCharHidden(*(SvxCharHiddenItem*)pItem);
+ aCharHidden.SetValue(FALSE);
+ rSet.Put(aCharHidden);
+ }
+
+ sw::ms::ImportXE(*pDoc, *pPam, sXE);
+
+ sFieldStr.Erase();
+ }
+ }
+ break;
+
+ case '{':
+ if( RTF_IGNOREFLAG != GetNextToken() )
+ SkipToken( -1 );
+ // Unknown und alle bekannten nicht ausgewerteten Gruppen
+ // sofort ueberspringen
+ else if( RTF_UNKNOWNCONTROL != GetNextToken() )
+ SkipToken( -2 );
+ else
+ {
+ // gleich herausfiltern
+ ReadUnknownData();
+ if( '}' != GetNextToken() )
+ eState = SVPAR_ERROR;
+ break;
+ }
+ ++nNumOpenBrakets;
+ break;
+
+ case RTF_U:
+ {
+ if( nTokenValue )
+ sFieldStr += (sal_Unicode)nTokenValue;
+ else
+ sFieldStr += aToken;
+ }
+ break;
+
+ case RTF_LINE: cCh = '\n'; goto INSINGLECHAR;
+ case RTF_TAB: cCh = '\t'; goto INSINGLECHAR;
+ case RTF_SUBENTRYINDEX: cCh = ':'; goto INSINGLECHAR;
+ case RTF_EMDASH: cCh = 151; goto INSINGLECHAR;
+ case RTF_ENDASH: cCh = 150; goto INSINGLECHAR;
+ case RTF_BULLET: cCh = 149; goto INSINGLECHAR;
+ case RTF_LQUOTE: cCh = 145; goto INSINGLECHAR;
+ case RTF_RQUOTE: cCh = 146; goto INSINGLECHAR;
+ case RTF_LDBLQUOTE: cCh = 147; goto INSINGLECHAR;
+ case RTF_RDBLQUOTE: cCh = 148; goto INSINGLECHAR;
+INSINGLECHAR:
+ sFieldStr += ByteString::ConvertToUnicode( cCh,
+ RTL_TEXTENCODING_MS_1252 );
+ break;
+
+ // kein Break, aToken wird als Text gesetzt
+ case RTF_TEXTTOKEN:
+ sFieldStr += aToken;
+ break;
+
+ case RTF_BKMK_KEY:
+ case RTF_TC:
+ case RTF_NEXTFILE:
+ case RTF_TEMPLATE:
+ case RTF_SHPRSLT:
+ SkipGroup();
+ break;
+
+ case RTF_PAR:
+ sFieldStr.Append('\x0a');
+ break;
+ default:
+ SvxRTFParser::NextToken( nToken );
+ break;
+ }
+ }
+
+ SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet
+}
+
+
+void SwRTFParser::ReadField()
+{
+ bReadSwFly = false; //#it may be that any uses of this need to be removed and replaced
+ int nRet = 0;
+ int nNumOpenBrakets = 1; // die erste wurde schon vorher erkannt !!
+ int bFldInst = FALSE, bFldRslt = FALSE;
+ String sFieldStr, sFieldNm;
+ BYTE cCh;
+
+ int nToken;
+ while (nNumOpenBrakets && IsParserWorking())
+ {
+ switch (nToken = GetNextToken())
+ {
+ case '}':
+ {
+ --nNumOpenBrakets;
+ if( 1 != nNumOpenBrakets || !bFldInst )
+ break;
+
+ if( !bFldRslt )
+ {
+ // FieldInst vollstaendig eingelesen, was ist es denn?
+ nRet = MakeFieldInst( sFieldStr );
+ switch ( nRet )
+ {
+ case RTFFLD_INCLUDETEXT:
+ case RTFFLD_TOC:
+ case RTFFLD_INDEX:
+ // erstmal Index/Inhaltsverzeichniss ueberspringen
+ // und als normalen Text einfuegen. Spaeter mal auch dem
+ // SwPaM darum aufspannen.
+ return ;
+
+ case RTFFLD_IMPORT:
+ case RTFFLD_HYPERLINK:
+ sFieldNm = sFieldStr;
+ break;
+ }
+ sFieldStr.Erase();
+ }
+ else if (RTFFLD_UNKNOWN == nRet)
+ {
+ // FieldResult wurde eingelesen
+ if (SwTxtNode* pTxtNd = pPam->GetPoint()->nNode.GetNode().GetTxtNode())
+ {
+ SwTxtAttr* const pFldAttr =
+ pTxtNd->GetTxtAttrForCharAt(
+ pPam->GetPoint()->nContent.GetIndex()-1 );
+
+ if (pFldAttr)
+ {
+ const SwField *pFld = pFldAttr->GetFld().GetFld();
+ SwFieldType *pTyp = pFld ? pFld->GetTyp() : 0;
+ ASSERT(pTyp->Which() == RES_USERFLD, "expected a user field");
+ if (pTyp->Which() == RES_USERFLD)
+ {
+ SwUserFieldType *pUsrTyp = (SwUserFieldType*)pTyp;
+ pUsrTyp->SetContent(sFieldStr);
+ }
+ }
+ }
+ }
+ else if( sFieldNm.Len() )
+ {
+ switch ( nRet )
+ {
+ case RTFFLD_IMPORT:
+ // Grafik einfuegen
+ InsPicture( sFieldNm );
+ nRet = INT_MAX;
+ break;
+ case RTFFLD_HYPERLINK:
+ if( sFieldStr.Len() )
+ {
+ if(sNestedFieldStr.Len())
+ sFieldStr.Insert(sNestedFieldStr);
+
+ sNestedFieldStr.Erase();
+ // im FieldStr steht der anzuzeigenden Text, im
+ pDoc->InsertString( *pPam, sFieldStr );
+
+ String sTarget( sFieldNm.GetToken( 1, '\1' ));
+ if( sTarget.Len() )
+ sFieldNm.Erase( sFieldNm.Len() - sTarget.Len() -1 );
+
+ // oder ueber den Stack setzen??
+ pPam->SetMark();
+ pPam->GetMark()->nContent -= sFieldStr.Len();
+ pDoc->InsertPoolItem( *pPam,
+ SwFmtINetFmt( sFieldNm, sTarget ),
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ pPam->DeleteMark();
+
+ }
+ break;
+ }
+ }
+ else if(bNestedField)
+ {
+ if(nRet == RTFFLD_PAGEREF)
+ {
+ // #17371 Nasty hack to get a pageref within a hyperlink working
+ sNestedFieldStr = sFieldStr;
+ }
+
+ }
+
+ }
+ break;
+
+ case '{':
+ if( RTF_IGNOREFLAG != GetNextToken() )
+ SkipToken( -1 );
+ // Unknown und alle bekannten nicht ausgewerteten Gruppen
+ // sofort ueberspringen
+ else if( RTF_UNKNOWNCONTROL != GetNextToken() )
+ SkipToken( -2 );
+ else
+ {
+ // gleich herausfiltern
+ ReadUnknownData();
+ if( '}' != GetNextToken() )
+ eState = SVPAR_ERROR;
+ break;
+ }
+ ++nNumOpenBrakets;
+ break;
+
+ case RTF_DATAFIELD:
+ SkipGroup();
+ break;
+
+ case RTF_FIELD:
+ bNestedField = true;
+ ReadField();
+ break;
+
+ case RTF_FLDINST:
+ bFldInst = TRUE;
+ break;
+
+ case RTF_FLDRSLT:
+ bFldRslt = TRUE;
+ break;
+
+ case RTF_U:
+ {
+ if( nTokenValue )
+ sFieldStr += (sal_Unicode)nTokenValue;
+ else
+ sFieldStr += aToken;
+ }
+ break;
+
+ case RTF_LINE: cCh = '\n'; goto INSINGLECHAR;
+ case RTF_TAB: cCh = '\t'; goto INSINGLECHAR;
+ case RTF_SUBENTRYINDEX: cCh = ':'; goto INSINGLECHAR;
+ case RTF_EMDASH: cCh = 151; goto INSINGLECHAR;
+ case RTF_ENDASH: cCh = 150; goto INSINGLECHAR;
+ case RTF_BULLET: cCh = 149; goto INSINGLECHAR;
+ case RTF_LQUOTE: cCh = 145; goto INSINGLECHAR;
+ case RTF_RQUOTE: cCh = 146; goto INSINGLECHAR;
+ case RTF_LDBLQUOTE: cCh = 147; goto INSINGLECHAR;
+ case RTF_RDBLQUOTE: cCh = 148; goto INSINGLECHAR;
+INSINGLECHAR:
+ sFieldStr += ByteString::ConvertToUnicode( cCh,
+ RTL_TEXTENCODING_MS_1252 );
+ break;
+
+ // kein Break, aToken wird als Text gesetzt
+ case RTF_TEXTTOKEN:
+ sFieldStr += aToken;
+ break;
+
+ case RTF_PICT: // Pic-Daten einlesen!
+ if( RTFFLD_IMPORT == nRet )
+ {
+ Graphic aGrf;
+ SvxRTFPictureType aPicType;
+ if( ReadBmpData( aGrf, aPicType ) )
+ {
+ InsPicture( sFieldNm, &aGrf, &aPicType );
+ nRet = INT_MAX;
+ }
+ SkipGroup();
+ }
+ break;
+
+ case RTF_BKMK_KEY:
+ case RTF_XE:
+ case RTF_TC:
+ case RTF_NEXTFILE:
+ case RTF_TEMPLATE:
+ case RTF_SHPRSLT:
+ SkipGroup();
+ break;
+
+ case RTF_CS:
+ // we write every time "EQ "
+ if( bFldInst && 0 == sFieldStr.SearchAscii( "EQ " ))
+ {
+ // insert behind the EQ the "\*cs<NO> " string. This is utilize
+ // in the MakeFieldInst
+ String sTmp;
+ (sTmp.AssignAscii( "\\* cs" )
+ += String::CreateFromInt32( nTokenValue )) += ' ';
+ sFieldStr.Insert( sTmp, 3 );
+ }
+ break;
+ case RTF_FFNAME:
+ case RTF_FORMFIELD:
+ break;
+ case RTF_PAR:
+ sFieldStr.Append('\x0a');
+ break;
+ default:
+ SvxRTFParser::NextToken( nToken );
+ break;
+ }
+ }
+
+ // Grafik einfuegen
+ if (RTFFLD_IMPORT == nRet && sFieldNm.Len())
+ InsPicture( sFieldNm );
+
+ SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet
+}
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */