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

Kate

  • sources
  • kde-4.12
  • applications
  • kate
  • part
  • vimode
katevimodebase.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries and the Kate part.
2  *
3  * Copyright (C) 2008 - 2012 Erlend Hamberg <ehamberg@gmail.com>
4  * Copyright (C) 2009 Paul Gideon Dann <pdgiddie@gmail.com>
5  * Copyright (C) 2011 Svyatoslav Kuzmich <svatoslav1@gmail.com>
6  * Copyright (C) 2012 - 2013 Simon St James <kdedevel@etotheipiplusone.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB. If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #include "katevimodebase.h"
25 #include "katevirange.h"
26 #include "kateglobal.h"
27 #include "kateviglobal.h"
28 #include "katevivisualmode.h"
29 #include "katevinormalmode.h"
30 #include "katevireplacemode.h"
31 #include "kateviinputmodemanager.h"
32 
33 #include <QString>
34 #include <QRegExp>
35 #include "kateconfig.h"
36 #include "katedocument.h"
37 #include "kateviewinternal.h"
38 #include <ktexteditor/view.h>
39 #include "katerenderer.h"
40 
41 using KTextEditor::Cursor;
42 using KTextEditor::Range;
43 
44 // TODO: the "previous word/WORD [end]" methods should be optimized. now they're being called in a
45 // loop and all calculations done up to finding a match are trown away when called with a count > 1
46 // because they will simply be called again from the last found position.
47 // They should take the count as a parameter and collect the positions in a QList, then return
48 // element (count - 1)
49 
51 // HELPER METHODS
53 
54 void KateViModeBase::yankToClipBoard(QChar chosen_register, QString text)
55 {
56  if ((chosen_register == '0' || chosen_register == '-') && text.length() > 1) { //only yank to the clipboard if no register was specified and textlength > 1
57  KateGlobal::self()->copyToClipboard(text);
58  }
59 }
60 
61 bool KateViModeBase::deleteRange( KateViRange &r, OperationMode mode, bool addToRegister)
62 {
63  r.normalize();
64  bool res = false;
65  QString removedText = getRange( r, mode );
66 
67  if ( mode == LineWise ) {
68  doc()->editStart();
69  for ( int i = 0; i < r.endLine-r.startLine+1; i++ ) {
70  res = doc()->removeLine( r.startLine );
71  }
72  doc()->editEnd();
73  } else {
74  res = doc()->removeText( Range( r.startLine, r.startColumn, r.endLine, r.endColumn), mode == Block );
75  }
76 
77  QChar chosenRegister = getChosenRegister( '0' );
78  if ( addToRegister ) {
79  if ( r.startLine == r.endLine ) {
80  chosenRegister = getChosenRegister( '-' );
81  fillRegister( chosenRegister , removedText, mode );
82  } else {
83  fillRegister(chosenRegister, removedText, mode );
84  }
85  }
86  yankToClipBoard(chosenRegister, removedText);
87 
88  return res;
89 }
90 
91 const QString KateViModeBase::getRange( KateViRange &r, OperationMode mode) const
92 {
93  r.normalize();
94  QString s;
95 
96  if ( mode == LineWise ) {
97  r.startColumn = 0;
98  r.endColumn = getLine( r.endLine ).length();
99  }
100 
101  if ( r.motionType == ViMotion::InclusiveMotion ) {
102  r.endColumn++;
103  }
104 
105  Range range( r.startLine, r.startColumn, r.endLine, r.endColumn);
106 
107  if ( mode == LineWise ) {
108  s = doc()->textLines( range ).join( QChar( '\n' ) );
109  s.append( QChar( '\n' ) );
110  } else if ( mode == Block ) {
111  s = doc()->text( range, true );
112  } else {
113  s = doc()->text( range );
114  }
115 
116  return s;
117 }
118 
119 const QString KateViModeBase::getLine( int lineNumber ) const
120 {
121  QString line;
122 
123  if ( lineNumber == -1 ) {
124  Cursor cursor ( m_view->cursorPosition() );
125  line = m_view->currentTextLine();
126  } else {
127  line = doc()->line( lineNumber );
128  }
129 
130  return line;
131 }
132 
133 const QChar KateViModeBase::getCharUnderCursor() const
134 {
135  Cursor c( m_view->cursorPosition() );
136 
137  QString line = getLine( c.line() );
138 
139  if ( line.length() == 0 && c.column() >= line.length() ) {
140  return QChar::Null;
141  }
142 
143  return line.at( c.column() );
144 }
145 
146 const QString KateViModeBase::getWordUnderCursor() const
147 {
148 
149  return doc()->text( getWordRangeUnderCursor() );
150 }
151 
152 const Range KateViModeBase::getWordRangeUnderCursor() const
153 {
154  Cursor c( m_view->cursorPosition() );
155 
156  // find first character that is a “word letter” and start the search there
157  QChar ch = doc()->character( c );
158  int i = 0;
159  while ( !ch.isLetterOrNumber() && ! ch.isMark() && ch != '_'
160  && m_extraWordCharacters.indexOf( ch) == -1 ) {
161 
162  // advance cursor one position
163  c.setColumn( c.column()+1 );
164  if ( c.column() > doc()->lineLength( c.line() ) ) {
165  c.setColumn(0);
166  c.setLine( c.line()+1 );
167  if (c.line() == doc()->lines())
168  {
169  return Range::invalid();
170  }
171  }
172 
173  ch = doc()->character( c );
174  i++; // count characters that were advanced so we know where to start the search
175  }
176 
177  // move cursor the word (if cursor was placed on e.g. a paren, this will move
178  // it to the right
179  updateCursor( c );
180 
181  Cursor c1 = findPrevWordStart( c.line(), c.column()+1+i, true );
182  Cursor c2 = findWordEnd( c1.line(), c1.column()+i-1, true );
183  c2.setColumn( c2.column()+1 );
184 
185  return Range(c1, c2);
186 }
187 
188 Range KateViModeBase::findPattern(const QString& pattern, bool backwards, bool caseSensitive, const Cursor& startFrom, int count) const
189 {
190  Cursor searchBegin = startFrom;
191  KTextEditor::Search::SearchOptions flags = KTextEditor::Search::Regex;
192 
193  if (count == -1)
194  {
195  count = getCount();
196  }
197 
198  if ( backwards ) {
199  flags |= KTextEditor::Search::Backwards;
200  }
201  if (!caseSensitive)
202  {
203  flags |= KTextEditor::Search::CaseInsensitive;
204  }
205  Range finalMatch;
206  for (int i = 0; i < count; i++)
207  {
208  if (!backwards)
209  {
210  const KTextEditor::Range matchRange = m_view->doc()->searchText(KTextEditor::Range(Cursor(searchBegin.line(), searchBegin.column() + 1), m_view->doc()->documentEnd()), pattern, flags).first();
211 
212  if (matchRange.isValid())
213  {
214  finalMatch = matchRange;
215  }
216  else
217  {
218  // Wrap around.
219  const KTextEditor::Range wrappedMatchRange = m_view->doc()->searchText(KTextEditor::Range(m_view->doc()->documentRange().start(), m_view->doc()->documentEnd()), pattern, flags).first();
220  if (wrappedMatchRange.isValid())
221  {
222  finalMatch = wrappedMatchRange;
223  }
224  else
225  {
226  return Range::invalid();
227  }
228  }
229  }
230  else
231  {
232  // Ok - this is trickier: we can't search in the range from doc start to searchBegin, because
233  // the match might extend *beyond* searchBegin.
234  // We could search through the entire document and then filter out only those matches that are
235  // after searchBegin, but it's more efficient to instead search from the start of the
236  // document until the beginning of the line after searchBegin, and then filter.
237  // Unfortunately, searchText doesn't necessarily turn up all matches (just the first one, sometimes)
238  // so we must repeatedly search in such a way that the previous match isn't found, until we either
239  // find no matches at all, or the first match that is before searchBegin.
240  Cursor newSearchBegin = Cursor(searchBegin.line(), m_view->doc()->lineLength(searchBegin.line()));
241  Range bestMatch = Range::invalid();
242  while (true)
243  {
244  QVector<Range> matchesUnfiltered = m_view->doc()->searchText(Range(newSearchBegin, m_view->doc()->documentRange().start()), pattern, flags);
245  kDebug(13070) << "matchesUnfiltered: " << matchesUnfiltered << " searchBegin: " << newSearchBegin;
246 
247  if (matchesUnfiltered.size() == 1 && !matchesUnfiltered.first().isValid())
248  {
249  break;
250  }
251 
252  // After sorting, the last element in matchesUnfiltered is the last match position.
253  qSort(matchesUnfiltered);
254 
255  QVector<Range> filteredMatches;
256  foreach(Range unfilteredMatch, matchesUnfiltered)
257  {
258  if (unfilteredMatch.start() < searchBegin)
259  {
260  filteredMatches.append(unfilteredMatch);
261  }
262  }
263  if (!filteredMatches.isEmpty())
264  {
265  // Want the latest matching range that is before searchBegin.
266  bestMatch = filteredMatches.last();
267  break;
268  }
269 
270  // We found some unfiltered matches, but none were suitable. In case matchesUnfiltered wasn't
271  // all matching elements, search again, starting from before the earliest matching range.
272  if (filteredMatches.isEmpty())
273  {
274  newSearchBegin = matchesUnfiltered.first().start();
275  }
276  }
277 
278  Range matchRange = bestMatch;
279 
280  if (matchRange.isValid())
281  {
282  finalMatch = matchRange;
283  }
284  else
285  {
286  const KTextEditor::Range wrappedMatchRange = m_view->doc()->searchText(KTextEditor::Range(m_view->doc()->documentEnd(), m_view->doc()->documentRange().start()), pattern, flags).first();
287 
288 
289  if (wrappedMatchRange.isValid())
290  {
291  finalMatch = wrappedMatchRange;
292  }
293  else
294  {
295  return Range::invalid();
296  }
297  }
298  }
299  searchBegin = finalMatch.start();
300  }
301  return finalMatch;
302 }
303 
304 KateViRange KateViModeBase::findPatternForMotion( const QString& pattern, bool backwards, bool caseSensitive, const Cursor& startFrom, int count ) const
305 {
306  kDebug( 13070 ) << "searching for pattern \"" << pattern << "\", backwards = " << backwards
307  << ", caseSensitive = " << caseSensitive << ", count = " << count;
308  if ( pattern.isEmpty() ) {
309  return KateViRange();
310  }
311 
312  Range match = findPattern(pattern, backwards, caseSensitive, startFrom, count);
313 
314  return KateViRange( match.start().line(), match.start().column(), match.end().line(), match.end().column(), ViMotion::ExclusiveMotion );
315 }
316 
317 Cursor KateViModeBase::findNextWordStart( int fromLine, int fromColumn, bool onlyCurrentLine ) const
318 {
319  QString line = getLine( fromLine );
320 
321  // the start of word pattern need to take m_extraWordCharacters into account if defined
322  QString startOfWordPattern("\\b(\\w");
323  if ( m_extraWordCharacters.length() > 0 ) {
324  startOfWordPattern.append( QLatin1String( "|[" )+m_extraWordCharacters+']' );
325  }
326  startOfWordPattern.append( ')' );
327 
328  QRegExp startOfWord( startOfWordPattern ); // start of a word
329  QRegExp nonSpaceAfterSpace( "\\s\\S" ); // non-space right after space
330  QRegExp nonWordAfterWord( "\\b(?!\\s)\\W" ); // word-boundary followed by a non-word which is not a space
331 
332  int l = fromLine;
333  int c = fromColumn;
334 
335  bool found = false;
336 
337  while ( !found ) {
338  int c1 = startOfWord.indexIn( line, c + 1 );
339  int c2 = nonSpaceAfterSpace.indexIn( line, c );
340  int c3 = nonWordAfterWord.indexIn( line, c + 1 );
341 
342  if ( c1 == -1 && c2 == -1 && c3 == -1 ) {
343  if ( onlyCurrentLine ) {
344  return Cursor::invalid();
345  } else if ( l >= doc()->lines()-1 ) {
346  c = qMax(line.length()-1, 0);
347  return Cursor::invalid();
348  } else {
349  c = 0;
350  l++;
351 
352  line = getLine( l );
353 
354  if ( line.length() == 0 || !line.at( c ).isSpace() ) {
355  found = true;
356  }
357 
358  continue;
359  }
360  }
361 
362  c2++; // the second regexp will match one character *before* the character we want to go to
363 
364  if ( c1 <= 0 )
365  c1 = line.length()-1;
366  if ( c2 <= 0 )
367  c2 = line.length()-1;
368  if ( c3 <= 0 )
369  c3 = line.length()-1;
370 
371  c = qMin( c1, qMin( c2, c3 ) );
372 
373  found = true;
374  }
375 
376  return Cursor( l, c );
377 }
378 
379 Cursor KateViModeBase::findNextWORDStart( int fromLine, int fromColumn, bool onlyCurrentLine ) const
380 {
381  Cursor cursor ( m_view->cursorPosition() );
382  QString line = getLine();
383  KateViRange r( cursor.line(), cursor.column(), ViMotion::ExclusiveMotion );
384 
385  int l = fromLine;
386  int c = fromColumn;
387 
388  bool found = false;
389  QRegExp startOfWORD("\\s\\S");
390 
391  while ( !found ) {
392  c = startOfWORD.indexIn( line, c );
393 
394  if ( c == -1 ) {
395  if ( onlyCurrentLine ) {
396  return Cursor( l, c );
397  } else if ( l >= doc()->lines()-1 ) {
398  c = line.length()-1;
399  break;
400  } else {
401  c = 0;
402  l++;
403 
404  line = getLine( l );
405 
406  if ( line.length() == 0 || !line.at( c ).isSpace() ) {
407  found = true;
408  }
409 
410  continue;
411  }
412  } else {
413  c++;
414  found = true;
415  }
416  }
417 
418  return Cursor( l, c );
419 }
420 
421 Cursor KateViModeBase::findPrevWordEnd( int fromLine, int fromColumn, bool onlyCurrentLine ) const
422 {
423  QString line = getLine( fromLine );
424 
425  QString endOfWordPattern = "\\S\\s|\\S$|\\w\\W|\\S\\b|^$";
426 
427  if ( m_extraWordCharacters.length() > 0 ) {
428  endOfWordPattern.append( "|["+m_extraWordCharacters+"][^" +m_extraWordCharacters+']' );
429  }
430 
431  QRegExp endOfWord( endOfWordPattern );
432 
433  int l = fromLine;
434  int c = fromColumn;
435 
436  bool found = false;
437 
438  while ( !found ) {
439  int c1 = endOfWord.lastIndexIn( line, c-1 );
440 
441  if ( c1 != -1 && c-1 != -1 ) {
442  found = true;
443  c = c1;
444  } else {
445  if ( onlyCurrentLine ) {
446  return Cursor::invalid();
447  } else if ( l > 0 ) {
448  line = getLine( --l );
449  c = line.length();
450 
451  continue;
452  } else {
453  return Cursor::invalid();
454  }
455  }
456  }
457 
458  return Cursor( l, c );
459 }
460 
461 Cursor KateViModeBase::findPrevWORDEnd( int fromLine, int fromColumn, bool onlyCurrentLine ) const
462 {
463  QString line = getLine( fromLine );
464 
465  QRegExp endOfWORDPattern( "\\S\\s|\\S$|^$" );
466 
467  QRegExp endOfWORD( endOfWORDPattern );
468 
469  int l = fromLine;
470  int c = fromColumn;
471 
472  bool found = false;
473 
474  while ( !found ) {
475  int c1 = endOfWORD.lastIndexIn( line, c-1 );
476 
477  if ( c1 != -1 && c-1 != -1 ) {
478  found = true;
479  c = c1;
480  } else {
481  if ( onlyCurrentLine ) {
482  return Cursor::invalid();
483  } else if ( l > 0 ) {
484  line = getLine( --l );
485  c = line.length();
486 
487  continue;
488  } else {
489  c = 0;
490  return Cursor::invalid();
491  }
492  }
493  }
494 
495  return Cursor( l, c );
496 }
497 
498 Cursor KateViModeBase::findPrevWordStart( int fromLine, int fromColumn, bool onlyCurrentLine ) const
499 {
500  QString line = getLine( fromLine );
501 
502  // the start of word pattern need to take m_extraWordCharacters into account if defined
503  QString startOfWordPattern("\\b(\\w");
504  if ( m_extraWordCharacters.length() > 0 ) {
505  startOfWordPattern.append( QLatin1String( "|[" )+m_extraWordCharacters+']' );
506  }
507  startOfWordPattern.append( ')' );
508 
509  QRegExp startOfWord( startOfWordPattern ); // start of a word
510  QRegExp nonSpaceAfterSpace( "\\s\\S" ); // non-space right after space
511  QRegExp nonWordAfterWord( "\\b(?!\\s)\\W" ); // word-boundary followed by a non-word which is not a space
512  QRegExp startOfLine( "^\\S" ); // non-space at start of line
513 
514  int l = fromLine;
515  int c = fromColumn;
516 
517  bool found = false;
518 
519  while ( !found ) {
520  int c1 = startOfWord.lastIndexIn( line, -line.length()+c-1 );
521  int c2 = nonSpaceAfterSpace.lastIndexIn( line, -line.length()+c-2 );
522  int c3 = nonWordAfterWord.lastIndexIn( line, -line.length()+c-1 );
523  int c4 = startOfLine.lastIndexIn( line, -line.length()+c-1 );
524 
525  if ( c1 == -1 && c2 == -1 && c3 == -1 && c4 == -1 ) {
526  if ( onlyCurrentLine ) {
527  return Cursor::invalid();
528  } else if ( l <= 0 ) {
529  return Cursor::invalid();
530  } else {
531  line = getLine( --l );
532  c = line.length();
533 
534  if ( line.length() == 0 ) {
535  c = 0;
536  found = true;
537  }
538 
539  continue;
540  }
541  }
542 
543  c2++; // the second regexp will match one character *before* the character we want to go to
544 
545  if ( c1 <= 0 )
546  c1 = 0;
547  if ( c2 <= 0 )
548  c2 = 0;
549  if ( c3 <= 0 )
550  c3 = 0;
551  if ( c4 <= 0 )
552  c4 = 0;
553 
554  c = qMax( c1, qMax( c2, qMax( c3, c4 ) ) );
555 
556  found = true;
557  }
558 
559  return Cursor( l, c );
560 }
561 
562 Cursor KateViModeBase::findPrevWORDStart( int fromLine, int fromColumn, bool onlyCurrentLine ) const
563 {
564  QString line = getLine( fromLine );
565 
566  QRegExp startOfWORD("\\s\\S");
567  QRegExp startOfLineWORD("^\\S");
568 
569  int l = fromLine;
570  int c = fromColumn;
571 
572  bool found = false;
573 
574  while ( !found ) {
575  int c1 = startOfWORD.lastIndexIn( line, -line.length()+c-2 );
576  int c2 = startOfLineWORD.lastIndexIn( line, -line.length()+c-1 );
577 
578  if ( c1 == -1 && c2 == -1 ) {
579  if ( onlyCurrentLine ) {
580  return Cursor::invalid();
581  } else if ( l <= 0 ) {
582  return Cursor::invalid();
583  } else {
584  line = getLine( --l );
585  c = line.length();
586 
587  if ( line.length() == 0 ) {
588  c = 0;
589  found = true;
590  }
591 
592  continue;
593  }
594  }
595 
596  c1++; // the startOfWORD pattern matches one character before the word
597 
598  c = qMax( c1, c2 );
599 
600  if ( c <= 0 )
601  c = 0;
602 
603  found = true;
604  }
605 
606  return Cursor( l, c );
607 }
608 
609 Cursor KateViModeBase::findWordEnd( int fromLine, int fromColumn, bool onlyCurrentLine ) const
610 {
611  QString line = getLine( fromLine );
612 
613  QString endOfWordPattern = "\\S\\s|\\S$|\\w\\W|\\S\\b";
614 
615  if ( m_extraWordCharacters.length() > 0 ) {
616  endOfWordPattern.append( "|["+m_extraWordCharacters+"][^" +m_extraWordCharacters+']' );
617  }
618 
619  QRegExp endOfWORD( endOfWordPattern );
620 
621  int l = fromLine;
622  int c = fromColumn;
623 
624  bool found = false;
625 
626  while ( !found ) {
627  int c1 = endOfWORD.indexIn( line, c+1 );
628 
629  if ( c1 != -1 ) {
630  found = true;
631  c = c1;
632  } else {
633  if ( onlyCurrentLine ) {
634  return Cursor::invalid();
635  } else if ( l >= doc()->lines()-1 ) {
636  c = line.length()-1;
637  return Cursor::invalid();
638  } else {
639  c = -1;
640  line = getLine( ++l );
641 
642  continue;
643  }
644  }
645  }
646 
647  return Cursor( l, c );
648 }
649 
650 Cursor KateViModeBase::findWORDEnd( int fromLine, int fromColumn, bool onlyCurrentLine ) const
651 {
652  QString line = getLine( fromLine );
653 
654  QRegExp endOfWORD( "\\S\\s|\\S$" );
655 
656  int l = fromLine;
657  int c = fromColumn;
658 
659  bool found = false;
660 
661  while ( !found ) {
662  int c1 = endOfWORD.indexIn( line, c+1 );
663 
664  if ( c1 != -1 ) {
665  found = true;
666  c = c1;
667  } else {
668  if ( onlyCurrentLine ) {
669  return Cursor::invalid();
670  } else if ( l >= doc()->lines()-1 ) {
671  c = line.length()-1;
672  return Cursor::invalid();
673  } else {
674  c = -1;
675  line = getLine( ++l );
676 
677  continue;
678  }
679  }
680  }
681 
682  return Cursor( l, c );
683 }
684 
685 KateViRange innerRange(KateViRange range, bool inner) {
686  KateViRange r = range;
687 
688  if (inner) {
689  const int columnDistance = qAbs(r.startColumn - r.endColumn);
690  if ((r.startLine == r.endLine) && columnDistance == 1 )
691  {
692  // Start and end are right next to each other; there is nothing inside them.
693  return KateViRange::invalid();
694  }
695  r.startColumn++;
696  r.endColumn--;
697  }
698 
699  return r;
700 }
701 
702 KateViRange KateViModeBase::findSurroundingQuotes( const QChar &c, bool inner ) const {
703  Cursor cursor(m_view->cursorPosition());
704  KateViRange r;
705  r.startLine = cursor.line();
706  r.endLine = cursor.line();
707 
708  QString line = doc()->line(cursor.line());
709 
710 
711  // If cursor on the quote we should shoose the best direction.
712  if (line.at(cursor.column()) == c) {
713 
714  int attribute = m_view->doc()->kateTextLine(cursor.line())->attribute(cursor.column());
715 
716  // If at the beginning of the line - then we might search the end.
717  if ( doc()->kateTextLine(cursor.line())->attribute(cursor.column() + 1) == attribute &&
718  doc()->kateTextLine(cursor.line())->attribute(cursor.column() - 1) != attribute ) {
719  r.startColumn = cursor.column();
720  r.endColumn = line.indexOf( c, cursor.column() + 1 );
721 
722  return innerRange(r, inner);
723  }
724 
725  // If at the end of the line - then we might search the beginning.
726  if ( doc()->kateTextLine(cursor.line())->attribute(cursor.column() + 1) != attribute &&
727  doc()->kateTextLine(cursor.line())->attribute(cursor.column() - 1) == attribute ) {
728 
729  r.startColumn =line.lastIndexOf( c, cursor.column() - 1 ) ;
730  r.endColumn = cursor.column();
731 
732  return innerRange(r, inner);
733 
734  }
735  // Try to search the quote to right
736  int c1 = line.indexOf(c, cursor.column() + 1);
737  if ( c1 != -1 ) {
738  r.startColumn = cursor.column();
739  r.endColumn = c1;
740 
741  return innerRange(r, inner);
742  }
743 
744  // Try to search the quote to left
745  int c2 = line.lastIndexOf(c, cursor.column() - 1);
746  if ( c2 != -1 ) {
747  r.startColumn = c2;
748  r.endColumn = cursor.column();
749 
750  return innerRange(r, inner);
751  }
752 
753  // Nothing found - give up :)
754  return KateViRange::invalid();
755  }
756 
757 
758  r.startColumn = line.lastIndexOf( c, cursor.column() );
759  r.endColumn = line.indexOf( c, cursor.column() );
760 
761  if ( r.startColumn == -1 || r.endColumn == -1 || r.startColumn > r.endColumn ) {
762  return KateViRange::invalid();
763  }
764 
765  return innerRange(r, inner);
766 }
767 
768 
769 KateViRange KateViModeBase::findSurroundingBrackets( const QChar &c1,
770  const QChar &c2,
771  bool inner,
772  const QChar &nested1,
773  const QChar &nested2) const
774 {
775 
776  Cursor cursor( m_view->cursorPosition() );
777 
778  KateViRange r( cursor.line(), cursor.column(), ViMotion::InclusiveMotion );
779 
780  // Chars should not differs. For equal chars use findSurroundingQuotes.
781  Q_ASSERT( c1 != c2 );
782 
783  QStack<QChar> stack;
784  int column = cursor.column();
785  int line = cursor.line();
786  bool should_break = false;
787 
788  // Going through the text and pushing respectively brackets to the stack.
789  // Then pop it out if the stack head is the bracket under cursor.
790 
791  if (column < m_view->doc()->line(line).size() && m_view->doc()->line(line).at(column) == c2) {
792  r.endLine = line;
793  r.endColumn = column;
794  } else {
795 
796  if ( column < m_view->doc()->line(line).size() && m_view->doc()->line(line).at(column) == c1 )
797  column++;
798 
799  stack.push(c2);
800  for (; line < m_view->doc()->lines() && !should_break; line++ ) {
801  for (;column < m_view->doc()->line( line ).size(); column++ ) {
802  QChar next_char = stack.pop();
803 
804  if (next_char != m_view->doc()->line(line).at(column))
805  stack.push(next_char);
806 
807  if ( stack.isEmpty() ) {
808  should_break = true;
809  break;
810  }
811 
812  if ( m_view->doc()->line(line).at(column) == nested1 )
813  stack.push(nested2);
814  }
815  if (should_break)
816  break;
817 
818  column = 0;
819  }
820 
821  if (!should_break) {
822  return KateViRange::invalid();
823  }
824 
825  r.endColumn = column;
826  r.endLine = line;
827 
828  }
829 
830  // The same algorythm but going from the left to right.
831 
832  line = cursor.line();
833  column = cursor.column();
834 
835  if (column < m_view->doc()->line(line).size() && m_view->doc()->line(line).at(column) == c1) {
836  r.startLine = line;
837  r.startColumn = column;
838  } else {
839  if (column < m_view->doc()->line(line).size() && m_view->doc()->line(line).at(column) == c2) {
840  column--;
841  }
842 
843  stack.clear();
844  stack.push(c1);
845 
846  should_break = false;
847  for (; line >= 0 && !should_break; line-- ) {
848  for (;column >= 0 && column < m_view->doc()->line(line).size(); column-- ) {
849  QChar next_char = stack.pop();
850 
851  if (next_char != m_view->doc()->line(line).at(column)) {
852  stack.push(next_char);
853  }
854 
855  if ( stack.isEmpty() ) {
856  should_break = true;
857  break;
858  }
859 
860  if ( m_view->doc()->line(line).at(column) == nested2 )
861  stack.push(nested1);
862  }
863 
864  if (should_break)
865  break;
866 
867  column = m_view->doc()->line(line - 1).size() - 1;
868  }
869 
870  if (!should_break) {
871  return KateViRange::invalid();
872  }
873 
874  r.startColumn = column;
875  r.startLine = line;
876 
877  }
878 
879  return innerRange(r, inner);
880 }
881 
882 KateViRange KateViModeBase::findSurrounding( const QRegExp &c1, const QRegExp &c2, bool inner ) const
883 {
884  Cursor cursor( m_view->cursorPosition() );
885  QString line = getLine();
886 
887  int col1 = line.lastIndexOf( c1, cursor.column() );
888  int col2 = line.indexOf( c2, cursor.column() );
889 
890  KateViRange r( cursor.line(), col1, cursor.line(), col2, ViMotion::InclusiveMotion );
891 
892  if ( col1 == -1 || col2 == -1 || col1 > col2 ) {
893  return KateViRange::invalid();
894  }
895 
896  if ( inner ) {
897  r.startColumn++;
898  r.endColumn--;
899  }
900 
901  return r;
902 }
903 
904 int KateViModeBase::findLineStartingWitchChar( const QChar &c, unsigned int count, bool forward ) const
905 {
906  int line = m_view->cursorPosition().line();
907  int lines = doc()->lines();
908  unsigned int hits = 0;
909 
910  if ( forward ) {
911  line++;
912  } else {
913  line--;
914  }
915 
916  while ( line < lines && line >= 0 && hits < count ) {
917  QString l = getLine( line );
918  if ( l.length() > 0 && l.at( 0 ) == c ) {
919  hits++;
920  }
921  if ( hits != count ) {
922  if ( forward ) {
923  line++;
924  } else {
925  line--;
926  }
927  }
928  }
929 
930  if ( hits == getCount() ) {
931  return line;
932  }
933 
934  return -1;
935 }
936 
937 void KateViModeBase::updateCursor( const Cursor &c ) const
938 {
939  m_viewInternal->updateCursor( c );
940 }
941 
945 QChar KateViModeBase::getChosenRegister( const QChar &defaultReg ) const
946 {
947  QChar reg = ( m_register != QChar::Null ) ? m_register : defaultReg;
948 
949  return reg;
950 }
951 
952 QString KateViModeBase::getRegisterContent( const QChar &reg )
953 {
954  QString r = KateGlobal::self()->viInputModeGlobal()->getRegisterContent( reg );
955 
956  if ( r.isNull() ) {
957  error( i18n( "Nothing in register %1", reg ));
958  }
959 
960  return r;
961 }
962 
963 OperationMode KateViModeBase::getRegisterFlag( const QChar &reg ) const
964 {
965  return KateGlobal::self()->viInputModeGlobal()->getRegisterFlag( reg );
966 }
967 
968 void KateViModeBase::fillRegister( const QChar &reg, const QString &text, OperationMode flag )
969 {
970  KateGlobal::self()->viInputModeGlobal()->fillRegister( reg, text, flag );
971 }
972 
973 
974 void KateViModeBase::addJump(KTextEditor::Cursor cursor)
975 {
976  m_viInputModeManager->addJump(cursor);
977 }
978 
979 KTextEditor::Cursor KateViModeBase::getNextJump(KTextEditor::Cursor cursor)
980 {
981  return m_viInputModeManager->getNextJump(cursor);
982 }
983 
984 KTextEditor::Cursor KateViModeBase::getPrevJump(KTextEditor::Cursor cursor)
985 {
986  return m_viInputModeManager->getPrevJump(cursor);
987 }
988 
989 KateViRange KateViModeBase::goLineDown()
990 {
991  return goLineUpDown( getCount() );
992 }
993 
994 KateViRange KateViModeBase::goLineUp()
995 {
996  return goLineUpDown( -getCount() );
997 }
998 
1003 KateViRange KateViModeBase::goLineUpDown( int lines )
1004 {
1005  Cursor c( m_view->cursorPosition() );
1006  KateViRange r( c.line(), c.column(), ViMotion::InclusiveMotion );
1007  int tabstop = doc()->config()->tabWidth();
1008 
1009  // if in an empty document, just return
1010  if ( lines == 0 ) {
1011  return r;
1012  }
1013 
1014  r.endLine += lines;
1015 
1016  // limit end line to be from line 0 through the last line
1017  if ( r.endLine < 0 ) {
1018  r.endLine = 0;
1019  } else if ( r.endLine > doc()->lines()-1 ) {
1020  r.endLine = doc()->lines()-1;
1021  }
1022 
1023  Kate::TextLine startLine = doc()->plainKateTextLine( c.line() );
1024  Kate::TextLine endLine = doc()->plainKateTextLine( r.endLine );
1025 
1026  int endLineLen = doc()->lineLength( r.endLine )-1;
1027 
1028  if ( endLineLen < 0 ) {
1029  endLineLen = 0;
1030  }
1031 
1032  int endLineLenVirt = endLine->toVirtualColumn(endLineLen, tabstop);
1033  int virtColumnStart = startLine->toVirtualColumn(c.column(), tabstop);
1034 
1035  // if sticky column isn't set, set end column and set sticky column to its virtual column
1036  if ( m_stickyColumn == -1 ) {
1037  r.endColumn = endLine->fromVirtualColumn( virtColumnStart, tabstop );
1038  m_stickyColumn = virtColumnStart;
1039  } else {
1040  // sticky is set - set end column to its value
1041  r.endColumn = endLine->fromVirtualColumn( m_stickyColumn, tabstop );
1042  }
1043 
1044  // make sure end column won't be after the last column of a line
1045  if ( r.endColumn > endLineLen ) {
1046  r.endColumn = endLineLen;
1047  }
1048 
1049  // if we move to a line shorter than the current column, go to its end
1050  if ( virtColumnStart > endLineLenVirt ) {
1051  r.endColumn = endLineLen;
1052  }
1053 
1054  return r;
1055 }
1056 
1057 KateViRange KateViModeBase::goVisualLineUpDown(int lines) {
1058 
1059  Cursor c( m_view->cursorPosition() );
1060  KateViRange r( c.line(), c.column(), ViMotion::InclusiveMotion );
1061  int tabstop = doc()->config()->tabWidth();
1062 
1063  if ( lines == 0 ) {
1064  // We're not moving anywhere.
1065  return r;
1066  }
1067 
1068  // Work out the real and visual line pair of the beginning of the visual line we'd end up
1069  // on by moving lines visual lines. We ignore the column, for now.
1070  int finishVisualLine = m_viewInternal->cache()->viewLine(m_view->cursorPosition());
1071  int finishRealLine = m_view->cursorPosition().line();
1072  int count = qAbs(lines);
1073  bool invalidPos = false;
1074  if (lines > 0)
1075  {
1076  // Find the beginning of the visual line "lines" visual lines down.
1077  while (count > 0)
1078  {
1079  finishVisualLine++;
1080  if (finishVisualLine >= m_viewInternal->cache()->line(finishRealLine)->viewLineCount())
1081  {
1082  finishRealLine++;
1083  finishVisualLine = 0;
1084  }
1085  if (finishRealLine >= doc()->lines())
1086  {
1087  invalidPos = true;
1088  break;
1089  }
1090  count--;
1091  }
1092  }
1093  else
1094  {
1095  // Find the beginning of the visual line "lines" visual lines up.
1096  while (count > 0)
1097  {
1098  finishVisualLine--;
1099  if (finishVisualLine < 0)
1100  {
1101  finishRealLine--;
1102  if (finishRealLine < 0)
1103  {
1104  invalidPos = true;
1105  break;
1106  }
1107  finishVisualLine = m_viewInternal->cache()->line(finishRealLine)->viewLineCount() - 1;
1108  }
1109  count--;
1110  }
1111  }
1112  if (invalidPos)
1113  {
1114  r.endLine = -1;
1115  r.endColumn = -1;
1116  return r;
1117  }
1118 
1119  // We know the final (real) line ...
1120  r.endLine = finishRealLine;
1121  // ... now work out the final (real) column.
1122 
1123  if ( m_stickyColumn == -1 || !m_lastMotionWasVisualLineUpOrDown) {
1124  // Compute new sticky column. It is a *visual* sticky column.
1125  int startVisualLine = m_viewInternal->cache()->viewLine(m_view->cursorPosition());
1126  int startRealLine = m_view->cursorPosition().line();
1127  const Kate::TextLine startLine = doc()->plainKateTextLine( c.line() );
1128  // Adjust for the fact that if the portion of the line before wrapping is indented,
1129  // the continuations are also "invisibly" (i.e. without any spaces in the text itself) indented.
1130  const bool isWrappedContinuation = (m_viewInternal->cache()->textLayout(startRealLine, startVisualLine).lineLayout().lineNumber() != 0);
1131  const int numInvisibleIndentChars = isWrappedContinuation ? startLine->toVirtualColumn(m_viewInternal->cache()->line(startRealLine)->textLine()->nextNonSpaceChar(0), tabstop) : 0;
1132 
1133  const int realLineStartColumn = m_viewInternal->cache()->textLayout(startRealLine, startVisualLine).startCol();
1134  const int lineStartVirtualColumn = startLine->toVirtualColumn( realLineStartColumn, tabstop );
1135  const int visualColumnNoInvisibleIndent = startLine->toVirtualColumn(c.column(), tabstop) - lineStartVirtualColumn;
1136  m_stickyColumn = visualColumnNoInvisibleIndent + numInvisibleIndentChars;
1137  Q_ASSERT(m_stickyColumn >= 0);
1138  }
1139 
1140  // The "real" (non-virtual) beginning of the current "line", which might be a wrapped continuation of a
1141  // "real" line.
1142  const int realLineStartColumn = m_viewInternal->cache()->textLayout(finishRealLine, finishVisualLine).startCol();
1143  const Kate::TextLine endLine = doc()->plainKateTextLine( r.endLine );
1144  // Adjust for the fact that if the portion of the line before wrapping is indented,
1145  // the continuations are also "invisibly" (i.e. without any spaces in the text itself) indented.
1146  const bool isWrappedContinuation = (m_viewInternal->cache()->textLayout(finishRealLine, finishVisualLine).lineLayout().lineNumber() != 0);
1147  const int numInvisibleIndentChars = isWrappedContinuation ? endLine->toVirtualColumn(m_viewInternal->cache()->line(finishRealLine)->textLine()->nextNonSpaceChar(0), tabstop) : 0;
1148  if (m_stickyColumn == (unsigned int)KateVi::EOL)
1149  {
1150  const int visualEndColumn = m_viewInternal->cache()->textLayout(finishRealLine, finishVisualLine).lineLayout().textLength() - 1;
1151  r.endColumn = endLine->fromVirtualColumn( visualEndColumn + realLineStartColumn - numInvisibleIndentChars, tabstop );
1152  }
1153  else
1154  {
1155  // Algorithm: find the "real" column corresponding to the start of the line. Offset from that
1156  // until the "visual" column is equal to the "visual" sticky column.
1157  int realOffsetToVisualStickyColumn = 0;
1158  const int lineStartVirtualColumn = endLine->toVirtualColumn( realLineStartColumn, tabstop );
1159  while (true)
1160  {
1161  const int visualColumn = endLine->toVirtualColumn( realLineStartColumn + realOffsetToVisualStickyColumn, tabstop ) - lineStartVirtualColumn + numInvisibleIndentChars;
1162  if (visualColumn >= m_stickyColumn)
1163  {
1164  break;
1165  }
1166  realOffsetToVisualStickyColumn++;
1167  }
1168  r.endColumn = realLineStartColumn + realOffsetToVisualStickyColumn;
1169  }
1170  m_currentMotionWasVisualLineUpOrDown = true;
1171 
1172  return r;
1173 }
1174 
1175 
1176 bool KateViModeBase::startNormalMode()
1177 {
1178  // store the key presses for this "insert mode session" so that it can be repeated with the
1179  // '.' command
1180  if (!m_viInputModeManager->isReplayingLastChange()) {
1181  m_viInputModeManager->storeLastChangeCommand();
1182  m_viInputModeManager->clearCurrentChangeLog();
1183  }
1184 
1185  m_viInputModeManager->viEnterNormalMode();
1186  m_view->doc()->setUndoMergeAllEdits(false);
1187  m_view->updateViModeBarMode();
1188 
1189  return true;
1190 }
1191 
1192 bool KateViModeBase::startInsertMode()
1193 {
1194  m_viInputModeManager->viEnterInsertMode();
1195  m_view->doc()->setUndoMergeAllEdits(true);
1196  m_view->updateViModeBarMode();
1197 
1198  return true;
1199 }
1200 
1201 bool KateViModeBase::startReplaceMode()
1202 {
1203  m_view->doc()->setUndoMergeAllEdits(true);
1204  m_viInputModeManager->viEnterReplaceMode();
1205  m_view->updateViModeBarMode();
1206 
1207  return true;
1208 }
1209 
1210 bool KateViModeBase::startVisualMode()
1211 {
1212  if ( m_view->getCurrentViMode() == VisualLineMode ) {
1213  m_viInputModeManager->getViVisualMode()->setVisualLine( false );
1214  m_viInputModeManager->changeViMode(VisualMode);
1215  } else if (m_view->getCurrentViMode() == VisualBlockMode ) {
1216  m_viInputModeManager->getViVisualMode()->setVisualBlock( false );
1217  m_viInputModeManager->changeViMode(VisualMode);
1218  } else {
1219  m_viInputModeManager->viEnterVisualMode();
1220  }
1221 
1222  m_view->updateViModeBarMode();
1223 
1224  return true;
1225 }
1226 
1227 bool KateViModeBase::startVisualBlockMode()
1228 {
1229  if ( m_view->getCurrentViMode() == VisualMode ) {
1230  m_viInputModeManager->getViVisualMode()->setVisualBlock( true );
1231  m_viInputModeManager->changeViMode(VisualBlockMode);
1232  } else {
1233  m_viInputModeManager->viEnterVisualMode( VisualBlockMode );
1234  }
1235 
1236  m_view->updateViModeBarMode();
1237 
1238  return true;
1239 }
1240 
1241 bool KateViModeBase::startVisualLineMode()
1242 {
1243  if ( m_view->getCurrentViMode() == VisualMode ) {
1244  m_viInputModeManager->getViVisualMode()->setVisualLine( true );
1245  m_viInputModeManager->changeViMode(VisualLineMode);
1246  } else {
1247  m_viInputModeManager->viEnterVisualMode( VisualLineMode );
1248  }
1249 
1250  m_view->updateViModeBarMode();
1251 
1252  return true;
1253 }
1254 
1255 void KateViModeBase::error( const QString &errorMsg )
1256 {
1257  delete m_infoMessage;
1258 
1259  // nop if no vi mode around
1260  if (!m_view->viInputMode())
1261  return;
1262 
1263  m_infoMessage = new KTextEditor::Message(errorMsg, KTextEditor::Message::Error);
1264  m_infoMessage->setPosition(KTextEditor::Message::BottomInView);
1265  m_infoMessage->setAutoHide(2000); // 2 seconds
1266  m_infoMessage->setView(m_view);
1267 
1268  m_view->doc()->postMessage(m_infoMessage);
1269 }
1270 
1271 void KateViModeBase::message( const QString &msg )
1272 {
1273  delete m_infoMessage;
1274 
1275  // nop if no vi mode around
1276  if (!m_view->viInputMode())
1277  return;
1278 
1279  m_infoMessage = new KTextEditor::Message(msg, KTextEditor::Message::Positive);
1280  m_infoMessage->setPosition(KTextEditor::Message::BottomInView);
1281  m_infoMessage->setAutoHide(2000); // 2 seconds
1282  m_infoMessage->setView(m_view);
1283 
1284  m_view->doc()->postMessage(m_infoMessage);
1285 }
1286 
1287 QString KateViModeBase::getVerbatimKeys() const
1288 {
1289  return m_keysVerbatim;
1290 }
1291 
1292 const QChar KateViModeBase::getCharAtVirtualColumn( QString &line, int virtualColumn,
1293  int tabWidth ) const
1294 {
1295  int column = 0;
1296  int tempCol = 0;
1297 
1298  // sanity check: if the line is empty, there are no chars
1299  if ( line.length() == 0 ) {
1300  return QChar::Null;
1301  }
1302 
1303  while ( tempCol < virtualColumn ) {
1304  if ( line.at( column ) == '\t' ) {
1305  tempCol += tabWidth - ( tempCol % tabWidth );
1306  } else {
1307  tempCol++;
1308  }
1309 
1310  if ( tempCol <= virtualColumn ) {
1311  column++;
1312 
1313  if ( column >= line.length() ) {
1314  return QChar::Null;
1315  }
1316  }
1317  }
1318 
1319  if ( line.length() > column )
1320  return line.at( column );
1321 
1322  return QChar::Null;
1323 }
1324 
1325 void KateViModeBase::addToNumberUnderCursor( int count )
1326 {
1327  Cursor c( m_view->cursorPosition() );
1328  QString line = getLine();
1329 
1330  if (line.isEmpty())
1331  {
1332  return;
1333  }
1334 
1335  int numberStartPos = -1;
1336  QString numberAsString;
1337  QRegExp numberRegex( "(0x)([0-9a-fA-F]+)|\\-?\\d+" );
1338  const int cursorColumn = c.column();
1339  const int currentLineLength = doc()->lineLength(c.line());
1340  const Cursor prevWordStart = findPrevWordStart(c.line(), cursorColumn);
1341  int wordStartPos = prevWordStart.column();
1342  if (prevWordStart.line() < c.line())
1343  {
1344  // The previous word starts on the previous line: ignore.
1345  wordStartPos = 0;
1346  }
1347  if (wordStartPos > 0 && line.at(wordStartPos - 1) == '-') wordStartPos--;
1348  for (int searchFromColumn = wordStartPos; searchFromColumn < currentLineLength; searchFromColumn++)
1349  {
1350  numberStartPos = numberRegex.indexIn( line, searchFromColumn );
1351 
1352  numberAsString = numberRegex.cap();
1353 
1354  if (numberStartPos + numberAsString.length() <= c.column())
1355  {
1356  // This number is before the cursor; keep on searching.
1357  numberStartPos = -1;
1358  }
1359  else
1360  {
1361  // This'll do!
1362  break;
1363  }
1364  }
1365 
1366  if (numberStartPos == -1)
1367  {
1368  // None found.
1369  return;
1370  }
1371 
1372  bool ok = false;
1373  int base = numberRegex.cap( 1 ).isEmpty() ? 10 : 16;
1374  if (base != 16 && numberAsString.startsWith("0") && numberAsString != "0")
1375  {
1376  numberAsString.toInt( &ok, 8 );
1377  if (ok)
1378  {
1379  // Octal.
1380  base = 8;
1381  }
1382  }
1383  const int originalNumber = numberAsString.toInt( &ok, base );
1384  QString withoutBase = numberAsString;
1385  if (base == 16)
1386  {
1387  withoutBase = numberRegex.cap(2);
1388  }
1389  else if (base == 8)
1390  {
1391  withoutBase = numberAsString.mid(1); // Strip off leading 0.
1392  }
1393 
1394  kDebug( 13070 ) << "base: " << base;
1395  kDebug( 13070 ) << "n: " << originalNumber;
1396 
1397  if ( !ok ) {
1398  // conversion to int failed. give up.
1399  return;
1400  }
1401 
1402  // increase/decrease number
1403  const int newNumber = originalNumber + count;
1404 
1405  // Create the new text string to be inserted. Prepend with “0x” if in base 16, and "0" if base 8.
1406  // For non-decimal numbers, try to keep the length of the number the same (including leading 0's).
1407  QString newNumberPadded = (base == 16 || base == 8) ? QString("%1").arg(newNumber, withoutBase.length(), base, QChar('0')) : QString("%1").arg(newNumber, 0, base);
1408  QString newNumberText = newNumberPadded;
1409  if (base == 16)
1410  {
1411  newNumberText = "0x" + newNumberText;
1412  }
1413  else if (base == 8)
1414  {
1415  newNumberText = "0" + newNumberText;
1416  }
1417 
1418  // Replace the old number string with the new.
1419  doc()->editStart();
1420  doc()->removeText( KTextEditor::Range( c.line(), numberStartPos , c.line(), numberStartPos+numberAsString.length() ) );
1421  doc()->insertText( KTextEditor::Cursor( c.line(), numberStartPos ), newNumberText );
1422  doc()->editEnd();
1423  updateCursor(Cursor(m_view->cursorPosition().line(), numberStartPos + newNumberText.length() - 1));
1424 }
1425 
1426 void KateViModeBase::switchView(Direction direction) {
1427 
1428  QList<KateView*> visible_views;
1429  foreach (KateView* view, KateGlobal::self()->views() ) {
1430  if (view->isVisible())
1431  visible_views.push_back(view);
1432  }
1433 
1434  QPoint current_point = m_view->mapToGlobal(m_view->pos());
1435  int curr_x1 = current_point.x();
1436  int curr_x2 = current_point.x() + m_view->width();
1437  int curr_y1 = current_point.y();
1438  int curr_y2 = current_point.y() + m_view->height();
1439  int curr_cursor_y = m_view->mapToGlobal(m_view->cursorToCoordinate(m_view->cursorPosition())).y();
1440  int curr_cursor_x = m_view->mapToGlobal(m_view->cursorToCoordinate(m_view->cursorPosition())).x();
1441 
1442  KateView *bestview = NULL;
1443  int best_x1 = -1, best_x2 = -1, best_y1 = -1, best_y2 = -1, best_center_y = -1, best_center_x = -1;
1444 
1445  if (direction == Next && visible_views.count() != 1) {
1446  for (int i=0; i< visible_views.count(); i++) {
1447  if (visible_views.at(i) == m_view) {
1448  if (i != visible_views.count() - 1 )
1449  bestview = visible_views.at(i + 1);
1450  else
1451  bestview = visible_views.at(0);
1452  }
1453  }
1454  } else {
1455  foreach (KateView* view, visible_views ) {
1456  QPoint point = view->mapToGlobal(view->pos());
1457  int x1 = point.x();
1458  int x2 = point.x() + view->width();
1459  int y1 = point.y();
1460  int y2 = point.y() + m_view->height();
1461  int center_y = (y1 + y2) / 2;
1462  int center_x = (x1 + x2) / 2;
1463 
1464  switch (direction) {
1465  case Left:
1466  if (view != m_view && x2 <= curr_x1 &&
1467  ( x2 > best_x2 ||
1468  (x2 == best_x2 && qAbs(curr_cursor_y - center_y) < qAbs(curr_cursor_y - best_center_y)) ||
1469  bestview == NULL)){
1470  bestview = view;
1471  best_x2 = x2;
1472  best_center_y = center_y;
1473  }
1474  break;
1475  case Right:
1476  if (view != m_view && x1 >= curr_x2 &&
1477  ( x1 < best_x1 ||
1478  (x1 == best_x1 && qAbs(curr_cursor_y - center_y) < qAbs(curr_cursor_y - best_center_y)) ||
1479  bestview == NULL)){
1480  bestview = view;
1481  best_x1 = x1;
1482  best_center_y = center_y;
1483  }
1484  break;
1485  case Down:
1486  if (view != m_view && y1 >= curr_y2 &&
1487  ( y1 < best_y1 ||
1488  (y1 == best_y1 && qAbs(curr_cursor_x - center_x) < qAbs(curr_cursor_x - best_center_x)) ||
1489  bestview == NULL)){
1490  bestview = view;
1491  best_y1 = y1;
1492  best_center_x = center_x;
1493  }
1494  case Up:
1495  if (view != m_view && y2 <= curr_y1 &&
1496  ( y2 > best_y2 ||
1497  (y2 == best_y2 && qAbs(curr_cursor_x - center_x) < qAbs(curr_cursor_x - best_center_x)) ||
1498  bestview == NULL)){
1499  bestview = view;
1500  best_y2 = y2;
1501  best_center_x = center_x;
1502  }
1503  break;
1504  default:
1505  return;
1506  }
1507 
1508  }
1509  }
1510  if (bestview != NULL ) {
1511  bestview->setFocus();
1512  KateViewConfig::global()->setViInputMode(true);
1513  }
1514 }
katevinormalmode.h
KateDocument::line
virtual QString line(int line) const
Definition: katedocument.cpp:447
KateViRange::endLine
int endLine
Definition: katevirange.h:44
KateView::updateViModeBarMode
void updateViModeBarMode()
Update vi mode statusbar according to the current mode.
Definition: kateview.cpp:1548
KTextEditor::Range::start
Cursor & start()
KateViInputModeManager::viEnterNormalMode
void viEnterNormalMode()
set normal mode to be the active vi mode and perform the needed setup work
Definition: kateviinputmodemanager.cpp:472
KateDocument::config
KateDocumentConfig * config()
Configuration.
Definition: katedocument.h:1009
katevirange.h
KateViModeBase::findWORDEnd
Cursor findWORDEnd(int fromLine, int fromColumn, bool onlyCurrentLine=false) const
Definition: katevimodebase.cpp:650
KateViVisualMode::setVisualLine
void setVisualLine(bool l)
Definition: katevivisualmode.cpp:215
KateTextLayout::startCol
int startCol() const
Definition: katetextlayout.cpp:127
Kate::Script::i18n
QScriptValue i18n(QScriptContext *context, QScriptEngine *engine)
i18n("text", arguments [optional])
Definition: katescripthelpers.cpp:186
KateViModeBase::findPrevWORDStart
Cursor findPrevWORDStart(int fromLine, int fromColumn, bool onlyCurrentLine=false) const
Definition: katevimodebase.cpp:562
Left
KateViModeBase::getRegisterFlag
OperationMode getRegisterFlag(const QChar &reg) const
Definition: katevimodebase.cpp:963
KateViRange::normalize
void normalize()
Definition: katevirange.cpp:53
KateViModeBase::m_infoMessage
QPointer< KTextEditor::Message > m_infoMessage
Definition: katevimodebase.h:180
KateViModeBase::findSurroundingQuotes
KateViRange findSurroundingQuotes(const QChar &c, bool inner=false) const
Definition: katevimodebase.cpp:702
katevimodebase.h
katerenderer.h
katevivisualmode.h
KateDocument::removeLine
virtual bool removeLine(int line)
Definition: katedocument.cpp:727
KateViModeBase::getWordUnderCursor
const QString getWordUnderCursor() const
Definition: katevimodebase.cpp:146
KTextEditor::Range::isValid
virtual bool isValid() const
KateViModeBase::getCharUnderCursor
const QChar getCharUnderCursor() const
Definition: katevimodebase.cpp:133
KateViModeBase::getCharAtVirtualColumn
const QChar getCharAtVirtualColumn(QString &line, int virtualColumn, int tabWidht) const
Definition: katevimodebase.cpp:1292
Right
KateViModeBase::m_currentMotionWasVisualLineUpOrDown
bool m_currentMotionWasVisualLineUpOrDown
Definition: katevimodebase.h:170
KateViModeBase::doc
KateDocument * doc() const
Definition: katevimodebase.h:172
KateViInputModeManager::changeViMode
void changeViMode(ViMode newMode)
changes the current vi mode to the given mode
Definition: kateviinputmodemanager.cpp:444
KateDocument::lineLength
virtual int lineLength(int line) const
Definition: katedocument.cpp:758
VisualMode
Definition: kateviinputmodemanager.h:51
KateLineLayout::textLine
const Kate::TextLine & textLine(bool forceReload=false) const
Definition: katelinelayout.cpp:65
katedocument.h
KateLayoutCache::textLayout
KateTextLayout textLayout(const KTextEditor::Cursor &realCursor)
Returns the layout describing the text line which is occupied by realCursor.
Definition: katelayoutcache.cpp:337
KateGlobal::copyToClipboard
void copyToClipboard(const QString &text)
Copy text to clipboard an remember it in the history.
Definition: kateglobal.cpp:547
KateViRange::invalid
static KateViRange invalid()
Definition: katevirange.h:56
KateGlobal::self
static KateGlobal * self()
Kate Part Internal stuff ;)
Definition: kateglobal.cpp:462
QString
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KTextEditor::Cursor
KateViRange::startColumn
int startColumn
Definition: katevirange.h:41
KateDocument::plainKateTextLine
Kate::TextLine plainKateTextLine(uint i)
Definition: katedocument.cpp:4713
KateViModeBase::getRange
const QString getRange(KateViRange &r, OperationMode mode=LineWise) const
Definition: katevimodebase.cpp:91
KateViInputModeManager::getNextJump
KTextEditor::Cursor getNextJump(KTextEditor::Cursor cursor)
Definition: kateviinputmodemanager.cpp:675
KTextEditor::Search::Regex
KateViModeBase::goLineUpDown
KateViRange goLineUpDown(int lines)
method for moving up or down one or more lines note: the sticky column is always a virtual column ...
Definition: katevimodebase.cpp:1003
kateviinputmodemanager.h
innerRange
KateViRange innerRange(KateViRange range, bool inner)
Definition: katevimodebase.cpp:685
KateViInputModeManager::addJump
void addJump(KTextEditor::Cursor cursor)
Definition: kateviinputmodemanager.cpp:656
KateViModeBase::goVisualLineUpDown
KateViRange goVisualLineUpDown(int lines)
Definition: katevimodebase.cpp:1057
KateViModeBase::findPrevWORDEnd
Cursor findPrevWORDEnd(int fromLine, int fromColumn, bool onlyCurrentLine=false) const
Definition: katevimodebase.cpp:461
KateDocument::insertText
virtual bool insertText(const KTextEditor::Cursor &position, const QString &s, bool block=false)
Definition: katedocument.cpp:530
KateViVisualMode::setVisualBlock
void setVisualBlock(bool l)
Definition: katevivisualmode.cpp:224
KateDocument::textLines
virtual QStringList textLines(const KTextEditor::Range &range, bool block=false) const
Definition: katedocument.cpp:398
KateViewConfig::setViInputMode
void setViInputMode(bool on)
Definition: kateconfig.cpp:1698
KateViModeBase::m_view
KateView * m_view
Definition: katevimodebase.h:172
KateViModeBase::fillRegister
void fillRegister(const QChar &reg, const QString &text, OperationMode flag=CharWise)
Definition: katevimodebase.cpp:968
KateDocument::character
virtual QChar character(const KTextEditor::Cursor &position) const
Definition: katedocument.cpp:388
KateViRange
Definition: katevirange.h:33
Up
Definition: katevimodebase.h:56
KateViRange::endColumn
int endColumn
Definition: katevirange.h:44
view.h
KateViRange::motionType
ViMotion::MotionType motionType
Definition: katevirange.h:45
KateViModeBase::startNormalMode
bool startNormalMode()
Definition: katevimodebase.cpp:1176
kateglobal.h
KateViModeBase::getNextJump
KTextEditor::Cursor getNextJump(KTextEditor::Cursor)
Definition: katevimodebase.cpp:979
KateView::cursorToCoordinate
QPoint cursorToCoordinate(const KTextEditor::Cursor &cursor) const
Definition: kateview.cpp:2408
KateLayoutCache::line
KateLineLayoutPtr line(int realLine, int virtualLine=-1)
Returns the KateLineLayout for the specified line.
Definition: katelayoutcache.cpp:280
KateViModeBase::startReplaceMode
bool startReplaceMode()
Definition: katevimodebase.cpp:1201
KateViModeBase::updateCursor
void updateCursor(const Cursor &c) const
Definition: katevimodebase.cpp:937
KateDocument::lines
virtual int lines() const
Definition: katedocument.cpp:753
KateDocument::documentEnd
virtual KTextEditor::Cursor documentEnd() const
Definition: katedocument.cpp:4682
KateViInputModeManager::viEnterVisualMode
void viEnterVisualMode(ViMode visualMode=VisualMode)
set visual mode to be the active vi mode and make the needed setup work
Definition: kateviinputmodemanager.cpp:514
KateViModeBase::getVerbatimKeys
QString getVerbatimKeys() const
Definition: katevimodebase.cpp:1287
KateViModeBase::switchView
void switchView(Direction direction=Next)
Definition: katevimodebase.cpp:1426
kateviewinternal.h
KTextEditor::Search::Backwards
KateViModeBase::goLineDown
KateViRange goLineDown()
Definition: katevimodebase.cpp:989
KateViModeBase::findPattern
Range findPattern(const QString &pattern, bool backwards, bool caseSensitive, const Cursor &startFrom, int count=-1) const
Definition: katevimodebase.cpp:188
Next
Definition: katevimodebase.h:60
Direction
Direction
Definition: katevimodebase.h:55
KateViModeBase::startInsertMode
bool startInsertMode()
Definition: katevimodebase.cpp:1192
KateViModeBase::getLine
const QString getLine(int lineNumber=-1) const
Definition: katevimodebase.cpp:119
KTextEditor::Document::documentRange
Range documentRange() const
KateViModeBase::m_stickyColumn
int m_stickyColumn
Definition: katevimodebase.h:168
KateViModeBase::findWordEnd
Cursor findWordEnd(int fromLine, int fromColumn, bool onlyCurrentLine=false) const
Definition: katevimodebase.cpp:609
KateLineLayout::viewLineCount
int viewLineCount() const
Definition: katelinelayout.cpp:172
KateLayoutCache::viewLine
KateTextLayout & viewLine(int viewLine)
Returns the layout of the corresponding line in the view.
Definition: katelayoutcache.cpp:358
KateView
Definition: kateview.h:78
VisualBlockMode
Definition: kateviinputmodemanager.h:53
KateViModeBase::getCount
unsigned int getCount() const
Definition: katevimodebase.h:131
KTextEditor::Range
KateViModeBase::findNextWordStart
Cursor findNextWordStart(int fromLine, int fromColumn, bool onlyCurrentLine=false) const
Definition: katevimodebase.cpp:317
KateViModeBase::startVisualLineMode
bool startVisualLineMode()
Definition: katevimodebase.cpp:1241
KateViModeBase::message
void message(const QString &msg)
Definition: katevimodebase.cpp:1271
LineWise
Definition: katevimodebase.h:51
KateViModeBase::error
void error(const QString &errorMsg)
Definition: katevimodebase.cpp:1255
KateDocument::setUndoMergeAllEdits
void setUndoMergeAllEdits(bool merge)
Definition: katedocument.cpp:4723
KateViModeBase::startVisualBlockMode
bool startVisualBlockMode()
Definition: katevimodebase.cpp:1227
Down
Definition: katevimodebase.h:57
ok
KGuiItem ok()
KateDocument::kateTextLine
Kate::TextLine kateTextLine(uint i)
Definition: katedocument.cpp:4707
VisualLineMode
Definition: kateviinputmodemanager.h:52
KateDocument::searchText
virtual QVector< KTextEditor::Range > searchText(const KTextEditor::Range &range, const QString &pattern, const KTextEditor::Search::SearchOptions options)
Definition: katedocument.cpp:1387
KateViModeBase::m_keysVerbatim
QString m_keysVerbatim
Definition: katevimodebase.h:166
KateView::cursorPosition
KTextEditor::Cursor cursorPosition() const
Definition: kateview.cpp:2398
KateViModeBase::findLineStartingWitchChar
int findLineStartingWitchChar(const QChar &c, unsigned int count, bool forward=true) const
Definition: katevimodebase.cpp:904
ViMotion::ExclusiveMotion
Definition: katevirange.h:29
KTextEditor::Cursor::line
virtual int line() const
KateViInputModeManager::storeLastChangeCommand
void storeLastChangeCommand()
copy the contents of the key events log to m_lastChange so that it can be repeated ...
Definition: kateviinputmodemanager.cpp:278
KateGlobal::viInputModeGlobal
KateViGlobal * viInputModeGlobal()
vi input mode global
Definition: kateglobal.h:338
KateViGlobal::getRegisterFlag
OperationMode getRegisterFlag(const QChar &reg) const
Definition: kateviglobal.cpp:126
KateViModeBase::goLineUp
KateViRange goLineUp()
Definition: katevimodebase.cpp:994
KateViModeBase::getChosenRegister
QChar getChosenRegister(const QChar &defaultReg) const
Definition: katevimodebase.cpp:945
KateViModeBase::yankToClipBoard
void yankToClipBoard(QChar chosen_register, QString text)
Definition: katevimodebase.cpp:54
KateView::viInputMode
bool viInputMode() const
Definition: kateview.cpp:1515
QPoint
KateView::getCurrentViMode
ViMode getCurrentViMode() const
Definition: kateview.cpp:1562
KateVi::EOL
const unsigned int EOL
Definition: kateviglobal.h:41
KateDocument::editEnd
void editEnd()
End a editor operation.
Definition: katedocument.cpp:796
KateViModeBase::deleteRange
bool deleteRange(KateViRange &r, OperationMode mode=LineWise, bool addToRegister=true)
Definition: katevimodebase.cpp:61
KateViModeBase::getPrevJump
KTextEditor::Cursor getPrevJump(KTextEditor::Cursor)
Definition: katevimodebase.cpp:984
KTextEditor::Range::end
Cursor & end()
KateViModeBase::addJump
void addJump(KTextEditor::Cursor cursor)
Definition: katevimodebase.cpp:974
KateViModeBase::m_viInputModeManager
KateViInputModeManager * m_viInputModeManager
Definition: katevimodebase.h:177
KateViInputModeManager::getPrevJump
KTextEditor::Cursor getPrevJump(KTextEditor::Cursor cursor)
Definition: kateviinputmodemanager.cpp:692
Kate::TextLine
QSharedPointer< TextLineData > TextLine
The normal world only accesses the text lines with shared pointers.
Definition: katetextline.h:443
KTextEditor::Message::Positive
KateViModeBase::m_extraWordCharacters
QString m_extraWordCharacters
Definition: katevimodebase.h:165
OperationMode
OperationMode
Definition: katevimodebase.h:49
KateViInputModeManager::isReplayingLastChange
bool isReplayingLastChange() const
Definition: kateviinputmodemanager.h:153
katevireplacemode.h
KateDocument::text
virtual QString text(const KTextEditor::Range &range, bool blockwise=false) const
Definition: katedocument.cpp:337
KateViModeBase::m_lastMotionWasVisualLineUpOrDown
bool m_lastMotionWasVisualLineUpOrDown
Definition: katevimodebase.h:169
KateViInputModeManager::clearCurrentChangeLog
void clearCurrentChangeLog()
clear the key event log
Definition: kateviinputmodemanager.h:163
KateViModeBase::getRegisterContent
QString getRegisterContent(const QChar &reg)
Definition: katevimodebase.cpp:952
KateViModeBase::findSurroundingBrackets
KateViRange findSurroundingBrackets(const QChar &c1, const QChar &c2, bool inner, const QChar &nested1, const QChar &nested2) const
Definition: katevimodebase.cpp:769
KateTextLayout::lineLayout
const QTextLine & lineLayout() const
Definition: katetextlayout.cpp:117
KateViModeBase::findPrevWordEnd
Cursor findPrevWordEnd(int fromLine, int fromColumn, bool onlyCurrentLine=false) const
Definition: katevimodebase.cpp:421
KateView::doc
KateDocument * doc()
accessor to katedocument pointer
Definition: kateview.h:552
Block
Definition: katevimodebase.h:52
KateDocument::postMessage
virtual bool postMessage(KTextEditor::Message *message)
Definition: katedocument.cpp:5498
KateViModeBase::startVisualMode
bool startVisualMode()
Definition: katevimodebase.cpp:1210
KTextEditor::Search::CaseInsensitive
KateViModeBase::getWordRangeUnderCursor
const Range getWordRangeUnderCursor() const
Definition: katevimodebase.cpp:152
KateViInputModeManager::getViVisualMode
KateViVisualMode * getViVisualMode()
Definition: kateviinputmodemanager.cpp:544
KateDocument::editStart
void editStart()
Enclose editor actions with editStart() and editEnd() to group them.
Definition: katedocument.cpp:776
KTextEditor::Message::Error
KateView::currentTextLine
QString currentTextLine()
Definition: kateview.cpp:2428
KateDocumentConfig::tabWidth
int tabWidth() const
Definition: kateconfig.cpp:403
KateViModeBase::findPrevWordStart
Cursor findPrevWordStart(int fromLine, int fromColumn, bool onlyCurrentLine=false) const
Definition: katevimodebase.cpp:498
KateViModeBase::findSurrounding
KateViRange findSurrounding(const QRegExp &c1, const QRegExp &c2, bool inner=false) const
Definition: katevimodebase.cpp:882
KTextEditor::Message::BottomInView
kateviglobal.h
kateconfig.h
KateViGlobal::getRegisterContent
QString getRegisterContent(const QChar &reg) const
Definition: kateviglobal.cpp:121
KTextEditor::Cursor::setColumn
virtual void setColumn(int column)
KTextEditor::Cursor::column
int column() const
ViMotion::InclusiveMotion
Definition: katevirange.h:29
KTextEditor::Message
KateViGlobal::fillRegister
void fillRegister(const QChar &reg, const QString &text, OperationMode flag=CharWise)
Definition: kateviglobal.cpp:146
KateViRange::startLine
int startLine
Definition: katevirange.h:41
KateViModeBase::m_viewInternal
KateViewInternal * m_viewInternal
Definition: katevimodebase.h:176
KateDocument::removeText
virtual bool removeText(const KTextEditor::Range &range, bool block=false)
Definition: katedocument.cpp:633
KateViModeBase::findNextWORDStart
Cursor findNextWORDStart(int fromLine, int fromColumn, bool onlyCurrentLine=false) const
Definition: katevimodebase.cpp:379
KateViInputModeManager::viEnterInsertMode
void viEnterInsertMode()
set insert mode to be the active vi mode and perform the needed setup work
Definition: kateviinputmodemanager.cpp:499
KateViModeBase::addToNumberUnderCursor
void addToNumberUnderCursor(int count)
Definition: katevimodebase.cpp:1325
KateViModeBase::findPatternForMotion
KateViRange findPatternForMotion(const QString &pattern, bool backwards, bool caseSensitive, const Cursor &startFrom, int count=1) const
Definition: katevimodebase.cpp:304
QList< KateView * >
KateViewConfig::global
static KateViewConfig * global()
Definition: kateconfig.h:402
KateViInputModeManager::viEnterReplaceMode
void viEnterReplaceMode()
set replace mode to be the active vi mode and make the needed setup work
Definition: kateviinputmodemanager.cpp:526
KateViModeBase::m_register
QChar m_register
Definition: katevimodebase.h:154
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:31:53 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Kate

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

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Applications
  •   Libraries
  •     libkonq
  • Konsole

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal