diff --git a/NEWS.md b/NEWS.md index 4d66fe04..b189007e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -15,6 +15,8 @@ Red Panda C++ Version 2.8 - enhancement: Let encoding options in the statusbar more explicit. - fix: Crash when find occurrences in a project that has missing files. - enhancement: Print current selection can be used in the print dialog. + - enhancement: Print syntax colored content. + - enhancement: Correctly handle tab in the exported RTF. Red Panda C++ Version 2.7 diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index f31ee1f9..8ecdc004 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -31,8 +31,9 @@ #include #include "qsynedit/syntaxer/cpp.h" #include "syntaxermanager.h" -#include "qsynedit/exporter/synrtfexporter.h" -#include "qsynedit/exporter/synhtmlexporter.h" +#include "qsynedit/exporter/rtfexporter.h" +#include "qsynedit/exporter/htmlexporter.h" +#include "qsynedit/exporter/qtsupportedhtmlexporter.h" #include "qsynedit/Constants.h" #include #include @@ -1482,10 +1483,9 @@ void Editor::copyAsHTML() { if (!selAvail()) return; - QSynedit::SynHTMLExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding()); + QSynedit::HTMLExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding()); exporter.setTitle(QFileInfo(mFilename).fileName()); - exporter.setExportAsText(false); exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground()); exporter.setFont(font()); QSynedit::PSyntaxer hl = syntaxer(); @@ -1504,7 +1504,7 @@ void Editor::copyAsHTML() )); exporter.setCreateHTMLFragment(true); - exporter.ExportRange(document(),blockBegin(),blockEnd()); + exporter.exportRange(document(),blockBegin(),blockEnd()); //clipboard takes the owner ship QMimeData * mimeData = new QMimeData; @@ -2956,43 +2956,52 @@ void Editor::print() dialog.setWindowTitle(tr("Print Document")); dialog.setOption(QAbstractPrintDialog::PrintCurrentPage,false); dialog.setOption(QAbstractPrintDialog::PrintPageRange,false); + if (selAvail()) - dialog.setOption(QAbstractPrintDialog::PrintSelection); + dialog.setOption(QAbstractPrintDialog::PrintSelection,true); + if (dialog.exec() != QDialog::Accepted) { return; } - QTextDocument doc; - QStringList lst; - if (dialog.testOption(QAbstractPrintDialog::PrintSelection)) - lst = textToLines(selText()); - else - lst = contents(); - for (int i=0;igetDefaultSystemEncoding()); + + exporter.setTitle(QFileInfo(mFilename).fileName()); + exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground()); + + exporter.setFont(font()); + QSynedit::PSyntaxer hl = syntaxer(); + if (!pSettings->editor().copyHTMLUseEditorColor()) { + hl = syntaxerManager.copy(syntaxer()); + syntaxerManager.applyColorScheme(hl,pSettings->editor().copyHTMLColorScheme()); } + exporter.setSyntaxer(hl); + exporter.setOnFormatToken(std::bind(&Editor::onExportedFormatToken, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4, + std::placeholders::_5 + )); + + if (dialog.testOption(QAbstractPrintDialog::PrintSelection)) + exporter.exportRange(document(),blockBegin(),blockEnd()); + else + exporter.exportAll(document()); + + QString html = exporter.text(); + QTextDocument doc; + doc.setDefaultFont(font()); - doc.setPlainText(lst.join(lineBreak())); + doc.setHtml(html); doc.print(&printer); } void Editor::exportAsRTF(const QString &rtfFilename) { - QSynedit::SynRTFExporter exporter(pCharsetInfoManager->getDefaultSystemEncoding()); + QSynedit::RTFExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding()); exporter.setTitle(extractFileName(rtfFilename)); - exporter.setExportAsText(true); exporter.setUseBackground(pSettings->editor().copyRTFUseBackground()); exporter.setFont(font()); QSynedit::PSyntaxer hl = syntaxer(); @@ -3009,15 +3018,14 @@ void Editor::exportAsRTF(const QString &rtfFilename) std::placeholders::_4, std::placeholders::_5 )); - exporter.ExportAll(document()); - exporter.SaveToFile(rtfFilename); + exporter.exportAll(document()); + exporter.saveToFile(rtfFilename); } void Editor::exportAsHTML(const QString &htmlFilename) { - QSynedit::SynHTMLExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding()); + QSynedit::HTMLExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding()); exporter.setTitle(extractFileName(htmlFilename)); - exporter.setExportAsText(false); exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground()); exporter.setFont(font()); QSynedit::PSyntaxer hl = syntaxer(); @@ -3034,8 +3042,8 @@ void Editor::exportAsHTML(const QString &htmlFilename) std::placeholders::_4, std::placeholders::_5 )); - exporter.ExportAll(document()); - exporter.SaveToFile(htmlFilename); + exporter.exportAll(document()); + exporter.saveToFile(htmlFilename); } void Editor::showCompletion(const QString& preWord,bool autoComplete, CodeCompletionType type) diff --git a/libs/qsynedit/qsynedit.pro b/libs/qsynedit/qsynedit.pro index a8dabd9d..d64b7ed0 100644 --- a/libs/qsynedit/qsynedit.pro +++ b/libs/qsynedit/qsynedit.pro @@ -27,9 +27,10 @@ SOURCES += qsynedit/CodeFolding.cpp \ qsynedit/SynEdit.cpp \ qsynedit/TextBuffer.cpp \ qsynedit/TextPainter.cpp \ - qsynedit/exporter/synexporter.cpp \ - qsynedit/exporter/synhtmlexporter.cpp \ - qsynedit/exporter/synrtfexporter.cpp \ + qsynedit/exporter/exporter.cpp \ + qsynedit/exporter/htmlexporter.cpp \ + qsynedit/exporter/qtsupportedhtmlexporter.cpp \ + qsynedit/exporter/rtfexporter.cpp \ qsynedit/syntaxer/asm.cpp \ qsynedit/syntaxer/cpp.cpp \ qsynedit/syntaxer/customhighlighterv1.cpp \ @@ -53,9 +54,10 @@ HEADERS += qsynedit/Search.h \ qsynedit/TextBuffer.h \ qsynedit/TextPainter.h \ qsynedit/Types.h \ - qsynedit/exporter/synexporter.h \ - qsynedit/exporter/synhtmlexporter.h \ - qsynedit/exporter/synrtfexporter.h \ + qsynedit/exporter/exporter.h \ + qsynedit/exporter/htmlexporter.h \ + qsynedit/exporter/qtsupportedhtmlexporter.h \ + qsynedit/exporter/rtfexporter.h \ qsynedit/syntaxer/asm.h \ qsynedit/syntaxer/cpp.h \ qsynedit/syntaxer/customhighlighterv1.h \ diff --git a/libs/qsynedit/qsynedit/exporter/exporter.cpp b/libs/qsynedit/qsynedit/exporter/exporter.cpp new file mode 100644 index 00000000..290e9a69 --- /dev/null +++ b/libs/qsynedit/qsynedit/exporter/exporter.cpp @@ -0,0 +1,378 @@ +/* + * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "exporter.h" + +#include +#include +#include +#include +#include + +namespace QSynedit { + +Exporter::Exporter(int tabSize, const QByteArray charset): + mTabSize(tabSize), + mCharset(charset) +{ + mFont = QGuiApplication::font(); + mBackgroundColor = QGuiApplication::palette().color(QPalette::Base); + mForegroundColor = QGuiApplication::palette().color(QPalette::Text); + mUseBackground = false; + mFileEndingType = NewlineType::Windows; + clear(); + setTitle(""); +} + +void Exporter::clear() +{ + mText.clear(); + mLastStyle = FontStyle::fsNone; + mLastBG = QGuiApplication::palette().color(QPalette::Base); + mLastFG = QGuiApplication::palette().color(QPalette::Text); +} + +void Exporter::exportAll(const PDocument& doc) +{ + exportRange(doc, BufferCoord{1, 1}, BufferCoord{INT_MAX, INT_MAX}); +} + +void Exporter::exportRange(const PDocument& doc, BufferCoord start, BufferCoord stop) +{ + // abort if not all necessary conditions are met + if (!doc || !mSyntaxer || (doc->count() == 0)) + return; + stop.line = std::max(1, std::min(stop.line, doc->count())); + stop.ch = std::max(1, std::min(stop.ch, doc->getString(stop.line - 1).length() + 1)); + start.line = std::max(1, std::min(start.line, doc->count())); + start.ch = std::max(1, std::min(start.ch, doc->getString(start.line - 1).length() + 1)); + if ( (start.line > doc->count()) || (start.line > stop.line) ) + return; + if ((start.line == stop.line) && (start.ch >= stop.ch)) + return; + // initialization + mText.clear(); + // export all the lines into fBuffer + mFirstAttribute = true; + + if (start.line == 1) + mSyntaxer->resetState(); + else + mSyntaxer->setState(doc->ranges(start.line-2)); + for (int i = start.line; i<=stop.line; i++) { + QString Line = doc->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 + mSyntaxer->setLine(Line, i); + while (!mSyntaxer->eol()) { + PTokenAttribute attri = mSyntaxer->getTokenAttribute(); + int startPos = mSyntaxer->getTokenPos(); + QString token = mSyntaxer->getToken(); + if (i==start.line && (startPos+token.length() < start.ch)) { + mSyntaxer->next(); + continue; + } + if (i==stop.line && (startPos >= stop.ch-1)) { + mSyntaxer->next(); + continue; + } + if (i==stop.line && (startPos+token.length() > stop.ch)) { + token = token.remove(stop.ch - startPos - 1); + } + if (i==start.line && startPos < start.ch-1) { + token = token.mid(start.ch-1-startPos); + } + + QString Token = replaceReservedChars(token); + if (mOnFormatToken) + mOnFormatToken(mSyntaxer, i, mSyntaxer->getTokenPos()+1, mSyntaxer->getToken(),attri); + setTokenAttribute(attri); + formatToken(Token); + mSyntaxer->next(); + } + if (i!=stop.line) + formatNewLine(); + } + if (!mFirstAttribute) + formatAfterLastAttribute(); + // insert header + insertData(0, getHeader()); + // add footer + addData(getFooter()); +} + +void Exporter::saveToFile(const QString &filename) +{ + QFile file(filename); + if (file.open(QIODevice::WriteOnly)) { + writeToStream(file); + } else { + throw FileError(QObject::tr("Can't open file '%1' to write!").arg(filename)); + } +} + +void Exporter::writeToStream(QIODevice &stream) +{ + QTextCodec *codec=getCodec(); + if (stream.write(codec->fromUnicode(mText))<0) { + throw FileError(QObject::tr("Failed to write data.")); + } +} + +QFont Exporter::font() const +{ + return mFont; +} + +void Exporter::setFont(const QFont &font) +{ + mFont = font; +} + +PSyntaxer Exporter::syntaxer() const +{ + return mSyntaxer; +} + +void Exporter::setSyntaxer(PSyntaxer value) +{ + if (mSyntaxer != value) { + mSyntaxer = value; + clear(); + if ((mSyntaxer) && (mSyntaxer->whitespaceAttribute()) && mUseBackground) + mBackgroundColor = mSyntaxer->whitespaceAttribute()->background(); + } +} + +QString Exporter::title() const +{ + return mTitle; +} + +void Exporter::setTitle(const QString &Value) +{ + if (mTitle != Value) { + if (!Value.isEmpty()) + mTitle = Value; + else + mTitle = "Untitled"; + } +} + +bool Exporter::useBackground() const +{ + return mUseBackground; +} + +void Exporter::setUseBackground(bool Value) +{ + if (mUseBackground != Value) { + mUseBackground = Value; + clear(); + if ((mSyntaxer) && (mSyntaxer->whitespaceAttribute()) && mUseBackground) + mBackgroundColor = mSyntaxer->whitespaceAttribute()->background(); + } +} + +NewlineType Exporter::fileEndingType() const +{ + return mFileEndingType; +} + +void Exporter::setFileEndingType(const NewlineType &fileEndingType) +{ + mFileEndingType = fileEndingType; +} + +QColor Exporter::foregroundColor() const +{ + return mForegroundColor; +} + +void Exporter::setForegroundColor(const QColor &value) +{ + if (mForegroundColor != value) { + mForegroundColor = value; + } +} + +QColor Exporter::backgroundColor() const +{ + return mBackgroundColor; +} + +void Exporter::setBackgroundColor(const QColor &value) +{ + if (mBackgroundColor != value) { + mBackgroundColor = value; + } +} + +QByteArray Exporter::charset() const +{ + return mCharset; +} + +void Exporter::setCharset(const QByteArray &charset) +{ + mCharset = charset; +} + +QString Exporter::defaultFilter() const +{ + return mDefaultFilter; +} + +void Exporter::setDefaultFilter(const QString &defaultFilter) +{ + mDefaultFilter = defaultFilter; +} + +void Exporter::addData(const QString &text) +{ + if (!text.isEmpty()) { + mText.append(text); + } +} + +void Exporter::addDataNewLine(const QString &text) +{ + addData(text); + addNewLine(); +} + +void Exporter::addNewLine() +{ + addData(lineBreak()); +} + +void Exporter::formatToken(const QString &token) +{ + addData(token); +} + +int Exporter::getBufferSize() const +{ + return mText.size(); +} + +QTextCodec * Exporter::getCodec() const { + QTextCodec* codec = QTextCodec::codecForName(mCharset); + if (codec == nullptr) + codec = QTextCodec::codecForLocale(); + return codec; +} +void Exporter::insertData(int pos, const QString &text) +{ + if (!text.isEmpty()) { + mText.insert(pos,text); + } +} + +QString Exporter::replaceReservedChars(const QString &token) +{ + if (token.isEmpty()) + return ""; + QString result; + for (QChar ch:token) { + if (mReplaceReserved.contains(ch)) { + result += mReplaceReserved[ch]; + } else { + result += ch; + } + } + return result; +} + +static QColor ValidatedColor(const QColor& color, const QColor& defaultColor) { + if (color.isValid()) + return color; + else + return defaultColor; +} + +void Exporter::setTokenAttribute(PTokenAttribute attri) +{ + if (mFirstAttribute) { + mFirstAttribute = false; + mLastBG = ValidatedColor(attri->background(), mBackgroundColor); + mLastFG = ValidatedColor(attri->foreground(), mForegroundColor); + mLastStyle = attri->styles(); + formatBeforeFirstAttribute( + mUseBackground && (mLastBG != mBackgroundColor), + mLastFG != mForegroundColor, attri->styles()); + } else { + bool ChangedBG = mUseBackground && + (mLastBG != ValidatedColor(attri->background(), mBackgroundColor)); + bool ChangedFG = (mLastFG != ValidatedColor(attri->foreground(), mForegroundColor)); + if (ChangedBG || ChangedFG || (mLastStyle != attri->styles())) { + // which font style bits are to reset? + FontStyles ChangedStyles = mLastStyle & ~(attri->styles()); + formatAttributeDone(ChangedBG, ChangedFG, ChangedStyles); + // which font style bits are to set? + ChangedStyles = attri->styles() & ~(mLastStyle); + mLastBG = ValidatedColor(attri->background(), mBackgroundColor); + mLastFG = ValidatedColor(attri->foreground(), mForegroundColor); + mLastStyle = attri->styles(); + formatAttributeInit(ChangedBG, ChangedFG, ChangedStyles); + } + } +} + +QByteArray Exporter::buffer() const +{ + QTextCodec* codec = getCodec(); + return codec->fromUnicode(mText); +} + +const QString &Exporter::text() const +{ + return mText; +} + +QByteArray Exporter::clipboardFormat() +{ + return mClipboardFormat; +} + +FormatTokenHandler Exporter::onFormatToken() const +{ + return mOnFormatToken; +} + +void Exporter::setOnFormatToken(const FormatTokenHandler &onFormatToken) +{ + mOnFormatToken = onFormatToken; +} + +QString Exporter::lineBreak() +{ + switch(mFileEndingType) { + case NewlineType::Unix: + return "\n"; + case NewlineType::Windows: + return "\r\n"; + case NewlineType::MacOld: + return "\r"; + } + return "\n"; +} + +} diff --git a/libs/qsynedit/qsynedit/exporter/synexporter.h b/libs/qsynedit/qsynedit/exporter/exporter.h similarity index 68% rename from libs/qsynedit/qsynedit/exporter/synexporter.h rename to libs/qsynedit/qsynedit/exporter/exporter.h index ee84b603..2d75f9d5 100644 --- a/libs/qsynedit/qsynedit/exporter/synexporter.h +++ b/libs/qsynedit/qsynedit/exporter/exporter.h @@ -14,8 +14,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef SYNEXPORTER_H -#define SYNEXPORTER_H +#ifndef EXPORTER_H +#define EXPORTER_H #include #include "../SynEdit.h" @@ -23,48 +23,41 @@ namespace QSynedit { using FormatTokenHandler = std::function; -class SynExporter +class Exporter { public: - explicit SynExporter(const QByteArray charset); + explicit Exporter(int tabSize, const QByteArray charset); /** * @brief Clears the output buffer and any internal data that relates to the last * exported text. */ virtual void clear(); - /** - * @brief Copies the output buffer contents to the clipboard, as the native format - * or as text depending on the ExportAsText property. - */ - void CopyToClipboard(); /** * @brief Exports everything in the strings parameter to the output buffer. - * @param ALines + * @param doc */ - void ExportAll(PDocument ALines); + void exportAll(const PDocument& doc); /** * @brief Exports the given range of the strings parameter to the output buffer. - * @param ALines - * @param Start - * @param Stop + * @param doc + * @param start + * @param stop */ - void ExportRange(PDocument ALines, - BufferCoord Start, BufferCoord Stop); + void exportRange(const PDocument& doc, + BufferCoord start, BufferCoord stop); /** * @brief Saves the contents of the output buffer to a file. * @param AFileName */ - void SaveToFile(const QString& AFileName); + void saveToFile(const QString& filename); /** * @brief Saves the contents of the output buffer to a stream. - * @param AStream + * @param stream */ - void SaveToStream(QIODevice& AStream); - bool exportAsText() const; - void setExportAsText(bool Value); + void writeToStream(QIODevice& stream); QFont font() const; void setFont(const QFont &font); @@ -85,7 +78,7 @@ public: * @brief The clipboard format the exporter creates as native format. * @return */ - virtual QByteArray clipboardFormat(); + QByteArray clipboardFormat(); QColor foregroundColor() const; void setForegroundColor(const QColor &value); @@ -102,15 +95,16 @@ public: FormatTokenHandler onFormatToken() const; void setOnFormatToken(const FormatTokenHandler &onFormatToken); - const QByteArray& buffer() const; + QByteArray buffer() const; + const QString& text() const; protected: + int mTabSize; + QByteArray mClipboardFormat; QByteArray mCharset; QColor mBackgroundColor; QColor mForegroundColor; - QByteArray mClipboardFormat; QString mDefaultFilter; - bool mExportAsText; QFont mFont; PSyntaxer mSyntaxer; QColor mLastBG; @@ -125,126 +119,119 @@ protected: /** * @brief Adds a string to the output buffer. - * @param AText + * @param text */ - void AddData(const QString& AText); + void addData(const QString& text); /** * @brief Adds a string and a trailing newline to the output buffer. - * @param AText + * @param text */ - void AddDataNewLine(const QString& AText); + void addDataNewLine(const QString& text); /** * @brief Adds a newline to the output buffer. */ - void AddNewLine(); - - - /** - * @brief Copies the data under this format to the clipboard. The clipboard has to - * be opened explicitly when more than one format is to be set. - */ - void CopyToClipboardFormat(QByteArray AFormat); + void addNewLine(); /** * @brief Has to be overridden in descendant classes to add the closing format * strings to the output buffer. The parameters can be used to track what * changes are made for the next token. - * @param BackgroundChanged - * @param ForegroundChanged - * @param FontStylesChanged + * @param backgroundChanged + * @param foregroundChanged + * @param fontStyles */ - virtual void FormatAttributeDone(bool BackgroundChanged, bool ForegroundChanged, - FontStyles FontStylesChanged) = 0; + virtual void formatAttributeDone(bool backgroundChanged, bool foregroundChanged, + FontStyles fontStyles) = 0; /** * @brief Has to be overridden in descendant classes to add the opening format * strings to the output buffer. The parameters can be used to track what * changes have been made in respect to the previous token. - * @param BackgroundChanged - * @param ForegroundChanged - * @param FontStylesChanged + * @param backgroundChanged + * @param foregroundChanged + * @param fontStyles */ - virtual void FormatAttributeInit(bool BackgroundChanged, bool ForegroundChanged, - FontStyles FontStylesChanged) = 0; + virtual void formatAttributeInit(bool backgroundChanged, bool foregroundChanged, + FontStyles fontStyles) = 0; /** * @brief Has to be overridden in descendant classes to add the closing format * strings to the output buffer after the last token has been written. */ - virtual void FormatAfterLastAttribute() = 0; + virtual void formatAfterLastAttribute() = 0; /** * @brief Has to be overridden in descendant classes to add the opening format * strings to the output buffer when the first token is about to be written. - * @param BackgroundChanged - * @param ForegroundChanged - * @param FontStylesChanged + * @param backgroundChanged + * @param foregroundChanged + * @param fontStyles */ - virtual void FormatBeforeFirstAttribute(bool BackgroundChanged, bool ForegroundChanged, - FontStyles FontStylesChanged) = 0; + virtual void formatBeforeFirstAttribute(bool backgroundChanged, bool foregroundChanged, + FontStyles fontStyles) = 0; /** * @brief Can be overridden in descendant classes to add the formatted text of * the actual token text to the output buffer. */ - virtual void FormatToken(const 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. */ - virtual void FormatNewLine() = 0; + virtual void formatNewLine() = 0; /** * @brief Returns the size of the formatted text in the output buffer, to be used * in the format header or footer. * @return */ - int GetBufferSize(); + int getBufferSize() const; /** * @brief Has to be overridden in descendant classes to return the correct output * format footer. * @return */ - virtual QString GetFooter() = 0; + virtual QString getFooter() = 0; /** * @brief Has to be overridden in descendant classes to return the name of the * output format. * @return */ - virtual QString GetFormatName() = 0; + virtual QString getFormatName() = 0; /** * @brief Has to be overridden in descendant classes to return the correct output * format header. * @return */ - virtual QString GetHeader() = 0; + virtual QString getHeader() = 0; /** * @brief Inserts a data block at the given position into the output buffer. Is * used to insert the format header after the exporting, since some header * data may be known only after the conversion is done. - * @param APos - * @param AText + * @param pos + * @param text */ - void InsertData(int APos, const QString& AText); + void insertData(int pos, const QString& text); /** * @brief Returns a string that has all the invalid chars of the output format * replaced with the entries in the replacement array. */ - QString ReplaceReservedChars(const QString &AToken); + QString replaceReservedChars(const QString &token); /** * @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 * added to the output buffer. - * @param Attri + * @param attri */ - virtual void SetTokenAttribute(PTokenAttribute Attri); + virtual void setTokenAttribute(PTokenAttribute attri); - QTextCodec *getCodec(); + QTextCodec *getCodec() const; private: - QByteArray mBuffer; + QString mText; bool mFirstAttribute; FormatTokenHandler mOnFormatToken; }; } -#endif // SYNEXPORTER_H +#endif // EXPORTER_H diff --git a/libs/qsynedit/qsynedit/exporter/synhtmlexporter.cpp b/libs/qsynedit/qsynedit/exporter/htmlexporter.cpp similarity index 52% rename from libs/qsynedit/qsynedit/exporter/synhtmlexporter.cpp rename to libs/qsynedit/qsynedit/exporter/htmlexporter.cpp index 91a353db..da917a44 100644 --- a/libs/qsynedit/qsynedit/exporter/synhtmlexporter.cpp +++ b/libs/qsynedit/qsynedit/exporter/htmlexporter.cpp @@ -14,14 +14,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "synhtmlexporter.h" +#include "htmlexporter.h" #include "../MiscProcs.h" #include namespace QSynedit { -SynHTMLExporter::SynHTMLExporter(int tabSize,const QByteArray charset): - SynExporter(charset) +HTMLExporter::HTMLExporter(int tabSize,const QByteArray charset): + Exporter(tabSize,charset) { mClipboardFormat = "text/html"; mDefaultFilter = "HTML Documents (*.htm;*.html)|*.htm;*.html"; @@ -35,139 +35,139 @@ SynHTMLExporter::SynHTMLExporter(int tabSize,const QByteArray charset): mCreateHTMLFragment = false; } -bool SynHTMLExporter::createHTMLFragment() const +bool HTMLExporter::createHTMLFragment() const { return mCreateHTMLFragment; } -void SynHTMLExporter::setCreateHTMLFragment(bool createHTMLFragment) +void HTMLExporter::setCreateHTMLFragment(bool createHTMLFragment) { mCreateHTMLFragment = createHTMLFragment; } -QString SynHTMLExporter::AttriToCSS(PTokenAttribute Attri, const QString &UniqueAttriName) +QString HTMLExporter::attriToCSS(PTokenAttribute attri, const QString &uniqueAttriName) { - QString StyleName = MakeValidName(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()) + "; "; + 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(FontStyle::fsBold)) - Result += "font-weight: bold; "; - if (Attri->styles().testFlag(FontStyle::fsItalic)) - Result += "font-style: italic; "; - if (Attri->styles().testFlag(FontStyle::fsUnderline)) - Result += "text-decoration: underline; "; - if (Attri->styles().testFlag(FontStyle::fsStrikeOut)) - Result += "text-decoration: line-through; "; - Result += "}"; - return Result; -} - -bool SynHTMLExporter::AttriToCSSCallback(PSyntaxer , PTokenAttribute 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(PSyntaxer Highlighter, PTokenAttribute Attri) -{ - QString result; - enumTokenAttributes(Highlighter,false, - std::bind( - &SynHTMLExporter::StyleNameCallback,this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4), - {&Attri,&result}); + if (attri->styles().testFlag(FontStyle::fsBold)) + result += "font-weight: bold; "; + if (attri->styles().testFlag(FontStyle::fsItalic)) + result += "font-style: italic; "; + if (attri->styles().testFlag(FontStyle::fsUnderline)) + result += "text-decoration: underline; "; + if (attri->styles().testFlag(FontStyle::fsStrikeOut)) + result += "text-decoration: line-through; "; + result += "}"; return result; } -QString SynHTMLExporter::MakeValidName(const QString &Name) +bool HTMLExporter::attriToCSSCallback(PSyntaxer , PTokenAttribute attri, const QString& uniqueAttriName, QList params) { - 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; + QString& styles = *static_cast(params[0]); + styles.append(attriToCSS(attri,uniqueAttriName) + lineBreak()); + return true; } -bool SynHTMLExporter::StyleNameCallback(PSyntaxer /*Highlighter*/, PTokenAttribute Attri, const QString& UniqueAttriName, QList params) +QString HTMLExporter::colorToHTML(const QColor &color) const { - PTokenAttribute& AttriToFind = *static_cast(params[0]); - QString& StyleName = *static_cast(params[1]); + return color.name(); +} - if (Attri == AttriToFind) { - StyleName.clear(); - StyleName.append(MakeValidName(UniqueAttriName)); +QString HTMLExporter::getStyleName(PSyntaxer syntaxer, PTokenAttribute attri) +{ + QString result; + enumTokenAttributes(syntaxer,false, + std::bind( + &HTMLExporter::styleNameCallback,this, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4), + {&attri,&result}); + return result; +} + +QString HTMLExporter::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 HTMLExporter::styleNameCallback(PSyntaxer /*syntaxer*/, PTokenAttribute attri, const QString& uniqueAttriName, QList params) +{ + PTokenAttribute& 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 , FontStyles ) +void HTMLExporter::formatAttributeDone(bool , bool , FontStyles ) { - AddData(""); + addData(""); } -void SynHTMLExporter::FormatAttributeInit(bool , bool , FontStyles ) +void HTMLExporter::formatAttributeInit(bool , bool , FontStyles ) { - QString StyleName = GetStyleName(mSyntaxer, mLastAttri); - AddData(QString("").arg(StyleName)); + QString styleName = getStyleName(mSyntaxer, mLastAttri); + addData(QString("").arg(styleName)); } -void SynHTMLExporter::FormatAfterLastAttribute() +void HTMLExporter::formatAfterLastAttribute() { - AddData(""); + addData(""); } -void SynHTMLExporter::FormatBeforeFirstAttribute(bool, bool, FontStyles) +void HTMLExporter::formatBeforeFirstAttribute(bool, bool, FontStyles) { - QString StyleName = GetStyleName(mSyntaxer, mLastAttri); - AddData(QString("").arg(StyleName)); + QString styleName = getStyleName(mSyntaxer, mLastAttri); + addData(QString("").arg(styleName)); } -void SynHTMLExporter::FormatNewLine() +void HTMLExporter::formatNewLine() { - AddData("
"); - AddNewLine(); + addData("
"); + addNewLine(); } -QString SynHTMLExporter::GetFooter() +QString HTMLExporter::getFooter() { - QString Result = ""; - Result = "
" + lineBreak(); + QString result = ""; + result = "" + lineBreak(); if (mCreateHTMLFragment) - Result += ""; - Result += ""+lineBreak()+ ""; - return Result; + result += ""; + result += ""+lineBreak()+ ""; + return result; } -QString SynHTMLExporter::GetFormatName() +QString HTMLExporter::getFormatName() { return "HTML"; } -QString SynHTMLExporter::GetHeader() +QString HTMLExporter::getHeader() { using namespace std::placeholders; - QString Styles; + QString styles; enumTokenAttributes(mSyntaxer, true, - std::bind(&SynHTMLExporter::AttriToCSSCallback, + std::bind(&HTMLExporter::attriToCSSCallback, this, _1, _2, _3, _4), - {&Styles}); + {&styles}); QString HTMLAsTextHeader = ""+lineBreak() + "" + lineBreak() + @@ -184,12 +184,12 @@ QString SynHTMLExporter::GetHeader() "" + lineBreak() + "" + lineBreak() + "" + lineBreak(); - QString Header = HTMLAsTextHeader + QString header = HTMLAsTextHeader .arg(mTitle) .arg(QString(mCharset)) - .arg(ColorToHTML(mForegroundColor)) - .arg(ColorToHTML(mBackgroundColor)) - .arg(Styles); + .arg(colorToHTML(mForegroundColor)) + .arg(colorToHTML(mBackgroundColor)) + .arg(styles); if (mCreateHTMLFragment) { HTMLAsTextHeader = ""+lineBreak() + "" + lineBreak() + @@ -205,26 +205,26 @@ QString SynHTMLExporter::GetHeader() "" + lineBreak() + "" + lineBreak() + "" + lineBreak(); - Header = HTMLAsTextHeader + header = HTMLAsTextHeader .arg(QString(mCharset)) - .arg(ColorToHTML(mForegroundColor)) - .arg(ColorToHTML(mBackgroundColor)) - .arg(Styles); + .arg(colorToHTML(mForegroundColor)) + .arg(colorToHTML(mBackgroundColor)) + .arg(styles); } - QString Result = Header; + QString result = header; if (mCreateHTMLFragment) { - Result += ""; + result += ""; } - Result += QString("") + result += QString("
") .arg(pixelToPoint(mFont.pixelSize())) .arg(mFont.family()); - return Result; + return result; } -void SynHTMLExporter::SetTokenAttribute(PTokenAttribute Attri) +void HTMLExporter::setTokenAttribute(PTokenAttribute attri) { - mLastAttri = Attri; - SynExporter::SetTokenAttribute(Attri); + mLastAttri = attri; + Exporter::setTokenAttribute(attri); } } diff --git a/libs/qsynedit/qsynedit/exporter/htmlexporter.h b/libs/qsynedit/qsynedit/exporter/htmlexporter.h new file mode 100644 index 00000000..41c86150 --- /dev/null +++ b/libs/qsynedit/qsynedit/exporter/htmlexporter.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef HTMLEXPORTER_H +#define HTMLEXPORTER_H + +#include "exporter.h" + +namespace QSynedit { +class HTMLExporter : public Exporter +{ +public: + HTMLExporter(int tabSize,const QByteArray charset); + bool createHTMLFragment() const; + void setCreateHTMLFragment(bool createHTMLFragment); + +protected: + bool mCreateHTMLFragment; +private: + PTokenAttribute mLastAttri; + QString attriToCSS(PTokenAttribute attri, const QString& uniqueAttriName); + bool attriToCSSCallback(PSyntaxer syntaxer, PTokenAttribute attri, + const QString& uniqueAttriName, QList params); + QString colorToHTML(const QColor &color) const; + QString getStyleName(PSyntaxer syntaxer, + PTokenAttribute attri); + QString makeValidName(const QString &name); + bool styleNameCallback(PSyntaxer syntaxer, PTokenAttribute attri, + const QString& uniqueAttriName, QList params); + + // SynExporter interface +protected: + void formatAttributeDone(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles); + void formatAttributeInit(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles); + void formatAfterLastAttribute(); + void formatBeforeFirstAttribute(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles); + void formatNewLine(); + QString getFooter(); + QString getFormatName(); + QString getHeader(); + void setTokenAttribute(PTokenAttribute Attri); +}; +} +#endif // HTMLEXPORTER_H diff --git a/libs/qsynedit/qsynedit/exporter/qtsupportedhtmlexporter.cpp b/libs/qsynedit/qsynedit/exporter/qtsupportedhtmlexporter.cpp new file mode 100644 index 00000000..2c8adf2f --- /dev/null +++ b/libs/qsynedit/qsynedit/exporter/qtsupportedhtmlexporter.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "qtsupportedhtmlexporter.h" +#include "../MiscProcs.h" +#include + +namespace QSynedit { + +QtSupportedHtmlExporter::QtSupportedHtmlExporter(int tabSize,const QByteArray charset): + Exporter(tabSize,charset) +{ + mClipboardFormat = "text/html"; + mDefaultFilter = "HTML Documents (*.htm;*.html)|*.htm;*.html"; + // setup array of chars to be replaced + mReplaceReserved['&'] = "&"; + mReplaceReserved['<'] = "<"; + mReplaceReserved['>'] = ">"; + mReplaceReserved['"'] = """; + mReplaceReserved[' '] = " "; + mReplaceReserved['\t'] = mReplaceReserved[' '].repeated(tabSize); + mCreateHTMLFragment = false; +} + +bool QtSupportedHtmlExporter::createHTMLFragment() const +{ + return mCreateHTMLFragment; +} + +void QtSupportedHtmlExporter::setCreateHTMLFragment(bool createHTMLFragment) +{ + mCreateHTMLFragment = createHTMLFragment; +} + +QString QtSupportedHtmlExporter::attriToCSS(PTokenAttribute attri) +{ + QString result; + if (mUseBackground && attri->background().isValid()) + result += "background-color: " + colorToHTML(attri->background()) + "; "; + if (attri->foreground().isValid()) + result += "color: " + colorToHTML(attri->foreground()) + "; "; + + if (attri->styles().testFlag(FontStyle::fsBold)) + result += "font-weight: bold; "; + if (attri->styles().testFlag(FontStyle::fsItalic)) + result += "font-style: italic; "; + if (attri->styles().testFlag(FontStyle::fsUnderline)) + result += "text-decoration: underline; "; + if (attri->styles().testFlag(FontStyle::fsStrikeOut)) + result += "text-decoration: line-through; "; + return result; +} + +QString QtSupportedHtmlExporter::colorToHTML(const QColor &color) +{ + return color.name(); +} + +void QtSupportedHtmlExporter::formatAttributeDone(bool , bool , FontStyles ) +{ + addData(""); +} + +void QtSupportedHtmlExporter::formatAttributeInit(bool , bool , FontStyles ) +{ + addData(QString("").arg(attriToCSS(mLastAttri))); +} + +void QtSupportedHtmlExporter::formatAfterLastAttribute() +{ + addData(""); +} + +void QtSupportedHtmlExporter::formatBeforeFirstAttribute(bool, bool, FontStyles) +{ + addData(QString("").arg(attriToCSS(mLastAttri))); +} + +void QtSupportedHtmlExporter::formatNewLine() +{ + addData("
"); + addNewLine(); +} + +QString QtSupportedHtmlExporter::getFooter() +{ + QString result = ""; + result = "
" + lineBreak(); + if (mCreateHTMLFragment) + result += ""; + result += ""+lineBreak()+ ""; + return result; +} + +QString QtSupportedHtmlExporter::getFormatName() +{ + return "HTML"; +} + +QString QtSupportedHtmlExporter::getHeader() +{ + using namespace std::placeholders; + QString styles; + + + QString HTMLAsTextHeader = ""+lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + ""+ lineBreak() + + "%1" + lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + "" + lineBreak(); + QString header = HTMLAsTextHeader + .arg(mTitle) + .arg(QString(mCharset)); + if (mCreateHTMLFragment) { + HTMLAsTextHeader = ""+lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + ""+ lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + "" + lineBreak() + + "" + lineBreak(); + header = HTMLAsTextHeader + .arg(QString(mCharset)); + } + QString result = header; + if (mCreateHTMLFragment) { + result += ""+lineBreak(); + } + if (mUseBackground) { + result += QString("
") + .arg(colorToHTML(mForegroundColor)) + .arg(colorToHTML(mBackgroundColor)) + .arg(pixelToPoint(mFont.pixelSize())) + .arg(mFont.family())+lineBreak(); + } else { + result += QString("
") + .arg(colorToHTML(mForegroundColor)) + .arg(pixelToPoint(mFont.pixelSize())) + .arg(mFont.family())+lineBreak(); + } + + return result; +} + +void QtSupportedHtmlExporter::setTokenAttribute(PTokenAttribute Attri) +{ + mLastAttri = Attri; + Exporter::setTokenAttribute(Attri); +} +} diff --git a/libs/qsynedit/qsynedit/exporter/qtsupportedhtmlexporter.h b/libs/qsynedit/qsynedit/exporter/qtsupportedhtmlexporter.h new file mode 100644 index 00000000..6f5bfd0e --- /dev/null +++ b/libs/qsynedit/qsynedit/exporter/qtsupportedhtmlexporter.h @@ -0,0 +1,34 @@ +#ifndef QTSUPPORTEDHTMLEXPORTER_H +#define QTSUPPORTEDHTMLEXPORTER_H + +#include "exporter.h" + +namespace QSynedit { +class QtSupportedHtmlExporter : public Exporter +{ +public: + QtSupportedHtmlExporter(int tabSize,const QByteArray charset); + bool createHTMLFragment() const; + void setCreateHTMLFragment(bool createHTMLFragment); + +protected: + bool mCreateHTMLFragment; +private: + PTokenAttribute mLastAttri; + QString attriToCSS(PTokenAttribute attri); + QString colorToHTML(const QColor &color); + + // SynExporter interface +protected: + void formatAttributeDone(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles); + void formatAttributeInit(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles); + void formatAfterLastAttribute(); + void formatBeforeFirstAttribute(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles); + void formatNewLine(); + QString getFooter(); + QString getFormatName(); + QString getHeader(); + void setTokenAttribute(PTokenAttribute Attri); +}; +} +#endif // QTSUPPORTEDHTMLEXPORTER_H diff --git a/libs/qsynedit/qsynedit/exporter/rtfexporter.cpp b/libs/qsynedit/qsynedit/exporter/rtfexporter.cpp new file mode 100644 index 00000000..91aa1bc0 --- /dev/null +++ b/libs/qsynedit/qsynedit/exporter/rtfexporter.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "rtfexporter.h" +namespace QSynedit { + +RTFExporter::RTFExporter(int tabSize, const QByteArray charset):Exporter(tabSize,charset) +{ + 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['}'] = "\\}"; + mReplaceReserved['\t'] = "\\tab"; + +} + +QString RTFExporter::colorToRTF(const QColor &color) const +{ + return QString("\\red%1\\green%2\\blue%3;") + .arg(color.red()) + .arg(color.green()) + .arg(color.blue()); +} + +int RTFExporter::getColorIndex(const QColor &color) +{ + int index = mListColors.indexOf(color); + if (index<0) { + mListColors.append(color); + index = mListColors.length()-1; + } + return index; +} + +QString RTFExporter::getFontTable() +{ + QString result = "{\\fonttbl{\\f0\\fmodern\\fcharset134 " + + replaceReservedChars(mFont.family()); + result = result + ";}}" + lineBreak(); + return result; +} + +void RTFExporter::formatAttributeDone(bool , bool , FontStyles fontStyles) +{ + // nothing to do about the color, but reset the font style + if (fontStyles.testFlag(FontStyle::fsBold)) { + mAttributesChanged = true; + addData("\\b0"); + } + if (fontStyles.testFlag(FontStyle::fsItalic)) { + mAttributesChanged = true; + addData("\\i0"); + } + if (fontStyles.testFlag(FontStyle::fsUnderline)) { + mAttributesChanged = true; + addData("\\ul0"); + } + if (fontStyles.testFlag(FontStyle::fsStrikeOut)) { + mAttributesChanged = true; + addData("\\strike0"); + } +} + +void RTFExporter::formatAttributeInit(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles) +{ + // 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 (fontStyles.testFlag(FontStyle::fsBold)) { + mAttributesChanged = true; + addData("\\b0"); + } + if (fontStyles.testFlag(FontStyle::fsItalic)) { + mAttributesChanged = true; + addData("\\i0"); + } + if (fontStyles.testFlag(FontStyle::fsUnderline)) { + mAttributesChanged = true; + addData("\\ul0"); + } + if (fontStyles.testFlag(FontStyle::fsStrikeOut)) { + mAttributesChanged = true; + addData("\\strike0"); + } + if (mAttributesChanged) { + addData(" "); + mAttributesChanged = false; + } +} + +void RTFExporter::formatAfterLastAttribute() +{ + // no need to reset the font style here... +} + +void RTFExporter::formatBeforeFirstAttribute(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles) +{ + formatAttributeInit(backgroundChanged, foregroundChanged, fontStyles); +} + +void RTFExporter::formatNewLine() +{ + addNewLine(); + addData("\\par "); +} + +QString RTFExporter::getFooter() +{ + return "}"; +} + +QString RTFExporter::getFormatName() +{ + return "RTF"; +} + +QString RTFExporter::getHeader() +{ + QFontMetrics fm(mFont); + int tabWidth = mTabSize * fm.horizontalAdvance("M")*72*20/fm.fontDpi(); + + QString result = QString("{\\rtf1\\ansi\\deff0\\deftab%1").arg(tabWidth) + getFontTable(); + // all the colors + result = result + "{\\colortbl"; + for (int i = 0; i. + */ +#ifndef RTFEXPORTER_H +#define RTFEXPORTER_H + +#include "exporter.h" + +namespace QSynedit { + +class RTFExporter : public Exporter +{ +public: + explicit RTFExporter(int tabSize,const QByteArray charset); +private: + bool mAttributesChanged; + QList mListColors; + QString colorToRTF(const QColor& AColor) const; + int getColorIndex(const QColor& AColor); + QString getFontTable(); + + // SynExporter interface +protected: + void formatAttributeDone(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles) override; + void formatAttributeInit(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles) override; + void formatAfterLastAttribute() override; + void formatBeforeFirstAttribute(bool backgroundChanged, bool foregroundChanged, FontStyles fontStyles) override; + void formatNewLine() override; + QString getFooter() override; + QString getFormatName() override; + QString getHeader() override; +}; + +} +#endif // RTFEXPORTER_H diff --git a/libs/qsynedit/qsynedit/exporter/synexporter.cpp b/libs/qsynedit/qsynedit/exporter/synexporter.cpp deleted file mode 100644 index eb13d9b3..00000000 --- a/libs/qsynedit/qsynedit/exporter/synexporter.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "synexporter.h" - -#include -#include -#include -#include -#include - -namespace QSynedit { - -SynExporter::SynExporter(const QByteArray charset):mCharset(charset) -{ - mClipboardFormat = "text/plain"; - mFont = QGuiApplication::font(); - mBackgroundColor = QGuiApplication::palette().color(QPalette::Base); - mForegroundColor = QGuiApplication::palette().color(QPalette::Text); - mUseBackground = false; - mExportAsText = false; - mFileEndingType = NewlineType::Windows; - clear(); - setTitle(""); -} - -void SynExporter::clear() -{ - mBuffer.clear(); - mLastStyle = FontStyle::fsNone; - mLastBG = QGuiApplication::palette().color(QPalette::Base); - mLastFG = QGuiApplication::palette().color(QPalette::Text); -} - -void SynExporter::CopyToClipboard() -{ - if (mExportAsText) { - CopyToClipboardFormat("text/plain"); - } else - CopyToClipboardFormat(clipboardFormat()); -} - -void SynExporter::ExportAll(PDocument ALines) -{ - ExportRange(ALines, BufferCoord{1, 1}, BufferCoord{INT_MAX, INT_MAX}); -} - -void SynExporter::ExportRange(PDocument ALines, BufferCoord Start, BufferCoord Stop) -{ - // abort if not all necessary conditions are met - if (!ALines || !mSyntaxer || (ALines->count() == 0)) - return; - Stop.line = std::max(1, std::min(Stop.line, ALines->count())); - Stop.ch = std::max(1, std::min(Stop.ch, ALines->getString(Stop.line - 1).length() + 1)); - Start.line = std::max(1, std::min(Start.line, ALines->count())); - Start.ch = std::max(1, std::min(Start.ch, ALines->getString(Start.line - 1).length() + 1)); - if ( (Start.line > ALines->count()) || (Start.line > Stop.line) ) - return; - if ((Start.line == Stop.line) && (Start.ch >= Stop.ch)) - return; - // initialization - mBuffer.clear(); - // export all the lines into fBuffer - mFirstAttribute = true; - - if (Start.line == 1) - mSyntaxer->resetState(); - else - mSyntaxer->setState(ALines->ranges(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 - mSyntaxer->setLine(Line, i); - while (!mSyntaxer->eol()) { - PTokenAttribute attri = mSyntaxer->getTokenAttribute(); - int startPos = mSyntaxer->getTokenPos(); - QString token = mSyntaxer->getToken(); - if (i==Start.line && (startPos+token.length() < Start.ch)) { - mSyntaxer->next(); - continue; - } - if (i==Stop.line && (startPos >= Stop.ch-1)) { - mSyntaxer->next(); - continue; - } - if (i==Stop.line && (startPos+token.length() > Stop.ch)) { - token = token.remove(Stop.ch - startPos - 1); - } - if (i==Start.line && startPos < Start.ch-1) { - token = token.mid(Start.ch-1-startPos); - } - - QString Token = ReplaceReservedChars(token); - if (mOnFormatToken) - mOnFormatToken(mSyntaxer, i, mSyntaxer->getTokenPos()+1, mSyntaxer->getToken(),attri); - SetTokenAttribute(attri); - FormatToken(Token); - mSyntaxer->next(); - } - if (i!=Stop.line) - 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); - } else { - throw FileError(QObject::tr("Can't open file '%1' to write!").arg(AFileName)); - } -} - -void SynExporter::SaveToStream(QIODevice &AStream) -{ - if (AStream.write(mBuffer)<0) { - throw FileError(QObject::tr("Failed to write data.")); - } -} - -bool SynExporter::exportAsText() const -{ - return mExportAsText; -} - -void SynExporter::setExportAsText(bool Value) -{ - if (mExportAsText != Value) { - mExportAsText = Value; - clear(); - } -} - -QFont SynExporter::font() const -{ - return mFont; -} - -void SynExporter::setFont(const QFont &font) -{ - mFont = font; -} - -PSyntaxer SynExporter::syntaxer() const -{ - return mSyntaxer; -} - -void SynExporter::setSyntaxer(PSyntaxer value) -{ - if (mSyntaxer != value) { - mSyntaxer = value; - clear(); - if ((mSyntaxer) && (mSyntaxer->whitespaceAttribute()) && mUseBackground) - mBackgroundColor = mSyntaxer->whitespaceAttribute()->background(); - } -} - -QString SynExporter::title() const -{ - return mTitle; -} - -void SynExporter::setTitle(const QString &Value) -{ - if (mTitle != Value) { - if (!Value.isEmpty()) - mTitle = Value; - else - mTitle = "Untitled"; - } -} - -bool SynExporter::useBackground() const -{ - return mUseBackground; -} - -void SynExporter::setUseBackground(bool Value) -{ - if (mUseBackground != Value) { - mUseBackground = Value; - clear(); - if ((mSyntaxer) && (mSyntaxer->whitespaceAttribute()) && mUseBackground) - mBackgroundColor = mSyntaxer->whitespaceAttribute()->background(); - } -} - -NewlineType SynExporter::fileEndingType() const -{ - return mFileEndingType; -} - -void SynExporter::setFileEndingType(const NewlineType &fileEndingType) -{ - mFileEndingType = fileEndingType; -} - -QColor SynExporter::foregroundColor() const -{ - return mForegroundColor; -} - -void SynExporter::setForegroundColor(const QColor &value) -{ - if (mForegroundColor != value) { - mForegroundColor = value; - } -} - -QColor SynExporter::backgroundColor() const -{ - return mBackgroundColor; -} - -void SynExporter::setBackgroundColor(const QColor &value) -{ - if (mBackgroundColor != value) { - mBackgroundColor = value; - } -} - -QByteArray SynExporter::charset() const -{ - return mCharset; -} - -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 = getCodec(); - mBuffer.append(codec->fromUnicode(AText)); - } -} - -void SynExporter::AddDataNewLine(const QString &AText) -{ - AddData(AText); - AddNewLine(); -} - -void SynExporter::AddNewLine() -{ - AddData(lineBreak()); -} - -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(const QString &Token) -{ - AddData(Token); -} - -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 = getCodec(); - mBuffer.insert(APos,codec->fromUnicode(AText)); - } -} - -QString SynExporter::ReplaceReservedChars(const QString &AToken) -{ - if (AToken.isEmpty()) - return ""; - QString result; - for (QChar ch:AToken) { - if (mReplaceReserved.contains(ch)) { - result += mReplaceReserved[ch]; - } else { - result += ch; - } - } - return result; -} - -static QColor ValidatedColor(const QColor& color, const QColor& defaultColor) { - if (color.isValid()) - return color; - else - return defaultColor; -} -void SynExporter::SetTokenAttribute(PTokenAttribute Attri) -{ - if (mFirstAttribute) { - mFirstAttribute = false; - mLastBG = ValidatedColor(Attri->background(), mBackgroundColor); - mLastFG = ValidatedColor(Attri->foreground(), mForegroundColor); - mLastStyle = Attri->styles(); - FormatBeforeFirstAttribute( - mUseBackground && (mLastBG != mBackgroundColor), - mLastFG != mForegroundColor, Attri->styles()); - } else { - bool ChangedBG = mUseBackground && - (mLastBG != ValidatedColor(Attri->background(), mBackgroundColor)); - bool ChangedFG = (mLastFG != ValidatedColor(Attri->foreground(), mForegroundColor)); - if (ChangedBG || ChangedFG || (mLastStyle != Attri->styles())) { - // which font style bits are to reset? - FontStyles ChangedStyles = mLastStyle & ~(Attri->styles()); - FormatAttributeDone(ChangedBG, ChangedFG, ChangedStyles); - // which font style bits are to set? - ChangedStyles = Attri->styles() & ~(mLastStyle); - mLastBG = ValidatedColor(Attri->background(), mBackgroundColor); - mLastFG = ValidatedColor(Attri->foreground(), mForegroundColor); - mLastStyle = Attri->styles(); - FormatAttributeInit(ChangedBG, ChangedFG, ChangedStyles); - } - } -} - -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 NewlineType::Unix: - return "\n"; - case NewlineType::Windows: - return "\r\n"; - case NewlineType::MacOld: - return "\r"; - } - return "\n"; -} - -} diff --git a/libs/qsynedit/qsynedit/exporter/synhtmlexporter.h b/libs/qsynedit/qsynedit/exporter/synhtmlexporter.h deleted file mode 100644 index 1439914c..00000000 --- a/libs/qsynedit/qsynedit/exporter/synhtmlexporter.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef SYNHTMLEXPORTER_H -#define SYNHTMLEXPORTER_H - -#include "synexporter.h" - -namespace QSynedit { -class SynHTMLExporter : public SynExporter -{ -public: - SynHTMLExporter(int tabSize,const QByteArray charset); - bool createHTMLFragment() const; - void setCreateHTMLFragment(bool createHTMLFragment); - -protected: - bool mCreateHTMLFragment; -private: - PTokenAttribute mLastAttri; - QString AttriToCSS(PTokenAttribute Attri, const QString& UniqueAttriName); - bool AttriToCSSCallback(PSyntaxer Highlighter, PTokenAttribute Attri, - const QString& UniqueAttriName, QList params); - QString ColorToHTML(const QColor &AColor); - QString GetStyleName(PSyntaxer Highlighter, - PTokenAttribute Attri); - QString MakeValidName(const QString &Name); - bool StyleNameCallback(PSyntaxer Highlighter, PTokenAttribute Attri, - const QString& UniqueAttriName, QList params); - - // SynExporter interface -protected: - void FormatAttributeDone(bool BackgroundChanged, bool ForegroundChanged, FontStyles FontStylesChanged); - void FormatAttributeInit(bool BackgroundChanged, bool ForegroundChanged, FontStyles FontStylesChanged); - void FormatAfterLastAttribute(); - void FormatBeforeFirstAttribute(bool BackgroundChanged, bool ForegroundChanged, FontStyles FontStylesChanged); - void FormatNewLine(); - QString GetFooter(); - QString GetFormatName(); - QString GetHeader(); - void SetTokenAttribute(PTokenAttribute Attri); -}; -} -#endif // SYNHTMLEXPORTER_H diff --git a/libs/qsynedit/qsynedit/exporter/synrtfexporter.cpp b/libs/qsynedit/qsynedit/exporter/synrtfexporter.cpp deleted file mode 100644 index aa75940e..00000000 --- a/libs/qsynedit/qsynedit/exporter/synrtfexporter.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "synrtfexporter.h" -namespace QSynedit { - -SynRTFExporter::SynRTFExporter(const QByteArray charset):SynExporter(charset) -{ - 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 , FontStyles FontStylesChanged) -{ - // nothing to do about the color, but reset the font style - if (FontStylesChanged.testFlag(FontStyle::fsBold)) { - mAttributesChanged = true; - AddData("\\b0"); - } - if (FontStylesChanged.testFlag(FontStyle::fsItalic)) { - mAttributesChanged = true; - AddData("\\i0"); - } - if (FontStylesChanged.testFlag(FontStyle::fsUnderline)) { - mAttributesChanged = true; - AddData("\\ul0"); - } - if (FontStylesChanged.testFlag(FontStyle::fsStrikeOut)) { - mAttributesChanged = true; - AddData("\\strike0"); - } -} - -void SynRTFExporter::FormatAttributeInit(bool BackgroundChanged, bool ForegroundChanged, FontStyles 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(FontStyle::fsBold)) { - mAttributesChanged = true; - AddData("\\b0"); - } - if (FontStylesChanged.testFlag(FontStyle::fsItalic)) { - mAttributesChanged = true; - AddData("\\i0"); - } - if (FontStylesChanged.testFlag(FontStyle::fsUnderline)) { - mAttributesChanged = true; - AddData("\\ul0"); - } - if (FontStylesChanged.testFlag(FontStyle::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, FontStyles 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. - */ -#ifndef SYNRTFEXPORTER_H -#define SYNRTFEXPORTER_H - -#include "synexporter.h" - -namespace QSynedit { - -class SynRTFExporter : public SynExporter -{ -public: - explicit SynRTFExporter(const QByteArray charset); -private: - bool mAttributesChanged; - QList mListColors; - QString ColorToRTF(const QColor& AColor) const; - int GetColorIndex(const QColor& AColor); - QString GetFontTable(); - - // SynExporter interface -protected: - void FormatAttributeDone(bool BackgroundChanged, bool ForegroundChanged, FontStyles FontStylesChanged) override; - void FormatAttributeInit(bool BackgroundChanged, bool ForegroundChanged, FontStyles FontStylesChanged) override; - void FormatAfterLastAttribute() override; - void FormatBeforeFirstAttribute(bool BackgroundChanged, bool ForegroundChanged, FontStyles FontStylesChanged) override; - void FormatNewLine() override; - QString GetFooter() override; - QString GetFormatName() override; - QString GetHeader() override; -}; - -} -#endif // SYNRTFEXPORTER_H