summaryrefslogtreecommitdiff
path: root/noncore/apps/tinykate/libkate/document
authorjowenn <jowenn>2002-11-10 21:08:01 (UTC)
committer jowenn <jowenn>2002-11-10 21:08:01 (UTC)
commite97a6da57804aa14907dec327fbae71bff9b383e (patch) (side-by-side diff)
tree15f6ee292dba24bdda72f5c72f6d2224c3516763 /noncore/apps/tinykate/libkate/document
parent7c012ee8cd16d8befacc6f6750711443fac0fd5e (diff)
downloadopie-e97a6da57804aa14907dec327fbae71bff9b383e.zip
opie-e97a6da57804aa14907dec327fbae71bff9b383e.tar.gz
opie-e97a6da57804aa14907dec327fbae71bff9b383e.tar.bz2
import of tiny kate. (saving not possible yet)
Diffstat (limited to 'noncore/apps/tinykate/libkate/document') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/tinykate/libkate/document/katebuffer.cpp179
-rw-r--r--noncore/apps/tinykate/libkate/document/katebuffer.h143
-rw-r--r--noncore/apps/tinykate/libkate/document/katecmd.cpp58
-rw-r--r--noncore/apps/tinykate/libkate/document/katecmd.h57
-rw-r--r--noncore/apps/tinykate/libkate/document/katecmds.cpp278
-rw-r--r--noncore/apps/tinykate/libkate/document/katecmds.h94
-rw-r--r--noncore/apps/tinykate/libkate/document/katedialogs.cpp588
-rw-r--r--noncore/apps/tinykate/libkate/document/katedialogs.h160
-rw-r--r--noncore/apps/tinykate/libkate/document/katedocument.cpp3169
-rw-r--r--noncore/apps/tinykate/libkate/document/katedocument.h569
-rw-r--r--noncore/apps/tinykate/libkate/document/katedocumentIface.h32
-rw-r--r--noncore/apps/tinykate/libkate/document/katehighlight.cpp1459
-rw-r--r--noncore/apps/tinykate/libkate/document/katehighlight.h349
-rw-r--r--noncore/apps/tinykate/libkate/document/katesyntaxdocument.cpp306
-rw-r--r--noncore/apps/tinykate/libkate/document/katesyntaxdocument.h73
-rw-r--r--noncore/apps/tinykate/libkate/document/katetextline.cpp289
-rw-r--r--noncore/apps/tinykate/libkate/document/katetextline.h359
17 files changed, 8162 insertions, 0 deletions
diff --git a/noncore/apps/tinykate/libkate/document/katebuffer.cpp b/noncore/apps/tinykate/libkate/document/katebuffer.cpp
new file mode 100644
index 0000000..22a4917
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katebuffer.cpp
@@ -0,0 +1,179 @@
+/*
+ This file is part of KWrite
+ Copyright (c) 2000 Waldo Bastian <bastian@kde.org>
+ Copyright (c) 2002 Joseph Wenninger <jowenn@kde.org>
+
+ $Id$
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ 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 "katebuffer.h"
+
+// Includes for reading file
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <qtimer.h>
+#include <qtextcodec.h>
+
+//
+
+#include <assert.h>
+#include <kdebug.h>
+
+/**
+ * Create an empty buffer.
+ */
+KWBuffer::KWBuffer()
+{
+ clear();
+}
+
+void
+KWBuffer::clear()
+{
+ m_stringListIt=0;
+ m_stringListCurrent=0;
+ m_stringList.clear();
+ m_lineCount=1;
+ m_stringListIt = m_stringList.append(new TextLine());
+}
+
+/**
+ * Insert a file at line @p line in the buffer.
+ */
+void
+KWBuffer::insertFile(int line, const QString &file, QTextCodec *codec)
+{
+ if (line) {
+ qDebug("insert File only supports insertion at line 0 == file opening");
+ return;
+ }
+ clear();
+ QFile iofile(file);
+ iofile.open(IO_ReadOnly);
+ QTextStream stream(&iofile);
+ stream.setCodec(codec);
+ QString qsl;
+ int count=0;
+ for (count=0;((qsl=stream.readLine())!=QString::null); count++)
+ {
+ if (count==0)
+ {
+ (*m_stringListIt)->append(qsl.unicode(),qsl.length());
+ }
+ else
+ {
+ TextLine::Ptr tl=new TextLine();
+ tl ->append(qsl.unicode(),qsl.length());
+ m_stringListIt=m_stringList.append(tl);
+ }
+ }
+ if (count!=0)
+ {
+ m_stringListCurrent=count-1;
+ m_lineCount=count;
+ }
+}
+
+void
+KWBuffer::loadFilePart()
+{
+}
+
+
+void
+KWBuffer::insertData(int line, const QByteArray &data, QTextCodec *codec)
+{
+}
+
+void
+KWBuffer::slotLoadFile()
+{
+ loadFilePart();
+// emit linesChanged(m_totalLines);
+ emit linesChanged(20);
+}
+
+/**
+ * Return the total number of lines in the buffer.
+ */
+int
+KWBuffer::count()
+{
+ qDebug("m_stringList.count %d",m_stringList.count());
+ return m_lineCount;
+// return m_stringList.count();
+// return m_totalLines;
+}
+
+
+void KWBuffer::seek(int i)
+{
+ if (m_stringListCurrent == i)
+ return;
+ while(m_stringListCurrent < i)
+ {
+ ++m_stringListCurrent;
+ ++m_stringListIt;
+ }
+ while(m_stringListCurrent > i)
+ {
+ --m_stringListCurrent;
+ --m_stringListIt;
+ }
+}
+
+
+TextLine::Ptr
+KWBuffer::line(int i)
+{
+ if (i>=m_stringList.count()) return 0;
+ seek(i);
+ return *m_stringListIt;
+}
+
+void
+KWBuffer::insertLine(int i, TextLine::Ptr line)
+{
+ seek(i);
+ m_stringListIt = m_stringList.insert(m_stringListIt, line);
+ m_stringListCurrent = i;
+ m_lineCount++;
+}
+
+
+void
+KWBuffer::removeLine(int i)
+{
+ seek(i);
+ m_stringListIt = m_stringList.remove(m_stringListIt);
+ m_stringListCurrent = i;
+ m_lineCount--;
+}
+
+void
+KWBuffer::changeLine(int i)
+{
+}
+
diff --git a/noncore/apps/tinykate/libkate/document/katebuffer.h b/noncore/apps/tinykate/libkate/document/katebuffer.h
new file mode 100644
index 0000000..9088498
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katebuffer.h
@@ -0,0 +1,143 @@
+/*
+ This file is part of KWrite
+ Copyright (c) 2000 Waldo Bastian <bastian@kde.org>
+ Copyright (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 version 2 as published by the Free Software Foundation.
+
+ 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 _KWBUFFER_H_
+#define _KWBUFFER_H_
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qlist.h>
+#include <qobject.h>
+#include <qtimer.h>
+
+#include "katetextline.h"
+
+class QTextCodec;
+
+/**
+ * The KWBuffer class maintains a collections of lines.
+ * It allows to maintain state information in a lazy way.
+ * It handles swapping out of data using secondary storage.
+ *
+ * It is designed to handle large amounts of text-data efficiently
+ * with respect to CPU and memory usage.
+ *
+ * @author Waldo Bastian <bastian@kde.org>
+ */
+class KWBuffer : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Create an empty buffer.
+ */
+ KWBuffer();
+
+ /**
+ * Insert a file at line @p line in the buffer.
+ * Using @p codec to decode the file.
+ */
+ void insertFile(int line, const QString &file, QTextCodec *codec);
+
+ /**
+ * Insert a block of data at line @p line in the buffer.
+ * Using @p codec to decode the file.
+ */
+ void insertData(int line, const QByteArray &data, QTextCodec *codec);
+
+ /**
+ * Return the total number of lines in the buffer.
+ */
+ int count();
+
+ /**
+ * Return line @p i
+ */
+ TextLine::Ptr line(int i);
+
+ /**
+ * Insert @p line in front of line @p i
+ */
+ void insertLine(int i, TextLine::Ptr line);
+
+ /**
+ * Remove line @p i
+ */
+ void removeLine(int i);
+
+ /**
+ * Change line @p i
+ */
+ void changeLine(int i);
+
+ /**
+ * Clear the buffer.
+ */
+ void clear();
+
+signals:
+
+ void textChanged();
+ /**
+ * Emitted during loading.
+ */
+ void linesChanged(int lines);
+ void needHighlight(long,long);
+
+protected:
+ /**
+ * Make sure @p buf gets loaded.
+ */
+ void loadBlock(KWBufBlock *buf);
+
+ /**
+ * Make sure @p buf gets parsed.
+ */
+ void parseBlock(KWBufBlock *buf);
+
+ /**
+ * Mark @p buf dirty.
+ */
+ void dirtyBlock(KWBufBlock *buf);
+
+ /**
+ * Find the block containing line @p i
+ */
+ KWBufBlock *findBlock(int i);
+
+ /**
+ * Load a part of the file that is currently loading.
+ */
+ void loadFilePart();
+
+protected slots:
+ void slotLoadFile();
+
+protected:
+ TextLine::List m_stringList;
+ TextLine::List::Iterator m_stringListIt;
+ int m_stringListCurrent;
+ int m_lineCount;
+ void seek(int i);
+
+
+};
+
+#endif
diff --git a/noncore/apps/tinykate/libkate/document/katecmd.cpp b/noncore/apps/tinykate/libkate/document/katecmd.cpp
new file mode 100644
index 0000000..beebaa2
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katecmd.cpp
@@ -0,0 +1,58 @@
+/***************************************************************************
+ katecmd.cpp - description
+ -------------------
+ begin : Mon Feb 5 2001
+ copyright : (C) 2001 by Christoph 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. *
+ * *
+ ***************************************************************************/
+
+#include "katecmd.h"
+#include "katecmds.h"
+
+
+#include "katedocument.h"
+
+KateCmd::KateCmd (KateDocument *doc) : QObject (doc)
+{
+ myDoc = doc;
+
+ myParser.append (new KateCommands::InsertTime (myDoc));
+ myParser.append (new KateCommands::SedReplace (myDoc));
+ myParser.append (new KateCommands::Character (myDoc));
+}
+
+KateCmd::~KateCmd ()
+{
+}
+
+void KateCmd::execCmd (QString cmd, KateView *view)
+{
+ for (uint i=0; i<myParser.count(); i++)
+ {
+ if (myParser.at(i)->execCmd (cmd, view))
+ break;
+ }
+}
+
+KateCmdParser::KateCmdParser (KateDocument *doc)
+{
+ myDoc = doc;
+}
+
+KateCmdParser::~KateCmdParser()
+{
+}
+
+
diff --git a/noncore/apps/tinykate/libkate/document/katecmd.h b/noncore/apps/tinykate/libkate/document/katecmd.h
new file mode 100644
index 0000000..72158cc
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katecmd.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ katecmd.h - description
+ -------------------
+ begin : Mon Feb 5 2001
+ copyright : (C) 2001 by Christoph 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef _KATE_CMD_H
+#define _KATE_CMD_H
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qlist.h>
+#include <katedocument.h>
+
+class KateCmdParser
+{
+ public:
+ KateCmdParser (KateDocument *doc=0L);
+ virtual ~KateCmdParser ();
+
+ virtual bool execCmd (QString cmd=0L, KateView *view=0L)=0;
+
+ private:
+ KateDocument *myDoc;
+};
+
+class KateCmd : public QObject
+{
+ Q_OBJECT
+
+ public:
+ KateCmd (KateDocument *doc=0L);
+ ~KateCmd ();
+
+ void execCmd (QString cmd=0L, KateView *view=0L);
+
+ private:
+ KateDocument *myDoc;
+ QList<KateCmdParser> myParser;
+};
+
+#endif
+
diff --git a/noncore/apps/tinykate/libkate/document/katecmds.cpp b/noncore/apps/tinykate/libkate/document/katecmds.cpp
new file mode 100644
index 0000000..3647853
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katecmds.cpp
@@ -0,0 +1,278 @@
+/***************************************************************************
+ katecmds.cpp - description
+ -------------------
+ copyright : (C) 2001 by The Kate Team
+ (C) 2002 by Joseph Wenninger
+ email : kwrite-devel@kde.org
+ 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 "katecmds.h"
+#include <qregexp.h>
+#include <qregexp3.h>
+#include <qdatetime.h>
+#include "katedocument.h"
+#include <kdebug.h>
+
+namespace KateCommands
+{
+
+
+bool InsertTime::execCmd(QString cmd, KateView *view)
+{
+ if (cmd.left(5) == "time")
+ {
+ view->insertText(QTime::currentTime().toString());
+ return true;
+ }
+
+ return false;
+}
+
+static void replace(QString &s, const QString &needle, const QString &with)
+{
+ int pos=0;
+ while (1)
+ {
+ pos=s.find(needle, pos);
+ if (pos==-1) break;
+ s.replace(pos, needle.length(), with);
+ pos+=with.length();
+ }
+
+}
+
+// stolen from QString::replace
+static void replace(QString &s, QRegExp3 &rx, const QString &with)
+{
+ if (s.isEmpty()) return;
+ int index = 0;
+ int slen = with.length();
+ int len;
+ while (index < (int)s.length())
+ {
+ index = rx.search(s, index);
+ len = rx.matchedLength();
+ if ( index >= 0 )
+ {
+ s.replace(index, len, with);
+ index += slen;
+ if (!len)
+ break; // Avoid infinite loop on 0-length matches, e.g. [a-z]*
+ }
+ else
+ break;
+ }
+}
+
+
+
+static int backslashString(const QString &haystack, const QString &needle, int index)
+{
+ int len=haystack.length();
+ int searchlen=needle.length();
+ bool evenCount=true;
+ while (index<len)
+ {
+ if (haystack[index]=='\\')
+ {
+ evenCount=!evenCount;
+ }
+ else
+ { // isn't a slash
+ if (!evenCount)
+ {
+ if (haystack.mid(index, searchlen)==needle)
+ return index-1;
+ }
+ evenCount=true;
+ }
+ index++;
+
+ }
+
+ return -1;
+}
+
+
+// exchange "\t" for the actual tab character, for example
+static void exchangeAbbrevs(QString &str)
+{
+ // the format is (findreplace)*[nullzero]
+ char *magic="a\x07t\t";
+
+ while (*magic)
+ {
+ int index=0;
+ char replace=magic[1];
+ while ((index=backslashString(str, QChar(*magic), index))!=-1)
+ {
+ str.replace(index, 2, QChar(replace));
+ index++;
+ }
+ magic++;
+ magic++;
+ }
+}
+
+QString SedReplace::sedMagic(QString textLine, QString find, QString rep, bool noCase, bool repeat)
+{
+ QRegExp3 matcher(find, noCase);
+
+ int start=0;
+ while (start!=-1)
+ {
+ start=matcher.search(textLine, start);
+
+ if (start==-1) break;
+
+ int length=matcher.matchedLength();
+
+
+ // now set the backreferences in the replacement
+ QStringList backrefs=matcher.capturedTexts();
+ int refnum=1;
+
+ QStringList::Iterator i = backrefs.begin();
+ ++i;
+
+ for (; i!=backrefs.end(); ++i)
+ {
+ // I need to match "\\" or "", but not "\"
+ QString number=QString::number(refnum);
+
+ int index=0;
+ while (index!=-1)
+ {
+ index=backslashString(rep, number, index);
+ if (index>=0)
+ {
+ rep.replace(index, 2, *i);
+ index+=(*i).length();
+ }
+ }
+
+ refnum++;
+ }
+
+ textLine.replace(start, length, rep);
+ if (!repeat) break;
+ start+=rep.length();
+ }
+
+ replace(textLine, "\\\\", "\\");
+ replace(textLine, "\\/", "/");
+
+ return textLine;
+}
+
+
+static void setLineText(KateView *view, int line, const QString &text)
+{
+// view->doc()->removeLine(line);
+// view->doc()->insertLine(text, line);
+ view->doc()->replaceLine(text,line);
+}
+
+bool SedReplace::execCmd(QString cmd, KateView *view)
+{
+ kdDebug(13010)<<"SedReplace::execCmd()"<<endl;
+ if (QRegExp("[$%]?s/.+/.*/[ig]*").find(cmd, 0)==-1)
+ return false;
+
+ bool fullFile=cmd[0]=='%';
+ bool noCase=cmd[cmd.length()-1]=='i' || cmd[cmd.length()-2]=='i';
+ bool repeat=cmd[cmd.length()-1]=='g' || cmd[cmd.length()-2]=='g';
+ bool onlySelect=cmd[0]=='$';
+
+ QRegExp3 splitter("^[$%]?s/((?:[^\\\\/]|\\\\[\\\\/\\$0-9tadDsSwW])*)/((?:[^\\\\/]|\\\\[\\\\/\\$0-9tadDsSwW])*)/[ig]*$");
+ if (splitter.search(cmd)<0) return false;
+
+ QString find=splitter.cap(1);
+ kdDebug(13010)<< "SedReplace: find=" << find.latin1() <<endl;
+
+ QString replace=splitter.cap(2);
+ exchangeAbbrevs(replace);
+ kdDebug(13010)<< "SedReplace: replace=" << replace.latin1() <<endl;
+
+
+ if (fullFile)
+ {
+ int numLines=view->doc()->numLines();
+ for (int line=0; line < numLines; line++)
+ {
+ QString text=view->textLine(line);
+ text=sedMagic(text, find, replace, noCase, repeat);
+ setLineText(view, line, text);
+ }
+ }
+ else if (onlySelect)
+ {
+ // Not implemented
+ }
+ else
+ { // just this line
+ QString textLine=view->currentTextLine();
+ int line=view->currentLine();
+ textLine=sedMagic(textLine, find, replace, noCase, repeat);
+ setLineText(view, line, textLine);
+ }
+ return true;
+}
+
+bool Character::execCmd(QString cmd, KateView *view)
+{
+ // hex, octal, base 9+1
+ QRegExp3 num("^char: *(0?x[0-9A-Fa-f]{1,4}|0[0-7]{1,6}|[0-9]{1,3})$");
+ if (num.search(cmd)==-1) return false;
+
+ cmd=num.cap(1);
+
+ // identify the base
+
+ unsigned short int number=0;
+ int base=10;
+ if (cmd[0]=='x' || cmd.left(2)=="0x")
+ {
+ cmd.replace(QRegExp("^0?x"), "");
+ base=16;
+ }
+ else if (cmd[0]=='0')
+ base=8;
+ bool ok;
+ number=cmd.toUShort(&ok, base);
+ if (!ok || number==0) return false;
+ if (number<=255)
+ {
+ char buf[2];
+ buf[0]=(char)number;
+ buf[1]=0;
+ view->insertText(QString(buf));
+ }
+ else
+ { // do the unicode thing
+ QChar c(number);
+ view->insertText(QString(&c, 1));
+ }
+
+ return true;
+}
+
+bool Fifo::execCmd(QString cmd, KateView *view)
+{
+
+}
+
+}
+
+// vim: noet
+
diff --git a/noncore/apps/tinykate/libkate/document/katecmds.h b/noncore/apps/tinykate/libkate/document/katecmds.h
new file mode 100644
index 0000000..bbd5937
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katecmds.h
@@ -0,0 +1,94 @@
+/***************************************************************************
+ katecmds.h - description
+ -------------------
+ copyright : (C) 2001 by The Kate Team
+ (C) 2002 by Joseph Wenninger
+ email : kwrite-devel@kde.org
+ 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. *
+ * *
+ ***************************************************************************/
+#ifndef _KATECMDS_H
+#define _KATECMDS_H
+
+#include "katecmd.h"
+
+
+/**
+ * this namespace will be maintained by Charles Samuels <charles@kde.org>
+ * so we're going to be using this indentation style here.
+ *
+ * Respect my style, and I'll respect your's!
+ **/
+namespace KateCommands
+{
+
+/**
+ * This is by Christoph Cullmann
+ **/
+class InsertTime : public KateCmdParser
+{
+public:
+ InsertTime(KateDocument *doc=0) : KateCmdParser(doc) { }
+
+ bool execCmd(QString cmd=0, KateView *view=0);
+};
+
+/**
+ * -- Charles Samuels <charles@kde.org>
+ * Support vim/sed find and replace
+ * s/search/replace/ find search, replace with replace on this line
+ * %s/search/replace/ do the same to the whole file
+ * s/search/replace/i do the S. and R., but case insensitively
+ * $s/search/replace/ do the search are replacement to the selection only
+ *
+ * $s/// is currently unsupported
+ **/
+class SedReplace : public KateCmdParser
+{
+public:
+ SedReplace(KateDocument *doc=0) : KateCmdParser(doc) { }
+
+ bool execCmd(QString cmd=0, KateView *view=0);
+private:
+ static QString sedMagic(QString textLine, QString find, QString replace, bool noCase, bool repeat);
+};
+
+/**
+ * insert a unicode or ascii character
+ * base 9+1: 1234
+ * hex: 0x1234 or x1234
+ * octal: 01231
+ *
+ * prefixed with "char:"
+ **/
+class Character : public KateCmdParser
+{
+public:
+ Character(KateDocument *doc=0) : KateCmdParser(doc) { }
+
+ bool execCmd(QString cmd=0, KateView *view=0);
+};
+
+class Fifo : public KateCmdParser
+{
+public:
+ Fifo(KateDocument *doc=0) : KateCmdParser(doc) { }
+
+ bool execCmd(QString cmd=0, KateView *view=0);
+};
+
+}
+
+// vim: noet
+
+#endif
+
diff --git a/noncore/apps/tinykate/libkate/document/katedialogs.cpp b/noncore/apps/tinykate/libkate/document/katedialogs.cpp
new file mode 100644
index 0000000..2f0ed7b
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katedialogs.cpp
@@ -0,0 +1,588 @@
+/***************************************************************************
+ katedialogs.cpp - description
+ -------------------
+ copyright : (C) 2001 by The Kate Team
+ (C) 2002 by Joseph Wenninger
+ email : kwrite-devel@kde.org
+ 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 "katedialogs.h"
+#include <klocale.h>
+#include <kdebug.h>
+#include <qgroupbox.h>
+#include <qvgroupbox.h>
+#include <qhgroupbox.h>
+#include <qhbox.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qwidgetstack.h>
+#include <qlabel.h>
+#include <qlistview.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+//FIXME #include <kcharsets.h>
+#include <kglobal.h>
+#include <qmap.h>
+#include <kmessagebox.h>
+#include <kstddirs.h>
+
+
+/*******************************************************************************************************************
+* Context Editor *
+*******************************************************************************************************************/
+
+StyleChanger::StyleChanger( QWidget *parent )
+ : QWidget(parent)
+{
+ QLabel *label;
+
+ QGridLayout *glay = new QGridLayout( this, 4, 3, 0, KDialog::spacingHint() );
+ CHECK_PTR(glay);
+ glay->addColSpacing( 1, KDialog::spacingHint() ); // Looks better
+ glay->setColStretch( 2, 10 );
+
+ col = new KColorButton(this);
+ CHECK_PTR(col);
+ connect(col,SIGNAL(changed(const QColor &)),this,SLOT(changed()));
+ label = new QLabel(col,i18n("Normal:"),this);
+ CHECK_PTR(label);
+ glay->addWidget(label,0,0);
+ glay->addWidget(col,1,0);
+
+ selCol = new KColorButton(this);
+ CHECK_PTR(selCol);
+ connect(selCol,SIGNAL(changed(const QColor &)),this,SLOT(changed()));
+ label = new QLabel(selCol,i18n("Selected:"),this);
+ CHECK_PTR(label);
+ glay->addWidget(label,2,0);
+ glay->addWidget(selCol,3,0);
+
+ bold = new QCheckBox(i18n("Bold"),this);
+ CHECK_PTR(bold);
+ connect(bold,SIGNAL(clicked()),SLOT(changed()));
+ glay->addWidget(bold,1,2);
+
+ italic = new QCheckBox(i18n("Italic"),this);
+ CHECK_PTR(italic);
+ connect(italic,SIGNAL(clicked()),SLOT(changed()));
+ glay->addWidget(italic,2,2);
+}
+
+void StyleChanger::setRef(ItemStyle *s) {
+
+ style = s;
+ col->setColor(style->col);
+ selCol->setColor(style->selCol);
+ bold->setChecked(style->bold);
+ italic->setChecked(style->italic);
+
+}
+
+void StyleChanger::setEnabled(bool enable) {
+
+ col->setEnabled(enable);
+ selCol->setEnabled(enable);
+ bold->setEnabled(enable);
+ italic->setEnabled(enable);
+}
+
+void StyleChanger::changed() {
+
+ if (style) {
+ style->col = col->color();
+ style->selCol = selCol->color();
+ style->bold = bold->isChecked();
+ style->italic = italic->isChecked();
+ }
+}
+
+HighlightDialog::HighlightDialog( HlManager *hlManager, ItemStyleList *styleList,
+ HlDataList *highlightDataList,
+ int hlNumber, QWidget *parent,
+ const char *name, bool modal )
+ :KDialogBase(parent,name,modal,i18n("Highlight Settings"), Ok|Cancel, Ok)
+{
+// QVBox *page = makeVBoxMainWidget();
+ QFrame *page=addPage("FIXME");
+ (new QVBoxLayout(page))->setAutoAdd(true);
+ content=new HighlightDialogPage(hlManager,styleList,highlightDataList,hlNumber,page);
+}
+
+void HighlightDialog::done(int r)
+{
+ kdDebug(13010)<<"HighlightDialod done"<<endl;
+ content->saveData();
+ KDialogBase::done(r);
+}
+
+HighlightDialogPage::HighlightDialogPage(HlManager *hlManager, ItemStyleList *styleList,
+ HlDataList* highlightDataList,
+ int hlNumber,QWidget *parent, const char *name)
+ :QTabWidget(parent,name),defaultItemStyleList(styleList),hlData(0L)
+
+{
+
+ // defaults =========================================================
+
+ QFrame *page1 = new QFrame(this);
+ addTab(page1,i18n("&Defaults"));
+ QGridLayout *grid = new QGridLayout(page1, 1, 1);
+
+ QVGroupBox *dvbox1 = new QVGroupBox( i18n("Default Item Styles"), page1 );
+ /*QLabel *label = */new QLabel( i18n("Item:"), dvbox1 );
+ QComboBox *styleCombo = new QComboBox( false, dvbox1 );
+ defaultStyleChanger = new StyleChanger( dvbox1 );
+ for( int i = 0; i < hlManager->defaultStyles(); i++ ) {
+ styleCombo->insertItem(hlManager->defaultStyleName(i));
+ }
+ connect(styleCombo, SIGNAL(activated(int)), this, SLOT(defaultChanged(int)));
+ grid->addWidget(dvbox1, 0,0);
+
+ defaultChanged(0);
+
+ // highlight modes =====================================================
+
+ QFrame *page2 = new QFrame(this);
+ addTab(page2,i18n("&Highlight Modes"));
+ //grid = new QGridLayout(page2,2,2);
+ QVBoxLayout *bl=new QVBoxLayout(page2);
+ bl->setAutoAdd(true);
+ QHGroupBox *hbox1 = new QHGroupBox( i18n("Config Select"), page2 );
+ hbox1->layout()->setMargin(5);
+ QVBox *vbox1=new QVBox(hbox1);
+// grid->addMultiCellWidget(vbox1,0,0,0,1);
+ QVGroupBox *vbox2 = new QVGroupBox( i18n("Item Style"), page2 );
+// grid->addWidget(vbox2,1,0);
+ QVGroupBox *vbox3 = new QVGroupBox( i18n("Highlight Auto Select"), hbox1 );
+ //grid->addWidget(vbox3,1,1);
+
+ QLabel *label = new QLabel( i18n("Highlight:"), vbox1 );
+ hlCombo = new QComboBox( false, vbox1 );
+ QHBox *modHl = new QHBox(vbox1);
+// connect(new QPushButton(i18n("New"),modHl),SIGNAL(clicked()),this,SLOT(hlNew()));
+// connect(new QPushButton(i18n("Edit"),modHl),SIGNAL(clicked()),this,SLOT(hlEdit()));
+ connect( hlCombo, SIGNAL(activated(int)),
+ this, SLOT(hlChanged(int)) );
+ for( int i = 0; i < hlManager->highlights(); i++) {
+ hlCombo->insertItem(hlManager->hlName(i));
+ }
+ hlCombo->setCurrentItem(hlNumber);
+
+
+ label = new QLabel( i18n("Item:"), vbox2 );
+ itemCombo = new QComboBox( false, vbox2 );
+ connect( itemCombo, SIGNAL(activated(int)), this, SLOT(itemChanged(int)) );
+
+ label = new QLabel( i18n("File Extensions:"), vbox3 );
+ wildcards = new QLineEdit( vbox3 );
+ label = new QLabel( i18n("Mime Types:"), vbox3 );
+ mimetypes = new QLineEdit( vbox3 );
+
+
+ styleDefault = new QCheckBox(i18n("Default"), vbox2 );
+ connect(styleDefault,SIGNAL(clicked()),SLOT(changed()));
+ styleChanger = new StyleChanger( vbox2 );
+
+ hlDataList = highlightDataList;
+ hlChanged(hlNumber);
+}
+
+
+void HighlightDialogPage::defaultChanged(int z)
+{
+ defaultStyleChanger->setRef(defaultItemStyleList->at(z));
+}
+
+
+void HighlightDialogPage::hlChanged(int z)
+{
+ writeback();
+
+ hlData = hlDataList->at(z);
+
+ wildcards->setText(hlData->wildcards);
+ mimetypes->setText(hlData->mimetypes);
+
+ itemCombo->clear();
+ for (ItemData *itemData = hlData->itemDataList.first(); itemData != 0L;
+ itemData = hlData->itemDataList.next()) {
+ kdDebug(13010) << itemData->name << endl;
+ itemCombo->insertItem(i18n(itemData->name.latin1()));
+ }
+
+ itemChanged(0);
+}
+
+void HighlightDialogPage::itemChanged(int z)
+{
+ itemData = hlData->itemDataList.at(z);
+
+ styleDefault->setChecked(itemData->defStyle);
+ styleChanger->setRef(itemData);
+}
+
+void HighlightDialogPage::changed()
+{
+ itemData->defStyle = styleDefault->isChecked();
+}
+
+void HighlightDialogPage::writeback() {
+ if (hlData) {
+ hlData->wildcards = wildcards->text();
+ hlData->mimetypes = mimetypes->text();
+ }
+}
+
+void HighlightDialogPage::saveData() {
+ kdDebug(13010)<<"HighlightDialogPage::saveData()"<<endl;
+ writeback();
+}
+
+
+void HighlightDialogPage::hlEdit() {
+ HlEditDialog diag(0,0,"hlEdit", true,hlData);
+ diag.show();
+}
+
+void HighlightDialogPage::hlNew() {
+ HlEditDialog diag(0,0,"hlEdit",true,0);
+ diag.show();
+}
+
+
+HlEditDialog::HlEditDialog(HlManager *,QWidget *parent, const char *name, bool modal,HlData *data)
+ :KDialogBase(KDialogBase::Swallow, i18n("Highlight Conditions"), Ok|Cancel, Ok, parent, name, modal)
+{
+ currentItem=0;
+ transTableCnt=0;
+ QHBox *wid=new QHBox(this);
+ QVBox *lbox=new QVBox(wid);
+ contextList=new KListView(lbox);
+ contextList->setRootIsDecorated(true);
+ contextList->addColumn(i18n("Syntax structure"));
+ contextList->setSorting(-1);
+ QHBox *bbox=new QHBox(lbox);
+ QPushButton *addContext=new QPushButton(i18n("New Context"),bbox);
+ QPushButton *addItem=new QPushButton(i18n("New Item"),bbox);
+ QVGroupBox *opt = new QVGroupBox( i18n("Options"), wid);
+ stack=new QWidgetStack(opt);
+ initContextOptions(contextOptions=new QVBox(stack));
+ stack->addWidget(contextOptions,HlEContext);
+ initItemOptions(itemOptions=new QVBox(stack));
+ stack->addWidget(itemOptions,HlEItem);
+ stack->raiseWidget(HlEContext);
+ setMainWidget(wid);
+ if (data!=0) loadFromDocument(data);
+ else newDocument();
+ connect(contextList,SIGNAL(currentChanged( QListViewItem*)),this,SLOT(currentSelectionChanged ( QListViewItem * )));
+ connect(addContext,SIGNAL(clicked()),this,SLOT(contextAddNew()));
+ connect(addItem,SIGNAL(clicked()),this,SLOT(ItemAddNew()));
+ }
+
+void HlEditDialog::newDocument()
+{
+ KStandardDirs *dirs = KGlobal::dirs();
+ QStringList list=dirs->findAllResources("data","kate/syntax/syntax.template",false,true);
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ HlData data("","",*it);
+ loadFromDocument(&data);
+ return;
+ }
+ KMessageBox::error(this,i18n("Can't find template file"));
+}
+
+
+void HlEditDialog::initContextOptions(QVBox *co)
+{
+ if( co!=0)
+ {
+ QHBox *tmp = new QHBox(co);
+ (void) new QLabel(i18n("Description:"),tmp);
+ ContextDescr=new QLineEdit(tmp);
+ tmp= new QHBox(co);
+ (void) new QLabel(i18n("Attribute:"),tmp);
+ ContextAttribute=new QComboBox(tmp);
+ tmp= new QHBox(co);
+ (void) new QLabel(i18n("LineEnd:"),tmp);
+ ContextLineEnd = new QComboBox(tmp);
+ connect(ContextDescr,SIGNAL(textChanged(const QString&)),this,SLOT(contextDescrChanged(const QString&)));
+ connect(ContextLineEnd,SIGNAL(activated(int)),this,SLOT(contextLineEndChanged(int)));
+ connect(ContextAttribute,SIGNAL(activated(int)),this,SLOT(contextAttributeChanged(int)));
+ }
+ else
+ kdDebug(13010)<<"initContextOptions: Widget is 0"<<endl;
+}
+
+
+void HlEditDialog::insertTranslationList(QString tag, QString trans,int length)
+ {
+ ItemInfo data(trans,length);
+ id2tag.insert(transTableCnt,tag);
+ id2info.insert(transTableCnt,data);
+ tag2id.insert(tag,transTableCnt);
+ transTableCnt++;
+ }
+
+
+void HlEditDialog::initItemOptions(QVBox *co)
+{
+ if (co!=0)
+ {
+ QHBox *tmp = new QHBox(co);
+ (void) new QLabel(i18n("Type:"),tmp);
+ ItemType = new QComboBox(tmp);
+ tmp= new QHBox(co);
+ (void) new QLabel(i18n("Parameter:"),tmp);
+ ItemParameter= new QLineEdit(tmp);
+ tmp= new QHBox(co);
+ (void) new QLabel(i18n("Attribute:"),tmp);
+ ItemAttribute= new QComboBox(tmp);
+ (void) new QLabel(i18n("Context switch:"),tmp);
+ ItemContext = new QComboBox(tmp);
+ co->setSpacing(15);
+ QPushButton *delItem=new QPushButton(i18n("Delete this item"),co);
+
+ /* init translation lists */
+ insertTranslationList("CharDetect","CharDetect",1);
+ insertTranslationList("2CharDetect","2CharDetect",2);
+ insertTranslationList("RangeDetect","RangeDetect",2);
+ insertTranslationList("StringDetect","StringDetect",-1);
+ insertTranslationList("AnyChar","AnyChar",-1);
+ insertTranslationList("RegExpr","RegExpr",-1);
+ insertTranslationList("Int","Int",0);
+ insertTranslationList("Float","Float",0);
+ insertTranslationList("keyword","keyword",0);
+ insertTranslationList("dataType","dataType",0);
+ ItemType->clear();
+ for (int i=0; i<transTableCnt; i++) ItemType->insertItem(id2info[i].trans_i18n);
+ connect(ItemType,SIGNAL(activated(int)),this,SLOT(ItemTypeChanged(int)));
+ connect(ItemParameter,SIGNAL(textChanged(const QString&)),this,SLOT(ItemParameterChanged(const QString&)));
+ connect(ItemAttribute,SIGNAL(activated(int)),this,SLOT(ItemAttributeChanged(int)));
+ connect(ItemContext,SIGNAL(activated(int)),this,SLOT(ItemContextChanged(int)));
+ }
+ else
+ kdDebug(13010)<<"initItemOptions: Widget is 0"<<endl;
+}
+
+void HlEditDialog::loadFromDocument(HlData *hl)
+{
+ struct syntaxContextData *data;
+ QListViewItem *last=0,*lastsub=0;
+
+ HlManager::self()->syntax->setIdentifier(hl->identifier);
+ data=HlManager::self()->syntax->getGroupInfo("highlighting","context");
+ int i=0;
+ if (data)
+ {
+ while (HlManager::self()->syntax->nextGroup(data)) //<context tags>
+ {
+ kdDebug(13010)<< "Adding context to list"<<endl;
+ last= new QListViewItem(contextList,last,
+ HlManager::self()->syntax->groupData(data,QString("name")),
+ QString("%1").arg(i),
+ HlManager::self()->syntax->groupData(data,QString("attribute")),
+ HlManager::self()->syntax->groupData(data,QString("lineEndContext")));
+ i++;
+ lastsub=0;
+ while (HlManager::self()->syntax->nextItem(data))
+ {
+ kdDebug(13010)<< "Adding item to list"<<endl;
+ lastsub=addContextItem(last,lastsub,data);
+ }
+
+
+ }
+ if (data) HlManager::self()->syntax->freeGroupInfo(data);
+ }
+ ContextAttribute->clear();
+ ItemAttribute->clear();
+ data=HlManager::self()->syntax->getGroupInfo("highlighting","itemData");
+ while (HlManager::self()->syntax->nextGroup(data))
+ {
+ ContextAttribute->insertItem(HlManager::self()->syntax->groupData(data,QString("name")));
+ ItemAttribute->insertItem(HlManager::self()->syntax->groupData(data,QString("name")));
+ }
+ if (data) HlManager::self()->syntax->freeGroupInfo(data);
+}
+
+QListViewItem *HlEditDialog::addContextItem(QListViewItem *_parent,QListViewItem *prev,struct syntaxContextData *data)
+ {
+
+ kdDebug(13010)<<HlManager::self()->syntax->groupItemData(data,QString("name")) << endl;
+
+ QString dataname=HlManager::self()->syntax->groupItemData(data,QString(""));
+ QString attr=(HlManager::self()->syntax->groupItemData(data,QString("attribute")));
+ QString context=(HlManager::self()->syntax->groupItemData(data,QString("context")));
+ char chr;
+ if (! HlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty())
+ chr= (HlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0];
+ else
+ chr=0;
+ QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String"));
+ char chr1;
+ if (! HlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty())
+ chr1= (HlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0];
+ else
+ chr1=0;
+ bool insensitive=(HlManager::self()->syntax->groupItemData(data,QString("insensitive"))==QString("TRUE"));
+ QString param("");
+ if ((dataname=="keyword") || (dataname=="dataType")) param=dataname;
+ else if (dataname=="CharDetect") param=chr;
+ else if ((dataname=="2CharDetect") || (dataname=="RangeDetect")) param=QString("%1%2").arg(chr).arg(chr1);
+ else if ((dataname=="StringDetect") || (dataname=="AnyChar") || (dataname=="RegExpr")) param=stringdata;
+ else kdDebug(13010)<<"***********************************"<<endl<<"Unknown entry for Context:"<<dataname<<endl;
+ kdDebug(13010)<<dataname << endl;
+ return new QListViewItem(_parent,prev,i18n(dataname.latin1())+" "+param,dataname,param,attr,context);
+ }
+
+
+void HlEditDialog::currentSelectionChanged ( QListViewItem *it)
+ {
+ kdDebug(13010)<<"Update data view"<<endl<<"Depth:"<<it->depth()<<endl;
+ currentItem=it;
+ if (it->depth()==0) showContext();
+ else showItem();
+ }
+
+
+/****************************************************************************/
+/* CONTEXTS */
+/****************************************************************************/
+
+
+void HlEditDialog::showContext()
+ {
+ stack->raiseWidget(HlEContext);
+ ContextDescr->setText(currentItem->text(0));
+ ContextAttribute->setCurrentItem(currentItem->text(2).toInt());
+ ContextLineEnd->clear();
+ for (QListViewItem *it=contextList->firstChild();it;it=it->nextSibling())
+ ContextLineEnd->insertItem(it->text(0));
+ ContextLineEnd->setCurrentItem(currentItem->text(3).toInt());
+// ContextAttribute->setText(currentItem->text(1));
+// ContextLineEnd->setText(currentItem->text(2));
+ }
+
+void HlEditDialog::contextDescrChanged(const QString& name)
+ {
+ if (currentItem)
+ {
+ currentItem->setText(0,name);
+ ContextLineEnd->changeItem(name,currentItem->text(3).toInt());
+ }
+ }
+
+void HlEditDialog::contextAttributeChanged(int id)
+{
+ if (currentItem)
+ {
+ currentItem->setText(2,QString("%1").arg(id));
+ }
+}
+
+void HlEditDialog::contextLineEndChanged(int id)
+{
+ kdDebug(13010)<<"contextLineEndChanged"<<endl;
+ if (currentItem)
+ {
+ currentItem->setText(3,QString("%1").arg(id));
+ }
+}
+
+void HlEditDialog::contextAddNew()
+{
+ QListViewItem *it=contextList->firstChild();
+ for (;it->nextSibling()!=0;it=it->nextSibling());
+ it=new QListViewItem(contextList,it,i18n("New Context"),QString("%1").arg(it->text(1).toInt()),"0","0");
+ contextList->setSelected(it,true);
+}
+
+/****************************************************************************/
+/* ITEMS */
+/****************************************************************************/
+
+void HlEditDialog::showItem()
+ {
+ stack->raiseWidget(HlEItem);
+ ItemContext->clear();
+ for (QListViewItem *it=contextList->firstChild();it;it=it->nextSibling())
+ ItemContext->insertItem(it->text(0));
+ ItemContext->setCurrentItem(currentItem->text(4).toInt());
+ ItemAttribute->setCurrentItem(currentItem->text(3).toInt());
+ QMap<QString,int>::Iterator iter=tag2id.find(currentItem->text(1));
+ if (iter==tag2id.end())
+ kdDebug(13010)<<"Oops, unknown itemtype in showItem: "<<currentItem->text(1)<<endl;
+ else
+ {
+ ItemType->setCurrentItem(*iter);
+ if (id2info[*iter].length==0) ItemParameter->hide();
+ else
+ {
+ ItemParameter->setMaxLength(id2info[*iter].length);
+ ItemParameter->show();
+ ItemParameter->setText(currentItem->text(2));
+ }
+ }
+
+ }
+
+void HlEditDialog::ItemTypeChanged(int id)
+{
+ if (currentItem)
+ {
+ currentItem->setText(1,id2tag[id]);
+ ItemParameter->setMaxLength(id2info[id].length);
+ ItemParameterChanged(ItemParameter->text());
+ }
+}
+
+void HlEditDialog::ItemParameterChanged(const QString& name)
+{
+ if (currentItem)
+ {
+ currentItem->setText(2,name);
+ currentItem->setText(0,id2info[ItemType->currentItem()].trans_i18n+" "+currentItem->text(2));
+ }
+}
+
+void HlEditDialog::ItemAttributeChanged(int attr)
+{
+ if (currentItem)
+ {
+ currentItem->setText(3,QString("%1").arg(attr));
+ }
+}
+
+void HlEditDialog::ItemContextChanged(int cont)
+{
+ if (currentItem)
+ {
+ currentItem->setText(4,QString("%1").arg(cont));
+ }
+}
+
+void HlEditDialog::ItemAddNew()
+{
+ QListViewItem *it;
+ if (currentItem)
+ {
+ if (currentItem->depth()==0) it=currentItem->firstChild();
+ else
+ it=currentItem;
+ if (it) for (;it->nextSibling();it=it->nextSibling());
+ (void) new QListViewItem(it ? it->parent() : currentItem,it,"StringDetect "+i18n("New Item"),"StringDetect",i18n("New Item"),0,it ? it->parent()->text(1) : currentItem->text(1));
+ }
+}
diff --git a/noncore/apps/tinykate/libkate/document/katedialogs.h b/noncore/apps/tinykate/libkate/document/katedialogs.h
new file mode 100644
index 0000000..f37f45a
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katedialogs.h
@@ -0,0 +1,160 @@
+/***************************************************************************
+ katedialogs.h - description
+ -------------------
+ copyright : (C) 2001 by The Kate Team
+ (C) 2002 by Joseph Wenninger
+ email : kwrite-devel@kde.org
+ 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. *
+ * *
+ ***************************************************************************/
+#ifndef KATEDIALOGS_H
+#define KATEDIALOGS_H
+#include <kdialog.h>
+#include <kdialogbase.h>
+#include "katesyntaxdocument.h"
+#include "katehighlight.h"
+#include <klistview.h>
+#include <qtabwidget.h>
+#include <kcolorbutton.h>
+
+class QWidgetStack;
+class QVBox;
+class KListView;
+class QListViewItem;
+struct syntaxContextData;
+class QCheckBox;
+//class ItemFont;
+#define HlEUnknown 0
+#define HlEContext 1
+#define HlEItem 2
+ //--------
+
+
+class StyleChanger : public QWidget {
+ Q_OBJECT
+ public:
+ StyleChanger(QWidget *parent );
+ void setRef(ItemStyle *);
+ void setEnabled(bool);
+ protected slots:
+ void changed();
+ protected:
+ ItemStyle *style;
+ KColorButton *col;
+ KColorButton *selCol;
+ QCheckBox *bold;
+ QCheckBox *italic;
+};
+
+class HighlightDialogPage : public QTabWidget
+{
+ Q_OBJECT
+ public:
+ HighlightDialogPage(HlManager *, ItemStyleList *, HlDataList *, int hlNumber,
+ QWidget *parent=0, const char *name=0);
+ void saveData();
+
+ protected slots:
+ void defaultChanged(int);
+
+ void hlChanged(int);
+ void itemChanged(int);
+ void changed();
+ void hlEdit();
+ void hlNew();
+ protected:
+ StyleChanger *defaultStyleChanger;
+ ItemStyleList *defaultItemStyleList;
+
+ void writeback();
+ QComboBox *itemCombo, *hlCombo;
+ QLineEdit *wildcards;
+ QLineEdit *mimetypes;
+ QCheckBox *styleDefault;
+ StyleChanger *styleChanger;
+
+ HlDataList *hlDataList;
+ HlData *hlData;
+ ItemData *itemData;
+};
+
+class ItemInfo
+{
+ public:
+ ItemInfo():trans_i18n(),length(0){};
+ ItemInfo(QString _trans,int _length):trans_i18n(_trans),length(_length){};
+ QString trans_i18n;
+ int length;
+};
+
+class HighlightDialog : public KDialogBase
+{
+ Q_OBJECT
+ public:
+ HighlightDialog( HlManager *hlManager, ItemStyleList *styleList,
+ HlDataList *highlightDataList,
+ int hlNumber, QWidget *parent,
+ const char *name=0, bool modal=true );
+ private:
+ HighlightDialogPage *content;
+ protected:
+ virtual void done(int r);
+};
+
+class HlEditDialog : public KDialogBase
+{
+ Q_OBJECT
+ public:
+ HlEditDialog(HlManager *,QWidget *parent=0, const char *name=0, bool modal=true, HlData *data=0);
+ private:
+ class QWidgetStack *stack;
+ class QVBox *contextOptions, *itemOptions;
+ class KListView *contextList;
+ class QListViewItem *currentItem;
+ void initContextOptions(class QVBox *co);
+ void initItemOptions(class QVBox *co);
+ void loadFromDocument(HlData *hl);
+ void showContext();
+ void showItem();
+
+ QListViewItem *addContextItem(QListViewItem *_parent,QListViewItem *prev,struct syntaxContextData *data);
+ void insertTranslationList(QString tag, QString trans,int length);
+ void newDocument();
+
+ class QLineEdit *ContextDescr;
+ class QComboBox *ContextAttribute;
+ class QComboBox *ContextLineEnd;
+
+ class QComboBox *ItemType;
+ class QComboBox *ItemContext;
+ class QLineEdit *ItemParameter;
+ class QComboBox *ItemAttribute;
+
+ class QMap<int,QString> id2tag;
+ class QMap<int,ItemInfo> id2info;
+ class QMap<QString,int> tag2id;
+ int transTableCnt;
+ protected slots:
+ void currentSelectionChanged ( QListViewItem * );
+ void contextDescrChanged(const QString&);
+ void contextLineEndChanged(int);
+ void contextAttributeChanged(int);
+ void contextAddNew();
+
+ void ItemTypeChanged(int id);
+ void ItemParameterChanged(const QString& name);
+ void ItemAttributeChanged(int attr);
+ void ItemContextChanged(int cont);
+ void ItemAddNew();
+};
+
+#endif
diff --git a/noncore/apps/tinykate/libkate/document/katedocument.cpp b/noncore/apps/tinykate/libkate/document/katedocument.cpp
new file mode 100644
index 0000000..0d84bcf
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katedocument.cpp
@@ -0,0 +1,3169 @@
+/***************************************************************************
+ 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();
+
+ 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 false;
+ }
+
+ 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 true;
+}
+
+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();
+ 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));
+
+ colors[0] = config->readColorEntry("Color Background", &colors[0]);
+ colors[1] = config->readColorEntry("Color Selected", &colors[1]);
+
+ config->sync();
+}
+
+void KateDocument::writeConfig()
+{
+ KConfig *config = KGlobal::config();
+ config->setGroup("Kate Document");
+#if 0
+ cofig->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();
+}
+
+void KateDocument::readSessionConfig(KConfig *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)
+{
+#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::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
new file mode 100644
index 0000000..220d188
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katedocument.h
@@ -0,0 +1,569 @@
+/***************************************************************************
+ 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 *);
+
+ 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);
+
+ 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/katedocumentIface.h b/noncore/apps/tinykate/libkate/document/katedocumentIface.h
new file mode 100644
index 0000000..51c7506
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katedocumentIface.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ katedocumentIface.h - description
+ -------------------
+ copyright : (C) 2001 by The Kate Team
+ (C) 2002 by Joseph Wenninger
+ email : kwrite-devel@kde.org
+ 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. *
+ * *
+ ***************************************************************************/
+#ifndef _KATEDOCUMENT_IFACE_H_
+#define _KATEDOCUMENT_IFACE_H_
+
+#include <dcopobject.h>
+
+class KateDocumentDCOPIface : virtual public DCOPObject
+{
+ K_DCOP
+
+ k_dcop:
+ virtual void open (const QString &name=0)=0;
+};
+#endif
+
diff --git a/noncore/apps/tinykate/libkate/document/katehighlight.cpp b/noncore/apps/tinykate/libkate/document/katehighlight.cpp
new file mode 100644
index 0000000..797968b
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katehighlight.cpp
@@ -0,0 +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;
+ config=KGlobal::config();
+ config->setGroup(iName + QString(" Highlight"));
+ return config;
+}
+
+QString Highlight::getWildcards() {
+ KConfig *config;
+
+ config = getKConfig();
+
+ //if wildcards not yet in config, then use iWildCards as default
+ return config->readEntry("Wildcards", iWildcards);
+}
+
+
+QString Highlight::getMimetypes() {
+ KConfig *config;
+
+ config = getKConfig();
+
+ return config->readEntry("Mimetypes", iMimetypes);
+}
+
+
+HlData *Highlight::getData() {
+ KConfig *config;
+ HlData *hlData;
+
+ config = getKConfig();
+
+// 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;
+
+ config = getKConfig();
+
+// 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;
+
+ config = getKConfig();
+ getItemDataList(list, config);
+}
+
+void Highlight::getItemDataList(ItemDataList &list, KConfig *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
+ * class, which should be used
+ * as storage
+ *************
+ * output: none
+ *************
+ * return value: none
+*******************************************************************************************/
+
+void Highlight::setItemDataList(ItemDataList &list, KConfig *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;
+ 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;
+ 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;
+ 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
new file mode 100644
index 0000000..1baddcc
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katehighlight.h
@@ -0,0 +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;
+
+//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();
+ QString getWildcards();
+ QString getMimetypes();
+ HlData *getData();
+ void setData(HlData *);
+ void getItemDataList(ItemDataList &);
+ void getItemDataList(ItemDataList &, KConfig *);
+ void setItemDataList(ItemDataList &, KConfig *);
+ 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
new file mode 100644
index 0000000..c51221b
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katesyntaxdocument.cpp
@@ -0,0 +1,306 @@
+/***************************************************************************
+ 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 <qfile.h>
+#include <kdebug.h>
+#include <kstddirs.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <qstringlist.h>
+#include <kconfig.h>
+#include <kglobal.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();
+ KStandardDirs *dirs = KGlobal::dirs();
+
+ QStringList list=dirs->findAllResources("data","kate/syntax/*.xml",false,true);
+
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ QString Group="Highlighting_Cache"+*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:"+(*it));
+ setIdentifier(*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 = *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->value());
+ m_data+="TEST";//e2->value().stripWhiteSpace();
+
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return m_data;
+}
diff --git a/noncore/apps/tinykate/libkate/document/katesyntaxdocument.h b/noncore/apps/tinykate/libkate/document/katesyntaxdocument.h
new file mode 100644
index 0000000..5c5c5a4
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katesyntaxdocument.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ katesyntaxdocument.h - 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef SYNTAXDOCUMENT_H
+#define SYNTAXDOCUMENT_H
+
+#include <opie/xmltree.h>
+#include <qlist.h>
+#include <qstringlist.h>
+
+
+class syntaxModeListItem
+{
+ public:
+ QString name;
+ QString section;
+ QString mimetype;
+ QString extension;
+ QString identifier;
+};
+
+class syntaxContextData
+{
+ public:
+ Opie::XMLElement *parent;
+ Opie::XMLElement *currentGroup;
+ Opie::XMLElement *item;
+};
+
+typedef QList<syntaxModeListItem> SyntaxModeList;
+
+class SyntaxDocument
+{
+ public:
+ SyntaxDocument();
+ ~SyntaxDocument();
+
+ QStringList& finddata(const QString& mainGroup,const QString& type,bool clearList=true);
+ SyntaxModeList modeList();
+
+ syntaxContextData* getGroupInfo(const QString& langName, const QString &group);
+ void freeGroupInfo(syntaxContextData* data);
+ syntaxContextData* getConfig(const QString& mainGroupName, const QString &Config);
+ bool nextItem(syntaxContextData* data);
+ bool nextGroup(syntaxContextData* data);
+ syntaxContextData* getSubItems(syntaxContextData* data);
+ QString groupItemData(syntaxContextData* data,QString name);
+ QString groupData(syntaxContextData* data,QString name);
+ void setIdentifier(const QString& identifier);
+
+ private:
+ Opie::XMLElement *m_root;
+ void setupModeList(bool force=false);
+ QString currentFile;
+ SyntaxModeList myModeList;
+ QStringList m_data;
+};
+
+#endif
diff --git a/noncore/apps/tinykate/libkate/document/katetextline.cpp b/noncore/apps/tinykate/libkate/document/katetextline.cpp
new file mode 100644
index 0000000..f44cc1c
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katetextline.cpp
@@ -0,0 +1,289 @@
+/*
+ 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 "katetextline.h"
+#include <kdebug.h>
+
+TextLine::TextLine(uchar attribute, int context)
+ : text(0L), attributes(0L), attr(attribute), ctx(context), myMark (0)
+{
+}
+
+TextLine::~TextLine()
+{
+}
+
+
+void TextLine::replace(uint pos, uint delLen, const QChar *insText, uint insLen, uchar *insAttribs)
+{
+ uint oldLen = text.length();
+
+ text.remove (pos, delLen);
+ text.insert (pos, insText, insLen);
+
+ if (oldLen<text.length()) attributes.resize (text.length());
+
+ if (text.length() == 0)
+ {
+ attributes.resize (0);
+ return;
+ }
+
+ if (pos >= oldLen)
+ {
+ for (uint t=oldLen; t < attributes.size(); t++)
+ {
+ attributes[t]=0;
+ }
+ }
+
+ int newAtStuff = insLen-delLen;
+ for (uint m=pos+delLen; m < attributes.size(); m++)
+ {
+ if (m+newAtStuff >= attributes.size()) break;
+ if (m >= attributes.size()) break;
+
+ attributes[m+newAtStuff]=attributes[m];
+ }
+
+ if (insAttribs == 0L)
+ {
+ for (uint m3=pos; m3 < pos+insLen; m3++)
+ {
+ if (m3 < attributes.size()) attributes[m3]=0;
+ }
+ }
+ else
+ {
+ for (uint m2=pos; m2 < pos+insLen; m2++)
+ {
+ if (m2 < attributes.size()) attributes[m2]=insAttribs[m2-pos];
+ }
+ }
+
+ if (oldLen>text.length()) attributes.resize (text.length());
+}
+
+void TextLine::wrap(TextLine::Ptr nextLine, uint pos)
+{
+ int l = text.length() - pos;
+
+ if (l > 0)
+ {
+ nextLine->replace(0, 0, &text.unicode()[pos], l, &attributes[pos]);
+ attr = attributes[pos];
+ truncate(pos);
+ }
+}
+
+void TextLine::unWrap(uint pos, TextLine::Ptr nextLine, uint len) {
+
+ replace(pos, 0, nextLine->text.unicode(), len, nextLine->attributes.data());
+ attr = nextLine->getRawAttr(len);
+ nextLine->replace(0, len, 0L, 0);
+}
+
+int TextLine::firstChar() const {
+ uint z = 0;
+
+ while (z < text.length() && text[z].isSpace()) z++;
+
+ if (z < text.length())
+ return z;
+ else
+ return -1;
+}
+
+int TextLine::lastChar() const {
+ uint z = text.length();
+
+ while (z > 0 && text[z - 1].isSpace()) z--;
+ return z;
+}
+
+void TextLine::removeSpaces() {
+
+ while (text.length() > 0 && text[text.length() - 1].isSpace()) text.truncate (text.length()-1);
+}
+
+QChar TextLine::getChar(uint pos) const {
+ if (pos < text.length()) return text.constref(pos);
+ return ' ';
+}
+const QChar *TextLine::firstNonSpace()
+{
+ const QChar *ptr=getText();
+ int first=firstChar();
+ return (first > -1) ? ptr+first : ptr;
+}
+
+bool TextLine::startingWith(QString& match)
+{
+ return text.startsWith (match);
+}
+
+bool TextLine::endingWith(QString& match) {
+
+ int matchLen = match.length();
+
+ // Get the last chars of the textline
+ QString lastChars = text.right(matchLen);
+
+ return (lastChars == match);
+}
+
+int TextLine::cursorX(uint pos, uint tabChars) const {
+ int l, x, z;
+
+ l = (pos < text.length()) ? pos : text.length();
+ x = 0;
+ for (z = 0; z < l; z++) {
+ if (text[z] == '\t') x += tabChars - (x % tabChars); else x++;
+ }
+ x += pos - l;
+ return x;
+}
+
+void TextLine::setAttribs(uchar attribute, uint start, uint end) {
+ uint z;
+
+ if (end > text.length()) end = text.length();
+ for (z = start; z < end; z++) attributes[z] = (attributes[z] & taSelected) | attribute;
+}
+
+void TextLine::setAttr(uchar attribute) {
+ attr = (attr & taSelected) | attribute;
+}
+
+uchar TextLine::getAttr(uint pos) const {
+ if (pos < text.length()) return attributes[pos] & taAttrMask;
+ return attr & taAttrMask;
+}
+
+uchar TextLine::getAttr() const {
+ return attr & taAttrMask;
+}
+
+uchar TextLine::getRawAttr(uint pos) const {
+ if (pos < text.length()) return attributes[pos];
+ return (attr & taSelected) ? attr : attr | 256;
+}
+
+uchar TextLine::getRawAttr() const {
+ return attr;
+}
+
+void TextLine::setContext(int context) {
+ ctx = context;
+}
+
+int TextLine::getContext() const {
+ return ctx;
+}
+
+
+void TextLine::select(bool sel, uint start, uint end) {
+ uint z;
+
+ if (end > text.length()) end = text.length();
+ if (sel) {
+ for (z = start; z < end; z++) attributes[z] |= taSelected;
+ } else {
+ for (z = start; z < end; z++) attributes[z] &= ~taSelected;
+ }
+}
+
+void TextLine::selectEol(bool sel, uint pos) {
+ uint z;
+
+ if (sel) {
+ for (z = pos; z < text.length(); z++) attributes[z] |= taSelected;
+ attr |= taSelected;
+ } else {
+ for (z = pos; z < text.length(); z++) attributes[z] &= ~taSelected;
+ attr &= ~taSelected;
+ }
+}
+
+
+void TextLine::toggleSelect(uint start, uint end) {
+ uint z;
+
+ if (end > text.length()) end = text.length();
+ for (z = start; z < end; z++) attributes[z] = attributes[z] ^ taSelected;
+}
+
+
+void TextLine::toggleSelectEol(uint pos) {
+ uint z;
+
+ for (z = pos; z < text.length(); z++) attributes[z] = attributes[z] ^ taSelected;
+ attr = attr ^ taSelected;
+}
+
+
+int TextLine::numSelected() const {
+ uint z, n;
+
+ n = 0;
+ for (z = 0; z < text.length(); z++) if (attributes[z] & taSelected) n++;
+ return n;
+}
+
+bool TextLine::isSelected(uint pos) const {
+ if (pos < text.length()) return (attributes[pos] & taSelected);
+ return (attr & taSelected);
+}
+
+bool TextLine::isSelected() const {
+ return (attr & taSelected);
+}
+
+int TextLine::findSelected(uint pos) const {
+ while (pos < text.length() && attributes[pos] & taSelected) pos++;
+ return pos;
+}
+
+int TextLine::findUnselected(uint pos) const {
+ while (pos < text.length() && !(attributes[pos] & taSelected)) pos++;
+ return pos;
+}
+
+int TextLine::findRevSelected(uint pos) const {
+ while (pos > 0 && attributes[pos - 1] & taSelected) pos--;
+ return pos;
+}
+
+int TextLine::findRevUnselected(uint pos) const {
+ while (pos > 0 && !(attributes[pos - 1] & taSelected)) pos--;
+ return pos;
+}
+
+void TextLine::addMark (uint m)
+{
+ myMark = myMark | m;
+}
+
+void TextLine::delMark (uint m)
+{
+ myMark = myMark & ~m;
+}
diff --git a/noncore/apps/tinykate/libkate/document/katetextline.h b/noncore/apps/tinykate/libkate/document/katetextline.h
new file mode 100644
index 0000000..c2968cc
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/document/katetextline.h
@@ -0,0 +1,359 @@
+/*
+ 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 _KWTEXTLINE_H_
+#define _KWTEXTLINE_H_
+
+#include <stdlib.h>
+
+#include <qstring.h>
+#include <qarray.h>
+#include <qvaluelist.h>
+
+#include <ksharedptr.h>
+
+/**
+ FastValueList: QValueList, but with a faster at() like QList
+ FVPrivate is needed so that "const" functions can change the
+ current position
+*/
+template<class T>
+class FVPrivate
+{
+public:
+ int curpos;
+ typedef QValueListConstIterator<T> Iterator;
+ Iterator curit;
+
+ FVPrivate() { curpos=-1; };
+};
+
+template<class T>
+class FastValueList : public QValueList<T>
+{
+public:
+ typedef QValueListIterator<T> Iterator;
+ typedef QValueListConstIterator<T> ConstIterator;
+protected:
+ FVPrivate<T> *fvp;
+
+ Iterator fastat( uint i ) {
+ uint num=count();
+ if (i>=num) {return end();}
+ if (fvp->curpos<0) { fvp->curpos=0; fvp->curit=begin(); }
+ uint curpos=(uint) fvp->curpos;
+ Iterator curit(fvp->curit.node);
+ if (curpos==i) return curit;
+
+ int diff=i-curpos;
+ bool forward;
+ if (diff<0) diff=-diff;
+ if (((uint)diff < i) && ((uint)diff < num-i)) { // start from current node
+ forward=i > (uint)curpos;
+ } else if (i < num - i) { // start from first node
+ curit=begin(); diff=i; forward=TRUE;
+ } else { // start from last node
+ curit=fromLast(); diff=num - i - 1;
+ if (diff<0) diff=0;
+ forward=FALSE;
+ }
+ if (forward) {
+ while(diff--) curit++;
+ } else {
+ while(diff--) curit--;
+ }
+ fvp->curpos=i; fvp->curit=curit;
+ return curit;
+ }
+ ConstIterator fastat( uint i ) const {
+ uint num=count();
+ if (i>=num) {return end();}
+ if (fvp->curpos<0) { fvp->curpos=0; fvp->curit=begin(); }
+ uint curpos=(uint) fvp->curpos;
+ ConstIterator curit=fvp->curit;
+ if (curpos==i) return curit;
+
+ int diff=i-curpos;
+ bool forward;
+ if (diff<0) diff=-diff;
+ if (((uint)diff < i) && ((uint)diff < num-i)) { // start from current node
+ forward=i > (uint)curpos;
+ } else if (i < num - i) { // start from first node
+ curit=begin(); diff=i; forward=TRUE;
+ } else { // start from last node
+ curit=fromLast(); diff=num - i - 1;
+ if (diff<0) diff=0;
+ forward=FALSE;
+ }
+ if (forward) {
+ while(diff--) curit++;
+ } else {
+ while(diff--) curit--;
+ }
+ fvp->curpos=i; fvp->curit=curit;
+ return curit;
+ }
+
+public:
+ FastValueList() : QValueList<T>()
+ { fvp=new FVPrivate<T>(); }
+ FastValueList(const FastValueList<T>& l) : QValueList<T>(l)
+ { fvp=new FVPrivate<T>(); }
+ ~FastValueList() { delete fvp; }
+
+ Iterator insert( Iterator it, const T& x ) {
+ fvp->curpos=-1; return QValueList<T>::insert(it, x);
+ }
+
+ Iterator append( const T& x ) {
+ fvp->curpos=-1; return QValueList<T>::append( x );
+ }
+ Iterator prepend( const T& x ) {
+ fvp->curpos=-1; return QValueList<T>::prepend( x );
+ }
+
+ Iterator remove( Iterator it ) {
+ fvp->curpos=-1; return QValueList<T>::remove( it );
+ }
+ void remove( const T& x ) {
+ fvp->curpos=-1; QValueList<T>::remove( x );
+ }
+
+ T& operator[] ( uint i ) { detach(); return fastat(i); }
+ const T& operator[] ( uint i ) const { return *fastat(i); }
+ Iterator at( uint i ) { detach(); return fastat(i); }
+ ConstIterator at( uint i ) const { return ConstIterator( fastat(i) ); }
+};
+
+
+/**
+ The TextLine represents a line of text. A text line that contains the
+ text, an attribute for each character, an attribute for the free space
+ behind the last character and a context number for the syntax highlight.
+ The attribute stores the index to a table that contains fonts and colors
+ and also if a character is selected.
+*/
+class TextLine : public KShared
+{
+ friend class KWBuffer;
+ friend class KWBufBlock;
+
+public:
+ typedef KSharedPtr<TextLine> Ptr;
+ typedef FastValueList<Ptr> List;
+
+public:
+ /**
+ Creates an empty text line with given attribute and syntax highlight
+ context
+ */
+ TextLine(uchar attribute = 0, int context = 0);
+ ~TextLine();
+
+ /**
+ Returns the length
+ */
+ uint length() const {return text.length();}
+ /**
+ Universal text manipulation method. It can be used to insert, delete
+ or replace text.
+ */
+ void replace(uint pos, uint delLen, const QChar *insText, uint insLen, uchar *insAttribs = 0L);
+
+ /**
+ Appends a string of length l to the textline
+ */
+ void append(const QChar *s, uint l) {replace(text.length(), 0, s, l);}
+ /**
+ Wraps the text from the given position to the end to the next line
+ */
+ void wrap(TextLine::Ptr nextLine, uint pos);
+ /**
+ Wraps the text of given length from the beginning of the next line to
+ this line at the given position
+ */
+ void unWrap(uint pos, TextLine::Ptr nextLine, uint len);
+ /**
+ Truncates the textline to the new length
+ */
+ void truncate(uint newLen) { text.truncate(newLen); attributes.resize(text.length()); }
+ /**
+ Returns the position of the first character which is not a white space
+ */
+ int firstChar() const;
+ /**
+ Returns the position of the last character which is not a white space
+ */
+ int lastChar() const;
+ /**
+ Removes trailing spaces
+ */
+ void removeSpaces();
+ /**
+ Gets the char at the given position
+ */
+ QChar getChar(uint pos) const;
+ /**
+ Gets the text. WARNING: it is not null terminated
+ */
+ const QChar *getText() const {return text.unicode();};
+ /**
+ Gets a C-like null terminated string
+ */
+ const QString getString() { return text; };
+
+ /*
+ Gets a null terminated pointer to first non space char
+ */
+ const QChar *firstNonSpace();
+ /**
+ Returns the x position of the cursor at the given position, which
+ depends on the number of tab characters
+ */
+ int cursorX(uint pos, uint tabChars) const;
+ /**
+ Is the line starting with the given string
+ */
+ bool startingWith(QString& match);
+ /**
+ Is the line ending with the given string
+ */
+ bool endingWith(QString& match);
+
+ /**
+ Sets the attributes from start to end -1
+ */
+ void setAttribs(uchar attribute, uint start, uint end);
+ /**
+ Sets the attribute for the free space behind the last character
+ */
+ void setAttr(uchar attribute);
+ /**
+ Gets the attribute at the given position
+ */
+ uchar getAttr(uint pos) const;
+ /**
+ Gets the attribute for the free space behind the last character
+ */
+ uchar getAttr() const;
+ /**
+ Gets the attribute, including the select state, at the given position
+ */
+ uchar getRawAttr(uint pos) const;
+ /**
+ Gets the attribute, including the select state, for the free space
+ behind the last character
+ */
+ uchar getRawAttr() const;
+
+ /**
+ Sets the syntax highlight context number
+ */
+ void setContext(int context);
+ /**
+ Gets the syntax highlight context number
+ */
+ int getContext() const;
+
+ /**
+ Sets the select state from start to end -1
+ */
+ void select(bool sel, uint start, uint end);
+ /**
+ Sets the select state from the given position to the end, including
+ the free space behind the last character
+ */
+ void selectEol(bool sel, uint pos);
+ /**
+ Toggles the select state from start to end -1
+ */
+ void toggleSelect(uint start, uint end);
+ /**
+ Toggles the select state from the given position to the end, including
+ the free space behind the last character
+ */
+ void toggleSelectEol(uint pos);
+ /**
+ Returns the number of selected characters
+ */
+ int numSelected() const;
+ /**
+ Returns if the character at the given position is selected
+ */
+ bool isSelected(uint pos) const;
+ /**
+ Returns true if the free space behind the last character is selected
+ */
+ bool isSelected() const;
+ /**
+ Finds the next selected character, starting at the given position
+ */
+ int findSelected(uint pos) const;
+ /**
+ Finds the next unselected character, starting at the given position
+ */
+ int findUnselected(uint pos) const;
+ /**
+ Finds the previous selected character, starting at the given position
+ */
+ int findRevSelected(uint pos) const;
+ /**
+ Finds the previous unselected character, starting at the given position
+ */
+ int findRevUnselected(uint pos) const;
+
+ void clearMark () { myMark = 0; };
+ void addMark ( uint m );
+ void delMark ( uint m );
+ uint mark() { return myMark; };
+
+ uchar *getAttribs() { return attributes.data(); }
+
+ protected:
+ /**
+ The text
+ */
+ QString text;
+ /**
+ The attributes
+ */
+ QArray<uchar> attributes;
+ /**
+ The attribute of the free space behind the end
+ */
+ uchar attr;
+ /**
+ The syntax highlight context
+ */
+ int ctx;
+ /**
+ The marks of the current line
+ */
+ uint myMark;
+};
+
+//text attribute constants
+const int taSelected = 0x40;
+const int taAttrMask = ~taSelected & 0xFF;
+
+#endif //KWTEXTLINE_H
+