xref: /trunk/main/sw/source/core/doc/extinput.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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