summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/tinykate/libkate/document/katedocument.cpp7
1 files changed, 6 insertions, 1 deletions
diff --git a/noncore/apps/tinykate/libkate/document/katedocument.cpp b/noncore/apps/tinykate/libkate/document/katedocument.cpp
index a70f3aa..b82a86a 100644
--- a/noncore/apps/tinykate/libkate/document/katedocument.cpp
+++ b/noncore/apps/tinykate/libkate/document/katedocument.cpp
@@ -1,752 +1,757 @@
/***************************************************************************
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 "kmessagebox.h"
#include "kglobal.h"
//#include "kcharsets.h"
#include "kdebug.h"
//#include "kinstance.h"
#include "kglobalsettings.h"
//#include "kaction.h"
//#include "kstdaction.h"
#include "../view/kateview.h"
#include "katebuffer.h"
#include "katetextline.h"
#include "katecmd.h"
/* OPIE */
#include <opie2/odebug.h>
#include <qpe/config.h>
/* QT */
#include <qfileinfo.h>
#include <qdatetime.h>
#include <qstring.h>
#include <qtimer.h>
#include <qobject.h>
#include <qapplication.h>
#include <qclipboard.h>
#include <qfont.h>
#include <qpainter.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qtextcodec.h>
/* STD */
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
KateAction::KateAction(Action a, PointStruc &cursor, int len, const QString &text)
: action(a), cursor(cursor), len(len), text(text) {
}
KateActionGroup::KateActionGroup(PointStruc &aStart, int type)
: start(aStart), action(0L), undoType(type) {
}
KateActionGroup::~KateActionGroup() {
KateAction *current, *next;
current = action;
while (current) {
next = current->next;
delete current;
current = next;
}
}
void KateActionGroup::insertAction(KateAction *a) {
a->next = action;
action = a;
}
const char * KateActionGroup::typeName(int type)
{
// return a short text description of the given undo group type suitable for a menu
// not the lack of i18n's, the caller is expected to handle translation
switch (type) {
case ugPaste : return "Paste Text";
case ugDelBlock : return "Selection Overwrite";
case ugIndent : return "Indent";
case ugUnindent : return "Unindent";
case ugComment : return "Comment";
case ugUncomment : return "Uncomment";
case ugReplace : return "Text Replace";
case ugSpell : return "Spell Check";
case ugInsChar : return "Typing";
case ugDelChar : return "Delete Text";
case ugInsLine : return "New Line";
case ugDelLine : return "Delete Line";
}
return "";
}
const int KateDocument::maxAttribs = 32;
QStringList KateDocument::searchForList = QStringList();
QStringList KateDocument::replaceWithList = QStringList();
uint KateDocument::uniqueID = 0;
QPtrDict<KateDocument::KateDocPrivate>* KateDocument::d_ptr = 0;
KateDocument::KateDocument(bool bSingleViewMode, bool bBrowserView,
QWidget *parentWidget, const char *widgetName,
QObject *, const char *)
: Kate::Document (),
myFont(KGlobalSettings::generalFont()), myFontBold(KGlobalSettings::generalFont()), myFontItalic(KGlobalSettings::generalFont()), myFontBI(KGlobalSettings::generalFont()),
myFontMetrics (myFont), myFontMetricsBold (myFontBold), myFontMetricsItalic (myFontItalic), myFontMetricsBI (myFontBI),
hlManager(HlManager::self ())
{
d(this)->hlSetByUser = false;
PreHighlightedTill=0;
RequestPreHighlightTill=0;
m_bSingleViewMode=bSingleViewMode;
m_bBrowserView = bBrowserView;
m_url = QString::null;
// NOTE: QFont::CharSet doesn't provide all the charsets KDE supports
// (esp. it doesn't distinguish between UTF-8 and iso10646-1)
myEncoding = QString::fromLatin1(QTextCodec::codecForLocale()->name());
maxLength = -1;
setFont (KGlobalSettings::generalFont());
myDocID = uniqueID;
uniqueID++;
myDocName = QString ("");
fileInfo = new QFileInfo ();
myCmd = new KateCmd (this);
connect(this,SIGNAL(modifiedChanged()),this,SLOT(slotModChanged()));
buffer = new KWBuffer;
connect(buffer, SIGNAL(linesChanged(int)), this, SLOT(slotBufferChanged()));
// connect(buffer, SIGNAL(textChanged()), this, SIGNAL(textChanged()));
connect(buffer, SIGNAL(needHighlight(long,long)),this,SLOT(slotBufferHighlight(long,long)));
colors[0] = KGlobalSettings::baseColor();
colors[1] = KGlobalSettings::highlightColor();
m_attribs = new Attribute[maxAttribs];
m_highlight = 0L;
tabChars = 8;
m_singleSelection = false;
newDocGeometry = false;
readOnly = false;
newDoc = false;
modified = false;
undoList.setAutoDelete(true);
undoState = 0;
undoSteps = 50;
pseudoModal = 0L;
clear();
setHighlight(0); //calls updateFontData()
// if the user changes the highlight with the dialog, notify the doc
connect(hlManager,SIGNAL(changed()),SLOT(hlChanged()));
newDocGeometry = false;
readConfig();
setReadOnly(false);
}
void KateDocument::setDontChangeHlOnSave()
{
d(this)->hlSetByUser = true;
}
void KateDocument::setFont (QFont font)
{
kdDebug()<<"Kate:: setFont"<<endl;
int oldwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
myFont = font;
myFontBold = QFont (font);
myFontBold.setBold (true);
myFontItalic = QFont (font);
myFontItalic.setItalic (true);
myFontBI = QFont (font);
myFontBI.setBold (true);
myFontBI.setItalic (true);
myFontMetrics = CachedFontMetrics (myFont);
myFontMetricsBold = CachedFontMetrics (myFontBold);
myFontMetricsItalic = CachedFontMetrics (myFontItalic);
myFontMetricsBI = CachedFontMetrics (myFontBI);
int newwidth=myFontMetrics.width('W'); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
maxLength=maxLength*(float)newwidth/(float)oldwidth; //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
updateFontData();
updateViews(); //Quick & Dirty Hack (by JoWenn) //Remove in KDE 3.0
}
long KateDocument::needPreHighlight(long till)
{
int max=numLines()-1;
if (till>max)
{
till=max;
}
if (PreHighlightedTill>=till) return -1;
long tmp=RequestPreHighlightTill;
if (RequestPreHighlightTill<till)
{
RequestPreHighlightTill=till;
if (tmp<=PreHighlightedTill) QTimer::singleShot(10,this,SLOT(doPreHighlight()));
}
return RequestPreHighlightTill;
}
void KateDocument::doPreHighlight()
{
int from = PreHighlightedTill;
int till = PreHighlightedTill+200;
int max = numLines()-1;
if (till > max)
{
till = max;
}
PreHighlightedTill = till;
updateLines(from,till);
emit preHighlightChanged(PreHighlightedTill);
if (PreHighlightedTill<RequestPreHighlightTill)
QTimer::singleShot(10,this,SLOT(doPreHighlight()));
}
KateDocument::~KateDocument()
{
m_highlight->release();
writeConfig();
if ( !m_bSingleViewMode )
{
m_views.setAutoDelete( true );
m_views.clear();
m_views.setAutoDelete( false );
}
delete_d(this);
}
void KateDocument::openURL(const QString &filename)
{
m_file=filename;
fileInfo->setFile (m_file);
setMTime();
if (!fileInfo->exists() || !fileInfo->isReadable())
{
odebug << "File doesn't exit or couldn't be read" << oendl;
return ;
}
buffer->clear();
#warning fixme
// buffer->insertFile(0, m_file, KGlobal::charsets()->codecForName(myEncoding));
odebug << "Telling buffer to open file" << oendl;
buffer->insertFile(0, m_file, QTextCodec::codecForLocale());
setMTime();
if (myWordWrap)
wrapText (myWordWrapAt);
int hl = hlManager->wildcardFind( m_file );
setHighlight(hl);
updateLines();
updateViews();
emit fileNameChanged();
return ;
}
bool KateDocument::saveFile()
{
QFile f( m_file );
if ( !f.open( IO_WriteOnly ) )
return false; // Error
QTextStream stream(&f);
stream.setEncoding(QTextStream::RawUnicode); // disable Unicode headers
#warning fixme
// stream.setCodec(KGlobal::charsets()->codecForName(myEncoding));
stream.setCodec(QTextCodec::codecForLocale()); // this line sets the mapper to the correct codec
int maxLine = numLines();
int line = 0;
while(true)
{
stream << getTextLine(line)->getString();
line++;
if (line >= maxLine) break;
if (eolMode == KateDocument::eolUnix) stream << "\n";
else if (eolMode == KateDocument::eolDos) stream << "\r\n";
else if (eolMode == KateDocument::eolMacintosh) stream << '\r';
};
f.close();
fileInfo->setFile (m_file);
setMTime();
if (!(d(this)->hlSetByUser))
{
int hl = hlManager->wildcardFind( m_file );
setHighlight(hl);
}
emit fileNameChanged ();
- return (f.status() == IO_Ok);
+ if(f.status() == IO_Ok) {
+ setModified(false);
+ return true;
+ }
+ else
+ return false;
}
KTextEditor::View *KateDocument::createView( QWidget *parent, const char *name )
{
return new KateView( this, parent, name);
}
QString KateDocument::textLine( int line ) const
{
TextLine::Ptr l = getTextLine( line );
if ( !l )
return QString();
return l->getString();
}
void KateDocument::replaceLine(const QString& s,int line)
{
remove_Line(line,false);
insert_Line(s,line,true);
}
void KateDocument::insertLine( const QString &str, int l ) {
insert_Line(str,l,true);
}
void KateDocument::insert_Line(const QString& s,int line, bool update)
{
kdDebug(13020)<<"KateDocument::insertLine "<<s<<QString(" %1").arg(line)<<endl;
TextLine::Ptr TL=new TextLine();
TL->append(s.unicode(),s.length());
buffer->insertLine(line,TL);
if (update)
{
newDocGeometry=true;
updateLines(line);
updateViews();
}
}
void KateDocument::insertAt( const QString &s, int line, int col, bool )
{
VConfig c;
c.view = 0; // ### FIXME
c.cursor.x = col;
c.cursor.y = line;
c.cXPos = 0; // ### FIXME
c.flags = 0; // ### FIXME
insert( c, s );
}
void KateDocument::removeLine( int line ) {
remove_Line(line,true);
}
void KateDocument::remove_Line(int line,bool update)
{
kdDebug(13020)<<"KateDocument::removeLine "<<QString("%1").arg(line)<<endl;
buffer->removeLine(line);
// newDocGeometry=true;
// if line==0)
if (update)
{
updateLines(line);
updateViews();
}
}
int KateDocument::length() const
{
return text().length();
}
void KateDocument::setSelection( int , int , int , int )
{
}
bool KateDocument::hasSelection() const
{
return (selectEnd >= selectStart);
}
QString KateDocument::selection() const
{
uint flags = 0;
TextLine::Ptr textLine;
int len, z, start, end, i;
len = 1;
if (!(flags & KateView::cfVerticalSelect)) {
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
len += textLine->numSelected();
if (textLine->isSelected()) len++;
}
QString s;
len = 0;
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
end = 0;
do {
start = textLine->findUnselected(end);
end = textLine->findSelected(start);
for (i = start; i < end; i++) {
s[len] = textLine->getChar(i);
len++;
}
} while (start < end);
if (textLine->isSelected()) {
s[len] = '\n';
len++;
}
}
// s[len] = '\0';
return s;
} else {
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
len += textLine->numSelected() + 1;
}
QString s;
len = 0;
for (z = selectStart; z <= selectEnd; z++) {
textLine = getTextLine(z);
end = 0;
do {
start = textLine->findUnselected(end);
end = textLine->findSelected(start);
for (i = start; i < end; i++) {
s[len] = textLine->getChar(i);
len++;
}
} while (start < end);
s[len] = '\n';
len++;
}
// s[len] = '\0'; // the final \0 is not counted in length()
return s;
}
}
int KateDocument::numLines() const
{
return buffer->count();
}
TextLine::Ptr KateDocument::getTextLine(int line) const
{
// This is a hack to get this stuff working.
return buffer->line(line);
}
int KateDocument::textLength(int line) {
TextLine::Ptr textLine = getTextLine(line);
if (!textLine) return 0;
return textLine->length();
}
void KateDocument::setTabWidth(int chars) {
if (tabChars == chars) return;
if (chars < 1) chars = 1;
if (chars > 16) chars = 16;
tabChars = chars;
updateFontData();
maxLength = -1;
for (int i=0; i < buffer->count(); i++)
{
TextLine::Ptr textLine = buffer->line(i);
int len = textWidth(textLine,textLine->length());
if (len > maxLength) {
maxLength = len;
longestLine = textLine;
}
}
}
void KateDocument::setReadOnly(bool m) {
KTextEditor::View *view;
if (m != readOnly) {
readOnly = m;
// if (readOnly) recordReset();
for (view = m_views.first(); view != 0L; view = m_views.next() ) {
emit static_cast<KateView *>( view )->newStatus();
}
}
}
bool KateDocument::isReadOnly() const {
return readOnly;
}
void KateDocument::setNewDoc( bool m )
{
// KTextEditor::View *view;
if ( m != newDoc )
{
newDoc = m;
//// if (readOnly) recordReset();
// for (view = m_views.first(); view != 0L; view = m_views.next() ) {
// emit static_cast<KateView *>( view )->newStatus();
// }
}
}
bool KateDocument::isNewDoc() const {
return newDoc;
}
void KateDocument::setModified(bool m) {
KTextEditor::View *view;
if (m != modified) {
modified = m;
for (view = m_views.first(); view != 0L; view = m_views.next() ) {
emit static_cast<KateView *>( view )->newStatus();
}
emit modifiedChanged ();
}
}
bool KateDocument::isModified() const {
return modified;
}
void KateDocument::readConfig()
{
KateConfig *config = KGlobal::config();
config->setGroup("Kate Document");
myWordWrap = config->readBoolEntry("Word Wrap On", false);
myWordWrapAt = config->readNumEntry("Word Wrap At", 80);
if (myWordWrap)
wrapText (myWordWrapAt);
setTabWidth(config->readNumEntry("TabWidth", 8));
setUndoSteps(config->readNumEntry("UndoSteps", 50));
m_singleSelection = config->readBoolEntry("SingleSelection", false);
myEncoding = config->readEntry("Encoding", QString::fromLatin1(QTextCodec::codecForLocale()->name()));
setFont (config->readFontEntry("Font", myFont));
colors[0] = config->readColorEntry("Color Background", colors[0]);
colors[1] = config->readColorEntry("Color Selected", colors[1]);
// config->sync();
}
void KateDocument::writeConfig()
{
KateConfig *config = KGlobal::config();
config->setGroup("Kate Document");
config->writeEntry("Word Wrap On", myWordWrap);
config->writeEntry("Word Wrap At", myWordWrapAt);
config->writeEntry("TabWidth", tabChars);
config->writeEntry("UndoSteps", undoSteps);
config->writeEntry("SingleSelection", m_singleSelection);
config->writeEntry("Encoding", myEncoding);
config->writeEntry("Font", myFont);
config->writeEntry("Color Background", colors[0]);
config->writeEntry("Color Selected", colors[1]);
// config->sync();
}
void KateDocument::readSessionConfig(KateConfig *config)
{
m_url = config->readEntry("URL"); // ### doesn't this break the encoding? (Simon)
setHighlight(hlManager->nameFind(config->readEntry("Highlight")));
// anders: restore bookmarks if possible
QValueList<int> l = config->readIntListEntry("Bookmarks");
if ( l.count() ) {
for (uint i=0; i < l.count(); i++) {
if ( numLines() < l[i] ) break;
getTextLine( l[i] )->addMark( Bookmark );
}
}
}
void KateDocument::writeSessionConfig(KateConfig *config)
{
#if 0
config->writeEntry("URL", m_url); // ### encoding?? (Simon)
config->writeEntry("Highlight", m_highlight->name());
// anders: save bookmarks
QList<Kate::Mark> l = marks();
QValueList<int> ml;
for (uint i=0; i < l.count(); i++) {
if ( l.at(i)->type == 1) // only save bookmarks
ml << l.at(i)->line;
}
if ( ml.count() )
config->writeEntry("Bookmarks", ml);
#endif
}
void KateDocument::setHighlight(int n) {
Highlight *h;
// hlNumber = n;
h = hlManager->getHl(n);
if (h == m_highlight) {
updateLines();
} else {
if (m_highlight != 0L) m_highlight->release();
h->use();
m_highlight = h;
makeAttribs();
}
PreHighlightedTill=0;
RequestPreHighlightTill=0;
emit(highlightChanged());
}
void KateDocument::makeAttribs() {
odebug << "KateDocument::makeAttribs()" << oendl;
m_numAttribs = hlManager->makeAttribs(m_highlight, m_attribs, maxAttribs);
updateFontData();
updateLines();
}
void KateDocument::updateFontData() {
int maxAscent, maxDescent;
int tabWidth;
KateView *view;
maxAscent = myFontMetrics.ascent();
maxDescent = myFontMetrics.descent();
tabWidth = myFontMetrics.width(' ');
fontHeight = maxAscent + maxDescent + 1;
fontAscent = maxAscent;
m_tabWidth = tabChars*tabWidth;
for (view = views.first(); view != 0L; view = views.next() ) {
view->myViewInternal->drawBuffer->resize(view->width(),fontHeight);
view->tagAll();
view->updateCursor();
}
}
void KateDocument::hlChanged() { //slot
makeAttribs();
updateViews();
}
void KateDocument::addView(KTextEditor::View *view) {
views.append( static_cast<KateView *>( view ) );
KTextEditor::Document::addView( view );
connect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) );
}
void KateDocument::removeView(KTextEditor::View *view) {
// if (undoView == view) recordReset();
disconnect( static_cast<KateView *>( view ), SIGNAL( destroyed() ), this, SLOT( slotViewDestroyed() ) );
views.removeRef( static_cast<KateView *>( view ) );
KTextEditor::Document::removeView( view );
}
void KateDocument::slotViewDestroyed()
{
views.removeRef( static_cast<const KateView *>( sender() ) );
}
bool KateDocument::ownedView(KateView *view) {
// do we own the given view?
return (views.containsRef(view) > 0);
}
bool KateDocument::isLastView(int numViews) {
return ((int) views.count() == numViews);
}
int KateDocument::textWidth(const TextLine::Ptr &textLine, int cursorX) {
int x;
int z;
QChar ch;
Attribute *a;
x = 0;