xref: /aoo41x/main/sw/source/core/doc/extinput.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <com/sun/star/i18n/ScriptType.hpp>
32 
33 #include <editeng/langitem.hxx>
34 #include <editeng/scripttypeitem.hxx>
35 
36 #include <vcl/keycodes.hxx>
37 #include <vcl/cmdevt.hxx>
38 
39 #include <hintids.hxx>
40 #include <extinput.hxx>
41 #include <doc.hxx>
42 #include <IDocumentUndoRedo.hxx>
43 #include <index.hxx>
44 #include <ndtxt.hxx>
45 #include <txtfrm.hxx>
46 #include <swundo.hxx>
47 
48 
49 using namespace ::com::sun::star;
50 
51 SwExtTextInput::SwExtTextInput( const SwPaM& rPam, Ring* pRing )
52     : SwPaM( *rPam.GetPoint(), (SwPaM*)pRing ),
53     eInputLanguage(LANGUAGE_DONTKNOW)
54 {
55 	bIsOverwriteCursor = sal_False;
56 	bInsText = sal_True;
57 }
58 
59 SwExtTextInput::~SwExtTextInput()
60 {
61     SwDoc *const pDoc = GetDoc();
62     if (pDoc->IsInDtor()) { return; /* #i58606# */ }
63 
64 	SwTxtNode* pTNd = GetPoint()->nNode.GetNode().GetTxtNode();
65 	if( pTNd )
66 	{
67 		SwIndex& rIdx = GetPoint()->nContent;
68 		xub_StrLen nSttCnt = rIdx.GetIndex(),
69 				   nEndCnt = GetMark()->nContent.GetIndex();
70 		if( nEndCnt != nSttCnt )
71 		{
72 			if( nEndCnt < nSttCnt )
73 			{
74 				xub_StrLen n = nEndCnt; nEndCnt = nSttCnt; nSttCnt = n;
75 			}
76 
77 			// damit Undo / Redlining usw. richtig funktioniert,
78 			// muss ueber die Doc-Schnittstellen gegangen werden !!!
79             if(eInputLanguage != LANGUAGE_DONTKNOW)
80             {
81                 // --> FME 2005-02-11 #i41974# Only set language attribute
82                 // for CJK/CTL scripts.
83                 bool bLang = true;
84                 // <--
85                 sal_uInt16 nWhich = RES_CHRATR_LANGUAGE;
86                 switch(GetI18NScriptTypeOfLanguage(eInputLanguage))
87                 {
88                     case  i18n::ScriptType::ASIAN:     nWhich = RES_CHRATR_CJK_LANGUAGE; break;
89                     case  i18n::ScriptType::COMPLEX:   nWhich = RES_CHRATR_CTL_LANGUAGE; break;
90                     default: bLang = false;
91                 }
92                 if ( bLang )
93                 {
94                     SvxLanguageItem aLangItem( eInputLanguage, nWhich );
95                     pDoc->InsertPoolItem(*this, aLangItem, 0 );
96                 }
97             }
98             rIdx = nSttCnt;
99 			String sTxt( pTNd->GetTxt().Copy( nSttCnt, nEndCnt - nSttCnt ));
100 			if( bIsOverwriteCursor && sOverwriteText.Len() )
101 			{
102                 xub_StrLen nLen = sTxt.Len();
103 				if( nLen > sOverwriteText.Len() )
104 				{
105 					rIdx += sOverwriteText.Len();
106                     pTNd->EraseText( rIdx, nLen - sOverwriteText.Len() );
107 					rIdx = nSttCnt;
108                     pTNd->ReplaceText( rIdx, sOverwriteText.Len(),
109 											sOverwriteText );
110 					if( bInsText )
111 					{
112 						rIdx = nSttCnt;
113                         pDoc->GetIDocumentUndoRedo().StartUndo(
114                                 UNDO_OVERWRITE, NULL );
115 						pDoc->Overwrite( *this, sTxt.Copy( 0,
116 													sOverwriteText.Len() ));
117                         pDoc->InsertString( *this,
118                             sTxt.Copy( sOverwriteText.Len() ) );
119                         pDoc->GetIDocumentUndoRedo().EndUndo(
120                                 UNDO_OVERWRITE, NULL );
121                     }
122                 }
123                 else
124                 {
125                     pTNd->ReplaceText( rIdx, nLen,
126                             sOverwriteText.Copy( 0, nLen ));
127 					if( bInsText )
128 					{
129 						rIdx = nSttCnt;
130 						pDoc->Overwrite( *this, sTxt );
131 					}
132 				}
133 			}
134 			else
135             {
136                 pTNd->EraseText( rIdx, nEndCnt - nSttCnt );
137 
138 				if( bInsText )
139                 {
140                     pDoc->InsertString( *this, sTxt );
141                 }
142 			}
143 		}
144 	}
145 }
146 
147 void SwExtTextInput::SetInputData( const CommandExtTextInputData& rData )
148 {
149 	SwTxtNode* pTNd = GetPoint()->nNode.GetNode().GetTxtNode();
150 	if( pTNd )
151 	{
152 		xub_StrLen nSttCnt = GetPoint()->nContent.GetIndex(),
153 					nEndCnt = GetMark()->nContent.GetIndex();
154 		if( nEndCnt < nSttCnt )
155 		{
156 			xub_StrLen n = nEndCnt; nEndCnt = nSttCnt; nSttCnt = n;
157 		}
158 
159 		SwIndex aIdx( pTNd, nSttCnt );
160 		const String& rNewStr = rData.GetText();
161 
162 		if( bIsOverwriteCursor && sOverwriteText.Len() )
163 		{
164 			xub_StrLen nReplace = nEndCnt - nSttCnt;
165 			if( rNewStr.Len() < nReplace )
166 			{
167 				// then we must insert from the saved original text
168 				// some characters
169 				nReplace = nReplace - rNewStr.Len();
170 				aIdx += rNewStr.Len();
171                 pTNd->ReplaceText( aIdx, nReplace,
172 							sOverwriteText.Copy( rNewStr.Len(), nReplace ));
173 				aIdx = nSttCnt;
174 				nReplace = rNewStr.Len();
175 			}
176 			else if( sOverwriteText.Len() < nReplace )
177 			{
178 				nReplace = nReplace - sOverwriteText.Len();
179 				aIdx += sOverwriteText.Len();
180                 pTNd->EraseText( aIdx, nReplace );
181 				aIdx = nSttCnt;
182 				nReplace = sOverwriteText.Len();
183 			}
184 			else if( (nReplace = sOverwriteText.Len()) > rNewStr.Len() )
185 				nReplace = rNewStr.Len();
186 
187             pTNd->ReplaceText( aIdx, nReplace, rNewStr );
188 			if( !HasMark() )
189 				SetMark();
190 			GetMark()->nContent = aIdx;
191 		}
192 		else
193 		{
194 			if( nSttCnt < nEndCnt )
195             {
196                 pTNd->EraseText( aIdx, nEndCnt - nSttCnt );
197             }
198 
199             pTNd->InsertText( rNewStr, aIdx,
200                     IDocumentContentOperations::INS_EMPTYEXPAND );
201 			if( !HasMark() )
202 				SetMark();
203 		}
204 
205 		GetPoint()->nContent = nSttCnt;
206 
207 		if( aAttrs.Count() )
208 			aAttrs.Remove( 0, aAttrs.Count() );
209 		if( rData.GetTextAttr() )
210 			aAttrs.Insert( rData.GetTextAttr(), rData.GetText().Len(), 0 );
211 	}
212 }
213 
214 void SwExtTextInput::SetOverwriteCursor( sal_Bool bFlag )
215 {
216 	bIsOverwriteCursor = bFlag;
217 
218 	SwTxtNode* pTNd;
219 	if( bIsOverwriteCursor &&
220 		0 != (pTNd = GetPoint()->nNode.GetNode().GetTxtNode()) )
221 	{
222 		xub_StrLen nSttCnt = GetPoint()->nContent.GetIndex(),
223 					nEndCnt = GetMark()->nContent.GetIndex();
224 		sOverwriteText = pTNd->GetTxt().Copy( nEndCnt < nSttCnt ? nEndCnt
225 																: nSttCnt );
226 		if( sOverwriteText.Len() )
227 		{
228 			xub_StrLen nInWrdAttrPos = sOverwriteText.Search( CH_TXTATR_INWORD ),
229 					nWrdAttrPos = sOverwriteText.Search( CH_TXTATR_BREAKWORD );
230 			if( nWrdAttrPos < nInWrdAttrPos )
231 				nInWrdAttrPos = nWrdAttrPos;
232 			if( STRING_NOTFOUND != nInWrdAttrPos )
233 				sOverwriteText.Erase( nInWrdAttrPos );
234 		}
235 	}
236 }
237 
238 // die Doc Schnittstellen:
239 
240 SwExtTextInput* SwDoc::CreateExtTextInput( const SwPaM& rPam )
241 {
242 	SwExtTextInput* pNew = new SwExtTextInput( rPam, pExtInputRing );
243 	if( !pExtInputRing )
244 		pExtInputRing = pNew;
245 	pNew->SetMark();
246 	return pNew;
247 }
248 
249 void SwDoc::DeleteExtTextInput( SwExtTextInput* pDel )
250 {
251 	if( pDel == pExtInputRing )
252 	{
253 		if( pDel->GetNext() != pExtInputRing )
254 			pExtInputRing = (SwPaM*)pDel->GetNext();
255 		else
256 			pExtInputRing = 0;
257 	}
258 	delete pDel;
259 }
260 
261 SwExtTextInput* SwDoc::GetExtTextInput( const SwNode& rNd,
262 										xub_StrLen nCntntPos ) const
263 {
264 	SwExtTextInput* pRet = 0;
265 	if( pExtInputRing )
266 	{
267 		sal_uLong nNdIdx = rNd.GetIndex();
268 		SwExtTextInput* pTmp = (SwExtTextInput*)pExtInputRing;
269 		do {
270 			sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
271 				  nMk = pTmp->GetMark()->nNode.GetIndex();
272 			xub_StrLen nPtCnt = pTmp->GetPoint()->nContent.GetIndex(),
273 				  	   nMkCnt = pTmp->GetMark()->nContent.GetIndex();
274 
275 			if( nPt < nMk || ( nPt == nMk && nPtCnt < nMkCnt ))
276 			{
277 				sal_uLong nTmp = nMk; nMk = nPt; nPt = nTmp;
278 				nTmp = nMkCnt; nMkCnt = nPtCnt; nPtCnt = (xub_StrLen)nTmp;
279 			}
280 
281 			if( nMk <= nNdIdx && nNdIdx <= nPt &&
282 				( STRING_NOTFOUND == nCntntPos ||
283 					( nMkCnt <= nCntntPos && nCntntPos <= nPtCnt )))
284 			{
285 				pRet = pTmp;
286 				break;
287 			}
288 		} while( pExtInputRing != (pTmp = (SwExtTextInput*)pExtInputRing ) );
289 	}
290 	return pRet;
291 }
292 
293 SwExtTextInput* SwDoc::GetExtTextInput() const
294 {
295 	ASSERT( !pExtInputRing || pExtInputRing == pExtInputRing->GetNext(),
296 			"more then one InputEngine available" );
297 	return (SwExtTextInput*)pExtInputRing;
298 }
299 
300 
301