- enhancement: Print current selection can be used in the print dialog.

- enhancement: Print syntax colored content.
  - enhancement: Correctly handle tab in the exported RTF.
This commit is contained in:
Roy Qu 2023-01-06 11:41:04 +08:00
parent 17160b7c3d
commit b01a51ab91
15 changed files with 1066 additions and 885 deletions

View File

@ -15,6 +15,8 @@ Red Panda C++ Version 2.8
- enhancement: Let encoding options in the statusbar more explicit. - enhancement: Let encoding options in the statusbar more explicit.
- fix: Crash when find occurrences in a project that has missing files. - 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 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 Red Panda C++ Version 2.7

View File

@ -31,8 +31,9 @@
#include <QMimeData> #include <QMimeData>
#include "qsynedit/syntaxer/cpp.h" #include "qsynedit/syntaxer/cpp.h"
#include "syntaxermanager.h" #include "syntaxermanager.h"
#include "qsynedit/exporter/synrtfexporter.h" #include "qsynedit/exporter/rtfexporter.h"
#include "qsynedit/exporter/synhtmlexporter.h" #include "qsynedit/exporter/htmlexporter.h"
#include "qsynedit/exporter/qtsupportedhtmlexporter.h"
#include "qsynedit/Constants.h" #include "qsynedit/Constants.h"
#include <QGuiApplication> #include <QGuiApplication>
#include <QClipboard> #include <QClipboard>
@ -1482,10 +1483,9 @@ void Editor::copyAsHTML()
{ {
if (!selAvail()) if (!selAvail())
return; return;
QSynedit::SynHTMLExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding()); QSynedit::HTMLExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding());
exporter.setTitle(QFileInfo(mFilename).fileName()); exporter.setTitle(QFileInfo(mFilename).fileName());
exporter.setExportAsText(false);
exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground()); exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground());
exporter.setFont(font()); exporter.setFont(font());
QSynedit::PSyntaxer hl = syntaxer(); QSynedit::PSyntaxer hl = syntaxer();
@ -1504,7 +1504,7 @@ void Editor::copyAsHTML()
)); ));
exporter.setCreateHTMLFragment(true); exporter.setCreateHTMLFragment(true);
exporter.ExportRange(document(),blockBegin(),blockEnd()); exporter.exportRange(document(),blockBegin(),blockEnd());
//clipboard takes the owner ship //clipboard takes the owner ship
QMimeData * mimeData = new QMimeData; QMimeData * mimeData = new QMimeData;
@ -2956,43 +2956,52 @@ void Editor::print()
dialog.setWindowTitle(tr("Print Document")); dialog.setWindowTitle(tr("Print Document"));
dialog.setOption(QAbstractPrintDialog::PrintCurrentPage,false); dialog.setOption(QAbstractPrintDialog::PrintCurrentPage,false);
dialog.setOption(QAbstractPrintDialog::PrintPageRange,false); dialog.setOption(QAbstractPrintDialog::PrintPageRange,false);
if (selAvail()) if (selAvail())
dialog.setOption(QAbstractPrintDialog::PrintSelection); dialog.setOption(QAbstractPrintDialog::PrintSelection,true);
if (dialog.exec() != QDialog::Accepted) { if (dialog.exec() != QDialog::Accepted) {
return; return;
} }
QTextDocument doc;
QStringList lst; QSynedit::QtSupportedHtmlExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding());
if (dialog.testOption(QAbstractPrintDialog::PrintSelection))
lst = textToLines(selText()); exporter.setTitle(QFileInfo(mFilename).fileName());
else exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground());
lst = contents();
for (int i=0;i<lst.length();i++) { exporter.setFont(font());
int columns = 0; QSynedit::PSyntaxer hl = syntaxer();
QString line = lst[i]; if (!pSettings->editor().copyHTMLUseEditorColor()) {
QString newLine; hl = syntaxerManager.copy(syntaxer());
for (QChar ch:line) { syntaxerManager.applyColorScheme(hl,pSettings->editor().copyHTMLColorScheme());
if (ch=='\t') {
int charCol = tabWidth() - (columns % tabWidth());
newLine += QString(charCol,' ');
columns += charCol;
} else {
newLine+=ch;
columns+=charColumns(ch);
}
}
lst[i]=newLine;
} }
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.setDefaultFont(font());
doc.setPlainText(lst.join(lineBreak())); doc.setHtml(html);
doc.print(&printer); doc.print(&printer);
} }
void Editor::exportAsRTF(const QString &rtfFilename) void Editor::exportAsRTF(const QString &rtfFilename)
{ {
QSynedit::SynRTFExporter exporter(pCharsetInfoManager->getDefaultSystemEncoding()); QSynedit::RTFExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding());
exporter.setTitle(extractFileName(rtfFilename)); exporter.setTitle(extractFileName(rtfFilename));
exporter.setExportAsText(true);
exporter.setUseBackground(pSettings->editor().copyRTFUseBackground()); exporter.setUseBackground(pSettings->editor().copyRTFUseBackground());
exporter.setFont(font()); exporter.setFont(font());
QSynedit::PSyntaxer hl = syntaxer(); QSynedit::PSyntaxer hl = syntaxer();
@ -3009,15 +3018,14 @@ void Editor::exportAsRTF(const QString &rtfFilename)
std::placeholders::_4, std::placeholders::_4,
std::placeholders::_5 std::placeholders::_5
)); ));
exporter.ExportAll(document()); exporter.exportAll(document());
exporter.SaveToFile(rtfFilename); exporter.saveToFile(rtfFilename);
} }
void Editor::exportAsHTML(const QString &htmlFilename) void Editor::exportAsHTML(const QString &htmlFilename)
{ {
QSynedit::SynHTMLExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding()); QSynedit::HTMLExporter exporter(tabWidth(), pCharsetInfoManager->getDefaultSystemEncoding());
exporter.setTitle(extractFileName(htmlFilename)); exporter.setTitle(extractFileName(htmlFilename));
exporter.setExportAsText(false);
exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground()); exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground());
exporter.setFont(font()); exporter.setFont(font());
QSynedit::PSyntaxer hl = syntaxer(); QSynedit::PSyntaxer hl = syntaxer();
@ -3034,8 +3042,8 @@ void Editor::exportAsHTML(const QString &htmlFilename)
std::placeholders::_4, std::placeholders::_4,
std::placeholders::_5 std::placeholders::_5
)); ));
exporter.ExportAll(document()); exporter.exportAll(document());
exporter.SaveToFile(htmlFilename); exporter.saveToFile(htmlFilename);
} }
void Editor::showCompletion(const QString& preWord,bool autoComplete, CodeCompletionType type) void Editor::showCompletion(const QString& preWord,bool autoComplete, CodeCompletionType type)

