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