summaryrefslogtreecommitdiffstats
path: root/tdeui/keditcl1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tdeui/keditcl1.cpp')
-rw-r--r--tdeui/keditcl1.cpp718
1 files changed, 718 insertions, 0 deletions
diff --git a/tdeui/keditcl1.cpp b/tdeui/keditcl1.cpp
new file mode 100644
index 000000000..fe886f434
--- /dev/null
+++ b/tdeui/keditcl1.cpp
@@ -0,0 +1,718 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1997 Bernd Johannes Wuebben <wuebben@math.cornell.edu>
+ Copyright (C) 2000 Waldo Bastian <bastian@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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <tqdragobject.h>
+#include <tqpopupmenu.h>
+#include <tqtextstream.h>
+#include <tqtimer.h>
+
+#include <kapplication.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kcmenumngr.h>
+#include <kfontdialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstdaccel.h>
+#include <kurldrag.h>
+
+#include "keditcl.h"
+#include "keditcl.moc"
+
+class KEdit::KEditPrivate
+{
+public:
+ bool overwriteEnabled:1;
+ bool posDirty:1;
+ bool autoUpdate:1;
+};
+
+
+KEdit::KEdit(TQWidget *_parent, const char *name)
+ : TQMultiLineEdit(_parent, name)
+{
+ d = new KEditPrivate;
+ d->overwriteEnabled = false;
+ d->posDirty = true;
+ d->autoUpdate = true;
+
+ parent = _parent;
+
+ // set some defaults
+
+ line_pos = col_pos = 0;
+
+ srchdialog = NULL;
+ replace_dialog= NULL;
+ gotodialog = NULL;
+
+ setAcceptDrops(true);
+ KCursor::setAutoHideCursor( this, true );
+
+ connect(this, TQT_SIGNAL(cursorPositionChanged(int,int)),
+ this, TQT_SLOT(slotCursorPositionChanged()));
+}
+
+
+KEdit::~KEdit()
+{
+ delete d;
+}
+
+void
+KEdit::setAutoUpdate(bool b)
+{
+ d->autoUpdate = b;
+}
+
+void
+KEdit::insertText(TQTextStream *stream)
+{
+// setAutoUpdate(false);
+ int line, col;
+ getCursorPosition(&line, &col);
+ int saveline = line;
+ int savecol = col;
+ TQString textLine;
+
+ // MS: Patch by Martin Schenk <martin@schenk.com>
+ // MS: disable UNDO, or TQMultiLineEdit remembers every textLine !!!
+ // memory usage is:
+ // textLine: 2*size rounded up to nearest power of 2 (520Kb -> 1024Kb)
+ // widget: about (2*size + 60bytes*lines)
+ // -> without disabling undo, it often needs almost 8*size
+ int oldUndoDepth = undoDepth();
+ setUndoDepth( 0 ); // ### -1?
+
+ // MS: read everything at once if file <= 1MB,
+ // else read in 5000-line chunks to keep memory usage acceptable.
+ TQIODevice *dev=stream->tqdevice();
+ if (dev && dev->size()>(1024*1024)) {
+ while(1) {
+ int i;
+ textLine="";
+ for (i=0; i<5000; i++) {
+ TQString line=stream->readLine();
+ if (line.isNull()) break; // EOF
+ textLine+=line+'\n';
+ }
+ insertAt(textLine, line, col);
+ line+=i; col=0;
+ if (i!=5000) break;
+ }
+ }
+ else {
+ textLine = stream->read(); // Read all !
+ insertAt( textLine, line, col);
+ }
+ setUndoDepth( oldUndoDepth );
+
+ setCursorPosition(saveline, savecol);
+// setAutoUpdate(true);
+
+// tqrepaint();
+
+ setModified(true);
+ setFocus();
+
+ // Bernd: Please don't leave debug message like that lying around
+ // they cause ENORMOUSE performance hits. Once upon a day
+ // kedit used to be really really fast using memmap etc .....
+ // oh well ....
+
+ // TQString str = text();
+ // for (int i = 0; i < (int) str.length(); i++)
+ // printf("KEdit: U+%04X\n", str[i].tqunicode());
+
+}
+
+void
+KEdit::cleanWhiteSpace()
+{
+ d->autoUpdate = false;
+ if (!hasMarkedText())
+ selectAll();
+ TQString oldText = markedText();
+ TQString newText;
+ TQStringList lines = TQStringList::split('\n', oldText, true);
+ bool addSpace = false;
+ bool firstLine = true;
+ TQChar lastChar = oldText[oldText.length()-1];
+ TQChar firstChar = oldText[0];
+ for(TQStringList::Iterator it = lines.begin();
+ it != lines.end();)
+ {
+ TQString line = (*it).simplifyWhiteSpace();
+ if (line.isEmpty())
+ {
+ if (addSpace)
+ newText += TQString::tqfromLatin1("\n\n");
+ if (firstLine)
+ {
+ if (firstChar.isSpace())
+ newText += '\n';
+ firstLine = false;
+ }
+ addSpace = false;
+ }
+ else
+ {
+ if (addSpace)
+ newText += ' ';
+ if (firstLine)
+ {
+ if (firstChar.isSpace())
+ newText += ' ';
+ firstLine = false;
+ }
+ newText += line;
+ addSpace = true;
+ }
+ it = lines.remove(it);
+ }
+ if (addSpace)
+ {
+ if (lastChar == '\n')
+ newText += '\n';
+ else if (lastChar.isSpace())
+ newText += ' ';
+ }
+
+ if (oldText == newText)
+ {
+ deselect();
+ d->autoUpdate = true;
+ tqrepaint();
+ return;
+ }
+ if (wordWrap() == NoWrap)
+ {
+ // If wordwrap is off, we have to do some line-wrapping ourselves now
+ // We use another TQMultiLineEdit for this, so that we get nice undo
+ // behavior.
+ TQMultiLineEdit *we = new TQMultiLineEdit();
+ we->setWordWrap(FixedColumnWidth);
+ we->setWrapColumnOrWidth(78);
+ we->setText(newText);
+ newText = TQString::null;
+ for(int i = 0; i < we->numLines(); i++)
+ {
+ TQString line = we->textLine(i);
+ if (line.right(1) != "\n")
+ line += '\n';
+ newText += line;
+ }
+ delete we;
+ }
+
+ insert(newText);
+ d->autoUpdate = true;
+ tqrepaint();
+
+ setModified(true);
+ setFocus();
+}
+
+
+void
+KEdit::saveText(TQTextStream *stream)
+{
+ saveText(stream, false);
+}
+
+void
+KEdit::saveText(TQTextStream *stream, bool softWrap)
+{
+ int line_count = numLines()-1;
+ if (line_count < 0)
+ return;
+
+ if (softWrap || (wordWrap() == NoWrap))
+ {
+ for(int i = 0; i < line_count; i++)
+ {
+ (*stream) << textLine(i) << '\n';
+ }
+ (*stream) << textLine(line_count);
+ }
+ else
+ {
+ for(int i = 0; i <= line_count; i++)
+ {
+ int lines_in_parag = linesOfParagraph(i);
+ if (lines_in_parag == 1)
+ {
+ (*stream) << textLine(i);
+ }
+ else
+ {
+ TQString parag_text = textLine(i);
+ int pos = 0;
+ int first_pos = 0;
+ int current_line = 0;
+ while(true) {
+ while(lineOfChar(i, pos) == current_line) pos++;
+ (*stream) << parag_text.mid(first_pos, pos - first_pos - 1) << '\n';
+ current_line++;
+ first_pos = pos;
+ if (current_line+1 == lines_in_parag)
+ {
+ // Last line
+ (*stream) << parag_text.mid(pos);
+ break;
+ }
+ }
+ }
+ if (i < line_count)
+ (*stream) << '\n';
+ }
+ }
+}
+
+int KEdit::currentLine(){
+
+ computePosition();
+ return line_pos;
+
+}
+
+int KEdit::currentColumn(){
+
+ computePosition();
+ return col_pos;
+}
+
+void KEdit::slotCursorPositionChanged()
+{
+ d->posDirty = true;
+ emit CursorPositionChanged();
+}
+
+void KEdit::computePosition()
+{
+ if (!d->posDirty) return;
+ d->posDirty = false;
+
+ int line, col;
+
+ getCursorPosition(&line,&col);
+
+ // line is expressed in paragraphs, we now need to convert to lines
+ line_pos = 0;
+ if (wordWrap() == NoWrap)
+ {
+ line_pos = line;
+ }
+ else
+ {
+ for(int i = 0; i < line; i++)
+ line_pos += linesOfParagraph(i);
+ }
+
+ int line_offset = lineOfChar(line, col);
+ line_pos += line_offset;
+
+ // We now calculate where the current line starts in the paragraph.
+ TQString linetext = textLine(line);
+ int start_of_line = 0;
+ if (line_offset > 0)
+ {
+ start_of_line = col;
+ while(lineOfChar(line, --start_of_line) == line_offset);
+ start_of_line++;
+ }
+
+
+ // O.K here is the deal: The function getCursorPositoin returns the character
+ // position of the cursor, not the screenposition. I.e,. assume the line
+ // consists of ab\tc then the character c will be on the screen on position 8
+ // whereas getCursorPosition will return 3 if the cursors is on the character c.
+ // Therefore we need to compute the screen position from the character position.
+ // That's what all the following trouble is all about:
+
+ int coltemp = col-start_of_line;
+ int pos = 0;
+ int find = 0;
+ int mem = 0;
+ bool found_one = false;
+
+ // if you understand the following algorithm you are worthy to look at the
+ // kedit+ sources -- if not, go away ;-)
+
+
+ while(find >=0 && find <= coltemp- 1 ){
+ find = linetext.find('\t', find+start_of_line, true )-start_of_line;
+ if( find >=0 && find <= coltemp - 1 ){
+ found_one = true;
+ pos = pos + find - mem;
+ pos = pos + 8 - pos % 8;
+ mem = find;
+ find ++;
+ }
+ }
+
+ pos = pos + coltemp - mem; // add the number of characters behind the
+ // last tab on the line.
+
+ if (found_one){
+ pos = pos - 1;
+ }
+
+ col_pos = pos;
+}
+
+
+void KEdit::keyPressEvent ( TQKeyEvent *e)
+{
+ // ignore Ctrl-Return so that KDialogBase can catch them
+ if ( e->key() == Key_Return && e->state() == ControlButton ) {
+ e->ignore();
+ return;
+ }
+
+ KKey key(e);
+ int keyQt = key.keyCodeQt();
+
+ if ( keyQt == CTRL+Key_K ){
+
+ int line = 0;
+ int col = 0;
+ TQString killstring;
+
+ if(!killing){
+ killbufferstring = "";
+ killtrue = false;
+ lastwasanewline = false;
+ }
+
+ if(!atEnd()){
+
+ getCursorPosition(&line,&col);
+ killstring = textLine(line);
+ killstring = killstring.mid(col,killstring.length());
+
+
+ if(!killbufferstring.isEmpty() && !killtrue && !lastwasanewline){
+ killbufferstring += '\n';
+ }
+
+ if( (killstring.length() == 0) && !killtrue){
+ killbufferstring += '\n';
+ lastwasanewline = true;
+ }
+
+ if(killstring.length() > 0){
+
+ killbufferstring += killstring;
+ lastwasanewline = false;
+ killtrue = true;
+
+ }else{
+
+ lastwasanewline = false;
+ killtrue = !killtrue;
+
+ }
+
+ }else{
+
+ if(killbufferstring.isEmpty() && !killtrue && !lastwasanewline){
+ killtrue = true;
+ }
+
+ }
+
+ killing = true;
+
+ TQMultiLineEdit::keyPressEvent(e);
+ setModified(true);
+ return;
+ }
+ else if ( keyQt == CTRL+Key_Y ){
+
+ int line = 0;
+ int col = 0;
+
+ getCursorPosition(&line,&col);
+
+ TQString tmpstring = killbufferstring;
+ if(!killtrue)
+ tmpstring += '\n';
+
+ insertAt(tmpstring,line,col);
+
+ killing = false;
+ setModified(true);
+ return;
+ }
+
+ killing = false;
+
+ if ( KStdAccel::copy().contains( key ) )
+ copy();
+ else if ( isReadOnly() )
+ TQMultiLineEdit::keyPressEvent( e );
+ // If this is an unmodified printable key, send it directly to TQMultiLineEdit.
+ else if ( !(key.keyCodeQt() & (CTRL | ALT)) && !e->text().isEmpty() && TQString(e->text()).tqunicode()->isPrint() )
+ TQMultiLineEdit::keyPressEvent( e );
+ else if ( KStdAccel::paste().contains( key ) ) {
+ paste();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::cut().contains( key ) ) {
+ cut();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::undo().contains( key ) ) {
+ undo();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::redo().contains( key ) ) {
+ redo();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::deleteWordBack().contains( key ) ) {
+ moveCursor(MoveWordBackward, true);
+ if (hasSelectedText())
+ del();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::deleteWordForward().contains( key ) ) {
+ moveCursor(MoveWordForward, true);
+ if (hasSelectedText())
+ del();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::backwardWord().contains( key ) ) {
+ CursorAction action = MoveWordBackward;
+ int para, index;
+ getCursorPosition( &para, & index );
+ if (text(para).isRightToLeft())
+ action = MoveWordForward;
+ moveCursor(action, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::forwardWord().contains( key ) ) {
+ CursorAction action = MoveWordForward;
+ int para, index;
+ getCursorPosition( &para, & index );
+ if (text(para).isRightToLeft())
+ action = MoveWordBackward;
+ moveCursor( action, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::next().contains( key ) ) {
+ moveCursor( MovePgDown, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::prior().contains( key ) ) {
+ moveCursor( MovePgUp, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::home().contains( key ) ) {
+ moveCursor( MoveHome, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::end().contains( key ) ) {
+ moveCursor( MoveEnd, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::beginningOfLine().contains( key ) ) {
+ moveCursor( MoveLineStart, false);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::endOfLine().contains( key ) ) {
+ moveCursor( MoveLineEnd, false);
+ slotCursorPositionChanged();
+ }
+ else if ( key == Key_Insert ) {
+ if (d->overwriteEnabled)
+ {
+ this->setOverwriteMode(!this->isOverwriteMode());
+ emit toggle_overwrite_signal();
+ }
+ }
+ else
+ TQMultiLineEdit::keyPressEvent(e);
+}
+
+void KEdit::installRBPopup(TQPopupMenu *p) {
+ KContextMenuManager::insert( this, p );
+}
+
+void KEdit::selectFont(){
+
+ TQFont font = this->font();
+ KFontDialog::getFont(font);
+ this->setFont(font);
+
+}
+
+void KEdit::doGotoLine() {
+
+ if( !gotodialog )
+ gotodialog = new KEdGotoLine( parent, "gotodialog" );
+
+ this->clearFocus();
+
+ gotodialog->exec();
+ // this seems to be not necessary
+ // gotodialog->setFocus();
+ if( gotodialog->result() != KEdGotoLine::Accepted)
+ return;
+ int target_line = gotodialog->getLineNumber()-1;
+ if (wordWrap() == NoWrap)
+ {
+ setCursorPosition( target_line, 0 );
+ setFocus();
+ return;
+ }
+
+ int max_parag = paragraphs();
+
+ int line = 0;
+ int parag = -1;
+ int lines_in_parag = 0;
+ while ((++parag < max_parag) && (line + lines_in_parag < target_line))
+ {
+ line += lines_in_parag;
+ lines_in_parag = linesOfParagraph(parag);
+ }
+
+ int col = 0;
+ if (parag >= max_parag)
+ {
+ target_line = line + lines_in_parag - 1;
+ parag = max_parag-1;
+ }
+
+ while(1+line+lineOfChar(parag,col) < target_line) col++;
+ setCursorPosition( parag, col );
+ setFocus();
+}
+
+
+void KEdit::dragMoveEvent(TQDragMoveEvent* e) {
+
+ if(KURLDrag::canDecode(e))
+ e->accept();
+ else if(TQTextDrag::canDecode(e))
+ TQMultiLineEdit::dragMoveEvent(e);
+}
+
+void KEdit::contentsDragMoveEvent(TQDragMoveEvent* e) {
+
+ if(KURLDrag::canDecode(e))
+ e->accept();
+ else if(TQTextDrag::canDecode(e))
+ TQMultiLineEdit::contentsDragMoveEvent(e);
+}
+
+void KEdit::dragEnterEvent(TQDragEnterEvent* e) {
+
+ kdDebug() << "KEdit::dragEnterEvent()" << endl;
+ e->accept(KURLDrag::canDecode(e) || TQTextDrag::canDecode(e));
+}
+
+void KEdit::contentsDragEnterEvent(TQDragEnterEvent* e) {
+
+ kdDebug() << "KEdit::contentsDragEnterEvent()" << endl;
+ e->accept(KURLDrag::canDecode(e) || TQTextDrag::canDecode(e));
+}
+
+
+void KEdit::dropEvent(TQDropEvent* e) {
+
+ kdDebug() << "KEdit::dropEvent()" << endl;
+
+ if(KURLDrag::canDecode(e)) {
+ emit gotUrlDrop(e);
+ }
+ else if(TQTextDrag::canDecode(e))
+ TQMultiLineEdit::dropEvent(e);
+}
+
+void KEdit::contentsDropEvent(TQDropEvent* e) {
+
+ kdDebug() << "KEdit::contentsDropEvent()" << endl;
+
+ if(KURLDrag::canDecode(e)) {
+ emit gotUrlDrop(e);
+ }
+ else if(TQTextDrag::canDecode(e))
+ TQMultiLineEdit::contentsDropEvent(e);
+}
+
+void KEdit::setOverwriteEnabled(bool b)
+{
+ d->overwriteEnabled = b;
+}
+
+// TQWidget::create() turns off mouse-Tracking which would break auto-hiding
+void KEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
+{
+ TQMultiLineEdit::create( id, initializeWindow, destroyOldWindow );
+ KCursor::setAutoHideCursor( this, true );
+}
+
+void KEdit::ensureCursorVisible()
+{
+ if (!d->autoUpdate)
+ return;
+
+ TQMultiLineEdit::ensureCursorVisible();
+}
+
+void KEdit::setCursor( const TQCursor &c )
+{
+ if (!d->autoUpdate)
+ return;
+
+ TQMultiLineEdit::setCursor(c);
+}
+
+void KEdit::viewportPaintEvent( TQPaintEvent*pe )
+{
+ if (!d->autoUpdate)
+ return;
+
+ TQMultiLineEdit::viewportPaintEvent(pe);
+}
+
+
+void KEdGotoLine::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+void KEdFind::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+void KEdReplace::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+void KEdit::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+