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