View File

@ -27,9 +27,10 @@ SOURCES += qsynedit/CodeFolding.cpp \
qsynedit/SynEdit.cpp \ qsynedit/SynEdit.cpp \
qsynedit/TextBuffer.cpp \ qsynedit/TextBuffer.cpp \
qsynedit/TextPainter.cpp \ qsynedit/TextPainter.cpp \
qsynedit/exporter/synexporter.cpp \ qsynedit/exporter/exporter.cpp \
qsynedit/exporter/synhtmlexporter.cpp \ qsynedit/exporter/htmlexporter.cpp \
qsynedit/exporter/synrtfexporter.cpp \ qsynedit/exporter/qtsupportedhtmlexporter.cpp \
qsynedit/exporter/rtfexporter.cpp \
qsynedit/syntaxer/asm.cpp \ qsynedit/syntaxer/asm.cpp \
qsynedit/syntaxer/cpp.cpp \ qsynedit/syntaxer/cpp.cpp \
qsynedit/syntaxer/customhighlighterv1.cpp \ qsynedit/syntaxer/customhighlighterv1.cpp \
@ -53,9 +54,10 @@ HEADERS += qsynedit/Search.h \
qsynedit/TextBuffer.h \ qsynedit/TextBuffer.h \
qsynedit/TextPainter.h \ qsynedit/TextPainter.h \
qsynedit/Types.h \ qsynedit/Types.h \
qsynedit/exporter/synexporter.h \ qsynedit/exporter/exporter.h \
qsynedit/exporter/synhtmlexporter.h \ qsynedit/exporter/htmlexporter.h \
qsynedit/exporter/synrtfexporter.h \ qsynedit/exporter/qtsupportedhtmlexporter.h \
qsynedit/exporter/rtfexporter.h \
qsynedit/syntaxer/asm.h \ qsynedit/syntaxer/asm.h \
qsynedit/syntaxer/cpp.h \ qsynedit/syntaxer/cpp.h \
qsynedit/syntaxer/customhighlighterv1.h \ qsynedit/syntaxer/customhighlighterv1.h \

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include "exporter.h"
#include <QClipboard>
#include <QFile>
#include <QGuiApplication>
#include <QMimeData>
#include <QTextCodec>
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";
}
}

