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>
26 
27 #include <vcl/keycodes.hxx>
28 #include <vcl/commandevent.hxx>
29 
30 #include <hintids.hxx>
31 #include <extinput.hxx>
32 #include <doc.hxx>
33 #include <IDocumentUndoRedo.hxx>
34 #include <index.hxx>
35 #include <ndtxt.hxx>
36 #include <txtfrm.hxx>
37 #include <swundo.hxx>
38 
39 using namespace ::com::sun::star;
40 
41 SwExtTextInput::SwExtTextInput( const SwPaM& rPam, Ring* pRing )
42  : SwPaM( *rPam.GetPoint(), static_cast<SwPaM*>(pRing) ),
43  eInputLanguage(LANGUAGE_DONTKNOW)
44 {
45  bIsOverwriteCursor = false;
46  bInsText = true;
47 }
48 
50 {
51  SwDoc *const pDoc = GetDoc();
52  if (pDoc->IsInDtor()) { return; /* #i58606# */ }
53 
55  if( pTNd )
56  {
57  SwIndex& rIdx = GetPoint()->nContent;
58  sal_Int32 nSttCnt = rIdx.GetIndex();
59  sal_Int32 nEndCnt = GetMark()->nContent.GetIndex();
60  if( nEndCnt != nSttCnt )
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( bIsOverwriteCursor && !sOverwriteText.isEmpty() )
75  {
76  const sal_Int32 nLen = sText.getLength();
77  const sal_Int32 nOWLen = sOverwriteText.getLength();
78  if( nLen > nOWLen )
79  {
80  rIdx += nOWLen;
81  pTNd->EraseText( rIdx, nLen - nOWLen );
82  rIdx = nSttCnt;
83  pTNd->ReplaceText( rIdx, nOWLen, sOverwriteText );
84  if( 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, sOverwriteText.copy( 0, nLen ));
96  if( 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( bInsText )
108  {
109  pDoc->getIDocumentContentOperations().InsertString( *this, sText );
110  }
111  }
112  pDoc->GetIDocumentUndoRedo().DoGroupUndo(bKeepGroupUndo);
114  {
115  sal_uInt16 nWhich = RES_CHRATR_LANGUAGE;
117  switch(nScriptType)
118  {
119  case i18n::ScriptType::ASIAN:
120  nWhich = RES_CHRATR_CJK_LANGUAGE; break;
121  case i18n::ScriptType::COMPLEX:
122  nWhich = RES_CHRATR_CTL_LANGUAGE; break;
123  }
124  // #i41974# Only set language attribute for CJK/CTL scripts.
125  if (RES_CHRATR_LANGUAGE != nWhich && pTNd->GetLang( nSttCnt, nEndCnt-nSttCnt, nScriptType) != eInputLanguage)
126  {
127  SvxLanguageItem aLangItem( eInputLanguage, nWhich );
128  rIdx = nSttCnt;
129  GetMark()->nContent = nEndCnt;
130  pDoc->getIDocumentContentOperations().InsertPoolItem(*this, aLangItem );
131  }
132 
133  }
134  }
135  }
136 }
137 
139 {
141  if( pTNd )
142  {
143  sal_Int32 nSttCnt = GetPoint()->nContent.GetIndex();
144  sal_Int32 nEndCnt = GetMark()->nContent.GetIndex();
145  if( nEndCnt < nSttCnt )
146  {
147  std::swap(nSttCnt, nEndCnt);
148  }
149 
150  SwIndex aIdx( pTNd, nSttCnt );
151  const OUString& rNewStr = rData.GetText();
152 
153  if( bIsOverwriteCursor && !sOverwriteText.isEmpty() )
154  {
155  sal_Int32 nReplace = nEndCnt - nSttCnt;
156  const sal_Int32 nNewLen = rNewStr.getLength();
157  if( nNewLen < nReplace )
158  {
159  // We have to insert some characters from the saved original text
160  nReplace -= nNewLen;
161  aIdx += nNewLen;
162  pTNd->ReplaceText( aIdx, nReplace,
163  sOverwriteText.copy( nNewLen, nReplace ));
164  aIdx = nSttCnt;
165  nReplace = nNewLen;
166  }
167  else
168  {
169  const sal_Int32 nOWLen = sOverwriteText.getLength();
170  if( nOWLen < nReplace )
171  {
172  aIdx += nOWLen;
173  pTNd->EraseText( aIdx, nReplace-nOWLen );
174  aIdx = nSttCnt;
175  nReplace = nOWLen;
176  }
177  else
178  {
179  nReplace = std::min(nOWLen, nNewLen);
180  }
181  }
182 
183  pTNd->ReplaceText( aIdx, nReplace, rNewStr );
184  if( !HasMark() )
185  SetMark();
186  GetMark()->nContent = aIdx;
187  }
188  else
189  {
190  if( nSttCnt < nEndCnt )
191  {
192  pTNd->EraseText( aIdx, nEndCnt - nSttCnt );
193  }
194 
195  pTNd->InsertText( rNewStr, aIdx,
197  if( !HasMark() )
198  SetMark();
199  }
200 
201  GetPoint()->nContent = nSttCnt;
202 
203  aAttrs.clear();
204  if( rData.GetTextAttr() )
205  {
206  const ExtTextInputAttr *pAttrs = rData.GetTextAttr();
207  aAttrs.insert( aAttrs.begin(), pAttrs, pAttrs + rData.GetText().getLength() );
208  }
209  }
210 }
211 
213 {
214  bIsOverwriteCursor = bFlag;
215  if (!bIsOverwriteCursor)
216  return;
217 
218  const SwTextNode *const pTNd = GetPoint()->nNode.GetNode().GetTextNode();
219  if (pTNd)
220  {
221  const sal_Int32 nSttCnt = GetPoint()->nContent.GetIndex();
222  const sal_Int32 nEndCnt = GetMark()->nContent.GetIndex();
223  sOverwriteText = pTNd->GetText().copy( std::min(nSttCnt, nEndCnt) );
224  if( !sOverwriteText.isEmpty() )
225  {
226  const sal_Int32 nInPos = sOverwriteText.indexOf( CH_TXTATR_INWORD );
227  const sal_Int32 nBrkPos = sOverwriteText.indexOf( CH_TXTATR_BREAKWORD );
228 
229  // Find the first attr found, if any.
230  sal_Int32 nPos = std::min(nInPos, nBrkPos);
231  if (nPos<0)
232  {
233  nPos = std::max(nInPos, nBrkPos);
234  }
235  if (nPos>=0)
236  {
237  sOverwriteText = sOverwriteText.copy( 0, nPos );
238  }
239  }
240  }
241 }
242 
243 // The Doc interfaces
244 
246 {
247  SwExtTextInput* pNew = new SwExtTextInput( rPam, mpExtInputRing );
248  if( !mpExtInputRing )
249  mpExtInputRing = pNew;
250  pNew->SetMark();
251  return pNew;
252 }
253 
255 {
256  if( pDel == mpExtInputRing )
257  {
258  if( pDel->GetNext() != mpExtInputRing )
259  mpExtInputRing = pDel->GetNext();
260  else
261  mpExtInputRing = nullptr;
262  }
263  delete pDel;
264 }
265 
267  sal_Int32 nContentPos ) const
268 {
269  SwExtTextInput* pRet = nullptr;
270  if( mpExtInputRing )
271  {
272  sal_uLong nNdIdx = rNd.GetIndex();
274  do {
275  sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
276  nMk = pTmp->GetMark()->nNode.GetIndex();
277  sal_Int32 nPtCnt = pTmp->GetPoint()->nContent.GetIndex();
278  sal_Int32 nMkCnt = pTmp->GetMark()->nContent.GetIndex();
279 
280  if( nPt < nMk || ( nPt == nMk && nPtCnt < nMkCnt ))
281  {
282  sal_uLong nTmp = nMk; nMk = nPt; nPt = nTmp;
283  sal_Int32 nTmp2 = nMkCnt; nMkCnt = nPtCnt; nPtCnt = nTmp2;
284  }
285 
286  if( nMk <= nNdIdx && nNdIdx <= nPt &&
287  ( nContentPos<0 ||
288  ( nMkCnt <= nContentPos && nContentPos <= nPtCnt )))
289  {
290  pRet = pTmp;
291  break;
292  }
293  pTmp = pTmp->GetNext();
294  } while ( pTmp!=mpExtInputRing );
295  }
296  return pRet;
297 }
298 
300 {
301  OSL_ENSURE( !mpExtInputRing || !mpExtInputRing->IsMultiSelection(),
302  "more than one InputEngine available" );
303  return mpExtInputRing;
304 }
305 
306 /* 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:92
bool IsMultiSelection() const
Definition: pam.hxx:272
#define RES_CHRATR_LANGUAGE
Definition: hintids.hxx:78
const OUString & GetText() const
Definition: ndtxt.hxx:211
SwNodeIndex nNode
Definition: pam.hxx:37
virtual ~SwExtTextInput() override
Definition: extinput.cxx:49
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:118
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:176
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:347
SwExtTextInput * GetExtTextInput() const
Definition: extinput.cxx:299
#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:151
void SetOverwriteCursor(bool bFlag)
Definition: extinput.cxx:212
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:245
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:2668
OUString InsertText(const OUString &rStr, const SwIndex &rIdx, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
insert text content
Definition: ndtxt.cxx:2283
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
#define RES_CHRATR_CTL_LANGUAGE
Definition: hintids.hxx:97
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:3683
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:254
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:3386
bool bIsOverwriteCursor
Definition: extinput.hxx:32
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:457
SwExtTextInput(const SwPaM &rPam, Ring *pRing)
Definition: extinput.cxx:41
sal_Int32 nPos
void SetInputData(const CommandExtTextInputData &rData)
Definition: extinput.cxx:138
std::vector< ExtTextInputAttr > aAttrs
Definition: extinput.hxx:29
SwExtTextInput * mpExtInputRing
Definition: doc.hxx:271
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:843
Base class of the Writer document model elements.
Definition: node.hxx:79
const ExtTextInputAttr * GetTextAttr() const