LibreOffice Module sw (master) 1
loktxdoc.cxx
Go to the documentation of this file.
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 <unotxdoc.hxx>
21
22#include <map>
23#include <utility>
24#include <vector>
25
26#include <com/sun/star/beans/XPropertyAccess.hpp>
27
29#include <o3tl/string_view.hxx>
30#include <tools/json_writer.hxx>
31#include <tools/urlobj.hxx>
32#include <xmloff/odffields.hxx>
33
35#include <doc.hxx>
36#include <docsh.hxx>
37#include <fmtrfmrk.hxx>
38#include <wrtsh.hxx>
39#include <txtrfmrk.hxx>
40#include <ndtxt.hxx>
41
42using namespace ::com::sun::star;
43
44namespace
45{
52void GetTextFormFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
53 const std::map<OUString, OUString>& rArguments)
54{
55 OUString aType;
56 OUString aCommandPrefix;
57 {
58 auto it = rArguments.find("type");
59 if (it != rArguments.end())
60 {
61 aType = it->second;
62 }
63
64 it = rArguments.find("commandPrefix");
65 if (it != rArguments.end())
66 {
67 aCommandPrefix = it->second;
68 }
69 }
70
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)
75 {
76 auto pFieldmark = dynamic_cast<sw::mark::IFieldmark*>(*it);
77 assert(pFieldmark);
78 if (pFieldmark->GetFieldname() != aType)
79 {
80 continue;
81 }
82
83 auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
84 if (itParam == pFieldmark->GetParameters()->end())
85 {
86 continue;
87 }
88
89 OUString aCommand;
90 itParam->second >>= aCommand;
91 if (!aCommand.startsWith(aCommandPrefix))
92 {
93 continue;
94 }
95
96 tools::ScopedJsonWriterStruct aField = rJsonWriter.startStruct();
97 rJsonWriter.put("type", aType);
98 rJsonWriter.put("command", aCommand);
99 }
100}
101
108void GetTextFormField(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
109 const std::map<OUString, OUString>& rArguments)
110{
111 OUString aType;
112 OUString aCommandPrefix;
113 auto it = rArguments.find("type");
114 if (it != rArguments.end())
115 {
116 aType = it->second;
117 }
118
119 it = rArguments.find("commandPrefix");
120 if (it != rArguments.end())
121 {
122 aCommandPrefix = it->second;
123 }
124
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");
130 if (!pFieldmark)
131 {
132 return;
133 }
134
135 if (pFieldmark->GetFieldname() != aType)
136 {
137 return;
138 }
139
140 auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
141 if (itParam == pFieldmark->GetParameters()->end())
142 {
143 return;
144 }
145
146 OUString aCommand;
147 itParam->second >>= aCommand;
148 if (!aCommand.startsWith(aCommandPrefix))
149 {
150 return;
151 }
152
153 rJsonWriter.put("type", aType);
154 rJsonWriter.put("command", aCommand);
155}
156
162void GetDocumentProperties(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
163 const std::map<OUString, OUString>& rArguments)
164{
165 OUString aNamePrefix;
166 auto it = rArguments.find("namePrefix");
167 if (it != rArguments.end())
168 {
169 aNamePrefix = it->second;
170 }
171
172 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(pDocShell->GetModel(),
173 uno::UNO_QUERY);
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)
180 {
181 if (!rUDP.Name.startsWith(aNamePrefix))
182 {
183 continue;
184 }
185
186 if (rUDP.Value.getValueTypeClass() != uno::TypeClass_STRING)
187 {
188 continue;
189 }
190
191 OUString aValue;
192 rUDP.Value >>= aValue;
193
194 tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
195 rJsonWriter.put("name", rUDP.Name);
196 rJsonWriter.put("type", "string");
197 rJsonWriter.put("value", aValue);
198 }
199}
200
206void GetBookmarks(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
207 const std::map<OUString, OUString>& rArguments)
208{
209 OUString aNamePrefix;
210 {
211 auto it = rArguments.find("namePrefix");
212 if (it != rArguments.end())
213 {
214 aNamePrefix = it->second;
215 }
216 }
217
218 IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess();
219 tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("bookmarks");
220 for (auto it = rIDMA.getBookmarksBegin(); it != rIDMA.getBookmarksEnd(); ++it)
221 {
222 sw::mark::IMark* pMark = *it;
223 if (!pMark->GetName().startsWith(aNamePrefix))
224 {
225 continue;
226 }
227
228 tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
229 rJsonWriter.put("name", pMark->GetName());
230 }
231}
232
238void GetBookmark(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
239 const std::map<OUString, OUString>& rArguments)
240{
241 OUString aNamePrefix;
242 {
243 auto it = rArguments.find("namePrefix");
244 if (it != rArguments.end())
245 {
246 aNamePrefix = it->second;
247 }
248 }
249
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");
255 if (!pBookmark)
256 {
257 return;
258 }
259
260 if (!pBookmark->GetName().startsWith(aNamePrefix))
261 {
262 return;
263 }
264
265 rJsonWriter.put("name", pBookmark->GetName());
266}
267
274void GetFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
275 const std::map<OUString, OUString>& rArguments)
276{
277 OUString aTypeName;
278 {
279 auto it = rArguments.find("typeName");
280 if (it != rArguments.end())
281 {
282 aTypeName = it->second;
283 }
284 }
285 // See SwFieldTypeFromString().
286 if (aTypeName != "SetRef")
287 {
288 return;
289 }
290
291 OUString aNamePrefix;
292 {
293 auto it = rArguments.find("namePrefix");
294 if (it != rArguments.end())
295 {
296 aNamePrefix = it->second;
297 }
298 }
299
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)
304 {
305 aRefMarks.push_back(pDoc->GetRefMark(i));
306 }
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;
315 });
316
317 for (const auto& pRefMark : aRefMarks)
318 {
319 if (!pRefMark->GetRefName().startsWith(aNamePrefix))
320 {
321 continue;
322 }
323
324 tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
325 rJsonWriter.put("name", pRefMark->GetRefName());
326 }
327}
328
335void GetField(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
336 const std::map<OUString, OUString>& rArguments)
337{
338 OUString aTypeName;
339 {
340 auto it = rArguments.find("typeName");
341 if (it != rArguments.end())
342 {
343 aTypeName = it->second;
344 }
345 }
346 // See SwFieldTypeFromString().
347 if (aTypeName != "SetRef")
348 {
349 return;
350 }
351
352 OUString aNamePrefix;
353 {
354 auto it = rArguments.find("namePrefix");
355 if (it != rArguments.end())
356 {
357 aNamePrefix = it->second;
358 }
359 }
360
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");
367 if (aAttrs.empty())
368 {
369 return;
370 }
371
372 const SwFormatRefMark& rRefmark = aAttrs[0]->GetRefMark();
373 if (!rRefmark.GetRefName().startsWith(aNamePrefix))
374 {
375 return;
376 }
377
378 rJsonWriter.put("name", rRefmark.GetRefName());
379}
380
386void GetSections(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell,
387 const std::map<OUString, OUString>& rArguments)
388{
389 OUString aNamePrefix;
390 {
391 auto it = rArguments.find("namePrefix");
392 if (it != rArguments.end())
393 {
394 aNamePrefix = it->second;
395 }
396 }
397
398 SwDoc* pDoc = pDocShell->GetDoc();
399 tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("sections");
400 for (const auto& pSection : pDoc->GetSections())
401 {
402 if (!pSection->GetName().startsWith(aNamePrefix))
403 {
404 continue;
405 }
406
407 tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
408 rJsonWriter.put("name", pSection->GetName());
409 }
410}
411}
412
413bool SwXTextDocument::supportsCommand(std::u16string_view rCommand)
414{
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" };
419
420 return std::find(vForward.begin(), vForward.end(), rCommand) != vForward.end();
421}
422
423void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand)
424{
425 std::map<OUString, OUString> aMap;
426
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");
435
436 INetURLObject aParser(OUString::fromUtf8(rCommand));
437 OUString aArguments = aParser.GetParam();
438 sal_Int32 nParamIndex = 0;
439 do
440 {
441 std::u16string_view aParam = o3tl::getToken(aArguments, 0, '&', nParamIndex);
442 sal_Int32 nIndex = 0;
443 OUString aKey;
444 OUString aValue;
445 do
446 {
447 std::u16string_view aToken = o3tl::getToken(aParam, 0, '=', nIndex);
448 if (aKey.isEmpty())
449 aKey = aToken;
450 else
451 aValue = aToken;
452 } while (nIndex >= 0);
453 OUString aDecodedValue
455 aMap[aKey] = aDecodedValue;
456 } while (nParamIndex >= 0);
457
458 if (o3tl::starts_with(rCommand, aTextFormFields))
459 {
460 GetTextFormFields(rJsonWriter, m_pDocShell, aMap);
461 }
462 if (o3tl::starts_with(rCommand, aTextFormField))
463 {
464 GetTextFormField(rJsonWriter, m_pDocShell, aMap);
465 }
466 else if (o3tl::starts_with(rCommand, aSetDocumentProperties))
467 {
468 GetDocumentProperties(rJsonWriter, m_pDocShell, aMap);
469 }
470 else if (o3tl::starts_with(rCommand, aBookmarks))
471 {
472 GetBookmarks(rJsonWriter, m_pDocShell, aMap);
473 }
474 else if (o3tl::starts_with(rCommand, aFields))
475 {
476 GetFields(rJsonWriter, m_pDocShell, aMap);
477 }
478 else if (o3tl::starts_with(rCommand, aSections))
479 {
480 GetSections(rJsonWriter, m_pDocShell, aMap);
481 }
482 else if (o3tl::starts_with(rCommand, aBookmark))
483 {
484 GetBookmark(rJsonWriter, m_pDocShell, aMap);
485 }
486 else if (o3tl::starts_with(rCommand, aField))
487 {
488 GetField(rJsonWriter, m_pDocShell, aMap);
489 }
490}
491
492/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
Provides access to the marks of a document.
virtual const_iterator_t getFieldmarksBegin() const =0
returns a STL-like random access iterator to the begin of the sequence of fieldmarks.
virtual const_iterator_t getBookmarksBegin() const =0
returns a STL-like random access iterator to the begin of the sequence the IBookmarks.
virtual const_iterator_t getFieldmarksEnd() const =0
returns a STL-like random access iterator to the end of the sequence of fieldmarks.
virtual sw::mark::IFieldmark * getInnerFieldmarkFor(const SwPosition &pos) const =0
virtual const_iterator_t getBookmarksEnd() const =0
returns a STL-like random access iterator to the end of the sequence of IBookmarks.
virtual sw::mark::IMark * getOneInnermostBookmarkFor(const SwPosition &rPos) const =0
Get the innermost bookmark that contains rPos.
static OUString decode(std::u16string_view rText, DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
OUString GetParam(rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
css::uno::Reference< css::frame::XModel3 > GetModel() const
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:194
SwWrtShell * GetWrtShell()
Access to the SwWrtShell belonging to SwView.
Definition: docsh.hxx:225
SwDoc * GetDoc()
returns Doc. But be careful!
Definition: docsh.hxx:204
Definition: doc.hxx:197
SwSectionFormats & GetSections()
Definition: doc.hxx:1356
sal_uInt16 GetRefMarks(std::vector< OUString > *=nullptr) const
Definition: doc.cxx:1104
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1890
const SwFormatRefMark * GetRefMark(std::u16string_view rName) const
Definition: doc.cxx:1060
OUString & GetRefName()
Definition: fmtrfmrk.hxx:63
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
const SwPosition * GetPoint() const
Definition: pam.hxx:253
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
std::vector< SwTextAttr * > GetTextAttrsAt(sal_Int32 const nIndex, sal_uInt16 const nWhich) const
get the innermost text attributes covering position nIndex.
Definition: ndtxt.cxx:1795
Used by the UI to modify the document model.
Definition: wrtsh.hxx:97
void getCommandValues(tools::JsonWriter &rJsonWriter, std::string_view rCommand) override
Definition: loktxdoc.cxx:423
SwDocShell * m_pDocShell
Definition: unotxdoc.hxx:148
bool supportsCommand(std::u16string_view rCommand) override
Definition: loktxdoc.cxx:413
virtual const OUString & GetName() const =0
void put(std::u16string_view pPropName, const OUString &rPropValue)
ScopedJsonWriterStruct startStruct()
ScopedJsonWriterNode startNode(std::string_view)
ScopedJsonWriterArray startArray(std::string_view)
float u
constexpr TypedWhichId< SwFormatRefMark > RES_TXTATR_REFMARK(RES_TXTATR_WITHEND_BEGIN)
Sequence< PropertyValue > aArguments
sal_Int32 nIndex
int i
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
HashMap_OWString_Interface aMap
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
OUString aCommand