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