~ubuntu-branches/ubuntu/maverick/juffed/maverick-updates

« back to all changes in this revision

Viewing changes to src/SciDoc.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Maia Kozheva
  • Date: 2010-07-22 15:01:58 UTC
  • Revision ID: james.westby@ubuntu.com-20100722150158-m3792gi6tj0y8zl6
Tags: upstream-0.8.1
ImportĀ upstreamĀ versionĀ 0.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
JuffEd - An advanced text editor
 
3
Copyright 2007-2009 Mikhail Murzin
 
4
 
 
5
This program is free software; you can redistribute it and/or
 
6
modify it under the terms of the GNU General Public License 
 
7
version 2 as published by the Free Software Foundation.
 
8
 
 
9
This program is distributed in the hope that it will be useful,
 
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
GNU General Public License for more details.
 
13
 
 
14
You should have received a copy of the GNU General Public License
 
15
along with this program; if not, write to the Free Software
 
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
17
*/
 
18
 
 
19
#include "SciDoc.h"
 
20
 
 
21
#include "AppInfo.h"
 
22
#include "AutocompleteSettings.h"
 
23
#include "CommandStorage.h"
 
24
#include "Functions.h"
 
25
#include "Log.h"
 
26
#include "LexerStorage.h"
 
27
#include "MainSettings.h"
 
28
#include "JuffScintilla.h"
 
29
#include "PrintSettings.h"
 
30
#include "TextDocSettings.h"
 
31
 
 
32
#include <qsciapis.h>
 
33
#include <qscilexer.h>
 
34
//#include <qscimacro.h>
 
35
#include <qsciprinter.h>
 
36
#include <qsciscintilla.h>
 
37
 
 
38
#include <QtCore/QDir>
 
39
#include <QtCore/QFile>
 
40
#include <QtCore/QTextCodec>
 
41
#include <QtCore/QTextStream>
 
42
#include <QtGui/QMenu>
 
43
#include <QtGui/QMessageBox>
 
44
#include <QtGui/QPrintDialog>
 
45
#include <QtGui/QScrollBar>
 
46
#include <QtGui/QSplitter>
 
47
 
 
48
#include <stdio.h>
 
49
 
 
50
namespace Juff {
 
51
 
 
52
class SciDoc::Interior {
 
53
public:
 
54
        Interior() {
 
55
                syntax_ = "none";
 
56
                codec_ = QTextCodec::codecForLocale();
 
57
                charsetName_ = codec_->name();
 
58
 
 
59
                edit1_ = createEdit();
 
60
                edit2_ = createEdit();
 
61
                edit2_->setDocument(edit1_->document());
 
62
                curEdit_ = NULL;
 
63
 
 
64
                spl_ = new QSplitter(Qt::Vertical);
 
65
                spl_->addWidget(edit1_);
 
66
                spl_->addWidget(edit2_);
 
67
 
 
68
                spl_->setSizes(QList<int>() << 0 << spl_->height());
 
69
                
 
70
                searchStartingLine_ = -1;
 
71
                searchStartingCol_ = -1;
 
72
                searchSteppedOver_ = false;
 
73
                searchStartingScroll_ = 0;
 
74
        }
 
75
 
 
76
 
 
77
        ~Interior() {
 
78
                delete spl_;
 
79
        }
 
80
 
 
81
        JuffScintilla* createEdit() {
 
82
                JuffScintilla* edit = new JuffScintilla();
 
83
                edit->setUtf8(true);
 
84
                edit->setIndentationGuidesForegroundColor(TextDocSettings::defaultFontColor());
 
85
                edit->setIndentationGuidesBackgroundColor(TextDocSettings::defaultBgColor());
 
86
                edit->setFolding(QsciScintilla::BoxedTreeFoldStyle);
 
87
                edit->setAutoIndent(true);
 
88
                edit->setBraceMatching(QsciScintilla::SloppyBraceMatch);
 
89
                edit->setMatchedBraceBackgroundColor(TextDocSettings::matchedBraceBgColor());
 
90
 
 
91
                edit->setMarginLineNumbers(1, true);
 
92
                edit->setMarginSensitivity(1, true);
 
93
                edit->setMarginWidth(2, 12);
 
94
                //      set the 1st margin accept markers 
 
95
                //      number 1 and 2 (binary mask 00000110 == 6)
 
96
                edit->setMarginMarkerMask(1, 6);
 
97
                edit->markerDefine(QsciScintilla::RightTriangle, 1);
 
98
                edit->markerDefine(QsciScintilla::Background, 2);
 
99
                edit->setMarkerForegroundColor(QColor(100, 100, 100));
 
100
                edit->setMarkerBackgroundColor(TextDocSettings::markersColor());
 
101
//              edit->setMarginsBackgroundColor(QColor(50, 50, 50));
 
102
//              edit->setMarginsForegroundColor(QColor(150, 150, 150));
 
103
//              edit->setFoldMarginColors(QColor(150, 150, 150), QColor(50, 50, 50));
 
104
 
 
105
                return edit;
 
106
        }
 
107
 
 
108
        QSplitter* spl_;
 
109
        JuffScintilla* edit1_;
 
110
        JuffScintilla* edit2_;
 
111
        JuffScintilla* curEdit_;
 
112
        
 
113
        QString syntax_;
 
114
        QTextCodec* codec_;
 
115
        QString charsetName_;
 
116
        int searchStartingLine_;
 
117
        int searchStartingCol_;
 
118
        bool searchSteppedOver_;
 
119
        int searchStartingScroll_;
 
120
 
 
121
};
 
122
 
 
123
SciDoc::SciDoc(const QString& fileName) : Document(fileName) {
 
124
        docInt_ = new Interior();
 
125
 
 
126
        wrapText(TextDocSettings::widthAdjust());
 
127
        showLineNumbers(TextDocSettings::showLineNumbers());
 
128
        showInvisibleSymbols(TextDocSettings::showInvisibleSymbols());
 
129
 
 
130
        if ( !fileName.isEmpty() && !isNoname(fileName) ) {
 
131
                readDoc();
 
132
                docInt_->edit1_->setModified(false);
 
133
 
 
134
                //      syntax highlighting
 
135
                QString lexName = LexerStorage::instance()->lexerName(fileName);
 
136
                setSyntax(lexName);
 
137
                
 
138
                //      line endings
 
139
                QFile file(fileName);
 
140
                if ( file.open(QIODevice::ReadOnly) ) {
 
141
                        QString line = QString::fromLocal8Bit(file.readLine().constData());
 
142
                        QRegExp re(".*(\r?\n?)");
 
143
                        if ( re.exactMatch(line) ) {
 
144
                                QString ending = re.cap(1);
 
145
                                if ( ending == "\r\n" ) {
 
146
                                        docInt_->edit1_->setEolMode(QsciScintilla::EolWindows);
 
147
                                }
 
148
                                else if ( ending == "\r" ) {
 
149
                                        docInt_->edit1_->setEolMode(QsciScintilla::EolMac);
 
150
                                }
 
151
                                else {
 
152
                                        docInt_->edit1_->setEolMode(QsciScintilla::EolUnix);
 
153
                                }       
 
154
                        }
 
155
                        file.close();
 
156
                }
 
157
        }
 
158
        else {
 
159
                setSyntax("none");
 
160
        }
 
161
 
 
162
        connect(docInt_->edit1_, SIGNAL(modificationChanged(bool)), this, SIGNAL(modified(bool)));
 
163
        connect(docInt_->edit1_, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(onCursorMove(int, int)));
 
164
        connect(docInt_->edit2_, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(onCursorMove(int, int)));
 
165
        connect(docInt_->edit1_, SIGNAL(contextMenuCalled(int, int)), this, SIGNAL(contextMenuCalled(int, int)));
 
166
        connect(docInt_->edit2_, SIGNAL(contextMenuCalled(int, int)), this, SIGNAL(contextMenuCalled(int, int)));
 
167
        connect(docInt_->edit1_, SIGNAL(marginClicked(int, int, Qt::KeyboardModifiers)), SLOT(onMarginClicked(int, int, Qt::KeyboardModifiers)));
 
168
        connect(docInt_->edit2_, SIGNAL(marginClicked(int, int, Qt::KeyboardModifiers)), SLOT(onMarginClicked(int, int, Qt::KeyboardModifiers)));
 
169
        connect(docInt_->edit1_, SIGNAL(linesChanged()), SLOT(onLinesCountChanged()));
 
170
        connect(docInt_->edit1_, SIGNAL(focusReceived()), SLOT(onEditReceivedFocus()));
 
171
        connect(docInt_->edit2_, SIGNAL(focusReceived()), SLOT(onEditReceivedFocus()));
 
172
 
 
173
        applySettings();
 
174
        
 
175
        QAction* unindentAct = new QAction(this);
 
176
        unindentAct->setShortcut(QKeySequence("Shift+Tab"));
 
177
        connect(unindentAct, SIGNAL(activated()), this, SLOT(unindent()));
 
178
        widget()->addAction(unindentAct);
 
179
}
 
180
 
 
181
void SciDoc::init() {
 
182
        docInt_->spl_->setFocusProxy(docInt_->edit2_);
 
183
        docInt_->edit2_->setFocus();
 
184
}
 
185
 
 
186
SciDoc::~SciDoc() {
 
187
        delete docInt_;
 
188
}
 
189
 
 
190
void SciDoc::setFileName(const QString& fileName) {
 
191
        Document::setFileName(fileName);
 
192
        QString lexName = LexerStorage::instance()->lexerName(fileName);
 
193
        if ( lexName != docInt_->syntax_ ) {
 
194
                setSyntax(lexName);
 
195
        }
 
196
}
 
197
 
 
198
void SciDoc::print() {
 
199
        QsciPrinter prn;
 
200
        QPrintDialog dlg(&prn, widget());
 
201
        if (dlg.exec() == QDialog::Accepted) {
 
202
                prn.setWrapMode(TextDocSettings::widthAdjust() || PrintSettings::alwaysWrap() ? QsciScintilla::WrapWord : QsciScintilla::WrapNone);
 
203
                
 
204
                int line1(-1), line2(-1), col1(-1), col2(-1);
 
205
                JuffScintilla* edit = getActiveEdit();
 
206
                if ( edit ) {
 
207
                        QsciLexer* lexer = edit->lexer();
 
208
                        if ( !PrintSettings::keepBgColor() ) {
 
209
                                lexer->setDefaultPaper(Qt::white);
 
210
                                lexer->setPaper(Qt::white);
 
211
                                lexer->setDefaultColor(Qt::black);
 
212
                        }
 
213
                        if ( !PrintSettings::keepColors() ) {
 
214
                                lexer->setColor(Qt::black);
 
215
                        }
 
216
                        edit->getSelection(&line1, &col1, &line2, &col2);
 
217
                        if (line1 >=0 && line2 >= 0 && col1 >= 0 && col2 >= 0) {
 
218
                                //      We have selection. Print it.
 
219
                                
 
220
                                --line2;
 
221
                                prn.printRange(edit, line1, line2);
 
222
                        }
 
223
                        else {
 
224
                                //      We don't have selection. Print the whole text.
 
225
                                prn.printRange(edit, 0);
 
226
                        }
 
227
                        QFont font = TextDocSettings::font();
 
228
                        LexerStorage::instance()->updateLexers(font);
 
229
                }
 
230
        }
 
231
}
 
232
 
 
233
QWidget* SciDoc::widget() {
 
234
        return docInt_->spl_;
 
235
}
 
236
 
 
237
JuffScintilla* SciDoc::getActiveEdit() const {
 
238
        return docInt_->curEdit_;
 
239
}
 
240
 
 
241
bool SciDoc::isModified() const {
 
242
        return docInt_->edit1_->isModified();
 
243
}
 
244
 
 
245
void SciDoc::setModified(bool mod) {
 
246
        return docInt_->edit1_->setModified(mod);
 
247
}
 
248
 
 
249
void SciDoc::undo() {
 
250
        JuffScintilla* edit = getActiveEdit();
 
251
        if ( !edit )
 
252
                return;
 
253
        
 
254
        edit->undo();
 
255
}
 
256
 
 
257
void SciDoc::redo() {
 
258
        JuffScintilla* edit = getActiveEdit();
 
259
        if ( !edit )
 
260
                return;
 
261
        
 
262
        edit->redo();
 
263
}
 
264
 
 
265
void SciDoc::cut() {
 
266
        JuffScintilla* edit = getActiveEdit();
 
267
        if ( !edit )
 
268
                return;
 
269
 
 
270
        edit->cut();
 
271
}
 
272
 
 
273
void SciDoc::copy() {
 
274
        JuffScintilla* edit = getActiveEdit();
 
275
        if ( !edit )
 
276
                return;
 
277
 
 
278
        edit->copy();
 
279
}
 
280
 
 
281
void SciDoc::paste() {
 
282
        JuffScintilla* edit = getActiveEdit();
 
283
        if ( !edit )
 
284
                return;
 
285
 
 
286
        edit->paste();
 
287
}
 
288
 
 
289
void SciDoc::unindent() {
 
290
        JUFFENTRY;
 
291
        
 
292
        int line1(-1), line2(-1), col1(-1), col2(-1);
 
293
        JuffScintilla* edit = getActiveEdit();
 
294
        if ( !edit )
 
295
                return;
 
296
        
 
297
        if ( edit->hasSelectedText() ) {
 
298
                edit->getSelection(&line1, &col1, &line2, &col2);
 
299
                if ( col2 == 0 )
 
300
                        --line2;
 
301
                
 
302
                if (line1 <= line2 && line1 >= 0) {
 
303
                        for (int l = line1; l <= line2; ++l) {
 
304
                                edit->unindent(l);
 
305
                        }
 
306
                }
 
307
        }
 
308
        else {
 
309
                edit->getCursorPosition(&line1, &col1);
 
310
                if ( line1 >= 0 ) {
 
311
                        edit->unindent(line1);
 
312
                }
 
313
        }
 
314
}
 
315
 
 
316
 
 
317
 
 
318
void prepareForFind(QsciScintilla* edit, const QString& s, const DocFindFlags& flags) {
 
319
        QString str(s);
 
320
        if ( flags.backwards && edit->hasSelectedText() ) {
 
321
                int fromRow, fromCol, toRow, toCol;
 
322
                edit->getSelection(&fromRow, &fromCol, &toRow, &toCol);
 
323
                if ( fromRow == toRow ) {
 
324
                        QString selection = edit->selectedText();
 
325
                        if ( flags.isRegExp ) {
 
326
                                QRegExp r(str);
 
327
                                r.setCaseSensitivity(flags.matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive);
 
328
                                if ( r.exactMatch(selection) ) {
 
329
                                        edit->setCursorPosition(fromRow, fromCol);
 
330
                                }
 
331
                        }
 
332
                        else {
 
333
                                if ( !flags.matchCase ) {
 
334
                                        str = str.toLower();
 
335
                                        selection = selection.toLower();
 
336
                                }
 
337
                                if ( selection.compare(str) == 0 ) {
 
338
                                        edit->setCursorPosition(fromRow, fromCol);
 
339
                                }
 
340
                        }
 
341
                }
 
342
        }
 
343
}
 
344
 
 
345
void stepOver(JuffScintilla* edit, bool back) {
 
346
        int row(0), col(0);
 
347
        if ( back ) {
 
348
                row = edit->lines() - 1;
 
349
                col = edit->text(row).length();
 
350
        }
 
351
        else {
 
352
                row = 0;
 
353
                col = 0;
 
354
        }
 
355
        
 
356
        edit->setCursorPosition(row, col);
 
357
}
 
358
 
 
359
void SciDoc::find(const QString& str, const DocFindFlags& flags) {
 
360
        JUFFENTRY;
 
361
 
 
362
        if ( str.isEmpty() )
 
363
                return;
 
364
 
 
365
        JuffScintilla* edit = getActiveEdit();
 
366
        if ( !edit )
 
367
                return;
 
368
 
 
369
        edit->getCursorPosition(&(docInt_->searchStartingLine_), &(docInt_->searchStartingCol_));
 
370
        docInt_->searchSteppedOver_ = false;
 
371
        docInt_->searchStartingScroll_ = edit->verticalScrollBar()->value();
 
372
        
 
373
        startFind(edit, str, flags);
 
374
}
 
375
 
 
376
void SciDoc::startFind(JuffScintilla* edit, const QString& str, const DocFindFlags& flags) {
 
377
        prepareForFind(edit, str, flags);
 
378
 
 
379
        bool found = edit->find(str, flags);
 
380
        if ( !found ) {
 
381
                //      not found
 
382
                if ( !docInt_->searchSteppedOver_ ) {
 
383
                        docInt_->searchSteppedOver_ = true;
 
384
                        stepOver(edit, flags.backwards);
 
385
                        startFind(edit, str, flags);
 
386
                }
 
387
                else {
 
388
                        edit->setCursorPosition(docInt_->searchStartingLine_, docInt_->searchStartingCol_);
 
389
                        edit->verticalScrollBar()->setValue(docInt_->searchStartingScroll_);
 
390
                        QMessageBox::information(edit, tr("Information"), tr("Text '%1' was not found").arg(str));
 
391
                        return;
 
392
                }
 
393
        }
 
394
}
 
395
 
 
396
void SciDoc::replace(const QString& str1, const QString& str2, const DocFindFlags& flags) {
 
397
        JUFFENTRY;
 
398
 
 
399
        if ( str1.isEmpty() )
 
400
                return;
 
401
 
 
402
        JuffScintilla* edit = getActiveEdit();
 
403
        if ( !edit )
 
404
                return;
 
405
 
 
406
        prepareForFind(edit, str1, flags);
 
407
 
 
408
        edit->getCursorPosition(&(docInt_->searchStartingLine_), &(docInt_->searchStartingCol_));
 
409
        docInt_->searchSteppedOver_ = false;
 
410
        docInt_->searchStartingScroll_ = edit->verticalScrollBar()->value();
 
411
        
 
412
        bool replaceAll = false;
 
413
        int count = 0;
 
414
        startReplace(edit, str1, str2, flags, replaceAll, count);
 
415
}
 
416
 
 
417
void SciDoc::startReplace(JuffScintilla* edit, const QString& str1, const QString& str2, const DocFindFlags& flags, bool& replaceAll, int& count) {
 
418
        bool cancelled = false;
 
419
        while ( edit->find(str1, flags) ) {
 
420
                if ( !doReplace(edit, str1, str2, flags, replaceAll) ) {
 
421
                        cancelled = true;
 
422
                        break;
 
423
                }
 
424
                else {
 
425
                        ++count;
 
426
                }
 
427
        }
 
428
        if ( !cancelled ) {
 
429
                //      reached the end or the beginning
 
430
                if ( !docInt_->searchSteppedOver_ ) {
 
431
                        docInt_->searchSteppedOver_ = true;
 
432
                        stepOver(edit, flags.backwards);
 
433
                        startReplace(edit, str1, str2, flags, replaceAll, count);
 
434
                }
 
435
                else {
 
436
                        edit->setCursorPosition(docInt_->searchStartingLine_, docInt_->searchStartingCol_);
 
437
                        edit->verticalScrollBar()->setValue(docInt_->searchStartingScroll_);
 
438
                        QMessageBox::information(edit, tr("Information"), tr("Replacement finished (%1 replacements were made)").arg(count));
 
439
                        return;
 
440
                }
 
441
        }
 
442
}
 
443
 
 
444
enum Answer { Yes, No, All, Cancel };
 
445
 
 
446
Answer confirm(QWidget* w) {
 
447
        Answer answer = No;
 
448
        QMessageBox::StandardButton btn = QMessageBox::question(w, QObject::tr("Confirmation"), 
 
449
                        QObject::tr("Replace this text?"), 
 
450
                        QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll | QMessageBox::Cancel, 
 
451
                        QMessageBox::Yes);
 
452
 
 
453
        switch (btn) {
 
454
                case QMessageBox::Yes:
 
455
                        answer = Yes;
 
456
                                break;
 
457
                case QMessageBox::No:
 
458
                        answer = No;
 
459
                        break;
 
460
                case QMessageBox::Cancel:
 
461
                        answer = Cancel;
 
462
                        break;
 
463
                case QMessageBox::YesToAll:
 
464
                        answer = All;
 
465
                        break;
 
466
                default: ;
 
467
        }
 
468
 
 
469
        return answer;
 
470
}
 
471
 
 
472
bool SciDoc::doReplace(JuffScintilla* edit, const QString& str1, const QString& str2, const DocFindFlags& flags, bool& replaceAll) {
 
473
        QString selectedText = edit->selectedText();
 
474
        QString targetText(str2);
 
475
        if ( flags.isRegExp ) {
 
476
                QRegExp regExp(str1);
 
477
                regExp.setCaseSensitivity(flags.matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive);
 
478
                if ( regExp.exactMatch(selectedText) ) {
 
479
                        QStringList matches = regExp.capturedTexts();
 
480
                        int n = matches.size();
 
481
                        for ( int i = 0; i < n; ++i ) {
 
482
                                targetText.replace(QString("\\%1").arg(i), matches[i]);
 
483
                        }
 
484
                }
 
485
                else
 
486
                        return false;
 
487
        }
 
488
 
 
489
        if ( !replaceAll ) {
 
490
                //      ask for confirmation if replace all hasn't been chosen yet
 
491
                
 
492
                Answer conf = confirm(widget());
 
493
                if ( conf == Cancel )
 
494
                        return false;
 
495
                else if ( conf == Yes ) {
 
496
                        edit->replaceSelected(targetText, flags.backwards);
 
497
                        edit->selectAll(false);
 
498
                }
 
499
                else if ( conf == All ) {
 
500
                        edit->replaceSelected(targetText, flags.backwards);
 
501
                        edit->selectAll(false);
 
502
                        replaceAll = true;
 
503
                }
 
504
        }
 
505
        else {
 
506
                //      just replace, because there has been chosen "select all"
 
507
                edit->replaceSelected(targetText, flags.backwards);
 
508
                edit->selectAll(false);
 
509
        }
 
510
        return true;
 
511
}
 
512
 
 
513
void SciDoc::showLineNumbers(bool show) {
 
514
        JUFFENTRY2;
 
515
        
 
516
        docInt_->edit1_->showLineNumbers(show);
 
517
        docInt_->edit2_->showLineNumbers(show);
 
518
}
 
519
 
 
520
void SciDoc::wrapText(bool wrap) {
 
521
        JUFFENTRY2;
 
522
        
 
523
        if ( wrap ) {
 
524
                docInt_->edit1_->setWrapMode(QsciScintilla::WrapWord);
 
525
                docInt_->edit2_->setWrapMode(QsciScintilla::WrapWord);
 
526
        }
 
527
        else {
 
528
                docInt_->edit1_->setWrapMode(QsciScintilla::WrapNone);
 
529
                docInt_->edit2_->setWrapMode(QsciScintilla::WrapNone);
 
530
        }
 
531
        TextDocSettings::setWidthAdjust(wrap);
 
532
}
 
533
 
 
534
void SciDoc::showInvisibleSymbols(bool show) {
 
535
        docInt_->edit1_->setWhitespaceVisibility(show ? QsciScintilla::WsVisible : QsciScintilla::WsInvisible);
 
536
        docInt_->edit1_->setWrapVisualFlags(show ? QsciScintilla::WrapFlagByBorder : QsciScintilla::WrapFlagNone);
 
537
        docInt_->edit2_->setWhitespaceVisibility(show ? QsciScintilla::WsVisible : QsciScintilla::WsInvisible);
 
538
        docInt_->edit2_->setWrapVisualFlags(show ? QsciScintilla::WrapFlagByBorder : QsciScintilla::WrapFlagNone);
 
539
        TextDocSettings::setShowInvisibleSymbols(show);
 
540
}
 
541
 
 
542
 
 
543
 
 
544
 
 
545
void SciDoc::stripTrailingSpaces() {
 
546
        JuffScintilla* edit = getActiveEdit();
 
547
        if ( !edit )
 
548
                return;
 
549
 
 
550
        int line, col;
 
551
        getCursorPos(line, col);
 
552
        QString text = edit->text();
 
553
        QStringList lines = text.split(QRegExp("\r\n|\r|\n"));
 
554
        QRegExp rx("[ \t]+$");
 
555
        int i = 0;
 
556
        foreach (QString str, lines) {
 
557
                int pos = str.indexOf(rx);
 
558
                if ( pos >= 0 ) {
 
559
                        edit->setSelection(i, 0, i, str.length());
 
560
                        str.truncate(pos);
 
561
                        replaceSelectedText(str);
 
562
                }
 
563
                ++i;
 
564
        }
 
565
        setCursorPos(line, col);
 
566
}
 
567
 
 
568
bool SciDoc::save(const QString& fileName, const QString& charset, QString& error) {
 
569
        JUFFENTRY;
 
570
 
 
571
        if ( MainSettings::stripTrailingSpaces() )
 
572
                stripTrailingSpaces();
 
573
 
 
574
        QFile file(fileName);
 
575
        if ( file.open(QIODevice::WriteOnly) ) {
 
576
                QString text("");
 
577
                text = docInt_->edit1_->text();
 
578
                QTextCodec* codec = QTextCodec::codecForName(charset.toAscii());
 
579
                if ( !charset.isEmpty() && codec ) {
 
580
                        file.write(codec->fromUnicode(text));
 
581
                }
 
582
                else {
 
583
                        file.write(docInt_->codec_->fromUnicode(text));
 
584
                }
 
585
                file.close();
 
586
                Document::save(fileName, charset, error);
 
587
                return true;
 
588
        }
 
589
        else {
 
590
                error = tr("Can't open file for writing");
 
591
                return false;
 
592
        }
 
593
}
 
594
 
 
595
void SciDoc::reload() {
 
596
        if ( !Juff::isNoname(fileName()) ) {
 
597
                int line, col;
 
598
                getCursorPos(line, col);
 
599
                int scroll = curScrollPos();
 
600
                readDoc();
 
601
                setModified(false);
 
602
                if ( line >=0 && col >= 0 ) {
 
603
                        setCursorPos(line, col);
 
604
                        setScrollPos(scroll);
 
605
                }
 
606
        }
 
607
}
 
608
 
 
609
void SciDoc::readDoc(bool keepCharset /* = false*/) {
 
610
        QString text;
 
611
        QFile file(fileName());
 
612
        if ( file.open(QIODevice::ReadOnly) ) {
 
613
                
 
614
                if ( !keepCharset ) {
 
615
                        QString codecName = guessCharset();
 
616
                        QTextCodec* codec = QTextCodec::codecForName(codecName.toAscii());
 
617
                        if ( codec ) {
 
618
                                docInt_->codec_ = codec;
 
619
                                docInt_->charsetName_ = codecName;
 
620
                        }
 
621
                }
 
622
                
 
623
                QTextStream ts(&file);
 
624
                ts.setCodec(docInt_->codec_);
 
625
                docInt_->edit1_->setText(ts.readAll());
 
626
        }
 
627
}
 
628
 
 
629
void SciDoc::applySettings() {
 
630
        JUFFENTRY2;
 
631
        
 
632
        QFont font = TextDocSettings::font();
 
633
        LexerStorage::instance()->updateLexers(font);
 
634
        showLineNumbers(TextDocSettings::showLineNumbers());
 
635
 
 
636
        QsciScintilla* edits[] = { docInt_->edit1_, docInt_->edit2_ };
 
637
        for (int i = 0; i < 2; ++i ) {
 
638
                QsciScintilla* edit = edits[i];
 
639
 
 
640
 
 
641
                edit->setTabWidth(TextDocSettings::tabStopWidth());
 
642
                edit->setIndentationsUseTabs(!TextDocSettings::replaceTabsWithSpaces());
 
643
 
 
644
                int lInd = TextDocSettings::lineLengthIndicator();
 
645
                if ( lInd > 0 ) {
 
646
                        edit->setEdgeMode(QsciScintilla::EdgeLine);
 
647
                        edit->setEdgeColumn(lInd);
 
648
                }
 
649
                else {
 
650
                        edit->setEdgeMode(QsciScintilla::EdgeNone);
 
651
                }
 
652
                
 
653
                edit->setCaretLineVisible(TextDocSettings::highlightCurrentLine());
 
654
                edit->setCaretLineBackgroundColor(LexerStorage::instance()->curLineColor(docInt_->syntax_));
 
655
                edit->setIndentationGuides(TextDocSettings::showIndents());
 
656
                edit->setBackspaceUnindents(TextDocSettings::backspaceUnindents());
 
657
                edit->setMarkerBackgroundColor(TextDocSettings::markersColor());
 
658
                if ( QsciLexer* lexer = edit->lexer() ) {
 
659
                        edit->setCaretForegroundColor(lexer->defaultColor());
 
660
                        edit->setIndentationGuidesForegroundColor(TextDocSettings::indentsColor());
 
661
                        edit->setIndentationGuidesBackgroundColor(lexer->defaultPaper());
 
662
                }
 
663
                edit->setMatchedBraceBackgroundColor(TextDocSettings::matchedBraceBgColor());
 
664
                
 
665
                // selection
 
666
                QColor selBgColor = TextDocSettings::selectionBgColor();
 
667
                edit->setSelectionBackgroundColor(selBgColor);
 
668
                if ( selBgColor.red() + selBgColor.green() + selBgColor.blue() < 3 * 255 / 2)
 
669
                        edit->setSelectionForegroundColor(QColor(255, 255, 255));
 
670
                else
 
671
                        edit->setSelectionForegroundColor(QColor(0, 0, 0));
 
672
 
 
673
                //      autocompletion
 
674
                edit->setAutoCompletionThreshold(AutocompleteSettings::threshold());
 
675
                edit->setAutoCompletionReplaceWord(AutocompleteSettings::replaceWord());
 
676
                edit->setAutoCompletionCaseSensitivity(AutocompleteSettings::caseSensitive());
 
677
                if ( AutocompleteSettings::useDocument() ) {
 
678
                        if ( AutocompleteSettings::useApis() )
 
679
                                edit->setAutoCompletionSource(QsciScintilla::AcsAll);
 
680
                        else
 
681
                                edit->setAutoCompletionSource(QsciScintilla::AcsDocument);
 
682
                }
 
683
                else {
 
684
                        if ( AutocompleteSettings::useApis() )
 
685
                                edit->setAutoCompletionSource(QsciScintilla::AcsAPIs);
 
686
                        else
 
687
                                edit->setAutoCompletionSource(QsciScintilla::AcsNone);
 
688
                }
 
689
        }
 
690
}
 
691
 
 
692
void SciDoc::updateActivated() {
 
693
        wrapText(TextDocSettings::widthAdjust());
 
694
        showLineNumbers(TextDocSettings::showLineNumbers());
 
695
}
 
696
 
 
697
void SciDoc::addContextMenuActions(const ActionList& list) {
 
698
        docInt_->edit1_->addContextMenuActions(list);
 
699
        docInt_->edit2_->addContextMenuActions(list);
 
700
}
 
701
 
 
702
 
 
703
int SciDoc::lineCount() const {
 
704
        return docInt_->edit1_->lines();
 
705
}
 
706
 
 
707
QString SciDoc::getLine(int line) const {
 
708
        return docInt_->edit1_->text(line);
 
709
}
 
710
 
 
711
void SciDoc::zoomIn() {
 
712
        docInt_->edit1_->zoomIn();
 
713
        docInt_->edit2_->zoomIn();
 
714
}
 
715
 
 
716
void SciDoc::zoomOut() {
 
717
        docInt_->edit1_->zoomOut();
 
718
        docInt_->edit2_->zoomOut();
 
719
}
 
720
 
 
721
void SciDoc::zoom100() {
 
722
        docInt_->edit1_->zoomTo(0);
 
723
        docInt_->edit2_->zoomTo(0);
 
724
}
 
725
 
 
726
void SciDoc::onCursorMove(int line, int col) {
 
727
        JuffScintilla* edit = getActiveEdit();
 
728
        if ( edit == sender() )
 
729
                emit cursorPositionChanged(line, col);
 
730
}
 
731
 
 
732
 
 
733
void SciDoc::gotoLine(int line) {
 
734
        JUFFENTRY2;
 
735
 
 
736
        JuffScintilla* edit = getActiveEdit();
 
737
        if ( !edit )
 
738
                return;
 
739
 
 
740
        edit->setCursorPosition(line, 0);
 
741
}
 
742
 
 
743
int SciDoc::curLine() const {
 
744
        int line = -1, col = -1;
 
745
        JuffScintilla* edit = getActiveEdit();
 
746
        if ( !edit ) 
 
747
                return -1;
 
748
        
 
749
        edit->getCursorPosition(&line, &col);
 
750
        return line;
 
751
}
 
752
 
 
753
QString SciDoc::text() const { 
 
754
        return docInt_->edit1_->text(); 
 
755
}
 
756
 
 
757
QString SciDoc::text(int line) const { 
 
758
        return docInt_->edit1_->text(line); 
 
759
}
 
760
 
 
761
QString SciDoc::wordUnderCursor() const {
 
762
        JuffScintilla* edit = getActiveEdit();
 
763
        if ( !edit )
 
764
                return QString();
 
765
        
 
766
        return edit->wordUnderCursor(); 
 
767
}
 
768
 
 
769
QString SciDoc::selectedText() const {
 
770
        JuffScintilla* edit = getActiveEdit();
 
771
        if ( !edit )
 
772
                return QString();
 
773
        
 
774
        return edit->selectedText(); 
 
775
}
 
776
 
 
777
void SciDoc::getCursorPos(int& line, int& col) const {
 
778
        JuffScintilla* edit = getActiveEdit();
 
779
        if ( !edit )
 
780
                return;
 
781
        
 
782
        edit->getCursorPosition(&line, &col);
 
783
}
 
784
 
 
785
void SciDoc::setCursorPos(int line, int col) {
 
786
        JuffScintilla* edit = getActiveEdit();
 
787
        if ( !edit )
 
788
                return;
 
789
        
 
790
        edit->setCursorPosition(line, col);
 
791
        edit->setFocus();
 
792
}
 
793
 
 
794
void SciDoc::getSelection(int& line1, int& col1, int& line2, int& col2) const {
 
795
        JuffScintilla* edit = getActiveEdit();
 
796
        if ( !edit )
 
797
                return;
 
798
        
 
799
        edit->getSelection(&line1, &col1, &line2, &col2);
 
800
}
 
801
 
 
802
void SciDoc::setSelection(int line1, int col1, int line2, int col2) {
 
803
        JuffScintilla* edit = getActiveEdit();
 
804
        if ( !edit )
 
805
                return;
 
806
        
 
807
        edit->setSelection(line1, col1, line2, col2);
 
808
}
 
809
 
 
810
void SciDoc::insertText(const QString& text) {
 
811
        JuffScintilla* edit = getActiveEdit();
 
812
        if ( !edit )
 
813
                return;
 
814
        
 
815
        int row, col;
 
816
        getCursorPos(row, col);
 
817
        int newLines = text.count(QRegExp("\r\n|\n|\r"));
 
818
        edit->insert(text);
 
819
        if ( newLines == 0 )
 
820
                setCursorPos(row, col + text.length());
 
821
}
 
822
 
 
823
void SciDoc::removeSelectedText() {
 
824
        JuffScintilla* edit = getActiveEdit();
 
825
        if ( !edit )
 
826
                return;
 
827
        
 
828
        edit->removeSelectedText();
 
829
}
 
830
 
 
831
void SciDoc::replaceSelectedText(const QString& text) {
 
832
        JuffScintilla* edit = getActiveEdit();
 
833
        if ( !edit )
 
834
                return;
 
835
 
 
836
        edit->beginUndoAction();
 
837
        removeSelectedText();
 
838
        insertText(text);
 
839
        edit->endUndoAction();
 
840
}
 
841
 
 
842
int SciDoc::curScrollPos() const {
 
843
        JuffScintilla* edit = getActiveEdit();
 
844
        if ( !edit )
 
845
                return 0;
 
846
        
 
847
        QScrollBar* scr = edit->verticalScrollBar();
 
848
        if ( scr ) {
 
849
                return scr->value();
 
850
        }
 
851
        else {
 
852
                return 0;
 
853
        }
 
854
}
 
855
 
 
856
void SciDoc::setScrollPos(int pos) {
 
857
        JuffScintilla* edit = getActiveEdit();
 
858
        if ( !edit )
 
859
                return;
 
860
        
 
861
        QScrollBar* scr = edit->verticalScrollBar();
 
862
        if ( scr ) {
 
863
                scr->setValue(pos);
 
864
        }
 
865
}
 
866
 
 
867
 
 
868
void SciDoc::onMarginClicked (int margin, int line, Qt::KeyboardModifiers state) {
 
869
        JUFFENTRY;
 
870
        
 
871
        if ( margin == 1 ) {
 
872
                //      margin that contains line numbers
 
873
                toggleMarker(line);
 
874
        }
 
875
}
 
876
 
 
877
IntList SciDoc::markers() const {
 
878
        IntList list;
 
879
        int line = 0;
 
880
        while ( (line = docInt_->edit1_->markerFindNext(line, 2)) >= 0 ) {
 
881
                list << line++;
 
882
        }
 
883
        return list;
 
884
}
 
885
 
 
886
void SciDoc::toggleMarker(int line) {
 
887
        JuffScintilla* edit = getActiveEdit();
 
888
        if ( !edit )
 
889
                return;
 
890
 
 
891
        if ( edit->markersAtLine(line) & 2 ) {
 
892
                edit->markerDelete(line, 1);
 
893
                edit->markerDelete(line, 2);
 
894
        }
 
895
        else {
 
896
                edit->markerAdd(line, 1);
 
897
                edit->markerAdd(line, 2);
 
898
        }
 
899
 
 
900
        //      Markers will be added to/deleted from the 2nd edit 
 
901
        //      automatically since they share the same document
 
902
}
 
903
 
 
904
void SciDoc::toggleMarker() {
 
905
        JuffScintilla* edit = getActiveEdit();
 
906
        if ( !edit )
 
907
                return;
 
908
 
 
909
        int line, col;
 
910
        edit->getCursorPosition(&line, &col);
 
911
        toggleMarker(line);
 
912
}
 
913
 
 
914
void SciDoc::nextMarker() {
 
915
        JuffScintilla* edit = getActiveEdit();
 
916
        if ( !edit )
 
917
                return;
 
918
        
 
919
        int row(-1), col(-1);
 
920
        edit->getCursorPosition(&row, &col);
 
921
 
 
922
        int mLine = edit->markerFindNext(row + 1, 2);
 
923
        if ( mLine >= 0 ) {
 
924
                gotoLine(mLine);
 
925
        }
 
926
        else {
 
927
                mLine = edit->markerFindNext(0, 2);
 
928
                if ( mLine >= 0 ) {
 
929
                        gotoLine(mLine);
 
930
                }
 
931
        }
 
932
}
 
933
 
 
934
void SciDoc::prevMarker() {
 
935
        JuffScintilla* edit = getActiveEdit();
 
936
        if ( !edit )
 
937
                return;
 
938
        
 
939
        int row(-1), col(-1);
 
940
        edit->getCursorPosition(&row, &col);
 
941
 
 
942
        int mLine = edit->markerFindPrevious(row - 1 , 2);
 
943
        if ( mLine >= 0 ) {
 
944
                gotoLine(mLine);
 
945
        }
 
946
        else {
 
947
                mLine = edit->markerFindPrevious(lineCount() - 1, 2);
 
948
                if ( mLine >= 0 ) {
 
949
                        gotoLine(mLine);
 
950
                }
 
951
        }
 
952
}
 
953
 
 
954
void SciDoc::removeAllMarkers() {
 
955
        docInt_->edit1_->markerDeleteAll();
 
956
        
 
957
        //      Markers will be deleted from the 2nd edit 
 
958
        //      automatically since they share the same document
 
959
}
 
960
 
 
961
QString SciDoc::charset() const {
 
962
        return docInt_->charsetName_;
 
963
}
 
964
 
 
965
void SciDoc::setCharset(const QString& charset, bool confirm /*= false*/) {
 
966
        JUFFENTRY;
 
967
        
 
968
        QTextCodec* codec = QTextCodec::codecForName(charset.toAscii());
 
969
        if ( codec != 0 ) {
 
970
                int ret = QMessageBox::Yes;
 
971
                if ( confirm && isModified() && !isNoname(fileName()) ) {
 
972
                        QString str = tr("All unsaved changes will be lost.\nDo you want to proceed?");
 
973
                        ret = QMessageBox::question(widget(), tr("Warning"),
 
974
                                str, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
 
975
                }
 
976
                if ( ret == QMessageBox::Yes ) {
 
977
                        docInt_->codec_ = codec;
 
978
                        docInt_->charsetName_ = charset;
 
979
                        if ( !isNoname(fileName()) ) {
 
980
                                readDoc(true);
 
981
                                setModified(false);
 
982
                        }
 
983
                }
 
984
        }
 
985
}
 
986
 
 
987
QString SciDoc::syntax() const {
 
988
        return docInt_->syntax_;
 
989
}
 
990
 
 
991
void SciDoc::setSyntax(const QString& lexName) {
 
992
        if ( lexName.isEmpty() )
 
993
                return;
 
994
 
 
995
        docInt_->syntax_ = lexName;
 
996
 
 
997
        QsciLexer* lexer = LexerStorage::instance()->lexer(lexName);
 
998
 
 
999
        loadAutocompletionAPI(lexName, lexer);
 
1000
        
 
1001
        docInt_->edit1_->setLexer(lexer);
 
1002
        docInt_->edit2_->setLexer(lexer);
 
1003
}
 
1004
 
 
1005
void SciDoc::loadAutocompletionAPI(const QString& lexName, QsciLexer* lexer) {
 
1006
        if ( NULL == lexer )
 
1007
                return;
 
1008
        
 
1009
        QDir dir(AppInfo::configDirPath() + "/apis");
 
1010
        QString fileName = lexName.toLower() + ".api";
 
1011
        fileName.replace(QString("+"), "plus").replace(QString("#"), "sharp");
 
1012
        if ( dir.entryList(QDir::Files).contains(fileName) ) {
 
1013
                QsciAPIs* apis = new QsciAPIs(lexer);
 
1014
                if ( apis->load(dir.absoluteFilePath(fileName)) ) {
 
1015
                        apis->prepare();
 
1016
                        lexer->setAPIs(apis);
 
1017
                }
 
1018
                else {
 
1019
                        delete apis;
 
1020
                }
 
1021
        }
 
1022
}
 
1023
 
 
1024
EolMode SciDoc::eolMode() const {
 
1025
        if ( docInt_->edit1_->eolMode() == QsciScintilla::EolWindows ) {
 
1026
                return EolWin;
 
1027
        }
 
1028
        else if ( docInt_->edit1_->eolMode() == QsciScintilla::EolMac ) {
 
1029
                return EolMac;
 
1030
        }
 
1031
        else {
 
1032
                return EolUnix;
 
1033
        }
 
1034
}
 
1035
 
 
1036
void SciDoc::setEolMode(EolMode eol) {
 
1037
        switch ( eol ) {
 
1038
                case EolWin: 
 
1039
                        docInt_->edit1_->convertEols(QsciScintilla::EolWindows);
 
1040
                        docInt_->edit1_->setEolMode(QsciScintilla::EolWindows); 
 
1041
                        break;
 
1042
                
 
1043
                case EolMac: 
 
1044
                        docInt_->edit1_->convertEols(QsciScintilla::EolMac); 
 
1045
                        docInt_->edit1_->setEolMode(QsciScintilla::EolMac); 
 
1046
                        break;
 
1047
                
 
1048
                case EolUnix: 
 
1049
                        docInt_->edit1_->convertEols(QsciScintilla::EolUnix); 
 
1050
                        docInt_->edit1_->setEolMode(QsciScintilla::EolUnix); 
 
1051
                        break;
 
1052
        }
 
1053
}
 
1054
 
 
1055
/*QsciMacro* SciDoc::newMacro() {
 
1056
        JuffScintilla* edit = getActiveEdit();
 
1057
        if ( !edit )
 
1058
                return 0;
 
1059
        
 
1060
        return new QsciMacro(edit);
 
1061
}
 
1062
 
 
1063
void SciDoc::runMacro(const QString& mcr) {
 
1064
        JuffScintilla* edit = getActiveEdit();
 
1065
        if ( !edit )
 
1066
                return;
 
1067
 
 
1068
        QsciMacro macro(edit);
 
1069
        if ( macro.load(mcr) ) {
 
1070
                macro.play();
 
1071
        }
 
1072
}*/
 
1073
 
 
1074
void SciDoc::goToMatchingBrace() {
 
1075
        JuffScintilla* edit = getActiveEdit();
 
1076
        if ( !edit )
 
1077
                return;
 
1078
        
 
1079
        edit->moveToMatchingBrace();
 
1080
}
 
1081
 
 
1082
void SciDoc::selectToMatchingBrace() {
 
1083
        JuffScintilla* edit = getActiveEdit();
 
1084
        if ( !edit )
 
1085
                return;
 
1086
        
 
1087
        edit->selectToMatchingBrace();
 
1088
}
 
1089
 
 
1090
void SciDoc::commentLine(JuffScintilla* edit, int line, const QString& str1, const QString& comment) {
 
1091
        QString str2 = comment + str1;
 
1092
        edit->setSelection(line, 0, line + 1, 0);
 
1093
        replaceSelectedText(str2);
 
1094
}
 
1095
 
 
1096
void SciDoc::uncommentLine(JuffScintilla* edit, int line, const QString& str1, const QString& comment) {
 
1097
        int pos = str1.indexOf(comment);
 
1098
        QString str2 = str1;
 
1099
        str2.replace(pos, comment.length(), "");
 
1100
        edit->setSelection(line, 0, line + 1, 0);
 
1101
        replaceSelectedText(str2);
 
1102
}
 
1103
 
 
1104
void SciDoc::toggleLineComment() {
 
1105
        JUFFENTRY;
 
1106
 
 
1107
        JuffScintilla* edit = getActiveEdit();
 
1108
        if ( !edit )
 
1109
                return;
 
1110
 
 
1111
        QString comment;
 
1112
        QString& s = docInt_->syntax_;
 
1113
        if ( s == "C++" || s == "PHP" || s == "C#" || s == "Java" || s == "JavaScript" )
 
1114
                comment = "//";
 
1115
        else if ( s == "Bash" || s == "Python" || s == "CMake" || s == "Makefile" )
 
1116
                comment = "#";
 
1117
        else if ( s == "Fortran" )
 
1118
                comment = "!";
 
1119
        //      TODO : need to add more syntaxes
 
1120
 
 
1121
        if ( comment.isEmpty() )
 
1122
                return;
 
1123
 
 
1124
        if ( edit->hasSelectedText() ) {
 
1125
                int line1, col1, line2, col2, curLine, curCol;
 
1126
                edit->getSelection(&line1, &col1, &line2, &col2);
 
1127
                edit->getCursorPosition(&curLine, &curCol);
 
1128
 
 
1129
                QString str1 = text(line1);
 
1130
                QString ln = str1.simplified();
 
1131
                bool toComment = true;
 
1132
                if ( ln.startsWith(comment) ) {
 
1133
                        toComment = false;
 
1134
                }
 
1135
 
 
1136
                if ( col2 == 0 )
 
1137
                        --line2;
 
1138
 
 
1139
                edit->beginUndoAction();
 
1140
                for ( int line = line1; line <= line2; ++line ) {
 
1141
                        str1 = text(line);
 
1142
                        if ( toComment ) {
 
1143
                                if ( !str1.simplified().startsWith(comment) )
 
1144
                                        commentLine(edit, line, str1, comment);
 
1145
                        }
 
1146
                        else {
 
1147
                                if ( str1.simplified().startsWith(comment) )
 
1148
                                        uncommentLine(edit, line, str1, comment);
 
1149
                        }
 
1150
                }
 
1151
                edit->endUndoAction();
 
1152
                if ( curCol > 0 )
 
1153
                        edit->setCursorPosition(curLine, curCol + comment.length() * (toComment ? 1 : -1) );
 
1154
                else
 
1155
                        edit->setCursorPosition(curLine, curCol);
 
1156
        }
 
1157
        else {
 
1158
                int line1, col1;
 
1159
                edit->getCursorPosition(&line1, &col1);
 
1160
                QString str1 = text(line1);
 
1161
 
 
1162
                QString ln = str1.simplified();
 
1163
                if ( ln.startsWith(comment) ) {
 
1164
                        uncommentLine(edit, line1, str1, comment);
 
1165
                        edit->setCursorPosition(line1, col1 - comment.length());
 
1166
                }
 
1167
                else {
 
1168
                        commentLine(edit, line1, str1, comment);
 
1169
                        edit->setCursorPosition(line1, col1 + comment.length());
 
1170
                }
 
1171
        }
 
1172
}
 
1173
 
 
1174
void SciDoc::toggleBlockComment() {
 
1175
        JUFFENTRY;
 
1176
 
 
1177
        JuffScintilla* edit = getActiveEdit();
 
1178
        if ( !edit )
 
1179
                return;
 
1180
 
 
1181
        QString commBeg, commEnd;
 
1182
        QString& s = docInt_->syntax_;
 
1183
        if ( s == "C++" || s == "Java" || s == "C#" || s == "PHP" || s == "CSS" || s == "JavaScript" ) {
 
1184
                commBeg = "/*";
 
1185
                commEnd = "*/";
 
1186
        }
 
1187
        else if ( docInt_->syntax_ == "HTML" || docInt_->syntax_ == "XML" ) {
 
1188
                commBeg = "<!--";
 
1189
                commEnd = "-->";
 
1190
        }
 
1191
        else if ( docInt_->syntax_ == "Python" ) {
 
1192
                commBeg = "'''";
 
1193
                commEnd = "'''";
 
1194
        }
 
1195
        //      TODO : need to add more syntaxes
 
1196
 
 
1197
        if ( commBeg.isEmpty() || commEnd.isEmpty() )
 
1198
                return;
 
1199
 
 
1200
        if ( edit->hasSelectedText() ) {
 
1201
                int line1, col1, line2, col2, curLine, curCol;
 
1202
                edit->getSelection(&line1, &col1, &line2, &col2);
 
1203
                edit->getCursorPosition(&curLine, &curCol);
 
1204
                
 
1205
                QString str1 = edit->selectedText();
 
1206
                bool toComment = true;
 
1207
                if ( str1.startsWith(commBeg) && str1.endsWith(commEnd) )
 
1208
                        toComment = false;
 
1209
 
 
1210
                QString str2;
 
1211
                if ( toComment )
 
1212
                        str2 = commBeg + str1 + commEnd;
 
1213
                else {
 
1214
                        str2 = str1;
 
1215
                        str2.chop(commEnd.length());
 
1216
                        str2.remove(0, commBeg.length());
 
1217
                }
 
1218
                replaceSelectedText(str2);
 
1219
                if ( line1 == line2 ) {
 
1220
                        if ( curCol == col1 )
 
1221
                                edit->setCursorPosition(curLine, curCol);
 
1222
                        else
 
1223
                                edit->setCursorPosition(curLine, curCol + (commBeg.length() + commEnd.length()) * (toComment ? 1 : -1));
 
1224
                }
 
1225
                else {
 
1226
                        if ( curLine == line2 && curCol == col2)
 
1227
                                edit->setCursorPosition(curLine, curCol + commEnd.length() * (toComment ? 1 : -1) );
 
1228
                        else
 
1229
                                edit->setCursorPosition(curLine, curCol);
 
1230
                }
 
1231
        }
 
1232
}
 
1233
 
 
1234
void SciDoc::duplicateLine() {
 
1235
        JUFFENTRY;
 
1236
 
 
1237
        JuffScintilla* edit = getActiveEdit();
 
1238
        if ( !edit )
 
1239
                return;
 
1240
        
 
1241
        if ( edit->hasSelectedText() )
 
1242
                edit->SendScintilla(QsciScintilla::SCI_SELECTIONDUPLICATE);
 
1243
        else
 
1244
                edit->SendScintilla(QsciScintilla::SCI_LINEDUPLICATE);
 
1245
}
 
1246
 
 
1247
void SciDoc::moveLineUp() {
 
1248
        JUFFENTRY;
 
1249
 
 
1250
        JuffScintilla* edit = getActiveEdit();
 
1251
        if ( !edit )
 
1252
                return;
 
1253
        
 
1254
        edit->SendScintilla(QsciScintilla::SCI_LINETRANSPOSE);
 
1255
        edit->SendScintilla(QsciScintilla::SCI_LINEUP);
 
1256
}
 
1257
 
 
1258
void SciDoc::deleteCurrentLine() {
 
1259
        JUFFENTRY;
 
1260
 
 
1261
        JuffScintilla* edit = getActiveEdit();
 
1262
        if ( !edit )
 
1263
                return;
 
1264
        
 
1265
        edit->SendScintilla(QsciScintilla::SCI_LINEDELETE);
 
1266
}
 
1267
 
 
1268
void SciDoc::toUpperCase()
 
1269
{
 
1270
        JUFFENTRY;
 
1271
 
 
1272
        JuffScintilla* edit = getActiveEdit();
 
1273
        if ( !edit )
 
1274
                return;
 
1275
        
 
1276
        edit->SendScintilla(QsciScintilla::SCI_UPPERCASE);
 
1277
}
 
1278
 
 
1279
void SciDoc::toLowerCase()
 
1280
{
 
1281
        JUFFENTRY;
 
1282
 
 
1283
        JuffScintilla* edit = getActiveEdit();
 
1284
        if ( !edit )
 
1285
                return;
 
1286
        
 
1287
        edit->SendScintilla(QsciScintilla::SCI_LOWERCASE);
 
1288
}
 
1289
 
 
1290
void SciDoc::changeSplitOrientation() {
 
1291
        JUFFENTRY;
 
1292
        
 
1293
        if ( docInt_->spl_->orientation() == Qt::Vertical ) {
 
1294
                docInt_->spl_->setOrientation(Qt::Horizontal);
 
1295
        }
 
1296
        else {
 
1297
                docInt_->spl_->setOrientation(Qt::Vertical);
 
1298
        }
 
1299
}
 
1300
 
 
1301
void SciDoc::onLinesCountChanged() {
 
1302
        emit linesCountChanged(lineCount());
 
1303
}
 
1304
 
 
1305
void SciDoc::onEditReceivedFocus() {
 
1306
        JuffScintilla* edit = qobject_cast<JuffScintilla*>(sender());
 
1307
        if ( !edit )
 
1308
                return;
 
1309
        
 
1310
        docInt_->curEdit_ = edit;
 
1311
}
 
1312
 
 
1313
}
 
1314