• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kate
 

kate

  • kate
  • part
katedocument.cpp
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 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License version 2 as published by the Free Software Foundation.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02111-13020, USA.
19 */
20 
21 //BEGIN includes
22 #include "katedocument.h"
23 #include "katedocument.moc"
24 #include "katekeyinterceptorfunctor.h"
25 #include "katefactory.h"
26 #include "katedialogs.h"
27 #include "katehighlight.h"
28 #include "kateview.h"
29 #include "katesearch.h"
30 #include "kateautoindent.h"
31 #include "katetextline.h"
32 #include "katedocumenthelpers.h"
33 #include "kateprinter.h"
34 #include "katelinerange.h"
35 #include "katesupercursor.h"
36 #include "katearbitraryhighlight.h"
37 #include "katerenderer.h"
38 #include "kateattribute.h"
39 #include "kateconfig.h"
40 #include "katefiletype.h"
41 #include "kateschema.h"
42 #include "katetemplatehandler.h"
43 #include <tdetexteditor/plugin.h>
44 
45 #include <tdeio/job.h>
46 #include <tdeio/netaccess.h>
47 #include <tdeio/tdefileitem.h>
48 
49 
50 #include <tdeparts/event.h>
51 
52 #include <tdelocale.h>
53 #include <tdeglobal.h>
54 #include <tdeapplication.h>
55 #include <tdepopupmenu.h>
56 #include <tdeconfig.h>
57 #include <tdefiledialog.h>
58 #include <tdemessagebox.h>
59 #include <kstdaction.h>
60 #include <kiconloader.h>
61 #include <kxmlguifactory.h>
62 #include <kdialogbase.h>
63 #include <kdebug.h>
64 #include <tdeglobalsettings.h>
65 #include <klibloader.h>
66 #include <kdirwatch.h>
67 #include <twin.h>
68 #include <kencodingfiledialog.h>
69 #include <tdetempfile.h>
70 #include <kmdcodec.h>
71 #include <kstandarddirs.h>
72 
73 #include <tqtimer.h>
74 #include <tqfile.h>
75 #include <tqclipboard.h>
76 #include <tqtextstream.h>
77 #include <tqtextcodec.h>
78 #include <tqmap.h>
79 //END includes
80 
81 //BEGIN PRIVATE CLASSES
82 class KatePartPluginItem
83 {
84  public:
85  KTextEditor::Plugin *plugin;
86 };
87 //END PRIVATE CLASSES
88 
89 //BEGIN d'tor, c'tor
90 //
91 // KateDocument Constructor
92 //
93 KateDocument::KateDocument ( bool bSingleViewMode, bool bBrowserView,
94  bool bReadOnly, TQWidget *parentWidget,
95  const char *widgetName, TQObject *parent, const char *name)
96 : Kate::Document(parent, name),
97  m_plugins (KateFactory::self()->plugins().count()),
98  m_undoDontMerge(false),
99  m_undoIgnoreCancel(false),
100  lastUndoGroupWhenSaved( 0 ),
101  lastRedoGroupWhenSaved( 0 ),
102  docWasSavedWhenUndoWasEmpty( true ),
103  docWasSavedWhenRedoWasEmpty( true ),
104  m_modOnHd (false),
105  m_modOnHdReason (0),
106  m_job (0),
107  m_tempFile (0),
108  m_tabInterceptor(0)
109 {
110  m_undoComplexMerge=false;
111  m_isInUndo = false;
112  // my dcop object
113  setObjId ("KateDocument#"+documentDCOPSuffix());
114 
115  // tdetexteditor interfaces
116  setBlockSelectionInterfaceDCOPSuffix (documentDCOPSuffix());
117  setConfigInterfaceDCOPSuffix (documentDCOPSuffix());
118  setConfigInterfaceExtensionDCOPSuffix (documentDCOPSuffix());
119  setCursorInterfaceDCOPSuffix (documentDCOPSuffix());
120  setEditInterfaceDCOPSuffix (documentDCOPSuffix());
121  setEncodingInterfaceDCOPSuffix (documentDCOPSuffix());
122  setHighlightingInterfaceDCOPSuffix (documentDCOPSuffix());
123  setMarkInterfaceDCOPSuffix (documentDCOPSuffix());
124  setMarkInterfaceExtensionDCOPSuffix (documentDCOPSuffix());
125  setPrintInterfaceDCOPSuffix (documentDCOPSuffix());
126  setSearchInterfaceDCOPSuffix (documentDCOPSuffix());
127  setSelectionInterfaceDCOPSuffix (documentDCOPSuffix());
128  setSelectionInterfaceExtDCOPSuffix (documentDCOPSuffix());
129  setSessionConfigInterfaceDCOPSuffix (documentDCOPSuffix());
130  setUndoInterfaceDCOPSuffix (documentDCOPSuffix());
131  setWordWrapInterfaceDCOPSuffix (documentDCOPSuffix());
132 
133  // init local plugin array
134  m_plugins.fill (0);
135 
136  // register doc at factory
137  KateFactory::self()->registerDocument (this);
138 
139  m_reloading = false;
140  m_loading = false;
141  m_encodingSticky = false;
142 
143  m_buffer = new KateBuffer (this);
144 
145  // init the config object, be careful not to use it
146  // until the initial readConfig() call is done
147  m_config = new KateDocumentConfig (this);
148 
149  // init some more vars !
150  m_activeView = 0L;
151 
152  hlSetByUser = false;
153  m_fileType = -1;
154  m_fileTypeSetByUser = false;
155  setInstance( KateFactory::self()->instance() );
156 
157  editSessionNumber = 0;
158  editIsRunning = false;
159  m_editCurrentUndo = 0L;
160  editWithUndo = false;
161 
162  m_docNameNumber = 0;
163 
164  m_bSingleViewMode = bSingleViewMode;
165  m_bBrowserView = bBrowserView;
166  m_bReadOnly = bReadOnly;
167 
168  m_marks.setAutoDelete( true );
169  m_markPixmaps.setAutoDelete( true );
170  m_markDescriptions.setAutoDelete( true );
171  setMarksUserChangable( markType01 );
172 
173  m_undoMergeTimer = new TQTimer(this);
174  connect(m_undoMergeTimer, TQ_SIGNAL(timeout()), TQ_SLOT(undoCancel()));
175 
176  clearMarks ();
177  clearUndo ();
178  clearRedo ();
179  setModified (false);
180  docWasSavedWhenUndoWasEmpty = true;
181 
182  // normal hl
183  m_buffer->setHighlight (0);
184 
185  m_extension = new KateBrowserExtension( this );
186  m_arbitraryHL = new KateArbitraryHighlight();
187  m_indenter = KateAutoIndent::createIndenter ( this, 0 );
188 
189  m_indenter->updateConfig ();
190 
191  // some nice signals from the buffer
192  connect(m_buffer, TQ_SIGNAL(tagLines(int,int)), this, TQ_SLOT(tagLines(int,int)));
193  connect(m_buffer, TQ_SIGNAL(codeFoldingUpdated()),this,TQ_SIGNAL(codeFoldingUpdated()));
194 
195  // if the user changes the highlight with the dialog, notify the doc
196  connect(KateHlManager::self(),TQ_SIGNAL(changed()),TQ_SLOT(internalHlChanged()));
197 
198  // signal for the arbitrary HL
199  connect(m_arbitraryHL, TQ_SIGNAL(tagLines(KateView*, KateSuperRange*)), TQ_SLOT(tagArbitraryLines(KateView*, KateSuperRange*)));
200 
201  // signals for mod on hd
202  connect( KateFactory::self()->dirWatch(), TQ_SIGNAL(dirty (const TQString &)),
203  this, TQ_SLOT(slotModOnHdDirty (const TQString &)) );
204 
205  connect( KateFactory::self()->dirWatch(), TQ_SIGNAL(created (const TQString &)),
206  this, TQ_SLOT(slotModOnHdCreated (const TQString &)) );
207 
208  connect( KateFactory::self()->dirWatch(), TQ_SIGNAL(deleted (const TQString &)),
209  this, TQ_SLOT(slotModOnHdDeleted (const TQString &)) );
210 
211  // update doc name
212  setDocName ("");
213 
214  // if single view mode, like in the konqui embedding, create a default view ;)
215  if ( m_bSingleViewMode )
216  {
217  KTextEditor::View *view = createView( parentWidget, widgetName );
218  insertChildClient( view );
219  view->show();
220  setWidget( view );
221  }
222 
223  connect(this,TQ_SIGNAL(sigQueryClose(bool *, bool*)),this,TQ_SLOT(slotQueryClose_save(bool *, bool*)));
224 
225  m_isasking = 0;
226 
227  // plugins
228  for (uint i=0; i<KateFactory::self()->plugins().count(); i++)
229  {
230  if (config()->plugin (i))
231  loadPlugin (i);
232  }
233 }
234 
235 //
236 // KateDocument Destructor
237 //
238 KateDocument::~KateDocument()
239 {
240  // remove file from dirwatch
241  deactivateDirWatch ();
242 
243  if (!singleViewMode())
244  {
245  // clean up remaining views
246  m_views.setAutoDelete( true );
247  m_views.clear();
248  }
249 
250  delete m_editCurrentUndo;
251 
252  delete m_arbitraryHL;
253 
254  // cleanup the undo items, very important, truee :/
255  undoItems.setAutoDelete(true);
256  undoItems.clear();
257 
258  // clean up plugins
259  unloadAllPlugins ();
260 
261  delete m_config;
262  delete m_indenter;
263  KateFactory::self()->deregisterDocument (this);
264 }
265 //END
266 
267 //BEGIN Plugins
268 void KateDocument::unloadAllPlugins ()
269 {
270  for (uint i=0; i<m_plugins.count(); i++)
271  unloadPlugin (i);
272 }
273 
274 void KateDocument::enableAllPluginsGUI (KateView *view)
275 {
276  for (uint i=0; i<m_plugins.count(); i++)
277  enablePluginGUI (m_plugins[i], view);
278 }
279 
280 void KateDocument::disableAllPluginsGUI (KateView *view)
281 {
282  for (uint i=0; i<m_plugins.count(); i++)
283  disablePluginGUI (m_plugins[i], view);
284 }
285 
286 void KateDocument::loadPlugin (uint pluginIndex)
287 {
288  if (m_plugins[pluginIndex]) return;
289 
290  m_plugins[pluginIndex] = KTextEditor::createPlugin (TQFile::encodeName((KateFactory::self()->plugins())[pluginIndex]->library()), this);
291 
292  enablePluginGUI (m_plugins[pluginIndex]);
293 }
294 
295 void KateDocument::unloadPlugin (uint pluginIndex)
296 {
297  if (!m_plugins[pluginIndex]) return;
298 
299  disablePluginGUI (m_plugins[pluginIndex]);
300 
301  delete m_plugins[pluginIndex];
302  m_plugins[pluginIndex] = 0L;
303 }
304 
305 void KateDocument::enablePluginGUI (KTextEditor::Plugin *plugin, KateView *view)
306 {
307  if (!plugin) return;
308  if (!KTextEditor::pluginViewInterface(plugin)) return;
309 
310  KXMLGUIFactory *factory = view->factory();
311  if ( factory )
312  factory->removeClient( view );
313 
314  KTextEditor::pluginViewInterface(plugin)->addView(view);
315 
316  if ( factory )
317  factory->addClient( view );
318 }
319 
320 void KateDocument::enablePluginGUI (KTextEditor::Plugin *plugin)
321 {
322  if (!plugin) return;
323  if (!KTextEditor::pluginViewInterface(plugin)) return;
324 
325  for (uint i=0; i< m_views.count(); i++)
326  enablePluginGUI (plugin, m_views.at(i));
327 }
328 
329 void KateDocument::disablePluginGUI (KTextEditor::Plugin *plugin, KateView *view)
330 {
331  if (!plugin) return;
332  if (!KTextEditor::pluginViewInterface(plugin)) return;
333 
334  KXMLGUIFactory *factory = view->factory();
335  if ( factory )
336  factory->removeClient( view );
337 
338  KTextEditor::pluginViewInterface( plugin )->removeView( view );
339 
340  if ( factory )
341  factory->addClient( view );
342 }
343 
344 void KateDocument::disablePluginGUI (KTextEditor::Plugin *plugin)
345 {
346  if (!plugin) return;
347  if (!KTextEditor::pluginViewInterface(plugin)) return;
348 
349  for (uint i=0; i< m_views.count(); i++)
350  disablePluginGUI (plugin, m_views.at(i));
351 }
352 //END
353 
354 //BEGIN KTextEditor::Document stuff
355 
356 KTextEditor::View *KateDocument::createView( TQWidget *parent, const char *name )
357 {
358  KateView* newView = new KateView( this, parent, name);
359  connect(newView, TQ_SIGNAL(cursorPositionChanged()), TQ_SLOT(undoCancel()));
360  if ( s_fileChangedDialogsActivated )
361  connect( newView, TQ_SIGNAL(gotFocus( Kate::View * )), this, TQ_SLOT(slotModifiedOnDisk()) );
362  return newView;
363 }
364 
365 TQPtrList<KTextEditor::View> KateDocument::views () const
366 {
367  return m_textEditViews;
368 }
369 
370 void KateDocument::setActiveView( KateView *view )
371 {
372  if ( m_activeView == view ) return;
373 
374  m_activeView = view;
375 }
376 //END
377 
378 //BEGIN KTextEditor::ConfigInterfaceExtension stuff
379 
380 uint KateDocument::configPages () const
381 {
382  return 10;
383 }
384 
385 KTextEditor::ConfigPage *KateDocument::configPage (uint number, TQWidget *parent, const char * )
386 {
387  switch( number )
388  {
389  case 0:
390  return new KateViewDefaultsConfig (parent);
391 
392  case 1:
393  return new KateSchemaConfigPage (parent, this);
394 
395  case 2:
396  return new KateSelectConfigTab (parent);
397 
398  case 3:
399  return new KateEditConfigTab (parent);
400 
401  case 4:
402  return new KateIndentConfigTab (parent);
403 
404  case 5:
405  return new KateSaveConfigTab (parent);
406 
407  case 6:
408  return new KateHlConfigPage (parent, this);
409 
410  case 7:
411  return new KateFileTypeConfigTab (parent);
412 
413  case 8:
414  return new KateEditKeyConfiguration (parent, this);
415 
416  case 9:
417  return new KatePartPluginConfigPage (parent);
418 
419  default:
420  return 0;
421  }
422 
423  return 0;
424 }
425 
426 TQString KateDocument::configPageName (uint number) const
427 {
428  switch( number )
429  {
430  case 0:
431  return i18n ("Appearance");
432 
433  case 1:
434  return i18n ("Fonts & Colors");
435 
436  case 2:
437  return i18n ("Cursor & Selection");
438 
439  case 3:
440  return i18n ("Editing");
441 
442  case 4:
443  return i18n ("Indentation");
444 
445  case 5:
446  return i18n("Open/Save");
447 
448  case 6:
449  return i18n ("Highlighting");
450 
451  case 7:
452  return i18n("Filetypes");
453 
454  case 8:
455  return i18n ("Shortcuts");
456 
457  case 9:
458  return i18n ("Plugins");
459 
460  default:
461  return TQString ("");
462  }
463 
464  return TQString ("");
465 }
466 
467 TQString KateDocument::configPageFullName (uint number) const
468 {
469  switch( number )
470  {
471  case 0:
472  return i18n("Appearance");
473 
474  case 1:
475  return i18n ("Font & Color Schemas");
476 
477  case 2:
478  return i18n ("Cursor & Selection Behavior");
479 
480  case 3:
481  return i18n ("Editing Options");
482 
483  case 4:
484  return i18n ("Indentation Rules");
485 
486  case 5:
487  return i18n("File Opening & Saving");
488 
489  case 6:
490  return i18n ("Highlighting Rules");
491 
492  case 7:
493  return i18n("Filetype Specific Settings");
494 
495  case 8:
496  return i18n ("Shortcuts Configuration");
497 
498  case 9:
499  return i18n ("Plugin Manager");
500 
501  default:
502  return TQString ("");
503  }
504 
505  return TQString ("");
506 }
507 
508 TQPixmap KateDocument::configPagePixmap (uint number, int size) const
509 {
510  switch( number )
511  {
512  case 0:
513  return BarIcon("view_text",size);
514 
515  case 1:
516  return BarIcon("colorize", size);
517 
518  case 2:
519  return BarIcon("frame_edit", size);
520 
521  case 3:
522  return BarIcon("edit", size);
523 
524  case 4:
525  return BarIcon("format-justify-right", size);
526 
527  case 5:
528  return BarIcon("document-save", size);
529 
530  case 6:
531  return BarIcon("text-x-src", size);
532 
533  case 7:
534  return BarIcon("edit", size);
535 
536  case 8:
537  return BarIcon("key_enter", size);
538 
539  case 9:
540  return BarIcon("connect_established", size);
541 
542  default:
543  return BarIcon("edit", size);
544  }
545 
546  return BarIcon("edit", size);
547 }
548 //END
549 
550 //BEGIN KTextEditor::EditInterface stuff
551 
552 TQString KateDocument::text() const
553 {
554  TQString s;
555 
556  for (uint i = 0; i < m_buffer->count(); i++)
557  {
558  KateTextLine::Ptr textLine = m_buffer->plainLine(i);
559 
560  if (textLine)
561  {
562  s.append (textLine->string());
563 
564  if ((i+1) < m_buffer->count())
565  s.append('\n');
566  }
567  }
568 
569  return s;
570 }
571 
572 TQString KateDocument::text ( uint startLine, uint startCol, uint endLine, uint endCol ) const
573 {
574  return text(startLine, startCol, endLine, endCol, false);
575 }
576 
577 TQString KateDocument::text ( uint startLine, uint startCol, uint endLine, uint endCol, bool blockwise) const
578 {
579  if ( blockwise && (startCol > endCol) )
580  return TQString ();
581 
582  TQString s;
583 
584  if (startLine == endLine)
585  {
586  if (startCol > endCol)
587  return TQString ();
588 
589  KateTextLine::Ptr textLine = m_buffer->plainLine(startLine);
590 
591  if ( !textLine )
592  return TQString ();
593 
594  return textLine->string(startCol, endCol-startCol);
595  }
596  else
597  {
598 
599  for (uint i = startLine; (i <= endLine) && (i < m_buffer->count()); i++)
600  {
601  KateTextLine::Ptr textLine = m_buffer->plainLine(i);
602 
603  if ( !blockwise )
604  {
605  if (i == startLine)
606  s.append (textLine->string(startCol, textLine->length()-startCol));
607  else if (i == endLine)
608  s.append (textLine->string(0, endCol));
609  else
610  s.append (textLine->string());
611  }
612  else
613  {
614  s.append( textLine->string( startCol, endCol-startCol));
615  }
616 
617  if ( i < endLine )
618  s.append('\n');
619  }
620  }
621 
622  return s;
623 }
624 
625 TQString KateDocument::textLine( uint line ) const
626 {
627  KateTextLine::Ptr l = m_buffer->plainLine(line);
628 
629  if (!l)
630  return TQString();
631 
632  return l->string();
633 }
634 
635 bool KateDocument::setText(const TQString &s)
636 {
637  if (!isReadWrite())
638  return false;
639 
640  TQPtrList<KTextEditor::Mark> m = marks ();
641  TQValueList<KTextEditor::Mark> msave;
642 
643  for (uint i=0; i < m.count(); i++)
644  msave.append (*m.at(i));
645 
646  editStart ();
647 
648  // delete the text
649  clear();
650 
651  // insert the new text
652  insertText (0, 0, s);
653 
654  editEnd ();
655 
656  for (uint i=0; i < msave.count(); i++)
657  setMark (msave[i].line, msave[i].type);
658 
659  return true;
660 }
661 
662 bool KateDocument::clear()
663 {
664  if (!isReadWrite())
665  return false;
666 
667  for (KateView * view = m_views.first(); view != 0L; view = m_views.next() ) {
668  view->clear();
669  view->tagAll();
670  view->update();
671  }
672 
673  clearMarks ();
674 
675  return removeText (0,0,lastLine()+1, 0);
676 }
677 
678 bool KateDocument::insertText( uint line, uint col, const TQString &s)
679 {
680  return insertText (line, col, s, false);
681 }
682 
683 bool KateDocument::insertText( uint line, uint col, const TQString &s, bool blockwise )
684 {
685  if (!isReadWrite())
686  return false;
687 
688  if (s.isEmpty())
689  return true;
690 
691  if (line == numLines())
692  editInsertLine(line,"");
693  else if (line > lastLine())
694  return false;
695 
696  editStart ();
697 
698  uint insertPos = col;
699  uint len = s.length();
700 
701  TQString buf;
702 
703  bool replacetabs = ( config()->configFlags() & KateDocumentConfig::cfReplaceTabsDyn && ! m_isInUndo );
704  uint tw = config()->tabWidth();
705  uint insertPosExpanded = insertPos;
706  KateTextLine::Ptr l = m_buffer->line( line );
707  if (l != 0)
708  insertPosExpanded = l->cursorX( insertPos, tw );
709 
710  for (uint pos = 0; pos < len; pos++)
711  {
712  TQChar ch = s[pos];
713 
714  if (ch == '\n')
715  {
716  editInsertText (line, insertPos, buf);
717 
718  if ( !blockwise )
719  {
720  editWrapLine (line, insertPos + buf.length());
721  insertPos = insertPosExpanded = 0;
722  }
723  else
724  {
725  if ( line == lastLine() )
726  editWrapLine (line, insertPos + buf.length());
727  }
728 
729  line++;
730  buf.truncate(0);
731  l = m_buffer->line( line );
732  if (l)
733  insertPosExpanded = l->cursorX( insertPos, tw );
734  }
735  else
736  {
737  if ( replacetabs && ch == '\t' )
738  {
739  uint tr = tw - ( insertPosExpanded+buf.length() )%tw;
740  for ( uint i=0; i < tr; i++ )
741  buf += ' ';
742  }
743  else
744  buf += ch; // append char to buffer
745  }
746  }
747 
748  editInsertText (line, insertPos, buf);
749 
750  editEnd ();
751  emit textInserted(line,insertPos);
752  return true;
753 }
754 
755 bool KateDocument::removeText ( uint startLine, uint startCol, uint endLine, uint endCol )
756 {
757  return removeText (startLine, startCol, endLine, endCol, false);
758 }
759 
760 bool KateDocument::removeText ( uint startLine, uint startCol, uint endLine, uint endCol, bool blockwise)
761 {
762  if (!isReadWrite())
763  return false;
764 
765  if ( blockwise && (startCol > endCol) )
766  return false;
767 
768  if ( startLine > endLine )
769  return false;
770 
771  if ( startLine > lastLine() )
772  return false;
773 
774  if (!blockwise) {
775  emit aboutToRemoveText(KateTextRange(startLine,startCol,endLine,endCol));
776  }
777  editStart ();
778 
779  if ( !blockwise )
780  {
781  if ( endLine > lastLine() )
782  {
783  endLine = lastLine()+1;
784  endCol = 0;
785  }
786 
787  if (startLine == endLine)
788  {
789  editRemoveText (startLine, startCol, endCol-startCol);
790  }
791  else if ((startLine+1) == endLine)
792  {
793  if ( (m_buffer->plainLine(startLine)->length()-startCol) > 0 )
794  editRemoveText (startLine, startCol, m_buffer->plainLine(startLine)->length()-startCol);
795 
796  editRemoveText (startLine+1, 0, endCol);
797  editUnWrapLine (startLine);
798  }
799  else
800  {
801  for (uint line = endLine; line >= startLine; line--)
802  {
803  if ((line > startLine) && (line < endLine))
804  {
805  editRemoveLine (line);
806  }
807  else
808  {
809  if (line == endLine)
810  {
811  if ( endLine <= lastLine() )
812  editRemoveText (line, 0, endCol);
813  }
814  else
815  {
816  if ( (m_buffer->plainLine(line)->length()-startCol) > 0 )
817  editRemoveText (line, startCol, m_buffer->plainLine(line)->length()-startCol);
818 
819  editUnWrapLine (startLine);
820  }
821  }
822 
823  if ( line == 0 )
824  break;
825  }
826  }
827  } // if ( ! blockwise )
828  else
829  {
830  if ( endLine > lastLine() )
831  endLine = lastLine ();
832 
833  for (uint line = endLine; line >= startLine; line--)
834  {
835 
836  editRemoveText (line, startCol, endCol-startCol);
837 
838  if ( line == 0 )
839  break;
840  }
841  }
842 
843  editEnd ();
844  emit textRemoved();
845  return true;
846 }
847 
848 bool KateDocument::insertLine( uint l, const TQString &str )
849 {
850  if (!isReadWrite())
851  return false;
852 
853  if (l > numLines())
854  return false;
855 
856  return editInsertLine (l, str);
857 }
858 
859 bool KateDocument::removeLine( uint line )
860 {
861  if (!isReadWrite())
862  return false;
863 
864  if (line > lastLine())
865  return false;
866 
867  return editRemoveLine (line);
868 }
869 
870 uint KateDocument::length() const
871 {
872  uint l = 0;
873 
874  for (uint i = 0; i < m_buffer->count(); i++)
875  {
876  KateTextLine::Ptr line = m_buffer->plainLine(i);
877 
878  if (line)
879  l += line->length();
880  }
881 
882  return l;
883 }
884 
885 uint KateDocument::numLines() const
886 {
887  return m_buffer->count();
888 }
889 
890 uint KateDocument::numVisLines() const
891 {
892  return m_buffer->countVisible ();
893 }
894 
895 int KateDocument::lineLength ( uint line ) const
896 {
897  KateTextLine::Ptr l = m_buffer->plainLine(line);
898 
899  if (!l)
900  return -1;
901 
902  return l->length();
903 }
904 //END
905 
906 //BEGIN KTextEditor::EditInterface internal stuff
907 //
908 // Starts an edit session with (or without) undo, update of view disabled during session
909 //
910 void KateDocument::editStart (bool withUndo)
911 {
912  editSessionNumber++;
913 
914  if (editSessionNumber > 1)
915  return;
916 
917  editIsRunning = true;
918  editWithUndo = withUndo;
919 
920  if (editWithUndo)
921  undoStart();
922  else
923  undoCancel();
924 
925  for (uint z = 0; z < m_views.count(); z++)
926  {
927  m_views.at(z)->editStart ();
928  }
929 
930  m_buffer->editStart ();
931 }
932 
933 void KateDocument::undoStart()
934 {
935  if (m_editCurrentUndo || (m_activeView && m_activeView->imComposeEvent())) return;
936 
937  // Make sure the buffer doesn't get bigger than requested
938  if ((config()->undoSteps() > 0) && (undoItems.count() > config()->undoSteps()))
939  {
940  undoItems.setAutoDelete(true);
941  undoItems.removeFirst();
942  undoItems.setAutoDelete(false);
943  docWasSavedWhenUndoWasEmpty = false;
944  }
945 
946  // new current undo item
947  m_editCurrentUndo = new KateUndoGroup(this);
948 }
949 
950 void KateDocument::undoEnd()
951 {
952  if (m_activeView && m_activeView->imComposeEvent())
953  return;
954 
955  if (m_editCurrentUndo)
956  {
957  bool changedUndo = false;
958 
959  if (m_editCurrentUndo->isEmpty())
960  delete m_editCurrentUndo;
961  else if (!m_undoDontMerge && undoItems.last() && undoItems.last()->merge(m_editCurrentUndo,m_undoComplexMerge))
962  delete m_editCurrentUndo;
963  else
964  {
965  undoItems.append(m_editCurrentUndo);
966  changedUndo = true;
967  }
968 
969  m_undoDontMerge = false;
970  m_undoIgnoreCancel = true;
971 
972  m_editCurrentUndo = 0L;
973 
974  // (Re)Start the single-shot timer to cancel the undo merge
975  // the user has 5 seconds to input more data, or undo merging gets canceled for the current undo item.
976  m_undoMergeTimer->start(5000, true);
977 
978  if (changedUndo)
979  emit undoChanged();
980  }
981 }
982 
983 void KateDocument::undoCancel()
984 {
985  if (m_undoIgnoreCancel) {
986  m_undoIgnoreCancel = false;
987  return;
988  }
989 
990  m_undoDontMerge = true;
991 
992  Q_ASSERT(!m_editCurrentUndo);
993 
994  // As you can see by the above assert, neither of these should really be required
995  delete m_editCurrentUndo;
996  m_editCurrentUndo = 0L;
997 }
998 
999 void KateDocument::undoSafePoint() {
1000  Q_ASSERT(m_editCurrentUndo);
1001  if (!m_editCurrentUndo) return;
1002  m_editCurrentUndo->safePoint();
1003 }
1004 
1005 //
1006 // End edit session and update Views
1007 //
1008 void KateDocument::editEnd ()
1009 {
1010  if (editSessionNumber == 0)
1011  return;
1012 
1013  // wrap the new/changed text, if something really changed!
1014  if (m_buffer->editChanged() && (editSessionNumber == 1))
1015  if (editWithUndo && config()->wordWrap())
1016  wrapText (m_buffer->editTagStart(), m_buffer->editTagEnd());
1017 
1018  editSessionNumber--;
1019 
1020  if (editSessionNumber > 0)
1021  return;
1022 
1023  // end buffer edit, will trigger hl update
1024  // this will cause some possible adjustment of tagline start/end
1025  m_buffer->editEnd ();
1026 
1027  if (editWithUndo)
1028  undoEnd();
1029 
1030  // edit end for all views !!!!!!!!!
1031  for (uint z = 0; z < m_views.count(); z++)
1032  m_views.at(z)->editEnd (m_buffer->editTagStart(), m_buffer->editTagEnd(), m_buffer->editTagFrom());
1033 
1034  if (m_buffer->editChanged())
1035  {
1036  setModified(true);
1037  emit textChanged ();
1038  }
1039 
1040  editIsRunning = false;
1041 }
1042 
1043 bool KateDocument::wrapText (uint startLine, uint endLine)
1044 {
1045  uint col = config()->wordWrapAt();
1046 
1047  if (col == 0)
1048  return false;
1049 
1050  editStart ();
1051 
1052  for (uint line = startLine; (line <= endLine) && (line < numLines()); line++)
1053  {
1054  KateTextLine::Ptr l = m_buffer->line(line);
1055 
1056  if (!l)
1057  return false;
1058 
1059  kdDebug (13020) << "try wrap line: " << line << endl;
1060 
1061  if (l->lengthWithTabs(m_buffer->tabWidth()) > col)
1062  {
1063  KateTextLine::Ptr nextl = m_buffer->line(line+1);
1064 
1065  kdDebug (13020) << "do wrap line: " << line << endl;
1066 
1067  const TQChar *text = l->text();
1068  uint eolPosition = l->length()-1;
1069 
1070  // take tabs into account here, too
1071  uint x = 0;
1072  const TQString & t = l->string();
1073  uint z2 = 0;
1074  for ( ; z2 < l->length(); z2++)
1075  {
1076  if (t[z2] == TQChar('\t'))
1077  x += m_buffer->tabWidth() - (x % m_buffer->tabWidth());
1078  else
1079  x++;
1080 
1081  if (x > col)
1082  break;
1083  }
1084 
1085  uint searchStart = kMin (z2, l->length()-1);
1086 
1087  // If where we are wrapping is an end of line and is a space we don't
1088  // want to wrap there
1089  if (searchStart == eolPosition && text[searchStart].isSpace())
1090  searchStart--;
1091 
1092  // Scan backwards looking for a place to break the line
1093  // We are not interested in breaking at the first char
1094  // of the line (if it is a space), but we are at the second
1095  // anders: if we can't find a space, try breaking on a word
1096  // boundry, using KateHighlight::canBreakAt().
1097  // This could be a priority (setting) in the hl/filetype/document
1098  int z = 0;
1099  uint nw = 0; // alternative position, a non word character
1100  for (z=searchStart; z > 0; z--)
1101  {
1102  if (text[z].isSpace()) break;
1103  if ( ! nw && highlight()->canBreakAt( text[z] , l->attribute(z) ) )
1104  nw = z;
1105  }
1106 
1107  if (z > 0)
1108  {
1109  // cu space
1110  editRemoveText (line, z, 1);
1111  }
1112  else
1113  {
1114  // There was no space to break at so break at a nonword character if
1115  // found, or at the wrapcolumn ( that needs be configurable )
1116  // Don't try and add any white space for the break
1117  if ( nw && nw < col ) nw++; // break on the right side of the character
1118  z = nw ? nw : col;
1119  }
1120 
1121  if (nextl && !nextl->isAutoWrapped())
1122  {
1123  editWrapLine (line, z, true);
1124  editMarkLineAutoWrapped (line+1, true);
1125 
1126  endLine++;
1127  }
1128  else
1129  {
1130  if (nextl && (nextl->length() > 0) && !nextl->getChar(0).isSpace() && ((l->length() < 1) || !l->getChar(l->length()-1).isSpace()))
1131  editInsertText (line+1, 0, TQString (" "));
1132 
1133  bool newLineAdded = false;
1134  editWrapLine (line, z, false, &newLineAdded);
1135 
1136  editMarkLineAutoWrapped (line+1, true);
1137 
1138  endLine++;
1139  }
1140  }
1141  }
1142 
1143  editEnd ();
1144 
1145  return true;
1146 }
1147 
1148 void KateDocument::editAddUndo (KateUndoGroup::UndoType type, uint line, uint col, uint len, const TQString &text)
1149 {
1150  if (editIsRunning && editWithUndo && m_editCurrentUndo) {
1151  m_editCurrentUndo->addItem(type, line, col, len, text);
1152 
1153  // Clear redo buffer
1154  if (redoItems.count()) {
1155  redoItems.setAutoDelete(true);
1156  redoItems.clear();
1157  redoItems.setAutoDelete(false);
1158  }
1159  }
1160 }
1161 
1162 bool KateDocument::editInsertText ( uint line, uint col, const TQString &str )
1163 {
1164  if (!isReadWrite())
1165  return false;
1166 
1167  TQString s = str;
1168 
1169  KateTextLine::Ptr l = m_buffer->line(line);
1170 
1171  if (!l)
1172  return false;
1173 
1174  if ( config()->configFlags() & KateDocumentConfig::cfReplaceTabsDyn && ! m_isInUndo )
1175  {
1176  uint tw = config()->tabWidth();
1177  int pos = 0;
1178  uint l = 0;
1179  while ( (pos = s.find('\t')) > -1 )
1180  {
1181  l = tw - ( (col + pos)%tw );
1182  s.replace( pos, 1, TQString().fill( ' ', l ) );
1183  }
1184  }
1185 
1186  editStart ();
1187 
1188  editAddUndo (KateUndoGroup::editInsertText, line, col, s.length(), s);
1189 
1190  l->insertText (col, s.length(), s.unicode());
1191 // removeTrailingSpace(line); // ### nessecary?
1192 
1193  m_buffer->changeLine(line);
1194 
1195  for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
1196  it.current()->editTextInserted (line, col, s.length());
1197 
1198  editEnd ();
1199 
1200  return true;
1201 }
1202 
1203 bool KateDocument::editRemoveText ( uint line, uint col, uint len )
1204 {
1205  if (!isReadWrite())
1206  return false;
1207 
1208  KateTextLine::Ptr l = m_buffer->line(line);
1209 
1210  if (!l)
1211  return false;
1212 
1213  editStart ();
1214 
1215  editAddUndo (KateUndoGroup::editRemoveText, line, col, len, l->string().mid(col, len));
1216 
1217  l->removeText (col, len);
1218  removeTrailingSpace( line );
1219 
1220  m_buffer->changeLine(line);
1221 
1222  for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
1223  it.current()->editTextRemoved (line, col, len);
1224 
1225  editEnd ();
1226 
1227  return true;
1228 }
1229 
1230 bool KateDocument::editMarkLineAutoWrapped ( uint line, bool autowrapped )
1231 {
1232  if (!isReadWrite())
1233  return false;
1234 
1235  KateTextLine::Ptr l = m_buffer->line(line);
1236 
1237  if (!l)
1238  return false;
1239 
1240  editStart ();
1241 
1242  editAddUndo (KateUndoGroup::editMarkLineAutoWrapped, line, autowrapped ? 1 : 0, 0, TQString::null);
1243 
1244  l->setAutoWrapped (autowrapped);
1245 
1246  m_buffer->changeLine(line);
1247 
1248  editEnd ();
1249 
1250  return true;
1251 }
1252 
1253 bool KateDocument::editWrapLine ( uint line, uint col, bool newLine, bool *newLineAdded)
1254 {
1255  if (!isReadWrite())
1256  return false;
1257 
1258  KateTextLine::Ptr l = m_buffer->line(line);
1259 
1260  if (!l)
1261  return false;
1262 
1263  editStart ();
1264 
1265  KateTextLine::Ptr nextLine = m_buffer->line(line+1);
1266 
1267  int pos = l->length() - col;
1268 
1269  if (pos < 0)
1270  pos = 0;
1271 
1272  editAddUndo (KateUndoGroup::editWrapLine, line, col, pos, (!nextLine || newLine) ? "1" : "0");
1273 
1274  if (!nextLine || newLine)
1275  {
1276  KateTextLine::Ptr textLine = new KateTextLine();
1277 
1278  textLine->insertText (0, pos, l->text()+col, l->attributes()+col);
1279  l->truncate(col);
1280 
1281  m_buffer->insertLine (line+1, textLine);
1282  m_buffer->changeLine(line);
1283 
1284  TQPtrList<KTextEditor::Mark> list;
1285  for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
1286  {
1287  if( it.current()->line >= line )
1288  {
1289  if ((col == 0) || (it.current()->line > line))
1290  list.append( it.current() );
1291  }
1292  }
1293 
1294  for( TQPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
1295  {
1296  KTextEditor::Mark* mark = m_marks.take( it.current()->line );
1297  mark->line++;
1298  m_marks.insert( mark->line, mark );
1299  }
1300 
1301  if( !list.isEmpty() )
1302  emit marksChanged();
1303 
1304  // yes, we added a new line !
1305  if (newLineAdded)
1306  (*newLineAdded) = true;
1307  }
1308  else
1309  {
1310  nextLine->insertText (0, pos, l->text()+col, l->attributes()+col);
1311  l->truncate(col);
1312 
1313  m_buffer->changeLine(line);
1314  m_buffer->changeLine(line+1);
1315 
1316  // no, no new line added !
1317  if (newLineAdded)
1318  (*newLineAdded) = false;
1319  }
1320 
1321  for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
1322  it.current()->editLineWrapped (line, col, !nextLine || newLine);
1323 
1324  editEnd ();
1325 
1326  return true;
1327 }
1328 
1329 bool KateDocument::editUnWrapLine ( uint line, bool removeLine, uint length )
1330 {
1331  if (!isReadWrite())
1332  return false;
1333 
1334  KateTextLine::Ptr l = m_buffer->line(line);
1335  KateTextLine::Ptr nextLine = m_buffer->line(line+1);
1336 
1337  if (!l || !nextLine)
1338  return false;
1339 
1340  editStart ();
1341 
1342  uint col = l->length ();
1343 
1344  editAddUndo (KateUndoGroup::editUnWrapLine, line, col, length, removeLine ? "1" : "0");
1345 
1346  if (removeLine)
1347  {
1348  l->insertText (col, nextLine->length(), nextLine->text(), nextLine->attributes());
1349 
1350  m_buffer->changeLine(line);
1351  m_buffer->removeLine(line+1);
1352  }
1353  else
1354  {
1355  l->insertText (col, (nextLine->length() < length) ? nextLine->length() : length,
1356  nextLine->text(), nextLine->attributes());
1357  nextLine->removeText (0, (nextLine->length() < length) ? nextLine->length() : length);
1358 
1359  m_buffer->changeLine(line);
1360  m_buffer->changeLine(line+1);
1361  }
1362 
1363  TQPtrList<KTextEditor::Mark> list;
1364  for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
1365  {
1366  if( it.current()->line >= line+1 )
1367  list.append( it.current() );
1368 
1369  if ( it.current()->line == line+1 )
1370  {
1371  KTextEditor::Mark* mark = m_marks.take( line );
1372 
1373  if (mark)
1374  {
1375  it.current()->type |= mark->type;
1376  }
1377  }
1378  }
1379 
1380  for( TQPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
1381  {
1382  KTextEditor::Mark* mark = m_marks.take( it.current()->line );
1383  mark->line--;
1384  m_marks.insert( mark->line, mark );
1385  }
1386 
1387  if( !list.isEmpty() )
1388  emit marksChanged();
1389 
1390  for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
1391  it.current()->editLineUnWrapped (line, col, removeLine, length);
1392 
1393  editEnd ();
1394 
1395  return true;
1396 }
1397 
1398 bool KateDocument::editInsertLine ( uint line, const TQString &s )
1399 {
1400  if (!isReadWrite())
1401  return false;
1402 
1403  if ( line > numLines() )
1404  return false;
1405 
1406  editStart ();
1407 
1408  editAddUndo (KateUndoGroup::editInsertLine, line, 0, s.length(), s);
1409 
1410  removeTrailingSpace( line ); // old line
1411 
1412  KateTextLine::Ptr tl = new KateTextLine();
1413  tl->insertText (0, s.length(), s.unicode(), 0);
1414  m_buffer->insertLine(line, tl);
1415  m_buffer->changeLine(line);
1416 
1417  removeTrailingSpace( line ); // new line
1418 
1419  TQPtrList<KTextEditor::Mark> list;
1420  for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
1421  {
1422  if( it.current()->line >= line )
1423  list.append( it.current() );
1424  }
1425 
1426  for( TQPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
1427  {
1428  KTextEditor::Mark* mark = m_marks.take( it.current()->line );
1429  mark->line++;
1430  m_marks.insert( mark->line, mark );
1431  }
1432 
1433  if( !list.isEmpty() )
1434  emit marksChanged();
1435 
1436  for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
1437  it.current()->editLineInserted (line);
1438 
1439  editEnd ();
1440 
1441  return true;
1442 }
1443 
1444 bool KateDocument::editRemoveLine ( uint line )
1445 {
1446  if (!isReadWrite())
1447  return false;
1448 
1449  if ( line > lastLine() )
1450  return false;
1451 
1452  if ( numLines() == 1 )
1453  return editRemoveText (0, 0, m_buffer->line(0)->length());
1454 
1455  editStart ();
1456 
1457  editAddUndo (KateUndoGroup::editRemoveLine, line, 0, lineLength(line), textLine(line));
1458 
1459  m_buffer->removeLine(line);
1460 
1461  TQPtrList<KTextEditor::Mark> list;
1462  KTextEditor::Mark* rmark = 0;
1463  for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
1464  {
1465  if ( (it.current()->line > line) )
1466  list.append( it.current() );
1467  else if ( (it.current()->line == line) )
1468  rmark = it.current();
1469  }
1470 
1471  if (rmark)
1472  delete (m_marks.take (rmark->line));
1473 
1474  for( TQPtrListIterator<KTextEditor::Mark> it( list ); it.current(); ++it )
1475  {
1476  KTextEditor::Mark* mark = m_marks.take( it.current()->line );
1477  mark->line--;
1478  m_marks.insert( mark->line, mark );
1479  }
1480 
1481  if( !list.isEmpty() )
1482  emit marksChanged();
1483 
1484  for( TQPtrListIterator<KateSuperCursor> it (m_superCursors); it.current(); ++it )
1485  it.current()->editLineRemoved (line);
1486 
1487  editEnd();
1488 
1489  return true;
1490 }
1491 //END
1492 
1493 //BEGIN KTextEditor::UndoInterface stuff
1494 
1495 uint KateDocument::undoCount () const
1496 {
1497  return undoItems.count ();
1498 }
1499 
1500 uint KateDocument::redoCount () const
1501 {
1502  return redoItems.count ();
1503 }
1504 
1505 uint KateDocument::undoSteps () const
1506 {
1507  return m_config->undoSteps();
1508 }
1509 
1510 void KateDocument::setUndoSteps(uint steps)
1511 {
1512  m_config->setUndoSteps (steps);
1513 }
1514 
1515 void KateDocument::undo()
1516 {
1517  m_isInUndo = true;
1518  if ((undoItems.count() > 0) && undoItems.last())
1519  {
1520  clearSelection ();
1521 
1522  undoItems.last()->undo();
1523  redoItems.append (undoItems.last());
1524  undoItems.removeLast ();
1525  updateModified();
1526 
1527  emit undoChanged ();
1528  }
1529  m_isInUndo = false;
1530 }
1531 
1532 void KateDocument::redo()
1533 {
1534  m_isInUndo = true;
1535  if ((redoItems.count() > 0) && redoItems.last())
1536  {
1537  clearSelection ();
1538 
1539  redoItems.last()->redo();
1540  undoItems.append (redoItems.last());
1541  redoItems.removeLast ();
1542  updateModified();
1543 
1544  emit undoChanged ();
1545  }
1546  m_isInUndo = false;
1547 }
1548 
1549 void KateDocument::updateModified()
1550 {
1551  /*
1552  How this works:
1553 
1554  After noticing that there where to many scenarios to take into
1555  consideration when using 'if's to toggle the "Modified" flag
1556  I came up with this baby, flexible and repetitive calls are
1557  minimal.
1558 
1559  A numeric unique pattern is generated by toggleing a set of bits,
1560  each bit symbolizes a different state in the Undo Redo structure.
1561 
1562  undoItems.isEmpty() != null BIT 1
1563  redoItems.isEmpty() != null BIT 2
1564  docWasSavedWhenUndoWasEmpty == true BIT 3
1565  docWasSavedWhenRedoWasEmpty == true BIT 4
1566  lastUndoGroupWhenSavedIsLastUndo BIT 5
1567  lastUndoGroupWhenSavedIsLastRedo BIT 6
1568  lastRedoGroupWhenSavedIsLastUndo BIT 7
1569  lastRedoGroupWhenSavedIsLastRedo BIT 8
1570 
1571  If you find a new pattern, please add it to the patterns array
1572  */
1573 
1574  unsigned char currentPattern = 0;
1575  const unsigned char patterns[] = {5,16,24,26,88,90,93,133,144,149,165};
1576  const unsigned char patternCount = sizeof(patterns);
1577  KateUndoGroup* undoLast = 0;
1578  KateUndoGroup* redoLast = 0;
1579 
1580  if (undoItems.isEmpty())
1581  {
1582  currentPattern |= 1;
1583  }
1584  else
1585  {
1586  undoLast = undoItems.last();
1587  }
1588 
1589  if (redoItems.isEmpty())
1590  {
1591  currentPattern |= 2;
1592  }
1593  else
1594  {
1595  redoLast = redoItems.last();
1596  }
1597 
1598  if (docWasSavedWhenUndoWasEmpty) currentPattern |= 4;
1599  if (docWasSavedWhenRedoWasEmpty) currentPattern |= 8;
1600  if (lastUndoGroupWhenSaved == undoLast) currentPattern |= 16;
1601  if (lastUndoGroupWhenSaved == redoLast) currentPattern |= 32;
1602  if (lastRedoGroupWhenSaved == undoLast) currentPattern |= 64;
1603  if (lastRedoGroupWhenSaved == redoLast) currentPattern |= 128;
1604 
1605  // This will print out the pattern information
1606 
1607  kdDebug(13020) << k_funcinfo
1608  << "Pattern:" << static_cast<unsigned int>(currentPattern) << endl;
1609 
1610  for (uint patternIndex = 0; patternIndex < patternCount; ++patternIndex)
1611  {
1612  if ( currentPattern == patterns[patternIndex] )
1613  {
1614  setModified( false );
1615  kdDebug(13020) << k_funcinfo << "setting modified to false!" << endl;
1616  break;
1617  }
1618  }
1619 }
1620 
1621 void KateDocument::clearUndo()
1622 {
1623  undoItems.setAutoDelete (true);
1624  undoItems.clear ();
1625  undoItems.setAutoDelete (false);
1626 
1627  lastUndoGroupWhenSaved = 0;
1628  docWasSavedWhenUndoWasEmpty = false;
1629 
1630  emit undoChanged ();
1631 }
1632 
1633 void KateDocument::clearRedo()
1634 {
1635  redoItems.setAutoDelete (true);
1636  redoItems.clear ();
1637  redoItems.setAutoDelete (false);
1638 
1639  lastRedoGroupWhenSaved = 0;
1640  docWasSavedWhenRedoWasEmpty = false;
1641 
1642  emit undoChanged ();
1643 }
1644 
1645 TQPtrList<KTextEditor::Cursor> KateDocument::cursors () const
1646 {
1647  return myCursors;
1648 }
1649 //END
1650 
1651 //BEGIN KTextEditor::SearchInterface stuff
1652 
1653 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)
1654 {
1655  if (text.isEmpty())
1656  return false;
1657 
1658  int line = startLine;
1659  int col = startCol;
1660 
1661  if (!backwards)
1662  {
1663  int searchEnd = lastLine();
1664 
1665  while (line <= searchEnd)
1666  {
1667  KateTextLine::Ptr textLine = m_buffer->plainLine(line);
1668 
1669  if (!textLine)
1670  return false;
1671 
1672  uint foundAt, myMatchLen;
1673  bool found = textLine->searchText (col, text, &foundAt, &myMatchLen, casesensitive, false);
1674 
1675  if (found)
1676  {
1677  (*foundAtLine) = line;
1678  (*foundAtCol) = foundAt;
1679  (*matchLen) = myMatchLen;
1680  return true;
1681  }
1682 
1683  col = 0;
1684  line++;
1685  }
1686  }
1687  else
1688  {
1689  // backward search
1690  int searchEnd = 0;
1691 
1692  while (line >= searchEnd)
1693  {
1694  KateTextLine::Ptr textLine = m_buffer->plainLine(line);
1695 
1696  if (!textLine)
1697  return false;
1698 
1699  uint foundAt, myMatchLen;
1700  bool found = textLine->searchText (col, text, &foundAt, &myMatchLen, casesensitive, true);
1701 
1702  if (found)
1703  {
1704  /* if ((uint) line == startLine && foundAt + myMatchLen >= (uint) col
1705  && line == selectStart.line() && foundAt == (uint) selectStart.col()
1706  && line == selectEnd.line() && foundAt + myMatchLen == (uint) selectEnd.col())
1707  {
1708  // To avoid getting stuck at one match we skip a match if it is already
1709  // selected (most likely because it has just been found).
1710  if (foundAt > 0)
1711  col = foundAt - 1;
1712  else {
1713  if (--line >= 0)
1714  col = lineLength(line);
1715  }
1716  continue;
1717  }*/
1718 
1719  (*foundAtLine) = line;
1720  (*foundAtCol) = foundAt;
1721  (*matchLen) = myMatchLen;
1722  return true;
1723  }
1724 
1725  if (line >= 1)
1726  col = lineLength(line-1);
1727 
1728  line--;
1729  }
1730  }
1731 
1732  return false;
1733 }
1734 
1735 bool KateDocument::searchText (unsigned int startLine, unsigned int startCol, const TQRegExp &regexp, unsigned int *foundAtLine, unsigned int *foundAtCol, unsigned int *matchLen, bool backwards)
1736 {
1737  kdDebug(13020)<<"KateDocument::searchText( "<<startLine<<", "<<startCol<<", "<<TQString(regexp.pattern())<<", "<<backwards<<" )"<<endl;
1738  if (regexp.isEmpty() || !regexp.isValid())
1739  return false;
1740 
1741  int line = startLine;
1742  int col = startCol;
1743 
1744  if (!backwards)
1745  {
1746  int searchEnd = lastLine();
1747 
1748  while (line <= searchEnd)
1749  {
1750  KateTextLine::Ptr textLine = m_buffer->plainLine(line);
1751 
1752  if (!textLine)
1753  return false;
1754 
1755  uint foundAt, myMatchLen;
1756  bool found = textLine->searchText (col, regexp, &foundAt, &myMatchLen, false);
1757 
1758  if (found)
1759  {
1760  // A special case which can only occur when searching with a regular expression consisting
1761  // only of a lookahead (e.g. ^(?=\{) for a function beginning without selecting '{').
1762  if (myMatchLen == 0 && (uint) line == startLine && foundAt == (uint) col)
1763  {
1764  if (col < lineLength(line))
1765  col++;
1766  else {
1767  line++;
1768  col = 0;
1769  }
1770  continue;
1771  }
1772 
1773  (*foundAtLine) = line;
1774  (*foundAtCol) = foundAt;
1775  (*matchLen) = myMatchLen;
1776  return true;
1777  }
1778 
1779  col = 0;
1780  line++;
1781  }
1782  }
1783  else
1784  {
1785  // backward search
1786  int searchEnd = 0;
1787 
1788  while (line >= searchEnd)
1789  {
1790  KateTextLine::Ptr textLine = m_buffer->plainLine(line);
1791 
1792  if (!textLine)
1793  return false;
1794 
1795  uint foundAt, myMatchLen;
1796  bool found = textLine->searchText (col, regexp, &foundAt, &myMatchLen, true);
1797 
1798  if (found)
1799  {
1800  /*if ((uint) line == startLine && foundAt + myMatchLen >= (uint) col
1801  && line == selectStart.line() && foundAt == (uint) selectStart.col()
1802  && line == selectEnd.line() && foundAt + myMatchLen == (uint) selectEnd.col())
1803  {
1804  // To avoid getting stuck at one match we skip a match if it is already
1805  // selected (most likely because it has just been found).
1806  if (foundAt > 0)
1807  col = foundAt - 1;
1808  else {
1809  if (--line >= 0)
1810  col = lineLength(line);
1811  }
1812  continue;
1813  }*/
1814 
1815  (*foundAtLine) = line;
1816  (*foundAtCol) = foundAt;
1817  (*matchLen) = myMatchLen;
1818  return true;
1819  }
1820 
1821  if (line >= 1)
1822  col = lineLength(line-1);
1823 
1824  line--;
1825  }
1826  }
1827 
1828  return false;
1829 }
1830 //END
1831 
1832 //BEGIN KTextEditor::HighlightingInterface stuff
1833 
1834 uint KateDocument::hlMode ()
1835 {
1836  return KateHlManager::self()->findHl(highlight());
1837 }
1838 
1839 bool KateDocument::setHlMode (uint mode)
1840 {
1841  m_buffer->setHighlight (mode);
1842 
1843  if (true)
1844  {
1845  setDontChangeHlOnSave();
1846  return true;
1847  }
1848 
1849  return false;
1850 }
1851 
1852 void KateDocument::bufferHlChanged ()
1853 {
1854  // update all views
1855  makeAttribs(false);
1856 
1857  emit hlChanged();
1858 }
1859 
1860 uint KateDocument::hlModeCount ()
1861 {
1862  return KateHlManager::self()->highlights();
1863 }
1864 
1865 TQString KateDocument::hlModeName (uint mode)
1866 {
1867  return KateHlManager::self()->hlName (mode);
1868 }
1869 
1870 TQString KateDocument::hlModeSectionName (uint mode)
1871 {
1872  return KateHlManager::self()->hlSection (mode);
1873 }
1874 
1875 void KateDocument::setDontChangeHlOnSave()
1876 {
1877  hlSetByUser = true;
1878 }
1879 //END
1880 
1881 //BEGIN KTextEditor::ConfigInterface stuff
1882 void KateDocument::readConfig(TDEConfig *config)
1883 {
1884  config->setGroup("Kate Document Defaults");
1885 
1886  // read max loadable blocks, more blocks will be swapped out
1887  KateBuffer::setMaxLoadedBlocks (config->readNumEntry("Maximal Loaded Blocks", KateBuffer::maxLoadedBlocks()));
1888 
1889  KateDocumentConfig::global()->readConfig (config);
1890 
1891  config->setGroup("Kate View Defaults");
1892  KateViewConfig::global()->readConfig (config);
1893 
1894  config->setGroup("Kate Renderer Defaults");
1895  KateRendererConfig::global()->readConfig (config);
1896 }
1897 
1898 void KateDocument::writeConfig(TDEConfig *config)
1899 {
1900  config->setGroup("Kate Document Defaults");
1901 
1902  // write max loadable blocks, more blocks will be swapped out
1903  config->writeEntry("Maximal Loaded Blocks", KateBuffer::maxLoadedBlocks());
1904 
1905  KateDocumentConfig::global()->writeConfig (config);
1906 
1907  config->setGroup("Kate View Defaults");
1908  KateViewConfig::global()->writeConfig (config);
1909 
1910  config->setGroup("Kate Renderer Defaults");
1911  KateRendererConfig::global()->writeConfig (config);
1912 }
1913 
1914 void KateDocument::readConfig()
1915 {
1916  TDEConfig *config = kapp->config();
1917  readConfig (config);
1918 }
1919 
1920 void KateDocument::writeConfig()
1921 {
1922  TDEConfig *config = kapp->config();
1923  writeConfig (config);
1924  config->sync();
1925 }
1926 
1927 void KateDocument::readSessionConfig(TDEConfig *tdeconfig)
1928 {
1929  // restore the url
1930  KURL url (tdeconfig->readEntry("URL"));
1931 
1932  // get the encoding
1933  TQString tmpenc=tdeconfig->readEntry("Encoding");
1934  if (!tmpenc.isEmpty() && (tmpenc != encoding()))
1935  setEncoding(tmpenc);
1936 
1937  // open the file if url valid
1938  if (!url.isEmpty() && url.isValid())
1939  openURL (url);
1940 
1941  // restore the hl stuff
1942  m_buffer->setHighlight(KateHlManager::self()->nameFind(tdeconfig->readEntry("Highlighting")));
1943 
1944  if (hlMode() > 0)
1945  hlSetByUser = true;
1946 
1947  // indent mode
1948  config()->setIndentationMode( (uint)tdeconfig->readNumEntry("Indentation Mode", config()->indentationMode() ) );
1949 
1950  // Restore Bookmarks
1951  TQValueList<int> marks = tdeconfig->readIntListEntry("Bookmarks");
1952  for( uint i = 0; i < marks.count(); i++ )
1953  addMark( marks[i], KateDocument::markType01 );
1954 }
1955 
1956 void KateDocument::writeSessionConfig(TDEConfig *tdeconfig)
1957 {
1958  if ( m_url.isLocalFile() && !TDEGlobal::dirs()->relativeLocation("tmp", m_url.path()).startsWith("/"))
1959  return;
1960  // save url
1961  tdeconfig->writeEntry("URL", m_url.prettyURL() );
1962 
1963  // save encoding
1964  tdeconfig->writeEntry("Encoding",encoding());
1965 
1966  // save hl
1967  tdeconfig->writeEntry("Highlighting", highlight()->name());
1968 
1969  tdeconfig->writeEntry("Indentation Mode", config()->indentationMode() );
1970 
1971  // Save Bookmarks
1972  TQValueList<int> marks;
1973  for( TQIntDictIterator<KTextEditor::Mark> it( m_marks );
1974  it.current() && it.current()->type & KTextEditor::MarkInterface::markType01;
1975  ++it )
1976  marks << it.current()->line;
1977 
1978  tdeconfig->writeEntry( "Bookmarks", marks );
1979 }
1980 
1981 void KateDocument::configDialog()
1982 {
1983  KDialogBase *kd = new KDialogBase ( KDialogBase::IconList,
1984  i18n("Configure"),
1985  KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Help,
1986  KDialogBase::Ok,
1987  kapp->mainWidget() );
1988 
1989 #ifndef TQ_WS_WIN //TODO: reenable
1990  KWin::setIcons( kd->winId(), kapp->icon(), kapp->miniIcon() );
1991 #endif
1992 
1993  TQPtrList<KTextEditor::ConfigPage> editorPages;
1994 
1995  for (uint i = 0; i < KTextEditor::configInterfaceExtension (this)->configPages (); i++)
1996  {
1997  TQStringList path;
1998  path.clear();
1999  path << KTextEditor::configInterfaceExtension (this)->configPageName (i);
2000  TQVBox *page = kd->addVBoxPage(path, KTextEditor::configInterfaceExtension (this)->configPageFullName (i),
2001  KTextEditor::configInterfaceExtension (this)->configPagePixmap(i, TDEIcon::SizeMedium) );
2002 
2003  editorPages.append (KTextEditor::configInterfaceExtension (this)->configPage(i, page));
2004  }
2005 
2006  if (kd->exec())
2007  {
2008  KateDocumentConfig::global()->configStart ();
2009  KateViewConfig::global()->configStart ();
2010  KateRendererConfig::global()->configStart ();
2011 
2012  for (uint i=0; i<editorPages.count(); i++)
2013  {
2014  editorPages.at(i)->apply();
2015  }
2016 
2017  KateDocumentConfig::global()->configEnd ();
2018  KateViewConfig::global()->configEnd ();
2019  KateRendererConfig::global()->configEnd ();
2020 
2021  writeConfig ();
2022  }
2023 
2024  delete kd;
2025 }
2026 
2027 uint KateDocument::mark( uint line )
2028 {
2029  if( !m_marks[line] )
2030  return 0;
2031  return m_marks[line]->type;
2032 }
2033 
2034 void KateDocument::setMark( uint line, uint markType )
2035 {
2036  clearMark( line );
2037  addMark( line, markType );
2038 }
2039 
2040 void KateDocument::clearMark( uint line )
2041 {
2042  if( line > lastLine() )
2043  return;
2044 
2045  if( !m_marks[line] )
2046  return;
2047 
2048  KTextEditor::Mark* mark = m_marks.take( line );
2049  emit markChanged( *mark, MarkRemoved );
2050  emit marksChanged();
2051  delete mark;
2052  tagLines( line, line );
2053  repaintViews(true);
2054 }
2055 
2056 void KateDocument::addMark( uint line, uint markType )
2057 {
2058  if( line > lastLine())
2059  return;
2060 
2061  if( markType == 0 )
2062  return;
2063 
2064  if( m_marks[line] ) {
2065  KTextEditor::Mark* mark = m_marks[line];
2066 
2067  // Remove bits already set
2068  markType &= ~mark->type;
2069 
2070  if( markType == 0 )
2071  return;
2072 
2073  // Add bits
2074  mark->type |= markType;
2075  } else {
2076  KTextEditor::Mark *mark = new KTextEditor::Mark;
2077  mark->line = line;
2078  mark->type = markType;
2079  m_marks.insert( line, mark );
2080  }
2081 
2082  // Emit with a mark having only the types added.
2083  KTextEditor::Mark temp;
2084  temp.line = line;
2085  temp.type = markType;
2086  emit markChanged( temp, MarkAdded );
2087 
2088  emit marksChanged();
2089  tagLines( line, line );
2090  repaintViews(true);
2091 }
2092 
2093 void KateDocument::removeMark( uint line, uint markType )
2094 {
2095  if( line > lastLine() )
2096  return;
2097  if( !m_marks[line] )
2098  return;
2099 
2100  KTextEditor::Mark* mark = m_marks[line];
2101 
2102  // Remove bits not set
2103  markType &= mark->type;
2104 
2105  if( markType == 0 )
2106  return;
2107 
2108  // Subtract bits
2109  mark->type &= ~markType;
2110 
2111  // Emit with a mark having only the types removed.
2112  KTextEditor::Mark temp;
2113  temp.line = line;
2114  temp.type = markType;
2115  emit markChanged( temp, MarkRemoved );
2116 
2117  if( mark->type == 0 )
2118  m_marks.remove( line );
2119 
2120  emit marksChanged();
2121  tagLines( line, line );
2122  repaintViews(true);
2123 }
2124 
2125 TQPtrList<KTextEditor::Mark> KateDocument::marks()
2126 {
2127  TQPtrList<KTextEditor::Mark> list;
2128 
2129  for( TQIntDictIterator<KTextEditor::Mark> it( m_marks );
2130  it.current(); ++it ) {
2131  list.append( it.current() );
2132  }
2133 
2134  return list;
2135 }
2136 
2137 void KateDocument::clearMarks()
2138 {
2139  for( TQIntDictIterator<KTextEditor::Mark> it( m_marks );
2140  it.current(); ++it ) {
2141  KTextEditor::Mark* mark = it.current();
2142  emit markChanged( *mark, MarkRemoved );
2143  tagLines( mark->line, mark->line );
2144  }
2145 
2146  m_marks.clear();
2147 
2148  emit marksChanged();
2149  repaintViews(true);
2150 }
2151 
2152 void KateDocument::setPixmap( MarkInterface::MarkTypes type, const TQPixmap& pixmap )
2153 {
2154  m_markPixmaps.replace( type, new TQPixmap( pixmap ) );
2155 }
2156 
2157 void KateDocument::setDescription( MarkInterface::MarkTypes type, const TQString& description )
2158 {
2159  m_markDescriptions.replace( type, new TQString( description ) );
2160 }
2161 
2162 TQPixmap *KateDocument::markPixmap( MarkInterface::MarkTypes type )
2163 {
2164  return m_markPixmaps[type];
2165 }
2166 
2167 TQColor KateDocument::markColor( MarkInterface::MarkTypes type )
2168 {
2169  uint reserved = (0x1 << KTextEditor::MarkInterface::reservedMarkersCount()) - 1;
2170  if ((uint)type >= (uint)markType01 && (uint)type <= reserved) {
2171  return KateRendererConfig::global()->lineMarkerColor(type);
2172  } else {
2173  return TQColor();
2174  }
2175 }
2176 
2177 TQString KateDocument::markDescription( MarkInterface::MarkTypes type )
2178 {
2179  if( m_markDescriptions[type] )
2180  return *m_markDescriptions[type];
2181  return TQString::null;
2182 }
2183 
2184 void KateDocument::setMarksUserChangable( uint markMask )
2185 {
2186  m_editableMarks = markMask;
2187 }
2188 
2189 uint KateDocument::editableMarks()
2190 {
2191  return m_editableMarks;
2192 }
2193 //END
2194 
2195 //BEGIN KTextEditor::PrintInterface stuff
2196 bool KateDocument::printDialog ()
2197 {
2198  return KatePrinter::print (this);
2199 }
2200 
2201 bool KateDocument::print ()
2202 {
2203  return KatePrinter::print (this);
2204 }
2205 //END
2206 
2207 //BEGIN KTextEditor::DocumentInfoInterface (### unfinished)
2208 TQString KateDocument::mimeType()
2209 {
2210  KMimeType::Ptr result = KMimeType::defaultMimeTypePtr();
2211 
2212  // if the document has a URL, try KMimeType::findByURL
2213  if ( ! m_url.isEmpty() )
2214  result = KMimeType::findByURL( m_url );
2215 
2216  else if ( m_url.isEmpty() || ! m_url.isLocalFile() )
2217  result = mimeTypeForContent();
2218 
2219  return result->name();
2220 }
2221 
2222 // TODO implement this -- how to calculate?
2223 long KateDocument::fileSize()
2224 {
2225  return 0;
2226 }
2227 
2228 // TODO implement this
2229 TQString KateDocument::niceFileSize()
2230 {
2231  return "UNKNOWN";
2232 }
2233 
2234 KMimeType::Ptr KateDocument::mimeTypeForContent()
2235 {
2236  TQByteArray buf (1024);
2237  uint bufpos = 0;
2238 
2239  for (uint i=0; i < numLines(); i++)
2240  {
2241  TQString line = textLine( i );
2242  uint len = line.length() + 1;
2243 
2244  if (bufpos + len > 1024)
2245  len = 1024 - bufpos;
2246 
2247  memcpy(&buf[bufpos], (line + "\n").latin1(), len);
2248 
2249  bufpos += len;
2250 
2251  if (bufpos >= 1024)
2252  break;
2253  }
2254  buf.resize( bufpos );
2255 
2256  int accuracy = 0;
2257  return KMimeType::findByContent( buf, &accuracy );
2258 }
2259 //END KTextEditor::DocumentInfoInterface
2260 
2261 
2262 //BEGIN KParts::ReadWrite stuff
2263 
2264 bool KateDocument::openURL( const KURL &url )
2265 {
2266 // kdDebug(13020)<<"KateDocument::openURL( "<<url.prettyURL()<<")"<<endl;
2267  // no valid URL
2268  if ( !url.isValid() )
2269  return false;
2270 
2271  // could not close old one
2272  if ( !closeURL() )
2273  return false;
2274 
2275  // set my url
2276  m_url = url;
2277 
2278  if ( m_url.isLocalFile() )
2279  {
2280  // local mode, just like in kpart
2281 
2282  m_file = m_url.path();
2283 
2284  emit started( 0 );
2285 
2286  if (openFile())
2287  {
2288  emit completed();
2289  emit setWindowCaption( m_url.prettyURL() );
2290 
2291  return true;
2292  }
2293 
2294  return false;
2295  }
2296  else
2297  {
2298  // remote mode
2299 
2300  m_bTemp = true;
2301 
2302  m_tempFile = new KTempFile ();
2303  m_file = m_tempFile->name();
2304 
2305  m_job = TDEIO::get ( url, false, isProgressInfoEnabled() );
2306 
2307  // connect to slots
2308  connect( m_job, TQ_SIGNAL( data( TDEIO::Job*, const TQByteArray& ) ),
2309  TQ_SLOT( slotDataKate( TDEIO::Job*, const TQByteArray& ) ) );
2310 
2311  connect( m_job, TQ_SIGNAL( result( TDEIO::Job* ) ),
2312  TQ_SLOT( slotFinishedKate( TDEIO::Job* ) ) );
2313 
2314  TQWidget *w = widget ();
2315  if (!w && !m_views.isEmpty ())
2316  w = m_views.first();
2317 
2318  if (w)
2319  m_job->setWindow (w->topLevelWidget());
2320 
2321  emit started( m_job );
2322 
2323  return true;
2324  }
2325 }
2326 
2327 void KateDocument::slotDataKate ( TDEIO::Job *, const TQByteArray &data )
2328 {
2329 // kdDebug(13020) << "KateDocument::slotData" << endl;
2330 
2331  if (!m_tempFile || !m_tempFile->file())
2332  return;
2333 
2334  m_tempFile->file()->writeBlock (data);
2335 }
2336 
2337 void KateDocument::slotFinishedKate ( TDEIO::Job * job )
2338 {
2339 // kdDebug(13020) << "KateDocument::slotJobFinished" << endl;
2340 
2341  if (!m_tempFile)
2342  return;
2343 
2344  delete m_tempFile;
2345  m_tempFile = 0;
2346  m_job = 0;
2347 
2348  if (job->error())
2349  emit canceled( job->errorString() );
2350  else
2351  {
2352  if ( openFile(job) )
2353  emit setWindowCaption( m_url.prettyURL() );
2354  emit completed();
2355  }
2356 }
2357 
2358 void KateDocument::abortLoadKate()
2359 {
2360  if ( m_job )
2361  {
2362  kdDebug(13020) << "Aborting job " << m_job << endl;
2363  m_job->kill();
2364  m_job = 0;
2365  }
2366 
2367  delete m_tempFile;
2368  m_tempFile = 0;
2369 }
2370 
2371 bool KateDocument::openFile()
2372 {
2373  return openFile (0);
2374 }
2375 
2376 bool KateDocument::openFile(TDEIO::Job * job)
2377 {
2378  m_loading = true;
2379  // add new m_file to dirwatch
2380  activateDirWatch ();
2381 
2382  //
2383  // use metadata
2384  //
2385  if (job)
2386  {
2387  TQString metaDataCharset = job->queryMetaData("charset");
2388 
2389  // only overwrite config if nothing set
2390  if (!metaDataCharset.isEmpty () && (!m_config->isSetEncoding() || m_config->encoding().isEmpty()))
2391  setEncoding (metaDataCharset);
2392  }
2393 
2394  //
2395  // service type magic to get encoding right
2396  //
2397  TQString serviceType = m_extension->urlArgs().serviceType.simplifyWhiteSpace();
2398  int pos = serviceType.find(';');
2399  if (pos != -1)
2400  setEncoding (serviceType.mid(pos+1));
2401 
2402  // if the encoding is set here - on the command line/from the dialog/from TDEIO
2403  // we prevent file type and document variables from changing it
2404  bool encodingSticky = m_encodingSticky;
2405  m_encodingSticky = m_config->isSetEncoding();
2406 
2407  // Try getting the filetype here, so that variables does not have to be reset.
2408  int fileTypeFound = KateFactory::self()->fileTypeManager()->fileType (this);
2409  if ( fileTypeFound > -1 )
2410  updateFileType( fileTypeFound );
2411 
2412  // read dir config (if possible and wanted)
2413  if (!m_reloading)
2414  readDirConfig ();
2415 
2416  // do we have success ?
2417  bool success = m_buffer->openFile (m_file);
2418  //
2419  // yeah, success
2420  //
2421  m_loading = false; // done reading file.
2422  if (success)
2423  {
2424  /*if (highlight() && !m_url.isLocalFile()) {
2425  // The buffer's highlighting gets nuked by KateBuffer::clear()
2426  m_buffer->setHighlight(m_highlight);
2427  }*/
2428 
2429  // update our hl type if needed
2430  if (!hlSetByUser)
2431  {
2432  int hl (KateHlManager::self()->detectHighlighting (this));
2433 
2434  if (hl >= 0)
2435  m_buffer->setHighlight(hl);
2436  }
2437 
2438  // update file type if we haven't allready done so.
2439  if ( fileTypeFound < 0 )
2440  updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
2441 
2442  // read vars
2443  readVariables();
2444 
2445  // update the md5 digest
2446  createDigest( m_digest );
2447  }
2448 
2449  //
2450  // update views
2451  //
2452  for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
2453  {
2454  view->updateView(true);
2455  }
2456 
2457  //
2458  // emit the signal we need for example for kate app
2459  //
2460  emit fileNameChanged ();
2461 
2462  //
2463  // set doc name, dummy value as arg, don't need it
2464  //
2465  setDocName (TQString::null);
2466 
2467  //
2468  // to houston, we are not modified
2469  //
2470  if (m_modOnHd)
2471  {
2472  m_modOnHd = false;
2473  m_modOnHdReason = 0;
2474  emit modifiedOnDisc (this, m_modOnHd, 0);
2475  }
2476 
2477  //
2478  // display errors
2479  //
2480  if (s_openErrorDialogsActivated)
2481  {
2482  if (!success && m_buffer->loadingBorked())
2483  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()));
2484  else if (!success)
2485  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()));
2486  }
2487 
2488  // warn -> opened binary file!!!!!!!
2489  if (m_buffer->binary())
2490  {
2491  // this file can't be saved again without killing it
2492  setReadWrite( false );
2493 
2494  KMessageBox::information (widget()
2495  , i18n ("The file %1 is a binary, saving it will result in a corrupt file.").arg(m_url.url())
2496  , i18n ("Binary File Opened")
2497  , "Binary File Opened Warning");
2498  }
2499 
2500  m_encodingSticky = encodingSticky;
2501 
2502  //
2503  // return the success
2504  //
2505  return success;
2506 }
2507 
2508 bool KateDocument::save()
2509 {
2510  bool l ( url().isLocalFile() );
2511 
2512  if ( ( l && config()->backupFlags() & KateDocumentConfig::LocalFiles )
2513  || ( ! l && config()->backupFlags() & KateDocumentConfig::RemoteFiles ) )
2514  {
2515  KURL u( url() );
2516  u.setFileName( config()->backupPrefix() + url().fileName() + config()->backupSuffix() );
2517 
2518  kdDebug () << "backup src file name: " << url() << endl;
2519  kdDebug () << "backup dst file name: " << u << endl;
2520 
2521  // get the right permissions, start with safe default
2522  mode_t perms = 0600;
2523  TDEIO::UDSEntry fentry;
2524  if (TDEIO::NetAccess::stat (url(), fentry, kapp->mainWidget()))
2525  {
2526  kdDebug () << "stating succesfull: " << url() << endl;
2527  KFileItem item (fentry, url());
2528  perms = item.permissions();
2529  }
2530 
2531  // first del existing file if any, than copy over the file we have
2532  // failure if a: the existing file could not be deleted, b: the file could not be copied
2533  if ( (!TDEIO::NetAccess::exists( u, false, kapp->mainWidget() ) || TDEIO::NetAccess::del( u, kapp->mainWidget() ))
2534  && TDEIO::NetAccess::file_copy( url(), u, perms, true, false, kapp->mainWidget() ) )
2535  {
2536  kdDebug(13020)<<"backing up successfull ("<<url().prettyURL()<<" -> "<<u.prettyURL()<<")"<<endl;
2537  }
2538  else
2539  {
2540  kdDebug(13020)<<"backing up failed ("<<url().prettyURL()<<" -> "<<u.prettyURL()<<")"<<endl;
2541  // FIXME: notify user for real ;)
2542  }
2543  }
2544 
2545  return KParts::ReadWritePart::save();
2546 }
2547 
2548 bool KateDocument::saveFile()
2549 {
2550  //
2551  // we really want to save this file ?
2552  //
2553  if (m_buffer->loadingBorked() && (KMessageBox::warningContinueCancel(widget(),
2554  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))
2555  return false;
2556 
2557  //
2558  // warn -> try to save binary file!!!!!!!
2559  //
2560  if (m_buffer->binary() && (KMessageBox::warningContinueCancel (widget()
2561  , i18n ("The file %1 is a binary, saving it will result in a corrupt file.").arg(m_url.url())
2562  , i18n ("Trying to Save Binary File")
2563  , i18n("Save Nevertheless"), "Binary File Save Warning") != KMessageBox::Continue))
2564  return false;
2565 
2566  if ( !url().isEmpty() )
2567  {
2568  if (s_fileChangedDialogsActivated && m_modOnHd)
2569  {
2570  TQString str = reasonedMOHString() + "\n\n";
2571 
2572  if (!isModified())
2573  {
2574  if (KMessageBox::warningContinueCancel(0,
2575  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)
2576  return false;
2577  }
2578  else
2579  {
2580  if (KMessageBox::warningContinueCancel(0,
2581  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)
2582  return false;
2583  }
2584  }
2585  }
2586 
2587  //
2588  // can we encode it if we want to save it ?
2589  //
2590  if (!m_buffer->canEncode ()
2591  && (KMessageBox::warningContinueCancel(0,
2592  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))
2593  {
2594  return false;
2595  }
2596 
2597  // remove file from dirwatch
2598  deactivateDirWatch ();
2599 
2600  //
2601  // try to save
2602  //
2603  bool success = m_buffer->saveFile (m_file);
2604 
2605  // update the md5 digest
2606  createDigest( m_digest );
2607 
2608  // add m_file again to dirwatch
2609  activateDirWatch ();
2610 
2611  //
2612  // hurray, we had success, do stuff we need
2613  //
2614  if (success)
2615  {
2616  // update our hl type if needed
2617  if (!hlSetByUser)
2618  {
2619  int hl (KateHlManager::self()->detectHighlighting (this));
2620 
2621  if (hl >= 0)
2622  m_buffer->setHighlight(hl);
2623  }
2624 
2625  // read our vars
2626  readVariables();
2627  }
2628 
2629  //
2630  // we are not modified
2631  //
2632  if (success && m_modOnHd)
2633  {
2634  m_modOnHd = false;
2635  m_modOnHdReason = 0;
2636  emit modifiedOnDisc (this, m_modOnHd, 0);
2637  }
2638 
2639  //
2640  // display errors
2641  //
2642  if (!success)
2643  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()));
2644 
2645  //
2646  // return success
2647  //
2648  return success;
2649 }
2650 
2651 bool KateDocument::saveAs( const KURL &u )
2652 {
2653  TQString oldDir = url().directory();
2654 
2655  if ( KParts::ReadWritePart::saveAs( u ) )
2656  {
2657  // null means base on filename
2658  setDocName( TQString::null );
2659 
2660  if ( u.directory() != oldDir )
2661  readDirConfig();
2662 
2663  emit fileNameChanged();
2664  emit nameChanged((Kate::Document *) this);
2665 
2666  return true;
2667  }
2668 
2669  return false;
2670 }
2671 
2672 void KateDocument::readDirConfig ()
2673 {
2674  int depth = config()->searchDirConfigDepth ();
2675 
2676  if (m_url.isLocalFile() && (depth > -1))
2677  {
2678  TQString currentDir = TQFileInfo (m_file).dirPath();
2679 
2680  // only search as deep as specified or not at all ;)
2681  while (depth > -1)
2682  {
2683  kdDebug (13020) << "search for config file in path: " << currentDir << endl;
2684 
2685  // try to open config file in this dir
2686  TQFile f (currentDir + "/.kateconfig");
2687 
2688  if (f.open (IO_ReadOnly))
2689  {
2690  TQTextStream stream (&f);
2691 
2692  uint linesRead = 0;
2693  TQString line = stream.readLine();
2694  while ((linesRead < 32) && !line.isNull())
2695  {
2696  readVariableLine( line );
2697 
2698  line = stream.readLine();
2699 
2700  linesRead++;
2701  }
2702 
2703  break;
2704  }
2705 
2706  TQString newDir = TQFileInfo (currentDir).dirPath();
2707 
2708  // bail out on looping (for example reached /)
2709  if (currentDir == newDir)
2710  break;
2711 
2712  currentDir = newDir;
2713  --depth;
2714  }
2715  }
2716 }
2717 
2718 void KateDocument::activateDirWatch ()
2719 {
2720  // same file as we are monitoring, return
2721  if (m_file == m_dirWatchFile)
2722  return;
2723 
2724  // remove the old watched file
2725  deactivateDirWatch ();
2726 
2727  // add new file if needed
2728  if (m_url.isLocalFile() && !m_file.isEmpty())
2729  {
2730  KateFactory::self()->dirWatch ()->addFile (m_file);
2731  m_dirWatchFile = m_file;
2732  }
2733 }
2734 
2735 void KateDocument::deactivateDirWatch ()
2736 {
2737  if (!m_dirWatchFile.isEmpty())
2738  KateFactory::self()->dirWatch ()->removeFile (m_dirWatchFile);
2739 
2740  m_dirWatchFile = TQString::null;
2741 }
2742 
2743 bool KateDocument::closeURL()
2744 {
2745  abortLoadKate();
2746 
2747  //
2748  // file mod on hd
2749  //
2750  if ( !m_reloading && !url().isEmpty() )
2751  {
2752  if (s_fileChangedDialogsActivated && m_modOnHd)
2753  {
2754  if (!(KMessageBox::warningContinueCancel(
2755  widget(),
2756  reasonedMOHString() + "\n\n" + i18n("Do you really want to continue to close this file? Data loss may occur."),
2757  i18n("Possible Data Loss"), i18n("Close Nevertheless"),
2758  TQString("kate_close_modonhd_%1").arg( m_modOnHdReason ) ) == KMessageBox::Continue))
2759  return false;
2760  }
2761  }
2762 
2763  //
2764  // first call the normal tdeparts implementation
2765  //
2766  if (!KParts::ReadWritePart::closeURL ())
2767  return false;
2768 
2769  // remove file from dirwatch
2770  deactivateDirWatch ();
2771 
2772  //
2773  // empty url + filename
2774  //
2775  m_url = KURL ();
2776  m_file = TQString::null;
2777 
2778  // we are not modified
2779  if (m_modOnHd)
2780  {
2781  m_modOnHd = false;
2782  m_modOnHdReason = 0;
2783  emit modifiedOnDisc (this, m_modOnHd, 0);
2784  }
2785 
2786  // clear the buffer
2787  m_buffer->clear();
2788 
2789  // remove all marks
2790  clearMarks ();
2791 
2792  // clear undo/redo history
2793  clearUndo();
2794  clearRedo();
2795 
2796  // no, we are no longer modified
2797  setModified(false);
2798 
2799  // we have no longer any hl
2800  m_buffer->setHighlight(0);
2801 
2802  // update all our views
2803  for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
2804  {
2805  // Explicitly call the internal version because we don't want this to look like
2806  // an external request (and thus have the view not TQWidget::scroll()ed.
2807  view->setCursorPositionInternal(0, 0, 1, false);
2808  view->clearSelection();
2809  view->updateView(true);
2810  }
2811 
2812  // uh, filename changed
2813  emit fileNameChanged ();
2814 
2815  // update doc name
2816  setDocName (TQString::null);
2817 
2818  // success
2819  return true;
2820 }
2821 
2822 void KateDocument::setReadWrite( bool rw )
2823 {
2824  if (isReadWrite() != rw)
2825  {
2826  KParts::ReadWritePart::setReadWrite (rw);
2827 
2828  for( KateView* view = m_views.first(); view != 0L; view = m_views.next() )
2829  {
2830  view->slotUpdate();
2831  view->slotReadWriteChanged ();
2832  }
2833  }
2834 }
2835 
2836 void KateDocument::setModified(bool m) {
2837 
2838  if (isModified() != m) {
2839  KParts::ReadWritePart::setModified (m);
2840 
2841  for( KateView* view = m_views.first(); view != 0L; view = m_views.next() )
2842  {
2843  view->slotUpdate();
2844  }
2845 
2846  emit modifiedChanged ();
2847  emit modStateChanged ((Kate::Document *)this);
2848  }
2849  if ( m == false )
2850  {
2851  if ( ! undoItems.isEmpty() )
2852  {
2853  lastUndoGroupWhenSaved = undoItems.last();
2854  }
2855 
2856  if ( ! redoItems.isEmpty() )
2857  {
2858  lastRedoGroupWhenSaved = redoItems.last();
2859  }
2860 
2861  docWasSavedWhenUndoWasEmpty = undoItems.isEmpty();
2862  docWasSavedWhenRedoWasEmpty = redoItems.isEmpty();
2863  }
2864 }
2865 //END
2866 
2867 //BEGIN Kate specific stuff ;)
2868 
2869 void KateDocument::makeAttribs(bool needInvalidate)
2870 {
2871  for (uint z = 0; z < m_views.count(); z++)
2872  m_views.at(z)->renderer()->updateAttributes ();
2873 
2874  if (needInvalidate)
2875  m_buffer->invalidateHighlighting();
2876 
2877  tagAll ();
2878 }
2879 
2880 // the attributes of a hl have changed, update
2881 void KateDocument::internalHlChanged()
2882 {
2883  makeAttribs();
2884 }
2885 
2886 void KateDocument::addView(KTextEditor::View *view) {
2887  if (!view)
2888  return;
2889 
2890  m_views.append( (KateView *) view );
2891  m_textEditViews.append( view );
2892 
2893  // apply the view & renderer vars from the file type
2894  const KateFileType *t = 0;
2895  if ((m_fileType > -1) && (t = KateFactory::self()->fileTypeManager()->fileType(m_fileType)))
2896  readVariableLine (t->varLine, true);
2897 
2898  // apply the view & renderer vars from the file
2899  readVariables (true);
2900 
2901  m_activeView = (KateView *) view;
2902 }
2903 
2904 void KateDocument::removeView(KTextEditor::View *view) {
2905  if (!view)
2906  return;
2907 
2908  if (m_activeView == view)
2909  m_activeView = 0L;
2910 
2911  m_views.removeRef( (KateView *) view );
2912  m_textEditViews.removeRef( view );
2913 }
2914 
2915 void KateDocument::addSuperCursor(KateSuperCursor *cursor, bool privateC) {
2916  if (!cursor)
2917  return;
2918 
2919  m_superCursors.append( cursor );
2920 
2921  if (!privateC)
2922  myCursors.append( cursor );
2923 }
2924 
2925 void KateDocument::removeSuperCursor(KateSuperCursor *cursor, bool privateC) {
2926  if (!cursor)
2927  return;
2928 
2929  if (!privateC)
2930  myCursors.removeRef( cursor );
2931 
2932  m_superCursors.removeRef( cursor );
2933 }
2934 
2935 bool KateDocument::ownedView(KateView *view) {
2936  // do we own the given view?
2937  return (m_views.containsRef(view) > 0);
2938 }
2939 
2940 bool KateDocument::isLastView(int numViews) {
2941  return ((int) m_views.count() == numViews);
2942 }
2943 
2944 uint KateDocument::currentColumn( const KateTextCursor& cursor )
2945 {
2946  KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
2947 
2948  if (textLine)
2949  return textLine->cursorX(cursor.col(), config()->tabWidth());
2950  else
2951  return 0;
2952 }
2953 
2954 bool KateDocument::typeChars ( KateView *view, const TQString &chars )
2955 {
2956  KateTextLine::Ptr textLine = m_buffer->plainLine(view->cursorLine ());
2957 
2958  if (!textLine)
2959  return false;
2960 
2961  bool bracketInserted = false;
2962  TQString buf;
2963  TQChar c;
2964 
2965  for( uint z = 0; z < chars.length(); z++ )
2966  {
2967  TQChar ch = c = chars[z];
2968  if (ch.isPrint() || ch == '\t')
2969  {
2970  buf.append (ch);
2971 
2972  if (!bracketInserted && (config()->configFlags() & KateDocument::cfAutoBrackets))
2973  {
2974  TQChar end_ch;
2975  bool complete = true;
2976  TQChar prevChar = textLine->getChar(view->cursorColumnReal()-1);
2977  TQChar nextChar = textLine->getChar(view->cursorColumnReal());
2978  switch(ch) {
2979  case '(': end_ch = ')'; break;
2980  case '[': end_ch = ']'; break;
2981  case '{': end_ch = '}'; break;
2982  case '\'':end_ch = '\'';break;
2983  case '"': end_ch = '"'; break;
2984  default: complete = false;
2985  }
2986  if (complete)
2987  {
2988  if (view->hasSelection())
2989  { // there is a selection, enclose the selection
2990  buf.append (view->selection());
2991  buf.append (end_ch);
2992  bracketInserted = true;
2993  }
2994  else
2995  { // no selection, check whether we should better refuse to complete
2996  if ( ( (ch == '\'' || ch == '"') &&
2997  (prevChar.isLetterOrNumber() || prevChar == ch) )
2998  || nextChar.isLetterOrNumber()
2999  || (nextChar == end_ch && prevChar != ch) )
3000  {
3001  kdDebug(13020) << "AutoBracket refused before: " << nextChar << "\n";
3002  }
3003  else
3004  {
3005  buf.append (end_ch);
3006  bracketInserted = true;
3007  }
3008  }
3009  }
3010  }
3011  }
3012  }
3013 
3014  if (buf.isEmpty())
3015  return false;
3016 
3017  editStart ();
3018 
3019  if (!view->config()->persistentSelection() && view->hasSelection() )
3020  view->removeSelectedText();
3021 
3022  int oldLine = view->cursorLine ();
3023  int oldCol = view->cursorColumnReal ();
3024 
3025 
3026  if (config()->configFlags() & KateDocument::cfOvr)
3027  removeText (view->cursorLine(), view->cursorColumnReal(), view->cursorLine(), kMin( view->cursorColumnReal()+buf.length(), textLine->length() ) );
3028 
3029  insertText (view->cursorLine(), view->cursorColumnReal(), buf);
3030  m_indenter->processChar(c);
3031 
3032  editEnd ();
3033 
3034  if (bracketInserted)
3035  view->setCursorPositionInternal (view->cursorLine(), view->cursorColumnReal()-1);
3036 
3037  emit charactersInteractivelyInserted (oldLine, oldCol, chars);
3038 
3039  return true;
3040 }
3041 
3042 void KateDocument::newLine( KateTextCursor& c, KateViewInternal *v )
3043 {
3044  editStart();
3045 
3046  if( !v->view()->config()->persistentSelection() && v->view()->hasSelection() )
3047  v->view()->removeSelectedText();
3048 
3049  // temporary hack to get the cursor pos right !!!!!!!!!
3050  c = v->getCursor ();
3051 
3052  if (c.line() > (int)lastLine())
3053  c.setLine(lastLine());
3054 
3055  if ( c.line() < 0 )
3056  c.setLine( 0 );
3057 
3058  uint ln = c.line();
3059 
3060  KateTextLine::Ptr textLine = kateTextLine(c.line());
3061 
3062  if (c.col() > (int)textLine->length())
3063  c.setCol(textLine->length());
3064 
3065  if (m_indenter->canProcessNewLine ())
3066  {
3067  int pos = textLine->firstChar();
3068 
3069  // length should do the job better
3070  if (pos < 0)
3071  pos = textLine->length();
3072 
3073  if (c.col() < pos)
3074  c.setCol(pos); // place cursor on first char if before
3075 
3076  editWrapLine (c.line(), c.col());
3077 
3078  KateDocCursor cursor (c.line() + 1, pos, this);
3079  m_indenter->processNewline(cursor, true);
3080 
3081  c.setPos(cursor);
3082  }
3083  else
3084  {
3085  editWrapLine (c.line(), c.col());
3086  c.setPos(c.line() + 1, 0);
3087  }
3088 
3089  removeTrailingSpace( ln );
3090 
3091  editEnd();
3092 }
3093 
3094 void KateDocument::transpose( const KateTextCursor& cursor)
3095 {
3096  KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
3097 
3098  if (!textLine || (textLine->length() < 2))
3099  return;
3100 
3101  uint col = cursor.col();
3102 
3103  if (col > 0)
3104  col--;
3105 
3106  if ((textLine->length() - col) < 2)
3107  return;
3108 
3109  uint line = cursor.line();
3110  TQString s;
3111 
3112  //clever swap code if first character on the line swap right&left
3113  //otherwise left & right
3114  s.append (textLine->getChar(col+1));
3115  s.append (textLine->getChar(col));
3116  //do the swap
3117 
3118  // do it right, never ever manipulate a textline
3119  editStart ();
3120  editRemoveText (line, col, 2);
3121  editInsertText (line, col, s);
3122  editEnd ();
3123 }
3124 
3125 void KateDocument::backspace( KateView *view, const KateTextCursor& c )
3126 {
3127  if ( !view->config()->persistentSelection() && view->hasSelection() ) {
3128  view->removeSelectedText();
3129  return;
3130  }
3131 
3132  uint col = kMax( c.col(), 0 );
3133  uint line = kMax( c.line(), 0 );
3134 
3135  if ((col == 0) && (line == 0))
3136  return;
3137 
3138  int complement = 0;
3139  if (col > 0)
3140  {
3141  if (config()->configFlags() & KateDocument::cfAutoBrackets)
3142  {
3143  // if inside empty (), {}, [], '', "" delete both
3144  KateTextLine::Ptr tl = m_buffer->plainLine(line);
3145  if(!tl) return;
3146  TQChar prevChar = tl->getChar(col-1);
3147  TQChar nextChar = tl->getChar(col);
3148 
3149  if ( (prevChar == '"' && nextChar == '"') ||
3150  (prevChar == '\'' && nextChar == '\'') ||
3151  (prevChar == '(' && nextChar == ')') ||
3152  (prevChar == '[' && nextChar == ']') ||
3153  (prevChar == '{' && nextChar == '}') )
3154  {
3155  complement = 1;
3156  }
3157  }
3158  if (!(config()->configFlags() & KateDocument::cfBackspaceIndents))
3159  {
3160  // ordinary backspace
3161  //c.cursor.col--;
3162  removeText(line, col-1, line, col+complement);
3163  }
3164  else
3165  {
3166  // backspace indents: erase to next indent position
3167  KateTextLine::Ptr textLine = m_buffer->plainLine(line);
3168 
3169  // don't forget this check!!!! really!!!!
3170  if (!textLine)
3171  return;
3172 
3173  int colX = textLine->cursorX(col, config()->tabWidth());
3174  int pos = textLine->firstChar();
3175  if (pos > 0)
3176  pos = textLine->cursorX(pos, config()->tabWidth());
3177 
3178  if (pos < 0 || pos >= (int)colX)
3179  {
3180  // only spaces on left side of cursor
3181  indent( view, line, -1);
3182  }
3183  else
3184  removeText(line, col-1, line, col+complement);
3185  }
3186  }
3187  else
3188  {
3189  // col == 0: wrap to previous line
3190  if (line >= 1)
3191  {
3192  KateTextLine::Ptr textLine = m_buffer->plainLine(line-1);
3193 
3194  // don't forget this check!!!! really!!!!
3195  if (!textLine)
3196  return;
3197 
3198  if (config()->wordWrap() && textLine->endingWith(TQString::fromLatin1(" ")))
3199  {
3200  // gg: in hard wordwrap mode, backspace must also eat the trailing space
3201  removeText (line-1, textLine->length()-1, line, 0);
3202  }
3203  else
3204  removeText (line-1, textLine->length(), line, 0);
3205  }
3206  }
3207 
3208  emit backspacePressed();
3209 }
3210 
3211 void KateDocument::del( KateView *view, const KateTextCursor& c )
3212 {
3213  if ( !view->config()->persistentSelection() && view->hasSelection() ) {
3214  view->removeSelectedText();
3215  return;
3216  }
3217 
3218  if( c.col() < (int) m_buffer->plainLine(c.line())->length())
3219  {
3220  removeText(c.line(), c.col(), c.line(), c.col()+1);
3221  }
3222  else if ( (uint)c.line() < lastLine() )
3223  {
3224  removeText(c.line(), c.col(), c.line()+1, 0);
3225  }
3226 }
3227 
3228 void KateDocument::paste ( KateView* view )
3229 {
3230  TQString s = TQApplication::clipboard()->text();
3231 
3232  if (s.isEmpty())
3233  return;
3234 
3235  uint lines = s.contains (TQChar ('\n'));
3236 
3237  m_undoDontMerge = true;
3238 
3239  editStart ();
3240 
3241  if (!view->config()->persistentSelection() && view->hasSelection() )
3242  view->removeSelectedText();
3243 
3244  uint line = view->cursorLine ();
3245  uint column = view->cursorColumnReal ();
3246 
3247  insertText ( line, column, s, view->blockSelectionMode() );
3248 
3249  editEnd();
3250 
3251  // move cursor right for block select, as the user is moved right internal
3252  // even in that case, but user expects other behavior in block selection
3253  // mode !
3254  if (view->blockSelectionMode())
3255  view->setCursorPositionInternal (line+lines, column);
3256 
3257  if (m_indenter->canProcessLine()
3258  && config()->configFlags() & KateDocumentConfig::cfIndentPastedText)
3259  {
3260  editStart();
3261 
3262  KateDocCursor begin(line, 0, this);
3263  KateDocCursor end(line + lines, 0, this);
3264 
3265  m_indenter->processSection (begin, end);
3266 
3267  editEnd();
3268  }
3269 
3270  if (!view->blockSelectionMode()) emit charactersSemiInteractivelyInserted (line, column, s);
3271  m_undoDontMerge = true;
3272 }
3273 
3274 void KateDocument::insertIndentChars ( KateView *view )
3275 {
3276  editStart ();
3277 
3278  TQString s;
3279  if (config()->configFlags() & KateDocument::cfSpaceIndent)
3280  {
3281  int width = config()->indentationWidth();
3282  s.fill (' ', width - (view->cursorColumnReal() % width));
3283  }
3284  else
3285  s.append ('\t');
3286 
3287  insertText (view->cursorLine(), view->cursorColumnReal(), s);
3288 
3289  editEnd ();
3290 }
3291 
3292 void KateDocument::indent ( KateView *v, uint line, int change)
3293 {
3294  editStart ();
3295 
3296  if (!hasSelection())
3297  {
3298  // single line
3299  optimizeLeadingSpace(line, config()->configFlags(), change);
3300  }
3301  else
3302  {
3303  int sl = v->selStartLine();
3304  int el = v->selEndLine();
3305  int ec = v->selEndCol();
3306 
3307  if ((ec == 0) && ((el-1) >= 0))
3308  {
3309  el--; /* */
3310  }
3311 
3312  if (config()->configFlags() & KateDocument::cfKeepIndentProfile && change < 0) {
3313  // unindent so that the existing indent profile doesn't get screwed
3314  // if any line we may unindent is already full left, don't do anything
3315  int adjustedChange = -change;
3316 
3317  for (line = sl; (int) line <= el && adjustedChange > 0; line++) {
3318  KateTextLine::Ptr textLine = m_buffer->plainLine(line);
3319  int firstChar = textLine->firstChar();
3320  if (firstChar >= 0 && (v->lineSelected(line) || v->lineHasSelected(line))) {
3321  int maxUnindent = textLine->cursorX(firstChar, config()->tabWidth()) / config()->indentationWidth();
3322  if (maxUnindent < adjustedChange)
3323  adjustedChange = maxUnindent;
3324  }
3325  }
3326 
3327  change = -adjustedChange;
3328  }
3329 
3330  const bool rts = config()->configFlags() & KateDocumentConfig::cfRemoveTrailingDyn;
3331  for (line = sl; (int) line <= el; line++) {
3332  if ((v->lineSelected(line) || v->lineHasSelected(line))
3333  && (!rts || lineLength(line) > 0)) {
3334  optimizeLeadingSpace(line, config()->configFlags(), change);
3335  }
3336  }
3337  }
3338 
3339  editEnd ();
3340 }
3341 
3342 void KateDocument::align(KateView *view, uint line)
3343 {
3344  if (m_indenter->canProcessLine())
3345  {
3346  editStart ();
3347 
3348  if (!view->hasSelection())
3349  {
3350  KateDocCursor curLine(line, 0, this);
3351  m_indenter->processLine (curLine);
3352  editEnd ();
3353  activeView()->setCursorPosition (line, curLine.col());
3354  }
3355  else
3356  {
3357  m_indenter->processSection (view->selStart(), view->selEnd());
3358  editEnd ();
3359  }
3360  }
3361 }
3362 
3363 /*
3364  Optimize the leading whitespace for a single line.
3365  If change is > 0, it adds indentation units (indentationChars)
3366  if change is == 0, it only optimizes
3367  If change is < 0, it removes indentation units
3368  This will be used to indent, unindent, and optimal-fill a line.
3369  If excess space is removed depends on the flag cfKeepExtraSpaces
3370  which has to be set by the user
3371 */
3372 void KateDocument::optimizeLeadingSpace(uint line, int flags, int change)
3373 {
3374  KateTextLine::Ptr textline = m_buffer->plainLine(line);
3375 
3376  int first_char = textline->firstChar();
3377 
3378  int w = 0;
3379  if (flags & KateDocument::cfSpaceIndent)
3380  w = config()->indentationWidth();
3381  else
3382  w = config()->tabWidth();
3383 
3384  if (first_char < 0)
3385  first_char = textline->length();
3386 
3387  int space = textline->cursorX(first_char, config()->tabWidth()) + change * w;
3388  if (space < 0)
3389  space = 0;
3390 
3391  if (!(flags & KateDocument::cfKeepExtraSpaces))
3392  {
3393  uint extra = space % w;
3394 
3395  space -= extra;
3396  if (extra && change < 0) {
3397  // otherwise it unindents too much (e.g. 12 chars when indentation is 8 chars wide)
3398  space += w;
3399  }
3400  }
3401 
3402  //kdDebug(13020) << "replace With Op: " << line << " " << first_char << " " << space << endl;
3403  replaceWithOptimizedSpace(line, first_char, space, flags);
3404 }
3405 
3406 void KateDocument::replaceWithOptimizedSpace(uint line, uint upto_column, uint space, int flags)
3407 {
3408  uint length;
3409  TQString new_space;
3410 
3411  if (flags & KateDocument::cfSpaceIndent && ! (flags & KateDocumentConfig::cfMixedIndent) ) {
3412  length = space;
3413  new_space.fill(' ', length);
3414  }
3415  else {
3416  length = space / config()->tabWidth();
3417  new_space.fill('\t', length);
3418 
3419  TQString extra_space;
3420  extra_space.fill(' ', space % config()->tabWidth());
3421  length += space % config()->tabWidth();
3422  new_space += extra_space;
3423  }
3424 
3425  KateTextLine::Ptr textline = m_buffer->plainLine(line);
3426  uint change_from;
3427  for (change_from = 0; change_from < upto_column && change_from < length; change_from++) {
3428  if (textline->getChar(change_from) != new_space[change_from])
3429  break;
3430  }
3431 
3432  editStart();
3433 
3434  if (change_from < upto_column)
3435  removeText(line, change_from, line, upto_column);
3436 
3437  if (change_from < length)
3438  insertText(line, change_from, new_space.right(length - change_from));
3439 
3440  editEnd();
3441 }
3442 
3443 /*
3444  Remove a given string at the begining
3445  of the current line.
3446 */
3447 bool KateDocument::removeStringFromBegining(int line, TQString &str)
3448 {
3449  KateTextLine::Ptr textline = m_buffer->plainLine(line);
3450 
3451  int index = 0;
3452  bool there = false;
3453 
3454  if (textline->startingWith(str))
3455  there = true;
3456  else
3457  {
3458  index = textline->firstChar ();
3459 
3460  if ((index >= 0) && (textline->length() >= (index + str.length())) && (textline->string(index, str.length()) == str))
3461  there = true;
3462  }
3463 
3464  if (there)
3465  {
3466  // Remove some chars
3467  removeText (line, index, line, index+str.length());
3468  }
3469 
3470  return there;
3471 }
3472 
3473 /*
3474  Remove a given string at the end
3475  of the current line.
3476 */
3477 bool KateDocument::removeStringFromEnd(int line, TQString &str)
3478 {
3479  KateTextLine::Ptr textline = m_buffer->plainLine(line);
3480 
3481  int index = 0;
3482  bool there = false;
3483 
3484  if(textline->endingWith(str))
3485  {
3486  index = textline->length() - str.length();
3487  there = true;
3488  }
3489  else
3490  {
3491  index = textline->lastChar ()-str.length()+1;
3492 
3493  if ((index >= 0) && (textline->length() >= (index + str.length())) && (textline->string(index, str.length()) == str))
3494  there = true;
3495  }
3496 
3497  if (there)
3498  {
3499  // Remove some chars
3500  removeText (line, index, line, index+str.length());
3501  }
3502 
3503  return there;
3504 }
3505 
3506 /*
3507  Add to the current line a comment line mark at
3508  the begining.
3509 */
3510 void KateDocument::addStartLineCommentToSingleLine( int line, int attrib )
3511 {
3512  if (highlight()->getCommentSingleLinePosition(attrib)==KateHighlighting::CSLPosColumn0)
3513  {
3514  TQString commentLineMark = highlight()->getCommentSingleLineStart( attrib ) + " ";
3515  insertText (line, 0, commentLineMark);
3516  }
3517  else
3518  {
3519  TQString commentLineMark=highlight()->getCommentSingleLineStart(attrib);
3520  KateTextLine::Ptr l = m_buffer->line(line);
3521  int pos=l->firstChar();
3522  if (pos >=0)
3523  insertText(line,pos,commentLineMark);
3524  }
3525 }
3526 
3527 /*
3528  Remove from the current line a comment line mark at
3529  the begining if there is one.
3530 */
3531 bool KateDocument::removeStartLineCommentFromSingleLine( int line, int attrib )
3532 {
3533  TQString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
3534  TQString longCommentMark = shortCommentMark + " ";
3535 
3536  editStart();
3537 
3538  // Try to remove the long comment mark first
3539  bool removed = (removeStringFromBegining(line, longCommentMark)
3540  || removeStringFromBegining(line, shortCommentMark));
3541 
3542  editEnd();
3543 
3544  return removed;
3545 }
3546 
3547 /*
3548  Add to the current line a start comment mark at the
3549  begining and a stop comment mark at the end.
3550 */
3551 void KateDocument::addStartStopCommentToSingleLine( int line, int attrib )
3552 {
3553  TQString startCommentMark = highlight()->getCommentStart( attrib ) + " ";
3554  TQString stopCommentMark = " " + highlight()->getCommentEnd( attrib );
3555 
3556  editStart();
3557 
3558  // Add the start comment mark
3559  insertText (line, 0, startCommentMark);
3560 
3561  // Go to the end of the line
3562  int col = m_buffer->plainLine(line)->length();
3563 
3564  // Add the stop comment mark
3565  insertText (line, col, stopCommentMark);
3566 
3567  editEnd();
3568 }
3569 
3570 /*
3571  Remove from the current line a start comment mark at
3572  the begining and a stop comment mark at the end.
3573 */
3574 bool KateDocument::removeStartStopCommentFromSingleLine( int line, int attrib )
3575 {
3576  TQString shortStartCommentMark = highlight()->getCommentStart( attrib );
3577  TQString longStartCommentMark = shortStartCommentMark + " ";
3578  TQString shortStopCommentMark = highlight()->getCommentEnd( attrib );
3579  TQString longStopCommentMark = " " + shortStopCommentMark;
3580 
3581  editStart();
3582 
3583 #ifdef __GNUC__
3584 #warning "that's a bad idea, can lead to stray endings, FIXME"
3585 #endif
3586  // Try to remove the long start comment mark first
3587  bool removedStart = (removeStringFromBegining(line, longStartCommentMark)
3588  || removeStringFromBegining(line, shortStartCommentMark));
3589 
3590  bool removedStop = false;
3591  if (removedStart)
3592  {
3593  // Try to remove the long stop comment mark first
3594  removedStop = (removeStringFromEnd(line, longStopCommentMark)
3595  || removeStringFromEnd(line, shortStopCommentMark));
3596  }
3597 
3598  editEnd();
3599 
3600  return (removedStart || removedStop);
3601 }
3602 
3603 /*
3604  Add to the current selection a start comment
3605  mark at the begining and a stop comment mark
3606  at the end.
3607 */
3608 void KateDocument::addStartStopCommentToSelection( KateView *view, int attrib )
3609 {
3610  TQString startComment = highlight()->getCommentStart( attrib );
3611  TQString endComment = highlight()->getCommentEnd( attrib );
3612 
3613  int sl = view->selStartLine();
3614  int el = view->selEndLine();
3615  int sc = view->selStartCol();
3616  int ec = view->selEndCol();
3617 
3618  if ((ec == 0) && ((el-1) >= 0))
3619  {
3620  el--;
3621  ec = m_buffer->plainLine (el)->length();
3622  }
3623 
3624  editStart();
3625 
3626  insertText (el, ec, endComment);
3627  insertText (sl, sc, startComment);
3628 
3629  editEnd ();
3630 
3631  // Set the new selection
3632  ec += endComment.length() + ( (el == sl) ? startComment.length() : 0 );
3633  view->setSelection(sl, sc, el, ec);
3634 }
3635 
3636 /*
3637  Add to the current selection a comment line
3638  mark at the begining of each line.
3639 */
3640 void KateDocument::addStartLineCommentToSelection( KateView *view, int attrib )
3641 {
3642  TQString commentLineMark = highlight()->getCommentSingleLineStart( attrib ) + " ";
3643 
3644  int sl = view->selStartLine();
3645  int el = view->selEndLine();
3646 
3647  if ((view->selEndCol() == 0) && ((el-1) >= 0))
3648  {
3649  el--;
3650  }
3651 
3652  editStart();
3653 
3654  // For each line of the selection
3655  for (int z = el; z >= sl; z--) {
3656  //insertText (z, 0, commentLineMark);
3657  addStartLineCommentToSingleLine(z, attrib );
3658  }
3659 
3660  editEnd ();
3661 
3662  // Set the new selection
3663 
3664  KateDocCursor end (view->selEnd());
3665  end.setCol(view->selEndCol() + ((el == view->selEndLine()) ? commentLineMark.length() : 0) );
3666 
3667  view->setSelection(view->selStartLine(), 0, end.line(), end.col());
3668 }
3669 
3670 bool KateDocument::nextNonSpaceCharPos(int &line, int &col)
3671 {
3672  for(; line < (int)m_buffer->count(); line++) {
3673  KateTextLine::Ptr textLine = m_buffer->plainLine(line);
3674 
3675  if (!textLine)
3676  break;
3677 
3678  col = textLine->nextNonSpaceChar(col);
3679  if(col != -1)
3680  return true; // Next non-space char found
3681  col = 0;
3682  }
3683  // No non-space char found
3684  line = -1;
3685  col = -1;
3686  return false;
3687 }
3688 
3689 bool KateDocument::previousNonSpaceCharPos(int &line, int &col)
3690 {
3691  while(true)
3692  {
3693  KateTextLine::Ptr textLine = m_buffer->plainLine(line);
3694 
3695  if (!textLine)
3696  break;
3697 
3698  col = textLine->previousNonSpaceChar(col);
3699  if(col != -1) return true;
3700  if(line == 0) return false;
3701  --line;
3702  col = textLine->length();
3703 }
3704  // No non-space char found
3705  line = -1;
3706  col = -1;
3707  return false;
3708 }
3709 
3710 /*
3711  Remove from the selection a start comment mark at
3712  the begining and a stop comment mark at the end.
3713 */
3714 bool KateDocument::removeStartStopCommentFromSelection( KateView *view, int attrib )
3715 {
3716  TQString startComment = highlight()->getCommentStart( attrib );
3717  TQString endComment = highlight()->getCommentEnd( attrib );
3718 
3719  int sl = kMax<int> (0, view->selStartLine());
3720  int el = kMin<int> (view->selEndLine(), lastLine());
3721  int sc = view->selStartCol();
3722  int ec = view->selEndCol();
3723 
3724  // The selection ends on the char before selectEnd
3725  if (ec != 0) {
3726  ec--;
3727  } else {
3728  if (el > 0) {
3729  el--;
3730  ec = m_buffer->plainLine(el)->length() - 1;
3731  }
3732  }
3733 
3734  int startCommentLen = startComment.length();
3735  int endCommentLen = endComment.length();
3736 
3737  // had this been perl or sed: s/^\s*$startComment(.+?)$endComment\s*/$1/
3738 
3739  bool remove = nextNonSpaceCharPos(sl, sc)
3740  && m_buffer->plainLine(sl)->stringAtPos(sc, startComment)
3741  && previousNonSpaceCharPos(el, ec)
3742  && ( (ec - endCommentLen + 1) >= 0 )
3743  && m_buffer->plainLine(el)->stringAtPos(ec - endCommentLen + 1, endComment);
3744 
3745  if (remove) {
3746  editStart();
3747 
3748  removeText (el, ec - endCommentLen + 1, el, ec + 1);
3749  removeText (sl, sc, sl, sc + startCommentLen);
3750 
3751  editEnd ();
3752  // set new selection not necessary, as the selection cursors are KateSuperCursors
3753  }
3754 
3755  return remove;
3756 }
3757 
3758 bool KateDocument::removeStartStopCommentFromRegion(const KateTextCursor &start,const KateTextCursor &end,int attrib)
3759 {
3760  TQString startComment = highlight()->getCommentStart( attrib );
3761  TQString endComment = highlight()->getCommentEnd( attrib );
3762  int startCommentLen = startComment.length();
3763  int endCommentLen = endComment.length();
3764 
3765  bool remove = m_buffer->plainLine(start.line())->stringAtPos(start.col(), startComment)
3766  && ( (end.col() - endCommentLen ) >= 0 )
3767  && m_buffer->plainLine(end.line())->stringAtPos(end.col() - endCommentLen , endComment);
3768  if (remove) {
3769  editStart();
3770  removeText(end.line(),end.col()-endCommentLen,end.line(),end.col());
3771  removeText(start.line(),start.col(),start.line(),start.col()+startCommentLen);
3772  editEnd();
3773  }
3774  return remove;
3775 }
3776 
3777 /*
3778  Remove from the begining of each line of the
3779  selection a start comment line mark.
3780 */
3781 bool KateDocument::removeStartLineCommentFromSelection( KateView *view, int attrib )
3782 {
3783  TQString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
3784  TQString longCommentMark = shortCommentMark + " ";
3785 
3786  int sl = view->selStartLine();
3787  int el = view->selEndLine();
3788 
3789  if ((view->selEndCol() == 0) && ((el-1) >= 0))
3790  {
3791  el--;
3792  }
3793 
3794  // Find out how many char will be removed from the last line
3795  int removeLength = 0;
3796  if (m_buffer->plainLine(el)->startingWith(longCommentMark))
3797  removeLength = longCommentMark.length();
3798  else if (m_buffer->plainLine(el)->startingWith(shortCommentMark))
3799  removeLength = shortCommentMark.length();
3800 
3801  bool removed = false;
3802 
3803  editStart();
3804 
3805  // For each line of the selection
3806  for (int z = el; z >= sl; z--)
3807  {
3808  // Try to remove the long comment mark first
3809  removed = (removeStringFromBegining(z, longCommentMark)
3810  || removeStringFromBegining(z, shortCommentMark)
3811  || removed);
3812  }
3813 
3814  editEnd();
3815  // updating selection already done by the KateSuperCursors
3816  return removed;
3817 }
3818 
3819 /*
3820  Comment or uncomment the selection or the current
3821  line if there is no selection.
3822 */
3823 void KateDocument::comment( KateView *v, uint line,uint column, int change)
3824 {
3825  // We need to check that we can sanely comment the selectino or region.
3826  // It is if the attribute of the first and last character of the range to
3827  // comment belongs to the same language definition.
3828  // for lines with no text, we need the attribute for the lines context.
3829  bool hassel = v->hasSelection();
3830  int startAttrib, endAttrib;
3831  if ( hassel )
3832  {
3833  KateTextLine::Ptr ln = kateTextLine( v->selStartLine() );
3834  int l = v->selStartLine(), c = v->selStartCol();
3835  startAttrib = nextNonSpaceCharPos( l, c ) ? kateTextLine( l )->attribute( c ) : 0;
3836 
3837  ln = kateTextLine( v->selEndLine() );
3838  l = v->selEndLine(), c = v->selEndCol();
3839  endAttrib = previousNonSpaceCharPos( l, c ) ? kateTextLine( l )->attribute( c ) : 0;
3840  }
3841  else
3842  {
3843  KateTextLine::Ptr ln = kateTextLine( line );
3844  if ( ln->length() )
3845  {
3846  startAttrib = ln->attribute( ln->firstChar() );
3847  endAttrib = ln->attribute( ln->lastChar() );
3848  }
3849  else
3850  {
3851  int l = line, c = 0;
3852  if ( nextNonSpaceCharPos( l, c ) || previousNonSpaceCharPos( l, c ) )
3853  startAttrib = endAttrib = kateTextLine( l )->attribute( c );
3854  else
3855  startAttrib = endAttrib = 0;
3856  }
3857  }
3858 
3859  if ( ! highlight()->canComment( startAttrib, endAttrib ) )
3860  {
3861  kdDebug(13020)<<"canComment( "<<startAttrib<<", "<<endAttrib<<" ) returned false!"<<endl;
3862  return;
3863  }
3864 
3865  bool hasStartLineCommentMark = !(highlight()->getCommentSingleLineStart( startAttrib ).isEmpty());
3866  bool hasStartStopCommentMark = ( !(highlight()->getCommentStart( startAttrib ).isEmpty())
3867  && !(highlight()->getCommentEnd( endAttrib ).isEmpty()) );
3868 
3869  bool removed = false;
3870 
3871  if (change > 0) // comment
3872  {
3873  if ( !hassel )
3874  {
3875  if ( hasStartLineCommentMark )
3876  addStartLineCommentToSingleLine( line, startAttrib );
3877  else if ( hasStartStopCommentMark )
3878  addStartStopCommentToSingleLine( line, startAttrib );
3879  }
3880  else
3881  {
3882  // anders: prefer single line comment to avoid nesting probs
3883  // If the selection starts after first char in the first line
3884  // or ends before the last char of the last line, we may use
3885  // multiline comment markers.
3886  // TODO We should try to detect nesting.
3887  // - if selection ends at col 0, most likely she wanted that
3888  // line ignored
3889  if ( hasStartStopCommentMark &&
3890  ( !hasStartLineCommentMark || (
3891  ( v->selStartCol() > m_buffer->plainLine( v->selStartLine() )->firstChar() ) ||
3892  ( v->selEndCol() < ((int)m_buffer->plainLine( v->selEndLine() )->length()) )
3893  ) ) )
3894  addStartStopCommentToSelection( v, startAttrib );
3895  else if ( hasStartLineCommentMark )
3896  addStartLineCommentToSelection( v, startAttrib );
3897  }
3898  }
3899  else // uncomment
3900  {
3901  if ( !hassel )
3902  {
3903  removed = ( hasStartLineCommentMark
3904  && removeStartLineCommentFromSingleLine( line, startAttrib ) )
3905  || ( hasStartStopCommentMark
3906  && removeStartStopCommentFromSingleLine( line, startAttrib ) );
3907  if ((!removed) && foldingTree()) {
3908  kdDebug(13020)<<"easy approach for uncommenting did not work, trying harder (folding tree)"<<endl;
3909  int commentRegion=(highlight()->commentRegion(startAttrib));
3910  if (commentRegion){
3911  KateCodeFoldingNode *n=foldingTree()->findNodeForPosition(line,column);
3912  if (n) {
3913  KateTextCursor start,end;
3914  if ((n->nodeType()==commentRegion) && n->getBegin(foldingTree(), &start) && n->getEnd(foldingTree(), &end)) {
3915  kdDebug(13020)<<"Enclosing region found:"<<start.col()<<"/"<<start.line()<<"-"<<end.col()<<"/"<<end.line()<<endl;
3916  removeStartStopCommentFromRegion(start,end,startAttrib);
3917  } else {
3918  kdDebug(13020)<<"Enclosing region found, but not valid"<<endl;
3919  kdDebug(13020)<<"Region found: "<<n->nodeType()<<" region needed: "<<commentRegion<<endl;
3920  }
3921  //perhaps nested regions should be hadled here too...
3922  } else kdDebug(13020)<<"No enclosing region found"<<endl;
3923  } else kdDebug(13020)<<"No comment region specified for current hl"<<endl;
3924  }
3925  }
3926  else
3927  {
3928  // anders: this seems like it will work with above changes :)
3929  removed = ( hasStartLineCommentMark
3930  && removeStartLineCommentFromSelection( v, startAttrib ) )
3931  || ( hasStartStopCommentMark
3932  && removeStartStopCommentFromSelection( v, startAttrib ) );
3933  }
3934  }
3935 }
3936 
3937 void KateDocument::transform( KateView *v, const KateTextCursor &c,
3938  KateDocument::TextTransform t )
3939 {
3940  editStart();
3941  uint cl( c.line() ), cc( c.col() );
3942  bool selectionRestored = false;
3943 
3944  if ( hasSelection() )
3945  {
3946  // cache the selection and cursor, so we can be sure to restore.
3947  KateTextCursor selstart = v->selStart();
3948  KateTextCursor selend = v->selEnd();
3949 
3950  int ln = v->selStartLine();
3951  while ( ln <= selend.line() )
3952  {
3953  uint start, end;
3954  start = (ln == selstart.line() || v->blockSelectionMode()) ?
3955  selstart.col() : 0;
3956  end = (ln == selend.line() || v->blockSelectionMode()) ?
3957  selend.col() : lineLength( ln );
3958  if ( start > end )
3959  {
3960  uint t = start;
3961  start = end;
3962  end = t;
3963  }
3964  TQString s = text( ln, start, ln, end );
3965  TQString o = s;
3966 
3967  if ( t == Uppercase )
3968  s = s.upper();
3969  else if ( t == Lowercase )
3970  s = s.lower();
3971  else // Capitalize
3972  {
3973  KateTextLine::Ptr l = m_buffer->plainLine( ln );
3974  uint p ( 0 );
3975  while( p < s.length() )
3976  {
3977  // If bol or the character before is not in a word, up this one:
3978  // 1. if both start and p is 0, upper char.
3979  // 2. if blockselect or first line, and p == 0 and start-1 is not in a word, upper
3980  // 3. if p-1 is not in a word, upper.
3981  if ( ( ! start && ! p ) ||
3982  ( ( ln == selstart.line() || v->blockSelectionMode() ) &&
3983  ! p && ! highlight()->isInWord( l->getChar( start - 1 )) ) ||
3984  ( p && ! highlight()->isInWord( s.at( p-1 ) ) )
3985  )
3986  s[p] = s.at(p).upper();
3987  p++;
3988  }
3989  }
3990 
3991  if ( o != s )
3992  {
3993  removeText( ln, start, ln, end );
3994  insertText( ln, start, s );
3995  }
3996 
3997  ln++;
3998  }
3999 
4000  // restore selection
4001  v->setSelection( selstart, selend );
4002  selectionRestored = true;
4003 
4004  } else { // no selection
4005  TQString o = text( cl, cc, cl, cc + 1 );
4006  TQString s;
4007  int n ( cc );
4008  switch ( t ) {
4009  case Uppercase:
4010  s = o.upper();
4011  break;
4012  case Lowercase:
4013  s = o.lower();
4014  break;
4015  case Capitalize:
4016  {
4017  KateTextLine::Ptr l = m_buffer->plainLine( cl );
4018  while ( n > 0 && highlight()->isInWord( l->getChar( n-1 ), l->attribute( n-1 ) ) )
4019  n--;
4020  o = text( cl, n, cl, n + 1 );
4021  s = o.upper();
4022  }
4023  break;
4024  default:
4025  break;
4026  }
4027 
4028  if ( s != o )
4029  {
4030  removeText( cl, n, cl, n+1 );
4031  insertText( cl, n, s );
4032  }
4033  }
4034  editEnd();
4035 
4036  if ( ! selectionRestored )
4037  v->setCursorPosition( cl, cc );
4038 }
4039 
4040 void KateDocument::joinLines( uint first, uint last )
4041 {
4042 // if ( first == last ) last += 1;
4043  editStart();
4044  int line( first );
4045  while ( first < last )
4046  {
4047  // Normalize the whitespace in the joined lines by making sure there's
4048  // always exactly one space between the joined lines
4049  // This cannot be done in editUnwrapLine, because we do NOT want this
4050  // behaviour when deleting from the start of a line, just when explicitly
4051  // calling the join command
4052  KateTextLine::Ptr l = m_buffer->line( line );
4053  KateTextLine::Ptr tl = m_buffer->line( line + 1 );
4054 
4055  if ( !l || !tl )
4056  {
4057  editEnd();
4058  return;
4059  }
4060 
4061  int pos = tl->firstChar();
4062  if ( pos >= 0 )
4063  {
4064  if (pos != 0)
4065  editRemoveText( line + 1, 0, pos );
4066  if ( !( l->length() == 0 || l->getChar( l->length() - 1 ).isSpace() ) )
4067  editInsertText( line + 1, 0, " " );
4068  }
4069  else
4070  {
4071  // Just remove the whitespace and let Kate handle the rest
4072  editRemoveText( line + 1, 0, tl->length() );
4073  }
4074 
4075  editUnWrapLine( line );
4076  first++;
4077  }
4078  editEnd();
4079 }
4080 
4081 TQString KateDocument::getWord( const KateTextCursor& cursor ) {
4082  int start, end, len;
4083 
4084  KateTextLine::Ptr textLine = m_buffer->plainLine(cursor.line());
4085  len = textLine->length();
4086  start = end = cursor.col();
4087  if (start > len) // Probably because of non-wrapping cursor mode.
4088  return TQString("");
4089 
4090  while (start > 0 && highlight()->isInWord(textLine->getChar(start - 1), textLine->attribute(start - 1))) start--;
4091  while (end < len && highlight()->isInWord(textLine->getChar(end), textLine->attribute(end))) end++;
4092  len = end - start;
4093  return TQString(&textLine->text()[start], len);
4094 }
4095 
4096 void KateDocument::tagLines(int start, int end)
4097 {
4098  for (uint z = 0; z < m_views.count(); z++)
4099  m_views.at(z)->tagLines (start, end, true);
4100 }
4101 
4102 void KateDocument::tagLines(KateTextCursor start, KateTextCursor end)
4103 {
4104  // May need to switch start/end cols if in block selection mode
4105  if (blockSelectionMode() && start.col() > end.col()) {
4106  int sc = start.col();
4107  start.setCol(end.col());
4108  end.setCol(sc);
4109  }
4110 
4111  for (uint z = 0; z < m_views.count(); z++)
4112  m_views.at(z)->tagLines(start, end, true);
4113 }
4114 
4115 void KateDocument::repaintViews(bool paintOnlyDirty)
4116 {
4117  for (uint z = 0; z < m_views.count(); z++)
4118  m_views.at(z)->repaintText(paintOnlyDirty);
4119 }
4120 
4121 void KateDocument::tagAll()
4122 {
4123  for (uint z = 0; z < m_views.count(); z++)
4124  {
4125  m_views.at(z)->tagAll();
4126  m_views.at(z)->updateView (true);
4127  }
4128 }
4129 
4130 uint KateDocument::configFlags ()
4131 {
4132  return config()->configFlags();
4133 }
4134 
4135 void KateDocument::setConfigFlags (uint flags)
4136 {
4137  config()->setConfigFlags(flags);
4138 }
4139 
4140 inline bool isStartBracket( const TQChar& c ) { return c == '{' || c == '[' || c == '('; }
4141 inline bool isEndBracket ( const TQChar& c ) { return c == '}' || c == ']' || c == ')'; }
4142 inline bool isBracket ( const TQChar& c ) { return isStartBracket( c ) || isEndBracket( c ); }
4143 
4144 /*
4145  Bracket matching uses the following algorithm:
4146  If in overwrite mode, match the bracket currently underneath the cursor.
4147  Otherwise, if the character to the right of the cursor is an starting bracket,
4148  match it. Otherwise if the character to the left of the cursor is a
4149  ending bracket, match it. Otherwise, if the the character to the left
4150  of the cursor is an starting bracket, match it. Otherwise, if the character
4151  to the right of the cursor is an ending bracket, match it. Otherwise, don't
4152  match anything.
4153 */
4154 void KateDocument::newBracketMark( const KateTextCursor& cursor, KateBracketRange& bm, int maxLines )
4155 {
4156  bm.setValid(false);
4157 
4158  bm.start() = cursor;
4159 
4160  if( !findMatchingBracket( bm.start(), bm.end(), maxLines ) )
4161  return;
4162 
4163  bm.setValid(true);
4164 
4165  const int tw = config()->tabWidth();
4166  const int indentStart = m_buffer->plainLine(bm.start().line())->indentDepth(tw);
4167  const int indentEnd = m_buffer->plainLine(bm.end().line())->indentDepth(tw);
4168  bm.setIndentMin(kMin(indentStart, indentEnd));
4169 }
4170 
4171 bool KateDocument::findMatchingBracket( KateTextCursor& start, KateTextCursor& end, int maxLines )
4172 {
4173  KateTextLine::Ptr textLine = m_buffer->plainLine( start.line() );
4174  if( !textLine )
4175  return false;
4176 
4177  TQChar right = textLine->getChar( start.col() );
4178  TQChar left = textLine->getChar( start.col() - 1 );
4179  TQChar bracket;
4180 
4181  if ( config()->configFlags() & cfOvr ) {
4182  if( isBracket( right ) ) {
4183  bracket = right;
4184  } else {
4185  return false;
4186  }
4187  } else if ( isStartBracket( right ) ) {
4188  bracket = right;
4189  } else if ( isEndBracket( left ) ) {
4190  start.setCol(start.col() - 1);
4191  bracket = left;
4192  } else if ( isBracket( left ) ) {
4193  start.setCol(start.col() - 1);
4194  bracket = left;
4195  } else if ( isBracket( right ) ) {
4196  bracket = right;
4197  } else {
4198  return false;
4199  }
4200 
4201  TQChar opposite;
4202 
4203  switch( bracket ) {
4204  case '{': opposite = '}'; break;
4205  case '}': opposite = '{'; break;
4206  case '[': opposite = ']'; break;
4207  case ']': opposite = '['; break;
4208  case '(': opposite = ')'; break;
4209  case ')': opposite = '('; break;
4210  default: return false;
4211  }
4212 
4213  bool forward = isStartBracket( bracket );
4214  int startAttr = textLine->attribute( start.col() );
4215  uint count = 0;
4216  int lines = 0;
4217  end = start;
4218 
4219  while( true ) {
4220  /* Increment or decrement, check base cases */
4221  if( forward ) {
4222  end.setCol(end.col() + 1);
4223  if( end.col() >= lineLength( end.line() ) ) {
4224  if( end.line() >= (int)lastLine() )
4225  return false;
4226  end.setPos(end.line() + 1, 0);
4227  textLine = m_buffer->plainLine( end.line() );
4228  lines++;
4229  }
4230  } else {
4231  end.setCol(end.col() - 1);
4232  if( end.col() < 0 ) {
4233  if( end.line() <= 0 )
4234  return false;
4235  end.setLine(end.line() - 1);
4236  end.setCol(lineLength( end.line() ) - 1);
4237  textLine = m_buffer->plainLine( end.line() );
4238  lines++;
4239  }
4240  }
4241 
4242  if ((maxLines != -1) && (lines > maxLines))
4243  return false;
4244 
4245  /* Easy way to skip comments */
4246  if( textLine->attribute( end.col() ) != startAttr )
4247  continue;
4248 
4249  /* Check for match */
4250  TQChar c = textLine->getChar( end.col() );
4251  if( c == bracket ) {
4252  count++;
4253  } else if( c == opposite ) {
4254  if( count == 0 )
4255  return true;
4256  count--;
4257  }
4258 
4259  }
4260 }
4261 
4262 void KateDocument::guiActivateEvent( KParts::GUIActivateEvent *ev )
4263 {
4264  KParts::ReadWritePart::guiActivateEvent( ev );
4265  if ( ev->activated() )
4266  emit selectionChanged();
4267 }
4268 
4269 void KateDocument::setDocName (TQString name )
4270 {
4271  if ( name == m_docName )
4272  return;
4273 
4274  if ( !name.isEmpty() )
4275  {
4276  // TODO check for similarly named documents
4277  m_docName = name;
4278  updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
4279  emit nameChanged((Kate::Document *) this);
4280  return;
4281  }
4282 
4283  // if the name is set, and starts with FILENAME, it should not be changed!
4284  if ( ! url().isEmpty() && m_docName.startsWith( url().filename() ) ) return;
4285 
4286  int count = -1;
4287 
4288  for (uint z=0; z < KateFactory::self()->documents()->count(); z++)
4289  {
4290  if ( (KateFactory::self()->documents()->at(z) != this) && (KateFactory::self()->documents()->at(z)->url().filename() == url().filename()) )
4291  if ( KateFactory::self()->documents()->at(z)->m_docNameNumber > count )
4292  count = KateFactory::self()->documents()->at(z)->m_docNameNumber;
4293  }
4294 
4295  m_docNameNumber = count + 1;
4296 
4297  m_docName = url().filename();
4298 
4299  if (m_docName.isEmpty())
4300  m_docName = i18n ("Untitled");
4301 
4302  if (m_docNameNumber > 0)
4303  m_docName = TQString(m_docName + " (%1)").arg(m_docNameNumber+1);
4304 
4305  updateFileType (KateFactory::self()->fileTypeManager()->fileType (this));
4306  emit nameChanged ((Kate::Document *) this);
4307 }
4308 
4309 void KateDocument::slotModifiedOnDisk( Kate::View * /*v*/ )
4310 {
4311  if ( m_isasking < 0 )
4312  {
4313  m_isasking = 0;
4314  return;
4315  }
4316 
4317  if ( !s_fileChangedDialogsActivated || m_isasking )
4318  return;
4319 
4320  if (m_modOnHd && !url().isEmpty())
4321  {
4322  m_isasking = 1;
4323 
4324  KateModOnHdPrompt p( this, m_modOnHdReason, reasonedMOHString(), widget() );
4325  switch ( p.exec() )
4326  {
4327  case KateModOnHdPrompt::Save:
4328  {
4329  m_modOnHd = false;
4330  KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveURLAndEncoding(config()->encoding(),
4331  url().url(),TQString::null,widget(),i18n("Save File"));
4332 
4333  kdDebug(13020)<<"got "<<res.URLs.count()<<" URLs"<<endl;
4334  if( ! res.URLs.isEmpty() && ! res.URLs.first().isEmpty() && checkOverwrite( res.URLs.first() ) )
4335  {
4336  setEncoding( res.encoding );
4337 
4338  if( ! saveAs( res.URLs.first() ) )
4339  {
4340  KMessageBox::error( widget(), i18n("Save failed") );
4341  m_modOnHd = true;
4342  }
4343  else
4344  emit modifiedOnDisc( this, false, 0 );
4345  }
4346  else // the save as dialog was cancelled, we are still modified on disk
4347  {
4348  m_modOnHd = true;
4349  }
4350 
4351  m_isasking = 0;
4352  break;
4353  }
4354 
4355  case KateModOnHdPrompt::Reload:
4356  m_modOnHd = false;
4357  emit modifiedOnDisc( this, false, 0 );
4358  reloadFile();
4359  m_isasking = 0;
4360  break;
4361 
4362  case KateModOnHdPrompt::Ignore:
4363  m_modOnHd = false;
4364  emit modifiedOnDisc( this, false, 0 );
4365  m_isasking = 0;
4366  break;
4367 
4368  case KateModOnHdPrompt::Overwrite:
4369  m_modOnHd = false;
4370  emit modifiedOnDisc( this, false, 0 );
4371  m_isasking = 0;
4372  save();
4373  break;
4374 
4375  default: // cancel: ignore next focus event
4376  m_isasking = -1;
4377  }
4378  }
4379 }
4380 
4381 void KateDocument::setModifiedOnDisk( int reason )
4382 {
4383  m_modOnHdReason = reason;
4384  m_modOnHd = (reason > 0);
4385  emit modifiedOnDisc( this, (reason > 0), reason );
4386 }
4387 
4388 class KateDocumentTmpMark
4389 {
4390  public:
4391  TQString line;
4392  KTextEditor::Mark mark;
4393 };
4394 
4395 void KateDocument::reloadFile()
4396 {
4397  if ( !url().isEmpty() )
4398  {
4399  if (m_modOnHd && s_fileChangedDialogsActivated)
4400  {
4401  int i = KMessageBox::warningYesNoCancel
4402  (0, reasonedMOHString() + "\n\n" + i18n("What do you want to do?"),
4403  i18n("File Was Changed on Disk"), i18n("&Reload File"), i18n("&Ignore Changes"));
4404 
4405  if ( i != KMessageBox::Yes)
4406  {
4407  if (i == KMessageBox::No)
4408  {
4409  m_modOnHd = false;
4410  m_modOnHdReason = 0;
4411  emit modifiedOnDisc (this, m_modOnHd, 0);
4412  }
4413 
4414  return;
4415  }
4416  }
4417 
4418  TQValueList<KateDocumentTmpMark> tmp;
4419 
4420  for( TQIntDictIterator<KTextEditor::Mark> it( m_marks ); it.current(); ++it )
4421  {
4422  KateDocumentTmpMark m;
4423 
4424  m.line = textLine (it.current()->line);
4425  m.mark = *it.current();
4426 
4427  tmp.append (m);
4428  }
4429 
4430  uint mode = hlMode ();
4431  bool byUser = hlSetByUser;
4432 
4433  m_storedVariables.clear();
4434 
4435  m_reloading = true;
4436 
4437  TQValueList<int> lines, cols;
4438  for ( uint i=0; i < m_views.count(); i++ )
4439  {
4440  lines.append( m_views.at( i )->cursorLine() );
4441  cols.append( m_views.at( i )->cursorColumn() );
4442  }
4443 
4444  KateDocument::openURL( url() );
4445 
4446  for ( uint i=0; i < m_views.count(); i++ )
4447  m_views.at( i )->setCursorPositionInternal( lines[ i ], cols[ i ], m_config->tabWidth(), false );
4448 
4449  m_reloading = false;
4450 
4451  for ( TQValueList<int>::size_type z=0; z < tmp.size(); z++ )
4452  {
4453  if (z < numLines())
4454  {
4455  if (textLine(tmp[z].mark.line) == tmp[z].line)
4456  setMark (tmp[z].mark.line, tmp[z].mark.type);
4457  }
4458  }
4459 
4460  if (byUser)
4461  setHlMode (mode);
4462  }
4463 }
4464 
4465 void KateDocument::flush ()
4466 {
4467  closeURL ();
4468 }
4469 
4470 void KateDocument::setWordWrap (bool on)
4471 {
4472  config()->setWordWrap (on);
4473 }
4474 
4475 bool KateDocument::wordWrap ()
4476 {
4477  return config()->wordWrap ();
4478 }
4479 
4480 void KateDocument::setWordWrapAt (uint col)
4481 {
4482  config()->setWordWrapAt (col);
4483 }
4484 
4485 unsigned int KateDocument::wordWrapAt ()
4486 {
4487  return config()->wordWrapAt ();
4488 }
4489 
4490 void KateDocument::applyWordWrap ()
4491 {
4492  // dummy to make the API happy
4493 }
4494 
4495 void KateDocument::setPageUpDownMovesCursor (bool on)
4496 {
4497  config()->setPageUpDownMovesCursor (on);
4498 }
4499 
4500 bool KateDocument::pageUpDownMovesCursor ()
4501 {
4502  return config()->pageUpDownMovesCursor ();
4503 }
4504 
4505 void KateDocument::dumpRegionTree()
4506 {
4507  m_buffer->foldingTree()->debugDump();
4508 }
4509 //END
4510 
4511 //BEGIN KTextEditor::CursorInterface stuff
4512 
4513 KTextEditor::Cursor *KateDocument::createCursor ( )
4514 {
4515  return new KateSuperCursor (this, false, 0, 0, this);
4516 }
4517 
4518 void KateDocument::tagArbitraryLines(KateView* view, KateSuperRange* range)
4519 {
4520  if (view)
4521  view->tagLines(range->start(), range->end());
4522  else
4523  tagLines(range->start(), range->end());
4524 }
4525 
4526 void KateDocument::lineInfo (KateLineInfo *info, unsigned int line)
4527 {
4528  m_buffer->lineInfo(info,line);
4529 }
4530 
4531 KateCodeFoldingTree *KateDocument::foldingTree ()
4532 {
4533  return m_buffer->foldingTree();
4534 }
4535 
4536 void KateDocument::setEncoding (const TQString &e)
4537 {
4538  if ( m_encodingSticky )
4539  return;
4540 
4541  TQString ce = m_config->encoding().lower();
4542  if ( e.lower() == ce )
4543  return;
4544 
4545  m_config->setEncoding( e );
4546  if ( ! m_loading )
4547  reloadFile();
4548 }
4549 
4550 TQString KateDocument::encoding() const
4551 {
4552  return m_config->encoding();
4553 }
4554 
4555 void KateDocument::updateConfig ()
4556 {
4557  emit undoChanged ();
4558  tagAll();
4559 
4560  for (KateView * view = m_views.first(); view != 0L; view = m_views.next() )
4561  {
4562  view->updateDocumentConfig ();
4563  }
4564 
4565  // switch indenter if needed
4566  if (m_indenter->modeNumber() != m_config->indentationMode())
4567  {
4568  delete m_indenter;
4569  m_indenter = KateAutoIndent::createIndenter ( this, m_config->indentationMode() );
4570  }
4571 
4572  m_indenter->updateConfig();
4573 
4574  m_buffer->setTabWidth (config()->tabWidth());
4575 
4576  // plugins
4577  for (uint i=0; i<KateFactory::self()->plugins().count(); i++)
4578  {
4579  if (config()->plugin (i))
4580  loadPlugin (i);
4581  else
4582  unloadPlugin (i);
4583  }
4584 }
4585 
4586 //BEGIN Variable reader
4587 // "local variable" feature by anders, 2003
4588 /* TODO
4589  add config options (how many lines to read, on/off)
4590  add interface for plugins/apps to set/get variables
4591  add view stuff
4592 */
4593 TQRegExp KateDocument::kvLine = TQRegExp("kate:(.*)");
4594 TQRegExp KateDocument::kvLineWildcard = TQRegExp("kate-wildcard\\((.*)\\):(.*)");
4595 TQRegExp KateDocument::kvLineMime = TQRegExp("kate-mimetype\\((.*)\\):(.*)");
4596 TQRegExp KateDocument::kvVar = TQRegExp("([\\w\\-]+)\\s+([^;]+)");
4597 
4598 void KateDocument::readVariables(bool onlyViewAndRenderer)
4599 {
4600  if (!onlyViewAndRenderer)
4601  m_config->configStart();
4602 
4603  // views!
4604  KateView *v;
4605  for (v = m_views.first(); v != 0L; v= m_views.next() )
4606  {
4607  v->config()->configStart();
4608  v->renderer()->config()->configStart();
4609  }
4610  // read a number of lines in the top/bottom of the document
4611  for (uint i=0; i < kMin( 9U, numLines() ); ++i )
4612  {
4613  readVariableLine( textLine( i ), onlyViewAndRenderer );
4614  }
4615  if ( numLines() > 10 )
4616  {
4617  for ( uint i = kMax(10U, numLines() - 10); i < numLines(); ++i )
4618  {
4619  readVariableLine( textLine( i ), onlyViewAndRenderer );
4620  }
4621  }
4622 
4623  if (!onlyViewAndRenderer)
4624  m_config->configEnd();
4625 
4626  for (v = m_views.first(); v != 0L; v= m_views.next() )
4627  {
4628  v->config()->configEnd();
4629  v->renderer()->config()->configEnd();
4630  }
4631 }
4632 
4633 void KateDocument::readVariableLine( TQString t, bool onlyViewAndRenderer )
4634 {
4635  // simple check first, no regex
4636  // no kate inside, no vars, simple...
4637  if (t.find("kate") < 0)
4638  return;
4639 
4640  // found vars, if any
4641  TQString s;
4642 
4643  if ( kvLine.search( t ) > -1 )
4644  {
4645  s = kvLine.cap(1);
4646 
4647  kdDebug (13020) << "normal variable line kate: matched: " << s << endl;
4648  }
4649  else if (kvLineWildcard.search( t ) > -1) // regex given
4650  {
4651  TQStringList wildcards (TQStringList::split(';', kvLineWildcard.cap(1)));
4652  TQString nameOfFile = url().fileName();
4653 
4654  bool found = false;
4655  for (TQStringList::size_type i = 0; !found && i < wildcards.size(); ++i)
4656  {
4657  TQRegExp wildcard (wildcards[i], true/*TQt::CaseSensitive*/, true/*TQRegExp::Wildcard*/);
4658 
4659  found = wildcard.exactMatch (nameOfFile);
4660  }
4661 
4662  // nothing usable found...
4663  if (!found)
4664  return;
4665 
4666  s = kvLineWildcard.cap(2);
4667 
4668  kdDebug (13020) << "guarded variable line kate-wildcard: matched: " << s << endl;
4669  }
4670  else if (kvLineMime.search( t ) > -1) // mime-type given
4671  {
4672  TQStringList types (TQStringList::split(';', kvLineMime.cap(1)));
4673 
4674  // no matching type found
4675  if (!types.contains (mimeType ()))
4676  return;
4677 
4678  s = kvLineMime.cap(2);
4679 
4680  kdDebug (13020) << "guarded variable line kate-mimetype: matched: " << s << endl;
4681  }
4682  else // nothing found
4683  {
4684  return;
4685  }
4686 
4687  TQStringList vvl; // view variable names
4688  vvl << "dynamic-word-wrap" << "dynamic-word-wrap-indicators"
4689  << "line-numbers" << "icon-border" << "folding-markers"
4690  << "bookmark-sorting" << "auto-center-lines"
4691  << "icon-bar-color"
4692  // renderer
4693  << "background-color" << "selection-color"
4694  << "current-line-color" << "bracket-highlight-color"
4695  << "word-wrap-marker-color"
4696  << "font" << "font-size" << "scheme";
4697  int p( 0 );
4698 
4699  TQString var, val;
4700  while ( (p = kvVar.search( s, p )) > -1 )
4701  {
4702  p += kvVar.matchedLength();
4703  var = kvVar.cap( 1 );
4704  val = TQString(kvVar.cap( 2 )).stripWhiteSpace();
4705  bool state; // store booleans here
4706  int n; // store ints here
4707 
4708  // only apply view & renderer config stuff
4709  if (onlyViewAndRenderer)
4710  {
4711  if ( vvl.contains( var ) ) // FIXME define above
4712  setViewVariable( var, val );
4713  }
4714  else
4715  {
4716  // BOOL SETTINGS
4717  if ( var == "word-wrap" && checkBoolValue( val, &state ) )
4718  setWordWrap( state ); // ??? FIXME CHECK
4719  else if ( var == "block-selection" && checkBoolValue( val, &state ) )
4720  setBlockSelectionMode( state );
4721  // KateConfig::configFlags
4722  // FIXME should this be optimized to only a few calls? how?
4723  else if ( var == "backspace-indents" && checkBoolValue( val, &state ) )
4724  m_config->setConfigFlags( KateDocumentConfig::cfBackspaceIndents, state );
4725  else if ( var == "replace-tabs" && checkBoolValue( val, &state ) )
4726  m_config->setConfigFlags( KateDocumentConfig::cfReplaceTabsDyn, state );
4727  else if ( var == "remove-trailing-space" && checkBoolValue( val, &state ) )
4728  m_config->setConfigFlags( KateDocumentConfig::cfRemoveTrailingDyn, state );
4729  else if ( var == "wrap-cursor" && checkBoolValue( val, &state ) )
4730  m_config->setConfigFlags( KateDocumentConfig::cfWrapCursor, state );
4731  else if ( var == "auto-brackets" && checkBoolValue( val, &state ) )
4732  m_config->setConfigFlags( KateDocumentConfig::cfAutoBrackets, state );
4733  else if ( var == "overwrite-mode" && checkBoolValue( val, &state ) )
4734  m_config->setConfigFlags( KateDocumentConfig::cfOvr, state );
4735  else if ( var == "keep-indent-profile" && checkBoolValue( val, &state ) )
4736  m_config->setConfigFlags( KateDocumentConfig::cfKeepIndentProfile, state );
4737  else if ( var == "keep-extra-spaces" && checkBoolValue( val, &state ) )
4738  m_config->setConfigFlags( KateDocumentConfig::cfKeepExtraSpaces, state );
4739  else if ( var == "tab-indents" && checkBoolValue( val, &state ) )
4740  m_config->setConfigFlags( KateDocumentConfig::cfTabIndents, state );
4741  else if ( var == "show-tabs" && checkBoolValue( val, &state ) )
4742  m_config->setConfigFlags( KateDocumentConfig::cfShowTabs, state );
4743  else if ( var == "space-indent" && checkBoolValue( val, &state ) )
4744  m_config->setConfigFlags( KateDocumentConfig::cfSpaceIndent, state );
4745  else if ( var == "smart-home" && checkBoolValue( val, &state ) )
4746  m_config->setConfigFlags( KateDocumentConfig::cfSmartHome, state );
4747  else if ( var == "replace-trailing-space-save" && checkBoolValue( val, &state ) )
4748  m_config->setConfigFlags( KateDocumentConfig::cfRemoveSpaces, state );
4749  else if ( var == "auto-insert-doxygen" && checkBoolValue( val, &state) )
4750  m_config->setConfigFlags( KateDocumentConfig::cfDoxygenAutoTyping, state);
4751  else if ( var == "mixed-indent" && checkBoolValue( val, &state ) )
4752  m_config->setConfigFlags( KateDocumentConfig::cfMixedIndent, state );
4753 
4754  // INTEGER SETTINGS
4755  else if ( var == "tab-width" && checkIntValue( val, &n ) )
4756  m_config->setTabWidth( n );
4757  else if ( var == "indent-width" && checkIntValue( val, &n ) )
4758  m_config->setIndentationWidth( n );
4759  else if ( var == "indent-mode" )
4760  {
4761  if ( checkIntValue( val, &n ) )
4762  m_config->setIndentationMode( n );
4763  else
4764  m_config->setIndentationMode( KateAutoIndent::modeNumber( val) );
4765  }
4766  else if ( var == "word-wrap-column" && checkIntValue( val, &n ) && n > 0 ) // uint, but hard word wrap at 0 will be no fun ;)
4767  m_config->setWordWrapAt( n );
4768  else if ( var == "undo-steps" && checkIntValue( val, &n ) && n >= 0 )
4769  setUndoSteps( n );
4770 
4771  // STRING SETTINGS
4772  else if ( var == "eol" || var == "end-of-line" )
4773  {
4774  TQStringList l;
4775  l << "unix" << "dos" << "mac";
4776  if ( (n = l.findIndex( val.lower() )) != -1 )
4777  m_config->setEol( n );
4778  }
4779  else if ( var == "encoding" )
4780  m_config->setEncoding( val );
4781  else if ( var == "syntax" || var == "hl" )
4782  {
4783  for ( uint i=0; i < hlModeCount(); i++ )
4784  {
4785  if ( hlModeName( i ).lower() == val.lower() )
4786  {
4787  setHlMode( i );
4788  break;
4789  }
4790  }
4791  }
4792 
4793  // VIEW SETTINGS
4794  else if ( vvl.contains( var ) )
4795  setViewVariable( var, val );
4796  else
4797  {
4798  m_storedVariables.insert( var, val );
4799  emit variableChanged( var, val );
4800  }
4801  }
4802  }
4803 }
4804 
4805 void KateDocument::setViewVariable( TQString var, TQString val )
4806 {
4807  KateView *v;
4808  bool state;
4809  int n;
4810  TQColor c;
4811  for (v = m_views.first(); v != 0L; v= m_views.next() )
4812  {
4813  if ( var == "dynamic-word-wrap" && checkBoolValue( val, &state ) )
4814  v->config()->setDynWordWrap( state );
4815  else if ( var == "persistent-selection" && checkBoolValue( val, &state ) )
4816  v->config()->setPersistentSelection( state );
4817  //else if ( var = "dynamic-word-wrap-indicators" )
4818  else if ( var == "line-numbers" && checkBoolValue( val, &state ) )
4819  v->config()->setLineNumbers( state );
4820  else if (var == "icon-border" && checkBoolValue( val, &state ) )
4821  v->config()->setIconBar( state );
4822  else if (var == "folding-markers" && checkBoolValue( val, &state ) )
4823  v->config()->setFoldingBar( state );
4824  else if ( var == "auto-center-lines" && checkIntValue( val, &n ) )
4825  v->config()->setAutoCenterLines( n ); // FIXME uint, > N ??
4826  else if ( var == "icon-bar-color" && checkColorValue( val, c ) )
4827  v->renderer()->config()->setIconBarColor( c );
4828  // RENDERER
4829  else if ( var == "background-color" && checkColorValue( val, c ) )
4830  v->renderer()->config()->setBackgroundColor( c );
4831  else if ( var == "selection-color" && checkColorValue( val, c ) )
4832  v->renderer()->config()->setSelectionColor( c );
4833  else if ( var == "current-line-color" && checkColorValue( val, c ) )
4834  v->renderer()->config()->setHighlightedLineColor( c );
4835  else if ( var == "bracket-highlight-color" && checkColorValue( val, c ) )
4836  v->renderer()->config()->setHighlightedBracketColor( c );
4837  else if ( var == "word-wrap-marker-color" && checkColorValue( val, c ) )
4838  v->renderer()->config()->setWordWrapMarkerColor( c );
4839  else if ( var == "font" || ( var == "font-size" && checkIntValue( val, &n ) ) )
4840  {
4841  TQFont _f( *v->renderer()->config()->font( ) );
4842 
4843  if ( var == "font" )
4844  {
4845  _f.setFamily( val );
4846  _f.setFixedPitch( TQFont( val ).fixedPitch() );
4847  }
4848  else
4849  _f.setPointSize( n );
4850 
4851  v->renderer()->config()->setFont( _f );
4852  }
4853  else if ( var == "scheme" )
4854  {
4855  v->renderer()->config()->setSchema( KateFactory::self()->schemaManager()->number( val ) );
4856  }
4857  }
4858 }
4859 
4860 bool KateDocument::checkBoolValue( TQString val, bool *result )
4861 {
4862  val = val.stripWhiteSpace().lower();
4863  TQStringList l;
4864  l << "1" << "on" << "true";
4865  if ( l.contains( val ) )
4866  {
4867  *result = true;
4868  return true;
4869  }
4870  l.clear();
4871  l << "0" << "off" << "false";
4872  if ( l.contains( val ) )
4873  {
4874  *result = false;
4875  return true;
4876  }
4877  return false;
4878 }
4879 
4880 bool KateDocument::checkIntValue( TQString val, int *result )
4881 {
4882  bool ret( false );
4883  *result = val.toInt( &ret );
4884  return ret;
4885 }
4886 
4887 bool KateDocument::checkColorValue( TQString val, TQColor &c )
4888 {
4889  c.setNamedColor( val );
4890  return c.isValid();
4891 }
4892 
4893 // KTextEditor::variable
4894 TQString KateDocument::variable( const TQString &name ) const
4895 {
4896  if ( m_storedVariables.contains( name ) )
4897  return m_storedVariables[ name ];
4898 
4899  return "";
4900 }
4901 
4902 //END
4903 
4904 void KateDocument::slotModOnHdDirty (const TQString &path)
4905 {
4906  if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 1))
4907  {
4908  // compare md5 with the one we have (if we have one)
4909  if ( ! m_digest.isEmpty() )
4910  {
4911  TQCString tmp;
4912  if ( createDigest( tmp ) && tmp == m_digest )
4913  return;
4914  }
4915 
4916  m_modOnHd = true;
4917  m_modOnHdReason = 1;
4918 
4919  // reenable dialog if not running atm
4920  if (m_isasking == -1)
4921  m_isasking = false;
4922 
4923  emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
4924  }
4925 }
4926 
4927 void KateDocument::slotModOnHdCreated (const TQString &path)
4928 {
4929  if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 2))
4930  {
4931  m_modOnHd = true;
4932  m_modOnHdReason = 2;
4933 
4934  // reenable dialog if not running atm
4935  if (m_isasking == -1)
4936  m_isasking = false;
4937 
4938  emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
4939  }
4940 }
4941 
4942 void KateDocument::slotModOnHdDeleted (const TQString &path)
4943 {
4944  if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != 3))
4945  {
4946  m_modOnHd = true;
4947  m_modOnHdReason = 3;
4948 
4949  // reenable dialog if not running atm
4950  if (m_isasking == -1)
4951  m_isasking = false;
4952 
4953  emit modifiedOnDisc (this, m_modOnHd, m_modOnHdReason);
4954  }
4955 }
4956 
4957 bool KateDocument::createDigest( TQCString &result )
4958 {
4959  bool ret = false;
4960  result = "";
4961  if ( url().isLocalFile() )
4962  {
4963  TQFile f ( url().path() );
4964  if ( f.open( IO_ReadOnly) )
4965  {
4966  KMD5 md5;
4967  ret = md5.update( f );
4968  md5.hexDigest( result );
4969  f.close();
4970  ret = true;
4971  }
4972  }
4973  return ret;
4974 }
4975 
4976 TQString KateDocument::reasonedMOHString() const
4977 {
4978  switch( m_modOnHdReason )
4979  {
4980  case 1:
4981  return i18n("The file '%1' was modified by another program.").arg( url().pathOrURL() );
4982  break;
4983  case 2:
4984  return i18n("The file '%1' was created by another program.").arg( url().pathOrURL() );
4985  break;
4986  case 3:
4987  return i18n("The file '%1' was deleted by another program.").arg( url().pathOrURL() );
4988  break;
4989  default:
4990  return TQString();
4991  }
4992 }
4993 
4994 void KateDocument::removeTrailingSpace( uint line )
4995 {
4996  // remove trailing spaces from left line if required
4997  if ( config()->configFlags() & KateDocumentConfig::cfRemoveTrailingDyn )
4998  {
4999  KateTextLine::Ptr ln = kateTextLine( line );
5000 
5001  if ( ! ln ) return;
5002 
5003  if ( line == activeView()->cursorLine()
5004  && activeView()->cursorColumnReal() >= (uint)kMax(0,ln->lastChar()) )
5005  return;
5006 
5007  if ( ln->length() )
5008  {
5009  uint p = ln->lastChar() + 1;
5010  uint l = ln->length() - p;
5011  if ( l )
5012  editRemoveText( line, p, l);
5013  }
5014  }
5015 }
5016 
5017 void KateDocument::updateFileType (int newType, bool user)
5018 {
5019  if (user || !m_fileTypeSetByUser)
5020  {
5021  const KateFileType *t = 0;
5022  if ((newType == -1) || (t = KateFactory::self()->fileTypeManager()->fileType (newType)))
5023  {
5024  m_fileType = newType;
5025 
5026  if (t)
5027  {
5028  m_config->configStart();
5029  // views!
5030  KateView *v;
5031  for (v = m_views.first(); v != 0L; v= m_views.next() )
5032  {
5033  v->config()->configStart();
5034  v->renderer()->config()->configStart();
5035  }
5036 
5037  readVariableLine( t->varLine );
5038 
5039  m_config->configEnd();
5040  for (v = m_views.first(); v != 0L; v= m_views.next() )
5041  {
5042  v->config()->configEnd();
5043  v->renderer()->config()->configEnd();
5044  }
5045  }
5046  }
5047  }
5048 }
5049 
5050 uint KateDocument::documentNumber () const
5051 {
5052  return KTextEditor::Document::documentNumber ();
5053 }
5054 
5055 long KateDocument::documentListPosition () const
5056 {
5057  return KTextEditor::Document::documentListPosition ();
5058 }
5059 
5060 void KateDocument::setDocumentListPosition (long pos)
5061 {
5062  KTextEditor::Document::setDocumentListPosition (pos);
5063 }
5064 
5065 
5066 
5067 void KateDocument::slotQueryClose_save(bool *handled, bool* abortClosing) {
5068  *handled=true;
5069  *abortClosing=true;
5070  if (m_url.isEmpty())
5071  {
5072  KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveURLAndEncoding(config()->encoding(),
5073  TQString::null,TQString::null,0,i18n("Save File"));
5074 
5075  if( res.URLs.isEmpty() || !checkOverwrite( res.URLs.first() ) ) {
5076  *abortClosing=true;
5077  return;
5078  }
5079  setEncoding( res.encoding );
5080  saveAs( res.URLs.first() );
5081  *abortClosing=false;
5082  }
5083  else
5084  {
5085  save();
5086  *abortClosing=false;
5087  }
5088 
5089 }
5090 
5091 bool KateDocument::checkOverwrite( KURL u )
5092 {
5093  if( !u.isLocalFile() )
5094  return true;
5095 
5096  TQFileInfo info( u.path() );
5097  if( !info.exists() )
5098  return true;
5099 
5100  return KMessageBox::Cancel != KMessageBox::warningContinueCancel( 0,
5101  i18n( "A file named \"%1\" already exists. "
5102  "Are you sure you want to overwrite it?" ).arg( info.fileName() ),
5103  i18n( "Overwrite File?" ),
5104  i18n( "&Overwrite" ) );
5105 }
5106 
5107 void KateDocument::setDefaultEncoding (const TQString &encoding)
5108 {
5109  s_defaultEncoding = encoding;
5110 }
5111 
5112 //BEGIN KTextEditor::TemplateInterface
5113 bool KateDocument::insertTemplateTextImplementation ( uint line, uint column, const TQString &templateString, const TQMap<TQString,TQString> &initialValues, TQWidget *) {
5114  return (new KateTemplateHandler(this,line,column,templateString,initialValues))->initOk();
5115 }
5116 
5117 void KateDocument::testTemplateCode() {
5118  int col=activeView()->cursorColumn();
5119  int line=activeView()->cursorLine();
5120  insertTemplateText(line,col,"for ${index} \\${NOPLACEHOLDER} ${index} ${blah} ${fullname} \\$${Placeholder} \\${${PLACEHOLDER2}}\n next line:${ANOTHERPLACEHOLDER} $${DOLLARBEFOREPLACEHOLDER} {NOTHING} {\n${cursor}\n}",TQMap<TQString,TQString>());
5121 }
5122 
5123 bool KateDocument::invokeTabInterceptor(KKey key) {
5124  if (m_tabInterceptor) return (*m_tabInterceptor)(key);
5125  return false;
5126 }
5127 
5128 bool KateDocument::setTabInterceptor(KateKeyInterceptorFunctor *interceptor) {
5129  if (m_tabInterceptor) return false;
5130  m_tabInterceptor=interceptor;
5131  return true;
5132 }
5133 
5134 bool KateDocument::removeTabInterceptor(KateKeyInterceptorFunctor *interceptor) {
5135  if (m_tabInterceptor!=interceptor) return false;
5136  m_tabInterceptor=0;
5137  return true;
5138 }
5139 //END KTextEditor::TemplateInterface
5140 
5141 //BEGIN DEPRECATED STUFF
5142  bool KateDocument::setSelection ( uint startLine, uint startCol, uint endLine, uint endCol )
5143 { if (m_activeView) return m_activeView->setSelection (startLine, startCol, endLine, endCol); return false; }
5144 
5145  bool KateDocument::clearSelection ()
5146  { if (m_activeView) return m_activeView->clearSelection(); return false; }
5147 
5148  bool KateDocument::hasSelection () const
5149  { if (m_activeView) return m_activeView->hasSelection (); return false; }
5150 
5151  TQString KateDocument::selection () const
5152  { if (m_activeView) return m_activeView->selection (); return TQString(""); }
5153 
5154  bool KateDocument::removeSelectedText ()
5155  { if (m_activeView) return m_activeView->removeSelectedText (); return false; }
5156 
5157  bool KateDocument::selectAll()
5158  { if (m_activeView) return m_activeView->selectAll (); return false; }
5159 
5160  int KateDocument::selStartLine()
5161  { if (m_activeView) return m_activeView->selStartLine (); return 0; }
5162 
5163  int KateDocument::selStartCol()
5164  { if (m_activeView) return m_activeView->selStartCol (); return 0; }
5165 
5166  int KateDocument::selEndLine()
5167  { if (m_activeView) return m_activeView->selEndLine (); return 0; }
5168 
5169  int KateDocument::selEndCol()
5170  { if (m_activeView) return m_activeView->selEndCol (); return 0; }
5171 
5172  bool KateDocument::blockSelectionMode ()
5173  { if (m_activeView) return m_activeView->blockSelectionMode (); return false; }
5174 
5175 bool KateDocument::setBlockSelectionMode (bool on)
5176  { if (m_activeView) return m_activeView->setBlockSelectionMode (on); return false; }
5177 
5178 bool KateDocument::toggleBlockSelectionMode ()
5179  { if (m_activeView) return m_activeView->toggleBlockSelectionMode (); return false; }
5180 //END DEPRECATED
5181 
5182 //END DEPRECATED STUFF
KDialogBase
KDialogBase::addVBoxPage
TQVBox * addVBoxPage(const TQString &itemName, const TQString &header=TQString::null, const TQPixmap &pixmap=TQPixmap())
KDialogBase::Help
Help
KDialogBase::Ok
Ok
KDialogBase::Cancel
Cancel
KKey
KMD5
KMD5::update
void update(const char *in, int len=-1)
KMD5::hexDigest
TQCString hexDigest()
KMessageBox::information
static void information(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const TQString &dontShowAgainName=TQString::null, int options=Notify)
KMessageBox::error
static void error(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, int options=Notify)
KMessageBox::warningYesNoCancel
static int warningYesNoCancel(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const KGuiItem &buttonYes=KStdGuiItem::yes(), const KGuiItem &buttonNo=KStdGuiItem::no(), const TQString &dontAskAgainName=TQString::null, int options=Notify)
KMessageBox::warningContinueCancel
static int warningContinueCancel(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const KGuiItem &buttonContinue=KStdGuiItem::cont(), const TQString &dontAskAgainName=TQString::null, int options=Notify)
KParts::GUIActivateEvent
KParts::ReadOnlyPart::guiActivateEvent
virtual void guiActivateEvent(GUIActivateEvent *event)
KParts::ReadWritePart::setReadWrite
virtual void setReadWrite(bool readwrite=true)
KParts::ReadWritePart::saveAs
virtual bool saveAs(const KURL &url)
KParts::ReadWritePart::closeURL
virtual bool closeURL()
KParts::ReadWritePart::save
virtual bool save()
KParts::ReadWritePart::setModified
virtual void setModified()
KTempFile
KURL
KURL::path
TQString path() const
KURL::directory
TQString directory(bool _strip_trailing_slash_from_result=true, bool _ignore_trailing_slash_in_path=true) const
KURL::fileName
TQString fileName(bool _ignore_trailing_slash_in_path=true) const
KURL::filename
TQString filename(bool _ignore_trailing_slash_in_path=true) const
KURL::isLocalFile
bool isLocalFile() const
KURL::prettyURL
TQString prettyURL(int _trailing=0) const
KURL::isValid
bool isValid() const
KWin::setIcons
static void setIcons(WId win, const TQPixmap &icon, const TQPixmap &miniIcon)
KXMLGUIFactory
KXMLGUIFactory::removeClient
void removeClient(KXMLGUIClient *client)
KXMLGUIFactory::addClient
void addClient(KXMLGUIClient *client)
KateArbitraryHighlight
An arbitrary highlighting interface for Kate.
Definition: katearbitraryhighlight.h:61
KateAutoIndent::modeNumber
virtual uint modeNumber() const
Mode index of this mode.
Definition: kateautoindent.h:185
KateAutoIndent::createIndenter
static KateAutoIndent * createIndenter(KateDocument *doc, uint mode)
Static methods to create and list indention modes.
Definition: kateautoindent.cpp:38
KateBrowserExtension
Interface for embedding KateDocument into a browser.
Definition: katedocumenthelpers.h:37
KateBuffer
The KateBuffer class maintains a collections of lines.
Definition: katebuffer.h:342
KateBuffer::setMaxLoadedBlocks
static void setMaxLoadedBlocks(uint count)
modifier for max loaded blocks limit
Definition: katebuffer.cpp:79
KateBuffer::maxLoadedBlocks
static uint maxLoadedBlocks()
maximal loaded block count
Definition: katebuffer.h:352
KateDocCursor
Cursor class with a pointer to its document.
Definition: katecursor.h:93
KateModOnHdPrompt
This dialog will prompt the user for what do with a file that is modified on disk.
Definition: katedialogs.h:371
KateSuperCursor
Possible additional features:
Definition: katesupercursor.h:46
KateSuperRange
Represents a range of text, from the start() to the end().
Definition: katesupercursor.h:169
KateTextCursor
Simple cursor class with no document pointer.
Definition: katecursor.h:34
KateTextLine
The KateTextLine represents a line of text.
Definition: katetextline.h:42
KateUndoGroup
Class to manage a group of undo items.
Definition: kateundo.h:34
KateUndoGroup::UndoType
UndoType
Types for undo items.
Definition: kateundo.h:63
Kate::Document
This interface provides access to the Kate Document class.
Definition: document.h:190
Kate::View
The Kate::View text editor interface.
Definition: view.h:45
TDEConfigBase::readEntry
TQString readEntry(const TQString &pKey, const TQString &aDefault=TQString::null) const
TDEConfigBase::readNumEntry
int readNumEntry(const TQString &pKey, int nDefault=0) const
TDEConfigBase::readIntListEntry
TQValueList< int > readIntListEntry(const TQString &pKey) const
TDEConfigBase::sync
virtual void sync()
TDEConfigBase::writeEntry
void writeEntry(const TQString &pKey, const TQString &pValue, bool bPersistent=true, bool bGlobal=false, bool bNLS=false)
TDEConfigBase::setGroup
void setGroup(const TQString &group)
TDEConfig
TDEGlobal::dirs
static TDEStandardDirs * dirs()
TDEIcon::SizeMedium
SizeMedium
TDESharedPtr
TDESharedPtr::count
int count() const
TDEStandardDirs::relativeLocation
TQString relativeLocation(const char *type, const TQString &absPath)
endl
kndbgstream & endl(kndbgstream &s)
kdDebug
kdbgstream kdDebug(int area=0)
flush
kndbgstream & flush(kndbgstream &s)
KNotifyClient::instance
TDEInstance * instance()
KStdAction::clear
TDEAction * clear(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
KStdAction::saveAs
TDEAction * saveAs(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
Kate
Kate namespace All classes in this namespace must stay BC during one major release series (e....
Definition: document.h:51
TDEStdAccel::forward
const TDEShortcut & forward()
TDEStdAccel::key
int key(StdAccel id)
TDEStdAccel::name
TQString name(StdAccel id)
TDEStdAccel::end
const TDEShortcut & end()
TDEStdAccel::save
const TDEShortcut & save()
tdelocale.h

kate

Skip menu "kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kate

Skip menu "kate"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kate by doxygen 1.9.1
This website is maintained by Timothy Pearson.