Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/source/uibase/fldui/fldmgr.cxx
Line
Count
Source
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 <config_features.h>
21
#include <config_fuzzers.h>
22
23
#include <cmdid.h>
24
#include <hintids.hxx>
25
#include <o3tl/enumrange.hxx>
26
#include <svl/numformat.hxx>
27
#include <svl/stritem.hxx>
28
#include <com/sun/star/text/DefaultNumberingProvider.hpp>
29
#include <com/sun/star/text/XDefaultNumberingProvider.hpp>
30
#include <com/sun/star/text/XNumberingTypeInfo.hpp>
31
#include <com/sun/star/style/NumberingType.hpp>
32
#include <com/sun/star/beans/XPropertySet.hpp>
33
#include <com/sun/star/sdbc/XConnection.hpp>
34
#include <com/sun/star/sdbc/XDataSource.hpp>
35
#include <com/sun/star/uri/UriReferenceFactory.hpp>
36
#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
37
#include <comphelper/processfactory.hxx>
38
#include <comphelper/string.hxx>
39
#include <o3tl/string_view.hxx>
40
#include <tools/resary.hxx>
41
#include <osl/diagnose.h>
42
#include <sfx2/dispatch.hxx>
43
#include <sfx2/linkmgr.hxx>
44
#include <sfx2/app.hxx>
45
#include <sfx2/viewfrm.hxx>
46
#include <svx/strarray.hxx>
47
#include <fmtrfmrk.hxx>
48
#include <svl/zforlist.hxx>
49
#include <svl/zformat.hxx>
50
#include <vcl/mnemonic.hxx>
51
#include <view.hxx>
52
#include <wrtsh.hxx>
53
#include <doc.hxx>
54
#include <swmodule.hxx>
55
#include <fmtinfmt.hxx>
56
#include <cellatr.hxx>
57
#include <dbmgr.hxx>
58
#include <shellres.hxx>
59
#include <fldbas.hxx>
60
#include <docufld.hxx>
61
#include <chpfld.hxx>
62
#include <ddefld.hxx>
63
#include <expfld.hxx>
64
#include <reffld.hxx>
65
#include <usrfld.hxx>
66
#include <dbfld.hxx>
67
#include <authfld.hxx>
68
#include <flddat.hxx>
69
#include <fldmgr.hxx>
70
#include <ndtxt.hxx>
71
#include <cntfrm.hxx>
72
#include <flddropdown.hxx>
73
#include <strings.hrc>
74
#include <tox.hxx>
75
#include <viewopt.hxx>
76
#include <txmsrt.hxx>
77
#include <pam2html.hxx>
78
#include <unotools/useroptions.hxx>
79
#include <IDocumentContentOperations.hxx>
80
#if ENABLE_YRS
81
#include <IDocumentState.hxx>
82
#include <txtfld.hxx>
83
#endif
84
#include <txtrfmrk.hxx>
85
86
using namespace com::sun::star::uno;
87
using namespace com::sun::star::container;
88
using namespace com::sun::star::beans;
89
using namespace com::sun::star::text;
90
using namespace com::sun::star::style;
91
using namespace com::sun::star::sdbc;
92
using namespace ::com::sun::star;
93
94
// groups of fields
95
enum
96
{
97
    GRP_DOC_BEGIN   =  0,
98
    GRP_DOC_END     =  GRP_DOC_BEGIN + 12,
99
100
    GRP_FKT_BEGIN   =  GRP_DOC_END,
101
    GRP_FKT_END     =  GRP_FKT_BEGIN + 8,
102
103
    GRP_REF_BEGIN   =  GRP_FKT_END,
104
    GRP_REF_END     =  GRP_REF_BEGIN + 2,
105
106
    GRP_REG_BEGIN   =  GRP_REF_END,
107
    GRP_REG_END     =  GRP_REG_BEGIN + 1,
108
109
    GRP_DB_BEGIN    =  GRP_REG_END,
110
    GRP_DB_END      =  GRP_DB_BEGIN  + 5,
111
112
    GRP_VAR_BEGIN   =  GRP_DB_END,
113
    GRP_VAR_END     =  GRP_VAR_BEGIN + 9
114
};
115
116
enum
117
{
118
    GRP_WEB_DOC_BEGIN   =  0,
119
    GRP_WEB_DOC_END     =  GRP_WEB_DOC_BEGIN + 9,
120
121
    GRP_WEB_FKT_BEGIN   =  GRP_WEB_DOC_END + 2,
122
    GRP_WEB_FKT_END     =  GRP_WEB_FKT_BEGIN + 0,   // the group is empty!
123
124
    GRP_WEB_REF_BEGIN   =  GRP_WEB_FKT_END + 6,     // the group is empty!
125
    GRP_WEB_REF_END     =  GRP_WEB_REF_BEGIN + 0,
126
127
    GRP_WEB_REG_BEGIN   =  GRP_WEB_REF_END + 2,
128
    GRP_WEB_REG_END     =  GRP_WEB_REG_BEGIN + 1,
129
130
    GRP_WEB_DB_BEGIN    =  GRP_WEB_REG_END,         // the group is empty!
131
    GRP_WEB_DB_END      =  GRP_WEB_DB_BEGIN  + 0,
132
133
    GRP_WEB_VAR_BEGIN   =  GRP_WEB_DB_END + 5,
134
    GRP_WEB_VAR_END     =  GRP_WEB_VAR_BEGIN + 1
135
};
136
137
const sal_uInt16 VF_COUNT = 1; // { 0 }
138
const sal_uInt16 VF_USR_COUNT = 2; // { 0, nsSwExtendedSubType::SUB_CMD }
139
const sal_uInt16 VF_DB_COUNT = 1; // { nsSwExtendedSubType::SUB_OWN_FMT }
140
141
const TranslateId FLD_EU_ARY[] =
142
{
143
    FLD_EU_COMPANY,
144
    FLD_EU_GIVENNAME,
145
    FLD_EU_SURNAME,
146
    FLD_EU_INITIALS,
147
    FLD_EU_STREET,
148
    FLD_EU_COUNTRY,
149
    FLD_EU_POSTCODE,
150
    FLD_EU_TOWN,
151
    FLD_EU_TITLE,
152
    FLD_EU_POS,
153
    FLD_EU_TELPERSONAL,
154
    FLD_EU_TELWORK,
155
    FLD_EU_FAX,
156
    FLD_EU_EMAIL,
157
    FLD_EU_REGION
158
};
159
160
const TranslateId FMT_AUTHOR_ARY[] =
161
{
162
    FMT_AUTHOR_NAME,
163
    FMT_AUTHOR_SCUT
164
};
165
166
const TranslateId FLD_DATE_ARY[] =
167
{
168
    FLD_DATE_FIX,
169
    FLD_DATE_STD,
170
};
171
172
const TranslateId FLD_TIME_ARY[] =
173
{
174
    FLD_TIME_FIX,
175
    FLD_TIME_STD
176
};
177
178
const TranslateId FMT_NUM_ARY[] =
179
{
180
    FMT_NUM_ABC,
181
    FMT_NUM_SABC,
182
    FMT_NUM_ABC_N,
183
    FMT_NUM_SABC_N,
184
    FMT_NUM_ROMAN,
185
    FMT_NUM_SROMAN,
186
    FMT_NUM_ARABIC,
187
    FMT_NUM_PAGEDESC,
188
    FMT_NUM_PAGESPECIAL
189
};
190
191
// tdf#170392 - this should be aligned with enum SwFileNameFormat in sw/inc/fldbas.hxx
192
// including com::sun::star::text::FilenameDisplayFormat
193
const TranslateId FMT_FF_ARY[] =
194
{
195
    FMT_FF_PATHNAME,
196
    FMT_FF_PATH,
197
    FMT_FF_NAME_NOEXT,
198
    FMT_FF_NAME,
199
    FMT_FF_UI_NAME,
200
    FMT_FF_UI_RANGE
201
};
202
203
const TranslateId FLD_STAT_ARY[] =
204
{
205
    FLD_STAT_PAGE,
206
    FLD_STAT_PAGE_RANGE,
207
    FLD_STAT_PARA,
208
    FLD_STAT_WORD,
209
    FLD_STAT_CHAR,
210
    FLD_STAT_TABLE,
211
    FLD_STAT_GRF,
212
    FLD_STAT_OBJ
213
};
214
215
const TranslateId FMT_CHAPTER_ARY[] =
216
{
217
    FMT_CHAPTER_NO,
218
    FMT_CHAPTER_NAME,
219
    FMT_CHAPTER_NAMENO,
220
    FMT_CHAPTER_NO_NOSEPARATOR
221
};
222
223
const TranslateId FLD_INPUT_ARY[] =
224
{
225
    FLD_INPUT_TEXT
226
};
227
228
const TranslateId FMT_MARK_ARY[] =
229
{
230
    FMT_MARK_TEXT,
231
    FMT_MARK_TABLE,
232
    FMT_MARK_FRAME,
233
    FMT_MARK_GRAFIC,
234
    FMT_MARK_OLE
235
};
236
237
const TranslateId FMT_REF_ARY[] =
238
{
239
    FMT_REF_PAGE,
240
    FMT_REF_CHAPTER,
241
    FMT_REF_TEXT,
242
    FMT_REF_UPDOWN,
243
    FMT_REF_PAGE_PGDSC,
244
    FMT_REF_ONLYNUMBER,
245
    FMT_REF_ONLYCAPTION,
246
    FMT_REF_ONLYSEQNO,
247
    FMT_REF_NUMBER,
248
    FMT_REF_NUMBER_NO_CONTEXT,
249
    FMT_REF_NUMBER_FULL_CONTEXT
250
};
251
252
const TranslateId FMT_REG_ARY[] =
253
{
254
    FMT_REG_AUTHOR,
255
    FMT_REG_TIME,
256
    FMT_REG_DATE
257
};
258
259
const TranslateId FMT_DBFLD_ARY[] =
260
{
261
    FMT_DBFLD_DB,
262
    FMT_DBFLD_SYS
263
};
264
265
const TranslateId FMT_SETVAR_ARY[] =
266
{
267
    FMT_SETVAR_SYS,
268
    FMT_SETVAR_TEXT
269
};
270
271
const TranslateId FMT_GETVAR_ARY[] =
272
{
273
    FMT_GETVAR_TEXT,
274
    FMT_GETVAR_NAME
275
};
276
277
const TranslateId FMT_DDE_ARY[] =
278
{
279
    FMT_DDE_NORMAL,
280
    FMT_DDE_HOT
281
};
282
283
const TranslateId FLD_PAGEREF_ARY[] =
284
{
285
    FLD_PAGEREF_OFF,
286
    FLD_PAGEREF_ON
287
};
288
289
const TranslateId FMT_USERVAR_ARY[] =
290
{
291
    FMT_USERVAR_TEXT,
292
    FMT_USERVAR_CMD
293
};
294
295
namespace {
296
297
// field types and subtypes
298
struct SwFieldPack
299
{
300
    SwFieldTypesEnum nTypeId;
301
302
    const TranslateId* pSubTypeResIds;
303
    size_t       nSubTypeLength;
304
305
    const TranslateId* pFormatResIds;
306
    size_t       nFormatLength;
307
};
308
309
}
310
311
// strings and formats
312
const SwFieldPack aSwFields[] =
313
{
314
    // Document
315
    { SwFieldTypesEnum::ExtendedUser,       FLD_EU_ARY,         std::size(FLD_EU_ARY),     nullptr,          0 },
316
    { SwFieldTypesEnum::Author,             nullptr,            0,                         FMT_AUTHOR_ARY,   std::size(FMT_AUTHOR_ARY) },
317
    { SwFieldTypesEnum::Date,               FLD_DATE_ARY,       std::size(FLD_DATE_ARY),   nullptr,          0 },
318
    { SwFieldTypesEnum::Time,               FLD_TIME_ARY,       std::size(FLD_TIME_ARY),   nullptr,          0 },
319
    { SwFieldTypesEnum::PageNumber,         nullptr,            0,                         FMT_NUM_ARY,      std::size(FMT_NUM_ARY) -1 },
320
    { SwFieldTypesEnum::NextPage,           nullptr,            0,                         FMT_NUM_ARY,      std::size(FMT_NUM_ARY) },
321
    { SwFieldTypesEnum::PreviousPage,       nullptr,            0,                         FMT_NUM_ARY,      std::size(FMT_NUM_ARY) },
322
    { SwFieldTypesEnum::Filename,           nullptr,            0,                         FMT_FF_ARY,       std::size(FMT_FF_ARY) },
323
    { SwFieldTypesEnum::DocumentStatistics, FLD_STAT_ARY,       std::size(FLD_STAT_ARY),   FMT_NUM_ARY,      std::size(FMT_NUM_ARY) -1 },
324
325
    { SwFieldTypesEnum::Chapter,            nullptr,            0,                         FMT_CHAPTER_ARY,  std::size(FMT_CHAPTER_ARY) },
326
    { SwFieldTypesEnum::TemplateName,       nullptr,            0,                         FMT_FF_ARY,       std::size(FMT_FF_ARY) },
327
    { SwFieldTypesEnum::ParagraphSignature, nullptr,            0,                         nullptr,          0 },
328
329
    // Functions
330
    { SwFieldTypesEnum::ConditionalText,    nullptr,            0,                         nullptr,          0 },
331
    { SwFieldTypesEnum::Dropdown,           nullptr,            0,                         nullptr,          0 },
332
    { SwFieldTypesEnum::Input,              FLD_INPUT_ARY,      std::size(FLD_INPUT_ARY),  nullptr,          0 },
333
    { SwFieldTypesEnum::Macro,              nullptr,            0,                         nullptr,          0 },
334
    { SwFieldTypesEnum::JumpEdit,           nullptr,            0,                         FMT_MARK_ARY,     std::size(FMT_MARK_ARY) },
335
    { SwFieldTypesEnum::CombinedChars,      nullptr,            0,                         nullptr,          0 },
336
    { SwFieldTypesEnum::HiddenText,         nullptr,            0,                         nullptr,          0 },
337
    { SwFieldTypesEnum::HiddenParagraph,    nullptr,            0,                         nullptr,          0 },
338
339
    // Cross-References
340
    { SwFieldTypesEnum::SetRef,             nullptr,            0,                         nullptr,          0 },
341
    { SwFieldTypesEnum::GetRef,             nullptr,            0,                         FMT_REF_ARY,      std::size(FMT_REF_ARY) },
342
343
    // DocInformation
344
    { SwFieldTypesEnum::DocumentInfo,       nullptr,            0,                         FMT_REG_ARY,      std::size(FMT_REG_ARY) },
345
346
    // Database
347
    { SwFieldTypesEnum::Database,           nullptr,            0,                         FMT_DBFLD_ARY,    std::size(FMT_DBFLD_ARY) },
348
    { SwFieldTypesEnum::DatabaseNextSet,    nullptr,            0,                         nullptr,          0 },
349
    { SwFieldTypesEnum::DatabaseNumberSet,  nullptr,            0,                         nullptr,          0 },
350
    { SwFieldTypesEnum::DatabaseSetNumber,  nullptr,            0,                         FMT_NUM_ARY,      std::size(FMT_NUM_ARY) - 2 },
351
    { SwFieldTypesEnum::DatabaseName,       nullptr,            0,                         nullptr,          0 },
352
353
    // Variables
354
    { SwFieldTypesEnum::Set,                nullptr,            0,                         FMT_SETVAR_ARY,   std::size(FMT_SETVAR_ARY) },
355
356
    { SwFieldTypesEnum::Get,                nullptr,            0,                         FMT_GETVAR_ARY,   std::size(FMT_GETVAR_ARY) },
357
    { SwFieldTypesEnum::DDE,                nullptr,            0,                         FMT_DDE_ARY,      std::size(FMT_DDE_ARY) },
358
    { SwFieldTypesEnum::Formel,             nullptr,            0,                         FMT_GETVAR_ARY,   std::size(FMT_GETVAR_ARY) },
359
    { SwFieldTypesEnum::Input,              FLD_INPUT_ARY,      std::size(FLD_INPUT_ARY),  nullptr,          0 },
360
    { SwFieldTypesEnum::Sequence,           nullptr,            0,                         FMT_NUM_ARY,      std::size(FMT_NUM_ARY) - 2 },
361
    { SwFieldTypesEnum::SetRefPage,         FLD_PAGEREF_ARY,    std::size(FLD_PAGEREF_ARY),nullptr,          0 },
362
    { SwFieldTypesEnum::GetRefPage,         nullptr,            0,                         FMT_NUM_ARY,      std::size(FMT_NUM_ARY) - 1 },
363
    { SwFieldTypesEnum::User,               nullptr,            0,                         FMT_USERVAR_ARY,  std::size(FMT_USERVAR_ARY) }
364
};
365
366
// access to the shell
367
static SwWrtShell* lcl_GetShell()
368
0
{
369
0
    if (SwView* pView = GetActiveView())
370
0
        return pView->GetWrtShellPtr();
371
0
    return nullptr;
372
0
}
373
374
0
static sal_uInt16 GetPackCount() {  return std::size(aSwFields); }
375
376
// FieldManager controls inserting and updating of fields
377
SwFieldMgr::SwFieldMgr(SwWrtShell* pSh ) :
378
0
    m_pWrtShell(pSh),
