• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Kate

katevinormalmode.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002  * Copyright (C) 2008 Erlend Hamberg <ehamberg@gmail.com>
00003  * Copyright (C) 2008 Evgeniy Ivanov <powerfox@kde.ru>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) version 3.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "katevinormalmode.h"
00022 #include "katevivisualmode.h"
00023 #include "kateviinputmodemanager.h"
00024 #include "katesmartmanager.h"
00025 #include "katesmartrange.h"
00026 #include "katebuffer.h"
00027 #include <QApplication>
00028 #include <QList>
00029 
00030 KateViNormalMode::KateViNormalMode( KateViInputModeManager *viInputModeManager, KateView * view, KateViewInternal * viewInternal )
00031 {
00032   m_view = view;
00033   m_viewInternal = viewInternal;
00034   m_viInputModeManager = viInputModeManager;
00035   m_stickyColumn = -1;
00036 
00037   // FIXME: make configurable:
00038   m_extraWordCharacters = "";
00039   m_matchingItems["/*"] = "*/";
00040   m_matchingItems["*/"] = "-/*";
00041 
00042   m_matchItemRegex = generateMatchingItemRegex();
00043 
00044   m_defaultRegister = '"';
00045   m_marks = new QMap<QChar, KTextEditor::SmartCursor*>;
00046   m_keyParser = new KateViKeySequenceParser();
00047 
00048   initializeCommands();
00049   resetParser(); // initialise with start configuration
00050 }
00051 
00052 KateViNormalMode::~KateViNormalMode()
00053 {
00054   delete m_marks;
00055   delete m_keyParser;
00056 }
00057 
00062 bool KateViNormalMode::handleKeypress( const QKeyEvent *e )
00063 {
00064   int keyCode = e->key();
00065   QString text = e->text();
00066 
00067   // ignore modifier keys alone
00068   if ( keyCode == Qt::Key_Shift || keyCode == Qt::Key_Control
00069       || keyCode == Qt::Key_Alt || keyCode == Qt::Key_Meta ) {
00070     return false;
00071   }
00072 
00073   if ( keyCode == Qt::Key_Escape ) {
00074     reset();
00075     return true;
00076   }
00077 
00078   QChar key = m_keyParser->KeyEventToQChar( e->key(), e->text(), e->modifiers(), e->nativeScanCode() );
00079   //kDebug( 13070 ) << key << "(" << keyCode << ")";
00080   m_keysVerbatim.append( m_keyParser->decodeKeySequence( key ) );
00081 
00082   QChar c = QChar::Null;
00083   if ( m_keys.size() > 0 ) {
00084     c = m_keys.at( m_keys.size()-1 ); // last char
00085   }
00086 
00087   if ( ( keyCode >= Qt::Key_0 && keyCode <= Qt::Key_9 && c != '"' )     // key 0-9
00088       && ( m_countTemp != 0 || keyCode != Qt::Key_0 )                   // the first digit can't be 0
00089       && ( c != 'f' && c != 't' && c != 'F' && c != 'T' && c != 'r' ) ){// "find character" motions
00090 
00091     m_countTemp *= 10;
00092     m_countTemp += keyCode-Qt::Key_0;
00093 
00094     return true;
00095   } else if ( m_countTemp != 0 ) {
00096     m_count = getCount() * m_countTemp;
00097     m_countTemp = 0;
00098 
00099     kDebug( 13070 ) << "count = " << getCount();
00100   }
00101 
00102   m_keys.append( key );
00103 
00104   // Special case: "cw" and "cW" work the same as "ce" and "cE" if the cursor is
00105   // on a non-blank.  This is because Vim interprets "cw" as change-word, and a
00106   // word does not include the following white space. (:help cw in vim)
00107   if ( ( m_keys == "cw" || m_keys == "cW" ) && !getCharUnderCursor().isSpace() ) {
00108     // Special case of the special case: :-)
00109     // If the cursor is at the end of the current word rewrite to "cl"
00110     KTextEditor::Cursor c1( m_view->cursorPosition() ); // current position
00111     KTextEditor::Cursor c2 = findWordEnd(c1.line(), c1.column()-1, true); // word end
00112 
00113     if ( c1 == c2 ) { // the cursor is at the end of a word
00114       m_keys = "cl";
00115     } else {
00116       if ( m_keys.at(1) == 'w' ) {
00117         m_keys = "ce";
00118       } else {
00119         m_keys = "cE";
00120       }
00121     }
00122   }
00123 
00124   if ( m_keys[ 0 ] == Qt::Key_QuoteDbl ) {
00125     if ( m_keys.size() < 2 ) {
00126       return true; // waiting for a register
00127     }
00128     else {
00129       QChar r = m_keys[ 1 ].toLower();
00130 
00131       if ( ( r >= '0' && r <= '9' ) || ( r >= 'a' && r <= 'z' ) || r == '_' || r == '+' || r == '*' ) {
00132         m_register = r;
00133         kDebug( 13070 ) << "Register set to " << r;
00134         m_keys.clear();
00135         return true;
00136       }
00137       else {
00138         resetParser();
00139         return true;
00140       }
00141     }
00142   }
00143 
00144 
00145   // if we have any matching commands so far, check which ones still match
00146   if ( m_matchingCommands.size() > 0 ) {
00147     int n = m_matchingCommands.size()-1;
00148 
00149     // remove commands not matching anymore
00150     for ( int i = n; i >= 0; i-- ) {
00151       if ( !m_commands.at( m_matchingCommands.at( i ) )->matches( m_keys ) ) {
00152         //kDebug( 13070 ) << "removing " << m_commands.at( m_matchingCommands.at( i ) )->pattern() << ", size before remove is " << m_matchingCommands.size();
00153         if ( m_commands.at( m_matchingCommands.at( i ) )->needsMotion() ) {
00154           // "cache" command needing a motion for later
00155           //kDebug( 13070 ) << "m_motionOperatorIndex set to " << m_motionOperatorIndex;
00156           m_motionOperatorIndex = m_matchingCommands.at( i );
00157         }
00158         m_matchingCommands.remove( i );
00159       }
00160     }
00161 
00162     // check if any of the matching commands need a motion/text object, if so
00163     // push the current command length to m_awaitingMotionOrTextObject so one
00164     // knows where to split the command between the operator and the motion
00165     for ( int i = 0; i < m_matchingCommands.size(); i++ ) {
00166       if ( m_commands.at( m_matchingCommands.at( i ) )->needsMotion() ) {
00167         m_awaitingMotionOrTextObject.push( m_keys.size() );
00168         break;
00169       }
00170     }
00171   } else {
00172     // go through all registered commands and put possible matches in m_matchingCommands
00173     for ( int i = 0; i < m_commands.size(); i++ ) {
00174       if ( m_commands.at( i )->matches( m_keys ) ) {
00175         m_matchingCommands.push_back( i );
00176         if ( m_commands.at( i )->needsMotion() && m_commands.at( i )->pattern().length() == m_keys.size() ) {
00177           m_awaitingMotionOrTextObject.push( m_keys.size() );
00178         }
00179       }
00180     }
00181   }
00182 
00183   // this indicates where in the command string one should start looking for a motion command
00184   int checkFrom = ( m_awaitingMotionOrTextObject.isEmpty() ? 0 : m_awaitingMotionOrTextObject.top() );
00185 
00186   //kDebug( 13070 ) << "checkFrom: " << checkFrom;
00187 
00188   // look for matching motion commands from position 'checkFrom'
00189   // FIXME: if checkFrom hasn't changed, only motions whose index is in
00190   // m_matchingMotions shold be checked
00191   if ( checkFrom < m_keys.size() ) {
00192     for ( int i = 0; i < m_motions.size(); i++ ) {
00193       //kDebug( 13070 )  << "\tchecking " << m_keys.mid( checkFrom )  << " against " << m_motions.at( i )->pattern();
00194       if ( m_motions.at( i )->matches( m_keys.mid( checkFrom ) ) ) {
00195         //kDebug( 13070 )  << m_keys.mid( checkFrom ) << " matches!";
00196         m_matchingMotions.push_back( i );
00197 
00198         // if it matches exact, we have found the motion command to execute
00199         if ( m_motions.at( i )->matchesExact( m_keys.mid( checkFrom ) ) ) {
00200           if ( checkFrom == 0 ) {
00201             // no command given before motion, just move the cursor to wherever
00202             // the motion says it should go to
00203             KateViRange r = m_motions.at( i )->execute();
00204 
00205             // make sure the position is valid before moving the cursor there
00206             if ( r.valid
00207                 && r.endLine >= 0
00208                 && ( r.endLine == 0 || r.endLine <= doc()->lines()-1 )
00209                 && r.endColumn >= 0
00210                 && ( r.endColumn == 0 || r.endColumn < doc()->lineLength( r.endLine ) ) ) {
00211               kDebug( 13070 ) << "No command given, going to position ("
00212                 << r.endLine << "," << r.endColumn << ")";
00213               goToPos( r );
00214               m_viInputModeManager->clearLog();
00215             } else {
00216               kDebug( 13070 ) << "Invalid position: (" << r.endLine << "," << r.endColumn << ")";
00217             }
00218 
00219             resetParser();
00220             return true;
00221           } else {
00222             // execute the specified command and supply the position returned from
00223             // the motion
00224 
00225             m_commandRange = m_motions.at( i )->execute();
00226 
00227             // if we didn't get an explicit start position, use the current cursor position
00228             if ( m_commandRange.startLine == -1 ) {
00229               KTextEditor::Cursor c( m_view->cursorPosition() );
00230               m_commandRange.startLine = c.line();
00231               m_commandRange.startColumn = c.column();
00232             }
00233 
00234             // Special case: "word motions" should never cross a line boundary when they are the
00235             // input to a command
00236             if ( ( m_keys.right(1) == "w" || m_keys.right(1) == "W" )
00237                 && m_commandRange.endLine > m_commandRange.startLine ) {
00238               m_commandRange = motionToEOL();
00239 
00240               KTextEditor::Cursor c( m_view->cursorPosition() );
00241               m_commandRange.startLine = c.line();
00242               m_commandRange.startColumn = c.column();
00243             }
00244 
00245             if ( m_commandRange.valid ) {
00246               kDebug( 13070 ) << "Run command" << m_commands.at( m_motionOperatorIndex )->pattern()
00247                 << "from (" << m_commandRange.startLine << "," << m_commandRange.endLine << ")"
00248                 << "to (" << m_commandRange.endLine << "," << m_commandRange.endColumn << ")";
00249               executeCommand( m_commands.at( m_motionOperatorIndex ) );
00250             } else {
00251               kDebug( 13070 ) << "Invalid range: "
00252                 << "from (" << m_commandRange.startLine << "," << m_commandRange.endLine << ")"
00253                 << "to (" << m_commandRange.endLine << "," << m_commandRange.endColumn << ")";
00254             }
00255 
00256             reset();
00257             return true;
00258           }
00259         }
00260       }
00261     }
00262   }
00263 
00264   //kDebug( 13070 ) << "'" << m_keys << "' MATCHING COMMANDS: " << m_matchingCommands.size();
00265   //kDebug( 13070 ) << "'" << m_keys << "' MATCHING MOTIONS: " << m_matchingMotions.size();
00266   //kDebug( 13070 ) << "'" << m_keys << "' AWAITING MOTION OR TO (INDEX): " << ( m_awaitingMotionOrTextObject.isEmpty() ? 0 : m_awaitingMotionOrTextObject.top() );
00267 
00268   // if we have only one match, check if it is a perfect match and if so, execute it
00269   // if it's not waiting for a motion or a text object
00270   if ( m_matchingCommands.size() == 1 ) {
00271     if ( m_commands.at( m_matchingCommands.at( 0 ) )->matchesExact( m_keys )
00272         && !m_commands.at( m_matchingCommands.at( 0 ) )->needsMotion() ) {
00273       //kDebug( 13070 ) << "Running command at index " << m_matchingCommands.at( 0 );
00274 
00275       KateViCommand *cmd = m_commands.at( m_matchingCommands.at( 0 ) );
00276       executeCommand( cmd );
00277 
00278       // check if reset() should be called. some commands in visual mode should not end visual mode
00279       if ( cmd->shouldReset() ) {
00280         reset();
00281       }
00282       resetParser();
00283 
00284       return true;
00285     }
00286   } else if ( m_matchingCommands.size() == 0 && m_matchingMotions.size() == 0 ) {
00287     //if ( m_awaitingMotionOrTextObject.size() == 0 ) {
00288       resetParser();
00289       return false;
00290     //} else {
00291 
00292     //}
00293   }
00294 
00295   m_matchingMotions.clear();
00296   return false;
00297 }
00298 
00303 void KateViNormalMode::resetParser()
00304 {
00305   kDebug( 13070 ) << "***RESET***";
00306   m_keys.clear();
00307   m_keysVerbatim.clear();
00308   m_count = 0;
00309   m_countTemp = 0;
00310   m_register = QChar::Null;
00311   m_findWaitingForChar = false;
00312   m_waitingForMotionOrTextObject = -1;
00313   m_matchingCommands.clear();
00314   m_matchingMotions.clear();
00315   m_awaitingMotionOrTextObject.clear();
00316   m_motionOperatorIndex = 0;
00317 }
00318 
00319 // reset the command parser
00320 void KateViNormalMode::reset()
00321 {
00322     resetParser();
00323     m_commandRange.startLine = -1;
00324     m_commandRange.startColumn = -1;
00325 }
00326 
00327 void KateViNormalMode::goToPos( const KateViRange &r )
00328 {
00329   KTextEditor::Cursor c;
00330   c.setLine( r.endLine );
00331   c.setColumn( r.endColumn );
00332 
00333   if ( r.jump ) {
00334     addCurrentPositionToJumpList();
00335   }
00336 
00337   if ( c.line() >= doc()->lines() ) {
00338     c.setLine( doc()->lines()-1 );
00339   }
00340 
00341   updateCursor( c );
00342 }
00343 
00344 void KateViNormalMode::executeCommand( const KateViCommand* cmd )
00345 {
00346   cmd->execute();
00347 
00348   // if the command was a change, and it didn't enter insert mode, store the key presses so that
00349   // they can be repeated with '.'
00350   if ( m_viInputModeManager->getCurrentViMode() != InsertMode ) {
00351     if ( cmd->isChange() && !m_viInputModeManager->isRunningMacro() ) {
00352       m_viInputModeManager->storeChangeCommand();
00353     }
00354 
00355     m_viInputModeManager->clearLog();
00356   }
00357 
00358   // make sure the cursor does not end up after the end of the line
00359   KTextEditor::Cursor c( m_view->cursorPosition() );
00360   if ( m_viInputModeManager->getCurrentViMode() == NormalMode ) {
00361     int lineLength = doc()->lineLength( c.line() );
00362 
00363     if ( c.column() >= lineLength ) {
00364       if ( lineLength == 0 ) {
00365         c.setColumn( 0 );
00366       } else {
00367         c.setColumn( lineLength-1 );
00368       }
00369     }
00370     updateCursor( c );
00371   }
00372 }
00373 
00374 void KateViNormalMode::addCurrentPositionToJumpList()
00375 {
00376     KTextEditor::Cursor c( m_view->cursorPosition() );
00377 
00378     KateSmartCursor *cursor = doc()->smartManager()->newSmartCursor( c );
00379 
00380     m_marks->insert( '\'', cursor );
00381 }
00382 
00384 // COMMANDS AND OPERATORS
00386 
00391 bool KateViNormalMode::commandEnterInsertMode()
00392 {
00393   return startInsertMode();
00394 }
00395 
00400 bool KateViNormalMode::commandEnterInsertModeAppend()
00401 {
00402   KTextEditor::Cursor c( m_view->cursorPosition() );
00403   c.setColumn( c.column()+1 );
00404 
00405   // if empty line, the cursor should start at column 0
00406   if ( doc()->lineLength( c.line() ) == 0 ) {
00407     c.setColumn( 0 );
00408   }
00409 
00410   updateCursor( c );
00411 
00412   return startInsertMode();
00413 }
00414 
00419 bool KateViNormalMode::commandEnterInsertModeAppendEOL()
00420 {
00421   KTextEditor::Cursor c( m_view->cursorPosition() );
00422   c.setColumn( doc()->lineLength( c.line() ) );
00423   updateCursor( c );
00424 
00425   return startInsertMode();
00426 }
00427 
00428 bool KateViNormalMode::commandEnterInsertModeBeforeFirstCharacterOfLine()
00429 {
00430   KTextEditor::Cursor cursor( m_view->cursorPosition() );
00431   QRegExp nonSpace( "\\S" );
00432   int c = getLine().indexOf( nonSpace );
00433   if ( c == -1 ) {
00434     c = 0;
00435   }
00436   cursor.setColumn( c );
00437   updateCursor( cursor );
00438 
00439   return startInsertMode();
00440 }
00441 
00442 bool KateViNormalMode::commandEnterVisualLineMode()
00443 {
00444   if ( m_viInputModeManager->getCurrentViMode() == VisualLineMode ) {
00445     reset();
00446     return true;
00447   }
00448 
00449   return startVisualLineMode();
00450 }
00451 
00452 bool KateViNormalMode::commandEnterVisualMode()
00453 {
00454   if ( m_viInputModeManager->getCurrentViMode() == VisualMode ) {
00455     reset();
00456     return true;
00457   }
00458 
00459   return startVisualMode();
00460 }
00461 
00462 bool KateViNormalMode::commandToOtherEnd()
00463 {
00464   if ( m_viInputModeManager->getCurrentViMode() == VisualLineMode
00465       || m_viInputModeManager->getCurrentViMode() == VisualMode ) {
00466     m_viInputModeManager->getViVisualMode()->switchStartEnd();
00467     return true;
00468   }
00469 
00470   return false;
00471 }
00472 
00473 KateViRange KateViNormalMode::motionWordForward()
00474 {
00475   KTextEditor::Cursor c( m_view->cursorPosition() );
00476   KateViRange r( c.line(), c.column(), ViMotion::ExclusiveMotion );
00477 
00478   // Special case: If we're already on the very last character in the document, the motion should be
00479   // inclusive so the last character gets included
00480   if ( c.line() == doc()->lines()-1 && c.column() == doc()->lineLength( c.line() )-1 ) {
00481     r.motionType = ViMotion::InclusiveMotion;
00482   } else {
00483     for ( unsigned int i = 0; i < getCount(); i++ ) {
00484       c = findNextWordStart( c.line(), c.column() );
00485 
00486       // stop when at the last char in the document
00487       if ( c.line() == doc()->lines()-1 && c.column() == doc()->lineLength( c.line() )-1 ) {
00488         // if we still haven't "used up the count", make the motion inclusive, so that the last char
00489         // is included
00490         if ( i < getCount() ) {
00491           r.motionType = ViMotion::InclusiveMotion;
00492         }
00493         break;
00494       }
00495     }
00496   }
00497 
00498   r.endColumn = c.column();
00499   r.endLine = c.line();
00500 
00501   return r;
00502 }
00503 
00504 KateViRange KateViNormalMode::motionWordBackward()
00505 {
00506   KTextEditor::Cursor c( m_view->cursorPosition() );
00507   KateViRange r( c.line(), c.column(), ViMotion::ExclusiveMotion );
00508 
00509   for ( unsigned int i = 0; i < getCount(); i++ ) {
00510     c = findPrevWordStart( c.line(), c.column() );
00511 
00512     // stop when at the first char in the document
00513     if ( c.line() == 0 && c.column() == 0 ) {
00514       break;
00515     }
00516   }
00517 
00518   r.endColumn = c.column();
00519   r.endLine = c.line();
00520 
00521   return r;
00522 }
00523 
00524 KateViRange KateViNormalMode::motionWORDForward()
00525 {
00526   KTextEditor::Cursor c( m_view->cursorPosition() );
00527   KateViRange r( c.line(), c.column(), ViMotion::ExclusiveMotion );
00528 
00529   for ( unsigned int i = 0; i < getCount(); i++ ) {
00530     c = findNextWORDStart( c.line(), c.column() );
00531 
00532     // stop when at the last char in the document
00533     if ( c.line() == doc()->lines()-1 && c.column() == doc()->lineLength( c.line() )-1 ) {
00534       break;
00535     }
00536   }
00537 
00538   r.endColumn = c.column();
00539   r.endLine = c.line();
00540 
00541   return r;
00542 }
00543 
00544 KateViRange KateViNormalMode::motionWORDBackward()
00545 {
00546   KTextEditor::Cursor c( m_view->cursorPosition() );
00547   KateViRange r( c.line(), c.column(), ViMotion::ExclusiveMotion );
00548 
00549   for ( unsigned int i = 0; i < getCount(); i++ ) {
00550     c = findPrevWORDStart( c.line(), c.column() );
00551 
00552     // stop when at the first char in the document
00553     if ( c.line() == 0 && c.column() == 0 ) {
00554       break;
00555     }
00556   }
00557 
00558   r.endColumn = c.column();
00559   r.endLine = c.line();
00560 
00561   return r;
00562 }
00563 
00564 KateViRange KateViNormalMode::motionToEndOfWord()
00565 {
00566     KTextEditor::Cursor c( m_view->cursorPosition() );
00567     KateViRange r( c.line(), c.column(), ViMotion::InclusiveMotion );
00568 
00569     for ( unsigned int i = 0; i < getCount(); i++ ) {
00570         c = findWordEnd( c.line(), c.column() );
00571     }
00572 
00573     r.endColumn = c.column();
00574     r.endLine = c.line();
00575 
00576     return r;
00577 }
00578 
00579 KateViRange KateViNormalMode::motionToEndOfWORD()
00580 {
00581     KTextEditor::Cursor c( m_view->cursorPosition() );
00582     KateViRange r( c.line(), c.column(), ViMotion::InclusiveMotion );
00583 
00584     for ( unsigned int i = 0; i < getCount(); i++ ) {
00585         c = findWORDEnd( c.line(), c.column() );
00586     }
00587 
00588     r.endColumn = c.column();
00589     r.endLine = c.line();
00590 
00591     return r;
00592 }
00593 
00594 KateViRange KateViNormalMode::motionToEndOfPrevWord()
00595 {
00596     KTextEditor::Cursor c( m_view->cursorPosition() );
00597     KateViRange r( c.line(), c.column(), ViMotion::InclusiveMotion );
00598 
00599     for ( unsigned int i = 0; i < getCount(); i++ ) {
00600       c = findPrevWordEnd( c.line(), c.column() );
00601 
00602       // stop when at the first char in the document
00603       if ( c.line() == 0 && c.column() == 0 ) {
00604         break;
00605       }
00606     }
00607 
00608     r.endColumn = c.column();
00609     r.endLine = c.line();
00610 
00611     return r;
00612 }
00613 
00614 KateViRange KateViNormalMode::motionToEndOfPrevWORD()
00615 {
00616     KTextEditor::Cursor c( m_view->cursorPosition() );
00617     KateViRange r( c.line(), c.column(), ViMotion::InclusiveMotion );
00618 
00619     for ( unsigned int i = 0; i < getCount(); i++ ) {
00620       c = findPrevWORDEnd( c.line(), c.column() );
00621 
00622       // stop when at the first char in the document
00623       if ( c.line() == 0 && c.column() == 0 ) {
00624         break;
00625       }
00626     }
00627 
00628     r.endColumn = c.column();
00629     r.endLine = c.line();
00630 
00631     return r;
00632 }
00633 
00634 bool KateViNormalMode::commandDeleteLine()
00635 {
00636   KTextEditor::Cursor c( m_view->cursorPosition() );
00637 
00638   KateViRange r;
00639 
00640   r.startLine = c.line();
00641   r.endLine = c.line()+getCount()-1;
00642 
00643   int column = c.column();
00644 
00645   bool ret = deleteRange( r, true );
00646 
00647   c = m_view->cursorPosition();
00648   if ( column > getLine().length()-1 ) {
00649     column = getLine().length()-1;
00650   }
00651   if ( column < 0 ) {
00652     column = 0;
00653   }
00654 
00655   if ( c.line() > doc()->lines()-1 ) {
00656     c.setLine( doc()->lines()-1 );
00657   }
00658 
00659   c.setColumn( column );
00660   updateCursor( c );
00661 
00662   return ret;
00663 }
00664 
00665 bool KateViNormalMode::commandDelete()
00666 {
00667   bool linewise = m_viInputModeManager->getCurrentViMode() == VisualLineMode
00668     || ( m_commandRange.startLine != m_commandRange.endLine
00669       && m_viInputModeManager->getCurrentViMode() != VisualMode );
00670 
00671   return deleteRange( m_commandRange, linewise );
00672 }
00673 
00674 bool KateViNormalMode::commandDeleteToEOL()
00675 {
00676   KTextEditor::Cursor c( m_view->cursorPosition() );
00677 
00678   m_commandRange.endLine = c.line();
00679   m_commandRange.endColumn = doc()->lineLength( c.line() );
00680 
00681   if ( m_viInputModeManager->getCurrentViMode() == NormalMode ) {
00682     m_commandRange.startLine = c.line();
00683     m_commandRange.startColumn = c.column();
00684   }
00685 
00686   bool linewise = ( m_viInputModeManager->getCurrentViMode() == VisualMode
00687       || m_viInputModeManager->getCurrentViMode() == VisualLineMode );
00688 
00689   bool r = deleteRange( m_commandRange, linewise );
00690 
00691   if ( !linewise ) {
00692     c.setColumn( doc()->lineLength( c.line() )-1 );
00693   } else {
00694     c.setLine( m_commandRange.startLine-1 );
00695     c.setColumn( m_commandRange.startColumn );
00696   }
00697 
00698   // make sure cursor position is valid after deletion
00699   if ( c.line() < 0 ) {
00700     c.setLine( 0 );
00701   }
00702   if ( c.column() > doc()->lineLength( c.line() )-1 ) {
00703     c.setColumn( doc()->lineLength( c.line() )-1 );
00704   }
00705   if ( c.column() < 0 ) {
00706     c.setColumn( 0 );
00707   }
00708 
00709   updateCursor( c );
00710 
00711   return r;
00712 }
00713 
00714 bool KateViNormalMode::commandMakeLowercase()
00715 {
00716   KTextEditor::Cursor c( m_view->cursorPosition() );
00717 
00718   int line1 = m_commandRange.startLine;
00719   int line2 = m_commandRange.endLine;
00720 
00721   if ( line1 == line2 ) { // characterwise
00722     int endColumn = ( m_commandRange.endColumn > c.column() ) ? m_commandRange.endColumn : c.column();
00723     int startColumn = ( m_commandRange.startColumn < c.column() ) ? m_commandRange.startColumn : c.column();
00724     if ( m_commandRange.isInclusive() )
00725       endColumn++;
00726 
00727     KTextEditor::Range range( KTextEditor::Cursor( c.line(), startColumn ), KTextEditor::Cursor( c.line(), endColumn ) );
00728     doc()->replaceText( range, getLine().mid( startColumn, endColumn-startColumn ).toLower() );
00729   }
00730   else { // linewise
00731     QString s;
00732     for ( int i = ( line1 < line2 ? line1 : line2 ); i <= ( line1 < line2 ? line2 : line1 ); i++ ) {
00733        s.append( doc()->line( i ).toLower() + '\n' );
00734     }
00735 
00736     // remove the laste \n
00737     s.chop( 1 );
00738 
00739     KTextEditor::Range range( KTextEditor::Cursor( c.line(), 0 ),
00740         KTextEditor::Cursor( line2, doc()->lineLength( line2 ) ) );
00741 
00742     doc()->replaceText( range, s );
00743   }
00744 
00745   updateCursor( c );
00746 
00747   return true;
00748 }
00749 
00750 bool KateViNormalMode::commandMakeLowercaseLine()
00751 {
00752   KTextEditor::Cursor c( m_view->cursorPosition() );
00753 
00754   m_commandRange.startLine = c.line();
00755   m_commandRange.endLine = c.line();
00756   m_commandRange.startColumn = 0;
00757   m_commandRange.endColumn = doc()->lineLength( c.line() );
00758 
00759   return commandMakeLowercase();
00760 }
00761 
00762 bool KateViNormalMode::commandMakeUppercase()
00763 {
00764   KTextEditor::Cursor c( m_view->cursorPosition() );
00765 
00766   int line1 = m_commandRange.startLine;
00767   int line2 = m_commandRange.endLine;
00768 
00769   if ( line1 == line2 ) { // characterwise
00770     int endColumn = ( m_commandRange.endColumn > c.column() ) ? m_commandRange.endColumn : c.column();
00771     int startColumn = ( m_commandRange.startColumn < c.column() ) ? m_commandRange.startColumn : c.column();
00772     if ( m_commandRange.isInclusive() )
00773       endColumn++;
00774 
00775     KTextEditor::Range range( KTextEditor::Cursor( c.line(), startColumn ), KTextEditor::Cursor( c.line(), endColumn ) );
00776     doc()->replaceText( range, getLine().mid( startColumn, endColumn-startColumn ).toUpper() );
00777   }
00778   else { // linewise
00779     QString s;
00780     for ( int i = ( line1 < line2 ? line1 : line2 ); i <= ( line1 < line2 ? line2 : line1 ); i++ ) {
00781        s.append( doc()->line( i ).toUpper() + '\n' );
00782     }
00783 
00784     // remove the laste \n
00785     s.chop( 1 );
00786 
00787     KTextEditor::Range range( KTextEditor::Cursor( c.line(), 0 ),
00788         KTextEditor::Cursor( line2, doc()->lineLength( line2 ) ) );
00789 
00790     doc()->replaceText( range, s );
00791   }
00792 
00793   updateCursor( c );
00794 
00795   return true;
00796 }
00797 
00798 bool KateViNormalMode::commandMakeUppercaseLine()
00799 {
00800   KTextEditor::Cursor c( m_view->cursorPosition() );
00801 
00802   m_commandRange.startLine = c.line();
00803   m_commandRange.endLine = c.line();
00804   m_commandRange.startColumn = 0;
00805   m_commandRange.endColumn = doc()->lineLength( c.line() );
00806 
00807   return commandMakeUppercase();
00808 }
00809 
00810 bool KateViNormalMode::commandChangeCase()
00811 {
00812   QString text;
00813   KTextEditor::Range range;
00814   KTextEditor::Cursor c( m_view->cursorPosition() );
00815 
00816   // in visual mode, the range is from start position to end position...
00817   if ( m_viInputModeManager->getCurrentViMode() == VisualMode ) {
00818     KTextEditor::Cursor c2 = m_viInputModeManager->getViVisualMode()->getStart();
00819 
00820     if ( c2 > c ) {
00821       c2.setColumn( c2.column()+1 );
00822     } else {
00823       c.setColumn( c.column()+1 );
00824     }
00825 
00826     range.setRange( c, c2 );
00827   // ... in visual line mode, the range is from column 0 on the first line to
00828   // the line length of the last line...
00829   } else if ( m_viInputModeManager->getCurrentViMode() == VisualLineMode ) {
00830     KTextEditor::Cursor c2 = m_viInputModeManager->getViVisualMode()->getStart();
00831 
00832     if ( c2 > c ) {
00833       c2.setColumn( doc()->lineLength( c2.line() ) );
00834       c.setColumn( 0 );
00835     } else {
00836       c.setColumn( doc()->lineLength( c.line() ) );
00837       c2.setColumn( 0 );
00838     }
00839 
00840     range.setRange( c, c2 );
00841   // ... and in normal mode the range is from the current position to the
00842   // current position + count
00843   } else {
00844     KTextEditor::Cursor c2 = c;
00845     c2.setColumn( c.column()+getCount() );
00846 
00847     if ( c2.column() > doc()->lineLength( c.line() ) ) {
00848       c2.setColumn( doc()->lineLength( c.line() ) );
00849     }
00850 
00851     range.setRange( c, c2 );
00852   }
00853 
00854   // get the text the command should operate on
00855   text = doc()->text ( range );
00856 
00857   // for every character, switch its case
00858   for ( int i = 0; i < text.length(); i++ ) {
00859     if ( text.at(i).isUpper() ) {
00860       text[i] = text.at(i).toLower();
00861     } else if ( text.at(i).isLower() ) {
00862       text[i] = text.at(i).toUpper();
00863     }
00864   }
00865 
00866   // replace the old text with the modified text
00867   doc()->replaceText( range, text );
00868 
00869   // in normal mode, move the cursor to the right, in visual mode move the
00870   // cursor to the start of the selection
00871   if ( m_viInputModeManager->getCurrentViMode() == NormalMode ) {
00872     updateCursor( range.end() );
00873   } else {
00874     updateCursor( range.start() );
00875   }
00876 
00877   return true;
00878 }
00879 
00880 bool KateViNormalMode::commandOpenNewLineUnder()
00881 {
00882   KTextEditor::Cursor c( m_view->cursorPosition() );
00883 
00884   c.setColumn( getLine().length() );
00885   updateCursor( c );
00886 
00887   for ( unsigned int i = 0; i < getCount(); i++ ) {
00888     doc()->newLine( m_view );
00889   }
00890 
00891   startInsertMode();
00892   m_viewInternal->repaint ();
00893 
00894   return true;
00895 }
00896 
00897 bool KateViNormalMode::commandOpenNewLineOver()
00898 {
00899   KTextEditor::Cursor c( m_view->cursorPosition() );
00900 
00901   if ( c.line() == 0 ) {
00902     for (unsigned int i = 0; i < getCount(); i++ ) {
00903       doc()->insertLine( 0, QString() );
00904     }
00905     c.setColumn( 0 );
00906     c.setLine( 0 );
00907     updateCursor( c );
00908   } else {
00909     c.setLine( c.line()-1 );
00910     c.setColumn( getLine( c.line() ).length() );
00911     updateCursor( c );
00912     for ( unsigned int i = 0; i < getCount(); i++ ) {
00913         doc()->newLine( m_view );
00914     }
00915 
00916     if ( getCount() > 1 ) {
00917       c = m_view->cursorPosition();
00918       c.setLine( c.line()-(getCount()-1 ) );
00919       updateCursor( c );
00920     }
00921     //c.setLine( c.line()-getCount() );
00922   }
00923 
00924   startInsertMode();
00925   m_viewInternal->repaint ();
00926 
00927   return true;
00928 }
00929 
00930 bool KateViNormalMode::commandJoinLines()
00931 {
00932   KTextEditor::Cursor c( m_view->cursorPosition() );
00933 
00934   int n = getCount();
00935 
00936   // if we were given a range of lines, this information overrides the previous
00937   if ( m_commandRange.startLine != -1 && m_commandRange.endLine != -1 ) {
00938     c.setLine ( m_commandRange.startLine );
00939     n = m_commandRange.endLine-m_commandRange.startLine;
00940   }
00941 
00942   // make sure we don't try to join lines past the document end
00943   if ( n > doc()->lines()-1-c.line() ) {
00944       n = doc()->lines()-1-c.line();
00945   }
00946 
00947   doc()->joinLines( c.line(), c.line()+n );
00948 
00949   return true;
00950 }
00951 
00952 bool KateViNormalMode::commandChange()
00953 {
00954   KTextEditor::Cursor c( m_view->cursorPosition() );
00955 
00956   bool linewise = ( m_commandRange.startLine != m_commandRange.endLine
00957       && m_viInputModeManager->getCurrentViMode() != VisualMode );
00958 
00959   doc()->editStart();
00960   commandDelete();
00961 
00962   // if we deleted several lines, insert an empty line and put the cursor there
00963   if ( linewise ) {
00964     doc()->insertLine( m_commandRange.startLine, QString() );
00965     c.setLine( m_commandRange.startLine );
00966     updateCursor( c );
00967   }
00968   doc()->editEnd();
00969 
00970   commandEnterInsertMode();
00971 
00972   return true;
00973 }
00974 
00975 bool KateViNormalMode::commandChangeToEOL()
00976 {
00977   commandDeleteToEOL();
00978   commandEnterInsertModeAppend();
00979 
00980   return true;
00981 }
00982 
00983 bool KateViNormalMode::commandChangeLine()
00984 {
00985   KTextEditor::Cursor c( m_view->cursorPosition() );
00986   c.setColumn( 0 );
00987   updateCursor( c );
00988 
00989   doc()->editStart();
00990 
00991   // if count >= 2 start by deleting the whole lines
00992   if ( getCount() >= 2 ) {
00993     KateViRange r( c.line(), 0, c.line()+getCount()-2, 0, ViMotion::InclusiveMotion );
00994     deleteRange( r );
00995   }
00996 
00997   // ... then delete the _contents_ of the last line, but keep the line
00998   KateViRange r( c.line(), c.column(), c.line(), doc()->lineLength( c.line() )-1,
00999       ViMotion::InclusiveMotion );
01000   deleteRange( r, false, true );
01001   doc()->editEnd();
01002 
01003   // ... then enter insert mode
01004   commandEnterInsertModeAppend();
01005 
01006   return true;
01007 }
01008 
01009 bool KateViNormalMode::commandSubstituteChar()
01010 {
01011   if ( commandDeleteChar() ) {
01012     return commandEnterInsertMode();
01013   }
01014 
01015   return false;
01016 }
01017 
01018 bool KateViNormalMode::commandSubstituteLine()
01019 {
01020   return commandChangeLine();
01021 }
01022 
01023 bool KateViNormalMode::commandYank()
01024 {
01025   KTextEditor::Cursor c( m_view->cursorPosition() );
01026 
01027   bool r = false;
01028   QString yankedText;
01029 
01030   bool linewise = ( m_commandRange.startLine != m_commandRange.endLine
01031       && m_viInputModeManager->getCurrentViMode() != VisualMode );
01032 
01033   yankedText = getRange( m_commandRange, linewise );
01034 
01035   fillRegister( getChosenRegister( '0' ), yankedText );
01036 
01037   return r;
01038 }
01039 
01040 bool KateViNormalMode::commandYankLine()
01041 {
01042   KTextEditor::Cursor c( m_view->cursorPosition() );
01043   QString lines;
01044   int linenum = c.line();
01045 
01046   for ( unsigned int i = 0; i < getCount(); i++ ) {
01047       lines.append( getLine( linenum + i ) + '\n' );
01048   }
01049   fillRegister( getChosenRegister( '0' ), lines );
01050 
01051   return true;
01052 }
01053 
01054 bool KateViNormalMode::commandYankToEOL()
01055 {
01056   return false;
01057 }
01058 
01059 // insert the text in the given register at the cursor position
01060 // the cursor should end up at the end of what was pasted
01061 bool KateViNormalMode::commandPaste()
01062 {
01063   KTextEditor::Cursor c( m_view->cursorPosition() );
01064   KTextEditor::Cursor cAfter = c;
01065   QChar reg = getChosenRegister( m_defaultRegister );
01066 
01067   QString textToInsert = getRegisterContent( reg );
01068 
01069   if ( getCount() > 1 ) {
01070     QString temp = textToInsert;
01071     for ( unsigned int i = 1; i < getCount(); i++ ) {
01072       textToInsert.append( temp );
01073     }
01074   }
01075 
01076   if ( textToInsert.indexOf('\n') != -1 ) { // lines
01077     textToInsert.chop( 1 ); // remove the last \n
01078     c.setColumn( getLine().length() ); // paste after the current line and ...
01079     textToInsert.prepend( QChar( '\n' ) ); // ... prepend a \n, so the text starts on a new line
01080 
01081     cAfter.setLine( cAfter.line()+1 );
01082   } else { // one line
01083     if ( getLine( c.line() ).length() > 0 ) {
01084       c.setColumn( c.column()+1 );
01085     }
01086 
01087     cAfter.setColumn( cAfter.column() + textToInsert.length() );
01088   }
01089 
01090   doc()->insertText( c, textToInsert );
01091 
01092   updateCursor( cAfter );
01093 
01094   return true;
01095 }
01096 
01097 // insert the text in the given register before the cursor position
01098 // the cursor should end up at the end of what was pasted
01099 bool KateViNormalMode::commandPasteBefore()
01100 {
01101   KTextEditor::Cursor c( m_view->cursorPosition() );
01102   KTextEditor::Cursor cAfter = c;
01103   QChar reg = getChosenRegister( m_defaultRegister );
01104 
01105   QString textToInsert = getRegisterContent( reg );
01106 
01107   if ( getCount() > 1 ) {
01108     QString temp = textToInsert;
01109     for ( unsigned int i = 1; i < getCount(); i++ ) {
01110       textToInsert.append( temp );
01111     }
01112   }
01113 
01114   if ( textToInsert.indexOf('\n') != -1 ) { // lines
01115     c.setColumn( 0 );
01116   } else {
01117     cAfter.setColumn( cAfter.column()+textToInsert.length()-1 );
01118   }
01119 
01120   doc()->insertText( c, textToInsert );
01121 
01122   updateCursor( cAfter );
01123 
01124   return true;
01125 }
01126 
01127 bool KateViNormalMode::commandDeleteChar()
01128 {
01129     KTextEditor::Cursor c( m_view->cursorPosition() );
01130     KateViRange r( c.line(), c.column(), c.line(), c.column()+getCount(), ViMotion::ExclusiveMotion );
01131 
01132     if ( m_commandRange.startLine != -1 && m_commandRange.startColumn != -1 ) {
01133       r = m_commandRange;
01134     } else {
01135       if ( r.endColumn > doc()->lineLength( r.startLine ) ) {
01136         r.endColumn = doc()->lineLength( r.startLine );
01137       }
01138     }
01139 
01140     // should only delete entire lines if in visual line mode
01141     bool linewise = m_viInputModeManager->getCurrentViMode() == VisualLineMode;
01142 
01143     return deleteRange( r, linewise );
01144 }
01145 
01146 bool KateViNormalMode::commandDeleteCharBackward()
01147 {
01148     KTextEditor::Cursor c( m_view->cursorPosition() );
01149 
01150     KateViRange r( c.line(), c.column()-getCount(), c.line(), c.column(), ViMotion::ExclusiveMotion );
01151 
01152     if ( m_commandRange.startLine != -1 && m_commandRange.startColumn != -1 ) {
01153       r = m_commandRange;
01154     } else {
01155       if ( r.startColumn < 0 ) {
01156         r.startColumn = 0;
01157       }
01158     }
01159 
01160     // should only delete entire lines if in visual line mode
01161     bool linewise = m_viInputModeManager->getCurrentViMode() == VisualLineMode;
01162 
01163     return deleteRange( r, linewise );
01164 }
01165 
01166 bool KateViNormalMode::commandReplaceCharacter()
01167 {
01168   KTextEditor::Cursor c1( m_view->cursorPosition() );
01169   KTextEditor::Cursor c2( m_view->cursorPosition() );
01170 
01171   c2.setColumn( c2.column()+1 );
01172 
01173   bool r = doc()->replaceText( KTextEditor::Range( c1, c2 ), m_keys.right( 1 ) );
01174 
01175   updateCursor( c1 );
01176 
01177   return r;
01178 }
01179 
01180 bool KateViNormalMode::commandSwitchToCmdLine()
01181 {
01182     m_view->switchToCmdLine();
01183     return true;
01184 }
01185 
01186 bool KateViNormalMode::commandSearch()
01187 {
01188     m_view->find();
01189     return true;
01190 }
01191 
01192 bool KateViNormalMode::commandUndo()
01193 {
01194     doc()->undo();
01195     return true;
01196 }
01197 
01198 bool KateViNormalMode::commandRedo()
01199 {
01200     doc()->redo();
01201     return true;
01202 }
01203 
01204 bool KateViNormalMode::commandSetMark()
01205 {
01206   KTextEditor::Cursor c( m_view->cursorPosition() );
01207 
01208   KateSmartCursor *cursor = doc()->smartManager()->newSmartCursor( c );
01209 
01210   m_marks->insert( m_keys.at( m_keys.size()-1 ), cursor );
01211   kDebug( 13070 ) << "set mark at (" << c.line() << "," << c.column() << ")";
01212 
01213   return true;
01214 }
01215 
01216 bool KateViNormalMode::commandFindPrev()
01217 {
01218     m_view->findPrevious();
01219 
01220     return true;
01221 }
01222 
01223 bool KateViNormalMode::commandFindNext()
01224 {
01225     m_view->findNext();
01226 
01227     return true;
01228 }
01229 
01230 bool KateViNormalMode::commandIndentLine()
01231 {
01232     KTextEditor::Cursor c( m_view->cursorPosition() );
01233 
01234     for ( unsigned int i = 0; i < getCount(); i++ ) {
01235         doc()->indent( m_view, c.line()+i, 1 );
01236     }
01237 
01238     return true;
01239 }
01240 
01241 bool KateViNormalMode::commandUnindentLine()
01242 {
01243     KTextEditor::Cursor c( m_view->cursorPosition() );
01244 
01245     for ( unsigned int i = 0; i < getCount(); i++ ) {
01246         doc()->indent( m_view, c.line()+i, -1 );
01247     }
01248 
01249     return true;
01250 }
01251 
01252 bool KateViNormalMode::commandIndentLines()
01253 {
01254   KTextEditor::Cursor c( m_view->cursorPosition() );
01255 
01256   m_commandRange.normalize();
01257 
01258   int line1 = m_commandRange.startLine;
01259   int line2 = m_commandRange.endLine;
01260 
01261   doc()->editStart();
01262   for ( int i = line1; i <= line2; i++ ) {
01263       doc()->indent( m_view, i, 1 );
01264   }
01265   doc()->editEnd();
01266 
01267   return true;
01268 }
01269 
01270 bool KateViNormalMode::commandUnindentLines()
01271 {
01272   KTextEditor::Cursor c( m_view->cursorPosition() );
01273 
01274   m_commandRange.normalize();
01275 
01276   int line1 = m_commandRange.startLine;
01277   int line2 = m_commandRange.endLine;
01278 
01279   doc()->editStart();
01280   for ( int i = line1; i <= line2; i++ ) {
01281       doc()->indent( m_view, i, -1 );
01282   }
01283   doc()->editEnd();
01284 
01285   return true;
01286 }
01287 
01288 bool KateViNormalMode::commandScrollPageDown()
01289 {
01290   m_view->pageDown();
01291 
01292   return true;
01293 }
01294 
01295 bool KateViNormalMode::commandScrollPageUp()
01296 {
01297   m_view->pageUp();
01298 
01299   return true;
01300 }
01301 
01302 bool KateViNormalMode::commandAbort()
01303 {
01304   reset();
01305   return true;
01306 }
01307 
01308 bool KateViNormalMode::commandPrintCharacterCode()
01309 {
01310   QChar ch = getCharUnderCursor();
01311 
01312   if ( ch == QChar::Null ) {
01313       message( QString( "NUL" ) );
01314   } else {
01315 
01316     int code = ch.unicode();
01317 
01318     message( QString("<%1> %2,  Hex %3,  Octal %4")
01319         .arg( ch )                          // char
01320         .arg( code )                        // decimal
01321         .arg( code, 0, 16 )                 // hexadecimal
01322         .arg( code, 3, 8, QChar('0') ) );   // octal
01323   }
01324 
01325   return true;
01326 }
01327 
01328 bool KateViNormalMode::commandRepeatLastChange()
01329 {
01330   resetParser();
01331   m_viInputModeManager->repeatLastChange();
01332 
01333   return true;
01334 }
01335 
01336 bool KateViNormalMode::commandAlignLine()
01337 {
01338   const int line = m_view->cursorPosition().line();
01339   KTextEditor::Range alignRange( KTextEditor::Cursor(line, 0), KTextEditor::Cursor(line, 0) );
01340 
01341   doc()->align( m_view, alignRange );
01342 
01343   return true;
01344 }
01345 
01346 bool KateViNormalMode::commandAlignLines()
01347 {
01348   KTextEditor::Cursor c( m_view->cursorPosition() );
01349   m_commandRange.normalize();
01350 
01351   KTextEditor::Cursor start(m_commandRange.startLine, 0);
01352   KTextEditor::Cursor end(m_commandRange.endLine, 0);
01353 
01354   doc()->align( m_view, KTextEditor::Range( start, end ) );
01355 
01356   return true;
01357 }
01358 
01360 // MOTIONS
01362 
01363 KateViRange KateViNormalMode::motionDown()
01364 {
01365   return goLineDown();
01366 }
01367 
01368 
01369 KateViRange KateViNormalMode::motionUp()
01370 {
01371   return goLineUp();
01372 }
01373 
01374 KateViRange KateViNormalMode::motionLeft()
01375 {
01376   KTextEditor::Cursor cursor ( m_view->cursorPosition() );
01377   m_stickyColumn = -1;
01378   KateViRange r( cursor.line(), cursor.column(), ViMotion::ExclusiveMotion );
01379   r.endColumn -= getCount();
01380 
01381   return r;
01382 }
01383 
01384 KateViRange KateViNormalMode::motionRight()
01385 {
01386   KTextEditor::Cursor cursor ( m_view->cursorPosition() );
01387   m_stickyColumn = -1;
01388   KateViRange r( cursor.line(), cursor.column(), ViMotion::ExclusiveMotion );
01389   r.endColumn += getCount();
01390 
01391   return r;
01392 }
01393 
01394 KateViRange KateViNormalMode::motionToEOL()
01395 {
01396   m_stickyColumn = -1;
01397   KTextEditor::Cursor c( m_view->cursorPosition() );
01398   KateViRange r( c.line(), getLine().length()-1, ViMotion::InclusiveMotion );
01399 
01400   return r;
01401 }
01402 
01403 KateViRange KateViNormalMode::motionToColumn0()
01404 {
01405   m_stickyColumn = -1;
01406   KTextEditor::Cursor cursor ( m_view->cursorPosition() );
01407   KateViRange r( cursor.line(), 0, ViMotion::ExclusiveMotion );
01408 
01409   return r;
01410 }
01411 
01412 KateViRange KateViNormalMode::motionToFirstCharacterOfLine()
01413 {
01414   m_stickyColumn = -1;
01415 
01416   KTextEditor::Cursor cursor ( m_view->cursorPosition() );
01417   QRegExp nonSpace( "\\S" );
01418   int c = getLine().indexOf( nonSpace );
01419 
01420   KateViRange r( cursor.line(), c, ViMotion::ExclusiveMotion );
01421 
01422   return r;
01423 }
01424 
01425 KateViRange KateViNormalMode::motionFindChar()
01426 {
01427   KTextEditor::Cursor cursor ( m_view->cursorPosition() );
01428   QString line = getLine();
01429 
01430   int matchColumn = cursor.column();
01431 
01432   for ( unsigned int i = 0; i < getCount(); i++ ) {
01433     matchColumn = line.indexOf( m_keys.right( 1 ), matchColumn+1 );
01434     if ( matchColumn == -1 )
01435       break;
01436   }
01437 
01438   KateViRange r;
01439 
01440   r.startColumn = cursor.column();
01441   r.startLine = cursor.line();
01442   r.endColumn = matchColumn;
01443   r.endLine = cursor.line();
01444 
01445   return r;
01446 }
01447 
01448 KateViRange KateViNormalMode::motionFindCharBackward()
01449 {
01450   KTextEditor::Cursor cursor ( m_view->cursorPosition() );
01451   QString line = getLine();
01452 
01453   int matchColumn = -1;
01454 
01455   unsigned int hits = 0;
01456   int i = cursor.column()-1;
01457 
01458   while ( hits != getCount() && i >= 0 ) {
01459     if ( line.at( i ) == m_keys.at( m_keys.size()-1 ) )
01460       hits++;
01461 
01462     if ( hits == getCount() )
01463       matchColumn = i;
01464 
01465     i--;
01466   }
01467 
01468   KateViRange r;
01469 
01470   r.endColumn = matchColumn;
01471   r.endLine = cursor.line();
01472 
01473   return r;
01474 }
01475 
01476 KateViRange KateViNormalMode::motionToChar()
01477 {
01478   KTextEditor::Cursor cursor ( m_view->cursorPosition() );
01479   QString line = getLine();
01480 
01481   int matchColumn = cursor.column()+1;
01482 
01483   for ( unsigned int i = 0; i < getCount(); i++ ) {
01484     matchColumn = line.indexOf( m_keys.right( 1 ), matchColumn+1 );
01485     if ( matchColumn == -1 )
01486       break;
01487   }
01488 
01489   KateViRange r;
01490 
01491   r.endColumn = matchColumn-1;
01492   r.endLine = cursor.line();
01493 
01494   return r;
01495 }
01496 
01497 KateViRange KateViNormalMode::motionToCharBackward()
01498 {
01499   KTextEditor::Cursor cursor ( m_view->cursorPosition() );
01500   QString line = getLine();
01501 
01502   int matchColumn = -1;
01503 
01504   unsigned int hits = 0;
01505   int i = cursor.column()-2;
01506 
01507   while ( hits != getCount() && i >= 0 ) {
01508     if ( line.at( i ) == m_keys.at( m_keys.size()-1 ) )
01509       hits++;
01510 
01511     if ( hits == getCount() )
01512       matchColumn = i;
01513 
01514     i--;
01515   }
01516 
01517   KateViRange r;
01518 
01519   r.endColumn = matchColumn+1;
01520   r.endLine = cursor.line();
01521 
01522   return r;
01523 }
01524 
01525 KateViRange KateViNormalMode::motionToLineFirst()
01526 {
01527     KateViRange r( getCount()-1, 0, ViMotion::InclusiveMotion );
01528     m_stickyColumn = -1;
01529 
01530     if ( r.endLine > doc()->lines() - 1 ) {
01531       r.endLine = doc()->lines() - 1;
01532     }
01533     r.jump = true;
01534 
01535     return r;
01536 }
01537 
01538 KateViRange KateViNormalMode::motionToLineLast()
01539 {
01540   KateViRange r( doc()->lines()-1, 0, ViMotion::InclusiveMotion );
01541   m_stickyColumn = -1;
01542 
01543   // don't use getCount() here, no count and a count of 1 is different here...
01544   if ( m_count != 0 ) {
01545     r.endLine = m_count-1;
01546   }
01547 
01548   if ( r.endLine > doc()->lines() - 1 ) {
01549     r.endLine = doc()->lines() - 1;
01550   }
01551   r.jump = true;
01552 
01553   return r;
01554 }
01555 
01556 KateViRange KateViNormalMode::motionToScreenColumn()
01557 {
01558   m_stickyColumn = -1;
01559 
01560   KTextEditor::Cursor c( m_view->cursorPosition() );
01561 
01562   int column = getCount()-1;
01563 
01564   if ( doc()->lineLength( c.line() )-1 < (int)getCount()-1 ) {
01565       column = doc()->lineLength( c.line() )-1;
01566   }
01567 
01568   return KateViRange( c.line(), column, ViMotion::ExclusiveMotion );
01569 }
01570 
01571 KateViRange KateViNormalMode::motionToMark()
01572 {
01573   KateViRange r;
01574 
01575   QChar reg = m_keys.at( m_keys.size()-1 );
01576 
01577   // ` and ' is the same register (position before jump)
01578   if ( reg == '`' ) {
01579       reg = '\'';
01580   }
01581 
01582   KTextEditor::SmartCursor* cursor;
01583   if ( m_marks->contains( reg ) ) {
01584     cursor = m_marks->value( reg );
01585     r.endLine = cursor->line();
01586     r.endColumn = cursor->column();
01587   } else {
01588     error(QString("Mark not set: ") + m_keys.right( 1 ) );
01589     r.valid = false;
01590   }
01591 
01592   r.jump = true;
01593 
01594   return r;
01595 }
01596 
01597 KateViRange KateViNormalMode::motionToMarkLine()
01598 {
01599   KateViRange r = motionToMark();
01600   r.endColumn = 0; // FIXME: should be first non-blank on line
01601 
01602   r.jump = true;
01603 
01604   return r;
01605 }
01606 
01607 KateViRange KateViNormalMode::motionToMatchingItem()
01608 {
01609   KateViRange r;
01610   KTextEditor::Cursor c( m_view->cursorPosition() );
01611   int lines = doc()->lines();
01612   QString l = getLine();
01613   int n1 = l.indexOf( m_matchItemRegex, c.column() );
01614   int n2;
01615 
01616   if ( n1 == -1 ) {
01617     r.valid = false;
01618     return r;
01619   } else {
01620     n2 = l.indexOf( QRegExp( "\\s|$" ), n1 );
01621   }
01622 
01623   // text item we want to find a matching item for
01624   QString item = l.mid( n1, n2-n1 );
01625 
01626   // use kate's built-in matching bracket finder for brackets
01627   if ( QString("{}()[]").indexOf( item ) != -1 ) {
01628 
01629     // move the cursor to the first bracket
01630     c.setColumn( n1+1 );
01631     updateCursor( c );
01632 
01633     // find the matching one
01634     c = m_viewInternal->findMatchingBracket();
01635 
01636     if ( c > m_view->cursorPosition() ) {
01637       c.setColumn( c.column()-1 );
01638     }
01639   } else {
01640     int toFind = 1;
01641     //int n2 = l.indexOf( QRegExp( "\\s|$" ), n1 );
01642 
01643     //QString item = l.mid( n1, n2-n1 );
01644     QString matchingItem = m_matchingItems[ item ];
01645 
01646     int line = c.line();
01647     int column = n2-item.length();
01648     bool reverse = false;
01649 
01650     if ( matchingItem.left( 1 ) == "-" ) {
01651       matchingItem.remove( 0, 1 ); // remove the '-'
01652       reverse = true;
01653     }
01654 
01655     // make sure we don't hit the text item we start the search from
01656     if ( column == 0 && reverse ) {
01657       column -= item.length();
01658     }
01659 
01660     int itemIdx;
01661     int matchItemIdx;
01662 
01663     while ( toFind > 0 ) {
01664       if ( !reverse ) {
01665         itemIdx = l.indexOf( item, column );
01666         matchItemIdx = l.indexOf( matchingItem, column );
01667 
01668         if ( itemIdx != -1 && ( matchItemIdx == -1 || itemIdx < matchItemIdx ) ) {
01669             toFind++;
01670         }
01671       } else {
01672         itemIdx = l.lastIndexOf( item, column-1 );
01673         matchItemIdx = l.lastIndexOf( matchingItem, column-1 );
01674 
01675         if ( itemIdx != -1 && ( matchItemIdx == -1 || itemIdx > matchItemIdx ) ) {
01676             toFind++;
01677         }
01678       }
01679 
01680       if ( matchItemIdx != -1 || itemIdx != -1 ) {
01681           if ( !reverse ) {
01682             column = qMin( (unsigned int)itemIdx, (unsigned int)matchItemIdx );
01683           } else {
01684             column = qMax( itemIdx, matchItemIdx );
01685           }
01686       }
01687 
01688       if ( matchItemIdx != -1 ) { // match on current line
01689           if ( matchItemIdx == column ) {
01690               toFind--;
01691               c.setLine( line );
01692               c.setColumn( column );
01693           }
01694       } else { // no match, advance one line if possible
01695         ( reverse) ? line-- : line++;
01696         column = 0;
01697 
01698         if ( ( !reverse && line >= lines ) || ( reverse && line < 0 ) ) {
01699           r.valid = false;
01700           break;
01701         } else {
01702           l = getLine( line );
01703         }
01704       }
01705     }
01706   }
01707 
01708   r.endLine = c.line();
01709   r.endColumn = c.column();
01710   r.jump = true;
01711 
01712   return r;
01713 }
01714 
01715 KateViRange KateViNormalMode::motionToNextBraceBlockStart()
01716 {
01717   KateViRange r;
01718 
01719   int line = findLineStartingWitchChar( '{', getCount() );
01720 
01721   if ( line == -1 ) {
01722     r.valid = false;
01723     return r;
01724   }
01725 
01726   r.endLine = line;
01727   r.endColumn = 0;
01728   r.jump = true;
01729 
01730   return r;
01731 }
01732 
01733 KateViRange KateViNormalMode::motionToPreviousBraceBlockStart()
01734 {
01735   KateViRange r;
01736 
01737   int line = findLineStartingWitchChar( '{', getCount(), false );
01738 
01739   if ( line == -1 ) {
01740     r.valid = false;
01741     return r;
01742   }
01743 
01744   r.endLine = line;
01745   r.endColumn = 0;
01746   r.jump = true;
01747 
01748   return r;
01749 }
01750 
01751 KateViRange KateViNormalMode::motionToNextBraceBlockEnd()
01752 {
01753   KateViRange r;
01754 
01755   int line = findLineStartingWitchChar( '}', getCount() );
01756 
01757   if ( line == -1 ) {
01758     r.valid = false;
01759     return r;
01760   }
01761 
01762   r.endLine = line;
01763   r.endColumn = 0;
01764   r.jump = true;
01765 
01766   return r;
01767 }
01768 
01769 KateViRange KateViNormalMode::motionToPreviousBraceBlockEnd()
01770 {
01771   KateViRange r;
01772 
01773   int line = findLineStartingWitchChar( '{', getCount(), false );
01774 
01775   if ( line == -1 ) {
01776     r.valid = false;
01777     return r;
01778   }
01779 
01780   r.endLine = line;
01781   r.endColumn = 0;
01782   r.jump = true;
01783 
01784   return r;
01785 }
01786 
01788 // TEXT OBJECTS
01790 
01791 KateViRange KateViNormalMode::textObjectAWord()
01792 {
01793     KTextEditor::Cursor c( m_view->cursorPosition() );
01794 
01795     KTextEditor::Cursor c1 = findPrevWordStart( c.line(), c.column()+1, true );
01796     KTextEditor::Cursor c2( c );
01797 
01798     for ( unsigned int i = 0; i < getCount(); i++ ) {
01799         c2 = findNextWordStart( c2.line(), c2.column(), true );
01800     }
01801 
01802     c2.setColumn( c2.column()-1 ); // don't include the first char of the following word
01803     KateViRange r( c.line(), c.column(), ViMotion::InclusiveMotion );
01804 
01805     // sanity check
01806     if ( c1.line() != c2.line() || c1.column() > c2.column() ) {
01807         r.valid = false;
01808     } else {
01809         r.startLine = c1.line();
01810         r.endLine = c2.line();
01811         r.startColumn = c1.column();
01812         r.endColumn = c2.column();
01813     }
01814 
01815     return r;
01816 }
01817 
01818 KateViRange KateViNormalMode::textObjectInnerWord()
01819 {
01820     KTextEditor::Cursor c( m_view->cursorPosition() );
01821 
01822     KTextEditor::Cursor c1 = findPrevWordStart( c.line(), c.column()+1, true );
01823     // need to start search in column-1 because it might be a one-character word
01824     KTextEditor::Cursor c2( c.line(), c.column()-1 );
01825 
01826     for ( unsigned int i = 0; i < getCount(); i++ ) {
01827         c2 = findWordEnd( c2.line(), c2.column(), true );
01828     }
01829 
01830     KateViRange r;
01831 
01832     // sanity check
01833     if ( c1.line() != c2.line() || c1.column() > c2.column() ) {
01834         r.valid = false;
01835     } else {
01836         r.startLine = c1.line();
01837         r.endLine = c2.line();
01838         r.startColumn = c1.column();
01839         r.endColumn = c2.column();
01840     }
01841 
01842     return r;
01843 }
01844 
01845 KateViRange KateViNormalMode::textObjectAWORD()
01846 {
01847     KTextEditor::Cursor c( m_view->cursorPosition() );
01848 
01849     KTextEditor::Cursor c1 = findPrevWORDStart( c.line(), c.column()+1, true );
01850     KTextEditor::Cursor c2( c );
01851 
01852     for ( unsigned int i = 0; i < getCount(); i++ ) {
01853         c2 = findNextWORDStart( c2.line(), c2.column(), true );
01854     }
01855 
01856     KateViRange r( c.line(), c.column(), ViMotion::ExclusiveMotion );
01857 
01858     // sanity check
01859     if ( c1.line() != c2.line() || c1.column() > c2.column() ) {
01860         r.valid = false;
01861     } else {
01862         r.startLine = c1.line();
01863         r.endLine = c2.line();
01864         r.startColumn = c1.column();
01865         r.endColumn = c2.column();
01866     }
01867 
01868     return r;
01869 }
01870 
01871 KateViRange KateViNormalMode::textObjectInnerWORD()
01872 {
01873     KTextEditor::Cursor c( m_view->cursorPosition() );
01874 
01875     KTextEditor::Cursor c1 = findPrevWORDStart( c.line(), c.column()+1, true );
01876     KTextEditor::Cursor c2( c );
01877 
01878     for ( unsigned int i = 0; i < getCount(); i++ ) {
01879         c2 = findWORDEnd( c2.line(), c2.column(), true );
01880     }
01881 
01882     KateViRange r;
01883 
01884     // sanity check
01885     if ( c1.line() != c2.line() || c1.column() > c2.column() ) {
01886         r.valid = false;
01887     } else {
01888         r.startLine = c1.line();
01889         r.endLine = c2.line();
01890         r.startColumn = c1.column();
01891         r.endColumn = c2.column();
01892     }
01893 
01894     return r;
01895 }
01896 
01897 KateViRange KateViNormalMode::textObjectAQuoteDouble()
01898 {
01899     return findSurrounding( '"', '"', false );
01900 }
01901 
01902 KateViRange KateViNormalMode::textObjectInnerQuoteDouble()
01903 {
01904     return findSurrounding( '"', '"', true );
01905 }
01906 
01907 KateViRange KateViNormalMode::textObjectAQuoteSingle()
01908 {
01909     return findSurrounding( '\'', '\'', false );
01910 }
01911 
01912 KateViRange KateViNormalMode::textObjectInnerQuoteSingle()
01913 {
01914     return findSurrounding( '\'', '\'', true );
01915 }
01916 
01917 KateViRange KateViNormalMode::textObjectAParen()
01918 {
01919     return findSurrounding( '(', ')', false );
01920 }
01921 
01922 KateViRange KateViNormalMode::textObjectInnerParen()
01923 {
01924     return findSurrounding( '(', ')', true );
01925 }
01926 
01927 KateViRange KateViNormalMode::textObjectABracket()
01928 {
01929     return findSurrounding( '[', ']', false );
01930 }
01931 
01932 KateViRange KateViNormalMode::textObjectInnerBracket()
01933 {
01934     return findSurrounding( '[', ']', true );
01935 }
01936 
01937 // add commands
01938 // when adding commands here, remember to add them to visual mode too (if applicable)
01939 void KateViNormalMode::initializeCommands()
01940 {
01941   m_commands.push_back( new KateViCommand( this, "a", &KateViNormalMode::commandEnterInsertModeAppend, IS_CHANGE ) );
01942   m_commands.push_back( new KateViCommand( this, "A", &KateViNormalMode::commandEnterInsertModeAppendEOL, IS_CHANGE ) );
01943   m_commands.push_back( new KateViCommand( this, "i", &KateViNormalMode::commandEnterInsertMode, IS_CHANGE ) );
01944   m_commands.push_back( new KateViCommand( this, "I", &KateViNormalMode::commandEnterInsertModeBeforeFirstCharacterOfLine, IS_CHANGE ) );
01945   m_commands.push_back( new KateViCommand( this, "v", &KateViNormalMode::commandEnterVisualMode ) );
01946   m_commands.push_back( new KateViCommand( this, "V", &KateViNormalMode::commandEnterVisualLineMode ) );
01947   m_commands.push_back( new KateViCommand( this, "o", &KateViNormalMode::commandOpenNewLineUnder, IS_CHANGE ) );
01948   m_commands.push_back( new KateViCommand( this, "O", &KateViNormalMode::commandOpenNewLineOver, IS_CHANGE ) );
01949   m_commands.push_back( new KateViCommand( this, "J", &KateViNormalMode::commandJoinLines, IS_CHANGE ) );
01950   m_commands.push_back( new KateViCommand( this, "c", &KateViNormalMode::commandChange, IS_CHANGE | NEEDS_MOTION ) );
01951   m_commands.push_back( new KateViCommand( this, "C", &KateViNormalMode::commandChangeToEOL, IS_CHANGE ) );
01952   m_commands.push_back( new KateViCommand( this, "cc", &KateViNormalMode::commandChangeLine, IS_CHANGE ) );
01953   m_commands.push_back( new KateViCommand( this, "s", &KateViNormalMode::commandSubstituteChar, IS_CHANGE ) );
01954   m_commands.push_back( new KateViCommand( this, "S", &KateViNormalMode::commandSubstituteLine, IS_CHANGE ) );
01955   m_commands.push_back( new KateViCommand( this, "dd", &KateViNormalMode::commandDeleteLine, IS_CHANGE ) );
01956   m_commands.push_back( new KateViCommand( this, "d", &KateViNormalMode::commandDelete, IS_CHANGE | NEEDS_MOTION ) );
01957   m_commands.push_back( new KateViCommand( this, "D", &KateViNormalMode::commandDeleteToEOL, IS_CHANGE ) );
01958   m_commands.push_back( new KateViCommand( this, "x", &KateViNormalMode::commandDeleteChar, IS_CHANGE ) );
01959   m_commands.push_back( new KateViCommand( this, "X", &KateViNormalMode::commandDeleteCharBackward, IS_CHANGE ) );
01960   m_commands.push_back( new KateViCommand( this, "gu", &KateViNormalMode::commandMakeLowercase, IS_CHANGE | NEEDS_MOTION ) );
01961   m_commands.push_back( new KateViCommand( this, "guu", &KateViNormalMode::commandMakeLowercaseLine, IS_CHANGE ) );
01962   m_commands.push_back( new KateViCommand( this, "gU", &KateViNormalMode::commandMakeUppercase, IS_CHANGE | NEEDS_MOTION ) );
01963   m_commands.push_back( new KateViCommand( this, "gUU", &KateViNormalMode::commandMakeUppercaseLine, IS_CHANGE ) );
01964   m_commands.push_back( new KateViCommand( this, "y", &KateViNormalMode::commandYank, NEEDS_MOTION ) );
01965   m_commands.push_back( new KateViCommand( this, "yy", &KateViNormalMode::commandYankLine ) );
01966   m_commands.push_back( new KateViCommand( this, "Y", &KateViNormalMode::commandYankToEOL, NEEDS_MOTION ) );
01967   m_commands.push_back( new KateViCommand( this, "p", &KateViNormalMode::commandPaste, IS_CHANGE ) );
01968   m_commands.push_back( new KateViCommand( this, "P", &KateViNormalMode::commandPasteBefore, IS_CHANGE ) );
01969   m_commands.push_back( new KateViCommand( this, "r.", &KateViNormalMode::commandReplaceCharacter, IS_CHANGE | REGEX_PATTERN ) );
01970   m_commands.push_back( new KateViCommand( this, ":", &KateViNormalMode::commandSwitchToCmdLine ) );
01971   m_commands.push_back( new KateViCommand( this, "/", &KateViNormalMode::commandSearch ) );
01972   m_commands.push_back( new KateViCommand( this, "u", &KateViNormalMode::commandUndo) );
01973   m_commands.push_back( new KateViCommand( this, "<c-r>", &KateViNormalMode::commandRedo ) );
01974   m_commands.push_back( new KateViCommand( this, "U", &KateViNormalMode::commandRedo ) );
01975   m_commands.push_back( new KateViCommand( this, "m.", &KateViNormalMode::commandSetMark, REGEX_PATTERN ) );
01976   m_commands.push_back( new KateViCommand( this, "n", &KateViNormalMode::commandFindNext ) );
01977   m_commands.push_back( new KateViCommand( this, "N", &KateViNormalMode::commandFindPrev ) );
01978   m_commands.push_back( new KateViCommand( this, ">>", &KateViNormalMode::commandIndentLine, IS_CHANGE ) );
01979   m_commands.push_back( new KateViCommand( this, "<<", &KateViNormalMode::commandUnindentLine, IS_CHANGE ) );
01980   m_commands.push_back( new KateViCommand( this, ">", &KateViNormalMode::commandIndentLines, IS_CHANGE | NEEDS_MOTION ) );
01981   m_commands.push_back( new KateViCommand( this, "<", &KateViNormalMode::commandUnindentLines, IS_CHANGE | NEEDS_MOTION ) );
01982   m_commands.push_back( new KateViCommand( this, "<c-f>", &KateViNormalMode::commandScrollPageDown ) );
01983   m_commands.push_back( new KateViCommand( this, "<pagedown>", &KateViNormalMode::commandScrollPageDown ) );
01984   m_commands.push_back( new KateViCommand( this, "<c-b>", &KateViNormalMode::commandScrollPageUp ) );
01985   m_commands.push_back( new KateViCommand( this, "<pageup>", &KateViNormalMode::commandScrollPageUp ) );
01986   m_commands.push_back( new KateViCommand( this, "ga", &KateViNormalMode::commandPrintCharacterCode, SHOULD_NOT_RESET ) );
01987   m_commands.push_back( new KateViCommand( this, ".", &KateViNormalMode::commandRepeatLastChange ) );
01988   m_commands.push_back( new KateViCommand( this, "==", &KateViNormalMode::commandAlignLine, IS_CHANGE ) );
01989   m_commands.push_back( new KateViCommand( this, "=", &KateViNormalMode::commandAlignLines, IS_CHANGE | NEEDS_MOTION) );
01990   m_commands.push_back( new KateViCommand( this, "~", &KateViNormalMode::commandChangeCase, IS_CHANGE ) );
01991 
01992   // regular motions
01993   m_motions.push_back( new KateViMotion( this, "h", &KateViNormalMode::motionLeft ) );
01994   m_motions.push_back( new KateViMotion( this, "<left>", &KateViNormalMode::motionLeft ) );
01995   m_motions.push_back( new KateViMotion( this, "<backspace>", &KateViNormalMode::motionLeft ) );
01996   m_motions.push_back( new KateViMotion( this, "j", &KateViNormalMode::motionDown ) );
01997   m_motions.push_back( new KateViMotion( this, "<down>", &KateViNormalMode::motionDown ) );
01998   m_motions.push_back( new KateViMotion( this, "k", &KateViNormalMode::motionUp ) );
01999   m_motions.push_back( new KateViMotion( this, "<up>", &KateViNormalMode::motionUp ) );
02000   m_motions.push_back( new KateViMotion( this, "l", &KateViNormalMode::motionRight ) );
02001   m_motions.push_back( new KateViMotion( this, "<right>", &KateViNormalMode::motionRight ) );
02002   m_motions.push_back( new KateViMotion( this, " ", &KateViNormalMode::motionRight ) );
02003   m_motions.push_back( new KateViMotion( this, "$", &KateViNormalMode::motionToEOL ) );
02004   m_motions.push_back( new KateViMotion( this, "<end>", &KateViNormalMode::motionToEOL ) );
02005   m_motions.push_back( new KateViMotion( this, "0", &KateViNormalMode::motionToColumn0 ) );
02006   m_motions.push_back( new KateViMotion( this, "<home>", &KateViNormalMode::motionToColumn0 ) );
02007   m_motions.push_back( new KateViMotion( this, "^", &KateViNormalMode::motionToFirstCharacterOfLine ) );
02008   m_motions.push_back( new KateViMotion( this, "f.", &KateViNormalMode::motionFindChar, REGEX_PATTERN ) );
02009   m_motions.push_back( new KateViMotion( this, "F.", &KateViNormalMode::motionFindCharBackward, REGEX_PATTERN ) );
02010   m_motions.push_back( new KateViMotion( this, "t.", &KateViNormalMode::motionToChar, REGEX_PATTERN ) );
02011   m_motions.push_back( new KateViMotion( this, "T.", &KateViNormalMode::motionToCharBackward, REGEX_PATTERN ) );
02012   m_motions.push_back( new KateViMotion( this, "gg", &KateViNormalMode::motionToLineFirst ) );
02013   m_motions.push_back( new KateViMotion( this, "G", &KateViNormalMode::motionToLineLast ) );
02014   m_motions.push_back( new KateViMotion( this, "w", &KateViNormalMode::motionWordForward ) );
02015   m_motions.push_back( new KateViMotion( this, "W", &KateViNormalMode::motionWORDForward ) );
02016   m_motions.push_back( new KateViMotion( this, "b", &KateViNormalMode::motionWordBackward ) );
02017   m_motions.push_back( new KateViMotion( this, "B", &KateViNormalMode::motionWORDBackward ) );
02018   m_motions.push_back( new KateViMotion( this, "e", &KateViNormalMode::motionToEndOfWord ) );
02019   m_motions.push_back( new KateViMotion( this, "E", &KateViNormalMode::motionToEndOfWORD ) );
02020   m_motions.push_back( new KateViMotion( this, "ge", &KateViNormalMode::motionToEndOfPrevWord ) );
02021   m_motions.push_back( new KateViMotion( this, "gE", &KateViNormalMode::motionToEndOfPrevWORD ) );
02022   m_motions.push_back( new KateViMotion( this, "|", &KateViNormalMode::motionToScreenColumn ) );
02023   m_motions.push_back( new KateViMotion( this, "%", &KateViNormalMode::motionToMatchingItem ) );
02024   m_motions.push_back( new KateViMotion( this, "`[a-zA-Z]", &KateViNormalMode::motionToMark, REGEX_PATTERN ) );
02025   m_motions.push_back( new KateViMotion( this, "'[a-zA-Z]", &KateViNormalMode::motionToMarkLine, REGEX_PATTERN ) );
02026   m_motions.push_back( new KateViMotion( this, "[[", &KateViNormalMode::motionToPreviousBraceBlockStart ) );
02027   m_motions.push_back( new KateViMotion( this, "]]", &KateViNormalMode::motionToNextBraceBlockStart ) );
02028   m_motions.push_back( new KateViMotion( this, "[]", &KateViNormalMode::motionToPreviousBraceBlockEnd ) );
02029   m_motions.push_back( new KateViMotion( this, "][", &KateViNormalMode::motionToNextBraceBlockEnd ) );
02030 
02031   // text objects
02032   m_motions.push_back( new KateViMotion( this, "iw", &KateViNormalMode::textObjectInnerWord ) );
02033   m_motions.push_back( new KateViMotion( this, "aw", &KateViNormalMode::textObjectAWord ) );
02034   m_motions.push_back( new KateViMotion( this, "i\"", &KateViNormalMode::textObjectInnerQuoteDouble ) );
02035   m_motions.push_back( new KateViMotion( this, "a\"", &KateViNormalMode::textObjectAQuoteDouble ) );
02036   m_motions.push_back( new KateViMotion( this, "i'", &KateViNormalMode::textObjectInnerQuoteSingle ) );
02037   m_motions.push_back( new KateViMotion( this, "a'", &KateViNormalMode::textObjectAQuoteSingle ) );
02038   m_motions.push_back( new KateViMotion( this, "i[()]", &KateViNormalMode::textObjectInnerParen, REGEX_PATTERN ) );
02039   m_motions.push_back( new KateViMotion( this, "a[()]", &KateViNormalMode::textObjectAParen, REGEX_PATTERN ) );
02040   m_motions.push_back( new KateViMotion( this, "i[\\[\\]]", &KateViNormalMode::textObjectInnerBracket, REGEX_PATTERN ) );
02041   m_motions.push_back( new KateViMotion( this, "a[\\[\\]]", &KateViNormalMode::textObjectABracket, REGEX_PATTERN ) );
02042 }
02043 
02044 QRegExp KateViNormalMode::generateMatchingItemRegex()
02045 {
02046   QString pattern("\\[|\\]|\\{|\\}|\\(|\\)|");
02047   QList<QString> keys = m_matchingItems.keys();
02048 
02049   for ( int i = 0; i < keys.size(); i++ ) {
02050     QString s = m_matchingItems[ keys[ i ] ];
02051     s = s.replace( QRegExp( "^-" ), QChar() );
02052     s = s.replace( QRegExp( "\\*" ), "\\*" );
02053     s = s.replace( QRegExp( "\\+" ), "\\+" );
02054     s = s.replace( QRegExp( "\\[" ), "\\[" );
02055     s = s.replace( QRegExp( "\\]" ), "\\]" );
02056     s = s.replace( QRegExp( "\\(" ), "\\(" );
02057     s = s.replace( QRegExp( "\\)" ), "\\)" );
02058     s = s.replace( QRegExp( "\\{" ), "\\{" );
02059     s = s.replace( QRegExp( "\\}" ), "\\}" );
02060 
02061     pattern.append( s );
02062 
02063     if ( i != keys.size()-1 ) {
02064       pattern.append( "|" );
02065     }
02066   }
02067 
02068   return QRegExp( pattern );
02069 }

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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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