1
|
#include <CtrlLib/CtrlLib.h>
|
2
|
|
3
|
NAMESPACE_UPP
|
4
|
|
5
|
TextCtrl::TextCtrl()
|
6
|
{
|
7
|
Unicode();
|
8
|
undosteps = 10;
|
9
|
Clear();
|
10
|
undoserial = 0;
|
11
|
incundoserial = false;
|
12
|
undo_op = false;
|
13
|
WhenBar = THISBACK(StdBar);
|
14
|
charset = CHARSET_UNICODE;
|
15
|
color[INK_NORMAL] = SColorText;
|
16
|
color[INK_DISABLED] = SColorDisabled;
|
17
|
color[INK_SELECTED] = SColorHighlightText;
|
18
|
color[PAPER_NORMAL] = SColorPaper;
|
19
|
color[PAPER_READONLY] = SColorFace;
|
20
|
color[PAPER_SELECTED] = SColorHighlight;
|
21
|
processtab = true;
|
22
|
processenter = true;
|
23
|
nobg = false;
|
24
|
}
|
25
|
|
26
|
TextCtrl::~TextCtrl() {}
|
27
|
|
28
|
void TextCtrl::MiddleDown(Point p, dword flags)
|
29
|
{
|
30
|
if(IsReadOnly())
|
31
|
return;
|
32
|
if(AcceptText(Selection())) {
|
33
|
WString w = GetWString(Selection());
|
34
|
selclick = false;
|
35
|
LeftDown(p, flags);
|
36
|
Paste(w);
|
37
|
Action();
|
38
|
}
|
39
|
}
|
40
|
|
41
|
void TextCtrl::CancelMode()
|
42
|
{
|
43
|
selclick = false;
|
44
|
dropcaret = Null;
|
45
|
isdrag = false;
|
46
|
}
|
47
|
|
48
|
void TextCtrl::Clear()
|
49
|
{
|
50
|
cline = cpos = 0;
|
51
|
total = 0;
|
52
|
line.Clear();
|
53
|
line.Shrink();
|
54
|
ClearLines();
|
55
|
line.Add();
|
56
|
InsertLines(0, 1);
|
57
|
DirtyFrom(0);
|
58
|
undo.Clear();
|
59
|
redo.Clear();
|
60
|
ClearDirty();
|
61
|
anchor = -1;
|
62
|
cursor = 0;
|
63
|
SetSb();
|
64
|
PlaceCaret(0);
|
65
|
SelectionChanged();
|
66
|
Refresh();
|
67
|
}
|
68
|
|
69
|
void TextCtrl::DirtyFrom(int line) {}
|
70
|
void TextCtrl::SelectionChanged() {}
|
71
|
void TextCtrl::ClearLines() {}
|
72
|
void TextCtrl::InsertLines(int line, int count) {}
|
73
|
void TextCtrl::RemoveLines(int line, int count) {}
|
74
|
void TextCtrl::PreInsert(int pos, const WString& text) {}
|
75
|
void TextCtrl::PostInsert(int pos, const WString& text) {}
|
76
|
void TextCtrl::PreRemove(int pos, int size) {}
|
77
|
void TextCtrl::PostRemove(int pos, int size) {}
|
78
|
void TextCtrl::RefreshLine(int i) {}
|
79
|
void TextCtrl::InvalidateLine(int i) {}
|
80
|
void TextCtrl::SetSb() {}
|
81
|
void TextCtrl::PlaceCaret(int newcursor, bool sel) {}
|
82
|
|
83
|
void TextCtrl::CachePos(int pos) {
|
84
|
int p = pos;
|
85
|
cline = GetLinePos(p);
|
86
|
cpos = pos - p;
|
87
|
}
|
88
|
|
89
|
int TextCtrl::Load(Stream& s, byte charset) {
|
90
|
Clear();
|
91
|
line.Clear();
|
92
|
ClearLines();
|
93
|
StringBuffer ln;
|
94
|
total = 0;
|
95
|
SetCharset(charset);
|
96
|
if(charset == CHARSET_UTF8_BOM && s.GetLeft() >= 3) {
|
97
|
int64 pos = s.GetPos();
|
98
|
byte h[3];
|
99
|
if(!(s.Get(h, 3) == 3 && h[0] == 0xEF && h[1] == 0xBB && h[2] == 0xBF))
|
100
|
s.Seek(pos);
|
101
|
charset = CHARSET_UTF8;
|
102
|
}
|
103
|
bool cr = false;
|
104
|
byte b8 = 0;
|
105
|
while(!s.IsEof()) {
|
106
|
int c = s.Get();
|
107
|
if(c == '\r')
|
108
|
cr = true;
|
109
|
if(c == '\n') {
|
110
|
if(charset != CHARSET_UTF8 || (b8 & 128)) {
|
111
|
WString w = ToUnicode(~ln, ln.GetCount(), charset);
|
112
|
line.Add(w);
|
113
|
total += w.GetLength() + 1;
|
114
|
}
|
115
|
else {
|
116
|
total += ln.GetCount() + 1;
|
117
|
Ln& l = line.Add();
|
118
|
l.len = ln.GetCount();
|
119
|
l.text = ln;
|
120
|
}
|
121
|
ln.Clear();
|
122
|
b8 = 0;
|
123
|
}
|
124
|
if(c >= ' ' || c == '\t') {
|
125
|
b8 |= c;
|
126
|
ln.Cat(c);
|
127
|
}
|
128
|
}
|
129
|
WString w = ToUnicode(~ln, ln.GetCount(), charset);
|
130
|
line.Add(w);
|
131
|
total += w.GetLength();
|
132
|
InsertLines(0, line.GetCount());
|
133
|
Update();
|
134
|
SetSb();
|
135
|
PlaceCaret(0);
|
136
|
return line.GetCount() > 1 ? cr ? LE_CRLF : LE_LF : LE_DEFAULT;
|
137
|
}
|
138
|
|
139
|
void TextCtrl::Save(Stream& s, byte charset, int line_endings) const {
|
140
|
if(charset == CHARSET_UTF8_BOM) {
|
141
|
static byte bom[] = { 0xEF, 0xBB, 0xBF };
|
142
|
s.Put(bom, 3);
|
143
|
charset = CHARSET_UTF8;
|
144
|
}
|
145
|
charset = ResolveCharset(charset);
|
146
|
String le = "\n";
|
147
|
#ifdef PLATFORM_WIN32
|
148
|
if(line_endings == LE_DEFAULT)
|
149
|
le = "\r\n";
|
150
|
#endif
|
151
|
if(line_endings == LE_CRLF)
|
152
|
le = "\r\n";
|
153
|
for(int i = 0; i < line.GetCount(); i++) {
|
154
|
if(i)
|
155
|
s.Put(le);
|
156
|
String txt = charset == CHARSET_UTF8 ? line[i].text
|
157
|
: FromUnicode(line[i], charset);
|
158
|
const char *e = txt.End();
|
159
|
for(const char *w = txt; w != e; w++)
|
160
|
s.Put(*w == DEFAULTCHAR ? '?' : *w);
|
161
|
}
|
162
|
}
|
163
|
|
164
|
void TextCtrl::Set(const String& s, byte charset) {
|
165
|
StringStream ss(s);
|
166
|
Load(ss, charset);
|
167
|
}
|
168
|
|
169
|
String TextCtrl::Get(byte charset) const
|
170
|
{
|
171
|
StringStream ss;
|
172
|
Save(ss, charset);
|
173
|
return ss;
|
174
|
}
|
175
|
|
176
|
int TextCtrl::GetInvalidCharPos(byte charset) const
|
177
|
{
|
178
|
int q = 0;
|
179
|
if(charset != CHARSET_UTF8 && charset != CHARSET_UTF8_BOM)
|
180
|
for(int i = 0; i < line.GetCount(); i++) {
|
181
|
WString txt = line[i];
|
182
|
WString ctxt = ToUnicode(FromUnicode(txt, charset), charset);
|
183
|
for(int w = 0; w < txt.GetLength(); w++)
|
184
|
if(txt[w] != ctxt[w])
|
185
|
return q + w;
|
186
|
q += txt.GetLength() + 1;
|
187
|
}
|
188
|
return -1;
|
189
|
}
|
190
|
|
191
|
void TextCtrl::ClearDirty()
|
192
|
{
|
193
|
dirty = 0;
|
194
|
ClearModify();
|
195
|
WhenState();
|
196
|
}
|
197
|
|
198
|
TextCtrl::UndoData TextCtrl::PickUndoData()
|
199
|
{
|
200
|
UndoData data;
|
201
|
data.undo = pick(undo);
|
202
|
data.redo = pick(redo);
|
203
|
data.undoserial = undoserial;
|
204
|
return data;
|
205
|
}
|
206
|
|
207
|
void TextCtrl::SetPickUndoData(TextCtrl::UndoData rval_ data)
|
208
|
{
|
209
|
undo = pick(data.undo);
|
210
|
redo = pick(data.redo);
|
211
|
undoserial = data.undoserial;
|
212
|
incundoserial = true;
|
213
|
}
|
214
|
|
215
|
void TextCtrl::Set(const WString& s)
|
216
|
{
|
217
|
Clear();
|
218
|
Insert0(0, s);
|
219
|
}
|
220
|
|
221
|
void TextCtrl::SetData(const Value& v)
|
222
|
{
|
223
|
Set((WString)v);
|
224
|
}
|
225
|
|
226
|
Value TextCtrl::GetData() const
|
227
|
{
|
228
|
return GetW();
|
229
|
}
|
230
|
|
231
|
String TextCtrl::GetEncodedLine(int i, byte charset) const
|
232
|
{
|
233
|
charset = ResolveCharset(charset);
|
234
|
if(charset == CHARSET_UTF8 && charset != CHARSET_UTF8_BOM)
|
235
|
return line[i].text;
|
236
|
return FromUnicode(FromUtf8(line[i].text), charset);
|
237
|
}
|
238
|
|
239
|
int TextCtrl::GetLinePos(int& pos) const {
|
240
|
if(pos < cpos && cpos - pos < pos) {
|
241
|
int i = cline;
|
242
|
int ps = cpos;
|
243
|
for(;;) {
|
244
|
ps -= line[--i].GetLength() + 1;
|
245
|
if(ps <= pos) {
|
246
|
pos = pos - ps;
|
247
|
return i;
|
248
|
}
|
249
|
}
|
250
|
}
|
251
|
else {
|
252
|
int i = 0;
|
253
|
if(pos >= cpos) {
|
254
|
pos -= cpos;
|
255
|
i = cline;
|
256
|
}
|
257
|
for(;;) {
|
258
|
int n = line[i].GetLength() + 1;
|
259
|
if(pos < n) return i;
|
260
|
pos -= n;
|
261
|
i++;
|
262
|
if(i >= line.GetCount()) {
|
263
|
pos = line.Top().GetLength();
|
264
|
return line.GetCount() - 1;
|
265
|
}
|
266
|
}
|
267
|
}
|
268
|
}
|
269
|
|
270
|
int TextCtrl::GetPos(int ln, int lpos) const {
|
271
|
ln = minmax(ln, 0, line.GetCount() - 1);
|
272
|
int i, pos;
|
273
|
if(ln < cline && cline - ln < ln) {
|
274
|
pos = cpos;
|
275
|
i = cline;
|
276
|
while(i > ln)
|
277
|
pos -= line[--i].GetLength() + 1;
|
278
|
}
|
279
|
else {
|
280
|
if(ln >= cline) {
|
281
|
pos = cpos;
|
282
|
i = cline;
|
283
|
}
|
284
|
else {
|
285
|
pos = 0;
|
286
|
i = 0;
|
287
|
}
|
288
|
while(i < ln)
|
289
|
pos += line[i++].GetLength() + 1;
|
290
|
}
|
291
|
return pos + min(line[ln].GetLength(), lpos);
|
292
|
}
|
293
|
|
294
|
WString TextCtrl::GetW(int pos, int size) const
|
295
|
{
|
296
|
int i = GetLinePos(pos);
|
297
|
WString r;
|
298
|
for(;;) {
|
299
|
if(i >= line.GetCount()) break;
|
300
|
WString ln = line[i++];
|
301
|
int sz = min(ln.GetLength() - pos, size);
|
302
|
r.Cat(ln.Mid(pos, sz));
|
303
|
size -= sz;
|
304
|
if(size == 0) break;
|
305
|
#ifdef PLATFORM_WIN32
|
306
|
r.Cat('\r');
|
307
|
#endif
|
308
|
r.Cat('\n');
|
309
|
size--;
|
310
|
if(size == 0) break;
|
311
|
pos = 0;
|
312
|
}
|
313
|
return r;
|
314
|
}
|
315
|
|
316
|
String TextCtrl::Get(int pos, int size, byte charset) const
|
317
|
{
|
318
|
return FromUnicode(GetW(pos, size), charset);
|
319
|
}
|
320
|
|
321
|
int TextCtrl::GetChar(int pos) const {
|
322
|
int i = GetLinePos(pos);
|
323
|
WString ln = line[i];
|
324
|
int c = ln.GetLength() == pos ? '\n' : ln[pos];
|
325
|
return c;
|
326
|
}
|
327
|
|
328
|
int TextCtrl::Insert0(int pos, const WString& txt) {
|
329
|
int inspos = pos;
|
330
|
PreInsert(inspos, txt);
|
331
|
if(pos < cpos)
|
332
|
cpos = cline = 0;
|
333
|
int i = GetLinePos(pos);
|
334
|
DirtyFrom(i);
|
335
|
int size = 0;
|
336
|
WString ln;
|
337
|
Vector<Ln> iln;
|
338
|
for(const wchar *s = txt; s < txt.End(); s++)
|
339
|
if(*s >= ' ' || *s == '\t') {
|
340
|
ln.Cat(*s);
|
341
|
size++;
|
342
|
}
|
343
|
else
|
344
|
if(*s == '\n') {
|
345
|
iln.Add(ln);
|
346
|
size++;
|
347
|
ln.Clear();
|
348
|
}
|
349
|
|
350
|
WString l = line[i];
|
351
|
if(iln.GetCount()) {
|
352
|
iln[0] = l.Mid(0, pos) + WString(iln[0]);
|
353
|
ln.Cat(l.Mid(pos));
|
354
|
line[i] = ln;
|
355
|
InvalidateLine(i);
|
356
|
line.Insert(i, iln);
|
357
|
InsertLines(i, iln.GetCount());
|
358
|
Refresh();
|
359
|
}
|
360
|
else {
|
361
|
line[i] = l.Mid(0, pos) + ln + l.Mid(pos);
|
362
|
InvalidateLine(i);
|
363
|
RefreshLine(i);
|
364
|
}
|
365
|
total += size;
|
366
|
SetSb();
|
367
|
Update();
|
368
|
PostInsert(inspos, txt);
|
369
|
return size;
|
370
|
}
|
371
|
|
372
|
void TextCtrl::Remove0(int pos, int size) {
|
373
|
int rmpos = pos, rmsize = size;
|
374
|
PreRemove(rmpos, rmsize);
|
375
|
total -= size;
|
376
|
if(pos < cpos)
|
377
|
cpos = cline = 0;
|
378
|
int i = GetLinePos(pos);
|
379
|
DirtyFrom(i);
|
380
|
WString ln = line[i];
|
381
|
int sz = min(ln.GetLength() - pos, size);
|
382
|
ln.Remove(pos, sz);
|
383
|
size -= sz;
|
384
|
line[i] = ln;
|
385
|
if(size == 0) {
|
386
|
InvalidateLine(i);
|
387
|
RefreshLine(i);
|
388
|
}
|
389
|
else {
|
390
|
size--;
|
391
|
int j = i + 1;
|
392
|
for(;;) {
|
393
|
int sz = line[j].GetLength() + 1;
|
394
|
if(sz > size) break;
|
395
|
j++;
|
396
|
size -= sz;
|
397
|
}
|
398
|
WString p1 = line[i];
|
399
|
WString p2 = line[j];
|
400
|
p1.Insert(p1.GetLength(), p2.Mid(size, p2.GetLength() - size));
|
401
|
line[i] = p1;
|
402
|
line.Remove(i + 1, j - i);
|
403
|
RemoveLines(i + 1, j - i);
|
404
|
InvalidateLine(i);
|
405
|
Refresh();
|
406
|
}
|
407
|
Update();
|
408
|
PostRemove(rmpos, rmsize);
|
409
|
SetSb();
|
410
|
}
|
411
|
|
412
|
void TextCtrl::Undodo()
|
413
|
{
|
414
|
while(undo.GetCount() > undosteps)
|
415
|
undo.DropHead();
|
416
|
redo.Clear();
|
417
|
}
|
418
|
|
419
|
void TextCtrl::NextUndo()
|
420
|
{
|
421
|
undoserial += incundoserial;
|
422
|
incundoserial = false;
|
423
|
}
|
424
|
|
425
|
void TextCtrl::IncDirty() {
|
426
|
dirty++;
|
427
|
if(dirty == 0 || dirty == 1)
|
428
|
{
|
429
|
if(dirty)
|
430
|
SetModify();
|
431
|
else
|
432
|
ClearModify();
|
433
|
WhenState();
|
434
|
}
|
435
|
}
|
436
|
|
437
|
void TextCtrl::DecDirty() {
|
438
|
dirty--;
|
439
|
if(dirty == 0 || dirty == -1)
|
440
|
{
|
441
|
if(dirty)
|
442
|
SetModify();
|
443
|
else
|
444
|
ClearModify();
|
445
|
WhenState();
|
446
|
}
|
447
|
}
|
448
|
|
449
|
int TextCtrl::InsertU(int pos, const WString& txt, bool typing) {
|
450
|
int sz = Insert0(pos, txt);
|
451
|
if(undosteps) {
|
452
|
if(undo.GetCount() > 1 && typing && *txt != '\n' && IsDirty()) {
|
453
|
UndoRec& u = undo.Tail();
|
454
|
if(u.typing && u.pos + u.size == pos) {
|
455
|
u.size += txt.GetLength();
|
456
|
return sz;
|
457
|
}
|
458
|
}
|
459
|
UndoRec& u = undo.AddTail();
|
460
|
incundoserial = true;
|
461
|
IncDirty();
|
462
|
u.serial = undoserial;
|
463
|
u.pos = pos;
|
464
|
u.size = sz;
|
465
|
u.typing = typing;
|
466
|
}
|
467
|
return sz;
|
468
|
}
|
469
|
|
470
|
void TextCtrl::RemoveU(int pos, int size) {
|
471
|
if(size + pos > total)
|
472
|
size = total - pos;
|
473
|
if(size <= 0) return;
|
474
|
if(undosteps) {
|
475
|
UndoRec& u = undo.AddTail();
|
476
|
incundoserial = true;
|
477
|
IncDirty();
|
478
|
u.serial = undoserial;
|
479
|
u.pos = pos;
|
480
|
u.size = 0;
|
481
|
u.text = Get(pos, size, CHARSET_UTF8);
|
482
|
u.typing = false;
|
483
|
}
|
484
|
Remove0(pos, size);
|
485
|
}
|
486
|
|
487
|
int TextCtrl::Insert(int pos, const WString& _txt, bool typing) {
|
488
|
WString txt = _txt;
|
489
|
if(charset != CHARSET_UNICODE && charset != CHARSET_UTF8_BOM)
|
490
|
for(int i = 0; i < txt.GetCount(); i++)
|
491
|
if(FromUnicode(txt[i], charset) == DEFAULTCHAR)
|
492
|
txt.Set(i, '?');
|
493
|
int sz = InsertU(pos, txt, typing);
|
494
|
Undodo();
|
495
|
return sz;
|
496
|
}
|
497
|
|
498
|
int TextCtrl::Insert(int pos, const String& txt, byte charset)
|
499
|
{
|
500
|
return Insert(pos, ToUnicode(txt, charset), false);
|
501
|
}
|
502
|
|
503
|
void TextCtrl::Remove(int pos, int size) {
|
504
|
RemoveU(pos, size);
|
505
|
Undodo();
|
506
|
}
|
507
|
|
508
|
void TextCtrl::Undo() {
|
509
|
if(undo.IsEmpty()) return;
|
510
|
undo_op = true;
|
511
|
int nc = 0;
|
512
|
int s = undo.Tail().serial;
|
513
|
while(undo.GetCount()) {
|
514
|
const UndoRec& u = undo.Tail();
|
515
|
if(u.serial != s)
|
516
|
break;
|
517
|
UndoRec& r = redo.AddTail();
|
518
|
r.serial = s;
|
519
|
r.typing = false;
|
520
|
nc = r.pos = u.pos;
|
521
|
CachePos(r.pos);
|
522
|
if(u.size) {
|
523
|
r.size = 0;
|
524
|
r.text = Get(u.pos, u.size, CHARSET_UTF8);
|
525
|
Remove0(u.pos, u.size);
|
526
|
}
|
527
|
else {
|
528
|
WString text = FromUtf8(u.text);
|
529
|
r.size = Insert0(u.pos, text);
|
530
|
nc += r.size;
|
531
|
}
|
532
|
undo.DropTail();
|
533
|
DecDirty();
|
534
|
}
|
535
|
ClearSelection();
|
536
|
PlaceCaret(nc, false);
|
537
|
Action();
|
538
|
undo_op = false;
|
539
|
}
|
540
|
|
541
|
void TextCtrl::Redo() {
|
542
|
if(!redo.GetCount()) return;
|
543
|
NextUndo();
|
544
|
int s = redo.Tail().serial;
|
545
|
int nc = 0;
|
546
|
while(redo.GetCount()) {
|
547
|
const UndoRec& r = redo.Tail();
|
548
|
if(r.serial != s)
|
549
|
break;
|
550
|
nc = r.pos + r.size;
|
551
|
CachePos(r.pos);
|
552
|
if(r.size)
|
553
|
RemoveU(r.pos, r.size);
|
554
|
else
|
555
|
nc += InsertU(r.pos, FromUtf8(r.text));
|
556
|
redo.DropTail();
|
557
|
IncDirty();
|
558
|
}
|
559
|
ClearSelection();
|
560
|
PlaceCaret(nc, false);
|
561
|
Action();
|
562
|
}
|
563
|
|
564
|
void TextCtrl::ClearSelection() {
|
565
|
anchor = -1;
|
566
|
Refresh();
|
567
|
WhenSel();
|
568
|
}
|
569
|
|
570
|
void TextCtrl::SetSelection(int l, int h) {
|
571
|
if(l != h) {
|
572
|
PlaceCaret(minmax(l, 0, total), false);
|
573
|
PlaceCaret(minmax(h, 0, total), true);
|
574
|
}
|
575
|
else
|
576
|
SetCursor(l);
|
577
|
}
|
578
|
|
579
|
bool TextCtrl::GetSelection(int& l, int& h) const {
|
580
|
if(anchor < 0) {
|
581
|
l = h = cursor;
|
582
|
return false;
|
583
|
}
|
584
|
else {
|
585
|
l = min(anchor, cursor);
|
586
|
h = max(anchor, cursor);
|
587
|
return true;
|
588
|
}
|
589
|
}
|
590
|
|
591
|
String TextCtrl::GetSelection(byte charset) const {
|
592
|
int l, h;
|
593
|
if(GetSelection(l, h))
|
594
|
return Get(l, h - l, charset);
|
595
|
return String();
|
596
|
}
|
597
|
|
598
|
WString TextCtrl::GetSelectionW() const {
|
599
|
int l, h;
|
600
|
if(GetSelection(l, h))
|
601
|
return GetW(l, h - l);
|
602
|
return WString();
|
603
|
}
|
604
|
|
605
|
bool TextCtrl::RemoveSelection() {
|
606
|
int l, h;
|
607
|
if(anchor < 0) return false;
|
608
|
GetSelection(l, h);
|
609
|
Remove(l, h - l);
|
610
|
anchor = -1;
|
611
|
Refresh();
|
612
|
PlaceCaret(l);
|
613
|
Action();
|
614
|
return true;
|
615
|
}
|
616
|
|
617
|
void TextCtrl::RefreshLines(int l1, int l2) {
|
618
|
int h = max(l1, l2);
|
619
|
for(int i = min(l1, l2); i <= h; i++)
|
620
|
RefreshLine(i);
|
621
|
}
|
622
|
|
623
|
void TextCtrl::Cut() {
|
624
|
if(!IsReadOnly() && IsSelection()) {
|
625
|
Copy();
|
626
|
RemoveSelection();
|
627
|
}
|
628
|
}
|
629
|
|
630
|
void TextCtrl::Copy() {
|
631
|
int l, h;
|
632
|
if(!GetSelection(l, h)) {
|
633
|
int i = GetLine(cursor);
|
634
|
l = GetPos(i);
|
635
|
h = l + line[i].GetLength() + 1;
|
636
|
}
|
637
|
WString txt = GetW(l, h - l);
|
638
|
ClearClipboard();
|
639
|
AppendClipboardUnicodeText(txt);
|
640
|
AppendClipboardText(txt.ToString());
|
641
|
}
|
642
|
|
643
|
void TextCtrl::SelectAll() {
|
644
|
SetSelection();
|
645
|
}
|
646
|
|
647
|
int TextCtrl::Paste(const WString& text) {
|
648
|
if(IsReadOnly()) return 0;
|
649
|
RemoveSelection();
|
650
|
int n = Insert(cursor, text);
|
651
|
PlaceCaret(cursor + n);
|
652
|
Refresh();
|
653
|
return n;
|
654
|
}
|
655
|
|
656
|
void TextCtrl::Paste() {
|
657
|
WString w = ReadClipboardUnicodeText();
|
658
|
if(w.IsEmpty())
|
659
|
w = ReadClipboardText().ToWString();
|
660
|
Paste(w);
|
661
|
Action();
|
662
|
}
|
663
|
|
664
|
void TextCtrl::StdBar(Bar& menu) {
|
665
|
NextUndo();
|
666
|
if(undosteps) {
|
667
|
menu.Add(undo.GetCount() && IsEditable(), t_("Undo"), CtrlImg::undo(), THISBACK(Undo))
|
668
|
.Key(K_ALT_BACKSPACE)
|
669
|
.Key(K_CTRL_Z);
|
670
|
menu.Add(redo.GetCount() && IsEditable(), t_("Redo"), CtrlImg::redo(), THISBACK(Redo))
|
671
|
.Key(K_SHIFT|K_ALT_BACKSPACE)
|
672
|
.Key(K_SHIFT_CTRL_Z);
|
673
|
menu.Separator();
|
674
|
}
|
675
|
menu.Add(IsEditable() && IsSelection(),
|
676
|
t_("Cut"), CtrlImg::cut(), THISBACK(Cut))
|
677
|
.Key(K_SHIFT_DELETE)
|
678
|
.Key(K_CTRL_X);
|
679
|
menu.Add(IsSelection(),
|
680
|
t_("Copy"), CtrlImg::copy(), THISBACK(Copy))
|
681
|
.Key(K_CTRL_INSERT)
|
682
|
.Key(K_CTRL_C);
|
683
|
menu.Add(IsEditable() && IsClipboardAvailableText(),
|
684
|
t_("Paste"), CtrlImg::paste(), THISBACK(DoPaste))
|
685
|
.Key(K_SHIFT_INSERT)
|
686
|
.Key(K_CTRL_V);
|
687
|
menu.Add(IsEditable() && IsSelection(),
|
688
|
t_("Erase"), CtrlImg::remove(), THISBACK(DoRemoveSelection))
|
689
|
.Key(K_DELETE);
|
690
|
menu.Separator();
|
691
|
menu.Add(GetLength(),
|
692
|
t_("Select all"), CtrlImg::select_all(), THISBACK(SelectAll))
|
693
|
.Key(K_CTRL_A);
|
694
|
}
|
695
|
|
696
|
String TextCtrl::GetSelectionData(const String& fmt) const
|
697
|
{
|
698
|
return GetTextClip(GetSelectionW(), fmt);
|
699
|
}
|
700
|
|
701
|
END_UPP_NAMESPACE
|