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->clearSelection();
02737 view->updateView(true);
02738 }
02739
02740
02741 emit fileNameChanged ();
02742
02743
02744 setDocName (QString::null);
02745
02746
02747 return true;
02748 }
02749
02750 void KateDocument::setReadWrite( bool rw )
02751 {
02752 if (isReadWrite() != rw)
02753 {
02754 KParts::ReadWritePart::setReadWrite (rw);
02755
02756 for( KateView* view = m_views.first(); view != 0L; view = m_views.next() )
02757 {
02758 view->slotUpdate();
02759 view->slotReadWriteChanged ();
02760 }
02761 }
02762 }
02763
02764 void KateDocument::setModified(bool m) {
02765
02766 if (isModified() != m) {
02767 KParts::ReadWritePart::setModified (m);
02768
02769 for( KateView* view = m_views.first(); view != 0L; view = m_views.next() )
02770 {
02771 view->slotUpdate();
02772 }
02773
02774 emit modifiedChanged ();
02775 emit modStateChanged ((Kate::Document *)this);
02776 }
02777 if ( m == false && ! undoItems.isEmpty() )
02778 {
02779 lastUndoGroupWhenSaved = undoItems.last();
02780 }
02781
02782 if ( m == false ) docWasSavedWhenUndoWasEmpty = undoItems.isEmpty();
02783 }
02784
02785
02786
02787
02788 void KateDocument::makeAttribs(bool needInvalidate)
02789 {
02790 for (uint z = 0; z < m_views.count(); z++)
02791 m_views.at(z)->renderer()->updateAttributes ();
02792
02793 if (needInvalidate)
02794 m_buffer->invalidateHighlighting();
02795
02796 tagAll ();
02797 }
02798
02799
02800 void KateDocument::internalHlChanged()
02801 {
02802 makeAttribs();
02803 }
02804
02805 void KateDocument::addView(KTextEditor::View *view) {
02806 if (!view)
02807 return;
02808
02809 m_views.append( (KateView *) view );
02810 m_textEditViews.append( view );
02811
02812
02813 const KateFileType *t = 0;
02814 if ((m_fileType > -1) && (t = KateFactory::self()->fileTypeManager()->fileType(m_fileType)))
02815 readVariableLine (t->varLine, true);
02816
02817
02818 readVariables (true);
02819
02820 m_activeView = (KateView *) view;
02821 }
02822
02823 void KateDocument::removeView(KTextEditor::View *view) {
02824 if (!view)
02825 return;
02826
02827 if (m_activeView == view)
02828 m_activeView = 0L;
02829
02830 m_views.removeRef( (KateView *) view );
02831 m_textEditViews.removeRef( view );
02832 }
02833
02834 void KateDocument::addSuperCursor(KateSuperCursor *cursor, bool privateC) {
02835 if (!cursor)
02836 return;
02837
02838 m_superCursors.append( cursor );
02839
02840 if (!privateC)
02841 myCursors.append( cursor );
02842 }
02843
02844 void KateDocument::removeSuperCursor(KateSuperCursor *cursor, bool privateC) {
02845 if (!cursor)
02846 return;
02847
02848 if (!privateC)
02849 myCursors.removeRef( cursor );
02850
02851 m_superCursors.removeRef( cursor );
02852 }
02853
02854 bool KateDocument::ownedView(KateView *view) {
02855
02856 return (m_views.containsRef(view) > 0);
02857 }
02858
02859 bool KateDocument::isLastView(int numViews) {
02860 return ((int) m_views.count() == numViews);
02861 }
02862
02863 uint KateDocument::currentColumn( const KateTextCursor& cursor )
02864 {
02865 KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
02866
02867 if (textLine)
02868 return textLine->cursorX(cursor.col(), config()->tabWidth());
02869 else
02870 return 0;
02871 }
02872
02873 bool KateDocument::typeChars ( KateView *view, const QString &chars )
02874 {
02875 KateTextLine::Ptr textLine = m_buffer->plainLine(view->cursorLine ());
02876
02877 if (!textLine)
02878 return false;
02879
02880 bool bracketInserted = false;
02881 QString buf;
02882 QChar c;
02883
02884 for( uint z = 0; z < chars.length(); z++ )
02885 {
02886 QChar ch = c = chars[z];
02887 if (ch.isPrint() || ch == '\t')
02888 {
02889 buf.append (ch);
02890
02891 if (!bracketInserted && (config()->configFlags() & KateDocument::cfAutoBrackets))
02892 {
02893 QChar end_ch;
02894 bool complete = true;
02895 QChar prevChar = textLine->getChar(view->cursorColumn()-1);
02896 QChar nextChar = textLine->getChar(view->cursorColumn());
02897 switch(ch) {
02898 case '(': end_ch = ')'; break;
02899 case '[': end_ch = ']'; break;
02900 case '{': end_ch = '}'; break;
02901 case '\'':end_ch = '\'';break;
02902 case '"': end_ch = '"'; break;
02903 default: complete = false;
02904 }
02905 if (complete)
02906 {
02907 if (view->hasSelection())
02908 {
02909 buf.append (view->selection());
02910 buf.append (end_ch);
02911 bracketInserted = true;
02912 }
02913 else
02914 {
02915 if ( ( (ch == '\'' || ch == '"') &&
02916 (prevChar.isLetterOrNumber() || prevChar == ch) )
02917 || nextChar.isLetterOrNumber()
02918 || (nextChar == end_ch && prevChar != ch) )
02919 {
02920 kdDebug(13020) << "AutoBracket refused before: " << nextChar << "\n";
02921 }
02922 else
02923 {
02924 buf.append (end_ch);
02925 bracketInserted = true;
02926 }
02927 }
02928 }
02929 }
02930 }
02931 }
02932
02933 if (buf.isEmpty())
02934 return false;
02935
02936 editStart ();
02937
02938 if (!view->config()->persistentSelection() && view->hasSelection() )
02939 view->removeSelectedText();
02940
02941 int oldLine = view->cursorLine ();
02942 int oldCol = view->cursorColumnReal ();
02943
02944
02945 if (config()->configFlags() & KateDocument::cfOvr)
02946 removeText (view->cursorLine(), view->cursorColumnReal(), view->cursorLine(), QMIN( view->cursorColumnReal()+buf.length(), textLine->length() ) );
02947
02948 insertText (view->cursorLine(), view->cursorColumnReal(), buf);
02949 m_indenter->processChar(c);
02950
02951 editEnd ();
02952
02953 if (bracketInserted)
02954 view->setCursorPositionInternal (view->cursorLine(), view->cursorColumnReal()-1);
02955
02956 emit charactersInteractivelyInserted (oldLine, oldCol, chars);
02957
02958 return true;
02959 }
02960
02961 void KateDocument::newLine( KateTextCursor& c, KateViewInternal *v )
02962 {
02963 editStart();
02964
02965 if( !v->view()->config()->persistentSelection() && v->view()->hasSelection() )
02966 v->view()->removeSelectedText();
02967
02968
02969 c = v->getCursor ();
02970
02971 if (c.line() > (int)lastLine())
02972 c.setLine(lastLine());
02973
02974 if ( c.line() < 0 )
02975 c.setLine( 0 );
02976
02977 uint ln = c.line();
02978
02979 KateTextLine::Ptr textLine = kateTextLine(c.line());
02980
02981 if (c.col() > (int)textLine->length())
02982 c.setCol(textLine->length());
02983
02984 if (m_indenter->canProcessNewLine ())
02985 {
02986 int pos = textLine->firstChar();
02987
02988
02989 if (pos < 0)
02990 pos = textLine->length();
02991
02992 if (c.col() < pos)
02993 c.setCol(pos);
02994
02995 editWrapLine (c.line(), c.col());
02996
02997 KateDocCursor cursor (c.line() + 1, pos, this);
02998 m_indenter->processNewline(cursor, true);
02999
03000 c.setPos(cursor);
03001 }
03002 else
03003 {
03004 editWrapLine (c.line(), c.col());
03005 c.setPos(c.line() + 1, 0);
03006 }
03007
03008 removeTrailingSpace( ln );
03009
03010 editEnd();
03011 }
03012
03013 void KateDocument::transpose( const KateTextCursor& cursor)
03014 {
03015 KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
03016
03017 if (!textLine || (textLine->length() < 2))
03018 return;
03019
03020 uint col = cursor.col();
03021
03022 if (col > 0)
03023 col--;
03024
03025 if ((textLine->length() - col) < 2)
03026 return;
03027
03028 uint line = cursor.line();
03029 QString s;
03030
03031
03032
03033 s.append (textLine->getChar(col+1));
03034 s.append (textLine->getChar(col));
03035
03036
03037
03038 editStart ();
03039 editRemoveText (line, col, 2);
03040 editInsertText (line, col, s);
03041 editEnd ();
03042 }
03043
03044 void KateDocument::backspace( KateView *view, const KateTextCursor& c )
03045 {
03046 if ( !view->config()->persistentSelection() && view->hasSelection() ) {
03047 view->removeSelectedText();
03048 return;
03049 }
03050
03051 uint col = QMAX( c.col(), 0 );
03052 uint line = QMAX( c.line(), 0 );
03053
03054 if ((col == 0) && (line == 0))
03055 return;
03056
03057 int complement = 0;
03058 if (col > 0)
03059 {
03060 if (config()->configFlags() & KateDocument::cfAutoBrackets)
03061 {
03062
03063 KateTextLine::Ptr tl = m_buffer->plainLine(line);
03064 if(!tl) return;
03065 QChar prevChar = tl->getChar(col-1);
03066 QChar nextChar = tl->getChar(col);
03067
03068 if ( (prevChar == '"' && nextChar == '"') ||
03069 (prevChar == '\'' && nextChar == '\'') ||
03070 (prevChar == '(' && nextChar == ')') ||
03071 (prevChar == '[' && nextChar == ']') ||
03072 (prevChar == '{' && nextChar == '}') )
03073 {
03074 complement = 1;
03075 }
03076 }
03077 if (!(config()->configFlags() & KateDocument::cfBackspaceIndents))
03078 {
03079
03080
03081 removeText(line, col-1, line, col+complement);
03082 }
03083 else
03084 {
03085
03086 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
03087
03088
03089 if (!textLine)
03090 return;
03091
03092 int colX = textLine->cursorX(col, config()->tabWidth());
03093 int pos = textLine->firstChar();
03094 if (pos > 0)
03095 pos = textLine->cursorX(pos, config()->tabWidth());
03096
03097 if (pos < 0 || pos >= (int)colX)
03098 {
03099
03100
03101 int y = line;
03102 while (--y >= 0)
03103 {
03104
03105 textLine = m_buffer->plainLine(y);
03106
03107 pos = textLine->firstChar();
03108
03109 if (pos >= 0)
03110 {
03111 pos = textLine->cursorX(pos, config()->tabWidth());
03112 if (pos < (int)colX)
03113 {
03114 replaceWithOptimizedSpace(line, col, pos, config()->configFlags());
03115 break;
03116 }
03117 }
03118 }
03119 if (y < 0) {
03120
03121 removeText(line, 0, line, col+complement);
03122 }
03123 }
03124 else
03125 removeText(line, col-1, line, col+complement);
03126 }
03127 }
03128 else
03129 {
03130
03131 if (line >= 1)
03132 {
03133 KateTextLine::Ptr textLine = m_buffer->plainLine(line-1);
03134
03135
03136 if (!textLine)
03137 return;
03138
03139 if (config()->wordWrap() && textLine->endingWith(QString::fromLatin1(" ")))
03140 {
03141
03142 removeText (line-1, textLine->length()-1, line, 0);
03143 }
03144 else
03145 removeText (line-1, textLine->length(), line, 0);
03146 }
03147 }
03148
03149 emit backspacePressed();
03150 }
03151
03152 void KateDocument::del( KateView *view, const KateTextCursor& c )
03153 {
03154 if ( !view->config()->persistentSelection() && view->hasSelection() ) {
03155 view->removeSelectedText();
03156 return;
03157 }
03158
03159 if( c.col() < (int) m_buffer->plainLine(c.line())->length())
03160 {
03161 removeText(c.line(), c.col(), c.line(), c.col()+1);
03162 }
03163 else if ( (uint)c.line() < lastLine() )
03164 {
03165 removeText(c.line(), c.col(), c.line()+1, 0);
03166 }
03167 }
03168
03169 void KateDocument::paste ( KateView* view )
03170 {
03171 QString s = QApplication::clipboard()->text();
03172
03173 if (s.isEmpty())
03174 return;
03175
03176 uint lines = s.contains (QChar ('\n'));
03177
03178 m_undoDontMerge = true;
03179
03180 editStart ();
03181
03182 if (!view->config()->persistentSelection() && view->hasSelection() )
03183 view->removeSelectedText();
03184
03185 uint line = view->cursorLine ();
03186 uint column = view->cursorColumnReal ();
03187
03188 insertText ( line, column, s, view->blockSelectionMode() );
03189
03190 editEnd();
03191
03192
03193
03194
03195 if (view->blockSelectionMode())
03196 view->setCursorPositionInternal (line+lines, column);
03197
03198 if (m_indenter->canProcessLine())
03199 {
03200 editStart();
03201
03202 KateDocCursor begin(line, 0, this);
03203 KateDocCursor end(line + lines, 0, this);
03204
03205 m_indenter->processSection (begin, end);
03206
03207 editEnd();
03208 }
03209
03210 if (!view->blockSelectionMode()) emit charactersSemiInteractivelyInserted (line, column, s);
03211 m_undoDontMerge = true;
03212 }
03213
03214 void KateDocument::insertIndentChars ( KateView *view )
03215 {
03216 editStart ();
03217
03218 QString s;
03219 if (config()->configFlags() & KateDocument::cfSpaceIndent)
03220 {
03221 int width = config()->indentationWidth();
03222 s.fill (' ', width - (view->cursorColumnReal() % width));
03223 }
03224 else
03225 s.append ('\t');
03226
03227 insertText (view->cursorLine(), view->cursorColumnReal(), s);
03228
03229 editEnd ();
03230 }
03231
03232 void KateDocument::indent ( KateView *v, uint line, int change)
03233 {
03234 editStart ();
03235
03236 if (!hasSelection())
03237 {
03238
03239 optimizeLeadingSpace(line, config()->configFlags(), change);
03240 }
03241 else
03242 {
03243 int sl = v->selStartLine();
03244 int el = v->selEndLine();
03245 int ec = v->selEndCol();
03246
03247 if ((ec == 0) && ((el-1) >= 0))
03248 {
03249 el--;
03250 }
03251
03252 if (config()->configFlags() & KateDocument::cfKeepIndentProfile && change < 0) {
03253
03254
03255 int adjustedChange = -change;
03256
03257 for (line = sl; (int) line <= el && adjustedChange > 0; line++) {
03258 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
03259 int firstChar = textLine->firstChar();
03260 if (firstChar >= 0 && (v->lineSelected(line) || v->lineHasSelected(line))) {
03261 int maxUnindent = textLine->cursorX(firstChar, config()->tabWidth()) / config()->indentationWidth();
03262 if (maxUnindent < adjustedChange)
03263 adjustedChange = maxUnindent;
03264 }
03265 }
03266
03267 change = -adjustedChange;
03268 }
03269
03270 for (line = sl; (int) line <= el; line++) {
03271 if (v->lineSelected(line) || v->lineHasSelected(line)) {
03272 optimizeLeadingSpace(line, config()->configFlags(), change);
03273 }
03274 }
03275 }
03276
03277 editEnd ();
03278 }
03279
03280 void KateDocument::align(KateView *view, uint line)
03281 {
03282 if (m_indenter->canProcessLine())
03283 {
03284 editStart ();
03285
03286 if (!view->hasSelection())
03287 {
03288 KateDocCursor curLine(line, 0, this);
03289 m_indenter->processLine (curLine);
03290 editEnd ();
03291 activeView()->setCursorPosition (line, curLine.col());
03292 }
03293 else
03294 {
03295 m_indenter->processSection (view->selStart(), view->selEnd());
03296 editEnd ();
03297 }
03298 }
03299 }
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310 void KateDocument::optimizeLeadingSpace(uint line, int flags, int change)
03311 {
03312 KateTextLine::Ptr textline = m_buffer->plainLine(line);
03313
03314 int first_char = textline->firstChar();
03315
03316 int w = 0;
03317 if (flags & KateDocument::cfSpaceIndent)
03318 w = config()->indentationWidth();
03319 else
03320 w = config()->tabWidth();
03321
03322 if (first_char < 0)
03323 first_char = textline->length();
03324
03325 int space = textline->cursorX(first_char, config()->tabWidth()) + change * w;
03326 if (space < 0)
03327 space = 0;
03328
03329 if (!(flags & KateDocument::cfKeepExtraSpaces))
03330 {
03331 uint extra = space % w;
03332
03333 space -= extra;
03334 if (extra && change < 0) {
03335
03336 space += w;
03337 }
03338 }
03339
03340
03341 replaceWithOptimizedSpace(line, first_char, space, flags);
03342 }
03343
03344 void KateDocument::replaceWithOptimizedSpace(uint line, uint upto_column, uint space, int flags)
03345 {
03346 uint length;
03347 QString new_space;
03348
03349 if (flags & KateDocument::cfSpaceIndent && ! (flags & KateDocumentConfig::cfMixedIndent) ) {
03350 length = space;
03351 new_space.fill(' ', length);
03352 }
03353 else {
03354 length = space / config()->tabWidth();
03355 new_space.fill('\t', length);
03356
03357 QString extra_space;
03358 extra_space.fill(' ', space % config()->tabWidth());
03359 length += space % config()->tabWidth();
03360 new_space += extra_space;
03361 }
03362
03363 KateTextLine::Ptr textline = m_buffer->plainLine(line);
03364 uint change_from;
03365 for (change_from = 0; change_from < upto_column && change_from < length; change_from++) {
03366 if (textline->getChar(change_from) != new_space[change_from])
03367 break;
03368 }
03369
03370 editStart();
03371
03372 if (change_from < upto_column)
03373 removeText(line, change_from, line, upto_column);
03374
03375 if (change_from < length)
03376 insertText(line, change_from, new_space.right(length - change_from));
03377
03378 editEnd();
03379 }
03380
03381
03382
03383
03384
03385 bool KateDocument::removeStringFromBegining(int line, QString &str)
03386 {
03387 KateTextLine::Ptr textline = m_buffer->plainLine(line);
03388
03389 int index = 0;
03390 bool there = false;
03391
03392 if (textline->startingWith(str))
03393 there = true;
03394 else
03395 {
03396 index = textline->firstChar ();
03397
03398 if ((index >= 0) && (textline->length() >= (index + str.length())) && (textline->string(index, str.length()) == str))
03399 there = true;
03400 }
03401
03402 if (there)
03403 {
03404
03405 removeText (line, index, line, index+str.length());
03406 }
03407
03408 return there;
03409 }
03410
03411
03412
03413
03414
03415 bool KateDocument::removeStringFromEnd(int line, QString &str)
03416 {
03417 KateTextLine::Ptr textline = m_buffer->plainLine(line);
03418
03419 int index = 0;
03420 bool there = false;
03421
03422 if(textline->endingWith(str))
03423 {
03424 index = textline->length() - str.length();
03425 there = true;
03426 }
03427 else
03428 {
03429 index = textline->lastChar ()-str.length()+1;
03430
03431 if ((index >= 0) && (textline->length() >= (index + str.length())) && (textline->string(index, str.length()) == str))
03432 there = true;
03433 }
03434
03435 if (there)
03436 {
03437
03438 removeText (line, index, line, index+str.length());
03439 }
03440
03441 return there;
03442 }
03443
03444
03445
03446
03447
03448 void KateDocument::addStartLineCommentToSingleLine( int line, int attrib )
03449 {
03450 if (highlight()->getCommentSingleLinePosition(attrib)==KateHighlighting::CSLPosColumn0)
03451 {
03452 QString commentLineMark = highlight()->getCommentSingleLineStart( attrib ) + " ";
03453 insertText (line, 0, commentLineMark);
03454 }
03455 else
03456 {
03457 QString commentLineMark=highlight()->getCommentSingleLineStart(attrib);
03458 KateTextLine::Ptr l = m_buffer->line(line);
03459 int pos=l->firstChar();
03460 if (pos >=0)
03461 insertText(line,pos,commentLineMark);
03462 }
03463 }
03464
03465
03466
03467
03468
03469 bool KateDocument::removeStartLineCommentFromSingleLine( int line, int attrib )
03470 {
03471 QString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
03472 QString longCommentMark = shortCommentMark + " ";
03473
03474 editStart();
03475
03476
03477 bool removed = (removeStringFromBegining(line, longCommentMark)
03478 || removeStringFromBegining(line, shortCommentMark));
03479
03480 editEnd();
03481
03482 return removed;
03483 }
03484
03485
03486
03487
03488
03489 void KateDocument::addStartStopCommentToSingleLine( int line, int attrib )
03490 {
03491 QString startCommentMark = highlight()->getCommentStart( attrib ) + " ";
03492 QString stopCommentMark = " " + highlight()->getCommentEnd( attrib );
03493
03494 editStart();
03495
03496
03497 insertText (line, 0, startCommentMark);
03498
03499
03500 int col = m_buffer->plainLine(line)->length();
03501
03502
03503 insertText (line, col, stopCommentMark);
03504
03505 editEnd();
03506 }
03507
03508
03509
03510
03511
03512 bool KateDocument::removeStartStopCommentFromSingleLine( int line, int attrib )
03513 {
03514 QString shortStartCommentMark = highlight()->getCommentStart( attrib );
03515 QString longStartCommentMark = shortStartCommentMark + " ";
03516 QString shortStopCommentMark = highlight()->getCommentEnd( attrib );
03517 QString longStopCommentMark = " " + shortStopCommentMark;
03518
03519 editStart();
03520
03521 #ifdef __GNUC__
03522 #warning "that's a bad idea, can lead to stray endings, FIXME"
03523 #endif
03524
03525 bool removedStart = (removeStringFromBegining(line, longStartCommentMark)
03526 || removeStringFromBegining(line, shortStartCommentMark));
03527
03528 bool removedStop = false;
03529 if (removedStart)
03530 {
03531
03532 removedStop = (removeStringFromEnd(line, longStopCommentMark)
03533 || removeStringFromEnd(line, shortStopCommentMark));
03534 }
03535
03536 editEnd();
03537
03538 return (removedStart || removedStop);
03539 }
03540
03541
03542
03543
03544
03545
03546 void KateDocument::addStartStopCommentToSelection( KateView *view, int attrib )
03547 {
03548 QString startComment = highlight()->getCommentStart( attrib );
03549 QString endComment = highlight()->getCommentEnd( attrib );
03550
03551 int sl = view->selStartLine();
03552 int el = view->selEndLine();
03553 int sc = view->selStartCol();
03554 int ec = view->selEndCol();
03555
03556 if ((ec == 0) && ((el-1) >= 0))
03557 {
03558 el--;
03559 ec = m_buffer->plainLine (el)->length();
03560 }
03561
03562 editStart();
03563
03564 insertText (el, ec, endComment);
03565 insertText (sl, sc, startComment);
03566
03567 editEnd ();
03568
03569
03570 ec += endComment.length() + ( (el == sl) ? startComment.length() : 0 );
03571 view->setSelection(sl, sc, el, ec);
03572 }
03573
03574
03575
03576
03577
03578 void KateDocument::addStartLineCommentToSelection( KateView *view, int attrib )
03579 {
03580 QString commentLineMark = highlight()->getCommentSingleLineStart( attrib ) + " ";
03581
03582 int sl = view->selStartLine();
03583 int el = view->selEndLine();
03584
03585 if ((view->selEndCol() == 0) && ((el-1) >= 0))
03586 {
03587 el--;
03588 }
03589
03590 editStart();
03591
03592
03593 for (int z = el; z >= sl; z--) {
03594
03595 addStartLineCommentToSingleLine(z, attrib );
03596 }
03597
03598 editEnd ();
03599
03600
03601
03602 KateDocCursor end (view->selEnd());
03603 end.setCol(view->selEndCol() + ((el == view->selEndLine()) ? commentLineMark.length() : 0) );
03604
03605 view->setSelection(view->selStartLine(), 0, end.line(), end.col());
03606 }
03607
03608 bool KateDocument::nextNonSpaceCharPos(int &line, int &col)
03609 {
03610 for(; line < (int)m_buffer->count(); line++) {
03611 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
03612
03613 if (!textLine)
03614 break;
03615
03616 col = textLine->nextNonSpaceChar(col);
03617 if(col != -1)
03618 return true;
03619 col = 0;
03620 }
03621
03622 line = -1;
03623 col = -1;
03624 return false;
03625 }
03626
03627 bool KateDocument::previousNonSpaceCharPos(int &line, int &col)
03628 {
03629 while(true)
03630 {
03631 KateTextLine::Ptr textLine = m_buffer->plainLine(line);
03632
03633 if (!textLine)
03634 break;
03635
03636 col = textLine->previousNonSpaceChar(col);
03637 if(col != -1) return true;
03638 if(line == 0) return false;
03639 --line;
03640 col = textLine->length();
03641 }
03642
03643 line = -1;
03644 col = -1;
03645 return false;
03646 }
03647
03648
03649
03650
03651
03652 bool KateDocument::removeStartStopCommentFromSelection( KateView *view, int attrib )
03653 {
03654 QString startComment = highlight()->getCommentStart( attrib );
03655 QString endComment = highlight()->getCommentEnd( attrib );
03656
03657 int sl = kMax<int> (0, view->selStartLine());
03658 int el = kMin<int> (view->selEndLine(), lastLine());
03659 int sc = view->selStartCol();
03660 int ec = view->selEndCol();
03661
03662
03663 if (ec != 0) {
03664 ec--;
03665 } else {
03666 if (el > 0) {
03667 el--;
03668 ec = m_buffer->plainLine(el)->length() - 1;
03669 }
03670 }
03671
03672 int startCommentLen = startComment.length();
03673 int endCommentLen = endComment.length();
03674
03675
03676
03677 bool remove = nextNonSpaceCharPos(sl, sc)
03678 && m_buffer->plainLine(sl)->stringAtPos(sc, startComment)
03679 && previousNonSpaceCharPos(el, ec)
03680 && ( (ec - endCommentLen + 1) >= 0 )
03681 && m_buffer->plainLine(el)->stringAtPos(ec - endCommentLen + 1, endComment);
03682
03683 if (remove) {
03684 editStart();
03685
03686 removeText (el, ec - endCommentLen + 1, el, ec + 1);
03687 removeText (sl, sc, sl, sc + startCommentLen);
03688
03689 editEnd ();
03690
03691
03692 ec -= endCommentLen + ( (el == sl) ? startCommentLen : 0 );
03693 view->setSelection(sl, sc, el, ec + 1);
03694 }
03695
03696 return remove;
03697 }
03698
03699 bool KateDocument::removeStartStopCommentFromRegion(const KateTextCursor &start,const KateTextCursor &end,int attrib)
03700 {
03701 QString startComment = highlight()->getCommentStart( attrib );
03702 QString endComment = highlight()->getCommentEnd( attrib );
03703 int startCommentLen = startComment.length();
03704 int endCommentLen = endComment.length();
03705
03706 bool remove = m_buffer->plainLine(start.line())->stringAtPos(start.col(), startComment)
03707 && ( (end.col() - endCommentLen ) >= 0 )
03708 && m_buffer->plainLine(end.line())->stringAtPos(end.col() - endCommentLen , endComment);
03709 if (remove) {
03710 editStart();
03711 removeText(end.line(),end.col()-endCommentLen,end.line(),end.col());
03712 removeText(start.line(),start.col(),start.line(),start.col()+startCommentLen);
03713 editEnd();
03714 }
03715 return remove;
03716 }
03717
03718
03719
03720
03721
03722 bool KateDocument::removeStartLineCommentFromSelection( KateView *view, int attrib )
03723 {
03724 QString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
03725 QString longCommentMark = shortCommentMark + " ";
03726
03727 int sl = view->selStartLine();
03728 int el = view->selEndLine();
03729
03730 if ((view->selEndCol() == 0) && ((el-1) >= 0))
03731 {
03732 el--;
03733 }
03734
03735
03736 int removeLength = 0;
03737 if (m_buffer->plainLine(el)->startingWith(longCommentMark))
03738 removeLength = longCommentMark.length();
03739 else if (m_buffer->plainLine(el)->startingWith(shortCommentMark))
03740 removeLength = shortCommentMark.length();
03741
03742 bool removed = false;
03743
03744 editStart();
03745
03746
03747 for (int z = el; z >= sl; z--)
03748 {
03749
03750 removed = (removeStringFromBegining(z, longCommentMark)
03751 || removeStringFromBegining(z, shortCommentMark)
03752 || removed);
03753 }
03754
03755 editEnd();
03756
03757 if (removed)
03758 {
03759
03760 KateDocCursor end (view->selEnd());
03761 end.setCol(view->selEndCol() - ((el == view->selEndLine()) ? removeLength : 0) );
03762
03763 setSelection(view->selStartLine(), view->selStartCol(), end.line(), end.col());
03764 }
03765
03766 return removed;
03767 }
03768
03769
03770
03771
03772
03773 void KateDocument::comment( KateView *v, uint line,uint column, int change)
03774 {
03775
03776
03777
03778
03779 bool hassel = v->hasSelection();
03780 int startAttrib, endAttrib;
03781 if ( hassel )
03782 {
03783 KateTextLine::Ptr ln = kateTextLine( v->selStartLine() );
03784 int l = v->selStartLine(), c = v->selStartCol();
03785 startAttrib = nextNonSpaceCharPos( l, c ) ? kateTextLine( l )->attribute( c ) : 0;
03786
03787 ln = kateTextLine( v->selEndLine() );
03788 l = v->selEndLine(), c = v->selEndCol();
03789 endAttrib = previousNonSpaceCharPos( l, c ) ? kateTextLine( l )->attribute( c ) : 0;
03790 }
03791 else
03792 {
03793 KateTextLine::Ptr ln = kateTextLine( line );
03794 if ( ln->length() )
03795 {
03796 startAttrib = ln->attribute( ln->firstChar() );
03797 endAttrib = ln->attribute( ln->lastChar() );
03798 }
03799 else
03800 {
03801 int l = line, c = 0;
03802 if ( nextNonSpaceCharPos( l, c ) || previousNonSpaceCharPos( l, c ) )
03803 startAttrib = endAttrib = kateTextLine( l )->attribute( c );
03804 else
03805 startAttrib = endAttrib = 0;
03806 }
03807 }
03808
03809 if ( ! highlight()->canComment( startAttrib, endAttrib ) )
03810 {
03811 kdDebug(13020)<<"canComment( "<<startAttrib<<", "<<endAttrib<<" ) returned false!"<<endl;
03812 return;
03813 }
03814
03815 bool hasStartLineCommentMark = !(highlight()->getCommentSingleLineStart( startAttrib ).isEmpty());
03816 bool hasStartStopCommentMark = ( !(highlight()->getCommentStart( startAttrib ).isEmpty())
03817 && !(highlight()->getCommentEnd( endAttrib ).isEmpty()) );
03818
03819 bool removed = false;
03820
03821 if (change > 0)
03822 {
03823 if ( !hassel )
03824 {
03825 if ( hasStartLineCommentMark )
03826 addStartLineCommentToSingleLine( line, startAttrib );
03827 else if ( hasStartStopCommentMark )
03828 addStartStopCommentToSingleLine( line, startAttrib );
03829 }
03830 else
03831 {
03832
03833
03834
03835
03836
03837
03838
03839 if ( hasStartStopCommentMark &&
03840 ( !hasStartLineCommentMark || (
03841 ( v->selStartCol() > m_buffer->plainLine( v->selStartLine() )->firstChar() ) ||
03842 ( v->selEndCol() < ((int)m_buffer->plainLine( v->selEndLine() )->length()) )
03843 ) ) )
03844 addStartStopCommentToSelection( v, startAttrib );
03845 else if ( hasStartLineCommentMark )
03846 addStartLineCommentToSelection( v, startAttrib );
03847 }
03848 }
03849 else
03850 {
03851 if ( !hassel )
03852 {
03853 removed = ( hasStartLineCommentMark
03854 && removeStartLineCommentFromSingleLine( line, startAttrib ) )
03855 || ( hasStartStopCommentMark
03856 && removeStartStopCommentFromSingleLine( line, startAttrib ) );
03857 if ((!removed) && foldingTree()) {
03858 kdDebug(13020)<<"easy approach for uncommenting did not work, trying harder (folding tree)"<<endl;
03859 int commentRegion=(highlight()->commentRegion(startAttrib));
03860 if (commentRegion){
03861 KateCodeFoldingNode *n=foldingTree()->findNodeForPosition(line,column);
03862 if (n) {
03863 KateTextCursor start,end;
03864 if ((n->nodeType()==commentRegion) && n->getBegin(foldingTree(), &start) && n->getEnd(foldingTree(), &end)) {
03865 kdDebug(13020)<<"Enclosing region found:"<<start.col()<<"/"<<start.line()<<"-"<<end.col()<<"/"<<end.line()<<endl;
03866 removeStartStopCommentFromRegion(start,end,startAttrib);
03867 } else {
03868 kdDebug(13020)<<"Enclosing region found, but not valid"<<endl;
03869 kdDebug(13020)<<"Region found: "<<n->nodeType()<<" region needed: "<<commentRegion<<endl;
03870 }
03871
03872 } else kdDebug(13020)<<"No enclosing region found"<<endl;
03873 } else kdDebug(13020)<<"No comment region specified for current hl"<<endl;
03874 }
03875 }
03876 else
03877 {
03878
03879 removed = ( hasStartLineCommentMark
03880 && removeStartLineCommentFromSelection( v, startAttrib ) )
03881 || ( hasStartStopCommentMark
03882 && removeStartStopCommentFromSelection( v, startAttrib ) );
03883 }
03884 }
03885 }
03886
03887 void KateDocument::transform( KateView *v, const KateTextCursor &c,
03888 KateDocument::TextTransform t )
03889 {
03890 editStart();
03891 uint cl( c.line() ), cc( c.col() );
03892 bool selectionRestored = false;
03893
03894 if ( hasSelection() )
03895 {
03896
03897 KateTextCursor selstart = v->selStart();
03898 KateTextCursor selend = v->selEnd();
03899
03900 int ln = v->selStartLine();
03901 while ( ln <= selend.line() )
03902 {
03903 uint start, end;
03904 start = (ln == selstart.line() || v->blockSelectionMode()) ?
03905 selstart.col() : 0;
03906 end = (ln == selend.line() || v->blockSelectionMode()) ?
03907 selend.col() : lineLength( ln );
03908 if ( start > end )
03909 {
03910 uint t = start;
03911 start = end;
03912 end = t;
03913 }
03914 QString s = text( ln, start, ln, end );
03915
03916 if ( t == Uppercase )
03917 s = s.upper();
03918 else if ( t == Lowercase )
03919 s = s.lower();
03920 else
03921 {
03922 KateTextLine::Ptr l = m_buffer->plainLine( ln );
03923 uint p ( 0 );
03924 while( p < s.length() )
03925 {
03926
03927
03928
03929
03930 if ( ( ! start && ! p ) ||
03931 ( ( ln == selstart.line() || v->blockSelectionMode() ) &&
03932 ! p && ! highlight()->isInWord( l->getChar( start - 1 )) ) ||
03933 ( p && ! highlight()->isInWord( s.at( p-1 ) ) )
03934 )
03935 s[p] = s.at(p).upper();
03936 p++;
03937 }
03938 }
03939
03940 removeText( ln, start, ln, end );
03941 insertText( ln, start, s );
03942
03943 ln++;
03944 }
03945
03946
03947 v->setSelection( selstart, selend );
03948 selectionRestored = true;
03949
03950 } else {
03951 QString s;
03952 int n ( cc );
03953 switch ( t ) {
03954 case Uppercase:
03955 s = text( cl, cc, cl, cc + 1 ).upper();
03956 break;
03957 case Lowercase:
03958 s = text( cl, cc, cl, cc + 1 ).lower();
03959 break;
03960 case Capitalize:
03961 {
03962 KateTextLine::Ptr l = m_buffer->plainLine( cl );
03963 while ( n > 0 && highlight()->isInWord( l->getChar( n-1 ), l->attribute( n-1 ) ) )
03964 n--;
03965 s = text( cl, n, cl, n + 1 ).upper();
03966 }
03967 break;
03968 default:
03969 break;
03970 }
03971 removeText( cl, n, cl, n+1 );
03972 insertText( cl, n, s );
03973 }
03974
03975 if ( ! selectionRestored )
03976 v->setCursorPosition( cl, cc );
03977
03978 editEnd();
03979 }
03980
03981 void KateDocument::joinLines( uint first, uint last )
03982 {
03983
03984 editStart();
03985 int line( first );
03986 while ( first < last )
03987 {
03988
03989
03990
03991
03992
03993 KateTextLine::Ptr l = m_buffer->line( line );
03994 KateTextLine::Ptr tl = m_buffer->line( line + 1 );
03995
03996 if ( !l || !tl )
03997 {
03998 editEnd();
03999 return;
04000 }
04001
04002 int pos = tl->firstChar();
04003 if ( pos >= 0 )
04004 {
04005 if (pos != 0)
04006 editRemoveText( line + 1, 0, pos );
04007 if ( !( l->length() == 0 || l->getChar( l->length() - 1 ).isSpace() ) )
04008 editInsertText( line + 1, 0, " " );
04009 }
04010 else
04011 {
04012
04013 editRemoveText( line + 1, 0, tl->length() );
04014 }
04015
04016 editUnWrapLine( line );
04017 first++;
04018 }
04019 editEnd();
04020 }
04021
04022 QString KateDocument::getWord( const KateTextCursor& cursor ) {
04023 int start, end, len;
04024
04025 KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
04026 len = textLine->length();
04027 start = end = cursor.col();
04028 if (start > len)
04029 return QString("");
04030
04031 while (start > 0 && highlight()->isInWord(textLine->getChar(start - 1), textLine->attribute(start - 1))) start--;
04032 while (end < len && highlight()->isInWord(textLine->getChar(end), textLine->attribute(end))) end++;
04033 len = end - start;
04034 return QString(&textLine->text()[start], len);
04035 }
04036
04037 void KateDocument::tagLines(int start, int end)
04038 {
04039 for (uint z = 0; z < m_views.count(); z++)
04040 m_views.at(z)->tagLines (start, end, true);
04041 }
04042
04043 void KateDocument::tagLines(KateTextCursor start, KateTextCursor end)
04044 {
04045
04046 if (blockSelectionMode() && start.col() > end.col()) {
04047 int sc = start.col();
04048 start.setCol(end.col());
04049 end.setCol(sc);
04050 }
04051
04052 for (uint z = 0; z < m_views.count(); z++)
04053 m_views.at(z)->tagLines(start, end, true);
04054 }
04055
04056 void KateDocument::repaintViews(bool paintOnlyDirty)
04057 {
04058 for (uint z = 0; z < m_views.count(); z++)
04059 m_views.at(z)->repaintText(paintOnlyDirty);
04060 }
04061
04062 void KateDocument::tagAll()
04063 {
04064 for (uint z = 0; z < m_views.count(); z++)
04065 {
04066 m_views.at(z)->tagAll();
04067 m_views.at(z)->updateView (true);
04068 }
04069 }
04070
04071 uint KateDocument::configFlags ()
04072 {
04073 return config()->configFlags();
04074 }
04075
04076 void KateDocument::setConfigFlags (uint flags)
04077 {
04078 config()->setConfigFlags(flags);
04079 }
04080
04081 inline bool isStartBracket( const QChar& c ) { return c == '{' || c == '[' || c == '('; }
04082 inline bool isEndBracket ( const QChar& c ) { return c == '}' || c == ']' || c == ')'; }
04083 inline bool isBracket ( const QChar& c ) { return isStartBracket( c ) || isEndBracket( c ); }
04084
04085
04086
04087
04088
04089
04090
04091
04092
04093
04094
04095 void KateDocument::newBracketMark( const KateTextCursor& cursor, KateBracketRange& bm, int maxLines )
04096 {
04097 bm.setValid(false);
04098
04099 bm.start() = cursor;
04100
04101 if( !findMatchingBracket( bm.start(), bm.end(), maxLines ) )
04102 return;
04103
04104 bm.setValid(true);
04105
04106 const int tw = config()->tabWidth();
04107 const int indentStart = m_buffer->plainLine(bm.start().line())->indentDepth(tw);
04108 const int indentEnd = m_buffer->plainLine(bm.end().line())->indentDepth(tw);
04109 bm.setIndentMin(QMIN(indentStart, indentEnd));
04110 }
04111
04112 bool KateDocument::findMatchingBracket( KateTextCursor& start, KateTextCursor& end, int maxLines )
04113 {
04114 KateTextLine::Ptr textLine = m_buffer->plainLine( start.line() );
04115 if( !textLine )
04116 return false;
04117
04118 QChar right = textLine->getChar( start.col() );
04119 QChar left = textLine->getChar( start.col() - 1 );
04120 QChar bracket;
04121
04122 if ( config()->configFlags() & cfOvr ) {
04123 if( isBracket( right ) ) {
04124 bracket = right;
04125 } else {
04126 return false;
04127 }
04128 } else if ( isStartBracket( right ) ) {
04129 bracket = right;
04130 } else if ( isEndBracket( left ) ) {
04131 start.setCol(start.col() - 1);
04132 bracket = left;
04133 } else if ( isBracket( left ) ) {
04134 start.setCol(start.col() - 1);
04135 bracket = left;
04136 } else if ( isBracket( right ) ) {
04137 bracket = right;
04138 } else {
04139 return false;
04140 }
04141
04142 QChar opposite;
04143
04144 switch( bracket ) {
04145 case '{': opposite = '}'; break;
04146 case '}': opposite = '{'; break;
04147 case '[': opposite = ']'; break;
04148 case ']': opposite = '['; break;
04149 case '(': opposite = ')'; break;
04150 case ')': opposite = '('; break;
04151 default: return false;
04152 }
04153
04154 bool forward = isStartBracket( bracket );
04155 int startAttr = textLine->attribute( start.col() );
04156 uint count = 0;
04157 int lines = 0;
04158 end = start;
04159
04160 while( true ) {
04161
04162 if( forward ) {
04163 end.setCol(end.col() + 1);
04164 if( end.col() >= lineLength( end.line() ) ) {
04165 if( end.line() >= (int)lastLine() )
04166 return false;
04167 end.setPos(end.line() + 1, 0);
04168 textLine = m_buffer->plainLine( end.line() );
04169 lines++;
04170 }
04171 } else {
04172 end.setCol(end.col() - 1);
04173 if( end.col() < 0 ) {
04174 if( end.line() <= 0 )
04175 return false;
04176 end.setLine(end.line() - 1);
04177 end.setCol(lineLength( end.line() ) - 1);
04178 textLine = m_buffer->plainLine( end.line() );
04179 lines++;
04180 }
04181 }
04182
04183 if ((maxLines != -1) && (lines > maxLines))
04184 return false;
04185
04186
04187 if( textLine->attribute( end.col() ) != startAttr )
04188 continue;
04189
04190
04191 QChar c = textLine->getChar( end.col() );
04192 if( c == bracket ) {
04193 count++;
04194 } else if( c == opposite ) {
04195 if( count == 0 )
04196 return true;
04197 count--;
04198 }
04199
04200 }
04201 }
04202
04203 void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev )
04204 {
04205 KParts::ReadWritePart::guiActivateEvent( ev );
04206 if ( ev->activated() )
04207 emit selectionChanged();
04208 }
04209
04210 void KateDocument::setDocName (QString name )
04211 {
04212 if ( name == m_docName )
04213 return;
04214
04215 if ( !name.isEmpty() )
04216 {
04217
04218 m_docName = name;
04219 updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
04220 emit nameChanged((Kate::Document *) this);
04221 return;
04222 }
04223
04224
04225 if ( ! url().isEmpty() && m_docName.startsWith( url().filename() ) ) return;
04226
04227 int count = -1;
04228
04229 for (uint z=0; z < KateFactory::self()->documents()->count(); z++)
04230 {
04231 if ( (KateFactory::self()->documents()->at(z) != this) && (KateFactory::self()->documents()->at(z)->url().filename() == url().filename()) )
04232 if ( KateFactory::self()->documents()->at(z)->m_docNameNumber > count )
04233 count = KateFactory::self()->documents()->at(z)->m_docNameNumber;
04234 }
04235
04236 m_docNameNumber = count + 1;
04237
04238 m_docName = url().filename();
04239
04240 if (m_docName.isEmpty())
04241 m_docName = i18n ("Untitled");
04242
04243 if (m_docNameNumber > 0)
04244 m_docName = QString(m_docName + " (%1)").arg(m_docNameNumber+1);
04245
04246 updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
04247 emit nameChanged ((Kate::Document *) this);
04248 }
04249
04250 void KateDocument::slotModifiedOnDisk( Kate::View * )
04251 {
04252 if ( m_isasking < 0 )
04253 {
04254 m_isasking = 0;
04255 return;
04256 }
04257
04258 if ( !s_fileChangedDialogsActivated || m_isasking )
04259 return;
04260
04261 if (m_modOnHd && !url().isEmpty())
04262 {
04263 m_isasking = 1;
04264
04265 KateModOnHdPrompt p( this, m_modOnHdReason, reasonedMOHString(), widget() );
04266 switch ( p.exec() )
04267 {
04268 case KateModOnHdPrompt::Save:
04269 {
04270 m_modOnHd = false;
04271 KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveURLAndEncoding(config()->encoding(),
04272 url().url(),QString::null,widget(),i18n("Save File"));
04273
04274 kdDebug(13020)<<"got "<<res.URLs.count()<<" URLs"<<endl;
04275 if( ! res.URLs.isEmpty() && ! res.URLs.first().isEmpty() && checkOverwrite( res.URLs.first() ) )
04276 {
04277 setEncoding( res.encoding );
04278
04279 if( ! saveAs( res.URLs.first() ) )
04280 {
04281 KMessageBox::error( widget(), i18n("Save failed") );
04282 m_modOnHd = true;
04283 }
04284 else
04285 emit modifiedOnDisc( this, false, 0 );
04286 }
04287 else
04288 {
04289 m_modOnHd = true;
04290 }
04291
04292 m_isasking = 0;
04293 break;
04294 }
04295
04296 case KateModOnHdPrompt::Reload:
04297 m_modOnHd = false;
04298 emit modifiedOnDisc( this, false, 0 );
04299 reloadFile();
04300 m_isasking = 0;
04301 break;
04302
04303 case KateModOnHdPrompt::Ignore:
04304 m_modOnHd = false;
04305 emit modifiedOnDisc( this, false, 0 );
04306 m_isasking = 0;
04307 break;
04308
04309 case KateModOnHdPrompt::Overwrite:
04310 m_modOnHd = false;
04311 emit modifiedOnDisc( this, false, 0 );
04312 m_isasking = 0;
04313 save();
04314 break;
04315
04316 default:
04317 m_isasking = -1;
04318 }
04319 }
04320 }
04321
04322 void KateDocument::setModifiedOnDisk( int reason )
04323 {
04324 m_modOnHdReason = reason;
04325 m_modOnHd = (reason > 0);
04326 emit modifiedOnDisc( this, (reason > 0), reason );
04327 }
04328
04329 class KateDocumentTmpMark
04330 {
04331 public:
04332 QString line;
04333 KTextEditor::Mark mark;
04334 };
04335
04336 void KateDocument::reloadFile()
04337 {
04338 if ( !url().isEmpty() )
04339 {
04340 if (m_modOnHd && s_fileChangedDialogsActivated)
04341 {
04342 int i = KMessageBox::warningYesNoCancel
04343 (0, reasonedMOHString() + "\n\n" + i18n("What do you want to do?"),
04344 i18n("File Was Changed on Disk"), i18n("&Reload File"), i18n("&Ignore Changes"));
04345
04346 if ( i != KMessageBox::Yes)
04347 {
04348 if (i == KMessageBox::No)
04349 {
04350 m_modOnHd = false;
04351 m_modOnHdReason = 0;
04352 emit modifiedOnDisc (this, m_modOnHd, 0);
04353 }
04354
04355 return;
04356 }
04357 }
04358
04359 QValueList<KateDocumentTmpMark> tmp;
04360
04361 for( QIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
04362 {
04363 KateDocumentTmpMark m;
04364
04365 m.line = textLine (it.current()->line);
04366 m.mark = *it.current();
04367
04368 tmp.append (m);
04369 }
04370
04371 uint mode = hlMode ();
04372 bool byUser = hlSetByUser;
04373
04374 m_storedVariables.clear();
04375
04376 m_reloading = true;
04377
04378 QValueList<int> lines, cols;
04379 for ( uint i=0; i < m_views.count(); i++ )
04380 {
04381 lines.append( m_views.at( i )->cursorLine() );
04382 cols.append( m_views.at( i )->cursorColumn() );
04383 }
04384
04385 KateDocument::openURL( url() );
04386
04387 for ( uint i=0; i < m_views.count(); i++ )
04388 m_views.at( i )->setCursorPositionInternal( lines[ i ], cols[ i ], m_config->tabWidth(), false );
04389
04390 m_reloading = false;
04391
04392 for (uint z=0; z < tmp.size(); z++)
04393 {
04394 if (z < numLines())
04395 {
04396 if (textLine(tmp[z].mark.line) == tmp[z].line)
04397 setMark (tmp[z].mark.line, tmp[z].mark.type);
04398 }
04399 }
04400
04401 if (byUser)
04402 setHlMode (mode);
04403 }
04404 }
04405
04406 void KateDocument::flush ()
04407 {
04408 closeURL ();
04409 }
04410
04411 void KateDocument::setWordWrap (bool on)
04412 {
04413 config()->setWordWrap (on);
04414 }
04415
04416 bool KateDocument::wordWrap ()
04417 {
04418 return config()->wordWrap ();
04419 }
04420
04421 void KateDocument::setWordWrapAt (uint col)
04422 {
04423 config()->setWordWrapAt (col);
04424 }
04425
04426 unsigned int KateDocument::wordWrapAt ()
04427 {
04428 return config()->wordWrapAt ();
04429 }
04430
04431 void KateDocument::applyWordWrap ()
04432 {
04433
04434 }
04435
04436 void KateDocument::setPageUpDownMovesCursor (bool on)
04437 {
04438 config()->setPageUpDownMovesCursor (on);
04439 }
04440
04441 bool KateDocument::pageUpDownMovesCursor ()
04442 {
04443 return config()->pageUpDownMovesCursor ();
04444 }
04445
04446 void KateDocument::dumpRegionTree()
04447 {
04448 m_buffer->foldingTree()->debugDump();
04449 }
04450
04451
04452
04453
04454 KTextEditor::Cursor *KateDocument::createCursor ( )
04455 {
04456 return new KateSuperCursor (this, false, 0, 0, this);
04457 }
04458
04459 void KateDocument::tagArbitraryLines(KateView* view, KateSuperRange* range)
04460 {
04461 if (view)
04462 view->tagLines(range->start(), range->end());
04463 else
04464 tagLines(range->start(), range->end());
04465 }
04466
04467 void KateDocument::lineInfo (KateLineInfo *info, unsigned int line)
04468 {
04469 m_buffer->lineInfo(info,line);
04470 }
04471
04472 KateCodeFoldingTree *KateDocument::foldingTree ()
04473 {
04474 return m_buffer->foldingTree();
04475 }
04476
04477 void KateDocument::setEncoding (const QString &e)
04478 {
04479 if ( m_encodingSticky )
04480 return;
04481
04482 QString ce = m_config->encoding().lower();
04483 if ( e.lower() == ce )
04484 return;
04485
04486 m_config->setEncoding( e );
04487 if ( ! m_loading )
04488 reloadFile();
04489 }
04490
04491 QString KateDocument::encoding() const
04492 {
04493 return m_config->encoding();
04494 }
04495
04496 void KateDocument::updateConfig ()
04497 {
04498 emit undoChanged ();
04499 tagAll();
04500
04501 for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
04502 {
04503 view->updateDocumentConfig ();
04504 }
04505
04506
04507 if (m_indenter->modeNumber() != m_config->indentationMode())
04508 {
04509 delete m_indenter;
04510 m_indenter = KateAutoIndent::createIndenter ( this, m_config->indentationMode() );
04511 }
04512
04513 m_indenter->updateConfig();
04514
04515 m_buffer->setTabWidth (config()->tabWidth());
04516
04517
04518 for (uint i=0; i<KateFactory::self()->plugins().count(); i++)
04519 {
04520 if (config()->plugin (i))
04521 loadPlugin (i);
04522 else
04523 unloadPlugin (i);
04524 }
04525 }
04526
04527
04528
04529
04530
04531
04532
04533
04534 QRegExp KateDocument::kvLine = QRegExp("kate:(.*)");
04535 QRegExp KateDocument::kvVar = QRegExp("([\\w\\-]+)\\s+([^;]+)");
04536
04537 void KateDocument::readVariables(bool onlyViewAndRenderer)
04538 {
04539 if (!onlyViewAndRenderer)
04540 m_config->configStart();
04541
04542
04543 KateView *v;
04544 for (v = m_views.first(); v != 0L; v= m_views.next() )
04545 {
04546 v->config()->configStart();
04547 v->renderer()->config()->configStart();
04548 }
04549
04550 for (uint i=0; i < QMIN( 9, numLines() ); ++i )
04551 {
04552 readVariableLine( textLine( i ), onlyViewAndRenderer );
04553 }
04554 if ( numLines() > 10 )
04555 {
04556 for ( uint i = QMAX(10, numLines() - 10); i < numLines(); ++i )
04557 {
04558 readVariableLine( textLine( i ), onlyViewAndRenderer );
04559 }
04560 }
04561
04562 if (!onlyViewAndRenderer)
04563 m_config->configEnd();
04564
04565 for (v = m_views.first(); v != 0L; v= m_views.next() )
04566 {
04567 v->config()->configEnd();
04568 v->renderer()->config()->configEnd();
04569 }
04570 }
04571
04572 void KateDocument::readVariableLine( QString t, bool onlyViewAndRenderer )
04573 {
04574 if ( kvLine.search( t ) > -1 )
04575 {
04576 QStringList vvl;
04577 vvl << "dynamic-word-wrap" << "dynamic-word-wrap-indicators"
04578 << "line-numbers" << "icon-border" << "folding-markers"
04579 << "bookmark-sorting" << "auto-center-lines"
04580 << "icon-bar-color"
04581
04582 << "background-color" << "selection-color"
04583 << "current-line-color" << "bracket-highlight-color"
04584 << "word-wrap-marker-color"
04585 << "font" << "font-size" << "scheme";
04586 int p( 0 );
04587 QString s = kvLine.cap(1);
04588 QString var, val;
04589 while ( (p = kvVar.search( s, p )) > -1 )
04590 {
04591 p += kvVar.matchedLength();
04592 var = kvVar.cap( 1 );
04593 val = kvVar.cap( 2 ).stripWhiteSpace();
04594 bool state;
04595 int n;
04596
04597
04598 if (onlyViewAndRenderer)
04599 {
04600 if ( vvl.contains( var ) )
04601 setViewVariable( var, val );
04602 }
04603 else
04604 {
04605
04606 if ( var == "word-wrap" && checkBoolValue( val, &state ) )
04607 setWordWrap( state );
04608 else if ( var == "block-selection" && checkBoolValue( val, &state ) )
04609 setBlockSelectionMode( state );
04610
04611
04612 else if ( var == "backspace-indents" && checkBoolValue( val, &state ) )
04613 m_config->setConfigFlags( KateDocumentConfig::cfBackspaceIndents, state );
04614 else if ( var == "replace-tabs" && checkBoolValue( val, &state ) )
04615 m_config->setConfigFlags( KateDocumentConfig::cfReplaceTabsDyn, state );
04616 else if ( var == "remove-trailing-space" && checkBoolValue( val, &state ) )
04617 m_config->setConfigFlags( KateDocumentConfig::cfRemoveTrailingDyn, state );
04618 else if ( var == "wrap-cursor" && checkBoolValue( val, &state ) )
04619 m_config->setConfigFlags( KateDocumentConfig::cfWrapCursor, state );
04620 else if ( var == "auto-brackets" && checkBoolValue( val, &state ) )
04621 m_config->setConfigFlags( KateDocumentConfig::cfAutoBrackets, state );
04622 else if ( var == "overwrite-mode" && checkBoolValue( val, &state ) )
04623 m_config->setConfigFlags( KateDocumentConfig::cfOvr, state );
04624 else if ( var == "keep-indent-profile" && checkBoolValue( val, &state ) )
04625 m_config->setConfigFlags( KateDocumentConfig::cfKeepIndentProfile, state );
04626 else if ( var == "keep-extra-spaces" && checkBoolValue( val, &state ) )
04627 m_config->setConfigFlags( KateDocumentConfig::cfKeepExtraSpaces, state );
04628 else if ( var == "tab-indents" && checkBoolValue( val, &state ) )
04629 m_config->setConfigFlags( KateDocumentConfig::cfTabIndents, state );
04630 else if ( var == "show-tabs" && checkBoolValue( val, &state ) )
04631 m_config->setConfigFlags( KateDocumentConfig::cfShowTabs, state );
04632 else if ( var == "space-indent" && checkBoolValue( val, &state ) )
04633 m_config->setConfigFlags( KateDocumentConfig::cfSpaceIndent, state );
04634 else if ( var == "smart-home" && checkBoolValue( val, &state ) )
04635 m_config->setConfigFlags( KateDocumentConfig::cfSmartHome, state );
04636 else if ( var == "replace-trailing-space-save" && checkBoolValue( val, &state ) )
04637 m_config->setConfigFlags( KateDocumentConfig::cfRemoveSpaces, state );
04638 else if ( var == "auto-insert-doxygen" && checkBoolValue( val, &state) )
04639 m_config->setConfigFlags( KateDocumentConfig::cfDoxygenAutoTyping, state);
04640 else if ( var == "mixed-indent" && checkBoolValue( val, &state ) )
04641 m_config->setConfigFlags( KateDocumentConfig::cfMixedIndent, state );
04642
04643
04644 else if ( var == "tab-width" && checkIntValue( val, &n ) )
04645 m_config->setTabWidth( n );
04646 else if ( var == "indent-width" && checkIntValue( val, &n ) )
04647 m_config->setIndentationWidth( n );
04648 else if ( var == "indent-mode" )
04649 {
04650 if ( checkIntValue( val, &n ) )
04651 m_config->setIndentationMode( n );
04652 else
04653 m_config->setIndentationMode( KateAutoIndent::modeNumber( val) );
04654 }
04655 else if ( var == "word-wrap-column" && n > 0 && checkIntValue( val, &n ) )
04656 m_config->setWordWrapAt( n );
04657 else if ( var == "undo-steps" && n >= 0 && checkIntValue( val, &n ) )
04658 setUndoSteps( n );
04659
04660
04661 else if ( var == "eol" || var == "end-of-line" )
04662 {
04663 QStringList l;
04664 l << "unix" << "dos" << "mac";
04665 if ( (n = l.findIndex( val.lower() )) != -1 )
04666 m_config->setEol( n );
04667 }
04668 else if ( var == "encoding" )
04669 m_config->setEncoding( val );
04670 else if ( var == "syntax" || var == "hl" )
04671 {
04672 for ( uint i=0; i < hlModeCount(); i++ )
04673 {
04674 if ( hlModeName( i ).lower() == val.lower() )
04675 {
04676 setHlMode( i );
04677 break;
04678 }
04679 }
04680 }
04681
04682
04683 else if ( vvl.contains( var ) )
04684 setViewVariable( var, val );
04685 else
04686 {
04687 m_storedVariables.insert( var, val );
04688 emit variableChanged( var, val );
04689 }
04690 }
04691 }
04692 }
04693 }
04694
04695 void KateDocument::setViewVariable( QString var, QString val )
04696 {
04697 KateView *v;
04698 bool state;
04699 int n;
04700 QColor c;
04701 for (v = m_views.first(); v != 0L; v= m_views.next() )
04702 {
04703 if ( var == "dynamic-word-wrap" && checkBoolValue( val, &state ) )
04704 v->config()->setDynWordWrap( state );
04705 else if ( var == "persistent-selection" && checkBoolValue( val, &state ) )
04706 v->config()->setPersistentSelection( state );
04707
04708 else if ( var == "line-numbers" && checkBoolValue( val, &state ) )
04709 v->config()->setLineNumbers( state );
04710 else if (var == "icon-border" && checkBoolValue( val, &state ) )
04711 v->config()->setIconBar( state );
04712 else if (var == "folding-markers" && checkBoolValue( val, &state ) )
04713 v->config()->setFoldingBar( state );
04714 else if ( var == "auto-center-lines" && checkIntValue( val, &n ) )
04715 v->config()->setAutoCenterLines( n );
04716 else if ( var == "icon-bar-color" && checkColorValue( val, c ) )
04717 v->renderer()->config()->setIconBarColor( c );
04718
04719 else if ( var == "background-color" && checkColorValue( val, c ) )
04720 v->renderer()->config()->setBackgroundColor( c );
04721 else if ( var == "selection-color" && checkColorValue( val, c ) )
04722 v->renderer()->config()->setSelectionColor( c );
04723 else if ( var == "current-line-color" && checkColorValue( val, c ) )
04724 v->renderer()->config()->setHighlightedLineColor( c );
04725 else if ( var == "bracket-highlight-color" && checkColorValue( val, c ) )
04726 v->renderer()->config()->setHighlightedBracketColor( c );
04727 else if ( var == "word-wrap-marker-color" && checkColorValue( val, c ) )
04728 v->renderer()->config()->setWordWrapMarkerColor( c );
04729 else if ( var == "font" || ( var == "font-size" && checkIntValue( val, &n ) ) )
04730 {
04731 QFont _f( *v->renderer()->config()->font( ) );
04732
04733 if ( var == "font" )
04734 {
04735 _f.setFamily( val );
04736 _f.setFixedPitch( QFont( val ).fixedPitch() );
04737 }
04738 else
04739 _f.setPointSize( n );
04740
04741 v->renderer()->config()->setFont( _f );
04742 }
04743 else if ( var == "scheme" )
04744 {
04745 v->renderer()->config()->setSchema( KateFactory::self()->schemaManager()->number( val ) );
04746 }
04747 }
04748 }
04749
04750 bool KateDocument::checkBoolValue( QString val, bool *result )
04751 {
04752 val = val.stripWhiteSpace().lower();
04753 QStringList l;
04754 l << "1" << "on" << "true";
04755 if ( l.contains( val ) )
04756 {
04757 *result = true;
04758 return true;
04759 }
04760 l.clear();
04761 l << "0" << "off" << "false";
04762 if ( l.contains( val ) )
04763 {
04764 *result = false;
04765 return true;
04766 }
04767 return false;
04768 }
04769
04770 bool KateDocument::checkIntValue( QString val, int *result )
04771 {
04772 bool ret( false );
04773 *result = val.toInt( &ret );
04774 return ret;
04775 }
04776
04777 bool KateDocument::checkColorValue( QString val, QColor &c )
04778 {
04779 c.setNamedColor( val );
04780 return c.isValid();
04781 }
04782
04783
04784 QString KateDocument::variable( const QString &name ) const
04785 {
04786 if ( m_storedVariables.contains( name ) )
04787 return m_storedVariables[ name ];
04788
04789 return "";
04790 }
04791
04792
04793
04794 void KateDocument::slotModOnHdDirty (const QString &path)
04795 {
04796 if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 1))
04797 {
04798
04799 if ( ! m_digest.isEmpty() )
04800 {
04801 QCString tmp;
04802 if ( createDigest( tmp ) && tmp == m_digest )
04803 return;
04804 }
04805
04806 m_modOnHd = true;
04807 m_modOnHdReason = 1;
04808
04809
04810 if (m_isasking == -1)
04811 m_isasking = false;
04812
04813 emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
04814 }
04815 }
04816
04817 void KateDocument::slotModOnHdCreated (const QString &path)
04818 {
04819 if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 2))
04820 {
04821 m_modOnHd = true;
04822 m_modOnHdReason = 2;
04823
04824
04825 if (m_isasking == -1)
04826 m_isasking = false;
04827
04828 emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
04829 }
04830 }
04831
04832 void KateDocument::slotModOnHdDeleted (const QString &path)
04833 {
04834 if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 3))
04835 {
04836 m_modOnHd = true;
04837 m_modOnHdReason = 3;
04838
04839
04840 if (m_isasking == -1)
04841 m_isasking = false;
04842
04843 emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
04844 }
04845 }
04846
04847 bool KateDocument::createDigest( QCString &result )
04848 {
04849 bool ret = false;
04850 result = "";
04851 if ( url().isLocalFile() )
04852 {
04853 QFile f ( url().path() );
04854 if ( f.open( IO_ReadOnly) )
04855 {
04856 KMD5 md5;
04857 ret = md5.update( f );
04858 md5.hexDigest( result );
04859 f.close();
04860 ret = true;
04861 }
04862 }
04863 return ret;
04864 }
04865
04866 QString KateDocument::reasonedMOHString() const
04867 {
04868 switch( m_modOnHdReason )
04869 {
04870 case 1:
04871 return i18n("The file '%1' was modified by another program.").arg( url().prettyURL() );
04872 break;
04873 case 2:
04874 return i18n("The file '%1' was created by another program.").arg( url().prettyURL() );
04875 break;
04876 case 3:
04877 return i18n("The file '%1' was deleted by another program.").arg( url().prettyURL() );
04878 break;
04879 default:
04880 return QString();
04881 }
04882 }
04883
04884 void KateDocument::removeTrailingSpace( uint line )
04885 {
04886
04887 if ( config()->configFlags() & KateDocumentConfig::cfRemoveTrailingDyn )
04888 {
04889 KateTextLine::Ptr ln = kateTextLine( line );
04890
04891 if ( ! ln ) return;
04892
04893 if ( line == activeView()->cursorLine()
04894 && activeView()->cursorColumnReal() >= (uint)QMAX(0,ln->lastChar()) )
04895 return;
04896
04897 if ( ln->length() )
04898 {
04899 uint p = ln->lastChar() + 1;
04900 uint l = ln->length() - p;
04901 if ( l )
04902 editRemoveText( line, p, l);
04903 }
04904 }
04905 }
04906
04907 void KateDocument::updateFileType (int newType, bool user)
04908 {
04909 if (user || !m_fileTypeSetByUser)
04910 {
04911 const KateFileType *t = 0;
04912 if ((newType == -1) || (t = KateFactory::self()->fileTypeManager()->fileType (newType)))
04913 {
04914 m_fileType = newType;
04915
04916 if (t)
04917 {
04918 m_config->configStart();
04919
04920 KateView *v;
04921 for (v = m_views.first(); v != 0L; v= m_views.next() )
04922 {
04923 v->config()->configStart();
04924 v->renderer()->config()->configStart();
04925 }
04926
04927 readVariableLine( t->varLine );
04928
04929 m_config->configEnd();
04930 for (v = m_views.first(); v != 0L; v= m_views.next() )
04931 {
04932 v->config()->configEnd();
04933 v->renderer()->config()->configEnd();
04934 }
04935 }
04936 }
04937 }
04938 }
04939
04940 uint KateDocument::documentNumber () const
04941 {
04942 return KTextEditor::Document::documentNumber ();
04943 }
04944
04945
04946
04947
04948 void KateDocument::slotQueryClose_save(bool *handled, bool* abortClosing) {
04949 *handled=true;
04950 *abortClosing=true;
04951 if (m_url.isEmpty())
04952 {
04953 KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveURLAndEncoding(config()->encoding(),
04954 QString::null,QString::null,0,i18n("Save File"));
04955
04956 if( res.URLs.isEmpty() || !checkOverwrite( res.URLs.first() ) ) {
04957 *abortClosing=true;
04958 return;
04959 }
04960 setEncoding( res.encoding );
04961 saveAs( res.URLs.first() );
04962 *abortClosing=false;
04963 }
04964 else
04965 {
04966 save();
04967 *abortClosing=false;
04968 }
04969
04970 }
04971
04972 bool KateDocument::checkOverwrite( KURL u )
04973 {
04974 if( !u.isLocalFile() )
04975 return true;
04976
04977 QFileInfo info( u.path() );
04978 if( !info.exists() )
04979 return true;
04980
04981 return KMessageBox::Cancel != KMessageBox::warningContinueCancel( 0,
04982 i18n( "A file named \"%1\" already exists. "
04983 "Are you sure you want to overwrite it?" ).arg( info.fileName() ),
04984 i18n( "Overwrite File?" ),
04985 i18n( "&Overwrite" ) );
04986 }
04987
04988 void KateDocument::setDefaultEncoding (const QString &encoding)
04989 {
04990 s_defaultEncoding = encoding;
04991 }
04992
04993
04994 bool KateDocument::insertTemplateTextImplementation ( uint line, uint column, const QString &templateString, const QMap<QString,QString> &initialValues, QWidget *) {
04995 return (new KateTemplateHandler(this,line,column,templateString,initialValues))->initOk();
04996 }
04997
04998 void KateDocument::testTemplateCode() {
04999 int col=activeView()->cursorColumn();
05000 int line=activeView()->cursorLine();
05001 insertTemplateText(line,col,"for ${index} \\${NOPLACEHOLDER} ${index} ${blah} ${fullname} \\$${Placeholder} \\${${PLACEHOLDER2}}\n next line:${ANOTHERPLACEHOLDER} $${DOLLARBEFOREPLACEHOLDER} {NOTHING} {\n${cursor}\n}",QMap<QString,QString>());
05002 }
05003
05004 bool KateDocument::invokeTabInterceptor(KKey key) {
05005 if (m_tabInterceptor) return (*m_tabInterceptor)(key);
05006 return false;
05007 }
05008
05009 bool KateDocument::setTabInterceptor(KateKeyInterceptorFunctor *interceptor) {
05010 if (m_tabInterceptor) return false;
05011 m_tabInterceptor=interceptor;
05012 return true;
05013 }
05014
05015 bool KateDocument::removeTabInterceptor(KateKeyInterceptorFunctor *interceptor) {
05016 if (m_tabInterceptor!=interceptor) return false;
05017 m_tabInterceptor=0;
05018 return true;
05019 }
05020
05021
05022
05023 bool KateDocument::setSelection ( uint startLine, uint startCol, uint endLine, uint endCol )
05024 { if (m_activeView) return m_activeView->setSelection (startLine, startCol, endLine, endCol); return false; }
05025
05026 bool KateDocument::clearSelection ()
05027 { if (m_activeView) return m_activeView->clearSelection(); return false; }
05028
05029 bool KateDocument::hasSelection () const
05030 { if (m_activeView) return m_activeView->hasSelection (); return false; }
05031
05032 QString KateDocument::selection () const
05033 { if (m_activeView) return m_activeView->selection (); return QString(""); }
05034
05035 bool KateDocument::removeSelectedText ()
05036 { if (m_activeView) return m_activeView->removeSelectedText (); return false; }
05037
05038 bool KateDocument::selectAll()
05039 { if (m_activeView) return m_activeView->selectAll (); return false; }
05040
05041 int KateDocument::selStartLine()
05042 { if (m_activeView) return m_activeView->selStartLine (); return 0; }
05043
05044 int KateDocument::selStartCol()
05045 { if (m_activeView) return m_activeView->selStartCol (); return 0; }
05046
05047 int KateDocument::selEndLine()
05048 { if (m_activeView) return m_activeView->selEndLine (); return 0; }
05049
05050 int KateDocument::selEndCol()
05051 { if (m_activeView) return m_activeView->selEndCol (); return 0; }
05052
05053 bool KateDocument::blockSelectionMode ()
05054 { if (m_activeView) return m_activeView->blockSelectionMode (); return false; }
05055
05056 bool KateDocument::setBlockSelectionMode (bool on)
05057 { if (m_activeView) return m_activeView->setBlockSelectionMode (on); return false; }
05058
05059 bool KateDocument::toggleBlockSelectionMode ()
05060 { if (m_activeView) return m_activeView->toggleBlockSelectionMode (); return false; }
05061
05062
05063
05064
05065