LibreOffice Module sw (master)  1
extinput.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 <algorithm>
21 
22 #include <com/sun/star/i18n/ScriptType.hpp>
23 
24 #include <editeng/langitem.hxx>
25 #include <osl/diagnose.h>
26 #include <svl/languageoptions.hxx>
27 #include <vcl/commandevent.hxx>
28 
29 #include <hintids.hxx>
30 #include <extinput.hxx>
31 #include <doc.hxx>
32 #include <IDocumentUndoRedo.hxx>
33 #include <index.hxx>
34 #include <ndtxt.hxx>
35 #include <swundo.hxx>
36 
37 using namespace ::com::sun::star;
38 
39 SwExtTextInput::SwExtTextInput( const SwPaM& rPam, Ring* pRing )
40  : SwPaM( *rPam.GetPoint(), static_cast<SwPaM*>(pRing) ),
41  m_eInputLanguage(LANGUAGE_DONTKNOW)
42 {
43  m_bIsOverwriteCursor = false;
44  m_bInsText = true;
45 }
46 
48 {
49  SwDoc *const pDoc = GetDoc();
50  if (pDoc->IsInDtor()) { return; /* #i58606# */ }
51 
53  if( !pTNd )
54  return;
55 
56  SwIndex& rIdx = GetPoint()->nContent;
57  sal_Int32 nSttCnt = rIdx.GetIndex();
58  sal_Int32 nEndCnt = GetMark()->nContent.GetIndex();
59  if( nEndCnt == nSttCnt )
60  return;
61 
62  // Prevent IME edited text being grouped with non-IME edited text.
63  bool bKeepGroupUndo = pDoc->GetIDocumentUndoRedo().DoesGroupUndo();
64  pDoc->GetIDocumentUndoRedo().DoGroupUndo(false);
65  if( nEndCnt < nSttCnt )
66  {
67  std::swap(nSttCnt, nEndCnt);
68  }
69 
70  // In order to get Undo/Redlining etc. working correctly,
71  // we need to go through the Doc interface
72  rIdx = nSttCnt;
73  const OUString sText( pTNd->GetText().copy(nSttCnt, nEndCnt - nSttCnt));
74  if( m_bIsOverwriteCursor && !m_sOverwriteText.isEmpty() )
75  {
76  const sal_Int32 nLen = sText.getLength();
77  const sal_Int32 nOWLen = m_sOverwriteText.getLength();
78  if( nLen > nOWLen )
79  {
80  rIdx += nOWLen;
81  pTNd->EraseText( rIdx, nLen - nOWLen );
82  rIdx = nSttCnt;
83  pTNd->ReplaceText( rIdx, nOWLen, m_sOverwriteText );
84  if( m_bInsText )
85  {
86  rIdx = nSttCnt;
88  pDoc->getIDocumentContentOperations().Overwrite( *this, sText.copy( 0, nOWLen ) );
89  pDoc->getIDocumentContentOperations().InsertString( *this, sText.copy( nOWLen ) );
91  }
92  }
93  else
94  {
95  pTNd->ReplaceText( rIdx, nLen, m_sOverwriteText.copy( 0, nLen ));
96  if( m_bInsText )
97  {
98  rIdx = nSttCnt;
99  pDoc->getIDocumentContentOperations().Overwrite( *this, sText );
100  }
101  }
102  }
103  else
104  {
105  pTNd->EraseText( rIdx, nEndCnt - nSttCnt );
106 
107  if( m_bInsText )
108  {
109  pDoc->getIDocumentContentOperations().InsertString( *this, sText );
110  }
111  }
112  pDoc->GetIDocumentUndoRedo().DoGroupUndo(bKeepGroupUndo);
114  return;
115 
116  sal_uInt16 nWhich = RES_CHRATR_LANGUAGE;
118  switch(nScriptType)
119  {
120  case i18n::ScriptType::ASIAN:
121  nWhich = RES_CHRATR_CJK_LANGUAGE; break;
122  case i18n::ScriptType::COMPLEX:
123  nWhich = RES_CHRATR_CTL_LANGUAGE; break;
124  }
125  // #i41974# Only set language attribute for CJK/CTL scripts.
126  if (RES_CHRATR_LANGUAGE != nWhich && pTNd->GetLang( nSttCnt, nEndCnt-nSttCnt, nScriptType) != m_eInputLanguage)
127  {
128  SvxLanguageItem aLangItem( m_eInputLanguage, nWhich );
129  rIdx = nSttCnt;
130  GetMark()->nContent = nEndCnt;
131  pDoc->getIDocumentContentOperations().InsertPoolItem(*this, aLangItem );
132  }
133 }
134 
136 {
138  if( !pTNd )
139  return;
140 
141  sal_Int32 nSttCnt = GetPoint()->nContent.GetIndex();
142  sal_Int32 nEndCnt = GetMark()->nContent.GetIndex();
143  if( nEndCnt < nSttCnt )
144  {
145  std::swap(nSttCnt, nEndCnt);
146  }
147 
148  SwIndex aIdx( pTNd, nSttCnt );
149  const OUString& rNewStr = rData.GetText();
150 
151  if( m_bIsOverwriteCursor && !m_sOverwriteText.isEmpty() )
152  {
153  sal_Int32 nReplace = nEndCnt - nSttCnt;
154  const sal_Int32 nNewLen = rNewStr.getLength();
155  if( nNewLen < nReplace )
156  {
157  // We have to insert some characters from the saved original text
158  nReplace -= nNewLen;
159  aIdx += nNewLen;
160  pTNd->ReplaceText( aIdx, nReplace,
161  m_sOverwriteText.copy( nNewLen, nReplace ));
162  aIdx = nSttCnt;
163  nReplace = nNewLen;
164  }
165  else
166  {
167  const sal_Int32 nOWLen = m_sOverwriteText.getLength();
168  if( nOWLen < nReplace )
169  {
170  aIdx += nOWLen;
171  pTNd->EraseText( aIdx, nReplace-nOWLen );
172  aIdx = nSttCnt;
173  nReplace = nOWLen;
174  }
175  else
176  {
177  nReplace = std::min(nOWLen, nNewLen);
178  }
179  }
180 
181  pTNd->ReplaceText( aIdx, nReplace, rNewStr );
182  if( !HasMark() )
183  SetMark();
184  GetMark()->nContent = aIdx;
185  }
186  else
187  {
188  if( nSttCnt < nEndCnt )
189  {
190  pTNd->EraseText( aIdx, nEndCnt - nSttCnt );
191  }
192 
193  pTNd->InsertText( rNewStr, aIdx,
195  if( !HasMark() )
196  SetMark();
197  }
198 
199  GetPoint()->nContent = nSttCnt;
200 
201  m_aAttrs.clear();
202  if( rData.GetTextAttr() )
203  {
204  const ExtTextInputAttr *pAttrs = rData.GetTextAttr();
205  m_aAttrs.insert( m_aAttrs.begin(), pAttrs, pAttrs + rData.GetText().getLength() );
206  }
207 }
208 
210 {
211  m_bIsOverwriteCursor = bFlag;
213  return;
214 
215  const SwTextNode *const pTNd = GetPoint()->nNode.GetNode().GetTextNode();
216  if (!pTNd)
217  return;
218 
219  const sal_Int32 nSttCnt = GetPoint()->nContent.GetIndex();
220  const sal_Int32 nEndCnt = GetMark()->nContent.GetIndex();
221  m_sOverwriteText = pTNd->GetText().copy( std::min(nSttCnt, nEndCnt) );
222  if( m_sOverwriteText.isEmpty() )
223  return;
224 
225  const sal_Int32 nInPos = m_sOverwriteText.indexOf( CH_TXTATR_INWORD );
226  const sal_Int32 nBrkPos = m_sOverwriteText.indexOf( CH_TXTATR_BREAKWORD );
227 
228  // Find the first attr found, if any.
229  sal_Int32 nPos = std::min(nInPos, nBrkPos);
230  if (nPos<0)
231  {
232  nPos = std::max(nInPos, nBrkPos);
233  }
234  if (nPos>=0)
235  {
236  m_sOverwriteText = m_sOverwriteText.copy( 0, nPos );
237  }
238 }
239 
240 // The Doc interfaces
241 
243 {
244  SwExtTextInput* pNew = new SwExtTextInput( rPam, mpExtInputRing );
245  if( !mpExtInputRing )
246  mpExtInputRing = pNew;
247  pNew->SetMark();
248  return pNew;
249 }
250 
252 {
253  if( pDel == mpExtInputRing )
254  {
255  if( pDel->GetNext() != mpExtInputRing )
256  mpExtInputRing = pDel->GetNext();
257  else
258  mpExtInputRing = nullptr;
259  }
260  delete pDel;
261 }
262 
264  sal_Int32 nContentPos ) const
265 {
266  SwExtTextInput* pRet = nullptr;
267  if( mpExtInputRing )
268  {
269  sal_uLong nNdIdx = rNd.GetIndex();
271  do {
272  sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
273  nMk = pTmp->GetMark()->nNode.GetIndex();
274  sal_Int32 nPtCnt = pTmp->GetPoint()->nContent.GetIndex();
275  sal_Int32 nMkCnt = pTmp->GetMark()->nContent.GetIndex();
276 
277  if( nPt < nMk || ( nPt == nMk && nPtCnt < nMkCnt ))
278  {
279  sal_uLong nTmp = nMk; nMk = nPt; nPt = nTmp;
280  sal_Int32 nTmp2 = nMkCnt; nMkCnt = nPtCnt; nPtCnt = nTmp2;
281  }
282 
283  if( nMk <= nNdIdx && nNdIdx <= nPt &&
284  ( nContentPos<0 ||
285  ( nMkCnt <= nContentPos && nContentPos <= nPtCnt )))
286  {
287  pRet = pTmp;
288  break;
289  }
290  pTmp = pTmp->GetNext();
291  } while ( pTmp!=mpExtInputRing );
292  }
293  return pRet;
294 }
295 
297 {
298  OSL_ENSURE( !mpExtInputRing || !mpExtInputRing->IsMultiSelection(),
299  "more than one InputEngine available" );
300  return mpExtInputRing;
301 }
302 
303 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uLong GetIndex() const
Definition: node.hxx:282
bool IsMultiSelection() const
Definition: pam.hxx:272
const OUString & GetText() const
Definition: ndtxt.hxx:211
SwNodeIndex nNode
Definition: pam.hxx:37
virtual ~SwExtTextInput() override
Definition: extinput.cxx:47
sal_uIntPtr sal_uLong
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_LANGUAGE(10)
const SwPosition * GetMark() const
Definition: pam.hxx:209
virtual SwUndoId EndUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Closes undo block.
Definition: doc.hxx:184
SwNode & GetNode() const
Definition: ndindex.hxx:119
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:143
OUString m_sOverwriteText
Definition: extinput.hxx:30
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:314
SwExtTextInput * GetExtTextInput() const
Definition: extinput.cxx:296
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:170
#define CH_TXTATR_INWORD
Definition: hintids.hxx:171
SwIndex nContent
Definition: pam.hxx:38
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_CTL_LANGUAGE(29)
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
void SetOverwriteCursor(bool bFlag)
Definition: extinput.cxx:209
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
const OUString & GetText() const
virtual bool InsertString(const SwPaM &rRg, const OUString &, const SwInsertFlags nInsertMode=SwInsertFlags::EMPTYEXPAND)=0
Insert string into existing text node at position rRg.Point().
virtual bool Overwrite(const SwPaM &rRg, const OUString &rStr)=0
Overwrite string in an existing text node.
bool m_bIsOverwriteCursor
Definition: extinput.hxx:32
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
const SwPosition * GetPoint() const
Definition: pam.hxx:207
SwExtTextInput * GetNext()
Definition: extinput.hxx:45
virtual bool DoesGroupUndo() const =0
Is Group Undo enabled?
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
SwDoc * GetDoc() const
Definition: pam.hxx:243
static sal_Int16 GetI18NScriptTypeOfLanguage(LanguageType nLang)
Marks a character position inside a document model node.
Definition: index.hxx:33
#define LANGUAGE_DONTKNOW
SwExtTextInput * CreateExtTextInput(const SwPaM &rPam)
Definition: extinput.cxx:242
virtual void DoGroupUndo(bool const bDoUndo)=0
Enable/Disable Group Undo.
void EraseText(const SwIndex &rIdx, const sal_Int32 nCount=SAL_MAX_INT32, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
delete text content ATTENTION: must not be called with a range that overlaps the start of an attribut...
Definition: ndtxt.cxx:2661
OUString InsertText(const OUString &rStr, const SwIndex &rIdx, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
insert text content
Definition: ndtxt.cxx:2278
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
LanguageType m_eInputLanguage
Definition: extinput.hxx:33
void ReplaceText(const SwIndex &rStart, const sal_Int32 nDelLen, const OUString &rText)
replace nDelLen characters at rStart with rText in case the replacement does not fit, it is partially inserted up to the capacity of the node
Definition: ndtxt.cxx:3677
virtual bool InsertPoolItem(const SwPaM &rRg, const SfxPoolItem &, const SetAttrMode nFlags=SetAttrMode::DEFAULT, SwRootFrame const *pLayout=nullptr, bool bExpandCharToPara=false, SwTextAttr **ppNewTextAttr=nullptr)=0
Insert an attribute.
void DeleteExtTextInput(SwExtTextInput *pDel)
Definition: extinput.cxx:251
sal_Int32 GetIndex() const
Definition: index.hxx:91
LanguageType GetLang(const sal_Int32 nBegin, const sal_Int32 nLen=0, sal_uInt16 nScript=0) const
Definition: thints.cxx:3402
bool IsInDtor() const
Definition: doc.hxx:398
ExtTextInputAttr
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:475
std::vector< ExtTextInputAttr > m_aAttrs
Definition: extinput.hxx:29
SwExtTextInput(const SwPaM &rPam, Ring *pRing)
Definition: extinput.cxx:39
void SetInputData(const CommandExtTextInputData &rData)
Definition: extinput.cxx:135
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_CJK_LANGUAGE(24)
SwExtTextInput * mpExtInputRing
Definition: doc.hxx:270
sal_uInt16 nPos
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:844
Base class of the Writer document model elements.
Definition: node.hxx:79
const ExtTextInputAttr * GetTextAttr() const