379
0
    m_bEvalExp(true)
380
0
{
381
    // determine current field if existing
382
0
    GetCurField();
383
0
}
384
385
SwFieldMgr::~SwFieldMgr()
386
0
{
387
0
}
388
389
// organise RefMark by names
390
bool  SwFieldMgr::CanInsertRefMark( const SwMarkName& rStr )
391
0
{
392
0
    bool bRet = false;
393
0
    SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
394
0
    OSL_ENSURE(pSh, "no SwWrtShell found");
395
0
    if(pSh)
396
0
    {
397
0
        sal_uInt16 nCnt = pSh->GetCursorCnt();
398
399
        // the last Cursor doesn't have to be a spanned selection
400
0
        if( 1 < nCnt && !pSh->SwCursorShell::HasSelection() )
401
0
            --nCnt;
402
403
0
        bRet =  2 > nCnt && nullptr == pSh->GetRefMark( rStr );
404
0
    }
405
0
    return bRet;
406
0
}
407
408
// access over ResIds
409
void SwFieldMgr::RemoveFieldType(SwFieldIds nResId, const OUString& rName )
410
0
{
411
0
    SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
412
0
    OSL_ENSURE(pSh, "no SwWrtShell found");
413
0
    if( pSh )
414
0
        pSh->RemoveFieldType(nResId, rName);
415
0
}
416
417
size_t SwFieldMgr::GetFieldTypeCount() const
418
0
{
419
0
    SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
420
0
    OSL_ENSURE(pSh, "no SwWrtShell found");
421
0
    return pSh ? pSh->GetFieldTypeCount() : 0;
422
0
}
423
424
SwFieldType* SwFieldMgr::GetFieldType(SwFieldIds nResId, size_t nField) const
425
0
{
426
0
    SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
427
0
    OSL_ENSURE(pSh, "no SwWrtShell found");
428
0
    return pSh ? pSh->GetFieldType(nField, nResId) : nullptr;
429
0
}
430
431
SwFieldType* SwFieldMgr::GetFieldType(SwFieldIds nResId, const OUString& rName) const
432
0
{
433
0
    SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
434
0
    OSL_ENSURE(pSh, "no SwWrtShell found");
435
0
    return pSh ? pSh->GetFieldType(nResId, rName) : nullptr;
436
0
}
437
438
// determine current field
439
SwField* SwFieldMgr::GetCurField()
440
0
{
441
0
    SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
442
0
    if ( pSh )
443
0
        m_pCurField = pSh->GetCurField( true );
444
0
    else
445
0
        m_pCurField = nullptr;
446
447
    // initialise strings and format
448
0
    m_aCurPar1.clear();
449
0
    m_aCurPar2.clear();
450
0
    m_sCurFrame.clear();
451
452
0
    if(!m_pCurField)
453
0
        return nullptr;
454
455
    // preprocess current values; determine parameter 1 and parameter 2
456
457
0
    m_aCurPar1    = m_pCurField->GetPar1();
458
0
    m_aCurPar2    = m_pCurField->GetPar2();
459
460
0
    return m_pCurField;
461
0
}
462
463
// provide group range
464
const SwFieldGroupRgn& SwFieldMgr::GetGroupRange(bool bHtmlMode, SwFieldGroup nGrpId)
465
0
{
466
0
    static SwFieldGroupRgn const aRanges[] =
467
0
    {
468
0
        { /* Document   */  GRP_DOC_BEGIN,  GRP_DOC_END },
469
0
        { /* Functions  */  GRP_FKT_BEGIN,  GRP_FKT_END },
470
0
        { /* Cross-Refs */  GRP_REF_BEGIN,  GRP_REF_END },
471
0
        { /* DocInfos   */  GRP_REG_BEGIN,  GRP_REG_END },
472
0
        { /* Database   */  GRP_DB_BEGIN,   GRP_DB_END  },
473
0
        { /* User       */  GRP_VAR_BEGIN,  GRP_VAR_END }
474
0
    };
475
0
    static SwFieldGroupRgn const aWebRanges[] =
476
0
    {
477
0
        { /* Document    */  GRP_WEB_DOC_BEGIN,  GRP_WEB_DOC_END },
478
0
        { /* Functions   */  GRP_WEB_FKT_BEGIN,  GRP_WEB_FKT_END },
479
0
        { /* Cross-Refs  */  GRP_WEB_REF_BEGIN,  GRP_WEB_REF_END },
480
0
        { /* DocInfos    */  GRP_WEB_REG_BEGIN,  GRP_WEB_REG_END },
481
0
        { /* Database    */  GRP_WEB_DB_BEGIN,   GRP_WEB_DB_END  },
482
0
        { /* User        */  GRP_WEB_VAR_BEGIN,  GRP_WEB_VAR_END }
483
0
    };
484
485
0
    if (bHtmlMode)
486
0
        return aWebRanges[static_cast<int>(nGrpId)];
487
0
    else
488
0
        return aRanges[static_cast<int>(nGrpId)];
489
0
}
490
491
// determine GroupId
492
SwFieldGroup SwFieldMgr::GetGroup(SwFieldTypesEnum nTypeId, sal_uInt16 nSubType)
493
0
{
494
0
    if (nTypeId == SwFieldTypesEnum::SetInput)
495
0
        nTypeId = SwFieldTypesEnum::Set;
496
497
0
    if (nTypeId == SwFieldTypesEnum::Input && (static_cast<SwInputFieldSubType>(nSubType) & SwInputFieldSubType::User))
498
0
        nTypeId = SwFieldTypesEnum::User;
499
500
0
    if (nTypeId == SwFieldTypesEnum::FixedDate)
501
0
        nTypeId = SwFieldTypesEnum::Date;
502
503
0
    if (nTypeId == SwFieldTypesEnum::FixedTime)
504
0
        nTypeId = SwFieldTypesEnum::Time;
505
506
0
    for( auto i : o3tl::enumrange<SwFieldGroup>() )
507
0
    {
508
0
        const SwFieldGroupRgn& rRange = GetGroupRange(false/*bHtmlMode*/, i);
509
0
        for (sal_uInt16 nPos = rRange.nStart; nPos < rRange.nEnd; nPos++)
510
0
        {
511
0
            if (aSwFields[nPos].nTypeId == nTypeId)
512
0
                return i;
513
0
        }
514
0
    }
515
0
    assert(false);
516
0
    return SwFieldGroup::Document; // random choice
517
0
}
518
519
// determine names to TypeId
520
//  ACCESS over TYP_...
521
SwFieldTypesEnum SwFieldMgr::GetTypeId(sal_uInt16 nPos)
522
0
{
523
0
    assert(nPos < ::GetPackCount() && "forbidden Pos");
524
0
    return aSwFields[ nPos ].nTypeId;
525
0
}
526
527
const OUString & SwFieldMgr::GetTypeStr(sal_uInt16 nPos)
528
0
{
529
0
    assert(nPos < ::GetPackCount() && "forbidden TypeId");
530
531
0
    SwFieldTypesEnum nFieldWh = aSwFields[ nPos ].nTypeId;
532
533
0
    return SwFieldType::GetTypeStr( nFieldWh );
534
0
}
535
536
// determine Pos in the list
537
sal_uInt16 SwFieldMgr::GetPos(SwFieldTypesEnum nTypeId)
538
0
{
539
0
    switch( nTypeId )
540
0
    {
541
0
        case SwFieldTypesEnum::FixedDate:  nTypeId = SwFieldTypesEnum::Date;      break;
542
0
        case SwFieldTypesEnum::FixedTime:  nTypeId = SwFieldTypesEnum::Time;      break;
543
0
        case SwFieldTypesEnum::SetInput:   nTypeId = SwFieldTypesEnum::Set;       break;
544
0
        case SwFieldTypesEnum::UserInput:   nTypeId = SwFieldTypesEnum::User;      break;
545
0
        default: break;
546
0
    }
547
548
0
    for(sal_uInt16 i = 0; i < GetPackCount(); i++)
549
0
        if(aSwFields[i].nTypeId == nTypeId)
550
0
            return i;
551
552
0
    return USHRT_MAX;
553
0
}
554
555
// localise subtypes of a field
556
void SwFieldMgr::GetSubTypes(SwFieldTypesEnum nTypeId, std::vector<OUString>& rToFill)
557
0
{
558
0
    SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
559
0
    OSL_ENSURE(pSh, "no SwWrtShell found");
560
0
    if(!pSh)
561
0
        return;
562
563
0
    const sal_uInt16 nPos = GetPos(nTypeId);
564
565
0
    switch(nTypeId)
566
0
    {
567
0
        case SwFieldTypesEnum::SetRef:
568
0
        case SwFieldTypesEnum::GetRef:
569
0
        {
570
            // references are no fields
571
0
            pSh->GetRefMarks( &rToFill );
572
0
            break;
573
0
        }
574
0
        case SwFieldTypesEnum::Macro:
575
0
        {
576
0
            break;
577
0
        }
578
0
        case SwFieldTypesEnum::Input:
579
0
        {
580
0
            rToFill.push_back(SwResId(aSwFields[nPos].pSubTypeResIds[0]));
581
0
            [[fallthrough]]; // move on at generic types
582
0
        }
583
0
        case SwFieldTypesEnum::DDE:
584
0
        case SwFieldTypesEnum::Sequence:
585
0
        case SwFieldTypesEnum::Formel:
586
0
        case SwFieldTypesEnum::Get:
587
0
        case SwFieldTypesEnum::Set:
588
0
        case SwFieldTypesEnum::User:
589
0
        {
590
591
0
            const size_t nCount = pSh->GetFieldTypeCount();
592
0
            for(size_t i = 0; i < nCount; ++i)
593
0
            {
594
0
                SwFieldType* pFieldType = pSh->GetFieldType( i );
595
0
                const SwFieldIds nWhich = pFieldType->Which();
596
597
0
                if((nTypeId == SwFieldTypesEnum::DDE && pFieldType->Which() == SwFieldIds::Dde) ||
598
599
0
                   (nTypeId == SwFieldTypesEnum::User && nWhich == SwFieldIds::User) ||
600
601
0
                   (nTypeId == SwFieldTypesEnum::Get && nWhich == SwFieldIds::SetExp &&
602
0
                    !(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & SwGetSetExpType::Sequence)) ||
603
604
0
                   (nTypeId == SwFieldTypesEnum::Set && nWhich == SwFieldIds::SetExp &&
605
0
                    !(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & SwGetSetExpType::Sequence)) ||
606
607
0
                   (nTypeId == SwFieldTypesEnum::Sequence && nWhich == SwFieldIds::SetExp  &&
608
0
                   (static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & SwGetSetExpType::Sequence)) ||
609
610
0
                   ((nTypeId == SwFieldTypesEnum::Input || nTypeId == SwFieldTypesEnum::Formel) &&
611
0
                     (nWhich == SwFieldIds::User ||
612
0
                      (nWhich == SwFieldIds::SetExp &&
613
0
                      !(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & SwGetSetExpType::Sequence))) ) )
614
0
                {
615
0
                    rToFill.push_back(pFieldType->GetName().toString());
616
0
                }
617
0
            }
618
0
            break;
619
0
        }
620
0
        case SwFieldTypesEnum::DatabaseNextSet:
621
0
        case SwFieldTypesEnum::DatabaseNumberSet:
622
0
        case SwFieldTypesEnum::DatabaseName:
623
0
        case SwFieldTypesEnum::DatabaseSetNumber:
624
0
            break;
625
626
0
        default:
627
0
        {
628
            // static SubTypes
629
0
            if(nPos != USHRT_MAX)
630
0
            {
631
0
                sal_uInt16 nCount;
632
0
                if (nTypeId == SwFieldTypesEnum::DocumentInfo)
633
0
                    nCount = static_cast<sal_uInt16>(SwDocInfoSubType::SubtypeEnd) - static_cast<sal_uInt16>(SwDocInfoSubType::SubtypeBegin);
634
0
                else
635
0
                    nCount = aSwFields[nPos].nSubTypeLength;
636
637
0
                for(sal_uInt16 i = 0; i < nCount; ++i)
638
0
                {
639
0
                    OUString sNew;
640
0
                    if (nTypeId == SwFieldTypesEnum::DocumentInfo)
641
0
                    {
642
0
                        if ( i == static_cast<sal_uInt16>(SwDocInfoSubType::Custom) )
643
0
                            sNew = SwResId(STR_CUSTOM_FIELD);
644
0
                        else
645
0
                            sNew = SwViewShell::GetShellRes()->aDocInfoLst[i];
646
0
                    }
647
0
                    else
648
0
                        sNew = SwResId(aSwFields[nPos].pSubTypeResIds[i]);
649
650
0
                    rToFill.push_back(sNew);
651
0
                }
652
0
            }
653
0
        }
654
0
    }
655
0
}
656
657
// determine format
658
//  ACCESS over TYP_...
659
sal_uInt16 SwFieldMgr::GetFormatCount(SwFieldTypesEnum nTypeId, bool bHtmlMode) const
660
0
{
661
0
    assert(nTypeId <= SwFieldTypesEnum::LAST && "forbidden TypeId");
662
0
    {
663
0
        const sal_uInt16 nPos = GetPos(nTypeId);
664
665
0
        if (nPos == USHRT_MAX || (bHtmlMode && nTypeId == SwFieldTypesEnum::Set))
666
0
            return 0;
667
668
0
        sal_uInt16 nCount = aSwFields[nPos].nFormatLength;
669
670
0
        if (nTypeId == SwFieldTypesEnum::Filename)
671
0
            nCount -= 2;  // no range or template
672
673
0
        const TranslateId* pStart = aSwFields[nPos].pFormatResIds;
674
0
        if (!pStart)
675
0
            return nCount;
676
677
0
        if (*pStart == FMT_GETVAR_ARY[0] || *pStart == FMT_SETVAR_ARY[0])
678
0
            return VF_COUNT;
679
0
        else if (*pStart == FMT_USERVAR_ARY[0])
680
0
            return VF_USR_COUNT;
681
0
        else if (*pStart == FMT_DBFLD_ARY[0])
682
0
            return VF_DB_COUNT;
683
0
        else if (*pStart == FMT_NUM_ARY[0])
684
0
        {
685
0
            GetNumberingInfo();
686
0
            if(m_xNumberingInfo.is())
687
0
            {
688
0
                const Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
689
                // #i28073# it's not necessarily a sorted sequence
690
                //skip all values below or equal to CHARS_LOWER_LETTER_N
691
0
                nCount += std::count_if(aTypes.begin(), aTypes.end(),
692
0
                    [](sal_Int16 nCurrent) { return nCurrent > NumberingType::CHARS_LOWER_LETTER_N; });
693
0
            }
694
0
            return nCount;
695
0
        }
696
697
0
        return nCount;
698
0
    }
699
0
}
700
701
// determine FormatString to a type
702
OUString SwFieldMgr::GetFormatStr(const SwField& rField) const
703
0
{
704
0
    return GetFormatStr(rField.GetTypeId(), rField.GetUntypedFormat());
705
0
}
706
707
// determine FormatString to a type
708
OUString SwFieldMgr::GetFormatStr(SwFieldTypesEnum nTypeId, sal_uInt32 nFormatId) const
709
0
{
710
0
    assert(nTypeId <= SwFieldTypesEnum::LAST && "forbidden TypeId");
711
0
    const sal_uInt16 nPos = GetPos(nTypeId);
712
713
0
    if (nPos == USHRT_MAX)
714
0
        return OUString();
715
716
0
    const TranslateId* pStart = aSwFields[nPos].pFormatResIds;
717
0
    if (!pStart)
718
0
        return OUString();
719
720
0
    if (SwFieldTypesEnum::Author == nTypeId || SwFieldTypesEnum::Filename == nTypeId)
721
0
        nFormatId &= ~static_cast<sal_uInt32>(SwFileNameFormat::Fixed); // mask out Fixed-Flag
722
723
0
    if (nFormatId < aSwFields[nPos].nFormatLength)
724
0
        return SwResId(pStart[nFormatId]);
725
726
0
    OUString aRet;
727
0
    if (*pStart == FMT_NUM_ARY[0])
728
0
    {
729
0
        if (m_xNumberingInfo.is())
730
0
        {
731
0
            const Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
732
0
            sal_Int32 nOffset = aSwFields[nPos].nFormatLength;
733
0
            sal_uInt32 nValidEntry = 0;
734
0
            for (const sal_Int16 nCurrent : aTypes)
735
0
            {
736
0
                if(nCurrent > NumberingType::CHARS_LOWER_LETTER_N &&
737
0
                        (nCurrent != (NumberingType::BITMAP | LINK_TOKEN)))
738
0
                {
739
0
                    if (nValidEntry == nFormatId - nOffset)
740
0
                    {
741
0
                        sal_uInt32 n = SvxNumberingTypeTable::FindIndex(nCurrent);
742
0
                        if (n != RESARRAY_INDEX_NOTFOUND)
743
0
                        {
744
0
                            aRet = SvxNumberingTypeTable::GetString(n);
745
0
                        }
746
0
                        else
747
0
                        {
748
0
                            aRet = m_xNumberingInfo->getNumberingIdentifier( nCurrent );
749
0
                        }
750
0
                        break;
751
0
                    }
752
0
                    ++nValidEntry;
753
0
                }
754
0
            }
755
0
        }
756
0
    }
757
758
0
    return aRet;
759
0
}
760
761
// determine FormatId from Pseudo-ID
762
sal_uInt16 SwFieldMgr::GetFormatId(SwFieldTypesEnum nTypeId, sal_uInt32 nFormatId) const
763
0
{
764
0
    sal_uInt16 nId = o3tl::narrowing<sal_uInt16>(nFormatId);
765
0
    switch( nTypeId )
766
0
    {
767
0
        case SwFieldTypesEnum::DocumentInfo:
768
0
        {
769
0
            TranslateId sId = aSwFields[GetPos(nTypeId)].pFormatResIds[nFormatId];
770
0
            if (sId == FMT_REG_AUTHOR)
771
0
                nId = static_cast<sal_uInt16>(SwDocInfoSubType::SubAuthor);
772
0
            else if (sId == FMT_REG_TIME)
773
0
                nId = static_cast<sal_uInt16>(SwDocInfoSubType::SubTime);
774
0
            else if (sId == FMT_REG_DATE)
775
0
                nId = static_cast<sal_uInt16>(SwDocInfoSubType::SubDate);
776
0
            break;
777
0
        }
778
0
        case SwFieldTypesEnum::PageNumber:
779
0
        case SwFieldTypesEnum::NextPage:
780
0
        case SwFieldTypesEnum::PreviousPage:
781
0
        case SwFieldTypesEnum::DocumentStatistics:
782
0
        case SwFieldTypesEnum::DatabaseSetNumber:
783
0
        case SwFieldTypesEnum::Sequence:
784
0
        case SwFieldTypesEnum::GetRefPage:
785
0
        {
786
0
            sal_uInt16 nPos = GetPos(nTypeId);
787
0
            if (nFormatId < aSwFields[nPos].nFormatLength)
788
0
            {
789
0
                const TranslateId sId = aSwFields[nPos].pFormatResIds[nFormatId];
790
0
                if (sId == FMT_NUM_ABC)
791
0
                    nId = SVX_NUM_CHARS_UPPER_LETTER;
792
0
                else if (sId == FMT_NUM_SABC)
793
0
                    nId = SVX_NUM_CHARS_LOWER_LETTER;
794
0
                else if (sId == FMT_NUM_ROMAN)
795
0
                    nId = SVX_NUM_ROMAN_UPPER;
796
0
                else if (sId == FMT_NUM_SROMAN)
797
0
                    nId = SVX_NUM_ROMAN_LOWER;
798
0
                else if (sId == FMT_NUM_ARABIC)
799
0
                    nId = SVX_NUM_ARABIC;
800
0
                else if (sId == FMT_NUM_PAGEDESC)
801
0
                    nId = SVX_NUM_PAGEDESC;
802
0
                else if (sId == FMT_NUM_PAGESPECIAL)
803
0
                    nId = SVX_NUM_CHAR_SPECIAL;
804
0
                else if (sId == FMT_NUM_ABC_N)
805
0
                    nId = SVX_NUM_CHARS_UPPER_LETTER_N;
806
0
                else if (sId == FMT_NUM_SABC_N)
807
0
                    nId = SVX_NUM_CHARS_LOWER_LETTER_N;
808
0
            }
809
0
            else if (m_xNumberingInfo.is())
810
0
            {
811
0
                const Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
812
0
                sal_Int32 nOffset = aSwFields[nPos].nFormatLength;
813
0
                sal_Int32 nValidEntry = 0;
814
0
                for (const sal_Int16 nCurrent : aTypes)
815
0
                {
816
0
                    if (nCurrent > NumberingType::CHARS_LOWER_LETTER_N)
817
0
                    {
818
0
                        if (nValidEntry == static_cast<sal_Int32>(nFormatId) - nOffset)
819
0
                        {
820
0
                            nId = nCurrent;
821
0
                            break;
822
0
                        }
823
0
                        ++nValidEntry;
824
0
                    }
825
0
                }
826
0
            }
827
0
            break;
828
0
        }
829
0
        case SwFieldTypesEnum::DDE:
830
0
        {
831
0
            const TranslateId sId = aSwFields[GetPos(nTypeId)].pFormatResIds[nFormatId];
832
0
            if (sId == FMT_DDE_NORMAL)
833
0
                nId = static_cast<sal_uInt16>(SfxLinkUpdateMode::ONCALL);
834
0
            else if (sId == FMT_DDE_HOT)
835
0
                nId = static_cast<sal_uInt16>(SfxLinkUpdateMode::ALWAYS);
836
0
            break;
837
0
        }
838
0
        default: break;
839
0
    }
840
0
    return nId;
841
0
}
842
843
// Traveling
844
bool SwFieldMgr::GoNextPrev( bool bNext, SwFieldType* pTyp )
845
0
{
846
0
    SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
847
0
    if(!pSh)
848
0
        return false;
849
850
0
    if( !pTyp && m_pCurField )
851
0
    {
852
0
        const SwFieldTypesEnum nTypeId = m_pCurField->GetTypeId();
853
0
        if( SwFieldTypesEnum::SetInput == nTypeId || SwFieldTypesEnum::UserInput == nTypeId )
854
0
            pTyp = pSh->GetFieldType( 0, SwFieldIds::Input );
855
0
        else
856
0
            pTyp = m_pCurField->GetTyp();
857
0
    }
858
859
0
    if (pTyp && pTyp->Which() == SwFieldIds::Database)
860
0
    {
861
        // for fieldcommand-edit (hop to all DB fields)
862
0
        return pSh->MoveFieldType( nullptr, bNext, SwFieldIds::Database );
863
0
    }
864
865
0
    return pTyp && pSh->MoveFieldType(pTyp, bNext);
866
0
}
867
868
// insert field types
869
void SwFieldMgr::InsertFieldType(SwFieldType const & rType)
870
0
{
871
0
    SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
872
0
    OSL_ENSURE(pSh, "no SwWrtShell found");
873
0
    if(pSh)
874
0
        pSh->InsertFieldType(rType);
875
0
}
876
877
// determine current TypeId
878
SwFieldTypesEnum SwFieldMgr::GetCurTypeId() const
879
0
{
880
0
    return m_pCurField ? m_pCurField->GetTypeId() : SwFieldTypesEnum::Unknown;
881
0
}
882
883
// Over string  insert field or update
884
bool SwFieldMgr::InsertField(
885
    SwInsertField_Data& rData)
