Fixed incorrect white-space between words.

This commit is contained in:
Vincent Richard 2007-11-20 21:45:54 +00:00
parent 6cafb90c08
commit a87652e7b4
5 changed files with 63 additions and 7 deletions

View File

@ -2,6 +2,10 @@
VERSION 0.8.2cvs
================
2007-11-20 Vincent Richard <vincent@vincent-richard.net>
* text, word: fixed incorrect white-space between words.
2007-07-09 Vincent Richard <vincent@vincent-richard.net>
* IMAPUtils.cpp: fixed bug in modified UTF-7 encoding (IMAP).

View File

@ -335,11 +335,12 @@ void text::encodeAndFold(utility::outputStream& os, const string::size_type maxL
const string::size_type firstLineOffset, string::size_type* lastLineLength, const int flags) const
{
string::size_type curLineLength = firstLineOffset;
word::generatorState state;
for (int wi = 0 ; wi < getWordCount() ; ++wi)
{
getWordAt(wi)->generate(os, maxLineLength, curLineLength,
&curLineLength, flags, (wi == 0));
&curLineLength, flags, &state);
}
if (lastLineLength)

View File

@ -309,16 +309,21 @@ void word::parse(const string& buffer, const string::size_type position,
void word::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
generate(os, maxLineLength, curLinePos, newLinePos, 0, true);
generate(os, maxLineLength, curLinePos, newLinePos, 0, NULL);
}
void word::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos, const int flags,
const bool isFirstWord) const
generatorState* state) const
{
string::size_type curLineLength = curLinePos;
generatorState defaultGeneratorState;
if (state == NULL)
state = &defaultGeneratorState;
// Calculate the number of ASCII chars to check whether encoding is needed
// and _which_ encoding to use.
const string::size_type asciiCount =
@ -374,7 +379,7 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe
// we write the full line no matter of the max line length...
if (!newLine && p != end && lastWSpos == end &&
!isFirstWord && curLineStart == m_buffer.begin())
!state->isFirstWord && curLineStart == m_buffer.begin())
{
// Here, we are continuing on the line of previous encoded
// word, but there is not even enough space to put the
@ -428,7 +433,7 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe
// last white-space.
#if 1
if (curLineLength != 1 && !isFirstWord)
if (curLineLength != NEW_LINE_SEQUENCE_LENGTH && !state->isFirstWord && state->prevWordIsEncoded)
os << " "; // Separate from previous word
#endif
@ -521,7 +526,7 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe
}
// Encode and fold input buffer
if (curLineLength != 1 && !isFirstWord)
if (!startNewLine && !state->isFirstWord && state->prevWordIsEncoded)
{
os << " "; // Separate from previous word
++curLineLength;
@ -554,11 +559,15 @@ void word::generate(utility::outputStream& os, const string::size_type maxLineLe
// End of the encoded word
os << wordEnd;
state->prevWordIsEncoded = true;
}
}
if (newLinePos)
*newLinePos = curLineLength;
state->isFirstWord = false;
}

View File

@ -41,6 +41,7 @@ VMIME_TEST_SUITE_BEGIN
VMIME_TEST(testWordConstructors)
VMIME_TEST(testWordParse)
VMIME_TEST(testWordGenerate)
VMIME_TEST(testWordGenerateSpace)
VMIME_TEST(testWordGenerateMultiBytes)
VMIME_TEST_LIST_END
@ -269,6 +270,31 @@ VMIME_TEST_SUITE_BEGIN
vmime::word("\xf1\xf2\xf3\xf4\xf5", vmime::charset("foo")).generate());
}
void testWordGenerateSpace()
{
// No white-space between an unencoded word and a encoded one
VASSERT_EQ("1", "Bonjour =?utf-8?Q?Fran=C3=A7ois?=",
vmime::text::newFromString("Bonjour Fran\xc3\xa7ois",
vmime::charset("utf-8"))->generate());
// White-space between two encoded words
vmime::text txt;
txt.appendWord(vmime::create <vmime::word>("\xc3\x89t\xc3\xa9", "utf-8"));
txt.appendWord(vmime::create <vmime::word>("Fran\xc3\xa7ois", "utf-8"));
const vmime::string decoded = "\xc3\x89t\xc3\xa9""Fran\xc3\xa7ois";
const vmime::string encoded = "=?utf-8?B?w4l0w6k=?= =?utf-8?Q?Fran=C3=A7ois?=";
// -- test encoding
VASSERT_EQ("2", encoded, txt.generate());
// -- ensure no space is added when decoding
vmime::text txt2;
txt2.parse(encoded, 0, encoded.length());
VASSERT_EQ("3", decoded, txt2.getWholeBuffer());
}
void testWordGenerateMultiBytes()
{
// Ensure we don't encode a non-integral number of characters

View File

@ -109,13 +109,29 @@ public:
ref <component> clone() const;
#ifndef VMIME_BUILDING_DOC
class generatorState
{
public:
generatorState()
: isFirstWord(true), prevWordIsEncoded(false)
{
}
bool isFirstWord;
bool prevWordIsEncoded;
};
#endif
using component::parse;
using component::generate;
void parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition = NULL);
void generate(utility::outputStream& os, const string::size_type maxLineLength = lineLengthLimits::infinite, const string::size_type curLinePos = 0, string::size_type* newLinePos = NULL) const;
void generate(utility::outputStream& os, const string::size_type maxLineLength, const string::size_type curLinePos, string::size_type* newLinePos, const int flags, const bool isFirstWord) const;
void generate(utility::outputStream& os, const string::size_type maxLineLength, const string::size_type curLinePos, string::size_type* newLinePos, const int flags, generatorState* state) const;
const std::vector <ref <const component> > getChildComponents() const;