1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
21 #include <com/sun/star/document/XDocumentProperties.hpp>
22 #include <com/sun/star/frame/XModel.hpp>
23 #include <osl/diagnose.h>
24 #include <docsh.hxx>
25 #include <IDocumentFieldsAccess.hxx>
26 #include <svtools/htmltokn.h>
27 #include <svl/zforlist.hxx>
28 #include <unotools/useroptions.hxx>
29 #include <fmtfld.hxx>
30 #include <ndtxt.hxx>
31 #include <doc.hxx>
32 #include <fldbas.hxx>
33 #include <docufld.hxx>
34 #include <flddat.hxx>
35 #include "htmlfld.hxx"
36 #include "swhtml.hxx"
37 
38 using namespace nsSwDocInfoSubType;
39 using namespace ::com::sun::star;
40 
41 namespace {
42 
43 struct HTMLNumFormatTableEntry
44 {
45     const char *pName;
46     NfIndexTableOffset eFormat;
47 };
48 
49 }
50 
51 HTMLOptionEnum<SwFieldIds> const aHTMLFieldTypeTable[] =
52 {
53     { OOO_STRING_SW_HTML_FT_author,   SwFieldIds::Author      },
54     { OOO_STRING_SW_HTML_FT_sender,   SwFieldIds::ExtUser     },
55     { "DATE",                         SwFieldIds::Date        },
56     { "TIME",                         SwFieldIds::Time        },
57     { OOO_STRING_SW_HTML_FT_datetime, SwFieldIds::DateTime    },
58     { OOO_STRING_SW_HTML_FT_page,     SwFieldIds::PageNumber  },
59     { OOO_STRING_SW_HTML_FT_docinfo,  SwFieldIds::DocInfo     },
60     { OOO_STRING_SW_HTML_FT_docstat,  SwFieldIds::DocStat     },
61     { OOO_STRING_SW_HTML_FT_filename, SwFieldIds::Filename    },
62     { nullptr,                        SwFieldIds(0)           }
63 };
64 
65 HTMLNumFormatTableEntry const aHTMLDateFieldFormatTable[] =
66 {
67     { "SSYS",       NF_DATE_SYSTEM_SHORT    },
68     { "LSYS",       NF_DATE_SYSTEM_LONG     },
69     { "DMY",        NF_DATE_SYS_DDMMYY,     },
70     { "DMYY",       NF_DATE_SYS_DDMMYYYY,   },
71     { "DMMY",       NF_DATE_SYS_DMMMYY,     },
72     { "DMMYY",      NF_DATE_SYS_DMMMYYYY,   },
73     { "DMMMY",      NF_DATE_DIN_DMMMMYYYY   },
74     { "DMMMYY",         NF_DATE_DIN_DMMMMYYYY   },
75     { "DDMMY",      NF_DATE_SYS_NNDMMMYY    },
76     { "DDMMMY",         NF_DATE_SYS_NNDMMMMYYYY },
77     { "DDMMMYY",    NF_DATE_SYS_NNDMMMMYYYY },
78     { "DDDMMMY",    NF_DATE_SYS_NNNNDMMMMYYYY },
79     { "DDDMMMYY",   NF_DATE_SYS_NNNNDMMMMYYYY },
80     { "MY",             NF_DATE_SYS_MMYY        },
81     { "MD",             NF_DATE_DIN_MMDD        },
82     { "YMD",        NF_DATE_DIN_YYMMDD      },
83     { "YYMD",       NF_DATE_DIN_YYYYMMDD    },
84     { nullptr,                    NF_NUMERIC_START }
85 };
86 
87 HTMLNumFormatTableEntry const aHTMLTimeFieldFormatTable[] =
88 {
89     { "SYS",     NF_TIME_HHMMSS },
90     { "SSMM24",      NF_TIME_HHMM },
91     { "SSMM12",      NF_TIME_HHMMAMPM },
92     { nullptr,                 NF_NUMERIC_START }
93 };
94 
95 HTMLOptionEnum<SvxNumType> const aHTMLPageNumFieldFormatTable[] =
96 {
97     { OOO_STRING_SW_HTML_FF_uletter,     SVX_NUM_CHARS_UPPER_LETTER },
98     { OOO_STRING_SW_HTML_FF_lletter,     SVX_NUM_CHARS_LOWER_LETTER },
99     { OOO_STRING_SW_HTML_FF_uroman,      SVX_NUM_ROMAN_UPPER },
100     { OOO_STRING_SW_HTML_FF_lroman,      SVX_NUM_ROMAN_LOWER },
101     { OOO_STRING_SW_HTML_FF_arabic,      SVX_NUM_ARABIC },
102     { OOO_STRING_SW_HTML_FF_none,        SVX_NUM_NUMBER_NONE },
103     { OOO_STRING_SW_HTML_FF_char,        SVX_NUM_CHAR_SPECIAL },
104     { OOO_STRING_SW_HTML_FF_page,        SVX_NUM_PAGEDESC },
105     { OOO_STRING_SW_HTML_FF_ulettern,    SVX_NUM_CHARS_UPPER_LETTER_N },
106     { OOO_STRING_SW_HTML_FF_llettern,    SVX_NUM_CHARS_LOWER_LETTER_N },
107     { nullptr,                           SvxNumType(0) }
108 };
109 
110 HTMLOptionEnum<SwExtUserSubType> const aHTMLExtUsrFieldSubTable[] =
111 {
112     { OOO_STRING_SW_HTML_FS_company,     EU_COMPANY },
113     { OOO_STRING_SW_HTML_FS_firstname,   EU_FIRSTNAME },
114     { OOO_STRING_SW_HTML_FS_name,        EU_NAME },
115     { OOO_STRING_SW_HTML_FS_shortcut,    EU_SHORTCUT },
116     { OOO_STRING_SW_HTML_FS_street,      EU_STREET },
117     { OOO_STRING_SW_HTML_FS_country,     EU_COUNTRY },
118     { OOO_STRING_SW_HTML_FS_zip,         EU_ZIP },
119     { OOO_STRING_SW_HTML_FS_city,        EU_CITY },
120     { OOO_STRING_SW_HTML_FS_title,       EU_TITLE },
121     { OOO_STRING_SW_HTML_FS_position,    EU_POSITION },
122     { OOO_STRING_SW_HTML_FS_pphone,      EU_PHONE_PRIVATE },
123     { OOO_STRING_SW_HTML_FS_cphone,      EU_PHONE_COMPANY },
124     { OOO_STRING_SW_HTML_FS_fax,         EU_FAX },
125     { OOO_STRING_SW_HTML_FS_email,       EU_EMAIL },
126     { OOO_STRING_SW_HTML_FS_state,       EU_STATE },
127     { nullptr,                           SwExtUserSubType(0) }
128 };
129 
130 HTMLOptionEnum<SwAuthorFormat> const aHTMLAuthorFieldFormatTable[] =
131 {
132     { OOO_STRING_SW_HTML_FF_name,        AF_NAME },
133     { OOO_STRING_SW_HTML_FF_shortcut,    AF_SHORTCUT },
134     { nullptr,                           SwAuthorFormat(0) }
135 };
136 
137 HTMLOptionEnum<SwPageNumSubType> const aHTMLPageNumFieldSubTable[] =
138 {
139     { OOO_STRING_SW_HTML_FS_random,      PG_RANDOM },
140     { OOO_STRING_SW_HTML_FS_next,        PG_NEXT },
141     { OOO_STRING_SW_HTML_FS_prev,        PG_PREV },
142     { nullptr,                           SwPageNumSubType(0)  }
143 };
144 
145 // UGLY: these are extensions of nsSwDocInfoSubType (in inc/docufld.hxx)
146 //       these are necessary for importing document info fields written by
147 //       older versions of OOo (< 3.0) which did not have DI_CUSTOM fields
148     const SwDocInfoSubType DI_INFO1         =  DI_SUBTYPE_END + 1;
149     const SwDocInfoSubType DI_INFO2         =  DI_SUBTYPE_END + 2;
150     const SwDocInfoSubType DI_INFO3         =  DI_SUBTYPE_END + 3;
151     const SwDocInfoSubType DI_INFO4         =  DI_SUBTYPE_END + 4;
152 
153 HTMLOptionEnum<sal_uInt16> const aHTMLDocInfoFieldSubTable[] =
154 {
155     { OOO_STRING_SW_HTML_FS_title,   DI_TITLE },
156     { OOO_STRING_SW_HTML_FS_theme,   DI_SUBJECT },
157     { OOO_STRING_SW_HTML_FS_keys,    DI_KEYS },
158     { OOO_STRING_SW_HTML_FS_comment, DI_COMMENT },
159     { "INFO1",                       DI_INFO1 },
160     { "INFO2",                       DI_INFO2 },
161     { "INFO3",                       DI_INFO3 },
162     { "INFO4",                       DI_INFO4 },
163     { OOO_STRING_SW_HTML_FS_custom,  DI_CUSTOM },
164     { OOO_STRING_SW_HTML_FS_create,  DI_CREATE },
165     { OOO_STRING_SW_HTML_FS_change,  DI_CHANGE },
166     { nullptr,                       0 }
167 };
168 
169 HTMLOptionEnum<sal_uInt16> const aHTMLDocInfoFieldFormatTable[] =
170 {
171     { OOO_STRING_SW_HTML_FF_author,  DI_SUB_AUTHOR },
172     { OOO_STRING_SW_HTML_FF_time,    DI_SUB_TIME },
173     { OOO_STRING_SW_HTML_FF_date,    DI_SUB_DATE },
174     { nullptr,                       0 }
175 };
176 
177 HTMLOptionEnum<SwDocStatSubType> const aHTMLDocStatFieldSubTable[] =
178 {
179     { OOO_STRING_SW_HTML_FS_page,    DS_PAGE },
180     { OOO_STRING_SW_HTML_FS_para,    DS_PARA },
181     { OOO_STRING_SW_HTML_FS_word,    DS_WORD },
182     { OOO_STRING_SW_HTML_FS_char,    DS_CHAR },
183     { OOO_STRING_SW_HTML_FS_tbl,     DS_TBL },
184     { OOO_STRING_SW_HTML_FS_grf,     DS_GRF },
185     { OOO_STRING_SW_HTML_FS_ole,     DS_OLE },
186     { nullptr,                       SwDocStatSubType(0) }
187 };
188 
189 HTMLOptionEnum<SwFileNameFormat> const aHTMLFileNameFieldFormatTable[] =
190 {
191     { OOO_STRING_SW_HTML_FF_name,       FF_NAME },
192     { OOO_STRING_SW_HTML_FF_pathname,   FF_PATHNAME },
193     { OOO_STRING_SW_HTML_FF_path,       FF_PATH },
194     { OOO_STRING_SW_HTML_FF_name_noext, FF_NAME_NOEXT },
195     { nullptr,                          SwFileNameFormat(0) }
196 };
197 
GetNumType(const OUString & rStr,SvxNumType nDfltType)198 SvxNumType SwHTMLParser::GetNumType( const OUString& rStr, SvxNumType nDfltType )
199 {
200     const HTMLOptionEnum<SvxNumType> *pOptEnums = aHTMLPageNumFieldFormatTable;
201     while( pOptEnums->pName )
202     {
203         if( rStr.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
204             return pOptEnums->nValue;
205         pOptEnums++;
206     }
207     return nDfltType;
208 }
209 
NewField()210 void SwHTMLParser::NewField()
211 {
212     bool bKnownType = false, bFixed = false,
213          bHasNumFormat = false, bHasNumValue = false;
214     SwFieldIds nType = SwFieldIds::Database;
215     OUString aValue, aNumFormat, aNumValue, aName;
216     const HTMLOption *pSubOption=nullptr, *pFormatOption=nullptr;
217 
218     const HTMLOptions& rHTMLOptions = GetOptions();
219     size_t i;
220 
221     for ( i = rHTMLOptions.size(); i; )
222     {
223         const HTMLOption& rOption = rHTMLOptions[--i];
224         switch( rOption.GetToken() )
225         {
226         case HtmlOptionId::TYPE:
227             bKnownType = rOption.GetEnum( nType, aHTMLFieldTypeTable );
228             break;
229         case HtmlOptionId::SUBTYPE:
230             pSubOption = &rOption;
231             break;
232         case HtmlOptionId::FORMAT:
233             pFormatOption = &rOption;
234             break;
235         case HtmlOptionId::NAME:
236             aName = rOption.GetString();
237             break;
238         case HtmlOptionId::VALUE:
239             aValue = rOption.GetString();
240             break;
241         case HtmlOptionId::SDNUM:
242             aNumFormat = rOption.GetString();
243             bHasNumFormat = true;
244             break;
245         case HtmlOptionId::SDVAL:
246             aNumValue = rOption.GetString();
247             bHasNumValue = true;
248             break;
249         case HtmlOptionId::SDFIXED:
250             bFixed = true;
251             break;
252         default: break;
253         }
254     }
255 
256     if( !bKnownType )
257         return;
258 
259     // Author and sender are only inserted as a variable field if the document
260     // was last changed by ourself or nobody changed it and it was created
261     // by ourself. Otherwise it will be a fixed field.
262     if( !bFixed &&
263         (SwFieldIds::ExtUser == nType ||
264          SwFieldIds::Author == nType) )
265     {
266         SvtUserOptions aOpt;
267         const OUString& rUser = aOpt.GetFullName();
268         SwDocShell *pDocShell(m_xDoc->GetDocShell());
269         OSL_ENSURE(pDocShell, "no SwDocShell");
270         if (pDocShell) {
271             uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
272                 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
273             uno::Reference<document::XDocumentProperties> xDocProps(
274                 xDPS->getDocumentProperties());
275             OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");
276             const OUString& rChanged = xDocProps->getModifiedBy();
277             const OUString& rCreated = xDocProps->getAuthor();
278             if( rUser.isEmpty() ||
279                 (!rChanged.isEmpty() ? rUser != rChanged : rUser != rCreated) )
280                 bFixed = true;
281         }
282     }
283 
284     SwFieldIds nWhich = nType;
285     if( SwFieldIds::Date==nType || SwFieldIds::Time==nType )
286         nWhich = SwFieldIds::DateTime;
287 
288     SwFieldType* pType = m_xDoc->getIDocumentFieldsAccess().GetSysFieldType( nWhich );
289     std::unique_ptr<SwField> xNewField;
290     bool bInsOnEndTag = false;
291 
292     switch( nType )
293     {
294     case SwFieldIds::ExtUser:
295         if( pSubOption )
296         {
297             SwExtUserSubType nSub;
298             sal_uLong nFormat = 0;
299             if( bFixed )
300             {
301                 nFormat |= AF_FIXED;
302                 bInsOnEndTag = true;
303             }
304             if( pSubOption->GetEnum( nSub, aHTMLExtUsrFieldSubTable ) )
305                 xNewField.reset(new SwExtUserField(static_cast<SwExtUserFieldType*>(pType), nSub, nFormat));
306         }
307         break;
308 
309     case SwFieldIds::Author:
310         {
311             SwAuthorFormat nFormat = AF_NAME;
312             if( pFormatOption )
313                 pFormatOption->GetEnum( nFormat, aHTMLAuthorFieldFormatTable );
314             if( bFixed )
315             {
316                 nFormat = static_cast<SwAuthorFormat>(static_cast<int>(nFormat) | AF_FIXED);
317                 bInsOnEndTag = true;
318             }
319 
320             xNewField.reset(new SwAuthorField(static_cast<SwAuthorFieldType*>(pType), nFormat));
321         }
322         break;
323 
324     case SwFieldIds::Date:
325     case SwFieldIds::Time:
326         {
327             sal_uInt32 nNumFormat = 0;
328             DateTime aDateTime( DateTime::SYSTEM );
329             sal_Int64 nTime = aDateTime.GetTime();
330             sal_Int32 nDate = aDateTime.GetDate();
331             sal_uInt16 nSub = 0;
332             bool bValidFormat = false;
333             HTMLNumFormatTableEntry const * pFormatTable;
334 
335             if( SwFieldIds::Date==nType )
336             {
337                 nSub = DATEFLD;
338                 pFormatTable = aHTMLDateFieldFormatTable;
339                 if( !aValue.isEmpty() )
340                     nDate = aValue.toInt32();
341             }
342             else
343             {
344                 nSub = TIMEFLD;
345                 pFormatTable = aHTMLTimeFieldFormatTable;
346                 if( !aValue.isEmpty() )
347                     nTime = static_cast<sal_uLong>(aValue.toInt32());
348             }
349             if( !aValue.isEmpty() )
350                 nSub |= FIXEDFLD;
351 
352             SvNumberFormatter *pFormatter = m_xDoc->GetNumberFormatter();
353             if( pFormatOption )
354             {
355                 const OUString& rFormat = pFormatOption->GetString();
356                 for( int k = 0; pFormatTable[k].pName; ++k )
357                 {
358                     if( rFormat.equalsIgnoreAsciiCaseAscii( pFormatTable[k].pName ) )
359                     {
360                         nNumFormat = pFormatter->GetFormatIndex(
361                                         pFormatTable[k].eFormat, LANGUAGE_SYSTEM);
362                         bValidFormat = true;
363                         break;
364                     }
365                 }
366             }
367             if( !bValidFormat )
368                 nNumFormat = pFormatter->GetFormatIndex( pFormatTable[i].eFormat,
369                                                       LANGUAGE_SYSTEM);
370 
371             xNewField.reset(new SwDateTimeField(static_cast<SwDateTimeFieldType *>(pType), nSub, nNumFormat));
372 
373             if (nSub & FIXEDFLD)
374                 static_cast<SwDateTimeField *>(xNewField.get())->SetDateTime(DateTime(Date(nDate), tools::Time(nTime)));
375         }
376         break;
377 
378     case SwFieldIds::DateTime:
379         if( bHasNumFormat )
380         {
381             sal_uInt16 nSub = 0;
382 
383             SvNumberFormatter *pFormatter = m_xDoc->GetNumberFormatter();
384             sal_uInt32 nNumFormat;
385             LanguageType eLang;
386             double dValue = GetTableDataOptionsValNum(
387                                 nNumFormat, eLang, aNumValue, aNumFormat,
388                                 *m_xDoc->GetNumberFormatter() );
389             SvNumFormatType nFormatType = pFormatter->GetType( nNumFormat );
390             switch( nFormatType )
391             {
392             case SvNumFormatType::DATE: nSub = DATEFLD; break;
393             case SvNumFormatType::TIME: nSub = TIMEFLD; break;
394             default: break;
395             }
396 
397             if( nSub )
398             {
399                 if( bHasNumValue )
400                     nSub |= FIXEDFLD;
401 
402                 xNewField.reset(new SwDateTimeField(static_cast<SwDateTimeFieldType *>(pType), nSub, nNumFormat));
403                 if (bHasNumValue)
404                     static_cast<SwDateTimeField*>(xNewField.get())->SetValue(dValue);
405             }
406         }
407         break;
408 
409     case SwFieldIds::PageNumber:
410         if( pSubOption )
411         {
412             SwPageNumSubType nSub;
413             if( pSubOption->GetEnum( nSub, aHTMLPageNumFieldSubTable ) )
414             {
415                 SvxNumType nFormat = SVX_NUM_PAGEDESC;
416                 if( pFormatOption )
417                     pFormatOption->GetEnum( nFormat, aHTMLPageNumFieldFormatTable );
418 
419                 short nOff = 0;
420 
421                 if( nFormat!=SVX_NUM_CHAR_SPECIAL && !aValue.isEmpty() )
422                     nOff = static_cast<short>(aValue.toInt32());
423                 else if( nSub == PG_NEXT  )
424                     nOff = 1;
425                 else if( nSub == PG_PREV  )
426                     nOff = -1;
427 
428                 if( nFormat==SVX_NUM_CHAR_SPECIAL &&
429                     nSub==PG_RANDOM )
430                     nFormat = SVX_NUM_PAGEDESC;
431 
432                 xNewField.reset(new SwPageNumberField(static_cast<SwPageNumberFieldType*>(pType), nSub, nFormat, nOff));
433                 if (nFormat == SVX_NUM_CHAR_SPECIAL)
434                     static_cast<SwPageNumberField*>(xNewField.get())->SetUserString(aValue);
435             }
436         }
437         break;
438 
439     case SwFieldIds::DocInfo:
440         if( pSubOption )
441         {
442             sal_uInt16 nSub;
443             if( pSubOption->GetEnum( nSub, aHTMLDocInfoFieldSubTable ) )
444             {
445                 sal_uInt16 nExtSub = 0;
446                 if( DI_CREATE==static_cast<SwDocInfoSubType>(nSub) ||
447                     DI_CHANGE==static_cast<SwDocInfoSubType>(nSub) )
448                 {
449                     nExtSub = DI_SUB_AUTHOR;
450                     if( pFormatOption )
451                         pFormatOption->GetEnum( nExtSub, aHTMLDocInfoFieldFormatTable );
452                     nSub |= nExtSub;
453                 }
454 
455                 sal_uInt32 nNumFormat = 0;
456                 double dValue = 0;
457                 if( bHasNumFormat && (DI_SUB_DATE==nExtSub || DI_SUB_TIME==nExtSub) )
458                 {
459                     LanguageType eLang;
460                     dValue = GetTableDataOptionsValNum(
461                                     nNumFormat, eLang, aNumValue, aNumFormat,
462                                     *m_xDoc->GetNumberFormatter() );
463                     bFixed &= bHasNumValue;
464                 }
465                 else
466                     bHasNumValue = false;
467 
468                 if( nSub >= DI_INFO1 && nSub <= DI_INFO4 && aName.isEmpty() )
469                 {
470                     // backward compatibility for OOo 2:
471                     // map to names stored in AddMetaUserDefined
472                     aName = m_InfoNames[nSub - DI_INFO1];
473                     nSub = DI_CUSTOM;
474                 }
475 
476                 if( bFixed )
477                 {
478                     nSub |= DI_SUB_FIXED;
479                     bInsOnEndTag = true;
480                 }
481 
482                 xNewField.reset(new SwDocInfoField(static_cast<SwDocInfoFieldType *>(pType), nSub, aName, nNumFormat));
483                 if (bHasNumValue)
484                     static_cast<SwDocInfoField*>(xNewField.get())->SetValue(dValue);
485             }
486         }
487         break;
488 
489     case SwFieldIds::DocStat:
490         if( pSubOption )
491         {
492             SwDocStatSubType nSub;
493             if( pSubOption->GetEnum( nSub, aHTMLDocStatFieldSubTable ) )
494             {
495                 SvxNumType nFormat = SVX_NUM_ARABIC;
496                 if( pFormatOption )
497                     pFormatOption->GetEnum( nFormat, aHTMLPageNumFieldFormatTable );
498                 xNewField.reset(new SwDocStatField(static_cast<SwDocStatFieldType*>(pType), nSub, nFormat));
499                 m_bUpdateDocStat |= (DS_PAGE != nSub);
500             }
501         }
502         break;
503 
504     case SwFieldIds::Filename:
505         {
506             SwFileNameFormat nFormat = FF_NAME;
507             if( pFormatOption )
508                 pFormatOption->GetEnum( nFormat, aHTMLFileNameFieldFormatTable );
509             if( bFixed )
510             {
511                 nFormat = static_cast<SwFileNameFormat>(static_cast<int>(nFormat) | FF_FIXED);
512                 bInsOnEndTag = true;
513             }
514 
515             xNewField.reset(new SwFileNameField(static_cast<SwFileNameFieldType*>(pType), nFormat));
516         }
517         break;
518     default:
519         ;
520     }
521 
522     if (!xNewField)
523         return;
524 
525     if (bInsOnEndTag)
526     {
527         m_xField = std::move(xNewField);
528     }
529     else
530     {
531         m_xDoc->getIDocumentContentOperations().InsertPoolItem(*m_pPam, SwFormatField(*xNewField));
532         xNewField.reset();
533     }
534     m_bInField = true;
535 }
536 
EndField()537 void SwHTMLParser::EndField()
538 {
539     if (m_xField)
540     {
541         switch (m_xField->Which())
542         {
543         case SwFieldIds::DocInfo:
544             OSL_ENSURE( static_cast<SwDocInfoField*>(m_xField.get())->IsFixed(),
545                     "Field DocInfo should not have been saved" );
546             static_cast<SwDocInfoField*>(m_xField.get())->SetExpansion( m_aContents );
547             break;
548 
549         case SwFieldIds::ExtUser:
550             OSL_ENSURE( static_cast<SwExtUserField*>(m_xField.get())->IsFixed(),
551                     "Field ExtUser should not have been saved" );
552             static_cast<SwExtUserField*>(m_xField.get())->SetExpansion( m_aContents );
553             break;
554 
555         case SwFieldIds::Author:
556             OSL_ENSURE( static_cast<SwAuthorField*>(m_xField.get())->IsFixed(),
557                     "Field Author should not have been saved" );
558             static_cast<SwAuthorField*>(m_xField.get())->SetExpansion( m_aContents );
559             break;
560 
561         case SwFieldIds::Filename:
562             OSL_ENSURE( static_cast<SwFileNameField*>(m_xField.get())->IsFixed(),
563                     "Field FileName should not have been saved" );
564             static_cast<SwFileNameField*>(m_xField.get())->SetExpansion( m_aContents );
565             break;
566         default: break;
567         }
568 
569         m_xDoc->getIDocumentContentOperations().InsertPoolItem( *m_pPam, SwFormatField(*m_xField) );
570         m_xField.reset();
571     }
572 
573     m_bInField = false;
574     m_aContents.clear();
575 }
576 
InsertFieldText()577 void SwHTMLParser::InsertFieldText()
578 {
579     if (m_xField)
580     {
581         // append the current text part to the text
582         m_aContents += aToken;
583     }
584 }
585 
InsertCommentText(const char * pTag)586 void SwHTMLParser::InsertCommentText( const char *pTag )
587 {
588     bool bEmpty = m_aContents.isEmpty();
589     if( !bEmpty )
590         m_aContents += "\n";
591 
592     m_aContents += aToken;
593     if( bEmpty && pTag )
594     {
595         m_aContents = OUString::Concat("HTML: <") + OUStringChar(*pTag) + ">" + m_aContents;
596     }
597 }
598 
InsertComment(const OUString & rComment,const char * pTag)599 void SwHTMLParser::InsertComment( const OUString& rComment, const char *pTag )
600 {
601     OUString aComment( rComment );
602     if( pTag )
603     {
604         aComment += "</" +
605             OUString::createFromAscii(pTag) +
606             ">";
607     }
608 
609     // MIB 24.06.97: If a PostIt should be insert after a space, we
610     // will insert before the space. Then there are less problems
611     // during formatting. (bug #40483#)
612     const sal_Int32 nPos = m_pPam->GetPoint()->nContent.GetIndex();
613     SwTextNode *pTextNd = m_pPam->GetNode().GetTextNode();
614     bool bMoveFwd = false;
615     if (nPos>0 && pTextNd && (' ' == pTextNd->GetText()[nPos-1]))
616     {
617         bMoveFwd = true;
618 
619         sal_uLong nNodeIdx = m_pPam->GetPoint()->nNode.GetIndex();
620         const sal_Int32 nIdx = m_pPam->GetPoint()->nContent.GetIndex();
621         for( auto i = m_aSetAttrTab.size(); i > 0; )
622         {
623             HTMLAttr *pAttr = m_aSetAttrTab[--i];
624             if( pAttr->GetStartParagraphIdx() != nNodeIdx ||
625                 pAttr->GetStartContent() != nIdx )
626                 break;
627 
628             if( RES_TXTATR_FIELD == pAttr->m_pItem->Which() &&
629                 SwFieldIds::Script == static_cast<const SwFormatField *>(pAttr->m_pItem.get())->GetField()->GetTyp()->Which() )
630             {
631                 bMoveFwd = false;
632                 break;
633             }
634         }
635 
636         if( bMoveFwd )
637             m_pPam->Move( fnMoveBackward );
638     }
639 
640     SwPostItField aPostItField(
641                     static_cast<SwPostItFieldType*>(m_xDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Postit )),
642                     OUString(), aComment, OUString(), OUString(), DateTime(DateTime::SYSTEM));
643     InsertAttr( SwFormatField( aPostItField ), false );
644 
645     if( bMoveFwd )
646         m_pPam->Move( fnMoveForward );
647 }
648 
649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
650