1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rtffld.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
36 #include <hintids.hxx>
38 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
39 #include <com/sun/star/i18n/ScriptType.hdl>
41 #ifndef _GRAPH_HXX //autogen
42 #include <vcl/graph.hxx>
44 #include <svtools/urihelper.hxx>
45 #include <svtools/rtftoken.h>
46 #include <svtools/zforlist.hxx>
47 #include <svx/fontitem.hxx>
48 #include <svx/fhgtitem.hxx>
49 #include <svx/langitem.hxx>
50 #include <svx/brkitem.hxx>
52 #include <fmtinfmt.hxx>
53 #include <swtypes.hxx>
57 #include <shellio.hxx>
59 #include <swparrtf.hxx>
60 #include <txatbase.hxx>
63 #include <docufld.hxx>
65 #include <charfmt.hxx>
67 #include <fmtruby.hxx>
69 #include <breakit.hxx>
71 #include <SwStyleNameMapper.hxx>
72 #include <svx/charhiddenitem.hxx>
75 // bestimme, ob es sich um ein IMPORT/TOC - Feld handelt.
76 // return: 0 - weder noch,
99 static RTF_FLD_TYPES
_WhichFld( String
& rName
, String
& rNext
)
101 // Strings sind PascalStrings; Laenge steht an 1. Stellen, dadurch wird
102 // sich der Aufruf von strlen erspart!!!
103 sal_Char __READONLY_DATA sTOC
[]= "\x03""toc";
104 sal_Char __READONLY_DATA sIMPORT
[]= "\x06""import";
105 sal_Char __READONLY_DATA sINDEX
[]= "\x05""index";
106 sal_Char __READONLY_DATA sSYMBOL
[]= "\x06""symbol";
107 sal_Char __READONLY_DATA sPAGE
[]= "\x04""page";
108 sal_Char __READONLY_DATA sNUMPAGES
[]= "\x08""numpages";
109 sal_Char __READONLY_DATA sDATE
[]= "\x04""date";
110 sal_Char __READONLY_DATA sTIME
[]= "\x04""time";
111 sal_Char __READONLY_DATA sDATA
[]= "\x04""data";
112 sal_Char __READONLY_DATA sMERGEFLD
[]= "\x0A""mergefield";
113 sal_Char __READONLY_DATA sIMPORT2
[]= "\x0E""includepicture";
114 sal_Char __READONLY_DATA sHYPERLINK
[]= "\x09""hyperlink";
115 sal_Char __READONLY_DATA sREF
[]= "\x03""ref";
116 sal_Char __READONLY_DATA sPAGEREF
[]= "\x07""pageref";
117 sal_Char __READONLY_DATA sEQ
[]= "\x02""eq";
118 sal_Char __READONLY_DATA sINCLUDETEXT
[]="\x0B""includetext";
120 struct _Dummy_RTF_FLD_TYPES
122 RTF_FLD_TYPES eFldType
;
123 const sal_Char
* pFldNm
;
125 __READONLY_DATA _Dummy_RTF_FLD_TYPES aFldNmArr
[RTFFLD_INCLUDETEXT
+ 1] = {
127 {RTFFLD_IMPORT
, sIMPORT
},
128 {RTFFLD_INDEX
, sINDEX
},
129 {RTFFLD_SYMBOL
, sSYMBOL
},
130 {RTFFLD_PAGE
, sPAGE
},
131 {RTFFLD_NUMPAGES
, sNUMPAGES
},
132 {RTFFLD_DATE
, sDATE
},
133 {RTFFLD_TIME
, sTIME
},
134 {RTFFLD_DATA
, sDATA
},
135 {RTFFLD_MERGEFLD
, sMERGEFLD
},
136 {RTFFLD_IMPORT
, sIMPORT2
},
137 {RTFFLD_HYPERLINK
, sHYPERLINK
},
139 {RTFFLD_PAGEREF
, sPAGEREF
},
141 {RTFFLD_INCLUDETEXT
, sINCLUDETEXT
}
146 return RTFFLD_UNKNOWN
;
149 sNm
= sNm
.EraseLeadingChars().GetToken(0, ' ');
150 ASSERT( sNm
.Len(), "Feldname hat keine Laenge!" );
152 return RTFFLD_UNKNOWN
;
154 xub_StrLen nTokenStt
= rName
.Search( sNm
);
157 for (size_t n
= 0; n
< sizeof(aFldNmArr
) / sizeof(aFldNmArr
[0]); ++n
)
159 const sal_Char
* pCmp
= aFldNmArr
[n
].pFldNm
;
161 xub_StrLen nFndPos
= sNm
.SearchAscii( pCmp
);
162 if( STRING_NOTFOUND
!= nFndPos
&&
163 ( !nFndPos
|| !isalpha(sNm
.GetChar( static_cast< xub_StrLen
>(nFndPos
-1) )) ) &&
164 ( nFndPos
+nLen
== sNm
.Len() || !isalpha(sNm
.GetChar( static_cast< xub_StrLen
>(nFndPos
+nLen
) ) ) ) )
166 // rName = sNm.Copy( nFndPos, nLen );
167 rName
= rName
.Copy( nFndPos
, static_cast< xub_StrLen
>(nLen
) );
168 nFndPos
+= nTokenStt
+ static_cast< xub_StrLen
>(nLen
);
169 while( rNext
.GetChar( nFndPos
) == ' ' ) ++nFndPos
;
170 rNext
.Erase( 0, nFndPos
);
171 rNext
.EraseTrailingChars();
172 return aFldNmArr
[n
].eFldType
;
175 return RTFFLD_UNKNOWN
; // nichts gefunden.
178 static USHORT
CheckNumberFmtStr( const String
& rNStr
)
180 const static sal_Char
* aNumberTypeTab
[] =
182 "\x0A""ALPHABETIC", /* CHARS_UPPER_LETTER*/
183 "\x0A""alphabetic", /* CHARS_LOWER_LETTER*/
184 "\x05""ROMAN", /* ROMAN_UPPER */
185 "\x05""roman", /* ROMAN_LOWER */
186 "\x06""ARABIC", /* ARABIC */
187 "\x04""NONE", /* NUMBER_NONE */
188 "\x04""CHAR", /* CHAR_SPECIAL */
189 "\x04""PAGE" /* PAGEDESC */
192 ASSERT(sizeof(aNumberTypeTab
) / sizeof(sal_Char
*)
193 >= SVX_NUM_PAGEDESC
- SVX_NUM_CHARS_UPPER_LETTER
, "impossible");
195 for (USHORT n
= SVX_NUM_CHARS_UPPER_LETTER
; n
<= SVX_NUM_PAGEDESC
; ++n
)
197 const sal_Char
* pCmp
= aNumberTypeTab
[n
- SVX_NUM_CHARS_UPPER_LETTER
];
199 if( rNStr
.EqualsAscii( pCmp
, 0, static_cast< xub_StrLen
>(nLen
) ))
200 return static_cast< USHORT
>(2 <= n
? n
: (n
+ SVX_NUM_CHARS_UPPER_LETTER_N
));
202 return SVX_NUM_PAGEDESC
; // default-Wert
210 RtfFieldSwitch( const String
& rParam
);
211 sal_Unicode
GetSwitch( String
& rParam
);
213 BOOL
IsAtEnd() const { return nCurPos
>= sParam
.Len(); }
214 xub_StrLen
GetCurPos() const { return nCurPos
; }
215 void Erase( xub_StrLen nEndPos
) { sParam
.Erase( 0, nEndPos
); }
216 void Insert( const String
& rIns
) { sParam
.Insert( rIns
, 0 ); }
217 const String
& GetStr() const { return sParam
; }
220 RtfFieldSwitch::RtfFieldSwitch( const String
& rParam
)
221 : sParam( rParam
), nCurPos( 0 )
223 sParam
.EraseTrailingChars().EraseLeadingChars();
226 sal_Unicode
RtfFieldSwitch::GetSwitch( String
& rParam
)
228 // beginnt ein Schalter?
229 sal_Unicode c
, cKey
= 0;
230 if( '\\' == (c
= sParam
.GetChar( nCurPos
)) )
232 if( '\\' == ( c
= sParam
.GetChar( ++nCurPos
)) )
233 c
= sParam
.GetChar( ++nCurPos
);
237 while( ++nCurPos
< sParam
.Len() &&
238 ' ' == ( c
= sParam
.GetChar( nCurPos
)) )
242 // dann alles in Hochkommatas oder bis zum naechsten // als
245 if( '"' != c
&& '\'' != c
)
246 c
= '\\', nOffset
= 0;
250 sParam
.Erase( 0, nCurPos
+ nOffset
);
251 rParam
= sParam
.GetToken( 0, c
);
252 sParam
.Erase( 0, rParam
.Len() + nOffset
).EraseLeadingChars();
254 rParam
.EraseTrailingChars();
260 struct RTF_EquationData
262 String sFontName
, sUp
, sDown
, sText
;
263 sal_Int32 nJustificationCode
, nFontSize
, nUp
, nDown
, nStyleNo
;
265 inline RTF_EquationData()
266 : nJustificationCode(0), nFontSize(0), nUp(0), nDown(0),
271 xub_StrLen
lcl_FindEndBracket( const String
& rStr
)
273 xub_StrLen nEnd
= rStr
.Len(), nRet
= STRING_NOTFOUND
, nPos
= 0;
276 for( ; nPos
< nEnd
; ++nPos
)
277 if( ')' == (cCh
= rStr
.GetChar( nPos
)) && !--nOpenCnt
)
282 else if( '(' == cCh
)
288 void lcl_ScanEquationField( const String
& rStr
, RTF_EquationData
& rData
,
289 sal_Unicode nSttKey
)
292 RtfFieldSwitch
aRFS( rStr
);
293 while( !aRFS
.IsAtEnd() )
296 sal_Unicode cKey
= aRFS
.GetSwitch( sParam
);
297 if( 1 == nSubSupFlag
)
299 else if( 1 < nSubSupFlag
)
302 BOOL bCheckBracket
= FALSE
;
308 case 'u': rData
.sUp
+= sParam
; break;
309 case 'd': rData
.sDown
+= sParam
; break;
310 default: rData
.sText
+= sParam
; break;
317 if( sParam
.EqualsIgnoreCaseAscii( "jc", 0, 2 ) )
318 rData
.nJustificationCode
= sParam
.Copy( 2 ).ToInt32();
319 else if( sParam
.EqualsIgnoreCaseAscii( "hps", 0, 3 ) )
320 rData
.nFontSize
= sParam
.Copy( 3 ).ToInt32();
321 else if( sParam
.EqualsIgnoreCaseAscii( "Font:", 0, 5 ) )
322 rData
.sFontName
= sParam
.Copy( 5 );
323 else if( sParam
.EqualsIgnoreCaseAscii( "cs", 0, 2 ) )
324 rData
.nStyleNo
= sParam
.Copy( 2 ).ToInt32();
332 if( sParam
.Len() && 'p' == sParam
.GetChar( 0 ) &&
335 rData
.nUp
= sParam
.Copy( 1 ).ToInt32();
336 bCheckBracket
= TRUE
;
341 if( sParam
.Len() && 'o' == sParam
.GetChar( 0 ) &&
344 rData
.nDown
= sParam
.Copy( 1 ).ToInt32();
345 bCheckBracket
= TRUE
;
350 bCheckBracket
= TRUE
;
355 if( bCheckBracket
&& sParam
.Len() )
357 xub_StrLen nEnd
, nStt
= sParam
.Search( '(' ),
359 if( STRING_NOTFOUND
!= nStt
)
361 sParam
.Erase( 0, nStt
+ 1 ) += aRFS
.GetStr();
362 if( STRING_NOTFOUND
!=
363 (nEnd
= ::lcl_FindEndBracket( sParam
)) )
365 // end in the added string?
366 if( (nLen
- nStt
- 1 ) < nEnd
)
367 aRFS
.Erase( nEnd
+ 1 - (nLen
- nStt
- 1));
370 // not all handled here, so set new into the RFS
371 aRFS
.Insert( sParam
.Copy( nEnd
+ 1,
372 nLen
- nStt
- nEnd
- 2 ));
374 if( aRFS
.GetStr().Len() &&
375 ( ',' == (cCh
= aRFS
.GetStr().GetChar(0)) ||
380 ::lcl_ScanEquationField( sParam
.Copy( 0, nEnd
),
388 int SwRTFParser::MakeFieldInst( String
& rFieldStr
)
390 // sicher den Original-String fuer die FeldNamen (User/Datenbank)
391 String
aSaveStr( rFieldStr
);
392 SwFieldType
* pFldType
;
393 int nRet
= _WhichFld(rFieldStr
, aSaveStr
);
395 //Strip Mergeformat from fields
397 while (STRING_NOTFOUND
!= ( nPos
= aSaveStr
.SearchAscii("\\*", nPos
)))
399 xub_StrLen nStartDel
= nPos
;
401 while (aSaveStr
.GetChar(nPos
) == ' ')
403 if (aSaveStr
.EqualsIgnoreCaseAscii("MERGEFORMAT", nPos
, 11))
405 xub_StrLen nNoDel
= (nPos
+ 11 ) - nStartDel
;
406 aSaveStr
.Erase(nStartDel
, nNoDel
);
407 nPos
-= (nStartDel
- nPos
);
414 case RTFFLD_INCLUDETEXT
:
418 //JP 11.03.96: vertraegt sich nicht so ganz mit Internet!
419 // if( STRING_NOTFOUND != ( nPos = aSaveStr.Search( '.' )))
420 // aSaveStr.Erase( nPos+4 );
422 aSaveStr
.EraseLeadingAndTrailingChars();
425 sal_Unicode c
= aSaveStr
.GetChar( 0 );
426 if( '"' == c
|| '\'' == c
)
428 aSaveStr
.Erase( 0, 1 );
429 aSaveStr
= aSaveStr
.GetToken( 0, c
);
432 rFieldStr
= URIHelper::SmartRel2Abs(
433 INetURLObject(GetBaseURL()), aSaveStr
,
434 URIHelper::GetMaybeFileHdl() );
436 // SkipGroup(); // ueberlese den Rest
440 case RTFFLD_NUMPAGES
:
442 SwDocStatField
aFld( (SwDocStatFieldType
*)pDoc
->GetSysFldType( RES_DOCSTATFLD
),
443 DS_PAGE
, SVX_NUM_ARABIC
);
444 if( STRING_NOTFOUND
!= ( nPos
= aSaveStr
.SearchAscii( "\\*" )) )
447 while( aSaveStr
.GetChar(nPos
) == ' ' ) nPos
++;
448 aSaveStr
.Erase( 0, nPos
);
450 // steht jetzt geanu auf dem Format-Namen
451 aFld
.ChangeFormat( CheckNumberFmtStr( aSaveStr
));
453 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( aFld
), 0 );
460 pFldType
= pDoc
->GetSysFldType( RES_PAGENUMBERFLD
);
461 SwPageNumberField
aPF( (SwPageNumberFieldType
*)pFldType
,
462 PG_RANDOM
, SVX_NUM_ARABIC
);
463 if( STRING_NOTFOUND
!= ( nPos
= aSaveStr
.SearchAscii( "\\*" )) )
466 while( aSaveStr
.GetChar(nPos
) == ' ' ) nPos
++;
467 aSaveStr
.Erase( 0, nPos
);
469 // steht jetzt geanu auf dem Format-Namen
470 aPF
.ChangeFormat( CheckNumberFmtStr( aSaveStr
));
472 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( aPF
), 0 );
473 SkipGroup(); // ueberlese den Rest
479 if( STRING_NOTFOUND
== ( nPos
= aSaveStr
.SearchAscii( "\\@" )) )
481 // es fehlt die Format - Angabe: defaulten auf Datum
482 pFldType
= pDoc
->GetSysFldType( RES_DATETIMEFLD
);
483 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( SwDateTimeField(
484 static_cast<SwDateTimeFieldType
*>(pFldType
), DATEFLD
)), 0);
488 // versuche aus dem Formatstring zu erkennen, ob es ein
489 // Datum oder Zeit oder Datum & Zeit Field ist
490 // nur das Format interressiert
491 aSaveStr
.Erase( 0, aSaveStr
.Search( '\"' )+1 );
492 // alles hinter dem Format interressiert auch nicht mehr.
493 aSaveStr
.Erase( aSaveStr
.Search( '\"' ) );
494 aSaveStr
.SearchAndReplaceAscii( "AM", aEmptyStr
);
495 aSaveStr
.SearchAndReplaceAscii( "PM", aEmptyStr
);
497 // #117892# M.M. Put the word date and time formatter stuff in a common area
498 // and get the rtf filter to use it
500 short nNumFmtType
= NUMBERFORMAT_UNDEFINED
;
501 ULONG nFmtIdx
= NUMBERFORMAT_UNDEFINED
;
504 RES_CHRATR eLang
= maPageDefaults
.mbRTLdoc
? RES_CHRATR_CTL_LANGUAGE
: RES_CHRATR_LANGUAGE
;
505 const SvxLanguageItem
*pLang
= (SvxLanguageItem
*)&pDoc
->GetAttrPool().GetDefaultItem( static_cast< USHORT
>(eLang
) );
506 rLang
= pLang
? pLang
->GetValue() : LANGUAGE_ENGLISH_US
;
508 SvNumberFormatter
* pFormatter
= pDoc
->GetNumberFormatter();
513 nFmtIdx
= sw::ms::MSDateTimeFormatToSwFormat(aSaveStr
, pFormatter
, rLang
, bHijri
);
515 nNumFmtType
= pFormatter
->GetType(nFmtIdx
);
518 pFldType
= pDoc
->GetSysFldType( RES_DATETIMEFLD
);
520 if(nNumFmtType
& NUMBERFORMAT_DATE
)
521 pFld
= new SwDateTimeField( (SwDateTimeFieldType
*)pFldType
, DATEFLD
, nFmtIdx
);
522 else if(nNumFmtType
== NUMBERFORMAT_TIME
)
523 pFld
= new SwDateTimeField( (SwDateTimeFieldType
*)pFldType
, TIMEFLD
, nFmtIdx
);
527 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( *pFld
), 0);
531 SkipGroup(); // ueberlese den Rest
537 // Datenbank-FileName: nur der Filename interressiert
538 // Zur Zeit werden nur SDF-Files verarbeitet, also suche nach
541 // im SWG geben die DATA Felder den Namen der Datenbank
542 // an. Dieser kann als Field oder als DBInfo interpretiert
544 // \\data -> Datenbank-Name als Field
545 // DATA -> Datenbank-Info
546 BOOL bField
= rFieldStr
.GetChar( 0 ) != 'D';
548 // nur der Name interressiert
549 if( STRING_NOTFOUND
!= (nPos
= aSaveStr
.Search( '.' )) )
550 aSaveStr
.Erase( nPos
);
552 aData
.sDataSource
= aSaveStr
;
555 pFldType
= pDoc
->GetSysFldType( RES_DBNAMEFLD
);
556 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( SwDBNameField(
557 static_cast<SwDBNameFieldType
*>(pFldType
), SwDBData())), 0);
560 pDoc
->ChgDBData( aData
); // MS: Keine DBInfo verwenden
561 SkipGroup(); // ueberlese den Rest
564 case RTFFLD_MERGEFLD
:
566 // ein Datenbank - Feld: nur der Name interressiert
567 // bis zum Ende vom String ist das der Feldname
568 SwDBFieldType
aTmp( pDoc
, aSaveStr
, SwDBData() ); //
569 SwDBField
aDBFld( (SwDBFieldType
*)pDoc
->InsertFldType( aTmp
));
571 aDBFld
.ChangeFormat( UF_STRING
);
572 pDoc
->InsertPoolItem(*pPam
, SwFmtFld( aDBFld
), 0);
573 SkipGroup(); // ueberlese den Rest
579 // loesche fuehrende Blanks
584 SfxItemSet
& rSet
= GetAttrSet();
586 BOOL bCharIns
= FALSE
;
587 RtfFieldSwitch
aRFS( aSaveStr
);
588 while( !aRFS
.IsAtEnd() )
591 sal_Unicode cKey
= aRFS
.GetSwitch( sParam
);
598 sal_Unicode nChar
= (sal_Unicode
)sParam
.ToInt32();
601 pDoc
->InsertString( *pPam
, nChar
);
610 SvxRTFFontTbl
& rTbl
= GetFontTbl();
611 for( Font
* pFont
= rTbl
.First(); pFont
;
612 pFont
= rTbl
.Next() )
613 if( pFont
->GetName() == sParam
)
615 rSet
.Put( SvxFontItem(
618 pFont
->GetStyleName(),
632 const USHORT nVal
= (USHORT
)(sParam
.ToInt32() * 20);
633 rSet
.Put( SvxFontHeightItem( nVal
,
634 100, RES_CHRATR_FONTSIZE
));
640 if( !IsNewGroup() ) AttrGroupEnd();
641 SetNewGroup( FALSE
);
643 SkipGroup(); // ueberlese den Rest
647 case RTFFLD_HYPERLINK
:
651 // return String ist URL, # Mark, \1 Frame
652 String sMark
, sFrame
;
653 RtfFieldSwitch
aRFS( aSaveStr
);
654 while( !aRFS
.IsAtEnd() )
657 sal_Unicode cKey
= aRFS
.GetSwitch( sParam
);
662 if( !rFieldStr
.Len() )
663 rFieldStr
= URIHelper::SmartRel2Abs(
664 INetURLObject(GetBaseURL()), sParam
,
665 URIHelper::GetMaybeFileHdl() );
668 case 'l': case 'L': sMark
= sParam
; break;
669 case 't': case 'T': sFrame
= sParam
; break;
674 ( rFieldStr
+= INET_MARK_TOKEN
) += sMark
;
676 ( rFieldStr
+= '\1' ) += sFrame
;
684 RTF_EquationData aData
;
685 ::lcl_ScanEquationField( aSaveStr
, aData
, 0 );
687 // is it a ruby attr?
688 if( aData
.sText
.Len() && aData
.sFontName
.Len() &&
689 aData
.nFontSize
&& aData
.sUp
.Len() && !aData
.sDown
.Len() )
691 //Translate and apply
692 switch( aData
.nJustificationCode
)
694 case 0: aData
.nJustificationCode
= 1; break;
695 case 1: aData
.nJustificationCode
= 3; break;
696 case 2: aData
.nJustificationCode
= 4; break;
697 case 4: aData
.nJustificationCode
= 2; break;
699 default: aData
.nJustificationCode
= 0; break;
702 SwFmtRuby
aRuby( aData
.sUp
);
703 SwCharFmt
* pCharFmt
= -1 != aData
.nStyleNo
704 ? aCharFmtTbl
.Get( aData
.nStyleNo
)
709 //Make a guess at which of asian of western we should be setting
711 if (pBreakIt
->GetBreakIter().is())
712 nScript
= pBreakIt
->GetBreakIter()->getScriptType( aData
.sUp
, 0);
714 nScript
= i18n::ScriptType::ASIAN
;
716 USHORT nFntHWhich
= GetWhichOfScript( RES_CHRATR_FONTSIZE
, nScript
),
717 nFntWhich
= GetWhichOfScript( RES_CHRATR_FONT
, nScript
);
719 //Check to see if we already have a ruby charstyle that this fits
720 for(USHORT i
=0; i
< aRubyCharFmts
.Count(); ++i
)
722 SwCharFmt
*pFmt
= (SwCharFmt
*)aRubyCharFmts
[i
];
723 const SvxFontHeightItem
&rF
= (const SvxFontHeightItem
&)
724 pFmt
->GetFmtAttr( nFntHWhich
);
725 if( rF
.GetHeight() == USHORT(aData
.nFontSize
* 10 ))
727 const SvxFontItem
&rFI
= (const SvxFontItem
&)
728 pFmt
->GetFmtAttr( nFntWhich
);
729 if( rFI
.GetFamilyName().Equals( aData
.sFontName
))
737 //Create a new char style if necessary
741 //Take this as the base name
742 SwStyleNameMapper::FillUIName( RES_POOLCHR_RUBYTEXT
, sNm
);
743 sNm
+= String::CreateFromInt32( aRubyCharFmts
.Count() + 1 );
744 pCharFmt
= pDoc
->MakeCharFmt( sNm
,
745 ( SwCharFmt
*)pDoc
->GetDfltCharFmt() );
747 SvxFontHeightItem
aHeightItem( aData
.nFontSize
* 10, 100, RES_CHRATR_FONTSIZE
);
748 aHeightItem
.SetWhich( nFntHWhich
);
750 SvxFontItem
aFontItem( FAMILY_DONTKNOW
, aData
.sFontName
,
751 aEmptyStr
, PITCH_DONTKNOW
, RTL_TEXTENCODING_DONTKNOW
, nFntWhich
);
753 pCharFmt
->SetFmtAttr( aHeightItem
);
754 pCharFmt
->SetFmtAttr( aFontItem
);
756 aRubyCharFmts
.Insert( p
, aRubyCharFmts
.Count() );
760 //Set the charstyle and justification
761 aRuby
.SetCharFmtName( pCharFmt
->GetName() );
762 aRuby
.SetCharFmtId( pCharFmt
->GetPoolFmtId() );
763 aRuby
.SetAdjustment( (USHORT
)aData
.nJustificationCode
);
765 // im FieldStr steht der anzuzeigenden Text, im
766 pDoc
->InsertString( *pPam
, aData
.sText
);
768 pPam
->GetMark()->nContent
-= aData
.sText
.Len();
769 pDoc
->InsertPoolItem( *pPam
, aRuby
,
770 nsSetAttrMode::SETATTR_DONTEXPAND
);
773 // or a combined character field?
774 else if( aData
.sUp
.Len() && aData
.sDown
.Len() &&
775 !aData
.sText
.Len() && !aData
.sFontName
.Len() &&
778 String
sFld( aData
.sUp
);
780 SwCombinedCharField
aFld((SwCombinedCharFieldType
*)pDoc
->
781 GetSysFldType( RES_COMBINED_CHARS
), sFld
);
782 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( aFld
), 0);
785 SkipGroup(); // ueberlese den Rest
792 RtfFieldSwitch
aRFS( aSaveStr
);
793 while( !aRFS
.IsAtEnd() )
796 sal_Unicode cKey
= aRFS
.GetSwitch( sParam
);
799 // In the case of pageref the only parameter we are
800 // interested in, is the name of the bookmark
802 if( !sOrigBkmName
.Len() ) // get name of bookmark
803 sOrigBkmName
= sParam
;
808 (SwGetRefFieldType
*)pDoc
->GetSysFldType( RES_GETREFFLD
),
809 sOrigBkmName
,REF_BOOKMARK
,0,REF_PAGE
);
813 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( aFld
), 0 );
816 bNestedField
= false;
823 bool bChapterNr
= false;
824 bool bAboveBelow
= false;
826 RtfFieldSwitch
aRFS( aSaveStr
);
827 while( !aRFS
.IsAtEnd() )
830 sal_Unicode cKey
= aRFS
.GetSwitch( sParam
);
834 if( !sOrigBkmName
.Len() ) // get name of bookmark
835 sOrigBkmName
= sParam
;
841 bChapterNr
= true; // activate flag 'Chapter Number'
849 if (!bAboveBelow
|| bChapterNr
)
854 (SwGetRefFieldType
*)pDoc
->GetSysFldType( RES_GETREFFLD
),
855 sOrigBkmName
,REF_BOOKMARK
,0,REF_CHAPTER
);
856 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( aFld
), 0 );
861 (SwGetRefFieldType
*)pDoc
->GetSysFldType( RES_GETREFFLD
),
862 sOrigBkmName
,REF_BOOKMARK
,0,REF_CONTENT
);
863 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( aFld
), 0 );
869 SwGetRefField
aFld( (SwGetRefFieldType
*)
870 pDoc
->GetSysFldType( RES_GETREFFLD
), sOrigBkmName
, REF_BOOKMARK
, 0,
872 pDoc
->InsertPoolItem(*pPam
, SwFmtFld(aFld
), 0);
883 // keines von den bekannten Feldern, also eine neues UserField
884 aSaveStr
.EraseLeadingChars().EraseTrailingChars();
885 SwUserFieldType
aTmp( pDoc
, aSaveStr
);
886 SwUserField
aUFld( (SwUserFieldType
*)pDoc
->InsertFldType( aTmp
));
887 aUFld
.ChangeFormat( UF_STRING
);
888 pDoc
->InsertPoolItem( *pPam
, SwFmtFld( aUFld
), 0);
889 nRet
= RTFFLD_UNKNOWN
;
897 void SwRTFParser::ReadXEField()
899 bReadSwFly
= false; //#it may be that any uses of this need to be removed and replaced
900 int nNumOpenBrakets
= 1;
905 while (nNumOpenBrakets
&& IsParserWorking())
907 switch (nToken
= GetNextToken())
915 String
sXE(sFieldStr
);
919 // we have to make sure the hidden text flag is not on
920 // otherwise the index will not see this index mark
921 SfxItemSet
& rSet
= GetAttrSet();
922 const SfxPoolItem
* pItem
;
923 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_CHRATR_HIDDEN
, sal_True
, &pItem
) )
925 SvxCharHiddenItem
aCharHidden(*(SvxCharHiddenItem
*)pItem
);
926 aCharHidden
.SetValue(FALSE
);
927 rSet
.Put(aCharHidden
);
930 sw::ms::ImportXE(*pDoc
, *pPam
, sXE
);
938 if( RTF_IGNOREFLAG
!= GetNextToken() )
940 // Unknown und alle bekannten nicht ausgewerteten Gruppen
941 // sofort ueberspringen
942 else if( RTF_UNKNOWNCONTROL
!= GetNextToken() )
946 // gleich herausfiltern
948 if( '}' != GetNextToken() )
949 eState
= SVPAR_ERROR
;
958 sFieldStr
+= (sal_Unicode
)nTokenValue
;
964 case RTF_LINE
: cCh
= '\n'; goto INSINGLECHAR
;
965 case RTF_TAB
: cCh
= '\t'; goto INSINGLECHAR
;
966 case RTF_SUBENTRYINDEX
: cCh
= ':'; goto INSINGLECHAR
;
967 case RTF_EMDASH
: cCh
= 151; goto INSINGLECHAR
;
968 case RTF_ENDASH
: cCh
= 150; goto INSINGLECHAR
;
969 case RTF_BULLET
: cCh
= 149; goto INSINGLECHAR
;
970 case RTF_LQUOTE
: cCh
= 145; goto INSINGLECHAR
;
971 case RTF_RQUOTE
: cCh
= 146; goto INSINGLECHAR
;
972 case RTF_LDBLQUOTE
: cCh
= 147; goto INSINGLECHAR
;
973 case RTF_RDBLQUOTE
: cCh
= 148; goto INSINGLECHAR
;
975 sFieldStr
+= ByteString::ConvertToUnicode( cCh
,
976 RTL_TEXTENCODING_MS_1252
);
979 // kein Break, aToken wird als Text gesetzt
993 sFieldStr
.Append('\x0a');
996 SvxRTFParser::NextToken( nToken
);
1001 SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet
1005 void SwRTFParser::ReadField()
1007 bReadSwFly
= false; //#it may be that any uses of this need to be removed and replaced
1009 int nNumOpenBrakets
= 1; // die erste wurde schon vorher erkannt !!
1010 int bFldInst
= FALSE
, bFldRslt
= FALSE
;
1011 String sFieldStr
, sFieldNm
;
1015 while (nNumOpenBrakets
&& IsParserWorking())
1017 switch (nToken
= GetNextToken())
1022 if( 1 != nNumOpenBrakets
|| !bFldInst
)
1027 // FieldInst vollstaendig eingelesen, was ist es denn?
1028 nRet
= MakeFieldInst( sFieldStr
);
1031 case RTFFLD_INCLUDETEXT
:
1034 // erstmal Index/Inhaltsverzeichniss ueberspringen
1035 // und als normalen Text einfuegen. Spaeter mal auch dem
1036 // SwPaM darum aufspannen.
1040 case RTFFLD_HYPERLINK
:
1041 sFieldNm
= sFieldStr
;
1046 else if (RTFFLD_UNKNOWN
== nRet
)
1048 // FieldResult wurde eingelesen
1049 if (SwTxtNode
* pTxtNd
= pPam
->GetPoint()->nNode
.GetNode().GetTxtNode())
1051 SwTxtAttr
* const pFldAttr
=
1052 pTxtNd
->GetTxtAttrForCharAt(
1053 pPam
->GetPoint()->nContent
.GetIndex()-1 );
1057 const SwField
*pFld
= pFldAttr
->GetFld().GetFld();
1058 SwFieldType
*pTyp
= pFld
? pFld
->GetTyp() : 0;
1059 ASSERT(pTyp
->Which() == RES_USERFLD
, "expected a user field");
1060 if (pTyp
->Which() == RES_USERFLD
)
1062 SwUserFieldType
*pUsrTyp
= (SwUserFieldType
*)pTyp
;
1063 pUsrTyp
->SetContent(sFieldStr
);
1068 else if( sFieldNm
.Len() )
1074 InsPicture( sFieldNm
);
1077 case RTFFLD_HYPERLINK
:
1078 if( sFieldStr
.Len() )
1080 if(sNestedFieldStr
.Len())
1081 sFieldStr
.Insert(sNestedFieldStr
);
1083 sNestedFieldStr
.Erase();
1084 // im FieldStr steht der anzuzeigenden Text, im
1085 pDoc
->InsertString( *pPam
, sFieldStr
);
1087 String
sTarget( sFieldNm
.GetToken( 1, '\1' ));
1089 sFieldNm
.Erase( sFieldNm
.Len() - sTarget
.Len() -1 );
1091 // oder ueber den Stack setzen??
1093 pPam
->GetMark()->nContent
-= sFieldStr
.Len();
1094 pDoc
->InsertPoolItem( *pPam
,
1095 SwFmtINetFmt( sFieldNm
, sTarget
),
1096 nsSetAttrMode::SETATTR_DONTEXPAND
);
1103 else if(bNestedField
)
1105 if(nRet
== RTFFLD_PAGEREF
)
1107 // #17371 Nasty hack to get a pageref within a hyperlink working
1108 sNestedFieldStr
= sFieldStr
;
1117 if( RTF_IGNOREFLAG
!= GetNextToken() )
1119 // Unknown und alle bekannten nicht ausgewerteten Gruppen
1120 // sofort ueberspringen
1121 else if( RTF_UNKNOWNCONTROL
!= GetNextToken() )
1125 // gleich herausfiltern
1127 if( '}' != GetNextToken() )
1128 eState
= SVPAR_ERROR
;
1139 bNestedField
= true;
1154 sFieldStr
+= (sal_Unicode
)nTokenValue
;
1156 sFieldStr
+= aToken
;
1160 case RTF_LINE
: cCh
= '\n'; goto INSINGLECHAR
;
1161 case RTF_TAB
: cCh
= '\t'; goto INSINGLECHAR
;
1162 case RTF_SUBENTRYINDEX
: cCh
= ':'; goto INSINGLECHAR
;
1163 case RTF_EMDASH
: cCh
= 151; goto INSINGLECHAR
;
1164 case RTF_ENDASH
: cCh
= 150; goto INSINGLECHAR
;
1165 case RTF_BULLET
: cCh
= 149; goto INSINGLECHAR
;
1166 case RTF_LQUOTE
: cCh
= 145; goto INSINGLECHAR
;
1167 case RTF_RQUOTE
: cCh
= 146; goto INSINGLECHAR
;
1168 case RTF_LDBLQUOTE
: cCh
= 147; goto INSINGLECHAR
;
1169 case RTF_RDBLQUOTE
: cCh
= 148; goto INSINGLECHAR
;
1171 sFieldStr
+= ByteString::ConvertToUnicode( cCh
,
1172 RTL_TEXTENCODING_MS_1252
);
1175 // kein Break, aToken wird als Text gesetzt
1177 sFieldStr
+= aToken
;
1180 case RTF_PICT
: // Pic-Daten einlesen!
1181 if( RTFFLD_IMPORT
== nRet
)
1184 SvxRTFPictureType aPicType
;
1185 if( ReadBmpData( aGrf
, aPicType
) )
1187 InsPicture( sFieldNm
, &aGrf
, &aPicType
);
1204 // we write every time "EQ "
1205 if( bFldInst
&& 0 == sFieldStr
.SearchAscii( "EQ " ))
1207 // insert behind the EQ the "\*cs<NO> " string. This is utilize
1208 // in the MakeFieldInst
1210 (sTmp
.AssignAscii( "\\* cs" )
1211 += String::CreateFromInt32( nTokenValue
)) += ' ';
1212 sFieldStr
.Insert( sTmp
, 3 );
1219 sFieldStr
.Append('\x0a');
1222 SvxRTFParser::NextToken( nToken
);
1228 if (RTFFLD_IMPORT
== nRet
&& sFieldNm
.Len())
1229 InsPicture( sFieldNm
);
1231 SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet
1234 /* vi:set tabstop=4 shiftwidth=4 expandtab: */