diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 4412f62b..69a9b6ba 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -2,7 +2,7 @@ QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -CONFIG += c++14 +CONFIG += c++17 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. @@ -27,12 +27,15 @@ SOURCES += \ qsynedit/TextBuffer.cpp \ qsynedit/TextPainter.cpp \ qsynedit/exporter/synexporter.cpp \ + qsynedit/exporter/synhtmlexporter.cpp \ + qsynedit/exporter/synrtfexporter.cpp \ qsynedit/highlighter/base.cpp \ qsynedit/highlighter/composition.cpp \ qsynedit/highlighter/cpp.cpp \ settingsdialog/compilersetdirectorieswidget.cpp \ settingsdialog/compilersetoptionwidget.cpp \ settings.cpp \ + settingsdialog/editorclipboardwidget.cpp \ settingsdialog/editorfontwidget.cpp \ settingsdialog/editorgeneralwidget.cpp \ settingsdialog/settingsdialog.cpp \ @@ -61,12 +64,15 @@ HEADERS += \ qsynedit/TextPainter.h \ qsynedit/Types.h \ qsynedit/exporter/synexporter.h \ + qsynedit/exporter/synhtmlexporter.h \ + qsynedit/exporter/synrtfexporter.h \ qsynedit/highlighter/base.h \ qsynedit/highlighter/composition.h \ qsynedit/highlighter/cpp.h \ settingsdialog/compilersetdirectorieswidget.h \ settingsdialog/compilersetoptionwidget.h \ settings.h \ + settingsdialog/editorclipboardwidget.h \ settingsdialog/editorfontwidget.h \ settingsdialog/editorgeneralwidget.h \ settingsdialog/settingsdialog.h \ @@ -81,6 +87,7 @@ FORMS += \ mainwindow.ui \ settingsdialog/compilersetdirectorieswidget.ui \ settingsdialog/compilersetoptionwidget.ui \ + settingsdialog/editorclipboardwidget.ui \ settingsdialog/editorfontwidget.ui \ settingsdialog/editorgeneralwidget.ui \ settingsdialog/settingsdialog.ui diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 0e184885..3336aeb1 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -12,8 +12,13 @@ #include #include #include +#include #include "qsynedit/highlighter/cpp.h" #include "HighlighterManager.h" +#include "qsynedit/exporter/synrtfexporter.h" +#include "qsynedit/exporter/synhtmlexporter.h" +#include +#include using namespace std; @@ -88,56 +93,23 @@ Editor::~Editor() { void Editor::loadFile() { QFile file(mFilename); -// if (!file.open(QFile::ReadOnly)) { -// QMessageBox::information(pMainWindow, -// tr("Error"), -// QString(tr("Can't Open File %1:%2")).arg(mFilename).arg(file.errorString())); -// } this->lines()->LoadFromFile(file,mEncodingOption,mFileEncoding); this->setModified(false); updateCaption(); - pMainWindow->updateStatusBarForEncoding(); + pMainWindow->updateForEncodingInfo(); } void Editor::saveFile(const QString &filename) { -// if (mEncodingOption!=ENCODING_AUTO_DETECT && mEncodingOption!=mFileEncoding) { -// mFileEncoding = mEncodingOption; -// } -// if (mEncodingOption == ENCODING_AUTO_DETECT && mFileEncoding == ENCODING_ASCII) { -// if (!isTextAllAscii(this->text())) { -// mFileEncoding = pSettings->editor().defaultEncoding(); -// } -// pMainWindow->updateStatusBarForEncoding(); -// //todo: update status bar, and set fileencoding using configurations -// } QFile file(filename); this->lines()->SaveToFile(file,mEncodingOption,mFileEncoding); - pMainWindow->updateStatusBarForEncoding(); -// QByteArray ba; -// if (mFileEncoding == ENCODING_UTF8) { -// ba = this->text().toUtf8(); -// } else if (mFileEncoding == ENCODING_UTF8_BOM) { -// ba.resize(3); -// ba[0]=0xEF; -// ba[1]=0xBB; -// ba[2]=0xBF; -// ba.append(this->text().toUtf8()); -// } else if (mFileEncoding == ENCODING_ASCII) { -// ba = this->text().toLatin1(); -// } else if (mFileEncoding == ENCODING_SYSTEM_DEFAULT) { -// ba = this->text().toLocal8Bit(); -// } else { -// QTextCodec* codec = QTextCodec::codecForName(mFileEncoding); -// ba = codec->fromUnicode(this->text()); -// } -// if (file.open(QFile::WriteOnly)) { -// if (file.write(ba)<0) { -// throw SaveException(QString(tr("Failed to Save file %1: %2")).arg(filename).arg(file.errorString())); -// } -// file.close(); -// } else { -// throw SaveException(QString(tr("Failed to Open file %1: %2")).arg(filename).arg(file.errorString())); -// } + pMainWindow->updateForEncodingInfo(); +} + +void Editor::convertToEncoding(const QByteArray &encoding) +{ + mEncodingOption = encoding; + setModified(true); + save(); } bool Editor::save(bool force, bool reparse) { @@ -155,6 +127,8 @@ bool Editor::save(bool force, bool reparse) { try { saveFile(mFilename); setModified(false); + mIsNew = false; + this->updateCaption(); } catch (SaveException& exception) { QMessageBox::information(pMainWindow,tr("Fail"), exception.reason()); @@ -177,10 +151,11 @@ bool Editor::saveAs(){ return false; } try { - saveFile(mFilename); mFilename = newName; + saveFile(mFilename); mIsNew = false; setModified(false); + this->updateCaption(); } catch (SaveException& exception) { QMessageBox::information(pMainWindow,tr("Fail"), exception.reason()); @@ -206,6 +181,10 @@ const QByteArray& Editor::encodingOption() const noexcept{ } void Editor::setEncodingOption(const QByteArray& encoding) noexcept{ mEncodingOption = encoding; + if (!this->isNew()) + this->loadFile(); + else + pMainWindow->updateForEncodingInfo(); } const QByteArray& Editor::fileEncoding() const noexcept{ return mFileEncoding; @@ -226,20 +205,17 @@ QTabWidget* Editor::pageControl() noexcept{ void Editor::wheelEvent(QWheelEvent *event) { if ( (event->modifiers() & Qt::ControlModifier)!=0) { - QFont oldFont = font(); - int size = oldFont.pointSize(); + int size = pSettings->editor().fontSize(); if (event->angleDelta().y()>0) { -// size = std::max(5,size-1); -// oldFont.setPointSize(oldFont.pointSize()); -// this->setFont(oldFont); - this->zoomIn(); + size = std::min(99,size+1); + pSettings->editor().setFontSize(size); + pMainWindow->updateEditorSettings(); event->accept(); return; } else { -// size = std::min(size+1,50); -// oldFont.setPointSize(oldFont.pointSize()); -// this->setFont(oldFont); - this->zoomOut(); + size = std::max(2,size-1); + pSettings->editor().setFontSize(size); + pMainWindow->updateEditorSettings(); event->accept(); return; } @@ -247,19 +223,96 @@ void Editor::wheelEvent(QWheelEvent *event) { SynEdit::wheelEvent(event); } +void Editor::focusInEvent(QFocusEvent *event) +{ + SynEdit::focusInEvent(event); + pMainWindow->updateEditorActions(); + pMainWindow->updateStatusbarForLineCol(); + pMainWindow->updateForStatusbarModeInfo(); +} + +void Editor::focusOutEvent(QFocusEvent *event) +{ + SynEdit::focusOutEvent(event); + pMainWindow->updateEditorActions(); + pMainWindow->updateStatusbarForLineCol(); + pMainWindow->updateForStatusbarModeInfo(); +} + +void Editor::copyToClipboard() +{ + if (pSettings->editor().copySizeLimit()) { + if (lines()->count() > pSettings->editor().copyLineLimits()) { + QMessageBox::information(pMainWindow,tr("Fail"), + tr("The text to be copied exceeds count limit!")); + return; + } + if (lines()->getTextLength() > pSettings->editor().copyCharLimits() * 1000) { + QMessageBox::information(pMainWindow,tr("Fail"), + tr("The text to be copied exceeds character limit!")); + return; + } + } + switch(pSettings->editor().copyWithFormatAs()) { + case 1: //HTML + copyAsHTML(); + break;; + default: + SynEdit::copyToClipboard(); + } +} + +void Editor::cutToClipboard() +{ + if (pSettings->editor().copySizeLimit()) { + if (lines()->count() > pSettings->editor().copyLineLimits()) { + QMessageBox::information(pMainWindow,tr("Fail"), + tr("The text to be cut exceeds count limit!")); + return; + } + if (lines()->getTextLength() > pSettings->editor().copyCharLimits() * 1000) { + QMessageBox::information(pMainWindow,tr("Fail"), + tr("The text to be cut exceeds character limit!")); + return; + } + } + SynEdit::cutToClipboard(); +} + +void Editor::copyAsHTML() +{ + if (!selAvail()) + return; + SynHTMLExporter SynExporterHTML; + + SynExporterHTML.setTitle(QFileInfo(mFilename).fileName()); + SynExporterHTML.setExportAsText(false); + SynExporterHTML.setUseBackground(true); + SynExporterHTML.setFont(font()); + SynExporterHTML.setHighlighter(highlighter()); + SynExporterHTML.setCreateHTMLFragment(true); + //SynExporterRTF.OnFormatToken := ExporterFormatToken; + + + SynExporterHTML.ExportRange(lines(),blockBegin(),blockEnd()); + + //SynExporterHTML.CopyToClipboard(); + + QMimeData * mimeData = new QMimeData; + + //sethtml will convert buffer to QString , which will cause encoding trouble + mimeData->setData(SynExporterHTML.clipboardFormat(),SynExporterHTML.buffer()); + //mimeData->setHtml("test"); + mimeData->setText(selText()); + + QGuiApplication::clipboard()->clear(); + QGuiApplication::clipboard()->setMimeData(mimeData); +} + void Editor::onModificationChanged(bool) { updateCaption(); } -void Editor::onCursorPositionChanged(int line, int index) { - pMainWindow->updateStatusBarForEditingInfo(line,index+1,lines()->count(),lines()->getTextLength()); -} - -void Editor::onLinesChanged(int startLine, int count) { - qDebug()<<"Editor lines changed"<count(); - qDebug()< fLineCount) @@ -295,8 +348,7 @@ void Editor::onStatusChanged(SynStatusChanges changes) // scSelection includes anything caret related if (changes.testFlag(SynStatusChange::scSelection)) { - //MainForm.SetStatusbarLineCol; - + pMainWindow->updateStatusbarForLineCol(); // // Update the function tip // fFunctionTip.ForceHide := false; @@ -338,17 +390,10 @@ void Editor::onStatusChanged(SynStatusChanges changes) // end; // end; -// if scInsertMode in Changes then begin -// with MainForm.Statusbar do begin -// // Set readonly / insert / overwrite -// if fText.ReadOnly then -// Panels[2].Text := Lang[ID_READONLY] -// else if fText.InsertMode then -// Panels[2].Text := Lang[ID_INSERT] -// else -// Panels[2].Text := Lang[ID_OVERWRITE]; -// end; -// end; + if (changes.testFlag(scInsertMode) | changes.testFlag(scReadOnly)) + pMainWindow->updateForStatusbarModeInfo(); + + pMainWindow->updateEditorActions(); // mainForm.CaretList.AddCaret(self,fText.CaretY,fText.CaretX); } diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index 4a1e253a..96a0ae8d 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -56,6 +56,7 @@ public: void loadFile(); void saveFile(const QString& filename); + void convertToEncoding(const QByteArray& encoding); bool save(bool force=false, bool reparse=true); bool saveAs(); void activate(); @@ -64,14 +65,14 @@ public: void updateCaption(const QString& newCaption=QString()); void applySettings(); - + void copyToClipboard() override; + void cutToClipboard() override; + void copyAsHTML(); signals: protected slots: void onModificationChanged(bool status) ; - void onCursorPositionChanged(int line, int index) ; - void onLinesChanged(int startLine, int count) ; void onStatusChanged(SynStatusChanges changes); private: @@ -86,6 +87,8 @@ private: // QWidget interface protected: void wheelEvent(QWheelEvent *event) override; + void focusInEvent(QFocusEvent *event); + void focusOutEvent(QFocusEvent *event); }; #endif // EDITOR_H diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 61a84b90..98f42c8e 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -12,6 +12,10 @@ #include "settingsdialog/settingsdialog.h" #include "compiler/compilermanager.h" +#include +#include +#include +#include #include MainWindow* pMainWindow; @@ -24,10 +28,13 @@ MainWindow::MainWindow(QWidget *parent) // status bar mFileInfoStatus=new QLabel(); mFileEncodingStatus = new QLabel(); + mFileModeStatus = new QLabel(); mFileInfoStatus->setStyleSheet("margin-left:10px; margin-right:10px"); mFileEncodingStatus->setStyleSheet("margin-left:10px; margin-right:10px"); + mFileModeStatus->setStyleSheet("margin-left:10px; margin-right:10px"); ui->statusbar->addWidget(mFileInfoStatus); ui->statusbar->addWidget(mFileEncodingStatus); + ui->statusbar->addWidget(mFileModeStatus); mEditorList = new EditorList(ui->EditorTabsLeft, ui->EditorTabsRight, ui->EditorPanelSplitter, @@ -48,6 +55,22 @@ MainWindow::MainWindow(QWidget *parent) ui->tableIssues->setErrorColor(QColor("Red")); ui->tableIssues->setWarningColor(QColor("Orange")); + + mMenuEncoding = new QMenu(); + mMenuEncoding->setTitle(tr("File Encoding")); + mMenuEncoding->addAction(ui->actionAuto_Detect); + mMenuEncoding->addAction(ui->actionEncode_in_ANSI); + mMenuEncoding->addAction(ui->actionEncode_in_UTF_8); + mMenuEncoding->addSeparator(); + mMenuEncoding->addAction(ui->actionConvert_to_ANSI); + mMenuEncoding->addAction(ui->actionConvert_to_UTF_8); + ui->menuEdit->insertMenu(ui->actionFoldAll,mMenuEncoding); + ui->menuEdit->insertSeparator(ui->actionFoldAll); + ui->actionAuto_Detect->setCheckable(true); + ui->actionEncode_in_ANSI->setCheckable(true); + ui->actionEncode_in_UTF_8->setCheckable(true); + + updateEditorActions(); } MainWindow::~MainWindow() @@ -55,20 +78,21 @@ MainWindow::~MainWindow() delete ui; } -void MainWindow::updateStatusBarForEncoding() { +void MainWindow::updateForEncodingInfo() { Editor * editor = mEditorList->getEditor(); if (editor!=NULL) { - mFileEncodingStatus->setText(editor->fileEncoding()); - } -} - -void MainWindow::updateStatusBarForEditingInfo(int line,int col,int lines,int charCount) -{ - Editor * editor = mEditorList->getEditor(); - if (editor!=NULL) { - mFileInfoStatus->setText( - QString(tr("Line: %1 Col: %2 Lines: %3 Chars: %4")).arg(line) - .arg(col).arg(lines).arg(charCount)); + mFileEncodingStatus->setText( + QString("%1(%2)") + .arg(QString(editor->encodingOption())) + .arg(QString(editor->fileEncoding()))); + ui->actionAuto_Detect->setChecked(editor->encodingOption() == ENCODING_AUTO_DETECT); + ui->actionEncode_in_ANSI->setChecked(editor->encodingOption() == ENCODING_SYSTEM_DEFAULT); + ui->actionEncode_in_UTF_8->setChecked(editor->encodingOption() == ENCODING_UTF8); + } else { + mFileEncodingStatus->setText(""); + ui->actionAuto_Detect->setChecked(false); + ui->actionEncode_in_ANSI->setChecked(false); + ui->actionEncode_in_UTF_8->setChecked(false); } } @@ -77,6 +101,93 @@ void MainWindow::updateEditorSettings() mEditorList->applySettings(); } +void MainWindow::updateEditorActions() +{ + Editor* e = mEditorList->getEditor(); + if (e==nullptr) { + ui->actionAuto_Detect->setEnabled(false); + ui->actionEncode_in_ANSI->setEnabled(false); + ui->actionEncode_in_UTF_8->setEnabled(false); + ui->actionConvert_to_ANSI->setEnabled(false); + ui->actionConvert_to_UTF_8->setEnabled(false); + ui->actionCompile->setEnabled(false); + ui->actionCopy->setEnabled(false); + ui->actionCut->setEnabled(false); + ui->actionFoldAll->setEnabled(false); + ui->actionIndent->setEnabled(false); + ui->actionPaste->setEnabled(false); + ui->actionRedo->setEnabled(false); + ui->actionRun->setEnabled(false); + ui->actionSave->setEnabled(false); + ui->actionSaveAs->setEnabled(false); + ui->actionSaveAll->setEnabled(false); + ui->actionSelectAll->setEnabled(false); + ui->actionToggleComment->setEnabled(false); + ui->actionUnIndent->setEnabled(false); + ui->actionUndo->setEnabled(false); + ui->actionUnfoldAll->setEnabled(false); + } else { + ui->actionAuto_Detect->setEnabled(true); + ui->actionEncode_in_ANSI->setEnabled(true); + ui->actionEncode_in_UTF_8->setEnabled(true); + ui->actionConvert_to_ANSI->setEnabled(e->encodingOption()!=ENCODING_SYSTEM_DEFAULT && e->fileEncoding()!=ENCODING_SYSTEM_DEFAULT); + ui->actionConvert_to_UTF_8->setEnabled(e->encodingOption()!=ENCODING_UTF8 && e->fileEncoding()!=ENCODING_UTF8); + //if (e->compilable()) + ui->actionCompile->setEnabled(true); + ui->actionRun->setEnabled(true); + ui->actionCopy->setEnabled(e->selAvail()); + ui->actionCut->setEnabled(e->selAvail()); + ui->actionFoldAll->setEnabled(e->lines()->count()>0); + ui->actionIndent->setEnabled(!e->readOnly()); + + ui->actionPaste->setEnabled(!e->readOnly() && !QGuiApplication::clipboard()->text().isEmpty()); + ui->actionRedo->setEnabled(e->canRedo()); + ui->actionUndo->setEnabled(e->canUndo()); + ui->actionSave->setEnabled(e->modified()); + ui->actionSaveAs->setEnabled(true); + ui->actionSaveAll->setEnabled(true); + ui->actionSelectAll->setEnabled(e->lines()->count()>0); + ui->actionToggleComment->setEnabled(!e->readOnly() && e->lines()->count()>0); + ui->actionUnIndent->setEnabled(!e->readOnly() && e->lines()->count()>0); + ui->actionUnfoldAll->setEnabled(e->lines()->count()>0); + } + +} + +void MainWindow::updateStatusbarForLineCol() +{ + Editor* e = mEditorList->getEditor(); + if (e!=nullptr) { + QString msg = tr("Line:%1 Col:%2 Selected:%3 Lines:%4 Length:%5") + .arg(e->caretY(),6) + .arg(e->caretX(),6) + .arg(e->selText().length(),6) + .arg(e->lines()->count(),6) + .arg(e->lines()->getTextLength(),6); + mFileInfoStatus->setText(msg); + } else { + mFileInfoStatus->setText(""); + } +} + +void MainWindow::updateForStatusbarModeInfo() +{ + Editor* e = mEditorList->getEditor(); + if (e!=nullptr) { + QString msg; + if (e->readOnly()) { + msg = tr("Read Only"); + } else if (e->insertMode()) { + msg = tr("Insert"); + } else { + msg = tr("Overwrite"); + } + mFileModeStatus->setText(msg); + } else { + mFileModeStatus->setText(""); + } +} + void MainWindow::openFiles(const QStringList &files) { mEditorList->beginUpdate(); @@ -99,7 +210,7 @@ void MainWindow::openFile(const QString &filename) editor = mEditorList->newEditor(filename,ENCODING_AUTO_DETECT, false,false); editor->activate(); - this->updateStatusBarForEncoding(); + this->updateForEncodingInfo(); } void MainWindow::setupActions() { @@ -124,7 +235,7 @@ void MainWindow::on_actionNew_triggered() { Editor * editor=mEditorList->newEditor("",ENCODING_AUTO_DETECT,false,true); editor->activate(); - updateStatusBarForEncoding(); + updateForEncodingInfo(); } void MainWindow::on_EditorTabsLeft_tabCloseRequested(int index) @@ -313,3 +424,54 @@ void MainWindow::on_tableIssues_doubleClicked(const QModelIndex &index) //editor->setCursorPosition(issue->line-1,issue->column-1); editor->activate(); } + +void MainWindow::on_actionEncode_in_ANSI_triggered() +{ + Editor * editor = mEditorList->getEditor(); + if (editor == nullptr) + return; + editor->setEncodingOption(ENCODING_SYSTEM_DEFAULT); +} + +void MainWindow::on_actionEncode_in_UTF_8_triggered() +{ + Editor * editor = mEditorList->getEditor(); + if (editor == nullptr) + return; + editor->setEncodingOption(ENCODING_UTF8); +} + +void MainWindow::on_actionAuto_Detect_triggered() +{ + Editor * editor = mEditorList->getEditor(); + if (editor == nullptr) + return; + editor->setEncodingOption(ENCODING_AUTO_DETECT); +} + +void MainWindow::on_actionConvert_to_ANSI_triggered() +{ + Editor * editor = mEditorList->getEditor(); + if (editor == nullptr) + return; + if (QMessageBox::information(this,tr("Confirm Convertion"), + tr("The editing file will be saved using %1 encoding.
This operation can't be reverted.
Are you sure to continue?") + .arg(QString(QTextCodec::codecForLocale()->name())), + QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes) + return; + editor->convertToEncoding(ENCODING_SYSTEM_DEFAULT); + +} + +void MainWindow::on_actionConvert_to_UTF_8_triggered() +{ + Editor * editor = mEditorList->getEditor(); + if (editor == nullptr) + return; + if (QMessageBox::information(this,tr("Confirm Convertion"), + tr("The editing file will be saved using %1 encoding.
This operation can't be reverted.
Are you sure to continue?") + .arg(ENCODING_UTF8), + QMessageBox::Yes, QMessageBox::No)!=QMessageBox::Yes) + return; + editor->convertToEncoding(ENCODING_UTF8); +} diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 9b26063f..a441b957 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -22,9 +22,11 @@ public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); - void updateStatusBarForEncoding(); - void updateStatusBarForEditingInfo(int line,int col,int lines,int charCount); + void updateForEncodingInfo(); + void updateStatusbarForLineCol(); + void updateForStatusbarModeInfo(); void updateEditorSettings(); + void updateEditorActions(); protected: void openFiles(const QStringList& files); @@ -73,6 +75,16 @@ private slots: void on_tableIssues_doubleClicked(const QModelIndex &index); + void on_actionEncode_in_ANSI_triggered(); + + void on_actionEncode_in_UTF_8_triggered(); + + void on_actionAuto_Detect_triggered(); + + void on_actionConvert_to_ANSI_triggered(); + + void on_actionConvert_to_UTF_8_triggered(); + public slots: void onCompileLog(const QString& msg); void onCompileIssue(PCompileIssue issue); @@ -87,6 +99,9 @@ private: EditorList* mEditorList; QLabel* mFileInfoStatus; QLabel* mFileEncodingStatus; + QLabel* mFileModeStatus; + QMenu * mMenuEncoding; + QMenu * mMenuEncodingList; QComboBox* mCompilerSet; CompilerManager* mCompilerManager; diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index 1ad0a71f..92fbed54 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -250,7 +250,7 @@ 0 0 946 - 25 + 26 @@ -546,6 +546,9 @@ + + true + Collapse All @@ -555,6 +558,31 @@ Uncollapse All + + + Encode in ANSI + + + + + Encode in UTF-8 + + + + + Auto Detect + + + + + Convert to ANSI + + + + + Convert to UTF-8 + + diff --git a/RedPandaIDE/qsynedit/MiscProcs.cpp b/RedPandaIDE/qsynedit/MiscProcs.cpp index 4d5879ef..09d66281 100644 --- a/RedPandaIDE/qsynedit/MiscProcs.cpp +++ b/RedPandaIDE/qsynedit/MiscProcs.cpp @@ -438,7 +438,7 @@ bool InternalEnumHighlighterAttris(PSynHighlighter Highlighter, } else if (Highlighter) { for (PSynHighlighterAttribute pAttr: Highlighter->attributes()){ QString UniqueAttriName = Highlighter->getName() - + HighlighterList.indexOf(Highlighter) + '.' + + QString("%1").arg(HighlighterList.indexOf(Highlighter)) + '.' + pAttr->name(); Result = highlighterAttriProc(Highlighter, pAttr, UniqueAttriName, Params); diff --git a/RedPandaIDE/qsynedit/MiscProcs.h b/RedPandaIDE/qsynedit/MiscProcs.h index 5f80ff27..68b2cc6c 100644 --- a/RedPandaIDE/qsynedit/MiscProcs.h +++ b/RedPandaIDE/qsynedit/MiscProcs.h @@ -74,7 +74,7 @@ QString DecodeString(const QString& s); using HighlighterAttriProc = std::function Params)>; + QList Params)>; // Enums all child highlighters and their attributes of a TSynMultiSyn through a // callback function. diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 6b2e029f..89e4e348 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -290,10 +290,34 @@ void SynEdit::setCaretXYCentered(bool ForceToMiddle, const BufferCoord &value) } +void SynEdit::setInsertMode(bool value) +{ + if (mInserting != value) { + mInserting = value; + updateCaret(); + statusChanged(scInsertMode); + } +} + +bool SynEdit::insertMode() const +{ + return mInserting; +} + +bool SynEdit::canUndo() const +{ + return !mReadOnly && mUndoList->CanUndo(); +} + +bool SynEdit::canRedo() const +{ + return !mReadOnly && mRedoList->CanUndo(); +} + int SynEdit::maxScrollWidth() const { if (mOptions.testFlag(eoScrollPastEol)) - return mLines->lengthOfLongestLine(); + return std::max(mLines->lengthOfLongestLine(),1); else return std::max(mLines->lengthOfLongestLine()-mCharsInWindow+1, 1); } @@ -1948,7 +1972,7 @@ void SynEdit::doAddChar(QChar AChar) while (iputString(mCaretY-1,temp); internalSetCaretXY(BufferCoord{i,mCaretY}); mUndoList->AddChange( @@ -2293,6 +2317,7 @@ void SynEdit::updateCaret() DisplayCoord coord = displayXY(); QPoint caretPos = RowColumnToPixels(coord); int caretWidth=mCharWidth; + qDebug()<<"caret"<count() && mCaretX <= mLines->getString(mCaretY-1).length()) { caretWidth = charColumns(mLines->getString(mCaretY-1)[mCaretX-1])*mCharWidth; } @@ -2882,12 +2907,25 @@ void SynEdit::doScrolled(int) invalidate(); } +bool SynEdit::readOnly() const +{ + return mReadOnly; +} + +void SynEdit::setReadOnly(bool readOnly) +{ + if (mReadOnly != readOnly) { + mReadOnly = readOnly; + statusChanged(scReadOnly); + } +} + SynGutter& SynEdit::gutter() { return mGutter; } -SynEditCaretType SynEdit::getInsertCaret() const +SynEditCaretType SynEdit::insertCaret() const { return mInsertCaret; } @@ -2897,7 +2935,7 @@ void SynEdit::setInsertCaret(const SynEditCaretType &insertCaret) mInsertCaret = insertCaret; } -SynEditCaretType SynEdit::getOverwriteCaret() const +SynEditCaretType SynEdit::overwriteCaret() const { return mOverwriteCaret; } @@ -2907,7 +2945,7 @@ void SynEdit::setOverwriteCaret(const SynEditCaretType &overwriteCaret) mOverwriteCaret = overwriteCaret; } -QColor SynEdit::getActiveLineColor() const +QColor SynEdit::activeLineColor() const { return mActiveLineColor; } @@ -2920,7 +2958,7 @@ void SynEdit::setActiveLineColor(const QColor &activeLineColor) } } -QColor SynEdit::getCaretColor() const +QColor SynEdit::caretColor() const { return mCaretColor; } @@ -2930,7 +2968,7 @@ void SynEdit::setCaretColor(const QColor &caretColor) mCaretColor = caretColor; } -int SynEdit::getTabWidth() const +int SynEdit::tabWidth() const { return mTabWidth; } @@ -3604,11 +3642,6 @@ PSynEditStringList SynEdit::lines() const return mLines; } -int SynEdit::tabWidth() const -{ - return mTabWidth; -} - bool SynEdit::empty() { return mLines->empty(); @@ -4305,16 +4338,15 @@ void SynEdit::ExecuteCommand(SynEditorCommand Command, QChar AChar, void *pData) break; case SynEditorCommand::ecInsertMode: if (!mReadOnly) - mInserting = true; + setInsertMode(true); break; case SynEditorCommand::ecOverwriteMode: if (!mReadOnly) - mInserting = false; + setInsertMode(false); break; case SynEditorCommand::ecToggleMode: if (!mReadOnly) { - mInserting = !mInserting; - updateCaret(); + setInsertMode(!mInserting); } break; case SynEditorCommand::ecCut: @@ -4963,7 +4995,10 @@ void SynEdit::linesChanged() vOldMode = mActiveSelectionMode; setBlockBegin(caretXY()); mActiveSelectionMode = vOldMode; - invalidateRect(mInvalidateRect); + if (mInvalidateRect.width()==0) + invalidate(); + else + invalidateRect(mInvalidateRect); mInvalidateRect = {0,0,0,0}; if (mGutter.showLineNumbers() && (mGutter.autoSize())) diff --git a/RedPandaIDE/qsynedit/SynEdit.h b/RedPandaIDE/qsynedit/SynEdit.h index 4ea0746d..ac141016 100644 --- a/RedPandaIDE/qsynedit/SynEdit.h +++ b/RedPandaIDE/qsynedit/SynEdit.h @@ -222,16 +222,16 @@ public: PSynHighlighterAttribute& Attri); //Commands - void cutToClipboard() { CommandProcessor(SynEditorCommand::ecCut);} - void copyToClipboard() { CommandProcessor(SynEditorCommand::ecCopy);} - void pasteFromClipboard() { CommandProcessor(SynEditorCommand::ecPaste);} - void undo() { CommandProcessor(SynEditorCommand::ecUndo);} - void redo() { CommandProcessor(SynEditorCommand::ecRedo);} - void zoomIn() { CommandProcessor(SynEditorCommand::ecZoomIn);} - void zoomOut() { CommandProcessor(SynEditorCommand::ecZoomOut);} - void selectAll() { { CommandProcessor(SynEditorCommand::ecSelectAll);}} - void tab() { { CommandProcessor(SynEditorCommand::ecTab);}} - void untab() { { CommandProcessor(SynEditorCommand::ecShiftTab);}} + virtual void cutToClipboard() { CommandProcessor(SynEditorCommand::ecCut);} + virtual void copyToClipboard() { CommandProcessor(SynEditorCommand::ecCopy);} + virtual void pasteFromClipboard() { CommandProcessor(SynEditorCommand::ecPaste);} + virtual void undo() { CommandProcessor(SynEditorCommand::ecUndo);} + virtual void redo() { CommandProcessor(SynEditorCommand::ecRedo);} + virtual void zoomIn() { CommandProcessor(SynEditorCommand::ecZoomIn);} + virtual void zoomOut() { CommandProcessor(SynEditorCommand::ecZoomOut);} + virtual void selectAll() { { CommandProcessor(SynEditorCommand::ecSelectAll);}} + virtual void tab() { { CommandProcessor(SynEditorCommand::ecTab);}} + virtual void untab() { { CommandProcessor(SynEditorCommand::ecShiftTab);}} // setter && getters @@ -259,8 +259,6 @@ public: bool modified() const; void setModified(bool Value); - int tabWidth() const; - PSynHighlighter highlighter() const; void setHighlighter(const PSynHighlighter &highlighter); @@ -283,23 +281,32 @@ public: SynEditorOptions getOptions() const; void setOptions(const SynEditorOptions &Value); - int getTabWidth() const; + int tabWidth() const; void setTabWidth(int tabWidth); - QColor getCaretColor() const; + QColor caretColor() const; void setCaretColor(const QColor &caretColor); - QColor getActiveLineColor() const; + QColor activeLineColor() const; void setActiveLineColor(const QColor &activeLineColor); - SynEditCaretType getOverwriteCaret() const; + SynEditCaretType overwriteCaret() const; void setOverwriteCaret(const SynEditCaretType &overwriteCaret); - SynEditCaretType getInsertCaret() const; + SynEditCaretType insertCaret() const; void setInsertCaret(const SynEditCaretType &insertCaret); SynGutter& gutter(); + bool readOnly() const; + void setReadOnly(bool readOnly); + + void setInsertMode(bool value); + bool insertMode() const; + + bool canUndo() const; + bool canRedo() const; + signals: void Changed(); diff --git a/RedPandaIDE/qsynedit/TextBuffer.cpp b/RedPandaIDE/qsynedit/TextBuffer.cpp index 4c5830b0..f480dddc 100644 --- a/RedPandaIDE/qsynedit/TextBuffer.cpp +++ b/RedPandaIDE/qsynedit/TextBuffer.cpp @@ -271,6 +271,7 @@ int SynEditStringList::getTextLength() Result += 1; } } + return Result; } void SynEditStringList::clear() @@ -549,11 +550,15 @@ void SynEditStringList::SaveToFile(QFile &file, const QByteArray& encoding, QByt bool allAscii = true; QTextCodec* codec; + realEncoding = encoding; if (realEncoding == ENCODING_UTF8_BOM) { - codec = QTextCodec::codecForName(ENCODING_UTF8_BOM); + codec = QTextCodec::codecForName(ENCODING_UTF8); + file.putChar(0xEF); + file.putChar(0xBB); + file.putChar(0xBF); } else if (realEncoding == ENCODING_SYSTEM_DEFAULT) { codec = QTextCodec::codecForLocale(); - } else if (realEncoding == ENCODING_ASCII) { + } else if (realEncoding == ENCODING_AUTO_DETECT) { codec = QTextCodec::codecForLocale(); } else { codec = QTextCodec::codecForName(realEncoding); @@ -567,24 +572,16 @@ void SynEditStringList::SaveToFile(QFile &file, const QByteArray& encoding, QByt } else { file.write(line->fString.toLatin1()); } - switch (mFileEndingType) { - case FileEndingType::Windows: - file.write("\r\n"); - break; - case FileEndingType::Linux: - file.write("\n"); - break; - case FileEndingType::Mac: - file.write("\r"); - break; - } + file.write(lineBreak().toLatin1()); } - if (encoding == ENCODING_AUTO_DETECT && allAscii) { - realEncoding = ENCODING_ASCII; + if (encoding == ENCODING_AUTO_DETECT) { + if (allAscii) + realEncoding = ENCODING_ASCII; + else + realEncoding = codec->name(); } } - void SynEditStringList::PutTextStr(const QString &text) { beginUpdate(); diff --git a/RedPandaIDE/qsynedit/exporter/synexporter.cpp b/RedPandaIDE/qsynedit/exporter/synexporter.cpp index 8b9047a3..a0b48ae9 100644 --- a/RedPandaIDE/qsynedit/exporter/synexporter.cpp +++ b/RedPandaIDE/qsynedit/exporter/synexporter.cpp @@ -1,6 +1,7 @@ #include "synexporter.h" #include +#include #include #include #include @@ -13,6 +14,8 @@ SynExporter::SynExporter() mForegroundColor = QGuiApplication::palette().color(QPalette::Text); mUseBackground = false; mExportAsText = false; + mCharset = QTextCodec::codecForLocale()->name(); + mFileEndingType = FileEndingType::Windows; clear(); setTitle(""); } @@ -28,9 +31,98 @@ void SynExporter::clear() void SynExporter::CopyToClipboard() { if (mExportAsText) { - CopyToClipboardFormat("text/plain"); + CopyToClipboardFormat("text/plain"); } else - CopyToClipboardFormat(clipboardFormat()); + CopyToClipboardFormat(clipboardFormat()); +} + +void SynExporter::ExportAll(PSynEditStringList ALines) +{ + ExportRange(ALines, BufferCoord{1, 1}, BufferCoord{INT_MAX, INT_MAX}); +} + +void SynExporter::ExportRange(PSynEditStringList ALines, BufferCoord Start, BufferCoord Stop) +{ + // abort if not all necessary conditions are met + if (!ALines || !mHighlighter || (ALines->count() == 0)) + return; + Stop.Line = std::max(1, std::min(Stop.Line, ALines->count())); + Stop.Char = std::max(1, std::min(Stop.Char, ALines->getString(Stop.Line - 1).length() + 1)); + Start.Line = std::max(1, std::min(Start.Line, ALines->count())); + Start.Char = std::max(1, std::min(Start.Char, ALines->getString(Start.Line - 1).length() + 1)); + if ( (Start.Line > ALines->count()) || (Start.Line > Stop.Line) ) + return; + if ((Start.Line == Stop.Line) && (Start.Char >= Stop.Char)) + return; + // initialization + mBuffer.clear(); + // export all the lines into fBuffer + mFirstAttribute = true; + + if (Start.Line == 1) + mHighlighter->resetState(); + else + mHighlighter->setState(ALines->ranges(Start.Line-2), + ALines->braceLevels(Start.Line-2), + ALines->bracketLevels(Start.Line-2), + ALines->parenthesisLevels(Start.Line-2)); + for (int i = Start.Line; i<=Stop.Line; i++) { + QString Line = ALines->getString(i-1); + // order is important, since Start.Y might be equal to Stop.Y +// if (i == Stop.Line) +// Line.remove(Stop.Char-1, INT_MAX); +// if ( (i = Start.Line) && (Start.Char > 1)) +// Line.remove(0, Start.Char - 1); + // export the line + mHighlighter->setLine(Line, i); + while (!mHighlighter->eol()) { + PSynHighlighterAttribute attri = mHighlighter->getTokenAttribute(); + int startPos = mHighlighter->getTokenPos(); + QString token = mHighlighter->getToken(); + if (i==Start.Line && (startPos+token.length() < Start.Char)) { + mHighlighter->next(); + continue; + } + if (i==Stop.Line && (startPos >= Stop.Char-1)) { + mHighlighter->next(); + continue; + } + if (i==Stop.Line && (startPos+token.length() > Stop.Char)) { + token = token.remove(Stop.Char - startPos - 1); + } + if (i==Start.Line && startPos < Start.Char-1) { + token = token.mid(Start.Char-1-startPos); + } + + QString Token = ReplaceReservedChars(token); + if (mOnFormatToken) + mOnFormatToken(i, mHighlighter->getTokenPos(), mHighlighter->getToken(),attri); + SetTokenAttribute(attri); + FormatToken(Token); + mHighlighter->next(); + } + FormatNewLine(); + } + if (!mFirstAttribute) + FormatAfterLastAttribute(); + // insert header + InsertData(0, GetHeader()); + // add footer + AddData(GetFooter()); +} + +void SynExporter::SaveToFile(const QString &AFileName) +{ + QFile file(AFileName); + if (file.open(QIODevice::WriteOnly)) { + SaveToStream(file); + file.close(); + } +} + +void SynExporter::SaveToStream(QIODevice &AStream) +{ + AStream.write(mBuffer); } bool SynExporter::exportAsText() const @@ -145,10 +237,20 @@ void SynExporter::setCharset(const QByteArray &charset) mCharset = charset; } +QString SynExporter::defaultFilter() const +{ + return mDefaultFilter; +} + +void SynExporter::setDefaultFilter(const QString &defaultFilter) +{ + mDefaultFilter = defaultFilter; +} + void SynExporter::AddData(const QString &AText) { if (!AText.isEmpty()) { - QTextCodec* codec = QTextCodec::codecForName(mCharset); + QTextCodec* codec = getCodec(); mBuffer.append(codec->fromUnicode(AText)); } } @@ -161,14 +263,7 @@ void SynExporter::AddDataNewLine(const QString &AText) void SynExporter::AddNewLine() { - switch(mFileEndingType) { - case FileEndingType::Linux: - AddData("\n"); - case FileEndingType::Windows: - AddData("\r\n"); - case FileEndingType::Mac: - AddData("\r"); - } + AddData(lineBreak()); } void SynExporter::CopyToClipboardFormat(QByteArray AFormat) @@ -176,10 +271,11 @@ void SynExporter::CopyToClipboardFormat(QByteArray AFormat) QClipboard* clipboard = QGuiApplication::clipboard(); QMimeData * mimeData = new QMimeData(); mimeData->setData(AFormat,mBuffer); + clipboard->clear(); clipboard->setMimeData(mimeData); } -void SynExporter::FormatToken(QString &Token) +void SynExporter::FormatToken(const QString &Token) { AddData(Token); } @@ -189,15 +285,21 @@ int SynExporter::GetBufferSize() return mBuffer.size(); } +QTextCodec * SynExporter::getCodec() { + QTextCodec* codec = QTextCodec::codecForName(mCharset); + if (codec == nullptr) + codec = QTextCodec::codecForLocale(); + return codec; +} void SynExporter::InsertData(int APos, const QString &AText) { if (!AText.isEmpty()) { - QTextCodec* codec = QTextCodec::codecForName(mCharset); + QTextCodec* codec = getCodec(); mBuffer.insert(APos,codec->fromUnicode(AText)); } } -QString SynExporter::ReplaceReservedChars(QString &AToken) +QString SynExporter::ReplaceReservedChars(const QString &AToken) { if (AToken.isEmpty()) return ""; @@ -246,7 +348,34 @@ void SynExporter::SetTokenAttribute(PSynHighlighterAttribute Attri) } } +const QByteArray &SynExporter::buffer() const +{ + return mBuffer; +} + QByteArray SynExporter::clipboardFormat() { return this->mClipboardFormat; } + +FormatTokenHandler SynExporter::onFormatToken() const +{ + return mOnFormatToken; +} + +void SynExporter::setOnFormatToken(const FormatTokenHandler &onFormatToken) +{ + mOnFormatToken = onFormatToken; +} + +QString SynExporter::lineBreak() +{ + switch(mFileEndingType) { + case FileEndingType::Linux: + return "\n"; + case FileEndingType::Windows: + return "\r\n"; + case FileEndingType::Mac: + return "\r"; + } +} diff --git a/RedPandaIDE/qsynedit/exporter/synexporter.h b/RedPandaIDE/qsynedit/exporter/synexporter.h index 7333472f..5802e3ff 100644 --- a/RedPandaIDE/qsynedit/exporter/synexporter.h +++ b/RedPandaIDE/qsynedit/exporter/synexporter.h @@ -6,10 +6,11 @@ -using FormatTokenHandler = std::function; class SynExporter { + public: explicit SynExporter(); @@ -27,7 +28,7 @@ public: * @brief Exports everything in the strings parameter to the output buffer. * @param ALines */ - void ExportAll(const SynEditStringList& ALines); + void ExportAll(PSynEditStringList ALines); /** * @brief Exports the given range of the strings parameter to the output buffer. @@ -35,8 +36,8 @@ public: * @param Start * @param Stop */ - void ExportRange(const SynEditStringList& ALines, - const BufferCoord& Start, const BufferCoord& Stop); + void ExportRange(PSynEditStringList ALines, + BufferCoord Start, BufferCoord Stop); /** * @brief Saves the contents of the output buffer to a file. * @param AFileName @@ -46,7 +47,7 @@ public: * @brief Saves the contents of the output buffer to a stream. * @param AStream */ - void SaveToStream(const QIODevice& AStream); + void SaveToStream(QIODevice& AStream); bool exportAsText() const; void setExportAsText(bool Value); @@ -80,6 +81,14 @@ public: QByteArray charset() const; void setCharset(const QByteArray &charset); + QString defaultFilter() const; + void setDefaultFilter(const QString &defaultFilter); + + FormatTokenHandler onFormatToken() const; + void setOnFormatToken(const FormatTokenHandler &onFormatToken); + + const QByteArray& buffer() const; + protected: QByteArray mCharset; QColor mBackgroundColor; @@ -97,6 +106,8 @@ protected: bool mUseBackground; FileEndingType mFileEndingType; + QString lineBreak(); + /** * @brief Adds a string to the output buffer. * @param AText @@ -161,7 +172,7 @@ protected: * @brief Can be overridden in descendant classes to add the formatted text of * the actual token text to the output buffer. */ - virtual void FormatToken(QString& Token) ; + virtual void FormatToken(const QString& Token) ; /** * @brief Has to be overridden in descendant classes to add a newline in the output * format to the output buffer. @@ -203,7 +214,7 @@ protected: * @brief Returns a string that has all the invalid chars of the output format * replaced with the entries in the replacement array. */ - QString ReplaceReservedChars(QString &AToken); + QString ReplaceReservedChars(const QString &AToken); /** * @brief Sets the token attribute of the next token to determine the changes * of colors and font styles so the properties of the next token can be @@ -211,10 +222,13 @@ protected: * @param Attri */ virtual void SetTokenAttribute(PSynHighlighterAttribute Attri); + + QTextCodec *getCodec(); private: QByteArray mBuffer; bool mFirstAttribute; FormatTokenHandler mOnFormatToken; + }; #endif // SYNEXPORTER_H diff --git a/RedPandaIDE/qsynedit/exporter/synhtmlexporter.cpp b/RedPandaIDE/qsynedit/exporter/synhtmlexporter.cpp new file mode 100644 index 00000000..2f1d5f75 --- /dev/null +++ b/RedPandaIDE/qsynedit/exporter/synhtmlexporter.cpp @@ -0,0 +1,186 @@ +#include "synhtmlexporter.h" +#include "../MiscProcs.h" +#include + +SynHTMLExporter::SynHTMLExporter() +{ + mClipboardFormat = "text/html"; + mDefaultFilter = "HTML Documents (*.htm;*.html)|*.htm;*.html"; + // setup array of chars to be replaced + mReplaceReserved['&'] = "&"; + mReplaceReserved['<'] = "<"; + mReplaceReserved['>'] = ">"; + mReplaceReserved['"'] = """; + mCreateHTMLFragment = false; +} + +bool SynHTMLExporter::createHTMLFragment() const +{ + return mCreateHTMLFragment; +} + +void SynHTMLExporter::setCreateHTMLFragment(bool createHTMLFragment) +{ + mCreateHTMLFragment = createHTMLFragment; +} + +QString SynHTMLExporter::AttriToCSS(PSynHighlighterAttribute Attri, const QString &UniqueAttriName) +{ + QString StyleName = MakeValidName(UniqueAttriName); + + QString Result = "." + StyleName + " { "; + if (mUseBackground && Attri->background().isValid()) + Result += "background-color: " + ColorToHTML(Attri->background()) + "; "; + if (Attri->foreground().isValid()) + Result += "color: " + ColorToHTML(Attri->foreground()) + "; "; + + if (Attri->styles().testFlag(SynFontStyle::fsBold)) + Result += "font-weight: bold; "; + if (Attri->styles().testFlag(SynFontStyle::fsItalic)) + Result += "font-style: italic; "; + if (Attri->styles().testFlag(SynFontStyle::fsUnderline)) + Result += "text-decoration: underline; "; + if (Attri->styles().testFlag(SynFontStyle::fsStrikeOut)) + Result += "text-decoration: line-through; "; + Result += "}"; + return Result; +} + +bool SynHTMLExporter::AttriToCSSCallback(PSynHighlighter , PSynHighlighterAttribute Attri, const QString& UniqueAttriName, QList params) +{ + QString& styles = *static_cast(params[0]); + styles.append(AttriToCSS(Attri,UniqueAttriName) + lineBreak()); + return true; +} + +QString SynHTMLExporter::ColorToHTML(const QColor &AColor) +{ + return AColor.name(); +} + +QString SynHTMLExporter::GetStyleName(PSynHighlighter Highlighter, PSynHighlighterAttribute Attri) +{ + QString result; + EnumHighlighterAttris(Highlighter,false, + std::bind( + &SynHTMLExporter::StyleNameCallback,this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4), + {&Attri,&result}); + return result; +} + +QString SynHTMLExporter::MakeValidName(const QString &Name) +{ + QString Result; + for (QChar ch:Name) { + ch = ch.toLower(); + if (ch == '.' || ch =='_') + Result += '-'; + else if ((ch >='a' && ch <= 'z') || (ch>='0' && ch<='9') || (ch == '-')) + Result += ch; + } + return Result; +} + +bool SynHTMLExporter::StyleNameCallback(PSynHighlighter Highlighter, PSynHighlighterAttribute Attri, const QString& UniqueAttriName, QList params) +{ + PSynHighlighterAttribute& AttriToFind = *static_cast(params[0]); + QString& StyleName = *static_cast(params[1]); + + if (Attri == AttriToFind) { + StyleName.clear(); + StyleName.append(MakeValidName(UniqueAttriName)); + return false; + } + return true; +} + +void SynHTMLExporter::FormatAttributeDone(bool , bool , SynFontStyles ) +{ + AddData(""); +} + +void SynHTMLExporter::FormatAttributeInit(bool , bool , SynFontStyles ) +{ + QString StyleName = GetStyleName(mHighlighter, mLastAttri); + AddData(QString("").arg(StyleName)); +} + +void SynHTMLExporter::FormatAfterLastAttribute() +{ + AddData(""); +} + +void SynHTMLExporter::FormatBeforeFirstAttribute(bool, bool, SynFontStyles) +{ + QString StyleName = GetStyleName(mHighlighter, mLastAttri); + AddData(QString("").arg(StyleName)); +} + +void SynHTMLExporter::FormatNewLine() +{ + AddNewLine(); +} + +QString SynHTMLExporter::GetFooter() +{ + QString Result = ""; + Result = "" + lineBreak() + "" + lineBreak(); + if (mCreateHTMLFragment) + Result += ""; + Result += ""+lineBreak()+ ""; + return Result; +} + +QString SynHTMLExporter::GetFormatName() +{ + return "HTML"; +} + +QString SynHTMLExporter::GetHeader() +{ + using namespace std::placeholders; + QString Styles; + EnumHighlighterAttris(mHighlighter, true, + std::bind(&SynHTMLExporter::AttriToCSSCallback, + this, _1, _2, _3, _4), + {&Styles}); + + QString HTMLAsTextHeader = ""+lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + ""+ lineBreak() + + "%1" + lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + "" + lineBreak(); + QString Header = HTMLAsTextHeader + .arg(mTitle) + .arg(QString(mCharset)) + .arg(ColorToHTML(mForegroundColor)) + .arg(ColorToHTML(mBackgroundColor)) + .arg(Styles); + QString Result = Header; + if (mCreateHTMLFragment) { + Result += ""; + } + Result += QString("
"+lineBreak()+"")
+            .arg(mFont.pointSize())
+            .arg(mFont.family());
+
+    return Result;
+}
+
+void SynHTMLExporter::SetTokenAttribute(PSynHighlighterAttribute Attri)
+{
+    mLastAttri = Attri;
+    SynExporter::SetTokenAttribute(Attri);
+}
diff --git a/RedPandaIDE/qsynedit/exporter/synhtmlexporter.h b/RedPandaIDE/qsynedit/exporter/synhtmlexporter.h
new file mode 100644
index 00000000..637de40e
--- /dev/null
+++ b/RedPandaIDE/qsynedit/exporter/synhtmlexporter.h
@@ -0,0 +1,40 @@
+#ifndef SYNHTMLEXPORTER_H
+#define SYNHTMLEXPORTER_H
+
+#include "synexporter.h"
+
+class SynHTMLExporter : public SynExporter
+{
+public:
+    SynHTMLExporter();
+    bool createHTMLFragment() const;
+    void setCreateHTMLFragment(bool createHTMLFragment);
+
+protected:
+    bool mCreateHTMLFragment;
+private:
+    PSynHighlighterAttribute mLastAttri;
+    QString AttriToCSS(PSynHighlighterAttribute Attri, const QString& UniqueAttriName);
+    bool AttriToCSSCallback(PSynHighlighter Highlighter, PSynHighlighterAttribute  Attri,
+                            const QString& UniqueAttriName,  QList params);
+    QString ColorToHTML(const QColor &AColor);
+    QString GetStyleName(PSynHighlighter Highlighter,
+                         PSynHighlighterAttribute Attri);
+    QString MakeValidName(const QString &Name);
+    bool StyleNameCallback(PSynHighlighter Highlighter, PSynHighlighterAttribute  Attri,
+                           const QString& UniqueAttriName,  QList params);
+
+    // SynExporter interface
+protected:
+    void FormatAttributeDone(bool BackgroundChanged, bool ForegroundChanged, SynFontStyles FontStylesChanged);
+    void FormatAttributeInit(bool BackgroundChanged, bool ForegroundChanged, SynFontStyles FontStylesChanged);
+    void FormatAfterLastAttribute();
+    void FormatBeforeFirstAttribute(bool BackgroundChanged, bool ForegroundChanged, SynFontStyles FontStylesChanged);
+    void FormatNewLine();
+    QString GetFooter();
+    QString GetFormatName();
+    QString GetHeader();
+    void SetTokenAttribute(PSynHighlighterAttribute Attri);
+};
+
+#endif // SYNHTMLEXPORTER_H
diff --git a/RedPandaIDE/qsynedit/exporter/synrtfexporter.cpp b/RedPandaIDE/qsynedit/exporter/synrtfexporter.cpp
new file mode 100644
index 00000000..deaa1d78
--- /dev/null
+++ b/RedPandaIDE/qsynedit/exporter/synrtfexporter.cpp
@@ -0,0 +1,150 @@
+#include "synrtfexporter.h"
+
+SynRTFExporter::SynRTFExporter():SynExporter()
+{
+    mDefaultFilter = "Rich Text Format Documents (*.rtf)|*.rtf";
+    mClipboardFormat = "application/x-qt-windows-mime;value=\"Rich Format Text\"";
+    //mClipboardFormat = "Rich Format Text";
+    // setup array of chars to be replaced
+    mReplaceReserved['\\'] = "\\\\";
+    mReplaceReserved['{'] = "\\{";
+    mReplaceReserved['}'] = "\\}";
+
+}
+
+QString SynRTFExporter::ColorToRTF(const QColor &AColor) const
+{
+    return QString("\\red%1\\green%2\\blue%3;")
+            .arg(AColor.red())
+            .arg(AColor.green())
+            .arg(AColor.blue());
+}
+
+int SynRTFExporter::GetColorIndex(const QColor &AColor)
+{
+    int index = mListColors.indexOf(AColor);
+    if (index<0) {
+        mListColors.append(AColor);
+        index = mListColors.length()-1;
+    }
+    return index;
+}
+
+QString SynRTFExporter::GetFontTable()
+{
+    QString Result = "{\\fonttbl{\\f0\\fmodern\\fcharset134 "
+        + ReplaceReservedChars(mFont.family());
+    Result = Result + ";}}" + lineBreak();
+    return Result;
+}
+
+void SynRTFExporter::FormatAttributeDone(bool , bool , SynFontStyles FontStylesChanged)
+{
+    // nothing to do about the color, but reset the font style
+    if (FontStylesChanged.testFlag(SynFontStyle::fsBold)) {
+        mAttributesChanged = true;
+        AddData("\\b0");
+    }
+    if (FontStylesChanged.testFlag(SynFontStyle::fsItalic)) {
+        mAttributesChanged = true;
+        AddData("\\i0");
+    }
+    if (FontStylesChanged.testFlag(SynFontStyle::fsUnderline)) {
+        mAttributesChanged = true;
+        AddData("\\ul0");
+    }
+    if (FontStylesChanged.testFlag(SynFontStyle::fsStrikeOut)) {
+        mAttributesChanged = true;
+        AddData("\\strike0");
+    }
+}
+
+void SynRTFExporter::FormatAttributeInit(bool BackgroundChanged, bool ForegroundChanged, SynFontStyles FontStylesChanged)
+{
+    // background color
+    if (BackgroundChanged) {
+        AddData(QString("\\chshdng0\\chcbpat%1\\cb%2\\highlight%3 ")
+              .arg(GetColorIndex(mLastBG))
+              .arg(GetColorIndex(mLastBG))
+              .arg(GetColorIndex(mLastBG)));
+        mAttributesChanged = true;
+    }
+    // text color
+    if (ForegroundChanged) {
+        AddData(QString("\\cf%1").arg(GetColorIndex(mLastFG)));
+        mAttributesChanged = true;
+    }
+    // font styles
+    // nothing to do about the color, but reset the font style
+    if (FontStylesChanged.testFlag(SynFontStyle::fsBold)) {
+        mAttributesChanged = true;
+        AddData("\\b0");
+    }
+    if (FontStylesChanged.testFlag(SynFontStyle::fsItalic)) {
+        mAttributesChanged = true;
+        AddData("\\i0");
+    }
+    if (FontStylesChanged.testFlag(SynFontStyle::fsUnderline)) {
+        mAttributesChanged = true;
+        AddData("\\ul0");
+    }
+    if (FontStylesChanged.testFlag(SynFontStyle::fsStrikeOut)) {
+        mAttributesChanged = true;
+        AddData("\\strike0");
+    }
+    if (mAttributesChanged) {
+        AddData(" ");
+        mAttributesChanged = false;
+    }
+}
+
+void SynRTFExporter::FormatAfterLastAttribute()
+{
+    // no need to reset the font style here...
+}
+
+void SynRTFExporter::FormatBeforeFirstAttribute(bool BackgroundChanged, bool ForegroundChanged, SynFontStyles FontStylesChanged)
+{
+    FormatAttributeInit(BackgroundChanged, ForegroundChanged, FontStylesChanged);
+}
+
+void SynRTFExporter::FormatNewLine()
+{
+    AddNewLine();
+    AddData("\\par ");
+}
+
+QString SynRTFExporter::GetFooter()
+{
+    return "}";
+}
+
+QString SynRTFExporter::GetFormatName()
+{
+    return "RTF";
+}
+
+QString SynRTFExporter::GetHeader()
+{
+    QString Result = "{\\rtf1\\ansi\\deff0\\deftab720" + GetFontTable();
+    // all the colors
+    Result = Result + "{\\colortbl";
+    for (int i = 0; i mListColors;
+    QString ColorToRTF(const QColor& AColor) const;
+    int GetColorIndex(const QColor& AColor);
+    QString GetFontTable();
+
+    // SynExporter interface
+protected:
+    void FormatAttributeDone(bool BackgroundChanged, bool ForegroundChanged, SynFontStyles FontStylesChanged) override;
+    void FormatAttributeInit(bool BackgroundChanged, bool ForegroundChanged, SynFontStyles FontStylesChanged) override;
+    void FormatAfterLastAttribute() override;
+    void FormatBeforeFirstAttribute(bool BackgroundChanged, bool ForegroundChanged, SynFontStyles FontStylesChanged) override;
+    void FormatNewLine() override;
+    QString GetFooter() override;
+    QString GetFormatName() override;
+    QString GetHeader() override;
+};
+
+#endif // SYNRTFEXPORTER_H
diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp
index 6b61ef95..3ec7b1b7 100644
--- a/RedPandaIDE/settings.cpp
+++ b/RedPandaIDE/settings.cpp
@@ -21,6 +21,11 @@ Settings::Settings(const QString &filename):
 {
 }
 
+Settings::~Settings()
+{
+    mEditor.save();
+}
+
 void Settings::beginGroup(const QString &group)
 {
     mSettings.beginGroup(group);
@@ -229,6 +234,106 @@ void Settings::Editor::setGutterRightOffset(int gutterRightOffset)
     mGutterRightOffset = gutterRightOffset;
 }
 
+int Settings::Editor::copyWithFormatAs() const
+{
+    return mCopyWithFormatAs;
+}
+
+void Settings::Editor::setCopyWithFormatAs(int copyWithFormatAs)
+{
+    mCopyWithFormatAs = copyWithFormatAs;
+}
+
+QString Settings::Editor::copyHTMLColorSchema() const
+{
+    return mCopyHTMLColorSchema;
+}
+
+void Settings::Editor::setCopyHTMLColorSchema(const QString ©HTMLColorSchema)
+{
+    mCopyHTMLColorSchema = copyHTMLColorSchema;
+}
+
+bool Settings::Editor::copyHTMLUseEditorColor() const
+{
+    return mCopyHTMLUseEditorColor;
+}
+
+void Settings::Editor::setCopyHTMLUseEditorColor(bool copyHTMLUseEditorColor)
+{
+    mCopyHTMLUseEditorColor = copyHTMLUseEditorColor;
+}
+
+bool Settings::Editor::copyHTMLUseBackground() const
+{
+    return mCopyHTMLUseBackground;
+}
+
+void Settings::Editor::setCopyHTMLUseBackground(bool copyHTMLUseBackground)
+{
+    mCopyHTMLUseBackground = copyHTMLUseBackground;
+}
+
+QString Settings::Editor::copyRTFColorSchema() const
+{
+    return mCopyRTFColorSchema;
+}
+
+void Settings::Editor::setCopyRTFColorSchema(const QString ©RTFColorSchema)
+{
+    mCopyRTFColorSchema = copyRTFColorSchema;
+}
+
+bool Settings::Editor::copyRTFUseEditorColor() const
+{
+    return mCopyRTFUseEditorColor;
+}
+
+void Settings::Editor::setCopyRTFUseEditorColor(bool copyRTFUseEditorColor)
+{
+    mCopyRTFUseEditorColor = copyRTFUseEditorColor;
+}
+
+bool Settings::Editor::copyRTFUseBackground() const
+{
+    return mCopyRTFUseBackground;
+}
+
+void Settings::Editor::setCopyRTFUseBackground(bool copyRTFUseBackground)
+{
+    mCopyRTFUseBackground = copyRTFUseBackground;
+}
+
+int Settings::Editor::copyLineLimits() const
+{
+    return mCopyLineLimits;
+}
+
+void Settings::Editor::setCopyLineLimits(int copyLineLimits)
+{
+    mCopyLineLimits = copyLineLimits;
+}
+
+int Settings::Editor::copyCharLimits() const
+{
+    return mCopyCharLimits;
+}
+
+void Settings::Editor::setCopyCharLimits(int copyCharLimits)
+{
+    mCopyCharLimits = copyCharLimits;
+}
+
+bool Settings::Editor::copySizeLimit() const
+{
+    return mCopySizeLimit;
+}
+
+void Settings::Editor::setCopySizeLimit(bool copyLimit)
+{
+    mCopySizeLimit = copyLimit;
+}
+
 int Settings::Editor::gutterLeftOffset() const
 {
     return mGutterLeftOffset;
@@ -441,6 +546,18 @@ void Settings::Editor::doSave()
     saveValue("gutter_font_name",mGutterFontName);
     saveValue("gutter_font_size",mGutterFontSize);
     saveValue("gutter_font_only_monospaced",mGutterFontOnlyMonospaced);
+
+    //copy
+    saveValue("copy_limit",mCopySizeLimit);
+    saveValue("copy_char_limits",mCopyCharLimits);
+    saveValue("copy_line_limits",mCopyLineLimits);
+    saveValue("copy_with_format_as",mCopyWithFormatAs);
+    saveValue("copy_rtf_use_background",mCopyRTFUseBackground);
+    saveValue("copy_rtf_use_editor_color_schema",mCopyRTFUseEditorColor);
+    saveValue("copy_rtf_color_schema",mCopyRTFColorSchema);
+    saveValue("copy_html_use_background",mCopyHTMLUseBackground);
+    saveValue("copy_html_use_editor_color_schema",mCopyHTMLUseEditorColor);
+    saveValue("copy_html_color_schema", mCopyHTMLColorSchema);
 }
 
 void Settings::Editor::doLoad()
@@ -487,6 +604,19 @@ void Settings::Editor::doLoad()
     mGutterFontName = stringValue("gutter_font_name","consolas");
     mGutterFontSize = intValue("gutter_font_size",QGuiApplication::font().pointSize());
     mGutterFontOnlyMonospaced = boolValue("gutter_font_only_monospaced",true);
+
+    //copy
+    mCopySizeLimit = boolValue("copy_limit",true);
+    mCopyCharLimits = intValue("copy_char_limits",100);
+    mCopyLineLimits = intValue("copy_line_limits",100000);
+    mCopyWithFormatAs = intValue("copy_with_format_as",0);
+    mCopyRTFUseBackground = boolValue("copy_rtf_use_background",false);
+    mCopyRTFUseEditorColor = boolValue("copy_rtf_use_editor_color_schema",true);
+    mCopyRTFColorSchema = stringValue("copy_rtf_color_schema","");
+    mCopyHTMLUseBackground = boolValue("copy_html_use_background",false);
+    mCopyHTMLUseEditorColor = boolValue("copy_html_use_editor_color_schema",true);
+    mCopyHTMLColorSchema = stringValue("copy_html_color_schema","");
+
 }
 
 SynEditCaretType Settings::Editor::caretForOverwrite() const