886
0
{
887
0
    std::unique_ptr<SwField> pField;
888
0
    bool bExp = false;
889
0
    bool bTable = false;
890
0
    bool bPageVar = false;
891
0
    sal_uInt32 nFormatId = rData.m_nFormatId;
892
0
    SwInputFieldSubType nInputSubType = SwInputFieldSubType::None; // only used for SwInputField
893
0
    sal_Unicode cSeparator = rData.m_cSeparator;
894
0
    SwWrtShell* pCurShell = rData.m_pSh;
895
0
    if(!pCurShell)
896
0
        pCurShell = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
897
0
    OSL_ENSURE(pCurShell, "no SwWrtShell found");
898
0
    if(!pCurShell)
899
0
        return false;
900
901
0
    switch (rData.m_nTypeId)
902
0
    {   // ATTENTION this field is inserted by a separate dialog
903
0
        case SwFieldTypesEnum::Postit:
904
0
        {
905
0
            SvtUserOptions aUserOpt;
906
0
            SwPostItFieldType* pType = static_cast<SwPostItFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Postit));
907
0
            auto const pPostItField(
908
0
                new SwPostItField(
909
0
                    pType,
910
0
                    rData.m_sPar1, // author
911
0
                    rData.m_sPar2, // content
912
0
                    aUserOpt.GetID(), // author's initials
913
0
                    SwMarkName(), // name
914
0
                    DateTime(DateTime::SYSTEM) ));
915
0
            if (rData.m_oParentId)
916
0
            {
917
0
                pPostItField->SetParentId(std::get<0>(*rData.m_oParentId));
918
0
                pPostItField->SetParentPostItId(std::get<1>(*rData.m_oParentId));
919
0
                pPostItField->SetParentName(std::get<2>(*rData.m_oParentId));
920
0
            }
921
#if ENABLE_YRS
922
            pPostItField->SetYrsCommentId(pCurShell->GetDoc()->getIDocumentState().YrsGenNewCommentId());
923
#endif
924
0
            pField.reset(pPostItField);
925
0
        }
