Skip to content

Commit

Permalink
Changed way word-wrapping works to allow for Chinese characters
Browse files Browse the repository at this point in the history
  • Loading branch information
nickgammon committed Mar 24, 2018
1 parent fa61212 commit 2ff6873
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 28 deletions.
1 change: 0 additions & 1 deletion Line.cpp
Expand Up @@ -34,7 +34,6 @@ CLine::CLine (const long nLineNumber,
{
hard_return = false;
len = 0;
last_space = -1;
m_iPreambleOffset = 0;
m_theTime = CTime::GetCurrentTime();
QueryPerformanceCounter (&m_lineHighPerformanceTime);
Expand Down
1 change: 0 additions & 1 deletion OtherTypes.h
Expand Up @@ -322,7 +322,6 @@ class CLine : public CObject
bool hard_return;
unsigned char flags;
int len;
int last_space;
char * text; // allocated as necessary and then resized
CStyleList styleList; // list of styles applying to text, see above
CTime m_theTime; // time this line arrived
Expand Down
14 changes: 14 additions & 0 deletions Utilities.cpp
Expand Up @@ -3441,3 +3441,17 @@ const char * p = sName;

return true;
} // end of IsSubName

// find the last occurrence of c in the string s, maximum length count
const char *strnrchr(const char *s, const char c, size_t count)
{
const char * ret = NULL;
size_t n = 0;
while (*s && n < count++)
{
if( *s == c )
ret = s; // remember where character is, keep searching
s++;
}
return ret;
} // end of strnrchr
8 changes: 7 additions & 1 deletion dialogs/TextAttributesDlg.cpp
Expand Up @@ -113,9 +113,15 @@ void CTextAttributesDlg::OnLineInfo()
YES_OR_NO (m_pLine->flags & BOOKMARK)
));

// work out where the last space is
const char * space = strnrchr(m_pLine->text, ' ', m_pLine->len);
int last_space = -1;
if (space)
last_space = space - m_pLine->text;

INFO (TFormat (" Length = %i, last space = %i",
m_pLine->len,
m_pLine->last_space));
last_space));

CString strText = CString (m_pLine->text, m_pLine->len);

