From e97a6da57804aa14907dec327fbae71bff9b383e Mon Sep 17 00:00:00 2001 From: jowenn Date: Sun, 10 Nov 2002 21:08:01 +0000 Subject: import of tiny kate. (saving not possible yet) --- (limited to 'noncore') diff --git a/noncore/apps/tinykate/install b/noncore/apps/tinykate/install new file mode 100755 index 0000000..912c91b --- a/dev/null +++ b/noncore/apps/tinykate/install @@ -0,0 +1,13 @@ +#!/bin/sh +if [ a$OPIEDIR = a ] +then +echo OPIEDIR must be set +exit +fi +[ -f $OPIEDIR/pics/tinykate_icon.xpm ] || cp tinykate_icon.xpm $OPIEDIR/pics/ +[ -f $OPIEDIR/apps/tinykate.desktop ] || cp tinykate.desktop $OPIEDIR/apps/ +mv $OPIEDIR/Makefile $OPIEDIR/Makefile.orig +sed "s/APPS=/&tinykate \\\\ \\ + /" $OPIEDIR/Makefile.orig >> $OPIEDIR/Makefile +echo You may wish to move the desktop file in to +echo an appropriate subdirectory of the menus. diff --git a/noncore/apps/tinykate/libkate/document/katebuffer.cpp b/noncore/apps/tinykate/libkate/document/katebuffer.cpp new file mode 100644 index 0000000..22a4917 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katebuffer.cpp @@ -0,0 +1,179 @@ +/* + This file is part of KWrite + Copyright (c) 2000 Waldo Bastian + Copyright (c) 2002 Joseph Wenninger + + $Id$ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#include "katebuffer.h" + +// Includes for reading file +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +// + +#include +#include + +/** + * Create an empty buffer. + */ +KWBuffer::KWBuffer() +{ + clear(); +} + +void +KWBuffer::clear() +{ + m_stringListIt=0; + m_stringListCurrent=0; + m_stringList.clear(); + m_lineCount=1; + m_stringListIt = m_stringList.append(new TextLine()); +} + +/** + * Insert a file at line @p line in the buffer. + */ +void +KWBuffer::insertFile(int line, const QString &file, QTextCodec *codec) +{ + if (line) { + qDebug("insert File only supports insertion at line 0 == file opening"); + return; + } + clear(); + QFile iofile(file); + iofile.open(IO_ReadOnly); + QTextStream stream(&iofile); + stream.setCodec(codec); + QString qsl; + int count=0; + for (count=0;((qsl=stream.readLine())!=QString::null); count++) + { + if (count==0) + { + (*m_stringListIt)->append(qsl.unicode(),qsl.length()); + } + else + { + TextLine::Ptr tl=new TextLine(); + tl ->append(qsl.unicode(),qsl.length()); + m_stringListIt=m_stringList.append(tl); + } + } + if (count!=0) + { + m_stringListCurrent=count-1; + m_lineCount=count; + } +} + +void +KWBuffer::loadFilePart() +{ +} + + +void +KWBuffer::insertData(int line, const QByteArray &data, QTextCodec *codec) +{ +} + +void +KWBuffer::slotLoadFile() +{ + loadFilePart(); +// emit linesChanged(m_totalLines); + emit linesChanged(20); +} + +/** + * Return the total number of lines in the buffer. + */ +int +KWBuffer::count() +{ + qDebug("m_stringList.count %d",m_stringList.count()); + return m_lineCount; +// return m_stringList.count(); +// return m_totalLines; +} + + +void KWBuffer::seek(int i) +{ + if (m_stringListCurrent == i) + return; + while(m_stringListCurrent < i) + { + ++m_stringListCurrent; + ++m_stringListIt; + } + while(m_stringListCurrent > i) + { + --m_stringListCurrent; + --m_stringListIt; + } +} + + +TextLine::Ptr +KWBuffer::line(int i) +{ + if (i>=m_stringList.count()) return 0; + seek(i); + return *m_stringListIt; +} + +void +KWBuffer::insertLine(int i, TextLine::Ptr line) +{ + seek(i); + m_stringListIt = m_stringList.insert(m_stringListIt, line); + m_stringListCurrent = i; + m_lineCount++; +} + + +void +KWBuffer::removeLine(int i) +{ + seek(i); + m_stringListIt = m_stringList.remove(m_stringListIt); + m_stringListCurrent = i; + m_lineCount--; +} + +void +KWBuffer::changeLine(int i) +{ +} + diff --git a/noncore/apps/tinykate/libkate/document/katebuffer.h b/noncore/apps/tinykate/libkate/document/katebuffer.h new file mode 100644 index 0000000..9088498 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katebuffer.h @@ -0,0 +1,143 @@ +/* + This file is part of KWrite + Copyright (c) 2000 Waldo Bastian + Copyright (c) 2002 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _KWBUFFER_H_ +#define _KWBUFFER_H_ + +#include +#include +#include +#include +#include + +#include "katetextline.h" + +class QTextCodec; + +/** + * The KWBuffer class maintains a collections of lines. + * It allows to maintain state information in a lazy way. + * It handles swapping out of data using secondary storage. + * + * It is designed to handle large amounts of text-data efficiently + * with respect to CPU and memory usage. + * + * @author Waldo Bastian + */ +class KWBuffer : public QObject +{ + Q_OBJECT +public: + /** + * Create an empty buffer. + */ + KWBuffer(); + + /** + * Insert a file at line @p line in the buffer. + * Using @p codec to decode the file. + */ + void insertFile(int line, const QString &file, QTextCodec *codec); + + /** + * Insert a block of data at line @p line in the buffer. + * Using @p codec to decode the file. + */ + void insertData(int line, const QByteArray &data, QTextCodec *codec); + + /** + * Return the total number of lines in the buffer. + */ + int count(); + + /** + * Return line @p i + */ + TextLine::Ptr line(int i); + + /** + * Insert @p line in front of line @p i + */ + void insertLine(int i, TextLine::Ptr line); + + /** + * Remove line @p i + */ + void removeLine(int i); + + /** + * Change line @p i + */ + void changeLine(int i); + + /** + * Clear the buffer. + */ + void clear(); + +signals: + + void textChanged(); + /** + * Emitted during loading. + */ + void linesChanged(int lines); + void needHighlight(long,long); + +protected: + /** + * Make sure @p buf gets loaded. + */ + void loadBlock(KWBufBlock *buf); + + /** + * Make sure @p buf gets parsed. + */ + void parseBlock(KWBufBlock *buf); + + /** + * Mark @p buf dirty. + */ + void dirtyBlock(KWBufBlock *buf); + + /** + * Find the block containing line @p i + */ + KWBufBlock *findBlock(int i); + + /** + * Load a part of the file that is currently loading. + */ + void loadFilePart(); + +protected slots: + void slotLoadFile(); + +protected: + TextLine::List m_stringList; + TextLine::List::Iterator m_stringListIt; + int m_stringListCurrent; + int m_lineCount; + void seek(int i); + + +}; + +#endif diff --git a/noncore/apps/tinykate/libkate/document/katecmd.cpp b/noncore/apps/tinykate/libkate/document/katecmd.cpp new file mode 100644 index 0000000..beebaa2 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katecmd.cpp @@ -0,0 +1,58 @@ +/*************************************************************************** + katecmd.cpp - description + ------------------- + begin : Mon Feb 5 2001 + copyright : (C) 2001 by Christoph Cullmann + (C) 2002 by Joseph Wenninger + email : crossfire@babylon2k.de + jowenn@kde.org + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "katecmd.h" +#include "katecmds.h" + + +#include "katedocument.h" + +KateCmd::KateCmd (KateDocument *doc) : QObject (doc) +{ + myDoc = doc; + + myParser.append (new KateCommands::InsertTime (myDoc)); + myParser.append (new KateCommands::SedReplace (myDoc)); + myParser.append (new KateCommands::Character (myDoc)); +} + +KateCmd::~KateCmd () +{ +} + +void KateCmd::execCmd (QString cmd, KateView *view) +{ + for (uint i=0; iexecCmd (cmd, view)) + break; + } +} + +KateCmdParser::KateCmdParser (KateDocument *doc) +{ + myDoc = doc; +} + +KateCmdParser::~KateCmdParser() +{ +} + + diff --git a/noncore/apps/tinykate/libkate/document/katecmd.h b/noncore/apps/tinykate/libkate/document/katecmd.h new file mode 100644 index 0000000..72158cc --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katecmd.h @@ -0,0 +1,57 @@ +/*************************************************************************** + katecmd.h - description + ------------------- + begin : Mon Feb 5 2001 + copyright : (C) 2001 by Christoph Cullmann + (C) 2002 by Joseph Wenninger + email : crossfire@babylon2k.de + jowenn@kde.org + +***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _KATE_CMD_H +#define _KATE_CMD_H + +#include +#include +#include +#include + +class KateCmdParser +{ + public: + KateCmdParser (KateDocument *doc=0L); + virtual ~KateCmdParser (); + + virtual bool execCmd (QString cmd=0L, KateView *view=0L)=0; + + private: + KateDocument *myDoc; +}; + +class KateCmd : public QObject +{ + Q_OBJECT + + public: + KateCmd (KateDocument *doc=0L); + ~KateCmd (); + + void execCmd (QString cmd=0L, KateView *view=0L); + + private: + KateDocument *myDoc; + QList myParser; +}; + +#endif + diff --git a/noncore/apps/tinykate/libkate/document/katecmds.cpp b/noncore/apps/tinykate/libkate/document/katecmds.cpp new file mode 100644 index 0000000..3647853 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katecmds.cpp @@ -0,0 +1,278 @@ +/*************************************************************************** + katecmds.cpp - description + ------------------- + copyright : (C) 2001 by The Kate Team + (C) 2002 by Joseph Wenninger + email : kwrite-devel@kde.org + jowenn@kde.org + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#include "katecmds.h" +#include +#include +#include +#include "katedocument.h" +#include + +namespace KateCommands +{ + + +bool InsertTime::execCmd(QString cmd, KateView *view) +{ + if (cmd.left(5) == "time") + { + view->insertText(QTime::currentTime().toString()); + return true; + } + + return false; +} + +static void replace(QString &s, const QString &needle, const QString &with) +{ + int pos=0; + while (1) + { + pos=s.find(needle, pos); + if (pos==-1) break; + s.replace(pos, needle.length(), with); + pos+=with.length(); + } + +} + +// stolen from QString::replace +static void replace(QString &s, QRegExp3 &rx, const QString &with) +{ + if (s.isEmpty()) return; + int index = 0; + int slen = with.length(); + int len; + while (index < (int)s.length()) + { + index = rx.search(s, index); + len = rx.matchedLength(); + if ( index >= 0 ) + { + s.replace(index, len, with); + index += slen; + if (!len) + break; // Avoid infinite loop on 0-length matches, e.g. [a-z]* + } + else + break; + } +} + + + +static int backslashString(const QString &haystack, const QString &needle, int index) +{ + int len=haystack.length(); + int searchlen=needle.length(); + bool evenCount=true; + while (index=0) + { + rep.replace(index, 2, *i); + index+=(*i).length(); + } + } + + refnum++; + } + + textLine.replace(start, length, rep); + if (!repeat) break; + start+=rep.length(); + } + + replace(textLine, "\\\\", "\\"); + replace(textLine, "\\/", "/"); + + return textLine; +} + + +static void setLineText(KateView *view, int line, const QString &text) +{ +// view->doc()->removeLine(line); +// view->doc()->insertLine(text, line); + view->doc()->replaceLine(text,line); +} + +bool SedReplace::execCmd(QString cmd, KateView *view) +{ + kdDebug(13010)<<"SedReplace::execCmd()"<insertText(QString(buf)); + } + else + { // do the unicode thing + QChar c(number); + view->insertText(QString(&c, 1)); + } + + return true; +} + +bool Fifo::execCmd(QString cmd, KateView *view) +{ + +} + +} + +// vim: noet + diff --git a/noncore/apps/tinykate/libkate/document/katecmds.h b/noncore/apps/tinykate/libkate/document/katecmds.h new file mode 100644 index 0000000..bbd5937 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katecmds.h @@ -0,0 +1,94 @@ +/*************************************************************************** + katecmds.h - description + ------------------- + copyright : (C) 2001 by The Kate Team + (C) 2002 by Joseph Wenninger + email : kwrite-devel@kde.org + jowenn@kde.org + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef _KATECMDS_H +#define _KATECMDS_H + +#include "katecmd.h" + + +/** + * this namespace will be maintained by Charles Samuels + * so we're going to be using this indentation style here. + * + * Respect my style, and I'll respect your's! + **/ +namespace KateCommands +{ + +/** + * This is by Christoph Cullmann + **/ +class InsertTime : public KateCmdParser +{ +public: + InsertTime(KateDocument *doc=0) : KateCmdParser(doc) { } + + bool execCmd(QString cmd=0, KateView *view=0); +}; + +/** + * -- Charles Samuels + * Support vim/sed find and replace + * s/search/replace/ find search, replace with replace on this line + * %s/search/replace/ do the same to the whole file + * s/search/replace/i do the S. and R., but case insensitively + * $s/search/replace/ do the search are replacement to the selection only + * + * $s/// is currently unsupported + **/ +class SedReplace : public KateCmdParser +{ +public: + SedReplace(KateDocument *doc=0) : KateCmdParser(doc) { } + + bool execCmd(QString cmd=0, KateView *view=0); +private: + static QString sedMagic(QString textLine, QString find, QString replace, bool noCase, bool repeat); +}; + +/** + * insert a unicode or ascii character + * base 9+1: 1234 + * hex: 0x1234 or x1234 + * octal: 01231 + * + * prefixed with "char:" + **/ +class Character : public KateCmdParser +{ +public: + Character(KateDocument *doc=0) : KateCmdParser(doc) { } + + bool execCmd(QString cmd=0, KateView *view=0); +}; + +class Fifo : public KateCmdParser +{ +public: + Fifo(KateDocument *doc=0) : KateCmdParser(doc) { } + + bool execCmd(QString cmd=0, KateView *view=0); +}; + +} + +// vim: noet + +#endif + diff --git a/noncore/apps/tinykate/libkate/document/katedialogs.cpp b/noncore/apps/tinykate/libkate/document/katedialogs.cpp new file mode 100644 index 0000000..2f0ed7b --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katedialogs.cpp @@ -0,0 +1,588 @@ +/*************************************************************************** + katedialogs.cpp - description + ------------------- + copyright : (C) 2001 by The Kate Team + (C) 2002 by Joseph Wenninger + email : kwrite-devel@kde.org + jowenn@kde.org + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#include "katedialogs.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//FIXME #include +#include +#include +#include +#include + + +/******************************************************************************************************************* +* Context Editor * +*******************************************************************************************************************/ + +StyleChanger::StyleChanger( QWidget *parent ) + : QWidget(parent) +{ + QLabel *label; + + QGridLayout *glay = new QGridLayout( this, 4, 3, 0, KDialog::spacingHint() ); + CHECK_PTR(glay); + glay->addColSpacing( 1, KDialog::spacingHint() ); // Looks better + glay->setColStretch( 2, 10 ); + + col = new KColorButton(this); + CHECK_PTR(col); + connect(col,SIGNAL(changed(const QColor &)),this,SLOT(changed())); + label = new QLabel(col,i18n("Normal:"),this); + CHECK_PTR(label); + glay->addWidget(label,0,0); + glay->addWidget(col,1,0); + + selCol = new KColorButton(this); + CHECK_PTR(selCol); + connect(selCol,SIGNAL(changed(const QColor &)),this,SLOT(changed())); + label = new QLabel(selCol,i18n("Selected:"),this); + CHECK_PTR(label); + glay->addWidget(label,2,0); + glay->addWidget(selCol,3,0); + + bold = new QCheckBox(i18n("Bold"),this); + CHECK_PTR(bold); + connect(bold,SIGNAL(clicked()),SLOT(changed())); + glay->addWidget(bold,1,2); + + italic = new QCheckBox(i18n("Italic"),this); + CHECK_PTR(italic); + connect(italic,SIGNAL(clicked()),SLOT(changed())); + glay->addWidget(italic,2,2); +} + +void StyleChanger::setRef(ItemStyle *s) { + + style = s; + col->setColor(style->col); + selCol->setColor(style->selCol); + bold->setChecked(style->bold); + italic->setChecked(style->italic); + +} + +void StyleChanger::setEnabled(bool enable) { + + col->setEnabled(enable); + selCol->setEnabled(enable); + bold->setEnabled(enable); + italic->setEnabled(enable); +} + +void StyleChanger::changed() { + + if (style) { + style->col = col->color(); + style->selCol = selCol->color(); + style->bold = bold->isChecked(); + style->italic = italic->isChecked(); + } +} + +HighlightDialog::HighlightDialog( HlManager *hlManager, ItemStyleList *styleList, + HlDataList *highlightDataList, + int hlNumber, QWidget *parent, + const char *name, bool modal ) + :KDialogBase(parent,name,modal,i18n("Highlight Settings"), Ok|Cancel, Ok) +{ +// QVBox *page = makeVBoxMainWidget(); + QFrame *page=addPage("FIXME"); + (new QVBoxLayout(page))->setAutoAdd(true); + content=new HighlightDialogPage(hlManager,styleList,highlightDataList,hlNumber,page); +} + +void HighlightDialog::done(int r) +{ + kdDebug(13010)<<"HighlightDialod done"<saveData(); + KDialogBase::done(r); +} + +HighlightDialogPage::HighlightDialogPage(HlManager *hlManager, ItemStyleList *styleList, + HlDataList* highlightDataList, + int hlNumber,QWidget *parent, const char *name) + :QTabWidget(parent,name),defaultItemStyleList(styleList),hlData(0L) + +{ + + // defaults ========================================================= + + QFrame *page1 = new QFrame(this); + addTab(page1,i18n("&Defaults")); + QGridLayout *grid = new QGridLayout(page1, 1, 1); + + QVGroupBox *dvbox1 = new QVGroupBox( i18n("Default Item Styles"), page1 ); + /*QLabel *label = */new QLabel( i18n("Item:"), dvbox1 ); + QComboBox *styleCombo = new QComboBox( false, dvbox1 ); + defaultStyleChanger = new StyleChanger( dvbox1 ); + for( int i = 0; i < hlManager->defaultStyles(); i++ ) { + styleCombo->insertItem(hlManager->defaultStyleName(i)); + } + connect(styleCombo, SIGNAL(activated(int)), this, SLOT(defaultChanged(int))); + grid->addWidget(dvbox1, 0,0); + + defaultChanged(0); + + // highlight modes ===================================================== + + QFrame *page2 = new QFrame(this); + addTab(page2,i18n("&Highlight Modes")); + //grid = new QGridLayout(page2,2,2); + QVBoxLayout *bl=new QVBoxLayout(page2); + bl->setAutoAdd(true); + QHGroupBox *hbox1 = new QHGroupBox( i18n("Config Select"), page2 ); + hbox1->layout()->setMargin(5); + QVBox *vbox1=new QVBox(hbox1); +// grid->addMultiCellWidget(vbox1,0,0,0,1); + QVGroupBox *vbox2 = new QVGroupBox( i18n("Item Style"), page2 ); +// grid->addWidget(vbox2,1,0); + QVGroupBox *vbox3 = new QVGroupBox( i18n("Highlight Auto Select"), hbox1 ); + //grid->addWidget(vbox3,1,1); + + QLabel *label = new QLabel( i18n("Highlight:"), vbox1 ); + hlCombo = new QComboBox( false, vbox1 ); + QHBox *modHl = new QHBox(vbox1); +// connect(new QPushButton(i18n("New"),modHl),SIGNAL(clicked()),this,SLOT(hlNew())); +// connect(new QPushButton(i18n("Edit"),modHl),SIGNAL(clicked()),this,SLOT(hlEdit())); + connect( hlCombo, SIGNAL(activated(int)), + this, SLOT(hlChanged(int)) ); + for( int i = 0; i < hlManager->highlights(); i++) { + hlCombo->insertItem(hlManager->hlName(i)); + } + hlCombo->setCurrentItem(hlNumber); + + + label = new QLabel( i18n("Item:"), vbox2 ); + itemCombo = new QComboBox( false, vbox2 ); + connect( itemCombo, SIGNAL(activated(int)), this, SLOT(itemChanged(int)) ); + + label = new QLabel( i18n("File Extensions:"), vbox3 ); + wildcards = new QLineEdit( vbox3 ); + label = new QLabel( i18n("Mime Types:"), vbox3 ); + mimetypes = new QLineEdit( vbox3 ); + + + styleDefault = new QCheckBox(i18n("Default"), vbox2 ); + connect(styleDefault,SIGNAL(clicked()),SLOT(changed())); + styleChanger = new StyleChanger( vbox2 ); + + hlDataList = highlightDataList; + hlChanged(hlNumber); +} + + +void HighlightDialogPage::defaultChanged(int z) +{ + defaultStyleChanger->setRef(defaultItemStyleList->at(z)); +} + + +void HighlightDialogPage::hlChanged(int z) +{ + writeback(); + + hlData = hlDataList->at(z); + + wildcards->setText(hlData->wildcards); + mimetypes->setText(hlData->mimetypes); + + itemCombo->clear(); + for (ItemData *itemData = hlData->itemDataList.first(); itemData != 0L; + itemData = hlData->itemDataList.next()) { + kdDebug(13010) << itemData->name << endl; + itemCombo->insertItem(i18n(itemData->name.latin1())); + } + + itemChanged(0); +} + +void HighlightDialogPage::itemChanged(int z) +{ + itemData = hlData->itemDataList.at(z); + + styleDefault->setChecked(itemData->defStyle); + styleChanger->setRef(itemData); +} + +void HighlightDialogPage::changed() +{ + itemData->defStyle = styleDefault->isChecked(); +} + +void HighlightDialogPage::writeback() { + if (hlData) { + hlData->wildcards = wildcards->text(); + hlData->mimetypes = mimetypes->text(); + } +} + +void HighlightDialogPage::saveData() { + kdDebug(13010)<<"HighlightDialogPage::saveData()"<setRootIsDecorated(true); + contextList->addColumn(i18n("Syntax structure")); + contextList->setSorting(-1); + QHBox *bbox=new QHBox(lbox); + QPushButton *addContext=new QPushButton(i18n("New Context"),bbox); + QPushButton *addItem=new QPushButton(i18n("New Item"),bbox); + QVGroupBox *opt = new QVGroupBox( i18n("Options"), wid); + stack=new QWidgetStack(opt); + initContextOptions(contextOptions=new QVBox(stack)); + stack->addWidget(contextOptions,HlEContext); + initItemOptions(itemOptions=new QVBox(stack)); + stack->addWidget(itemOptions,HlEItem); + stack->raiseWidget(HlEContext); + setMainWidget(wid); + if (data!=0) loadFromDocument(data); + else newDocument(); + connect(contextList,SIGNAL(currentChanged( QListViewItem*)),this,SLOT(currentSelectionChanged ( QListViewItem * ))); + connect(addContext,SIGNAL(clicked()),this,SLOT(contextAddNew())); + connect(addItem,SIGNAL(clicked()),this,SLOT(ItemAddNew())); + } + +void HlEditDialog::newDocument() +{ + KStandardDirs *dirs = KGlobal::dirs(); + QStringList list=dirs->findAllResources("data","kate/syntax/syntax.template",false,true); + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + { + HlData data("","",*it); + loadFromDocument(&data); + return; + } + KMessageBox::error(this,i18n("Can't find template file")); +} + + +void HlEditDialog::initContextOptions(QVBox *co) +{ + if( co!=0) + { + QHBox *tmp = new QHBox(co); + (void) new QLabel(i18n("Description:"),tmp); + ContextDescr=new QLineEdit(tmp); + tmp= new QHBox(co); + (void) new QLabel(i18n("Attribute:"),tmp); + ContextAttribute=new QComboBox(tmp); + tmp= new QHBox(co); + (void) new QLabel(i18n("LineEnd:"),tmp); + ContextLineEnd = new QComboBox(tmp); + connect(ContextDescr,SIGNAL(textChanged(const QString&)),this,SLOT(contextDescrChanged(const QString&))); + connect(ContextLineEnd,SIGNAL(activated(int)),this,SLOT(contextLineEndChanged(int))); + connect(ContextAttribute,SIGNAL(activated(int)),this,SLOT(contextAttributeChanged(int))); + } + else + kdDebug(13010)<<"initContextOptions: Widget is 0"<setSpacing(15); + QPushButton *delItem=new QPushButton(i18n("Delete this item"),co); + + /* init translation lists */ + insertTranslationList("CharDetect","CharDetect",1); + insertTranslationList("2CharDetect","2CharDetect",2); + insertTranslationList("RangeDetect","RangeDetect",2); + insertTranslationList("StringDetect","StringDetect",-1); + insertTranslationList("AnyChar","AnyChar",-1); + insertTranslationList("RegExpr","RegExpr",-1); + insertTranslationList("Int","Int",0); + insertTranslationList("Float","Float",0); + insertTranslationList("keyword","keyword",0); + insertTranslationList("dataType","dataType",0); + ItemType->clear(); + for (int i=0; iinsertItem(id2info[i].trans_i18n); + connect(ItemType,SIGNAL(activated(int)),this,SLOT(ItemTypeChanged(int))); + connect(ItemParameter,SIGNAL(textChanged(const QString&)),this,SLOT(ItemParameterChanged(const QString&))); + connect(ItemAttribute,SIGNAL(activated(int)),this,SLOT(ItemAttributeChanged(int))); + connect(ItemContext,SIGNAL(activated(int)),this,SLOT(ItemContextChanged(int))); + } + else + kdDebug(13010)<<"initItemOptions: Widget is 0"<syntax->setIdentifier(hl->identifier); + data=HlManager::self()->syntax->getGroupInfo("highlighting","context"); + int i=0; + if (data) + { + while (HlManager::self()->syntax->nextGroup(data)) // + { + kdDebug(13010)<< "Adding context to list"<syntax->groupData(data,QString("name")), + QString("%1").arg(i), + HlManager::self()->syntax->groupData(data,QString("attribute")), + HlManager::self()->syntax->groupData(data,QString("lineEndContext"))); + i++; + lastsub=0; + while (HlManager::self()->syntax->nextItem(data)) + { + kdDebug(13010)<< "Adding item to list"<syntax->freeGroupInfo(data); + } + ContextAttribute->clear(); + ItemAttribute->clear(); + data=HlManager::self()->syntax->getGroupInfo("highlighting","itemData"); + while (HlManager::self()->syntax->nextGroup(data)) + { + ContextAttribute->insertItem(HlManager::self()->syntax->groupData(data,QString("name"))); + ItemAttribute->insertItem(HlManager::self()->syntax->groupData(data,QString("name"))); + } + if (data) HlManager::self()->syntax->freeGroupInfo(data); +} + +QListViewItem *HlEditDialog::addContextItem(QListViewItem *_parent,QListViewItem *prev,struct syntaxContextData *data) + { + + kdDebug(13010)<syntax->groupItemData(data,QString("name")) << endl; + + QString dataname=HlManager::self()->syntax->groupItemData(data,QString("")); + QString attr=(HlManager::self()->syntax->groupItemData(data,QString("attribute"))); + QString context=(HlManager::self()->syntax->groupItemData(data,QString("context"))); + char chr; + if (! HlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty()) + chr= (HlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0]; + else + chr=0; + QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String")); + char chr1; + if (! HlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty()) + chr1= (HlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0]; + else + chr1=0; + bool insensitive=(HlManager::self()->syntax->groupItemData(data,QString("insensitive"))==QString("TRUE")); + QString param(""); + if ((dataname=="keyword") || (dataname=="dataType")) param=dataname; + else if (dataname=="CharDetect") param=chr; + else if ((dataname=="2CharDetect") || (dataname=="RangeDetect")) param=QString("%1%2").arg(chr).arg(chr1); + else if ((dataname=="StringDetect") || (dataname=="AnyChar") || (dataname=="RegExpr")) param=stringdata; + else kdDebug(13010)<<"***********************************"<depth()<depth()==0) showContext(); + else showItem(); + } + + +/****************************************************************************/ +/* CONTEXTS */ +/****************************************************************************/ + + +void HlEditDialog::showContext() + { + stack->raiseWidget(HlEContext); + ContextDescr->setText(currentItem->text(0)); + ContextAttribute->setCurrentItem(currentItem->text(2).toInt()); + ContextLineEnd->clear(); + for (QListViewItem *it=contextList->firstChild();it;it=it->nextSibling()) + ContextLineEnd->insertItem(it->text(0)); + ContextLineEnd->setCurrentItem(currentItem->text(3).toInt()); +// ContextAttribute->setText(currentItem->text(1)); +// ContextLineEnd->setText(currentItem->text(2)); + } + +void HlEditDialog::contextDescrChanged(const QString& name) + { + if (currentItem) + { + currentItem->setText(0,name); + ContextLineEnd->changeItem(name,currentItem->text(3).toInt()); + } + } + +void HlEditDialog::contextAttributeChanged(int id) +{ + if (currentItem) + { + currentItem->setText(2,QString("%1").arg(id)); + } +} + +void HlEditDialog::contextLineEndChanged(int id) +{ + kdDebug(13010)<<"contextLineEndChanged"<setText(3,QString("%1").arg(id)); + } +} + +void HlEditDialog::contextAddNew() +{ + QListViewItem *it=contextList->firstChild(); + for (;it->nextSibling()!=0;it=it->nextSibling()); + it=new QListViewItem(contextList,it,i18n("New Context"),QString("%1").arg(it->text(1).toInt()),"0","0"); + contextList->setSelected(it,true); +} + +/****************************************************************************/ +/* ITEMS */ +/****************************************************************************/ + +void HlEditDialog::showItem() + { + stack->raiseWidget(HlEItem); + ItemContext->clear(); + for (QListViewItem *it=contextList->firstChild();it;it=it->nextSibling()) + ItemContext->insertItem(it->text(0)); + ItemContext->setCurrentItem(currentItem->text(4).toInt()); + ItemAttribute->setCurrentItem(currentItem->text(3).toInt()); + QMap::Iterator iter=tag2id.find(currentItem->text(1)); + if (iter==tag2id.end()) + kdDebug(13010)<<"Oops, unknown itemtype in showItem: "<text(1)<setCurrentItem(*iter); + if (id2info[*iter].length==0) ItemParameter->hide(); + else + { + ItemParameter->setMaxLength(id2info[*iter].length); + ItemParameter->show(); + ItemParameter->setText(currentItem->text(2)); + } + } + + } + +void HlEditDialog::ItemTypeChanged(int id) +{ + if (currentItem) + { + currentItem->setText(1,id2tag[id]); + ItemParameter->setMaxLength(id2info[id].length); + ItemParameterChanged(ItemParameter->text()); + } +} + +void HlEditDialog::ItemParameterChanged(const QString& name) +{ + if (currentItem) + { + currentItem->setText(2,name); + currentItem->setText(0,id2info[ItemType->currentItem()].trans_i18n+" "+currentItem->text(2)); + } +} + +void HlEditDialog::ItemAttributeChanged(int attr) +{ + if (currentItem) + { + currentItem->setText(3,QString("%1").arg(attr)); + } +} + +void HlEditDialog::ItemContextChanged(int cont) +{ + if (currentItem) + { + currentItem->setText(4,QString("%1").arg(cont)); + } +} + +void HlEditDialog::ItemAddNew() +{ + QListViewItem *it; + if (currentItem) + { + if (currentItem->depth()==0) it=currentItem->firstChild(); + else + it=currentItem; + if (it) for (;it->nextSibling();it=it->nextSibling()); + (void) new QListViewItem(it ? it->parent() : currentItem,it,"StringDetect "+i18n("New Item"),"StringDetect",i18n("New Item"),0,it ? it->parent()->text(1) : currentItem->text(1)); + } +} diff --git a/noncore/apps/tinykate/libkate/document/katedialogs.h b/noncore/apps/tinykate/libkate/document/katedialogs.h new file mode 100644 index 0000000..f37f45a --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katedialogs.h @@ -0,0 +1,160 @@ +/*************************************************************************** + katedialogs.h - description + ------------------- + copyright : (C) 2001 by The Kate Team + (C) 2002 by Joseph Wenninger + email : kwrite-devel@kde.org + jowenn@kde.org + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef KATEDIALOGS_H +#define KATEDIALOGS_H +#include +#include +#include "katesyntaxdocument.h" +#include "katehighlight.h" +#include +#include +#include + +class QWidgetStack; +class QVBox; +class KListView; +class QListViewItem; +struct syntaxContextData; +class QCheckBox; +//class ItemFont; +#define HlEUnknown 0 +#define HlEContext 1 +#define HlEItem 2 + //-------- + + +class StyleChanger : public QWidget { + Q_OBJECT + public: + StyleChanger(QWidget *parent ); + void setRef(ItemStyle *); + void setEnabled(bool); + protected slots: + void changed(); + protected: + ItemStyle *style; + KColorButton *col; + KColorButton *selCol; + QCheckBox *bold; + QCheckBox *italic; +}; + +class HighlightDialogPage : public QTabWidget +{ + Q_OBJECT + public: + HighlightDialogPage(HlManager *, ItemStyleList *, HlDataList *, int hlNumber, + QWidget *parent=0, const char *name=0); + void saveData(); + + protected slots: + void defaultChanged(int); + + void hlChanged(int); + void itemChanged(int); + void changed(); + void hlEdit(); + void hlNew(); + protected: + StyleChanger *defaultStyleChanger; + ItemStyleList *defaultItemStyleList; + + void writeback(); + QComboBox *itemCombo, *hlCombo; + QLineEdit *wildcards; + QLineEdit *mimetypes; + QCheckBox *styleDefault; + StyleChanger *styleChanger; + + HlDataList *hlDataList; + HlData *hlData; + ItemData *itemData; +}; + +class ItemInfo +{ + public: + ItemInfo():trans_i18n(),length(0){}; + ItemInfo(QString _trans,int _length):trans_i18n(_trans),length(_length){}; + QString trans_i18n; + int length; +}; + +class HighlightDialog : public KDialogBase +{ + Q_OBJECT + public: + HighlightDialog( HlManager *hlManager, ItemStyleList *styleList, + HlDataList *highlightDataList, + int hlNumber, QWidget *parent, + const char *name=0, bool modal=true ); + private: + HighlightDialogPage *content; + protected: + virtual void done(int r); +}; + +class HlEditDialog : public KDialogBase +{ + Q_OBJECT + public: + HlEditDialog(HlManager *,QWidget *parent=0, const char *name=0, bool modal=true, HlData *data=0); + private: + class QWidgetStack *stack; + class QVBox *contextOptions, *itemOptions; + class KListView *contextList; + class QListViewItem *currentItem; + void initContextOptions(class QVBox *co); + void initItemOptions(class QVBox *co); + void loadFromDocument(HlData *hl); + void showContext(); + void showItem(); + + QListViewItem *addContextItem(QListViewItem *_parent,QListViewItem *prev,struct syntaxContextData *data); + void insertTranslationList(QString tag, QString trans,int length); + void newDocument(); + + class QLineEdit *ContextDescr; + class QComboBox *ContextAttribute; + class QComboBox *ContextLineEnd; + + class QComboBox *ItemType; + class QComboBox *ItemContext; + class QLineEdit *ItemParameter; + class QComboBox *ItemAttribute; + + class QMap id2tag; + class QMap id2info; + class QMap tag2id; + int transTableCnt; + protected slots: + void currentSelectionChanged ( QListViewItem * ); + void contextDescrChanged(const QString&); + void contextLineEndChanged(int); + void contextAttributeChanged(int); + void contextAddNew(); + + void ItemTypeChanged(int id); + void ItemParameterChanged(const QString& name); + void ItemAttributeChanged(int attr); + void ItemContextChanged(int cont); + void ItemAddNew(); +}; + +#endif diff --git a/noncore/apps/tinykate/libkate/document/katedocument.cpp b/noncore/apps/tinykate/libkate/document/katedocument.cpp new file mode 100644 index 0000000..0d84bcf --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katedocument.cpp @@ -0,0 +1,3169 @@ +/*************************************************************************** + katedocument.cpp - description + ------------------- + begin : Mon Jan 15 2001 + copyright : (C) 2001 by Christoph "Crossfire" Cullmann + (C) 2002 by Joseph Wenninger + email : crossfire@babylon2k.de + jowenn@kde.org + +***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* + Copyright (C) 1998, 1999 Jochen Wilhelmy + digisnap@cs.tu-berlin.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "katedocument.h" + + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +//#include +#include +//#include + +#include +//#include +//#include + +#include "../view/kateview.h" +#include "katebuffer.h" +#include "katetextline.h" + +#include "katecmd.h" + +KateAction::KateAction(Action a, PointStruc &cursor, int len, const QString &text) + : action(a), cursor(cursor), len(len), text(text) { +} + +KateActionGroup::KateActionGroup(PointStruc &aStart, int type) + : start(aStart), action(0L), undoType(type) { +} + +KateActionGroup::~KateActionGroup() { + KateAction *current, *next; + + current = action; + while (current) { + next = current->next; + delete current; + current = next; + } +} + +void KateActionGroup::insertAction(KateAction *a) { + a->next = action; + action = a; +} + +const char * KateActionGroup::typeName(int type) +{ + // return a short text description of the given undo group type suitable for a menu + // not the lack of i18n's, the caller is expected to handle translation + switch (type) { + case ugPaste : return "Paste Text"; + case ugDelBlock : return "Selection Overwrite"; + case ugIndent : return "Indent"; + case ugUnindent : return "Unindent"; + case ugComment : return "Comment"; + case ugUncomment : return "Uncomment"; + case ugReplace : return "Text Replace"; + case ugSpell : return "Spell Check"; + case ugInsChar : return "Typing"; + case ugDelChar : return "Delete Text"; + case ugInsLine : return "New Line"; + case ugDelLine : return "Delete Line"; + } + return ""; +} + +const int KateDocument::maxAttribs = 32; + +QStringList KateDocument::searchForList = QStringList(); +QStringList KateDocument::replaceWithList = QStringList(); + +uint KateDocument::uniqueID = 0; + +QPtrDict* KateDocument::d_ptr = 0; + + +KateDocument::KateDocument(bool bSingleViewMode, bool bBrowserView, + QWidget *parentWidget, const char *widgetName, + QObject *, const char *) + : Kate::Document (), + myFont(KGlobalSettings::generalFont()), myFontBold(KGlobalSettings::generalFont()), myFontItalic(KGlobalSettings::generalFont()), myFontBI(KGlobalSettings::generalFont()), + myFontMetrics (myFont), myFontMetricsBold (myFontBold), myFontMetricsItalic (myFontItalic), myFontMetricsBI (myFontBI), + hlManager(HlManager::self ()) +{ + + d(this)->hlSetByUser = false; + PreHighlightedTill=0; + RequestPreHighlightTill=0; + + m_bSingleViewMode=bSingleViewMode; + m_bBrowserView = bBrowserView; + + m_url = QString::null; + + // NOTE: QFont::CharSet doesn't provide all the charsets KDE supports + // (esp. it doesn't distinguish between UTF-8 and iso10646-1) + + myEncoding = QString::fromLatin1(QTextCodec::codecForLocale()->name()); + + maxLength = -1; + + setFont (KGlobalSettings::generalFont()); + + myDocID = uniqueID; + uniqueID++; + + myDocName = QString (""); + fileInfo = new QFileInfo (); + + myCmd = new KateCmd (this); + + connect(this,SIGNAL(modifiedChanged ()),this,SLOT(slotModChanged ())); + + buffer = new KWBuffer; + connect(buffer, SIGNAL(linesChanged(int)), this, SLOT(slotBufferChanged())); +// connect(buffer, SIGNAL(textChanged()), this, SIGNAL(textChanged())); + connect(buffer, SIGNAL(needHighlight(long,long)),this,SLOT(slotBufferHighlight(long,long))); + + colors[0] = KGlobalSettings::baseColor(); + colors[1] = KGlobalSettings::highlightColor(); + + m_attribs = new Attribute[maxAttribs]; + + m_highlight = 0L; + tabChars = 8; + + m_singleSelection = false; + + newDocGeometry = false; + readOnly = false; + newDoc = false; + + modified = false; + + undoList.setAutoDelete(true); + undoState = 0; + undoSteps = 50; + + pseudoModal = 0L; + clear(); + + setHighlight(0); //calls updateFontData() + // if the user changes the highlight with the dialog, notify the doc + connect(hlManager,SIGNAL(changed()),SLOT(hlChanged())); + + newDocGeometry = false; + + readConfig(); + + setReadOnly(false); +} + +void KateDocument::setDontChangeHlOnSave() +{ + d(this)->hlSetByUser = true; +} + +void KateDocument::setFont (QFont font) +{ + kdDebug()<<"Kate:: setFont"<max) + { + till=max; + } + if (PreHighlightedTill>=till) return -1; + + long tmp=RequestPreHighlightTill; + if (RequestPreHighlightTill max) + { + till = max; + } + PreHighlightedTill = till; + updateLines(from,till); + emit preHighlightChanged(PreHighlightedTill); + if (PreHighlightedTillrelease(); + + if ( !m_bSingleViewMode ) + { + m_views.setAutoDelete( true ); + m_views.clear(); + m_views.setAutoDelete( false ); + } + delete_d(this); +} + +void KateDocument::openURL(const QString &filename) +{ + + m_file=filename; + fileInfo->setFile (m_file); + setMTime(); + + if (!fileInfo->exists() || !fileInfo->isReadable()) + { + qDebug("File doesn't exit or couldn't be read"); + return false; + } + + buffer->clear(); +#warning fixme +// buffer->insertFile(0, m_file, KGlobal::charsets()->codecForName(myEncoding)); + qDebug("Telling buffer to open file"); + buffer->insertFile(0, m_file, QTextCodec::codecForLocale()); + + setMTime(); + + if (myWordWrap) + wrapText (myWordWrapAt); + + int hl = hlManager->wildcardFind( m_file ); + + setHighlight(hl); + + updateLines(); + updateViews(); + + emit fileNameChanged(); + + return true; +} + +bool KateDocument::saveFile() +{ + QFile f( m_file ); + if ( !f.open( IO_WriteOnly ) ) + return false; // Error + + QTextStream stream(&f); + + stream.setEncoding(QTextStream::RawUnicode); // disable Unicode headers +#warning fixme +// stream.setCodec(KGlobal::charsets()->codecForName(myEncoding)); + stream.setCodec(QTextCodec::codecForLocale()); // this line sets the mapper to the correct codec + + int maxLine = numLines(); + int line = 0; + while(true) + { + stream << getTextLine(line)->getString(); + line++; + if (line >= maxLine) break; + + if (eolMode == KateDocument::eolUnix) stream << "\n"; + else if (eolMode == KateDocument::eolDos) stream << "\r\n"; + else if (eolMode == KateDocument::eolMacintosh) stream << '\r'; + }; + f.close(); + + fileInfo->setFile (m_file); + setMTime(); + + if (!(d(this)->hlSetByUser)) + { + int hl = hlManager->wildcardFind( m_file ); + + setHighlight(hl); + } + emit fileNameChanged (); + + return (f.status() == IO_Ok); +} + +KTextEditor::View *KateDocument::createView( QWidget *parent, const char *name ) +{ + return new KateView( this, parent, name); +} + +QString KateDocument::textLine( int line ) const +{ + TextLine::Ptr l = getTextLine( line ); + if ( !l ) + return QString(); + + return l->getString(); +} + +void KateDocument::replaceLine(const QString& s,int line) +{ + remove_Line(line,false); + insert_Line(s,line,true); +} + +void KateDocument::insertLine( const QString &str, int l ) { + insert_Line(str,l,true); +} + +void KateDocument::insert_Line(const QString& s,int line, bool update) +{ + kdDebug(13020)<<"KateDocument::insertLine "<append(s.unicode(),s.length()); + buffer->insertLine(line,TL); + if (update) + { + newDocGeometry=true; + updateLines(line); + updateViews(); + } +} + +void KateDocument::insertAt( const QString &s, int line, int col, bool ) +{ + VConfig c; + c.view = 0; // ### FIXME + c.cursor.x = col; + c.cursor.y = line; + c.cXPos = 0; // ### FIXME + c.flags = 0; // ### FIXME + insert( c, s ); +} + +void KateDocument::removeLine( int line ) { + remove_Line(line,true); +} + +void KateDocument::remove_Line(int line,bool update) +{ + kdDebug(13020)<<"KateDocument::removeLine "<removeLine(line); +// newDocGeometry=true; +// if line==0) + if (update) + { + updateLines(line); + updateViews(); + } +} + +int KateDocument::length() const +{ + return text().length(); +} + +void KateDocument::setSelection( int , int , int , int ) +{ +} + +bool KateDocument::hasSelection() const +{ + return (selectEnd >= selectStart); +} + +QString KateDocument::selection() const +{ + uint flags = 0; + TextLine::Ptr textLine; + int len, z, start, end, i; + + len = 1; + if (!(flags & KateView::cfVerticalSelect)) { + for (z = selectStart; z <= selectEnd; z++) { + textLine = getTextLine(z); + len += textLine->numSelected(); + if (textLine->isSelected()) len++; + } + QString s; + len = 0; + for (z = selectStart; z <= selectEnd; z++) { + textLine = getTextLine(z); + end = 0; + do { + start = textLine->findUnselected(end); + end = textLine->findSelected(start); + for (i = start; i < end; i++) { + s[len] = textLine->getChar(i); + len++; + } + } while (start < end); + if (textLine->isSelected()) { + s[len] = '\n'; + len++; + } + } +// s[len] = '\0'; + return s; + } else { + for (z = selectStart; z <= selectEnd; z++) { + textLine = getTextLine(z); + len += textLine->numSelected() + 1; + } + QString s; + len = 0; + for (z = selectStart; z <= selectEnd; z++) { + textLine = getTextLine(z); + end = 0; + do { + start = textLine->findUnselected(end); + end = textLine->findSelected(start); + for (i = start; i < end; i++) { + s[len] = textLine->getChar(i); + len++; + } + } while (start < end); + s[len] = '\n'; + len++; + } +// s[len] = '\0'; // the final \0 is not counted in length() + return s; + } +} + +int KateDocument::numLines() const +{ + return buffer->count(); +} + + +TextLine::Ptr KateDocument::getTextLine(int line) const +{ + // This is a hack to get this stuff working. + return buffer->line(line); +} + +int KateDocument::textLength(int line) { + TextLine::Ptr textLine = getTextLine(line); + if (!textLine) return 0; + return textLine->length(); +} + +void KateDocument::setTabWidth(int chars) { + if (tabChars == chars) return; + if (chars < 1) chars = 1; + if (chars > 16) chars = 16; + tabChars = chars; + updateFontData(); + + maxLength = -1; + for (int i=0; i < buffer->count(); i++) + { + TextLine::Ptr textLine = buffer->line(i); + int len = textWidth(textLine,textLine->length()); + if (len > maxLength) { + maxLength = len; + longestLine = textLine; + } + } +} + +void KateDocument::setReadOnly(bool m) { + KTextEditor::View *view; + + if (m != readOnly) { + readOnly = m; +// if (readOnly) recordReset(); + for (view = m_views.first(); view != 0L; view = m_views.next() ) { + emit static_cast( view )->newStatus(); + } + } +} + +bool KateDocument::isReadOnly() const { + return readOnly; +} + +void KateDocument::setNewDoc( bool m ) +{ +// KTextEditor::View *view; + + if ( m != newDoc ) + { + newDoc = m; +//// if (readOnly) recordReset(); +// for (view = m_views.first(); view != 0L; view = m_views.next() ) { +// emit static_cast( view )->newStatus(); +// } + } +} + +bool KateDocument::isNewDoc() const { + return newDoc; +} + +void KateDocument::setModified(bool m) { + KTextEditor::View *view; + + if (m != modified) { + modified = m; + for (view = m_views.first(); view != 0L; view = m_views.next() ) { + emit static_cast( view )->newStatus(); + } + emit modifiedChanged (); + } +} + +bool KateDocument::isModified() const { + return modified; +} + +void KateDocument::readConfig() +{ + KConfig *config = KGlobal::config(); + config->setGroup("Kate Document"); + + myWordWrap = config->readBoolEntry("Word Wrap On", false); + myWordWrapAt = config->readNumEntry("Word Wrap At", 80); + if (myWordWrap) + wrapText (myWordWrapAt); + + setTabWidth(config->readNumEntry("TabWidth", 8)); + setUndoSteps(config->readNumEntry("UndoSteps", 50)); + m_singleSelection = config->readBoolEntry("SingleSelection", false); + myEncoding = config->readEntry("Encoding", QString::fromLatin1(QTextCodec::codecForLocale()->name())); + setFont (config->readFontEntry("Font", &myFont)); + + colors[0] = config->readColorEntry("Color Background", &colors[0]); + colors[1] = config->readColorEntry("Color Selected", &colors[1]); + + config->sync(); +} + +void KateDocument::writeConfig() +{ + KConfig *config = KGlobal::config(); + config->setGroup("Kate Document"); +#if 0 + cofig->writeEntry("Word Wrap On", myWordWrap); + config->writeEntry("Word Wrap At", myWordWrapAt); + config->writeEntry("TabWidth", tabChars); + config->writeEntry("UndoSteps", undoSteps); + config->writeEntry("SingleSelection", m_singleSelection); + config->writeEntry("Encoding", myEncoding); + config->writeEntry("Font", myFont); + config->writeEntry("Color Background", colors[0]); + config->writeEntry("Color Selected", colors[1]); +#endif + config->sync(); +} + +void KateDocument::readSessionConfig(KConfig *config) +{ + m_url = config->readEntry("URL"); // ### doesn't this break the encoding? (Simon) + setHighlight(hlManager->nameFind(config->readEntry("Highlight"))); + // anders: restore bookmarks if possible + QValueList l = config->readIntListEntry("Bookmarks"); + if ( l.count() ) { + for (uint i=0; i < l.count(); i++) { + if ( numLines() < l[i] ) break; + getTextLine( l[i] )->addMark( Bookmark ); + } + } +} + +void KateDocument::writeSessionConfig(KConfig *config) +{ +#if 0 + config->writeEntry("URL", m_url); // ### encoding?? (Simon) + config->writeEntry("Highlight", m_highlight->name()); + // anders: save bookmarks + QList l = marks(); + QValueList ml; + for (uint i=0; i < l.count(); i++) { + if ( l.at(i)->type == 1) // only save bookmarks + ml << l.at(i)->line; + } + if ( ml.count() ) + config->writeEntry("Bookmarks", ml); +#endif +} + + +void KateDocument::setHighlight(int n) { + Highlight *h; + +// hlNumber = n; + + h = hlManager->getHl(n); + if (h == m_highlight) { + updateLines(); + } else { + if (m_highlight != 0L) m_highlight->release(); + h->use(); + m_highlight = h; + makeAttribs(); + } + PreHighlightedTill=0; + RequestPreHighlightTill=0; + emit(highlightChanged()); +} + +void KateDocument::makeAttribs() { + qDebug("KateDocument::makeAttribs()"); + m_numAttribs = hlManager->makeAttribs(m_highlight, m_attribs, maxAttribs); + updateFontData(); + updateLines(); +} + +void KateDocument::updateFontData() { + int maxAscent, maxDescent; + int tabWidth; + KateView *view; + + maxAscent = myFontMetrics.ascent(); + maxDescent = myFontMetrics.descent(); + tabWidth = myFontMetrics.width(' '); + + fontHeight = maxAscent + maxDescent + 1; + fontAscent = maxAscent; + m_tabWidth = tabChars*tabWidth; + + for (view = views.first(); view != 0L; view = views.next() ) { + view->myViewInternal->drawBuffer->resize(view->width(),fontHeight); + view->tagAll(); + view->updateCursor(); + } +} + +void KateDocument::hlChanged() { //slot + makeAttribs(); + updateViews(); +} + + +void KateDocument::addView(KTextEditor::View *view) { + views.append( static_cast( view ) ); + KTextEditor::Document::addView( view ); + connect( static_cast( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) ); +} + +void KateDocument::removeView(KTextEditor::View *view) { +// if (undoView == view) recordReset(); + disconnect( static_cast( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) ); + views.removeRef( static_cast( view ) ); + KTextEditor::Document::removeView( view ); +} + +void KateDocument::slotViewDestroyed() +{ + views.removeRef( static_cast( sender() ) ); +} + +bool KateDocument::ownedView(KateView *view) { + // do we own the given view? + return (views.containsRef(view) > 0); +} + +bool KateDocument::isLastView(int numViews) { + return ((int) views.count() == numViews); +} + +int KateDocument::textWidth(const TextLine::Ptr &textLine, int cursorX) { + int x; + int z; + QChar ch; + Attribute *a; + + x = 0; + for (z = 0; z < cursorX; z++) { + ch = textLine->getChar(z); + a = &m_attribs[textLine->getAttr(z)]; + + if (ch == '\t') + x += m_tabWidth - (x % m_tabWidth); + else if (a->bold && a->italic) + x += myFontMetricsBI.width(ch); + else if (a->bold) + x += myFontMetricsBold.width(ch); + else if (a->italic) + x += myFontMetricsItalic.width(ch); + else + x += myFontMetrics.width(ch); + } + return x; +} + +int KateDocument::textWidth(PointStruc &cursor) { + if (cursor.x < 0) + cursor.x = 0; + if (cursor.y < 0) + cursor.y = 0; + if (cursor.y >= numLines()) + cursor.y = lastLine(); + return textWidth(getTextLine(cursor.y),cursor.x); +} + +int KateDocument::textWidth(bool wrapCursor, PointStruc &cursor, int xPos) { + int len; + int x, oldX; + int z; + QChar ch; + Attribute *a; + + if (cursor.y < 0) cursor.y = 0; + if (cursor.y > lastLine()) cursor.y = lastLine(); + TextLine::Ptr textLine = getTextLine(cursor.y); + len = textLine->length(); + + x = oldX = z = 0; + while (x < xPos && (!wrapCursor || z < len)) { + oldX = x; + ch = textLine->getChar(z); + a = &m_attribs[textLine->getAttr(z)]; + + if (ch == '\t') + x += m_tabWidth - (x % m_tabWidth); + else if (a->bold && a->italic) + x += myFontMetricsBI.width(ch); + else if (a->bold) + x += myFontMetricsBold.width(ch); + else if (a->italic) + x += myFontMetricsItalic.width(ch); + else + x += myFontMetrics.width(ch); + + z++; + } + if (xPos - oldX < x - xPos && z > 0) { + z--; + x = oldX; + } + cursor.x = z; + return x; +} + + +int KateDocument::textPos(const TextLine::Ptr &textLine, int xPos) { + int x, oldX; + int z; + QChar ch; + Attribute *a; + + x = oldX = z = 0; + while (x < xPos) { // && z < len) { + oldX = x; + ch = textLine->getChar(z); + a = &m_attribs[textLine->getAttr(z)]; + + if (ch == '\t') + x += m_tabWidth - (x % m_tabWidth); + else if (a->bold && a->italic) + x += myFontMetricsBI.width(ch); + else if (a->bold) + x += myFontMetricsBold.width(ch); + else if (a->italic) + x += myFontMetricsItalic.width(ch); + else + x += myFontMetrics.width(ch); + + z++; + } + if (xPos - oldX < x - xPos && z > 0) { + z--; + // newXPos = oldX; + }// else newXPos = x; + return z; +} + +int KateDocument::textWidth() { + return int(maxLength + 8); +} + +int KateDocument::textHeight() { + return numLines()*fontHeight; +} + +void KateDocument::insert(VConfig &c, const QString &s) { + int pos; + QChar ch; + QString buf; + + if (s.isEmpty()) return; + + recordStart(c, KateActionGroup::ugPaste); + + pos = 0; + if (!(c.flags & KateView::cfVerticalSelect)) { + do { + ch = s[pos]; + if (ch.isPrint() || ch == '\t') { + buf += ch; // append char to buffer + } else if (ch == '\n') { + recordAction(KateAction::newLine, c.cursor); // wrap contents behind cursor to new line + recordInsert(c, buf); // append to old line +// c.cursor.x += buf.length(); + buf.truncate(0); // clear buffer + c.cursor.y++; + c.cursor.x = 0; + } + pos++; + } while (pos < (int) s.length()); + } else { + int xPos; + + xPos = textWidth(c.cursor); + do { + ch = s[pos]; + if (ch.isPrint() || ch == '\t') { + buf += ch; + } else if (ch == '\n') { + recordInsert(c, buf); + c.cursor.x += buf.length(); + buf.truncate(0); + c.cursor.y++; + if (c.cursor.y >= numLines()) + recordAction(KateAction::insLine, c.cursor); + c.cursor.x = textPos(getTextLine(c.cursor.y), xPos); + } + pos++; + } while (pos < (int) s.length()); + } + recordInsert(c, buf); + c.cursor.x += buf.length(); + recordEnd(c); +} + +void KateDocument::insertFile(VConfig &c, QIODevice &dev) +{ + recordStart(c, KateActionGroup::ugPaste); + + QString buf; + QChar ch, last; + + QTextStream stream( &dev ); + + while ( !stream.atEnd() ) { + stream >> ch; + + if (ch.isPrint() || ch == '\t') { + buf += ch; + } else if (ch == '\n' || ch == '\r') { + if (last != '\r' || ch != '\n') { + recordAction(KateAction::newLine, c.cursor); + recordInsert(c, buf); + buf.truncate(0); + c.cursor.y++; + c.cursor.x = 0; + } + last = ch; + } + } + + recordInsert(c, buf); + recordEnd(c); +} + +int KateDocument::currentColumn(PointStruc &cursor) { + return getTextLine(cursor.y)->cursorX(cursor.x,tabChars); +} + +bool KateDocument::insertChars(VConfig &c, const QString &chars) { + int z, pos, l; + bool onlySpaces; + QChar ch; + QString buf; + + TextLine::Ptr textLine = getTextLine(c.cursor.y); + + pos = 0; + onlySpaces = true; + for (z = 0; z < (int) chars.length(); z++) { + ch = chars[z]; + if (ch == '\t' && c.flags & KateView::cfReplaceTabs) { + l = tabChars - (textLine->cursorX(c.cursor.x, tabChars) % tabChars); + while (l > 0) { + buf.insert(pos, ' '); + pos++; + l--; + } + } else if (ch.isPrint() || ch == '\t') { + buf.insert(pos, ch); + pos++; + if (ch != ' ') onlySpaces = false; + if (c.flags & KateView::cfAutoBrackets) { + if (ch == '(') buf.insert(pos, ')'); + if (ch == '[') buf.insert(pos, ']'); + if (ch == '{') buf.insert(pos, '}'); + } + } + } + //pos = cursor increment + + //return false if nothing has to be inserted + if (buf.isEmpty()) return false; + + //auto deletion of the marked text occurs not very often and can therefore + // be recorded separately + if (c.flags &KateView:: cfDelOnInput) delMarkedText(c); + + recordStart(c, KateActionGroup::ugInsChar); + recordReplace(c/*.cursor*/, (c.flags & KateView::cfOvr) ? buf.length() : 0, buf); + c.cursor.x += pos; + + if (myWordWrap && myWordWrapAt > 0) { + int line; + const QChar *s; +// int pos; + PointStruc actionCursor; + + line = c.cursor.y; + do { + textLine = getTextLine(line); + s = textLine->getText(); + l = textLine->length(); + for (z = myWordWrapAt; z < l; z++) if (!s[z].isSpace()) break; //search for text to wrap + if (z >= l) break; // nothing more to wrap + pos = myWordWrapAt; + for (; z >= 0; z--) { //find wrap position + if (s[z].isSpace()) { + pos = z + 1; + break; + } + } + //pos = wrap position + + if (line == c.cursor.y && pos <= c.cursor.x) { + //wrap cursor + c.cursor.y++; + c.cursor.x -= pos; + } + + if (line == lastLine() || (getTextLine(line+1)->length() == 0) ) { + //at end of doc: create new line + actionCursor.x = pos; + actionCursor.y = line; + recordAction(KateAction::newLine,actionCursor); + } else { + //wrap + actionCursor.y = line + 1; + if (!s[l - 1].isSpace()) { //add space in next line if necessary + actionCursor.x = 0; + recordInsert(actionCursor, " "); + } + actionCursor.x = textLine->length() - pos; + recordAction(KateAction::wordWrap, actionCursor); + } + line++; + } while (true); + } + recordEnd(c); + return true; +} + +QString tabString(int pos, int tabChars) { + QString s; + while (pos >= tabChars) { + s += '\t'; + pos -= tabChars; + } + while (pos > 0) { + s += ' '; + pos--; + } + return s; +} + +void KateDocument::newLine(VConfig &c) { + + //auto deletion of marked text is done by the view to have a more + // "low level" KateDocument::newLine method + recordStart(c, KateActionGroup::ugInsLine); + + if (!(c.flags & KateView::cfAutoIndent)) { + recordAction(KateAction::newLine,c.cursor); + c.cursor.y++; + c.cursor.x = 0; + } else { + TextLine::Ptr textLine = getTextLine(c.cursor.y); + int pos = textLine->firstChar(); + if (c.cursor.x < pos) c.cursor.x = pos; // place cursor on first char if before + + int y = c.cursor.y; + while ((y > 0) && (pos < 0)) { // search a not empty text line + textLine = getTextLine(--y); + pos = textLine->firstChar(); + } + recordAction(KateAction::newLine, c.cursor); + c.cursor.y++; + c.cursor.x = 0; + if (pos > 0) { + pos = textLine->cursorX(pos, tabChars); +// if (getTextLine(c.cursor.y)->length() > 0) { + QString s = tabString(pos, (c.flags & KateView::cfSpaceIndent) ? 0xffffff : tabChars); + recordInsert(c.cursor, s); + pos = s.length(); +// } +// recordInsert(c.cursor, QString(textLine->getText(), pos)); + c.cursor.x = pos; + } + } + + recordEnd(c); +} + +void KateDocument::killLine(VConfig &c) { + + recordStart(c, KateActionGroup::ugDelLine); + c.cursor.x = 0; + recordDelete(c.cursor, 0xffffff); + if (c.cursor.y < lastLine()) { + recordAction(KateAction::killLine, c.cursor); + } + recordEnd(c); +} + +void KateDocument::backspace(VConfig &c) { + + if (c.cursor.x <= 0 && c.cursor.y <= 0) return; + + if (c.cursor.x > 0) { + recordStart(c, KateActionGroup::ugDelChar); + if (!(c.flags & KateView::cfBackspaceIndents)) { + // ordinary backspace + c.cursor.x--; + recordDelete(c.cursor, 1); + } else { + // backspace indents: erase to next indent position + int l = 1; // del one char + + TextLine::Ptr textLine = getTextLine(c.cursor.y); + int pos = textLine->firstChar(); + if (pos < 0 || pos >= c.cursor.x) { + // only spaces on left side of cursor + // search a line with less spaces + int y = c.cursor.y; + while (y > 0) { + textLine = getTextLine(--y); + pos = textLine->firstChar(); + if (pos >= 0 && pos < c.cursor.x) { + l = c.cursor.x - pos; // del more chars + break; + } + } + } + // break effectively jumps here + c.cursor.x -= l; + recordDelete(c.cursor, l); + } + } else { + // c.cursor.x == 0: wrap to previous line + recordStart(c, KateActionGroup::ugDelLine); + c.cursor.y--; + c.cursor.x = getTextLine(c.cursor.y)->length(); + recordAction(KateAction::delLine,c.cursor); + } + recordEnd(c); +} + + +void KateDocument::del(VConfig &c) { + TextLine::Ptr textLine = getTextLine(c.cursor.y); + int len = (c.flags & KateView::cfRemoveSpaces) ? textLine->lastChar() : textLine->length(); + if (c.cursor.x < len/*getTextLine(c.cursor.y)->length()*/) { + // delete one character + recordStart(c, KateActionGroup::ugDelChar); + recordDelete(c.cursor, 1); + recordEnd(c); + } else { + if (c.cursor.y < lastLine()) { + // wrap next line to this line + textLine->truncate(c.cursor.x); // truncate spaces + recordStart(c, KateActionGroup::ugDelLine); + recordAction(KateAction::delLine,c.cursor); + recordEnd(c); + } + } +} + +void KateDocument::clear() { + PointStruc cursor; + KateView *view; + + setPseudoModal(0L); + cursor.x = cursor.y = 0; + for (view = views.first(); view != 0L; view = views.next() ) { + view->updateCursor(cursor); + view->tagAll(); + } + + eolMode = KateDocument::eolUnix; + + buffer->clear(); + longestLine = buffer->line(0); + + maxLength = 0; + + select.x = -1; + + selectStart = 0xffffff; + selectEnd = 0; + oldMarkState = false; + + setModified(false); + + undoList.clear(); + currentUndo = 0; + newUndo(); +} + +void KateDocument::cut(VConfig &c) { + + if (selectEnd < selectStart) return; + + copy(c.flags); + delMarkedText(c); +} + +void KateDocument::copy(int flags) { + + if (selectEnd < selectStart) return; + + QString s = markedText(flags); + if (!s.isEmpty()) { +//#if defined(_WS_X11_) + if (m_singleSelection) + disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), this, 0); +//#endif + QApplication::clipboard()->setText(s); +//#if defined(_WS_X11_) + if (m_singleSelection) { + connect(QApplication::clipboard(), SIGNAL(dataChanged()), + this, SLOT(clipboardChanged())); + } +//#endif + } +} + +void KateDocument::paste(VConfig &c) { + QString s = QApplication::clipboard()->text(); + if (!s.isEmpty()) { + insert(c, s); + } +} + +void KateDocument::toggleRect(int start, int end, int x1, int x2) { + int z, line; + bool t; + + if (x1 > x2) { + z = x1; + x1 = x2; + x2 = z; + } + if (start > end) { + z = start; + start = end; + end = z; + } + + t = false; + for (line = start; line < end; line++) { + int x, oldX, s, e, newX1, newX2; + QChar ch; + Attribute *a; + + TextLine::Ptr textLine = getTextLine(line); + + //--- speed optimization + //s = textPos(textLine, x1, newX1); + x = oldX = z = 0; + while (x < x1) { // && z < len) { + oldX = x; + ch = textLine->getChar(z); + a = &m_attribs[textLine->getAttr(z)]; + + if (ch == '\t') + x += m_tabWidth - (x % m_tabWidth); + else if (a->bold && a->italic) + x += myFontMetricsBI.width(ch); + else if (a->bold) + x += myFontMetricsBold.width(ch); + else if (a->italic) + x += myFontMetricsItalic.width(ch); + else + x += myFontMetrics.width(ch); + + z++; + } + s = z; + if (x1 - oldX < x - x1 && z > 0) { + s--; + newX1 = oldX; + } else newX1 = x; + //e = textPos(textLine, x2, newX2); + while (x < x2) { // && z < len) { + oldX = x; + ch = textLine->getChar(z); + a = &m_attribs[textLine->getAttr(z)]; + + if (ch == '\t') + x += m_tabWidth - (x % m_tabWidth); + else if (a->bold && a->italic) + x += myFontMetricsBI.width(ch); + else if (a->bold) + x += myFontMetricsBold.width(ch); + else if (a->italic) + x += myFontMetricsItalic.width(ch); + else + x += myFontMetrics.width(ch); + + z++; + } + e = z; + if (x2 - oldX < x - x2 && z > 0) { + e--; + newX2 = oldX; + } else newX2 = x; + //--- + + if (e > s) { + textLine->toggleSelect(s, e); + tagLineRange(line, newX1, newX2); + t = true; + } + } + if (t) { + end--; +// tagLines(start, end); + + if (start < selectStart) selectStart = start; + if (end > selectEnd) selectEnd = end; + emit selectionChanged(); + } +} + +void KateDocument::selectTo(VConfig &c, PointStruc &cursor, int cXPos) { + //c.cursor = old cursor position + //cursor = new cursor position + + if (c.cursor.x != select.x || c.cursor.y != select.y) { + //new selection + + if (!(c.flags & KateView::cfKeepSelection)) deselectAll(); +// else recordReset(); + + anchor = c.cursor; + aXPos = c.cXPos; + } + + if (!(c.flags & KateView::cfVerticalSelect)) { + //horizontal selections + int x, y, sXPos; + int ex, ey, eXPos; + bool sel; + + if (cursor.y > c.cursor.y || (cursor.y == c.cursor.y && cursor.x > c.cursor.x)) { + x = c.cursor.x; + y = c.cursor.y; + sXPos = c.cXPos; + ex = cursor.x; + ey = cursor.y; + eXPos = cXPos; + sel = true; + } else { + x = cursor.x; + y = cursor.y; + sXPos = cXPos; + ex = c.cursor.x; + ey = c.cursor.y; + eXPos = c.cXPos; + sel = false; + } + +// tagLines(y, ye); + if (y < ey) { + //tagLineRange(y, sXPos, 0xffffff); + tagLines(y, ey -1); + tagLineRange(ey, 0, eXPos); + } else tagLineRange(y, sXPos, eXPos); + + if (y < selectStart) selectStart = y; + if (ey > selectEnd) selectEnd = ey; + + TextLine::Ptr textLine = getTextLine(y); + + if (c.flags & KateView::cfXorSelect) { + //xor selection with old selection + while (y < ey) { + textLine->toggleSelectEol(x); + x = 0; + y++; + textLine = getTextLine(y); + } + textLine->toggleSelect(x, ex); + } else { + //set selection over old selection + + if (anchor.y > y || (anchor.y == y && anchor.x > x)) { + if (anchor.y < ey || (anchor.y == ey && anchor.x < ex)) { + sel = !sel; + while (y < anchor.y) { + textLine->selectEol(sel, x); + x = 0; + y++; + textLine = getTextLine(y); + } + textLine->select(sel, x, anchor.x); + x = anchor.x; + } + sel = !sel; + } + while (y < ey) { + textLine->selectEol(sel, x); + x = 0; + y++; + textLine = getTextLine(y); + } + textLine->select(sel, x, ex); + } + } else { + //vertical (block) selections +// int ax, sx, ex; + +// ax = textWidth(anchor); +// sx = textWidth(start); +// ex = textWidth(end); + + toggleRect(c.cursor.y + 1, cursor.y + 1, aXPos, c.cXPos); + toggleRect(anchor.y, cursor.y + 1, c.cXPos, cXPos); + } + select = cursor; + optimizeSelection(); + emit selectionChanged(); +} + + +void KateDocument::selectAll() { + int z; + TextLine::Ptr textLine; + + select.x = -1; + +// if (selectStart != 0 || selectEnd != lastLine()) recordReset(); + + selectStart = 0; + selectEnd = lastLine(); + + tagLines(selectStart,selectEnd); + + for (z = selectStart; z < selectEnd; z++) { + textLine = getTextLine(z); + textLine->selectEol(true,0); + } + textLine = getTextLine(z); + textLine->select(true,0,textLine->length()); + emit selectionChanged(); +} + +void KateDocument::deselectAll() { + select.x = -1; + if (selectEnd < selectStart) return; + +// recordReset(); + + tagLines(selectStart,selectEnd); + + for (int z = selectStart; z <= selectEnd; z++) { + TextLine::Ptr textLine = getTextLine(z); + textLine->selectEol(false,0); + } + selectStart = 0xffffff; + selectEnd = 0; + emit selectionChanged(); +} + +void KateDocument::invertSelection() { + TextLine::Ptr textLine; + + select.x = -1; + +// if (selectStart != 0 || selectEnd != lastLine()) recordReset(); + + selectStart = 0; + selectEnd = lastLine(); + + tagLines(selectStart,selectEnd); + + for (int z = selectStart; z < selectEnd; z++) { + textLine = getTextLine(z); + textLine->toggleSelectEol(0); + } + textLine = getTextLine(selectEnd); + textLine->toggleSelect(0,textLine->length()); + optimizeSelection(); + emit selectionChanged(); +} + +void KateDocument::selectWord(PointStruc &cursor, int flags) { + int start, end, len; + + TextLine::Ptr textLine = getTextLine(cursor.y); + len = textLine->length(); + start = end = cursor.x; + while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--; + while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++; + if (end <= start) return; + if (!(flags & KateView::cfKeepSelection)) deselectAll(); +// else recordReset(); + + textLine->select(true, start, end); + + anchor.x = start; + select.x = end; + anchor.y = select.y = cursor.y; + tagLines(cursor.y, cursor.y); + if (cursor.y < selectStart) selectStart = cursor.y; + if (cursor.y > selectEnd) selectEnd = cursor.y; + emit selectionChanged(); +} + +void KateDocument::selectLength(PointStruc &cursor, int length, int flags) { + int start, end; + + TextLine::Ptr textLine = getTextLine(cursor.y); + start = cursor.x; + end = start + length; + if (end <= start) return; + if (!(flags & KateView::cfKeepSelection)) deselectAll(); + + textLine->select(true, start, end); + + anchor.x = start; + select.x = end; + anchor.y = select.y = cursor.y; + tagLines(cursor.y, cursor.y); + if (cursor.y < selectStart) selectStart = cursor.y; + if (cursor.y > selectEnd) selectEnd = cursor.y; + emit selectionChanged(); +} + +void KateDocument::doIndent(VConfig &c, int change) { + + c.cursor.x = 0; + + recordStart(c, (change < 0) ? KateActionGroup::ugUnindent + : KateActionGroup::ugIndent); + + if (selectEnd < selectStart) { + // single line + optimizeLeadingSpace(c.cursor.y, c.flags, change); + } else { + // entire selection + TextLine::Ptr textLine; + int line, z; + QChar ch; + + if (c.flags & KateView::cfKeepIndentProfile && change < 0) { + // unindent so that the existing indent profile doesn´t get screwed + // if any line we may unindent is already full left, don't do anything + for (line = selectStart; line <= selectEnd; line++) { + textLine = getTextLine(line); + if (textLine->isSelected() || textLine->numSelected()) { + for (z = 0; z < tabChars; z++) { + ch = textLine->getChar(z); + if (ch == '\t') break; + if (ch != ' ') { + change = 0; + goto jumpOut; + } + } + } + } + jumpOut:; + } + + for (line = selectStart; line <= selectEnd; line++) { + textLine = getTextLine(line); + if (textLine->isSelected() || textLine->numSelected()) { + optimizeLeadingSpace(line, c.flags, change); + } + } + } + // recordEnd now removes empty undo records + recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent); +} + +/* + Optimize the leading whitespace for a single line. + If change is > 0, it adds indentation units (tabChars) + if change is == 0, it only optimizes + If change is < 0, it removes indentation units + This will be used to indent, unindent, and optimal-fill a line. + If excess space is removed depends on the flag cfKeepExtraSpaces + which has to be set by the user +*/ +void KateDocument::optimizeLeadingSpace(int line, int flags, int change) { + int len; + int chars, space, okLen; + QChar ch; + int extra; + QString s; + PointStruc cursor; + + TextLine::Ptr textLine = getTextLine(line); + len = textLine->length(); + space = 0; // length of space at the beginning of the textline + okLen = 0; // length of space which does not have to be replaced + for (chars = 0; chars < len; chars++) { + ch = textLine->getChar(chars); + if (ch == ' ') { + space++; + if (flags & KateView::cfSpaceIndent && okLen == chars) okLen++; + } else if (ch == '\t') { + space += tabChars - space % tabChars; + if (!(flags & KateView::cfSpaceIndent) && okLen == chars) okLen++; + } else break; + } + + space += change*tabChars; // modify space width + // if line contains only spaces it will be cleared + if (space < 0 || chars == len) space = 0; + + extra = space % tabChars; // extra spaces which don´t fit the indentation pattern + if (flags & KateView::cfKeepExtraSpaces) chars -= extra; + + if (flags & KateView::cfSpaceIndent) { + space -= extra; + ch = ' '; + } else { + space /= tabChars; + ch = '\t'; + } + + // don´t replace chars which are already ok + cursor.x = QMIN(okLen, QMIN(chars, space)); + chars -= cursor.x; + space -= cursor.x; + if (chars == 0 && space == 0) return; //nothing to do + + s.fill(ch, space); + +//printf("chars %d insert %d cursor.x %d\n", chars, insert, cursor.x); + cursor.y = line; + recordReplace(cursor, chars, s); +} + +void KateDocument::doComment(VConfig &c, int change) +{ + c.flags |=KateView:: cfPersistent; + + recordStart(c, (change < 0) ? KateActionGroup::ugUncomment + : KateActionGroup::ugComment); + + QString startComment = m_highlight->getCommentStart(); + QString startLineComment = m_highlight->getCommentSingleLineStart(); + QString endComment = m_highlight->getCommentEnd(); + + int startCommentLen = startComment.length(); + int startLineCommentLen = startLineComment.length(); + int endCommentLen = endComment.length(); + + if (change > 0) + { + if ( !hasMarkedText() ) + { + if (startLineComment != "") + { + // Add a start comment mark + c.cursor.x = 0; + recordReplace(c.cursor, 0, startLineComment); + } + else if ((startComment != "") && (endComment != "")) + { + // Add a start comment mark + c.cursor.x = 0; + recordReplace(c.cursor, 0, startComment); + + // Add an end comment mark + TextLine* textline = getTextLine(c.cursor.y); + c.cursor.x = textline->length(); + recordReplace(c.cursor, 0, endComment); + c.cursor.x = 0; + } + } + else if ((startComment != "") && (endComment != "")) + { + QString marked (c.view->markedText ()); + int preDeleteLine = -1, preDeleteCol = -1; + c.view->getCursorPosition (&preDeleteLine, &preDeleteCol); + + if (marked.length() > 0) + c.view->keyDelete (); + + int line = -1, col = -1; + c.view->getCursorPosition (&line, &col); + + c.view->insertText (startComment + marked + endComment); + } + } + else + { + if ( !hasMarkedText() ) + { + TextLine* textline = getTextLine(c.cursor.y); + + if(textline->startingWith(startLineComment)) + { + // Remove start comment mark + c.cursor.x = 0; + recordReplace(c.cursor, startLineCommentLen, ""); + } + else if (textline->startingWith(startComment) && textline->endingWith(endComment)) + { + // Remove start comment mark + c.cursor.x = 0; + recordReplace(c.cursor, startCommentLen, ""); + + // Remove end comment mark + if(endComment != "") + { + c.cursor.x = textline->length() - endCommentLen; + recordReplace(c.cursor, endCommentLen, ""); + c.cursor.x = 0; + } + } + } + else + { + QString marked (c.view->markedText ()); + int preDeleteLine = -1, preDeleteCol = -1; + c.view->getCursorPosition (&preDeleteLine, &preDeleteCol); + + int start = marked.find (startComment); + int end = marked.findRev (endComment); + + if ((start > -1) && (end > -1)) + { + marked.remove (start, startCommentLen); + marked.remove (end-startCommentLen, endCommentLen); + + c.view->keyDelete (); + + int line = -1, col = -1; + c.view->getCursorPosition (&line, &col); + c.view->insertText (marked); + } + } + } + + recordEnd(c.view, c.cursor, c.flags | KateView::cfPersistent); +} + + +QString KateDocument::text() const +{ + QString s; + + for (int i=0; i < buffer->count(); i++) + { + TextLine::Ptr textLine = buffer->line(i); + s.insert(s.length(), textLine->getText(), textLine->length()); + if ( (i < (buffer->count()-1)) ) + s.append('\n'); + } + + return s; +} + +QString KateDocument::getWord(PointStruc &cursor) { + int start, end, len; + + TextLine::Ptr textLine = getTextLine(cursor.y); + len = textLine->length(); + start = end = cursor.x; + while (start > 0 && m_highlight->isInWord(textLine->getChar(start - 1))) start--; + while (end < len && m_highlight->isInWord(textLine->getChar(end))) end++; + len = end - start; + return QString(&textLine->getText()[start], len); +} + +void KateDocument::setText(const QString &s) { + int pos; + QChar ch; + + clear(); + + int line=1; + + TextLine::Ptr textLine = buffer->line(0); + for (pos = 0; pos <= (int) s.length(); pos++) { + ch = s[pos]; + if (ch.isPrint() || ch == '\t') { + textLine->append(&ch, 1); + } else if (ch == '\n') + { + textLine = new TextLine(); + buffer->insertLine (line, textLine); + line++; + } + } + updateLines(); +} + + +QString KateDocument::markedText(int flags) { + TextLine::Ptr textLine; + int len, z, start, end, i; + + len = 1; + if (!(flags & KateView::cfVerticalSelect)) { + for (z = selectStart; z <= selectEnd; z++) { + textLine = getTextLine(z); + len += textLine->numSelected(); + if (textLine->isSelected()) len++; + } + QString s; + len = 0; + for (z = selectStart; z <= selectEnd; z++) { + textLine = getTextLine(z); + end = 0; + do { + start = textLine->findUnselected(end); + end = textLine->findSelected(start); + for (i = start; i < end; i++) { + s[len] = textLine->getChar(i); + len++; + } + } while (start < end); + if (textLine->isSelected()) { + s[len] = '\n'; + len++; + } + } +// s[len] = '\0'; + return s; + } else { + for (z = selectStart; z <= selectEnd; z++) { + textLine = getTextLine(z); + len += textLine->numSelected() + 1; + } + QString s; + len = 0; + for (z = selectStart; z <= selectEnd; z++) { + textLine = getTextLine(z); + end = 0; + do { + start = textLine->findUnselected(end); + end = textLine->findSelected(start); + for (i = start; i < end; i++) { + s[len] = textLine->getChar(i); + len++; + } + } while (start < end); + s[len] = '\n'; + len++; + } +// s[len] = '\0'; // the final \0 is not counted in length() + return s; + } +} + +void KateDocument::delMarkedText(VConfig &c/*, bool undo*/) { + int end = 0; + + if (selectEnd < selectStart) return; + + // the caller may have already started an undo record for the current action +// if (undo) + + //auto deletion of the marked text occurs not very often and can therefore + // be recorded separately + recordStart(c, KateActionGroup::ugDelBlock); + + for (c.cursor.y = selectEnd; c.cursor.y >= selectStart; c.cursor.y--) { + TextLine::Ptr textLine = getTextLine(c.cursor.y); + + c.cursor.x = textLine->length(); + do { + end = textLine->findRevUnselected(c.cursor.x); + if (end == 0) break; + c.cursor.x = textLine->findRevSelected(end); + recordDelete(c.cursor, end - c.cursor.x); + } while (true); + end = c.cursor.x; + c.cursor.x = textLine->length(); + if (textLine->isSelected()) recordAction(KateAction::delLine,c.cursor); + } + c.cursor.y++; + /*if (end < c.cursor.x)*/ c.cursor.x = end; + + selectEnd = -1; + select.x = -1; + + /*if (undo)*/ recordEnd(c); +} + +void KateDocument::tagLineRange(int line, int x1, int x2) { + int z; + + for (z = 0; z < (int) views.count(); z++) { + views.at(z)->tagLines(line, line, x1, x2); + } +} + +void KateDocument::tagLines(int start, int end) { + int z; + + for (z = 0; z < (int) views.count(); z++) { + views.at(z)->tagLines(start, end, 0, 0xffffff); + } +} + +void KateDocument::tagAll() { + int z; + + for (z = 0; z < (int) views.count(); z++) { + views.at(z)->tagAll(); + } +} + +void KateDocument::updateLines(int startLine, int endLine, int flags, int cursorY) { + TextLine::Ptr textLine; + int line, last_line; + int ctxNum, endCtx; +// kdDebug(13020)<<"******************KateDocument::updateLines Checkpoint 1"<line(startLine)==0) {kdDebug(13020)<<"********************No buffer for line " << startLine << " found**************"<= last_line) endLine = last_line; + + line = startLine; + ctxNum = 0; + if (line > 0) ctxNum = getTextLine(line - 1)->getContext(); + do { +// kdDebug(13020)<> error textLine==0"<removeSpaces(); + updateMaxLength(textLine); + } + endCtx = textLine->getContext(); + qDebug("DOHIGHLIGHT"); + ctxNum = m_highlight->doHighlight(ctxNum,textLine); + textLine->setContext(ctxNum); + line++; + } while ((buffer->line(line)!=0) && (line <= endLine || endCtx != ctxNum)); +// kdDebug(13020)<<"updateLines :: while loop left"<length()); + + if (len > maxLength) { + longestLine = textLine; + maxLength = len; + newDocGeometry = true; + } else { + if (!longestLine || (textLine == longestLine && len <= maxLength*3/4)) { + maxLength = -1; + for (int i = 0; i < numLines();i++) { + textLine = getTextLine(i); + len = textWidth(textLine,textLine->length()); + if (len > maxLength) { + maxLength = len; + longestLine = textLine; + } + } + newDocGeometry = true; + } + } +} + +void KateDocument::slotBufferChanged() { + newDocGeometry = true; + //updateLines();//JW + updateViews(); +} + +void KateDocument::slotBufferHighlight(long start,long stop) { + kdDebug(13020)<<"KateDocument::slotBufferHighlight"<startLoadTimer(); +} + +void KateDocument::updateViews(KateView *exclude) { + KateView *view; + int flags; + bool markState = hasMarkedText(); + + flags = (newDocGeometry) ? KateView::ufDocGeometry : 0; + for (view = views.first(); view != 0L; view = views.next() ) { + if (view != exclude) view->updateView(flags); + + // notify every view about the changed mark state.... + if (oldMarkState != markState) emit view->newMarkStatus(); + } + oldMarkState = markState; + newDocGeometry = false; +} + +QColor &KateDocument::cursorCol(int x, int y) { + int attr; + Attribute *a; + + TextLine::Ptr textLine = getTextLine(y); + attr = textLine->getRawAttr(x); + a = &m_attribs[attr & taAttrMask]; + if (attr & taSelected) return a->selCol; else return a->col; +} + +void KateDocument::paintTextLine(QPainter &paint, int line, int xStart, int xEnd, bool showTabs) +{ + paintTextLine (paint, line, 0, xStart, xEnd, showTabs); +} + +void KateDocument::paintTextLine(QPainter &paint, int line, int y, int xStart, int xEnd, bool showTabs) +{ + TextLine::Ptr textLine; + int len; + const QChar *s; + int z, x; + QChar ch; + Attribute *a = 0L; + int attr, nextAttr; + int xs; + int xc, zc; + + if (line > lastLine()) { + paint.fillRect(0, y, xEnd - xStart,fontHeight, colors[0]); + return; + } + + textLine = getTextLine(line); + len = textLine->length(); + s = textLine->getText(); + + // skip to first visible character + x = 0; + z = 0; + do { + xc = x; + zc = z; + if (z == len) break; + ch = s[z];//textLine->getChar(z); + if (ch == '\t') { + x += m_tabWidth - (x % m_tabWidth); + } else { + a = &m_attribs[textLine->getAttr(z)]; + + if (a->bold && a->italic) + x += myFontMetricsBI.width(ch); + else if (a->bold) + x += myFontMetricsBold.width(ch); + else if (a->italic) + x += myFontMetricsItalic.width(ch); + else + x += myFontMetrics.width(ch); + } + z++; + } while (x <= xStart); + + // draw background + xs = xStart; + attr = textLine->getRawAttr(zc); + while (x < xEnd) + { + nextAttr = textLine->getRawAttr(z); + if ((nextAttr ^ attr) & taSelected) + { + if (attr & taSelected) + paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[1]); + else + paint.fillRect(xs - xStart, y, x - xs, fontHeight, colors[0]); + + xs = x; + attr = nextAttr; + } + + if (z == len) break; + + ch = s[z];//textLine->getChar(z); + + if (ch == '\t') + x += m_tabWidth - (x % m_tabWidth); + else + { + a = &m_attribs[textLine->getAttr(z)]; + + if (a->bold && a->italic) + x += myFontMetricsBI.width(ch); + else if (a->bold) + x += myFontMetricsBold.width(ch); + else if (a->italic) + x += myFontMetricsItalic.width(ch); + else + x += myFontMetrics.width(ch); + } + z++; + } + + if (attr & taSelected) + paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[1]); + else + paint.fillRect(xs - xStart, y, xEnd - xs, fontHeight, colors[0]); + + len = z; //reduce length to visible length + + // draw text + x = xc; + z = zc; + y += fontAscent;// -1; + attr = -1; + while (z < len) { + ch = s[z];//textLine->getChar(z); + if (ch == '\t') { + if (z > zc) { + //this should cause no copy at all + QConstString str((QChar *) &s[zc], z - zc /*+1*/); + QString s = str.string(); + paint.drawText(x - xStart, y, s); + + if (a->bold && a->italic) + x += myFontMetricsBI.width(s); + else if (a->bold) + x += myFontMetricsBold.width(s); + else if (a->italic) + x += myFontMetricsItalic.width(s); + else + x += myFontMetrics.width(s); + } + zc = z +1; + + if (showTabs) { + nextAttr = textLine->getRawAttr(z); + if (nextAttr != attr) { + attr = nextAttr; + a = &m_attribs[attr & taAttrMask]; + + if (attr & taSelected) paint.setPen(a->selCol); + else paint.setPen(a->col); + + if (a->bold && a->italic) + paint.setFont(myFontBI); + else if (a->bold) + paint.setFont(myFontBold); + else if (a->italic) + paint.setFont(myFontItalic); + else + paint.setFont(myFont); + } + +// paint.drawLine(x - xStart, y -2, x - xStart, y); +// paint.drawLine(x - xStart, y, x - xStart + 2, y); + paint.drawPoint(x - xStart, y); + paint.drawPoint(x - xStart +1, y); + paint.drawPoint(x - xStart, y -1); + } + x += m_tabWidth - (x % m_tabWidth); + } else { + nextAttr = textLine->getRawAttr(z); + if (nextAttr != attr) { + if (z > zc) { + QConstString str((QChar *) &s[zc], z - zc /*+1*/); + QString s = str.string(); + paint.drawText(x - xStart, y, s); + + if (a->bold && a->italic) + x += myFontMetricsBI.width(s); + else if (a->bold) + x += myFontMetricsBold.width(s); + else if (a->italic) + x += myFontMetricsItalic.width(s); + else + x += myFontMetrics.width(s); + zc = z; + } + attr = nextAttr; + a = &m_attribs[attr & taAttrMask]; + + if (attr & taSelected) paint.setPen(a->selCol); + else paint.setPen(a->col); + + if (a->bold && a->italic) + paint.setFont(myFontBI); + else if (a->bold) + paint.setFont(myFontBold); + else if (a->italic) + paint.setFont(myFontItalic); + else + paint.setFont(myFont); + } + } + z++; + } + if (z > zc) { + QConstString str((QChar *) &s[zc], z - zc /*+1*/); + paint.drawText(x - xStart, y, str.string()); + } +} + +// Applies the search context, and returns whether a match was found. If one is, +// the length of the string matched is also returned. +bool KateDocument::doSearch(SConfig &sc, const QString &searchFor) { + int line, col; + int searchEnd; + int bufLen, tlen; + QChar *t; + TextLine::Ptr textLine; + int pos, newPos; + + if (searchFor.isEmpty()) return false; + + bufLen = 0; + t = 0L; + + line = sc.cursor.y; + col = sc.cursor.x; + if (!(sc.flags & KateView::sfBackward)) { + //forward search + if (sc.flags & KateView::sfSelected) { + if (line < selectStart) { + line = selectStart; + col = 0; + } + searchEnd = selectEnd; + } else searchEnd = lastLine(); + + while (line <= searchEnd) { + textLine = getTextLine(line); + tlen = textLine->length(); + if (tlen > bufLen) { + delete t; + bufLen = (tlen + 255) & (~255); + t = new QChar[bufLen]; + } + memcpy(t, textLine->getText(), tlen*sizeof(QChar)); + if (sc.flags & KateView::sfSelected) { + pos = 0; + do { + pos = textLine->findSelected(pos); + newPos = textLine->findUnselected(pos); + memset(&t[pos], 0, (newPos - pos)*sizeof(QChar)); + pos = newPos; + } while (pos < tlen); + } + + QString text(t, tlen); + if (sc.flags & KateView::sfWholeWords) { + // Until the end of the line... + while (col < tlen) { + // ...find the next match. + col = sc.search(text, col); + if (col != -1) { + // Is the match delimited correctly? + if (((col == 0) || (!m_highlight->isInWord(t[col]))) && + ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) { + goto found; + } + else { + // Start again from the next character. + col++; + } + } + else { + // No match. + break; + } + } + } + else { + // Non-whole-word search. + col = sc.search(text, col); + if (col != -1) + goto found; + } + col = 0; + line++; + } + } else { + // backward search + if (sc.flags & KateView::sfSelected) { + if (line > selectEnd) { + line = selectEnd; + col = -1; + } + searchEnd = selectStart; + } else searchEnd = 0; + + while (line >= searchEnd) { + textLine = getTextLine(line); + tlen = textLine->length(); + if (tlen > bufLen) { + delete t; + bufLen = (tlen + 255) & (~255); + t = new QChar[bufLen]; + } + memcpy(t, textLine->getText(), tlen*sizeof(QChar)); + if (sc.flags & KateView::sfSelected) { + pos = 0; + do { + pos = textLine->findSelected(pos); + newPos = textLine->findUnselected(pos); + memset(&t[pos], 0, (newPos - pos)*sizeof(QChar)); + pos = newPos; + } while (pos < tlen); + } + + if (col < 0 || col > tlen) col = tlen; + + QString text(t, tlen); + if (sc.flags & KateView::sfWholeWords) { + // Until the beginning of the line... + while (col >= 0) { + // ...find the next match. + col = sc.search(text, col); + if (col != -1) { + // Is the match delimited correctly? + if (((col == 0) || (!m_highlight->isInWord(t[col]))) && + ((col + sc.matchedLength == tlen) || (!m_highlight->isInWord(t[col + sc.matchedLength])))) { + goto found; + } + else { + // Start again from the previous character. + col--; + } + } + else { + // No match. + break; + } + } + } + else { + // Non-whole-word search. + col = sc.search(text, col); + if (col != -1) + goto found; + } + col = -1; + line--; + } + } + sc.flags |= KateView::sfWrapped; + return false; +found: + if (sc.flags & KateView::sfWrapped) { + if ((line > sc.startCursor.y || (line == sc.startCursor.y && col >= sc.startCursor.x)) + ^ ((sc.flags & KateView::sfBackward) != 0)) return false; + } + sc.cursor.x = col; + sc.cursor.y = line; + return true; +} + +void KateDocument::tagLine(int line) { + + if (tagStart > line) tagStart = line; + if (tagEnd < line) tagEnd = line; +} + +void KateDocument::insLine(int line) { + KateView *view; + + if (selectStart >= line) selectStart++; + if (selectEnd >= line) selectEnd++; + if (tagStart >= line) tagStart++; + if (tagEnd >= line) tagEnd++; + + newDocGeometry = true; + for (view = views.first(); view != 0L; view = views.next() ) { + view->insLine(line); + } +} + +void KateDocument::delLine(int line) { + KateView *view; + + if (selectStart >= line && selectStart > 0) selectStart--; + if (selectEnd >= line) selectEnd--; + if (tagStart >= line && tagStart > 0) tagStart--; + if (tagEnd >= line) tagEnd--; + + newDocGeometry = true; + for (view = views.first(); view != 0L; view = views.next() ) { + view->delLine(line); + } +} + +void KateDocument::optimizeSelection() { + TextLine::Ptr textLine; + + while (selectStart <= selectEnd) { + textLine = getTextLine(selectStart); + if (textLine->isSelected() || textLine->numSelected() > 0) break; + selectStart++; + } + while (selectEnd >= selectStart) { + textLine = getTextLine(selectEnd); + if (textLine->isSelected() || textLine->numSelected() > 0) break; + selectEnd--; + } + if (selectStart > selectEnd) { + selectStart = 0xffffff; + selectEnd = 0; + } +} + +void KateDocument::doAction(KateAction *a) { + + switch (a->action) { + case KateAction::replace: + doReplace(a); + break; + case KateAction::wordWrap: + doWordWrap(a); + break; + case KateAction::wordUnWrap: + doWordUnWrap(a); + break; + case KateAction::newLine: + doNewLine(a); + break; + case KateAction::delLine: + doDelLine(a); + break; + case KateAction::insLine: + doInsLine(a); + break; + case KateAction::killLine: + doKillLine(a); + break; +/* case KateAction::doubleLine: + break; + case KateAction::removeLine: + break;*/ + } +} + +void KateDocument::doReplace(KateAction *a) { + TextLine::Ptr textLine; + int l; + + //exchange current text with stored text in KateAction *a + + textLine = getTextLine(a->cursor.y); + l = textLine->length() - a->cursor.x; + if (l > a->len) l = a->len; + + QString oldText(&textLine->getText()[a->cursor.x], (l < 0) ? 0 : l); + textLine->replace(a->cursor.x, a->len, a->text.unicode(), a->text.length()); + + a->len = a->text.length(); + a->text = oldText; + + buffer->changeLine(a->cursor.y); + + tagLine(a->cursor.y); +} + +void KateDocument::doWordWrap(KateAction *a) { + TextLine::Ptr textLine; + + textLine = getTextLine(a->cursor.y - 1); + a->len = textLine->length() - a->cursor.x; + textLine->wrap(getTextLine(a->cursor.y),a->len); + + buffer->changeLine(a->cursor.y - 1); + buffer->changeLine(a->cursor.y); + + tagLine(a->cursor.y - 1); + tagLine(a->cursor.y); + if (selectEnd == a->cursor.y - 1) selectEnd++; + + a->action = KateAction::wordUnWrap; +} + +void KateDocument::doWordUnWrap(KateAction *a) { + TextLine::Ptr textLine; + + textLine = getTextLine(a->cursor.y - 1); +// textLine->setLength(a->len); + textLine->unWrap(a->len, getTextLine(a->cursor.y),a->cursor.x); + + buffer->changeLine(a->cursor.y - 1); + buffer->changeLine(a->cursor.y); + + tagLine(a->cursor.y - 1); + tagLine(a->cursor.y); + + a->action = KateAction::wordWrap; +} + +void KateDocument::doNewLine(KateAction *a) { + TextLine::Ptr textLine, newLine; + + textLine = getTextLine(a->cursor.y); + newLine = new TextLine(textLine->getRawAttr(), textLine->getContext()); + textLine->wrap(newLine,a->cursor.x); + + buffer->insertLine(a->cursor.y + 1, newLine); + buffer->changeLine(a->cursor.y); + + insLine(a->cursor.y + 1); + tagLine(a->cursor.y); + tagLine(a->cursor.y + 1); + if (selectEnd == a->cursor.y) selectEnd++;//addSelection(a->cursor.y + 1); + + a->action = KateAction::delLine; +} + +void KateDocument::doDelLine(KateAction *a) { + TextLine::Ptr textLine, nextLine; + + textLine = getTextLine(a->cursor.y); + nextLine = getTextLine(a->cursor.y+1); +// textLine->setLength(a->cursor.x); + textLine->unWrap(a->cursor.x, nextLine,nextLine->length()); + textLine->setContext(nextLine->getContext()); + if (longestLine == nextLine) longestLine = 0L; + + buffer->changeLine(a->cursor.y); + buffer->removeLine(a->cursor.y+1); + + tagLine(a->cursor.y); + delLine(a->cursor.y + 1); + + a->action = KateAction::newLine; +} + +void KateDocument::doInsLine(KateAction *a) { + + buffer->insertLine(a->cursor.y, new TextLine()); + + insLine(a->cursor.y); + + a->action = KateAction::killLine; +} + +void KateDocument::doKillLine(KateAction *a) { + TextLine::Ptr textLine = getTextLine(a->cursor.y); + if (longestLine == textLine) longestLine = 0L; + + buffer->removeLine(a->cursor.y); + + delLine(a->cursor.y); + tagLine(a->cursor.y); + + a->action = KateAction::insLine; +} + +void KateDocument::newUndo() { + KTextEditor::View *view; + int state; + + state = 0; + if (currentUndo > 0) state |= 1; + if (currentUndo < (int) undoList.count()) state |= 2; + undoState = state; + for (view = m_views.first(); view != 0L; view = m_views.next() ) { + emit static_cast( view )->newUndo(); + } +} + +void KateDocument::recordStart(VConfig &c, int newUndoType) { + recordStart(c.view, c.cursor, c.flags, newUndoType); +} + +void KateDocument::recordStart(KateView *, PointStruc &cursor, int flags, + int newUndoType, bool keepModal, bool mergeUndo) { + + KateActionGroup *g; + +// if (newUndoType == KateActionGroup::ugNone) { + // only a bug would cause this +//why should someone do this? we can't prevent all programming errors :) (jochen whilhelmy) +// debug("KateDocument::recordStart() called with no undo group type!"); +// return; +// } + + if (!keepModal) setPseudoModal(0L); + + //i optimized the group undo stuff a bit (jochen wilhelmy) + // recordReset() is not needed any more + g = undoList.getLast(); + if (g != 0L && ((undoCount < 1024 && flags & KateView::cfGroupUndo + && g->end.x == cursor.x && g->end.y == cursor.y) || mergeUndo)) { + + //undo grouping : same actions are put into one undo step + //precondition : new action starts where old stops or mergeUndo flag + if (g->undoType == newUndoType + || (g->undoType == KateActionGroup::ugInsChar + && newUndoType == KateActionGroup::ugInsLine) + || (g->undoType == KateActionGroup::ugDelChar + && newUndoType == KateActionGroup::ugDelLine)) { + + undoCount++; + if (g->undoType != newUndoType) undoCount = 0xffffff; + return; + } + } + undoCount = 0; +/* + if (undoView != view) { + // always kill the current undo group if the editing view changes + recordReset(); + undoType = newUndoType; + } else if (newUndoType == undoType) { +printf("bla!!!\n"); + // same as current type, keep using it + return; + } else if ( (undoType == KateActionGroup::ugInsChar && newUndoType == KateActionGroup::ugInsLine) || + (undoType == KateActionGroup::ugDelChar && newUndoType == KateActionGroup::ugDelLine) ) { + // some type combinations can run together... + undoType += 1000; + return; + } else { + recordReset(); + undoType = newUndoType; + } + + undoView = view; +*/ + while ((int) undoList.count() > currentUndo) undoList.removeLast(); + while ((int) undoList.count() > undoSteps) { + undoList.removeFirst(); + currentUndo--; + } + + g = new KateActionGroup(cursor, newUndoType); + undoList.append(g); +// currentUndo++; + + tagEnd = 0; + tagStart = 0xffffff; +} + +void KateDocument::recordAction(KateAction::Action action, PointStruc &cursor) { + KateAction *a; + + a = new KateAction(action, cursor); + doAction(a); + undoList.getLast()->insertAction(a); +} + +void KateDocument::recordInsert(VConfig &c, const QString &text) { + recordReplace(c, 0, text); +} + +void KateDocument::recordReplace(VConfig &c, int len, const QString &text) { + if (c.cursor.x > 0 && !(c.flags & KateView::cfSpaceIndent)) { + TextLine::Ptr textLine = getTextLine(c.cursor.y); + if (textLine->length() == 0) { + QString s = tabString(c.cursor.x, tabChars); + int len = s.length(); + s += text; + c.cursor.x = 0; + recordReplace(c.cursor, len, s); + c.cursor.x = len; + return; + } + } + recordReplace(c.cursor, len, text); +} + +void KateDocument::recordInsert(PointStruc &cursor, const QString &text) { + recordReplace(cursor, 0, text); +} + +void KateDocument::recordDelete(PointStruc &cursor, int len) { + recordReplace(cursor, len, QString::null); +} + +void KateDocument::recordReplace(PointStruc &cursor, int len, const QString &text) { + KateAction *a; + TextLine::Ptr textLine; + int l; + + if (len == 0 && text.isEmpty()) return; + + //try to append to last replace action + a = undoList.getLast()->action; + if (a == 0L || a->action != KateAction::replace + || a->cursor.x + a->len != cursor.x || a->cursor.y != cursor.y) { + +//if (a != 0L) printf("new %d %d\n", a->cursor.x + a->len, cursor.x); + a = new KateAction(KateAction::replace, cursor); + undoList.getLast()->insertAction(a); + } + + //replace + textLine = getTextLine(cursor.y); + l = textLine->length() - cursor.x; + if (l > len) l = len; + a->text.insert(a->text.length(), &textLine->getText()[cursor.x], (l < 0) ? 0 : l); + textLine->replace(cursor.x, len, text.unicode(), text.length()); + a->len += text.length(); + + buffer->changeLine(a->cursor.y); + updateMaxLength(textLine); + tagLine(a->cursor.y); +} + +void KateDocument::recordEnd(VConfig &c) { + recordEnd(c.view, c.cursor, c.flags); +} + +void KateDocument::recordEnd(KateView *view, PointStruc &cursor, int flags) { + KateActionGroup *g; + + // clear selection if option "persistent selections" is off +// if (!(flags & cfPersistent)) deselectAll(); + + g = undoList.getLast(); + if (g->action == 0L) { + // no action has been done: remove empty undo record + undoList.removeLast(); + return; + } + // store end cursor position for redo + g->end = cursor; + currentUndo = undoList.count(); + + if (tagStart <= tagEnd) { + optimizeSelection(); + updateLines(tagStart, tagEnd, flags, cursor.y); + setModified(true); + } + + view->updateCursor(cursor, flags); + +// newUndo(); +/* + undoCount++; + // we limit the number of individual undo operations for sanity - is 1K reasonable? + // this is also where we handle non-group undo preference + // if the undo type is singlular, we always finish it now + if ( undoType == KateActionGroup::ugPaste || + undoType == KateActionGroup::ugDelBlock || + undoType > 1000 || + undoCount > 1024 || !(flags & cfGroupUndo) ) { +printf("recordend %d %d\n", undoType, undoCount); + recordReset(); + } +*/ + + // this should keep the flood of signals down a little... + if (undoCount == 0) newUndo(); + emit textChanged(); +} +/* +void KateDocument::recordReset() +{ + if (pseudoModal) + return; + + // forces the next call of recordStart() to begin a new undo group + // not used in normal editing, but used by markFound(), etc. + undoType = KateActionGroup::ugNone; + undoCount = 0; + undoView = NULL; + undoReported = false; +printf("recordreset\n"); +} +*/ + +/* +void KateDocument::recordDel(PointStruc &cursor, TextLine::Ptr &textLine, int l) { + int len; + + len = textLine->length() - cursor.x; + if (len > l) len = l; + if (len > 0) { + insertUndo(new KateAction(KateAction::replace,cursor,&textLine->getText()[cursor.x],len)); + } +} +*/ + + +void KateDocument::doActionGroup(KateActionGroup *g, int flags, bool undo) { + KateAction *a, *next; + + setPseudoModal(0L); + if (!(flags & KateView::cfPersistent)) deselectAll(); + tagEnd = 0; + tagStart = 0xffffff; + + a = g->action; + g->action = 0L; + while (a) { + doAction(a); + next = a->next; + g->insertAction(a); + a = next; + } + optimizeSelection(); + if (tagStart <= tagEnd) updateLines(tagStart, tagEnd, flags); + + // the undo/redo functions set undo to true, all others should leave it + // alone (default) + if (!undo) { + setModified(true); + newUndo(); + } +} + +int KateDocument::nextUndoType() +{ + KateActionGroup *g; + + if (currentUndo <= 0) return KateActionGroup::ugNone; + g = undoList.at(currentUndo - 1); + return g->undoType; +} + +int KateDocument::nextRedoType() +{ + KateActionGroup *g; + + if (currentUndo >= (int) undoList.count()) return KateActionGroup::ugNone; + g = undoList.at(currentUndo); +// if (!g) return KateActionGroup::ugNone; + return g->undoType; +} + +void KateDocument::undoTypeList(QValueList &lst) +{ + lst.clear(); + for (int i = currentUndo-1; i>=0 ;i--) + lst.append(undoList.at(i)->undoType); +} + +void KateDocument::redoTypeList(QValueList &lst) +{ + lst.clear(); + for (int i = currentUndo+1; i<(int)undoList.count(); i++) + lst.append(undoList.at(i)->undoType); +} + +void KateDocument::undo(VConfig &c, int count) { + KateActionGroup *g = 0L; + int num; + bool needUpdate = false; // don't update the cursor until completely done + + if (count <= 0) return; + + for (num = 0 ; num < count ; num++) { + if (currentUndo <= 0) break; + currentUndo--; + g = undoList.at(currentUndo); + doActionGroup(g, c.flags, true); // do not setModified() or newUndo() + needUpdate = true; + +// if (num == 0) recordReset(); + } + + if (needUpdate) { + // since we told doActionGroup() not to do this stuff, we need to do it now + c.view->updateCursor(g->start); + setModified(true); + newUndo(); + } +} + +void KateDocument::redo(VConfig &c, int count) { + KateActionGroup *g = 0L; + int num; + bool needUpdate = false; // don't update the cursor until completely done + + if (count <= 0) return; + + for (num = 0 ; num < count ; num++) { + if (currentUndo+1 > (int)undoList.count()) break; + g = undoList.at(currentUndo); + currentUndo++; + doActionGroup(g, c.flags, true); // do not setModified() or newUndo() + needUpdate = true; + +// if (num == 0) recordReset(); + } + + if (needUpdate) { + // since we told doActionGroup() not to do this stuff, we need to do it now + c.view->updateCursor(g->end); + setModified(true); + newUndo(); + } +} + +void KateDocument::clearRedo() { + // disable redos + // this was added as an assist to the spell checker + bool deleted = false; + + while ((int) undoList.count() > currentUndo) { + deleted = true; + undoList.removeLast(); + } + + if (deleted) newUndo(); +} + +void KateDocument::setUndoSteps(int steps) { + if (steps < 5) steps = 5; + undoSteps = steps; +} + +void KateDocument::setPseudoModal(QWidget *w) { +// QWidget *old = pseudoModal; + + // (glenebob) + // this is a temporary hack to make the spell checker work a little + // better - as kspell progresses, this sort of thing should become + // obsolete or worked around more cleanly + // this is relied upon *only* by the spell-check code + if (pseudoModal && pseudoModal != (QWidget*)1L) + delete pseudoModal; + +// pseudoModal = 0L; +// if (old || w) recordReset(); + + pseudoModal = w; +} + + +void KateDocument::newBracketMark(PointStruc &cursor, BracketMark &bm) +{ + TextLine::Ptr textLine; + int x, line, count, attr; + QChar bracket, opposite, ch; + Attribute *a; + + bm.eXPos = -1; //mark bracked mark as invalid + x = cursor.x -1; // -1 to look at left side of cursor + if (x < 0) return; + line = cursor.y; //current line + count = 0; //bracket counter for nested brackets + + textLine = getTextLine(line); + if (!textLine) return; + + bracket = textLine->getChar(x); + attr = textLine->getAttr(x); + + if (bracket == '(' || bracket == '[' || bracket == '{') + { + //get opposite bracket + opposite = ')'; + if (bracket == '[') opposite = ']'; + if (bracket == '{') opposite = '}'; + //get attribute of bracket (opposite bracket must have the same attribute) + x++; + while (line - cursor.y < 40) { + //go to next line on end of line + while (x >= (int) textLine->length()) { + line++; + if (line > lastLine()) return; + textLine = getTextLine(line); + x = 0; + } + if (textLine->getAttr(x) == attr) { + //try to find opposite bracked + ch = textLine->getChar(x); + if (ch == bracket) count++; //same bracket : increase counter + if (ch == opposite) { + count--; + if (count < 0) goto found; + } + } + x++; + } + } + else if (bracket == ')' || bracket == ']' || bracket == '}') + { + opposite = '('; + if (bracket == ']') opposite = '['; + if (bracket == '}') opposite = '{'; + x--; + while (cursor.y - line < 20) { + + while (x < 0) { + line--; + if (line < 0) return; + textLine = getTextLine(line); + x = textLine->length() -1; + } + if (textLine->getAttr(x) == attr) { + ch = textLine->getChar(x); + if (ch == bracket) count++; + if (ch == opposite) { + count--; + if (count < 0) goto found; + } + } + x--; + } + } + return; + +found: + //cursor position of opposite bracket + bm.cursor.x = x; + bm.cursor.y = line; + //x position (start and end) of related bracket + bm.sXPos = textWidth(textLine, x); + a = &m_attribs[attr]; + + if (a->bold && a->italic) + bm.eXPos = bm.sXPos + myFontMetricsBI.width(bracket); + else if (a->bold) + bm.eXPos = bm.sXPos + myFontMetricsBold.width(bracket); + else if (a->italic) + bm.eXPos = bm.sXPos + myFontMetricsItalic.width(bracket); + else + bm.eXPos = bm.sXPos + myFontMetrics.width(bracket); +} + +void KateDocument::clipboardChanged() { //slot +//#if defined(_WS_X11_) + if (m_singleSelection) { + disconnect(QApplication::clipboard(), SIGNAL(dataChanged()), + this, SLOT(clipboardChanged())); + deselectAll(); + updateViews(); + } +//#endif +} + +#if 0 +void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev ) +{ + KParts::ReadWritePart::guiActivateEvent( ev ); + if ( ev->activated() ) + emit selectionChanged(); +} +#endif + +void KateDocument::setDocName (QString docName) +{ + myDocName = docName; + emit nameChanged (this); +} + +void KateDocument::setMTime() +{ + if (fileInfo && !fileInfo->fileName().isEmpty()) { + fileInfo->refresh(); + mTime = fileInfo->lastModified(); + } +} + +void KateDocument::isModOnHD(bool forceReload) +{ + if (fileInfo && !fileInfo->fileName().isEmpty()) { + fileInfo->refresh(); + if (fileInfo->lastModified() > mTime) { + if ( forceReload || + (KMessageBox::warningContinueCancel(0, + (i18n("The file %1 has changed on disk.\nDo you want to reload it?\n\nIf you cancel you will lose these changes next time you save this file")).arg(m_url), + i18n("File has changed on Disk"), + i18n("Yes") ) == KMessageBox::Continue) + ) + reloadFile(); + else + setMTime(); + } + } +} + +void KateDocument::reloadFile() +{ +#warning fixme +#if 0 + if (fileInfo && !fileInfo->fileName().isEmpty()) { + KateDocument::openFile(); + setMTime(); + } +#endif +} + +void KateDocument::slotModChanged() +{ + emit modStateChanged (this); +} + +QList KateDocument::marks () +{ + QList list; + TextLine::Ptr line; + + for (int i=0; i < numLines(); i++) + { + line = getTextLine(i); + if (line->mark() != 0) + { + Kate::Mark *mark=new Kate::Mark; + mark->line = i; + mark->type = line->mark(); + list.append (mark); + } + } + + return list; +} + +void KateDocument::flush () +{ + if (isReadOnly()) + return; + + m_url = QString::null; + fileInfo->setFile (QString()); + setMTime(); + + clear(); + updateViews(); + + emit fileNameChanged (); +} + +void KateDocument::open (const QString &name) +{ + openURL (name); +} + +void KateDocument::wrapText (uint col) +{ + int line = 0; + int z = 0; + + while(true) + { + TextLine::Ptr l = getTextLine(line); + + if (l->length() > col) + { + TextLine::Ptr tl = new TextLine(); + buffer->insertLine(line+1,tl); + const QChar *text = l->getText(); + + for (z=col; z>0; z--) + { + if (z < 1) break; + if (text[z].isSpace()) break; + } + + if (z < 1) z=col; + + l->wrap (tl, z); + } + + line++; + if (line >= numLines()) break; + }; + + newDocGeometry=true; + updateLines(); + updateViews(); +} + +void KateDocument::setWordWrap (bool on) +{ + if (on != myWordWrap && on) + wrapText (myWordWrapAt); + + myWordWrap = on; +} + +void KateDocument::setWordWrapAt (uint col) +{ + if (myWordWrapAt != col && myWordWrap) + wrapText (myWordWrapAt); + + myWordWrapAt = col; +} + +void KateDocument::applyWordWrap () +{ + wrapText (myWordWrapAt); +} diff --git a/noncore/apps/tinykate/libkate/document/katedocument.h b/noncore/apps/tinykate/libkate/document/katedocument.h new file mode 100644 index 0000000..220d188 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katedocument.h @@ -0,0 +1,569 @@ +/*************************************************************************** + katedocument.h - description + ------------------- + begin : Mon Jan 15 2001 + copyright : (C) 2001 by Christoph "Crossfire" Cullmann + (C) 2002 by Joseph Wenninger + email : crossfire@babylon2k.de + jowenn@kde.org + +***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* + Copyright (C) 1998, 1999 Jochen Wilhelmy + digisnap@cs.tu-berlin.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef kate_document_h +#define kate_document_h + + +#include +#include +#include +#include +#include +#include +#include + +#include "../view/kateview.h" +#include "katehighlight.h" +#include "katebuffer.h" +#include "katetextline.h" + + +#include + +class KateCmd; + +class CachedFontMetrics : public QFontMetrics { +private: + short *warray[256]; +public: + CachedFontMetrics(const QFont& f) : QFontMetrics(f) { + for (int i=0; i<256; i++) warray[i]=0; + } + ~CachedFontMetrics() { + for (int i=0; i<256; i++) + if (warray[i]) delete[] warray[i]; + } + int width(QChar c) { + uchar cell=c.cell(); + uchar row=c.row(); + short *wa=warray[row]; + if (!wa) { + // qDebug("create row: %d",row); + wa=warray[row]=new short[256]; + for (int i=0; i<256; i++) wa[i]=-1; + } + if (wa[cell]<0) wa[cell]=(short) QFontMetrics::width(c); + return (int)wa[cell]; + } + int width(QString s) { return QFontMetrics::width(s); } +}; + +class Attribute { + public: + Attribute() { ; }; + + QColor col; + QColor selCol; + bool bold; + bool italic; +}; + +class KateAction { + public: + enum Action {replace, wordWrap, wordUnWrap, newLine, delLine, + insLine, killLine};//, doubleLine, removeLine}; + + KateAction(Action, PointStruc &cursor, int len = 0, + const QString &text = QString::null); + + Action action; + PointStruc cursor; + int len; + QString text; + KateAction *next; +}; + +class KateActionGroup { + public: + // the undo group types + enum { ugNone, // + ugPaste, // paste + ugDelBlock, // delete/replace selected text + ugIndent, // indent + ugUnindent, // unindent + ugComment, // comment + ugUncomment, // uncomment + ugReplace, // text search/replace + ugSpell, // spell check + ugInsChar, // char type/deleting + ugDelChar, // '' '' + ugInsLine, // line insert/delete + ugDelLine // '' '' + }; + + KateActionGroup(PointStruc &aStart, int type = ugNone); + ~KateActionGroup(); + void insertAction(KateAction *); + + static const char * typeName(int type); + + PointStruc start; + PointStruc end; + KateAction *action; + int undoType; +}; + +/** + The text document. It contains the textlines, controls the + document changing operations and does undo/redo. WARNING: do not change + the text contents directly in methods where this is not explicitly + permitted. All changes have to be made with some basic operations, + which are recorded by the undo/redo system. + @see TextLine + @author Jochen Wilhelmy +*/ +class KateDocument: public Kate::Document +{ + Q_OBJECT + friend class KateViewInternal; + friend class KateView; + friend class KateIconBorder; + + public: + KateDocument(bool bSingleViewMode=false, bool bBrowserView=false, QWidget *parentWidget = 0, const char *widgetName = 0, QObject * = 0, const char * = 0); + ~KateDocument(); + + protected: + QFont myFont, myFontBold, myFontItalic, myFontBI; + CachedFontMetrics myFontMetrics, myFontMetricsBold, myFontMetricsItalic, myFontMetricsBI; + + public: + void setFont (QFont font); + QFont getFont () { return myFont; }; + CachedFontMetrics getFontMetrics () { return myFontMetrics; }; + + virtual bool saveFile(); + + virtual KTextEditor::View *createView( QWidget *parent, const char *name ); + virtual QString textLine( int line ) const; + + virtual void insertLine( const QString &s, int line = -1 ); + + void insert_Line(const QString& s,int line=-1, bool update=true); + void remove_Line(int line,bool update=true); + void replaceLine(const QString& s,int line=-1); + virtual void insertAt( const QString &s, int line, int col, bool mark = FALSE ); + virtual void removeLine( int line ); + virtual int length() const; + + virtual void setSelection( int row_from, int col_from, int row_to, int col_t ); + virtual bool hasSelection() const; + virtual QString selection() const; + + // only to make part work, don't change it ! + bool m_bSingleViewMode; + +// public interface + /** + * gets the number of lines + */ + virtual int numLines() const; + + /** + * gets the last line number (numLines() -1) + */ + int lastLine() const {return numLines()-1;} + + /** + gets the given line + @return the TextLine object at the given line + @see TextLine + */ + TextLine::Ptr getTextLine(int line) const; + + /** + get the length in pixels of the given line + */ + int textLength(int line); + + void setTabWidth(int); + int tabWidth() {return tabChars;} + void setReadOnly(bool); + bool isReadOnly() const; + void setNewDoc( bool ); + bool isNewDoc() const; + virtual void setReadWrite( bool ){}; + virtual bool isReadWrite() const {return true;} + virtual void setModified(bool); + virtual bool isModified() const; + void setSingleSelection(bool ss) {m_singleSelection = ss;} + bool singleSelection() {return m_singleSelection;} + + void readConfig(); + void writeConfig(); + void readSessionConfig(KConfig *); + void writeSessionConfig(KConfig *); + + bool hasBrowserExtension() const { return m_bBrowserView; } + + protected: + bool m_bBrowserView; + + signals: + void selectionChanged(); + void highlightChanged(); + void modifiedChanged (); + void preHighlightChanged(long); + + // search stuff + protected: + static QStringList searchForList; + static QStringList replaceWithList; + static uint uniqueID; + + // highlight stuff + public: + Highlight *highlight() {return m_highlight;} + int highlightNum() {return hlManager->findHl(m_highlight);} + int numAttribs() {return m_numAttribs;} + Attribute *attribs() {return m_attribs;} + void setDontChangeHlOnSave(); + + protected: + void setHighlight(int n); + void makeAttribs(); + void updateFontData(); + + protected slots: + void hlChanged(); + +// view interaction + public: + virtual void addView(KTextEditor::View *); + virtual void removeView(KTextEditor::View *); + bool ownedView(KateView *); + bool isLastView(int numViews); + + int getTextLineCount() {return numLines();} + + int textWidth(const TextLine::Ptr &, int cursorX); + int textWidth(PointStruc &cursor); + int textWidth(bool wrapCursor, PointStruc &cursor, int xPos); + int textPos(const TextLine::Ptr &, int xPos); +// int textPos(TextLine::Ptr &, int xPos, int &newXPos); + int textWidth(); + int textHeight(); + + void insert(VConfig &, const QString &); + void insertFile(VConfig &, QIODevice &); + + int currentColumn(PointStruc &cursor); + bool insertChars(VConfig &, const QString &chars); + void newLine(VConfig &); + void killLine(VConfig &); + void backspace(VConfig &); + void del(VConfig &); + void clear(); + void cut(VConfig &); + void copy(int flags); + void paste(VConfig &); + + void toggleRect(int, int, int, int); + void selectTo(VConfig &c, PointStruc &cursor, int cXPos); + void selectAll(); + void deselectAll(); + void invertSelection(); + void selectWord(PointStruc &cursor, int flags); + void selectLength(PointStruc &cursor, int length, int flags); + + void indent(VConfig &c) {doIndent(c, 1);} + void unIndent(VConfig &c) {doIndent(c, -1);} + void cleanIndent(VConfig &c) {doIndent(c, 0);} + // called by indent/unIndent/cleanIndent + // just does some setup and then calls optimizeLeadingSpace() + void doIndent(VConfig &, int change); + // optimize leading whitespace on a single line - see kwdoc.cpp for full description + void optimizeLeadingSpace(int line, int flags, int change); + + void comment(VConfig &c) {doComment(c, 1);} + void unComment(VConfig &c) {doComment(c, -1);} + void doComment(VConfig &, int change); + + virtual QString text() const; + QString getWord(PointStruc &cursor); + + public slots: + virtual void setText(const QString &); + + public: + long needPreHighlight(long till); + bool hasMarkedText() {return (selectEnd >= selectStart);} + QString markedText(int flags); + void delMarkedText(VConfig &/*, bool undo = true*/); + + void tagLineRange(int line, int x1, int x2); + void tagLines(int start, int end); + void tagAll(); + void updateLines(int startLine = 0, int endLine = 0xffffff, int flags = 0, int cursorY = -1); + void updateMaxLength(TextLine::Ptr &); + void updateViews(KateView *exclude = 0L); + + QColor &cursorCol(int x, int y); + void paintTextLine(QPainter &, int line, int xStart, int xEnd, bool showTabs); + void paintTextLine(QPainter &, int line, int y, int xStart, int xEnd, bool showTabs); + + bool doSearch(SConfig &s, const QString &searchFor); + +// internal + void tagLine(int line); + void insLine(int line); + void delLine(int line); + void optimizeSelection(); + + void doAction(KateAction *); + void doReplace(KateAction *); + void doWordWrap(KateAction *); + void doWordUnWrap(KateAction *); + void doNewLine(KateAction *); + void doDelLine(KateAction *); + void doInsLine(KateAction *); + void doKillLine(KateAction *); + void newUndo(); + + void recordStart(VConfig &, int newUndoType); + void recordStart(KateView *, PointStruc &, int flags, int newUndoType, bool keepModal = false, bool mergeUndo = false); + void recordAction(KateAction::Action, PointStruc &); + void recordInsert(VConfig &, const QString &text); + void recordReplace(VConfig &, int len, const QString &text); + void recordInsert(PointStruc &, const QString &text); + void recordDelete(PointStruc &, int len); + void recordReplace(PointStruc &, int len, const QString &text); + void recordEnd(VConfig &); + void recordEnd(KateView *, PointStruc &, int flags); + void doActionGroup(KateActionGroup *, int flags, bool undo = false); + + int nextUndoType(); + int nextRedoType(); + void undoTypeList(QValueList &lst); + void redoTypeList(QValueList &lst); + void undo(VConfig &, int count = 1); + void redo(VConfig &, int count = 1); + void clearRedo(); + void setUndoSteps(int steps); + + void setPseudoModal(QWidget *); + + void newBracketMark(PointStruc &, BracketMark &); + + + protected slots: + void clipboardChanged(); + void slotBufferChanged(); + void slotBufferHighlight(long,long); + void doPreHighlight(); + + private slots: + void slotViewDestroyed(); + +// member variables + protected: + long PreHighlightedTill; + long RequestPreHighlightTill; + KWBuffer *buffer; + QColor colors[2]; + HlManager *hlManager; + Highlight *m_highlight; + int m_numAttribs; + static const int maxAttribs; + Attribute *m_attribs; + + int eolMode; + + int tabChars; + int m_tabWidth; + int fontHeight; + int fontAscent; + + QList views; + bool newDocGeometry; + + TextLine::Ptr longestLine; + float maxLength; + + PointStruc select; + PointStruc anchor; + int aXPos; + int selectStart; + int selectEnd; + bool oldMarkState; + bool m_singleSelection; // false: windows-like, true: X11-like + + bool readOnly; + bool newDoc; // True if the file is a new document (used to determine whether + // to check for overwriting files on save) + bool modified; + + bool myWordWrap; + uint myWordWrapAt; + + QList undoList; + int currentUndo; + int undoState; + int undoSteps; + int tagStart; + int tagEnd; + int undoCount; //counts merged undo steps + + QWidget *pseudoModal; //the replace prompt is pseudo modal + + public: + /** Tjecks if the file on disk is newer than document contents. + If forceReload is true, the document is reloaded without asking the user, + otherwise [default] the user is asked what to do. */ + void isModOnHD(bool forceReload=false); + + uint docID () {return myDocID;}; + QString docName () {return myDocName;}; + + void setDocName (QString docName); + + public slots: + /** Reloads the current document from disk if possible */ + void reloadFile(); + + private slots: + void slotModChanged (); + + private: + /** updates mTime to reflect file on fs. + called from constructor and from saveFile. */ + void setMTime(); + uint myDocID; + QFileInfo* fileInfo; + QDateTime mTime; + QString myDocName; + + QString m_url; + QString m_file; + void openURL(const QString &filename); + private: + KateCmd *myCmd; + + public: + KateCmd *cmd () { return myCmd; }; + + private: + QString myEncoding; + + public: + void setEncoding (QString e) { myEncoding = e; }; + QString encoding() { return myEncoding; }; + + void setWordWrap (bool on); + bool wordWrap () { return myWordWrap; }; + + void setWordWrapAt (uint col); + uint wordWrapAt () { return myWordWrapAt; }; + + signals: + void modStateChanged (KateDocument *doc); + void nameChanged (KateDocument *doc); + + public: + QList marks (); + + public slots: + // clear buffer/filename - update the views + void flush (); + + signals: + /** + The file has been saved (perhaps the name has changed). The main window + can use this to change its caption + */ + void fileNameChanged (); + + public: + //end of line settings + enum Eol_settings {eolUnix=0,eolDos=1,eolMacintosh=2}; + + // for the DCOP interface + public: + void open (const QString &name=0); + + public: + // wrap the text of the document at the column col + void wrapText (uint col); + + public slots: + void applyWordWrap (); + + private: + + class KateDocPrivate + { + public: + bool hlSetByUser; + }; + + +// BCI: Add a real d-pointer in the next BIC release +static QPtrDict* d_ptr; +static void cleanup_d_ptr() + { + delete d_ptr; + } + +KateDocPrivate* d( const KateDocument* foo ) + { + if ( !d_ptr ) { + d_ptr = new QPtrDict; + //qAddPostRoutine( cleanup_d_ptr ); + } + KateDocPrivate* ret = d_ptr->find( (void*) foo ); + if ( ! ret ) { + ret = new KateDocPrivate; + d_ptr->replace( (void*) foo, ret ); + } + return ret; + } + +void delete_d( const KateDocument* foo ) + { + if ( d_ptr ) + d_ptr->remove( (void*) foo ); + } + +}; + +#endif + + diff --git a/noncore/apps/tinykate/libkate/document/katedocumentIface.h b/noncore/apps/tinykate/libkate/document/katedocumentIface.h new file mode 100644 index 0000000..51c7506 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katedocumentIface.h @@ -0,0 +1,32 @@ +/*************************************************************************** + katedocumentIface.h - description + ------------------- + copyright : (C) 2001 by The Kate Team + (C) 2002 by Joseph Wenninger + email : kwrite-devel@kde.org + jowenn@kde.org + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef _KATEDOCUMENT_IFACE_H_ +#define _KATEDOCUMENT_IFACE_H_ + +#include + +class KateDocumentDCOPIface : virtual public DCOPObject +{ + K_DCOP + + k_dcop: + virtual void open (const QString &name=0)=0; +}; +#endif + diff --git a/noncore/apps/tinykate/libkate/document/katehighlight.cpp b/noncore/apps/tinykate/libkate/document/katehighlight.cpp new file mode 100644 index 0000000..797968b --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katehighlight.cpp @@ -0,0 +1,1459 @@ +/* + Copyright (C) 1998, 1999 Jochen Wilhelmy + digisnap@cs.tu-berlin.de + (C) 2002, 2001 The Kate Team + (C) 2002 Joseph Wenninger + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +//#include +//#include +#include +//#include +#include +#include +#include + +#include "katehighlight.h" + + +#include "katetextline.h" +#include "katedocument.h" +#include "katesyntaxdocument.h" + + +HlManager *HlManager::s_pSelf = 0; + +enum Item_styles { dsNormal,dsKeyword,dsDataType,dsDecVal,dsBaseN,dsFloat,dsChar,dsString,dsComment,dsOthers}; + +static bool trueBool = true; +static QString stdDeliminator = QString ("!%&()*+,-./:;<=>?[]^{|}~ \t\\"); + +int getDefStyleNum(QString name) +{ + if (name=="dsNormal") return dsNormal; + if (name=="dsKeyword") return dsKeyword; + if (name=="dsDataType") return dsDataType; + if (name=="dsDecVal") return dsDecVal; + if (name=="dsBaseN") return dsBaseN; + if (name=="dsFloat") return dsFloat; + if (name=="dsChar") return dsChar; + if (name=="dsString") return dsString; + if (name=="dsComment") return dsComment; + if (name=="dsOthers") return dsOthers; + + return dsNormal; +} + +bool ustrchr(const QChar *s, uint len, QChar c) +{ + for (int z=0; z < len; z++) + { + if (*s == c) return true; + s++; + } + + return false; +} + +HlItem::HlItem(int attribute, int context) + : attr(attribute), ctx(context) {subItems=0; +} + +HlItem::~HlItem() +{ + //kdDebug(13010)<<"In hlItem::~HlItem()"<setAutoDelete(true); subItems->clear(); delete subItems;} +} + +bool HlItem::startEnable(QChar c) +{ + return true; +} + +HlCharDetect::HlCharDetect(int attribute, int context, QChar c) + : HlItem(attribute,context), sChar(c) { +} + +const QChar *HlCharDetect::checkHgl(const QChar *str, int len, bool) { + if (*str == sChar) return str + 1; + return 0L; +} + +Hl2CharDetect::Hl2CharDetect(int attribute, int context, QChar ch1, QChar ch2) + : HlItem(attribute,context) { + sChar1 = ch1; + sChar2 = ch2; +} + +const QChar *Hl2CharDetect::checkHgl(const QChar *str, int len, bool) { + if (str[0] == sChar1 && str[1] == sChar2) return str + 2; + return 0L; +} + +HlStringDetect::HlStringDetect(int attribute, int context, const QString &s, bool inSensitive) + : HlItem(attribute, context), str(inSensitive ? s.upper():s), _inSensitive(inSensitive) { +} + +HlStringDetect::~HlStringDetect() { +} + +const QChar *HlStringDetect::checkHgl(const QChar *s, int len, bool) { + if (!_inSensitive) {if (memcmp(s, str.unicode(), str.length()*sizeof(QChar)) == 0) return s + str.length();} + else + { + QString tmp=QString(s,str.length()).upper(); + if (tmp==str) return s+str.length(); + } + return 0L; +} + + +HlRangeDetect::HlRangeDetect(int attribute, int context, QChar ch1, QChar ch2) + : HlItem(attribute,context) { + sChar1 = ch1; + sChar2 = ch2; +} + +const QChar *HlRangeDetect::checkHgl(const QChar *s, int len, bool) { + if (*s == sChar1) + { + do + { + s++; + len--; + if (len == 0) return 0L; + } + while (*s != sChar2); + + return s + 1; + } + return 0L; +} + +HlKeyword::HlKeyword (int attribute, int context,bool casesensitive, const QChar *deliminator, uint deliLen) + : HlItem(attribute,context), dict (113, casesensitive) +{ + deliminatorChars = deliminator; + deliminatorLen = deliLen; + _caseSensitive=casesensitive; +} + +HlKeyword::~HlKeyword() { +} + +bool HlKeyword::startEnable(QChar c) +{ + return ustrchr(deliminatorChars, deliminatorLen, c); +} + +// If we use a dictionary for lookup we don't really need +// an item as such we are using the key to lookup +void HlKeyword::addWord(const QString &word) +{ + words.append(word); + dict.insert(word,&trueBool); +} + +void HlKeyword::addList(const QStringList& list) +{ + + words+=list; + for(uint i=0;i 0) && (!ustrchr(deliminatorChars, deliminatorLen, *s2)) ) + { + s2++; + len--; + } + + if (s2 == s) return 0L; + + QString lookup = QString(s,s2-s); + + if ( dict.find(lookup) ) return s2; + return 0L; +} + +HlInt::HlInt(int attribute, int context) + : HlItem(attribute,context) { +} + +const QChar *HlInt::checkHgl(const QChar *str, int len, bool) { + const QChar *s,*s1; + + s = str; + while (s->isDigit()) s++; + if (s > str) + { + if (subItems) + { + for (HlItem *it=subItems->first();it;it=subItems->next()) + { + s1=it->checkHgl(s, len, false); + if (s1) return s1; + } + } + return s; + } + return 0L; +} + +HlFloat::HlFloat(int attribute, int context) + : HlItem(attribute,context) { +} + +const QChar *HlFloat::checkHgl(const QChar *s, int len, bool) { + bool b, p; + const QChar *s1; + + b = false; + while (s->isDigit()){ + s++; + b = true; + } + if (p = (*s == '.')) { + s++; + while (s->isDigit()) { + s++; + b = true; + } + } + if (!b) return 0L; + if ((*s&0xdf) == 'E') s++; + else + if (!p) return 0L; + else + { + if (subItems) + { + for (HlItem *it=subItems->first();it;it=subItems->next()) + { + s1=it->checkHgl(s, len, false); + if (s1) return s1; + } + } + return s; + } + if ((*s == '-')||(*s =='+')) s++; + b = false; + while (s->isDigit()) { + s++; + b = true; + } + if (b) + { + if (subItems) + { + for (HlItem *it=subItems->first();it;it=subItems->next()) + { + s1=it->checkHgl(s, len, false); + if (s1) return s1; + } + } + return s; + } + else return 0L; +} + + +HlCInt::HlCInt(int attribute, int context) + : HlInt(attribute,context) { +} + +const QChar *HlCInt::checkHgl(const QChar *s, int len, bool lineStart) { + +// if (*s == '0') s++; else s = HlInt::checkHgl(s); + s = HlInt::checkHgl(s, len, lineStart); + if (s != 0L) { + int l = 0; + int u = 0; + const QChar *str; + + do { + str = s; + if ((*s&0xdf) == 'L' ) { + l++; + if (l > 2) return 0L; + s++; + } + if ((*s&0xdf) == 'U' ){ + u++; + if (u > 1) return 0L; + s++; + } + } while (s != str); + } + return s; +} + +HlCOct::HlCOct(int attribute, int context) + : HlItem(attribute,context) { +} + +const QChar *HlCOct::checkHgl(const QChar *str, int len, bool) { + const QChar *s; + + if (*str == '0') { + str++; + s = str; + while (*s >= '0' && *s <= '7') s++; + if (s > str) { + if ((*s&0xdf) == 'L' || (*s&0xdf) == 'U' ) s++; + return s; + } + } + return 0L; +} + +HlCHex::HlCHex(int attribute, int context) + : HlItem(attribute,context) { +} + +const QChar *HlCHex::checkHgl(const QChar *str, int len, bool) { + const QChar *s=str; +#if 0 + int i; + for (i=0;(*s)!='\0';s++,i++); + QString line(str,i); + QRegExp3 rx("0[xX][a-fA-F\\d]+[UuLl]?"); // this matches but is also matching parenthesis + int pos=rx.search(line,0); + if(pos > -1) return str+rx.matchedLength(); + else + return 0L; + +#else + if (str[0] == '0' && ((str[1]&0xdf) == 'X' )) { + str += 2; + s = str; + while (s->isDigit() || ((*s&0xdf) >= 'A' && (*s&0xdf) <= 'F') /*|| (*s >= 'a' && *s <= 'f')*/) s++; + if (s > str) { + if ((*s&0xdf) == 'L' || (*s&0xdf) == 'U' ) s++; + return s; + } + } + return 0L; +#endif +} + +HlCFloat::HlCFloat(int attribute, int context) + : HlFloat(attribute,context) { +} + +const QChar *HlCFloat::checkHgl(const QChar *s, int len, bool lineStart) { + + s = HlFloat::checkHgl(s, len, lineStart); + if (s && ((*s&0xdf) == 'F' )) s++; + return s; +} + +HlAnyChar::HlAnyChar(int attribute, int context, const QChar* charList, uint len) + : HlItem(attribute, context) { + _charList=charList; + _charListLen=len; +} + +const QChar *HlAnyChar::checkHgl(const QChar *s, int len, bool) +{ + if (ustrchr(_charList, _charListLen, *s)) return s +1; + return 0L; +} + +HlRegExpr::HlRegExpr(int attribute, int context,QString regexp) + : HlItem(attribute, context) { + + handlesLinestart=regexp.startsWith("^"); + if(!handlesLinestart) regexp.prepend("^"); + Expr=new QRegExp3(regexp); +} + +const QChar *HlRegExpr::checkHgl(const QChar *s, int len, bool lineStart) +{ + if ((!lineStart) && handlesLinestart) return 0; + + QString line(s,len); + int pos = Expr->search( line, 0 ); + if (pos==-1) return 0L; + else + return (s+Expr->matchedLength()); +}; + + +HlLineContinue::HlLineContinue(int attribute, int context) + : HlItem(attribute,context) { +} + +const QChar *HlLineContinue::checkHgl(const QChar *s, int len, bool) { + + if ((s[0].latin1() == '\\') && (len == 1)) + { + return s + 1; + } + return 0L; +} + + +HlCStringChar::HlCStringChar(int attribute, int context) + : HlItem(attribute,context) { +} + +//checks for hex and oct (for example \x1b or \033) +const QChar *checkCharHexOct(const QChar *str) { + const QChar *s; + s=str; + int n; + if (*s == 'x') { + n = 0; + do { + s++; + n *= 16; + if (s->isDigit()) n += *s - '0'; + else if ((*s&0xdf) >= 'A' && (*s&0xdf) <= 'F') n += (*s&0xdf) - 'A' + 10; +// else if (*s >= 'a' && *s <= 'f') n += *s - 'a' + 10; + else break; + if (n >= 256) return 0L; + } while (true); + if (s - str == 1) return 0L; + } else { + if (!(*s >= '0' && *s <= '7')) return 0L; + n = *s - '0'; + do { + s++; + n *= 8; + if (*s >= '0' && *s <= '7') n += *s - '0'; else break; + if (n >= 256) return s; + } while (s - str < 3); + } + return s; +} +// checks for C escaped chars \n and escaped hex/octal chars +const QChar *checkEscapedChar(const QChar *s, int len) { + int i; + if (s[0] == '\\' && (len > 1) ) { + s++; + switch(*s){ + case 'a': // checks for control chars + case 'b': // we want to fall through + case 'e': + case 'f': + + case 'n': + case 'r': + case 't': + case 'v': + case '\'': + case '\"': + case '?' : // added ? ANSI C classifies this as an escaped char + case '\\': s++; + break; + case 'x': // if it's like \xff + s++; // eat the x + // these for loops can probably be + // replaced with something else but + // for right now they work + // check for hexdigits + for(i=0;i<2 &&(*s >= '0' && *s <= '9' || (*s&0xdf) >= 'A' && (*s&0xdf) <= 'F');i++,s++); + if(i==0) return 0L; // takes care of case '\x' + break; + + case '0': case '1': case '2': case '3' : + case '4': case '5': case '6': case '7' : + for(i=0;i < 3 &&(*s >='0'&& *s<='7');i++,s++); + break; + default: return 0L; + } + return s; + } + return 0L; +} + +const QChar *HlCStringChar::checkHgl(const QChar *str, int len, bool) { + return checkEscapedChar(str, len); +} + + +HlCChar::HlCChar(int attribute, int context) + : HlItem(attribute,context) { +} + +const QChar *HlCChar::checkHgl(const QChar *str, int len, bool) { + const QChar *s; + + if ((len > 1) && (str[0] == '\'') && (str[1] != '\'')) + { + s = checkEscapedChar(&str[1], len); //try to match escaped char + if (!s) s = &str[2]; //match single non-escaped char + if (*s == '\'') return s + 1; + } + return 0L; +} + + +//-------- +ItemStyle::ItemStyle() : selCol(Qt::white), bold(false), italic(false) { +} + +ItemStyle::ItemStyle(const QColor &col, const QColor &selCol, + bool bold, bool italic) + : col(col), selCol(selCol), bold(bold), italic(italic) { +} + +ItemData::ItemData(const QString name, int defStyleNum) + : name(name), defStyleNum(defStyleNum), defStyle(true) { +} + +ItemData::ItemData(const QString name, int defStyleNum, + const QColor &col, const QColor &selCol, bool bold, bool italic) + : ItemStyle(col,selCol,bold,italic), name(name), defStyleNum(defStyleNum), + defStyle(false) { +} + +HlData::HlData(const QString &wildcards, const QString &mimetypes, const QString &identifier) + : wildcards(wildcards), mimetypes(mimetypes), identifier(identifier) { + +//JW itemDataList.setAutoDelete(true); +} + +HlContext::HlContext(int attribute, int lineEndContext, int _lineBeginContext) + : attr(attribute), ctx(lineEndContext),lineBeginContext(_lineBeginContext) { + items.setAutoDelete(true); +} + +Hl2CharDetect::Hl2CharDetect(int attribute, int context, const QChar *s) + : HlItem(attribute,context) { + sChar1 = s[0]; + sChar2 = s[1]; +} + +Highlight::Highlight(syntaxModeListItem *def) : refCount(0) +{ + noHl = false; + + if (def == 0) + { + noHl = true; + iName = I18N_NOOP("Normal"); + iSection = ""; + } + else + { + iName = def->name; + iSection = def->section; + iWildcards = def->extension; + iMimetypes = def->mimetype; + identifier = def->identifier; + } + deliminator = stdDeliminator; + deliminatorChars = deliminator.unicode(); + deliminatorLen = deliminator.length(); +} + +Highlight::~Highlight() +{ +} + +int Highlight::doHighlight(int ctxNum, TextLine *textLine) +{ + if (noHl) + { + textLine->setAttribs(0,0,textLine->length()); + textLine->setAttr(0); + return 0; + } + + HlContext *context; + const QChar *s2; + HlItem *item; + + context = contextList[ctxNum]; + if (context->lineBeginContext!=-1) + { + ctxNum=context->lineBeginContext; + context=contextList[ctxNum]; + } + + QChar lastChar = ' '; + + // first char + const QChar *str = textLine->getText(); + + // non space char - index of that char + const QChar *s1 = textLine->firstNonSpace(); + uint z = textLine->firstChar(); + + // length of textline + uint len = textLine->length(); + + bool found = false; + while (z < len) + { + found = false; + + for (item = context->items.first(); item != 0L; item = context->items.next()) + { + if (item->startEnable(lastChar)) + { + s2 = item->checkHgl(s1, len-z, z==0); + if (s2 > s1) + { + qDebug("An item has been detected"); + textLine->setAttribs(item->attr,s1 - str,s2 - str); + ctxNum = item->ctx; + context = contextList[ctxNum]; + z = z + s2 - s1 - 1; + s1 = s2 - 1; + found = true; + break; + } + } + } + + // nothing found: set attribute of one char + if (!found) + textLine->setAttribs(context->attr,s1 - str,s1 - str + 1); + + lastChar = *s1; + s1++; + z++; + } + + //set "end of line"-properties + textLine->setAttr(context->attr); + + //return new context + return context->ctx; +} + +KConfig *Highlight::getKConfig() { + KConfig *config; + config=KGlobal::config(); + config->setGroup(iName + QString(" Highlight")); + return config; +} + +QString Highlight::getWildcards() { + KConfig *config; + + config = getKConfig(); + + //if wildcards not yet in config, then use iWildCards as default + return config->readEntry("Wildcards", iWildcards); +} + + +QString Highlight::getMimetypes() { + KConfig *config; + + config = getKConfig(); + + return config->readEntry("Mimetypes", iMimetypes); +} + + +HlData *Highlight::getData() { + KConfig *config; + HlData *hlData; + + config = getKConfig(); + +// iWildcards = config->readEntry("Wildcards"); +// iMimetypes = config->readEntry("Mimetypes"); +// hlData = new HlData(iWildcards,iMimetypes); + hlData = new HlData( + config->readEntry("Wildcards", iWildcards), + config->readEntry("Mimetypes", iMimetypes), + config->readEntry("Identifier", identifier)); + getItemDataList(hlData->itemDataList, config); + return hlData; +} + +void Highlight::setData(HlData *hlData) { + KConfig *config; + + config = getKConfig(); + +// iWildcards = hlData->wildcards; +// iMimetypes = hlData->mimetypes; + + config->writeEntry("Wildcards",hlData->wildcards); + config->writeEntry("Mimetypes",hlData->mimetypes); + + setItemDataList(hlData->itemDataList,config); +} + +void Highlight::getItemDataList(ItemDataList &list) { + KConfig *config; + + config = getKConfig(); + getItemDataList(list, config); +} + +void Highlight::getItemDataList(ItemDataList &list, KConfig *config) { + ItemData *p; + QString s; + QRgb col, selCol; + + list.clear(); +//JW list.setAutoDelete(true); + createItemData(list); + + for (p = list.first(); p != 0L; p = list.next()) { + s = config->readEntry(p->name); + if (!s.isEmpty()) { + sscanf(s.latin1(),"%d,%X,%X,%d,%d", &p->defStyle,&col,&selCol,&p->bold,&p->italic); + p->col.setRgb(col); + p->selCol.setRgb(selCol); + } + } +} + +/******************************************************************************************* + Highlight - setItemDataList + saves the ItemData / attribute / style definitions to the apps configfile. + Especially needed for user overridden values. + + * input: ItemDataList &list :reference to the list, whose + * items should be saved + * KConfig *config :Pointer KDE configuration + * class, which should be used + * as storage + ************* + * output: none + ************* + * return value: none +*******************************************************************************************/ + +void Highlight::setItemDataList(ItemDataList &list, KConfig *config) { + ItemData *p; + QString s; + + for (p = list.first(); p != 0L; p = list.next()) { + s.sprintf("%d,%X,%X,%d,%d", + p->defStyle,p->col.rgb(),p->selCol.rgb(),p->bold,p->italic); + config->writeEntry(p->name,s); + } +} + + +/******************************************************************************************* + Highlight - use + Increase the usage count and trigger initialization if needed + + * input: none + ************* + * output: none + ************* + * return value: none +*******************************************************************************************/ + +void Highlight::use() +{ + if (refCount == 0) init(); + refCount++; +} + + +/******************************************************************************************* + Highlight - release + Decrease the usage count and trigger a cleanup if needed + + * input: none + ************* + * output: none + ************* + * return value: none +*******************************************************************************************/ + +void Highlight::release() +{ + refCount--; + if (refCount == 0) done(); +} + +/******************************************************************************************* + Highlight - init + If it's the first time a particular highlighting is used create the needed contextlist + + * input: none + ************* + * output: none + ************* + * return value: none +*******************************************************************************************/ + +void Highlight::init() +{ + if (noHl) + return; + + for (int z = 0; z < nContexts; z++) contextList[z] = 0L; + makeContextList(); +} + + +/******************************************************************************************* + Highlight - done + If the there is no document using the highlighting style free the complete context + structure. + + * input: none + ************* + * output: none + ************* + * return value: none +*******************************************************************************************/ + +void Highlight::done() +{ + if (noHl) + return; + + for (int z = 0; z < nContexts; z++) delete contextList[z]; +} + + +/******************************************************************************************* + Highlight - createItemData + This function reads the itemData entries from the config file, which specifies the + default attribute styles for matched items/contexts. + + * input: none + ************* + * output: ItemDataList &list :A reference to the internal + list containing the parsed + default config + ************* + * return value: none +*******************************************************************************************/ + +void Highlight::createItemData(ItemDataList &list) +{ + qDebug("Highlight::createItemData"); + + // If no highlighting is selected we need only one default. + if (noHl) + { + list.append(new ItemData(I18N_NOOP("Normal Text"), dsNormal)); + return; + } + + QString color; + QString selColor; + QString bold; + QString italic; + + // If the internal list isn't already available read the config file + if (internalIDList.count()==0) + { + //if all references to the list are destried the contents will also be deleted + internalIDList.setAutoDelete(true); + syntaxContextData *data; + + qDebug("Trying to read itemData section"); + + //Tell the syntax document class which file we want to parse and which data group + HlManager::self()->syntax->setIdentifier(identifier); + data=HlManager::self()->syntax->getGroupInfo("highlighting","itemData"); + //begin with the real parsing + while (HlManager::self()->syntax->nextGroup(data)) + { + qDebug("Setting up one itemData element"); + // read all attributes + color=HlManager::self()->syntax->groupData(data,QString("color")); + selColor=HlManager::self()->syntax->groupData(data,QString("selColor")); + bold=HlManager::self()->syntax->groupData(data,QString("bold")); + italic=HlManager::self()->syntax->groupData(data,QString("italic")); + //check if the user overrides something + if ( (!color.isEmpty()) && (!selColor.isEmpty()) && (!bold.isEmpty()) && (!italic.isEmpty())) + { + //create a user defined style + internalIDList.append(new ItemData( + HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(), + getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum"))), + QColor(color),QColor(selColor),(bold=="true") || (bold=="1"), (italic=="true") || (italic=="1") + )); + } + else + { + //assign a default style + internalIDList.append(new ItemData( + HlManager::self()->syntax->groupData(data,QString("name")).simplifyWhiteSpace(), + getDefStyleNum(HlManager::self()->syntax->groupData(data,QString("defStyleNum"))))); + + } + } + //clean up + if (data) HlManager::self()->syntax->freeGroupInfo(data); + } + + //set the ouput reference + list=internalIDList; +} + + +/******************************************************************************************* + Highlight - lookupAttrName + This function is a helper for makeContextList and createHlItem. It looks the given + attribute name in the itemData list up and returns it's index + + * input: QString &name :the attribute name to lookup + * ItemDataList &iDl :the list containing all + * available attributes + ************* + * output: none + ************* + * return value: int :The index of the attribute + * or 0 +*******************************************************************************************/ + +int Highlight::lookupAttrName(const QString& name, ItemDataList &iDl) +{ + for (int i=0;iname==name) return i; + } + kdDebug(13010)<<"Couldn't resolve itemDataName"<index translation + ************* + * output: none + ************* + * return value: HlItem * : Pointer to the newly created item + * object +*******************************************************************************************/ + +HlItem *Highlight::createHlItem(syntaxContextData *data, ItemDataList &iDl) +{ + // No highlighting -> exit + if (noHl) + return 0; + + // get the (tagname) itemd type + QString dataname=HlManager::self()->syntax->groupItemData(data,QString("")); + + // BEGIN - Translation of the attribute parameter + QString tmpAttr=HlManager::self()->syntax->groupItemData(data,QString("attribute")).simplifyWhiteSpace(); + int attr; + if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) + attr=tmpAttr.toInt(); + else + attr=lookupAttrName(tmpAttr,iDl); + // END - Translation of the attribute parameter + + // Info about context switch + int context=((HlManager::self()->syntax->groupItemData(data,QString("context"))).toInt()); + + // Get the char parameter (eg DetectChar) + char chr; + if (! HlManager::self()->syntax->groupItemData(data,QString("char")).isEmpty()) + chr= (HlManager::self()->syntax->groupItemData(data,QString("char")).latin1())[0]; + else + chr=0; + + // Get the String parameter (eg. StringDetect) + QString stringdata=HlManager::self()->syntax->groupItemData(data,QString("String")); + + // Get a second char parameter (char1) (eg Detect2Chars) + char chr1; + if (! HlManager::self()->syntax->groupItemData(data,QString("char1")).isEmpty()) + chr1= (HlManager::self()->syntax->groupItemData(data,QString("char1")).latin1())[0]; + else + chr1=0; + + // Will be removed eventuall. Atm used for StringDetect + bool insensitive=(HlManager::self()->syntax->groupItemData(data,QString("insensitive"))==QString("TRUE")); + + + //Create the item corresponding to it's type and set it's parameters + if (dataname=="keyword") + { + HlKeyword *keyword=new HlKeyword(attr,context,casesensitive, + deliminatorChars, deliminatorLen); + + //Get the entries for the keyword lookup list + keyword->addList(HlManager::self()->syntax->finddata("highlighting",stringdata)); + return keyword; + } else + if (dataname=="Float") return (new HlFloat(attr,context)); else + if (dataname=="Int") return(new HlInt(attr,context)); else + if (dataname=="DetectChar") return(new HlCharDetect(attr,context,chr)); else + if (dataname=="Detect2Chars") return(new Hl2CharDetect(attr,context,chr,chr1)); else + if (dataname=="RangeDetect") return(new HlRangeDetect(attr,context, chr, chr1)); else + if (dataname=="LineContinue") return(new HlLineContinue(attr,context)); else + if (dataname=="StringDetect") return(new HlStringDetect(attr,context,stringdata,insensitive)); else + if (dataname=="AnyChar") return(new HlAnyChar(attr,context,stringdata.unicode(), stringdata.length())); else + if (dataname=="RegExpr") return(new HlRegExpr(attr,context,stringdata)); else + if(dataname=="HlCChar") return ( new HlCChar(attr,context));else + if(dataname=="HlCHex") return (new HlCHex(attr,context));else + if(dataname=="HlCOct") return (new HlCOct(attr,context)); else + if(dataname=="HlCStringChar") return (new HlCStringChar(attr,context)); else + + { + // oops, unknown type. Perhaps a spelling error in the xml file + return 0; + } + + +} + + +/******************************************************************************************* + Highlight - isInWord + + * input: Qchar c Character to investigate + ************* + * output: none + ************* + * return value: returns true, if c is no deliminator +*******************************************************************************************/ + +bool Highlight::isInWord(QChar c) +{ + return !ustrchr(deliminatorChars, deliminatorLen, c); +} + + + +/******************************************************************************************* + Highlight - readCommentConfig + This function is a helper for makeContextList. It parses the xml file for + information, how single or multi line comments are marked + + * input: none + ************* + * output: none + ************* + * return value: none +*******************************************************************************************/ + +void Highlight::readCommentConfig() +{ + + cslStart = ""; + HlManager::self()->syntax->setIdentifier(identifier); + + syntaxContextData *data=HlManager::self()->syntax->getGroupInfo("general","comment"); + if (data) + { +// kdDebug(13010)<<"COMMENT DATA FOUND"<syntax->nextGroup(data)) + { + + if (HlManager::self()->syntax->groupData(data,"name")=="singleLine") + cslStart=HlManager::self()->syntax->groupData(data,"start"); + if (HlManager::self()->syntax->groupData(data,"name")=="multiLine") + { + cmlStart=HlManager::self()->syntax->groupData(data,"start"); + cmlEnd=HlManager::self()->syntax->groupData(data,"end"); + } + } + HlManager::self()->syntax->freeGroupInfo(data); + } + +} + +/******************************************************************************************* + Highlight - readGlobalKeyWordConfig + This function is a helper for makeContextList. It parses the xml file for + information, if keywords should be treated case(in)sensitive and creates the keyword + delimiter list. Which is the default list, without any given weak deliminiators + + * input: none + ************* + * output: none + ************* + * return value: none +*******************************************************************************************/ + + +void Highlight::readGlobalKeywordConfig() +{ + // Tell the syntax document class which file we want to parse + HlManager::self()->syntax->setIdentifier(identifier); + + // Get the keywords config entry + syntaxContextData * data=HlManager::self()->syntax->getConfig("general","keywords"); + if (data) + { + kdDebug(13010)<<"Found global keyword config"<syntax->groupItemData(data,QString("casesensitive"))!="0") + casesensitive=true; else {casesensitive=false; kdDebug(13010)<<"Turning on case insensitiveness"<syntax->groupItemData(data,QString("weakDeliminator"))); + + // remove any weakDelimitars (if any) from the default list and store this list. + int f; + for (int s=0; s < weakDeliminator.length(); s++) + { + f = 0; + f = deliminator.find (weakDeliminator[s]); + + if (f > -1) + deliminator.remove (f, 1); + } + + deliminatorChars = deliminator.unicode(); + deliminatorLen = deliminator.length(); + + HlManager::self()->syntax->freeGroupInfo(data); + } + else + { + //Default values + casesensitive=true; + weakDeliminator=QString(""); + } + +} + +/******************************************************************************************* + Highlight - makeContextList + That's the most important initialization function for each highlighting. It's called + each time a document gets a highlighting style assigned. parses the xml file and + creates a corresponding internal structure + + * input: none + ************* + * output: none + ************* + * return value: none +*******************************************************************************************/ + + +void Highlight::makeContextList() +{ + if (noHl) + return; + + HlKeyword *keyword=0, *dataType=0; + syntaxContextData *data, *datasub; + HlItem *c; + + readCommentConfig(); + readGlobalKeywordConfig(); + + // Let the syntax document class know, which file we'd like to parse + HlManager::self()->syntax->setIdentifier(identifier); + + // This list is needed for the translation of the attribute parameter, if the itemData name is given instead of the index + ItemDataList iDl; + createItemData(iDl); + + //start the real work + data=HlManager::self()->syntax->getGroupInfo("highlighting","context"); + int i=0; + if (data) + { + while (HlManager::self()->syntax->nextGroup(data)) + { + + // BEGIN - Translation of the attribute parameter + QString tmpAttr=HlManager::self()->syntax->groupData(data,QString("attribute")).simplifyWhiteSpace(); + int attr; + if (QString("%1").arg(tmpAttr.toInt())==tmpAttr) + attr=tmpAttr.toInt(); + else + attr=lookupAttrName(tmpAttr,iDl); + // END - Translation of the attribute parameter + + contextList[i]=new HlContext( + attr, + (HlManager::self()->syntax->groupData(data,QString("lineEndContext"))).toInt(), + (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).isEmpty()?-1: + (HlManager::self()->syntax->groupData(data,QString("lineBeginContext"))).toInt()); + + + //Let's create all items for the context + while (HlManager::self()->syntax->nextItem(data)) + { +// kdDebug(13010)<< "In make Contextlist: Item:"<items.append(c); + + // Not supported completely atm and only one level. Subitems.(all have to be matched to at once) + datasub=HlManager::self()->syntax->getSubItems(data); + bool tmpbool; + if (tmpbool=HlManager::self()->syntax->nextItem(datasub)) + { + c->subItems=new QList; + for (;tmpbool;tmpbool=HlManager::self()->syntax->nextItem(datasub)) + c->subItems->append(createHlItem(datasub,iDl)); + } + HlManager::self()->syntax->freeGroupInfo(datasub); + // end of sublevel + } +// kdDebug(13010)<<"Last line in loop"<syntax->freeGroupInfo(data); + + +} + +HlManager::HlManager() : QObject(0L) +{ + syntax = new SyntaxDocument(); + SyntaxModeList modeList = syntax->modeList(); + + hlList.setAutoDelete(true); + hlList.append(new Highlight(0)); + + uint i=0; + while (i < modeList.count()) + { + hlList.append(new Highlight(modeList.at(i))); + i++; + } +} + +HlManager::~HlManager() { + if(syntax) delete syntax; +} + +HlManager *HlManager::self() +{ + if ( !s_pSelf ) + s_pSelf = new HlManager; + return s_pSelf; +} + +Highlight *HlManager::getHl(int n) { + if (n < 0 || n >= (int) hlList.count()) n = 0; + return hlList.at(n); +} + +int HlManager::defaultHl() { + KConfig *config; + config = KGlobal::config(); + config->setGroup("General Options"); + +#warning fixme return nameFind(config->readEntry("Highlight")); + +} + + +int HlManager::nameFind(const QString &name) { + int z; + + for (z = hlList.count() - 1; z > 0; z--) { + if (hlList.at(z)->iName == name) break; + } + return z; +} + +int HlManager::wildcardFind(const QString &fileName) { + Highlight *highlight; + int p1, p2; + QString w; + for (highlight = hlList.first(); highlight != 0L; highlight = hlList.next()) { + p1 = 0; + w = highlight->getWildcards(); + while (p1 < (int) w.length()) { + p2 = w.find(';',p1); + if (p2 == -1) p2 = w.length(); + if (p1 < p2) { + QRegExp regExp(w.mid(p1,p2 - p1),true,true); + if (regExp.match(fileName) == 0) return hlList.at(); + } + p1 = p2 + 1; + } + } + return -1; +} + + +int HlManager::makeAttribs(Highlight *highlight, Attribute *a, int maxAttribs) { + ItemStyleList defaultStyleList; + ItemStyle *defaultStyle; + ItemDataList itemDataList; + ItemData *itemData; + int nAttribs, z; + + qDebug("HlManager::makeAttribs"); + + defaultStyleList.setAutoDelete(true); + getDefaults(defaultStyleList); + +// itemDataList.setAutoDelete(true); + highlight->getItemDataList(itemDataList); + nAttribs = itemDataList.count(); + for (z = 0; z < nAttribs; z++) { + qDebug("HlManager::makeAttribs: createing one attribute definition"); + itemData = itemDataList.at(z); + if (itemData->defStyle) { + // default style + defaultStyle = defaultStyleList.at(itemData->defStyleNum); + a[z].col = defaultStyle->col; + a[z].selCol = defaultStyle->selCol; + a[z].bold = defaultStyle->bold; + a[z].italic = defaultStyle->italic; + } else { + // custom style + a[z].col = itemData->col; + a[z].selCol = itemData->selCol; + a[z].bold = itemData->bold; + a[z].italic = itemData->italic; + } + } + + for (; z < maxAttribs; z++) { + a[z].col = black; + a[z].selCol = black; + a[z].bold = defaultStyle->bold; + a[z].italic = defaultStyle->italic; + } + return nAttribs; +} + +int HlManager::defaultStyles() { + return 10; +} + +QString HlManager::defaultStyleName(int n) +{ + static QStringList names; + + if (names.isEmpty()) + { + names << i18n("Normal"); + names << i18n("Keyword"); + names << i18n("Data Type"); + names << i18n("Decimal/Value"); + names << i18n("Base-N Integer"); + names << i18n("Floating Point"); + names << i18n("Character"); + names << i18n("String"); + names << i18n("Comment"); + names << i18n("Others"); + } + + return names[n]; +} + +void HlManager::getDefaults(ItemStyleList &list) { + KConfig *config; + int z; + ItemStyle *i; + QString s; + QRgb col, selCol; + + list.setAutoDelete(true); + //ItemStyle(color, selected color, bold, italic) + list.append(new ItemStyle(black,white,false,false)); //normal + list.append(new ItemStyle(black,white,true,false)); //keyword + list.append(new ItemStyle(darkRed,white,false,false)); //datatype + list.append(new ItemStyle(blue,cyan,false,false)); //decimal/value + list.append(new ItemStyle(darkCyan,cyan,false,false)); //base n + list.append(new ItemStyle(darkMagenta,cyan,false,false));//float + list.append(new ItemStyle(magenta,magenta,false,false)); //char + list.append(new ItemStyle(red,red,false,false)); //string + list.append(new ItemStyle(darkGray,gray,false,true)); //comment + list.append(new ItemStyle(darkGreen,green,false,false)); //others + +#warning fixme +/* + config = KateFactory::instance()->config(); + config->setGroup("Default Item Styles"); + for (z = 0; z < defaultStyles(); z++) { + i = list.at(z); + s = config->readEntry(defaultStyleName(z)); + if (!s.isEmpty()) { + sscanf(s.latin1(),"%X,%X,%d,%d",&col,&selCol,&i->bold,&i->italic); + i->col.setRgb(col); + i->selCol.setRgb(selCol); + } + } +*/ +} + +void HlManager::setDefaults(ItemStyleList &list) { + KConfig *config; + int z; + ItemStyle *i; + char s[64]; +#warning fixme +/* + config = KateFactory::instance()->config(); + config->setGroup("Default Item Styles"); + for (z = 0; z < defaultStyles(); z++) { + i = list.at(z); + sprintf(s,"%X,%X,%d,%d",i->col.rgb(),i->selCol.rgb(),i->bold, i->italic); + config->writeEntry(defaultStyleName(z),s); + } +*/ + emit changed(); +} + + +int HlManager::highlights() { + return (int) hlList.count(); +} + +QString HlManager::hlName(int n) { + return hlList.at(n)->iName; +} + +QString HlManager::hlSection(int n) { + return hlList.at(n)->iSection; +} + +void HlManager::getHlDataList(HlDataList &list) { + int z; + + for (z = 0; z < (int) hlList.count(); z++) { + list.append(hlList.at(z)->getData()); + } +} + +void HlManager::setHlDataList(HlDataList &list) { + int z; + + for (z = 0; z < (int) hlList.count(); z++) { + hlList.at(z)->setData(list.at(z)); + } + //notify documents about changes in highlight configuration + emit changed(); +} diff --git a/noncore/apps/tinykate/libkate/document/katehighlight.h b/noncore/apps/tinykate/libkate/document/katehighlight.h new file mode 100644 index 0000000..1baddcc --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katehighlight.h @@ -0,0 +1,349 @@ +/* + Copyright (C) 1998, 1999 Jochen Wilhelmy + digisnap@cs.tu-berlin.de + (C) 2002, 2001 The Kate Team + (C) 2002 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _HIGHLIGHT_H_ +#define _HIGHLIGHT_H_ + +#include +#include + +#include +#include +#include +#include +#include "../qt3back/qregexp3.h" +#include + +class SyntaxDocument; +struct syntaxModeListItem; +struct syntaxContextData; + +class QCheckBox; +class QComboBox; +class QLineEdit; + +class TextLine; +class Attribute; + +class HlItem { + public: + HlItem(int attribute, int context); + virtual ~HlItem(); + virtual bool startEnable(QChar); + virtual const QChar *checkHgl(const QChar *, int len, bool) = 0; + QList *subItems; + int attr; + int ctx; +}; + +class HlCharDetect : public HlItem { + public: + HlCharDetect(int attribute, int context, QChar); + virtual const QChar *checkHgl(const QChar *, int len, bool); + protected: + QChar sChar; +}; + +class Hl2CharDetect : public HlItem { + public: + Hl2CharDetect(int attribute, int context, QChar ch1, QChar ch2); + Hl2CharDetect(int attribute, int context, const QChar *ch); + + virtual const QChar *checkHgl(const QChar *, int len, bool); + protected: + QChar sChar1; + QChar sChar2; +}; + +class HlStringDetect : public HlItem { + public: + HlStringDetect(int attribute, int context, const QString &, bool inSensitive=false); + virtual ~HlStringDetect(); + virtual const QChar *checkHgl(const QChar *, int len, bool); + protected: + const QString str; + bool _inSensitive; +}; + +class HlRangeDetect : public HlItem { + public: + HlRangeDetect(int attribute, int context, QChar ch1, QChar ch2); + virtual const QChar *checkHgl(const QChar *, int len, bool); + protected: + QChar sChar1; + QChar sChar2; +}; + +class HlKeyword : public HlItem +{ + public: + HlKeyword(int attribute, int context,bool casesensitive, const QChar *deliminator, uint deliLen); + virtual ~HlKeyword(); + + virtual void addWord(const QString &); + virtual void addList(const QStringList &); + virtual const QChar *checkHgl(const QChar *, int len, bool); + QStringList getList() { return words;}; + virtual bool startEnable(QChar c); + + protected: + QStringList words; + QDict dict; + bool _caseSensitive; + const QChar *deliminatorChars; + uint deliminatorLen; +}; + +class HlPHex : public HlItem { + public: + HlPHex(int attribute,int context); + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; +class HlInt : public HlItem { + public: + HlInt(int attribute, int context); + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; + +class HlFloat : public HlItem { + public: + HlFloat(int attribute, int context); + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; + +class HlCInt : public HlInt { + public: + HlCInt(int attribute, int context); + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; + +class HlCOct : public HlItem { + public: + HlCOct(int attribute, int context); + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; + +class HlCHex : public HlItem { + public: + HlCHex(int attribute, int context); + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; + +class HlCFloat : public HlFloat { + public: + HlCFloat(int attribute, int context); + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; + +class HlLineContinue : public HlItem { + public: + HlLineContinue(int attribute, int context); + virtual bool endEnable(QChar c) {return c == '\0';} + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; + +class HlCStringChar : public HlItem { + public: + HlCStringChar(int attribute, int context); + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; + +class HlCChar : public HlItem { + public: + HlCChar(int attribute, int context); + virtual const QChar *checkHgl(const QChar *, int len, bool); +}; + +class HlAnyChar : public HlItem { + public: + HlAnyChar(int attribute, int context, const QChar* charList, uint len); + virtual const QChar *checkHgl(const QChar *, int len, bool); + const QChar* _charList; + uint _charListLen; +}; + +class HlRegExpr : public HlItem { + public: + HlRegExpr(int attribute, int context,QString expr); + ~HlRegExpr(){delete Expr;}; + virtual const QChar *checkHgl(const QChar *, int len, bool); + QRegExp3 *Expr; + bool handlesLinestart; +}; + +//-------- + + +//Item Style: color, selected color, bold, italic +class ItemStyle { + public: + ItemStyle(); +// ItemStyle(const ItemStyle &); + ItemStyle(const QColor &, const QColor &, bool bold, bool italic); + ItemStyle(ItemStyle *its){col=its->col;selCol=its->selCol; bold=its->bold; italic=its->italic;} +// void setData(const ItemStyle &); + QColor col; + QColor selCol; + int bold; //boolean value + int italic; //boolean value +}; + +typedef QList ItemStyleList; + +//Item Properties: name, Item Style, Item Font +class ItemData : public ItemStyle { + public: + ItemData(const QString name, int defStyleNum); + ItemData(const QString name, int defStyleNum, + const QColor&, const QColor&, bool bold, bool italic); + ItemData(ItemData +*itd):ItemStyle((ItemStyle*)itd),name(itd->name),defStyleNum(itd->defStyleNum),defStyle(itd->defStyle){;} + const QString name; + int defStyleNum; + int defStyle; //boolean value +}; + +typedef QList ItemDataList; + +class HlData { + public: + HlData(const QString &wildcards, const QString &mimetypes,const QString &identifier); + ItemDataList itemDataList; + QString wildcards; + QString mimetypes; + QString identifier; +}; + +typedef QList HlDataList; + +class HlManager; +class KConfig; + +//context +class HlContext { + public: + HlContext(int attribute, int lineEndContext,int _lineBeginContext); + QList items; + int attr; + int ctx; + int lineBeginContext; +}; + +class Highlight +{ + friend class HlManager; + + public: + Highlight(syntaxModeListItem *def); + ~Highlight(); + + int doHighlight(int ctxNum, TextLine *); + + KConfig *getKConfig(); + QString getWildcards(); + QString getMimetypes(); + HlData *getData(); + void setData(HlData *); + void getItemDataList(ItemDataList &); + void getItemDataList(ItemDataList &, KConfig *); + void setItemDataList(ItemDataList &, KConfig *); + QString name() {return iName;} + QString section() {return iSection;} + void use(); + void release(); + bool isInWord(QChar c); + + QString getCommentStart() {return cmlStart;}; + QString getCommentEnd() {return cmlEnd;}; + QString getCommentSingleLineStart() { return cslStart;}; + + protected: + void init(); + void done(); + void makeContextList (); + void createItemData (ItemDataList &list); + void readGlobalKeywordConfig(); + void readCommentConfig(); + HlItem *createHlItem(struct syntaxContextData *data, ItemDataList &iDl); + int lookupAttrName(const QString& name, ItemDataList &iDl); + ItemDataList internalIDList; + static const int nContexts = 32; + HlContext *contextList[nContexts]; + + bool noHl; + bool casesensitive; + QString weakDeliminator; + QString deliminator; + const QChar *deliminatorChars; + uint deliminatorLen; + QString cmlStart; + QString cmlEnd; + QString cslStart; + QString iName; + QString iSection; + QString iWildcards; + QString iMimetypes; + QString identifier; + int refCount; +}; + +class HlManager : public QObject { + Q_OBJECT + public: + HlManager(); + ~HlManager(); + + static HlManager *self(); + + Highlight *getHl(int n); + int defaultHl(); + int nameFind(const QString &name); + + int wildcardFind(const QString &fileName); + int findHl(Highlight *h) {return hlList.find(h);} + + int makeAttribs(Highlight *, Attribute *, int maxAttribs); + + int defaultStyles(); + QString defaultStyleName(int n); + void getDefaults(ItemStyleList &); + void setDefaults(ItemStyleList &); + + int highlights(); + QString hlName(int n); + QString hlSection(int n); + void getHlDataList(HlDataList &); + void setHlDataList(HlDataList &); + + SyntaxDocument *syntax; + + signals: + void changed(); + protected: + QList hlList; + static HlManager *s_pSelf; +}; + + + + +#endif //_HIGHLIGHT_H_ diff --git a/noncore/apps/tinykate/libkate/document/katesyntaxdocument.cpp b/noncore/apps/tinykate/libkate/document/katesyntaxdocument.cpp new file mode 100644 index 0000000..c51221b --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katesyntaxdocument.cpp @@ -0,0 +1,306 @@ +/*************************************************************************** + katesyntaxdocument.cpp - description + ------------------- + begin : Sat 31 March 2001 + copyright : (C) 2001,2002 by Joseph Wenninger + email : jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "katesyntaxdocument.h" +#include +#include +#include +#include +#include +#include +#include +#include + + + +SyntaxDocument::SyntaxDocument() +{ + m_root=0; + currentFile=""; + setupModeList(); +} + +void SyntaxDocument::setIdentifier(const QString& identifier) +{ +#warning FIXME delete m_root; + m_root=Opie::XMLElement::load(identifier); + if (!m_root) KMessageBox::error( 0L, i18n("Can't open %1").arg(identifier) ); + +} + +SyntaxDocument::~SyntaxDocument() +{ +} + +void SyntaxDocument::setupModeList(bool force) +{ + + if (myModeList.count() > 0) return; + + KConfig *config=KGlobal::config(); + KStandardDirs *dirs = KGlobal::dirs(); + + QStringList list=dirs->findAllResources("data","kate/syntax/*.xml",false,true); + + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + { + QString Group="Highlighting_Cache"+*it; + + if ((config->hasGroup(Group)) && (!force)) + { + config->setGroup(Group); + syntaxModeListItem *mli=new syntaxModeListItem; + mli->name = config->readEntry("name",""); + mli->section = config->readEntry("section",""); + mli->mimetype = config->readEntry("mimetype",""); + mli->extension = config->readEntry("extension",""); + mli->identifier = *it; + myModeList.append(mli); + } + else + { + qDebug("Found a description file:"+(*it)); + setIdentifier(*it); + Opie::XMLElement *e=m_root; + if (e) + { + e=e->firstChild(); + qDebug(e->tagName()); + if (e->tagName()=="language") + { + syntaxModeListItem *mli=new syntaxModeListItem; + mli->name = e->attribute("name"); + mli->section = e->attribute("section"); + mli->mimetype = e->attribute("mimetype"); + mli->extension = e->attribute("extensions"); + qDebug(QString("valid description for: %1/%2").arg(mli->section).arg(mli->name)); + if (mli->section.isEmpty()) + mli->section=i18n("Other"); + + mli->identifier = *it; +#warning fixme +/* + config->setGroup(Group); + config->writeEntry("name",mli->name); + config->writeEntry("section",mli->section); + config->writeEntry("mimetype",mli->mimetype); + config->writeEntry("extension",mli->extension); +*/ + myModeList.append(mli); + } + } + } + } +// } + +// config->sync(); +} + +SyntaxModeList SyntaxDocument::modeList() +{ + return myModeList; +} + +bool SyntaxDocument::nextGroup( syntaxContextData* data) +{ + if(!data) return false; + + if (!data->currentGroup) + data->currentGroup=data->parent->firstChild(); + else + data->currentGroup=data->currentGroup->nextChild(); + + data->item=0; + + if (!data->currentGroup) + return false; + else + return true; +} + +bool SyntaxDocument::nextItem( syntaxContextData* data) +{ + if(!data) return false; + + if (!data->item) + data->item=data->currentGroup->firstChild(); + else + data->item=data->item->nextChild(); + + if (!data->item) + return false; + else + return true; +} + +QString SyntaxDocument::groupItemData( syntaxContextData* data,QString name) +{ + if(!data) + return QString::null; + + if ( (data->item) && (name.isEmpty())) + return data->item->tagName(); + + if (data->item) + return data->item->attribute(name); + else + return QString(); +} + +QString SyntaxDocument::groupData( syntaxContextData* data,QString name) +{ + if(!data) + return QString::null; + + if (data->currentGroup) + return data->currentGroup->attribute(name); + else + return QString(); +} + +void SyntaxDocument::freeGroupInfo( syntaxContextData* data) +{ + if (data) + delete data; +} + +syntaxContextData* SyntaxDocument::getSubItems(syntaxContextData* data) +{ + syntaxContextData *retval=new syntaxContextData; + retval->parent=0; + retval->currentGroup=0; + retval->item=0; + if (data != 0) + { + retval->parent=data->currentGroup; + retval->currentGroup=data->item; + retval->item=0; + } + + return retval; +} + +syntaxContextData* SyntaxDocument::getConfig(const QString& mainGroupName, const QString &Config) +{ + Opie::XMLElement *e = m_root->firstChild()->firstChild(); + + while (e) + { + kdDebug(13010)<<"in SyntaxDocument::getGroupInfo (outer loop) " <tagName().compare(mainGroupName)==0 ) + { + Opie::XMLElement *e1=e->firstChild(); + + while (e1) + { + kdDebug(13010)<<"in SyntaxDocument::getGroupInfo (inner loop) " <tagName()==Config) + { + syntaxContextData *data=new ( syntaxContextData); + data->currentGroup=0; + data->parent=0; + data->item=e1; + return data; + } + + e1=e1->nextChild(); + } + + kdDebug(13010) << "WARNING :returning null 3"<< endl; + return 0; + } + + e=e->nextChild(); + } + + kdDebug(13010) << "WARNING :returning null 4" << endl; + return 0; +} + + + +syntaxContextData* SyntaxDocument::getGroupInfo(const QString& mainGroupName, const QString &group) +{ + + Opie::XMLElement *e=m_root->firstChild()->firstChild(); + + while (e) + { + kdDebug(13010)<<"in SyntaxDocument::getGroupInfo (outer loop) " <tagName().compare(mainGroupName)==0 ) + { + Opie::XMLElement *e1=e->firstChild(); + + while (e1) + { + kdDebug(13010)<<"in SyntaxDocument::getGroupInfo (inner loop) " <tagName()==group+"s") + { + syntaxContextData *data=new ( syntaxContextData); + data->parent=e1; + data->currentGroup=0; + data->item=0; + return data; + } + + e1=e1->nextChild(); + } + + kdDebug(13010) << "WARNING : getGroupInfo returning null :1 " << endl; + return 0; + } + + e=e->nextChild(); + } + + kdDebug(13010) << "WARNING : getGroupInfo returning null :2" << endl; + return 0; +} + + +QStringList& SyntaxDocument::finddata(const QString& mainGroup,const QString& type,bool clearList) +{ + Opie::XMLElement *e = m_root->firstChild(); + if (clearList) + m_data.clear(); + + for(e=e->firstChild(); e; e=e->nextChild()) + { + if (e->tagName()==mainGroup) + { + for (Opie::XMLElement *e1=e->firstChild();e1;e1=e1->nextChild()) + { + if (e1->tagName()!="list") continue; + + if (e1->attribute("name")==type) + { + for (Opie::XMLElement *e2=e1->firstChild();e2;e2=e2->nextChild()) + qDebug("FOUND A LIST ENTRY("+e2->tagName()+"):"+e2->value()); + m_data+="TEST";//e2->value().stripWhiteSpace(); + + break; + } + } + break; + } + } + + return m_data; +} diff --git a/noncore/apps/tinykate/libkate/document/katesyntaxdocument.h b/noncore/apps/tinykate/libkate/document/katesyntaxdocument.h new file mode 100644 index 0000000..5c5c5a4 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katesyntaxdocument.h @@ -0,0 +1,73 @@ +/*************************************************************************** + katesyntaxdocument.h - description + ------------------- + begin : Sat 31 March 2001 + copyright : (C) 2001,2002 by Joseph Wenninger + email : jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef SYNTAXDOCUMENT_H +#define SYNTAXDOCUMENT_H + +#include +#include +#include + + +class syntaxModeListItem +{ + public: + QString name; + QString section; + QString mimetype; + QString extension; + QString identifier; +}; + +class syntaxContextData +{ + public: + Opie::XMLElement *parent; + Opie::XMLElement *currentGroup; + Opie::XMLElement *item; +}; + +typedef QList SyntaxModeList; + +class SyntaxDocument +{ + public: + SyntaxDocument(); + ~SyntaxDocument(); + + QStringList& finddata(const QString& mainGroup,const QString& type,bool clearList=true); + SyntaxModeList modeList(); + + syntaxContextData* getGroupInfo(const QString& langName, const QString &group); + void freeGroupInfo(syntaxContextData* data); + syntaxContextData* getConfig(const QString& mainGroupName, const QString &Config); + bool nextItem(syntaxContextData* data); + bool nextGroup(syntaxContextData* data); + syntaxContextData* getSubItems(syntaxContextData* data); + QString groupItemData(syntaxContextData* data,QString name); + QString groupData(syntaxContextData* data,QString name); + void setIdentifier(const QString& identifier); + + private: + Opie::XMLElement *m_root; + void setupModeList(bool force=false); + QString currentFile; + SyntaxModeList myModeList; + QStringList m_data; +}; + +#endif diff --git a/noncore/apps/tinykate/libkate/document/katetextline.cpp b/noncore/apps/tinykate/libkate/document/katetextline.cpp new file mode 100644 index 0000000..f44cc1c --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katetextline.cpp @@ -0,0 +1,289 @@ +/* + Copyright (C) 1998, 1999 Jochen Wilhelmy + digisnap@cs.tu-berlin.de + (C) 2002, 2001 The Kate Team + (C) 2002 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "katetextline.h" +#include + +TextLine::TextLine(uchar attribute, int context) + : text(0L), attributes(0L), attr(attribute), ctx(context), myMark (0) +{ +} + +TextLine::~TextLine() +{ +} + + +void TextLine::replace(uint pos, uint delLen, const QChar *insText, uint insLen, uchar *insAttribs) +{ + uint oldLen = text.length(); + + text.remove (pos, delLen); + text.insert (pos, insText, insLen); + + if (oldLen= oldLen) + { + for (uint t=oldLen; t < attributes.size(); t++) + { + attributes[t]=0; + } + } + + int newAtStuff = insLen-delLen; + for (uint m=pos+delLen; m < attributes.size(); m++) + { + if (m+newAtStuff >= attributes.size()) break; + if (m >= attributes.size()) break; + + attributes[m+newAtStuff]=attributes[m]; + } + + if (insAttribs == 0L) + { + for (uint m3=pos; m3 < pos+insLen; m3++) + { + if (m3 < attributes.size()) attributes[m3]=0; + } + } + else + { + for (uint m2=pos; m2 < pos+insLen; m2++) + { + if (m2 < attributes.size()) attributes[m2]=insAttribs[m2-pos]; + } + } + + if (oldLen>text.length()) attributes.resize (text.length()); +} + +void TextLine::wrap(TextLine::Ptr nextLine, uint pos) +{ + int l = text.length() - pos; + + if (l > 0) + { + nextLine->replace(0, 0, &text.unicode()[pos], l, &attributes[pos]); + attr = attributes[pos]; + truncate(pos); + } +} + +void TextLine::unWrap(uint pos, TextLine::Ptr nextLine, uint len) { + + replace(pos, 0, nextLine->text.unicode(), len, nextLine->attributes.data()); + attr = nextLine->getRawAttr(len); + nextLine->replace(0, len, 0L, 0); +} + +int TextLine::firstChar() const { + uint z = 0; + + while (z < text.length() && text[z].isSpace()) z++; + + if (z < text.length()) + return z; + else + return -1; +} + +int TextLine::lastChar() const { + uint z = text.length(); + + while (z > 0 && text[z - 1].isSpace()) z--; + return z; +} + +void TextLine::removeSpaces() { + + while (text.length() > 0 && text[text.length() - 1].isSpace()) text.truncate (text.length()-1); +} + +QChar TextLine::getChar(uint pos) const { + if (pos < text.length()) return text.constref(pos); + return ' '; +} +const QChar *TextLine::firstNonSpace() +{ + const QChar *ptr=getText(); + int first=firstChar(); + return (first > -1) ? ptr+first : ptr; +} + +bool TextLine::startingWith(QString& match) +{ + return text.startsWith (match); +} + +bool TextLine::endingWith(QString& match) { + + int matchLen = match.length(); + + // Get the last chars of the textline + QString lastChars = text.right(matchLen); + + return (lastChars == match); +} + +int TextLine::cursorX(uint pos, uint tabChars) const { + int l, x, z; + + l = (pos < text.length()) ? pos : text.length(); + x = 0; + for (z = 0; z < l; z++) { + if (text[z] == '\t') x += tabChars - (x % tabChars); else x++; + } + x += pos - l; + return x; +} + +void TextLine::setAttribs(uchar attribute, uint start, uint end) { + uint z; + + if (end > text.length()) end = text.length(); + for (z = start; z < end; z++) attributes[z] = (attributes[z] & taSelected) | attribute; +} + +void TextLine::setAttr(uchar attribute) { + attr = (attr & taSelected) | attribute; +} + +uchar TextLine::getAttr(uint pos) const { + if (pos < text.length()) return attributes[pos] & taAttrMask; + return attr & taAttrMask; +} + +uchar TextLine::getAttr() const { + return attr & taAttrMask; +} + +uchar TextLine::getRawAttr(uint pos) const { + if (pos < text.length()) return attributes[pos]; + return (attr & taSelected) ? attr : attr | 256; +} + +uchar TextLine::getRawAttr() const { + return attr; +} + +void TextLine::setContext(int context) { + ctx = context; +} + +int TextLine::getContext() const { + return ctx; +} + + +void TextLine::select(bool sel, uint start, uint end) { + uint z; + + if (end > text.length()) end = text.length(); + if (sel) { + for (z = start; z < end; z++) attributes[z] |= taSelected; + } else { + for (z = start; z < end; z++) attributes[z] &= ~taSelected; + } +} + +void TextLine::selectEol(bool sel, uint pos) { + uint z; + + if (sel) { + for (z = pos; z < text.length(); z++) attributes[z] |= taSelected; + attr |= taSelected; + } else { + for (z = pos; z < text.length(); z++) attributes[z] &= ~taSelected; + attr &= ~taSelected; + } +} + + +void TextLine::toggleSelect(uint start, uint end) { + uint z; + + if (end > text.length()) end = text.length(); + for (z = start; z < end; z++) attributes[z] = attributes[z] ^ taSelected; +} + + +void TextLine::toggleSelectEol(uint pos) { + uint z; + + for (z = pos; z < text.length(); z++) attributes[z] = attributes[z] ^ taSelected; + attr = attr ^ taSelected; +} + + +int TextLine::numSelected() const { + uint z, n; + + n = 0; + for (z = 0; z < text.length(); z++) if (attributes[z] & taSelected) n++; + return n; +} + +bool TextLine::isSelected(uint pos) const { + if (pos < text.length()) return (attributes[pos] & taSelected); + return (attr & taSelected); +} + +bool TextLine::isSelected() const { + return (attr & taSelected); +} + +int TextLine::findSelected(uint pos) const { + while (pos < text.length() && attributes[pos] & taSelected) pos++; + return pos; +} + +int TextLine::findUnselected(uint pos) const { + while (pos < text.length() && !(attributes[pos] & taSelected)) pos++; + return pos; +} + +int TextLine::findRevSelected(uint pos) const { + while (pos > 0 && attributes[pos - 1] & taSelected) pos--; + return pos; +} + +int TextLine::findRevUnselected(uint pos) const { + while (pos > 0 && !(attributes[pos - 1] & taSelected)) pos--; + return pos; +} + +void TextLine::addMark (uint m) +{ + myMark = myMark | m; +} + +void TextLine::delMark (uint m) +{ + myMark = myMark & ~m; +} diff --git a/noncore/apps/tinykate/libkate/document/katetextline.h b/noncore/apps/tinykate/libkate/document/katetextline.h new file mode 100644 index 0000000..c2968cc --- a/dev/null +++ b/noncore/apps/tinykate/libkate/document/katetextline.h @@ -0,0 +1,359 @@ +/* + Copyright (C) 1998, 1999 Jochen Wilhelmy + digisnap@cs.tu-berlin.de + (C) 2002, 2001 The Kate Team + (C) 2002 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _KWTEXTLINE_H_ +#define _KWTEXTLINE_H_ + +#include + +#include +#include +#include + +#include + +/** + FastValueList: QValueList, but with a faster at() like QList + FVPrivate is needed so that "const" functions can change the + current position +*/ +template +class FVPrivate +{ +public: + int curpos; + typedef QValueListConstIterator Iterator; + Iterator curit; + + FVPrivate() { curpos=-1; }; +}; + +template +class FastValueList : public QValueList +{ +public: + typedef QValueListIterator Iterator; + typedef QValueListConstIterator ConstIterator; +protected: + FVPrivate *fvp; + + Iterator fastat( uint i ) { + uint num=count(); + if (i>=num) {return end();} + if (fvp->curpos<0) { fvp->curpos=0; fvp->curit=begin(); } + uint curpos=(uint) fvp->curpos; + Iterator curit(fvp->curit.node); + if (curpos==i) return curit; + + int diff=i-curpos; + bool forward; + if (diff<0) diff=-diff; + if (((uint)diff < i) && ((uint)diff < num-i)) { // start from current node + forward=i > (uint)curpos; + } else if (i < num - i) { // start from first node + curit=begin(); diff=i; forward=TRUE; + } else { // start from last node + curit=fromLast(); diff=num - i - 1; + if (diff<0) diff=0; + forward=FALSE; + } + if (forward) { + while(diff--) curit++; + } else { + while(diff--) curit--; + } + fvp->curpos=i; fvp->curit=curit; + return curit; + } + ConstIterator fastat( uint i ) const { + uint num=count(); + if (i>=num) {return end();} + if (fvp->curpos<0) { fvp->curpos=0; fvp->curit=begin(); } + uint curpos=(uint) fvp->curpos; + ConstIterator curit=fvp->curit; + if (curpos==i) return curit; + + int diff=i-curpos; + bool forward; + if (diff<0) diff=-diff; + if (((uint)diff < i) && ((uint)diff < num-i)) { // start from current node + forward=i > (uint)curpos; + } else if (i < num - i) { // start from first node + curit=begin(); diff=i; forward=TRUE; + } else { // start from last node + curit=fromLast(); diff=num - i - 1; + if (diff<0) diff=0; + forward=FALSE; + } + if (forward) { + while(diff--) curit++; + } else { + while(diff--) curit--; + } + fvp->curpos=i; fvp->curit=curit; + return curit; + } + +public: + FastValueList() : QValueList() + { fvp=new FVPrivate(); } + FastValueList(const FastValueList& l) : QValueList(l) + { fvp=new FVPrivate(); } + ~FastValueList() { delete fvp; } + + Iterator insert( Iterator it, const T& x ) { + fvp->curpos=-1; return QValueList::insert(it, x); + } + + Iterator append( const T& x ) { + fvp->curpos=-1; return QValueList::append( x ); + } + Iterator prepend( const T& x ) { + fvp->curpos=-1; return QValueList::prepend( x ); + } + + Iterator remove( Iterator it ) { + fvp->curpos=-1; return QValueList::remove( it ); + } + void remove( const T& x ) { + fvp->curpos=-1; QValueList::remove( x ); + } + + T& operator[] ( uint i ) { detach(); return fastat(i); } + const T& operator[] ( uint i ) const { return *fastat(i); } + Iterator at( uint i ) { detach(); return fastat(i); } + ConstIterator at( uint i ) const { return ConstIterator( fastat(i) ); } +}; + + +/** + The TextLine represents a line of text. A text line that contains the + text, an attribute for each character, an attribute for the free space + behind the last character and a context number for the syntax highlight. + The attribute stores the index to a table that contains fonts and colors + and also if a character is selected. +*/ +class TextLine : public KShared +{ + friend class KWBuffer; + friend class KWBufBlock; + +public: + typedef KSharedPtr Ptr; + typedef FastValueList List; + +public: + /** + Creates an empty text line with given attribute and syntax highlight + context + */ + TextLine(uchar attribute = 0, int context = 0); + ~TextLine(); + + /** + Returns the length + */ + uint length() const {return text.length();} + /** + Universal text manipulation method. It can be used to insert, delete + or replace text. + */ + void replace(uint pos, uint delLen, const QChar *insText, uint insLen, uchar *insAttribs = 0L); + + /** + Appends a string of length l to the textline + */ + void append(const QChar *s, uint l) {replace(text.length(), 0, s, l);} + /** + Wraps the text from the given position to the end to the next line + */ + void wrap(TextLine::Ptr nextLine, uint pos); + /** + Wraps the text of given length from the beginning of the next line to + this line at the given position + */ + void unWrap(uint pos, TextLine::Ptr nextLine, uint len); + /** + Truncates the textline to the new length + */ + void truncate(uint newLen) { text.truncate(newLen); attributes.resize(text.length()); } + /** + Returns the position of the first character which is not a white space + */ + int firstChar() const; + /** + Returns the position of the last character which is not a white space + */ + int lastChar() const; + /** + Removes trailing spaces + */ + void removeSpaces(); + /** + Gets the char at the given position + */ + QChar getChar(uint pos) const; + /** + Gets the text. WARNING: it is not null terminated + */ + const QChar *getText() const {return text.unicode();}; + /** + Gets a C-like null terminated string + */ + const QString getString() { return text; }; + + /* + Gets a null terminated pointer to first non space char + */ + const QChar *firstNonSpace(); + /** + Returns the x position of the cursor at the given position, which + depends on the number of tab characters + */ + int cursorX(uint pos, uint tabChars) const; + /** + Is the line starting with the given string + */ + bool startingWith(QString& match); + /** + Is the line ending with the given string + */ + bool endingWith(QString& match); + + /** + Sets the attributes from start to end -1 + */ + void setAttribs(uchar attribute, uint start, uint end); + /** + Sets the attribute for the free space behind the last character + */ + void setAttr(uchar attribute); + /** + Gets the attribute at the given position + */ + uchar getAttr(uint pos) const; + /** + Gets the attribute for the free space behind the last character + */ + uchar getAttr() const; + /** + Gets the attribute, including the select state, at the given position + */ + uchar getRawAttr(uint pos) const; + /** + Gets the attribute, including the select state, for the free space + behind the last character + */ + uchar getRawAttr() const; + + /** + Sets the syntax highlight context number + */ + void setContext(int context); + /** + Gets the syntax highlight context number + */ + int getContext() const; + + /** + Sets the select state from start to end -1 + */ + void select(bool sel, uint start, uint end); + /** + Sets the select state from the given position to the end, including + the free space behind the last character + */ + void selectEol(bool sel, uint pos); + /** + Toggles the select state from start to end -1 + */ + void toggleSelect(uint start, uint end); + /** + Toggles the select state from the given position to the end, including + the free space behind the last character + */ + void toggleSelectEol(uint pos); + /** + Returns the number of selected characters + */ + int numSelected() const; + /** + Returns if the character at the given position is selected + */ + bool isSelected(uint pos) const; + /** + Returns true if the free space behind the last character is selected + */ + bool isSelected() const; + /** + Finds the next selected character, starting at the given position + */ + int findSelected(uint pos) const; + /** + Finds the next unselected character, starting at the given position + */ + int findUnselected(uint pos) const; + /** + Finds the previous selected character, starting at the given position + */ + int findRevSelected(uint pos) const; + /** + Finds the previous unselected character, starting at the given position + */ + int findRevUnselected(uint pos) const; + + void clearMark () { myMark = 0; }; + void addMark ( uint m ); + void delMark ( uint m ); + uint mark() { return myMark; }; + + uchar *getAttribs() { return attributes.data(); } + + protected: + /** + The text + */ + QString text; + /** + The attributes + */ + QArray attributes; + /** + The attribute of the free space behind the end + */ + uchar attr; + /** + The syntax highlight context + */ + int ctx; + /** + The marks of the current line + */ + uint myMark; +}; + +//text attribute constants +const int taSelected = 0x40; +const int taAttrMask = ~taSelected & 0xFF; + +#endif //KWTEXTLINE_H + 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 @@ +/*************************************************************************** + document.h - description + ------------------- + begin : Mon Jan 15 2001 + copyright : (C) 2001 by Christoph "Crossfire" Cullmann + (C) 2002 by Joseph Wenninger + email : crossfire@babylon2k.de + jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + ***************************************************************************/ + +#ifndef _KATE_DOCUMENT_INCLUDE_ +#define _KATE_DOCUMENT_INCLUDE_ + +#include + +class KConfig; + +namespace Kate +{ + +/** internal class for document bookmarks. */ +class Mark +{ + public: + uint line; + uint type; +}; + +/** This interface provedes access to the Kate Document class. +*/ +class Document : public KTextEditor::Document +{ + Q_OBJECT + + public: + Document (); + virtual ~Document (); + + public: + /** Read document config. + */ + virtual void readConfig () { ; }; + /** Save document config. + */ + virtual void writeConfig () { ; }; + + /** Read document session config. + */ + virtual void readSessionConfig (KConfig *) { ; }; + /** Save document session config. + */ + virtual void writeSessionConfig (KConfig *) { ; }; + + /** Returns the document ID. + */ + virtual uint docID () { return 0L; }; + + /** Defines possible mark types. A line can have marks of different types. + */ + enum marks + { + Bookmark = 1, + Breakpoint = 2, + markType0 = 4, + markType1 = 8, + markType2 = 16, + markType3 = 32, + markType4 = 64, + markType5 = 128, + markType6 = 256, + markType7 = 512, + markType8 = 1024 + }; + + /** A list of all marks in a document. Use binary comparing to find marks of a specific type. + */ + virtual QList marks () { QList l; return l; }; + + public slots: + // clear buffer/filename - update the views + virtual void flush () { ; }; +}; + +}; + +#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 @@ +/*************************************************************************** + interfaces.cpp - description + ------------------- + begin : Mon Jan 15 2001 + copyright : (C) 2001 by Christoph "Crossfire" Cullmann + (C) 2002 by Joseph Wenninger + email : crossfire@babylon2k.de + jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + ***************************************************************************/ + +#include "document.h" + +#include "view.h" + +namespace Kate +{ + +Document::Document () : KTextEditor::Document (0L, 0L) +{ +} + +Document::~Document () +{ +} + +View::View ( KTextEditor::Document *doc, QWidget *parent, const char *name ) : KTextEditor::View (doc, parent, name) +{ +} + +View::~View () +{ +} + +}; 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 @@ +/*************************************************************************** + view.h - description + ------------------- + begin : Mon Jan 15 2001 + copyright : (C) 2001 by Christoph "Crossfire" Cullmann + (C) 2002 by Joseph Wenninger + email : crossfire@babylon2k.de + jowenn@kde.org +***************************************************************************/ + +/*************************************************************************** + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + ***************************************************************************/ + +#ifndef _KATE_VIEW_INCLUDE_ +#define _KATE_VIEW_INCLUDE_ + +#include + +class KConfig; + +namespace Kate +{ + +class Document; +class Mark; + +/** This interface provides access to the view. +*/ +class View : public KTextEditor::View +{ + Q_OBJECT + + public: + View ( KTextEditor::Document *doc, QWidget *parent, const char *name = 0 ); + virtual ~View (); + + /** Returns a pointer to the document of the view. + */ + virtual Document *getDoc () { return 0L; }; + + /** Returns the marked text in the view. + */ + virtual QString markedText () { return 0L; }; + + public slots: + /** popup a config dialog for the editor part. + */ + virtual void configDialog () { ; }; + + // Highlighting slots + virtual void setHl (int) { ; }; + virtual int getHl () { return 0; }; + virtual int getHlCount () { return 0; }; + virtual QString getHlName (int) { return 0L; }; + virtual QString getHlSection (int) { return 0L; }; + + // undo/redo stuff + virtual void undo () { ; }; + virtual void redo () { ; }; + virtual void undoHistory() { ; }; + + public: + // read/save config of the view + virtual void readConfig () { ; }; + virtual void writeConfig () { ; }; + + // read/save sessionconfig of the view + virtual void readSessionConfig (KConfig *) { ; }; + virtual void writeSessionConfig (KConfig *) { ; }; + + public slots: + // some simply key commands + virtual void keyReturn () { ; }; + virtual void keyDelete () { ; }; + virtual void backspace () { ; }; + virtual void killLine () { ; }; + + // move cursor in the view + virtual void cursorLeft () { ; }; + virtual void shiftCursorLeft () { ; }; + virtual void cursorRight () { ; }; + virtual void shiftCursorRight () { ; }; + virtual void wordLeft () { ; }; + virtual void shiftWordLeft () { ; }; + virtual void wordRight () { ; }; + virtual void shiftWordRight () { ; }; + virtual void home () { ; }; + virtual void shiftHome () { ; }; + virtual void end () { ; }; + virtual void shiftEnd () { ; }; + virtual void up () { ; }; + virtual void shiftUp () { ; }; + virtual void down () { ; }; + virtual void shiftDown () { ; }; + virtual void scrollUp () { ; }; + virtual void scrollDown () { ; }; + virtual void topOfView () { ; }; + virtual void bottomOfView () { ; }; + virtual void pageUp () { ; }; + virtual void shiftPageUp () { ; }; + virtual void pageDown () { ; }; + virtual void shiftPageDown () { ; }; + virtual void top () { ; }; + virtual void shiftTop () { ; }; + virtual void bottom () { ; }; + virtual void shiftBottom () { ; }; + + public slots: + // edit command popup window + virtual void slotEditCommand () { ; }; + + // icon border enable/disable + virtual void setIconBorder (bool) { ; }; + virtual void toggleIconBorder () { ; }; + + // goto mark + virtual void gotoMark (Mark *) { ; }; + + // toggle current line bookmark or clear all bookmarks + virtual void toggleBookmark () { ; }; + virtual void clearBookmarks () { ; }; + + public: + // is iconborder visible ? + virtual bool iconBorder() { return false; }; + + public slots: + /** + Flushes the document of the text widget. The user is given + a chance to save the current document if the current document has + been modified. + */ + virtual void flush () { ; }; + + public: + /** + Returns true if the current document can be + discarded. If the document is modified, the user is asked if he wants + to save it. On "cancel" the function returns false. + */ + virtual bool canDiscard() { return false; }; +}; + +}; + +#endif diff --git a/noncore/apps/tinykate/libkate/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 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Simon Hausmann + Copyright (C) 2002 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#include "ktexteditor.h" + +using namespace KTextEditor; + +class View::ViewPrivate +{ +public: + ViewPrivate() + { + } + ~ViewPrivate() + { + } + + Document *m_doc; + bool m_bContextPopup; +}; + +View::View( Document *doc, QWidget *parent, const char *name ) +: QWidget( parent, name ) +{ + d = new ViewPrivate; + d->m_doc = doc; + d->m_bContextPopup = true; +} + +View::~View() +{ + delete d; +} + +Document *View::document() const +{ + return d->m_doc; +} + +void View::insertText( const QString &text, bool mark ) +{ + int line, col; + getCursorPosition( &line, &col ); + document()->insertAt( text, line, col, mark ); +} + +void View::setInternalContextMenuEnabled( bool b ) +{ + d->m_bContextPopup = b; +} + +bool View::internalContextMenuEnabled() const +{ + return d->m_bContextPopup; +} + +class Document::DocumentPrivate +{ +public: + DocumentPrivate() + { + } + ~DocumentPrivate() + { + } + +}; + +Document::Document( QObject *parent, const char *name ) + : QObject(parent,name) +{ + d = new DocumentPrivate; +} + +Document::~Document() +{ + //one never knows... + QListIterator it( m_views ); + + for (; it.current(); ++it ) + disconnect( it.current(), SIGNAL( destroyed() ), + this, SLOT( slotViewDestroyed() ) ); + + delete d; +} + +QList Document::views() const +{ + return m_views; +} + +void Document::addView( View *view ) +{ + if ( !view ) + return; + + if ( m_views.findRef( view ) != -1 ) + return; + + m_views.append( view ); + connect( view, SIGNAL( destroyed() ), + this, SLOT( slotViewDestroyed() ) ); +} + +void Document::removeView( View *view ) +{ + if ( !view ) + return; + + disconnect( view, SIGNAL( destroyed() ), + this, SLOT( slotViewDestroyed() ) ); + + m_views.removeRef( view ); +} + +void Document::slotViewDestroyed() +{ + const View *view = static_cast( sender() ); + m_views.removeRef( view ); +} + + 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 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Simon Hausmann + Copyright (C) 2002 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __ktexteditor_h__ +#define __ktexteditor_h__ + +#include +#include + +/** + * This is the kparts interface classes for text editors. + * The text editors use the Document/View model that allows multiple views into + * one file (Document) + * + * Line numbers passed via this interface must begin at line number zero (0). + * + * TODO: See documentation at http://??????? for information on how to use kparts in + * general. A simple (but sufficient) implementation is shown below. + * + *
+ * QHBoxLayout *layout = new QHBoxLayout(this);
+ * QSplitter *fixme = new QSplitter(this);
+ *
+ * KTrader::OfferList offers = KTrader::self()->query( "KTextEditor/Document" );
+ * assert( offers.count() >= 1 );
+ * KService::Ptr service = *offers.begin();
+ * KLibFactory *factory = KLibLoader::self()->factory( service->library() );
+ * assert( factory );
+ * m_part = static_cast(
+ * 						factory->create( this, 0, "KTextEditor::Document" ) );
+ * assert( m_part );
+ * m_part->createView( fixme, 0 );
+ * layout->addWidget(fixme);
+ * m_part->setText( "" );
+ * 
+ * + * You may also be able to use a dynamic_cast for the document part above + * (depending on compliation of the library used) + * + */ + +namespace KTextEditor +{ + +class Document; + +/** + * The View class encapsulates a single view into the document. + */ + +class View : public QWidget +{ + Q_OBJECT + +public: + /** + * Create a new view to the given document. The document must be non-null. + */ + View( Document *doc, QWidget *parent, const char *name = 0 ); + virtual ~View(); + + /** + * Acessor to the parent Document. + */ + virtual Document *document() const; // XXX fix when renaming KXMLGUIClient::document + + virtual void setCursorPosition( int line, int col, bool mark = false ) = 0; + virtual void getCursorPosition( int *line, int *col ) = 0; + + /** + * Inserts text at the current cursor position into the document + */ + virtual void insertText( const QString &text, bool mark = false ); + + /** + * Overwrite mode is where the char under the cursor is replaced with the + * char typed by the user + */ + virtual bool isOverwriteMode() const = 0; + + /** + * You should reimplement this method. + * If the internal popupmenu property is enabled, then the implementation + * is free to handle/use/implement/show a context popupmenu ( see also + * KContextMenuManager class in kdeui ). If disabled, then the + * implementation should emit the @ref contextPopupMenu signal. + */ + virtual void setInternalContextMenuEnabled( bool b ); + virtual bool internalContextMenuEnabled() const; + +public slots: + virtual void setOverwriteMode( bool b ) = 0; + +signals: + /** + * Connect here when you want to implement a custom popup menu. + */ + void contextPopupMenu( const QPoint &p ); + + /** + * Connect here if you want to track the scrolling within the editor. This + * allows you to add specialised borders that displays extra data about + * particular lines such as breakpoints etc. + */ + void scrollValueChanged( int value ); + +private: + class ViewPrivate; + ViewPrivate *d; +}; + +class Document : public QObject +{ + Q_OBJECT +public: + Document( QObject *parent = 0, const char *name = 0 ); + virtual ~Document(); + + /** + * Create a view that will display the document data. You can create as many + * views as you like. When the user modifies data in one view then all other + * views will be updated as well. + */ + virtual View *createView( QWidget *parent, const char *name = 0 ) = 0; + + /* + * Accessor to the list of views. + */ + virtual QList views() const; + + /** + * @return All the text from the requested line. + */ + virtual QString textLine( int line ) const = 0; + + virtual void setSelection( int row_from, int col_from, int row_to, int col_t ) = 0; + virtual bool hasSelection() const = 0; + virtual QString selection() const = 0; + + /** + * @return The current number of lines in the document + */ + virtual int numLines() const = 0; + + /** + * Insert line(s) at the given line number. If the line number is -1 + * (the default) then the line is added to end of the document + */ + virtual void insertLine( const QString &s, int line = -1 ) = 0; + + /** + * Add the line(s) into the document at the given line and column. + */ + virtual void insertAt( const QString &s, int line, int col, bool mark = FALSE ) = 0; + + virtual void removeLine( int line ) = 0; + + /** + * @return the complete document as a single QString + */ + virtual QString text() const = 0; + + /** + * @return the number of characters in the document + */ + virtual int length() const = 0; + +public slots: + /** + * Set the given text into the view. + * Warning: This will overwrite any data currently held in this view. + */ + virtual void setText( const QString &t ) = 0; + +signals: + + /** + * When the user changes the text then this signal is emitted + * TODO: - explain why and what type of change trigger this? + */ + void textChanged(); + + /** + */ + void deleted( int startLine, int endLine ); + + /** + */ + void inserted( int startLine, int endLine ); + +protected: + /** + * Call this method in your document implementation whenever you created a new + * view. + * (like in @ref createView ) + */ + virtual void addView( View *view ); + + /** + * Call this method in your document implementation whenever you delete a view. + */ + virtual void removeView( View *view ); + + QList m_views; + +private slots: + + /** + * The view emits a destroyed() signal which is connected to this slot + * and removed from our internal list. Note: The view* is obtained from + * the QObject::sender() method. + */ + void slotViewDestroyed(); + +private: + class DocumentPrivate; + DocumentPrivate *d; +}; + +}; + +#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 @@ +TEMPLATE = lib +CONFIG = qt warn_on release +DESTDIR = $(OPIEDIR)/bin +HEADERS = microkde/kapplication.h \ + microkde/kconfig.h \ + microkde/kdebug.h \ + microkde/kdialog.h \ + microkde/kdialogbase.h \ + microkde/kfiledialog.h \ + microkde/kglobal.h \ + microkde/kiconloader.h \ + microkde/klineedit.h \ + microkde/klocale.h \ + microkde/kmessagebox.h \ + microkde/kprinter.h \ + microkde/krestrictedline.h \ + microkde/kseparator.h \ + microkde/ksimpleconfig.h \ + microkde/kstandarddirs.h \ + microkde/ktempfile.h \ + microkde/kunload.h \ + microkde/kurlrequester.h \ + microkde/kfontdialog.h \ + microkde/krun.h \ + microkde/knumvalidator.h \ + microkde/kstaticdeleter.h \ + microkde/klistview.h \ + microkde/kglobalsettings.h \ + microkde/kcolorbtn.h \ + \ + \ + qt3back/qregexp3.h \ + kde/ksharedptr.h \ + document/katebuffer.h document/katedialogs.h \ + document/katetextline.h \ + document/katecmd.h \ + document/katehighlight.h \ + document/katecmds.h document/katedocument.h \ + document/katesyntaxdocument.h \ + view/kateundohistory.h \ + view/kateview.h \ + view/kateviewdialog.h \ + interfaces/view.h \ + interfaces/document.h \ + ktexteditor/ktexteditor.h + +SOURCES = microkde/kapplication.cpp \ + microkde/kdialogbase.cpp \ + microkde/kconfig.cpp \ + microkde/klocale.cpp \ + microkde/kmessagebox.cpp \ + microkde/kprocess.cpp \ + microkde/kstandarddirs.cpp \ + microkde/ktempfile.cpp \ + microkde/kurlrequester.cpp \ + microkde/kcolordialog.cpp \ + microkde/kfontdialog.cpp \ + microkde/krun.cpp \ + microkde/knumvalidator.cpp \ + microkde/kglobal.cpp \ + microkde/kglobalsettings.cpp \ + microkde/kcolorbtn.cpp \ + \ + \ + qt3back/qregexp3.cpp \ + ktexteditor/ktexteditor.cpp \ + document/katebuffer.cpp document/katedialogs.cpp \ + document/katehighlight.cpp \ + document/katecmd.cpp \ + document/katesyntaxdocument.cpp document/katecmds.cpp \ + document/katedocument.cpp document/katetextline.cpp \ + view/kateundohistory.cpp \ + view/kateview.cpp \ + view/kateviewdialog.cpp \ + interfaces/interfaces.cpp + +INTERFACES = +INCLUDEPATH += $(OPIEDIR)/include $(OPIEDIR)/noncore/apps/tinykate/libkate/microkde \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/document \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/view \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/interfaces \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/ktexteditor \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/qt3back +DEPENDPATH += $(OPIEDIR)/include +LIBS += -lqpe -lopie +TARGET = tinykate + +INCLUDEPATH += $(OPIEDIR)/include +DESTDIR = $(QTDIR)/lib$(PROJMAK) + 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 @@ +#ifndef MINIKDE_KACTION_H +#define MINIKDE_KACTION_H + +#include + +#define KAction QAction + +#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 @@ +#include + +#include "kapplication.h" + +int KApplication::random() +{ + return rand(); +} 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 @@ +#ifndef MINIKDE_KAPPLICATION_H +#define MINIKDE_KAPPLICATION_H + +class KApplication +{ + public: + static int random(); + static int cursorFlashTime() { return 1000; } +}; + +#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 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Martin Jones (mjones@kde.org) + Copyright (C) 1999 Cristian Tibirna (ctibirna@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include +#include "kcolordialog.h" +#include "kcolorbtn.h" + +KColorButton::KColorButton( QWidget *parent, const char *name ) + : QPushButton( parent, name ), dragFlag(false) +{ + // 2000-10-15 (putzer): fixes broken keyboard usage + connect (this, SIGNAL(clicked()), this, SLOT(chooseColor())); +} + +KColorButton::KColorButton( const QColor &c, QWidget *parent, + const char *name ) + : QPushButton( parent, name ), col(c), dragFlag(false) +{ + + // 2000-10-15 (putzer): fixes broken keyboard usage + connect (this, SIGNAL(clicked()), this, SLOT(chooseColor())); +} + +void KColorButton::setColor( const QColor &c ) +{ + col = c; + repaint( false ); +} + +void KColorButton::drawButtonLabel( QPainter *painter ) +{ + QRect r = QApplication::style().buttonRect( 0, 0, width(), height() ); + int l = r.x(); + int t = r.y(); + int w = r.width(); + int h = r.height(); + int b = 5; + + QColor lnCol = colorGroup().text(); + QColor fillCol = isEnabled() ? col : backgroundColor(); + + if ( isDown() ) { + qDrawPlainRect( painter, l+b+1, t+b+1, w-b*2, h-b*2, lnCol, 1, 0 ); + b++; + painter->fillRect( l+b+1, t+b+1, w-b*2, h-b*2, fillCol ); + } else { + qDrawPlainRect( painter, l+b, t+b, w-b*2, h-b*2, lnCol, 1, 0 ); + b++; + painter->fillRect( l+b, t+b, w-b*2, h-b*2, fillCol ); + } +} + +void KColorButton::chooseColor() +{ + if( KColorDialog::getColor( col) == QDialog::Rejected ) + { + return; + } + + repaint( false ); + emit changed( col ); +} + 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 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Martin Jones (mjones@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __COLBTN_H__ +#define __COLBTN_H__ + +#include + +/** +* This widget can be used to display or allow user selection of a colour. +* +* @see KColorDialog +* +* @short A pushbutton to display or allow user selection of a colour. +* @version $Id$ +*/ +class KColorButton : public QPushButton +{ + Q_OBJECT + Q_PROPERTY( QColor color READ color WRITE setColor ) + +public: + /** + * Constructor. Create a KColorButton. + */ + KColorButton( QWidget *parent, const char *name = 0L ); + /** + * Constructor. Create a KColorButton. + * @param c The initial colour of the button. + */ + KColorButton( const QColor &c, QWidget *parent, const char *name = 0L ); + /** + * Destructor. + */ + virtual ~KColorButton() {} + + /** + * The current colour. + * @return The current colour. + */ + QColor color() const + { return col; } + /** + * Set the current colour. + * + * @param c The colour to set. + */ + void setColor( const QColor &c ); + +signals: + /** + * This signal will be emitted when the colour of the widget + * is changed, either with @ref #setColor() or via user selection. + */ + void changed( const QColor &newColor ); + +protected slots: + void chooseColor(); + +protected: + /** + * @reimplemented + */ + virtual void drawButtonLabel( QPainter *p ); + +private: + QColor col; + QPoint mPos; + bool dragFlag; + + class KColorButtonPrivate; + KColorButtonPrivate *d; +}; + +#endif + 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 @@ +#ifndef K_COLOR_BUTTON_H +#define K_COLOR_BUTTON_H +#include +#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 @@ +#include "kcolordialog.h" + +int KColorDialog::getColor( const QColor & ) +{ + return 0; +} 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 @@ +#ifndef MINIKDE_KCOLORDIALOG_H +#define MINIKDE_KCOLORDIALOG_H + +#include + +class KColorDialog +{ + public: + enum { Accepted }; + + static int getColor( const QColor & ); +}; + +#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 @@ +#include +#include + +#include "kdebug.h" + +#include "kconfig.h" + +QString KConfig::mGroup = ""; +//QString KConfig::mGroup = "General"; + +KConfig::KConfig( const QString &fileName ) + : mFileName( fileName ), mDirty( false ) +{ + kdDebug() << "KConfig::KConfig(): '" << fileName << "'" << endl; + + load(); +} + + +KConfig::~KConfig() +{ + sync(); +} + +void KConfig::setGroup( const QString &group ) +{ + return; + +// kdDebug() << "KConfig::setGroup(): '" << group << "'" << endl; + + mGroup = group; + + if ( mGroup.right( 1 ) != "/" ) mGroup += "/"; +} + + +QValueList KConfig::readIntListEntry( const QString & ) +{ + QValueList l; + return l; +} + +int KConfig::readNumEntry( const QString &, int def ) +{ + return def; +} + +QString KConfig::readEntry( const QString &key, const QString &def ) +{ + QMap::ConstIterator it = mStringMap.find( mGroup + key ); + + if ( it == mStringMap.end() ) { + return def; + } + + return *it; +} + +QStringList KConfig::readListEntry( const QString & ) +{ + return QStringList(); +} + +bool KConfig::readBoolEntry( const QString &key, bool def ) +{ + QMap::ConstIterator it = mBoolMap.find( mGroup + key ); + + if ( it == mBoolMap.end() ) { + return def; + } + + return *it; +} + +QColor KConfig::readColorEntry( const QString &, QColor *def ) +{ + if ( def ) return *def; + return QColor(); +} + +QFont KConfig::readFontEntry( const QString &, QFont *def ) +{ + if ( def ) return *def; + return QFont(); +} + + +void KConfig::writeEntry( const QString &, QValueList ) +{ +} + +void KConfig::writeEntry( const QString &, int ) +{ +} + +void KConfig::writeEntry( const QString &key, const QString &value ) +{ + mStringMap.insert( mGroup + key, value ); + + mDirty = true; +} + +void KConfig::writeEntry( const QString &, const QStringList & ) +{ +} + +void KConfig::writeEntry( const QString &key, bool value) +{ + mBoolMap.insert( mGroup + key, value ); + + mDirty = true; +} + +void KConfig::writeEntry( const QString &, const QColor & ) +{ +} + +void KConfig::writeEntry( const QString &, const QFont & ) +{ +} + +void KConfig::load() +{ + mBoolMap.clear(); + mStringMap.clear(); + + QFile f( mFileName ); + if ( !f.open( IO_ReadOnly ) ) { + kdDebug() << "KConfig::load(): Can't open file '" << mFileName << "'" + << endl; + return; + } + + + QTextStream t( &f ); + + QString line = t.readLine(); + + while ( !line.isNull() ) { + QStringList tokens = QStringList::split( ",", line ); + if ( tokens[0] == "bool" ) { + bool value = false; + if ( tokens[2] == "1" ) value = true; + + mBoolMap.insert( tokens[1], value ); + } else if ( tokens[0] == "QString" ) { + QString value = tokens[2]; + mStringMap.insert( tokens[1], value ); + } + + line = t.readLine(); + } +} + +void KConfig::sync() +{ + if ( !mDirty ) return; + + QFile f( mFileName ); + if ( !f.open( IO_WriteOnly ) ) { + kdDebug() << "KConfig::sync(): Can't open file '" << mFileName << "'" + << endl; + return; + } + + QTextStream t( &f ); + + QMap::ConstIterator itBool; + for( itBool = mBoolMap.begin(); itBool != mBoolMap.end(); ++itBool ) { + t << "bool," << itBool.key() << "," << (*itBool ) << endl; + } + + QMap::ConstIterator itString; + for( itString = mStringMap.begin(); itString != mStringMap.end(); ++itString ) { + t << "QString," << itString.key() << "," << (*itString ) << endl; + } + + f.close(); + + mDirty = false; +} diff --git a/noncore/apps/tinykate/libkate/microkde/kconfig.h b/noncore/apps/tinykate/libkate/microkde/kconfig.h new file mode 100644 index 0000000..8bd768a --- a/dev/null +++ b/noncore/apps/tinykate/libkate/microkde/kconfig.h @@ -0,0 +1,51 @@ +#ifndef MINIKDE_KCONFIG_H +#define MINIKDE_KCONFIG_H + +#include +#include +#include +#include +#include +#include + +class KConfig +{ + public: + KConfig( const QString & ); + ~KConfig(); + + void setGroup( const QString & ); + + bool hasGroup( const QString &) {return false;} + + QValueList readIntListEntry( const QString & ); + int readNumEntry( const QString &, int def=0 ); + QString readEntry( const QString &, const QString &def=QString::null ); + QStringList readListEntry( const QString & ); + bool readBoolEntry( const QString &, bool def=false ); + QColor readColorEntry( const QString &, QColor * ); + QFont readFontEntry( const QString &, QFont * ); + + void writeEntry( const QString &, QValueList ); + void writeEntry( const QString &, int ); + void writeEntry( const QString &, const QString & ); + void writeEntry( const QString &, const QStringList & ); + void writeEntry( const QString &, bool ); + void writeEntry( const QString &, const QColor & ); + void writeEntry( const QString &, const QFont & ); + + void load(); + void sync(); + + private: + static QString mGroup; + + QString mFileName; + + QMap mBoolMap; + QMap mStringMap; + + bool mDirty; +}; + +#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 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "kdatepicker.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kdatetbl.h" +#include "kdatepicker.moc" + + +KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name) + : QFrame(parent,name), + yearForward(new QToolButton(this)), + yearBackward(new QToolButton(this)), + monthForward(new QToolButton(this)), + monthBackward(new QToolButton(this)), + selectMonth(new QToolButton(this)), + selectYear(new QToolButton(this)), + line(new QLineEdit(this)), + val(new KDateValidator(this)), + table(new KDateTable(this)), + fontsize(10) +{ + // ----- + setFontSize(10); + line->setValidator(val); + yearForward->setPixmap(BarIcon(QString::fromLatin1("2rightarrow"))); + yearBackward->setPixmap(BarIcon(QString::fromLatin1("2leftarrow"))); + monthForward->setPixmap(BarIcon(QString::fromLatin1("1rightarrow"))); + monthBackward->setPixmap(BarIcon(QString::fromLatin1("1leftarrow"))); + setDate(dt); // set button texts + connect(table, SIGNAL(dateChanged(QDate)), SLOT(dateChangedSlot(QDate))); + connect(table, SIGNAL(tableClicked()), SLOT(tableClickedSlot())); + connect(monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked())); + connect(monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked())); + connect(yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked())); + connect(yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked())); + connect(selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked())); + connect(selectYear, SIGNAL(clicked()), SLOT(selectYearClicked())); + connect(line, SIGNAL(returnPressed()), SLOT(lineEnterPressed())); +} + +KDatePicker::~KDatePicker() +{ +} + +void +KDatePicker::resizeEvent(QResizeEvent*) +{ + QWidget *buttons[] = { + yearBackward, + monthBackward, + selectMonth, + selectYear, + monthForward, + yearForward }; + const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]); + QSize sizes[NoOfButtons]; + int buttonHeight=0; + int count; + int w; + int x=0; + // ----- calculate button row height: + for(count=0; countsizeHint(); + buttonHeight=QMAX(buttonHeight, sizes[count].height()); + } + // ----- calculate size of the month button: + w=0; + for(count=0; countsetGeometry(x, 0, w, buttonHeight); + x+=w; + } + // ----- place the line edit for direct input: + sizes[0]=line->sizeHint(); + line->setGeometry(0, height()-sizes[0].height(), width(), sizes[0].height()); + // ----- adjust the table: + table->setGeometry(0, buttonHeight, width(), + height()-buttonHeight-sizes[0].height()); +} + +void +KDatePicker::dateChangedSlot(QDate date) +{ + kdDebug() << "KDatePicker::dateChangedSlot: date changed (" << date.year() << "/" << date.month() << "/" << date.day() << ")." << endl; + line->setText(KGlobal::locale()->formatDate(date, true)); + emit(dateChanged(date)); +} + +void +KDatePicker::tableClickedSlot() +{ + kdDebug() << "KDatePicker::tableClickedSlot: table clicked." << endl; + emit(dateSelected(table->getDate())); + emit(tableClicked()); +} + +const QDate& +KDatePicker::getDate() const +{ + return table->getDate(); +} + +const QDate & +KDatePicker::date() const +{ + return table->getDate(); +} + +bool +KDatePicker::setDate(const QDate& date) +{ + if(date.isValid()) { + QString temp; + // ----- + table->setDate(date); + selectMonth->setText(KGlobal::locale()->monthName(date.month(), false)); + temp.setNum(date.year()); + selectYear->setText(temp); + line->setText(KGlobal::locale()->formatDate(date, true)); + return true; + } else { + kdDebug() << "KDatePicker::setDate: refusing to set invalid date." << endl; + return false; + } +} + +void +KDatePicker::monthForwardClicked() +{ + QDate temp=table->getDate(); + int day=temp.day(); + // ----- + if(temp.month()==12) { + temp.setYMD(temp.year()+1, 1, 1); + } else { + temp.setYMD(temp.year(), temp.month()+1, 1); + } + if(temp.daysInMonth()getDate(); + int day=temp.day(); + // ----- + if(temp.month()==1) + { + temp.setYMD(temp.year()-1, 12, 1); + } else { + temp.setYMD(temp.year(), temp.month()-1, 1); + } + if(temp.daysInMonth()getDate(); + int day=temp.day(); + // ----- + temp.setYMD(temp.year()+1, temp.month(), 1); + if(temp.daysInMonth()getDate(); + int day=temp.day(); + // ----- + temp.setYMD(temp.year()-1, temp.month(), 1); + if(temp.daysInMonth()resize(picker->sizeHint()); + popup->setMainWidget(picker); + picker->setFocus(); + connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int))); + if(popup->exec(selectMonth->mapToGlobal(QPoint(0, selectMonth->height())))) + { + QDate date; + int day; + // ----- + month=picker->getResult(); + date=table->getDate(); + day=date.day(); + // ----- construct a valid date in this month: + date.setYMD(date.year(), month, 1); + date.setYMD(date.year(), month, QMIN(day, date.daysInMonth())); + // ----- set this month + setDate(date); + } else { + KNotifyClient::beep(); + } + delete popup; +} + +void +KDatePicker::selectYearClicked() +{ + int year; + KPopupFrame* popup = new KPopupFrame(this); + KDateInternalYearSelector* picker = new KDateInternalYearSelector(fontsize, popup); + // ----- + picker->resize(picker->sizeHint()); + popup->setMainWidget(picker); + connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int))); + picker->setFocus(); + if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height())))) + { + QDate date; + int day; + // ----- + year=picker->getYear(); + date=table->getDate(); + day=date.day(); + // ----- construct a valid date in this month: + date.setYMD(year, date.month(), 1); + date.setYMD(year, date.month(), QMIN(day, date.daysInMonth())); + // ----- set this month + setDate(date); + } else { + KNotifyClient::beep(); + } + delete popup; +} + +void +KDatePicker::setEnabled(bool enable) +{ + QWidget *widgets[]= { + yearForward, yearBackward, monthForward, monthBackward, + selectMonth, selectYear, + line, table }; + const int Size=sizeof(widgets)/sizeof(widgets[0]); + int count; + // ----- + for(count=0; countsetEnabled(enable); + } +} + +void +KDatePicker::lineEnterPressed() +{ + QDate temp; + // ----- + if(val->date(line->text(), temp)==QValidator::Acceptable) + { + kdDebug() << "KDatePicker::lineEnterPressed: valid date entered." << endl; + emit(dateEntered(temp)); + setDate(temp); + } else { + KNotifyClient::beep(); + kdDebug() << "KDatePicker::lineEnterPressed: invalid date entered." << endl; + } +} + +QSize +KDatePicker::sizeHint() const +{ + QSize tableSize=table->sizeHint(); + QWidget *buttons[]={ + yearBackward, + monthBackward, + selectMonth, + selectYear, + monthForward, + yearForward }; + const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]); + QSize sizes[NoOfButtons]; + int cx=0, cy=0, count; + // ----- store the size hints: + for(count=0; countsizeHint(); + if(buttons[count]==selectMonth) + { + cx+=maxMonthRect.width(); + } else { + cx+=sizes[count].width(); + } + cy=QMAX(sizes[count].height(), cy); + } + // ----- calculate width hint: + cx=QMAX(cx, tableSize.width()); // line edit ignored + // ----- calculate height hint: + cy+=tableSize.height()+line->sizeHint().height(); + return QSize(cx, cy); +} + +void +KDatePicker::setFontSize(int s) +{ + QWidget *buttons[]= { + // yearBackward, + // monthBackward, + selectMonth, + selectYear, + // monthForward, + // yearForward + }; + const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]); + int count; + QFont font; + QRect r; + // ----- + fontsize=s; + for(count=0; countfont(); + font.setPointSize(s); + buttons[count]->setFont(font); + } + QFontMetrics metrics(selectMonth->fontMetrics()); + for(int i=1; i <= 12; ++i) + { // maxMonthRect is used by sizeHint() + r=metrics.boundingRect(KGlobal::locale()->monthName(i, false)); + maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width())); + maxMonthRect.setHeight(QMAX(r.height(), maxMonthRect.height())); + } + table->setFontSize(s); +} + +void KDatePicker::virtual_hook( int id, void* data ) +{ /*BASE::virtual_hook( id, data );*/ } + 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 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef MICROKDE_KDATEPICKER_H +#define MICROKDE_KDATEPICKER_H +#include +#include + +class QLineEdit; +class QToolButton; +class KDateValidator; +class KDateTable; + +/** + * Provides a widget for calendar date input. + * + * Different from the + * previous versions, it now emits two types of signals, either + * @ref dateSelected() or @ref dateEntered() (see documentation for both + * signals). + * + * A line edit has been added in the newer versions to allow the user + * to select a date directly by entering numbers like 19990101 + * or 990101. + * + * @image kdatepicker.png KDatePicker + * + * @version $Id$ + * @author Tim Gilman, Mirko Boehm + * + * @short A date selection widget. + **/ +class KDatePicker: public QFrame +{ + Q_OBJECT +public: + /** The usual constructor. The given date will be displayed + * initially. + **/ + KDatePicker(QWidget *parent=0, + QDate=QDate::currentDate(), + const char *name=0); + /** + * The destructor. + **/ + virtual ~KDatePicker(); + + /** The size hint for date pickers. The size hint recommends the + * minimum size of the widget so that all elements may be placed + * without clipping. This sometimes looks ugly, so when using the + * size hint, try adding 28 to each of the reported numbers of + * pixels. + **/ + QSize sizeHint() const; + + /** + * Sets the date. + * + * @returns @p false and does not change anything + * if the date given is invalid. + **/ + bool setDate(const QDate&); + + /** + * Returns the selected date. + * @deprecated + **/ + const QDate& getDate() const; + + /** + * @returns the selected date. + */ + const QDate &date() const; + + /** + * Enables or disables the widget. + **/ + void setEnabled(bool); + + /** + * Sets the font size of the widgets elements. + **/ + void setFontSize(int); + /** + * Returns the font size of the widget elements. + */ + int fontSize() const + { return fontsize; } + +protected: + /// the resize event + void resizeEvent(QResizeEvent*); + /// the year forward button + QToolButton *yearForward; + /// the year backward button + QToolButton *yearBackward; + /// the month forward button + QToolButton *monthForward; + /// the month backward button + QToolButton *monthBackward; + /// the button for selecting the month directly + QToolButton *selectMonth; + /// the button for selecting the year directly + QToolButton *selectYear; + /// the line edit to enter the date directly + QLineEdit *line; + /// the validator for the line edit: + KDateValidator *val; + /// the date table + KDateTable *table; + /// the size calculated during resize events + // QSize sizehint; + /// the widest month string in pixels: + QSize maxMonthRect; +protected slots: + void dateChangedSlot(QDate); + void tableClickedSlot(); + void monthForwardClicked(); + void monthBackwardClicked(); + void yearForwardClicked(); + void yearBackwardClicked(); + void selectMonthClicked(); + void selectYearClicked(); + void lineEnterPressed(); +signals: + /** This signal is emitted each time the selected date is changed. + * Usually, this does not mean that the date has been entered, + * since the date also changes, for example, when another month is + * selected. + * @see dateSelected + */ + void dateChanged(QDate); + /** This signal is emitted each time a day has been selected by + * clicking on the table (hitting a day in the current month). It + * has the same meaning as dateSelected() in older versions of + * KDatePicker. + */ + void dateSelected(QDate); + /** This signal is emitted when enter is pressed and a VALID date + * has been entered before into the line edit. Connect to both + * dateEntered() and dateSelected() to receive all events where the + * user really enters a date. + */ + void dateEntered(QDate); + /** This signal is emitted when the day has been selected by + * clicking on it in the table. + */ + void tableClicked(); + +private: + /// the font size for the widget + int fontsize; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDatePickerPrivate; + KDatePickerPrivate *d; +}; + +#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 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/////////////////// KDateTable widget class ////////////////////// +// +// Copyright (C) 1997 Tim D. Gilman +// (C) 1998-2001 Mirko Boehm +// Written using Qt (http://www.troll.no) for the +// KDE project (http://www.kde.org) +// +// This is a support class for the KDatePicker class. It just +// draws the calender table without titles, but could theoretically +// be used as a standalone. +// +// When a date is selected by the user, it emits a signal: +// dateSelected(QDate) + +#include +#include +#include +#include +#include +#include +#include "kdatetbl.h" +#include +#include +#include +#include +#include +#include +#include + +KDateValidator::KDateValidator(QWidget* parent, const char* name) + : QValidator(parent, name) +{ +} + +QValidator::State +KDateValidator::validate(QString& text, int&) const +{ + QDate temp; + // ----- everything is tested in date(): + return date(text, temp); +} + +QValidator::State +KDateValidator::date(const QString& text, QDate& d) const +{ + QDate tmp = KGlobal::locale()->readDate(text); + if (!tmp.isNull()) + { + d = tmp; + return Acceptable; + } else + return Valid; +} + +void +KDateValidator::fixup( QString& ) const +{ + +} + +KDateTable::KDateTable(QWidget *parent, QDate date_, const char* name, WFlags f) + : QGridView(parent, name, f) +{ + setFontSize(10); + if(!date_.isValid()) + { + kdDebug() << "KDateTable ctor: WARNING: Given date is invalid, using current date." << endl; + date_=QDate::currentDate(); + } + setFocusPolicy( QWidget::StrongFocus ); + setNumRows(7); // 6 weeks max + headline + setNumCols(7); // 7 days a week + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); +#if 0 + viewport()->setEraseColor(lightGray); +#endif + setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth +} + +void +KDateTable::paintCell(QPainter *painter, int row, int col) +{ + QRect rect; + QString text; + QPen pen; + int w=cellWidth(); + int h=cellHeight(); + int pos; + QBrush brushBlue(blue); + QBrush brushLightblue(lightGray); + QFont font=KGlobalSettings::generalFont(); + // ----- + font.setPointSize(fontsize); + if(row==0) + { // we are drawing the headline + font.setBold(true); + painter->setFont(font); + bool normalday = true; + QString daystr; + if (KGlobal::locale()->weekStartsMonday()) + { + daystr = KGlobal::locale()->weekDayName(col+1, true); + if (col == 5 || col == 6) + normalday = false; + } else { + daystr = KGlobal::locale()->weekDayName(col==0? 7 : col, true); + if (col == 0 || col == 6) + normalday = false; + } + if (!normalday) + { + painter->setPen(lightGray); + painter->setBrush(brushLightblue); + painter->drawRect(0, 0, w, h); + painter->setPen(blue); + } else { + painter->setPen(blue); + painter->setBrush(brushBlue); + painter->drawRect(0, 0, w, h); + painter->setPen(white); + } + painter->drawText(0, 0, w, h-1, AlignCenter, + daystr, -1, &rect); + painter->setPen(black); + painter->moveTo(0, h-1); + painter->lineTo(w-1, h-1); + // ----- draw the weekday: + } else { + painter->setFont(font); + pos=7*(row-1)+col; + if (KGlobal::locale()->weekStartsMonday()) + pos++; + if(possetPen(gray); + } else { // paint a day of the current month + text.setNum(pos-firstday+1); + painter->setPen(black); + } + + pen=painter->pen(); + if(firstday+date.day()-1==pos) + { + if(hasFocus()) + { // draw the currently selected date + painter->setPen(red); + painter->setBrush(darkRed); + pen=white; + } else { + painter->setPen(darkGray); + painter->setBrush(darkGray); + pen=white; + } + } else { + painter->setBrush(lightGray); + painter->setPen(lightGray); + } + painter->drawRect(0, 0, w, h); + painter->setPen(pen); + painter->drawText(0, 0, w, h, AlignCenter, text, -1, &rect); + } + if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width()); + if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height()); +} + +void +KDateTable::keyPressEvent( QKeyEvent *e ) +{ + if ( e->key() == Qt::Key_Prior ) { + if ( date.month() == 1 ) { + KNotifyClient::beep(); + return; + } + int day = date.day(); + if ( day > 27 ) + while ( !QDate::isValid( date.year(), date.month()-1, day ) ) + day--; + setDate(QDate(date.year(), date.month()-1, day)); + return; + } + if ( e->key() == Qt::Key_Next ) { + if ( date.month() == 12 ) { + KNotifyClient::beep(); + return; + } + int day = date.day(); + if ( day > 27 ) + while ( !QDate::isValid( date.year(), date.month()+1, day ) ) + day--; + setDate(QDate(date.year(), date.month()+1, day)); + return; + } + + int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0; + + int temp=firstday+date.day()-dayoff; + int pos = temp; + + if ( e->key() == Qt::Key_Up ) { + pos -= 7; + } + if ( e->key() == Qt::Key_Down ) { + pos += 7; + } + if ( e->key() == Qt::Key_Left ) { + pos--; + } + if ( e->key() == Qt::Key_Right ) { + pos++; + } + + if(pos+dayoff<=firstday) + { // this day is in the previous month + KNotifyClient::beep(); + return; + } + if(firstday+numdayswidth()/7); + setCellHeight(viewport()->height()/7); +} + +void +KDateTable::setFontSize(int size) +{ + int count; + QFontMetrics metrics(fontMetrics()); + QRect rect; + // ----- store rectangles: + fontsize=size; + // ----- find largest day name: + maxCell.setWidth(0); + maxCell.setHeight(0); + for(count=0; count<7; ++count) + { + rect=metrics.boundingRect(KGlobal::locale()->weekDayName(count+1, true)); + maxCell.setWidth(QMAX(maxCell.width(), rect.width())); + maxCell.setHeight(QMAX(maxCell.height(), rect.height())); + } + // ----- compare with a real wide number and add some space: + rect=metrics.boundingRect(QString::fromLatin1("88")); + maxCell.setWidth(QMAX(maxCell.width()+2, rect.width())); + maxCell.setHeight(QMAX(maxCell.height()+4, rect.height())); +} + +void +KDateTable::contentsMousePressEvent(QMouseEvent *e) +{ + if(e->type()!=QEvent::MouseButtonPress) + { // the KDatePicker only reacts on mouse press events: + return; + } + if(!isEnabled()) + { + KNotifyClient::beep(); + return; + } + + int dayoff = KGlobal::locale()->weekStartsMonday() ? 1 : 0; + // ----- + int row, col, pos, temp; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + if(row<0 || col<0) + { // the user clicked on the frame of the table + return; + } + pos=7*(row-1)+col+1; + if(pos+dayoff<=firstday) + { // this day is in the previous month + KNotifyClient::beep(); + return; + } + if(firstday+numdays0 && maxCell.width()>0) + { + return QSize(maxCell.width()*numCols()+2*frameWidth(), + (maxCell.height()+2)*numRows()+2*frameWidth()); + } else { + kdDebug() << "KDateTable::sizeHint: obscure failure - " << endl; + return QSize(-1, -1); + } +} + +KDateInternalMonthPicker::KDateInternalMonthPicker +(int fontsize, QWidget* parent, const char* name) + : QGridView(parent, name), + result(0) // invalid +{ + QRect rect; + QFont font; + // ----- + activeCol = -1; + activeRow = -1; + font=KGlobalSettings::generalFont(); + font.setPointSize(fontsize); + setFont(font); + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); + setFrameStyle(QFrame::NoFrame); + setNumRows(4); + setNumCols(3); + // enable to find drawing failures: + // setTableFlags(Tbl_clipCellPainting); +#if 0 + viewport()->setEraseColor(lightGray); // for consistency with the datepicker +#endif + // ----- find the preferred size + // (this is slow, possibly, but unfortunatly it is needed here): + QFontMetrics metrics(font); + for(int i=1; i <= 12; ++i) + { + rect=metrics.boundingRect(KGlobal::locale()->monthName(i, false)); + if(max.width()setPen(black); +} + +void +KDateInternalMonthPicker::viewportResizeEvent(QResizeEvent*) +{ + setCellWidth(width()/3); + setCellHeight(height()/4); +} + +void +KDateInternalMonthPicker::paintCell(QPainter* painter, int row, int col) +{ + int index; + QString text; + // ----- find the number of the cell: + index=3*row+col+1; + text=KGlobal::locale()->monthName(index, false); + painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text); + if ( activeCol == col && activeRow == row ) + painter->drawRect( 0, 0, cellWidth(), cellHeight() ); +} + +void +KDateInternalMonthPicker::contentsMousePressEvent(QMouseEvent *e) +{ + if(!isEnabled() || e->button() != LeftButton) + { + KNotifyClient::beep(); + return; + } + // ----- + int row, col; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + + if(row<0 || col<0) + { // the user clicked on the frame of the table + activeCol = -1; + activeRow = -1; + } else { + activeCol = col; + activeRow = row; + updateCell( row, col /*, false */ ); + } +} + +void +KDateInternalMonthPicker::contentsMouseMoveEvent(QMouseEvent *e) +{ + if (e->state() & LeftButton) + { + int row, col; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + int tmpRow = -1, tmpCol = -1; + if(row<0 || col<0) + { // the user clicked on the frame of the table + if ( activeCol > -1 ) + { + tmpRow = activeRow; + tmpCol = activeCol; + } + activeCol = -1; + activeRow = -1; + } else { + bool differentCell = (activeRow != row || activeCol != col); + if ( activeCol > -1 && differentCell) + { + tmpRow = activeRow; + tmpCol = activeCol; + } + if ( differentCell) + { + activeRow = row; + activeCol = col; + updateCell( row, col /*, false */ ); // mark the new active cell + } + } + if ( tmpRow > -1 ) // repaint the former active cell + updateCell( tmpRow, tmpCol /*, true */ ); + } +} + +void +KDateInternalMonthPicker::contentsMouseReleaseEvent(QMouseEvent *e) +{ + if(!isEnabled()) + { + return; + } + // ----- + int row, col, pos; + QPoint mouseCoord; + // ----- + mouseCoord = e->pos(); + row=rowAt(mouseCoord.y()); + col=columnAt(mouseCoord.x()); + if(row<0 || col<0) + { // the user clicked on the frame of the table + emit(closeMe(0)); + } + pos=3*row+col+1; + result=pos; + emit(closeMe(1)); +} + + + +KDateInternalYearSelector::KDateInternalYearSelector +(int fontsize, QWidget* parent, const char* name) + : QLineEdit(parent, name), + val(new QIntValidator(this)), + result(0) +{ + QFont font; + // ----- + font=KGlobalSettings::generalFont(); + font.setPointSize(fontsize); + setFont(font); +#if 0 + setFrameStyle(QFrame::NoFrame); +#endif + // we have to respect the limits of QDate here, I fear: + val->setRange(0, 8000); + setValidator(val); + connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot())); +} + +void +KDateInternalYearSelector::yearEnteredSlot() +{ + bool ok; + int year; + QDate date; + // ----- check if this is a valid year: + year=text().toInt(&ok); + if(!ok) + { + KNotifyClient::beep(); + return; + } + date.setYMD(year, 1, 1); + if(!date.isValid()) + { + KNotifyClient::beep(); + return; + } + result=year; + emit(closeMe(1)); +} + +int +KDateInternalYearSelector::getYear() +{ + return result; +} + +void +KDateInternalYearSelector::setYear(int year) +{ + QString temp; + // ----- + temp.setNum(year); + setText(temp); +} + +KPopupFrame::KPopupFrame(QWidget* parent, const char* name) + : QFrame(parent, name, WType_Popup), + result(0), // rejected + main(0) +{ + setFrameStyle(QFrame::Box|QFrame::Raised); + setMidLineWidth(2); +} + +void +KPopupFrame::keyPressEvent(QKeyEvent* e) +{ + if(e->key()==Key_Escape) + { + result=0; // rejected + qApp->exit_loop(); + } +} + +void +KPopupFrame::close(int r) +{ + result=r; + qApp->exit_loop(); +} + +void +KPopupFrame::setMainWidget(QWidget* m) +{ + main=m; + if(main!=0) + { + resize(main->width()+2*frameWidth(), main->height()+2*frameWidth()); + } +} + +void +KPopupFrame::resizeEvent(QResizeEvent*) +{ + if(main!=0) + { + main->setGeometry(frameWidth(), frameWidth(), + width()-2*frameWidth(), height()-2*frameWidth()); + } +} + +void +KPopupFrame::popup(const QPoint &pos) +{ + // Make sure the whole popup is visible. + QRect d = QApplication::desktop()->frameGeometry(); + int x = pos.x(); + int y = pos.y(); + int w = width(); + int h = height(); + if (x+w > d.x()+d.width()) + x = d.width() - w; + if (y+h > d.y()+d.height()) + y = d.height() - h; + if (x < d.x()) + x = 0; + if (y < d.y()) + y = 0; + + // Pop the thingy up. + move(x, y); + show(); +} + +int +KPopupFrame::exec(QPoint pos) +{ + popup(pos); + repaint(); + qApp->enter_loop(); + hide(); + return result; +} + +int +KPopupFrame::exec(int x, int y) +{ + return exec(QPoint(x, y)); +} + +void KPopupFrame::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDateTable::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +#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 @@ +/* -*- C++ -*- + This file is part of the KDE libraries + Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) + (C) 1998-2001 Mirko Boehm (mirko@kde.org) + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KDATETBL_H +#define KDATETBL_H + +#include +#include +#include +#include + +/** +* A table containing month names. It is used to pick a month directly. +* @internal +* @version $Id$ +* @author Tim Gilman, Mirko Boehm +*/ +class KDateInternalMonthPicker : public QGridView +{ + Q_OBJECT +protected: + /** + * Store the month that has been clicked [1..12]. + */ + int result; + /** + * the cell under mouse cursor when LBM is pressed + */ + short int activeCol; + short int activeRow; + /** + * Contains the largest rectangle needed by the month names. + */ + QRect max; +signals: + /** + * This is send from the mouse click event handler. + */ + void closeMe(int); +public: + /** + * The constructor. + */ + KDateInternalMonthPicker(int fontsize, QWidget* parent, const char* name=0); + /** + * The size hint. + */ + QSize sizeHint() const; + /** + * Return the result. 0 means no selection (reject()), 1..12 are the + * months. + */ + int getResult() const; +protected: + /** + * Set up the painter. + */ + void setupPainter(QPainter *p); + /** + * The resize event. + */ + void viewportResizeEvent(QResizeEvent*); + /** + * Paint a cell. This simply draws the month names in it. + */ + virtual void paintCell(QPainter* painter, int row, int col); + /** + * Catch mouse click and move events to paint a rectangle around the item. + */ + void contentsMousePressEvent(QMouseEvent *e); + void contentsMouseMoveEvent(QMouseEvent *e); + /** + * Emit monthSelected(int) when a cell has been released. + */ + void contentsMouseReleaseEvent(QMouseEvent *e); + +private: + class KDateInternalMonthPrivate; + KDateInternalMonthPrivate *d; +}; + +/** Year selection widget. +* @internal +* @version $Id$ +* @author Tim Gilman, Mirko Boehm +*/ +class KDateInternalYearSelector : public QLineEdit +{ + Q_OBJECT +protected: + QIntValidator *val; + int result; +public slots: + void yearEnteredSlot(); +signals: + void closeMe(int); +public: + KDateInternalYearSelector(int fontsize, + QWidget* parent=0, + const char* name=0); + int getYear(); + void setYear(int year); + +private: + class KDateInternalYearPrivate; + KDateInternalYearPrivate *d; +}; + +/** + * Frame with popup menu behaviour. + * @author Tim Gilman, Mirko Boehm + * @version $Id$ + */ +class KPopupFrame : public QFrame +{ + Q_OBJECT +protected: + /** + * The result. It is returned from exec() when the popup window closes. + */ + int result; + /** + * Catch key press events. + */ + void keyPressEvent(QKeyEvent* e); + /** + * The only subwidget that uses the whole dialog window. + */ + QWidget *main; +public slots: + /** + * Close the popup window. This is called from the main widget, usually. + * @p r is the result returned from exec(). + */ + void close(int r); +public: + /** + * The contructor. Creates a dialog without buttons. + */ + KPopupFrame(QWidget* parent=0, const char* name=0); + /** + * Set the main widget. You cannot set the main widget from the constructor, + * since it must be a child of the frame itselfes. + * Be careful: the size is set to the main widgets size. It is up to you to + * set the main widgets correct size before setting it as the main + * widget. + */ + void setMainWidget(QWidget* m); + /** + * The resize event. Simply resizes the main widget to the whole + * widgets client size. + */ + void resizeEvent(QResizeEvent*); + /** + * Open the popup window at position pos. + */ + void popup(const QPoint &pos); + /** + * Execute the popup window. + */ + int exec(QPoint p); + /** + * Dito. + */ + int exec(int x, int y); + +private: + + virtual bool close(bool alsoDelete) { return QFrame::close(alsoDelete); } +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KPopupFramePrivate; + KPopupFramePrivate *d; +}; + +/** +* Validates user-entered dates. +*/ +class KDateValidator : public QValidator +{ +public: + KDateValidator(QWidget* parent=0, const char* name=0); + virtual State validate(QString&, int&) const; + virtual void fixup ( QString & input ) const; + State date(const QString&, QDate&) const; +}; + +/** + * Date selection table. + * This is a support class for the KDatePicker class. It just + * draws the calender table without titles, but could theoretically + * be used as a standalone. + * + * When a date is selected by the user, it emits a signal: + * dateSelected(QDate) + * + * @internal + * @version $Id$ + * @author Tim Gilman, Mirko Boehm + */ +class KDateTable : public QGridView +{ + Q_OBJECT +public: + /** + * The constructor. + */ + KDateTable(QWidget *parent=0, + QDate date=QDate::currentDate(), + const char* name=0, WFlags f=0); + /** + * Returns a recommended size for the widget. + * To save some time, the size of the largest used cell content is + * calculated in each paintCell() call, since all calculations have + * to be done there anyway. The size is stored in maxCell. The + * sizeHint() simply returns a multiple of maxCell. + */ + virtual QSize sizeHint() const; + /** + * Set the font size of the date table. + */ + void setFontSize(int size); + /** + * Select and display this date. + */ + bool setDate(const QDate&); + const QDate& getDate() const; + + +protected: + /** + * Paint a cell. + */ + virtual void paintCell(QPainter*, int, int); + /** + * Handle the resize events. + */ + virtual void viewportResizeEvent(QResizeEvent *); + /** + * React on mouse clicks that select a date. + */ + virtual void contentsMousePressEvent(QMouseEvent *); + virtual void keyPressEvent( QKeyEvent *e ); + virtual void focusInEvent( QFocusEvent *e ); + virtual void focusOutEvent( QFocusEvent *e ); + /** + * The font size of the displayed text. + */ + int fontsize; + /** + * The currently selected date. + */ + QDate date; + /** + * The day of the first day in the month [1..7]. + */ + int firstday; + /** + * The number of days in the current month. + */ + int numdays; + /** + * The number of days in the previous month. + */ + int numDaysPrevMonth; + /** + * unused + */ + bool unused_hasSelection; + /** + * Save the size of the largest used cell content. + */ + QRect maxCell; +signals: + /** + * The selected date changed. + */ + void dateChanged(QDate); + /** + * A date has been selected by clicking on the table. + */ + void tableClicked(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDateTablePrivate; + KDateTablePrivate *d; +}; + +#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 @@ +#ifndef MINIKDE_KDEBUG_H +#define MINIKDE_KDEBUG_H + +#include + +#include + +class kdbgstream; +typedef kdbgstream & (*KDBGFUNC)(kdbgstream &); // manipulator function + +class kdbgstream { + public: + kdbgstream(unsigned int _area, unsigned int _level, bool _print = true) : + area(_area), level(_level), print(_print) { } + kdbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print = true) : + output(QString::fromLatin1(initialString)), area(_area), level(_level), print(_print) { } + ~kdbgstream() + { + if (!output.isEmpty()) { + fprintf(stderr,"ASSERT: debug output not ended with \\n\n"); + *this << "\n"; + } + } + kdbgstream &operator<<(bool i) { + if (!print) return *this; + output += QString::fromLatin1(i ? "true" : "false"); + return *this; + } + kdbgstream &operator<<(short i) { + if (!print) return *this; + QString tmp; tmp.setNum(i); output += tmp; + return *this; + } + kdbgstream &operator<<(unsigned short i) { + if (!print) return *this; + QString tmp; tmp.setNum(i); output += tmp; + return *this; + } + kdbgstream &operator<<(char i) { + if (!print) return *this; + QString tmp; tmp.setNum(int(i)); output += tmp; + return *this; + } + kdbgstream &operator<<(unsigned char i) { + if (!print) return *this; + QString tmp; tmp.setNum(static_cast(i)); output += tmp; + return *this; + } + + kdbgstream &operator<<(int i) { + if (!print) return *this; + QString tmp; tmp.setNum(i); output += tmp; + return *this; + } + kdbgstream &operator<<(unsigned int i) { + if (!print) return *this; + QString tmp; tmp.setNum(i); output += tmp; + return *this; + } + kdbgstream &operator<<(long i) { + if (!print) return *this; + QString tmp; tmp.setNum(i); output += tmp; + return *this; + } + kdbgstream &operator<<(unsigned long i) { + if (!print) return *this; + QString tmp; tmp.setNum(i); output += tmp; + return *this; + } + kdbgstream &operator<<(const QString& string) { + if (!print) return *this; + output += string; + if (output.at(output.length() -1 ) == '\n') + flush(); + return *this; + } + kdbgstream &operator<<(const char *string) { + if (!print) return *this; + output += QString::fromUtf8(string); + if (output.at(output.length() - 1) == '\n') + flush(); + return *this; + } + kdbgstream &operator<<(const QCString& string) { + *this << string.data(); + return *this; + } + kdbgstream& operator<<(KDBGFUNC f) { + if (!print) return *this; + return (*f)(*this); + } + kdbgstream& operator<<(double d) { + QString tmp; tmp.setNum(d); output += tmp; + return *this; + } + void flush() { + if (output.isEmpty() || !print) + return; + printf("%s",output.latin1()); + output = QString::null; + } + private: + QString output; + unsigned int area, level; + bool print; +}; + +inline kdbgstream &endl( kdbgstream &s) { s << "\n"; return s; } + +inline kdbgstream kdDebug(int area = 0) { return kdbgstream(area, 0); } + +#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 @@ +#ifndef MINIKDE_KDIALOG_H +#define MINIKDE_KDIALOG_H + +#include + +class KDialog : public QDialog +{ + public: + KDialog( QWidget *parent=0, const char *name=0, bool modal=true ) : + QDialog( parent, name, modal ) {} + + static int spacingHint() { return 3; } + static int marginHint() { return 3; } +}; + +#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 @@ +#include +#include +#include +#include + +#include "klocale.h" +#include "kdebug.h" + +#include "kdialogbase.h" + +KDialogBase::KDialogBase() +{ +} + +KDialogBase::KDialogBase( QWidget *parent, const char *name, bool modal, + const QString &caption, + int buttonMask, ButtonCode defaultButton, + bool separator, + const QString &user1, + const QString &user2, + const QString &user3) : + KDialog( parent, name, modal ) +{ + init( caption, buttonMask, user1 ); +} + +KDialogBase::KDialogBase( int dialogFace, const QString &caption, + int buttonMask, ButtonCode defaultButton, + QWidget *parent, const char *name, bool modal, + bool separator, + const QString &user1, + const QString &user2, + const QString &user3) : + KDialog( parent, name, modal ) +{ + init( caption, buttonMask, user1 ); +} + +KDialogBase::~KDialogBase() +{ +} + +void KDialogBase::init( const QString &caption, int buttonMask, + const QString &user1 ) +{ + mMainWidget = 0; + mTabWidget = 0; + mPlainPage = 0; + mTopLayout = 0; + + if ( !caption.isEmpty() ) { + setCaption( caption ); + } + + if ( buttonMask & User1 ) { + mUser1Button = new QPushButton( user1, this ); + connect( mUser1Button, SIGNAL( clicked() ), SLOT( slotUser1() ) ); + } else { + mUser1Button = 0; + } + + if ( buttonMask & Ok ) { + mOkButton = new QPushButton( i18n("Ok"), this ); + connect( mOkButton, SIGNAL( clicked() ), SLOT( slotOk() ) ); + } else { + mOkButton = 0; + } + + if ( buttonMask & Apply ) { + mApplyButton = new QPushButton( i18n("Apply"), this ); + connect( mApplyButton, SIGNAL( clicked() ), SLOT( slotApply() ) ); + } else { + mApplyButton = 0; + } + + if ( buttonMask & Cancel ) { + mCancelButton = new QPushButton( i18n("Cancel"), this ); + connect( mCancelButton, SIGNAL( clicked() ), SLOT( slotCancel() ) ); + } else { + mCancelButton = 0; + } + + if ( buttonMask & Close ) { + mCloseButton = new QPushButton( i18n("Close"), this ); + connect( mCloseButton, SIGNAL( clicked() ), SLOT( slotClose() ) ); + } else { + mCloseButton = 0; + } +} + +QTabWidget *KDialogBase::tabWidget() +{ + if ( !mTabWidget ) { + mTabWidget = new QTabWidget( this ); + setMainWidget( mTabWidget ); + } + return mTabWidget; +} + +void KDialogBase::initLayout() +{ + delete mTopLayout; + mTopLayout = new QVBoxLayout( this ); + mTopLayout->setMargin( marginHint() ); + mTopLayout->setSpacing( spacingHint() ); + + mTopLayout->addWidget( mMainWidget ); + + QBoxLayout *buttonLayout = new QHBoxLayout; + mTopLayout->addLayout( buttonLayout ); + + if ( mUser1Button ) buttonLayout->addWidget( mUser1Button ); + if ( mOkButton ) buttonLayout->addWidget( mOkButton ); + if ( mApplyButton ) buttonLayout->addWidget( mApplyButton ); + if ( mCancelButton ) buttonLayout->addWidget( mCancelButton ); + if ( mCloseButton ) buttonLayout->addWidget( mCloseButton ); +} + +QFrame *KDialogBase::addPage( const QString &name ) +{ +// kdDebug() << "KDialogBase::addPage(): " << name << endl; + + QFrame *frame = new QFrame( tabWidget() ); + tabWidget()->addTab( frame, name ); + return frame; +} + +QFrame *KDialogBase::addPage( const QString &name, int, const QPixmap & ) +{ + return addPage( name ); +} + + +void KDialogBase::setMainWidget( QWidget *widget ) +{ + kdDebug() << "KDialogBase::setMainWidget()" << endl; + + mMainWidget = widget; + initLayout(); +} + + +void KDialogBase::enableButton( ButtonCode id, bool state ) +{ + QPushButton *button = 0; + switch ( id ) { + case Ok: + button = mOkButton; + break; + case Apply: + button = mApplyButton; + break; + default: + break; + } + if ( button ) { + button->setEnabled( state ); + } +} + +void KDialogBase::enableButtonOK( bool state ) +{ + enableButton( Ok, state ); +} + +void KDialogBase::enableButtonApply( bool state ) +{ + enableButton( Apply, state ); +} + + +int KDialogBase::pageIndex( QWidget *widget ) const +{ + return 0; +} + + +bool KDialogBase::showPage( int index ) +{ + return false; +} + +QFrame *KDialogBase::plainPage() +{ + if ( !mPlainPage ) { + mPlainPage = new QFrame( this ); + setMainWidget( mPlainPage ); + } + return mPlainPage; +} + +void KDialogBase::slotOk() +{ + accept(); +} + +void KDialogBase::slotApply() +{ +} + +void KDialogBase::slotCancel() +{ + reject(); +} + +void KDialogBase::slotClose() +{ + accept(); +} + +void KDialogBase::slotUser1() +{ + emit user1Clicked(); +} 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 @@ +#ifndef MINIKDE_KDIALOGBASE_H +#define MINIKDE_KDIALOGBASE_H + +#include + +#include "kdialog.h" + +class QPushButton; +class QLayout; +class QTabWidget; +class QBoxLayout; + +class KDialogBase : public KDialog +{ + Q_OBJECT + public: + enum ButtonCode + { + Help = 0x00000001, + Default = 0x00000002, + Ok = 0x00000004, + Apply = 0x00000008, + Try = 0x00000010, + Cancel = 0x00000020, + Close = 0x00000040, + User1 = 0x00000080, + User2 = 0x00000100, + User3 = 0x00000200, + No = 0x00000080, + Yes = 0x00000100, + Details = 0x00000400, + Filler = 0x40000000, + Stretch = 0x80000000 + }; + + enum DialogType + { + TreeList, + Tabbed, + Plain, + Swallow, + IconList + }; + + KDialogBase(); + KDialogBase( QWidget *parent=0, const char *name=0, bool modal=true, + const QString &caption=QString::null, + int buttonMask=Ok|Apply|Cancel, ButtonCode defaultButton=Ok, + bool separator=false, + const QString &user1=QString::null, + const QString &user2=QString::null, + const QString &user3=QString::null); + KDialogBase( int dialogFace, const QString &caption, + int buttonMask, ButtonCode defaultButton, + QWidget *parent=0, const char *name=0, bool modal=true, + bool separator=false, + const QString &user1=QString::null, + const QString &user2=QString::null, + const QString &user3=QString::null); + virtual ~KDialogBase(); + + QFrame *addPage( const QString & ); + QFrame *addPage( const QString &, int, const QPixmap & ); + + void setMainWidget( QWidget *widget ); + + void enableButton( ButtonCode id, bool state ); + void enableButtonOK( bool state ); + void enableButtonApply( bool state ); + + int pageIndex( QWidget *widget ) const; + + bool showPage( int index ); + + QFrame *plainPage(); + + signals: + void user1Clicked(); + + protected slots: + virtual void slotOk(); + virtual void slotApply(); + virtual void slotCancel(); + virtual void slotClose(); + virtual void slotUser1(); + + private: + QTabWidget *tabWidget(); + void init( const QString &caption, int buttonMask, + const QString &user1=QString::null ); + void initLayout(); + + QWidget *mMainWidget; + QTabWidget *mTabWidget; + QFrame *mPlainPage; + QBoxLayout *mTopLayout; + + QPushButton *mUser1Button; + QPushButton *mCloseButton; + QPushButton *mOkButton; + QPushButton *mApplyButton; + QPushButton *mCancelButton; +}; + +#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 @@ +#include "kemailsettings.h" + +QString KEMailSettings::getSetting(KEMailSettings::Setting s) +{ + return QString::null; +} 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 @@ +#ifndef MINIKDE_KEMAILSETTINGS_H +#define MINIKDE_KEMAILSETTINGS_H + +#include + +class KEMailSettings +{ + public: + enum Setting { + ClientProgram, + ClientTerminal, + RealName, + EmailAddress, + ReplyToAddress, + Organization, + OutServer, + OutServerLogin, + OutServerPass, + OutServerType, + OutServerCommand, + OutServerTLS, + InServer, + InServerLogin, + InServerPass, + InServerType, + InServerMBXType, + InServerTLS + }; + QString getSetting(KEMailSettings::Setting s); +}; + +#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 @@ +#ifndef MICROKDE_KFILEDIALOG_H +#define MICROKDE_KFILEDIALOG_H + +class KFileDialog +{ + public: + + static QString getSaveFileName( const QString &, + const QString &, QWidget * ) + { + return QString::null; + } + + static QString getOpenFileName( const QString &, + const QString &, QWidget * ) + { + return QString::null; + } +}; + +#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 @@ +#include "kfontdialog.h" + +int KFontDialog::getFont( const QFont & ) +{ + return 0; +} 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 @@ +#ifndef MINIKDE_KFONTDIALOG_H +#define MINIKDE_KFONTDIALOG_H + +#include + +class KFontDialog +{ + public: + enum { Accepted }; + + static int getFont( const QFont & ); +}; + +#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 @@ +#include "kglobal.h" + +KLocale *KGlobal::mLocale = 0; +KConfig *KGlobal::mConfig = 0; +KIconLoader *KGlobal::mIconLoader = 0; +KStandardDirs *KGlobal::mDirs = 0; + +QString KGlobal::mAppName = "godot"; + +KLocale *KGlobal::locale() +{ + if ( !mLocale ) { + mLocale = new KLocale(); + } + + return mLocale; +} + +KConfig *KGlobal::config() +{ + if ( !mConfig ) { + mConfig = new KConfig( KStandardDirs::appDir() + mAppName + "rc" ); + } + + return mConfig; +} + +KIconLoader *KGlobal::iconLoader() +{ + if ( !mIconLoader ) { + mIconLoader = new KIconLoader(); + } + + return mIconLoader; +} + +KStandardDirs *KGlobal::dirs() +{ + if ( !mDirs ) { + mDirs = new KStandardDirs(); + } + + return mDirs; +} + +void KGlobal::setAppName( const QString &appName ) +{ + mAppName = appName; +} diff --git a/noncore/apps/tinykate/libkate/microkde/kglobal.h b/noncore/apps/tinykate/libkate/microkde/kglobal.h new file mode 100644 index 0000000..8985bd4 --- a/dev/null +++ b/noncore/apps/tinykate/libkate/microkde/kglobal.h @@ -0,0 +1,27 @@ +#ifndef MINIKDE_KGLOBAL_H +#define MINIKDE_KGLOBAL_H + +#include "klocale.h" +#include "kiconloader.h" +#include "kstandarddirs.h" +#include "kconfig.h" + +class KGlobal { + public: + static KLocale *locale(); + static KConfig *config(); + static KIconLoader *iconLoader(); + static KStandardDirs *dirs(); + + static void setAppName( const QString & ); + + private: + static KLocale *mLocale; + static KConfig *mConfig; + static KIconLoader *mIconLoader; + static KStandardDirs *mDirs; + + static QString mAppName; +}; + +#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 @@ +#include "kglobalsettings.h" + +QFont KGlobalSettings::generalFont() +{ + return QFont("fixed",12); +} + +QColor KGlobalSettings::baseColor() +{ + return Qt::white; +} + +QColor KGlobalSettings::highlightColor() +{ + return Qt::blue; +} + 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 @@ +#ifndef MICROKDE_KGLOBALSETTINGS_H +#define MICROKDE_KGLOBALSETTINGS_H + +#include +#include + +class KGlobalSettings +{ + public: + static QFont generalFont(); + static QColor baseColor(); + static QColor highlightColor(); +}; + +#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 @@ +#include + +#include "kiconloader.h" + +QPixmap KIconLoader::loadIcon( const QString &name, int ) +{ + return Resource::loadPixmap( "kate/" + name ); +} + +QString KIconLoader::iconPath( const QString &, int ) +{ + return QString::null; +} + +QPixmap BarIcon( const QString &name ) +{ + return Resource::loadPixmap( "kate/" + name ); +} + +QPixmap DesktopIcon( const QString &name, int ) +{ + return Resource::loadPixmap( "kate/" + name ); +} + +QPixmap SmallIcon( const QString &name ) +{ + return Resource::loadPixmap( "kate/" + name ); +} + +QPixmap SmallIconSet( const QString &name ) +{ + return Resource::loadPixmap( "kate/" + name ); +} 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 @@ +#ifndef MINIKDE_KICONLOADER_H +#define MINIKDE_KICONLOADER_H + +#include +#include + +class KIcon +{ + public: + enum Group { NoGroup=-1, Desktop=0, Toolbar, MainToolbar, Small, + Panel, LastGroup, User }; + enum StdSizes { SizeSmall=16, SizeMedium=32, SizeLarge=48 }; +}; + +class KIconLoader +{ + public: + QPixmap loadIcon( const QString &name, int ); + + QString iconPath( const QString &, int ); +}; + +QPixmap BarIcon(const QString& name); + +QPixmap DesktopIcon(const QString& name, int); + +QPixmap SmallIcon(const QString& name); + +QPixmap SmallIconSet( const QString &name ); + +#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 @@ +#ifndef MINIKDE_KLINEEDIT_H +#define MINIKDE_KLINEEDIT_H + +#include + +class KLineEdit : public QLineEdit +{ + public: + KLineEdit( QWidget *parent=0, const char *name=0 ) : + QLineEdit( parent, name ) {} +}; + +#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 @@ +#ifndef _mykdelineeditdlg_h_ +#define _mykdelineeditdlg_h_ + +#include + +#define KLineEditDlg QInputDialog + +#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 @@ +#ifndef MICROKDE_KLISTVIEW_H +#define MICROKDE_KLISTVIEW_H + +#include +#include +#include + +class KConfig; + +class KListView : public QListView +{ + Q_OBJECT + public: + KListView( QWidget *parent=0, const char *name=0 ) + : QListView( parent, name ) {} + + void saveLayout( KConfig *, const QString & ) {} + void restoreLayout( KConfig *, const QString & ) {} + + signals: + void doubleClicked( QListViewItem *, QPoint, int ); +}; + +#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 @@ +#include + +#include "kdebug.h" + +#include "klocale.h" + +QString i18n(const char *text) +{ + return QString( text ); +} + +QString i18n(const char *,const char *text) +{ + return QString( text ); +} + +inline void put_it_in( QChar *buffer, uint& index, const QString &s ) +{ + for ( uint l = 0; l < s.length(); l++ ) + buffer[index++] = s.at( l ); +} + +inline void put_it_in( QChar *buffer, uint& index, int number ) +{ + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; +} + +static int readInt(const QString &str, uint &pos) +{ + if (!str.at(pos).isDigit()) return -1; + int result = 0; + for (; str.length() > pos && str.at(pos).isDigit(); pos++) + { + result *= 10; + result += str.at(pos).digitValue(); + } + + return result; +} + +QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const +{ + const QString rst = timeFormat(); + + // only "pm/am" here can grow, the rest shrinks, but + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 30]; + + uint index = 0; + bool escape = false; + int number = 0; + + for ( uint format_index = 0; format_index < rst.length(); format_index++ ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'H': + put_it_in( buffer, index, pTime.hour() ); + break; + case 'I': + put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 ); + break; + case 'M': + put_it_in( buffer, index, pTime.minute() ); + break; + case 'S': + if (includeSecs) + put_it_in( buffer, index, pTime.second() ); + else + { + // we remove the seperator sign before the seconds and + // assume that works everywhere + --index; + break; + } + break; + case 'k': + number = pTime.hour(); + case 'l': + // to share the code + if ( rst.at( format_index ).unicode() == 'l' ) + number = (pTime.hour() + 11) % 12 + 1; + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'p': + { + QString s; + if ( pTime.hour() >= 12 ) + put_it_in( buffer, index, i18n("pm") ); + else + put_it_in( buffer, index, i18n("am") ); + break; + } + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const +{ + const QString rst = shortFormat?dateFormatShort():dateFormat(); + + // I'm rather safe than sorry + QChar *buffer = new QChar[rst.length() * 3 / 2 + 50]; + + unsigned int index = 0; + bool escape = false; + int number = 0; + + for ( uint format_index = 0; format_index < rst.length(); ++format_index ) + { + if ( !escape ) + { + if ( rst.at( format_index ).unicode() == '%' ) + escape = true; + else + buffer[index++] = rst.at( format_index ); + } + else + { + switch ( rst.at( format_index ).unicode() ) + { + case '%': + buffer[index++] = '%'; + break; + case 'Y': + put_it_in( buffer, index, pDate.year() / 100 ); + case 'y': + put_it_in( buffer, index, pDate.year() % 100 ); + break; + case 'n': + number = pDate.month(); + case 'e': + // to share the code + if ( rst.at( format_index ).unicode() == 'e' ) + number = pDate.day(); + if ( number / 10 ) + buffer[index++] = number / 10 + '0'; + buffer[index++] = number % 10 + '0'; + break; + case 'm': + put_it_in( buffer, index, pDate.month() ); + break; + case 'b': + put_it_in( buffer, index, monthName(pDate.month(), true) ); + break; + case 'B': + put_it_in( buffer, index, monthName(pDate.month(), false) ); + break; + case 'd': + put_it_in( buffer, index, pDate.day() ); + break; + case 'a': + put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), true) ); + break; + case 'A': + put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), false) ); + break; + default: + buffer[index++] = rst.at( format_index ); + break; + } + escape = false; + } + } + QString ret( buffer, index ); + delete [] buffer; + return ret; +} + +QString KLocale::formatDateTime(const QDateTime &pDateTime, + bool shortFormat, + bool includeSeconds) const +{ + return i18n("concatenation of dates and time", "%1 %2") + .arg( formatDate( pDateTime.date(), shortFormat ) ) + .arg( formatTime( pDateTime.time(), includeSeconds ) ); +} + +QString KLocale::formatDateTime(const QDateTime &pDateTime) const +{ + return formatDateTime(pDateTime, true); +} + +QDate KLocale::readDate(const QString &intstr, bool* ok) const +{ + QDate date; + date = readDate(intstr, true, ok); + if (date.isValid()) return date; + return readDate(intstr, false, ok); +} + +QDate KLocale::readDate(const QString &intstr, bool shortFormat, bool* ok) const +{ + QString fmt = (shortFormat ? dateFormatShort() : dateFormat()).simplifyWhiteSpace(); + return readDate( intstr, fmt, ok ); +} + +QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const +{ + //kdDebug(173) << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl; + QString str = intstr.simplifyWhiteSpace().lower(); + int day = -1, month = -1; + // allow the year to be omitted if not in the format + int year = QDate::currentDate().year(); + uint strpos = 0; + uint fmtpos = 0; + + while (fmt.length() > fmtpos || str.length() > strpos) + { + if ( !(fmt.length() > fmtpos && str.length() > strpos) ) + goto error; + + QChar c = fmt.at(fmtpos++); + + if (c != '%') { + if (c.isSpace()) + strpos++; + else if (c != str.at(strpos++)) + goto error; + continue; + } + + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = fmt.at(fmtpos++); + switch (c) + { + case 'a': + case 'A': + // this will just be ignored + { // Cristian Tache: porting to Win: Block added because of "j" redefinition + for (int j = 1; j < 8; j++) { + QString s = weekDayName(j, c == 'a').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + strpos += len; + } + break; + } + case 'b': + case 'B': + { // Cristian Tache: porting to Win: Block added because of "j" redefinition + for (int j = 1; j < 13; j++) { + QString s = monthName(j, c == 'b').lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) { + month = j; + strpos += len; + } + } + break; + } + case 'd': + case 'e': + day = readInt(str, strpos); + if (day < 1 || day > 31) + goto error; + + break; + + case 'n': + case 'm': + month = readInt(str, strpos); + if (month < 1 || month > 12) + goto error; + + break; + + case 'Y': + case 'y': + year = readInt(str, strpos); + if (year < 0) + goto error; + // Qt treats a year in the range 0-100 as 1900-1999. + // It is nicer for the user if we treat 0-68 as 2000-2068 + if (year < 69) + year += 2000; + else if (c == 'y') + year += 1900; + + break; + } + } + //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl; + if ( year != -1 && month != -1 && day != -1 ) + { + if (ok) *ok = true; + return QDate(year, month, day); + } + error: + if (ok) *ok = false; + return QDate(); // invalid date +} + +QTime KLocale::readTime(const QString &intstr, bool *ok) const +{ + QTime _time; + _time = readTime(intstr, true, ok); + if (_time.isValid()) return _time; + return readTime(intstr, false, ok); +} + +QTime KLocale::readTime(const QString &intstr, bool seconds, bool *ok) const +{ + QString str = intstr.simplifyWhiteSpace().lower(); + QString Format = timeFormat().simplifyWhiteSpace(); + if (!seconds) + Format.replace(QRegExp(QString::fromLatin1(".%S")), QString::null); + + int hour = -1, minute = -1, second = seconds ? -1 : 0; // don't require seconds + bool g_12h = false; + bool pm = false; + uint strpos = 0; + uint Formatpos = 0; + + while (Format.length() > Formatpos || str.length() > strpos) + { + if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error; + + QChar c = Format.at(Formatpos++); + + if (c != '%') + { + if (c.isSpace()) + strpos++; + else if (c != str.at(strpos++)) + goto error; + continue; + } + + // remove space at the begining + if (str.length() > strpos && str.at(strpos).isSpace()) + strpos++; + + c = Format.at(Formatpos++); + switch (c) + { + case 'p': + { + QString s; + s = i18n("pm").lower(); + int len = s.length(); + if (str.mid(strpos, len) == s) + { + pm = true; + strpos += len; + } + else + { + s = i18n("am").lower(); + len = s.length(); + if (str.mid(strpos, len) == s) { + pm = false; + strpos += len; + } + else + goto error; + } + } + break; + + case 'k': + case 'H': + g_12h = false; + hour = readInt(str, strpos); + if (hour < 0 || hour > 23) + goto error; + + break; + + case 'l': + case 'I': + g_12h = true; + hour = readInt(str, strpos); + if (hour < 1 || hour > 12) + goto error; + + break; + + case 'M': + minute = readInt(str, strpos); + if (minute < 0 || minute > 59) + goto error; + + break; + + case 'S': + second = readInt(str, strpos); + if (second < 0 || second > 59) + goto error; + + break; + } + } + if (g_12h) + { + hour %= 12; + if (pm) hour += 12; + } + + if (ok) *ok = true; + return QTime(hour, minute, second); + + error: + if (ok) *ok = false; + return QTime(-1, -1, -1); // return invalid date if it didn't work + // This will be removed in the near future, since it gives a warning on stderr. + // The presence of the bool* (since KDE-3.0) removes the need for an invalid QTime. +} + +bool KLocale::use12Clock() const +{ + return false; +} + +bool KLocale::weekStartsMonday() const +{ + return true; +} + +QString KLocale::weekDayName(int i,bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return i18n("Monday", "Mon"); + case 2: return i18n("Tuesday", "Tue"); + case 3: return i18n("Wednesday", "Wed"); + case 4: return i18n("Thursday", "Thu"); + case 5: return i18n("Friday", "Fri"); + case 6: return i18n("Saturday", "Sat"); + case 7: return i18n("Sunday", "Sun"); + } + else + switch ( i ) + { + case 1: return i18n("Monday"); + case 2: return i18n("Tuesday"); + case 3: return i18n("Wednesday"); + case 4: return i18n("Thursday"); + case 5: return i18n("Friday"); + case 6: return i18n("Saturday"); + case 7: return i18n("Sunday"); + } + + return QString::null; +} + +QString KLocale::monthName(int i,bool shortName) const +{ + if ( shortName ) + switch ( i ) + { + case 1: return i18n("January", "Jan"); + case 2: return i18n("February", "Feb"); + case 3: return i18n("March", "Mar"); + case 4: return i18n("April", "Apr"); + case 5: return i18n("May short", "May"); + case 6: return i18n("June", "Jun"); + case 7: return i18n("July", "Jul"); + case 8: return i18n("August", "Aug"); + case 9: return i18n("September", "Sep"); + case 10: return i18n("October", "Oct"); + case 11: return i18n("November", "Nov"); + case 12: return i18n("December", "Dec"); + } + else + switch (i) + { + case 1: return i18n("January"); + case 2: return i18n("February"); + case 3: return i18n("March"); + case 4: return i18n("April"); + case 5: return i18n("May long", "May"); + case 6: return i18n("June"); + case 7: return i18n("July"); + case 8: return i18n("August"); + case 9: return i18n("September"); + case 10: return i18n("October"); + case 11: return i18n("November"); + case 12: return i18n("December"); + } + + return QString::null; +} + +QString KLocale::country() const +{ + return QString::null; +} + +QString KLocale::dateFormat() const +{ + return "%A %d %B %Y"; +} + +QString KLocale::dateFormatShort() const +{ + return "%d.%m.%Y"; +} + +QString KLocale::timeFormat() const +{ + return "%H:%M:%S"; +} 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 @@ +#ifndef MINIKDE_KLOCALE_H +#define MINIKDE_KLOCALE_H + +#include +#include + + +#define I18N_NOOP(x) x + + +QString i18n(const char *text); +QString i18n(const char *hint, const char *text); + +// Qt3's uic generates i18n( "msg", "comment" ) calls which conflict +// with our i18n method. we use uic -tr tr2i18n to redirect +// to the right i18n() function +inline QString tr2i18n(const char* message, const char* =0) { + return i18n( message); +} + +class KLocale +{ + public: + + QString formatDate(const QDate &pDate, bool shortFormat = false) const; + QString formatTime(const QTime &pTime, bool includeSecs = false) const; + QString formatDateTime(const QDateTime &pDateTime) const; + QString formatDateTime(const QDateTime &pDateTime, + bool shortFormat, + bool includeSecs = false) const; + + QDate readDate(const QString &str, bool* ok = 0) const; + QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const; + QTime readTime(const QString &str, bool* ok = 0) const; + + bool use12Clock() const; + bool weekStartsMonday() const; + + QString weekDayName(int,bool=false) const; + QString monthName(int,bool=false) const; + + QString country() const; + + QString dateFormat() const; + QString dateFormatShort() const; + QString timeFormat() const; + + private: + QTime readTime(const QString &str, bool seconds, bool *ok) const; + QDate readDate(const QString &str, bool shortFormat, bool *ok) const; +}; + +#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 @@ +#include "kmessagebox.h" +#include "klocale.h" + +#include + +void KMessageBox::sorry( QWidget *parent, + const QString &text, + const QString &caption, bool ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Sorry"); + } + + QMessageBox::warning( parent, cap, text ); +} + +int KMessageBox::warningYesNoCancel(QWidget *parent, const QString &text) +{ + int result = QMessageBox::warning(parent,i18n("Warning"),text,QMessageBox::Yes, + QMessageBox::No, QMessageBox::Cancel); + switch (result) { + case QMessageBox::Yes: return Yes; + case QMessageBox::No: return No; + case QMessageBox::Cancel: return Cancel; + } +} + +int KMessageBox::questionYesNo(QWidget *parent, + const QString &text, + const QString &textYes, + const QString &textNo, + bool notify=true ) +{ + int result =QMessageBox::warning(parent,i18n("Question"),text,textYes,textNo); + if ( result == 0 ) return KMessageBox::Yes; + return KMessageBox::No; +} + + + + +int KMessageBox::warningContinueCancel( QWidget *parent, + const QString &text, + const QString &caption, + const QString &buttonContinue, + const QString &dontAskAgainName, + bool notify ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Warning"); + } + + int result = QMessageBox::warning( parent, cap, text, i18n("Ok"), + i18n("Cancel") ); + + if ( result == 0 ) return KMessageBox::Continue; + return KMessageBox::Cancel; +} + +void KMessageBox::error( QWidget *parent, + const QString &text, + const QString &caption, bool notify ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Error"); + } + + QMessageBox::critical( parent, cap, text ); +} + +void KMessageBox::information( QWidget *parent, + const QString &text, + const QString &caption, + const QString &, + bool ) +{ + QString cap = caption; + + if (cap.isEmpty()) { + cap = i18n("Information"); + } + + QMessageBox::information( parent, cap, text ); +} 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 @@ +#ifndef MINIKDE_KMESSAGEBOX_H +#define MINIKDE_KMESSAGEBOX_H + +#include + +class QWidget; + +class KMessageBox +{ + public: + enum { Ok = 1, Cancel = 2, Yes = 3, No = 4, Continue = 5 }; + + static void sorry(QWidget *parent, + const QString &text, + const QString &caption = QString::null, bool notify=true); + + static int warningContinueCancel(QWidget *parent, + const QString &text, + const QString &caption = QString::null, + const QString &buttonContinue = QString::null, + const QString &dontAskAgainName = QString::null, + bool notify=true ); + + + static int questionYesNo(QWidget *parent, + const QString &text, + const QString &textYes, + const QString &textNo, + bool notify=true ); + + static int warningYesNoCancel(QWidget *parent, const QString &text); + + + static void error(QWidget *parent, + const QString &text, + const QString &caption = QString::null, bool notify=true); + + static void information(QWidget *parent, + const QString &text, + const QString &caption = QString::null, + const QString &dontShowAgainName = QString::null, + bool notify=true); +}; + + +#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 @@ +#ifndef MINIKDE_KNOTIFYCLIENT_H +#define MINIKDE_KNOTIFYCLIENT_H + +#include + +class KNotifyClient +{ + public: + + static void beep() {} + static void beep( const QString & ) {} +}; + +#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 @@ +#include + +#include "knumvalidator.h" + +KIntValidator::KIntValidator( int a, int b, QLineEdit *c ) + : QIntValidator( a, b, c ) +{ +} 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 @@ +#ifndef MINIKDE_KNUMVALIDATOR_H +#define MINIKDE_KNUMVALIDATOR_H + +#include + +class QLineEdit; + +class KIntValidator : public QIntValidator +{ + public: + KIntValidator( int, int, QLineEdit * ); +}; + +#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 @@ +#ifndef _MYKPOPUPMENU_H_ +#define _MYKPOPUPMENU_H_ + +#include + +#define KPopupMenu QPopupMenu + +#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 @@ +#ifndef MINIKDE_KPRINTER_H +#define MINIKDE_KPRINTER_H + +#include + +#define KPrinter QPrinter + +#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 @@ +#include "kprocess.h" + +void KProcess::clearArguments() +{ +} + +KProcess & KProcess::operator<<( const QString & ) +{ + return *this; +} + +bool KProcess::start() +{ + return false; +} 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 @@ +#ifndef MINIKDE_KPROCESS_H +#define MINIKDE_KPROCESS_H + +#include + +class KProcess : public QObject +{ + public: + void clearArguments(); + + KProcess & operator<<( const QString & ); + + bool start(); +}; + +#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 @@ +#ifndef MINIKDE_KRESTRICTEDLINE_H +#define MINIKDE_KRESTRICTEDLINE_H + +#include "klineedit.h" + +class KRestrictedLine : public KLineEdit +{ + public: + KRestrictedLine( QWidget *parent, const char *, const QString & ) : + KLineEdit( parent ) {} +}; + +#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 @@ +#include "krun.h" + +bool KRun::runCommand(const QString &, const QString &, const QString &) +{ + return false; +} 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 @@ +#ifndef MINIKDE_KRUN_H +#define MINIKDE_KRUN_H + +#include + +class KRun +{ + public: + static bool runCommand(const QString &a, const QString &b=QString::null, + const QString &c=QString::null); +}; + +#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 @@ +#ifndef MINIKDE_KSEPARATOR_H +#define MINIKDE_KSEPARATOR_H + +class KSeparator +{ +}; + +#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 @@ +/* This file is part of the KDE libraries + Copyright (c) 1999 Waldo Bastian + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +#ifndef KSharedPTR_H +#define KSharedPTR_H + +/** + * Reference counting for shared objects. If you derive your object + * from this class, then you may use it in conjunction with + * @ref KSharedPtr to control the lifetime of your object. + * + * Specifically, all classes that derive from KShared have an internal + * counter keeping track of how many other objects have a reference to + * their object. If used with @ref KSharedPtr, then your object will + * not be deleted until all references to the object have been + * released. + * + * You should probably not ever use any of the methods in this class + * directly -- let the @ref KSharedPtr take care of that. Just derive + * your class from KShared and forget about it. + * + * @author Waldo Bastian + * @version $Id$ + */ +class KShared { +public: + /** + * Standard constructor. This will initialize the reference count + * on this object to 0 + */ + KShared() : count(0) { } + + /** + * Copy constructor. This will @em not actually copy the objects + * but it will initialize the reference count on this object to 0 + */ + KShared( const KShared & ) : count(0) { } + + /** + * Overloaded assignment operator + */ + KShared &operator=(const KShared & ) { return *this; } + + /** + * Increases the reference count by one + */ + void _KShared_ref() { count++; } + + /** + * Releases a reference (decreases the reference count by one). If + * the count goes to 0, this object will delete itself + */ + void _KShared_unref() { if (!--count) delete this; } + + /** + * Return the current number of references held + * + * @return Number of references + */ + int _KShared_count() { return count; } + +protected: + virtual ~KShared() { } + int count; // ### KDE 3.0: rename to something like _KShared_count + // or make private +}; + +/** + * Can be used to control the lifetime of an object that has derived + * @ref KShared. As long a someone holds a KSharedPtr on some KShared + * object it won't become deleted but is deleted once its reference + * count is 0. This struct emulates C++ pointers perfectly. So just + * use it like a simple C++ pointer. + * + * KShared and KSharedPtr are preferred over QShared / QSharedPtr + * since they are more safe. + * + * @author Waldo Bastian + * @version $Id$ + */ +template< class T > +struct KSharedPtr +{ +public: + KSharedPtr() + : ptr(0) { } + KSharedPtr( T* t ) + : ptr(t) { if ( ptr ) ptr->_KShared_ref(); } + KSharedPtr( const KSharedPtr& p ) + : ptr(p.ptr) { if ( ptr ) ptr->_KShared_ref(); } + + ~KSharedPtr() { if ( ptr ) ptr->_KShared_unref(); } + + KSharedPtr& operator= ( const KSharedPtr& p ) { + if ( ptr == p.ptr ) return *this; + if ( ptr ) ptr->_KShared_unref(); + ptr = p.ptr; + if ( ptr ) ptr->_KShared_ref(); + return *this; + } + KSharedPtr& operator= ( T* p ) { + if ( ptr == p ) return *this; + if ( ptr ) ptr->_KShared_unref(); + ptr = p; + if ( ptr ) ptr->_KShared_ref(); + return *this; + } + bool operator== ( const KSharedPtr& p ) const { return ( ptr == p.ptr ); } + bool operator!= ( const KSharedPtr& p ) const { return ( ptr != p.ptr ); } + bool operator== ( const T* p ) const { return ( ptr == p ); } + bool operator!= ( const T* p ) const { return ( ptr != p ); } + bool operator!() const { return ( ptr == 0 ); } + operator T*() const { return ptr; } + + T* data() { return ptr; } + const T* data() const { return ptr; } + + const T& operator*() const { return *ptr; } + T& operator*() { return *ptr; } + const T* operator->() const { return ptr; } + T* operator->() { return ptr; } + + int count() const { return ptr->_KShared_count(); } // for debugging purposes +private: + T* ptr; +}; + +#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 @@ +#ifndef MINIKDE_KSIMPLECONFIG_H +#define MINIKDE_KSIMPLECONFIG_H + +#include "kconfig.h" + +class KSimpleConfig : public KConfig +{ + public: + KSimpleConfig( const QString &file ) : KConfig( file ) {} +}; + +#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 @@ +#include "kdebug.h" + +#include "kstandarddirs.h" + +QString KStandardDirs::mAppDir = QString::null; + +QString locate( const char *type, const QString& filename ) +{ + QString path = KStandardDirs::appDir() + type + "_" + filename; + + kdDebug() << "locate: '" << path << "'" << endl; + + return path; +} + +QString locateLocal( const char *type, const QString& filename ) +{ + return locate( type, filename ); +} + +QStringList KStandardDirs::findAllResources( const QString &, const QString &, bool, bool) +{ + QStringList list; + list.append("/cpp.xml"); + return list; +// return QStringList(); +} + +QString KStandardDirs::findResourceDir( const QString &, const QString & ) +{ + return QString::null; +} + +void KStandardDirs::setAppDir( const QString &appDir ) +{ + mAppDir = appDir; + + if ( mAppDir.right( 1 ) != "/" ) mAppDir += "/"; +} 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 @@ +#ifndef MINIKDE_KSTANDARDDIRS_H +#define MINIKDE_KSTANDARDDIRS_H + +#include +#include + +QString locate( const char *type, const QString& filename ); +QString locateLocal( const char *type, const QString& filename ); + +class KStandardDirs +{ + public: + QStringList findAllResources( const QString &, const QString &, bool, bool); + QString findResourceDir( const QString &, const QString & ); + + static void setAppDir( const QString & ); + static QString appDir() { return mAppDir; } + + private: + static QString mAppDir; +}; + +#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 @@ +/* + * This file is part of the KDE Libraries + * Copyright (C) 2000 Stephan Kulow + * 2001 KDE Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _KSTATIC_DELETER_H_ +#define _KSTATIC_DELETER_H_ + +template +class KStaticDeleter +{ + public: + KStaticDeleter() {}; + type *setObject( type *obj, bool isArray = false) { return obj; } + virtual ~KStaticDeleter() {}; +}; + +#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 @@ +#ifndef MINIKDE_KSTANDARDDIRS_H +#define MINIKDE_KSTANDARDDIRS_H + +#include +#include + +QString locate( const char *type, const QString& filename ); +QString locateLocal( const char *type, const QString& filename ); + +class KStandardDirs +{ + public: + QStringList findAllResources( const QString &, const QString &, bool, bool); + QString findResourceDir( const QString &, const QString & ); + + static void setAppDir( const QString & ); + static QString appDir() { return mAppDir; } + + private: + static QString mAppDir; +}; + +#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 @@ +#include + +#include "ktempfile.h" + +KTempFile::KTempFile() +{ +} + +KTempFile::KTempFile( const QString &filename, const QString &extension ) +{ +} + +void KTempFile::setAutoDelete( bool ) +{ +} + +QString KTempFile::name() +{ + return QString::null; +} + +QTextStream *KTempFile::textStream() +{ + return 0; +} 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 @@ +#ifndef MINIKDE_KTEMPFILE_H +#define MINIKDE_KTEMPFILE_H + +#include + +class QTextStream; + +class KTempFile +{ + public: + KTempFile(); + KTempFile( const QString &filename, const QString &extension ); + + void setAutoDelete( bool ); + QString name(); + + QTextStream *textStream(); +}; + +#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 @@ +#ifndef MINIKDE_KUNLOAD_H +#define MINIKDE_KUNLOAD_H + +#define _UNLOAD(p) + +#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 @@ +#include "klineedit.h" + +#include "kurlrequester.h" + +KURLRequester::KURLRequester( QWidget *parent ) : + QWidget( parent ) +{ + mLineEdit = new KLineEdit( parent ); +} + +KLineEdit *KURLRequester::lineEdit() +{ + return mLineEdit; +} 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 @@ +#ifndef MINIKDE_KURLREQUESTER_H +#define MINIKDE_KURLREQUESTER_H + +class KLineEdit; + +class KURLRequester : public QWidget +{ + public: + KURLRequester( QWidget *parent ); + + KLineEdit *lineEdit(); + + private: + KLineEdit *mLineEdit; +}; + +#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 @@ +This is a backport I got from Scott Manson, I just added an additional #ifndef QT_NO_COMPAT in the .cpp file around a match +function + +************************* + This is ___NOT___ the original version from Trolltech, so don't blame them if something is wrong. +************************* + +Use it at your own risk, neither Trolltech, Scott Manson nor I take any responsibility, if it damages your system or causes +unexpected behaviour or causes loss of data + +Joseph Wenninger + 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 @@ +/**************************************************************************** +** $Id$ +** +** Implementation of QRegExp class +** +** Created : 950126 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#if QT_VERSION >=300 +#error QRegExp3 is now in QT 3 use QRegExp instead +#endif + +#include "qarray.h" +#include "qbitarray.h" +#include "qcache.h" +#include "qintdict.h" +#include "qmap.h" +#if QT_VERSION < 300 +#include "./qregexp3.h" +#else +#include "qregexp.h" +#endif +#include "qstring.h" +#include "qtl.h" +#include "qvector.h" + +#include + +/* + WARNING! Be sure to read qregexp.tex before modifying this file. +*/ + +/*! + \class QRegExp3 qregexp.h + + \brief The QRegExp class provides pattern matching using regular expressions. + + \ingroup tools + \ingroup misc + \ingroup shared + + + Regular expressions, "regexps", provide a way to find patterns + within text. This is useful in many contexts, for example: + +
    +
  1. \e Validation. A regexp can be used to check whether a piece of + text meets some criteria, e.g. is an integer or contains no + whitespace. +
  2. \e Searching. Regexps provide a much more powerful means of + searching text than simple string matching does. For example we can + create a regexp which says "find one of the words 'mail', 'letter' + or 'correspondence' but not any of the words 'email', 'mailman' + 'mailer', 'letterbox' etc." +
  3. Search and Replace. A regexp can be used to replace a + pattern with a piece of text, for example replace all occurrences of + '&' with '\&' except where the '&' is already followed by + 'amp;'. +
  4. String Splitting. A regexp can be used to identify + where a string should be split into its component fields, e.g. + splitting tab delimited strings. +
+ + We present a very brief introduction to regexps, a description of + Qt's regexp language, some code examples, and finally the function + documentation. QRegExp is modelled on Perl's regexp engine and fully + supports Unicode. QRegExp may also be used in the weaker 'wildcard' + (globbing) mode which works in a similar way to command shells. A + good text on regexps is Mastering Regular Expressions: Powerful + Techniques for Perl and Other Tools by Jeffrey E. Friedl, ISBN + 1565922573. + + Experienced regexp users may prefer to skip the introduction and + go directly to the relevant information: + + + + Introduction + + Regexps are built up from expressions, quantifiers and assertions. + The simplest form of expression is simply a character, e.g. x + or 5. An expression can also be a set of characters. For + example, [ABCD], will match an A or a B or a + C or a D. As a shorthand we could write this as + [A-D]. If we want to match any of the captital letters in the + English alphabet we can write [A-Z]. A quantifier tells the + regexp engine how many occurrences of the expression we want, e.g. + x{1,1} means match an x which occurs at least once and + at most once. We'll look at assertions and more complex expressions + later. Note that regexps cannot be used to check for balanced + brackets or tags (unless you know the maximum level of nesting). + + + We'll start by writing a regexp to match integers in the range 0 to + 99. We will require at least one digit so we will start with + [0-9]{1,1} which means match a digit exactly once. This + regexp alone will match integers in the range 0 to 9. To match one + or two digits we can increase the maximum number of occurrences so + the regexp becomes [0-9]{1,2} meaning match a digit at least + once and at most twice. However, this regexp as it stands will not + match correctly. This regexp will match one or two digits \e within + a string. To ensure that we match against the whole string we must + use the anchor assertions. We need ^ (caret) which when it is + the first character in the regexp means that the regexp must match + from the beginning of the string. And we also need $ (dollar) + which when it is the last character in the regexp means that the + regexp must match until the end of the string. So now our regexp is + ^[0-9]{1,2}$. Note that assertions do not match any + characters. + + If you've seen regexps elsewhere they may have looked different from + the one above. This is because some sets of characters and some + quantifiers are so common that they have special symbols to + represent them. [0-9] can be replaced with the symbol + \d. The quantifier to match exactly one occurrence, + {1,1}, can be replaced with the expression itself. This means + that x{1,1} is exactly the same as x alone. So our 0 + to 99 matcher could be written: ^\d{1,2}$, although most + people would write it ^\d\d?$. The ? is the same as + the quantifier {0,1}, i.e. a minimum of no occurrences a + maximum of one occurrence. This is used to make an expression + optional. The regexp ^\d\d?$ means "from the beginning of the + string match one digit followed by zero or one digits and then the + end of the string". + + Our second example is matching the words 'mail', 'letter' or + 'correspondence' but without matching 'email', 'mailman', 'mailer', + 'letterbox' etc. We'll start by just matching 'mail'. In full the + regexp is, m{1,1}a{1,1}i{1,1}l{1,1}, but since an expression + itself is automatically quantified by {1,1} we can simply + write this as mail; an 'm' followed by an 'a' followed by an + 'i' followed by an 'l'. The symbol '|' (bar) is used for \e + alternation, so our regexp now becomes + mail|letter|correspondence which means match 'mail' \e or + 'letter' \e or 'correspondence'. Whilst this regexp will find the + words we want it will also find words we don't want such as 'email'. + We will start by putting our regexp in parenthesis + (mail|letter|correspondence). Parenthesis have two effects, + firstly they group expressions together and secondly they identify + parts of the regexp that we wish to capture. + Our regexp still matches any of the three words but now they are + grouped together as a unit. This is useful for building up more + complex regexps. It is also useful because it allows us to examine + which of the words actually matched. We need to use another + assertion, this time \b "word boundary": + \b(mail|letter|correspondence)\b. This regexp means "match a + word boundary followed by the expression in parenthesis followed by + another word boundary". The \b assertion matches at a \e + position in the regexp not a \e character in the regexp. A word + boundary is any non-word character such as a space a newline or the + beginning or end of the string. + + For our third example we want to replace ampersands with the HTML + entity '\&'. The regexp to match is simple: \&, i.e. + match one ampersand. Unfortunately this will mess up our text if + some of the ampersands have already been turned into HTML entities. + So what we really want to say is replace an ampersand providing it + is not followed by 'amp;'. For this we need the negative lookahead + assertion and our regexp becomes: \&(?!amp;). The negative + lookahead assertion is introduced with '(?!' and finishes at the + ')'. It means that the text it contains, 'amp;' in our example, must + \e not follow the expression that preceeds it. + + Regexps provide a rich language that can be used in a variety of + ways. For example suppose we want to count all the occurrences of + 'Eric' and 'Eirik' in a string. Two valid regexps to match these are + \\b(Eric|Eirik)\\b and + \\bEi?ri[ck]\\b. We need the word boundary + '\b' so we don't get 'Ericsson' etc. The second regexp actually + matches more than we want, 'Eric', 'Erik', 'Eiric' and 'Eirik'. + + We will implement some the examples above in the + code examples section. + + + Characters and Abbreviations for Sets of Characters + +
    + +
  • c Any character represents itself unless it has a special regexp + meaning. Thus c matches the character \e c. + +
  • \\c A character that follows a backslash matches the + character itself except where mentioned below. For example if you + wished to match a literal caret at the beginning of a string you + would write \^. + +
  • \\a This matches the ASCII bell character (BEL, 0x07). +
  • \\f This matches the ASCII form feed character (FF, 0x0C). +
  • \\n This matches the ASCII line feed character (LF, 0x0A), (Unix newline). +
  • \\r This matches the ASCII carriage return character (CR, 0x0D). +
  • \\t This matches the ASCII horizontal tab character (HT, 0x09). +
  • \\v This matches the ASCII vertical tab character (VT, 0x0B). +
  • \\xhhhh This matches the Unicode character corresponding + to the hexadecimal number hhhh (between 0x0000 and 0xFFFF). \0ooo + (i.e., \zero ooo) matches the ASCII/Latin-1 character corresponding + to the octal number ooo (between 0 and 0377). +
  • . (dot) This matches any character (including newline). +
  • \\d This matches a digit (see QChar::isDigit()). +
  • \\D This matches a non-digit. +
  • \\s This matches a whitespace (see QChar::isSpace()). +
  • \\S This matches a non-whitespace. +
  • \\w This matches a word character (see QChar::isLetterOrNumber()). +
  • \\W This matches a non-word character. +
  • \\n The nth + backreference, e.g. \1, \2, etc. +
+ + Note that the C++ compiler transforms backslashes in strings so + to include a \\ in a regexp you will need to enter it twice, + i.e. \\\\. + + Sets of Characters + + Square brackets are used to match any character in the set of + characters contained within the square brackets. All the character + set abbreviations described above can be used within square + brackets. Apart from the character set abbreviations and the + following two exceptions no characters have special meanings in + square brackets. + +
    + +
  • ^ The caret negates the character set if it occurs as the + first character, i.e. immediately after the opening square bracket. + For example, [abc] matches 'a' or 'b' or 'c', but + [^abc] matches anything \e except 'a' or 'b' or 'c'. + +
  • - The dash is used to indicate a range of characters, for + example [W-Z] matches 'W' or 'X' or 'Y' or 'Z'. + +
+ + Using the predefined character set abbreviations is more portable + than using character ranges across platforms and languages. For + example, [0-9] matches a digit in Western alphabets but + \d matches a digit in \e any alphabet. + + Note that in most regexp literature sets of characters are called + "character classes". + + Quantifiers + + By default an expression is automatically quantified by + {1,1}, i.e. it should occur exactly once. In the following + list E stands for any expression. An expression is a + character or an abbreviation for a set of characters or a set of + characters in square brackets or any parenthesised expression. + +
    + +
  • E? Matches zero or one occurrence of E. + This quantifier means "the previous expression is optional" since it + will match whether or not the expression occurs in the string. + It is the same as E{0,1}. For example dents? + will match 'dent' and 'dents'. + +
  • E+ Matches one or more occurrences of E. + This is the same as E{1,MAXINT}. For example, + 0+ will match '0', '00', '000', etc. + +
  • E* Matches zero or more occurrences of E. + This is the same as E{0,MAXINT}. The * + quantifier is often used by a mistake. Since it matches \e zero or + more occurrences it will match no occurrences at all. For example if + we want to match strings that end in whitespace and use the regexp + \s*$ we would get a match on every string. This is because we + have said find zero or more whitespace followed by the end of string, + so even strings that don't end in whitespace will match. The regexp + we want in this case is \s+$ to match strings that have at + least one whitespace at the end. + +
  • E{n} Matches exactly \e n occurrences of the + expression. This is the same as repeating the expression \e n times. + For example, x{5} is the same as xxxxx. It is also the + same as E{n,n}, e.g. x{5,5}. + +
  • E{n,} Matches at least \e n occurrences of the + expression. This is the same as E{n,MAXINT}. + +
  • E{,m} Matches at most \e m occurrences of the + expression. This is the same as E{0,m}. + +
  • E{n,m} Matches at least \e n occurrences of the + expression and at most \e m occurrences of the expression. + +
+ + (MAXINT is implementation dependent but will not be smaller than + 16384.) + + If we wish to apply a quantifier to more than just the preceeding + character we can use parenthesis to group characters together in an + expression. For example, tag+ matches a 't' followed by an + 'a' followed by at least one 'g', whereas (tag)+ matches at + least one occurrence of 'tag'. + + Note that quantifiers are "greedy", they will match as much text as + they can. For example, 0+ will match as many zeros as it can + from the first zero it finds, e.g. '2.0005'. Quantifiers can + be made non-greedy, see setMinimal(). + + Capturing Text + + Parenthesis allow us to group elements together so that we can + quantify and capture them. For example if we have the expression + mail|letter|correspondence that matches a string we know that + \e one of the words matched but not which one. Using parenthesis + allows us to "capture" whatever is matched within their bounds, so + if we used (mail|letter|correspondence) and matched this + regexp against the string "I sent you some email" we can use the + cap() or capturedTexts() functions to extract the matched + characters, in this case 'mail'. + + We can use captured text within the regexp itself. To refer to the + captured text we use \e backreferences which are indexed from 1 the + same as for cap(). For example we could search for duplicate words + in a string using \b(\w+)\W+\1\b which means match a word + boundary followed by one or more word characters followed by one or + more non-word characters followed by the same text as the first + parenthesised expression followed by a word boundary. + + If we want to use parenthesis purely for grouping and not for + capturing we use the non-capturing syntax, e.g. + (?:green|blue). Non-capturing parenthesis begin '(?:' and end + ')'. In this example we match either 'green' or 'blue' but we do not + capture the match so we can only know whether or not we matched but + not which color we actually found. Using non-capturing parenthesis + is more efficient than using capturing parenthesis since the regexp + engine has to do less book-keeping. + + Both capturing and non-capturing parenthesis may be nested. + + Assertions + + Assertions make some statement about the text at the point where + they occur in the regexp but they do not match any characters. + In the following list E stands for any expression. + +
    +
  • ^ If the caret is the first character in the regexp + (apart from opening parenthesis) it signifies the beginning of the + string. It has no special meaning elsewhere (except as the first + character of a set of characters in square brackets). For example, + ^#include will only match strings which \e begin with the + characters '#include'. + +
  • $ If the dollar is the last character in the regexp + (apart from closing parenthesis) it signifies the end of the string. + It has no special meaning elsewhere. For example, \d\s*$ + will match strings which end with a digit optionally followed by + whitespace. + +
  • \\b A word boundary. For example the regexp + \\bOK\\b means match immediately after a + word boundary (e.g. start of string or whitespace) the letter 'O' + then the letter 'K' immediately before another word boundary (e.g. + end of string or whitespace). But note that the assertion does not + actually match any whitespace so if we write + (\\bOK\\b) and we have a match it + will only contain 'OK' even if the string is "Its OK now". + +
  • \\B A non-word boundary. This assertion is true + wherever \\b is false. For example if we searched for + \\Bon\\B in "Left on" the match would fail + (space and end of string aren't non-word boundaries), but it would + match in "tonne". + +
  • (?=E) Positive lookahead. This assertion is true + if the expression matches at this point in the regex. This assertion + does not match any characters. For example, + ^#define\s+(\w+)(?=MAX) will match strings which begin with + '#define' followed by at least one whitespace followed by at least + one word character followed by 'MAX'. The first set of parenthesis + will capture the word character(s) matched. This regexp will not + match '#define DEBUG' but will match '#define INTMAX + 32767'. + +
  • (?!E) Negative lookahead. This assertion is true + if the expression does not match at this point in the regex. This + assertion does not match any characters. For example, + ^#define\s+(\w+)\s*$ will match strings which begin with + '#define' followed by at least one whitespace followed by at least + one word character optionally followed by whitespace. This regexp + will match define's that exist but have no value, i.e. it will not + match '#define INTMAX 32767' but it will match '#define DEBUG'. + +
+ + Wildcard Matching (globbing) + + Most command shells such as \e bash or \e cmd support "file + globbing", the ability to identify a group of files by using + wildcards. Wildcard matching is much simpler than full regexps and + has only four features: + +
    + +
  • c Any character represents itself apart from those + mentioned below. Thus c matches the character \e c. + +
  • ? This matches any single character. It is the same as + . in full regexps. + +
  • * This matches zero or more of any characters. It is the + same as .* in full regexps. + +
  • [...] Sets of characters can be represented in square + brackets the same as for full regexps. + + + +
+ + For example if we are in wildcard mode and have strings which + contain filenames we could identify HTML files with *.html. + This will match zero or more characters followed by a dot followed + by 'h', 't', 'm' and 'l'. + + Notes for Perl Users + + Most of the character class abbreviations supported by Perl are + supported by QRegExp, see + + characters and abbreviations for sets of characters. + + QRegExp's quantifiers are the same as Perl's greedy quantifiers. + Non-greedy matching cannot be applied to individual quantifiers, but + can be applied to all the quantifiers in the pattern. For example, + to match the Perl regex ro+?m requires: + \code + QRegExp rx( "ro+m" ); + rx.setMinimal( TRUE ); + \endcode + + The equivalent of Perl's /i option is + setCaseSensitive(FALSE). + + Perl's /g option can be emulated using a + loop. + + In QRegExp . matches any character, therefore all QRegExp + regexps have the equivalent of Perl's /s option. QRegExp + does not have an equivalent to Perl's /m option, but this + can be emulated in various ways for example by splitting the input + into lines or by looping with a regexp that searches for newlines. + + Because QRegExp is string oriented there are no \A, \Z or \z + assertions. The \G assertion is not supported but can be emulated in + a loop. + + Perl's $& is cap(0) or capturedTexts()[0]. There are no QRegExp + equivalents for $`, $' or $+. $1, $2 etc correspond to + cap(1) or capturedTexts()[1], cap(2) or capturedTexts()[2], etc. + + To substitute a pattern use QString::replace(). + + Perl's extended /x syntax is not supported, nor are regexp + comments (?#comment) or directives, e.g. (?i). + + Both zero-width positive and zero-width negative lookahead + assertions (?=pattern) and (?!pattern) are supported with the same + syntax as Perl. Perl's lookbehind assertions, "independent" + subexpressions and conditional expressions are not supported. + + Non-capturing parenthesis are also supported, with the same + (?:pattern) syntax. + + See QStringList::split() and QStringList::join() for equivalents to + Perl's split and join functions. + + Note: because C++ transforms \\'s they must be written \e twice in + code, e.g. \\b must be written \\\\b. + + Code Examples + + \code + QRegExp rx( "^\\d\\d?$" ); // Match integers 0 to 99 + rx.search( "123" ); // Returns -1 (no match) + rx.search( "-6" ); // Returns -1 (no match) + rx.search( "6" ); // Returns 0 (matched as position 0) + \endcode + + The third string matches '6'. This is a simple validation + regexp for integers in the range 0 to 99. + + \code + QRegExp rx( "^\\S+$" ); // Match strings which have no whitespace + rx.search( "Hello world" ); // Returns -1 (no match) + rx.search( "This_is-OK" ); // Returns 0 (matched at position 0) + \endcode + + The second string matches 'This_is-OK'. We've used the + character set abbreviation '\S' (non-whitespace) and the anchors to + match strings which contain no whitespace. + + In the following example we match strings containing 'mail' or + 'letter' or 'correspondence' but only match whole words i.e. not + 'email' + + \code + QRegExp rx( "\\b(mail|letter|correspondence)\\b" ); + rx.search( "I sent you an email" ); // Returns -1 (no match) + rx.search( "Please write the letter" ); // Returns 17 (matched at position 17) + \endcode + + The second string matches "Please write the letter". The word + 'letter' is also captured (because of the parenthesis). We can see + what text we've captured like this: + + \code + QString captured = rx.cap( 1 ); // captured contains "letter" + \endcode + + This will capture the text from the first set of capturing + parenthesis (counting capturing left parenthesis from left to + right). The parenthesis are counted from 1 since cap( 0 ) is the + whole matched regexp (equivalent to '&' in most regexp engines). + + \code + QRegExp rx( "&(?!amp;)" ); // Match ampersands but not & + QString line1 = "This & that"; + line1.replace( rx, "&" ); + // line1 == "This & that" + QString line2 = "His & hers & theirs"; + line2.replace( rx, "&" ); + // line2 == "His & hers & theirs" + \endcode + + Here we've passed the QRegExp to QString's replace() function to + replace the matched text with new text. + + \code + QString str = "One Eric another Eirik, and an Ericsson. How many Eiriks, Eric?"; + QRegExp rx( "\\b(Eric|Eirik)\\b" ); // Match Eric or Eirik + int pos = 0; // Where we are in the string + int count = 0; // How many Eric and Eirik's we've counted + while ( pos >= 0 ) { + pos = rx.search( str, pos ); + if ( pos >= 0 ) { + pos++; // Move along in str + count++; // Count our Eric or Eirik + } + } + \endcode + + We've used the search() function to repeatedly match the regexp in + the string. Note that instead of moving forward by one character at + a time pos++ we could have written pos += + rx.matchedLength() to skip over the already matched string. The + count will equal 3, matching 'One Eric another Eirik, + and an Ericsson. How many Eiriks, Eric?'; it doesn't match + 'Ericsson' or 'Eiriks' because they are not bounded by non-word + boundaries. + + One common use of regexps is to split lines of delimited data into + their component fields. + + \code + str = "Trolltech AS\twww.trolltech.com\tNorway"; + QString company, web, country; + rx.setPattern( "^([^\t]+)\t([^\t]+)\t([^\t]+)$" ); + if ( rx.search( str ) != -1 ) { + company = rx.cap( 1 ); + web = rx.cap( 2 ); + country = rx.cap( 3 ); + } + \endcode + + In this example our input lines have the format company name, web + address and country. Unfortunately the regexp is rather long and not + very versatile -- the code will break if we add any more fields. A + simpler and better solution is to look for the separator, '\t' in + this case, and take the surrounding text. The QStringList split() + function can take a separator string or regexp as an argument and + split a string accordingly. + + \code + QStringList field = QStringList::split( "\t", str ); + \endcode + + Here field[0] is the company, field[1] the web address and so on. + + To immitate the matching of a shell we can use wildcard mode. + + \code + QRegExp rx( "*.html" ); // Invalid regexp: * doesn't quantify anything + rx.setWildcard( TRUE ); // Now its a valid wildcard regexp + rx.search( "index.html" ); // Returns 0 (matched at position 0) + rx.search( "default.htm" ); // Returns -1 (no match) + rx.search( "readme.txt" ); // Returns -1 (no match) + \endcode + + Wildcard matching can be convenient because of its simplicity, but + any wildcard regex can be defined using full regexps, e.g. + .*\.html$. Notice that we can't match both \c .html and \c + .htm files with a wildcard unless we use *.htm* which will + also match 'test.html.bak'. A full regexp gives us the precision we + need, .*\.html?$. + + QRegExp can match case insensitively using setCaseSensitive(), and + can use non-greedy matching, see setMinimal(). By default QRegExp + uses full regexps but this can be changed with setWildcard(). + Searching can be forward with search() or backward with searchRev(). + Captured text can be accessed using capturedTexts() which returns a + string list of all captured strings, or using cap() which returns + the captured string for the given index. The pos() function takes a + match index and returns the position in the string where the match + was made (or -1 if there was no match). + + \sa QRegExpValidator QString QStringList + + +*/ + +static const int NumBadChars = 128; +#define BadChar( ch ) ( (ch).cell() % NumBadChars ) + +static const int NoOccurrence = INT_MAX; +static const int EmptyCapture = INT_MAX; +static const int InftyLen = INT_MAX; +static const int InftyRep = 1000; +static const int EOS = -1; + +#ifndef QT_NO_REGEXP_OPTIM +static int engCount = 0; +static QArray *noOccurrences = 0; +static QArray *firstOccurrenceAtZero = 0; +#endif + +/* + Merges two QArrays of ints and puts the result into the first one. +*/ +static void mergeInto( QArray *a, const QArray& b ) +{ + int asize = a->size(); + int bsize = b.size(); + if ( asize == 0 ) { + *a = b.copy(); +#ifndef QT_NO_REGEXP_OPTIM + } else if ( bsize == 1 && (*a)[asize - 1] < b[0] ) { + a->resize( asize + 1 ); + (*a)[asize] = b[0]; +#endif + } else if ( bsize >= 1 ) { + int csize = asize + bsize; + QArray c( csize ); + int i = 0, j = 0, k = 0; + while ( i < asize ) { + if ( j < bsize ) { + if ( (*a)[i] == b[j] ) { + i++; + csize--; + } else if ( (*a)[i] < b[j] ) { + c[k++] = (*a)[i++]; + } else { + c[k++] = b[j++]; + } + } else { + memcpy( c.data() + k, (*a).data() + i, + (asize - i) * sizeof(int) ); + break; + } + } + c.resize( csize ); + if ( j < bsize ) + memcpy( c.data() + k, b.data() + j, (bsize - j) * sizeof(int) ); + *a = c; + } +} + +/* + Merges two disjoint QMaps of (int, int) pairs and puts the result into the + first one. +*/ +static void mergeInto( QMap *a, const QMap& b ) +{ + QMap::ConstIterator it; + for ( it = b.begin(); it != b.end(); ++it ) + a->insert( it.key(), *it ); +} + +/* + Returns the value associated to key k in QMap m of (int, int) pairs, or 0 if + no such value is explicitly present. +*/ +static int at( const QMap& m, int k ) +{ + QMap::ConstIterator it = m.find( k ); + if ( it == m.end() ) + return 0; + else + return *it; +} + +#ifndef QT_NO_REGEXP_WILDCARD +/* + Translates a wildcard pattern to an equivalent regular expression pattern + (e.g., *.cpp to .*\.cpp). +*/ +static QString wc2rx( const QString& wc ) +{ + int wclen = wc.length(); + QString rx = QString::fromLatin1( "" ); + int i = 0; + while ( i < wclen ) { + QChar c = wc[i++]; + switch ( c.unicode() ) { + case '*': + rx += QString::fromLatin1( ".*" ); + break; + case '?': + rx += QChar( '.' ); + break; + case '$': + case '(': + case ')': + case '+': + case '.': + case '\\': + case '^': + case '{': + case '|': + case '}': + rx += QChar( '\\' ); + rx += c; + break; + case '[': + rx += c; + if ( wc[i] == QChar('^') ) + rx += wc[i++]; + if ( i < wclen ) { + if ( rx[i] == ']' ) + rx += wc[i++]; + while ( i < wclen && wc[i] != QChar(']') ) { + if ( wc[i] == '\\' ) + rx += QChar( '\\' ); + rx += wc[i++]; + } + } + break; + default: + rx += c; + } + } + return rx; +} +#endif + +/* + The class QRegExpEngine encapsulates a modified nondeterministic finite + automaton (NFA). +*/ +class QRegExpEngine : public QShared +{ +public: +#ifndef QT_NO_REGEXP_CCLASS + /* + The class CharClass represents a set of characters, such as can be found + in regular expressions (e.g., [a-z] denotes the set {a, b, ..., z}). + */ + class CharClass + { + public: + CharClass(); + CharClass( const CharClass& cc ) { operator=( cc ); } + + CharClass& operator=( const CharClass& cc ); + + void clear(); + bool negative() const { return n; } + void setNegative( bool negative ); + void addCategories( int cats ); + void addRange( ushort from, ushort to ); + void addSingleton( ushort ch ) { addRange( ch, ch ); } + + bool in( QChar ch ) const; +#ifndef QT_NO_REGEXP_OPTIM + const QArray& firstOccurrence() const { return occ1; } +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + + private: + /* + The struct Range represents a range of characters (e.g., [0-9] denotes + range 48 to 57). + */ + struct Range + { + ushort from; // 48 + ushort to; // 57 + }; + + int c; // character classes + QArray r; // character ranges + bool n; // negative? +#ifndef QT_NO_REGEXP_OPTIM + QArray occ1; // first-occurrence array +#endif + }; +#else + struct CharClass + { + int x; // dummy + +#ifndef QT_NO_REGEXP_OPTIM + const QArray& firstOccurrence() const { + return *firstOccurrenceAtZero; + } +#endif + }; +#endif + + QRegExpEngine( bool caseSensitive ) { setup( caseSensitive ); } + QRegExpEngine( const QString& rx, bool caseSensitive ); +#ifndef QT_NO_REGEXP_OPTIM + ~QRegExpEngine(); +#endif + + bool isValid() const { return valid; } + bool caseSensitive() const { return cs; } + int numCaptures() const { return realncap; } + QArray match( const QString& str, int pos, bool minimal, + bool oneTest ); + int matchedLength() const { return mmMatchedLen; } + + int createState( QChar ch ); + int createState( const CharClass& cc ); +#ifndef QT_NO_REGEXP_BACKREF + int createState( int bref ); +#endif + + void addCatTransitions( const QArray& from, const QArray& to ); +#ifndef QT_NO_REGEXP_CAPTURE + void addPlusTransitions( const QArray& from, const QArray& to, + int atom ); +#endif + +#ifndef QT_NO_REGEXP_ANCHOR_ALT + int anchorAlternation( int a, int b ); + int anchorConcatenation( int a, int b ); +#else + int anchorAlternation( int a, int b ) { return a & b; } + int anchorConcatenation( int a, int b ) { return a | b; } +#endif + void addAnchors( int from, int to, int a ); + +#ifndef QT_NO_REGEXP_OPTIM + void setupGoodStringHeuristic( int earlyStart, int lateStart, + const QString& str ); + void setupBadCharHeuristic( int minLen, const QArray& firstOcc ); + void heuristicallyChooseHeuristic(); +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + +private: + enum { CharClassBit = 0x10000, BackRefBit = 0x20000 }; + + /* + The struct State represents one state in a modified NFA. The input + characters matched are stored in the state instead of on the transitions, + something possible for an automaton constructed from a regular expression. + */ + struct State + { +#ifndef QT_NO_REGEXP_CAPTURE + int atom; // which atom does this state belong to? +#endif + int match; // what does it match? (see CharClassBit and BackRefBit) + QArray outs; // out-transitions + QMap *reenter; // atoms reentered when transiting out + QMap *anchors; // anchors met when transiting out + +#ifndef QT_NO_REGEXP_CAPTURE + State( int a, int m ) + : atom( a ), match( m ), reenter( 0 ), anchors( 0 ) { } +#else + State( int m ) + : match( m ), reenter( 0 ), anchors( 0 ) { } +#endif + ~State() { delete reenter; delete anchors; } + }; + +#ifndef QT_NO_REGEXP_LOOKAHEAD + /* + The struct Lookahead represents a lookahead a la Perl (e.g., (?=foo) and + (?!bar)). + */ + struct Lookahead + { + QRegExpEngine *eng; // NFA representing the embedded regular expression + bool neg; // negative lookahead? + + Lookahead( QRegExpEngine *eng0, bool neg0 ) + : eng( eng0 ), neg( neg0 ) { } + ~Lookahead() { delete eng; } + }; +#endif + +#ifndef QT_NO_REGEXP_CAPTURE + /* + The struct Atom represents one node in the hierarchy of regular expression + atoms. + */ + struct Atom + { + int parent; // index of parent in array of atoms + int capture; // index of capture, from 1 to ncap + }; +#endif + +#ifndef QT_NO_REGEXP_ANCHOR_ALT + /* + The struct AnchorAlternation represents a pair of anchors with OR + semantics. + */ + struct AnchorAlternation + { + int a; // this anchor... + int b; // ...or this one + }; +#endif + + enum { InitialState = 0, FinalState = 1 }; + void setup( bool caseSensitive ); + int setupState( int match ); + + /* + Let's hope that 13 lookaheads and 14 back-references are enough. + */ + enum { MaxLookaheads = 13, MaxBackRefs = 14 }; + enum { Anchor_Dollar = 0x00000001, Anchor_Caret = 0x00000002, + Anchor_Word = 0x00000004, Anchor_NonWord = 0x00000008, + Anchor_FirstLookahead = 0x00000010, + Anchor_BackRef1Empty = Anchor_FirstLookahead << MaxLookaheads, + Anchor_BackRef0Empty = Anchor_BackRef1Empty >> 1, + Anchor_Alternation = Anchor_BackRef1Empty << MaxBackRefs, + + Anchor_LookaheadMask = ( Anchor_FirstLookahead - 1 ) ^ + ( (Anchor_FirstLookahead << MaxLookaheads) - 1 ) }; +#ifndef QT_NO_REGEXP_CAPTURE + int startAtom( bool capture ); + void finishAtom( int atom ) { cf = f[atom].parent; } +#endif + +#ifndef QT_NO_REGEXP_LOOKAHEAD + int addLookahead( QRegExpEngine *eng, bool negative ); +#endif + +#ifndef QT_NO_REGEXP_CAPTURE + bool isBetterCapture( const int *begin1, const int *end1, const int *begin2, + const int *end2 ); +#endif + bool testAnchor( int i, int a, const int *capBegin ); + +#ifndef QT_NO_REGEXP_OPTIM + bool goodStringMatch(); + bool badCharMatch(); +#else + bool bruteMatch(); +#endif + bool matchHere(); + + QVector s; // array of states + int ns; // number of states +#ifndef QT_NO_REGEXP_CAPTURE + QArray f; // atom hierarchy + int nf; // number of atoms + int cf; // current atom +#endif + int realncap; // number of captures, seen from the outside + int ncap; // number of captures, seen from the inside +#ifndef QT_NO_REGEXP_CCLASS + QVector cl; // array of character classes +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + QVector ahead; // array of lookaheads +#endif +#ifndef QT_NO_REGEXP_ANCHOR_ALT + QArray aa; // array of (a, b) pairs of anchors +#endif +#ifndef QT_NO_REGEXP_OPTIM + bool caretAnchored; // does the regexp start with ^? +#endif + bool valid; // is the regular expression valid? + bool cs; // case sensitive? +#ifndef QT_NO_REGEXP_BACKREF + int nbrefs; // number of back-references +#endif + +#ifndef QT_NO_REGEXP_OPTIM + bool useGoodStringHeuristic; // use goodStringMatch? otherwise badCharMatch + + int goodEarlyStart; // the index where goodStr can first occur in a match + int goodLateStart; // the index where goodStr can last occur in a match + QString goodStr; // the string that any match has to contain + + int minl; // the minimum length of a match + QArray occ1; // first-occurrence array +#endif + + /* + The class Box is an abstraction for a regular expression fragment. It can + also be seen as one node in the syntax tree of a regular expression with + synthetized attributes. + + It's interface is ugly for performance reasons. + */ + class Box + { + public: + Box( QRegExpEngine *engine ); + Box( const Box& b ) { operator=( b ); } + + Box& operator=( const Box& b ); + + void clear() { operator=(Box(eng)); } + void set( QChar ch ); + void set( const CharClass& cc ); +#ifndef QT_NO_REGEXP_BACKREF + void set( int bref ); +#endif + + void cat( const Box& b ); + void orx( const Box& b ); + void plus( int atom ); + void opt(); + void catAnchor( int a ); +#ifndef QT_NO_REGEXP_OPTIM + void setupHeuristics(); +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + + private: + void addAnchorsToEngine( const Box& to ) const; + + QRegExpEngine *eng; // the automaton under construction + QArray ls; // the left states (firstpos) + QArray rs; // the right states (lastpos) + QMap lanchors; // the left anchors + QMap ranchors; // the right anchors + int skipanchors; // the anchors to match if the box is skipped + +#ifndef QT_NO_REGEXP_OPTIM + int earlyStart; // the index where str can first occur + int lateStart; // the index where str can last occur + QString str; // a string that has to occur in any match + QString leftStr; // a string occurring at the left of this box + QString rightStr; // a string occurring at the right of this box + int maxl; // the maximum length of this box (possibly InftyLen) +#endif + + int minl; // the minimum length of this box +#ifndef QT_NO_REGEXP_OPTIM + QArray occ1; // first-occurrence array +#endif + }; + friend class Box; + + /* + This is the lexical analyzer for regular expressions. + */ + enum { Tok_Eos, Tok_Dollar, Tok_LeftParen, Tok_MagicLeftParen, + Tok_PosLookahead, Tok_NegLookahead, Tok_RightParen, Tok_CharClass, + Tok_Caret, Tok_Quantifier, Tok_Bar, Tok_Word, Tok_NonWord, + Tok_Char = 0x10000, Tok_BackRef = 0x20000 }; + int getChar(); + int getEscape(); +#ifndef QT_NO_REGEXP_INTERVAL + int getRep( int def ); +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + void skipChars( int n ); +#endif + void startTokenizer( const QChar *rx, int len ); + int getToken(); + + const QChar *yyIn; // a pointer to the input regular expression pattern + int yyPos0; // the position of yyTok in the input pattern + int yyPos; // the position of the next character to read + int yyLen; // the length of yyIn + int yyCh; // the last character read + CharClass *yyCharClass; // attribute for Tok_CharClass tokens + int yyMinRep; // attribute for Tok_Quantifier + int yyMaxRep; // ditto + bool yyError; // syntax error or overflow during parsing? + + /* + This is the syntactic analyzer for regular expressions. + */ + int parse( const QChar *rx, int len ); + void parseAtom( Box *box ); + void parseFactor( Box *box ); + void parseTerm( Box *box ); + void parseExpression( Box *box ); + + int yyTok; // the last token read + bool yyMayCapture; // set this to FALSE to disable capturing + + /* + This is the engine state during matching. + */ + const QString *mmStr; // a pointer to the input QString + const QChar *mmIn; // a pointer to the input string data + int mmPos; // the current position in the string + int mmLen; // the length of the input string + bool mmMinimal; // minimal matching? + QArray mmCaptured; // an array of pairs (start, len) + QArray mmCapturedNoMatch; // an array of pairs (-1, -1) + QArray mmBigArray; // big QArray array + int *mmInNextStack; // is state is mmNextStack? + int *mmCurStack; // stack of current states + int *mmNextStack; // stack of next states + int *mmCurCapBegin; // start of current states' captures + int *mmNextCapBegin; // start of next states' captures + int *mmCurCapEnd; // end of current states' captures + int *mmNextCapEnd; // end of next states' captures + int *mmTempCapBegin; // start of temporary captures + int *mmTempCapEnd; // end of temporary captures + int *mmCapBegin; // start of captures for a next state + int *mmCapEnd; // end of captures for a next state + int *mmSlideTab; // bump-along slide table for bad-character heuristic + int mmSlideTabSize; // size of slide table +#ifndef QT_NO_REGEXP_BACKREF + QIntDict mmSleeping; // dictionary of back-reference sleepers +#endif + int mmMatchedLen; // length of match or of matched string for partial match +}; + +QRegExpEngine::QRegExpEngine( const QString& rx, bool caseSensitive ) +#ifndef QT_NO_REGEXP_BACKREF + : mmSleeping( 101 ) +#endif +{ + setup( caseSensitive ); + valid = ( parse(rx.unicode(), rx.length()) == (int) rx.length() ); +} + +#ifndef QT_NO_REGEXP_OPTIM +QRegExpEngine::~QRegExpEngine() +{ + if ( --engCount == 0 ) { + delete noOccurrences; + noOccurrences = 0; + delete firstOccurrenceAtZero; + firstOccurrenceAtZero = 0; + } +} +#endif + +/* + Tries to match in str and returns an array of (begin, length) pairs for + captured text. If there is no match, all pairs are (-1, -1). +*/ +QArray QRegExpEngine::match( const QString& str, int pos, bool minimal, + bool oneTest ) +{ + mmStr = &str; + mmIn = str.unicode(); + if ( mmIn == 0 ) + mmIn = &QChar::null; + mmPos = pos; + mmLen = str.length(); + mmMinimal = minimal; + mmMatchedLen = 0; + + bool matched = FALSE; + if ( valid && mmPos >= 0 && mmPos <= mmLen ) { +#ifndef QT_NO_REGEXP_OPTIM + if ( mmPos <= mmLen - minl ) { + if ( caretAnchored || oneTest ) + matched = matchHere(); + else if ( useGoodStringHeuristic ) + matched = goodStringMatch(); + else + matched = badCharMatch(); + } +#else + matched = oneTest ? matchHere() : bruteMatch(); +#endif + } + + if ( matched ) { + mmCaptured.detach(); + mmCaptured[0] = mmPos; + mmCaptured[1] = mmMatchedLen; + for ( int j = 0; j < realncap; j++ ) { + int len = mmCapEnd[j] - mmCapBegin[j]; + mmCaptured[2 + 2 * j] = len > 0 ? mmPos + mmCapBegin[j] : 0; + mmCaptured[2 + 2 * j + 1] = len; + } + return mmCaptured; + } else { + return mmCapturedNoMatch; + } +} + +/* + The three following functions add one state to the automaton and return the + number of the state. +*/ + +int QRegExpEngine::createState( QChar ch ) +{ + return setupState( ch.unicode() ); +} + +int QRegExpEngine::createState( const CharClass& cc ) +{ +#ifndef QT_NO_REGEXP_CCLASS + int n = cl.size(); + cl.resize( n + 1 ); + cl.insert( n, new CharClass(cc) ); + return setupState( CharClassBit | n ); +#else + Q_UNUSED( cc ); + return setupState( CharClassBit ); +#endif +} + +#ifndef QT_NO_REGEXP_BACKREF +int QRegExpEngine::createState( int bref ) +{ + if ( bref > nbrefs ) { + nbrefs = bref; + if ( nbrefs > MaxBackRefs ) { + yyError = TRUE; + return 0; + } + } + return setupState( BackRefBit | bref ); +} +#endif + +/* + The two following functions add a transition between all pairs of states + (i, j) where i is fond in from, and j is found in to. + + Cat-transitions are distinguished from plus-transitions for capturing. +*/ + +void QRegExpEngine::addCatTransitions( const QArray& from, + const QArray& to ) +{ + for ( int i = 0; i < (int) from.size(); i++ ) { + State *st = s[from[i]]; + mergeInto( &st->outs, to ); + } +} + +#ifndef QT_NO_REGEXP_CAPTURE +void QRegExpEngine::addPlusTransitions( const QArray& from, + const QArray& to, int atom ) +{ + for ( int i = 0; i < (int) from.size(); i++ ) { + State *st = s[from[i]]; + QArray oldOuts = st->outs.copy(); + mergeInto( &st->outs, to ); + if ( f[atom].capture >= 0 ) { + if ( st->reenter == 0 ) + st->reenter = new QMap; + for ( int j = 0; j < (int) to.size(); j++ ) { + if ( !st->reenter->contains(to[j]) && + oldOuts.bsearch(to[j]) < 0 ) + st->reenter->insert( to[j], atom ); + } + } + } +} +#endif + +#ifndef QT_NO_REGEXP_ANCHOR_ALT +/* + Returns an anchor that means a OR b. +*/ +int QRegExpEngine::anchorAlternation( int a, int b ) +{ + if ( ((a & b) == a || (a & b) == b) && ((a | b) & Anchor_Alternation) == 0 ) + return a & b; + + int n = aa.size(); + aa.resize( n + 1 ); + aa[n].a = a; + aa[n].b = b; + return Anchor_Alternation | n; +} + +/* + Returns an anchor that means a AND b. +*/ +int QRegExpEngine::anchorConcatenation( int a, int b ) +{ + if ( ((a | b) & Anchor_Alternation) == 0 ) + return a | b; + if ( (b & Anchor_Alternation) != 0 ) + qSwap( a, b ); + int aprime = anchorConcatenation( aa[a ^ Anchor_Alternation].a, b ); + int bprime = anchorConcatenation( aa[a ^ Anchor_Alternation].b, b ); + return anchorAlternation( aprime, bprime ); +} +#endif + +/* + Adds anchor a on a transition caracterised by its from state and its to state. +*/ +void QRegExpEngine::addAnchors( int from, int to, int a ) +{ + State *st = s[from]; + if ( st->anchors == 0 ) + st->anchors = new QMap; + if ( st->anchors->contains(to) ) + a = anchorAlternation( (*st->anchors)[to], a ); + st->anchors->insert( to, a ); +} + +#ifndef QT_NO_REGEXP_OPTIM +/* + The two following functions provide the engine with the information needed by + its matching heuristics. +*/ + +void QRegExpEngine::setupGoodStringHeuristic( int earlyStart, int lateStart, + const QString& str ) +{ + goodEarlyStart = earlyStart; + goodLateStart = lateStart; + goodStr = cs ? str : str.lower(); +} + +void QRegExpEngine::setupBadCharHeuristic( int minLen, + const QArray& firstOcc ) +{ + minl = minLen; + occ1 = cs ? firstOcc : *firstOccurrenceAtZero; +} + +/* + This function chooses between the good-string and the bad-character + heuristics. It computes two scores and chooses the heuristic with the highest + score. + + Here are some common-sense constraints on the scores that should be respected + if the formulas are ever modified: (1) If goodStr is empty, the good-string + heuristic scores 0. (2) If the search is case insensitive, the good-string + heuristic should be used, unless it scores 0. (Case insensitivity + turns all entries of occ1 to 0.) (3) If (goodLateStart - goodEarlyStart) is + big, the good-string heuristic should score less. +*/ +void QRegExpEngine::heuristicallyChooseHeuristic() +{ + int i; + + if ( minl == 0 ) + return; + + /* + Magic formula: The good string has to constitute a good proportion of the + minimum-length string, and appear at a more-or-less known index. + */ + int goodStringScore = ( 64 * goodStr.length() / minl ) - + ( goodLateStart - goodEarlyStart ); + + /* + Less magic formula: We pick a couple of characters at random, and check + whether they are good or bad. + */ + int badCharScore = 0; + int step = QMAX( 1, NumBadChars / 32 ); + for ( i = 1; i < NumBadChars; i += step ) { + if ( occ1[i] == NoOccurrence ) + badCharScore += minl; + else + badCharScore += occ1[i]; + } + badCharScore /= minl; + + useGoodStringHeuristic = ( goodStringScore > badCharScore ); +} +#endif + +#if defined(QT_DEBUG) +void QRegExpEngine::dump() const +{ + int i, j; + qDebug( "Case %ssensitive engine", cs ? "" : "in" ); + qDebug( " States" ); + for ( i = 0; i < ns; i++ ) { + qDebug( " %d%s", i, + i == InitialState ? " (initial)" : + i == FinalState ? " (final)" : "" ); +#ifndef QT_NO_REGEXP_CAPTURE + qDebug( " in atom %d", s[i]->atom ); +#endif + int m = s[i]->match; + if ( (m & CharClassBit) != 0 ) { + qDebug( " match character class %d", m ^ CharClassBit ); +#ifndef QT_NO_REGEXP_CCLASS + cl[m ^ CharClassBit]->dump(); +#else + qDebug( " negative character class" ); +#endif + } else if ( (m & BackRefBit) != 0 ) { + qDebug( " match back-reference %d", m ^ BackRefBit ); + } else if ( m >= 0x20 && m <= 0x7e ) { + qDebug( " match 0x%.4x (%c)", m, m ); + } else { + qDebug( " match 0x%.4x", m ); + } + for ( j = 0; j < (int) s[i]->outs.size(); j++ ) { + int next = s[i]->outs[j]; + qDebug( " -> %d", next ); + if ( s[i]->reenter != 0 && s[i]->reenter->contains(next) ) + qDebug( " [reenter %d]", (*s[i]->reenter)[next] ); + if ( s[i]->anchors != 0 && at(*s[i]->anchors, next) != 0 ) + qDebug( " [anchors 0x%.8x]", (*s[i]->anchors)[next] ); + } + } +#ifndef QT_NO_REGEXP_CAPTURE + if ( nf > 0 ) { + qDebug( " Atom Parent Capture" ); + for ( i = 0; i < nf; i++ ) + qDebug( " %6d %6d %6d", i, f[i].parent, f[i].capture ); + } +#endif +#ifndef QT_NO_REGEXP_ANCHOR_ALT + for ( i = 0; i < (int) aa.size(); i++ ) + qDebug( " Anchor alternation 0x%.8x: 0x%.8x 0x%.9x", i, aa[i].a, + aa[i].b ); +#endif +} +#endif + +void QRegExpEngine::setup( bool caseSensitive ) +{ +#ifndef QT_NO_REGEXP_OPTIM + if ( engCount++ == 0 ) { + noOccurrences = new QArray( NumBadChars ); + firstOccurrenceAtZero = new QArray( NumBadChars ); + noOccurrences->fill( NoOccurrence ); + firstOccurrenceAtZero->fill( 0 ); + } +#endif + s.setAutoDelete( TRUE ); + s.resize( 32 ); + ns = 0; +#ifndef QT_NO_REGEXP_CAPTURE + f.resize( 32 ); + nf = 0; + cf = -1; +#endif + realncap = 0; + ncap = 0; +#ifndef QT_NO_REGEXP_CCLASS + cl.setAutoDelete( TRUE ); +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + ahead.setAutoDelete( TRUE ); +#endif +#ifndef QT_NO_REGEXP_OPTIM + caretAnchored = TRUE; +#endif + valid = FALSE; + cs = caseSensitive; +#ifndef QT_NO_REGEXP_BACKREF + nbrefs = 0; +#endif +#ifndef QT_NO_REGEXP_OPTIM + useGoodStringHeuristic = FALSE; + minl = 0; + occ1 = *firstOccurrenceAtZero; +#endif + mmCapturedNoMatch.fill( -1, 2 ); +} + +int QRegExpEngine::setupState( int match ) +{ + if ( (ns & (ns + 1)) == 0 && ns + 1 >= (int) s.size() ) + s.resize( (ns + 1) << 1 ); +#ifndef QT_NO_REGEXP_CAPTURE + s.insert( ns, new State(cf, match) ); +#else + s.insert( ns, new State(match) ); +#endif + return ns++; +} + +#ifndef QT_NO_REGEXP_CAPTURE +/* + Functions startAtom() and finishAtom() should be called to delimit atoms. + When a state is created, it is assigned to the current atom. The information + is later used for capturing. +*/ +int QRegExpEngine::startAtom( bool capture ) +{ + if ( (nf & (nf + 1)) == 0 && nf + 1 >= (int) f.size() ) + f.resize( (nf + 1) << 1 ); + f[nf].parent = cf; + cf = nf++; + f[cf].capture = capture ? ncap++ : -1; + return cf; +} +#endif + +#ifndef QT_NO_REGEXP_LOOKAHEAD +/* + Creates a lookahead anchor. +*/ +int QRegExpEngine::addLookahead( QRegExpEngine *eng, bool negative ) +{ + int n = ahead.size(); + if ( n == MaxLookaheads ) { + yyError = TRUE; + return 0; + } + ahead.resize( n + 1 ); + ahead.insert( n, new Lookahead(eng, negative) ); + return Anchor_FirstLookahead << n; +} +#endif + +#ifndef QT_NO_REGEXP_CAPTURE +/* + We want the longest leftmost captures. +*/ +bool QRegExpEngine::isBetterCapture( const int *begin1, const int *end1, + const int *begin2, const int *end2 ) +{ + for ( int i = 0; i < ncap; i++ ) { + int delta = begin2[i] - begin1[i]; // it has to start early... + if ( delta == 0 ) + delta = end1[i] - end2[i]; // ...and end late (like a party) + + if ( delta != 0 ) + return delta > 0; + } + return FALSE; +} +#endif + +/* + Returns TRUE if anchor a matches at position mmPos + i in the input string, + otherwise FALSE. +*/ +bool QRegExpEngine::testAnchor( int i, int a, const int *capBegin ) +{ + int j; + +#ifndef QT_NO_REGEXP_ANCHOR_ALT + if ( (a & Anchor_Alternation) != 0 ) { + return testAnchor( i, aa[a ^ Anchor_Alternation].a, capBegin ) || + testAnchor( i, aa[a ^ Anchor_Alternation].b, capBegin ); + } +#endif + + if ( (a & Anchor_Caret) != 0 ) { + if ( mmPos + i != 0 ) + return FALSE; + } + if ( (a & Anchor_Dollar) != 0 ) { + if ( mmPos + i != mmLen ) + return FALSE; + } +#ifndef QT_NO_REGEXP_ESCAPE + if ( (a & (Anchor_Word | Anchor_NonWord)) != 0 ) { + bool before = FALSE, after = FALSE; + if ( mmPos + i != 0 ) + before = mmIn[mmPos + i - 1].isLetterOrNumber(); + if ( mmPos + i != mmLen ) + after = mmIn[mmPos + i].isLetterOrNumber(); + if ( (a & Anchor_Word) != 0 && (before == after) ) + return FALSE; + if ( (a & Anchor_NonWord) != 0 && (before != after) ) + return FALSE; + } +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + bool catchx = TRUE; + + if ( (a & Anchor_LookaheadMask) != 0 ) { + QConstString cstr = QConstString( (QChar *) mmIn + mmPos + i, + mmLen - mmPos - i ); + for ( j = 0; j < (int) ahead.size(); j++ ) { + if ( (a & (Anchor_FirstLookahead << j)) != 0 ) { + catchx = ( ahead[j]->eng->match(cstr.string(), 0, TRUE, + TRUE)[0] == 0 ); + if ( catchx == ahead[j]->neg ) + return FALSE; + } + } + } +#endif +#ifndef QT_NO_REGEXP_CAPTURE +#ifndef QT_NO_REGEXP_BACKREF + for ( j = 0; j < nbrefs; j++ ) { + if ( (a & (Anchor_BackRef1Empty << j)) != 0 ) { + if ( capBegin[j] != EmptyCapture ) + return FALSE; + } + } +#endif +#endif + return TRUE; +} + +#ifndef QT_NO_REGEXP_OPTIM +/* + The three following functions are what Jeffrey Friedl would call transmissions + (or bump-alongs). Using one or the other should make no difference, except + in performance. +*/ + +bool QRegExpEngine::goodStringMatch() +{ + int k = mmPos + goodEarlyStart; + + while ( (k = mmStr->find(goodStr, k, cs)) != -1 ) { + int from = k - goodLateStart; + int to = k - goodEarlyStart; + if ( from > mmPos ) + mmPos = from; + + while ( mmPos <= to ) { + if ( matchHere() ) + return TRUE; + mmPos++; + } + k++; + } + return FALSE; +} + +bool QRegExpEngine::badCharMatch() +{ + int slideHead = 0; + int slideNext = 0; + int i; + int lastPos = mmLen - minl; + memset( mmSlideTab, 0, mmSlideTabSize * sizeof(int) ); + + /* + Set up the slide table, used for the bad-character heuristic, using + the table of first occurrence of each character. + */ + for ( i = 0; i < minl; i++ ) { + int sk = occ1[BadChar(mmIn[mmPos + i])]; + if ( sk == NoOccurrence ) + sk = i + 1; + if ( sk > 0 ) { + int k = i + 1 - sk; + if ( k < 0 ) { + sk = i + 1; + k = 0; + } + if ( sk > mmSlideTab[k] ) + mmSlideTab[k] = sk; + } + } + + if ( mmPos > lastPos ) + return FALSE; + + while ( TRUE ) { + if ( ++slideNext >= mmSlideTabSize ) + slideNext = 0; + if ( mmSlideTab[slideHead] > 0 ) { + if ( mmSlideTab[slideHead] - 1 > mmSlideTab[slideNext] ) + mmSlideTab[slideNext] = mmSlideTab[slideHead] - 1; + mmSlideTab[slideHead] = 0; + } else { + if ( matchHere() ) + return TRUE; + } + + if ( mmPos == lastPos ) + break; + + /* + Update the slide table. This code has much in common with the + initialization code. + */ + int sk = occ1[BadChar(mmIn[mmPos + minl])]; + if ( sk == NoOccurrence ) { + mmSlideTab[slideNext] = minl; + } else if ( sk > 0 ) { + int k = slideNext + minl - sk; + if ( k >= mmSlideTabSize ) + k -= mmSlideTabSize; + if ( sk > mmSlideTab[k] ) + mmSlideTab[k] = sk; + } + slideHead = slideNext; + mmPos++; + } + return FALSE; +} +#else +bool QRegExpEngine::bruteMatch() +{ + while ( mmPos <= mmLen ) { + if ( matchHere() ) + return TRUE; + mmPos++; + } + return FALSE; +} +#endif + +/* + Here's the core of the engine. It tries to do a match here and now. +*/ +bool QRegExpEngine::matchHere() +{ + int ncur = 1, nnext = 0; + int i = 0, j, k, m; + bool match = FALSE; + + mmMatchedLen = -1; + mmCurStack[0] = InitialState; + +#ifndef QT_NO_REGEXP_CAPTURE + if ( ncap > 0 ) { + for ( j = 0; j < ncap; j++ ) { + mmCurCapBegin[j] = EmptyCapture; + mmCurCapEnd[j] = EmptyCapture; + } + } +#endif + +#ifndef QT_NO_REGEXP_BACKREF + int *zzZ = 0; + + while ( (ncur > 0 || mmSleeping.count() > 0) && i <= mmLen - mmPos && + !match ) +#else + while ( ncur > 0 && i <= mmLen - mmPos && !match ) +#endif + { + int ch = ( i < mmLen - mmPos ) ? mmIn[mmPos + i].unicode() : 0; + for ( j = 0; j < ncur; j++ ) { + int cur = mmCurStack[j]; + State *scur = s[cur]; + QArray& outs = scur->outs; + for ( k = 0; k < (int) outs.size(); k++ ) { + int next = outs[k]; + State *snext = s[next]; + bool in = TRUE; +#ifndef QT_NO_REGEXP_BACKREF + int needSomeSleep = 0; +#endif + + /* + First, check if the anchors are anchored properly. + */ + if ( scur->anchors != 0 ) { + int a = at( *scur->anchors, next ); + if ( a != 0 && !testAnchor(i, a, mmCurCapBegin + j * ncap) ) + in = FALSE; + } + /* + If indeed they are, check if the input character is correct + for this transition. + */ + if ( in ) { + m = snext->match; + if ( (m & (CharClassBit | BackRefBit)) == 0 ) { + if ( cs ) + in = ( m == ch ); + else + in = ( QChar(m).lower() == QChar(ch).lower() ); + } else if ( next == FinalState ) { + mmMatchedLen = i; + match = mmMinimal; + in = TRUE; + } else if ( (m & CharClassBit) != 0 ) { +#ifndef QT_NO_REGEXP_CCLASS + const CharClass *cc = cl[m ^ CharClassBit]; + if ( cs ) + in = cc->in( ch ); + else if ( cc->negative() ) + in = cc->in( QChar(ch).lower() ) && + cc->in( QChar(ch).upper() ); + else + in = cc->in( QChar(ch).lower() ) || + cc->in( QChar(ch).upper() ); +#endif +#ifndef QT_NO_REGEXP_BACKREF + } else { /* ( (m & BackRefBit) != 0 ) */ + int bref = m ^ BackRefBit; + int ell = j * ncap + ( bref - 1 ); + + in = bref <= ncap && mmCurCapBegin[ell] != EmptyCapture; + if ( in ) { + if ( cs ) + in = ( mmIn[mmPos + mmCurCapBegin[ell]] + == QChar(ch) ); + else + in = ( mmIn[mmPos + mmCurCapBegin[ell]].lower() + == QChar(ch).lower() ); + } + + if ( in ) { + int delta; + if ( mmCurCapEnd[ell] == EmptyCapture ) + delta = i - mmCurCapBegin[ell]; + else + delta = mmCurCapEnd[ell] - mmCurCapBegin[ell]; + + in = ( delta <= mmLen - mmPos ); + if ( in && delta > 1 ) { + int n; + if ( cs ) { + for ( n = 1; n < delta; n++ ) { + if ( mmIn[mmPos + + mmCurCapBegin[ell] + n] != + mmIn[mmPos + i + n] ) + break; + } + } else { + for ( n = 1; n < delta; n++ ) { + QChar a = mmIn[mmPos + + mmCurCapBegin[ell] + n]; + QChar b = mmIn[mmPos + i + n]; + if ( a.lower() != b.lower() ) + break; + } + } + in = ( n == delta ); + if ( in ) + needSomeSleep = delta - 1; + } + } +#endif + } + } + + /* + All is right. We must now update our data structures. + */ + if ( in ) { +#ifndef QT_NO_REGEXP_CAPTURE + int *capBegin, *capEnd; +#endif + /* + If the next state was not encountered yet, all is fine. + */ + if ( (m = mmInNextStack[next]) == -1 ) { + m = nnext++; + mmNextStack[m] = next; + mmInNextStack[next] = m; +#ifndef QT_NO_REGEXP_CAPTURE + capBegin = mmNextCapBegin + m * ncap; + capEnd = mmNextCapEnd + m * ncap; + + /* + Otherwise, we'll first maintain captures in temporary + arrays, and decide at the end whether it's best to keep + the previous capture zones or the new ones. + */ + } else { + capBegin = mmTempCapBegin; + capEnd = mmTempCapEnd; +#endif + } + +#ifndef QT_NO_REGEXP_CAPTURE + /* + Updating the capture zones is much of a task. + */ + if ( ncap > 0 ) { + memcpy( capBegin, mmCurCapBegin + j * ncap, + ncap * sizeof(int) ); + memcpy( capEnd, mmCurCapEnd + j * ncap, + ncap * sizeof(int) ); + int c = scur->atom, n = snext->atom; + int p = -1, q = -1; + int cap; + + /* + Lemma 1. For any x in the range [0..nf), we have + f[x].parent < x. + + Proof. By looking at startAtom(), it is clear that + cf < nf holds all the time, and thus that + f[nf].parent < nf. + */ + + /* + If we are reentering an atom, we empty all capture + zones inside it. + */ + if ( scur->reenter != 0 && + (q = at(*scur->reenter, next)) != 0 ) { + QBitArray b; + b.fill( FALSE, nf ); + b.setBit( q, TRUE ); + for ( int ell = q + 1; ell < nf; ell++ ) { + if ( b.testBit(f[ell].parent) ) { + b.setBit( ell, TRUE ); + cap = f[ell].capture; + if ( cap >= 0 ) { + capBegin[cap] = EmptyCapture; + capEnd[cap] = EmptyCapture; + } + } + } + p = f[q].parent; + + /* + Otherwise, close the capture zones we are leaving. + We are leaving f[c].capture, f[f[c].parent].capture, + f[f[f[c].parent].parent].capture, ..., until + f[x].capture, with x such that f[x].parent is the + youngest common ancestor for c and n. + + We go up along c's and n's ancestry until we find x. + */ + } else { + p = c; + q = n; + while ( p != q ) { + if ( p > q ) { + cap = f[p].capture; + if ( cap >= 0 ) { + if ( capBegin[cap] == i ) { + capBegin[cap] = EmptyCapture; + capEnd[cap] = EmptyCapture; + } else { + capEnd[cap] = i; + } + } + p = f[p].parent; + } else { + q = f[q].parent; + } + } + } + + /* + In any case, we now open the capture zones we are + entering. We work upwards from n until we reach p + (the parent of the atom we reenter or the youngest + common ancestor). + */ + while ( n > p ) { + cap = f[n].capture; + if ( cap >= 0 ) { + capBegin[cap] = i; + capEnd[cap] = EmptyCapture; + } + n = f[n].parent; + } + /* + If the next state was already in mmNextStack, we must + choose carefully which capture zones we want to keep. + */ + if ( capBegin == mmTempCapBegin && + isBetterCapture(capBegin, capEnd, + mmNextCapBegin + m * ncap, + mmNextCapEnd + m * ncap) ) { + memcpy( mmNextCapBegin + m * ncap, capBegin, + ncap * sizeof(int) ); + memcpy( mmNextCapEnd + m * ncap, capEnd, + ncap * sizeof(int) ); + } + } +#ifndef QT_NO_REGEXP_BACKREF + /* + We are done with updating the capture zones. It's now + time to put the next state to sleep, if it needs to, and + to remove it from mmNextStack. + */ + if ( needSomeSleep > 0 ) { + zzZ = new int[1 + 2 * ncap]; + zzZ[0] = next; + if ( ncap > 0 ) { + memcpy( zzZ + 1, capBegin, ncap * sizeof(int) ); + memcpy( zzZ + 1 + ncap, capEnd, + ncap * sizeof(int) ); + } + mmInNextStack[mmNextStack[--nnext]] = -1; + mmSleeping.insert( i + needSomeSleep, zzZ ); + } +#endif +#endif + } + } + } +#ifndef QT_NO_REGEXP_CAPTURE + /* + If we reached the final state, hurray! Copy the captured zone. + */ + if ( ncap > 0 && (m = mmInNextStack[FinalState]) != -1 ) { + memcpy( mmCapBegin, mmNextCapBegin + m * ncap, ncap * sizeof(int) ); + memcpy( mmCapEnd, mmNextCapEnd + m * ncap, ncap * sizeof(int) ); + } +#ifndef QT_NO_REGEXP_BACKREF + /* + It's time to wake up the sleepers. + */ + if ( mmSleeping.count() > 0 ) { + while ( (zzZ = mmSleeping.take(i)) != 0 ) { + int next = zzZ[0]; + int *capBegin = zzZ + 1; + int *capEnd = zzZ + 1 + ncap; + bool copyOver = TRUE; + + if ( (m = mmInNextStack[zzZ[0]]) == -1 ) { + m = nnext++; + mmNextStack[m] = next; + mmInNextStack[next] = m; + } else { + copyOver = isBetterCapture( mmNextCapBegin + m * ncap, + mmNextCapEnd + m * ncap, + capBegin, capEnd ); + } + if ( copyOver ) { + memcpy( mmNextCapBegin + m * ncap, capBegin, + ncap * sizeof(int) ); + memcpy( mmNextCapEnd + m * ncap, capEnd, + ncap * sizeof(int) ); + } + delete[] zzZ; + } + } +#endif +#endif + for ( j = 0; j < nnext; j++ ) + mmInNextStack[mmNextStack[j]] = -1; + + qSwap( mmCurStack, mmNextStack ); +#ifndef QT_NO_REGEXP_CAPTURE + qSwap( mmCurCapBegin, mmNextCapBegin ); + qSwap( mmCurCapEnd, mmNextCapEnd ); +#endif + ncur = nnext; + nnext = 0; + i++; + } + +#ifndef QT_NO_REGEXP_BACKREF + /* + If minimal matching is enabled, we might have some sleepers left. + */ + while ( !mmSleeping.isEmpty() ) { + zzZ = mmSleeping.take( *QIntDictIterator(mmSleeping) ); + delete[] zzZ; + } +#endif + + match = ( mmMatchedLen >= 0 ); + if ( !match ) + mmMatchedLen = i - 1; + return match; +} + +#ifndef QT_NO_REGEXP_CCLASS + +QRegExpEngine::CharClass::CharClass() + : c( 0 ), n( FALSE ) +#ifndef QT_NO_REGEXP_OPTIM + , occ1( *noOccurrences ) +#endif +{ +} + +QRegExpEngine::CharClass& QRegExpEngine::CharClass::operator=( + const CharClass& cc ) +{ + c = cc.c; + r = cc.r.copy(); + n = cc.n; +#ifndef QT_NO_REGEXP_OPTIM + occ1 = cc.occ1; +#endif + return *this; +} + +void QRegExpEngine::CharClass::clear() +{ + c = 0; + r.resize( 0 ); + n = FALSE; +} + +void QRegExpEngine::CharClass::setNegative( bool negative ) +{ + n = negative; +#ifndef QT_NO_REGEXP_OPTIM + occ1 = *firstOccurrenceAtZero; +#endif +} + +void QRegExpEngine::CharClass::addCategories( int cats ) +{ + c |= cats; +#ifndef QT_NO_REGEXP_OPTIM + occ1 = *firstOccurrenceAtZero; +#endif +} + +void QRegExpEngine::CharClass::addRange( ushort from, ushort to ) +{ + if ( from > to ) + qSwap( from, to ); + int n = r.size(); + r.resize( n + 1 ); + r[n].from = from; + r[n].to = to; + +#ifndef QT_NO_REGEXP_OPTIM + int i; + + if ( to - from < NumBadChars ) { + occ1.detach(); + if ( from % NumBadChars <= to % NumBadChars ) { + for ( i = from % NumBadChars; i <= to % NumBadChars; i++ ) + occ1[i] = 0; + } else { + for ( i = 0; i <= to % NumBadChars; i++ ) + occ1[i] = 0; + for ( i = from % NumBadChars; i < NumBadChars; i++ ) + occ1[i] = 0; + } + } else { + occ1 = *firstOccurrenceAtZero; + } +#endif +} + +bool QRegExpEngine::CharClass::in( QChar ch ) const +{ +#ifndef QT_NO_REGEXP_OPTIM + if ( occ1[BadChar(ch)] == NoOccurrence ) + return n; +#endif + + if ( c != 0 && (c & (1 << (int) ch.category())) != 0 ) + return !n; + for ( int i = 0; i < (int) r.size(); i++ ) { + if ( ch.unicode() >= r[i].from && ch.unicode() <= r[i].to ) + return !n; + } + return n; +} + +#if defined(QT_DEBUG) +void QRegExpEngine::CharClass::dump() const +{ + int i; + qDebug( " %stive character class", n ? "nega" : "posi" ); +#ifndef QT_NO_REGEXP_CCLASS + if ( c != 0 ) + qDebug( " categories 0x%.8x", c ); +#endif + for ( i = 0; i < (int) r.size(); i++ ) + qDebug( " 0x%.4x through 0x%.4x", r[i].from, r[i].to ); +} +#endif +#endif + +QRegExpEngine::Box::Box( QRegExpEngine *engine ) + : eng( engine ), skipanchors( 0 ) +#ifndef QT_NO_REGEXP_OPTIM + , earlyStart( 0 ), lateStart( 0 ), maxl( 0 ), occ1( *noOccurrences ) +#endif +{ + minl = 0; +} + +QRegExpEngine::Box& QRegExpEngine::Box::operator=( const Box& b ) +{ + eng = b.eng; + ls = b.ls; + rs = b.rs; + lanchors = b.lanchors; + ranchors = b.ranchors; + skipanchors = b.skipanchors; +#ifndef QT_NO_REGEXP_OPTIM + earlyStart = b.earlyStart; + lateStart = b.lateStart; + str = b.str; + leftStr = b.leftStr; + rightStr = b.rightStr; + maxl = b.maxl; + occ1 = b.occ1; +#endif + minl = b.minl; + return *this; +} + +void QRegExpEngine::Box::set( QChar ch ) +{ + ls.resize( 1 ); + ls[0] = eng->createState( ch ); + rs = ls; + rs.detach(); +#ifndef QT_NO_REGEXP_OPTIM + str = ch; + leftStr = ch; + rightStr = ch; + maxl = 1; + occ1.detach(); + occ1[BadChar(ch)] = 0; +#endif + minl = 1; +} + +void QRegExpEngine::Box::set( const CharClass& cc ) +{ + ls.resize( 1 ); + ls[0] = eng->createState( cc ); + rs = ls; + rs.detach(); +#ifndef QT_NO_REGEXP_OPTIM + maxl = 1; + occ1 = cc.firstOccurrence(); +#endif + minl = 1; +} + +#ifndef QT_NO_REGEXP_BACKREF +void QRegExpEngine::Box::set( int bref ) +{ + ls.resize( 1 ); + ls[0] = eng->createState( bref ); + rs = ls; + rs.detach(); + if ( bref >= 1 && bref <= MaxBackRefs ) + skipanchors = Anchor_BackRef0Empty << bref; +#ifndef QT_NO_REGEXP_OPTIM + maxl = InftyLen; +#endif + minl = 0; +} +#endif + +void QRegExpEngine::Box::cat( const Box& b ) +{ + eng->addCatTransitions( rs, b.ls ); + addAnchorsToEngine( b ); + if ( minl == 0 ) { + mergeInto( &lanchors, b.lanchors ); + if ( skipanchors != 0 ) { + for ( int i = 0; i < (int) b.ls.size(); i++ ) { + int a = eng->anchorConcatenation( at(lanchors, b.ls[i]), + skipanchors ); + lanchors.insert( b.ls[i], a ); + } + } + mergeInto( &ls, b.ls ); + } + if ( b.minl == 0 ) { + mergeInto( &ranchors, b.ranchors ); + if ( b.skipanchors != 0 ) { + for ( int i = 0; i < (int) rs.size(); i++ ) { + int a = eng->anchorConcatenation( at(ranchors, rs[i]), + b.skipanchors ); + ranchors.insert( rs[i], a ); + } + } + mergeInto( &rs, b.rs ); + } else { + ranchors = b.ranchors; + rs = b.rs; + } + +#ifndef QT_NO_REGEXP_OPTIM + if ( maxl != InftyLen ) { + if ( rightStr.length() + b.leftStr.length() > + QMAX(str.length(), b.str.length()) ) { + earlyStart = minl - rightStr.length(); + lateStart = maxl - rightStr.length(); + str = rightStr + b.leftStr; + } else if ( b.str.length() > str.length() ) { + earlyStart = minl + b.earlyStart; + lateStart = maxl + b.lateStart; + str = b.str; + } + } + + if ( (int) leftStr.length() == maxl ) + leftStr += b.leftStr; + if ( (int) b.rightStr.length() == b.maxl ) + rightStr += b.rightStr; + else + rightStr = b.rightStr; + + if ( maxl == InftyLen || b.maxl == InftyLen ) + maxl = InftyLen; + else + maxl += b.maxl; + + occ1.detach(); + for ( int i = 0; i < NumBadChars; i++ ) { + if ( b.occ1[i] != NoOccurrence && minl + b.occ1[i] < occ1[i] ) + occ1[i] = minl + b.occ1[i]; + } +#endif + + minl += b.minl; + if ( minl == 0 ) + skipanchors = eng->anchorConcatenation( skipanchors, b.skipanchors ); + else + skipanchors = 0; +} + +void QRegExpEngine::Box::orx( const Box& b ) +{ + mergeInto( &ls, b.ls ); + mergeInto( &lanchors, b.lanchors ); + mergeInto( &rs, b.rs ); + mergeInto( &ranchors, b.ranchors ); + skipanchors = eng->anchorAlternation( skipanchors, b.skipanchors ); + +#ifndef QT_NO_REGEXP_OPTIM + occ1.detach(); + for ( int i = 0; i < NumBadChars; i++ ) { + if ( occ1[i] > b.occ1[i] ) + occ1[i] = b.occ1[i]; + } + earlyStart = 0; + lateStart = 0; + str = QString::null; + leftStr = QString::null; + rightStr = QString::null; + if ( b.maxl > maxl ) + maxl = b.maxl; +#endif + if ( b.minl < minl ) + minl = b.minl; +} + +void QRegExpEngine::Box::plus( int atom ) +{ +#ifndef QT_NO_REGEXP_CAPTURE + eng->addPlusTransitions( rs, ls, atom ); +#else + Q_UNUSED( atom ); + eng->addCatTransitions( rs, ls ); +#endif + addAnchorsToEngine( *this ); +#ifndef QT_NO_REGEXP_OPTIM + maxl = InftyLen; +#endif +} + +void QRegExpEngine::Box::opt() +{ +#ifndef QT_NO_REGEXP_OPTIM + earlyStart = 0; + lateStart = 0; + str = QString::null; + leftStr = QString::null; + rightStr = QString::null; +#endif + skipanchors = 0; + minl = 0; +} + +void QRegExpEngine::Box::catAnchor( int a ) +{ + if ( a != 0 ) { + for ( int i = 0; i < (int) rs.size(); i++ ) { + a = eng->anchorConcatenation( at(ranchors, rs[i]), a ); + ranchors.insert( rs[i], a ); + } + if ( minl == 0 ) + skipanchors = eng->anchorConcatenation( skipanchors, a ); + } +} + +#ifndef QT_NO_REGEXP_OPTIM +void QRegExpEngine::Box::setupHeuristics() +{ + eng->setupGoodStringHeuristic( earlyStart, lateStart, str ); + + /* + A regular expression such as 112|1 has occ1['2'] = 2 and minl = 1 at this + point. An entry of occ1 has to be at most minl or infinity for the rest + of the algorithm to go well. + + We waited until here before normalizing these cases (instead of doing it + in Box::orx()) because sometimes things improve by themselves; consider + (112|1)34. + */ + for ( int i = 0; i < NumBadChars; i++ ) { + if ( occ1[i] != NoOccurrence && occ1[i] >= minl ) + occ1[i] = minl; + } + eng->setupBadCharHeuristic( minl, occ1 ); + + eng->heuristicallyChooseHeuristic(); +} +#endif + +#if defined(QT_DEBUG) +void QRegExpEngine::Box::dump() const +{ + int i; + qDebug( "Box of at least %d character%s", minl, minl == 1 ? "" : "s" ); + qDebug( " Left states:" ); + for ( i = 0; i < (int) ls.size(); i++ ) { + if ( at(lanchors, ls[i]) == 0 ) + qDebug( " %d", ls[i] ); + else + qDebug( " %d [anchors 0x%.8x]", ls[i], lanchors[ls[i]] ); + } + qDebug( " Right states:" ); + for ( i = 0; i < (int) rs.size(); i++ ) { + if ( at(ranchors, ls[i]) == 0 ) + qDebug( " %d", rs[i] ); + else + qDebug( " %d [anchors 0x%.8x]", rs[i], ranchors[rs[i]] ); + } + qDebug( " Skip anchors: 0x%.8x", skipanchors ); +} +#endif + +void QRegExpEngine::Box::addAnchorsToEngine( const Box& to ) const +{ + for ( int i = 0; i < (int) to.ls.size(); i++ ) { + for ( int j = 0; j < (int) rs.size(); j++ ) { + int a = eng->anchorConcatenation( at(ranchors, rs[j]), + at(to.lanchors, to.ls[i]) ); + eng->addAnchors( rs[j], to.ls[i], a ); + } + } +} + +int QRegExpEngine::getChar() +{ + return ( yyPos == yyLen ) ? EOS : yyIn[yyPos++].unicode(); +} + +int QRegExpEngine::getEscape() +{ +#ifndef QT_NO_REGEXP_ESCAPE + const char tab[] = "afnrtv"; // no b, as \b means word boundary + const char backTab[] = "\a\f\n\r\t\v"; + ushort low; + int i; +#endif + ushort val; + int prevCh = yyCh; + + if ( prevCh == EOS ) { + yyError = TRUE; + return Tok_Char | '\\'; + } + yyCh = getChar(); +#ifndef QT_NO_REGEXP_ESCAPE + if ( (prevCh & ~0xff) == 0 ) { + const char *p = strchr( tab, prevCh ); + if ( p != 0 ) + return Tok_Char | backTab[p - tab]; + } +#endif + + switch ( prevCh ) { +#ifndef QT_NO_REGEXP_ESCAPE + case '0': + val = 0; + for ( i = 0; i < 3; i++ ) { + if ( yyCh >= '0' && yyCh <= '7' ) + val = ( val << 3 ) | ( yyCh - '0' ); + else + break; + yyCh = getChar(); + } + if ( (val & ~0377) != 0 ) + yyError = TRUE; + return Tok_Char | val; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case 'B': + return Tok_NonWord; +#endif +#ifndef QT_NO_REGEXP_CCLASS + case 'D': + // see QChar::isDigit() + yyCharClass->addCategories( 0x7fffffef ); + return Tok_CharClass; + case 'S': + // see QChar::isSpace() + yyCharClass->addCategories( 0x7ffff87f ); + yyCharClass->addRange( 0x0000, 0x0008 ); + yyCharClass->addRange( 0x000e, 0x001f ); + yyCharClass->addRange( 0x007f, 0x009f ); + return Tok_CharClass; + case 'W': + // see QChar::isLetterOrNumber() + yyCharClass->addCategories( 0x7ff07f8f ); + return Tok_CharClass; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case 'b': + return Tok_Word; +#endif +#ifndef QT_NO_REGEXP_CCLASS + case 'd': + // see QChar::isDigit() + yyCharClass->addCategories( 0x00000010 ); + return Tok_CharClass; + case 's': + // see QChar::isSpace() + yyCharClass->addCategories( 0x00000380 ); + yyCharClass->addRange( 0x0009, 0x000d ); + return Tok_CharClass; + case 'w': + // see QChar::isLetterOrNumber() + yyCharClass->addCategories( 0x000f8070 ); + return Tok_CharClass; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case 'x': + val = 0; + for ( i = 0; i < 4; i++ ) { + low = QChar( yyCh ).lower(); + if ( low >= '0' && low <= '9' ) + val = ( val << 4 ) | ( low - '0' ); + else if ( low >= 'a' && low <= 'f' ) + val = ( val << 4 ) | ( low - 'a' + 10 ); + else + break; + yyCh = getChar(); + } + return Tok_Char | val; +#endif + default: + if ( prevCh >= '1' && prevCh <= '9' ) { +#ifndef QT_NO_REGEXP_BACKREF + val = prevCh - '0'; + while ( yyCh >= '0' && yyCh <= '9' ) { + val = ( val *= 10 ) | ( yyCh - '0' ); + yyCh = getChar(); + } + return Tok_BackRef | val; +#else + yyError = TRUE; +#endif + } + return Tok_Char | prevCh; + } +} + +#ifndef QT_NO_REGEXP_INTERVAL +int QRegExpEngine::getRep( int def ) +{ + if ( yyCh >= '0' && yyCh <= '9' ) { + int rep = 0; + do { + rep = 10 * rep + yyCh - '0'; + if ( rep >= InftyRep ) { + yyError = TRUE; + rep = def; + } + yyCh = getChar(); + } while ( yyCh >= '0' && yyCh <= '9' ); + return rep; + } else { + return def; + } +} +#endif + +#ifndef QT_NO_REGEXP_LOOKAHEAD +void QRegExpEngine::skipChars( int n ) +{ + if ( n > 0 ) { + yyPos += n - 1; + yyCh = getChar(); + } +} +#endif + +void QRegExpEngine::startTokenizer( const QChar *rx, int len ) +{ + yyIn = rx; + yyPos0 = 0; + yyPos = 0; + yyLen = len; + yyCh = getChar(); + yyCharClass = new CharClass; + yyMinRep = 0; + yyMaxRep = 0; + yyError = FALSE; +} + +int QRegExpEngine::getToken() +{ +#ifndef QT_NO_REGEXP_CCLASS + ushort pendingCh = 0; + bool charPending; + bool rangePending; + int tok; +#endif + int prevCh = yyCh; + + yyPos0 = yyPos - 1; +#ifndef QT_NO_REGEXP_CCLASS + yyCharClass->clear(); +#endif + yyMinRep = 0; + yyMaxRep = 0; + yyCh = getChar(); + switch ( prevCh ) { + case EOS: + yyPos0 = yyPos; + return Tok_Eos; + case '$': + return Tok_Dollar; + case '(': + if ( yyCh == '?' ) { + prevCh = getChar(); + yyCh = getChar(); + switch ( prevCh ) { +#ifndef QT_NO_REGEXP_LOOKAHEAD + case '!': + return Tok_NegLookahead; + case '=': + return Tok_PosLookahead; +#endif + case ':': + return Tok_MagicLeftParen; + default: + yyError = TRUE; + return Tok_MagicLeftParen; + } + } else { + return Tok_LeftParen; + } + case ')': + return Tok_RightParen; + case '*': + yyMinRep = 0; + yyMaxRep = InftyRep; + return Tok_Quantifier; + case '+': + yyMinRep = 1; + yyMaxRep = InftyRep; + return Tok_Quantifier; + case '.': +#ifndef QT_NO_REGEXP_CCLASS + yyCharClass->setNegative( TRUE ); +#endif + return Tok_CharClass; + case '?': + yyMinRep = 0; + yyMaxRep = 1; + return Tok_Quantifier; + case '[': +#ifndef QT_NO_REGEXP_CCLASS + if ( yyCh == '^' ) { + yyCharClass->setNegative( TRUE ); + yyCh = getChar(); + } + charPending = FALSE; + rangePending = FALSE; + do { + if ( yyCh == '-' && charPending && !rangePending ) { + rangePending = TRUE; + yyCh = getChar(); + } else { + if ( charPending && !rangePending ) { + yyCharClass->addSingleton( pendingCh ); + charPending = FALSE; + } + if ( yyCh == '\\' ) { + yyCh = getChar(); + tok = getEscape(); + if ( tok == Tok_Word ) + tok = '\b'; + } else { + tok = Tok_Char | yyCh; + yyCh = getChar(); + } + if ( tok == Tok_CharClass ) { + if ( rangePending ) { + yyCharClass->addSingleton( '-' ); + yyCharClass->addSingleton( pendingCh ); + charPending = FALSE; + rangePending = FALSE; + } + } else if ( (tok & Tok_Char) != 0 ) { + if ( rangePending ) { + yyCharClass->addRange( pendingCh, tok ^ Tok_Char ); + charPending = FALSE; + rangePending = FALSE; + } else { + pendingCh = tok ^ Tok_Char; + charPending = TRUE; + } + } else { + yyError = TRUE; + } + } + } while ( yyCh != ']' && yyCh != EOS ); + if ( rangePending ) + yyCharClass->addSingleton( '-' ); + if ( charPending ) + yyCharClass->addSingleton( pendingCh ); + if ( yyCh == EOS ) + yyError = TRUE; + else + yyCh = getChar(); + return Tok_CharClass; +#else + yyError = TRUE; + return Tok_Char | '['; +#endif + case '\\': + return getEscape(); + case ']': + yyError = TRUE; + return Tok_Char | ']'; + case '^': + return Tok_Caret; +#ifndef QT_NO_REGEXP_INTERVAL + case '{': + yyMinRep = getRep( 0 ); + yyMaxRep = yyMinRep; + if ( yyCh == ',' ) { + yyCh = getChar(); + yyMaxRep = getRep( InftyRep ); + } + if ( yyMaxRep < yyMinRep ) + qSwap( yyMinRep, yyMaxRep ); + if ( yyCh != '}' ) + yyError = TRUE; + yyCh = getChar(); + return Tok_Quantifier; +#else + yyError = TRUE; + return Tok_Char | '{'; +#endif + case '|': + return Tok_Bar; + case '}': + yyError = TRUE; + return Tok_Char | '}'; + default: + return Tok_Char | prevCh; + } +} + +int QRegExpEngine::parse( const QChar *pattern, int len ) +{ + valid = TRUE; + startTokenizer( pattern, len ); + yyTok = getToken(); +#ifndef QT_NO_REGEXP_CAPTURE + yyMayCapture = TRUE; +#else + yyMayCapture = FALSE; +#endif + +#ifndef QT_NO_REGEXP_CAPTURE + int atom = startAtom( FALSE ); +#endif + CharClass anything; + Box box( this ); // create InitialState + box.set( anything ); + Box rightBox( this ); // create FinalState + rightBox.set( anything ); + + Box middleBox( this ); + parseExpression( &middleBox ); +#ifndef QT_NO_REGEXP_CAPTURE + finishAtom( atom ); +#endif +#ifndef QT_NO_REGEXP_OPTIM + middleBox.setupHeuristics(); +#endif + box.cat( middleBox ); + box.cat( rightBox ); + delete yyCharClass; + yyCharClass = 0; + + realncap = ncap; +#ifndef QT_NO_REGEXP_BACKREF + if ( nbrefs > ncap ) + ncap = nbrefs; +#endif + + mmCaptured.resize( 2 + 2 * realncap ); + mmCapturedNoMatch.fill( -1, 2 + 2 * realncap ); + + /* + We use one QArray for all the big data used a lot in matchHere() and + friends. + */ +#ifndef QT_NO_REGEXP_OPTIM + mmSlideTabSize = QMAX( minl + 1, 16 ); +#else + mmSlideTabSize = 0; +#endif + mmBigArray.resize( (3 + 4 * ncap) * ns + 4 * ncap + mmSlideTabSize ); + + mmInNextStack = mmBigArray.data(); + memset( mmInNextStack, -1, ns * sizeof(int) ); + mmCurStack = mmInNextStack + ns; + mmNextStack = mmInNextStack + 2 * ns; + + mmCurCapBegin = mmInNextStack + 3 * ns; + mmNextCapBegin = mmCurCapBegin + ncap * ns; + mmCurCapEnd = mmCurCapBegin + 2 * ncap * ns; + mmNextCapEnd = mmCurCapBegin + 3 * ncap * ns; + + mmTempCapBegin = mmCurCapBegin + 4 * ncap * ns; + mmTempCapEnd = mmTempCapBegin + ncap; + mmCapBegin = mmTempCapBegin + 2 * ncap; + mmCapEnd = mmTempCapBegin + 3 * ncap; + + mmSlideTab = mmTempCapBegin + 4 * ncap; + + if ( yyError ) + return -1; + +#ifndef QT_NO_REGEXP_OPTIM + State *sinit = s[InitialState]; + caretAnchored = ( sinit->anchors != 0 ); + if ( caretAnchored ) { + QMap& anchors = *sinit->anchors; + QMap::ConstIterator a; + for ( a = anchors.begin(); a != anchors.end(); ++a ) { +#ifndef QT_NO_REGEXP_ANCHOR_ALT + if ( (*a & Anchor_Alternation) != 0 ) + break; +#endif + if ( (*a & Anchor_Caret) == 0 ) { + caretAnchored = FALSE; + break; + } + } + } +#endif + return yyPos0; +} + +void QRegExpEngine::parseAtom( Box *box ) +{ +#ifndef QT_NO_REGEXP_LOOKAHEAD + QRegExpEngine *eng = 0; + bool neg; + int len; +#endif + + switch ( yyTok ) { + case Tok_Dollar: + box->catAnchor( Anchor_Dollar ); + break; + case Tok_Caret: + box->catAnchor( Anchor_Caret ); + break; +#ifndef QT_NO_REGEXP_LOOKAHEAD + case Tok_PosLookahead: + case Tok_NegLookahead: + neg = ( yyTok == Tok_NegLookahead ); + eng = new QRegExpEngine( cs ); + len = eng->parse( yyIn + yyPos - 1, yyLen - yyPos + 1 ); + if ( len >= 0 ) + skipChars( len ); + else + yyError = TRUE; + box->catAnchor( addLookahead(eng, neg) ); + yyTok = getToken(); + if ( yyTok != Tok_RightParen ) + yyError = TRUE; + break; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case Tok_Word: + box->catAnchor( Anchor_Word ); + break; + case Tok_NonWord: + box->catAnchor( Anchor_NonWord ); + break; +#endif + case Tok_LeftParen: + case Tok_MagicLeftParen: + yyTok = getToken(); + parseExpression( box ); + if ( yyTok != Tok_RightParen ) + yyError = TRUE; + break; + case Tok_CharClass: + box->set( *yyCharClass ); + break; + default: + if ( (yyTok & Tok_Char) != 0 ) + box->set( QChar(yyTok ^ Tok_Char) ); +#ifndef QT_NO_REGEXP_BACKREF + else if ( (yyTok & Tok_BackRef) != 0 ) + box->set( yyTok ^ Tok_BackRef ); +#endif + else + yyError = TRUE; + } + yyTok = getToken(); +} + +void QRegExpEngine::parseFactor( Box *box ) +{ +#ifndef QT_NO_REGEXP_CAPTURE + int atom = startAtom( yyMayCapture && yyTok == Tok_LeftParen ); +#else + static const int atom = 0; +#endif + +#ifndef QT_NO_REGEXP_INTERVAL +#define YYREDO() \ + yyIn = in, yyPos0 = pos0, yyPos = pos, yyLen = len, yyCh = ch, \ + *yyCharClass = charClass, yyMinRep = 0, yyMaxRep = 0, yyTok = tok + + const QChar *in = yyIn; + int pos0 = yyPos0; + int pos = yyPos; + int len = yyLen; + int ch = yyCh; + CharClass charClass; + if ( yyTok == Tok_CharClass ) + charClass = *yyCharClass; + int tok = yyTok; + bool mayCapture = yyMayCapture; +#endif + + parseAtom( box ); +#ifndef QT_NO_REGEXP_CAPTURE + finishAtom( atom ); +#endif + + if ( yyTok == Tok_Quantifier ) { + if ( yyMaxRep == InftyRep ) { + box->plus( atom ); +#ifndef QT_NO_REGEXP_INTERVAL + } else if ( yyMaxRep == 0 ) { + box->clear(); +#endif + } + if ( yyMinRep == 0 ) + box->opt(); + +#ifndef QT_NO_REGEXP_INTERVAL + yyMayCapture = FALSE; + int alpha = ( yyMinRep == 0 ) ? 0 : yyMinRep - 1; + int beta = ( yyMaxRep == InftyRep ) ? 0 : yyMaxRep - ( alpha + 1 ); + + Box rightBox( this ); + int i; + + for ( i = 0; i < beta; i++ ) { + YYREDO(); + Box leftBox( this ); + parseAtom( &leftBox ); + leftBox.cat( rightBox ); + leftBox.opt(); + rightBox = leftBox; + } + for ( i = 0; i < alpha; i++ ) { + YYREDO(); + Box leftBox( this ); + parseAtom( &leftBox ); + leftBox.cat( rightBox ); + rightBox = leftBox; + } + rightBox.cat( *box ); + *box = rightBox; +#endif + yyTok = getToken(); +#ifndef QT_NO_REGEXP_INTERVAL + yyMayCapture = mayCapture; +#endif + } +#undef YYREDO +} + +void QRegExpEngine::parseTerm( Box *box ) +{ +#ifndef QT_NO_REGEXP_OPTIM + if ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) + parseFactor( box ); +#endif + while ( yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar ) { + Box rightBox( this ); + parseFactor( &rightBox ); + box->cat( rightBox ); + } +} + +void QRegExpEngine::parseExpression( Box *box ) +{ + parseTerm( box ); + while ( yyTok == Tok_Bar ) { + Box rightBox( this ); + yyTok = getToken(); + parseTerm( &rightBox ); + box->orx( rightBox ); + } +} + +/* + The class QRegExpPrivate contains the private data of a regular expression + other than the automaton. It makes it possible for many QRegExp objects to + use the same QRegExpEngine object with different QRegExpPrivate objects. +*/ +struct QRegExpPrivate +{ + QString pattern; // regular-expression or wildcard pattern + QString rxpattern; // regular-expression pattern +#ifndef QT_NO_REGEXP_WILDCARD + bool wc; // wildcard mode? +#endif + bool min; // minimal matching? (instead of maximal) +#ifndef QT_NO_REGEXP_CAPTURE + QString t; // last string passed to QRegExp::search() or searchRev() + QStringList capturedCache; // what QRegExp::capturedTexts() returned last +#endif + QArray captured; // what QRegExpEngine::search() returned last + + QRegExpPrivate() { captured.fill( -1, 2 ); } +}; + +#ifndef QT_NO_REGEXP_OPTIM +static QCache *engineCache = 0; +#endif + +static QRegExpEngine *newEngine( const QString& pattern, bool caseSensitive ) +{ +#ifndef QT_NO_REGEXP_OPTIM + if ( engineCache != 0 ) { + QRegExpEngine *eng = engineCache->take( pattern ); + if ( eng == 0 || eng->caseSensitive() != caseSensitive ) { + delete eng; + } else { + eng->ref(); + return eng; + } + } +#endif + return new QRegExpEngine( pattern, caseSensitive ); +} + +static void derefEngine( QRegExpEngine *eng, const QString& pattern ) +{ + if ( eng != 0 && eng->deref() ) { +#ifndef QT_NO_REGEXP_OPTIM + if ( engineCache == 0 ) { + engineCache = new QCache; + engineCache->setAutoDelete( TRUE ); + } + if ( !pattern.isNull() && + engineCache->insert(pattern, eng, 4 + pattern.length() / 4) ) + return; +#else + Q_UNUSED( pattern ); +#endif + delete eng; + } +} + +/*! + Constructs an empty regexp. + + \sa isValid() +*/ +QRegExp3::QRegExp3() +{ + eng = new QRegExpEngine( TRUE ); + priv = new QRegExpPrivate; + priv->pattern = QString::null; +#ifndef QT_NO_REGEXP_WILDCARD + priv->wc = FALSE; +#endif + priv->min = FALSE; + compile( TRUE ); +} + +/*! + Constructs a regular expression object for the given \a pattern + string. The pattern must be given using wildcard notation if \a + wildcard is TRUE (default is FALSE). The pattern is case sensitive, + unless \a caseSensitive is FALSE. Matching is greedy (maximal), but + can be changed by calling setMinimal(). + + \sa setPattern() setCaseSensitive() setWildcard() setMinimal() +*/ +QRegExp3::QRegExp3( const QString& pattern, bool caseSensitive, bool wildcard ) +{ + eng = 0; + priv = new QRegExpPrivate; + priv->pattern = pattern; +#ifndef QT_NO_REGEXP_WILDCARD + priv->wc = wildcard; +#endif + priv->min = FALSE; + compile( caseSensitive ); +} + +/*! + Constructs a regular expression as a copy of \a rx. + + \sa operator=() +*/ +QRegExp3::QRegExp3( const QRegExp3& rx ) +{ + eng = 0; + priv = new QRegExpPrivate; + operator=( rx ); +} + +/*! + Destroys the regular expression and cleans up its internal data. +*/ +QRegExp3::~QRegExp3() +{ + derefEngine( eng, priv->rxpattern ); + delete priv; +} + +/*! + Copies the regular expression \a rx and returns a reference to the copy. + The case sensitivity, wildcard and minimal matching options are copied as + well. +*/ +QRegExp3& QRegExp3::operator=( const QRegExp3& rx ) +{ + rx.eng->ref(); + derefEngine( eng, priv->rxpattern ); + eng = rx.eng; + priv->pattern = rx.priv->pattern; + priv->rxpattern = rx.priv->rxpattern; +#ifndef QT_NO_REGEXP_WILDCARD + priv->wc = rx.priv->wc; +#endif + priv->min = rx.priv->min; +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = rx.priv->t; + priv->capturedCache = rx.priv->capturedCache; +#endif + priv->captured = rx.priv->captured; + return *this; +} + +/*! + Returns TRUE if this regular expression is equal to \a rx, otherwise + returns FALSE. + + Two QRegExp3 objects are equal if they have the same pattern strings + and the same settings for case sensitivity, wildcard and minimal + matching. +*/ +bool QRegExp3::operator==( const QRegExp3& rx ) const +{ + return priv->pattern == rx.priv->pattern && + eng->caseSensitive() == rx.eng->caseSensitive() && +#ifndef QT_NO_REGEXP_WILDCARD + priv->wc == rx.priv->wc && +#endif + priv->min == rx.priv->min; +} + +/*! \fn bool QRegExp3::operator!=( const QRegExp& rx ) const + + Returns TRUE if this regular expression is not equal to \a rx, otherwise + FALSE. + + \sa operator==() +*/ + +/*! + Returns TRUE if the pattern string is empty, otherwise FALSE. + + If you call match() with an empty pattern on an empty string it will + return TRUE otherwise it returns FALSE since match() operates over the + whole string. If you call search() with an empty pattern on \e any + string it will return the start position (0 by default) since it will + match at the start position, because the empty pattern matches the + 'emptiness' at the start of the string, and the length of the match + returned by matchedLength() will be 0. + + See QString::isEmpty(). +*/ + +bool QRegExp3::isEmpty() const +{ + return priv->pattern.isEmpty(); +} + +/*! + Returns TRUE if the regular expression is valid, or FALSE if it's invalid. An + invalid regular expression never matches. + + The pattern [a-z is an example of an invalid pattern, since it lacks + a closing square bracket. + + Note that the validity of a regexp may also depend on the setting of + the wildcard flag, for example *.html is a valid wildcard + regexp but an invalid full regexp. +*/ +bool QRegExp3::isValid() const +{ + return eng->isValid(); +} + +/*! + Returns the pattern string of the regular expression. The pattern has either + regular expression syntax or wildcard syntax, depending on wildcard(). + + \sa setPattern() +*/ +QString QRegExp3::pattern() const +{ + return priv->pattern; +} + +/*! + Sets the pattern string to \a pattern and returns a reference to this regular + expression. The case sensitivity, wildcard and minimal matching options are + not changed. + + \sa pattern() +*/ +void QRegExp3::setPattern( const QString& pattern ) +{ + if ( priv->pattern != pattern ) { + priv->pattern = pattern; + compile( caseSensitive() ); + } +} + +/*! + Returns TRUE if case sensitivity is enabled, otherwise FALSE. The default is + TRUE. + + \sa setCaseSensitive() +*/ +bool QRegExp3::caseSensitive() const +{ + return eng->caseSensitive(); +} + +/*! + Sets case sensitive matching to \a sensitive. + + If \a sensitive is TRUE, \\.txt$ matches + readme.txt but not README.TXT. + + \sa caseSensitive() +*/ +void QRegExp3::setCaseSensitive( bool sensitive ) +{ + if ( sensitive != eng->caseSensitive() ) + compile( sensitive ); +} + +#ifndef QT_NO_REGEXP_WILDCARD +/*! + Returns TRUE if wildcard mode is enabled, otherwise FALSE. The default is + FALSE. + + \sa setWildcard() +*/ +bool QRegExp3::wildcard() const +{ + return priv->wc; +} + +/*! Sets the wildcard mode for the regular expression. The default is FALSE. + + Setting \a wildcard to TRUE enables simple shell-like wildcard + matching. + (See wildcard matching (globbing).) + + For example, r*.txt matches the string readme.txt in wildcard + mode, but does not match readme. + + \sa wildcard() +*/ +void QRegExp3::setWildcard( bool wildcard ) +{ + if ( wildcard != priv->wc ) { + priv->wc = wildcard; + compile( caseSensitive() ); + } +} +#endif + +/*! Returns TRUE if minimal (non-greedy) matching is enabled, otherwise + returns FALSE. + + \sa setMinimal() +*/ +bool QRegExp3::minimal() const +{ + return priv->min; +} + +/*! + Enables or disables minimal matching. If \a minimal is FALSE, matching is + greedy (maximal) which is the default. + + For example, suppose we have the input string "We must be \bold\, + very \bold\!" and the pattern \.*\. With + the default greedy (maximal) matching, the match is + "We must be \bold\, very \bold\!". But with + minimal (non-greedy) matching the first match is: + "We must be \bold\, very \bold\!" and the + second match is + "We must be \bold\, very \bold\!". + In practice we might use the pattern \[^\<]+\, + although this will still fail for nested tags. + + \sa minimal() +*/ +void QRegExp3::setMinimal( bool minimal ) +{ + priv->min = minimal; +} + +/*! + Returns TRUE if \a str is matched exactly by this regular expression + otherwise it returns FALSE. You can determine how much of the string was + matched by calling matchedLength(). + + For a given regexp string, R, match("R") is the equivalent + of search("^R$") since match() effectively encloses the + regexp in the start of string and end of string anchors. + + For example, if the regular expression is blue, then match() + returns TRUE only for input blue. For inputs + bluebell, blutak and lightblue, match() + returns FALSE and matchedLength() will return 4, 3 and 0 respectively. + + \sa search() searchRev() QRegExpValidator +*/ +bool QRegExp3::exactMatch( const QString& str ) +{ +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = str; + priv->capturedCache.clear(); +#endif + + priv->captured = eng->match( str, 0, priv->min, TRUE ); + if ( priv->captured[1] == (int) str.length() ) { + return TRUE; + } else { + priv->captured.detach(); + priv->captured[0] = 0; + priv->captured[1] = eng->matchedLength(); + return FALSE; + } +} + +/*! \overload + + This version does not set matchedLength(), capturedTexts() and friends. +*/ +bool QRegExp3::exactMatch( const QString& str ) const +{ + return eng->match(str, 0, priv->min, TRUE)[0] == 0 && + eng->matchedLength() == (int) str.length(); +} + +/*! \obsolete + + Attempts to match in \a str, starting from position \a index. Returns the + position of the match, or -1 if there was no match. + + The length of the match is stored in \a *len, unless \a len is a null pointer. + + If \a indexIsStart is TRUE (the default), the position \a index in the string + will match the start of string anchor, ^, in the regexp, if present. + Otherwise, position 0 in \a str will match. + + Use search() and matchedLength() instead of this function. + + If you really need the \a indexIsStart functionality, try this: + + \code + QRegExp3 rx( "some pattern" ); + int pos = rx.search( str.mid( index ) ); + if ( pos != -1 ) + pos += index; + int len = rx.matchedLength(); + \endcode +*/ +#ifndef QT_NO_COMPAT +int QRegExp3::match( const QString& str, int index, int *len, + bool indexIsStart ) +{ + int pos; + if ( indexIsStart ) { + pos = search( str.mid(index) ); + if ( pos >= 0 ) { + pos += index; + if ( len != 0 ) + *len = matchedLength(); + } else { + if ( len != 0 ) + *len = 0; + } + } else { + pos = search( str, index ); + if ( len != 0 ) + *len = matchedLength(); + } + return pos; +} +#endif + +/*! + Attempts to find a match in \a str from position \a start (0 by default). If + \a start is -1, the search starts at the last character; if -2, at the next to + last character; etc. + + Returns the position of the first match, or -1 if there was no match. + + You might prefer to use QString::find(), QString::contains() or even + QStringList::grep(). To replace matches use QString::replace(). + + Example: + \code + QString str = "offsets: 1.23 .50 71.00 6.00"; + QRegExp3 rx( "\\d*\\.\\d+" ); // very simple floating point matching + int count = 0; + int pos = 0; + while ( pos >= 0 ) { + pos = rx.search( str, pos ); + count++; + } + // pos will be 9, 14, 18 and finally 24; count will end up as 4. + \endcode + + \sa searchRev() match() matchedLength() capturedTexts() +*/ +// QChar versions + +#ifdef QCHAR_SUPPORT +const QString makeString(const QChar *str) +{ +// A sentinel value checked in case the QChar *ptr is never null terminated + const uint MAXLENGTH=65535; + + const QChar *s=str; + uint i=0; + while(i < MAXLENGTH && *s != QChar::null) { i++;s++ ;} + return QString(str,i); + +} +int QRegExp3::search(const QChar *str,int start) +{ + return search(makeString(str),start); +} +int QRegExp3::search(const QChar *str,int start) const +{ + return search(makeString(str),start); +} +int QRegExp3::searchRev(const QChar *str,int start) +{ + return searchRev(makeString(str),start); +} +int QRegExp3::searchRev(const QChar *str,int start) const +{ + return searchRev(makeString(str),start); +} +bool QRegExp3::exactMatch(const QChar *str) +{ + return exactMatch(makeString(str)); +} +bool QRegExp3::exactMatch(const QChar *str) const +{ + return exactMatch(makeString(str)); +} +#endif // QCHAR_SUPPORT + +int QRegExp3::search( const QString& str, int start ) +{ + if ( start < 0 ) + start += str.length(); +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = str; + priv->capturedCache.clear(); +#endif + priv->captured = eng->match( str, start, priv->min, FALSE ); + return priv->captured[0]; +} + +/*! \overload + + This version does not set matchedLength(), capturedTexts() and friends. +*/ +int QRegExp3::search( const QString& str, int start ) const +{ + if ( start < 0 ) + start += str.length(); + return eng->match( str, start, priv->min, FALSE )[0]; +} + +/*! + Attempts to find a match backwards in \a str from position \a start. If + \a start is -1 (the default), the search starts at the last character; if -2, + at the next to last character; etc. + + Returns the position of the first match, or -1 if there was no match. + + You might prefer to use QString::findRev(). + + \sa search() matchedLength() capturedTexts() +*/ +int QRegExp3::searchRev( const QString& str, int start ) +{ + if ( start < 0 ) + start += str.length(); +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = str; + priv->capturedCache.clear(); +#endif + if ( start < 0 || start > (int) str.length() ) { + priv->captured.detach(); + priv->captured.fill( -1 ); + return -1; + } + + while ( start >= 0 ) { + priv->captured = eng->match( str, start, priv->min, TRUE ); + if ( priv->captured[0] == start ) + return start; + start--; + } + return -1; +} + +/*! \overload + + This version does not set matchedLength(), capturedText() and friends. +*/ +int QRegExp3::searchRev( const QString& str, int start ) const +{ + if ( start < 0 ) + start += str.length(); + if ( start < 0 || start > (int) str.length() ) + return -1; + + while ( start >= 0 ) { + if ( eng->match(str, start, priv->min, TRUE)[0] == start ) + return start; + start--; + } + return -1; +} + +/*! + Returns the length of the last matched string, or -1 if there was no match. + + \sa match() search() +*/ +int QRegExp3::matchedLength() +{ + return priv->captured[1]; +} + +#ifndef QT_NO_REGEXP_CAPTURE +/*! + Returns a list of the captured text strings. + + The first string in the list is the entire matched string. Each + subsequent list element contains a string that matched a + (capturing) subexpression of the regexp. + + For example: + \code + QRegExp3 rx( "(\\d+)(\\s*)(cm|inch(es)?)" ); + int pos = rx.search( "Length: 36 inches" ); + QStringList list = rx.capturedTexts(); + // list is now ( "36 inches", "36", " ", "inches", "es" ). + \endcode + + The above example also captures elements + that may be present but which we have no interest in. This problem + can be solved by using non-capturing parenthesis: + + \code + QRegExp3 rx( "(\\d+)(?:\\s*)(cm|inch(?:es)?)" ); + int pos = rx.search( "Length: 36 inches" ); + QStringList list = rx.capturedTexts(); + // list is now ( "36 inches", "36", "inches" ). + \endcode + + Some regexps can match an indeterminate number of times. For example + if the input string is "Offsets: 12 14 99 231 7" and the regexp, + rx, is (\\d+)+, we would hope to get a + list of all the numbers matched. However, after calling + rx.search(str), capturedTexts() will return the list ( "12", + "12" ), i.e. the entire match was "12" and the first subexpression + matched was "12". The correct approach is to use cap() in a + loop. + + The order of elements in the string list is as follows. The first + element is the entire matching string. Each subsequent element + corresponds to the next capturing open left parenthesis. Thus + capturedTexts()[1] is the text of the first capturing parenthesis, + capturedTexts()[2] is the text of the second and so on (corresponding + to $1, $2 etc. in some other regexp languages). + + \sa cap() pos() +*/ +QStringList QRegExp3::capturedTexts() +{ + if ( priv->capturedCache.isEmpty() ) { + for ( int i = 0; i < (int) priv->captured.size(); i += 2 ) { + QString m; + if ( priv->captured[i + 1] == 0 ) + m = QString::fromLatin1( "" ); + else if ( priv->captured[i] >= 0 ) + m = priv->t.mid( priv->captured[i], + priv->captured[i + 1] ); + priv->capturedCache.append( m ); + } + priv->t = QString::null; + } + return priv->capturedCache; +} + +/*! Returns the text captured by the \a nth subexpression. The entire match + has index 0 and the parenthesised subexpressions have indices starting + from 1 (excluding non-capturing parenthesis). + + \code + QRegExp3 rxlen( "(\\d+)(?:\\s*)(cm|inch)" ); + int pos = rxlen.search( "Length: 189cm" ); + if ( pos > -1 ) { + QString value = rxlen.cap( 1 ); // "189" + QString unit = rxlen.cap( 2 ); // "cm" + // ... + } + \endcode + + + Some patterns may lead to a number of matches which cannot be + determined in advance, for example: + + \code + QRegExp3 rx( "(\\d+)" ); + str = "Offsets: 12 14 99 231 7"; + QStringList list; + pos = 0; + while ( pos >= 0 ) { + pos = rx.search( str, pos ); + if ( pos > -1 ) { + list += rx.cap( 1 ); + pos += rx.matchedLength(); + } + } + // list contains: ( "12", "14", "99", "231", "7" ). + \endcode + + The order of elements matched by cap() is as follows. The first + element, cap( 0 ), is the entire matching string. Each subsequent + element corresponds to the next capturing open left parenthesis. Thus + cap( 1 ) is the text of the first capturing parenthesis, cap( 2 ) is + the text of the second and so on. + + \sa search() pos() capturedTexts() +*/ +QString QRegExp3::cap( int nth ) +{ + if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) + return QString::null; + else + return capturedTexts()[nth]; +} + +/*! Returns the position of the \a nth captured text in the + searched string. If \a nth is 0 (the default), pos() returns the + position of the whole match. + + Example: + \code + QRegExp3 rx( "/([a-z]+)/([a-z]+)" ); + rx.search( "Output /dev/null" ); // Returns 7 (position of /dev/null) + rx.pos( 0 ); // Returns 7 (position of /dev/null) + rx.pos( 1 ); // Returns 8 (position of dev) + rx.pos( 2 ); // Returns 12 (position of null) + \endcode + + Note that pos() returns -1 for zero-length matches. (For example, if + cap(4) would return an empty string, pos(4) returns -1.) This is due + to an implementation tradeoff. + + \sa capturedTexts() cap() +*/ +int QRegExp3::pos( int nth ) +{ + if ( nth < 0 || nth >= (int) priv->captured.size() / 2 ) + return -1; + else + return priv->captured[2 * nth]; +} +#endif + +void QRegExp3::compile( bool caseSensitive ) +{ + derefEngine( eng, priv->rxpattern ); +#ifndef QT_NO_REGEXP_WILDCARD + if ( priv->wc ) + priv->rxpattern = wc2rx( priv->pattern ); + else +#endif + priv->rxpattern = priv->pattern.isNull() ? QString::fromLatin1( "" ) + : priv->pattern; + eng = newEngine( priv->rxpattern, caseSensitive ); +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = QString::null; + priv->capturedCache.clear(); +#endif + priv->captured.detach(); + priv->captured.fill( -1, 2 + 2 * eng->numCaptures() ); +} 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 @@ +/**************************************************************************** +** $Id$ +** +** Definition of QRegExp class +** +** Created : 950126 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses may use this file in accordance with the Qt Commercial License +** Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef QREGEXP3_H +#define QREGEXP3_H +#ifndef QT_H +#include "qstringlist.h" +#endif // QT_H + + +#if QT_VERSION >=300 +#include +#else +class QRegExpEngine; +struct QRegExpPrivate; + +class Q_EXPORT QRegExp3 +{ +public: + QRegExp3(); + QRegExp3( const QString& pattern, bool caseSensitive = TRUE, + bool wildcard = FALSE ); + QRegExp3( const QRegExp3& rx ); + ~QRegExp3(); + QRegExp3& operator=( const QRegExp3& rx ); + + bool operator==( const QRegExp3& rx ) const; + bool operator!=( const QRegExp3& rx ) const { return !operator==( rx ); } + + bool isEmpty() const; + bool isValid() const; + QString pattern() const; + void setPattern( const QString& pattern ); + bool caseSensitive() const; + void setCaseSensitive( bool sensitive ); +#ifndef QT_NO_REGEXP_WILDCARD + bool wildcard() const; + void setWildcard( bool wildcard ); +#endif + bool minimal() const; + void setMinimal( bool minimal ); + + bool exactMatch( const QString& str ); + bool exactMatch( const QString& str ) const; +#ifndef QT_NO_COMPAT + int match( const QString& str, int index, int *len = 0, + bool indexIsStart = TRUE ); +#endif + int search( const QString& str, int start = 0 ); + int search( const QString& str, int start = 0 ) const; +// QChar versions +#ifdef QCHAR_SUPPORT + int search(const QChar *str,int start=0); + int search(const QChar *str,int start=0) const; + int searchRev(const QChar *str,int start=-1); + int searchRev(const QChar *str,int start=-1) const ; + bool exactMatch(const QChar *str); + bool exactMatch(const QChar *str) const; +// end QChar versions +#endif + int searchRev( const QString& str, int start = -1 ); + int searchRev( const QString& str, int start = -1 ) const; + int matchedLength(); +#ifndef QT_NO_REGEXP_CAPTURE + QStringList capturedTexts(); + QString cap( int nth = 0 ); + int pos( int nth = 0 ); +#endif + +private: + void compile( bool caseSensitive ); + + QRegExpEngine *eng; + QRegExpPrivate *priv; +}; +#endif // QT_VERSION >= 300 +#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 @@ +/* + Copyright (C) 1999 Glen Parker + Copyright (C) 2002 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + -------------------------------------------------------------------- + + This implements a dialog used to display and control undo/redo history. + It uses a specialized QListBox subclass to provide a selection mechanism + that must: + 1) always have the first item selected, and + 2) maintain a contiguous multiple selection +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "kateview.h" + +#include "kateundohistory.h" + +///////////////////////////////////////////////////////////////////// +// UndoHistory implementation +// +UndoHistory::UndoHistory(KateView *kWrite, QWidget *parent, const char *name, bool modal, WFlags f) + : QDialog(parent, name, modal, f) +{ + this->kWrite = kWrite; + + QPushButton *btn; + QLabel *lbl; + QHBoxLayout *hLayout; + QVBoxLayout *vLayout; + + hLayout = new QHBoxLayout(this, 5, 4); + + vLayout = new QVBoxLayout(hLayout); + lbl = new QLabel(i18n("Undo List"), this); + lbUndo = new UndoListBox(this); + vLayout->addWidget(lbl); + vLayout->addWidget(lbUndo); + + vLayout = new QVBoxLayout(hLayout); + lbl = new QLabel(i18n("Redo List"), this); + lbRedo = new UndoListBox(this); + vLayout->addWidget(lbl); + vLayout->addWidget(lbRedo); + + lbUndo->setMinimumSize(QSize(150,140)); + lbRedo->setMinimumSize(QSize(150,140)); + + connect(lbUndo, SIGNAL(sigSelected(int)), this, SLOT(slotUndoSelChanged(int))); + connect(lbRedo, SIGNAL(sigSelected(int)), this, SLOT(slotRedoSelChanged(int))); + + vLayout = new QVBoxLayout(hLayout); + + btnUndo = new QPushButton(this); + btnUndo->setText(i18n("&Undo")); + btnUndo->setEnabled(false); + btnUndo->setFixedSize(btnUndo->sizeHint()); + connect(btnUndo, SIGNAL(clicked()), this, SLOT(slotUndo())); + + vLayout->addWidget(btnUndo, 0); + + btnRedo = new QPushButton(this); + btnRedo->setText(i18n("&Redo")); + btnRedo->setEnabled(false); + btnRedo->setFixedSize(btnRedo->sizeHint()); + connect(btnRedo, SIGNAL(clicked()), this, SLOT(slotRedo())); + + vLayout->addWidget(btnRedo, 0); + + btn = new QPushButton(this); + btn->setText(i18n("&Close")); + btn->setFixedSize(btn->sizeHint()); + connect(btn, SIGNAL(clicked()), this, SLOT(close())); + + vLayout->addWidget(btn, 0, AlignBottom); + + newUndo(); +} + +UndoHistory::~UndoHistory() +{} + +void UndoHistory::newUndo() +{ + QValueList undoList; + QValueList::Iterator it; + + // we don't want a signal storm... + disconnect(lbUndo, SIGNAL(sigSelected(int)), this, SLOT(slotUndoSelChanged(int))); + disconnect(lbRedo, SIGNAL(sigSelected(int)), this, SLOT(slotRedoSelChanged(int))); + + kWrite->undoTypeList(undoList); + + lbUndo->clear(); + + for (it = undoList.begin() ; it != undoList.end() ; it++) { + lbUndo->insertItem(i18n(kWrite->undoTypeName(*it))); + } + + kWrite->redoTypeList(undoList); + + lbRedo->clear(); + for (it = undoList.begin() ; it != undoList.end() ; it++) { + lbRedo->insertItem(i18n(kWrite->undoTypeName(*it))); + } + + connect(lbUndo, SIGNAL(sigSelected(int)), this, SLOT(slotUndoSelChanged(int))); + connect(lbRedo, SIGNAL(sigSelected(int)), this, SLOT(slotRedoSelChanged(int))); + + slotUndoSelChanged(lbUndo->selCount()); + slotRedoSelChanged(lbRedo->selCount()); +} + +void UndoHistory::slotUndo() +{ + int selCount = lbUndo->selCount(); + emit undo(selCount); + lbRedo->setSelCount(selCount); +} +void UndoHistory::slotRedo() +{ + int selCount = lbRedo->selCount(); + emit redo(selCount); + lbUndo->setSelCount(selCount); +} + +void UndoHistory::slotUndoSelChanged(int cnt) +{ + btnUndo->setEnabled(cnt > 0); +} + +void UndoHistory::slotRedoSelChanged(int cnt) +{ + btnRedo->setEnabled(cnt > 0); +} + +///////////////////////////////////////////////////////////////////// +// UndoListBox implementation +// +UndoListBox::UndoListBox(QWidget *parent, const char *name, WFlags f) + : QListBox(parent, name, f) +{ + _selCount = 0; + setSelectionMode(Extended); + connect(this, SIGNAL(highlighted(int)), this, SLOT(_slotSelectionChanged())); + connect(this, SIGNAL(selectionChanged()), this, SLOT(_slotSelectionChanged())); +} + +UndoListBox::~UndoListBox() +{} + +void UndoListBox::insertItem (const QString &text, int index) +{ + bool sig = false; + + if (count() == 0) + sig = true; + else if (index > -1) + sig = (isSelected(index)); + + QListBox::insertItem(text, index); + + if (sig) + _slotSelectionChanged(); +} + +void UndoListBox::removeItem (int index) +{ + bool sig; + + if (count() == 1) + sig = true; + else if (index == -1) + sig = (isSelected(count() - 1)); + else + sig = (isSelected(index)); + + QListBox::removeItem(index); + + if (sig) + _slotSelectionChanged(); +} + +void UndoListBox::clear() +{ + bool sig = (count() > 0); + + QListBox::clear(); + + if (sig) + _slotSelectionChanged(); +} + +int UndoListBox::selCount() +{ + return _selCount; +} + +void UndoListBox::setSelCount(int count) +{ + if (count == _selCount) + return; + + if (count < 1 || count > (int)this->count()) + return; + + setCurrentItem(count - 1); +} + +// make sure the first item is selected, and that there are no holes +void UndoListBox::_slotSelectionChanged() +{ + int count = this->count(); + + if (! count) { + if (_selCount != 0) { + _selCount = 0; + emit sigSelected(_selCount); + } + return; + } + + if (currentItem() < 0) + setCurrentItem(0); + + int i; + int currItem = currentItem(); + int max = (currItem+1 > _selCount ? currItem+1 : _selCount); + + for (i = 0 ; i < max ; i++) { + if (i > currItem) { + if (isSelected(i)) { + setSelected(i, false); + } + } else { + if (! isSelected(i)) { + setSelected(i, true); + } + } + } + + if (_selCount != currItem + 1) { + _selCount = currItem + 1; + emit sigSelected(_selCount); + } +} 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 @@ +/* + Copyright (C) 1999 Glen Parker + Copyright (C) 2002 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + -------------------------------------------------------------------- + + This implements a dialog used to display and control undo/redo history. + It uses a specialized QListBox subclass to provide a selection mechanism + that will: + 1) always have the first item selected, and + 2) maintain a contiguous multiple selection +*/ + +#ifndef __undohistory_h_ +#define __undohistory_h_ + +#include +#include + +#include "kateview.h" + +class UndoListBox; + +// the dialog class that provides the interface to the user +class UndoHistory : public QDialog +{ + Q_OBJECT + + public: + /** + Constructed just like a regular QDialog + */ + UndoHistory(KateView*, QWidget *parent=0, const char *name=0, bool modal=FALSE, WFlags f=0); + virtual ~UndoHistory(); + + public slots: + /** + This should be called whenever a change occurs in the undo/redo list. + Causes the dialog to update its interface. + */ + void newUndo(); + + signals: + /** + Emitted when the user hits the Undo button. Specifies the number of + operations to undo. + */ + void undo(int); + /** + Emitted when the user hits the Redo button. Specifies the number of + undone operations to redo. + */ + void redo(int); + + protected: + KateView *kWrite; + + UndoListBox *lbUndo, + *lbRedo; + QPushButton *btnUndo, + *btnRedo; + + protected slots: + void slotUndo(); + void slotRedo(); + void slotUndoSelChanged(int); + void slotRedoSelChanged(int); + +}; + +// listbox class used to provide contiguous, 0-based selection +// this is used internally +class UndoListBox : public QListBox +{ + Q_OBJECT + + public: + UndoListBox(QWidget * parent=0, const char * name=0, WFlags f=0); + virtual ~UndoListBox(); + + int selCount(); + void setSelCount(int count); + + void insertItem (const QString &text, int index = -1); + void removeItem (int index); + void clear(); + + protected: + int _selCount; + + signals: + void sigSelected(int); + + protected slots: + void _slotSelectionChanged(); + +}; + +#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 @@ +/*************************************************************************** + kateview.cpp - description + ------------------- + begin : Mon Jan 15 2001 + copyright : (C) 2001 by Christoph "Crossfire" Cullmann + (C) 2002 by Joseph Wenninger + email : crossfire@babylon2k.de + jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* + Copyright (C) 1998, 1999 Jochen Wilhelmy + digisnap@cs.tu-berlin.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + + +#include "kateview.h" + +#include "../document/katedocument.h" +#include "../document/katecmd.h" +#include "../document/katehighlight.h" +#include "kateviewdialog.h" +#include "../document/katedialogs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../document/katetextline.h" +#include "kateviewdialog.h" +#include "kateundohistory.h" +#include + +KateViewInternal::KateViewInternal(KateView *view, KateDocument *doc) : QWidget(view) +{ + waitForPreHighlight=-1; + myView = view; + myDoc = doc; + + iconBorderWidth = 16; + iconBorderHeight = 800; + + QWidget::setCursor(ibeamCursor); + setBackgroundMode(NoBackground); + + setFocusPolicy(StrongFocus); + + xScroll = new QScrollBar(QScrollBar::Horizontal,myView); + yScroll = new QScrollBar(QScrollBar::Vertical,myView); + connect(xScroll,SIGNAL(valueChanged(int)),SLOT(changeXPos(int))); + connect(yScroll,SIGNAL(valueChanged(int)),SLOT(changeYPos(int))); + connect(yScroll,SIGNAL(valueChanged(int)),myView,SIGNAL(scrollValueChanged(int))); + connect( doc, SIGNAL (preHighlightChanged(long)),this,SLOT(slotPreHighlightUpdate(long))); + + xPos = 0; + yPos = 0; + + scrollTimer = 0; + + cursor.x = 0; + cursor.y = 0; + cursorOn = false; + cursorTimer = 0; + cXPos = 0; + cOldXPos = 0; + + startLine = 0; + endLine = -1; + + exposeCursor = false; + updateState = 0; + numLines = 0; + lineRanges = 0L; + newXPos = -1; + newYPos = -1; + + drawBuffer = new QPixmap (); + drawBuffer->setOptimization (QPixmap::BestOptim); + + bm.sXPos = 0; + bm.eXPos = -1; + +} + + +KateViewInternal::~KateViewInternal() +{ + delete [] lineRanges; + delete drawBuffer; +} + + +void KateViewInternal::slotPreHighlightUpdate(long line) +{ + //kdDebug()<=waitForPreHighlight) + { + waitForPreHighlight=-1; + repaint(); + } + } +} + +void KateViewInternal::doCursorCommand(VConfig &c, int cmdNum) { + + switch (cmdNum) { + case KateView::cmLeft: + cursorLeft(c); + break; + case KateView::cmRight: + cursorRight(c); + break; + case KateView::cmWordLeft: + wordLeft(c); + break; + case KateView::cmWordRight: + wordRight(c); + break; + case KateView::cmHome: + home(c); + break; + case KateView::cmEnd: + end(c); + break; + case KateView::cmUp: + cursorUp(c); + break; + case KateView::cmDown: + cursorDown(c); + break; + case KateView::cmScrollUp: + scrollUp(c); + break; + case KateView::cmScrollDown: + scrollDown(c); + break; + case KateView::cmTopOfView: + topOfView(c); + break; + case KateView::cmBottomOfView: + bottomOfView(c); + break; + case KateView::cmPageUp: + pageUp(c); + break; + case KateView::cmPageDown: + pageDown(c); + break; + case KateView::cmTop: + top_home(c); + break; + case KateView::cmBottom: + bottom_end(c); + break; + } +} + +void KateViewInternal::doEditCommand(VConfig &c, int cmdNum) { + + switch (cmdNum) { + case KateView::cmCopy: + myDoc->copy(c.flags); + return; + case KateView::cmSelectAll: + myDoc->selectAll(); + return; + case KateView::cmDeselectAll: + myDoc->deselectAll(); + return; + case KateView::cmInvertSelection: + myDoc->invertSelection(); + return; + } + if (myView->isReadOnly()) return; + switch (cmdNum) { + case KateView::cmReturn: + if (c.flags & KateView::cfDelOnInput) myDoc->delMarkedText(c); + myDoc->newLine(c); + //emit returnPressed(); + //e->ignore(); + return; + case KateView::cmDelete: + if ((c.flags & KateView::cfDelOnInput) && myDoc->hasMarkedText()) + myDoc->delMarkedText(c); + else myDoc->del(c); + return; + case KateView::cmBackspace: + if ((c.flags & KateView::cfDelOnInput) && myDoc->hasMarkedText()) + myDoc->delMarkedText(c); + else myDoc->backspace(c); + return; + case KateView::cmKillLine: + myDoc->killLine(c); + return; + case KateView::cmCut: + myDoc->cut(c); + return; + case KateView::cmPaste: + if (c.flags & KateView::cfDelOnInput) myDoc->delMarkedText(c); + myDoc->paste(c); + return; + case KateView::cmUndo: + myDoc->undo(c); + return; + case KateView::cmRedo: + myDoc->redo(c); + return; + case KateView::cmIndent: + myDoc->indent(c); + return; + case KateView::cmUnindent: + myDoc->unIndent(c); + return; + case KateView::cmCleanIndent: + myDoc->cleanIndent(c); + return; + case KateView::cmComment: + myDoc->comment(c); + return; + case KateView::cmUncomment: + myDoc->unComment(c); + return; + } +} + +void KateViewInternal::cursorLeft(VConfig &c) { + + cursor.x--; + if (c.flags & KateView::cfWrapCursor && cursor.x < 0 && cursor.y > 0) { + cursor.y--; + cursor.x = myDoc->textLength(cursor.y); + } + cOldXPos = cXPos = myDoc->textWidth(cursor); + changeState(c); +} + +void KateViewInternal::cursorRight(VConfig &c) { + + if (c.flags & KateView::cfWrapCursor) { + if (cursor.x >= myDoc->textLength(cursor.y)) { + if (cursor.y == myDoc->lastLine()) return; + cursor.y++; + cursor.x = -1; + } + } + cursor.x++; + cOldXPos = cXPos = myDoc->textWidth(cursor); + changeState(c); +} + +void KateViewInternal::wordLeft(VConfig &c) { + Highlight *highlight; + + highlight = myDoc->highlight(); + TextLine::Ptr textLine = myDoc->getTextLine(cursor.y); + + if (cursor.x > 0) { + do { + cursor.x--; + } while (cursor.x > 0 && !highlight->isInWord(textLine->getChar(cursor.x))); + while (cursor.x > 0 && highlight->isInWord(textLine->getChar(cursor.x -1))) + cursor.x--; + } else { + if (cursor.y > 0) { + cursor.y--; + textLine = myDoc->getTextLine(cursor.y); + cursor.x = textLine->length(); + } + } + + cOldXPos = cXPos = myDoc->textWidth(cursor); + changeState(c); +} + +void KateViewInternal::wordRight(VConfig &c) { + Highlight *highlight; + int len; + + highlight = myDoc->highlight(); + TextLine::Ptr textLine = myDoc->getTextLine(cursor.y); + len = textLine->length(); + + if (cursor.x < len) { + do { + cursor.x++; + } while (cursor.x < len && highlight->isInWord(textLine->getChar(cursor.x))); + while (cursor.x < len && !highlight->isInWord(textLine->getChar(cursor.x))) + cursor.x++; + } else { + if (cursor.y < myDoc->lastLine()) { + cursor.y++; + textLine = myDoc->getTextLine(cursor.y); + cursor.x = 0; + } + } + + cOldXPos = cXPos = myDoc->textWidth(cursor); + changeState(c); +} + +void KateViewInternal::home(VConfig &c) { + int lc; + + lc = (c.flags & KateView::cfSmartHome) ? myDoc->getTextLine(cursor.y)->firstChar() : 0; + if (lc <= 0 || cursor.x == lc) { + cursor.x = 0; + cOldXPos = cXPos = 0; + } else { + cursor.x = lc; + cOldXPos = cXPos = myDoc->textWidth(cursor); + } + + changeState(c); +} + +void KateViewInternal::end(VConfig &c) { + cursor.x = myDoc->textLength(cursor.y); + cOldXPos = cXPos = myDoc->textWidth(cursor); + changeState(c); +} + + +void KateViewInternal::cursorUp(VConfig &c) { + + cursor.y--; + cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); + changeState(c); +} + + +void KateViewInternal::cursorDown(VConfig &c) { + int x; + + if (cursor.y == myDoc->lastLine()) { + x = myDoc->textLength(cursor.y); + if (cursor.x >= x) return; + cursor.x = x; + cXPos = myDoc->textWidth(cursor); + } else { + cursor.y++; + cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor, cursor, cOldXPos); + } + changeState(c); +} + +void KateViewInternal::scrollUp(VConfig &c) { + + if (! yPos) return; + + newYPos = yPos - myDoc->fontHeight; + if (cursor.y == (yPos + height())/myDoc->fontHeight -1) { + cursor.y--; + cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); + + changeState(c); + } +} + +void KateViewInternal::scrollDown(VConfig &c) { + + if (endLine >= myDoc->lastLine()) return; + + newYPos = yPos + myDoc->fontHeight; + if (cursor.y == (yPos + myDoc->fontHeight -1)/myDoc->fontHeight) { + cursor.y++; + cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); + changeState(c); + } +} + +void KateViewInternal::topOfView(VConfig &c) { + + cursor.y = (yPos + myDoc->fontHeight -1)/myDoc->fontHeight; + cursor.x = 0; + cOldXPos = cXPos = 0; + changeState(c); +} + +void KateViewInternal::bottomOfView(VConfig &c) { + + cursor.y = (yPos + height())/myDoc->fontHeight -1; + if (cursor.y < 0) cursor.y = 0; + if (cursor.y > myDoc->lastLine()) cursor.y = myDoc->lastLine(); + cursor.x = 0; + cOldXPos = cXPos = 0; + changeState(c); +} + +void KateViewInternal::pageUp(VConfig &c) { + int lines = (endLine - startLine - 1); + + if (lines <= 0) lines = 1; + + if (!(c.flags & KateView::cfPageUDMovesCursor) && yPos > 0) { + newYPos = yPos - lines * myDoc->fontHeight; + if (newYPos < 0) newYPos = 0; + } + cursor.y -= lines; + cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor, cursor, cOldXPos); + changeState(c); +// cursorPageUp(c); +} + +void KateViewInternal::pageDown(VConfig &c) { + + int lines = (endLine - startLine - 1); + + if (!(c.flags & KateView::cfPageUDMovesCursor) && endLine < myDoc->lastLine()) { + if (lines < myDoc->lastLine() - endLine) + newYPos = yPos + lines * myDoc->fontHeight; + else + newYPos = yPos + (myDoc->lastLine() - endLine) * myDoc->fontHeight; + } + cursor.y += lines; + cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); + changeState(c); +// cursorPageDown(c); +} + +// go to the top, same X position +void KateViewInternal::top(VConfig &c) { + +// cursor.x = 0; + cursor.y = 0; + cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); +// cOldXPos = cXPos = 0; + changeState(c); +} + +// go to the bottom, same X position +void KateViewInternal::bottom(VConfig &c) { + +// cursor.x = 0; + cursor.y = myDoc->lastLine(); + cXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor,cursor,cOldXPos); +// cOldXPos = cXPos = 0; + changeState(c); +} + +// go to the top left corner +void KateViewInternal::top_home(VConfig &c) +{ + cursor.y = 0; + cursor.x = 0; + cOldXPos = cXPos = 0; + changeState(c); +} + +// go to the bottom right corner +void KateViewInternal::bottom_end(VConfig &c) { + + cursor.y = myDoc->lastLine(); + cursor.x = myDoc->textLength(cursor.y); + cOldXPos = cXPos = myDoc->textWidth(cursor); + changeState(c); +} + + +void KateViewInternal::changeXPos(int p) { + int dx; + + dx = xPos - p; + xPos = p; + if (QABS(dx) < width()) scroll(dx, 0); else update(); +} + +void KateViewInternal::changeYPos(int p) { + int dy; + + dy = yPos - p; + yPos = p; + clearDirtyCache(height()); + + if (QABS(dy) < height()) + { + scroll(0, dy); + leftBorder->scroll(0, dy); + } + else + update(); +} + + +void KateViewInternal::getVConfig(VConfig &c) { + + c.view = myView; + c.cursor = cursor; + c.cXPos = cXPos; + c.flags = myView->configFlags; +} + +void KateViewInternal::changeState(VConfig &c) { + /* + * we need to be sure to kill the selection on an attempted cursor + * movement even if the cursor doesn't physically move, + * but we need to be careful not to do some other things in this case, + * like we don't want to expose the cursor + */ + +// if (cursor.x == c.cursor.x && cursor.y == c.cursor.y) return; + bool nullMove = (cursor.x == c.cursor.x && cursor.y == c.cursor.y); + +// if (cursor.y != c.cursor.y || c.flags & KateView::cfMark) myDoc->recordReset(); + + if (! nullMove) { + + exposeCursor = true; + + // mark old position of cursor as dirty + if (cursorOn) { + tagLines(c.cursor.y, c.cursor.y, c.cXPos -2, c.cXPos +3); + cursorOn = false; + } + + // mark old bracket mark position as dirty + if (bm.sXPos < bm.eXPos) { + tagLines(bm.cursor.y, bm.cursor.y, bm.sXPos, bm.eXPos); + } + // make new bracket mark + myDoc->newBracketMark(cursor, bm); + + // remove trailing spaces when leaving a line + if (c.flags & KateView::cfRemoveSpaces && cursor.y != c.cursor.y) { + TextLine::Ptr textLine = myDoc->getTextLine(c.cursor.y); + int newLen = textLine->lastChar(); + if (newLen != textLine->length()) { + textLine->truncate(newLen); + // if some spaces are removed, tag the line as dirty + myDoc->tagLines(c.cursor.y, c.cursor.y); + } + } + } + + if (c.flags & KateView::cfMark) { + if (! nullMove) + myDoc->selectTo(c, cursor, cXPos); + } else { + if (!(c.flags & KateView::cfPersistent)) + myDoc->deselectAll(); + } +} + +void KateViewInternal::insLine(int line) { + + if (line <= cursor.y) { + cursor.y++; + } + if (line < startLine) { + startLine++; + endLine++; + yPos += myDoc->fontHeight; + } else if (line <= endLine) { + tagAll(); + } +} + +void KateViewInternal::delLine(int line) { + + if (line <= cursor.y && cursor.y > 0) { + cursor.y--; + } + if (line < startLine) { + startLine--; + endLine--; + yPos -= myDoc->fontHeight; + } else if (line <= endLine) { + tagAll(); + } +} + +void KateViewInternal::updateCursor() { + cOldXPos = cXPos = myDoc->textWidth(cursor); +} + + +void KateViewInternal::updateCursor(PointStruc &newCursor) { + updateCursor(newCursor, myView->config()); +} + +void KateViewInternal::updateCursor(PointStruc &newCursor, int flags) { + + if (!(flags & KateView::cfPersistent)) myDoc->deselectAll(); + + exposeCursor = true; + if (cursorOn) { + tagLines(cursor.y, cursor.y, cXPos -2, cXPos +3); + cursorOn = false; + } + + if (bm.sXPos < bm.eXPos) { + tagLines(bm.cursor.y, bm.cursor.y, bm.sXPos, bm.eXPos); + } + myDoc->newBracketMark(newCursor, bm); + + cursor = newCursor; + cOldXPos = cXPos = myDoc->textWidth(cursor); +} + +// init the line dirty cache +void KateViewInternal::clearDirtyCache(int height) { + int lines, z; + + // calc start and end line of visible part + startLine = yPos/myDoc->fontHeight; + endLine = (yPos + height -1)/myDoc->fontHeight; + + updateState = 0; + + lines = endLine - startLine +1; + if (lines > numLines) { // resize the dirty cache + numLines = lines*2; + delete [] lineRanges; + lineRanges = new LineRange[numLines]; + } + + for (z = 0; z < lines; z++) { // clear all lines + lineRanges[z].start = 0xffffff; + lineRanges[z].end = -2; + } + newXPos = newYPos = -1; +} + +void KateViewInternal::tagLines(int start, int end, int x1, int x2) { + LineRange *r; + int z; + + start -= startLine; + if (start < 0) start = 0; + end -= startLine; + if (end > endLine - startLine) end = endLine - startLine; + + if (x1 <= 0) x1 = -2; + if (x1 < xPos-2) x1 = xPos-2; + if (x2 > width() + xPos-2) x2 = width() + xPos-2; + if (x1 >= x2) return; + + r = &lineRanges[start]; + for (z = start; z <= end; z++) { + if (x1 < r->start) r->start = x1; + if (x2 > r->end) r->end = x2; + r++; + updateState |= 1; + } +} + +void KateViewInternal::tagAll() { + updateState = 3; +} + +void KateViewInternal::setPos(int x, int y) { + newXPos = x; + newYPos = y; +} + +void KateViewInternal::center() { + newXPos = 0; + newYPos = cursor.y*myDoc->fontHeight - height()/2; + if (newYPos < 0) newYPos = 0; +} + +void KateViewInternal::updateView(int flags) { + int fontHeight; + int oldXPos, oldYPos; + int w, h; + int z; + bool b; + int xMax, yMax; + int cYPos; + int cXPosMin, cXPosMax, cYPosMin, cYPosMax; + int dx, dy; + int pageScroll; + int scrollbarWidth = style().scrollBarExtent().width(); + +//debug("upView %d %d %d %d %d", exposeCursor, updateState, flags, newXPos, newYPos); + if (exposeCursor || flags & KateView::ufDocGeometry) { + emit myView->newCurPos(); + } else { + if (updateState == 0 && newXPos < 0 && newYPos < 0) return; + } + + if (cursorTimer) { + killTimer(cursorTimer); + cursorTimer = startTimer(KApplication::cursorFlashTime() / 2); + cursorOn = true; + } + + oldXPos = xPos; + oldYPos = yPos; +/* if (flags & ufPos) { + xPos = newXPos; + yPos = newYPos; + exposeCursor = true; + }*/ + if (newXPos >= 0) xPos = newXPos; + if (newYPos >= 0) yPos = newYPos; + + fontHeight = myDoc->fontHeight; + cYPos = cursor.y*fontHeight; + + z = 0; + do { + w = myView->width() - 4; + h = myView->height() - 4; + + xMax = myDoc->textWidth() - w; + b = (xPos > 0 || xMax > 0); + if (b) h -= scrollbarWidth; + yMax = myDoc->textHeight() - h; + if (yPos > 0 || yMax > 0) { + w -= scrollbarWidth; + xMax += scrollbarWidth; + if (!b && xMax > 0) { + h -= scrollbarWidth; + yMax += scrollbarWidth; + } + } + + if (!exposeCursor) break; +// if (flags & KateView::ufNoScroll) break; +/* + if (flags & KateView::ufCenter) { + cXPosMin = xPos + w/3; + cXPosMax = xPos + (w*2)/3; + cYPosMin = yPos + h/3; + cYPosMax = yPos + ((h - fontHeight)*2)/3; + } else {*/ + cXPosMin = xPos + 4; + cXPosMax = xPos + w - 8; + cYPosMin = yPos; + cYPosMax = yPos + (h - fontHeight); +// } + + if (cXPos < cXPosMin) { + xPos -= cXPosMin - cXPos; + } + if (xPos < 0) xPos = 0; + if (cXPos > cXPosMax) { + xPos += cXPos - cXPosMax; + } + if (cYPos < cYPosMin) { + yPos -= cYPosMin - cYPos; + } + if (yPos < 0) yPos = 0; + if (cYPos > cYPosMax) { + yPos += cYPos - cYPosMax; + } + + z++; + } while (z < 2); + + if (xMax < xPos) xMax = xPos; + if (yMax < yPos) yMax = yPos; + + if (xMax > 0) { + pageScroll = w - (w % fontHeight) - fontHeight; + if (pageScroll <= 0) + pageScroll = fontHeight; + + xScroll->blockSignals(true); + xScroll->setGeometry(2,h + 2,w,scrollbarWidth); + xScroll->setRange(0,xMax); + xScroll->setValue(xPos); + xScroll->setSteps(fontHeight,pageScroll); + xScroll->blockSignals(false); + xScroll->show(); + } else xScroll->hide(); + + if (yMax > 0) { + pageScroll = h - (h % fontHeight) - fontHeight; + if (pageScroll <= 0) + pageScroll = fontHeight; + + yScroll->blockSignals(true); + yScroll->setGeometry(w + 2,2,scrollbarWidth,h); + yScroll->setRange(0,yMax); + yScroll->setValue(yPos); + yScroll->setSteps(fontHeight,pageScroll); + yScroll->blockSignals(false); + yScroll->show(); + } else yScroll->hide(); + + if (w != width() || h != height()) { + clearDirtyCache(h); + resize(w,h); + } else { + dx = oldXPos - xPos; + dy = oldYPos - yPos; + + b = updateState == 3; + if (flags & KateView::ufUpdateOnScroll) { + b |= dx || dy; + } else { + b |= QABS(dx)*3 > w*2 || QABS(dy)*3 > h*2; + } + + if (b) { + clearDirtyCache(h); + update(); + } else { + if (dy) + leftBorder->scroll(0, dy); + if (updateState > 0) paintTextLines(oldXPos, oldYPos); + clearDirtyCache(h); + + if (dx || dy) { + scroll(dx,dy); +// kapp->syncX(); +// scroll2(dx - dx/2,dy - dy/2); +// } else { + } + if (cursorOn) paintCursor(); + if (bm.eXPos > bm.sXPos) paintBracketMark(); + } + } + exposeCursor = false; +// updateState = 0; +} + + +void KateViewInternal::paintTextLines(int xPos, int yPos) { +// int xStart, xEnd; + int line;//, z; + int h; + LineRange *r; + + if (!drawBuffer) return; + if (drawBuffer->isNull()) return; + + QPainter paint; + paint.begin(drawBuffer); + + h = myDoc->fontHeight; + r = lineRanges; + for (line = startLine; line <= endLine; line++) { + if (r->start < r->end) { +//debug("painttextline %d %d %d", line, r->start, r->end); + myDoc->paintTextLine(paint, line, r->start, r->end, myView->configFlags & KateView::cfShowTabs); + bitBlt(this, r->start - (xPos-2), line*h - yPos, drawBuffer, 0, 0, + r->end - r->start, h); + leftBorder->paintLine(line); + } + r++; + } + + paint.end(); +} + +void KateViewInternal::paintCursor() { + int h, y, x; + static int cx = 0, cy = 0, ch = 0; + + h = myDoc->fontHeight; + y = h*cursor.y - yPos; + x = cXPos - (xPos-2); + + if(myDoc->myFont != font()) setFont(myDoc->myFont); + if(cx != x || cy != y || ch != h){ + cx = x; + cy = y; + ch = h; + setMicroFocusHint(cx, cy, 0, ch - 2); + } + + QPainter paint; + if (cursorOn) { + paint.begin(this); + paint.setClipping(false); + paint.setPen(myDoc->cursorCol(cursor.x,cursor.y)); + + h += y - 1; + paint.drawLine(x, y, x, h); + + paint.end(); + } else { if (drawBuffer && !drawBuffer->isNull()) { + paint.begin(drawBuffer); + myDoc->paintTextLine(paint, cursor.y, cXPos - 2, cXPos + 3, myView->configFlags & KateView::cfShowTabs); + bitBlt(this,x - 2,y, drawBuffer, 0, 0, 5, h); + paint.end(); } + } + +} + +void KateViewInternal::paintBracketMark() { + int y; + + y = myDoc->fontHeight*(bm.cursor.y +1) - yPos -1; + + QPainter paint; + paint.begin(this); + paint.setPen(myDoc->cursorCol(bm.cursor.x, bm.cursor.y)); + + paint.drawLine(bm.sXPos - (xPos-2), y, bm.eXPos - (xPos-2) -1, y); + paint.end(); +} + +void KateViewInternal::placeCursor(int x, int y, int flags) { + VConfig c; + + getVConfig(c); + c.flags |= flags; + cursor.y = (yPos + y)/myDoc->fontHeight; + cXPos = cOldXPos = myDoc->textWidth(c.flags & KateView::cfWrapCursor, cursor,xPos-2 + x); + changeState(c); +} + +// given physical coordinates, report whether the text there is selected +bool KateViewInternal::isTargetSelected(int x, int y) { + + y = (yPos + y) / myDoc->fontHeight; + + TextLine::Ptr line = myDoc->getTextLine(y); + if (!line) + return false; + + x = myDoc->textPos(line, x); + + return line->isSelected(x); +} + +void KateViewInternal::focusInEvent(QFocusEvent *) { +// debug("got focus %d",cursorTimer); + + if (!cursorTimer) { + cursorTimer = startTimer(KApplication::cursorFlashTime() / 2); + cursorOn = true; + paintCursor(); + } +} + +void KateViewInternal::focusOutEvent(QFocusEvent *) { +// debug("lost focus %d", cursorTimer); + + if (cursorTimer) { + killTimer(cursorTimer); + cursorTimer = 0; + } + + if (cursorOn) { + cursorOn = false; + paintCursor(); + } +} + +void KateViewInternal::keyPressEvent(QKeyEvent *e) { + VConfig c; +// int ascii; + +/* if (e->state() & AltButton) { + e->ignore(); + return; + }*/ +// debug("ascii %i, key %i, state %i",e->ascii(), e->key(), e->state()); + + getVConfig(c); +// ascii = e->ascii(); + + if (!myView->isReadOnly()) { + if (c.flags & KateView::cfTabIndents && myDoc->hasMarkedText()) { + if (e->key() == Qt::Key_Tab) { + myDoc->indent(c); + myDoc->updateViews(); + return; + } + if (e->key() == Qt::Key_Backtab) { + myDoc->unIndent(c); + myDoc->updateViews(); + return; + } + } + if ( !(e->state() & ControlButton ) && myDoc->insertChars(c, e->text())) { + myDoc->updateViews(); + e->accept(); + return; + } + } + e->ignore(); +} + +void KateViewInternal::mousePressEvent(QMouseEvent *e) { + + if (e->button() == LeftButton) { + + int flags; + + flags = 0; + if (e->state() & ShiftButton) { + flags |= KateView::cfMark; + if (e->state() & ControlButton) flags |= KateView::cfMark | KateView::cfKeepSelection; + } + placeCursor(e->x(), e->y(), flags); + scrollX = 0; + scrollY = 0; + if (!scrollTimer) scrollTimer = startTimer(50); + myDoc->updateViews(); + } + if (e->button() == MidButton) { + placeCursor(e->x(), e->y()); + if (! myView->isReadOnly()) + myView->paste(); + } + if (myView->rmbMenu && e->button() == RightButton) { + myView->rmbMenu->popup(mapToGlobal(e->pos())); + } + myView->mousePressEvent(e); // this doesn't do anything, does it? + // it does :-), we need this for KDevelop, so please don't uncomment it again -Sandy +} + +void KateViewInternal::mouseDoubleClickEvent(QMouseEvent *e) { + + if (e->button() == LeftButton) { + VConfig c; + getVConfig(c); + myDoc->selectWord(c.cursor, c.flags); + myDoc->updateViews(); + } +} + +void KateViewInternal::mouseReleaseEvent(QMouseEvent *e) { + + if (e->button() == LeftButton) { + if (myView->config() & KateView::cfMouseAutoCopy) myView->copy(); + killTimer(scrollTimer); + scrollTimer = 0; + } +} + +void KateViewInternal::mouseMoveEvent(QMouseEvent *e) { + + if (e->state() & LeftButton) { + int flags; + int d; + int x = e->x(), + y = e->y(); + + mouseX = e->x(); + mouseY = e->y(); + scrollX = 0; + scrollY = 0; + d = myDoc->fontHeight; + if (mouseX < 0) { + mouseX = 0; + scrollX = -d; + } + if (mouseX > width()) { + mouseX = width(); + scrollX = d; + } + if (mouseY < 0) { + mouseY = 0; + scrollY = -d; + } + if (mouseY > height()) { + mouseY = height(); + scrollY = d; + } +//debug("modifiers %d", ((KGuiCmdApp *) kapp)->getModifiers()); + flags = KateView::cfMark; + if (e->state() & ControlButton) flags |= KateView::cfKeepSelection; + placeCursor(mouseX, mouseY, flags); + myDoc->updateViews(/*ufNoScroll*/); + } +} + + + +void KateViewInternal::wheelEvent( QWheelEvent *e ) +{ + if( yScroll->isVisible() == true ) + { + QApplication::sendEvent( yScroll, e ); + } +} + + + +void KateViewInternal::paintEvent(QPaintEvent *e) { + int xStart, xEnd; + int h; + int line, y, yEnd; + + QRect updateR = e->rect(); + + if (!drawBuffer) return; + if (drawBuffer->isNull()) return; + + QPainter paint; + paint.begin(drawBuffer); + + xStart = xPos-2 + updateR.x(); + xEnd = xStart + updateR.width(); + + h = myDoc->fontHeight; + line = (yPos + updateR.y()) / h; + y = line*h - yPos; + yEnd = updateR.y() + updateR.height(); + waitForPreHighlight=myDoc->needPreHighlight(waitForPreHighlight=line+((long)(yEnd-y)/h)+5); + + while (y < yEnd) + { + TextLine *textLine; + int ctxNum = 0; + myDoc->paintTextLine(paint, line, xStart, xEnd, myView->configFlags & KateView::cfShowTabs); + bitBlt(this, updateR.x(), y, drawBuffer, 0, 0, updateR.width(), h); + leftBorder->paintLine(line); + line++; + y += h; + } + paint.end(); + + if (cursorOn) paintCursor(); + if (bm.eXPos > bm.sXPos) paintBracketMark(); +} + +void KateViewInternal::resizeEvent(QResizeEvent *) +{ + drawBuffer->resize (width(), myDoc->fontHeight); + leftBorder->resize(iconBorderWidth, height()); +} + +void KateViewInternal::timerEvent(QTimerEvent *e) { + if (e->timerId() == cursorTimer) { + cursorOn = !cursorOn; + paintCursor(); + } + if (e->timerId() == scrollTimer && (scrollX | scrollY)) { + xScroll->setValue(xPos + scrollX); + yScroll->setValue(yPos + scrollY); + + placeCursor(mouseX, mouseY, KateView::cfMark); + myDoc->updateViews(/*ufNoScroll*/); + } +} + +uint KateView::uniqueID = 0; + +KateView::KateView(KateDocument *doc, QWidget *parent, const char * name) : Kate::View (doc, parent, name) +{ + + myViewID = uniqueID; + uniqueID++; + + active = false; + myIconBorder = false; + + myDoc = doc; + myViewInternal = new KateViewInternal (this,doc); + myViewInternal->move(2, 2); + myViewInternal->leftBorder = new KateIconBorder(this, myViewInternal); + myViewInternal->leftBorder->setGeometry(2, 2, myViewInternal->iconBorderWidth, myViewInternal->iconBorderHeight); + myViewInternal->leftBorder->hide(); + + doc->addView( this ); + + + // some defaults + configFlags = KateView::cfAutoIndent | KateView::cfBackspaceIndents + | KateView::cfTabIndents | KateView::cfKeepIndentProfile + | KateView::cfRemoveSpaces + | KateView::cfDelOnInput | KateView::cfMouseAutoCopy | KateView::cfWrapCursor + | KateView::cfGroupUndo | KateView::cfShowTabs | KateView::cfSmartHome; + + searchFlags = 0; + replacePrompt = 0L; + rmbMenu = 0L; + + + setFocusProxy( myViewInternal ); + myViewInternal->setFocus(); + resize(parent->width() -4, parent->height() -4); + + + myViewInternal->installEventFilter( this ); + + //setupActions(); + + connect( this, SIGNAL( newStatus() ), this, SLOT( slotUpdate() ) ); + connect( this, SIGNAL( newUndo() ), this, SLOT( slotNewUndo() ) ); + connect( doc, SIGNAL( fileNameChanged() ), this, SLOT( slotFileStatusChanged() ) ); + connect( doc, SIGNAL( highlightChanged() ), this, SLOT( slotHighlightChanged() ) ); + + readConfig(); +// setHighlight->setCurrentItem(getHl()); + slotUpdate(); +} + +KateView::~KateView() +{ + + if (myDoc && !myDoc->m_bSingleViewMode) + myDoc->removeView( this ); + + delete myViewInternal; + +} + +#if 0 +void KateView::setupActions() +{ +#if 0 + KStdAction::close( this, SLOT(flush()), actionCollection(), "file_close" ); + + KStdAction::save(this, SLOT(save()), actionCollection()); + + // setup edit menu + editUndo = KStdAction::undo(this, SLOT(undo()), actionCollection()); + editRedo = KStdAction::redo(this, SLOT(redo()), actionCollection()); + editUndoHist = new KAction(i18n("Undo/Redo &History..."), 0, this, SLOT(undoHistory()), + actionCollection(), "edit_undoHistory"); + KStdAction::cut(this, SLOT(cut()), actionCollection()); + KStdAction::copy(this, SLOT(copy()), actionCollection()); + KStdAction::paste(this, SLOT(paste()), actionCollection()); + + if ( myDoc->hasBrowserExtension() ) + { + KStdAction::saveAs(this, SLOT(saveAs()), myDoc->actionCollection()); + KStdAction::find(this, SLOT(find()), myDoc->actionCollection(), "find"); + KStdAction::findNext(this, SLOT(findAgain()), myDoc->actionCollection(), "find_again"); + KStdAction::findPrev(this, SLOT(findPrev()), myDoc->actionCollection(), "find_prev"); + KStdAction::gotoLine(this, SLOT(gotoLine()), myDoc->actionCollection(), "goto_line" ); + new KAction(i18n("&Configure Editor..."), 0, this, SLOT(configDialog()),myDoc->actionCollection(), "set_confdlg"); + setHighlight = new KSelectAction(i18n("&Highlight Mode"), 0, myDoc->actionCollection(), "set_highlight"); + KStdAction::selectAll(this, SLOT(selectAll()), myDoc->actionCollection(), "select_all"); + new KAction(i18n("&Deselect All"), 0, this, SLOT(deselectAll()), + myDoc->actionCollection(), "unselect_all"); + new KAction(i18n("Invert &Selection"), 0, this, SLOT(invertSelection()), + myDoc->actionCollection(), "invert_select"); + + new KAction(i18n("Increase Font Sizes"), "viewmag+", 0, this, SLOT(slotIncFontSizes()), + myDoc->actionCollection(), "incFontSizes"); + new KAction(i18n("Decrease Font Sizes"), "viewmag-", 0, this, SLOT(slotDecFontSizes()), + myDoc->actionCollection(), "decFontSizes"); + } + else + { + KStdAction::saveAs(this, SLOT(saveAs()), actionCollection()); + KStdAction::find(this, SLOT(find()), actionCollection()); + KStdAction::findNext(this, SLOT(findAgain()), actionCollection()); + KStdAction::findPrev(this, SLOT(findPrev()), actionCollection(), "edit_find_prev"); + KStdAction::gotoLine(this, SLOT(gotoLine()), actionCollection()); + new KAction(i18n("&Configure Editor..."), 0, this, SLOT(configDialog()),actionCollection(), "set_confdlg"); + setHighlight = new KSelectAction(i18n("&Highlight Mode"), 0, actionCollection(), "set_highlight"); + KStdAction::selectAll(this, SLOT(selectAll()), actionCollection()); + new KAction(i18n("&Deselect All"), 0, this, SLOT(deselectAll()), + actionCollection(), "edit_deselectAll"); + new KAction(i18n("Invert &Selection"), 0, this, SLOT(invertSelection()), + actionCollection(), "edit_invertSelection"); + + new KAction(i18n("Increase Font Sizes"), "viewmag+", 0, this, SLOT(slotIncFontSizes()), + actionCollection(), "incFontSizes"); + new KAction(i18n("Decrease Font Sizes"), "viewmag-", 0, this, SLOT(slotDecFontSizes()), + actionCollection(), "decFontSizes"); + } + + new KAction(i18n("Apply Word Wrap"), 0, myDoc, SLOT(applyWordWrap()), actionCollection(), "edit_apply_wordwrap"); + + KStdAction::replace(this, SLOT(replace()), actionCollection()); + + new KAction(i18n("Editing Co&mmand"), Qt::CTRL+Qt::Key_M, this, SLOT(slotEditCommand()), + actionCollection(), "edit_cmd"); + + // setup bookmark menu + bookmarkToggle = new KAction(i18n("Toggle &Bookmark"), Qt::CTRL+Qt::Key_B, this, SLOT(toggleBookmark()), actionCollection(), "edit_bookmarkToggle"); + bookmarkClear = new KAction(i18n("Clear Bookmarks"), 0, this, SLOT(clearBookmarks()), actionCollection(), "edit_bookmarksClear"); + + // connect settings menu aboutToshow + bookmarkMenu = new KActionMenu(i18n("&Bookmarks"), actionCollection(), "bookmarks"); + connect(bookmarkMenu->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(bookmarkMenuAboutToShow())); + + new KToggleAction(i18n("Show &IconBorder"), Key_F6, this, SLOT(toggleIconBorder()), actionCollection(), "view_border"); + + // setup Tools menu + KStdAction::spelling(this, SLOT(spellcheck()), actionCollection()); + new KAction(i18n("&Indent"), "indent", Qt::CTRL+Qt::Key_I, this, SLOT(indent()), + actionCollection(), "tools_indent"); + new KAction(i18n("&Unindent"), "unindent", Qt::CTRL+Qt::Key_U, this, SLOT(unIndent()), + actionCollection(), "tools_unindent"); + new KAction(i18n("&Clean Indentation"), 0, this, SLOT(cleanIndent()), + actionCollection(), "tools_cleanIndent"); + new KAction(i18n("C&omment"), CTRL+Qt::Key_NumberSign, this, SLOT(comment()), + actionCollection(), "tools_comment"); + new KAction(i18n("Unco&mment"), CTRL+SHIFT+Qt::Key_NumberSign, this, SLOT(uncomment()), + actionCollection(), "tools_uncomment"); + + setVerticalSelection = new KToggleAction(i18n("&Vertical Selection"), Key_F4, this, SLOT(toggleVertical()), + actionCollection(), "set_verticalSelect"); + + connect(setHighlight, SIGNAL(activated(int)), this, SLOT(setHl(int))); + QStringList list; + for (int z = 0; z < HlManager::self()->highlights(); z++) + list.append(HlManager::self()->hlName(z)); + setHighlight->setItems(list); + + setEndOfLine = new KSelectAction(i18n("&End Of Line"), 0, actionCollection(), "set_eol"); + connect(setEndOfLine, SIGNAL(activated(int)), this, SLOT(setEol(int))); + list.clear(); + list.append("&Unix"); + list.append("&Windows/Dos"); + list.append("&Macintosh"); + setEndOfLine->setItems(list); +#endif +} +#endif + +void KateView::slotUpdate() +{ + int cfg = config(); + +#warning fixme setVerticalSelection->setChecked(cfg & KateView::cfVerticalSelect); + + slotNewUndo(); +} +void KateView::slotFileStatusChanged() +{ + int eol = getEol(); + eol = eol>=1 ? eol : 0; + +#warning fixme setEndOfLine->setCurrentItem(eol); +} +void KateView::slotNewUndo() +{ +#if 0 + int state = undoState(); + + editUndoHist->setEnabled(state & 1 || state & 2); + + QString t = i18n("Und&o"); // it would be nicer to fetch the original string + if (state & 1) { + editUndo->setEnabled(true); + t += ' '; + t += i18n(undoTypeName(nextUndoType())); + } else { + editUndo->setEnabled(false); + } + editUndo->setText(t); + + t = i18n("Re&do"); // it would be nicer to fetch the original string + if (state & 2) { + editRedo->setEnabled(true); + t += ' '; + t += i18n(undoTypeName(nextRedoType())); + } else { + editRedo->setEnabled(false); + } + editRedo->setText(t); +#endif +} + +void KateView::slotHighlightChanged() +{ +// setHighlight->setCurrentItem(getHl()); +} + + +void KateView::keyPressEvent( QKeyEvent *ev ) +{ + switch ( ev->key() ) + { + case Key_Left: + if ( ev->state() & ShiftButton ) + { + if ( ev->state() & ControlButton ) + shiftWordLeft(); + else + shiftCursorLeft(); + } + else if ( ev->state() & ControlButton ) + wordLeft(); + else + cursorLeft(); + break; + case Key_Right: + if ( ev->state() & ShiftButton ) + { + if ( ev->state() & ControlButton ) + shiftWordRight(); + else + shiftCursorRight(); + } + else if ( ev->state() & ControlButton ) + wordRight(); + else + cursorRight(); + break; + case Key_Home: + if ( ev->state() & ShiftButton ) + { + if ( ev->state() & ControlButton ) + shiftTop(); + else + shiftHome(); + } + else if ( ev->state() & ControlButton ) + top(); + else + home(); + break; + case Key_End: + if ( ev->state() & ShiftButton ) + { + if ( ev->state() & ControlButton ) + shiftBottom(); + else + shiftEnd(); + } + else if ( ev->state() & ControlButton ) + bottom(); + else + end(); + break; + case Key_Up: + if ( ev->state() & ShiftButton ) + shiftUp(); + else if ( ev->state() & ControlButton ) + scrollUp(); + else + up(); + break; + case Key_Down: + if ( ev->state() & ShiftButton ) + shiftDown(); + else if ( ev->state() & ControlButton ) + scrollDown(); + else + down(); + break; + case Key_PageUp: + if ( ev->state() & ShiftButton ) + shiftPageUp(); + else if ( ev->state() & ControlButton ) + topOfView(); + else + pageUp(); + break; + case Key_PageDown: + if ( ev->state() & ShiftButton ) + shiftPageDown(); + else if ( ev->state() & ControlButton ) + bottomOfView(); + else + pageDown(); + break; + case Key_Return: + case Key_Enter: + keyReturn(); + break; + case Key_Delete: + if ( ev->state() & ControlButton ) + { + VConfig c; + shiftWordRight(); + myViewInternal->getVConfig(c); + myDoc->delMarkedText(c); + myViewInternal->update(); + } + else keyDelete(); + break; + case Key_Backspace: + if ( ev->state() & ControlButton ) + { + VConfig c; + shiftWordLeft(); + myViewInternal->getVConfig(c); + myDoc->delMarkedText(c); + myViewInternal->update(); + } + else backspace(); + break; + case Key_Insert: + toggleInsert(); + break; + case Key_K: + if ( ev->state() & ControlButton ) + { + killLine(); + break; + } + default: + KTextEditor::View::keyPressEvent( ev ); + return; + break; + } + ev->accept(); +} + + +void KateView::setCursorPosition( int line, int col, bool /*mark*/ ) +{ + setCursorPositionInternal( line, col ); +} + +void KateView::getCursorPosition( int *line, int *col ) +{ + if ( line ) + *line = currentLine(); + + if ( col ) + *col = currentColumn(); +} + + +int KateView::currentLine() { + return myViewInternal->cursor.y; +} + +int KateView::currentColumn() { + return myDoc->currentColumn(myViewInternal->cursor); +} + +int KateView::currentCharNum() { + return myViewInternal->cursor.x; +} + +void KateView::setCursorPositionInternal(int line, int col) { + PointStruc cursor; + + cursor.x = col; + cursor.y = line; + myViewInternal->updateCursor(cursor); + myViewInternal->center(); +// myViewInternal->updateView(ufPos, 0, line*myDoc->fontHeight - height()/2); +// myDoc->updateViews(myViewInternal); //uptade all other views except this one + myDoc->updateViews(); +} + +int KateView::config() { + int flags; + + flags = configFlags; + if (myDoc->singleSelection()) flags |= KateView::cfSingleSelection; + return flags; +} + +void KateView::setConfig(int flags) { + bool updateView; + + // cfSingleSelection is a doc-property + myDoc->setSingleSelection(flags & KateView::cfSingleSelection); + flags &= ~KateView::cfSingleSelection; + + if (flags != configFlags) { + // update the view if visibility of tabs has changed + updateView = (flags ^ configFlags) & KateView::cfShowTabs; + configFlags = flags; + emit newStatus(); + if (updateView) myViewInternal->update(); + } +} + +int KateView::tabWidth() { + return myDoc->tabChars; +} + +void KateView::setTabWidth(int w) { + myDoc->setTabWidth(w); + myDoc->updateViews(); +} + +void KateView::setEncoding (QString e) { + myDoc->setEncoding (e); + myDoc->updateViews(); +} + +int KateView::undoSteps() { + return myDoc->undoSteps; +} + +void KateView::setUndoSteps(int s) { + myDoc->setUndoSteps(s); +} + +bool KateView::isReadOnly() { + return myDoc->readOnly; +} + +bool KateView::isModified() { + return myDoc->modified; +} + +void KateView::setReadOnly(bool m) { + myDoc->setReadOnly(m); +} + +void KateView::setModified(bool m) { + myDoc->setModified(m); +} + +bool KateView::isLastView() { + return myDoc->isLastView(1); +} + +KateDocument *KateView::doc() { + return myDoc; +} + +int KateView::undoState() { + if (isReadOnly()) + return 0; + else + return myDoc->undoState; +} + +int KateView::nextUndoType() { + return myDoc->nextUndoType(); +} + +int KateView::nextRedoType() { + return myDoc->nextRedoType(); +} + +void KateView::undoTypeList(QValueList &lst) +{ + myDoc->undoTypeList(lst); +} + +void KateView::redoTypeList(QValueList &lst) +{ + myDoc->redoTypeList(lst); +} + +const char * KateView::undoTypeName(int type) { + return KateActionGroup::typeName(type); +} + +QColor* KateView::getColors() +{ + return myDoc->colors; +} + +void KateView::applyColors() +{ + myDoc->tagAll(); + myDoc->updateViews(); +} + +bool KateView::isOverwriteMode() const +{ + return ( configFlags & KateView::cfOvr ); +} + +void KateView::setOverwriteMode( bool b ) +{ + if ( isOverwriteMode() && !b ) + setConfig( configFlags ^ KateView::cfOvr ); + else + setConfig( configFlags | KateView::cfOvr ); +} + +void KateView::toggleInsert() { + setConfig(configFlags ^ KateView::cfOvr); +} + +void KateView::toggleVertical() +{ + setConfig(configFlags ^ KateView::cfVerticalSelect); +} + + +int KateView::numLines() { + return myDoc->numLines(); +} + +QString KateView::text() { + return myDoc->text(); +} + +QString KateView::currentTextLine() { + TextLine::Ptr textLine = myDoc->getTextLine(myViewInternal->cursor.y); + return QString(textLine->getText(), textLine->length()); +} + +QString KateView::textLine(int num) { + TextLine::Ptr textLine = myDoc->getTextLine(num); + return QString(textLine->getText(), textLine->length()); +} + +QString KateView::currentWord() { + return myDoc->getWord(myViewInternal->cursor); +} + +QString KateView::word(int x, int y) { + PointStruc cursor; + cursor.y = (myViewInternal->yPos + y)/myDoc->fontHeight; + if (cursor.y < 0 || cursor.y > myDoc->lastLine()) return QString(); + cursor.x = myDoc->textPos(myDoc->getTextLine(cursor.y), myViewInternal->xPos-2 + x); + return myDoc->getWord(cursor); +} + +void KateView::setText(const QString &s) { + myDoc->setText(s); + myDoc->updateViews(); +} + +void KateView::insertText(const QString &s, bool /*mark*/) { + VConfig c; + myViewInternal->getVConfig(c); + myDoc->insert(c, s); + myDoc->updateViews(); +} + +bool KateView::hasMarkedText() { + return myDoc->hasMarkedText(); +} + +QString KateView::markedText() { + return myDoc->markedText(configFlags); +} + +bool KateView::canDiscard() { + int query; + + if (isModified()) { + query = KMessageBox::warningYesNoCancel(this, + i18n("The current Document has been modified.\nWould you like to save it?")); + switch (query) { + case KMessageBox::Yes: //yes + if (save() == CANCEL) return false; + if (isModified()) { + query = KMessageBox::warningContinueCancel(this, + i18n("Could not save the document.\nDiscard it and continue?"), + QString::null, i18n("&Discard")); + if (query == KMessageBox::Cancel) return false; + } + break; + case KMessageBox::Cancel: //cancel + return false; + } + } + return true; +} + +void KateView::flush() +{ + if (canDiscard()) myDoc->flush(); +} + +KateView::fileResult KateView::save() { + int query = KMessageBox::Yes; + if (isModified()) { + return saveAs(); + } + return OK; +} + +KateView::fileResult KateView::saveAs() { + return OK; +} + +void KateView::doCursorCommand(int cmdNum) { + VConfig c; + myViewInternal->getVConfig(c); + if (cmdNum & selectFlag) c.flags |= KateView::cfMark; + if (cmdNum & multiSelectFlag) c.flags |= KateView::cfMark | KateView::cfKeepSelection; + cmdNum &= ~(selectFlag | multiSelectFlag); + myViewInternal->doCursorCommand(c, cmdNum); + myDoc->updateViews(); +} + +void KateView::doEditCommand(int cmdNum) { + VConfig c; + myViewInternal->getVConfig(c); + myViewInternal->doEditCommand(c, cmdNum); + myDoc->updateViews(); +} + +void KateView::undoMultiple(int count) { + if (isReadOnly()) + return; + + VConfig c; + myViewInternal->getVConfig(c); + myDoc->undo(c, count); + myDoc->updateViews(); +} + +void KateView::redoMultiple(int count) { + if (isReadOnly()) + return; + + VConfig c; + myViewInternal->getVConfig(c); + myDoc->redo(c, count); + myDoc->updateViews(); +} + +void KateView::undoHistory() +{ + UndoHistory *undoH; + + undoH = new UndoHistory(this, this, "UndoHistory", true); + + undoH->setCaption(i18n("Undo/Redo History")); + + connect(this,SIGNAL(newUndo()),undoH,SLOT(newUndo())); + connect(undoH,SIGNAL(undo(int)),this,SLOT(undoMultiple(int))); + connect(undoH,SIGNAL(redo(int)),this,SLOT(redoMultiple(int))); + + undoH->exec(); + + delete undoH; +} + +static void kwview_addToStrList(QStringList &list, const QString &str) { + if (list.count() > 0) { + if (list.first() == str) return; + QStringList::Iterator it; + it = list.find(str); + if (*it != 0L) list.remove(it); + if (list.count() >= 16) list.remove(list.fromLast()); + } + list.prepend(str); +} + +void KateView::find() { + SearchDialog *searchDialog; + + if (!myDoc->hasMarkedText()) searchFlags &= ~KateView::sfSelected; + + searchDialog = new SearchDialog(this, myDoc->searchForList, myDoc->replaceWithList, + searchFlags & ~KateView::sfReplace); + + // If the user has marked some text we use that otherwise + // use the word under the cursor. + QString str; + if (myDoc->hasMarkedText()) + str = markedText(); + + if (str.isEmpty()) + str = currentWord(); + + if (!str.isEmpty()) + { + str.replace(QRegExp("^\n"), ""); + int pos=str.find("\n"); + if (pos>-1) + str=str.left(pos); + searchDialog->setSearchText( str ); + } + + myViewInternal->focusOutEvent(0L);// QT bug ? + if (searchDialog->exec() == QDialog::Accepted) { + kwview_addToStrList(myDoc->searchForList, searchDialog->getSearchFor()); + searchFlags = searchDialog->getFlags() | (searchFlags & KateView::sfPrompt); + initSearch(s, searchFlags); + findAgain(s); + } + delete searchDialog; +} + +void KateView::replace() { + SearchDialog *searchDialog; + + if (isReadOnly()) return; + + if (!myDoc->hasMarkedText()) searchFlags &= ~KateView::sfSelected; + searchDialog = new SearchDialog(this, myDoc->searchForList, myDoc->replaceWithList, + searchFlags | KateView::sfReplace); + + // If the user has marked some text we use that otherwise + // use the word under the cursor. + QString str; + if (myDoc->hasMarkedText()) + str = markedText(); + + if (str.isEmpty()) + str = currentWord(); + + if (!str.isEmpty()) + { + str.replace(QRegExp("^\n"), ""); + int pos=str.find("\n"); + if (pos>-1) + str=str.left(pos); + searchDialog->setSearchText( str ); + } + + myViewInternal->focusOutEvent(0L);// QT bug ? + if (searchDialog->exec() == QDialog::Accepted) { +// myDoc->recordReset(); + kwview_addToStrList(myDoc->searchForList, searchDialog->getSearchFor()); + kwview_addToStrList(myDoc->replaceWithList, searchDialog->getReplaceWith()); + searchFlags = searchDialog->getFlags(); + initSearch(s, searchFlags); + replaceAgain(); + } + delete searchDialog; +} + +void KateView::gotoLine() { + GotoLineDialog *dlg; + PointStruc cursor; + + dlg = new GotoLineDialog(this, myViewInternal->cursor.y + 1, myDoc->numLines()); +// dlg = new GotoLineDialog(myViewInternal->cursor.y + 1, this); + + if (dlg->exec() == QDialog::Accepted) { +// myDoc->recordReset(); + cursor.x = 0; + cursor.y = dlg->getLine() - 1; + myDoc->needPreHighlight(cursor.y); + myViewInternal->updateCursor(cursor); + myViewInternal->center(); + myViewInternal->updateView(KateView::ufUpdateOnScroll); + myDoc->updateViews(this); //uptade all other views except this one + } + delete dlg; +} + + +void KateView::initSearch(SConfig &s, int flags) { + + s.flags = flags; + s.setPattern(myDoc->searchForList.first()); + + if (!(s.flags & KateView::sfFromBeginning)) { + // If we are continuing a backward search, make sure we do not get stuck + // at an existing match. + s.cursor = myViewInternal->cursor; + TextLine::Ptr textLine = myDoc->getTextLine(s.cursor.y); + QString const txt(textLine->getText(),textLine->length()); + const QString searchFor= myDoc->searchForList.first(); + int pos = s.cursor.x-searchFor.length()-1; + if ( pos < 0 ) pos = 0; + pos= txt.find(searchFor, pos, s.flags & KateView::sfCaseSensitive); + if ( s.flags & KateView::sfBackward ) + { + if ( pos <= s.cursor.x ) s.cursor.x= pos-1; + } + else + if ( pos == s.cursor.x ) s.cursor.x++; + } else { + if (!(s.flags & KateView::sfBackward)) { + s.cursor.x = 0; + s.cursor.y = 0; + } else { + s.cursor.x = -1; + s.cursor.y = myDoc->lastLine(); + } + s.flags |= KateView::sfFinished; + } + if (!(s.flags & KateView::sfBackward)) { + if (!(s.cursor.x || s.cursor.y)) + s.flags |= KateView::sfFinished; + } + s.startCursor = s.cursor; +} + +void KateView::continueSearch(SConfig &s) { + + if (!(s.flags & KateView::sfBackward)) { + s.cursor.x = 0; + s.cursor.y = 0; + } else { + s.cursor.x = -1; + s.cursor.y = myDoc->lastLine(); + } + s.flags |= KateView::sfFinished; + s.flags &= ~KateView::sfAgain; +} + +void KateView::findAgain(SConfig &s) { + int query; + PointStruc cursor; + QString str; + + QString searchFor = myDoc->searchForList.first(); + + if( searchFor.isEmpty() ) { + find(); + return; + } + + do { + query = KMessageBox::Cancel; + if (myDoc->doSearch(s,searchFor)) { + cursor = s.cursor; + if (!(s.flags & KateView::sfBackward)) + s.cursor.x += s.matchedLength; + myViewInternal->updateCursor(s.cursor); //does deselectAll() + exposeFound(cursor,s.matchedLength,(s.flags & KateView::sfAgain) ? 0 : KateView::ufUpdateOnScroll,false); + } else { + if (!(s.flags & KateView::sfFinished)) { + // ask for continue + if (!(s.flags & KateView::sfBackward)) { + // forward search + str = i18n("End of document reached.\n" + "Continue from the beginning?"); + query = KMessageBox::warningContinueCancel(this, + str, i18n("Find"), i18n("Continue")); + } else { + // backward search + str = i18n("Beginning of document reached.\n" + "Continue from the end?"); + query = KMessageBox::warningContinueCancel(this, + str, i18n("Find"), i18n("Continue")); + } + continueSearch(s); + } else { + // wrapped + KMessageBox::sorry(this, + i18n("Search string '%1' not found!").arg(searchFor), + i18n("Find")); + } + } + } while (query == KMessageBox::Continue); +} + +void KateView::replaceAgain() { + if (isReadOnly()) + return; + + replaces = 0; + if (s.flags & KateView::sfPrompt) { + doReplaceAction(-1); + } else { + doReplaceAction(KateView::srAll); + } +} + +void KateView::doReplaceAction(int result, bool found) { + int rlen; + PointStruc cursor; + bool started; + + QString searchFor = myDoc->searchForList.first(); + QString replaceWith = myDoc->replaceWithList.first(); + rlen = replaceWith.length(); + + switch (result) { + case KateView::srYes: //yes + myDoc->recordStart(this, s.cursor, configFlags, + KateActionGroup::ugReplace, true); + myDoc->recordReplace(s.cursor, s.matchedLength, replaceWith); + replaces++; + if (s.cursor.y == s.startCursor.y && s.cursor.x < s.startCursor.x) + s.startCursor.x += rlen - s.matchedLength; + if (!(s.flags & KateView::sfBackward)) s.cursor.x += rlen; + myDoc->recordEnd(this, s.cursor, configFlags | KateView::cfPersistent); + break; + case KateView::srNo: //no + if (!(s.flags & KateView::sfBackward)) s.cursor.x += s.matchedLength; + break; + case KateView::srAll: //replace all + deleteReplacePrompt(); + do { + started = false; + while (found || myDoc->doSearch(s,searchFor)) { + if (!started) { + found = false; + myDoc->recordStart(this, s.cursor, configFlags, + KateActionGroup::ugReplace); + started = true; + } + myDoc->recordReplace(s.cursor, s.matchedLength, replaceWith); + replaces++; + if (s.cursor.y == s.startCursor.y && s.cursor.x < s.startCursor.x) + s.startCursor.x += rlen - s.matchedLength; + if (!(s.flags & KateView::sfBackward)) s.cursor.x += rlen; + } + if (started) myDoc->recordEnd(this, s.cursor, + configFlags | KateView::cfPersistent); + } while (!askReplaceEnd()); + return; + case KateView::srCancel: //cancel + deleteReplacePrompt(); + return; + default: + replacePrompt = 0L; + } + + do { + if (myDoc->doSearch(s,searchFor)) { + //text found: highlight it, show replace prompt if needed and exit + cursor = s.cursor; + if (!(s.flags & KateView::sfBackward)) cursor.x += s.matchedLength; + myViewInternal->updateCursor(cursor); //does deselectAll() + exposeFound(s.cursor,s.matchedLength,(s.flags & KateView::sfAgain) ? 0 : KateView::ufUpdateOnScroll,true); + if (replacePrompt == 0L) { + replacePrompt = new ReplacePrompt(this); + myDoc->setPseudoModal(replacePrompt);//disable(); + connect(replacePrompt,SIGNAL(clicked()),this,SLOT(replaceSlot())); + replacePrompt->show(); //this is not modal + } + return; //exit if text found + } + //nothing found: repeat until user cancels "repeat from beginning" dialog + } while (!askReplaceEnd()); + deleteReplacePrompt(); +} + +void KateView::exposeFound(PointStruc &cursor, int slen, int flags, bool replace) { + int x1, x2, y1, y2, xPos, yPos; + + VConfig c; + myViewInternal->getVConfig(c); + myDoc->selectLength(cursor,slen,c.flags); + + TextLine::Ptr textLine = myDoc->getTextLine(cursor.y); + x1 = myDoc->textWidth(textLine,cursor.x) -10; + x2 = myDoc->textWidth(textLine,cursor.x + slen) +20; + y1 = myDoc->fontHeight*cursor.y -10; + y2 = y1 + myDoc->fontHeight +30; + + xPos = myViewInternal->xPos; + yPos = myViewInternal->yPos; + + if (x1 < 0) x1 = 0; + if (replace) y2 += 90; + + if (x1 < xPos || x2 > xPos + myViewInternal->width()) { + xPos = x2 - myViewInternal->width(); + } + if (y1 < yPos || y2 > yPos + myViewInternal->height()) { + xPos = x2 - myViewInternal->width(); + yPos = myDoc->fontHeight*cursor.y - height()/3; + } + myViewInternal->setPos(xPos, yPos); + myViewInternal->updateView(flags);// | ufPos,xPos,yPos); + myDoc->updateViews(this); +} + +void KateView::deleteReplacePrompt() { + myDoc->setPseudoModal(0L); +} + +bool KateView::askReplaceEnd() { + QString str; + int query; + + myDoc->updateViews(); + if (s.flags & KateView::sfFinished) { + // replace finished + str = i18n("%1 replacement(s) made").arg(replaces); + KMessageBox::information(this, str, i18n("Replace")); + return true; + } + + // ask for continue + if (!(s.flags & KateView::sfBackward)) { + // forward search + str = i18n("%1 replacement(s) made.\n" + "End of document reached.\n" + "Continue from the beginning?").arg(replaces); + query = KMessageBox::questionYesNo(this, str, i18n("Replace"), + i18n("Continue"), i18n("Stop")); + } else { + // backward search + str = i18n("%1 replacement(s) made.\n" + "Beginning of document reached.\n" + "Continue from the end?").arg(replaces); + query = KMessageBox::questionYesNo(this, str, i18n("Replace"), + i18n("Continue"), i18n("Stop")); + } + replaces = 0; + continueSearch(s); + return (query == KMessageBox::No); +} + +void KateView::replaceSlot() { + doReplaceAction(replacePrompt->result(),true); +} + +void KateView::installPopup(QPopupMenu *rmb_Menu) +{ + rmbMenu = rmb_Menu; +} + +void KateView::readConfig() +{ + KConfig *config = KGlobal::config(); + config->setGroup("Kate View"); + + searchFlags = config->readNumEntry("SearchFlags", KateView::sfPrompt); + configFlags = config->readNumEntry("ConfigFlags", configFlags) & ~KateView::cfMark; + + config->sync(); +} + +void KateView::writeConfig() +{ + KConfig *config = KGlobal::config(); + config->setGroup("Kate View"); + + config->writeEntry("SearchFlags",searchFlags); + config->writeEntry("ConfigFlags",configFlags); + + config->sync(); +} + +void KateView::readSessionConfig(KConfig *config) +{ + PointStruc cursor; + + myViewInternal->xPos = config->readNumEntry("XPos"); + myViewInternal->yPos = config->readNumEntry("YPos"); + cursor.x = config->readNumEntry("CursorX"); + cursor.y = config->readNumEntry("CursorY"); + myViewInternal->updateCursor(cursor); + myIconBorder = config->readBoolEntry("IconBorder on"); + setIconBorder(myIconBorder); +} + +void KateView::writeSessionConfig(KConfig *config) +{ + config->writeEntry("XPos",myViewInternal->xPos); + config->writeEntry("YPos",myViewInternal->yPos); + config->writeEntry("CursorX",myViewInternal->cursor.x); + config->writeEntry("CursorY",myViewInternal->cursor.y); + config->writeEntry("IconBorder on", myIconBorder); +} + +void KateView::configDialog() +{ + +#warning fixme + +#if 1 + KDialogBase *kd = new KDialogBase(KDialogBase::IconList, + i18n("Configure Editor"), + KDialogBase::Ok | KDialogBase::Cancel | + KDialogBase::Help , + KDialogBase::Ok, this, "tabdialog"); + + // color options + QFrame *page=kd->addPage(i18n("Colors")); + (new QVBoxLayout(page))->setAutoAdd(true); + ColorConfig *colorConfig = new ColorConfig(page); + QColor* colors = getColors(); + colorConfig->setColors(colors); + + page = kd->addPage(i18n("Fonts")); + (new QVBoxLayout(page))->setAutoAdd(true); + + FontConfig *fontConfig = new FontConfig(page); + fontConfig->setFont (myDoc->getFont()); + + // indent options + page=kd->addPage(i18n("Indent")); + (new QVBoxLayout(page))->setAutoAdd(true); + + IndentConfigTab *indentConfig = new IndentConfigTab(page, this); + + // select options + page=kd->addPage(i18n("Select")); + (new QVBoxLayout(page))->setAutoAdd(true); + + SelectConfigTab *selectConfig = new SelectConfigTab(page, this); + + // edit options + page=kd->addPage(i18n("Edit")); + (new QVBoxLayout(page))->setAutoAdd(true); + + EditConfigTab *editConfig = new EditConfigTab(page, this); + + + + HighlightDialogPage *hlPage; + HlManager *hlManager; + HlDataList hlDataList; + ItemStyleList defaultStyleList; + + hlManager = HlManager::self(); + + defaultStyleList.setAutoDelete(true); + hlManager->getDefaults(defaultStyleList); + + hlDataList.setAutoDelete(true); + //this gets the data from the KConfig object + hlManager->getHlDataList(hlDataList); + + page=kd->addPage(i18n("Highlighting")); + (new QVBoxLayout(page))->setAutoAdd(true); + + hlPage = new HighlightDialogPage(hlManager, &defaultStyleList, &hlDataList, 0, page); + + if (kd->exec()) { + // color options + colorConfig->getColors(colors); + myDoc->setFont (fontConfig->getFont()); + + applyColors(); + // indent options + indentConfig->getData(this); + // select options + selectConfig->getData(this); + // edit options + editConfig->getData(this); + // spell checker + hlManager->setHlDataList(hlDataList); + hlManager->setDefaults(defaultStyleList); + hlPage->saveData(); + } + + delete kd; + +#endif +} + +int KateView::getHl() { + return myDoc->highlightNum(); +} + +void KateView::setDontChangeHlOnSave() +{ + myDoc->setDontChangeHlOnSave(); +} + +void KateView::setHl(int n) { + myDoc->setHighlight(n); + myDoc->setDontChangeHlOnSave(); + myDoc->updateViews(); +} + +int KateView::getEol() { + return myDoc->eolMode; +} + +void KateView::setEol(int eol) { + if (isReadOnly()) + return; + + myDoc->eolMode = eol; + myDoc->setModified(true); +} + + + +void KateView::paintEvent(QPaintEvent *e) { + int x, y; + + QRect updateR = e->rect(); // update rectangle +// debug("Update rect = ( %i, %i, %i, %i )", +// updateR.x(),updateR.y(), updateR.width(), updateR.height() ); + + int ux1 = updateR.x(); + int uy1 = updateR.y(); + int ux2 = ux1 + updateR.width(); + int uy2 = uy1 + updateR.height(); + + QPainter paint; + paint.begin(this); + + QColorGroup g = colorGroup(); + x = width(); + y = height(); + + paint.setPen(g.dark()); + if (uy1 <= 0) paint.drawLine(0,0,x-2,0); + if (ux1 <= 0) paint.drawLine(0,1,0,y-2); + + paint.setPen(black); + if (uy1 <= 1) paint.drawLine(1,1,x-3,1); + if (ux1 <= 1) paint.drawLine(1,2,1,y-3); + + paint.setPen(g.midlight()); + if (uy2 >= y-1) paint.drawLine(1,y-2,x-3,y-2); + if (ux2 >= x-1) paint.drawLine(x-2,1,x-2,y-2); + + paint.setPen(g.light()); + if (uy2 >= y) paint.drawLine(0,y-1,x-2,y-1); + if (ux2 >= x) paint.drawLine(x-1,0,x-1,y-1); + + x -= 2 + 16; + y -= 2 + 16; + if (ux2 > x && uy2 > y) { + paint.fillRect(x,y,16,16,g.background()); + } + paint.end(); +} + +void KateView::resizeEvent(QResizeEvent *) { + +// debug("Resize %d, %d",e->size().width(),e->size().height()); + +//myViewInternal->resize(width() -20, height() -20); + myViewInternal->tagAll(); + myViewInternal->updateView(0/*ufNoScroll*/); +} + + +// Applies a new pattern to the search context. +void SConfig::setPattern(QString &newPattern) { + bool regExp = (flags & KateView::sfRegularExpression); + + m_pattern = newPattern; + if (regExp) { + m_regExp.setCaseSensitive(flags & KateView::sfCaseSensitive); + m_regExp.setPattern(m_pattern); + } +} + +// Applies the search context to the given string, and returns whether a match was found. If one is, +// the length of the string matched is also returned. +int SConfig::search(QString &text, int index) { + bool regExp = (flags & KateView::sfRegularExpression); + bool caseSensitive = (flags & KateView::sfCaseSensitive); + + if (flags & KateView::sfBackward) { + if (regExp) { + index = text.findRev(m_regExp, index); + } + else { + index = text.findRev(m_pattern, index, caseSensitive); + } + } + else { + if (regExp) { + index = text.find(m_regExp, index); + } + else { + index = text.find(m_pattern, index, caseSensitive); + } + } + + // Work out the matched length. + if (index != -1) + { + if (regExp) { + m_regExp.match(text, index, &matchedLength, false); + } + else { + matchedLength = m_pattern.length(); + } + } + return index; +} + +void KateView::setActive (bool b) +{ + active = b; +} + +bool KateView::isActive () +{ + return active; +} + +void KateView::setFocus () +{ + QWidget::setFocus (); + + emit gotFocus (this); +} + +bool KateView::eventFilter (QObject *object, QEvent *event) +{ + + if ( (event->type() == QEvent::FocusIn) ) + emit gotFocus (this); + + if ( (event->type() == QEvent::KeyPress) ) + { + QKeyEvent * ke=(QKeyEvent *)event; + + if ((ke->key()==Qt::Key_Tab) || (ke->key()==Qt::Key_BackTab)) + { + myViewInternal->keyPressEvent(ke); + return true; + } + } + return QWidget::eventFilter (object, event); +} + +void KateView::findAgain (bool back) +{ + bool b= (searchFlags & sfBackward) > 0; + initSearch(s, (searchFlags & ((b==back)?~sfBackward:~0) & ~sfFromBeginning) // clear flag for forward searching + | sfPrompt | sfAgain | ((b!=back)?sfBackward:0) ); + if (s.flags & sfReplace) + replaceAgain(); + else + KateView::findAgain(s); +} + +void KateView::slotEditCommand () +{ +#warning fixme +/* + bool ok; + QString cmd = KLineEditDlg::getText("Editing Command", "", &ok, this); + + if (ok) + myDoc->cmd()->execCmd (cmd, this);*/ +} + +void KateView::setIconBorder (bool enable) +{ + myIconBorder = enable; + + if (myIconBorder) + { + myViewInternal->move(myViewInternal->iconBorderWidth+2, 2); + myViewInternal->leftBorder->show(); + } + else + { + myViewInternal->leftBorder->hide(); + myViewInternal->move(2, 2); + } +} + +void KateView::toggleIconBorder () +{ + setIconBorder (!myIconBorder); +} + +void KateView::gotoMark (Kate::Mark *mark) +{ + PointStruc cursor; + + cursor.x = 0; + cursor.y = mark->line; + myDoc->needPreHighlight(cursor.y); + myViewInternal->updateCursor(cursor); + myViewInternal->center(); + myViewInternal->updateView(KateView::ufUpdateOnScroll); + myDoc->updateViews(this); +} + +void KateView::toggleBookmark () +{ + TextLine::Ptr line = myDoc->getTextLine (currentLine()); + + if (line->mark()&KateDocument::Bookmark) + line->delMark(KateDocument::Bookmark); + else + line->addMark(KateDocument::Bookmark); + + myDoc->tagLines (currentLine(), currentLine()); + myDoc->updateViews(); +} + +void KateView::clearBookmarks() +{ + QList list = myDoc->marks(); + for (int i=0; (uint) i < list.count(); i++) + { + if (list.at(i)->type&KateDocument::Bookmark) + { + myDoc->getTextLine(list.at(i)->line)->delMark(KateDocument::Bookmark); + myDoc->tagLines(list.at(i)->line, list.at(i)->line); + } + } + + myDoc->updateViews(); +} + +void KateView::bookmarkMenuAboutToShow() +{ +#warning fixme +#if 0 + bookmarkMenu->popupMenu()->clear (); + bookmarkToggle->plug (bookmarkMenu->popupMenu()); + bookmarkClear->plug (bookmarkMenu->popupMenu()); + bookmarkMenu->popupMenu()->insertSeparator (); + + list = myDoc->marks(); + for (int i=0; (uint) i < list.count(); i++) + { + if (list.at(i)->type&KateDocument::Bookmark) + { + QString bText = textLine(list.at(i)->line); + bText.truncate(32); + bText.append ("..."); + bookmarkMenu->popupMenu()->insertItem ( QString("%1 - \"%2\"").arg(list.at(i)->line).arg(bText), this, SLOT (gotoBookmark(int)), 0, i ); + } + } +#endif +} + +void KateView::gotoBookmark (int n) +{ + gotoMark (list.at(n)); +} + +int KateView::getHlCount () +{ + return HlManager::self()->highlights(); +} + +QString KateView::getHlName (int z) +{ + return HlManager::self()->hlName(z); +} + +QString KateView::getHlSection (int z) +{ + return HlManager::self()->hlSection (z); +} + +void KateView::slotIncFontSizes () +{ + QFont font = myDoc->getFont(); + font.setPointSize (font.pointSize()+2); + myDoc->setFont (font); +} + +void KateView::slotDecFontSizes () +{ + QFont font = myDoc->getFont(); + font.setPointSize (font.pointSize()-2); + myDoc->setFont (font); +} + +const char*bookmark_xpm[]={ +"12 16 4 1", +"b c #808080", +"a c #000080", +"# c #0000ff", +". c None", +"............", +"............", +"........###.", +".......#...a", +"......#.##.a", +".....#.#..aa", +"....#.#...a.", +"...#.#.a.a..", +"..#.#.a.a...", +".#.#.a.a....", +"#.#.a.a.....", +"#.#a.a...bbb", +"#...a..bbb..", +".aaa.bbb....", +"............", +"............"}; + +const char* breakpoint_xpm[]={ +"11 16 6 1", +"c c #c6c6c6", +". c None", +"# c #000000", +"d c #840000", +"a c #ffffff", +"b c #ff0000", +"...........", +"...........", +"...#####...", +"..#aaaaa#..", +".#abbbbbb#.", +"#abbbbbbbb#", +"#abcacacbd#", +"#abbbbbbbb#", +"#abcacacbd#", +"#abbbbbbbb#", +".#bbbbbbb#.", +"..#bdbdb#..", +"...#####...", +"...........", +"...........", +"..........."}; + +const char*breakpoint_bl_xpm[]={ +"11 16 7 1", +"a c #c0c0ff", +"# c #000000", +"c c #0000c0", +"e c #0000ff", +"b c #dcdcdc", +"d c #ffffff", +". c None", +"...........", +"...........", +"...#####...", +"..#ababa#..", +".#bcccccc#.", +"#acccccccc#", +"#bcadadace#", +"#acccccccc#", +"#bcadadace#", +"#acccccccc#", +".#ccccccc#.", +"..#cecec#..", +"...#####...", +"...........", +"...........", +"..........."}; + +const char*breakpoint_gr_xpm[]={ +"11 16 6 1", +"c c #c6c6c6", +"d c #2c2c2c", +"# c #000000", +". c None", +"a c #ffffff", +"b c #555555", +"...........", +"...........", +"...#####...", +"..#aaaaa#..", +".#abbbbbb#.", +"#abbbbbbbb#", +"#abcacacbd#", +"#abbbbbbbb#", +"#abcacacbd#", +"#abbbbbbbb#", +".#bbbbbbb#.", +"..#bdbdb#..", +"...#####...", +"...........", +"...........", +"..........."}; + +const char*ddd_xpm[]={ +"11 16 4 1", +"a c #00ff00", +"b c #000000", +". c None", +"# c #00c000", +"...........", +"...........", +"...........", +"#a.........", +"#aaa.......", +"#aaaaa.....", +"#aaaaaaa...", +"#aaaaaaaaa.", +"#aaaaaaa#b.", +"#aaaaa#b...", +"#aaa#b.....", +"#a#b.......", +"#b.........", +"...........", +"...........", +"..........."}; + + + +KateIconBorder::KateIconBorder(KateView *view, KateViewInternal *internalView) + : QWidget(view), myView(view), myInternalView(internalView) +{ + lmbSetsBreakpoints = true; +} + +KateIconBorder::~KateIconBorder() +{ +} + +void KateIconBorder::paintLine(int i) +{ + if (!myView->myIconBorder) return; + + QPainter p(this); + + int fontHeight = myView->doc()->fontHeight; + int y = i*fontHeight - myInternalView->yPos; + p.fillRect(0, y, myInternalView->iconBorderWidth-2, fontHeight, colorGroup().background()); + p.setPen(white); + p.drawLine(myInternalView->iconBorderWidth-2, y, myInternalView->iconBorderWidth-2, y + fontHeight); + p.setPen(QColor(colorGroup().background()).dark()); + p.drawLine(myInternalView->iconBorderWidth-1, y, myInternalView->iconBorderWidth-1, y + fontHeight); + + TextLine *line = myView->doc()->getTextLine(i); + if (!line) + return; + + if (line->mark()&KateDocument::Bookmark) + p.drawPixmap(2, y, QPixmap(bookmark_xpm)); /* + if (line && (line->breakpointId() != -1)) { + if (!line->breakpointEnabled()) + p.drawPixmap(2, y, QPixmap(breakpoint_gr_xpm)); + else if (line->breakpointPending()) + p.drawPixmap(2, y, QPixmap(breakpoint_bl_xpm)); + else + p.drawPixmap(2, y, QPixmap(breakpoint_xpm)); + } + if (line->isExecutionPoint()) + p.drawPixmap(2, y, QPixmap(ddd_xpm)); */ +} + + +void KateIconBorder::paintEvent(QPaintEvent* e) +{ + if (!myView->myIconBorder) return; + + int lineStart = 0; + int lineEnd = 0; + + QRect updateR = e->rect(); + + KateDocument *doc = myView->doc(); + int h = doc->fontHeight; + int yPos = myInternalView->yPos; + if (h) { + lineStart = (yPos + updateR.y()) / h; + lineEnd = QMAX((yPos + updateR.y() + updateR.height()) / h, (int)doc->numLines()); + } + + for(int i = lineStart; i <= lineEnd; ++i) + paintLine(i); +} + + +void KateIconBorder::mousePressEvent(QMouseEvent* e) +{ + myInternalView->placeCursor( 0, e->y(), 0 ); + + KateDocument *doc = myView->doc(); + int cursorOnLine = (e->y() + myInternalView->yPos) / doc->fontHeight; + TextLine *line = doc->getTextLine(cursorOnLine); + + switch (e->button()) { + case LeftButton: + if (!line) + break; + else + { + if (line->mark()&KateDocument::Bookmark) + line->delMark (KateDocument::Bookmark); + else + line->addMark (KateDocument::Bookmark); + + doc->tagLines(cursorOnLine, cursorOnLine); + doc->updateViews(); + } + break; + /* case RightButton: + { + if (!line) + break; + KPopupMenu popup; + popup.setCheckable(true); + popup.insertTitle(i18n("Breakpoints/Bookmarks")); + int idToggleBookmark = popup.insertItem(i18n("Toggle bookmark")); + popup.insertSeparator(); + int idToggleBreakpoint = popup.insertItem(i18n("Toggle breakpoint")); + int idEditBreakpoint = popup.insertItem(i18n("Edit breakpoint")); + int idEnableBreakpoint = popup.insertItem(i18n("Disable breakpoint")); + popup.insertSeparator(); + popup.insertSeparator(); + int idLmbSetsBreakpoints = popup.insertItem(i18n("LMB sets breakpoints")); + int idLmbSetsBookmarks = popup.insertItem(i18n("LMB sets bookmarks")); + + popup.setItemChecked(idLmbSetsBreakpoints, lmbSetsBreakpoints); + popup.setItemChecked(idLmbSetsBookmarks, !lmbSetsBreakpoints); + + if (line->breakpointId() == -1) { + popup.setItemEnabled(idEditBreakpoint, false); + popup.setItemEnabled(idEnableBreakpoint, false); + popup.changeItem(idEnableBreakpoint, i18n("Enable breakpoint")); + } + int res = popup.exec(mapToGlobal(e->pos())); + if (res == idToggleBookmark) { + line->toggleBookmark(); + doc->tagLines(cursorOnLine, cursorOnLine); + doc->updateViews(); + } else if (res == idToggleBreakpoint) + emit myView->toggledBreakpoint(cursorOnLine); + else if (res == idEditBreakpoint) + emit myView->editedBreakpoint(cursorOnLine); + else if (res == idEnableBreakpoint) + emit myView->toggledBreakpointEnabled(cursorOnLine+1); + else if (res == idLmbSetsBreakpoints || res == idLmbSetsBookmarks) + lmbSetsBreakpoints = !lmbSetsBreakpoints; + break; + } + case MidButton: + line->toggleBookmark(); + doc->tagLines(cursorOnLine, cursorOnLine); + doc->updateViews(); + break; */ + default: + break; + } +} + + + diff --git a/noncore/apps/tinykate/libkate/view/kateview.h b/noncore/apps/tinykate/libkate/view/kateview.h new file mode 100644 index 0000000..2e78a3a --- a/dev/null +++ b/noncore/apps/tinykate/libkate/view/kateview.h @@ -0,0 +1,865 @@ +/*************************************************************************** + kateview.h - description + ------------------- + begin : Mon Jan 15 2001 + copyright : (C) 2001 by Christoph "Crossfire" Cullmann + (C) 2002 by Joseph Wenninger + email : crossfire@babylon2k.de + jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* + Copyright (C) 1998, 1999 Jochen Wilhelmy + digisnap@cs.tu-berlin.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef kate_view_h +#define kate_view_h + +#include "../interfaces/view.h" +#include "../interfaces/document.h" + +#include +#include +#include + + +class KateDocument; +class Highlight; + +/* +//dialog results +const int srYes = QDialog::Accepted; +const int srNo = 10; +const int srAll = 11; +const int srCancel = QDialog::Rejected; +*/ +// --- config flags --- +// indent + +enum Select_flags { + selectFlag = 0x100000, + multiSelectFlag = 0x200000 +}; +//state commands +enum State_commands { + cmToggleInsert = 1, + cmToggleVertical = 2 +}; + +class KateViewInternal; +class KateView; + +struct PointStruc { + int x; + int y; +}; + +struct VConfig { + KateView *view; + PointStruc cursor; + int cXPos; + int flags; +}; + +struct SConfig { + PointStruc cursor; + PointStruc startCursor; + int flags; + + // Set the pattern to be used for searching. + void setPattern(QString &newPattern); + + // Search the given string. + int search(QString &text, int index); + + // The length of the last match found using pattern or regExp. + int matchedLength; + +private: + QString m_pattern; + + // The regular expression corresponding to pattern. Only guaranteed valid if + // flags has sfRegularExpression set. + QRegExp m_regExp; +}; + +struct LineRange { + int start; + int end; +}; + +struct BracketMark { + PointStruc cursor; + int sXPos; + int eXPos; +}; + + +class KateIconBorder : public QWidget +{ +public: + KateIconBorder(KateView *view, class KateViewInternal *internalView); + ~KateIconBorder(); + + void paintLine(int i); + +protected: + void paintEvent(QPaintEvent* e); + void mousePressEvent(QMouseEvent* e); + +private: + + KateView *myView; + class KateViewInternal *myInternalView; + bool lmbSetsBreakpoints; +}; + +class KateViewInternal : public QWidget { + Q_OBJECT + friend class KateDocument; + friend class KateView; + friend class KateIconBorder; + + private: + long waitForPreHighlight; + int iconBorderWidth; + int iconBorderHeight; + + protected slots: + void slotPreHighlightUpdate(long line); + + public: + KateViewInternal(KateView *view, KateDocument *doc); + ~KateViewInternal(); + + virtual void doCursorCommand(VConfig &, int cmdNum); + virtual void doEditCommand(VConfig &, int cmdNum); + + void cursorLeft(VConfig &); + void cursorRight(VConfig &); + void wordLeft(VConfig &); + void wordRight(VConfig &); + void home(VConfig &); + void end(VConfig &); + void cursorUp(VConfig &); + void cursorDown(VConfig &); + void scrollUp(VConfig &); + void scrollDown(VConfig &); + void topOfView(VConfig &); + void bottomOfView(VConfig &); + void pageUp(VConfig &); + void pageDown(VConfig &); + void cursorPageUp(VConfig &); + void cursorPageDown(VConfig &); + void top(VConfig &); + void bottom(VConfig &); + void top_home(VConfig &c); + void bottom_end(VConfig &c); + + protected slots: + void changeXPos(int); + void changeYPos(int); + + protected: + void getVConfig(VConfig &); + void changeState(VConfig &); + void insLine(int line); + void delLine(int line); + void updateCursor(); + void updateCursor(PointStruc &newCursor); + void updateCursor(PointStruc &newCursor, int flags); + void clearDirtyCache(int height); + void tagLines(int start, int end, int x1, int x2); + void tagAll(); + void setPos(int x, int y); + void center(); + + void updateView(int flags); + + void paintTextLines(int xPos, int yPos); + void paintCursor(); + void paintBracketMark(); + + void placeCursor(int x, int y, int flags = 0); + bool isTargetSelected(int x, int y); + +// void doDrag(); + + virtual void focusInEvent(QFocusEvent *); + virtual void focusOutEvent(QFocusEvent *); + virtual void keyPressEvent(QKeyEvent *e); + virtual void mousePressEvent(QMouseEvent *); + virtual void mouseDoubleClickEvent(QMouseEvent *); + virtual void mouseReleaseEvent(QMouseEvent *); + virtual void mouseMoveEvent(QMouseEvent *); + virtual void wheelEvent( QWheelEvent *e ); + virtual void paintEvent(QPaintEvent *); + virtual void resizeEvent(QResizeEvent *); + virtual void timerEvent(QTimerEvent *); + + + KateView *myView; + KateDocument *myDoc; + QScrollBar *xScroll; + QScrollBar *yScroll; + KateIconBorder *leftBorder; + + int xPos; + int yPos; + + int mouseX; + int mouseY; + int scrollX; + int scrollY; + int scrollTimer; + + PointStruc cursor; + bool cursorOn; + int cursorTimer; + int cXPos; + int cOldXPos; + + int startLine; + int endLine; + + bool exposeCursor; + int updateState; + int numLines; + LineRange *lineRanges; + int newXPos; + int newYPos; + + QPixmap *drawBuffer; + + BracketMark bm; + +}; + +/** + The KateView text editor widget. It has many options, document/view + architecture and syntax highlight. + @author Jochen Wilhelmy +*/ + +class KateView : public Kate::View +{ + Q_OBJECT + friend class KateViewInternal; + friend class KateDocument; + friend class KateIconBorder; + + public: + KateView(KateDocument *doc=0L, QWidget *parent = 0L, const char * name = 0); + ~KateView(); + + virtual void setCursorPosition( int line, int col, bool mark = false ); + virtual void getCursorPosition( int *line, int *col ); + + virtual bool isOverwriteMode() const; + virtual void setOverwriteMode( bool b ); + +//status and config functions + /** + Returns the current line number, that is the line the cursor is on. + For the first line it returns 0. Signal newCurPos() is emitted on + cursor position changes. + */ + int currentLine(); + /** + Returns the current column number. It handles tab's correctly. + For the first column it returns 0. + */ + int currentColumn(); + /** + Returns the number of the character, that the cursor is on (cursor x) + */ + int currentCharNum(); + /** + Sets the current cursor position + */ + void setCursorPositionInternal(int line, int col); + /** + Returns the config flags. See the cfXXX constants in the .h file. + */ + int config();// {return configFlags;} + /** + Sets the config flags + */ + void setConfig(int); + + int tabWidth(); + void setTabWidth(int); + void setEncoding (QString e); + int undoSteps(); + void setUndoSteps(int); + + // bool isOverwriteMode(); + /** + Returns true if the document is in read only mode. + */ + bool isReadOnly(); + /** + Returns true if the document has been modified. + */ + bool isModified(); + /** + Sets the read-only flag of the document + */ + void setReadOnly(bool); + /** + Sets the modification status of the document + */ + void setModified(bool m = true); + /** + Returns true if this editor is the only owner of its document + */ + bool isLastView(); + /** + Returns the document object + */ + KateDocument *doc(); + + /* + Bit 0 : undo possible, Bit 1 : redo possible. + Used to enable/disable undo/redo menu items and toolbar buttons + */ + int undoState(); + /** + Returns the type of the next undo group. + */ + int nextUndoType(); + /** + Returns the type of the next redo group. + */ + int nextRedoType(); + /** + Returns a list of all available undo types, in undo order. + */ + void undoTypeList(QValueList &lst); + /** + Returns a list of all available redo types, in redo order. + */ + void redoTypeList(QValueList &lst); + /** + Returns a short text description of the given undo type, + which is obtained with nextUndoType(), nextRedoType(), undoTypeList(), and redoTypeList(), + suitable for display in a menu entry. It is not translated; + use i18n() before displaying this string. + */ + const char * undoTypeName(int undoType); + + QColor* getColors(); + void applyColors(); + + + public slots: + void slotUpdate(); + void slotFileStatusChanged(); + void slotNewUndo(); + void slotHighlightChanged(); + + public slots: + /** + Toggles Insert mode + */ + void toggleInsert(); + /** + Toggles "Vertical Selections" option + */ + void toggleVertical(); + signals: + /** + The cursor position has changed. Get the values with currentLine() + and currentColumn() + */ + void newCurPos(); + /** + Modified flag or config flags have changed + */ + void newStatus(); + /** + The undo/redo enable status has changed + */ + void newUndo(); + /** + The marked text state has changed. This can be used to enable/disable + cut and copy + */ + void newMarkStatus(); + + // emitted when saving a remote URL with KIO::NetAccess. In that case we have to disable the UI. + void enableUI( bool enable ); + + protected: + virtual void keyPressEvent( QKeyEvent *ev ); + + int configFlags; + + /* + * Check if the given URL already exists. Currently used by both save() and saveAs() + * + * Asks the user for permission and returns the message box result and defaults to + * KMessageBox::Yes in case of doubt + */ + +//text access + public: + /** + Gets the number of text lines; + */ + int numLines(); + /** + Gets the complete document content as string + */ + QString text(); + /** + Gets the text line where the cursor is on + */ + QString currentTextLine(); + /** + Gets a text line + */ + QString textLine(int num); + /** + Gets the word where the cursor is on + */ + QString currentWord(); + /** + Gets the word at position x, y. Can be used to find + the word under the mouse cursor + */ + QString word(int x, int y); + /** + Discard old text without warning and set new text + */ + void setText(const QString &); + /** + Insert text at the current cursor position. If length is a positive + number, it restricts the number of inserted characters + */ + virtual void insertText(const QString &, bool mark = false); + /** + Queries if there is marked text + */ + bool hasMarkedText(); + /** + Gets the marked text as string + */ + QString markedText(); + + public: + enum fileResult { OK, CANCEL, RETRY, ERROR }; + + /** + Returns true if the current document can be + discarded. If the document is modified, the user is asked if he wants + to save it. On "cancel" the function returns false. + */ + bool canDiscard(); + + public slots: + /** + Flushes the document of the text widget. The user is given + a chance to save the current document if the current document has + been modified. + */ + void flush (); + /** + Saves the file if necessary under the current file name. If the current file + name is Untitled, as it is after a call to newFile(), this routing will + call saveAs(). + */ + fileResult save(); + /** + Allows the user to save the file under a new name. This starts the + automatic highlight selection. + */ + fileResult saveAs(); + /** + Moves the marked text into the clipboard + */ + void cut() {doEditCommand(KateView::cmCut);} + /** + Copies the marked text into the clipboard + */ + void copy() {doEditCommand(KateView::cmCopy);} + /** + Inserts text from the clipboard at the actual cursor position + */ + void paste() {doEditCommand(KateView::cmPaste);} + /** + Undoes the last operation. The number of undo steps is configurable + */ + void undo() {doEditCommand(KateView::cmUndo);} + /** + Repeats an operation which has been undone before. + */ + void redo() {doEditCommand(KateView::cmRedo);} + /** + Undoes operations. + Called by slot undo(). + */ + void undoMultiple(int count); + /** + Repeats operation which have been undone before. + Called by slot redo(). + */ + void redoMultiple(int count); + /** + Displays the undo history dialog + */ + void undoHistory(); + /** + Moves the current line or the selection one position to the right + */ + void indent() {doEditCommand(KateView::cmIndent);}; + /** + Moves the current line or the selection one position to the left + */ + void unIndent() {doEditCommand(KateView::cmUnindent);}; + /** + Optimizes the selected indentation, replacing tabs and spaces as needed + */ + void cleanIndent() {doEditCommand(KateView::cmCleanIndent);}; + /** + Selects all text + */ + void selectAll() {doEditCommand(KateView::cmSelectAll);} + /** + Deselects all text + */ + void deselectAll() {doEditCommand(KateView::cmDeselectAll);} + /** + Inverts the current selection + */ + void invertSelection() {doEditCommand(KateView::cmInvertSelection);} + /** + comments out current line + */ + void comment() {doEditCommand(KateView::cmComment);}; + /** + removes comment signs in the current line + */ + void uncomment() {doEditCommand(KateView::cmUncomment);}; + + void keyReturn() {doEditCommand(KateView::cmReturn);}; + void keyDelete() {doEditCommand(KateView::cmDelete);}; + void backspace() {doEditCommand(KateView::cmBackspace);}; + void killLine() {doEditCommand(KateView::cmKillLine);}; + +// cursor commands... + + void cursorLeft() {doCursorCommand(KateView::cmLeft);}; + void shiftCursorLeft() {doCursorCommand(KateView::cmLeft | selectFlag);}; + void cursorRight() {doCursorCommand(KateView::cmRight);} + void shiftCursorRight() {doCursorCommand(KateView::cmRight | selectFlag);} + void wordLeft() {doCursorCommand(KateView::cmWordLeft);}; + void shiftWordLeft() {doCursorCommand(KateView::cmWordLeft | selectFlag);}; + void wordRight() {doCursorCommand(KateView::cmWordRight);}; + void shiftWordRight() {doCursorCommand(KateView::cmWordRight | selectFlag);}; + void home() {doCursorCommand(KateView::cmHome);}; + void shiftHome() {doCursorCommand(KateView::cmHome | selectFlag);}; + void end() {doCursorCommand(KateView::cmEnd);}; + void shiftEnd() {doCursorCommand(KateView::cmEnd | selectFlag);}; + void up() {doCursorCommand(KateView::cmUp);}; + void shiftUp() {doCursorCommand(KateView::cmUp | selectFlag);}; + void down() {doCursorCommand(KateView::cmDown);}; + void shiftDown() {doCursorCommand(KateView::cmDown | selectFlag);}; + void scrollUp() {doCursorCommand(KateView::cmScrollUp);}; + void scrollDown() {doCursorCommand(KateView::cmScrollDown);}; + void topOfView() {doCursorCommand(KateView::cmTopOfView);}; + void bottomOfView() {doCursorCommand(KateView::cmBottomOfView);}; + void pageUp() {doCursorCommand(KateView::cmPageUp);}; + void shiftPageUp() {doCursorCommand(KateView::cmPageUp | selectFlag);}; + void pageDown() {doCursorCommand(KateView::cmPageDown);}; + void shiftPageDown() {doCursorCommand(KateView::cmPageDown | selectFlag);}; + void top() {doCursorCommand(KateView::cmTop);}; + void shiftTop() {doCursorCommand(KateView::cmTop | selectFlag);}; + void bottom() {doCursorCommand(KateView::cmBottom);}; + void shiftBottom() {doCursorCommand(KateView::cmBottom | selectFlag);}; + +//search/replace functions + public slots: + /** + Presents a search dialog to the user + */ + void find(); + /** + Presents a replace dialog to the user + */ + void replace(); + + /** + Presents a "Goto Line" dialog to the user + */ + void gotoLine(); + protected: + void initSearch(SConfig &, int flags); + void continueSearch(SConfig &); + void findAgain(SConfig &); + void replaceAgain(); + void doReplaceAction(int result, bool found = false); + void exposeFound(PointStruc &cursor, int slen, int flags, bool replace); + void deleteReplacePrompt(); + bool askReplaceEnd(); + protected slots: + void replaceSlot(); + protected: + int searchFlags; + int replaces; + SConfig s; + QDialog *replacePrompt; + +//right mouse button popup menu & bookmark menu + public: + /** + Install a Popup Menu. The Popup Menu will be activated on + a right mouse button press event. + */ + void installPopup(QPopupMenu *rmb_Menu); + + protected: + QPopupMenu *rmbMenu; + + signals: + void bookAddChanged(bool enabled); + void bookClearChanged(bool enabled); + +//config file / session management functions + public: + /** + Reads config entries + */ + void readConfig(); + /** + Writes config entries i + */ + void writeConfig(); + /** + Reads session config out of the KConfig object. This also includes + the actual cursor position and the bookmarks. + */ + void readSessionConfig(KConfig *); + /** + Writes session config into the KConfig object + */ + void writeSessionConfig(KConfig *); + + + public: + void setDontChangeHlOnSave(); + + + // syntax highlight + public slots: + /** + Presents the setup dialog to the user + */ + void configDialog (); + /** + Gets the highlight number + */ + int getHl(); + /** + Sets the highlight number n + */ + void setHl(int n); + /** + Get the end of line mode (Unix, Macintosh or Dos) + */ + int getEol(); + /** + Set the end of line mode (Unix, Macintosh or Dos) + */ + void setEol(int); + +//internal + protected: + virtual void paintEvent(QPaintEvent *); + virtual void resizeEvent(QResizeEvent *); + + void doCursorCommand(int cmdNum); + void doEditCommand(int cmdNum); + + KateViewInternal *myViewInternal; + KateDocument *myDoc; + + + // some kwriteview stuff + protected: + void insLine(int line) { myViewInternal->insLine(line); }; + void delLine(int line) { myViewInternal->delLine(line); }; + void updateCursor() { myViewInternal->updateCursor(); }; + void updateCursor(PointStruc &newCursor) { myViewInternal->updateCursor(newCursor); }; + void updateCursor(PointStruc &newCursor, int flags) { myViewInternal->updateCursor(newCursor, flags); }; + + void clearDirtyCache(int height) { myViewInternal->clearDirtyCache(height); }; + void tagLines(int start, int end, int x1, int x2) { myViewInternal->tagLines(start, end, x1, x2); }; + void tagAll() { myViewInternal->tagAll(); }; + void setPos(int x, int y) { myViewInternal->setPos(x, y); }; + void center() { myViewInternal->center(); }; + + void updateView(int flags) { myViewInternal->updateView(flags); }; + + + + public: + enum Config_flags { + cfAutoIndent= 0x1, + cfBackspaceIndents= 0x2, + cfWordWrap= 0x4, + cfReplaceTabs= 0x8, + cfRemoveSpaces = 0x10, + cfWrapCursor= 0x20, + cfAutoBrackets= 0x40, + cfPersistent= 0x80, + cfKeepSelection= 0x100, + cfVerticalSelect= 0x200, + cfDelOnInput= 0x400, + cfXorSelect= 0x800, + cfOvr= 0x1000, + cfMark= 0x2000, + cfGroupUndo= 0x4000, + cfKeepIndentProfile= 0x8000, + cfKeepExtraSpaces= 0x10000, + cfMouseAutoCopy= 0x20000, + cfSingleSelection= 0x40000, + cfTabIndents= 0x80000, + cfPageUDMovesCursor= 0x100000, + cfShowTabs= 0x200000, + cfSpaceIndent= 0x400000, + cfSmartHome = 0x800000}; + + enum Dialog_results { + srYes=QDialog::Accepted, + srNo=10, + srAll, + srCancel=QDialog::Rejected}; + +//search flags + enum Search_flags { + sfCaseSensitive=1, + sfWholeWords=2, + sfFromBeginning=4, + sfBackward=8, + sfSelected=16, + sfPrompt=32, + sfReplace=64, + sfAgain=128, + sfWrapped=256, + sfFinished=512, + sfRegularExpression=1024}; + +//update flags + enum Update_flags { + ufDocGeometry=1, + ufUpdateOnScroll=2, + ufPos=4}; + +//load flags + enum Load_flags { + lfInsert=1, + lfNewFile=2, + lfNoAutoHl=4}; + +//cursor movement commands + enum Cursor_commands + { cmLeft,cmRight,cmWordLeft,cmWordRight, + cmHome,cmEnd,cmUp,cmDown, + cmScrollUp,cmScrollDown,cmTopOfView,cmBottomOfView, + cmPageUp,cmPageDown,cmCursorPageUp,cmCursorPageDown, + cmTop,cmBottom}; +//edit commands + enum Edit_commands { + cmReturn=1,cmDelete,cmBackspace,cmKillLine,cmUndo, + cmRedo,cmCut,cmCopy,cmPaste,cmIndent,cmUnindent,cmCleanIndent, + cmSelectAll,cmDeselectAll,cmInvertSelection,cmComment, + cmUncomment}; +//find commands + enum Find_commands { cmFind=1,cmReplace,cmFindAgain,cmGotoLine}; + + public: + void setActive (bool b); + bool isActive (); + + private: + bool active; + bool myIconBorder; + QList list; + + public slots: + virtual void setFocus (); + void findAgain(bool back=false); + void findAgain () { findAgain(false); }; + void findPrev () { findAgain(true); }; + + protected: + bool eventFilter(QObject* o, QEvent* e); + + signals: + void gotFocus (KateView *); + + public slots: + void slotEditCommand (); + void setIconBorder (bool enable); + void toggleIconBorder (); + void gotoMark (Kate::Mark *mark); + void toggleBookmark (); + void clearBookmarks (); + + public: + bool iconBorder() { return myIconBorder; } ; + + private slots: + void bookmarkMenuAboutToShow(); + void gotoBookmark (int n); + + public: + Kate::Document *getDoc () + { return (Kate::Document*) myDoc; }; + + public slots: + int getHlCount (); + QString getHlName (int); + QString getHlSection (int); + + void slotIncFontSizes (); + void slotDecFontSizes (); + + protected: + uint myViewID; + static uint uniqueID; +}; + +#endif + + + + + + diff --git a/noncore/apps/tinykate/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 @@ +/*************************************************************************** + kateviewdialog.cpp - description + ------------------- + copyright : (C) 2001 by The Kate Team + (C) 2002 by Joseph Wenninger + email : kwrite-devel@kde.org + jowenn@kde.org + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +// Dialogs + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../document/katedocument.h" +#include "kateviewdialog.h" + +SearchDialog::SearchDialog( QWidget *parent, QStringList &searchFor, QStringList &replaceWith, int flags ) + : KDialogBase( parent, 0L, true, i18n( "Find Text" ), Ok | Cancel, Ok ) + , m_replace( 0L ) +{ + QWidget *page = new QWidget( this ); + setMainWidget( page ); + + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + + m_search = new QComboBox( true, page ); + m_search->insertStringList( searchFor ); + m_search->setMinimumWidth( m_search->sizeHint().width() ); + m_search->lineEdit()->selectAll(); + QLabel *label = new QLabel( m_search, i18n( "&Text To Find:" ), page ); + m_optRegExp = new QCheckBox( i18n( "Regular Expression" ), page ); + topLayout->addWidget( label ); + topLayout->addWidget( m_search ); + topLayout->addWidget( m_optRegExp ); + + if( flags & KateView::sfReplace ) + { + // make it a replace dialog + setCaption( i18n( "Replace Text" ) ); + m_replace = new QComboBox( true, page ); + m_replace->insertStringList( replaceWith ); + m_replace->setMinimumWidth( m_search->sizeHint().width() ); + label = new QLabel( m_replace, i18n( "&Replace With:" ), page ); + //m_optPlaceholders = new QCheckBox( i18n( "&Use Placeholders" ), page ); + topLayout->addWidget( label ); + topLayout->addWidget( m_replace ); + //topLayout->addWidget( m_optPlaceholders ); + } + + QGroupBox *group = new QGroupBox( i18n( "Options" ), page ); + topLayout->addWidget( group, 10 ); + + QGridLayout *gbox = new QGridLayout( group, 5, 2, spacingHint() ); + gbox->addRowSpacing( 0, fontMetrics().lineSpacing() ); + gbox->setRowStretch( 4, 10 ); + + m_opt1 = new QCheckBox( i18n( "C&ase Sensitive" ), group ); + gbox->addWidget( m_opt1, 1, 0 ); + + m_opt2 = new QCheckBox(i18n("&Whole Words Only" ), group ); + gbox->addWidget( m_opt2, 2, 0 ); + + m_opt3 = new QCheckBox(i18n("&From Beginning" ), group ); + gbox->addWidget( m_opt3, 3, 0 ); + + m_opt4 = new QCheckBox(i18n("Find &Backwards" ), group ); + gbox->addWidget( m_opt4, 1, 1 ); + + m_opt5 = new QCheckBox(i18n("&Selected Text" ), group ); + gbox->addWidget( m_opt5, 2, 1 ); + + m_opt1->setChecked( flags & KateView::sfCaseSensitive ); + m_opt2->setChecked( flags & KateView::sfWholeWords ); + m_opt3->setChecked( flags & KateView::sfFromBeginning ); + m_optRegExp->setChecked( flags & KateView::sfRegularExpression ); + m_opt4->setChecked( flags & KateView::sfBackward ); + m_opt5->setChecked( flags & KateView::sfSelected ); + + if( m_replace ) + { + m_opt6 = new QCheckBox( i18n( "&Prompt On Replace" ), group ); + m_opt6->setChecked( flags & KateView::sfPrompt ); + gbox->addWidget( m_opt6, 3, 1 ); + } + + m_search->setFocus(); +} + +QString SearchDialog::getSearchFor() +{ + return m_search->currentText(); +} + +QString SearchDialog::getReplaceWith() +{ + return m_replace->currentText(); +} + +int SearchDialog::getFlags() +{ + int flags = 0; + + if( m_opt1->isChecked() ) flags |= KateView::sfCaseSensitive; + if( m_opt2->isChecked() ) flags |= KateView::sfWholeWords; + if( m_opt3->isChecked() ) flags |= KateView::sfFromBeginning; + if( m_opt4->isChecked() ) flags |= KateView::sfBackward; + if( m_opt5->isChecked() ) flags |= KateView::sfSelected; + if( m_optRegExp->isChecked() ) flags |= KateView::sfRegularExpression; + if( m_replace ) + { + if( m_opt6->isChecked() ) + flags |= KateView::sfPrompt; + + flags |= KateView::sfReplace; + } + + return flags; +} + +void SearchDialog::slotOk() +{ + if ( !m_search->currentText().isEmpty() ) + { + if ( !m_optRegExp->isChecked() ) + { + accept(); + } + else + { + // Check for a valid regular expression. + + QRegExp regExp( m_search->currentText() ); + + if ( regExp.isValid() ) + accept(); + } + } +} + +void SearchDialog::setSearchText( const QString &searchstr ) + { + m_search->insertItem( searchstr, 0 ); + m_search->setCurrentItem( 0 ); + m_search->lineEdit()->selectAll(); + } + +// this dialog is not modal +ReplacePrompt::ReplacePrompt( QWidget *parent ) + : KDialogBase(parent, 0L, false, i18n( "Replace Text" ), + User3 | User2 | User1 | Close, User3, true, + i18n("&All"), i18n("&No"), i18n("&Yes")) { + + QWidget *page = new QWidget(this); + setMainWidget(page); + + QBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + QLabel *label = new QLabel(i18n("Replace this occurence?"),page); + topLayout->addWidget(label ); +} + +void ReplacePrompt::slotUser1( void ) { // All + done(KateView::srAll); +} + +void ReplacePrompt::slotUser2( void ) { // No + done(KateView::srNo); +} + +void ReplacePrompt::slotUser3( void ) { // Yes + accept(); +} + +void ReplacePrompt::done(int r) { + setResult(r); + emit clicked(); +} + +void ReplacePrompt::closeEvent(QCloseEvent *) { + reject(); +} + +GotoLineDialog::GotoLineDialog(QWidget *parent, int line, int max) + : KDialogBase(parent, 0L, true, i18n("Goto Line"), Ok | Cancel, Ok) { + + QWidget *page = new QWidget(this); + setMainWidget(page); + + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); + e1 = new QSpinBox(page); + e1->setMinValue(1); + e1->setMaxValue(max); + e1->setValue((int)line); + + QLabel *label = new QLabel( e1,i18n("&Goto Line:"), page ); + topLayout->addWidget(label); + topLayout->addWidget(e1); + topLayout->addSpacing(spacingHint()); // A little bit extra space + topLayout->addStretch(10); + e1->setFocus(); +} + +int GotoLineDialog::getLine() { + return e1->value(); +} + +const int IndentConfigTab::flags[] = {KateView::cfAutoIndent, KateView::cfSpaceIndent, + KateView::cfBackspaceIndents,KateView::cfTabIndents, KateView::cfKeepIndentProfile, KateView::cfKeepExtraSpaces}; + +IndentConfigTab::IndentConfigTab(QWidget *parent, KateView *view) + : QWidget(parent, 0L) +{ + QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() ); + int configFlags = view->config(); + + opt[0] = new QCheckBox(i18n("&Auto Indent"), this); + layout->addWidget(opt[0], 0, AlignLeft); + opt[0]->setChecked(configFlags & flags[0]); + + opt[1] = new QCheckBox(i18n("Indent With &Spaces"), this); + layout->addWidget(opt[1], 0, AlignLeft); + opt[1]->setChecked(configFlags & flags[1]); + + opt[2] = new QCheckBox(i18n("&Backspace Key Indents"), this); + layout->addWidget(opt[2], 0, AlignLeft); + opt[2]->setChecked(configFlags & flags[2]); + + opt[3] = new QCheckBox(i18n("&Tab Key Indents"), this); + layout->addWidget(opt[3], 0, AlignLeft); + opt[3]->setChecked(configFlags & flags[3]); + + opt[4] = new QCheckBox(i18n("Keep Indent &Profile"), this); + layout->addWidget(opt[4], 0, AlignLeft); +// opt[4]->setChecked(configFlags & flags[4]); + opt[4]->setChecked(true); + opt[4]->hide(); + + opt[5] = new QCheckBox(i18n("&Keep Extra Spaces"), this); + layout->addWidget(opt[5], 0, AlignLeft); + opt[5]->setChecked(configFlags & flags[5]); + + layout->addStretch(); + + // What is this? help + QWhatsThis::add(opt[0], i18n("When Auto indent is on, KateView will indent new lines to equal the indent on the previous line.

If the previous line is blank, the nearest line above with text is used")); + QWhatsThis::add(opt[1], i18n("Check this if you want to indent with spaces rather than tabs.
A Tab will be converted to Tab-width as set in the edit options")); + QWhatsThis::add(opt[2], i18n("This allows the backspace key to be used to indent.")); + QWhatsThis::add(opt[3], i18n("This allows the tab key to be used to indent.")); + QWhatsThis::add(opt[4], i18n("This retains current indentation settings for future documents.")); + QWhatsThis::add(opt[5], i18n("Indentations of more than the selected number of spaces will not be shortened.")); +} + +void IndentConfigTab::getData(KateView *view) { + int configFlags, z; + + configFlags = view->config(); + for (z = 0; z < numFlags; z++) { + configFlags &= ~flags[z]; + if (opt[z]->isChecked()) configFlags |= flags[z]; + } + view->setConfig(configFlags); +} + +const int SelectConfigTab::flags[] = {KateView::cfPersistent, KateView::cfDelOnInput, + KateView::cfMouseAutoCopy, KateView::cfSingleSelection, KateView::cfVerticalSelect, KateView::cfXorSelect}; + +SelectConfigTab::SelectConfigTab(QWidget *parent, KateView *view) + : QWidget(parent, 0L) +{ + QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() ); + int configFlags = view->config(); + + opt[0] = new QCheckBox(i18n("&Persistent Selections"), this); + layout->addWidget(opt[0], 0, AlignLeft); + opt[0]->setChecked(configFlags & flags[0]); + + opt[1] = new QCheckBox(i18n("&Overwrite Selections"), this); + layout->addWidget(opt[1], 0, AlignLeft); + opt[1]->setChecked(configFlags & flags[1]); + + opt[2] = new QCheckBox(i18n("Mouse &Autocopy"), this); + layout->addWidget(opt[2], 0, AlignLeft); + opt[2]->setChecked(configFlags & flags[2]); + + opt[3] = new QCheckBox(i18n("&X11-like Single Selection"), this); + layout->addWidget(opt[3], 0, AlignLeft); + opt[3]->setChecked(configFlags & flags[3]); + + opt[4] = new QCheckBox(i18n("&Vertical Selections"), this); + layout->addWidget(opt[4], 0, AlignLeft); + opt[4]->setChecked(configFlags & flags[4]); + + opt[5] = new QCheckBox(i18n("&Toggle Old"), this); + layout->addWidget(opt[5], 0, AlignLeft); + opt[5]->setChecked(configFlags & flags[5]); + + layout->addStretch(); + + // What is this? help + 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.

Note: If the Overwrite Selections option is activated then any typed character input or paste operation will replace the selected text.")); + QWhatsThis::add(opt[1], i18n("When this is on, any keyed character input or paste operation will replace the selected text.")); + QWhatsThis::add(opt[2], i18n("When this is on, any text selected with the mouse will be automatically copied to the clipboard.")); + QWhatsThis::add(opt[3], i18n("Not implemented yet.")); + QWhatsThis::add(opt[4], i18n("Enabling this allows you to make vertical selections.")); + QWhatsThis::add(opt[5], i18n("Not yet implemented.")); +} + +void SelectConfigTab::getData(KateView *view) { + int configFlags, z; + + configFlags = view->config(); + for (z = 0; z < numFlags; z++) { + configFlags &= ~flags[z]; // clear flag + if (opt[z]->isChecked()) configFlags |= flags[z]; // set flag if checked + } + view->setConfig(configFlags); +} + +const int EditConfigTab::flags[] = {KateView::cfWordWrap, KateView::cfReplaceTabs, KateView::cfRemoveSpaces, + KateView::cfAutoBrackets, KateView::cfGroupUndo, KateView::cfShowTabs, KateView::cfSmartHome, + KateView::cfPageUDMovesCursor, KateView::cfWrapCursor}; + +EditConfigTab::EditConfigTab(QWidget *parent, KateView *view) + : QWidget(parent, 0L) { + + QHBoxLayout *mainLayout; + QVBoxLayout *cbLayout, *leLayout; + int configFlags; + + mainLayout = new QHBoxLayout(this, 0, KDialog::spacingHint() ); + + // checkboxes + cbLayout = new QVBoxLayout( mainLayout ); + configFlags = view->config(); + + opt[0] = new QCheckBox(i18n("&Word wrap"), this); + cbLayout->addWidget(opt[0], 0, AlignLeft); + opt[0]->setChecked(view->doc()->wordWrap()); + + opt[1] = new QCheckBox(i18n("Replace &tabs with spaces"), this); + cbLayout->addWidget(opt[1], 0, AlignLeft); + opt[1]->setChecked(configFlags & flags[1]); + + opt[2] = new QCheckBox(i18n("&Remove trailing spaces"), this); + cbLayout->addWidget(opt[2], 0, AlignLeft); + opt[2]->setChecked(configFlags & flags[2]); + + opt[3] = new QCheckBox(i18n("&Auto brackets"), this); + cbLayout->addWidget(opt[3], 0, AlignLeft); + opt[3]->setChecked(configFlags & flags[3]); + + opt[4] = new QCheckBox(i18n("Group &undos"), this); + cbLayout->addWidget(opt[4], 0, AlignLeft); + opt[4]->setChecked(configFlags & flags[4]); + + opt[5] = new QCheckBox(i18n("&Show tabs"), this); + cbLayout->addWidget(opt[5], 0, AlignLeft); + opt[5]->setChecked(configFlags & flags[5]); + + opt[6] = new QCheckBox(i18n("Smart &home"), this); + cbLayout->addWidget(opt[6], 0, AlignLeft); + opt[6]->setChecked(configFlags & flags[6]); + + opt[7] = new QCheckBox(i18n("&Page up/down moves cursor"), this); + cbLayout->addWidget(opt[7], 0, AlignLeft); + opt[7]->setChecked(configFlags & flags[7]); + + opt[8] = new QCheckBox(i18n("Wrap &cursor"), this); + cbLayout->addWidget(opt[8], 0, AlignLeft); + opt[8]->setChecked(configFlags & flags[8]); + + cbLayout->addStretch(); + + // edit lines + leLayout = new QVBoxLayout(); + mainLayout->addLayout(leLayout,10); + + e1 = new QSpinBox(this); + e1->setMinValue(20); + e1->setMaxValue( 200); + e1->setValue((int)(view->doc()->wordWrapAt())); +#warning fixme e1->setLabel(i18n("Wrap Words At:")); + + e2 = new QSpinBox(this); + e2->setMinValue(1); + e2->setMaxValue(16); + e2->setValue((int)view->tabWidth()); + +#warning fixme e2->setLabel(i18n("Tab/Indent Width:")); + + e3 = new QSpinBox(this); + e3->setMinValue(5); + e3->setMaxValue( 30000); +#warning fixme e3->setLabel(i18n("Undo steps:")); + e3->setValue((int)view->undoSteps()); + + leLayout->addWidget(e1, 0, AlignLeft); + leLayout->addWidget(e2, 0, AlignLeft); + leLayout->addWidget(e3, 0, AlignLeft); + + + QVBox *box = new QVBox (this); + leLayout->addWidget (box, 0, AlignLeft); + + new QLabel (i18n("Encoding:"), box); + + encoding = new QComboBox(box); +#warning fixme +#if 0 + encoding->insertStringList (KGlobal::charsets()->availableEncodingNames()); + encoding->setCurrentItem (KGlobal::charsets()->availableEncodingNames().findIndex(view->doc()->encoding())); +#endif + leLayout->addStretch(); + + // What is this? help + 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.

NOTE: Word Wrap will not change existing lines or wrap them for easy reading as in some applications.")); + 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.")); + QWhatsThis::add(opt[1], i18n("KateView will replace any tabs with the number of spaces indicated in the Tab Width: entry.")); + 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.")); + QWhatsThis::add(opt[2], i18n("KateView will automatically eliminate extra spaces at the ends of lines of text.")); + 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.")); + QWhatsThis::add(opt[4], i18n("Checking this will cause sequences of similar actions to be undone at once.")); + QWhatsThis::add(opt[5], i18n("The editor will display a symbol to indicate the presence of a tab in the text.")); + QWhatsThis::add(opt[6], i18n("Not yet implemented.")); + 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.

If not selected, it will remain at it's relative position in the visible text.")); + QWhatsThis::add(e3, i18n("Sets the number of undo/redo steps to record. More steps uses more memory.")); + QWhatsThis::add(opt[8], i18n("When on, moving the insertion cursor using the Left and Right keys will go on to previous/next line at beginning/end of the line, similar to most editors.

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.")); +} + +void EditConfigTab::getData(KateView *view) +{ + int configFlags, z; + + configFlags = view->config(); + for (z = 1; z < numFlags; z++) { + configFlags &= ~flags[z]; + if (opt[z]->isChecked()) configFlags |= flags[z]; + } + view->setConfig(configFlags); + + view->setEncoding (encoding->currentText()); + view->doc()->setWordWrapAt(e1->value()); + view->doc()->setWordWrap (opt[0]->isChecked()); + view->setTabWidth(e2->value()); + view->setUndoSteps(e3->value()); +} + +ColorConfig::ColorConfig( QWidget *parent, char *name ) + : QWidget( parent, name ) +{ + QGridLayout *glay = new QGridLayout( this, 6, 2, 0, KDialog::spacingHint()); + glay->setColStretch(1,1); + glay->setRowStretch(5,1); + + QLabel *label; + + label = new QLabel( i18n("Background:"), this); + label->setAlignment( AlignRight|AlignVCenter ); + m_back = new KColorButton( this ); + glay->addWidget( label, 0, 0 ); + glay->addWidget( m_back, 0, 1 ); + + label = new QLabel( i18n("Selected:"), this); + label->setAlignment( AlignRight|AlignVCenter ); + m_selected = new KColorButton( this ); + glay->addWidget( label, 2, 0 ); + glay->addWidget( m_selected, 2, 1 ); + + // QWhatsThis help + QWhatsThis::add(m_back, i18n("Sets the background color of the editing area")); + QWhatsThis::add(m_selected, i18n("Sets the background color of the selection. To set the text color for selected text, use the "Configure Highlighting" dialog.")); +} + + +ColorConfig::~ColorConfig() +{ +} + +void ColorConfig::setColors(QColor *colors) +{ + m_back->setColor( colors[0] ); + m_selected->setColor( colors[1] ); +} + +void ColorConfig::getColors(QColor *colors) +{ + colors[0] = m_back->color(); + colors[1] = m_selected->color(); +} + +FontConfig::FontConfig( QWidget *parent, char *name ) + : QWidget( parent, name ) +{ + // sizemanagment + QGridLayout *grid = new QGridLayout( this, 1, 1 ); +#if 0 + m_fontchooser = new KFontChooser ( this ); + m_fontchooser->enableColumn(KFontChooser::StyleList, false); + grid->addWidget( m_fontchooser, 0, 0); + + connect (m_fontchooser, SIGNAL (fontSelected( const QFont & )), this, SLOT (slotFontSelected( const QFont & ))); +#endif +} + +FontConfig::~FontConfig() +{ +} + +void FontConfig::setFont ( const QFont &font ) +{ +#if 0 + m_fontchooser->setFont (font); + myFont = font; +#endif +} + +void FontConfig::slotFontSelected( const QFont &font ) +{ + myFont = font; +} + + + + 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 @@ +/*************************************************************************** + kateviewdialog.h - description + ------------------- + copyright : (C) 2001 by The Kate Team + (C) 2002 by Joseph Wenninger + email : kwrite-devel@kde.org + jowenn@kde.org + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +// Dialogs + +#ifndef _KWDIALOG_H_ +#define _KWDIALOG_H_ + + +class QCheckBox; +class QLineEdit; +class QPushButton; +class QRadioButton; +class QSpinBox; +class KColorButton; +class QComboBox; + +#include +#include "kateview.h" + +class SearchDialog : public KDialogBase +{ + Q_OBJECT + + public: + SearchDialog( QWidget *parent, QStringList &searchFor, QStringList &replaceWith, int flags ); + QString getSearchFor(); + QString getReplaceWith(); + int getFlags(); + void setSearchText( const QString &searchstr ); + + protected slots: + void slotOk(); + + protected: + QComboBox *m_search; + QComboBox *m_replace; + QCheckBox *m_opt1; + QCheckBox *m_opt2; + QCheckBox *m_opt3; + QCheckBox *m_optRegExp; + QCheckBox *m_opt4; + QCheckBox *m_opt5; + QCheckBox *m_opt6; +}; + +class ReplacePrompt : public KDialogBase +{ + Q_OBJECT + + public: + + ReplacePrompt(QWidget *parent); + + signals: + + void clicked(); + + protected slots: + + void slotUser1( void ); // All + void slotUser2( void ); // No + void slotUser3( void ); // Yes + virtual void done(int); + + protected: + + void closeEvent(QCloseEvent *); +}; + +class GotoLineDialog : public KDialogBase +{ + Q_OBJECT + + public: + + GotoLineDialog(QWidget *parent, int line, int max); + int getLine(); + + protected: + + QSpinBox *e1; + QPushButton *btnOK; +}; + +class IndentConfigTab : public QWidget +{ + Q_OBJECT + + public: + + IndentConfigTab(QWidget *parent, KateView *); + void getData(KateView *); + + protected: + + static const int numFlags = 6; + static const int flags[numFlags]; + QCheckBox *opt[numFlags]; +}; + +class SelectConfigTab : public QWidget +{ + Q_OBJECT + + public: + + SelectConfigTab(QWidget *parent, KateView *); + void getData(KateView *); + + protected: + + static const int numFlags = 6; + static const int flags[numFlags]; + QCheckBox *opt[numFlags]; +}; + +class EditConfigTab : public QWidget +{ + Q_OBJECT + + public: + + EditConfigTab(QWidget *parent, KateView *); + void getData(KateView *); + + protected: + + static const int numFlags = 9; + static const int flags[numFlags]; + QCheckBox *opt[numFlags]; + QComboBox *encoding; + + + QSpinBox *e1; + QSpinBox *e2; + QSpinBox *e3; +}; + +class ColorConfig : public QWidget +{ + Q_OBJECT + +public: + + ColorConfig( QWidget *parent = 0, char *name = 0 ); + ~ColorConfig(); + + void setColors( QColor * ); + void getColors( QColor * ); + +private: + + KColorButton *m_back; + KColorButton *m_selected; +}; + +class FontConfig : public QWidget +{ + Q_OBJECT + +public: + + FontConfig( QWidget *parent = 0, char *name = 0 ); + ~FontConfig(); + + void setFont ( const QFont &font ); + QFont getFont ( ) { return myFont; }; + + private: +// class KFontChooser *m_fontchooser; + QFont myFont; + + private slots: + void slotFontSelected( const QFont &font ); +}; + + +#endif //_KWDIALOG_H_ diff --git a/noncore/apps/tinykate/main.cpp b/noncore/apps/tinykate/main.cpp new file mode 100644 index 0000000..e92df69 --- a/dev/null +++ b/noncore/apps/tinykate/main.cpp @@ -0,0 +1,29 @@ +/*************************************************************************** + main.cpp + ------------------- + begin : November 2002 + copyright : (C) 2002 by Joseph Wenninger + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation. * + * ONLY VERSION 2 OF THE LICENSE IS APPLICABLE * + * * + ***************************************************************************/ +#include +#include +#include "tinykate.h" + + +int main( int argc, char ** argv ) +{ + QPEApplication a( argc, argv ); + + TinyKate *m = new TinyKate(); + a.setMainWidget( m ); + m->showMaximized(); + return a.exec(); +} diff --git a/noncore/apps/tinykate/pics/edit-redo.xpm b/noncore/apps/tinykate/pics/edit-redo.xpm new file mode 100644 index 0000000..7557ac5 --- a/dev/null +++ b/noncore/apps/tinykate/pics/edit-redo.xpm @@ -0,0 +1,90 @@ +/* XPM */ +static char * edit_redo_xpm[] = { +"18 17 70 1", +" c None", +". c #1E472E", +"+ c #234E33", +"@ c #1B4029", +"# c #1B422A", +"$ c #AFBEBA", +"% c #DBEADF", +"& c #C1CECC", +"* c #214A30", +"= c #224B31", +"- c #163321", +"; c #BFD0C8", +"> c #90BD9F", +", c #227D37", +"' c #C0D1C9", +") c #245135", +"! c #153220", +"~ c #BDCEC7", +"{ c #2F9645", +"] c #3BB057", +"^ c #43BA5C", +"/ c #224B30", +"( c #173A23", +"_ c #143120", +": c #38774E", +"< c #1E4335", +"[ c #0B281E", +"} c #143D29", +"| c #3FAF57", +"1 c #42B75B", +"2 c #7BA08A", +"3 c #0F2417", +"4 c #081914", +"5 c #050E0D", +"6 c #123926", +"7 c #36A34D", +"8 c #9DC6AA", +"9 c #88AB9C", +"0 c #C2DBCA", +"a c #040B06", +"b c #0A1F18", +"c c #0D3525", +"d c #2A8F3D", +"e c #CFE0D4", +"f c #0A1910", +"g c #0D2419", +"h c #030C0B", +"i c #041714", +"j c #259039", +"k c #3E9951", +"l c #B2D1BC", +"m c #03090A", +"n c #071112", +"o c #55AE72", +"p c #5AB975", +"q c #5AA77B", +"r c #468166", +"s c #000001", +"t c #10211F", +"u c #03080A", +"v c #010003", +"w c #020005", +"x c #000000", +"y c #14311F", +"z c #050B0C", +"A c #162D26", +"B c #050D0E", +"C c #142724", +"D c #090F10", +"E c #050A0C", +" ", +" ", +" ..+ ", +" @#$%&*= ", +" -;>,,,%'* ) ", +" !~,,{]^,,%/ )( ", +" _,:<[[}|1,%*)2( ", +"3,)4 567,890( ", +"a,b c7,de( ", +"fgh i,jkl( ", +" mn 4,opqr( ", +" stu vvvwvvxy ", +" zA5 ", +" BCD ", +" sEs ", +" ", +" "}; diff --git a/noncore/apps/tinykate/pics/edit-undo.xpm b/noncore/apps/tinykate/pics/edit-undo.xpm new file mode 100644 index 0000000..17a1f30 --- a/dev/null +++ b/noncore/apps/tinykate/pics/edit-undo.xpm @@ -0,0 +1,90 @@ +/* XPM */ +static char * edit_undo_xpm[] = { +"18 17 70 1", +" c None", +". c #234E33", +"+ c #1E472E", +"@ c #224B31", +"# c #214A30", +"$ c #C1CECC", +"% c #DBEADF", +"& c #AFBEBA", +"* c #1B422A", +"= c #1B4029", +"- c #245135", +"; c #C0D1C9", +"> c #227D37", +", c #90BD9F", +"' c #BFD0C8", +") c #163321", +"! c #173A23", +"~ c #224B30", +"{ c #43BA5C", +"] c #3BB057", +"^ c #2F9645", +"/ c #BDCEC7", +"( c #153220", +"_ c #7BA08A", +": c #42B75B", +"< c #3FAF57", +"[ c #143D29", +"} c #0B281E", +"| c #1E4335", +"1 c #38774E", +"2 c #143120", +"3 c #C2DBCA", +"4 c #88AB9C", +"5 c #9DC6AA", +"6 c #36A34D", +"7 c #123926", +"8 c #050E0D", +"9 c #081914", +"0 c #0F2417", +"a c #CFE0D4", +"b c #2A8F3D", +"c c #0D3525", +"d c #0A1F18", +"e c #040B06", +"f c #B2D1BC", +"g c #3E9951", +"h c #259039", +"i c #041714", +"j c #030C0B", +"k c #0D2419", +"l c #0A1910", +"m c #468166", +"n c #5AA77B", +"o c #5AB975", +"p c #55AE72", +"q c #071112", +"r c #03090A", +"s c #14311F", +"t c #000000", +"u c #010003", +"v c #020005", +"w c #03080A", +"x c #10211F", +"y c #000001", +"z c #162D26", +"A c #050B0C", +"B c #090F10", +"C c #142724", +"D c #050D0E", +"E c #050A0C", +" ", +" ", +" .++ ", +" @#$%&*= ", +"- #;%>>>,') ", +"!- ~%>>{]^>>/( ", +"!_-#%>:<[}}|1>2 ", +"!345>678 9->0 ", +"!ab>6c d>e ", +"!fgh>i jkl ", +"!mnop>9 qr ", +"stuuvuuu wxy ", +" 8zA ", +" BCD ", +" yEy ", +" ", +" "}; diff --git a/noncore/apps/tinykate/pics/file-new.xpm b/noncore/apps/tinykate/pics/file-new.xpm new file mode 100644 index 0000000..ec8dd63 --- a/dev/null +++ b/noncore/apps/tinykate/pics/file-new.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static const char * file_new_xpm[] = { +"16 16 5 1", +" c None", +". c #808080", +"+ c #FFFFFF", +"@ c #C0C0C0", +"# c #000000", +" .......... ", +" .++++++++@. ", +" .++++++++@+. ", +" .++++++++#### ", +" .++++++++++@# ", +" .++++++++++@# ", +" .++++++++++@# ", +" .++++++++++@# ", +" .++++++++++@# ", +" .++++++++++@# ", +" .++++++++++@# ", +" .++++++++++@# ", +" .++++++++++@# ", +" .++++++++++@# ", +" .@@@@@@@@@@@# ", +" ############# "}; diff --git a/noncore/apps/tinykate/pics/file-open.xpm b/noncore/apps/tinykate/pics/file-open.xpm new file mode 100644 index 0000000..8449d5b --- a/dev/null +++ b/noncore/apps/tinykate/pics/file-open.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static const char * file_open_xpm[] = { +"16 16 6 1", +" c None", +". c #808080", +"+ c #FFFFFF", +"@ c #C0C0C0", +"# c #FFFF00", +"$ c #000000", +" ", +" ..... ", +" .+++++. ", +" .+@#@#@+...... ", +" .+#@#@#@+++++.$", +" .+@#@#@#@#@#@.$", +".............#.$", +".++++++++++.$@.$", +".+@#@#@#@#@#$..$", +" .+@#@#@#@#@.$.$", +" .+#@#@#@#@#@$.$", +" .+#@#@#@#@#.$$", +" ............$$", +" $$$$$$$$$$$$$", +" ", +" "}; diff --git a/noncore/apps/tinykate/pics/file-save.xpm b/noncore/apps/tinykate/pics/file-save.xpm new file mode 100644 index 0000000..039a174 --- a/dev/null +++ b/noncore/apps/tinykate/pics/file-save.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static const char * file_save_xpm[] = { +"16 16 5 1", +" c None", +". c #808080", +"+ c #FFFFFF", +"@ c #000000", +"# c #0000FF", +" ", +" ........ ", +" .++++++.@ ", +" .+....+.+@ #", +" .++++++.@@@ ##", +" .+....++++@ ##@", +" .+++++++++@##@ ", +" .+.......+##@ ", +" .++++++++##@ ", +" .+......@#@ ", +" .++++++@@@@ ", +" .+....@@@+@ ", +" .++++@++++@ ", +" .+++++++++@ ", +" @@@@@@@@@@@ ", +" "}; diff --git a/noncore/apps/tinykate/tinykate.cpp b/noncore/apps/tinykate/tinykate.cpp new file mode 100644 index 0000000..03c6e50 --- a/dev/null +++ b/noncore/apps/tinykate/tinykate.cpp @@ -0,0 +1,199 @@ +/*************************************************************************** + tinykate.cpp + Tiny KATE mainwindow + ------------------- + begin : November 2002 + copyright : (C) 2002 by Joseph Wenninger + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation. * + * ONLY VERSION 2 OF THE LICENSE IS APPLICABLE * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tinykate.h" +#include "pics/file-new.xpm" +#include "pics/file-open.xpm" +#include "pics/file-save.xpm" +#include "pics/edit-undo.xpm" +#include "pics/edit-redo.xpm" + +#include +#include + +TinyKate::TinyKate( QWidget *parent, const char *name, WFlags f) : + QMainWindow( parent, name, f ) +{ + currentView=0; + setCaption(tr("TinyKATE")); + + setToolBarsMovable(FALSE); + + QPEToolBar *bar = new QPEToolBar( this ); + bar->setHorizontalStretchable( TRUE ); + QPEMenuBar *mb = new QPEMenuBar( bar ); + mb->setMargin( 0 ); + + tabwidget=new OTabWidget(this); + setCentralWidget(tabwidget); + connect(tabwidget,SIGNAL(currentChanged( QWidget *)),this,SLOT(slotCurrentChanged(QWidget *))); + +//FILE ACTIONS + QPopupMenu *popup = new QPopupMenu( this ); + + // Action for creating a new document + QAction *a = new QAction( tr( "New" ), QPixmap((const char**)file_new_xpm ), QString::null, 0, this, 0 ); + a->addTo( popup ); + connect(a, SIGNAL(activated()), this, SLOT(slotNew())); + + // Action for opening an exisiting document + a = new QAction( tr( "Open" ), QPixmap((const char**)file_open_xpm), QString::null, 0, this, 0 ); + a->addTo(popup); + connect(a, SIGNAL(activated()), this, SLOT(slotOpen())); + + + // Action for saving document + a = new QAction( tr( "Save" ), QPixmap((const char**)file_save_xpm), QString::null, 0, this, 0 ); + a->addTo(popup); + + // Action for saving document to a new name + a = new QAction( tr( "Save As" ), QPixmap((const char**)file_save_xpm), QString::null, 0, this, 0 ); + a->addTo(popup); + + // Action for closing the currently active document + a = new QAction( tr( "Close" ), QPixmap(), QString::null, 0, this, 0 ); + a->addTo(popup); + connect(a, SIGNAL(activated()), this, SLOT(slotClose())); + + + mb->insertItem(tr("File"),popup); + +//EDIT ACTIONS + + // Action for cutting text + editCut = new QAction( tr( "Cut" ), Resource::loadPixmap( "cut" ), QString::null, 0, this, 0 ); + editCut->addTo( bar ); + + // Action for Copying text + editCopy = new QAction( tr( "Copy" ), Resource::loadPixmap( "copy" ), QString::null, 0, this, 0 ); + editCopy->addTo( bar ); + + // Action for pasting text + editPaste = new QAction( tr( "Paste" ), Resource::loadPixmap( "paste" ), QString::null, 0, this, 0 ); + editPaste->addTo( bar ); + + + // Action for finding / replacing text + editFindReplace = new QAction( tr( "Find/Replace" ), Resource::loadPixmap("find"), QString::null, 0, this, 0 ); + editFindReplace->addTo( bar ); + + // Action for undo + editUndo = new QAction( tr( "Undo" ), QPixmap((const char**)edit_undo_xpm), QString::null, 0, this, 0 ); + editUndo->addTo( bar ); + + // Action for redo + editRedo = new QAction( tr( "Redo" ), QPixmap((const char**)edit_redo_xpm), QString::null, 0, this, 0 ); + editRedo->addTo( bar ); + +//VIEW ACITONS + popup = new QPopupMenu( this ); + + viewIncFontSizes = new QAction( tr( "Font +" ), QString::null, 0, this, 0 ); + viewIncFontSizes->addTo( popup ); + + viewDecFontSizes = new QAction( tr( "Font -" ), QString::null, 0, this, 0 ); + viewDecFontSizes->addTo( popup ); + + mb->insertItem(tr("View"),popup); + + + + popup = new QPopupMenu( this ); + mb->insertItem(tr("Utils"),popup); + +//Highlight management + hlmenu=new QPopupMenu(this); + HlManager *hlm=HlManager::self(); + for (int i=0;ihighlights();i++) + { + hlmenu->insertItem(hlm->hlName(i),i); + } + popup->insertItem(tr("Highlighting"),hlmenu); + + + utilSettings = new QAction( tr( "Settings" ), QString::null, 0, this, 0 ); + utilSettings->addTo( popup); + +} + + +void TinyKate::slotOpen( ) +{ + QString filename=OFileDialog::getOpenFileName(OFileSelector::EXTENDED_ALL); + if (!filename.isEmpty()) { + KateDocument *kd= new KateDocument(false, false, this,0,this); + KTextEditor::View *kv; + tabwidget->addTab(kv=kd->createView(tabwidget,"bLAH"),"BLAH","BLAH"); + qDebug(filename); + kd->open(filename); + } +} + +void TinyKate::slotCurrentChanged( QWidget * view) +{ + if (currentView) { + disconnect(editCopy,SIGNAL(activated()),currentView,SLOT(copy())); + disconnect(editCut,SIGNAL(activated()),currentView,SLOT(cut())); + disconnect(editPaste,SIGNAL(activated()),currentView,SLOT(paste())); + disconnect(editUndo,SIGNAL(activated()),currentView,SLOT(undo())); + disconnect(editRedo,SIGNAL(activated()),currentView,SLOT(redo())); + disconnect(viewIncFontSizes,SIGNAL(activated()), currentView,SLOT(slotIncFontSizes())); + disconnect(viewDecFontSizes,SIGNAL(activated()), currentView,SLOT(slotDecFontSizes())); + disconnect(hlmenu,SIGNAL(activated(int)), currentView,SLOT(setHl(int))); + disconnect(utilSettings,SIGNAL(activated()), currentView,SLOT(configDialog())); + } + + currentView=(KTextEditor::View*)view; + + connect(editCopy,SIGNAL(activated()),currentView,SLOT(copy())); + connect(editCut,SIGNAL(activated()),currentView,SLOT(cut())); + connect(editPaste,SIGNAL(activated()),currentView,SLOT(paste())); + connect(editUndo,SIGNAL(activated()),currentView,SLOT(undo())); + connect(editRedo,SIGNAL(activated()),currentView,SLOT(redo())); + connect(viewIncFontSizes,SIGNAL(activated()), currentView,SLOT(slotIncFontSizes())); + connect(viewDecFontSizes,SIGNAL(activated()), currentView,SLOT(slotDecFontSizes())); + connect(hlmenu,SIGNAL(activated(int)), currentView,SLOT(setHl(int))); + connect(utilSettings,SIGNAL(activated()), currentView,SLOT(configDialog())); + +} + +void TinyKate::slotNew( ) +{ + KateDocument *kd= new KateDocument(false, false, this,0,this); + KTextEditor::View *kv; + tabwidget->addTab(kv=kd->createView(tabwidget,"BLAH"),"BLAH",tr("Unnamed %1").arg(0)); + +} + +void TinyKate::slotClose( ) +{ + if (currentView==0) return; + KTextEditor::View *dv=currentView; + currentView=0; + tabwidget->removePage(dv); + delete dv->document(); +} + diff --git a/noncore/apps/tinykate/tinykate.desktop b/noncore/apps/tinykate/tinykate.desktop new file mode 100644 index 0000000..2230a6b --- a/dev/null +++ b/noncore/apps/tinykate/tinykate.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Application +Exec=tinykate +Icon=tinykate_icon.xpm +Name=TinyKATE +Comment=Opie Advanced Texteditor diff --git a/noncore/apps/tinykate/tinykate.h b/noncore/apps/tinykate/tinykate.h new file mode 100644 index 0000000..6dda05d --- a/dev/null +++ b/noncore/apps/tinykate/tinykate.h @@ -0,0 +1,62 @@ +/*************************************************************************** + tinykate.h + Tiny KATE mainwindow + ------------------- + begin : November 2002 + copyright : (C) 2002 by Joseph Wenninger + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation. * + * ONLY VERSION 2 OF THE LICENSE IS APPLICABLE * + * * + ***************************************************************************/ + +#ifndef __TINYKATE_H__ +#define __TINYKATE_H__ + + +#include +#include +#include + +class QAction; +class QPopupMenu; + +class TinyKate : public QMainWindow +{ +Q_OBJECT +public: + TinyKate( QWidget *parent=0, const char *name=0, WFlags f = 0); + +public slots: + void slotOpen(); + +protected slots: + void slotNew(); + void slotClose(); + void slotCurrentChanged(QWidget *); + +private: + OTabWidget *tabwidget; + KTextEditor::View *currentView; + + QAction *editCopy; + QAction *editCut; + QAction *editPaste; + QAction *editUndo; + QAction *editRedo; + QAction *editFindReplace; + QAction *viewIncFontSizes; + QAction *viewDecFontSizes; + QAction *utilSettings; + + QPopupMenu *hlmenu; + +}; + + +#endif // __TINYKATE_H__ diff --git a/noncore/apps/tinykate/tinykate.pro b/noncore/apps/tinykate/tinykate.pro new file mode 100644 index 0000000..2079041 --- a/dev/null +++ b/noncore/apps/tinykate/tinykate.pro @@ -0,0 +1,16 @@ +TEMPLATE = app +CONFIG = qt warn_on release +DESTDIR = $(OPIEDIR)/bin +HEADERS = tinykate.h +SOURCES = tinykate.cpp main.cpp +INTERFACES = +INCLUDEPATH += $(OPIEDIR)/include $(OPIEDIR)/noncore/apps/tinykate/libkate/microkde \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/document \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/view \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/interfaces \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/ktexteditor \ + $(OPIEDIR)/noncore/apps/tinykate/libkate/qt3back + +DEPENDPATH += $(OPIEDIR)/include +LIBS += -lqpe -ltinykate -lopie +TARGET = tinykate diff --git a/noncore/apps/tinykate/tinykate_icon.xpm b/noncore/apps/tinykate/tinykate_icon.xpm new file mode 100644 index 0000000..e48e7c9 --- a/dev/null +++ b/noncore/apps/tinykate/tinykate_icon.xpm @@ -0,0 +1,20 @@ +/* XPM */ +static char *tinykate_xpm[] = { +"14 14 3 1", +" c None", +". c #000000", +"a c #FFFFFF", +" ", +" aaaaaaaaaaaa ", +" a..........a ", +" a..aaaaaa..a ", +" a.a.aaaa.a.a ", +" a.aa.aa.aa.a ", +" a.aaa..aaa.a ", +" a.aaa..aaa.a ", +" a.aa.aa.aa.a ", +" a.a.aaaa.a.a ", +" a..aaaaaa..a ", +" a..........a ", +" aaaaaaaaaaaa ", +" "}; -- cgit v0.9.0.2