summaryrefslogtreecommitdiff
path: root/noncore/apps/tinykate/libkate
authorjowenn <jowenn>2002-11-10 21:08:01 (UTC)
committer jowenn <jowenn>2002-11-10 21:08:01 (UTC)
commite97a6da57804aa14907dec327fbae71bff9b383e (patch) (unidiff)
tree15f6ee292dba24bdda72f5c72f6d2224c3516763 /noncore/apps/tinykate/libkate
parent7c012ee8cd16d8befacc6f6750711443fac0fd5e (diff)
downloadopie-e97a6da57804aa14907dec327fbae71bff9b383e.zip
opie-e97a6da57804aa14907dec327fbae71bff9b383e.tar.gz
opie-e97a6da57804aa14907dec327fbae71bff9b383e.tar.bz2
import of tiny kate. (saving not possible yet)
Diffstat (limited to 'noncore/apps/tinykate/libkate') (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
-rw-r--r--noncore/apps/tinykate/libkate/interfaces/document.h103
-rw-r--r--noncore/apps/tinykate/libkate/interfaces/interfaces.cpp51
-rw-r--r--noncore/apps/tinykate/libkate/interfaces/view.h160
-rw-r--r--noncore/apps/tinykate/libkate/ktexteditor/ktexteditor.cpp140
-rw-r--r--noncore/apps/tinykate/libkate/ktexteditor/ktexteditor.h239
-rw-r--r--noncore/apps/tinykate/libkate/libkate.pro90
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kaction.h8
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kapplication.cpp8
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kapplication.h11
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kcolorbtn.cpp84
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kcolorbtn.h92
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kcolorbutton.h4
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kcolordialog.cpp6
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kcolordialog.h14
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kconfig.cpp181
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kconfig.h51
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kdatepicker.cpp405
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kdatepicker.h177
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kdatetbl.cpp718
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kdatetbl.h308
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kdebug.h112
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kdialog.h16
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kdialogbase.cpp214
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kdialogbase.h105
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kemailsettings.cpp6
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kemailsettings.h32
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kfiledialog.h21
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kfontdialog.cpp6
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kfontdialog.h14
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kglobal.cpp49
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kglobal.h27
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kglobalsettings.cpp17
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kglobalsettings.h15
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kiconloader.cpp33
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kiconloader.h31
-rw-r--r--noncore/apps/tinykate/libkate/microkde/klineedit.h13
-rw-r--r--noncore/apps/tinykate/libkate/microkde/klineeditdlg.h8
-rw-r--r--noncore/apps/tinykate/libkate/microkde/klistview.h24
-rw-r--r--noncore/apps/tinykate/libkate/microkde/klocale.cpp530
-rw-r--r--noncore/apps/tinykate/libkate/microkde/klocale.h53
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kmessagebox.cpp90
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kmessagebox.h46
-rw-r--r--noncore/apps/tinykate/libkate/microkde/knotifyclient.h14
-rw-r--r--noncore/apps/tinykate/libkate/microkde/knumvalidator.cpp8
-rw-r--r--noncore/apps/tinykate/libkate/microkde/knumvalidator.h14
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kpopupmenu.h8
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kprinter.h8
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kprocess.cpp15
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kprocess.h16
-rw-r--r--noncore/apps/tinykate/libkate/microkde/krestrictedline.h13
-rw-r--r--noncore/apps/tinykate/libkate/microkde/krun.cpp6
-rw-r--r--noncore/apps/tinykate/libkate/microkde/krun.h13
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kseparator.h8
-rw-r--r--noncore/apps/tinykate/libkate/microkde/ksharedptr.h142
-rw-r--r--noncore/apps/tinykate/libkate/microkde/ksimpleconfig.h12
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kstandarddirs.cpp39
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kstandarddirs.h23
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kstaticdeleter.h35
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kstddirs.h23
-rw-r--r--noncore/apps/tinykate/libkate/microkde/ktempfile.cpp25
-rw-r--r--noncore/apps/tinykate/libkate/microkde/ktempfile.h20
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kunload.h6
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kurlrequester.cpp14
-rw-r--r--noncore/apps/tinykate/libkate/microkde/kurlrequester.h17
-rw-r--r--noncore/apps/tinykate/libkate/qt3back/README12
-rw-r--r--noncore/apps/tinykate/libkate/qt3back/qregexp3.cpp3767
-rw-r--r--noncore/apps/tinykate/libkate/qt3back/qregexp3.h111
-rw-r--r--noncore/apps/tinykate/libkate/view/kateundohistory.cpp271
-rw-r--r--noncore/apps/tinykate/libkate/view/kateundohistory.h114
-rw-r--r--noncore/apps/tinykate/libkate/view/kateview.cpp2923
-rw-r--r--noncore/apps/tinykate/libkate/view/kateview.h865
-rw-r--r--noncore/apps/tinykate/libkate/view/kateviewdialog.cpp556
-rw-r--r--noncore/apps/tinykate/libkate/view/kateviewdialog.h194
90 files changed, 21766 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
diff --git a/noncore/apps/tinykate/libkate/interfaces/document.h b/noncore/apps/tinykate/libkate/interfaces/document.h
new file mode 100644
index 0000000..cbfd1b3
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/interfaces/document.h
@@ -0,0 +1,103 @@
1/***************************************************************************
2 document.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 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Library General Public
14 License as published by the Free Software Foundation; either
15 version 2 of the License, or (at your option) any later version.
16
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Library General Public License for more details.
21
22 You should have received a copy of the GNU Library General Public License
23 along with this library; see the file COPYING.LIB. If not, write to
24 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26 ***************************************************************************/
27
28#ifndef _KATE_DOCUMENT_INCLUDE_
29#define _KATE_DOCUMENT_INCLUDE_
30
31#include <ktexteditor.h>
32
33class KConfig;
34
35namespace Kate
36{
37
38/** internal class for document bookmarks. */
39class Mark
40{
41 public:
42 uint line;
43 uint type;
44};
45
46/** This interface provedes access to the Kate Document class.
47*/
48class Document : public KTextEditor::Document
49{
50 Q_OBJECT
51
52 public:
53 Document ();
54 virtual ~Document ();
55
56 public:
57 /** Read document config.
58 */
59 virtual void readConfig () { ; };
60 /** Save document config.
61 */
62 virtual void writeConfig () { ; };
63
64 /** Read document session config.
65 */
66 virtual void readSessionConfig (KConfig *) { ; };
67 /** Save document session config.
68 */
69 virtual void writeSessionConfig (KConfig *) { ; };
70
71 /** Returns the document ID.
72 */
73 virtual uint docID () { return 0L; };
74
75 /** Defines possible mark types. A line can have marks of different types.
76 */
77 enum marks
78 {
79 Bookmark = 1,
80 Breakpoint = 2,
81 markType0 = 4,
82 markType1 = 8,
83 markType2 = 16,
84 markType3 = 32,
85 markType4 = 64,
86 markType5 = 128,
87 markType6 = 256,
88 markType7 = 512,
89 markType8 = 1024
90 };
91
92 /** A list of all marks in a document. Use binary comparing to find marks of a specific type.
93 */
94 virtual QList<Mark> marks () { QList<Mark> l; return l; };
95
96 public slots:
97 // clear buffer/filename - update the views
98 virtual void flush () { ; };
99};
100
101};
102
103#endif
diff --git a/noncore/apps/tinykate/libkate/interfaces/interfaces.cpp b/noncore/apps/tinykate/libkate/interfaces/interfaces.cpp
new file mode 100644
index 0000000..4fdd252
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/interfaces/interfaces.cpp
@@ -0,0 +1,51 @@
1/***************************************************************************
2 interfaces.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 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Library General Public
14 License as published by the Free Software Foundation; either
15 version 2 of the License, or (at your option) any later version.
16
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Library General Public License for more details.
21
22 You should have received a copy of the GNU Library General Public License
23 along with this library; see the file COPYING.LIB. If not, write to
24 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26 ***************************************************************************/
27
28#include "document.h"
29
30#include "view.h"
31
32namespace Kate
33{
34
35Document::Document () : KTextEditor::Document (0L, 0L)
36{
37}
38
39Document::~Document ()
40{
41}
42
43View::View ( KTextEditor::Document *doc, QWidget *parent, const char *name ) : KTextEditor::View (doc, parent, name)
44{
45}
46
47View::~View ()
48{
49}
50
51};
diff --git a/noncore/apps/tinykate/libkate/interfaces/view.h b/noncore/apps/tinykate/libkate/interfaces/view.h
new file mode 100644
index 0000000..5b24bb5
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/interfaces/view.h
@@ -0,0 +1,160 @@
1/***************************************************************************
2 view.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 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Library General Public
14 License as published by the Free Software Foundation; either
15 version 2 of the License, or (at your option) any later version.
16
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Library General Public License for more details.
21
22 You should have received a copy of the GNU Library General Public License
23 along with this library; see the file COPYING.LIB. If not, write to
24 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
26 ***************************************************************************/
27
28#ifndef _KATE_VIEW_INCLUDE_
29#define _KATE_VIEW_INCLUDE_
30
31#include <ktexteditor.h>
32
33class KConfig;
34
35namespace Kate
36{
37
38class Document;
39class Mark;
40
41/** This interface provides access to the view.
42*/
43class View : public KTextEditor::View
44{
45 Q_OBJECT
46
47 public:
48 View ( KTextEditor::Document *doc, QWidget *parent, const char *name = 0 );
49 virtual ~View ();
50
51 /** Returns a pointer to the document of the view.
52 */
53 virtual Document *getDoc () { return 0L; };
54
55 /** Returns the marked text in the view.
56 */
57 virtual QString markedText () { return 0L; };
58
59 public slots:
60 /** popup a config dialog for the editor part.
61 */
62 virtual void configDialog () { ; };
63
64 // Highlighting slots
65 virtual void setHl (int) { ; };
66 virtual int getHl () { return 0; };
67 virtual int getHlCount () { return 0; };
68 virtual QString getHlName (int) { return 0L; };
69 virtual QString getHlSection (int) { return 0L; };
70
71 // undo/redo stuff
72 virtual void undo () { ; };
73 virtual void redo () { ; };
74 virtual void undoHistory() { ; };
75
76 public:
77 // read/save config of the view
78 virtual void readConfig () { ; };
79 virtual void writeConfig () { ; };
80
81 // read/save sessionconfig of the view
82 virtual void readSessionConfig (KConfig *) { ; };
83 virtual void writeSessionConfig (KConfig *) { ; };
84
85 public slots:
86 // some simply key commands
87 virtual void keyReturn () { ; };
88 virtual void keyDelete () { ; };
89 virtual void backspace () { ; };
90 virtual void killLine () { ; };
91
92 // move cursor in the view
93 virtual void cursorLeft () { ; };
94 virtual void shiftCursorLeft () { ; };
95 virtual void cursorRight () { ; };
96 virtual void shiftCursorRight () { ; };
97 virtual void wordLeft () { ; };
98 virtual void shiftWordLeft () { ; };
99 virtual void wordRight () { ; };
100 virtual void shiftWordRight () { ; };
101 virtual void home () { ; };
102 virtual void shiftHome () { ; };
103 virtual void end () { ; };
104 virtual void shiftEnd () { ; };
105 virtual void up () { ; };
106 virtual void shiftUp () { ; };
107 virtual void down () { ; };
108 virtual void shiftDown () { ; };
109 virtual void scrollUp () { ; };
110 virtual void scrollDown () { ; };
111 virtual void topOfView () { ; };
112 virtual void bottomOfView () { ; };
113 virtual void pageUp () { ; };
114 virtual void shiftPageUp () { ; };
115 virtual void pageDown () { ; };
116 virtual void shiftPageDown () { ; };
117 virtual void top () { ; };
118 virtual void shiftTop () { ; };
119 virtual void bottom () { ; };
120 virtual void shiftBottom () { ; };
121
122 public slots:
123 // edit command popup window
124 virtual void slotEditCommand () { ; };
125
126 // icon border enable/disable
127 virtual void setIconBorder (bool) { ; };
128 virtual void toggleIconBorder () { ; };
129
130 // goto mark
131 virtual void gotoMark (Mark *) { ; };
132
133 // toggle current line bookmark or clear all bookmarks
134 virtual void toggleBookmark () { ; };
135 virtual void clearBookmarks () { ; };
136
137 public:
138 // is iconborder visible ?
139 virtual bool iconBorder() { return false; };
140
141 public slots:
142 /**
143 Flushes the document of the text widget. The user is given
144 a chance to save the current document if the current document has
145 been modified.
146 */
147 virtual void flush () { ; };
148
149 public:
150 /**
151 Returns true if the current document can be
152 discarded. If the document is modified, the user is asked if he wants
153 to save it. On "cancel" the function returns false.
154 */
155 virtual bool canDiscard() { return false; };
156};
157
158};
159
160#endif
diff --git a/noncore/apps/tinykate/libkate/ktexteditor/ktexteditor.cpp b/noncore/apps/tinykate/libkate/ktexteditor/ktexteditor.cpp
new file mode 100644
index 0000000..6b4d86d
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/ktexteditor/ktexteditor.cpp
@@ -0,0 +1,140 @@
1/* This file is part of the KDE project
2 Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
3 Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
22#include "ktexteditor.h"
23
24using namespace KTextEditor;
25
26class View::ViewPrivate
27{
28public:
29 ViewPrivate()
30 {
31 }
32 ~ViewPrivate()
33 {
34 }
35
36 Document *m_doc;
37 bool m_bContextPopup;
38};
39
40View::View( Document *doc, QWidget *parent, const char *name )
41: QWidget( parent, name )
42{
43 d = new ViewPrivate;
44 d->m_doc = doc;
45 d->m_bContextPopup = true;
46}
47
48View::~View()
49{
50 delete d;
51}
52
53Document *View::document() const
54{
55 return d->m_doc;
56}
57
58void View::insertText( const QString &text, bool mark )
59{
60 int line, col;
61 getCursorPosition( &line, &col );
62 document()->insertAt( text, line, col, mark );
63}
64
65void View::setInternalContextMenuEnabled( bool b )
66{
67 d->m_bContextPopup = b;
68}
69
70bool View::internalContextMenuEnabled() const
71{
72 return d->m_bContextPopup;
73}
74
75class Document::DocumentPrivate
76{
77public:
78 DocumentPrivate()
79 {
80 }
81 ~DocumentPrivate()
82 {
83 }
84
85};
86
87Document::Document( QObject *parent, const char *name )
88 : QObject(parent,name)
89{
90 d = new DocumentPrivate;
91}
92
93Document::~Document()
94{
95 //one never knows...
96 QListIterator<View> it( m_views );
97
98 for (; it.current(); ++it )
99 disconnect( it.current(), SIGNAL( destroyed() ),
100 this, SLOT( slotViewDestroyed() ) );
101
102 delete d;
103}
104
105QList<View> Document::views() const
106{
107 return m_views;
108}
109
110void Document::addView( View *view )
111{
112 if ( !view )
113 return;
114
115 if ( m_views.findRef( view ) != -1 )
116 return;
117
118 m_views.append( view );
119 connect( view, SIGNAL( destroyed() ),
120 this, SLOT( slotViewDestroyed() ) );
121}
122
123void Document::removeView( View *view )
124{
125 if ( !view )
126 return;
127
128 disconnect( view, SIGNAL( destroyed() ),
129 this, SLOT( slotViewDestroyed() ) );
130
131 m_views.removeRef( view );
132}
133
134void Document::slotViewDestroyed()
135{
136 const View *view = static_cast<const View *>( sender() );
137 m_views.removeRef( view );
138}
139
140
diff --git a/noncore/apps/tinykate/libkate/ktexteditor/ktexteditor.h b/noncore/apps/tinykate/libkate/ktexteditor/ktexteditor.h
new file mode 100644
index 0000000..595b5d3
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/ktexteditor/ktexteditor.h
@@ -0,0 +1,239 @@
1/* This file is part of the KDE project
2 Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
3 Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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 __ktexteditor_h__
22#define __ktexteditor_h__
23
24#include <qwidget.h>
25#include <qlist.h>
26
27/**
28 * This is the kparts interface classes for text editors.
29 * The text editors use the Document/View model that allows multiple views into
30 * one file (Document)
31 *
32 * Line numbers passed via this interface must begin at line number zero (0).
33 *
34 * TODO: See documentation at http://??????? for information on how to use kparts in
35 * general. A simple (but sufficient) implementation is shown below.
36 *
37 * <pre>
38 * QHBoxLayout *layout = new QHBoxLayout(this);
39 * QSplitter *fixme = new QSplitter(this);
40 *
41 * KTrader::OfferList offers = KTrader::self()->query( "KTextEditor/Document" );
42 * assert( offers.count() >= 1 );
43 * KService::Ptr service = *offers.begin();
44 * KLibFactory *factory = KLibLoader::self()->factory( service->library() );
45 * assert( factory );
46 * m_part = static_cast<KTextEditor::Document *>(
47 * factory->create( this, 0, "KTextEditor::Document" ) );
48 * assert( m_part );
49 * m_part->createView( fixme, 0 );
50 * layout->addWidget(fixme);
51 * m_part->setText( "" );
52 * </pre>
53 *
54 * You may also be able to use a dynamic_cast for the document part above
55 * (depending on compliation of the library used)
56 *
57 */
58
59namespace KTextEditor
60{
61
62class Document;
63
64/**
65 * The View class encapsulates a single view into the document.
66 */
67
68class View : public QWidget
69{
70 Q_OBJECT
71
72public:
73 /**
74 * Create a new view to the given document. The document must be non-null.
75 */
76 View( Document *doc, QWidget *parent, const char *name = 0 );
77 virtual ~View();
78
79 /**
80 * Acessor to the parent Document.
81 */
82 virtual Document *document() const; // XXX fix when renaming KXMLGUIClient::document
83
84 virtual void setCursorPosition( int line, int col, bool mark = false ) = 0;
85 virtual void getCursorPosition( int *line, int *col ) = 0;
86
87 /**
88 * Inserts text at the current cursor position into the document
89 */
90 virtual void insertText( const QString &text, bool mark = false );
91
92 /**
93 * Overwrite mode is where the char under the cursor is replaced with the
94 * char typed by the user
95 */
96 virtual bool isOverwriteMode() const = 0;
97
98 /**
99 * You should reimplement this method.
100 * If the internal popupmenu property is enabled, then the implementation
101 * is free to handle/use/implement/show a context popupmenu ( see also
102 * KContextMenuManager class in kdeui ). If disabled, then the
103 * implementation should emit the @ref contextPopupMenu signal.
104 */
105 virtual void setInternalContextMenuEnabled( bool b );
106 virtual bool internalContextMenuEnabled() const;
107
108public slots:
109 virtual void setOverwriteMode( bool b ) = 0;
110
111signals:
112 /**
113 * Connect here when you want to implement a custom popup menu.
114 */
115 void contextPopupMenu( const QPoint &p );
116
117 /**
118 * Connect here if you want to track the scrolling within the editor. This
119 * allows you to add specialised borders that displays extra data about
120 * particular lines such as breakpoints etc.
121 */
122 void scrollValueChanged( int value );
123
124private:
125 class ViewPrivate;
126 ViewPrivate *d;
127};
128
129class Document : public QObject
130{
131 Q_OBJECT
132public:
133 Document( QObject *parent = 0, const char *name = 0 );
134 virtual ~Document();
135
136 /**
137 * Create a view that will display the document data. You can create as many
138 * views as you like. When the user modifies data in one view then all other
139 * views will be updated as well.
140 */
141 virtual View *createView( QWidget *parent, const char *name = 0 ) = 0;
142
143 /*
144 * Accessor to the list of views.
145 */
146 virtual QList<View> views() const;
147
148 /**
149 * @return All the text from the requested line.
150 */
151 virtual QString textLine( int line ) const = 0;
152
153 virtual void setSelection( int row_from, int col_from, int row_to, int col_t ) = 0;
154 virtual bool hasSelection() const = 0;
155 virtual QString selection() const = 0;
156
157 /**
158 * @return The current number of lines in the document
159 */
160 virtual int numLines() const = 0;
161
162 /**
163 * Insert line(s) at the given line number. If the line number is -1
164 * (the default) then the line is added to end of the document
165 */
166 virtual void insertLine( const QString &s, int line = -1 ) = 0;
167
168 /**
169 * Add the line(s) into the document at the given line and column.
170 */
171 virtual void insertAt( const QString &s, int line, int col, bool mark = FALSE ) = 0;
172
173 virtual void removeLine( int line ) = 0;
174
175 /**
176 * @return the complete document as a single QString
177 */
178 virtual QString text() const = 0;
179
180 /**
181 * @return the number of characters in the document
182 */
183 virtual int length() const = 0;
184
185public slots:
186 /**
187 * Set the given text into the view.
188 * Warning: This will overwrite any data currently held in this view.
189 */
190 virtual void setText( const QString &t ) = 0;
191
192signals:
193
194 /**
195 * When the user changes the text then this signal is emitted
196 * TODO: - explain why and what type of change trigger this?
197 */
198 void textChanged();
199
200 /**
201 */
202 void deleted( int startLine, int endLine );
203
204 /**
205 */
206 void inserted( int startLine, int endLine );
207
208protected:
209 /**
210 * Call this method in your document implementation whenever you created a new
211 * view.
212 * (like in @ref createView )
213 */
214 virtual void addView( View *view );
215
216 /**
217 * Call this method in your document implementation whenever you delete a view.
218 */
219 virtual void removeView( View *view );
220
221 QList<View> m_views;
222
223private slots:
224
225 /**
226 * The view emits a destroyed() signal which is connected to this slot
227 * and removed from our internal list. Note: The view* is obtained from
228 * the QObject::sender() method.
229 */
230 void slotViewDestroyed();
231
232private:
233 class DocumentPrivate;
234 DocumentPrivate *d;
235};
236
237};
238
239#endif
diff --git a/noncore/apps/tinykate/libkate/libkate.pro b/noncore/apps/tinykate/libkate/libkate.pro
new file mode 100644
index 0000000..a504abf
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/libkate.pro
@@ -0,0 +1,90 @@
1 TEMPLATE= lib
2 CONFIG = qt warn_on release
3 DESTDIR = $(OPIEDIR)/bin
4 HEADERS = microkde/kapplication.h \
5 microkde/kconfig.h \
6 microkde/kdebug.h \
7 microkde/kdialog.h \
8 microkde/kdialogbase.h \
9 microkde/kfiledialog.h \
10 microkde/kglobal.h \
11 microkde/kiconloader.h \
12 microkde/klineedit.h \
13 microkde/klocale.h \
14 microkde/kmessagebox.h \
15 microkde/kprinter.h \
16 microkde/krestrictedline.h \
17 microkde/kseparator.h \
18 microkde/ksimpleconfig.h \
19 microkde/kstandarddirs.h \
20 microkde/ktempfile.h \
21 microkde/kunload.h \
22 microkde/kurlrequester.h \
23 microkde/kfontdialog.h \
24 microkde/krun.h \
25 microkde/knumvalidator.h \
26 microkde/kstaticdeleter.h \
27 microkde/klistview.h \
28 microkde/kglobalsettings.h \
29 microkde/kcolorbtn.h \
30 \
31 \
32 qt3back/qregexp3.h \
33 kde/ksharedptr.h \
34 document/katebuffer.h document/katedialogs.h \
35 document/katetextline.h \
36 document/katecmd.h \
37 document/katehighlight.h \
38 document/katecmds.h document/katedocument.h \
39 document/katesyntaxdocument.h \
40 view/kateundohistory.h \
41 view/kateview.h \
42 view/kateviewdialog.h \
43 interfaces/view.h \
44 interfaces/document.h \
45 ktexteditor/ktexteditor.h
46
47 SOURCES = microkde/kapplication.cpp \
48 microkde/kdialogbase.cpp \
49 microkde/kconfig.cpp \
50 microkde/klocale.cpp \
51 microkde/kmessagebox.cpp \
52 microkde/kprocess.cpp \
53 microkde/kstandarddirs.cpp \
54 microkde/ktempfile.cpp \
55 microkde/kurlrequester.cpp \
56 microkde/kcolordialog.cpp \
57 microkde/kfontdialog.cpp \
58 microkde/krun.cpp \
59 microkde/knumvalidator.cpp \
60 microkde/kglobal.cpp \
61 microkde/kglobalsettings.cpp \
62 microkde/kcolorbtn.cpp \
63 \
64 \
65 qt3back/qregexp3.cpp \
66 ktexteditor/ktexteditor.cpp \
67 document/katebuffer.cpp document/katedialogs.cpp \
68 document/katehighlight.cpp \
69 document/katecmd.cpp \
70 document/katesyntaxdocument.cpp document/katecmds.cpp \
71 document/katedocument.cpp document/katetextline.cpp \
72 view/kateundohistory.cpp \
73 view/kateview.cpp \
74 view/kateviewdialog.cpp \
75 interfaces/interfaces.cpp
76
77 INTERFACES=
78 INCLUDEPATH+= $(OPIEDIR)/include $(OPIEDIR)/noncore/apps/tinykate/libkate/microkde \
79 $(OPIEDIR)/noncore/apps/tinykate/libkate/document \
80 $(OPIEDIR)/noncore/apps/tinykate/libkate/view \
81 $(OPIEDIR)/noncore/apps/tinykate/libkate/interfaces \
82 $(OPIEDIR)/noncore/apps/tinykate/libkate/ktexteditor \
83 $(OPIEDIR)/noncore/apps/tinykate/libkate/qt3back
84 DEPENDPATH+= $(OPIEDIR)/include
85LIBS += -lqpe -lopie
86 TARGET = tinykate
87
88INCLUDEPATH += $(OPIEDIR)/include
89DESTDIR = $(QTDIR)/lib$(PROJMAK)
90
diff --git a/noncore/apps/tinykate/libkate/microkde/kaction.h b/noncore/apps/tinykate/libkate/microkde/kaction.h
new file mode 100644
index 0000000..622330e
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kaction.h
@@ -0,0 +1,8 @@
1#ifndef MINIKDE_KACTION_H
2#define MINIKDE_KACTION_H
3
4#include <qaction.h>
5
6#define KAction QAction
7
8#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kapplication.cpp b/noncore/apps/tinykate/libkate/microkde/kapplication.cpp
new file mode 100644
index 0000000..60ed579
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kapplication.cpp
@@ -0,0 +1,8 @@
1#include <stdlib.h>
2
3#include "kapplication.h"
4
5int KApplication::random()
6{
7 return rand();
8}
diff --git a/noncore/apps/tinykate/libkate/microkde/kapplication.h b/noncore/apps/tinykate/libkate/microkde/kapplication.h
new file mode 100644
index 0000000..99fb4f0
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kapplication.h
@@ -0,0 +1,11 @@
1#ifndef MINIKDE_KAPPLICATION_H
2#define MINIKDE_KAPPLICATION_H
3
4class KApplication
5{
6 public:
7 static int random();
8 static int cursorFlashTime() { return 1000; }
9};
10
11#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kcolorbtn.cpp b/noncore/apps/tinykate/libkate/microkde/kcolorbtn.cpp
new file mode 100644
index 0000000..5d21f15
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kcolorbtn.cpp
@@ -0,0 +1,84 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 Martin Jones (mjones@kde.org)
3 Copyright (C) 1999 Cristian Tibirna (ctibirna@kde.org)
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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#include <qdialog.h>
22#include <qpainter.h>
23#include <qdrawutil.h>
24#include <qapplication.h>
25#include <kglobalsettings.h>
26#include "kcolordialog.h"
27#include "kcolorbtn.h"
28
29KColorButton::KColorButton( QWidget *parent, const char *name )
30 : QPushButton( parent, name ), dragFlag(false)
31{
32 // 2000-10-15 (putzer): fixes broken keyboard usage
33 connect (this, SIGNAL(clicked()), this, SLOT(chooseColor()));
34}
35
36KColorButton::KColorButton( const QColor &c, QWidget *parent,
37 const char *name )
38 : QPushButton( parent, name ), col(c), dragFlag(false)
39{
40
41 // 2000-10-15 (putzer): fixes broken keyboard usage
42 connect (this, SIGNAL(clicked()), this, SLOT(chooseColor()));
43}
44
45void KColorButton::setColor( const QColor &c )
46{
47 col = c;
48 repaint( false );
49}
50
51void KColorButton::drawButtonLabel( QPainter *painter )
52{
53 QRect r = QApplication::style().buttonRect( 0, 0, width(), height() );
54 int l = r.x();
55 int t = r.y();
56 int w = r.width();
57 int h = r.height();
58 int b = 5;
59
60 QColor lnCol = colorGroup().text();
61 QColor fillCol = isEnabled() ? col : backgroundColor();
62
63 if ( isDown() ) {
64 qDrawPlainRect( painter, l+b+1, t+b+1, w-b*2, h-b*2, lnCol, 1, 0 );
65 b++;
66 painter->fillRect( l+b+1, t+b+1, w-b*2, h-b*2, fillCol );
67 } else {
68 qDrawPlainRect( painter, l+b, t+b, w-b*2, h-b*2, lnCol, 1, 0 );
69 b++;
70 painter->fillRect( l+b, t+b, w-b*2, h-b*2, fillCol );
71 }
72}
73
74void KColorButton::chooseColor()
75{
76 if( KColorDialog::getColor( col) == QDialog::Rejected )
77 {
78 return;
79 }
80
81 repaint( false );
82 emit changed( col );
83}
84
diff --git a/noncore/apps/tinykate/libkate/microkde/kcolorbtn.h b/noncore/apps/tinykate/libkate/microkde/kcolorbtn.h
new file mode 100644
index 0000000..b79d5e8
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kcolorbtn.h
@@ -0,0 +1,92 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 Martin Jones (mjones@kde.org)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20#ifndef __COLBTN_H__
21#define __COLBTN_H__
22
23#include <qpushbutton.h>
24
25/**
26* This widget can be used to display or allow user selection of a colour.
27*
28* @see KColorDialog
29*
30* @short A pushbutton to display or allow user selection of a colour.
31* @version $Id$
32*/
33class KColorButton : public QPushButton
34{
35 Q_OBJECT
36 Q_PROPERTY( QColor color READ color WRITE setColor )
37
38public:
39 /**
40 * Constructor. Create a KColorButton.
41 */
42 KColorButton( QWidget *parent, const char *name = 0L );
43 /**
44 * Constructor. Create a KColorButton.
45 * @param cThe initial colour of the button.
46 */
47 KColorButton( const QColor &c, QWidget *parent, const char *name = 0L );
48 /**
49 * Destructor.
50 */
51 virtual ~KColorButton() {}
52
53 /**
54 * The current colour.
55 * @return The current colour.
56 */
57 QColor color() const
58 {return col; }
59 /**
60 * Set the current colour.
61 *
62 * @param cThe colour to set.
63 */
64 void setColor( const QColor &c );
65
66signals:
67 /**
68 * This signal will be emitted when the colour of the widget
69 * is changed, either with @ref #setColor() or via user selection.
70 */
71 void changed( const QColor &newColor );
72
73protected slots:
74 void chooseColor();
75
76protected:
77 /**
78 * @reimplemented
79 */
80 virtual void drawButtonLabel( QPainter *p );
81
82private:
83 QColor col;
84 QPoint mPos;
85 bool dragFlag;
86
87 class KColorButtonPrivate;
88 KColorButtonPrivate *d;
89};
90
91#endif
92
diff --git a/noncore/apps/tinykate/libkate/microkde/kcolorbutton.h b/noncore/apps/tinykate/libkate/microkde/kcolorbutton.h
new file mode 100644
index 0000000..b446eca
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kcolorbutton.h
@@ -0,0 +1,4 @@
1#ifndef K_COLOR_BUTTON_H
2#define K_COLOR_BUTTON_H
3#include <kcolorbtn.h>
4#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kcolordialog.cpp b/noncore/apps/tinykate/libkate/microkde/kcolordialog.cpp
new file mode 100644
index 0000000..3aee42a
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kcolordialog.cpp
@@ -0,0 +1,6 @@
1#include "kcolordialog.h"
2
3int KColorDialog::getColor( const QColor & )
4{
5 return 0;
6}
diff --git a/noncore/apps/tinykate/libkate/microkde/kcolordialog.h b/noncore/apps/tinykate/libkate/microkde/kcolordialog.h
new file mode 100644
index 0000000..0f831cd
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kcolordialog.h
@@ -0,0 +1,14 @@
1#ifndef MINIKDE_KCOLORDIALOG_H
2#define MINIKDE_KCOLORDIALOG_H
3
4#include <qcolor.h>
5
6class KColorDialog
7{
8 public:
9 enum { Accepted };
10
11 static int getColor( const QColor & );
12};
13
14#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kconfig.cpp b/noncore/apps/tinykate/libkate/microkde/kconfig.cpp
new file mode 100644
index 0000000..d88bda0
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kconfig.cpp
@@ -0,0 +1,181 @@
1#include <qfile.h>
2#include <qtextstream.h>
3
4#include "kdebug.h"
5
6#include "kconfig.h"
7
8QString KConfig::mGroup = "";
9//QString KConfig::mGroup = "General";
10
11KConfig::KConfig( const QString &fileName )
12 : mFileName( fileName ), mDirty( false )
13{
14 kdDebug() << "KConfig::KConfig(): '" << fileName << "'" << endl;
15
16 load();
17}
18
19
20KConfig::~KConfig()
21{
22 sync();
23}
24
25void KConfig::setGroup( const QString &group )
26{
27 return;
28
29// kdDebug() << "KConfig::setGroup(): '" << group << "'" << endl;
30
31 mGroup = group;
32
33 if ( mGroup.right( 1 ) != "/" ) mGroup += "/";
34}
35
36
37QValueList<int> KConfig::readIntListEntry( const QString & )
38{
39 QValueList<int> l;
40 return l;
41}
42
43int KConfig::readNumEntry( const QString &, int def )
44{
45 return def;
46}
47
48QString KConfig::readEntry( const QString &key, const QString &def )
49{
50 QMap<QString,QString>::ConstIterator it = mStringMap.find( mGroup + key );
51
52 if ( it == mStringMap.end() ) {
53 return def;
54 }
55
56 return *it;
57}
58
59QStringList KConfig::readListEntry( const QString & )
60{
61 return QStringList();
62}
63
64bool KConfig::readBoolEntry( const QString &key, bool def )
65{
66 QMap<QString,bool>::ConstIterator it = mBoolMap.find( mGroup + key );
67
68 if ( it == mBoolMap.end() ) {
69 return def;
70 }
71
72 return *it;
73}
74
75QColor KConfig::readColorEntry( const QString &, QColor *def )
76{
77 if ( def ) return *def;
78 return QColor();
79}
80
81QFont KConfig::readFontEntry( const QString &, QFont *def )
82{
83 if ( def ) return *def;
84 return QFont();
85}
86
87
88void KConfig::writeEntry( const QString &, QValueList<int> )
89{
90}
91
92void KConfig::writeEntry( const QString &, int )
93{
94}
95
96void KConfig::writeEntry( const QString &key, const QString &value )
97{
98 mStringMap.insert( mGroup + key, value );
99
100 mDirty = true;
101}
102
103void KConfig::writeEntry( const QString &, const QStringList & )
104{
105}
106
107void KConfig::writeEntry( const QString &key, bool value)
108{
109 mBoolMap.insert( mGroup + key, value );
110
111 mDirty = true;
112}
113
114void KConfig::writeEntry( const QString &, const QColor & )
115{
116}
117
118void KConfig::writeEntry( const QString &, const QFont & )
119{
120}
121
122void KConfig::load()
123{
124 mBoolMap.clear();
125 mStringMap.clear();
126
127 QFile f( mFileName );
128 if ( !f.open( IO_ReadOnly ) ) {
129 kdDebug() << "KConfig::load(): Can't open file '" << mFileName << "'"
130 << endl;
131 return;
132 }
133
134
135 QTextStream t( &f );
136
137 QString line = t.readLine();
138
139 while ( !line.isNull() ) {
140 QStringList tokens = QStringList::split( ",", line );
141 if ( tokens[0] == "bool" ) {
142 bool value = false;
143 if ( tokens[2] == "1" ) value = true;
144
145 mBoolMap.insert( tokens[1], value );
146 } else if ( tokens[0] == "QString" ) {
147 QString value = tokens[2];
148 mStringMap.insert( tokens[1], value );
149 }
150
151 line = t.readLine();
152 }
153}
154
155void KConfig::sync()
156{
157 if ( !mDirty ) return;
158
159 QFile f( mFileName );
160 if ( !f.open( IO_WriteOnly ) ) {
161 kdDebug() << "KConfig::sync(): Can't open file '" << mFileName << "'"
162 << endl;
163 return;
164 }
165
166 QTextStream t( &f );
167
168 QMap<QString,bool>::ConstIterator itBool;
169 for( itBool = mBoolMap.begin(); itBool != mBoolMap.end(); ++itBool ) {
170 t << "bool," << itBool.key() << "," << (*itBool ) << endl;
171 }
172
173 QMap<QString,QString>::ConstIterator itString;
174 for( itString = mStringMap.begin(); itString != mStringMap.end(); ++itString ) {
175 t << "QString," << itString.key() << "," << (*itString ) << endl;
176 }
177
178 f.close();
179
180 mDirty = false;
181}
diff --git a/noncore/apps/tinykate/libkate/microkde/kconfig.h b/noncore/apps/tinykate/libkate/microkde/kconfig.h
new file mode 100644
index 0000000..8bd768a
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kconfig.h
@@ -0,0 +1,51 @@
1#ifndef MINIKDE_KCONFIG_H
2#define MINIKDE_KCONFIG_H
3
4#include <qstring.h>
5#include <qstringlist.h>
6#include <qvaluelist.h>
7#include <qcolor.h>
8#include <qfont.h>
9#include <qmap.h>
10
11class KConfig
12{
13 public:
14 KConfig( const QString & );
15 ~KConfig();
16
17 void setGroup( const QString & );
18
19 bool hasGroup( const QString &) {return false;}
20
21 QValueList<int> readIntListEntry( const QString & );
22 int readNumEntry( const QString &, int def=0 );
23 QString readEntry( const QString &, const QString &def=QString::null );
24 QStringList readListEntry( const QString & );
25 bool readBoolEntry( const QString &, bool def=false );
26 QColor readColorEntry( const QString &, QColor * );
27 QFont readFontEntry( const QString &, QFont * );
28
29 void writeEntry( const QString &, QValueList<int> );
30 void writeEntry( const QString &, int );
31 void writeEntry( const QString &, const QString & );
32 void writeEntry( const QString &, const QStringList & );
33 void writeEntry( const QString &, bool );
34 void writeEntry( const QString &, const QColor & );
35 void writeEntry( const QString &, const QFont & );
36
37 void load();
38 void sync();
39
40 private:
41 static QString mGroup;
42
43 QString mFileName;
44
45 QMap<QString,bool> mBoolMap;
46 QMap<QString,QString> mStringMap;
47
48 bool mDirty;
49};
50
51#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kdatepicker.cpp b/noncore/apps/tinykate/libkate/microkde/kdatepicker.cpp
new file mode 100644
index 0000000..2cdd609
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kdatepicker.cpp
@@ -0,0 +1,405 @@
1/* -*- C++ -*-
2 This file is part of the KDE libraries
3 Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
4 (C) 1998-2001 Mirko Boehm (mirko@kde.org)
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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#include "kdatepicker.h"
22#include <kglobal.h>
23#include <kapplication.h>
24#include <klocale.h>
25#include <kiconloader.h>
26#include <qframe.h>
27#include <qpainter.h>
28#include <qdialog.h>
29#include <qtoolbutton.h>
30#include <qfont.h>
31#include <qlineedit.h>
32#include <qvalidator.h>
33#include <kdebug.h>
34#include <knotifyclient.h>
35#include "kdatetbl.h"
36#include "kdatepicker.moc"
37
38
39KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name)
40 : QFrame(parent,name),
41 yearForward(new QToolButton(this)),
42 yearBackward(new QToolButton(this)),
43 monthForward(new QToolButton(this)),
44 monthBackward(new QToolButton(this)),
45 selectMonth(new QToolButton(this)),
46 selectYear(new QToolButton(this)),
47 line(new QLineEdit(this)),
48 val(new KDateValidator(this)),
49 table(new KDateTable(this)),
50 fontsize(10)
51{
52 // -----
53 setFontSize(10);
54 line->setValidator(val);
55 yearForward->setPixmap(BarIcon(QString::fromLatin1("2rightarrow")));
56 yearBackward->setPixmap(BarIcon(QString::fromLatin1("2leftarrow")));
57 monthForward->setPixmap(BarIcon(QString::fromLatin1("1rightarrow")));
58 monthBackward->setPixmap(BarIcon(QString::fromLatin1("1leftarrow")));
59 setDate(dt); // set button texts
60 connect(table, SIGNAL(dateChanged(QDate)), SLOT(dateChangedSlot(QDate)));
61 connect(table, SIGNAL(tableClicked()), SLOT(tableClickedSlot()));
62 connect(monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked()));
63 connect(monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked()));
64 connect(yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked()));
65 connect(yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked()));
66 connect(selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked()));
67 connect(selectYear, SIGNAL(clicked()), SLOT(selectYearClicked()));
68 connect(line, SIGNAL(returnPressed()), SLOT(lineEnterPressed()));
69}
70
71KDatePicker::~KDatePicker()
72{
73}
74
75void
76KDatePicker::resizeEvent(QResizeEvent*)
77{
78 QWidget *buttons[] = {
79 yearBackward,
80 monthBackward,
81 selectMonth,
82 selectYear,
83 monthForward,
84 yearForward };
85 const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
86 QSize sizes[NoOfButtons];
87 int buttonHeight=0;
88 int count;
89 int w;
90 int x=0;
91 // ----- calculate button row height:
92 for(count=0; count<NoOfButtons; ++count) {
93 sizes[count]=buttons[count]->sizeHint();
94 buttonHeight=QMAX(buttonHeight, sizes[count].height());
95 }
96 // ----- calculate size of the month button:
97 w=0;
98 for(count=0; count<NoOfButtons; ++count) {
99 if(buttons[count]!=selectMonth)
100 {
101 w+=sizes[count].width();
102 } else {
103 x=count;
104 }
105 }
106 sizes[x].setWidth(width()-w); // stretch the month button
107 // ----- place the buttons:
108 x=0;
109 for(count=0; count<NoOfButtons; ++count)
110 {
111 w=sizes[count].width();
112 buttons[count]->setGeometry(x, 0, w, buttonHeight);
113 x+=w;
114 }
115 // ----- place the line edit for direct input:
116 sizes[0]=line->sizeHint();
117 line->setGeometry(0, height()-sizes[0].height(), width(), sizes[0].height());
118 // ----- adjust the table:
119 table->setGeometry(0, buttonHeight, width(),
120 height()-buttonHeight-sizes[0].height());
121}
122
123void
124KDatePicker::dateChangedSlot(QDate date)
125{
126 kdDebug() << "KDatePicker::dateChangedSlot: date changed (" << date.year() << "/" << date.month() << "/" << date.day() << ")." << endl;
127 line->setText(KGlobal::locale()->formatDate(date, true));
128 emit(dateChanged(date));
129}
130
131void
132KDatePicker::tableClickedSlot()
133{
134 kdDebug() << "KDatePicker::tableClickedSlot: table clicked." << endl;
135 emit(dateSelected(table->getDate()));
136 emit(tableClicked());
137}
138
139const QDate&
140KDatePicker::getDate() const
141{
142 return table->getDate();
143}
144
145const QDate &
146KDatePicker::date() const
147{
148 return table->getDate();
149}
150
151bool
152KDatePicker::setDate(const QDate& date)
153{
154 if(date.isValid()) {
155 QString temp;
156 // -----
157 table->setDate(date);
158 selectMonth->setText(KGlobal::locale()->monthName(date.month(), false));
159 temp.setNum(date.year());
160 selectYear->setText(temp);
161 line->setText(KGlobal::locale()->formatDate(date, true));
162 return true;
163 } else {
164 kdDebug() << "KDatePicker::setDate: refusing to set invalid date." << endl;
165 return false;
166 }
167}
168
169void
170KDatePicker::monthForwardClicked()
171{
172 QDate temp=table->getDate();
173 int day=temp.day();
174 // -----
175 if(temp.month()==12) {
176 temp.setYMD(temp.year()+1, 1, 1);
177 } else {
178 temp.setYMD(temp.year(), temp.month()+1, 1);
179 }
180 if(temp.daysInMonth()<day) {
181 temp.setYMD(temp.year(), temp.month(), temp.daysInMonth());
182 } else {
183 temp.setYMD(temp.year(), temp.month(), day);
184 }
185 // assert(temp.isValid());
186 setDate(temp);
187}
188
189void
190KDatePicker::monthBackwardClicked()
191{
192 QDate temp=table->getDate();
193 int day=temp.day();
194 // -----
195 if(temp.month()==1)
196 {
197 temp.setYMD(temp.year()-1, 12, 1);
198 } else {
199 temp.setYMD(temp.year(), temp.month()-1, 1);
200 }
201 if(temp.daysInMonth()<day)
202 {
203 temp.setYMD(temp.year(), temp.month(), temp.daysInMonth());
204 } else {
205 temp.setYMD(temp.year(), temp.month(), day);
206 }
207 // assert(temp.isValid());
208 setDate(temp);
209}
210
211void
212KDatePicker::yearForwardClicked()
213{
214 QDate temp=table->getDate();
215 int day=temp.day();
216 // -----
217 temp.setYMD(temp.year()+1, temp.month(), 1);
218 if(temp.daysInMonth()<day)
219 {
220 temp.setYMD(temp.year(), temp.month(), temp.daysInMonth());
221 } else {
222 temp.setYMD(temp.year(), temp.month(), day);
223 }
224 // assert(temp.isValid());
225 setDate(temp);
226}
227
228void
229KDatePicker::yearBackwardClicked()
230{
231 QDate temp=table->getDate();
232 int day=temp.day();
233 // -----
234 temp.setYMD(temp.year()-1, temp.month(), 1);
235 if(temp.daysInMonth()<day)
236 {
237 temp.setYMD(temp.year(), temp.month(), temp.daysInMonth());
238 } else {
239 temp.setYMD(temp.year(), temp.month(), day);
240 }
241 // assert(temp.isValid());
242 setDate(temp);
243}
244
245void
246KDatePicker::selectMonthClicked()
247{
248 int month;
249 KPopupFrame* popup = new KPopupFrame(this);
250 KDateInternalMonthPicker* picker = new KDateInternalMonthPicker(fontsize, popup);
251 // -----
252 picker->resize(picker->sizeHint());
253 popup->setMainWidget(picker);
254 picker->setFocus();
255 connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
256 if(popup->exec(selectMonth->mapToGlobal(QPoint(0, selectMonth->height()))))
257 {
258 QDate date;
259 int day;
260 // -----
261 month=picker->getResult();
262 date=table->getDate();
263 day=date.day();
264 // ----- construct a valid date in this month:
265 date.setYMD(date.year(), month, 1);
266 date.setYMD(date.year(), month, QMIN(day, date.daysInMonth()));
267 // ----- set this month
268 setDate(date);
269 } else {
270 KNotifyClient::beep();
271 }
272 delete popup;
273}
274
275void
276KDatePicker::selectYearClicked()
277{
278 int year;
279 KPopupFrame* popup = new KPopupFrame(this);
280 KDateInternalYearSelector* picker = new KDateInternalYearSelector(fontsize, popup);
281 // -----
282 picker->resize(picker->sizeHint());
283 popup->setMainWidget(picker);
284 connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
285 picker->setFocus();
286 if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height()))))
287 {
288 QDate date;
289 int day;
290 // -----
291 year=picker->getYear();
292 date=table->getDate();
293 day=date.day();
294 // ----- construct a valid date in this month:
295 date.setYMD(year, date.month(), 1);
296 date.setYMD(year, date.month(), QMIN(day, date.daysInMonth()));
297 // ----- set this month
298 setDate(date);
299 } else {
300 KNotifyClient::beep();
301 }
302 delete popup;
303}
304
305void
306KDatePicker::setEnabled(bool enable)
307{
308 QWidget *widgets[]= {
309 yearForward, yearBackward, monthForward, monthBackward,
310 selectMonth, selectYear,
311 line, table };
312 const int Size=sizeof(widgets)/sizeof(widgets[0]);
313 int count;
314 // -----
315 for(count=0; count<Size; ++count)
316 {
317 widgets[count]->setEnabled(enable);
318 }
319}
320
321void
322KDatePicker::lineEnterPressed()
323{
324 QDate temp;
325 // -----
326 if(val->date(line->text(), temp)==QValidator::Acceptable)
327 {
328 kdDebug() << "KDatePicker::lineEnterPressed: valid date entered." << endl;
329 emit(dateEntered(temp));
330 setDate(temp);
331 } else {
332 KNotifyClient::beep();
333 kdDebug() << "KDatePicker::lineEnterPressed: invalid date entered." << endl;
334 }
335}
336
337QSize
338KDatePicker::sizeHint() const
339{
340 QSize tableSize=table->sizeHint();
341 QWidget *buttons[]={
342 yearBackward,
343 monthBackward,
344 selectMonth,
345 selectYear,
346 monthForward,
347 yearForward };
348 const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
349 QSize sizes[NoOfButtons];
350 int cx=0, cy=0, count;
351 // ----- store the size hints:
352 for(count=0; count<NoOfButtons; ++count)
353 {
354 sizes[count]=buttons[count]->sizeHint();
355 if(buttons[count]==selectMonth)
356 {
357 cx+=maxMonthRect.width();
358 } else {
359 cx+=sizes[count].width();
360 }
361 cy=QMAX(sizes[count].height(), cy);
362 }
363 // ----- calculate width hint:
364 cx=QMAX(cx, tableSize.width()); // line edit ignored
365 // ----- calculate height hint:
366 cy+=tableSize.height()+line->sizeHint().height();
367 return QSize(cx, cy);
368}
369
370void
371KDatePicker::setFontSize(int s)
372{
373 QWidget *buttons[]= {
374 // yearBackward,
375 // monthBackward,
376 selectMonth,
377 selectYear,
378 // monthForward,
379 // yearForward
380 };
381 const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
382 int count;
383 QFont font;
384 QRect r;
385 // -----
386 fontsize=s;
387 for(count=0; count<NoOfButtons; ++count)
388 {
389 font=buttons[count]->font();
390 font.setPointSize(s);
391 buttons[count]->setFont(font);
392 }
393 QFontMetrics metrics(selectMonth->fontMetrics());
394 for(int i=1; i <= 12; ++i)
395 { // maxMonthRect is used by sizeHint()
396 r=metrics.boundingRect(KGlobal::locale()->monthName(i, false));
397 maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width()));
398 maxMonthRect.setHeight(QMAX(r.height(), maxMonthRect.height()));
399 }
400 table->setFontSize(s);
401}
402
403void KDatePicker::virtual_hook( int id, void* data )
404{ /*BASE::virtual_hook( id, data );*/ }
405
diff --git a/noncore/apps/tinykate/libkate/microkde/kdatepicker.h b/noncore/apps/tinykate/libkate/microkde/kdatepicker.h
new file mode 100644
index 0000000..8fe8d66
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kdatepicker.h
@@ -0,0 +1,177 @@
1/* -*- C++ -*-
2 This file is part of the KDE libraries
3 Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
4 (C) 1998-2001 Mirko Boehm (mirko@kde.org)
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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#ifndef MICROKDE_KDATEPICKER_H
21#define MICROKDE_KDATEPICKER_H
22#include <qdatetime.h>
23#include <qframe.h>
24
25class QLineEdit;
26class QToolButton;
27class KDateValidator;
28class KDateTable;
29
30/**
31 * Provides a widget for calendar date input.
32 *
33 * Different from the
34 * previous versions, it now emits two types of signals, either
35 * @ref dateSelected() or @ref dateEntered() (see documentation for both
36 * signals).
37 *
38 * A line edit has been added in the newer versions to allow the user
39 * to select a date directly by entering numbers like 19990101
40 * or 990101.
41 *
42 * @image kdatepicker.png KDatePicker
43 *
44 * @version $Id$
45 * @author Tim Gilman, Mirko Boehm
46 *
47 * @short A date selection widget.
48 **/
49class KDatePicker: public QFrame
50{
51 Q_OBJECT
52public:
53 /** The usual constructor. The given date will be displayed
54 * initially.
55 **/
56 KDatePicker(QWidget *parent=0,
57 QDate=QDate::currentDate(),
58 const char *name=0);
59 /**
60 * The destructor.
61 **/
62 virtual ~KDatePicker();
63
64 /** The size hint for date pickers. The size hint recommends the
65 * minimum size of the widget so that all elements may be placed
66 * without clipping. This sometimes looks ugly, so when using the
67 * size hint, try adding 28 to each of the reported numbers of
68 * pixels.
69 **/
70 QSize sizeHint() const;
71
72 /**
73 * Sets the date.
74 *
75 * @returns @p false and does not change anything
76 * if the date given is invalid.
77 **/
78 bool setDate(const QDate&);
79
80 /**
81 * Returns the selected date.
82 * @deprecated
83 **/
84 const QDate& getDate() const;
85
86 /**
87 * @returns the selected date.
88 */
89 const QDate &date() const;
90
91 /**
92 * Enables or disables the widget.
93 **/
94 void setEnabled(bool);
95
96 /**
97 * Sets the font size of the widgets elements.
98 **/
99 void setFontSize(int);
100 /**
101 * Returns the font size of the widget elements.
102 */
103 int fontSize() const
104 { return fontsize; }
105
106protected:
107 /// the resize event
108 void resizeEvent(QResizeEvent*);
109 /// the year forward button
110 QToolButton *yearForward;
111 /// the year backward button
112 QToolButton *yearBackward;
113 /// the month forward button
114 QToolButton *monthForward;
115 /// the month backward button
116 QToolButton *monthBackward;
117 /// the button for selecting the month directly
118 QToolButton *selectMonth;
119 /// the button for selecting the year directly
120 QToolButton *selectYear;
121 /// the line edit to enter the date directly
122 QLineEdit *line;
123 /// the validator for the line edit:
124 KDateValidator *val;
125 /// the date table
126 KDateTable *table;
127 /// the size calculated during resize events
128 // QSize sizehint;
129 /// the widest month string in pixels:
130 QSize maxMonthRect;
131protected slots:
132 void dateChangedSlot(QDate);
133 void tableClickedSlot();
134 void monthForwardClicked();
135 void monthBackwardClicked();
136 void yearForwardClicked();
137 void yearBackwardClicked();
138 void selectMonthClicked();
139 void selectYearClicked();
140 void lineEnterPressed();
141signals:
142 /** This signal is emitted each time the selected date is changed.
143 * Usually, this does not mean that the date has been entered,
144 * since the date also changes, for example, when another month is
145 * selected.
146 * @see dateSelected
147 */
148 void dateChanged(QDate);
149 /** This signal is emitted each time a day has been selected by
150 * clicking on the table (hitting a day in the current month). It
151 * has the same meaning as dateSelected() in older versions of
152 * KDatePicker.
153 */
154 void dateSelected(QDate);
155 /** This signal is emitted when enter is pressed and a VALID date
156 * has been entered before into the line edit. Connect to both
157 * dateEntered() and dateSelected() to receive all events where the
158 * user really enters a date.
159 */
160 void dateEntered(QDate);
161 /** This signal is emitted when the day has been selected by
162 * clicking on it in the table.
163 */
164 void tableClicked();
165
166private:
167 /// the font size for the widget
168 int fontsize;
169
170protected:
171 virtual void virtual_hook( int id, void* data );
172private:
173 class KDatePickerPrivate;
174 KDatePickerPrivate *d;
175};
176
177#endif // KDATEPICKER_H
diff --git a/noncore/apps/tinykate/libkate/microkde/kdatetbl.cpp b/noncore/apps/tinykate/libkate/microkde/kdatetbl.cpp
new file mode 100644
index 0000000..c56991d
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kdatetbl.cpp
@@ -0,0 +1,718 @@
1/* -*- C++ -*-
2 This file is part of the KDE libraries
3 Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
4 (C) 1998-2001 Mirko Boehm (mirko@kde.org)
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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/////////////////// KDateTable widget class //////////////////////
22//
23// Copyright (C) 1997 Tim D. Gilman
24// (C) 1998-2001 Mirko Boehm
25// Written using Qt (http://www.troll.no) for the
26// KDE project (http://www.kde.org)
27//
28// This is a support class for the KDatePicker class. It just
29// draws the calender table without titles, but could theoretically
30// be used as a standalone.
31//
32// When a date is selected by the user, it emits a signal:
33// dateSelected(QDate)
34
35#include <kglobal.h>
36#include <kglobalsettings.h>
37#include <kapplication.h>
38#include <klocale.h>
39#include <kdebug.h>
40#include <knotifyclient.h>
41#include "kdatetbl.h"
42#include <qdatetime.h>
43#include <qstring.h>
44#include <qpen.h>
45#include <qpainter.h>
46#include <qdialog.h>
47#include <assert.h>
48#include <qapplication.h>
49
50KDateValidator::KDateValidator(QWidget* parent, const char* name)
51 : QValidator(parent, name)
52{
53}
54
55QValidator::State
56KDateValidator::validate(QString& text, int&) const
57{
58 QDate temp;
59 // ----- everything is tested in date():
60 return date(text, temp);
61}
62
63QValidator::State
64KDateValidator::date(const QString& text, QDate& d) const
65{
66 QDate tmp = KGlobal::locale()->readDate(text);
67 if (!tmp.isNull())
68 {
69 d = tmp;
70 return Acceptable;
71 } else
72 return Valid;
73}
74
75void
76KDateValidator::fixup( QString& ) const
77{
78
79}
80
81KDateTable::KDateTable(QWidget *parent, QDate date_, const char* name, WFlags f)
82 : QGridView(parent, name, f)
83{
84 setFontSize(10);
85 if(!date_.isValid())
86 {
87 kdDebug() << "KDateTable ctor: WARNING: Given date is invalid, using current date." << endl;
88 date_=QDate::currentDate();
89 }
90 setFocusPolicy( QWidget::StrongFocus );
91 setNumRows(7); // 6 weeks max + headline
92 setNumCols(7); // 7 days a week
93 setHScrollBarMode(AlwaysOff);
94 setVScrollBarMode(AlwaysOff);
95#if 0
96 viewport()->setEraseColor(lightGray);
97#endif
98 setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth
99}
100
101void
102KDateTable::paintCell(QPainter *painter, int row, int col)
103{
104 QRect rect;
105 QString text;
106 QPen pen;
107 int w=cellWidth();
108 int h=cellHeight();
109 int pos;
110 QBrush brushBlue(blue);
111 QBrush brushLightblue(lightGray);
112 QFont font=KGlobalSettings::generalFont();
113 // -----
114 font.setPointSize(fontsize);
115 if(row==0)
116 { // we are drawing the headline
117 font.setBold(true);
118 painter->setFont(font);
119 bool normalday = true;
120 QString daystr;
121 if (KGlobal::locale()->weekStartsMonday())
122 {
123 daystr = KGlobal::locale()->weekDayName(col+1, true);
124 if (col == 5 || col == 6)
125 normalday = false;
126 } else {
127 daystr = KGlobal::locale()->weekDayName(col==0? 7 : col, true);
128 if (col == 0 || col == 6)
129 normalday = false;
130 }
131 if (!normalday)
132 {
133 painter->setPen(lightGray);
134 painter->setBrush(brushLightblue);
135 painter->drawRect(0, 0, w, h);
136 painter->setPen(blue);
137 } else {
138 painter->setPen(blue);
139 painter->setBrush(brushBlue);
140 painter->drawRect(0, 0, w, h);
141 painter->setPen(white);
142 }
143 painter->drawText(0, 0, w, h-1, AlignCenter,
144 daystr, -1, &rect);
145 painter->setPen(black);
146 painter->moveTo(0, h-1);
147 painter->lineTo(w-1, h-1);
148 // ----- draw the weekday:
149 } else {
150 painter->setFont(font);
151 pos=7*(row-1)+col;
152 if (KGlobal::locale()->weekStartsMonday())
153 pos++;
154 if(pos<firstday || (firstday+numdays<=pos))
155 { // we are either
156 // ° painting a day of the previous month or
157 // ° painting a day of the following month
158 if(pos<firstday)
159 { // previous month
160 text.setNum(numDaysPrevMonth+pos-firstday+1);
161 } else { // following month
162 text.setNum(pos-firstday-numdays+1);
163 }
164 painter->setPen(gray);
165 } else { // paint a day of the current month
166 text.setNum(pos-firstday+1);
167 painter->setPen(black);
168 }
169
170 pen=painter->pen();
171 if(firstday+date.day()-1==pos)
172 {
173 if(hasFocus())
174 { // draw the currently selected date
175 painter->setPen(red);
176 painter->setBrush(darkRed);
177 pen=white;
178 } else {
179 painter->setPen(darkGray);
180 painter->setBrush(darkGray);
181 pen=white;
182 }
183 } else {
184 painter->setBrush(lightGray);
185 painter->setPen(lightGray);
186 }
187 painter->drawRect(0, 0, w, h);
188 painter->setPen(pen);
189 painter->drawText(0, 0, w, h, AlignCenter, text, -1, &rect);
190 }
191 if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
192 if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
193}
194
195void
196KDateTable::keyPressEvent( QKeyEvent *e )
197{
198 if ( e->key() == Qt::Key_Prior ) {
199 if ( date.month() == 1 ) {
200 KNotifyClient::beep();
201 return;
202 }
203 int day = date.day();
204 if ( day > 27 )
205 while ( !QDate::isValid( date.year(), date.month()-1, day ) )
206 day--;
207 setDate(QDate(date.year(), date.month()-1, day));
208 return;
209 }
210 if ( e->key() == Qt::Key_Next ) {
211 if ( date.month() == 12 ) {
212 KNotifyClient::beep();
213 return;
214 }
215 int day = date.day();
216 if ( day > 27 )
217 while ( !QDate::isValid( date.year(), date.month()+1, day ) )
218 day--;
219 setDate(QDate(date.year(), date.month()+1, day));
220 return;
221 }
222
223 int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0;
224
225 int temp=firstday+date.day()-dayoff;
226 int pos = temp;
227
228 if ( e->key() == Qt::Key_Up ) {
229 pos -= 7;
230 }
231 if ( e->key() == Qt::Key_Down ) {
232 pos += 7;
233 }
234 if ( e->key() == Qt::Key_Left ) {
235 pos--;
236 }
237 if ( e->key() == Qt::Key_Right ) {
238 pos++;
239 }
240
241 if(pos+dayoff<=firstday)
242 { // this day is in the previous month
243 KNotifyClient::beep();
244 return;
245 }
246 if(firstday+numdays<pos+dayoff)
247 { // this date is in the next month
248 KNotifyClient::beep(i18n( "Month not long enough" ));
249 return;
250 }
251
252 if ( pos == temp )
253 return;
254
255 setDate(QDate(date.year(), date.month(), pos-firstday+dayoff));
256 updateCell(temp/7+1, temp%7); // Update the previously selected cell
257 updateCell(pos/7+1, pos%7); // Update the selected cell
258 assert(QDate(date.year(), date.month(), pos-firstday+dayoff).isValid());
259}
260
261void
262KDateTable::viewportResizeEvent(QResizeEvent * e)
263{
264 QGridView::viewportResizeEvent(e);
265
266 setCellWidth(viewport()->width()/7);
267 setCellHeight(viewport()->height()/7);
268}
269
270void
271KDateTable::setFontSize(int size)
272{
273 int count;
274 QFontMetrics metrics(fontMetrics());
275 QRect rect;
276 // ----- store rectangles:
277 fontsize=size;
278 // ----- find largest day name:
279 maxCell.setWidth(0);
280 maxCell.setHeight(0);
281 for(count=0; count<7; ++count)
282 {
283 rect=metrics.boundingRect(KGlobal::locale()->weekDayName(count+1, true));
284 maxCell.setWidth(QMAX(maxCell.width(), rect.width()));
285 maxCell.setHeight(QMAX(maxCell.height(), rect.height()));
286 }
287 // ----- compare with a real wide number and add some space:
288 rect=metrics.boundingRect(QString::fromLatin1("88"));
289 maxCell.setWidth(QMAX(maxCell.width()+2, rect.width()));
290 maxCell.setHeight(QMAX(maxCell.height()+4, rect.height()));
291}
292
293void
294KDateTable::contentsMousePressEvent(QMouseEvent *e)
295{
296 if(e->type()!=QEvent::MouseButtonPress)
297 { // the KDatePicker only reacts on mouse press events:
298 return;
299 }
300 if(!isEnabled())
301 {
302 KNotifyClient::beep();
303 return;
304 }
305
306 int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0;
307 // -----
308 int row, col, pos, temp;
309 QPoint mouseCoord;
310 // -----
311 mouseCoord = e->pos();
312 row=rowAt(mouseCoord.y());
313 col=columnAt(mouseCoord.x());
314 if(row<0 || col<0)
315 { // the user clicked on the frame of the table
316 return;
317 }
318 pos=7*(row-1)+col+1;
319 if(pos+dayoff<=firstday)
320 { // this day is in the previous month
321 KNotifyClient::beep();
322 return;
323 }
324 if(firstday+numdays<pos+dayoff)
325 { // this date is in the next month
326 KNotifyClient::beep();
327 return;
328 }
329 temp=firstday+date.day()-dayoff-1;
330 setDate(QDate(date.year(), date.month(), pos-firstday+dayoff));
331 updateCell(temp/7+1, temp%7); // Update the previously selected cell
332 updateCell(row, col); // Update the selected cell
333 // assert(QDate(date.year(), date.month(), pos-firstday+dayoff).isValid());
334 emit(tableClicked());
335}
336
337bool
338KDateTable::setDate(const QDate& date_)
339{
340 bool changed=false;
341 QDate temp;
342 // -----
343 if(!date_.isValid())
344 {
345 kdDebug() << "KDateTable::setDate: refusing to set invalid date." << endl;
346 return false;
347 }
348 if(date!=date_)
349 {
350 date=date_;
351 changed=true;
352 }
353 temp.setYMD(date.year(), date.month(), 1);
354 firstday=temp.dayOfWeek();
355 if(firstday==1) firstday=8;
356 numdays=date.daysInMonth();
357 if(date.month()==1)
358 { // set to december of previous year
359 temp.setYMD(date.year()-1, 12, 1);
360 } else { // set to previous month
361 temp.setYMD(date.year(), date.month()-1, 1);
362 }
363 numDaysPrevMonth=temp.daysInMonth();
364 if(changed)
365 {
366 repaintContents(false);
367 }
368 emit(dateChanged(date));
369 return true;
370}
371
372const QDate&
373KDateTable::getDate() const
374{
375 return date;
376}
377
378void KDateTable::focusInEvent( QFocusEvent *e )
379{
380 repaintContents(false);
381 QGridView::focusInEvent( e );
382}
383
384void KDateTable::focusOutEvent( QFocusEvent *e )
385{
386 repaintContents(false);
387 QGridView::focusOutEvent( e );
388}
389
390QSize
391KDateTable::sizeHint() const
392{
393 if(maxCell.height()>0 && maxCell.width()>0)
394 {
395 return QSize(maxCell.width()*numCols()+2*frameWidth(),
396 (maxCell.height()+2)*numRows()+2*frameWidth());
397 } else {
398 kdDebug() << "KDateTable::sizeHint: obscure failure - " << endl;
399 return QSize(-1, -1);
400 }
401}
402
403KDateInternalMonthPicker::KDateInternalMonthPicker
404(int fontsize, QWidget* parent, const char* name)
405 : QGridView(parent, name),
406 result(0) // invalid
407{
408 QRect rect;
409 QFont font;
410 // -----
411 activeCol = -1;
412 activeRow = -1;
413 font=KGlobalSettings::generalFont();
414 font.setPointSize(fontsize);
415 setFont(font);
416 setHScrollBarMode(AlwaysOff);
417 setVScrollBarMode(AlwaysOff);
418 setFrameStyle(QFrame::NoFrame);
419 setNumRows(4);
420 setNumCols(3);
421 // enable to find drawing failures:
422 // setTableFlags(Tbl_clipCellPainting);
423#if 0
424 viewport()->setEraseColor(lightGray); // for consistency with the datepicker
425#endif
426 // ----- find the preferred size
427 // (this is slow, possibly, but unfortunatly it is needed here):
428 QFontMetrics metrics(font);
429 for(int i=1; i <= 12; ++i)
430 {
431 rect=metrics.boundingRect(KGlobal::locale()->monthName(i, false));
432 if(max.width()<rect.width()) max.setWidth(rect.width());
433 if(max.height()<rect.height()) max.setHeight(rect.height());
434 }
435
436}
437
438QSize
439KDateInternalMonthPicker::sizeHint() const
440{
441 return QSize((max.width()+6)*numCols()+2*frameWidth(),
442 (max.height()+6)*numRows()+2*frameWidth());
443}
444
445int
446KDateInternalMonthPicker::getResult() const
447{
448 return result;
449}
450
451void
452KDateInternalMonthPicker::setupPainter(QPainter *p)
453{
454 p->setPen(black);
455}
456
457void
458KDateInternalMonthPicker::viewportResizeEvent(QResizeEvent*)
459{
460 setCellWidth(width()/3);
461 setCellHeight(height()/4);
462}
463
464void
465KDateInternalMonthPicker::paintCell(QPainter* painter, int row, int col)
466{
467 int index;
468 QString text;
469 // ----- find the number of the cell:
470 index=3*row+col+1;
471 text=KGlobal::locale()->monthName(index, false);
472 painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text);
473 if ( activeCol == col && activeRow == row )
474 painter->drawRect( 0, 0, cellWidth(), cellHeight() );
475}
476
477void
478KDateInternalMonthPicker::contentsMousePressEvent(QMouseEvent *e)
479{
480 if(!isEnabled() || e->button() != LeftButton)
481 {
482 KNotifyClient::beep();
483 return;
484 }
485 // -----
486 int row, col;
487 QPoint mouseCoord;
488 // -----
489 mouseCoord = e->pos();
490 row=rowAt(mouseCoord.y());
491 col=columnAt(mouseCoord.x());
492
493 if(row<0 || col<0)
494 { // the user clicked on the frame of the table
495 activeCol = -1;
496 activeRow = -1;
497 } else {
498 activeCol = col;
499 activeRow = row;
500 updateCell( row, col /*, false */ );
501 }
502}
503
504void
505KDateInternalMonthPicker::contentsMouseMoveEvent(QMouseEvent *e)
506{
507 if (e->state() & LeftButton)
508 {
509 int row, col;
510 QPoint mouseCoord;
511 // -----
512 mouseCoord = e->pos();
513 row=rowAt(mouseCoord.y());
514 col=columnAt(mouseCoord.x());
515 int tmpRow = -1, tmpCol = -1;
516 if(row<0 || col<0)
517 { // the user clicked on the frame of the table
518 if ( activeCol > -1 )
519 {
520 tmpRow = activeRow;
521 tmpCol = activeCol;
522 }
523 activeCol = -1;
524 activeRow = -1;
525 } else {
526 bool differentCell = (activeRow != row || activeCol != col);
527 if ( activeCol > -1 && differentCell)
528 {
529 tmpRow = activeRow;
530 tmpCol = activeCol;
531 }
532 if ( differentCell)
533 {
534 activeRow = row;
535 activeCol = col;
536 updateCell( row, col /*, false */ ); // mark the new active cell
537 }
538 }
539 if ( tmpRow > -1 ) // repaint the former active cell
540 updateCell( tmpRow, tmpCol /*, true */ );
541 }
542}
543
544void
545KDateInternalMonthPicker::contentsMouseReleaseEvent(QMouseEvent *e)
546{
547 if(!isEnabled())
548 {
549 return;
550 }
551 // -----
552 int row, col, pos;
553 QPoint mouseCoord;
554 // -----
555 mouseCoord = e->pos();
556 row=rowAt(mouseCoord.y());
557 col=columnAt(mouseCoord.x());
558 if(row<0 || col<0)
559 { // the user clicked on the frame of the table
560 emit(closeMe(0));
561 }
562 pos=3*row+col+1;
563 result=pos;
564 emit(closeMe(1));
565}
566
567
568
569KDateInternalYearSelector::KDateInternalYearSelector
570(int fontsize, QWidget* parent, const char* name)
571 : QLineEdit(parent, name),
572 val(new QIntValidator(this)),
573 result(0)
574{
575 QFont font;
576 // -----
577 font=KGlobalSettings::generalFont();
578 font.setPointSize(fontsize);
579 setFont(font);
580#if 0
581 setFrameStyle(QFrame::NoFrame);
582#endif
583 // we have to respect the limits of QDate here, I fear:
584 val->setRange(0, 8000);
585 setValidator(val);
586 connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot()));
587}
588
589void
590KDateInternalYearSelector::yearEnteredSlot()
591{
592 bool ok;
593 int year;
594 QDate date;
595 // ----- check if this is a valid year:
596 year=text().toInt(&ok);
597 if(!ok)
598 {
599 KNotifyClient::beep();
600 return;
601 }
602 date.setYMD(year, 1, 1);
603 if(!date.isValid())
604 {
605 KNotifyClient::beep();
606 return;
607 }
608 result=year;
609 emit(closeMe(1));
610}
611
612int
613KDateInternalYearSelector::getYear()
614{
615 return result;
616}
617
618void
619KDateInternalYearSelector::setYear(int year)
620{
621 QString temp;
622 // -----
623 temp.setNum(year);
624 setText(temp);
625}
626
627KPopupFrame::KPopupFrame(QWidget* parent, const char* name)
628 : QFrame(parent, name, WType_Popup),
629 result(0), // rejected
630 main(0)
631{
632 setFrameStyle(QFrame::Box|QFrame::Raised);
633 setMidLineWidth(2);
634}
635
636void
637KPopupFrame::keyPressEvent(QKeyEvent* e)
638{
639 if(e->key()==Key_Escape)
640 {
641 result=0; // rejected
642 qApp->exit_loop();
643 }
644}
645
646void
647KPopupFrame::close(int r)
648{
649 result=r;
650 qApp->exit_loop();
651}
652
653void
654KPopupFrame::setMainWidget(QWidget* m)
655{
656 main=m;
657 if(main!=0)
658 {
659 resize(main->width()+2*frameWidth(), main->height()+2*frameWidth());
660 }
661}
662
663void
664KPopupFrame::resizeEvent(QResizeEvent*)
665{
666 if(main!=0)
667 {
668 main->setGeometry(frameWidth(), frameWidth(),
669 width()-2*frameWidth(), height()-2*frameWidth());
670 }
671}
672
673void
674KPopupFrame::popup(const QPoint &pos)
675{
676 // Make sure the whole popup is visible.
677 QRect d = QApplication::desktop()->frameGeometry();
678 int x = pos.x();
679 int y = pos.y();
680 int w = width();
681 int h = height();
682 if (x+w > d.x()+d.width())
683 x = d.width() - w;
684 if (y+h > d.y()+d.height())
685 y = d.height() - h;
686 if (x < d.x())
687 x = 0;
688 if (y < d.y())
689 y = 0;
690
691 // Pop the thingy up.
692 move(x, y);
693 show();
694}
695
696int
697KPopupFrame::exec(QPoint pos)
698{
699 popup(pos);
700 repaint();
701 qApp->enter_loop();
702 hide();
703 return result;
704}
705
706int
707KPopupFrame::exec(int x, int y)
708{
709 return exec(QPoint(x, y));
710}
711
712void KPopupFrame::virtual_hook( int, void* )
713{ /*BASE::virtual_hook( id, data );*/ }
714
715void KDateTable::virtual_hook( int, void* )
716{ /*BASE::virtual_hook( id, data );*/ }
717
718#include "kdatetbl.moc"
diff --git a/noncore/apps/tinykate/libkate/microkde/kdatetbl.h b/noncore/apps/tinykate/libkate/microkde/kdatetbl.h
new file mode 100644
index 0000000..df7b7ef
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kdatetbl.h
@@ -0,0 +1,308 @@
1/* -*- C++ -*-
2 This file is part of the KDE libraries
3 Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
4 (C) 1998-2001 Mirko Boehm (mirko@kde.org)
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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#ifndef KDATETBL_H
21#define KDATETBL_H
22
23#include <qvalidator.h>
24#include <qgridview.h>
25#include <qlineedit.h>
26#include <qdatetime.h>
27
28/**
29* A table containing month names. It is used to pick a month directly.
30* @internal
31* @version $Id$
32* @author Tim Gilman, Mirko Boehm
33*/
34class KDateInternalMonthPicker : public QGridView
35{
36 Q_OBJECT
37protected:
38 /**
39 * Store the month that has been clicked [1..12].
40 */
41 int result;
42 /**
43 * the cell under mouse cursor when LBM is pressed
44 */
45 short int activeCol;
46 short int activeRow;
47 /**
48 * Contains the largest rectangle needed by the month names.
49 */
50 QRect max;
51signals:
52 /**
53 * This is send from the mouse click event handler.
54 */
55 void closeMe(int);
56public:
57 /**
58 * The constructor.
59 */
60 KDateInternalMonthPicker(int fontsize, QWidget* parent, const char* name=0);
61 /**
62 * The size hint.
63 */
64 QSize sizeHint() const;
65 /**
66 * Return the result. 0 means no selection (reject()), 1..12 are the
67 * months.
68 */
69 int getResult() const;
70protected:
71 /**
72 * Set up the painter.
73 */
74 void setupPainter(QPainter *p);
75 /**
76 * The resize event.
77 */
78 void viewportResizeEvent(QResizeEvent*);
79 /**
80 * Paint a cell. This simply draws the month names in it.
81 */
82 virtual void paintCell(QPainter* painter, int row, int col);
83 /**
84 * Catch mouse click and move events to paint a rectangle around the item.
85 */
86 void contentsMousePressEvent(QMouseEvent *e);
87 void contentsMouseMoveEvent(QMouseEvent *e);
88 /**
89 * Emit monthSelected(int) when a cell has been released.
90 */
91 void contentsMouseReleaseEvent(QMouseEvent *e);
92
93private:
94 class KDateInternalMonthPrivate;
95 KDateInternalMonthPrivate *d;
96};
97
98/** Year selection widget.
99* @internal
100* @version $Id$
101* @author Tim Gilman, Mirko Boehm
102*/
103class KDateInternalYearSelector : public QLineEdit
104{
105 Q_OBJECT
106protected:
107 QIntValidator *val;
108 int result;
109public slots:
110 void yearEnteredSlot();
111signals:
112 void closeMe(int);
113public:
114 KDateInternalYearSelector(int fontsize,
115 QWidget* parent=0,
116 const char* name=0);
117 int getYear();
118 void setYear(int year);
119
120private:
121 class KDateInternalYearPrivate;
122 KDateInternalYearPrivate *d;
123};
124
125/**
126 * Frame with popup menu behaviour.
127 * @author Tim Gilman, Mirko Boehm
128 * @version $Id$
129 */
130class KPopupFrame : public QFrame
131{
132 Q_OBJECT
133protected:
134 /**
135 * The result. It is returned from exec() when the popup window closes.
136 */
137 int result;
138 /**
139 * Catch key press events.
140 */
141 void keyPressEvent(QKeyEvent* e);
142 /**
143 * The only subwidget that uses the whole dialog window.
144 */
145 QWidget *main;
146public slots:
147 /**
148 * Close the popup window. This is called from the main widget, usually.
149 * @p r is the result returned from exec().
150 */
151 void close(int r);
152public:
153 /**
154 * The contructor. Creates a dialog without buttons.
155 */
156 KPopupFrame(QWidget* parent=0, const char* name=0);
157 /**
158 * Set the main widget. You cannot set the main widget from the constructor,
159 * since it must be a child of the frame itselfes.
160 * Be careful: the size is set to the main widgets size. It is up to you to
161 * set the main widgets correct size before setting it as the main
162 * widget.
163 */
164 void setMainWidget(QWidget* m);
165 /**
166 * The resize event. Simply resizes the main widget to the whole
167 * widgets client size.
168 */
169 void resizeEvent(QResizeEvent*);
170 /**
171 * Open the popup window at position pos.
172 */
173 void popup(const QPoint &pos);
174 /**
175 * Execute the popup window.
176 */
177 int exec(QPoint p);
178 /**
179 * Dito.
180 */
181 int exec(int x, int y);
182
183private:
184
185 virtual bool close(bool alsoDelete) { return QFrame::close(alsoDelete); }
186protected:
187 virtual void virtual_hook( int id, void* data );
188private:
189 class KPopupFramePrivate;
190 KPopupFramePrivate *d;
191};
192
193/**
194* Validates user-entered dates.
195*/
196class KDateValidator : public QValidator
197{
198public:
199 KDateValidator(QWidget* parent=0, const char* name=0);
200 virtual State validate(QString&, int&) const;
201 virtual void fixup ( QString & input ) const;
202 State date(const QString&, QDate&) const;
203};
204
205/**
206 * Date selection table.
207 * This is a support class for the KDatePicker class. It just
208 * draws the calender table without titles, but could theoretically
209 * be used as a standalone.
210 *
211 * When a date is selected by the user, it emits a signal:
212 * dateSelected(QDate)
213 *
214 * @internal
215 * @version $Id$
216 * @author Tim Gilman, Mirko Boehm
217 */
218class KDateTable : public QGridView
219{
220 Q_OBJECT
221public:
222 /**
223 * The constructor.
224 */
225 KDateTable(QWidget *parent=0,
226 QDate date=QDate::currentDate(),
227 const char* name=0, WFlags f=0);
228 /**
229 * Returns a recommended size for the widget.
230 * To save some time, the size of the largest used cell content is
231 * calculated in each paintCell() call, since all calculations have
232 * to be done there anyway. The size is stored in maxCell. The
233 * sizeHint() simply returns a multiple of maxCell.
234 */
235 virtual QSize sizeHint() const;
236 /**
237 * Set the font size of the date table.
238 */
239 void setFontSize(int size);
240 /**
241 * Select and display this date.
242 */
243 bool setDate(const QDate&);
244 const QDate& getDate() const;
245
246
247protected:
248 /**
249 * Paint a cell.
250 */
251 virtual void paintCell(QPainter*, int, int);
252 /**
253 * Handle the resize events.
254 */
255 virtual void viewportResizeEvent(QResizeEvent *);
256 /**
257 * React on mouse clicks that select a date.
258 */
259 virtual void contentsMousePressEvent(QMouseEvent *);
260 virtual void keyPressEvent( QKeyEvent *e );
261 virtual void focusInEvent( QFocusEvent *e );
262 virtual void focusOutEvent( QFocusEvent *e );
263 /**
264 * The font size of the displayed text.
265 */
266 int fontsize;
267 /**
268 * The currently selected date.
269 */
270 QDate date;
271 /**
272 * The day of the first day in the month [1..7].
273 */
274 int firstday;
275 /**
276 * The number of days in the current month.
277 */
278 int numdays;
279 /**
280 * The number of days in the previous month.
281 */
282 int numDaysPrevMonth;
283 /**
284 * unused
285 */
286 bool unused_hasSelection;
287 /**
288 * Save the size of the largest used cell content.
289 */
290 QRect maxCell;
291signals:
292 /**
293 * The selected date changed.
294 */
295 void dateChanged(QDate);
296 /**
297 * A date has been selected by clicking on the table.
298 */
299 void tableClicked();
300
301protected:
302 virtual void virtual_hook( int id, void* data );
303private:
304 class KDateTablePrivate;
305 KDateTablePrivate *d;
306};
307
308#endif // KDATETBL_H
diff --git a/noncore/apps/tinykate/libkate/microkde/kdebug.h b/noncore/apps/tinykate/libkate/microkde/kdebug.h
new file mode 100644
index 0000000..9042644
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kdebug.h
@@ -0,0 +1,112 @@
1#ifndef MINIKDE_KDEBUG_H
2#define MINIKDE_KDEBUG_H
3
4#include <stdio.h>
5
6#include <qstring.h>
7
8class kdbgstream;
9typedef kdbgstream & (*KDBGFUNC)(kdbgstream &); // manipulator function
10
11class kdbgstream {
12 public:
13 kdbgstream(unsigned int _area, unsigned int _level, bool _print = true) :
14 area(_area), level(_level), print(_print) { }
15 kdbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print = true) :
16 output(QString::fromLatin1(initialString)), area(_area), level(_level), print(_print) { }
17 ~kdbgstream()
18 {
19 if (!output.isEmpty()) {
20 fprintf(stderr,"ASSERT: debug output not ended with \\n\n");
21 *this << "\n";
22 }
23 }
24 kdbgstream &operator<<(bool i) {
25 if (!print) return *this;
26 output += QString::fromLatin1(i ? "true" : "false");
27 return *this;
28 }
29 kdbgstream &operator<<(short i) {
30 if (!print) return *this;
31 QString tmp; tmp.setNum(i); output += tmp;
32 return *this;
33 }
34 kdbgstream &operator<<(unsigned short i) {
35 if (!print) return *this;
36 QString tmp; tmp.setNum(i); output += tmp;
37 return *this;
38 }
39 kdbgstream &operator<<(char i) {
40 if (!print) return *this;
41 QString tmp; tmp.setNum(int(i)); output += tmp;
42 return *this;
43 }
44 kdbgstream &operator<<(unsigned char i) {
45 if (!print) return *this;
46 QString tmp; tmp.setNum(static_cast<unsigned int>(i)); output += tmp;
47 return *this;
48 }
49
50 kdbgstream &operator<<(int i) {
51 if (!print) return *this;
52 QString tmp; tmp.setNum(i); output += tmp;
53 return *this;
54 }
55 kdbgstream &operator<<(unsigned int i) {
56 if (!print) return *this;
57 QString tmp; tmp.setNum(i); output += tmp;
58 return *this;
59 }
60 kdbgstream &operator<<(long i) {
61 if (!print) return *this;
62 QString tmp; tmp.setNum(i); output += tmp;
63 return *this;
64 }
65 kdbgstream &operator<<(unsigned long i) {
66 if (!print) return *this;
67 QString tmp; tmp.setNum(i); output += tmp;
68 return *this;
69 }
70 kdbgstream &operator<<(const QString& string) {
71 if (!print) return *this;
72 output += string;
73 if (output.at(output.length() -1 ) == '\n')
74 flush();
75 return *this;
76 }
77 kdbgstream &operator<<(const char *string) {
78 if (!print) return *this;
79 output += QString::fromUtf8(string);
80 if (output.at(output.length() - 1) == '\n')
81 flush();
82 return *this;
83 }
84 kdbgstream &operator<<(const QCString& string) {
85 *this << string.data();
86 return *this;
87 }
88 kdbgstream& operator<<(KDBGFUNC f) {
89 if (!print) return *this;
90 return (*f)(*this);
91 }
92 kdbgstream& operator<<(double d) {
93 QString tmp; tmp.setNum(d); output += tmp;
94 return *this;
95 }
96 void flush() {
97 if (output.isEmpty() || !print)
98 return;
99 printf("%s",output.latin1());
100 output = QString::null;
101 }
102 private:
103 QString output;
104 unsigned int area, level;
105 bool print;
106};
107
108inline kdbgstream &endl( kdbgstream &s) { s << "\n"; return s; }
109
110inline kdbgstream kdDebug(int area = 0) { return kdbgstream(area, 0); }
111
112#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kdialog.h b/noncore/apps/tinykate/libkate/microkde/kdialog.h
new file mode 100644
index 0000000..56f6bb0
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kdialog.h
@@ -0,0 +1,16 @@
1#ifndef MINIKDE_KDIALOG_H
2#define MINIKDE_KDIALOG_H
3
4#include <qdialog.h>
5
6class KDialog : public QDialog
7{
8 public:
9 KDialog( QWidget *parent=0, const char *name=0, bool modal=true ) :
10 QDialog( parent, name, modal ) {}
11
12 static int spacingHint() { return 3; }
13 static int marginHint() { return 3; }
14};
15
16#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kdialogbase.cpp b/noncore/apps/tinykate/libkate/microkde/kdialogbase.cpp
new file mode 100644
index 0000000..8caefe0
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kdialogbase.cpp
@@ -0,0 +1,214 @@
1#include <qtabwidget.h>
2#include <qpushbutton.h>
3#include <qlayout.h>
4#include <qframe.h>
5
6#include "klocale.h"
7#include "kdebug.h"
8
9#include "kdialogbase.h"
10
11KDialogBase::KDialogBase()
12{
13}
14
15KDialogBase::KDialogBase( QWidget *parent, const char *name, bool modal,
16 const QString &caption,
17 int buttonMask, ButtonCode defaultButton,
18 bool separator,
19 const QString &user1,
20 const QString &user2,
21 const QString &user3) :
22 KDialog( parent, name, modal )
23{
24 init( caption, buttonMask, user1 );
25}
26
27KDialogBase::KDialogBase( int dialogFace, const QString &caption,
28 int buttonMask, ButtonCode defaultButton,
29 QWidget *parent, const char *name, bool modal,
30 bool separator,
31 const QString &user1,
32 const QString &user2,
33 const QString &user3) :
34 KDialog( parent, name, modal )
35{
36 init( caption, buttonMask, user1 );
37}
38
39KDialogBase::~KDialogBase()
40{
41}
42
43void KDialogBase::init( const QString &caption, int buttonMask,
44 const QString &user1 )
45{
46 mMainWidget = 0;
47 mTabWidget = 0;
48 mPlainPage = 0;
49 mTopLayout = 0;
50
51 if ( !caption.isEmpty() ) {
52 setCaption( caption );
53 }
54
55 if ( buttonMask & User1 ) {
56 mUser1Button = new QPushButton( user1, this );
57 connect( mUser1Button, SIGNAL( clicked() ), SLOT( slotUser1() ) );
58 } else {
59 mUser1Button = 0;
60 }
61
62 if ( buttonMask & Ok ) {
63 mOkButton = new QPushButton( i18n("Ok"), this );
64 connect( mOkButton, SIGNAL( clicked() ), SLOT( slotOk() ) );
65 } else {
66 mOkButton = 0;
67 }
68
69 if ( buttonMask & Apply ) {
70 mApplyButton = new QPushButton( i18n("Apply"), this );
71 connect( mApplyButton, SIGNAL( clicked() ), SLOT( slotApply() ) );
72 } else {
73 mApplyButton = 0;
74 }
75
76 if ( buttonMask & Cancel ) {
77 mCancelButton = new QPushButton( i18n("Cancel"), this );
78 connect( mCancelButton, SIGNAL( clicked() ), SLOT( slotCancel() ) );
79 } else {
80 mCancelButton = 0;
81 }
82
83 if ( buttonMask & Close ) {
84 mCloseButton = new QPushButton( i18n("Close"), this );
85 connect( mCloseButton, SIGNAL( clicked() ), SLOT( slotClose() ) );
86 } else {
87 mCloseButton = 0;
88 }
89}
90
91QTabWidget *KDialogBase::tabWidget()
92{
93 if ( !mTabWidget ) {
94 mTabWidget = new QTabWidget( this );
95 setMainWidget( mTabWidget );
96 }
97 return mTabWidget;
98}
99
100void KDialogBase::initLayout()
101{
102 delete mTopLayout;
103 mTopLayout = new QVBoxLayout( this );
104 mTopLayout->setMargin( marginHint() );
105 mTopLayout->setSpacing( spacingHint() );
106
107 mTopLayout->addWidget( mMainWidget );
108
109 QBoxLayout *buttonLayout = new QHBoxLayout;
110 mTopLayout->addLayout( buttonLayout );
111
112 if ( mUser1Button ) buttonLayout->addWidget( mUser1Button );
113 if ( mOkButton ) buttonLayout->addWidget( mOkButton );
114 if ( mApplyButton ) buttonLayout->addWidget( mApplyButton );
115 if ( mCancelButton ) buttonLayout->addWidget( mCancelButton );
116 if ( mCloseButton ) buttonLayout->addWidget( mCloseButton );
117}
118
119QFrame *KDialogBase::addPage( const QString &name )
120{
121// kdDebug() << "KDialogBase::addPage(): " << name << endl;
122
123 QFrame *frame = new QFrame( tabWidget() );
124 tabWidget()->addTab( frame, name );
125 return frame;
126}
127
128QFrame *KDialogBase::addPage( const QString &name, int, const QPixmap & )
129{
130 return addPage( name );
131}
132
133
134void KDialogBase::setMainWidget( QWidget *widget )
135{
136 kdDebug() << "KDialogBase::setMainWidget()" << endl;
137
138 mMainWidget = widget;
139 initLayout();
140}
141
142
143void KDialogBase::enableButton( ButtonCode id, bool state )
144{
145 QPushButton *button = 0;
146 switch ( id ) {
147 case Ok:
148 button = mOkButton;
149 break;
150 case Apply:
151 button = mApplyButton;
152 break;
153 default:
154 break;
155 }
156 if ( button ) {
157 button->setEnabled( state );
158 }
159}
160
161void KDialogBase::enableButtonOK( bool state )
162{
163 enableButton( Ok, state );
164}
165
166void KDialogBase::enableButtonApply( bool state )
167{
168 enableButton( Apply, state );
169}
170
171
172int KDialogBase::pageIndex( QWidget *widget ) const
173{
174 return 0;
175}
176
177
178bool KDialogBase::showPage( int index )
179{
180 return false;
181}
182
183QFrame *KDialogBase::plainPage()
184{
185 if ( !mPlainPage ) {
186 mPlainPage = new QFrame( this );
187 setMainWidget( mPlainPage );
188 }
189 return mPlainPage;
190}
191
192void KDialogBase::slotOk()
193{
194 accept();
195}
196
197void KDialogBase::slotApply()
198{
199}
200
201void KDialogBase::slotCancel()
202{
203 reject();
204}
205
206void KDialogBase::slotClose()
207{
208 accept();
209}
210
211void KDialogBase::slotUser1()
212{
213 emit user1Clicked();
214}
diff --git a/noncore/apps/tinykate/libkate/microkde/kdialogbase.h b/noncore/apps/tinykate/libkate/microkde/kdialogbase.h
new file mode 100644
index 0000000..dfb85d2
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kdialogbase.h
@@ -0,0 +1,105 @@
1#ifndef MINIKDE_KDIALOGBASE_H
2#define MINIKDE_KDIALOGBASE_H
3
4#include <qframe.h>
5
6#include "kdialog.h"
7
8class QPushButton;
9class QLayout;
10class QTabWidget;
11class QBoxLayout;
12
13class KDialogBase : public KDialog
14{
15 Q_OBJECT
16 public:
17 enum ButtonCode
18 {
19 Help = 0x00000001,
20 Default = 0x00000002,
21 Ok = 0x00000004,
22 Apply = 0x00000008,
23 Try = 0x00000010,
24 Cancel = 0x00000020,
25 Close = 0x00000040,
26 User1 = 0x00000080,
27 User2 = 0x00000100,
28 User3 = 0x00000200,
29 No = 0x00000080,
30 Yes = 0x00000100,
31 Details = 0x00000400,
32 Filler = 0x40000000,
33 Stretch = 0x80000000
34 };
35
36 enum DialogType
37 {
38 TreeList,
39 Tabbed,
40 Plain,
41 Swallow,
42 IconList
43 };
44
45 KDialogBase();
46 KDialogBase( QWidget *parent=0, const char *name=0, bool modal=true,
47 const QString &caption=QString::null,
48 int buttonMask=Ok|Apply|Cancel, ButtonCode defaultButton=Ok,
49 bool separator=false,
50 const QString &user1=QString::null,
51 const QString &user2=QString::null,
52 const QString &user3=QString::null);
53 KDialogBase( int dialogFace, const QString &caption,
54 int buttonMask, ButtonCode defaultButton,
55 QWidget *parent=0, const char *name=0, bool modal=true,
56 bool separator=false,
57 const QString &user1=QString::null,
58 const QString &user2=QString::null,
59 const QString &user3=QString::null);
60 virtual ~KDialogBase();
61
62 QFrame *addPage( const QString & );
63 QFrame *addPage( const QString &, int, const QPixmap & );
64
65 void setMainWidget( QWidget *widget );
66
67 void enableButton( ButtonCode id, bool state );
68 void enableButtonOK( bool state );
69 void enableButtonApply( bool state );
70
71 int pageIndex( QWidget *widget ) const;
72
73 bool showPage( int index );
74
75 QFrame *plainPage();
76
77 signals:
78 void user1Clicked();
79
80 protected slots:
81 virtual void slotOk();
82 virtual void slotApply();
83 virtual void slotCancel();
84 virtual void slotClose();
85 virtual void slotUser1();
86
87 private:
88 QTabWidget *tabWidget();
89 void init( const QString &caption, int buttonMask,
90 const QString &user1=QString::null );
91 void initLayout();
92
93 QWidget *mMainWidget;
94 QTabWidget *mTabWidget;
95 QFrame *mPlainPage;
96 QBoxLayout *mTopLayout;
97
98 QPushButton *mUser1Button;
99 QPushButton *mCloseButton;
100 QPushButton *mOkButton;
101 QPushButton *mApplyButton;
102 QPushButton *mCancelButton;
103};
104
105#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kemailsettings.cpp b/noncore/apps/tinykate/libkate/microkde/kemailsettings.cpp
new file mode 100644
index 0000000..9a9ad84
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kemailsettings.cpp
@@ -0,0 +1,6 @@
1#include "kemailsettings.h"
2
3QString KEMailSettings::getSetting(KEMailSettings::Setting s)
4{
5 return QString::null;
6}
diff --git a/noncore/apps/tinykate/libkate/microkde/kemailsettings.h b/noncore/apps/tinykate/libkate/microkde/kemailsettings.h
new file mode 100644
index 0000000..cf43f17
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kemailsettings.h
@@ -0,0 +1,32 @@
1#ifndef MINIKDE_KEMAILSETTINGS_H
2#define MINIKDE_KEMAILSETTINGS_H
3
4#include <qstring.h>
5
6class KEMailSettings
7{
8 public:
9 enum Setting {
10 ClientProgram,
11 ClientTerminal,
12 RealName,
13 EmailAddress,
14 ReplyToAddress,
15 Organization,
16 OutServer,
17 OutServerLogin,
18 OutServerPass,
19 OutServerType,
20 OutServerCommand,
21 OutServerTLS,
22 InServer,
23 InServerLogin,
24 InServerPass,
25 InServerType,
26 InServerMBXType,
27 InServerTLS
28 };
29 QString getSetting(KEMailSettings::Setting s);
30};
31
32#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kfiledialog.h b/noncore/apps/tinykate/libkate/microkde/kfiledialog.h
new file mode 100644
index 0000000..61781f0
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kfiledialog.h
@@ -0,0 +1,21 @@
1#ifndef MICROKDE_KFILEDIALOG_H
2#define MICROKDE_KFILEDIALOG_H
3
4class KFileDialog
5{
6 public:
7
8 static QString getSaveFileName( const QString &,
9 const QString &, QWidget * )
10 {
11 return QString::null;
12 }
13
14 static QString getOpenFileName( const QString &,
15 const QString &, QWidget * )
16 {
17 return QString::null;
18 }
19};
20
21#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kfontdialog.cpp b/noncore/apps/tinykate/libkate/microkde/kfontdialog.cpp
new file mode 100644
index 0000000..d199936
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kfontdialog.cpp
@@ -0,0 +1,6 @@
1#include "kfontdialog.h"
2
3int KFontDialog::getFont( const QFont & )
4{
5 return 0;
6}
diff --git a/noncore/apps/tinykate/libkate/microkde/kfontdialog.h b/noncore/apps/tinykate/libkate/microkde/kfontdialog.h
new file mode 100644
index 0000000..a4bf23d
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kfontdialog.h
@@ -0,0 +1,14 @@
1#ifndef MINIKDE_KFONTDIALOG_H
2#define MINIKDE_KFONTDIALOG_H
3
4#include <qfont.h>
5
6class KFontDialog
7{
8 public:
9 enum { Accepted };
10
11 static int getFont( const QFont & );
12};
13
14#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kglobal.cpp b/noncore/apps/tinykate/libkate/microkde/kglobal.cpp
new file mode 100644
index 0000000..572768d
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kglobal.cpp
@@ -0,0 +1,49 @@
1#include "kglobal.h"
2
3KLocale *KGlobal::mLocale = 0;
4KConfig *KGlobal::mConfig = 0;
5KIconLoader *KGlobal::mIconLoader = 0;
6KStandardDirs *KGlobal::mDirs = 0;
7
8QString KGlobal::mAppName = "godot";
9
10KLocale *KGlobal::locale()
11{
12 if ( !mLocale ) {
13 mLocale = new KLocale();
14 }
15
16 return mLocale;
17}
18
19KConfig *KGlobal::config()
20{
21 if ( !mConfig ) {
22 mConfig = new KConfig( KStandardDirs::appDir() + mAppName + "rc" );
23 }
24
25 return mConfig;
26}
27
28KIconLoader *KGlobal::iconLoader()
29{
30 if ( !mIconLoader ) {
31 mIconLoader = new KIconLoader();
32 }
33
34 return mIconLoader;
35}
36
37KStandardDirs *KGlobal::dirs()
38{
39 if ( !mDirs ) {
40 mDirs = new KStandardDirs();
41 }
42
43 return mDirs;
44}
45
46void KGlobal::setAppName( const QString &appName )
47{
48 mAppName = appName;
49}
diff --git a/noncore/apps/tinykate/libkate/microkde/kglobal.h b/noncore/apps/tinykate/libkate/microkde/kglobal.h
new file mode 100644
index 0000000..8985bd4
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kglobal.h
@@ -0,0 +1,27 @@
1#ifndef MINIKDE_KGLOBAL_H
2#define MINIKDE_KGLOBAL_H
3
4#include "klocale.h"
5#include "kiconloader.h"
6#include "kstandarddirs.h"
7#include "kconfig.h"
8
9class KGlobal {
10 public:
11 static KLocale *locale();
12 static KConfig *config();
13 static KIconLoader *iconLoader();
14 static KStandardDirs *dirs();
15
16 static void setAppName( const QString & );
17
18 private:
19 static KLocale *mLocale;
20 static KConfig *mConfig;
21 static KIconLoader *mIconLoader;
22 static KStandardDirs *mDirs;
23
24 static QString mAppName;
25};
26
27#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kglobalsettings.cpp b/noncore/apps/tinykate/libkate/microkde/kglobalsettings.cpp
new file mode 100644
index 0000000..cb5fe4c
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kglobalsettings.cpp
@@ -0,0 +1,17 @@
1#include "kglobalsettings.h"
2
3QFont KGlobalSettings::generalFont()
4{
5 return QFont("fixed",12);
6}
7
8QColor KGlobalSettings::baseColor()
9{
10 return Qt::white;
11}
12
13QColor KGlobalSettings::highlightColor()
14{
15 return Qt::blue;
16}
17
diff --git a/noncore/apps/tinykate/libkate/microkde/kglobalsettings.h b/noncore/apps/tinykate/libkate/microkde/kglobalsettings.h
new file mode 100644
index 0000000..34cdb49
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kglobalsettings.h
@@ -0,0 +1,15 @@
1#ifndef MICROKDE_KGLOBALSETTINGS_H
2#define MICROKDE_KGLOBALSETTINGS_H
3
4#include <qfont.h>
5#include <qcolor.h>
6
7class KGlobalSettings
8{
9 public:
10 static QFont generalFont();
11 static QColor baseColor();
12 static QColor highlightColor();
13};
14
15#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kiconloader.cpp b/noncore/apps/tinykate/libkate/microkde/kiconloader.cpp
new file mode 100644
index 0000000..83a2cad
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kiconloader.cpp
@@ -0,0 +1,33 @@
1#include <qpe/resource.h>
2
3#include "kiconloader.h"
4
5QPixmap KIconLoader::loadIcon( const QString &name, int )
6{
7 return Resource::loadPixmap( "kate/" + name );
8}
9
10QString KIconLoader::iconPath( const QString &, int )
11{
12 return QString::null;
13}
14
15QPixmap BarIcon( const QString &name )
16{
17 return Resource::loadPixmap( "kate/" + name );
18}
19
20QPixmap DesktopIcon( const QString &name, int )
21{
22 return Resource::loadPixmap( "kate/" + name );
23}
24
25QPixmap SmallIcon( const QString &name )
26{
27 return Resource::loadPixmap( "kate/" + name );
28}
29
30QPixmap SmallIconSet( const QString &name )
31{
32 return Resource::loadPixmap( "kate/" + name );
33}
diff --git a/noncore/apps/tinykate/libkate/microkde/kiconloader.h b/noncore/apps/tinykate/libkate/microkde/kiconloader.h
new file mode 100644
index 0000000..c4f642e
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kiconloader.h
@@ -0,0 +1,31 @@
1#ifndef MINIKDE_KICONLOADER_H
2#define MINIKDE_KICONLOADER_H
3
4#include <qpixmap.h>
5#include <qstring.h>
6
7class KIcon
8{
9 public:
10 enum Group { NoGroup=-1, Desktop=0, Toolbar, MainToolbar, Small,
11 Panel, LastGroup, User };
12 enum StdSizes { SizeSmall=16, SizeMedium=32, SizeLarge=48 };
13};
14
15class KIconLoader
16{
17 public:
18 QPixmap loadIcon( const QString &name, int );
19
20 QString iconPath( const QString &, int );
21};
22
23QPixmap BarIcon(const QString& name);
24
25QPixmap DesktopIcon(const QString& name, int);
26
27QPixmap SmallIcon(const QString& name);
28
29QPixmap SmallIconSet( const QString &name );
30
31#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/klineedit.h b/noncore/apps/tinykate/libkate/microkde/klineedit.h
new file mode 100644
index 0000000..26956ad
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/klineedit.h
@@ -0,0 +1,13 @@
1#ifndef MINIKDE_KLINEEDIT_H
2#define MINIKDE_KLINEEDIT_H
3
4#include <qlineedit.h>
5
6class KLineEdit : public QLineEdit
7{
8 public:
9 KLineEdit( QWidget *parent=0, const char *name=0 ) :
10 QLineEdit( parent, name ) {}
11};
12
13#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/klineeditdlg.h b/noncore/apps/tinykate/libkate/microkde/klineeditdlg.h
new file mode 100644
index 0000000..4136054
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/klineeditdlg.h
@@ -0,0 +1,8 @@
1#ifndef _mykdelineeditdlg_h_
2#define _mykdelineeditdlg_h_
3
4#include <qinputdialog.h>
5
6#define KLineEditDlg QInputDialog
7
8#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/klistview.h b/noncore/apps/tinykate/libkate/microkde/klistview.h
new file mode 100644
index 0000000..008acbc
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/klistview.h
@@ -0,0 +1,24 @@
1#ifndef MICROKDE_KLISTVIEW_H
2#define MICROKDE_KLISTVIEW_H
3
4#include <qlistview.h>
5#include <qpoint.h>
6#include <qstring.h>
7
8class KConfig;
9
10class KListView : public QListView
11{
12 Q_OBJECT
13 public:
14 KListView( QWidget *parent=0, const char *name=0 )
15 : QListView( parent, name ) {}
16
17 void saveLayout( KConfig *, const QString & ) {}
18 void restoreLayout( KConfig *, const QString & ) {}
19
20 signals:
21 void doubleClicked( QListViewItem *, QPoint, int );
22};
23
24#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/klocale.cpp b/noncore/apps/tinykate/libkate/microkde/klocale.cpp
new file mode 100644
index 0000000..dfdb97a
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/klocale.cpp
@@ -0,0 +1,530 @@
1#include <qregexp.h>
2
3#include "kdebug.h"
4
5#include "klocale.h"
6
7QString i18n(const char *text)
8{
9 return QString( text );
10}
11
12QString i18n(const char *,const char *text)
13{
14 return QString( text );
15}
16
17inline void put_it_in( QChar *buffer, uint& index, const QString &s )
18{
19 for ( uint l = 0; l < s.length(); l++ )
20 buffer[index++] = s.at( l );
21}
22
23inline void put_it_in( QChar *buffer, uint& index, int number )
24{
25 buffer[index++] = number / 10 + '0';
26 buffer[index++] = number % 10 + '0';
27}
28
29static int readInt(const QString &str, uint &pos)
30{
31 if (!str.at(pos).isDigit()) return -1;
32 int result = 0;
33 for (; str.length() > pos && str.at(pos).isDigit(); pos++)
34 {
35 result *= 10;
36 result += str.at(pos).digitValue();
37 }
38
39 return result;
40}
41
42QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const
43{
44 const QString rst = timeFormat();
45
46 // only "pm/am" here can grow, the rest shrinks, but
47 // I'm rather safe than sorry
48 QChar *buffer = new QChar[rst.length() * 3 / 2 + 30];
49
50 uint index = 0;
51 bool escape = false;
52 int number = 0;
53
54 for ( uint format_index = 0; format_index < rst.length(); format_index++ )
55 {
56 if ( !escape )
57 {
58 if ( rst.at( format_index ).unicode() == '%' )
59 escape = true;
60 else
61 buffer[index++] = rst.at( format_index );
62 }
63 else
64 {
65 switch ( rst.at( format_index ).unicode() )
66 {
67 case '%':
68 buffer[index++] = '%';
69 break;
70 case 'H':
71 put_it_in( buffer, index, pTime.hour() );
72 break;
73 case 'I':
74 put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
75 break;
76 case 'M':
77 put_it_in( buffer, index, pTime.minute() );
78 break;
79 case 'S':
80 if (includeSecs)
81 put_it_in( buffer, index, pTime.second() );
82 else
83 {
84 // we remove the seperator sign before the seconds and
85 // assume that works everywhere
86 --index;
87 break;
88 }
89 break;
90 case 'k':
91 number = pTime.hour();
92 case 'l':
93 // to share the code
94 if ( rst.at( format_index ).unicode() == 'l' )
95 number = (pTime.hour() + 11) % 12 + 1;
96 if ( number / 10 )
97 buffer[index++] = number / 10 + '0';
98 buffer[index++] = number % 10 + '0';
99 break;
100 case 'p':
101 {
102 QString s;
103 if ( pTime.hour() >= 12 )
104 put_it_in( buffer, index, i18n("pm") );
105 else
106 put_it_in( buffer, index, i18n("am") );
107 break;
108 }
109 default:
110 buffer[index++] = rst.at( format_index );
111 break;
112 }
113 escape = false;
114 }
115 }
116 QString ret( buffer, index );
117 delete [] buffer;
118 return ret;
119}
120
121QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const
122{
123 const QString rst = shortFormat?dateFormatShort():dateFormat();
124
125 // I'm rather safe than sorry
126 QChar *buffer = new QChar[rst.length() * 3 / 2 + 50];
127
128 unsigned int index = 0;
129 bool escape = false;
130 int number = 0;
131
132 for ( uint format_index = 0; format_index < rst.length(); ++format_index )
133 {
134 if ( !escape )
135 {
136 if ( rst.at( format_index ).unicode() == '%' )
137 escape = true;
138 else
139 buffer[index++] = rst.at( format_index );
140 }
141 else
142 {
143 switch ( rst.at( format_index ).unicode() )
144 {
145 case '%':
146 buffer[index++] = '%';
147 break;
148 case 'Y':
149 put_it_in( buffer, index, pDate.year() / 100 );
150 case 'y':
151 put_it_in( buffer, index, pDate.year() % 100 );
152 break;
153 case 'n':
154 number = pDate.month();
155 case 'e':
156 // to share the code
157 if ( rst.at( format_index ).unicode() == 'e' )
158 number = pDate.day();
159 if ( number / 10 )
160 buffer[index++] = number / 10 + '0';
161 buffer[index++] = number % 10 + '0';
162 break;
163 case 'm':
164 put_it_in( buffer, index, pDate.month() );
165 break;
166 case 'b':
167 put_it_in( buffer, index, monthName(pDate.month(), true) );
168 break;
169 case 'B':
170 put_it_in( buffer, index, monthName(pDate.month(), false) );
171 break;
172 case 'd':
173 put_it_in( buffer, index, pDate.day() );
174 break;
175 case 'a':
176 put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), true) );
177 break;
178 case 'A':
179 put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), false) );
180 break;
181 default:
182 buffer[index++] = rst.at( format_index );
183 break;
184 }
185 escape = false;
186 }
187 }
188 QString ret( buffer, index );
189 delete [] buffer;
190 return ret;
191}
192
193QString KLocale::formatDateTime(const QDateTime &pDateTime,
194 bool shortFormat,
195 bool includeSeconds) const
196{
197 return i18n("concatenation of dates and time", "%1 %2")
198 .arg( formatDate( pDateTime.date(), shortFormat ) )
199 .arg( formatTime( pDateTime.time(), includeSeconds ) );
200}
201
202QString KLocale::formatDateTime(const QDateTime &pDateTime) const
203{
204 return formatDateTime(pDateTime, true);
205}
206
207QDate KLocale::readDate(const QString &intstr, bool* ok) const
208{
209 QDate date;
210 date = readDate(intstr, true, ok);
211 if (date.isValid()) return date;
212 return readDate(intstr, false, ok);
213}
214
215QDate KLocale::readDate(const QString &intstr, bool shortFormat, bool* ok) const
216{
217 QString fmt = (shortFormat ? dateFormatShort() : dateFormat()).simplifyWhiteSpace();
218 return readDate( intstr, fmt, ok );
219}
220
221QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const
222{
223 //kdDebug(173) << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl;
224 QString str = intstr.simplifyWhiteSpace().lower();
225 int day = -1, month = -1;
226 // allow the year to be omitted if not in the format
227 int year = QDate::currentDate().year();
228 uint strpos = 0;
229 uint fmtpos = 0;
230
231 while (fmt.length() > fmtpos || str.length() > strpos)
232 {
233 if ( !(fmt.length() > fmtpos && str.length() > strpos) )
234 goto error;
235
236 QChar c = fmt.at(fmtpos++);
237
238 if (c != '%') {
239 if (c.isSpace())
240 strpos++;
241 else if (c != str.at(strpos++))
242 goto error;
243 continue;
244 }
245
246 // remove space at the begining
247 if (str.length() > strpos && str.at(strpos).isSpace())
248 strpos++;
249
250 c = fmt.at(fmtpos++);
251 switch (c)
252 {
253 case 'a':
254 case 'A':
255 // this will just be ignored
256 { // Cristian Tache: porting to Win: Block added because of "j" redefinition
257 for (int j = 1; j < 8; j++) {
258 QString s = weekDayName(j, c == 'a').lower();
259 int len = s.length();
260 if (str.mid(strpos, len) == s)
261 strpos += len;
262 }
263 break;
264 }
265 case 'b':
266 case 'B':
267 { // Cristian Tache: porting to Win: Block added because of "j" redefinition
268 for (int j = 1; j < 13; j++) {
269 QString s = monthName(j, c == 'b').lower();
270 int len = s.length();
271 if (str.mid(strpos, len) == s) {
272 month = j;
273 strpos += len;
274 }
275 }
276 break;
277 }
278 case 'd':
279 case 'e':
280 day = readInt(str, strpos);
281 if (day < 1 || day > 31)
282 goto error;
283
284 break;
285
286 case 'n':
287 case 'm':
288 month = readInt(str, strpos);
289 if (month < 1 || month > 12)
290 goto error;
291
292 break;
293
294 case 'Y':
295 case 'y':
296 year = readInt(str, strpos);
297 if (year < 0)
298 goto error;
299 // Qt treats a year in the range 0-100 as 1900-1999.
300 // It is nicer for the user if we treat 0-68 as 2000-2068
301 if (year < 69)
302 year += 2000;
303 else if (c == 'y')
304 year += 1900;
305
306 break;
307 }
308 }
309 //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl;
310 if ( year != -1 && month != -1 && day != -1 )
311 {
312 if (ok) *ok = true;
313 return QDate(year, month, day);
314 }
315 error:
316 if (ok) *ok = false;
317 return QDate(); // invalid date
318}
319
320QTime KLocale::readTime(const QString &intstr, bool *ok) const
321{
322 QTime _time;
323 _time = readTime(intstr, true, ok);
324 if (_time.isValid()) return _time;
325 return readTime(intstr, false, ok);
326}
327
328QTime KLocale::readTime(const QString &intstr, bool seconds, bool *ok) const
329{
330 QString str = intstr.simplifyWhiteSpace().lower();
331 QString Format = timeFormat().simplifyWhiteSpace();
332 if (!seconds)
333 Format.replace(QRegExp(QString::fromLatin1(".%S")), QString::null);
334
335 int hour = -1, minute = -1, second = seconds ? -1 : 0; // don't require seconds
336 bool g_12h = false;
337 bool pm = false;
338 uint strpos = 0;
339 uint Formatpos = 0;
340
341 while (Format.length() > Formatpos || str.length() > strpos)
342 {
343 if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error;
344
345 QChar c = Format.at(Formatpos++);
346
347 if (c != '%')
348 {
349 if (c.isSpace())
350 strpos++;
351 else if (c != str.at(strpos++))
352 goto error;
353 continue;
354 }
355
356 // remove space at the begining
357 if (str.length() > strpos && str.at(strpos).isSpace())
358 strpos++;
359
360 c = Format.at(Formatpos++);
361 switch (c)
362 {
363 case 'p':
364 {
365 QString s;
366 s = i18n("pm").lower();
367 int len = s.length();
368 if (str.mid(strpos, len) == s)
369 {
370 pm = true;
371 strpos += len;
372 }
373 else
374 {
375 s = i18n("am").lower();
376 len = s.length();
377 if (str.mid(strpos, len) == s) {
378 pm = false;
379 strpos += len;
380 }
381 else
382 goto error;
383 }
384 }
385 break;
386
387 case 'k':
388 case 'H':
389 g_12h = false;
390 hour = readInt(str, strpos);
391 if (hour < 0 || hour > 23)
392 goto error;
393
394 break;
395
396 case 'l':
397 case 'I':
398 g_12h = true;
399 hour = readInt(str, strpos);
400 if (hour < 1 || hour > 12)
401 goto error;
402
403 break;
404
405 case 'M':
406 minute = readInt(str, strpos);
407 if (minute < 0 || minute > 59)
408 goto error;
409
410 break;
411
412 case 'S':
413 second = readInt(str, strpos);
414 if (second < 0 || second > 59)
415 goto error;
416
417 break;
418 }
419 }
420 if (g_12h)
421 {
422 hour %= 12;
423 if (pm) hour += 12;
424 }
425
426 if (ok) *ok = true;
427 return QTime(hour, minute, second);
428
429 error:
430 if (ok) *ok = false;
431 return QTime(-1, -1, -1); // return invalid date if it didn't work
432 // This will be removed in the near future, since it gives a warning on stderr.
433 // The presence of the bool* (since KDE-3.0) removes the need for an invalid QTime.
434}
435
436bool KLocale::use12Clock() const
437{
438 return false;
439}
440
441bool KLocale::weekStartsMonday() const
442{
443 return true;
444}
445
446QString KLocale::weekDayName(int i,bool shortName) const
447{
448 if ( shortName )
449 switch ( i )
450 {
451 case 1: return i18n("Monday", "Mon");
452 case 2: return i18n("Tuesday", "Tue");
453 case 3: return i18n("Wednesday", "Wed");
454 case 4: return i18n("Thursday", "Thu");
455 case 5: return i18n("Friday", "Fri");
456 case 6: return i18n("Saturday", "Sat");
457 case 7: return i18n("Sunday", "Sun");
458 }
459 else
460 switch ( i )
461 {
462 case 1: return i18n("Monday");
463 case 2: return i18n("Tuesday");
464 case 3: return i18n("Wednesday");
465 case 4: return i18n("Thursday");
466 case 5: return i18n("Friday");
467 case 6: return i18n("Saturday");
468 case 7: return i18n("Sunday");
469 }
470
471 return QString::null;
472}
473
474QString KLocale::monthName(int i,bool shortName) const
475{
476 if ( shortName )
477 switch ( i )
478 {
479 case 1: return i18n("January", "Jan");
480 case 2: return i18n("February", "Feb");
481 case 3: return i18n("March", "Mar");
482 case 4: return i18n("April", "Apr");
483 case 5: return i18n("May short", "May");
484 case 6: return i18n("June", "Jun");
485 case 7: return i18n("July", "Jul");
486 case 8: return i18n("August", "Aug");
487 case 9: return i18n("September", "Sep");
488 case 10: return i18n("October", "Oct");
489 case 11: return i18n("November", "Nov");
490 case 12: return i18n("December", "Dec");
491 }
492 else
493 switch (i)
494 {
495 case 1: return i18n("January");
496 case 2: return i18n("February");
497 case 3: return i18n("March");
498 case 4: return i18n("April");
499 case 5: return i18n("May long", "May");
500 case 6: return i18n("June");
501 case 7: return i18n("July");
502 case 8: return i18n("August");
503 case 9: return i18n("September");
504 case 10: return i18n("October");
505 case 11: return i18n("November");
506 case 12: return i18n("December");
507 }
508
509 return QString::null;
510}
511
512QString KLocale::country() const
513{
514 return QString::null;
515}
516
517QString KLocale::dateFormat() const
518{
519 return "%A %d %B %Y";
520}
521
522QString KLocale::dateFormatShort() const
523{
524 return "%d.%m.%Y";
525}
526
527QString KLocale::timeFormat() const
528{
529 return "%H:%M:%S";
530}
diff --git a/noncore/apps/tinykate/libkate/microkde/klocale.h b/noncore/apps/tinykate/libkate/microkde/klocale.h
new file mode 100644
index 0000000..cff200b
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/klocale.h
@@ -0,0 +1,53 @@
1#ifndef MINIKDE_KLOCALE_H
2#define MINIKDE_KLOCALE_H
3
4#include <qstring.h>
5#include <qdatetime.h>
6
7
8#define I18N_NOOP(x) x
9
10
11QString i18n(const char *text);
12QString i18n(const char *hint, const char *text);
13
14// Qt3's uic generates i18n( "msg", "comment" ) calls which conflict
15// with our i18n method. we use uic -tr tr2i18n to redirect
16// to the right i18n() function
17inline QString tr2i18n(const char* message, const char* =0) {
18 return i18n( message);
19}
20
21class KLocale
22{
23 public:
24
25 QString formatDate(const QDate &pDate, bool shortFormat = false) const;
26 QString formatTime(const QTime &pTime, bool includeSecs = false) const;
27 QString formatDateTime(const QDateTime &pDateTime) const;
28 QString formatDateTime(const QDateTime &pDateTime,
29 bool shortFormat,
30 bool includeSecs = false) const;
31
32 QDate readDate(const QString &str, bool* ok = 0) const;
33 QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const;
34 QTime readTime(const QString &str, bool* ok = 0) const;
35
36 bool use12Clock() const;
37 bool weekStartsMonday() const;
38
39 QString weekDayName(int,bool=false) const;
40 QString monthName(int,bool=false) const;
41
42 QString country() const;
43
44 QString dateFormat() const;
45 QString dateFormatShort() const;
46 QString timeFormat() const;
47
48 private:
49 QTime readTime(const QString &str, bool seconds, bool *ok) const;
50 QDate readDate(const QString &str, bool shortFormat, bool *ok) const;
51};
52
53#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kmessagebox.cpp b/noncore/apps/tinykate/libkate/microkde/kmessagebox.cpp
new file mode 100644
index 0000000..fd305cd
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kmessagebox.cpp
@@ -0,0 +1,90 @@
1#include "kmessagebox.h"
2#include "klocale.h"
3
4#include <qmessagebox.h>
5
6void KMessageBox::sorry( QWidget *parent,
7 const QString &text,
8 const QString &caption, bool )
9{
10 QString cap = caption;
11
12 if (cap.isEmpty()) {
13 cap = i18n("Sorry");
14 }
15
16 QMessageBox::warning( parent, cap, text );
17}
18
19int KMessageBox::warningYesNoCancel(QWidget *parent, const QString &text)
20{
21 int result = QMessageBox::warning(parent,i18n("Warning"),text,QMessageBox::Yes,
22 QMessageBox::No, QMessageBox::Cancel);
23 switch (result) {
24 case QMessageBox::Yes: return Yes;
25 case QMessageBox::No: return No;
26 case QMessageBox::Cancel: return Cancel;
27 }
28}
29
30int KMessageBox::questionYesNo(QWidget *parent,
31 const QString &text,
32 const QString &textYes,
33 const QString &textNo,
34 bool notify=true )
35{
36 int result =QMessageBox::warning(parent,i18n("Question"),text,textYes,textNo);
37 if ( result == 0 ) return KMessageBox::Yes;
38 return KMessageBox::No;
39}
40
41
42
43
44int KMessageBox::warningContinueCancel( QWidget *parent,
45 const QString &text,
46 const QString &caption,
47 const QString &buttonContinue,
48 const QString &dontAskAgainName,
49 bool notify )
50{
51 QString cap = caption;
52
53 if (cap.isEmpty()) {
54 cap = i18n("Warning");
55 }
56
57 int result = QMessageBox::warning( parent, cap, text, i18n("Ok"),
58 i18n("Cancel") );
59
60 if ( result == 0 ) return KMessageBox::Continue;
61 return KMessageBox::Cancel;
62}
63
64void KMessageBox::error( QWidget *parent,
65 const QString &text,
66 const QString &caption, bool notify )
67{
68 QString cap = caption;
69
70 if (cap.isEmpty()) {
71 cap = i18n("Error");
72 }
73
74 QMessageBox::critical( parent, cap, text );
75}
76
77void KMessageBox::information( QWidget *parent,
78 const QString &text,
79 const QString &caption,
80 const QString &,
81 bool )
82{
83 QString cap = caption;
84
85 if (cap.isEmpty()) {
86 cap = i18n("Information");
87 }
88
89 QMessageBox::information( parent, cap, text );
90}
diff --git a/noncore/apps/tinykate/libkate/microkde/kmessagebox.h b/noncore/apps/tinykate/libkate/microkde/kmessagebox.h
new file mode 100644
index 0000000..d7c971f
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kmessagebox.h
@@ -0,0 +1,46 @@
1#ifndef MINIKDE_KMESSAGEBOX_H
2#define MINIKDE_KMESSAGEBOX_H
3
4#include <qstring.h>
5
6class QWidget;
7
8class KMessageBox
9{
10 public:
11 enum { Ok = 1, Cancel = 2, Yes = 3, No = 4, Continue = 5 };
12
13 static void sorry(QWidget *parent,
14 const QString &text,
15 const QString &caption = QString::null, bool notify=true);
16
17 static int warningContinueCancel(QWidget *parent,
18 const QString &text,
19 const QString &caption = QString::null,
20 const QString &buttonContinue = QString::null,
21 const QString &dontAskAgainName = QString::null,
22 bool notify=true );
23
24
25 static int questionYesNo(QWidget *parent,
26 const QString &text,
27 const QString &textYes,
28 const QString &textNo,
29 bool notify=true );
30
31 static int warningYesNoCancel(QWidget *parent, const QString &text);
32
33
34 static void error(QWidget *parent,
35 const QString &text,
36 const QString &caption = QString::null, bool notify=true);
37
38 static void information(QWidget *parent,
39 const QString &text,
40 const QString &caption = QString::null,
41 const QString &dontShowAgainName = QString::null,
42 bool notify=true);
43};
44
45
46#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/knotifyclient.h b/noncore/apps/tinykate/libkate/microkde/knotifyclient.h
new file mode 100644
index 0000000..118026a
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/knotifyclient.h
@@ -0,0 +1,14 @@
1#ifndef MINIKDE_KNOTIFYCLIENT_H
2#define MINIKDE_KNOTIFYCLIENT_H
3
4#include <qstring.h>
5
6class KNotifyClient
7{
8 public:
9
10 static void beep() {}
11 static void beep( const QString & ) {}
12};
13
14#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/knumvalidator.cpp b/noncore/apps/tinykate/libkate/microkde/knumvalidator.cpp
new file mode 100644
index 0000000..67e632f
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/knumvalidator.cpp
@@ -0,0 +1,8 @@
1#include <qlineedit.h>
2
3#include "knumvalidator.h"
4
5KIntValidator::KIntValidator( int a, int b, QLineEdit *c )
6 : QIntValidator( a, b, c )
7{
8}
diff --git a/noncore/apps/tinykate/libkate/microkde/knumvalidator.h b/noncore/apps/tinykate/libkate/microkde/knumvalidator.h
new file mode 100644
index 0000000..92eda01
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/knumvalidator.h
@@ -0,0 +1,14 @@
1#ifndef MINIKDE_KNUMVALIDATOR_H
2#define MINIKDE_KNUMVALIDATOR_H
3
4#include <qvalidator.h>
5
6class QLineEdit;
7
8class KIntValidator : public QIntValidator
9{
10 public:
11 KIntValidator( int, int, QLineEdit * );
12};
13
14#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kpopupmenu.h b/noncore/apps/tinykate/libkate/microkde/kpopupmenu.h
new file mode 100644
index 0000000..fb35943
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kpopupmenu.h
@@ -0,0 +1,8 @@
1#ifndef _MYKPOPUPMENU_H_
2#define _MYKPOPUPMENU_H_
3
4#include <qpopupmenu.h>
5
6#define KPopupMenu QPopupMenu
7
8#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kprinter.h b/noncore/apps/tinykate/libkate/microkde/kprinter.h
new file mode 100644
index 0000000..b99d689
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kprinter.h
@@ -0,0 +1,8 @@
1#ifndef MINIKDE_KPRINTER_H
2#define MINIKDE_KPRINTER_H
3
4#include <qprinter.h>
5
6#define KPrinter QPrinter
7
8#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kprocess.cpp b/noncore/apps/tinykate/libkate/microkde/kprocess.cpp
new file mode 100644
index 0000000..62033e9
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kprocess.cpp
@@ -0,0 +1,15 @@
1#include "kprocess.h"
2
3void KProcess::clearArguments()
4{
5}
6
7KProcess & KProcess::operator<<( const QString & )
8{
9 return *this;
10}
11
12bool KProcess::start()
13{
14 return false;
15}
diff --git a/noncore/apps/tinykate/libkate/microkde/kprocess.h b/noncore/apps/tinykate/libkate/microkde/kprocess.h
new file mode 100644
index 0000000..96dce54
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kprocess.h
@@ -0,0 +1,16 @@
1#ifndef MINIKDE_KPROCESS_H
2#define MINIKDE_KPROCESS_H
3
4#include <qobject.h>
5
6class KProcess : public QObject
7{
8 public:
9 void clearArguments();
10
11 KProcess & operator<<( const QString & );
12
13 bool start();
14};
15
16#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/krestrictedline.h b/noncore/apps/tinykate/libkate/microkde/krestrictedline.h
new file mode 100644
index 0000000..200546c
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/krestrictedline.h
@@ -0,0 +1,13 @@
1#ifndef MINIKDE_KRESTRICTEDLINE_H
2#define MINIKDE_KRESTRICTEDLINE_H
3
4#include "klineedit.h"
5
6class KRestrictedLine : public KLineEdit
7{
8 public:
9 KRestrictedLine( QWidget *parent, const char *, const QString & ) :
10 KLineEdit( parent ) {}
11};
12
13#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/krun.cpp b/noncore/apps/tinykate/libkate/microkde/krun.cpp
new file mode 100644
index 0000000..a170add
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/krun.cpp
@@ -0,0 +1,6 @@
1#include "krun.h"
2
3bool KRun::runCommand(const QString &, const QString &, const QString &)
4{
5 return false;
6}
diff --git a/noncore/apps/tinykate/libkate/microkde/krun.h b/noncore/apps/tinykate/libkate/microkde/krun.h
new file mode 100644
index 0000000..1b63cb7
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/krun.h
@@ -0,0 +1,13 @@
1#ifndef MINIKDE_KRUN_H
2#define MINIKDE_KRUN_H
3
4#include <qstring.h>
5
6class KRun
7{
8 public:
9 static bool runCommand(const QString &a, const QString &b=QString::null,
10 const QString &c=QString::null);
11};
12
13#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kseparator.h b/noncore/apps/tinykate/libkate/microkde/kseparator.h
new file mode 100644
index 0000000..9fc0b51
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kseparator.h
@@ -0,0 +1,8 @@
1#ifndef MINIKDE_KSEPARATOR_H
2#define MINIKDE_KSEPARATOR_H
3
4class KSeparator
5{
6};
7
8#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/ksharedptr.h b/noncore/apps/tinykate/libkate/microkde/ksharedptr.h
new file mode 100644
index 0000000..55ed2e9
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/ksharedptr.h
@@ -0,0 +1,142 @@
1/* This file is part of the KDE libraries
2 Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 Boston, MA 02111-1307, USA.
17*/
18#ifndef KSharedPTR_H
19#define KSharedPTR_H
20
21/**
22 * Reference counting for shared objects. If you derive your object
23 * from this class, then you may use it in conjunction with
24 * @ref KSharedPtr to control the lifetime of your object.
25 *
26 * Specifically, all classes that derive from KShared have an internal
27 * counter keeping track of how many other objects have a reference to
28 * their object. If used with @ref KSharedPtr, then your object will
29 * not be deleted until all references to the object have been
30 * released.
31 *
32 * You should probably not ever use any of the methods in this class
33 * directly -- let the @ref KSharedPtr take care of that. Just derive
34 * your class from KShared and forget about it.
35 *
36 * @author Waldo Bastian <bastian@kde.org>
37 * @version $Id$
38 */
39class KShared {
40public:
41 /**
42 * Standard constructor. This will initialize the reference count
43 * on this object to 0
44 */
45 KShared() : count(0) { }
46
47 /**
48 * Copy constructor. This will @em not actually copy the objects
49 * but it will initialize the reference count on this object to 0
50 */
51 KShared( const KShared & ) : count(0) { }
52
53 /**
54 * Overloaded assignment operator
55 */
56 KShared &operator=(const KShared & ) { return *this; }
57
58 /**
59 * Increases the reference count by one
60 */
61 void _KShared_ref() { count++; }
62
63 /**
64 * Releases a reference (decreases the reference count by one). If
65 * the count goes to 0, this object will delete itself
66 */
67 void _KShared_unref() { if (!--count) delete this; }
68
69 /**
70 * Return the current number of references held
71 *
72 * @return Number of references
73 */
74 int _KShared_count() { return count; }
75
76protected:
77 virtual ~KShared() { }
78 int count; // ### KDE 3.0: rename to something like _KShared_count
79 // or make private
80};
81
82/**
83 * Can be used to control the lifetime of an object that has derived
84 * @ref KShared. As long a someone holds a KSharedPtr on some KShared
85 * object it won't become deleted but is deleted once its reference
86 * count is 0. This struct emulates C++ pointers perfectly. So just
87 * use it like a simple C++ pointer.
88 *
89 * KShared and KSharedPtr are preferred over QShared / QSharedPtr
90 * since they are more safe.
91 *
92 * @author Waldo Bastian <bastian@kde.org>
93 * @version $Id$
94 */
95template< class T >
96struct KSharedPtr
97{
98public:
99 KSharedPtr()
100 : ptr(0) { }
101 KSharedPtr( T* t )
102 : ptr(t) { if ( ptr ) ptr->_KShared_ref(); }
103 KSharedPtr( const KSharedPtr& p )
104 : ptr(p.ptr) { if ( ptr ) ptr->_KShared_ref(); }
105
106 ~KSharedPtr() { if ( ptr ) ptr->_KShared_unref(); }
107
108 KSharedPtr<T>& operator= ( const KSharedPtr<T>& p ) {
109 if ( ptr == p.ptr ) return *this;
110 if ( ptr ) ptr->_KShared_unref();
111 ptr = p.ptr;
112 if ( ptr ) ptr->_KShared_ref();
113 return *this;
114 }
115 KSharedPtr<T>& operator= ( T* p ) {
116 if ( ptr == p ) return *this;
117 if ( ptr ) ptr->_KShared_unref();
118 ptr = p;
119 if ( ptr ) ptr->_KShared_ref();
120 return *this;
121 }
122 bool operator== ( const KSharedPtr<T>& p ) const { return ( ptr == p.ptr ); }
123 bool operator!= ( const KSharedPtr<T>& p ) const { return ( ptr != p.ptr ); }
124 bool operator== ( const T* p ) const { return ( ptr == p ); }
125 bool operator!= ( const T* p ) const { return ( ptr != p ); }
126 bool operator!() const { return ( ptr == 0 ); }
127 operator T*() const { return ptr; }
128
129 T* data() { return ptr; }
130 const T* data() const { return ptr; }
131
132 const T& operator*() const { return *ptr; }
133 T& operator*() { return *ptr; }
134 const T* operator->() const { return ptr; }
135 T* operator->() { return ptr; }
136
137 int count() const { return ptr->_KShared_count(); } // for debugging purposes
138private:
139 T* ptr;
140};
141
142#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/ksimpleconfig.h b/noncore/apps/tinykate/libkate/microkde/ksimpleconfig.h
new file mode 100644
index 0000000..1efd982
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/ksimpleconfig.h
@@ -0,0 +1,12 @@
1#ifndef MINIKDE_KSIMPLECONFIG_H
2#define MINIKDE_KSIMPLECONFIG_H
3
4#include "kconfig.h"
5
6class KSimpleConfig : public KConfig
7{
8 public:
9 KSimpleConfig( const QString &file ) : KConfig( file ) {}
10};
11
12#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kstandarddirs.cpp b/noncore/apps/tinykate/libkate/microkde/kstandarddirs.cpp
new file mode 100644
index 0000000..befa667
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kstandarddirs.cpp
@@ -0,0 +1,39 @@
1#include "kdebug.h"
2
3#include "kstandarddirs.h"
4
5QString KStandardDirs::mAppDir = QString::null;
6
7QString locate( const char *type, const QString& filename )
8{
9 QString path = KStandardDirs::appDir() + type + "_" + filename;
10
11 kdDebug() << "locate: '" << path << "'" << endl;
12
13 return path;
14}
15
16QString locateLocal( const char *type, const QString& filename )
17{
18 return locate( type, filename );
19}
20
21QStringList KStandardDirs::findAllResources( const QString &, const QString &, bool, bool)
22{
23 QStringList list;
24 list.append("/cpp.xml");
25 return list;
26// return QStringList();
27}
28
29QString KStandardDirs::findResourceDir( const QString &, const QString & )
30{
31 return QString::null;
32}
33
34void KStandardDirs::setAppDir( const QString &appDir )
35{
36 mAppDir = appDir;
37
38 if ( mAppDir.right( 1 ) != "/" ) mAppDir += "/";
39}
diff --git a/noncore/apps/tinykate/libkate/microkde/kstandarddirs.h b/noncore/apps/tinykate/libkate/microkde/kstandarddirs.h
new file mode 100644
index 0000000..fa5e460
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kstandarddirs.h
@@ -0,0 +1,23 @@
1#ifndef MINIKDE_KSTANDARDDIRS_H
2#define MINIKDE_KSTANDARDDIRS_H
3
4#include <qstring.h>
5#include <qstringlist.h>
6
7QString locate( const char *type, const QString& filename );
8QString locateLocal( const char *type, const QString& filename );
9
10class KStandardDirs
11{
12 public:
13 QStringList findAllResources( const QString &, const QString &, bool, bool);
14 QString findResourceDir( const QString &, const QString & );
15
16 static void setAppDir( const QString & );
17 static QString appDir() { return mAppDir; }
18
19 private:
20 static QString mAppDir;
21};
22
23#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kstaticdeleter.h b/noncore/apps/tinykate/libkate/microkde/kstaticdeleter.h
new file mode 100644
index 0000000..190f3e4
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kstaticdeleter.h
@@ -0,0 +1,35 @@
1/*
2 * This file is part of the KDE Libraries
3 * Copyright (C) 2000 Stephan Kulow <coolo@kde.org>
4 * 2001 KDE Team
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 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
23#ifndef _KSTATIC_DELETER_H_
24#define _KSTATIC_DELETER_H_
25
26template<class type>
27class KStaticDeleter
28{
29 public:
30 KStaticDeleter() {};
31 type *setObject( type *obj, bool isArray = false) { return obj; }
32 virtual ~KStaticDeleter() {};
33};
34
35#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kstddirs.h b/noncore/apps/tinykate/libkate/microkde/kstddirs.h
new file mode 100644
index 0000000..fa5e460
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kstddirs.h
@@ -0,0 +1,23 @@
1#ifndef MINIKDE_KSTANDARDDIRS_H
2#define MINIKDE_KSTANDARDDIRS_H
3
4#include <qstring.h>
5#include <qstringlist.h>
6
7QString locate( const char *type, const QString& filename );
8QString locateLocal( const char *type, const QString& filename );
9
10class KStandardDirs
11{
12 public:
13 QStringList findAllResources( const QString &, const QString &, bool, bool);
14 QString findResourceDir( const QString &, const QString & );
15
16 static void setAppDir( const QString & );
17 static QString appDir() { return mAppDir; }
18
19 private:
20 static QString mAppDir;
21};
22
23#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/ktempfile.cpp b/noncore/apps/tinykate/libkate/microkde/ktempfile.cpp
new file mode 100644
index 0000000..b9166bd
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/ktempfile.cpp
@@ -0,0 +1,25 @@
1#include <qtextstream.h>
2
3#include "ktempfile.h"
4
5KTempFile::KTempFile()
6{
7}
8
9KTempFile::KTempFile( const QString &filename, const QString &extension )
10{
11}
12
13void KTempFile::setAutoDelete( bool )
14{
15}
16
17QString KTempFile::name()
18{
19 return QString::null;
20}
21
22QTextStream *KTempFile::textStream()
23{
24 return 0;
25}
diff --git a/noncore/apps/tinykate/libkate/microkde/ktempfile.h b/noncore/apps/tinykate/libkate/microkde/ktempfile.h
new file mode 100644
index 0000000..20dfa82
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/ktempfile.h
@@ -0,0 +1,20 @@
1#ifndef MINIKDE_KTEMPFILE_H
2#define MINIKDE_KTEMPFILE_H
3
4#include <qstring.h>
5
6class QTextStream;
7
8class KTempFile
9{
10 public:
11 KTempFile();
12 KTempFile( const QString &filename, const QString &extension );
13
14 void setAutoDelete( bool );
15 QString name();
16
17 QTextStream *textStream();
18};
19
20#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kunload.h b/noncore/apps/tinykate/libkate/microkde/kunload.h
new file mode 100644
index 0000000..1c3d00f
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kunload.h
@@ -0,0 +1,6 @@
1#ifndef MINIKDE_KUNLOAD_H
2#define MINIKDE_KUNLOAD_H
3
4#define _UNLOAD(p)
5
6#endif
diff --git a/noncore/apps/tinykate/libkate/microkde/kurlrequester.cpp b/noncore/apps/tinykate/libkate/microkde/kurlrequester.cpp
new file mode 100644
index 0000000..29d173b
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kurlrequester.cpp
@@ -0,0 +1,14 @@
1#include "klineedit.h"
2
3#include "kurlrequester.h"
4
5KURLRequester::KURLRequester( QWidget *parent ) :
6 QWidget( parent )
7{
8 mLineEdit = new KLineEdit( parent );
9}
10
11KLineEdit *KURLRequester::lineEdit()
12{
13 return mLineEdit;
14}
diff --git a/noncore/apps/tinykate/libkate/microkde/kurlrequester.h b/noncore/apps/tinykate/libkate/microkde/kurlrequester.h
new file mode 100644
index 0000000..8b39196
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/microkde/kurlrequester.h
@@ -0,0 +1,17 @@
1#ifndef MINIKDE_KURLREQUESTER_H
2#define MINIKDE_KURLREQUESTER_H
3
4class KLineEdit;
5
6class KURLRequester : public QWidget
7{
8 public:
9 KURLRequester( QWidget *parent );
10
11 KLineEdit *lineEdit();
12
13 private:
14 KLineEdit *mLineEdit;
15};
16
17#endif
diff --git a/noncore/apps/tinykate/libkate/qt3back/README b/noncore/apps/tinykate/libkate/qt3back/README
new file mode 100644
index 0000000..e329aee
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/qt3back/README
@@ -0,0 +1,12 @@
1This is a backport I got from Scott Manson, I just added an additional #ifndef QT_NO_COMPAT in the .cpp file around a match
2function
3
4*************************
5 This is ___NOT___ the original version from Trolltech, so don't blame them if something is wrong.
6*************************
7
8Use it at your own risk, neither Trolltech, Scott Manson nor I take any responsibility, if it damages your system or causes
9unexpected behaviour or causes loss of data
10
11Joseph Wenninger
12<jowenn@kde.org>
diff --git a/noncore/apps/tinykate/libkate/qt3back/qregexp3.cpp b/noncore/apps/tinykate/libkate/qt3back/qregexp3.cpp
new file mode 100644
index 0000000..a2c680f
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/qt3back/qregexp3.cpp
@@ -0,0 +1,3767 @@
1/****************************************************************************
2** $Id$
3**
4** Implementation of QRegExp class
5**
6** Created : 950126
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the tools module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37#if QT_VERSION >=300
38#error QRegExp3 is now in QT 3 use QRegExp instead
39#endif
40
41#include "qarray.h"
42#include "qbitarray.h"
43#include "qcache.h"
44#include "qintdict.h"
45#include "qmap.h"
46#if QT_VERSION < 300
47#include "./qregexp3.h"
48#else
49#include "qregexp.h"
50#endif
51#include "qstring.h"
52#include "qtl.h"
53#include "qvector.h"
54
55#include <limits.h>
56
57/*
58 WARNING! Be sure to read qregexp.tex before modifying this file.
59*/
60
61/*!
62 \class QRegExp3 qregexp.h
63
64 \brief The QRegExp class provides pattern matching using regular expressions.
65
66 \ingroup tools
67 \ingroup misc
68 \ingroup shared
69
70
71 Regular expressions, "regexps", provide a way to find patterns
72 within text. This is useful in many contexts, for example:
73
74 <ol>
75 <li>\e Validation. A regexp can be used to check whether a piece of
76 text meets some criteria, e.g. is an integer or contains no
77 whitespace.
78 <li>\e Searching. Regexps provide a much more powerful means of
79 searching text than simple string matching does. For example we can
80 create a regexp which says "find one of the words 'mail', 'letter'
81 or 'correspondence' but not any of the words 'email', 'mailman'
82 'mailer', 'letterbox' etc."
83 <li><em>Search and Replace.</em> A regexp can be used to replace a
84 pattern with a piece of text, for example replace all occurrences of
85 '&' with '\&amp;' except where the '&' is already followed by
86 'amp;'.
87 <li><em>String Splitting.</em> A regexp can be used to identify
88 where a string should be split into its component fields, e.g.
89 splitting tab delimited strings.
90 </ol>
91
92 We present a very brief introduction to regexps, a description of
93 Qt's regexp language, some code examples, and finally the function
94 documentation. QRegExp is modelled on Perl's regexp engine and fully
95 supports Unicode. QRegExp may also be used in the weaker 'wildcard'
96 (globbing) mode which works in a similar way to command shells. A
97 good text on regexps is <i>Mastering Regular Expressions: Powerful
98 Techniques for Perl and Other Tools</i> by Jeffrey E. Friedl, ISBN
99 1565922573.
100
101 Experienced regexp users may prefer to skip the introduction and
102 go directly to the relevant information:
103
104 <ul>
105 <li><a href="#characters-and-abbreviations-for-sets-of-characters">
106 Characters and Abbreviations for Sets of Characters</a>
107 <li><a href="#sets-of-characters">Sets of Characters</a>
108 <li><a href="#quantifiers">Quantifiers</a>
109 <li><a href="#capturing-text">Capturing Text</a>
110 <li><a href="#assertions">Assertions</a>
111 <li><a href="#wildcard-matching">Wildcard Matching (globbing)</a>
112 <li><a href="#perl-users">Notes for Perl Users</a>
113 <li><a href="#code-examples">Code Examples</a>
114 <li><a href="#member-function-documentation">Member Function Documentation</a>
115 </ul>
116
117 <b>Introduction</b>
118
119 Regexps are built up from expressions, quantifiers and assertions.
120 The simplest form of expression is simply a character, e.g. <b>x</b>
121 or <b>5</b>. An expression can also be a set of characters. For
122 example, <b>[ABCD]</b>, will match an <b>A</b> or a <b>B</b> or a
123 <b>C</b> or a <b>D</b>. As a shorthand we could write this as
124 <b>[A-D]</b>. If we want to match any of the captital letters in the
125 English alphabet we can write <b>[A-Z]</b>. A quantifier tells the
126 regexp engine how many occurrences of the expression we want, e.g.
127 <b>x{1,1}</b> means match an <b>x</b> which occurs at least once and
128 at most once. We'll look at assertions and more complex expressions
129 later. Note that regexps cannot be used to check for balanced
130 brackets or tags (unless you know the maximum level of nesting).
131
132
133 We'll start by writing a regexp to match integers in the range 0 to
134 99. We will require at least one digit so we will start with
135 <b>[0-9]{1,1}</b> which means match a digit exactly once. This
136 regexp alone will match integers in the range 0 to 9. To match one
137 or two digits we can increase the maximum number of occurrences so
138 the regexp becomes <b>[0-9]{1,2}</b> meaning match a digit at least
139 once and at most twice. However, this regexp as it stands will not
140 match correctly. This regexp will match one or two digits \e within
141 a string. To ensure that we match against the whole string we must
142 use the anchor assertions. We need <b>^</b> (caret) which when it is
143 the first character in the regexp means that the regexp must match
144 from the beginning of the string. And we also need <b>$</b> (dollar)
145 which when it is the last character in the regexp means that the
146 regexp must match until the end of the string. So now our regexp is
147 <b>^[0-9]{1,2}$</b>. Note that assertions do not match any
148 characters.
149
150 If you've seen regexps elsewhere they may have looked different from
151 the one above. This is because some sets of characters and some
152 quantifiers are so common that they have special symbols to
153 represent them. <b>[0-9]</b> can be replaced with the symbol
154 <b>\d</b>. The quantifier to match exactly one occurrence,
155 <b>{1,1}</b>, can be replaced with the expression itself. This means
156 that <b>x{1,1}</b> is exactly the same as <b>x</b> alone. So our 0
157 to 99 matcher could be written: <b>^\d{1,2}$</b>, although most
158 people would write it <b>^\d\d?$</b>. The <b>?</b> is the same as
159 the quantifier <b>{0,1}</b>, i.e. a minimum of no occurrences a
160 maximum of one occurrence. This is used to make an expression
161 optional. The regexp <b>^\d\d?$</b> means "from the beginning of the
162 string match one digit followed by zero or one digits and then the
163 end of the string".
164
165 Our second example is matching the words 'mail', 'letter' or
166 'correspondence' but without matching 'email', 'mailman', 'mailer',
167 'letterbox' etc. We'll start by just matching 'mail'. In full the
168 regexp is, <b>m{1,1}a{1,1}i{1,1}l{1,1}</b>, but since an expression
169 itself is automatically quantified by <b>{1,1}</b> we can simply
170 write this as <b>mail</b>; an 'm' followed by an 'a' followed by an
171 'i' followed by an 'l'. The symbol '|' (bar) is used for \e
172 alternation, so our regexp now becomes
173 <b>mail|letter|correspondence</b> which means match 'mail' \e or
174 'letter' \e or 'correspondence'. Whilst this regexp will find the
175 words we want it will also find words we don't want such as 'email'.
176 We will start by putting our regexp in parenthesis
177 <b>(mail|letter|correspondence)</b>. Parenthesis have two effects,
178 firstly they group expressions together and secondly they identify
179 parts of the regexp that we wish to <a href="#capturing-text">capture</a>.
180 Our regexp still matches any of the three words but now they are
181 grouped together as a unit. This is useful for building up more
182 complex regexps. It is also useful because it allows us to examine
183 which of the words actually matched. We need to use another
184 assertion, this time <b>\b</b> "word boundary":
185 <b>\b(mail|letter|correspondence)\b</b>. This regexp means "match a
186 word boundary followed by the expression in parenthesis followed by
187 another word boundary". The <b>\b</b> assertion matches at a \e
188 position in the regexp not a \e character in the regexp. A word
189 boundary is any non-word character such as a space a newline or the
190 beginning or end of the string.
191
192 For our third example we want to replace ampersands with the HTML
193 entity '\&amp;'. The regexp to match is simple: <b>\&</b>, i.e.
194 match one ampersand. Unfortunately this will mess up our text if
195 some of the ampersands have already been turned into HTML entities.
196 So what we really want to say is replace an ampersand providing it
197 is not followed by 'amp;'. For this we need the negative lookahead
198 assertion and our regexp becomes: <b>\&(?!amp;)</b>. The negative
199 lookahead assertion is introduced with '(?!' and finishes at the
200 ')'. It means that the text it contains, 'amp;' in our example, must
201 \e not follow the expression that preceeds it.
202
203 Regexps provide a rich language that can be used in a variety of
204 ways. For example suppose we want to count all the occurrences of
205 'Eric' and 'Eirik' in a string. Two valid regexps to match these are
206 <b>\\</b><b>b(Eric|Eirik)</b><b>\\</b><b>b</b> and
207 <b>\\</b><b>bEi?ri[ck]</b><b>\\</b><b>b</b>. We need the word boundary
208 '\b' so we don't get 'Ericsson' etc. The second regexp actually
209 matches more than we want, 'Eric', 'Erik', 'Eiric' and 'Eirik'.
210
211 We will implement some the examples above in the
212 <a href="#code-examples">code examples</a> section.
213
214 <a name="characters-and-abbreviations-for-sets-of-characters">
215 <b>Characters and Abbreviations for Sets of Characters</b></a>
216
217 <ul>
218
219 <li><b>c</b> Any character represents itself unless it has a special regexp
220 meaning. Thus <b>c</b> matches the character \e c.
221
222 <li><b>\\</b><b>c</b> A character that follows a backslash matches the
223 character itself except where mentioned below. For example if you
224 wished to match a literal caret at the beginning of a string you
225 would write <b>\^</b>.
226
227 <li><b>\\</b><b>a</b> This matches the ASCII bell character (BEL, 0x07).
228 <li><b>\\</b><b>f</b> This matches the ASCII form feed character (FF, 0x0C).
229 <li><b>\\</b><b>n</b> This matches the ASCII line feed character (LF, 0x0A), (Unix newline).
230 <li><b>\\</b><b>r</b> This matches the ASCII carriage return character (CR, 0x0D).
231 <li><b>\\</b><b>t</b> This matches the ASCII horizontal tab character (HT, 0x09).
232 <li><b>\\</b><b>v</b> This matches the ASCII vertical tab character (VT, 0x0B).
233 <li><b>\\</b><b>xhhhh</b> This matches the Unicode character corresponding
234 to the hexadecimal number hhhh (between 0x0000 and 0xFFFF). \0ooo
235 (i.e., \zero ooo) matches the ASCII/Latin-1 character corresponding
236 to the octal number ooo (between 0 and 0377).
237 <li><b>. (dot)</b> This matches any character (including newline).
238 <li><b>\\</b><b>d</b> This matches a digit (see QChar::isDigit()).
239 <li><b>\\</b><b>D</b> This matches a non-digit.
240 <li><b>\\</b><b>s</b> This matches a whitespace (see QChar::isSpace()).
241 <li><b>\\</b><b>S</b> This matches a non-whitespace.
242 <li><b>\\</b><b>w</b> This matches a word character (see QChar::isLetterOrNumber()).
243 <li><b>\\</b><b>W</b> This matches a non-word character.
244 <li><b>\\</b><b>n</b> The n<sup>th</sup>
245 <a href="#capturing-text">backreference</a>, e.g. \1, \2, etc.
246 </ul>
247
248 <em>Note that the C++ compiler transforms backslashes in strings so
249 to include a <b>\\</b> in a regexp you will need to enter it twice,
250 i.e. <b>\\</b><b>\\</b>.</em>
251
252 <a name="sets-of-characters"><b>Sets of Characters</b></a>
253
254 Square brackets are used to match any character in the set of
255 characters contained within the square brackets. All the character
256 set abbreviations described above can be used within square
257 brackets. Apart from the character set abbreviations and the
258 following two exceptions no characters have special meanings in
259 square brackets.
260
261 <ul>
262
263 <li><b>^</b> The caret negates the character set if it occurs as the
264 first character, i.e. immediately after the opening square bracket.
265 For example, <b>[abc]</b> matches 'a' or 'b' or 'c', but
266 <b>[^abc]</b> matches anything \e except 'a' or 'b' or 'c'.
267
268 <li><b>-</b> The dash is used to indicate a range of characters, for
269 example <b>[W-Z]</b> matches 'W' or 'X' or 'Y' or 'Z'.
270
271 </ul>
272
273 Using the predefined character set abbreviations is more portable
274 than using character ranges across platforms and languages. For
275 example, <b>[0-9]</b> matches a digit in Western alphabets but
276 <b>\d</b> matches a digit in \e any alphabet.
277
278 Note that in most regexp literature sets of characters are called
279 "character classes".
280
281 <a name="quantifiers"><b>Quantifiers</b></a>
282
283 By default an expression is automatically quantified by
284 <b>{1,1}</b>, i.e. it should occur exactly once. In the following
285 list <b><i>E</i></b> stands for any expression. An expression is a
286 character or an abbreviation for a set of characters or a set of
287 characters in square brackets or any parenthesised expression.
288
289 <ul>
290
291 <li><b><i>E</i>?</b> Matches zero or one occurrence of <i>E</i>.
292 This quantifier means "the previous expression is optional" since it
293 will match whether or not the expression occurs in the string.
294 It is the same as <b><i>E</i>{0,1}</b>. For example <b>dents?</b>
295 will match 'dent' and 'dents'.
296
297 <li><b><i>E</i>+</b> Matches one or more occurrences of <i>E</i>.
298 This is the same as <b><i>E</i>{1,MAXINT}</b>. For example,
299 <b>0+</b> will match '0', '00', '000', etc.
300
301 <li><b><i>E</i>*</b> Matches zero or more occurrences of <i>E</i>.
302 This is the same as <b><i>E</i>{0,MAXINT}</b>. The <b>*</b>
303 quantifier is often used by a mistake. Since it matches \e zero or
304 more occurrences it will match no occurrences at all. For example if
305 we want to match strings that end in whitespace and use the regexp
306 <b>\s*$</b> we would get a match on every string. This is because we
307 have said find zero or more whitespace followed by the end of string,
308 so even strings that don't end in whitespace will match. The regexp
309 we want in this case is <b>\s+$</b> to match strings that have at
310 least one whitespace at the end.
311
312 <li><b><i>E</i>{n}</b> Matches exactly \e n occurrences of the
313 expression. This is the same as repeating the expression \e n times.
314 For example, <b>x{5}</b> is the same as <b>xxxxx</b>. It is also the
315 same as <b><i>E</i>{n,n}</b>, e.g. <b>x{5,5}</b>.
316
317 <li><b><i>E</i>{n,}</b> Matches at least \e n occurrences of the
318 expression. This is the same as <b><i>E</i>{n,MAXINT}</b>.
319
320 <li><b><i>E</i>{,m}</b> Matches at most \e m occurrences of the
321 expression. This is the same as <b><i>E</i>{0,m}</b>.
322
323 <li><b><i>E</i>{n,m}</b> Matches at least \e n occurrences of the
324 expression and at most \e m occurrences of the expression.
325
326 </ul>
327
328 (MAXINT is implementation dependent but will not be smaller than
329 16384.)
330
331 If we wish to apply a quantifier to more than just the preceeding
332 character we can use parenthesis to group characters together in an
333 expression. For example, <b>tag+</b> matches a 't' followed by an
334 'a' followed by at least one 'g', whereas <b>(tag)+</b> matches at
335 least one occurrence of 'tag'.
336
337 Note that quantifiers are "greedy", they will match as much text as
338 they can. For example, <b>0+</b> will match as many zeros as it can
339 from the first zero it finds, e.g. '2.<u>000</u>5'. Quantifiers can
340 be made non-greedy, see setMinimal().
341
342 <a name="capturing-text"><b>Capturing Text</b></a>
343
344 Parenthesis allow us to group elements together so that we can
345 quantify and capture them. For example if we have the expression
346 <b>mail|letter|correspondence</b> that matches a string we know that
347 \e one of the words matched but not which one. Using parenthesis
348 allows us to "capture" whatever is matched within their bounds, so
349 if we used <b>(mail|letter|correspondence)</b> and matched this
350 regexp against the string "I sent you some email" we can use the
351 cap() or capturedTexts() functions to extract the matched
352 characters, in this case 'mail'.
353
354 We can use captured text within the regexp itself. To refer to the
355 captured text we use \e backreferences which are indexed from 1 the
356 same as for cap(). For example we could search for duplicate words
357 in a string using <b>\b(\w+)\W+\1\b</b> which means match a word
358 boundary followed by one or more word characters followed by one or
359 more non-word characters followed by the same text as the first
360 parenthesised expression followed by a word boundary.
361
362 If we want to use parenthesis purely for grouping and not for
363 capturing we use the non-capturing syntax, e.g.
364 <b>(?:green|blue)</b>. Non-capturing parenthesis begin '(?:' and end
365 ')'. In this example we match either 'green' or 'blue' but we do not
366 capture the match so we can only know whether or not we matched but
367 not which color we actually found. Using non-capturing parenthesis
368 is more efficient than using capturing parenthesis since the regexp
369 engine has to do less book-keeping.
370
371 Both capturing and non-capturing parenthesis may be nested.
372
373 <a name="assertions"><b>Assertions</b></a>
374
375 Assertions make some statement about the text at the point where
376 they occur in the regexp but they do not match any characters.
377 In the following list <b><i>E</i></b> stands for any expression.
378
379 <ul>
380 <li><b>^</b> If the caret is the first character in the regexp
381 (apart from opening parenthesis) it signifies the beginning of the
382 string. It has no special meaning elsewhere (except as the first
383 character of a set of characters in square brackets). For example,
384 <b>^#include</b> will only match strings which \e begin with the
385 characters '#include'.
386
387 <li><b>$</b> If the dollar is the last character in the regexp
388 (apart from closing parenthesis) it signifies the end of the string.
389 It has no special meaning elsewhere. For example, <b>\d\s*$</b>
390 will match strings which end with a digit optionally followed by
391 whitespace.
392
393 <li><b>\\</b><b>b</b> A word boundary. For example the regexp
394 <b>\\</b><b>bOK</b>\\</b><b>b</b> means match immediately after a
395 word boundary (e.g. start of string or whitespace) the letter 'O'
396 then the letter 'K' immediately before another word boundary (e.g.
397 end of string or whitespace). But note that the assertion does not
398 actually match any whitespace so if we write
399 <b>(</b><b>\\</b><b>bOK</b>\\</b><b>b)</b> and we have a match it
400 will only contain 'OK' even if the string is "Its <u>OK</u> now".
401
402 <li><b>\\</b><b>B</b> A non-word boundary. This assertion is true
403 wherever <b>\\</b><b>b</b> is false. For example if we searched for
404 <b>\\</b><b>Bon</b>\\</b><b>B</b> in "Left on" the match would fail
405 (space and end of string aren't non-word boundaries), but it would
406 match in "t<u>on</u>ne".
407
408 <li><b>(?=<i>E</i>)</b> Positive lookahead. This assertion is true
409 if the expression matches at this point in the regex. This assertion
410 does not match any characters. For example,
411 <b>^#define\s+(\w+)(?=MAX)</b> will match strings which begin with
412 '#define' followed by at least one whitespace followed by at least
413 one word character followed by 'MAX'. The first set of parenthesis
414 will capture the word character(s) matched. This regexp will not
415 match '#define DEBUG' but will match '#define <u>INT</u>MAX
416 32767'.
417
418 <li><b>(?!<i>E</i>)</b> Negative lookahead. This assertion is true
419 if the expression does not match at this point in the regex. This
420 assertion does not match any characters. For example,
421 <b>^#define\s+(\w+)\s*$</b> will match strings which begin with
422 '#define' followed by at least one whitespace followed by at least
423 one word character optionally followed by whitespace. This regexp
424 will match define's that exist but have no value, i.e. it will not
425 match '#define INTMAX 32767' but it will match '#define <u>DEBUG</u>'.
426
427 </ul>
428
429 <a name="wildcard-matching"><b>Wildcard Matching (globbing)</b></a>
430
431 Most command shells such as \e bash or \e cmd support "file
432 globbing", the ability to identify a group of files by using
433 wildcards. Wildcard matching is much simpler than full regexps and
434 has only four features:
435
436 <ul>
437
438 <li><b>c</b> Any character represents itself apart from those
439 mentioned below. Thus <b>c</b> matches the character \e c.
440
441 <li><b>?</b> This matches any single character. It is the same as
442 <b>.</b> in full regexps.
443
444 <li><b>*</b> This matches zero or more of any characters. It is the
445 same as <b>.*</b> in full regexps.
446
447 <li><b>[...]</b> Sets of characters can be represented in square
448 brackets the same as for full regexps.
449
450 <!-- JASMIN: Are the character classes, \w, etc supported in
451 wildcards? -->
452
453 </ul>
454
455 For example if we are in wildcard mode and have strings which
456 contain filenames we could identify HTML files with <b>*.html</b>.
457 This will match zero or more characters followed by a dot followed
458 by 'h', 't', 'm' and 'l'.
459
460 <a name="perl-users"><b>Notes for Perl Users</b></a>
461
462 Most of the character class abbreviations supported by Perl are
463 supported by QRegExp, see
464 <a href="#characters-and-abbreviations-for-sets-of-characters">
465 characters and abbreviations for sets of characters</a>.
466
467 QRegExp's quantifiers are the same as Perl's greedy quantifiers.
468 Non-greedy matching cannot be applied to individual quantifiers, but
469 can be applied to all the quantifiers in the pattern. For example,
470 to match the Perl regex <b>ro+?m</b> requires:
471 \code
472 QRegExp rx( "ro+m" );
473 rx.setMinimal( TRUE );
474 \endcode
475
476 The equivalent of Perl's <tt>/i</tt> option is
477 setCaseSensitive(FALSE).
478
479 Perl's <tt>/g</tt> option can be emulated using a
480 <a href="#cap_in_a_loop">loop</a>.
481
482 In QRegExp <b>.</b> matches any character, therefore all QRegExp
483 regexps have the equivalent of Perl's <tt>/s</tt> option. QRegExp
484 does not have an equivalent to Perl's <tt>/m</tt> option, but this
485 can be emulated in various ways for example by splitting the input
486 into lines or by looping with a regexp that searches for newlines.
487
488 Because QRegExp is string oriented there are no \A, \Z or \z
489 assertions. The \G assertion is not supported but can be emulated in
490 a loop.
491
492 Perl's $& is cap(0) or capturedTexts()[0]. There are no QRegExp
493 equivalents for $`, $' or $+. $1, $2 etc correspond to
494 cap(1) or capturedTexts()[1], cap(2) or capturedTexts()[2], etc.
495
496 To substitute a pattern use QString::replace().
497
498 Perl's extended <tt>/x</tt> syntax is not supported, nor are regexp
499 comments (?#comment) or directives, e.g. (?i).
500
501 Both zero-width positive and zero-width negative lookahead
502 assertions (?=pattern) and (?!pattern) are supported with the same
503 syntax as Perl. Perl's lookbehind assertions, "independent"
504 subexpressions and conditional expressions are not supported.
505
506 Non-capturing parenthesis are also supported, with the same
507 (?:pattern) syntax.
508
509 See QStringList::split() and QStringList::join() for equivalents to
510 Perl's split and join functions.
511
512 Note: because C++ transforms \\'s they must be written \e twice in
513 code, e.g. <b>\\</b><b>b</b> must be written <b>\\</b><b>\\</b><b>b</b>.
514
515 <a name="code-examples"><b>Code Examples</b></a>
516
517 \code
518 QRegExp rx( "^\\d\\d?$" );// Match integers 0 to 99
519 rx.search( "123" ); // Returns -1 (no match)
520 rx.search( "-6" ); // Returns -1 (no match)
521 rx.search( "6" ); // Returns 0 (matched as position 0)
522 \endcode
523
524 The third string matches '<u>6</u>'. This is a simple validation
525 regexp for integers in the range 0 to 99.
526
527 \code
528 QRegExp rx( "^\\S+$" );// Match strings which have no whitespace
529 rx.search( "Hello world" );// Returns -1 (no match)
530 rx.search( "This_is-OK" );// Returns 0 (matched at position 0)
531 \endcode
532
533 The second string matches '<u>This_is-OK</u>'. We've used the
534 character set abbreviation '\S' (non-whitespace) and the anchors to
535 match strings which contain no whitespace.
536
537 In the following example we match strings containing 'mail' or
538 'letter' or 'correspondence' but only match whole words i.e. not
539 'email'
540
541 \code
542 QRegExp rx( "\\b(mail|letter|correspondence)\\b" );
543 rx.search( "I sent you an email" ); // Returns -1 (no match)
544 rx.search( "Please write the letter" ); // Returns 17 (matched at position 17)
545 \endcode
546
547 The second string matches "Please write the <u>letter</u>". The word
548 'letter' is also captured (because of the parenthesis). We can see
549 what text we've captured like this:
550
551 \code
552 QString captured = rx.cap( 1 ); // captured contains "letter"
553 \endcode
554
555 This will capture the text from the first set of capturing
556 parenthesis (counting capturing left parenthesis from left to
557 right). The parenthesis are counted from 1 since cap( 0 ) is the
558 whole matched regexp (equivalent to '&' in most regexp engines).
559
560 \code
561 QRegExp rx( "&(?!amp;)" ); // Match ampersands but not &amp;
562 QString line1 = "This & that";
563 line1.replace( rx, "&amp;" );
564 // line1 == "This &amp; that"
565 QString line2 = "His &amp; hers & theirs";
566 line2.replace( rx, "&amp;" );
567 // line2 == "His &amp; hers &amp; theirs"
568 \endcode
569
570 Here we've passed the QRegExp to QString's replace() function to
571 replace the matched text with new text.
572
573 \code
574 QString str = "One Eric another Eirik, and an Ericsson. How many Eiriks, Eric?";
575 QRegExp rx( "\\b(Eric|Eirik)\\b" );// Match Eric or Eirik
576 int pos = 0; // Where we are in the string
577 int count = 0; // How many Eric and Eirik's we've counted
578 while ( pos >= 0 ) {
579 pos = rx.search( str, pos );
580 if ( pos >= 0 ) {
581 pos++;// Move along in str
582 count++;// Count our Eric or Eirik
583 }
584 }
585 \endcode
586
587 We've used the search() function to repeatedly match the regexp in
588 the string. Note that instead of moving forward by one character at
589 a time <tt>pos++</tt> we could have written <tt>pos +=
590 rx.matchedLength()</tt> to skip over the already matched string. The
591 count will equal 3, matching 'One <u>Eric</u> another <u>Eirik</u>,
592 and an Ericsson. How many Eiriks, <u>Eric</u>?'; it doesn't match
593 'Ericsson' or 'Eiriks' because they are not bounded by non-word
594 boundaries.
595
596 One common use of regexps is to split lines of delimited data into
597 their component fields.
598
599 \code
600 str = "Trolltech AS\twww.trolltech.com\tNorway";
601 QString company, web, country;
602 rx.setPattern( "^([^\t]+)\t([^\t]+)\t([^\t]+)$" );
603 if ( rx.search( str ) != -1 ) {
604 company = rx.cap( 1 );
605 web= rx.cap( 2 );
606 country = rx.cap( 3 );
607 }
608 \endcode
609
610 In this example our input lines have the format company name, web
611 address and country. Unfortunately the regexp is rather long and not
612 very versatile -- the code will break if we add any more fields. A
613 simpler and better solution is to look for the separator, '\t' in
614 this case, and take the surrounding text. The QStringList split()
615 function can take a separator string or regexp as an argument and
616 split a string accordingly.
617
618 \code
619 QStringList field = QStringList::split( "\t", str );
620 \endcode
621
622 Here field[0] is the company, field[1] the web address and so on.
623
624 To immitate the matching of a shell we can use wildcard mode.
625
626 \code
627 QRegExp rx( "*.html" );// Invalid regexp: * doesn't quantify anything
628 rx.setWildcard( TRUE );// Now its a valid wildcard regexp
629 rx.search( "index.html" );// Returns 0 (matched at position 0)
630 rx.search( "default.htm" );// Returns -1 (no match)
631 rx.search( "readme.txt" );// Returns -1 (no match)
632 \endcode
633
634 Wildcard matching can be convenient because of its simplicity, but
635 any wildcard regex can be defined using full regexps, e.g.
636 <b>.*\.html$</b>. Notice that we can't match both \c .html and \c
637 .htm files with a wildcard unless we use <b>*.htm*</b> which will
638 also match 'test.html.bak'. A full regexp gives us the precision we
639 need, <b>.*\.html?$</b>.
640
641 QRegExp can match case insensitively using setCaseSensitive(), and
642 can use non-greedy matching, see setMinimal(). By default QRegExp
643 uses full regexps but this can be changed with setWildcard().
644 Searching can be forward with search() or backward with searchRev().
645 Captured text can be accessed using capturedTexts() which returns a
646 string list of all captured strings, or using cap() which returns
647 the captured string for the given index. The pos() function takes a
648 match index and returns the position in the string where the match
649 was made (or -1 if there was no match).
650
651 \sa QRegExpValidator QString QStringList
652
653 <a name="member-function-documentation"/>
654*/
655
656static const int NumBadChars = 128;
657#define BadChar( ch ) ( (ch).cell() % NumBadChars )
658
659static const int NoOccurrence = INT_MAX;
660static const int EmptyCapture = INT_MAX;
661static const int InftyLen = INT_MAX;
662static const int InftyRep = 1000;
663static const int EOS = -1;
664
665#ifndef QT_NO_REGEXP_OPTIM
666static int engCount = 0;
667static QArray<int> *noOccurrences = 0;
668static QArray<int> *firstOccurrenceAtZero = 0;
669#endif
670
671/*
672 Merges two QArrays of ints and puts the result into the first one.
673*/
674static void mergeInto( QArray<int> *a, const QArray<int>& b )
675{
676 int asize = a->size();
677 int bsize = b.size();
678 if ( asize == 0 ) {
679 *a = b.copy();
680#ifndef QT_NO_REGEXP_OPTIM
681 } else if ( bsize == 1 && (*a)[asize - 1] < b[0] ) {
682 a->resize( asize + 1 );
683 (*a)[asize] = b[0];
684#endif
685 } else if ( bsize >= 1 ) {
686 int csize = asize + bsize;
687 QArray<int> c( csize );
688 int i = 0, j = 0, k = 0;
689 while ( i < asize ) {
690 if ( j < bsize ) {
691 if ( (*a)[i] == b[j] ) {
692 i++;
693 csize--;
694 } else if ( (*a)[i] < b[j] ) {
695 c[k++] = (*a)[i++];
696 } else {
697 c[k++] = b[j++];
698 }
699 } else {
700 memcpy( c.data() + k, (*a).data() + i,
701 (asize - i) * sizeof(int) );
702 break;
703 }
704 }
705 c.resize( csize );
706 if ( j < bsize )
707 memcpy( c.data() + k, b.data() + j, (bsize - j) * sizeof(int) );
708 *a = c;
709 }
710}
711
712/*
713 Merges two disjoint QMaps of (int, int) pairs and puts the result into the
714 first one.
715*/
716static void mergeInto( QMap<int, int> *a, const QMap<int, int>& b )
717{
718 QMap<int, int>::ConstIterator it;
719 for ( it = b.begin(); it != b.end(); ++it )
720 a->insert( it.key(), *it );
721}
722
723/*
724 Returns the value associated to key k in QMap m of (int, int) pairs, or 0 if
725 no such value is explicitly present.
726*/
727static int at( const QMap<int, int>& m, int k )
728{
729 QMap<int, int>::ConstIterator it = m.find( k );
730 if ( it == m.end() )
731 return 0;
732 else
733 return *it;
734}
735
736#ifndef QT_NO_REGEXP_WILDCARD
737/*
738 Translates a wildcard pattern to an equivalent regular expression pattern
739 (e.g., *.cpp to .*\.cpp).
740*/
741static QString wc2rx( const QString& wc )
742{
743 int wclen = wc.length();
744 QString rx = QString::fromLatin1( "" );
745 int i = 0;
746 while ( i < wclen ) {
747 QChar c = wc[i++];
748 switch ( c.unicode() ) {
749 case '*':
750 rx += QString::fromLatin1( ".*" );
751 break;
752 case '?':
753 rx += QChar( '.' );
754 break;
755 case '$':
756 case '(':
757 case ')':
758 case '+':
759 case '.':
760 case '\\':
761 case '^':
762 case '{':
763 case '|':
764 case '}':
765 rx += QChar( '\\' );
766 rx += c;
767 break;
768 case '[':
769 rx += c;
770 if ( wc[i] == QChar('^') )
771 rx += wc[i++];
772 if ( i < wclen ) {
773 if ( rx[i] == ']' )
774 rx += wc[i++];
775 while ( i < wclen && wc[i] != QChar(']') ) {
776 if ( wc[i] == '\\' )
777 rx += QChar( '\\' );
778 rx += wc[i++];
779 }
780 }
781 break;
782 default:
783 rx += c;
784 }
785 }
786 return rx;
787}
788#endif
789
790/*
791 The class QRegExpEngine encapsulates a modified nondeterministic finite
792 automaton (NFA).
793*/
794class QRegExpEngine : public QShared
795{
796public:
797#ifndef QT_NO_REGEXP_CCLASS
798 /*
799 The class CharClass represents a set of characters, such as can be found
800 in regular expressions (e.g., [a-z] denotes the set {a, b, ..., z}).
801 */
802 class CharClass
803 {
804 public:
805 CharClass();
806 CharClass( const CharClass& cc ) { operator=( cc ); }
807
808 CharClass& operator=( const CharClass& cc );
809
810 void clear();
811 bool negative() const { return n; }
812 void setNegative( bool negative );
813 void addCategories( int cats );
814 void addRange( ushort from, ushort to );
815 void addSingleton( ushort ch ) { addRange( ch, ch ); }
816
817 bool in( QChar ch ) const;
818#ifndef QT_NO_REGEXP_OPTIM
819 const QArray<int>& firstOccurrence() const { return occ1; }
820#endif
821
822#if defined(QT_DEBUG)
823 void dump() const;
824#endif
825
826 private:
827 /*
828 The struct Range represents a range of characters (e.g., [0-9] denotes
829 range 48 to 57).
830 */
831 struct Range
832 {
833 ushort from; // 48
834 ushort to; // 57
835 };
836
837 int c; // character classes
838 QArray<Range> r; // character ranges
839 bool n; // negative?
840#ifndef QT_NO_REGEXP_OPTIM
841 QArray<int> occ1; // first-occurrence array
842#endif
843 };
844#else
845 struct CharClass
846 {
847 int x; // dummy
848
849#ifndef QT_NO_REGEXP_OPTIM
850 const QArray<int>& firstOccurrence() const {
851 return *firstOccurrenceAtZero;
852 }
853#endif
854 };
855#endif
856
857 QRegExpEngine( bool caseSensitive ) { setup( caseSensitive ); }
858 QRegExpEngine( const QString& rx, bool caseSensitive );
859#ifndef QT_NO_REGEXP_OPTIM
860 ~QRegExpEngine();
861#endif
862
863 bool isValid() const { return valid; }
864 bool caseSensitive() const { return cs; }
865 int numCaptures() const { return realncap; }
866 QArray<int> match( const QString& str, int pos, bool minimal,
867 bool oneTest );
868 int matchedLength() const { return mmMatchedLen; }
869
870 int createState( QChar ch );
871 int createState( const CharClass& cc );
872#ifndef QT_NO_REGEXP_BACKREF
873 int createState( int bref );
874#endif
875
876 void addCatTransitions( const QArray<int>& from, const QArray<int>& to );
877#ifndef QT_NO_REGEXP_CAPTURE
878 void addPlusTransitions( const QArray<int>& from, const QArray<int>& to,
879 int atom );
880#endif
881
882#ifndef QT_NO_REGEXP_ANCHOR_ALT
883 int anchorAlternation( int a, int b );
884 int anchorConcatenation( int a, int b );
885#else
886 int anchorAlternation( int a, int b ) { return a & b; }
887 int anchorConcatenation( int a, int b ) { return a | b; }
888#endif
889 void addAnchors( int from, int to, int a );
890
891#ifndef QT_NO_REGEXP_OPTIM
892 void setupGoodStringHeuristic( int earlyStart, int lateStart,
893 const QString& str );
894 void setupBadCharHeuristic( int minLen, const QArray<int>& firstOcc );
895 void heuristicallyChooseHeuristic();
896#endif
897
898#if defined(QT_DEBUG)
899 void dump() const;
900#endif
901
902private:
903 enum { CharClassBit = 0x10000, BackRefBit = 0x20000 };
904
905 /*
906 The struct State represents one state in a modified NFA. The input
907 characters matched are stored in the state instead of on the transitions,
908 something possible for an automaton constructed from a regular expression.
909 */
910 struct State
911 {
912#ifndef QT_NO_REGEXP_CAPTURE
913 int atom; // which atom does this state belong to?
914#endif
915 int match; // what does it match? (see CharClassBit and BackRefBit)
916 QArray<int> outs; // out-transitions
917 QMap<int, int> *reenter; // atoms reentered when transiting out
918 QMap<int, int> *anchors; // anchors met when transiting out
919
920#ifndef QT_NO_REGEXP_CAPTURE
921 State( int a, int m )
922 : atom( a ), match( m ), reenter( 0 ), anchors( 0 ) { }
923#else
924 State( int m )
925 : match( m ), reenter( 0 ), anchors( 0 ) { }
926#endif
927 ~State() { delete reenter; delete anchors; }
928 };
929
930#ifndef QT_NO_REGEXP_LOOKAHEAD
931 /*
932 The struct Lookahead represents a lookahead a la Perl (e.g., (?=foo) and
933 (?!bar)).
934 */
935 struct Lookahead
936 {
937 QRegExpEngine *eng; // NFA representing the embedded regular expression
938 bool neg; // negative lookahead?
939
940 Lookahead( QRegExpEngine *eng0, bool neg0 )
941 : eng( eng0 ), neg( neg0 ) { }
942 ~Lookahead() { delete eng; }
943 };
944#endif
945
946#ifndef QT_NO_REGEXP_CAPTURE
947 /*
948 The struct Atom represents one node in the hierarchy of regular expression
949 atoms.
950 */
951 struct Atom
952 {
953 int parent; // index of parent in array of atoms
954 int capture; // index of capture, from 1 to ncap
955 };
956#endif
957
958#ifndef QT_NO_REGEXP_ANCHOR_ALT
959 /*
960 The struct AnchorAlternation represents a pair of anchors with OR
961 semantics.
962 */
963 struct AnchorAlternation
964 {
965 int a; // this anchor...
966 int b; // ...or this one
967 };
968#endif
969
970 enum { InitialState = 0, FinalState = 1 };
971 void setup( bool caseSensitive );
972 int setupState( int match );
973
974 /*
975 Let's hope that 13 lookaheads and 14 back-references are enough.
976 */
977 enum { MaxLookaheads = 13, MaxBackRefs = 14 };
978 enum { Anchor_Dollar = 0x00000001, Anchor_Caret = 0x00000002,
979 Anchor_Word = 0x00000004, Anchor_NonWord = 0x00000008,
980 Anchor_FirstLookahead = 0x00000010,
981 Anchor_BackRef1Empty = Anchor_FirstLookahead << MaxLookaheads,
982 Anchor_BackRef0Empty = Anchor_BackRef1Empty >> 1,
983 Anchor_Alternation = Anchor_BackRef1Empty << MaxBackRefs,
984
985 Anchor_LookaheadMask = ( Anchor_FirstLookahead - 1 ) ^
986 ( (Anchor_FirstLookahead << MaxLookaheads) - 1 ) };
987#ifndef QT_NO_REGEXP_CAPTURE
988 int startAtom( bool capture );
989 void finishAtom( int atom ) { cf = f[atom].parent; }
990#endif
991
992#ifndef QT_NO_REGEXP_LOOKAHEAD
993 int addLookahead( QRegExpEngine *eng, bool negative );
994#endif
995
996#ifndef QT_NO_REGEXP_CAPTURE
997 bool isBetterCapture( const int *begin1, const int *end1, const int *begin2,
998 const int *end2 );
999#endif
1000 bool testAnchor( int i, int a, const int *capBegin );
1001
1002#ifndef QT_NO_REGEXP_OPTIM
1003 bool goodStringMatch();
1004 bool badCharMatch();
1005#else
1006 bool bruteMatch();
1007#endif
1008 bool matchHere();
1009
1010 QVector<State> s; // array of states
1011 int ns; // number of states
1012#ifndef QT_NO_REGEXP_CAPTURE
1013 QArray<Atom> f; // atom hierarchy
1014 int nf; // number of atoms
1015 int cf; // current atom
1016#endif
1017 int realncap; // number of captures, seen from the outside
1018 int ncap; // number of captures, seen from the inside
1019#ifndef QT_NO_REGEXP_CCLASS
1020 QVector<CharClass> cl; // array of character classes
1021#endif
1022#ifndef QT_NO_REGEXP_LOOKAHEAD
1023 QVector<Lookahead> ahead; // array of lookaheads
1024#endif
1025#ifndef QT_NO_REGEXP_ANCHOR_ALT
1026 QArray<AnchorAlternation> aa; // array of (a, b) pairs of anchors
1027#endif
1028#ifndef QT_NO_REGEXP_OPTIM
1029 bool caretAnchored; // does the regexp start with ^?
1030#endif
1031 bool valid; // is the regular expression valid?
1032 bool cs; // case sensitive?
1033#ifndef QT_NO_REGEXP_BACKREF
1034 int nbrefs; // number of back-references
1035#endif
1036
1037#ifndef QT_NO_REGEXP_OPTIM
1038 bool useGoodStringHeuristic; // use goodStringMatch? otherwise badCharMatch
1039
1040 int goodEarlyStart; // the index where goodStr can first occur in a match
1041 int goodLateStart; // the index where goodStr can last occur in a match
1042 QString goodStr; // the string that any match has to contain
1043
1044 int minl; // the minimum length of a match
1045 QArray<int> occ1; // first-occurrence array
1046#endif
1047
1048 /*
1049 The class Box is an abstraction for a regular expression fragment. It can
1050 also be seen as one node in the syntax tree of a regular expression with
1051 synthetized attributes.
1052
1053 It's interface is ugly for performance reasons.
1054 */
1055 class Box
1056 {
1057 public:
1058 Box( QRegExpEngine *engine );
1059 Box( const Box& b ) { operator=( b ); }
1060
1061 Box& operator=( const Box& b );
1062
1063 void clear() { operator=(Box(eng)); }
1064 void set( QChar ch );
1065 void set( const CharClass& cc );
1066#ifndef QT_NO_REGEXP_BACKREF
1067 void set( int bref );
1068#endif
1069
1070 void cat( const Box& b );
1071 void orx( const Box& b );
1072 void plus( int atom );
1073 void opt();
1074 void catAnchor( int a );
1075#ifndef QT_NO_REGEXP_OPTIM
1076 void setupHeuristics();
1077#endif
1078
1079#if defined(QT_DEBUG)
1080 void dump() const;
1081#endif
1082
1083 private:
1084 void addAnchorsToEngine( const Box& to ) const;
1085
1086 QRegExpEngine *eng; // the automaton under construction
1087 QArray<int> ls; // the left states (firstpos)
1088 QArray<int> rs; // the right states (lastpos)
1089 QMap<int, int> lanchors; // the left anchors
1090 QMap<int, int> ranchors; // the right anchors
1091 int skipanchors; // the anchors to match if the box is skipped
1092
1093#ifndef QT_NO_REGEXP_OPTIM
1094 int earlyStart; // the index where str can first occur
1095 int lateStart; // the index where str can last occur
1096 QString str; // a string that has to occur in any match
1097 QString leftStr; // a string occurring at the left of this box
1098 QString rightStr; // a string occurring at the right of this box
1099 int maxl; // the maximum length of this box (possibly InftyLen)
1100#endif
1101
1102 int minl; // the minimum length of this box
1103#ifndef QT_NO_REGEXP_OPTIM
1104 QArray<int> occ1; // first-occurrence array
1105#endif
1106 };
1107 friend class Box;
1108
1109 /*
1110 This is the lexical analyzer for regular expressions.
1111 */
1112 enum { Tok_Eos, Tok_Dollar, Tok_LeftParen, Tok_MagicLeftParen,
1113 Tok_PosLookahead, Tok_NegLookahead, Tok_RightParen, Tok_CharClass,
1114 Tok_Caret, Tok_Quantifier, Tok_Bar, Tok_Word, Tok_NonWord,
1115 Tok_Char = 0x10000, Tok_BackRef = 0x20000 };
1116 int getChar();
1117 int getEscape();
1118#ifndef QT_NO_REGEXP_INTERVAL
1119 int getRep( int def );
1120#endif
1121#ifndef QT_NO_REGEXP_LOOKAHEAD
1122 void skipChars( int n );
1123#endif
1124 void startTokenizer( const QChar *rx, int len );
1125 int getToken();
1126
1127 const QChar *yyIn; // a pointer to the input regular expression pattern
1128 int yyPos0; // the position of yyTok in the input pattern
1129 int yyPos; // the position of the next character to read
1130 int yyLen; // the length of yyIn
1131 int yyCh; // the last character read
1132 CharClass *yyCharClass; // attribute for Tok_CharClass tokens
1133 int yyMinRep; // attribute for Tok_Quantifier
1134 int yyMaxRep; // ditto
1135 bool yyError; // syntax error or overflow during parsing?
1136
1137 /*
1138 This is the syntactic analyzer for regular expressions.
1139 */
1140 int parse( const QChar *rx, int len );
1141 void parseAtom( Box *box );
1142 void parseFactor( Box *box );
1143 void parseTerm( Box *box );
1144 void parseExpression( Box *box );
1145
1146 int yyTok; // the last token read
1147 bool yyMayCapture; // set this to FALSE to disable capturing
1148
1149 /*
1150 This is the engine state during matching.
1151 */
1152 const QString *mmStr; // a pointer to the input QString
1153 const QChar *mmIn; // a pointer to the input string data
1154 int mmPos; // the current position in the string
1155 int mmLen; // the length of the input string
1156 bool mmMinimal; // minimal matching?
1157 QArray<int> mmCaptured; // an array of pairs (start, len)
1158 QArray<int> mmCapturedNoMatch; // an array of pairs (-1, -1)
1159 QArray<int> mmBigArray; // big QArray<int> array
1160 int *mmInNextStack; // is state is mmNextStack?
1161 int *mmCurStack; // stack of current states
1162 int *mmNextStack; // stack of next states
1163 int *mmCurCapBegin; // start of current states' captures
1164 int *mmNextCapBegin; // start of next states' captures
1165 int *mmCurCapEnd; // end of current states' captures
1166 int *mmNextCapEnd; // end of next states' captures
1167 int *mmTempCapBegin; // start of temporary captures
1168 int *mmTempCapEnd; // end of temporary captures
1169 int *mmCapBegin; // start of captures for a next state
1170 int *mmCapEnd; // end of captures for a next state
1171 int *mmSlideTab; // bump-along slide table for bad-character heuristic
1172 int mmSlideTabSize; // size of slide table
1173#ifndef QT_NO_REGEXP_BACKREF
1174 QIntDict<int> mmSleeping; // dictionary of back-reference sleepers
1175#endif
1176 int mmMatchedLen; // length of match or of matched string for partial match
1177};
1178
1179QRegExpEngine::QRegExpEngine( const QString& rx, bool caseSensitive )
1180#ifndef QT_NO_REGEXP_BACKREF
1181 : mmSleeping( 101 )
1182#endif
1183{
1184 setup( caseSensitive );
1185 valid = ( parse(rx.unicode(), rx.length()) == (int) rx.length() );
1186}
1187
1188#ifndef QT_NO_REGEXP_OPTIM
1189QRegExpEngine::~QRegExpEngine()
1190{
1191 if ( --engCount == 0 ) {
1192 delete noOccurrences;
1193 noOccurrences = 0;
1194 delete firstOccurrenceAtZero;
1195 firstOccurrenceAtZero = 0;
1196 }
1197}
1198#endif
1199
1200/*
1201 Tries to match in str and returns an array of (begin, length) pairs for
1202 captured text. If there is no match, all pairs are (-1, -1).
1203*/
1204QArray<int> QRegExpEngine::match( const QString& str, int pos, bool minimal,
1205 bool oneTest )
1206{
1207 mmStr = &str;
1208 mmIn = str.unicode();
1209 if ( mmIn == 0 )
1210 mmIn = &QChar::null;
1211 mmPos = pos;
1212 mmLen = str.length();
1213 mmMinimal = minimal;
1214 mmMatchedLen = 0;
1215
1216 bool matched = FALSE;
1217 if ( valid && mmPos >= 0 && mmPos <= mmLen ) {
1218#ifndef QT_NO_REGEXP_OPTIM
1219 if ( mmPos <= mmLen - minl ) {
1220 if ( caretAnchored || oneTest )
1221 matched = matchHere();
1222 else if ( useGoodStringHeuristic )
1223 matched = goodStringMatch();
1224 else
1225 matched = badCharMatch();
1226 }
1227#else
1228 matched = oneTest ? matchHere() : bruteMatch();
1229#endif
1230 }
1231
1232 if ( matched ) {
1233 mmCaptured.detach();
1234 mmCaptured[0] = mmPos;
1235 mmCaptured[1] = mmMatchedLen;
1236 for ( int j = 0; j < realncap; j++ ) {
1237 int len = mmCapEnd[j] - mmCapBegin[j];
1238 mmCaptured[2 + 2 * j] = len > 0 ? mmPos + mmCapBegin[j] : 0;
1239 mmCaptured[2 + 2 * j + 1] = len;
1240 }
1241 return mmCaptured;
1242 } else {
1243 return mmCapturedNoMatch;
1244 }
1245}
1246
1247/*
1248 The three following functions add one state to the automaton and return the
1249 number of the state.
1250*/
1251
1252int QRegExpEngine::createState( QChar ch )
1253{
1254 return setupState( ch.unicode() );
1255}
1256
1257int QRegExpEngine::createState( const CharClass& cc )
1258{
1259#ifndef QT_NO_REGEXP_CCLASS
1260 int n = cl.size();
1261 cl.resize( n + 1 );
1262 cl.insert( n, new CharClass(cc) );
1263 return setupState( CharClassBit | n );
1264#else
1265 Q_UNUSED( cc );
1266 return setupState( CharClassBit );
1267#endif
1268}
1269
1270#ifndef QT_NO_REGEXP_BACKREF
1271int QRegExpEngine::createState( int bref )
1272{
1273 if ( bref > nbrefs ) {
1274 nbrefs = bref;
1275 if ( nbrefs > MaxBackRefs ) {
1276 yyError = TRUE;
1277 return 0;
1278 }
1279 }
1280 return setupState( BackRefBit | bref );
1281}
1282#endif
1283
1284/*
1285 The two following functions add a transition between all pairs of states
1286 (i, j) where i is fond in from, and j is found in to.
1287
1288 Cat-transitions are distinguished from plus-transitions for capturing.
1289*/
1290
1291void QRegExpEngine::addCatTransitions( const QArray<int>& from,
1292 const QArray<int>& to )
1293{
1294 for ( int i = 0; i < (int) from.size(); i++ ) {
1295 State *st = s[from[i]];
1296 mergeInto( &st->outs, to );
1297 }
1298}
1299
1300#ifndef QT_NO_REGEXP_CAPTURE
1301void QRegExpEngine::addPlusTransitions( const QArray<int>& from,
1302 const QArray<int>& to, int atom )
1303{
1304 for ( int i = 0; i < (int) from.size(); i++ ) {
1305 State *st = s[from[i]];
1306 QArray<int> oldOuts = st->outs.copy();
1307 mergeInto( &st->outs, to );
1308 if ( f[atom].capture >= 0 ) {
1309 if ( st->reenter == 0 )
1310 st->reenter = new QMap<int, int>;
1311 for ( int j = 0; j < (int) to.size(); j++ ) {
1312 if ( !st->reenter->contains(to[j]) &&
1313 oldOuts.bsearch(to[j]) < 0 )
1314 st->reenter->insert( to[j], atom );
1315 }
1316 }
1317 }
1318}
1319#endif
1320
1321#ifndef QT_NO_REGEXP_ANCHOR_ALT
1322/*
1323 Returns an anchor that means a OR b.
1324*/
1325int QRegExpEngine::anchorAlternation( int a, int b )
1326{
1327 if ( ((a & b) == a || (a & b) == b) && ((a | b) & Anchor_Alternation) == 0 )
1328 return a & b;
1329
1330 int n = aa.size();
1331 aa.resize( n + 1 );
1332 aa[n].a = a;
1333 aa[n].b = b;
1334 return Anchor_Alternation | n;
1335}
1336
1337/*
1338 Returns an anchor that means a AND b.
1339*/
1340int QRegExpEngine::anchorConcatenation( int a, int b )
1341{
1342 if ( ((a | b) & Anchor_Alternation) == 0 )
1343 return a | b;
1344 if ( (b & Anchor_Alternation) != 0 )
1345 qSwap( a, b );
1346 int aprime = anchorConcatenation( aa[a ^ Anchor_Alternation].a, b );
1347 int bprime = anchorConcatenation( aa[a ^ Anchor_Alternation].b, b );
1348 return anchorAlternation( aprime, bprime );
1349}
1350#endif
1351
1352/*
1353 Adds anchor a on a transition caracterised by its from state and its to state.
1354*/
1355void QRegExpEngine::addAnchors( int from, int to, int a )
1356{
1357 State *st = s[from];
1358 if ( st->anchors == 0 )
1359 st->anchors = new QMap<int, int>;
1360 if ( st->anchors->contains(to) )
1361 a = anchorAlternation( (*st->anchors)[to], a );
1362 st->anchors->insert( to, a );
1363}
1364
1365#ifndef QT_NO_REGEXP_OPTIM
1366/*
1367 The two following functions provide the engine with the information needed by
1368 its matching heuristics.
1369*/
1370
1371void QRegExpEngine::setupGoodStringHeuristic( int earlyStart, int lateStart,
1372 const QString& str )
1373{
1374 goodEarlyStart = earlyStart;
1375 goodLateStart = lateStart;
1376 goodStr = cs ? str : str.lower();
1377}
1378
1379void QRegExpEngine::setupBadCharHeuristic( int minLen,
1380 const QArray<int>& firstOcc )
1381{
1382 minl = minLen;
1383 occ1 = cs ? firstOcc : *firstOccurrenceAtZero;
1384}
1385
1386/*
1387 This function chooses between the good-string and the bad-character
1388 heuristics. It computes two scores and chooses the heuristic with the highest
1389 score.
1390
1391 Here are some common-sense constraints on the scores that should be respected
1392 if the formulas are ever modified: (1) If goodStr is empty, the good-string
1393 heuristic scores 0. (2) If the search is case insensitive, the good-string
1394 heuristic should be used, unless it scores 0. (Case insensitivity
1395 turns all entries of occ1 to 0.) (3) If (goodLateStart - goodEarlyStart) is
1396 big, the good-string heuristic should score less.
1397*/
1398void QRegExpEngine::heuristicallyChooseHeuristic()
1399{
1400 int i;
1401
1402 if ( minl == 0 )
1403 return;
1404
1405 /*
1406 Magic formula: The good string has to constitute a good proportion of the
1407 minimum-length string, and appear at a more-or-less known index.
1408 */
1409 int goodStringScore = ( 64 * goodStr.length() / minl ) -
1410 ( goodLateStart - goodEarlyStart );
1411
1412 /*
1413 Less magic formula: We pick a couple of characters at random, and check
1414 whether they are good or bad.
1415 */
1416 int badCharScore = 0;
1417 int step = QMAX( 1, NumBadChars / 32 );
1418 for ( i = 1; i < NumBadChars; i += step ) {
1419 if ( occ1[i] == NoOccurrence )
1420 badCharScore += minl;
1421 else
1422 badCharScore += occ1[i];
1423 }
1424 badCharScore /= minl;
1425
1426 useGoodStringHeuristic = ( goodStringScore > badCharScore );
1427}
1428#endif
1429
1430#if defined(QT_DEBUG)
1431void QRegExpEngine::dump() const
1432{
1433 int i, j;
1434 qDebug( "Case %ssensitive engine", cs ? "" : "in" );
1435 qDebug( " States" );
1436 for ( i = 0; i < ns; i++ ) {
1437 qDebug( " %d%s", i,
1438 i == InitialState ? " (initial)" :
1439 i == FinalState ? " (final)" : "" );
1440#ifndef QT_NO_REGEXP_CAPTURE
1441 qDebug( " in atom %d", s[i]->atom );
1442#endif
1443 int m = s[i]->match;
1444 if ( (m & CharClassBit) != 0 ) {
1445 qDebug( " match character class %d", m ^ CharClassBit );
1446#ifndef QT_NO_REGEXP_CCLASS
1447 cl[m ^ CharClassBit]->dump();
1448#else
1449 qDebug( " negative character class" );
1450#endif
1451 } else if ( (m & BackRefBit) != 0 ) {
1452 qDebug( " match back-reference %d", m ^ BackRefBit );
1453 } else if ( m >= 0x20 && m <= 0x7e ) {
1454 qDebug( " match 0x%.4x (%c)", m, m );
1455 } else {
1456 qDebug( " match 0x%.4x", m );
1457 }
1458 for ( j = 0; j < (int) s[i]->outs.size(); j++ ) {
1459 int next = s[i]->outs[j];
1460 qDebug( " -> %d", next );
1461 if ( s[i]->reenter != 0 && s[i]->reenter->contains(next) )
1462 qDebug( " [reenter %d]", (*s[i]->reenter)[next] );
1463 if ( s[i]->anchors != 0 && at(*s[i]->anchors, next) != 0 )
1464 qDebug( " [anchors 0x%.8x]", (*s[i]->anchors)[next] );
1465 }
1466 }
1467#ifndef QT_NO_REGEXP_CAPTURE
1468 if ( nf > 0 ) {
1469 qDebug( " Atom Parent Capture" );
1470 for ( i = 0; i < nf; i++ )
1471 qDebug( " %6d %6d %6d", i, f[i].parent, f[i].capture );
1472 }
1473#endif
1474#ifndef QT_NO_REGEXP_ANCHOR_ALT
1475 for ( i = 0; i < (int) aa.size(); i++ )
1476 qDebug( " Anchor alternation 0x%.8x: 0x%.8x 0x%.9x", i, aa[i].a,
1477 aa[i].b );
1478#endif
1479}
1480#endif
1481
1482void QRegExpEngine::setup( bool caseSensitive )
1483{
1484#ifndef QT_NO_REGEXP_OPTIM
1485 if ( engCount++ == 0 ) {
1486 noOccurrences = new QArray<int>( NumBadChars );
1487 firstOccurrenceAtZero = new QArray<int>( NumBadChars );
1488 noOccurrences->fill( NoOccurrence );
1489 firstOccurrenceAtZero->fill( 0 );
1490 }
1491#endif
1492 s.setAutoDelete( TRUE );
1493 s.resize( 32 );
1494 ns = 0;
1495#ifndef QT_NO_REGEXP_CAPTURE
1496 f.resize( 32 );
1497 nf = 0;
1498 cf = -1;
1499#endif
1500 realncap = 0;
1501 ncap = 0;
1502#ifndef QT_NO_REGEXP_CCLASS
1503 cl.setAutoDelete( TRUE );
1504#endif
1505#ifndef QT_NO_REGEXP_LOOKAHEAD
1506 ahead.setAutoDelete( TRUE );
1507#endif
1508#ifndef QT_NO_REGEXP_OPTIM
1509 caretAnchored = TRUE;
1510#endif
1511 valid = FALSE;
1512 cs = caseSensitive;
1513#ifndef QT_NO_REGEXP_BACKREF
1514 nbrefs = 0;
1515#endif
1516#ifndef QT_NO_REGEXP_OPTIM
1517 useGoodStringHeuristic = FALSE;
1518 minl = 0;
1519 occ1 = *firstOccurrenceAtZero;
1520#endif
1521 mmCapturedNoMatch.fill( -1, 2 );
1522}
1523
1524int QRegExpEngine::setupState( int match )
1525{
1526 if ( (ns & (ns + 1)) == 0 && ns + 1 >= (int) s.size() )
1527 s.resize( (ns + 1) << 1 );
1528#ifndef QT_NO_REGEXP_CAPTURE
1529 s.insert( ns, new State(cf, match) );
1530#else
1531 s.insert( ns, new State(match) );
1532#endif
1533 return ns++;
1534}
1535
1536#ifndef QT_NO_REGEXP_CAPTURE
1537/*
1538 Functions startAtom() and finishAtom() should be called to delimit atoms.
1539 When a state is created, it is assigned to the current atom. The information
1540 is later used for capturing.
1541*/
1542int QRegExpEngine::startAtom( bool capture )
1543{
1544 if ( (nf & (nf + 1)) == 0 && nf + 1 >= (int) f.size() )
1545 f.resize( (nf + 1) << 1 );
1546 f[nf].parent = cf;
1547 cf = nf++;
1548 f[cf].capture = capture ? ncap++ : -1;
1549 return cf;
1550}
1551#endif
1552
1553#ifndef QT_NO_REGEXP_LOOKAHEAD
1554/*
1555 Creates a lookahead anchor.
1556*/
1557int QRegExpEngine::addLookahead( QRegExpEngine *eng, bool negative )
1558{
1559 int n = ahead.size();
1560 if ( n == MaxLookaheads ) {
1561 yyError = TRUE;
1562 return 0;
1563 }
1564 ahead.resize( n + 1 );
1565 ahead.insert( n, new Lookahead(eng, negative) );
1566 return Anchor_FirstLookahead << n;
1567}
1568#endif
1569
1570#ifndef QT_NO_REGEXP_CAPTURE
1571/*
1572 We want the longest leftmost captures.
1573*/
1574bool QRegExpEngine::isBetterCapture( const int *begin1, const int *end1,
1575 const int *begin2, const int *end2 )
1576{
1577 for ( int i = 0; i < ncap; i++ ) {
1578 int delta = begin2[i] - begin1[i]; // it has to start early...
1579 if ( delta == 0 )
1580 delta = end1[i] - end2[i]; // ...and end late (like a party)
1581
1582 if ( delta != 0 )
1583 return delta > 0;
1584 }
1585 return FALSE;
1586}
1587#endif
1588
1589/*
1590 Returns TRUE if anchor a matches at position mmPos + i in the input string,
1591 otherwise FALSE.
1592*/
1593bool QRegExpEngine::testAnchor( int i, int a, const int *capBegin )
1594{
1595 int j;
1596
1597#ifndef QT_NO_REGEXP_ANCHOR_ALT
1598 if ( (a & Anchor_Alternation) != 0 ) {
1599 return testAnchor( i, aa[a ^ Anchor_Alternation].a, capBegin ) ||
1600 testAnchor( i, aa[a ^ Anchor_Alternation].b, capBegin );
1601 }
1602#endif
1603
1604 if ( (a & Anchor_Caret) != 0 ) {
1605 if ( mmPos + i != 0 )
1606 return FALSE;
1607 }
1608 if ( (a & Anchor_Dollar) != 0 ) {
1609 if ( mmPos + i != mmLen )
1610 return FALSE;
1611 }
1612#ifndef QT_NO_REGEXP_ESCAPE
1613 if ( (a & (Anchor_Word | Anchor_NonWord)) != 0 ) {
1614 bool before = FALSE, after = FALSE;
1615 if ( mmPos + i != 0 )
1616 before = mmIn[mmPos + i - 1].isLetterOrNumber();
1617 if ( mmPos + i != mmLen )
1618 after = mmIn[mmPos + i].isLetterOrNumber();
1619 if ( (a & Anchor_Word) != 0 && (before == after) )
1620 return FALSE;
1621 if ( (a & Anchor_NonWord) != 0 && (before != after) )
1622 return FALSE;
1623 }
1624#endif
1625#ifndef QT_NO_REGEXP_LOOKAHEAD
1626 bool catchx = TRUE;
1627
1628 if ( (a & Anchor_LookaheadMask) != 0 ) {
1629 QConstString cstr = QConstString( (QChar *) mmIn + mmPos + i,
1630 mmLen - mmPos - i );
1631 for ( j = 0; j < (int) ahead.size(); j++ ) {
1632 if ( (a & (Anchor_FirstLookahead << j)) != 0 ) {
1633 catchx = ( ahead[j]->eng->match(cstr.string(), 0, TRUE,
1634 TRUE)[0] == 0 );
1635 if ( catchx == ahead[j]->neg )
1636 return FALSE;
1637 }
1638 }
1639 }
1640#endif
1641#ifndef QT_NO_REGEXP_CAPTURE
1642#ifndef QT_NO_REGEXP_BACKREF
1643 for ( j = 0; j < nbrefs; j++ ) {
1644 if ( (a & (Anchor_BackRef1Empty << j)) != 0 ) {
1645 if ( capBegin[j] != EmptyCapture )
1646 return FALSE;
1647 }
1648 }
1649#endif
1650#endif
1651 return TRUE;
1652}
1653
1654#ifndef QT_NO_REGEXP_OPTIM
1655/*
1656 The three following functions are what Jeffrey Friedl would call transmissions
1657 (or bump-alongs). Using one or the other should make no difference, except
1658 in performance.
1659*/
1660
1661bool QRegExpEngine::goodStringMatch()
1662{
1663 int k = mmPos + goodEarlyStart;
1664
1665 while ( (k = mmStr->find(goodStr, k, cs)) != -1 ) {
1666 int from = k - goodLateStart;
1667 int to = k - goodEarlyStart;
1668 if ( from > mmPos )
1669 mmPos = from;
1670
1671 while ( mmPos <= to ) {
1672 if ( matchHere() )
1673 return TRUE;
1674 mmPos++;
1675 }
1676 k++;
1677 }
1678 return FALSE;
1679}
1680
1681bool QRegExpEngine::badCharMatch()
1682{
1683 int slideHead = 0;
1684 int slideNext = 0;
1685 int i;
1686 int lastPos = mmLen - minl;
1687 memset( mmSlideTab, 0, mmSlideTabSize * sizeof(int) );
1688
1689 /*
1690 Set up the slide table, used for the bad-character heuristic, using
1691 the table of first occurrence of each character.
1692 */
1693 for ( i = 0; i < minl; i++ ) {
1694 int sk = occ1[BadChar(mmIn[mmPos + i])];
1695 if ( sk == NoOccurrence )
1696 sk = i + 1;
1697 if ( sk > 0 ) {
1698 int k = i + 1 - sk;
1699 if ( k < 0 ) {
1700 sk = i + 1;
1701 k = 0;
1702 }
1703 if ( sk > mmSlideTab[k] )
1704 mmSlideTab[k] = sk;
1705 }
1706 }
1707
1708 if ( mmPos > lastPos )
1709 return FALSE;
1710
1711 while ( TRUE ) {
1712 if ( ++slideNext >= mmSlideTabSize )
1713 slideNext = 0;
1714 if ( mmSlideTab[slideHead] > 0 ) {
1715 if ( mmSlideTab[slideHead] - 1 > mmSlideTab[slideNext] )
1716 mmSlideTab[slideNext] = mmSlideTab[slideHead] - 1;
1717 mmSlideTab[slideHead] = 0;
1718 } else {
1719 if ( matchHere() )
1720 return TRUE;
1721 }
1722
1723 if ( mmPos == lastPos )
1724 break;
1725
1726 /*
1727 Update the slide table. This code has much in common with the
1728 initialization code.
1729 */
1730 int sk = occ1[BadChar(mmIn[mmPos + minl])];
1731 if ( sk == NoOccurrence ) {
1732 mmSlideTab[slideNext] = minl;
1733 } else if ( sk > 0 ) {
1734 int k = slideNext + minl - sk;
1735 if ( k >= mmSlideTabSize )
1736 k -= mmSlideTabSize;
1737 if ( sk > mmSlideTab[k] )
1738 mmSlideTab[k] = sk;
1739 }
1740 slideHead = slideNext;
1741 mmPos++;
1742 }
1743 return FALSE;
1744}
1745#else
1746bool QRegExpEngine::bruteMatch()
1747{
1748 while ( mmPos <= mmLen ) {
1749 if ( matchHere() )
1750 return TRUE;
1751 mmPos++;
1752 }
1753 return FALSE;
1754}
1755#endif
1756
1757/*
1758 Here's the core of the engine. It tries to do a match here and now.
1759*/
1760bool QRegExpEngine::matchHere()
1761{
1762 int ncur = 1, nnext = 0;
1763 int i = 0, j, k, m;
1764 bool match = FALSE;
1765
1766 mmMatchedLen = -1;
1767 mmCurStack[0] = InitialState;
1768
1769#ifndef QT_NO_REGEXP_CAPTURE
1770 if ( ncap > 0 ) {
1771 for ( j = 0; j < ncap; j++ ) {
1772 mmCurCapBegin[j] = EmptyCapture;
1773 mmCurCapEnd[j] = EmptyCapture;
1774 }
1775 }
1776#endif
1777
1778#ifndef QT_NO_REGEXP_BACKREF
1779 int *zzZ = 0;
1780
1781 while ( (ncur > 0 || mmSleeping.count() > 0) && i <= mmLen - mmPos &&
1782 !match )
1783#else
1784 while ( ncur > 0 && i <= mmLen - mmPos && !match )
1785#endif
1786 {
1787 int ch = ( i < mmLen - mmPos ) ? mmIn[mmPos + i].unicode() : 0;
1788 for ( j = 0; j < ncur; j++ ) {
1789 int cur = mmCurStack[j];
1790 State *scur = s[cur];
1791 QArray<int>& outs = scur->outs;
1792 for ( k = 0; k < (int) outs.size(); k++ ) {
1793 int next = outs[k];
1794 State *snext = s[next];
1795 bool in = TRUE;
1796#ifndef QT_NO_REGEXP_BACKREF
1797 int needSomeSleep = 0;
1798#endif
1799
1800 /*
1801 First, check if the anchors are anchored properly.
1802 */
1803 if ( scur->anchors != 0 ) {
1804 int a = at( *scur->anchors, next );
1805 if ( a != 0 && !testAnchor(i, a, mmCurCapBegin + j * ncap) )
1806 in = FALSE;
1807 }
1808 /*
1809 If indeed they are, check if the input character is correct
1810 for this transition.
1811 */
1812 if ( in ) {
1813 m = snext->match;
1814 if ( (m & (CharClassBit | BackRefBit)) == 0 ) {
1815 if ( cs )
1816 in = ( m == ch );
1817 else
1818 in = ( QChar(m).lower() == QChar(ch).lower() );
1819 } else if ( next == FinalState ) {
1820 mmMatchedLen = i;
1821 match = mmMinimal;
1822 in = TRUE;
1823 } else if ( (m & CharClassBit) != 0 ) {
1824#ifndef QT_NO_REGEXP_CCLASS
1825 const CharClass *cc = cl[m ^ CharClassBit];
1826 if ( cs )
1827 in = cc->in( ch );
1828 else if ( cc->negative() )
1829 in = cc->in( QChar(ch).lower() ) &&
1830 cc->in( QChar(ch).upper() );
1831 else
1832 in = cc->in( QChar(ch).lower() ) ||
1833 cc->in( QChar(ch).upper() );
1834#endif
1835#ifndef QT_NO_REGEXP_BACKREF
1836 } else { /* ( (m & BackRefBit) != 0 ) */
1837 int bref = m ^ BackRefBit;
1838 int ell = j * ncap + ( bref - 1 );
1839
1840 in = bref <= ncap && mmCurCapBegin[ell] != EmptyCapture;
1841 if ( in ) {
1842 if ( cs )
1843 in = ( mmIn[mmPos + mmCurCapBegin[ell]]
1844 == QChar(ch) );
1845 else
1846 in = ( mmIn[mmPos + mmCurCapBegin[ell]].lower()
1847 == QChar(ch).lower() );
1848 }
1849
1850 if ( in ) {
1851 int delta;
1852 if ( mmCurCapEnd[ell] == EmptyCapture )
1853 delta = i - mmCurCapBegin[ell];
1854 else
1855 delta = mmCurCapEnd[ell] - mmCurCapBegin[ell];
1856
1857 in = ( delta <= mmLen - mmPos );
1858 if ( in && delta > 1 ) {
1859 int n;
1860 if ( cs ) {
1861 for ( n = 1; n < delta; n++ ) {
1862 if ( mmIn[mmPos +
1863 mmCurCapBegin[ell] + n] !=
1864 mmIn[mmPos + i + n] )
1865 break;
1866 }
1867 } else {
1868 for ( n = 1; n < delta; n++ ) {
1869 QChar a = mmIn[mmPos +
1870 mmCurCapBegin[ell] + n];
1871 QChar b = mmIn[mmPos + i + n];
1872 if ( a.lower() != b.lower() )
1873 break;
1874 }
1875 }
1876 in = ( n == delta );
1877 if ( in )
1878 needSomeSleep = delta - 1;
1879 }
1880 }
1881#endif
1882 }
1883 }
1884
1885 /*
1886 All is right. We must now update our data structures.
1887 */
1888 if ( in ) {
1889#ifndef QT_NO_REGEXP_CAPTURE
1890 int *capBegin, *capEnd;
1891#endif
1892 /*
1893 If the next state was not encountered yet, all is fine.
1894 */
1895 if ( (m = mmInNextStack[next]) == -1 ) {
1896 m = nnext++;
1897 mmNextStack[m] = next;
1898 mmInNextStack[next] = m;
1899#ifndef QT_NO_REGEXP_CAPTURE
1900 capBegin = mmNextCapBegin + m * ncap;
1901 capEnd = mmNextCapEnd + m * ncap;
1902
1903 /*
1904 Otherwise, we'll first maintain captures in temporary
1905 arrays, and decide at the end whether it's best to keep
1906 the previous capture zones or the new ones.
1907 */
1908 } else {
1909 capBegin = mmTempCapBegin;
1910 capEnd = mmTempCapEnd;
1911#endif
1912 }
1913
1914#ifndef QT_NO_REGEXP_CAPTURE
1915 /*
1916 Updating the capture zones is much of a task.
1917 */
1918 if ( ncap > 0 ) {
1919 memcpy( capBegin, mmCurCapBegin + j * ncap,
1920 ncap * sizeof(int) );
1921 memcpy( capEnd, mmCurCapEnd + j * ncap,
1922 ncap * sizeof(int) );
1923 int c = scur->atom, n = snext->atom;
1924 int p = -1, q = -1;
1925 int cap;
1926
1927 /*
1928 Lemma 1. For any x in the range [0..nf), we have
1929 f[x].parent < x.
1930
1931 Proof. By looking at startAtom(), it is clear that
1932 cf < nf holds all the time, and thus that
1933 f[nf].parent < nf.
1934 */
1935
1936 /*
1937 If we are reentering an atom, we empty all capture
1938 zones inside it.
1939 */
1940 if ( scur->reenter != 0 &&
1941 (q = at(*scur->reenter, next)) != 0 ) {
1942 QBitArray b;
1943 b.fill( FALSE, nf );
1944 b.setBit( q, TRUE );
1945 for ( int ell = q + 1; ell < nf; ell++ ) {
1946 if ( b.testBit(f[ell].parent) ) {
1947 b.setBit( ell, TRUE );
1948 cap = f[ell].capture;
1949 if ( cap >= 0 ) {
1950 capBegin[cap] = EmptyCapture;
1951 capEnd[cap] = EmptyCapture;
1952 }
1953 }
1954 }
1955 p = f[q].parent;
1956
1957 /*
1958 Otherwise, close the capture zones we are leaving.
1959 We are leaving f[c].capture, f[f[c].parent].capture,
1960 f[f[f[c].parent].parent].capture, ..., until
1961 f[x].capture, with x such that f[x].parent is the
1962 youngest common ancestor for c and n.
1963
1964 We go up along c's and n's ancestry until we find x.
1965 */
1966 } else {
1967 p = c;
1968 q = n;
1969 while ( p != q ) {
1970 if ( p > q ) {
1971 cap = f[p].capture;
1972 if ( cap >= 0 ) {
1973 if ( capBegin[cap] == i ) {
1974 capBegin[cap] = EmptyCapture;
1975 capEnd[cap] = EmptyCapture;
1976 } else {
1977 capEnd[cap] = i;
1978 }
1979 }
1980 p = f[p].parent;
1981 } else {
1982 q = f[q].parent;
1983 }
1984 }
1985 }
1986
1987 /*
1988 In any case, we now open the capture zones we are
1989 entering. We work upwards from n until we reach p
1990 (the parent of the atom we reenter or the youngest
1991 common ancestor).
1992 */
1993 while ( n > p ) {
1994 cap = f[n].capture;
1995 if ( cap >= 0 ) {
1996 capBegin[cap] = i;
1997 capEnd[cap] = EmptyCapture;
1998 }
1999 n = f[n].parent;
2000 }
2001 /*
2002 If the next state was already in mmNextStack, we must
2003 choose carefully which capture zones we want to keep.
2004 */
2005 if ( capBegin == mmTempCapBegin &&
2006 isBetterCapture(capBegin, capEnd,
2007 mmNextCapBegin + m * ncap,
2008 mmNextCapEnd + m * ncap) ) {
2009 memcpy( mmNextCapBegin + m * ncap, capBegin,
2010 ncap * sizeof(int) );
2011 memcpy( mmNextCapEnd + m * ncap, capEnd,
2012 ncap * sizeof(int) );
2013 }
2014 }
2015#ifndef QT_NO_REGEXP_BACKREF
2016 /*
2017 We are done with updating the capture zones. It's now
2018 time to put the next state to sleep, if it needs to, and
2019 to remove it from mmNextStack.
2020 */
2021 if ( needSomeSleep > 0 ) {
2022 zzZ = new int[1 + 2 * ncap];
2023 zzZ[0] = next;
2024 if ( ncap > 0 ) {
2025 memcpy( zzZ + 1, capBegin, ncap * sizeof(int) );
2026 memcpy( zzZ + 1 + ncap, capEnd,
2027 ncap * sizeof(int) );
2028 }
2029 mmInNextStack[mmNextStack[--nnext]] = -1;
2030 mmSleeping.insert( i + needSomeSleep, zzZ );
2031 }
2032#endif
2033#endif
2034 }
2035 }
2036 }
2037#ifndef QT_NO_REGEXP_CAPTURE
2038 /*
2039 If we reached the final state, hurray! Copy the captured zone.
2040 */
2041 if ( ncap > 0 && (m = mmInNextStack[FinalState]) != -1 ) {
2042 memcpy( mmCapBegin, mmNextCapBegin + m * ncap, ncap * sizeof(int) );
2043 memcpy( mmCapEnd, mmNextCapEnd + m * ncap, ncap * sizeof(int) );
2044 }
2045#ifndef QT_NO_REGEXP_BACKREF
2046 /*
2047 It's time to wake up the sleepers.
2048 */
2049 if ( mmSleeping.count() > 0 ) {
2050 while ( (zzZ = mmSleeping.take(i)) != 0 ) {
2051 int next = zzZ[0];
2052 int *capBegin = zzZ + 1;
2053 int *capEnd = zzZ + 1 + ncap;
2054 bool copyOver = TRUE;
2055
2056 if ( (m = mmInNextStack[zzZ[0]]) == -1 ) {
2057 m = nnext++;
2058 mmNextStack[m] = next;
2059 mmInNextStack[next] = m;
2060 } else {
2061 copyOver = isBetterCapture( mmNextCapBegin + m * ncap,
2062 mmNextCapEnd + m * ncap,
2063 capBegin, capEnd );
2064 }
2065 if ( copyOver ) {
2066 memcpy( mmNextCapBegin + m * ncap, capBegin,
2067 ncap * sizeof(int) );
2068 memcpy( mmNextCapEnd + m * ncap, capEnd,
2069 ncap * sizeof(int) );
2070 }
2071 delete[] zzZ;
2072 }
2073 }
2074#endif
2075#endif
2076 for ( j = 0; j < nnext; j++ )
2077 mmInNextStack[mmNextStack[j]] = -1;
2078
2079 qSwap( mmCurStack, mmNextStack );
2080#ifndef QT_NO_REGEXP_CAPTURE
2081 qSwap( mmCurCapBegin, mmNextCapBegin );
2082 qSwap( mmCurCapEnd, mmNextCapEnd );
2083#endif
2084 ncur = nnext;
2085 nnext = 0;
2086 i++;
2087 }
2088
2089#ifndef QT_NO_REGEXP_BACKREF
2090 /*
2091 If minimal matching is enabled, we might have some sleepers left.
2092 */
2093 while ( !mmSleeping.isEmpty() ) {
2094 zzZ = mmSleeping.take( *QIntDictIterator<int>(mmSleeping) );
2095 delete[] zzZ;
2096 }
2097#endif
2098
2099 match = ( mmMatchedLen >= 0 );
2100 if ( !match )
2101 mmMatchedLen = i - 1;
2102 return match;
2103}
2104
2105#ifndef QT_NO_REGEXP_CCLASS
2106
2107QRegExpEngine::CharClass::CharClass()
2108 : c( 0 ), n( FALSE )
2109#ifndef QT_NO_REGEXP_OPTIM
2110 , occ1( *noOccurrences )
2111#endif
2112{
2113}
2114
2115QRegExpEngine::CharClass& QRegExpEngine::CharClass::operator=(
2116 const CharClass& cc )
2117{
2118 c = cc.c;
2119 r = cc.r.copy();
2120 n = cc.n;
2121#ifndef QT_NO_REGEXP_OPTIM
2122 occ1 = cc.occ1;
2123#endif
2124 return *this;
2125}
2126
2127void QRegExpEngine::CharClass::clear()
2128{
2129 c = 0;
2130 r.resize( 0 );
2131 n = FALSE;
2132}
2133
2134void QRegExpEngine::CharClass::setNegative( bool negative )
2135{
2136 n = negative;
2137#ifndef QT_NO_REGEXP_OPTIM
2138 occ1 = *firstOccurrenceAtZero;
2139#endif
2140}
2141
2142void QRegExpEngine::CharClass::addCategories( int cats )
2143{
2144 c |= cats;
2145#ifndef QT_NO_REGEXP_OPTIM
2146 occ1 = *firstOccurrenceAtZero;
2147#endif
2148}
2149
2150void QRegExpEngine::CharClass::addRange( ushort from, ushort to )
2151{
2152 if ( from > to )
2153 qSwap( from, to );
2154 int n = r.size();
2155 r.resize( n + 1 );
2156 r[n].from = from;
2157 r[n].to = to;
2158
2159#ifndef QT_NO_REGEXP_OPTIM
2160 int i;
2161
2162 if ( to - from < NumBadChars ) {
2163 occ1.detach();
2164 if ( from % NumBadChars <= to % NumBadChars ) {
2165 for ( i = from % NumBadChars; i <= to % NumBadChars; i++ )
2166 occ1[i] = 0;
2167 } else {
2168 for ( i = 0; i <= to % NumBadChars; i++ )
2169 occ1[i] = 0;
2170 for ( i = from % NumBadChars; i < NumBadChars; i++ )
2171 occ1[i] = 0;
2172 }
2173 } else {
2174 occ1 = *firstOccurrenceAtZero;
2175 }
2176#endif
2177}
2178
2179bool QRegExpEngine::CharClass::in( QChar ch ) const
2180{
2181#ifndef QT_NO_REGEXP_OPTIM
2182 if ( occ1[BadChar(ch)] == NoOccurrence )
2183 return n;
2184#endif
2185
2186 if ( c != 0 && (c & (1 << (int) ch.category())) != 0 )
2187 return !n;
2188 for ( int i = 0; i < (int) r.size(); i++ ) {
2189 if ( ch.unicode() >= r[i].from && ch.unicode() <= r[i].to )
2190 return !n;
2191 }
2192 return n;
2193}
2194
2195#if defined(QT_DEBUG)
2196void QRegExpEngine::CharClass::dump() const
2197{
2198 int i;
2199 qDebug( " %stive character class", n ? "nega" : "posi" );
2200#ifndef QT_NO_REGEXP_CCLASS
2201 if ( c != 0 )
2202 qDebug( " categories 0x%.8x", c );
2203#endif
2204 for ( i = 0; i < (int) r.size(); i++ )
2205 qDebug( " 0x%.4x through 0x%.4x", r[i].from, r[i].to );
2206}
2207#endif
2208#endif
2209
2210QRegExpEngine::Box::Box( QRegExpEngine *engine )
2211 : eng( engine ), skipanchors( 0 )
2212#ifndef QT_NO_REGEXP_OPTIM
2213 , earlyStart( 0 ), lateStart( 0 ), maxl( 0 ), occ1( *noOccurrences )
2214#endif
2215{
2216 minl = 0;
2217}
2218
2219QRegExpEngine::Box& QRegExpEngine::Box::operator=( const Box& b )
2220{
2221 eng = b.eng;
2222 ls = b.ls;
2223 rs = b.rs;
2224 lanchors = b.lanchors;
2225 ranchors = b.ranchors;
2226 skipanchors = b.skipanchors;
2227#ifndef QT_NO_REGEXP_OPTIM
2228 earlyStart = b.earlyStart;
2229 lateStart = b.lateStart;
2230 str = b.str;
2231 leftStr = b.leftStr;
2232 rightStr = b.rightStr;
2233 maxl = b.maxl;
2234 occ1 = b.occ1;
2235#endif
2236 minl = b.minl;
2237 return *this;
2238}
2239
2240void QRegExpEngine::Box::set( QChar ch )
2241{
2242 ls.resize( 1 );
2243 ls[0] = eng->createState( ch );
2244 rs = ls;
2245 rs.detach();
2246#ifndef QT_NO_REGEXP_OPTIM
2247 str = ch;
2248 leftStr = ch;
2249 rightStr = ch;
2250 maxl = 1;
2251 occ1.detach();
2252 occ1[BadChar(ch)] = 0;
2253#endif
2254 minl = 1;
2255}
2256
2257void QRegExpEngine::Box::set( const CharClass& cc )
2258{
2259 ls.resize( 1 );
2260 ls[0] = eng->createState( cc );
2261 rs = ls;
2262 rs.detach();
2263#ifndef QT_NO_REGEXP_OPTIM
2264 maxl = 1;
2265 occ1 = cc.firstOccurrence();
2266#endif
2267 minl = 1;
2268}
2269
2270#ifndef QT_NO_REGEXP_BACKREF
2271void QRegExpEngine::Box::set( int bref )
2272{
2273 ls.resize( 1 );
2274 ls[0] = eng->createState( bref );
2275 rs = ls;
2276 rs.detach();
2277 if ( bref >= 1 && bref <= MaxBackRefs )
2278 skipanchors = Anchor_BackRef0Empty << bref;
2279#ifndef QT_NO_REGEXP_OPTIM
2280 maxl = InftyLen;
2281#endif
2282 minl = 0;
2283}
2284#endif
2285
2286void QRegExpEngine::Box::cat( const Box& b )
2287{
2288 eng->addCatTransitions( rs, b.ls );
2289 addAnchorsToEngine( b );
2290 if ( minl == 0 ) {
2291 mergeInto( &lanchors, b.lanchors );
2292 if ( skipanchors != 0 ) {
2293 for ( int i = 0; i < (int) b.ls.size(); i++ ) {
2294 int a = eng->anchorConcatenation( at(lanchors, b.ls[i]),
2295 skipanchors );
2296 lanchors.insert( b.ls[i], a );
2297 }
2298 }
2299 mergeInto( &ls, b.ls );
2300 }
2301 if ( b.minl == 0 ) {
2302 mergeInto( &ranchors, b.ranchors );
2303 if ( b.skipanchors != 0 ) {
2304 for ( int i = 0; i < (int) rs.size(); i++ ) {
2305 int a = eng->anchorConcatenation( at(ranchors, rs[i]),
2306 b.skipanchors );
2307 ranchors.insert( rs[i], a );
2308 }
2309 }
2310 mergeInto( &rs, b.rs );
2311 } else {
2312 ranchors = b.ranchors;
2313 rs = b.rs;
2314 }
2315
2316#ifndef QT_NO_REGEXP_OPTIM
2317 if ( maxl != InftyLen ) {
2318 if ( rightStr.length() + b.leftStr.length() >
2319 QMAX(str.length(), b.str.length()) ) {
2320 earlyStart = minl - rightStr.length();
2321 lateStart = maxl - rightStr.length();
2322 str = rightStr + b.leftStr;
2323 } else if ( b.str.length() > str.length() ) {
2324 earlyStart = minl + b.earlyStart;
2325 lateStart = maxl + b.lateStart;
2326 str = b.str;
2327 }
2328 }
2329
2330 if ( (int) leftStr.length() == maxl )
2331 leftStr += b.leftStr;
2332 if ( (int) b.rightStr.length() == b.maxl )
2333 rightStr += b.rightStr;
2334 else
2335 rightStr = b.rightStr;
2336
2337 if ( maxl == InftyLen || b.maxl == InftyLen )
2338 maxl = InftyLen;
2339 else
2340 maxl += b.maxl;
2341
2342 occ1.detach();
2343 for ( int i = 0; i < NumBadChars; i++ ) {
2344 if ( b.occ1[i] != NoOccurrence && minl + b.occ1[i] < occ1[i] )
2345 occ1[i] = minl + b.occ1[i];
2346 }
2347#endif
2348
2349 minl += b.minl;
2350 if ( minl == 0 )
2351 skipanchors = eng->anchorConcatenation( skipanchors, b.skipanchors );
2352 else
2353 skipanchors = 0;
2354}
2355
2356void QRegExpEngine::Box::orx( const Box& b )
2357{
2358 mergeInto( &ls, b.ls );
2359 mergeInto( &lanchors, b.lanchors );
2360 mergeInto( &rs, b.rs );
2361 mergeInto( &ranchors, b.ranchors );
2362 skipanchors = eng->anchorAlternation( skipanchors, b.skipanchors );
2363
2364#ifndef QT_NO_REGEXP_OPTIM
2365 occ1.detach();
2366 for ( int i = 0; i < NumBadChars; i++ ) {
2367 if ( occ1[i] > b.occ1[i] )
2368 occ1[i] = b.occ1[i];
2369 }
2370 earlyStart = 0;
2371 lateStart = 0;
2372 str = QString::null;
2373 leftStr = QString::null;
2374 rightStr = QString::null;
2375 if ( b.maxl > maxl )
2376 maxl = b.maxl;
2377#endif
2378 if ( b.minl < minl )
2379 minl = b.minl;
2380}
2381
2382void QRegExpEngine::Box::plus( int atom )
2383{
2384#ifndef QT_NO_REGEXP_CAPTURE
2385 eng->addPlusTransitions( rs, ls, atom );
2386#else
2387 Q_UNUSED( atom );
2388 eng->addCatTransitions( rs, ls );
2389#endif
2390 addAnchorsToEngine( *this );
2391#ifndef QT_NO_REGEXP_OPTIM
2392 maxl = InftyLen;
2393#endif
2394}
2395
2396void QRegExpEngine::Box::opt()
2397{
2398#ifndef QT_NO_REGEXP_OPTIM
2399 earlyStart = 0;
2400 lateStart = 0;
2401 str = QString::null;
2402 leftStr = QString::null;
2403 rightStr = QString::null;
2404#endif
2405 skipanchors = 0;
2406 minl = 0;
2407}
2408
2409void QRegExpEngine::Box::catAnchor( int a )
2410{
2411 if ( a != 0 ) {
2412 for ( int i = 0; i < (int) rs.size(); i++ ) {
2413 a = eng->anchorConcatenation( at(ranchors, rs[i]), a );
2414 ranchors.insert( rs[i], a );
2415 }
2416 if ( minl == 0 )
2417 skipanchors = eng->anchorConcatenation( skipanchors, a );
2418 }
2419}
2420
2421#ifndef QT_NO_REGEXP_OPTIM
2422void QRegExpEngine::Box::setupHeuristics()
2423{
2424 eng->setupGoodStringHeuristic( earlyStart, lateStart, str );
2425
2426 /*
2427 A regular expression such as 112|1 has occ1['2'] = 2 and minl = 1 at this
2428 point. An entry of occ1 has to be at most minl or infinity for the rest
2429 of the algorithm to go well.
2430
2431 We waited until here before normalizing these cases (instead of doing it
2432 in Box::orx()) because sometimes things improve by themselves; consider
2433 (112|1)34.
2434 */
2435 for ( int i = 0; i < NumBadChars; i++ ) {
2436 if ( occ1[i] != NoOccurrence && occ1[i] >= minl )
2437 occ1[i] = minl;
2438 }
2439 eng->setupBadCharHeuristic( minl, occ1 );
2440
2441 eng->heuristicallyChooseHeuristic();
2442}
2443#endif
2444
2445#if defined(QT_DEBUG)
2446void QRegExpEngine::Box::dump() const
2447{
2448 int i;
2449 qDebug( "Box of at least %d character%s", minl, minl == 1 ? "" : "s" );
2450 qDebug( " Left states:" );
2451 for ( i = 0; i < (int) ls.size(); i++ ) {
2452 if ( at(lanchors, ls[i]) == 0 )
2453 qDebug( " %d", ls[i] );
2454 else
2455 qDebug( " %d [anchors 0x%.8x]", ls[i], lanchors[ls[i]] );
2456 }
2457 qDebug( " Right states:" );
2458 for ( i = 0; i < (int) rs.size(); i++ ) {
2459 if ( at(ranchors, ls[i]) == 0 )
2460 qDebug( " %d", rs[i] );
2461 else
2462 qDebug( " %d [anchors 0x%.8x]", rs[i], ranchors[rs[i]] );
2463 }
2464 qDebug( " Skip anchors: 0x%.8x", skipanchors );
2465}
2466#endif
2467
2468void QRegExpEngine::Box::addAnchorsToEngine( const Box& to ) const
2469{
2470 for ( int i = 0; i < (int) to.ls.size(); i++ ) {
2471 for ( int j = 0; j < (int) rs.size(); j++ ) {
2472 int a = eng->anchorConcatenation( at(ranchors, rs[j]),
2473 at(to.lanchors, to.ls[i]) );
2474 eng->addAnchors( rs[j], to.ls[i], a );
2475 }
2476 }
2477}
2478
2479int QRegExpEngine::getChar()
2480{
2481 return ( yyPos == yyLen ) ? EOS : yyIn[yyPos++].unicode();
2482}
2483
2484int QRegExpEngine::getEscape()
2485{
2486#ifndef QT_NO_REGEXP_ESCAPE
2487 const char tab[] = "afnrtv"; // no b, as \b means word boundary
2488 const char backTab[] = "\a\f\n\r\t\v";
2489 ushort low;
2490 int i;
2491#endif
2492 ushort val;
2493 int prevCh = yyCh;
2494
2495 if ( prevCh == EOS ) {
2496 yyError = TRUE;
2497 return Tok_Char | '\\';
2498 }
2499 yyCh = getChar();
2500#ifndef QT_NO_REGEXP_ESCAPE
2501 if ( (prevCh & ~0xff) == 0 ) {
2502 const char *p = strchr( tab, prevCh );
2503 if ( p != 0 )
2504 return Tok_Char | backTab[p - tab];
2505 }
2506#endif
2507
2508 switch ( prevCh ) {
2509#ifndef QT_NO_REGEXP_ESCAPE
2510 case '0':
2511 val = 0;
2512 for ( i = 0; i < 3; i++ ) {
2513 if ( yyCh >= '0' && yyCh <= '7' )
2514 val = ( val << 3 ) | ( yyCh - '0' );
2515 else
2516 break;
2517 yyCh = getChar();
2518 }
2519 if ( (val & ~0377) != 0 )
2520 yyError = TRUE;
2521 return Tok_Char | val;
2522#endif
2523#ifndef QT_NO_REGEXP_ESCAPE
2524 case 'B':
2525 return Tok_NonWord;
2526#endif
2527#ifndef QT_NO_REGEXP_CCLASS
2528 case 'D':
2529 // see QChar::isDigit()
2530 yyCharClass->addCategories( 0x7fffffef );
2531 return Tok_CharClass;
2532 case 'S':
2533 // see QChar::isSpace()
2534 yyCharClass->addCategories( 0x7ffff87f );
2535 yyCharClass->addRange( 0x0000, 0x0008 );
2536 yyCharClass->addRange( 0x000e, 0x001f );
2537 yyCharClass->addRange( 0x007f, 0x009f );
2538 return Tok_CharClass;
2539 case 'W':
2540 // see QChar::isLetterOrNumber()
2541 yyCharClass->addCategories( 0x7ff07f8f );
2542 return Tok_CharClass;
2543#endif
2544#ifndef QT_NO_REGEXP_ESCAPE
2545 case 'b':
2546 return Tok_Word;
2547#endif
2548#ifndef QT_NO_REGEXP_CCLASS
2549 case 'd':
2550 // see QChar::isDigit()
2551 yyCharClass->addCategories( 0x00000010 );
2552 return Tok_CharClass;
2553 case 's':
2554 // see QChar::isSpace()
2555 yyCharClass->addCategories( 0x00000380 );
2556 yyCharClass->addRange( 0x0009, 0x000d );
2557 return Tok_CharClass;
2558 case 'w':
2559 // see QChar::isLetterOrNumber()
2560 yyCharClass->addCategories( 0x000f8070 );
2561 return Tok_CharClass;
2562#endif
2563#ifndef QT_NO_REGEXP_ESCAPE
2564 case 'x':
2565 val = 0;
2566 for ( i = 0; i < 4; i++ ) {
2567 low = QChar( yyCh ).lower();
2568 if ( low >= '0' && low <= '9' )
2569 val = ( val << 4 ) | ( low - '0' );
2570 else if ( low >= 'a' && low <= 'f' )
2571 val = ( val << 4 ) | ( low - 'a' + 10 );
2572 else
2573 break;
2574 yyCh = getChar();
2575 }
2576 return Tok_Char | val;
2577#endif
2578 default:
2579 if ( prevCh >= '1' && prevCh <= '9' ) {
2580#ifndef QT_NO_REGEXP_BACKREF
2581 val = prevCh - '0';
2582 while ( yyCh >= '0' && yyCh <= '9' ) {
2583 val = ( val *= 10 ) | ( yyCh - '0' );
2584 yyCh = getChar();
2585 }
2586 return Tok_BackRef | val;
2587#else
2588 yyError = TRUE;
2589#endif
2590 }
2591 return Tok_Char | prevCh;
2592 }
2593}
2594
2595#ifndef QT_NO_REGEXP_INTERVAL
2596int QRegExpEngine::getRep( int def )
2597{
2598 if ( yyCh >= '0' && yyCh <= '9' ) {
2599 int rep = 0;
2600 do {
2601 rep = 10 * rep + yyCh - '0';
2602 if ( rep >= InftyRep ) {
2603 yyError = TRUE;
2604 rep = def;
2605 }
2606 yyCh = getChar();
2607 } while ( yyCh >= '0' && yyCh <= '9' );
2608 return rep;
2609 } else {
2610 return def;
2611 }
2612}
2613#endif
2614
2615#ifndef QT_NO_REGEXP_LOOKAHEAD
2616void QRegExpEngine::skipChars( int n )
2617{
2618 if ( n > 0 ) {
2619 yyPos += n - 1;
2620 yyCh = getChar();
2621 }
2622}
2623#endif
2624
2625void QRegExpEngine::startTokenizer( const QChar *rx, int len )
2626{
2627 yyIn = rx;
2628 yyPos0 = 0;
2629 yyPos = 0;
2630 yyLen = len;
2631 yyCh = getChar();
2632 yyCharClass = new CharClass;
2633 yyMinRep = 0;
2634 yyMaxRep = 0;
2635 yyError = FALSE;
2636}
2637
2638int QRegExpEngine::getToken()
2639{
2640#ifndef QT_NO_REGEXP_CCLASS
2641 ushort pendingCh = 0;
2642 bool charPending;
2643 bool rangePending;
2644 int tok;
2645#endif
2646 int prevCh = yyCh;
2647
2648 yyPos0 = yyPos - 1;
2649#ifndef QT_NO_REGEXP_CCLASS
2650 yyCharClass->clear();
2651#endif
2652 yyMinRep = 0;
2653 yyMaxRep = 0;
2654 yyCh = getChar();
2655 switch ( prevCh ) {
2656 case EOS:
2657 yyPos0 = yyPos;
2658 return Tok_Eos;
2659 case '$':
2660 return Tok_Dollar;
2661 case '(':
2662 if ( yyCh == '?' ) {
2663 prevCh = getChar();
2664 yyCh = getChar();
2665 switch ( prevCh ) {
2666#ifndef QT_NO_REGEXP_LOOKAHEAD
2667 case '!':
2668 return Tok_NegLookahead;
2669 case '=':
2670 return Tok_PosLookahead;
2671#endif
2672 case ':':
2673 return Tok_MagicLeftParen;
2674 default:
2675 yyError = TRUE;
2676 return Tok_MagicLeftParen;
2677 }
2678 } else {
2679 return Tok_LeftParen;
2680 }
2681 case ')':
2682 return Tok_RightParen;
2683 case '*':
2684 yyMinRep = 0;
2685 yyMaxRep = InftyRep;
2686 return Tok_Quantifier;
2687 case '+':
2688 yyMinRep = 1;
2689 yyMaxRep = InftyRep;
2690 return Tok_Quantifier;
2691 case '.':
2692#ifndef QT_NO_REGEXP_CCLASS
2693 yyCharClass->setNegative( TRUE );
2694#endif
2695 return Tok_CharClass;
2696 case '?':
2697 yyMinRep = 0;
2698 yyMaxRep = 1;
2699 return Tok_Quantifier;
2700 case '[':
2701#ifndef QT_NO_REGEXP_CCLASS
2702 if ( yyCh == '^' ) {
2703 yyCharClass->setNegative( TRUE );
2704 yyCh = getChar();
2705 }
2706 charPending = FALSE;
2707 rangePending = FALSE;
2708 do {
2709 if ( yyCh == '-' && charPending && !rangePending ) {
2710 rangePending = TRUE;
2711 yyCh = getChar();
2712 } else {
2713 if ( charPending && !rangePending ) {
2714 yyCharClass->addSingleton( pendingCh );
2715 charPending = FALSE;
2716 }
2717 if ( yyCh == '\\' ) {
2718 yyCh = getChar();
2719 tok = getEscape();
2720 if ( tok == Tok_Word )
2721 tok = '\b';
2722 } else {
2723 tok = Tok_Char | yyCh;
2724 yyCh = getChar();
2725 }
2726 if ( tok == Tok_CharClass ) {
2727 if ( rangePending ) {
2728 yyCharClass->addSingleton( '-' );
2729 yyCharClass->addSingleton( pendingCh );
2730 charPending = FALSE;
2731 rangePending = FALSE;
2732 }
2733 } else if ( (tok & Tok_Char) != 0 ) {
2734 if ( rangePending ) {
2735 yyCharClass->addRange( pendingCh, tok ^ Tok_Char );
2736 charPending = FALSE;
2737 rangePending = FALSE;
2738 } else {
2739 pendingCh = tok ^ Tok_Char;
2740 charPending = TRUE;
2741 }
2742 } else {
2743 yyError = TRUE;
2744 }
2745 }
2746 } while ( yyCh != ']' && yyCh != EOS );
2747 if ( rangePending )
2748 yyCharClass->addSingleton( '-' );
2749 if ( charPending )
2750 yyCharClass->addSingleton( pendingCh );
2751 if ( yyCh == EOS )
2752 yyError = TRUE;
2753 else
2754 yyCh = getChar();
2755 return Tok_CharClass;
2756#else
2757 yyError = TRUE;
2758 return Tok_Char | '[';
2759#endif
2760 case '\\':
2761 return getEscape();
2762 case ']':
2763 yyError = TRUE;
2764 return Tok_Char | ']';
2765 case '^':
2766 return Tok_Caret;
2767#ifndef QT_NO_REGEXP_INTERVAL
2768 case '{':
2769 yyMinRep = getRep( 0 );
2770 yyMaxRep = yyMinRep;
2771 if ( yyCh == ',' ) {
2772 yyCh = getChar();
2773 yyMaxRep = getRep( InftyRep );
2774 }
2775 if ( yyMaxRep < yyMinRep )
2776 qSwap( yyMinRep, yyMaxRep );
2777 if ( yyCh != '}' )
2778 yyError = TRUE;
2779 yyCh = getChar();
2780 return Tok_Quantifier;
2781#else
2782 yyError = TRUE;
2783 return Tok_Char | '{';
2784#endif
2785 case '|':
2786 return Tok_Bar;
2787 case '}':
2788 yyError = TRUE;
2789 return Tok_Char | '}';
2790 default:
2791 return Tok_Char | prevCh;
2792 }
2793}
2794
2795int QRegExpEngine::parse( const QChar *pattern, int len )
2796{
2797 valid = TRUE;
2798 startTokenizer( pattern, len );
2799 yyTok = getToken();
2800#ifndef QT_NO_REGEXP_CAPTURE
2801 yyMayCapture = TRUE;
2802#else
2803 yyMayCapture = FALSE;
2804#endif
2805
2806#ifndef QT_NO_REGEXP_CAPTURE
2807 int atom = startAtom( FALSE );
2808#endif
2809 CharClass anything;
2810 Box box( this ); // create InitialState
2811 box.set( anything );
2812 Box rightBox( this ); // create FinalState
2813 rightBox.set( anything );
2814
2815 Box middleBox( this );
2816 parseExpression( &middleBox );
2817#ifndef QT_NO_REGEXP_CAPTURE
2818 finishAtom( atom );
2819#endif
2820#ifndef QT_NO_REGEXP_OPTIM
2821 middleBox.setupHeuristics();
2822#endif
2823 box.cat( middleBox );
2824 box.cat( rightBox );
2825 delete yyCharClass;
2826 yyCharClass = 0;
2827
2828 realncap = ncap;
2829#ifndef QT_NO_REGEXP_BACKREF
2830 if ( nbrefs > ncap )
2831 ncap = nbrefs;
2832#endif
2833
2834 mmCaptured.resize( 2 + 2 * realncap );
2835 mmCapturedNoMatch.fill( -1, 2 + 2 * realncap );
2836
2837 /*
2838 We use one QArray<int> for all the big data used a lot in matchHere() and
2839 friends.
2840 */
2841#ifndef QT_NO_REGEXP_OPTIM
2842 mmSlideTabSize = QMAX( minl + 1, 16 );
2843#else
2844 mmSlideTabSize = 0;
2845#endif
2846 mmBigArray.resize( (3 + 4 * ncap) * ns + 4 * ncap + mmSlideTabSize );
2847
2848 mmInNextStack = mmBigArray.data();
2849 memset( mmInNextStack, -1, ns * sizeof(int) );
2850 mmCurStack = mmInNextStack + ns;
2851 mmNextStack = mmInNextStack + 2 * ns;
2852
2853 mmCurCapBegin = mmInNextStack + 3 * ns;
2854 mmNextCapBegin = mmCurCapBegin + ncap * ns;
2855 mmCurCapEnd = mmCurCapBegin + 2 * ncap * ns;
2856 mmNextCapEnd = mmCurCapBegin + 3 * ncap * ns;
2857
2858 mmTempCapBegin = mmCurCapBegin + 4 * ncap * ns;
2859 mmTempCapEnd = mmTempCapBegin + ncap;
2860 mmCapBegin = mmTempCapBegin + 2 * ncap;
2861 mmCapEnd = mmTempCapBegin + 3 * ncap;
2862
2863 mmSlideTab = mmTempCapBegin + 4 * ncap;
2864
2865 if ( yyError )
2866 return -1;
2867
2868#ifndef QT_NO_REGEXP_OPTIM
2869 State *sinit = s[InitialState];
2870 caretAnchored = ( sinit->anchors != 0 );
2871 if ( caretAnchored ) {
2872 QMap<int, int>& anchors = *sinit->anchors;
2873 QMap<int, int>::ConstIterator a;
2874 for ( a = anchors.begin(); a != anchors.end(); ++a ) {
2875#ifndef QT_NO_REGEXP_ANCHOR_ALT
2876 if ( (*a & Anchor_Alternation) != 0 )
2877 break;
2878#endif
2879 if ( (*a & Anchor_Caret) == 0 ) {
2880 caretAnchored = FALSE;
2881 break;
2882 }
2883 }
2884 }
2885#endif
2886 return yyPos0;
2887}
2888
2889void QRegExpEngine::parseAtom( Box *box )
2890{
2891#ifndef QT_NO_REGEXP_LOOKAHEAD
2892 QRegExpEngine *eng = 0;
2893 bool neg;
2894 int len;
2895#endif
2896
2897 switch ( yyTok ) {
2898 case Tok_Dollar:
2899 box->catAnchor( Anchor_Dollar );
2900 break;
2901 case Tok_Caret:
2902 box->catAnchor( Anchor_Caret );
2903 break;
2904#ifndef QT_NO_REGEXP_LOOKAHEAD
2905 case Tok_PosLookahead:
2906 case Tok_NegLookahead:
2907 neg = ( yyTok == Tok_NegLookahead );
2908 eng = new QRegExpEngine( cs );
2909 len = eng->parse( yyIn + yyPos - 1, yyLen - yyPos + 1 );
2910 if ( len >= 0 )
2911 skipChars( len );
2912 else
2913 yyError = TRUE;
2914 box->catAnchor( addLookahead(eng, neg) );
2915 yyTok = getToken();
2916 if ( yyTok != Tok_RightParen )
2917 yyError = TRUE;
2918 break;
2919#endif
2920#ifndef QT_NO_REGEXP_ESCAPE
2921 case Tok_Word:
2922 box->catAnchor( Anchor_Word );
2923 break;
2924 case Tok_NonWord:
2925 box->catAnchor( Anchor_NonWord );
2926 break;
2927#endif
2928 case Tok_LeftParen:
2929 case Tok_MagicLeftParen:
2930 yyTok = getToken();
2931 parseExpression( box );
2932 if ( yyTok != Tok_RightParen )
2933 yyError = TRUE;
2934 break;
2935 case Tok_CharClass:
2936 box->set( *yyCharClass );
2937 break;
2938 default:
2939 if ( (yyTok & Tok_Char) != 0 )
2940 box->set( QChar(yyTok ^ Tok_Char) );
2941#ifndef QT_NO_REGEXP_BACKREF
2942 else if ( (yyTok & Tok_BackRef) != 0 )
2943 box->set( yyTok ^ Tok_BackRef );
2944#endif
2945 else
2946 yyError = TRUE;
2947 }
2948 yyTok = getToken();
2949}
2950
2951void QRegExpEngine::parseFactor( Box *box )
2952{
2953#ifndef QT_NO_REGEXP_CAPTURE
2954 int atom = startAtom( yyMayCapture && yyTok == Tok_LeftParen );
2955#else
2956 static const int atom = 0;
2957#endif
2958
2959#ifndef QT_NO_REGEXP_INTERVAL
2960#define YYREDO() \
2961 yyIn = in, yyPos0 = pos0, yyPos = pos, yyLen = len, yyCh = ch, \
2962 *yyCharClass = charClass, yyMinRep = 0, yyMaxRep = 0, yyTok = tok
2963
2964 const QChar *in = yyIn;
2965 int pos0 = yyPos0;
2966 int pos = yyPos;
2967 int len = yyLen;
2968 int ch = yyCh;
2969 CharClass charClass;
2970 if ( yyTok == Tok_CharClass )
2971 charClass = *yyCharClass;
2972 int tok = yyTok;
2973 bool mayCapture = yyMayCapture;
2974#endif
2975
2976 parseAtom( box );
2977#ifndef QT_NO_REGEXP_CAPTURE
2978 finishAtom( atom );
2979#endif
2980
2981 if ( yyTok == Tok_Quantifier ) {
2982 if ( yyMaxRep == InftyRep ) {
2983 box->plus( atom );
2984#ifndef QT_NO_REGEXP_INTERVAL
2985 } else if ( yyMaxRep == 0 ) {
2986 box->clear();
2987#endif
2988 }
2989 if ( yyMinRep == 0 )
2990 box->opt();
2991
2992#ifndef QT_NO_REGEXP_INTERVAL
2993 yyMayCapture = FALSE;
2994 int alpha = ( yyMinRep == 0 ) ? 0 : yyMinRep - 1;
2995 int beta = ( yyMaxRep == InftyRep ) ? 0 : yyMaxRep - ( alpha + 1 );
2996
2997 Box rightBox( this );
2998 int i;
2999
3000 for ( i = 0; i < beta; i++ ) {
3001 YYREDO();
3002 Box leftBox( this );
3003 parseAtom( &leftBox );
3004 leftBox.cat( rightBox );
3005 leftBox.opt();
3006 rightBox = leftBox;
3007 }
3008 for ( i = 0; i < alpha; i++ ) {
3009 YYREDO();
3010 Box leftBox( this );
3011 parseAtom( &leftBox );
3012 leftBox.cat( rightBox );
3013 rightBox = leftBox;
3014 }
3015 rightBox.cat( *box );
3016 *box = rightBox;
3017#endif
3018 yyTok = getToken();
3019#ifndef QT_NO_REGEXP_INTERVAL
3020 yyMayCapture = mayCapture;
3021#endif
3022 }
3023#undef YYREDO
3024}
3025
3026void QRegExpEngine::parseTerm( Box *box )
3027{
3028#ifndef QT_NO_REGEXP_OPTIM
3029 if ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar )
3030 parseFactor( box );
3031#endif
3032 while ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) {
3033 Box rightBox( this );
3034 parseFactor( &rightBox );
3035 box->cat( rightBox );
3036 }
3037}
3038
3039void QRegExpEngine::parseExpression( Box *box )
3040{
3041 parseTerm( box );
3042 while ( yyTok == Tok_Bar ) {
3043 Box rightBox( this );
3044 yyTok = getToken();
3045 parseTerm( &rightBox );
3046 box->orx( rightBox );
3047 }
3048}
3049
3050/*
3051 The class QRegExpPrivate contains the private data of a regular expression
3052 other than the automaton. It makes it possible for many QRegExp objects to
3053 use the same QRegExpEngine object with different QRegExpPrivate objects.
3054*/
3055struct QRegExpPrivate
3056{
3057 QString pattern; // regular-expression or wildcard pattern
3058 QString rxpattern; // regular-expression pattern
3059#ifndef QT_NO_REGEXP_WILDCARD
3060 bool wc; // wildcard mode?
3061#endif
3062 bool min; // minimal matching? (instead of maximal)
3063#ifndef QT_NO_REGEXP_CAPTURE
3064 QString t; // last string passed to QRegExp::search() or searchRev()
3065 QStringList capturedCache; // what QRegExp::capturedTexts() returned last
3066#endif
3067 QArray<int> captured; // what QRegExpEngine::search() returned last
3068
3069 QRegExpPrivate() { captured.fill( -1, 2 ); }
3070};
3071
3072#ifndef QT_NO_REGEXP_OPTIM
3073static QCache<QRegExpEngine> *engineCache = 0;
3074#endif
3075
3076static QRegExpEngine *newEngine( const QString& pattern, bool caseSensitive )
3077{
3078#ifndef QT_NO_REGEXP_OPTIM
3079 if ( engineCache != 0 ) {
3080 QRegExpEngine *eng = engineCache->take( pattern );
3081 if ( eng == 0 || eng->caseSensitive() != caseSensitive ) {
3082 delete eng;
3083 } else {
3084 eng->ref();
3085 return eng;
3086 }
3087 }
3088#endif
3089 return new QRegExpEngine( pattern, caseSensitive );
3090}
3091
3092static void derefEngine( QRegExpEngine *eng, const QString& pattern )
3093{
3094 if ( eng != 0 && eng->deref() ) {
3095#ifndef QT_NO_REGEXP_OPTIM
3096 if ( engineCache == 0 ) {
3097 engineCache = new QCache<QRegExpEngine>;
3098 engineCache->setAutoDelete( TRUE );
3099 }
3100 if ( !pattern.isNull() &&
3101 engineCache->insert(pattern, eng, 4 + pattern.length() / 4) )
3102 return;
3103#else
3104 Q_UNUSED( pattern );
3105#endif
3106 delete eng;
3107 }
3108}
3109
3110/*!
3111 Constructs an empty regexp.
3112
3113 \sa isValid()
3114*/
3115QRegExp3::QRegExp3()
3116{
3117 eng = new QRegExpEngine( TRUE );
3118 priv = new QRegExpPrivate;
3119 priv->pattern = QString::null;
3120#ifndef QT_NO_REGEXP_WILDCARD
3121 priv->wc = FALSE;
3122#endif
3123 priv->min = FALSE;
3124 compile( TRUE );
3125}
3126
3127/*!
3128 Constructs a regular expression object for the given \a pattern
3129 string. The pattern must be given using wildcard notation if \a
3130 wildcard is TRUE (default is FALSE). The pattern is case sensitive,
3131 unless \a caseSensitive is FALSE. Matching is greedy (maximal), but
3132 can be changed by calling setMinimal().
3133
3134 \sa setPattern() setCaseSensitive() setWildcard() setMinimal()
3135*/
3136QRegExp3::QRegExp3( const QString& pattern, bool caseSensitive, bool wildcard )
3137{
3138 eng = 0;
3139 priv = new QRegExpPrivate;
3140 priv->pattern = pattern;
3141#ifndef QT_NO_REGEXP_WILDCARD
3142 priv->wc = wildcard;
3143#endif
3144 priv->min = FALSE;
3145 compile( caseSensitive );
3146}
3147
3148/*!
3149 Constructs a regular expression as a copy of \a rx.
3150
3151 \sa operator=()
3152*/
3153QRegExp3::QRegExp3( const QRegExp3& rx )
3154{
3155 eng = 0;
3156 priv = new QRegExpPrivate;
3157 operator=( rx );
3158}
3159
3160/*!
3161 Destroys the regular expression and cleans up its internal data.
3162*/
3163QRegExp3::~QRegExp3()
3164{
3165 derefEngine( eng, priv->rxpattern );
3166 delete priv;
3167}
3168
3169/*!
3170 Copies the regular expression \a rx and returns a reference to the copy.
3171 The case sensitivity, wildcard and minimal matching options are copied as
3172 well.
3173*/
3174QRegExp3& QRegExp3::operator=( const QRegExp3& rx )
3175{
3176 rx.eng->ref();
3177 derefEngine( eng, priv->rxpattern );
3178 eng = rx.eng;
3179 priv->pattern = rx.priv->pattern;
3180 priv->rxpattern = rx.priv->rxpattern;
3181#ifndef QT_NO_REGEXP_WILDCARD
3182 priv->wc = rx.priv->wc;
3183#endif
3184 priv->min = rx.priv->min;
3185#ifndef QT_NO_REGEXP_CAPTURE
3186 priv->t = rx.priv->t;
3187 priv->capturedCache = rx.priv->capturedCache;
3188#endif
3189 priv->captured = rx.priv->captured;
3190 return *this;
3191}
3192
3193/*!
3194 Returns TRUE if this regular expression is equal to \a rx, otherwise
3195 returns FALSE.
3196
3197 Two QRegExp3 objects are equal if they have the same pattern strings
3198 and the same settings for case sensitivity, wildcard and minimal
3199 matching.
3200*/
3201bool QRegExp3::operator==( const QRegExp3& rx ) const
3202{
3203 return priv->pattern == rx.priv->pattern &&
3204 eng->caseSensitive() == rx.eng->caseSensitive() &&
3205#ifndef QT_NO_REGEXP_WILDCARD
3206 priv->wc == rx.priv->wc &&
3207#endif
3208 priv->min == rx.priv->min;
3209}
3210
3211/*! \fn bool QRegExp3::operator!=( const QRegExp& rx ) const
3212
3213 Returns TRUE if this regular expression is not equal to \a rx, otherwise
3214 FALSE.
3215
3216 \sa operator==()
3217*/
3218
3219/*!
3220 Returns TRUE if the pattern string is empty, otherwise FALSE.
3221
3222 If you call match() with an empty pattern on an empty string it will
3223 return TRUE otherwise it returns FALSE since match() operates over the
3224 whole string. If you call search() with an empty pattern on \e any
3225 string it will return the start position (0 by default) since it will
3226 match at the start position, because the empty pattern matches the
3227 'emptiness' at the start of the string, and the length of the match
3228 returned by matchedLength() will be 0.
3229
3230 See QString::isEmpty().
3231*/
3232
3233bool QRegExp3::isEmpty() const
3234{
3235 return priv->pattern.isEmpty();
3236}
3237
3238/*!
3239 Returns TRUE if the regular expression is valid, or FALSE if it's invalid. An
3240 invalid regular expression never matches.
3241
3242 The pattern <b>[a-z</b> is an example of an invalid pattern, since it lacks
3243 a closing square bracket.
3244
3245 Note that the validity of a regexp may also depend on the setting of
3246 the wildcard flag, for example <b>*.html</b> is a valid wildcard
3247 regexp but an invalid full regexp.
3248*/
3249bool QRegExp3::isValid() const
3250{
3251 return eng->isValid();
3252}
3253
3254/*!
3255 Returns the pattern string of the regular expression. The pattern has either
3256 regular expression syntax or wildcard syntax, depending on wildcard().
3257
3258 \sa setPattern()
3259*/
3260QString QRegExp3::pattern() const
3261{
3262 return priv->pattern;
3263}
3264
3265/*!
3266 Sets the pattern string to \a pattern and returns a reference to this regular
3267 expression. The case sensitivity, wildcard and minimal matching options are
3268 not changed.
3269
3270 \sa pattern()
3271*/
3272void QRegExp3::setPattern( const QString& pattern )
3273{
3274 if ( priv->pattern != pattern ) {
3275 priv->pattern = pattern;
3276 compile( caseSensitive() );
3277 }
3278}
3279
3280/*!
3281 Returns TRUE if case sensitivity is enabled, otherwise FALSE. The default is
3282 TRUE.
3283
3284 \sa setCaseSensitive()
3285*/
3286bool QRegExp3::caseSensitive() const
3287{
3288 return eng->caseSensitive();
3289}
3290
3291/*!
3292 Sets case sensitive matching to \a sensitive.
3293
3294 If \a sensitive is TRUE, <b>\\</b><b>.txt$</b> matches
3295 <tt>readme.txt</tt> but not <tt>README.TXT</tt>.
3296
3297 \sa caseSensitive()
3298*/
3299void QRegExp3::setCaseSensitive( bool sensitive )
3300{
3301 if ( sensitive != eng->caseSensitive() )
3302 compile( sensitive );
3303}
3304
3305#ifndef QT_NO_REGEXP_WILDCARD
3306/*!
3307 Returns TRUE if wildcard mode is enabled, otherwise FALSE. The default is
3308 FALSE.
3309
3310 \sa setWildcard()
3311*/
3312bool QRegExp3::wildcard() const
3313{
3314 return priv->wc;
3315}
3316
3317/*! Sets the wildcard mode for the regular expression. The default is FALSE.
3318
3319 Setting \a wildcard to TRUE enables simple shell-like wildcard
3320 matching.
3321 (See <a href="#wildcard-matching">wildcard matching (globbing)</a>.)
3322
3323 For example, <b>r*.txt</b> matches the string <tt>readme.txt</tt> in wildcard
3324 mode, but does not match <tt>readme</tt>.
3325
3326 \sa wildcard()
3327*/
3328void QRegExp3::setWildcard( bool wildcard )
3329{
3330 if ( wildcard != priv->wc ) {
3331 priv->wc = wildcard;
3332 compile( caseSensitive() );
3333 }
3334}
3335#endif
3336
3337/*! Returns TRUE if minimal (non-greedy) matching is enabled, otherwise
3338 returns FALSE.
3339
3340 \sa setMinimal()
3341*/
3342bool QRegExp3::minimal() const
3343{
3344 return priv->min;
3345}
3346
3347/*!
3348 Enables or disables minimal matching. If \a minimal is FALSE, matching is
3349 greedy (maximal) which is the default.
3350
3351 For example, suppose we have the input string "We must be \<b>bold\</b>,
3352 very \<b>bold\</b>!" and the pattern <b>\<b>.*\</b></b>. With
3353 the default greedy (maximal) matching, the match is
3354 "We must be <u>\<b>bold\</b>, very \<b>bold\</b></u>!". But with
3355 minimal (non-greedy) matching the first match is:
3356 "We must be <u>\<b>bold\</b></u>, very \<b>bold\</b>!" and the
3357 second match is
3358 "We must be \<b>bold\</b>, very <u>\<b>bold\</b></u>!".
3359 In practice we might use the pattern <b>\<b>[^\<]+\</b></b>,
3360 although this will still fail for nested tags.
3361
3362 \sa minimal()
3363*/
3364void QRegExp3::setMinimal( bool minimal )
3365{
3366 priv->min = minimal;
3367}
3368
3369/*!
3370 Returns TRUE if \a str is matched exactly by this regular expression
3371 otherwise it returns FALSE. You can determine how much of the string was
3372 matched by calling matchedLength().
3373
3374 For a given regexp string, R, <tt>match("R")</tt> is the equivalent
3375 of <tt>search("^R$")</tt> since match() effectively encloses the
3376 regexp in the start of string and end of string anchors.
3377
3378 For example, if the regular expression is <b>blue</b>, then match()
3379 returns TRUE only for input <tt>blue</tt>. For inputs
3380 <tt>bluebell</tt>, <tt>blutak</tt> and <tt>lightblue</tt>, match()
3381 returns FALSE and matchedLength() will return 4, 3 and 0 respectively.
3382
3383 \sa search() searchRev() QRegExpValidator
3384*/
3385bool QRegExp3::exactMatch( const QString& str )
3386{
3387#ifndef QT_NO_REGEXP_CAPTURE
3388 priv->t = str;
3389 priv->capturedCache.clear();
3390#endif
3391
3392 priv->captured = eng->match( str, 0, priv->min, TRUE );
3393 if ( priv->captured[1] == (int) str.length() ) {
3394 return TRUE;
3395 } else {
3396 priv->captured.detach();
3397 priv->captured[0] = 0;
3398 priv->captured[1] = eng->matchedLength();
3399 return FALSE;
3400 }
3401}
3402
3403/*! \overload
3404
3405 This version does not set matchedLength(), capturedTexts() and friends.
3406*/
3407bool QRegExp3::exactMatch( const QString& str ) const
3408{
3409 return eng->match(str, 0, priv->min, TRUE)[0] == 0 &&
3410 eng->matchedLength() == (int) str.length();
3411}
3412
3413/*! \obsolete
3414
3415 Attempts to match in \a str, starting from position \a index. Returns the
3416 position of the match, or -1 if there was no match.
3417
3418 The length of the match is stored in \a *len, unless \a len is a null pointer.
3419
3420 If \a indexIsStart is TRUE (the default), the position \a index in the string
3421 will match the start of string anchor, <b>^</b>, in the regexp, if present.
3422 Otherwise, position 0 in \a str will match.
3423
3424 Use search() and matchedLength() instead of this function.
3425
3426 If you really need the \a indexIsStart functionality, try this:
3427
3428 \code
3429 QRegExp3 rx( "some pattern" );
3430 int pos = rx.search( str.mid( index ) );
3431 if ( pos != -1 )
3432 pos += index;
3433 int len = rx.matchedLength();
3434 \endcode
3435*/
3436#ifndef QT_NO_COMPAT
3437int QRegExp3::match( const QString& str, int index, int *len,
3438 bool indexIsStart )
3439{
3440 int pos;
3441 if ( indexIsStart ) {
3442 pos = search( str.mid(index) );
3443 if ( pos >= 0 ) {
3444 pos += index;
3445 if ( len != 0 )
3446 *len = matchedLength();
3447 } else {
3448 if ( len != 0 )
3449 *len = 0;
3450 }
3451 } else {
3452 pos = search( str, index );
3453 if ( len != 0 )
3454 *len = matchedLength();
3455 }
3456 return pos;
3457}
3458#endif
3459
3460/*!
3461 Attempts to find a match in \a str from position \a start (0 by default). If
3462 \a start is -1, the search starts at the last character; if -2, at the next to
3463 last character; etc.
3464
3465 Returns the position of the first match, or -1 if there was no match.
3466
3467 You might prefer to use QString::find(), QString::contains() or even
3468 QStringList::grep(). To replace matches use QString::replace().
3469
3470 Example:
3471 \code
3472 QString str = "offsets: 1.23 .50 71.00 6.00";
3473 QRegExp3 rx( "\\d*\\.\\d+" ); // very simple floating point matching
3474 int count = 0;
3475 int pos = 0;
3476 while ( pos >= 0 ) {
3477 pos = rx.search( str, pos );
3478 count++;
3479 }
3480 // pos will be 9, 14, 18 and finally 24; count will end up as 4.
3481 \endcode
3482
3483 \sa searchRev() match() matchedLength() capturedTexts()
3484*/
3485// QChar versions
3486
3487#ifdef QCHAR_SUPPORT
3488const QString makeString(const QChar *str)
3489{
3490// A sentinel value checked in case the QChar *ptr is never null terminated
3491 const uint MAXLENGTH=65535;
3492
3493 const QChar *s=str;
3494 uint i=0;
3495 while(i < MAXLENGTH && *s != QChar::null) { i++;s++ ;}
3496 return QString(str,i);
3497
3498}
3499int QRegExp3::search(const QChar *str,int start)
3500{
3501 return search(makeString(str),start);
3502}
3503int QRegExp3::search(const QChar *str,int start) const
3504{
3505 return search(makeString(str),start);
3506}
3507int QRegExp3::searchRev(const QChar *str,int start)
3508{
3509 return searchRev(makeString(str),start);
3510}
3511int QRegExp3::searchRev(const QChar *str,int start) const
3512{
3513 return searchRev(makeString(str),start);
3514}
3515bool QRegExp3::exactMatch(const QChar *str)
3516{
3517 return exactMatch(makeString(str));
3518}
3519bool QRegExp3::exactMatch(const QChar *str) const
3520{
3521 return exactMatch(makeString(str));
3522}
3523#endif // QCHAR_SUPPORT
3524
3525int QRegExp3::search( const QString& str, int start )
3526{
3527 if ( start < 0 )
3528 start += str.length();
3529#ifndef QT_NO_REGEXP_CAPTURE
3530 priv->t = str;
3531 priv->capturedCache.clear();
3532#endif
3533 priv->captured = eng->match( str, start, priv->min, FALSE );
3534 return priv->captured[0];
3535}
3536
3537/*! \overload
3538
3539 This version does not set matchedLength(), capturedTexts() and friends.
3540*/
3541int QRegExp3::search( const QString& str, int start ) const
3542{
3543 if ( start < 0 )
3544 start += str.length();
3545 return eng->match( str, start, priv->min, FALSE )[0];
3546}
3547
3548/*!
3549 Attempts to find a match backwards in \a str from position \a start. If
3550 \a start is -1 (the default), the search starts at the last character; if -2,
3551 at the next to last character; etc.
3552
3553 Returns the position of the first match, or -1 if there was no match.
3554
3555 You might prefer to use QString::findRev().
3556
3557 \sa search() matchedLength() capturedTexts()
3558*/
3559int QRegExp3::searchRev( const QString& str, int start )
3560{
3561 if ( start < 0 )
3562 start += str.length();
3563#ifndef QT_NO_REGEXP_CAPTURE
3564 priv->t = str;
3565 priv->capturedCache.clear();
3566#endif
3567 if ( start < 0 || start > (int) str.length() ) {
3568 priv->captured.detach();
3569 priv->captured.fill( -1 );
3570 return -1;
3571 }
3572
3573 while ( start >= 0 ) {
3574 priv->captured = eng->match( str, start, priv->min, TRUE );
3575 if ( priv->captured[0] == start )
3576 return start;
3577 start--;
3578 }
3579 return -1;
3580}
3581
3582/*! \overload
3583
3584 This version does not set matchedLength(), capturedText() and friends.
3585*/
3586int QRegExp3::searchRev( const QString& str, int start ) const
3587{
3588 if ( start < 0 )
3589 start += str.length();
3590 if ( start < 0 || start > (int) str.length() )
3591 return -1;
3592
3593 while ( start >= 0 ) {
3594 if ( eng->match(str, start, priv->min, TRUE)[0] == start )
3595 return start;
3596 start--;
3597 }
3598 return -1;
3599}
3600
3601/*!
3602 Returns the length of the last matched string, or -1 if there was no match.
3603
3604 \sa match() search()
3605*/
3606int QRegExp3::matchedLength()
3607{
3608 return priv->captured[1];
3609}
3610
3611#ifndef QT_NO_REGEXP_CAPTURE
3612/*!
3613 Returns a list of the captured text strings.
3614
3615 The first string in the list is the entire matched string. Each
3616 subsequent list element contains a string that matched a
3617 (capturing) subexpression of the regexp.
3618
3619 For example:
3620 \code
3621 QRegExp3 rx( "(\\d+)(\\s*)(cm|inch(es)?)" );
3622 int pos = rx.search( "Length: 36 inches" );
3623 QStringList list = rx.capturedTexts();
3624 // list is now ( "36 inches", "36", " ", "inches", "es" ).
3625 \endcode
3626
3627 The above example also captures elements
3628 that may be present but which we have no interest in. This problem
3629 can be solved by using non-capturing parenthesis:
3630
3631 \code
3632 QRegExp3 rx( "(\\d+)(?:\\s*)(cm|inch(?:es)?)" );
3633 int pos = rx.search( "Length: 36 inches" );
3634 QStringList list = rx.capturedTexts();
3635 // list is now ( "36 inches", "36", "inches" ).
3636 \endcode
3637
3638 Some regexps can match an indeterminate number of times. For example
3639 if the input string is "Offsets: 12 14 99 231 7" and the regexp,
3640 <tt>rx</tt>, is <b>(</b><b>\\</b><b>d+)+</b>, we would hope to get a
3641 list of all the numbers matched. However, after calling
3642 <tt>rx.search(str)</tt>, capturedTexts() will return the list ( "12",
3643 "12" ), i.e. the entire match was "12" and the first subexpression
3644 matched was "12". The correct approach is to use cap() in a
3645 <a href="#cap_in_a_loop">loop</a>.
3646
3647 The order of elements in the string list is as follows. The first
3648 element is the entire matching string. Each subsequent element
3649 corresponds to the next capturing open left parenthesis. Thus
3650 capturedTexts()[1] is the text of the first capturing parenthesis,
3651 capturedTexts()[2] is the text of the second and so on (corresponding
3652 to $1, $2 etc. in some other regexp languages).
3653
3654 \sa cap() pos()
3655*/
3656QStringList QRegExp3::capturedTexts()
3657{
3658 if ( priv->capturedCache.isEmpty() ) {
3659 for ( int i = 0; i < (int) priv->captured.size(); i += 2 ) {
3660 QString m;
3661 if ( priv->captured[i + 1] == 0 )
3662 m = QString::fromLatin1( "" );
3663 else if ( priv->captured[i] >= 0 )
3664 m = priv->t.mid( priv->captured[i],
3665 priv->captured[i + 1] );
3666 priv->capturedCache.append( m );
3667 }
3668 priv->t = QString::null;
3669 }
3670 return priv->capturedCache;
3671}
3672
3673/*! Returns the text captured by the \a nth subexpression. The entire match
3674 has index 0 and the parenthesised subexpressions have indices starting
3675 from 1 (excluding non-capturing parenthesis).
3676
3677 \code
3678 QRegExp3 rxlen( "(\\d+)(?:\\s*)(cm|inch)" );
3679 int pos = rxlen.search( "Length: 189cm" );
3680 if ( pos > -1 ) {
3681 QString value = rxlen.cap( 1 );// "189"
3682 QString unit = rxlen.cap( 2 ); // "cm"
3683 // ...
3684 }
3685 \endcode
3686
3687 <a name="cap_in_a_loop">
3688 Some patterns may lead to a number of matches which cannot be
3689 determined in advance, for example:</a>
3690
3691 \code
3692 QRegExp3 rx( "(\\d+)" );
3693 str = "Offsets: 12 14 99 231 7";
3694 QStringList list;
3695 pos = 0;
3696 while ( pos >= 0 ) {
3697 pos = rx.search( str, pos );
3698 if ( pos > -1 ) {
3699 list += rx.cap( 1 );
3700 pos += rx.matchedLength();
3701 }
3702 }
3703 // list contains: ( "12", "14", "99", "231", "7" ).
3704 \endcode
3705
3706 The order of elements matched by cap() is as follows. The first
3707 element, cap( 0 ), is the entire matching string. Each subsequent
3708 element corresponds to the next capturing open left parenthesis. Thus
3709 cap( 1 ) is the text of the first capturing parenthesis, cap( 2 ) is
3710 the text of the second and so on.
3711
3712 \sa search() pos() capturedTexts()
3713*/
3714QString QRegExp3::cap( int nth )
3715{
3716 if ( nth < 0 || nth >= (int) priv->captured.size() / 2 )
3717 return QString::null;
3718 else
3719 return capturedTexts()[nth];
3720}
3721
3722/*! Returns the position of the \a nth captured text in the
3723 searched string. If \a nth is 0 (the default), pos() returns the
3724 position of the whole match.
3725
3726 Example:
3727 \code
3728 QRegExp3 rx( "/([a-z]+)/([a-z]+)" );
3729 rx.search( "Output /dev/null" );// Returns 7 (position of /dev/null)
3730 rx.pos( 0 ); // Returns 7 (position of /dev/null)
3731 rx.pos( 1 ); // Returns 8 (position of dev)
3732 rx.pos( 2 ); // Returns 12 (position of null)
3733 \endcode
3734
3735 Note that pos() returns -1 for zero-length matches. (For example, if
3736 cap(4) would return an empty string, pos(4) returns -1.) This is due
3737 to an implementation tradeoff.
3738
3739 \sa capturedTexts() cap()
3740*/
3741int QRegExp3::pos( int nth )
3742{
3743 if ( nth < 0 || nth >= (int) priv->captured.size() / 2 )
3744 return -1;
3745 else
3746 return priv->captured[2 * nth];
3747}
3748#endif
3749
3750void QRegExp3::compile( bool caseSensitive )
3751{
3752 derefEngine( eng, priv->rxpattern );
3753#ifndef QT_NO_REGEXP_WILDCARD
3754 if ( priv->wc )
3755 priv->rxpattern = wc2rx( priv->pattern );
3756 else
3757#endif
3758 priv->rxpattern = priv->pattern.isNull() ? QString::fromLatin1( "" )
3759 : priv->pattern;
3760 eng = newEngine( priv->rxpattern, caseSensitive );
3761#ifndef QT_NO_REGEXP_CAPTURE
3762 priv->t = QString::null;
3763 priv->capturedCache.clear();
3764#endif
3765 priv->captured.detach();
3766 priv->captured.fill( -1, 2 + 2 * eng->numCaptures() );
3767}
diff --git a/noncore/apps/tinykate/libkate/qt3back/qregexp3.h b/noncore/apps/tinykate/libkate/qt3back/qregexp3.h
new file mode 100644
index 0000000..5b75131
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/qt3back/qregexp3.h
@@ -0,0 +1,111 @@
1/****************************************************************************
2** $Id$
3**
4** Definition of QRegExp class
5**
6** Created : 950126
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the tools module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#ifndef QREGEXP3_H
39#define QREGEXP3_H
40#ifndef QT_H
41#include "qstringlist.h"
42#endif // QT_H
43
44
45#if QT_VERSION >=300
46#include <qregexp.h>
47#else
48class QRegExpEngine;
49struct QRegExpPrivate;
50
51class Q_EXPORT QRegExp3
52{
53public:
54 QRegExp3();
55 QRegExp3( const QString& pattern, bool caseSensitive = TRUE,
56 bool wildcard = FALSE );
57 QRegExp3( const QRegExp3& rx );
58 ~QRegExp3();
59 QRegExp3& operator=( const QRegExp3& rx );
60
61 bool operator==( const QRegExp3& rx ) const;
62 bool operator!=( const QRegExp3& rx ) const { return !operator==( rx ); }
63
64 bool isEmpty() const;
65 bool isValid() const;
66 QString pattern() const;
67 void setPattern( const QString& pattern );
68 bool caseSensitive() const;
69 void setCaseSensitive( bool sensitive );
70#ifndef QT_NO_REGEXP_WILDCARD
71 bool wildcard() const;
72 void setWildcard( bool wildcard );
73#endif
74 bool minimal() const;
75 void setMinimal( bool minimal );
76
77 bool exactMatch( const QString& str );
78 bool exactMatch( const QString& str ) const;
79#ifndef QT_NO_COMPAT
80 int match( const QString& str, int index, int *len = 0,
81 bool indexIsStart = TRUE );
82#endif
83 int search( const QString& str, int start = 0 );
84 int search( const QString& str, int start = 0 ) const;
85// QChar versions
86#ifdef QCHAR_SUPPORT
87 int search(const QChar *str,int start=0);
88 int search(const QChar *str,int start=0) const;
89 int searchRev(const QChar *str,int start=-1);
90 int searchRev(const QChar *str,int start=-1) const ;
91 bool exactMatch(const QChar *str);
92 bool exactMatch(const QChar *str) const;
93 // end QChar versions
94#endif
95 int searchRev( const QString& str, int start = -1 );
96 int searchRev( const QString& str, int start = -1 ) const;
97 int matchedLength();
98#ifndef QT_NO_REGEXP_CAPTURE
99 QStringList capturedTexts();
100 QString cap( int nth = 0 );
101 int pos( int nth = 0 );
102#endif
103
104private:
105 void compile( bool caseSensitive );
106
107 QRegExpEngine *eng;
108 QRegExpPrivate *priv;
109};
110#endif // QT_VERSION >= 300
111#endif // QREGEXP_H
diff --git a/noncore/apps/tinykate/libkate/view/kateundohistory.cpp b/noncore/apps/tinykate/libkate/view/kateundohistory.cpp
new file mode 100644
index 0000000..b7b9b56
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/view/kateundohistory.cpp
@@ -0,0 +1,271 @@
1/*
2 Copyright (C) 1999 Glen Parker <glenebob@nwlink.com>
3 Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
22 This implements a dialog used to display and control undo/redo history.
23 It uses a specialized QListBox subclass to provide a selection mechanism
24 that must:
25 1) always have the first item selected, and
26 2) maintain a contiguous multiple selection
27*/
28
29#include <stdio.h>
30
31#include <qwidget.h>
32#include <qdialog.h>
33#include <qlayout.h>
34#include <qlabel.h>
35#include <qlistbox.h>
36#include <qpushbutton.h>
37
38#include <klocale.h>
39
40#include "kateview.h"
41
42#include "kateundohistory.h"
43
44/////////////////////////////////////////////////////////////////////
45// UndoHistory implementation
46//
47UndoHistory::UndoHistory(KateView *kWrite, QWidget *parent, const char *name, bool modal, WFlags f)
48 : QDialog(parent, name, modal, f)
49{
50 this->kWrite = kWrite;
51
52 QPushButton *btn;
53 QLabel *lbl;
54 QHBoxLayout *hLayout;
55 QVBoxLayout *vLayout;
56
57 hLayout = new QHBoxLayout(this, 5, 4);
58
59 vLayout = new QVBoxLayout(hLayout);
60 lbl = new QLabel(i18n("Undo List"), this);
61 lbUndo = new UndoListBox(this);
62 vLayout->addWidget(lbl);
63 vLayout->addWidget(lbUndo);
64
65 vLayout = new QVBoxLayout(hLayout);
66 lbl = new QLabel(i18n("Redo List"), this);
67 lbRedo = new UndoListBox(this);
68 vLayout->addWidget(lbl);
69 vLayout->addWidget(lbRedo);
70
71 lbUndo->setMinimumSize(QSize(150,140));
72 lbRedo->setMinimumSize(QSize(150,140));
73
74 connect(lbUndo, SIGNAL(sigSelected(int)), this, SLOT(slotUndoSelChanged(int)));
75 connect(lbRedo, SIGNAL(sigSelected(int)), this, SLOT(slotRedoSelChanged(int)));
76
77 vLayout = new QVBoxLayout(hLayout);
78
79 btnUndo = new QPushButton(this);
80 btnUndo->setText(i18n("&Undo"));
81 btnUndo->setEnabled(false);
82 btnUndo->setFixedSize(btnUndo->sizeHint());
83 connect(btnUndo, SIGNAL(clicked()), this, SLOT(slotUndo()));
84
85 vLayout->addWidget(btnUndo, 0);
86
87 btnRedo = new QPushButton(this);
88 btnRedo->setText(i18n("&Redo"));
89 btnRedo->setEnabled(false);
90 btnRedo->setFixedSize(btnRedo->sizeHint());
91 connect(btnRedo, SIGNAL(clicked()), this, SLOT(slotRedo()));
92
93 vLayout->addWidget(btnRedo, 0);
94
95 btn = new QPushButton(this);
96 btn->setText(i18n("&Close"));
97 btn->setFixedSize(btn->sizeHint());
98 connect(btn, SIGNAL(clicked()), this, SLOT(close()));
99
100 vLayout->addWidget(btn, 0, AlignBottom);
101
102 newUndo();
103}
104
105UndoHistory::~UndoHistory()
106{}
107
108void UndoHistory::newUndo()
109{
110 QValueList<int> undoList;
111 QValueList<int>::Iterator it;
112
113 // we don't want a signal storm...
114 disconnect(lbUndo, SIGNAL(sigSelected(int)), this, SLOT(slotUndoSelChanged(int)));
115 disconnect(lbRedo, SIGNAL(sigSelected(int)), this, SLOT(slotRedoSelChanged(int)));
116
117 kWrite->undoTypeList(undoList);
118
119 lbUndo->clear();
120
121 for (it = undoList.begin() ; it != undoList.end() ; it++) {
122 lbUndo->insertItem(i18n(kWrite->undoTypeName(*it)));
123 }
124
125 kWrite->redoTypeList(undoList);
126
127 lbRedo->clear();
128 for (it = undoList.begin() ; it != undoList.end() ; it++) {
129 lbRedo->insertItem(i18n(kWrite->undoTypeName(*it)));
130 }
131
132 connect(lbUndo, SIGNAL(sigSelected(int)), this, SLOT(slotUndoSelChanged(int)));
133 connect(lbRedo, SIGNAL(sigSelected(int)), this, SLOT(slotRedoSelChanged(int)));
134
135 slotUndoSelChanged(lbUndo->selCount());
136 slotRedoSelChanged(lbRedo->selCount());
137}
138
139void UndoHistory::slotUndo()
140{
141 int selCount = lbUndo->selCount();
142 emit undo(selCount);
143 lbRedo->setSelCount(selCount);
144}
145void UndoHistory::slotRedo()
146{
147 int selCount = lbRedo->selCount();
148 emit redo(selCount);
149 lbUndo->setSelCount(selCount);
150}
151
152void UndoHistory::slotUndoSelChanged(int cnt)
153{
154 btnUndo->setEnabled(cnt > 0);
155}
156
157void UndoHistory::slotRedoSelChanged(int cnt)
158{
159 btnRedo->setEnabled(cnt > 0);
160}
161
162/////////////////////////////////////////////////////////////////////
163// UndoListBox implementation
164//
165UndoListBox::UndoListBox(QWidget *parent, const char *name, WFlags f)
166 : QListBox(parent, name, f)
167{
168 _selCount = 0;
169 setSelectionMode(Extended);
170 connect(this, SIGNAL(highlighted(int)), this, SLOT(_slotSelectionChanged()));
171 connect(this, SIGNAL(selectionChanged()), this, SLOT(_slotSelectionChanged()));
172}
173
174UndoListBox::~UndoListBox()
175{}
176
177void UndoListBox::insertItem (const QString &text, int index)
178{
179 bool sig = false;
180
181 if (count() == 0)
182 sig = true;
183 else if (index > -1)
184 sig = (isSelected(index));
185
186 QListBox::insertItem(text, index);
187
188 if (sig)
189 _slotSelectionChanged();
190}
191
192void UndoListBox::removeItem (int index)
193{
194 bool sig;
195
196 if (count() == 1)
197 sig = true;
198 else if (index == -1)
199 sig = (isSelected(count() - 1));
200 else
201 sig = (isSelected(index));
202
203 QListBox::removeItem(index);
204
205 if (sig)
206 _slotSelectionChanged();
207}
208
209void UndoListBox::clear()
210{
211 bool sig = (count() > 0);
212
213 QListBox::clear();
214
215 if (sig)
216 _slotSelectionChanged();
217}
218
219int UndoListBox::selCount()
220{
221 return _selCount;
222}
223
224void UndoListBox::setSelCount(int count)
225{
226 if (count == _selCount)
227 return;
228
229 if (count < 1 || count > (int)this->count())
230 return;
231
232 setCurrentItem(count - 1);
233}
234
235// make sure the first item is selected, and that there are no holes
236void UndoListBox::_slotSelectionChanged()
237{
238 int count = this->count();
239
240 if (! count) {
241 if (_selCount != 0) {
242 _selCount = 0;
243 emit sigSelected(_selCount);
244 }
245 return;
246 }
247
248 if (currentItem() < 0)
249 setCurrentItem(0);
250
251 int i;
252 int currItem = currentItem();
253 int max = (currItem+1 > _selCount ? currItem+1 : _selCount);
254
255 for (i = 0 ; i < max ; i++) {
256 if (i > currItem) {
257 if (isSelected(i)) {
258 setSelected(i, false);
259 }
260 } else {
261 if (! isSelected(i)) {
262 setSelected(i, true);
263 }
264 }
265 }
266
267 if (_selCount != currItem + 1) {
268 _selCount = currItem + 1;
269 emit sigSelected(_selCount);
270 }
271}
diff --git a/noncore/apps/tinykate/libkate/view/kateundohistory.h b/noncore/apps/tinykate/libkate/view/kateundohistory.h
new file mode 100644
index 0000000..eb91af9
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/view/kateundohistory.h
@@ -0,0 +1,114 @@
1/*
2 Copyright (C) 1999 Glen Parker <glenebob@nwlink.com>
3 Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
22 This implements a dialog used to display and control undo/redo history.
23 It uses a specialized QListBox subclass to provide a selection mechanism
24 that will:
25 1) always have the first item selected, and
26 2) maintain a contiguous multiple selection
27*/
28
29#ifndef __undohistory_h_
30#define __undohistory_h_
31
32#include <qdialog.h>
33#include <qlistbox.h>
34
35#include "kateview.h"
36
37class UndoListBox;
38
39// the dialog class that provides the interface to the user
40class UndoHistory : public QDialog
41{
42 Q_OBJECT
43
44 public:
45 /**
46 Constructed just like a regular QDialog
47 */
48 UndoHistory(KateView*, QWidget *parent=0, const char *name=0, bool modal=FALSE, WFlags f=0);
49 virtual ~UndoHistory();
50
51 public slots:
52 /**
53 This should be called whenever a change occurs in the undo/redo list.
54 Causes the dialog to update its interface.
55 */
56 void newUndo();
57
58 signals:
59 /**
60 Emitted when the user hits the Undo button. Specifies the number of
61 operations to undo.
62 */
63 void undo(int);
64 /**
65 Emitted when the user hits the Redo button. Specifies the number of
66 undone operations to redo.
67 */
68 void redo(int);
69
70 protected:
71 KateView *kWrite;
72
73 UndoListBox *lbUndo,
74 *lbRedo;
75 QPushButton *btnUndo,
76 *btnRedo;
77
78 protected slots:
79 void slotUndo();
80 void slotRedo();
81 void slotUndoSelChanged(int);
82 void slotRedoSelChanged(int);
83
84};
85
86// listbox class used to provide contiguous, 0-based selection
87// this is used internally
88class UndoListBox : public QListBox
89{
90 Q_OBJECT
91
92 public:
93 UndoListBox(QWidget * parent=0, const char * name=0, WFlags f=0);
94 virtual ~UndoListBox();
95
96 int selCount();
97 void setSelCount(int count);
98
99 void insertItem (const QString &text, int index = -1);
100 void removeItem (int index);
101 void clear();
102
103 protected:
104 int _selCount;
105
106 signals:
107 void sigSelected(int);
108
109 protected slots:
110 void _slotSelectionChanged();
111
112};
113
114#endif
diff --git a/noncore/apps/tinykate/libkate/view/kateview.cpp b/noncore/apps/tinykate/libkate/view/kateview.cpp
new file mode 100644
index 0000000..8f3a25e
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/view/kateview.cpp
@@ -0,0 +1,2923 @@
1/***************************************************************************
2 kateview.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 * 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
20/*
21 Copyright (C) 1998, 1999 Jochen Wilhelmy
22 digisnap@cs.tu-berlin.de
23
24 This library is free software; you can redistribute it and/or
25 modify it under the terms of the GNU Library General Public
26 License as published by the Free Software Foundation; either
27 version 2 of the License, or (at your option) any later version.
28
29 This library is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 Library General Public License for more details.
33
34 You should have received a copy of the GNU Library General Public License
35 along with this library; see the file COPYING.LIB. If not, write to
36 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
37 Boston, MA 02111-1307, USA.
38*/
39
40
41
42#include "kateview.h"
43
44#include "../document/katedocument.h"
45#include "../document/katecmd.h"
46#include "../document/katehighlight.h"
47#include "kateviewdialog.h"
48#include "../document/katedialogs.h"
49
50#include <qfocusdata.h>
51#include <kdebug.h>
52#include <kapplication.h>
53#include <qscrollbar.h>
54#include <qiodevice.h>
55#include <qpopupmenu.h>
56#include <kpopupmenu.h>
57#include <qkeycode.h>
58#include <qintdict.h>
59#include <kconfig.h>
60#include <qfont.h>
61#include <qpainter.h>
62#include <qpixmap.h>
63#include <qfileinfo.h>
64#include <qfile.h>
65#include <qevent.h>
66#include <qdir.h>
67#include <qvbox.h>
68#include <qprintdialog.h>
69#include <qpaintdevicemetrics.h>
70#include <qiodevice.h>
71#include <qbuffer.h>
72#include <qfocusdata.h>
73#include <klocale.h>
74#include <kglobal.h>
75#include <kdebug.h>
76#include <kmessagebox.h>
77#include <qregexp.h>
78#include <kdialogbase.h>
79#include <klineeditdlg.h>
80#include <qapplication.h>
81#include <kfiledialog.h>
82#include <kiconloader.h>
83#include "../document/katetextline.h"
84#include "kateviewdialog.h"
85#include "kateundohistory.h"
86#include <qlayout.h>
87
88KateViewInternal::KateViewInternal(KateView *view, KateDocument *doc) : QWidget(view)
89{
90 waitForPreHighlight=-1;
91 myView = view;
92 myDoc = doc;
93
94 iconBorderWidth = 16;
95 iconBorderHeight = 800;
96
97 QWidget::setCursor(ibeamCursor);
98 setBackgroundMode(NoBackground);
99
100 setFocusPolicy(StrongFocus);
101
102 xScroll = new QScrollBar(QScrollBar::Horizontal,myView);
103 yScroll = new QScrollBar(QScrollBar::Vertical,myView);
104 connect(xScroll,SIGNAL(valueChanged(int)),SLOT(changeXPos(int)));
105 connect(yScroll,SIGNAL(valueChanged(int)),SLOT(changeYPos(int)));
106 connect(yScroll,SIGNAL(valueChanged(int)),myView,SIGNAL(scrollValueChanged(int)));
107 connect( doc, SIGNAL (preHighlightChanged(long)),this,SLOT(slotPreHighlightUpdate(long)));
108
109 xPos = 0;
110 yPos = 0;
111
112 scrollTimer = 0;
113
114 cursor.x = 0;
115 cursor.y = 0;
116 cursorOn = false;
117 cursorTimer = 0;
118 cXPos = 0;
119 cOldXPos = 0;
120
121 startLine = 0;
122 endLine = -1;
123
124 exposeCursor = false;
125 updateState = 0;
126 numLines = 0;
127 lineRanges = 0L;
128 newXPos = -1;
129 newYPos = -1;
130
131 drawBuffer = new QPixmap ();
132 drawBuffer->setOptimization (QPixmap::BestOptim);
133
134 bm.sXPos = 0;
135 bm.eXPos = -1;
136
137}
138
139
140KateViewInternal::~KateViewInternal()
141{
142 delete [] lineRanges;
143 delete drawBuffer;
144}
145
146
147void KateViewInternal::slotPreHighlightUpdate(long line)
148{
149 //kdDebug()<<QString("slotPreHighlightUpdate - Wait for: %1, line: %2").arg(waitForPreHighlight).arg(line)<<endl;
150 if (waitForPreHighlight!=-1)
151 {
152 if (line>=waitForPreHighlight)
153 {
154 waitForPreHighlight=-1;
155 repaint();
156 }
157 }
158}
159
160void KateViewInternal::doCursorCommand(VConfig &c, int cmdNum) {
161
162 switch (cmdNum) {
163 case KateView::cmLeft:
164 cursorLeft(c);
165 break;
166 case KateView::cmRight:
167 cursorRight(c);
168 break;
169 case KateView::cmWordLeft:
170 wordLeft(c);
171 break;
172 case KateView::cmWordRight:
173 wordRight(c);
174 break;
175 case KateView::cmHome:
176 home(c);
177 break;
178 case KateView::cmEnd:
179 end(c);
180 break;
181 case KateView::cmUp:
182 cursorUp(c);
183 break;
184 case KateView::cmDown:
185 cursorDown(c);
186 break;
187 case KateView::cmScrollUp:
188 scrollUp(c);
189 break;
190 case KateView::cmScrollDown:
191 scrollDown(c);
192 break;
193 case KateView::cmTopOfView:
194 topOfView(c);
195 break;
196 case KateView::cmBottomOfView:
197 bottomOfView(c);
198 break;
199 case KateView::cmPageUp:
200 pageUp(c);
201 break;
202 case KateView::cmPageDown:
203 pageDown(c);
204 break;
205 case KateView::cmTop:
206 top_home(c);
207 break;
208 case KateView::cmBottom:
209 bottom_end(c);
210 break;
211 }
212}
213
214void KateViewInternal::doEditCommand(VConfig &c, int cmdNum) {
215
216 switch (cmdNum) {
217 case KateView::cmCopy:
218 myDoc->copy(c.flags);
219 return;
220 case KateView::cmSelectAll:
221 myDoc->selectAll();
222 return;
223 case KateView::cmDeselectAll:
224 myDoc->deselectAll();
225 return;
226 case KateView::cmInvertSelection:
227 myDoc->invertSelection();
228 return;
229 }
230 if (myView->isReadOnly()) return;
231 switch (cmdNum) {
232 case KateView::cmReturn:
233 if (c.flags & KateView::cfDelOnInput) myDoc->delMarkedText(c);
234 myDoc->newLine(c);
235 //emit returnPressed();
236 //e->ignore();
237 return;
238 case KateView::cmDelete:
239 if ((c.flags & KateView::cfDelOnInput) && myDoc->hasMarkedText())
240 myDoc->delMarkedText(c);
241 else myDoc->del(c);
242 return;
243 case KateView::cmBackspace:
244 if ((c.flags & KateView::cfDelOnInput) && myDoc->hasMarkedText())
245 myDoc->delMarkedText(c);
246 else myDoc->backspace(c);
247 return;
248 case KateView::cmKillLine:
249 myDoc->killLine(c);
250 return;
251 case KateView::cmCut:
252 myDoc->cut(c);
253 return;
254 case KateView::cmPaste:
255 if (c.flags & KateView::cfDelOnInput) myDoc->delMarkedText(c);
256 myDoc->paste(c);
257 return;
258 case KateView::cmUndo:
259 myDoc->undo(c);
260 return;
261 case KateView::cmRedo:
262 myDoc->redo(c);
263 return;
264 case KateView::cmIndent:
265 myDoc->indent(c);
266 return;
267 case KateView::cmUnindent:
268 myDoc->unIndent(c);
269 return;
270 case KateView::cmCleanIndent:
271 myDoc->cleanIndent(c);
272 return;
273 case KateView::cmComment:
274 myDoc->comment(c);
275 return;
276 case KateView::cmUncomment:
277 myDoc->unComment(c);
278 return;
279 }
280}
281
282void KateViewInternal::cursorLeft(VConfig &c) {
283
284 cursor.x--;
285 if (c.flags & KateView::cfWrapCursor && cursor.x < 0 && cursor.y > 0) {
286 cursor.y--;
287 cursor.x = myDoc->textLength(cursor.y);
288 }
289 cOldXPos = cXPos = myDoc->textWidth(cursor);
290 changeState(c);
291}
292
293void KateViewInternal::cursorRight(VConfig &c) {
294
295 if (c.flags & KateView::cfWrapCursor) {
296 if (cursor.x >= myDoc->textLength(cursor.y)) {
297 if (cursor.y == myDoc->lastLine()) return;
298 cursor.y++;
299 cursor.x = -1;
300 }
301 }
302 cursor.x++;
303 cOldXPos = cXPos = myDoc->textWidth(cursor);
304 changeState(c);
305}
306
307void KateViewInternal::wordLeft(VConfig &c) {
308 Highlight *highlight;
309
310 highlight = myDoc->highlight();
311 TextLine::Ptr textLine = myDoc->getTextLine(cursor.y);
312
313 if (cursor.x > 0) {
314 do {
315 cursor.x--;
316 } while (cursor.x > 0 && !highlight->isInWord(textLine->getChar(cursor.x)));
317 while (cursor.x > 0 && highlight->isInWord(textLine->getChar(cursor.x -1)))
318 cursor.x--;
319 } else {
320 if (cursor.y > 0) {
321 cursor.y--;
322 textLine = myDoc->getTextLine(cursor.y);
323 cursor.x = textLine->length();
324 }
325 }
326
327 cOldXPos = cXPos = myDoc->textWidth(cursor);
328 changeState(c);
329}
330
331void KateViewInternal::wordRight(VConfig &c) {
332 Highlight *highlight;
333 int len;
334
335 highlight = myDoc->highlight();
336 TextLine::Ptr textLine = myDoc->getTextLine(cursor.y);
337 len = textLine->length();
338
339 if (cursor.x < len) {
340 do {
341 cursor.x++;
342 } while (cursor.x < len && highlight->isInWord(textLine->getChar(cursor.x)));
343 while (cursor.x < len && !highlight->isInWord(textLine->getChar(cursor.x)))
344 cursor.x++;
345 } else {
346 if (cursor.y < myDoc->lastLine()) {
347 cursor.y++;
348 textLine = myDoc->getTextLine(cursor.y);
349 cursor.x = 0;
350 }
351 }
352
353 cOldXPos = cXPos = myDoc->textWidth(cursor);
354 changeState(c);
355}
356
357void KateViewInternal::home(VConfig &c) {
358 int lc;
359
360 lc = (c.flags & KateView::cfSmartHome) ? myDoc->getTextLine(cursor.y)->firstChar() : 0;
361 if (lc <= 0 || cursor.x == lc) {
362 cursor.x = 0;
363 cOldXPos = cXPos = 0;
364 } else {
365 cursor.x = lc;
366 cOldXPos = cXPos = myDoc->textWidth(cursor);
367 }
368
369 changeState(c);
370}
371
372void KateViewInternal::end(VConfig &c) {
373 cursor.x = myDoc->textLength(cursor.y);
374 cOldXPos = cXPos = myDoc->textWidth(cursor);
375 changeState(c);
376}
377
378
379void KateViewInternal::cursorUp(VConfig &c) {
380
381 cursor.y--;
382 cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos);
383 changeState(c);
384}
385
386
387void KateViewInternal::cursorDown(VConfig &c) {
388 int x;
389
390 if (cursor.y == myDoc->lastLine()) {
391 x = myDoc->textLength(cursor.y);
392 if (cursor.x >= x) return;
393 cursor.x = x;
394 cXPos = myDoc->textWidth(cursor);
395 } else {
396 cursor.y++;
397 cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor, cursor, cOldXPos);
398 }
399 changeState(c);
400}
401
402void KateViewInternal::scrollUp(VConfig &c) {
403
404 if (! yPos) return;
405
406 newYPos = yPos - myDoc->fontHeight;
407 if (cursor.y == (yPos + height())/myDoc->fontHeight -1) {
408 cursor.y--;
409 cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos);
410
411 changeState(c);
412 }
413}
414
415void KateViewInternal::scrollDown(VConfig &c) {
416
417 if (endLine >= myDoc->lastLine()) return;
418
419 newYPos = yPos + myDoc->fontHeight;
420 if (cursor.y == (yPos + myDoc->fontHeight -1)/myDoc->fontHeight) {
421 cursor.y++;
422 cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos);
423 changeState(c);
424 }
425}
426
427void KateViewInternal::topOfView(VConfig &c) {
428
429 cursor.y = (yPos + myDoc->fontHeight -1)/myDoc->fontHeight;
430 cursor.x = 0;
431 cOldXPos = cXPos = 0;
432 changeState(c);
433}
434
435void KateViewInternal::bottomOfView(VConfig &c) {
436
437 cursor.y = (yPos + height())/myDoc->fontHeight -1;
438 if (cursor.y < 0) cursor.y = 0;
439 if (cursor.y > myDoc->lastLine()) cursor.y = myDoc->lastLine();
440 cursor.x = 0;
441 cOldXPos = cXPos = 0;
442 changeState(c);
443}
444
445void KateViewInternal::pageUp(VConfig &c) {
446 int lines = (endLine - startLine - 1);
447
448 if (lines <= 0) lines = 1;
449
450 if (!(c.flags & KateView::cfPageUDMovesCursor) && yPos > 0) {
451 newYPos = yPos - lines * myDoc->fontHeight;
452 if (newYPos < 0) newYPos = 0;
453 }
454 cursor.y -= lines;
455 cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor, cursor, cOldXPos);
456 changeState(c);
457// cursorPageUp(c);
458}
459
460void KateViewInternal::pageDown(VConfig &c) {
461
462 int lines = (endLine - startLine - 1);
463
464 if (!(c.flags & KateView::cfPageUDMovesCursor) && endLine < myDoc->lastLine()) {
465 if (lines < myDoc->lastLine() - endLine)
466 newYPos = yPos + lines * myDoc->fontHeight;
467 else
468 newYPos = yPos + (myDoc->lastLine() - endLine) * myDoc->fontHeight;
469 }
470 cursor.y += lines;
471 cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos);
472 changeState(c);
473// cursorPageDown(c);
474}
475
476// go to the top, same X position
477void KateViewInternal::top(VConfig &c) {
478
479// cursor.x = 0;
480 cursor.y = 0;
481 cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos);
482// cOldXPos = cXPos = 0;
483 changeState(c);
484}
485
486// go to the bottom, same X position
487void KateViewInternal::bottom(VConfig &c) {
488
489// cursor.x = 0;
490 cursor.y = myDoc->lastLine();
491 cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos);
492// cOldXPos = cXPos = 0;
493 changeState(c);
494}
495
496// go to the top left corner
497void KateViewInternal::top_home(VConfig &c)
498{
499 cursor.y = 0;
500 cursor.x = 0;
501 cOldXPos = cXPos = 0;
502 changeState(c);
503}
504
505// go to the bottom right corner
506void KateViewInternal::bottom_end(VConfig &c) {
507
508 cursor.y = myDoc->lastLine();
509 cursor.x = myDoc->textLength(cursor.y);
510 cOldXPos = cXPos = myDoc->textWidth(cursor);
511 changeState(c);
512}
513
514
515void KateViewInternal::changeXPos(int p) {
516 int dx;
517
518 dx = xPos - p;
519 xPos = p;
520 if (QABS(dx) < width()) scroll(dx, 0); else update();
521}
522
523void KateViewInternal::changeYPos(int p) {
524 int dy;
525
526 dy = yPos - p;
527 yPos = p;
528 clearDirtyCache(height());
529
530 if (QABS(dy) < height())
531 {
532 scroll(0, dy);
533 leftBorder->scroll(0, dy);
534 }
535 else
536 update();
537}
538
539
540void KateViewInternal::getVConfig(VConfig &c) {
541
542 c.view = myView;
543 c.cursor = cursor;
544 c.cXPos = cXPos;
545 c.flags = myView->configFlags;
546}
547
548void KateViewInternal::changeState(VConfig &c) {
549 /*
550 * we need to be sure to kill the selection on an attempted cursor
551 * movement even if the cursor doesn't physically move,
552 * but we need to be careful not to do some other things in this case,
553 * like we don't want to expose the cursor
554 */
555
556// if (cursor.x == c.cursor.x && cursor.y == c.cursor.y) return;
557 bool nullMove = (cursor.x == c.cursor.x && cursor.y == c.cursor.y);
558
559// if (cursor.y != c.cursor.y || c.flags & KateView::cfMark) myDoc->recordReset();
560
561 if (! nullMove) {
562
563 exposeCursor = true;
564
565 // mark old position of cursor as dirty
566 if (cursorOn) {
567 tagLines(c.cursor.y, c.cursor.y, c.cXPos -2, c.cXPos +3);
568 cursorOn = false;
569 }
570
571 // mark old bracket mark position as dirty
572 if (bm.sXPos < bm.eXPos) {
573 tagLines(bm.cursor.y, bm.cursor.y, bm.sXPos, bm.eXPos);
574 }
575 // make new bracket mark
576 myDoc->newBracketMark(cursor, bm);
577
578 // remove trailing spaces when leaving a line
579 if (c.flags & KateView::cfRemoveSpaces && cursor.y != c.cursor.y) {
580 TextLine::Ptr textLine = myDoc->getTextLine(c.cursor.y);
581 int newLen = textLine->lastChar();
582 if (newLen != textLine->length()) {
583 textLine->truncate(newLen);
584 // if some spaces are removed, tag the line as dirty
585 myDoc->tagLines(c.cursor.y, c.cursor.y);
586 }
587 }
588 }
589
590 if (c.flags & KateView::cfMark) {
591 if (! nullMove)
592 myDoc->selectTo(c, cursor, cXPos);
593 } else {
594 if (!(c.flags & KateView::cfPersistent))
595 myDoc->deselectAll();
596 }
597}
598
599void KateViewInternal::insLine(int line) {
600
601 if (line <= cursor.y) {
602 cursor.y++;
603 }
604 if (line < startLine) {
605 startLine++;
606 endLine++;
607 yPos += myDoc->fontHeight;
608 } else if (line <= endLine) {
609 tagAll();
610 }
611}
612
613void KateViewInternal::delLine(int line) {
614
615 if (line <= cursor.y && cursor.y > 0) {
616 cursor.y--;
617 }
618 if (line < startLine) {
619 startLine--;
620 endLine--;
621 yPos -= myDoc->fontHeight;
622 } else if (line <= endLine) {
623 tagAll();
624 }
625}
626
627void KateViewInternal::updateCursor() {
628 cOldXPos = cXPos = myDoc->textWidth(cursor);
629}
630
631
632void KateViewInternal::updateCursor(PointStruc &newCursor) {
633 updateCursor(newCursor, myView->config());
634}
635
636void KateViewInternal::updateCursor(PointStruc &newCursor, int flags) {
637
638 if (!(flags & KateView::cfPersistent)) myDoc->deselectAll();
639
640 exposeCursor = true;
641 if (cursorOn) {
642 tagLines(cursor.y, cursor.y, cXPos -2, cXPos +3);
643 cursorOn = false;
644 }
645
646 if (bm.sXPos < bm.eXPos) {
647 tagLines(bm.cursor.y, bm.cursor.y, bm.sXPos, bm.eXPos);
648 }
649 myDoc->newBracketMark(newCursor, bm);
650
651 cursor = newCursor;
652 cOldXPos = cXPos = myDoc->textWidth(cursor);
653}
654
655// init the line dirty cache
656void KateViewInternal::clearDirtyCache(int height) {
657 int lines, z;
658
659 // calc start and end line of visible part
660 startLine = yPos/myDoc->fontHeight;
661 endLine = (yPos + height -1)/myDoc->fontHeight;
662
663 updateState = 0;
664
665 lines = endLine - startLine +1;
666 if (lines > numLines) { // resize the dirty cache
667 numLines = lines*2;
668 delete [] lineRanges;
669 lineRanges = new LineRange[numLines];
670 }
671
672 for (z = 0; z < lines; z++) { // clear all lines
673 lineRanges[z].start = 0xffffff;
674 lineRanges[z].end = -2;
675 }
676 newXPos = newYPos = -1;
677}
678
679void KateViewInternal::tagLines(int start, int end, int x1, int x2) {
680 LineRange *r;
681 int z;
682
683 start -= startLine;
684 if (start < 0) start = 0;
685 end -= startLine;
686 if (end > endLine - startLine) end = endLine - startLine;
687
688 if (x1 <= 0) x1 = -2;
689 if (x1 < xPos-2) x1 = xPos-2;
690 if (x2 > width() + xPos-2) x2 = width() + xPos-2;
691 if (x1 >= x2) return;
692
693 r = &lineRanges[start];
694 for (z = start; z <= end; z++) {
695 if (x1 < r->start) r->start = x1;
696 if (x2 > r->end) r->end = x2;
697 r++;
698 updateState |= 1;
699 }
700}
701
702void KateViewInternal::tagAll() {
703 updateState = 3;
704}
705
706void KateViewInternal::setPos(int x, int y) {
707 newXPos = x;
708 newYPos = y;
709}
710
711void KateViewInternal::center() {
712 newXPos = 0;
713 newYPos = cursor.y*myDoc->fontHeight - height()/2;
714 if (newYPos < 0) newYPos = 0;
715}
716
717void KateViewInternal::updateView(int flags) {
718 int fontHeight;
719 int oldXPos, oldYPos;
720 int w, h;
721 int z;
722 bool b;
723 int xMax, yMax;
724 int cYPos;
725 int cXPosMin, cXPosMax, cYPosMin, cYPosMax;
726 int dx, dy;
727 int pageScroll;
728 int scrollbarWidth = style().scrollBarExtent().width();
729
730//debug("upView %d %d %d %d %d", exposeCursor, updateState, flags, newXPos, newYPos);
731 if (exposeCursor || flags & KateView::ufDocGeometry) {
732 emit myView->newCurPos();
733 } else {
734 if (updateState == 0 && newXPos < 0 && newYPos < 0) return;
735 }
736
737 if (cursorTimer) {
738 killTimer(cursorTimer);
739 cursorTimer = startTimer(KApplication::cursorFlashTime() / 2);
740 cursorOn = true;
741 }
742
743 oldXPos = xPos;
744 oldYPos = yPos;
745/* if (flags & ufPos) {
746 xPos = newXPos;
747 yPos = newYPos;
748 exposeCursor = true;
749 }*/
750 if (newXPos >= 0) xPos = newXPos;
751 if (newYPos >= 0) yPos = newYPos;
752
753 fontHeight = myDoc->fontHeight;
754 cYPos = cursor.y*fontHeight;
755
756 z = 0;
757 do {
758 w = myView->width() - 4;
759 h = myView->height() - 4;
760
761 xMax = myDoc->textWidth() - w;
762 b = (xPos > 0 || xMax > 0);
763 if (b) h -= scrollbarWidth;
764 yMax = myDoc->textHeight() - h;
765 if (yPos > 0 || yMax > 0) {
766 w -= scrollbarWidth;
767 xMax += scrollbarWidth;
768 if (!b && xMax > 0) {
769 h -= scrollbarWidth;
770 yMax += scrollbarWidth;
771 }
772 }
773
774 if (!exposeCursor) break;
775// if (flags & KateView::ufNoScroll) break;
776/*
777 if (flags & KateView::ufCenter) {
778 cXPosMin = xPos + w/3;
779 cXPosMax = xPos + (w*2)/3;
780 cYPosMin = yPos + h/3;
781 cYPosMax = yPos + ((h - fontHeight)*2)/3;
782 } else {*/
783 cXPosMin = xPos + 4;
784 cXPosMax = xPos + w - 8;
785 cYPosMin = yPos;
786 cYPosMax = yPos + (h - fontHeight);
787// }
788
789 if (cXPos < cXPosMin) {
790 xPos -= cXPosMin - cXPos;
791 }
792 if (xPos < 0) xPos = 0;
793 if (cXPos > cXPosMax) {
794 xPos += cXPos - cXPosMax;
795 }
796 if (cYPos < cYPosMin) {
797 yPos -= cYPosMin - cYPos;
798 }
799 if (yPos < 0) yPos = 0;
800 if (cYPos > cYPosMax) {
801 yPos += cYPos - cYPosMax;
802 }
803
804 z++;
805 } while (z < 2);
806
807 if (xMax < xPos) xMax = xPos;
808 if (yMax < yPos) yMax = yPos;
809
810 if (xMax > 0) {
811 pageScroll = w - (w % fontHeight) - fontHeight;
812 if (pageScroll <= 0)
813 pageScroll = fontHeight;
814
815 xScroll->blockSignals(true);
816 xScroll->setGeometry(2,h + 2,w,scrollbarWidth);
817 xScroll->setRange(0,xMax);
818 xScroll->setValue(xPos);
819 xScroll->setSteps(fontHeight,pageScroll);
820 xScroll->blockSignals(false);
821 xScroll->show();
822 } else xScroll->hide();
823
824 if (yMax > 0) {
825 pageScroll = h - (h % fontHeight) - fontHeight;
826 if (pageScroll <= 0)
827 pageScroll = fontHeight;
828
829 yScroll->blockSignals(true);
830 yScroll->setGeometry(w + 2,2,scrollbarWidth,h);
831 yScroll->setRange(0,yMax);
832 yScroll->setValue(yPos);
833 yScroll->setSteps(fontHeight,pageScroll);
834 yScroll->blockSignals(false);
835 yScroll->show();
836 } else yScroll->hide();
837
838 if (w != width() || h != height()) {
839 clearDirtyCache(h);
840 resize(w,h);
841 } else {
842 dx = oldXPos - xPos;
843 dy = oldYPos - yPos;
844
845 b = updateState == 3;
846 if (flags & KateView::ufUpdateOnScroll) {
847 b |= dx || dy;
848 } else {
849 b |= QABS(dx)*3 > w*2 || QABS(dy)*3 > h*2;
850 }
851
852 if (b) {
853 clearDirtyCache(h);
854 update();
855 } else {
856 if (dy)
857 leftBorder->scroll(0, dy);
858 if (updateState > 0) paintTextLines(oldXPos, oldYPos);
859 clearDirtyCache(h);
860
861 if (dx || dy) {
862 scroll(dx,dy);
863// kapp->syncX();
864// scroll2(dx - dx/2,dy - dy/2);
865// } else {
866 }
867 if (cursorOn) paintCursor();
868 if (bm.eXPos > bm.sXPos) paintBracketMark();
869 }
870 }
871 exposeCursor = false;
872// updateState = 0;
873}
874
875
876void KateViewInternal::paintTextLines(int xPos, int yPos) {
877// int xStart, xEnd;
878 int line;//, z;
879 int h;
880 LineRange *r;
881
882 if (!drawBuffer) return;
883 if (drawBuffer->isNull()) return;
884
885 QPainter paint;
886 paint.begin(drawBuffer);
887
888 h = myDoc->fontHeight;
889 r = lineRanges;
890 for (line = startLine; line <= endLine; line++) {
891 if (r->start < r->end) {
892//debug("painttextline %d %d %d", line, r->start, r->end);
893 myDoc->paintTextLine(paint, line, r->start, r->end, myView->configFlags & KateView::cfShowTabs);
894 bitBlt(this, r->start - (xPos-2), line*h - yPos, drawBuffer, 0, 0,
895 r->end - r->start, h);
896 leftBorder->paintLine(line);
897 }
898 r++;
899 }
900
901 paint.end();
902}
903
904void KateViewInternal::paintCursor() {
905 int h, y, x;
906 static int cx = 0, cy = 0, ch = 0;
907
908 h = myDoc->fontHeight;
909 y = h*cursor.y - yPos;
910 x = cXPos - (xPos-2);
911
912 if(myDoc->myFont != font()) setFont(myDoc->myFont);
913 if(cx != x || cy != y || ch != h){
914 cx = x;
915 cy = y;
916 ch = h;
917 setMicroFocusHint(cx, cy, 0, ch - 2);
918 }
919
920 QPainter paint;
921 if (cursorOn) {
922 paint.begin(this);
923 paint.setClipping(false);
924 paint.setPen(myDoc->cursorCol(cursor.x,cursor.y));
925
926 h += y - 1;
927 paint.drawLine(x, y, x, h);
928
929 paint.end();
930 } else { if (drawBuffer && !drawBuffer->isNull()) {
931 paint.begin(drawBuffer);
932 myDoc->paintTextLine(paint, cursor.y, cXPos - 2, cXPos + 3, myView->configFlags & KateView::cfShowTabs);
933 bitBlt(this,x - 2,y, drawBuffer, 0, 0, 5, h);
934 paint.end(); }
935 }
936
937}
938
939void KateViewInternal::paintBracketMark() {
940 int y;
941
942 y = myDoc->fontHeight*(bm.cursor.y +1) - yPos -1;
943
944 QPainter paint;
945 paint.begin(this);
946 paint.setPen(myDoc->cursorCol(bm.cursor.x, bm.cursor.y));
947
948 paint.drawLine(bm.sXPos - (xPos-2), y, bm.eXPos - (xPos-2) -1, y);
949 paint.end();
950}
951
952void KateViewInternal::placeCursor(int x, int y, int flags) {
953 VConfig c;
954
955 getVConfig(c);
956 c.flags |= flags;
957 cursor.y = (yPos + y)/myDoc->fontHeight;
958 cXPos = cOldXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor, cursor,xPos-2 + x);
959 changeState(c);
960}
961
962// given physical coordinates, report whether the text there is selected
963bool KateViewInternal::isTargetSelected(int x, int y) {
964
965 y = (yPos + y) / myDoc->fontHeight;
966
967 TextLine::Ptr line = myDoc->getTextLine(y);
968 if (!line)
969 return false;
970
971 x = myDoc->textPos(line, x);
972
973 return line->isSelected(x);
974}
975
976void KateViewInternal::focusInEvent(QFocusEvent *) {
977// debug("got focus %d",cursorTimer);
978
979 if (!cursorTimer) {
980 cursorTimer = startTimer(KApplication::cursorFlashTime() / 2);
981 cursorOn = true;
982 paintCursor();
983 }
984}
985
986void KateViewInternal::focusOutEvent(QFocusEvent *) {
987// debug("lost focus %d", cursorTimer);
988
989 if (cursorTimer) {
990 killTimer(cursorTimer);
991 cursorTimer = 0;
992 }
993
994 if (cursorOn) {
995 cursorOn = false;
996 paintCursor();
997 }
998}
999
1000void KateViewInternal::keyPressEvent(QKeyEvent *e) {
1001 VConfig c;
1002// int ascii;
1003
1004/* if (e->state() & AltButton) {
1005 e->ignore();
1006 return;
1007 }*/
1008// debug("ascii %i, key %i, state %i",e->ascii(), e->key(), e->state());
1009
1010 getVConfig(c);
1011// ascii = e->ascii();
1012
1013 if (!myView->isReadOnly()) {
1014 if (c.flags & KateView::cfTabIndents && myDoc->hasMarkedText()) {
1015 if (e->key() == Qt::Key_Tab) {
1016 myDoc->indent(c);
1017 myDoc->updateViews();
1018 return;
1019 }
1020 if (e->key() == Qt::Key_Backtab) {
1021 myDoc->unIndent(c);
1022 myDoc->updateViews();
1023 return;
1024 }
1025 }
1026 if ( !(e->state() & ControlButton ) && myDoc->insertChars(c, e->text())) {
1027 myDoc->updateViews();
1028 e->accept();
1029 return;
1030 }
1031 }
1032 e->ignore();
1033}
1034
1035void KateViewInternal::mousePressEvent(QMouseEvent *e) {
1036
1037 if (e->button() == LeftButton) {
1038
1039 int flags;
1040
1041 flags = 0;
1042 if (e->state() & ShiftButton) {
1043 flags |= KateView::cfMark;
1044 if (e->state() & ControlButton) flags |= KateView::cfMark | KateView::cfKeepSelection;
1045 }
1046 placeCursor(e->x(), e->y(), flags);
1047 scrollX = 0;
1048 scrollY = 0;
1049 if (!scrollTimer) scrollTimer = startTimer(50);
1050 myDoc->updateViews();
1051 }
1052 if (e->button() == MidButton) {
1053 placeCursor(e->x(), e->y());
1054 if (! myView->isReadOnly())
1055 myView->paste();
1056 }
1057 if (myView->rmbMenu && e->button() == RightButton) {
1058 myView->rmbMenu->popup(mapToGlobal(e->pos()));
1059 }
1060 myView->mousePressEvent(e); // this doesn't do anything, does it?
1061 // it does :-), we need this for KDevelop, so please don't uncomment it again -Sandy
1062}
1063
1064void KateViewInternal::mouseDoubleClickEvent(QMouseEvent *e) {
1065
1066 if (e->button() == LeftButton) {
1067 VConfig c;
1068 getVConfig(c);
1069 myDoc->selectWord(c.cursor, c.flags);
1070 myDoc->updateViews();
1071 }
1072}
1073
1074void KateViewInternal::mouseReleaseEvent(QMouseEvent *e) {
1075
1076 if (e->button() == LeftButton) {
1077 if (myView->config() & KateView::cfMouseAutoCopy) myView->copy();
1078 killTimer(scrollTimer);
1079 scrollTimer = 0;
1080 }
1081}
1082
1083void KateViewInternal::mouseMoveEvent(QMouseEvent *e) {
1084
1085 if (e->state() & LeftButton) {
1086 int flags;
1087 int d;
1088 int x = e->x(),
1089 y = e->y();
1090
1091 mouseX = e->x();
1092 mouseY = e->y();
1093 scrollX = 0;
1094 scrollY = 0;
1095 d = myDoc->fontHeight;
1096 if (mouseX < 0) {
1097 mouseX = 0;
1098 scrollX = -d;
1099 }
1100 if (mouseX > width()) {
1101 mouseX = width();
1102 scrollX = d;
1103 }
1104 if (mouseY < 0) {
1105 mouseY = 0;
1106 scrollY = -d;
1107 }
1108 if (mouseY > height()) {
1109 mouseY = height();
1110 scrollY = d;
1111 }
1112//debug("modifiers %d", ((KGuiCmdApp *) kapp)->getModifiers());
1113 flags = KateView::cfMark;
1114 if (e->state() & ControlButton) flags |= KateView::cfKeepSelection;
1115 placeCursor(mouseX, mouseY, flags);
1116 myDoc->updateViews(/*ufNoScroll*/);
1117 }
1118}
1119
1120
1121
1122void KateViewInternal::wheelEvent( QWheelEvent *e )
1123{
1124 if( yScroll->isVisible() == true )
1125 {
1126 QApplication::sendEvent( yScroll, e );
1127 }
1128}
1129
1130
1131
1132void KateViewInternal::paintEvent(QPaintEvent *e) {
1133 int xStart, xEnd;
1134 int h;
1135 int line, y, yEnd;
1136
1137 QRect updateR = e->rect();
1138
1139 if (!drawBuffer) return;
1140 if (drawBuffer->isNull()) return;
1141
1142 QPainter paint;
1143 paint.begin(drawBuffer);
1144
1145 xStart = xPos-2 + updateR.x();
1146 xEnd = xStart + updateR.width();
1147
1148 h = myDoc->fontHeight;
1149 line = (yPos + updateR.y()) / h;
1150 y = line*h - yPos;
1151 yEnd = updateR.y() + updateR.height();
1152 waitForPreHighlight=myDoc->needPreHighlight(waitForPreHighlight=line+((long)(yEnd-y)/h)+5);
1153
1154 while (y < yEnd)
1155 {
1156 TextLine *textLine;
1157 int ctxNum = 0;
1158 myDoc->paintTextLine(paint, line, xStart, xEnd, myView->configFlags & KateView::cfShowTabs);
1159 bitBlt(this, updateR.x(), y, drawBuffer, 0, 0, updateR.width(), h);
1160 leftBorder->paintLine(line);
1161 line++;
1162 y += h;
1163 }
1164 paint.end();
1165
1166 if (cursorOn) paintCursor();
1167 if (bm.eXPos > bm.sXPos) paintBracketMark();
1168}
1169
1170void KateViewInternal::resizeEvent(QResizeEvent *)
1171{
1172 drawBuffer->resize (width(), myDoc->fontHeight);
1173 leftBorder->resize(iconBorderWidth, height());
1174}
1175
1176void KateViewInternal::timerEvent(QTimerEvent *e) {
1177 if (e->timerId() == cursorTimer) {
1178 cursorOn = !cursorOn;
1179 paintCursor();
1180 }
1181 if (e->timerId() == scrollTimer && (scrollX | scrollY)) {
1182 xScroll->setValue(xPos + scrollX);
1183 yScroll->setValue(yPos + scrollY);
1184
1185 placeCursor(mouseX, mouseY, KateView::cfMark);
1186 myDoc->updateViews(/*ufNoScroll*/);
1187 }
1188}
1189
1190uint KateView::uniqueID = 0;
1191
1192KateView::KateView(KateDocument *doc, QWidget *parent, const char * name) : Kate::View (doc, parent, name)
1193{
1194
1195 myViewID = uniqueID;
1196 uniqueID++;
1197
1198 active = false;
1199 myIconBorder = false;
1200
1201 myDoc = doc;
1202 myViewInternal = new KateViewInternal (this,doc);
1203 myViewInternal->move(2, 2);
1204 myViewInternal->leftBorder = new KateIconBorder(this, myViewInternal);
1205 myViewInternal->leftBorder->setGeometry(2, 2, myViewInternal->iconBorderWidth, myViewInternal->iconBorderHeight);
1206 myViewInternal->leftBorder->hide();
1207
1208 doc->addView( this );
1209
1210
1211 // some defaults
1212 configFlags = KateView::cfAutoIndent | KateView::cfBackspaceIndents
1213 | KateView::cfTabIndents | KateView::cfKeepIndentProfile
1214 | KateView::cfRemoveSpaces
1215 | KateView::cfDelOnInput | KateView::cfMouseAutoCopy | KateView::cfWrapCursor
1216 | KateView::cfGroupUndo | KateView::cfShowTabs | KateView::cfSmartHome;
1217
1218 searchFlags = 0;
1219 replacePrompt = 0L;
1220 rmbMenu = 0L;
1221
1222
1223 setFocusProxy( myViewInternal );
1224 myViewInternal->setFocus();
1225 resize(parent->width() -4, parent->height() -4);
1226
1227
1228 myViewInternal->installEventFilter( this );
1229
1230 //setupActions();
1231
1232 connect( this, SIGNAL( newStatus() ), this, SLOT( slotUpdate() ) );
1233 connect( this, SIGNAL( newUndo() ), this, SLOT( slotNewUndo() ) );
1234 connect( doc, SIGNAL( fileNameChanged() ), this, SLOT( slotFileStatusChanged() ) );
1235 connect( doc, SIGNAL( highlightChanged() ), this, SLOT( slotHighlightChanged() ) );
1236
1237 readConfig();
1238// setHighlight->setCurrentItem(getHl());
1239 slotUpdate();
1240}
1241
1242KateView::~KateView()
1243{
1244
1245 if (myDoc && !myDoc->m_bSingleViewMode)
1246 myDoc->removeView( this );
1247
1248 delete myViewInternal;
1249
1250}
1251
1252#if 0
1253void KateView::setupActions()
1254{
1255#if 0
1256 KStdAction::close( this, SLOT(flush()), actionCollection(), "file_close" );
1257
1258 KStdAction::save(this, SLOT(save()), actionCollection());
1259
1260 // setup edit menu
1261 editUndo = KStdAction::undo(this, SLOT(undo()), actionCollection());
1262 editRedo = KStdAction::redo(this, SLOT(redo()), actionCollection());
1263 editUndoHist = new KAction(i18n("Undo/Redo &History..."), 0, this, SLOT(undoHistory()),
1264 actionCollection(), "edit_undoHistory");
1265 KStdAction::cut(this, SLOT(cut()), actionCollection());
1266 KStdAction::copy(this, SLOT(copy()), actionCollection());
1267 KStdAction::paste(this, SLOT(paste()), actionCollection());
1268
1269 if ( myDoc->hasBrowserExtension() )
1270 {
1271 KStdAction::saveAs(this, SLOT(saveAs()), myDoc->actionCollection());
1272 KStdAction::find(this, SLOT(find()), myDoc->actionCollection(), "find");
1273 KStdAction::findNext(this, SLOT(findAgain()), myDoc->actionCollection(), "find_again");
1274 KStdAction::findPrev(this, SLOT(findPrev()), myDoc->actionCollection(), "find_prev");
1275 KStdAction::gotoLine(this, SLOT(gotoLine()), myDoc->actionCollection(), "goto_line" );
1276 new KAction(i18n("&Configure Editor..."), 0, this, SLOT(configDialog()),myDoc->actionCollection(), "set_confdlg");
1277 setHighlight = new KSelectAction(i18n("&Highlight Mode"), 0, myDoc->actionCollection(), "set_highlight");
1278 KStdAction::selectAll(this, SLOT(selectAll()), myDoc->actionCollection(), "select_all");
1279 new KAction(i18n("&Deselect All"), 0, this, SLOT(deselectAll()),
1280 myDoc->actionCollection(), "unselect_all");
1281 new KAction(i18n("Invert &Selection"), 0, this, SLOT(invertSelection()),
1282 myDoc->actionCollection(), "invert_select");
1283
1284 new KAction(i18n("Increase Font Sizes"), "viewmag+", 0, this, SLOT(slotIncFontSizes()),
1285 myDoc->actionCollection(), "incFontSizes");
1286 new KAction(i18n("Decrease Font Sizes"), "viewmag-", 0, this, SLOT(slotDecFontSizes()),
1287 myDoc->actionCollection(), "decFontSizes");
1288 }
1289 else
1290 {
1291 KStdAction::saveAs(this, SLOT(saveAs()), actionCollection());
1292 KStdAction::find(this, SLOT(find()), actionCollection());
1293 KStdAction::findNext(this, SLOT(findAgain()), actionCollection());
1294 KStdAction::findPrev(this, SLOT(findPrev()), actionCollection(), "edit_find_prev");
1295 KStdAction::gotoLine(this, SLOT(gotoLine()), actionCollection());
1296 new KAction(i18n("&Configure Editor..."), 0, this, SLOT(configDialog()),actionCollection(), "set_confdlg");
1297 setHighlight = new KSelectAction(i18n("&Highlight Mode"), 0, actionCollection(), "set_highlight");
1298 KStdAction::selectAll(this, SLOT(selectAll()), actionCollection());
1299 new KAction(i18n("&Deselect All"), 0, this, SLOT(deselectAll()),
1300 actionCollection(), "edit_deselectAll");
1301 new KAction(i18n("Invert &Selection"), 0, this, SLOT(invertSelection()),
1302 actionCollection(), "edit_invertSelection");
1303
1304 new KAction(i18n("Increase Font Sizes"), "viewmag+", 0, this, SLOT(slotIncFontSizes()),
1305 actionCollection(), "incFontSizes");
1306 new KAction(i18n("Decrease Font Sizes"), "viewmag-", 0, this, SLOT(slotDecFontSizes()),
1307 actionCollection(), "decFontSizes");
1308 }
1309
1310 new KAction(i18n("Apply Word Wrap"), 0, myDoc, SLOT(applyWordWrap()), actionCollection(), "edit_apply_wordwrap");
1311
1312 KStdAction::replace(this, SLOT(replace()), actionCollection());
1313
1314 new KAction(i18n("Editing Co&mmand"), Qt::CTRL+Qt::Key_M, this, SLOT(slotEditCommand()),
1315 actionCollection(), "edit_cmd");
1316
1317 // setup bookmark menu
1318 bookmarkToggle = new KAction(i18n("Toggle &Bookmark"), Qt::CTRL+Qt::Key_B, this, SLOT(toggleBookmark()), actionCollection(), "edit_bookmarkToggle");
1319 bookmarkClear = new KAction(i18n("Clear Bookmarks"), 0, this, SLOT(clearBookmarks()), actionCollection(), "edit_bookmarksClear");
1320
1321 // connect settings menu aboutToshow
1322 bookmarkMenu = new KActionMenu(i18n("&Bookmarks"), actionCollection(), "bookmarks");
1323 connect(bookmarkMenu->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(bookmarkMenuAboutToShow()));
1324
1325 new KToggleAction(i18n("Show &IconBorder"), Key_F6, this, SLOT(toggleIconBorder()), actionCollection(), "view_border");
1326
1327 // setup Tools menu
1328 KStdAction::spelling(this, SLOT(spellcheck()), actionCollection());
1329 new KAction(i18n("&Indent"), "indent", Qt::CTRL+Qt::Key_I, this, SLOT(indent()),
1330 actionCollection(), "tools_indent");
1331 new KAction(i18n("&Unindent"), "unindent", Qt::CTRL+Qt::Key_U, this, SLOT(unIndent()),
1332 actionCollection(), "tools_unindent");
1333 new KAction(i18n("&Clean Indentation"), 0, this, SLOT(cleanIndent()),
1334 actionCollection(), "tools_cleanIndent");
1335 new KAction(i18n("C&omment"), CTRL+Qt::Key_NumberSign, this, SLOT(comment()),
1336 actionCollection(), "tools_comment");
1337 new KAction(i18n("Unco&mment"), CTRL+SHIFT+Qt::Key_NumberSign, this, SLOT(uncomment()),
1338 actionCollection(), "tools_uncomment");
1339
1340 setVerticalSelection = new KToggleAction(i18n("&Vertical Selection"), Key_F4, this, SLOT(toggleVertical()),
1341 actionCollection(), "set_verticalSelect");
1342
1343 connect(setHighlight, SIGNAL(activated(int)), this, SLOT(setHl(int)));
1344 QStringList list;
1345 for (int z = 0; z < HlManager::self()->highlights(); z++)
1346 list.append(HlManager::self()->hlName(z));
1347 setHighlight->setItems(list);
1348
1349 setEndOfLine = new KSelectAction(i18n("&End Of Line"), 0, actionCollection(), "set_eol");
1350 connect(setEndOfLine, SIGNAL(activated(int)), this, SLOT(setEol(int)));
1351 list.clear();
1352 list.append("&Unix");
1353 list.append("&Windows/Dos");
1354 list.append("&Macintosh");
1355 setEndOfLine->setItems(list);
1356#endif
1357}
1358#endif
1359
1360void KateView::slotUpdate()
1361{
1362 int cfg = config();
1363
1364#warning fixme setVerticalSelection->setChecked(cfg & KateView::cfVerticalSelect);
1365
1366 slotNewUndo();
1367}
1368void KateView::slotFileStatusChanged()
1369{
1370 int eol = getEol();
1371 eol = eol>=1 ? eol : 0;
1372
1373#warning fixme setEndOfLine->setCurrentItem(eol);
1374}
1375void KateView::slotNewUndo()
1376{
1377#if 0
1378 int state = undoState();
1379
1380 editUndoHist->setEnabled(state & 1 || state & 2);
1381
1382 QString t = i18n("Und&o"); // it would be nicer to fetch the original string
1383 if (state & 1) {
1384 editUndo->setEnabled(true);
1385 t += ' ';
1386 t += i18n(undoTypeName(nextUndoType()));
1387 } else {
1388 editUndo->setEnabled(false);
1389 }
1390 editUndo->setText(t);
1391
1392 t = i18n("Re&do"); // it would be nicer to fetch the original string
1393 if (state & 2) {
1394 editRedo->setEnabled(true);
1395 t += ' ';
1396 t += i18n(undoTypeName(nextRedoType()));
1397 } else {
1398 editRedo->setEnabled(false);
1399 }
1400 editRedo->setText(t);
1401#endif
1402}
1403
1404void KateView::slotHighlightChanged()
1405{
1406// setHighlight->setCurrentItem(getHl());
1407}
1408
1409
1410void KateView::keyPressEvent( QKeyEvent *ev )
1411{
1412 switch ( ev->key() )
1413 {
1414 case Key_Left:
1415 if ( ev->state() & ShiftButton )
1416 {
1417 if ( ev->state() & ControlButton )
1418 shiftWordLeft();
1419 else
1420 shiftCursorLeft();
1421 }
1422 else if ( ev->state() & ControlButton )
1423 wordLeft();
1424 else
1425 cursorLeft();
1426 break;
1427 case Key_Right:
1428 if ( ev->state() & ShiftButton )
1429 {
1430 if ( ev->state() & ControlButton )
1431 shiftWordRight();
1432 else
1433 shiftCursorRight();
1434 }
1435 else if ( ev->state() & ControlButton )
1436 wordRight();
1437 else
1438 cursorRight();
1439 break;
1440 case Key_Home:
1441 if ( ev->state() & ShiftButton )
1442 {
1443 if ( ev->state() & ControlButton )
1444 shiftTop();
1445 else
1446 shiftHome();
1447 }
1448 else if ( ev->state() & ControlButton )
1449 top();
1450 else
1451 home();
1452 break;
1453 case Key_End:
1454 if ( ev->state() & ShiftButton )
1455 {
1456 if ( ev->state() & ControlButton )
1457 shiftBottom();
1458 else
1459 shiftEnd();
1460 }
1461 else if ( ev->state() & ControlButton )
1462 bottom();
1463 else
1464 end();
1465 break;
1466 case Key_Up:
1467 if ( ev->state() & ShiftButton )
1468 shiftUp();
1469 else if ( ev->state() & ControlButton )
1470 scrollUp();
1471 else
1472 up();
1473 break;
1474 case Key_Down:
1475 if ( ev->state() & ShiftButton )
1476 shiftDown();
1477 else if ( ev->state() & ControlButton )
1478 scrollDown();
1479 else
1480 down();
1481 break;
1482 case Key_PageUp:
1483 if ( ev->state() & ShiftButton )
1484 shiftPageUp();
1485 else if ( ev->state() & ControlButton )
1486 topOfView();
1487 else
1488 pageUp();
1489 break;
1490 case Key_PageDown:
1491 if ( ev->state() & ShiftButton )
1492 shiftPageDown();
1493 else if ( ev->state() & ControlButton )
1494 bottomOfView();
1495 else
1496 pageDown();
1497 break;
1498 case Key_Return:
1499 case Key_Enter:
1500 keyReturn();
1501 break;
1502 case Key_Delete:
1503 if ( ev->state() & ControlButton )
1504 {
1505 VConfig c;
1506 shiftWordRight();
1507 myViewInternal->getVConfig(c);
1508 myDoc->delMarkedText(c);
1509 myViewInternal->update();
1510 }
1511 else keyDelete();
1512 break;
1513 case Key_Backspace:
1514 if ( ev->state() & ControlButton )
1515 {
1516 VConfig c;
1517 shiftWordLeft();
1518 myViewInternal->getVConfig(c);
1519 myDoc->delMarkedText(c);
1520 myViewInternal->update();
1521 }
1522 else backspace();
1523 break;
1524 case Key_Insert:
1525 toggleInsert();
1526 break;
1527 case Key_K:
1528 if ( ev->state() & ControlButton )
1529 {
1530 killLine();
1531 break;
1532 }
1533 default:
1534 KTextEditor::View::keyPressEvent( ev );
1535 return;
1536 break;
1537 }
1538 ev->accept();
1539}
1540
1541
1542void KateView::setCursorPosition( int line, int col, bool /*mark*/ )
1543{
1544 setCursorPositionInternal( line, col );
1545}
1546
1547void KateView::getCursorPosition( int *line, int *col )
1548{
1549 if ( line )
1550 *line = currentLine();
1551
1552 if ( col )
1553 *col = currentColumn();
1554}
1555
1556
1557int KateView::currentLine() {
1558 return myViewInternal->cursor.y;
1559}
1560
1561int KateView::currentColumn() {
1562 return myDoc->currentColumn(myViewInternal->cursor);
1563}
1564
1565int KateView::currentCharNum() {
1566 return myViewInternal->cursor.x;
1567}
1568
1569void KateView::setCursorPositionInternal(int line, int col) {
1570 PointStruc cursor;
1571
1572 cursor.x = col;
1573 cursor.y = line;
1574 myViewInternal->updateCursor(cursor);
1575 myViewInternal->center();
1576// myViewInternal->updateView(ufPos, 0, line*myDoc->fontHeight - height()/2);
1577// myDoc->updateViews(myViewInternal); //uptade all other views except this one
1578 myDoc->updateViews();
1579}
1580
1581int KateView::config() {
1582 int flags;
1583
1584 flags = configFlags;
1585 if (myDoc->singleSelection()) flags |= KateView::cfSingleSelection;
1586 return flags;
1587}
1588
1589void KateView::setConfig(int flags) {
1590 bool updateView;
1591
1592 // cfSingleSelection is a doc-property
1593 myDoc->setSingleSelection(flags & KateView::cfSingleSelection);
1594 flags &= ~KateView::cfSingleSelection;
1595
1596 if (flags != configFlags) {
1597 // update the view if visibility of tabs has changed
1598 updateView = (flags ^ configFlags) & KateView::cfShowTabs;
1599 configFlags = flags;
1600 emit newStatus();
1601 if (updateView) myViewInternal->update();
1602 }
1603}
1604
1605int KateView::tabWidth() {
1606 return myDoc->tabChars;
1607}
1608
1609void KateView::setTabWidth(int w) {
1610 myDoc->setTabWidth(w);
1611 myDoc->updateViews();
1612}
1613
1614void KateView::setEncoding (QString e) {
1615 myDoc->setEncoding (e);
1616 myDoc->updateViews();
1617}
1618
1619int KateView::undoSteps() {
1620 return myDoc->undoSteps;
1621}
1622
1623void KateView::setUndoSteps(int s) {
1624 myDoc->setUndoSteps(s);
1625}
1626
1627bool KateView::isReadOnly() {
1628 return myDoc->readOnly;
1629}
1630
1631bool KateView::isModified() {
1632 return myDoc->modified;
1633}
1634
1635void KateView::setReadOnly(bool m) {
1636 myDoc->setReadOnly(m);
1637}
1638
1639void KateView::setModified(bool m) {
1640 myDoc->setModified(m);
1641}
1642
1643bool KateView::isLastView() {
1644 return myDoc->isLastView(1);
1645}
1646
1647KateDocument *KateView::doc() {
1648 return myDoc;
1649}
1650
1651int KateView::undoState() {
1652 if (isReadOnly())
1653 return 0;
1654 else
1655 return myDoc->undoState;
1656}
1657
1658int KateView::nextUndoType() {
1659 return myDoc->nextUndoType();
1660}
1661
1662int KateView::nextRedoType() {
1663 return myDoc->nextRedoType();
1664}
1665
1666void KateView::undoTypeList(QValueList<int> &lst)
1667{
1668 myDoc->undoTypeList(lst);
1669}
1670
1671void KateView::redoTypeList(QValueList<int> &lst)
1672{
1673 myDoc->redoTypeList(lst);
1674}
1675
1676const char * KateView::undoTypeName(int type) {
1677 return KateActionGroup::typeName(type);
1678}
1679
1680QColor* KateView::getColors()
1681{
1682 return myDoc->colors;
1683}
1684
1685void KateView::applyColors()
1686{
1687 myDoc->tagAll();
1688 myDoc->updateViews();
1689}
1690
1691bool KateView::isOverwriteMode() const
1692{
1693 return ( configFlags & KateView::cfOvr );
1694}
1695
1696void KateView::setOverwriteMode( bool b )
1697{
1698 if ( isOverwriteMode() && !b )
1699 setConfig( configFlags ^ KateView::cfOvr );
1700 else
1701 setConfig( configFlags | KateView::cfOvr );
1702}
1703
1704void KateView::toggleInsert() {
1705 setConfig(configFlags ^ KateView::cfOvr);
1706}
1707
1708void KateView::toggleVertical()
1709{
1710 setConfig(configFlags ^ KateView::cfVerticalSelect);
1711}
1712
1713
1714int KateView::numLines() {
1715 return myDoc->numLines();
1716}
1717
1718QString KateView::text() {
1719 return myDoc->text();
1720}
1721
1722QString KateView::currentTextLine() {
1723 TextLine::Ptr textLine = myDoc->getTextLine(myViewInternal->cursor.y);
1724 return QString(textLine->getText(), textLine->length());
1725}
1726
1727QString KateView::textLine(int num) {
1728 TextLine::Ptr textLine = myDoc->getTextLine(num);
1729 return QString(textLine->getText(), textLine->length());
1730}
1731
1732QString KateView::currentWord() {
1733 return myDoc->getWord(myViewInternal->cursor);
1734}
1735
1736QString KateView::word(int x, int y) {
1737 PointStruc cursor;
1738 cursor.y = (myViewInternal->yPos + y)/myDoc->fontHeight;
1739 if (cursor.y < 0 || cursor.y > myDoc->lastLine()) return QString();
1740 cursor.x = myDoc->textPos(myDoc->getTextLine(cursor.y), myViewInternal->xPos-2 + x);
1741 return myDoc->getWord(cursor);
1742}
1743
1744void KateView::setText(const QString &s) {
1745 myDoc->setText(s);
1746 myDoc->updateViews();
1747}
1748
1749void KateView::insertText(const QString &s, bool /*mark*/) {
1750 VConfig c;
1751 myViewInternal->getVConfig(c);
1752 myDoc->insert(c, s);
1753 myDoc->updateViews();
1754}
1755
1756bool KateView::hasMarkedText() {
1757 return myDoc->hasMarkedText();
1758}
1759
1760QString KateView::markedText() {
1761 return myDoc->markedText(configFlags);
1762}
1763
1764bool KateView::canDiscard() {
1765 int query;
1766
1767 if (isModified()) {
1768 query = KMessageBox::warningYesNoCancel(this,
1769 i18n("The current Document has been modified.\nWould you like to save it?"));
1770 switch (query) {
1771 case KMessageBox::Yes: //yes
1772 if (save() == CANCEL) return false;
1773 if (isModified()) {
1774 query = KMessageBox::warningContinueCancel(this,
1775 i18n("Could not save the document.\nDiscard it and continue?"),
1776 QString::null, i18n("&Discard"));
1777 if (query == KMessageBox::Cancel) return false;
1778 }
1779 break;
1780 case KMessageBox::Cancel: //cancel
1781 return false;
1782 }
1783 }
1784 return true;
1785}
1786
1787void KateView::flush()
1788{
1789 if (canDiscard()) myDoc->flush();
1790}
1791
1792KateView::fileResult KateView::save() {
1793 int query = KMessageBox::Yes;
1794 if (isModified()) {
1795 return saveAs();
1796 }
1797 return OK;
1798}
1799
1800KateView::fileResult KateView::saveAs() {
1801 return OK;
1802}
1803
1804void KateView::doCursorCommand(int cmdNum) {
1805 VConfig c;
1806 myViewInternal->getVConfig(c);
1807 if (cmdNum & selectFlag) c.flags |= KateView::cfMark;
1808 if (cmdNum & multiSelectFlag) c.flags |= KateView::cfMark | KateView::cfKeepSelection;
1809 cmdNum &= ~(selectFlag | multiSelectFlag);
1810 myViewInternal->doCursorCommand(c, cmdNum);
1811 myDoc->updateViews();
1812}
1813
1814void KateView::doEditCommand(int cmdNum) {
1815 VConfig c;
1816 myViewInternal->getVConfig(c);
1817 myViewInternal->doEditCommand(c, cmdNum);
1818 myDoc->updateViews();
1819}
1820
1821void KateView::undoMultiple(int count) {
1822 if (isReadOnly())
1823 return;
1824
1825 VConfig c;
1826 myViewInternal->getVConfig(c);
1827 myDoc->undo(c, count);
1828 myDoc->updateViews();
1829}
1830
1831void KateView::redoMultiple(int count) {
1832 if (isReadOnly())
1833 return;
1834
1835 VConfig c;
1836 myViewInternal->getVConfig(c);
1837 myDoc->redo(c, count);
1838 myDoc->updateViews();
1839}
1840
1841void KateView::undoHistory()
1842{
1843 UndoHistory *undoH;
1844
1845 undoH = new UndoHistory(this, this, "UndoHistory", true);
1846
1847 undoH->setCaption(i18n("Undo/Redo History"));
1848
1849 connect(this,SIGNAL(newUndo()),undoH,SLOT(newUndo()));
1850 connect(undoH,SIGNAL(undo(int)),this,SLOT(undoMultiple(int)));
1851 connect(undoH,SIGNAL(redo(int)),this,SLOT(redoMultiple(int)));
1852
1853 undoH->exec();
1854
1855 delete undoH;
1856}
1857
1858static void kwview_addToStrList(QStringList &list, const QString &str) {
1859 if (list.count() > 0) {
1860 if (list.first() == str) return;
1861 QStringList::Iterator it;
1862 it = list.find(str);
1863 if (*it != 0L) list.remove(it);
1864 if (list.count() >= 16) list.remove(list.fromLast());
1865 }
1866 list.prepend(str);
1867}
1868
1869void KateView::find() {
1870 SearchDialog *searchDialog;
1871
1872 if (!myDoc->hasMarkedText()) searchFlags &= ~KateView::sfSelected;
1873
1874 searchDialog = new SearchDialog(this, myDoc->searchForList, myDoc->replaceWithList,
1875 searchFlags & ~KateView::sfReplace);
1876
1877 // If the user has marked some text we use that otherwise
1878 // use the word under the cursor.
1879 QString str;
1880 if (myDoc->hasMarkedText())
1881 str = markedText();
1882
1883 if (str.isEmpty())
1884 str = currentWord();
1885
1886 if (!str.isEmpty())
1887 {
1888 str.replace(QRegExp("^\n"), "");
1889 int pos=str.find("\n");
1890 if (pos>-1)
1891 str=str.left(pos);
1892 searchDialog->setSearchText( str );
1893 }
1894
1895 myViewInternal->focusOutEvent(0L);// QT bug ?
1896 if (searchDialog->exec() == QDialog::Accepted) {
1897 kwview_addToStrList(myDoc->searchForList, searchDialog->getSearchFor());
1898 searchFlags = searchDialog->getFlags() | (searchFlags & KateView::sfPrompt);
1899 initSearch(s, searchFlags);
1900 findAgain(s);
1901 }
1902 delete searchDialog;
1903}
1904
1905void KateView::replace() {
1906 SearchDialog *searchDialog;
1907
1908 if (isReadOnly()) return;
1909
1910 if (!myDoc->hasMarkedText()) searchFlags &= ~KateView::sfSelected;
1911 searchDialog = new SearchDialog(this, myDoc->searchForList, myDoc->replaceWithList,
1912 searchFlags | KateView::sfReplace);
1913
1914 // If the user has marked some text we use that otherwise
1915 // use the word under the cursor.
1916 QString str;
1917 if (myDoc->hasMarkedText())
1918 str = markedText();
1919
1920 if (str.isEmpty())
1921 str = currentWord();
1922
1923 if (!str.isEmpty())
1924 {
1925 str.replace(QRegExp("^\n"), "");
1926 int pos=str.find("\n");
1927 if (pos>-1)
1928 str=str.left(pos);
1929 searchDialog->setSearchText( str );
1930 }
1931
1932 myViewInternal->focusOutEvent(0L);// QT bug ?
1933 if (searchDialog->exec() == QDialog::Accepted) {
1934// myDoc->recordReset();
1935 kwview_addToStrList(myDoc->searchForList, searchDialog->getSearchFor());
1936 kwview_addToStrList(myDoc->replaceWithList, searchDialog->getReplaceWith());
1937 searchFlags = searchDialog->getFlags();
1938 initSearch(s, searchFlags);
1939 replaceAgain();
1940 }
1941 delete searchDialog;
1942}
1943
1944void KateView::gotoLine() {
1945 GotoLineDialog *dlg;
1946 PointStruc cursor;
1947
1948 dlg = new GotoLineDialog(this, myViewInternal->cursor.y + 1, myDoc->numLines());
1949// dlg = new GotoLineDialog(myViewInternal->cursor.y + 1, this);
1950
1951 if (dlg->exec() == QDialog::Accepted) {
1952// myDoc->recordReset();
1953 cursor.x = 0;
1954 cursor.y = dlg->getLine() - 1;
1955 myDoc->needPreHighlight(cursor.y);
1956 myViewInternal->updateCursor(cursor);
1957 myViewInternal->center();
1958 myViewInternal->updateView(KateView::ufUpdateOnScroll);
1959 myDoc->updateViews(this); //uptade all other views except this one
1960 }
1961 delete dlg;
1962}
1963
1964
1965void KateView::initSearch(SConfig &s, int flags) {
1966
1967 s.flags = flags;
1968 s.setPattern(myDoc->searchForList.first());
1969
1970 if (!(s.flags & KateView::sfFromBeginning)) {
1971 // If we are continuing a backward search, make sure we do not get stuck
1972 // at an existing match.
1973 s.cursor = myViewInternal->cursor;
1974 TextLine::Ptr textLine = myDoc->getTextLine(s.cursor.y);
1975 QString const txt(textLine->getText(),textLine->length());
1976 const QString searchFor= myDoc->searchForList.first();
1977 int pos = s.cursor.x-searchFor.length()-1;
1978 if ( pos < 0 ) pos = 0;
1979 pos= txt.find(searchFor, pos, s.flags & KateView::sfCaseSensitive);
1980 if ( s.flags & KateView::sfBackward )
1981 {
1982 if ( pos <= s.cursor.x ) s.cursor.x= pos-1;
1983 }
1984 else
1985 if ( pos == s.cursor.x ) s.cursor.x++;
1986 } else {
1987 if (!(s.flags & KateView::sfBackward)) {
1988 s.cursor.x = 0;
1989 s.cursor.y = 0;
1990 } else {
1991 s.cursor.x = -1;
1992 s.cursor.y = myDoc->lastLine();
1993 }
1994 s.flags |= KateView::sfFinished;
1995 }
1996 if (!(s.flags & KateView::sfBackward)) {
1997 if (!(s.cursor.x || s.cursor.y))
1998 s.flags |= KateView::sfFinished;
1999 }
2000 s.startCursor = s.cursor;
2001}
2002
2003void KateView::continueSearch(SConfig &s) {
2004
2005 if (!(s.flags & KateView::sfBackward)) {
2006 s.cursor.x = 0;
2007 s.cursor.y = 0;
2008 } else {
2009 s.cursor.x = -1;
2010 s.cursor.y = myDoc->lastLine();
2011 }
2012 s.flags |= KateView::sfFinished;
2013 s.flags &= ~KateView::sfAgain;
2014}
2015
2016void KateView::findAgain(SConfig &s) {
2017 int query;
2018 PointStruc cursor;
2019 QString str;
2020
2021 QString searchFor = myDoc->searchForList.first();
2022
2023 if( searchFor.isEmpty() ) {
2024 find();
2025 return;
2026 }
2027
2028 do {
2029 query = KMessageBox::Cancel;
2030 if (myDoc->doSearch(s,searchFor)) {
2031 cursor = s.cursor;
2032 if (!(s.flags & KateView::sfBackward))
2033 s.cursor.x += s.matchedLength;
2034 myViewInternal->updateCursor(s.cursor); //does deselectAll()
2035 exposeFound(cursor,s.matchedLength,(s.flags & KateView::sfAgain) ? 0 : KateView::ufUpdateOnScroll,false);
2036 } else {
2037 if (!(s.flags & KateView::sfFinished)) {
2038 // ask for continue
2039 if (!(s.flags & KateView::sfBackward)) {
2040 // forward search
2041 str = i18n("End of document reached.\n"
2042 "Continue from the beginning?");
2043 query = KMessageBox::warningContinueCancel(this,
2044 str, i18n("Find"), i18n("Continue"));
2045 } else {
2046 // backward search
2047 str = i18n("Beginning of document reached.\n"
2048 "Continue from the end?");
2049 query = KMessageBox::warningContinueCancel(this,
2050 str, i18n("Find"), i18n("Continue"));
2051 }
2052 continueSearch(s);
2053 } else {
2054 // wrapped
2055 KMessageBox::sorry(this,
2056 i18n("Search string '%1' not found!").arg(searchFor),
2057 i18n("Find"));
2058 }
2059 }
2060 } while (query == KMessageBox::Continue);
2061}
2062
2063void KateView::replaceAgain() {
2064 if (isReadOnly())
2065 return;
2066
2067 replaces = 0;
2068 if (s.flags & KateView::sfPrompt) {
2069 doReplaceAction(-1);
2070 } else {
2071 doReplaceAction(KateView::srAll);
2072 }
2073}
2074
2075void KateView::doReplaceAction(int result, bool found) {
2076 int rlen;
2077 PointStruc cursor;
2078 bool started;
2079
2080 QString searchFor = myDoc->searchForList.first();
2081 QString replaceWith = myDoc->replaceWithList.first();
2082 rlen = replaceWith.length();
2083
2084 switch (result) {
2085 case KateView::srYes: //yes
2086 myDoc->recordStart(this, s.cursor, configFlags,
2087 KateActionGroup::ugReplace, true);
2088 myDoc->recordReplace(s.cursor, s.matchedLength, replaceWith);
2089 replaces++;
2090 if (s.cursor.y == s.startCursor.y && s.cursor.x < s.startCursor.x)
2091 s.startCursor.x += rlen - s.matchedLength;
2092 if (!(s.flags & KateView::sfBackward)) s.cursor.x += rlen;
2093 myDoc->recordEnd(this, s.cursor, configFlags | KateView::cfPersistent);
2094 break;
2095 case KateView::srNo: //no
2096 if (!(s.flags & KateView::sfBackward)) s.cursor.x += s.matchedLength;
2097 break;
2098 case KateView::srAll: //replace all
2099 deleteReplacePrompt();
2100 do {
2101 started = false;
2102 while (found || myDoc->doSearch(s,searchFor)) {
2103 if (!started) {
2104 found = false;
2105 myDoc->recordStart(this, s.cursor, configFlags,
2106 KateActionGroup::ugReplace);
2107 started = true;
2108 }
2109 myDoc->recordReplace(s.cursor, s.matchedLength, replaceWith);
2110 replaces++;
2111 if (s.cursor.y == s.startCursor.y && s.cursor.x < s.startCursor.x)
2112 s.startCursor.x += rlen - s.matchedLength;
2113 if (!(s.flags & KateView::sfBackward)) s.cursor.x += rlen;
2114 }
2115 if (started) myDoc->recordEnd(this, s.cursor,
2116 configFlags | KateView::cfPersistent);
2117 } while (!askReplaceEnd());
2118 return;
2119 case KateView::srCancel: //cancel
2120 deleteReplacePrompt();
2121 return;
2122 default:
2123 replacePrompt = 0L;
2124 }
2125
2126 do {
2127 if (myDoc->doSearch(s,searchFor)) {
2128 //text found: highlight it, show replace prompt if needed and exit
2129 cursor = s.cursor;
2130 if (!(s.flags & KateView::sfBackward)) cursor.x += s.matchedLength;
2131 myViewInternal->updateCursor(cursor); //does deselectAll()
2132 exposeFound(s.cursor,s.matchedLength,(s.flags & KateView::sfAgain) ? 0 : KateView::ufUpdateOnScroll,true);
2133 if (replacePrompt == 0L) {
2134 replacePrompt = new ReplacePrompt(this);
2135 myDoc->setPseudoModal(replacePrompt);//disable();
2136 connect(replacePrompt,SIGNAL(clicked()),this,SLOT(replaceSlot()));
2137 replacePrompt->show(); //this is not modal
2138 }
2139 return; //exit if text found
2140 }
2141 //nothing found: repeat until user cancels "repeat from beginning" dialog
2142 } while (!askReplaceEnd());
2143 deleteReplacePrompt();
2144}
2145
2146void KateView::exposeFound(PointStruc &cursor, int slen, int flags, bool replace) {
2147 int x1, x2, y1, y2, xPos, yPos;
2148
2149 VConfig c;
2150 myViewInternal->getVConfig(c);
2151 myDoc->selectLength(cursor,slen,c.flags);
2152
2153 TextLine::Ptr textLine = myDoc->getTextLine(cursor.y);
2154 x1 = myDoc->textWidth(textLine,cursor.x) -10;
2155 x2 = myDoc->textWidth(textLine,cursor.x + slen) +20;
2156 y1 = myDoc->fontHeight*cursor.y -10;
2157 y2 = y1 + myDoc->fontHeight +30;
2158
2159 xPos = myViewInternal->xPos;
2160 yPos = myViewInternal->yPos;
2161
2162 if (x1 < 0) x1 = 0;
2163 if (replace) y2 += 90;
2164
2165 if (x1 < xPos || x2 > xPos + myViewInternal->width()) {
2166 xPos = x2 - myViewInternal->width();
2167 }
2168 if (y1 < yPos || y2 > yPos + myViewInternal->height()) {
2169 xPos = x2 - myViewInternal->width();
2170 yPos = myDoc->fontHeight*cursor.y - height()/3;
2171 }
2172 myViewInternal->setPos(xPos, yPos);
2173 myViewInternal->updateView(flags);// | ufPos,xPos,yPos);
2174 myDoc->updateViews(this);
2175}
2176
2177void KateView::deleteReplacePrompt() {
2178 myDoc->setPseudoModal(0L);
2179}
2180
2181bool KateView::askReplaceEnd() {
2182 QString str;
2183 int query;
2184
2185 myDoc->updateViews();
2186 if (s.flags & KateView::sfFinished) {
2187 // replace finished
2188 str = i18n("%1 replacement(s) made").arg(replaces);
2189 KMessageBox::information(this, str, i18n("Replace"));
2190 return true;
2191 }
2192
2193 // ask for continue
2194 if (!(s.flags & KateView::sfBackward)) {
2195 // forward search
2196 str = i18n("%1 replacement(s) made.\n"
2197 "End of document reached.\n"
2198 "Continue from the beginning?").arg(replaces);
2199 query = KMessageBox::questionYesNo(this, str, i18n("Replace"),
2200 i18n("Continue"), i18n("Stop"));
2201 } else {
2202 // backward search
2203 str = i18n("%1 replacement(s) made.\n"
2204 "Beginning of document reached.\n"
2205 "Continue from the end?").arg(replaces);
2206 query = KMessageBox::questionYesNo(this, str, i18n("Replace"),
2207 i18n("Continue"), i18n("Stop"));
2208 }
2209 replaces = 0;
2210 continueSearch(s);
2211 return (query == KMessageBox::No);
2212}
2213
2214void KateView::replaceSlot() {
2215 doReplaceAction(replacePrompt->result(),true);
2216}
2217
2218void KateView::installPopup(QPopupMenu *rmb_Menu)
2219{
2220 rmbMenu = rmb_Menu;
2221}
2222
2223void KateView::readConfig()
2224{
2225 KConfig *config = KGlobal::config();
2226 config->setGroup("Kate View");
2227
2228 searchFlags = config->readNumEntry("SearchFlags", KateView::sfPrompt);
2229 configFlags = config->readNumEntry("ConfigFlags", configFlags) & ~KateView::cfMark;
2230
2231 config->sync();
2232}
2233
2234void KateView::writeConfig()
2235{
2236 KConfig *config = KGlobal::config();
2237 config->setGroup("Kate View");
2238
2239 config->writeEntry("SearchFlags",searchFlags);
2240 config->writeEntry("ConfigFlags",configFlags);
2241
2242 config->sync();
2243}
2244
2245void KateView::readSessionConfig(KConfig *config)
2246{
2247 PointStruc cursor;
2248
2249 myViewInternal->xPos = config->readNumEntry("XPos");
2250 myViewInternal->yPos = config->readNumEntry("YPos");
2251 cursor.x = config->readNumEntry("CursorX");
2252 cursor.y = config->readNumEntry("CursorY");
2253 myViewInternal->updateCursor(cursor);
2254 myIconBorder = config->readBoolEntry("IconBorder on");
2255 setIconBorder(myIconBorder);
2256}
2257
2258void KateView::writeSessionConfig(KConfig *config)
2259{
2260 config->writeEntry("XPos",myViewInternal->xPos);
2261 config->writeEntry("YPos",myViewInternal->yPos);
2262 config->writeEntry("CursorX",myViewInternal->cursor.x);
2263 config->writeEntry("CursorY",myViewInternal->cursor.y);
2264 config->writeEntry("IconBorder on", myIconBorder);
2265}
2266
2267void KateView::configDialog()
2268{
2269
2270#warning fixme
2271
2272#if 1
2273 KDialogBase *kd = new KDialogBase(KDialogBase::IconList,
2274 i18n("Configure Editor"),
2275 KDialogBase::Ok | KDialogBase::Cancel |
2276 KDialogBase::Help ,
2277 KDialogBase::Ok, this, "tabdialog");
2278
2279 // color options
2280 QFrame *page=kd->addPage(i18n("Colors"));
2281 (new QVBoxLayout(page))->setAutoAdd(true);
2282 ColorConfig *colorConfig = new ColorConfig(page);
2283 QColor* colors = getColors();
2284 colorConfig->setColors(colors);
2285
2286 page = kd->addPage(i18n("Fonts"));
2287 (new QVBoxLayout(page))->setAutoAdd(true);
2288
2289 FontConfig *fontConfig = new FontConfig(page);
2290 fontConfig->setFont (myDoc->getFont());
2291
2292 // indent options
2293 page=kd->addPage(i18n("Indent"));
2294 (new QVBoxLayout(page))->setAutoAdd(true);
2295
2296 IndentConfigTab *indentConfig = new IndentConfigTab(page, this);
2297
2298 // select options
2299 page=kd->addPage(i18n("Select"));
2300 (new QVBoxLayout(page))->setAutoAdd(true);
2301
2302 SelectConfigTab *selectConfig = new SelectConfigTab(page, this);
2303
2304 // edit options
2305 page=kd->addPage(i18n("Edit"));
2306 (new QVBoxLayout(page))->setAutoAdd(true);
2307
2308 EditConfigTab *editConfig = new EditConfigTab(page, this);
2309
2310
2311
2312 HighlightDialogPage *hlPage;
2313 HlManager *hlManager;
2314 HlDataList hlDataList;
2315 ItemStyleList defaultStyleList;
2316
2317 hlManager = HlManager::self();
2318
2319 defaultStyleList.setAutoDelete(true);
2320 hlManager->getDefaults(defaultStyleList);
2321
2322 hlDataList.setAutoDelete(true);
2323 //this gets the data from the KConfig object
2324 hlManager->getHlDataList(hlDataList);
2325
2326 page=kd->addPage(i18n("Highlighting"));
2327 (new QVBoxLayout(page))->setAutoAdd(true);
2328
2329 hlPage = new HighlightDialogPage(hlManager, &defaultStyleList, &hlDataList, 0, page);
2330
2331 if (kd->exec()) {
2332 // color options
2333 colorConfig->getColors(colors);
2334 myDoc->setFont (fontConfig->getFont());
2335
2336 applyColors();
2337 // indent options
2338 indentConfig->getData(this);
2339 // select options
2340 selectConfig->getData(this);
2341 // edit options
2342 editConfig->getData(this);
2343 // spell checker
2344 hlManager->setHlDataList(hlDataList);
2345 hlManager->setDefaults(defaultStyleList);
2346 hlPage->saveData();
2347 }
2348
2349 delete kd;
2350
2351#endif
2352}
2353
2354int KateView::getHl() {
2355 return myDoc->highlightNum();
2356}
2357
2358void KateView::setDontChangeHlOnSave()
2359{
2360 myDoc->setDontChangeHlOnSave();
2361}
2362
2363void KateView::setHl(int n) {
2364 myDoc->setHighlight(n);
2365 myDoc->setDontChangeHlOnSave();
2366 myDoc->updateViews();
2367}
2368
2369int KateView::getEol() {
2370 return myDoc->eolMode;
2371}
2372
2373void KateView::setEol(int eol) {
2374 if (isReadOnly())
2375 return;
2376
2377 myDoc->eolMode = eol;
2378 myDoc->setModified(true);
2379}
2380
2381
2382
2383void KateView::paintEvent(QPaintEvent *e) {
2384 int x, y;
2385
2386 QRect updateR = e->rect(); // update rectangle
2387// debug("Update rect = ( %i, %i, %i, %i )",
2388// updateR.x(),updateR.y(), updateR.width(), updateR.height() );
2389
2390 int ux1 = updateR.x();
2391 int uy1 = updateR.y();
2392 int ux2 = ux1 + updateR.width();
2393 int uy2 = uy1 + updateR.height();
2394
2395 QPainter paint;
2396 paint.begin(this);
2397
2398 QColorGroup g = colorGroup();
2399 x = width();
2400 y = height();
2401
2402 paint.setPen(g.dark());
2403 if (uy1 <= 0) paint.drawLine(0,0,x-2,0);
2404 if (ux1 <= 0) paint.drawLine(0,1,0,y-2);
2405
2406 paint.setPen(black);
2407 if (uy1 <= 1) paint.drawLine(1,1,x-3,1);
2408 if (ux1 <= 1) paint.drawLine(1,2,1,y-3);
2409
2410 paint.setPen(g.midlight());
2411 if (uy2 >= y-1) paint.drawLine(1,y-2,x-3,y-2);
2412 if (ux2 >= x-1) paint.drawLine(x-2,1,x-2,y-2);
2413
2414 paint.setPen(g.light());
2415 if (uy2 >= y) paint.drawLine(0,y-1,x-2,y-1);
2416 if (ux2 >= x) paint.drawLine(x-1,0,x-1,y-1);
2417
2418 x -= 2 + 16;
2419 y -= 2 + 16;
2420 if (ux2 > x && uy2 > y) {
2421 paint.fillRect(x,y,16,16,g.background());
2422 }
2423 paint.end();
2424}
2425
2426void KateView::resizeEvent(QResizeEvent *) {
2427
2428// debug("Resize %d, %d",e->size().width(),e->size().height());
2429
2430//myViewInternal->resize(width() -20, height() -20);
2431 myViewInternal->tagAll();
2432 myViewInternal->updateView(0/*ufNoScroll*/);
2433}
2434
2435
2436// Applies a new pattern to the search context.
2437void SConfig::setPattern(QString &newPattern) {
2438 bool regExp = (flags & KateView::sfRegularExpression);
2439
2440 m_pattern = newPattern;
2441 if (regExp) {
2442 m_regExp.setCaseSensitive(flags & KateView::sfCaseSensitive);
2443 m_regExp.setPattern(m_pattern);
2444 }
2445}
2446
2447// Applies the search context to the given string, and returns whether a match was found. If one is,
2448// the length of the string matched is also returned.
2449int SConfig::search(QString &text, int index) {
2450 bool regExp = (flags & KateView::sfRegularExpression);
2451 bool caseSensitive = (flags & KateView::sfCaseSensitive);
2452
2453 if (flags & KateView::sfBackward) {
2454 if (regExp) {
2455 index = text.findRev(m_regExp, index);
2456 }
2457 else {
2458 index = text.findRev(m_pattern, index, caseSensitive);
2459 }
2460 }
2461 else {
2462 if (regExp) {
2463 index = text.find(m_regExp, index);
2464 }
2465 else {
2466 index = text.find(m_pattern, index, caseSensitive);
2467 }
2468 }
2469
2470 // Work out the matched length.
2471 if (index != -1)
2472 {
2473 if (regExp) {
2474 m_regExp.match(text, index, &matchedLength, false);
2475 }
2476 else {
2477 matchedLength = m_pattern.length();
2478 }
2479 }
2480 return index;
2481}
2482
2483void KateView::setActive (bool b)
2484{
2485 active = b;
2486}
2487
2488bool KateView::isActive ()
2489{
2490 return active;
2491}
2492
2493void KateView::setFocus ()
2494{
2495 QWidget::setFocus ();
2496
2497 emit gotFocus (this);
2498}
2499
2500bool KateView::eventFilter (QObject *object, QEvent *event)
2501{
2502
2503 if ( (event->type() == QEvent::FocusIn) )
2504 emit gotFocus (this);
2505
2506 if ( (event->type() == QEvent::KeyPress) )
2507 {
2508 QKeyEvent * ke=(QKeyEvent *)event;
2509
2510 if ((ke->key()==Qt::Key_Tab) || (ke->key()==Qt::Key_BackTab))
2511 {
2512 myViewInternal->keyPressEvent(ke);
2513 return true;
2514 }
2515 }
2516 return QWidget::eventFilter (object, event);
2517}
2518
2519void KateView::findAgain (bool back)
2520{
2521 bool b= (searchFlags & sfBackward) > 0;
2522 initSearch(s, (searchFlags & ((b==back)?~sfBackward:~0) & ~sfFromBeginning) // clear flag for forward searching
2523 | sfPrompt | sfAgain | ((b!=back)?sfBackward:0) );
2524 if (s.flags & sfReplace)
2525 replaceAgain();
2526 else
2527 KateView::findAgain(s);
2528}
2529
2530void KateView::slotEditCommand ()
2531{
2532#warning fixme
2533/*
2534 bool ok;
2535 QString cmd = KLineEditDlg::getText("Editing Command", "", &ok, this);
2536
2537 if (ok)
2538 myDoc->cmd()->execCmd (cmd, this);*/
2539}
2540
2541void KateView::setIconBorder (bool enable)
2542{
2543 myIconBorder = enable;
2544
2545 if (myIconBorder)
2546 {
2547 myViewInternal->move(myViewInternal->iconBorderWidth+2, 2);
2548 myViewInternal->leftBorder->show();
2549 }
2550 else
2551 {
2552 myViewInternal->leftBorder->hide();
2553 myViewInternal->move(2, 2);
2554 }
2555}
2556
2557void KateView::toggleIconBorder ()
2558{
2559 setIconBorder (!myIconBorder);
2560}
2561
2562void KateView::gotoMark (Kate::Mark *mark)
2563{
2564 PointStruc cursor;
2565
2566 cursor.x = 0;
2567 cursor.y = mark->line;
2568 myDoc->needPreHighlight(cursor.y);
2569 myViewInternal->updateCursor(cursor);
2570 myViewInternal->center();
2571 myViewInternal->updateView(KateView::ufUpdateOnScroll);
2572 myDoc->updateViews(this);
2573}
2574
2575void KateView::toggleBookmark ()
2576{
2577 TextLine::Ptr line = myDoc->getTextLine (currentLine());
2578
2579 if (line->mark()&KateDocument::Bookmark)
2580 line->delMark(KateDocument::Bookmark);
2581 else
2582 line->addMark(KateDocument::Bookmark);
2583
2584 myDoc->tagLines (currentLine(), currentLine());
2585 myDoc->updateViews();
2586}
2587
2588void KateView::clearBookmarks()
2589{
2590 QList<Kate::Mark> list = myDoc->marks();
2591 for (int i=0; (uint) i < list.count(); i++)
2592 {
2593 if (list.at(i)->type&KateDocument::Bookmark)
2594 {
2595 myDoc->getTextLine(list.at(i)->line)->delMark(KateDocument::Bookmark);
2596 myDoc->tagLines(list.at(i)->line, list.at(i)->line);
2597 }
2598 }
2599
2600 myDoc->updateViews();
2601}
2602
2603void KateView::bookmarkMenuAboutToShow()
2604{
2605#warning fixme
2606#if 0
2607 bookmarkMenu->popupMenu()->clear ();
2608 bookmarkToggle->plug (bookmarkMenu->popupMenu());
2609 bookmarkClear->plug (bookmarkMenu->popupMenu());
2610 bookmarkMenu->popupMenu()->insertSeparator ();
2611
2612 list = myDoc->marks();
2613 for (int i=0; (uint) i < list.count(); i++)
2614 {
2615 if (list.at(i)->type&KateDocument::Bookmark)
2616 {
2617 QString bText = textLine(list.at(i)->line);
2618 bText.truncate(32);
2619 bText.append ("...");
2620 bookmarkMenu->popupMenu()->insertItem ( QString("%1 - \"%2\"").arg(list.at(i)->line).arg(bText), this, SLOT (gotoBookmark(int)), 0, i );
2621 }
2622 }
2623#endif
2624}
2625
2626void KateView::gotoBookmark (int n)
2627{
2628 gotoMark (list.at(n));
2629}
2630
2631int KateView::getHlCount ()
2632{
2633 return HlManager::self()->highlights();
2634}
2635
2636QString KateView::getHlName (int z)
2637{
2638 return HlManager::self()->hlName(z);
2639}
2640
2641QString KateView::getHlSection (int z)
2642{
2643 return HlManager::self()->hlSection (z);
2644}
2645
2646void KateView::slotIncFontSizes ()
2647{
2648 QFont font = myDoc->getFont();
2649 font.setPointSize (font.pointSize()+2);
2650 myDoc->setFont (font);
2651}
2652
2653void KateView::slotDecFontSizes ()
2654{
2655 QFont font = myDoc->getFont();
2656 font.setPointSize (font.pointSize()-2);
2657 myDoc->setFont (font);
2658}
2659
2660const char*bookmark_xpm[]={
2661"12 16 4 1",
2662"b c #808080",
2663"a c #000080",
2664"# c #0000ff",
2665". c None",
2666"............",
2667"............",
2668"........###.",
2669".......#...a",
2670"......#.##.a",
2671".....#.#..aa",
2672"....#.#...a.",
2673"...#.#.a.a..",
2674"..#.#.a.a...",
2675".#.#.a.a....",
2676"#.#.a.a.....",
2677"#.#a.a...bbb",
2678"#...a..bbb..",
2679".aaa.bbb....",
2680"............",
2681"............"};
2682
2683const char* breakpoint_xpm[]={
2684"11 16 6 1",
2685"c c #c6c6c6",
2686". c None",
2687"# c #000000",
2688"d c #840000",
2689"a c #ffffff",
2690"b c #ff0000",
2691"...........",
2692"...........",
2693"...#####...",
2694"..#aaaaa#..",
2695".#abbbbbb#.",
2696"#abbbbbbbb#",
2697"#abcacacbd#",
2698"#abbbbbbbb#",
2699"#abcacacbd#",
2700"#abbbbbbbb#",
2701".#bbbbbbb#.",
2702"..#bdbdb#..",
2703"...#####...",
2704"...........",
2705"...........",
2706"..........."};
2707
2708const char*breakpoint_bl_xpm[]={
2709"11 16 7 1",
2710"a c #c0c0ff",
2711"# c #000000",
2712"c c #0000c0",
2713"e c #0000ff",
2714"b c #dcdcdc",
2715"d c #ffffff",
2716". c None",
2717"...........",
2718"...........",
2719"...#####...",
2720"..#ababa#..",
2721".#bcccccc#.",
2722"#acccccccc#",
2723"#bcadadace#",
2724"#acccccccc#",
2725"#bcadadace#",
2726"#acccccccc#",
2727".#ccccccc#.",
2728"..#cecec#..",
2729"...#####...",
2730"...........",
2731"...........",
2732"..........."};
2733
2734const char*breakpoint_gr_xpm[]={
2735"11 16 6 1",
2736"c c #c6c6c6",
2737"d c #2c2c2c",
2738"# c #000000",
2739". c None",
2740"a c #ffffff",
2741"b c #555555",
2742"...........",
2743"...........",
2744"...#####...",
2745"..#aaaaa#..",
2746".#abbbbbb#.",
2747"#abbbbbbbb#",
2748"#abcacacbd#",
2749"#abbbbbbbb#",
2750"#abcacacbd#",
2751"#abbbbbbbb#",
2752".#bbbbbbb#.",
2753"..#bdbdb#..",
2754"...#####...",
2755"...........",
2756"...........",
2757"..........."};
2758
2759const char*ddd_xpm[]={
2760"11 16 4 1",
2761"a c #00ff00",
2762"b c #000000",
2763". c None",
2764"# c #00c000",
2765"...........",
2766"...........",
2767"...........",
2768"#a.........",
2769"#aaa.......",
2770"#aaaaa.....",
2771"#aaaaaaa...",
2772"#aaaaaaaaa.",
2773"#aaaaaaa#b.",
2774"#aaaaa#b...",
2775"#aaa#b.....",
2776"#a#b.......",
2777"#b.........",
2778"...........",
2779"...........",
2780"..........."};
2781
2782
2783
2784KateIconBorder::KateIconBorder(KateView *view, KateViewInternal *internalView)
2785 : QWidget(view), myView(view), myInternalView(internalView)
2786{
2787 lmbSetsBreakpoints = true;
2788}
2789
2790KateIconBorder::~KateIconBorder()
2791{
2792}
2793
2794void KateIconBorder::paintLine(int i)
2795{
2796 if (!myView->myIconBorder) return;
2797
2798 QPainter p(this);
2799
2800 int fontHeight = myView->doc()->fontHeight;
2801 int y = i*fontHeight - myInternalView->yPos;
2802 p.fillRect(0, y, myInternalView->iconBorderWidth-2, fontHeight, colorGroup().background());
2803 p.setPen(white);
2804 p.drawLine(myInternalView->iconBorderWidth-2, y, myInternalView->iconBorderWidth-2, y + fontHeight);
2805 p.setPen(QColor(colorGroup().background()).dark());
2806 p.drawLine(myInternalView->iconBorderWidth-1, y, myInternalView->iconBorderWidth-1, y + fontHeight);
2807
2808 TextLine *line = myView->doc()->getTextLine(i);
2809 if (!line)
2810 return;
2811
2812 if (line->mark()&KateDocument::Bookmark)
2813 p.drawPixmap(2, y, QPixmap(bookmark_xpm)); /*
2814 if (line && (line->breakpointId() != -1)) {
2815 if (!line->breakpointEnabled())
2816 p.drawPixmap(2, y, QPixmap(breakpoint_gr_xpm));
2817 else if (line->breakpointPending())
2818 p.drawPixmap(2, y, QPixmap(breakpoint_bl_xpm));
2819 else
2820 p.drawPixmap(2, y, QPixmap(breakpoint_xpm));
2821 }
2822 if (line->isExecutionPoint())
2823 p.drawPixmap(2, y, QPixmap(ddd_xpm)); */
2824}
2825
2826
2827void KateIconBorder::paintEvent(QPaintEvent* e)
2828{
2829 if (!myView->myIconBorder) return;
2830
2831 int lineStart = 0;
2832 int lineEnd = 0;
2833
2834 QRect updateR = e->rect();
2835
2836 KateDocument *doc = myView->doc();
2837 int h = doc->fontHeight;
2838 int yPos = myInternalView->yPos;
2839 if (h) {
2840 lineStart = (yPos + updateR.y()) / h;
2841 lineEnd = QMAX((yPos + updateR.y() + updateR.height()) / h, (int)doc->numLines());
2842 }
2843
2844 for(int i = lineStart; i <= lineEnd; ++i)
2845 paintLine(i);
2846}
2847
2848
2849void KateIconBorder::mousePressEvent(QMouseEvent* e)
2850{
2851 myInternalView->placeCursor( 0, e->y(), 0 );
2852
2853 KateDocument *doc = myView->doc();
2854 int cursorOnLine = (e->y() + myInternalView->yPos) / doc->fontHeight;
2855 TextLine *line = doc->getTextLine(cursorOnLine);
2856
2857 switch (e->button()) {
2858 case LeftButton:
2859 if (!line)
2860 break;
2861 else
2862 {
2863 if (line->mark()&KateDocument::Bookmark)
2864 line->delMark (KateDocument::Bookmark);
2865 else
2866 line->addMark (KateDocument::Bookmark);
2867
2868 doc->tagLines(cursorOnLine, cursorOnLine);
2869 doc->updateViews();
2870 }
2871 break;
2872 /* case RightButton:
2873 {
2874 if (!line)
2875 break;
2876 KPopupMenu popup;
2877 popup.setCheckable(true);
2878 popup.insertTitle(i18n("Breakpoints/Bookmarks"));
2879 int idToggleBookmark = popup.insertItem(i18n("Toggle bookmark"));
2880 popup.insertSeparator();
2881 int idToggleBreakpoint = popup.insertItem(i18n("Toggle breakpoint"));
2882 int idEditBreakpoint = popup.insertItem(i18n("Edit breakpoint"));
2883 int idEnableBreakpoint = popup.insertItem(i18n("Disable breakpoint"));
2884 popup.insertSeparator();
2885 popup.insertSeparator();
2886 int idLmbSetsBreakpoints = popup.insertItem(i18n("LMB sets breakpoints"));
2887 int idLmbSetsBookmarks = popup.insertItem(i18n("LMB sets bookmarks"));
2888
2889 popup.setItemChecked(idLmbSetsBreakpoints, lmbSetsBreakpoints);
2890 popup.setItemChecked(idLmbSetsBookmarks, !lmbSetsBreakpoints);
2891
2892 if (line->breakpointId() == -1) {
2893 popup.setItemEnabled(idEditBreakpoint, false);
2894 popup.setItemEnabled(idEnableBreakpoint, false);
2895 popup.changeItem(idEnableBreakpoint, i18n("Enable breakpoint"));
2896 }
2897 int res = popup.exec(mapToGlobal(e->pos()));
2898 if (res == idToggleBookmark) {
2899 line->toggleBookmark();
2900 doc->tagLines(cursorOnLine, cursorOnLine);
2901 doc->updateViews();
2902 } else if (res == idToggleBreakpoint)
2903 emit myView->toggledBreakpoint(cursorOnLine);
2904 else if (res == idEditBreakpoint)
2905 emit myView->editedBreakpoint(cursorOnLine);
2906 else if (res == idEnableBreakpoint)
2907 emit myView->toggledBreakpointEnabled(cursorOnLine+1);
2908 else if (res == idLmbSetsBreakpoints || res == idLmbSetsBookmarks)
2909 lmbSetsBreakpoints = !lmbSetsBreakpoints;
2910 break;
2911 }
2912 case MidButton:
2913 line->toggleBookmark();
2914 doc->tagLines(cursorOnLine, cursorOnLine);
2915 doc->updateViews();
2916 break; */
2917 default:
2918 break;
2919 }
2920}
2921
2922
2923
diff --git a/noncore/apps/tinykate/libkate/view/kateview.h b/noncore/apps/tinykate/libkate/view/kateview.h
new file mode 100644
index 0000000..2e78a3a
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/view/kateview.h
@@ -0,0 +1,865 @@
1/***************************************************************************
2 kateview.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 * 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
20/*
21 Copyright (C) 1998, 1999 Jochen Wilhelmy
22 digisnap@cs.tu-berlin.de
23
24 This library is free software; you can redistribute it and/or
25 modify it under the terms of the GNU Library General Public
26 License as published by the Free Software Foundation; either
27 version 2 of the License, or (at your option) any later version.
28
29 This library is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 Library General Public License for more details.
33
34 You should have received a copy of the GNU Library General Public License
35 along with this library; see the file COPYING.LIB. If not, write to
36 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
37 Boston, MA 02111-1307, USA.
38*/
39
40#ifndef kate_view_h
41#define kate_view_h
42
43#include "../interfaces/view.h"
44#include "../interfaces/document.h"
45
46#include <qlist.h>
47#include <qstring.h>
48#include <qdialog.h>
49
50
51class KateDocument;
52class Highlight;
53
54/*
55//dialog results
56const int srYes = QDialog::Accepted;
57const int srNo = 10;
58const int srAll = 11;
59const int srCancel = QDialog::Rejected;
60*/
61// --- config flags ---
62// indent
63
64enum Select_flags {
65 selectFlag = 0x100000,
66 multiSelectFlag = 0x200000
67};
68//state commands
69enum State_commands {
70 cmToggleInsert = 1,
71 cmToggleVertical = 2
72};
73
74class KateViewInternal;
75class KateView;
76
77struct PointStruc {
78 int x;
79 int y;
80};
81
82struct VConfig {
83 KateView *view;
84 PointStruc cursor;
85 int cXPos;
86 int flags;
87};
88
89struct SConfig {
90 PointStruc cursor;
91 PointStruc startCursor;
92 int flags;
93
94 // Set the pattern to be used for searching.
95 void setPattern(QString &newPattern);
96
97 // Search the given string.
98 int search(QString &text, int index);
99
100 // The length of the last match found using pattern or regExp.
101 int matchedLength;
102
103private:
104 QString m_pattern;
105
106 // The regular expression corresponding to pattern. Only guaranteed valid if
107 // flags has sfRegularExpression set.
108 QRegExp m_regExp;
109};
110
111struct LineRange {
112 int start;
113 int end;
114};
115
116struct BracketMark {
117 PointStruc cursor;
118 int sXPos;
119 int eXPos;
120};
121
122
123class KateIconBorder : public QWidget
124{
125public:
126 KateIconBorder(KateView *view, class KateViewInternal *internalView);
127 ~KateIconBorder();
128
129 void paintLine(int i);
130
131protected:
132 void paintEvent(QPaintEvent* e);
133 void mousePressEvent(QMouseEvent* e);
134
135private:
136
137 KateView *myView;
138 class KateViewInternal *myInternalView;
139 bool lmbSetsBreakpoints;
140};
141
142class KateViewInternal : public QWidget {
143 Q_OBJECT
144 friend class KateDocument;
145 friend class KateView;
146 friend class KateIconBorder;
147
148 private:
149 long waitForPreHighlight;
150 int iconBorderWidth;
151 int iconBorderHeight;
152
153 protected slots:
154 void slotPreHighlightUpdate(long line);
155
156 public:
157 KateViewInternal(KateView *view, KateDocument *doc);
158 ~KateViewInternal();
159
160 virtual void doCursorCommand(VConfig &, int cmdNum);
161 virtual void doEditCommand(VConfig &, int cmdNum);
162
163 void cursorLeft(VConfig &);
164 void cursorRight(VConfig &);
165 void wordLeft(VConfig &);
166 void wordRight(VConfig &);
167 void home(VConfig &);
168 void end(VConfig &);
169 void cursorUp(VConfig &);
170 void cursorDown(VConfig &);
171 void scrollUp(VConfig &);
172 void scrollDown(VConfig &);
173 void topOfView(VConfig &);
174 void bottomOfView(VConfig &);
175 void pageUp(VConfig &);
176 void pageDown(VConfig &);
177 void cursorPageUp(VConfig &);
178 void cursorPageDown(VConfig &);
179 void top(VConfig &);
180 void bottom(VConfig &);
181 void top_home(VConfig &c);
182 void bottom_end(VConfig &c);
183
184 protected slots:
185 void changeXPos(int);
186 void changeYPos(int);
187
188 protected:
189 void getVConfig(VConfig &);
190 void changeState(VConfig &);
191 void insLine(int line);
192 void delLine(int line);
193 void updateCursor();
194 void updateCursor(PointStruc &newCursor);
195 void updateCursor(PointStruc &newCursor, int flags);
196 void clearDirtyCache(int height);
197 void tagLines(int start, int end, int x1, int x2);
198 void tagAll();
199 void setPos(int x, int y);
200 void center();
201
202 void updateView(int flags);
203
204 void paintTextLines(int xPos, int yPos);
205 void paintCursor();
206 void paintBracketMark();
207
208 void placeCursor(int x, int y, int flags = 0);
209 bool isTargetSelected(int x, int y);
210
211// void doDrag();
212
213 virtual void focusInEvent(QFocusEvent *);
214 virtual void focusOutEvent(QFocusEvent *);
215 virtual void keyPressEvent(QKeyEvent *e);
216 virtual void mousePressEvent(QMouseEvent *);
217 virtual void mouseDoubleClickEvent(QMouseEvent *);
218 virtual void mouseReleaseEvent(QMouseEvent *);
219 virtual void mouseMoveEvent(QMouseEvent *);
220 virtual void wheelEvent( QWheelEvent *e );
221 virtual void paintEvent(QPaintEvent *);
222 virtual void resizeEvent(QResizeEvent *);
223 virtual void timerEvent(QTimerEvent *);
224
225
226 KateView *myView;
227 KateDocument *myDoc;
228 QScrollBar *xScroll;
229 QScrollBar *yScroll;
230 KateIconBorder *leftBorder;
231
232 int xPos;
233 int yPos;
234
235 int mouseX;
236 int mouseY;
237 int scrollX;
238 int scrollY;
239 int scrollTimer;
240
241 PointStruc cursor;
242 bool cursorOn;
243 int cursorTimer;
244 int cXPos;
245 int cOldXPos;
246
247 int startLine;
248 int endLine;
249
250 bool exposeCursor;
251 int updateState;
252 int numLines;
253 LineRange *lineRanges;
254 int newXPos;
255 int newYPos;
256
257 QPixmap *drawBuffer;
258
259 BracketMark bm;
260
261};
262
263/**
264 The KateView text editor widget. It has many options, document/view
265 architecture and syntax highlight.
266 @author Jochen Wilhelmy
267*/
268
269class KateView : public Kate::View
270{
271 Q_OBJECT
272 friend class KateViewInternal;
273 friend class KateDocument;
274 friend class KateIconBorder;
275
276 public:
277 KateView(KateDocument *doc=0L, QWidget *parent = 0L, const char * name = 0);
278 ~KateView();
279
280 virtual void setCursorPosition( int line, int col, bool mark = false );
281 virtual void getCursorPosition( int *line, int *col );
282
283 virtual bool isOverwriteMode() const;
284 virtual void setOverwriteMode( bool b );
285
286//status and config functions
287 /**
288 Returns the current line number, that is the line the cursor is on.
289 For the first line it returns 0. Signal newCurPos() is emitted on
290 cursor position changes.
291 */
292 int currentLine();
293 /**
294 Returns the current column number. It handles tab's correctly.
295 For the first column it returns 0.
296 */
297 int currentColumn();
298 /**
299 Returns the number of the character, that the cursor is on (cursor x)
300 */
301 int currentCharNum();
302 /**
303 Sets the current cursor position
304 */
305 void setCursorPositionInternal(int line, int col);
306 /**
307 Returns the config flags. See the cfXXX constants in the .h file.
308 */
309 int config();// {return configFlags;}
310 /**
311 Sets the config flags
312 */
313 void setConfig(int);
314
315 int tabWidth();
316 void setTabWidth(int);
317 void setEncoding (QString e);
318 int undoSteps();
319 void setUndoSteps(int);
320
321 // bool isOverwriteMode();
322 /**
323 Returns true if the document is in read only mode.
324 */
325 bool isReadOnly();
326 /**
327 Returns true if the document has been modified.
328 */
329 bool isModified();
330 /**
331 Sets the read-only flag of the document
332 */
333 void setReadOnly(bool);
334 /**
335 Sets the modification status of the document
336 */
337 void setModified(bool m = true);
338 /**
339 Returns true if this editor is the only owner of its document
340 */
341 bool isLastView();
342 /**
343 Returns the document object
344 */
345 KateDocument *doc();
346
347 /*
348 Bit 0 : undo possible, Bit 1 : redo possible.
349 Used to enable/disable undo/redo menu items and toolbar buttons
350 */
351 int undoState();
352 /**
353 Returns the type of the next undo group.
354 */
355 int nextUndoType();
356 /**
357 Returns the type of the next redo group.
358 */
359 int nextRedoType();
360 /**
361 Returns a list of all available undo types, in undo order.
362 */
363 void undoTypeList(QValueList<int> &lst);
364 /**
365 Returns a list of all available redo types, in redo order.
366 */
367 void redoTypeList(QValueList<int> &lst);
368 /**
369 Returns a short text description of the given undo type,
370 which is obtained with nextUndoType(), nextRedoType(), undoTypeList(), and redoTypeList(),
371 suitable for display in a menu entry. It is not translated;
372 use i18n() before displaying this string.
373 */
374 const char * undoTypeName(int undoType);
375
376 QColor* getColors();
377 void applyColors();
378
379
380 public slots:
381 void slotUpdate();
382 void slotFileStatusChanged();
383 void slotNewUndo();
384 void slotHighlightChanged();
385
386 public slots:
387 /**
388 Toggles Insert mode
389 */
390 void toggleInsert();
391 /**
392 Toggles "Vertical Selections" option
393 */
394 void toggleVertical();
395 signals:
396 /**
397 The cursor position has changed. Get the values with currentLine()
398 and currentColumn()
399 */
400 void newCurPos();
401 /**
402 Modified flag or config flags have changed
403 */
404 void newStatus();
405 /**
406 The undo/redo enable status has changed
407 */
408 void newUndo();
409 /**
410 The marked text state has changed. This can be used to enable/disable
411 cut and copy
412 */
413 void newMarkStatus();
414
415 // emitted when saving a remote URL with KIO::NetAccess. In that case we have to disable the UI.
416 void enableUI( bool enable );
417
418 protected:
419 virtual void keyPressEvent( QKeyEvent *ev );
420
421 int configFlags;
422
423 /*
424 * Check if the given URL already exists. Currently used by both save() and saveAs()
425 *
426 * Asks the user for permission and returns the message box result and defaults to
427 * KMessageBox::Yes in case of doubt
428 */
429
430//text access
431 public:
432 /**
433 Gets the number of text lines;
434 */
435 int numLines();
436 /**
437 Gets the complete document content as string
438 */
439 QString text();
440 /**
441 Gets the text line where the cursor is on
442 */
443 QString currentTextLine();
444 /**
445 Gets a text line
446 */
447 QString textLine(int num);
448 /**
449 Gets the word where the cursor is on
450 */
451 QString currentWord();
452 /**
453 Gets the word at position x, y. Can be used to find
454 the word under the mouse cursor
455 */
456 QString word(int x, int y);
457 /**
458 Discard old text without warning and set new text
459 */
460 void setText(const QString &);
461 /**
462 Insert text at the current cursor position. If length is a positive
463 number, it restricts the number of inserted characters
464 */
465 virtual void insertText(const QString &, bool mark = false);
466 /**
467 Queries if there is marked text
468 */
469 bool hasMarkedText();
470 /**
471 Gets the marked text as string
472 */
473 QString markedText();
474
475 public:
476 enum fileResult { OK, CANCEL, RETRY, ERROR };
477
478 /**
479 Returns true if the current document can be
480 discarded. If the document is modified, the user is asked if he wants
481 to save it. On "cancel" the function returns false.
482 */
483 bool canDiscard();
484
485 public slots:
486 /**
487 Flushes the document of the text widget. The user is given
488 a chance to save the current document if the current document has
489 been modified.
490 */
491 void flush ();
492 /**
493 Saves the file if necessary under the current file name. If the current file
494 name is Untitled, as it is after a call to newFile(), this routing will
495 call saveAs().
496 */
497 fileResult save();
498 /**
499 Allows the user to save the file under a new name. This starts the
500 automatic highlight selection.
501 */
502 fileResult saveAs();
503 /**
504 Moves the marked text into the clipboard
505 */
506 void cut() {doEditCommand(KateView::cmCut);}
507 /**
508 Copies the marked text into the clipboard
509 */
510 void copy() {doEditCommand(KateView::cmCopy);}
511 /**
512 Inserts text from the clipboard at the actual cursor position
513 */
514 void paste() {doEditCommand(KateView::cmPaste);}
515 /**
516 Undoes the last operation. The number of undo steps is configurable
517 */
518 void undo() {doEditCommand(KateView::cmUndo);}
519 /**
520 Repeats an operation which has been undone before.
521 */
522 void redo() {doEditCommand(KateView::cmRedo);}
523 /**
524 Undoes <count> operations.
525 Called by slot undo().
526 */
527 void undoMultiple(int count);
528 /**
529 Repeats <count> operation which have been undone before.
530 Called by slot redo().
531 */
532 void redoMultiple(int count);
533 /**
534 Displays the undo history dialog
535 */
536 void undoHistory();
537 /**
538 Moves the current line or the selection one position to the right
539 */
540 void indent() {doEditCommand(KateView::cmIndent);};
541 /**
542 Moves the current line or the selection one position to the left
543 */
544 void unIndent() {doEditCommand(KateView::cmUnindent);};
545 /**
546 Optimizes the selected indentation, replacing tabs and spaces as needed
547 */
548 void cleanIndent() {doEditCommand(KateView::cmCleanIndent);};
549 /**
550 Selects all text
551 */
552 void selectAll() {doEditCommand(KateView::cmSelectAll);}
553 /**
554 Deselects all text
555 */
556 void deselectAll() {doEditCommand(KateView::cmDeselectAll);}
557 /**
558 Inverts the current selection
559 */
560 void invertSelection() {doEditCommand(KateView::cmInvertSelection);}
561 /**
562 comments out current line
563 */
564 void comment() {doEditCommand(KateView::cmComment);};
565 /**
566 removes comment signs in the current line
567 */
568 void uncomment() {doEditCommand(KateView::cmUncomment);};
569
570 void keyReturn() {doEditCommand(KateView::cmReturn);};
571 void keyDelete() {doEditCommand(KateView::cmDelete);};
572 void backspace() {doEditCommand(KateView::cmBackspace);};
573 void killLine() {doEditCommand(KateView::cmKillLine);};
574
575// cursor commands...
576
577 void cursorLeft() {doCursorCommand(KateView::cmLeft);};
578 void shiftCursorLeft() {doCursorCommand(KateView::cmLeft | selectFlag);};
579 void cursorRight() {doCursorCommand(KateView::cmRight);}
580 void shiftCursorRight() {doCursorCommand(KateView::cmRight | selectFlag);}
581 void wordLeft() {doCursorCommand(KateView::cmWordLeft);};
582 void shiftWordLeft() {doCursorCommand(KateView::cmWordLeft | selectFlag);};
583 void wordRight() {doCursorCommand(KateView::cmWordRight);};
584 void shiftWordRight() {doCursorCommand(KateView::cmWordRight | selectFlag);};
585 void home() {doCursorCommand(KateView::cmHome);};
586 void shiftHome() {doCursorCommand(KateView::cmHome | selectFlag);};
587 void end() {doCursorCommand(KateView::cmEnd);};
588 void shiftEnd() {doCursorCommand(KateView::cmEnd | selectFlag);};
589 void up() {doCursorCommand(KateView::cmUp);};
590 void shiftUp() {doCursorCommand(KateView::cmUp | selectFlag);};
591 void down() {doCursorCommand(KateView::cmDown);};
592 void shiftDown() {doCursorCommand(KateView::cmDown | selectFlag);};
593 void scrollUp() {doCursorCommand(KateView::cmScrollUp);};
594 void scrollDown() {doCursorCommand(KateView::cmScrollDown);};
595 void topOfView() {doCursorCommand(KateView::cmTopOfView);};
596 void bottomOfView() {doCursorCommand(KateView::cmBottomOfView);};
597 void pageUp() {doCursorCommand(KateView::cmPageUp);};
598 void shiftPageUp() {doCursorCommand(KateView::cmPageUp | selectFlag);};
599 void pageDown() {doCursorCommand(KateView::cmPageDown);};
600 void shiftPageDown() {doCursorCommand(KateView::cmPageDown | selectFlag);};
601 void top() {doCursorCommand(KateView::cmTop);};
602 void shiftTop() {doCursorCommand(KateView::cmTop | selectFlag);};
603 void bottom() {doCursorCommand(KateView::cmBottom);};
604 void shiftBottom() {doCursorCommand(KateView::cmBottom | selectFlag);};
605
606//search/replace functions
607 public slots:
608 /**
609 Presents a search dialog to the user
610 */
611 void find();
612 /**
613 Presents a replace dialog to the user
614 */
615 void replace();
616
617 /**
618 Presents a "Goto Line" dialog to the user
619 */
620 void gotoLine();
621 protected:
622 void initSearch(SConfig &, int flags);
623 void continueSearch(SConfig &);
624 void findAgain(SConfig &);
625 void replaceAgain();
626 void doReplaceAction(int result, bool found = false);
627 void exposeFound(PointStruc &cursor, int slen, int flags, bool replace);
628 void deleteReplacePrompt();
629 bool askReplaceEnd();
630 protected slots:
631 void replaceSlot();
632 protected:
633 int searchFlags;
634 int replaces;
635 SConfig s;
636 QDialog *replacePrompt;
637
638//right mouse button popup menu & bookmark menu
639 public:
640 /**
641 Install a Popup Menu. The Popup Menu will be activated on
642 a right mouse button press event.
643 */
644 void installPopup(QPopupMenu *rmb_Menu);
645
646 protected:
647 QPopupMenu *rmbMenu;
648
649 signals:
650 void bookAddChanged(bool enabled);
651 void bookClearChanged(bool enabled);
652
653//config file / session management functions
654 public:
655 /**
656 Reads config entries
657 */
658 void readConfig();
659 /**
660 Writes config entries i
661 */
662 void writeConfig();
663 /**
664 Reads session config out of the KConfig object. This also includes
665 the actual cursor position and the bookmarks.
666 */
667 void readSessionConfig(KConfig *);
668 /**
669 Writes session config into the KConfig object
670 */
671 void writeSessionConfig(KConfig *);
672
673
674 public:
675 void setDontChangeHlOnSave();
676
677
678 // syntax highlight
679 public slots:
680 /**
681 Presents the setup dialog to the user
682 */
683 void configDialog ();
684 /**
685 Gets the highlight number
686 */
687 int getHl();
688 /**
689 Sets the highlight number n
690 */
691 void setHl(int n);
692 /**
693 Get the end of line mode (Unix, Macintosh or Dos)
694 */
695 int getEol();
696 /**
697 Set the end of line mode (Unix, Macintosh or Dos)
698 */
699 void setEol(int);
700
701//internal
702 protected:
703 virtual void paintEvent(QPaintEvent *);
704 virtual void resizeEvent(QResizeEvent *);
705
706 void doCursorCommand(int cmdNum);
707 void doEditCommand(int cmdNum);
708
709 KateViewInternal *myViewInternal;
710 KateDocument *myDoc;
711
712
713 // some kwriteview stuff
714 protected:
715 void insLine(int line) { myViewInternal->insLine(line); };
716 void delLine(int line) { myViewInternal->delLine(line); };
717 void updateCursor() { myViewInternal->updateCursor(); };
718 void updateCursor(PointStruc &newCursor) { myViewInternal->updateCursor(newCursor); };
719 void updateCursor(PointStruc &newCursor, int flags) { myViewInternal->updateCursor(newCursor, flags); };
720
721 void clearDirtyCache(int height) { myViewInternal->clearDirtyCache(height); };
722 void tagLines(int start, int end, int x1, int x2) { myViewInternal->tagLines(start, end, x1, x2); };
723 void tagAll() { myViewInternal->tagAll(); };
724 void setPos(int x, int y) { myViewInternal->setPos(x, y); };
725 void center() { myViewInternal->center(); };
726
727 void updateView(int flags) { myViewInternal->updateView(flags); };
728
729
730
731 public:
732 enum Config_flags {
733 cfAutoIndent= 0x1,
734 cfBackspaceIndents= 0x2,
735 cfWordWrap= 0x4,
736 cfReplaceTabs= 0x8,
737 cfRemoveSpaces = 0x10,
738 cfWrapCursor= 0x20,
739 cfAutoBrackets= 0x40,
740 cfPersistent= 0x80,
741 cfKeepSelection= 0x100,
742 cfVerticalSelect= 0x200,
743 cfDelOnInput= 0x400,
744 cfXorSelect= 0x800,
745 cfOvr= 0x1000,
746 cfMark= 0x2000,
747 cfGroupUndo= 0x4000,
748 cfKeepIndentProfile= 0x8000,
749 cfKeepExtraSpaces= 0x10000,
750 cfMouseAutoCopy= 0x20000,
751 cfSingleSelection= 0x40000,
752 cfTabIndents= 0x80000,
753 cfPageUDMovesCursor= 0x100000,
754 cfShowTabs= 0x200000,
755 cfSpaceIndent= 0x400000,
756 cfSmartHome = 0x800000};
757
758 enum Dialog_results {
759 srYes=QDialog::Accepted,
760 srNo=10,
761 srAll,
762 srCancel=QDialog::Rejected};
763
764//search flags
765 enum Search_flags {
766 sfCaseSensitive=1,
767 sfWholeWords=2,
768 sfFromBeginning=4,
769 sfBackward=8,
770 sfSelected=16,
771 sfPrompt=32,
772 sfReplace=64,
773 sfAgain=128,
774 sfWrapped=256,
775 sfFinished=512,
776 sfRegularExpression=1024};
777
778//update flags
779 enum Update_flags {
780 ufDocGeometry=1,
781 ufUpdateOnScroll=2,
782 ufPos=4};
783
784//load flags
785 enum Load_flags {
786 lfInsert=1,
787 lfNewFile=2,
788 lfNoAutoHl=4};
789
790//cursor movement commands
791 enum Cursor_commands
792 { cmLeft,cmRight,cmWordLeft,cmWordRight,
793 cmHome,cmEnd,cmUp,cmDown,
794 cmScrollUp,cmScrollDown,cmTopOfView,cmBottomOfView,
795 cmPageUp,cmPageDown,cmCursorPageUp,cmCursorPageDown,
796 cmTop,cmBottom};
797//edit commands
798 enum Edit_commands {
799 cmReturn=1,cmDelete,cmBackspace,cmKillLine,cmUndo,
800 cmRedo,cmCut,cmCopy,cmPaste,cmIndent,cmUnindent,cmCleanIndent,
801 cmSelectAll,cmDeselectAll,cmInvertSelection,cmComment,
802 cmUncomment};
803//find commands
804 enum Find_commands { cmFind=1,cmReplace,cmFindAgain,cmGotoLine};
805
806 public:
807 void setActive (bool b);
808 bool isActive ();
809
810 private:
811 bool active;
812 bool myIconBorder;
813 QList<Kate::Mark> list;
814
815 public slots:
816 virtual void setFocus ();
817 void findAgain(bool back=false);
818 void findAgain () { findAgain(false); };
819 void findPrev () { findAgain(true); };
820
821 protected:
822 bool eventFilter(QObject* o, QEvent* e);
823
824 signals:
825 void gotFocus (KateView *);
826
827 public slots:
828 void slotEditCommand ();
829 void setIconBorder (bool enable);
830 void toggleIconBorder ();
831 void gotoMark (Kate::Mark *mark);
832 void toggleBookmark ();
833 void clearBookmarks ();
834
835 public:
836 bool iconBorder() { return myIconBorder; } ;
837
838 private slots:
839 void bookmarkMenuAboutToShow();
840 void gotoBookmark (int n);
841
842 public:
843 Kate::Document *getDoc ()
844 { return (Kate::Document*) myDoc; };
845
846 public slots:
847 int getHlCount ();
848 QString getHlName (int);
849 QString getHlSection (int);
850
851 void slotIncFontSizes ();
852 void slotDecFontSizes ();
853
854 protected:
855 uint myViewID;
856 static uint uniqueID;
857};
858
859#endif
860
861
862
863
864
865
diff --git a/noncore/apps/tinykate/libkate/view/kateviewdialog.cpp b/noncore/apps/tinykate/libkate/view/kateviewdialog.cpp
new file mode 100644
index 0000000..a311042
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/view/kateviewdialog.cpp
@@ -0,0 +1,556 @@
1/***************************************************************************
2 kateviewdialog.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// Dialogs
20
21#include <stdio.h>
22#include <stdlib.h>
23
24#include <qgrid.h>
25#include <qlabel.h>
26#include <qlayout.h>
27#include <qlistbox.h>
28#include <qspinbox.h>
29#include <qcombobox.h>
30#include <qgroupbox.h>
31#include <qlineedit.h>
32#include <qcheckbox.h>
33#include <qcollection.h>
34#include <qpushbutton.h>
35#include <qobjectlist.h>
36#include <qradiobutton.h>
37#include <qwhatsthis.h>
38#include <qstringlist.h>
39#include <klocale.h>
40#include <kcolorbtn.h>
41#include <qcombobox.h>
42#include <kglobal.h>
43#include <qvbox.h>
44#include <qspinbox.h>
45#include <kfontdialog.h>
46
47#include "../document/katedocument.h"
48#include "kateviewdialog.h"
49
50SearchDialog::SearchDialog( QWidget *parent, QStringList &searchFor, QStringList &replaceWith, int flags )
51 : KDialogBase( parent, 0L, true, i18n( "Find Text" ), Ok | Cancel, Ok )
52 , m_replace( 0L )
53{
54 QWidget *page = new QWidget( this );
55 setMainWidget( page );
56
57 QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
58
59 m_search = new QComboBox( true, page );
60 m_search->insertStringList( searchFor );
61 m_search->setMinimumWidth( m_search->sizeHint().width() );
62 m_search->lineEdit()->selectAll();
63 QLabel *label = new QLabel( m_search, i18n( "&Text To Find:" ), page );
64 m_optRegExp = new QCheckBox( i18n( "Regular Expression" ), page );
65 topLayout->addWidget( label );
66 topLayout->addWidget( m_search );
67 topLayout->addWidget( m_optRegExp );
68
69 if( flags & KateView::sfReplace )
70 {
71 // make it a replace dialog
72 setCaption( i18n( "Replace Text" ) );
73 m_replace = new QComboBox( true, page );
74 m_replace->insertStringList( replaceWith );
75 m_replace->setMinimumWidth( m_search->sizeHint().width() );
76 label = new QLabel( m_replace, i18n( "&Replace With:" ), page );
77 //m_optPlaceholders = new QCheckBox( i18n( "&Use Placeholders" ), page );
78 topLayout->addWidget( label );
79 topLayout->addWidget( m_replace );
80 //topLayout->addWidget( m_optPlaceholders );
81 }
82
83 QGroupBox *group = new QGroupBox( i18n( "Options" ), page );
84 topLayout->addWidget( group, 10 );
85
86 QGridLayout *gbox = new QGridLayout( group, 5, 2, spacingHint() );
87 gbox->addRowSpacing( 0, fontMetrics().lineSpacing() );
88 gbox->setRowStretch( 4, 10 );
89
90 m_opt1 = new QCheckBox( i18n( "C&ase Sensitive" ), group );
91 gbox->addWidget( m_opt1, 1, 0 );
92
93 m_opt2 = new QCheckBox(i18n("&Whole Words Only" ), group );
94 gbox->addWidget( m_opt2, 2, 0 );
95
96 m_opt3 = new QCheckBox(i18n("&From Beginning" ), group );
97 gbox->addWidget( m_opt3, 3, 0 );
98
99 m_opt4 = new QCheckBox(i18n("Find &Backwards" ), group );
100 gbox->addWidget( m_opt4, 1, 1 );
101
102 m_opt5 = new QCheckBox(i18n("&Selected Text" ), group );
103 gbox->addWidget( m_opt5, 2, 1 );
104
105 m_opt1->setChecked( flags & KateView::sfCaseSensitive );
106 m_opt2->setChecked( flags & KateView::sfWholeWords );
107 m_opt3->setChecked( flags & KateView::sfFromBeginning );
108 m_optRegExp->setChecked( flags & KateView::sfRegularExpression );
109 m_opt4->setChecked( flags & KateView::sfBackward );
110 m_opt5->setChecked( flags & KateView::sfSelected );
111
112 if( m_replace )
113 {
114 m_opt6 = new QCheckBox( i18n( "&Prompt On Replace" ), group );
115 m_opt6->setChecked( flags & KateView::sfPrompt );
116 gbox->addWidget( m_opt6, 3, 1 );
117 }
118
119 m_search->setFocus();
120}
121
122QString SearchDialog::getSearchFor()
123{
124 return m_search->currentText();
125}
126
127QString SearchDialog::getReplaceWith()
128{
129 return m_replace->currentText();
130}
131
132int SearchDialog::getFlags()
133{
134 int flags = 0;
135
136 if( m_opt1->isChecked() ) flags |= KateView::sfCaseSensitive;
137 if( m_opt2->isChecked() ) flags |= KateView::sfWholeWords;
138 if( m_opt3->isChecked() ) flags |= KateView::sfFromBeginning;
139 if( m_opt4->isChecked() ) flags |= KateView::sfBackward;
140 if( m_opt5->isChecked() ) flags |= KateView::sfSelected;
141 if( m_optRegExp->isChecked() ) flags |= KateView::sfRegularExpression;
142 if( m_replace )
143 {
144 if( m_opt6->isChecked() )
145 flags |= KateView::sfPrompt;
146
147 flags |= KateView::sfReplace;
148 }
149
150 return flags;
151}
152
153void SearchDialog::slotOk()
154{
155 if ( !m_search->currentText().isEmpty() )
156 {
157 if ( !m_optRegExp->isChecked() )
158 {
159 accept();
160 }
161 else
162 {
163 // Check for a valid regular expression.
164
165 QRegExp regExp( m_search->currentText() );
166
167 if ( regExp.isValid() )
168 accept();
169 }
170 }
171}
172
173void SearchDialog::setSearchText( const QString &searchstr )
174 {
175 m_search->insertItem( searchstr, 0 );
176 m_search->setCurrentItem( 0 );
177 m_search->lineEdit()->selectAll();
178 }
179
180// this dialog is not modal
181ReplacePrompt::ReplacePrompt( QWidget *parent )
182 : KDialogBase(parent, 0L, false, i18n( "Replace Text" ),
183 User3 | User2 | User1 | Close, User3, true,
184 i18n("&All"), i18n("&No"), i18n("&Yes")) {
185
186 QWidget *page = new QWidget(this);
187 setMainWidget(page);
188
189 QBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
190 QLabel *label = new QLabel(i18n("Replace this occurence?"),page);
191 topLayout->addWidget(label );
192}
193
194void ReplacePrompt::slotUser1( void ) { // All
195 done(KateView::srAll);
196}
197
198void ReplacePrompt::slotUser2( void ) { // No
199 done(KateView::srNo);
200}
201
202void ReplacePrompt::slotUser3( void ) { // Yes
203 accept();
204}
205
206void ReplacePrompt::done(int r) {
207 setResult(r);
208 emit clicked();
209}
210
211void ReplacePrompt::closeEvent(QCloseEvent *) {
212 reject();
213}
214
215GotoLineDialog::GotoLineDialog(QWidget *parent, int line, int max)
216 : KDialogBase(parent, 0L, true, i18n("Goto Line"), Ok | Cancel, Ok) {
217
218 QWidget *page = new QWidget(this);
219 setMainWidget(page);
220
221 QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
222 e1 = new QSpinBox(page);
223 e1->setMinValue(1);
224 e1->setMaxValue(max);
225 e1->setValue((int)line);
226
227 QLabel *label = new QLabel( e1,i18n("&Goto Line:"), page );
228 topLayout->addWidget(label);
229 topLayout->addWidget(e1);
230 topLayout->addSpacing(spacingHint()); // A little bit extra space
231 topLayout->addStretch(10);
232 e1->setFocus();
233}
234
235int GotoLineDialog::getLine() {
236 return e1->value();
237}
238
239const int IndentConfigTab::flags[] = {KateView::cfAutoIndent, KateView::cfSpaceIndent,
240 KateView::cfBackspaceIndents,KateView::cfTabIndents, KateView::cfKeepIndentProfile, KateView::cfKeepExtraSpaces};
241
242IndentConfigTab::IndentConfigTab(QWidget *parent, KateView *view)
243 : QWidget(parent, 0L)
244{
245 QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );
246 int configFlags = view->config();
247
248 opt[0] = new QCheckBox(i18n("&Auto Indent"), this);
249 layout->addWidget(opt[0], 0, AlignLeft);
250 opt[0]->setChecked(configFlags & flags[0]);
251
252 opt[1] = new QCheckBox(i18n("Indent With &Spaces"), this);
253 layout->addWidget(opt[1], 0, AlignLeft);
254 opt[1]->setChecked(configFlags & flags[1]);
255
256 opt[2] = new QCheckBox(i18n("&Backspace Key Indents"), this);
257 layout->addWidget(opt[2], 0, AlignLeft);
258 opt[2]->setChecked(configFlags & flags[2]);
259
260 opt[3] = new QCheckBox(i18n("&Tab Key Indents"), this);
261 layout->addWidget(opt[3], 0, AlignLeft);
262 opt[3]->setChecked(configFlags & flags[3]);
263
264 opt[4] = new QCheckBox(i18n("Keep Indent &Profile"), this);
265 layout->addWidget(opt[4], 0, AlignLeft);
266// opt[4]->setChecked(configFlags & flags[4]);
267 opt[4]->setChecked(true);
268 opt[4]->hide();
269
270 opt[5] = new QCheckBox(i18n("&Keep Extra Spaces"), this);
271 layout->addWidget(opt[5], 0, AlignLeft);
272 opt[5]->setChecked(configFlags & flags[5]);
273
274 layout->addStretch();
275
276 // What is this? help
277 QWhatsThis::add(opt[0], i18n("When <b>Auto indent</b> is on, KateView will indent new lines to equal the indent on the previous line.<p>If the previous line is blank, the nearest line above with text is used"));
278 QWhatsThis::add(opt[1], i18n("Check this if you want to indent with spaces rather than tabs.<br>A Tab will be converted to <u>Tab-width</u> as set in the <b>edit</b> options"));
279 QWhatsThis::add(opt[2], i18n("This allows the <b>backspace</b> key to be used to indent."));
280 QWhatsThis::add(opt[3], i18n("This allows the <b>tab</b> key to be used to indent."));
281 QWhatsThis::add(opt[4], i18n("This retains current indentation settings for future documents."));
282 QWhatsThis::add(opt[5], i18n("Indentations of more than the selected number of spaces will not be shortened."));
283}
284
285void IndentConfigTab::getData(KateView *view) {
286 int configFlags, z;
287
288 configFlags = view->config();
289 for (z = 0; z < numFlags; z++) {
290 configFlags &= ~flags[z];
291 if (opt[z]->isChecked()) configFlags |= flags[z];
292 }
293 view->setConfig(configFlags);
294}
295
296const int SelectConfigTab::flags[] = {KateView::cfPersistent, KateView::cfDelOnInput,
297 KateView::cfMouseAutoCopy, KateView::cfSingleSelection, KateView::cfVerticalSelect, KateView::cfXorSelect};
298
299SelectConfigTab::SelectConfigTab(QWidget *parent, KateView *view)
300 : QWidget(parent, 0L)
301{
302 QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );
303 int configFlags = view->config();
304
305 opt[0] = new QCheckBox(i18n("&Persistent Selections"), this);
306 layout->addWidget(opt[0], 0, AlignLeft);
307 opt[0]->setChecked(configFlags & flags[0]);
308
309 opt[1] = new QCheckBox(i18n("&Overwrite Selections"), this);
310 layout->addWidget(opt[1], 0, AlignLeft);
311 opt[1]->setChecked(configFlags & flags[1]);
312
313 opt[2] = new QCheckBox(i18n("Mouse &Autocopy"), this);
314 layout->addWidget(opt[2], 0, AlignLeft);
315 opt[2]->setChecked(configFlags & flags[2]);
316
317 opt[3] = new QCheckBox(i18n("&X11-like Single Selection"), this);
318 layout->addWidget(opt[3], 0, AlignLeft);
319 opt[3]->setChecked(configFlags & flags[3]);
320
321 opt[4] = new QCheckBox(i18n("&Vertical Selections"), this);
322 layout->addWidget(opt[4], 0, AlignLeft);
323 opt[4]->setChecked(configFlags & flags[4]);
324
325 opt[5] = new QCheckBox(i18n("&Toggle Old"), this);
326 layout->addWidget(opt[5], 0, AlignLeft);
327 opt[5]->setChecked(configFlags & flags[5]);
328
329 layout->addStretch();
330
331 // What is this? help
332 QWhatsThis::add(opt[0], i18n("Enabling this prevents key input or cursor movement by way of the arrow keys from causing the elimination of text selection.<p><b>Note:</b> If the Overwrite Selections option is activated then any typed character input or paste operation will replace the selected text."));
333 QWhatsThis::add(opt[1], i18n("When this is on, any keyed character input or paste operation will replace the selected text."));
334 QWhatsThis::add(opt[2], i18n("When this is on, any text selected with the mouse will be automatically copied to the clipboard."));
335 QWhatsThis::add(opt[3], i18n("Not implemented yet."));
336 QWhatsThis::add(opt[4], i18n("Enabling this allows you to make vertical selections."));
337 QWhatsThis::add(opt[5], i18n("Not yet implemented."));
338}
339
340void SelectConfigTab::getData(KateView *view) {
341 int configFlags, z;
342
343 configFlags = view->config();
344 for (z = 0; z < numFlags; z++) {
345 configFlags &= ~flags[z]; // clear flag
346 if (opt[z]->isChecked()) configFlags |= flags[z]; // set flag if checked
347 }
348 view->setConfig(configFlags);
349}
350
351const int EditConfigTab::flags[] = {KateView::cfWordWrap, KateView::cfReplaceTabs, KateView::cfRemoveSpaces,
352 KateView::cfAutoBrackets, KateView::cfGroupUndo, KateView::cfShowTabs, KateView::cfSmartHome,
353 KateView::cfPageUDMovesCursor, KateView::cfWrapCursor};
354
355EditConfigTab::EditConfigTab(QWidget *parent, KateView *view)
356 : QWidget(parent, 0L) {
357
358 QHBoxLayout *mainLayout;
359 QVBoxLayout *cbLayout, *leLayout;
360 int configFlags;
361
362 mainLayout = new QHBoxLayout(this, 0, KDialog::spacingHint() );
363
364 // checkboxes
365 cbLayout = new QVBoxLayout( mainLayout );
366 configFlags = view->config();
367
368 opt[0] = new QCheckBox(i18n("&Word wrap"), this);
369 cbLayout->addWidget(opt[0], 0, AlignLeft);
370 opt[0]->setChecked(view->doc()->wordWrap());
371
372 opt[1] = new QCheckBox(i18n("Replace &tabs with spaces"), this);
373 cbLayout->addWidget(opt[1], 0, AlignLeft);
374 opt[1]->setChecked(configFlags & flags[1]);
375
376 opt[2] = new QCheckBox(i18n("&Remove trailing spaces"), this);
377 cbLayout->addWidget(opt[2], 0, AlignLeft);
378 opt[2]->setChecked(configFlags & flags[2]);
379
380 opt[3] = new QCheckBox(i18n("&Auto brackets"), this);
381 cbLayout->addWidget(opt[3], 0, AlignLeft);
382 opt[3]->setChecked(configFlags & flags[3]);
383
384 opt[4] = new QCheckBox(i18n("Group &undos"), this);
385 cbLayout->addWidget(opt[4], 0, AlignLeft);
386 opt[4]->setChecked(configFlags & flags[4]);
387
388 opt[5] = new QCheckBox(i18n("&Show tabs"), this);
389 cbLayout->addWidget(opt[5], 0, AlignLeft);
390 opt[5]->setChecked(configFlags & flags[5]);
391
392 opt[6] = new QCheckBox(i18n("Smart &home"), this);
393 cbLayout->addWidget(opt[6], 0, AlignLeft);
394 opt[6]->setChecked(configFlags & flags[6]);
395
396 opt[7] = new QCheckBox(i18n("&Page up/down moves cursor"), this);
397 cbLayout->addWidget(opt[7], 0, AlignLeft);
398 opt[7]->setChecked(configFlags & flags[7]);
399
400 opt[8] = new QCheckBox(i18n("Wrap &cursor"), this);
401 cbLayout->addWidget(opt[8], 0, AlignLeft);
402 opt[8]->setChecked(configFlags & flags[8]);
403
404 cbLayout->addStretch();
405
406 // edit lines
407 leLayout = new QVBoxLayout();
408 mainLayout->addLayout(leLayout,10);
409
410 e1 = new QSpinBox(this);
411 e1->setMinValue(20);
412 e1->setMaxValue( 200);
413 e1->setValue((int)(view->doc()->wordWrapAt()));
414#warning fixme e1->setLabel(i18n("Wrap Words At:"));
415
416 e2 = new QSpinBox(this);
417 e2->setMinValue(1);
418 e2->setMaxValue(16);
419 e2->setValue((int)view->tabWidth());
420
421#warning fixme e2->setLabel(i18n("Tab/Indent Width:"));
422
423 e3 = new QSpinBox(this);
424 e3->setMinValue(5);
425 e3->setMaxValue( 30000);
426#warning fixme e3->setLabel(i18n("Undo steps:"));
427 e3->setValue((int)view->undoSteps());
428
429 leLayout->addWidget(e1, 0, AlignLeft);
430 leLayout->addWidget(e2, 0, AlignLeft);
431 leLayout->addWidget(e3, 0, AlignLeft);
432
433
434 QVBox *box = new QVBox (this);
435 leLayout->addWidget (box, 0, AlignLeft);
436
437 new QLabel (i18n("Encoding:"), box);
438
439 encoding = new QComboBox(box);
440#warning fixme
441#if 0
442 encoding->insertStringList (KGlobal::charsets()->availableEncodingNames());
443 encoding->setCurrentItem (KGlobal::charsets()->availableEncodingNames().findIndex(view->doc()->encoding()));
444#endif
445 leLayout->addStretch();
446
447 // What is this? help
448 QWhatsThis::add(opt[0], i18n("Word wrap is a feature that causes the editor to automatically start a new line of text and move (wrap) the cursor to the beginning of that new line. KateView will automatically start a new line of text when the current line reaches the length specified by the Wrap Words At: option.<p><b>NOTE:<b> Word Wrap will not change existing lines or wrap them for easy reading as in some applications."));
449 QWhatsThis::add(e1, i18n("If the Word Wrap option is selected this entry determines the length (in characters) at which the editor will automatically start a new line."));
450 QWhatsThis::add(opt[1], i18n("KateView will replace any tabs with the number of spaces indicated in the Tab Width: entry."));
451 QWhatsThis::add(e2, i18n("If the Replace Tabs By Spaces option is selected this entry determines the number of spaces with which the editor will automatically replace tabs."));
452 QWhatsThis::add(opt[2], i18n("KateView will automatically eliminate extra spaces at the ends of lines of text."));
453 QWhatsThis::add(opt[3], i18n("When the user types a left bracket ([,(, or {) KateView automatically enters the right bracket (}, ), or ]) to the right of the cursor."));
454 QWhatsThis::add(opt[4], i18n("Checking this will cause sequences of similar actions to be undone at once."));
455 QWhatsThis::add(opt[5], i18n("The editor will display a symbol to indicate the presence of a tab in the text."));
456 QWhatsThis::add(opt[6], i18n("Not yet implemented."));
457 QWhatsThis::add(opt[7], i18n("If this is selected, the insertion cursor will be moved to the first/last line when pressing the page up/down buttons.<p>If not selected, it will remain at it's relative position in the visible text."));
458 QWhatsThis::add(e3, i18n("Sets the number of undo/redo steps to record. More steps uses more memory."));
459 QWhatsThis::add(opt[8], i18n("When on, moving the insertion cursor using the <b>Left</b> and <b>Right</b> keys will go on to previous/next line at beginning/end of the line, similar to most editors.<p>When off, the insertion cursor cannot be moved left of the line start, but it can be moved off the line end, which can be very handy for programmers."));
460}
461
462void EditConfigTab::getData(KateView *view)
463{
464 int configFlags, z;
465
466 configFlags = view->config();
467 for (z = 1; z < numFlags; z++) {
468 configFlags &= ~flags[z];
469 if (opt[z]->isChecked()) configFlags |= flags[z];
470 }
471 view->setConfig(configFlags);
472
473 view->setEncoding (encoding->currentText());
474 view->doc()->setWordWrapAt(e1->value());
475 view->doc()->setWordWrap (opt[0]->isChecked());
476 view->setTabWidth(e2->value());
477 view->setUndoSteps(e3->value());
478}
479
480ColorConfig::ColorConfig( QWidget *parent, char *name )
481 : QWidget( parent, name )
482{
483 QGridLayout *glay = new QGridLayout( this, 6, 2, 0, KDialog::spacingHint());
484 glay->setColStretch(1,1);
485 glay->setRowStretch(5,1);
486
487 QLabel *label;
488
489 label = new QLabel( i18n("Background:"), this);
490 label->setAlignment( AlignRight|AlignVCenter );
491 m_back = new KColorButton( this );
492 glay->addWidget( label, 0, 0 );
493 glay->addWidget( m_back, 0, 1 );
494
495 label = new QLabel( i18n("Selected:"), this);
496 label->setAlignment( AlignRight|AlignVCenter );
497 m_selected = new KColorButton( this );
498 glay->addWidget( label, 2, 0 );
499 glay->addWidget( m_selected, 2, 1 );
500
501 // QWhatsThis help
502 QWhatsThis::add(m_back, i18n("Sets the background color of the editing area"));
503 QWhatsThis::add(m_selected, i18n("Sets the background color of the selection. To set the text color for selected text, use the &quot;<b>Configure Highlighting</b>&quot; dialog."));
504}
505
506
507ColorConfig::~ColorConfig()
508{
509}
510
511void ColorConfig::setColors(QColor *colors)
512{
513 m_back->setColor( colors[0] );
514 m_selected->setColor( colors[1] );
515}
516
517void ColorConfig::getColors(QColor *colors)
518{
519 colors[0] = m_back->color();
520 colors[1] = m_selected->color();
521}
522
523FontConfig::FontConfig( QWidget *parent, char *name )
524 : QWidget( parent, name )
525{
526 // sizemanagment
527 QGridLayout *grid = new QGridLayout( this, 1, 1 );
528#if 0
529 m_fontchooser = new KFontChooser ( this );
530 m_fontchooser->enableColumn(KFontChooser::StyleList, false);
531 grid->addWidget( m_fontchooser, 0, 0);
532
533 connect (m_fontchooser, SIGNAL (fontSelected( const QFont & )), this, SLOT (slotFontSelected( const QFont & )));
534#endif
535}
536
537FontConfig::~FontConfig()
538{
539}
540
541void FontConfig::setFont ( const QFont &font )
542{
543#if 0
544 m_fontchooser->setFont (font);
545 myFont = font;
546#endif
547}
548
549void FontConfig::slotFontSelected( const QFont &font )
550{
551 myFont = font;
552}
553
554
555
556
diff --git a/noncore/apps/tinykate/libkate/view/kateviewdialog.h b/noncore/apps/tinykate/libkate/view/kateviewdialog.h
new file mode 100644
index 0000000..60f30bd
--- a/dev/null
+++ b/noncore/apps/tinykate/libkate/view/kateviewdialog.h
@@ -0,0 +1,194 @@
1/***************************************************************************
2 kateviewdialog.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// Dialogs
20
21#ifndef _KWDIALOG_H_
22#define _KWDIALOG_H_
23
24
25class QCheckBox;
26class QLineEdit;
27class QPushButton;
28class QRadioButton;
29class QSpinBox;
30class KColorButton;
31class QComboBox;
32
33#include <kdialogbase.h>
34#include "kateview.h"
35
36class SearchDialog : public KDialogBase
37{
38 Q_OBJECT
39
40 public:
41 SearchDialog( QWidget *parent, QStringList &searchFor, QStringList &replaceWith, int flags );
42 QString getSearchFor();
43 QString getReplaceWith();
44 int getFlags();
45 void setSearchText( const QString &searchstr );
46
47 protected slots:
48 void slotOk();
49
50 protected:
51 QComboBox *m_search;
52 QComboBox *m_replace;
53 QCheckBox *m_opt1;
54 QCheckBox *m_opt2;
55 QCheckBox *m_opt3;
56 QCheckBox *m_optRegExp;
57 QCheckBox *m_opt4;
58 QCheckBox *m_opt5;
59 QCheckBox *m_opt6;
60};
61
62class ReplacePrompt : public KDialogBase
63{
64 Q_OBJECT
65
66 public:
67
68 ReplacePrompt(QWidget *parent);
69
70 signals:
71
72 void clicked();
73
74 protected slots:
75
76 void slotUser1( void ); // All
77 void slotUser2( void ); // No
78 void slotUser3( void ); // Yes
79 virtual void done(int);
80
81 protected:
82
83 void closeEvent(QCloseEvent *);
84};
85
86class GotoLineDialog : public KDialogBase
87{
88 Q_OBJECT
89
90 public:
91
92 GotoLineDialog(QWidget *parent, int line, int max);
93 int getLine();
94
95 protected:
96
97 QSpinBox *e1;
98 QPushButton *btnOK;
99};
100
101class IndentConfigTab : public QWidget
102{
103 Q_OBJECT
104
105 public:
106
107 IndentConfigTab(QWidget *parent, KateView *);
108 void getData(KateView *);
109
110 protected:
111
112 static const int numFlags = 6;
113 static const int flags[numFlags];
114 QCheckBox *opt[numFlags];
115};
116
117class SelectConfigTab : public QWidget
118{
119 Q_OBJECT
120
121 public:
122
123 SelectConfigTab(QWidget *parent, KateView *);
124 void getData(KateView *);
125
126 protected:
127
128 static const int numFlags = 6;
129 static const int flags[numFlags];
130 QCheckBox *opt[numFlags];
131};
132
133class EditConfigTab : public QWidget
134{
135 Q_OBJECT
136
137 public:
138
139 EditConfigTab(QWidget *parent, KateView *);
140 void getData(KateView *);
141
142 protected:
143
144 static const int numFlags = 9;
145 static const int flags[numFlags];
146 QCheckBox *opt[numFlags];
147 QComboBox *encoding;
148
149
150 QSpinBox *e1;
151 QSpinBox *e2;
152 QSpinBox *e3;
153};
154
155class ColorConfig : public QWidget
156{
157 Q_OBJECT
158
159public:
160
161 ColorConfig( QWidget *parent = 0, char *name = 0 );
162 ~ColorConfig();
163
164 void setColors( QColor * );
165 void getColors( QColor * );
166
167private:
168
169 KColorButton *m_back;
170 KColorButton *m_selected;
171};
172
173class FontConfig : public QWidget
174{
175 Q_OBJECT
176
177public:
178
179 FontConfig( QWidget *parent = 0, char *name = 0 );
180 ~FontConfig();
181
182 void setFont ( const QFont &font );
183 QFont getFont ( ) { return myFont; };
184
185 private:
186// class KFontChooser *m_fontchooser;
187 QFont myFont;
188
189 private slots:
190 void slotFontSelected( const QFont &font );
191};
192
193
194#endif //_KWDIALOG_H_