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