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