Expand Down
57 changes: 32 additions & 25 deletions doc.cpp
Expand Up @@ -1627,57 +1627,56 @@ Unicode range UTF-8 bytes
(m_pCurrentLine->len >= m_pCurrentLine->iMemoryAllocated)) // emergency bail-out
{

int last_space = -1;

// do auto line wrapping here

// first see if we can split at a multibyte character if no space was found
// see if we can split at a multibyte character

if (m_pCurrentLine->last_space < 0 && // no space found
(m_pCurrentLine->len - m_pCurrentLine->last_space) >= m_nWrapColumn &&
if (m_pCurrentLine->len >= m_nWrapColumn &&
m_pCurrentLine->len >= 10 &&
!m_bUTF_8) // not for UTF-8
{
int multibyte_start = -1;
for (int i = 0; i < m_pCurrentLine->len - 1; i++)
{
unsigned char c1 = m_pCurrentLine->text [i];
unsigned char c2 = m_pCurrentLine->text [i + 1];
if (c1 >= 0x81 && c1 <= 0xFE && // first Big5 character
((c2 >= 0x40 && c2 <= 0x7E) || (c2 >= 0xA1 && c2 <= 0xFE))) // second Big5 character
multibyte_start = i++; // remember position, jump the second byte
else if (c1 >= 0xA1 && c1 <= 0xF7 && c2 >= 0xA1 && c2 <= 0xFE) // GB2132
multibyte_start = i++; // remember position, jump the second byte
else if (c1 <= 0x7F)
multibyte_start = i; // we can split after any ordinary character
((c2 >= 0x40 && c2 <= 0x7E) || (c2 >= 0xA1 && c2 <= 0xFE))) // second Big5 character
last_space = i++; // remember position, skip the second byte
else if (c1 >= 0xA1 && c1 <= 0xF7 &&
c2 >= 0xA1 && c2 <= 0xFE) // GB2132
last_space = i++; // remember position, skip the second byte
else if (c1 == ' ' && m_wrap)
last_space = i; // or split at a space
}

m_pCurrentLine->last_space = multibyte_start;
} // end of checking for a Big5 or GB2132 break point

if (!m_wrap ||
m_pCurrentLine->last_space < 0 ||
(m_pCurrentLine->len - m_pCurrentLine->last_space) >= m_nWrapColumn)
last_space < 0 ||
(m_pCurrentLine->len - last_space) >= m_nWrapColumn)
StartNewLine_KeepPreviousStyle (flags);
else
{
saved_count = m_pCurrentLine->len -
m_pCurrentLine->last_space;
saved_count = m_pCurrentLine->len - last_space;

// note - saved_count should not be zero because length is 1-relative
// (eg. 1) and last_space is zero-relative (eg. 0)
if (!m_indent_paras)
{
saved_count--; // one less to copy
m_pCurrentLine->last_space++; // one more on this line (the space)
m_pCurrentLine->len = m_pCurrentLine->last_space; // this line is longer
last_space++; // one more on this line (the space)
m_pCurrentLine->len = last_space; // this line is longer
} // end of indenting not wanted

// saved_count might be zero now, because of no indenting
if (saved_count > 0)
{
// save portion of text destined for new line
CString strText = CString (&m_pCurrentLine->text [m_pCurrentLine->last_space],
CString strText = CString (&m_pCurrentLine->text [last_space],
saved_count);
m_pCurrentLine->len = m_pCurrentLine->last_space;
m_pCurrentLine->len = last_space;

CLine * pPreviousLine = m_pCurrentLine; // remember this line

Expand Down Expand Up @@ -1744,9 +1743,6 @@ Unicode range UTF-8 bytes

} // end of line wrapping wanted and possible
} // end of line being full
else
if (c == ' ')
m_pCurrentLine->last_space = m_pCurrentLine->len;

ASSERT (m_pCurrentLine->text);

Expand Down Expand Up @@ -2189,9 +2185,15 @@ CString strLine (lpszText, size);
} // end of \n\n
else
{
// work out where the last space is
const char * space = strnrchr(m_pCurrentLine->text, ' ', m_pCurrentLine->len);
int last_space = -1;
if (space)
last_space = space - m_pCurrentLine->text;

// don't run words together - if a newline follows a word,
// insert a space
if (m_pCurrentLine->last_space != (m_pCurrentLine->len - 1))
if (last_space != (m_pCurrentLine->len - 1))
{
if (m_cLastChar == '.' && m_pCurrentLine->len < m_nWrapColumn)
AddToLine (" ", flags); // two spaces after period
Expand Down Expand Up @@ -2237,7 +2239,6 @@ CString strLine (lpszText, size);

m_pCurrentLine->hard_return = false;
m_pCurrentLine->len = 0;
m_pCurrentLine->last_space = -1;

} // end of letting a \r delete line contents

Expand All @@ -2254,8 +2255,14 @@ CString strLine (lpszText, size);
case ' ': // space
if (m_bInParagraph && !(flags & NOTE_OR_COMMAND)) // for <P>
{
// work out where the last space is
const char * space = strnrchr(m_pCurrentLine->text, ' ', m_pCurrentLine->len);
int last_space = -1;
if (space)
last_space = space - m_pCurrentLine->text;

// multiple consecutive spaces - discard extras
if (m_pCurrentLine->last_space == (m_pCurrentLine->len - 1))
if (last_space == (m_pCurrentLine->len - 1))
{
if (m_cLastChar != '\n')
m_cLastChar = c; // remember it
Expand Down
1 change: 1 addition & 0 deletions stdafx.h
Expand Up @@ -869,6 +869,7 @@ convenient for user programs that want to test its value. */
#define DEBUG_PLUGIN_ID "138a692642ab4f9e7a1af63b" // special plugin ID for Debug "summary"
bool IsPluginID (const char * sID);
bool IsSubName (const char * sName);
const char *strnrchr(const char *s, const char c, size_t count);

typedef struct
{
Expand Down

0 comments on commit 2ff6873

Please sign in to comment.