1 class TextCtrl : public Ctrl, protected TextArrayOps { 2 public: 3 virtual void SetData(const Value& v); 4 virtual Value GetData() const; 5 virtual void CancelMode(); 6 virtual String GetSelectionData(const String& fmt) const; 7 virtual void MiddleDown(Point p, dword flags); 8 9 public: 10 struct UndoRec { 11 int serial; 12 int pos; 13 int size; 14 String data; 15 bool typing; 16 SetTextUndoRec17 void SetText(const String& text) { data = FastCompress(text); } GetTextUndoRec18 String GetText() const { return FastDecompress(data); } 19 }; 20 21 struct UndoData { 22 int undoserial; 23 BiArray<UndoRec> undo; 24 BiArray<UndoRec> redo; 25 ClearUndoData26 void Clear() { undo.Clear(); redo.Clear(); } 27 }; 28 29 enum { 30 INK_NORMAL, 31 INK_DISABLED, 32 INK_SELECTED, 33 PAPER_NORMAL, 34 PAPER_READONLY, 35 PAPER_SELECTED, 36 WHITESPACE, 37 WARN_WHITESPACE, 38 COLOR_COUNT, 39 }; 40 41 protected: GetTotal()42 virtual int64 GetTotal() const { return total; } GetCharAt(int64 i)43 virtual int GetCharAt(int64 i) const { return GetChar(i); } 44 45 virtual void DirtyFrom(int line); 46 virtual void SelectionChanged(); 47 virtual void ClearLines(); 48 virtual void InsertLines(int line, int count); 49 virtual void RemoveLines(int line, int count); 50 virtual void PreInsert(int pos, const WString& text); 51 virtual void PostInsert(int pos, const WString& text); 52 virtual void PreRemove(int pos, int size); 53 virtual void PostRemove(int pos, int size); 54 virtual void SetSb(); 55 virtual void PlaceCaret(int64 newcursor, bool sel = false); 56 virtual void InvalidateLine(int i); 57 virtual int RemoveRectSelection(); 58 virtual WString CopyRectSelection(); 59 virtual int PasteRectSelection(const WString& s); 60 virtual String GetPasteText(); 61 62 struct Ln : Moveable<Ln> { 63 int len; 64 String text; 65 LnLn66 Ln() { len = 0; } 67 }; 68 69 Vector<Ln> lin; 70 int64 total; 71 72 int64 cpos; 73 int cline; 74 int64 cursor, anchor; 75 int undoserial; 76 bool rectsel; 77 bool incundoserial; 78 int undosteps; 79 BiArray<UndoRec> undo; 80 BiArray<UndoRec> redo; 81 int dirty; 82 int undo_op; 83 byte charset; 84 bool truncated; 85 86 bool selclick; 87 Point dropcaret; 88 bool isdrag; 89 90 Color color[COLOR_COUNT]; 91 92 bool processtab, processenter; 93 bool nobg; 94 int max_total; 95 int max_line_len; 96 97 mutable Stream *view; 98 struct ViewCache { 99 int blk; 100 Vector<Ln> line; 101 }; 102 mutable ViewCache view_cache[2]; 103 mutable int viewlines; 104 105 Vector<int64> offset256; 106 Vector<int> total256; 107 int view_loading_lock; 108 int64 view_loading_pos; 109 bool view_all; 110 111 void IncDirty(); 112 void DecDirty(); 113 int Insert0(int pos, const WString& txt); 114 void Remove0(int pos, int size); 115 int InsertU(int pos, const WString& txt, bool typing = false); 116 void RemoveU(int pos, int size); 117 void Undodo(); 118 int Insert(int pos, const WString& txt, bool typing); DoPaste()119 void DoPaste() { Paste(); } DoRemoveSelection()120 void DoRemoveSelection() { RemoveSelection(); } 121 void RefreshLines(int l1, int l2); 122 static bool IsUnicodeCharset(byte charset); 123 124 int Load0(Stream& in, byte charset, bool view); 125 int LoadLines(Vector<Ln>& ls, int n, int64& total, Stream& in, byte charset, 126 int max_line_len, int max_total, bool& truncated) const; 127 void ViewLoading(); 128 SetLine(int i,const String & txt,int len)129 void SetLine(int i, const String& txt, int len) { lin[i].text = txt; lin[i].len = len; } SetLine(int i,const WString & w)130 void SetLine(int i, const WString& w) { SetLine(i, ToUtf8(w), w.GetCount()); } LineRemove(int i,int n)131 void LineRemove(int i, int n) { lin.Remove(i, n); } LineInsert(int i,int n)132 void LineInsert(int i, int n) { lin.InsertN(i, n); } 133 const Ln& GetLn(int i) const; 134 135 int GetLinePos32(int& pos) const; 136 bool GetSelection32(int& l, int& h) const; 137 int GetPos32(int line, int column = 0) const { return (int)GetPos64(line, column); } 138 int GetLength32() const; 139 int GetCursor32() const; 140 141 public: 142 virtual void RefreshLine(int i); 143 144 Event<Bar&> WhenBar; 145 Event<> WhenState; 146 Event<> WhenSel; 147 Event<int64> WhenViewMapping; 148 149 void CachePos(int64 pos); 150 void CacheLinePos(int linei); 151 152 enum CS { CHARSET_UTF8_BOM = 250, CHARSET_UTF16_LE, CHARSET_UTF16_BE, CHARSET_UTF16_LE_BOM, CHARSET_UTF16_BE_BOM }; 153 enum LE { LE_DEFAULT, LE_CRLF, LE_LF }; 154 155 int Load(Stream& s, byte charset = CHARSET_DEFAULT) { return Load0(s, charset, false); } IsTruncated()156 bool IsTruncated() const { return truncated; } 157 void Save(Stream& s, byte charset = CHARSET_DEFAULT, int line_endings = LE_DEFAULT) const; 158 159 int GetInvalidCharPos(byte charset = CHARSET_DEFAULT) const; 160 bool CheckCharset(byte charset = CHARSET_DEFAULT) const { return GetInvalidCharPos(charset) < 0; } 161 LimitSize(int64 size)162 int LimitSize(int64 size) const { return int(view ? min((int64)max_total, size) : size); } 163 GetLinePos(int & pos)164 int GetLinePos(int& pos) const { return GetLinePos32(pos); } 165 int GetPos(int line, int column = 0) const { return GetPos32(line, column); } 166 167 void Set(const WString& s); 168 void Set(const String& s, byte charset = CHARSET_DEFAULT); 169 String Get(byte charset = CHARSET_DEFAULT) const; 170 String Get(int64 pos, int size, byte charset = CHARSET_DEFAULT) const; 171 WString GetW(int64 pos, int size) const; GetW()172 WString GetW() const { return GetW(0, LimitSize(GetLength64())); } 173 174 void ClearDirty(); IsDirty()175 bool IsDirty() const { return dirty; } 176 177 void Clear(); 178 GetLine(int64 pos)179 int GetLine(int64 pos) const { return GetLinePos64(pos); } 180 181 const String& GetUtf8Line(int i) const; GetWLine(int i)182 WString GetWLine(int i) const { return FromUtf8(GetUtf8Line(i)); } 183 String GetEncodedLine(int i, byte charset = CHARSET_DEFAULT) const; 184 int GetLineLength(int i) const; 185 GetLength()186 int GetLength() const { return GetLength32(); } GetLineCount()187 int GetLineCount() const { return view ? viewlines : lin.GetCount(); } 188 int GetChar(int64 pos) const; GetChar()189 int GetChar() const { return cursor < GetLength64() ? GetChar(cursor) : 0; } 190 int operator[](int64 pos) const { return GetChar(pos); } 191 GetCursor()192 int GetCursor() const { return GetCursor32(); } GetCursorLine()193 int GetCursorLine() const { return GetLine(GetCursor64()); } 194 195 void SetSelection(int64 anchor = 0, int64 cursor = INT_MAX); IsSelection()196 bool IsSelection() const { return IsAnySelection() && !rectsel; } IsRectSelection()197 bool IsRectSelection() const { return IsAnySelection() && rectsel; } IsAnySelection()198 bool IsAnySelection() const { return anchor >= 0 && anchor != cursor; } GetSelection(int & l,int & h)199 bool GetSelection(int& l, int& h) const{ return GetSelection32(l, h); } 200 bool GetSelection(int64& l, int64& h) const; 201 String GetSelection(byte charset = CHARSET_DEFAULT) const; 202 WString GetSelectionW() const; 203 void ClearSelection(); 204 bool RemoveSelection(); SetCursor(int64 cursor)205 void SetCursor(int64 cursor) { PlaceCaret(cursor); } 206 int Paste(const WString& text); 207 Insert(int pos,const WString & txt)208 int Insert(int pos, const WString& txt) { return Insert(pos, txt, false); } 209 int Insert(int pos, const String& txt, byte charset = CHARSET_DEFAULT); Insert(int pos,const char * txt)210 int Insert(int pos, const char *txt) { return Insert(pos, WString(txt)); } 211 void Remove(int pos, int size); 212 Append(const WString & txt)213 int Append(const WString& txt) { return Insert(GetLength(), txt); } 214 int Append(const String& txt, byte charset = CHARSET_DEFAULT) { return Insert(GetLength(), txt, charset); } Append(const char * txt)215 int Append(const char *txt) { return Append(WString(txt)); } 216 217 void NextUndo(); 218 void Undo(); 219 void Redo(); IsUndo()220 bool IsUndo() const { return undo.GetCount(); } IsRedo()221 bool IsRedo() const { return redo.GetCount(); } ClearUndo()222 void ClearUndo() { undo.Clear(); redo.Clear(); } ClearRedo()223 void ClearRedo() { redo.Clear(); } IsUndoOp()224 bool IsUndoOp() const { return undo_op; } 225 UndoData PickUndoData(); 226 void SetPickUndoData(UndoData&& data); 227 228 void Cut(); 229 void Copy(); 230 void Paste(); 231 void SelectAll(); 232 233 void StdBar(Bar& menu); 234 SetCharset(byte cs)235 void SetCharset(byte cs) { charset = ResolveCharset(cs); } GetCharset()236 byte GetCharset() const { return charset; } 237 SetColor(int i,Color c)238 void SetColor(int i, Color c) { color[i] = c; Refresh(); } GetColor(int i)239 Color GetColor(int i) const { return color[i]; } 240 241 int View(Stream& s, byte charset = CHARSET_DEFAULT) { return Load0(s, charset, true); } 242 void WaitView(int line = INT_MAX, bool progress = false); LockViewMapping()243 void LockViewMapping() { view_loading_lock++; } 244 void UnlockViewMapping(); 245 void SerializeViewMap(Stream& s); IsView()246 bool IsView() const { return view; } GetViewSize()247 int64 GetViewSize() const { return view ? view->GetSize() : 0; } 248 249 int GetLinePos64(int64& pos) const; 250 int64 GetPos64(int line, int column = 0) const; GetLength64()251 int64 GetLength64() const { return total; } GetCursor64()252 int64 GetCursor64() const { return cursor; } 253 UndoSteps(int n)254 TextCtrl& UndoSteps(int n) { undosteps = n; Undodo(); return *this; } GetUndoSteps()255 int GetUndoSteps() const { return undosteps; } 256 TextCtrl& ProcessTab(bool b = true) { processtab = b; return *this; } NoProcessTab()257 TextCtrl& NoProcessTab() { return ProcessTab(false); } 258 TextCtrl& ProcessEnter(bool b = true) { processenter = b; return *this; } NoProcessEnter()259 TextCtrl& NoProcessEnter() { return ProcessEnter(false); } 260 TextCtrl& NoBackground(bool b = true) { nobg = b; Transparent(); Refresh(); return *this; } MaxLength(int len,int linelen)261 TextCtrl& MaxLength(int len, int linelen) { max_total = len; max_line_len = linelen; return *this; } IsNoBackground()262 bool IsNoBackground() const { return nobg; } IsProcessTab()263 bool IsProcessTab() const { return processtab; } IsProcessEnter()264 bool IsProcessEnter() const { return processenter; } 265 266 typedef TextCtrl CLASSNAME; 267 268 TextCtrl(); 269 virtual ~TextCtrl(); 270 }; 271 272 class LineEdit : public TextCtrl { 273 public: 274 virtual bool Key(dword key, int count); 275 virtual void Paint(Draw& w); 276 virtual void LeftDown(Point p, dword flags); 277 virtual void RightDown(Point p, dword flags); 278 virtual void LeftRepeat(Point p, dword keyflags); 279 virtual void LeftDouble(Point p, dword keyflags); 280 virtual void LeftTriple(Point p, dword keyflags); 281 virtual void LeftUp(Point p, dword flags); 282 virtual void LeftDrag(Point p, dword flags); 283 virtual void MouseMove(Point p, dword flags); 284 virtual void MouseWheel(Point, int zdelta, dword); 285 virtual Image CursorImage(Point, dword); 286 virtual void DragAndDrop(Point p, PasteClip& d); 287 virtual void DragRepeat(Point p); 288 virtual void DragLeave(); 289 virtual void Layout(); 290 virtual void RefreshLine(int i); 291 292 protected: 293 virtual void SetSb(); 294 virtual void PlaceCaret(int64 newcursor, bool sel = false); 295 virtual int RemoveRectSelection(); 296 virtual WString CopyRectSelection(); 297 virtual int PasteRectSelection(const WString& s); 298 299 public: 300 enum Flags { 301 SHIFT_L = 1, 302 SHIFT_R = 2, 303 SPELLERROR = 4, 304 }; 305 306 struct Highlight : Moveable<Highlight> { 307 Color paper; 308 Color ink; 309 Font font; 310 word flags; 311 wchar chr; 312 313 bool operator==(const Highlight& h) const 314 { return paper == h.paper && ink == h.ink && font == h.font; } 315 HighlightHighlight316 Highlight() { flags = 0; } 317 }; 318 319 struct EditPos : Moveable<EditPos> { 320 int sby; 321 int64 cursor; 322 323 void Serialize(Stream& s); ClearEditPos324 void Clear() { sby = 0; cursor = 0; } EditPosEditPos325 EditPos() { Clear(); } 326 }; 327 328 protected: 329 virtual void HighlightLine(int line, Vector<Highlight>& h, int64 pos); 330 virtual void NewScrollPos(); 331 332 ScrollBars sb; 333 int gcolumn; 334 int64 mpos; 335 336 337 Font font; 338 CharFilter filter; 339 int tabsize; 340 int bordercolumn; 341 Color bordercolor; 342 Color hline, vline; 343 int vlinex; 344 Scroller scroller; 345 Point caretpos; 346 bool nohbar; 347 bool showtabs; 348 bool cutline; 349 bool overwrite; 350 bool showspaces; 351 bool showlines; 352 bool showreadonly; 353 bool warnwhitespace; 354 bool dorectsel; // TODO: Refactor this ugly hack! 355 356 void Paint0(Draw& w); 357 358 void AlignChar(); 359 360 void MovePage(int dir, bool sel); 361 362 void PlaceCaret0(Point p); 363 int PlaceCaretNoG(int64 newcursor, bool sel = false); 364 365 void Scroll(); 366 void SetHBar(); 367 Rect DropCaret(); 368 void RefreshDropCaret(); DoPasteColumn()369 void DoPasteColumn() { PasteColumn(); } 370 371 struct RefreshDraw; 372 friend class TextCtrl; 373 GetMousePos32(Point p)374 int GetMousePos32(Point p) const { return (int)GetMousePos(p); } 375 376 public: 377 Event<> WhenScroll; 378 379 Size GetFontSize() const; 380 int64 GetGPos(int ln, int cl) const; 381 int64 GetMousePos(Point p) const; 382 Point GetColumnLine(int64 pos) const; GetColumnLinePos(Point pos)383 int64 GetColumnLinePos(Point pos) const { return GetGPos(pos.y, pos.x); } 384 Point GetIndexLine(int64 pos) const; 385 int64 GetIndexLinePos(Point pos) const; 386 387 void SetRectSelection(int64 l, int64 h); 388 void SetRectSelection(const Rect& rect); 389 Rect GetRectSelection() const; 390 bool GetRectSelection(const Rect& rect, int line, int64& l, int64& h); 391 ScrollUp()392 void ScrollUp() { sb.LineUp(); } ScrollDown()393 void ScrollDown() { sb.LineDown(); } ScrollPageUp()394 void ScrollPageUp() { sb.PageUp(); } ScrollPageDown()395 void ScrollPageDown() { sb.PageDown(); } ScrollBegin()396 void ScrollBegin() { sb.VertBegin(); } ScrollEnd()397 void ScrollEnd() { sb.VertEnd(); } 398 399 Rect GetLineScreenRect(int line) const; 400 401 void TopCursor(int lines = 0); 402 void CenterCursor(); 403 404 void MoveUpDown(int n, bool sel = false); 405 406 void MoveLeft(bool sel = false); 407 void MoveRight(bool sel = false); 408 void MoveUp(bool sel = false); 409 void MoveDown(bool sel = false); 410 void MovePageUp(bool sel = false); 411 void MovePageDown(bool sel = false); 412 void MoveHome(bool sel = false); 413 void MoveEnd(bool sel = false); 414 void MoveTextBegin(bool sel = false); 415 void MoveTextEnd(bool sel = false); 416 417 bool InsertChar(dword key, int count = 1, bool canoverwrite = false); 418 void DeleteChar(); 419 void Backspace(); 420 void DeleteLine(); 421 void CutLine(); 422 423 void PasteColumn(const WString& text); 424 void PasteColumn(); 425 426 void Sort(); 427 GetScrollPos()428 Point GetScrollPos() const { return sb; } GetPageSize()429 Size GetPageSize() { return sb.GetPage(); } SetScrollPos(Point p)430 void SetScrollPos(Point p) { sb.Set(p); } 431 432 EditPos GetEditPos() const; 433 void SetEditPos(const EditPos& pos); 434 void SetEditPosSb(const LineEdit::EditPos& pos); 435 void SetEditPosSbOnly(const LineEdit::EditPos& pos); 436 437 void ScrollIntoCursor(); 438 GetCaretPoint()439 Point GetCaretPoint() const { return caretpos; } 440 441 void Clear(); 442 443 void OverWriteMode(bool o = true) { overwrite = o; PlaceCaret(cursor, false); } IsOverWriteMode()444 bool IsOverWriteMode() const { return overwrite; } 445 446 void RefreshChars(bool (*predicate)(int c)); 447 448 LineEdit& TabSize(int n); GetTabSize()449 int GetTabSize() const { return tabsize; } 450 LineEdit& BorderColumn(int col, Color c = SColorFace()); GetBorderColumn()451 int GetBorderColumn() const { return bordercolumn; } 452 LineEdit& SetFont(Font f); GetFont()453 Font GetFont() const { return font; } 454 LineEdit& NoHorzScrollbar(bool b = true) { nohbar = b; ScrollIntoCursor(); return *this; } IsNoHorzScrollbar()455 bool IsNoHorzScrollbar() const { return nohbar; } 456 LineEdit& ShowTabs(bool st = true) { showtabs = st; Refresh(); return *this; } IsShowTabs()457 bool IsShowTabs() const { return showtabs; } 458 LineEdit& ShowSpaces(bool ss = true) { showspaces = ss; Refresh(); return *this; } IsShowSpaces()459 bool IsShowSpaces() const { return showspaces; } 460 LineEdit& ShowLineEndings(bool sl = true) { showlines = sl; Refresh(); return *this; } IsShowLineEndings()461 bool IsShowLineEndings() const { return showlines; } 462 LineEdit& WarnWhiteSpace(bool b = true) { warnwhitespace = b; Refresh(); return *this; } IsWantWhiteSpace()463 bool IsWantWhiteSpace() const { return warnwhitespace; } WithCutLine(bool b)464 LineEdit& WithCutLine(bool b) { cutline = b; return *this; } NoCutLine()465 LineEdit& NoCutLine() { return WithCutLine(false); } IsWithCutLine()466 bool IsWithCutLine() const { return cutline; } SetFilter(int (* f)(int c))467 LineEdit& SetFilter(int (*f)(int c)) { filter = f; return *this; } ShowReadOnly(bool b)468 LineEdit& ShowReadOnly(bool b) { showreadonly = b; Refresh(); return *this; } NoShowReadOnly()469 LineEdit& NoShowReadOnly() { return ShowReadOnly(false); } IsShowReadOnly()470 bool IsShowReadOnly() { return showreadonly; } ShowCurrentLine(Color color)471 LineEdit& ShowCurrentLine(Color color) { hline = color; Refresh(); return *this; } ShowCurrentColumn(Color color)472 LineEdit& ShowCurrentColumn(Color color) { vline = color; Refresh(); return *this; } 473 SetScrollBarStyle(const ScrollBar::Style & s)474 LineEdit& SetScrollBarStyle(const ScrollBar::Style& s) { sb.SetStyle(s); return *this; } 475 476 typedef LineEdit CLASSNAME; 477 478 LineEdit(); 479 virtual ~LineEdit(); 480 }; 481 482 class DocEdit : public TextCtrl { 483 public: 484 virtual void Paint(Draw& w); 485 virtual void Layout(); 486 virtual bool Key(dword key, int count); 487 virtual void LeftDown(Point p, dword flags); 488 virtual void LeftDouble(Point p, dword keyflags); 489 virtual void LeftTriple(Point p, dword keyflags); 490 virtual void LeftUp(Point p, dword flags); 491 virtual void RightDown(Point p, dword w); 492 virtual void MouseMove(Point p, dword flags); 493 virtual void MouseWheel(Point p, int zdelta, dword keyflags); 494 virtual Image CursorImage(Point p, dword keyflags); 495 virtual void GotFocus(); 496 virtual void LostFocus(); 497 virtual void RefreshLine(int i); 498 virtual void SetSb(); 499 500 virtual void DragAndDrop(Point p, PasteClip& d); 501 virtual void DragRepeat(Point p); 502 virtual void DragLeave(); 503 virtual void LeftDrag(Point p, dword flags); 504 505 protected: 506 virtual void ClearLines(); 507 virtual void InsertLines(int line, int count); 508 virtual void RemoveLines(int line, int count); 509 virtual void PlaceCaret(int64 pos, bool select = false); 510 virtual void InvalidateLine(int i); 511 512 struct Para : Moveable<Para> { 513 int cx, cy; 514 ParaPara515 Para() { cx = -1; cy = 0; } 516 }; 517 518 Vector<Para> para; 519 Font font; 520 int after; 521 CharFilter filter; 522 ScrollBar sb; 523 int cx; 524 bool updownleave, eofline; 525 526 struct Fmt { 527 FontInfo fi; 528 int len; 529 Buffer<wchar> text; 530 Buffer<int> width; 531 Vector<int> line; LineEndFmt532 int LineEnd(int i) { 533 return i < line.GetCount() - 1 ? line[i + 1] : len; 534 } 535 }; 536 Fmt Format(const WString& text) const; 537 538 void Invalidate(); 539 int GetHeight(int i); 540 void Scroll(); 541 void PlaceCaret(bool scroll); 542 int GetY(int parai); 543 int GetCursorPos(Point p); 544 Point GetCaret(int pos); 545 void VertMove(int delta, bool select, bool scs); 546 void HomeEnd(int x, bool select); 547 void RefreshStyle(); 548 Rect DropCaret(); 549 void RefreshDropCaret(); 550 int GetMousePos(Point p); 551 552 public: After(int a)553 DocEdit& After(int a) { after = a; RefreshStyle(); return *this; } SetFont(Font f)554 DocEdit& SetFont(Font f) { font = f; RefreshStyle(); return *this; } SetFilter(int (* f)(int c))555 DocEdit& SetFilter(int (*f)(int c)) { filter = f; return *this; } 556 DocEdit& AutoHideSb(bool b = true) { sb.AutoHide(b); return *this; } IsAutoHideSb()557 bool IsAutoHideSb() const { return sb.IsAutoHide(); } 558 DocEdit& UpDownLeave(bool u = true) { updownleave = u; return *this; } NoUpDownLeave()559 DocEdit& NoUpDownLeave() { return UpDownLeave(false); } IsUpDownLeave()560 bool IsUpDownLeave() const { return updownleave; } SetScrollBarStyle(const ScrollBar::Style & s)561 DocEdit& SetScrollBarStyle(const ScrollBar::Style& s) { sb.SetStyle(s); return *this; } 562 DocEdit& EofLine(bool b = true) { eofline = b; return *this; } NoEofLine()563 DocEdit& NoEofLine() { return EofLine(false); } IsEofLine()564 bool IsEofLine() const { return eofline; } 565 566 typedef DocEdit CLASSNAME; 567 568 DocEdit(); 569 virtual ~DocEdit(); 570 }; 571