KHTML
khtmlfind.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 * 00003 * Copyright (C) 2008 Bernhard Beschow <bbeschow cs tu berlin de> 00004 * (C) 2009 Germain Garand <germain@ebooksfrance.org> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Library General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Library General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Library General Public License 00017 * along with this library; see the file COPYING.LIB. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "khtmlfind_p.h" 00023 00024 #include "khtml_part.h" 00025 #include "khtmlviewbar.h" 00026 #include "khtmlfindbar.h" 00027 00028 #include "dom/html_document.h" 00029 #include "html/html_documentimpl.h" 00030 #include "rendering/render_text.h" 00031 #include "rendering/render_replaced.h" 00032 #include "xml/dom_selection.h" 00033 00034 #include "khtmlview.h" 00035 00036 #include <config.h> 00037 00038 #include <QtGui/QClipboard> 00039 00040 #include "rendering/render_form.h" 00041 00042 #define d this 00043 00044 using khtml::RenderPosition; 00045 00046 using namespace DOM; 00047 00048 KHTMLFind::KHTMLFind( KHTMLPart *part, KHTMLFind *parent ) : 00049 m_part( part ), 00050 m_find( 0 ), 00051 m_parent( parent ), 00052 m_findDialog( 0 ) 00053 { 00054 connect( part, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()) ); 00055 } 00056 00057 00058 KHTMLFind::~KHTMLFind() 00059 { 00060 d->m_find = 0; // deleted by its parent, the view. 00061 } 00062 00063 void KHTMLFind::findTextBegin() 00064 { 00065 d->m_findPos = -1; 00066 d->m_findNode = 0; 00067 d->m_findPosEnd = -1; 00068 d->m_findNodeEnd= 0; 00069 d->m_findPosStart = -1; 00070 d->m_findNodeStart = 0; 00071 d->m_findNodePrevious = 0; 00072 delete d->m_find; 00073 d->m_find = 0L; 00074 } 00075 00076 bool KHTMLFind::initFindNode( bool selection, bool reverse, bool fromCursor ) 00077 { 00078 if ( m_part->document().isNull() ) 00079 return false; 00080 00081 DOM::NodeImpl* firstNode = 0L; 00082 if (m_part->document().isHTMLDocument()) 00083 firstNode = m_part->htmlDocument().body().handle(); 00084 else 00085 firstNode = m_part->document().handle(); 00086 00087 if ( !firstNode ) 00088 { 00089 //kDebug(6050) << "no first node (body or doc) -> return false"; 00090 return false; 00091 } 00092 if ( selection && m_part->hasSelection() ) 00093 { 00094 //kDebug(6050) << "using selection"; 00095 const Selection &sel = m_part->caret(); 00096 if ( !fromCursor ) 00097 { 00098 d->m_findNode = reverse ? sel.end().node() : sel.start().node(); 00099 d->m_findPos = reverse ? sel.end().offset() : sel.start().offset(); 00100 } 00101 d->m_findNodeEnd = reverse ? sel.start().node() : sel.end().node(); 00102 d->m_findPosEnd = reverse ? sel.start().offset() : sel.end().offset(); 00103 d->m_findNodeStart = !reverse ? sel.start().node() : sel.end().node(); 00104 d->m_findPosStart = !reverse ? sel.start().offset() : sel.end().offset(); 00105 d->m_findNodePrevious = d->m_findNodeStart; 00106 } 00107 else // whole document 00108 { 00109 //kDebug(6050) << "whole doc"; 00110 if ( !fromCursor ) 00111 { 00112 d->m_findNode = firstNode; 00113 d->m_findPos = reverse ? -1 : 0; 00114 } 00115 d->m_findNodeEnd = reverse ? firstNode : 0; 00116 d->m_findPosEnd = reverse ? 0 : -1; 00117 d->m_findNodeStart = !reverse ? firstNode : 0; 00118 d->m_findPosStart = !reverse ? 0 : -1; 00119 d->m_findNodePrevious = d->m_findNodeStart; 00120 if ( reverse ) 00121 { 00122 // Need to find out the really last object, to start from it 00123 khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0; 00124 if ( obj ) 00125 { 00126 // find the last object in the render tree 00127 while ( obj->lastChild() ) 00128 { 00129 obj = obj->lastChild(); 00130 } 00131 // now get the last object with a NodeImpl associated 00132 while ( !obj->element() && obj->objectAbove() ) 00133 { 00134 obj = obj->objectAbove(); 00135 } 00136 d->m_findNode = obj->element(); 00137 } 00138 } 00139 } 00140 return true; 00141 } 00142 00143 void KHTMLFind::deactivate() 00144 { 00145 kDebug(6050); 00146 d->m_lastFindState.options = d->m_findDialog->options(); 00147 d->m_lastFindState.history = d->m_findDialog->findHistory(); 00148 if (!m_parent) { 00149 d->m_findDialog->hide(); 00150 d->m_findDialog->disconnect(); 00151 d->m_findDialog->deleteLater(); 00152 } 00153 d->m_findDialog = 0L; 00154 00155 // if the selection is limited to a single link, that link gets focus 00156 const DOM::Selection sel = m_part->caret(); 00157 if(sel.start().node() == sel.end().node()) 00158 { 00159 bool isLink = false; 00160 00161 // checks whether the node has a <A> parent 00162 DOM::NodeImpl *parent = sel.start().node(); 00163 while ( parent ) 00164 { 00165 if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A ) 00166 { 00167 isLink = true; 00168 break; 00169 } 00170 parent = parent->parentNode(); 00171 } 00172 00173 if(isLink == true) 00174 { 00175 static_cast<DOM::DocumentImpl *>( m_part->document().handle() )->setFocusNode( parent ); 00176 } 00177 } 00178 } 00179 00180 void KHTMLFind::slotFindDestroyed() 00181 { 00182 d->m_find = 0; 00183 } 00184 00185 void KHTMLFind::activate() 00186 { 00187 // First do some init to make sure we can search in this frame 00188 if ( m_part->document().isNull() ) 00189 return; 00190 00191 // Raise if already opened 00192 if ( d->m_findDialog && !m_parent ) 00193 { 00194 m_part->pBottomViewBar()->showBarWidget( d->m_findDialog ); 00195 return; 00196 } 00197 00198 // The lineedit of the dialog would make khtml lose its selection, otherwise 00199 #ifndef QT_NO_CLIPBOARD 00200 disconnect( qApp->clipboard(), SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()) ); 00201 #endif 00202 00203 if (m_parent) 00204 d->m_findDialog = m_parent->findBar(); 00205 else 00206 { 00207 // Now show the dialog in which the user can choose options. 00208 d->m_findDialog = new KHTMLFindBar( m_part->widget() ); 00209 d->m_findDialog->setHasSelection( m_part->hasSelection() ); 00210 d->m_findDialog->setHasCursor( d->m_findNode != 0 ); 00211 #if 0 00212 if ( d->m_findNode ) // has a cursor -> default to 'FromCursor' 00213 d->m_lastFindState.options |= KFind::FromCursor; 00214 #endif 00215 00216 // TODO? optionsDialog.setPattern( d->m_lastFindState.text ); 00217 d->m_findDialog->setFindHistory( d->m_lastFindState.history ); 00218 d->m_findDialog->setOptions( d->m_lastFindState.options ); 00219 d->m_findDialog->setFocus(); 00220 00221 d->m_lastFindState.options = -1; // force update in findTextNext 00222 d->m_lastFindState.last_dir = -1; 00223 00224 m_part->pBottomViewBar()->addBarWidget( d->m_findDialog ); 00225 m_part->pBottomViewBar()->showBarWidget( d->m_findDialog ); 00226 connect( d->m_findDialog, SIGNAL(searchChanged()), this, SLOT(slotSearchChanged()) ); 00227 connect( d->m_findDialog, SIGNAL(findNextClicked()), this, SLOT(slotFindNext()) ); 00228 connect( d->m_findDialog, SIGNAL(findPreviousClicked()), this, SLOT(slotFindPrevious()) ); 00229 connect( d->m_findDialog, SIGNAL(hideMe()), this, SLOT(deactivate()) ); 00230 } 00231 #ifndef QT_NO_CLIPBOARD 00232 connect( qApp->clipboard(), SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()) ); 00233 #endif 00234 if (m_findDialog) { 00235 createNewKFind( m_findDialog->pattern() , 0 /*options*/, m_findDialog, 0 ); 00236 } else if (m_parent && m_parent->find()) { 00237 createNewKFind( m_parent->find()->pattern(), m_parent->find()->options(), static_cast<QWidget*>(m_parent->find()->parent()), 0 ); 00238 } 00239 } 00240 00241 // ### this crawling through the render tree sucks. There should be another way to 00242 // do that. 00243 static inline KHTMLPart* innerPart( khtml::RenderObject *ro ) { 00244 if (!ro || !ro->isWidget() || ro->isFormElement()) 00245 return 0; 00246 KHTMLView* v = qobject_cast<KHTMLView*>( static_cast<khtml::RenderWidget*>(ro)->widget() ); 00247 return v ? v->part() : 0; 00248 } 00249 static inline KHTMLPart* innerPartFromNode( DOM::NodeImpl *node ) { 00250 return (node && node->renderer() ? innerPart( node->renderer() ) : 0); 00251 } 00252 00253 void KHTMLFind::createNewKFind( const QString &str, long options, QWidget *parent, KFindDialog *findDialog ) 00254 { 00255 // First do some init to make sure we can search in this frame 00256 if ( m_part->document().isNull() ) 00257 return; 00258 00259 if (m_findNode) { 00260 if (KHTMLPart* p = innerPartFromNode(m_findNode)) { 00261 p->clearSelection(); 00262 p->findTextBegin(); 00263 } 00264 } 00265 00266 // Create the KFind object 00267 delete d->m_find; 00268 d->m_find = new KFind( str, options, parent, findDialog ); 00269 d->m_find->closeFindNextDialog(); // we use KFindDialog non-modal, so we don't want other dlg popping up 00270 connect( d->m_find, SIGNAL( highlight( const QString &, int, int ) ), 00271 this, SLOT( slotHighlight( const QString &, int, int ) ) ); 00272 connect( d->m_find, SIGNAL( destroyed() ), 00273 this, SLOT( slotFindDestroyed() ) ); 00274 //connect(d->m_find, SIGNAL( findNext() ), 00275 // this, SLOT( slotFindNext() ) ); 00276 00277 if ( !findDialog ) 00278 { 00279 d->m_lastFindState.options = options; 00280 initFindNode( options & KFind::SelectedText, 00281 options & KFind::FindBackwards, 00282 options & KFind::FromCursor ); 00283 } 00284 } 00285 00286 bool KHTMLFind::findTextNext( bool reverse ) 00287 { 00288 if (!d->m_find) 00289 { 00290 // We didn't show the find dialog yet, let's do it then (#49442) 00291 activate(); 00292 00293 // FIXME Ugly hack: activate() may not create KFind object, so check whether it was created 00294 if (!d->m_find) 00295 return false; 00296 00297 // It also means the user is trying to match a previous pattern, so try and 00298 // restore the last saved pattern. 00299 if (!m_parent && (!d->m_findDialog || !d->m_findDialog->restoreLastPatternFromHistory())) 00300 return false; 00301 } 00302 00303 long options = 0; 00304 if ( d->m_findDialog ) // 0 when we close the dialog 00305 { 00306 // there is a search dialog 00307 // make sure pattern from search dialog is used 00308 // (### in fact pattern changes should always trigger a reconstruction of the KFind object cf. slotSearchChanged 00309 // - so make this an assert) 00310 if ( (d->m_find->pattern() != d->m_findDialog->pattern()) ) { 00311 d->m_find->setPattern( d->m_findDialog->pattern() ); 00312 d->m_find->resetCounts(); 00313 } 00314 00315 // make sure options from search dialog are used 00316 options = d->m_findDialog->options(); 00317 if ( d->m_lastFindState.options != options ) 00318 { 00319 d->m_find->setOptions( options ); 00320 00321 if ( options & KFind::SelectedText ) //#### FIXME find in selection for frames! 00322 Q_ASSERT( m_part->hasSelection() ); 00323 00324 long difference = d->m_lastFindState.options ^ options; 00325 if ( difference & (KFind::SelectedText | KFind::FromCursor ) ) 00326 { 00327 // Important options changed -> reset search range 00328 (void) initFindNode( options & KFind::SelectedText, 00329 options & KFind::FindBackwards, 00330 options & KFind::FromCursor ); 00331 } 00332 d->m_lastFindState.options = options; 00333 } 00334 } else { 00335 // no dialog 00336 options = d->m_lastFindState.options; 00337 } 00338 00339 // only adopt options for search direction manually 00340 if( reverse ) 00341 options = options ^ KFind::FindBackwards; 00342 00343 // make sure our options are used by KFind 00344 if( d->m_find->options() != options ) 00345 d->m_find->setOptions( options ); 00346 00347 // Changing find direction. Start and end nodes must be switched. 00348 // Additionally since d->m_findNode points after the last node 00349 // that was searched, it needs to be "after" it in the opposite direction. 00350 if( d->m_lastFindState.last_dir != -1 00351 && bool( d->m_lastFindState.last_dir ) != bool( options & KFind::FindBackwards )) 00352 { 00353 qSwap( d->m_findNodeEnd, d->m_findNodeStart ); 00354 qSwap( d->m_findPosEnd, d->m_findPosStart ); 00355 qSwap( d->m_findNode, d->m_findNodePrevious ); 00356 00357 // d->m_findNode now point at the end of the last searched line - advance one node 00358 khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0; 00359 khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0; 00360 if ( obj == end ) 00361 obj = 0L; 00362 else if ( obj ) 00363 { 00364 do { 00365 obj = (options & KFind::FindBackwards) ? obj->objectAbove() : obj->objectBelow(); 00366 } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) ); 00367 } 00368 if ( obj ) 00369 d->m_findNode = obj->element(); 00370 else { 00371 // already at end, start again 00372 (void) initFindNode( options & KFind::SelectedText, 00373 options & KFind::FindBackwards, 00374 options & KFind::FromCursor ); 00375 } 00376 } 00377 d->m_lastFindState.last_dir = ( options & KFind::FindBackwards ) ? 1 : 0; 00378 00379 int numMatchesOld = m_find->numMatches(); 00380 KFind::Result res = KFind::NoMatch; 00381 khtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0; 00382 khtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0; 00383 //kDebug(6050) << "obj=" << obj << " end=" << end; 00384 while( res == KFind::NoMatch ) 00385 { 00386 if ( d->m_find->needData() ) 00387 { 00388 if ( !obj ) { 00389 //kDebug(6050) << "obj=0 -> done"; 00390 break; // we're done 00391 } 00392 //kDebug(6050) << " gathering data"; 00393 // First make up the QString for the current 'line' (i.e. up to \n) 00394 // We also want to remember the DOMNode for every portion of the string. 00395 // We store this in an index->node list. 00396 00397 d->m_stringPortions.clear(); 00398 bool newLine = false; 00399 QString str; 00400 DOM::NodeImpl* lastNode = d->m_findNode; 00401 while ( obj && !newLine ) 00402 { 00403 // Grab text from render object 00404 QString s; 00405 if ( obj->renderName() == QLatin1String("RenderTextArea") ) 00406 { 00407 s = static_cast<khtml::RenderTextArea *>(obj)->text(); 00408 s = s.replace(0xa0, ' '); 00409 } 00410 else if ( obj->renderName() == QLatin1String("RenderLineEdit") ) 00411 { 00412 khtml::RenderLineEdit *parentLine= static_cast<khtml::RenderLineEdit *>(obj); 00413 if (parentLine->widget()->echoMode() == QLineEdit::Normal) 00414 s = parentLine->widget()->text(); 00415 s = s.replace(0xa0, ' '); 00416 } 00417 else if ( obj->isText() ) 00418 { 00419 bool isLink = false; 00420 00421 // checks whether the node has a <A> parent 00422 if ( options & KHTMLPart::FindLinksOnly ) 00423 { 00424 DOM::NodeImpl *parent = obj->element(); 00425 while ( parent ) 00426 { 00427 if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A ) 00428 { 00429 isLink = true; 00430 break; 00431 } 00432 parent = parent->parentNode(); 00433 } 00434 } 00435 else 00436 { 00437 isLink = true; 00438 } 00439 00440 if ( isLink ) 00441 { 00442 s = static_cast<khtml::RenderText *>(obj)->data().string(); 00443 s = s.replace(0xa0, ' '); 00444 } 00445 } 00446 else if ( KHTMLPart *p = innerPart(obj) ) 00447 { 00448 if (p->pFindTextNextInThisFrame(reverse)) 00449 { 00450 numMatchesOld++; 00451 res = KFind::Match; 00452 lastNode = obj->element(); 00453 break; 00454 } 00455 00456 } 00457 else if ( obj->isBR() ) 00458 s = '\n'; 00459 else if ( !obj->isInline() && !str.isEmpty() ) 00460 s = '\n'; 00461 00462 if ( lastNode == d->m_findNodeEnd ) 00463 s.truncate( d->m_findPosEnd ); 00464 if ( !s.isEmpty() ) 00465 { 00466 newLine = s.indexOf( '\n' ) != -1; // did we just get a newline? 00467 if( !( options & KFind::FindBackwards )) 00468 { 00469 //kDebug(6050) << "StringPortion: " << index << "-" << index+s.length()-1 << " -> " << lastNode; 00470 d->m_stringPortions.append( StringPortion( str.length(), lastNode ) ); 00471 str += s; 00472 } 00473 else // KFind itself can search backwards, so str must not be built backwards 00474 { 00475 for( QList<StringPortion>::Iterator it = d->m_stringPortions.begin(); 00476 it != d->m_stringPortions.end(); 00477 ++it ) 00478 (*it).index += s.length(); 00479 d->m_stringPortions.prepend( StringPortion( 0, lastNode ) ); 00480 str.prepend( s ); 00481 } 00482 } 00483 // Compare obj and end _after_ we processed the 'end' node itself 00484 if ( obj == end ) 00485 obj = 0L; 00486 else 00487 { 00488 // Move on to next object (note: if we found a \n already, then obj (and lastNode) 00489 // will point to the _next_ object, i.e. they are in advance. 00490 do { 00491 // We advance until the next RenderObject that has a NodeImpl as its element(). 00492 // Otherwise (if we keep the 'last node', and it has a '\n') we might be stuck 00493 // on that object forever... 00494 obj = (options & KFind::FindBackwards) ? obj->objectAbove() : obj->objectBelow(); 00495 } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) ); 00496 } 00497 if ( obj ) 00498 lastNode = obj->element(); 00499 else 00500 lastNode = 0; 00501 } // end while 00502 00503 if ( !str.isEmpty() ) 00504 { 00505 d->m_find->setData( str, d->m_findPos ); 00506 } 00507 d->m_findPos = -1; // not used during the findnext loops. Only during init. 00508 d->m_findNodePrevious = d->m_findNode; 00509 d->m_findNode = lastNode; 00510 } 00511 if ( !d->m_find->needData() && !(res == KFind::Match) ) // happens if str was empty 00512 { 00513 // Let KFind inspect the text fragment, and emit highlighted if a match is found 00514 res = d->m_find->find(); 00515 } 00516 } // end while 00517 00518 if ( res == KFind::NoMatch ) // i.e. we're done 00519 { 00520 kDebug(6050) << "No more matches."; 00521 if ( !(options & KHTMLPart::FindNoPopups) && d->m_find->shouldRestart() ) 00522 { 00523 kDebug(6050) << "Restarting"; 00524 initFindNode( false, options & KFind::FindBackwards, false ); 00525 d->m_find->resetCounts(); 00526 findTextNext( reverse ); 00527 } 00528 else // really done 00529 { 00530 kDebug(6050) << "Finishing"; 00531 //delete d->m_find; 00532 //d->m_find = 0L; 00533 initFindNode( false, options & KFind::FindBackwards, false ); 00534 d->m_find->resetCounts(); 00535 d->m_part->clearSelection(); 00536 } 00537 kDebug(6050) << "Dialog closed."; 00538 } 00539 00540 if ( m_findDialog != 0 ) 00541 { 00542 m_findDialog->setFoundMatch( res == KFind::Match ); 00543 m_findDialog->setAtEnd( m_find->numMatches() < numMatchesOld ); 00544 } 00545 00546 return res == KFind::Match; 00547 } 00548 00549 void KHTMLFind::slotHighlight( const QString& /*text*/, int index, int length ) 00550 { 00551 //kDebug(6050) << "slotHighlight index=" << index << " length=" << length; 00552 QList<StringPortion>::Iterator it = d->m_stringPortions.begin(); 00553 const QList<StringPortion>::Iterator itEnd = d->m_stringPortions.end(); 00554 QList<StringPortion>::Iterator prev = it; 00555 // We stop at the first portion whose index is 'greater than', and then use the previous one 00556 while ( it != itEnd && (*it).index <= index ) 00557 { 00558 prev = it; 00559 ++it; 00560 } 00561 Q_ASSERT ( prev != itEnd ); 00562 DOM::NodeImpl* node = (*prev).node; 00563 Q_ASSERT( node ); 00564 00565 Selection sel(RenderPosition(node, index - (*prev).index).position()); 00566 00567 khtml::RenderObject* obj = node->renderer(); 00568 khtml::RenderTextArea *renderTextArea = 0L; 00569 khtml::RenderLineEdit *renderLineEdit = 0L; 00570 00571 Q_ASSERT( obj ); 00572 if ( obj ) 00573 { 00574 int x = 0, y = 0; 00575 00576 if ( obj->renderName() == QLatin1String("RenderTextArea") ) 00577 renderTextArea = static_cast<khtml::RenderTextArea *>(obj); 00578 if ( obj->renderName() == QLatin1String("RenderLineEdit") ) 00579 renderLineEdit = static_cast<khtml::RenderLineEdit *>(obj); 00580 if ( !renderLineEdit && !renderTextArea ) 00581 //if (static_cast<khtml::RenderText *>(node->renderer()) 00582 // ->posOfChar(d->m_startOffset, x, y)) 00583 { 00584 int dummy; 00585 static_cast<khtml::RenderText *>(node->renderer()) 00586 ->caretPos( RenderPosition::fromDOMPosition(sel.start()).renderedOffset(), false, x, y, dummy, dummy ); // more precise than posOfChar 00587 //kDebug(6050) << "topleft: " << x << "," << y; 00588 if ( x != -1 || y != -1 ) 00589 { 00590 int gox = m_part->view()->contentsX(); 00591 if (x+50 > m_part->view()->contentsX() + m_part->view()->visibleWidth()) 00592 gox = x - m_part->view()->visibleWidth() + 50; 00593 if (x-10 < m_part->view()->contentsX()) 00594 gox = x - m_part->view()->visibleWidth() - 10; 00595 if (gox < 0) gox = 0; 00596 m_part->view()->setContentsPos(gox, y-50); 00597 } 00598 } 00599 } 00600 // Now look for end node 00601 it = prev; // no need to start from beginning again 00602 while ( it != itEnd && (*it).index < index + length ) 00603 { 00604 prev = it; 00605 ++it; 00606 } 00607 Q_ASSERT ( prev != itEnd ); 00608 00609 sel.moveTo(sel.start(), RenderPosition((*prev).node, index + length - (*prev).index).position()); 00610 00611 #if 0 00612 kDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " << 00613 d->m_selectionEnd.handle() << "," << d->m_endOffset << endl; 00614 it = d->m_stringPortions.begin(); 00615 for ( ; it != d->m_stringPortions.end() ; ++it ) 00616 kDebug(6050) << " StringPortion: from index=" << (*it).index << " -> node=" << (*it).node; 00617 #endif 00618 if ( renderTextArea ) 00619 renderTextArea->highLightWord( length, sel.end().offset()-length ); 00620 else if ( renderLineEdit ) 00621 renderLineEdit->highLightWord( length, sel.end().offset()-length ); 00622 else 00623 { 00624 m_part->setCaret( sel ); 00625 // d->m_doc->updateSelection(); 00626 if (sel.end().node()->renderer() ) 00627 { 00628 int x, y, height, dummy; 00629 static_cast<khtml::RenderText *>(sel.end().node()->renderer()) 00630 ->caretPos( RenderPosition::fromDOMPosition(sel.end()).renderedOffset(), false, x, y, dummy, height ); // more precise than posOfChar 00631 //kDebug(6050) << "bottomright: " << x << "," << y+height; 00632 } 00633 } 00634 m_part->emitSelectionChanged(); 00635 00636 } 00637 00638 void KHTMLFind::slotSelectionChanged() 00639 { 00640 if ( d->m_findDialog ) 00641 d->m_findDialog->setHasSelection( m_part->hasSelection() ); 00642 } 00643 00644 void KHTMLFind::slotSearchChanged() 00645 { 00646 createNewKFind( m_findDialog->pattern(), m_findDialog->options(), m_findDialog, 0 ); 00647 findTextNext(); 00648 } 00649 00650 void KHTMLFind::slotFindNext() 00651 { 00652 findTextNext(); 00653 } 00654 00655 void KHTMLFind::slotFindPrevious() 00656 { 00657 findTextNext( true ); // find backwards 00658 }
KDE 4.6 API Reference