1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 #include <com/sun/star/i18n/ScriptType.hpp>
28
29 #include <editeng/langitem.hxx>
30 #include <editeng/scripttypeitem.hxx>
31
32 #include <vcl/keycodes.hxx>
33 #include <vcl/cmdevt.hxx>
34
35 #include <hintids.hxx>
36 #include <extinput.hxx>
37 #include <doc.hxx>
38 #include <IDocumentUndoRedo.hxx>
39 #include <index.hxx>
40 #include <ndtxt.hxx>
41 #include <txtfrm.hxx>
42 #include <swundo.hxx>
43
44
45 using namespace ::com::sun::star;
46
SwExtTextInput(const SwPaM & rPam,Ring * pRing)47 SwExtTextInput::SwExtTextInput( const SwPaM& rPam, Ring* pRing )
48 : SwPaM( *rPam.GetPoint(), (SwPaM*)pRing ),
49 eInputLanguage(LANGUAGE_DONTKNOW)
50 {
51 bIsOverwriteCursor = sal_False;
52 bInsText = sal_True;
53 }
54
~SwExtTextInput()55 SwExtTextInput::~SwExtTextInput()
56 {
57 SwDoc *const pDoc = GetDoc();
58 if (pDoc->IsInDtor()) { return; /* #i58606# */ }
59
60 SwTxtNode* pTNd = GetPoint()->nNode.GetNode().GetTxtNode();
61 if( pTNd )
62 {
63 SwIndex& rIdx = GetPoint()->nContent;
64 xub_StrLen nSttCnt = rIdx.GetIndex(),
65 nEndCnt = GetMark()->nContent.GetIndex();
66 if( nEndCnt != nSttCnt )
67 {
68 if( nEndCnt < nSttCnt )
69 {
70 xub_StrLen n = nEndCnt; nEndCnt = nSttCnt; nSttCnt = n;
71 }
72
73 // damit Undo / Redlining usw. richtig funktioniert,
74 // muss ueber die Doc-Schnittstellen gegangen werden !!!
75 if(eInputLanguage != LANGUAGE_DONTKNOW)
76 {
77 // --> FME 2005-02-11 #i41974# Only set language attribute
78 // for CJK/CTL scripts.
79 bool bLang = true;
80 // <--
81 sal_uInt16 nWhich = RES_CHRATR_LANGUAGE;
82 switch(GetI18NScriptTypeOfLanguage(eInputLanguage))
83 {
84 case i18n::ScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break;
85 case i18n::ScriptType::COMPLEX: nWhich = RES_CHRATR_CTL_LANGUAGE; break;
86 default: bLang = false;
87 }
88 if ( bLang )
89 {
90 SvxLanguageItem aLangItem( eInputLanguage, nWhich );
91 pDoc->InsertPoolItem(*this, aLangItem, 0 );
92 }
93 }
94 rIdx = nSttCnt;
95 String sTxt( pTNd->GetTxt().Copy( nSttCnt, nEndCnt - nSttCnt ));
96 if( bIsOverwriteCursor && sOverwriteText.Len() )
97 {
98 xub_StrLen nLen = sTxt.Len();
99 if( nLen > sOverwriteText.Len() )
100 {
101 rIdx += sOverwriteText.Len();
102 pTNd->EraseText( rIdx, nLen - sOverwriteText.Len() );
103 rIdx = nSttCnt;
104 pTNd->ReplaceText( rIdx, sOverwriteText.Len(),
105 sOverwriteText );
106 if( bInsText )
107 {
108 rIdx = nSttCnt;
109 pDoc->GetIDocumentUndoRedo().StartUndo(
110 UNDO_OVERWRITE, NULL );
111 pDoc->Overwrite( *this, sTxt.Copy( 0,
112 sOverwriteText.Len() ));
113 pDoc->InsertString( *this,
114 sTxt.Copy( sOverwriteText.Len() ) );
115 pDoc->GetIDocumentUndoRedo().EndUndo(
116 UNDO_OVERWRITE, NULL );
117 }
118 }
119 else
120 {
121 pTNd->ReplaceText( rIdx, nLen,
122 sOverwriteText.Copy( 0, nLen ));
123 if( bInsText )
124 {
125 rIdx = nSttCnt;
126 pDoc->Overwrite( *this, sTxt );
127 }
128 }
129 }
130 else
131 {
132 pTNd->EraseText( rIdx, nEndCnt - nSttCnt );
133
134 if( bInsText )
135 {
136 pDoc->InsertString( *this, sTxt );
137 }
138 }
139 }
140 }
141 }
142
SetInputData(const CommandExtTextInputData & rData)143 void SwExtTextInput::SetInputData( const CommandExtTextInputData& rData )
144 {
145 SwTxtNode* pTNd = GetPoint()->nNode.GetNode().GetTxtNode();
146 if( pTNd )
147 {
148 xub_StrLen nSttCnt = GetPoint()->nContent.GetIndex(),
149 nEndCnt = GetMark()->nContent.GetIndex();
150 if( nEndCnt < nSttCnt )
151 {
152 xub_StrLen n = nEndCnt; nEndCnt = nSttCnt; nSttCnt = n;
153 }
154
155 SwIndex aIdx( pTNd, nSttCnt );
156 const String& rNewStr = rData.GetText();
157
158 if( bIsOverwriteCursor && sOverwriteText.Len() )
159 {
160 xub_StrLen nReplace = nEndCnt - nSttCnt;
161 if( rNewStr.Len() < nReplace )
162 {
163 // then we must insert from the saved original text
164 // some characters
165 nReplace = nReplace - rNewStr.Len();
166 aIdx += rNewStr.Len();
167 pTNd->ReplaceText( aIdx, nReplace,
168 sOverwriteText.Copy( rNewStr.Len(), nReplace ));
169 aIdx = nSttCnt;
170 nReplace = rNewStr.Len();
171 }
172 else if( sOverwriteText.Len() < nReplace )
173 {
174 nReplace = nReplace - sOverwriteText.Len();
175 aIdx += sOverwriteText.Len();
176 pTNd->EraseText( aIdx, nReplace );
177 aIdx = nSttCnt;
178 nReplace = sOverwriteText.Len();
179 }
180 else if( (nReplace = sOverwriteText.Len()) > rNewStr.Len() )
181 nReplace = rNewStr.Len();
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,
196 IDocumentContentOperations::INS_EMPTYEXPAND );
197 if( !HasMark() )
198 SetMark();
199 }
200
201 GetPoint()->nContent = nSttCnt;
202
203 if( aAttrs.Count() )
204 aAttrs.Remove( 0, aAttrs.Count() );
205 if( rData.GetTextAttr() )
206 aAttrs.Insert( rData.GetTextAttr(), rData.GetText().Len(), 0 );
207 }
208 }
209
SetOverwriteCursor(sal_Bool bFlag)210 void SwExtTextInput::SetOverwriteCursor( sal_Bool bFlag )
211 {
212 bIsOverwriteCursor = bFlag;
213
214 SwTxtNode* pTNd;
215 if( bIsOverwriteCursor &&
216 0 != (pTNd = GetPoint()->nNode.GetNode().GetTxtNode()) )
217 {
218 xub_StrLen nSttCnt = GetPoint()->nContent.GetIndex(),
219 nEndCnt = GetMark()->nContent.GetIndex();
220 sOverwriteText = pTNd->GetTxt().Copy( nEndCnt < nSttCnt ? nEndCnt
221 : nSttCnt );
222 if( sOverwriteText.Len() )
223 {
224 xub_StrLen nInWrdAttrPos = sOverwriteText.Search( CH_TXTATR_INWORD ),
225 nWrdAttrPos = sOverwriteText.Search( CH_TXTATR_BREAKWORD );
226 if( nWrdAttrPos < nInWrdAttrPos )
227 nInWrdAttrPos = nWrdAttrPos;
228 if( STRING_NOTFOUND != nInWrdAttrPos )
229 sOverwriteText.Erase( nInWrdAttrPos );
230 }
231 }
232 }
233
234 // die Doc Schnittstellen:
235
CreateExtTextInput(const SwPaM & rPam)236 SwExtTextInput* SwDoc::CreateExtTextInput( const SwPaM& rPam )
237 {
238 SwExtTextInput* pNew = new SwExtTextInput( rPam, pExtInputRing );
239 if( !pExtInputRing )
240 pExtInputRing = pNew;
241 pNew->SetMark();
242 return pNew;
243 }
244
DeleteExtTextInput(SwExtTextInput * pDel)245 void SwDoc::DeleteExtTextInput( SwExtTextInput* pDel )
246 {
247 if( pDel == pExtInputRing )
248 {
249 if( pDel->GetNext() != pExtInputRing )
250 pExtInputRing = (SwPaM*)pDel->GetNext();
251 else
252 pExtInputRing = 0;
253 }
254 delete pDel;
255 }
256
GetExtTextInput(const SwNode & rNd,xub_StrLen nCntntPos) const257 SwExtTextInput* SwDoc::GetExtTextInput( const SwNode& rNd,
258 xub_StrLen nCntntPos ) const
259 {
260 SwExtTextInput* pRet = 0;
261 if( pExtInputRing )
262 {
263 sal_uLong nNdIdx = rNd.GetIndex();
264 SwExtTextInput* pTmp = (SwExtTextInput*)pExtInputRing;
265 do {
266 sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
267 nMk = pTmp->GetMark()->nNode.GetIndex();
268 xub_StrLen nPtCnt = pTmp->GetPoint()->nContent.GetIndex(),
269 nMkCnt = pTmp->GetMark()->nContent.GetIndex();
270
271 if( nPt < nMk || ( nPt == nMk && nPtCnt < nMkCnt ))
272 {
273 sal_uLong nTmp = nMk; nMk = nPt; nPt = nTmp;
274 nTmp = nMkCnt; nMkCnt = nPtCnt; nPtCnt = (xub_StrLen)nTmp;
275 }
276
277 if( nMk <= nNdIdx && nNdIdx <= nPt &&
278 ( STRING_NOTFOUND == nCntntPos ||
279 ( nMkCnt <= nCntntPos && nCntntPos <= nPtCnt )))
280 {
281 pRet = pTmp;
282 break;
283 }
284 } while( pExtInputRing != (pTmp = (SwExtTextInput*)pExtInputRing ) );
285 }
286 return pRet;
287 }
288
GetExtTextInput() const289 SwExtTextInput* SwDoc::GetExtTextInput() const
290 {
291 ASSERT( !pExtInputRing || pExtInputRing == pExtInputRing->GetNext(),
292 "more than one InputEngine available" );
293 return (SwExtTextInput*)pExtInputRing;
294 }
295
296