926
0
        break;
927
0
        case SwFieldTypesEnum::Script:
928
0
        {
929
0
            SwScriptFieldType* pType =
930
0
                static_cast<SwScriptFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Script));
931
0
            pField.reset(new SwScriptField(pType, rData.m_sPar1, rData.m_sPar2, static_cast<bool>(nFormatId)));
932
0
            break;
933
0
        }
934
935
0
    case SwFieldTypesEnum::CombinedChars:
936
0
        {
937
0
            SwCombinedCharFieldType* pType = static_cast<SwCombinedCharFieldType*>(
938
0
                pCurShell->GetFieldType( 0, SwFieldIds::CombinedChars ));
939
0
            pField.reset(new SwCombinedCharField( pType, rData.m_sPar1 ));
940
0
        }
941
0
        break;
942
943
0
    case SwFieldTypesEnum::Authority:
944
0
        {
945
0
            SwAuthorityFieldType* pType =
946
0
                static_cast<SwAuthorityFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::TableOfAuthorities));
947
0
            if (!pType)
948
0
            {
949
0
                SwAuthorityFieldType const type(pCurShell->GetDoc());
950
0
                pType = static_cast<SwAuthorityFieldType*>(
951
0
                            pCurShell->InsertFieldType(type));
952
0
            }
953
0
            pField.reset(new SwAuthorityField(pType, rData.m_sPar1));
954
0
        }
955
0
        break;
956
957
0
    case SwFieldTypesEnum::Date:
958
0
    case SwFieldTypesEnum::Time:
959
0
        {
960
0
            sal_uInt16 nSubType = rData.m_nSubType;
961
0
            SwDateTimeSubType nSub = (rData.m_nTypeId == SwFieldTypesEnum::Date ? SwDateTimeSubType::Date : SwDateTimeSubType::Time);
962
0
            if (nSubType != DATE_VAR)
963
0
                nSub |= SwDateTimeSubType::Fixed;
964
965
0
            SwDateTimeFieldType* pTyp =
966
0
                static_cast<SwDateTimeFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::DateTime) );
967
0
            pField.reset(new SwDateTimeField(pTyp, nSub, nFormatId));
968
0
            pField->SetPar2(rData.m_sPar2);
969
0
            break;
970
0
        }
971
972
0
    case SwFieldTypesEnum::Filename:
973
0
        {
974
0
            SwFileNameFieldType* pTyp =
975
0
                static_cast<SwFileNameFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Filename) );
976
0
            pField.reset(new SwFileNameField(pTyp, static_cast<SwFileNameFormat>(nFormatId)));
977
0
            break;
978
0
        }
979
980
0
    case SwFieldTypesEnum::TemplateName:
981
0
        {
982
0
            SwTemplNameFieldType* pTyp =
983
0
                static_cast<SwTemplNameFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::TemplateName) );
984
0
            pField.reset(new SwTemplNameField(pTyp, static_cast<SwFileNameFormat>(nFormatId)));
985
0
            break;
986
0
        }
987
988
0
    case SwFieldTypesEnum::Chapter:
989
0
        {
990
0
            sal_uInt16 nByte = o3tl::narrowing<sal_uInt16>(rData.m_sPar2.toInt32());
991
0
            SwChapterFieldType* pTyp =
992
0
                static_cast<SwChapterFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Chapter) );
993
0
            pField.reset(new SwChapterField(pTyp, static_cast<SwChapterFormat>(nFormatId)));
994
0
            nByte = std::max(sal_uInt16(1), nByte);
995
0
            nByte = std::min(nByte, sal_uInt16(MAXLEVEL));
996
0
            nByte -= 1;
997
0
            static_cast<SwChapterField*>(pField.get())->SetLevel(static_cast<sal_uInt8>(nByte));
998
0
            break;
999
0
        }
1000
1001
0
    case SwFieldTypesEnum::NextPage:
1002
0
    case SwFieldTypesEnum::PreviousPage:
1003
0
    case SwFieldTypesEnum::PageNumber:
1004
0
        {
1005
0
            SwPageNumSubType nSubType = static_cast<SwPageNumSubType>(rData.m_nSubType);
1006
0
            short nOff = static_cast<short>(rData.m_sPar2.toInt32());
1007
1008
0
            if(rData.m_nTypeId == SwFieldTypesEnum::NextPage)
1009
0
            {
1010
0
                if( SVX_NUM_CHAR_SPECIAL == nFormatId )
1011
0
                    nOff = 1;
1012
0
                else
1013
0
                    nOff += 1;
1014
0
                nSubType = SwPageNumSubType::Next;
1015
0
            }
1016
0
            else if(rData.m_nTypeId == SwFieldTypesEnum::PreviousPage)
1017
0
            {
1018
0
                if( SVX_NUM_CHAR_SPECIAL == nFormatId )
1019
0
                    nOff = -1;
1020
0
                else
1021
0
                    nOff -= 1;
1022
0
                nSubType =  SwPageNumSubType::Previous;
1023
0
            }
1024
0
            else
1025
0
                nSubType = SwPageNumSubType::Random;
1026
1027
0
            SwPageNumberFieldType* pTyp =
1028
0
                static_cast<SwPageNumberFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::PageNumber) );
