Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / uno / loktxdoc.cxx
blob4843af4cf443619a785b47bf76273f83590d8e96
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <unotxdoc.hxx>
22 #include <map>
23 #include <utility>
24 #include <vector>
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>
35 #include <doc.hxx>
36 #include <docsh.hxx>
37 #include <fmtrfmrk.hxx>
38 #include <wrtsh.hxx>
39 #include <txtrfmrk.hxx>
40 #include <ndtxt.hxx>
42 using namespace ::com::sun::star;
44 namespace
46 /// Implements getCommandValues(".uno:TextFormFields").
47 ///
48 /// Parameters:
49 ///
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)
55 OUString aType;
56 OUString aCommandPrefix;
58 auto it = rArguments.find("type");
59 if (it != rArguments.end())
61 aType = it->second;
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);
77 assert(pFieldmark);
78 if (pFieldmark->GetFieldname() != aType)
80 continue;
83 auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
84 if (itParam == pFieldmark->GetParameters()->end())
86 continue;
89 OUString aCommand;
90 itParam->second >>= aCommand;
91 if (!aCommand.startsWith(aCommandPrefix))
93 continue;
96 tools::ScopedJsonWriterStruct aField = rJsonWriter.startStruct();
97 rJsonWriter.put("type", aType);
98 rJsonWriter.put("command", aCommand);
102 /// Implements getCommandValues(".uno:TextFormField").
104 /// Parameters:
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)
111 OUString aType;
112 OUString aCommandPrefix;
113 auto it = rArguments.find("type");
114 if (it != rArguments.end())
116 aType = it->second;
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");
130 if (!pFieldmark)
132 return;
135 if (pFieldmark->GetFieldname() != aType)
137 return;
140 auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
141 if (itParam == pFieldmark->GetParameters()->end())
143 return;
146 OUString aCommand;
147 itParam->second >>= aCommand;
148 if (!aCommand.startsWith(aCommandPrefix))
150 return;
153 rJsonWriter.put("type", aType);
154 rJsonWriter.put("command", aCommand);
157 /// Implements getCommandValues(".uno:SetDocumentProperties").
159 /// Parameters:
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(),
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)
181 if (!rUDP.Name.startsWith(aNamePrefix))
183 continue;
186 if (rUDP.Value.getValueTypeClass() != uno::TypeClass_STRING)
188 continue;
191 OUString aValue;
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").
203 /// Parameters:
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))
225 continue;
228 tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
229 rJsonWriter.put("name", pMark->GetName());
233 /// Implements getCommandValues(".uno:Bookmark").
235 /// Parameters:
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");
255 if (!pBookmark)
257 return;
260 if (!pBookmark->GetName().startsWith(aNamePrefix))
262 return;
265 rJsonWriter.put("name", pBookmark->GetName());
268 /// Implements getCommandValues(".uno:Fields").
270 /// Parameters:
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)
277 OUString aTypeName;
279 auto it = rArguments.find("typeName");
280 if (it != rArguments.end())
282 aTypeName = it->second;
285 // See SwFieldTypeFromString().
286 if (aTypeName != "SetRef")
288 return;
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))
321 continue;
324 tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct();
325 rJsonWriter.put("name", pRefMark->GetRefName());
329 /// Implements getCommandValues(".uno:Field").
331 /// Parameters:
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)
338 OUString aTypeName;
340 auto it = rArguments.find("typeName");
341 if (it != rArguments.end())
343 aTypeName = it->second;
346 // See SwFieldTypeFromString().
347 if (aTypeName != "SetRef")
349 return;
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");
367 if (aAttrs.empty())
369 return;
372 const SwFormatRefMark& rRefmark = aAttrs[0]->GetRefMark();
373 if (!rRefmark.GetRefName().startsWith(aNamePrefix))
375 return;
378 rJsonWriter.put("name", rRefmark.GetRefName());
381 /// Implements getCommandValues(".uno:Sections").
383 /// Parameters:
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))
404 continue;
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;
443 OUString aKey;
444 OUString aValue;
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
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: */