From 70c2c0f7a27f6a83a840ca5f570a9e2424cbff66 Mon Sep 17 00:00:00 2001 From: rion Date: Tue, 15 Oct 2013 00:32:17 +0600 Subject: [PATCH] Two new options for QxtMailMessage: word wrap limit and preserve start spaces word wrap limit sets maximum line length before it will be wrapped to next line. default is 78 but for some clients it may be less (ex: thunderbird). so if you are going to generate *.eml setWordWrapLimit will be helpful. preserve start spaces controls start of wrapped line. so if your very long line starts with 4 spaces then wrapped part will start also with 4 spaces 0 if this feature is disabled. --- src/network/qxtmailmessage.cpp | 125 ++++++++++++++++++--------------- src/network/qxtmailmessage.h | 3 + 2 files changed, 70 insertions(+), 58 deletions(-) diff --git a/src/network/qxtmailmessage.cpp b/src/network/qxtmailmessage.cpp index 78d31163..b41f0033 100644 --- a/src/network/qxtmailmessage.cpp +++ b/src/network/qxtmailmessage.cpp @@ -54,12 +54,15 @@ struct QxtMailMessagePrivate : public QSharedData QxtMailMessagePrivate(const QxtMailMessagePrivate& other) : QSharedData(other), rcptTo(other.rcptTo), rcptCc(other.rcptCc), rcptBcc(other.rcptBcc), subject(other.subject), body(other.body), sender(other.sender), - extraHeaders(other.extraHeaders), attachments(other.attachments) {} + extraHeaders(other.extraHeaders), attachments(other.attachments), + wordWrapLimit(78), preserveStartSpaces(false) {} QStringList rcptTo, rcptCc, rcptBcc; QString subject, body, sender; QHash extraHeaders; QHash attachments; mutable QByteArray boundary; + int wordWrapLimit; + bool preserveStartSpaces; }; class QxtRfc2822Parser @@ -243,6 +246,25 @@ void QxtMailMessage::removeAttachment(const QString& filename) qxt_d->attachments.remove(filename); } +/*! + * \brief Rewrites default 78 word wrap line length limit with new \a limit + */ +void QxtMailMessage::setWordWrapLimit(int limit) +{ + qxt_d->wordWrapLimit = limit; +} + +/*! + * \brief Forces wrapped line to have the same indent as original. + * + * Ex: If your very long line starts with 4 sp. then wrapped part + * will start with 4 sp too when this feature enabled + */ +void QxtMailMessage::setWordWrapPreserveStartSpaces(bool state) +{ + qxt_d->preserveStartSpaces = state; +} + QByteArray qxt_fold_mime_header(const QString& key, const QString& value, QTextCodec* latin1, const QByteArray& prefix) { QByteArray rv = ""; @@ -443,72 +465,59 @@ QByteArray QxtMailMessage::rfc2822() const { QByteArray b = latin1->fromUnicode(body()); int len = b.length(); - QByteArray line = ""; - QByteArray word = ""; - for (int i = 0; i < len; i++) + QByteArray line; + QByteArray word; + QByteArray spaces; + QByteArray startSpaces; + for (int i = 0; i <= len; i++) { - if (b[i] == '\n' || b[i] == '\r') - { - if (line.isEmpty()) - { - line = word; - word = ""; - } - else if (line.length() + word.length() + 1 <= 78) - { - line = line + ' ' + word; - word = ""; - } - if(line[0] == '.') - rv += "."; - rv += line + "\r\n"; - if ((b[i+1] == '\n' || b[i+1] == '\r') && b[i] != b[i+1]) - { - // If we're looking at a CRLF pair, skip the second half - i++; - } - line = word; + char ignoredChar = 0; + if (i != len) { + ignoredChar = b[i] == '\n'? '\r' : b[i] == '\r'? '\n' : 0; } - else if (b[i] == ' ') - { - if (line.length() + word.length() + 1 > 78) - { + if (!(ignoredChar || (i == len) || (b[i] == ' ') || (b[i] == '\t'))) { + // the char is part of word + if (word.isEmpty()) { // start of new word / end of spaces + if (line.isEmpty()) { + startSpaces = spaces; + } + } + word += b[i]; + continue; + } + + // space char, so end of word or continuous spaces + if (!word.isEmpty()) { // start of new space area / end of word + if (line.length() + spaces.length() + + word.length() > qxt_d->wordWrapLimit) { + // have to wrap word to next line if(line[0] == '.') rv += "."; rv += line + "\r\n"; - line = word; + if (qxt_d->preserveStartSpaces) { + line = startSpaces + word; + } else { + line = word; + } + } else { // no wrap required + line += spaces + word; } - else if (line.isEmpty()) - { - line = word; - } - else - { - line = line + ' ' + word; - } - word = ""; + word.clear(); + spaces.clear(); } - else - { - word += b[i]; + + if (ignoredChar || i == len) { // new line or eof + // trailing `spaces` are ignored here + if(line[0] == '.') + rv += "."; + rv += line + "\r\n"; + line.clear(); + startSpaces.clear(); + spaces.clear(); + } else { + spaces += b[i]; } } - if (line.length() + word.length() + 1 > 78) - { - if(line[0] == '.') - rv += "."; - rv += line + "\r\n"; - line = word; - } - else if (!word.isEmpty()) - { - line += ' ' + word; - } - if(!line.isEmpty()) { - if(line[0] == '.') - rv += "."; - rv += line + "\r\n"; - } } else if (useQuotedPrintable) { diff --git a/src/network/qxtmailmessage.h b/src/network/qxtmailmessage.h index 7abcb724..5af370ee 100644 --- a/src/network/qxtmailmessage.h +++ b/src/network/qxtmailmessage.h @@ -82,6 +82,9 @@ public: void addAttachment(const QString& filename, const QxtMailAttachment& attach); void removeAttachment(const QString& filename); + void setWordWrapLimit(int limit); + void setWordWrapPreserveStartSpaces(bool state); + QByteArray rfc2822() const; static QxtMailMessage fromRfc2822(const QByteArray&);