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