author | kergoth <kergoth> | 2003-01-28 03:23:14 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2003-01-28 03:23:14 (UTC) |
commit | de1321a53998bc1d078f9492395c2a26392875ed (patch) (side-by-side diff) | |
tree | b36d59612da5bbafeaddd28cb88a222b699d2645 | |
parent | 728a7a4966c342be32c80c045cbae500160fc17b (diff) | |
download | opie-de1321a53998bc1d078f9492395c2a26392875ed.zip opie-de1321a53998bc1d078f9492395c2a26392875ed.tar.gz opie-de1321a53998bc1d078f9492395c2a26392875ed.tar.bz2 |
Added a Config derivative.
19 files changed, 834 insertions, 307 deletions
diff --git a/noncore/apps/tinykate/libkate/document/katedocument.cpp b/noncore/apps/tinykate/libkate/document/katedocument.cpp index df1de8d..6807544 100644 --- a/noncore/apps/tinykate/libkate/document/katedocument.cpp +++ b/noncore/apps/tinykate/libkate/document/katedocument.cpp @@ -1,3177 +1,3176 @@ /*************************************************************************** katedocument.cpp - description ------------------- begin : Mon Jan 15 2001 copyright : (C) 2001 by Christoph "Crossfire" Cullmann (C) 2002 by Joseph Wenninger email : crossfire@babylon2k.de jowenn@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* Copyright (C) 1998, 1999 Jochen Wilhelmy digisnap@cs.tu-berlin.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "katedocument.h" #include <qfileinfo.h> #include <qdatetime.h> #include <kmessagebox.h> #include <klocale.h> #include <qpe/config.h> #include <qstring.h> #include <sys/time.h> #include <unistd.h> #include <stdio.h> #include <qtimer.h> #include <qobject.h> #include <qapplication.h> #include <qclipboard.h> #include <qfont.h> #include <qpainter.h> #include <qfile.h> #include <qtextstream.h> #include <qtextcodec.h> #include <kglobal.h> #include <klocale.h> //#include <kcharsets.h> #include <kdebug.h> //#include <kinstance.h> #include <kglobalsettings.h> //#include <kaction.h> //#include <kstdaction.h> #include "../view/kateview.h" #include "katebuffer.h" #include "katetextline.h" #include "katecmd.h" KateAction::KateAction(Action a, PointStruc &cursor, int len, const QString &text) : action(a), cursor(cursor), len(len), text(text) { } KateActionGroup::KateActionGroup(PointStruc &aStart, int type) : start(aStart), action(0L), undoType(type) { } KateActionGroup::~KateActionGroup() { KateAction *current, *next; current = action; while (current) { next = current->next; delete current; current = next; } } void KateActionGroup::insertAction(KateAction *a) { a->next = action; action = a; } const char * KateActionGroup::typeName(int type) { // return a short text description of the given undo group type suitable for a menu // not the lack of i18n's, the caller is expected to handle translation switch (type) { case ugPaste : return "Paste Text"; case ugDelBlock : return "Selection Overwrite"; case ugIndent : return "Indent"; case ugUnindent : return "Unindent"; case ugComment : return "Comment"; case ugUncomment : return "Uncomment"; case ugReplace : return "Text Replace"; case ugSpell : return "Spell Check"; case ugInsChar : return "Typing"; case ugDelChar : return "Delete Text"; case ugInsLine : return "New Line"; case ugDelLine : return "Delete Line"; } return ""; } const int KateDocument::maxAttribs = 32; QStringList KateDocument::searchForList = QStringList(); QStringList KateDocument::replaceWithList = QStringList(); uint KateDocument::uniqueID = 0; QPtrDict<KateDocument::KateDocPrivate>* KateDocument::d_ptr = 0; KateDocument::KateDocument(bool bSingleViewMode, bool bBrowserView, QWidget *parentWidget, const char *widgetName, QObject *, const char *) : Kate::Document (), myFont(KGlobalSettings::generalFont()), myFontBold(KGlobalSettings::generalFont()), myFontItalic(KGlobalSettings::generalFont()), myFontBI(KGlobalSettings::generalFont()), myFontMetrics (myFont), myFontMetricsBold (myFontBold), myFontMetricsItalic (myFontItalic), myFontMetricsBI (myFontBI), hlManager(HlManager::self ()) { d(this)->hlSetByUser = false; PreHighlightedTill=0; RequestPreHighlightTill=0; m_bSingleViewMode=bSingleViewMode; m_bBrowserView = bBrowserView; m_url = QString::null; // NOTE: QFont::CharSet doesn't provide all the charsets KDE supports // (esp. it doesn't distinguish between UTF-8 and iso10646-1) myEncoding = QString::fromLatin1(QTextCodec::codecForLocale()->name()); maxLength = -1; setFont (KGlobalSettings::generalFont()); myDocID = uniqueID; uniqueID++; myDocName = QString (""); fileInfo = new QFileInfo (); myCmd = new KateCmd (this); connect(this,SIGNAL(modifiedChanged ()),this,SLOT(slotModChanged ())); buffer = new KWBuffer; connect(buffer, SIGNAL(linesChanged(int)), this, SLOT(slotBufferChanged())); // connect(buffer, SIGNAL(textChanged()), this, SIGNAL(textChanged())); connect(buffer, SIGNAL(needHighlight(long,long)),this,SLOT(slotBufferHighlight(long,long))); colors[0] = KGlobalSettings::baseColor(); colors[1] = KGlobalSettings::highlightColor(); m_attribs = new Attribute[maxAttribs]; m_highlight = 0L; tabChars = 8; m_singleSelection = false; newDocGeometry = false; readOnly = false; newDoc = false; modified = false; undoList.setAutoDelete(true); undoState = 0; undoSteps = 50; pseudoModal = 0L; clear(); setHighlight(0); //calls updateFontData() // if the user changes the highlight with the dialog, notify the doc connect(hlManager,SIGNAL(changed()),SLOT(hlChanged())); newDocGeometry = false; readConfig(); setReadOnly(false); } void KateDocument::setDontChangeHlOnSave() { d(this)->hlSetByUser = true; } void KateDocument::setFont (QFont font) { kdDebug()<<"Kate:: setFont"<<endl; int oldwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 myFont = font; myFontBold = QFont (font); myFontBold.setBold (true); myFontItalic = QFont (font); myFontItalic.setItalic (true); myFontBI = QFont (font); myFontBI.setBold (true); myFontBI.setItalic (true); myFontMetrics = CachedFontMetrics (myFont); myFontMetricsBold = CachedFontMetrics (myFontBold); myFontMetricsItalic = CachedFontMetrics (myFontItalic); myFontMetricsBI = CachedFontMetrics (myFontBI); int newwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 maxLength=maxLength*(float)newwidth/(float)oldwidth; //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 updateFontData(); updateViews(); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0 } long KateDocument::needPreHighlight(long till) { int max=numLines()-1; if (till>max) { till=max; } if (PreHighlightedTill>=till) return -1; long tmp=RequestPreHighlightTill; if (RequestPreHighlightTill<till) { RequestPreHighlightTill=till; if (tmp<=PreHighlightedTill) QTimer::singleShot(10,this,SLOT(doPreHighlight())); } return RequestPreHighlightTill; } void KateDocument::doPreHighlight() { int from = PreHighlightedTill; int till = PreHighlightedTill+200; int max = numLines()-1; if (till > max) { till = max; } PreHighlightedTill = till; updateLines(from,till); emit preHighlightChanged(PreHighlightedTill); if (PreHighlightedTill<RequestPreHighlightTill) QTimer::singleShot(10,this,SLOT(doPreHighlight())); } KateDocument::~KateDocument() { m_highlight->release(); + writeConfig(); if ( !m_bSingleViewMode ) { m_views.setAutoDelete( true ); m_views.clear(); m_views.setAutoDelete( false ); } delete_d(this); } void KateDocument::openURL(const QString &filename) { m_file=filename; fileInfo->setFile (m_file); setMTime(); if (!fileInfo->exists() || !fileInfo->isReadable()) { qDebug("File doesn't exit or couldn't be read"); return ; } buffer->clear(); #warning fixme // buffer->insertFile(0, m_file, KGlobal::charsets()->codecForName(myEncoding)); qDebug("Telling buffer to open file"); buffer->insertFile(0, m_file, QTextCodec::codecForLocale()); setMTime(); if (myWordWrap) wrapText (myWordWrapAt); int hl = hlManager->wildcardFind( m_file ); setHighlight(hl); updateLines(); updateViews(); emit fileNameChanged(); return ; } bool KateDocument::saveFile() { QFile f( m_file ); if ( !f.open( IO_WriteOnly ) ) return false; // Error QTextStream stream(&f); stream.setEncoding(QTextStream::RawUnicode); // disable Unicode headers #warning fixme // stream.setCodec(KGlobal::charsets()->codecForName(myEncoding)); stream.setCodec(QTextCodec::codecForLocale()); // this line sets the mapper to the correct codec int maxLine = numLines(); int line = 0; while(true) { stream << getTextLine(line)->getString(); line++; if (line >= maxLine) break; if (eolMode == KateDocument::eolUnix) stream << "\n"; else if (eolMode == KateDocument::eolDos) stream << "\r\n"; else if (eolMode == KateDocument::eolMacintosh) stream << '\r'; }; f.close(); fileInfo->setFile (m_file); setMTime(); if (!(d(this)->hlSetByUser)) { int hl = hlManager->wildcardFind( m_file ); setHighlight(hl); } emit fileNameChanged (); return (f.status() == IO_Ok); } KTextEditor::View *KateDocument::createView( QWidget *parent, const char *name ) { return new KateView( this, parent, name); } QString KateDocument::textLine( int line ) const { TextLine::Ptr l = getTextLine( line ); if ( !l ) return QString(); return l->getString(); } void KateDocument::replaceLine(const QString& s,int line) { remove_Line(line,false); insert_Line(s,line,true); } void KateDocument::insertLine( const QString &str, int l ) { insert_Line(str,l,true); } void KateDocument::insert_Line(const QString& s,int line, bool update) { kdDebug(13020)<<"KateDocument::insertLine "<<s<<QString(" %1").arg(line)<<endl; TextLine::Ptr TL=new TextLine(); TL->append(s.unicode(),s.length()); buffer->insertLine(line,TL); if (update) { newDocGeometry=true; updateLines(line); updateViews(); } } void KateDocument::insertAt( const QString &s, int line, int col, bool ) { VConfig c; c.view = 0; // ### FIXME c.cursor.x = col; c.cursor.y = line; c.cXPos = 0; // ### FIXME c.flags = 0; // ### FIXME insert( c, s ); } void KateDocument::removeLine( int line ) { remove_Line(line,true); } void KateDocument::remove_Line(int line,bool update) { kdDebug(13020)<<"KateDocument::removeLine "<<QString("%1").arg(line)<<endl; buffer->removeLine(line); // newDocGeometry=true; // if line==0) if (update) { updateLines(line); updateViews(); } } int KateDocument::length() const { return text().length(); } void KateDocument::setSelection( int , int , int , int ) { } bool KateDocument::hasSelection() const { return (selectEnd >= selectStart); } QString KateDocument::selection() const { uint flags = 0; TextLine::Ptr textLine; int len, z, start, end, i; len = 1; if (!(flags & KateView::cfVerticalSelect)) { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected(); if (textLine->isSelected()) len++; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); if (textLine->isSelected()) { s[len] = '\n'; len++; } } // s[len] = '\0'; return s; } else { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected() + 1; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); s[len] = '\n'; len++; } // s[len] = '\0'; // the final \0 is not counted in length() return s; } } int KateDocument::numLines() const { return buffer->count(); } TextLine::Ptr KateDocument::getTextLine(int line) const { // This is a hack to get this stuff working. return buffer->line(line); } int KateDocument::textLength(int line) { TextLine::Ptr textLine = getTextLine(line); if (!textLine) return 0; return textLine->length(); } void KateDocument::setTabWidth(int chars) { if (tabChars == chars) return; if (chars < 1) chars = 1; if (chars > 16) chars = 16; tabChars = chars; updateFontData(); maxLength = -1; for (int i=0; i < buffer->count(); i++) { TextLine::Ptr textLine = buffer->line(i); int len = textWidth(textLine,textLine->length()); if (len > maxLength) { maxLength = len; longestLine = textLine; } } } void KateDocument::setReadOnly(bool m) { KTextEditor::View *view; if (m != readOnly) { readOnly = m; // if (readOnly) recordReset(); for (view = m_views.first(); view != 0L; view = m_views.next() ) { emit static_cast<KateView *>( view )->newStatus(); } } } bool KateDocument::isReadOnly() const { return readOnly; } void KateDocument::setNewDoc( bool m ) { // KTextEditor::View *view; if ( m != newDoc ) { newDoc = m; //// if (readOnly) recordReset(); // for (view = m_views.first(); view != 0L; view = m_views.next() ) { // emit static_cast<KateView *>( view )->newStatus(); // } } } bool KateDocument::isNewDoc() const { return newDoc; } void KateDocument::setModified(bool m) { KTextEditor::View *view; if (m != modified) { modified = m; for (view = m_views.first(); view != 0L; view = m_views.next() ) { emit static_cast<KateView *>( view )->newStatus(); } emit modifiedChanged (); } } bool KateDocument::isModified() const { return modified; } void KateDocument::readConfig() { - KConfig *config = KGlobal::config(); + KateConfig *config = KGlobal::config(); config->setGroup("Kate Document"); myWordWrap = config->readBoolEntry("Word Wrap On", false); myWordWrapAt = config->readNumEntry("Word Wrap At", 80); if (myWordWrap) wrapText (myWordWrapAt); setTabWidth(config->readNumEntry("TabWidth", 8)); setUndoSteps(config->readNumEntry("UndoSteps", 50)); m_singleSelection = config->readBoolEntry("SingleSelection", false); myEncoding = config->readEntry("Encoding", QString::fromLatin1(QTextCodec::codecForLocale()->name())); - setFont (config->readFontEntry("Font", &myFont)); + setFont (config->readFontEntry("Font", myFont)); - colors[0] = config->readColorEntry("Color Background", &colors[0]); - colors[1] = config->readColorEntry("Color Selected", &colors[1]); + colors[0] = config->readColorEntry("Color Background", colors[0]); + colors[1] = config->readColorEntry("Color Selected", colors[1]); - config->sync(); +// config->sync(); } void KateDocument::writeConfig() { - KConfig *config = KGlobal::config(); + KateConfig *config = KGlobal::config(); config->setGroup("Kate Document"); -#if 0 - cofig->writeEntry("Word Wrap On", myWordWrap); + config->writeEntry("Word Wrap On", myWordWrap); config->writeEntry("Word Wrap At", myWordWrapAt); config->writeEntry("TabWidth", tabChars); config->writeEntry("UndoSteps", undoSteps); config->writeEntry("SingleSelection", m_singleSelection); config->writeEntry("Encoding", myEncoding); config->writeEntry("Font", myFont); config->writeEntry("Color Background", colors[0]); config->writeEntry("Color Selected", colors[1]); -#endif - config->sync(); +// config->sync(); } -void KateDocument::readSessionConfig(KConfig *config) +void KateDocument::readSessionConfig(KateConfig *config) { m_url = config->readEntry("URL"); // ### doesn't this break the encoding? (Simon) setHighlight(hlManager->nameFind(config->readEntry("Highlight"))); // anders: restore bookmarks if possible QValueList<int> l = config->readIntListEntry("Bookmarks"); if ( l.count() ) { for (uint i=0; i < l.count(); i++) { if ( numLines() < l[i] ) break; getTextLine( l[i] )->addMark( Bookmark ); } } } -void KateDocument::writeSessionConfig(KConfig *config) +void KateDocument::writeSessionConfig(KateConfig *config) { #if 0 config->writeEntry("URL", m_url); // ### encoding?? (Simon) config->writeEntry("Highlight", m_highlight->name()); // anders: save bookmarks QList<Kate::Mark> l = marks(); QValueList<int> ml; for (uint i=0; i < l.count(); i++) { if ( l.at(i)->type == 1) // only save bookmarks ml << l.at(i)->line; } if ( ml.count() ) config->writeEntry("Bookmarks", ml); #endif } void KateDocument::setHighlight(int n) { Highlight *h; // hlNumber = n; h = hlManager->getHl(n); if (h == m_highlight) { updateLines(); } else { if (m_highlight != 0L) m_highlight->release(); h->use(); m_highlight = h; makeAttribs(); } PreHighlightedTill=0; RequestPreHighlightTill=0; emit(highlightChanged()); } void KateDocument::makeAttribs() { qDebug("KateDocument::makeAttribs()"); m_numAttribs = hlManager->makeAttribs(m_highlight, m_attribs, maxAttribs); updateFontData(); updateLines(); } void KateDocument::updateFontData() { int maxAscent, maxDescent; int tabWidth; KateView *view; maxAscent = myFontMetrics.ascent(); maxDescent = myFontMetrics.descent(); tabWidth = myFontMetrics.width(' '); fontHeight = maxAscent + maxDescent + 1; fontAscent = maxAscent; m_tabWidth = tabChars*tabWidth; for (view = views.first(); view != 0L; view = views.next() ) { view->myViewInternal->drawBuffer->resize(view->width(),fontHeight); view->tagAll(); view->updateCursor(); } } void KateDocument::hlChanged() { //slot makeAttribs(); updateViews(); } void KateDocument::addView(KTextEditor::View *view) { views.append( static_cast<KateView *>( view ) ); KTextEditor::Document::addView( view ); connect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) ); } void KateDocument::removeView(KTextEditor::View *view) { // if (undoView == view) recordReset(); disconnect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) ); views.removeRef( static_cast<KateView *>( view ) ); KTextEditor::Document::removeView( view ); } void KateDocument::slotViewDestroyed() { views.removeRef( static_cast<const KateView *>( sender() ) ); } bool KateDocument::ownedView(KateView *view) { // do we own the given view? return (views.containsRef(view) > 0); } bool KateDocument::isLastView(int numViews) { return ((int) views.count() == numViews); } int KateDocument::textWidth(const TextLine::Ptr &textLine, int cursorX) { int x; int z; QChar ch; Attribute *a; x = 0; for (z = 0; z < cursorX; z++) { ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); } return x; } int KateDocument::textWidth(PointStruc &cursor) { if (cursor.x < 0) cursor.x = 0; if (cursor.y < 0) cursor.y = 0; if (cursor.y >= numLines()) cursor.y = lastLine(); return textWidth(getTextLine(cursor.y),cursor.x); } int KateDocument::textWidth(bool wrapCursor, PointStruc &cursor, int xPos) { int len; int x, oldX; int z; QChar ch; Attribute *a; if (cursor.y < 0) cursor.y = 0; if (cursor.y > lastLine()) cursor.y = lastLine(); TextLine::Ptr textLine = getTextLine(cursor.y); len = textLine->length(); x = oldX = z = 0; while (x < xPos && (!wrapCursor || z < len)) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } if (xPos - oldX < x - xPos && z > 0) { z--; x = oldX; } cursor.x = z; return x; } int KateDocument::textPos(const TextLine::Ptr &textLine, int xPos) { int x, oldX; int z; QChar ch; Attribute *a; x = oldX = z = 0; while (x < xPos) { // && z < len) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } if (xPos - oldX < x - xPos && z > 0) { z--; // newXPos = oldX; }// else newXPos = x; return z; } int KateDocument::textWidth() { return int(maxLength + 8); } int KateDocument::textHeight() { return numLines()*fontHeight; } void KateDocument::insert(VConfig &c, const QString &s) { int pos; QChar ch; QString buf; if (s.isEmpty()) return; recordStart(c, KateActionGroup::ugPaste); pos = 0; if (!(c.flags & KateView::cfVerticalSelect)) { do { ch = s[pos]; if (ch.isPrint() || ch == '\t') { buf += ch; // append char to buffer } else if (ch == '\n') { recordAction(KateAction::newLine, c.cursor); // wrap contents behind cursor to new line recordInsert(c, buf); // append to old line // c.cursor.x += buf.length(); buf.truncate(0); // clear buffer c.cursor.y++; c.cursor.x = 0; } pos++; } while (pos < (int) s.length()); } else { int xPos; xPos = textWidth(c.cursor); do { ch = s[pos]; if (ch.isPrint() || ch == '\t') { buf += ch; } else if (ch == '\n') { recordInsert(c, buf); c.cursor.x += buf.length(); buf.truncate(0); c.cursor.y++; if (c.cursor.y >= numLines()) recordAction(KateAction::insLine, c.cursor); c.cursor.x = textPos(getTextLine(c.cursor.y), xPos); } pos++; } while (pos < (int) s.length()); } recordInsert(c, buf); c.cursor.x += buf.length(); recordEnd(c); } void KateDocument::insertFile(VConfig &c, QIODevice &dev) { recordStart(c, KateActionGroup::ugPaste); QString buf; QChar ch, last; QTextStream stream( &dev ); while ( !stream.atEnd() ) { stream >> ch; if (ch.isPrint() || ch == '\t') { buf += ch; } else if (ch == '\n' || ch == '\r') { if (last != '\r' || ch != '\n') { recordAction(KateAction::newLine, c.cursor); recordInsert(c, buf); buf.truncate(0); c.cursor.y++; c.cursor.x = 0; } last = ch; } } recordInsert(c, buf); recordEnd(c); } int KateDocument::currentColumn(PointStruc &cursor) { return getTextLine(cursor.y)->cursorX(cursor.x,tabChars); } bool KateDocument::insertChars(VConfig &c, const QString &chars) { int z, pos, l; bool onlySpaces; QChar ch; QString buf; TextLine::Ptr textLine = getTextLine(c.cursor.y); pos = 0; onlySpaces = true; for (z = 0; z < (int) chars.length(); z++) { ch = chars[z]; if (ch == '\t' && c.flags & KateView::cfReplaceTabs) { l = tabChars - (textLine->cursorX(c.cursor.x, tabChars) % tabChars); while (l > 0) { buf.insert(pos, ' '); pos++; l--; } } else if (ch.isPrint() || ch == '\t') { buf.insert(pos, ch); pos++; if (ch != ' ') onlySpaces = false; if (c.flags & KateView::cfAutoBrackets) { if (ch == '(') buf.insert(pos, ')'); if (ch == '[') buf.insert(pos, ']'); if (ch == '{') buf.insert(pos, '}'); } } } //pos = cursor increment //return false if nothing has to be inserted if (buf.isEmpty()) return false; //auto deletion of the marked text occurs not very often and can therefore // be recorded separately if (c.flags &KateView:: cfDelOnInput) delMarkedText(c); recordStart(c, KateActionGroup::ugInsChar); recordReplace(c/*.cursor*/, (c.flags & KateView::cfOvr) ? buf.length() : 0, buf); c.cursor.x += pos; if (myWordWrap && myWordWrapAt > 0) { int line; const QChar *s; // int pos; PointStruc actionCursor; line = c.cursor.y; do { textLine = getTextLine(line); s = textLine->getText(); l = textLine->length(); for (z = myWordWrapAt; z < l; z++) if (!s[z].isSpace()) break; //search for text to wrap if (z >= l) break; // nothing more to wrap pos = myWordWrapAt; for (; z >= 0; z--) { //find wrap position if (s[z].isSpace()) { pos = z + 1; break; } } //pos = wrap position if (line == c.cursor.y && pos <= c.cursor.x) { //wrap cursor c.cursor.y++; c.cursor.x -= pos; } if (line == lastLine() || (getTextLine(line+1)->length() == 0) ) { //at end of doc: create new line actionCursor.x = pos; actionCursor.y = line; recordAction(KateAction::newLine,actionCursor); } else { //wrap actionCursor.y = line + 1; if (!s[l - 1].isSpace()) { //add space in next line if necessary actionCursor.x = 0; recordInsert(actionCursor, " "); } actionCursor.x = textLine->length() - pos; recordAction(KateAction::wordWrap, actionCursor); } line++; } while (true); } recordEnd(c); return true; } QString tabString(int pos, int tabChars) { QString s; while (pos >= tabChars) { s += '\t'; pos -= tabChars; } while (pos > 0) { s += ' '; pos--; } return s; } void KateDocument::newLine(VConfig &c) { //auto deletion of marked text is done by the view to have a more // "low level" KateDocument::newLine method recordStart(c, KateActionGroup::ugInsLine); if (!(c.flags & KateView::cfAutoIndent)) { recordAction(KateAction::newLine,c.cursor); c.cursor.y++; c.cursor.x = 0; } else { TextLine::Ptr textLine = getTextLine(c.cursor.y); int pos = textLine->firstChar(); if (c.cursor.x < pos) c.cursor.x = pos; // place cursor on first char if before int y = c.cursor.y; while ((y > 0) && (pos < 0)) { // search a not empty text line textLine = getTextLine(--y); pos = textLine->firstChar(); } recordAction(KateAction::newLine, c.cursor); c.cursor.y++; c.cursor.x = 0; if (pos > 0) { pos = textLine->cursorX(pos, tabChars); // if (getTextLine(c.cursor.y)->length() > 0) { QString s = tabString(pos, (c.flags & KateView::cfSpaceIndent) ? 0xffffff : tabChars); recordInsert(c.cursor, s); pos = s.length(); // } // recordInsert(c.cursor, QString(textLine->getText(), pos)); c.cursor.x = pos; } } recordEnd(c); } void KateDocument::killLine(VConfig &c) { recordStart(c, KateActionGroup::ugDelLine); c.cursor.x = 0; recordDelete(c.cursor, 0xffffff); if (c.cursor.y < lastLine()) { recordAction(KateAction::killLine, c.cursor); } recordEnd(c); } void KateDocument::backspace(VConfig &c) { if (c.cursor.x <= 0 && c.cursor.y <= 0) return; if (c.cursor.x > 0) { recordStart(c, KateActionGroup::ugDelChar); if (!(c.flags & KateView::cfBackspaceIndents)) { // ordinary backspace c.cursor.x--; recordDelete(c.cursor, 1); } else { // backspace indents: erase to next indent position int l = 1; // del one char TextLine::Ptr textLine = getTextLine(c.cursor.y); int pos = textLine->firstChar(); if (pos < 0 || pos >= c.cursor.x) { // only spaces on left side of cursor // search a line with less spaces int y = c.cursor.y; while (y > 0) { textLine = getTextLine(--y); pos = textLine->firstChar(); if (pos >= 0 && pos < c.cursor.x) { l = c.cursor.x - pos; // del more chars break; } } } // break effectively jumps here c.cursor.x -= l; recordDelete(c.cursor, l); } } else { // c.cursor.x == 0: wrap to previous line recordStart(c, KateActionGroup::ugDelLine); c.cursor.y--; c.cursor.x = getTextLine(c.cursor.y)->length(); recordAction(KateAction::delLine,c.cursor); } recordEnd(c); } void KateDocument::del(VConfig &c) { TextLine::Ptr textLine = getTextLine(c.cursor.y); int len = (c.flags & KateView::cfRemoveSpaces) ? textLine->lastChar() : textLine->length(); if (c.cursor.x < len/*getTextLine(c.cursor.y)->length()*/) { // delete one character recordStart(c, KateActionGroup::ugDelChar); recordDelete(c.cursor, 1); recordEnd(c); } else { if (c.cursor.y < lastLine()) { // wrap next line to this line textLine->truncate(c.cursor.x); // truncate spaces recordStart(c, KateActionGroup::ugDelLine); recordAction(KateAction::delLine,c.cursor); recordEnd(c); } } } void KateDocument::clear() { PointStruc cursor; KateView *view; setPseudoModal(0L); cursor.x = cursor.y = 0; for (view = views.first(); view != 0L; view = views.next() ) { view->updateCursor(cursor); view->tagAll(); } eolMode = KateDocument::eolUnix; buffer->clear(); longestLine = buffer->line(0); maxLength = 0; select.x = -1; selectStart = 0xffffff; selectEnd = 0; oldMarkState = false; setModified(false); undoList.clear(); currentUndo = 0; newUndo(); } void KateDocument::cut(VConfig &c) { if (selectEnd < selectStart) return; copy(c.flags); delMarkedText(c); } void KateDocument::copy(int flags) { if (selectEnd < selectStart) return; QString s = markedText(flags); if (!s.isEmpty()) { //#if defined(_WS_X11_) if (m_singleSelection) disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), this, 0); //#endif QApplication::clipboard()->setText(s); //#if defined(_WS_X11_) if (m_singleSelection) { connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged())); } //#endif } } void KateDocument::paste(VConfig &c) { QString s = QApplication::clipboard()->text(); if (!s.isEmpty()) { insert(c, s); } } void KateDocument::toggleRect(int start, int end, int x1, int x2) { int z, line; bool t; if (x1 > x2) { z = x1; x1 = x2; x2 = z; } if (start > end) { z = start; start = end; end = z; } t = false; for (line = start; line < end; line++) { int x, oldX, s, e, newX1, newX2; QChar ch; Attribute *a; TextLine::Ptr textLine = getTextLine(line); //--- speed optimization //s = textPos(textLine, x1, newX1); x = oldX = z = 0; while (x < x1) { // && z < len) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } s = z; if (x1 - oldX < x - x1 && z > 0) { s--; newX1 = oldX; } else newX1 = x; //e = textPos(textLine, x2, newX2); while (x < x2) { // && z < len) { oldX = x; ch = textLine->getChar(z); a = &m_attribs[textLine->getAttr(z)]; if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); z++; } e = z; if (x2 - oldX < x - x2 && z > 0) { e--; newX2 = oldX; } else newX2 = x; //--- if (e > s) { textLine->toggleSelect(s, e); tagLineRange(line, newX1, newX2); t = true; } } if (t) { end--; // tagLines(start, end); if (start < selectStart) selectStart = start; if (end > selectEnd) selectEnd = end; emit selectionChanged(); } } void KateDocument::selectTo(VConfig &c, PointStruc &cursor, int cXPos) { //c.cursor = old cursor position //cursor = new cursor position if (c.cursor.x != select.x || c.cursor.y != select.y) { //new selection if (!(c.flags & KateView::cfKeepSelection)) deselectAll(); // else recordReset(); anchor = c.cursor; aXPos = c.cXPos; } if (!(c.flags & KateView::cfVerticalSelect)) { //horizontal selections int x, y, sXPos; int ex, ey, eXPos; bool sel; if (cursor.y > c.cursor.y || (cursor.y == c.cursor.y && cursor.x > c.cursor.x)) { x = c.cursor.x; y = c.cursor.y; sXPos = c.cXPos; ex = cursor.x; ey = cursor.y; eXPos = cXPos; sel = true; } else { x = cursor.x; y = cursor.y; sXPos = cXPos; ex = c.cursor.x; ey = c.cursor.y; eXPos = c.cXPos; sel = false; } // tagLines(y, ye); if (y < ey) { //tagLineRange(y, sXPos, 0xffffff); tagLines(y, ey -1); tagLineRange(ey, 0, eXPos); } else tagLineRange(y, sXPos, eXPos); if (y < selectStart) selectStart = y; if (ey > selectEnd) selectEnd = ey; TextLine::Ptr textLine = getTextLine(y); if (c.flags & KateView::cfXorSelect) { //xor selection with old selection while (y < ey) { textLine->toggleSelectEol(x); x = 0; y++; textLine = getTextLine(y); } textLine->toggleSelect(x, ex); } else { //set selection over old selection if (anchor.y > y || (anchor.y == y && anchor.x > x)) { if (anchor.y < ey || (anchor.y == ey && anchor.x < ex)) { sel = !sel; while (y < anchor.y) { textLine->selectEol(sel, x); x = 0; y++; textLine = getTextLine(y); } textLine->select(sel, x, anchor.x); x = anchor.x; } sel = !sel; } while (y < ey) { textLine->selectEol(sel, x); x = 0; y++; textLine = getTextLine(y); } textLine->select(sel, x, ex); } } else { //vertical (block) selections // int ax, sx, ex; // ax = textWidth(anchor); // sx = textWidth(start); // ex = textWidth(end); toggleRect(c.cursor.y + 1, cursor.y + 1, aXPos, c.cXPos); toggleRect(anchor.y, cursor.y + 1, c.cXPos, cXPos); } select = cursor; optimizeSelection(); emit selectionChanged(); } void KateDocument::selectAll() { int z; TextLine::Ptr textLine; select.x = -1; // if (selectStart != 0 || selectEnd != lastLine()) recordReset(); selectStart = 0; selectEnd = lastLine(); tagLines(selectStart,selectEnd); for (z = selectStart; z < selectEnd; z++) { textLine = getTextLine(z); textLine->selectEol(true,0); } textLine = getTextLine(z); textLine->select(true,0,textLine->length()); emit selectionChanged(); } void KateDocument::deselectAll() { select.x = -1; if (selectEnd < selectStart) return; // recordReset(); tagLines(selectStart,selectEnd); for (int z = selectStart; z <= selectEnd; z++) { TextLine::Ptr textLine = getTextLine(z); textLine->selectEol(false,0); } selectStart = 0xffffff; selectEnd = 0; emit selectionChanged(); } void KateDocument::invertSelection() { TextLine::Ptr textLine; select.x = -1; // if (selectStart != 0 || selectEnd != lastLine()) recordReset(); selectStart = 0; selectEnd = lastLine(); tagLines(selectStart,selectEnd); for (int z = selectStart; z < selectEnd; z++) { textLine = getTextLine(z); textLine->toggleSelectEol(0); } textLine = getTextLine(selectEnd); textLine->toggleSelect(0,textLine->length()); optimizeSelection(); emit selectionChanged(); } void KateDocument::selectWord(PointStruc &cursor, int flags) { int start, end, len; TextLine::Ptr textLine = getTextLine(cursor.y); len = textLine->length(); start = end = cursor.x; while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--; while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++; if (end <= start) return; if (!(flags & KateView::cfKeepSelection)) deselectAll(); // else recordReset(); textLine->select(true, start, end); anchor.x = start; select.x = end; anchor.y = select.y = cursor.y; tagLines(cursor.y, cursor.y); if (cursor.y < selectStart) selectStart = cursor.y; if (cursor.y > selectEnd) selectEnd = cursor.y; emit selectionChanged(); } void KateDocument::selectLength(PointStruc &cursor, int length, int flags) { int start, end; TextLine::Ptr textLine = getTextLine(cursor.y); start = cursor.x; end = start + length; if (end <= start) return; if (!(flags & KateView::cfKeepSelection)) deselectAll(); textLine->select(true, start, end); anchor.x = start; select.x = end; anchor.y = select.y = cursor.y; tagLines(cursor.y, cursor.y); if (cursor.y < selectStart) selectStart = cursor.y; if (cursor.y > selectEnd) selectEnd = cursor.y; emit selectionChanged(); } void KateDocument::doIndent(VConfig &c, int change) { c.cursor.x = 0; recordStart(c, (change < 0) ? KateActionGroup::ugUnindent : KateActionGroup::ugIndent); if (selectEnd < selectStart) { // single line optimizeLeadingSpace(c.cursor.y, c.flags, change); } else { // entire selection TextLine::Ptr textLine; int line, z; QChar ch; if (c.flags & KateView::cfKeepIndentProfile && change < 0) { // unindent so that the existing indent profile doesn´t get screwed // if any line we may unindent is already full left, don't do anything for (line = selectStart; line <= selectEnd; line++) { textLine = getTextLine(line); if (textLine->isSelected() || textLine->numSelected()) { for (z = 0; z < tabChars; z++) { ch = textLine->getChar(z); if (ch == '\t') break; if (ch != ' ') { change = 0; goto jumpOut; } } } } jumpOut:; } for (line = selectStart; line <= selectEnd; line++) { textLine = getTextLine(line); if (textLine->isSelected() || textLine->numSelected()) { optimizeLeadingSpace(line, c.flags, change); } } } // recordEnd now removes empty undo records recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent); } /* Optimize the leading whitespace for a single line. If change is > 0, it adds indentation units (tabChars) if change is == 0, it only optimizes If change is < 0, it removes indentation units This will be used to indent, unindent, and optimal-fill a line. If excess space is removed depends on the flag cfKeepExtraSpaces which has to be set by the user */ void KateDocument::optimizeLeadingSpace(int line, int flags, int change) { int len; int chars, space, okLen; QChar ch; int extra; QString s; PointStruc cursor; TextLine::Ptr textLine = getTextLine(line); len = textLine->length(); space = 0; // length of space at the beginning of the textline okLen = 0; // length of space which does not have to be replaced for (chars = 0; chars < len; chars++) { ch = textLine->getChar(chars); if (ch == ' ') { space++; if (flags & KateView::cfSpaceIndent && okLen == chars) okLen++; } else if (ch == '\t') { space += tabChars - space % tabChars; if (!(flags & KateView::cfSpaceIndent) && okLen == chars) okLen++; } else break; } space += change*tabChars; // modify space width // if line contains only spaces it will be cleared if (space < 0 || chars == len) space = 0; extra = space % tabChars; // extra spaces which don´t fit the indentation pattern if (flags & KateView::cfKeepExtraSpaces) chars -= extra; if (flags & KateView::cfSpaceIndent) { space -= extra; ch = ' '; } else { space /= tabChars; ch = '\t'; } // don´t replace chars which are already ok cursor.x = QMIN(okLen, QMIN(chars, space)); chars -= cursor.x; space -= cursor.x; if (chars == 0 && space == 0) return; //nothing to do s.fill(ch, space); //printf("chars %d insert %d cursor.x %d\n", chars, insert, cursor.x); cursor.y = line; recordReplace(cursor, chars, s); } void KateDocument::doComment(VConfig &c, int change) { c.flags |=KateView:: cfPersistent; recordStart(c, (change < 0) ? KateActionGroup::ugUncomment : KateActionGroup::ugComment); QString startComment = m_highlight->getCommentStart(); QString startLineComment = m_highlight->getCommentSingleLineStart(); QString endComment = m_highlight->getCommentEnd(); int startCommentLen = startComment.length(); int startLineCommentLen = startLineComment.length(); int endCommentLen = endComment.length(); if (change > 0) { if ( !hasMarkedText() ) { if (startLineComment != "") { // Add a start comment mark c.cursor.x = 0; recordReplace(c.cursor, 0, startLineComment); } else if ((startComment != "") && (endComment != "")) { // Add a start comment mark c.cursor.x = 0; recordReplace(c.cursor, 0, startComment); // Add an end comment mark TextLine* textline = getTextLine(c.cursor.y); c.cursor.x = textline->length(); recordReplace(c.cursor, 0, endComment); c.cursor.x = 0; } } else if ((startComment != "") && (endComment != "")) { QString marked (c.view->markedText ()); int preDeleteLine = -1, preDeleteCol = -1; c.view->getCursorPosition (&preDeleteLine, &preDeleteCol); if (marked.length() > 0) c.view->keyDelete (); int line = -1, col = -1; c.view->getCursorPosition (&line, &col); c.view->insertText (startComment + marked + endComment); } } else { if ( !hasMarkedText() ) { TextLine* textline = getTextLine(c.cursor.y); if(textline->startingWith(startLineComment)) { // Remove start comment mark c.cursor.x = 0; recordReplace(c.cursor, startLineCommentLen, ""); } else if (textline->startingWith(startComment) && textline->endingWith(endComment)) { // Remove start comment mark c.cursor.x = 0; recordReplace(c.cursor, startCommentLen, ""); // Remove end comment mark if(endComment != "") { c.cursor.x = textline->length() - endCommentLen; recordReplace(c.cursor, endCommentLen, ""); c.cursor.x = 0; } } } else { QString marked (c.view->markedText ()); int preDeleteLine = -1, preDeleteCol = -1; c.view->getCursorPosition (&preDeleteLine, &preDeleteCol); int start = marked.find (startComment); int end = marked.findRev (endComment); if ((start > -1) && (end > -1)) { marked.remove (start, startCommentLen); marked.remove (end-startCommentLen, endCommentLen); c.view->keyDelete (); int line = -1, col = -1; c.view->getCursorPosition (&line, &col); c.view->insertText (marked); } } } recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent); } QString KateDocument::text() const { QString s; for (int i=0; i < buffer->count(); i++) { TextLine::Ptr textLine = buffer->line(i); s.insert(s.length(), textLine->getText(), textLine->length()); if ( (i < (buffer->count()-1)) ) s.append('\n'); } return s; } QString KateDocument::getWord(PointStruc &cursor) { int start, end, len; TextLine::Ptr textLine = getTextLine(cursor.y); len = textLine->length(); start = end = cursor.x; while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--; while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++; len = end - start; return QString(&textLine->getText()[start], len); } void KateDocument::setText(const QString &s) { int pos; QChar ch; clear(); int line=1; TextLine::Ptr textLine = buffer->line(0); for (pos = 0; pos <= (int) s.length(); pos++) { ch = s[pos]; if (ch.isPrint() || ch == '\t') { textLine->append(&ch, 1); } else if (ch == '\n') { textLine = new TextLine(); buffer->insertLine (line, textLine); line++; } } updateLines(); } QString KateDocument::markedText(int flags) { TextLine::Ptr textLine; int len, z, start, end, i; len = 1; if (!(flags & KateView::cfVerticalSelect)) { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected(); if (textLine->isSelected()) len++; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); if (textLine->isSelected()) { s[len] = '\n'; len++; } } // s[len] = '\0'; return s; } else { for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); len += textLine->numSelected() + 1; } QString s; len = 0; for (z = selectStart; z <= selectEnd; z++) { textLine = getTextLine(z); end = 0; do { start = textLine->findUnselected(end); end = textLine->findSelected(start); for (i = start; i < end; i++) { s[len] = textLine->getChar(i); len++; } } while (start < end); s[len] = '\n'; len++; } // s[len] = '\0'; // the final \0 is not counted in length() return s; } } void KateDocument::delMarkedText(VConfig &c/*, bool undo*/) { int end = 0; if (selectEnd < selectStart) return; // the caller may have already started an undo record for the current action // if (undo) //auto deletion of the marked text occurs not very often and can therefore // be recorded separately recordStart(c, KateActionGroup::ugDelBlock); for (c.cursor.y = selectEnd; c.cursor.y >= selectStart; c.cursor.y--) { TextLine::Ptr textLine = getTextLine(c.cursor.y); c.cursor.x = textLine->length(); do { end = textLine->findRevUnselected(c.cursor.x); if (end == 0) break; c.cursor.x = textLine->findRevSelected(end); recordDelete(c.cursor, end - c.cursor.x); } while (true); end = c.cursor.x; c.cursor.x = textLine->length(); if (textLine->isSelected()) recordAction(KateAction::delLine,c.cursor); } c.cursor.y++; /*if (end < c.cursor.x)*/ c.cursor.x = end; selectEnd = -1; select.x = -1; /*if (undo)*/ recordEnd(c); } void KateDocument::tagLineRange(int line, int x1, int x2) { int z; for (z = 0; z < (int) views.count(); z++) { views.at(z)->tagLines(line, line, x1, x2); } } void KateDocument::tagLines(int start, int end) { int z; for (z = 0; z < (int) views.count(); z++) { views.at(z)->tagLines(start, end, 0, 0xffffff); } } void KateDocument::tagAll() { int z; for (z = 0; z < (int) views.count(); z++) { views.at(z)->tagAll(); } } void KateDocument::updateLines(int startLine, int endLine, int flags, int cursorY) { TextLine::Ptr textLine; int line, last_line; int ctxNum, endCtx; // kdDebug(13020)<<"******************KateDocument::updateLines Checkpoint 1"<<endl; if (buffer->line(startLine)==0) {kdDebug(13020)<<"********************No buffer for line " << startLine << " found**************"<<endl; return;}; // kdDebug(13020)<<"KateDocument::updateLines Checkpoint 2"<<endl; last_line = lastLine(); // if (endLine >= last_line) endLine = last_line; line = startLine; ctxNum = 0; if (line > 0) ctxNum = getTextLine(line - 1)->getContext(); do { // kdDebug(13020)<<QString("**************Working on line: %1").arg(line)<<endl; textLine = getTextLine(line); if (textLine==0) kdDebug(13020)<<"****updateLines()>> error textLine==0"<<endl; if (line <= endLine && line != cursorY) { if (flags & KateView::cfRemoveSpaces) textLine->removeSpaces(); updateMaxLength(textLine); } endCtx = textLine->getContext(); // qDebug("DOHIGHLIGHT"); ctxNum = m_highlight->doHighlight(ctxNum,textLine); textLine->setContext(ctxNum); line++; } while ((buffer->line(line)!=0) && (line <= endLine || endCtx != ctxNum)); // kdDebug(13020)<<"updateLines :: while loop left"<<endl; tagLines(startLine, line - 1); } void KateDocument::updateMaxLength(TextLine::Ptr &textLine) { int len; len = textWidth(textLine,textLine->length()); if (len > maxLength) { longestLine = textLine; maxLength = len; newDocGeometry = true; } else { if (!longestLine || (textLine == longestLine && len <= maxLength*3/4)) { maxLength = -1; for (int i = 0; i < numLines();i++) { textLine = getTextLine(i); len = textWidth(textLine,textLine->length()); if (len > maxLength) { maxLength = len; longestLine = textLine; } } newDocGeometry = true; } } } void KateDocument::slotBufferChanged() { newDocGeometry = true; //updateLines();//JW updateViews(); } void KateDocument::slotBufferHighlight(long start,long stop) { kdDebug(13020)<<"KateDocument::slotBufferHighlight"<<QString("%1-%2").arg(start).arg(stop)<<endl; updateLines(start,stop); // buffer->startLoadTimer(); } void KateDocument::updateViews(KateView *exclude) { KateView *view; int flags; bool markState = hasMarkedText(); flags = (newDocGeometry) ? KateView::ufDocGeometry : 0; for (view = views.first(); view != 0L; view = views.next() ) { if (view != exclude) view->updateView(flags); // notify every view about the changed mark state.... if (oldMarkState != markState) emit view->newMarkStatus(); } oldMarkState = markState; newDocGeometry = false; } QColor &KateDocument::cursorCol(int x, int y) { int attr; Attribute *a; TextLine::Ptr textLine = getTextLine(y); attr = textLine->getRawAttr(x); a = &m_attribs[attr & taAttrMask]; if (attr & taSelected) return a->selCol; else return a->col; } void KateDocument::paintTextLine(QPainter &paint, int line, int xStart, int xEnd, bool showTabs) { paintTextLine (paint, line, 0, xStart, xEnd, showTabs); } void KateDocument::paintTextLine(QPainter &paint, int line, int y, int xStart, int xEnd, bool showTabs) { TextLine::Ptr textLine; int len; const QChar *s; int z, x; QChar ch; Attribute *a = 0L; int attr, nextAttr; int xs; int xc, zc; if (line > lastLine()) { paint.fillRect(0, y, xEnd - xStart,fontHeight, colors[0]); return; } textLine = getTextLine(line); len = textLine->length(); s = textLine->getText(); // skip to first visible character x = 0; z = 0; do { xc = x; zc = z; if (z == len) break; ch = s[z];//textLine->getChar(z); if (ch == '\t') { x += m_tabWidth - (x % m_tabWidth); } else { a = &m_attribs[textLine->getAttr(z)]; if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); } z++; } while (x <= xStart); // draw background xs = xStart; attr = textLine->getRawAttr(zc); while (x < xEnd) { nextAttr = textLine->getRawAttr(z); if ((nextAttr ^ attr) & taSelected) { if (attr & taSelected) paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[1]); else paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[0]); xs = x; attr = nextAttr; } if (z == len) break; ch = s[z];//textLine->getChar(z); if (ch == '\t') x += m_tabWidth - (x % m_tabWidth); else { a = &m_attribs[textLine->getAttr(z)]; if (a->bold && a->italic) x += myFontMetricsBI.width(ch); else if (a->bold) x += myFontMetricsBold.width(ch); else if (a->italic) x += myFontMetricsItalic.width(ch); else x += myFontMetrics.width(ch); } z++; } if (attr & taSelected) paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[1]); else paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[0]); len = z; //reduce length to visible length // draw text x = xc; z = zc; y += fontAscent;// -1; attr = -1; while (z < len) { ch = s[z];//textLine->getChar(z); if (ch == '\t') { if (z > zc) { //this should cause no copy at all QConstString str((QChar *) &s[zc], z - zc /*+1*/); QString s = str.string(); paint.drawText(x - xStart, y, s); if (a->bold && a->italic) x += myFontMetricsBI.width(s); else if (a->bold) x += myFontMetricsBold.width(s); else if (a->italic) x += myFontMetricsItalic.width(s); else x += myFontMetrics.width(s); } zc = z +1; if (showTabs) { nextAttr = textLine->getRawAttr(z); if (nextAttr != attr) { attr = nextAttr; a = &m_attribs[attr & taAttrMask]; if (attr & taSelected) paint.setPen(a->selCol); else paint.setPen(a->col); if (a->bold && a->italic) paint.setFont(myFontBI); else if (a->bold) paint.setFont(myFontBold); else if (a->italic) paint.setFont(myFontItalic); else paint.setFont(myFont); } // paint.drawLine(x - xStart, y -2, x - xStart, y); // paint.drawLine(x - xStart, y, x - xStart + 2, y); paint.drawPoint(x - xStart, y); paint.drawPoint(x - xStart +1, y); paint.drawPoint(x - xStart, y -1); } x += m_tabWidth - (x % m_tabWidth); } else { nextAttr = textLine->getRawAttr(z); if (nextAttr != attr) { if (z > zc) { QConstString str((QChar *) &s[zc], z - zc /*+1*/); QString s = str.string(); paint.drawText(x - xStart, y, s); if (a->bold && a->italic) x += myFontMetricsBI.width(s); else if (a->bold) x += myFontMetricsBold.width(s); else if (a->italic) x += myFontMetricsItalic.width(s); else x += myFontMetrics.width(s); zc = z; } attr = nextAttr; a = &m_attribs[attr & taAttrMask]; if (attr & taSelected) paint.setPen(a->selCol); else paint.setPen(a->col); if (a->bold && a->italic) paint.setFont(myFontBI); else if (a->bold) paint.setFont(myFontBold); else if (a->italic) paint.setFont(myFontItalic); else paint.setFont(myFont); } } z++; } if (z > zc) { QConstString str((QChar *) &s[zc], z - zc /*+1*/); paint.drawText(x - xStart, y, str.string()); } } // Applies the search context, and returns whether a match was found. If one is, // the length of the string matched is also returned. bool KateDocument::doSearch(SConfig &sc, const QString &searchFor) { int line, col; int searchEnd; int bufLen, tlen; QChar *t; TextLine::Ptr textLine; int pos, newPos; if (searchFor.isEmpty()) return false; bufLen = 0; t = 0L; line = sc.cursor.y; col = sc.cursor.x; if (!(sc.flags & KateView::sfBackward)) { //forward search if (sc.flags & KateView::sfSelected) { if (line < selectStart) { line = selectStart; col = 0; } searchEnd = selectEnd; } else searchEnd = lastLine(); while (line <= searchEnd) { textLine = getTextLine(line); tlen = textLine->length(); if (tlen > bufLen) { delete t; bufLen = (tlen + 255) & (~255); t = new QChar[bufLen]; } memcpy(t, textLine->getText(), tlen*sizeof(QChar)); if (sc.flags & KateView::sfSelected) { pos = 0; do { pos = textLine->findSelected(pos); newPos = textLine->findUnselected(pos); memset(&t[pos], 0, (newPos - pos)*sizeof(QChar)); pos = newPos; } while (pos < tlen); } QString text(t, tlen); if (sc.flags & KateView::sfWholeWords) { // Until the end of the line... while (col < tlen) { // ...find the next match. col = sc.search(text, col); if (col != -1) { // Is the match delimited correctly? if (((col == 0) || (!m_highlight->isInWord(t[col]))) && ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) { goto found; } else { // Start again from the next character. col++; } } else { // No match. break; } } } else { // Non-whole-word search. col = sc.search(text, col); if (col != -1) goto found; } col = 0; line++; } } else { // backward search if (sc.flags & KateView::sfSelected) { if (line > selectEnd) { line = selectEnd; col = -1; } searchEnd = selectStart; } else searchEnd = 0; while (line >= searchEnd) { textLine = getTextLine(line); tlen = textLine->length(); if (tlen > bufLen) { delete t; bufLen = (tlen + 255) & (~255); t = new QChar[bufLen]; } memcpy(t, textLine->getText(), tlen*sizeof(QChar)); if (sc.flags & KateView::sfSelected) { pos = 0; do { pos = textLine->findSelected(pos); newPos = textLine->findUnselected(pos); memset(&t[pos], 0, (newPos - pos)*sizeof(QChar)); pos = newPos; } while (pos < tlen); } if (col < 0 || col > tlen) col = tlen; QString text(t, tlen); if (sc.flags & KateView::sfWholeWords) { // Until the beginning of the line... while (col >= 0) { // ...find the next match. col = sc.search(text, col); if (col != -1) { // Is the match delimited correctly? if (((col == 0) || (!m_highlight->isInWord(t[col]))) && ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) { goto found; } else { // Start again from the previous character. col--; } } else { // No match. break; } } } else { // Non-whole-word search. col = sc.search(text, col); if (col != -1) goto found; } col = -1; line--; } } sc.flags |= KateView::sfWrapped; return false; found: if (sc.flags & KateView::sfWrapped) { if ((line > sc.startCursor.y || (line == sc.startCursor.y && col >= sc.startCursor.x)) ^ ((sc.flags & KateView::sfBackward) != 0)) return false; } sc.cursor.x = col; sc.cursor.y = line; return true; } void KateDocument::tagLine(int line) { if (tagStart > line) tagStart = line; if (tagEnd < line) tagEnd = line; } void KateDocument::insLine(int line) { KateView *view; if (selectStart >= line) selectStart++; if (selectEnd >= line) selectEnd++; if (tagStart >= line) tagStart++; if (tagEnd >= line) tagEnd++; newDocGeometry = true; for (view = views.first(); view != 0L; view = views.next() ) { view->insLine(line); } } void KateDocument::delLine(int line) { KateView *view; if (selectStart >= line && selectStart > 0) selectStart--; if (selectEnd >= line) selectEnd--; if (tagStart >= line && tagStart > 0) tagStart--; if (tagEnd >= line) tagEnd--; newDocGeometry = true; for (view = views.first(); view != 0L; view = views.next() ) { view->delLine(line); } } void KateDocument::optimizeSelection() { TextLine::Ptr textLine; while (selectStart <= selectEnd) { textLine = getTextLine(selectStart); if (textLine->isSelected() || textLine->numSelected() > 0) break; selectStart++; } while (selectEnd >= selectStart) { textLine = getTextLine(selectEnd); if (textLine->isSelected() || textLine->numSelected() > 0) break; selectEnd--; } if (selectStart > selectEnd) { selectStart = 0xffffff; selectEnd = 0; } } void KateDocument::doAction(KateAction *a) { switch (a->action) { case KateAction::replace: doReplace(a); break; case KateAction::wordWrap: doWordWrap(a); break; case KateAction::wordUnWrap: doWordUnWrap(a); break; case KateAction::newLine: doNewLine(a); break; case KateAction::delLine: doDelLine(a); break; case KateAction::insLine: doInsLine(a); break; case KateAction::killLine: doKillLine(a); break; /* case KateAction::doubleLine: break; case KateAction::removeLine: break;*/ } } void KateDocument::doReplace(KateAction *a) { TextLine::Ptr textLine; int l; //exchange current text with stored text in KateAction *a textLine = getTextLine(a->cursor.y); l = textLine->length() - a->cursor.x; if (l > a->len) l = a->len; QString oldText(&textLine->getText()[a->cursor.x], (l < 0) ? 0 : l); textLine->replace(a->cursor.x, a->len, a->text.unicode(), a->text.length()); a->len = a->text.length(); a->text = oldText; buffer->changeLine(a->cursor.y); tagLine(a->cursor.y); } void KateDocument::doWordWrap(KateAction *a) { TextLine::Ptr textLine; textLine = getTextLine(a->cursor.y - 1); a->len = textLine->length() - a->cursor.x; textLine->wrap(getTextLine(a->cursor.y),a->len); buffer->changeLine(a->cursor.y - 1); buffer->changeLine(a->cursor.y); tagLine(a->cursor.y - 1); tagLine(a->cursor.y); if (selectEnd == a->cursor.y - 1) selectEnd++; a->action = KateAction::wordUnWrap; } void KateDocument::doWordUnWrap(KateAction *a) { TextLine::Ptr textLine; textLine = getTextLine(a->cursor.y - 1); // textLine->setLength(a->len); textLine->unWrap(a->len, getTextLine(a->cursor.y),a->cursor.x); buffer->changeLine(a->cursor.y - 1); buffer->changeLine(a->cursor.y); tagLine(a->cursor.y - 1); tagLine(a->cursor.y); a->action = KateAction::wordWrap; } void KateDocument::doNewLine(KateAction *a) { TextLine::Ptr textLine, newLine; textLine = getTextLine(a->cursor.y); newLine = new TextLine(textLine->getRawAttr(), textLine->getContext()); textLine->wrap(newLine,a->cursor.x); buffer->insertLine(a->cursor.y + 1, newLine); buffer->changeLine(a->cursor.y); insLine(a->cursor.y + 1); tagLine(a->cursor.y); tagLine(a->cursor.y + 1); if (selectEnd == a->cursor.y) selectEnd++;//addSelection(a->cursor.y + 1); a->action = KateAction::delLine; } void KateDocument::doDelLine(KateAction *a) { TextLine::Ptr textLine, nextLine; textLine = getTextLine(a->cursor.y); nextLine = getTextLine(a->cursor.y+1); // textLine->setLength(a->cursor.x); textLine->unWrap(a->cursor.x, nextLine,nextLine->length()); textLine->setContext(nextLine->getContext()); if (longestLine == nextLine) longestLine = 0L; buffer->changeLine(a->cursor.y); buffer->removeLine(a->cursor.y+1); tagLine(a->cursor.y); delLine(a->cursor.y + 1); a->action = KateAction::newLine; } void KateDocument::doInsLine(KateAction *a) { buffer->insertLine(a->cursor.y, new TextLine()); insLine(a->cursor.y); a->action = KateAction::killLine; } void KateDocument::doKillLine(KateAction *a) { TextLine::Ptr textLine = getTextLine(a->cursor.y); if (longestLine == textLine) longestLine = 0L; buffer->removeLine(a->cursor.y); delLine(a->cursor.y); tagLine(a->cursor.y); a->action = KateAction::insLine; } void KateDocument::newUndo() { KTextEditor::View *view; int state; state = 0; if (currentUndo > 0) state |= 1; if (currentUndo < (int) undoList.count()) state |= 2; undoState = state; for (view = m_views.first(); view != 0L; view = m_views.next() ) { emit static_cast<KateView *>( view )->newUndo(); } } void KateDocument::recordStart(VConfig &c, int newUndoType) { recordStart(c.view, c.cursor, c.flags, newUndoType); } void KateDocument::recordStart(KateView *, PointStruc &cursor, int flags, int newUndoType, bool keepModal, bool mergeUndo) { KateActionGroup *g; // if (newUndoType == KateActionGroup::ugNone) { // only a bug would cause this //why should someone do this? we can't prevent all programming errors :) (jochen whilhelmy) // debug("KateDocument::recordStart() called with no undo group type!"); // return; // } if (!keepModal) setPseudoModal(0L); //i optimized the group undo stuff a bit (jochen wilhelmy) // recordReset() is not needed any more g = undoList.getLast(); if (g != 0L && ((undoCount < 1024 && flags & KateView::cfGroupUndo && g->end.x == cursor.x && g->end.y == cursor.y) || mergeUndo)) { //undo grouping : same actions are put into one undo step //precondition : new action starts where old stops or mergeUndo flag if (g->undoType == newUndoType || (g->undoType == KateActionGroup::ugInsChar && newUndoType == KateActionGroup::ugInsLine) || (g->undoType == KateActionGroup::ugDelChar && newUndoType == KateActionGroup::ugDelLine)) { undoCount++; if (g->undoType != newUndoType) undoCount = 0xffffff; return; } } undoCount = 0; /* if (undoView != view) { // always kill the current undo group if the editing view changes recordReset(); undoType = newUndoType; } else if (newUndoType == undoType) { printf("bla!!!\n"); // same as current type, keep using it return; } else if ( (undoType == KateActionGroup::ugInsChar && newUndoType == KateActionGroup::ugInsLine) || (undoType == KateActionGroup::ugDelChar && newUndoType == KateActionGroup::ugDelLine) ) { // some type combinations can run together... undoType += 1000; return; } else { recordReset(); undoType = newUndoType; } undoView = view; */ while ((int) undoList.count() > currentUndo) undoList.removeLast(); while ((int) undoList.count() > undoSteps) { undoList.removeFirst(); currentUndo--; } g = new KateActionGroup(cursor, newUndoType); undoList.append(g); // currentUndo++; tagEnd = 0; tagStart = 0xffffff; } void KateDocument::recordAction(KateAction::Action action, PointStruc &cursor) { KateAction *a; a = new KateAction(action, cursor); doAction(a); undoList.getLast()->insertAction(a); } void KateDocument::recordInsert(VConfig &c, const QString &text) { recordReplace(c, 0, text); } void KateDocument::recordReplace(VConfig &c, int len, const QString &text) { if (c.cursor.x > 0 && !(c.flags & KateView::cfSpaceIndent)) { TextLine::Ptr textLine = getTextLine(c.cursor.y); if (textLine->length() == 0) { QString s = tabString(c.cursor.x, tabChars); int len = s.length(); s += text; c.cursor.x = 0; recordReplace(c.cursor, len, s); c.cursor.x = len; return; } } recordReplace(c.cursor, len, text); } void KateDocument::recordInsert(PointStruc &cursor, const QString &text) { recordReplace(cursor, 0, text); } void KateDocument::recordDelete(PointStruc &cursor, int len) { recordReplace(cursor, len, QString::null); } void KateDocument::recordReplace(PointStruc &cursor, int len, const QString &text) { KateAction *a; TextLine::Ptr textLine; int l; if (len == 0 && text.isEmpty()) return; //try to append to last replace action a = undoList.getLast()->action; if (a == 0L || a->action != KateAction::replace || a->cursor.x + a->len != cursor.x || a->cursor.y != cursor.y) { //if (a != 0L) printf("new %d %d\n", a->cursor.x + a->len, cursor.x); a = new KateAction(KateAction::replace, cursor); undoList.getLast()->insertAction(a); } //replace textLine = getTextLine(cursor.y); l = textLine->length() - cursor.x; if (l > len) l = len; a->text.insert(a->text.length(), &textLine->getText()[cursor.x], (l < 0) ? 0 : l); textLine->replace(cursor.x, len, text.unicode(), text.length()); a->len += text.length(); buffer->changeLine(a->cursor.y); updateMaxLength(textLine); tagLine(a->cursor.y); } void KateDocument::recordEnd(VConfig &c) { recordEnd(c.view, c.cursor, c.flags); } void KateDocument::recordEnd(KateView *view, PointStruc &cursor, int flags) { KateActionGroup *g; // clear selection if option "persistent selections" is off // if (!(flags & cfPersistent)) deselectAll(); g = undoList.getLast(); if (g->action == 0L) { // no action has been done: remove empty undo record undoList.removeLast(); return; } // store end cursor position for redo g->end = cursor; currentUndo = undoList.count(); if (tagStart <= tagEnd) { optimizeSelection(); updateLines(tagStart, tagEnd, flags, cursor.y); setModified(true); } view->updateCursor(cursor, flags); // newUndo(); /* undoCount++; // we limit the number of individual undo operations for sanity - is 1K reasonable? // this is also where we handle non-group undo preference // if the undo type is singlular, we always finish it now if ( undoType == KateActionGroup::ugPaste || undoType == KateActionGroup::ugDelBlock || undoType > 1000 || undoCount > 1024 || !(flags & cfGroupUndo) ) { printf("recordend %d %d\n", undoType, undoCount); recordReset(); } */ // this should keep the flood of signals down a little... if (undoCount == 0) newUndo(); emit textChanged(); } /* void KateDocument::recordReset() { if (pseudoModal) return; // forces the next call of recordStart() to begin a new undo group // not used in normal editing, but used by markFound(), etc. undoType = KateActionGroup::ugNone; undoCount = 0; undoView = NULL; undoReported = false; printf("recordreset\n"); } */ /* void KateDocument::recordDel(PointStruc &cursor, TextLine::Ptr &textLine, int l) { int len; len = textLine->length() - cursor.x; if (len > l) len = l; if (len > 0) { insertUndo(new KateAction(KateAction::replace,cursor,&textLine->getText()[cursor.x],len)); } } */ void KateDocument::doActionGroup(KateActionGroup *g, int flags, bool undo) { KateAction *a, *next; setPseudoModal(0L); if (!(flags & KateView::cfPersistent)) deselectAll(); tagEnd = 0; tagStart = 0xffffff; a = g->action; g->action = 0L; while (a) { doAction(a); next = a->next; g->insertAction(a); a = next; } optimizeSelection(); if (tagStart <= tagEnd) updateLines(tagStart, tagEnd, flags); // the undo/redo functions set undo to true, all others should leave it // alone (default) if (!undo) { setModified(true); newUndo(); } } int KateDocument::nextUndoType() { KateActionGroup *g; if (currentUndo <= 0) return KateActionGroup::ugNone; g = undoList.at(currentUndo - 1); return g->undoType; } int KateDocument::nextRedoType() { KateActionGroup *g; if (currentUndo >= (int) undoList.count()) return KateActionGroup::ugNone; g = undoList.at(currentUndo); // if (!g) return KateActionGroup::ugNone; return g->undoType; } void KateDocument::undoTypeList(QValueList<int> &lst) { lst.clear(); for (int i = currentUndo-1; i>=0 ;i--) lst.append(undoList.at(i)->undoType); } void KateDocument::redoTypeList(QValueList<int> &lst) { lst.clear(); for (int i = currentUndo+1; i<(int)undoList.count(); i++) lst.append(undoList.at(i)->undoType); } void KateDocument::undo(VConfig &c, int count) { KateActionGroup *g = 0L; int num; bool needUpdate = false; // don't update the cursor until completely done if (count <= 0) return; for (num = 0 ; num < count ; num++) { if (currentUndo <= 0) break; currentUndo--; g = undoList.at(currentUndo); doActionGroup(g, c.flags, true); // do not setModified() or newUndo() needUpdate = true; // if (num == 0) recordReset(); } if (needUpdate) { // since we told doActionGroup() not to do this stuff, we need to do it now c.view->updateCursor(g->start); setModified(true); newUndo(); } } void KateDocument::redo(VConfig &c, int count) { KateActionGroup *g = 0L; int num; bool needUpdate = false; // don't update the cursor until completely done if (count <= 0) return; for (num = 0 ; num < count ; num++) { if (currentUndo+1 > (int)undoList.count()) break; g = undoList.at(currentUndo); currentUndo++; doActionGroup(g, c.flags, true); // do not setModified() or newUndo() needUpdate = true; // if (num == 0) recordReset(); } if (needUpdate) { // since we told doActionGroup() not to do this stuff, we need to do it now c.view->updateCursor(g->end); setModified(true); newUndo(); } } void KateDocument::clearRedo() { // disable redos // this was added as an assist to the spell checker bool deleted = false; while ((int) undoList.count() > currentUndo) { deleted = true; undoList.removeLast(); } if (deleted) newUndo(); } void KateDocument::setUndoSteps(int steps) { if (steps < 5) steps = 5; undoSteps = steps; } void KateDocument::setPseudoModal(QWidget *w) { // QWidget *old = pseudoModal; // (glenebob) // this is a temporary hack to make the spell checker work a little // better - as kspell progresses, this sort of thing should become // obsolete or worked around more cleanly // this is relied upon *only* by the spell-check code if (pseudoModal && pseudoModal != (QWidget*)1L) delete pseudoModal; // pseudoModal = 0L; // if (old || w) recordReset(); pseudoModal = w; } void KateDocument::newBracketMark(PointStruc &cursor, BracketMark &bm) { TextLine::Ptr textLine; int x, line, count, attr; QChar bracket, opposite, ch; Attribute *a; bm.eXPos = -1; //mark bracked mark as invalid x = cursor.x -1; // -1 to look at left side of cursor if (x < 0) return; line = cursor.y; //current line count = 0; //bracket counter for nested brackets textLine = getTextLine(line); if (!textLine) return; bracket = textLine->getChar(x); attr = textLine->getAttr(x); if (bracket == '(' || bracket == '[' || bracket == '{') { //get opposite bracket opposite = ')'; if (bracket == '[') opposite = ']'; if (bracket == '{') opposite = '}'; //get attribute of bracket (opposite bracket must have the same attribute) x++; while (line - cursor.y < 40) { //go to next line on end of line while (x >= (int) textLine->length()) { line++; if (line > lastLine()) return; textLine = getTextLine(line); x = 0; } if (textLine->getAttr(x) == attr) { //try to find opposite bracked ch = textLine->getChar(x); if (ch == bracket) count++; //same bracket : increase counter if (ch == opposite) { count--; if (count < 0) goto found; } } x++; } } else if (bracket == ')' || bracket == ']' || bracket == '}') { opposite = '('; if (bracket == ']') opposite = '['; if (bracket == '}') opposite = '{'; x--; while (cursor.y - line < 20) { while (x < 0) { line--; if (line < 0) return; textLine = getTextLine(line); x = textLine->length() -1; } if (textLine->getAttr(x) == attr) { ch = textLine->getChar(x); if (ch == bracket) count++; if (ch == opposite) { count--; if (count < 0) goto found; } } x--; } } return; found: //cursor position of opposite bracket bm.cursor.x = x; bm.cursor.y = line; //x position (start and end) of related bracket bm.sXPos = textWidth(textLine, x); a = &m_attribs[attr]; if (a->bold && a->italic) bm.eXPos = bm.sXPos + myFontMetricsBI.width(bracket); else if (a->bold) bm.eXPos = bm.sXPos + myFontMetricsBold.width(bracket); else if (a->italic) bm.eXPos = bm.sXPos + myFontMetricsItalic.width(bracket); else bm.eXPos = bm.sXPos + myFontMetrics.width(bracket); } void KateDocument::clipboardChanged() { //slot //#if defined(_WS_X11_) if (m_singleSelection) { disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged())); deselectAll(); updateViews(); } //#endif } #if 0 void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev ) { KParts::ReadWritePart::guiActivateEvent( ev ); if ( ev->activated() ) emit selectionChanged(); } #endif void KateDocument::setDocName (QString docName) { myDocName = docName; emit nameChanged (this); } void KateDocument::setDocFile (QString docFile) { m_file = docFile; emit fileNameChanged (); } void KateDocument::setMTime() { if (fileInfo && !fileInfo->fileName().isEmpty()) { fileInfo->refresh(); mTime = fileInfo->lastModified(); } } void KateDocument::isModOnHD(bool forceReload) { if (fileInfo && !fileInfo->fileName().isEmpty()) { fileInfo->refresh(); if (fileInfo->lastModified() > mTime) { if ( forceReload || (KMessageBox::warningContinueCancel(0, (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), i18n("File has changed on Disk"), i18n("Yes") ) == KMessageBox::Continue) ) reloadFile(); else setMTime(); } } } void KateDocument::reloadFile() { #warning fixme #if 0 if (fileInfo && !fileInfo->fileName().isEmpty()) { KateDocument::openFile(); setMTime(); } #endif } void KateDocument::slotModChanged() { emit modStateChanged (this); } QList<Kate::Mark> KateDocument::marks () { QList<Kate::Mark> list; TextLine::Ptr line; for (int i=0; i < numLines(); i++) { line = getTextLine(i); if (line->mark() != 0) { Kate::Mark *mark=new Kate::Mark; mark->line = i; mark->type = line->mark(); list.append (mark); } } return list; } void KateDocument::flush () { if (isReadOnly()) return; m_url = QString::null; fileInfo->setFile (QString()); setMTime(); clear(); updateViews(); emit fileNameChanged (); } void KateDocument::open (const QString &name) { openURL (name); } void KateDocument::wrapText (uint col) { int line = 0; int z = 0; while(true) { TextLine::Ptr l = getTextLine(line); if (l->length() > col) { TextLine::Ptr tl = new TextLine(); buffer->insertLine(line+1,tl); const QChar *text = l->getText(); for (z=col; z>0; z--) { if (z < 1) break; if (text[z].isSpace()) break; } if (z < 1) z=col; l->wrap (tl, z); } line++; if (line >= numLines()) break; }; newDocGeometry=true; updateLines(); updateViews(); } void KateDocument::setWordWrap (bool on) { if (on != myWordWrap && on) wrapText (myWordWrapAt); myWordWrap = on; } void KateDocument::setWordWrapAt (uint col) { if (myWordWrapAt != col && myWordWrap) wrapText (myWordWrapAt); myWordWrapAt = col; } void KateDocument::applyWordWrap () { wrapText (myWordWrapAt); } diff --git a/noncore/apps/tinykate/libkate/document/katedocument.h b/noncore/apps/tinykate/libkate/document/katedocument.h index 356541f..9d8ec6a 100644 --- a/noncore/apps/tinykate/libkate/document/katedocument.h +++ b/noncore/apps/tinykate/libkate/document/katedocument.h @@ -1,570 +1,570 @@ /*************************************************************************** katedocument.h - description ------------------- begin : Mon Jan 15 2001 copyright : (C) 2001 by Christoph "Crossfire" Cullmann (C) 2002 by Joseph Wenninger email : crossfire@babylon2k.de jowenn@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* Copyright (C) 1998, 1999 Jochen Wilhelmy digisnap@cs.tu-berlin.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef kate_document_h #define kate_document_h #include <qobject.h> #include <qlist.h> #include <qcolor.h> #include <qfont.h> #include <qfontmetrics.h> #include <qdatetime.h> #include <qfileinfo.h> #include "../view/kateview.h" #include "katehighlight.h" #include "katebuffer.h" #include "katetextline.h" #include <qptrdict.h> class KateCmd; class CachedFontMetrics : public QFontMetrics { private: short *warray[256]; public: CachedFontMetrics(const QFont& f) : QFontMetrics(f) { for (int i=0; i<256; i++) warray[i]=0; } ~CachedFontMetrics() { for (int i=0; i<256; i++) if (warray[i]) delete[] warray[i]; } int width(QChar c) { uchar cell=c.cell(); uchar row=c.row(); short *wa=warray[row]; if (!wa) { // qDebug("create row: %d",row); wa=warray[row]=new short[256]; for (int i=0; i<256; i++) wa[i]=-1; } if (wa[cell]<0) wa[cell]=(short) QFontMetrics::width(c); return (int)wa[cell]; } int width(QString s) { return QFontMetrics::width(s); } }; class Attribute { public: Attribute() { ; }; QColor col; QColor selCol; bool bold; bool italic; }; class KateAction { public: enum Action {replace, wordWrap, wordUnWrap, newLine, delLine, insLine, killLine};//, doubleLine, removeLine}; KateAction(Action, PointStruc &cursor, int len = 0, const QString &text = QString::null); Action action; PointStruc cursor; int len; QString text; KateAction *next; }; class KateActionGroup { public: // the undo group types enum { ugNone, // ugPaste, // paste ugDelBlock, // delete/replace selected text ugIndent, // indent ugUnindent, // unindent ugComment, // comment ugUncomment, // uncomment ugReplace, // text search/replace ugSpell, // spell check ugInsChar, // char type/deleting ugDelChar, // '' '' ugInsLine, // line insert/delete ugDelLine // '' '' }; KateActionGroup(PointStruc &aStart, int type = ugNone); ~KateActionGroup(); void insertAction(KateAction *); static const char * typeName(int type); PointStruc start; PointStruc end; KateAction *action; int undoType; }; /** The text document. It contains the textlines, controls the document changing operations and does undo/redo. WARNING: do not change the text contents directly in methods where this is not explicitly permitted. All changes have to be made with some basic operations, which are recorded by the undo/redo system. @see TextLine @author Jochen Wilhelmy */ class KateDocument: public Kate::Document { Q_OBJECT friend class KateViewInternal; friend class KateView; friend class KateIconBorder; public: KateDocument(bool bSingleViewMode=false, bool bBrowserView=false, QWidget *parentWidget = 0, const char *widgetName = 0, QObject * = 0, const char * = 0); ~KateDocument(); protected: QFont myFont, myFontBold, myFontItalic, myFontBI; CachedFontMetrics myFontMetrics, myFontMetricsBold, myFontMetricsItalic, myFontMetricsBI; public: void setFont (QFont font); QFont getFont () { return myFont; }; CachedFontMetrics getFontMetrics () { return myFontMetrics; }; virtual bool saveFile(); virtual KTextEditor::View *createView( QWidget *parent, const char *name ); virtual QString textLine( int line ) const; virtual void insertLine( const QString &s, int line = -1 ); void insert_Line(const QString& s,int line=-1, bool update=true); void remove_Line(int line,bool update=true); void replaceLine(const QString& s,int line=-1); virtual void insertAt( const QString &s, int line, int col, bool mark = FALSE ); virtual void removeLine( int line ); virtual int length() const; virtual void setSelection( int row_from, int col_from, int row_to, int col_t ); virtual bool hasSelection() const; virtual QString selection() const; // only to make part work, don't change it ! bool m_bSingleViewMode; // public interface /** * gets the number of lines */ virtual int numLines() const; /** * gets the last line number (numLines() -1) */ int lastLine() const {return numLines()-1;} /** gets the given line @return the TextLine object at the given line @see TextLine */ TextLine::Ptr getTextLine(int line) const; /** get the length in pixels of the given line */ int textLength(int line); void setTabWidth(int); int tabWidth() {return tabChars;} void setReadOnly(bool); bool isReadOnly() const; void setNewDoc( bool ); bool isNewDoc() const; virtual void setReadWrite( bool ){}; virtual bool isReadWrite() const {return true;} virtual void setModified(bool); virtual bool isModified() const; void setSingleSelection(bool ss) {m_singleSelection = ss;} bool singleSelection() {return m_singleSelection;} void readConfig(); void writeConfig(); - void readSessionConfig(KConfig *); - void writeSessionConfig(KConfig *); + void readSessionConfig(KateConfig *); + void writeSessionConfig(KateConfig *); bool hasBrowserExtension() const { return m_bBrowserView; } protected: bool m_bBrowserView; signals: void selectionChanged(); void highlightChanged(); void modifiedChanged (); void preHighlightChanged(long); // search stuff protected: static QStringList searchForList; static QStringList replaceWithList; static uint uniqueID; // highlight stuff public: Highlight *highlight() {return m_highlight;} int highlightNum() {return hlManager->findHl(m_highlight);} int numAttribs() {return m_numAttribs;} Attribute *attribs() {return m_attribs;} void setDontChangeHlOnSave(); protected: void setHighlight(int n); void makeAttribs(); void updateFontData(); protected slots: void hlChanged(); // view interaction public: virtual void addView(KTextEditor::View *); virtual void removeView(KTextEditor::View *); bool ownedView(KateView *); bool isLastView(int numViews); int getTextLineCount() {return numLines();} int textWidth(const TextLine::Ptr &, int cursorX); int textWidth(PointStruc &cursor); int textWidth(bool wrapCursor, PointStruc &cursor, int xPos); int textPos(const TextLine::Ptr &, int xPos); // int textPos(TextLine::Ptr &, int xPos, int &newXPos); int textWidth(); int textHeight(); void insert(VConfig &, const QString &); void insertFile(VConfig &, QIODevice &); int currentColumn(PointStruc &cursor); bool insertChars(VConfig &, const QString &chars); void newLine(VConfig &); void killLine(VConfig &); void backspace(VConfig &); void del(VConfig &); void clear(); void cut(VConfig &); void copy(int flags); void paste(VConfig &); void toggleRect(int, int, int, int); void selectTo(VConfig &c, PointStruc &cursor, int cXPos); void selectAll(); void deselectAll(); void invertSelection(); void selectWord(PointStruc &cursor, int flags); void selectLength(PointStruc &cursor, int length, int flags); void indent(VConfig &c) {doIndent(c, 1);} void unIndent(VConfig &c) {doIndent(c, -1);} void cleanIndent(VConfig &c) {doIndent(c, 0);} // called by indent/unIndent/cleanIndent // just does some setup and then calls optimizeLeadingSpace() void doIndent(VConfig &, int change); // optimize leading whitespace on a single line - see kwdoc.cpp for full description void optimizeLeadingSpace(int line, int flags, int change); void comment(VConfig &c) {doComment(c, 1);} void unComment(VConfig &c) {doComment(c, -1);} void doComment(VConfig &, int change); virtual QString text() const; QString getWord(PointStruc &cursor); public slots: virtual void setText(const QString &); public: long needPreHighlight(long till); bool hasMarkedText() {return (selectEnd >= selectStart);} QString markedText(int flags); void delMarkedText(VConfig &/*, bool undo = true*/); void tagLineRange(int line, int x1, int x2); void tagLines(int start, int end); void tagAll(); void updateLines(int startLine = 0, int endLine = 0xffffff, int flags = 0, int cursorY = -1); void updateMaxLength(TextLine::Ptr &); void updateViews(KateView *exclude = 0L); QColor &cursorCol(int x, int y); void paintTextLine(QPainter &, int line, int xStart, int xEnd, bool showTabs); void paintTextLine(QPainter &, int line, int y, int xStart, int xEnd, bool showTabs); bool doSearch(SConfig &s, const QString &searchFor); // internal void tagLine(int line); void insLine(int line); void delLine(int line); void optimizeSelection(); void doAction(KateAction *); void doReplace(KateAction *); void doWordWrap(KateAction *); void doWordUnWrap(KateAction *); void doNewLine(KateAction *); void doDelLine(KateAction *); void doInsLine(KateAction *); void doKillLine(KateAction *); void newUndo(); void recordStart(VConfig &, int newUndoType); void recordStart(KateView *, PointStruc &, int flags, int newUndoType, bool keepModal = false, bool mergeUndo = false); void recordAction(KateAction::Action, PointStruc &); void recordInsert(VConfig &, const QString &text); void recordReplace(VConfig &, int len, const QString &text); void recordInsert(PointStruc &, const QString &text); void recordDelete(PointStruc &, int len); void recordReplace(PointStruc &, int len, const QString &text); void recordEnd(VConfig &); void recordEnd(KateView *, PointStruc &, int flags); void doActionGroup(KateActionGroup *, int flags, bool undo = false); int nextUndoType(); int nextRedoType(); void undoTypeList(QValueList<int> &lst); void redoTypeList(QValueList<int> &lst); void undo(VConfig &, int count = 1); void redo(VConfig &, int count = 1); void clearRedo(); void setUndoSteps(int steps); void setPseudoModal(QWidget *); void newBracketMark(PointStruc &, BracketMark &); protected slots: void clipboardChanged(); void slotBufferChanged(); void slotBufferHighlight(long,long); void doPreHighlight(); private slots: void slotViewDestroyed(); // member variables protected: long PreHighlightedTill; long RequestPreHighlightTill; KWBuffer *buffer; QColor colors[2]; HlManager *hlManager; Highlight *m_highlight; int m_numAttribs; static const int maxAttribs; Attribute *m_attribs; int eolMode; int tabChars; int m_tabWidth; int fontHeight; int fontAscent; QList<KateView> views; bool newDocGeometry; TextLine::Ptr longestLine; float maxLength; PointStruc select; PointStruc anchor; int aXPos; int selectStart; int selectEnd; bool oldMarkState; bool m_singleSelection; // false: windows-like, true: X11-like bool readOnly; bool newDoc; // True if the file is a new document (used to determine whether // to check for overwriting files on save) bool modified; bool myWordWrap; uint myWordWrapAt; QList<KateActionGroup> undoList; int currentUndo; int undoState; int undoSteps; int tagStart; int tagEnd; int undoCount; //counts merged undo steps QWidget *pseudoModal; //the replace prompt is pseudo modal public: /** Tjecks if the file on disk is newer than document contents. If forceReload is true, the document is reloaded without asking the user, otherwise [default] the user is asked what to do. */ void isModOnHD(bool forceReload=false); uint docID () {return myDocID;}; QString docName () {return myDocName;}; void setDocName (QString docName); void setDocFile (QString docFile); public slots: /** Reloads the current document from disk if possible */ void reloadFile(); private slots: void slotModChanged (); private: /** updates mTime to reflect file on fs. called from constructor and from saveFile. */ void setMTime(); uint myDocID; QFileInfo* fileInfo; QDateTime mTime; QString myDocName; QString m_url; QString m_file; void openURL(const QString &filename); private: KateCmd *myCmd; public: KateCmd *cmd () { return myCmd; }; private: QString myEncoding; public: void setEncoding (QString e) { myEncoding = e; }; QString encoding() { return myEncoding; }; void setWordWrap (bool on); bool wordWrap () { return myWordWrap; }; void setWordWrapAt (uint col); uint wordWrapAt () { return myWordWrapAt; }; signals: void modStateChanged (KateDocument *doc); void nameChanged (KateDocument *doc); public: QList<Kate::Mark> marks (); public slots: // clear buffer/filename - update the views void flush (); signals: /** The file has been saved (perhaps the name has changed). The main window can use this to change its caption */ void fileNameChanged (); public: //end of line settings enum Eol_settings {eolUnix=0,eolDos=1,eolMacintosh=2}; // for the DCOP interface public: void open (const QString &name=0); public: // wrap the text of the document at the column col void wrapText (uint col); public slots: void applyWordWrap (); private: class KateDocPrivate { public: bool hlSetByUser; }; // BCI: Add a real d-pointer in the next BIC release static QPtrDict<KateDocPrivate>* d_ptr; static void cleanup_d_ptr() { delete d_ptr; } KateDocPrivate* d( const KateDocument* foo ) { if ( !d_ptr ) { d_ptr = new QPtrDict<KateDocPrivate>; //qAddPostRoutine( cleanup_d_ptr ); } KateDocPrivate* ret = d_ptr->find( (void*) foo ); if ( ! ret ) { ret = new KateDocPrivate; d_ptr->replace( (void*) foo, ret ); } return ret; } void delete_d( const KateDocument* foo ) { if ( d_ptr ) d_ptr->remove( (void*) foo ); } }; #endif diff --git a/noncore/apps/tinykate/libkate/document/katehighlight.cpp b/noncore/apps/tinykate/libkate/document/katehighlight.cpp index 797968b..0d2c283 100644 --- a/noncore/apps/tinykate/libkate/document/katehighlight.cpp +++ b/noncore/apps/tinykate/libkate/document/katehighlight.cpp @@ -1,1459 +1,1459 @@ /* Copyright (C) 1998, 1999 Jochen Wilhelmy digisnap@cs.tu-berlin.de (C) 2002, 2001 The Kate Team <kwrite-devel@kde.org> (C) 2002 Joseph Wenninger <jowenn@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <string.h> #include <qtextstream.h> #include <qpe/config.h> #include <kglobal.h> //#include <kinstance.h> //#include <kmimemagic.h> #include <klocale.h> //#include <kregexp.h> #include <kglobalsettings.h> #include <kdebug.h> #include <kstddirs.h> #include "katehighlight.h" #include "katetextline.h" #include "katedocument.h" #include "katesyntaxdocument.h" HlManager *HlManager::s_pSelf = 0; enum Item_styles { dsNormal,dsKeyword,dsDataType,dsDecVal,dsBaseN,dsFloat,dsChar,dsString,dsComment,dsOthers}; static bool trueBool = true; static QString stdDeliminator = QString ("!%&()*+,-./:;<=>?[]^{|}~ \t\\"); int getDefStyleNum(QString name) { if (name=="dsNormal") return dsNormal; if (name=="dsKeyword") return dsKeyword; if (name=="dsDataType") return dsDataType; if (name=="dsDecVal") return dsDecVal; if (name=="dsBaseN") return dsBaseN; if (name=="dsFloat") return dsFloat; if (name=="dsChar") return dsChar; if (name=="dsString") return dsString; if (name=="dsComment") return dsComment; if (name=="dsOthers") return dsOthers; return dsNormal; } bool ustrchr(const QChar *s, uint len, QChar c) { for (int z=0; z < len; z++) { if (*s == c) return true; s++; } return false; } HlItem::HlItem(int attribute, int context) : attr(attribute), ctx(context) {subItems=0; } HlItem::~HlItem() { //kdDebug(13010)<<"In hlItem::~HlItem()"<<endl; if (subItems!=0) {subItems->setAutoDelete(true); subItems->clear(); delete subItems;} } bool HlItem::startEnable(QChar c) { return true; } HlCharDetect::HlCharDetect(int attribute, int context, QChar c) : HlItem(attribute,context), sChar(c) { } const QChar *HlCharDetect::checkHgl(const QChar *str, int len, bool) { if (*str == sChar) return str + 1; return 0L; } Hl2CharDetect::Hl2CharDetect(int attribute, int context, QChar ch1, QChar ch2) : HlItem(attribute,context) { sChar1 = ch1; sChar2 = ch2; } const QChar *Hl2CharDetect::checkHgl(const QChar *str, int len, bool) { if (str[0] == sChar1 && str[1] == sChar2) return str + 2; return 0L; } HlStringDetect::HlStringDetect(int attribute, int context, const QString &s, bool inSensitive) : HlItem(attribute, context), str(inSensitive ? s.upper():s), _inSensitive(inSensitive) { } HlStringDetect::~HlStringDetect() { } const QChar *HlStringDetect::checkHgl(const QChar *s, int len, bool) { if (!_inSensitive) {if (memcmp(s, str.unicode(), str.length()*sizeof(QChar)) == 0) return s + str.length();} else { QString tmp=QString(s,str.length()).upper(); if (tmp==str) return s+str.length(); } return 0L; } HlRangeDetect::HlRangeDetect(int attribute, int context, QChar ch1, QChar ch2) : HlItem(attribute,context) { sChar1 = ch1; sChar2 = ch2; } const QChar *HlRangeDetect::checkHgl(const QChar *s, int len, bool) { if (*s == sChar1) { do { s++; len--; if (len == 0) return 0L; } while (*s != sChar2); return s + 1; } return 0L; } HlKeyword::HlKeyword (int attribute, int context,bool casesensitive, const QChar *deliminator, uint deliLen) : HlItem(attribute,context), dict (113, casesensitive) { deliminatorChars = deliminator; deliminatorLen = deliLen; _caseSensitive=casesensitive; } HlKeyword::~HlKeyword() { } bool HlKeyword::startEnable(QChar c) { return ustrchr(deliminatorChars, deliminatorLen, c); } // If we use a dictionary for lookup we don't really need // an item as such we are using the key to lookup void HlKeyword::addWord(const QString &word) { words.append(word); dict.insert(word,&trueBool); } void HlKeyword::addList(const QStringList& list) { words+=list; for(uint i=0;i<list.count();i++) dict.insert(list[i], &trueBool); } const QChar *HlKeyword::checkHgl(const QChar *s, int len, bool b) { if (len == 0) return 0L; const QChar *s2 = s; while ( (len > 0) && (!ustrchr(deliminatorChars, deliminatorLen, *s2)) ) { s2++; len--; } if (s2 == s) return 0L; QString lookup = QString(s,s2-s); if ( dict.find(lookup) ) return s2; return 0L; } HlInt::HlInt(int attribute, int context) : HlItem(attribute,context) { } const QChar *HlInt::checkHgl(const QChar *str, int len, bool) { const QChar *s,*s1; s = str; while (s->isDigit()) s++; if (s > str) { if (subItems) { for (HlItem *it=subItems->first();it;it=subItems->next()) { s1=it->checkHgl(s, len, false); if (s1) return s1; } } return s; } return 0L; } HlFloat::HlFloat(int attribute, int context) : HlItem(attribute,context) { } const QChar *HlFloat::checkHgl(const QChar *s, int len, bool) { bool b, p; const QChar *s1; b = false; while (s->isDigit()){ s++; b = true; } if (p = (*s == '.')) { s++; while (s->isDigit()) { s++; b = true; } } if (!b) return 0L; if ((*s&0xdf) == 'E') s++; else if (!p) return 0L; else { if (subItems) { for (HlItem *it=subItems->first();it;it=subItems->next()) { s1=it->checkHgl(s, len, false); if (s1) return s1; } } return s; } if ((*s == '-')||(*s =='+')) s++; b = false; while (s->isDigit()) { s++; b = true; } if (b) { if (subItems) { for (HlItem *it=subItems->first();it;it=subItems->next()) { s1=it->checkHgl(s, len, false); if (s1) return s1; } } return s; } else return 0L; } HlCInt::HlCInt(int attribute, int context) : HlInt(attribute,context) { } const QChar *HlCInt::checkHgl(const QChar *s, int len, bool lineStart) { // if (*s == '0') s++; else s = HlInt::checkHgl(s); s = HlInt::checkHgl(s, len, lineStart); if (s != 0L) { int l = 0; int u = 0; const QChar *str; do { str = s; if ((*s&0xdf) == 'L' ) { l++; if (l > 2) return 0L; s++; } if ((*s&0xdf) == 'U' ){ u++; if (u > 1) return 0L; s++; } } while (s != str); } return s; } HlCOct::HlCOct(int attribute, int context) : HlItem(attribute,context) { } const QChar *HlCOct::checkHgl(const QChar *str, int len, bool) { const QChar *s; if (*str == '0') { str++; s = str; while (*s >= '0' && *s <= '7') s++; if (s > str) { if ((*s&0xdf) == 'L' || (*s&0xdf) == 'U' ) s++; return s; } } return 0L; } HlCHex::HlCHex(int attribute, int context) : HlItem(attribute,context) { } const QChar *HlCHex::checkHgl(const QChar *str, int len, bool) { const QChar *s=str; #if 0 int i; for (i=0;(*s)!='\0';s++,i++); QString line(str,i); QRegExp3 rx("0[xX][a-fA-F\\d]+[UuLl]?"); // this matches but is also matching parenthesis int pos=rx.search(line,0); if(pos > -1) return str+rx.matchedLength(); else return 0L; #else if (str[0] == '0' && ((str[1]&0xdf) == 'X' )) { str += 2; s = str; while (s->isDigit() || ((*s&0xdf) >= 'A' && (*s&0xdf) <= 'F') /*|| (*s >= 'a' && *s <= 'f')*/) s++; if (s > str) { if ((*s&0xdf) == 'L' || (*s&0xdf) == 'U' ) s++; return s; } } return 0L; #endif } HlCFloat::HlCFloat(int attribute, int context) : HlFloat(attribute,context) { } const QChar *HlCFloat::checkHgl(const QChar *s, int len, bool lineStart) { s = HlFloat::checkHgl(s, len, lineStart); if (s && ((*s&0xdf) == 'F' )) s++; return s; } HlAnyChar::HlAnyChar(int attribute, int context, const QChar* charList, uint len) : HlItem(attribute, context) { _charList=charList; _charListLen=len; } const QChar *HlAnyChar::checkHgl(const QChar *s, int len, bool) { if (ustrchr(_charList, _charListLen, *s)) return s +1; return 0L; } HlRegExpr::HlRegExpr(int attribute, int context,QString regexp) : HlItem(attribute, context) { handlesLinestart=regexp.startsWith("^"); if(!handlesLinestart) regexp.prepend("^"); Expr=new QRegExp3(regexp); } const QChar *HlRegExpr::checkHgl(const QChar *s, int len, bool lineStart) { if ((!lineStart) && handlesLinestart) return 0; QString line(s,len); int pos = Expr->search( line, 0 ); if (pos==-1) return 0L; else return (s+Expr->matchedLength()); }; HlLineContinue::HlLineContinue(int attribute, int context) : HlItem(attribute,context) { } const QChar *HlLineContinue::checkHgl(const QChar *s, int len, bool) { if ((s[0].latin1() == '\\') && (len == 1)) { return s + 1; } return 0L; } HlCStringChar::HlCStringChar(int attribute, int context) : HlItem(attribute,context) { } //checks for hex and oct (for example \x1b or \033) const QChar *checkCharHexOct(const QChar *str) { const QChar *s; s=str; int n; if (*s == 'x') { n = 0; do { s++; n *= 16; if (s->isDigit()) n += *s - '0'; else if ((*s&0xdf) >= 'A' && (*s&0xdf) <= 'F') n += (*s&0xdf) - 'A' + 10; // else if (*s >= 'a' && *s <= 'f') n += *s - 'a' + 10; else break; if (n >= 256) return 0L; } while (true); if (s - str == 1) return 0L; } else { if (!(*s >= '0' && *s <= '7')) return 0L; n = *s - '0'; do { s++; n *= 8; if (*s >= '0' && *s <= '7') n += *s - '0'; else break; if (n >= 256) return s; } while (s - str < 3); } return s; } // checks for C escaped chars \n and escaped hex/octal chars const QChar *checkEscapedChar(const QChar *s, int len) { int i; if (s[0] == '\\' && (len > 1) ) { s++; switch(*s){ case 'a': // checks for control chars case 'b': // we want to fall through case 'e': case 'f': case 'n': case 'r': case 't': case 'v': case '\'': case '\"': case '?' : // added ? ANSI C classifies this as an escaped char case '\\': s++; break; case 'x': // if it's like \xff s++; // eat the x // these for loops can probably be // replaced with something else but // for right now they work // check for hexdigits for(i=0;i<2 &&(*s >= '0' && *s <= '9' || (*s&0xdf) >= 'A' && (*s&0xdf) <= 'F');i++,s++); if(i==0) return 0L; // takes care of case '\x' break; case '0': case '1': case '2': case '3' : case '4': case '5': case '6': case '7' : for(i=0;i < 3 &&(*s >='0'&& *s<='7');i++,s++); break; default: return 0L; } return s; } return 0L; } const QChar *HlCStringChar::checkHgl(const QChar *str, int len, bool) { return checkEscapedChar(str, len); } HlCChar::HlCChar(int attribute, int context) : HlItem(attribute,context) { } const QChar *HlCChar::checkHgl(const QChar *str, int len, bool) { const QChar *s; if ((len > 1) && (str[0] == '\'') && (str[1] != '\'')) { s = checkEscapedChar(&str[1], len); //try to match escaped char if (!s) s = &str[2]; //match single non-escaped char if (*s == '\'') return s + 1; } return 0L; } //-------- ItemStyle::ItemStyle() : selCol(Qt::white), bold(false), italic(false) { } ItemStyle::ItemStyle(const QColor &col, const QColor &selCol, bool bold, bool italic) : col(col), selCol(selCol), bold(bold), italic(italic) { } ItemData::ItemData(const QString name, int defStyleNum) : name(name), defStyleNum(defStyleNum), defStyle(true) { } ItemData::ItemData(const QString name, int defStyleNum, const QColor &col, const QColor &selCol, bool bold, bool italic) : ItemStyle(col,selCol,bold,italic), name(name), defStyleNum(defStyleNum), defStyle(false) { } HlData::HlData(const QString &wildcards, const QString &mimetypes, const QString &identifier) : wildcards(wildcards), mimetypes(mimetypes), identifier(identifier) { //JW itemDataList.setAutoDelete(true); } HlContext::HlContext(int attribute, int lineEndContext, int _lineBeginContext) : attr(attribute), ctx(lineEndContext),lineBeginContext(_lineBeginContext) { items.setAutoDelete(true); } Hl2CharDetect::Hl2CharDetect(int attribute, int context, const QChar *s) : HlItem(attribute,context) { sChar1 = s[0]; sChar2 = s[1]; } Highlight::Highlight(syntaxModeListItem *def) : refCount(0) { noHl = false; if (def == 0) { noHl = true; iName = I18N_NOOP("Normal"); iSection = ""; } else { iName = def->name; iSection = def->section; iWildcards = def->extension; iMimetypes = def->mimetype; identifier = def->identifier; } deliminator = stdDeliminator; deliminatorChars = deliminator.unicode(); deliminatorLen = deliminator.length(); } Highlight::~Highlight() { } int Highlight::doHighlight(int ctxNum, TextLine *textLine) { if (noHl) { textLine->setAttribs(0,0,textLine->length()); textLine->setAttr(0); return 0; } HlContext *context; const QChar *s2; HlItem *item; context = contextList[ctxNum]; if (context->lineBeginContext!=-1) { ctxNum=context->lineBeginContext; context=contextList[ctxNum]; } QChar lastChar = ' '; // first char const QChar *str = textLine->getText(); // non space char - index of that char const QChar *s1 = textLine->firstNonSpace(); uint z = textLine->firstChar(); // length of textline uint len = textLine->length(); bool found = false; while (z < len) { found = false; for (item = context->items.first(); item != 0L; item = context->items.next()) { if (item->startEnable(lastChar)) { s2 = item->checkHgl(s1, len-z, z==0); if (s2 > s1) { qDebug("An item has been detected"); textLine->setAttribs(item->attr,s1 - str,s2 - str); ctxNum = item->ctx; context = contextList[ctxNum]; z = z + s2 - s1 - 1; s1 = s2 - 1; found = true; break; } } } // nothing found: set attribute of one char if (!found) textLine->setAttribs(context->attr,s1 - str,s1 - str + 1); lastChar = *s1; s1++; z++; } //set "end of line"-properties textLine->setAttr(context->attr); //return new context return context->ctx; } -KConfig *Highlight::getKConfig() { - KConfig *config; +KateConfig *Highlight::getKateConfig() { + KateConfig *config; config=KGlobal::config(); config->setGroup(iName + QString(" Highlight")); return config; } QString Highlight::getWildcards() { - KConfig *config; + KateConfig *config; - config = getKConfig(); + config = getKateConfig(); //if wildcards not yet in config, then use iWildCards as default return config->readEntry("Wildcards", iWildcards); } QString Highlight::getMimetypes() { - KConfig *config; + KateConfig *config; - config = getKConfig(); + config = getKateConfig(); return config->readEntry("Mimetypes", iMimetypes); } HlData *Highlight::getData() { - KConfig *config; + KateConfig *config; HlData *hlData; - config = getKConfig(); + config = getKateConfig(); // iWildcards = config->readEntry("Wildcards"); // iMimetypes = config->readEntry("Mimetypes"); // hlData = new HlData(iWildcards,iMimetypes); hlData = new HlData( config->readEntry("Wildcards", iWildcards), config->readEntry("Mimetypes", iMimetypes), config->readEntry("Identifier", identifier)); getItemDataList(hlData->itemDataList, config); return hlData; } void Highlight::setData(HlData *hlData) { - KConfig *config; + KateConfig *config; - config = getKConfig(); + config = getKateConfig(); // iWildcards = hlData->wildcards; // iMimetypes = hlData->mimetypes; config->writeEntry("Wildcards",hlData->wildcards); config->writeEntry("Mimetypes",hlData->mimetypes); setItemDataList(hlData->itemDataList,config); } void Highlight::getItemDataList(ItemDataList &list) { - KConfig *config; + KateConfig *config; - config = getKConfig(); + config = getKateConfig(); getItemDataList(list, config); } -void Highlight::getItemDataList(ItemDataList &list, KConfig *config) { +void Highlight::getItemDataList(ItemDataList &list, KateConfig *config) { ItemData *p; QString s; QRgb col, selCol; list.clear(); //JW list.setAutoDelete(true); createItemData(list); for (p = list.first(); p != 0L; p = list.next()) { s = config->readEntry(p->name); if (!s.isEmpty()) { sscanf(s.latin1(),"%d,%X,%X,%d,%d", &p->defStyle,&col,&selCol,&p->bold,&p->italic); p->col.setRgb(col); p->selCol.setRgb(selCol); } } } /******************************************************************************************* Highlight - setItemDataList saves the ItemData / attribute / style definitions to the apps configfile. Especially needed for user overridden values. * input: ItemDataList &list :reference to the list, whose * items should be saved - * KConfig *config :Pointer KDE configuration + * KateConfig *config :Pointer KDE configuration * class, which should be used * as storage ************* * output: none ************* * return value: none *******************************************************************************************/ -void Highlight::setItemDataList(ItemDataList &list, KConfig *config) { +void Highlight::setItemDataList(ItemDataList &list, KateConfig *config) { ItemData *p; QString s; for (p = list.first(); p != 0L; p = list.next()) { s.sprintf("%d,%X,%X,%d,%d", p->defStyle,p->col.rgb(),p->selCol.rgb(),p->bold,p->italic); config->writeEntry(p->name,s); } } /******************************************************************************************* Highlight - use Increase the usage count and trigger initialization if needed * input: none ************* * output: none ************* * return value: none *******************************************************************************************/ void Highlight::use() { if (refCount == 0) init(); refCount++; } /******************************************************************************************* Highlight - release Decrease the usage count and trigger a cleanup if needed * input: none ************* * output: none ************* * return value: none *******************************************************************************************/ void Highlight::release() { refCount--; if (refCount == 0) done(); } /******************************************************************************************* Highlight - init If it's the first time a particular highlighting is used create the needed contextlist * input: none ************* * output: none ************* * return value: none *******************************************************************************************/ void Highlight::init() { if (noHl) return; for (int z = 0; z < nContexts; z++) contextList[z] = 0L; makeContextList(); } /******************************************************************************************* Highlight - done If the there is no document using the highlighting style free the complete context structure. * input: none ************* * output: none ************* * return value: none *******************************************************************************************/ void Highlight::done() { if (noHl) return; for (int z = 0; z < nContexts; z++) delete contextList[z]; } /******************************************************************************************* Highlight - createItemData This function reads the itemData entries from the config file, which specifies the default attribute styles for matched items/contexts. * input: none ************* * output: ItemDataList &list :A reference to the internal list containing the parsed default config ************* * return value: none *******************************************************************************************/ void Highlight::createItemData(ItemDataList &list) { qDebug("Highlight::createItemData"); // If no highlighting is selected we need only one default. if (noHl) { list.append(new ItemData(I18N_NOOP("Normal Text"), dsNormal)); return; } QString color; QString selColor; QString bold; QString italic; // If the internal list isn't already available read the config file if (internalIDList.count()==0) { //if all references to the list are destried the contents will also be deleted internalIDList.setAutoDelete(true); syntaxContextData *data; qDebug("Trying to read itemData section"); //Tell the syntax document class which file we want to parse and which data group HlManager::self()->syntax->setIdentifier(identifier); data=HlManager::self()->syntax->getGroupInfo("highlighting","itemData"); //begin with the real parsing while (HlManager::self()->syntax->nextGroup(data)) { qDebug("Setting up one itemData element"); // read all attributes color=HlManager::self()->syntax->groupData(data,QString("color")); selColor=HlManager::self()->syntax->groupData(data,QString("selColor")); bold=HlManager::self()->syntax->groupData(data,QString("bold")); italic=HlManager::self()->syntax->groupData(data,QString("italic")); //check if the user overrides something if ( (!color.isEmpty()) && (!selColor.isEmpty()) && (!bold.isEmpty()) && (!italic.isEmpty())) { //create a user defined style internalIDList.append(new ItemData( HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(), getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum"))), QColor(color),QColor(selColor),(bold=="true") || (bold=="1"), (italic=="true") || (italic=="1") )); } else { //assign a default style internalIDList.append(new ItemData( HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(), getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum"))))); } } //clean up if (data) HlManager::self()->syntax->freeGroupInfo(data); } //set the ouput reference list=internalIDList; } /******************************************************************************************* Highlight - lookupAttrName This function is a helper for makeContextList and createHlItem. It looks the given attribute name in the itemData list up and returns it's index * input: QString &name :the attribute name to lookup * ItemDataList &iDl :the list containing all * available attributes ************* * output: none ************* * return value: int :The index of the attribute * or 0 *******************************************************************************************/ int Highlight::lookupAttrName(const QString& name, ItemDataList &iDl) { for (int i=0;i<iDl.count();i++) { if (iDl.at(i)->name==name) return i; } kdDebug(13010)<<"Couldn't resolve itemDataName"<<endl; return 0; } /******************************************************************************************* Highlight - createHlItem This function is a helper for makeContextList. It parses the xml file for information, how single or multi line comments are marked * input: syntaxContextData *data : Data about the item read from * the xml file * ItemDataList &iDl : List of all available itemData * entries. Needed for attribute * name->index translation ************* * output: none ************* * return value: HlItem * : Pointer to the newly created item * object *******************************************************************************************/ HlItem *Highlight::createHlItem(syntaxContextData *data, ItemDataList &iDl) { // No highlighting -> exit if (noHl) return 0; // get the (tagname) itemd type QString dataname=HlManager::self()->syntax->groupItemData(data,QString("")); // BEGIN - Translation of the attribute parameter QString tmpAttr=HlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace(); int attr; if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) attr=tmpAttr.toInt(); else attr=lookupAttrName(tmpAttr,iDl); // END - Translation of the attribute parameter // Info about context switch int context=((HlManager::self()->syntax->groupItemData(data,QString("context"))).toInt()); // Get the char parameter (eg DetectChar) char chr; if (! HlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty()) chr= (HlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0]; else chr=0; // Get the String parameter (eg. StringDetect) QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String")); // Get a second char parameter (char1) (eg Detect2Chars) char chr1; if (! HlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty()) chr1= (HlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0]; else chr1=0; // Will be removed eventuall. Atm used for StringDetect bool insensitive=(HlManager::self()->syntax->groupItemData(data,QString("insensitive"))==QString("TRUE")); //Create the item corresponding to it's type and set it's parameters if (dataname=="keyword") { HlKeyword *keyword=new HlKeyword(attr,context,casesensitive, deliminatorChars, deliminatorLen); //Get the entries for the keyword lookup list keyword->addList(HlManager::self()->syntax->finddata("highlighting",stringdata)); return keyword; } else if (dataname=="Float") return (new HlFloat(attr,context)); else if (dataname=="Int") return(new HlInt(attr,context)); else if (dataname=="DetectChar") return(new HlCharDetect(attr,context,chr)); else if (dataname=="Detect2Chars") return(new Hl2CharDetect(attr,context,chr,chr1)); else if (dataname=="RangeDetect") return(new HlRangeDetect(attr,context, chr, chr1)); else if (dataname=="LineContinue") return(new HlLineContinue(attr,context)); else if (dataname=="StringDetect") return(new HlStringDetect(attr,context,stringdata,insensitive)); else if (dataname=="AnyChar") return(new HlAnyChar(attr,context,stringdata.unicode(), stringdata.length())); else if (dataname=="RegExpr") return(new HlRegExpr(attr,context,stringdata)); else if(dataname=="HlCChar") return ( new HlCChar(attr,context));else if(dataname=="HlCHex") return (new HlCHex(attr,context));else if(dataname=="HlCOct") return (new HlCOct(attr,context)); else if(dataname=="HlCStringChar") return (new HlCStringChar(attr,context)); else { // oops, unknown type. Perhaps a spelling error in the xml file return 0; } } /******************************************************************************************* Highlight - isInWord * input: Qchar c Character to investigate ************* * output: none ************* * return value: returns true, if c is no deliminator *******************************************************************************************/ bool Highlight::isInWord(QChar c) { return !ustrchr(deliminatorChars, deliminatorLen, c); } /******************************************************************************************* Highlight - readCommentConfig This function is a helper for makeContextList. It parses the xml file for information, how single or multi line comments are marked * input: none ************* * output: none ************* * return value: none *******************************************************************************************/ void Highlight::readCommentConfig() { cslStart = ""; HlManager::self()->syntax->setIdentifier(identifier); syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("general","comment"); if (data) { // kdDebug(13010)<<"COMMENT DATA FOUND"<<endl; while (HlManager::self()->syntax->nextGroup(data)) { if (HlManager::self()->syntax->groupData(data,"name")=="singleLine") cslStart=HlManager::self()->syntax->groupData(data,"start"); if (HlManager::self()->syntax->groupData(data,"name")=="multiLine") { cmlStart=HlManager::self()->syntax->groupData(data,"start"); cmlEnd=HlManager::self()->syntax->groupData(data,"end"); } } HlManager::self()->syntax->freeGroupInfo(data); } } /******************************************************************************************* Highlight - readGlobalKeyWordConfig This function is a helper for makeContextList. It parses the xml file for information, if keywords should be treated case(in)sensitive and creates the keyword delimiter list. Which is the default list, without any given weak deliminiators * input: none ************* * output: none ************* * return value: none *******************************************************************************************/ void Highlight::readGlobalKeywordConfig() { // Tell the syntax document class which file we want to parse HlManager::self()->syntax->setIdentifier(identifier); // Get the keywords config entry syntaxContextData * data=HlManager::self()->syntax->getConfig("general","keywords"); if (data) { kdDebug(13010)<<"Found global keyword config"<<endl; if (HlManager::self()->syntax->groupItemData(data,QString("casesensitive"))!="0") casesensitive=true; else {casesensitive=false; kdDebug(13010)<<"Turning on case insensitiveness"<<endl;} //get the weak deliminators weakDeliminator=(!HlManager::self()->syntax->groupItemData(data,QString("weakDeliminator"))); // remove any weakDelimitars (if any) from the default list and store this list. int f; for (int s=0; s < weakDeliminator.length(); s++) { f = 0; f = deliminator.find (weakDeliminator[s]); if (f > -1) deliminator.remove (f, 1); } deliminatorChars = deliminator.unicode(); deliminatorLen = deliminator.length(); HlManager::self()->syntax->freeGroupInfo(data); } else { //Default values casesensitive=true; weakDeliminator=QString(""); } } /******************************************************************************************* Highlight - makeContextList That's the most important initialization function for each highlighting. It's called each time a document gets a highlighting style assigned. parses the xml file and creates a corresponding internal structure * input: none ************* * output: none ************* * return value: none *******************************************************************************************/ void Highlight::makeContextList() { if (noHl) return; HlKeyword *keyword=0, *dataType=0; syntaxContextData *data, *datasub; HlItem *c; readCommentConfig(); readGlobalKeywordConfig(); // Let the syntax document class know, which file we'd like to parse HlManager::self()->syntax->setIdentifier(identifier); // This list is needed for the translation of the attribute parameter, if the itemData name is given instead of the index ItemDataList iDl; createItemData(iDl); //start the real work data=HlManager::self()->syntax->getGroupInfo("highlighting","context"); int i=0; if (data) { while (HlManager::self()->syntax->nextGroup(data)) { // BEGIN - Translation of the attribute parameter QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace(); int attr; if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) attr=tmpAttr.toInt(); else attr=lookupAttrName(tmpAttr,iDl); // END - Translation of the attribute parameter contextList[i]=new HlContext( attr, (HlManager::self()->syntax->groupData(data,QString("lineEndContext"))).toInt(), (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1: (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt()); //Let's create all items for the context while (HlManager::self()->syntax->nextItem(data)) { // kdDebug(13010)<< "In make Contextlist: Item:"<<endl; c=createHlItem(data,iDl); if (c) { contextList[i]->items.append(c); // Not supported completely atm and only one level. Subitems.(all have to be matched to at once) datasub=HlManager::self()->syntax->getSubItems(data); bool tmpbool; if (tmpbool=HlManager::self()->syntax->nextItem(datasub)) { c->subItems=new QList<HlItem>; for (;tmpbool;tmpbool=HlManager::self()->syntax->nextItem(datasub)) c->subItems->append(createHlItem(datasub,iDl)); } HlManager::self()->syntax->freeGroupInfo(datasub); // end of sublevel } // kdDebug(13010)<<"Last line in loop"<<endl; } i++; } } HlManager::self()->syntax->freeGroupInfo(data); } HlManager::HlManager() : QObject(0L) { syntax = new SyntaxDocument(); SyntaxModeList modeList = syntax->modeList(); hlList.setAutoDelete(true); hlList.append(new Highlight(0)); uint i=0; while (i < modeList.count()) { hlList.append(new Highlight(modeList.at(i))); i++; } } HlManager::~HlManager() { if(syntax) delete syntax; } HlManager *HlManager::self() { if ( !s_pSelf ) s_pSelf = new HlManager; return s_pSelf; } Highlight *HlManager::getHl(int n) { if (n < 0 || n >= (int) hlList.count()) n = 0; return hlList.at(n); } int HlManager::defaultHl() { - KConfig *config; + KateConfig *config; config = KGlobal::config(); config->setGroup("General Options"); #warning fixme return nameFind(config->readEntry("Highlight")); } int HlManager::nameFind(const QString &name) { int z; for (z = hlList.count() - 1; z > 0; z--) { if (hlList.at(z)->iName == name) break; } return z; } int HlManager::wildcardFind(const QString &fileName) { Highlight *highlight; int p1, p2; QString w; for (highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) { p1 = 0; w = highlight->getWildcards(); while (p1 < (int) w.length()) { p2 = w.find(';',p1); if (p2 == -1) p2 = w.length(); if (p1 < p2) { QRegExp regExp(w.mid(p1,p2 - p1),true,true); if (regExp.match(fileName) == 0) return hlList.at(); } p1 = p2 + 1; } } return -1; } int HlManager::makeAttribs(Highlight *highlight, Attribute *a, int maxAttribs) { ItemStyleList defaultStyleList; ItemStyle *defaultStyle; ItemDataList itemDataList; ItemData *itemData; int nAttribs, z; qDebug("HlManager::makeAttribs"); defaultStyleList.setAutoDelete(true); getDefaults(defaultStyleList); // itemDataList.setAutoDelete(true); highlight->getItemDataList(itemDataList); nAttribs = itemDataList.count(); for (z = 0; z < nAttribs; z++) { qDebug("HlManager::makeAttribs: createing one attribute definition"); itemData = itemDataList.at(z); if (itemData->defStyle) { // default style defaultStyle = defaultStyleList.at(itemData->defStyleNum); a[z].col = defaultStyle->col; a[z].selCol = defaultStyle->selCol; a[z].bold = defaultStyle->bold; a[z].italic = defaultStyle->italic; } else { // custom style a[z].col = itemData->col; a[z].selCol = itemData->selCol; a[z].bold = itemData->bold; a[z].italic = itemData->italic; } } for (; z < maxAttribs; z++) { a[z].col = black; a[z].selCol = black; a[z].bold = defaultStyle->bold; a[z].italic = defaultStyle->italic; } return nAttribs; } int HlManager::defaultStyles() { return 10; } QString HlManager::defaultStyleName(int n) { static QStringList names; if (names.isEmpty()) { names << i18n("Normal"); names << i18n("Keyword"); names << i18n("Data Type"); names << i18n("Decimal/Value"); names << i18n("Base-N Integer"); names << i18n("Floating Point"); names << i18n("Character"); names << i18n("String"); names << i18n("Comment"); names << i18n("Others"); } return names[n]; } void HlManager::getDefaults(ItemStyleList &list) { - KConfig *config; + KateConfig *config; int z; ItemStyle *i; QString s; QRgb col, selCol; list.setAutoDelete(true); //ItemStyle(color, selected color, bold, italic) list.append(new ItemStyle(black,white,false,false)); //normal list.append(new ItemStyle(black,white,true,false)); //keyword list.append(new ItemStyle(darkRed,white,false,false)); //datatype list.append(new ItemStyle(blue,cyan,false,false)); //decimal/value list.append(new ItemStyle(darkCyan,cyan,false,false)); //base n list.append(new ItemStyle(darkMagenta,cyan,false,false));//float list.append(new ItemStyle(magenta,magenta,false,false)); //char list.append(new ItemStyle(red,red,false,false)); //string list.append(new ItemStyle(darkGray,gray,false,true)); //comment list.append(new ItemStyle(darkGreen,green,false,false)); //others #warning fixme /* config = KateFactory::instance()->config(); config->setGroup("Default Item Styles"); for (z = 0; z < defaultStyles(); z++) { i = list.at(z); s = config->readEntry(defaultStyleName(z)); if (!s.isEmpty()) { sscanf(s.latin1(),"%X,%X,%d,%d",&col,&selCol,&i->bold,&i->italic); i->col.setRgb(col); i->selCol.setRgb(selCol); } } */ } void HlManager::setDefaults(ItemStyleList &list) { - KConfig *config; + KateConfig *config; int z; ItemStyle *i; char s[64]; #warning fixme /* config = KateFactory::instance()->config(); config->setGroup("Default Item Styles"); for (z = 0; z < defaultStyles(); z++) { i = list.at(z); sprintf(s,"%X,%X,%d,%d",i->col.rgb(),i->selCol.rgb(),i->bold, i->italic); config->writeEntry(defaultStyleName(z),s); } */ emit changed(); } int HlManager::highlights() { return (int) hlList.count(); } QString HlManager::hlName(int n) { return hlList.at(n)->iName; } QString HlManager::hlSection(int n) { return hlList.at(n)->iSection; } void HlManager::getHlDataList(HlDataList &list) { int z; for (z = 0; z < (int) hlList.count(); z++) { list.append(hlList.at(z)->getData()); } } void HlManager::setHlDataList(HlDataList &list) { int z; for (z = 0; z < (int) hlList.count(); z++) { hlList.at(z)->setData(list.at(z)); } //notify documents about changes in highlight configuration emit changed(); } diff --git a/noncore/apps/tinykate/libkate/document/katehighlight.h b/noncore/apps/tinykate/libkate/document/katehighlight.h index 1baddcc..fddf585 100644 --- a/noncore/apps/tinykate/libkate/document/katehighlight.h +++ b/noncore/apps/tinykate/libkate/document/katehighlight.h @@ -1,349 +1,349 @@ /* Copyright (C) 1998, 1999 Jochen Wilhelmy digisnap@cs.tu-berlin.de (C) 2002, 2001 The Kate Team <kwrite-devel@kde.org> (C) 2002 Joseph Wenninger <jowenn@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _HIGHLIGHT_H_ #define _HIGHLIGHT_H_ #include <qlist.h> #include <qdialog.h> #include <kcolorbtn.h> #include <qstrvec.h> #include <qdict.h> #include <qregexp.h> #include "../qt3back/qregexp3.h" #include <kdebug.h> class SyntaxDocument; struct syntaxModeListItem; struct syntaxContextData; class QCheckBox; class QComboBox; class QLineEdit; class TextLine; class Attribute; class HlItem { public: HlItem(int attribute, int context); virtual ~HlItem(); virtual bool startEnable(QChar); virtual const QChar *checkHgl(const QChar *, int len, bool) = 0; QList<HlItem> *subItems; int attr; int ctx; }; class HlCharDetect : public HlItem { public: HlCharDetect(int attribute, int context, QChar); virtual const QChar *checkHgl(const QChar *, int len, bool); protected: QChar sChar; }; class Hl2CharDetect : public HlItem { public: Hl2CharDetect(int attribute, int context, QChar ch1, QChar ch2); Hl2CharDetect(int attribute, int context, const QChar *ch); virtual const QChar *checkHgl(const QChar *, int len, bool); protected: QChar sChar1; QChar sChar2; }; class HlStringDetect : public HlItem { public: HlStringDetect(int attribute, int context, const QString &, bool inSensitive=false); virtual ~HlStringDetect(); virtual const QChar *checkHgl(const QChar *, int len, bool); protected: const QString str; bool _inSensitive; }; class HlRangeDetect : public HlItem { public: HlRangeDetect(int attribute, int context, QChar ch1, QChar ch2); virtual const QChar *checkHgl(const QChar *, int len, bool); protected: QChar sChar1; QChar sChar2; }; class HlKeyword : public HlItem { public: HlKeyword(int attribute, int context,bool casesensitive, const QChar *deliminator, uint deliLen); virtual ~HlKeyword(); virtual void addWord(const QString &); virtual void addList(const QStringList &); virtual const QChar *checkHgl(const QChar *, int len, bool); QStringList getList() { return words;}; virtual bool startEnable(QChar c); protected: QStringList words; QDict<bool> dict; bool _caseSensitive; const QChar *deliminatorChars; uint deliminatorLen; }; class HlPHex : public HlItem { public: HlPHex(int attribute,int context); virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlInt : public HlItem { public: HlInt(int attribute, int context); virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlFloat : public HlItem { public: HlFloat(int attribute, int context); virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlCInt : public HlInt { public: HlCInt(int attribute, int context); virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlCOct : public HlItem { public: HlCOct(int attribute, int context); virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlCHex : public HlItem { public: HlCHex(int attribute, int context); virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlCFloat : public HlFloat { public: HlCFloat(int attribute, int context); virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlLineContinue : public HlItem { public: HlLineContinue(int attribute, int context); virtual bool endEnable(QChar c) {return c == '\0';} virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlCStringChar : public HlItem { public: HlCStringChar(int attribute, int context); virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlCChar : public HlItem { public: HlCChar(int attribute, int context); virtual const QChar *checkHgl(const QChar *, int len, bool); }; class HlAnyChar : public HlItem { public: HlAnyChar(int attribute, int context, const QChar* charList, uint len); virtual const QChar *checkHgl(const QChar *, int len, bool); const QChar* _charList; uint _charListLen; }; class HlRegExpr : public HlItem { public: HlRegExpr(int attribute, int context,QString expr); ~HlRegExpr(){delete Expr;}; virtual const QChar *checkHgl(const QChar *, int len, bool); QRegExp3 *Expr; bool handlesLinestart; }; //-------- //Item Style: color, selected color, bold, italic class ItemStyle { public: ItemStyle(); // ItemStyle(const ItemStyle &); ItemStyle(const QColor &, const QColor &, bool bold, bool italic); ItemStyle(ItemStyle *its){col=its->col;selCol=its->selCol; bold=its->bold; italic=its->italic;} // void setData(const ItemStyle &); QColor col; QColor selCol; int bold; //boolean value int italic; //boolean value }; typedef QList<ItemStyle> ItemStyleList; //Item Properties: name, Item Style, Item Font class ItemData : public ItemStyle { public: ItemData(const QString name, int defStyleNum); ItemData(const QString name, int defStyleNum, const QColor&, const QColor&, bool bold, bool italic); ItemData(ItemData *itd):ItemStyle((ItemStyle*)itd),name(itd->name),defStyleNum(itd->defStyleNum),defStyle(itd->defStyle){;} const QString name; int defStyleNum; int defStyle; //boolean value }; typedef QList<ItemData> ItemDataList; class HlData { public: HlData(const QString &wildcards, const QString &mimetypes,const QString &identifier); ItemDataList itemDataList; QString wildcards; QString mimetypes; QString identifier; }; typedef QList<HlData> HlDataList; class HlManager; -class KConfig; +class KateConfig; //context class HlContext { public: HlContext(int attribute, int lineEndContext,int _lineBeginContext); QList<HlItem> items; int attr; int ctx; int lineBeginContext; }; class Highlight { friend class HlManager; public: Highlight(syntaxModeListItem *def); ~Highlight(); int doHighlight(int ctxNum, TextLine *); - KConfig *getKConfig(); + KateConfig *getKateConfig(); QString getWildcards(); QString getMimetypes(); HlData *getData(); void setData(HlData *); void getItemDataList(ItemDataList &); - void getItemDataList(ItemDataList &, KConfig *); - void setItemDataList(ItemDataList &, KConfig *); + void getItemDataList(ItemDataList &, KateConfig *); + void setItemDataList(ItemDataList &, KateConfig *); QString name() {return iName;} QString section() {return iSection;} void use(); void release(); bool isInWord(QChar c); QString getCommentStart() {return cmlStart;}; QString getCommentEnd() {return cmlEnd;}; QString getCommentSingleLineStart() { return cslStart;}; protected: void init(); void done(); void makeContextList (); void createItemData (ItemDataList &list); void readGlobalKeywordConfig(); void readCommentConfig(); HlItem *createHlItem(struct syntaxContextData *data, ItemDataList &iDl); int lookupAttrName(const QString& name, ItemDataList &iDl); ItemDataList internalIDList; static const int nContexts = 32; HlContext *contextList[nContexts]; bool noHl; bool casesensitive; QString weakDeliminator; QString deliminator; const QChar *deliminatorChars; uint deliminatorLen; QString cmlStart; QString cmlEnd; QString cslStart; QString iName; QString iSection; QString iWildcards; QString iMimetypes; QString identifier; int refCount; }; class HlManager : public QObject { Q_OBJECT public: HlManager(); ~HlManager(); static HlManager *self(); Highlight *getHl(int n); int defaultHl(); int nameFind(const QString &name); int wildcardFind(const QString &fileName); int findHl(Highlight *h) {return hlList.find(h);} int makeAttribs(Highlight *, Attribute *, int maxAttribs); int defaultStyles(); QString defaultStyleName(int n); void getDefaults(ItemStyleList &); void setDefaults(ItemStyleList &); int highlights(); QString hlName(int n); QString hlSection(int n); void getHlDataList(HlDataList &); void setHlDataList(HlDataList &); SyntaxDocument *syntax; signals: void changed(); protected: QList<Highlight> hlList; static HlManager *s_pSelf; }; #endif //_HIGHLIGHT_H_ diff --git a/noncore/apps/tinykate/libkate/document/katesyntaxdocument.cpp b/noncore/apps/tinykate/libkate/document/katesyntaxdocument.cpp index e45daa4..844f27d 100644 --- a/noncore/apps/tinykate/libkate/document/katesyntaxdocument.cpp +++ b/noncore/apps/tinykate/libkate/document/katesyntaxdocument.cpp @@ -1,311 +1,305 @@ /*************************************************************************** katesyntaxdocument.cpp - description ------------------- begin : Sat 31 March 2001 copyright : (C) 2001,2002 by Joseph Wenninger email : jowenn@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "katesyntaxdocument.h" +#include <kateconfig.h> #include <qfile.h> #include <kdebug.h> #include <kstddirs.h> #include <klocale.h> #include <kmessagebox.h> #include <qstringlist.h> -#include <kconfig.h> #include <kglobal.h> #include <qpe/qpeapplication.h> #include <qdir.h> SyntaxDocument::SyntaxDocument() { m_root=0; currentFile=""; setupModeList(); } void SyntaxDocument::setIdentifier(const QString& identifier) { #warning FIXME delete m_root; m_root=Opie::XMLElement::load(identifier); if (!m_root) KMessageBox::error( 0L, i18n("Can't open %1").arg(identifier) ); } SyntaxDocument::~SyntaxDocument() { } void SyntaxDocument::setupModeList(bool force) { if (myModeList.count() > 0) return; - KConfig *config=KGlobal::config(); + KateConfig *config=KGlobal::config(); KStandardDirs *dirs = KGlobal::dirs(); // QStringList list=dirs->findAllResources("data","kate/syntax/*.xml",false,true); QString path=QPEApplication::qpeDir() +"share/tinykate/syntax/"; QDir dir(path); QStringList list=dir.entryList("*.xml"); for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { QString Group="Highlighting_Cache"+path+*it; - if ((config->hasGroup(Group)) && (!force)) { config->setGroup(Group); syntaxModeListItem *mli=new syntaxModeListItem; mli->name = config->readEntry("name",""); mli->section = config->readEntry("section",""); mli->mimetype = config->readEntry("mimetype",""); mli->extension = config->readEntry("extension",""); mli->identifier = *it; myModeList.append(mli); } else { qDebug("Found a description file:"+path+(*it)); setIdentifier(path+(*it)); Opie::XMLElement *e=m_root; if (e) { e=e->firstChild(); qDebug(e->tagName()); if (e->tagName()=="language") { syntaxModeListItem *mli=new syntaxModeListItem; mli->name = e->attribute("name"); mli->section = e->attribute("section"); mli->mimetype = e->attribute("mimetype"); mli->extension = e->attribute("extensions"); qDebug(QString("valid description for: %1/%2").arg(mli->section).arg(mli->name)); if (mli->section.isEmpty()) mli->section=i18n("Other"); mli->identifier = path+(*it); -#warning fixme -/* config->setGroup(Group); config->writeEntry("name",mli->name); config->writeEntry("section",mli->section); config->writeEntry("mimetype",mli->mimetype); config->writeEntry("extension",mli->extension); -*/ myModeList.append(mli); } } } } -// } - // config->sync(); } SyntaxModeList SyntaxDocument::modeList() { return myModeList; } bool SyntaxDocument::nextGroup( syntaxContextData* data) { if(!data) return false; if (!data->currentGroup) data->currentGroup=data->parent->firstChild(); else data->currentGroup=data->currentGroup->nextChild(); data->item=0; if (!data->currentGroup) return false; else return true; } bool SyntaxDocument::nextItem( syntaxContextData* data) { if(!data) return false; if (!data->item) data->item=data->currentGroup->firstChild(); else data->item=data->item->nextChild(); if (!data->item) return false; else return true; } QString SyntaxDocument::groupItemData( syntaxContextData* data,QString name) { if(!data) return QString::null; if ( (data->item) && (name.isEmpty())) return data->item->tagName(); if (data->item) return data->item->attribute(name); else return QString(); } QString SyntaxDocument::groupData( syntaxContextData* data,QString name) { if(!data) return QString::null; if (data->currentGroup) return data->currentGroup->attribute(name); else return QString(); } void SyntaxDocument::freeGroupInfo( syntaxContextData* data) { if (data) delete data; } syntaxContextData* SyntaxDocument::getSubItems(syntaxContextData* data) { syntaxContextData *retval=new syntaxContextData; retval->parent=0; retval->currentGroup=0; retval->item=0; if (data != 0) { retval->parent=data->currentGroup; retval->currentGroup=data->item; retval->item=0; } return retval; } syntaxContextData* SyntaxDocument::getConfig(const QString& mainGroupName, const QString &Config) { Opie::XMLElement *e = m_root->firstChild()->firstChild(); while (e) { kdDebug(13010)<<"in SyntaxDocument::getGroupInfo (outer loop) " <<endl; if (e->tagName().compare(mainGroupName)==0 ) { Opie::XMLElement *e1=e->firstChild(); while (e1) { kdDebug(13010)<<"in SyntaxDocument::getGroupInfo (inner loop) " <<endl; if (e1->tagName()==Config) { syntaxContextData *data=new ( syntaxContextData); data->currentGroup=0; data->parent=0; data->item=e1; return data; } e1=e1->nextChild(); } kdDebug(13010) << "WARNING :returning null 3"<< endl; return 0; } e=e->nextChild(); } kdDebug(13010) << "WARNING :returning null 4" << endl; return 0; } syntaxContextData* SyntaxDocument::getGroupInfo(const QString& mainGroupName, const QString &group) { Opie::XMLElement *e=m_root->firstChild()->firstChild(); while (e) { kdDebug(13010)<<"in SyntaxDocument::getGroupInfo (outer loop) " <<endl; if (e->tagName().compare(mainGroupName)==0 ) { Opie::XMLElement *e1=e->firstChild(); while (e1) { kdDebug(13010)<<"in SyntaxDocument::getGroupInfo (inner loop) " <<endl; if (e1->tagName()==group+"s") { syntaxContextData *data=new ( syntaxContextData); data->parent=e1; data->currentGroup=0; data->item=0; return data; } e1=e1->nextChild(); } kdDebug(13010) << "WARNING : getGroupInfo returning null :1 " << endl; return 0; } e=e->nextChild(); } kdDebug(13010) << "WARNING : getGroupInfo returning null :2" << endl; return 0; } QStringList& SyntaxDocument::finddata(const QString& mainGroup,const QString& type,bool clearList) { Opie::XMLElement *e = m_root->firstChild(); if (clearList) m_data.clear(); for(e=e->firstChild(); e; e=e->nextChild()) { if (e->tagName()==mainGroup) { for (Opie::XMLElement *e1=e->firstChild();e1;e1=e1->nextChild()) { if (e1->tagName()!="list") continue; if (e1->attribute("name")==type) { for (Opie::XMLElement *e2=e1->firstChild();e2;e2=e2->nextChild()) { qDebug("FOUND A LIST ENTRY("+e2->tagName()+"):"+e2->firstChild()->value()); m_data+=e2->firstChild()->value().stripWhiteSpace(); } break; } } break; } } return m_data; } diff --git a/noncore/apps/tinykate/libkate/interfaces/document.h b/noncore/apps/tinykate/libkate/interfaces/document.h index cbfd1b3..af885f1 100644 --- a/noncore/apps/tinykate/libkate/interfaces/document.h +++ b/noncore/apps/tinykate/libkate/interfaces/document.h @@ -1,103 +1,103 @@ /*************************************************************************** document.h - description ------------------- begin : Mon Jan 15 2001 copyright : (C) 2001 by Christoph "Crossfire" Cullmann (C) 2002 by Joseph Wenninger email : crossfire@babylon2k.de jowenn@kde.org ***************************************************************************/ /*************************************************************************** This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef _KATE_DOCUMENT_INCLUDE_ #define _KATE_DOCUMENT_INCLUDE_ #include <ktexteditor.h> -class KConfig; +class KateConfig; namespace Kate { /** internal class for document bookmarks. */ class Mark { public: uint line; uint type; }; /** This interface provedes access to the Kate Document class. */ class Document : public KTextEditor::Document { Q_OBJECT public: Document (); virtual ~Document (); public: /** Read document config. */ virtual void readConfig () { ; }; /** Save document config. */ virtual void writeConfig () { ; }; /** Read document session config. */ - virtual void readSessionConfig (KConfig *) { ; }; + virtual void readSessionConfig (KateConfig *) { ; }; /** Save document session config. */ - virtual void writeSessionConfig (KConfig *) { ; }; + virtual void writeSessionConfig (KateConfig *) { ; }; /** Returns the document ID. */ virtual uint docID () { return 0L; }; /** Defines possible mark types. A line can have marks of different types. */ enum marks { Bookmark = 1, Breakpoint = 2, markType0 = 4, markType1 = 8, markType2 = 16, markType3 = 32, markType4 = 64, markType5 = 128, markType6 = 256, markType7 = 512, markType8 = 1024 }; /** A list of all marks in a document. Use binary comparing to find marks of a specific type. */ virtual QList<Mark> marks () { QList<Mark> l; return l; }; public slots: // clear buffer/filename - update the views virtual void flush () { ; }; }; }; #endif diff --git a/noncore/apps/tinykate/libkate/interfaces/view.h b/noncore/apps/tinykate/libkate/interfaces/view.h index 5b24bb5..5846395 100644 --- a/noncore/apps/tinykate/libkate/interfaces/view.h +++ b/noncore/apps/tinykate/libkate/interfaces/view.h @@ -1,160 +1,160 @@ /*************************************************************************** view.h - description ------------------- begin : Mon Jan 15 2001 copyright : (C) 2001 by Christoph "Crossfire" Cullmann (C) 2002 by Joseph Wenninger email : crossfire@babylon2k.de jowenn@kde.org ***************************************************************************/ /*************************************************************************** This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ #ifndef _KATE_VIEW_INCLUDE_ #define _KATE_VIEW_INCLUDE_ #include <ktexteditor.h> -class KConfig; +class KateConfig; namespace Kate { class Document; class Mark; /** This interface provides access to the view. */ class View : public KTextEditor::View { Q_OBJECT public: View ( KTextEditor::Document *doc, QWidget *parent, const char *name = 0 ); virtual ~View (); /** Returns a pointer to the document of the view. */ virtual Document *getDoc () { return 0L; }; /** Returns the marked text in the view. */ virtual QString markedText () { return 0L; }; public slots: /** popup a config dialog for the editor part. */ virtual void configDialog () { ; }; // Highlighting slots virtual void setHl (int) { ; }; virtual int getHl () { return 0; }; virtual int getHlCount () { return 0; }; virtual QString getHlName (int) { return 0L; }; virtual QString getHlSection (int) { return 0L; }; // undo/redo stuff virtual void undo () { ; }; virtual void redo () { ; }; virtual void undoHistory() { ; }; public: // read/save config of the view virtual void readConfig () { ; }; virtual void writeConfig () { ; }; // read/save sessionconfig of the view - virtual void readSessionConfig (KConfig *) { ; }; - virtual void writeSessionConfig (KConfig *) { ; }; + virtual void readSessionConfig (KateConfig *) { ; }; + virtual void writeSessionConfig (KateConfig *) { ; }; public slots: // some simply key commands virtual void keyReturn () { ; }; virtual void keyDelete () { ; }; virtual void backspace () { ; }; virtual void killLine () { ; }; // move cursor in the view virtual void cursorLeft () { ; }; virtual void shiftCursorLeft () { ; }; virtual void cursorRight () { ; }; virtual void shiftCursorRight () { ; }; virtual void wordLeft () { ; }; virtual void shiftWordLeft () { ; }; virtual void wordRight () { ; }; virtual void shiftWordRight () { ; }; virtual void home () { ; }; virtual void shiftHome () { ; }; virtual void end () { ; }; virtual void shiftEnd () { ; }; virtual void up () { ; }; virtual void shiftUp () { ; }; virtual void down () { ; }; virtual void shiftDown () { ; }; virtual void scrollUp () { ; }; virtual void scrollDown () { ; }; virtual void topOfView () { ; }; virtual void bottomOfView () { ; }; virtual void pageUp () { ; }; virtual void shiftPageUp () { ; }; virtual void pageDown () { ; }; virtual void shiftPageDown () { ; }; virtual void top () { ; }; virtual void shiftTop () { ; }; virtual void bottom () { ; }; virtual void shiftBottom () { ; }; public slots: // edit command popup window virtual void slotEditCommand () { ; }; // icon border enable/disable virtual void setIconBorder (bool) { ; }; virtual void toggleIconBorder () { ; }; // goto mark virtual void gotoMark (Mark *) { ; }; // toggle current line bookmark or clear all bookmarks virtual void toggleBookmark () { ; }; virtual void clearBookmarks () { ; }; public: // is iconborder visible ? virtual bool iconBorder() { return false; }; public slots: /** Flushes the document of the text widget. The user is given a chance to save the current document if the current document has been modified. */ virtual void flush () { ; }; public: /** Returns true if the current document can be discarded. If the document is modified, the user is asked if he wants to save it. On "cancel" the function returns false. */ virtual bool canDiscard() { return false; }; }; }; #endif diff --git a/noncore/apps/tinykate/libkate/kateconfig.cpp b/noncore/apps/tinykate/libkate/kateconfig.cpp new file mode 100644 index 0000000..06ac49f --- a/dev/null +++ b/noncore/apps/tinykate/libkate/kateconfig.cpp @@ -0,0 +1,634 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include <qdir.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qmessagebox.h> +#if QT_VERSION <= 230 && defined(QT_NO_CODECS) +#include <qtextcodec.h> +#endif +#include <qtextstream.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> + +#define QTOPIA_INTERNAL_LANGLIST +#include "kateconfig.h" +#include <qpe/global.h> + + +/*! + \internal +*/ +QString KateConfig::configFilename(const QString& name, Domain d) +{ + switch (d) { + case File: + return name; + case User: { + QDir dir = (QString(getenv("HOME")) + "/Settings"); + if ( !dir.exists() ) + mkdir(dir.path().local8Bit(),0700); + return dir.path() + "/" + name + ".conf"; + } + } + return name; +} + +/*! + \class KateConfig config.h + \brief The KateConfig class provides for saving application cofniguration state. + + You should keep a KateConfig in existence only while you do not want others + to be able to change the state. There is no locking currently, but there + may be in the future. +*/ + +/*! + \enum KateConfig::KateConfigGroup + \internal +*/ + +/*! + \enum KateConfig::Domain + + \value File + \value User + + See KateConfig for details. +*/ + +/*! + Constructs a config that will load or create a configuration with the + given \a name in the given \a domain. + + You must call setGroup() before doing much else with the KateConfig. + + In the default Domain, \e User, + the configuration is user-specific. \a name should not contain "/" in + this case, and in general should be the name of the C++ class that is + primarily responsible for maintaining the configuration. + + In the File Domain, \a name is an absolute filename. +*/ +KateConfig::KateConfig( const QString &name, Domain domain ) + : filename( configFilename(name,domain) ) +{ + qWarning("KateConfig constructor\n"); + git = groups.end(); + read(); + QStringList l = Global::languageList(); + lang = l[0]; + glang = l[1]; +} + + +// Sharp ROM compatibility +KateConfig::KateConfig ( const QString &name, bool what ) + : filename( configFilename(name,what ? User : File) ) +{ + git = groups.end(); + read(); + QStringList l = Global::languageList(); + lang = l[0]; + glang = l[1]; +} + +/*! + Writes any changes to disk and destroys the in-memory object. +*/ +KateConfig::~KateConfig() +{ + qWarning("KateConfig destructor\n"); + if ( changed ) + write(); +} + +/*! + Returns whether the current group has an entry called \a key. +*/ +bool KateConfig::hasKey( const QString &key ) const +{ + if ( groups.end() == git ) + return FALSE; + KateConfigGroup::ConstIterator it = ( *git ).find( key ); + return it != ( *git ).end(); +} + +/*! + Sets the current group for subsequent reading and writing of + entries to \a gname. Grouping allows the application to partition the namespace. + + This function must be called prior to any reading or writing + of entries. + + The \a gname must not be empty. +*/ +void KateConfig::setGroup( const QString &gname ) +{ + QMap< QString, KateConfigGroup>::Iterator it = groups.find( gname ); + if ( it == groups.end() ) { + git = groups.insert( gname, KateConfigGroup() ); + changed = TRUE; + return; + } + git = it; +} + +/*! + Writes a (\a key, \a value) entry to the current group. + + \sa readEntry() +*/ +void KateConfig::writeEntry( const QString &key, const char* value ) +{ + writeEntry(key,QString(value)); +} + +/*! + Writes a (\a key, \a value) entry to the current group. + + \sa readEntry() +*/ +void KateConfig::writeEntry( const QString &key, const QString &value ) +{ + if ( git == groups.end() ) { + qWarning( "no group set" ); + return; + } + if ( (*git)[key] != value ) { + ( *git ).insert( key, value ); + changed = TRUE; + } +} + +/* + Note that the degree of protection offered by the encryption here is + only sufficient to avoid the most casual observation of the configuration + files. People with access to the files can write down the contents and + decrypt it using this source code. + + Conceivably, and at some burden to the user, this encryption could + be improved. +*/ +static QString encipher(const QString& plain) +{ + // mainly, we make it long + QString cipher; + int mix=28730492; + for (int i=0; i<(int)plain.length(); i++) { + int u = plain[i].unicode(); + int c = u ^ mix; + QString x = QString::number(c,36); + cipher.append(QChar('a'+x.length())); + cipher.append(x); + mix *= u; + } + return cipher; +} + +static QString decipher(const QString& cipher) +{ + QString plain; + int mix=28730492; + for (int i=0; i<(int)cipher.length();) { + int l = cipher[i].unicode()-'a'; + QString x = cipher.mid(i+1,l); i+=l+1; + int u = x.toInt(0,36) ^ mix; + plain.append(QChar(u)); + mix *= u; + } + return plain; +} + +/*! + Writes an encrypted (\a key, \a value) entry to the current group. + + Note that the degree of protection offered by the encryption is + only sufficient to avoid the most casual observation of the configuration + files. + + \sa readEntry() +*/ +void KateConfig::writeEntryCrypt( const QString &key, const QString &value ) +{ + if ( git == groups.end() ) { + qWarning( "no group set" ); + return; + } + QString evalue = encipher(value); + if ( (*git)[key] != evalue ) { + ( *git ).insert( key, evalue ); + changed = TRUE; + } +} + +/*! + Writes a (\a key, \a num) entry to the current group. + + \sa readNumEntry() +*/ +void KateConfig::writeEntry( const QString &key, int num ) +{ + QString s; + s.setNum( num ); + writeEntry( key, s ); +} + +void KateConfig::writeEntry( const QString &key, unsigned int num ) +{ + QString s; + s.setNum( num ); + writeEntry( key, s ); +} + +#ifdef Q_HAS_BOOL_TYPE +/*! + Writes a (\a key, \a b) entry to the current group. This is equivalent + to writing a 0 or 1 as an integer entry. + + \sa readBoolEntry() +*/ +void KateConfig::writeEntry( const QString &key, bool b ) +{ + QString s; + s.setNum( ( int )b ); + writeEntry( key, s ); +} +#endif + +/*! + Writes a (\a key, \a lst) entry to the current group. The list + is separated by \a sep, so the strings must not contain that character. + + \sa readListEntry() +*/ +void KateConfig::writeEntry( const QString &key, const QStringList &lst, const QChar &sep ) +{ + QString s; + QStringList::ConstIterator it = lst.begin(); + for ( ; it != lst.end(); ++it ) + s += *it + sep; + writeEntry( key, s ); +} + +void KateConfig::writeEntry( const QString &key, const QColor &val ) +{ + QStringList l; + l.append( QString().setNum(val.red()) ); + l.append( QString().setNum(val.green()) ); + l.append( QString().setNum(val.blue()) ); + + writeEntry( key, l, QChar(',') ); +} + +void KateConfig::writeEntry( const QString &key, const QFont &val ) +{ + QStringList l; + l.append( val.family() ); + l.append( QString().setNum(val.pointSize()) ); + l.append( QString().setNum(val.weight()) ); + l.append( QString().setNum((int)val.italic()) ); + l.append( QString().setNum((int)val.charSet()) ); + + writeEntry( key, l, QChar(',') ); +} + +/*! + Removes the \a key entry from the current group. Does nothing if + there is no such entry. +*/ + +void KateConfig::removeEntry( const QString &key ) +{ + if ( git == groups.end() ) { + qWarning( "no group set" ); + return; + } + ( *git ).remove( key ); + changed = TRUE; +} + +/*! + \fn bool KateConfig::operator == ( const KateConfig & other ) const + + Tests for equality with \a other. KateConfig objects are equal if they refer to the same filename. +*/ + +/*! + \fn bool KateConfig::operator != ( const KateConfig & other ) const + + Tests for inequality with \a other. KateConfig objects are equal if they refer to the same filename. +*/ + +/*! + \fn QString KateConfig::readEntry( const QString &key, const QString &deflt ) const + + Reads a string entry stored with \a key, defaulting to \a deflt if there is no entry. +*/ + +/*! + \internal + For compatibility, non-const version. +*/ +QString KateConfig::readEntry( const QString &key, const QString &deflt ) +{ + QString res = readEntryDirect( key+"["+lang+"]" ); + if ( !res.isNull() ) + return res; + if ( !glang.isEmpty() ) { + res = readEntryDirect( key+"["+glang+"]" ); + if ( !res.isNull() ) + return res; + } + return readEntryDirect( key, deflt ); +} + +/*! + \fn QString KateConfig::readEntryCrypt( const QString &key, const QString &deflt ) const + + Reads an encrypted string entry stored with \a key, defaulting to \a deflt if there is no entry. +*/ + +/*! + \internal + For compatibility, non-const version. +*/ +QString KateConfig::readEntryCrypt( const QString &key, const QString &deflt ) +{ + QString res = readEntryDirect( key+"["+lang+"]" ); + if ( res.isNull() && glang.isEmpty() ) + res = readEntryDirect( key+"["+glang+"]" ); + if ( res.isNull() ) + res = readEntryDirect( key, QString::null ); + if ( res.isNull() ) + return deflt; + return decipher(res); +} + +/*! + \fn QString KateConfig::readEntryDirect( const QString &key, const QString &deflt ) const + \internal +*/ + +/*! + \internal + For compatibility, non-const version. +*/ +QString KateConfig::readEntryDirect( const QString &key, const QString &deflt ) +{ + if ( git == groups.end() ) { + //qWarning( "no group set" ); + return deflt; + } + KateConfigGroup::ConstIterator it = ( *git ).find( key ); + if ( it != ( *git ).end() ) + return *it; + else + return deflt; +} + +/*! + \fn int KateConfig::readNumEntry( const QString &key, int deflt ) const + Reads a numeric entry stored with \a key, defaulting to \a deflt if there is no entry. +*/ + +/*! + \internal + For compatibility, non-const version. +*/ +int KateConfig::readNumEntry( const QString &key, int deflt ) +{ + QString s = readEntry( key ); + if ( s.isEmpty() ) + return deflt; + else + return s.toInt(); +} + +/*! + \fn bool KateConfig::readBoolEntry( const QString &key, bool deflt ) const + Reads a bool entry stored with \a key, defaulting to \a deflt if there is no entry. +*/ + +/*! + \internal + For compatibility, non-const version. +*/ +bool KateConfig::readBoolEntry( const QString &key, bool deflt ) +{ + QString s = readEntry( key ); + if ( s.isEmpty() ) + return deflt; + else + return (bool)s.toInt(); +} + +/*! + \fn QStringList KateConfig::readListEntry( const QString &key, const QChar &sep ) const + Reads a string list entry stored with \a key, and with \a sep as the separator. +*/ + +/*! + \internal + For compatibility, non-const version. +*/ +QStringList KateConfig::readListEntry( const QString &key, const QChar &sep ) +{ + QString s = readEntry( key ); + if ( s.isEmpty() ) + return QStringList(); + else + return QStringList::split( sep, s ); +} + +QColor KateConfig::readColorEntry( const QString &key, const QColor &def ) const +{ + QStringList list = readListEntry(key, QChar(',')); + if( list.count() != 3 ) + return def; + + return QColor(list[0].toInt(), list[1].toInt(), list[2].toInt()); +} + +QFont KateConfig::readFontEntry( const QString &key, const QFont &def ) const +{ + QStringList list = readListEntry(key, QChar(',')); + if( list.count() != 5 ) + return def; + + return QFont(list[0], list[1].toInt(), list[2].toInt(), (bool)list[3].toInt(), (QFont::CharSet)list[4].toInt()); +} + +QValueList<int> KateConfig::readIntListEntry( const QString &key ) const +{ + QString s = readEntry( key ); + QValueList<int> il; + if ( s.isEmpty() ) + return il; + + QStringList l = QStringList::split( QChar(','), s ); + + QStringList::Iterator l_it; + for( l_it = l.begin(); l_it != l.end(); ++l_it ) + il.append( (*l_it).toInt() ); + return il; +} + +/*! + Removes all entries from the current group. +*/ +void KateConfig::clearGroup() +{ + if ( git == groups.end() ) { + qWarning( "no group set" ); + return; + } + if ( !(*git).isEmpty() ) { + ( *git ).clear(); + changed = TRUE; + } +} + +/*! + \internal +*/ +void KateConfig::write( const QString &fn ) +{ + QString strNewFile; + if ( !fn.isEmpty() ) + filename = fn; + strNewFile = filename + ".new"; + + QFile f( strNewFile ); + if ( !f.open( IO_WriteOnly|IO_Raw ) ) { + qWarning( "could not open for writing `%s'", strNewFile.latin1() ); + git = groups.end(); + return; + } + + QString str; + QCString cstr; + QMap< QString, KateConfigGroup >::Iterator g_it = groups.begin(); + + for ( ; g_it != groups.end(); ++g_it ) { + str += "[" + g_it.key() + "]\n"; + KateConfigGroup::Iterator e_it = ( *g_it ).begin(); + for ( ; e_it != ( *g_it ).end(); ++e_it ) + str += e_it.key() + " = " + *e_it + "\n"; + } + cstr = str.utf8(); + + int total_length; + total_length = f.writeBlock( cstr.data(), cstr.length() ); + if ( total_length != int(cstr.length()) ) { + QMessageBox::critical( 0, QObject::tr("Out of Space"), + QObject::tr("There was a problem creating\nKateConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") ); + f.close(); + QFile::remove( strNewFile ); + return; + } + + f.close(); + // now rename the file... + if ( rename( strNewFile, filename ) < 0 ) { + qWarning( "problem renaming the file %s to %s", strNewFile.latin1(), + filename.latin1() ); + QFile::remove( strNewFile ); + } +} + +/*! + Returns whether the KateConfig is in a valid state. +*/ +bool KateConfig::isValid() const +{ + return groups.end() != git; +} + +/*! + \internal +*/ +void KateConfig::read() +{ + changed = FALSE; + + if ( !QFileInfo( filename ).exists() ) { + git = groups.end(); + return; + } + + QFile f( filename ); + if ( !f.open( IO_ReadOnly ) ) { + git = groups.end(); + return; + } + + QTextStream s( &f ); +#if QT_VERSION <= 230 && defined(QT_NO_CODECS) + // The below should work, but doesn't in Qt 2.3.0 + s.setCodec( QTextCodec::codecForMib( 106 ) ); +#else + s.setEncoding( QTextStream::UnicodeUTF8 ); +#endif + + QStringList list = QStringList::split('\n', s.read() ); + f.close(); + + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + if ( !parse( *it ) ) { + git = groups.end(); + return; + } + } +} + +/*! + \internal +*/ +bool KateConfig::parse( const QString &l ) +{ + QString line = l.stripWhiteSpace(); + + if ( line [0] == QChar ( '#' )) + return true; // ignore comments + + if ( line[ 0 ] == QChar( '[' ) ) { + QString gname = line; + gname = gname.remove( 0, 1 ); + if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) ) + gname = gname.remove( gname.length() - 1, 1 ); + git = groups.insert( gname, KateConfigGroup() ); + } else if ( !line.isEmpty() ) { + if ( git == groups.end() ) + return FALSE; + int eq = line.find( '=' ); + if ( eq == -1 ) + return FALSE; + QString key = line.left(eq).stripWhiteSpace(); + QString value = line.mid(eq+1).stripWhiteSpace(); + ( *git ).insert( key, value ); + } + return TRUE; +} diff --git a/noncore/apps/tinykate/libkate/kateconfig.h b/noncore/apps/tinykate/libkate/kateconfig.h new file mode 100644 index 0000000..80a4e67 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/kateconfig.h @@ -0,0 +1,117 @@ +/********************************************************************** +** Copyright (C) 2000 Trolltech AS. All rights reserved. +** +** This file is part of Qtopia Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef KATECONFIG_H +#define KATECONFIG_H + +// ##### could use QSettings with Qt 3.0 + +#include <qmap.h> +#include <qstringlist.h> +#include <qfont.h> +#include <qcolor.h> + +class KateConfigPrivate; +class KateConfig +{ +public: + typedef QMap< QString, QString > KateConfigGroup; + + enum Domain { File, User }; + KateConfig( const QString &name, Domain domain=User ); + ~KateConfig(); + + bool operator == ( const KateConfig & other ) const { return (filename == other.filename); } + bool operator != ( const KateConfig & other ) const { return (filename != other.filename); } + + bool isValid() const; + bool hasKey( const QString &key ) const; + + // inline for better SharpROM BC + inline bool hasGroup ( const QString &gname ) const { return ( groups. find ( gname ) != groups. end ( )); }; + inline QStringList groupList ( ) const { QStringList sl; for ( QMap< QString, KateConfigGroup >::ConstIterator it = groups. begin ( ); it != groups. end ( ); ++it ) { sl << it.key(); } return sl; }; + + void setGroup( const QString &gname ); + void writeEntry( const QString &key, const char* value ); + void writeEntry( const QString &key, const QString &value ); + void writeEntryCrypt( const QString &key, const QString &value ); + void writeEntry( const QString &key, int num ); + void writeEntry( const QString &key, unsigned int num ); +#ifdef Q_HAS_BOOL_TYPE + void writeEntry( const QString &key, bool b ); +#endif + void writeEntry( const QString &key, const QStringList &lst, const QChar &sep ); + void writeEntry( const QString &key, const QColor & ); + void writeEntry( const QString &key, const QFont & ); + void removeEntry( const QString &key ); + + QString readEntry( const QString &key, const QString &deflt = QString::null ) const; + QString readEntryCrypt( const QString &key, const QString &deflt = QString::null ) const; + QString readEntryDirect( const QString &key, const QString &deflt = QString::null ) const; + int readNumEntry( const QString &key, int deflt = -1 ) const; + bool readBoolEntry( const QString &key, bool deflt = FALSE ) const; + QStringList readListEntry( const QString &key, const QChar &sep ) const; + QColor readColorEntry( const QString &, const QColor & ) const; + QFont readFontEntry( const QString &, const QFont & ) const; + QValueList<int> readIntListEntry( const QString &key ) const; + + // For compatibility, non-const versions. + QString readEntry( const QString &key, const QString &deflt ); + QString readEntryCrypt( const QString &key, const QString &deflt ); + QString readEntryDirect( const QString &key, const QString &deflt ); + int readNumEntry( const QString &key, int deflt ); + bool readBoolEntry( const QString &key, bool deflt ); + QStringList readListEntry( const QString &key, const QChar &sep ); + + void clearGroup(); + + void write( const QString &fn = QString::null ); + +protected: + void read(); + bool parse( const QString &line ); + + QMap< QString, KateConfigGroup > groups; + QMap< QString, KateConfigGroup >::Iterator git; + QString filename; + QString lang; + QString glang; + bool changed; + KateConfigPrivate *d; + static QString configFilename(const QString& name, Domain); + +private: // Sharp ROM compatibility + KateConfig( const QString &name, bool what ); +}; + +inline QString KateConfig::readEntry( const QString &key, const QString &deflt ) const +{ return ((KateConfig*)this)->readEntry(key,deflt); } +inline QString KateConfig::readEntryCrypt( const QString &key, const QString &deflt ) const +{ return ((KateConfig*)this)->readEntryCrypt(key,deflt); } +inline QString KateConfig::readEntryDirect( const QString &key, const QString &deflt ) const +{ return ((KateConfig*)this)->readEntryDirect(key,deflt); } +inline int KateConfig::readNumEntry( const QString &key, int deflt ) const +{ return ((KateConfig*)this)->readNumEntry(key,deflt); } +inline bool KateConfig::readBoolEntry( const QString &key, bool deflt ) const +{ return ((KateConfig*)this)->readBoolEntry(key,deflt); } +inline QStringList KateConfig::readListEntry( const QString &key, const QChar &sep ) const +{ return ((KateConfig*)this)->readListEntry(key,sep); } + +#endif diff --git a/noncore/apps/tinykate/libkate/libkate.pro b/noncore/apps/tinykate/libkate/libkate.pro index b0354e6..0082106 100644 --- a/noncore/apps/tinykate/libkate/libkate.pro +++ b/noncore/apps/tinykate/libkate/libkate.pro @@ -1,90 +1,91 @@ TEMPLATE = lib CONFIG = qt warn_on release HEADERS = microkde/kapplication.h \ - microkde/kconfig.h \ + kateconfig.h \ microkde/kdebug.h \ microkde/kdialog.h \ microkde/kdialogbase.h \ microkde/kfiledialog.h \ microkde/kglobal.h \ microkde/kiconloader.h \ microkde/klineedit.h \ microkde/klocale.h \ microkde/kmessagebox.h \ microkde/kprinter.h \ microkde/krestrictedline.h \ microkde/kseparator.h \ - microkde/ksimpleconfig.h \ microkde/kstandarddirs.h \ microkde/ktempfile.h \ microkde/kunload.h \ microkde/kurlrequester.h \ microkde/kfontdialog.h \ microkde/krun.h \ microkde/knumvalidator.h \ microkde/kstaticdeleter.h \ microkde/klistview.h \ microkde/kglobalsettings.h \ microkde/kcolorbtn.h \ \ \ qt3back/qregexp3.h \ kde/ksharedptr.h \ document/katebuffer.h document/katedialogs.h \ document/katetextline.h \ document/katecmd.h \ document/katehighlight.h \ document/katecmds.h document/katedocument.h \ document/katesyntaxdocument.h \ view/kateundohistory.h \ view/kateview.h \ view/kateviewdialog.h \ interfaces/view.h \ interfaces/document.h \ ktexteditor/ktexteditor.h SOURCES = microkde/kapplication.cpp \ microkde/kdialogbase.cpp \ - microkde/kconfig.cpp \ + kateconfig.cpp \ microkde/klocale.cpp \ microkde/kmessagebox.cpp \ microkde/kprocess.cpp \ microkde/kstandarddirs.cpp \ microkde/ktempfile.cpp \ microkde/kurlrequester.cpp \ microkde/kcolordialog.cpp \ microkde/kfontdialog.cpp \ microkde/krun.cpp \ microkde/knumvalidator.cpp \ microkde/kglobal.cpp \ microkde/kglobalsettings.cpp \ microkde/kcolorbtn.cpp \ \ \ qt3back/qregexp3.cpp \ ktexteditor/ktexteditor.cpp \ document/katebuffer.cpp document/katedialogs.cpp \ document/katehighlight.cpp \ document/katecmd.cpp \ document/katesyntaxdocument.cpp document/katecmds.cpp \ document/katedocument.cpp document/katetextline.cpp \ view/kateundohistory.cpp \ view/kateview.cpp \ view/kateviewdialog.cpp \ interfaces/interfaces.cpp INTERFACES = -INCLUDEPATH += $(OPIEDIR)/include $(OPIEDIR)/noncore/apps/tinykate/libkate/microkde \ +INCLUDEPATH += $(OPIEDIR)/include \ + $(OPIEDIR)/noncore/apps/tinykate/libkate \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/microkde \ $(OPIEDIR)/noncore/apps/tinykate/libkate/document \ $(OPIEDIR)/noncore/apps/tinykate/libkate/view \ $(OPIEDIR)/noncore/apps/tinykate/libkate/interfaces \ $(OPIEDIR)/noncore/apps/tinykate/libkate/ktexteditor \ $(OPIEDIR)/noncore/apps/tinykate/libkate/qt3back DEPENDPATH += $(OPIEDIR)/include LIBS += -lqpe -lopie TARGET = tinykate INCLUDEPATH += $(OPIEDIR)/include DESTDIR = $(OPIEDIR)/lib$(PROJMAK) include ( $(OPIEDIR)/include.pro ) diff --git a/noncore/apps/tinykate/libkate/microkde/kconfig.cpp b/noncore/apps/tinykate/libkate/microkde/kconfig.cpp deleted file mode 100644 index d88bda0..0000000 --- a/noncore/apps/tinykate/libkate/microkde/kconfig.cpp +++ b/dev/null @@ -1,181 +0,0 @@ -#include <qfile.h> -#include <qtextstream.h> - -#include "kdebug.h" - -#include "kconfig.h" - -QString KConfig::mGroup = ""; -//QString KConfig::mGroup = "General"; - -KConfig::KConfig( const QString &fileName ) - : mFileName( fileName ), mDirty( false ) -{ - kdDebug() << "KConfig::KConfig(): '" << fileName << "'" << endl; - - load(); -} - - -KConfig::~KConfig() -{ - sync(); -} - -void KConfig::setGroup( const QString &group ) -{ - return; - -// kdDebug() << "KConfig::setGroup(): '" << group << "'" << endl; - - mGroup = group; - - if ( mGroup.right( 1 ) != "/" ) mGroup += "/"; -} - - -QValueList<int> KConfig::readIntListEntry( const QString & ) -{ - QValueList<int> l; - return l; -} - -int KConfig::readNumEntry( const QString &, int def ) -{ - return def; -} - -QString KConfig::readEntry( const QString &key, const QString &def ) -{ - QMap<QString,QString>::ConstIterator it = mStringMap.find( mGroup + key ); - - if ( it == mStringMap.end() ) { - return def; - } - - return *it; -} - -QStringList KConfig::readListEntry( const QString & ) -{ - return QStringList(); -} - -bool KConfig::readBoolEntry( const QString &key, bool def ) -{ - QMap<QString,bool>::ConstIterator it = mBoolMap.find( mGroup + key ); - - if ( it == mBoolMap.end() ) { - return def; - } - - return *it; -} - -QColor KConfig::readColorEntry( const QString &, QColor *def ) -{ - if ( def ) return *def; - return QColor(); -} - -QFont KConfig::readFontEntry( const QString &, QFont *def ) -{ - if ( def ) return *def; - return QFont(); -} - - -void KConfig::writeEntry( const QString &, QValueList<int> ) -{ -} - -void KConfig::writeEntry( const QString &, int ) -{ -} - -void KConfig::writeEntry( const QString &key, const QString &value ) -{ - mStringMap.insert( mGroup + key, value ); - - mDirty = true; -} - -void KConfig::writeEntry( const QString &, const QStringList & ) -{ -} - -void KConfig::writeEntry( const QString &key, bool value) -{ - mBoolMap.insert( mGroup + key, value ); - - mDirty = true; -} - -void KConfig::writeEntry( const QString &, const QColor & ) -{ -} - -void KConfig::writeEntry( const QString &, const QFont & ) -{ -} - -void KConfig::load() -{ - mBoolMap.clear(); - mStringMap.clear(); - - QFile f( mFileName ); - if ( !f.open( IO_ReadOnly ) ) { - kdDebug() << "KConfig::load(): Can't open file '" << mFileName << "'" - << endl; - return; - } - - - QTextStream t( &f ); - - QString line = t.readLine(); - - while ( !line.isNull() ) { - QStringList tokens = QStringList::split( ",", line ); - if ( tokens[0] == "bool" ) { - bool value = false; - if ( tokens[2] == "1" ) value = true; - - mBoolMap.insert( tokens[1], value ); - } else if ( tokens[0] == "QString" ) { - QString value = tokens[2]; - mStringMap.insert( tokens[1], value ); - } - - line = t.readLine(); - } -} - -void KConfig::sync() -{ - if ( !mDirty ) return; - - QFile f( mFileName ); - if ( !f.open( IO_WriteOnly ) ) { - kdDebug() << "KConfig::sync(): Can't open file '" << mFileName << "'" - << endl; - return; - } - - QTextStream t( &f ); - - QMap<QString,bool>::ConstIterator itBool; - for( itBool = mBoolMap.begin(); itBool != mBoolMap.end(); ++itBool ) { - t << "bool," << itBool.key() << "," << (*itBool ) << endl; - } - - QMap<QString,QString>::ConstIterator itString; - for( itString = mStringMap.begin(); itString != mStringMap.end(); ++itString ) { - t << "QString," << itString.key() << "," << (*itString ) << endl; - } - - f.close(); - - mDirty = false; -} diff --git a/noncore/apps/tinykate/libkate/microkde/kconfig.h b/noncore/apps/tinykate/libkate/microkde/kconfig.h deleted file mode 100644 index 8bd768a..0000000 --- a/noncore/apps/tinykate/libkate/microkde/kconfig.h +++ b/dev/null @@ -1,51 +0,0 @@ -#ifndef MINIKDE_KCONFIG_H -#define MINIKDE_KCONFIG_H - -#include <qstring.h> -#include <qstringlist.h> -#include <qvaluelist.h> -#include <qcolor.h> -#include <qfont.h> -#include <qmap.h> - -class KConfig -{ - public: - KConfig( const QString & ); - ~KConfig(); - - void setGroup( const QString & ); - - bool hasGroup( const QString &) {return false;} - - QValueList<int> readIntListEntry( const QString & ); - int readNumEntry( const QString &, int def=0 ); - QString readEntry( const QString &, const QString &def=QString::null ); - QStringList readListEntry( const QString & ); - bool readBoolEntry( const QString &, bool def=false ); - QColor readColorEntry( const QString &, QColor * ); - QFont readFontEntry( const QString &, QFont * ); - - void writeEntry( const QString &, QValueList<int> ); - void writeEntry( const QString &, int ); - void writeEntry( const QString &, const QString & ); - void writeEntry( const QString &, const QStringList & ); - void writeEntry( const QString &, bool ); - void writeEntry( const QString &, const QColor & ); - void writeEntry( const QString &, const QFont & ); - - void load(); - void sync(); - - private: - static QString mGroup; - - QString mFileName; - - QMap<QString,bool> mBoolMap; - QMap<QString,QString> mStringMap; - - bool mDirty; -}; - -#endif diff --git a/noncore/apps/tinykate/libkate/microkde/kglobal.cpp b/noncore/apps/tinykate/libkate/microkde/kglobal.cpp index 572768d..9b5c4d3 100644 --- a/noncore/apps/tinykate/libkate/microkde/kglobal.cpp +++ b/noncore/apps/tinykate/libkate/microkde/kglobal.cpp @@ -1,49 +1,49 @@ #include "kglobal.h" KLocale *KGlobal::mLocale = 0; -KConfig *KGlobal::mConfig = 0; +KateConfig *KGlobal::mConfig = 0; KIconLoader *KGlobal::mIconLoader = 0; KStandardDirs *KGlobal::mDirs = 0; QString KGlobal::mAppName = "godot"; KLocale *KGlobal::locale() { if ( !mLocale ) { mLocale = new KLocale(); } return mLocale; } -KConfig *KGlobal::config() +KateConfig *KGlobal::config() { if ( !mConfig ) { - mConfig = new KConfig( KStandardDirs::appDir() + mAppName + "rc" ); + mConfig = new KateConfig( mAppName ); } return mConfig; } KIconLoader *KGlobal::iconLoader() { if ( !mIconLoader ) { mIconLoader = new KIconLoader(); } return mIconLoader; } KStandardDirs *KGlobal::dirs() { if ( !mDirs ) { mDirs = new KStandardDirs(); } return mDirs; } void KGlobal::setAppName( const QString &appName ) { mAppName = appName; } diff --git a/noncore/apps/tinykate/libkate/microkde/kglobal.h b/noncore/apps/tinykate/libkate/microkde/kglobal.h index 8985bd4..e4e2c79 100644 --- a/noncore/apps/tinykate/libkate/microkde/kglobal.h +++ b/noncore/apps/tinykate/libkate/microkde/kglobal.h @@ -1,27 +1,27 @@ #ifndef MINIKDE_KGLOBAL_H #define MINIKDE_KGLOBAL_H #include "klocale.h" #include "kiconloader.h" #include "kstandarddirs.h" -#include "kconfig.h" +#include <kateconfig.h> class KGlobal { public: static KLocale *locale(); - static KConfig *config(); + static KateConfig *config(); static KIconLoader *iconLoader(); static KStandardDirs *dirs(); static void setAppName( const QString & ); private: static KLocale *mLocale; - static KConfig *mConfig; + static KateConfig *mConfig; static KIconLoader *mIconLoader; static KStandardDirs *mDirs; static QString mAppName; }; #endif diff --git a/noncore/apps/tinykate/libkate/view/kateview.cpp b/noncore/apps/tinykate/libkate/view/kateview.cpp index 63e941f..af3b30d 100644 --- a/noncore/apps/tinykate/libkate/view/kateview.cpp +++ b/noncore/apps/tinykate/libkate/view/kateview.cpp @@ -1,2923 +1,2923 @@ /*************************************************************************** kateview.cpp - description ------------------- begin : Mon Jan 15 2001 copyright : (C) 2001 by Christoph "Crossfire" Cullmann (C) 2002 by Joseph Wenninger email : crossfire@babylon2k.de jowenn@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* Copyright (C) 1998, 1999 Jochen Wilhelmy digisnap@cs.tu-berlin.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "kateview.h" #include "../document/katedocument.h" #include "../document/katecmd.h" #include "../document/katehighlight.h" #include "kateviewdialog.h" #include "../document/katedialogs.h" +#include <kateconfig.h> #include <qfocusdata.h> #include <kdebug.h> #include <kapplication.h> #include <qscrollbar.h> #include <qiodevice.h> #include <qpopupmenu.h> #include <kpopupmenu.h> #include <qkeycode.h> #include <qintdict.h> -#include <kconfig.h> #include <qfont.h> #include <qpainter.h> #include <qpixmap.h> #include <qfileinfo.h> #include <qfile.h> #include <qevent.h> #include <qdir.h> #include <qvbox.h> #include <qprintdialog.h> #include <qpaintdevicemetrics.h> #include <qiodevice.h> #include <qbuffer.h> #include <qfocusdata.h> #include <klocale.h> #include <kglobal.h> #include <kdebug.h> #include <kmessagebox.h> #include <qregexp.h> #include <kdialogbase.h> #include <klineeditdlg.h> #include <qapplication.h> #include <kfiledialog.h> #include <kiconloader.h> #include "../document/katetextline.h" #include "kateviewdialog.h" #include "kateundohistory.h" #include <qlayout.h> KateViewInternal::KateViewInternal(KateView *view, KateDocument *doc) : QWidget(view) { waitForPreHighlight=-1; myView = view; myDoc = doc; iconBorderWidth = 16; iconBorderHeight = 800; QWidget::setCursor(ibeamCursor); setBackgroundMode(NoBackground); setFocusPolicy(StrongFocus); xScroll = new QScrollBar(QScrollBar::Horizontal,myView); yScroll = new QScrollBar(QScrollBar::Vertical,myView); connect(xScroll,SIGNAL(valueChanged(int)),SLOT(changeXPos(int))); connect(yScroll,SIGNAL(valueChanged(int)),SLOT(changeYPos(int))); connect(yScroll,SIGNAL(valueChanged(int)),myView,SIGNAL(scrollValueChanged(int))); connect( doc, SIGNAL (preHighlightChanged(long)),this,SLOT(slotPreHighlightUpdate(long))); xPos = 0; yPos = 0; scrollTimer = 0; cursor.x = 0; cursor.y = 0; cursorOn = false; cursorTimer = 0; cXPos = 0; cOldXPos = 0; startLine = 0; endLine = -1; exposeCursor = false; updateState = 0; numLines = 0; lineRanges = 0L; newXPos = -1; newYPos = -1; drawBuffer = new QPixmap (); drawBuffer->setOptimization (QPixmap::BestOptim); bm.sXPos = 0; bm.eXPos = -1; } KateViewInternal::~KateViewInternal() { delete [] lineRanges; delete drawBuffer; } void KateViewInternal::slotPreHighlightUpdate(long line) { //kdDebug()<<QString("slotPreHighlightUpdate - Wait for: %1, line: %2").arg(waitForPreHighlight).arg(line)<<endl; if (waitForPreHighlight!=-1) { if (line>=waitForPreHighlight) { waitForPreHighlight=-1; repaint(); } } } void KateViewInternal::doCursorCommand(VConfig &c, int cmdNum) { switch (cmdNum) { case KateView::cmLeft: cursorLeft(c); break; case KateView::cmRight: cursorRight(c); break; case KateView::cmWordLeft: wordLeft(c); break; case KateView::cmWordRight: wordRight(c); break; case KateView::cmHome: home(c); break; case KateView::cmEnd: end(c); break; case KateView::cmUp: cursorUp(c); break; case KateView::cmDown: cursorDown(c); break; case KateView::cmScrollUp: scrollUp(c); break; case KateView::cmScrollDown: scrollDown(c); break; case KateView::cmTopOfView: topOfView(c); break; case KateView::cmBottomOfView: bottomOfView(c); break; case KateView::cmPageUp: pageUp(c); break; case KateView::cmPageDown: pageDown(c); break; case KateView::cmTop: top_home(c); break; case KateView::cmBottom: bottom_end(c); break; } } void KateViewInternal::doEditCommand(VConfig &c, int cmdNum) { switch (cmdNum) { case KateView::cmCopy: myDoc->copy(c.flags); return; case KateView::cmSelectAll: myDoc->selectAll(); return; case KateView::cmDeselectAll: myDoc->deselectAll(); return; case KateView::cmInvertSelection: myDoc->invertSelection(); return; } if (myView->isReadOnly()) return; switch (cmdNum) { case KateView::cmReturn: if (c.flags & KateView::cfDelOnInput) myDoc->delMarkedText(c); myDoc->newLine(c); //emit returnPressed(); //e->ignore(); return; case KateView::cmDelete: if ((c.flags & KateView::cfDelOnInput) && myDoc->hasMarkedText()) myDoc->delMarkedText(c); else myDoc->del(c); return; case KateView::cmBackspace: if ((c.flags & KateView::cfDelOnInput) && myDoc->hasMarkedText()) myDoc->delMarkedText(c); else myDoc->backspace(c); return; case KateView::cmKillLine: myDoc->killLine(c); return; case KateView::cmCut: myDoc->cut(c); return; case KateView::cmPaste: if (c.flags & KateView::cfDelOnInput) myDoc->delMarkedText(c); myDoc->paste(c); return; case KateView::cmUndo: myDoc->undo(c); return; case KateView::cmRedo: myDoc->redo(c); return; case KateView::cmIndent: myDoc->indent(c); return; case KateView::cmUnindent: myDoc->unIndent(c); return; case KateView::cmCleanIndent: myDoc->cleanIndent(c); return; case KateView::cmComment: myDoc->comment(c); return; case KateView::cmUncomment: myDoc->unComment(c); return; } } void KateViewInternal::cursorLeft(VConfig &c) { cursor.x--; if (c.flags & KateView::cfWrapCursor && cursor.x < 0 && cursor.y > 0) { cursor.y--; cursor.x = myDoc->textLength(cursor.y); } cOldXPos = cXPos = myDoc->textWidth(cursor); changeState(c); } void KateViewInternal::cursorRight(VConfig &c) { if (c.flags & KateView::cfWrapCursor) { if (cursor.x >= myDoc->textLength(cursor.y)) { if (cursor.y == myDoc->lastLine()) return; cursor.y++; cursor.x = -1; } } cursor.x++; cOldXPos = cXPos = myDoc->textWidth(cursor); changeState(c); } void KateViewInternal::wordLeft(VConfig &c) { Highlight *highlight; highlight = myDoc->highlight(); TextLine::Ptr textLine = myDoc->getTextLine(cursor.y); if (cursor.x > 0) { do { cursor.x--; } while (cursor.x > 0 && !highlight->isInWord(textLine->getChar(cursor.x))); while (cursor.x > 0 && highlight->isInWord(textLine->getChar(cursor.x -1))) cursor.x--; } else { if (cursor.y > 0) { cursor.y--; textLine = myDoc->getTextLine(cursor.y); cursor.x = textLine->length(); } } cOldXPos = cXPos = myDoc->textWidth(cursor); changeState(c); } void KateViewInternal::wordRight(VConfig &c) { Highlight *highlight; int len; highlight = myDoc->highlight(); TextLine::Ptr textLine = myDoc->getTextLine(cursor.y); len = textLine->length(); if (cursor.x < len) { do { cursor.x++; } while (cursor.x < len && highlight->isInWord(textLine->getChar(cursor.x))); while (cursor.x < len && !highlight->isInWord(textLine->getChar(cursor.x))) cursor.x++; } else { if (cursor.y < myDoc->lastLine()) { cursor.y++; textLine = myDoc->getTextLine(cursor.y); cursor.x = 0; } } cOldXPos = cXPos = myDoc->textWidth(cursor); changeState(c); } void KateViewInternal::home(VConfig &c) { int lc; lc = (c.flags & KateView::cfSmartHome) ? myDoc->getTextLine(cursor.y)->firstChar() : 0; if (lc <= 0 || cursor.x == lc) { cursor.x = 0; cOldXPos = cXPos = 0; } else { cursor.x = lc; cOldXPos = cXPos = myDoc->textWidth(cursor); } changeState(c); } void KateViewInternal::end(VConfig &c) { cursor.x = myDoc->textLength(cursor.y); cOldXPos = cXPos = myDoc->textWidth(cursor); changeState(c); } void KateViewInternal::cursorUp(VConfig &c) { cursor.y--; cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); changeState(c); } void KateViewInternal::cursorDown(VConfig &c) { int x; if (cursor.y == myDoc->lastLine()) { x = myDoc->textLength(cursor.y); if (cursor.x >= x) return; cursor.x = x; cXPos = myDoc->textWidth(cursor); } else { cursor.y++; cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor, cursor, cOldXPos); } changeState(c); } void KateViewInternal::scrollUp(VConfig &c) { if (! yPos) return; newYPos = yPos - myDoc->fontHeight; if (cursor.y == (yPos + height())/myDoc->fontHeight -1) { cursor.y--; cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); changeState(c); } } void KateViewInternal::scrollDown(VConfig &c) { if (endLine >= myDoc->lastLine()) return; newYPos = yPos + myDoc->fontHeight; if (cursor.y == (yPos + myDoc->fontHeight -1)/myDoc->fontHeight) { cursor.y++; cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); changeState(c); } } void KateViewInternal::topOfView(VConfig &c) { cursor.y = (yPos + myDoc->fontHeight -1)/myDoc->fontHeight; cursor.x = 0; cOldXPos = cXPos = 0; changeState(c); } void KateViewInternal::bottomOfView(VConfig &c) { cursor.y = (yPos + height())/myDoc->fontHeight -1; if (cursor.y < 0) cursor.y = 0; if (cursor.y > myDoc->lastLine()) cursor.y = myDoc->lastLine(); cursor.x = 0; cOldXPos = cXPos = 0; changeState(c); } void KateViewInternal::pageUp(VConfig &c) { int lines = (endLine - startLine - 1); if (lines <= 0) lines = 1; if (!(c.flags & KateView::cfPageUDMovesCursor) && yPos > 0) { newYPos = yPos - lines * myDoc->fontHeight; if (newYPos < 0) newYPos = 0; } cursor.y -= lines; cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor, cursor, cOldXPos); changeState(c); // cursorPageUp(c); } void KateViewInternal::pageDown(VConfig &c) { int lines = (endLine - startLine - 1); if (!(c.flags & KateView::cfPageUDMovesCursor) && endLine < myDoc->lastLine()) { if (lines < myDoc->lastLine() - endLine) newYPos = yPos + lines * myDoc->fontHeight; else newYPos = yPos + (myDoc->lastLine() - endLine) * myDoc->fontHeight; } cursor.y += lines; cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); changeState(c); // cursorPageDown(c); } // go to the top, same X position void KateViewInternal::top(VConfig &c) { // cursor.x = 0; cursor.y = 0; cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); // cOldXPos = cXPos = 0; changeState(c); } // go to the bottom, same X position void KateViewInternal::bottom(VConfig &c) { // cursor.x = 0; cursor.y = myDoc->lastLine(); cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); // cOldXPos = cXPos = 0; changeState(c); } // go to the top left corner void KateViewInternal::top_home(VConfig &c) { cursor.y = 0; cursor.x = 0; cOldXPos = cXPos = 0; changeState(c); } // go to the bottom right corner void KateViewInternal::bottom_end(VConfig &c) { cursor.y = myDoc->lastLine(); cursor.x = myDoc->textLength(cursor.y); cOldXPos = cXPos = myDoc->textWidth(cursor); changeState(c); } void KateViewInternal::changeXPos(int p) { int dx; dx = xPos - p; xPos = p; if (QABS(dx) < width()) scroll(dx, 0); else update(); } void KateViewInternal::changeYPos(int p) { int dy; dy = yPos - p; yPos = p; clearDirtyCache(height()); if (QABS(dy) < height()) { scroll(0, dy); leftBorder->scroll(0, dy); } else update(); } void KateViewInternal::getVConfig(VConfig &c) { c.view = myView; c.cursor = cursor; c.cXPos = cXPos; c.flags = myView->configFlags; } void KateViewInternal::changeState(VConfig &c) { /* * we need to be sure to kill the selection on an attempted cursor * movement even if the cursor doesn't physically move, * but we need to be careful not to do some other things in this case, * like we don't want to expose the cursor */ // if (cursor.x == c.cursor.x && cursor.y == c.cursor.y) return; bool nullMove = (cursor.x == c.cursor.x && cursor.y == c.cursor.y); // if (cursor.y != c.cursor.y || c.flags & KateView::cfMark) myDoc->recordReset(); if (! nullMove) { exposeCursor = true; // mark old position of cursor as dirty if (cursorOn) { tagLines(c.cursor.y, c.cursor.y, c.cXPos -2, c.cXPos +3); cursorOn = false; } // mark old bracket mark position as dirty if (bm.sXPos < bm.eXPos) { tagLines(bm.cursor.y, bm.cursor.y, bm.sXPos, bm.eXPos); } // make new bracket mark myDoc->newBracketMark(cursor, bm); // remove trailing spaces when leaving a line if (c.flags & KateView::cfRemoveSpaces && cursor.y != c.cursor.y) { TextLine::Ptr textLine = myDoc->getTextLine(c.cursor.y); int newLen = textLine->lastChar(); if (newLen != textLine->length()) { textLine->truncate(newLen); // if some spaces are removed, tag the line as dirty myDoc->tagLines(c.cursor.y, c.cursor.y); } } } if (c.flags & KateView::cfMark) { if (! nullMove) myDoc->selectTo(c, cursor, cXPos); } else { if (!(c.flags & KateView::cfPersistent)) myDoc->deselectAll(); } } void KateViewInternal::insLine(int line) { if (line <= cursor.y) { cursor.y++; } if (line < startLine) { startLine++; endLine++; yPos += myDoc->fontHeight; } else if (line <= endLine) { tagAll(); } } void KateViewInternal::delLine(int line) { if (line <= cursor.y && cursor.y > 0) { cursor.y--; } if (line < startLine) { startLine--; endLine--; yPos -= myDoc->fontHeight; } else if (line <= endLine) { tagAll(); } } void KateViewInternal::updateCursor() { cOldXPos = cXPos = myDoc->textWidth(cursor); } void KateViewInternal::updateCursor(PointStruc &newCursor) { updateCursor(newCursor, myView->config()); } void KateViewInternal::updateCursor(PointStruc &newCursor, int flags) { if (!(flags & KateView::cfPersistent)) myDoc->deselectAll(); exposeCursor = true; if (cursorOn) { tagLines(cursor.y, cursor.y, cXPos -2, cXPos +3); cursorOn = false; } if (bm.sXPos < bm.eXPos) { tagLines(bm.cursor.y, bm.cursor.y, bm.sXPos, bm.eXPos); } myDoc->newBracketMark(newCursor, bm); cursor = newCursor; cOldXPos = cXPos = myDoc->textWidth(cursor); } // init the line dirty cache void KateViewInternal::clearDirtyCache(int height) { int lines, z; // calc start and end line of visible part startLine = yPos/myDoc->fontHeight; endLine = (yPos + height -1)/myDoc->fontHeight; updateState = 0; lines = endLine - startLine +1; if (lines > numLines) { // resize the dirty cache numLines = lines*2; delete [] lineRanges; lineRanges = new LineRange[numLines]; } for (z = 0; z < lines; z++) { // clear all lines lineRanges[z].start = 0xffffff; lineRanges[z].end = -2; } newXPos = newYPos = -1; } void KateViewInternal::tagLines(int start, int end, int x1, int x2) { LineRange *r; int z; start -= startLine; if (start < 0) start = 0; end -= startLine; if (end > endLine - startLine) end = endLine - startLine; if (x1 <= 0) x1 = -2; if (x1 < xPos-2) x1 = xPos-2; if (x2 > width() + xPos-2) x2 = width() + xPos-2; if (x1 >= x2) return; r = &lineRanges[start]; for (z = start; z <= end; z++) { if (x1 < r->start) r->start = x1; if (x2 > r->end) r->end = x2; r++; updateState |= 1; } } void KateViewInternal::tagAll() { updateState = 3; } void KateViewInternal::setPos(int x, int y) { newXPos = x; newYPos = y; } void KateViewInternal::center() { newXPos = 0; newYPos = cursor.y*myDoc->fontHeight - height()/2; if (newYPos < 0) newYPos = 0; } void KateViewInternal::updateView(int flags) { int fontHeight; int oldXPos, oldYPos; int w, h; int z; bool b; int xMax, yMax; int cYPos; int cXPosMin, cXPosMax, cYPosMin, cYPosMax; int dx, dy; int pageScroll; int scrollbarWidth = style().scrollBarExtent().width(); //debug("upView %d %d %d %d %d", exposeCursor, updateState, flags, newXPos, newYPos); if (exposeCursor || flags & KateView::ufDocGeometry) { emit myView->newCurPos(); } else { if (updateState == 0 && newXPos < 0 && newYPos < 0) return; } if (cursorTimer) { killTimer(cursorTimer); cursorTimer = startTimer(KApplication::cursorFlashTime() / 2); cursorOn = true; } oldXPos = xPos; oldYPos = yPos; /* if (flags & ufPos) { xPos = newXPos; yPos = newYPos; exposeCursor = true; }*/ if (newXPos >= 0) xPos = newXPos; if (newYPos >= 0) yPos = newYPos; fontHeight = myDoc->fontHeight; cYPos = cursor.y*fontHeight; z = 0; do { w = myView->width() - 4; h = myView->height() - 4; xMax = myDoc->textWidth() - w; b = (xPos > 0 || xMax > 0); if (b) h -= scrollbarWidth; yMax = myDoc->textHeight() - h; if (yPos > 0 || yMax > 0) { w -= scrollbarWidth; xMax += scrollbarWidth; if (!b && xMax > 0) { h -= scrollbarWidth; yMax += scrollbarWidth; } } if (!exposeCursor) break; // if (flags & KateView::ufNoScroll) break; /* if (flags & KateView::ufCenter) { cXPosMin = xPos + w/3; cXPosMax = xPos + (w*2)/3; cYPosMin = yPos + h/3; cYPosMax = yPos + ((h - fontHeight)*2)/3; } else {*/ cXPosMin = xPos + 4; cXPosMax = xPos + w - 8; cYPosMin = yPos; cYPosMax = yPos + (h - fontHeight); // } if (cXPos < cXPosMin) { xPos -= cXPosMin - cXPos; } if (xPos < 0) xPos = 0; if (cXPos > cXPosMax) { xPos += cXPos - cXPosMax; } if (cYPos < cYPosMin) { yPos -= cYPosMin - cYPos; } if (yPos < 0) yPos = 0; if (cYPos > cYPosMax) { yPos += cYPos - cYPosMax; } z++; } while (z < 2); if (xMax < xPos) xMax = xPos; if (yMax < yPos) yMax = yPos; if (xMax > 0) { pageScroll = w - (w % fontHeight) - fontHeight; if (pageScroll <= 0) pageScroll = fontHeight; xScroll->blockSignals(true); xScroll->setGeometry(2,h + 2,w,scrollbarWidth); xScroll->setRange(0,xMax); xScroll->setValue(xPos); xScroll->setSteps(fontHeight,pageScroll); xScroll->blockSignals(false); xScroll->show(); } else xScroll->hide(); if (yMax > 0) { pageScroll = h - (h % fontHeight) - fontHeight; if (pageScroll <= 0) pageScroll = fontHeight; yScroll->blockSignals(true); yScroll->setGeometry(w + 2,2,scrollbarWidth,h); yScroll->setRange(0,yMax); yScroll->setValue(yPos); yScroll->setSteps(fontHeight,pageScroll); yScroll->blockSignals(false); yScroll->show(); } else yScroll->hide(); if (w != width() || h != height()) { clearDirtyCache(h); resize(w,h); } else { dx = oldXPos - xPos; dy = oldYPos - yPos; b = updateState == 3; if (flags & KateView::ufUpdateOnScroll) { b |= dx || dy; } else { b |= QABS(dx)*3 > w*2 || QABS(dy)*3 > h*2; } if (b) { clearDirtyCache(h); update(); } else { if (dy) leftBorder->scroll(0, dy); if (updateState > 0) paintTextLines(oldXPos, oldYPos); clearDirtyCache(h); if (dx || dy) { scroll(dx,dy); // kapp->syncX(); // scroll2(dx - dx/2,dy - dy/2); // } else { } if (cursorOn) paintCursor(); if (bm.eXPos > bm.sXPos) paintBracketMark(); } } exposeCursor = false; // updateState = 0; } void KateViewInternal::paintTextLines(int xPos, int yPos) { // int xStart, xEnd; int line;//, z; int h; LineRange *r; if (!drawBuffer) return; if (drawBuffer->isNull()) return; QPainter paint; paint.begin(drawBuffer); h = myDoc->fontHeight; r = lineRanges; for (line = startLine; line <= endLine; line++) { if (r->start < r->end) { //debug("painttextline %d %d %d", line, r->start, r->end); myDoc->paintTextLine(paint, line, r->start, r->end, myView->configFlags & KateView::cfShowTabs); bitBlt(this, r->start - (xPos-2), line*h - yPos, drawBuffer, 0, 0, r->end - r->start, h); leftBorder->paintLine(line); } r++; } paint.end(); } void KateViewInternal::paintCursor() { int h, y, x; static int cx = 0, cy = 0, ch = 0; h = myDoc->fontHeight; y = h*cursor.y - yPos; x = cXPos - (xPos-2); if(myDoc->myFont != font()) setFont(myDoc->myFont); if(cx != x || cy != y || ch != h){ cx = x; cy = y; ch = h; setMicroFocusHint(cx, cy, 0, ch - 2); } QPainter paint; if (cursorOn) { paint.begin(this); paint.setClipping(false); paint.setPen(myDoc->cursorCol(cursor.x,cursor.y)); h += y - 1; paint.drawLine(x, y, x, h); paint.end(); } else { if (drawBuffer && !drawBuffer->isNull()) { paint.begin(drawBuffer); myDoc->paintTextLine(paint, cursor.y, cXPos - 2, cXPos + 3, myView->configFlags & KateView::cfShowTabs); bitBlt(this,x - 2,y, drawBuffer, 0, 0, 5, h); paint.end(); } } } void KateViewInternal::paintBracketMark() { int y; y = myDoc->fontHeight*(bm.cursor.y +1) - yPos -1; QPainter paint; paint.begin(this); paint.setPen(myDoc->cursorCol(bm.cursor.x, bm.cursor.y)); paint.drawLine(bm.sXPos - (xPos-2), y, bm.eXPos - (xPos-2) -1, y); paint.end(); } void KateViewInternal::placeCursor(int x, int y, int flags) { VConfig c; getVConfig(c); c.flags |= flags; cursor.y = (yPos + y)/myDoc->fontHeight; cXPos = cOldXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor, cursor,xPos-2 + x); changeState(c); } // given physical coordinates, report whether the text there is selected bool KateViewInternal::isTargetSelected(int x, int y) { y = (yPos + y) / myDoc->fontHeight; TextLine::Ptr line = myDoc->getTextLine(y); if (!line) return false; x = myDoc->textPos(line, x); return line->isSelected(x); } void KateViewInternal::focusInEvent(QFocusEvent *) { // debug("got focus %d",cursorTimer); if (!cursorTimer) { cursorTimer = startTimer(KApplication::cursorFlashTime() / 2); cursorOn = true; paintCursor(); } } void KateViewInternal::focusOutEvent(QFocusEvent *) { // debug("lost focus %d", cursorTimer); if (cursorTimer) { killTimer(cursorTimer); cursorTimer = 0; } if (cursorOn) { cursorOn = false; paintCursor(); } } void KateViewInternal::keyPressEvent(QKeyEvent *e) { VConfig c; // int ascii; /* if (e->state() & AltButton) { e->ignore(); return; }*/ // debug("ascii %i, key %i, state %i",e->ascii(), e->key(), e->state()); getVConfig(c); // ascii = e->ascii(); if (!myView->isReadOnly()) { if (c.flags & KateView::cfTabIndents && myDoc->hasMarkedText()) { if (e->key() == Qt::Key_Tab) { myDoc->indent(c); myDoc->updateViews(); return; } if (e->key() == Qt::Key_Backtab) { myDoc->unIndent(c); myDoc->updateViews(); return; } } if ( !(e->state() & ControlButton ) && myDoc->insertChars(c, e->text())) { myDoc->updateViews(); e->accept(); return; } } e->ignore(); } void KateViewInternal::mousePressEvent(QMouseEvent *e) { if (e->button() == LeftButton) { int flags; flags = 0; if (e->state() & ShiftButton) { flags |= KateView::cfMark; if (e->state() & ControlButton) flags |= KateView::cfMark | KateView::cfKeepSelection; } placeCursor(e->x(), e->y(), flags); scrollX = 0; scrollY = 0; if (!scrollTimer) scrollTimer = startTimer(50); myDoc->updateViews(); } if (e->button() == MidButton) { placeCursor(e->x(), e->y()); if (! myView->isReadOnly()) myView->paste(); } if (myView->rmbMenu && e->button() == RightButton) { myView->rmbMenu->popup(mapToGlobal(e->pos())); } myView->mousePressEvent(e); // this doesn't do anything, does it? // it does :-), we need this for KDevelop, so please don't uncomment it again -Sandy } void KateViewInternal::mouseDoubleClickEvent(QMouseEvent *e) { if (e->button() == LeftButton) { VConfig c; getVConfig(c); myDoc->selectWord(c.cursor, c.flags); myDoc->updateViews(); } } void KateViewInternal::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == LeftButton) { if (myView->config() & KateView::cfMouseAutoCopy) myView->copy(); killTimer(scrollTimer); scrollTimer = 0; } } void KateViewInternal::mouseMoveEvent(QMouseEvent *e) { if (e->state() & LeftButton) { int flags; int d; int x = e->x(), y = e->y(); mouseX = e->x(); mouseY = e->y(); scrollX = 0; scrollY = 0; d = myDoc->fontHeight; if (mouseX < 0) { mouseX = 0; scrollX = -d; } if (mouseX > width()) { mouseX = width(); scrollX = d; } if (mouseY < 0) { mouseY = 0; scrollY = -d; } if (mouseY > height()) { mouseY = height(); scrollY = d; } //debug("modifiers %d", ((KGuiCmdApp *) kapp)->getModifiers()); flags = KateView::cfMark; if (e->state() & ControlButton) flags |= KateView::cfKeepSelection; placeCursor(mouseX, mouseY, flags); myDoc->updateViews(/*ufNoScroll*/); } } void KateViewInternal::wheelEvent( QWheelEvent *e ) { if( yScroll->isVisible() == true ) { QApplication::sendEvent( yScroll, e ); } } void KateViewInternal::paintEvent(QPaintEvent *e) { int xStart, xEnd; int h; int line, y, yEnd; QRect updateR = e->rect(); if (!drawBuffer) return; if (drawBuffer->isNull()) return; QPainter paint; paint.begin(drawBuffer); xStart = xPos-2 + updateR.x(); xEnd = xStart + updateR.width(); h = myDoc->fontHeight; line = (yPos + updateR.y()) / h; y = line*h - yPos; yEnd = updateR.y() + updateR.height(); waitForPreHighlight=myDoc->needPreHighlight(waitForPreHighlight=line+((long)(yEnd-y)/h)+5); while (y < yEnd) { TextLine *textLine; int ctxNum = 0; myDoc->paintTextLine(paint, line, xStart, xEnd, myView->configFlags & KateView::cfShowTabs); bitBlt(this, updateR.x(), y, drawBuffer, 0, 0, updateR.width(), h); leftBorder->paintLine(line); line++; y += h; } paint.end(); if (cursorOn) paintCursor(); if (bm.eXPos > bm.sXPos) paintBracketMark(); } void KateViewInternal::resizeEvent(QResizeEvent *) { drawBuffer->resize (width(), myDoc->fontHeight); leftBorder->resize(iconBorderWidth, height()); } void KateViewInternal::timerEvent(QTimerEvent *e) { if (e->timerId() == cursorTimer) { cursorOn = !cursorOn; paintCursor(); } if (e->timerId() == scrollTimer && (scrollX | scrollY)) { xScroll->setValue(xPos + scrollX); yScroll->setValue(yPos + scrollY); placeCursor(mouseX, mouseY, KateView::cfMark); myDoc->updateViews(/*ufNoScroll*/); } } uint KateView::uniqueID = 0; KateView::KateView(KateDocument *doc, QWidget *parent, const char * name) : Kate::View (doc, parent, name) { myViewID = uniqueID; uniqueID++; active = false; myIconBorder = false; myDoc = doc; myViewInternal = new KateViewInternal (this,doc); myViewInternal->move(2, 2); myViewInternal->leftBorder = new KateIconBorder(this, myViewInternal); myViewInternal->leftBorder->setGeometry(2, 2, myViewInternal->iconBorderWidth, myViewInternal->iconBorderHeight); myViewInternal->leftBorder->hide(); doc->addView( this ); // some defaults configFlags = KateView::cfAutoIndent | KateView::cfBackspaceIndents | KateView::cfTabIndents | KateView::cfKeepIndentProfile | KateView::cfRemoveSpaces | KateView::cfDelOnInput | KateView::cfMouseAutoCopy | KateView::cfWrapCursor | KateView::cfGroupUndo | KateView::cfShowTabs | KateView::cfSmartHome; searchFlags = 0; replacePrompt = 0L; rmbMenu = 0L; setFocusProxy( myViewInternal ); myViewInternal->setFocus(); resize(parent->width() -4, parent->height() -4); myViewInternal->installEventFilter( this ); //setupActions(); connect( this, SIGNAL( newStatus() ), this, SLOT( slotUpdate() ) ); connect( this, SIGNAL( newUndo() ), this, SLOT( slotNewUndo() ) ); connect( doc, SIGNAL( fileNameChanged() ), this, SLOT( slotFileStatusChanged() ) ); connect( doc, SIGNAL( highlightChanged() ), this, SLOT( slotHighlightChanged() ) ); readConfig(); // setHighlight->setCurrentItem(getHl()); slotUpdate(); } KateView::~KateView() { + writeConfig(); if (myDoc && !myDoc->m_bSingleViewMode) myDoc->removeView( this ); delete myViewInternal; - } #if 0 void KateView::setupActions() { #if 0 KStdAction::close( this, SLOT(flush()), actionCollection(), "file_close" ); KStdAction::save(this, SLOT(save()), actionCollection()); // setup edit menu editUndo = KStdAction::undo(this, SLOT(undo()), actionCollection()); editRedo = KStdAction::redo(this, SLOT(redo()), actionCollection()); editUndoHist = new KAction(i18n("Undo/Redo &History..."), 0, this, SLOT(undoHistory()), actionCollection(), "edit_undoHistory"); KStdAction::cut(this, SLOT(cut()), actionCollection()); KStdAction::copy(this, SLOT(copy()), actionCollection()); KStdAction::paste(this, SLOT(paste()), actionCollection()); if ( myDoc->hasBrowserExtension() ) { KStdAction::saveAs(this, SLOT(saveAs()), myDoc->actionCollection()); KStdAction::find(this, SLOT(find()), myDoc->actionCollection(), "find"); KStdAction::findNext(this, SLOT(findAgain()), myDoc->actionCollection(), "find_again"); KStdAction::findPrev(this, SLOT(findPrev()), myDoc->actionCollection(), "find_prev"); KStdAction::gotoLine(this, SLOT(gotoLine()), myDoc->actionCollection(), "goto_line" ); new KAction(i18n("&Configure Editor..."), 0, this, SLOT(configDialog()),myDoc->actionCollection(), "set_confdlg"); setHighlight = new KSelectAction(i18n("&Highlight Mode"), 0, myDoc->actionCollection(), "set_highlight"); KStdAction::selectAll(this, SLOT(selectAll()), myDoc->actionCollection(), "select_all"); new KAction(i18n("&Deselect All"), 0, this, SLOT(deselectAll()), myDoc->actionCollection(), "unselect_all"); new KAction(i18n("Invert &Selection"), 0, this, SLOT(invertSelection()), myDoc->actionCollection(), "invert_select"); new KAction(i18n("Increase Font Sizes"), "viewmag+", 0, this, SLOT(slotIncFontSizes()), myDoc->actionCollection(), "incFontSizes"); new KAction(i18n("Decrease Font Sizes"), "viewmag-", 0, this, SLOT(slotDecFontSizes()), myDoc->actionCollection(), "decFontSizes"); } else { KStdAction::saveAs(this, SLOT(saveAs()), actionCollection()); KStdAction::find(this, SLOT(find()), actionCollection()); KStdAction::findNext(this, SLOT(findAgain()), actionCollection()); KStdAction::findPrev(this, SLOT(findPrev()), actionCollection(), "edit_find_prev"); KStdAction::gotoLine(this, SLOT(gotoLine()), actionCollection()); new KAction(i18n("&Configure Editor..."), 0, this, SLOT(configDialog()),actionCollection(), "set_confdlg"); setHighlight = new KSelectAction(i18n("&Highlight Mode"), 0, actionCollection(), "set_highlight"); KStdAction::selectAll(this, SLOT(selectAll()), actionCollection()); new KAction(i18n("&Deselect All"), 0, this, SLOT(deselectAll()), actionCollection(), "edit_deselectAll"); new KAction(i18n("Invert &Selection"), 0, this, SLOT(invertSelection()), actionCollection(), "edit_invertSelection"); new KAction(i18n("Increase Font Sizes"), "viewmag+", 0, this, SLOT(slotIncFontSizes()), actionCollection(), "incFontSizes"); new KAction(i18n("Decrease Font Sizes"), "viewmag-", 0, this, SLOT(slotDecFontSizes()), actionCollection(), "decFontSizes"); } new KAction(i18n("Apply Word Wrap"), 0, myDoc, SLOT(applyWordWrap()), actionCollection(), "edit_apply_wordwrap"); KStdAction::replace(this, SLOT(replace()), actionCollection()); new KAction(i18n("Editing Co&mmand"), Qt::CTRL+Qt::Key_M, this, SLOT(slotEditCommand()), actionCollection(), "edit_cmd"); // setup bookmark menu bookmarkToggle = new KAction(i18n("Toggle &Bookmark"), Qt::CTRL+Qt::Key_B, this, SLOT(toggleBookmark()), actionCollection(), "edit_bookmarkToggle"); bookmarkClear = new KAction(i18n("Clear Bookmarks"), 0, this, SLOT(clearBookmarks()), actionCollection(), "edit_bookmarksClear"); // connect settings menu aboutToshow bookmarkMenu = new KActionMenu(i18n("&Bookmarks"), actionCollection(), "bookmarks"); connect(bookmarkMenu->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(bookmarkMenuAboutToShow())); new KToggleAction(i18n("Show &IconBorder"), Key_F6, this, SLOT(toggleIconBorder()), actionCollection(), "view_border"); // setup Tools menu KStdAction::spelling(this, SLOT(spellcheck()), actionCollection()); new KAction(i18n("&Indent"), "indent", Qt::CTRL+Qt::Key_I, this, SLOT(indent()), actionCollection(), "tools_indent"); new KAction(i18n("&Unindent"), "unindent", Qt::CTRL+Qt::Key_U, this, SLOT(unIndent()), actionCollection(), "tools_unindent"); new KAction(i18n("&Clean Indentation"), 0, this, SLOT(cleanIndent()), actionCollection(), "tools_cleanIndent"); new KAction(i18n("C&omment"), CTRL+Qt::Key_NumberSign, this, SLOT(comment()), actionCollection(), "tools_comment"); new KAction(i18n("Unco&mment"), CTRL+SHIFT+Qt::Key_NumberSign, this, SLOT(uncomment()), actionCollection(), "tools_uncomment"); setVerticalSelection = new KToggleAction(i18n("&Vertical Selection"), Key_F4, this, SLOT(toggleVertical()), actionCollection(), "set_verticalSelect"); connect(setHighlight, SIGNAL(activated(int)), this, SLOT(setHl(int))); QStringList list; for (int z = 0; z < HlManager::self()->highlights(); z++) list.append(HlManager::self()->hlName(z)); setHighlight->setItems(list); setEndOfLine = new KSelectAction(i18n("&End Of Line"), 0, actionCollection(), "set_eol"); connect(setEndOfLine, SIGNAL(activated(int)), this, SLOT(setEol(int))); list.clear(); list.append("&Unix"); list.append("&Windows/Dos"); list.append("&Macintosh"); setEndOfLine->setItems(list); #endif } #endif void KateView::slotUpdate() { int cfg = config(); #warning fixme setVerticalSelection->setChecked(cfg & KateView::cfVerticalSelect); slotNewUndo(); } void KateView::slotFileStatusChanged() { int eol = getEol(); eol = eol>=1 ? eol : 0; #warning fixme setEndOfLine->setCurrentItem(eol); } void KateView::slotNewUndo() { #if 0 int state = undoState(); editUndoHist->setEnabled(state & 1 || state & 2); QString t = i18n("Und&o"); // it would be nicer to fetch the original string if (state & 1) { editUndo->setEnabled(true); t += ' '; t += i18n(undoTypeName(nextUndoType())); } else { editUndo->setEnabled(false); } editUndo->setText(t); t = i18n("Re&do"); // it would be nicer to fetch the original string if (state & 2) { editRedo->setEnabled(true); t += ' '; t += i18n(undoTypeName(nextRedoType())); } else { editRedo->setEnabled(false); } editRedo->setText(t); #endif } void KateView::slotHighlightChanged() { // setHighlight->setCurrentItem(getHl()); } void KateView::keyPressEvent( QKeyEvent *ev ) { switch ( ev->key() ) { case Key_Left: if ( ev->state() & ShiftButton ) { if ( ev->state() & ControlButton ) shiftWordLeft(); else shiftCursorLeft(); } else if ( ev->state() & ControlButton ) wordLeft(); else cursorLeft(); break; case Key_Right: if ( ev->state() & ShiftButton ) { if ( ev->state() & ControlButton ) shiftWordRight(); else shiftCursorRight(); } else if ( ev->state() & ControlButton ) wordRight(); else cursorRight(); break; case Key_Home: if ( ev->state() & ShiftButton ) { if ( ev->state() & ControlButton ) shiftTop(); else shiftHome(); } else if ( ev->state() & ControlButton ) top(); else home(); break; case Key_End: if ( ev->state() & ShiftButton ) { if ( ev->state() & ControlButton ) shiftBottom(); else shiftEnd(); } else if ( ev->state() & ControlButton ) bottom(); else end(); break; case Key_Up: if ( ev->state() & ShiftButton ) shiftUp(); else if ( ev->state() & ControlButton ) scrollUp(); else up(); break; case Key_Down: if ( ev->state() & ShiftButton ) shiftDown(); else if ( ev->state() & ControlButton ) scrollDown(); else down(); break; case Key_PageUp: if ( ev->state() & ShiftButton ) shiftPageUp(); else if ( ev->state() & ControlButton ) topOfView(); else pageUp(); break; case Key_PageDown: if ( ev->state() & ShiftButton ) shiftPageDown(); else if ( ev->state() & ControlButton ) bottomOfView(); else pageDown(); break; case Key_Return: case Key_Enter: keyReturn(); break; case Key_Delete: if ( ev->state() & ControlButton ) { VConfig c; shiftWordRight(); myViewInternal->getVConfig(c); myDoc->delMarkedText(c); myViewInternal->update(); } else keyDelete(); break; case Key_Backspace: if ( ev->state() & ControlButton ) { VConfig c; shiftWordLeft(); myViewInternal->getVConfig(c); myDoc->delMarkedText(c); myViewInternal->update(); } else backspace(); break; case Key_Insert: toggleInsert(); break; case Key_K: if ( ev->state() & ControlButton ) { killLine(); break; } default: KTextEditor::View::keyPressEvent( ev ); return; break; } ev->accept(); } void KateView::setCursorPosition( int line, int col, bool /*mark*/ ) { setCursorPositionInternal( line, col ); } void KateView::getCursorPosition( int *line, int *col ) { if ( line ) *line = currentLine(); if ( col ) *col = currentColumn(); } int KateView::currentLine() { return myViewInternal->cursor.y; } int KateView::currentColumn() { return myDoc->currentColumn(myViewInternal->cursor); } int KateView::currentCharNum() { return myViewInternal->cursor.x; } void KateView::setCursorPositionInternal(int line, int col) { PointStruc cursor; cursor.x = col; cursor.y = line; myViewInternal->updateCursor(cursor); myViewInternal->center(); // myViewInternal->updateView(ufPos, 0, line*myDoc->fontHeight - height()/2); // myDoc->updateViews(myViewInternal); //uptade all other views except this one myDoc->updateViews(); } int KateView::config() { int flags; flags = configFlags; if (myDoc->singleSelection()) flags |= KateView::cfSingleSelection; return flags; } void KateView::setConfig(int flags) { bool updateView; // cfSingleSelection is a doc-property myDoc->setSingleSelection(flags & KateView::cfSingleSelection); flags &= ~KateView::cfSingleSelection; if (flags != configFlags) { // update the view if visibility of tabs has changed updateView = (flags ^ configFlags) & KateView::cfShowTabs; configFlags = flags; emit newStatus(); if (updateView) myViewInternal->update(); } } int KateView::tabWidth() { return myDoc->tabChars; } void KateView::setTabWidth(int w) { myDoc->setTabWidth(w); myDoc->updateViews(); } void KateView::setEncoding (QString e) { myDoc->setEncoding (e); myDoc->updateViews(); } int KateView::undoSteps() { return myDoc->undoSteps; } void KateView::setUndoSteps(int s) { myDoc->setUndoSteps(s); } bool KateView::isReadOnly() { return myDoc->readOnly; } bool KateView::isModified() { return myDoc->modified; } void KateView::setReadOnly(bool m) { myDoc->setReadOnly(m); } void KateView::setModified(bool m) { myDoc->setModified(m); } bool KateView::isLastView() { return myDoc->isLastView(1); } KateDocument *KateView::doc() { return myDoc; } int KateView::undoState() { if (isReadOnly()) return 0; else return myDoc->undoState; } int KateView::nextUndoType() { return myDoc->nextUndoType(); } int KateView::nextRedoType() { return myDoc->nextRedoType(); } void KateView::undoTypeList(QValueList<int> &lst) { myDoc->undoTypeList(lst); } void KateView::redoTypeList(QValueList<int> &lst) { myDoc->redoTypeList(lst); } const char * KateView::undoTypeName(int type) { return KateActionGroup::typeName(type); } QColor* KateView::getColors() { return myDoc->colors; } void KateView::applyColors() { myDoc->tagAll(); myDoc->updateViews(); } bool KateView::isOverwriteMode() const { return ( configFlags & KateView::cfOvr ); } void KateView::setOverwriteMode( bool b ) { if ( isOverwriteMode() && !b ) setConfig( configFlags ^ KateView::cfOvr ); else setConfig( configFlags | KateView::cfOvr ); } void KateView::toggleInsert() { setConfig(configFlags ^ KateView::cfOvr); } void KateView::toggleVertical() { setConfig(configFlags ^ KateView::cfVerticalSelect); } int KateView::numLines() { return myDoc->numLines(); } QString KateView::text() { return myDoc->text(); } QString KateView::currentTextLine() { TextLine::Ptr textLine = myDoc->getTextLine(myViewInternal->cursor.y); return QString(textLine->getText(), textLine->length()); } QString KateView::textLine(int num) { TextLine::Ptr textLine = myDoc->getTextLine(num); return QString(textLine->getText(), textLine->length()); } QString KateView::currentWord() { return myDoc->getWord(myViewInternal->cursor); } QString KateView::word(int x, int y) { PointStruc cursor; cursor.y = (myViewInternal->yPos + y)/myDoc->fontHeight; if (cursor.y < 0 || cursor.y > myDoc->lastLine()) return QString(); cursor.x = myDoc->textPos(myDoc->getTextLine(cursor.y), myViewInternal->xPos-2 + x); return myDoc->getWord(cursor); } void KateView::setText(const QString &s) { myDoc->setText(s); myDoc->updateViews(); } void KateView::insertText(const QString &s, bool /*mark*/) { VConfig c; myViewInternal->getVConfig(c); myDoc->insert(c, s); myDoc->updateViews(); } bool KateView::hasMarkedText() { return myDoc->hasMarkedText(); } QString KateView::markedText() { return myDoc->markedText(configFlags); } bool KateView::canDiscard() { int query; if (isModified()) { query = KMessageBox::warningYesNoCancel(this, i18n("The current Document has been modified.\nWould you like to save it?")); switch (query) { case KMessageBox::Yes: //yes if (save() == CANCEL) return false; if (isModified()) { query = KMessageBox::warningContinueCancel(this, i18n("Could not save the document.\nDiscard it and continue?"), QString::null, i18n("&Discard")); if (query == KMessageBox::Cancel) return false; } break; case KMessageBox::Cancel: //cancel return false; } } return true; } void KateView::flush() { if (canDiscard()) myDoc->flush(); } KateView::fileResult KateView::save() { int query = KMessageBox::Yes; if (isModified()) { return saveAs(); } return OK; } KateView::fileResult KateView::saveAs() { return OK; } void KateView::doCursorCommand(int cmdNum) { VConfig c; myViewInternal->getVConfig(c); if (cmdNum & selectFlag) c.flags |= KateView::cfMark; if (cmdNum & multiSelectFlag) c.flags |= KateView::cfMark | KateView::cfKeepSelection; cmdNum &= ~(selectFlag | multiSelectFlag); myViewInternal->doCursorCommand(c, cmdNum); myDoc->updateViews(); } void KateView::doEditCommand(int cmdNum) { VConfig c; myViewInternal->getVConfig(c); myViewInternal->doEditCommand(c, cmdNum); myDoc->updateViews(); } void KateView::undoMultiple(int count) { if (isReadOnly()) return; VConfig c; myViewInternal->getVConfig(c); myDoc->undo(c, count); myDoc->updateViews(); } void KateView::redoMultiple(int count) { if (isReadOnly()) return; VConfig c; myViewInternal->getVConfig(c); myDoc->redo(c, count); myDoc->updateViews(); } void KateView::undoHistory() { UndoHistory *undoH; undoH = new UndoHistory(this, this, "UndoHistory", true); undoH->setCaption(i18n("Undo/Redo History")); connect(this,SIGNAL(newUndo()),undoH,SLOT(newUndo())); connect(undoH,SIGNAL(undo(int)),this,SLOT(undoMultiple(int))); connect(undoH,SIGNAL(redo(int)),this,SLOT(redoMultiple(int))); undoH->exec(); delete undoH; } static void kwview_addToStrList(QStringList &list, const QString &str) { if (list.count() > 0) { if (list.first() == str) return; QStringList::Iterator it; it = list.find(str); if (*it != 0L) list.remove(it); if (list.count() >= 16) list.remove(list.fromLast()); } list.prepend(str); } void KateView::find() { SearchDialog *searchDialog; if (!myDoc->hasMarkedText()) searchFlags &= ~KateView::sfSelected; searchDialog = new SearchDialog(this, myDoc->searchForList, myDoc->replaceWithList, searchFlags & ~KateView::sfReplace); // If the user has marked some text we use that otherwise // use the word under the cursor. QString str; if (myDoc->hasMarkedText()) str = markedText(); if (str.isEmpty()) str = currentWord(); if (!str.isEmpty()) { str.replace(QRegExp("^\n"), ""); int pos=str.find("\n"); if (pos>-1) str=str.left(pos); searchDialog->setSearchText( str ); } myViewInternal->focusOutEvent(0L);// QT bug ? if (searchDialog->exec() == QDialog::Accepted) { kwview_addToStrList(myDoc->searchForList, searchDialog->getSearchFor()); searchFlags = searchDialog->getFlags() | (searchFlags & KateView::sfPrompt); initSearch(s, searchFlags); findAgain(s); } delete searchDialog; } void KateView::replace() { SearchDialog *searchDialog; if (isReadOnly()) return; if (!myDoc->hasMarkedText()) searchFlags &= ~KateView::sfSelected; searchDialog = new SearchDialog(this, myDoc->searchForList, myDoc->replaceWithList, searchFlags | KateView::sfReplace); // If the user has marked some text we use that otherwise // use the word under the cursor. QString str; if (myDoc->hasMarkedText()) str = markedText(); if (str.isEmpty()) str = currentWord(); if (!str.isEmpty()) { str.replace(QRegExp("^\n"), ""); int pos=str.find("\n"); if (pos>-1) str=str.left(pos); searchDialog->setSearchText( str ); } myViewInternal->focusOutEvent(0L);// QT bug ? if (searchDialog->exec() == QDialog::Accepted) { // myDoc->recordReset(); kwview_addToStrList(myDoc->searchForList, searchDialog->getSearchFor()); kwview_addToStrList(myDoc->replaceWithList, searchDialog->getReplaceWith()); searchFlags = searchDialog->getFlags(); initSearch(s, searchFlags); replaceAgain(); } delete searchDialog; } void KateView::gotoLine() { GotoLineDialog *dlg; PointStruc cursor; dlg = new GotoLineDialog(this, myViewInternal->cursor.y + 1, myDoc->numLines()); // dlg = new GotoLineDialog(myViewInternal->cursor.y + 1, this); if (dlg->exec() == QDialog::Accepted) { // myDoc->recordReset(); cursor.x = 0; cursor.y = dlg->getLine() - 1; myDoc->needPreHighlight(cursor.y); myViewInternal->updateCursor(cursor); myViewInternal->center(); myViewInternal->updateView(KateView::ufUpdateOnScroll); myDoc->updateViews(this); //uptade all other views except this one } delete dlg; } void KateView::initSearch(SConfig &s, int flags) { s.flags = flags; s.setPattern(myDoc->searchForList.first()); if (!(s.flags & KateView::sfFromBeginning)) { // If we are continuing a backward search, make sure we do not get stuck // at an existing match. s.cursor = myViewInternal->cursor; TextLine::Ptr textLine = myDoc->getTextLine(s.cursor.y); QString const txt(textLine->getText(),textLine->length()); const QString searchFor= myDoc->searchForList.first(); int pos = s.cursor.x-searchFor.length()-1; if ( pos < 0 ) pos = 0; pos= txt.find(searchFor, pos, s.flags & KateView::sfCaseSensitive); if ( s.flags & KateView::sfBackward ) { if ( pos <= s.cursor.x ) s.cursor.x= pos-1; } else if ( pos == s.cursor.x ) s.cursor.x++; } else { if (!(s.flags & KateView::sfBackward)) { s.cursor.x = 0; s.cursor.y = 0; } else { s.cursor.x = -1; s.cursor.y = myDoc->lastLine(); } s.flags |= KateView::sfFinished; } if (!(s.flags & KateView::sfBackward)) { if (!(s.cursor.x || s.cursor.y)) s.flags |= KateView::sfFinished; } s.startCursor = s.cursor; } void KateView::continueSearch(SConfig &s) { if (!(s.flags & KateView::sfBackward)) { s.cursor.x = 0; s.cursor.y = 0; } else { s.cursor.x = -1; s.cursor.y = myDoc->lastLine(); } s.flags |= KateView::sfFinished; s.flags &= ~KateView::sfAgain; } void KateView::findAgain(SConfig &s) { int query; PointStruc cursor; QString str; QString searchFor = myDoc->searchForList.first(); if( searchFor.isEmpty() ) { find(); return; } do { query = KMessageBox::Cancel; if (myDoc->doSearch(s,searchFor)) { cursor = s.cursor; if (!(s.flags & KateView::sfBackward)) s.cursor.x += s.matchedLength; myViewInternal->updateCursor(s.cursor); //does deselectAll() exposeFound(cursor,s.matchedLength,(s.flags & KateView::sfAgain) ? 0 : KateView::ufUpdateOnScroll,false); } else { if (!(s.flags & KateView::sfFinished)) { // ask for continue if (!(s.flags & KateView::sfBackward)) { // forward search str = i18n("End of document reached.\n" "Continue from the beginning?"); query = KMessageBox::warningContinueCancel(this, str, i18n("Find"), i18n("Continue")); } else { // backward search str = i18n("Beginning of document reached.\n" "Continue from the end?"); query = KMessageBox::warningContinueCancel(this, str, i18n("Find"), i18n("Continue")); } continueSearch(s); } else { // wrapped KMessageBox::sorry(this, i18n("Search string '%1' not found!").arg(searchFor), i18n("Find")); } } } while (query == KMessageBox::Continue); } void KateView::replaceAgain() { if (isReadOnly()) return; replaces = 0; if (s.flags & KateView::sfPrompt) { doReplaceAction(-1); } else { doReplaceAction(KateView::srAll); } } void KateView::doReplaceAction(int result, bool found) { int rlen; PointStruc cursor; bool started; QString searchFor = myDoc->searchForList.first(); QString replaceWith = myDoc->replaceWithList.first(); rlen = replaceWith.length(); switch (result) { case KateView::srYes: //yes myDoc->recordStart(this, s.cursor, configFlags, KateActionGroup::ugReplace, true); myDoc->recordReplace(s.cursor, s.matchedLength, replaceWith); replaces++; if (s.cursor.y == s.startCursor.y && s.cursor.x < s.startCursor.x) s.startCursor.x += rlen - s.matchedLength; if (!(s.flags & KateView::sfBackward)) s.cursor.x += rlen; myDoc->recordEnd(this, s.cursor, configFlags | KateView::cfPersistent); break; case KateView::srNo: //no if (!(s.flags & KateView::sfBackward)) s.cursor.x += s.matchedLength; break; case KateView::srAll: //replace all deleteReplacePrompt(); do { started = false; while (found || myDoc->doSearch(s,searchFor)) { if (!started) { found = false; myDoc->recordStart(this, s.cursor, configFlags, KateActionGroup::ugReplace); started = true; } myDoc->recordReplace(s.cursor, s.matchedLength, replaceWith); replaces++; if (s.cursor.y == s.startCursor.y && s.cursor.x < s.startCursor.x) s.startCursor.x += rlen - s.matchedLength; if (!(s.flags & KateView::sfBackward)) s.cursor.x += rlen; } if (started) myDoc->recordEnd(this, s.cursor, configFlags | KateView::cfPersistent); } while (!askReplaceEnd()); return; case KateView::srCancel: //cancel deleteReplacePrompt(); return; default: replacePrompt = 0L; } do { if (myDoc->doSearch(s,searchFor)) { //text found: highlight it, show replace prompt if needed and exit cursor = s.cursor; if (!(s.flags & KateView::sfBackward)) cursor.x += s.matchedLength; myViewInternal->updateCursor(cursor); //does deselectAll() exposeFound(s.cursor,s.matchedLength,(s.flags & KateView::sfAgain) ? 0 : KateView::ufUpdateOnScroll,true); if (replacePrompt == 0L) { replacePrompt = new ReplacePrompt(this); myDoc->setPseudoModal(replacePrompt);//disable(); connect(replacePrompt,SIGNAL(clicked()),this,SLOT(replaceSlot())); replacePrompt->show(); //this is not modal } return; //exit if text found } //nothing found: repeat until user cancels "repeat from beginning" dialog } while (!askReplaceEnd()); deleteReplacePrompt(); } void KateView::exposeFound(PointStruc &cursor, int slen, int flags, bool replace) { int x1, x2, y1, y2, xPos, yPos; VConfig c; myViewInternal->getVConfig(c); myDoc->selectLength(cursor,slen,c.flags); TextLine::Ptr textLine = myDoc->getTextLine(cursor.y); x1 = myDoc->textWidth(textLine,cursor.x) -10; x2 = myDoc->textWidth(textLine,cursor.x + slen) +20; y1 = myDoc->fontHeight*cursor.y -10; y2 = y1 + myDoc->fontHeight +30; xPos = myViewInternal->xPos; yPos = myViewInternal->yPos; if (x1 < 0) x1 = 0; if (replace) y2 += 90; if (x1 < xPos || x2 > xPos + myViewInternal->width()) { xPos = x2 - myViewInternal->width(); } if (y1 < yPos || y2 > yPos + myViewInternal->height()) { xPos = x2 - myViewInternal->width(); yPos = myDoc->fontHeight*cursor.y - height()/3; } myViewInternal->setPos(xPos, yPos); myViewInternal->updateView(flags);// | ufPos,xPos,yPos); myDoc->updateViews(this); } void KateView::deleteReplacePrompt() { myDoc->setPseudoModal(0L); } bool KateView::askReplaceEnd() { QString str; int query; myDoc->updateViews(); if (s.flags & KateView::sfFinished) { // replace finished str = i18n("%1 replacement(s) made").arg(replaces); KMessageBox::information(this, str, i18n("Replace")); return true; } // ask for continue if (!(s.flags & KateView::sfBackward)) { // forward search str = i18n("%1 replacement(s) made.\n" "End of document reached.\n" "Continue from the beginning?").arg(replaces); query = KMessageBox::questionYesNo(this, str, i18n("Replace"), i18n("Continue"), i18n("Stop")); } else { // backward search str = i18n("%1 replacement(s) made.\n" "Beginning of document reached.\n" "Continue from the end?").arg(replaces); query = KMessageBox::questionYesNo(this, str, i18n("Replace"), i18n("Continue"), i18n("Stop")); } replaces = 0; continueSearch(s); return (query == KMessageBox::No); } void KateView::replaceSlot() { doReplaceAction(replacePrompt->result(),true); } void KateView::installPopup(QPopupMenu *rmb_Menu) { rmbMenu = rmb_Menu; } void KateView::readConfig() { - KConfig *config = KGlobal::config(); + KateConfig *config = KGlobal::config(); config->setGroup("Kate View"); searchFlags = config->readNumEntry("SearchFlags", KateView::sfPrompt); configFlags = config->readNumEntry("ConfigFlags", configFlags) & ~KateView::cfMark; - config->sync(); +// config->sync(); } void KateView::writeConfig() { - KConfig *config = KGlobal::config(); + KateConfig *config = KGlobal::config(); config->setGroup("Kate View"); config->writeEntry("SearchFlags",searchFlags); config->writeEntry("ConfigFlags",configFlags); - config->sync(); +// config->sync(); } -void KateView::readSessionConfig(KConfig *config) +void KateView::readSessionConfig(KateConfig *config) { PointStruc cursor; myViewInternal->xPos = config->readNumEntry("XPos"); myViewInternal->yPos = config->readNumEntry("YPos"); cursor.x = config->readNumEntry("CursorX"); cursor.y = config->readNumEntry("CursorY"); myViewInternal->updateCursor(cursor); myIconBorder = config->readBoolEntry("IconBorder on"); setIconBorder(myIconBorder); } -void KateView::writeSessionConfig(KConfig *config) +void KateView::writeSessionConfig(KateConfig *config) { config->writeEntry("XPos",myViewInternal->xPos); config->writeEntry("YPos",myViewInternal->yPos); config->writeEntry("CursorX",myViewInternal->cursor.x); config->writeEntry("CursorY",myViewInternal->cursor.y); config->writeEntry("IconBorder on", myIconBorder); } void KateView::configDialog() { #warning fixme #if 1 KDialogBase *kd = new KDialogBase(KDialogBase::IconList, i18n("Configure Editor"), KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Help , KDialogBase::Ok, this, "tabdialog"); // color options QFrame *page=kd->addPage(i18n("Colors")); (new QVBoxLayout(page))->setAutoAdd(true); ColorConfig *colorConfig = new ColorConfig(page); QColor* colors = getColors(); colorConfig->setColors(colors); page = kd->addPage(i18n("Fonts")); (new QVBoxLayout(page))->setAutoAdd(true); FontConfig *fontConfig = new FontConfig(page); fontConfig->setFont (myDoc->getFont()); // indent options page=kd->addPage(i18n("Indent")); (new QVBoxLayout(page))->setAutoAdd(true); IndentConfigTab *indentConfig = new IndentConfigTab(page, this); // select options page=kd->addPage(i18n("Select")); (new QVBoxLayout(page))->setAutoAdd(true); SelectConfigTab *selectConfig = new SelectConfigTab(page, this); // edit options page=kd->addPage(i18n("Edit")); (new QVBoxLayout(page))->setAutoAdd(true); EditConfigTab *editConfig = new EditConfigTab(page, this); HighlightDialogPage *hlPage; HlManager *hlManager; HlDataList hlDataList; ItemStyleList defaultStyleList; hlManager = HlManager::self(); defaultStyleList.setAutoDelete(true); hlManager->getDefaults(defaultStyleList); hlDataList.setAutoDelete(true); - //this gets the data from the KConfig object + //this gets the data from the KateConfig object hlManager->getHlDataList(hlDataList); page=kd->addPage(i18n("Highlighting")); (new QVBoxLayout(page))->setAutoAdd(true); hlPage = new HighlightDialogPage(hlManager, &defaultStyleList, &hlDataList, 0, page); kd->showMaximized(); if (kd->exec()) { // color options colorConfig->getColors(colors); myDoc->setFont (fontConfig->getFont()); applyColors(); // indent options indentConfig->getData(this); // select options selectConfig->getData(this); // edit options editConfig->getData(this); // spell checker hlManager->setHlDataList(hlDataList); hlManager->setDefaults(defaultStyleList); hlPage->saveData(); } // delete kd; #endif } int KateView::getHl() { return myDoc->highlightNum(); } void KateView::setDontChangeHlOnSave() { myDoc->setDontChangeHlOnSave(); } void KateView::setHl(int n) { myDoc->setHighlight(n); myDoc->setDontChangeHlOnSave(); myDoc->updateViews(); } int KateView::getEol() { return myDoc->eolMode; } void KateView::setEol(int eol) { if (isReadOnly()) return; myDoc->eolMode = eol; myDoc->setModified(true); } void KateView::paintEvent(QPaintEvent *e) { int x, y; QRect updateR = e->rect(); // update rectangle // debug("Update rect = ( %i, %i, %i, %i )", // updateR.x(),updateR.y(), updateR.width(), updateR.height() ); int ux1 = updateR.x(); int uy1 = updateR.y(); int ux2 = ux1 + updateR.width(); int uy2 = uy1 + updateR.height(); QPainter paint; paint.begin(this); QColorGroup g = colorGroup(); x = width(); y = height(); paint.setPen(g.dark()); if (uy1 <= 0) paint.drawLine(0,0,x-2,0); if (ux1 <= 0) paint.drawLine(0,1,0,y-2); paint.setPen(black); if (uy1 <= 1) paint.drawLine(1,1,x-3,1); if (ux1 <= 1) paint.drawLine(1,2,1,y-3); paint.setPen(g.midlight()); if (uy2 >= y-1) paint.drawLine(1,y-2,x-3,y-2); if (ux2 >= x-1) paint.drawLine(x-2,1,x-2,y-2); paint.setPen(g.light()); if (uy2 >= y) paint.drawLine(0,y-1,x-2,y-1); if (ux2 >= x) paint.drawLine(x-1,0,x-1,y-1); x -= 2 + 16; y -= 2 + 16; if (ux2 > x && uy2 > y) { paint.fillRect(x,y,16,16,g.background()); } paint.end(); } void KateView::resizeEvent(QResizeEvent *) { // debug("Resize %d, %d",e->size().width(),e->size().height()); //myViewInternal->resize(width() -20, height() -20); myViewInternal->tagAll(); myViewInternal->updateView(0/*ufNoScroll*/); } // Applies a new pattern to the search context. void SConfig::setPattern(QString &newPattern) { bool regExp = (flags & KateView::sfRegularExpression); m_pattern = newPattern; if (regExp) { m_regExp.setCaseSensitive(flags & KateView::sfCaseSensitive); m_regExp.setPattern(m_pattern); } } // Applies the search context to the given string, and returns whether a match was found. If one is, // the length of the string matched is also returned. int SConfig::search(QString &text, int index) { bool regExp = (flags & KateView::sfRegularExpression); bool caseSensitive = (flags & KateView::sfCaseSensitive); if (flags & KateView::sfBackward) { if (regExp) { index = text.findRev(m_regExp, index); } else { index = text.findRev(m_pattern, index, caseSensitive); } } else { if (regExp) { index = text.find(m_regExp, index); } else { index = text.find(m_pattern, index, caseSensitive); } } // Work out the matched length. if (index != -1) { if (regExp) { m_regExp.match(text, index, &matchedLength, false); } else { matchedLength = m_pattern.length(); } } return index; } void KateView::setActive (bool b) { active = b; } bool KateView::isActive () { return active; } void KateView::setFocus () { QWidget::setFocus (); emit gotFocus (this); } bool KateView::eventFilter (QObject *object, QEvent *event) { if ( (event->type() == QEvent::FocusIn) ) emit gotFocus (this); if ( (event->type() == QEvent::KeyPress) ) { QKeyEvent * ke=(QKeyEvent *)event; if ((ke->key()==Qt::Key_Tab) || (ke->key()==Qt::Key_BackTab)) { myViewInternal->keyPressEvent(ke); return true; } } return QWidget::eventFilter (object, event); } void KateView::findAgain (bool back) { bool b= (searchFlags & sfBackward) > 0; initSearch(s, (searchFlags & ((b==back)?~sfBackward:~0) & ~sfFromBeginning) // clear flag for forward searching | sfPrompt | sfAgain | ((b!=back)?sfBackward:0) ); if (s.flags & sfReplace) replaceAgain(); else KateView::findAgain(s); } void KateView::slotEditCommand () { #warning fixme /* bool ok; QString cmd = KLineEditDlg::getText("Editing Command", "", &ok, this); if (ok) myDoc->cmd()->execCmd (cmd, this);*/ } void KateView::setIconBorder (bool enable) { myIconBorder = enable; if (myIconBorder) { myViewInternal->move(myViewInternal->iconBorderWidth+2, 2); myViewInternal->leftBorder->show(); } else { myViewInternal->leftBorder->hide(); myViewInternal->move(2, 2); } } void KateView::toggleIconBorder () { setIconBorder (!myIconBorder); } void KateView::gotoMark (Kate::Mark *mark) { PointStruc cursor; cursor.x = 0; cursor.y = mark->line; myDoc->needPreHighlight(cursor.y); myViewInternal->updateCursor(cursor); myViewInternal->center(); myViewInternal->updateView(KateView::ufUpdateOnScroll); myDoc->updateViews(this); } void KateView::toggleBookmark () { TextLine::Ptr line = myDoc->getTextLine (currentLine()); if (line->mark()&KateDocument::Bookmark) line->delMark(KateDocument::Bookmark); else line->addMark(KateDocument::Bookmark); myDoc->tagLines (currentLine(), currentLine()); myDoc->updateViews(); } void KateView::clearBookmarks() { QList<Kate::Mark> list = myDoc->marks(); for (int i=0; (uint) i < list.count(); i++) { if (list.at(i)->type&KateDocument::Bookmark) { myDoc->getTextLine(list.at(i)->line)->delMark(KateDocument::Bookmark); myDoc->tagLines(list.at(i)->line, list.at(i)->line); } } myDoc->updateViews(); } void KateView::bookmarkMenuAboutToShow() { #warning fixme #if 0 bookmarkMenu->popupMenu()->clear (); bookmarkToggle->plug (bookmarkMenu->popupMenu()); bookmarkClear->plug (bookmarkMenu->popupMenu()); bookmarkMenu->popupMenu()->insertSeparator (); list = myDoc->marks(); for (int i=0; (uint) i < list.count(); i++) { if (list.at(i)->type&KateDocument::Bookmark) { QString bText = textLine(list.at(i)->line); bText.truncate(32); bText.append ("..."); bookmarkMenu->popupMenu()->insertItem ( QString("%1 - \"%2\"").arg(list.at(i)->line).arg(bText), this, SLOT (gotoBookmark(int)), 0, i ); } } #endif } void KateView::gotoBookmark (int n) { gotoMark (list.at(n)); } int KateView::getHlCount () { return HlManager::self()->highlights(); } QString KateView::getHlName (int z) { return HlManager::self()->hlName(z); } QString KateView::getHlSection (int z) { return HlManager::self()->hlSection (z); } void KateView::slotIncFontSizes () { QFont font = myDoc->getFont(); font.setPointSize (font.pointSize()+2); myDoc->setFont (font); } void KateView::slotDecFontSizes () { QFont font = myDoc->getFont(); font.setPointSize (font.pointSize()-2); myDoc->setFont (font); } const char*bookmark_xpm[]={ "12 16 4 1", "b c #808080", "a c #000080", "# c #0000ff", ". c None", "............", "............", "........###.", ".......#...a", "......#.##.a", ".....#.#..aa", "....#.#...a.", "...#.#.a.a..", "..#.#.a.a...", ".#.#.a.a....", "#.#.a.a.....", "#.#a.a...bbb", "#...a..bbb..", ".aaa.bbb....", "............", "............"}; const char* breakpoint_xpm[]={ "11 16 6 1", "c c #c6c6c6", ". c None", "# c #000000", "d c #840000", "a c #ffffff", "b c #ff0000", "...........", "...........", "...#####...", "..#aaaaa#..", ".#abbbbbb#.", "#abbbbbbbb#", "#abcacacbd#", "#abbbbbbbb#", "#abcacacbd#", "#abbbbbbbb#", ".#bbbbbbb#.", "..#bdbdb#..", "...#####...", "...........", "...........", "..........."}; const char*breakpoint_bl_xpm[]={ "11 16 7 1", "a c #c0c0ff", "# c #000000", "c c #0000c0", "e c #0000ff", "b c #dcdcdc", "d c #ffffff", ". c None", "...........", "...........", "...#####...", "..#ababa#..", ".#bcccccc#.", "#acccccccc#", "#bcadadace#", "#acccccccc#", "#bcadadace#", "#acccccccc#", ".#ccccccc#.", "..#cecec#..", "...#####...", "...........", "...........", "..........."}; const char*breakpoint_gr_xpm[]={ "11 16 6 1", "c c #c6c6c6", "d c #2c2c2c", "# c #000000", ". c None", "a c #ffffff", "b c #555555", "...........", "...........", "...#####...", "..#aaaaa#..", ".#abbbbbb#.", "#abbbbbbbb#", "#abcacacbd#", "#abbbbbbbb#", "#abcacacbd#", "#abbbbbbbb#", ".#bbbbbbb#.", "..#bdbdb#..", "...#####...", "...........", "...........", "..........."}; const char*ddd_xpm[]={ "11 16 4 1", "a c #00ff00", "b c #000000", ". c None", "# c #00c000", "...........", "...........", "...........", "#a.........", "#aaa.......", "#aaaaa.....", "#aaaaaaa...", "#aaaaaaaaa.", "#aaaaaaa#b.", "#aaaaa#b...", "#aaa#b.....", "#a#b.......", "#b.........", "...........", "...........", "..........."}; KateIconBorder::KateIconBorder(KateView *view, KateViewInternal *internalView) : QWidget(view), myView(view), myInternalView(internalView) { lmbSetsBreakpoints = true; } KateIconBorder::~KateIconBorder() { } void KateIconBorder::paintLine(int i) { if (!myView->myIconBorder) return; QPainter p(this); int fontHeight = myView->doc()->fontHeight; int y = i*fontHeight - myInternalView->yPos; p.fillRect(0, y, myInternalView->iconBorderWidth-2, fontHeight, colorGroup().background()); p.setPen(white); p.drawLine(myInternalView->iconBorderWidth-2, y, myInternalView->iconBorderWidth-2, y + fontHeight); p.setPen(QColor(colorGroup().background()).dark()); p.drawLine(myInternalView->iconBorderWidth-1, y, myInternalView->iconBorderWidth-1, y + fontHeight); TextLine *line = myView->doc()->getTextLine(i); if (!line) return; if (line->mark()&KateDocument::Bookmark) p.drawPixmap(2, y, QPixmap(bookmark_xpm)); /* if (line && (line->breakpointId() != -1)) { if (!line->breakpointEnabled()) p.drawPixmap(2, y, QPixmap(breakpoint_gr_xpm)); else if (line->breakpointPending()) p.drawPixmap(2, y, QPixmap(breakpoint_bl_xpm)); else p.drawPixmap(2, y, QPixmap(breakpoint_xpm)); } if (line->isExecutionPoint()) p.drawPixmap(2, y, QPixmap(ddd_xpm)); */ } void KateIconBorder::paintEvent(QPaintEvent* e) { if (!myView->myIconBorder) return; int lineStart = 0; int lineEnd = 0; QRect updateR = e->rect(); KateDocument *doc = myView->doc(); int h = doc->fontHeight; int yPos = myInternalView->yPos; if (h) { lineStart = (yPos + updateR.y()) / h; lineEnd = QMAX((yPos + updateR.y() + updateR.height()) / h, (int)doc->numLines()); } for(int i = lineStart; i <= lineEnd; ++i) paintLine(i); } void KateIconBorder::mousePressEvent(QMouseEvent* e) { myInternalView->placeCursor( 0, e->y(), 0 ); KateDocument *doc = myView->doc(); int cursorOnLine = (e->y() + myInternalView->yPos) / doc->fontHeight; TextLine *line = doc->getTextLine(cursorOnLine); switch (e->button()) { case LeftButton: if (!line) break; else { if (line->mark()&KateDocument::Bookmark) line->delMark (KateDocument::Bookmark); else line->addMark (KateDocument::Bookmark); doc->tagLines(cursorOnLine, cursorOnLine); doc->updateViews(); } break; /* case RightButton: { if (!line) break; KPopupMenu popup; popup.setCheckable(true); popup.insertTitle(i18n("Breakpoints/Bookmarks")); int idToggleBookmark = popup.insertItem(i18n("Toggle bookmark")); popup.insertSeparator(); int idToggleBreakpoint = popup.insertItem(i18n("Toggle breakpoint")); int idEditBreakpoint = popup.insertItem(i18n("Edit breakpoint")); int idEnableBreakpoint = popup.insertItem(i18n("Disable breakpoint")); popup.insertSeparator(); popup.insertSeparator(); int idLmbSetsBreakpoints = popup.insertItem(i18n("LMB sets breakpoints")); int idLmbSetsBookmarks = popup.insertItem(i18n("LMB sets bookmarks")); popup.setItemChecked(idLmbSetsBreakpoints, lmbSetsBreakpoints); popup.setItemChecked(idLmbSetsBookmarks, !lmbSetsBreakpoints); if (line->breakpointId() == -1) { popup.setItemEnabled(idEditBreakpoint, false); popup.setItemEnabled(idEnableBreakpoint, false); popup.changeItem(idEnableBreakpoint, i18n("Enable breakpoint")); } int res = popup.exec(mapToGlobal(e->pos())); if (res == idToggleBookmark) { line->toggleBookmark(); doc->tagLines(cursorOnLine, cursorOnLine); doc->updateViews(); } else if (res == idToggleBreakpoint) emit myView->toggledBreakpoint(cursorOnLine); else if (res == idEditBreakpoint) emit myView->editedBreakpoint(cursorOnLine); else if (res == idEnableBreakpoint) emit myView->toggledBreakpointEnabled(cursorOnLine+1); else if (res == idLmbSetsBreakpoints || res == idLmbSetsBookmarks) lmbSetsBreakpoints = !lmbSetsBreakpoints; break; } case MidButton: line->toggleBookmark(); doc->tagLines(cursorOnLine, cursorOnLine); doc->updateViews(); break; */ default: break; } } diff --git a/noncore/apps/tinykate/libkate/view/kateview.h b/noncore/apps/tinykate/libkate/view/kateview.h index 2e78a3a..858e8a1 100644 --- a/noncore/apps/tinykate/libkate/view/kateview.h +++ b/noncore/apps/tinykate/libkate/view/kateview.h @@ -1,865 +1,866 @@ /*************************************************************************** kateview.h - description ------------------- begin : Mon Jan 15 2001 copyright : (C) 2001 by Christoph "Crossfire" Cullmann (C) 2002 by Joseph Wenninger email : crossfire@babylon2k.de jowenn@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* Copyright (C) 1998, 1999 Jochen Wilhelmy digisnap@cs.tu-berlin.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef kate_view_h #define kate_view_h #include "../interfaces/view.h" #include "../interfaces/document.h" #include <qlist.h> #include <qstring.h> #include <qdialog.h> class KateDocument; +class KateConfig; class Highlight; /* //dialog results const int srYes = QDialog::Accepted; const int srNo = 10; const int srAll = 11; const int srCancel = QDialog::Rejected; */ // --- config flags --- // indent enum Select_flags { selectFlag = 0x100000, multiSelectFlag = 0x200000 }; //state commands enum State_commands { cmToggleInsert = 1, cmToggleVertical = 2 }; class KateViewInternal; class KateView; struct PointStruc { int x; int y; }; struct VConfig { KateView *view; PointStruc cursor; int cXPos; int flags; }; struct SConfig { PointStruc cursor; PointStruc startCursor; int flags; // Set the pattern to be used for searching. void setPattern(QString &newPattern); // Search the given string. int search(QString &text, int index); // The length of the last match found using pattern or regExp. int matchedLength; private: QString m_pattern; // The regular expression corresponding to pattern. Only guaranteed valid if // flags has sfRegularExpression set. QRegExp m_regExp; }; struct LineRange { int start; int end; }; struct BracketMark { PointStruc cursor; int sXPos; int eXPos; }; class KateIconBorder : public QWidget { public: KateIconBorder(KateView *view, class KateViewInternal *internalView); ~KateIconBorder(); void paintLine(int i); protected: void paintEvent(QPaintEvent* e); void mousePressEvent(QMouseEvent* e); private: KateView *myView; class KateViewInternal *myInternalView; bool lmbSetsBreakpoints; }; class KateViewInternal : public QWidget { Q_OBJECT friend class KateDocument; friend class KateView; friend class KateIconBorder; private: long waitForPreHighlight; int iconBorderWidth; int iconBorderHeight; protected slots: void slotPreHighlightUpdate(long line); public: KateViewInternal(KateView *view, KateDocument *doc); ~KateViewInternal(); virtual void doCursorCommand(VConfig &, int cmdNum); virtual void doEditCommand(VConfig &, int cmdNum); void cursorLeft(VConfig &); void cursorRight(VConfig &); void wordLeft(VConfig &); void wordRight(VConfig &); void home(VConfig &); void end(VConfig &); void cursorUp(VConfig &); void cursorDown(VConfig &); void scrollUp(VConfig &); void scrollDown(VConfig &); void topOfView(VConfig &); void bottomOfView(VConfig &); void pageUp(VConfig &); void pageDown(VConfig &); void cursorPageUp(VConfig &); void cursorPageDown(VConfig &); void top(VConfig &); void bottom(VConfig &); void top_home(VConfig &c); void bottom_end(VConfig &c); protected slots: void changeXPos(int); void changeYPos(int); protected: void getVConfig(VConfig &); void changeState(VConfig &); void insLine(int line); void delLine(int line); void updateCursor(); void updateCursor(PointStruc &newCursor); void updateCursor(PointStruc &newCursor, int flags); void clearDirtyCache(int height); void tagLines(int start, int end, int x1, int x2); void tagAll(); void setPos(int x, int y); void center(); void updateView(int flags); void paintTextLines(int xPos, int yPos); void paintCursor(); void paintBracketMark(); void placeCursor(int x, int y, int flags = 0); bool isTargetSelected(int x, int y); // void doDrag(); virtual void focusInEvent(QFocusEvent *); virtual void focusOutEvent(QFocusEvent *); virtual void keyPressEvent(QKeyEvent *e); virtual void mousePressEvent(QMouseEvent *); virtual void mouseDoubleClickEvent(QMouseEvent *); virtual void mouseReleaseEvent(QMouseEvent *); virtual void mouseMoveEvent(QMouseEvent *); virtual void wheelEvent( QWheelEvent *e ); virtual void paintEvent(QPaintEvent *); virtual void resizeEvent(QResizeEvent *); virtual void timerEvent(QTimerEvent *); KateView *myView; KateDocument *myDoc; QScrollBar *xScroll; QScrollBar *yScroll; KateIconBorder *leftBorder; int xPos; int yPos; int mouseX; int mouseY; int scrollX; int scrollY; int scrollTimer; PointStruc cursor; bool cursorOn; int cursorTimer; int cXPos; int cOldXPos; int startLine; int endLine; bool exposeCursor; int updateState; int numLines; LineRange *lineRanges; int newXPos; int newYPos; QPixmap *drawBuffer; BracketMark bm; }; /** The KateView text editor widget. It has many options, document/view architecture and syntax highlight. @author Jochen Wilhelmy */ class KateView : public Kate::View { Q_OBJECT friend class KateViewInternal; friend class KateDocument; friend class KateIconBorder; public: KateView(KateDocument *doc=0L, QWidget *parent = 0L, const char * name = 0); ~KateView(); virtual void setCursorPosition( int line, int col, bool mark = false ); virtual void getCursorPosition( int *line, int *col ); virtual bool isOverwriteMode() const; virtual void setOverwriteMode( bool b ); //status and config functions /** Returns the current line number, that is the line the cursor is on. For the first line it returns 0. Signal newCurPos() is emitted on cursor position changes. */ int currentLine(); /** Returns the current column number. It handles tab's correctly. For the first column it returns 0. */ int currentColumn(); /** Returns the number of the character, that the cursor is on (cursor x) */ int currentCharNum(); /** Sets the current cursor position */ void setCursorPositionInternal(int line, int col); /** Returns the config flags. See the cfXXX constants in the .h file. */ int config();// {return configFlags;} /** Sets the config flags */ void setConfig(int); int tabWidth(); void setTabWidth(int); void setEncoding (QString e); int undoSteps(); void setUndoSteps(int); // bool isOverwriteMode(); /** Returns true if the document is in read only mode. */ bool isReadOnly(); /** Returns true if the document has been modified. */ bool isModified(); /** Sets the read-only flag of the document */ void setReadOnly(bool); /** Sets the modification status of the document */ void setModified(bool m = true); /** Returns true if this editor is the only owner of its document */ bool isLastView(); /** Returns the document object */ KateDocument *doc(); /* Bit 0 : undo possible, Bit 1 : redo possible. Used to enable/disable undo/redo menu items and toolbar buttons */ int undoState(); /** Returns the type of the next undo group. */ int nextUndoType(); /** Returns the type of the next redo group. */ int nextRedoType(); /** Returns a list of all available undo types, in undo order. */ void undoTypeList(QValueList<int> &lst); /** Returns a list of all available redo types, in redo order. */ void redoTypeList(QValueList<int> &lst); /** Returns a short text description of the given undo type, which is obtained with nextUndoType(), nextRedoType(), undoTypeList(), and redoTypeList(), suitable for display in a menu entry. It is not translated; use i18n() before displaying this string. */ const char * undoTypeName(int undoType); QColor* getColors(); void applyColors(); public slots: void slotUpdate(); void slotFileStatusChanged(); void slotNewUndo(); void slotHighlightChanged(); public slots: /** Toggles Insert mode */ void toggleInsert(); /** Toggles "Vertical Selections" option */ void toggleVertical(); signals: /** The cursor position has changed. Get the values with currentLine() and currentColumn() */ void newCurPos(); /** Modified flag or config flags have changed */ void newStatus(); /** The undo/redo enable status has changed */ void newUndo(); /** The marked text state has changed. This can be used to enable/disable cut and copy */ void newMarkStatus(); // emitted when saving a remote URL with KIO::NetAccess. In that case we have to disable the UI. void enableUI( bool enable ); protected: virtual void keyPressEvent( QKeyEvent *ev ); int configFlags; /* * Check if the given URL already exists. Currently used by both save() and saveAs() * * Asks the user for permission and returns the message box result and defaults to * KMessageBox::Yes in case of doubt */ //text access public: /** Gets the number of text lines; */ int numLines(); /** Gets the complete document content as string */ QString text(); /** Gets the text line where the cursor is on */ QString currentTextLine(); /** Gets a text line */ QString textLine(int num); /** Gets the word where the cursor is on */ QString currentWord(); /** Gets the word at position x, y. Can be used to find the word under the mouse cursor */ QString word(int x, int y); /** Discard old text without warning and set new text */ void setText(const QString &); /** Insert text at the current cursor position. If length is a positive number, it restricts the number of inserted characters */ virtual void insertText(const QString &, bool mark = false); /** Queries if there is marked text */ bool hasMarkedText(); /** Gets the marked text as string */ QString markedText(); public: enum fileResult { OK, CANCEL, RETRY, ERROR }; /** Returns true if the current document can be discarded. If the document is modified, the user is asked if he wants to save it. On "cancel" the function returns false. */ bool canDiscard(); public slots: /** Flushes the document of the text widget. The user is given a chance to save the current document if the current document has been modified. */ void flush (); /** Saves the file if necessary under the current file name. If the current file name is Untitled, as it is after a call to newFile(), this routing will call saveAs(). */ fileResult save(); /** Allows the user to save the file under a new name. This starts the automatic highlight selection. */ fileResult saveAs(); /** Moves the marked text into the clipboard */ void cut() {doEditCommand(KateView::cmCut);} /** Copies the marked text into the clipboard */ void copy() {doEditCommand(KateView::cmCopy);} /** Inserts text from the clipboard at the actual cursor position */ void paste() {doEditCommand(KateView::cmPaste);} /** Undoes the last operation. The number of undo steps is configurable */ void undo() {doEditCommand(KateView::cmUndo);} /** Repeats an operation which has been undone before. */ void redo() {doEditCommand(KateView::cmRedo);} /** Undoes <count> operations. Called by slot undo(). */ void undoMultiple(int count); /** Repeats <count> operation which have been undone before. Called by slot redo(). */ void redoMultiple(int count); /** Displays the undo history dialog */ void undoHistory(); /** Moves the current line or the selection one position to the right */ void indent() {doEditCommand(KateView::cmIndent);}; /** Moves the current line or the selection one position to the left */ void unIndent() {doEditCommand(KateView::cmUnindent);}; /** Optimizes the selected indentation, replacing tabs and spaces as needed */ void cleanIndent() {doEditCommand(KateView::cmCleanIndent);}; /** Selects all text */ void selectAll() {doEditCommand(KateView::cmSelectAll);} /** Deselects all text */ void deselectAll() {doEditCommand(KateView::cmDeselectAll);} /** Inverts the current selection */ void invertSelection() {doEditCommand(KateView::cmInvertSelection);} /** comments out current line */ void comment() {doEditCommand(KateView::cmComment);}; /** removes comment signs in the current line */ void uncomment() {doEditCommand(KateView::cmUncomment);}; void keyReturn() {doEditCommand(KateView::cmReturn);}; void keyDelete() {doEditCommand(KateView::cmDelete);}; void backspace() {doEditCommand(KateView::cmBackspace);}; void killLine() {doEditCommand(KateView::cmKillLine);}; // cursor commands... void cursorLeft() {doCursorCommand(KateView::cmLeft);}; void shiftCursorLeft() {doCursorCommand(KateView::cmLeft | selectFlag);}; void cursorRight() {doCursorCommand(KateView::cmRight);} void shiftCursorRight() {doCursorCommand(KateView::cmRight | selectFlag);} void wordLeft() {doCursorCommand(KateView::cmWordLeft);}; void shiftWordLeft() {doCursorCommand(KateView::cmWordLeft | selectFlag);}; void wordRight() {doCursorCommand(KateView::cmWordRight);}; void shiftWordRight() {doCursorCommand(KateView::cmWordRight | selectFlag);}; void home() {doCursorCommand(KateView::cmHome);}; void shiftHome() {doCursorCommand(KateView::cmHome | selectFlag);}; void end() {doCursorCommand(KateView::cmEnd);}; void shiftEnd() {doCursorCommand(KateView::cmEnd | selectFlag);}; void up() {doCursorCommand(KateView::cmUp);}; void shiftUp() {doCursorCommand(KateView::cmUp | selectFlag);}; void down() {doCursorCommand(KateView::cmDown);}; void shiftDown() {doCursorCommand(KateView::cmDown | selectFlag);}; void scrollUp() {doCursorCommand(KateView::cmScrollUp);}; void scrollDown() {doCursorCommand(KateView::cmScrollDown);}; void topOfView() {doCursorCommand(KateView::cmTopOfView);}; void bottomOfView() {doCursorCommand(KateView::cmBottomOfView);}; void pageUp() {doCursorCommand(KateView::cmPageUp);}; void shiftPageUp() {doCursorCommand(KateView::cmPageUp | selectFlag);}; void pageDown() {doCursorCommand(KateView::cmPageDown);}; void shiftPageDown() {doCursorCommand(KateView::cmPageDown | selectFlag);}; void top() {doCursorCommand(KateView::cmTop);}; void shiftTop() {doCursorCommand(KateView::cmTop | selectFlag);}; void bottom() {doCursorCommand(KateView::cmBottom);}; void shiftBottom() {doCursorCommand(KateView::cmBottom | selectFlag);}; //search/replace functions public slots: /** Presents a search dialog to the user */ void find(); /** Presents a replace dialog to the user */ void replace(); /** Presents a "Goto Line" dialog to the user */ void gotoLine(); protected: void initSearch(SConfig &, int flags); void continueSearch(SConfig &); void findAgain(SConfig &); void replaceAgain(); void doReplaceAction(int result, bool found = false); void exposeFound(PointStruc &cursor, int slen, int flags, bool replace); void deleteReplacePrompt(); bool askReplaceEnd(); protected slots: void replaceSlot(); protected: int searchFlags; int replaces; SConfig s; QDialog *replacePrompt; //right mouse button popup menu & bookmark menu public: /** Install a Popup Menu. The Popup Menu will be activated on a right mouse button press event. */ void installPopup(QPopupMenu *rmb_Menu); protected: QPopupMenu *rmbMenu; signals: void bookAddChanged(bool enabled); void bookClearChanged(bool enabled); //config file / session management functions public: /** Reads config entries */ void readConfig(); /** Writes config entries i */ void writeConfig(); /** - Reads session config out of the KConfig object. This also includes + Reads session config out of the KateConfig object. This also includes the actual cursor position and the bookmarks. */ - void readSessionConfig(KConfig *); + void readSessionConfig(KateConfig *); /** - Writes session config into the KConfig object + Writes session config into the KateConfig object */ - void writeSessionConfig(KConfig *); + void writeSessionConfig(KateConfig *); public: void setDontChangeHlOnSave(); // syntax highlight public slots: /** Presents the setup dialog to the user */ void configDialog (); /** Gets the highlight number */ int getHl(); /** Sets the highlight number n */ void setHl(int n); /** Get the end of line mode (Unix, Macintosh or Dos) */ int getEol(); /** Set the end of line mode (Unix, Macintosh or Dos) */ void setEol(int); //internal protected: virtual void paintEvent(QPaintEvent *); virtual void resizeEvent(QResizeEvent *); void doCursorCommand(int cmdNum); void doEditCommand(int cmdNum); KateViewInternal *myViewInternal; KateDocument *myDoc; // some kwriteview stuff protected: void insLine(int line) { myViewInternal->insLine(line); }; void delLine(int line) { myViewInternal->delLine(line); }; void updateCursor() { myViewInternal->updateCursor(); }; void updateCursor(PointStruc &newCursor) { myViewInternal->updateCursor(newCursor); }; void updateCursor(PointStruc &newCursor, int flags) { myViewInternal->updateCursor(newCursor, flags); }; void clearDirtyCache(int height) { myViewInternal->clearDirtyCache(height); }; void tagLines(int start, int end, int x1, int x2) { myViewInternal->tagLines(start, end, x1, x2); }; void tagAll() { myViewInternal->tagAll(); }; void setPos(int x, int y) { myViewInternal->setPos(x, y); }; void center() { myViewInternal->center(); }; void updateView(int flags) { myViewInternal->updateView(flags); }; public: enum Config_flags { cfAutoIndent= 0x1, cfBackspaceIndents= 0x2, cfWordWrap= 0x4, cfReplaceTabs= 0x8, cfRemoveSpaces = 0x10, cfWrapCursor= 0x20, cfAutoBrackets= 0x40, cfPersistent= 0x80, cfKeepSelection= 0x100, cfVerticalSelect= 0x200, cfDelOnInput= 0x400, cfXorSelect= 0x800, cfOvr= 0x1000, cfMark= 0x2000, cfGroupUndo= 0x4000, cfKeepIndentProfile= 0x8000, cfKeepExtraSpaces= 0x10000, cfMouseAutoCopy= 0x20000, cfSingleSelection= 0x40000, cfTabIndents= 0x80000, cfPageUDMovesCursor= 0x100000, cfShowTabs= 0x200000, cfSpaceIndent= 0x400000, cfSmartHome = 0x800000}; enum Dialog_results { srYes=QDialog::Accepted, srNo=10, srAll, srCancel=QDialog::Rejected}; //search flags enum Search_flags { sfCaseSensitive=1, sfWholeWords=2, sfFromBeginning=4, sfBackward=8, sfSelected=16, sfPrompt=32, sfReplace=64, sfAgain=128, sfWrapped=256, sfFinished=512, sfRegularExpression=1024}; //update flags enum Update_flags { ufDocGeometry=1, ufUpdateOnScroll=2, ufPos=4}; //load flags enum Load_flags { lfInsert=1, lfNewFile=2, lfNoAutoHl=4}; //cursor movement commands enum Cursor_commands { cmLeft,cmRight,cmWordLeft,cmWordRight, cmHome,cmEnd,cmUp,cmDown, cmScrollUp,cmScrollDown,cmTopOfView,cmBottomOfView, cmPageUp,cmPageDown,cmCursorPageUp,cmCursorPageDown, cmTop,cmBottom}; //edit commands enum Edit_commands { cmReturn=1,cmDelete,cmBackspace,cmKillLine,cmUndo, cmRedo,cmCut,cmCopy,cmPaste,cmIndent,cmUnindent,cmCleanIndent, cmSelectAll,cmDeselectAll,cmInvertSelection,cmComment, cmUncomment}; //find commands enum Find_commands { cmFind=1,cmReplace,cmFindAgain,cmGotoLine}; public: void setActive (bool b); bool isActive (); private: bool active; bool myIconBorder; QList<Kate::Mark> list; public slots: virtual void setFocus (); void findAgain(bool back=false); void findAgain () { findAgain(false); }; void findPrev () { findAgain(true); }; protected: bool eventFilter(QObject* o, QEvent* e); signals: void gotFocus (KateView *); public slots: void slotEditCommand (); void setIconBorder (bool enable); void toggleIconBorder (); void gotoMark (Kate::Mark *mark); void toggleBookmark (); void clearBookmarks (); public: bool iconBorder() { return myIconBorder; } ; private slots: void bookmarkMenuAboutToShow(); void gotoBookmark (int n); public: Kate::Document *getDoc () { return (Kate::Document*) myDoc; }; public slots: int getHlCount (); QString getHlName (int); QString getHlSection (int); void slotIncFontSizes (); void slotDecFontSizes (); protected: uint myViewID; static uint uniqueID; }; #endif diff --git a/noncore/apps/tinykate/tinykate.cpp b/noncore/apps/tinykate/tinykate.cpp index 6164fa5..aecc1bd 100644 --- a/noncore/apps/tinykate/tinykate.cpp +++ b/noncore/apps/tinykate/tinykate.cpp @@ -1,258 +1,268 @@ /*************************************************************************** tinykate.cpp Tiny KATE mainwindow ------------------- begin : November 2002 copyright : (C) 2002 by Joseph Wenninger <jowenn@kde.org> ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation. * * ONLY VERSION 2 OF THE LICENSE IS APPLICABLE * * * ***************************************************************************/ #include <qwidget.h> #include <qaction.h> #include <qlayout.h> #include <qpe/qpetoolbar.h> #include <qpe/qpemenubar.h> #include <qpe/resource.h> #include <qpe/global.h> #include <qpe/qpeapplication.h> #include <opie/ofiledialog.h> #include "tinykate.h" #include "pics/file-new.xpm" #include "pics/file-open.xpm" #include "pics/file-save.xpm" #include "pics/edit-undo.xpm" #include "pics/edit-redo.xpm" #include <katedocument.h> #include <katehighlight.h> #include <kateview.h> +#include <kglobal.h> TinyKate::TinyKate( QWidget *parent, const char *name, WFlags f) : QMainWindow( parent, name, f ) { nextUnnamed=0; currentView=0; viewCount=0; setCaption(tr("TinyKATE")); + KGlobal::setAppName("TinyKATE"); setToolBarsMovable(FALSE); QPEToolBar *bar = new QPEToolBar( this ); bar->setHorizontalStretchable( TRUE ); QPEMenuBar *mb = new QPEMenuBar( bar ); mb->setMargin( 0 ); tabwidget=new OTabWidget(this); setCentralWidget(tabwidget); connect(tabwidget,SIGNAL(currentChanged( QWidget *)),this,SLOT(slotCurrentChanged(QWidget *))); //FILE ACTIONS QPopupMenu *popup = new QPopupMenu( this ); // Action for creating a new document QAction *a = new QAction( tr( "New" ), QPixmap((const char**)file_new_xpm ), QString::null, 0, this, 0 ); a->addTo( popup ); connect(a, SIGNAL(activated()), this, SLOT(slotNew())); // Action for opening an exisiting document a = new QAction( tr( "Open" ), QPixmap((const char**)file_open_xpm), QString::null, 0, this, 0 ); a->addTo(popup); connect(a, SIGNAL(activated()), this, SLOT(slotOpen())); // Action for saving document a = new QAction( tr( "Save" ), QPixmap((const char**)file_save_xpm), QString::null, 0, this, 0 ); a->addTo(popup); connect(a, SIGNAL(activated()), this, SLOT(slotSave())); // Action for saving document to a new name a = new QAction( tr( "Save As" ), QPixmap((const char**)file_save_xpm), QString::null, 0, this, 0 ); a->addTo(popup); connect(a, SIGNAL(activated()), this, SLOT(slotSaveAs())); // Action for closing the currently active document a = new QAction( tr( "Close" ), QPixmap(), QString::null, 0, this, 0 ); a->addTo(popup); connect(a, SIGNAL(activated()), this, SLOT(slotClose())); mb->insertItem(tr("File"),popup); //EDIT ACTIONS // Action for cutting text editCut = new QAction( tr( "Cut" ), Resource::loadPixmap( "cut" ), QString::null, 0, this, 0 ); editCut->addTo( bar ); // Action for Copying text editCopy = new QAction( tr( "Copy" ), Resource::loadPixmap( "copy" ), QString::null, 0, this, 0 ); editCopy->addTo( bar ); // Action for pasting text editPaste = new QAction( tr( "Paste" ), Resource::loadPixmap( "paste" ), QString::null, 0, this, 0 ); editPaste->addTo( bar ); // Action for finding / replacing text editFindReplace = new QAction( tr( "Find/Replace" ), Resource::loadPixmap("find"), QString::null, 0, this, 0 ); editFindReplace->addTo( bar ); // Action for undo editUndo = new QAction( tr( "Undo" ), QPixmap((const char**)edit_undo_xpm), QString::null, 0, this, 0 ); editUndo->addTo( bar ); // Action for redo editRedo = new QAction( tr( "Redo" ), QPixmap((const char**)edit_redo_xpm), QString::null, 0, this, 0 ); editRedo->addTo( bar ); //VIEW ACITONS popup = new QPopupMenu( this ); viewIncFontSizes = new QAction( tr( "Font +" ), QString::null, 0, this, 0 ); viewIncFontSizes->addTo( popup ); viewDecFontSizes = new QAction( tr( "Font -" ), QString::null, 0, this, 0 ); viewDecFontSizes->addTo( popup ); mb->insertItem(tr("View"),popup); popup = new QPopupMenu( this ); mb->insertItem(tr("Utils"),popup); //Highlight management hlmenu=new QPopupMenu(this); HlManager *hlm=HlManager::self(); for (int i=0;i<hlm->highlights();i++) { hlmenu->insertItem(hlm->hlName(i),i); } popup->insertItem(tr("Highlighting"),hlmenu); utilSettings = new QAction( tr( "Settings" ), QString::null, 0, this, 0 ); utilSettings->addTo( popup); if( qApp->argc() > 1) open(qApp->argv()[1]); else slotNew(); } +TinyKate::~TinyKate( ) +{ + qWarning("TinyKate destructor\n"); + if( KGlobal::config() != 0 ) { + qWarning("deleting KateConfig object..\n"); + delete KGlobal::config(); + } +} void TinyKate::slotOpen( ) { QString filename = OFileDialog::getOpenFileName( OFileSelector::EXTENDED_ALL, QPEApplication::documentDir()); if (!filename.isEmpty()) { open(filename); } } void TinyKate::open(const QString & filename) { KateDocument *kd= new KateDocument(false, false, this,0,this); KTextEditor::View *kv; QFileInfo fi(filename); QString filenamed = fi.fileName(); tabwidget->addTab(kv=kd->createView(tabwidget,"bLAH"),"tinykate/tinykate", filenamed ); qDebug(filename); kd->setDocName( filenamed); kd->open( filename ); viewCount++; } void TinyKate::slotCurrentChanged( QWidget * view) { if (currentView) { disconnect(editCopy,SIGNAL(activated()),currentView,SLOT(copy())); disconnect(editCut,SIGNAL(activated()),currentView,SLOT(cut())); disconnect(editPaste,SIGNAL(activated()),currentView,SLOT(paste())); disconnect(editUndo,SIGNAL(activated()),currentView,SLOT(undo())); disconnect(editRedo,SIGNAL(activated()),currentView,SLOT(redo())); disconnect(viewIncFontSizes,SIGNAL(activated()), currentView,SLOT(slotIncFontSizes())); disconnect(viewDecFontSizes,SIGNAL(activated()), currentView,SLOT(slotDecFontSizes())); disconnect(hlmenu,SIGNAL(activated(int)), currentView,SLOT(setHl(int))); disconnect(utilSettings,SIGNAL(activated()), currentView,SLOT(configDialog())); } currentView=(KTextEditor::View*)view; connect(editCopy,SIGNAL(activated()),currentView,SLOT(copy())); connect(editCut,SIGNAL(activated()),currentView,SLOT(cut())); connect(editPaste,SIGNAL(activated()),currentView,SLOT(paste())); connect(editUndo,SIGNAL(activated()),currentView,SLOT(undo())); connect(editRedo,SIGNAL(activated()),currentView,SLOT(redo())); connect(viewIncFontSizes,SIGNAL(activated()), currentView,SLOT(slotIncFontSizes())); connect(viewDecFontSizes,SIGNAL(activated()), currentView,SLOT(slotDecFontSizes())); connect(hlmenu,SIGNAL(activated(int)), currentView,SLOT(setHl(int))); connect(utilSettings,SIGNAL(activated()), currentView,SLOT(configDialog())); } void TinyKate::slotNew( ) { KateDocument *kd= new KateDocument(false, false, this,0,this); KTextEditor::View *kv; tabwidget->addTab(kv=kd->createView(tabwidget,"BLAH"), "tinykate/tinykate", tr("Unnamed %1").arg(nextUnnamed++)); viewCount++; } void TinyKate::slotClose( ) { if (currentView==0) return; KTextEditor::View *dv=currentView; currentView=0; tabwidget->removePage(dv); delete dv->document(); viewCount--; if (!viewCount) slotNew(); } void TinyKate::slotSave() { // feel free to make this how you want if (currentView==0) return; // KateView *kv = (KateView*) currentView; KateDocument *kd = (KateDocument*) currentView->document(); // qDebug("saving file "+kd->docName()); if( kd->docName().isEmpty()) slotSaveAs(); else kd->saveFile(); // kv->save(); // kd->saveFile(); } void TinyKate::slotSaveAs() { if (currentView==0) return; KateDocument *kd = (KateDocument*) currentView->document(); QString filename=OFileDialog::getSaveFileName(OFileSelector::EXTENDED_ALL, QPEApplication::documentDir()); if (!filename.isEmpty()) { qDebug("saving file "+filename); QFileInfo fi(filename); QString filenamed = fi.fileName(); kd->setDocFile( filename); kd->setDocName( filenamed); kd->saveFile(); // KTextEditor::View *dv = currentView; // tabwidget->changeTab( dv, filenamed); // need to change tab label here } } diff --git a/noncore/apps/tinykate/tinykate.h b/noncore/apps/tinykate/tinykate.h index 7b61bae..bb32f98 100644 --- a/noncore/apps/tinykate/tinykate.h +++ b/noncore/apps/tinykate/tinykate.h @@ -1,67 +1,68 @@ /*************************************************************************** tinykate.h Tiny KATE mainwindow ------------------- begin : November 2002 copyright : (C) 2002 by Joseph Wenninger <jowenn@kde.org> ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation. * * ONLY VERSION 2 OF THE LICENSE IS APPLICABLE * * * ***************************************************************************/ #ifndef __TINYKATE_H__ #define __TINYKATE_H__ #include <qmainwindow.h> #include <opie/otabwidget.h> #include <ktexteditor.h> class QAction; class QPopupMenu; class TinyKate : public QMainWindow { Q_OBJECT public: TinyKate( QWidget *parent=0, const char *name=0, WFlags f = 0); + ~TinyKate( ); public slots: - QString currentFileName; void slotNew(); protected slots: void slotOpen(); void slotClose(); void slotCurrentChanged(QWidget *); void slotSave(); void slotSaveAs(); protected: void open(const QString&); private: + QString currentFileName; OTabWidget *tabwidget; KTextEditor::View *currentView; QAction *editCopy; QAction *editCut; QAction *editPaste; QAction *editUndo; QAction *editRedo; QAction *editFindReplace; QAction *viewIncFontSizes; QAction *viewDecFontSizes; QAction *utilSettings; QPopupMenu *hlmenu; uint nextUnnamed; uint viewCount; }; #endif // __TINYKATE_H__ diff --git a/noncore/apps/tinykate/tinykate.pro b/noncore/apps/tinykate/tinykate.pro index 61b60a6..632bd49 100644 --- a/noncore/apps/tinykate/tinykate.pro +++ b/noncore/apps/tinykate/tinykate.pro @@ -1,20 +1,22 @@ TEMPLATE = app CONFIG = qt warn_on release DESTDIR = $(OPIEDIR)/bin HEADERS = tinykate.h SOURCES = tinykate.cpp main.cpp INTERFACES = -INCLUDEPATH += $(OPIEDIR)/include $(OPIEDIR)/noncore/apps/tinykate/libkate/microkde \ +INCLUDEPATH += $(OPIEDIR)/include \ + $(OPIEDIR)/noncore/apps/tinykate/libkate \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/microkde \ $(OPIEDIR)/noncore/apps/tinykate/libkate/document \ $(OPIEDIR)/noncore/apps/tinykate/libkate/view \ $(OPIEDIR)/noncore/apps/tinykate/libkate/interfaces \ $(OPIEDIR)/noncore/apps/tinykate/libkate/ktexteditor \ $(OPIEDIR)/noncore/apps/tinykate/libkate/qt3back DEPENDPATH += $(OPIEDIR)/include LIBS += -lqpe -ltinykate -lopie TARGET = tinykate include ( $(OPIEDIR)/include.pro ) |