1029
0
            pField.reset(new SwPageNumberField(pTyp, nSubType, static_cast<SvxNumType>(nFormatId), nOff));
1030
1031
0
            if( SVX_NUM_CHAR_SPECIAL == nFormatId &&
1032
0
                ( SwPageNumSubType::Previous == nSubType || SwPageNumSubType::Next == nSubType ) )
1033
0
                static_cast<SwPageNumberField*>(pField.get())->SetUserString( rData.m_sPar2 );
1034
0
            break;
1035
0
        }
1036
1037
0
    case SwFieldTypesEnum::DocumentStatistics:
1038
0
        {
1039
0
            sal_uInt16 nSubType = rData.m_nSubType;
1040
0
            SwDocStatFieldType* pTyp =
1041
0
                static_cast<SwDocStatFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::DocStat) );
1042
0
            pField.reset(new SwDocStatField(pTyp, static_cast<SwDocStatSubType>(nSubType), static_cast<SvxNumType>(nFormatId)));
1043
0
            break;
1044
0
        }
1045
1046
0
    case SwFieldTypesEnum::Author:
1047
0
        {
1048
0
            SwAuthorFieldType* pTyp =
1049
0
                static_cast<SwAuthorFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Author) );
1050
0
            pField.reset(new SwAuthorField(pTyp, static_cast<SwAuthorFormat>(nFormatId)));
1051
0
            break;
1052
0
        }
1053
1054
0
    case SwFieldTypesEnum::ConditionalText:
1055
0
    case SwFieldTypesEnum::HiddenText:
1056
0
        {
1057
0
            SwHiddenTextFieldType* pTyp =
1058
0
                static_cast<SwHiddenTextFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::HiddenText) );
1059
0
            pField.reset(new SwHiddenTextField(pTyp, true, rData.m_sPar1, rData.m_sPar2, false, rData.m_nTypeId));
1060
0
            bExp = true;
1061
0
            break;
1062
0
        }
1063
1064
0
    case SwFieldTypesEnum::HiddenParagraph:
1065
0
        {
1066
0
            SwHiddenParaFieldType* pTyp =
1067
0
                static_cast<SwHiddenParaFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::HiddenPara) );
1068
0
            pField.reset(new SwHiddenParaField(pTyp, rData.m_sPar1));
1069
0
            bExp = true;
1070
0
            break;
1071
0
        }
1072
1073
0
    case SwFieldTypesEnum::SetRef:
1074
0
        {
1075
0
            if( !rData.m_sPar1.isEmpty() && CanInsertRefMark( SwMarkName(rData.m_sPar1) ) )
1076
0
            {
1077
0
                const OUString& rRefmarkText = rData.m_sPar2;
1078
0
                SwPaM* pCursorPos = pCurShell->GetCursor();
1079
0
                pCurShell->StartAction();
1080
0
                bool bHadMark = pCursorPos->HasMark();
1081
                // If we have no selection and the refmark text is provided, then the text is
1082
                // expected to be HTML.
1083
0
                if (!bHadMark && !rRefmarkText.isEmpty())
1084
0
                {
1085
                    // Split node to remember where the start position is.
1086
0
                    bool bSuccess = pCurShell->GetDoc()->getIDocumentContentOperations().SplitNode(
1087
0
                            *pCursorPos->GetPoint(), /*bChkTableStart=*/false);
1088
0
                    if (bSuccess)
1089
0
                    {
1090
0
                        SwPaM aRefmarkPam(*pCursorPos->GetPoint());
1091
0
                        aRefmarkPam.Move(fnMoveBackward, GoInContent);
1092
1093
                        // Paste HTML content.
1094
0
                        SwPam2Html::PasteHTMLToPaM(
1095
0
                                *pCurShell, pCursorPos, rRefmarkText.toUtf8());
1096
1097
                        // Undo the above SplitNode().
1098
0
                        aRefmarkPam.SetMark();
1099
0
                        aRefmarkPam.Move(fnMoveForward, GoInContent);
1100
0
                        pCurShell->GetDoc()->getIDocumentContentOperations().DeleteAndJoin(
1101
0
                                aRefmarkPam);
1102
0
                        *aRefmarkPam.GetMark() = *pCursorPos->GetPoint();
1103
0
                        *pCursorPos = aRefmarkPam;
1104
0
                    }
1105
0
                }
1106
1107
0
                pCurShell->SetAttrItem( SwFormatRefMark( SwMarkName(rData.m_sPar1) ) );
1108
0
                if (rData.m_bNeverExpand)
1109
0
                {
1110
0
                    SwTextRefMark* xTextRefMark = const_cast<SwTextRefMark*>(
1111
0
                        pCurShell->GetRefMark(SwMarkName(rData.m_sPar1))->GetTextRefMark());
1112
0
                    xTextRefMark->SetDontExpand(true);
1113
0
                    xTextRefMark->SetLockExpandFlag(true);
1114
0
                    xTextRefMark->SetDontExpandStartAttr(true);
1115
0
                }
1116
1117
0
                if (!bHadMark && !rRefmarkText.isEmpty())
1118
0
                {
1119
0
                    pCursorPos->DeleteMark();
1120
0
                }
1121
0
                pCurShell->EndAction();
1122
0
                return true;
1123
0
            }
1124
0
            return false;
1125
0
        }
1126
1127
0
    case SwFieldTypesEnum::GetRef:
1128
0
        {
1129
0
            ReferencesSubtype nSubType = static_cast<ReferencesSubtype>(rData.m_nSubType);
1130
0
            SwGetRefFieldType* pTyp =
1131
0
                static_cast<SwGetRefFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::GetRef) );
1132
1133
0
            sal_uInt16 nSeqNo = 0;
1134
0
            sal_uInt16 nFlags = 0;
1135
1136
0
            if (nSubType == ReferencesSubtype::Style) nFlags = o3tl::narrowing<sal_uInt16>(rData.m_sPar2.toInt32());
1137
0
            else nSeqNo = o3tl::narrowing<sal_uInt16>(rData.m_sPar2.toInt32());
1138
1139
0
            OUString sReferenceLanguage;
1140
            // handle language-variant formats
1141
0
            if (nFormatId >= std::size(FMT_REF_ARY))
1142
0
            {
1143
0
                LanguageType nLang = GetCurrLanguage();
1144
0
                if (nLang == LANGUAGE_HUNGARIAN)
1145
0
                {
1146
0
                    if (nFormatId >= std::size(FMT_REF_ARY) * 2)
1147
0
                        sReferenceLanguage = "Hu";
1148
0
                    else
1149
0
                        sReferenceLanguage = "hu";
1150
0
                }
1151
0
                nFormatId %= std::size(FMT_REF_ARY);
1152
0
            }
1153
1154
0
            pField.reset(new SwGetRefField(pTyp, SwMarkName(rData.m_sPar1), sReferenceLanguage, nSubType, nSeqNo, nFlags, static_cast<RefFieldFormat>(nFormatId)));
1155
0
            bExp = true;
1156
0
            break;
1157
0
        }
1158
1159
0
    case SwFieldTypesEnum::DDE:
1160
0
        {
1161
            //JP 28.08.95: DDE-Topics/-Items can have blanks in their names!
1162
            //              That's not yet considered here.
1163
0
            sal_Int32 nIndex = 0;
1164
0
            OUString sCmd = rData.m_sPar2.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex);
1165
0
            if (nIndex>=0 && ++nIndex<sCmd.getLength())
1166
0
            {
1167
0
                sCmd = sCmd.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex);
1168
0
            }
1169
1170
0
            SwDDEFieldType aType( UIName(rData.m_sPar1), sCmd, static_cast<SfxLinkUpdateMode>(nFormatId) );
1171
0
            SwDDEFieldType* pTyp = static_cast<SwDDEFieldType*>( pCurShell->InsertFieldType( aType ) );
1172
0
            pField.reset(new SwDDEField( pTyp ));
1173
0
            break;
1174
0
        }
1175
1176
0
    case SwFieldTypesEnum::Macro:
1177
0
        {
1178
0
            SwMacroFieldType* pTyp =
1179
0
                static_cast<SwMacroFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Macro));
1180
1181
0
            pField.reset(new SwMacroField(pTyp, rData.m_sPar1, rData.m_sPar2));
1182
1183
0
            break;
1184
0
        }
1185
1186
0
    case SwFieldTypesEnum::Internet:
1187
0
        {
1188
0
            SwFormatINetFormat aFormat( rData.m_sPar1, m_sCurFrame );
1189
0
            return pCurShell->InsertURL( aFormat, rData.m_sPar2 );
1190
0
        }
1191
1192
0
    case SwFieldTypesEnum::JumpEdit:
1193
0
        {
1194
0
            SwJumpEditFieldType* pTyp =
1195
0
                static_cast<SwJumpEditFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::JumpEdit));
1196
1197
0
            pField.reset(new SwJumpEditField(pTyp, static_cast<SwJumpEditFormat>(nFormatId), rData.m_sPar1, rData.m_sPar2));
1198
0
            break;
1199
0
        }
1200
1201
0
    case SwFieldTypesEnum::DocumentInfo:
1202
0
        {
1203
0
            sal_uInt16 nSubType = rData.m_nSubType;
1204
0
            SwDocInfoFieldType* pTyp = static_cast<SwDocInfoFieldType*>( pCurShell->GetFieldType(
1205
0
                0, SwFieldIds::DocInfo ) );
1206
0
            pField.reset(new SwDocInfoField(pTyp, static_cast<SwDocInfoSubType>(nSubType), rData.m_sPar1, nFormatId));
1207
0
            break;
1208
0
        }
1209
1210
0
    case SwFieldTypesEnum::ExtendedUser:
1211
0
        {
1212
0
            SwExtUserSubType nSubType = static_cast<SwExtUserSubType>(rData.m_nSubType);
1213
0
            SwExtUserFieldType* pTyp = static_cast<SwExtUserFieldType*>( pCurShell->GetFieldType(
1214
0
                0, SwFieldIds::ExtUser) );
1215
0
            pField.reset(new SwExtUserField(pTyp, nSubType, static_cast<SwAuthorFormat>(nFormatId)));
1216
0
            break;
1217
0
        }
1218
1219
0
    case SwFieldTypesEnum::Database:
1220
0
        {
1221
#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
1222
            SwDBData aDBData;
1223
            OUString sPar1;
1224
            SwDBFieldSubType nSubType = static_cast<SwDBFieldSubType>(rData.m_nSubType);
1225
1226
            if (rData.m_sPar1.indexOf(DB_DELIM)<0)
1227
            {
1228
                aDBData = pCurShell->GetDBData();
1229
                sPar1 = rData.m_sPar1;
1230
            }
1231
            else
1232
            {
1233
                sal_Int32 nIdx{ 0 };
1234
                aDBData.sDataSource = rData.m_sPar1.getToken(0, DB_DELIM, nIdx);
1235
                aDBData.sCommand = rData.m_sPar1.getToken(0, DB_DELIM, nIdx);
1236
                aDBData.nCommandType = o3tl::toInt32(o3tl::getToken(rData.m_sPar1, 0, DB_DELIM, nIdx));
1237
                sPar1 = rData.m_sPar1.getToken(0, DB_DELIM, nIdx);
1238
            }
1239
1240
            if(!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData)
1241
                pCurShell->ChgDBData(aDBData);
1242
1243
            SwDBFieldType* pTyp = static_cast<SwDBFieldType*>(pCurShell->InsertFieldType(
1244
                SwDBFieldType(pCurShell->GetDoc(), sPar1, aDBData) ) );
1245
            pField.reset(new SwDBField(pTyp, 0, nSubType));
1246
1247
            if( !(nSubType & SwDBFieldSubType::OwnFormat) ) // determine database format
1248
            {
1249
                Reference< XDataSource> xSource;
1250
                Reference<XConnection> xConnection;
1251
                rData.m_aDBConnection >>= xConnection;
1252
                Reference<XPropertySet> xColumn;
1253
                rData.m_aDBColumn >>= xColumn;
1254
                if(xColumn.is())
1255
                {
1256
                    nFormatId = SwDBManager::GetColumnFormat(xSource, xConnection, xColumn,
1257
                        pCurShell->GetNumberFormatter(), GetCurrLanguage() );
1258
                }
1259
                else
1260
                    nFormatId = pCurShell->GetDBManager()->GetColumnFormat(
1261
                    aDBData.sDataSource, aDBData.sCommand, sPar1,
1262
                    pCurShell->GetNumberFormatter(), GetCurrLanguage() );
1263
            }
1264
            static_cast<SwDBField*>(pField.get())->SetFormat( nFormatId );
1265
1266
            bExp = true;
1267
#endif
1268
0
            break;
1269
0
        }
1270
1271
0
    case SwFieldTypesEnum::DatabaseSetNumber:
1272
0
    case SwFieldTypesEnum::DatabaseNumberSet:
1273
0
    case SwFieldTypesEnum::DatabaseNextSet:
1274
0
    case SwFieldTypesEnum::DatabaseName:
1275
0
        {
1276
#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
1277
            SwDBData aDBData;
1278
1279
            // extract DBName from rData.m_sPar1. Format: DBName.TableName.CommandType.ExpStrg
1280
            sal_Int32 nTablePos = rData.m_sPar1.indexOf(DB_DELIM);
1281
            sal_Int32 nExpPos = -1;
1282
1283
            if (nTablePos>=0)
1284
            {
1285
                aDBData.sDataSource = rData.m_sPar1.copy(0, nTablePos++);
1286
                sal_Int32 nCmdTypePos = rData.m_sPar1.indexOf(DB_DELIM, nTablePos);
1287
                if (nCmdTypePos>=0)
1288
                {
1289
                    aDBData.sCommand = rData.m_sPar1.copy(nTablePos, nCmdTypePos++ - nTablePos);
1290
                    nExpPos = rData.m_sPar1.indexOf(DB_DELIM, nCmdTypePos);
1291
                    if (nExpPos>=0)
1292
                    {
1293
                        aDBData.nCommandType = o3tl::toInt32(rData.m_sPar1.subView(nCmdTypePos, nExpPos++ - nCmdTypePos));
1294
                    }
1295
                }
1296
            }
1297
1298
            sal_Int32 nPos = 0;
1299
            if (nExpPos>=0)
1300
                nPos = nExpPos;
1301
            else if (nTablePos>=0)
1302
                nPos = nTablePos;
1303
1304
            OUString sPar1 = rData.m_sPar1.copy(nPos);
1305
1306
            if (!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData)
1307
                pCurShell->ChgDBData(aDBData);
1308
1309
            switch(rData.m_nTypeId)
1310
            {
1311
            case SwFieldTypesEnum::DatabaseName:
1312
                {
1313
                    SwDBNameFieldType* pTyp =
1314
                        static_cast<SwDBNameFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::DatabaseName));
1315
                    pField.reset(new SwDBNameField(pTyp, aDBData));
1316
1317
                    break;
1318
                }
1319
            case SwFieldTypesEnum::DatabaseNextSet:
1320
                {
1321
                    SwDBNextSetFieldType* pTyp = static_cast<SwDBNextSetFieldType*>(pCurShell->GetFieldType(
1322
                        0, SwFieldIds::DbNextSet) );
1323
                    pField.reset(new SwDBNextSetField(pTyp, sPar1, aDBData));
1324
                    bExp = true;
1325
                    break;
1326
                }
1327
            case SwFieldTypesEnum::DatabaseNumberSet:
1328
                {
1329
                    SwDBNumSetFieldType* pTyp = static_cast<SwDBNumSetFieldType*>( pCurShell->GetFieldType(
1330
                        0, SwFieldIds::DbNumSet) );
1331
                    pField.reset(new SwDBNumSetField( pTyp, sPar1, rData.m_sPar2, aDBData));
1332
                    bExp = true;
1333
                    break;
1334
                }
1335
            case SwFieldTypesEnum::DatabaseSetNumber:
1336
                {
1337
                    SwDBSetNumberFieldType* pTyp = static_cast<SwDBSetNumberFieldType*>(
1338
                        pCurShell->GetFieldType(0, SwFieldIds::DbSetNumber) );
1339
                    pField.reset(new SwDBSetNumberField( pTyp, aDBData, nFormatId));
1340
                    bExp = true;
1341
                    break;
1342
                }
1343
            default: break;
1344
            }
1345
#endif
1346
0
            break;
1347
0
        }
1348
1349
0
    case SwFieldTypesEnum::User:
1350
0
        {
1351
0
            SwUserType nSubType = static_cast<SwUserType>(rData.m_nSubType);
1352
0
            SwUserFieldType* pTyp =
1353
0
                static_cast<SwUserFieldType*>( pCurShell->GetFieldType(SwFieldIds::User, rData.m_sPar1) );
1354
1355
            // only if existing
1356
0
            if(!pTyp)
1357
0
            {
1358
0
                pTyp = static_cast<SwUserFieldType*>( pCurShell->InsertFieldType(
1359
0
                    SwUserFieldType(pCurShell->GetDoc(), UIName(rData.m_sPar1))) );
1360
0
            }
1361
0
            if (pTyp->GetContent(nFormatId) != rData.m_sPar2)
1362
0
                pTyp->SetContent(rData.m_sPar2, nFormatId);
1363
0
            pField.reset(new SwUserField(pTyp, nSubType, nFormatId));
1364
0
            bTable = true;
1365
0
            break;
1366
0
        }
1367
1368
0
    case SwFieldTypesEnum::Input:
1369
0
        {
1370
0
            nInputSubType = static_cast<SwInputFieldSubType>(rData.m_nSubType);
1371
0
            if ((nInputSubType & SwInputFieldSubType::LowerMask) == SwInputFieldSubType::Var)
1372
0
            {
1373
0
                SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>(
1374
0
                    pCurShell->GetFieldType(SwFieldIds::SetExp, rData.m_sPar1) );
1375
1376
                // no Expression Type with this name existing -> create
1377
0
                if(pTyp)
1378
0
                {
1379
0
                    std::unique_ptr<SwSetExpField> pExpField(
1380
0
                        new SwSetExpField(pTyp, OUString(), nFormatId));
1381
1382
                    // Don't change type of SwSetExpFieldType:
1383
0
                    if (nInputSubType & SwInputFieldSubType::Invisible)
1384
0
                    {
1385
0
                        SwGetSetExpType nOldSubType = pExpField->GetSubType();
1386
0
                        pExpField->SetSubType(nOldSubType | SwGetSetExpType::Invisible);
1387
0
                    }
1388
0
                    pExpField->SetPromptText(rData.m_sPar2);
1389
0
                    pExpField->SetInputFlag(true) ;
1390
0
                    bExp = true;
1391
0
                    pField = std::move(pExpField);
1392
0
                }
1393
0
                else
1394
0
                    return false;
1395
0
            }
1396
0
            else
1397
0
            {
1398
0
                SwInputFieldType* pTyp =
1399
0
                    static_cast<SwInputFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Input) );
1400
1401
0
                pField.reset(
1402
0
                    new SwInputField( pTyp, rData.m_sPar1, rData.m_sPar2, nInputSubType|SwInputFieldSubType::Invisible, nFormatId));
1403
0
            }
1404
0
            break;
1405
0
        }
1406
1407
0
    case SwFieldTypesEnum::Set:
1408
0
        {
1409
0
            SwGetSetExpType nSubType = static_cast<SwGetSetExpType>(rData.m_nSubType);
1410
0
            if (rData.m_sPar2.isEmpty())   // empty variables are not allowed
1411
0
                return false;
1412
1413
0
            SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>( pCurShell->InsertFieldType(
1414
0
                SwSetExpFieldType(pCurShell->GetDoc(), UIName(rData.m_sPar1)) ) );
1415
1416
0
            std::unique_ptr<SwSetExpField> pExpField(new SwSetExpField( pTyp, rData.m_sPar2, nFormatId));
1417
0
            pExpField->SetSubType(nSubType);
1418
0
            pExpField->SetPar2(rData.m_sPar2);
1419
0
            bExp = true;
1420
0
            pField = std::move(pExpField);
1421
0
            break;
1422
0
        }
1423
1424
0
    case SwFieldTypesEnum::Sequence:
1425
0
        {
1426
0
            sal_uInt16 nSubType = rData.m_nSubType;
1427
0
            SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>( pCurShell->InsertFieldType(
1428
0
                SwSetExpFieldType(pCurShell->GetDoc(), UIName(rData.m_sPar1), SwGetSetExpType::Sequence)));
1429
1430
0
            sal_uInt8 nLevel = static_cast< sal_uInt8 >(nSubType & 0xff);
1431
1432
0
            pTyp->SetOutlineLvl(nLevel);
1433
0
            if (nLevel != 0x7f && cSeparator == 0)
1434
0
                cSeparator = '.';
1435
1436
0
            pTyp->SetDelimiter(OUString(cSeparator));
1437
0
            pField.reset(new SwSetExpField(pTyp, rData.m_sPar2, nFormatId));
1438
0
            bExp = true;
1439
0
            break;
1440
0
        }
1441
1442
0
    case SwFieldTypesEnum::Get:
1443
0
        {
1444
0
            SwGetSetExpType nSubType = static_cast<SwGetSetExpType>(rData.m_nSubType);
1445
            // is there a corresponding SetField
1446
0
            SwSetExpFieldType* pSetTyp = static_cast<SwSetExpFieldType*>(
1447
0
                pCurShell->GetFieldType(SwFieldIds::SetExp, rData.m_sPar1));
1448
1449
0
            if(pSetTyp)
1450
0
            {
1451
0
                SwGetExpFieldType* pTyp = static_cast<SwGetExpFieldType*>( pCurShell->GetFieldType(
1452
0
                    0, SwFieldIds::GetExp) );
1453
0
                pField.reset( new SwGetExpField(pTyp, rData.m_sPar1, nSubType | pSetTyp->GetType(), nFormatId) );
1454
0
                bExp = true;
1455
0
            }
1456
0
            else
1457
0
                return false;
1458
0
            break;
1459
0
        }
1460
1461
0
    case SwFieldTypesEnum::Formel:
1462
0
        {
1463
0
            if(pCurShell->GetFrameType(nullptr,false) & FrameTypeFlags::TABLE)
1464
0
            {
1465
0
                pCurShell->StartAllAction();
1466
1467
0
                SvNumberFormatter* pFormatter = pCurShell->GetDoc()->GetNumberFormatter();
1468
0
                const SvNumberformat* pEntry = pFormatter->GetEntry(nFormatId);
1469
1470
0
                if (pEntry)
1471
0
                {
1472
0
                    SfxStringItem aFormat(FN_NUMBER_FORMAT, pEntry->GetFormatstring());
1473
0
                    pCurShell->GetView().GetViewFrame().GetDispatcher()->
1474
0
                        ExecuteList(FN_NUMBER_FORMAT, SfxCallMode::SYNCHRON,
1475
0
                                { &aFormat });
1476
0
                }
1477
1478
0
                SfxItemSet aBoxSet(SfxItemSet::makeFixedSfxItemSet<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA>(pCurShell->GetAttrPool()));
1479
1480
0
                OUString sFormula(comphelper::string::stripStart(rData.m_sPar2, ' '));
1481
0
                if ( sFormula.startsWith("=") )
1482
0
                {
1483
0
                    sFormula = sFormula.copy(1);
1484
0
                }
1485
1486
0
                aBoxSet.Put( SwTableBoxFormula( sFormula ));
1487
0
                pCurShell->SetTableBoxFormulaAttrs( aBoxSet );
1488
0
                pCurShell->UpdateTable();
1489
1490
0
                pCurShell->EndAllAction();
1491
0
                return true;
1492
1493
0
            }
1494
0
            else
1495
0
            {
1496
0
                SwGetExpFieldType* pTyp = static_cast<SwGetExpFieldType*>(
1497
0
                    pCurShell->GetFieldType(0, SwFieldIds::GetExp) );
1498
0
                pField.reset( new SwGetExpField(pTyp, rData.m_sPar2, static_cast<SwGetSetExpType>(rData.m_nSubType), nFormatId) );
1499
0
                bExp = true;
1500
0
            }
1501
0
            break;
1502
0
        }
1503
0
        case SwFieldTypesEnum::SetRefPage:
1504
0
            pField.reset( new SwRefPageSetField( static_cast<SwRefPageSetFieldType*>(
1505
0
                                pCurShell->GetFieldType( 0, SwFieldIds::RefPageSet ) ),
1506
0
                                static_cast<short>(rData.m_sPar2.toInt32()), 0 != rData.m_nSubType  ) );
1507
0
            bPageVar = true;
1508
0
            break;
1509
1510
0
        case SwFieldTypesEnum::GetRefPage:
1511
0
            pField.reset( new SwRefPageGetField( static_cast<SwRefPageGetFieldType*>(
1512
0
                            pCurShell->GetFieldType( 0, SwFieldIds::RefPageGet ) ), static_cast<SvxNumType>(nFormatId) ) );
1513
0
            bPageVar = true;
1514
0
            break;
1515
0
        case SwFieldTypesEnum::Dropdown :
1516
0
        {
1517
0
            pField.reset( new SwDropDownField(pCurShell->GetFieldType( 0, SwFieldIds::Dropdown )) );
1518
0
            const sal_Int32 nTokenCount = comphelper::string::getTokenCount(rData.m_sPar2, DB_DELIM);
1519
0
            Sequence<OUString> aEntries(nTokenCount);
1520
0
            OUString* pArray = aEntries.getArray();
1521
0
            for(sal_Int32 nToken = 0, nIdx = 0; nToken < nTokenCount; nToken++)
1522
0
                pArray[nToken] = rData.m_sPar2.getToken(0, DB_DELIM, nIdx);
1523
0
            static_cast<SwDropDownField*>(pField.get())->SetItems(aEntries);
1524
0
            static_cast<SwDropDownField*>(pField.get())->SetName(rData.m_sPar1);
1525
0
        }
1526
0
        break;
1527
1528
        // Insert Paragraph Signature field by signing the paragraph.
1529
        // The resulting field is really a metadata field, created and added via signing.
1530
0
        case SwFieldTypesEnum::ParagraphSignature:
1531
0
            pCurShell->SignParagraph();
1532
0
            return true;
1533
1534
0
        default:
1535
0
        {   assert(false && "wrong field type");
1536
0
            return false;
1537
0
        }
1538
0
    }
1539
0
    assert(pField && "field not available");
1540
1541
    //the auto language flag has to be set prior to the language!
1542
0
    pField->SetAutomaticLanguage(rData.m_bIsAutomaticLanguage);
1543
0
    LanguageType nLang = GetCurrLanguage();
1544
0
    pField->SetLanguage(nLang);
1545
1546
    // insert
1547
0
    pCurShell->StartAllAction();
1548
1549
0
    ::std::optional<SwPosition> oAnchorStart;
1550
0
    bool const isSuccess = pCurShell->InsertField2(*pField, rData.m_oAnnotationRange ? &*rData.m_oAnnotationRange : nullptr, &oAnchorStart);
1551
1552
0
    if (isSuccess)
1553
0
    {
1554
0
        if (SwFieldTypesEnum::Input == rData.m_nTypeId)
1555
0
        {
1556
0
            pCurShell->Push();
1557
1558
            // start dialog, not before the field is inserted tdf#99529
1559
0
            pCurShell->Left(SwCursorSkipMode::Chars, false,
1560
0
                (SwInputFieldSubType::Var == (nInputSubType & SwInputFieldSubType::LowerMask) || pCurShell->GetViewOptions()->IsFieldName()) ? 1 : 2,
1561
0
                false);
1562
0
            pCurShell->StartInputFieldDlg(pField.get(), false, true, rData.m_pParent);
1563
1564
0
            pCurShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
1565
0
        }
1566
1567
0
        if (bExp && m_bEvalExp)
1568
0
        {
1569
0
            pCurShell->UpdateExpFields(true);
1570
0
        }
1571
1572
0
        if (bTable)
1573
0
        {
1574
0
            pCurShell->Left(SwCursorSkipMode::Chars, false, 1, false );
1575
0
            pCurShell->UpdateOneField(*pField);
1576
0
            pCurShell->Right(SwCursorSkipMode::Chars, false, 1, false );
1577
0
        }
1578
0
        else if (bPageVar)
1579
0
        {
1580
0
            static_cast<SwRefPageGetFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::RefPageGet))->UpdateFields();
1581
0
        }
1582
0
        else if (SwFieldTypesEnum::GetRef == rData.m_nTypeId)
1583
0
        {
1584
0
            pField->GetTyp()->UpdateFields();
1585
0
        }
1586
0
    }
1587
1588
    // delete temporary field
1589
0
    pField.reset();
1590
1591
0
    pCurShell->EndAllAction();
1592
1593
#if ENABLE_YRS
1594
    if (isSuccess && rData.m_nTypeId == SwFieldTypesEnum::Postit)
1595
    {
1596
        // now the SwAnnotationWin are created
1597
        // shell cursor is behind field
1598
        SwPosition const pos{pCurShell->GetCursor()->GetPoint()->nContent, -1};
1599
        pCurShell->GetDoc()->getIDocumentState().YrsAddComment(
1600
            pos, oAnchorStart,
1601
            static_cast<SwPostItField const&>(*SwCursorShell::GetTextFieldAtPos(&pos, ::sw::GetTextAttrMode::Default)->GetFormatField().GetField()),
1602
            true);
1603
    }
1604
#endif
1605
1606
0
    return isSuccess;
1607
0
}
1608
1609
// fields update
1610
void SwFieldMgr::UpdateCurField(sal_uInt32 nFormat,
1611
                            const OUString& rPar1,
1612
                            const OUString& rPar2,
1613
                            std::unique_ptr<SwField> pTmpField)
1614
0
{
1615
    // change format
1616
0
    assert(m_pCurField && "no field at CursorPos");
1617
1618
0
    if (!pTmpField)
1619
0
        pTmpField = m_pCurField->CopyField();
1620
1621
0
    SwFieldType* pType   = pTmpField->GetTyp();
1622
0
    const SwFieldTypesEnum nTypeId = pTmpField->GetTypeId();
1623
1624
0
    SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
1625
0
    OSL_ENSURE(pSh, "no SwWrtShell found");
1626
0
    if(!pSh)
1627
0
        return;
1628
0
    pSh->StartAllAction();
1629
1630
0
    bool bSetPar2 = true;
1631
0
    bool bSetPar1 = true;
1632
0
    OUString sPar2( rPar2 );
1633
1634
    // Order to Format
1635
0
    switch( nTypeId )
1636
0
    {
1637
0
        case SwFieldTypesEnum::DDE:
1638
0
        {
1639
            // DDE-Topics/-Items can have blanks in their names!
1640
            //  That's not yet considered here!
1641
0
            sal_Int32 nIndex = 0;
1642
0
            sPar2 = sPar2.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex );
1643
0
            if (nIndex>=0 && ++nIndex<sPar2.getLength())
1644
0
            {
1645
0
                sPar2 = sPar2.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex);
1646
0
            }
1647
0
            break;
1648
0
        }
1649
1650
0
        case SwFieldTypesEnum::Chapter:
1651
0
        {
1652
0
            sal_uInt16 nByte = o3tl::narrowing<sal_uInt16>(rPar2.toInt32());
1653
0
            nByte = std::max(sal_uInt16(1), nByte);
1654
0
            nByte = std::min(nByte, sal_uInt16(MAXLEVEL));
1655
0
            nByte -= 1;
1656
0
            static_cast<SwChapterField*>(pTmpField.get())->SetLevel(static_cast<sal_uInt8>(nByte));
1657
0
            bSetPar2 = false;
1658
0
            break;
1659
0
        }
1660
1661
0
        case SwFieldTypesEnum::Script:
1662
0
            static_cast<SwScriptField*>(pTmpField.get())->SetCodeURL(static_cast<bool>(nFormat));
1663
0
            break;
1664
1665
0
        case SwFieldTypesEnum::NextPage:
1666
0
            if( SVX_NUM_CHAR_SPECIAL == nFormat )
1667
0
            {
1668
0
                static_cast<SwPageNumberField*>(m_pCurField)->SetUserString( sPar2 );
1669
0
                sPar2 = "1";
1670
0
            }
1671
0
            else
1672
0
            {
1673
0
                if( nFormat + 2 == SVX_NUM_PAGEDESC )
1674
0
                    nFormat = SVX_NUM_PAGEDESC;
1675
0
                short nOff = static_cast<short>(sPar2.toInt32());
1676
0
                nOff += 1;
1677
0
                sPar2 = OUString::number(nOff);
1678
0
            }
1679
0
            break;
1680
1681
0
        case SwFieldTypesEnum::PreviousPage:
1682
0
            if( SVX_NUM_CHAR_SPECIAL == nFormat )
1683
0
            {
1684
0
                static_cast<SwPageNumberField*>(m_pCurField)->SetUserString( sPar2 );
1685
0
                sPar2 = "-1";
1686
0
            }
1687
0
            else
1688
0
            {
1689
0
                if( nFormat + 2 == SVX_NUM_PAGEDESC )
1690
0
                    nFormat = SVX_NUM_PAGEDESC;
1691
0
                short nOff = static_cast<short>(sPar2.toInt32());
1692
0
                nOff -= 1;
1693
0
                sPar2 = OUString::number(nOff);
1694
0
            }
1695
0
            break;
1696
1697
0
        case SwFieldTypesEnum::PageNumber:
1698
0
        case SwFieldTypesEnum::GetRefPage:
1699
0
            if( nFormat + 2 == SVX_NUM_PAGEDESC )
1700
0
                nFormat = SVX_NUM_PAGEDESC;
1701
0
            break;
1702
1703
0
        case SwFieldTypesEnum::GetRef:
1704
0
            {
1705
0
                bSetPar2 = false;
1706
0
                ReferencesSubtype nSubType = static_cast<ReferencesSubtype>(rPar2.toInt32());
1707
0
                static_cast<SwGetRefField*>(pTmpField.get())->SetSubType( nSubType );
1708
0
                const sal_Int32 nPos = rPar2.indexOf( '|' );
1709
0
                if( nPos>=0 )
1710
0
                    switch (nSubType) {
1711
0
                        case ReferencesSubtype::Style:
1712
0
                            static_cast<SwGetRefField*>(pTmpField.get())->SetFlags( o3tl::narrowing<sal_uInt16>(o3tl::toInt32(rPar2.subView( nPos + 1 ))));
1713
0
                            break;
1714
0
                        default:
1715
0
                            static_cast<SwGetRefField*>(pTmpField.get())->SetSeqNo( o3tl::narrowing<sal_uInt16>(o3tl::toInt32(rPar2.subView( nPos + 1 ))));
1716
0
                    }
1717
0
            }
1718
0
            break;
1719
0
        case SwFieldTypesEnum::Dropdown:
1720
0
        {
1721
0
            sal_Int32 nTokenCount = comphelper::string::getTokenCount(sPar2, DB_DELIM);
1722
0
            Sequence<OUString> aEntries(nTokenCount);
1723
0
            OUString* pArray = aEntries.getArray();
1724
0
            for(sal_Int32 nToken = 0, nIdx = 0; nToken < nTokenCount; nToken++)
1725
0
                pArray[nToken] = sPar2.getToken(0, DB_DELIM, nIdx);
1726
0
            static_cast<SwDropDownField*>(pTmpField.get())->SetItems(aEntries);
1727
0
            static_cast<SwDropDownField*>(pTmpField.get())->SetName(rPar1);
1728
0
            bSetPar1 = bSetPar2 = false;
1729
0
        }
1730
0
        break;
1731
0
        case SwFieldTypesEnum::Authority :
1732
0
        {
1733
            //#i99069# changes to a bibliography field should change the field type
1734
0
            SwAuthorityField* pAuthorityField = static_cast<SwAuthorityField*>(pTmpField.get());
1735
0
            SwAuthorityFieldType* pAuthorityType = static_cast<SwAuthorityFieldType*>(pType);
1736
0
            rtl::Reference<SwAuthEntry> xTempEntry(new SwAuthEntry);
1737
0
            for( sal_Int32 i = 0, nIdx = 0; i < AUTH_FIELD_END; ++i )
1738
0
                xTempEntry->SetAuthorField( static_cast<ToxAuthorityField>(i),
1739
0
                                rPar1.getToken( 0, TOX_STYLE_DELIMITER, nIdx ));
1740
1741
            // If just the page number of the URL changed, then update the current field and not
1742
            // others.
1743
0
            bool bEquivalent = true;
1744
0
            for (int i = 0; i < AUTH_FIELD_END; ++i)
1745
0
            {
1746
0
                auto eField = static_cast<ToxAuthorityField>(i);
1747
0
                if (eField == AUTH_FIELD_URL)
1748
0
                {
1749
0
                    if (SwTOXAuthority::GetSourceURL(xTempEntry->GetAuthorField(AUTH_FIELD_URL))
1750
0
                        != SwTOXAuthority::GetSourceURL(
1751
0
                               pAuthorityField->GetFieldText(AUTH_FIELD_URL)))
1752
0
                    {
1753
0
                        bEquivalent = false;
1754
0
                        break;
1755
0
                    }
1756
0
                }
1757
0
                else
1758
0
                {
1759
0
                    if (xTempEntry->GetAuthorField(eField) != pAuthorityField->GetFieldText(eField))
1760
0
                    {
1761
0
                        bEquivalent = false;
1762
0
                        break;
1763
0
                    }
1764
0
                }
1765
0
            }
1766
1767
0
            if (bEquivalent)
1768
0
            {
1769
0
                break;
1770
0
            }
1771
1772
0
            if( pAuthorityType->ChangeEntryContent( xTempEntry.get() ) )
1773
0
            {
1774
0
                pType->UpdateFields();
1775
0
                pSh->SetModified();
1776
0
            }
1777
1778
0
            if( xTempEntry->GetAuthorField( AUTH_FIELD_IDENTIFIER ) ==
1779
0
                pAuthorityField->GetFieldText( AUTH_FIELD_IDENTIFIER ) )
1780
0
                bSetPar1 = false; //otherwise it's a new or changed entry, the field needs to be updated
1781
0
            bSetPar2 = false;
1782
0
        }
1783
0
        break;
1784
0
        default: break;
1785
0
    }
1786
1787
    // set format
1788
    // setup format before SetPar2 because of NumberFormatter!
1789
0
    pTmpField->SetUntypedFormat(nFormat);
1790
1791
0
    if( bSetPar1 )
1792
0
        pTmpField->SetPar1( rPar1 );
1793
0
    if( bSetPar2 )
1794
0
        pTmpField->SetPar2( sPar2 );
1795
1796
    // kick off update
1797
0
    if(nTypeId == SwFieldTypesEnum::DDE ||
1798
0
       nTypeId == SwFieldTypesEnum::User ||
1799
0
       nTypeId == SwFieldTypesEnum::UserInput)
1800
0
    {
1801
0
        pType->UpdateFields();
1802
0
        pSh->SetModified();
1803
0
    }
1804
0
    else {
1805
        // mb: #32157
1806
0
        pSh->SwEditShell::UpdateOneField(*pTmpField);
1807
0
        GetCurField();
1808
0
    }
1809
1810
0
    pTmpField.reset();
1811
1812
0
    pSh->EndAllAction();
1813
0
}
1814
1815
// explicitly evaluate ExpressionFields
1816
void SwFieldMgr::EvalExpFields(SwWrtShell* pSh)
1817
0
{
1818
0
    if (pSh == nullptr)
1819
0
        pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
1820
1821
0
    if(pSh)
1822
0
    {
1823
0
        pSh->StartAllAction();
1824
0
        pSh->UpdateExpFields(true);
1825
0
        pSh->EndAllAction();
1826
0
    }
1827
0
}
1828
LanguageType SwFieldMgr::GetCurrLanguage() const
1829
0
{
1830
0
    SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
1831
0
    if( pSh )
1832
0
        return pSh->GetCurLang();
1833
0
    return SvtSysLocale().GetLanguageTag().getLanguageType();
1834
0
}
1835
1836
void SwFieldType::GetFieldName_()
1837
1
{
1838
1
    static constexpr o3tl::enumarray<SwFieldTypesEnum, TranslateId> coFieldNms
1839
1
    {
1840
1
        FLD_DATE_STD, /*Date*/
1841
1
        FLD_TIME_STD, /*Time*/
1842
1
        STR_FILENAMEFLD, /*Filename*/
1843
1
        STR_DBNAMEFLD, /*DatabaseName*/
1844
1
        STR_CHAPTERFLD, /*Chapter*/
1845
1
        STR_PAGENUMBERFLD, /*PageNumber*/
1846
1
        STR_DOCSTATFLD, /*DocumentStatistics*/
1847
1
        STR_AUTHORFLD, /*Author*/
1848
1
        STR_SETFLD, /*Set*/
1849
1
        STR_GETFLD, /*Get*/
1850
1
        STR_FORMELFLD, /*Formel*/
1851
1
        STR_HIDDENTXTFLD, /*HiddenText*/
1852
1
        STR_SETREFFLD, /*SetRef*/
1853
1
        STR_GETREFFLD, /*GetRef*/
1854
1
        STR_DDEFLD, /*DDE*/
1855
1
        STR_MACROFLD, /*Macro*/
1856
1
        STR_INPUTFLD, /*Input*/
1857
1
        STR_HIDDENPARAFLD, /*HiddenParagraph*/
1858
1
        STR_DOCINFOFLD, /*DocumentInfo*/
1859
1
        STR_DBFLD, /*Database*/
1860
1
        STR_USERFLD, /*User*/
1861
1
        STR_POSTITFLD, /*Postit*/
1862
1
        STR_TEMPLNAMEFLD, /*TemplateName*/
1863
1
        STR_SEQFLD, /*Sequence*/
1864
1
        STR_DBNEXTSETFLD, /*DatabaseNextSet*/
1865
1
        STR_DBNUMSETFLD, /*DatabaseNumberSet*/
1866
1
        STR_DBSETNUMBERFLD, /*DatabaseSetNumber*/
1867
1
        STR_CONDTXTFLD, /*ConditionalText*/
1868
1
        STR_NEXTPAGEFLD, /*NextPage*/
1869
1
        STR_PREVPAGEFLD, /*PreviousPage*/
1870
1
        STR_EXTUSERFLD, /*ExtendedUser*/
1871
1
        FLD_DATE_FIX, /*FixedDate*/
1872
1
        FLD_TIME_FIX, /*FixedTime*/
1873
1
        STR_SETINPUTFLD, /*SetInput*/
1874
1
        STR_USRINPUTFLD, /*UserInput*/
1875
1
        STR_SETREFPAGEFLD, /*SetRefPage*/
1876
1
        STR_GETREFPAGEFLD, /*GetRefPage*/
1877
1
        STR_INTERNETFLD, /*Internet*/
1878
1
        STR_JUMPEDITFLD, /*JumpEdit*/
1879
1
        STR_SCRIPTFLD, /*Script*/
1880
1
        STR_AUTHORITY, /*Authority*/
1881
1
        STR_COMBINED_CHARS, /*CombinedChars*/
1882
1
        STR_DROPDOWN, /*Dropdown*/
1883
1
        STR_CUSTOM_FIELD, /*Custom*/
1884
1
        STR_PARAGRAPH_SIGNATURE /*ParagraphSignature*/
1885
1
    };
1886
1887
    // insert infos for fields
1888
1
    SwFieldType::s_pFieldNames = new o3tl::enumarray<SwFieldTypesEnum, OUString>;
1889
1
    for( SwFieldTypesEnum i : o3tl::enumrange<SwFieldTypesEnum>() )
1890
45
    {
1891
45
        const OUString aTmp(SwResId(coFieldNms[i]));
1892
45
        (*SwFieldType::s_pFieldNames)[i] = MnemonicGenerator::EraseAllMnemonicChars( aTmp );
1893
45
    }
1894
1
}
1895
1896
bool SwFieldMgr::ChooseMacro(weld::Window* pDialogParent)
1897
0
{
1898
0
    bool bRet = false;
1899
1900
    // choose script dialog
1901
0
    OUString aScriptURL = SfxApplication::ChooseScript(pDialogParent);
1902
1903
    // the script selector dialog returns a valid script URL
1904
0
    if ( !aScriptURL.isEmpty() )
1905
0
    {
1906
0
        SetMacroPath( aScriptURL );
1907
0
        bRet = true;
1908
0
    }
1909
1910
0
    return bRet;
1911
0
}
1912
1913
void SwFieldMgr::SetMacroPath(const OUString& rPath)
1914
0
{
1915
0
    m_sMacroPath = rPath;
1916
0
    m_sMacroName = rPath;
1917
1918
    // try to set sMacroName member variable by parsing the macro path
1919
    // using the new URI parsing services
1920
1921
0
    const Reference< XComponentContext >& xContext =
1922
0
        ::comphelper::getProcessComponentContext();
1923
1924
0
    Reference< uri::XUriReferenceFactory >
1925
0
        xFactory = uri::UriReferenceFactory::create( xContext );
1926
1927
0
    Reference< uri::XVndSunStarScriptUrl >
1928
0
        xUrl( xFactory->parse( m_sMacroPath ), UNO_QUERY );
1929
1930
0
    if ( xUrl.is() )
1931
0
    {
1932
0
        m_sMacroName = xUrl->getName();
1933
0
    }
1934
0
}
1935
1936
sal_uInt32 SwFieldMgr::GetDefaultFormat(SwFieldTypesEnum nTypeId, bool bIsText, SvNumberFormatter* pFormatter)
1937
0
{
1938
0
    SvNumFormatType  nDefFormat;
1939
1940
0
    switch (nTypeId)
1941
0
    {
1942
0
        case SwFieldTypesEnum::Time:
1943
0
        case SwFieldTypesEnum::Date:
1944
0
        {
1945
0
            nDefFormat = (nTypeId == SwFieldTypesEnum::Date) ? SvNumFormatType::DATE : SvNumFormatType::TIME;
1946
0
        }
1947
0
        break;
1948
1949
0
        default:
1950
0
            if (bIsText)
1951
0
            {
1952
0
                nDefFormat = SvNumFormatType::TEXT;
1953
0
            }
1954
0
            else
1955
0
            {
1956
0
                nDefFormat = SvNumFormatType::ALL;
1957
0
            }
1958
0
            break;
1959
0
    }
1960
1961
0
    return pFormatter->GetStandardFormat(nDefFormat, GetCurrLanguage());
1962
0
}
1963
1964
Reference<XNumberingTypeInfo> const & SwFieldMgr::GetNumberingInfo() const
1965
0
{
1966
0
    if(!m_xNumberingInfo.is())
1967
0
    {
1968
0
        const Reference<XComponentContext>&         xContext( ::comphelper::getProcessComponentContext() );
1969
0
        Reference<XDefaultNumberingProvider> xDefNum = text::DefaultNumberingProvider::create(xContext);
1970
0
        const_cast<SwFieldMgr*>(this)->m_xNumberingInfo.set(xDefNum, UNO_QUERY);
1971
0
    }
1972
0
    return m_xNumberingInfo;
1973
0
}
1974
1975
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */