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