View File

@ -14,8 +14,8 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef SYNEXPORTER_H #ifndef EXPORTER_H
#define SYNEXPORTER_H #define EXPORTER_H
#include <QString> #include <QString>
#include "../SynEdit.h" #include "../SynEdit.h"
@ -23,48 +23,41 @@
namespace QSynedit { namespace QSynedit {
using FormatTokenHandler = std::function<void(PSyntaxer syntaxHighlighter, int line, int column, const QString& token, using FormatTokenHandler = std::function<void(PSyntaxer syntaxHighlighter, int line, int column, const QString& token,
PTokenAttribute& attr)>; PTokenAttribute& attr)>;
class SynExporter class Exporter
{ {
public: 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 * @brief Clears the output buffer and any internal data that relates to the last
* exported text. * exported text.
*/ */
virtual void clear(); 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. * @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. * @brief Exports the given range of the strings parameter to the output buffer.
* @param ALines * @param doc
* @param Start * @param start
* @param Stop * @param stop
*/ */
void ExportRange(PDocument ALines, void exportRange(const PDocument& doc,
BufferCoord Start, BufferCoord Stop); BufferCoord start, BufferCoord stop);
/** /**
* @brief Saves the contents of the output buffer to a file. * @brief Saves the contents of the output buffer to a file.
* @param AFileName * @param AFileName
*/ */
void SaveToFile(const QString& AFileName); void saveToFile(const QString& filename);
/** /**
* @brief Saves the contents of the output buffer to a stream. * @brief Saves the contents of the output buffer to a stream.
* @param AStream * @param stream
*/ */
void SaveToStream(QIODevice& AStream); void writeToStream(QIODevice& stream);
bool exportAsText() const;
void setExportAsText(bool Value);
QFont font() const; QFont font() const;
void setFont(const QFont &font); void setFont(const QFont &font);
@ -85,7 +78,7 @@ public:
* @brief The clipboard format the exporter creates as native format. * @brief The clipboard format the exporter creates as native format.
* @return * @return
*/ */
virtual QByteArray clipboardFormat(); QByteArray clipboardFormat();
QColor foregroundColor() const; QColor foregroundColor() const;
void setForegroundColor(const QColor &value); void setForegroundColor(const QColor &value);
@ -102,15 +95,16 @@ public:
FormatTokenHandler onFormatToken() const; FormatTokenHandler onFormatToken() const;
void setOnFormatToken(const FormatTokenHandler &onFormatToken); void setOnFormatToken(const FormatTokenHandler &onFormatToken);
const QByteArray& buffer() const; QByteArray buffer() const;
const QString& text() const;
protected: protected:
int mTabSize;
QByteArray mClipboardFormat;
QByteArray mCharset; QByteArray mCharset;
QColor mBackgroundColor; QColor mBackgroundColor;
QColor mForegroundColor; QColor mForegroundColor;
QByteArray mClipboardFormat;
QString mDefaultFilter; QString mDefaultFilter;
bool mExportAsText;
QFont mFont; QFont mFont;
PSyntaxer mSyntaxer; PSyntaxer mSyntaxer;
QColor mLastBG; QColor mLastBG;
@ -125,126 +119,119 @@ protected:
/** /**
* @brief Adds a string to the output buffer. * @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. * @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. * @brief Adds a newline to the output buffer.
*/ */
void AddNewLine(); 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);
/** /**
* @brief Has to be overridden in descendant classes to add the closing format * @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 * strings to the output buffer. The parameters can be used to track what
* changes are made for the next token. * changes are made for the next token.
* @param BackgroundChanged * @param backgroundChanged
* @param ForegroundChanged * @param foregroundChanged
* @param FontStylesChanged * @param fontStyles
*/ */
virtual void FormatAttributeDone(bool BackgroundChanged, bool ForegroundChanged, virtual void formatAttributeDone(bool backgroundChanged, bool foregroundChanged,
FontStyles FontStylesChanged) = 0; FontStyles fontStyles) = 0;
/** /**
* @brief Has to be overridden in descendant classes to add the opening format * @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 * strings to the output buffer. The parameters can be used to track what
* changes have been made in respect to the previous token. * changes have been made in respect to the previous token.
* @param BackgroundChanged * @param backgroundChanged
* @param ForegroundChanged * @param foregroundChanged
* @param FontStylesChanged * @param fontStyles
*/ */
virtual void FormatAttributeInit(bool BackgroundChanged, bool ForegroundChanged, virtual void formatAttributeInit(bool backgroundChanged, bool foregroundChanged,
FontStyles FontStylesChanged) = 0; FontStyles fontStyles) = 0;
/** /**
* @brief Has to be overridden in descendant classes to add the closing format * @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. * 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 * @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. * strings to the output buffer when the first token is about to be written.
* @param BackgroundChanged * @param backgroundChanged
* @param ForegroundChanged * @param foregroundChanged
* @param FontStylesChanged * @param fontStyles
*/ */
virtual void FormatBeforeFirstAttribute(bool BackgroundChanged, bool ForegroundChanged, virtual void formatBeforeFirstAttribute(bool backgroundChanged, bool foregroundChanged,
FontStyles FontStylesChanged) = 0; FontStyles fontStyles) = 0;
/** /**
* @brief Can be overridden in descendant classes to add the formatted text of * @brief Can be overridden in descendant classes to add the formatted text of
* the actual token text to the output buffer. * 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 * @brief Has to be overridden in descendant classes to add a newline in the output
* format to the output buffer. * 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 * @brief Returns the size of the formatted text in the output buffer, to be used
* in the format header or footer. * in the format header or footer.
* @return * @return
*/ */
int GetBufferSize(); int getBufferSize() const;
/** /**
* @brief Has to be overridden in descendant classes to return the correct output * @brief Has to be overridden in descendant classes to return the correct output
* format footer. * format footer.
* @return * @return
*/ */
virtual QString GetFooter() = 0; virtual QString getFooter() = 0;
/** /**
* @brief Has to be overridden in descendant classes to return the name of the * @brief Has to be overridden in descendant classes to return the name of the
* output format. * output format.
* @return * @return
*/ */
virtual QString GetFormatName() = 0; virtual QString getFormatName() = 0;
/** /**
* @brief Has to be overridden in descendant classes to return the correct output * @brief Has to be overridden in descendant classes to return the correct output
* format header. * format header.
* @return * @return
*/ */
virtual QString GetHeader() = 0; virtual QString getHeader() = 0;
/** /**
* @brief Inserts a data block at the given position into the output buffer. Is * @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 * used to insert the format header after the exporting, since some header
* data may be known only after the conversion is done. * data may be known only after the conversion is done.
* @param APos * @param pos
* @param AText * @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 * @brief Returns a string that has all the invalid chars of the output format
* replaced with the entries in the replacement array. * 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 * @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 * of colors and font styles so the properties of the next token can be
* added to the output buffer. * 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: private:
QByteArray mBuffer; QString mText;
bool mFirstAttribute; bool mFirstAttribute;
FormatTokenHandler mOnFormatToken; FormatTokenHandler mOnFormatToken;
}; };
} }
#endif // SYNEXPORTER_H #endif // EXPORTER_H

View File

@ -14,14 +14,14 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "synhtmlexporter.h" #include "htmlexporter.h"
#include "../MiscProcs.h" #include "../MiscProcs.h"
#include <functional> #include <functional>
namespace QSynedit { namespace QSynedit {
SynHTMLExporter::SynHTMLExporter(int tabSize,const QByteArray charset): HTMLExporter::HTMLExporter(int tabSize,const QByteArray charset):
SynExporter(charset) Exporter(tabSize,charset)
{ {
mClipboardFormat = "text/html"; mClipboardFormat = "text/html";
mDefaultFilter = "HTML Documents (*.htm;*.html)|*.htm;*.html"; mDefaultFilter = "HTML Documents (*.htm;*.html)|*.htm;*.html";
@ -35,139 +35,139 @@ SynHTMLExporter::SynHTMLExporter(int tabSize,const QByteArray charset):
mCreateHTMLFragment = false; mCreateHTMLFragment = false;
} }
bool SynHTMLExporter::createHTMLFragment() const bool HTMLExporter::createHTMLFragment() const
{ {
return mCreateHTMLFragment; return mCreateHTMLFragment;
} }
void SynHTMLExporter::setCreateHTMLFragment(bool createHTMLFragment) void HTMLExporter::setCreateHTMLFragment(bool createHTMLFragment)
{ {
mCreateHTMLFragment = 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 + " { "; QString result = "." + styleName + " { ";
if (mUseBackground && Attri->background().isValid()) if (mUseBackground && attri->background().isValid())
Result += "background-color: " + ColorToHTML(Attri->background()) + "; "; result += "background-color: " + colorToHTML(attri->background()) + "; ";
if (Attri->foreground().isValid()) if (attri->foreground().isValid())
Result += "color: " + ColorToHTML(Attri->foreground()) + "; "; result += "color: " + colorToHTML(attri->foreground()) + "; ";
if (Attri->styles().testFlag(FontStyle::fsBold)) if (attri->styles().testFlag(FontStyle::fsBold))
Result += "font-weight: bold; "; result += "font-weight: bold; ";
if (Attri->styles().testFlag(FontStyle::fsItalic)) if (attri->styles().testFlag(FontStyle::fsItalic))
Result += "font-style: italic; "; result += "font-style: italic; ";
if (Attri->styles().testFlag(FontStyle::fsUnderline)) if (attri->styles().testFlag(FontStyle::fsUnderline))
Result += "text-decoration: underline; "; result += "text-decoration: underline; ";
if (Attri->styles().testFlag(FontStyle::fsStrikeOut)) if (attri->styles().testFlag(FontStyle::fsStrikeOut))
Result += "text-decoration: line-through; "; result += "text-decoration: line-through; ";
Result += "}"; result += "}";
return Result;
}
bool SynHTMLExporter::AttriToCSSCallback(PSyntaxer , PTokenAttribute Attri, const QString& UniqueAttriName, QList<void *> params)
{
QString& styles = *static_cast<QString *>(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});
return result; return result;
} }
QString SynHTMLExporter::MakeValidName(const QString &Name) bool HTMLExporter::attriToCSSCallback(PSyntaxer , PTokenAttribute attri, const QString& uniqueAttriName, QList<void *> params)
{ {
QString Result; QString& styles = *static_cast<QString *>(params[0]);
for (QChar ch:Name) { styles.append(attriToCSS(attri,uniqueAttriName) + lineBreak());
ch = ch.toLower(); return true;
if (ch == '.' || ch =='_')
Result += '-';
else if ((ch >='a' && ch <= 'z') || (ch>='0' && ch<='9') || (ch == '-'))
Result += ch;
}
return Result;
} }
bool SynHTMLExporter::StyleNameCallback(PSyntaxer /*Highlighter*/, PTokenAttribute Attri, const QString& UniqueAttriName, QList<void *> params) QString HTMLExporter::colorToHTML(const QColor &color) const
{ {
PTokenAttribute& AttriToFind = *static_cast<PTokenAttribute*>(params[0]); return color.name();
QString& StyleName = *static_cast<QString *>(params[1]); }
if (Attri == AttriToFind) { QString HTMLExporter::getStyleName(PSyntaxer syntaxer, PTokenAttribute attri)
StyleName.clear(); {
StyleName.append(MakeValidName(UniqueAttriName)); 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<void *> params)
{
PTokenAttribute& attriToFind = *static_cast<PTokenAttribute*>(params[0]);
QString& styleName = *static_cast<QString *>(params[1]);
if (attri == attriToFind) {
styleName.clear();
styleName.append(makeValidName(uniqueAttriName));
return false; return false;
} }
return true; return true;
} }
void SynHTMLExporter::FormatAttributeDone(bool , bool , FontStyles ) void HTMLExporter::formatAttributeDone(bool , bool , FontStyles )
{ {
AddData("</span>"); addData("</span>");
} }
void SynHTMLExporter::FormatAttributeInit(bool , bool , FontStyles ) void HTMLExporter::formatAttributeInit(bool , bool , FontStyles )
{ {
QString StyleName = GetStyleName(mSyntaxer, mLastAttri); QString styleName = getStyleName(mSyntaxer, mLastAttri);
AddData(QString("<span class=\"%1\">").arg(StyleName)); addData(QString("<span class=\"%1\">").arg(styleName));
} }
void SynHTMLExporter::FormatAfterLastAttribute() void HTMLExporter::formatAfterLastAttribute()
{ {
AddData("</span>"); addData("</span>");
} }
void SynHTMLExporter::FormatBeforeFirstAttribute(bool, bool, FontStyles) void HTMLExporter::formatBeforeFirstAttribute(bool, bool, FontStyles)
{ {
QString StyleName = GetStyleName(mSyntaxer, mLastAttri); QString styleName = getStyleName(mSyntaxer, mLastAttri);
AddData(QString("<span class=\"%1\">").arg(StyleName)); addData(QString("<span class=\"%1\">").arg(styleName));
} }
void SynHTMLExporter::FormatNewLine() void HTMLExporter::formatNewLine()
{ {
AddData("<br />"); addData("<br />");
AddNewLine(); addNewLine();
} }
QString SynHTMLExporter::GetFooter() QString HTMLExporter::getFooter()
{ {
QString Result = ""; QString result = "";
Result = "</span>" + lineBreak(); result = "</div>" + lineBreak();
if (mCreateHTMLFragment) if (mCreateHTMLFragment)
Result += "<!--EndFragment-->"; result += "<!--EndFragment-->";
Result += "</body>"+lineBreak()+ "</html>"; result += "</body>"+lineBreak()+ "</html>";
return Result; return result;
} }
QString SynHTMLExporter::GetFormatName() QString HTMLExporter::getFormatName()
{ {
return "HTML"; return "HTML";
} }
QString SynHTMLExporter::GetHeader() QString HTMLExporter::getHeader()
{ {
using namespace std::placeholders; using namespace std::placeholders;
QString Styles; QString styles;
enumTokenAttributes(mSyntaxer, true, enumTokenAttributes(mSyntaxer, true,
std::bind(&SynHTMLExporter::AttriToCSSCallback, std::bind(&HTMLExporter::attriToCSSCallback,
this, _1, _2, _3, _4), this, _1, _2, _3, _4),
{&Styles}); {&styles});
QString HTMLAsTextHeader = "<?xml version=\"1.0\" encoding=\"%2\"?>"+lineBreak() + QString HTMLAsTextHeader = "<?xml version=\"1.0\" encoding=\"%2\"?>"+lineBreak() +
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" + lineBreak() + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" + lineBreak() +
@ -184,12 +184,12 @@ QString SynHTMLExporter::GetHeader()
"</style>" + lineBreak() + "</style>" + lineBreak() +
"</head>" + lineBreak() + "</head>" + lineBreak() +
"<body>" + lineBreak(); "<body>" + lineBreak();
QString Header = HTMLAsTextHeader QString header = HTMLAsTextHeader
.arg(mTitle) .arg(mTitle)
.arg(QString(mCharset)) .arg(QString(mCharset))
.arg(ColorToHTML(mForegroundColor)) .arg(colorToHTML(mForegroundColor))
.arg(ColorToHTML(mBackgroundColor)) .arg(colorToHTML(mBackgroundColor))
.arg(Styles); .arg(styles);
if (mCreateHTMLFragment) { if (mCreateHTMLFragment) {
HTMLAsTextHeader = "<?xml version=\"1.0\" encoding=\"%2\"?>"+lineBreak() + HTMLAsTextHeader = "<?xml version=\"1.0\" encoding=\"%2\"?>"+lineBreak() +
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" + lineBreak() + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" + lineBreak() +
@ -205,26 +205,26 @@ QString SynHTMLExporter::GetHeader()
"</style>" + lineBreak() + "</style>" + lineBreak() +
"</head>" + lineBreak() + "</head>" + lineBreak() +
"<body>" + lineBreak(); "<body>" + lineBreak();
Header = HTMLAsTextHeader header = HTMLAsTextHeader
.arg(QString(mCharset)) .arg(QString(mCharset))
.arg(ColorToHTML(mForegroundColor)) .arg(colorToHTML(mForegroundColor))
.arg(ColorToHTML(mBackgroundColor)) .arg(colorToHTML(mBackgroundColor))
.arg(Styles); .arg(styles);
} }
QString Result = Header; QString result = header;
if (mCreateHTMLFragment) { if (mCreateHTMLFragment) {
Result += "<!--StartFragment-->"; result += "<!--StartFragment-->";
} }
Result += QString("<span style=\"font: %1pt %2;\">") result += QString("<div style=\"font: %1pt %2;\">")
.arg(pixelToPoint(mFont.pixelSize())) .arg(pixelToPoint(mFont.pixelSize()))
.arg(mFont.family()); .arg(mFont.family());
return Result; return result;
} }
void SynHTMLExporter::SetTokenAttribute(PTokenAttribute Attri) void HTMLExporter::setTokenAttribute(PTokenAttribute attri)
{ {
mLastAttri = Attri; mLastAttri = attri;
SynExporter::SetTokenAttribute(Attri); Exporter::setTokenAttribute(attri);
} }
} }

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#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<void *> 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<void *> 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

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include "qtsupportedhtmlexporter.h"
#include "../MiscProcs.h"
#include <functional>
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['&'] = "&amp;";
mReplaceReserved['<'] = "&lt;";
mReplaceReserved['>'] = "&gt;";
mReplaceReserved['"'] = "&quot;";
mReplaceReserved[' '] = "&nbsp;";
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("</span>");
}
void QtSupportedHtmlExporter::formatAttributeInit(bool , bool , FontStyles )
{
addData(QString("<span style=\"%1\">").arg(attriToCSS(mLastAttri)));
}
void QtSupportedHtmlExporter::formatAfterLastAttribute()
{
addData("</span>");
}
void QtSupportedHtmlExporter::formatBeforeFirstAttribute(bool, bool, FontStyles)
{
addData(QString("<span style=\"%1\">").arg(attriToCSS(mLastAttri)));
}
void QtSupportedHtmlExporter::formatNewLine()
{
addData("<br />");
addNewLine();
}
QString QtSupportedHtmlExporter::getFooter()
{
QString result = "";
result = "</div>" + lineBreak();
if (mCreateHTMLFragment)
result += "<!--EndFragment-->";
result += "</body>"+lineBreak()+ "</html>";
return result;
}
QString QtSupportedHtmlExporter::getFormatName()
{
return "HTML";
}
QString QtSupportedHtmlExporter::getHeader()
{
using namespace std::placeholders;
QString styles;
QString HTMLAsTextHeader = "<?xml version=\"1.0\" encoding=\"%2\"?>"+lineBreak() +
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" + lineBreak() +
"<html xmlns=\"http://www.w3.org/1999/xhtml\">" + lineBreak() +
"<head>"+ lineBreak() +
"<title>%1</title>" + lineBreak() +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%2\" />" + lineBreak() +
"<meta name=\"generator\" content=\"QSynEdit HTML exporter\" />" + lineBreak() +
"</head>" + lineBreak() +
"<body>" + lineBreak();
QString header = HTMLAsTextHeader
.arg(mTitle)
.arg(QString(mCharset));
if (mCreateHTMLFragment) {
HTMLAsTextHeader = "<?xml version=\"1.0\" encoding=\"%2\"?>"+lineBreak() +
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" + lineBreak() +
"<html xmlns=\"http://www.w3.org/1999/xhtml\">" + lineBreak() +
"<head>"+ lineBreak() +
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%1\" />" + lineBreak() +
"<meta name=\"generator\" content=\"QSynEdit HTML exporter\" />" + lineBreak() +
"</head>" + lineBreak() +
"<body>" + lineBreak();
header = HTMLAsTextHeader
.arg(QString(mCharset));
}
QString result = header;
if (mCreateHTMLFragment) {
result += "<!--StartFragment-->"+lineBreak();
}
if (mUseBackground) {
result += QString("<div style=\"color: %1; background-color: %2; font: %3pt %4;\">")
.arg(colorToHTML(mForegroundColor))
.arg(colorToHTML(mBackgroundColor))
.arg(pixelToPoint(mFont.pixelSize()))
.arg(mFont.family())+lineBreak();
} else {
result += QString("<div style=\"color: %1; font: %2pt %3;\">")
.arg(colorToHTML(mForegroundColor))
.arg(pixelToPoint(mFont.pixelSize()))
.arg(mFont.family())+lineBreak();
}
return result;
}
void QtSupportedHtmlExporter::setTokenAttribute(PTokenAttribute Attri)
{
mLastAttri = Attri;
Exporter::setTokenAttribute(Attri);
}
}