diff --git a/RedPandaIDE/settings.h b/RedPandaIDE/settings.h
index 726afaf7..adec5046 100644
--- a/RedPandaIDE/settings.h
+++ b/RedPandaIDE/settings.h
@@ -178,6 +178,36 @@ public:
         int gutterRightOffset() const;
         void setGutterRightOffset(int gutterRightOffset);
 
+        bool copySizeLimit() const;
+        void setCopySizeLimit(bool copyLimit);
+
+        int copyCharLimits() const;
+        void setCopyCharLimits(int copyCharLimits);
+
+        int copyLineLimits() const;
+        void setCopyLineLimits(int copyLineLimits);
+
+        bool copyRTFUseBackground() const;
+        void setCopyRTFUseBackground(bool copyRTFUseBackground);
+
+        bool copyRTFUseEditorColor() const;
+        void setCopyRTFUseEditorColor(bool copyRTFUseEditorColor);
+
+        QString copyRTFColorSchema() const;
+        void setCopyRTFColorSchema(const QString ©RTFColorSchema);
+
+        bool copyHTMLUseBackground() const;
+        void setCopyHTMLUseBackground(bool copyHTMLUseBackground);
+
+        bool copyHTMLUseEditorColor() const;
+        void setCopyHTMLUseEditorColor(bool copyHTMLUseEditorColor);
+
+        QString copyHTMLColorSchema() const;
+        void setCopyHTMLColorSchema(const QString ©HTMLColorSchema);
+
+        int copyWithFormatAs() const;
+        void setCopyWithFormatAs(int copyWithFormatAs);
+
     private:
         QByteArray mDefaultEncoding;
         //General
@@ -222,6 +252,18 @@ public:
         int mGutterFontSize;
         bool mGutterFontOnlyMonospaced;
 
+        //copy
+        bool mCopySizeLimit;
+        int mCopyCharLimits;
+        int mCopyLineLimits;
+        int mCopyWithFormatAs;
+        bool mCopyRTFUseBackground;
+        bool mCopyRTFUseEditorColor;
+        QString mCopyRTFColorSchema;
+        bool mCopyHTMLUseBackground;
+        bool mCopyHTMLUseEditorColor;
+        QString mCopyHTMLColorSchema;
+
         // _Base interface
     protected:
         void doSave() override;
@@ -385,6 +427,7 @@ public:
     explicit Settings(const QString& filename);
     explicit Settings(Settings&& settings) = delete;
     explicit Settings(const Settings& settings) = delete;
+    ~Settings();
 
     Settings& operator= (const Settings& settings) = delete;
     Settings& operator= (const Settings&& settings) = delete;
diff --git a/RedPandaIDE/settingsdialog/editorclipboardwidget.cpp b/RedPandaIDE/settingsdialog/editorclipboardwidget.cpp
new file mode 100644
index 00000000..5b989673
--- /dev/null
+++ b/RedPandaIDE/settingsdialog/editorclipboardwidget.cpp
@@ -0,0 +1,59 @@
+#include "editorclipboardwidget.h"
+#include "ui_editorclipboardwidget.h"
+#include "../settings.h"
+#include "../mainwindow.h"
+
+EditorClipboardWidget::EditorClipboardWidget(const QString& name, const QString& group, QWidget *parent) :
+    SettingsWidget(name,group,parent),
+    ui(new Ui::EditorClipboardWidget)
+{
+    ui->setupUi(this);
+    ui->cbCopyWithFormatAs->addItem("None");
+    ui->cbCopyWithFormatAs->addItem("HTML");
+}
+
+EditorClipboardWidget::~EditorClipboardWidget()
+{
+    delete ui;
+}
+
+void EditorClipboardWidget::doLoad()
+{
+    //pSettings->editor().load();
+    //copy
+    QString mCopyHTMLColorSchema;
+
+    ui->grpCopySizeLimit->setChecked(pSettings->editor().copySizeLimit());
+    ui->spinCopyCharLimits->setValue(pSettings->editor().copyCharLimits());
+    ui->spinCopyLineLimits->setValue(pSettings->editor().copyLineLimits());
+    ui->cbCopyWithFormatAs->setCurrentIndex(std::max(0,std::min(ui->cbCopyWithFormatAs->count(),
+                                                                pSettings->editor().copyWithFormatAs())) );
+    ui->chkCopyRTFUseBackground->setChecked(pSettings->editor().copyRTFUseBackground());
+    ui->chkCopyRTFUseEditorColor->setChecked(pSettings->editor().copyRTFUseEditorColor());
+    //todo
+    //ui->cbCopyRTFColorSchema
+    ui->chkCopyHTMLUseBackground->setChecked(pSettings->editor().copyHTMLUseBackground());
+    ui->chkCopyHTMLUseEditorColor->setChecked(pSettings->editor().copyHTMLUseEditorColor());
+    //todo
+    //ui->cbCopyHTMLColorSchema
+
+}
+
+void EditorClipboardWidget::doSave()
+{
+    //copy
+    pSettings->editor().setCopySizeLimit(ui->grpCopySizeLimit->isChecked());
+    pSettings->editor().setCopyCharLimits(ui->spinCopyCharLimits->value());
+    pSettings->editor().setCopyLineLimits(ui->spinCopyLineLimits->value());
+    pSettings->editor().setCopyWithFormatAs(ui->cbCopyWithFormatAs->currentIndex());
+
+    pSettings->editor().setCopyRTFUseBackground(ui->chkCopyRTFUseBackground->isChecked());
+    pSettings->editor().setCopyRTFUseEditorColor(ui->chkCopyRTFUseEditorColor->isChecked());
+    //todo
+    //ui->cbCopyRTFColorSchema
+    pSettings->editor().setCopyHTMLUseBackground(ui->chkCopyHTMLUseBackground->isChecked());
+    pSettings->editor().setCopyHTMLUseEditorColor(ui->chkCopyHTMLUseEditorColor->isChecked());
+
+    pSettings->editor().save();
+    pMainWindow->updateEditorSettings();
+}
diff --git a/RedPandaIDE/settingsdialog/editorclipboardwidget.h b/RedPandaIDE/settingsdialog/editorclipboardwidget.h
new file mode 100644
index 00000000..49cb78ce
--- /dev/null
+++ b/RedPandaIDE/settingsdialog/editorclipboardwidget.h
@@ -0,0 +1,28 @@
+#ifndef EDITORCLIPBOARDWIDGET_H
+#define EDITORCLIPBOARDWIDGET_H
+
+#include 
+#include "settingswidget.h"
+
+namespace Ui {
+class EditorClipboardWidget;
+}
+
+class EditorClipboardWidget : public SettingsWidget
+{
+    Q_OBJECT
+
+public:
+    explicit EditorClipboardWidget(const QString& name, const QString& group, QWidget *parent = nullptr);
+    ~EditorClipboardWidget();
+
+private:
+    Ui::EditorClipboardWidget *ui;
+
+    // SettingsWidget interface
+protected:
+    void doLoad();
+    void doSave();
+};
+
+#endif // EDITORCLIPBOARDWIDGET_H
diff --git a/RedPandaIDE/settingsdialog/editorclipboardwidget.ui b/RedPandaIDE/settingsdialog/editorclipboardwidget.ui
new file mode 100644
index 00000000..54c8dd25
--- /dev/null
+++ b/RedPandaIDE/settingsdialog/editorclipboardwidget.ui
@@ -0,0 +1,285 @@
+
+
+ EditorClipboardWidget
+ 
+  
+   
+    0
+    0
+    400
+    429
+   
+  
+  
+   Form
+  
+  
+   
+    
+     
+      Copy Size Limit
+     
+     
+      true
+     
+     
+      
+       
+        
+         Don't copy text larger than
+        
+       
+      
+      
+       
+        
+         
+          0
+         
+         
+          0
+         
+         
+          0
+         
+         
+          0
+         
+         
+          
+           
+            Lines
+           
+          
+         
+         
+          
+           
+            Size(kilo characters):
+           
+          
+         
+         
+          
+           
+            1
+           
+           
+            99999999
+           
+          
+         
+         
+          
+           
+            1
+           
+           
+            999999
+           
+          
+         
+         
+          
+           
+            Qt::Horizontal
+           
+           
+            
+             40
+             20
+            
+           
+          
+         
+        
+       
+      
+     
+    
+   
+   
+    
+     
+      
+       
+        
+         Copy with format as
+        
+       
+      
+      
+       
+        
+         
+        
+       
+      
+      
+       
+        
+         Qt::Horizontal
+        
+        
+         
+          40
+          20
+         
+        
+       
+      
+     
+    
+   
+   
+    
+     
+      Copy && Export As HTML
+     
+     
+      false
+     
+     
+      
+       
+        
+         Use background color
+        
+       
+      
+      
+       
+        
+         Use editor's color schema
+        
+       
+      
+      
+       
+        
+         
+          0
+         
+         
+          0
+         
+         
+          0
+         
+         
+          0
+         
+         
+          
+           
+            Color schema
+           
+          
+         
+         
+          
+         
+         
+          
+           
+            Qt::Horizontal
+           
+           
+            
+             40
+             20
+            
+           
+          
+         
+        
+       
+      
+     
+    
+   
+   
+    
+     
+      Export As RTF
+     
+     
+      false
+     
+     
+      
+       
+        
+         Use background color
+        
+       
+      
+      
+       
+        
+         Use editor's color schema
+        
+       
+      
+      
+       
+        
+         
+          0
+         
+         
+          0
+         
+         
+          0
+         
+         
+          0
+         
+         
+          
+           
+            Color schema
+           
+          
+         
+         
+          
+         
+         
+          
+           
+            Qt::Horizontal
+           
+           
+            
+             40
+             20
+            
+           
+          
+         
+        
+       
+      
+     
+    
+   
+   
+    
+     
+      Qt::Vertical
+     
+     
+      
+       20
+       40
+      
+     
+    
+   
+  
+ 
+ 
+ 
+
diff --git a/RedPandaIDE/settingsdialog/settingsdialog.cpp b/RedPandaIDE/settingsdialog/settingsdialog.cpp
index baaf3b52..d7e6be2d 100644
--- a/RedPandaIDE/settingsdialog/settingsdialog.cpp
+++ b/RedPandaIDE/settingsdialog/settingsdialog.cpp
@@ -4,6 +4,7 @@
 #include "compilersetoptionwidget.h"
 #include "editorgeneralwidget.h"
 #include "editorfontwidget.h"
