TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5184 lines
129 KiB

  1. /* This file is part of the KDE libraries
  2. Copyright (C) 2001-2004 Christoph Cullmann <cullmann@kde.org>
  3. Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
  4. Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License version 2 as published by the Free Software Foundation.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public License
  13. along with this library; see the file COPYING.LIB. If not, write to
  14. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02111-13020, USA.
  16. */
  17. //BEGIN includes
  18. #include "katedocument.h"
  19. #include "katedocument.moc"
  20. #include "katekeyinterceptorfunctor.h"
  21. #include "katefactory.h"
  22. #include "katedialogs.h"
  23. #include "katehighlight.h"
  24. #include "kateview.h"
  25. #include "katesearch.h"
  26. #include "kateautoindent.h"
  27. #include "katetextline.h"
  28. #include "katedocumenthelpers.h"
  29. #include "kateprinter.h"
  30. #include "katelinerange.h"
  31. #include "katesupercursor.h"
  32. #include "katearbitraryhighlight.h"
  33. #include "katerenderer.h"
  34. #include "kateattribute.h"
  35. #include "kateconfig.h"
  36. #include "katefiletype.h"
  37. #include "kateschema.h"
  38. #include "katetemplatehandler.h"
  39. #include <tdetexteditor/plugin.h>
  40. #include <tdeio/job.h>
  41. #include <tdeio/netaccess.h>
  42. #include <tdeio/tdefileitem.h>
  43. #include <tdeparts/event.h>
  44. #include <tdelocale.h>
  45. #include <tdeglobal.h>
  46. #include <tdeapplication.h>
  47. #include <tdepopupmenu.h>
  48. #include <tdeconfig.h>
  49. #include <tdefiledialog.h>
  50. #include <tdemessagebox.h>
  51. #include <kstdaction.h>
  52. #include <kiconloader.h>
  53. #include <kxmlguifactory.h>
  54. #include <kdialogbase.h>
  55. #include <kdebug.h>
  56. #include <tdeglobalsettings.h>
  57. #include <klibloader.h>
  58. #include <kdirwatch.h>
  59. #include <twin.h>
  60. #include <kencodingfiledialog.h>
  61. #include <tdetempfile.h>
  62. #include <kmdcodec.h>
  63. #include <kstandarddirs.h>
  64. #include <tqtimer.h>
  65. #include <tqfile.h>
  66. #include <tqclipboard.h>
  67. #include <tqtextstream.h>
  68. #include <tqtextcodec.h>
  69. #include <tqmap.h>
  70. //END includes
  71. //BEGIN PRIVATE CLASSES
  72. class KatePartPluginItem
  73. {
  74. public:
  75. KTextEditor::Plugin *plugin;
  76. };
  77. //END PRIVATE CLASSES
  78. //BEGIN d'tor, c'tor
  79. //
  80. // KateDocument Constructor
  81. //
  82. KateDocument::KateDocument ( bool bSingleViewMode, bool bBrowserView,
  83. bool bReadOnly, TQWidget *parentWidget,
  84. const char *widgetName, TQObject *parent, const char *name)
  85. : Kate::Document(parent, name),
  86. m_plugins (KateFactory::self()->plugins().count()),
  87. m_undoDontMerge(false),
  88. m_undoIgnoreCancel(false),
  89. lastUndoGroupWhenSaved( 0 ),
  90. lastRedoGroupWhenSaved( 0 ),
  91. docWasSavedWhenUndoWasEmpty( true ),
  92. docWasSavedWhenRedoWasEmpty( true ),
  93. m_modOnHd (false),
  94. m_modOnHdReason (0),
  95. m_job (0),
  96. m_tempFile (0),
  97. m_tabInterceptor(0)
  98. {
  99. m_undoComplexMerge=false;
  100. m_isInUndo = false;
  101. // my dcop object
  102. setObjId ("KateDocument#"+documentDCOPSuffix());
  103. // tdetexteditor interfaces
  104. setBlockSelectionInterfaceDCOPSuffix (documentDCOPSuffix());
  105. setConfigInterfaceDCOPSuffix (documentDCOPSuffix());
  106. setConfigInterfaceExtensionDCOPSuffix (documentDCOPSuffix());
  107. setCursorInterfaceDCOPSuffix (documentDCOPSuffix());
  108. setEditInterfaceDCOPSuffix (documentDCOPSuffix());
  109. setEncodingInterfaceDCOPSuffix (documentDCOPSuffix());
  110. setHighlightingInterfaceDCOPSuffix (documentDCOPSuffix());
  111. setMarkInterfaceDCOPSuffix (documentDCOPSuffix());
  112. setMarkInterfaceExtensionDCOPSuffix (documentDCOPSuffix());
  113. setPrintInterfaceDCOPSuffix (documentDCOPSuffix());
  114. setSearchInterfaceDCOPSuffix (documentDCOPSuffix());
  115. setSelectionInterfaceDCOPSuffix (documentDCOPSuffix());
  116. setSelectionInterfaceExtDCOPSuffix (documentDCOPSuffix());
  117. setSessionConfigInterfaceDCOPSuffix (documentDCOPSuffix());
  118. setUndoInterfaceDCOPSuffix (documentDCOPSuffix());
  119. setWordWrapInterfaceDCOPSuffix (documentDCOPSuffix());
  120. // init local plugin array
  121. m_plugins.fill (0);
  122. // register doc at factory
  123. KateFactory::self()->registerDocument (this);
  124. m_reloading = false;
  125. m_loading = false;
  126. m_encodingSticky = false;
  127. m_buffer = new KateBuffer (this);
  128. // init the config object, be careful not to use it
  129. // until the initial readConfig() call is done
  130. m_config = new KateDocumentConfig (this);
  131. // init some more vars !
  132. m_activeView = 0L;
  133. hlSetByUser = false;
  134. m_fileType = -1;
  135. m_fileTypeSetByUser = false;
  136. setInstance( KateFactory::self()->instance() );
  137. editSessionNumber = 0;
  138. editIsRunning = false;
  139. m_editCurrentUndo = 0L;
  140. editWithUndo = false;
  141. m_docNameNumber = 0;
  142. m_bSingleViewMode = bSingleViewMode;
  143. m_bBrowserView = bBrowserView;
  144. m_bReadOnly = bReadOnly;
  145. m_marks.setAutoDelete( true );
  146. m_markPixmaps.setAutoDelete( true );
  147. m_markDescriptions.setAutoDelete( true );
  148. setMarksUserChangable( markType01 );
  149. m_undoMergeTimer = new TQTimer(this);
  150. connect(m_undoMergeTimer, TQT_SIGNAL(timeout()), TQT_SLOT(undoCancel()));
  151. clearMarks ();
  152. clearUndo ();
  153. clearRedo ();
  154. setModified (false);
  155. docWasSavedWhenUndoWasEmpty = true;
  156. // normal hl
  157. m_buffer->setHighlight (0);
  158. m_extension = new KateBrowserExtension( this );
  159. m_arbitraryHL = new KateArbitraryHighlight();
  160. m_indenter = KateAutoIndent::createIndenter ( this, 0 );
  161. m_indenter->updateConfig ();
  162. // some nice signals from the buffer
  163. connect(m_buffer, TQT_SIGNAL(tagLines(int,int)), this, TQT_SLOT(tagLines(int,int)));
  164. connect(m_buffer, TQT_SIGNAL(codeFoldingUpdated()),this,TQT_SIGNAL(codeFoldingUpdated()));
  165. // if the user changes the highlight with the dialog, notify the doc
  166. connect(KateHlManager::self(),TQT_SIGNAL(changed()),TQT_SLOT(internalHlChanged()));
  167. // signal for the arbitrary HL
  168. connect(m_arbitraryHL, TQT_SIGNAL(tagLines(KateView*, KateSuperRange*)), TQT_SLOT(tagArbitraryLines(KateView*, KateSuperRange*)));
  169. // signals for mod on hd
  170. connect( KateFactory::self()->dirWatch(), TQT_SIGNAL(dirty (const TQString &)),
  171. this, TQT_SLOT(slotModOnHdDirty (const TQString &)) );
  172. connect( KateFactory::self()->dirWatch(), TQT_SIGNAL(created (const TQString &)),
  173. this, TQT_SLOT(slotModOnHdCreated (const TQString &)) );
  174. connect( KateFactory::self()->dirWatch(), TQT_SIGNAL(deleted (const TQString &)),
  175. this, TQT_SLOT(slotModOnHdDeleted (const TQString &)) );
  176. // update doc name
  177. setDocName ("");
  178. // if single view mode, like in the konqui embedding, create a default view ;)
  179. if ( m_bSingleViewMode )
  180. {
  181. KTextEditor::View *view = createView( parentWidget, widgetName );
  182. insertChildClient( view );
  183. view->show();
  184. setWidget( view );
  185. }
  186. connect(this,TQT_SIGNAL(sigQueryClose(bool *, bool*)),this,TQT_SLOT(slotQueryClose_save(bool *, bool*)));
  187. m_isasking = 0;
  188. // plugins
  189. for (uint i=0; i<KateFactory::self()->plugins().count(); i++)
  190. {
  191. if (config()->plugin (i))
  192. loadPlugin (i);
  193. }
  194. }
  195. //
  196. // KateDocument Destructor
  197. //
  198. KateDocument::~KateDocument()
  199. {
  200. // remove file from dirwatch
  201. deactivateDirWatch ();
  202. if (!singleViewMode())
  203. {
  204. // clean up remaining views
  205. m_views.setAutoDelete( true );
  206. m_views.clear();
  207. }
  208. delete m_editCurrentUndo;
  209. delete m_arbitraryHL;
  210. // cleanup the undo items, very important, truee :/
  211. undoItems.setAutoDelete(true);
  212. undoItems.clear();
  213. // clean up plugins
  214. unloadAllPlugins ();
  215. delete m_config;
  216. delete m_indenter;
  217. KateFactory::self()->deregisterDocument (this);
  218. }
  219. //END
  220. //BEGIN Plugins
  221. void KateDocument::unloadAllPlugins ()
  222. {
  223. for (uint i=0; i<m_plugins.count(); i++)
  224. unloadPlugin (i);
  225. }
  226. void KateDocument::enableAllPluginsGUI (KateView *view)
  227. {
  228. for (uint i=0; i<m_plugins.count(); i++)
  229. enablePluginGUI (m_plugins[i], view);
  230. }
  231. void KateDocument::disableAllPluginsGUI (KateView *view)
  232. {
  233. for (uint i=0; i<m_plugins.count(); i++)
  234. disablePluginGUI (m_plugins[i], view);
  235. }
  236. void KateDocument::loadPlugin (uint pluginIndex)
  237. {
  238. if (m_plugins[pluginIndex]) return;
  239. m_plugins[pluginIndex] = KTextEditor::createPlugin (TQFile::encodeName((KateFactory::self()->plugins())[pluginIndex]->library()), this);
  240. enablePluginGUI (m_plugins[pluginIndex]);
  241. }
  242. void KateDocument::unloadPlugin (uint pluginIndex)
  243. {
  244. if (!m_plugins[pluginIndex]) return;
  245. disablePluginGUI (m_plugins[pluginIndex]);
  246. delete m_plugins[pluginIndex];
  247. m_plugins[pluginIndex] = 0L;
  248. }
  249. void KateDocument::enablePluginGUI (KTextEditor::Plugin *plugin, KateView *view)
  250. {
  251. if (!plugin) return;
  252. if (!KTextEditor::pluginViewInterface(plugin)) return;
  253. KXMLGUIFactory *factory = view->factory();
  254. if ( factory )
  255. factory->removeClient( view );
  256. KTextEditor::pluginViewInterface(plugin)->addView(view);
  257. if ( factory )
  258. factory->addClient( view );
  259. }
  260. void KateDocument::enablePluginGUI (KTextEditor::Plugin *plugin)
  261. {
  262. if (!plugin) return;
  263. if (!KTextEditor::pluginViewInterface(plugin)) return;
  264. for (uint i=0; i< m_views.count(); i++)
  265. enablePluginGUI (plugin, m_views.at(i));
  266. }
  267. void KateDocument::disablePluginGUI (KTextEditor::Plugin *plugin, KateView *view)
  268. {
  269. if (!plugin) return;
  270. if (!KTextEditor::pluginViewInterface(plugin)) return;
  271. KXMLGUIFactory *factory = view->factory();
  272. if ( factory )
  273. factory->removeClient( view );
  274. KTextEditor::pluginViewInterface( plugin )->removeView( view );
  275. if ( factory )
  276. factory->addClient( view );
  277. }
  278. void KateDocument::disablePluginGUI (KTextEditor::Plugin *plugin)
  279. {
  280. if (!plugin) return;
  281. if (!KTextEditor::pluginViewInterface(plugin)) return;
  282. for (uint i=0; i< m_views.count(); i++)
  283. disablePluginGUI (plugin, m_views.at(i));
  284. }
  285. //END
  286. //BEGIN KTextEditor::Document stuff
  287. KTextEditor::View *KateDocument::createView( TQWidget *parent, const char *name )
  288. {
  289. KateView* newView = new KateView( this, parent, name);
  290. connect(newView, TQT_SIGNAL(cursorPositionChanged()), TQT_SLOT(undoCancel()));
  291. if ( s_fileChangedDialogsActivated )
  292. connect( newView, TQT_SIGNAL(gotFocus( Kate::View * )), this, TQT_SLOT(slotModifiedOnDisk()) );
  293. return newView;
  294. }
  295. TQPtrList<KTextEditor::View> KateDocument::views () const
  296. {
  297. return m_textEditViews;
  298. }
  299. void KateDocument::setActiveView( KateView *view )
  300. {
  301. if ( m_activeView == view ) return;
  302. m_activeView = view;
  303. }
  304. //END
  305. //BEGIN KTextEditor::ConfigInterfaceExtension stuff
  306. uint KateDocument::configPages () const
  307. {
  308. return 10;
  309. }
  310. KTextEditor::ConfigPage *KateDocument::configPage (uint number, TQWidget *parent, const char * )
  311. {
  312. switch( number )
  313. {
  314. case 0:
  315. return new KateViewDefaultsConfig (parent);
  316. case 1:
  317. return new KateSchemaConfigPage (parent, this);
  318. case 2:
  319. return new KateSelectConfigTab (parent);
  320. case 3:
  321. return new KateEditConfigTab (parent);
  322. case 4:
  323. return new KateIndentConfigTab (parent);
  324. case 5:
  325. return new KateSaveConfigTab (parent);
  326. case 6:
  327. return new KateHlConfigPage (parent, this);
  328. case 7:
  329. return new KateFileTypeConfigTab (parent);
  330. case 8:
  331. return new KateEditKeyConfiguration (parent, this);
  332. case 9:
  333. return new KatePartPluginConfigPage (parent);
  334. default:
  335. return 0;
  336. }
  337. return 0;
  338. }
  339. TQString KateDocument::configPageName (uint number) const
  340. {
  341. switch( number )
  342. {
  343. case 0:
  344. return i18n ("Appearance");
  345. case 1:
  346. return i18n ("Fonts & Colors");
  347. case 2:
  348. return i18n ("Cursor & Selection");
  349. case 3:
  350. return i18n ("Editing");
  351. case 4:
  352. return i18n ("Indentation");
  353. case 5:
  354. return i18n("Open/Save");
  355. case 6:
  356. return i18n ("Highlighting");
  357. case 7:
  358. return i18n("Filetypes");
  359. case 8:
  360. return i18n ("Shortcuts");
  361. case 9:
  362. return i18n ("Plugins");
  363. default:
  364. return TQString ("");
  365. }
  366. return TQString ("");
  367. }
  368. TQString KateDocument::configPageFullName (uint number) const
  369. {
  370. switch( number )
  371. {
  372. case 0:
  373. return i18n("Appearance");
  374. case 1:
  375. return i18n ("Font & Color Schemas");
  376. case 2:
  377. return i18n ("Cursor & Selection Behavior");
  378. case 3:
  379. return i18n ("Editing Options");
  380. case 4:
  381. return i18n ("Indentation Rules");
  382. case 5:
  383. return i18n("File Opening & Saving");
  384. case 6:
  385. return i18n ("Highlighting Rules");
  386. case 7:
  387. return i18n("Filetype Specific Settings");
  388. case 8:
  389. return i18n ("Shortcuts Configuration");
  390. case 9:
  391. return i18n ("Plugin Manager");
  392. default:
  393. return TQString ("");
  394. }
  395. return TQString ("");
  396. }
  397. TQPixmap KateDocument::configPagePixmap (uint number, int size) const
  398. {
  399. switch( number )
  400. {
  401. case 0:
  402. return BarIcon("view_text",size);
  403. case 1:
  404. return BarIcon("colorize", size);
  405. case 2:
  406. return BarIcon("frame_edit", size);
  407. case 3:
  408. return BarIcon("edit", size);
  409. case 4:
  410. return BarIcon("rightjust", size);
  411. case 5:
  412. return BarIcon("filesave", size);
  413. case 6:
  414. return BarIcon("source", size);
  415. case 7:
  416. return BarIcon("edit", size);
  417. case 8:
  418. return BarIcon("key_enter", size);
  419. case 9:
  420. return BarIcon("connect_established", size);
  421. default:
  422. return BarIcon("edit", size);
  423. }
  424. return BarIcon("edit", size);
  425. }
  426. //END
  427. //BEGIN KTextEditor::EditInterface stuff
  428. TQString KateDocument::text() const
  429. {
  430. TQString s;
  431. for (uint i = 0; i < m_buffer->count(); i++)
  432. {
  433. KateTextLine::Ptr textLine = m_buffer->plainLine(i);
  434. if (textLine)
  435. {
  436. s.append (textLine->string());
  437. if ((i+1) < m_buffer->count())
  438. s.append('\n');
  439. }
  440. }
  441. return s;
  442. }
  443. TQString KateDocument::text ( uint startLine, uint startCol, uint endLine, uint endCol ) const
  444. {
  445. return text(startLine, startCol, endLine, endCol, false);
  446. }
  447. TQString KateDocument::text ( uint startLine, uint startCol, uint endLine, uint endCol, bool blockwise) const
  448. {
  449. if ( blockwise && (startCol > endCol) )
  450. return TQString ();
  451. TQString s;
  452. if (startLine == endLine)
  453. {
  454. if (startCol > endCol)
  455. return TQString ();
  456. KateTextLine::Ptr textLine = m_buffer->plainLine(startLine);
  457. if ( !textLine )
  458. return TQString ();
  459. return textLine->string(startCol, endCol-startCol);
  460. }
  461. else
  462. {
  463. for (uint i = startLine; (i <= endLine) && (i < m_buffer->count()); i++)
  464. {
  465. KateTextLine::Ptr textLine = m_buffer->plainLine(i);
  466. if ( !blockwise )
  467. {
  468. if (i == startLine)
  469. s.append (textLine->string(startCol, textLine->length()-startCol));
  470. else if (i == endLine)
  471. s.append (textLine->string(0, endCol));
  472. else
  473. s.append (textLine->string());
  474. }
  475. else
  476. {
  477. s.append( textLine->string( startCol, endCol-startCol));
  478. }
  479. if ( i < endLine )
  480. s.append('\n');
  481. }
  482. }
  483. return s;
  484. }
  485. TQString KateDocument::textLine( uint line ) const
  486. {
  487. KateTextLine::Ptr l = m_buffer->plainLine(line);
  488. if (!l)
  489. return TQString();
  490. return l->string();
  491. }
  492. bool KateDocument::setText(const TQString &s)
  493. {
  494. if (!isReadWrite())
  495. return false;
  496. TQPtrList<KTextEditor::Mark> m = marks ();
  497. TQValueList<KTextEditor::Mark> msave;
  498. for (uint i=0; i < m.count(); i++)
  499. msave.append (*m.at(i));
  500. editStart ();
  501. // delete the text
  502. clear();
  503. // insert the new text
  504. insertText (0, 0, s);
  505. editEnd ();
  506. for (uint i=0; i < msave.count(); i++)
  507. setMark (msave[i].line, msave[i].type);
  508. return true;
  509. }
  510. bool KateDocument::clear()
  511. {
  512. if (!isReadWrite())
  513. return false;
  514. for (KateView * view = m_views.first(); view != 0L; view = m_views.next() ) {
  515. view->clear();
  516. view->tagAll();
  517. view->update();
  518. }
  519. clearMarks ();
  520. return removeText (0,0,lastLine()+1, 0);
  521. }
  522. bool KateDocument::insertText( uint line, uint col, const TQString &s)
  523. {
  524. return insertText (line, col, s, false);
  525. }
  526. bool KateDocument::insertText( uint line, uint col, const TQString &s, bool blockwise )
  527. {
  528. if (!isReadWrite())
  529. return false;
  530. if (s.isEmpty())
  531. return true;
  532. if (line == numLines())
  533. editInsertLine(line,"");
  534. else if (line > lastLine())
  535. return false;
  536. editStart ();
  537. uint insertPos = col;
  538. uint len = s.length();
  539. TQString buf;
  540. bool replacetabs = ( config()->configFlags() & KateDocumentConfig::cfReplaceTabsDyn && ! m_isInUndo );
  541. uint tw = config()->tabWidth();
  542. uint insertPosExpanded = insertPos;
  543. KateTextLine::Ptr l = m_buffer->line( line );
  544. if (l != 0)
  545. insertPosExpanded = l->cursorX( insertPos, tw );
  546. for (uint pos = 0; pos < len; pos++)
  547. {
  548. TQChar ch = s[pos];
  549. if (ch == '\n')
  550. {
  551. editInsertText (line, insertPos, buf);
  552. if ( !blockwise )
  553. {
  554. editWrapLine (line, insertPos + buf.length());
  555. insertPos = insertPosExpanded = 0;
  556. }
  557. else
  558. {
  559. if ( line == lastLine() )
  560. editWrapLine (line, insertPos + buf.length());
  561. }
  562. line++;
  563. buf.truncate(0);
  564. l = m_buffer->line( line );
  565. if (l)
  566. insertPosExpanded = l->cursorX( insertPos, tw );
  567. }
  568. else
  569. {
  570. if ( replacetabs && ch == '\t' )
  571. {
  572. uint tr = tw - ( insertPosExpanded+buf.length() )%tw;
  573. for ( uint i=0; i < tr; i++ )
  574. buf += ' ';
  575. }
  576. else
  577. buf += ch; // append char to buffer
  578. }
  579. }
  580. editInsertText (line, insertPos, buf);
  581. editEnd ();
  582. emit textInserted(line,insertPos);
  583. return true;
  584. }
  585. bool KateDocument::removeText ( uint startLine, uint startCol, uint endLine, uint endCol )
  586. {
  587. return removeText (startLine, startCol, endLine, endCol, false);
  588. }
  589. bool KateDocument::removeText ( uint startLine, uint startCol, uint endLine, uint endCol, bool blockwise)
  590. {
  591. if (!isReadWrite())
  592. return false;
  593. if ( blockwise && (startCol > endCol) )
  594. return false;
  595. if ( startLine > endLine )
  596. return false;
  597. if ( startLine > lastLine() )
  598. return false;
  599. if (!blockwise) {
  600. emit aboutToRemoveText(KateTextRange(startLine,startCol,endLine,endCol));
  601. }
  602. editStart ();
  603. if ( !blockwise )
  604. {
  605. if ( endLine > lastLine() )
  606. {
  607. endLine = lastLine()+1;
  608. endCol = 0;
  609. }
  610. if (startLine == endLine)
  611. {
  612. editRemoveText (startLine, startCol, endCol-startCol);
  613. }
  614. else if ((startLine+1) == endLine)
  615. {
  616. if ( (m_buffer->plainLine(startLine)->length()-startCol) > 0 )
  617. editRemoveText (startLine, startCol, m_buffer->plainLine(startLine)->length()-startCol);
  618. editRemoveText (startLine+1, 0, endCol);
  619. editUnWrapLine (startLine);
  620. }
  621. else
  622. {
  623. for (uint line = endLine; line >= startLine; line--)
  624. {
  625. if ((line > startLine) && (line < endLine))
  626. {
  627. editRemoveLine (line);
  628. }
  629. else
  630. {
  631. if (line == endLine)
  632. {
  633. if ( endLine <= lastLine() )
  634. editRemoveText (line, 0, endCol);
  635. }
  636. else
  637. {
  638. if ( (m_buffer->plainLine(line)->length()-startCol) > 0 )
  639. editRemoveText (line, startCol, m_buffer->plainLine(line)->length()-startCol);
  640. editUnWrapLine (startLine);
  641. }
  642. }
  643. if ( line == 0 )
  644. break;
  645. }
  646. }
  647. } // if ( ! blockwise )
  648. else
  649. {
  650. if ( endLine > lastLine() )
  651. endLine = lastLine ();
  652. for (uint line = endLine; line >= startLine; line--)
  653. {
  654. editRemoveText (line, startCol, endCol-startCol);
  655. if ( line == 0 )
  656. break;
  657. }
  658. }
  659. editEnd ();
  660. emit textRemoved();
  661. return true;
  662. }
  663. bool KateDocument::insertLine( uint l, const TQString &str )
  664. {
  665. if (!isReadWrite())
  666. return false;
  667. if (l > numLines())
  668. return false;
  669. return editInsertLine (l, str);
  670. }
  671. bool KateDocument::removeLine( uint line )
  672. {
  673. if (!isReadWrite())
  674. return false;
  675. if (line > lastLine())
  676. return false;
  677. return editRemoveLine (line);
  678. }
  679. uint KateDocument::length() const
  680. {
  681. uint l = 0;
  682. for (uint i = 0; i < m_buffer->count(); i++)
  683. {
  684. KateTextLine::Ptr line = m_buffer->plainLine(i);
  685. if (line)
  686. l += line->length();
  687. }
  688. return l;
  689. }
  690. uint KateDocument::numLines() const
  691. {
  692. return m_buffer->count();
  693. }
  694. uint KateDocument::numVisLines() const
  695. {
  696. return m_buffer->countVisible ();
  697. }
  698. int KateDocument::lineLength ( uint line ) const
  699. {
  700. KateTextLine::Ptr l = m_buffer->plainLine(line);
  701. if (!l)
  702. return -1;
  703. return l->length();
  704. }
  705. //END
  706. //BEGIN KTextEditor::EditInterface internal stuff
  707. //
  708. // Starts an edit session with (or without) undo, update of view disabled during session
  709. //
  710. void KateDocument::editStart (bool withUndo)
  711. {
  712. editSessionNumber++;
  713. if (editSessionNumber > 1)
  714. return;
  715. editIsRunning = true;
  716. editWithUndo = withUndo;
  717. if (editWithUndo)
  718. undoStart();
  719. else
  720. undoCancel();
  721. for (uint z = 0; z < m_views.count(); z++)
  722. {
  723. m_views.at(z)->editStart ();
  724. }
  725. m_buffer->editStart ();
  726. }
  727. void KateDocument::undoStart()
  728. {
  729. if (m_editCurrentUndo || (m_activeView && m_activeView->imComposeEvent())) return;
  730. // Make sure the buffer doesn't get bigger than requested
  731. if ((config()->undoSteps() > 0) && (undoItems.count() > config()->undoSteps()))
  732. {
  733. undoItems.setAutoDelete(true);
  734. undoItems.removeFirst();
  735. undoItems.setAutoDelete(false);
  736. docWasSavedWhenUndoWasEmpty = false;
  737. }
  738. // new current undo item
  739. m_editCurrentUndo = new KateUndoGroup(this);
  740. }
  741. void KateDocument::undoEnd()
  742. {
  743. if (m_activeView && m_activeView->imComposeEvent())
  744. return;
  745. if (m_editCurrentUndo)
  746. {
  747. bool<