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: htmlfld.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"
36 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
37 #include <com/sun/star/document/XDocumentProperties.hpp>
40 #include <svtools/htmltokn.h>
41 #include <svtools/zformat.hxx>
42 #include <svtools/useroptions.hxx>
47 #include <docufld.hxx>
49 #include <htmlfld.hxx>
52 using namespace nsSwDocInfoSubType
;
53 using namespace ::com::sun::star
;
55 struct HTMLNumFmtTblEntry
57 const sal_Char
*pName
;
58 NfIndexTableOffset eFmt
;
61 static HTMLOptionEnum __FAR_DATA aHTMLFldTypeTable
[] =
63 { OOO_STRING_SW_HTML_FT_author
, RES_AUTHORFLD
},
64 { OOO_STRING_SW_HTML_FT_sender
, RES_EXTUSERFLD
},
65 { "DATE", RES_DATEFLD
},
66 { "TIME", RES_TIMEFLD
},
67 { OOO_STRING_SW_HTML_FT_datetime
,RES_DATETIMEFLD
},
68 { OOO_STRING_SW_HTML_FT_page
, RES_PAGENUMBERFLD
},
69 { OOO_STRING_SW_HTML_FT_docinfo
, RES_DOCINFOFLD
},
70 { OOO_STRING_SW_HTML_FT_docstat
, RES_DOCSTATFLD
},
71 { OOO_STRING_SW_HTML_FT_filename
,RES_FILENAMEFLD
},
75 static HTMLNumFmtTblEntry __FAR_DATA aHTMLDateFldFmtTable
[] =
77 { "SSYS", NF_DATE_SYSTEM_SHORT
},
78 { "LSYS", NF_DATE_SYSTEM_LONG
},
79 { "DMY", NF_DATE_SYS_DDMMYY
, },
80 { "DMYY", NF_DATE_SYS_DDMMYYYY
, },
81 { "DMMY", NF_DATE_SYS_DMMMYY
, },
82 { "DMMYY", NF_DATE_SYS_DMMMYYYY
, },
83 { "DMMMY", NF_DATE_DIN_DMMMMYYYY
},
84 { "DMMMYY", NF_DATE_DIN_DMMMMYYYY
},
85 { "DDMMY", NF_DATE_SYS_NNDMMMYY
},
86 { "DDMMMY", NF_DATE_SYS_NNDMMMMYYYY
},
87 { "DDMMMYY", NF_DATE_SYS_NNDMMMMYYYY
},
88 { "DDDMMMY", NF_DATE_SYS_NNNNDMMMMYYYY
},
89 { "DDDMMMYY", NF_DATE_SYS_NNNNDMMMMYYYY
},
90 { "MY", NF_DATE_SYS_MMYY
},
91 { "MD", NF_DATE_DIN_MMDD
},
92 { "YMD", NF_DATE_DIN_YYMMDD
},
93 { "YYMD", NF_DATE_DIN_YYYYMMDD
},
94 { 0, NF_NUMERIC_START
}
97 static HTMLNumFmtTblEntry __FAR_DATA aHTMLTimeFldFmtTable
[] =
99 { "SYS", NF_TIME_HHMMSS
},
100 { "SSMM24", NF_TIME_HHMM
},
101 { "SSMM12", NF_TIME_HHMMAMPM
},
102 { 0, NF_NUMERIC_START
}
105 static HTMLOptionEnum __FAR_DATA aHTMLPageNumFldFmtTable
[] =
107 { OOO_STRING_SW_HTML_FF_uletter
, SVX_NUM_CHARS_UPPER_LETTER
},
108 { OOO_STRING_SW_HTML_FF_lletter
, SVX_NUM_CHARS_LOWER_LETTER
},
109 { OOO_STRING_SW_HTML_FF_uroman
, SVX_NUM_ROMAN_UPPER
},
110 { OOO_STRING_SW_HTML_FF_lroman
, SVX_NUM_ROMAN_LOWER
},
111 { OOO_STRING_SW_HTML_FF_arabic
, SVX_NUM_ARABIC
},
112 { OOO_STRING_SW_HTML_FF_none
, SVX_NUM_NUMBER_NONE
},
113 { OOO_STRING_SW_HTML_FF_char
, SVX_NUM_CHAR_SPECIAL
},
114 { OOO_STRING_SW_HTML_FF_page
, SVX_NUM_PAGEDESC
},
115 { OOO_STRING_SW_HTML_FF_ulettern
, SVX_NUM_CHARS_UPPER_LETTER_N
},
116 { OOO_STRING_SW_HTML_FF_llettern
, SVX_NUM_CHARS_LOWER_LETTER_N
},
121 static HTMLOptionEnum __FAR_DATA aHTMLExtUsrFldSubTable
[] =
123 { OOO_STRING_SW_HTML_FS_company
, EU_COMPANY
},
124 { OOO_STRING_SW_HTML_FS_firstname
, EU_FIRSTNAME
},
125 { OOO_STRING_SW_HTML_FS_name
, EU_NAME
},
126 { OOO_STRING_SW_HTML_FS_shortcut
, EU_SHORTCUT
},
127 { OOO_STRING_SW_HTML_FS_street
, EU_STREET
},
128 { OOO_STRING_SW_HTML_FS_country
, EU_COUNTRY
},
129 { OOO_STRING_SW_HTML_FS_zip
, EU_ZIP
},
130 { OOO_STRING_SW_HTML_FS_city
, EU_CITY
},
131 { OOO_STRING_SW_HTML_FS_title
, EU_TITLE
},
132 { OOO_STRING_SW_HTML_FS_position
, EU_POSITION
},
133 { OOO_STRING_SW_HTML_FS_pphone
, EU_PHONE_PRIVATE
},
134 { OOO_STRING_SW_HTML_FS_cphone
, EU_PHONE_COMPANY
},
135 { OOO_STRING_SW_HTML_FS_fax
, EU_FAX
},
136 { OOO_STRING_SW_HTML_FS_email
, EU_EMAIL
},
137 { OOO_STRING_SW_HTML_FS_state
, EU_STATE
},
141 static HTMLOptionEnum __FAR_DATA aHTMLAuthorFldFmtTable
[] =
143 { OOO_STRING_SW_HTML_FF_name
, AF_NAME
},
144 { OOO_STRING_SW_HTML_FF_shortcut
, AF_SHORTCUT
},
148 static HTMLOptionEnum __FAR_DATA aHTMLPageNumFldSubTable
[] =
150 { OOO_STRING_SW_HTML_FS_random
, PG_RANDOM
},
151 { OOO_STRING_SW_HTML_FS_next
, PG_NEXT
},
152 { OOO_STRING_SW_HTML_FS_prev
, PG_PREV
},
156 // UGLY: these are extensions of nsSwDocInfoSubType (in inc/docufld.hxx)
157 // these are necessary for importing document info fields written by
158 // older versions of OOo (< 3.0) which did not have DI_CUSTOM fields
159 const SwDocInfoSubType DI_INFO1
= DI_SUBTYPE_END
+ 1;
160 const SwDocInfoSubType DI_INFO2
= DI_SUBTYPE_END
+ 2;
161 const SwDocInfoSubType DI_INFO3
= DI_SUBTYPE_END
+ 3;
162 const SwDocInfoSubType DI_INFO4
= DI_SUBTYPE_END
+ 4;
164 static HTMLOptionEnum __FAR_DATA aHTMLDocInfoFldSubTable
[] =
166 { OOO_STRING_SW_HTML_FS_title
, DI_TITEL
},
167 { OOO_STRING_SW_HTML_FS_theme
, DI_THEMA
},
168 { OOO_STRING_SW_HTML_FS_keys
, DI_KEYS
},
169 { OOO_STRING_SW_HTML_FS_comment
, DI_COMMENT
},
170 { "INFO1", DI_INFO1
},
171 { "INFO2", DI_INFO2
},
172 { "INFO3", DI_INFO3
},
173 { "INFO4", DI_INFO4
},
174 { OOO_STRING_SW_HTML_FS_custom
, DI_CUSTOM
},
175 { OOO_STRING_SW_HTML_FS_create
, DI_CREATE
},
176 { OOO_STRING_SW_HTML_FS_change
, DI_CHANGE
},
180 static HTMLOptionEnum __FAR_DATA aHTMLDocInfoFldFmtTable
[] =
182 { OOO_STRING_SW_HTML_FF_author
, DI_SUB_AUTHOR
},
183 { OOO_STRING_SW_HTML_FF_time
, DI_SUB_TIME
},
184 { OOO_STRING_SW_HTML_FF_date
, DI_SUB_DATE
},
188 static HTMLOptionEnum __FAR_DATA aHTMLDocStatFldSubTable
[] =
190 { OOO_STRING_SW_HTML_FS_page
, DS_PAGE
},
191 { OOO_STRING_SW_HTML_FS_para
, DS_PARA
},
192 { OOO_STRING_SW_HTML_FS_word
, DS_WORD
},
193 { OOO_STRING_SW_HTML_FS_char
, DS_CHAR
},
194 { OOO_STRING_SW_HTML_FS_tbl
, DS_TBL
},
195 { OOO_STRING_SW_HTML_FS_grf
, DS_GRF
},
196 { OOO_STRING_SW_HTML_FS_ole
, DS_OLE
},
200 static HTMLOptionEnum __FAR_DATA aHTMLFileNameFldFmtTable
[] =
202 { OOO_STRING_SW_HTML_FF_name
, FF_NAME
},
203 { OOO_STRING_SW_HTML_FF_pathname
, FF_PATHNAME
},
204 { OOO_STRING_SW_HTML_FF_path
, FF_PATH
},
205 { OOO_STRING_SW_HTML_FF_name_noext
, FF_NAME_NOEXT
},
211 USHORT
SwHTMLParser::GetNumType( const String
& rStr
, USHORT nDfltType
)
213 USHORT nType
= nDfltType
;
214 const HTMLOptionEnum
*pOptEnums
= aHTMLPageNumFldFmtTable
;
215 while( pOptEnums
->pName
)
216 if( !rStr
.EqualsIgnoreCaseAscii( pOptEnums
->pName
) )
221 if( pOptEnums
->pName
)
222 nType
= pOptEnums
->nValue
;
228 void SwHTMLParser::NewField()
230 BOOL bKnownType
= FALSE
, bFixed
= FALSE
,
231 bHasNumFmt
= FALSE
, bHasNumValue
= FALSE
;
233 String aValue
, aNumFmt
, aNumValue
, aName
;
234 const HTMLOption
*pSubOption
=0, *pFmtOption
=0;
236 const HTMLOptions
*pHTMLOptions
= GetOptions();
239 for( i
= pHTMLOptions
->Count(); i
; )
241 const HTMLOption
*pOption
= (*pHTMLOptions
)[--i
];
242 switch( pOption
->GetToken() )
245 bKnownType
= pOption
->GetEnum( nType
, aHTMLFldTypeTable
);
248 pSubOption
= pOption
;
251 pFmtOption
= pOption
;
254 aName
= pOption
->GetString();
257 aValue
= pOption
->GetString();
260 aNumFmt
= pOption
->GetString();
264 aNumValue
= pOption
->GetString();
276 // Autor und Absender werden nur als als variables Feld eingefuegt,
277 // wenn man das Dok selbst als letztes geaendert hat oder es noch
278 // niemend geandert hat und man das Dok erstellt hat. Sonst
279 // wird ein Fixed-Feld daraus gemacht.
281 (RES_EXTUSERFLD
== (RES_FIELDS
)nType
||
282 RES_AUTHORFLD
== (RES_FIELDS
)nType
) )
285 const String
& rUser
= aOpt
.GetFullName();
286 SwDocShell
*pDocShell(pDoc
->GetDocShell());
287 DBG_ASSERT(pDocShell
, "no SwDocShell");
289 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
290 pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
291 uno::Reference
<document::XDocumentProperties
> xDocProps(
292 xDPS
->getDocumentProperties());
293 DBG_ASSERT(xDocProps
.is(), "Doc has no DocumentProperties");
294 const String
& rChanged
= xDocProps
->getModifiedBy();
295 const String
& rCreated
= xDocProps
->getAuthor();
297 (rChanged
.Len() ? rUser
!= rChanged
: rUser
!= rCreated
) )
302 USHORT nWhich
= nType
;
303 if( RES_DATEFLD
==nType
|| RES_TIMEFLD
==nType
)
304 nWhich
= RES_DATETIMEFLD
;
306 SwFieldType
* pType
= pDoc
->GetSysFldType( nWhich
);
308 BOOL bInsOnEndTag
= FALSE
;
310 switch( (RES_FIELDS
)nType
)
322 if( pSubOption
->GetEnum( nSub
, aHTMLExtUsrFldSubTable
) )
323 pFld
= new SwExtUserField( (SwExtUserFieldType
*)pType
,
330 USHORT nFmt
= AF_NAME
;
332 pFmtOption
->GetEnum( nFmt
, aHTMLAuthorFldFmtTable
);
339 pFld
= new SwAuthorField( (SwAuthorFieldType
*)pType
, nFmt
);
347 ULONG nTime
= Time().GetTime(), nDate
= Date().GetDate();
349 BOOL bValidFmt
= FALSE
;
350 HTMLNumFmtTblEntry
* pFmtTbl
;
352 if( RES_DATEFLD
==nType
)
355 pFmtTbl
= aHTMLDateFldFmtTable
;
357 nDate
= (ULONG
)aValue
.ToInt32();
362 pFmtTbl
= aHTMLTimeFldFmtTable
;
364 nTime
= (ULONG
)aValue
.ToInt32();
369 SvNumberFormatter
*pFormatter
= pDoc
->GetNumberFormatter();
372 const String
& rFmt
= pFmtOption
->GetString();
373 for( USHORT k
= 0; pFmtTbl
[k
].pName
; k
++ )
375 if( rFmt
.EqualsIgnoreCaseAscii( pFmtTbl
[k
].pName
) )
377 nNumFmt
= pFormatter
->GetFormatIndex(
378 pFmtTbl
[k
].eFmt
, LANGUAGE_SYSTEM
);
385 nNumFmt
= pFormatter
->GetFormatIndex( pFmtTbl
[i
].eFmt
,
388 pFld
= new SwDateTimeField( (SwDateTimeFieldType
*)pType
,
392 ((SwDateTimeField
*)pFld
)->SetDateTime( DateTime(Date(nDate
), Time(nTime
)) );
396 case RES_DATETIMEFLD
:
401 SvNumberFormatter
*pFormatter
= pDoc
->GetNumberFormatter();
404 double dValue
= GetTableDataOptionsValNum(
405 nNumFmt
, eLang
, aNumValue
, aNumFmt
,
406 *pDoc
->GetNumberFormatter() );
407 short nFmtType
= pFormatter
->GetType( nNumFmt
);
410 case NUMBERFORMAT_DATE
: nSub
= DATEFLD
; break;
411 case NUMBERFORMAT_TIME
: nSub
= TIMEFLD
; break;
419 pFld
= new SwDateTimeField( (SwDateTimeFieldType
*)pType
,
422 ((SwDateTimeField
*)pFld
)->SetValue( dValue
);
427 case RES_PAGENUMBERFLD
:
431 if( pSubOption
->GetEnum( nSub
, aHTMLPageNumFldSubTable
) )
433 USHORT nFmt
= SVX_NUM_PAGEDESC
;
435 pFmtOption
->GetEnum( nFmt
, aHTMLPageNumFldFmtTable
);
439 if( (SvxExtNumType
)nFmt
!=SVX_NUM_CHAR_SPECIAL
&& aValue
.Len() )
440 nOff
= (short)aValue
.ToInt32();
441 else if( (SwPageNumSubType
)nSub
== PG_NEXT
)
443 else if( (SwPageNumSubType
)nSub
== PG_PREV
)
446 if( (SvxExtNumType
)nFmt
==SVX_NUM_CHAR_SPECIAL
&&
447 (SwPageNumSubType
)nSub
==PG_RANDOM
)
448 nFmt
= SVX_NUM_PAGEDESC
;
450 pFld
= new SwPageNumberField( (SwPageNumberFieldType
*)pType
, nSub
, nFmt
, nOff
);
451 if( (SvxExtNumType
)nFmt
==SVX_NUM_CHAR_SPECIAL
)
452 ((SwPageNumberField
*)pFld
)->SetUserString( aValue
);
461 if( pSubOption
->GetEnum( nSub
, aHTMLDocInfoFldSubTable
) )
464 if( DI_CREATE
==(SwDocInfoSubType
)nSub
||
465 DI_CHANGE
==(SwDocInfoSubType
)nSub
)
467 nExtSub
= DI_SUB_AUTHOR
;
469 pFmtOption
->GetEnum( nExtSub
, aHTMLDocInfoFldFmtTable
);
473 sal_uInt32 nNumFmt
= 0;
475 if( bHasNumFmt
&& (DI_SUB_DATE
==nExtSub
|| DI_SUB_TIME
==nExtSub
) )
478 dValue
= GetTableDataOptionsValNum(
479 nNumFmt
, eLang
, aNumValue
, aNumFmt
,
480 *pDoc
->GetNumberFormatter() );
481 bFixed
&= bHasNumValue
;
484 bHasNumValue
= FALSE
;
486 if( nSub
>= DI_INFO1
&& nSub
<= DI_INFO4
&& aName
.Len() == 0 )
488 // backward compatibility for OOo 2:
489 // map to names stored in AddMetaUserDefined
490 aName
= m_InfoNames
[nSub
- DI_INFO1
];
496 nSub
|= DI_SUB_FIXED
;
500 pFld
= new SwDocInfoField( (SwDocInfoFieldType
*)pType
,
501 nSub
, aName
, nNumFmt
);
503 ((SwDocInfoField
*)pFld
)->SetValue( dValue
);
512 if( pSubOption
->GetEnum( nSub
, aHTMLDocStatFldSubTable
) )
514 USHORT nFmt
= SVX_NUM_ARABIC
;
516 pFmtOption
->GetEnum( nFmt
, aHTMLPageNumFldFmtTable
);
517 pFld
= new SwDocStatField( (SwDocStatFieldType
*)pType
,
519 bUpdateDocStat
|= (DS_PAGE
!= nFmt
);
524 case RES_FILENAMEFLD
:
526 USHORT nFmt
= FF_NAME
;
528 pFmtOption
->GetEnum( nFmt
, aHTMLFileNameFldFmtTable
);
535 pFld
= new SwFileNameField( (SwFileNameFieldType
*)pType
, nFmt
);
550 pDoc
->InsertPoolItem( *pPam
, SwFmtFld(*pFld
), 0 );
557 void SwHTMLParser::EndField()
561 switch( pField
->Which() )
564 ASSERT( ((SwDocInfoField
*)pField
)->IsFixed(),
565 "DokInfo-Feld haette nicht gemerkt werden muessen" );
566 ((SwDocInfoField
*)pField
)->SetExpansion( aContents
);
570 ASSERT( ((SwExtUserField
*)pField
)->IsFixed(),
571 "ExtUser-Feld haette nicht gemerkt werden muessen" );
572 ((SwExtUserField
*)pField
)->SetExpansion( aContents
);
576 ASSERT( ((SwAuthorField
*)pField
)->IsFixed(),
577 "Author-Feld haette nicht gemerkt werden muessen" );
578 ((SwAuthorField
*)pField
)->SetExpansion( aContents
);
581 case RES_FILENAMEFLD
:
582 ASSERT( ((SwFileNameField
*)pField
)->IsFixed(),
583 "FileName-Feld haette nicht gemerkt werden muessen" );
584 ((SwFileNameField
*)pField
)->SetExpansion( aContents
);
588 pDoc
->InsertPoolItem( *pPam
, SwFmtFld(*pField
), 0 );
597 void SwHTMLParser::InsertFieldText()
601 // das aktuelle Textstueck an den Text anhaengen
606 void SwHTMLParser::InsertCommentText( const sal_Char
*pTag
)
608 BOOL bEmpty
= aContents
.Len() == 0;
615 String
aTmp( aContents
);
616 aContents
.AssignAscii( "HTML: <" );
617 aContents
.AppendAscii( pTag
);
618 aContents
.Append( '>' );
619 aContents
.Append( aTmp
);
623 void SwHTMLParser::InsertComment( const String
& rComment
, const sal_Char
*pTag
)
625 String
aComment( rComment
);
628 aComment
.AppendAscii( "</" );
629 aComment
.AppendAscii( pTag
);
630 aComment
.Append( '>' );
633 // MIB 24.06.97: Wenn ein PostIt nach einen Space eingefuegt
634 // werden soll, fuegen wir es vor dem Space ein. Dann gibt es
635 // weniger Probleme beim Formatieren (bug #40483#)
636 xub_StrLen nPos
= pPam
->GetPoint()->nContent
.GetIndex();
637 SwTxtNode
*pTxtNd
= pPam
->GetNode()->GetTxtNode();
638 BOOL bMoveFwd
= FALSE
;
639 if( nPos
>0 && pTxtNd
&& ' '==pTxtNd
->GetTxt().GetChar(nPos
-1) )
643 ULONG nNodeIdx
= pPam
->GetPoint()->nNode
.GetIndex();
644 xub_StrLen nIdx
= pPam
->GetPoint()->nContent
.GetIndex();
645 for( USHORT i
= aSetAttrTab
.Count(); i
> 0; )
647 _HTMLAttr
*pAttr
= aSetAttrTab
[--i
];
648 if( pAttr
->GetSttParaIdx() != nNodeIdx
||
649 pAttr
->GetSttCnt() != nIdx
)
652 if( RES_TXTATR_FIELD
== pAttr
->pItem
->Which() &&
653 RES_SCRIPTFLD
== ((const SwFmtFld
*)pAttr
->pItem
)->GetFld()
654 ->GetTyp()->Which() )
662 pPam
->Move( fnMoveBackward
);
665 SwPostItField
aPostItFld(
666 (SwPostItFieldType
*)pDoc
->GetSysFldType( RES_POSTITFLD
),
667 aEmptyStr
, aComment
, DateTime() );
668 InsertAttr( SwFmtFld( aPostItFld
) );
671 pPam
->Move( fnMoveForward
);