00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <qdragobject.h>
00023 #include <qpopupmenu.h>
00024 #include <qtextstream.h>
00025 #include <qtimer.h>
00026
00027 #include <kapplication.h>
00028 #include <kcursor.h>
00029 #include <kdebug.h>
00030 #include <kcmenumngr.h>
00031 #include <kfontdialog.h>
00032 #include <klocale.h>
00033 #include <kmessagebox.h>
00034 #include <kstdaccel.h>
00035 #include <kurldrag.h>
00036
00037 #include "keditcl.h"
00038 #include "keditcl.moc"
00039
00040 class KEdit::KEditPrivate
00041 {
00042 public:
00043 bool overwriteEnabled:1;
00044 bool posDirty:1;
00045 bool autoUpdate:1;
00046 };
00047
00048
00049 KEdit::KEdit(QWidget *_parent, const char *name)
00050 : QMultiLineEdit(_parent, name)
00051 {
00052 d = new KEditPrivate;
00053 d->overwriteEnabled = false;
00054 d->posDirty = true;
00055 d->autoUpdate = true;
00056
00057 parent = _parent;
00058
00059
00060
00061 line_pos = col_pos = 0;
00062
00063 srchdialog = NULL;
00064 replace_dialog= NULL;
00065 gotodialog = NULL;
00066
00067 setAcceptDrops(true);
00068 KCursor::setAutoHideCursor( this, true );
00069
00070 connect(this, SIGNAL(cursorPositionChanged(int,int)),
00071 this, SLOT(slotCursorPositionChanged()));
00072 }
00073
00074
00075 KEdit::~KEdit()
00076 {
00077 delete d;
00078 }
00079
00080 void
00081 KEdit::setAutoUpdate(bool b)
00082 {
00083 d->autoUpdate = b;
00084 }
00085
00086 void
00087 KEdit::insertText(QTextStream *stream)
00088 {
00089
00090 int line, col;
00091 getCursorPosition(&line, &col);
00092 int saveline = line;
00093 int savecol = col;
00094 QString textLine;
00095
00096
00097
00098
00099
00100
00101
00102 int oldUndoDepth = undoDepth();
00103 setUndoDepth( 0 );
00104
00105
00106
00107 QIODevice *dev=stream->device();
00108 if (dev && dev->size()>(1024*1024)) {
00109 while(1) {
00110 int i;
00111 textLine="";
00112 for (i=0; i<5000; i++) {
00113 QString line=stream->readLine();
00114 if (line.isNull()) break;
00115 textLine+=line+'\n';
00116 }
00117 insertAt(textLine, line, col);
00118 line+=i; col=0;
00119 if (i!=5000) break;
00120 }
00121 }
00122 else {
00123 textLine = stream->read();
00124 insertAt( textLine, line, col);
00125 }
00126 setUndoDepth( oldUndoDepth );
00127
00128 setCursorPosition(saveline, savecol);
00129
00130
00131
00132
00133 setModified(true);
00134 setFocus();
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 }
00146
00147 void
00148 KEdit::cleanWhiteSpace()
00149 {
00150 d->autoUpdate = false;
00151 if (!hasMarkedText())
00152 selectAll();
00153 QString oldText = markedText();
00154 QString newText;
00155 QStringList lines = QStringList::split('\n', oldText, true);
00156 bool addSpace = false;
00157 bool firstLine = true;
00158 QChar lastChar = oldText[oldText.length()-1];
00159 QChar firstChar = oldText[0];
00160 for(QStringList::Iterator it = lines.begin();
00161 it != lines.end();)
00162 {
00163 QString line = (*it).simplifyWhiteSpace();
00164 if (line.isEmpty())
00165 {
00166 if (addSpace)
00167 newText += QString::fromLatin1("\n\n");
00168 if (firstLine)
00169 {
00170 if (firstChar.isSpace())
00171 newText += '\n';
00172 firstLine = false;
00173 }
00174 addSpace = false;
00175 }
00176 else
00177 {
00178 if (addSpace)
00179 newText += ' ';
00180 if (firstLine)
00181 {
00182 if (firstChar.isSpace())
00183 newText += ' ';
00184 firstLine = false;
00185 }
00186 newText += line;
00187 addSpace = true;
00188 }
00189 it = lines.remove(it);
00190 }
00191 if (addSpace)
00192 {
00193 if (lastChar == '\n')
00194 newText += '\n';
00195 else if (lastChar.isSpace())
00196 newText += ' ';
00197 }
00198
00199 if (oldText == newText)
00200 {
00201 deselect();
00202 d->autoUpdate = true;
00203 repaint();
00204 return;
00205 }
00206 if (wordWrap() == NoWrap)
00207 {
00208
00209
00210
00211 QMultiLineEdit *we = new QMultiLineEdit();
00212 we->setWordWrap(FixedColumnWidth);
00213 we->setWrapColumnOrWidth(78);
00214 we->setText(newText);
00215 newText = QString::null;
00216 for(int i = 0; i < we->numLines(); i++)
00217 {
00218 QString line = we->textLine(i);
00219 if (line.right(1) != "\n")
00220 line += '\n';
00221 newText += line;
00222 }
00223 delete we;
00224 }
00225
00226 insert(newText);
00227 d->autoUpdate = true;
00228 repaint();
00229
00230 setModified(true);
00231 setFocus();
00232 }
00233
00234
00235 void
00236 KEdit::saveText(QTextStream *stream)
00237 {
00238 saveText(stream, false);
00239 }
00240
00241 void
00242 KEdit::saveText(QTextStream *stream, bool softWrap)
00243 {
00244 int line_count = numLines()-1;
00245 if (line_count < 0)
00246 return;
00247
00248 if (softWrap || (wordWrap() == NoWrap))
00249 {
00250 for(int i = 0; i < line_count; i++)
00251 {
00252 (*stream) << textLine(i) << '\n';
00253 }
00254 (*stream) << textLine(line_count);
00255 }
00256 else
00257 {
00258 for(int i = 0; i <= line_count; i++)
00259 {
00260 int lines_in_parag = linesOfParagraph(i);
00261 if (lines_in_parag == 1)
00262 {
00263 (*stream) << textLine(i);
00264 }
00265 else
00266 {
00267 QString parag_text = textLine(i);
00268 int pos = 0;
00269 int first_pos = 0;
00270 int current_line = 0;
00271 while(true) {
00272 while(lineOfChar(i, pos) == current_line) pos++;
00273 (*stream) << parag_text.mid(first_pos, pos - first_pos - 1) << '\n';
00274 current_line++;
00275 first_pos = pos;
00276 if (current_line+1 == lines_in_parag)
00277 {
00278
00279 (*stream) << parag_text.mid(pos);
00280 break;
00281 }
00282 }
00283 }
00284 if (i < line_count)
00285 (*stream) << '\n';
00286 }
00287 }
00288 }
00289
00290 int KEdit::currentLine(){
00291
00292 computePosition();
00293 return line_pos;
00294
00295 }
00296
00297 int KEdit::currentColumn(){
00298
00299 computePosition();
00300 return col_pos;
00301 }
00302
00303 void KEdit::slotCursorPositionChanged()
00304 {
00305 d->posDirty = true;
00306 emit CursorPositionChanged();
00307 }
00308
00309 void KEdit::computePosition()
00310 {
00311 if (!d->posDirty) return;
00312 d->posDirty = false;
00313
00314 int line, col;
00315
00316 getCursorPosition(&line,&col);
00317
00318
00319 line_pos = 0;
00320 if (wordWrap() == NoWrap)
00321 {
00322 line_pos = line;
00323 }
00324 else
00325 {
00326 for(int i = 0; i < line; i++)
00327 line_pos += linesOfParagraph(i);
00328 }
00329
00330 int line_offset = lineOfChar(line, col);
00331 line_pos += line_offset;
00332
00333
00334 QString linetext = textLine(line);
00335 int start_of_line = 0;
00336 if (line_offset > 0)
00337 {
00338 start_of_line = col;
00339 while(lineOfChar(line, --start_of_line) == line_offset);
00340 start_of_line++;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 int coltemp = col-start_of_line;
00352 int pos = 0;
00353 int find = 0;
00354 int mem = 0;
00355 bool found_one = false;
00356
00357
00358
00359
00360
00361 while(find >=0 && find <= coltemp- 1 ){
00362 find = linetext.find('\t', find+start_of_line, true )-start_of_line;
00363 if( find >=0 && find <= coltemp - 1 ){
00364 found_one = true;
00365 pos = pos + find - mem;
00366 pos = pos + 8 - pos % 8;
00367 mem = find;
00368 find ++;
00369 }
00370 }
00371
00372 pos = pos + coltemp - mem;
00373
00374
00375 if (found_one){
00376 pos = pos - 1;
00377 }
00378
00379 col_pos = pos;
00380 }
00381
00382
00383 void KEdit::keyPressEvent ( QKeyEvent *e)
00384 {
00385
00386 if ( e->key() == Key_Return && e->state() == ControlButton ) {
00387 e->ignore();
00388 return;
00389 }
00390
00391 KKey key(e);
00392 int keyQt = key.keyCodeQt();
00393
00394 if ( keyQt == CTRL+Key_K ){
00395
00396 int line = 0;
00397 int col = 0;
00398 QString killstring;
00399
00400 if(!killing){
00401 killbufferstring = "";
00402 killtrue = false;
00403 lastwasanewline = false;
00404 }
00405
00406 if(!atEnd()){
00407
00408 getCursorPosition(&line,&col);
00409 killstring = textLine(line);
00410 killstring = killstring.mid(col,killstring.length());
00411
00412
00413 if(!killbufferstring.isEmpty() && !killtrue && !lastwasanewline){
00414 killbufferstring += '\n';
00415 }
00416
00417 if( (killstring.length() == 0) && !killtrue){
00418 killbufferstring += '\n';
00419 lastwasanewline = true;
00420 }
00421
00422 if(killstring.length() > 0){
00423
00424 killbufferstring += killstring;
00425 lastwasanewline = false;
00426 killtrue = true;
00427
00428 }else{
00429
00430 lastwasanewline = false;
00431 killtrue = !killtrue;
00432
00433 }
00434
00435 }else{
00436
00437 if(killbufferstring.isEmpty() && !killtrue && !lastwasanewline){
00438 killtrue = true;
00439 }
00440
00441 }
00442
00443 killing = true;
00444
00445 QMultiLineEdit::keyPressEvent(e);
00446 setModified(true);
00447 return;
00448 }
00449 else if ( keyQt == CTRL+Key_Y ){
00450
00451 int line = 0;
00452 int col = 0;
00453
00454 getCursorPosition(&line,&col);
00455
00456 QString tmpstring = killbufferstring;
00457 if(!killtrue)
00458 tmpstring += '\n';
00459
00460 insertAt(tmpstring,line,col);
00461
00462 killing = false;
00463 setModified(true);
00464 return;
00465 }
00466
00467 killing = false;
00468
00469 if ( KStdAccel::copy().contains( key ) )
00470 copy();
00471 else if ( isReadOnly() )
00472 QMultiLineEdit::keyPressEvent( e );
00473
00474 else if ( !(key.keyCodeQt() & (CTRL | ALT)) && !e->text().isEmpty() && e->text().unicode()->isPrint() )
00475 QMultiLineEdit::keyPressEvent( e );
00476 else if ( KStdAccel::paste().contains( key ) ) {
00477 paste();
00478 setModified(true);
00479 slotCursorPositionChanged();
00480 }
00481 else if ( KStdAccel::cut().contains( key ) ) {
00482 cut();
00483 setModified(true);
00484 slotCursorPositionChanged();
00485 }
00486 else if ( KStdAccel::undo().contains( key ) ) {
00487 undo();
00488 setModified(true);
00489 slotCursorPositionChanged();
00490 }
00491 else if ( KStdAccel::redo().contains( key ) ) {
00492 redo();
00493 setModified(true);
00494 slotCursorPositionChanged();
00495 }
00496 else if ( KStdAccel::deleteWordBack().contains( key ) ) {
00497 moveCursor(MoveWordBackward, true);
00498 if (hasSelectedText())
00499 del();
00500 setModified(true);
00501 slotCursorPositionChanged();
00502 }
00503 else if ( KStdAccel::deleteWordForward().contains( key ) ) {
00504 moveCursor(MoveWordForward, true);
00505 if (hasSelectedText())
00506 del();
00507 setModified(true);
00508 slotCursorPositionChanged();
00509 }
00510 else if ( KStdAccel::backwardWord().contains( key ) ) {
00511 CursorAction action = MoveWordBackward;
00512 int para, index;
00513 getCursorPosition( ¶, & index );
00514 if (text(para).isRightToLeft())
00515 action = MoveWordForward;
00516 moveCursor(action, false );
00517 slotCursorPositionChanged();
00518 }
00519 else if ( KStdAccel::forwardWord().contains( key ) ) {
00520 CursorAction action = MoveWordForward;
00521 int para, index;
00522 getCursorPosition( ¶, & index );
00523 if (text(para).isRightToLeft())
00524 action = MoveWordBackward;
00525 moveCursor( action, false );
00526 slotCursorPositionChanged();
00527 }
00528 else if ( KStdAccel::next().contains( key ) ) {
00529 moveCursor( MovePgDown, false );
00530 slotCursorPositionChanged();
00531 }
00532 else if ( KStdAccel::prior().contains( key ) ) {
00533 moveCursor( MovePgUp, false );
00534 slotCursorPositionChanged();
00535 }
00536 else if ( KStdAccel::home().contains( key ) ) {
00537 moveCursor( MoveHome, false );
00538 slotCursorPositionChanged();
00539 }
00540 else if ( KStdAccel::end().contains( key ) ) {
00541 moveCursor( MoveEnd, false );
00542 slotCursorPositionChanged();
00543 }
00544 else if ( KStdAccel::beginningOfLine().contains( key ) ) {
00545 moveCursor( MoveLineStart, false);
00546 slotCursorPositionChanged();
00547 }
00548 else if ( KStdAccel::endOfLine().contains( key ) ) {
00549 moveCursor( MoveLineEnd, false);
00550 slotCursorPositionChanged();
00551 }
00552 else if ( key == Key_Insert ) {
00553 if (d->overwriteEnabled)
00554 {
00555 this->setOverwriteMode(!this->isOverwriteMode());
00556 emit toggle_overwrite_signal();
00557 }
00558 }
00559 else
00560 QMultiLineEdit::keyPressEvent(e);
00561 }
00562
00563 void KEdit::installRBPopup(QPopupMenu *p) {
00564 KContextMenuManager::insert( this, p );
00565 }
00566
00567 void KEdit::selectFont(){
00568
00569 QFont font = this->font();
00570 KFontDialog::getFont(font);
00571 this->setFont(font);
00572
00573 }
00574
00575 void KEdit::doGotoLine() {
00576
00577 if( !gotodialog )
00578 gotodialog = new KEdGotoLine( parent, "gotodialog" );
00579
00580 this->clearFocus();
00581
00582 gotodialog->exec();
00583
00584
00585 if( gotodialog->result() != KEdGotoLine::Accepted)
00586 return;
00587 int target_line = gotodialog->getLineNumber()-1;
00588 if (wordWrap() == NoWrap)
00589 {
00590 setCursorPosition( target_line, 0 );
00591 setFocus();
00592 return;
00593 }
00594
00595 int max_parag = paragraphs();
00596
00597 int line = 0;
00598 int parag = -1;
00599 int lines_in_parag = 0;
00600 while ((++parag < max_parag) && (line + lines_in_parag < target_line))
00601 {
00602 line += lines_in_parag;
00603 lines_in_parag = linesOfParagraph(parag);
00604 }
00605
00606 int col = 0;
00607 if (parag >= max_parag)
00608 {
00609 target_line = line + lines_in_parag - 1;
00610 parag = max_parag-1;
00611 }
00612
00613 while(1+line+lineOfChar(parag,col) < target_line) col++;
00614 setCursorPosition( parag, col );
00615 setFocus();
00616 }
00617
00618
00619 void KEdit::dragMoveEvent(QDragMoveEvent* e) {
00620
00621 if(KURLDrag::canDecode(e))
00622 e->accept();
00623 else if(QTextDrag::canDecode(e))
00624 QMultiLineEdit::dragMoveEvent(e);
00625 }
00626
00627 void KEdit::contentsDragMoveEvent(QDragMoveEvent* e) {
00628
00629 if(KURLDrag::canDecode(e))
00630 e->accept();
00631 else if(QTextDrag::canDecode(e))
00632 QMultiLineEdit::contentsDragMoveEvent(e);
00633 }
00634
00635 void KEdit::dragEnterEvent(QDragEnterEvent* e) {
00636
00637 kdDebug() << "KEdit::dragEnterEvent()" << endl;
00638 e->accept(KURLDrag::canDecode(e) || QTextDrag::canDecode(e));
00639 }
00640
00641 void KEdit::contentsDragEnterEvent(QDragEnterEvent* e) {
00642
00643 kdDebug() << "KEdit::contentsDragEnterEvent()" << endl;
00644 e->accept(KURLDrag::canDecode(e) || QTextDrag::canDecode(e));
00645 }
00646
00647
00648 void KEdit::dropEvent(QDropEvent* e) {
00649
00650 kdDebug() << "KEdit::dropEvent()" << endl;
00651
00652 if(KURLDrag::canDecode(e)) {
00653 emit gotUrlDrop(e);
00654 }
00655 else if(QTextDrag::canDecode(e))
00656 QMultiLineEdit::dropEvent(e);
00657 }
00658
00659 void KEdit::contentsDropEvent(QDropEvent* e) {
00660
00661 kdDebug() << "KEdit::contentsDropEvent()" << endl;
00662
00663 if(KURLDrag::canDecode(e)) {
00664 emit gotUrlDrop(e);
00665 }
00666 else if(QTextDrag::canDecode(e))
00667 QMultiLineEdit::contentsDropEvent(e);
00668 }
00669
00670 void KEdit::setOverwriteEnabled(bool b)
00671 {
00672 d->overwriteEnabled = b;
00673 }
00674
00675
00676 void KEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
00677 {
00678 QMultiLineEdit::create( id, initializeWindow, destroyOldWindow );
00679 KCursor::setAutoHideCursor( this, true );
00680 }
00681
00682 void KEdit::ensureCursorVisible()
00683 {
00684 if (!d->autoUpdate)
00685 return;
00686
00687 QMultiLineEdit::ensureCursorVisible();
00688 }
00689
00690 void KEdit::setCursor( const QCursor &c )
00691 {
00692 if (!d->autoUpdate)
00693 return;
00694
00695 QMultiLineEdit::setCursor(c);
00696 }
00697
00698 void KEdit::viewportPaintEvent( QPaintEvent*pe )
00699 {
00700 if (!d->autoUpdate)
00701 return;
00702
00703 QMultiLineEdit::viewportPaintEvent(pe);
00704 }
00705
00706
00707 void KEdGotoLine::virtual_hook( int id, void* data )
00708 { KDialogBase::virtual_hook( id, data ); }
00709
00710 void KEdFind::virtual_hook( int id, void* data )
00711 { KDialogBase::virtual_hook( id, data ); }
00712
00713 void KEdReplace::virtual_hook( int id, void* data )
00714 { KDialogBase::virtual_hook( id, data ); }
00715
00716 void KEdit::virtual_hook( int, void* )
00717 { }
00718