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

Kate

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