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  eInputLanguage(LANGUAGE_DONTKNOW)
42 {
43  bIsOverwriteCursor = false;
44  bInsText = true;
45 }
46 
48 {
49  SwDoc *const pDoc = GetDoc();
50  if (pDoc->IsInDtor()) { return; /* #i58606# */ }
51 
53  if( pTNd )
54  {
55  SwIndex& rIdx = GetPoint()->nContent;
56  sal_Int32 nSttCnt = rIdx.GetIndex();
57  sal_Int32 nEndCnt = GetMark()->nContent.GetIndex();
58  if( nEndCnt != nSttCnt )
59  {
60  // Prevent IME edited text being grouped with non-IME edited text.
61  bool bKeepGroupUndo = pDoc->GetIDocumentUndoRedo().DoesGroupUndo();
62  pDoc->GetIDocumentUndoRedo().DoGroupUndo(false);
63  if( nEndCnt < nSttCnt )
64  {
65  std::swap(nSttCnt, nEndCnt);
66  }
67 
68  // In order to get Undo/Redlining etc. working correctly,
69  // we need to go through the Doc interface
70  rIdx = nSttCnt;
71  const OUString sText( pTNd->GetText().copy(nSttCnt, nEndCnt - nSttCnt));
72  if( bIsOverwriteCursor && !sOverwriteText.isEmpty() )
73  {
74  const sal_Int32 nLen = sText.getLength();
75  const sal_Int32 nOWLen = sOverwriteText.getLength();
76  if( nLen > nOWLen )
77  {
78  rIdx += nOWLen;
79  pTNd->EraseText( rIdx, nLen - nOWLen );
80  rIdx = nSttCnt;
81  pTNd->ReplaceText( rIdx, nOWLen, sOverwriteText );
82  if( bInsText )
83  {
84  rIdx = nSttCnt;
86  pDoc->getIDocumentContentOperations().Overwrite( *this, sText.copy( 0, nOWLen ) );
87  pDoc->getIDocumentContentOperations().InsertString( *this, sText.copy( nOWLen ) );
89  }
90  }
91  else
92  {
93  pTNd->ReplaceText( rIdx, nLen, sOverwriteText.copy( 0, nLen ));
94  if( bInsText )
95  {
96  rIdx = nSttCnt;
97  pDoc->getIDocumentContentOperations().Overwrite( *this, sText );
98  }
99  }
100  }
101  else
102  {
103  pTNd->EraseText( rIdx, nEndCnt - nSttCnt );
104 
105  if( bInsText )
106  {
107  pDoc->getIDocumentContentOperations().InsertString( *this, sText );
108  }
109  }
110  pDoc->GetIDocumentUndoRedo().DoGroupUndo(bKeepGroupUndo);
112  {
113  sal_uInt16 nWhich = RES_CHRATR_LANGUAGE;
115  switch(nScriptType)
116  {
117  case i18n::ScriptType::ASIAN:
118  nWhich = RES_CHRATR_CJK_LANGUAGE; break;
119  case i18n::ScriptType::COMPLEX:
120  nWhich = RES_CHRATR_CTL_LANGUAGE; break;
121  }
122  // #i41974# Only set language attribute for CJK/CTL scripts.
123  if (RES_CHRATR_LANGUAGE != nWhich && pTNd->GetLang( nSttCnt, nEndCnt-nSttCnt, nScriptType) != eInputLanguage)
124  {
125  SvxLanguageItem aLangItem( eInputLanguage, nWhich );
126  rIdx = nSttCnt;
127  GetMark()->nContent = nEndCnt;
128  pDoc->getIDocumentContentOperations().InsertPoolItem(*this, aLangItem );
129  }
130 
131  }
132  }
133  }
134 }
135 
137 {
139  if( pTNd )
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( bIsOverwriteCursor && !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  sOverwriteText.copy( nNewLen, nReplace ));
162  aIdx = nSttCnt;
163  nReplace = nNewLen;
164  }
165  else
166  {
167  const sal_Int32 nOWLen = 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  aAttrs.clear();
202  if( rData.GetTextAttr() )
203  {
204  const ExtTextInputAttr *pAttrs = rData.GetTextAttr();
205  aAttrs.insert( aAttrs.begin(), pAttrs, pAttrs + rData.GetText().getLength() );
206  }
207  }
208 }
209 
211 {
212  bIsOverwriteCursor = bFlag;
213  if (!bIsOverwriteCursor)
214  return;
215 
216  const SwTextNode *const pTNd = GetPoint()->nNode.GetNode().GetTextNode();
217  if (pTNd)
218  {
219  const sal_Int32 nSttCnt = GetPoint()->nContent.GetIndex();
220  const sal_Int32 nEndCnt = GetMark()->nContent.GetIndex();
221  sOverwriteText = pTNd->GetText().copy( std::min(nSttCnt, nEndCnt) );
222  if( !sOverwriteText.isEmpty() )
223  {
224  const sal_Int32 nInPos = sOverwriteText.indexOf( CH_TXTATR_INWORD );
225  const sal_Int32 nBrkPos = sOverwriteText.indexOf( CH_TXTATR_BREAKWORD );
226 
227  // Find the first attr found, if any.
228  sal_Int32 nPos = std::min(nInPos, nBrkPos);
229  if (nPos<0)
230  {
231  nPos = std::max(nInPos, nBrkPos);
232  }
233  if (nPos>=0)
234  {
235  sOverwriteText = sOverwriteText.copy( 0, nPos );
236  }
237  }
238  }
239 }
240 
241 // The Doc interfaces
242 
244 {
245  SwExtTextInput* pNew = new SwExtTextInput( rPam, mpExtInputRing );
246  if( !mpExtInputRing )
247  mpExtInputRing = pNew;
248  pNew->SetMark();
249  return pNew;
250 }
251 
253 {
254  if( pDel == mpExtInputRing )
255  {
256  if( pDel->GetNext() != mpExtInputRing )
257  mpExtInputRing = pDel->GetNext();
258  else
259  mpExtInputRing = nullptr;
260  }
261  delete pDel;
262 }
263 
265  sal_Int32 nContentPos ) const
266 {
267  SwExtTextInput* pRet = nullptr;
268  if( mpExtInputRing )
269  {
270  sal_uLong nNdIdx = rNd.GetIndex();
272  do {
273  sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
274  nMk = pTmp->GetMark()->nNode.GetIndex();
275  sal_Int32 nPtCnt = pTmp->GetPoint()->nContent.GetIndex();
276  sal_Int32 nMkCnt = pTmp->GetMark()->nContent.GetIndex();
277 
278  if( nPt < nMk || ( nPt == nMk && nPtCnt < nMkCnt ))
279  {
280  sal_uLong nTmp = nMk; nMk = nPt; nPt = nTmp;
281  sal_Int32 nTmp2 = nMkCnt; nMkCnt = nPtCnt; nPtCnt = nTmp2;
282  }
283 
284  if( nMk <= nNdIdx && nNdIdx <= nPt &&
285  ( nContentPos<0 ||
286  ( nMkCnt <= nContentPos && nContentPos <= nPtCnt )))
287  {
288  pRet = pTmp;
289  break;
290  }
291  pTmp = pTmp->GetNext();
292  } while ( pTmp!=mpExtInputRing );
293  }
294  return pRet;
295 }
296 
298 {
299  OSL_ENSURE( !mpExtInputRing || !mpExtInputRing->IsMultiSelection(),
300  "more than one InputEngine available" );
301  return mpExtInputRing;
302 }
303 
304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString sOverwriteText
Definition: extinput.hxx:30
sal_uLong GetIndex() const
Definition: node.hxx:282
#define RES_CHRATR_CJK_LANGUAGE
Definition: hintids.hxx:93
bool IsMultiSelection() const
Definition: pam.hxx:272
#define RES_CHRATR_LANGUAGE
Definition: hintids.hxx:79
const OUString & GetText() const
Definition: ndtxt.hxx:210
SwNodeIndex nNode
Definition: pam.hxx:37
virtual ~SwExtTextInput() override
Definition: extinput.cxx:47
sal_uIntPtr sal_uLong
LanguageType eInputLanguage
Definition: extinput.hxx:33
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:185
SwNode & GetNode() const
Definition: ndindex.hxx:119
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:143
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:314
SwExtTextInput * GetExtTextInput() const
Definition: extinput.cxx:297
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:43
#define CH_TXTATR_INWORD
Definition: hintids.hxx:44
SwIndex nContent
Definition: pam.hxx:38
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
void SetOverwriteCursor(bool bFlag)
Definition: extinput.cxx:210
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.
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:37
#define LANGUAGE_DONTKNOW
SwExtTextInput * CreateExtTextInput(const SwPaM &rPam)
Definition: extinput.cxx:243
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:2657
OUString InsertText(const OUString &rStr, const SwIndex &rIdx, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
insert text content
Definition: ndtxt.cxx:2274
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
#define RES_CHRATR_CTL_LANGUAGE
Definition: hintids.hxx:98
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:3673
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:252
sal_Int32 GetIndex() const
Definition: index.hxx:95
LanguageType GetLang(const sal_Int32 nBegin, const sal_Int32 nLen=0, sal_uInt16 nScript=0) const
Definition: thints.cxx:3399
bool bIsOverwriteCursor
Definition: extinput.hxx:32
bool IsInDtor() const
Definition: doc.hxx:397
ExtTextInputAttr
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:469
SwExtTextInput(const SwPaM &rPam, Ring *pRing)
Definition: extinput.cxx:39
void SetInputData(const CommandExtTextInputData &rData)
Definition: extinput.cxx:136
std::vector< ExtTextInputAttr > aAttrs
Definition: extinput.hxx:29
SwExtTextInput * mpExtInputRing
Definition: doc.hxx:271
sal_uInt16 nPos
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
Base class of the Writer document model elements.
Definition: node.hxx:79
const ExtTextInputAttr * GetTextAttr() const