bump product version to 4.1.6.2
[LibreOffice.git] / sw / source / ui / fldui / fldmgr.cxx
blob439c36d9836838db46f4420dbbe2561194b0953e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <cmdid.h>
22 #include <hintids.hxx>
23 #include <svl/stritem.hxx>
24 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
25 #include <com/sun/star/container/XNameAccess.hpp>
26 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
27 #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
28 #include <com/sun/star/text/XNumberingTypeInfo.hpp>
29 #include <com/sun/star/style/NumberingType.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/sdbc/XConnection.hpp>
32 #include <com/sun/star/sdbc/XDataSource.hpp>
33 #include <com/sun/star/uri/UriReferenceFactory.hpp>
34 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
35 #include <comphelper/processfactory.hxx>
36 #include <comphelper/string.hxx>
37 #include <editeng/unolingu.hxx>
38 #include <unotools/localedatawrapper.hxx>
39 #include <sfx2/dispatch.hxx>
40 #include <sfx2/objsh.hxx>
41 #include <sfx2/linkmgr.hxx>
42 #include <sfx2/app.hxx>
43 #include <basic/basmgr.hxx>
44 #include <editeng/langitem.hxx>
45 #include <svl/macitem.hxx>
46 #include <basic/sbmod.hxx>
47 #include <fmtrfmrk.hxx>
48 #include <basic/sbmeth.hxx>
49 #include <basic/sbx.hxx>
50 #include <svl/zforlist.hxx>
51 #include <svl/zformat.hxx>
52 #include <vcl/mnemonic.hxx>
53 #include <view.hxx>
54 #include <wrtsh.hxx> // active window
55 #include <doc.hxx> // active window
56 #include <docsh.hxx> // active window
57 #include <swmodule.hxx>
58 #include <charatr.hxx>
59 #include <fmtinfmt.hxx>
60 #include <cellatr.hxx>
61 #include <dbmgr.hxx>
62 #include <shellres.hxx>
63 #include <fldbas.hxx>
64 #include <docufld.hxx>
65 #include <chpfld.hxx>
66 #include <ddefld.hxx>
67 #include <expfld.hxx>
68 #include <reffld.hxx>
69 #include <usrfld.hxx>
70 #include <dbfld.hxx>
71 #include <authfld.hxx>
72 #include <flddat.hxx>
73 #include <fldmgr.hxx>
74 #include <crsskip.hxx>
75 #include <flddropdown.hxx>
76 #include <fldui.hrc>
77 #include <tox.hxx>
78 #include <misc.hrc>
79 #include <cnttab.hxx>
81 using namespace com::sun::star::uno;
82 using namespace com::sun::star::container;
83 using namespace com::sun::star::lang;
84 using namespace com::sun::star::beans;
85 using namespace com::sun::star::text;
86 using namespace com::sun::star::style;
87 using namespace com::sun::star::sdbc;
88 using namespace ::com::sun::star;
89 using namespace nsSwDocInfoSubType;
91 /*--------------------------------------------------------------------
92 Description: groups of fields
93 --------------------------------------------------------------------*/
94 enum
96 GRP_DOC_BEGIN = 0,
97 GRP_DOC_END = GRP_DOC_BEGIN + 11,
99 GRP_FKT_BEGIN = GRP_DOC_END,
100 GRP_FKT_END = GRP_FKT_BEGIN + 8,
102 GRP_REF_BEGIN = GRP_FKT_END,
103 GRP_REF_END = GRP_REF_BEGIN + 2,
105 GRP_REG_BEGIN = GRP_REF_END,
106 GRP_REG_END = GRP_REG_BEGIN + 1,
108 GRP_DB_BEGIN = GRP_REG_END,
109 GRP_DB_END = GRP_DB_BEGIN + 5,
111 GRP_VAR_BEGIN = GRP_DB_END,
112 GRP_VAR_END = GRP_VAR_BEGIN + 9
115 enum
117 GRP_WEB_DOC_BEGIN = 0,
118 GRP_WEB_DOC_END = GRP_WEB_DOC_BEGIN + 9,
120 GRP_WEB_FKT_BEGIN = GRP_WEB_DOC_END + 2,
121 GRP_WEB_FKT_END = GRP_WEB_FKT_BEGIN + 0, // the group is empty!
123 GRP_WEB_REF_BEGIN = GRP_WEB_FKT_END + 6, // the group is empty!
124 GRP_WEB_REF_END = GRP_WEB_REF_BEGIN + 0,
126 GRP_WEB_REG_BEGIN = GRP_WEB_REF_END + 2,
127 GRP_WEB_REG_END = GRP_WEB_REG_BEGIN + 1,
129 GRP_WEB_DB_BEGIN = GRP_WEB_REG_END, // the group is empty!
130 GRP_WEB_DB_END = GRP_WEB_DB_BEGIN + 0,
132 GRP_WEB_VAR_BEGIN = GRP_WEB_DB_END + 5,
133 GRP_WEB_VAR_END = GRP_WEB_VAR_BEGIN + 1
136 /*--------------------------------------------------------------------
137 Description: formats in the correct order
138 --------------------------------------------------------------------*/
139 static const sal_uInt16 aSetFmt[] =
141 // at first the order has to match the ResourceIds for FMT_SETVAR_???
146 static const sal_uInt16 aGetFmt[] =
148 // at first the order has to match the ResourceIds for FMT_GETVAR_???
152 static const sal_uInt16 aUsrFmt[] =
154 // at first the order has to match the ResourceIds for FMT_SETVAR_???
156 nsSwExtendedSubType::SUB_CMD
159 static const sal_uInt16 aDBFmt[] =
161 // at first the order has to match the ResourceIds for FMT_DBFLD_???
162 nsSwExtendedSubType::SUB_OWN_FMT
165 static const sal_uInt16 VF_COUNT = sizeof(aGetFmt) / sizeof(sal_uInt16);
166 static const sal_uInt16 VF_USR_COUNT = sizeof(aUsrFmt) / sizeof(sal_uInt16);
167 static const sal_uInt16 VF_DB_COUNT = sizeof(aDBFmt) / sizeof(sal_uInt16);
169 /*--------------------------------------------------------------------
170 Description: field types and subtypes
171 --------------------------------------------------------------------*/
172 struct SwFldPack
174 sal_uInt16 nTypeId;
176 sal_uInt16 nSubTypeStart;
177 sal_uInt16 nSubTypeEnd;
179 sal_uLong nFmtBegin;
180 sal_uLong nFmtEnd;
183 /*--------------------------------------------------------------------
184 Description: strings and formats
185 --------------------------------------------------------------------*/
186 static const SwFldPack aSwFlds[] =
188 // Document
189 { TYP_EXTUSERFLD, FLD_EU_BEGIN, FLD_EU_END, 0, 0 },
190 { TYP_AUTHORFLD, 0, 0, FMT_AUTHOR_BEGIN, FMT_AUTHOR_END },
191 { TYP_DATEFLD, FLD_DATE_BEGIN, FLD_DATE_END, 0, 0 },
192 { TYP_TIMEFLD, FLD_TIME_BEGIN, FLD_TIME_END, 0, 0 },
193 { TYP_PAGENUMBERFLD, 0, 0, FMT_NUM_BEGIN, FMT_NUM_END-1 },
194 { TYP_NEXTPAGEFLD, 0, 0, FMT_NUM_BEGIN, FMT_NUM_END },
195 { TYP_PREVPAGEFLD, 0, 0, FMT_NUM_BEGIN, FMT_NUM_END },
196 { TYP_FILENAMEFLD, 0, 0, FMT_FF_BEGIN, FMT_FF_END },
197 { TYP_DOCSTATFLD, FLD_STAT_BEGIN, FLD_STAT_END, FMT_NUM_BEGIN, FMT_NUM_END-1 },
199 { TYP_CHAPTERFLD, 0, 0, FMT_CHAPTER_BEGIN, FMT_CHAPTER_END },
200 { TYP_TEMPLNAMEFLD, 0, 0, FMT_FF_BEGIN, FMT_FF_END },
202 // Functions
203 { TYP_CONDTXTFLD, 0, 0, 0, 0 },
204 { TYP_DROPDOWN, 0, 0, 0, 0 },
205 { TYP_INPUTFLD, FLD_INPUT_BEGIN, FLD_INPUT_END, 0, 0 },
206 { TYP_MACROFLD, 0, 0, 0, 0 },
207 { TYP_JUMPEDITFLD, 0, 0, FMT_MARK_BEGIN, FMT_MARK_END },
208 { TYP_COMBINED_CHARS, 0, 0, 0, 0 },
209 { TYP_HIDDENTXTFLD, 0, 0, 0, 0 },
210 { TYP_HIDDENPARAFLD, 0, 0, 0, 0 },
212 // Cross-References
213 { TYP_SETREFFLD, 0, 0, 0, 0 },
214 { TYP_GETREFFLD, 0, 0, FMT_REF_BEGIN, FMT_REF_END },
216 // DocInformation
217 { TYP_DOCINFOFLD, 0, 0, FMT_REG_BEGIN, FMT_REG_END },
219 // Database
220 { TYP_DBFLD, 0, 0, FMT_DBFLD_BEGIN, FMT_DBFLD_END },
221 { TYP_DBNEXTSETFLD, 0, 0, 0, 0 },
222 { TYP_DBNUMSETFLD, 0, 0, 0, 0 },
223 { TYP_DBSETNUMBERFLD, 0, 0, FMT_NUM_BEGIN, FMT_NUM_END-2 },
224 { TYP_DBNAMEFLD, 0, 0, 0, 0 },
226 // Variables
227 { TYP_SETFLD, 0, 0, FMT_SETVAR_BEGIN, FMT_SETVAR_END },
229 { TYP_GETFLD, 0, 0, FMT_GETVAR_BEGIN, FMT_GETVAR_END },
230 { TYP_DDEFLD, 0, 0, FMT_DDE_BEGIN, FMT_DDE_END },
231 { TYP_FORMELFLD, 0, 0, FMT_GETVAR_BEGIN, FMT_GETVAR_END },
232 { TYP_INPUTFLD, FLD_INPUT_BEGIN, FLD_INPUT_END, 0, 0 },
233 { TYP_SEQFLD, 0, 0, FMT_NUM_BEGIN, FMT_NUM_END-2 },
234 { TYP_SETREFPAGEFLD, FLD_PAGEREF_BEGIN, FLD_PAGEREF_END,0, 0 },
235 { TYP_GETREFPAGEFLD, 0, 0, FMT_NUM_BEGIN, FMT_NUM_END-1 },
236 { TYP_USERFLD, 0, 0, FMT_USERVAR_BEGIN, FMT_USERVAR_END }
239 /*--------------------------------------------------------------------
240 Description: access to the shell
241 --------------------------------------------------------------------*/
243 static SwWrtShell* lcl_GetShell()
245 SwView* pView;
246 if ( 0 != (pView = ::GetActiveView()) )
247 return pView->GetWrtShellPtr();
248 OSL_FAIL("no current shell found!");
249 return 0;
252 inline sal_uInt16 GetPackCount() { return sizeof(aSwFlds) / sizeof(SwFldPack); }
254 /*--------------------------------------------------------------------
255 Description: FieldManager controls inserting and updating of fields
256 --------------------------------------------------------------------*/
258 SwFldMgr::SwFldMgr(SwWrtShell* pSh ) :
259 pModule(0),
260 pMacroItem(0),
261 pWrtShell(pSh),
262 bEvalExp(sal_True)
264 // determine current field if existing
265 GetCurFld();
269 SwFldMgr::~SwFldMgr()
273 /*--------------------------------------------------------------------
274 Description: organise RefMark by names
275 --------------------------------------------------------------------*/
277 bool SwFldMgr::CanInsertRefMark( const String& rStr )
279 bool bRet = false;
280 SwWrtShell *pSh = pWrtShell ? pWrtShell : lcl_GetShell();
281 OSL_ENSURE(pSh, "no SwWrtShell found");
282 if(pSh)
284 sal_uInt16 nCnt = pSh->GetCrsrCnt();
286 // the last Crsr doesn't have to be a spanned selection
287 if( 1 < nCnt && !pSh->SwCrsrShell::HasSelection() )
288 --nCnt;
290 bRet = 2 > nCnt && 0 == pSh->GetRefMark( rStr );
292 return bRet;
295 /*--------------------------------------------------------------------
296 Description: access over ResIds
297 --------------------------------------------------------------------*/
299 void SwFldMgr::RemoveFldType(sal_uInt16 nResId, const String& rName )
301 SwWrtShell * pSh = pWrtShell ? pWrtShell : lcl_GetShell();
302 OSL_ENSURE(pSh, "no SwWrtShell found");
303 if( pSh )
304 pSh->RemoveFldType(nResId, rName);
307 sal_uInt16 SwFldMgr::GetFldTypeCount(sal_uInt16 nResId) const
309 SwWrtShell * pSh = pWrtShell ? pWrtShell : lcl_GetShell();
310 OSL_ENSURE(pSh, "no SwWrtShell found");
311 return pSh ? pSh->GetFldTypeCount(nResId) : 0;
315 SwFieldType* SwFldMgr::GetFldType(sal_uInt16 nResId, sal_uInt16 nId) const
317 SwWrtShell * pSh = pWrtShell ? pWrtShell : lcl_GetShell();
318 OSL_ENSURE(pSh, "no SwWrtShell found");
319 return pSh ? pSh->GetFldType(nId, nResId) : 0;
323 SwFieldType* SwFldMgr::GetFldType(sal_uInt16 nResId, const String& rName) const
325 SwWrtShell * pSh = pWrtShell ? pWrtShell : lcl_GetShell();
326 OSL_ENSURE(pSh, "no SwWrtShell found");
327 return pSh ? pSh->GetFldType(nResId, rName) : 0;
331 /*--------------------------------------------------------------------
332 Description: determine current field
333 --------------------------------------------------------------------*/
334 SwField* SwFldMgr::GetCurFld()
336 SwWrtShell *pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
337 if ( pSh )
338 pCurFld = pSh->GetCurFld();
339 else
340 pCurFld = NULL;
342 // initialise strings and format
343 aCurPar1.Erase();
344 aCurPar2.Erase();
345 sCurFrame.Erase();
346 nCurFmt = 0;
348 if(!pCurFld)
349 return 0;
351 // preprocess current values; determine parameter 1 and parameter 2
352 // as well as the format
353 const sal_uInt16 nTypeId = pCurFld->GetTypeId();
355 nCurFmt = pCurFld->GetFormat();
356 aCurPar1 = pCurFld->GetPar1();
357 aCurPar2 = pCurFld->GetPar2();
359 switch( nTypeId )
361 case TYP_PAGENUMBERFLD:
362 case TYP_NEXTPAGEFLD:
363 case TYP_PREVPAGEFLD:
364 case TYP_GETREFPAGEFLD:
365 if( nCurFmt == SVX_NUM_PAGEDESC )
366 nCurFmt -= 2;
367 break;
369 return pCurFld;
372 /*--------------------------------------------------------------------
373 Description: provide group range
374 --------------------------------------------------------------------*/
377 const SwFldGroupRgn& SwFldMgr::GetGroupRange(sal_Bool bHtmlMode, sal_uInt16 nGrpId) const
379 static SwFldGroupRgn const aRanges[] =
381 { /* Document */ GRP_DOC_BEGIN, GRP_DOC_END },
382 { /* Functions */ GRP_FKT_BEGIN, GRP_FKT_END },
383 { /* Cross-Refs */ GRP_REF_BEGIN, GRP_REF_END },
384 { /* DocInfos */ GRP_REG_BEGIN, GRP_REG_END },
385 { /* Database */ GRP_DB_BEGIN, GRP_DB_END },
386 { /* User */ GRP_VAR_BEGIN, GRP_VAR_END }
388 static SwFldGroupRgn const aWebRanges[] =
390 { /* Document */ GRP_WEB_DOC_BEGIN, GRP_WEB_DOC_END },
391 { /* Functions */ GRP_WEB_FKT_BEGIN, GRP_WEB_FKT_END },
392 { /* Cross-Refs */ GRP_WEB_REF_BEGIN, GRP_WEB_REF_END },
393 { /* DocInfos */ GRP_WEB_REG_BEGIN, GRP_WEB_REG_END },
394 { /* Database */ GRP_WEB_DB_BEGIN, GRP_WEB_DB_END },
395 { /* User */ GRP_WEB_VAR_BEGIN, GRP_WEB_VAR_END }
398 if (bHtmlMode)
399 return aWebRanges[(sal_uInt16)nGrpId];
400 else
401 return aRanges[(sal_uInt16)nGrpId];
404 /*--------------------------------------------------------------------
405 Description: determine GroupId
406 --------------------------------------------------------------------*/
408 sal_uInt16 SwFldMgr::GetGroup(sal_Bool bHtmlMode, sal_uInt16 nTypeId, sal_uInt16 nSubType) const
410 if (nTypeId == TYP_SETINPFLD)
411 nTypeId = TYP_SETFLD;
413 if (nTypeId == TYP_INPUTFLD && (nSubType & INP_USR))
414 nTypeId = TYP_USERFLD;
416 if (nTypeId == TYP_FIXDATEFLD)
417 nTypeId = TYP_DATEFLD;
419 if (nTypeId == TYP_FIXTIMEFLD)
420 nTypeId = TYP_TIMEFLD;
422 for (sal_uInt16 i = GRP_DOC; i <= GRP_VAR; i++)
424 const SwFldGroupRgn& rRange = GetGroupRange(bHtmlMode, i);
425 for (sal_uInt16 nPos = rRange.nStart; nPos < rRange.nEnd; nPos++)
427 if (aSwFlds[nPos].nTypeId == nTypeId)
428 return i;
431 return USHRT_MAX;
434 /*--------------------------------------------------------------------
435 Description: determine names to TypeId
436 ACCESS over TYP_....
437 --------------------------------------------------------------------*/
440 sal_uInt16 SwFldMgr::GetTypeId(sal_uInt16 nPos)
442 OSL_ENSURE(nPos < ::GetPackCount(), "forbidden Pos");
443 return aSwFlds[ nPos ].nTypeId;
447 const String& SwFldMgr::GetTypeStr(sal_uInt16 nPos)
449 OSL_ENSURE(nPos < ::GetPackCount(), "forbidden TypeId");
451 sal_uInt16 nFldWh = aSwFlds[ nPos ].nTypeId;
453 // special treatment for date/time fields (without var/fix)
454 if( TYP_DATEFLD == nFldWh )
456 static String g_aDate( SW_RES( STR_DATEFLD ) );
457 return g_aDate;
459 if( TYP_TIMEFLD == nFldWh )
461 static String g_aTime( SW_RES( STR_TIMEFLD ) );
462 return g_aTime;
465 return SwFieldType::GetTypeStr( nFldWh );
468 /*--------------------------------------------------------------------
469 Description: determine Pos in the list
470 --------------------------------------------------------------------*/
473 sal_uInt16 SwFldMgr::GetPos(sal_uInt16 nTypeId)
475 switch( nTypeId )
477 case TYP_FIXDATEFLD: nTypeId = TYP_DATEFLD; break;
478 case TYP_FIXTIMEFLD: nTypeId = TYP_TIMEFLD; break;
479 case TYP_SETINPFLD: nTypeId = TYP_SETFLD; break;
480 case TYP_USRINPFLD: nTypeId = TYP_USERFLD; break;
483 for(sal_uInt16 i = 0; i < GetPackCount(); i++)
484 if(aSwFlds[i].nTypeId == nTypeId)
485 return i;
487 return USHRT_MAX;
490 /*--------------------------------------------------------------------
491 Description: localise subtypes of a field
492 --------------------------------------------------------------------*/
494 bool SwFldMgr::GetSubTypes(sal_uInt16 nTypeId, std::vector<OUString>& rToFill)
496 bool bRet = false;
497 SwWrtShell *pSh = pWrtShell ? pWrtShell : lcl_GetShell();
498 OSL_ENSURE(pSh, "no SwWrtShell found");
499 if(pSh)
501 const sal_uInt16 nPos = GetPos(nTypeId);
503 switch(nTypeId)
505 case TYP_SETREFFLD:
506 case TYP_GETREFFLD:
508 // references are no fields
509 pSh->GetRefMarks( &rToFill );
510 break;
512 case TYP_MACROFLD:
514 break;
516 case TYP_INPUTFLD:
518 rToFill.push_back(String(SW_RESSTR(aSwFlds[nPos].nSubTypeStart)));
519 // move on at generic types
521 case TYP_DDEFLD:
522 case TYP_SEQFLD:
523 case TYP_FORMELFLD:
524 case TYP_GETFLD:
525 case TYP_SETFLD:
526 case TYP_USERFLD:
529 const sal_uInt16 nCount = pSh->GetFldTypeCount();
530 for(sal_uInt16 i = 0; i < nCount; ++i)
532 SwFieldType* pFldType = pSh->GetFldType( i );
533 const sal_uInt16 nWhich = pFldType->Which();
535 if((nTypeId == TYP_DDEFLD && pFldType->Which() == RES_DDEFLD) ||
537 (nTypeId == TYP_USERFLD && nWhich == RES_USERFLD) ||
539 (nTypeId == TYP_GETFLD && nWhich == RES_SETEXPFLD &&
540 !(((SwSetExpFieldType*)pFldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||
542 (nTypeId == TYP_SETFLD && nWhich == RES_SETEXPFLD &&
543 !(((SwSetExpFieldType*)pFldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||
545 (nTypeId == TYP_SEQFLD && nWhich == RES_SETEXPFLD &&
546 (((SwSetExpFieldType*)pFldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||
548 ((nTypeId == TYP_INPUTFLD || nTypeId == TYP_FORMELFLD) &&
549 (nWhich == RES_USERFLD ||
550 (nWhich == RES_SETEXPFLD &&
551 !(((SwSetExpFieldType*)pFldType)->GetType() & nsSwGetSetExpType::GSE_SEQ))) ) )
553 rToFill.push_back(pFldType->GetName());
556 break;
558 case TYP_DBNEXTSETFLD:
559 case TYP_DBNUMSETFLD:
560 case TYP_DBNAMEFLD:
561 case TYP_DBSETNUMBERFLD:
562 break;
564 default:
566 // static SubTypes
567 if(nPos != USHRT_MAX)
569 sal_uInt16 nCount;
570 if (nTypeId == TYP_DOCINFOFLD)
571 nCount = DI_SUBTYPE_END - DI_SUBTYPE_BEGIN;
572 else
573 nCount = aSwFlds[nPos].nSubTypeEnd - aSwFlds[nPos].nSubTypeStart;
575 for(sal_uInt16 i = 0; i < nCount; ++i)
577 String pNew;
578 if (nTypeId == TYP_DOCINFOFLD)
580 if ( i == DI_CUSTOM )
581 pNew = String(SW_RES( STR_CUSTOM ));
582 else
583 pNew = ViewShell::GetShellRes()->aDocInfoLst[i];
585 else
586 pNew = SW_RESSTR(aSwFlds[nPos].nSubTypeStart + i);
588 rToFill.push_back(pNew);
593 bRet = true;
595 return bRet;
598 /*--------------------------------------------------------------------
599 Description: determine format
600 ACCESS over TYP_....
601 --------------------------------------------------------------------*/
604 sal_uInt16 SwFldMgr::GetFormatCount(sal_uInt16 nTypeId, bool bIsText, sal_Bool bHtmlMode) const
606 OSL_ENSURE(nTypeId < TYP_END, "forbidden TypeId");
609 const sal_uInt16 nPos = GetPos(nTypeId);
611 if(nPos == USHRT_MAX || (bHtmlMode && nTypeId == TYP_SETFLD))
612 return 0;
614 sal_uLong nStart = aSwFlds[nPos].nFmtBegin;
615 sal_uLong nEnd = aSwFlds[nPos].nFmtEnd;
617 if (bIsText && nEnd - nStart >= 2)
618 return 2;
620 if (nTypeId == TYP_FILENAMEFLD)
621 nEnd -= 2; // no range or template
623 switch(nStart)
625 case FMT_GETVAR_BEGIN:
626 case FMT_SETVAR_BEGIN: return VF_COUNT;
627 case FMT_USERVAR_BEGIN: return VF_USR_COUNT;
628 case FMT_DBFLD_BEGIN: return VF_DB_COUNT;
629 case FMT_NUM_BEGIN:
631 sal_uInt16 nCount = (sal_uInt16)(nEnd - nStart);
632 GetNumberingInfo();
633 if(xNumberingInfo.is())
635 Sequence<sal_Int16> aTypes = xNumberingInfo->getSupportedNumberingTypes();
636 const sal_Int16* pTypes = aTypes.getConstArray();
637 for(sal_Int32 nType = 0; nType < aTypes.getLength(); nType++)
639 sal_Int16 nCurrent = pTypes[nType];
640 //skip all values below or equal to CHARS_LOWER_LETTER_N
641 if(nCurrent > NumberingType::CHARS_LOWER_LETTER_N)
643 // #i28073# it's not necessarily a sorted sequence
644 ++nCount;
648 return nCount;
652 return (sal_uInt16)(nEnd - nStart);
656 /*--------------------------------------------------------------------
657 Description: determine FormatString to a type
658 --------------------------------------------------------------------*/
661 String SwFldMgr::GetFormatStr(sal_uInt16 nTypeId, sal_uLong nFormatId) const
663 String aRet;
664 OSL_ENSURE(nTypeId < TYP_END, "forbidden TypeId");
666 const sal_uInt16 nPos = GetPos(nTypeId);
668 if(nPos == USHRT_MAX)
669 return aRet;
671 sal_uLong nStart;
673 nStart = aSwFlds[nPos].nFmtBegin;
675 if (TYP_AUTHORFLD == nTypeId|| TYP_FILENAMEFLD == nTypeId)
676 nFormatId &= ~FF_FIXED; // mask out Fixed-Flag
678 if((nStart + nFormatId) < aSwFlds[nPos].nFmtEnd)
679 aRet = SW_RESSTR((sal_uInt16)(nStart + nFormatId));
680 else if( FMT_NUM_BEGIN == nStart)
682 if(xNumberingInfo.is())
684 SwOLENames aNames(SW_RES(STRRES_NUMTYPES));
685 ResStringArray& rNames = aNames.GetNames();
687 Sequence<sal_Int16> aTypes = xNumberingInfo->getSupportedNumberingTypes();
688 const sal_Int16* pTypes = aTypes.getConstArray();
689 sal_Int32 nOffset = aSwFlds[nPos].nFmtEnd - nStart;
690 sal_Int32 nValidEntry = 0;
691 for(sal_Int32 nType = 0; nType < aTypes.getLength(); nType++)
693 sal_Int16 nCurrent = pTypes[nType];
694 if(nCurrent > NumberingType::CHARS_LOWER_LETTER_N)
696 if(nValidEntry == ((sal_Int32)nFormatId) - nOffset)
698 sal_uInt32 n = rNames.FindIndex(pTypes[nType]);
699 if (n != RESARRAY_INDEX_NOTFOUND)
701 aRet = rNames.GetString(n);
703 else
705 aRet = xNumberingInfo->getNumberingIdentifier( pTypes[nType] );
707 break;
709 ++nValidEntry;
715 return aRet;
718 /*--------------------------------------------------------------------
719 Description: determine FormatId from Pseudo-ID
720 --------------------------------------------------------------------*/
722 sal_uInt16 SwFldMgr::GetFormatId(sal_uInt16 nTypeId, sal_uLong nFormatId) const
724 sal_uInt16 nId = (sal_uInt16)nFormatId;
726 switch( nTypeId )
728 case TYP_DOCINFOFLD:
729 switch( aSwFlds[ GetPos( nTypeId ) ].nFmtBegin + nFormatId )
731 case FMT_REG_AUTHOR: nId = DI_SUB_AUTHOR; break;
732 case FMT_REG_TIME: nId = DI_SUB_TIME; break;
733 case FMT_REG_DATE: nId = DI_SUB_DATE; break;
735 break;
737 case TYP_PAGENUMBERFLD:
738 case TYP_NEXTPAGEFLD:
739 case TYP_PREVPAGEFLD:
740 case TYP_DOCSTATFLD:
741 case TYP_DBSETNUMBERFLD:
742 case TYP_SEQFLD:
743 case TYP_GETREFPAGEFLD:
745 sal_uInt16 nPos = GetPos( nTypeId );
746 sal_uLong nBegin = aSwFlds[ nPos ].nFmtBegin;
747 sal_uLong nEnd = aSwFlds[nPos].nFmtEnd;
748 if((nBegin + nFormatId) < nEnd)
750 switch( nBegin + nFormatId )
752 case FMT_NUM_ABC: nId = SVX_NUM_CHARS_UPPER_LETTER; break;
753 case FMT_NUM_SABC: nId = SVX_NUM_CHARS_LOWER_LETTER; break;
754 case FMT_NUM_ROMAN: nId = SVX_NUM_ROMAN_UPPER; break;
755 case FMT_NUM_SROMAN: nId = SVX_NUM_ROMAN_LOWER; break;
756 case FMT_NUM_ARABIC: nId = SVX_NUM_ARABIC; break;
757 case FMT_NUM_PAGEDESC: nId = SVX_NUM_PAGEDESC; break;
758 case FMT_NUM_PAGESPECIAL: nId = SVX_NUM_CHAR_SPECIAL; break;
759 case FMT_NUM_ABC_N: nId = SVX_NUM_CHARS_UPPER_LETTER_N; break;
760 case FMT_NUM_SABC_N: nId = SVX_NUM_CHARS_LOWER_LETTER_N; break;
763 else if(xNumberingInfo.is())
765 Sequence<sal_Int16> aTypes = xNumberingInfo->getSupportedNumberingTypes();
766 const sal_Int16* pTypes = aTypes.getConstArray();
767 sal_Int32 nOffset = nEnd - nBegin;
768 sal_Int32 nValidEntry = 0;
769 for(sal_Int32 nType = 0; nType < aTypes.getLength(); nType++)
771 sal_Int16 nCurrent = pTypes[nType];
772 if(nCurrent > NumberingType::CHARS_LOWER_LETTER_N)
774 if(nValidEntry == ((sal_Int32)nFormatId) - nOffset)
776 nId = pTypes[nType];
777 break;
779 ++nValidEntry;
784 break;
785 case TYP_DDEFLD:
786 switch ( aSwFlds[ GetPos( nTypeId ) ].nFmtBegin + nFormatId )
788 case FMT_DDE_NORMAL: nId = sfx2::LINKUPDATE_ONCALL; break;
789 case FMT_DDE_HOT: nId = sfx2::LINKUPDATE_ALWAYS; break;
791 break;
794 return nId;
798 /*--------------------------------------------------------------------
799 Description: Traveling
800 --------------------------------------------------------------------*/
803 sal_Bool SwFldMgr::GoNextPrev( sal_Bool bNext, SwFieldType* pTyp )
805 SwWrtShell* pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
806 if(!pSh)
807 return sal_False;
809 if( !pTyp && pCurFld )
811 const sal_uInt16 nTypeId = pCurFld->GetTypeId();
812 if( TYP_SETINPFLD == nTypeId || TYP_USRINPFLD == nTypeId )
813 pTyp = pSh->GetFldType( 0, RES_INPUTFLD );
814 else
815 pTyp = pCurFld->GetTyp();
818 if (pTyp && pTyp->Which() == RES_DBFLD)
820 // for fieldcommand-edit (hop to all DB fields)
821 return pSh->MoveFldType( 0, bNext, USHRT_MAX, RES_DBFLD );
824 return pTyp && pSh ? pSh->MoveFldType( pTyp, bNext ) : sal_False;
827 /*--------------------------------------------------------------------
828 Description: insert field types
829 --------------------------------------------------------------------*/
832 void SwFldMgr::InsertFldType(SwFieldType& rType)
834 SwWrtShell* pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
835 OSL_ENSURE(pSh, "no SwWrtShell found");
836 if(pSh)
837 pSh->InsertFldType(rType);
840 /*--------------------------------------------------------------------
841 Description: determine current TypeId
842 --------------------------------------------------------------------*/
845 sal_uInt16 SwFldMgr::GetCurTypeId() const
847 return pCurFld ? pCurFld->GetTypeId() : USHRT_MAX;
850 /*--------------------------------------------------------------------
851 Description: Over string insert field or update
852 --------------------------------------------------------------------*/
855 sal_Bool SwFldMgr::InsertFld( const SwInsertFld_Data& rData, SwPaM *pPam )
857 SwField* pFld = 0;
858 bool bExp = false;
859 bool bTbl = false;
860 bool bPageVar = false;
861 sal_uLong nFormatId = rData.nFormatId;
862 sal_uInt16 nSubType = rData.nSubType;
863 sal_Unicode cSeparator = rData.cSeparator;
864 SwWrtShell* pCurShell = rData.pSh;
865 if(!pCurShell)
866 pCurShell = pWrtShell ? pWrtShell : ::lcl_GetShell();
867 OSL_ENSURE(pCurShell, "no SwWrtShell found");
868 if(!pCurShell)
869 return sal_False;
871 switch(rData.nTypeId)
872 { // ATTENTION this field is inserted by a separate dialog
873 case TYP_POSTITFLD:
875 SwPostItFieldType* pType = (SwPostItFieldType*)pCurShell->GetFldType(0, RES_POSTITFLD);
876 pFld = new SwPostItField(pType, rData.sPar1, rData.sPar2, aEmptyStr, aEmptyStr, DateTime( DateTime::SYSTEM ));
877 break;
879 case TYP_SCRIPTFLD:
881 SwScriptFieldType* pType =
882 (SwScriptFieldType*)pCurShell->GetFldType(0, RES_SCRIPTFLD);
883 pFld = new SwScriptField(pType, rData.sPar1, rData.sPar2, (sal_Bool)nFormatId);
884 break;
886 case TYP_COMBINED_CHARS:
888 SwCombinedCharFieldType* pType = (SwCombinedCharFieldType*)
889 pCurShell->GetFldType( 0, RES_COMBINED_CHARS );
890 pFld = new SwCombinedCharField( pType, rData.sPar1 );
892 break;
893 case TYP_AUTHORITY:
895 SwAuthorityFieldType* pType =
896 (SwAuthorityFieldType*)pCurShell->GetFldType(0, RES_AUTHORITY);
897 if (!pType)
899 SwAuthorityFieldType const type(pCurShell->GetDoc());
900 pType = static_cast<SwAuthorityFieldType*>(
901 pCurShell->InsertFldType(type));
903 pFld = new SwAuthorityField(pType, rData.sPar1);
905 break;
906 case TYP_DATEFLD:
907 case TYP_TIMEFLD:
909 sal_uInt16 nSub = static_cast< sal_uInt16 >(rData.nTypeId == TYP_DATEFLD ? DATEFLD : TIMEFLD);
910 nSub |= nSubType == DATE_VAR ? 0 : FIXEDFLD;
912 SwDateTimeFieldType* pTyp =
913 (SwDateTimeFieldType*)pCurShell->GetFldType(0, RES_DATETIMEFLD);
914 pFld = new SwDateTimeField(pTyp, nSub, nFormatId);
915 pFld->SetPar2(rData.sPar2);
916 break;
918 case TYP_FILENAMEFLD:
920 SwFileNameFieldType* pTyp =
921 (SwFileNameFieldType*)pCurShell->GetFldType(0, RES_FILENAMEFLD);
922 pFld = new SwFileNameField(pTyp, nFormatId);
923 break;
925 case TYP_TEMPLNAMEFLD:
927 SwTemplNameFieldType* pTyp =
928 (SwTemplNameFieldType*)pCurShell->GetFldType(0, RES_TEMPLNAMEFLD);
929 pFld = new SwTemplNameField(pTyp, nFormatId);
930 break;
932 case TYP_CHAPTERFLD:
934 sal_uInt16 nByte = (sal_uInt16)rData.sPar2.ToInt32();
935 SwChapterFieldType* pTyp =
936 (SwChapterFieldType*)pCurShell->GetFldType(0, RES_CHAPTERFLD);
937 pFld = new SwChapterField(pTyp, nFormatId);
938 nByte = std::max(sal_uInt16(1), nByte);
939 nByte = std::min(nByte, sal_uInt16(MAXLEVEL));
940 nByte -= 1;
941 ((SwChapterField*)pFld)->SetLevel((sal_uInt8)nByte);
942 break;
944 case TYP_NEXTPAGEFLD:
945 case TYP_PREVPAGEFLD:
946 case TYP_PAGENUMBERFLD:
948 short nOff = (short)rData.sPar2.ToInt32();
950 if(rData.nTypeId == TYP_NEXTPAGEFLD)
952 if( SVX_NUM_CHAR_SPECIAL == nFormatId )
953 nOff = 1;
954 else
955 nOff += 1;
956 nSubType = PG_NEXT;
958 else if(rData.nTypeId == TYP_PREVPAGEFLD)
960 if( SVX_NUM_CHAR_SPECIAL == nFormatId )
961 nOff = -1;
962 else
963 nOff -= 1;
964 nSubType = PG_PREV;
966 else
967 nSubType = PG_RANDOM;
969 SwPageNumberFieldType* pTyp =
970 (SwPageNumberFieldType*)pCurShell->GetFldType(0, RES_PAGENUMBERFLD);
971 pFld = new SwPageNumberField(pTyp, nSubType, nFormatId, nOff);
973 if( SVX_NUM_CHAR_SPECIAL == nFormatId &&
974 ( PG_PREV == nSubType || PG_NEXT == nSubType ) )
975 ((SwPageNumberField*)pFld)->SetUserString( rData.sPar2 );
976 break;
978 case TYP_DOCSTATFLD:
979 { SwDocStatFieldType* pTyp =
980 (SwDocStatFieldType*)pCurShell->GetFldType(0, RES_DOCSTATFLD);
981 pFld = new SwDocStatField(pTyp, nSubType, nFormatId);
982 break;
984 case TYP_AUTHORFLD:
985 { SwAuthorFieldType* pTyp =
986 (SwAuthorFieldType*)pCurShell->GetFldType(0, RES_AUTHORFLD);
987 pFld = new SwAuthorField(pTyp, nFormatId);
988 break;
990 case TYP_CONDTXTFLD:
991 case TYP_HIDDENTXTFLD:
993 SwHiddenTxtFieldType* pTyp =
994 (SwHiddenTxtFieldType*)pCurShell->GetFldType(0, RES_HIDDENTXTFLD);
995 pFld = new SwHiddenTxtField(pTyp, sal_True, rData.sPar1, rData.sPar2, sal_False, rData.nTypeId);
996 bExp = true;
997 break;
999 case TYP_HIDDENPARAFLD:
1001 SwHiddenParaFieldType* pTyp =
1002 (SwHiddenParaFieldType*)pCurShell->GetFldType(0, RES_HIDDENPARAFLD);
1003 pFld = new SwHiddenParaField(pTyp, rData.sPar1);
1004 bExp = true;
1005 break;
1007 case TYP_SETREFFLD:
1009 if( rData.sPar1.Len() > 0 && CanInsertRefMark( rData.sPar1 ) )
1011 pCurShell->SetAttr( SwFmtRefMark( rData.sPar1 ) );
1012 return sal_True;
1014 return sal_False;
1016 case TYP_GETREFFLD:
1018 SwGetRefFieldType* pTyp =
1019 (SwGetRefFieldType*)pCurShell->GetFldType(0, RES_GETREFFLD);
1020 sal_uInt16 nSeqNo = (sal_uInt16)rData.sPar2.ToInt32();
1021 pFld = new SwGetRefField(pTyp, rData.sPar1, nSubType, nSeqNo, nFormatId);
1022 bExp = true;
1023 break;
1025 case TYP_DDEFLD:
1027 //JP 28.08.95: DDE-Topics/-Items can have blanks in their names!
1028 // That's not yet considered here.
1029 String sCmd( rData.sPar2 );
1030 sal_uInt16 nTmpPos = sCmd.SearchAndReplace( ' ', sfx2::cTokenSeparator );
1031 sCmd.SearchAndReplace( ' ', sfx2::cTokenSeparator, nTmpPos );
1033 SwDDEFieldType aType( rData.sPar1, sCmd, (sal_uInt16) nFormatId );
1034 SwDDEFieldType* pTyp = (SwDDEFieldType*) pCurShell->InsertFldType( aType );
1035 pFld = new SwDDEField( pTyp );
1036 break;
1038 case TYP_MACROFLD:
1040 SwMacroFieldType* pTyp =
1041 (SwMacroFieldType*)pCurShell->GetFldType(0, RES_MACROFLD);
1043 pFld = new SwMacroField(pTyp, rData.sPar1, rData.sPar2);
1045 break;
1047 case TYP_INTERNETFLD:
1049 SwFmtINetFmt aFmt( rData.sPar1, sCurFrame );
1050 if( pMacroItem )
1051 aFmt.SetMacroTbl( &pMacroItem->GetMacroTable() );
1052 return pCurShell->InsertURL( aFmt, rData.sPar2 );
1054 case TYP_JUMPEDITFLD:
1056 SwJumpEditFieldType* pTyp =
1057 (SwJumpEditFieldType*)pCurShell->GetFldType(0, RES_JUMPEDITFLD);
1059 pFld = new SwJumpEditField(pTyp, nFormatId, rData.sPar1, rData.sPar2 );
1060 break;
1062 case TYP_DOCINFOFLD:
1064 SwDocInfoFieldType* pTyp = (SwDocInfoFieldType*)pCurShell->GetFldType(
1065 0, RES_DOCINFOFLD );
1066 pFld = new SwDocInfoField(pTyp, nSubType, rData.sPar1, nFormatId);
1067 break;
1069 case TYP_EXTUSERFLD:
1071 SwExtUserFieldType* pTyp = (SwExtUserFieldType*)pCurShell->GetFldType(
1072 0, RES_EXTUSERFLD);
1073 pFld = new SwExtUserField(pTyp, nSubType, nFormatId);
1074 break;
1076 case TYP_DBFLD:
1078 SwDBData aDBData;
1079 String sPar1;
1081 if (rData.sPar1.Search(DB_DELIM) == STRING_NOTFOUND)
1083 aDBData = pCurShell->GetDBData();
1084 sPar1 = rData.sPar1;
1086 else
1088 aDBData.sDataSource = rData.sPar1.GetToken(0, DB_DELIM);
1089 aDBData.sCommand = rData.sPar1.GetToken(1, DB_DELIM);
1090 aDBData.nCommandType = rData.sPar1.GetToken(2, DB_DELIM).ToInt32();
1091 sPar1 = rData.sPar1.GetToken(3, DB_DELIM);
1094 if(!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData)
1095 pCurShell->ChgDBData(aDBData);
1097 SwDBFieldType* pTyp = (SwDBFieldType*)pCurShell->InsertFldType(
1098 SwDBFieldType(pCurShell->GetDoc(), sPar1, aDBData) );
1099 pFld = new SwDBField(pTyp);
1100 pFld->SetSubType(nSubType);
1102 if( !(nSubType & nsSwExtendedSubType::SUB_OWN_FMT) ) // determinee database format
1104 Reference< XDataSource> xSource;
1105 rData.aDBDataSource >>= xSource;
1106 Reference<XConnection> xConnection;
1107 rData.aDBConnection >>= xConnection;
1108 Reference<XPropertySet> xColumn;
1109 rData.aDBColumn >>= xColumn;
1110 if(xColumn.is())
1112 nFormatId = pCurShell->GetNewDBMgr()->GetColumnFmt(xSource, xConnection, xColumn,
1113 pCurShell->GetNumberFormatter(), GetCurrLanguage() );
1115 else
1116 nFormatId = pCurShell->GetNewDBMgr()->GetColumnFmt(
1117 aDBData.sDataSource, aDBData.sCommand, sPar1,
1118 pCurShell->GetNumberFormatter(), GetCurrLanguage() );
1120 pFld->ChangeFormat( nFormatId );
1122 bExp = true;
1123 break;
1125 case TYP_DBSETNUMBERFLD:
1126 case TYP_DBNUMSETFLD:
1127 case TYP_DBNEXTSETFLD:
1128 case TYP_DBNAMEFLD:
1130 sal_uInt16 nPos, nTablePos, nCmdTypePos, nExpPos;
1131 String sPar1;
1132 SwDBData aDBData;
1134 // excract DBName from rData.sPar1. Format: DBName.TableName.CommandType.ExpStrg
1135 if ((nTablePos = rData.sPar1.Search(DB_DELIM)) != STRING_NOTFOUND)
1136 aDBData.sDataSource = rData.sPar1.Copy(0, nTablePos++);
1137 if ((nCmdTypePos = rData.sPar1.Search(DB_DELIM, nTablePos)) != STRING_NOTFOUND)
1139 aDBData.sCommand = rData.sPar1.Copy(nTablePos, nCmdTypePos++ - nTablePos);
1141 if ((nExpPos = rData.sPar1.Search(DB_DELIM, nCmdTypePos)) != STRING_NOTFOUND)
1143 aDBData.nCommandType = rData.sPar1.Copy(nCmdTypePos, nExpPos++ - nCmdTypePos).ToInt32();
1145 if (nExpPos != STRING_NOTFOUND)
1146 nPos = nExpPos;
1147 else if (nTablePos != STRING_NOTFOUND)
1148 nPos = nTablePos;
1149 else
1150 nPos = 0;
1151 sPar1 = rData.sPar1.Copy(nPos);
1153 if (!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData)
1154 pCurShell->ChgDBData(aDBData);
1156 switch(rData.nTypeId)
1158 case TYP_DBNAMEFLD:
1160 SwDBNameFieldType* pTyp =
1161 (SwDBNameFieldType*)pCurShell->GetFldType(0, RES_DBNAMEFLD);
1162 pFld = new SwDBNameField(pTyp, aDBData);
1164 break;
1166 case TYP_DBNEXTSETFLD:
1168 SwDBNextSetFieldType* pTyp = (SwDBNextSetFieldType*)pCurShell->GetFldType(
1169 0, RES_DBNEXTSETFLD);
1170 pFld = new SwDBNextSetField(pTyp, sPar1, rData.sPar2, aDBData);
1171 bExp = true;
1172 break;
1174 case TYP_DBNUMSETFLD:
1176 SwDBNumSetFieldType* pTyp = (SwDBNumSetFieldType*)pCurShell->GetFldType(
1177 0, RES_DBNUMSETFLD);
1178 pFld = new SwDBNumSetField( pTyp, sPar1, rData.sPar2, aDBData);
1179 bExp = true;
1180 break;
1182 case TYP_DBSETNUMBERFLD:
1184 SwDBSetNumberFieldType* pTyp = (SwDBSetNumberFieldType*)
1185 pCurShell->GetFldType(0, RES_DBSETNUMBERFLD);
1186 pFld = new SwDBSetNumberField( pTyp, aDBData, nFormatId);
1187 bExp = true;
1188 break;
1191 break;
1193 case TYP_USERFLD:
1195 SwUserFieldType* pTyp =
1196 (SwUserFieldType*)pCurShell->GetFldType(RES_USERFLD, rData.sPar1);
1198 // only if existing
1199 if(!pTyp)
1201 pTyp = (SwUserFieldType*)pCurShell->InsertFldType(
1202 SwUserFieldType(pCurShell->GetDoc(), rData.sPar1));
1204 if (pTyp->GetContent(nFormatId) != rData.sPar2)
1205 pTyp->SetContent(rData.sPar2, nFormatId);
1206 pFld = new SwUserField(pTyp, 0, nFormatId);
1207 if (pFld->GetSubType() != nSubType)
1208 pFld->SetSubType(nSubType);
1209 bTbl = true;
1210 break;
1212 case TYP_INPUTFLD:
1214 if ((nSubType & 0x00ff) == INP_VAR)
1216 SwSetExpFieldType* pTyp = (SwSetExpFieldType*)
1217 pCurShell->GetFldType(RES_SETEXPFLD, rData.sPar1);
1219 // no Experssion Type with this name existing -> create
1220 if(pTyp)
1222 SwSetExpField* pExpFld =
1223 new SwSetExpField(pTyp, aEmptyStr, nFormatId);
1225 // Don't change type of SwSetExpFieldType:
1226 sal_uInt16 nOldSubType = pExpFld->GetSubType();
1227 pExpFld->SetSubType(nOldSubType | (nSubType & 0xff00));
1229 pExpFld->SetPromptText(rData.sPar2);
1230 pExpFld->SetInputFlag(sal_True) ;
1231 bExp = true;
1232 pFld = pExpFld;
1234 else
1235 return sal_False;
1237 else
1239 SwInputFieldType* pTyp =
1240 (SwInputFieldType*)pCurShell->GetFldType(0, RES_INPUTFLD);
1242 SwInputField* pInpFld =
1243 new SwInputField(pTyp, rData.sPar1, rData.sPar2, nSubType|nsSwExtendedSubType::SUB_INVISIBLE, nFormatId);
1244 pFld = pInpFld;
1247 // start dialog
1248 pCurShell->StartInputFldDlg(pFld, sal_False, rData.pParent);
1249 break;
1251 case TYP_SETFLD:
1253 if (!rData.sPar2.Len()) // empty variables are not allowed
1254 return sal_False;
1256 SwSetExpFieldType* pTyp = (SwSetExpFieldType*)pCurShell->InsertFldType(
1257 SwSetExpFieldType(pCurShell->GetDoc(), rData.sPar1) );
1259 SwSetExpField* pExpFld = new SwSetExpField( pTyp, rData.sPar2, nFormatId);
1260 pExpFld->SetSubType(nSubType);
1261 pExpFld->SetPar2(rData.sPar2);
1262 bExp = true;
1263 pFld = pExpFld;
1264 break;
1266 case TYP_SEQFLD:
1268 SwSetExpFieldType* pTyp = (SwSetExpFieldType*)pCurShell->InsertFldType(
1269 SwSetExpFieldType(pCurShell->GetDoc(), rData.sPar1, nsSwGetSetExpType::GSE_SEQ));
1271 sal_uInt8 nLevel = static_cast< sal_uInt8 >(nSubType & 0xff);
1273 pTyp->SetOutlineLvl(nLevel);
1274 if (nLevel != 0x7f && cSeparator == 0)
1275 cSeparator = '.';
1277 pTyp->SetDelimiter(OUString(cSeparator));
1278 SwSetExpField* pExpFld = new SwSetExpField(pTyp, rData.sPar2, nFormatId);
1279 bExp = true;
1280 pFld = pExpFld;
1281 nSubType = nsSwGetSetExpType::GSE_SEQ;
1282 break;
1284 case TYP_GETFLD:
1286 // is there a corresponding SetField
1287 SwSetExpFieldType* pSetTyp = (SwSetExpFieldType*)
1288 pCurShell->GetFldType(RES_SETEXPFLD, rData.sPar1);
1290 if(pSetTyp)
1292 SwGetExpFieldType* pTyp = (SwGetExpFieldType*)pCurShell->GetFldType(
1293 0, RES_GETEXPFLD);
1294 pFld = new SwGetExpField(pTyp, rData.sPar1, pSetTyp->GetType(), nFormatId);
1295 pFld->SetSubType(nSubType | pSetTyp->GetType());
1296 bExp = true;
1298 else
1299 return sal_False;
1300 break;
1302 case TYP_FORMELFLD:
1304 if(pCurShell->GetFrmType(0,sal_False) & FRMTYPE_TABLE)
1306 pCurShell->StartAllAction();
1308 SvNumberFormatter* pFormatter = pCurShell->GetDoc()->GetNumberFormatter();
1309 const SvNumberformat* pEntry = pFormatter->GetEntry(nFormatId);
1311 if (pEntry)
1313 SfxStringItem aFormat(FN_NUMBER_FORMAT, pEntry->GetFormatstring());
1314 pCurShell->GetView().GetViewFrame()->GetDispatcher()->
1315 Execute(FN_NUMBER_FORMAT, SFX_CALLMODE_SYNCHRON, &aFormat, 0L);
1318 SfxItemSet aBoxSet( pCurShell->GetAttrPool(),
1319 RES_BOXATR_FORMULA, RES_BOXATR_FORMULA );
1321 String sFml(comphelper::string::stripStart(rData.sPar2, ' '));
1322 if( sFml.Len() &&
1323 '=' == sFml.GetChar( 0 ) )
1324 sFml.Erase( 0, 1 );
1326 aBoxSet.Put( SwTblBoxFormula( sFml ));
1327 pCurShell->SetTblBoxFormulaAttrs( aBoxSet );
1328 pCurShell->UpdateTable();
1330 pCurShell->EndAllAction();
1331 return sal_True;
1334 else
1336 SwGetExpFieldType* pTyp = (SwGetExpFieldType*)
1337 pCurShell->GetFldType(0, RES_GETEXPFLD);
1338 pFld = new SwGetExpField(pTyp, rData.sPar2, nsSwGetSetExpType::GSE_FORMULA, nFormatId);
1339 pFld->SetSubType(nSubType);
1340 bExp = true;
1342 break;
1344 case TYP_SETREFPAGEFLD:
1345 pFld = new SwRefPageSetField( (SwRefPageSetFieldType*)
1346 pCurShell->GetFldType( 0, RES_REFPAGESETFLD ),
1347 (short)rData.sPar2.ToInt32(), 0 != nSubType );
1348 bPageVar = true;
1349 break;
1351 case TYP_GETREFPAGEFLD:
1352 pFld = new SwRefPageGetField( (SwRefPageGetFieldType*)
1353 pCurShell->GetFldType( 0, RES_REFPAGEGETFLD ), nFormatId );
1354 bPageVar = true;
1355 break;
1356 case TYP_DROPDOWN :
1358 pFld = new SwDropDownField(pCurShell->GetFldType( 0, RES_DROPDOWN ));
1359 xub_StrLen nTokenCount = comphelper::string::getTokenCount(rData.sPar2, DB_DELIM);
1360 Sequence<OUString> aEntries(nTokenCount);
1361 OUString* pArray = aEntries.getArray();
1362 for(xub_StrLen nToken = 0; nToken < nTokenCount; nToken++)
1363 pArray[nToken] = rData.sPar2.GetToken(nToken, DB_DELIM);
1364 ((SwDropDownField*)pFld)->SetItems(aEntries);
1365 ((SwDropDownField*)pFld)->SetName(rData.sPar1);
1367 break;
1368 default:
1369 { OSL_ENSURE(!this, "wrong field type");
1370 return sal_False;
1373 OSL_ENSURE(pFld, "field not available");
1376 //the auto language flag has to be set prior to the language!
1377 pFld->SetAutomaticLanguage(rData.bIsAutomaticLanguage);
1378 sal_uInt16 nLang = GetCurrLanguage();
1379 pFld->SetLanguage(nLang);
1381 // insert
1382 pCurShell->StartAllAction();
1384 SwPaM *pCommentRange = NULL;
1385 if (pPam && *pPam->GetPoint() != *pPam->GetMark() && rData.nTypeId == TYP_POSTITFLD)
1387 // If an annotation field will be inserted, pass through the affected range
1388 pCommentRange = pPam;
1391 pCurShell->Insert(*pFld, pCommentRange);
1393 if(bExp && bEvalExp)
1394 pCurShell->UpdateExpFlds(sal_True);
1396 if(bTbl)
1398 pCurShell->Left(CRSR_SKIP_CHARS, sal_False, 1, sal_False );
1399 pCurShell->UpdateFlds(*pFld);
1400 pCurShell->Right(CRSR_SKIP_CHARS, sal_False, 1, sal_False );
1402 else if( bPageVar )
1403 ((SwRefPageGetFieldType*)pCurShell->GetFldType( 0, RES_REFPAGEGETFLD ))->UpdateFlds();
1404 else if( TYP_GETREFFLD == rData.nTypeId )
1405 pFld->GetTyp()->ModifyNotification( 0, 0 );
1407 // delete temporary field
1408 delete pFld;
1410 pCurShell->EndAllAction();
1411 return sal_True;
1414 /*--------------------------------------------------------------------
1415 Description: fields update
1416 --------------------------------------------------------------------*/
1419 void SwFldMgr::UpdateCurFld(sal_uLong nFormat,
1420 const String& rPar1,
1421 const String& rPar2,
1422 SwField * _pTmpFld) // #111840#
1424 // change format
1425 OSL_ENSURE(pCurFld, "no field at CursorPos");
1427 bool bDelete = false;
1428 SwField *pTmpFld; // mb: fixed memory leak
1429 if (NULL != _pTmpFld)
1431 pTmpFld = _pTmpFld;
1433 else
1435 pTmpFld = pCurFld->CopyField();
1436 bDelete = true;
1439 SwFieldType* pType = pTmpFld->GetTyp();
1440 const sal_uInt16 nTypeId = pTmpFld->GetTypeId();
1442 SwWrtShell* pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
1443 OSL_ENSURE(pSh, "no SwWrtShell found");
1444 if(!pSh)
1445 return;
1446 pSh->StartAllAction();
1448 bool bSetPar2 = true;
1449 bool bSetPar1 = true;
1450 String sPar1( rPar1 );
1451 String sPar2( rPar2 );
1453 // Order to Format
1454 switch( nTypeId )
1456 case TYP_DDEFLD:
1458 // DDE-Topics/-Items can have blanks in their names!
1459 // That's not yet considered here!
1460 sal_uInt16 nTmpPos = sPar2.SearchAndReplace( ' ', sfx2::cTokenSeparator );
1461 sPar2.SearchAndReplace( ' ', sfx2::cTokenSeparator, nTmpPos );
1462 break;
1465 case TYP_CHAPTERFLD:
1467 sal_uInt16 nByte = (sal_uInt16)rPar2.ToInt32();
1468 nByte = std::max(sal_uInt16(1), nByte);
1469 nByte = std::min(nByte, sal_uInt16(MAXLEVEL));
1470 nByte -= 1;
1471 ((SwChapterField*)pTmpFld)->SetLevel((sal_uInt8)nByte);
1472 bSetPar2 = false;
1473 break;
1476 case TYP_SCRIPTFLD:
1477 ((SwScriptField*)pTmpFld)->SetCodeURL((sal_Bool)nFormat);
1478 break;
1480 case TYP_NEXTPAGEFLD:
1481 if( SVX_NUM_CHAR_SPECIAL == nFormat )
1483 ((SwPageNumberField*)pCurFld)->SetUserString( sPar2 );
1484 sPar2 = '1';
1486 else
1488 if( nFormat + 2 == SVX_NUM_PAGEDESC )
1489 nFormat = SVX_NUM_PAGEDESC;
1490 short nOff = (short)sPar2.ToInt32();
1491 nOff += 1;
1492 sPar2 = OUString::number(nOff);
1494 break;
1496 case TYP_PREVPAGEFLD:
1497 if( SVX_NUM_CHAR_SPECIAL == nFormat )
1499 ((SwPageNumberField*)pCurFld)->SetUserString( sPar2 );
1500 sPar2 = OUString("-1");
1502 else
1504 if( nFormat + 2 == SVX_NUM_PAGEDESC )
1505 nFormat = SVX_NUM_PAGEDESC;
1506 short nOff = (short)sPar2.ToInt32();
1507 nOff -= 1;
1508 sPar2 = OUString::number(nOff);
1510 break;
1512 case TYP_PAGENUMBERFLD:
1513 case TYP_GETREFPAGEFLD:
1514 if( nFormat + 2 == SVX_NUM_PAGEDESC )
1515 nFormat = SVX_NUM_PAGEDESC;
1516 break;
1518 case TYP_GETREFFLD:
1520 bSetPar2 = false;
1521 ((SwGetRefField*)pTmpFld)->SetSubType( (sal_uInt16)rPar2.ToInt32() );
1522 sal_uInt16 nPos = rPar2.Search( '|' );
1523 if( STRING_NOTFOUND != nPos )
1524 ((SwGetRefField*)pTmpFld)->SetSeqNo( (sal_uInt16)rPar2.Copy( nPos + 1 ).ToInt32());
1526 break;
1527 case TYP_DROPDOWN:
1529 xub_StrLen nTokenCount = comphelper::string::getTokenCount(sPar2, DB_DELIM);
1530 Sequence<OUString> aEntries(nTokenCount);
1531 OUString* pArray = aEntries.getArray();
1532 for(xub_StrLen nToken = 0; nToken < nTokenCount; nToken++)
1533 pArray[nToken] = sPar2.GetToken(nToken, DB_DELIM);
1534 ((SwDropDownField*)pTmpFld)->SetItems(aEntries);
1535 ((SwDropDownField*)pTmpFld)->SetName(sPar1);
1536 bSetPar1 = bSetPar2 = false;
1538 break;
1539 case TYP_AUTHORITY :
1541 //#i99069# changes to a bibliography field should change the field type
1542 SwAuthorityField* pAuthorityField = static_cast<SwAuthorityField*>(pTmpFld);
1543 SwAuthorityFieldType* pAuthorityType = static_cast<SwAuthorityFieldType*>(pType);
1544 SwAuthEntry aTempEntry;
1545 for( sal_uInt16 i = 0; i < AUTH_FIELD_END; ++i )
1546 aTempEntry.SetAuthorField( (ToxAuthorityField)i,
1547 rPar1.GetToken( i, TOX_STYLE_DELIMITER ));
1548 if( pAuthorityType->ChangeEntryContent( &aTempEntry ) )
1550 pType->UpdateFlds();
1551 pSh->SetModified();
1554 if( aTempEntry.GetAuthorField( AUTH_FIELD_IDENTIFIER ) ==
1555 pAuthorityField->GetFieldText( AUTH_FIELD_IDENTIFIER ) )
1556 bSetPar1 = false; //otherwise it's a new or changed entry, the field needs to be updated
1557 bSetPar2 = false;
1559 break;
1562 // set format
1563 // setup format before SetPar2 because of NumberFormatter!
1564 pTmpFld->ChangeFormat(nFormat);
1566 if(bSetPar1)
1567 pTmpFld->SetPar1( sPar1 );
1568 if( bSetPar2 )
1569 pTmpFld->SetPar2( sPar2 );
1571 // kick off update
1572 if(nTypeId == TYP_DDEFLD ||
1573 nTypeId == TYP_USERFLD ||
1574 nTypeId == TYP_USRINPFLD)
1576 pType->UpdateFlds();
1577 pSh->SetModified();
1579 else {
1580 // mb: #32157
1581 pSh->SwEditShell::UpdateFlds(*pTmpFld);
1582 GetCurFld();
1585 if (bDelete)
1586 delete pTmpFld;
1588 pSh->EndAllAction();
1591 /*--------------------------------------------------------------------
1592 Description: explicitly evaluate ExpressionFields
1593 --------------------------------------------------------------------*/
1594 void SwFldMgr::EvalExpFlds(SwWrtShell* pSh)
1596 if (pSh == NULL)
1597 pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
1599 if(pSh)
1601 pSh->StartAllAction();
1602 pSh->UpdateExpFlds(sal_True);
1603 pSh->EndAllAction();
1606 sal_uInt16 SwFldMgr::GetCurrLanguage() const
1608 SwWrtShell* pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
1609 if( pSh )
1610 return pSh->GetCurLang();
1611 return SvtSysLocale().GetLanguageTag().getLanguageType();
1614 void SwFieldType::_GetFldName()
1616 static sal_uInt16 coFldNms[] = {
1617 FLD_DATE_STD,
1618 FLD_TIME_STD,
1619 STR_FILENAMEFLD,
1620 STR_DBNAMEFLD,
1621 STR_CHAPTERFLD,
1622 STR_PAGENUMBERFLD,
1623 STR_DOCSTATFLD,
1624 STR_AUTHORFLD,
1625 STR_SETFLD,
1626 STR_GETFLD,
1627 STR_FORMELFLD,
1628 STR_HIDDENTXTFLD,
1629 STR_SETREFFLD,
1630 STR_GETREFFLD,
1631 STR_DDEFLD,
1632 STR_MACROFLD,
1633 STR_INPUTFLD,
1634 STR_HIDDENPARAFLD,
1635 STR_DOCINFOFLD,
1636 STR_DBFLD,
1637 STR_USERFLD,
1638 STR_POSTITFLD,
1639 STR_TEMPLNAMEFLD,
1640 STR_SEQFLD,
1641 STR_DBNEXTSETFLD,
1642 STR_DBNUMSETFLD,
1643 STR_DBSETNUMBERFLD,
1644 STR_CONDTXTFLD,
1645 STR_NEXTPAGEFLD,
1646 STR_PREVPAGEFLD,
1647 STR_EXTUSERFLD,
1648 FLD_DATE_FIX,
1649 FLD_TIME_FIX,
1650 STR_SETINPUTFLD,
1651 STR_USRINPUTFLD,
1652 STR_SETREFPAGEFLD,
1653 STR_GETREFPAGEFLD,
1654 STR_INTERNETFLD,
1655 STR_JUMPEDITFLD,
1656 STR_SCRIPTFLD,
1657 STR_AUTHORITY,
1658 STR_COMBINED_CHARS,
1659 STR_DROPDOWN,
1660 STR_CUSTOM
1663 // insert infos for fields
1664 SwFieldType::pFldNames = new std::vector<String>;
1665 SwFieldType::pFldNames->reserve(SAL_N_ELEMENTS(coFldNms));
1666 for( sal_uInt16 nIdx = 0; nIdx < SAL_N_ELEMENTS(coFldNms); ++nIdx )
1668 String aTmp(SW_RESSTR( coFldNms[ nIdx ] ));
1669 aTmp.Assign( MnemonicGenerator::EraseAllMnemonicChars( aTmp ) );
1670 SwFieldType::pFldNames->push_back(aTmp);
1674 sal_Bool SwFldMgr::ChooseMacro(const String&)
1676 sal_Bool bRet = sal_False;
1678 // choose script dialog
1679 OUString aScriptURL = SfxApplication::ChooseScript();
1681 // the script selector dialog returns a valid script URL
1682 if ( !aScriptURL.isEmpty() )
1684 SetMacroPath( aScriptURL );
1685 bRet = sal_True;
1688 return bRet;
1691 void SwFldMgr::SetMacroPath(const String& rPath)
1693 sMacroPath = rPath;
1694 sMacroName = rPath;
1696 // try to set sMacroName member variable by parsing the macro path
1697 // using the new URI parsing services
1699 Reference< XComponentContext > xContext =
1700 ::comphelper::getProcessComponentContext();
1702 Reference< uri::XUriReferenceFactory >
1703 xFactory = uri::UriReferenceFactory::create( xContext );
1705 Reference< uri::XVndSunStarScriptUrl >
1706 xUrl( xFactory->parse( sMacroPath ), UNO_QUERY );
1708 if ( xUrl.is() )
1710 sMacroName = xUrl->getName();
1714 sal_uLong SwFldMgr::GetDefaultFormat(sal_uInt16 nTypeId, bool bIsText, SvNumberFormatter* pFormatter, double* pVal)
1716 double fValue;
1717 short nDefFormat;
1719 switch (nTypeId)
1721 case TYP_TIMEFLD:
1722 case TYP_DATEFLD:
1724 Date aDate( Date::SYSTEM );
1725 Date* pNullDate = pFormatter->GetNullDate();
1727 fValue = aDate - *pNullDate;
1729 Time aTime( Time::SYSTEM );
1731 sal_uLong nNumFmtTime = (sal_uLong)aTime.GetSec() + (sal_uLong)aTime.GetMin() * 60L +
1732 (sal_uLong)aTime.GetHour() * 3600L;
1734 fValue += (double)nNumFmtTime / 86400.0;
1736 nDefFormat = (nTypeId == TYP_DATEFLD) ? NUMBERFORMAT_DATE : NUMBERFORMAT_TIME;
1738 break;
1740 default:
1741 if (bIsText)
1743 fValue = 0.0;
1744 nDefFormat = NUMBERFORMAT_TEXT;
1746 else
1748 fValue = 0.0;
1749 nDefFormat = NUMBERFORMAT_ALL;
1751 break;
1754 if (pVal)
1755 *pVal = fValue;
1757 return pFormatter->GetStandardFormat(nDefFormat, GetCurrLanguage());
1760 Reference<XNumberingTypeInfo> SwFldMgr::GetNumberingInfo() const
1762 if(!xNumberingInfo.is())
1764 Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
1765 Reference<XDefaultNumberingProvider> xDefNum = text::DefaultNumberingProvider::create(xContext);
1766 ((SwFldMgr*)this)->xNumberingInfo = Reference<XNumberingTypeInfo>(xDefNum, UNO_QUERY);
1768 return xNumberingInfo;
1771 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */