lltexteditor.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. /**
  2. * @file lltexteditor.h
  3. * @brief LLTextEditor base class
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. // Text editor widget to let users enter a a multi-line ASCII document//
  33. #ifndef LL_LLTEXTEDITOR_H
  34. #define LL_LLTEXTEDITOR_H
  35. #include "lleditmenuhandler.h"
  36. #include "llframetimer.h"
  37. #include "llkeywords.h"
  38. #include "llpreeditor.h"
  39. #include "llpreprocessor.h"
  40. #include "llstyle.h"
  41. #include "llrect.h"
  42. #include "lluictrl.h"
  43. #include "llpreeditor.h"
  44. class LLFontGL;
  45. class LLScrollbar;
  46. class LLViewBorder;
  47. class LLKeywordToken;
  48. class LLMenuItemCallGL;
  49. class LLTextCmd;
  50. class LLUICtrlFactory;
  51. constexpr llwchar FIRST_EMBEDDED_CHAR = 0x100000;
  52. constexpr llwchar LAST_EMBEDDED_CHAR = 0x10ffff;
  53. constexpr S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR -
  54. FIRST_EMBEDDED_CHAR + 1;
  55. class LLTextEditor : public LLUICtrl, public LLEditMenuHandler,
  56. protected LLPreeditor
  57. {
  58. protected:
  59. LOG_CLASS(LLTextEditor);
  60. public:
  61. // Constants
  62. enum HighlightPosition { WHOLE, START, MIDDLE, END };
  63. LLTextEditor(const std::string& name, const LLRect& rect,
  64. S32 max_length, const std::string& default_text,
  65. LLFontGL* glfont = NULL,
  66. bool allow_embedded_items = false);
  67. ~LLTextEditor() override;
  68. const std::string& getTag() const override;
  69. LLXMLNodePtr getXML(bool save_children = true) const override;
  70. static LLView* fromXML(LLXMLNodePtr nodep, LLView* parentp,
  71. class LLUICtrlFactory*);
  72. void setTextEditorParameters(LLXMLNodePtr node);
  73. LL_INLINE void setParseHTML(bool parsing) { mParseHTML = parsing; }
  74. // Mouse handler overrides
  75. bool handleMouseDown(S32 x, S32 y, MASK mask) override;
  76. bool handleMouseUp(S32 x, S32 y, MASK mask) override;
  77. bool handleMiddleMouseDown(S32 x,S32 y,MASK mask) override;
  78. bool handleRightMouseDown(S32 x, S32 y, MASK mask) override;
  79. bool handleHover(S32 x, S32 y, MASK mask) override;
  80. bool handleScrollWheel(S32 x, S32 y, S32 clicks) override;
  81. bool handleDoubleClick(S32 x, S32 y, MASK mask) override;
  82. bool handleKeyHere(KEY key, MASK mask) override;
  83. bool handleUnicodeCharHere(llwchar uni_char) override;
  84. bool handleToolTip(S32 x, S32 y, std::string& msg, LLRect* rect) override;
  85. bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
  86. EDragAndDropType cargo_type,
  87. void* cargo_data, EAcceptance* accept,
  88. std::string& tooltip_msg) override;
  89. void onMouseCaptureLost() override;
  90. // LLView overrides
  91. void reshape(S32 width, S32 height, bool call_from_parent = true) override;
  92. void draw() override;
  93. void onFocusReceived() override;
  94. void onFocusLost() override;
  95. void setEnabled(bool enabled) override;
  96. // LLUICtrl overrides
  97. void onTabInto() override;
  98. void clear() override;
  99. void setFocus(bool b) override;
  100. LL_INLINE bool acceptsTextInput() const override { return !mReadOnly; }
  101. LL_INLINE bool isDirty() const override { return mLastCmd || (mPristineCmd && mPristineCmd != mLastCmd); }
  102. // Returns true if user changed value at all
  103. LL_INLINE virtual bool isSpellDirty() const { return mWText != mPrevSpelledText; }
  104. // Clear dirty state
  105. LL_INLINE virtual void resetSpellDirty() { mPrevSpelledText = mWText; }
  106. struct SpellMenuBind
  107. {
  108. LLTextEditor* mOrigin;
  109. LLMenuItemCallGL* mMenuItem;
  110. std::string mWord;
  111. S32 mWordPositionStart;
  112. S32 mWordPositionEnd;
  113. S32 mWordY;
  114. };
  115. std::vector<S32> getMisspelledWordsPositions();
  116. virtual void spellReplace(SpellMenuBind* data);
  117. bool getWordBoundriesAt(const S32 at, S32* word_begin,
  118. S32* word_length) const;
  119. // LLEditMenuHandler interface
  120. void undo() override;
  121. bool canUndo() const override;
  122. void redo() override;
  123. bool canRedo() const override;
  124. void cut() override;
  125. bool canCut() const override;
  126. void copy() override;
  127. bool canCopy() const override;
  128. void paste() override;
  129. bool canPaste() const override;
  130. void doDelete() override;
  131. bool canDoDelete() const override;
  132. void selectAll() override;
  133. LL_INLINE bool canSelectAll() const override { return true; }
  134. virtual void deselect() override;
  135. LL_INLINE virtual bool canDeselect() const override { return hasSelection(); }
  136. // New methods
  137. virtual void updatePrimary();
  138. virtual void copyPrimary();
  139. virtual void pastePrimary();
  140. virtual bool canPastePrimary() const;
  141. void selectNext(const std::string& search_text_in, bool case_insensitive,
  142. bool wrap = true);
  143. bool replaceText(const std::string& search_text,
  144. const std::string& replace_text, bool case_insensitive,
  145. bool wrap = true);
  146. void replaceTextAll(const std::string& search_text,
  147. const std::string& replace_text,
  148. bool case_insensitive);
  149. // Undo/redo stack
  150. void blockUndo();
  151. // Text editing
  152. virtual void makePristine();
  153. bool isPristine() const;
  154. LL_INLINE bool allowsEmbeddedItems() const { return mAllowEmbeddedItems; }
  155. LL_INLINE void setPreserveSegments(bool b) { mPreserveSegments = b; }
  156. // Inserts text at cursor
  157. void insertText(const std::string& text);
  158. // Appends text at end
  159. void appendText(const std::string& wtext, bool allow_undo,
  160. bool prepend_newline, const LLStyleSP stylep = NULL);
  161. void appendColoredText(const std::string& wtext, bool allow_undo,
  162. bool prepend_newline, const LLColor4& color,
  163. const std::string& font_name = LLStringUtil::null);
  164. // If styled text starts a line, you need to prepend a newline.
  165. void appendStyledText(const std::string& new_text, bool allow_undo,
  166. bool prepend_newline, LLStyleSP stylep = NULL);
  167. // Tries and removes the first line. Returns the number of removed
  168. // characters (0 when nothing could be removed).
  169. S32 removeFirstLine();
  170. // Removes text from the end of document
  171. // Does not change highlight or cursor position.
  172. void removeTextFromEnd(S32 num_chars);
  173. bool tryToRevertToPristineState();
  174. void setCursor(S32 row, S32 column);
  175. void setCursorPos(S32 offset);
  176. void setCursorAndScrollToEnd();
  177. void scrollToPos(S32 pos);
  178. LL_INLINE S32 getCursorPos() { return mCursorPos; }
  179. void getLineAndColumnForPosition(S32 position, S32* line, S32* col,
  180. bool include_wordwrap);
  181. void getCurrentLineAndColumn(S32* line, S32* col, bool include_wordwrap);
  182. S32 getLineForPosition(S32 position);
  183. S32 getCurrentLine();
  184. void loadKeywords(const std::string& filename,
  185. const std::vector<std::string>& funcs,
  186. const std::vector<std::string>& tooltips,
  187. const LLColor3& func_color);
  188. LL_INLINE LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); }
  189. LL_INLINE LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); }
  190. // Color support
  191. LL_INLINE void setCursorColor(const LLColor4& c) { mCursorColor = c; }
  192. LL_INLINE void setFgColor(const LLColor4& c) { mFgColor = c; }
  193. LL_INLINE void setTextDefaultColor(const LLColor4& c) { mDefaultColor = c; }
  194. LL_INLINE void setReadOnlyFgColor(const LLColor4& c) { mReadOnlyFgColor = c; }
  195. LL_INLINE void setWriteableBgColor(const LLColor4& c) { mWriteableBgColor = c; }
  196. LL_INLINE void setReadOnlyBgColor(const LLColor4& c) { mReadOnlyBgColor = c; }
  197. void setTrackColor(const LLColor4& color);
  198. void setThumbColor(const LLColor4& color);
  199. void setHighlightColor(const LLColor4& color);
  200. void setShadowColor(const LLColor4& color);
  201. LL_INLINE LLColor4 getReadOnlyFgColor() { return mReadOnlyFgColor; }
  202. LL_INLINE void setSpellCheck(bool b) { mSpellCheck = b; }
  203. LL_INLINE bool getSpellCheck() { return mSpellCheck; }
  204. // Hacky methods to make it into a word-wrapping, potentially scrolling,
  205. // read-only text box.
  206. void setBorderVisible(bool b);
  207. bool isBorderVisible() const;
  208. void setHideScrollbarForShortDocs(bool b);
  209. void setWordWrap(bool b);
  210. LL_INLINE void setTabsToNextField(bool b) { mTabsToNextField = b; }
  211. LL_INLINE bool tabsToNextField() const { return mTabsToNextField; }
  212. LL_INLINE void setCommitOnFocusLost(bool b) { mCommitOnFocusLost = b; }
  213. // Hack to handle Notecards
  214. virtual bool importBuffer(const char* buffer, S32 length);
  215. virtual bool exportBuffer(std::string& buffer);
  216. LL_INLINE void setHandleEditKeysDirectly(bool b) { mHandleEditKeysDirectly = b; }
  217. LL_INLINE void setLinkColor(LLColor4 color) { mLinkColor = color; }
  218. LL_INLINE static void setLinksColor(const LLColor4& color) { sLinkColor = color; }
  219. LL_INLINE static LLColor4& getLinksColor() { return sLinkColor; }
  220. // Callbacks
  221. static void setURLCallbacks(void (*callback1)(const std::string& url),
  222. bool (*callback2)(const std::string& url),
  223. bool (*callback3)(const std::string& url))
  224. {
  225. sURLcallback = callback1;
  226. sSecondlifeURLcallback = callback2;
  227. sSecondlifeURLcallbackRightClick = callback3;
  228. }
  229. void setOnScrollEndCallback(void (*callback)(void*), void* userdata);
  230. void setKeystrokeCallback(void (*callback)(LLTextEditor*, void*),
  231. void* userdata);
  232. void setOnHandleKeyCallback(bool (*callback)(KEY, MASK, LLTextEditor*,
  233. void*),
  234. void* userdata);
  235. // New methods
  236. void setValue(const LLSD& value) override;
  237. LLSD getValue() const override;
  238. const std::string& getText() const;
  239. // Non-undoable
  240. void setText(const std::string& utf8str);
  241. void setWText(const LLWString& wtext);
  242. void setSelection(S32 start, S32 end);
  243. // Returns byte length limit
  244. LL_INLINE S32 getMaxLength() const { return mMaxTextByteLength; }
  245. // Change cursor
  246. void startOfLine();
  247. void endOfLine();
  248. void endOfDoc();
  249. bool isScrolledToTop();
  250. bool isScrolledToBottom();
  251. LL_INLINE const LLWString& getWText() const override { return mWText; }
  252. LL_INLINE llwchar getWChar(S32 pos) const { return mWText[pos]; }
  253. LL_INLINE LLWString getWSubString(S32 pos, S32 len) const { return mWText.substr(pos, len); }
  254. LL_INLINE S32 getLength() const { return mWText.length(); }
  255. LL_INLINE const LLTextSegment* getCurrentSegment() const
  256. {
  257. return getSegmentAtOffset(mCursorPos);
  258. }
  259. const LLTextSegment* getPreviousSegment() const;
  260. void getSelectedSegments(std::vector<const LLTextSegment*>& segments) const;
  261. LL_INLINE bool isReadOnly() { return mReadOnly; }
  262. // Allow to change the font on the fly. HB
  263. void setFont(LLFontGL* fontp);
  264. LL_INLINE LLFontGL* getFont() const { return mGLFont; }
  265. protected:
  266. void getSegmentAndOffset(S32 startpos, S32* segidxp, S32* offsetp) const;
  267. void drawPreeditMarker();
  268. void updateLineStartList(S32 startpos = 0);
  269. void updateScrollFromCursor();
  270. void updateTextRect();
  271. LL_INLINE const LLRect& getTextRect() const { return mTextRect; }
  272. void assignEmbedded(const std::string& s);
  273. bool truncate(); // Returns true if truncation occurs
  274. void removeCharOrTab();
  275. void setCursorAtLocalPos(S32 x, S32 y, bool round);
  276. S32 getCursorPosFromLocalCoord(S32 local_x, S32 local_y, bool round) const;
  277. void indentSelectedLines(S32 spaces);
  278. S32 indentLine(S32 pos, S32 spaces);
  279. void unindentLineBeforeCloseBrace();
  280. S32 getSegmentIdxAtOffset(S32 offset) const;
  281. const LLTextSegment* getSegmentAtLocalPos(S32 x, S32 y) const;
  282. const LLTextSegment* getSegmentAtOffset(S32 offset) const;
  283. LL_INLINE void reportBadKeystroke() { make_ui_sound("UISndBadKeystroke"); }
  284. bool handleNavigationKey(KEY key, MASK mask);
  285. bool handleSpecialKey(KEY key, MASK mask, bool* ret_key_hit);
  286. bool handleSelectionKey(KEY key, MASK mask);
  287. bool handleControlKey(KEY key, MASK mask);
  288. bool handleEditKey(KEY key, MASK mask);
  289. LL_INLINE bool hasSelection() const { return mSelectionStart != mSelectionEnd; }
  290. bool selectionContainsLineBreaks();
  291. void startSelection();
  292. void endSelection();
  293. void deleteSelection(bool transient_operation);
  294. S32 prevWordPos(S32 cursorPos) const;
  295. S32 nextWordPos(S32 cursorPos) const;
  296. LL_INLINE S32 getLineCount() const { return mLineStartList.size(); }
  297. S32 getLineStart(S32 line) const;
  298. void getLineAndOffset(S32 pos, S32* linep, S32* offsetp) const;
  299. S32 getPos(S32 line, S32 offset);
  300. void changePage(S32 delta);
  301. void changeLine(S32 delta);
  302. void autoIndent();
  303. void findEmbeddedItemSegments();
  304. virtual bool handleMouseUpOverSegment(S32 x, S32 y, MASK mask);
  305. LL_INLINE virtual llwchar pasteEmbeddedItem(llwchar chr) { return chr; }
  306. virtual void bindEmbeddedChars(LLFontGL*) const {}
  307. virtual void unbindEmbeddedChars(LLFontGL*) const {}
  308. S32 findHTMLToken(const std::string& line, S32 pos, bool reverse) const;
  309. bool findHTML(const std::string& line, S32* begin, S32* end) const;
  310. // Abstract inner base class representing an undoable editor command.
  311. // Concrete sub-classes can be defined for operations such as insert,
  312. // remove, etc. Used as arguments to the execute() method below.
  313. class LLTextCmd
  314. {
  315. public:
  316. LLTextCmd(S32 pos, bool group_with_next)
  317. : mPos(pos),
  318. mGroupWithNext(group_with_next)
  319. {
  320. }
  321. virtual ~LLTextCmd() = default;
  322. virtual bool execute(LLTextEditor* editor, S32* delta) = 0;
  323. virtual S32 undo(LLTextEditor* editor) = 0;
  324. virtual S32 redo(LLTextEditor* editor) = 0;
  325. LL_INLINE virtual bool canExtend(S32 pos) const { return false; }
  326. virtual void blockExtensions() {}
  327. virtual bool extendAndExecute(LLTextEditor* editor, S32 pos, llwchar c,
  328. S32* delta)
  329. {
  330. llassert(false);
  331. return 0;
  332. }
  333. LL_INLINE virtual bool hasExtCharValue(llwchar value) const
  334. {
  335. return false;
  336. }
  337. // Defined here so they can access protected LLTextEditor editing
  338. // methods
  339. LL_INLINE S32 insert(LLTextEditor* editor, S32 pos,
  340. const LLWString& wstr)
  341. {
  342. return editor->insertStringNoUndo(pos, wstr);
  343. }
  344. LL_INLINE S32 remove(LLTextEditor* editor, S32 pos, S32 length)
  345. {
  346. return editor->removeStringNoUndo(pos, length);
  347. }
  348. LL_INLINE S32 overwrite(LLTextEditor* editor, S32 pos, llwchar wc)
  349. {
  350. return editor->overwriteCharNoUndo(pos, wc);
  351. }
  352. LL_INLINE S32 getPosition() const { return mPos; }
  353. LL_INLINE bool groupWithNext() const { return mGroupWithNext; }
  354. private:
  355. const S32 mPos;
  356. bool mGroupWithNext;
  357. };
  358. // Takes and applies text commands.
  359. S32 execute(LLTextCmd* cmd);
  360. // Undoable operations
  361. void addChar(llwchar c); // at mCursorPos
  362. S32 addChar(S32 pos, llwchar wc);
  363. S32 overwriteChar(S32 pos, llwchar wc);
  364. void removeChar();
  365. S32 removeChar(S32 pos);
  366. S32 insert(S32 pos, const LLWString& wstr, bool with_next_op);
  367. S32 remove(S32 pos, S32 length, bool group_with_next_op);
  368. S32 append(const LLWString& wstr, bool group_with_next_op);
  369. // Direct operations
  370. // Returns number of characters actually inserted
  371. S32 insertStringNoUndo(S32 pos, const LLWString& wstr);
  372. S32 removeStringNoUndo(S32 pos, S32 length);
  373. S32 overwriteCharNoUndo(S32 pos, llwchar wc);
  374. LL_INLINE void resetKeystrokeTimer() { mKeystrokeTimer.reset(); }
  375. void updateAllowingLanguageInput();
  376. bool hasPreeditString() const;
  377. // Overrides LLPreeditor
  378. void resetPreedit() override;
  379. void updatePreedit(const LLWString& preedit_string,
  380. const segment_lengths_t& preedit_segment_lengths,
  381. const standouts_t& preedit_standouts,
  382. S32 caret_position) override;
  383. void markAsPreedit(S32 position, S32 length) override;
  384. void getPreeditRange(S32* position, S32* length) const override;
  385. void getSelectionRange(S32* position, S32* length) const override;
  386. bool getPreeditLocation(S32 query_offset, LLCoordGL* coord,
  387. LLRect* bounds, LLRect* control) const override;
  388. S32 getPreeditFontSize() const override;
  389. // Context menu actions
  390. static void spellCorrect(void* data);
  391. static void spellShow(void* data);
  392. static void spellAdd(void* data);
  393. static void spellIgnore(void* data);
  394. private:
  395. void pasteHelper(bool is_primary);
  396. void updateSegments();
  397. void pruneSegments();
  398. void drawBackground();
  399. void drawSelectionBackground();
  400. void drawCursor();
  401. void drawMisspelled();
  402. void drawText();
  403. void drawClippedSegment(const LLWString& wtext, S32 seg_start, S32 seg_end,
  404. F32 x, F32 y, S32 sel_left, S32 sel_right,
  405. const LLStyleSP& color, F32* right_x);
  406. LL_INLINE void needsReflow()
  407. {
  408. mReflowNeeded = true;
  409. // Cursor might have moved, need to scroll
  410. mScrollNeeded = true;
  411. }
  412. LL_INLINE void needsScroll() { mScrollNeeded = true; }
  413. private:
  414. LLKeywords mKeywords;
  415. static LLColor4 sLinkColor;
  416. static void (*sURLcallback)(const std::string& url);
  417. static bool (*sSecondlifeURLcallback)(const std::string& url);
  418. static bool (*sSecondlifeURLcallbackRightClick)(const std::string& url);
  419. // List of offsets and segment index of the start of each line. Always has
  420. // at least one node (0).
  421. struct line_info
  422. {
  423. line_info(S32 segment, S32 offset)
  424. : mSegment(segment),
  425. mOffset(offset)
  426. {
  427. }
  428. S32 mSegment;
  429. S32 mOffset;
  430. };
  431. struct line_info_compare
  432. {
  433. LL_INLINE bool operator()(const line_info& a, const line_info& b) const
  434. {
  435. if (a.mSegment < b.mSegment)
  436. {
  437. return true;
  438. }
  439. else if (a.mSegment > b.mSegment)
  440. {
  441. return false;
  442. }
  443. else
  444. {
  445. return a.mOffset < b.mOffset;
  446. }
  447. }
  448. };
  449. // Concrete LLTextCmd sub-classes used by the LLTextEditor base class
  450. class LLTextCmdInsert;
  451. class LLTextCmdAddChar;
  452. class LLTextCmdOverwriteChar;
  453. class LLTextCmdRemove;
  454. protected:
  455. // Scrollbar data
  456. class LLScrollbar* mScrollbar;
  457. void (*mOnScrollEndCallback)(void*);
  458. void* mOnScrollEndData;
  459. void (*mKeystrokeCallback)(LLTextEditor*, void*);
  460. void* mKeystrokeData;
  461. bool (*mOnHandleKeyCallback)(KEY, MASK,
  462. LLTextEditor*, void*);
  463. void* mOnHandleKeyData;
  464. // I-beam is just after the mCursorPos-th character.
  465. S32 mCursorPos;
  466. // Use these to determine if a click on an embedded item is a drag or not.
  467. S32 mMouseDownX;
  468. S32 mMouseDownY;
  469. // Are we in the middle of a drag-select? To figure out if there is a current
  470. // selection, call hasSelection().
  471. S32 mSelectionStart;
  472. S32 mSelectionEnd;
  473. S32 mLastSelectionX;
  474. S32 mLastSelectionY;
  475. std::string mHTML;
  476. typedef std::vector<LLTextSegment*> segment_list_t;
  477. segment_list_t mSegments;
  478. const LLTextSegment* mHoverSegment;
  479. LLWString mPreeditWString;
  480. LLWString mPreeditOverwrittenWString;
  481. std::vector<S32> mPreeditPositions;
  482. LLPreeditor::standouts_t mPreeditStandouts;
  483. bool mIsSelecting;
  484. bool mParseHTML;
  485. // Scrollbar
  486. bool mHideScrollbarForShortDocs;
  487. private:
  488. mutable std::string mUTF8Text;
  489. LLWString mWText;
  490. // Spell checking
  491. LLWString mPrevSpelledText; // saved string so we know whether to respell or not
  492. S32 mSpellCheckStart;
  493. S32 mSpellCheckEnd;
  494. std::vector<S32> mMisspellLocations; // where all the misspelled words are
  495. LLFrameTimer mSpellTimer;
  496. std::vector<SpellMenuBind*> mSuggestionMenuItems; // to keep track of what we have to remove before rebuilding the context menu
  497. bool mSpellCheck; // set in xui as "spell_check". Default value for a field
  498. bool mShowMisspelled; // whether to highlight misspelled words or not
  499. S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
  500. LLFontGL* mGLFont;
  501. class LLViewBorder* mBorder;
  502. LLTextCmd* mPristineCmd;
  503. LLTextCmd* mLastCmd;
  504. typedef std::deque<LLTextCmd*> undo_stack_t;
  505. undo_stack_t mUndoStack;
  506. // X pixel position where the user wants the cursor to be
  507. S32 mDesiredXPixel;
  508. // The rect in which text is drawn. Excludes borders.
  509. LLRect mTextRect;
  510. typedef std::vector<line_info> line_list_t;
  511. line_list_t mLineStartList;
  512. LLFrameTimer mKeystrokeTimer;
  513. LLColor4 mCursorColor;
  514. LLColor4 mFgColor;
  515. LLColor4 mDefaultColor;
  516. LLColor4 mReadOnlyFgColor;
  517. LLColor4 mWriteableBgColor;
  518. LLColor4 mReadOnlyBgColor;
  519. LLColor4 mFocusBgColor;
  520. LLColor4 mLinkColor;
  521. // Last position of the IME editor
  522. LLCoordGL mLastIMEPosition;
  523. bool mBaseDocIsPristine;
  524. bool mReflowNeeded;
  525. bool mScrollNeeded;
  526. bool mReadOnly;
  527. bool mWordWrap;
  528. bool mShowLineNumbers;
  529. // if true, tab moves focus to next field, else inserts spaces
  530. bool mTabsToNextField;
  531. bool mCommitOnFocusLost;
  532. // if true, keeps scroll position at bottom during resize
  533. bool mTrackBottom;
  534. bool mScrolledToBottom;
  535. bool mAllowEmbeddedItems;
  536. // HACK: used to preserve segments on replaceText[All]() in chat
  537. bool mPreserveSegments;
  538. // If true, the standard edit keys (Ctrl-X, Delete, etc,) are handled here
  539. // instead of routed by the menu system
  540. bool mHandleEditKeysDirectly;
  541. mutable bool mTextIsUpToDate;
  542. };
  543. class LLTextSegment
  544. {
  545. protected:
  546. LOG_CLASS(LLTextSegment);
  547. public:
  548. // For creating a compare value
  549. LLTextSegment(S32 start);
  550. LLTextSegment(const LLStyleSP& style, S32 start, S32 end);
  551. LLTextSegment(const LLColor4& color, S32 start, S32 end, bool is_visible);
  552. LLTextSegment(const LLColor4& color, S32 start, S32 end);
  553. LLTextSegment(const LLColor3& color, S32 start, S32 end);
  554. LL_INLINE S32 getStart() const { return mStart; }
  555. LL_INLINE S32 getEnd() const { return mEnd; }
  556. LL_INLINE void setEnd(S32 end) { mEnd = end; }
  557. LL_INLINE const LLColor4& getColor() const { return mStyle->getColor(); }
  558. LL_INLINE void setColor(const LLColor4& c) { mStyle->setColor(c); }
  559. LL_INLINE const LLStyleSP& getStyle() const { return mStyle; }
  560. LL_INLINE void setStyle(const LLStyleSP& s) { mStyle = s; }
  561. LL_INLINE void setIsDefault(bool b) { mIsDefault = b; }
  562. LL_INLINE bool getIsDefault() const { return mIsDefault; }
  563. LL_INLINE void setToken(LLKeywordToken* t) { mToken = t; }
  564. LL_INLINE LLKeywordToken* getToken() const { return mToken; }
  565. bool getToolTip(std::string& msg) const;
  566. void dump() const;
  567. LL_INLINE void shift(S32 offset)
  568. {
  569. if (offset + mEnd >= 0 && offset + mStart >= 0)
  570. {
  571. mEnd += offset;
  572. mStart += offset;
  573. }
  574. }
  575. struct compare
  576. {
  577. LL_INLINE bool operator()(const LLTextSegment* a,
  578. const LLTextSegment* b) const
  579. {
  580. return a->mStart < b->mStart;
  581. }
  582. };
  583. private:
  584. LLKeywordToken* mToken;
  585. S32 mStart;
  586. S32 mEnd;
  587. LLStyleSP mStyle;
  588. bool mIsDefault;
  589. };
  590. #endif // LL_TEXTEDITOR_