+#include "editorclipboardwidget.h"
 #include 
 #include 
 
@@ -30,6 +31,10 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
     pEditorFontWidget = new EditorFontWidget(tr("Font"),tr("Editor"));
     pEditorFontWidget->init();
     addWidget(pEditorFontWidget);
+
+    pEditorClipboardWidget = new EditorClipboardWidget(tr("Copy & Export"),tr("Editor"));
+    pEditorClipboardWidget->init();
+    addWidget(pEditorClipboardWidget);
 }
 
 SettingsDialog::~SettingsDialog()
diff --git a/RedPandaIDE/settingsdialog/settingsdialog.h b/RedPandaIDE/settingsdialog/settingsdialog.h
index 6ba9d4b0..fdda4643 100644
--- a/RedPandaIDE/settingsdialog/settingsdialog.h
+++ b/RedPandaIDE/settingsdialog/settingsdialog.h
@@ -13,6 +13,7 @@ class SettingsDialog;
 class CompilerSetOptionWidget;
 class EditorGeneralWidget;
 class EditorFontWidget;
+class EditorClipboardWidget;
 class PCompilerSet;
 class SettingsWidget;
 class SettingsDialog : public QDialog
@@ -46,6 +47,7 @@ private:
     CompilerSetOptionWidget* pCompilerSetOptionWidget;
     EditorGeneralWidget* pEditorGeneralWidget;
     EditorFontWidget* pEditorFontWidget;
+    EditorClipboardWidget *pEditorClipboardWidget;
 };
 
 #endif // SETTINGSDIALOG_H