summaryrefslogtreecommitdiff
path: root/noncore/apps/tinykate/libkate/document/katedocument.cpp
Unidiff
Diffstat (limited to 'noncore/apps/tinykate/libkate/document/katedocument.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/tinykate/libkate/document/katedocument.cpp3169
1 files changed, 3169 insertions, 0 deletions
diff --git a/noncore/apps/tinykate/libkate/document/katedocument.cpp b/noncore/apps/tinykate/libkate/document/katedocument.cpp
new file mode 100644
index 0000000..0d84bcf
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katedocument.cpp
@@ -0,0 +1,3169 @@
1/***************************************************************************
2 katedocument.cpp - description
3 -------------------
4 begin : Mon Jan 15 2001
5 copyright : (C) 2001 by Christoph "Crossfire" Cullmann
6 (C) 2002 by Joseph Wenninger
7 email : crossfire@babylon2k.de
8 jowenn@kde.org
9
10***************************************************************************/
11
12/***************************************************************************
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 ***************************************************************************/
20
21/*
22 Copyright (C) 1998, 1999 Jochen Wilhelmy
23 digisnap@cs.tu-berlin.de
24
25 This library is free software; you can redistribute it and/or
26 modify it under the terms of the GNU Library General Public
27 License as published by the Free Software Foundation; either
28 version 2 of the License, or (at your option) any later version.
29
30 This library is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 Library General Public License for more details.
34
35 You should have received a copy of the GNU Library General Public License
36 along with this library; see the file COPYING.LIB. If not, write to
37 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
38 Boston, MA 02111-1307, USA.
39*/
40
41#include "katedocument.h"
42
43
44#include <qfileinfo.h>
45#include <qdatetime.h>
46
47#include <kmessagebox.h>
48#include <klocale.h>
49#include <qpe/config.h>
50#include <qstring.h>
51
52#include <sys/time.h>
53#include <unistd.h>
54
55#include <stdio.h>
56
57#include <qtimer.h>
58#include <qobject.h>
59#include <qapplication.h>
60#include <qclipboard.h>
61#include <qfont.h>
62#include <qpainter.h>
63#include <qfile.h>
64#include <qtextstream.h>
65#include <qtextcodec.h>
66#include <kglobal.h>
67
68#include <klocale.h>
69//#include <kcharsets.h>
70#include <kdebug.h>
71//#include <kinstance.h>
72
73#include <kglobalsettings.h>
74//#include <kaction.h>
75//#include <kstdaction.h>
76
77#include "../view/kateview.h"
78#include "katebuffer.h"
79#include "katetextline.h"
80
81#include "katecmd.h"
82
83KateAction::KateAction(Action a, PointStruc &cursor, int len, const QString &text)
84 : action(a), cursor(cursor), len(len), text(text) {
85}
86
87KateActionGroup::KateActionGroup(PointStruc &aStart, int type)
88 : start(aStart), action(0L), undoType(type) {
89}
90
91KateActionGroup::~KateActionGroup() {
92 KateAction *current, *next;
93
94 current = action;
95 while (current) {
96 next = current->next;
97 delete current;
98 current = next;
99 }
100}
101
102void KateActionGroup::insertAction(KateAction *a) {
103 a->next = action;
104 action = a;
105}
106
107const char * KateActionGroup::typeName(int type)
108{
109 // return a short text description of the given undo group type suitable for a menu
110 // not the lack of i18n's, the caller is expected to handle translation
111 switch (type) {
112 case ugPaste : return "Paste Text";
113 case ugDelBlock : return "Selection Overwrite";
114 case ugIndent : return "Indent";
115 case ugUnindent : return "Unindent";
116 case ugComment : return "Comment";
117 case ugUncomment : return "Uncomment";
118 case ugReplace : return "Text Replace";
119 case ugSpell : return "Spell Check";
120 case ugInsChar : return "Typing";
121 case ugDelChar : return "Delete Text";
122 case ugInsLine : return "New Line";
123 case ugDelLine : return "Delete Line";
124 }
125 return "";
126}
127
128const int KateDocument::maxAttribs = 32;
129
130QStringList KateDocument::searchForList = QStringList();
131QStringList KateDocument::replaceWithList = QStringList();
132
133uint KateDocument::uniqueID = 0;
134
135QPtrDict<KateDocument::KateDocPrivate>* KateDocument::d_ptr = 0;
136
137
138KateDocument::KateDocument(bool bSingleViewMode, bool bBrowserView,
139 QWidget *parentWidget, const char *widgetName,
140 QObject *, const char *)
141 : Kate::Document (),
142 myFont(KGlobalSettings::generalFont()), myFontBold(KGlobalSettings::generalFont()), myFontItalic(KGlobalSettings::generalFont()), myFontBI(KGlobalSettings::generalFont()),
143 myFontMetrics (myFont), myFontMetricsBold (myFontBold), myFontMetricsItalic (myFontItalic), myFontMetricsBI (myFontBI),
144 hlManager(HlManager::self ())
145{
146
147 d(this)->hlSetByUser = false;
148 PreHighlightedTill=0;
149 RequestPreHighlightTill=0;
150
151 m_bSingleViewMode=bSingleViewMode;
152 m_bBrowserView = bBrowserView;
153
154 m_url = QString::null;
155
156 // NOTE: QFont::CharSet doesn't provide all the charsets KDE supports
157 // (esp. it doesn't distinguish between UTF-8 and iso10646-1)
158
159 myEncoding = QString::fromLatin1(QTextCodec::codecForLocale()->name());
160
161 maxLength = -1;
162
163 setFont (KGlobalSettings::generalFont());
164
165 myDocID = uniqueID;
166 uniqueID++;
167
168 myDocName = QString ("");
169 fileInfo = new QFileInfo ();
170
171 myCmd = new KateCmd (this);
172
173 connect(this,SIGNAL(modifiedChanged ()),this,SLOT(slotModChanged ()));
174
175 buffer = new KWBuffer;
176 connect(buffer, SIGNAL(linesChanged(int)), this, SLOT(slotBufferChanged()));
177// connect(buffer, SIGNAL(textChanged()), this, SIGNAL(textChanged()));
178 connect(buffer, SIGNAL(needHighlight(long,long)),this,SLOT(slotBufferHighlight(long,long)));
179
180 colors[0] = KGlobalSettings::baseColor();
181 colors[1] = KGlobalSettings::highlightColor();
182
183 m_attribs = new Attribute[maxAttribs];
184
185 m_highlight = 0L;
186 tabChars = 8;
187
188 m_singleSelection = false;
189
190 newDocGeometry = false;
191 readOnly = false;
192 newDoc = false;
193
194 modified = false;
195
196 undoList.setAutoDelete(true);
197 undoState = 0;
198 undoSteps = 50;
199
200 pseudoModal = 0L;
201 clear();
202
203 setHighlight(0); //calls updateFontData()
204 // if the user changes the highlight with the dialog, notify the doc
205 connect(hlManager,SIGNAL(changed()),SLOT(hlChanged()));
206
207 newDocGeometry = false;
208
209 readConfig();
210
211 setReadOnly(false);
212}
213
214void KateDocument::setDontChangeHlOnSave()
215{
216 d(this)->hlSetByUser = true;
217}
218
219void KateDocument::setFont (QFont font)
220{
221 kdDebug()<<"Kate:: setFont"<<endl;
222 int oldwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
223 myFont = font;
224 myFontBold = QFont (font);
225 myFontBold.setBold (true);
226
227 myFontItalic = QFont (font);
228 myFontItalic.setItalic (true);
229
230 myFontBI = QFont (font);
231 myFontBI.setBold (true);
232 myFontBI.setItalic (true);
233
234 myFontMetrics = CachedFontMetrics (myFont);
235 myFontMetricsBold = CachedFontMetrics (myFontBold);
236 myFontMetricsItalic = CachedFontMetrics (myFontItalic);
237 myFontMetricsBI = CachedFontMetrics (myFontBI);
238 int newwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
239 maxLength=maxLength*(float)newwidth/(float)oldwidth; //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
240
241 updateFontData();
242 updateViews(); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
243
244}
245
246long KateDocument::needPreHighlight(long till)
247{
248 int max=numLines()-1;
249 if (till>max)
250 {
251 till=max;
252 }
253 if (PreHighlightedTill>=till) return -1;
254
255 long tmp=RequestPreHighlightTill;
256 if (RequestPreHighlightTill<till)
257 {
258 RequestPreHighlightTill=till;
259 if (tmp<=PreHighlightedTill) QTimer::singleShot(10,this,SLOT(doPreHighlight()));
260 }
261 return RequestPreHighlightTill;
262}
263
264void KateDocument::doPreHighlight()
265{
266 int from = PreHighlightedTill;
267 int till = PreHighlightedTill+200;
268 int max = numLines()-1;
269 if (till > max)
270 {
271 till = max;
272 }
273 PreHighlightedTill = till;
274 updateLines(from,till);
275 emit preHighlightChanged(PreHighlightedTill);
276 if (PreHighlightedTill<RequestPreHighlightTill)
277 QTimer::singleShot(10,this,SLOT(doPreHighlight()));
278}
279
280KateDocument::~KateDocument()
281{
282 m_highlight->release();
283
284 if ( !m_bSingleViewMode )
285 {
286 m_views.setAutoDelete( true );
287 m_views.clear();
288 m_views.setAutoDelete( false );
289 }
290 delete_d(this);
291}
292
293void KateDocument::openURL(const QString &filename)
294{
295
296 m_file=filename;
297 fileInfo->setFile (m_file);
298 setMTime();
299
300 if (!fileInfo->exists() || !fileInfo->isReadable())
301 {
302 qDebug("File doesn't exit or couldn't be read");
303 return false;
304 }
305
306 buffer->clear();
307#warning fixme
308// buffer->insertFile(0, m_file, KGlobal::charsets()->codecForName(myEncoding));
309 qDebug("Telling buffer to open file");
310 buffer->insertFile(0, m_file, QTextCodec::codecForLocale());
311
312 setMTime();
313
314 if (myWordWrap)
315 wrapText (myWordWrapAt);
316
317 int hl = hlManager->wildcardFind( m_file );
318
319 setHighlight(hl);
320
321 updateLines();
322 updateViews();
323
324 emit fileNameChanged();
325
326 return true;
327}
328
329bool KateDocument::saveFile()
330{
331 QFile f( m_file );
332 if ( !f.open( IO_WriteOnly ) )
333 return false; // Error
334
335 QTextStream stream(&f);
336
337 stream.setEncoding(QTextStream::RawUnicode); // disable Unicode headers
338#warning fixme
339// stream.setCodec(KGlobal::charsets()->codecForName(myEncoding));
340 stream.setCodec(QTextCodec::codecForLocale()); // this line sets the mapper to the correct codec
341
342 int maxLine = numLines();
343 int line = 0;
344 while(true)
345 {
346 stream << getTextLine(line)->getString();
347 line++;
348 if (line >= maxLine) break;
349
350 if (eolMode == KateDocument::eolUnix) stream << "\n";
351 else if (eolMode == KateDocument::eolDos) stream << "\r\n";
352 else if (eolMode == KateDocument::eolMacintosh) stream << '\r';
353 };
354 f.close();
355
356 fileInfo->setFile (m_file);
357 setMTime();
358
359 if (!(d(this)->hlSetByUser))
360 {
361 int hl = hlManager->wildcardFind( m_file );
362
363 setHighlight(hl);
364 }
365 emit fileNameChanged ();
366
367 return (f.status() == IO_Ok);
368}
369
370KTextEditor::View *KateDocument::createView( QWidget *parent, const char *name )
371{
372 return new KateView( this, parent, name);
373}
374
375QString KateDocument::textLine( int line ) const
376{
377 TextLine::Ptr l = getTextLine( line );
378 if ( !l )
379 return QString();
380
381 return l->getString();
382}
383
384void KateDocument::replaceLine(const QString& s,int line)
385{
386 remove_Line(line,false);
387 insert_Line(s,line,true);
388}
389
390void KateDocument::insertLine( const QString &str, int l ) {
391 insert_Line(str,l,true);
392}
393
394void KateDocument::insert_Line(const QString& s,int line, bool update)
395{
396 kdDebug(13020)<<"KateDocument::insertLine "<<s<<QString("%1").arg(line)<<endl;
397 TextLine::Ptr TL=new TextLine();
398 TL->append(s.unicode(),s.length());
399 buffer->insertLine(line,TL);
400 if (update)
401 {
402 newDocGeometry=true;
403 updateLines(line);
404 updateViews();
405 }
406}
407
408void KateDocument::insertAt( const QString &s, int line, int col, bool )
409{
410 VConfig c;
411 c.view = 0; // ### FIXME
412 c.cursor.x = col;
413 c.cursor.y = line;
414 c.cXPos = 0; // ### FIXME
415 c.flags = 0; // ### FIXME
416 insert( c, s );
417}
418
419void KateDocument::removeLine( int line ) {
420 remove_Line(line,true);
421}
422
423void KateDocument::remove_Line(int line,bool update)
424{
425 kdDebug(13020)<<"KateDocument::removeLine "<<QString("%1").arg(line)<<endl;
426 buffer->removeLine(line);
427// newDocGeometry=true;
428// if line==0)
429 if (update)
430 {
431 updateLines(line);
432 updateViews();
433 }
434}
435
436int KateDocument::length() const
437{
438 return text().length();
439}
440
441void KateDocument::setSelection( int , int , int , int )
442{
443}
444
445bool KateDocument::hasSelection() const
446{
447 return (selectEnd >= selectStart);
448}
449
450QString KateDocument::selection() const
451{
452 uint flags = 0;
453 TextLine::Ptr textLine;
454 int len, z, start, end, i;
455
456 len = 1;
457 if (!(flags & KateView::cfVerticalSelect)) {
458 for (z = selectStart; z <= selectEnd; z++) {
459 textLine = getTextLine(z);
460 len += textLine->numSelected();
461 if (textLine->isSelected()) len++;
462 }
463 QString s;
464 len = 0;
465 for (z = selectStart; z <= selectEnd; z++) {
466 textLine = getTextLine(z);
467 end = 0;
468 do {
469 start = textLine->findUnselected(end);
470 end = textLine->findSelected(start);
471 for (i = start; i < end; i++) {
472 s[len] = textLine->getChar(i);
473 len++;
474 }
475 } while (start < end);
476 if (textLine->isSelected()) {
477 s[len] = '\n';
478 len++;
479 }
480 }
481// s[len] = '\0';
482 return s;
483 } else {
484 for (z = selectStart; z <= selectEnd; z++) {
485 textLine = getTextLine(z);
486 len += textLine->numSelected() + 1;
487 }
488 QString s;
489 len = 0;
490 for (z = selectStart; z <= selectEnd; z++) {
491 textLine = getTextLine(z);
492 end = 0;
493 do {
494 start = textLine->findUnselected(end);
495 end = textLine->findSelected(start);
496 for (i = start; i < end; i++) {
497 s[len] = textLine->getChar(i);
498 len++;
499 }
500 } while (start < end);
501 s[len] = '\n';
502 len++;
503 }
504// s[len] = '\0'; // the final \0 is not counted in length()
505 return s;
506 }
507}
508
509int KateDocument::numLines() const
510{
511 return buffer->count();
512}
513
514
515TextLine::Ptr KateDocument::getTextLine(int line) const
516{
517 // This is a hack to get this stuff working.
518 return buffer->line(line);
519}
520
521int KateDocument::textLength(int line) {
522 TextLine::Ptr textLine = getTextLine(line);
523 if (!textLine) return 0;
524 return textLine->length();
525}
526
527void KateDocument::setTabWidth(int chars) {
528 if (tabChars == chars) return;
529 if (chars < 1) chars = 1;
530 if (chars > 16) chars = 16;
531 tabChars = chars;
532 updateFontData();
533
534 maxLength = -1;
535 for (int i=0; i < buffer->count(); i++)
536 {
537 TextLine::Ptr textLine = buffer->line(i);
538 int len = textWidth(textLine,textLine->length());
539 if (len > maxLength) {
540 maxLength = len;
541 longestLine = textLine;
542 }
543 }
544}
545
546void KateDocument::setReadOnly(bool m) {
547 KTextEditor::View *view;
548
549 if (m != readOnly) {
550 readOnly = m;
551// if (readOnly) recordReset();
552 for (view = m_views.first(); view != 0L; view = m_views.next() ) {
553 emit static_cast<KateView *>( view )->newStatus();
554 }
555 }
556}
557
558bool KateDocument::isReadOnly() const {
559 return readOnly;
560}
561
562void KateDocument::setNewDoc( bool m )
563{
564// KTextEditor::View *view;
565
566 if ( m != newDoc )
567 {
568 newDoc = m;
569//// if (readOnly) recordReset();
570// for (view = m_views.first(); view != 0L; view = m_views.next() ) {
571// emit static_cast<KateView *>( view )->newStatus();
572// }
573 }
574}
575
576bool KateDocument::isNewDoc() const {
577 return newDoc;
578}
579
580void KateDocument::setModified(bool m) {
581 KTextEditor::View *view;
582
583 if (m != modified) {
584 modified = m;
585 for (view = m_views.first(); view != 0L; view = m_views.next() ) {
586 emit static_cast<KateView *>( view )->newStatus();
587 }
588 emit modifiedChanged ();
589 }
590}
591
592bool KateDocument::isModified() const {
593 return modified;
594}
595
596void KateDocument::readConfig()
597{
598 KConfig *config = KGlobal::config();
599 config->setGroup("Kate Document");
600
601 myWordWrap = config->readBoolEntry("Word Wrap On", false);
602 myWordWrapAt = config->readNumEntry("Word Wrap At", 80);
603 if (myWordWrap)
604 wrapText (myWordWrapAt);
605
606 setTabWidth(config->readNumEntry("TabWidth", 8));
607 setUndoSteps(config->readNumEntry("UndoSteps", 50));
608 m_singleSelection = config->readBoolEntry("SingleSelection", false);
609 myEncoding = config->readEntry("Encoding", QString::fromLatin1(QTextCodec::codecForLocale()->name()));
610 setFont (config->readFontEntry("Font", &myFont));
611
612 colors[0] = config->readColorEntry("Color Background", &colors[0]);
613 colors[1] = config->readColorEntry("Color Selected", &colors[1]);
614
615 config->sync();
616}
617
618void KateDocument::writeConfig()
619{
620 KConfig *config = KGlobal::config();
621 config->setGroup("Kate Document");
622#if 0
623 cofig->writeEntry("Word Wrap On", myWordWrap);
624 config->writeEntry("Word Wrap At", myWordWrapAt);
625 config->writeEntry("TabWidth", tabChars);
626 config->writeEntry("UndoSteps", undoSteps);
627 config->writeEntry("SingleSelection", m_singleSelection);
628 config->writeEntry("Encoding", myEncoding);
629 config->writeEntry("Font", myFont);
630 config->writeEntry("Color Background", colors[0]);
631 config->writeEntry("Color Selected", colors[1]);
632#endif
633 config->sync();
634}
635
636void KateDocument::readSessionConfig(KConfig *config)
637{
638 m_url = config->readEntry("URL"); // ### doesn't this break the encoding? (Simon)
639 setHighlight(hlManager->nameFind(config->readEntry("Highlight")));
640 // anders: restore bookmarks if possible
641 QValueList<int> l = config->readIntListEntry("Bookmarks");
642 if ( l.count() ) {
643 for (uint i=0; i < l.count(); i++) {
644 if ( numLines() < l[i] ) break;
645 getTextLine( l[i] )->addMark( Bookmark );
646 }
647 }
648}
649
650void KateDocument::writeSessionConfig(KConfig *config)
651{
652#if 0
653 config->writeEntry("URL", m_url); // ### encoding?? (Simon)
654 config->writeEntry("Highlight", m_highlight->name());
655 // anders: save bookmarks
656 QList<Kate::Mark> l = marks();
657 QValueList<int> ml;
658 for (uint i=0; i < l.count(); i++) {
659 if ( l.at(i)->type == 1) // only save bookmarks
660 ml << l.at(i)->line;
661 }
662 if ( ml.count() )
663 config->writeEntry("Bookmarks", ml);
664#endif
665}
666
667
668void KateDocument::setHighlight(int n) {
669 Highlight *h;
670
671// hlNumber = n;
672
673 h = hlManager->getHl(n);
674 if (h == m_highlight) {
675 updateLines();
676 } else {
677 if (m_highlight != 0L) m_highlight->release();
678 h->use();
679 m_highlight = h;
680 makeAttribs();
681 }
682 PreHighlightedTill=0;
683 RequestPreHighlightTill=0;
684 emit(highlightChanged());
685}
686
687void KateDocument::makeAttribs() {
688 qDebug("KateDocument::makeAttribs()");
689 m_numAttribs = hlManager->makeAttribs(m_highlight, m_attribs, maxAttribs);
690 updateFontData();
691 updateLines();
692}
693
694void KateDocument::updateFontData() {
695 int maxAscent, maxDescent;
696 int tabWidth;
697 KateView *view;
698
699 maxAscent = myFontMetrics.ascent();
700 maxDescent = myFontMetrics.descent();
701 tabWidth = myFontMetrics.width(' ');
702
703 fontHeight = maxAscent + maxDescent + 1;
704 fontAscent = maxAscent;
705 m_tabWidth = tabChars*tabWidth;
706
707 for (view = views.first(); view != 0L; view = views.next() ) {
708 view->myViewInternal->drawBuffer->resize(view->width(),fontHeight);
709 view->tagAll();
710 view->updateCursor();
711 }
712}
713
714void KateDocument::hlChanged() { //slot
715 makeAttribs();
716 updateViews();
717}
718
719
720void KateDocument::addView(KTextEditor::View *view) {
721 views.append( static_cast<KateView *>( view ) );
722 KTextEditor::Document::addView( view );
723 connect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) );
724}
725
726void KateDocument::removeView(KTextEditor::View *view) {
727// if (undoView == view) recordReset();
728 disconnect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) );
729 views.removeRef( static_cast<KateView *>( view ) );
730 KTextEditor::Document::removeView( view );
731}
732
733void KateDocument::slotViewDestroyed()
734{
735 views.removeRef( static_cast<const KateView *>( sender() ) );
736}
737
738bool KateDocument::ownedView(KateView *view) {
739 // do we own the given view?
740 return (views.containsRef(view) > 0);
741}
742
743bool KateDocument::isLastView(int numViews) {
744 return ((int) views.count() == numViews);
745}
746
747int KateDocument::textWidth(const TextLine::Ptr &textLine, int cursorX) {
748 int x;
749 int z;
750 QChar ch;
751 Attribute *a;
752
753 x = 0;
754 for (z = 0; z < cursorX; z++) {
755 ch = textLine->getChar(z);
756 a = &m_attribs[textLine->getAttr(z)];
757
758 if (ch == '\t')
759 x += m_tabWidth - (x % m_tabWidth);
760 else if (a->bold && a->italic)
761 x += myFontMetricsBI.width(ch);
762 else if (a->bold)
763 x += myFontMetricsBold.width(ch);
764 else if (a->italic)
765 x += myFontMetricsItalic.width(ch);
766 else
767 x += myFontMetrics.width(ch);
768 }
769 return x;
770}
771
772int KateDocument::textWidth(PointStruc &cursor) {
773 if (cursor.x < 0)
774 cursor.x = 0;
775 if (cursor.y < 0)
776 cursor.y = 0;
777 if (cursor.y >= numLines())
778 cursor.y = lastLine();
779 return textWidth(getTextLine(cursor.y),cursor.x);
780}
781
782int KateDocument::textWidth(bool wrapCursor, PointStruc &cursor, int xPos) {
783 int len;
784 int x, oldX;
785 int z;
786 QChar ch;
787 Attribute *a;
788
789 if (cursor.y < 0) cursor.y = 0;
790 if (cursor.y > lastLine()) cursor.y = lastLine();
791 TextLine::Ptr textLine = getTextLine(cursor.y);
792 len = textLine->length();
793
794 x = oldX = z = 0;
795 while (x < xPos && (!wrapCursor || z < len)) {
796 oldX = x;
797 ch = textLine->getChar(z);
798 a = &m_attribs[textLine->getAttr(z)];
799
800 if (ch == '\t')
801 x += m_tabWidth - (x % m_tabWidth);
802 else if (a->bold && a->italic)
803 x += myFontMetricsBI.width(ch);
804 else if (a->bold)
805 x += myFontMetricsBold.width(ch);
806 else if (a->italic)
807 x += myFontMetricsItalic.width(ch);
808 else
809 x += myFontMetrics.width(ch);
810
811 z++;
812 }
813 if (xPos - oldX < x - xPos && z > 0) {
814 z--;
815 x = oldX;
816 }
817 cursor.x = z;
818 return x;
819}
820
821
822int KateDocument::textPos(const TextLine::Ptr &textLine, int xPos) {
823 int x, oldX;
824 int z;
825 QChar ch;
826 Attribute *a;
827
828 x = oldX = z = 0;
829 while (x < xPos) { // && z < len) {
830 oldX = x;
831 ch = textLine->getChar(z);
832 a = &m_attribs[textLine->getAttr(z)];
833
834 if (ch == '\t')
835 x += m_tabWidth - (x % m_tabWidth);
836 else if (a->bold && a->italic)
837 x += myFontMetricsBI.width(ch);
838 else if (a->bold)
839 x += myFontMetricsBold.width(ch);
840 else if (a->italic)
841 x += myFontMetricsItalic.width(ch);
842 else
843 x += myFontMetrics.width(ch);
844
845 z++;
846 }
847 if (xPos - oldX < x - xPos && z > 0) {
848 z--;
849 // newXPos = oldX;
850 }// else newXPos = x;
851 return z;
852}
853
854int KateDocument::textWidth() {
855 return int(maxLength + 8);
856}
857
858int KateDocument::textHeight() {
859 return numLines()*fontHeight;
860}
861
862void KateDocument::insert(VConfig &c, const QString &s) {
863 int pos;
864 QChar ch;
865 QString buf;
866
867 if (s.isEmpty()) return;
868
869 recordStart(c, KateActionGroup::ugPaste);
870
871 pos = 0;
872 if (!(c.flags & KateView::cfVerticalSelect)) {
873 do {
874 ch = s[pos];
875 if (ch.isPrint() || ch == '\t') {
876 buf += ch; // append char to buffer
877 } else if (ch == '\n') {
878 recordAction(KateAction::newLine, c.cursor); // wrap contents behind cursor to new line
879 recordInsert(c, buf); // append to old line
880// c.cursor.x += buf.length();
881 buf.truncate(0); // clear buffer
882 c.cursor.y++;
883 c.cursor.x = 0;
884 }
885 pos++;
886 } while (pos < (int) s.length());
887 } else {
888 int xPos;
889
890 xPos = textWidth(c.cursor);
891 do {
892 ch = s[pos];
893 if (ch.isPrint() || ch == '\t') {
894 buf += ch;
895 } else if (ch == '\n') {
896 recordInsert(c, buf);
897 c.cursor.x += buf.length();
898 buf.truncate(0);
899 c.cursor.y++;
900 if (c.cursor.y >= numLines())
901 recordAction(KateAction::insLine, c.cursor);
902 c.cursor.x = textPos(getTextLine(c.cursor.y), xPos);
903 }
904 pos++;
905 } while (pos < (int) s.length());
906 }
907 recordInsert(c, buf);
908 c.cursor.x += buf.length();
909 recordEnd(c);
910}
911
912void KateDocument::insertFile(VConfig &c, QIODevice &dev)
913{
914 recordStart(c, KateActionGroup::ugPaste);
915
916 QString buf;
917 QChar ch, last;
918
919 QTextStream stream( &dev );
920
921 while ( !stream.atEnd() ) {
922 stream >> ch;
923
924 if (ch.isPrint() || ch == '\t') {
925 buf += ch;
926 } else if (ch == '\n' || ch == '\r') {
927 if (last != '\r' || ch != '\n') {
928 recordAction(KateAction::newLine, c.cursor);
929 recordInsert(c, buf);
930 buf.truncate(0);
931 c.cursor.y++;
932 c.cursor.x = 0;
933 }
934 last = ch;
935 }
936 }
937
938 recordInsert(c, buf);
939 recordEnd(c);
940}
941
942int KateDocument::currentColumn(PointStruc &cursor) {
943 return getTextLine(cursor.y)->cursorX(cursor.x,tabChars);
944}
945
946bool KateDocument::insertChars(VConfig &c, const QString &chars) {
947 int z, pos, l;
948 bool onlySpaces;
949 QChar ch;
950 QString buf;
951
952 TextLine::Ptr textLine = getTextLine(c.cursor.y);
953
954 pos = 0;
955 onlySpaces = true;
956 for (z = 0; z < (int) chars.length(); z++) {
957 ch = chars[z];
958 if (ch == '\t' && c.flags & KateView::cfReplaceTabs) {
959 l = tabChars - (textLine->cursorX(c.cursor.x, tabChars) % tabChars);
960 while (l > 0) {
961 buf.insert(pos, ' ');
962 pos++;
963 l--;
964 }
965 } else if (ch.isPrint() || ch == '\t') {
966 buf.insert(pos, ch);
967 pos++;
968 if (ch != ' ') onlySpaces = false;
969 if (c.flags & KateView::cfAutoBrackets) {
970 if (ch == '(') buf.insert(pos, ')');
971 if (ch == '[') buf.insert(pos, ']');
972 if (ch == '{') buf.insert(pos, '}');
973 }
974 }
975 }
976 //pos = cursor increment
977
978 //return false if nothing has to be inserted
979 if (buf.isEmpty()) return false;
980
981 //auto deletion of the marked text occurs not very often and can therefore
982 // be recorded separately
983 if (c.flags &KateView:: cfDelOnInput) delMarkedText(c);
984
985 recordStart(c, KateActionGroup::ugInsChar);
986 recordReplace(c/*.cursor*/, (c.flags & KateView::cfOvr) ? buf.length() : 0, buf);
987 c.cursor.x += pos;
988
989 if (myWordWrap && myWordWrapAt > 0) {
990 int line;
991 const QChar *s;
992// int pos;
993 PointStruc actionCursor;
994
995 line = c.cursor.y;
996 do {
997 textLine = getTextLine(line);
998 s = textLine->getText();
999 l = textLine->length();
1000 for (z = myWordWrapAt; z < l; z++) if (!s[z].isSpace()) break; //search for text to wrap
1001 if (z >= l) break; // nothing more to wrap
1002 pos = myWordWrapAt;
1003 for (; z >= 0; z--) { //find wrap position
1004 if (s[z].isSpace()) {
1005 pos = z + 1;
1006 break;
1007 }
1008 }
1009 //pos = wrap position
1010
1011 if (line == c.cursor.y && pos <= c.cursor.x) {
1012 //wrap cursor
1013 c.cursor.y++;
1014 c.cursor.x -= pos;
1015 }
1016
1017 if (line == lastLine() || (getTextLine(line+1)->length() == 0) ) {
1018 //at end of doc: create new line
1019 actionCursor.x = pos;
1020 actionCursor.y = line;
1021 recordAction(KateAction::newLine,actionCursor);
1022 } else {
1023 //wrap
1024 actionCursor.y = line + 1;
1025 if (!s[l - 1].isSpace()) { //add space in next line if necessary
1026 actionCursor.x = 0;
1027 recordInsert(actionCursor, " ");
1028 }
1029 actionCursor.x = textLine->length() - pos;
1030 recordAction(KateAction::wordWrap, actionCursor);
1031 }
1032 line++;
1033 } while (true);
1034 }
1035 recordEnd(c);
1036 return true;
1037}
1038
1039QString tabString(int pos, int tabChars) {
1040 QString s;
1041 while (pos >= tabChars) {
1042 s += '\t';
1043 pos -= tabChars;
1044 }
1045 while (pos > 0) {
1046 s += ' ';
1047 pos--;
1048 }
1049 return s;
1050}
1051
1052void KateDocument::newLine(VConfig &c) {
1053
1054 //auto deletion of marked text is done by the view to have a more
1055 // "low level" KateDocument::newLine method
1056 recordStart(c, KateActionGroup::ugInsLine);
1057
1058 if (!(c.flags & KateView::cfAutoIndent)) {
1059 recordAction(KateAction::newLine,c.cursor);
1060 c.cursor.y++;
1061 c.cursor.x = 0;
1062 } else {
1063 TextLine::Ptr textLine = getTextLine(c.cursor.y);
1064 int pos = textLine->firstChar();
1065 if (c.cursor.x < pos) c.cursor.x = pos; // place cursor on first char if before
1066
1067 int y = c.cursor.y;
1068 while ((y > 0) && (pos < 0)) { // search a not empty text line
1069 textLine = getTextLine(--y);
1070 pos = textLine->firstChar();
1071 }
1072 recordAction(KateAction::newLine, c.cursor);
1073 c.cursor.y++;
1074 c.cursor.x = 0;
1075 if (pos > 0) {
1076 pos = textLine->cursorX(pos, tabChars);
1077// if (getTextLine(c.cursor.y)->length() > 0) {
1078 QString s = tabString(pos, (c.flags & KateView::cfSpaceIndent) ? 0xffffff : tabChars);
1079 recordInsert(c.cursor, s);
1080 pos = s.length();
1081// }
1082// recordInsert(c.cursor, QString(textLine->getText(), pos));
1083 c.cursor.x = pos;
1084 }
1085 }
1086
1087 recordEnd(c);
1088}
1089
1090void KateDocument::killLine(VConfig &c) {
1091
1092 recordStart(c, KateActionGroup::ugDelLine);
1093 c.cursor.x = 0;
1094 recordDelete(c.cursor, 0xffffff);
1095 if (c.cursor.y < lastLine()) {
1096 recordAction(KateAction::killLine, c.cursor);
1097 }
1098 recordEnd(c);
1099}
1100
1101void KateDocument::backspace(VConfig &c) {
1102
1103 if (c.cursor.x <= 0 && c.cursor.y <= 0) return;
1104
1105 if (c.cursor.x > 0) {
1106 recordStart(c, KateActionGroup::ugDelChar);
1107 if (!(c.flags & KateView::cfBackspaceIndents)) {
1108 // ordinary backspace
1109 c.cursor.x--;
1110 recordDelete(c.cursor, 1);
1111 } else {
1112 // backspace indents: erase to next indent position
1113 int l = 1; // del one char
1114
1115 TextLine::Ptr textLine = getTextLine(c.cursor.y);
1116 int pos = textLine->firstChar();
1117 if (pos < 0 || pos >= c.cursor.x) {
1118 // only spaces on left side of cursor
1119 // search a line with less spaces
1120 int y = c.cursor.y;
1121 while (y > 0) {
1122 textLine = getTextLine(--y);
1123 pos = textLine->firstChar();
1124 if (pos >= 0 && pos < c.cursor.x) {
1125 l = c.cursor.x - pos; // del more chars
1126 break;
1127 }
1128 }
1129 }
1130 // break effectively jumps here
1131 c.cursor.x -= l;
1132 recordDelete(c.cursor, l);
1133 }
1134 } else {
1135 // c.cursor.x == 0: wrap to previous line
1136 recordStart(c, KateActionGroup::ugDelLine);
1137 c.cursor.y--;
1138 c.cursor.x = getTextLine(c.cursor.y)->length();
1139 recordAction(KateAction::delLine,c.cursor);
1140 }
1141 recordEnd(c);
1142}
1143
1144
1145void KateDocument::del(VConfig &c) {
1146 TextLine::Ptr textLine = getTextLine(c.cursor.y);
1147 int len = (c.flags & KateView::cfRemoveSpaces) ? textLine->lastChar() : textLine->length();
1148 if (c.cursor.x < len/*getTextLine(c.cursor.y)->length()*/) {
1149 // delete one character
1150 recordStart(c, KateActionGroup::ugDelChar);
1151 recordDelete(c.cursor, 1);
1152 recordEnd(c);
1153 } else {
1154 if (c.cursor.y < lastLine()) {
1155 // wrap next line to this line
1156 textLine->truncate(c.cursor.x); // truncate spaces
1157 recordStart(c, KateActionGroup::ugDelLine);
1158 recordAction(KateAction::delLine,c.cursor);
1159 recordEnd(c);
1160 }
1161 }
1162}
1163
1164void KateDocument::clear() {
1165 PointStruc cursor;
1166 KateView *view;
1167
1168 setPseudoModal(0L);
1169 cursor.x = cursor.y = 0;
1170 for (view = views.first(); view != 0L; view = views.next() ) {
1171 view->updateCursor(cursor);
1172 view->tagAll();
1173 }
1174
1175 eolMode = KateDocument::eolUnix;
1176
1177 buffer->clear();
1178 longestLine = buffer->line(0);
1179
1180 maxLength = 0;
1181
1182 select.x = -1;
1183
1184 selectStart = 0xffffff;
1185 selectEnd = 0;
1186 oldMarkState = false;
1187
1188 setModified(false);
1189
1190 undoList.clear();
1191 currentUndo = 0;
1192 newUndo();
1193}
1194
1195void KateDocument::cut(VConfig &c) {
1196
1197 if (selectEnd < selectStart) return;
1198
1199 copy(c.flags);
1200 delMarkedText(c);
1201}
1202
1203void KateDocument::copy(int flags) {
1204
1205 if (selectEnd < selectStart) return;
1206
1207 QString s = markedText(flags);
1208 if (!s.isEmpty()) {
1209//#if defined(_WS_X11_)
1210 if (m_singleSelection)
1211 disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), this, 0);
1212//#endif
1213 QApplication::clipboard()->setText(s);
1214//#if defined(_WS_X11_)
1215 if (m_singleSelection) {
1216 connect(QApplication::clipboard(), SIGNAL(dataChanged()),
1217 this, SLOT(clipboardChanged()));
1218 }
1219//#endif
1220 }
1221}
1222
1223void KateDocument::paste(VConfig &c) {
1224 QString s = QApplication::clipboard()->text();
1225 if (!s.isEmpty()) {
1226 insert(c, s);
1227 }
1228}
1229
1230void KateDocument::toggleRect(int start, int end, int x1, int x2) {
1231 int z, line;
1232 bool t;
1233
1234 if (x1 > x2) {
1235 z = x1;
1236 x1 = x2;
1237 x2 = z;
1238 }
1239 if (start > end) {
1240 z = start;
1241 start = end;
1242 end = z;
1243 }
1244
1245 t = false;
1246 for (line = start; line < end; line++) {
1247 int x, oldX, s, e, newX1, newX2;
1248 QChar ch;
1249 Attribute *a;
1250
1251 TextLine::Ptr textLine = getTextLine(line);
1252
1253 //--- speed optimization
1254 //s = textPos(textLine, x1, newX1);
1255 x = oldX = z = 0;
1256 while (x < x1) { // && z < len) {
1257 oldX = x;
1258 ch = textLine->getChar(z);
1259 a = &m_attribs[textLine->getAttr(z)];
1260
1261 if (ch == '\t')
1262 x += m_tabWidth - (x % m_tabWidth);
1263 else if (a->bold && a->italic)
1264 x += myFontMetricsBI.width(ch);
1265 else if (a->bold)
1266 x += myFontMetricsBold.width(ch);
1267 else if (a->italic)
1268 x += myFontMetricsItalic.width(ch);
1269 else
1270 x += myFontMetrics.width(ch);
1271
1272 z++;
1273 }
1274 s = z;
1275 if (x1 - oldX < x - x1 && z > 0) {
1276 s--;
1277 newX1 = oldX;
1278 } else newX1 = x;
1279 //e = textPos(textLine, x2, newX2);
1280 while (x < x2) { // && z < len) {
1281 oldX = x;
1282 ch = textLine->getChar(z);
1283 a = &m_attribs[textLine->getAttr(z)];
1284
1285 if (ch == '\t')
1286 x += m_tabWidth - (x % m_tabWidth);
1287 else if (a->bold && a->italic)
1288 x += myFontMetricsBI.width(ch);
1289 else if (a->bold)
1290 x += myFontMetricsBold.width(ch);
1291 else if (a->italic)
1292 x += myFontMetricsItalic.width(ch);
1293 else
1294 x += myFontMetrics.width(ch);
1295
1296 z++;
1297 }
1298 e = z;
1299 if (x2 - oldX < x - x2 && z > 0) {
1300 e--;
1301 newX2 = oldX;
1302 } else newX2 = x;
1303 //---
1304
1305 if (e > s) {
1306 textLine->toggleSelect(s, e);
1307 tagLineRange(line, newX1, newX2);
1308 t = true;
1309 }
1310 }
1311 if (t) {
1312 end--;
1313// tagLines(start, end);
1314
1315 if (start < selectStart) selectStart = start;
1316 if (end > selectEnd) selectEnd = end;
1317 emit selectionChanged();
1318 }
1319}
1320
1321void KateDocument::selectTo(VConfig &c, PointStruc &cursor, int cXPos) {
1322 //c.cursor = old cursor position
1323 //cursor = new cursor position
1324
1325 if (c.cursor.x != select.x || c.cursor.y != select.y) {
1326 //new selection
1327
1328 if (!(c.flags & KateView::cfKeepSelection)) deselectAll();
1329// else recordReset();
1330
1331 anchor = c.cursor;
1332 aXPos = c.cXPos;
1333 }
1334
1335 if (!(c.flags & KateView::cfVerticalSelect)) {
1336 //horizontal selections
1337 int x, y, sXPos;
1338 int ex, ey, eXPos;
1339 bool sel;
1340
1341 if (cursor.y > c.cursor.y || (cursor.y == c.cursor.y && cursor.x > c.cursor.x)) {
1342 x = c.cursor.x;
1343 y = c.cursor.y;
1344 sXPos = c.cXPos;
1345 ex = cursor.x;
1346 ey = cursor.y;
1347 eXPos = cXPos;
1348 sel = true;
1349 } else {
1350 x = cursor.x;
1351 y = cursor.y;
1352 sXPos = cXPos;
1353 ex = c.cursor.x;
1354 ey = c.cursor.y;
1355 eXPos = c.cXPos;
1356 sel = false;
1357 }
1358
1359// tagLines(y, ye);
1360 if (y < ey) {
1361 //tagLineRange(y, sXPos, 0xffffff);
1362 tagLines(y, ey -1);
1363 tagLineRange(ey, 0, eXPos);
1364 } else tagLineRange(y, sXPos, eXPos);
1365
1366 if (y < selectStart) selectStart = y;
1367 if (ey > selectEnd) selectEnd = ey;
1368
1369 TextLine::Ptr textLine = getTextLine(y);
1370
1371 if (c.flags & KateView::cfXorSelect) {
1372 //xor selection with old selection
1373 while (y < ey) {
1374 textLine->toggleSelectEol(x);
1375 x = 0;
1376 y++;
1377 textLine = getTextLine(y);
1378 }
1379 textLine->toggleSelect(x, ex);
1380 } else {
1381 //set selection over old selection
1382
1383 if (anchor.y > y || (anchor.y == y && anchor.x > x)) {
1384 if (anchor.y < ey || (anchor.y == ey && anchor.x < ex)) {
1385 sel = !sel;
1386 while (y < anchor.y) {
1387 textLine->selectEol(sel, x);
1388 x = 0;
1389 y++;
1390 textLine = getTextLine(y);
1391 }
1392 textLine->select(sel, x, anchor.x);
1393 x = anchor.x;
1394 }
1395 sel = !sel;
1396 }
1397 while (y < ey) {
1398 textLine->selectEol(sel, x);
1399 x = 0;
1400 y++;
1401 textLine = getTextLine(y);
1402 }
1403 textLine->select(sel, x, ex);
1404 }
1405 } else {
1406 //vertical (block) selections
1407// int ax, sx, ex;
1408
1409// ax = textWidth(anchor);
1410// sx = textWidth(start);
1411// ex = textWidth(end);
1412
1413 toggleRect(c.cursor.y + 1, cursor.y + 1, aXPos, c.cXPos);
1414 toggleRect(anchor.y, cursor.y + 1, c.cXPos, cXPos);
1415 }
1416 select = cursor;
1417 optimizeSelection();
1418 emit selectionChanged();
1419}
1420
1421
1422void KateDocument::selectAll() {
1423 int z;
1424 TextLine::Ptr textLine;
1425
1426 select.x = -1;
1427
1428// if (selectStart != 0 || selectEnd != lastLine()) recordReset();
1429
1430 selectStart = 0;
1431 selectEnd = lastLine();
1432
1433 tagLines(selectStart,selectEnd);
1434
1435 for (z = selectStart; z < selectEnd; z++) {
1436 textLine = getTextLine(z);
1437 textLine->selectEol(true,0);
1438 }
1439 textLine = getTextLine(z);
1440 textLine->select(true,0,textLine->length());
1441 emit selectionChanged();
1442}
1443
1444void KateDocument::deselectAll() {
1445 select.x = -1;
1446 if (selectEnd < selectStart) return;
1447
1448// recordReset();
1449
1450 tagLines(selectStart,selectEnd);
1451
1452 for (int z = selectStart; z <= selectEnd; z++) {
1453 TextLine::Ptr textLine = getTextLine(z);
1454 textLine->selectEol(false,0);
1455 }
1456 selectStart = 0xffffff;
1457 selectEnd = 0;
1458 emit selectionChanged();
1459}
1460
1461void KateDocument::invertSelection() {
1462 TextLine::Ptr textLine;
1463
1464 select.x = -1;
1465
1466// if (selectStart != 0 || selectEnd != lastLine()) recordReset();
1467
1468 selectStart = 0;
1469 selectEnd = lastLine();
1470
1471 tagLines(selectStart,selectEnd);
1472
1473 for (int z = selectStart; z < selectEnd; z++) {
1474 textLine = getTextLine(z);
1475 textLine->toggleSelectEol(0);
1476 }
1477 textLine = getTextLine(selectEnd);
1478 textLine->toggleSelect(0,textLine->length());
1479 optimizeSelection();
1480 emit selectionChanged();
1481}
1482
1483void KateDocument::selectWord(PointStruc &cursor, int flags) {
1484 int start, end, len;
1485
1486 TextLine::Ptr textLine = getTextLine(cursor.y);
1487 len = textLine->length();
1488 start = end = cursor.x;
1489 while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--;
1490 while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++;
1491 if (end <= start) return;
1492 if (!(flags & KateView::cfKeepSelection)) deselectAll();
1493// else recordReset();
1494
1495 textLine->select(true, start, end);
1496
1497 anchor.x = start;
1498 select.x = end;
1499 anchor.y = select.y = cursor.y;
1500 tagLines(cursor.y, cursor.y);
1501 if (cursor.y < selectStart) selectStart = cursor.y;
1502 if (cursor.y > selectEnd) selectEnd = cursor.y;
1503 emit selectionChanged();
1504}
1505
1506void KateDocument::selectLength(PointStruc &cursor, int length, int flags) {
1507 int start, end;
1508
1509 TextLine::Ptr textLine = getTextLine(cursor.y);
1510 start = cursor.x;
1511 end = start + length;
1512 if (end <= start) return;
1513 if (!(flags & KateView::cfKeepSelection)) deselectAll();
1514
1515 textLine->select(true, start, end);
1516
1517 anchor.x = start;
1518 select.x = end;
1519 anchor.y = select.y = cursor.y;
1520 tagLines(cursor.y, cursor.y);
1521 if (cursor.y < selectStart) selectStart = cursor.y;
1522 if (cursor.y > selectEnd) selectEnd = cursor.y;
1523 emit selectionChanged();
1524}
1525
1526void KateDocument::doIndent(VConfig &c, int change) {
1527
1528 c.cursor.x = 0;
1529
1530 recordStart(c, (change < 0) ? KateActionGroup::ugUnindent
1531 : KateActionGroup::ugIndent);
1532
1533 if (selectEnd < selectStart) {
1534 // single line
1535 optimizeLeadingSpace(c.cursor.y, c.flags, change);
1536 } else {
1537 // entire selection
1538 TextLine::Ptr textLine;
1539 int line, z;
1540 QChar ch;
1541
1542 if (c.flags & KateView::cfKeepIndentProfile && change < 0) {
1543 // unindent so that the existing indent profile doesn´t get screwed
1544 // if any line we may unindent is already full left, don't do anything
1545 for (line = selectStart; line <= selectEnd; line++) {
1546 textLine = getTextLine(line);
1547 if (textLine->isSelected() || textLine->numSelected()) {
1548 for (z = 0; z < tabChars; z++) {
1549 ch = textLine->getChar(z);
1550 if (ch == '\t') break;
1551 if (ch != ' ') {
1552 change = 0;
1553 goto jumpOut;
1554 }
1555 }
1556 }
1557 }
1558 jumpOut:;
1559 }
1560
1561 for (line = selectStart; line <= selectEnd; line++) {
1562 textLine = getTextLine(line);
1563 if (textLine->isSelected() || textLine->numSelected()) {
1564 optimizeLeadingSpace(line, c.flags, change);
1565 }
1566 }
1567 }
1568 // recordEnd now removes empty undo records
1569 recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent);
1570}
1571
1572/*
1573 Optimize the leading whitespace for a single line.
1574 If change is > 0, it adds indentation units (tabChars)
1575 if change is == 0, it only optimizes
1576 If change is < 0, it removes indentation units
1577 This will be used to indent, unindent, and optimal-fill a line.
1578 If excess space is removed depends on the flag cfKeepExtraSpaces
1579 which has to be set by the user
1580*/
1581void KateDocument::optimizeLeadingSpace(int line, int flags, int change) {
1582 int len;
1583 int chars, space, okLen;
1584 QChar ch;
1585 int extra;
1586 QString s;
1587 PointStruc cursor;
1588
1589 TextLine::Ptr textLine = getTextLine(line);
1590 len = textLine->length();
1591 space = 0; // length of space at the beginning of the textline
1592 okLen = 0; // length of space which does not have to be replaced
1593 for (chars = 0; chars < len; chars++) {
1594 ch = textLine->getChar(chars);
1595 if (ch == ' ') {
1596 space++;
1597 if (flags & KateView::cfSpaceIndent && okLen == chars) okLen++;
1598 } else if (ch == '\t') {
1599 space += tabChars - space % tabChars;
1600 if (!(flags & KateView::cfSpaceIndent) && okLen == chars) okLen++;
1601 } else break;
1602 }
1603
1604 space += change*tabChars; // modify space width
1605 // if line contains only spaces it will be cleared
1606 if (space < 0 || chars == len) space = 0;
1607
1608 extra = space % tabChars; // extra spaces which don´t fit the indentation pattern
1609 if (flags & KateView::cfKeepExtraSpaces) chars -= extra;
1610
1611 if (flags & KateView::cfSpaceIndent) {
1612 space -= extra;
1613 ch = ' ';
1614 } else {
1615 space /= tabChars;
1616 ch = '\t';
1617 }
1618
1619 // don´t replace chars which are already ok
1620 cursor.x = QMIN(okLen, QMIN(chars, space));
1621 chars -= cursor.x;
1622 space -= cursor.x;
1623 if (chars == 0 && space == 0) return; //nothing to do
1624
1625 s.fill(ch, space);
1626
1627//printf("chars %d insert %d cursor.x %d\n", chars, insert, cursor.x);
1628 cursor.y = line;
1629 recordReplace(cursor, chars, s);
1630}
1631
1632void KateDocument::doComment(VConfig &c, int change)
1633{
1634 c.flags |=KateView:: cfPersistent;
1635
1636 recordStart(c, (change < 0) ? KateActionGroup::ugUncomment
1637 : KateActionGroup::ugComment);
1638
1639 QString startComment = m_highlight->getCommentStart();
1640 QString startLineComment = m_highlight->getCommentSingleLineStart();
1641 QString endComment = m_highlight->getCommentEnd();
1642
1643 int startCommentLen = startComment.length();
1644 int startLineCommentLen = startLineComment.length();
1645 int endCommentLen = endComment.length();
1646
1647 if (change > 0)
1648 {
1649 if ( !hasMarkedText() )
1650 {
1651 if (startLineComment != "")
1652 {
1653 // Add a start comment mark
1654 c.cursor.x = 0;
1655 recordReplace(c.cursor, 0, startLineComment);
1656 }
1657 else if ((startComment != "") && (endComment != ""))
1658 {
1659 // Add a start comment mark
1660 c.cursor.x = 0;
1661 recordReplace(c.cursor, 0, startComment);
1662
1663 // Add an end comment mark
1664 TextLine* textline = getTextLine(c.cursor.y);
1665 c.cursor.x = textline->length();
1666 recordReplace(c.cursor, 0, endComment);
1667 c.cursor.x = 0;
1668 }
1669 }
1670 else if ((startComment != "") && (endComment != ""))
1671 {
1672 QString marked (c.view->markedText ());
1673 int preDeleteLine = -1, preDeleteCol = -1;
1674 c.view->getCursorPosition (&preDeleteLine, &preDeleteCol);
1675
1676 if (marked.length() > 0)
1677 c.view->keyDelete ();
1678
1679 int line = -1, col = -1;
1680 c.view->getCursorPosition (&line, &col);
1681
1682 c.view->insertText (startComment + marked + endComment);
1683 }
1684 }
1685 else
1686 {
1687 if ( !hasMarkedText() )
1688 {
1689 TextLine* textline = getTextLine(c.cursor.y);
1690
1691 if(textline->startingWith(startLineComment))
1692 {
1693 // Remove start comment mark
1694 c.cursor.x = 0;
1695 recordReplace(c.cursor, startLineCommentLen, "");
1696 }
1697 else if (textline->startingWith(startComment) && textline->endingWith(endComment))
1698 {
1699 // Remove start comment mark
1700 c.cursor.x = 0;
1701 recordReplace(c.cursor, startCommentLen, "");
1702
1703 // Remove end comment mark
1704 if(endComment != "")
1705 {
1706 c.cursor.x = textline->length() - endCommentLen;
1707 recordReplace(c.cursor, endCommentLen, "");
1708 c.cursor.x = 0;
1709 }
1710 }
1711 }
1712 else
1713 {
1714 QString marked (c.view->markedText ());
1715 int preDeleteLine = -1, preDeleteCol = -1;
1716 c.view->getCursorPosition (&preDeleteLine, &preDeleteCol);
1717
1718 int start = marked.find (startComment);
1719 int end = marked.findRev (endComment);
1720
1721 if ((start > -1) && (end > -1))
1722 {
1723 marked.remove (start, startCommentLen);
1724 marked.remove (end-startCommentLen, endCommentLen);
1725
1726 c.view->keyDelete ();
1727
1728 int line = -1, col = -1;
1729 c.view->getCursorPosition (&line, &col);
1730 c.view->insertText (marked);
1731 }
1732 }
1733 }
1734
1735 recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent);
1736}
1737
1738
1739QString KateDocument::text() const
1740{
1741 QString s;
1742
1743 for (int i=0; i < buffer->count(); i++)
1744 {
1745 TextLine::Ptr textLine = buffer->line(i);
1746 s.insert(s.length(), textLine->getText(), textLine->length());
1747 if ( (i < (buffer->count()-1)) )
1748 s.append('\n');
1749 }
1750
1751 return s;
1752}
1753
1754QString KateDocument::getWord(PointStruc &cursor) {
1755 int start, end, len;
1756
1757 TextLine::Ptr textLine = getTextLine(cursor.y);
1758 len = textLine->length();
1759 start = end = cursor.x;
1760 while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--;
1761 while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++;
1762 len = end - start;
1763 return QString(&textLine->getText()[start], len);
1764}
1765
1766void KateDocument::setText(const QString &s) {
1767 int pos;
1768 QChar ch;
1769
1770 clear();
1771
1772 int line=1;
1773
1774 TextLine::Ptr textLine = buffer->line(0);
1775 for (pos = 0; pos <= (int) s.length(); pos++) {
1776 ch = s[pos];
1777 if (ch.isPrint() || ch == '\t') {
1778 textLine->append(&ch, 1);
1779 } else if (ch == '\n')
1780 {
1781 textLine = new TextLine();
1782 buffer->insertLine (line, textLine);
1783 line++;
1784 }
1785 }
1786 updateLines();
1787}
1788
1789
1790QString KateDocument::markedText(int flags) {
1791 TextLine::Ptr textLine;
1792 int len, z, start, end, i;
1793
1794 len = 1;
1795 if (!(flags & KateView::cfVerticalSelect)) {
1796 for (z = selectStart; z <= selectEnd; z++) {
1797 textLine = getTextLine(z);
1798 len += textLine->numSelected();
1799 if (textLine->isSelected()) len++;
1800 }
1801 QString s;
1802 len = 0;
1803 for (z = selectStart; z <= selectEnd; z++) {
1804 textLine = getTextLine(z);
1805 end = 0;
1806 do {
1807 start = textLine->findUnselected(end);
1808 end = textLine->findSelected(start);
1809 for (i = start; i < end; i++) {
1810 s[len] = textLine->getChar(i);
1811 len++;
1812 }
1813 } while (start < end);
1814 if (textLine->isSelected()) {
1815 s[len] = '\n';
1816 len++;
1817 }
1818 }
1819// s[len] = '\0';
1820 return s;
1821 } else {
1822 for (z = selectStart; z <= selectEnd; z++) {
1823 textLine = getTextLine(z);
1824 len += textLine->numSelected() + 1;
1825 }
1826 QString s;
1827 len = 0;
1828 for (z = selectStart; z <= selectEnd; z++) {
1829 textLine = getTextLine(z);
1830 end = 0;
1831 do {
1832 start = textLine->findUnselected(end);
1833 end = textLine->findSelected(start);
1834 for (i = start; i < end; i++) {
1835 s[len] = textLine->getChar(i);
1836 len++;
1837 }
1838 } while (start < end);
1839 s[len] = '\n';
1840 len++;
1841 }
1842// s[len] = '\0'; // the final \0 is not counted in length()
1843 return s;
1844 }
1845}
1846
1847void KateDocument::delMarkedText(VConfig &c/*, bool undo*/) {
1848 int end = 0;
1849
1850 if (selectEnd < selectStart) return;
1851
1852 // the caller may have already started an undo record for the current action
1853// if (undo)
1854
1855 //auto deletion of the marked text occurs not very often and can therefore
1856 // be recorded separately
1857 recordStart(c, KateActionGroup::ugDelBlock);
1858
1859 for (c.cursor.y = selectEnd; c.cursor.y >= selectStart; c.cursor.y--) {
1860 TextLine::Ptr textLine = getTextLine(c.cursor.y);
1861
1862 c.cursor.x = textLine->length();
1863 do {
1864 end = textLine->findRevUnselected(c.cursor.x);
1865 if (end == 0) break;
1866 c.cursor.x = textLine->findRevSelected(end);
1867 recordDelete(c.cursor, end - c.cursor.x);
1868 } while (true);
1869 end = c.cursor.x;
1870 c.cursor.x = textLine->length();
1871 if (textLine->isSelected()) recordAction(KateAction::delLine,c.cursor);
1872 }
1873 c.cursor.y++;
1874 /*if (end < c.cursor.x)*/ c.cursor.x = end;
1875
1876 selectEnd = -1;
1877 select.x = -1;
1878
1879 /*if (undo)*/ recordEnd(c);
1880}
1881
1882void KateDocument::tagLineRange(int line, int x1, int x2) {
1883 int z;
1884
1885 for (z = 0; z < (int) views.count(); z++) {
1886 views.at(z)->tagLines(line, line, x1, x2);
1887 }
1888}
1889
1890void KateDocument::tagLines(int start, int end) {
1891 int z;
1892
1893 for (z = 0; z < (int) views.count(); z++) {
1894 views.at(z)->tagLines(start, end, 0, 0xffffff);
1895 }
1896}
1897
1898void KateDocument::tagAll() {
1899 int z;
1900
1901 for (z = 0; z < (int) views.count(); z++) {
1902 views.at(z)->tagAll();
1903 }
1904}
1905
1906void KateDocument::updateLines(int startLine, int endLine, int flags, int cursorY) {
1907 TextLine::Ptr textLine;
1908 int line, last_line;
1909 int ctxNum, endCtx;
1910// kdDebug(13020)<<"******************KateDocument::updateLines Checkpoint 1"<<endl;
1911 if (buffer->line(startLine)==0) {kdDebug(13020)<<"********************No buffer for line " << startLine << " found**************"<<endl; return;};
1912// kdDebug(13020)<<"KateDocument::updateLines Checkpoint 2"<<endl;
1913 last_line = lastLine();
1914// if (endLine >= last_line) endLine = last_line;
1915
1916 line = startLine;
1917 ctxNum = 0;
1918 if (line > 0) ctxNum = getTextLine(line - 1)->getContext();
1919 do {
1920// kdDebug(13020)<<QString("**************Working on line: %1").arg(line)<<endl;
1921 textLine = getTextLine(line);
1922 if (textLine==0) kdDebug(13020)<<"****updateLines()>> error textLine==0"<<endl;
1923 if (line <= endLine && line != cursorY) {
1924 if (flags & KateView::cfRemoveSpaces) textLine->removeSpaces();
1925 updateMaxLength(textLine);
1926 }
1927 endCtx = textLine->getContext();
1928 qDebug("DOHIGHLIGHT");
1929 ctxNum = m_highlight->doHighlight(ctxNum,textLine);
1930 textLine->setContext(ctxNum);
1931 line++;
1932 } while ((buffer->line(line)!=0) && (line <= endLine || endCtx != ctxNum));
1933// kdDebug(13020)<<"updateLines :: while loop left"<<endl;
1934 tagLines(startLine, line - 1);
1935}
1936
1937
1938void KateDocument::updateMaxLength(TextLine::Ptr &textLine) {
1939 int len;
1940
1941 len = textWidth(textLine,textLine->length());
1942
1943 if (len > maxLength) {
1944 longestLine = textLine;
1945 maxLength = len;
1946 newDocGeometry = true;
1947 } else {
1948 if (!longestLine || (textLine == longestLine && len <= maxLength*3/4)) {
1949 maxLength = -1;
1950 for (int i = 0; i < numLines();i++) {
1951 textLine = getTextLine(i);
1952 len = textWidth(textLine,textLine->length());
1953 if (len > maxLength) {
1954 maxLength = len;
1955 longestLine = textLine;
1956 }
1957 }
1958 newDocGeometry = true;
1959 }
1960 }
1961}
1962
1963void KateDocument::slotBufferChanged() {
1964 newDocGeometry = true;
1965 //updateLines();//JW
1966 updateViews();
1967}
1968
1969void KateDocument::slotBufferHighlight(long start,long stop) {
1970 kdDebug(13020)<<"KateDocument::slotBufferHighlight"<<QString("%1-%2").arg(start).arg(stop)<<endl;
1971 updateLines(start,stop);
1972// buffer->startLoadTimer();
1973}
1974
1975void KateDocument::updateViews(KateView *exclude) {
1976 KateView *view;
1977 int flags;
1978 bool markState = hasMarkedText();
1979
1980 flags = (newDocGeometry) ? KateView::ufDocGeometry : 0;
1981 for (view = views.first(); view != 0L; view = views.next() ) {
1982 if (view != exclude) view->updateView(flags);
1983
1984 // notify every view about the changed mark state....
1985 if (oldMarkState != markState) emit view->newMarkStatus();
1986 }
1987 oldMarkState = markState;
1988 newDocGeometry = false;
1989}
1990
1991QColor &KateDocument::cursorCol(int x, int y) {
1992 int attr;
1993 Attribute *a;
1994
1995 TextLine::Ptr textLine = getTextLine(y);
1996 attr = textLine->getRawAttr(x);
1997 a = &m_attribs[attr & taAttrMask];
1998 if (attr & taSelected) return a->selCol; else return a->col;
1999}
2000
2001void KateDocument::paintTextLine(QPainter &paint, int line, int xStart, int xEnd, bool showTabs)
2002{
2003 paintTextLine (paint, line, 0, xStart, xEnd, showTabs);
2004}
2005
2006void KateDocument::paintTextLine(QPainter &paint, int line, int y, int xStart, int xEnd, bool showTabs)
2007{
2008 TextLine::Ptr textLine;
2009 int len;
2010 const QChar *s;
2011 int z, x;
2012 QChar ch;
2013 Attribute *a = 0L;
2014 int attr, nextAttr;
2015 int xs;
2016 int xc, zc;
2017
2018 if (line > lastLine()) {
2019 paint.fillRect(0, y, xEnd - xStart,fontHeight, colors[0]);
2020 return;
2021 }
2022
2023 textLine = getTextLine(line);
2024 len = textLine->length();
2025 s = textLine->getText();
2026
2027 // skip to first visible character
2028 x = 0;
2029 z = 0;
2030 do {
2031 xc = x;
2032 zc = z;
2033 if (z == len) break;
2034 ch = s[z];//textLine->getChar(z);
2035 if (ch == '\t') {
2036 x += m_tabWidth - (x % m_tabWidth);
2037 } else {
2038 a = &m_attribs[textLine->getAttr(z)];
2039
2040 if (a->bold && a->italic)
2041 x += myFontMetricsBI.width(ch);
2042 else if (a->bold)
2043 x += myFontMetricsBold.width(ch);
2044 else if (a->italic)
2045 x += myFontMetricsItalic.width(ch);
2046 else
2047 x += myFontMetrics.width(ch);
2048 }
2049 z++;
2050 } while (x <= xStart);
2051
2052 // draw background
2053 xs = xStart;
2054 attr = textLine->getRawAttr(zc);
2055 while (x < xEnd)
2056 {
2057 nextAttr = textLine->getRawAttr(z);
2058 if ((nextAttr ^ attr) & taSelected)
2059 {
2060 if (attr & taSelected)
2061 paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[1]);
2062 else
2063 paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[0]);
2064
2065 xs = x;
2066 attr = nextAttr;
2067 }
2068
2069 if (z == len) break;
2070
2071 ch = s[z];//textLine->getChar(z);
2072
2073 if (ch == '\t')
2074 x += m_tabWidth - (x % m_tabWidth);
2075 else
2076 {
2077 a = &m_attribs[textLine->getAttr(z)];
2078
2079 if (a->bold && a->italic)
2080 x += myFontMetricsBI.width(ch);
2081 else if (a->bold)
2082 x += myFontMetricsBold.width(ch);
2083 else if (a->italic)
2084 x += myFontMetricsItalic.width(ch);
2085 else
2086 x += myFontMetrics.width(ch);
2087 }
2088 z++;
2089 }
2090
2091 if (attr & taSelected)
2092 paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[1]);
2093 else
2094 paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[0]);
2095
2096 len = z; //reduce length to visible length
2097
2098 // draw text
2099 x = xc;
2100 z = zc;
2101 y += fontAscent;// -1;
2102 attr = -1;
2103 while (z < len) {
2104 ch = s[z];//textLine->getChar(z);
2105 if (ch == '\t') {
2106 if (z > zc) {
2107 //this should cause no copy at all
2108 QConstString str((QChar *) &s[zc], z - zc /*+1*/);
2109 QString s = str.string();
2110 paint.drawText(x - xStart, y, s);
2111
2112 if (a->bold && a->italic)
2113 x += myFontMetricsBI.width(s);
2114 else if (a->bold)
2115 x += myFontMetricsBold.width(s);
2116 else if (a->italic)
2117 x += myFontMetricsItalic.width(s);
2118 else
2119 x += myFontMetrics.width(s);
2120 }
2121 zc = z +1;
2122
2123 if (showTabs) {
2124 nextAttr = textLine->getRawAttr(z);
2125 if (nextAttr != attr) {
2126 attr = nextAttr;
2127 a = &m_attribs[attr & taAttrMask];
2128
2129 if (attr & taSelected) paint.setPen(a->selCol);
2130 else paint.setPen(a->col);
2131
2132 if (a->bold && a->italic)
2133 paint.setFont(myFontBI);
2134 else if (a->bold)
2135 paint.setFont(myFontBold);
2136 else if (a->italic)
2137 paint.setFont(myFontItalic);
2138 else
2139 paint.setFont(myFont);
2140 }
2141
2142// paint.drawLine(x - xStart, y -2, x - xStart, y);
2143// paint.drawLine(x - xStart, y, x - xStart + 2, y);
2144 paint.drawPoint(x - xStart, y);
2145 paint.drawPoint(x - xStart +1, y);
2146 paint.drawPoint(x - xStart, y -1);
2147 }
2148 x += m_tabWidth - (x % m_tabWidth);
2149 } else {
2150 nextAttr = textLine->getRawAttr(z);
2151 if (nextAttr != attr) {
2152 if (z > zc) {
2153 QConstString str((QChar *) &s[zc], z - zc /*+1*/);
2154 QString s = str.string();
2155 paint.drawText(x - xStart, y, s);
2156
2157 if (a->bold && a->italic)
2158 x += myFontMetricsBI.width(s);
2159 else if (a->bold)
2160 x += myFontMetricsBold.width(s);
2161 else if (a->italic)
2162 x += myFontMetricsItalic.width(s);
2163 else
2164 x += myFontMetrics.width(s);
2165 zc = z;
2166 }
2167 attr = nextAttr;
2168 a = &m_attribs[attr & taAttrMask];
2169
2170 if (attr & taSelected) paint.setPen(a->selCol);
2171 else paint.setPen(a->col);
2172
2173 if (a->bold && a->italic)
2174 paint.setFont(myFontBI);
2175 else if (a->bold)
2176 paint.setFont(myFontBold);
2177 else if (a->italic)
2178 paint.setFont(myFontItalic);
2179 else
2180 paint.setFont(myFont);
2181 }
2182 }
2183 z++;
2184 }
2185 if (z > zc) {
2186 QConstString str((QChar *) &s[zc], z - zc /*+1*/);
2187 paint.drawText(x - xStart, y, str.string());
2188 }
2189}
2190
2191// Applies the search context, and returns whether a match was found. If one is,
2192// the length of the string matched is also returned.
2193bool KateDocument::doSearch(SConfig &sc, const QString &searchFor) {
2194 int line, col;
2195 int searchEnd;
2196 int bufLen, tlen;
2197 QChar *t;
2198 TextLine::Ptr textLine;
2199 int pos, newPos;
2200
2201 if (searchFor.isEmpty()) return false;
2202
2203 bufLen = 0;
2204 t = 0L;
2205
2206 line = sc.cursor.y;
2207 col = sc.cursor.x;
2208 if (!(sc.flags & KateView::sfBackward)) {
2209 //forward search
2210 if (sc.flags & KateView::sfSelected) {
2211 if (line < selectStart) {
2212 line = selectStart;
2213 col = 0;
2214 }
2215 searchEnd = selectEnd;
2216 } else searchEnd = lastLine();
2217
2218 while (line <= searchEnd) {
2219 textLine = getTextLine(line);
2220 tlen = textLine->length();
2221 if (tlen > bufLen) {
2222 delete t;
2223 bufLen = (tlen + 255) & (~255);
2224 t = new QChar[bufLen];
2225 }
2226 memcpy(t, textLine->getText(), tlen*sizeof(QChar));
2227 if (sc.flags & KateView::sfSelected) {
2228 pos = 0;
2229 do {
2230 pos = textLine->findSelected(pos);
2231 newPos = textLine->findUnselected(pos);
2232 memset(&t[pos], 0, (newPos - pos)*sizeof(QChar));
2233 pos = newPos;
2234 } while (pos < tlen);
2235 }
2236
2237 QString text(t, tlen);
2238 if (sc.flags & KateView::sfWholeWords) {
2239 // Until the end of the line...
2240 while (col < tlen) {
2241 // ...find the next match.
2242 col = sc.search(text, col);
2243 if (col != -1) {
2244 // Is the match delimited correctly?
2245 if (((col == 0) || (!m_highlight->isInWord(t[col]))) &&
2246 ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) {
2247 goto found;
2248 }
2249 else {
2250 // Start again from the next character.
2251 col++;
2252 }
2253 }
2254 else {
2255 // No match.
2256 break;
2257 }
2258 }
2259 }
2260 else {
2261 // Non-whole-word search.
2262 col = sc.search(text, col);
2263 if (col != -1)
2264 goto found;
2265 }
2266 col = 0;
2267 line++;
2268 }
2269 } else {
2270 // backward search
2271 if (sc.flags & KateView::sfSelected) {
2272 if (line > selectEnd) {
2273 line = selectEnd;
2274 col = -1;
2275 }
2276 searchEnd = selectStart;
2277 } else searchEnd = 0;
2278
2279 while (line >= searchEnd) {
2280 textLine = getTextLine(line);
2281 tlen = textLine->length();
2282 if (tlen > bufLen) {
2283 delete t;
2284 bufLen = (tlen + 255) & (~255);
2285 t = new QChar[bufLen];
2286 }
2287 memcpy(t, textLine->getText(), tlen*sizeof(QChar));
2288 if (sc.flags & KateView::sfSelected) {
2289 pos = 0;
2290 do {
2291 pos = textLine->findSelected(pos);
2292 newPos = textLine->findUnselected(pos);
2293 memset(&t[pos], 0, (newPos - pos)*sizeof(QChar));
2294 pos = newPos;
2295 } while (pos < tlen);
2296 }
2297
2298 if (col < 0 || col > tlen) col = tlen;
2299
2300 QString text(t, tlen);
2301 if (sc.flags & KateView::sfWholeWords) {
2302 // Until the beginning of the line...
2303 while (col >= 0) {
2304 // ...find the next match.
2305 col = sc.search(text, col);
2306 if (col != -1) {
2307 // Is the match delimited correctly?
2308 if (((col == 0) || (!m_highlight->isInWord(t[col]))) &&
2309 ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) {
2310 goto found;
2311 }
2312 else {
2313 // Start again from the previous character.
2314 col--;
2315 }
2316 }
2317 else {
2318 // No match.
2319 break;
2320 }
2321 }
2322 }
2323 else {
2324 // Non-whole-word search.
2325 col = sc.search(text, col);
2326 if (col != -1)
2327 goto found;
2328 }
2329 col = -1;
2330 line--;
2331 }
2332 }
2333 sc.flags |= KateView::sfWrapped;
2334 return false;
2335found:
2336 if (sc.flags & KateView::sfWrapped) {
2337 if ((line > sc.startCursor.y || (line == sc.startCursor.y && col >= sc.startCursor.x))
2338 ^ ((sc.flags & KateView::sfBackward) != 0)) return false;
2339 }
2340 sc.cursor.x = col;
2341 sc.cursor.y = line;
2342 return true;
2343}
2344
2345void KateDocument::tagLine(int line) {
2346
2347 if (tagStart > line) tagStart = line;
2348 if (tagEnd < line) tagEnd = line;
2349}
2350
2351void KateDocument::insLine(int line) {
2352 KateView *view;
2353
2354 if (selectStart >= line) selectStart++;
2355 if (selectEnd >= line) selectEnd++;
2356 if (tagStart >= line) tagStart++;
2357 if (tagEnd >= line) tagEnd++;
2358
2359 newDocGeometry = true;
2360 for (view = views.first(); view != 0L; view = views.next() ) {
2361 view->insLine(line);
2362 }
2363}
2364
2365void KateDocument::delLine(int line) {
2366 KateView *view;
2367
2368 if (selectStart >= line && selectStart > 0) selectStart--;
2369 if (selectEnd >= line) selectEnd--;
2370 if (tagStart >= line && tagStart > 0) tagStart--;
2371 if (tagEnd >= line) tagEnd--;
2372
2373 newDocGeometry = true;
2374 for (view = views.first(); view != 0L; view = views.next() ) {
2375 view->delLine(line);
2376 }
2377}
2378
2379void KateDocument::optimizeSelection() {
2380 TextLine::Ptr textLine;
2381
2382 while (selectStart <= selectEnd) {
2383 textLine = getTextLine(selectStart);
2384 if (textLine->isSelected() || textLine->numSelected() > 0) break;
2385 selectStart++;
2386 }
2387 while (selectEnd >= selectStart) {
2388 textLine = getTextLine(selectEnd);
2389 if (textLine->isSelected() || textLine->numSelected() > 0) break;
2390 selectEnd--;
2391 }
2392 if (selectStart > selectEnd) {
2393 selectStart = 0xffffff;
2394 selectEnd = 0;
2395 }
2396}
2397
2398void KateDocument::doAction(KateAction *a) {
2399
2400 switch (a->action) {
2401 case KateAction::replace:
2402 doReplace(a);
2403 break;
2404 case KateAction::wordWrap:
2405 doWordWrap(a);
2406 break;
2407 case KateAction::wordUnWrap:
2408 doWordUnWrap(a);
2409 break;
2410 case KateAction::newLine:
2411 doNewLine(a);
2412 break;
2413 case KateAction::delLine:
2414 doDelLine(a);
2415 break;
2416 case KateAction::insLine:
2417 doInsLine(a);
2418 break;
2419 case KateAction::killLine:
2420 doKillLine(a);
2421 break;
2422/* case KateAction::doubleLine:
2423 break;
2424 case KateAction::removeLine:
2425 break;*/
2426 }
2427}
2428
2429void KateDocument::doReplace(KateAction *a) {
2430 TextLine::Ptr textLine;
2431 int l;
2432
2433 //exchange current text with stored text in KateAction *a
2434
2435 textLine = getTextLine(a->cursor.y);
2436 l = textLine->length() - a->cursor.x;
2437 if (l > a->len) l = a->len;
2438
2439 QString oldText(&textLine->getText()[a->cursor.x], (l < 0) ? 0 : l);
2440 textLine->replace(a->cursor.x, a->len, a->text.unicode(), a->text.length());
2441
2442 a->len = a->text.length();
2443 a->text = oldText;
2444
2445 buffer->changeLine(a->cursor.y);
2446
2447 tagLine(a->cursor.y);
2448}
2449
2450void KateDocument::doWordWrap(KateAction *a) {
2451 TextLine::Ptr textLine;
2452
2453 textLine = getTextLine(a->cursor.y - 1);
2454 a->len = textLine->length() - a->cursor.x;
2455 textLine->wrap(getTextLine(a->cursor.y),a->len);
2456
2457 buffer->changeLine(a->cursor.y - 1);
2458 buffer->changeLine(a->cursor.y);
2459
2460 tagLine(a->cursor.y - 1);
2461 tagLine(a->cursor.y);
2462 if (selectEnd == a->cursor.y - 1) selectEnd++;
2463
2464 a->action = KateAction::wordUnWrap;
2465}
2466
2467void KateDocument::doWordUnWrap(KateAction *a) {
2468 TextLine::Ptr textLine;
2469
2470 textLine = getTextLine(a->cursor.y - 1);
2471// textLine->setLength(a->len);
2472 textLine->unWrap(a->len, getTextLine(a->cursor.y),a->cursor.x);
2473
2474 buffer->changeLine(a->cursor.y - 1);
2475 buffer->changeLine(a->cursor.y);
2476
2477 tagLine(a->cursor.y - 1);
2478 tagLine(a->cursor.y);
2479
2480 a->action = KateAction::wordWrap;
2481}
2482
2483void KateDocument::doNewLine(KateAction *a) {
2484 TextLine::Ptr textLine, newLine;
2485
2486 textLine = getTextLine(a->cursor.y);
2487 newLine = new TextLine(textLine->getRawAttr(), textLine->getContext());
2488 textLine->wrap(newLine,a->cursor.x);
2489
2490 buffer->insertLine(a->cursor.y + 1, newLine);
2491 buffer->changeLine(a->cursor.y);
2492
2493 insLine(a->cursor.y + 1);
2494 tagLine(a->cursor.y);
2495 tagLine(a->cursor.y + 1);
2496 if (selectEnd == a->cursor.y) selectEnd++;//addSelection(a->cursor.y + 1);
2497
2498 a->action = KateAction::delLine;
2499}
2500
2501void KateDocument::doDelLine(KateAction *a) {
2502 TextLine::Ptr textLine, nextLine;
2503
2504 textLine = getTextLine(a->cursor.y);
2505 nextLine = getTextLine(a->cursor.y+1);
2506// textLine->setLength(a->cursor.x);
2507 textLine->unWrap(a->cursor.x, nextLine,nextLine->length());
2508 textLine->setContext(nextLine->getContext());
2509 if (longestLine == nextLine) longestLine = 0L;
2510
2511 buffer->changeLine(a->cursor.y);
2512 buffer->removeLine(a->cursor.y+1);
2513
2514 tagLine(a->cursor.y);
2515 delLine(a->cursor.y + 1);
2516
2517 a->action = KateAction::newLine;
2518}
2519
2520void KateDocument::doInsLine(KateAction *a) {
2521
2522 buffer->insertLine(a->cursor.y, new TextLine());
2523
2524 insLine(a->cursor.y);
2525
2526 a->action = KateAction::killLine;
2527}
2528
2529void KateDocument::doKillLine(KateAction *a) {
2530 TextLine::Ptr textLine = getTextLine(a->cursor.y);
2531 if (longestLine == textLine) longestLine = 0L;
2532
2533 buffer->removeLine(a->cursor.y);
2534
2535 delLine(a->cursor.y);
2536 tagLine(a->cursor.y);
2537
2538 a->action = KateAction::insLine;
2539}
2540
2541void KateDocument::newUndo() {
2542 KTextEditor::View *view;
2543 int state;
2544
2545 state = 0;
2546 if (currentUndo > 0) state |= 1;
2547 if (currentUndo < (int) undoList.count()) state |= 2;
2548 undoState = state;
2549 for (view = m_views.first(); view != 0L; view = m_views.next() ) {
2550 emit static_cast<KateView *>( view )->newUndo();
2551 }
2552}
2553
2554void KateDocument::recordStart(VConfig &c, int newUndoType) {
2555 recordStart(c.view, c.cursor, c.flags, newUndoType);
2556}
2557
2558void KateDocument::recordStart(KateView *, PointStruc &cursor, int flags,
2559 int newUndoType, bool keepModal, bool mergeUndo) {
2560
2561 KateActionGroup *g;
2562
2563// if (newUndoType == KateActionGroup::ugNone) {
2564 // only a bug would cause this
2565//why should someone do this? we can't prevent all programming errors :) (jochen whilhelmy)
2566// debug("KateDocument::recordStart() called with no undo group type!");
2567// return;
2568// }
2569
2570 if (!keepModal) setPseudoModal(0L);
2571
2572 //i optimized the group undo stuff a bit (jochen wilhelmy)
2573 // recordReset() is not needed any more
2574 g = undoList.getLast();
2575 if (g != 0L && ((undoCount < 1024 && flags & KateView::cfGroupUndo
2576 && g->end.x == cursor.x && g->end.y == cursor.y) || mergeUndo)) {
2577
2578 //undo grouping : same actions are put into one undo step
2579 //precondition : new action starts where old stops or mergeUndo flag
2580 if (g->undoType == newUndoType
2581 || (g->undoType == KateActionGroup::ugInsChar
2582 && newUndoType == KateActionGroup::ugInsLine)
2583 || (g->undoType == KateActionGroup::ugDelChar
2584 && newUndoType == KateActionGroup::ugDelLine)) {
2585
2586 undoCount++;
2587 if (g->undoType != newUndoType) undoCount = 0xffffff;
2588 return;
2589 }
2590 }
2591 undoCount = 0;
2592/*
2593 if (undoView != view) {
2594 // always kill the current undo group if the editing view changes
2595 recordReset();
2596 undoType = newUndoType;
2597 } else if (newUndoType == undoType) {
2598printf("bla!!!\n");
2599 // same as current type, keep using it
2600 return;
2601 } else if ( (undoType == KateActionGroup::ugInsChar && newUndoType == KateActionGroup::ugInsLine) ||
2602 (undoType == KateActionGroup::ugDelChar && newUndoType == KateActionGroup::ugDelLine) ) {
2603 // some type combinations can run together...
2604 undoType += 1000;
2605 return;
2606 } else {
2607 recordReset();
2608 undoType = newUndoType;
2609 }
2610
2611 undoView = view;
2612*/
2613 while ((int) undoList.count() > currentUndo) undoList.removeLast();
2614 while ((int) undoList.count() > undoSteps) {
2615 undoList.removeFirst();
2616 currentUndo--;
2617 }
2618
2619 g = new KateActionGroup(cursor, newUndoType);
2620 undoList.append(g);
2621// currentUndo++;
2622
2623 tagEnd = 0;
2624 tagStart = 0xffffff;
2625}
2626
2627void KateDocument::recordAction(KateAction::Action action, PointStruc &cursor) {
2628 KateAction *a;
2629
2630 a = new KateAction(action, cursor);
2631 doAction(a);
2632 undoList.getLast()->insertAction(a);
2633}
2634
2635void KateDocument::recordInsert(VConfig &c, const QString &text) {
2636 recordReplace(c, 0, text);
2637}
2638
2639void KateDocument::recordReplace(VConfig &c, int len, const QString &text) {
2640 if (c.cursor.x > 0 && !(c.flags & KateView::cfSpaceIndent)) {
2641 TextLine::Ptr textLine = getTextLine(c.cursor.y);
2642 if (textLine->length() == 0) {
2643 QString s = tabString(c.cursor.x, tabChars);
2644 int len = s.length();
2645 s += text;
2646 c.cursor.x = 0;
2647 recordReplace(c.cursor, len, s);
2648 c.cursor.x = len;
2649 return;
2650 }
2651 }
2652 recordReplace(c.cursor, len, text);
2653}
2654
2655void KateDocument::recordInsert(PointStruc &cursor, const QString &text) {
2656 recordReplace(cursor, 0, text);
2657}
2658
2659void KateDocument::recordDelete(PointStruc &cursor, int len) {
2660 recordReplace(cursor, len, QString::null);
2661}
2662
2663void KateDocument::recordReplace(PointStruc &cursor, int len, const QString &text) {
2664 KateAction *a;
2665 TextLine::Ptr textLine;
2666 int l;
2667
2668 if (len == 0 && text.isEmpty()) return;
2669
2670 //try to append to last replace action
2671 a = undoList.getLast()->action;
2672 if (a == 0L || a->action != KateAction::replace
2673 || a->cursor.x + a->len != cursor.x || a->cursor.y != cursor.y) {
2674
2675//if (a != 0L) printf("new %d %d\n", a->cursor.x + a->len, cursor.x);
2676 a = new KateAction(KateAction::replace, cursor);
2677 undoList.getLast()->insertAction(a);
2678 }
2679
2680 //replace
2681 textLine = getTextLine(cursor.y);
2682 l = textLine->length() - cursor.x;
2683 if (l > len) l = len;
2684 a->text.insert(a->text.length(), &textLine->getText()[cursor.x], (l < 0) ? 0 : l);
2685 textLine->replace(cursor.x, len, text.unicode(), text.length());
2686 a->len += text.length();
2687
2688 buffer->changeLine(a->cursor.y);
2689 updateMaxLength(textLine);
2690 tagLine(a->cursor.y);
2691}
2692
2693void KateDocument::recordEnd(VConfig &c) {
2694 recordEnd(c.view, c.cursor, c.flags);
2695}
2696
2697void KateDocument::recordEnd(KateView *view, PointStruc &cursor, int flags) {
2698 KateActionGroup *g;
2699
2700 // clear selection if option "persistent selections" is off
2701// if (!(flags & cfPersistent)) deselectAll();
2702
2703 g = undoList.getLast();
2704 if (g->action == 0L) {
2705 // no action has been done: remove empty undo record
2706 undoList.removeLast();
2707 return;
2708 }
2709 // store end cursor position for redo
2710 g->end = cursor;
2711 currentUndo = undoList.count();
2712
2713 if (tagStart <= tagEnd) {
2714 optimizeSelection();
2715 updateLines(tagStart, tagEnd, flags, cursor.y);
2716 setModified(true);
2717 }
2718
2719 view->updateCursor(cursor, flags);
2720
2721// newUndo();
2722/*
2723 undoCount++;
2724 // we limit the number of individual undo operations for sanity - is 1K reasonable?
2725 // this is also where we handle non-group undo preference
2726 // if the undo type is singlular, we always finish it now
2727 if ( undoType == KateActionGroup::ugPaste ||
2728 undoType == KateActionGroup::ugDelBlock ||
2729 undoType > 1000 ||
2730 undoCount > 1024 || !(flags & cfGroupUndo) ) {
2731printf("recordend %d %d\n", undoType, undoCount);
2732 recordReset();
2733 }
2734*/
2735
2736 // this should keep the flood of signals down a little...
2737 if (undoCount == 0) newUndo();
2738 emit textChanged();
2739}
2740/*
2741void KateDocument::recordReset()
2742{
2743 if (pseudoModal)
2744 return;
2745
2746 // forces the next call of recordStart() to begin a new undo group
2747 // not used in normal editing, but used by markFound(), etc.
2748 undoType = KateActionGroup::ugNone;
2749 undoCount = 0;
2750 undoView = NULL;
2751 undoReported = false;
2752printf("recordreset\n");
2753}
2754*/
2755
2756/*
2757void KateDocument::recordDel(PointStruc &cursor, TextLine::Ptr &textLine, int l) {
2758 int len;
2759
2760 len = textLine->length() - cursor.x;
2761 if (len > l) len = l;
2762 if (len > 0) {
2763 insertUndo(new KateAction(KateAction::replace,cursor,&textLine->getText()[cursor.x],len));
2764 }
2765}
2766*/
2767
2768
2769void KateDocument::doActionGroup(KateActionGroup *g, int flags, bool undo) {
2770 KateAction *a, *next;
2771
2772 setPseudoModal(0L);
2773 if (!(flags & KateView::cfPersistent)) deselectAll();
2774 tagEnd = 0;
2775 tagStart = 0xffffff;
2776
2777 a = g->action;
2778 g->action = 0L;
2779 while (a) {
2780 doAction(a);
2781 next = a->next;
2782 g->insertAction(a);
2783 a = next;
2784 }
2785 optimizeSelection();
2786 if (tagStart <= tagEnd) updateLines(tagStart, tagEnd, flags);
2787
2788 // the undo/redo functions set undo to true, all others should leave it
2789 // alone (default)
2790 if (!undo) {
2791 setModified(true);
2792 newUndo();
2793 }
2794}
2795
2796int KateDocument::nextUndoType()
2797{
2798 KateActionGroup *g;
2799
2800 if (currentUndo <= 0) return KateActionGroup::ugNone;
2801 g = undoList.at(currentUndo - 1);
2802 return g->undoType;
2803}
2804
2805int KateDocument::nextRedoType()
2806{
2807 KateActionGroup *g;
2808
2809 if (currentUndo >= (int) undoList.count()) return KateActionGroup::ugNone;
2810 g = undoList.at(currentUndo);
2811// if (!g) return KateActionGroup::ugNone;
2812 return g->undoType;
2813}
2814
2815void KateDocument::undoTypeList(QValueList<int> &lst)
2816{
2817 lst.clear();
2818 for (int i = currentUndo-1; i>=0 ;i--)
2819 lst.append(undoList.at(i)->undoType);
2820}
2821
2822void KateDocument::redoTypeList(QValueList<int> &lst)
2823{
2824 lst.clear();
2825 for (int i = currentUndo+1; i<(int)undoList.count(); i++)
2826 lst.append(undoList.at(i)->undoType);
2827}
2828
2829void KateDocument::undo(VConfig &c, int count) {
2830 KateActionGroup *g = 0L;
2831 int num;
2832 bool needUpdate = false; // don't update the cursor until completely done
2833
2834 if (count <= 0) return;
2835
2836 for (num = 0 ; num < count ; num++) {
2837 if (currentUndo <= 0) break;
2838 currentUndo--;
2839 g = undoList.at(currentUndo);
2840 doActionGroup(g, c.flags, true); // do not setModified() or newUndo()
2841 needUpdate = true;
2842
2843// if (num == 0) recordReset();
2844 }
2845
2846 if (needUpdate) {
2847 // since we told doActionGroup() not to do this stuff, we need to do it now
2848 c.view->updateCursor(g->start);
2849 setModified(true);
2850 newUndo();
2851 }
2852}
2853
2854void KateDocument::redo(VConfig &c, int count) {
2855 KateActionGroup *g = 0L;
2856 int num;
2857 bool needUpdate = false; // don't update the cursor until completely done
2858
2859 if (count <= 0) return;
2860
2861 for (num = 0 ; num < count ; num++) {
2862 if (currentUndo+1 > (int)undoList.count()) break;
2863 g = undoList.at(currentUndo);
2864 currentUndo++;
2865 doActionGroup(g, c.flags, true); // do not setModified() or newUndo()
2866 needUpdate = true;
2867
2868// if (num == 0) recordReset();
2869 }
2870
2871 if (needUpdate) {
2872 // since we told doActionGroup() not to do this stuff, we need to do it now
2873 c.view->updateCursor(g->end);
2874 setModified(true);
2875 newUndo();
2876 }
2877}
2878
2879void KateDocument::clearRedo() {
2880 // disable redos
2881 // this was added as an assist to the spell checker
2882 bool deleted = false;
2883
2884 while ((int) undoList.count() > currentUndo) {
2885 deleted = true;
2886 undoList.removeLast();
2887 }
2888
2889 if (deleted) newUndo();
2890}
2891
2892void KateDocument::setUndoSteps(int steps) {
2893 if (steps < 5) steps = 5;
2894 undoSteps = steps;
2895}
2896
2897void KateDocument::setPseudoModal(QWidget *w) {
2898// QWidget *old = pseudoModal;
2899
2900 // (glenebob)
2901 // this is a temporary hack to make the spell checker work a little
2902 // better - as kspell progresses, this sort of thing should become
2903 // obsolete or worked around more cleanly
2904 // this is relied upon *only* by the spell-check code
2905 if (pseudoModal && pseudoModal != (QWidget*)1L)
2906 delete pseudoModal;
2907
2908// pseudoModal = 0L;
2909// if (old || w) recordReset();
2910
2911 pseudoModal = w;
2912}
2913
2914
2915void KateDocument::newBracketMark(PointStruc &cursor, BracketMark &bm)
2916{
2917 TextLine::Ptr textLine;
2918 int x, line, count, attr;
2919 QChar bracket, opposite, ch;
2920 Attribute *a;
2921
2922 bm.eXPos = -1; //mark bracked mark as invalid
2923 x = cursor.x -1; // -1 to look at left side of cursor
2924 if (x < 0) return;
2925 line = cursor.y; //current line
2926 count = 0; //bracket counter for nested brackets
2927
2928 textLine = getTextLine(line);
2929 if (!textLine) return;
2930
2931 bracket = textLine->getChar(x);
2932 attr = textLine->getAttr(x);
2933
2934 if (bracket == '(' || bracket == '[' || bracket == '{')
2935 {
2936 //get opposite bracket
2937 opposite = ')';
2938 if (bracket == '[') opposite = ']';
2939 if (bracket == '{') opposite = '}';
2940 //get attribute of bracket (opposite bracket must have the same attribute)
2941 x++;
2942 while (line - cursor.y < 40) {
2943 //go to next line on end of line
2944 while (x >= (int) textLine->length()) {
2945 line++;
2946 if (line > lastLine()) return;
2947 textLine = getTextLine(line);
2948 x = 0;
2949 }
2950 if (textLine->getAttr(x) == attr) {
2951 //try to find opposite bracked
2952 ch = textLine->getChar(x);
2953 if (ch == bracket) count++; //same bracket : increase counter
2954 if (ch == opposite) {
2955 count--;
2956 if (count < 0) goto found;
2957 }
2958 }
2959 x++;
2960 }
2961 }
2962 else if (bracket == ')' || bracket == ']' || bracket == '}')
2963 {
2964 opposite = '(';
2965 if (bracket == ']') opposite = '[';
2966 if (bracket == '}') opposite = '{';
2967 x--;
2968 while (cursor.y - line < 20) {
2969
2970 while (x < 0) {
2971 line--;
2972 if (line < 0) return;
2973 textLine = getTextLine(line);
2974 x = textLine->length() -1;
2975 }
2976 if (textLine->getAttr(x) == attr) {
2977 ch = textLine->getChar(x);
2978 if (ch == bracket) count++;
2979 if (ch == opposite) {
2980 count--;
2981 if (count < 0) goto found;
2982 }
2983 }
2984 x--;
2985 }
2986 }
2987 return;
2988
2989found:
2990 //cursor position of opposite bracket
2991 bm.cursor.x = x;
2992 bm.cursor.y = line;
2993 //x position (start and end) of related bracket
2994 bm.sXPos = textWidth(textLine, x);
2995 a = &m_attribs[attr];
2996
2997 if (a->bold && a->italic)
2998 bm.eXPos = bm.sXPos + myFontMetricsBI.width(bracket);
2999 else if (a->bold)
3000 bm.eXPos = bm.sXPos + myFontMetricsBold.width(bracket);
3001 else if (a->italic)
3002 bm.eXPos = bm.sXPos + myFontMetricsItalic.width(bracket);
3003 else
3004 bm.eXPos = bm.sXPos + myFontMetrics.width(bracket);
3005}
3006
3007void KateDocument::clipboardChanged() { //slot
3008//#if defined(_WS_X11_)
3009 if (m_singleSelection) {
3010 disconnect(QApplication::clipboard(), SIGNAL(dataChanged()),
3011 this, SLOT(clipboardChanged()));
3012 deselectAll();
3013 updateViews();
3014 }
3015//#endif
3016}
3017
3018#if 0
3019void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev )
3020{
3021 KParts::ReadWritePart::guiActivateEvent( ev );
3022 if ( ev->activated() )
3023 emit selectionChanged();
3024}
3025#endif
3026
3027void KateDocument::setDocName (QString docName)
3028{
3029 myDocName = docName;
3030 emit nameChanged (this);
3031}
3032
3033void KateDocument::setMTime()
3034{
3035 if (fileInfo && !fileInfo->fileName().isEmpty()) {
3036 fileInfo->refresh();
3037 mTime = fileInfo->lastModified();
3038 }
3039}
3040
3041void KateDocument::isModOnHD(bool forceReload)
3042{
3043 if (fileInfo && !fileInfo->fileName().isEmpty()) {
3044 fileInfo->refresh();
3045 if (fileInfo->lastModified() > mTime) {
3046 if ( forceReload ||
3047 (KMessageBox::warningContinueCancel(0,
3048 (i18n("The file %1 has changed on disk.\nDo you want to reload it?\n\nIf you cancel you will lose these changes next time you save this file")).arg(m_url),
3049 i18n("File has changed on Disk"),
3050 i18n("Yes") ) == KMessageBox::Continue)
3051 )
3052 reloadFile();
3053 else
3054 setMTime();
3055 }
3056 }
3057}
3058
3059void KateDocument::reloadFile()
3060{
3061#warning fixme
3062#if 0
3063 if (fileInfo && !fileInfo->fileName().isEmpty()) {
3064 KateDocument::openFile();
3065 setMTime();
3066 }
3067#endif
3068}
3069
3070void KateDocument::slotModChanged()
3071{
3072 emit modStateChanged (this);
3073}
3074
3075QList<Kate::Mark> KateDocument::marks ()
3076{
3077 QList<Kate::Mark> list;
3078 TextLine::Ptr line;
3079
3080 for (int i=0; i < numLines(); i++)
3081 {
3082 line = getTextLine(i);
3083 if (line->mark() != 0)
3084 {
3085 Kate::Mark *mark=new Kate::Mark;
3086 mark->line = i;
3087 mark->type = line->mark();
3088 list.append (mark);
3089 }
3090 }
3091
3092 return list;
3093}
3094
3095void KateDocument::flush ()
3096{
3097 if (isReadOnly())
3098 return;
3099
3100 m_url = QString::null;
3101 fileInfo->setFile (QString());
3102 setMTime();
3103
3104 clear();
3105 updateViews();
3106
3107 emit fileNameChanged ();
3108}
3109
3110void KateDocument::open (const QString &name)
3111{
3112 openURL (name);
3113}
3114
3115void KateDocument::wrapText (uint col)
3116{
3117 int line = 0;
3118 int z = 0;
3119
3120 while(true)
3121 {
3122 TextLine::Ptr l = getTextLine(line);
3123
3124 if (l->length() > col)
3125 {
3126 TextLine::Ptr tl = new TextLine();
3127 buffer->insertLine(line+1,tl);
3128 const QChar *text = l->getText();
3129
3130 for (z=col; z>0; z--)
3131 {
3132 if (z < 1) break;
3133 if (text[z].isSpace()) break;
3134 }
3135
3136 if (z < 1) z=col;
3137
3138 l->wrap (tl, z);
3139 }
3140
3141 line++;
3142 if (line >= numLines()) break;
3143 };
3144
3145 newDocGeometry=true;
3146 updateLines();
3147 updateViews();
3148}
3149
3150void KateDocument::setWordWrap (bool on)
3151{
3152 if (on != myWordWrap && on)
3153 wrapText (myWordWrapAt);
3154
3155 myWordWrap = on;
3156}
3157
3158void KateDocument::setWordWrapAt (uint col)
3159{
3160 if (myWordWrapAt != col && myWordWrap)
3161 wrapText (myWordWrapAt);
3162
3163 myWordWrapAt = col;
3164}
3165
3166void KateDocument::applyWordWrap ()
3167{
3168 wrapText (myWordWrapAt);
3169}