00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "katedocument.h"
00023 #include "katedocument.moc"
00024 #include "katekeyinterceptorfunctor.h"
00025 #include "katefactory.h"
00026 #include "katedialogs.h"
00027 #include "katehighlight.h"
00028 #include "kateview.h"
00029 #include "katesearch.h"
00030 #include "kateautoindent.h"
00031 #include "katetextline.h"
00032 #include "katedocumenthelpers.h"
00033 #include "kateprinter.h"
00034 #include "katelinerange.h"
00035 #include "katesupercursor.h"
00036 #include "katearbitraryhighlight.h"
00037 #include "katerenderer.h"
00038 #include "kateattribute.h"
00039 #include "kateconfig.h"
00040 #include "katefiletype.h"
00041 #include "kateschema.h"
00042 #include "katetemplatehandler.h"
00043 #include <ktexteditor/plugin.h>
00044
00045 #include <kio/job.h>
00046 #include <kio/netaccess.h>
00047 #include <kio/kfileitem.h>
00048
00049
00050 #include <kparts/event.h>
00051
00052 #include <klocale.h>
00053 #include <kglobal.h>
00054 #include <kapplication.h>
00055 #include <kpopupmenu.h>
00056 #include <kconfig.h>
00057 #include <kfiledialog.h>
00058 #include <kmessagebox.h>
00059 #include <kstdaction.h>
00060 #include <kiconloader.h>
00061 #include <kxmlguifactory.h>
00062 #include <kdialogbase.h>
00063 #include <kdebug.h>
00064 #include <kglobalsettings.h>
00065 #include <klibloader.h>
00066 #include <kdirwatch.h>
00067 #include <kwin.h>
00068 #include <kencodingfiledialog.h>
00069 #include <ktempfile.h>
00070 #include <kmdcodec.h>
00071
00072 #include <qtimer.h>
00073 #include <qfile.h>
00074 #include <qclipboard.h>
00075 #include <qtextstream.h>
00076 #include <qtextcodec.h>
00077 #include <qmap.h>
00078
00079
00080
00081 class KatePartPluginItem
00082 {
00083 public:
00084 KTextEditor::Plugin *plugin;
00085 };
00086
00087
00088
00089
00090
00091
00092 KateDocument::KateDocument ( bool bSingleViewMode, bool bBrowserView,
00093 bool bReadOnly, QWidget *parentWidget,
00094 const char *widgetName, QObject *parent, const char *name)
00095 : Kate::Document(parent, name),
00096 m_plugins (KateFactory::self()->plugins().count()),
00097 m_undoDontMerge(false),
00098 m_undoIgnoreCancel(false),
00099 lastUndoGroupWhenSaved( 0 ),
00100 docWasSavedWhenUndoWasEmpty( true ),
00101 m_modOnHd (false),
00102 m_modOnHdReason (0),
00103 m_job (0),
00104 m_tempFile (0),
00105 m_tabInterceptor(0)
00106 {
00107 m_undoComplexMerge=false;
00108 m_isInUndo = false;
00109
00110 setObjId ("KateDocument#"+documentDCOPSuffix());
00111
00112
00113 setBlockSelectionInterfaceDCOPSuffix (documentDCOPSuffix());
00114 setConfigInterfaceDCOPSuffix (documentDCOPSuffix());
00115 setConfigInterfaceExtensionDCOPSuffix (documentDCOPSuffix());
00116 setCursorInterfaceDCOPSuffix (documentDCOPSuffix());
00117 setEditInterfaceDCOPSuffix (documentDCOPSuffix());
00118 setEncodingInterfaceDCOPSuffix (documentDCOPSuffix());
00119 setHighlightingInterfaceDCOPSuffix (documentDCOPSuffix());
00120 setMarkInterfaceDCOPSuffix (documentDCOPSuffix());
00121 setMarkInterfaceExtensionDCOPSuffix (documentDCOPSuffix());
00122 setPrintInterfaceDCOPSuffix (documentDCOPSuffix());
00123 setSearchInterfaceDCOPSuffix (documentDCOPSuffix());
00124 setSelectionInterfaceDCOPSuffix (documentDCOPSuffix());
00125 setSelectionInterfaceExtDCOPSuffix (documentDCOPSuffix());
00126 setSessionConfigInterfaceDCOPSuffix (documentDCOPSuffix());
00127 setUndoInterfaceDCOPSuffix (documentDCOPSuffix());
00128 setWordWrapInterfaceDCOPSuffix (documentDCOPSuffix());
00129
00130
00131 m_plugins.fill (0);
00132
00133
00134 KateFactory::self()->registerDocument (this);
00135
00136 m_reloading = false;
00137 m_loading = false;
00138 m_encodingSticky = false;
00139
00140 m_buffer = new KateBuffer (this);
00141
00142
00143
00144 m_config = new KateDocumentConfig (this);
00145
00146
00147 m_activeView = 0L;
00148
00149 hlSetByUser = false;
00150 m_fileType = -1;
00151 m_fileTypeSetByUser = false;
00152 setInstance( KateFactory::self()->instance() );
00153
00154 editSessionNumber = 0;
00155 editIsRunning = false;
00156 m_editCurrentUndo = 0L;
00157 editWithUndo = false;
00158
00159 m_docNameNumber = 0;
00160
00161 m_bSingleViewMode = bSingleViewMode;
00162 m_bBrowserView = bBrowserView;
00163 m_bReadOnly = bReadOnly;
00164
00165 m_marks.setAutoDelete( true );
00166 m_markPixmaps.setAutoDelete( true );
00167 m_markDescriptions.setAutoDelete( true );
00168 setMarksUserChangable( markType01 );
00169
00170 m_undoMergeTimer = new QTimer(this);
00171 connect(m_undoMergeTimer, SIGNAL(timeout()), SLOT(undoCancel()));
00172
00173 clearMarks ();
00174 clearUndo ();
00175 clearRedo ();
00176 setModified (false);
00177 docWasSavedWhenUndoWasEmpty = true;
00178
00179
00180 m_buffer->setHighlight (0);
00181
00182 m_extension = new KateBrowserExtension( this );
00183 m_arbitraryHL = new KateArbitraryHighlight();
00184 m_indenter = KateAutoIndent::createIndenter ( this, 0 );
00185
00186 m_indenter->updateConfig ();
00187
00188
00189 connect(m_buffer, SIGNAL(tagLines(int,int)), this, SLOT(tagLines(int,int)));
00190 connect(m_buffer, SIGNAL(codeFoldingUpdated()),this,SIGNAL(codeFoldingUpdated()));
00191
00192
00193 connect(KateHlManager::self(),SIGNAL(changed()),SLOT(internalHlChanged()));
00194
00195
00196 connect(m_arbitraryHL, SIGNAL(tagLines(KateView*, KateSuperRange*)), SLOT(tagArbitraryLines(KateView*, KateSuperRange*)));
00197
00198
00199 connect( KateFactory::self()->dirWatch(), SIGNAL(dirty (const QString &)),
00200 this, SLOT(slotModOnHdDirty (const QString &)) );
00201
00202 connect( KateFactory::self()->dirWatch(), SIGNAL(created (const QString &)),
00203 this, SLOT(slotModOnHdCreated (const QString &)) );
00204
00205 connect( KateFactory::self()->dirWatch(), SIGNAL(deleted (const QString &)),
00206 this, SLOT(slotModOnHdDeleted (const QString &)) );
00207
00208
00209 setDocName ("");
00210
00211
00212 if ( m_bSingleViewMode )
00213 {
00214 KTextEditor::View *view = createView( parentWidget, widgetName );
00215 insertChildClient( view );
00216 view->show();
00217 setWidget( view );
00218 }
00219
00220 connect(this,SIGNAL(sigQueryClose(bool *, bool*)),this,SLOT(slotQueryClose_save(bool *, bool*)));
00221
00222 m_isasking = 0;
00223
00224
00225 for (uint i=0; i<KateFactory::self()->plugins().count(); i++)
00226 {
00227 if (config()->plugin (i))
00228 loadPlugin (i);
00229 }
00230 }
00231
00232
00233
00234
00235 KateDocument::~KateDocument()
00236 {
00237
00238 deactivateDirWatch ();
00239
00240 if (!singleViewMode())
00241 {
00242
00243 m_views.setAutoDelete( true );
00244 m_views.clear();
00245 }
00246
00247 delete m_editCurrentUndo;
00248
00249 delete m_arbitraryHL;
00250
00251
00252 undoItems.setAutoDelete(true);
00253 undoItems.clear();
00254
00255
00256 unloadAllPlugins ();
00257
00258 delete m_config;
00259 delete m_indenter;
00260 KateFactory::self()->deregisterDocument (this);
00261 }
00262
00263
00264
00265 void KateDocument::unloadAllPlugins ()
00266 {
00267 for (uint i=0; i<m_plugins.count(); i++)
00268 unloadPlugin (i);
00269 }
00270
00271 void KateDocument::enableAllPluginsGUI (KateView *view)
00272 {
00273 for (uint i=0; i<m_plugins.count(); i++)
00274 enablePluginGUI (m_plugins[i], view);
00275 }
00276
00277 void KateDocument::disableAllPluginsGUI (KateView *view)
00278 {
00279 for (uint i=0; i<m_plugins.count(); i++)
00280 disablePluginGUI (m_plugins[i], view);
00281 }
00282
00283 void KateDocument::loadPlugin (uint pluginIndex)
00284 {
00285 if (m_plugins[pluginIndex]) return;
00286
00287 m_plugins[pluginIndex] = KTextEditor::createPlugin (QFile::encodeName((KateFactory::self()->plugins())[pluginIndex]->library()), this);
00288
00289 enablePluginGUI (m_plugins[pluginIndex]);
00290 }
00291
00292 void KateDocument::unloadPlugin (uint pluginIndex)
00293 {
00294 if (!m_plugins[pluginIndex]) return;
00295
00296 disablePluginGUI (m_plugins[pluginIndex]);
00297
00298 delete m_plugins[pluginIndex];
00299 m_plugins[pluginIndex] = 0L;
00300 }
00301
00302 void KateDocument::enablePluginGUI (KTextEditor::Plugin *plugin, KateView *view)
00303 {
00304 if (!plugin) return;
00305 if (!KTextEditor::pluginViewInterface(plugin)) return;
00306
00307 KXMLGUIFactory *factory = view->factory();
00308 if ( factory )
00309 factory->removeClient( view );
00310
00311 KTextEditor::pluginViewInterface(plugin)->addView(view);
00312
00313 if ( factory )
00314 factory->addClient( view );
00315 }
00316
00317 void KateDocument::enablePluginGUI (KTextEditor::Plugin *plugin)
00318 {
00319 if (!plugin) return;
00320 if (!KTextEditor::pluginViewInterface(plugin)) return;
00321
00322 for (uint i=0; i< m_views.count(); i++)
00323 enablePluginGUI (plugin, m_views.at(i));
00324 }
00325
00326 void KateDocument::disablePluginGUI (KTextEditor::Plugin *plugin, KateView *view)
00327 {
00328 if (!plugin) return;
00329 if (!KTextEditor::pluginViewInterface(plugin)) return;
00330
00331 KXMLGUIFactory *factory = view->factory();
00332 if ( factory )
00333 factory->removeClient( view );
00334
00335 KTextEditor::pluginViewInterface( plugin )->removeView( view );
00336
00337 if ( factory )
00338 factory->addClient( view );
00339 }
00340
00341 void KateDocument::disablePluginGUI (KTextEditor::Plugin *plugin)
00342 {
00343 if (!plugin) return;
00344 if (!KTextEditor::pluginViewInterface(plugin)) return;
00345
00346 for (uint i=0; i< m_views.count(); i++)
00347 disablePluginGUI (plugin, m_views.at(i));
00348 }
00349
00350
00351
00352
00353 KTextEditor::View *KateDocument::createView( QWidget *parent, const char *name )
00354 {
00355 KateView* newView = new KateView( this, parent, name);
00356 connect(newView, SIGNAL(cursorPositionChanged()), SLOT(undoCancel()));
00357 if ( s_fileChangedDialogsActivated )
00358 connect( newView, SIGNAL(gotFocus( Kate::View * )), this, SLOT(slotModifiedOnDisk()) );
00359 return newView;
00360 }
00361
00362 QPtrList<KTextEditor::View> KateDocument::views () const
00363 {
00364 return m_textEditViews;
00365 }
00366
00367 void KateDocument::setActiveView( KateView *view )
00368 {
00369 if ( m_activeView == view ) return;
00370
00371 m_activeView = view;
00372 }
00373
00374
00375
00376
00377 uint KateDocument::configPages () const
00378 {
00379 return 10;
00380 }
00381
00382 KTextEditor::ConfigPage *KateDocument::configPage (uint number, QWidget *parent, const char * )
00383 {
00384 switch( number )
00385 {
00386 case 0:
00387 return new KateViewDefaultsConfig (parent);
00388
00389 case 1:
00390 return new KateSchemaConfigPage (parent, this);
00391
00392 case 2:
00393 return new KateSelectConfigTab (parent);
00394
00395 case 3:
00396 return new KateEditConfigTab (parent);
00397
00398 case 4:
00399 return new KateIndentConfigTab (parent);
00400
00401 case 5:
00402 return new KateSaveConfigTab (parent);
00403
00404 case 6:
00405 return new KateHlConfigPage (parent, this);
00406
00407 case 7:
00408 return new KateFileTypeConfigTab (parent);
00409
00410 case 8:
00411 return new KateEditKeyConfiguration (parent, this);
00412
00413 case 9:
00414 return new KatePartPluginConfigPage (parent);
00415
00416 default:
00417 return 0;
00418 }
00419
00420 return 0;
00421 }
00422
00423 QString KateDocument::configPageName (uint number) const
00424 {
00425 switch( number )
00426 {
00427 case 0:
00428 return i18n ("Appearance");
00429
00430 case 1:
00431 return i18n ("Fonts & Colors");
00432
00433 case 2:
00434 return i18n ("Cursor & Selection");
00435
00436 case 3:
00437 return i18n ("Editing");
00438
00439 case 4:
00440 return i18n ("Indentation");
00441
00442 case 5:
00443 return i18n("Open/Save");
00444
00445 case 6:
00446 return i18n ("Highlighting");
00447
00448 case 7:
00449 return i18n("Filetypes");
00450
00451 case 8:
00452 return i18n ("Shortcuts");
00453
00454 case 9:
00455 return i18n ("Plugins");
00456
00457 default:
00458 return QString ("");
00459 }
00460
00461 return QString ("");
00462 }
00463
00464 QString KateDocument::configPageFullName (uint number) const
00465 {
00466 switch( number )
00467 {
00468 case 0:
00469 return i18n("Appearance");
00470
00471 case 1:
00472 return i18n ("Font & Color Schemas");
00473
00474 case 2:
00475 return i18n ("Cursor & Selection Behavior");
00476
00477 case 3:
00478 return i18n ("Editing Options");
00479
00480 case 4:
00481 return i18n ("Indentation Rules");
00482
00483 case 5:
00484 return i18n("File Opening & Saving");
00485
00486 case 6:
00487 return i18n ("Highlighting Rules");
00488
00489 case 7:
00490 return i18n("Filetype Specific Settings");
00491
00492 case 8:
00493 return i18n ("Shortcuts Configuration");
00494
00495 case 9:
00496 return i18n ("Plugin Manager");
00497
00498 default:
00499 return QString ("");
00500 }
00501
00502 return QString ("");
00503 }
00504
00505 QPixmap KateDocument::configPagePixmap (uint number, int size) const
00506 {
00507 switch( number )
00508 {
00509 case 0:
00510 return BarIcon("view_text",size);
00511
00512 case 1:
00513 return BarIcon("colorize", size);
00514
00515 case 2:
00516 return BarIcon("frame_edit", size);
00517
00518 case 3:
00519 return BarIcon("edit", size);
00520
00521 case 4:
00522 return BarIcon("rightjust", size);
00523
00524 case 5:
00525 return BarIcon("filesave", size);
00526
00527 case 6:
00528 return BarIcon("source", size);
00529
00530 case 7:
00531 return BarIcon("edit", size);
00532
00533 case 8:
00534 return BarIcon("key_enter", size);
00535
00536 case 9:
00537 return BarIcon("connect_established", size);
00538
00539 default:
00540 return BarIcon("edit", size);
00541 }
00542
00543 return BarIcon("edit", size);
00544 }
00545
00546
00547
00548
00549 QString KateDocument::text() const
00550 {
00551 QString s;
00552
00553 for (uint i = 0; i < m_buffer->count(); i++)
00554 {
00555 KateTextLine::Ptr textLine = m_buffer->plainLine(i);
00556
00557 if (textLine)
00558 {
00559 s.append (textLine->string());
00560
00561 if ((i+1) < m_buffer->count())
00562 s.append('\n');
00563 }
00564 }
00565
00566 return s;
00567 }
00568
00569 QString KateDocument::text ( uint startLine, uint startCol, uint endLine, uint endCol ) const
00570 {
00571 return text(startLine, startCol, endLine, endCol, false);
00572 }
00573
00574 QString KateDocument::text ( uint startLine, uint startCol, uint endLine, uint endCol, bool blockwise) const
00575 {
00576 if ( blockwise && (startCol > endCol) )
00577 return QString ();
00578
00579 QString s;
00580
00581 if (startLine == endLine)
00582 {
00583 if (startCol > endCol)
00584 return QString ();
00585
00586 KateTextLine::Ptr textLine = m_buffer->plainLine(startLine);
00587
00588 if ( !textLine )
00589 return QString ();
00590
00591 return textLine->string(startCol, endCol-startCol);
00592 }
00593 else
00594 {
00595
00596 for (uint i = startLine; (i <= endLine) && (i < m_buffer->count()); i++)
00597 {
00598 KateTextLine::Ptr textLine = m_buffer->plainLine(i);
00599
00600 if ( !blockwise )
00601 {
00602 if (i == startLine)
00603 s.append (textLine->string(startCol, textLine->length()-startCol));
00604 else if (i == endLine)
00605 s.append (textLine->string(0, endCol));
00606 else
00607 s.append (textLine->string());
00608 }
00609 else
00610 {
00611 s.append( textLine->string( startCol, endCol-startCol));
00612 }
00613
00614 if ( i < endLine )
00615 s.append('\n');
00616 }
00617 }
00618
00619 return s;
00620 }
00621
00622 QString KateDocument::textLine( uint line ) const
00623 {
00624 KateTextLine::Ptr l = m_buffer->plainLine(line);
00625
00626 if (!l)
00627 return QString();
00628
00629 return l->string();
00630 }
00631
00632 bool KateDocument::setText(const QString &s)
00633 {
00634 if (!isReadWrite())
00635 return false;
00636
00637 QPtrList<KTextEditor::Mark> m = marks ();
00638 QValueList<KTextEditor::Mark> msave;
00639
00640 for (uint i=0; i < m.count(); i++)
00641 msave.append (*m.at(i));
00642
00643 editStart ();
00644
00645
00646 clear();
00647
00648
00649 insertText (0, 0, s);
00650
00651 editEnd ();
00652
00653 for (uint i=0; i < msave.count(); i++)
00654 setMark (msave[i].line, msave[i].type);
00655
00656 return true;
00657 }
00658
00659 bool KateDocument::clear()
00660 {
00661 if (!isReadWrite())
00662 return false;
00663
00664 for (KateView * view = m_views.first(); view != 0L; view = m_views.next() ) {
00665 view->clear();
00666 view->tagAll();
00667 view->update();
00668 }
00669
00670 clearMarks ();
00671
00672 return removeText (0,0,lastLine()+1, 0);
00673 }
00674
00675 bool KateDocument::insertText( uint line, uint col, const QString &s)
00676 {
00677 return insertText (line, col, s, false);
00678 }
00679
00680 bool KateDocument::insertText( uint line, uint col, const QString &s, bool blockwise )
00681 {
00682 if (!isReadWrite())
00683 return false;
00684
00685 if (s.isEmpty())
00686 return true;
00687
00688 if (line == numLines())
00689 editInsertLine(line,"");
00690 else if (line > lastLine())
00691 return false;
00692
00693 editStart ();
00694
00695 uint insertPos = col;
00696 uint len = s.length();
00697
00698 QString buf;
00699
00700 bool replacetabs = ( config()->configFlags() & KateDocumentConfig::cfReplaceTabsDyn && ! m_isInUndo );
00701 uint tw = config()->tabWidth();
00702 uint insertPosExpanded = insertPos;
00703 KateTextLine::Ptr l = m_buffer->line( line );
00704 if (l != 0)
00705 insertPosExpanded = l->cursorX( insertPos, tw );
00706
00707 for (uint pos = 0; pos < len; pos++)
00708 {
00709 QChar ch = s[pos];
00710
00711 if (ch == '\n')
00712 {
00713 editInsertText (line, insertPos, buf);
00714
00715 if ( !blockwise )
00716 {
00717 editWrapLine (line, insertPos + buf.length());
00718 insertPos = insertPosExpanded = 0;
00719 }
00720 else
00721 {
00722 if ( line == lastLine() )
00723 editWrapLine (line, insertPos + buf.length());
00724 }
00725
00726 line++;
00727 buf.truncate(0);
00728 l = m_buffer->line( line );
00729 if (l)
00730 insertPosExpanded = l->cursorX( insertPos, tw );
00731 }
00732 else
00733 {
00734 if ( replacetabs && ch == '\t' )
00735 {
00736 uint tr = tw - ( insertPosExpanded+buf.length() )%tw;
00737 for ( uint i=0; i < tr; i++ )
00738 buf += ' ';
00739 }
00740 else
00741 buf += ch;
00742 }
00743 }
00744
00745 editInsertText (line, insertPos, buf);
00746
00747 editEnd ();
00748 emit textInserted(line,insertPos);
00749 return true;
00750 }
00751
00752 bool KateDocument::removeText ( uint startLine, uint startCol, uint endLine, uint endCol )
00753 {
00754 return removeText (startLine, startCol, endLine, endCol, false);
00755 }
00756
00757 bool KateDocument::removeText ( uint startLine, uint startCol, uint endLine, uint endCol, bool blockwise)
00758 {
00759 if (!isReadWrite())
00760 return false;
00761
00762 if ( blockwise && (startCol > endCol) )
00763 return false;
00764
00765 if ( startLine > endLine )
00766 return false;
00767
00768 if ( startLine > lastLine() )
00769 return false;
00770
00771 if (!blockwise) {
00772 emit aboutToRemoveText(KateTextRange(startLine,startCol,endLine,endCol));
00773 }
00774 editStart ();
00775
00776 if ( !blockwise )
00777 {
00778 if ( endLine > lastLine() )
00779 {
00780 endLine = lastLine()+1;
00781 endCol = 0;
00782 }
00783
00784 if (startLine == endLine)
00785 {
00786 editRemoveText (startLine, startCol, endCol-startCol);
00787 }
00788 else if ((startLine+1) == endLine)
00789 {
00790 if ( (m_buffer->plainLine(startLine)->length()-startCol) > 0 )
00791 editRemoveText (startLine, startCol, m_buffer->plainLine(startLine)->length()-startCol);
00792
00793 editRemoveText (startLine+1, 0, endCol);
00794 editUnWrapLine (startLine);
00795 }
00796 else
00797 {
00798 for (uint line = endLine; line >= startLine; line--)
00799 {
00800 if ((line > startLine) && (line < endLine))
00801 {
00802 editRemoveLine (line);
00803 }
00804 else
00805 {
00806 if (line == endLine)
00807 {
00808 if ( endLine <= lastLine() )
00809 editRemoveText (line, 0, endCol);
00810 }
00811 else
00812 {
00813 if ( (m_buffer->plainLine(line)->length()-startCol) > 0 )
00814 editRemoveText (line, startCol, m_buffer->plainLine(line)->length()-startCol);
00815
00816 editUnWrapLine (startLine);
00817 }
00818 }
00819
00820 if ( line == 0 )
00821 break;
00822 }
00823 }
00824 }
00825 else
00826 {
00827 if ( endLine > lastLine() )
00828 endLine = lastLine ();
00829
00830 for (uint line = endLine; line >= startLine; line--)
00831 {
00832
00833 editRemoveText (line, startCol, endCol-startCol);
00834
00835 if ( line == 0 )
00836 break;
00837 }
00838 }
00839
00840 editEnd ();
00841 emit textRemoved();
00842 return true;
00843 }
00844
00845 bool KateDocument::insertLine( uint l, const QString &str )
00846 {
00847 if (!isReadWrite())
00848 return false;
00849
00850 if (l > numLines())
00851 return false;
00852
00853 return editInsertLine (l, str);
00854 }
00855
00856 bool KateDocument::removeLine( uint line )
00857 {
00858 if (!isReadWrite())
00859 return false;
00860
00861 if (line > lastLine())
00862 return false;
00863
00864 return editRemoveLine (line);
00865 }
00866
00867 uint KateDocument::length() const
00868 {
00869 uint l = 0;
00870
00871 for (uint i = 0; i < m_buffer->count(); i++)
00872 {
00873 KateTextLine::Ptr line = m_buffer->plainLine(i);
00874
00875 if (line)
00876 l += line->length();
00877 }
00878
00879 return l;
00880 }
00881
00882 uint KateDocument::numLines() const
00883 {
00884 return m_buffer->count();
00885 }
00886
00887 uint KateDocument::numVisLines() const
00888 {
00889 return m_buffer->countVisible ();
00890 }
00891
00892 int KateDocument::lineLength ( uint line ) const
00893 {
00894 KateTextLine::Ptr l = m_buffer->plainLine(line);
00895
00896 if (!l)
00897 return -1;
00898
00899 return l->length();
00900 }
00901
00902
00903
00904
00905
00906
00907 void KateDocument::editStart (bool withUndo)
00908 {
00909 editSessionNumber++;
00910
00911 if (editSessionNumber > 1)
00912 return;
00913
00914 editIsRunning = true;
00915 editWithUndo = withUndo;
00916
00917 if (editWithUndo)
00918 undoStart();
00919 else
00920 undoCancel();
00921
00922 for (uint z = 0; z < m_views.count(); z++)
00923 {
00924 m_views.at(z)->editStart ();
00925 }
00926
00927 m_buffer->editStart ();
00928 }
00929
00930 void KateDocument::undoStart()
00931 {
00932 if (m_editCurrentUndo || (m_activeView && m_activeView->imComposeEvent())) return;
00933
00934
00935 if ((config()->undoSteps() > 0) && (undoItems.count() > config()->undoSteps()))
00936 {
00937 undoItems.setAutoDelete(true);
00938 undoItems.removeFirst();
00939 undoItems.setAutoDelete(false);
00940 docWasSavedWhenUndoWasEmpty = false;
00941 }
00942
00943
00944 m_editCurrentUndo = new KateUndoGroup(this);
00945 }
00946
00947 void KateDocument::undoEnd()
00948 {
00949 if (m_activeView && m_activeView->imComposeEvent())
00950 return;
00951
00952 if (m_editCurrentUndo)
00953 {
00954 bool changedUndo = false;
00955
00956 if (m_editCurrentUndo->isEmpty())
00957 delete m_editCurrentUndo;
00958 else if (!m_undoDontMerge && undoItems.last() && undoItems.last()->merge(m_editCurrentUndo,m_undoComplexMerge))
00959 delete m_editCurrentUndo;
00960 else
00961 {
00962 undoItems.append(m_editCurrentUndo);
00963 changedUndo = true;
00964 }
00965
00966 m_undoDontMerge = false;
00967 m_undoIgnoreCancel = true;
00968
00969 m_editCurrentUndo = 0L;
00970
00971
00972
00973 m_undoMergeTimer->start(5000, true);
00974
00975 if (changedUndo)
00976 emit undoChanged();
00977 }
00978 }
00979
00980 void KateDocument::undoCancel()
00981 {
00982 if (m_undoIgnoreCancel) {
00983 m_undoIgnoreCancel = false;
00984 return;
00985 }
00986
00987 m_undoDontMerge = true;
00988
00989 Q_ASSERT(!m_editCurrentUndo);
00990
00991
00992 delete m_editCurrentUndo;
00993 m_editCurrentUndo = 0L;
00994 }
00995
00996 void KateDocument::undoSafePoint() {
00997 Q_ASSERT(m_editCurrentUndo);
00998 if (!m_editCurrentUndo) return;
00999 m_editCurrentUndo->safePoint();
01000 }
01001
01002
01003
01004
01005 void KateDocument::editEnd ()
01006 {
01007 if (editSessionNumber == 0)
01008 return;
01009
01010
01011 if (m_buffer->editChanged() && (editSessionNumber == 1))
01012 if (editWithUndo && config()->wordWrap())
01013 wrapText (m_buffer->editTagStart(), m_buffer->editTagEnd());
01014
01015 editSessionNumber--;
01016
01017 if (editSessionNumber > 0)
01018 return;
01019
01020
01021
01022 m_buffer->editEnd ();
01023
01024 if (editWithUndo)
01025 undoEnd();
01026
01027
01028 for (uint z = 0; z < m_views.count(); z++)
01029 m_views.at(z)->editEnd (m_buffer->editTagStart(), m_buffer->editTagEnd(), m_buffer->editTagFrom());
01030
01031 if (m_buffer->editChanged())
01032 {
01033 setModified(true);
01034 emit textChanged ();
01035 }
01036
01037 editIsRunning = false;
01038 }
01039
01040 bool KateDocument::wrapText (uint startLine, uint endLine)
01041 {
01042 uint col = config()->wordWrapAt();
01043
01044 if (col == 0)
01045 return false;
01046
01047 editStart ();
01048
01049 for (uint line = startLine; (line <= endLine) && (line < numLines()); line++)
01050 {
01051 KateTextLine::Ptr l = m_buffer->line(line);
01052
01053 if (!l)
01054 return false;
01055
01056 kdDebug (13020) << "try wrap line: " << line << endl;
01057
01058 if (l->lengthWithTabs(m_buffer->tabWidth()) > col)
01059 {
01060 KateTextLine::Ptr nextl = m_buffer->line(line+1);
01061
01062 kdDebug (13020) << "do wrap line: " << line << endl;
01063
01064 const QChar *text = l->text();
01065 uint eolPosition = l->length()-1;
01066
01067
01068 uint x = 0;
01069 const QString & t = l->string();
01070 uint z2 = 0;
01071 for ( ; z2 < l->length(); z2++)
01072 {
01073 if (t[z2] == QChar('\t'))
01074 x += m_buffer->tabWidth() - (x % m_buffer->tabWidth());
01075 else
01076 x++;
01077
01078 if (x > col)
01079 break;
01080 }
01081
01082 uint searchStart = kMin (z2, l->length()-1);
01083
01084
01085
01086 if (searchStart == eolPosition && text[searchStart].isSpace())
01087 searchStart--;
01088
01089
01090
01091
01092
01093
01094
01095 int z = 0;
01096 uint nw = 0;
01097 for (z=searchStart; z > 0; z--)
01098 {
01099 if (text[z].isSpace()) break;
01100 if ( ! nw && highlight()->canBreakAt( text[z] , l->attribute(z) ) )
01101 nw = z;
01102 }
01103
01104 if (z > 0)
01105 {
01106
01107 editRemoveText (line, z, 1);
01108 }
01109 else
01110 {
01111
01112
01113
01114 if ( nw && nw < col ) nw++;
01115 z = nw ? nw : col;
01116 }
01117
01118 if (nextl && !nextl->isAutoWrapped())
01119 {
01120 editWrapLine (line, z, true);
01121 editMarkLineAutoWrapped (line+1, true);
01122
01123 endLine++;
01124 }
01125 else
01126 {
01127 if (nextl && (nextl->length() > 0) && !nextl->getChar(0).isSpace() && ((l->length() < 1) || !l->getChar(l->length()-1).isSpace()))
01128 editInsertText (line+1, 0, QString (" "));
01129
01130 bool newLineAdded = false;
01131 editWrapLine (line, z, false, &newLineAdded);
01132
01133 editMarkLineAutoWrapped (line+1, true);
01134
01135 endLine++;
01136 }
01137 }
01138 }
01139
01140 editEnd ();
01141
01142 return true;
01143 }
01144
01145 void KateDocument::editAddUndo (KateUndoGroup::UndoType type, uint line, uint col, uint len, const QString &text)
01146 {
01147 if (editIsRunning && editWithUndo && m_editCurrentUndo) {
01148 m_editCurrentUndo->addItem(type, line, col, len, text);
01149
01150
01151 if (redoItems.count()) {
01152 redoItems.setAutoDelete(true);
01153 redoItems.clear();
01154 redoItems.setAutoDelete(false);
01155 }
01156 }
01157 }
01158
01159 bool KateDocument::editInsertText ( uint line, uint col, const QString &str )
01160 {
01161 if (!isReadWrite())
01162 return false;
01163
01164 QString s = str;
01165
01166 KateTextLine::Ptr l = m_buffer->line(line);
01167
01168 if (!l)
01169 return false;
01170
01171 if ( config()->configFlags() & KateDocumentConfig::cfReplaceTabsDyn && ! m_isInUndo )
01172 {
01173 uint tw = config()->tabWidth();
01174 int pos = 0;
01175 uint l = 0;
01176 while ( (pos = s.find('\t')) > -1 )
01177 {
01178 l = tw - ( (col + pos)%tw );
01179 s.replace( pos, 1, QString().fill( ' ', l ) );
01180 }
01181 }
01182
01183 editStart ();
01184
01185 editAddUndo (KateUndoGroup::editInsertText, line, col, s.length(), s);
01186
01187 l->insertText (col, s.length(), s.unicode());
01188
01189
01190 m_buffer->changeLine(line);
01191
01192 for( QPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
01193 it.current()->editTextInserted (line, col, s.length());
01194
01195 editEnd ();
01196
01197 return true;
01198 }
01199
01200 bool KateDocument::editRemoveText ( uint line, uint col, uint len )
01201 {
01202 if (!isReadWrite())
01203 return false;
01204
01205 KateTextLine::Ptr l = m_buffer->line(line);
01206
01207 if (!l)
01208 return false;
01209
01210 editStart ();
01211
01212 editAddUndo (KateUndoGroup::editRemoveText, line, col, len, l->string().mid(col, len));
01213
01214 l->removeText (col, len);
01215 removeTrailingSpace( line );
01216
01217 m_buffer->changeLine(line);
01218
01219 for( QPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
01220 it.current()->editTextRemoved (line, col, len);
01221
01222 editEnd ();
01223
01224 return true;
01225 }
01226
01227 bool KateDocument::editMarkLineAutoWrapped ( uint line, bool autowrapped )
01228 {
01229 if (!isReadWrite())
01230 return false;
01231
01232 KateTextLine::Ptr l = m_buffer->line(line);
01233
01234 if (!l)
01235 return false;
01236
01237 editStart ();
01238
01239 editAddUndo (KateUndoGroup::editMarkLineAutoWrapped, line, autowrapped ? 1 : 0, 0, QString::null);
01240
01241 l->setAutoWrapped (autowrapped);
01242
01243 m_buffer->changeLine(line);
01244
01245 editEnd ();
01246
01247 return true;
01248 }
01249
01250 bool KateDocument::editWrapLine ( uint line, uint col, bool newLine, bool *newLineAdded)
01251 {
01252 if (!isReadWrite())
01253 return false;
01254
01255 KateTextLine::Ptr l = m_buffer->line(line);
01256
01257 if (!l)
01258 return false;
01259
01260 editStart ();
01261
01262 KateTextLine::Ptr nextLine = m_buffer->line(line+1);
01263
01264 int pos = l->length() - col;
01265
01266 if (pos < 0)
01267 pos = 0;
01268
01269 editAddUndo (KateUndoGroup::editWrapLine, line, col, pos, (!nextLine || newLine) ? "1" : "0");
01270
01271 if (!nextLine || newLine)
01272 {
01273 KateTextLine::Ptr textLine = new KateTextLine();
01274
01275 textLine->insertText (0, pos, l->text()+col, l->attributes()+col);
01276 l->truncate(col);
01277
01278 m_buffer->insertLine (line+1, textLine);
01279 m_buffer->changeLine(line);
01280
01281 QPtrList<KTextEditor::Mark> list;
01282 for( QIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
01283 {
01284 if( it.current()->line >= line )
01285 {
01286 if ((col == 0) || (it.current()->line > line))
01287 list.append( it.current() );
01288 }
01289 }
01290
01291 for( QPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
01292 {
01293 KTextEditor::Mark* mark = m_marks.take( it.current()->line );
01294 mark->line++;
01295 m_marks.insert( mark->line, mark );
01296 }
01297
01298 if( !list.isEmpty() )
01299 emit marksChanged();
01300
01301
01302 if (newLineAdded)
01303 (*newLineAdded) = true;
01304 }
01305 else
01306 {
01307 nextLine->insertText (0, pos, l->text()+col, l->attributes()+col);
01308 l->truncate(col);
01309
01310 m_buffer->changeLine(line);
01311 m_buffer->changeLine(line+1);
01312
01313
01314 if (newLineAdded)
01315 (*newLineAdded) = false;
01316 }
01317
01318 for( QPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
01319 it.current()->editLineWrapped (line, col, !nextLine || newLine);
01320
01321 editEnd ();
01322
01323 return true;
01324 }
01325
01326 bool KateDocument::editUnWrapLine ( uint line, bool removeLine, uint length )
01327 {
01328 if (!isReadWrite())
01329 return false;
01330
01331 KateTextLine::Ptr l = m_buffer->line(line);
01332 KateTextLine::Ptr nextLine = m_buffer->line(line+1);
01333
01334 if (!l || !nextLine)
01335 return false;
01336
01337 editStart ();
01338
01339 uint col = l->length ();
01340
01341 editAddUndo (KateUndoGroup::editUnWrapLine, line, col, length, removeLine ? "1" : "0");
01342
01343 if (removeLine)
01344 {
01345 l->insertText (col, nextLine->length(), nextLine->text(), nextLine->attributes());
01346
01347 m_buffer->changeLine(line);
01348 m_buffer->removeLine(line+1);
01349 }
01350 else
01351 {
01352 l->insertText (col, (nextLine->length() < length) ? nextLine->length() : length,
01353 nextLine->text(), nextLine->attributes());
01354 nextLine->removeText (0, (nextLine->length() < length) ? nextLine->length() : length);
01355
01356 m_buffer->changeLine(line);
01357 m_buffer->changeLine(line+1);
01358 }
01359
01360 QPtrList<KTextEditor::Mark> list;
01361 for( QIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
01362 {
01363 if( it.current()->line >= line+1 )
01364 list.append( it.current() );
01365
01366 if ( it.current()->line == line+1 )
01367 {
01368 KTextEditor::Mark* mark = m_marks.take( line );
01369
01370 if (mark)
01371 {
01372 it.current()->type |= mark->type;
01373 }
01374 }
01375 }
01376
01377 for( QPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
01378 {
01379 KTextEditor::Mark* mark = m_marks.take( it.current()->line );
01380 mark->line--;
01381 m_marks.insert( mark->line, mark );
01382 }
01383
01384 if( !list.isEmpty() )
01385 emit marksChanged();
01386
01387 for( QPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
01388 it.current()->editLineUnWrapped (line, col, removeLine, length);
01389
01390 editEnd ();
01391
01392 return true;
01393 }
01394
01395 bool KateDocument::editInsertLine ( uint line, const QString &s )
01396 {
01397 if (!isReadWrite())
01398 return false;
01399
01400 if ( line > numLines() )
01401 return false;
01402
01403 editStart ();
01404
01405 editAddUndo (KateUndoGroup::editInsertLine, line, 0, s.length(), s);
01406
01407 removeTrailingSpace( line );
01408
01409 KateTextLine::Ptr tl = new KateTextLine();
01410 tl->insertText (0, s.length(), s.unicode(), 0);
01411 m_buffer->insertLine(line, tl);
01412 m_buffer->changeLine(line);
01413
01414 removeTrailingSpace( line );
01415
01416 QPtrList<KTextEditor::Mark> list;
01417 for( QIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
01418 {
01419 if( it.current()->line >= line )
01420 list.append( it.current() );
01421 }
01422
01423 for( QPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
01424 {
01425 KTextEditor::Mark* mark = m_marks.take( it.current()->line );
01426 mark->line++;
01427 m_marks.insert( mark->line, mark );
01428 }
01429
01430 if( !list.isEmpty() )
01431 emit marksChanged();
01432
01433 for( QPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
01434 it.current()->editLineInserted (line);
01435
01436 editEnd ();
01437
01438 return true;
01439 }
01440
01441 bool KateDocument::editRemoveLine ( uint line )
01442 {
01443 if (!isReadWrite())
01444 return false;
01445
01446 if ( line > lastLine() )
01447 return false;
01448
01449 if ( numLines() == 1 )
01450 return editRemoveText (0, 0, m_buffer->line(0)->length());
01451
01452 editStart ();
01453
01454 editAddUndo (KateUndoGroup::editRemoveLine, line, 0, lineLength(line), textLine(line));
01455
01456 m_buffer->removeLine(line);
01457
01458 QPtrList<KTextEditor::Mark> list;
01459 KTextEditor::Mark* rmark = 0;
01460 for( QIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
01461 {
01462 if ( (it.current()->line > line) )
01463 list.append( it.current() );
01464 else if ( (it.current()->line == line) )
01465 rmark = it.current();
01466 }
01467
01468 if (rmark)
01469 delete (m_marks.take (rmark->line));
01470
01471 for( QPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
01472 {
01473 KTextEditor::Mark* mark = m_marks.take( it.current()->line );
01474 mark->line--;
01475 m_marks.insert( mark->line, mark );
01476 }
01477
01478 if( !list.isEmpty() )
01479 emit marksChanged();
01480
01481 for( QPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
01482 it.current()->editLineRemoved (line);
01483
01484 editEnd();
01485
01486 return true;
01487 }
01488
01489
01490
01491
01492 uint KateDocument::undoCount () const
01493 {
01494 return undoItems.count ();
01495 }
01496
01497 uint KateDocument::redoCount () const
01498 {
01499 return redoItems.count ();
01500 }
01501
01502 uint KateDocument::undoSteps () const
01503 {
01504 return m_config->undoSteps();
01505 }
01506
01507 void KateDocument::setUndoSteps(uint steps)
01508 {
01509 m_config->setUndoSteps (steps);
01510 }
01511
01512 void KateDocument::undo()
01513 {
01514 m_isInUndo = true;
01515 if ((undoItems.count() > 0) && undoItems.last())
01516 {
01517 clearSelection ();
01518
01519 undoItems.last()->undo();
01520 redoItems.append (undoItems.last());
01521 undoItems.removeLast ();
01522 updateModified();
01523
01524 emit undoChanged ();
01525 }
01526 m_isInUndo = false;
01527 }
01528
01529 void KateDocument::redo()
01530 {
01531 m_isInUndo = true;
01532 if ((redoItems.count() > 0) && redoItems.last())
01533 {
01534 clearSelection ();
01535
01536 redoItems.last()->redo();
01537 undoItems.append (redoItems.last());
01538 redoItems.removeLast ();
01539 updateModified();
01540
01541 emit undoChanged ();
01542 }
01543 m_isInUndo = false;
01544 }
01545
01546 void KateDocument::updateModified()
01547 {
01548 if ( ( lastUndoGroupWhenSaved &&
01549 !undoItems.isEmpty() &&
01550 undoItems.last() == lastUndoGroupWhenSaved )
01551 || ( undoItems.isEmpty() && docWasSavedWhenUndoWasEmpty ) )
01552 {
01553 setModified( false );
01554 kdDebug(13020) << k_funcinfo << "setting modified to false!" << endl;
01555 };
01556 }
01557
01558 void KateDocument::clearUndo()
01559 {
01560 undoItems.setAutoDelete (true);
01561 undoItems.clear ();
01562 undoItems.setAutoDelete (false);
01563
01564 lastUndoGroupWhenSaved = 0;
01565 docWasSavedWhenUndoWasEmpty = false;
01566
01567 emit undoChanged ();
01568 }
01569
01570 void KateDocument::clearRedo()
01571 {
01572 redoItems.setAutoDelete (true);
01573 redoItems.clear ();
01574 redoItems.setAutoDelete (false);
01575
01576 emit undoChanged ();
01577 }
01578
01579 QPtrList<KTextEditor::Cursor> KateDocument::cursors () const
01580 {
01581 return myCursors;
01582 }
01583
01584
01585
01586
01587 bool KateDocument::searchText (unsigned int startLine, unsigned int startCol, const QString &text, unsigned int *foundAtLine, unsigned int *foundAtCol, unsigned int *matchLen, bool casesensitive, bool backwards)
01588 {
01589 if (text.isEmpty())
01590 return false;
01591
01592 int line = startLine;
01593 int col = startCol;
01594
01595 if (!backwards)
01596 {
01597 int searchEnd = lastLine();
01598
01599 while (line <= searchEnd)
01600 {
01601 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
01602
01603 if (!textLine)
01604 return false;
01605
01606 uint foundAt, myMatchLen;
01607 bool found = textLine->searchText (col, text, &foundAt, &myMatchLen, casesensitive, false);
01608
01609 if (found)
01610 {
01611 (*foundAtLine) = line;
01612 (*foundAtCol) = foundAt;
01613 (*matchLen) = myMatchLen;
01614 return true;
01615 }
01616
01617 col = 0;
01618 line++;
01619 }
01620 }
01621 else
01622 {
01623
01624 int searchEnd = 0;
01625
01626 while (line >= searchEnd)
01627 {
01628 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
01629
01630 if (!textLine)
01631 return false;
01632
01633 uint foundAt, myMatchLen;
01634 bool found = textLine->searchText (col, text, &foundAt, &myMatchLen, casesensitive, true);
01635
01636 if (found)
01637 {
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653 (*foundAtLine) = line;
01654 (*foundAtCol) = foundAt;
01655 (*matchLen) = myMatchLen;
01656 return true;
01657 }
01658
01659 if (line >= 1)
01660 col = lineLength(line-1);
01661
01662 line--;
01663 }
01664 }
01665
01666 return false;
01667 }
01668
01669 bool KateDocument::searchText (unsigned int startLine, unsigned int startCol, const QRegExp ®exp, unsigned int *foundAtLine, unsigned int *foundAtCol, unsigned int *matchLen, bool backwards)
01670 {
01671 kdDebug(13020)<<"KateDocument::searchText( "<<startLine<<", "<<startCol<<", "<<regexp.pattern()<<", "<<backwards<<" )"<<endl;
01672 if (regexp.isEmpty() || !regexp.isValid())
01673 return false;
01674
01675 int line = startLine;
01676 int col = startCol;
01677
01678 if (!backwards)
01679 {
01680 int searchEnd = lastLine();
01681
01682 while (line <= searchEnd)
01683 {
01684 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
01685
01686 if (!textLine)
01687 return false;
01688
01689 uint foundAt, myMatchLen;
01690 bool found = textLine->searchText (col, regexp, &foundAt, &myMatchLen, false);
01691
01692 if (found)
01693 {
01694
01695
01696 if (myMatchLen == 0 && (uint) line == startLine && foundAt == (uint) col)
01697 {
01698 if (col < lineLength(line))
01699 col++;
01700 else {
01701 line++;
01702 col = 0;
01703 }
01704 continue;
01705 }
01706
01707 (*foundAtLine) = line;
01708 (*foundAtCol) = foundAt;
01709 (*matchLen) = myMatchLen;
01710 return true;
01711 }
01712
01713 col = 0;
01714 line++;
01715 }
01716 }
01717 else
01718 {
01719
01720 int searchEnd = 0;
01721
01722 while (line >= searchEnd)
01723 {
01724 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
01725
01726 if (!textLine)
01727 return false;
01728
01729 uint foundAt, myMatchLen;
01730 bool found = textLine->searchText (col, regexp, &foundAt, &myMatchLen, true);
01731
01732 if (found)
01733 {
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749 (*foundAtLine) = line;
01750 (*foundAtCol) = foundAt;
01751 (*matchLen) = myMatchLen;
01752 return true;
01753 }
01754
01755 if (line >= 1)
01756 col = lineLength(line-1);
01757
01758 line--;
01759 }
01760 }
01761
01762 return false;
01763 }
01764
01765
01766
01767
01768 uint KateDocument::hlMode ()
01769 {
01770 return KateHlManager::self()->findHl(highlight());
01771 }
01772
01773 bool KateDocument::setHlMode (uint mode)
01774 {
01775 m_buffer->setHighlight (mode);
01776
01777 if (true)
01778 {
01779 setDontChangeHlOnSave();
01780 return true;
01781 }
01782
01783 return false;
01784 }
01785
01786 void KateDocument::bufferHlChanged ()
01787 {
01788
01789 makeAttribs(false);
01790
01791 emit hlChanged();
01792 }
01793
01794 uint KateDocument::hlModeCount ()
01795 {
01796 return KateHlManager::self()->highlights();
01797 }
01798
01799 QString KateDocument::hlModeName (uint mode)
01800 {
01801 return KateHlManager::self()->hlName (mode);
01802 }
01803
01804 QString KateDocument::hlModeSectionName (uint mode)
01805 {
01806 return KateHlManager::self()->hlSection (mode);
01807 }
01808
01809 void KateDocument::setDontChangeHlOnSave()
01810 {
01811 hlSetByUser = true;
01812 }
01813
01814
01815
01816 void KateDocument::readConfig(KConfig *config)
01817 {
01818 config->setGroup("Kate Document Defaults");
01819
01820
01821 KateBuffer::setMaxLoadedBlocks (config->readNumEntry("Maximal Loaded Blocks", KateBuffer::maxLoadedBlocks()));
01822
01823 KateDocumentConfig::global()->readConfig (config);
01824
01825 config->setGroup("Kate View Defaults");
01826 KateViewConfig::global()->readConfig (config);
01827
01828 config->setGroup("Kate Renderer Defaults");
01829 KateRendererConfig::global()->readConfig (config);
01830 }
01831
01832 void KateDocument::writeConfig(KConfig *config)
01833 {
01834 config->setGroup("Kate Document Defaults");
01835
01836
01837 config->writeEntry("Maximal Loaded Blocks", KateBuffer::maxLoadedBlocks());
01838
01839 KateDocumentConfig::global()->writeConfig (config);
01840
01841 config->setGroup("Kate View Defaults");
01842 KateViewConfig::global()->writeConfig (config);
01843
01844 config->setGroup("Kate Renderer Defaults");
01845 KateRendererConfig::global()->writeConfig (config);
01846 }
01847
01848 void KateDocument::readConfig()
01849 {
01850 KConfig *config = kapp->config();
01851 readConfig (config);
01852 }
01853
01854 void KateDocument::writeConfig()
01855 {
01856 KConfig *config = kapp->config();
01857 writeConfig (config);
01858 config->sync();
01859 }
01860
01861 void KateDocument::readSessionConfig(KConfig *kconfig)
01862 {
01863
01864 KURL url (kconfig->readEntry("URL"));
01865
01866
01867 QString tmpenc=kconfig->readEntry("Encoding");
01868 if (!tmpenc.isEmpty() && (tmpenc != encoding()))
01869 setEncoding(tmpenc);
01870
01871
01872 if (!url.isEmpty() && url.isValid())
01873 openURL (url);
01874
01875
01876 m_buffer->setHighlight(KateHlManager::self()->nameFind(kconfig->readEntry("Highlighting")));
01877
01878 if (hlMode() > 0)
01879 hlSetByUser = true;
01880
01881
01882 config()->setIndentationMode( (uint)kconfig->readNumEntry("Indentation Mode", config()->indentationMode() ) );
01883
01884
01885 QValueList<int> marks = kconfig->readIntListEntry("Bookmarks");
01886 for( uint i = 0; i < marks.count(); i++ )
01887 addMark( marks[i], KateDocument::markType01 );
01888 }
01889
01890 void KateDocument::writeSessionConfig(KConfig *kconfig)
01891 {
01892
01893 kconfig->writeEntry("URL", m_url.prettyURL() );
01894
01895
01896 kconfig->writeEntry("Encoding",encoding());
01897
01898
01899 kconfig->writeEntry("Highlighting", highlight()->name());
01900
01901 kconfig->writeEntry("Indentation Mode", config()->indentationMode() );
01902
01903
01904 QValueList<int> marks;
01905 for( QIntDictIterator<KTextEditor::Mark> it( m_marks );
01906 it.current() && it.current()->type & KTextEditor::MarkInterface::markType01;
01907 ++it )
01908 marks << it.current()->line;
01909
01910 kconfig->writeEntry( "Bookmarks", marks );
01911 }
01912
01913 void KateDocument::configDialog()
01914 {
01915 KDialogBase *kd = new KDialogBase ( KDialogBase::IconList,
01916 i18n("Configure"),
01917 KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Help,
01918 KDialogBase::Ok,
01919 kapp->mainWidget() );
01920
01921 #ifndef Q_WS_WIN //TODO: reenable
01922 KWin::setIcons( kd->winId(), kapp->icon(), kapp->miniIcon() );
01923 #endif
01924
01925 QPtrList<KTextEditor::ConfigPage> editorPages;
01926
01927 for (uint i = 0; i < KTextEditor::configInterfaceExtension (this)->configPages (); i++)
01928 {
01929 QStringList path;
01930 path.clear();
01931 path << KTextEditor::configInterfaceExtension (this)->configPageName (i);
01932 QVBox *page = kd->addVBoxPage(path, KTextEditor::configInterfaceExtension (this)->configPageFullName (i),
01933 KTextEditor::configInterfaceExtension (this)->configPagePixmap(i, KIcon::SizeMedium) );
01934
01935 editorPages.append (KTextEditor::configInterfaceExtension (this)->configPage(i, page));
01936 }
01937
01938 if (kd->exec())
01939 {
01940 KateDocumentConfig::global()->configStart ();
01941 KateViewConfig::global()->configStart ();
01942 KateRendererConfig::global()->configStart ();
01943
01944 for (uint i=0; i<editorPages.count(); i++)
01945 {
01946 editorPages.at(i)->apply();
01947 }
01948
01949 KateDocumentConfig::global()->configEnd ();
01950 KateViewConfig::global()->configEnd ();
01951 KateRendererConfig::global()->configEnd ();
01952
01953 writeConfig ();
01954 }
01955
01956 delete kd;
01957 }
01958
01959 uint KateDocument::mark( uint line )
01960 {
01961 if( !m_marks[line] )
01962 return 0;
01963 return m_marks[line]->type;
01964 }
01965
01966 void KateDocument::setMark( uint line, uint markType )
01967 {
01968 clearMark( line );
01969 addMark( line, markType );
01970 }
01971
01972 void KateDocument::clearMark( uint line )
01973 {
01974 if( line > lastLine() )
01975 return;
01976
01977 if( !m_marks[line] )
01978 return;
01979
01980 KTextEditor::Mark* mark = m_marks.take( line );
01981 emit markChanged( *mark, MarkRemoved );
01982 emit marksChanged();
01983 delete mark;
01984 tagLines( line, line );
01985 repaintViews(true);
01986 }
01987
01988 void KateDocument::addMark( uint line, uint markType )
01989 {
01990 if( line > lastLine())
01991 return;
01992
01993 if( markType == 0 )
01994 return;
01995
01996 if( m_marks[line] ) {
01997 KTextEditor::Mark* mark = m_marks[line];
01998
01999
02000 markType &= ~mark->type;
02001
02002 if( markType == 0 )
02003 return;
02004
02005
02006 mark->type |= markType;
02007 } else {
02008 KTextEditor::Mark *mark = new KTextEditor::Mark;
02009 mark->line = line;
02010 mark->type = markType;
02011 m_marks.insert( line, mark );
02012 }
02013
02014
02015 KTextEditor::Mark temp;
02016 temp.line = line;
02017 temp.type = markType;
02018 emit markChanged( temp, MarkAdded );
02019
02020 emit marksChanged();
02021 tagLines( line, line );
02022 repaintViews(true);
02023 }
02024
02025 void KateDocument::removeMark( uint line, uint markType )
02026 {
02027 if( line > lastLine() )
02028 return;
02029 if( !m_marks[line] )
02030 return;
02031
02032 KTextEditor::Mark* mark = m_marks[line];
02033
02034
02035 markType &= mark->type;
02036
02037 if( markType == 0 )
02038 return;
02039
02040
02041 mark->type &= ~markType;
02042
02043
02044 KTextEditor::Mark temp;
02045 temp.line = line;
02046 temp.type = markType;
02047 emit markChanged( temp, MarkRemoved );
02048
02049 if( mark->type == 0 )
02050 m_marks.remove( line );
02051
02052 emit marksChanged();
02053 tagLines( line, line );
02054 repaintViews(true);
02055 }
02056
02057 QPtrList<KTextEditor::Mark> KateDocument::marks()
02058 {
02059 QPtrList<KTextEditor::Mark> list;
02060
02061 for( QIntDictIterator<KTextEditor::Mark> it( m_marks );
02062 it.current(); ++it ) {
02063 list.append( it.current() );
02064 }
02065
02066 return list;
02067 }
02068
02069 void KateDocument::clearMarks()
02070 {
02071 for( QIntDictIterator<KTextEditor::Mark> it( m_marks );
02072 it.current(); ++it ) {
02073 KTextEditor::Mark* mark = it.current();
02074 emit markChanged( *mark, MarkRemoved );
02075 tagLines( mark->line, mark->line );
02076 }
02077
02078 m_marks.clear();
02079
02080 emit marksChanged();
02081 repaintViews(true);
02082 }
02083
02084 void KateDocument::setPixmap( MarkInterface::MarkTypes type, const QPixmap& pixmap )
02085 {
02086 m_markPixmaps.replace( type, new QPixmap( pixmap ) );
02087 }
02088
02089 void KateDocument::setDescription( MarkInterface::MarkTypes type, const QString& description )
02090 {
02091 m_markDescriptions.replace( type, new QString( description ) );
02092 }
02093
02094 QPixmap *KateDocument::markPixmap( MarkInterface::MarkTypes type )
02095 {
02096 return m_markPixmaps[type];
02097 }
02098
02099 QColor KateDocument::markColor( MarkInterface::MarkTypes type )
02100 {
02101 uint reserved = (0x1 << KTextEditor::MarkInterface::reservedMarkersCount()) - 1;
02102 if ((uint)type >= (uint)markType01 && (uint)type <= reserved) {
02103 return KateRendererConfig::global()->lineMarkerColor(type);
02104 } else {
02105 return QColor();
02106 }
02107 }
02108
02109 QString KateDocument::markDescription( MarkInterface::MarkTypes type )
02110 {
02111 if( m_markDescriptions[type] )
02112 return *m_markDescriptions[type];
02113 return QString::null;
02114 }
02115
02116 void KateDocument::setMarksUserChangable( uint markMask )
02117 {
02118 m_editableMarks = markMask;
02119 }
02120
02121 uint KateDocument::editableMarks()
02122 {
02123 return m_editableMarks;
02124 }
02125
02126
02127
02128 bool KateDocument::printDialog ()
02129 {
02130 return KatePrinter::print (this);
02131 }
02132
02133 bool KateDocument::print ()
02134 {
02135 return KatePrinter::print (this);
02136 }
02137
02138
02139
02140 QString KateDocument::mimeType()
02141 {
02142 KMimeType::Ptr result = KMimeType::defaultMimeTypePtr();
02143
02144
02145 if ( ! m_url.isEmpty() )
02146 result = KMimeType::findByURL( m_url );
02147
02148 else if ( m_url.isEmpty() || ! m_url.isLocalFile() )
02149 result = mimeTypeForContent();
02150
02151 return result->name();
02152 }
02153
02154
02155 long KateDocument::fileSize()
02156 {
02157 return 0;
02158 }
02159
02160
02161 QString KateDocument::niceFileSize()
02162 {
02163 return "UNKNOWN";
02164 }
02165
02166 KMimeType::Ptr KateDocument::mimeTypeForContent()
02167 {
02168 QByteArray buf (1024);
02169 uint bufpos = 0;
02170
02171 for (uint i=0; i < numLines(); i++)
02172 {
02173 QString line = textLine( i );
02174 uint len = line.length() + 1;
02175
02176 if (bufpos + len > 1024)
02177 len = 1024 - bufpos;
02178
02179 memcpy(&buf[bufpos], (line + "\n").latin1(), len);
02180
02181 bufpos += len;
02182
02183 if (bufpos >= 1024)
02184 break;
02185 }
02186 buf.resize( bufpos );
02187
02188 int accuracy = 0;
02189 return KMimeType::findByContent( buf, &accuracy );
02190 }
02191
02192
02193
02194
02195
02196 bool KateDocument::openURL( const KURL &url )
02197 {
02198
02199
02200 if ( !url.isValid() )
02201 return false;
02202
02203
02204 if ( !closeURL() )
02205 return false;
02206
02207
02208 m_url = url;
02209
02210 if ( m_url.isLocalFile() )
02211 {
02212
02213
02214 m_file = m_url.path();
02215
02216 emit started( 0 );
02217
02218 if (openFile())
02219 {
02220 emit completed();
02221 emit setWindowCaption( m_url.prettyURL() );
02222
02223 return true;
02224 }
02225
02226 return false;
02227 }
02228 else
02229 {
02230
02231
02232 m_bTemp = true;
02233
02234 m_tempFile = new KTempFile ();
02235 m_file = m_tempFile->name();
02236
02237 m_job = KIO::get ( url, false, isProgressInfoEnabled() );
02238
02239
02240 connect( m_job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
02241 SLOT( slotDataKate( KIO::Job*, const QByteArray& ) ) );
02242
02243 connect( m_job, SIGNAL( result( KIO::Job* ) ),
02244 SLOT( slotFinishedKate( KIO::Job* ) ) );
02245
02246 QWidget *w = widget ();
02247 if (!w && !m_views.isEmpty ())
02248 w = m_views.first();
02249
02250 if (w)
02251 m_job->setWindow (w->topLevelWidget());
02252
02253 emit started( m_job );
02254
02255 return true;
02256 }
02257 }
02258
02259 void KateDocument::slotDataKate ( KIO::Job *, const QByteArray &data )
02260 {
02261
02262
02263 if (!m_tempFile || !m_tempFile->file())
02264 return;
02265
02266 m_tempFile->file()->writeBlock (data);
02267 }
02268
02269 void KateDocument::slotFinishedKate ( KIO::Job * job )
02270 {
02271
02272
02273 if (!m_tempFile)
02274 return;
02275
02276 delete m_tempFile;
02277 m_tempFile = 0;
02278 m_job = 0;
02279
02280 if (job->error())
02281 emit canceled( job->errorString() );
02282 else
02283 {
02284 if ( openFile(job) )
02285 emit setWindowCaption( m_url.prettyURL() );
02286 emit completed();
02287 }
02288 }
02289
02290 void KateDocument::abortLoadKate()
02291 {
02292 if ( m_job )
02293 {
02294 kdDebug(13020) << "Aborting job " << m_job << endl;
02295 m_job->kill();
02296 m_job = 0;
02297 }
02298
02299 delete m_tempFile;
02300 m_tempFile = 0;
02301 }
02302
02303 bool KateDocument::openFile()
02304 {
02305 return openFile (0);
02306 }
02307
02308 bool KateDocument::openFile(KIO::Job * job)
02309 {
02310 m_loading = true;
02311
02312 activateDirWatch ();
02313
02314
02315
02316
02317 if (job)
02318 {
02319 QString metaDataCharset = job->queryMetaData("charset");
02320
02321
02322 if (!metaDataCharset.isEmpty () && (!m_config->isSetEncoding() || m_config->encoding().isEmpty()))
02323 setEncoding (metaDataCharset);
02324 }
02325
02326
02327
02328
02329 QString serviceType = m_extension->urlArgs().serviceType.simplifyWhiteSpace();
02330 int pos = serviceType.find(';');
02331 if (pos != -1)
02332 setEncoding (serviceType.mid(pos+1));
02333
02334
02335
02336 bool encodingSticky = m_encodingSticky;
02337 m_encodingSticky = m_config->isSetEncoding();
02338
02339
02340 int fileTypeFound = KateFactory::self()->fileTypeManager()->fileType (this);
02341 if ( fileTypeFound > -1 )
02342 updateFileType( fileTypeFound );
02343
02344
02345 bool success = m_buffer->openFile (m_file);
02346
02347
02348
02349 m_loading = false;
02350 if (success)
02351 {
02352
02353
02354
02355
02356
02357
02358 if (!hlSetByUser)
02359 {
02360 int hl (KateHlManager::self()->detectHighlighting (this));
02361
02362 if (hl >= 0)
02363 m_buffer->setHighlight(hl);
02364 }
02365
02366
02367 if ( fileTypeFound < 0 )
02368 updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
02369
02370
02371 readDirConfig ();
02372
02373
02374 readVariables();
02375
02376
02377 createDigest( m_digest );
02378 }
02379
02380
02381
02382
02383 for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
02384 {
02385 view->updateView(true);
02386 }
02387
02388
02389
02390
02391 emit fileNameChanged ();
02392
02393
02394
02395
02396 setDocName (QString::null);
02397
02398
02399
02400
02401 if (m_modOnHd)
02402 {
02403 m_modOnHd = false;
02404 m_modOnHdReason = 0;
02405 emit modifiedOnDisc (this, m_modOnHd, 0);
02406 }
02407
02408
02409
02410
02411 if (s_openErrorDialogsActivated)
02412 {
02413 if (!success && m_buffer->loadingBorked())
02414 KMessageBox::error (widget(), i18n ("The file %1 could not be loaded completely, as there is not enough temporary disk storage for it.").arg(m_url.url()));
02415 else if (!success)
02416 KMessageBox::error (widget(), i18n ("The file %1 could not be loaded, as it was not possible to read from it.\n\nCheck if you have read access to this file.").arg(m_url.url()));
02417 }
02418
02419
02420 if (m_buffer->binary())
02421 {
02422
02423 setReadWrite( false );
02424
02425 KMessageBox::information (widget()
02426 , i18n ("The file %1 is a binary, saving it will result in a corrupt file.").arg(m_url.url())
02427 , i18n ("Binary File Opened")
02428 , "Binary File Opened Warning");
02429 }
02430
02431 m_encodingSticky = encodingSticky;
02432
02433
02434
02435
02436 return success;
02437 }
02438
02439 bool KateDocument::save()
02440 {
02441 bool l ( url().isLocalFile() );
02442
02443 if ( ( l && config()->backupFlags() & KateDocumentConfig::LocalFiles )
02444 || ( ! l && config()->backupFlags() & KateDocumentConfig::RemoteFiles ) )
02445 {
02446 KURL u( url() );
02447 u.setFileName( config()->backupPrefix() + url().fileName() + config()->backupSuffix() );
02448
02449 kdDebug () << "backup src file name: " << url() << endl;
02450 kdDebug () << "backup dst file name: " << u << endl;
02451
02452
02453 mode_t perms = 0600;
02454 KIO::UDSEntry fentry;
02455 if (KIO::NetAccess::stat (url(), fentry, kapp->mainWidget()))
02456 {
02457 kdDebug () << "stating succesfull: " << url() << endl;
02458 KFileItem item (fentry, url());
02459 perms = item.permissions();
02460 }
02461
02462
02463
02464 if ( (!KIO::NetAccess::exists( u, false, kapp->mainWidget() ) || KIO::NetAccess::del( u, kapp->mainWidget() ))
02465 && KIO::NetAccess::file_copy( url(), u, perms, true, false, kapp->mainWidget() ) )
02466 {
02467 kdDebug(13020)<<"backing up successfull ("<<url().prettyURL()<<" -> "<<u.prettyURL()<<")"<<endl;
02468 }
02469 else
02470 {
02471 kdDebug(13020)<<"backing up failed ("<<url().prettyURL()<<" -> "<<u.prettyURL()<<")"<<endl;
02472
02473 }
02474 }
02475
02476 return KParts::ReadWritePart::save();
02477 }
02478
02479 bool KateDocument::saveFile()
02480 {
02481
02482
02483
02484 if (m_buffer->loadingBorked() && (KMessageBox::warningContinueCancel(widget(),
02485 i18n("This file could not be loaded correctly due to lack of temporary disk space. Saving it could cause data loss.\n\nDo you really want to save it?"),i18n("Possible Data Loss"),i18n("Save Nevertheless")) != KMessageBox::Continue))
02486 return false;
02487
02488
02489
02490
02491 if (m_buffer->binary() && (KMessageBox::warningContinueCancel (widget()
02492 , i18n ("The file %1 is a binary, saving it will result in a corrupt file.").arg(m_url.url())
02493 , i18n ("Trying to Save Binary File")
02494 , i18n("Save Nevertheless"), "Binary File Save Warning") != KMessageBox::Continue))
02495 return false;
02496
02497 if ( !url().isEmpty() )
02498 {
02499 if (s_fileChangedDialogsActivated && m_modOnHd)
02500 {
02501 QString str = reasonedMOHString() + "\n\n";
02502
02503 if (!isModified())
02504 {
02505 if (KMessageBox::warningContinueCancel(0,
02506 str + i18n("Do you really want to save this unmodified file? You could overwrite changed data in the file on disk."),i18n("Trying to Save Unmodified File"),i18n("Save Nevertheless")) != KMessageBox::Continue)
02507 return false;
02508 }
02509 else
02510 {
02511 if (KMessageBox::warningContinueCancel(0,
02512 str + i18n("Do you really want to save this file? Both your open file and the file on disk were changed. There could be some data lost."),i18n("Possible Data Loss"),i18n("Save Nevertheless")) != KMessageBox::Continue)
02513 return false;
02514 }
02515 }
02516 }
02517
02518
02519
02520
02521 if (!m_buffer->canEncode ()
02522 && (KMessageBox::warningContinueCancel(0,
02523 i18n("The selected encoding cannot encode every unicode character in this document. Do you really want to save it? There could be some data lost."),i18n("Possible Data Loss"),i18n("Save Nevertheless")) != KMessageBox::Continue))
02524 {
02525 return false;
02526 }
02527
02528
02529 deactivateDirWatch ();
02530
02531
02532
02533
02534 bool success = m_buffer->saveFile (m_file);
02535
02536
02537 createDigest( m_digest );
02538
02539
02540 activateDirWatch ();
02541
02542
02543
02544
02545 if (success)
02546 {
02547
02548 if (!hlSetByUser)
02549 {
02550 int hl (KateHlManager::self()->detectHighlighting (this));
02551
02552 if (hl >= 0)
02553 m_buffer->setHighlight(hl);
02554 }
02555
02556
02557 readVariables();
02558 }
02559
02560
02561
02562
02563 if (success && m_modOnHd)
02564 {
02565 m_modOnHd = false;
02566 m_modOnHdReason = 0;
02567 emit modifiedOnDisc (this, m_modOnHd, 0);
02568 }
02569
02570
02571
02572
02573 if (!success)
02574 KMessageBox::error (widget(), i18n ("The document could not be saved, as it was not possible to write to %1.\n\nCheck that you have write access to this file or that enough disk space is available.").arg(m_url.url()));
02575
02576
02577
02578
02579 return success;
02580 }
02581
02582 bool KateDocument::saveAs( const KURL &u )
02583 {
02584 QString oldDir = url().directory();
02585
02586 if ( KParts::ReadWritePart::saveAs( u ) )
02587 {
02588
02589 setDocName( QString::null );
02590
02591 if ( u.directory() != oldDir )
02592 readDirConfig();
02593
02594 emit fileNameChanged();
02595 emit nameChanged((Kate::Document *) this);
02596
02597 return true;
02598 }
02599
02600 return false;
02601 }
02602
02603 void KateDocument::readDirConfig ()
02604 {
02605 int depth = config()->searchDirConfigDepth ();
02606
02607 if (m_url.isLocalFile() && (depth > -1))
02608 {
02609 QString currentDir = QFileInfo (m_file).dirPath();
02610
02611
02612 while (depth > -1)
02613 {
02614 kdDebug (13020) << "search for config file in path: " << currentDir << endl;
02615
02616
02617 QFile f (currentDir + "/.kateconfig");
02618
02619 if (f.open (IO_ReadOnly))
02620 {
02621 QTextStream stream (&f);
02622
02623 uint linesRead = 0;
02624 QString line = stream.readLine();
02625 while ((linesRead < 32) && !line.isNull())
02626 {
02627 readVariableLine( line );
02628
02629 line = stream.readLine();
02630
02631 linesRead++;
02632 }
02633
02634 break;
02635 }
02636
02637 QString newDir = QFileInfo (currentDir).dirPath();
02638
02639
02640 if (currentDir == newDir)
02641 break;
02642
02643 currentDir = newDir;
02644 --depth;
02645 }
02646 }
02647 }
02648
02649 void KateDocument::activateDirWatch ()
02650 {
02651
02652 if (m_file == m_dirWatchFile)
02653 return;
02654
02655
02656 deactivateDirWatch ();
02657
02658
02659 if (m_url.isLocalFile() && !m_file.isEmpty())
02660 {
02661 KateFactory::self()->dirWatch ()->addFile (m_file);
02662 m_dirWatchFile = m_file;
02663 }
02664 }
02665
02666 void KateDocument::deactivateDirWatch ()
02667 {
02668 if (!m_dirWatchFile.isEmpty())
02669 KateFactory::self()->dirWatch ()->removeFile (m_dirWatchFile);
02670
02671 m_dirWatchFile = QString::null;
02672 }
02673
02674 bool KateDocument::closeURL()
02675 {
02676 abortLoadKate();
02677
02678
02679
02680
02681 if ( !m_reloading && !url().isEmpty() )
02682 {
02683 if (s_fileChangedDialogsActivated && m_modOnHd)
02684 {
02685 if (!(KMessageBox::warningContinueCancel(
02686 widget(),
02687 reasonedMOHString() + "\n\n" + i18n("Do you really want to continue to close this file? Data loss may occur."),
02688 i18n("Possible Data Loss"), i18n("Close Nevertheless"),
02689 QString("kate_close_modonhd_%1").arg( m_modOnHdReason ) ) == KMessageBox::Continue))
02690 return false;
02691 }
02692 }
02693
02694
02695
02696
02697 if (!KParts::ReadWritePart::closeURL ())
02698 return false;
02699
02700
02701 deactivateDirWatch ();
02702
02703
02704
02705
02706 m_url = KURL ();
02707 m_file = QString::null;
02708
02709
02710 if (m_modOnHd)
02711 {
02712 m_modOnHd = false;
02713 m_modOnHdReason = 0;
02714 emit modifiedOnDisc (this, m_modOnHd, 0);
02715 }
02716
02717
02718 m_buffer->clear();
02719
02720
02721 clearMarks ();
02722
02723
02724 clearUndo();
02725 clearRedo();
02726
02727
02728 setModified(false);
02729
02730
02731 m_buffer->setHighlight(0);
02732
02733
02734 for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
02735 {
02736
02737
02738 view->setCursorPositionInternal(0, 0, 1, false);
02739 view->clearSelection();
02740 view->updateView(true);
02741 }
02742
02743
02744 emit fileNameChanged ();
02745
02746
02747 setDocName (QString::null);
02748
02749
02750 return true;
02751 }
02752
02753 void KateDocument::setReadWrite( bool rw )
02754 {
02755 if (isReadWrite() != rw)
02756 {
02757 KParts::ReadWritePart::setReadWrite (rw);
02758
02759 for( KateView* view = m_views.first(); view != 0L; view = m_views.next() )
02760 {
02761 view->slotUpdate();
02762 view->slotReadWriteChanged ();
02763 }
02764 }
02765 }
02766
02767 void KateDocument::setModified(bool m) {
02768
02769 if (isModified() != m) {
02770 KParts::ReadWritePart::setModified (m);
02771
02772 for( KateView* view = m_views.first(); view != 0L; view = m_views.next() )
02773 {
02774 view->slotUpdate();
02775 }
02776
02777 emit modifiedChanged ();
02778 emit modStateChanged ((Kate::Document *)this);
02779 }
02780 if ( m == false && ! undoItems.isEmpty() )
02781 {
02782 lastUndoGroupWhenSaved = undoItems.last();
02783 }
02784
02785 if ( m == false ) docWasSavedWhenUndoWasEmpty = undoItems.isEmpty();
02786 }
02787
02788
02789
02790
02791 void KateDocument::makeAttribs(bool needInvalidate)
02792 {
02793 for (uint z = 0; z < m_views.count(); z++)
02794 m_views.at(z)->renderer()->updateAttributes ();
02795
02796 if (needInvalidate)
02797 m_buffer->invalidateHighlighting();
02798
02799 tagAll ();
02800 }
02801
02802
02803 void KateDocument::internalHlChanged()
02804 {
02805 makeAttribs();
02806 }
02807
02808 void KateDocument::addView(KTextEditor::View *view) {
02809 if (!view)
02810 return;
02811
02812 m_views.append( (KateView *) view );
02813 m_textEditViews.append( view );
02814
02815
02816 const KateFileType *t = 0;
02817 if ((m_fileType > -1) && (t = KateFactory::self()->fileTypeManager()->fileType(m_fileType)))
02818 readVariableLine (t->varLine, true);
02819
02820
02821 readVariables (true);
02822
02823 m_activeView = (KateView *) view;
02824 }
02825
02826 void KateDocument::removeView(KTextEditor::View *view) {
02827 if (!view)
02828 return;
02829
02830 if (m_activeView == view)
02831 m_activeView = 0L;
02832
02833 m_views.removeRef( (KateView *) view );
02834 m_textEditViews.removeRef( view );
02835 }
02836
02837 void KateDocument::addSuperCursor(KateSuperCursor *cursor, bool privateC) {
02838 if (!cursor)
02839 return;
02840
02841 m_superCursors.append( cursor );
02842
02843 if (!privateC)
02844 myCursors.append( cursor );
02845 }
02846
02847 void KateDocument::removeSuperCursor(KateSuperCursor *cursor, bool privateC) {
02848 if (!cursor)
02849 return;
02850
02851 if (!privateC)
02852 myCursors.removeRef( cursor );
02853
02854 m_superCursors.removeRef( cursor );
02855 }
02856
02857 bool KateDocument::ownedView(KateView *view) {
02858
02859 return (m_views.containsRef(view) > 0);
02860 }
02861
02862 bool KateDocument::isLastView(int numViews) {
02863 return ((int) m_views.count() == numViews);
02864 }
02865
02866 uint KateDocument::currentColumn( const KateTextCursor& cursor )
02867 {
02868 KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
02869
02870 if (textLine)
02871 return textLine->cursorX(cursor.col(), config()->tabWidth());
02872 else
02873 return 0;
02874 }
02875
02876 bool KateDocument::typeChars ( KateView *view, const QString &chars )
02877 {
02878 KateTextLine::Ptr textLine = m_buffer->plainLine(view->cursorLine ());
02879
02880 if (!textLine)
02881 return false;
02882
02883 bool bracketInserted = false;
02884 QString buf;
02885 QChar c;
02886
02887 for( uint z = 0; z < chars.length(); z++ )
02888 {
02889 QChar ch = c = chars[z];
02890 if (ch.isPrint() || ch == '\t')
02891 {
02892 buf.append (ch);
02893
02894 if (!bracketInserted && (config()->configFlags() & KateDocument::cfAutoBrackets))
02895 {
02896 QChar end_ch;
02897 bool complete = true;
02898 QChar prevChar = textLine->getChar(view->cursorColumn()-1);
02899 QChar nextChar = textLine->getChar(view->cursorColumn());
02900 switch(ch) {
02901 case '(': end_ch = ')'; break;
02902 case '[': end_ch = ']'; break;
02903 case '{': end_ch = '}'; break;
02904 case '\'':end_ch = '\'';break;
02905 case '"': end_ch = '"'; break;
02906 default: complete = false;
02907 }
02908 if (complete)
02909 {
02910 if (view->hasSelection())
02911 {
02912 buf.append (view->selection());
02913 buf.append (end_ch);
02914 bracketInserted = true;
02915 }
02916 else
02917 {
02918 if ( ( (ch == '\'' || ch == '"') &&
02919 (prevChar.isLetterOrNumber() || prevChar == ch) )
02920 || nextChar.isLetterOrNumber()
02921 || (nextChar == end_ch && prevChar != ch) )
02922 {
02923 kdDebug(13020) << "AutoBracket refused before: " << nextChar << "\n";
02924 }
02925 else
02926 {
02927 buf.append (end_ch);
02928 bracketInserted = true;
02929 }
02930 }
02931 }
02932 }
02933 }
02934 }
02935
02936 if (buf.isEmpty())
02937 return false;
02938
02939 editStart ();
02940
02941 if (!view->config()->persistentSelection() && view->hasSelection() )
02942 view->removeSelectedText();
02943
02944 int oldLine = view->cursorLine ();
02945 int oldCol = view->cursorColumnReal ();
02946
02947
02948 if (config()->configFlags() & KateDocument::cfOvr)
02949 removeText (view->cursorLine(), view->cursorColumnReal(), view->cursorLine(), kMin( view->cursorColumnReal()+buf.length(), textLine->length() ) );
02950
02951 insertText (view->cursorLine(), view->cursorColumnReal(), buf);
02952 m_indenter->processChar(c);
02953
02954 editEnd ();
02955
02956 if (bracketInserted)
02957 view->setCursorPositionInternal (view->cursorLine(), view->cursorColumnReal()-1);
02958
02959 emit charactersInteractivelyInserted (oldLine, oldCol, chars);
02960
02961 return true;
02962 }
02963
02964 void KateDocument::newLine( KateTextCursor& c, KateViewInternal *v )
02965 {
02966 editStart();
02967
02968 if( !v->view()->config()->persistentSelection() && v->view()->hasSelection() )
02969 v->view()->removeSelectedText();
02970
02971
02972 c = v->getCursor ();
02973
02974 if (c.line() > (int)lastLine())
02975 c.setLine(lastLine());
02976
02977 if ( c.line() < 0 )
02978 c.setLine( 0 );
02979
02980 uint ln = c.line();
02981
02982 KateTextLine::Ptr textLine = kateTextLine(c.line());
02983
02984 if (c.col() > (int)textLine->length())
02985 c.setCol(textLine->length());
02986
02987 if (m_indenter->canProcessNewLine ())
02988 {
02989 int pos = textLine->firstChar();
02990
02991
02992 if (pos < 0)
02993 pos = textLine->length();
02994
02995 if (c.col() < pos)
02996 c.setCol(pos);
02997
02998 editWrapLine (c.line(), c.col());
02999
03000 KateDocCursor cursor (c.line() + 1, pos, this);
03001 m_indenter->processNewline(cursor, true);
03002
03003 c.setPos(cursor);
03004 }
03005 else
03006 {
03007 editWrapLine (c.line(), c.col());
03008 c.setPos(c.line() + 1, 0);
03009 }
03010
03011 removeTrailingSpace( ln );
03012
03013 editEnd();
03014 }
03015
03016 void KateDocument::transpose( const KateTextCursor& cursor)
03017 {
03018 KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
03019
03020 if (!textLine || (textLine->length() < 2))
03021 return;
03022
03023 uint col = cursor.col();
03024
03025 if (col > 0)
03026 col--;
03027
03028 if ((textLine->length() - col) < 2)
03029 return;
03030
03031 uint line = cursor.line();
03032 QString s;
03033
03034
03035
03036 s.append (textLine->getChar(col+1));
03037 s.append (textLine->getChar(col));
03038
03039
03040
03041 editStart ();
03042 editRemoveText (line, col, 2);
03043 editInsertText (line, col, s);
03044 editEnd ();
03045 }
03046
03047 void KateDocument::backspace( KateView *view, const KateTextCursor& c )
03048 {
03049 if ( !view->config()->persistentSelection() && view->hasSelection() ) {
03050 view->removeSelectedText();
03051 return;
03052 }
03053
03054 uint col = kMax( c.col(), 0 );
03055 uint line = kMax( c.line(), 0 );
03056
03057 if ((col == 0) && (line == 0))
03058 return;
03059
03060 int complement = 0;
03061 if (col > 0)
03062 {
03063 if (config()->configFlags() & KateDocument::cfAutoBrackets)
03064 {
03065
03066 KateTextLine::Ptr tl = m_buffer->plainLine(line);
03067 if(!tl) return;
03068 QChar prevChar = tl->getChar(col-1);
03069 QChar nextChar = tl->getChar(col);
03070
03071 if ( (prevChar == '"' && nextChar == '"') ||
03072 (prevChar == '\'' && nextChar == '\'') ||
03073 (prevChar == '(' && nextChar == ')') ||
03074 (prevChar == '[' && nextChar == ']') ||
03075 (prevChar == '{' && nextChar == '}') )
03076 {
03077 complement = 1;
03078 }
03079 }
03080 if (!(config()->configFlags() & KateDocument::cfBackspaceIndents))
03081 {
03082
03083
03084 removeText(line, col-1, line, col+complement);
03085 }
03086 else
03087 {
03088
03089 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
03090
03091
03092 if (!textLine)
03093 return;
03094
03095 int colX = textLine->cursorX(col, config()->tabWidth());
03096 int pos = textLine->firstChar();
03097 if (pos > 0)
03098 pos = textLine->cursorX(pos, config()->tabWidth());
03099
03100 if (pos < 0 || pos >= (int)colX)
03101 {
03102
03103 indent( view, line, -1);
03104 }
03105 else
03106 removeText(line, col-1, line, col+complement);
03107 }
03108 }
03109 else
03110 {
03111
03112 if (line >= 1)
03113 {
03114 KateTextLine::Ptr textLine = m_buffer->plainLine(line-1);
03115
03116
03117 if (!textLine)
03118 return;
03119
03120 if (config()->wordWrap() && textLine->endingWith(QString::fromLatin1(" ")))
03121 {
03122
03123 removeText (line-1, textLine->length()-1, line, 0);
03124 }
03125 else
03126 removeText (line-1, textLine->length(), line, 0);
03127 }
03128 }
03129
03130 emit backspacePressed();
03131 }
03132
03133 void KateDocument::del( KateView *view, const KateTextCursor& c )
03134 {
03135 if ( !view->config()->persistentSelection() && view->hasSelection() ) {
03136 view->removeSelectedText();
03137 return;
03138 }
03139
03140 if( c.col() < (int) m_buffer->plainLine(c.line())->length())
03141 {
03142 removeText(c.line(), c.col(), c.line(), c.col()+1);
03143 }
03144 else if ( (uint)c.line() < lastLine() )
03145 {
03146 removeText(c.line(), c.col(), c.line()+1, 0);
03147 }
03148 }
03149
03150 void KateDocument::paste ( KateView* view )
03151 {
03152 QString s = QApplication::clipboard()->text();
03153
03154 if (s.isEmpty())
03155 return;
03156
03157 uint lines = s.contains (QChar ('\n'));
03158
03159 m_undoDontMerge = true;
03160
03161 editStart ();
03162
03163 if (!view->config()->persistentSelection() && view->hasSelection() )
03164 view->removeSelectedText();
03165
03166 uint line = view->cursorLine ();
03167 uint column = view->cursorColumnReal ();
03168
03169 insertText ( line, column, s, view->blockSelectionMode() );
03170
03171 editEnd();
03172
03173
03174
03175
03176 if (view->blockSelectionMode())
03177 view->setCursorPositionInternal (line+lines, column);
03178
03179 if (m_indenter->canProcessLine())
03180 {
03181 editStart();
03182
03183 KateDocCursor begin(line, 0, this);
03184 KateDocCursor end(line + lines, 0, this);
03185
03186 m_indenter->processSection (begin, end);
03187
03188 editEnd();
03189 }
03190
03191 if (!view->blockSelectionMode()) emit charactersSemiInteractivelyInserted (line, column, s);
03192 m_undoDontMerge = true;
03193 }
03194
03195 void KateDocument::insertIndentChars ( KateView *view )
03196 {
03197 editStart ();
03198
03199 QString s;
03200 if (config()->configFlags() & KateDocument::cfSpaceIndent)
03201 {
03202 int width = config()->indentationWidth();
03203 s.fill (' ', width - (view->cursorColumnReal() % width));
03204 }
03205 else
03206 s.append ('\t');
03207
03208 insertText (view->cursorLine(), view->cursorColumnReal(), s);
03209
03210 editEnd ();
03211 }
03212
03213 void KateDocument::indent ( KateView *v, uint line, int change)
03214 {
03215 editStart ();
03216
03217 if (!hasSelection())
03218 {
03219
03220 optimizeLeadingSpace(line, config()->configFlags(), change);
03221 }
03222 else
03223 {
03224 int sl = v->selStartLine();
03225 int el = v->selEndLine();
03226 int ec = v->selEndCol();
03227
03228 if ((ec == 0) && ((el-1) >= 0))
03229 {
03230 el--;
03231 }
03232
03233 if (config()->configFlags() & KateDocument::cfKeepIndentProfile && change < 0) {
03234
03235
03236 int adjustedChange = -change;
03237
03238 for (line = sl; (int) line <= el && adjustedChange > 0; line++) {
03239 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
03240 int firstChar = textLine->firstChar();
03241 if (firstChar >= 0 && (v->lineSelected(line) || v->lineHasSelected(line))) {
03242 int maxUnindent = textLine->cursorX(firstChar, config()->tabWidth()) / config()->indentationWidth();
03243 if (maxUnindent < adjustedChange)
03244 adjustedChange = maxUnindent;
03245 }
03246 }
03247
03248 change = -adjustedChange;
03249 }
03250
03251 for (line = sl; (int) line <= el; line++) {
03252 if (v->lineSelected(line) || v->lineHasSelected(line)) {
03253 optimizeLeadingSpace(line, config()->configFlags(), change);
03254 }
03255 }
03256 }
03257
03258 editEnd ();
03259 }
03260
03261 void KateDocument::align(KateView *view, uint line)
03262 {
03263 if (m_indenter->canProcessLine())
03264 {
03265 editStart ();
03266
03267 if (!view->hasSelection())
03268 {
03269 KateDocCursor curLine(line, 0, this);
03270 m_indenter->processLine (curLine);
03271 editEnd ();
03272 activeView()->setCursorPosition (line, curLine.col());
03273 }
03274 else
03275 {
03276 m_indenter->processSection (view->selStart(), view->selEnd());
03277 editEnd ();
03278 }
03279 }
03280 }
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291 void KateDocument::optimizeLeadingSpace(uint line, int flags, int change)
03292 {
03293 KateTextLine::Ptr textline = m_buffer->plainLine(line);
03294
03295 int first_char = textline->firstChar();
03296
03297 int w = 0;
03298 if (flags & KateDocument::cfSpaceIndent)
03299 w = config()->indentationWidth();
03300 else
03301 w = config()->tabWidth();
03302
03303 if (first_char < 0)
03304 first_char = textline->length();
03305
03306 int space = textline->cursorX(first_char, config()->tabWidth()) + change * w;
03307 if (space < 0)
03308 space = 0;
03309
03310 if (!(flags & KateDocument::cfKeepExtraSpaces))
03311 {
03312 uint extra = space % w;
03313
03314 space -= extra;
03315 if (extra && change < 0) {
03316
03317 space += w;
03318 }
03319 }
03320
03321
03322 replaceWithOptimizedSpace(line, first_char, space, flags);
03323 }
03324
03325 void KateDocument::replaceWithOptimizedSpace(uint line, uint upto_column, uint space, int flags)
03326 {
03327 uint length;
03328 QString new_space;
03329
03330 if (flags & KateDocument::cfSpaceIndent && ! (flags & KateDocumentConfig::cfMixedIndent) ) {
03331 length = space;
03332 new_space.fill(' ', length);
03333 }
03334 else {
03335 length = space / config()->tabWidth();
03336 new_space.fill('\t', length);
03337
03338 QString extra_space;
03339 extra_space.fill(' ', space % config()->tabWidth());
03340 length += space % config()->tabWidth();
03341 new_space += extra_space;
03342 }
03343
03344 KateTextLine::Ptr textline = m_buffer->plainLine(line);
03345 uint change_from;
03346 for (change_from = 0; change_from < upto_column && change_from < length; change_from++) {
03347 if (textline->getChar(change_from) != new_space[change_from])
03348 break;
03349 }
03350
03351 editStart();
03352
03353 if (change_from < upto_column)
03354 removeText(line, change_from, line, upto_column);
03355
03356 if (change_from < length)
03357 insertText(line, change_from, new_space.right(length - change_from));
03358
03359 editEnd();
03360 }
03361
03362
03363
03364
03365
03366 bool KateDocument::removeStringFromBegining(int line, QString &str)
03367 {
03368 KateTextLine::Ptr textline = m_buffer->plainLine(line);
03369
03370 int index = 0;
03371 bool there = false;
03372
03373 if (textline->startingWith(str))
03374 there = true;
03375 else
03376 {
03377 index = textline->firstChar ();
03378
03379 if ((index >= 0) && (textline->length() >= (index + str.length())) && (textline->string(index, str.length()) == str))
03380 there = true;
03381 }
03382
03383 if (there)
03384 {
03385
03386 removeText (line, index, line, index+str.length());
03387 }
03388
03389 return there;
03390 }
03391
03392
03393
03394
03395
03396 bool KateDocument::removeStringFromEnd(int line, QString &str)
03397 {
03398 KateTextLine::Ptr textline = m_buffer->plainLine(line);
03399
03400 int index = 0;
03401 bool there = false;
03402
03403 if(textline->endingWith(str))
03404 {
03405 index = textline->length() - str.length();
03406 there = true;
03407 }
03408 else
03409 {
03410 index = textline->lastChar ()-str.length()+1;
03411
03412 if ((index >= 0) && (textline->length() >= (index + str.length())) && (textline->string(index, str.length()) == str))
03413 there = true;
03414 }
03415
03416 if (there)
03417 {
03418
03419 removeText (line, index, line, index+str.length());
03420 }
03421
03422 return there;
03423 }
03424
03425
03426
03427
03428
03429 void KateDocument::addStartLineCommentToSingleLine( int line, int attrib )
03430 {
03431 if (highlight()->getCommentSingleLinePosition(attrib)==KateHighlighting::CSLPosColumn0)
03432 {
03433 QString commentLineMark = highlight()->getCommentSingleLineStart( attrib ) + " ";
03434 insertText (line, 0, commentLineMark);
03435 }
03436 else
03437 {
03438 QString commentLineMark=highlight()->getCommentSingleLineStart(attrib);
03439 KateTextLine::Ptr l = m_buffer->line(line);
03440 int pos=l->firstChar();
03441 if (pos >=0)
03442 insertText(line,pos,commentLineMark);
03443 }
03444 }
03445
03446
03447
03448
03449
03450 bool KateDocument::removeStartLineCommentFromSingleLine( int line, int attrib )
03451 {
03452 QString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
03453 QString longCommentMark = shortCommentMark + " ";
03454
03455 editStart();
03456
03457
03458 bool removed = (removeStringFromBegining(line, longCommentMark)
03459 || removeStringFromBegining(line, shortCommentMark));
03460
03461 editEnd();
03462
03463 return removed;
03464 }
03465
03466
03467
03468
03469
03470 void KateDocument::addStartStopCommentToSingleLine( int line, int attrib )
03471 {
03472 QString startCommentMark = highlight()->getCommentStart( attrib ) + " ";
03473 QString stopCommentMark = " " + highlight()->getCommentEnd( attrib );
03474
03475 editStart();
03476
03477
03478 insertText (line, 0, startCommentMark);
03479
03480
03481 int col = m_buffer->plainLine(line)->length();
03482
03483
03484 insertText (line, col, stopCommentMark);
03485
03486 editEnd();
03487 }
03488
03489
03490
03491
03492
03493 bool KateDocument::removeStartStopCommentFromSingleLine( int line, int attrib )
03494 {
03495 QString shortStartCommentMark = highlight()->getCommentStart( attrib );
03496 QString longStartCommentMark = shortStartCommentMark + " ";
03497 QString shortStopCommentMark = highlight()->getCommentEnd( attrib );
03498 QString longStopCommentMark = " " + shortStopCommentMark;
03499
03500 editStart();
03501
03502 #ifdef __GNUC__
03503 #warning "that's a bad idea, can lead to stray endings, FIXME"
03504 #endif
03505
03506 bool removedStart = (removeStringFromBegining(line, longStartCommentMark)
03507 || removeStringFromBegining(line, shortStartCommentMark));
03508
03509 bool removedStop = false;
03510 if (removedStart)
03511 {
03512
03513 removedStop = (removeStringFromEnd(line, longStopCommentMark)
03514 || removeStringFromEnd(line, shortStopCommentMark));
03515 }
03516
03517 editEnd();
03518
03519 return (removedStart || removedStop);
03520 }
03521
03522
03523
03524
03525
03526
03527 void KateDocument::addStartStopCommentToSelection( KateView *view, int attrib )
03528 {
03529 QString startComment = highlight()->getCommentStart( attrib );
03530 QString endComment = highlight()->getCommentEnd( attrib );
03531
03532 int sl = view->selStartLine();
03533 int el = view->selEndLine();
03534 int sc = view->selStartCol();
03535 int ec = view->selEndCol();
03536
03537 if ((ec == 0) && ((el-1) >= 0))
03538 {
03539 el--;
03540 ec = m_buffer->plainLine (el)->length();
03541 }
03542
03543 editStart();
03544
03545 insertText (el, ec, endComment);
03546 insertText (sl, sc, startComment);
03547
03548 editEnd ();
03549
03550
03551 ec += endComment.length() + ( (el == sl) ? startComment.length() : 0 );
03552 view->setSelection(sl, sc, el, ec);
03553 }
03554
03555
03556
03557
03558
03559 void KateDocument::addStartLineCommentToSelection( KateView *view, int attrib )
03560 {
03561 QString commentLineMark = highlight()->getCommentSingleLineStart( attrib ) + " ";
03562
03563 int sl = view->selStartLine();
03564 int el = view->selEndLine();
03565
03566 if ((view->selEndCol() == 0) && ((el-1) >= 0))
03567 {
03568 el--;
03569 }
03570
03571 editStart();
03572
03573
03574 for (int z = el; z >= sl; z--) {
03575
03576 addStartLineCommentToSingleLine(z, attrib );
03577 }
03578
03579 editEnd ();
03580
03581
03582
03583 KateDocCursor end (view->selEnd());
03584 end.setCol(view->selEndCol() + ((el == view->selEndLine()) ? commentLineMark.length() : 0) );
03585
03586 view->setSelection(view->selStartLine(), 0, end.line(), end.col());
03587 }
03588
03589 bool KateDocument::nextNonSpaceCharPos(int &line, int &col)
03590 {
03591 for(; line < (int)m_buffer->count(); line++) {
03592 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
03593
03594 if (!textLine)
03595 break;
03596
03597 col = textLine->nextNonSpaceChar(col);
03598 if(col != -1)
03599 return true;
03600 col = 0;
03601 }
03602
03603 line = -1;
03604 col = -1;
03605 return false;
03606 }
03607
03608 bool KateDocument::previousNonSpaceCharPos(int &line, int &col)
03609 {
03610 while(true)
03611 {
03612 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
03613
03614 if (!textLine)
03615 break;
03616
03617 col = textLine->previousNonSpaceChar(col);
03618 if(col != -1) return true;
03619 if(line == 0) return false;
03620 --line;
03621 col = textLine->length();
03622 }
03623
03624 line = -1;
03625 col = -1;
03626 return false;
03627 }
03628
03629
03630
03631
03632
03633 bool KateDocument::removeStartStopCommentFromSelection( KateView *view, int attrib )
03634 {
03635 QString startComment = highlight()->getCommentStart( attrib );
03636 QString endComment = highlight()->getCommentEnd( attrib );
03637
03638 int sl = kMax<int> (0, view->selStartLine());
03639 int el = kMin<int> (view->selEndLine(), lastLine());
03640 int sc = view->selStartCol();
03641 int ec = view->selEndCol();
03642
03643
03644 if (ec != 0) {
03645 ec--;
03646 } else {
03647 if (el > 0) {
03648 el--;
03649 ec = m_buffer->plainLine(el)->length() - 1;
03650 }
03651 }
03652
03653 int startCommentLen = startComment.length();
03654 int endCommentLen = endComment.length();
03655
03656
03657
03658 bool remove = nextNonSpaceCharPos(sl, sc)
03659 && m_buffer->plainLine(sl)->stringAtPos(sc, startComment)
03660 && previousNonSpaceCharPos(el, ec)
03661 && ( (ec - endCommentLen + 1) >= 0 )
03662 && m_buffer->plainLine(el)->stringAtPos(ec - endCommentLen + 1, endComment);
03663
03664 if (remove) {
03665 editStart();
03666
03667 removeText (el, ec - endCommentLen + 1, el, ec + 1);
03668 removeText (sl, sc, sl, sc + startCommentLen);
03669
03670 editEnd ();
03671
03672
03673 ec -= endCommentLen + ( (el == sl) ? startCommentLen : 0 );
03674 view->setSelection(sl, sc, el, ec + 1);
03675 }
03676
03677 return remove;
03678 }
03679
03680 bool KateDocument::removeStartStopCommentFromRegion(const KateTextCursor &start,const KateTextCursor &end,int attrib)
03681 {
03682 QString startComment = highlight()->getCommentStart( attrib );
03683 QString endComment = highlight()->getCommentEnd( attrib );
03684 int startCommentLen = startComment.length();
03685 int endCommentLen = endComment.length();
03686
03687 bool remove = m_buffer->plainLine(start.line())->stringAtPos(start.col(), startComment)
03688 && ( (end.col() - endCommentLen ) >= 0 )
03689 && m_buffer->plainLine(end.line())->stringAtPos(end.col() - endCommentLen , endComment);
03690 if (remove) {
03691 editStart();
03692 removeText(end.line(),end.col()-endCommentLen,end.line(),end.col());
03693 removeText(start.line(),start.col(),start.line(),start.col()+startCommentLen);
03694 editEnd();
03695 }
03696 return remove;
03697 }
03698
03699
03700
03701
03702
03703 bool KateDocument::removeStartLineCommentFromSelection( KateView *view, int attrib )
03704 {
03705 QString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
03706 QString longCommentMark = shortCommentMark + " ";
03707
03708 int sl = view->selStartLine();
03709 int el = view->selEndLine();
03710
03711 if ((view->selEndCol() == 0) && ((el-1) >= 0))
03712 {
03713 el--;
03714 }
03715
03716
03717 int removeLength = 0;
03718 if (m_buffer->plainLine(el)->startingWith(longCommentMark))
03719 removeLength = longCommentMark.length();
03720 else if (m_buffer->plainLine(el)->startingWith(shortCommentMark))
03721 removeLength = shortCommentMark.length();
03722
03723 bool removed = false;
03724
03725 editStart();
03726
03727
03728 for (int z = el; z >= sl; z--)
03729 {
03730
03731 removed = (removeStringFromBegining(z, longCommentMark)
03732 || removeStringFromBegining(z, shortCommentMark)
03733 || removed);
03734 }
03735
03736 editEnd();
03737
03738 if (removed)
03739 {
03740
03741 KateDocCursor end (view->selEnd());
03742 end.setCol(view->selEndCol() - ((el == view->selEndLine()) ? removeLength : 0) );
03743
03744 setSelection(view->selStartLine(), view->selStartCol(), end.line(), end.col());
03745 }
03746
03747 return removed;
03748 }
03749
03750
03751
03752
03753
03754 void KateDocument::comment( KateView *v, uint line,uint column, int change)
03755 {
03756
03757
03758
03759
03760 bool hassel = v->hasSelection();
03761 int startAttrib, endAttrib;
03762 if ( hassel )
03763 {
03764 KateTextLine::Ptr ln = kateTextLine( v->selStartLine() );
03765 int l = v->selStartLine(), c = v->selStartCol();
03766 startAttrib = nextNonSpaceCharPos( l, c ) ? kateTextLine( l )->attribute( c ) : 0;
03767
03768 ln = kateTextLine( v->selEndLine() );
03769 l = v->selEndLine(), c = v->selEndCol();
03770 endAttrib = previousNonSpaceCharPos( l, c ) ? kateTextLine( l )->attribute( c ) : 0;
03771 }
03772 else
03773 {
03774 KateTextLine::Ptr ln = kateTextLine( line );
03775 if ( ln->length() )
03776 {
03777 startAttrib = ln->attribute( ln->firstChar() );
03778 endAttrib = ln->attribute( ln->lastChar() );
03779 }
03780 else
03781 {
03782 int l = line, c = 0;
03783 if ( nextNonSpaceCharPos( l, c ) || previousNonSpaceCharPos( l, c ) )
03784 startAttrib = endAttrib = kateTextLine( l )->attribute( c );
03785 else
03786 startAttrib = endAttrib = 0;
03787 }
03788 }
03789
03790 if ( ! highlight()->canComment( startAttrib, endAttrib ) )
03791 {
03792 kdDebug(13020)<<"canComment( "<<startAttrib<<", "<<endAttrib<<" ) returned false!"<<endl;
03793 return;
03794 }
03795
03796 bool hasStartLineCommentMark = !(highlight()->getCommentSingleLineStart( startAttrib ).isEmpty());
03797 bool hasStartStopCommentMark = ( !(highlight()->getCommentStart( startAttrib ).isEmpty())
03798 && !(highlight()->getCommentEnd( endAttrib ).isEmpty()) );
03799
03800 bool removed = false;
03801
03802 if (change > 0)
03803 {
03804 if ( !hassel )
03805 {
03806 if ( hasStartLineCommentMark )
03807 addStartLineCommentToSingleLine( line, startAttrib );
03808 else if ( hasStartStopCommentMark )
03809 addStartStopCommentToSingleLine( line, startAttrib );
03810 }
03811 else
03812 {
03813
03814
03815
03816
03817
03818
03819
03820 if ( hasStartStopCommentMark &&
03821 ( !hasStartLineCommentMark || (
03822 ( v->selStartCol() > m_buffer->plainLine( v->selStartLine() )->firstChar() ) ||
03823 ( v->selEndCol() < ((int)m_buffer->plainLine( v->selEndLine() )->length()) )
03824 ) ) )
03825 addStartStopCommentToSelection( v, startAttrib );
03826 else if ( hasStartLineCommentMark )
03827 addStartLineCommentToSelection( v, startAttrib );
03828 }
03829 }
03830 else
03831 {
03832 if ( !hassel )
03833 {
03834 removed = ( hasStartLineCommentMark
03835 && removeStartLineCommentFromSingleLine( line, startAttrib ) )
03836 || ( hasStartStopCommentMark
03837 && removeStartStopCommentFromSingleLine( line, startAttrib ) );
03838 if ((!removed) && foldingTree()) {
03839 kdDebug(13020)<<"easy approach for uncommenting did not work, trying harder (folding tree)"<<endl;
03840 int commentRegion=(highlight()->commentRegion(startAttrib));
03841 if (commentRegion){
03842 KateCodeFoldingNode *n=foldingTree()->findNodeForPosition(line,column);
03843 if (n) {
03844 KateTextCursor start,end;
03845 if ((n->nodeType()==commentRegion) && n->getBegin(foldingTree(), &start) && n->getEnd(foldingTree(), &end)) {
03846 kdDebug(13020)<<"Enclosing region found:"<<start.col()<<"/"<<start.line()<<"-"<<end.col()<<"/"<<end.line()<<endl;
03847 removeStartStopCommentFromRegion(start,end,startAttrib);
03848 } else {
03849 kdDebug(13020)<<"Enclosing region found, but not valid"<<endl;
03850 kdDebug(13020)<<"Region found: "<<n->nodeType()<<" region needed: "<<commentRegion<<endl;
03851 }
03852
03853 } else kdDebug(13020)<<"No enclosing region found"<<endl;
03854 } else kdDebug(13020)<<"No comment region specified for current hl"<<endl;
03855 }
03856 }
03857 else
03858 {
03859
03860 removed = ( hasStartLineCommentMark
03861 && removeStartLineCommentFromSelection( v, startAttrib ) )
03862 || ( hasStartStopCommentMark
03863 && removeStartStopCommentFromSelection( v, startAttrib ) );
03864 }
03865 }
03866 }
03867
03868 void KateDocument::transform( KateView *v, const KateTextCursor &c,
03869 KateDocument::TextTransform t )
03870 {
03871 editStart();
03872 uint cl( c.line() ), cc( c.col() );
03873 bool selectionRestored = false;
03874
03875 if ( hasSelection() )
03876 {
03877
03878 KateTextCursor selstart = v->selStart();
03879 KateTextCursor selend = v->selEnd();
03880
03881 int ln = v->selStartLine();
03882 while ( ln <= selend.line() )
03883 {
03884 uint start, end;
03885 start = (ln == selstart.line() || v->blockSelectionMode()) ?
03886 selstart.col() : 0;
03887 end = (ln == selend.line() || v->blockSelectionMode()) ?
03888 selend.col() : lineLength( ln );
03889 if ( start > end )
03890 {
03891 uint t = start;
03892 start = end;
03893 end = t;
03894 }
03895 QString s = text( ln, start, ln, end );
03896
03897 if ( t == Uppercase )
03898 s = s.upper();
03899 else if ( t == Lowercase )
03900 s = s.lower();
03901 else
03902 {
03903 KateTextLine::Ptr l = m_buffer->plainLine( ln );
03904 uint p ( 0 );
03905 while( p < s.length() )
03906 {
03907
03908
03909
03910
03911 if ( ( ! start && ! p ) ||
03912 ( ( ln == selstart.line() || v->blockSelectionMode() ) &&
03913 ! p && ! highlight()->isInWord( l->getChar( start - 1 )) ) ||
03914 ( p && ! highlight()->isInWord( s.at( p-1 ) ) )
03915 )
03916 s[p] = s.at(p).upper();
03917 p++;
03918 }
03919 }
03920
03921 removeText( ln, start, ln, end );
03922 insertText( ln, start, s );
03923
03924 ln++;
03925 }
03926
03927
03928 v->setSelection( selstart, selend );
03929 selectionRestored = true;
03930
03931 } else {
03932 QString s;
03933 int n ( cc );
03934 switch ( t ) {
03935 case Uppercase:
03936 s = text( cl, cc, cl, cc + 1 ).upper();
03937 break;
03938 case Lowercase:
03939 s = text( cl, cc, cl, cc + 1 ).lower();
03940 break;
03941 case Capitalize:
03942 {
03943 KateTextLine::Ptr l = m_buffer->plainLine( cl );
03944 while ( n > 0 && highlight()->isInWord( l->getChar( n-1 ), l->attribute( n-1 ) ) )
03945 n--;
03946 s = text( cl, n, cl, n + 1 ).upper();
03947 }
03948 break;
03949 default:
03950 break;
03951 }
03952 removeText( cl, n, cl, n+1 );
03953 insertText( cl, n, s );
03954 }
03955
03956 if ( ! selectionRestored )
03957 v->setCursorPosition( cl, cc );
03958
03959 editEnd();
03960 }
03961
03962 void KateDocument::joinLines( uint first, uint last )
03963 {
03964
03965 editStart();
03966 int line( first );
03967 while ( first < last )
03968 {
03969
03970
03971
03972
03973
03974 KateTextLine::Ptr l = m_buffer->line( line );
03975 KateTextLine::Ptr tl = m_buffer->line( line + 1 );
03976
03977 if ( !l || !tl )
03978 {
03979 editEnd();
03980 return;
03981 }
03982
03983 int pos = tl->firstChar();
03984 if ( pos >= 0 )
03985 {
03986 if (pos != 0)
03987 editRemoveText( line + 1, 0, pos );
03988 if ( !( l->length() == 0 || l->getChar( l->length() - 1 ).isSpace() ) )
03989 editInsertText( line + 1, 0, " " );
03990 }
03991 else
03992 {
03993
03994 editRemoveText( line + 1, 0, tl->length() );
03995 }
03996
03997 editUnWrapLine( line );
03998 first++;
03999 }
04000 editEnd();
04001 }
04002
04003 QString KateDocument::getWord( const KateTextCursor& cursor ) {
04004 int start, end, len;
04005
04006 KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
04007 len = textLine->length();
04008 start = end = cursor.col();
04009 if (start > len)
04010 return QString("");
04011
04012 while (start > 0 && highlight()->isInWord(textLine->getChar(start - 1), textLine->attribute(start - 1))) start--;
04013 while (end < len && highlight()->isInWord(textLine->getChar(end), textLine->attribute(end))) end++;
04014 len = end - start;
04015 return QString(&textLine->text()[start], len);
04016 }
04017
04018 void KateDocument::tagLines(int start, int end)
04019 {
04020 for (uint z = 0; z < m_views.count(); z++)
04021 m_views.at(z)->tagLines (start, end, true);
04022 }
04023
04024 void KateDocument::tagLines(KateTextCursor start, KateTextCursor end)
04025 {
04026
04027 if (blockSelectionMode() && start.col() > end.col()) {
04028 int sc = start.col();
04029 start.setCol(end.col());
04030 end.setCol(sc);
04031 }
04032
04033 for (uint z = 0; z < m_views.count(); z++)
04034 m_views.at(z)->tagLines(start, end, true);
04035 }
04036
04037 void KateDocument::repaintViews(bool paintOnlyDirty)
04038 {
04039 for (uint z = 0; z < m_views.count(); z++)
04040 m_views.at(z)->repaintText(paintOnlyDirty);
04041 }
04042
04043 void KateDocument::tagAll()
04044 {
04045 for (uint z = 0; z < m_views.count(); z++)
04046 {
04047 m_views.at(z)->tagAll();
04048 m_views.at(z)->updateView (true);
04049 }
04050 }
04051
04052 uint KateDocument::configFlags ()
04053 {
04054 return config()->configFlags();
04055 }
04056
04057 void KateDocument::setConfigFlags (uint flags)
04058 {
04059 config()->setConfigFlags(flags);
04060 }
04061
04062 inline bool isStartBracket( const QChar& c ) { return c == '{' || c == '[' || c == '('; }
04063 inline bool isEndBracket ( const QChar& c ) { return c == '}' || c == ']' || c == ')'; }
04064 inline bool isBracket ( const QChar& c ) { return isStartBracket( c ) || isEndBracket( c ); }
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074
04075
04076 void KateDocument::newBracketMark( const KateTextCursor& cursor, KateBracketRange& bm, int maxLines )
04077 {
04078 bm.setValid(false);
04079
04080 bm.start() = cursor;
04081
04082 if( !findMatchingBracket( bm.start(), bm.end(), maxLines ) )
04083 return;
04084
04085 bm.setValid(true);
04086
04087 const int tw = config()->tabWidth();
04088 const int indentStart = m_buffer->plainLine(bm.start().line())->indentDepth(tw);
04089 const int indentEnd = m_buffer->plainLine(bm.end().line())->indentDepth(tw);
04090 bm.setIndentMin(kMin(indentStart, indentEnd));
04091 }
04092
04093 bool KateDocument::findMatchingBracket( KateTextCursor& start, KateTextCursor& end, int maxLines )
04094 {
04095 KateTextLine::Ptr textLine = m_buffer->plainLine( start.line() );
04096 if( !textLine )
04097 return false;
04098
04099 QChar right = textLine->getChar( start.col() );
04100 QChar left = textLine->getChar( start.col() - 1 );
04101 QChar bracket;
04102
04103 if ( config()->configFlags() & cfOvr ) {
04104 if( isBracket( right ) ) {
04105 bracket = right;
04106 } else {
04107 return false;
04108 }
04109 } else if ( isStartBracket( right ) ) {
04110 bracket = right;
04111 } else if ( isEndBracket( left ) ) {
04112 start.setCol(start.col() - 1);
04113 bracket = left;
04114 } else if ( isBracket( left ) ) {
04115 start.setCol(start.col() - 1);
04116 bracket = left;
04117 } else if ( isBracket( right ) ) {
04118 bracket = right;
04119 } else {
04120 return false;
04121 }
04122
04123 QChar opposite;
04124
04125 switch( bracket ) {
04126 case '{': opposite = '}'; break;
04127 case '}': opposite = '{'; break;
04128 case '[': opposite = ']'; break;
04129 case ']': opposite = '['; break;
04130 case '(': opposite = ')'; break;
04131 case ')': opposite = '('; break;
04132 default: return false;
04133 }
04134
04135 bool forward = isStartBracket( bracket );
04136 int startAttr = textLine->attribute( start.col() );
04137 uint count = 0;
04138 int lines = 0;
04139 end = start;
04140
04141 while( true ) {
04142
04143 if( forward ) {
04144 end.setCol(end.col() + 1);
04145 if( end.col() >= lineLength( end.line() ) ) {
04146 if( end.line() >= (int)lastLine() )
04147 return false;
04148 end.setPos(end.line() + 1, 0);
04149 textLine = m_buffer->plainLine( end.line() );
04150 lines++;
04151 }
04152 } else {
04153 end.setCol(end.col() - 1);
04154 if( end.col() < 0 ) {
04155 if( end.line() <= 0 )
04156 return false;
04157 end.setLine(end.line() - 1);
04158 end.setCol(lineLength( end.line() ) - 1);
04159 textLine = m_buffer->plainLine( end.line() );
04160 lines++;
04161 }
04162 }
04163
04164 if ((maxLines != -1) && (lines > maxLines))
04165 return false;
04166
04167
04168 if( textLine->attribute( end.col() ) != startAttr )
04169 continue;
04170
04171
04172 QChar c = textLine->getChar( end.col() );
04173 if( c == bracket ) {
04174 count++;
04175 } else if( c == opposite ) {
04176 if( count == 0 )
04177 return true;
04178 count--;
04179 }
04180
04181 }
04182 }
04183
04184 void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev )
04185 {
04186 KParts::ReadWritePart::guiActivateEvent( ev );
04187 if ( ev->activated() )
04188 emit selectionChanged();
04189 }
04190
04191 void KateDocument::setDocName (QString name )
04192 {
04193 if ( name == m_docName )
04194 return;
04195
04196 if ( !name.isEmpty() )
04197 {
04198
04199 m_docName = name;
04200 updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
04201 emit nameChanged((Kate::Document *) this);
04202 return;
04203 }
04204
04205
04206 if ( ! url().isEmpty() && m_docName.startsWith( url().filename() ) ) return;
04207
04208 int count = -1;
04209
04210 for (uint z=0; z < KateFactory::self()->documents()->count(); z++)
04211 {
04212 if ( (KateFactory::self()->documents()->at(z) != this) && (KateFactory::self()->documents()->at(z)->url().filename() == url().filename()) )
04213 if ( KateFactory::self()->documents()->at(z)->m_docNameNumber > count )
04214 count = KateFactory::self()->documents()->at(z)->m_docNameNumber;
04215 }
04216
04217 m_docNameNumber = count + 1;
04218
04219 m_docName = url().filename();
04220
04221 if (m_docName.isEmpty())
04222 m_docName = i18n ("Untitled");
04223
04224 if (m_docNameNumber > 0)
04225 m_docName = QString(m_docName + " (%1)").arg(m_docNameNumber+1);
04226
04227 updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
04228 emit nameChanged ((Kate::Document *) this);
04229 }
04230
04231 void KateDocument::slotModifiedOnDisk( Kate::View * )
04232 {
04233 if ( m_isasking < 0 )
04234 {
04235 m_isasking = 0;
04236 return;
04237 }
04238
04239 if ( !s_fileChangedDialogsActivated || m_isasking )
04240 return;
04241
04242 if (m_modOnHd && !url().isEmpty())
04243 {
04244 m_isasking = 1;
04245
04246 KateModOnHdPrompt p( this, m_modOnHdReason, reasonedMOHString(), widget() );
04247 switch ( p.exec() )
04248 {
04249 case KateModOnHdPrompt::Save:
04250 {
04251 m_modOnHd = false;
04252 KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveURLAndEncoding(config()->encoding(),
04253 url().url(),QString::null,widget(),i18n("Save File"));
04254
04255 kdDebug(13020)<<"got "<<res.URLs.count()<<" URLs"<<endl;
04256 if( ! res.URLs.isEmpty() && ! res.URLs.first().isEmpty() && checkOverwrite( res.URLs.first() ) )
04257 {
04258 setEncoding( res.encoding );
04259
04260 if( ! saveAs( res.URLs.first() ) )
04261 {
04262 KMessageBox::error( widget(), i18n("Save failed") );
04263 m_modOnHd = true;
04264 }
04265 else
04266 emit modifiedOnDisc( this, false, 0 );
04267 }
04268 else
04269 {
04270 m_modOnHd = true;
04271 }
04272
04273 m_isasking = 0;
04274 break;
04275 }
04276
04277 case KateModOnHdPrompt::Reload:
04278 m_modOnHd = false;
04279 emit modifiedOnDisc( this, false, 0 );
04280 reloadFile();
04281 m_isasking = 0;
04282 break;
04283
04284 case KateModOnHdPrompt::Ignore:
04285 m_modOnHd = false;
04286 emit modifiedOnDisc( this, false, 0 );
04287 m_isasking = 0;
04288 break;
04289
04290 case KateModOnHdPrompt::Overwrite:
04291 m_modOnHd = false;
04292 emit modifiedOnDisc( this, false, 0 );
04293 m_isasking = 0;
04294 save();
04295 break;
04296
04297 default:
04298 m_isasking = -1;
04299 }
04300 }
04301 }
04302
04303 void KateDocument::setModifiedOnDisk( int reason )
04304 {
04305 m_modOnHdReason = reason;
04306 m_modOnHd = (reason > 0);
04307 emit modifiedOnDisc( this, (reason > 0), reason );
04308 }
04309
04310 class KateDocumentTmpMark
04311 {
04312 public:
04313 QString line;
04314 KTextEditor::Mark mark;
04315 };
04316
04317 void KateDocument::reloadFile()
04318 {
04319 if ( !url().isEmpty() )
04320 {
04321 if (m_modOnHd && s_fileChangedDialogsActivated)
04322 {
04323 int i = KMessageBox::warningYesNoCancel
04324 (0, reasonedMOHString() + "\n\n" + i18n("What do you want to do?"),
04325 i18n("File Was Changed on Disk"), i18n("&Reload File"), i18n("&Ignore Changes"));
04326
04327 if ( i != KMessageBox::Yes)
04328 {
04329 if (i == KMessageBox::No)
04330 {
04331 m_modOnHd = false;
04332 m_modOnHdReason = 0;
04333 emit modifiedOnDisc (this, m_modOnHd, 0);
04334 }
04335
04336 return;
04337 }
04338 }
04339
04340 QValueList<KateDocumentTmpMark> tmp;
04341
04342 for( QIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
04343 {
04344 KateDocumentTmpMark m;
04345
04346 m.line = textLine (it.current()->line);
04347 m.mark = *it.current();
04348
04349 tmp.append (m);
04350 }
04351
04352 uint mode = hlMode ();
04353 bool byUser = hlSetByUser;
04354
04355 m_storedVariables.clear();
04356
04357 m_reloading = true;
04358
04359 QValueList<int> lines, cols;
04360 for ( uint i=0; i < m_views.count(); i++ )
04361 {
04362 lines.append( m_views.at( i )->cursorLine() );
04363 cols.append( m_views.at( i )->cursorColumn() );
04364 }
04365
04366 KateDocument::openURL( url() );
04367
04368 for ( uint i=0; i < m_views.count(); i++ )
04369 m_views.at( i )->setCursorPositionInternal( lines[ i ], cols[ i ], m_config->tabWidth(), false );
04370
04371 m_reloading = false;
04372
04373 for (uint z=0; z < tmp.size(); z++)
04374 {
04375 if (z < numLines())
04376 {
04377 if (textLine(tmp[z].mark.line) == tmp[z].line)
04378 setMark (tmp[z].mark.line, tmp[z].mark.type);
04379 }
04380 }
04381
04382 if (byUser)
04383 setHlMode (mode);
04384 }
04385 }
04386
04387 void KateDocument::flush ()
04388 {
04389 closeURL ();
04390 }
04391
04392 void KateDocument::setWordWrap (bool on)
04393 {
04394 config()->setWordWrap (on);
04395 }
04396
04397 bool KateDocument::wordWrap ()
04398 {
04399 return config()->wordWrap ();
04400 }
04401
04402 void KateDocument::setWordWrapAt (uint col)
04403 {
04404 config()->setWordWrapAt (col);
04405 }
04406
04407 unsigned int KateDocument::wordWrapAt ()
04408 {
04409 return config()->wordWrapAt ();
04410 }
04411
04412 void KateDocument::applyWordWrap ()
04413 {
04414
04415 }
04416
04417 void KateDocument::setPageUpDownMovesCursor (bool on)
04418 {
04419 config()->setPageUpDownMovesCursor (on);
04420 }
04421
04422 bool KateDocument::pageUpDownMovesCursor ()
04423 {
04424 return config()->pageUpDownMovesCursor ();
04425 }
04426
04427 void KateDocument::dumpRegionTree()
04428 {
04429 m_buffer->foldingTree()->debugDump();
04430 }
04431
04432
04433
04434
04435 KTextEditor::Cursor *KateDocument::createCursor ( )
04436 {
04437 return new KateSuperCursor (this, false, 0, 0, this);
04438 }
04439
04440 void KateDocument::tagArbitraryLines(KateView* view, KateSuperRange* range)
04441 {
04442 if (view)
04443 view->tagLines(range->start(), range->end());
04444 else
04445 tagLines(range->start(), range->end());
04446 }
04447
04448 void KateDocument::lineInfo (KateLineInfo *info, unsigned int line)
04449 {
04450 m_buffer->lineInfo(info,line);
04451 }
04452
04453 KateCodeFoldingTree *KateDocument::foldingTree ()
04454 {
04455 return m_buffer->foldingTree();
04456 }
04457
04458 void KateDocument::setEncoding (const QString &e)
04459 {
04460 if ( m_encodingSticky )
04461 return;
04462
04463 QString ce = m_config->encoding().lower();
04464 if ( e.lower() == ce )
04465 return;
04466
04467 m_config->setEncoding( e );
04468 if ( ! m_loading )
04469 reloadFile();
04470 }
04471
04472 QString KateDocument::encoding() const
04473 {
04474 return m_config->encoding();
04475 }
04476
04477 void KateDocument::updateConfig ()
04478 {
04479 emit undoChanged ();
04480 tagAll();
04481
04482 for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
04483 {
04484 view->updateDocumentConfig ();
04485 }
04486
04487
04488 if (m_indenter->modeNumber() != m_config->indentationMode())
04489 {
04490 delete m_indenter;
04491 m_indenter = KateAutoIndent::createIndenter ( this, m_config->indentationMode() );
04492 }
04493
04494 m_indenter->updateConfig();
04495
04496 m_buffer->setTabWidth (config()->tabWidth());
04497
04498
04499 for (uint i=0; i<KateFactory::self()->plugins().count(); i++)
04500 {
04501 if (config()->plugin (i))
04502 loadPlugin (i);
04503 else
04504 unloadPlugin (i);
04505 }
04506 }
04507
04508
04509
04510
04511
04512
04513
04514
04515 QRegExp KateDocument::kvLine = QRegExp("kate:(.*)");
04516 QRegExp KateDocument::kvVar = QRegExp("([\\w\\-]+)\\s+([^;]+)");
04517
04518 void KateDocument::readVariables(bool onlyViewAndRenderer)
04519 {
04520 if (!onlyViewAndRenderer)
04521 m_config->configStart();
04522
04523
04524 KateView *v;
04525 for (v = m_views.first(); v != 0L; v= m_views.next() )
04526 {
04527 v->config()->configStart();
04528 v->renderer()->config()->configStart();
04529 }
04530
04531 for (uint i=0; i < kMin( 9U, numLines() ); ++i )
04532 {
04533 readVariableLine( textLine( i ), onlyViewAndRenderer );
04534 }
04535 if ( numLines() > 10 )
04536 {
04537 for ( uint i = kMax(10U, numLines() - 10); i < numLines(); ++i )
04538 {
04539 readVariableLine( textLine( i ), onlyViewAndRenderer );
04540 }
04541 }
04542
04543 if (!onlyViewAndRenderer)
04544 m_config->configEnd();
04545
04546 for (v = m_views.first(); v != 0L; v= m_views.next() )
04547 {
04548 v->config()->configEnd();
04549 v->renderer()->config()->configEnd();
04550 }
04551 }
04552
04553 void KateDocument::readVariableLine( QString t, bool onlyViewAndRenderer )
04554 {
04555 if ( kvLine.search( t ) > -1 )
04556 {
04557 QStringList vvl;
04558 vvl << "dynamic-word-wrap" << "dynamic-word-wrap-indicators"
04559 << "line-numbers" << "icon-border" << "folding-markers"
04560 << "bookmark-sorting" << "auto-center-lines"
04561 << "icon-bar-color"
04562
04563 << "background-color" << "selection-color"
04564 << "current-line-color" << "bracket-highlight-color"
04565 << "word-wrap-marker-color"
04566 << "font" << "font-size" << "scheme";
04567 int p( 0 );
04568 QString s = kvLine.cap(1);
04569 QString var, val;
04570 while ( (p = kvVar.search( s, p )) > -1 )
04571 {
04572 p += kvVar.matchedLength();
04573 var = kvVar.cap( 1 );
04574 val = kvVar.cap( 2 ).stripWhiteSpace();
04575 bool state;
04576 int n;
04577
04578
04579 if (onlyViewAndRenderer)
04580 {
04581 if ( vvl.contains( var ) )
04582 setViewVariable( var, val );
04583 }
04584 else
04585 {
04586
04587 if ( var == "word-wrap" && checkBoolValue( val, &state ) )
04588 setWordWrap( state );
04589 else if ( var == "block-selection" && checkBoolValue( val, &state ) )
04590 setBlockSelectionMode( state );
04591
04592
04593 else if ( var == "backspace-indents" && checkBoolValue( val, &state ) )
04594 m_config->setConfigFlags( KateDocumentConfig::cfBackspaceIndents, state );
04595 else if ( var == "replace-tabs" && checkBoolValue( val, &state ) )
04596 m_config->setConfigFlags( KateDocumentConfig::cfReplaceTabsDyn, state );
04597 else if ( var == "remove-trailing-space" && checkBoolValue( val, &state ) )
04598 m_config->setConfigFlags( KateDocumentConfig::cfRemoveTrailingDyn, state );
04599 else if ( var == "wrap-cursor" && checkBoolValue( val, &state ) )
04600 m_config->setConfigFlags( KateDocumentConfig::cfWrapCursor, state );
04601 else if ( var == "auto-brackets" && checkBoolValue( val, &state ) )
04602 m_config->setConfigFlags( KateDocumentConfig::cfAutoBrackets, state );
04603 else if ( var == "overwrite-mode" && checkBoolValue( val, &state ) )
04604 m_config->setConfigFlags( KateDocumentConfig::cfOvr, state );
04605 else if ( var == "keep-indent-profile" && checkBoolValue( val, &state ) )
04606 m_config->setConfigFlags( KateDocumentConfig::cfKeepIndentProfile, state );
04607 else if ( var == "keep-extra-spaces" && checkBoolValue( val, &state ) )
04608 m_config->setConfigFlags( KateDocumentConfig::cfKeepExtraSpaces, state );
04609 else if ( var == "tab-indents" && checkBoolValue( val, &state ) )
04610 m_config->setConfigFlags( KateDocumentConfig::cfTabIndents, state );
04611 else if ( var == "show-tabs" && checkBoolValue( val, &state ) )
04612 m_config->setConfigFlags( KateDocumentConfig::cfShowTabs, state );
04613 else if ( var == "space-indent" && checkBoolValue( val, &state ) )
04614 m_config->setConfigFlags( KateDocumentConfig::cfSpaceIndent, state );
04615 else if ( var == "smart-home" && checkBoolValue( val, &state ) )
04616 m_config->setConfigFlags( KateDocumentConfig::cfSmartHome, state );
04617 else if ( var == "replace-trailing-space-save" && checkBoolValue( val, &state ) )
04618 m_config->setConfigFlags( KateDocumentConfig::cfRemoveSpaces, state );
04619 else if ( var == "auto-insert-doxygen" && checkBoolValue( val, &state) )
04620 m_config->setConfigFlags( KateDocumentConfig::cfDoxygenAutoTyping, state);
04621 else if ( var == "mixed-indent" && checkBoolValue( val, &state ) )
04622 m_config->setConfigFlags( KateDocumentConfig::cfMixedIndent, state );
04623
04624
04625 else if ( var == "tab-width" && checkIntValue( val, &n ) )
04626 m_config->setTabWidth( n );
04627 else if ( var == "indent-width" && checkIntValue( val, &n ) )
04628 m_config->setIndentationWidth( n );
04629 else if ( var == "indent-mode" )
04630 {
04631 if ( checkIntValue( val, &n ) )
04632 m_config->setIndentationMode( n );
04633 else
04634 m_config->setIndentationMode( KateAutoIndent::modeNumber( val) );
04635 }
04636 else if ( var == "word-wrap-column" && n > 0 && checkIntValue( val, &n ) )
04637 m_config->setWordWrapAt( n );
04638 else if ( var == "undo-steps" && n >= 0 && checkIntValue( val, &n ) )
04639 setUndoSteps( n );
04640
04641
04642 else if ( var == "eol" || var == "end-of-line" )
04643 {
04644 QStringList l;
04645 l << "unix" << "dos" << "mac";
04646 if ( (n = l.findIndex( val.lower() )) != -1 )
04647 m_config->setEol( n );
04648 }
04649 else if ( var == "encoding" )
04650 m_config->setEncoding( val );
04651 else if ( var == "syntax" || var == "hl" )
04652 {
04653 for ( uint i=0; i < hlModeCount(); i++ )
04654 {
04655 if ( hlModeName( i ).lower() == val.lower() )
04656 {
04657 setHlMode( i );
04658 break;
04659 }
04660 }
04661 }
04662
04663
04664 else if ( vvl.contains( var ) )
04665 setViewVariable( var, val );
04666 else
04667 {
04668 m_storedVariables.insert( var, val );
04669 emit variableChanged( var, val );
04670 }
04671 }
04672 }
04673 }
04674 }
04675
04676 void KateDocument::setViewVariable( QString var, QString val )
04677 {
04678 KateView *v;
04679 bool state;
04680 int n;
04681 QColor c;
04682 for (v = m_views.first(); v != 0L; v= m_views.next() )
04683 {
04684 if ( var == "dynamic-word-wrap" && checkBoolValue( val, &state ) )
04685 v->config()->setDynWordWrap( state );
04686 else if ( var == "persistent-selection" && checkBoolValue( val, &state ) )
04687 v->config()->setPersistentSelection( state );
04688
04689 else if ( var == "line-numbers" && checkBoolValue( val, &state ) )
04690 v->config()->setLineNumbers( state );
04691 else if (var == "icon-border" && checkBoolValue( val, &state ) )
04692 v->config()->setIconBar( state );
04693 else if (var == "folding-markers" && checkBoolValue( val, &state ) )
04694 v->config()->setFoldingBar( state );
04695 else if ( var == "auto-center-lines" && checkIntValue( val, &n ) )
04696 v->config()->setAutoCenterLines( n );
04697 else if ( var == "icon-bar-color" && checkColorValue( val, c ) )
04698 v->renderer()->config()->setIconBarColor( c );
04699
04700 else if ( var == "background-color" && checkColorValue( val, c ) )
04701 v->renderer()->config()->setBackgroundColor( c );
04702 else if ( var == "selection-color" && checkColorValue( val, c ) )
04703 v->renderer()->config()->setSelectionColor( c );
04704 else if ( var == "current-line-color" && checkColorValue( val, c ) )
04705 v->renderer()->config()->setHighlightedLineColor( c );
04706 else if ( var == "bracket-highlight-color" && checkColorValue( val, c ) )
04707 v->renderer()->config()->setHighlightedBracketColor( c );
04708 else if ( var == "word-wrap-marker-color" && checkColorValue( val, c ) )
04709 v->renderer()->config()->setWordWrapMarkerColor( c );
04710 else if ( var == "font" || ( var == "font-size" && checkIntValue( val, &n ) ) )
04711 {
04712 QFont _f( *v->renderer()->config()->font( ) );
04713
04714 if ( var == "font" )
04715 {
04716 _f.setFamily( val );
04717 _f.setFixedPitch( QFont( val ).fixedPitch() );
04718 }
04719 else
04720 _f.setPointSize( n );
04721
04722 v->renderer()->config()->setFont( _f );
04723 }
04724 else if ( var == "scheme" )
04725 {
04726 v->renderer()->config()->setSchema( KateFactory::self()->schemaManager()->number( val ) );
04727 }
04728 }
04729 }
04730
04731 bool KateDocument::checkBoolValue( QString val, bool *result )
04732 {
04733 val = val.stripWhiteSpace().lower();
04734 QStringList l;
04735 l << "1" << "on" << "true";
04736 if ( l.contains( val ) )
04737 {
04738 *result = true;
04739 return true;
04740 }
04741 l.clear();
04742 l << "0" << "off" << "false";
04743 if ( l.contains( val ) )
04744 {
04745 *result = false;
04746 return true;
04747 }
04748 return false;
04749 }
04750
04751 bool KateDocument::checkIntValue( QString val, int *result )
04752 {
04753 bool ret( false );
04754 *result = val.toInt( &ret );
04755 return ret;
04756 }
04757
04758 bool KateDocument::checkColorValue( QString val, QColor &c )
04759 {
04760 c.setNamedColor( val );
04761 return c.isValid();
04762 }
04763
04764
04765 QString KateDocument::variable( const QString &name ) const
04766 {
04767 if ( m_storedVariables.contains( name ) )
04768 return m_storedVariables[ name ];
04769
04770 return "";
04771 }
04772
04773
04774
04775 void KateDocument::slotModOnHdDirty (const QString &path)
04776 {
04777 if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 1))
04778 {
04779
04780 if ( ! m_digest.isEmpty() )
04781 {
04782 QCString tmp;
04783 if ( createDigest( tmp ) && tmp == m_digest )
04784 return;
04785 }
04786
04787 m_modOnHd = true;
04788 m_modOnHdReason = 1;
04789
04790
04791 if (m_isasking == -1)
04792 m_isasking = false;
04793
04794 emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
04795 }
04796 }
04797
04798 void KateDocument::slotModOnHdCreated (const QString &path)
04799 {
04800 if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 2))
04801 {
04802 m_modOnHd = true;
04803 m_modOnHdReason = 2;
04804
04805
04806 if (m_isasking == -1)
04807 m_isasking = false;
04808
04809 emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
04810 }
04811 }
04812
04813 void KateDocument::slotModOnHdDeleted (const QString &path)
04814 {
04815 if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 3))
04816 {
04817 m_modOnHd = true;
04818 m_modOnHdReason = 3;
04819
04820
04821 if (m_isasking == -1)
04822 m_isasking = false;
04823
04824 emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
04825 }
04826 }
04827
04828 bool KateDocument::createDigest( QCString &result )
04829 {
04830 bool ret = false;
04831 result = "";
04832 if ( url().isLocalFile() )
04833 {
04834 QFile f ( url().path() );
04835 if ( f.open( IO_ReadOnly) )
04836 {
04837 KMD5 md5;
04838 ret = md5.update( f );
04839 md5.hexDigest( result );
04840 f.close();
04841 ret = true;
04842 }
04843 }
04844 return ret;
04845 }
04846
04847 QString KateDocument::reasonedMOHString() const
04848 {
04849 switch( m_modOnHdReason )
04850 {
04851 case 1:
04852 return i18n("The file '%1' was modified by another program.").arg( url().prettyURL() );
04853 break;
04854 case 2:
04855 return i18n("The file '%1' was created by another program.").arg( url().prettyURL() );
04856 break;
04857 case 3:
04858 return i18n("The file '%1' was deleted by another program.").arg( url().prettyURL() );
04859 break;
04860 default:
04861 return QString();
04862 }
04863 }
04864
04865 void KateDocument::removeTrailingSpace( uint line )
04866 {
04867
04868 if ( config()->configFlags() & KateDocumentConfig::cfRemoveTrailingDyn )
04869 {
04870 KateTextLine::Ptr ln = kateTextLine( line );
04871
04872 if ( ! ln ) return;
04873
04874 if ( line == activeView()->cursorLine()
04875 && activeView()->cursorColumnReal() >= (uint)kMax(0,ln->lastChar()) )
04876 return;
04877
04878 if ( ln->length() )
04879 {
04880 uint p = ln->lastChar() + 1;
04881 uint l = ln->length() - p;
04882 if ( l )
04883 editRemoveText( line, p, l);
04884 }
04885 }
04886 }
04887
04888 void KateDocument::updateFileType (int newType, bool user)
04889 {
04890 if (user || !m_fileTypeSetByUser)
04891 {
04892 const KateFileType *t = 0;
04893 if ((newType == -1) || (t = KateFactory::self()->fileTypeManager()->fileType (newType)))
04894 {
04895 m_fileType = newType;
04896
04897 if (t)
04898 {
04899 m_config->configStart();
04900
04901 KateView *v;
04902 for (v = m_views.first(); v != 0L; v= m_views.next() )
04903 {
04904 v->config()->configStart();
04905 v->renderer()->config()->configStart();
04906 }
04907
04908 readVariableLine( t->varLine );
04909
04910 m_config->configEnd();
04911 for (v = m_views.first(); v != 0L; v= m_views.next() )
04912 {
04913 v->config()->configEnd();
04914 v->renderer()->config()->configEnd();
04915 }
04916 }
04917 }
04918 }
04919 }
04920
04921 uint KateDocument::documentNumber () const
04922 {
04923 return KTextEditor::Document::documentNumber ();
04924 }
04925
04926
04927
04928
04929 void KateDocument::slotQueryClose_save(bool *handled, bool* abortClosing) {
04930 *handled=true;
04931 *abortClosing=true;
04932 if (m_url.isEmpty())
04933 {
04934 KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveURLAndEncoding(config()->encoding(),
04935 QString::null,QString::null,0,i18n("Save File"));
04936
04937 if( res.URLs.isEmpty() || !checkOverwrite( res.URLs.first() ) ) {
04938 *abortClosing=true;
04939 return;
04940 }
04941 setEncoding( res.encoding );
04942 saveAs( res.URLs.first() );
04943 *abortClosing=false;
04944 }
04945 else
04946 {
04947 save();
04948 *abortClosing=false;
04949 }
04950
04951 }
04952
04953 bool KateDocument::checkOverwrite( KURL u )
04954 {
04955 if( !u.isLocalFile() )
04956 return true;
04957
04958 QFileInfo info( u.path() );
04959 if( !info.exists() )
04960 return true;
04961
04962 return KMessageBox::Cancel != KMessageBox::warningContinueCancel( 0,
04963 i18n( "A file named \"%1\" already exists. "
04964 "Are you sure you want to overwrite it?" ).arg( info.fileName() ),
04965 i18n( "Overwrite File?" ),
04966 i18n( "&Overwrite" ) );
04967 }
04968
04969 void KateDocument::setDefaultEncoding (const QString &encoding)
04970 {
04971 s_defaultEncoding = encoding;
04972 }
04973
04974
04975 bool KateDocument::insertTemplateTextImplementation ( uint line, uint column, const QString &templateString, const QMap<QString,QString> &initialValues, QWidget *) {
04976 return (new KateTemplateHandler(this,line,column,templateString,initialValues))->initOk();
04977 }
04978
04979 void KateDocument::testTemplateCode() {
04980 int col=activeView()->cursorColumn();
04981 int line=activeView()->cursorLine();
04982 insertTemplateText(line,col,"for ${index} \\${NOPLACEHOLDER} ${index} ${blah} ${fullname} \\$${Placeholder} \\${${PLACEHOLDER2}}\n next line:${ANOTHERPLACEHOLDER} $${DOLLARBEFOREPLACEHOLDER} {NOTHING} {\n${cursor}\n}",QMap<QString,QString>());
04983 }
04984
04985 bool KateDocument::invokeTabInterceptor(KKey key) {
04986 if (m_tabInterceptor) return (*m_tabInterceptor)(key);
04987 return false;
04988 }
04989
04990 bool KateDocument::setTabInterceptor(KateKeyInterceptorFunctor *interceptor) {
04991 if (m_tabInterceptor) return false;
04992 m_tabInterceptor=interceptor;
04993 return true;
04994 }
04995
04996 bool KateDocument::removeTabInterceptor(KateKeyInterceptorFunctor *interceptor) {
04997 if (m_tabInterceptor!=interceptor) return false;
04998 m_tabInterceptor=0;
04999 return true;
05000 }
05001
05002
05003
05004 bool KateDocument::setSelection ( uint startLine, uint startCol, uint endLine, uint endCol )
05005 { if (m_activeView) return m_activeView->setSelection (startLine, startCol, endLine, endCol); return false; }
05006
05007 bool KateDocument::clearSelection ()
05008 { if (m_activeView) return m_activeView->clearSelection(); return false; }
05009
05010 bool KateDocument::hasSelection () const
05011 { if (m_activeView) return m_activeView->hasSelection (); return false; }
05012
05013 QString KateDocument::selection () const
05014 { if (m_activeView) return m_activeView->selection (); return QString(""); }
05015
05016 bool KateDocument::removeSelectedText ()
05017 { if (m_activeView) return m_activeView->removeSelectedText (); return false; }
05018
05019 bool KateDocument::selectAll()
05020 { if (m_activeView) return m_activeView->selectAll (); return false; }
05021
05022 int KateDocument::selStartLine()
05023 { if (m_activeView) return m_activeView->selStartLine (); return 0; }
05024
05025 int KateDocument::selStartCol()
05026 { if (m_activeView) return m_activeView->selStartCol (); return 0; }
05027
05028 int KateDocument::selEndLine()
05029 { if (m_activeView) return m_activeView->selEndLine (); return 0; }
05030
05031 int KateDocument::selEndCol()
05032 { if (m_activeView) return m_activeView->selEndCol (); return 0; }
05033
05034 bool KateDocument::blockSelectionMode ()
05035 { if (m_activeView) return m_activeView->blockSelectionMode (); return false; }
05036
05037 bool KateDocument::setBlockSelectionMode (bool on)
05038 { if (m_activeView) return m_activeView->setBlockSelectionMode (on); return false; }
05039
05040 bool KateDocument::toggleBlockSelectionMode ()
05041 { if (m_activeView) return m_activeView->toggleBlockSelectionMode (); return false; }
05042
05043
05044
05045
05046