From 27f3cd0c7acce053781de69caef4c1929a712412 Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 30 Jul 2017 17:32:35 +0000 Subject: [PATCH] CtrlLib: TextCtrl now splits long lines git-svn-id: svn://ultimatepp.org/upp/trunk@11277 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/CtrlLib/Text.cpp | 135 ++++++++++++++------------------------ uppsrc/CtrlLib/TextEdit.h | 7 +- 2 files changed, 54 insertions(+), 88 deletions(-) diff --git a/uppsrc/CtrlLib/Text.cpp b/uppsrc/CtrlLib/Text.cpp index 1785a8da8..776f3eef2 100644 --- a/uppsrc/CtrlLib/Text.cpp +++ b/uppsrc/CtrlLib/Text.cpp @@ -35,6 +35,7 @@ TextCtrl::TextCtrl() max_total = 200 * 1024 * 1024; #endif #endif + max_line_len = 100000; truncated = false; } @@ -161,17 +162,20 @@ int TextCtrl::Load(Stream& in, byte charset) { cr = true; else if(c == '\n') { + truncate_line: WString l = wln; line.Add(l); total += l.GetCount() + 1; wln.Clear(); } - else + else { wln.Cat(c); + if(wln.GetCount() >= max_line_len) + goto truncate_line; + } } } else - if(charset == CHARSET_UTF8) for(;;) { byte h[200]; int size; @@ -185,105 +189,65 @@ int TextCtrl::Load(Stream& in, byte charset) { const byte *e = s + size; while(s < e) { const byte *b = s; + const byte *ee = s + min(e - s, max_line_len - ln.GetCount()); { - LTIMING("ChkLoop UTF8"); - while(s < e && (*s >= ' ' || *s == '\t')) { + while(s < ee && *s != '\r' && *s != '\n') { b8 |= *s++; - while(s < e && *s >= ' ' && *s < 128) // Interestingly, this speeds things up + while(s < ee && *s >= ' ' && *s < 128) // Interestingly, this speeds things up s++; - while(s < e && *s >= ' ') + while(s < ee && *s >= ' ') b8 |= *s++; } } if(b < s) { - LTIMING("ln.Cat"); - if(b - s + ln.GetCount() > max_total) - break; - ln.Cat((const char *)b, (const char *)s); + if(s - b + ln.GetCount() > max_total) + ln.Cat((const char *)b, max_total - ln.GetCount()); + else + ln.Cat((const char *)b, (const char *)s); } - if(s < e) { - if(*s == '\r') - cr = true; - if(*s == '\n') { - LTIMING("ADD"); - int len = (b8 & 0x80) ? utf8len(~ln, ln.GetCount()) : ln.GetCount(); - if(total + len + 1 > max_total) { - truncated = true; - goto out_of_limit; - } - total += len + 1; - Ln& l = line.Add(); - l.len = len; + while(ln.GetCount() >= max_line_len) { + int ei = max_line_len; + if(charset == CHARSET_UTF8) + while(ei > 0 && ei > max_line_len - 6 && !((byte)ln[ei] < 128 || IsUtf8Lead((byte)ln[ei]))) // break line at whole utf8 codepoint if possible + ei--; + String nln(~ln + ei, ln.GetCount() - ei); + ln.SetCount(ei); + int len = charset == CHARSET_UTF8 && (b8 & 0x80) ? utf8len(~ln, ln.GetCount()) : ln.GetCount(); + truncated = true; + if(total + len + 1 >= max_total) + goto out_of_limit; + total += len + 1; + Ln& l = line.Add(); + l.len = len; + if(charset == CHARSET_UTF8) l.text = ln; - ln.Clear(); - b8 = 0; - b = s; + else { + String h = ln; + l.text = ToCharset(CHARSET_UTF8, h, charset); } + ln = nln; + } + if(s < e && *s == '\r') { s++; + cr = true; } - } - } - else - for(;;) { - byte h[200]; - int size; - const byte *s = in.GetSzPtr(size); - if(size == 0) { - size = in.Get(h, 200); - s = h; - if(size == 0) - break; - } - const byte *e = s + size; - while(s < e) { - const byte *b = s; - { - LTIMING("ChkLoop"); - while(s < e && (*s >= ' ' || *s == '\t')) { - b8 |= *s++; - while(s < e && *s >= ' ' && *s < 128) // Interestingly, this speeds things up - s++; - while(s < e && *s >= ' ') - b8 |= *s++; - } - } - if(b < s) { - LTIMING("ln.Cat"); - if(b - s + ln.GetCount() > max_total) { + if(s < e && *s == '\n') { + int len = charset == CHARSET_UTF8 && (b8 & 0x80) ? utf8len(~ln, ln.GetCount()) : ln.GetCount(); + if(total + len + 1 > max_total) { truncated = true; goto out_of_limit; } - ln.Cat((const char *)b, (const char *)s); - } - if(s < e) { - if(*s == '\r') - cr = true; - if(*s == '\n') { - if(b8 & 128) { - LTIMING("ToUnicode"); - WString w = ToUnicode(~ln, ln.GetCount(), charset); - if(total + w.GetLength() + 1 > max_total) { - truncated = true; - goto out_of_limit; - } - line.Add(w); - total += w.GetLength() + 1; - } - else { - LTIMING("ADD"); - if(total + ln.GetCount() + 1 > max_total) { - truncated = true; - goto out_of_limit; - } - total += ln.GetCount() + 1; - Ln& l = line.Add(); - l.len = ln.GetCount(); - l.text = ln; - } - ln.Clear(); - b8 = 0; - b = s; + total += len + 1; + Ln& l = line.Add(); + l.len = len; + if(charset == CHARSET_UTF8) + l.text = ln; + else { + String h = ln; + l.text = ToCharset(CHARSET_UTF8, h, charset); } + ln.Clear(); + b8 = 0; s++; } } @@ -292,6 +256,7 @@ int TextCtrl::Load(Stream& in, byte charset) { out_of_limit: { WString w = ToUnicode(~ln, ln.GetCount(), charset); + DDUMP(w); if(total + w.GetLength() <= max_total) { line.Add(w); total += w.GetLength(); diff --git a/uppsrc/CtrlLib/TextEdit.h b/uppsrc/CtrlLib/TextEdit.h index 115401e91..d16583e1a 100644 --- a/uppsrc/CtrlLib/TextEdit.h +++ b/uppsrc/CtrlLib/TextEdit.h @@ -88,6 +88,7 @@ protected: bool processtab, processenter; bool nobg; int max_total; + int max_line_len; void IncDirty(); void DecDirty(); @@ -106,8 +107,8 @@ public: virtual void RefreshLine(int i); Event WhenBar; - Event<> WhenState; - Event<> WhenSel; + Event<> WhenState; + Event<> WhenSel; void CachePos(int pos); void CacheLinePos(int linei); @@ -201,7 +202,7 @@ public: TextCtrl& ProcessEnter(bool b = true) { processenter = b; return *this; } TextCtrl& NoProcessEnter() { return ProcessEnter(false); } TextCtrl& NoBackground(bool b = true) { nobg = b; Transparent(); Refresh(); return *this; } - TextCtrl& MaxLength(int len) { max_total = len; return *this; } + TextCtrl& MaxLength(int len, int linelen) { max_total = len; max_line_len = linelen; return *this; } bool IsNoBackground() const { return nobg; } bool IsProcessTab() const { return processtab; } bool IsProcessEnter() const { return processenter; }