• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

Kate

katevimodebase.cpp

Go to the documentation of this file.
00001 /*  This file is part of the KDE libraries and the Kate part.
00002  *
00003  *  Copyright (C) 2008 - 2009 Erlend Hamberg <ehamberg@gmail.com>
00004  *  Copyright (C) 2009 Paul Gideon Dann <pdgiddie@gmail.com>
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 "katevimodebase.h"
00023 #include "katevirange.h"
00024 #include "kateglobal.h"
00025 #include "kateviglobal.h"
00026 #include "katevivisualmode.h"
00027 #include "katevinormalmode.h"
00028 #include "katevireplacemode.h"
00029 #include "kateviinputmodemanager.h"
00030 
00031 #include <QString>
00032 #include <QRegExp>
00033 #include "kateconfig.h"
00034 #include "katedocument.h"
00035 #include "kateviewinternal.h"
00036 #include "katevimodebar.h"
00037 
00038 using KTextEditor::Cursor;
00039 using KTextEditor::Range;
00040 
00041 // TODO: the "previous word/WORD [end]" methods should be optimized. now they're being called in a
00042 // loop and all calculations done up to finding a match are trown away when called with a count > 1
00043 // because they will simply be called again from the last found position.
00044 // They should take the count as a parameter and collect the positions in a QList, then return
00045 // element (count - 1)
00046 
00048 // HELPER METHODS
00050 
00051 bool KateViModeBase::deleteRange( KateViRange &r, bool linewise, bool addToRegister)
00052 {
00053   r.normalize();
00054   bool res = false;
00055   QString removedText = getRange( r, linewise );
00056 
00057   if ( linewise ) {
00058     doc()->editStart();
00059     for ( int i = 0; i < r.endLine-r.startLine+1; i++ ) {
00060       res = doc()->removeLine( r.startLine );
00061     }
00062     doc()->editEnd();
00063   } else {
00064       res = doc()->removeText( Range( r.startLine, r.startColumn, r.endLine, r.endColumn) );
00065   }
00066 
00067   if ( addToRegister ) {
00068     if ( r.startLine == r.endLine ) {
00069       fillRegister( getChosenRegister( '-' ), removedText );
00070     } else {
00071       fillRegister( getChosenRegister( '0' ), removedText );
00072     }
00073   }
00074 
00075   return res;
00076 }
00077 
00078 const QString KateViModeBase::getRange( KateViRange &r, bool linewise) const
00079 {
00080   r.normalize();
00081   QString s;
00082 
00083   if ( linewise ) {
00084     r.startColumn = 0;
00085     r.endColumn = getLine( r.endLine ).length();
00086   }
00087 
00088   if ( r.motionType == ViMotion::InclusiveMotion ) {
00089     r.endColumn++;
00090   }
00091 
00092   Range range( r.startLine, r.startColumn, r.endLine, r.endColumn);
00093 
00094   if ( linewise ) {
00095     s = doc()->textLines( range ).join( QChar( '\n' ) );
00096     s.append( QChar( '\n' ) );
00097   } else {
00098       s = doc()->text( range );
00099   }
00100 
00101   return s;
00102 }
00103 
00104 const QString KateViModeBase::getLine( int lineNumber ) const
00105 {
00106   QString line;
00107 
00108   if ( lineNumber == -1 ) {
00109     Cursor cursor ( m_view->cursorPosition() );
00110     line = m_view->currentTextLine();
00111   } else {
00112     line = doc()->line( lineNumber );
00113   }
00114 
00115   return line;
00116 }
00117 
00118 const QChar KateViModeBase::getCharUnderCursor() const
00119 {
00120   Cursor c( m_view->cursorPosition() );
00121 
00122   QString line = getLine( c.line() );
00123 
00124   if ( line.length() == 0 && c.column() >= line.length() ) {
00125     return QChar::Null;
00126   }
00127 
00128   return line.at( c.column() );
00129 }
00130 
00131 const QString KateViModeBase::getWordUnderCursor() const
00132 {
00133   Cursor c( m_view->cursorPosition() );
00134   Cursor c1 = findPrevWordStart( c.line(), c.column()+1, true );
00135   Cursor c2 = findWordEnd( c1.line(), c1.column()-1, true );
00136   c2.setColumn( c2.column()+1 );
00137 
00138   return doc()->text( Range( c1, c2 ) );
00139 }
00140 
00141 KateViRange KateViModeBase::findPattern( const QString &pattern, bool backwards, int count ) const
00142 {
00143   kDebug( 13070 ) << "searching for pattern \"" << pattern << "\", backwards = " << backwards
00144     << ", count = " << count;
00145   if ( pattern.isEmpty() ) {
00146     return KateViRange();
00147   }
00148 
00149   Cursor c( m_view->cursorPosition() );
00150 
00151   KTextEditor::Search::SearchOptions flags = KTextEditor::Search::Regex;
00152 
00153   if ( backwards ) {
00154     flags |= KTextEditor::Search::Backwards;
00155   }
00156 
00157   for ( int i = count; i > 0; i-- ) {
00158     // prepare two ranges, one from start → cursor and one from cursor → end
00159     Range r1 = Range( Cursor( 0,0 ), c );
00160 
00161     // we want to search from current position + one
00162     if ( c.column() < doc()->lineLength( c.line() ) ) {
00163       c.setColumn( c.column()+1 );
00164     } else if ( c.line() < doc()->lines() ) {
00165       c.setColumn( 0 );
00166       c.setLine( c.line()+1 );
00167     }
00168 
00169     Range r2 = Range( c, doc()->documentEnd() );
00170 
00171     //kDebug( 13070 ) << "r1: " << r1;
00172     //kDebug( 13070 ) << "r2: " << r2;
00173 
00175     //kDebug( 13070 ) << "searching for " << pattern << " in " << (backwards ? "r1" : "r2") << " backwards = " << backwards;
00176     Range result = doc()->searchText( backwards ? r1 : r2, pattern, flags ).first();
00177     //kDebug( 13070 ) << "result: " << result;
00178 
00179     if ( result.isValid() ) {
00180       c = result.start();
00181     } else {
00182 
00183       // no hits, continue from the top
00184       result = doc()->searchText( backwards ? r2 : r1, pattern, flags ).first();
00185 
00186       c = result.start();
00187     }
00188   }
00189 
00190   return KateViRange( c.line(), c.column(), ViMotion::ExclusiveMotion );
00191 }
00192 
00193 Cursor KateViModeBase::findNextWordStart( int fromLine, int fromColumn, bool onlyCurrentLine ) const
00194 {
00195   QString line = getLine( fromLine );
00196 
00197   // the start of word pattern need to take m_extraWordCharacters into account if defined
00198   QString startOfWordPattern("\\b(\\w");
00199   if ( m_extraWordCharacters.length() > 0 ) {
00200     startOfWordPattern.append( QLatin1String( "|[" )+m_extraWordCharacters+']' );
00201   }
00202   startOfWordPattern.append( ')' );
00203 
00204   QRegExp startOfWord( startOfWordPattern );    // start of a word
00205   QRegExp nonSpaceAfterSpace( "\\s\\S" );       // non-space right after space
00206   QRegExp nonWordAfterWord( "\\b(?!\\s)\\W" );  // word-boundary followed by a non-word which is not a space
00207 
00208   int l = fromLine;
00209   int c = fromColumn;
00210 
00211   bool found = false;
00212 
00213   while ( !found ) {
00214     int c1 = startOfWord.indexIn( line, c + 1 );
00215     int c2 = nonSpaceAfterSpace.indexIn( line, c );
00216     int c3 = nonWordAfterWord.indexIn( line, c + 1 );
00217 
00218     if ( c1 == -1 && c2 == -1 && c3 == -1 ) {
00219         if ( onlyCurrentLine ) {
00220             return Cursor( l, c );
00221         } else if ( l >= doc()->lines()-1 ) {
00222             c = line.length()-1;
00223             return Cursor( l, c );
00224         } else {
00225             c = 0;
00226             l++;
00227 
00228             line = getLine( l );
00229 
00230         if ( line.length() == 0 || !line.at( c ).isSpace() ) {
00231           found = true;
00232         }
00233 
00234         continue;
00235       }
00236     }
00237 
00238     c2++; // the second regexp will match one character *before* the character we want to go to
00239 
00240     if ( c1 <= 0 )
00241       c1 = line.length()-1;
00242     if ( c2 <= 0 )
00243       c2 = line.length()-1;
00244     if ( c3 <= 0 )
00245       c3 = line.length()-1;
00246 
00247     c = qMin( c1, qMin( c2, c3 ) );
00248 
00249     found = true;
00250   }
00251 
00252   return Cursor( l, c );
00253 }
00254 
00255 Cursor KateViModeBase::findNextWORDStart( int fromLine, int fromColumn, bool onlyCurrentLine ) const
00256 {
00257   Cursor cursor ( m_view->cursorPosition() );
00258   QString line = getLine();
00259   KateViRange r( cursor.line(), cursor.column(), ViMotion::ExclusiveMotion );
00260 
00261   int l = fromLine;
00262   int c = fromColumn;
00263 
00264   bool found = false;
00265   QRegExp startOfWORD("\\s\\S");
00266 
00267   while ( !found ) {
00268     c = startOfWORD.indexIn( line, c+1 );
00269 
00270     if ( c == -1 ) {
00271       if ( onlyCurrentLine ) {
00272           return Cursor( l, c );
00273       } else if ( l >= doc()->lines()-1 ) {
00274         c = line.length()-1;
00275         break;
00276       } else {
00277         c = 0;
00278         l++;
00279 
00280         line = getLine( l );
00281 
00282         if ( line.length() == 0 || !line.at( c ).isSpace() ) {
00283           found = true;
00284         }
00285 
00286         continue;
00287       }
00288     } else {
00289       c++;
00290       found = true;
00291     }
00292   }
00293 
00294   return Cursor( l, c );
00295 }
00296 
00297 Cursor KateViModeBase::findPrevWordEnd( int fromLine, int fromColumn, bool onlyCurrentLine ) const
00298 {
00299   QString line = getLine( fromLine );
00300 
00301   QString endOfWordPattern = "\\S\\s|\\S$|\\w\\W|\\S\\b|^$";
00302 
00303   if ( m_extraWordCharacters.length() > 0 ) {
00304    endOfWordPattern.append( "|["+m_extraWordCharacters+"][^" +m_extraWordCharacters+']' );
00305   }
00306 
00307   QRegExp endOfWord( endOfWordPattern );
00308 
00309   int l = fromLine;
00310   int c = fromColumn;
00311 
00312   bool found = false;
00313 
00314   while ( !found ) {
00315       int c1 = endOfWord.lastIndexIn( line, c-1 );
00316 
00317       if ( c1 != -1 && c-1 != -1 ) {
00318           found = true;
00319           c = c1;
00320       } else {
00321           if ( onlyCurrentLine ) {
00322               return Cursor( l, c );
00323           } else if ( l > 0 ) {
00324               line = getLine( --l );
00325               c = line.length();
00326 
00327               continue;
00328           } else {
00329               c = 0;
00330               return Cursor( l, c );
00331           }
00332       }
00333   }
00334 
00335   return Cursor( l, c );
00336 }
00337 
00338 Cursor KateViModeBase::findPrevWORDEnd( int fromLine, int fromColumn, bool onlyCurrentLine ) const
00339 {
00340   QString line = getLine( fromLine );
00341 
00342   QRegExp endOfWORDPattern( "\\S\\s|\\S$|^$" );
00343 
00344   QRegExp endOfWORD( endOfWORDPattern );
00345 
00346   int l = fromLine;
00347   int c = fromColumn;
00348 
00349   bool found = false;
00350 
00351   while ( !found ) {
00352       int c1 = endOfWORD.lastIndexIn( line, c-1 );
00353 
00354       if ( c1 != -1 && c-1 != -1 ) {
00355           found = true;
00356           c = c1;
00357       } else {
00358           if ( onlyCurrentLine ) {
00359               return Cursor( l, c );
00360           } else if ( l > 0 ) {
00361               line = getLine( --l );
00362               c = line.length();
00363 
00364               continue;
00365           } else {
00366               c = 0;
00367               return Cursor( l, c );
00368           }
00369       }
00370   }
00371 
00372   return Cursor( l, c );
00373 }
00374 
00375 Cursor KateViModeBase::findPrevWordStart( int fromLine, int fromColumn, bool onlyCurrentLine ) const
00376 {
00377   QString line = getLine( fromLine );
00378 
00379   // the start of word pattern need to take m_extraWordCharacters into account if defined
00380   QString startOfWordPattern("\\b(\\w");
00381   if ( m_extraWordCharacters.length() > 0 ) {
00382     startOfWordPattern.append( QLatin1String( "|[" )+m_extraWordCharacters+']' );
00383   }
00384   startOfWordPattern.append( ')' );
00385 
00386   QRegExp startOfWord( startOfWordPattern );    // start of a word
00387   QRegExp nonSpaceAfterSpace( "\\s\\S" );       // non-space right after space
00388   QRegExp nonWordAfterWord( "\\b(?!\\s)\\W" );  // word-boundary followed by a non-word which is not a space
00389   QRegExp startOfLine( "^\\S" );                // non-space at start of line
00390 
00391   int l = fromLine;
00392   int c = fromColumn;
00393 
00394   bool found = false;
00395 
00396   while ( !found ) {
00397     int c1 = startOfWord.lastIndexIn( line, -line.length()+c-1 );
00398     int c2 = nonSpaceAfterSpace.lastIndexIn( line, -line.length()+c-2 );
00399     int c3 = nonWordAfterWord.lastIndexIn( line, -line.length()+c-1 );
00400     int c4 = startOfLine.lastIndexIn( line, -line.length()+c-1 );
00401 
00402     if ( c1 == -1 && c2 == -1 && c3 == -1 && c4 == -1 ) {
00403       if ( onlyCurrentLine ) {
00404           return Cursor( l, c );
00405       } else if ( l <= 0 ) {
00406         return Cursor( 0, 0 );
00407       } else {
00408         line = getLine( --l );
00409         c = line.length();
00410 
00411         if ( line.length() == 0 ) {
00412           c = 0;
00413           found = true;
00414         }
00415 
00416         continue;
00417       }
00418     }
00419 
00420     c2++; // the second regexp will match one character *before* the character we want to go to
00421 
00422     if ( c1 <= 0 )
00423       c1 = 0;
00424     if ( c2 <= 0 )
00425       c2 = 0;
00426     if ( c3 <= 0 )
00427       c3 = 0;
00428     if ( c4 <= 0 )
00429       c4 = 0;
00430 
00431     c = qMax( c1, qMax( c2, qMax( c3, c4 ) ) );
00432 
00433     found = true;
00434   }
00435 
00436   return Cursor( l, c );
00437 }
00438 
00439 Cursor KateViModeBase::findPrevWORDStart( int fromLine, int fromColumn, bool onlyCurrentLine ) const
00440 {
00441   QString line = getLine( fromLine );
00442 
00443   QRegExp startOfWORD("\\s\\S");
00444   QRegExp startOfLineWORD("^\\S");
00445 
00446   int l = fromLine;
00447   int c = fromColumn;
00448 
00449   bool found = false;
00450 
00451   while ( !found ) {
00452     int c1 = startOfWORD.lastIndexIn( line, -line.length()+c-2 );
00453     int c2 = startOfLineWORD.lastIndexIn( line, -line.length()+c-1 );
00454 
00455     if ( c1 == -1 && c2 == -1 ) {
00456       if ( onlyCurrentLine ) {
00457           return Cursor( l, c );
00458       } else if ( l <= 0 ) {
00459         return Cursor( 0, 0 );
00460       } else {
00461         line = getLine( --l );
00462         c = line.length();
00463 
00464         if ( line.length() == 0 ) {
00465           c = 0;
00466           found = true;
00467         }
00468 
00469         continue;
00470       }
00471     }
00472 
00473     c1++; // the startOfWORD pattern matches one character before the word
00474 
00475     c = qMax( c1, c2 );
00476 
00477     if ( c <= 0 )
00478       c = 0;
00479 
00480     found = true;
00481   }
00482 
00483   return Cursor( l, c );
00484 }
00485 
00486 Cursor KateViModeBase::findWordEnd( int fromLine, int fromColumn, bool onlyCurrentLine ) const
00487 {
00488   QString line = getLine( fromLine );
00489 
00490   QString endOfWordPattern = "\\S\\s|\\S$|\\w\\W|\\S\\b";
00491 
00492   if ( m_extraWordCharacters.length() > 0 ) {
00493    endOfWordPattern.append( "|["+m_extraWordCharacters+"][^" +m_extraWordCharacters+']' );
00494   }
00495 
00496   QRegExp endOfWORD( endOfWordPattern );
00497 
00498   int l = fromLine;
00499   int c = fromColumn;
00500 
00501   bool found = false;
00502 
00503   while ( !found ) {
00504       int c1 = endOfWORD.indexIn( line, c+1 );
00505 
00506       if ( c1 != -1 ) {
00507           found = true;
00508           c = c1;
00509       } else {
00510           if ( onlyCurrentLine ) {
00511               return Cursor( l, c );
00512           } else if ( l >= doc()->lines()-1 ) {
00513               c = line.length()-1;
00514               return Cursor( l, c );
00515           } else {
00516               c = -1;
00517               line = getLine( ++l );
00518 
00519               continue;
00520           }
00521       }
00522   }
00523 
00524   return Cursor( l, c );
00525 }
00526 
00527 Cursor KateViModeBase::findWORDEnd( int fromLine, int fromColumn, bool onlyCurrentLine ) const
00528 {
00529   QString line = getLine( fromLine );
00530 
00531   QRegExp endOfWORD( "\\S\\s|\\S$" );
00532 
00533   int l = fromLine;
00534   int c = fromColumn;
00535 
00536   bool found = false;
00537 
00538   while ( !found ) {
00539       int c1 = endOfWORD.indexIn( line, c+1 );
00540 
00541       if ( c1 != -1 ) {
00542           found = true;
00543           c = c1;
00544       } else {
00545           if ( onlyCurrentLine ) {
00546               return Cursor( l, c );
00547           } else if ( l >= doc()->lines()-1 ) {
00548               c = line.length()-1;
00549               return Cursor( l, c );
00550           } else {
00551               c = -1;
00552               line = getLine( ++l );
00553 
00554               continue;
00555           }
00556       }
00557   }
00558 
00559   return Cursor( l, c );
00560 }
00561 
00562 // FIXME: i" won't work if the cursor is on one of the chars
00563 KateViRange KateViModeBase::findSurrounding( const QChar &c1, const QChar &c2, bool inner ) const
00564 {
00565   Cursor cursor( m_view->cursorPosition() );
00566   QString line = getLine();
00567 
00568   int col1 = line.lastIndexOf( c1, cursor.column() );
00569   int col2 = line.indexOf( c2, cursor.column() );
00570 
00571   KateViRange r( cursor.line(), col1, cursor.line(), col2, ViMotion::InclusiveMotion );
00572 
00573   if ( col1 == -1 || col2 == -1 || col1 > col2 ) {
00574       r.valid = false;
00575   }
00576 
00577   if ( inner ) {
00578       r.startColumn++;
00579       r.endColumn--;
00580   }
00581 
00582   return r;
00583 }
00584 
00585 KateViRange KateViModeBase::findSurrounding( const QRegExp &c1, const QRegExp &c2, bool inner ) const
00586 {
00587   Cursor cursor( m_view->cursorPosition() );
00588   QString line = getLine();
00589 
00590   int col1 = line.lastIndexOf( c1, cursor.column() );
00591   int col2 = line.indexOf( c2, cursor.column() );
00592 
00593   KateViRange r( cursor.line(), col1, cursor.line(), col2, ViMotion::InclusiveMotion );
00594 
00595   if ( col1 == -1 || col2 == -1 || col1 > col2 ) {
00596       r.valid = false;
00597   }
00598 
00599   if ( inner ) {
00600       r.startColumn++;
00601       r.endColumn--;
00602   }
00603 
00604   return r;
00605 }
00606 
00607 int KateViModeBase::findLineStartingWitchChar( const QChar &c, unsigned int count, bool forward ) const
00608 {
00609   int line = m_view->cursorPosition().line();
00610   int lines = doc()->lines();
00611   unsigned int hits = 0;
00612 
00613   if ( forward ) {
00614     line++;
00615   } else {
00616     line--;
00617   }
00618 
00619   while ( line < lines && line > 0 && hits < count ) {
00620     QString l = getLine( line );
00621     if ( l.length() > 0 && l.at( 0 ) == c ) {
00622       hits++;
00623     }
00624     if ( hits != count ) {
00625       if ( forward ) {
00626         line++;
00627       } else {
00628         line--;
00629       }
00630     }
00631   }
00632 
00633   if ( hits == getCount() ) {
00634     return line;
00635   }
00636 
00637   return -1;
00638 }
00639 
00640 void KateViModeBase::updateCursor( const Cursor &c ) const
00641 {
00642   m_viewInternal->updateCursor( c );
00643 }
00644 
00648 QChar KateViModeBase::getChosenRegister( const QChar &defaultReg ) const
00649 {
00650   QChar reg = ( m_register != QChar::Null ) ? m_register : defaultReg;
00651 
00652   return reg;
00653 }
00654 
00655 QString KateViModeBase::getRegisterContent( const QChar &reg ) const
00656 {
00657   QString r = KateGlobal::self()->viInputModeGlobal()->getRegisterContent( reg );
00658 
00659   if ( r.isNull() ) {
00660     error( i18n( "Nothing in register %1" ,reg ));
00661   }
00662 
00663   return r;
00664 }
00665 
00666 void KateViModeBase::fillRegister( const QChar &reg, const QString &text )
00667 {
00668   KateGlobal::self()->viInputModeGlobal()->fillRegister( reg, text );
00669 }
00670 
00671 KateViRange KateViModeBase::goLineDown()
00672 {
00673   return goLineUpDown( getCount() );
00674 }
00675 
00676 KateViRange KateViModeBase::goLineUp()
00677 {
00678   return goLineUpDown( -getCount() );
00679 }
00680 
00685 KateViRange KateViModeBase::goLineUpDown( int lines )
00686 {
00687   Cursor c( m_view->cursorPosition() );
00688   KateViRange r( c.line(), c.column(), ViMotion::InclusiveMotion );
00689   int tabstop = doc()->config()->tabWidth();
00690 
00691   // if in an empty document, just return
00692   if ( lines == 0 ) {
00693     return r;
00694   }
00695 
00696   r.endLine += lines;
00697 
00698   // limit end line to be from line 0 through the last line
00699   if ( r.endLine < 0 ) {
00700     r.endLine = 0;
00701   } else if ( r.endLine > doc()->lines()-1 ) {
00702     r.endLine = doc()->lines()-1;
00703   }
00704 
00705   Kate::TextLine startLine = doc()->plainKateTextLine( c.line() );
00706   Kate::TextLine endLine = doc()->plainKateTextLine( r.endLine );
00707 
00708   int endLineLen = doc()->lineLength( r.endLine )-1;
00709 
00710   if ( endLineLen < 0 ) {
00711     endLineLen = 0;
00712   }
00713 
00714   int endLineLenVirt = endLine->toVirtualColumn(endLineLen, tabstop);
00715   int virtColumnStart = startLine->toVirtualColumn(c.column(), tabstop);
00716 
00717   // if sticky column isn't set, set end column and set sticky column to its virtual column
00718   if ( m_stickyColumn == -1 ) {
00719     r.endColumn = endLine->fromVirtualColumn( virtColumnStart, tabstop );
00720     m_stickyColumn = virtColumnStart;
00721   } else {
00722     // sticky is set - set end column to its value
00723     r.endColumn = endLine->fromVirtualColumn( m_stickyColumn, tabstop );
00724   }
00725 
00726   // make sure end column won't be after the last column of a line
00727   if ( r.endColumn > endLineLen ) {
00728     r.endColumn = endLineLen;
00729   }
00730 
00731   // if we move to a line shorter than the current column, go to its end
00732   if ( virtColumnStart > endLineLenVirt ) {
00733     r.endColumn = endLineLen;
00734   }
00735 
00736   return r;
00737 }
00738 
00739 bool KateViModeBase::startNormalMode()
00740 {
00741   // store the key presses for this "insert mode session" so that it can be repeated with the
00742   // '.' command
00743   if (!m_viInputModeManager->isRunningMacro()) {
00744     m_viInputModeManager->storeChangeCommand();
00745     m_viInputModeManager->clearLog();
00746   }
00747 
00748   m_viInputModeManager->viEnterNormalMode();
00749   m_view->doc()->setUndoMergeAllEdits(false);
00750   m_view->updateViModeBarMode();
00751 
00752   return true;
00753 }
00754 
00755 bool KateViModeBase::startInsertMode()
00756 {
00757   m_viInputModeManager->viEnterInsertMode();
00758   m_view->doc()->setUndoMergeAllEdits(true);
00759   m_view->updateViModeBarMode();
00760 
00761   return true;
00762 }
00763 
00764 bool KateViModeBase::startReplaceMode()
00765 {
00766   m_view->doc()->setUndoMergeAllEdits(true);
00767   m_viInputModeManager->viEnterReplaceMode();
00768   m_view->updateViModeBarMode();
00769 
00770   return true;
00771 }
00772 
00773 bool KateViModeBase::startVisualMode()
00774 {
00775   if ( m_view->getCurrentViMode() == VisualLineMode ) {
00776     m_viInputModeManager->getViVisualMode()->setVisualLine( false );
00777     m_viInputModeManager->changeViMode(VisualMode);
00778   } else if (m_view->getCurrentViMode() == VisualBlockMode ) {
00779     m_viInputModeManager->getViVisualMode()->setVisualBlock( false );
00780     m_viInputModeManager->changeViMode(VisualMode);
00781   } else {
00782     m_viInputModeManager->viEnterVisualMode();
00783   }
00784 
00785   m_view->updateViModeBarMode();
00786 
00787   return true;
00788 }
00789 
00790 bool KateViModeBase::startVisualBlockMode()
00791 {
00792   if ( m_view->getCurrentViMode() == VisualMode ) {
00793     m_viInputModeManager->getViVisualMode()->setVisualBlock( true );
00794     m_viInputModeManager->changeViMode(VisualBlockMode);
00795   } else {
00796     m_viInputModeManager->viEnterVisualMode( VisualBlockMode );
00797   }
00798 
00799   m_view->updateViModeBarMode();
00800 
00801   return true;
00802 }
00803 
00804 bool KateViModeBase::startVisualLineMode()
00805 {
00806   if ( m_view->getCurrentViMode() == VisualMode ) {
00807     m_viInputModeManager->getViVisualMode()->setVisualLine( true );
00808     m_viInputModeManager->changeViMode(VisualLineMode);
00809   } else {
00810     m_viInputModeManager->viEnterVisualMode( VisualLineMode );
00811   }
00812 
00813   m_view->updateViModeBarMode();
00814 
00815   return true;
00816 }
00817 
00818 void KateViModeBase::error( const QString &errorMsg ) const
00819 {
00820   m_view->viModeBar()->showErrorMessage(errorMsg);
00821 }
00822 
00823 void KateViModeBase::message( const QString &msg ) const
00824 {
00825   m_view->viModeBar()->showMessage(msg);
00826 }
00827 
00828 QString KateViModeBase::getVerbatimKeys() const
00829 {
00830   return m_keysVerbatim;
00831 }
00832 
00833 const QChar KateViModeBase::getCharAtVirtualColumn( QString &line, int virtualColumn,
00834     int tabWidth ) const
00835 {
00836   int column = 0;
00837   int tempCol = 0;
00838 
00839   // sanity check: if the line is empty, there are no chars
00840   if ( line.length() == 0 ) {
00841     return QChar::Null;
00842   }
00843 
00844   while ( tempCol < virtualColumn ) {
00845     if ( line.at( column ) == '\t' ) {
00846       tempCol += tabWidth - ( tempCol % tabWidth );
00847     } else {
00848       tempCol++;
00849     }
00850 
00851     if ( tempCol <= virtualColumn ) {
00852       column++;
00853 
00854       if ( column >= line.length() ) {
00855         return QChar::Null;
00856       }
00857     }
00858   }
00859 
00860   if ( line.length() > column )
00861     return line.at( column );
00862 
00863   return QChar::Null;
00864 }
00865 
00866 void KateViModeBase::addToNumberUnderCursor( int count )
00867 {
00868     Cursor c( m_view->cursorPosition() );
00869     QString line = getLine();
00870 
00871     int wordStart = findPrevWordStart( c.line(), c.column()+1, true ).column();
00872     int wordEnd = findWordEnd( c.line(), c.column()-1, true ).column();
00873 
00874     QRegExp number( "(0x)([0-9a-fA-F]+)|\\d+" );
00875 
00876     int start = number.indexIn( line, wordStart );
00877     if ( start <= wordEnd ) {
00878         // FIXME: ignore leading zeroes
00879         QString nString = number.cap();
00880         bool ok = false;
00881         int base = number.cap( 1 ).isEmpty() ? 10 : 16;
00882         int n = nString.toInt( &ok, base );
00883 
00884         kDebug( 13070 ) << "base: " << base;
00885         kDebug( 13070 ) << "n: " << n;
00886 
00887         if ( !ok ) {
00888             // conversion to int failed. give up.
00889             return;
00890         }
00891 
00892         // increase/decrease number
00893         n += count;
00894 
00895         // create the new text string to be inserted. prepend with “0x” if in base 16
00896         QString newText = (base == 16 ? "0x" : "") + QString::number(n, base);
00897 
00898         // replace the old number string with the new
00899         doc()->editStart();
00900         doc()->removeText( KTextEditor::Range( c.line(), start , c.line(), start+nString.length() ) );
00901         doc()->insertText( KTextEditor::Cursor( c.line(), start ), newText );
00902         doc()->editEnd();
00903     }
00904 }
00905 

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal