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