LineEdit optimizations

git-svn-id: svn://ultimatepp.org/upp/trunk@8108 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2015-01-30 14:32:29 +00:00
parent 88daad0aa4
commit 732b03a63d
6 changed files with 127 additions and 20 deletions

View file

@ -9,7 +9,7 @@ uses
uses(POSIX | LINUX | FREEBSD) PdfDraw;
file
CtrlLib.h options PCH,
CtrlLib.h options(BUILDER_OPTION) PCH,
CtrlLib readonly separator,
LabelBase.h,
LabelBase.cpp,

View file

@ -72,6 +72,17 @@ Size LineEdit::GetFontSize() const {
return Size(max(fi['M'], fi['W']), fi.GetHeight());
}
void LineEdit::SetRectSelection(int anchor, int cursor)
{
dorectsel = true;
SetSelection(anchor, cursor);
dorectsel = false;
}
void LineEdit::SetRectSelection(const Rect& rect)
{
SetRectSelection(GetGPos(rect.top, rect.left), GetGPos(rect.bottom, rect.right));
}
Rect LineEdit::GetRectSelection() const
{
@ -102,6 +113,7 @@ int LineEdit::RemoveRectSelection()
WString txt;
for(int i = rect.top; i <= rect.bottom; i++) {
int l, h;
CacheLinePos(i);
GetRectSelection(rect, i, l, h);
WString s = GetWLine(i);
s.Remove(l - GetPos(i), h - l);
@ -123,6 +135,7 @@ WString LineEdit::CopyRectSelection()
Rect rect = GetRectSelection();
for(int i = rect.top; i <= rect.bottom; i++) {
int l, h;
CacheLinePos(i);
int pos = GetPos(i);
GetRectSelection(rect, i, l, h);
txt.Cat(GetWLine(i).Mid(l - pos, h - l));
@ -142,6 +155,7 @@ int LineEdit::PasteRectSelection(const WString& s)
int n = 0;
for(int i = 0; i < cl.GetCount() && rect.top + i <= rect.bottom; i++) {
int l, h;
CacheLinePos(i);
GetRectSelection(rect, i + rect.top, l, h);
Remove(l, h - l);
int nn = Insert(l, cl[i]);
@ -165,7 +179,8 @@ void LineEdit::PasteColumn(const WString& text)
RemoveSelection();
Point p = t.TopLeft();
pos = cursor;
for(int i = 0; i < t.bottom - t.top + 1; i++) {
for(int i = 0; i < t.bottom - t.top + 1; i++) {
CacheLinePos(i + p.y);
int l = GetGPos(i + p.y, p.x);
pos = l + Insert(l, cl[i % cl.GetCount()]);
}
@ -175,6 +190,7 @@ void LineEdit::PasteColumn(const WString& text)
Point p = GetColumnLine(cursor);
pos = cursor;
for(int i = 0; i < cl.GetCount(); i++) {
CacheLinePos(i + p.y);
int li = p.y + i;
if(li < line.GetCount()) {
int l = GetGPos(i + p.y, p.x);
@ -481,20 +497,39 @@ void LineEdit::Layout() {
int LineEdit::GetGPos(int ln, int cl) const {
ln = minmax(ln, 0, line.GetCount() - 1);
WString txt = line[ln];
const wchar *b = txt;
const wchar *e = txt.End();
const wchar *s = b;
const String& stxt = line[ln].text;
const char *s = stxt;
const char *e = stxt.End();
const char *b = s;
int gl = 0;
int wpos = 0;
while(s < e) {
if(*s == '\t')
gl = (gl + tabsize) / tabsize * tabsize;
else
gl += 1 + IsCJKIdeograph(*s);
if((byte)*s < 128)
gl++;
else {
WString txt = FromUtf8(s, int(e - s));
const wchar *b = txt;
const wchar *e = txt.End();
const wchar *s = b;
while(s < e) {
if(*s == '\t')
gl = (gl + tabsize) / tabsize * tabsize;
else
gl += 1 + IsCJKIdeograph(*s);
if(cl < gl) break;
s++;
}
wpos = int(s - b);
break;
}
if(cl < gl) break;
s++;
}
return GetPos(ln, int(s - b));
return GetPos(ln, int(s - b) + wpos);
}
Point LineEdit::GetColumnLine(int pos) const {

View file

@ -87,12 +87,21 @@ int TextCtrl::RemoveRectSelection() { return 0; }
WString TextCtrl::CopyRectSelection() { return Null; }
int TextCtrl::PasteRectSelection(const WString& s) { return 0; }
void TextCtrl::CachePos(int pos) {
void TextCtrl::CachePos(int pos)
{
int p = pos;
cline = GetLinePos(p);
cpos = pos - p;
}
void TextCtrl::CacheLinePos(int linei)
{
if(linei >= 0 && linei < GetLineCount()) {
cpos = GetPos(linei);
cline = linei;
}
}
int TextCtrl::Load(Stream& in, byte charset) {
Clear();
line.Clear();
@ -381,12 +390,15 @@ int TextCtrl::GetPos(int ln, int lpos) const {
WString TextCtrl::GetW(int pos, int size) const
{
int i = GetLinePos(pos);
WString r;
WStringBuffer r;
for(;;) {
if(i >= line.GetCount()) break;
WString ln = line[i++];
int sz = min(ln.GetLength() - pos, size);
r.Cat(ln.Mid(pos, sz));
if(pos == 0 && sz == ln.GetLength())
r.Cat(ln);
else
r.Cat(ln.Mid(pos, sz));
size -= sz;
if(size == 0) break;
#ifdef PLATFORM_WIN32
@ -402,6 +414,29 @@ WString TextCtrl::GetW(int pos, int size) const
String TextCtrl::Get(int pos, int size, byte charset) const
{
if(charset == CHARSET_UTF8) {
int i = GetLinePos(pos);
StringBuffer r;
for(;;) {
if(i >= line.GetCount()) break;
int sz = min(line[i].GetLength() - pos, size);
const String& ln = line[i++].text;
if(pos == 0 && sz == ln.GetLength())
r.Cat(ln);
else
r.Cat(ln.ToWString().Mid(pos, sz).ToString());
size -= sz;
if(size == 0) break;
#ifdef PLATFORM_WIN32
r.Cat('\r');
#endif
r.Cat('\n');
size--;
if(size == 0) break;
pos = 0;
}
return r;
}
return FromUnicode(GetW(pos, size), charset);
}
@ -420,19 +455,35 @@ int TextCtrl::Insert0(int pos, const WString& txt) {
int i = GetLinePos(pos);
DirtyFrom(i);
int size = 0;
WString ln;
WStringBuffer lnb;
Vector<Ln> iln;
for(const wchar *s = txt; s < txt.End(); s++)
if(*s >= ' ' || *s == '\t') {
ln.Cat(*s);
const wchar *s = txt;
while(s < txt.End())
if(*s >= ' ') {
const wchar *b = s;
while(*s >= ' ') // txt is zero teminated...
s++;
int sz = int(s - b);
lnb.Cat(b, sz);
size += sz;
}
else
if(*s == '\t') {
lnb.Cat(*s);
size++;
s++;
}
else
if(*s == '\n') {
iln.Add(ln);
iln.Add(WString(lnb));
size++;
ln.Clear();
lnb.Clear();
s++;
}
else
s++;
WString ln = lnb;
WString l = line[i];
if(iln.GetCount()) {

View file

@ -105,6 +105,7 @@ public:
Callback WhenSel;
void CachePos(int pos);
void CacheLinePos(int linei);
enum { CHARSET_UTF8_BOM = 250 };
enum { LE_DEFAULT, LE_CRLF, LE_LF };
@ -311,6 +312,8 @@ public:
Point GetIndexLine(int pos) const;
int GetIndexLinePos(Point pos) const;
void SetRectSelection(int l, int h);
void SetRectSelection(const Rect& rect);
Rect GetRectSelection() const;
bool GetRectSelection(const Rect& rect, int line, int& l, int &h);

View file

@ -51,8 +51,8 @@ monospace glyphs `- the width of character is constant).&]
[s5;:LineEdit`:`:GetGPos`(int`,int`)const: [@(0.0.255) int]_[* GetGPos]([@(0.0.255) int]_[*@3 l
n], [@(0.0.255) int]_[*@3 cl])_[@(0.0.255) const]&]
[s2;%% Returns `"graphical`" position of [%-*@3 ln] line and [%-*@3 cl]
column. This takes into account any tabulator characters int
the line.&]
column. This takes into account any tabulator characters in the
line.&]
[s3; &]
[s4; &]
[s5;:LineEdit`:`:GetMousePos`(Point`)const: [@(0.0.255) int]_[* GetMousePos]([_^Point^ Poin
@ -85,6 +85,17 @@ oint]_[*@3 pos])_[@(0.0.255) const]&]
Does not account for tabulators.&]
[s3; &]
[s4; &]
[s5;:LineEdit`:`:SetRectSelection`(int`,int`): [@(0.0.255) void]_[* SetRectSelection]([@(0.0.255) i
nt]_[*@3 l], [@(0.0.255) int]_[*@3 h])&]
[s2;%% Sets rectangular selection.&]
[s3;%% &]
[s4; &]
[s5;:LineEdit`:`:SetRectSelection`(const Rect`&`): [@(0.0.255) void]_[* SetRectSelection](
[@(0.0.255) const]_[_^Rect^ Rect][@(0.0.255) `&]_[*@3 rect])&]
[s2;%% Same as SetRectSelection(GetGPos(rect.top, rect.left), GetGPos(rect.bottom,
rect.right));&]
[s3;%% &]
[s4; &]
[s5;:LineEdit`:`:GetRectSelection`(`)const: [_^Rect^ Rect]_[* GetRectSelection]()_[@(0.0.255) c
onst]&]
[s2;%% Returns rectangular selection (as `"graphical`").&]

View file

@ -109,7 +109,14 @@ from not`-modified to modified (`"dirty`") or back.&]
[s4; &]
[s5;:TextCtrl`:`:CachePos`(int`): [@(0.0.255) void]_[* CachePos]([@(0.0.255) int]_[*@3 pos])&]
[s2;%% This is specific optimization hint to the widget saying that
following operations will be performed near after [%-*@3 pos].
following operations will be performed near [%-*@3 pos]. Unlikely
to be used in the client code.&]
[s3;%% &]
[s4; &]
[s5;:TextCtrl`:`:CacheLinePos`(int`): [@(0.0.255) void]_[* CacheLinePos]([@(0.0.255) int]_[*@3 l
inei])&]
[s2;%% This is specific optimization hint to the widget saying that
following operations will be performed near line [%-*@3 linei].
Unlikely to be used in the client code.&]
[s3;%% &]
[s4; &]