View File

@ -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

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#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<mListColors.count();i++) {
result = result + colorToRTF(mListColors[i]);
}
result = result + colorToRTF(mBackgroundColor);
result = result + "}" + lineBreak();
// title and creator comment
result = result + "{\\info{\\comment Generated by the QSynEdit RTF " +
"exporter}" + lineBreak();
result = result + "{\\title " + mTitle + "}}" + lineBreak();
// if (mUseBackground)
// Result = Result + { TODO } #13#10;
result = result + QString("\\deflang1033\\pard\\plain\\f0\\fs%1 ").arg((int)(2 * pixelToPoint(mFont.pixelSize())));
if (mUseBackground)
result = result + QString("\\chshdng0\\chcbpat%1\\cb%2\\highlight%3 ")
.arg(getColorIndex(mLastBG))
.arg(getColorIndex(mBackgroundColor))
.arg(getColorIndex(mBackgroundColor));
return result;
}
}

View File

@ -0,0 +1,48 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
#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<QColor> 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

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#include "synexporter.h"
#include <QClipboard>
#include <QFile>
#include <QGuiApplication>
#include <QMimeData>
#include <QTextCodec>
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";
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#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<void *> 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<void *> 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

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#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<mListColors.count();i++) {
Result = Result + ColorToRTF(mListColors[i]);
}
Result = Result + ColorToRTF(mBackgroundColor);
Result = Result + "}" + lineBreak();
// title and creator comment
Result = Result + "{\\info{\\comment Generated by the QSynEdit RTF " +
"exporter}" + lineBreak();
Result = Result + "{\\title " + mTitle + "}}" + lineBreak();
// if (mUseBackground)
// Result = Result + { TODO } #13#10;
Result = Result + QString("\\deflang1033\\pard\\plain\\f0\\fs%1 ").arg((int)(2 * pixelToPoint(mFont.pixelSize())));
if (mUseBackground)
Result = Result + QString("\\chshdng0\\chcbpat%1\\cb%2\\highlight%3 ")
.arg(GetColorIndex(mLastBG))
.arg(GetColorIndex(mBackgroundColor))
.arg(GetColorIndex(mBackgroundColor));
return Result;
}
}

View File

@ -1,48 +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 <https://www.gnu.org/licenses/>.
*/
#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<QColor> 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