1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <unotxdoc.hxx>
26 #include <com/sun/star/beans/XPropertyAccess.hpp>
28 #include <comphelper/sequence.hxx>
29 #include <o3tl/string_view.hxx>
30 #include <tools/json_writer.hxx>
31 #include <tools/urlobj.hxx>
32 #include <xmloff/odffields.hxx>
34 #include <IDocumentMarkAccess.hxx>
37 #include <fmtrfmrk.hxx>
39 #include <txtrfmrk.hxx>
42 using namespace ::com::sun::star
;
46 /// Implements getCommandValues(".uno:TextFormFields").
50 /// - type: e.g. ODF_UNHANDLED
51 /// - commandPrefix: field command prefix to not return all fieldmarks
52 void GetTextFormFields(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
53 const std::map
<OUString
, OUString
>& rArguments
)
56 OUString aCommandPrefix
;
58 auto it
= rArguments
.find("type");
59 if (it
!= rArguments
.end())
64 it
= rArguments
.find("commandPrefix");
65 if (it
!= rArguments
.end())
67 aCommandPrefix
= it
->second
;
71 SwDoc
* pDoc
= pDocShell
->GetDoc();
72 IDocumentMarkAccess
* pMarkAccess
= pDoc
->getIDocumentMarkAccess();
73 tools::ScopedJsonWriterArray aFields
= rJsonWriter
.startArray("fields");
74 for (auto it
= pMarkAccess
->getFieldmarksBegin(); it
!= pMarkAccess
->getFieldmarksEnd(); ++it
)
76 auto pFieldmark
= dynamic_cast<sw::mark::IFieldmark
*>(*it
);
78 if (pFieldmark
->GetFieldname() != aType
)
83 auto itParam
= pFieldmark
->GetParameters()->find(ODF_CODE_PARAM
);
84 if (itParam
== pFieldmark
->GetParameters()->end())
90 itParam
->second
>>= aCommand
;
91 if (!aCommand
.startsWith(aCommandPrefix
))
96 tools::ScopedJsonWriterStruct aField
= rJsonWriter
.startStruct();
97 rJsonWriter
.put("type", aType
);
98 rJsonWriter
.put("command", aCommand
);
102 /// Implements getCommandValues(".uno:TextFormField").
106 /// - type: e.g. ODF_UNHANDLED
107 /// - commandPrefix: field command prefix to not return all fieldmarks
108 void GetTextFormField(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
109 const std::map
<OUString
, OUString
>& rArguments
)
112 OUString aCommandPrefix
;
113 auto it
= rArguments
.find("type");
114 if (it
!= rArguments
.end())
119 it
= rArguments
.find("commandPrefix");
120 if (it
!= rArguments
.end())
122 aCommandPrefix
= it
->second
;
125 IDocumentMarkAccess
& rIDMA
= *pDocShell
->GetDoc()->getIDocumentMarkAccess();
126 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
127 SwPosition
& rCursor
= *pWrtShell
->GetCursor()->GetPoint();
128 sw::mark::IFieldmark
* pFieldmark
= rIDMA
.getInnerFieldmarkFor(rCursor
);
129 auto typeNode
= rJsonWriter
.startNode("field");
135 if (pFieldmark
->GetFieldname() != aType
)
140 auto itParam
= pFieldmark
->GetParameters()->find(ODF_CODE_PARAM
);
141 if (itParam
== pFieldmark
->GetParameters()->end())
147 itParam
->second
>>= aCommand
;
148 if (!aCommand
.startsWith(aCommandPrefix
))
153 rJsonWriter
.put("type", aType
);
154 rJsonWriter
.put("command", aCommand
);
157 /// Implements getCommandValues(".uno:SetDocumentProperties").
161 /// - namePrefix: field name prefix to not return all user-defined properties
162 void GetDocumentProperties(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
163 const std::map
<OUString
, OUString
>& rArguments
)
165 OUString aNamePrefix
;
166 auto it
= rArguments
.find("namePrefix");
167 if (it
!= rArguments
.end())
169 aNamePrefix
= it
->second
;
172 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(pDocShell
->GetModel(),
174 uno::Reference
<document::XDocumentProperties
> xDP
= xDPS
->getDocumentProperties();
175 uno::Reference
<beans::XPropertyAccess
> xUDP(xDP
->getUserDefinedProperties(), uno::UNO_QUERY
);
176 auto aUDPs
= comphelper::sequenceToContainer
<std::vector
<beans::PropertyValue
>>(
177 xUDP
->getPropertyValues());
178 tools::ScopedJsonWriterArray aProperties
= rJsonWriter
.startArray("userDefinedProperties");
179 for (const auto& rUDP
: aUDPs
)
181 if (!rUDP
.Name
.startsWith(aNamePrefix
))
186 if (rUDP
.Value
.getValueTypeClass() != uno::TypeClass_STRING
)
192 rUDP
.Value
>>= aValue
;
194 tools::ScopedJsonWriterStruct aProperty
= rJsonWriter
.startStruct();
195 rJsonWriter
.put("name", rUDP
.Name
);
196 rJsonWriter
.put("type", "string");
197 rJsonWriter
.put("value", aValue
);
201 /// Implements getCommandValues(".uno:Bookmarks").
205 /// - namePrefix: bookmark name prefix to not return all bookmarks
206 void GetBookmarks(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
207 const std::map
<OUString
, OUString
>& rArguments
)
209 OUString aNamePrefix
;
211 auto it
= rArguments
.find("namePrefix");
212 if (it
!= rArguments
.end())
214 aNamePrefix
= it
->second
;
218 IDocumentMarkAccess
& rIDMA
= *pDocShell
->GetDoc()->getIDocumentMarkAccess();
219 tools::ScopedJsonWriterArray aBookmarks
= rJsonWriter
.startArray("bookmarks");
220 for (auto it
= rIDMA
.getBookmarksBegin(); it
!= rIDMA
.getBookmarksEnd(); ++it
)
222 sw::mark::IMark
* pMark
= *it
;
223 if (!pMark
->GetName().startsWith(aNamePrefix
))
228 tools::ScopedJsonWriterStruct aProperty
= rJsonWriter
.startStruct();
229 rJsonWriter
.put("name", pMark
->GetName());
233 /// Implements getCommandValues(".uno:Bookmark").
237 /// - namePrefix: bookmark name prefix to not return all bookmarks
238 void GetBookmark(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
239 const std::map
<OUString
, OUString
>& rArguments
)
241 OUString aNamePrefix
;
243 auto it
= rArguments
.find("namePrefix");
244 if (it
!= rArguments
.end())
246 aNamePrefix
= it
->second
;
250 IDocumentMarkAccess
& rIDMA
= *pDocShell
->GetDoc()->getIDocumentMarkAccess();
251 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
252 SwPosition
& rCursor
= *pWrtShell
->GetCursor()->GetPoint();
253 sw::mark::IMark
* pBookmark
= rIDMA
.getOneInnermostBookmarkFor(rCursor
);
254 tools::ScopedJsonWriterNode aBookmark
= rJsonWriter
.startNode("bookmark");
260 if (!pBookmark
->GetName().startsWith(aNamePrefix
))
265 rJsonWriter
.put("name", pBookmark
->GetName());
268 /// Implements getCommandValues(".uno:Fields").
272 /// - typeName: field type condition to not return all fields
273 /// - namePrefix: field name prefix to not return all fields
274 void GetFields(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
275 const std::map
<OUString
, OUString
>& rArguments
)
279 auto it
= rArguments
.find("typeName");
280 if (it
!= rArguments
.end())
282 aTypeName
= it
->second
;
285 // See SwFieldTypeFromString().
286 if (aTypeName
!= "SetRef")
291 OUString aNamePrefix
;
293 auto it
= rArguments
.find("namePrefix");
294 if (it
!= rArguments
.end())
296 aNamePrefix
= it
->second
;
300 SwDoc
* pDoc
= pDocShell
->GetDoc();
301 tools::ScopedJsonWriterArray aBookmarks
= rJsonWriter
.startArray("setRefs");
302 std::vector
<const SwFormatRefMark
*> aRefMarks
;
303 for (sal_uInt16 i
= 0; i
< pDoc
->GetRefMarks(); ++i
)
305 aRefMarks
.push_back(pDoc
->GetRefMark(i
));
307 // Sort the refmarks based on their start position.
308 std::sort(aRefMarks
.begin(), aRefMarks
.end(),
309 [](const SwFormatRefMark
* pMark1
, const SwFormatRefMark
* pMark2
) -> bool {
310 const SwTextRefMark
* pTextRefMark1
= pMark1
->GetTextRefMark();
311 const SwTextRefMark
* pTextRefMark2
= pMark2
->GetTextRefMark();
312 SwPosition
aPos1(pTextRefMark1
->GetTextNode(), pTextRefMark1
->GetStart());
313 SwPosition
aPos2(pTextRefMark2
->GetTextNode(), pTextRefMark2
->GetStart());
314 return aPos1
< aPos2
;
317 for (const auto& pRefMark
: aRefMarks
)
319 if (!pRefMark
->GetRefName().startsWith(aNamePrefix
))
324 tools::ScopedJsonWriterStruct aProperty
= rJsonWriter
.startStruct();
325 rJsonWriter
.put("name", pRefMark
->GetRefName());
329 /// Implements getCommandValues(".uno:Field").
333 /// - typeName: field type condition to not return all fields
334 /// - namePrefix: field name prefix to not return all fields
335 void GetField(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
336 const std::map
<OUString
, OUString
>& rArguments
)
340 auto it
= rArguments
.find("typeName");
341 if (it
!= rArguments
.end())
343 aTypeName
= it
->second
;
346 // See SwFieldTypeFromString().
347 if (aTypeName
!= "SetRef")
352 OUString aNamePrefix
;
354 auto it
= rArguments
.find("namePrefix");
355 if (it
!= rArguments
.end())
357 aNamePrefix
= it
->second
;
361 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
362 SwPosition
& rCursor
= *pWrtShell
->GetCursor()->GetPoint();
363 SwTextNode
* pTextNode
= rCursor
.GetNode().GetTextNode();
364 std::vector
<SwTextAttr
*> aAttrs
365 = pTextNode
->GetTextAttrsAt(rCursor
.GetContentIndex(), RES_TXTATR_REFMARK
);
366 tools::ScopedJsonWriterNode aRefmark
= rJsonWriter
.startNode("setRef");
372 const SwFormatRefMark
& rRefmark
= aAttrs
[0]->GetRefMark();
373 if (!rRefmark
.GetRefName().startsWith(aNamePrefix
))
378 rJsonWriter
.put("name", rRefmark
.GetRefName());
381 /// Implements getCommandValues(".uno:Sections").
385 /// - namePrefix: field name prefix to not return all sections
386 void GetSections(tools::JsonWriter
& rJsonWriter
, SwDocShell
* pDocShell
,
387 const std::map
<OUString
, OUString
>& rArguments
)
389 OUString aNamePrefix
;
391 auto it
= rArguments
.find("namePrefix");
392 if (it
!= rArguments
.end())
394 aNamePrefix
= it
->second
;
398 SwDoc
* pDoc
= pDocShell
->GetDoc();
399 tools::ScopedJsonWriterArray aBookmarks
= rJsonWriter
.startArray("sections");
400 for (const auto& pSection
: pDoc
->GetSections())
402 if (!pSection
->GetName().startsWith(aNamePrefix
))
407 tools::ScopedJsonWriterStruct aProperty
= rJsonWriter
.startStruct();
408 rJsonWriter
.put("name", pSection
->GetName());
413 bool SwXTextDocument::supportsCommand(std::u16string_view rCommand
)
415 static const std::initializer_list
<std::u16string_view
> vForward
416 = { u
"TextFormFields", u
"TextFormField", u
"SetDocumentProperties",
417 u
"Bookmarks", u
"Fields", u
"Sections",
418 u
"Bookmark", u
"Field" };
420 return std::find(vForward
.begin(), vForward
.end(), rCommand
) != vForward
.end();
423 void SwXTextDocument::getCommandValues(tools::JsonWriter
& rJsonWriter
, std::string_view rCommand
)
425 std::map
<OUString
, OUString
> aMap
;
427 static constexpr OStringLiteral
aTextFormFields(".uno:TextFormFields");
428 static constexpr OStringLiteral
aTextFormField(".uno:TextFormField");
429 static constexpr OStringLiteral
aSetDocumentProperties(".uno:SetDocumentProperties");
430 static constexpr OStringLiteral
aBookmarks(".uno:Bookmarks");
431 static constexpr OStringLiteral
aFields(".uno:Fields");
432 static constexpr OStringLiteral
aSections(".uno:Sections");
433 static constexpr OStringLiteral
aBookmark(".uno:Bookmark");
434 static constexpr OStringLiteral
aField(".uno:Field");
436 INetURLObject
aParser(OUString::fromUtf8(rCommand
));
437 OUString aArguments
= aParser
.GetParam();
438 sal_Int32 nParamIndex
= 0;
441 std::u16string_view aParam
= o3tl::getToken(aArguments
, 0, '&', nParamIndex
);
442 sal_Int32 nIndex
= 0;
447 std::u16string_view aToken
= o3tl::getToken(aParam
, 0, '=', nIndex
);
452 } while (nIndex
>= 0);
453 OUString aDecodedValue
454 = INetURLObject::decode(aValue
, INetURLObject::DecodeMechanism::WithCharset
);
455 aMap
[aKey
] = aDecodedValue
;
456 } while (nParamIndex
>= 0);
458 if (o3tl::starts_with(rCommand
, aTextFormFields
))
460 GetTextFormFields(rJsonWriter
, m_pDocShell
, aMap
);
462 if (o3tl::starts_with(rCommand
, aTextFormField
))
464 GetTextFormField(rJsonWriter
, m_pDocShell
, aMap
);
466 else if (o3tl::starts_with(rCommand
, aSetDocumentProperties
))
468 GetDocumentProperties(rJsonWriter
, m_pDocShell
, aMap
);
470 else if (o3tl::starts_with(rCommand
, aBookmarks
))
472 GetBookmarks(rJsonWriter
, m_pDocShell
, aMap
);
474 else if (o3tl::starts_with(rCommand
, aFields
))
476 GetFields(rJsonWriter
, m_pDocShell
, aMap
);
478 else if (o3tl::starts_with(rCommand
, aSections
))
480 GetSections(rJsonWriter
, m_pDocShell
, aMap
);
482 else if (o3tl::starts_with(rCommand
, aBookmark
))
484 GetBookmark(rJsonWriter
, m_pDocShell
, aMap
);
486 else if (o3tl::starts_with(rCommand
, aField
))
488 GetField(rJsonWriter
, m_pDocShell
, aMap
);
492 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */