summaryrefslogtreecommitdiff
path: root/indra/llui/lltexteditor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/lltexteditor.cpp')
-rw-r--r--indra/llui/lltexteditor.cpp4639
1 files changed, 2326 insertions, 2313 deletions
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 7150052b65..e030861f20 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file lltexteditor.cpp
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -32,7 +32,7 @@
#include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR
#include "llfontgl.h"
-#include "llgl.h" // LLGLSUIDefault()
+#include "llgl.h" // LLGLSUIDefault()
#include "lllocalcliprect.h"
#include "llrender.h"
#include "llui.h"
@@ -64,105 +64,105 @@
#include <queue>
#include "llcombobox.h"
-//
+//
// Globals
//
static LLDefaultChildRegistry::Register<LLTextEditor> r("simple_text_editor");
// Compiler optimization, generate extern template
template class LLTextEditor* LLView::getChild<class LLTextEditor>(
- const std::string& name, BOOL recurse) const;
+ const std::string& name, BOOL recurse) const;
//
// Constants
//
-const S32 SPACES_PER_TAB = 4;
-const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on
+const S32 SPACES_PER_TAB = 4;
+const F32 SPELLCHECK_DELAY = 0.5f; // delay between the last keypress and spell checking the word the cursor is on
///////////////////////////////////////////////////////////////////
class LLTextEditor::TextCmdInsert : public LLTextBase::TextCmd
{
public:
- TextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment)
- : TextCmd(pos, group_with_next, segment), mWString(ws)
- {
- }
- virtual ~TextCmdInsert() {}
- virtual BOOL execute( LLTextBase* editor, S32* delta )
- {
- *delta = insert(editor, getPosition(), mWString );
- LLWStringUtil::truncate(mWString, *delta);
- //mWString = wstring_truncate(mWString, *delta);
- return (*delta != 0);
- }
- virtual S32 undo( LLTextBase* editor )
- {
- remove(editor, getPosition(), mWString.length() );
- return getPosition();
- }
- virtual S32 redo( LLTextBase* editor )
- {
- insert(editor, getPosition(), mWString );
- return getPosition() + mWString.length();
- }
+ TextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment)
+ : TextCmd(pos, group_with_next, segment), mWString(ws)
+ {
+ }
+ virtual ~TextCmdInsert() {}
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
+ {
+ *delta = insert(editor, getPosition(), mWString );
+ LLWStringUtil::truncate(mWString, *delta);
+ //mWString = wstring_truncate(mWString, *delta);
+ return (*delta != 0);
+ }
+ virtual S32 undo( LLTextBase* editor )
+ {
+ remove(editor, getPosition(), mWString.length() );
+ return getPosition();
+ }
+ virtual S32 redo( LLTextBase* editor )
+ {
+ insert(editor, getPosition(), mWString );
+ return getPosition() + mWString.length();
+ }
private:
- LLWString mWString;
+ LLWString mWString;
};
///////////////////////////////////////////////////////////////////
class LLTextEditor::TextCmdAddChar : public LLTextBase::TextCmd
{
public:
- TextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment)
- : TextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE)
- {
- }
- virtual void blockExtensions()
- {
- mBlockExtensions = TRUE;
- }
- virtual BOOL canExtend(S32 pos) const
- {
- // cannot extend text with custom segments
- if (!mSegments.empty()) return FALSE;
-
- return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length());
- }
- virtual BOOL execute( LLTextBase* editor, S32* delta )
- {
- *delta = insert(editor, getPosition(), mWString);
- LLWStringUtil::truncate(mWString, *delta);
- //mWString = wstring_truncate(mWString, *delta);
- return (*delta != 0);
- }
- virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar wc, S32* delta )
- {
- LLWString ws;
- ws += wc;
-
- *delta = insert(editor, pos, ws);
- if( *delta > 0 )
- {
- mWString += wc;
- }
- return (*delta != 0);
- }
- virtual S32 undo( LLTextBase* editor )
- {
- remove(editor, getPosition(), mWString.length() );
- return getPosition();
- }
- virtual S32 redo( LLTextBase* editor )
- {
- insert(editor, getPosition(), mWString );
- return getPosition() + mWString.length();
- }
+ TextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment)
+ : TextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE)
+ {
+ }
+ virtual void blockExtensions()
+ {
+ mBlockExtensions = TRUE;
+ }
+ virtual BOOL canExtend(S32 pos) const
+ {
+ // cannot extend text with custom segments
+ if (!mSegments.empty()) return FALSE;
+
+ return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length());
+ }
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
+ {
+ *delta = insert(editor, getPosition(), mWString);
+ LLWStringUtil::truncate(mWString, *delta);
+ //mWString = wstring_truncate(mWString, *delta);
+ return (*delta != 0);
+ }
+ virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar wc, S32* delta )
+ {
+ LLWString ws;
+ ws += wc;
+
+ *delta = insert(editor, pos, ws);
+ if( *delta > 0 )
+ {
+ mWString += wc;
+ }
+ return (*delta != 0);
+ }
+ virtual S32 undo( LLTextBase* editor )
+ {
+ remove(editor, getPosition(), mWString.length() );
+ return getPosition();
+ }
+ virtual S32 redo( LLTextBase* editor )
+ {
+ insert(editor, getPosition(), mWString );
+ return getPosition() + mWString.length();
+ }
private:
- LLWString mWString;
- BOOL mBlockExtensions;
+ LLWString mWString;
+ BOOL mBlockExtensions;
};
@@ -171,30 +171,30 @@ private:
class LLTextEditor::TextCmdOverwriteChar : public LLTextBase::TextCmd
{
public:
- TextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc)
- : TextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {}
-
- virtual BOOL execute( LLTextBase* editor, S32* delta )
- {
- mOldChar = editor->getWText()[getPosition()];
- overwrite(editor, getPosition(), mChar);
- *delta = 0;
- return TRUE;
- }
- virtual S32 undo( LLTextBase* editor )
- {
- overwrite(editor, getPosition(), mOldChar);
- return getPosition();
- }
- virtual S32 redo( LLTextBase* editor )
- {
- overwrite(editor, getPosition(), mChar);
- return getPosition()+1;
- }
+ TextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc)
+ : TextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {}
+
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
+ {
+ mOldChar = editor->getWText()[getPosition()];
+ overwrite(editor, getPosition(), mChar);
+ *delta = 0;
+ return TRUE;
+ }
+ virtual S32 undo( LLTextBase* editor )
+ {
+ overwrite(editor, getPosition(), mOldChar);
+ return getPosition();
+ }
+ virtual S32 redo( LLTextBase* editor )
+ {
+ overwrite(editor, getPosition(), mChar);
+ return getPosition()+1;
+ }
private:
- llwchar mChar;
- llwchar mOldChar;
+ llwchar mChar;
+ llwchar mOldChar;
};
///////////////////////////////////////////////////////////////////
@@ -202,114 +202,116 @@ private:
class LLTextEditor::TextCmdRemove : public LLTextBase::TextCmd
{
public:
- TextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) :
- TextCmd(pos, group_with_next), mLen(len)
- {
- std::swap(mSegments, segments);
- }
- virtual BOOL execute( LLTextBase* editor, S32* delta )
- {
- mWString = editor->getWText().substr(getPosition(), mLen);
- *delta = remove(editor, getPosition(), mLen );
- return (*delta != 0);
- }
- virtual S32 undo( LLTextBase* editor )
- {
- insert(editor, getPosition(), mWString);
- return getPosition() + mWString.length();
- }
- virtual S32 redo( LLTextBase* editor )
- {
- remove(editor, getPosition(), mLen );
- return getPosition();
- }
+ TextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) :
+ TextCmd(pos, group_with_next), mLen(len)
+ {
+ std::swap(mSegments, segments);
+ }
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
+ {
+ mWString = editor->getWText().substr(getPosition(), mLen);
+ *delta = remove(editor, getPosition(), mLen );
+ return (*delta != 0);
+ }
+ virtual S32 undo( LLTextBase* editor )
+ {
+ insert(editor, getPosition(), mWString);
+ return getPosition() + mWString.length();
+ }
+ virtual S32 redo( LLTextBase* editor )
+ {
+ remove(editor, getPosition(), mLen );
+ return getPosition();
+ }
private:
- LLWString mWString;
- S32 mLen;
+ LLWString mWString;
+ S32 mLen;
};
///////////////////////////////////////////////////////////////////
LLTextEditor::Params::Params()
-: default_text("default_text"),
- prevalidate_callback("prevalidate_callback"),
- embedded_items("embedded_items", false),
- ignore_tab("ignore_tab", true),
- auto_indent("auto_indent", true),
- default_color("default_color"),
+: default_text("default_text"),
+ prevalidator("prevalidator"),
+ embedded_items("embedded_items", false),
+ ignore_tab("ignore_tab", true),
+ auto_indent("auto_indent", true),
+ default_color("default_color"),
commit_on_focus_lost("commit_on_focus_lost", false),
- show_context_menu("show_context_menu"),
- show_emoji_helper("show_emoji_helper"),
- enable_tooltip_paste("enable_tooltip_paste")
+ show_context_menu("show_context_menu"),
+ show_emoji_helper("show_emoji_helper"),
+ enable_tooltip_paste("enable_tooltip_paste")
{
- addSynonym(prevalidate_callback, "text_type");
+ addSynonym(prevalidator, "prevalidate_callback");
+ addSynonym(prevalidator, "text_type");
}
LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
- LLTextBase(p),
- mAutoreplaceCallback(),
- mBaseDocIsPristine(TRUE),
- mPristineCmd( NULL ),
- mLastCmd( NULL ),
- mDefaultColor( p.default_color() ),
- mAutoIndent(p.auto_indent),
- mCommitOnFocusLost( p.commit_on_focus_lost),
- mAllowEmbeddedItems( p.embedded_items ),
- mMouseDownX(0),
- mMouseDownY(0),
- mTabsToNextField(p.ignore_tab),
- mPrevalidateFunc(p.prevalidate_callback()),
- mShowContextMenu(p.show_context_menu),
- mShowEmojiHelper(p.show_emoji_helper),
- mEnableTooltipPaste(p.enable_tooltip_paste),
- mPassDelete(FALSE),
- mKeepSelectionOnReturn(false)
-{
- mSourceID.generate();
-
- //FIXME: use image?
- LLViewBorder::Params params;
- params.name = "text ed border";
- params.rect = getLocalRect();
- params.bevel_style = LLViewBorder::BEVEL_IN;
- params.border_thickness = 1;
- params.visible = p.border_visible;
- mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
- addChild( mBorder );
- setText(p.default_text());
-
- mParseOnTheFly = TRUE;
+ LLTextBase(p),
+ mAutoreplaceCallback(),
+ mBaseDocIsPristine(TRUE),
+ mPristineCmd( NULL ),
+ mLastCmd( NULL ),
+ mDefaultColor( p.default_color() ),
+ mAutoIndent(p.auto_indent),
+ mParseOnTheFly(false),
+ mCommitOnFocusLost( p.commit_on_focus_lost),
+ mAllowEmbeddedItems( p.embedded_items ),
+ mMouseDownX(0),
+ mMouseDownY(0),
+ mTabsToNextField(p.ignore_tab),
+ mPrevalidator(p.prevalidator()),
+ mShowContextMenu(p.show_context_menu),
+ mShowEmojiHelper(p.show_emoji_helper),
+ mEnableTooltipPaste(p.enable_tooltip_paste),
+ mPassDelete(false),
+ mKeepSelectionOnReturn(false)
+{
+ mSourceID.generate();
+
+ //FIXME: use image?
+ LLViewBorder::Params params;
+ params.name = "text ed border";
+ params.rect = getLocalRect();
+ params.bevel_style = LLViewBorder::BEVEL_IN;
+ params.border_thickness = 1;
+ params.visible = p.border_visible;
+ mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
+ addChild( mBorder );
+ setText(p.default_text());
+
+ mParseOnTheFly = true;
}
void LLTextEditor::initFromParams( const LLTextEditor::Params& p)
{
- LLTextBase::initFromParams(p);
+ LLTextBase::initFromParams(p);
- // HACK: text editors always need to be enabled so that we can scroll
- LLView::setEnabled(true);
+ // HACK: text editors always need to be enabled so that we can scroll
+ LLView::setEnabled(true);
- if (p.commit_on_focus_lost.isProvided())
- {
- mCommitOnFocusLost = p.commit_on_focus_lost;
- }
-
- updateAllowingLanguageInput();
+ if (p.commit_on_focus_lost.isProvided())
+ {
+ mCommitOnFocusLost = p.commit_on_focus_lost;
+ }
+
+ updateAllowingLanguageInput();
}
LLTextEditor::~LLTextEditor()
{
- gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() while LLTextEditor still valid
+ gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() while LLTextEditor still valid
- // Scrollbar is deleted by LLView
- std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
- mUndoStack.clear();
- // Mark the menu as dead or its retained in memory till shutdown.
- LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
- if(menu)
- {
- menu->die();
- mContextMenuHandle.markDead();
- }
+ // Scrollbar is deleted by LLView
+ std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
+ mUndoStack.clear();
+ // Mark the menu as dead or its retained in memory till shutdown.
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+ if(menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
}
////////////////////////////////////////////////////////////
@@ -318,649 +320,651 @@ LLTextEditor::~LLTextEditor()
void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
{
- // validate incoming text if necessary
- if (mPrevalidateFunc)
- {
- LLWString test_text = utf8str_to_wstring(utf8str);
- if (!mPrevalidateFunc(test_text))
- {
- // not valid text, nothing to do
- return;
- }
- }
+ // validate incoming text if necessary
+ if (mPrevalidator)
+ {
+ if (!mPrevalidator.validate(utf8str))
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ mPrevalidator.showLastErrorUsingTimeout();
+
+ // not valid text, nothing to do
+ return;
+ }
+ }
+
+ blockUndo();
+ deselect();
- blockUndo();
- deselect();
-
- mParseOnTheFly = FALSE;
- LLTextBase::setText(utf8str, input_params);
- mParseOnTheFly = TRUE;
+ mParseOnTheFly = false;
+ LLTextBase::setText(utf8str, input_params);
+ mParseOnTheFly = true;
- resetDirty();
+ resetDirty();
}
void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap)
{
- if (search_text_in.empty())
- {
- return;
- }
-
- LLWString text = getWText();
- LLWString search_text = utf8str_to_wstring(search_text_in);
- if (case_insensitive)
- {
- LLWStringUtil::toLower(text);
- LLWStringUtil::toLower(search_text);
- }
-
- if (mIsSelecting)
- {
- LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd);
-
- if (selected_text == search_text)
- {
- // We already have this word selected, we are searching for the next.
- setCursorPos(mCursorPos + search_text.size());
- }
- }
-
- S32 loc = text.find(search_text,mCursorPos);
-
- // If Maybe we wrapped, search again
- if (wrap && (-1 == loc))
- {
- loc = text.find(search_text);
- }
-
- // If still -1, then search_text just isn't found.
+ if (search_text_in.empty())
+ {
+ return;
+ }
+
+ LLWString text = getWText();
+ LLWString search_text = utf8str_to_wstring(search_text_in);
+ if (case_insensitive)
+ {
+ LLWStringUtil::toLower(text);
+ LLWStringUtil::toLower(search_text);
+ }
+
+ if (mIsSelecting)
+ {
+ LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd);
+
+ if (selected_text == search_text)
+ {
+ // We already have this word selected, we are searching for the next.
+ setCursorPos(mCursorPos + search_text.size());
+ }
+ }
+
+ S32 loc = text.find(search_text,mCursorPos);
+
+ // If Maybe we wrapped, search again
+ if (wrap && (-1 == loc))
+ {
+ loc = text.find(search_text);
+ }
+
+ // If still -1, then search_text just isn't found.
if (-1 == loc)
- {
- mIsSelecting = FALSE;
- mSelectionEnd = 0;
- mSelectionStart = 0;
- return;
- }
+ {
+ mIsSelecting = FALSE;
+ mSelectionEnd = 0;
+ mSelectionStart = 0;
+ return;
+ }
- setCursorPos(loc);
-
- mIsSelecting = TRUE;
- mSelectionEnd = mCursorPos;
- mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));
+ setCursorPos(loc);
+
+ mIsSelecting = TRUE;
+ mSelectionEnd = mCursorPos;
+ mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));
}
BOOL LLTextEditor::replaceText(const std::string& search_text_in, const std::string& replace_text,
- BOOL case_insensitive, BOOL wrap)
+ BOOL case_insensitive, BOOL wrap)
{
- BOOL replaced = FALSE;
+ BOOL replaced = FALSE;
- if (search_text_in.empty())
- {
- return replaced;
- }
+ if (search_text_in.empty())
+ {
+ return replaced;
+ }
- LLWString search_text = utf8str_to_wstring(search_text_in);
- if (mIsSelecting)
- {
- LLWString text = getWText();
- LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd);
+ LLWString search_text = utf8str_to_wstring(search_text_in);
+ if (mIsSelecting)
+ {
+ LLWString text = getWText();
+ LLWString selected_text = text.substr(mSelectionEnd, mSelectionStart - mSelectionEnd);
- if (case_insensitive)
- {
- LLWStringUtil::toLower(selected_text);
- LLWStringUtil::toLower(search_text);
- }
+ if (case_insensitive)
+ {
+ LLWStringUtil::toLower(selected_text);
+ LLWStringUtil::toLower(search_text);
+ }
- if (selected_text == search_text)
- {
- insertText(replace_text);
- replaced = TRUE;
- }
- }
+ if (selected_text == search_text)
+ {
+ insertText(replace_text);
+ replaced = TRUE;
+ }
+ }
- selectNext(search_text_in, case_insensitive, wrap);
- return replaced;
+ selectNext(search_text_in, case_insensitive, wrap);
+ return replaced;
}
void LLTextEditor::replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive)
{
- startOfDoc();
- selectNext(search_text, case_insensitive, FALSE);
+ startOfDoc();
+ selectNext(search_text, case_insensitive, FALSE);
- BOOL replaced = TRUE;
- while ( replaced )
- {
- replaced = replaceText(search_text,replace_text, case_insensitive, FALSE);
- }
+ BOOL replaced = TRUE;
+ while ( replaced )
+ {
+ replaced = replaceText(search_text,replace_text, case_insensitive, FALSE);
+ }
}
S32 LLTextEditor::prevWordPos(S32 cursorPos) const
{
- LLWString wtext(getWText());
- while( (cursorPos > 0) && (wtext[cursorPos-1] == ' ') )
- {
- cursorPos--;
- }
- while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) )
- {
- cursorPos--;
- }
- return cursorPos;
+ LLWString wtext(getWText());
+ while( (cursorPos > 0) && (wtext[cursorPos-1] == ' ') )
+ {
+ cursorPos--;
+ }
+ while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) )
+ {
+ cursorPos--;
+ }
+ return cursorPos;
}
S32 LLTextEditor::nextWordPos(S32 cursorPos) const
{
- LLWString wtext(getWText());
- while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) )
- {
- cursorPos++;
- }
- while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') )
- {
- cursorPos++;
- }
- return cursorPos;
+ LLWString wtext(getWText());
+ while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) )
+ {
+ cursorPos++;
+ }
+ while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') )
+ {
+ cursorPos++;
+ }
+ return cursorPos;
}
-const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const
+const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const
{
- static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment;
+ static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment;
- index_segment->setStart(mCursorPos);
- index_segment->setEnd(mCursorPos);
+ index_segment->setStart(mCursorPos);
+ index_segment->setEnd(mCursorPos);
- // find segment index at character to left of cursor (or rightmost edge of selection)
- segment_set_t::const_iterator it = mSegments.lower_bound(index_segment);
+ // find segment index at character to left of cursor (or rightmost edge of selection)
+ segment_set_t::const_iterator it = mSegments.lower_bound(index_segment);
- if (it != mSegments.end())
- {
- return *it;
- }
- else
- {
- return LLTextSegmentPtr();
- }
+ if (it != mSegments.end())
+ {
+ return *it;
+ }
+ else
+ {
+ return LLTextSegmentPtr();
+ }
}
void LLTextEditor::getSelectedSegments(LLTextEditor::segment_vec_t& segments) const
{
- S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
- S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
+ S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
+ S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
- return getSegmentsInRange(segments, left, right, true);
+ return getSegmentsInRange(segments, left, right, true);
}
void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out, S32 start, S32 end, bool include_partial) const
{
- segment_set_t::const_iterator first_it = getSegIterContaining(start);
- segment_set_t::const_iterator end_it = getSegIterContaining(end - 1);
- if (end_it != mSegments.end()) ++end_it;
+ segment_set_t::const_iterator first_it = getSegIterContaining(start);
+ segment_set_t::const_iterator end_it = getSegIterContaining(end - 1);
+ if (end_it != mSegments.end()) ++end_it;
- for (segment_set_t::const_iterator it = first_it; it != end_it; ++it)
- {
- LLTextSegmentPtr segment = *it;
- if (include_partial
- || (segment->getStart() >= start
- && segment->getEnd() <= end))
- {
- segments_out.push_back(segment);
- }
- }
+ for (segment_set_t::const_iterator it = first_it; it != end_it; ++it)
+ {
+ LLTextSegmentPtr segment = *it;
+ if (include_partial
+ || (segment->getStart() >= start
+ && segment->getEnd() <= end))
+ {
+ segments_out.push_back(segment);
+ }
+ }
}
void LLTextEditor::setShowEmojiHelper(bool show)
{
- if (!mShowEmojiHelper)
- {
- LLEmojiHelper::instance().hideHelper(this);
- }
+ if (!mShowEmojiHelper)
+ {
+ LLEmojiHelper::instance().hideHelper(this);
+ }
- mShowEmojiHelper = show;
+ mShowEmojiHelper = show;
}
BOOL LLTextEditor::selectionContainsLineBreaks()
{
- if (hasSelection())
- {
- S32 left = llmin(mSelectionStart, mSelectionEnd);
- S32 right = left + llabs(mSelectionStart - mSelectionEnd);
+ if (hasSelection())
+ {
+ S32 left = llmin(mSelectionStart, mSelectionEnd);
+ S32 right = left + llabs(mSelectionStart - mSelectionEnd);
- LLWString wtext = getWText();
- for( S32 i = left; i < right; i++ )
- {
- if (wtext[i] == '\n')
- {
- return TRUE;
- }
- }
- }
- return FALSE;
+ LLWString wtext = getWText();
+ for( S32 i = left; i < right; i++ )
+ {
+ if (wtext[i] == '\n')
+ {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
}
S32 LLTextEditor::indentLine( S32 pos, S32 spaces )
{
- // Assumes that pos is at the start of the line
- // spaces may be positive (indent) or negative (unindent).
- // Returns the actual number of characters added or removed.
-
- llassert(pos >= 0);
- llassert(pos <= getLength() );
-
- S32 delta_spaces = 0;
-
- if (spaces >= 0)
- {
- // Indent
- for(S32 i=0; i < spaces; i++)
- {
- delta_spaces += addChar(pos, ' ');
- }
- }
- else
- {
- // Unindent
- for(S32 i=0; i < -spaces; i++)
- {
- LLWString wtext = getWText();
- if (wtext[pos] == ' ')
- {
- delta_spaces += remove( pos, 1, FALSE );
- }
- }
- }
-
- return delta_spaces;
+ // Assumes that pos is at the start of the line
+ // spaces may be positive (indent) or negative (unindent).
+ // Returns the actual number of characters added or removed.
+
+ llassert(pos >= 0);
+ llassert(pos <= getLength() );
+
+ S32 delta_spaces = 0;
+
+ if (spaces >= 0)
+ {
+ // Indent
+ for(S32 i=0; i < spaces; i++)
+ {
+ delta_spaces += addChar(pos, ' ');
+ }
+ }
+ else
+ {
+ // Unindent
+ for(S32 i=0; i < -spaces; i++)
+ {
+ LLWString wtext = getWText();
+ if (wtext[pos] == ' ')
+ {
+ delta_spaces += remove( pos, 1, FALSE );
+ }
+ }
+ }
+
+ return delta_spaces;
}
void LLTextEditor::indentSelectedLines( S32 spaces )
{
- if( hasSelection() )
- {
- LLWString text = getWText();
- S32 left = llmin( mSelectionStart, mSelectionEnd );
- S32 right = left + llabs( mSelectionStart - mSelectionEnd );
- BOOL cursor_on_right = (mSelectionEnd > mSelectionStart);
- S32 cur = left;
-
- // Expand left to start of line
- while( (cur > 0) && (text[cur] != '\n') )
- {
- cur--;
- }
- left = cur;
- if( cur > 0 )
- {
- left++;
- }
-
- // Expand right to end of line
- if( text[right - 1] == '\n' )
- {
- right--;
- }
- else
- {
- while( (text[right] != '\n') && (right <= getLength() ) )
- {
- right++;
- }
- }
-
- // Disabling parsing on the fly to avoid updating text segments
- // until all indentation commands are executed.
- mParseOnTheFly = FALSE;
-
- // Find each start-of-line and indent it
- do
- {
- if( text[cur] == '\n' )
- {
- cur++;
- }
-
- S32 delta_spaces = indentLine( cur, spaces );
- if( delta_spaces > 0 )
- {
- cur += delta_spaces;
- }
- right += delta_spaces;
-
- text = getWText();
-
- // Find the next new line
- while( (cur < right) && (text[cur] != '\n') )
- {
- cur++;
- }
- }
- while( cur < right );
-
- mParseOnTheFly = TRUE;
-
- if( (right < getLength()) && (text[right] == '\n') )
- {
- right++;
- }
-
- // Set the selection and cursor
- if( cursor_on_right )
- {
- mSelectionStart = left;
- mSelectionEnd = right;
- }
- else
- {
- mSelectionStart = right;
- mSelectionEnd = left;
- }
- setCursorPos(mSelectionEnd);
- }
+ if( hasSelection() )
+ {
+ LLWString text = getWText();
+ S32 left = llmin( mSelectionStart, mSelectionEnd );
+ S32 right = left + llabs( mSelectionStart - mSelectionEnd );
+ BOOL cursor_on_right = (mSelectionEnd > mSelectionStart);
+ S32 cur = left;
+
+ // Expand left to start of line
+ while( (cur > 0) && (text[cur] != '\n') )
+ {
+ cur--;
+ }
+ left = cur;
+ if( cur > 0 )
+ {
+ left++;
+ }
+
+ // Expand right to end of line
+ if( text[right - 1] == '\n' )
+ {
+ right--;
+ }
+ else
+ {
+ while( (text[right] != '\n') && (right <= getLength() ) )
+ {
+ right++;
+ }
+ }
+
+ // Disabling parsing on the fly to avoid updating text segments
+ // until all indentation commands are executed.
+ mParseOnTheFly = false;
+
+ // Find each start-of-line and indent it
+ do
+ {
+ if( text[cur] == '\n' )
+ {
+ cur++;
+ }
+
+ S32 delta_spaces = indentLine( cur, spaces );
+ if( delta_spaces > 0 )
+ {
+ cur += delta_spaces;
+ }
+ right += delta_spaces;
+
+ text = getWText();
+
+ // Find the next new line
+ while( (cur < right) && (text[cur] != '\n') )
+ {
+ cur++;
+ }
+ }
+ while( cur < right );
+
+ mParseOnTheFly = true;
+
+ if( (right < getLength()) && (text[right] == '\n') )
+ {
+ right++;
+ }
+
+ // Set the selection and cursor
+ if( cursor_on_right )
+ {
+ mSelectionStart = left;
+ mSelectionEnd = right;
+ }
+ else
+ {
+ mSelectionStart = right;
+ mSelectionEnd = left;
+ }
+ setCursorPos(mSelectionEnd);
+ }
}
//virtual
BOOL LLTextEditor::canSelectAll() const
{
- return TRUE;
+ return TRUE;
}
// virtual
void LLTextEditor::selectAll()
{
- mSelectionStart = getLength();
- mSelectionEnd = 0;
- setCursorPos(mSelectionEnd);
- updatePrimary();
+ mSelectionStart = getLength();
+ mSelectionEnd = 0;
+ setCursorPos(mSelectionEnd);
+ updatePrimary();
}
void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos)
{
- setCursorPos(prev_cursor_pos);
- startSelection();
- setCursorPos(next_cursor_pos);
- endSelection();
+ setCursorPos(prev_cursor_pos);
+ startSelection();
+ setCursorPos(next_cursor_pos);
+ endSelection();
}
void LLTextEditor::insertEmoji(llwchar emoji)
{
- LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL;
- auto styleParams = LLStyle::Params();
- styleParams.font = LLFontGL::getFontEmoji();
- auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this);
- insert(mCursorPos, LLWString(1, emoji), false, segment);
- setCursorPos(mCursorPos + 1);
+ LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL;
+ auto styleParams = LLStyle::Params();
+ styleParams.font = LLFontGL::getFontEmojiLarge();
+ auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this);
+ insert(mCursorPos, LLWString(1, emoji), false, segment);
+ setCursorPos(mCursorPos + 1);
}
void LLTextEditor::handleEmojiCommit(llwchar emoji)
{
- S32 shortCodePos;
- if (LLEmojiHelper::isCursorInEmojiCode(getWText(), mCursorPos, &shortCodePos))
- {
- remove(shortCodePos, mCursorPos - shortCodePos, true);
- setCursorPos(shortCodePos);
+ S32 shortCodePos;
+ if (LLEmojiHelper::isCursorInEmojiCode(getWText(), mCursorPos, &shortCodePos))
+ {
+ remove(shortCodePos, mCursorPos - shortCodePos, true);
+ setCursorPos(shortCodePos);
- insertEmoji(emoji);
- }
+ insertEmoji(emoji);
+ }
}
BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
-
- // set focus first, in case click callbacks want to change it
- // RN: do we really need to have a tab stop?
- if (hasTabStop())
- {
- setFocus( TRUE );
- }
-
- // Let scrollbar have first dibs
- handled = LLTextBase::handleMouseDown(x, y, mask);
-
- if( !handled )
- {
- if (!(mask & MASK_SHIFT))
- {
- deselect();
- }
-
- BOOL start_select = TRUE;
- if( start_select )
- {
- // If we're not scrolling (handled by child), then we're selecting
- if (mask & MASK_SHIFT)
- {
- S32 old_cursor_pos = mCursorPos;
- setCursorAtLocalPos( x, y, true );
-
- if (hasSelection())
- {
- mSelectionEnd = mCursorPos;
- }
- else
- {
- mSelectionStart = old_cursor_pos;
- mSelectionEnd = mCursorPos;
- }
- // assume we're starting a drag select
- mIsSelecting = TRUE;
- }
- else
- {
- setCursorAtLocalPos( x, y, true );
- startSelection();
- }
- }
-
- handled = TRUE;
- }
-
- // Delay cursor flashing
- resetCursorBlink();
-
- if (handled && !gFocusMgr.getMouseCapture())
- {
- gFocusMgr.setMouseCapture( this );
- }
- return handled;
+ BOOL handled = FALSE;
+
+ // set focus first, in case click callbacks want to change it
+ // RN: do we really need to have a tab stop?
+ if (hasTabStop())
+ {
+ setFocus( TRUE );
+ }
+
+ // Let scrollbar have first dibs
+ handled = LLTextBase::handleMouseDown(x, y, mask);
+
+ if( !handled )
+ {
+ if (!(mask & MASK_SHIFT))
+ {
+ deselect();
+ }
+
+ BOOL start_select = TRUE;
+ if( start_select )
+ {
+ // If we're not scrolling (handled by child), then we're selecting
+ if (mask & MASK_SHIFT)
+ {
+ S32 old_cursor_pos = mCursorPos;
+ setCursorAtLocalPos( x, y, true );
+
+ if (hasSelection())
+ {
+ mSelectionEnd = mCursorPos;
+ }
+ else
+ {
+ mSelectionStart = old_cursor_pos;
+ mSelectionEnd = mCursorPos;
+ }
+ // assume we're starting a drag select
+ mIsSelecting = TRUE;
+ }
+ else
+ {
+ setCursorAtLocalPos( x, y, true );
+ startSelection();
+ }
+ }
+
+ handled = TRUE;
+ }
+
+ // Delay cursor flashing
+ resetCursorBlink();
+
+ if (handled && !gFocusMgr.getMouseCapture())
+ {
+ gFocusMgr.setMouseCapture( this );
+ }
+ return handled;
}
BOOL LLTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- if (hasTabStop())
- {
- setFocus(TRUE);
- }
+ if (hasTabStop())
+ {
+ setFocus(TRUE);
+ }
- bool show_menu = false;
+ bool show_menu = false;
- // Prefer editor menu if it has selection. See EXT-6806.
- if (hasSelection())
- {
- S32 click_pos = getDocIndexFromLocalCoord(x, y, FALSE);
- if (click_pos > mSelectionStart && click_pos < mSelectionEnd)
- {
- show_menu = true;
- }
- }
+ // Prefer editor menu if it has selection. See EXT-6806.
+ if (hasSelection())
+ {
+ S32 click_pos = getDocIndexFromLocalCoord(x, y, FALSE);
+ if (click_pos > mSelectionStart && click_pos < mSelectionEnd)
+ {
+ show_menu = true;
+ }
+ }
- // Let segments handle the click, if nothing does, show editor menu
- if (!show_menu && !LLTextBase::handleRightMouseDown(x, y, mask))
- {
- show_menu = true;
- }
+ // Let segments handle the click, if nothing does, show editor menu
+ if (!show_menu && !LLTextBase::handleRightMouseDown(x, y, mask))
+ {
+ show_menu = true;
+ }
- if (show_menu && getShowContextMenu())
- {
- showContextMenu(x, y);
- }
+ if (show_menu && getShowContextMenu())
+ {
+ showContextMenu(x, y);
+ }
- return TRUE;
+ return TRUE;
}
BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
- if (hasTabStop())
- {
- setFocus(TRUE);
- }
+ if (hasTabStop())
+ {
+ setFocus(TRUE);
+ }
- if (!LLTextBase::handleMouseDown(x, y, mask))
- {
- if( canPastePrimary() )
- {
- setCursorAtLocalPos( x, y, true );
- // does not rely on focus being set
- pastePrimary();
- }
- }
- return TRUE;
+ if (!LLTextBase::handleMouseDown(x, y, mask))
+ {
+ if( canPastePrimary() )
+ {
+ setCursorAtLocalPos( x, y, true );
+ // does not rely on focus being set
+ pastePrimary();
+ }
+ }
+ return TRUE;
}
BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
-
- if(hasMouseCapture() )
- {
- if( mIsSelecting )
- {
- if(mScroller)
- {
- mScroller->autoScroll(x, y);
- }
- S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
- S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
- setCursorAtLocalPos( clamped_x, clamped_y, true );
- mSelectionEnd = mCursorPos;
- }
- LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL;
- getWindow()->setCursor(UI_CURSOR_IBEAM);
- handled = TRUE;
- }
-
- if( !handled )
- {
- // Pass to children
- handled = LLTextBase::handleHover(x, y, mask);
- }
-
- if( handled )
- {
- // Delay cursor flashing
- resetCursorBlink();
- }
-
- if( !handled )
- {
- getWindow()->setCursor(UI_CURSOR_IBEAM);
- handled = TRUE;
- }
-
- return handled;
+ BOOL handled = FALSE;
+
+ if(hasMouseCapture() )
+ {
+ if( mIsSelecting )
+ {
+ if(mScroller)
+ {
+ mScroller->autoScroll(x, y);
+ }
+ S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
+ S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
+ setCursorAtLocalPos( clamped_x, clamped_y, true );
+ mSelectionEnd = mCursorPos;
+ }
+ LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (active)" << LL_ENDL;
+ getWindow()->setCursor(UI_CURSOR_IBEAM);
+ handled = TRUE;
+ }
+
+ if( !handled )
+ {
+ // Pass to children
+ handled = LLTextBase::handleHover(x, y, mask);
+ }
+
+ if( handled )
+ {
+ // Delay cursor flashing
+ resetCursorBlink();
+ }
+
+ if( !handled )
+ {
+ getWindow()->setCursor(UI_CURSOR_IBEAM);
+ handled = TRUE;
+ }
+
+ return handled;
}
BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
-
- // if I'm not currently selecting text
- if (!(mIsSelecting && hasMouseCapture()))
- {
- // let text segments handle mouse event
- handled = LLTextBase::handleMouseUp(x, y, mask);
- }
-
- if( !handled )
- {
- if( mIsSelecting )
- {
- if(mScroller)
- {
- mScroller->autoScroll(x, y);
- }
- S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
- S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
- setCursorAtLocalPos( clamped_x, clamped_y, true );
- endSelection();
- }
-
- // take selection to 'primary' clipboard
- updatePrimary();
-
- handled = TRUE;
- }
-
- // Delay cursor flashing
- resetCursorBlink();
-
- if( hasMouseCapture() )
- {
- gFocusMgr.setMouseCapture( NULL );
-
- handled = TRUE;
- }
-
- return handled;
+ BOOL handled = FALSE;
+
+ // if I'm not currently selecting text
+ if (!(mIsSelecting && hasMouseCapture()))
+ {
+ // let text segments handle mouse event
+ handled = LLTextBase::handleMouseUp(x, y, mask);
+ }
+
+ if( !handled )
+ {
+ if( mIsSelecting )
+ {
+ if(mScroller)
+ {
+ mScroller->autoScroll(x, y);
+ }
+ S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
+ S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
+ setCursorAtLocalPos( clamped_x, clamped_y, true );
+ endSelection();
+ }
+
+ // take selection to 'primary' clipboard
+ updatePrimary();
+
+ handled = TRUE;
+ }
+
+ // Delay cursor flashing
+ resetCursorBlink();
+
+ if( hasMouseCapture() )
+ {
+ gFocusMgr.setMouseCapture( NULL );
+
+ handled = TRUE;
+ }
+
+ return handled;
}
BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
+ BOOL handled = FALSE;
- // let scrollbar and text segments have first dibs
- handled = LLTextBase::handleDoubleClick(x, y, mask);
+ // let scrollbar and text segments have first dibs
+ handled = LLTextBase::handleDoubleClick(x, y, mask);
- if( !handled )
- {
- setCursorAtLocalPos( x, y, false );
- deselect();
+ if( !handled )
+ {
+ setCursorAtLocalPos( x, y, false );
+ deselect();
- LLWString text = getWText();
-
- if( LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
- {
- // Select word the cursor is over
- while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord(text[mCursorPos-1]))
- {
- if (!setCursorPos(mCursorPos - 1)) break;
- }
- startSelection();
+ LLWString text = getWText();
- while ((mCursorPos < (S32)text.length()) && LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
- {
- if (!setCursorPos(mCursorPos + 1)) break;
- }
-
- mSelectionEnd = mCursorPos;
- }
- else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) )
- {
- // Select the character the cursor is over
- startSelection();
- setCursorPos(mCursorPos + 1);
- mSelectionEnd = mCursorPos;
- }
+ if( LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
+ {
+ // Select word the cursor is over
+ while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord(text[mCursorPos-1]))
+ {
+ if (!setCursorPos(mCursorPos - 1)) break;
+ }
+ startSelection();
+
+ while ((mCursorPos < (S32)text.length()) && LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
+ {
+ if (!setCursorPos(mCursorPos + 1)) break;
+ }
+
+ mSelectionEnd = mCursorPos;
+ }
+ else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) )
+ {
+ // Select the character the cursor is over
+ startSelection();
+ setCursorPos(mCursorPos + 1);
+ mSelectionEnd = mCursorPos;
+ }
- // We don't want handleMouseUp() to "finish" the selection (and thereby
- // set mSelectionEnd to where the mouse is), so we finish the selection here.
- mIsSelecting = FALSE;
+ // We don't want handleMouseUp() to "finish" the selection (and thereby
+ // set mSelectionEnd to where the mouse is), so we finish the selection here.
+ mIsSelecting = FALSE;
- // delay cursor flashing
- resetCursorBlink();
+ // delay cursor flashing
+ resetCursorBlink();
- // take selection to 'primary' clipboard
- updatePrimary();
+ // take selection to 'primary' clipboard
+ updatePrimary();
- handled = TRUE;
- }
+ handled = TRUE;
+ }
- return handled;
+ return handled;
}
@@ -969,228 +973,232 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
S32 LLTextEditor::execute( TextCmd* cmd )
{
- if (!mReadOnly && mShowEmojiHelper)
- {
- // Any change to our contents should always hide the helper
- LLEmojiHelper::instance().hideHelper(this);
- }
-
- S32 delta = 0;
- if( cmd->execute(this, &delta) )
- {
- // Delete top of undo stack
- undo_stack_t::iterator enditer = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
- std::for_each(mUndoStack.begin(), enditer, DeletePointer());
- mUndoStack.erase(mUndoStack.begin(), enditer);
- // Push the new command is now on the top (front) of the undo stack.
- mUndoStack.push_front(cmd);
- mLastCmd = cmd;
-
- bool need_to_rollback = mPrevalidateFunc
- && !mPrevalidateFunc(getViewModel()->getDisplay());
- if (need_to_rollback)
- {
- // get rid of this last command and clean up undo stack
- undo();
-
- // remove any evidence of this command from redo history
- mUndoStack.pop_front();
- delete cmd;
-
- // failure, nothing changed
- delta = 0;
- }
- }
- else
- {
- // Operation failed, so don't put it on the undo stack.
- delete cmd;
- }
-
- return delta;
+ if (!mReadOnly && mShowEmojiHelper)
+ {
+ // Any change to our contents should always hide the helper
+ LLEmojiHelper::instance().hideHelper(this);
+ }
+
+ S32 delta = 0;
+ if( cmd->execute(this, &delta) )
+ {
+ // Delete top of undo stack
+ undo_stack_t::iterator enditer = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
+ std::for_each(mUndoStack.begin(), enditer, DeletePointer());
+ mUndoStack.erase(mUndoStack.begin(), enditer);
+ // Push the new command is now on the top (front) of the undo stack.
+ mUndoStack.push_front(cmd);
+ mLastCmd = cmd;
+
+ bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(getViewModel()->getDisplay());
+ if (need_to_rollback)
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ mPrevalidator.showLastErrorUsingTimeout();
+
+ // get rid of this last command and clean up undo stack
+ undo();
+
+ // remove any evidence of this command from redo history
+ mUndoStack.pop_front();
+ delete cmd;
+
+ // failure, nothing changed
+ delta = 0;
+ }
+ }
+ else
+ {
+ // Operation failed, so don't put it on the undo stack.
+ delete cmd;
+ }
+
+ return delta;
}
S32 LLTextEditor::insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment)
{
- return execute( new TextCmdInsert( pos, group_with_next_op, wstr, segment ) );
+ return execute( new TextCmdInsert( pos, group_with_next_op, wstr, segment ) );
}
S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op)
{
- S32 end_pos = getEditableIndex(pos + length, true);
- BOOL removedChar = FALSE;
+ S32 end_pos = getEditableIndex(pos + length, true);
+ BOOL removedChar = FALSE;
+
+ segment_vec_t segments_to_remove;
+ // store text segments
+ getSegmentsInRange(segments_to_remove, pos, pos + length, false);
- segment_vec_t segments_to_remove;
- // store text segments
- getSegmentsInRange(segments_to_remove, pos, pos + length, false);
-
- if (pos <= end_pos)
- {
- removedChar = execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) );
- }
+ if (pos <= end_pos)
+ {
+ removedChar = execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) );
+ }
- return removedChar;
+ return removedChar;
}
S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc)
{
- if ((S32)getLength() == pos)
- {
- return addChar(pos, wc);
- }
- else
- {
- return execute(new TextCmdOverwriteChar(pos, FALSE, wc));
- }
+ if ((S32)getLength() == pos)
+ {
+ return addChar(pos, wc);
+ }
+ else
+ {
+ return execute(new TextCmdOverwriteChar(pos, FALSE, wc));
+ }
}
// Remove a single character from the text. Tries to remove
// a pseudo-tab (up to for spaces in a row)
void LLTextEditor::removeCharOrTab()
{
- if (!getEnabled())
- {
- return;
- }
-
- if (mCursorPos > 0)
- {
- S32 chars_to_remove = 1;
-
- LLWString text = getWText();
- if (text[mCursorPos - 1] == ' ')
- {
- // Try to remove a "tab"
- S32 offset = getLineOffsetFromDocIndex(mCursorPos);
- if (offset > 0)
- {
- chars_to_remove = offset % SPACES_PER_TAB;
- if (chars_to_remove == 0)
- {
- chars_to_remove = SPACES_PER_TAB;
- }
-
- for (S32 i = 0; i < chars_to_remove; i++)
- {
- if (text[mCursorPos - i - 1] != ' ')
- {
- // Fewer than a full tab's worth of spaces, so
- // just delete a single character.
- chars_to_remove = 1;
- break;
- }
- }
- }
- }
-
- for (S32 i = 0; i < chars_to_remove; i++)
- {
- setCursorPos(mCursorPos - 1);
- remove(mCursorPos, 1, false);
- }
-
- tryToShowEmojiHelper();
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
+ if (!getEnabled())
+ {
+ return;
+ }
+
+ if (mCursorPos > 0)
+ {
+ S32 chars_to_remove = 1;
+
+ LLWString text = getWText();
+ if (text[mCursorPos - 1] == ' ')
+ {
+ // Try to remove a "tab"
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+ if (offset > 0)
+ {
+ chars_to_remove = offset % SPACES_PER_TAB;
+ if (chars_to_remove == 0)
+ {
+ chars_to_remove = SPACES_PER_TAB;
+ }
+
+ for (S32 i = 0; i < chars_to_remove; i++)
+ {
+ if (text[mCursorPos - i - 1] != ' ')
+ {
+ // Fewer than a full tab's worth of spaces, so
+ // just delete a single character.
+ chars_to_remove = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ for (S32 i = 0; i < chars_to_remove; i++)
+ {
+ setCursorPos(mCursorPos - 1);
+ remove(mCursorPos, 1, false);
+ }
+
+ tryToShowEmojiHelper();
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
}
// Remove a single character from the text
S32 LLTextEditor::removeChar(S32 pos)
{
- return remove(pos, 1, false);
+ return remove(pos, 1, false);
}
void LLTextEditor::removeChar()
{
- if (!getEnabled())
- {
- return;
- }
+ if (!getEnabled())
+ {
+ return;
+ }
- if (mCursorPos > 0)
- {
- setCursorPos(mCursorPos - 1);
- removeChar(mCursorPos);
- tryToShowEmojiHelper();
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
+ if (mCursorPos > 0)
+ {
+ setCursorPos(mCursorPos - 1);
+ removeChar(mCursorPos);
+ tryToShowEmojiHelper();
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
}
// Add a single character to the text
S32 LLTextEditor::addChar(S32 pos, llwchar wc)
{
- if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength)
- {
- make_ui_sound("UISndBadKeystroke");
- return 0;
- }
-
- if (mLastCmd && mLastCmd->canExtend(pos))
- {
- S32 delta = 0;
- if (mPrevalidateFunc)
- {
- // get a copy of current text contents
- LLWString test_string(getViewModel()->getDisplay());
-
- // modify text contents as if this addChar succeeded
- llassert(pos <= (S32)test_string.size());
- test_string.insert(pos, 1, wc);
- if (!mPrevalidateFunc( test_string))
- {
- return 0;
- }
- }
- mLastCmd->extendAndExecute(this, pos, wc, &delta);
-
- return delta;
- }
- else
- {
- return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
- }
+ if ((wstring_utf8_length(getWText()) + wchar_utf8_length(wc)) > mMaxTextByteLength)
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ return 0;
+ }
+
+ if (mLastCmd && mLastCmd->canExtend(pos))
+ {
+ if (mPrevalidator)
+ {
+ // get a copy of current text contents
+ LLWString test_string(getViewModel()->getDisplay());
+
+ // modify text contents as if this addChar succeeded
+ llassert(pos <= (S32)test_string.size());
+ test_string.insert(pos, 1, wc);
+ if (!mPrevalidator.validate(test_string))
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ mPrevalidator.showLastErrorUsingTimeout();
+ return 0;
+ }
+ }
+
+ S32 delta = 0;
+ mLastCmd->extendAndExecute(this, pos, wc, &delta);
+
+ return delta;
+ }
+
+ return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
}
void LLTextEditor::addChar(llwchar wc)
{
- if( !getEnabled() )
- {
- return;
- }
- if( hasSelection() )
- {
- deleteSelection(TRUE);
- }
- else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
- {
- removeChar(mCursorPos);
- }
-
- setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
- tryToShowEmojiHelper();
-
- if (!mReadOnly && mAutoreplaceCallback != NULL)
- {
- // autoreplace the text, if necessary
- S32 replacement_start;
- S32 replacement_length;
- LLWString replacement_string;
- S32 new_cursor_pos = mCursorPos;
- mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, getWText());
-
- if (replacement_length > 0 || !replacement_string.empty())
- {
- remove(replacement_start, replacement_length, true);
- insert(replacement_start, replacement_string, false, LLTextSegmentPtr());
- setCursorPos(new_cursor_pos);
- }
- }
+ if (!getEnabled())
+ {
+ return;
+ }
+
+ if (hasSelection())
+ {
+ deleteSelection(TRUE);
+ }
+ else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
+ {
+ removeChar(mCursorPos);
+ }
+
+ setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
+ tryToShowEmojiHelper();
+
+ if (!mReadOnly && mAutoreplaceCallback != NULL)
+ {
+ // autoreplace the text, if necessary
+ S32 replacement_start;
+ S32 replacement_length;
+ LLWString replacement_string;
+ S32 new_cursor_pos = mCursorPos;
+ mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, getWText());
+
+ if (replacement_length > 0 || !replacement_string.empty())
+ {
+ remove(replacement_start, replacement_length, true);
+ insert(replacement_start, replacement_string, false, LLTextSegmentPtr());
+ setCursorPos(new_cursor_pos);
+ }
+ }
}
void LLTextEditor::showEmojiHelper()
@@ -1226,791 +1234,796 @@ void LLTextEditor::tryToShowEmojiHelper()
void LLTextEditor::addLineBreakChar(BOOL group_together)
{
- if( !getEnabled() )
- {
- return;
- }
- if( hasSelection() )
- {
- deleteSelection(TRUE);
- }
- else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
- {
- removeChar(mCursorPos);
- }
+ if( !getEnabled() )
+ {
+ return;
+ }
+ if( hasSelection() )
+ {
+ deleteSelection(TRUE);
+ }
+ else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
+ {
+ removeChar(mCursorPos);
+ }
+
+ LLStyleConstSP sp(new LLStyle(LLStyle::Params()));
+ LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos);
- LLStyleConstSP sp(new LLStyle(LLStyle::Params()));
- LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos);
+ S32 pos = execute(new TextCmdAddChar(mCursorPos, group_together, '\n', segment));
- S32 pos = execute(new TextCmdAddChar(mCursorPos, group_together, '\n', segment));
-
- setCursorPos(mCursorPos + pos);
+ setCursorPos(mCursorPos + pos);
}
BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask)
{
- BOOL handled = FALSE;
-
- if( mask & MASK_SHIFT )
- {
- handled = TRUE;
-
- switch( key )
- {
- case KEY_LEFT:
- if( 0 < mCursorPos )
- {
- startSelection();
- setCursorPos(mCursorPos - 1);
- if( mask & MASK_CONTROL )
- {
- setCursorPos(prevWordPos(mCursorPos));
- }
- mSelectionEnd = mCursorPos;
- }
- break;
-
- case KEY_RIGHT:
- if( mCursorPos < getLength() )
- {
- startSelection();
- setCursorPos(mCursorPos + 1);
- if( mask & MASK_CONTROL )
- {
- setCursorPos(nextWordPos(mCursorPos));
- }
- mSelectionEnd = mCursorPos;
- }
- break;
-
- case KEY_UP:
- startSelection();
- changeLine( -1 );
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_PAGE_UP:
- startSelection();
- changePage( -1 );
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_HOME:
- startSelection();
- if( mask & MASK_CONTROL )
- {
- setCursorPos(0);
- }
- else
- {
- startOfLine();
- }
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_DOWN:
- startSelection();
- changeLine( 1 );
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_PAGE_DOWN:
- startSelection();
- changePage( 1 );
- mSelectionEnd = mCursorPos;
- break;
-
- case KEY_END:
- startSelection();
- if( mask & MASK_CONTROL )
- {
- setCursorPos(getLength());
- }
- else
- {
- endOfLine();
- }
- mSelectionEnd = mCursorPos;
- break;
-
- default:
- handled = FALSE;
- break;
- }
- }
-
- if( handled )
- {
- // take selection to 'primary' clipboard
- updatePrimary();
- }
-
- return handled;
+ BOOL handled = FALSE;
+
+ if( mask & MASK_SHIFT )
+ {
+ handled = TRUE;
+
+ switch( key )
+ {
+ case KEY_LEFT:
+ if( 0 < mCursorPos )
+ {
+ startSelection();
+ setCursorPos(mCursorPos - 1);
+ if( mask & MASK_CONTROL )
+ {
+ setCursorPos(prevWordPos(mCursorPos));
+ }
+ mSelectionEnd = mCursorPos;
+ }
+ break;
+
+ case KEY_RIGHT:
+ if( mCursorPos < getLength() )
+ {
+ startSelection();
+ setCursorPos(mCursorPos + 1);
+ if( mask & MASK_CONTROL )
+ {
+ setCursorPos(nextWordPos(mCursorPos));
+ }
+ mSelectionEnd = mCursorPos;
+ }
+ break;
+
+ case KEY_UP:
+ startSelection();
+ changeLine( -1 );
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_PAGE_UP:
+ startSelection();
+ changePage( -1 );
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_HOME:
+ startSelection();
+ if( mask & MASK_CONTROL )
+ {
+ setCursorPos(0);
+ }
+ else
+ {
+ startOfLine();
+ }
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_DOWN:
+ startSelection();
+ changeLine( 1 );
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_PAGE_DOWN:
+ startSelection();
+ changePage( 1 );
+ mSelectionEnd = mCursorPos;
+ break;
+
+ case KEY_END:
+ startSelection();
+ if( mask & MASK_CONTROL )
+ {
+ setCursorPos(getLength());
+ }
+ else
+ {
+ endOfLine();
+ }
+ mSelectionEnd = mCursorPos;
+ break;
+
+ default:
+ handled = FALSE;
+ break;
+ }
+ }
+
+ if( handled )
+ {
+ // take selection to 'primary' clipboard
+ updatePrimary();
+ }
+
+ return handled;
}
BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask)
{
- BOOL handled = FALSE;
-
- // Ignore capslock key
- if( MASK_NONE == mask )
- {
- handled = TRUE;
- switch( key )
- {
- case KEY_UP:
- changeLine( -1 );
- break;
-
- case KEY_PAGE_UP:
- changePage( -1 );
- break;
-
- case KEY_HOME:
- startOfLine();
- break;
-
- case KEY_DOWN:
- changeLine( 1 );
- deselect();
- break;
-
- case KEY_PAGE_DOWN:
- changePage( 1 );
- break;
-
- case KEY_END:
- endOfLine();
- break;
-
- case KEY_LEFT:
- if( hasSelection() )
- {
- setCursorPos(llmin( mSelectionStart, mSelectionEnd ));
- }
- else
- {
- if( 0 < mCursorPos )
- {
- setCursorPos(mCursorPos - 1);
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
- }
- break;
-
- case KEY_RIGHT:
- if( hasSelection() )
- {
- setCursorPos(llmax( mSelectionStart, mSelectionEnd ));
- }
- else
- {
- if( mCursorPos < getLength() )
- {
- setCursorPos(mCursorPos + 1);
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
- }
- break;
-
- default:
- handled = FALSE;
- break;
- }
- }
-
- if (handled)
- {
- deselect();
- }
-
- return handled;
+ BOOL handled = FALSE;
+
+ // Ignore capslock key
+ if( MASK_NONE == mask )
+ {
+ handled = TRUE;
+ switch( key )
+ {
+ case KEY_UP:
+ changeLine( -1 );
+ break;
+
+ case KEY_PAGE_UP:
+ changePage( -1 );
+ break;
+
+ case KEY_HOME:
+ startOfLine();
+ break;
+
+ case KEY_DOWN:
+ changeLine( 1 );
+ deselect();
+ break;
+
+ case KEY_PAGE_DOWN:
+ changePage( 1 );
+ break;
+
+ case KEY_END:
+ endOfLine();
+ break;
+
+ case KEY_LEFT:
+ if( hasSelection() )
+ {
+ setCursorPos(llmin( mSelectionStart, mSelectionEnd ));
+ }
+ else
+ {
+ if( 0 < mCursorPos )
+ {
+ setCursorPos(mCursorPos - 1);
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
+ }
+ break;
+
+ case KEY_RIGHT:
+ if( hasSelection() )
+ {
+ setCursorPos(llmax( mSelectionStart, mSelectionEnd ));
+ }
+ else
+ {
+ if( mCursorPos < getLength() )
+ {
+ setCursorPos(mCursorPos + 1);
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
+ }
+ break;
+
+ default:
+ handled = FALSE;
+ break;
+ }
+ }
+
+ if (handled)
+ {
+ deselect();
+ }
+
+ return handled;
}
void LLTextEditor::deleteSelection(BOOL group_with_next_op )
{
- if( getEnabled() && hasSelection() )
- {
- S32 pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
-
- remove( pos, length, group_with_next_op );
+ if( getEnabled() && hasSelection() )
+ {
+ S32 pos = llmin( mSelectionStart, mSelectionEnd );
+ S32 length = llabs( mSelectionStart - mSelectionEnd );
- deselect();
- setCursorPos(pos);
- }
+ remove( pos, length, group_with_next_op );
+
+ deselect();
+ setCursorPos(pos);
+ }
}
// virtual
BOOL LLTextEditor::canCut() const
{
- return !mReadOnly && hasSelection();
+ return !mReadOnly && hasSelection();
}
// cut selection to clipboard
void LLTextEditor::cut()
{
- if( !canCut() )
- {
- return;
- }
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
- LLClipboard::instance().copyToClipboard( getWText(), left_pos, length);
- deleteSelection( FALSE );
+ if( !canCut() )
+ {
+ return;
+ }
+ S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
+ S32 length = llabs( mSelectionStart - mSelectionEnd );
+ LLClipboard::instance().copyToClipboard( getWText(), left_pos, length);
+ deleteSelection( FALSE );
- onKeyStroke();
+ onKeyStroke();
}
BOOL LLTextEditor::canCopy() const
{
- return hasSelection();
+ return hasSelection();
}
// copy selection to clipboard
void LLTextEditor::copy()
{
- if( !canCopy() )
- {
- return;
- }
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
- LLClipboard::instance().copyToClipboard(getWText(), left_pos, length);
+ if( !canCopy() )
+ {
+ return;
+ }
+ S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
+ S32 length = llabs( mSelectionStart - mSelectionEnd );
+ LLClipboard::instance().copyToClipboard(getWText(), left_pos, length);
}
BOOL LLTextEditor::canPaste() const
{
- return !mReadOnly && LLClipboard::instance().isTextAvailable();
+ return !mReadOnly && LLClipboard::instance().isTextAvailable();
}
// paste from clipboard
void LLTextEditor::paste()
{
- bool is_primary = false;
- pasteHelper(is_primary);
+ bool is_primary = false;
+ pasteHelper(is_primary);
}
// paste from primary
void LLTextEditor::pastePrimary()
{
- bool is_primary = true;
- pasteHelper(is_primary);
+ bool is_primary = true;
+ pasteHelper(is_primary);
}
// paste from primary (itsprimary==true) or clipboard (itsprimary==false)
void LLTextEditor::pasteHelper(bool is_primary)
{
- mParseOnTheFly = FALSE;
- bool can_paste_it;
- if (is_primary)
- {
- can_paste_it = canPastePrimary();
- }
- else
- {
- can_paste_it = canPaste();
- }
+ struct BoolReset
+ {
+ BoolReset(bool& value) : mValuePtr(&value) { *mValuePtr = false; }
+ ~BoolReset() { *mValuePtr = true; }
+ bool* mValuePtr;
+ } reset(mParseOnTheFly);
- if (!can_paste_it)
- {
- return;
- }
+ bool can_paste_it;
+ if (is_primary)
+ {
+ can_paste_it = canPastePrimary();
+ }
+ else
+ {
+ can_paste_it = canPaste();
+ }
- LLWString paste;
- LLClipboard::instance().pasteFromClipboard(paste, is_primary);
+ if (!can_paste_it)
+ {
+ return;
+ }
- if (paste.empty())
- {
- return;
- }
+ LLWString paste;
+ LLClipboard::instance().pasteFromClipboard(paste, is_primary);
- // Delete any selected characters (the paste replaces them)
- if( (!is_primary) && hasSelection() )
- {
- deleteSelection(TRUE);
- }
+ if (paste.empty())
+ {
+ return;
+ }
+
+ // Delete any selected characters (the paste replaces them)
+ if( (!is_primary) && hasSelection() )
+ {
+ deleteSelection(TRUE);
+ }
- // Clean up string (replace tabs and remove characters that our fonts don't support).
- LLWString clean_string(paste);
- cleanStringForPaste(clean_string);
+ // Clean up string (replace tabs and remove characters that our fonts don't support).
+ LLWString clean_string(paste);
+ cleanStringForPaste(clean_string);
- // Insert the new text into the existing text.
+ // Insert the new text into the existing text.
- //paste text with linebreaks.
- pasteTextWithLinebreaks(clean_string);
+ //paste text with linebreaks.
+ pasteTextWithLinebreaks(clean_string);
- deselect();
+ deselect();
- onKeyStroke();
- mParseOnTheFly = TRUE;
+ onKeyStroke();
}
// Clean up string (replace tabs and remove characters that our fonts don't support).
void LLTextEditor::cleanStringForPaste(LLWString & clean_string)
{
- std::string clean_string_utf = wstring_to_utf8str(clean_string);
- std::replace( clean_string_utf.begin(), clean_string_utf.end(), '\r', '\n');
- clean_string = utf8str_to_wstring(clean_string_utf);
-
- LLWStringUtil::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB);
- if( mAllowEmbeddedItems )
- {
- const llwchar LF = 10;
- S32 len = clean_string.length();
- for( S32 i = 0; i < len; i++ )
- {
- llwchar wc = clean_string[i];
- if( (wc < LLFontFreetype::FIRST_CHAR) && (wc != LF) )
- {
- clean_string[i] = LL_UNKNOWN_CHAR;
- }
- else if (wc >= FIRST_EMBEDDED_CHAR && wc <= LAST_EMBEDDED_CHAR)
- {
- clean_string[i] = pasteEmbeddedItem(wc);
- }
- }
- }
+ std::string clean_string_utf = wstring_to_utf8str(clean_string);
+ std::replace( clean_string_utf.begin(), clean_string_utf.end(), '\r', '\n');
+ clean_string = utf8str_to_wstring(clean_string_utf);
+
+ LLWStringUtil::replaceTabsWithSpaces(clean_string, SPACES_PER_TAB);
+ if( mAllowEmbeddedItems )
+ {
+ const llwchar LF = 10;
+ S32 len = clean_string.length();
+ for( S32 i = 0; i < len; i++ )
+ {
+ llwchar wc = clean_string[i];
+ if( (wc < LLFontFreetype::FIRST_CHAR) && (wc != LF) )
+ {
+ clean_string[i] = LL_UNKNOWN_CHAR;
+ }
+ else if (wc >= FIRST_EMBEDDED_CHAR && wc <= LAST_EMBEDDED_CHAR)
+ {
+ clean_string[i] = pasteEmbeddedItem(wc);
+ }
+ }
+ }
}
void LLTextEditor::pasteTextWithLinebreaks(LLWString & clean_string)
{
- std::basic_string<llwchar>::size_type start = 0;
- std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start);
-
- while((pos != -1) && (pos != clean_string.length() -1))
- {
- if(pos!=start)
- {
- std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,pos-start);
- setCursorPos(mCursorPos + insert(mCursorPos, str, TRUE, LLTextSegmentPtr()));
- }
- addLineBreakChar(TRUE); // Add a line break and group with the next addition.
-
- start = pos+1;
- pos = clean_string.find('\n',start);
- }
-
- if (pos != start)
- {
- std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start);
- setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
- }
- else
- {
- addLineBreakChar(FALSE); // Add a line break and end the grouping.
- }
+ std::basic_string<llwchar>::size_type start = 0;
+ std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start);
+
+ while((pos != -1) && (pos != clean_string.length() -1))
+ {
+ if(pos!=start)
+ {
+ std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,pos-start);
+ setCursorPos(mCursorPos + insert(mCursorPos, str, TRUE, LLTextSegmentPtr()));
+ }
+ addLineBreakChar(TRUE); // Add a line break and group with the next addition.
+
+ start = pos+1;
+ pos = clean_string.find('\n',start);
+ }
+
+ if (pos != start)
+ {
+ std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start);
+ setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr()));
+ }
+ else
+ {
+ addLineBreakChar(FALSE); // Add a line break and end the grouping.
+ }
}
// copy selection to primary
void LLTextEditor::copyPrimary()
{
- if( !canCopy() )
- {
- return;
- }
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
- LLClipboard::instance().copyToClipboard(getWText(), left_pos, length, true);
+ if( !canCopy() )
+ {
+ return;
+ }
+ S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
+ S32 length = llabs( mSelectionStart - mSelectionEnd );
+ LLClipboard::instance().copyToClipboard(getWText(), left_pos, length, true);
}
BOOL LLTextEditor::canPastePrimary() const
{
- return !mReadOnly && LLClipboard::instance().isTextAvailable(true);
+ return !mReadOnly && LLClipboard::instance().isTextAvailable(true);
}
void LLTextEditor::updatePrimary()
{
- if (canCopy())
- {
- copyPrimary();
- }
-}
-
-BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask)
-{
- BOOL handled = FALSE;
-
- if( mask & MASK_CONTROL )
- {
- handled = TRUE;
-
- switch( key )
- {
- case KEY_HOME:
- if( mask & MASK_SHIFT )
- {
- startSelection();
- setCursorPos(0);
- mSelectionEnd = mCursorPos;
- }
- else
- {
- // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
- // all move the cursor as if clicking, so should deselect.
- deselect();
- startOfDoc();
- }
- break;
-
- case KEY_END:
- {
- if( mask & MASK_SHIFT )
- {
- startSelection();
- }
- else
- {
- // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
- // all move the cursor as if clicking, so should deselect.
- deselect();
- }
- endOfDoc();
- if( mask & MASK_SHIFT )
- {
- mSelectionEnd = mCursorPos;
- }
- break;
- }
-
- case KEY_RIGHT:
- if( mCursorPos < getLength() )
- {
- // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
- // all move the cursor as if clicking, so should deselect.
- deselect();
-
- setCursorPos(nextWordPos(mCursorPos + 1));
- }
- break;
-
-
- case KEY_LEFT:
- if( mCursorPos > 0 )
- {
- // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
- // all move the cursor as if clicking, so should deselect.
- deselect();
-
- setCursorPos(prevWordPos(mCursorPos - 1));
- }
- break;
-
- default:
- handled = FALSE;
- break;
- }
- }
-
- if (handled && !gFocusMgr.getMouseCapture())
- {
- updatePrimary();
- }
-
- return handled;
-}
-
-
-BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask)
- {
- BOOL handled = TRUE;
-
- if (mReadOnly) return FALSE;
-
- switch( key )
- {
- case KEY_INSERT:
- if (mask == MASK_NONE)
- {
- gKeyboard->toggleInsertMode();
- }
- break;
-
- case KEY_BACKSPACE:
- if( hasSelection() )
- {
- deleteSelection(FALSE);
- }
- else
- if( 0 < mCursorPos )
- {
- removeCharOrTab();
- }
- else
- {
- LLUI::getInstance()->reportBadKeystroke();
- }
- break;
-
-
- case KEY_RETURN:
- if (mask == MASK_NONE)
- {
- if( hasSelection() && !mKeepSelectionOnReturn )
- {
- deleteSelection(FALSE);
- }
- if (mAutoIndent)
- {
- autoIndent();
- }
- }
- else
- {
- handled = FALSE;
- break;
- }
- break;
-
- case KEY_TAB:
- if (mask & MASK_CONTROL)
- {
- handled = FALSE;
- break;
- }
- if( hasSelection() && selectionContainsLineBreaks() )
- {
- indentSelectedLines( (mask & MASK_SHIFT) ? -SPACES_PER_TAB : SPACES_PER_TAB );
- }
- else
- {
- if( hasSelection() )
- {
- deleteSelection(FALSE);
- }
-
- S32 offset = getLineOffsetFromDocIndex(mCursorPos);
-
- S32 spaces_needed = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
- for( S32 i=0; i < spaces_needed; i++ )
- {
- addChar( ' ' );
- }
- }
- break;
-
- default:
- handled = FALSE;
- break;
- }
-
- if (handled)
- {
- onKeyStroke();
- }
- return handled;
+ if (canCopy())
+ {
+ copyPrimary();
+ }
}
-
-void LLTextEditor::unindentLineBeforeCloseBrace()
+BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask)
{
- if( mCursorPos >= 1 )
- {
- LLWString text = getWText();
- if( ' ' == text[ mCursorPos - 1 ] )
- {
- S32 line = getLineNumFromDocIndex(mCursorPos, false);
- S32 line_start = getLineStart(line);
+ BOOL handled = FALSE;
+
+ if( mask & MASK_CONTROL )
+ {
+ handled = TRUE;
+
+ switch( key )
+ {
+ case KEY_HOME:
+ if( mask & MASK_SHIFT )
+ {
+ startSelection();
+ setCursorPos(0);
+ mSelectionEnd = mCursorPos;
+ }
+ else
+ {
+ // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
+ // all move the cursor as if clicking, so should deselect.
+ deselect();
+ startOfDoc();
+ }
+ break;
+
+ case KEY_END:
+ {
+ if( mask & MASK_SHIFT )
+ {
+ startSelection();
+ }
+ else
+ {
+ // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
+ // all move the cursor as if clicking, so should deselect.
+ deselect();
+ }
+ endOfDoc();
+ if( mask & MASK_SHIFT )
+ {
+ mSelectionEnd = mCursorPos;
+ }
+ break;
+ }
+
+ case KEY_RIGHT:
+ if( mCursorPos < getLength() )
+ {
+ // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
+ // all move the cursor as if clicking, so should deselect.
+ deselect();
+
+ setCursorPos(nextWordPos(mCursorPos + 1));
+ }
+ break;
+
+
+ case KEY_LEFT:
+ if( mCursorPos > 0 )
+ {
+ // Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
+ // all move the cursor as if clicking, so should deselect.
+ deselect();
+
+ setCursorPos(prevWordPos(mCursorPos - 1));
+ }
+ break;
+
+ default:
+ handled = FALSE;
+ break;
+ }
+ }
+
+ if (handled && !gFocusMgr.getMouseCapture())
+ {
+ updatePrimary();
+ }
+
+ return handled;
+}
+
+
+BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask)
+ {
+ BOOL handled = TRUE;
+
+ if (mReadOnly) return FALSE;
+
+ switch( key )
+ {
+ case KEY_INSERT:
+ if (mask == MASK_NONE)
+ {
+ gKeyboard->toggleInsertMode();
+ }
+ break;
+
+ case KEY_BACKSPACE:
+ if( hasSelection() )
+ {
+ deleteSelection(FALSE);
+ }
+ else
+ if( 0 < mCursorPos )
+ {
+ removeCharOrTab();
+ }
+ else
+ {
+ LLUI::getInstance()->reportBadKeystroke();
+ }
+ break;
+
+
+ case KEY_RETURN:
+ if (mask == MASK_NONE)
+ {
+ if( hasSelection() && !mKeepSelectionOnReturn )
+ {
+ deleteSelection(FALSE);
+ }
+ if (mAutoIndent)
+ {
+ autoIndent();
+ }
+ }
+ else
+ {
+ handled = FALSE;
+ break;
+ }
+ break;
+
+ case KEY_TAB:
+ if (mask & MASK_CONTROL)
+ {
+ handled = FALSE;
+ break;
+ }
+ if( hasSelection() && selectionContainsLineBreaks() )
+ {
+ indentSelectedLines( (mask & MASK_SHIFT) ? -SPACES_PER_TAB : SPACES_PER_TAB );
+ }
+ else
+ {
+ if( hasSelection() )
+ {
+ deleteSelection(FALSE);
+ }
+
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+
+ S32 spaces_needed = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
+ for( S32 i=0; i < spaces_needed; i++ )
+ {
+ addChar( ' ' );
+ }
+ }
+ break;
- // Jump over spaces in the current line
- while ((' ' == text[line_start]) && (line_start < mCursorPos))
- {
- line_start++;
- }
+ default:
+ handled = FALSE;
+ break;
+ }
- // Make sure there is nothing but ' ' before the Brace we are unindenting
- if (line_start == mCursorPos)
- {
- removeCharOrTab();
- }
- }
- }
+ if (handled)
+ {
+ onKeyStroke();
+ }
+ return handled;
+}
+
+
+void LLTextEditor::unindentLineBeforeCloseBrace()
+{
+ if( mCursorPos >= 1 )
+ {
+ LLWString text = getWText();
+ if( ' ' == text[ mCursorPos - 1 ] )
+ {
+ S32 line = getLineNumFromDocIndex(mCursorPos, false);
+ S32 line_start = getLineStart(line);
+
+ // Jump over spaces in the current line
+ while ((' ' == text[line_start]) && (line_start < mCursorPos))
+ {
+ line_start++;
+ }
+
+ // Make sure there is nothing but ' ' before the Brace we are unindenting
+ if (line_start == mCursorPos)
+ {
+ removeCharOrTab();
+ }
+ }
+ }
}
BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
{
- BOOL handled = FALSE;
-
- // Special case for TAB. If want to move to next field, report
- // not handled and let the parent take care of field movement.
- if (KEY_TAB == key && mTabsToNextField)
- {
- return FALSE;
- }
-
- if (mReadOnly && mScroller)
- {
- handled = (mScroller && mScroller->handleKeyHere( key, mask ))
- || handleSelectionKey(key, mask)
- || handleControlKey(key, mask);
- }
- else
- {
- if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask))
- {
- return TRUE;
- }
-
- if (mEnableTooltipPaste &&
- LLToolTipMgr::instance().toolTipVisible() &&
+ BOOL handled = FALSE;
+
+ // Special case for TAB. If want to move to next field, report
+ // not handled and let the parent take care of field movement.
+ if (KEY_TAB == key && mTabsToNextField)
+ {
+ return FALSE;
+ }
+
+ if (mReadOnly && mScroller)
+ {
+ handled = (mScroller && mScroller->handleKeyHere( key, mask ))
+ || handleSelectionKey(key, mask)
+ || handleControlKey(key, mask);
+ }
+ else
+ {
+ if (!mReadOnly && mShowEmojiHelper && LLEmojiHelper::instance().handleKey(this, key, mask))
+ {
+ return TRUE;
+ }
+
+ if (mEnableTooltipPaste &&
+ LLToolTipMgr::instance().toolTipVisible() &&
LLToolTipMgr::instance().isTooltipPastable() &&
- KEY_TAB == key)
- { // Paste the first line of a tooltip into the editor
- std::string message;
- LLToolTipMgr::instance().getToolTipMessage(message);
- LLWString tool_tip_text(utf8str_to_wstring(message));
-
- if (tool_tip_text.size() > 0)
- {
- // Delete any selected characters (the tooltip text replaces them)
- if(hasSelection())
- {
- deleteSelection(TRUE);
- }
-
- std::basic_string<llwchar>::size_type pos = tool_tip_text.find('\n',0);
- if (pos != -1)
- { // Extract the first line of the tooltip
- tool_tip_text = std::basic_string<llwchar>(tool_tip_text, 0, pos);
- }
-
- // Add the text
- cleanStringForPaste(tool_tip_text);
- pasteTextWithLinebreaks(tool_tip_text);
- handled = TRUE;
- }
- }
- else
- { // Normal key handling
- handled = handleNavigationKey( key, mask )
- || handleSelectionKey(key, mask)
- || handleControlKey(key, mask)
- || handleSpecialKey(key, mask);
- }
- }
-
- if( handled )
- {
- resetCursorBlink();
- needsScroll();
-
- if (mShowEmojiHelper)
- {
- // Dismiss the helper whenever we handled a key that it didn't
- LLEmojiHelper::instance().hideHelper(this);
- }
- }
-
- return handled;
+ KEY_TAB == key)
+ { // Paste the first line of a tooltip into the editor
+ std::string message;
+ LLToolTipMgr::instance().getToolTipMessage(message);
+ LLWString tool_tip_text(utf8str_to_wstring(message));
+
+ if (tool_tip_text.size() > 0)
+ {
+ // Delete any selected characters (the tooltip text replaces them)
+ if(hasSelection())
+ {
+ deleteSelection(TRUE);
+ }
+
+ std::basic_string<llwchar>::size_type pos = tool_tip_text.find('\n',0);
+ if (pos != -1)
+ { // Extract the first line of the tooltip
+ tool_tip_text = std::basic_string<llwchar>(tool_tip_text, 0, pos);
+ }
+
+ // Add the text
+ cleanStringForPaste(tool_tip_text);
+ pasteTextWithLinebreaks(tool_tip_text);
+ handled = TRUE;
+ }
+ }
+ else
+ { // Normal key handling
+ handled = handleNavigationKey( key, mask )
+ || handleSelectionKey(key, mask)
+ || handleControlKey(key, mask)
+ || handleSpecialKey(key, mask);
+ }
+ }
+
+ if( handled )
+ {
+ resetCursorBlink();
+ needsScroll();
+
+ if (mShowEmojiHelper)
+ {
+ // Dismiss the helper whenever we handled a key that it didn't
+ LLEmojiHelper::instance().hideHelper(this);
+ }
+ }
+
+ return handled;
}
BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
{
- if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL
- {
- return FALSE;
- }
+ if ((uni_char < 0x20) || (uni_char == 0x7F)) // Control character or DEL
+ {
+ return FALSE;
+ }
- BOOL handled = FALSE;
+ BOOL handled = FALSE;
- // Handle most keys only if the text editor is writeable.
- if( !mReadOnly )
- {
+ // Handle most keys only if the text editor is writeable.
+ if( !mReadOnly )
+ {
if (mShowEmojiHelper && uni_char < 0x80 && LLEmojiHelper::instance().handleKey(this, (KEY)uni_char, MASK_NONE))
{
return TRUE;
}
if( mAutoIndent && '}' == uni_char )
- {
- unindentLineBeforeCloseBrace();
- }
+ {
+ unindentLineBeforeCloseBrace();
+ }
- // TODO: KLW Add auto show of tool tip on (
- addChar( uni_char );
+ // TODO: KLW Add auto show of tool tip on (
+ addChar( uni_char );
- // Keys that add characters temporarily hide the cursor
- getWindow()->hideCursorUntilMouseMove();
+ // Keys that add characters temporarily hide the cursor
+ getWindow()->hideCursorUntilMouseMove();
- handled = TRUE;
- }
+ handled = TRUE;
+ }
- if( handled )
- {
- resetCursorBlink();
+ if( handled )
+ {
+ resetCursorBlink();
- // Most keystrokes will make the selection box go away, but not all will.
- deselect();
+ // Most keystrokes will make the selection box go away, but not all will.
+ deselect();
- onKeyStroke();
- }
+ onKeyStroke();
+ }
- return handled;
+ return handled;
}
// virtual
BOOL LLTextEditor::canDoDelete() const
{
- return !mReadOnly && ( !mPassDelete || ( hasSelection() || (mCursorPos < getLength())) );
+ return !mReadOnly && ( !mPassDelete || ( hasSelection() || (mCursorPos < getLength())) );
}
void LLTextEditor::doDelete()
{
- if( !canDoDelete() )
- {
- return;
- }
- if( hasSelection() )
- {
- deleteSelection(FALSE);
- }
- else
- if( mCursorPos < getLength() )
- {
- S32 i;
- S32 chars_to_remove = 1;
- LLWString text = getWText();
- if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) )
- {
- // Try to remove a full tab's worth of spaces
- S32 offset = getLineOffsetFromDocIndex(mCursorPos);
- chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
- if( chars_to_remove == 0 )
- {
- chars_to_remove = SPACES_PER_TAB;
- }
-
- for( i = 0; i < chars_to_remove; i++ )
- {
- if( text[mCursorPos + i] != ' ' )
- {
- chars_to_remove = 1;
- break;
- }
- }
- }
-
- for( i = 0; i < chars_to_remove; i++ )
- {
- setCursorPos(mCursorPos + 1);
- removeChar();
- }
-
- }
-
- onKeyStroke();
+ if( !canDoDelete() )
+ {
+ return;
+ }
+ if( hasSelection() )
+ {
+ deleteSelection(FALSE);
+ }
+ else
+ if( mCursorPos < getLength() )
+ {
+ S32 i;
+ S32 chars_to_remove = 1;
+ LLWString text = getWText();
+ if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) )
+ {
+ // Try to remove a full tab's worth of spaces
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+ chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
+ if( chars_to_remove == 0 )
+ {
+ chars_to_remove = SPACES_PER_TAB;
+ }
+
+ for( i = 0; i < chars_to_remove; i++ )
+ {
+ if( text[mCursorPos + i] != ' ' )
+ {
+ chars_to_remove = 1;
+ break;
+ }
+ }
+ }
+
+ for( i = 0; i < chars_to_remove; i++ )
+ {
+ setCursorPos(mCursorPos + 1);
+ removeChar();
+ }
+
+ }
+
+ onKeyStroke();
}
//----------------------------------------------------------------------------
@@ -2018,624 +2031,624 @@ void LLTextEditor::doDelete()
void LLTextEditor::blockUndo()
{
- mBaseDocIsPristine = FALSE;
- mLastCmd = NULL;
- std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
- mUndoStack.clear();
+ mBaseDocIsPristine = FALSE;
+ mLastCmd = NULL;
+ std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
+ mUndoStack.clear();
}
// virtual
BOOL LLTextEditor::canUndo() const
{
- return !mReadOnly && mLastCmd != NULL;
+ return !mReadOnly && mLastCmd != NULL;
}
void LLTextEditor::undo()
{
- if( !canUndo() )
- {
- return;
- }
- deselect();
- S32 pos = 0;
- do
- {
- pos = mLastCmd->undo(this);
- undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
- if (iter != mUndoStack.end())
- ++iter;
- if (iter != mUndoStack.end())
- mLastCmd = *iter;
- else
- mLastCmd = NULL;
+ if( !canUndo() )
+ {
+ return;
+ }
+ deselect();
+ S32 pos = 0;
+ do
+ {
+ pos = mLastCmd->undo(this);
+ undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
+ if (iter != mUndoStack.end())
+ ++iter;
+ if (iter != mUndoStack.end())
+ mLastCmd = *iter;
+ else
+ mLastCmd = NULL;
- } while( mLastCmd && mLastCmd->groupWithNext() );
+ } while( mLastCmd && mLastCmd->groupWithNext() );
- setCursorPos(pos);
+ setCursorPos(pos);
- onKeyStroke();
+ onKeyStroke();
}
BOOL LLTextEditor::canRedo() const
{
- return !mReadOnly && (mUndoStack.size() > 0) && (mLastCmd != mUndoStack.front());
+ return !mReadOnly && (mUndoStack.size() > 0) && (mLastCmd != mUndoStack.front());
}
void LLTextEditor::redo()
{
- if( !canRedo() )
- {
- return;
- }
- deselect();
- S32 pos = 0;
- do
- {
- if( !mLastCmd )
- {
- mLastCmd = mUndoStack.back();
- }
- else
- {
- undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
- if (iter != mUndoStack.begin())
- mLastCmd = *(--iter);
- else
- mLastCmd = NULL;
- }
-
- if( mLastCmd )
- {
- pos = mLastCmd->redo(this);
- }
- } while(
- mLastCmd &&
- mLastCmd->groupWithNext() &&
- (mLastCmd != mUndoStack.front()) );
-
- setCursorPos(pos);
-
- onKeyStroke();
+ if( !canRedo() )
+ {
+ return;
+ }
+ deselect();
+ S32 pos = 0;
+ do
+ {
+ if( !mLastCmd )
+ {
+ mLastCmd = mUndoStack.back();
+ }
+ else
+ {
+ undo_stack_t::iterator iter = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
+ if (iter != mUndoStack.begin())
+ mLastCmd = *(--iter);
+ else
+ mLastCmd = NULL;
+ }
+
+ if( mLastCmd )
+ {
+ pos = mLastCmd->redo(this);
+ }
+ } while(
+ mLastCmd &&
+ mLastCmd->groupWithNext() &&
+ (mLastCmd != mUndoStack.front()) );
+
+ setCursorPos(pos);
+
+ onKeyStroke();
}
void LLTextEditor::onFocusReceived()
{
- LLTextBase::onFocusReceived();
- updateAllowingLanguageInput();
+ LLTextBase::onFocusReceived();
+ updateAllowingLanguageInput();
}
void LLTextEditor::focusLostHelper()
{
- updateAllowingLanguageInput();
+ updateAllowingLanguageInput();
- // Route menu back to the default
- if( gEditMenuHandler == this )
- {
- gEditMenuHandler = NULL;
- }
+ // Route menu back to the default
+ if( gEditMenuHandler == this )
+ {
+ gEditMenuHandler = NULL;
+ }
- if (mCommitOnFocusLost)
- {
- onCommit();
- }
+ if (mCommitOnFocusLost)
+ {
+ onCommit();
+ }
- // Make sure cursor is shown again
- getWindow()->showCursorFromMouseMove();
+ // Make sure cursor is shown again
+ getWindow()->showCursorFromMouseMove();
}
void LLTextEditor::onFocusLost()
{
- focusLostHelper();
- LLTextBase::onFocusLost();
+ focusLostHelper();
+ LLTextBase::onFocusLost();
}
void LLTextEditor::onCommit()
{
- setControlValue(getValue());
- LLTextBase::onCommit();
+ setControlValue(getValue());
+ LLTextBase::onCommit();
}
void LLTextEditor::setEnabled(BOOL enabled)
{
- // just treat enabled as read-only flag
- bool read_only = !enabled;
- if (read_only != mReadOnly)
- {
- //mReadOnly = read_only;
- LLTextBase::setReadOnly(read_only);
- updateSegments();
- updateAllowingLanguageInput();
- }
+ // just treat enabled as read-only flag
+ bool read_only = !enabled;
+ if (read_only != mReadOnly)
+ {
+ //mReadOnly = read_only;
+ LLTextBase::setReadOnly(read_only);
+ updateSegments();
+ updateAllowingLanguageInput();
+ }
}
void LLTextEditor::showContextMenu(S32 x, S32 y)
{
- LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
- if (!menu)
- {
- llassert(LLMenuGL::sMenuContainer != NULL);
- menu = LLUICtrlFactory::createFromFile<LLContextMenu>("menu_text_editor.xml",
- LLMenuGL::sMenuContainer,
- LLMenuHolderGL::child_registry_t::instance());
+ LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
+ if (!menu)
+ {
+ llassert(LLMenuGL::sMenuContainer != NULL);
+ menu = LLUICtrlFactory::createFromFile<LLContextMenu>("menu_text_editor.xml",
+ LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
if(!menu)
{
LL_WARNS() << "Failed to create menu for LLTextEditor: " << getName() << LL_ENDL;
return;
}
- mContextMenuHandle = menu->getHandle();
- }
-
- // Route menu to this class
- // previously this was done in ::handleRightMoseDown:
- //if(hasTabStop())
- // setFocus(TRUE) - why? weird...
- // and then inside setFocus
- // ....
- // gEditMenuHandler = this;
- // ....
- // but this didn't work in all cases and just weird...
- //why not here?
- // (all this was done for EXT-4443)
-
- gEditMenuHandler = this;
-
- S32 screen_x, screen_y;
- localPointToScreen(x, y, &screen_x, &screen_y);
-
- setCursorAtLocalPos(x, y, false);
- if (hasSelection())
- {
- if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) )
- {
- deselect();
- }
- else
- {
- setCursorPos(llmax(mSelectionStart, mSelectionEnd));
- }
- }
-
- bool use_spellcheck = getSpellCheck(), is_misspelled = false;
- if (use_spellcheck)
- {
- mSuggestionList.clear();
-
- // If the cursor is on a misspelled word, retrieve suggestions for it
- std::string misspelled_word = getMisspelledWord(mCursorPos);
- if ((is_misspelled = !misspelled_word.empty()) == true)
- {
- LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList);
- }
- }
-
- menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty()));
- menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled));
- menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled));
- menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled));
- menu->show(screen_x, screen_y, this);
+ mContextMenuHandle = menu->getHandle();
+ }
+
+ // Route menu to this class
+ // previously this was done in ::handleRightMoseDown:
+ //if(hasTabStop())
+ // setFocus(TRUE) - why? weird...
+ // and then inside setFocus
+ // ....
+ // gEditMenuHandler = this;
+ // ....
+ // but this didn't work in all cases and just weird...
+ //why not here?
+ // (all this was done for EXT-4443)
+
+ gEditMenuHandler = this;
+
+ S32 screen_x, screen_y;
+ localPointToScreen(x, y, &screen_x, &screen_y);
+
+ setCursorAtLocalPos(x, y, false);
+ if (hasSelection())
+ {
+ if ( (mCursorPos < llmin(mSelectionStart, mSelectionEnd)) || (mCursorPos > llmax(mSelectionStart, mSelectionEnd)) )
+ {
+ deselect();
+ }
+ else
+ {
+ setCursorPos(llmax(mSelectionStart, mSelectionEnd));
+ }
+ }
+
+ bool use_spellcheck = getSpellCheck(), is_misspelled = false;
+ if (use_spellcheck)
+ {
+ mSuggestionList.clear();
+
+ // If the cursor is on a misspelled word, retrieve suggestions for it
+ std::string misspelled_word = getMisspelledWord(mCursorPos);
+ if ((is_misspelled = !misspelled_word.empty()) == true)
+ {
+ LLSpellChecker::instance().getSuggestions(misspelled_word, mSuggestionList);
+ }
+ }
+
+ menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty()));
+ menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled));
+ menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled));
+ menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled));
+ menu->show(screen_x, screen_y, this);
}
void LLTextEditor::drawPreeditMarker()
{
- static LLUICachedControl<F32> preedit_marker_brightness ("UIPreeditMarkerBrightness", 0);
- static LLUICachedControl<S32> preedit_marker_gap ("UIPreeditMarkerGap", 0);
- static LLUICachedControl<S32> preedit_marker_position ("UIPreeditMarkerPosition", 0);
- static LLUICachedControl<S32> preedit_marker_thickness ("UIPreeditMarkerThickness", 0);
- static LLUICachedControl<F32> preedit_standout_brightness ("UIPreeditStandoutBrightness", 0);
- static LLUICachedControl<S32> preedit_standout_gap ("UIPreeditStandoutGap", 0);
- static LLUICachedControl<S32> preedit_standout_position ("UIPreeditStandoutPosition", 0);
- static LLUICachedControl<S32> preedit_standout_thickness ("UIPreeditStandoutThickness", 0);
+ static LLUICachedControl<F32> preedit_marker_brightness ("UIPreeditMarkerBrightness", 0);
+ static LLUICachedControl<S32> preedit_marker_gap ("UIPreeditMarkerGap", 0);
+ static LLUICachedControl<S32> preedit_marker_position ("UIPreeditMarkerPosition", 0);
+ static LLUICachedControl<S32> preedit_marker_thickness ("UIPreeditMarkerThickness", 0);
+ static LLUICachedControl<F32> preedit_standout_brightness ("UIPreeditStandoutBrightness", 0);
+ static LLUICachedControl<S32> preedit_standout_gap ("UIPreeditStandoutGap", 0);
+ static LLUICachedControl<S32> preedit_standout_position ("UIPreeditStandoutPosition", 0);
+ static LLUICachedControl<S32> preedit_standout_thickness ("UIPreeditStandoutThickness", 0);
- if (!hasPreeditString())
- {
- return;
- }
+ if (!hasPreeditString())
+ {
+ return;
+ }
const LLWString textString(getWText());
- const llwchar *text = textString.c_str();
- const S32 text_len = getLength();
- const S32 num_lines = getLineCount();
-
- S32 cur_line = getFirstVisibleLine();
- if (cur_line >= num_lines)
- {
- return;
- }
-
- const S32 line_height = mFont->getLineHeight();
-
- S32 line_start = getLineStart(cur_line);
- S32 line_y = mVisibleTextRect.mTop - line_height;
- while((mVisibleTextRect.mBottom <= line_y) && (num_lines > cur_line))
- {
- S32 next_start = -1;
- S32 line_end = text_len;
-
- if ((cur_line + 1) < num_lines)
- {
- next_start = getLineStart(cur_line + 1);
- line_end = next_start;
- }
- if ( text[line_end-1] == '\n' )
- {
- --line_end;
- }
-
- // Does this line contain preedits?
- if (line_start >= mPreeditPositions.back())
- {
- // We have passed the preedits.
- break;
- }
- if (line_end > mPreeditPositions.front())
- {
- for (U32 i = 0; i < mPreeditStandouts.size(); i++)
- {
- S32 left = mPreeditPositions[i];
- S32 right = mPreeditPositions[i + 1];
- if (right <= line_start || left >= line_end)
- {
- continue;
- }
-
- line_info& line = mLineInfoList[cur_line];
- LLRect text_rect(line.mRect);
- text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents
- text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position
-
- S32 preedit_left = text_rect.mLeft;
- if (left > line_start)
- {
- preedit_left += mFont->getWidth(text, line_start, left - line_start);
- }
- S32 preedit_right = text_rect.mLeft;
- if (right < line_end)
- {
- preedit_right += mFont->getWidth(text, line_start, right - line_start);
- }
- else
- {
- preedit_right += mFont->getWidth(text, line_start, line_end - line_start);
- }
-
- if (mPreeditStandouts[i])
- {
- gl_rect_2d(preedit_left + preedit_standout_gap,
- text_rect.mBottom + mFont->getDescenderHeight() - 1,
- preedit_right - preedit_standout_gap - 1,
- text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_standout_thickness,
- (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f));
- }
- else
- {
- gl_rect_2d(preedit_left + preedit_marker_gap,
- text_rect.mBottom + mFont->getDescenderHeight() - 1,
- preedit_right - preedit_marker_gap - 1,
- text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_marker_thickness,
- (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f));
- }
- }
- }
-
- // move down one line
- line_y -= line_height;
- line_start = next_start;
- cur_line++;
- }
+ const llwchar *text = textString.c_str();
+ const S32 text_len = getLength();
+ const S32 num_lines = getLineCount();
+
+ S32 cur_line = getFirstVisibleLine();
+ if (cur_line >= num_lines)
+ {
+ return;
+ }
+
+ const S32 line_height = mFont->getLineHeight();
+
+ S32 line_start = getLineStart(cur_line);
+ S32 line_y = mVisibleTextRect.mTop - line_height;
+ while((mVisibleTextRect.mBottom <= line_y) && (num_lines > cur_line))
+ {
+ S32 next_start = -1;
+ S32 line_end = text_len;
+
+ if ((cur_line + 1) < num_lines)
+ {
+ next_start = getLineStart(cur_line + 1);
+ line_end = next_start;
+ }
+ if ( text[line_end-1] == '\n' )
+ {
+ --line_end;
+ }
+
+ // Does this line contain preedits?
+ if (line_start >= mPreeditPositions.back())
+ {
+ // We have passed the preedits.
+ break;
+ }
+ if (line_end > mPreeditPositions.front())
+ {
+ for (U32 i = 0; i < mPreeditStandouts.size(); i++)
+ {
+ S32 left = mPreeditPositions[i];
+ S32 right = mPreeditPositions[i + 1];
+ if (right <= line_start || left >= line_end)
+ {
+ continue;
+ }
+
+ line_info& line = mLineInfoList[cur_line];
+ LLRect text_rect(line.mRect);
+ text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents
+ text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position
+
+ S32 preedit_left = text_rect.mLeft;
+ if (left > line_start)
+ {
+ preedit_left += mFont->getWidth(text, line_start, left - line_start);
+ }
+ S32 preedit_right = text_rect.mLeft;
+ if (right < line_end)
+ {
+ preedit_right += mFont->getWidth(text, line_start, right - line_start);
+ }
+ else
+ {
+ preedit_right += mFont->getWidth(text, line_start, line_end - line_start);
+ }
+
+ if (mPreeditStandouts[i])
+ {
+ gl_rect_2d(preedit_left + preedit_standout_gap,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1,
+ preedit_right - preedit_standout_gap - 1,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_standout_thickness,
+ (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f));
+ }
+ else
+ {
+ gl_rect_2d(preedit_left + preedit_marker_gap,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1,
+ preedit_right - preedit_marker_gap - 1,
+ text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_marker_thickness,
+ (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f));
+ }
+ }
+ }
+
+ // move down one line
+ line_y -= line_height;
+ line_start = next_start;
+ cur_line++;
+ }
}
void LLTextEditor::draw()
{
- {
- // pad clipping rectangle so that cursor can draw at full width
- // when at left edge of mVisibleTextRect
- LLRect clip_rect(mVisibleTextRect);
- clip_rect.stretch(1);
- LLLocalClipRect clip(clip_rect);
- }
+ {
+ // pad clipping rectangle so that cursor can draw at full width
+ // when at left edge of mVisibleTextRect
+ LLRect clip_rect(mVisibleTextRect);
+ clip_rect.stretch(1);
+ LLLocalClipRect clip(clip_rect);
+ }
- LLTextBase::draw();
+ LLTextBase::draw();
drawPreeditMarker();
- //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
- // when in readonly mode
- mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly);
+ //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
+ // when in readonly mode
+ mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly);
}
// Start or stop the editor from accepting text-editing keystrokes
// see also LLLineEditor
void LLTextEditor::setFocus( BOOL new_state )
{
- BOOL old_state = hasFocus();
+ BOOL old_state = hasFocus();
- // Don't change anything if the focus state didn't change
- if (new_state == old_state) return;
+ // Don't change anything if the focus state didn't change
+ if (new_state == old_state) return;
- // Notify early if we are losing focus.
- if (!new_state)
- {
- getWindow()->allowLanguageTextInput(this, FALSE);
- }
+ // Notify early if we are losing focus.
+ if (!new_state)
+ {
+ getWindow()->allowLanguageTextInput(this, FALSE);
+ }
- LLTextBase::setFocus( new_state );
+ LLTextBase::setFocus( new_state );
- if( new_state )
- {
- // Route menu to this class
- gEditMenuHandler = this;
+ if( new_state )
+ {
+ // Route menu to this class
+ gEditMenuHandler = this;
- // Don't start the cursor flashing right away
- resetCursorBlink();
- }
- else
- {
- // Route menu back to the default
- if( gEditMenuHandler == this )
- {
- gEditMenuHandler = NULL;
- }
+ // Don't start the cursor flashing right away
+ resetCursorBlink();
+ }
+ else
+ {
+ // Route menu back to the default
+ if( gEditMenuHandler == this )
+ {
+ gEditMenuHandler = NULL;
+ }
- endSelection();
- }
+ endSelection();
+ }
}
// public
void LLTextEditor::setCursorAndScrollToEnd()
{
- deselect();
- endOfDoc();
+ deselect();
+ endOfDoc();
}
-void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap )
-{
- *line = getLineNumFromDocIndex(mCursorPos, include_wordwrap);
- *col = getLineOffsetFromDocIndex(mCursorPos, include_wordwrap);
+void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap )
+{
+ *line = getLineNumFromDocIndex(mCursorPos, include_wordwrap);
+ *col = getLineOffsetFromDocIndex(mCursorPos, include_wordwrap);
}
void LLTextEditor::autoIndent()
{
- // Count the number of spaces in the current line
- S32 line = getLineNumFromDocIndex(mCursorPos, false);
- S32 line_start = getLineStart(line);
- S32 space_count = 0;
- S32 i;
+ // Count the number of spaces in the current line
+ S32 line = getLineNumFromDocIndex(mCursorPos, false);
+ S32 line_start = getLineStart(line);
+ S32 space_count = 0;
+ S32 i;
- LLWString text = getWText();
- S32 offset = getLineOffsetFromDocIndex(mCursorPos);
- while(( ' ' == text[line_start] ) && (space_count < offset))
- {
- space_count++;
- line_start++;
- }
+ LLWString text = getWText();
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+ while(( ' ' == text[line_start] ) && (space_count < offset))
+ {
+ space_count++;
+ line_start++;
+ }
- // If we're starting a braced section, indent one level.
- if( (mCursorPos > 0) && (text[mCursorPos -1] == '{') )
- {
- space_count += SPACES_PER_TAB;
- }
+ // If we're starting a braced section, indent one level.
+ if( (mCursorPos > 0) && (text[mCursorPos -1] == '{') )
+ {
+ space_count += SPACES_PER_TAB;
+ }
- // Insert that number of spaces on the new line
+ // Insert that number of spaces on the new line
- //appendLineBreakSegment(LLStyle::Params());//addChar( '\n' );
- addLineBreakChar();
+ //appendLineBreakSegment(LLStyle::Params());//addChar( '\n' );
+ addLineBreakChar();
- for( i = 0; i < space_count; i++ )
- {
- addChar( ' ' );
- }
+ for( i = 0; i < space_count; i++ )
+ {
+ addChar( ' ' );
+ }
}
// Inserts new text at the cursor position
void LLTextEditor::insertText(const std::string &new_text)
{
- BOOL enabled = getEnabled();
- setEnabled( TRUE );
+ BOOL enabled = getEnabled();
+ setEnabled( TRUE );
- // Delete any selected characters (the insertion replaces them)
- if( hasSelection() )
- {
- deleteSelection(TRUE);
- }
+ // Delete any selected characters (the insertion replaces them)
+ if( hasSelection() )
+ {
+ deleteSelection(TRUE);
+ }
+
+ setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE, LLTextSegmentPtr() ));
- setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE, LLTextSegmentPtr() ));
-
- setEnabled( enabled );
+ setEnabled( enabled );
}
void LLTextEditor::insertText(LLWString &new_text)
{
- BOOL enabled = getEnabled();
- setEnabled( TRUE );
+ BOOL enabled = getEnabled();
+ setEnabled( TRUE );
- // Delete any selected characters (the insertion replaces them)
- if( hasSelection() )
- {
- deleteSelection(TRUE);
- }
+ // Delete any selected characters (the insertion replaces them)
+ if( hasSelection() )
+ {
+ deleteSelection(TRUE);
+ }
- setCursorPos(mCursorPos + insert( mCursorPos, new_text, FALSE, LLTextSegmentPtr() ));
+ setCursorPos(mCursorPos + insert( mCursorPos, new_text, FALSE, LLTextSegmentPtr() ));
- setEnabled( enabled );
+ setEnabled( enabled );
}
void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo)
{
- // Save old state
- S32 selection_start = mSelectionStart;
- S32 selection_end = mSelectionEnd;
- BOOL was_selecting = mIsSelecting;
- S32 cursor_pos = mCursorPos;
- S32 old_length = getLength();
- BOOL cursor_was_at_end = (mCursorPos == old_length);
+ // Save old state
+ S32 selection_start = mSelectionStart;
+ S32 selection_end = mSelectionEnd;
+ BOOL was_selecting = mIsSelecting;
+ S32 cursor_pos = mCursorPos;
+ S32 old_length = getLength();
+ BOOL cursor_was_at_end = (mCursorPos == old_length);
- deselect();
+ deselect();
- setCursorPos(old_length);
+ setCursorPos(old_length);
- LLWString widget_wide_text = utf8str_to_wstring(text);
+ LLWString widget_wide_text = utf8str_to_wstring(text);
- LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
- insert(getLength(), widget_wide_text, FALSE, segment);
+ LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
+ insert(getLength(), widget_wide_text, FALSE, segment);
- // Set the cursor and scroll position
- if( selection_start != selection_end )
- {
- mSelectionStart = selection_start;
- mSelectionEnd = selection_end;
+ // Set the cursor and scroll position
+ if( selection_start != selection_end )
+ {
+ mSelectionStart = selection_start;
+ mSelectionEnd = selection_end;
- mIsSelecting = was_selecting;
- setCursorPos(cursor_pos);
- }
- else if( cursor_was_at_end )
- {
- setCursorPos(getLength());
- }
- else
- {
- setCursorPos(cursor_pos);
- }
+ mIsSelecting = was_selecting;
+ setCursorPos(cursor_pos);
+ }
+ else if( cursor_was_at_end )
+ {
+ setCursorPos(getLength());
+ }
+ else
+ {
+ setCursorPos(cursor_pos);
+ }
- if (!allow_undo)
- {
- blockUndo();
- }
+ if (!allow_undo)
+ {
+ blockUndo();
+ }
}
void LLTextEditor::removeTextFromEnd(S32 num_chars)
{
- if (num_chars <= 0) return;
+ if (num_chars <= 0) return;
- remove(getLength() - num_chars, num_chars, FALSE);
+ remove(getLength() - num_chars, num_chars, FALSE);
- S32 len = getLength();
- setCursorPos (llclamp(mCursorPos, 0, len));
- mSelectionStart = llclamp(mSelectionStart, 0, len);
- mSelectionEnd = llclamp(mSelectionEnd, 0, len);
+ S32 len = getLength();
+ setCursorPos (llclamp(mCursorPos, 0, len));
+ mSelectionStart = llclamp(mSelectionStart, 0, len);
+ mSelectionEnd = llclamp(mSelectionEnd, 0, len);
- needsScroll();
+ needsScroll();
}
//----------------------------------------------------------------------------
void LLTextEditor::onSpellCheckPerformed()
{
- if (isPristine())
- {
- mBaseDocIsPristine = FALSE;
- }
+ if (isPristine())
+ {
+ mBaseDocIsPristine = FALSE;
+ }
}
void LLTextEditor::makePristine()
{
- mPristineCmd = mLastCmd;
- mBaseDocIsPristine = !mLastCmd;
+ mPristineCmd = mLastCmd;
+ mBaseDocIsPristine = !mLastCmd;
- // Create a clean partition in the undo stack. We don't want a single command to extend from
- // the "pre-pristine" state to the "post-pristine" state.
- if( mLastCmd )
- {
- mLastCmd->blockExtensions();
- }
+ // Create a clean partition in the undo stack. We don't want a single command to extend from
+ // the "pre-pristine" state to the "post-pristine" state.
+ if( mLastCmd )
+ {
+ mLastCmd->blockExtensions();
+ }
}
BOOL LLTextEditor::isPristine() const
{
- if( mPristineCmd )
- {
- return (mPristineCmd == mLastCmd);
- }
- else
- {
- // No undo stack, so check if the version before and commands were done was the original version
- return !mLastCmd && mBaseDocIsPristine;
- }
+ if( mPristineCmd )
+ {
+ return (mPristineCmd == mLastCmd);
+ }
+ else
+ {
+ // No undo stack, so check if the version before and commands were done was the original version
+ return !mLastCmd && mBaseDocIsPristine;
+ }
}
BOOL LLTextEditor::tryToRevertToPristineState()
{
- if( !isPristine() )
- {
- deselect();
- S32 i = 0;
- while( !isPristine() && canUndo() )
- {
- undo();
- i--;
- }
-
- while( !isPristine() && canRedo() )
- {
- redo();
- i++;
- }
-
- if( !isPristine() )
- {
- // failed, so go back to where we started
- while( i > 0 )
- {
- undo();
- i--;
- }
- }
- }
-
- return isPristine(); // TRUE => success
+ if( !isPristine() )
+ {
+ deselect();
+ S32 i = 0;
+ while( !isPristine() && canUndo() )
+ {
+ undo();
+ i--;
+ }
+
+ while( !isPristine() && canRedo() )
+ {
+ redo();
+ i++;
+ }
+
+ if( !isPristine() )
+ {
+ // failed, so go back to where we started
+ while( i > 0 )
+ {
+ undo();
+ i--;
+ }
+ }
+ }
+
+ return isPristine(); // TRUE => success
}
void LLTextEditor::updateLinkSegments()
{
- LLWString wtext = getWText();
-
- // update any segments that contain a link
- for (segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); ++it)
- {
- LLTextSegment *segment = *it;
- if (segment && segment->getStyle() && segment->getStyle()->isLink())
- {
- LLStyleConstSP style = segment->getStyle();
- LLStyleSP new_style(new LLStyle(*style));
- LLWString url_label = wtext.substr(segment->getStart(), segment->getEnd()-segment->getStart());
-
- segment_set_t::const_iterator next_it = mSegments.upper_bound(segment);
- LLTextSegment *next_segment = *next_it;
- if (next_segment)
- {
- LLWString next_url_label = wtext.substr(next_segment->getStart(), next_segment->getEnd()-next_segment->getStart());
- std::string link_check = wstring_to_utf8str(url_label) + wstring_to_utf8str(next_url_label);
- LLUrlMatch match;
-
- if ( LLUrlRegistry::instance().findUrl(link_check, match))
- {
- if(match.getQuery() == wstring_to_utf8str(next_url_label))
- {
- continue;
- }
- }
- }
-
- // if the link's label (what the user can edit) is a valid Url,
- // then update the link's HREF to be the same as the label text.
- // This lets users edit Urls in-place.
- if (acceptsTextInput() && LLUrlRegistry::instance().hasUrl(url_label))
- {
- std::string new_url = wstring_to_utf8str(url_label);
- LLStringUtil::trim(new_url);
- new_style->setLinkHREF(new_url);
- LLStyleConstSP sp(new_style);
- segment->setStyle(sp);
- }
- }
- }
+ LLWString wtext = getWText();
+
+ // update any segments that contain a link
+ for (segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); ++it)
+ {
+ LLTextSegment *segment = *it;
+ if (segment && segment->getStyle() && segment->getStyle()->isLink())
+ {
+ LLStyleConstSP style = segment->getStyle();
+ LLStyleSP new_style(new LLStyle(*style));
+ LLWString url_label = wtext.substr(segment->getStart(), segment->getEnd()-segment->getStart());
+
+ segment_set_t::const_iterator next_it = mSegments.upper_bound(segment);
+ LLTextSegment *next_segment = *next_it;
+ if (next_segment)
+ {
+ LLWString next_url_label = wtext.substr(next_segment->getStart(), next_segment->getEnd()-next_segment->getStart());
+ std::string link_check = wstring_to_utf8str(url_label) + wstring_to_utf8str(next_url_label);
+ LLUrlMatch match;
+
+ if ( LLUrlRegistry::instance().findUrl(link_check, match))
+ {
+ if(match.getQuery() == wstring_to_utf8str(next_url_label))
+ {
+ continue;
+ }
+ }
+ }
+
+ // if the link's label (what the user can edit) is a valid Url,
+ // then update the link's HREF to be the same as the label text.
+ // This lets users edit Urls in-place.
+ if (acceptsTextInput() && LLUrlRegistry::instance().hasUrl(url_label))
+ {
+ std::string new_url = wstring_to_utf8str(url_label);
+ LLStringUtil::trim(new_url);
+ new_style->setLinkHREF(new_url);
+ LLStyleConstSP sp(new_style);
+ segment->setStyle(sp);
+ }
+ }
+ }
}
void LLTextEditor::onMouseCaptureLost()
{
- endSelection();
+ endSelection();
}
///////////////////////////////////////////////////////////////////
@@ -2643,135 +2656,135 @@ void LLTextEditor::onMouseCaptureLost()
BOOL LLTextEditor::importBuffer(const char* buffer, S32 length )
{
- std::istringstream instream(buffer);
-
- // Version 1 format:
- // Linden text version 1\n
- // {\n
- // <EmbeddedItemList chunk>
- // Text length <bytes without \0>\n
- // <text without \0> (text may contain ext_char_values)
- // }\n
-
- char tbuf[MAX_STRING]; /* Flawfinder: ignore */
-
- S32 version = 0;
- instream.getline(tbuf, MAX_STRING);
- if( 1 != sscanf(tbuf, "Linden text version %d", &version) )
- {
- LL_WARNS() << "Invalid Linden text file header " << LL_ENDL;
- return FALSE;
- }
-
- if( 1 != version )
- {
- LL_WARNS() << "Invalid Linden text file version: " << version << LL_ENDL;
- return FALSE;
- }
-
- instream.getline(tbuf, MAX_STRING);
- if( 0 != sscanf(tbuf, "{") )
- {
- LL_WARNS() << "Invalid Linden text file format" << LL_ENDL;
- return FALSE;
- }
-
- S32 text_len = 0;
- instream.getline(tbuf, MAX_STRING);
- if( 1 != sscanf(tbuf, "Text length %d", &text_len) )
- {
- LL_WARNS() << "Invalid Linden text length field" << LL_ENDL;
- return FALSE;
- }
-
- if( text_len > mMaxTextByteLength )
- {
- LL_WARNS() << "Invalid Linden text length: " << text_len << LL_ENDL;
- return FALSE;
- }
-
- BOOL success = TRUE;
-
- char* text = new char[ text_len + 1];
- if (text == NULL)
- {
+ std::istringstream instream(buffer);
+
+ // Version 1 format:
+ // Linden text version 1\n
+ // {\n
+ // <EmbeddedItemList chunk>
+ // Text length <bytes without \0>\n
+ // <text without \0> (text may contain ext_char_values)
+ // }\n
+
+ char tbuf[MAX_STRING]; /* Flawfinder: ignore */
+
+ S32 version = 0;
+ instream.getline(tbuf, MAX_STRING);
+ if( 1 != sscanf(tbuf, "Linden text version %d", &version) )
+ {
+ LL_WARNS() << "Invalid Linden text file header " << LL_ENDL;
+ return FALSE;
+ }
+
+ if( 1 != version )
+ {
+ LL_WARNS() << "Invalid Linden text file version: " << version << LL_ENDL;
+ return FALSE;
+ }
+
+ instream.getline(tbuf, MAX_STRING);
+ if( 0 != sscanf(tbuf, "{") )
+ {
+ LL_WARNS() << "Invalid Linden text file format" << LL_ENDL;
+ return FALSE;
+ }
+
+ S32 text_len = 0;
+ instream.getline(tbuf, MAX_STRING);
+ if( 1 != sscanf(tbuf, "Text length %d", &text_len) )
+ {
+ LL_WARNS() << "Invalid Linden text length field" << LL_ENDL;
+ return FALSE;
+ }
+
+ if( text_len > mMaxTextByteLength )
+ {
+ LL_WARNS() << "Invalid Linden text length: " << text_len << LL_ENDL;
+ return FALSE;
+ }
+
+ BOOL success = TRUE;
+
+ char* text = new char[ text_len + 1];
+ if (text == NULL)
+ {
LLError::LLUserWarningMsg::showOutOfMemory();
- LL_ERRS() << "Memory allocation failure." << LL_ENDL;
- return FALSE;
- }
- instream.get(text, text_len + 1, '\0');
- text[text_len] = '\0';
- if( text_len != (S32)strlen(text) )/* Flawfinder: ignore */
- {
- LL_WARNS() << llformat("Invalid text length: %d != %d ",strlen(text),text_len) << LL_ENDL;/* Flawfinder: ignore */
- success = FALSE;
- }
-
- instream.getline(tbuf, MAX_STRING);
- if( success && (0 != sscanf(tbuf, "}")) )
- {
- LL_WARNS() << "Invalid Linden text file format: missing terminal }" << LL_ENDL;
- success = FALSE;
- }
-
- if( success )
- {
- // Actually set the text
- setText( LLStringExplicit(text) );
- }
-
- delete[] text;
-
- startOfDoc();
- deselect();
-
- return success;
+ LL_ERRS() << "Memory allocation failure." << LL_ENDL;
+ return FALSE;
+ }
+ instream.get(text, text_len + 1, '\0');
+ text[text_len] = '\0';
+ if( text_len != (S32)strlen(text) )/* Flawfinder: ignore */
+ {
+ LL_WARNS() << llformat("Invalid text length: %d != %d ",strlen(text),text_len) << LL_ENDL;/* Flawfinder: ignore */
+ success = FALSE;
+ }
+
+ instream.getline(tbuf, MAX_STRING);
+ if( success && (0 != sscanf(tbuf, "}")) )
+ {
+ LL_WARNS() << "Invalid Linden text file format: missing terminal }" << LL_ENDL;
+ success = FALSE;
+ }
+
+ if( success )
+ {
+ // Actually set the text
+ setText( LLStringExplicit(text) );
+ }
+
+ delete[] text;
+
+ startOfDoc();
+ deselect();
+
+ return success;
}
BOOL LLTextEditor::exportBuffer(std::string &buffer )
{
- std::ostringstream outstream(buffer);
-
- outstream << "Linden text version 1\n";
- outstream << "{\n";
+ std::ostringstream outstream(buffer);
+
+ outstream << "Linden text version 1\n";
+ outstream << "{\n";
- outstream << llformat("Text length %d\n", getLength() );
- outstream << getText();
- outstream << "}\n";
+ outstream << llformat("Text length %d\n", getLength() );
+ outstream << getText();
+ outstream << "}\n";
- return TRUE;
+ return TRUE;
}
void LLTextEditor::updateAllowingLanguageInput()
{
- LLWindow* window = getWindow();
- if (!window)
- {
- // test app, no window available
- return;
- }
- if (hasFocus() && !mReadOnly)
- {
- window->allowLanguageTextInput(this, TRUE);
- }
- else
- {
- window->allowLanguageTextInput(this, FALSE);
- }
+ LLWindow* window = getWindow();
+ if (!window)
+ {
+ // test app, no window available
+ return;
+ }
+ if (hasFocus() && !mReadOnly)
+ {
+ window->allowLanguageTextInput(this, TRUE);
+ }
+ else
+ {
+ window->allowLanguageTextInput(this, FALSE);
+ }
}
// Preedit is managed off the undo/redo command stack.
BOOL LLTextEditor::hasPreeditString() const
{
- return (mPreeditPositions.size() > 1);
+ return (mPreeditPositions.size() > 1);
}
void LLTextEditor::resetPreedit()
{
if (hasSelection())
{
- if (hasPreeditString())
+ if (hasPreeditString())
{
LL_WARNS() << "Preedit and selection!" << LL_ENDL;
deselect();
@@ -2781,277 +2794,277 @@ void LLTextEditor::resetPreedit()
deleteSelection(TRUE);
}
}
- if (hasPreeditString())
- {
- if (hasSelection())
- {
- LL_WARNS() << "Preedit and selection!" << LL_ENDL;
- deselect();
- }
+ if (hasPreeditString())
+ {
+ if (hasSelection())
+ {
+ LL_WARNS() << "Preedit and selection!" << LL_ENDL;
+ deselect();
+ }
- setCursorPos(mPreeditPositions.front());
- removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);
- insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString);
+ setCursorPos(mPreeditPositions.front());
+ removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);
+ insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString);
- mPreeditWString.clear();
- mPreeditOverwrittenWString.clear();
- mPreeditPositions.clear();
+ mPreeditWString.clear();
+ mPreeditOverwrittenWString.clear();
+ mPreeditPositions.clear();
- // A call to updatePreedit should soon follow under a
- // normal course of operation, so we don't need to
- // maintain internal variables such as line start
- // positions now.
- }
+ // A call to updatePreedit should soon follow under a
+ // normal course of operation, so we don't need to
+ // maintain internal variables such as line start
+ // positions now.
+ }
}
void LLTextEditor::updatePreedit(const LLWString &preedit_string,
- const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position)
+ const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position)
{
- // Just in case.
- if (mReadOnly)
- {
- return;
- }
+ // Just in case.
+ if (mReadOnly)
+ {
+ return;
+ }
- getWindow()->hideCursorUntilMouseMove();
+ getWindow()->hideCursorUntilMouseMove();
- S32 insert_preedit_at = mCursorPos;
+ S32 insert_preedit_at = mCursorPos;
+
+ mPreeditWString = preedit_string;
+ mPreeditPositions.resize(preedit_segment_lengths.size() + 1);
+ S32 position = insert_preedit_at;
+ for (segment_lengths_t::size_type i = 0; i < preedit_segment_lengths.size(); i++)
+ {
+ mPreeditPositions[i] = position;
+ position += preedit_segment_lengths[i];
+ }
+ mPreeditPositions.back() = position;
- mPreeditWString = preedit_string;
- mPreeditPositions.resize(preedit_segment_lengths.size() + 1);
- S32 position = insert_preedit_at;
- for (segment_lengths_t::size_type i = 0; i < preedit_segment_lengths.size(); i++)
- {
- mPreeditPositions[i] = position;
- position += preedit_segment_lengths[i];
- }
- mPreeditPositions.back() = position;
+ if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
+ {
+ mPreeditOverwrittenWString = getWText().substr(insert_preedit_at, mPreeditWString.length());
+ removeStringNoUndo(insert_preedit_at, mPreeditWString.length());
+ }
+ else
+ {
+ mPreeditOverwrittenWString.clear();
+ }
- if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
- {
- mPreeditOverwrittenWString = getWText().substr(insert_preedit_at, mPreeditWString.length());
- removeStringNoUndo(insert_preedit_at, mPreeditWString.length());
- }
- else
- {
- mPreeditOverwrittenWString.clear();
- }
-
- segment_vec_t segments;
- //pass empty segments to let "insertStringNoUndo" make new LLNormalTextSegment and insert it, if needed.
- insertStringNoUndo(insert_preedit_at, mPreeditWString, &segments);
+ segment_vec_t segments;
+ //pass empty segments to let "insertStringNoUndo" make new LLNormalTextSegment and insert it, if needed.
+ insertStringNoUndo(insert_preedit_at, mPreeditWString, &segments);
- mPreeditStandouts = preedit_standouts;
+ mPreeditStandouts = preedit_standouts;
- setCursorPos(insert_preedit_at + caret_position);
+ setCursorPos(insert_preedit_at + caret_position);
- // Update of the preedit should be caused by some key strokes.
- resetCursorBlink();
+ // Update of the preedit should be caused by some key strokes.
+ resetCursorBlink();
- onKeyStroke();
+ onKeyStroke();
}
BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const
{
- if (control)
- {
- LLRect control_rect_screen;
- localRectToScreen(mVisibleTextRect, &control_rect_screen);
- LLUI::getInstance()->screenRectToGL(control_rect_screen, control);
- }
-
- S32 preedit_left_position, preedit_right_position;
- if (hasPreeditString())
- {
- preedit_left_position = mPreeditPositions.front();
- preedit_right_position = mPreeditPositions.back();
- }
- else
- {
- preedit_left_position = preedit_right_position = mCursorPos;
- }
-
- const S32 query = (query_offset >= 0 ? preedit_left_position + query_offset : mCursorPos);
- if (query < preedit_left_position || query > preedit_right_position)
- {
- return FALSE;
- }
-
- const S32 first_visible_line = getFirstVisibleLine();
- if (query < getLineStart(first_visible_line))
- {
- return FALSE;
- }
-
- S32 current_line = first_visible_line;
- S32 current_line_start, current_line_end;
- for (;;)
- {
- current_line_start = getLineStart(current_line);
- current_line_end = getLineStart(current_line + 1);
- if (query >= current_line_start && query < current_line_end)
- {
- break;
- }
- if (current_line_start == current_line_end)
- {
- // We have reached on the last line. The query position must be here.
- break;
- }
- current_line++;
- }
+ if (control)
+ {
+ LLRect control_rect_screen;
+ localRectToScreen(mVisibleTextRect, &control_rect_screen);
+ LLUI::getInstance()->screenRectToGL(control_rect_screen, control);
+ }
+
+ S32 preedit_left_position, preedit_right_position;
+ if (hasPreeditString())
+ {
+ preedit_left_position = mPreeditPositions.front();
+ preedit_right_position = mPreeditPositions.back();
+ }
+ else
+ {
+ preedit_left_position = preedit_right_position = mCursorPos;
+ }
+
+ const S32 query = (query_offset >= 0 ? preedit_left_position + query_offset : mCursorPos);
+ if (query < preedit_left_position || query > preedit_right_position)
+ {
+ return FALSE;
+ }
+
+ const S32 first_visible_line = getFirstVisibleLine();
+ if (query < getLineStart(first_visible_line))
+ {
+ return FALSE;
+ }
+
+ S32 current_line = first_visible_line;
+ S32 current_line_start, current_line_end;
+ for (;;)
+ {
+ current_line_start = getLineStart(current_line);
+ current_line_end = getLineStart(current_line + 1);
+ if (query >= current_line_start && query < current_line_end)
+ {
+ break;
+ }
+ if (current_line_start == current_line_end)
+ {
+ // We have reached on the last line. The query position must be here.
+ break;
+ }
+ current_line++;
+ }
const LLWString textString(getWText());
- const llwchar * const text = textString.c_str();
- const S32 line_height = mFont->getLineHeight();
-
- if (coord)
- {
- const S32 query_x = mVisibleTextRect.mLeft + mFont->getWidth(text, current_line_start, query - current_line_start);
- const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
- S32 query_screen_x, query_screen_y;
- localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y);
- LLUI::getInstance()->screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY);
- }
-
- if (bounds)
- {
- S32 preedit_left = mVisibleTextRect.mLeft;
- if (preedit_left_position > current_line_start)
- {
- preedit_left += mFont->getWidth(text, current_line_start, preedit_left_position - current_line_start);
- }
-
- S32 preedit_right = mVisibleTextRect.mLeft;
- if (preedit_right_position < current_line_end)
- {
- preedit_right += mFont->getWidth(text, current_line_start, preedit_right_position - current_line_start);
- }
- else
- {
- preedit_right += mFont->getWidth(text, current_line_start, current_line_end - current_line_start);
- }
-
- const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height;
- const S32 preedit_bottom = preedit_top - line_height;
-
- const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom);
- LLRect preedit_rect_screen;
- localRectToScreen(preedit_rect_local, &preedit_rect_screen);
- LLUI::getInstance()->screenRectToGL(preedit_rect_screen, bounds);
- }
-
- return TRUE;
+ const llwchar * const text = textString.c_str();
+ const S32 line_height = mFont->getLineHeight();
+
+ if (coord)
+ {
+ const S32 query_x = mVisibleTextRect.mLeft + mFont->getWidth(text, current_line_start, query - current_line_start);
+ const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
+ S32 query_screen_x, query_screen_y;
+ localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y);
+ LLUI::getInstance()->screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY);
+ }
+
+ if (bounds)
+ {
+ S32 preedit_left = mVisibleTextRect.mLeft;
+ if (preedit_left_position > current_line_start)
+ {
+ preedit_left += mFont->getWidth(text, current_line_start, preedit_left_position - current_line_start);
+ }
+
+ S32 preedit_right = mVisibleTextRect.mLeft;
+ if (preedit_right_position < current_line_end)
+ {
+ preedit_right += mFont->getWidth(text, current_line_start, preedit_right_position - current_line_start);
+ }
+ else
+ {
+ preedit_right += mFont->getWidth(text, current_line_start, current_line_end - current_line_start);
+ }
+
+ const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height;
+ const S32 preedit_bottom = preedit_top - line_height;
+
+ const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom);
+ LLRect preedit_rect_screen;
+ localRectToScreen(preedit_rect_local, &preedit_rect_screen);
+ LLUI::getInstance()->screenRectToGL(preedit_rect_screen, bounds);
+ }
+
+ return TRUE;
}
void LLTextEditor::getSelectionRange(S32 *position, S32 *length) const
{
- if (hasSelection())
- {
- *position = llmin(mSelectionStart, mSelectionEnd);
- *length = llabs(mSelectionStart - mSelectionEnd);
- }
- else
- {
- *position = mCursorPos;
- *length = 0;
- }
+ if (hasSelection())
+ {
+ *position = llmin(mSelectionStart, mSelectionEnd);
+ *length = llabs(mSelectionStart - mSelectionEnd);
+ }
+ else
+ {
+ *position = mCursorPos;
+ *length = 0;
+ }
}
void LLTextEditor::getPreeditRange(S32 *position, S32 *length) const
{
- if (hasPreeditString())
- {
- *position = mPreeditPositions.front();
- *length = mPreeditPositions.back() - mPreeditPositions.front();
- }
- else
- {
- *position = mCursorPos;
- *length = 0;
- }
+ if (hasPreeditString())
+ {
+ *position = mPreeditPositions.front();
+ *length = mPreeditPositions.back() - mPreeditPositions.front();
+ }
+ else
+ {
+ *position = mCursorPos;
+ *length = 0;
+ }
}
void LLTextEditor::markAsPreedit(S32 position, S32 length)
{
- deselect();
- setCursorPos(position);
- if (hasPreeditString())
- {
- LL_WARNS() << "markAsPreedit invoked when hasPreeditString is true." << LL_ENDL;
- }
- mPreeditWString = LLWString( getWText(), position, length );
- if (length > 0)
- {
- mPreeditPositions.resize(2);
- mPreeditPositions[0] = position;
- mPreeditPositions[1] = position + length;
- mPreeditStandouts.resize(1);
- mPreeditStandouts[0] = FALSE;
- }
- else
- {
- mPreeditPositions.clear();
- mPreeditStandouts.clear();
- }
- if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
- {
- mPreeditOverwrittenWString = mPreeditWString;
- }
- else
- {
- mPreeditOverwrittenWString.clear();
- }
+ deselect();
+ setCursorPos(position);
+ if (hasPreeditString())
+ {
+ LL_WARNS() << "markAsPreedit invoked when hasPreeditString is true." << LL_ENDL;
+ }
+ mPreeditWString = LLWString( getWText(), position, length );
+ if (length > 0)
+ {
+ mPreeditPositions.resize(2);
+ mPreeditPositions[0] = position;
+ mPreeditPositions[1] = position + length;
+ mPreeditStandouts.resize(1);
+ mPreeditStandouts[0] = FALSE;
+ }
+ else
+ {
+ mPreeditPositions.clear();
+ mPreeditStandouts.clear();
+ }
+ if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
+ {
+ mPreeditOverwrittenWString = mPreeditWString;
+ }
+ else
+ {
+ mPreeditOverwrittenWString.clear();
+ }
}
S32 LLTextEditor::getPreeditFontSize() const
{
- return ll_round((F32)mFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]);
+ return ll_round((F32)mFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]);
}
BOOL LLTextEditor::isDirty() const
{
- if(mReadOnly)
- {
- return FALSE;
- }
+ if(mReadOnly)
+ {
+ return FALSE;
+ }
- if( mPristineCmd )
- {
- return ( mPristineCmd == mLastCmd );
- }
- else
- {
- return ( NULL != mLastCmd );
- }
+ if( mPristineCmd )
+ {
+ return ( mPristineCmd == mLastCmd );
+ }
+ else
+ {
+ return ( NULL != mLastCmd );
+ }
}
void LLTextEditor::setKeystrokeCallback(const keystroke_signal_t::slot_type& callback)
{
- mKeystrokeSignal.connect(callback);
+ mKeystrokeSignal.connect(callback);
}
void LLTextEditor::onKeyStroke()
{
- mKeystrokeSignal(this);
+ mKeystrokeSignal(this);
- mSpellCheckStart = mSpellCheckEnd = -1;
- mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY);
+ mSpellCheckStart = mSpellCheckEnd = -1;
+ mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY);
}
//virtual
void LLTextEditor::clear()
{
- getViewModel()->setDisplay(LLWStringUtil::null);
- clearSegments();
+ getViewModel()->setDisplay(LLWStringUtil::null);
+ clearSegments();
}
bool LLTextEditor::canLoadOrSaveToFile()
{
- return !mReadOnly;
+ return !mReadOnly;
}
S32 LLTextEditor::spacesPerTab()
{
- return SPACES_PER_TAB;
+ return SPACES_PER_TAB;
}