Merge branch 'DRTVWR-591-maint-X' of https://github.com/secondlife/viewer

# Conflicts:
#	indra/llui/lllineeditor.cpp
#	indra/llui/lltexteditor.cpp
#	indra/llui/lltransutil.cpp
#	indra/newview/app_settings/settings.xml
#	indra/newview/skins/default/xui/en/panel_landmark_info.xml
#	indra/newview/skins/default/xui/en/strings.xml
master
Ansariel 2024-03-27 14:07:32 +01:00
commit 7804859af2
52 changed files with 723 additions and 497 deletions

View File

@ -224,7 +224,7 @@ LLFolderView::LLFolderView(const Params& p)
params.font(getLabelFontForStyle(LLFontGL::NORMAL));
params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN);
params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2));
params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe);
params.prevalidator(&LLTextValidate::validateASCIIPrintableNoPipe);
params.commit_on_focus_lost(true);
params.visible(false);
mRenamer = LLUICtrlFactory::create<LLLineEditor> (params);

View File

@ -82,9 +82,9 @@ template class LLLineEditor* LLView::getChild<class LLLineEditor>(
LLLineEditor::Params::Params()
: max_length(""),
keystroke_callback("keystroke_callback"),
prevalidate_callback("prevalidate_callback"),
prevalidate_input_callback("prevalidate_input_callback"),
keystroke_callback("keystroke_callback"),
prevalidator("prevalidator"),
input_prevalidator("input_prevalidator"),
background_image("background_image"),
background_image_disabled("background_image_disabled"),
background_image_focused("background_image_focused"),
@ -112,6 +112,8 @@ LLLineEditor::Params::Params()
default_text("default_text")
{
changeDefault(mouse_opaque, true);
addSynonym(prevalidator, "prevalidate_callback");
addSynonym(input_prevalidator, "prevalidate_input_callback");
addSynonym(select_on_focus, "select_all_on_focus_received");
addSynonym(border, "border");
addSynonym(label, "watermark_text");
@ -159,6 +161,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mUseBgColor(p.use_bg_color),
mHaveHistory(FALSE),
mReplaceNewlinesWithSpaces( TRUE ),
mPrevalidator(p.prevalidator()),
mInputPrevalidator(p.input_prevalidator()),
mLabel(p.label),
mCursorColor(p.cursor_color()),
mBgColor(p.bg_color()),
@ -213,8 +217,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
}
mSpellCheckTimer.reset();
setPrevalidateInput(p.prevalidate_input_callback());
setPrevalidate(p.prevalidate_callback());
updateAllowingLanguageInput();
}
LLLineEditor::~LLLineEditor()
@ -1263,11 +1266,12 @@ void LLLineEditor::cut()
deleteSelection();
// Validate new string and rollback the if needed.
BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
if( need_to_rollback )
BOOL need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
if (need_to_rollback)
{
rollback.doRollback( this );
LLUI::getInstance()->reportBadKeystroke();
mPrevalidator.showLastErrorUsingTimeout();
}
else
{
@ -1396,11 +1400,12 @@ void LLLineEditor::pasteHelper(bool is_primary)
deselect();
// Validate new string and rollback the if needed.
BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
if( need_to_rollback )
BOOL need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
if (need_to_rollback)
{
rollback.doRollback( this );
LLUI::getInstance()->reportBadKeystroke();
mPrevalidator.showLastErrorUsingTimeout();
}
else
{
@ -1668,19 +1673,27 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask )
deselect();
}
BOOL need_to_rollback = FALSE;
bool prevalidator_failed = false;
// If read-only, don't allow changes
need_to_rollback |= (mReadOnly && (mText.getString() == rollback.getText()));
bool need_to_rollback = mReadOnly && (mText.getString() == rollback.getText());
// Validate new string and rollback the keystroke if needed.
need_to_rollback |= (mPrevalidateFunc && !mPrevalidateFunc(mText.getWString()));
if (!need_to_rollback && mPrevalidator)
{
prevalidator_failed = !mPrevalidator.validate(mText.getWString());
need_to_rollback |= prevalidator_failed;
}
if (need_to_rollback)
{
rollback.doRollback(this);
LLUI::getInstance()->reportBadKeystroke();
if (prevalidator_failed)
{
mPrevalidator.showLastErrorUsingTimeout();
}
}
// Notify owner if requested
@ -1727,20 +1740,18 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char)
deselect();
BOOL need_to_rollback = FALSE;
// Validate new string and rollback the keystroke if needed.
need_to_rollback |= ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
if( need_to_rollback )
bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
if (need_to_rollback)
{
rollback.doRollback( this );
LLUI::getInstance()->reportBadKeystroke();
mPrevalidator.showLastErrorUsingTimeout();
}
// Notify owner if requested
if( !need_to_rollback && handled )
if (!need_to_rollback && handled)
{
// HACK! The only usage of this callback doesn't do anything with the character.
// We'll have to do something about this if something ever changes! - Doug
@ -1770,7 +1781,7 @@ void LLLineEditor::doDelete()
deleteSelection();
}
else if ( getCursor() < mText.length())
{
{
const LLWString& text_to_delete = mText.getWString().substr(getCursor(), 1);
if (!prevalidateInput(text_to_delete))
@ -1783,11 +1794,12 @@ void LLLineEditor::doDelete()
}
// Validate new string and rollback the if needed.
BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
if( need_to_rollback )
bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
if (need_to_rollback)
{
rollback.doRollback( this );
rollback.doRollback(this);
LLUI::getInstance()->reportBadKeystroke();
mPrevalidator.showLastErrorUsingTimeout();
}
else
{
@ -2333,7 +2345,7 @@ void LLLineEditor::setFocus( BOOL new_state )
// fine on 1.15.0.2, since all prevalidate func reject any
// non-ASCII characters. I'm not sure on future versions,
// however.
getWindow()->allowLanguageTextInput(this, mPrevalidateFunc == NULL);
getWindow()->allowLanguageTextInput(this, !mPrevalidator);
#endif // <FS:Zi>
}
}
@ -2353,26 +2365,21 @@ void LLLineEditor::setRect(const LLRect& rect)
}
}
void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func)
void LLLineEditor::setPrevalidate(LLTextValidate::Validator validator)
{
mPrevalidateFunc = func;
mPrevalidator = validator;
updateAllowingLanguageInput();
}
void LLLineEditor::setPrevalidateInput(LLTextValidate::validate_func_t func)
void LLLineEditor::setPrevalidateInput(LLTextValidate::Validator validator)
{
mPrevalidateInputFunc = func;
mInputPrevalidator = validator;
updateAllowingLanguageInput();
}
bool LLLineEditor::prevalidateInput(const LLWString& wstr)
{
if (mPrevalidateInputFunc && !mPrevalidateInputFunc(wstr))
{
return false;
}
return true;
return mInputPrevalidator.validate(wstr);
}
// static
@ -2522,7 +2529,7 @@ void LLLineEditor::updateAllowingLanguageInput()
if (hasFocus() && !mReadOnly)
#else
// </FS:Zi>
if (hasFocus() && !mReadOnly && !mDrawAsterixes && mPrevalidateFunc == NULL)
if (hasFocus() && !mReadOnly && !mDrawAsterixes && !mPrevalidator)
#endif // <FS:Zi>
{
window->allowLanguageTextInput(this, TRUE);

View File

@ -76,8 +76,8 @@ public:
Optional<MaxLength> max_length;
Optional<keystroke_callback_t> keystroke_callback;
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_input_callback;
Optional<LLTextValidate::Validator, LLTextValidate::Validators> prevalidator;
Optional<LLTextValidate::Validator, LLTextValidate::Validators> input_prevalidator;
Optional<LLViewBorder::Params> border;
@ -277,12 +277,12 @@ public:
void setTextPadding(S32 left, S32 right);
// Prevalidation controls which keystrokes can affect the editor
void setPrevalidate( LLTextValidate::validate_func_t func );
void setPrevalidate(LLTextValidate::Validator validator);
// This method sets callback that prevents from:
// - deleting, selecting, typing, cutting, pasting characters that are not valid.
// Also callback that this method sets differs from setPrevalidate in a way that it validates just inputed
// symbols, before existing text is modified, but setPrevalidate validates line after it was modified.
void setPrevalidateInput(LLTextValidate::validate_func_t func);
void setPrevalidateInput(LLTextValidate::Validator validator);
static BOOL postvalidateFloat(const std::string &str);
bool prevalidateInput(const LLWString& wstr);
@ -392,8 +392,8 @@ protected:
std::list<std::pair<U32, U32> > mMisspellRanges;
std::vector<std::string> mSuggestionList;
LLTextValidate::validate_func_t mPrevalidateFunc;
LLTextValidate::validate_func_t mPrevalidateInputFunc;
LLTextValidate::Validator mPrevalidator;
LLTextValidate::Validator mInputPrevalidator;
LLFrameTimer mKeystrokeTimer;
LLTimer mTripleClickTimer;

View File

@ -138,7 +138,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
params.font(p.font);
params.max_length.bytes(MAX_STRING_LENGTH);
params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit);
params.prevalidate_callback(&LLTextValidate::validateFloat);
params.prevalidator(&LLTextValidate::validateFloat);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) );

View File

@ -47,9 +47,9 @@ void LLResMgr::setLocale( LLLOCALE_ID locale_id )
mLocale = locale_id;
}
char LLResMgr::getDecimalPoint() const
char LLResMgr::getDecimalPoint() const
{
char decimal = localeconv()->decimal_point[0];
char decimal = localeconv()->decimal_point[0];
#if LL_DARWIN
// On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
@ -62,9 +62,9 @@ char LLResMgr::getDecimalPoint() const
return decimal;
}
char LLResMgr::getThousandsSeparator() const
char LLResMgr::getThousandsSeparator() const
{
char separator = localeconv()->thousands_sep[0];
char separator = localeconv()->thousands_sep[0];
#if LL_DARWIN
// On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
@ -79,7 +79,7 @@ char LLResMgr::getThousandsSeparator() const
char LLResMgr::getMonetaryDecimalPoint() const
{
char decimal = localeconv()->mon_decimal_point[0];
char decimal = localeconv()->mon_decimal_point[0];
#if LL_DARWIN
// On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.
@ -92,9 +92,9 @@ char LLResMgr::getMonetaryDecimalPoint() const
return decimal;
}
char LLResMgr::getMonetaryThousandsSeparator() const
char LLResMgr::getMonetaryThousandsSeparator() const
{
char separator = localeconv()->mon_thousands_sep[0];
char separator = localeconv()->mon_thousands_sep[0];
#if LL_DARWIN
// On the Mac, locale support is broken before 10.4, which causes things to go all pear-shaped.

View File

@ -167,7 +167,7 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
}
line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit);
line_p.prevalidate_callback(&LLTextValidate::validateFloat);
line_p.prevalidator(&LLTextValidate::validateFloat);
mEditor = LLUICtrlFactory::create<LLLineEditor>(line_p);
mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onEditorGainFocus, _1, this ));

View File

@ -232,18 +232,19 @@ private:
///////////////////////////////////////////////////////////////////
LLTextEditor::Params::Params()
: default_text("default_text"),
prevalidate_callback("prevalidate_callback"),
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),
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"),
enable_tab_remove("enable_tab_remove", true) // <FS:Ansariel> FIRE-15591: Optional tab remove
{
addSynonym(prevalidate_callback, "text_type");
addSynonym(prevalidator, "prevalidate_callback");
addSynonym(prevalidator, "text_type");
}
LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
@ -254,16 +255,17 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
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),
mPrevalidateFunc(p.prevalidate_callback()),
mPrevalidator(p.prevalidator()),
mShowContextMenu(p.show_context_menu),
mShowEmojiHelper(p.show_emoji_helper),
mEnableTooltipPaste(p.enable_tooltip_paste),
mPassDelete(FALSE),
mPassDelete(false),
mKeepSelectionOnReturn(false),
mEnableTabRemove(p.enable_tab_remove) // <FS:Ansariel> FIRE-15591: Optional tab remove
{
@ -280,7 +282,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
addChild( mBorder );
setText(p.default_text());
mParseOnTheFly = TRUE;
mParseOnTheFly = true;
}
void LLTextEditor::initFromParams( const LLTextEditor::Params& p)
@ -321,11 +323,13 @@ LLTextEditor::~LLTextEditor()
void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
{
// validate incoming text if necessary
if (mPrevalidateFunc)
if (mPrevalidator)
{
LLWString test_text = utf8str_to_wstring(utf8str);
if (!mPrevalidateFunc(test_text))
if (!mPrevalidator.validate(utf8str))
{
LLUI::getInstance()->reportBadKeystroke();
mPrevalidator.showLastErrorUsingTimeout();
// not valid text, nothing to do
return;
}
@ -334,9 +338,9 @@ void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Param
blockUndo();
deselect();
mParseOnTheFly = FALSE;
mParseOnTheFly = false;
LLTextBase::setText(utf8str, input_params);
mParseOnTheFly = TRUE;
mParseOnTheFly = true;
resetDirty();
}
@ -659,7 +663,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces )
// Disabling parsing on the fly to avoid updating text segments
// until all indentation commands are executed.
mParseOnTheFly = FALSE;
mParseOnTheFly = false;
// Find each start-of-line and indent it
do
@ -686,7 +690,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces )
}
while( cur < right );
mParseOnTheFly = TRUE;
mParseOnTheFly = true;
if( (right < getLength()) && (text[right] == '\n') )
{
@ -1045,10 +1049,12 @@ S32 LLTextEditor::execute( TextCmd* cmd )
mUndoStack.push_front(cmd);
mLastCmd = cmd;
bool need_to_rollback = mPrevalidateFunc
&& !mPrevalidateFunc(getViewModel()->getDisplay());
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();
@ -1216,16 +1222,15 @@ void LLTextEditor::removeWord(bool prev)
// Add a single character to the text
S32 LLTextEditor::addChar(S32 pos, llwchar wc)
{
if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength)
if ((wstring_utf8_length(getWText()) + wchar_utf8_length(wc)) > mMaxTextByteLength)
{
make_ui_sound("UISndBadKeystroke");
LLUI::getInstance()->reportBadKeystroke();
return 0;
}
if (mLastCmd && mLastCmd->canExtend(pos))
{
S32 delta = 0;
if (mPrevalidateFunc)
if (mPrevalidator)
{
// get a copy of current text contents
LLWString test_string(getViewModel()->getDisplay());
@ -1233,28 +1238,31 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc)
// modify text contents as if this addChar succeeded
llassert(pos <= (S32)test_string.size());
test_string.insert(pos, 1, wc);
if (!mPrevalidateFunc( test_string))
if (!mPrevalidator.validate(test_string))
{
LLUI::getInstance()->reportBadKeystroke();
mPrevalidator.showLastErrorUsingTimeout();
return 0;
}
}
S32 delta = 0;
mLastCmd->extendAndExecute(this, pos, wc, &delta);
return delta;
}
else
{
return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
}
return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
}
void LLTextEditor::addChar(llwchar wc)
{
if( !getEnabled() )
if (!getEnabled())
{
return;
}
if( hasSelection() )
if (hasSelection())
{
deleteSelection(TRUE);
}
@ -1601,7 +1609,13 @@ void LLTextEditor::pastePrimary()
// paste from primary (itsprimary==true) or clipboard (itsprimary==false)
void LLTextEditor::pasteHelper(bool is_primary)
{
mParseOnTheFly = FALSE;
struct BoolReset
{
BoolReset(bool& value) : mValuePtr(&value) { *mValuePtr = false; }
~BoolReset() { *mValuePtr = true; }
bool* mValuePtr;
} reset(mParseOnTheFly);
bool can_paste_it;
if (is_primary)
{
@ -1650,7 +1664,6 @@ void LLTextEditor::pasteHelper(bool is_primary)
deselect();
onKeyStroke();
mParseOnTheFly = TRUE;
}

View File

@ -54,7 +54,7 @@ public:
struct Params : public LLInitParam::Block<Params, LLTextBase::Params>
{
Optional<std::string> default_text;
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
Optional<LLTextValidate::Validator, LLTextValidate::Validators> prevalidator;
Optional<bool> embedded_items,
ignore_tab,
@ -353,7 +353,7 @@ private:
LLCoordGL mLastIMEPosition; // Last position of the IME editor
keystroke_signal_t mKeystrokeSignal;
LLTextValidate::validate_func_t mPrevalidateFunc;
LLTextValidate::Validator mPrevalidator;
LLHandle<LLContextMenu> mContextMenuHandle;
}; // end class LLTextEditor

View File

@ -27,330 +27,452 @@
// Text editor widget to let users enter a single line.
#include "linden_common.h"
#include "lltextvalidate.h"
#include "llnotificationsutil.h"
#include "lltrans.h"
#include "llresmgr.h" // for LLLocale
namespace LLTextValidate
{
void ValidateTextNamedFuncs::declareValues()
{
declare("ascii", validateASCII);
declare("float", validateFloat);
declare("int", validateInt);
declare("positive_s32", validatePositiveS32);
declare("non_negative_s32", validateNonNegativeS32);
declare("alpha_num", validateAlphaNum);
declare("alpha_num_space", validateAlphaNumSpace);
declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe);
declare("ascii_printable_no_space", validateASCIIPrintableNoSpace);
declare("ascii_with_newline", validateASCIIWithNewLine);
}
// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
//
bool validateFloat(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
static S32 strtol(const std::string& str) { return ::strtol(str.c_str(), NULL, 10); }
static S32 strtol(const LLWString& str) { return ::strtol(wstring_to_utf8str(str).c_str(), NULL, 10); }
bool success = TRUE;
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
if( 0 < len )
{
// May be a comma or period, depending on the locale
llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint();
static LLSD llsd(const std::string& str) { return LLSD(str); }
static LLSD llsd(const LLWString& str) { return LLSD(wstring_to_utf8str(str)); }
template <class CHAR>
LLSD llsd(CHAR ch) { return llsd(std::basic_string<CHAR>(1, ch)); }
S32 i = 0;
// First character can be a negative sign
if( '-' == trimmed[0] )
{
i++;
}
for( ; i < len; i++ )
{
if( (decimal_point != trimmed[i] ) && !LLStringOps::isDigit( trimmed[i] ) )
{
success = FALSE;
break;
}
}
}
return success;
}
// Limits what characters can be used to [1234567890-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
//
bool validateInt(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
bool success = TRUE;
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
if( 0 < len )
{
S32 i = 0;
// First character can be a negative sign
if( '-' == trimmed[0] )
{
i++;
}
for( ; i < len; i++ )
{
if( !LLStringOps::isDigit( trimmed[i] ) )
{
success = FALSE;
break;
}
}
}
return success;
}
bool validatePositiveS32(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
bool success = TRUE;
if(0 < len)
{
if(('-' == trimmed[0]) || ('0' == trimmed[0]))
{
success = FALSE;
}
S32 i = 0;
while(success && (i < len))
{
if(!LLStringOps::isDigit(trimmed[i++]))
{
success = FALSE;
}
}
}
if (success)
{
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
if (val <= 0)
{
success = FALSE;
}
}
return success;
}
bool validateNonNegativeS32(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
bool success = TRUE;
if(0 < len)
{
if('-' == trimmed[0])
{
success = FALSE;
}
S32 i = 0;
while(success && (i < len))
{
if(!LLStringOps::isDigit(trimmed[i++]))
{
success = FALSE;
}
}
}
if (success)
{
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
if (val < 0)
{
success = FALSE;
}
}
return success;
}
bool validateNonNegativeS32NoSpace(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
LLWString test_str = str;
S32 len = test_str.length();
bool success = TRUE;
if(0 < len)
{
if('-' == test_str[0])
{
success = FALSE;
}
S32 i = 0;
while(success && (i < len))
{
if(!LLStringOps::isDigit(test_str[i]) || LLStringOps::isSpace(test_str[i++]))
{
success = FALSE;
}
}
}
if (success)
{
S32 val = strtol(wstring_to_utf8str(test_str).c_str(), NULL, 10);
if (val < 0)
{
success = FALSE;
}
}
return success;
}
bool validateAlphaNum(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
bool rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
if( !LLStringOps::isAlnum((char)str[len]) )
{
rv = FALSE;
break;
}
}
return rv;
}
bool validateAlphaNumSpace(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
bool rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
if(!(LLStringOps::isAlnum((char)str[len]) || (' ' == str[len])))
{
rv = FALSE;
break;
}
}
return rv;
}
// Used for most names of things stored on the server, due to old file-formats
// that used the pipe (|) for multiline text storage. Examples include
// inventory item names, parcel names, object names, etc.
bool validateASCIIPrintableNoPipe(const LLWString &str)
{
bool rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
llwchar wc = str[len];
if (wc < 0x20
|| wc > 0x7f
|| wc == '|')
{
rv = FALSE;
break;
}
if(!(wc == ' '
|| LLStringOps::isAlnum((char)wc)
|| LLStringOps::isPunct((char)wc) ) )
{
rv = FALSE;
break;
}
}
return rv;
}
// Used for avatar names
bool validateASCIIPrintableNoSpace(const LLWString &str)
{
bool rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
llwchar wc = str[len];
if (wc < 0x20
|| wc > 0x7f
|| LLStringOps::isSpace(wc))
{
rv = FALSE;
break;
}
if( !(LLStringOps::isAlnum((char)str[len]) ||
LLStringOps::isPunct((char)str[len]) ) )
{
rv = FALSE;
break;
}
}
return rv;
}
bool validateASCII(const LLWString &str)
{
bool rv = TRUE;
S32 len = str.length();
while(len--)
{
if (str[len] < 0x20 || str[len] > 0x7f)
{
rv = FALSE;
break;
}
}
return rv;
}
bool validateASCIINoLeadingSpace(const LLWString &str)
{
if (LLStringOps::isSpace(str[0]))
{
return FALSE;
}
return validateASCII(str);
}
// Used for multiline text stored on the server.
// Example is landmark description in Places SP.
bool validateASCIIWithNewLine(const LLWString &str)
{
bool rv = TRUE;
S32 len = str.length();
while(len--)
{
if ((str[len] < 0x20 && str[len] != 0xA) || str[len] > 0x7f)
{
rv = FALSE;
break;
}
}
return rv;
}
void ValidatorImpl::setLastErrorShowTime()
{
mLastErrorShowTime = (U32Seconds)LLTimer::getTotalTime();
}
void Validator::showLastErrorUsingTimeout(U32 timeout)
{
if (mImpl && (U32Seconds)LLTimer::getTotalTime() >= mImpl->getLastErrorShowTime() + timeout)
{
mImpl->setLastErrorShowTime();
std::string reason = LLTrans::getString(mImpl->getLastErrorName(), mImpl->getLastErrorValues());
LLNotificationsUtil::add("InvalidKeystroke", LLSD().with("REASON", reason));
}
}
// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
class ValidatorFloat : public ValidatorImpl
{
template <class CHAR>
bool validate(const std::basic_string<CHAR> &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
std::basic_string<CHAR> trimmed = str;
LLStringUtilBase<CHAR>::trim(trimmed);
S32 len = trimmed.length();
if (0 < len)
{
// May be a comma or period, depending on the locale
CHAR decimal_point = LLResMgr::getInstance()->getDecimalPoint();
S32 i = 0;
// First character can be a negative sign
if ('-' == trimmed.front())
{
i++;
}
for (; i < len; i++)
{
CHAR ch = trimmed[i];
if ((decimal_point != ch) && !LLStringOps::isDigit(ch))
{
return setError("Validator_ShouldBeDigitOrDot", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
}
}
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorFloatImpl;
Validator validateFloat(validatorFloatImpl);
// Limits what characters can be used to [1234567890-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
class ValidatorInt : public ValidatorImpl
{
template <class CHAR>
bool validate(const std::basic_string<CHAR> &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
std::basic_string<CHAR> trimmed = str;
LLStringUtilBase<CHAR>::trim(trimmed);
S32 len = trimmed.length();
if (0 < len)
{
S32 i = 0;
// First character can be a negative sign
if ('-' == trimmed.front())
{
i++;
}
for (; i < len; i++)
{
CHAR ch = trimmed[i];
if (!LLStringOps::isDigit(ch))
{
return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
}
}
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorIntImpl;
Validator validateInt(validatorIntImpl);
class ValidatorPositiveS32 : public ValidatorImpl
{
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
LLLocale locale(LLLocale::USER_LOCALE);
std::basic_string<CHAR> trimmed = str;
LLStringUtilBase<CHAR>::trim(trimmed);
S32 len = trimmed.length();
if (0 < len)
{
CHAR ch = trimmed.front();
if (('-' == ch) || ('0' == ch))
{
return setError("Validator_ShouldNotBeMinusOrZero", LLSD().with("CH", llsd(ch)));
}
for (S32 i = 0; i < len; ++i)
{
ch = trimmed[i];
if (!LLStringOps::isDigit(ch))
{
return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
}
}
}
S32 val = strtol(trimmed);
if (val <= 0)
{
return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(trimmed)));
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorPositiveS32Impl;
Validator validatePositiveS32(validatorPositiveS32Impl);
class ValidatorNonNegativeS32 : public ValidatorImpl
{
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
LLLocale locale(LLLocale::USER_LOCALE);
std::basic_string<CHAR> trimmed = str;
LLStringUtilBase<CHAR>::trim(trimmed);
S32 len = trimmed.length();
if (0 < len)
{
CHAR ch = trimmed.front();
if ('-' == ch)
{
return setError("Validator_ShouldNotBeMinus", LLSD().with("CH", llsd(ch)));
}
for (S32 i = 0; i < len; ++i)
{
ch = trimmed[i];
if (!LLStringOps::isDigit(ch))
{
return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
}
}
}
S32 val = strtol(trimmed);
if (val < 0)
{
return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(trimmed)));
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorNonNegativeS32Impl;
Validator validateNonNegativeS32(validatorNonNegativeS32Impl);
class ValidatorNonNegativeS32NoSpace : public ValidatorImpl
{
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
LLLocale locale(LLLocale::USER_LOCALE);
std::basic_string<CHAR> test_str = str;
S32 len = test_str.length();
if (0 < len)
{
CHAR ch = test_str.front();
if ('-' == ch)
{
return setError("Validator_ShouldNotBeMinus", LLSD().with("CH", llsd(ch)));
}
for (S32 i = 0; i < len; ++i)
{
ch = test_str[i];
if (!LLStringOps::isDigit(ch) || LLStringOps::isSpace(ch))
{
return setError("Validator_ShouldBeDigitNotSpace", LLSD().with("NR", i + 1).with("CH", llsd(ch)));
}
}
}
S32 val = strtol(test_str);
if (val < 0)
{
return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(test_str)));
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorNonNegativeS32NoSpaceImpl;
Validator validateNonNegativeS32NoSpace(validatorNonNegativeS32NoSpaceImpl);
class ValidatorAlphaNum : public ValidatorImpl
{
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
LLLocale locale(LLLocale::USER_LOCALE);
S32 len = str.length();
while (len--)
{
CHAR ch = str[len];
if (!LLStringOps::isAlnum(ch))
{
return setError("Validator_ShouldBeDigitOrAlpha", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
}
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorAlphaNumImpl;
Validator validateAlphaNum(validatorAlphaNumImpl);
class ValidatorAlphaNumSpace : public ValidatorImpl
{
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
LLLocale locale(LLLocale::USER_LOCALE);
S32 len = str.length();
while (len--)
{
CHAR ch = str[len];
if (!LLStringOps::isAlnum(ch) && (' ' != ch))
{
return setError("Validator_ShouldBeDigitOrAlphaOrSpace", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
}
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorAlphaNumSpaceImpl;
Validator validateAlphaNumSpace(validatorAlphaNumSpaceImpl);
// Used for most names of things stored on the server, due to old file-formats
// that used the pipe (|) for multiline text storage. Examples include
// inventory item names, parcel names, object names, etc.
class ValidatorASCIIPrintableNoPipe : public ValidatorImpl
{
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
S32 len = str.length();
while (len--)
{
CHAR ch = str[len];
if (ch < 0x20 || ch > 0x7f || ch == '|' ||
(ch != ' ' && !LLStringOps::isAlnum(ch) && !LLStringOps::isPunct(ch)))
{
return setError("Validator_ShouldBeDigitOrAlphaOrPunct", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
}
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorASCIIPrintableNoPipeImpl;
Validator validateASCIIPrintableNoPipe(validatorASCIIPrintableNoPipeImpl);
// Used for avatar names
class ValidatorASCIIPrintableNoSpace : public ValidatorImpl
{
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
S32 len = str.length();
while (len--)
{
CHAR ch = str[len];
if (ch <= 0x20 || ch > 0x7f || LLStringOps::isSpace(ch) ||
(!LLStringOps::isAlnum(ch) && !LLStringOps::isPunct(ch)))
{
return setError("Validator_ShouldBeDigitOrAlphaOrPunctNotSpace", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
}
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorASCIIPrintableNoSpaceImpl;
Validator validateASCIIPrintableNoSpace(validatorASCIIPrintableNoSpaceImpl);
class ValidatorASCII : public ValidatorImpl
{
protected:
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
S32 len = str.length();
while (len--)
{
CHAR ch = str[len];
if (ch < 0x20 || ch > 0x7f)
{
return setError("Validator_ShouldBeASCII", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
}
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorASCIIImpl;
Validator validateASCII(validatorASCIIImpl);
class ValidatorASCIINoLeadingSpace : public ValidatorASCII
{
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
if (LLStringOps::isSpace(str.front()))
{
return false;
}
return ValidatorASCII::validate<CHAR>(str);
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorASCIINoLeadingSpaceImpl;
Validator validateASCIINoLeadingSpace(validatorASCIINoLeadingSpaceImpl);
class ValidatorASCIIWithNewLine : public ValidatorImpl
{
// Used for multiline text stored on the server.
// Example is landmark description in Places SP.
template <class CHAR>
bool validate(const std::basic_string<CHAR>& str)
{
S32 len = str.length();
while (len--)
{
CHAR ch = str[len];
if ((ch < 0x20 && ch != 0xA) || ch > 0x7f)
{
return setError("Validator_ShouldBeNewLineOrASCII", LLSD().with("NR", len + 1).with("CH", llsd(ch)));
}
}
return resetError();
}
public:
/*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); }
/*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); }
} validatorASCIIWithNewLineImpl;
Validator validateASCIIWithNewLine(validatorASCIIWithNewLineImpl);
void Validators::declareValues()
{
declare("ascii", validateASCII);
declare("float", validateFloat);
declare("int", validateInt);
declare("positive_s32", validatePositiveS32);
declare("non_negative_s32", validateNonNegativeS32);
declare("alpha_num", validateAlphaNum);
declare("alpha_num_space", validateAlphaNumSpace);
declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe);
declare("ascii_printable_no_space", validateASCIIPrintableNoSpace);
declare("ascii_with_newline", validateASCIIWithNewLine);
}
} // namespace LLTextValidate

View File

@ -34,27 +34,68 @@
namespace LLTextValidate
{
typedef boost::function<BOOL (const LLWString &wstr)> validate_func_t;
class ValidatorImpl
{
public:
ValidatorImpl() {}
virtual ~ValidatorImpl() {}
struct ValidateTextNamedFuncs
: public LLInitParam::TypeValuesHelper<validate_func_t, ValidateTextNamedFuncs>
{
static void declareValues();
};
virtual bool validate(const std::string& str) = 0;
virtual bool validate(const LLWString& str) = 0;
bool validateFloat(const LLWString &str );
bool validateInt(const LLWString &str );
bool validatePositiveS32(const LLWString &str);
bool validateNonNegativeS32(const LLWString &str);
bool validateNonNegativeS32NoSpace(const LLWString &str);
bool validateAlphaNum(const LLWString &str );
bool validateAlphaNumSpace(const LLWString &str );
bool validateASCIIPrintableNoPipe(const LLWString &str);
bool validateASCIIPrintableNoSpace(const LLWString &str);
bool validateASCII(const LLWString &str);
bool validateASCIINoLeadingSpace(const LLWString &str);
bool validateASCIIWithNewLine(const LLWString &str);
}
bool setError(std::string name, LLSD values = LLSD()) { return mLastErrorName = name, mLastErrorValues = values, false; }
bool resetError() { return mLastErrorName.clear(), mLastErrorValues.clear(), true; }
const std::string& getLastErrorName() const { return mLastErrorName; }
const LLSD& getLastErrorValues() const { return mLastErrorValues; }
void setLastErrorShowTime();
U32 getLastErrorShowTime() const { return mLastErrorShowTime; }
protected:
std::string mLastErrorName;
LLSD mLastErrorValues;
U32 mLastErrorShowTime { 0 };
};
class Validator
{
public:
Validator() : mImpl(nullptr) {}
Validator(ValidatorImpl& impl) : mImpl(&impl) {}
Validator(const Validator& validator) : mImpl(validator.mImpl) {}
Validator(const Validator* validator) : mImpl(validator->mImpl) {}
bool validate(const std::string& str) const { return !mImpl || mImpl->validate(str); }
bool validate(const LLWString& str) const { return !mImpl || mImpl->validate(str); }
operator bool() const { return mImpl; }
static const U32 SHOW_LAST_ERROR_TIMEOUT_SEC = 30;
void showLastErrorUsingTimeout(U32 timeout = SHOW_LAST_ERROR_TIMEOUT_SEC);
private:
ValidatorImpl* mImpl;
};
// Available validators
extern Validator validateFloat;
extern Validator validateInt;
extern Validator validatePositiveS32;
extern Validator validateNonNegativeS32;
extern Validator validateNonNegativeS32NoSpace;
extern Validator validateAlphaNum;
extern Validator validateAlphaNumSpace;
extern Validator validateASCIIPrintableNoPipe;
extern Validator validateASCIIPrintableNoSpace;
extern Validator validateASCII;
extern Validator validateASCIINoLeadingSpace;
extern Validator validateASCIIWithNewLine;
// Add available validators to the internal map
struct Validators : public LLInitParam::TypeValuesHelper<Validator, Validators>
{
static void declareValues();
};
};
#endif

View File

@ -49,6 +49,36 @@ const U32 HOURS_MAX = 12;
const U32 MINUTES_PER_HOUR = 60;
const U32 MINUTES_PER_DAY = 24 * MINUTES_PER_HOUR;
class LLTimeValidatorImpl : public LLTextValidate::ValidatorImpl
{
public:
// virtual
bool validate(const std::string& str) override
{
std::string hours = LLTimeCtrl::getHoursString(str);
if (!LLTimeCtrl::isHoursStringValid(hours))
return setError("ValidatorInvalidHours", LLSD().with("STR", hours));
std::string minutes = LLTimeCtrl::getMinutesString(str);
if (!LLTimeCtrl::isMinutesStringValid(minutes))
return setError("ValidatorInvalidMinutes", LLSD().with("STR", minutes));
std::string ampm = LLTimeCtrl::getAMPMString(str);
if (!LLTimeCtrl::isPMAMStringValid(ampm))
return setError("ValidatorInvalidAMPM", LLSD().with("STR", ampm));
return resetError();
}
// virtual
bool validate(const LLWString& wstr) override
{
std::string str = wstring_to_utf8str(wstr);
return validate(str);
}
} validateTimeImpl;
LLTextValidate::Validator validateTime(validateTimeImpl);
LLTimeCtrl::Params::Params()
: label_width("label_width"),
@ -111,7 +141,7 @@ LLTimeCtrl::LLTimeCtrl(const LLTimeCtrl::Params& p)
params.keystroke_callback(boost::bind(&LLTimeCtrl::onTextEntry, this, _1));
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace);
mEditor->setPrevalidate(boost::bind(&LLTimeCtrl::isTimeStringValid, this, _1));
mEditor->setPrevalidate(validateTime);
mEditor->setText(LLStringExplicit("12:00 AM"));
addChild(mEditor);
@ -247,15 +277,6 @@ void LLTimeCtrl::onTextEntry(LLLineEditor* line_editor)
mTime = h24 * MINUTES_PER_HOUR + m;
}
bool LLTimeCtrl::isTimeStringValid(const LLWString &wstr)
{
std::string str = wstring_to_utf8str(wstr);
return isHoursStringValid(getHoursString(str)) &&
isMinutesStringValid(getMinutesString(str)) &&
isPMAMStringValid(getAMPMString(str));
}
void LLTimeCtrl::increaseMinutes()
{
mTime = (mTime + mSnapToMin) % MINUTES_PER_DAY - (mTime % mSnapToMin);

View File

@ -60,6 +60,18 @@ public:
void setTime24(F32 time); // 0.0 - 23.98(3)
static std::string getHoursString(const std::string& str);
static std::string getMinutesString(const std::string& str);
static std::string getAMPMString(const std::string& str);
static bool isHoursStringValid(const std::string& str);
static bool isMinutesStringValid(const std::string& str);
static bool isPMAMStringValid(const std::string& str);
static U32 parseHours(const std::string& str);
static U32 parseMinutes(const std::string& str);
static bool parseAMPM(const std::string& str);
protected:
LLTimeCtrl(const Params&);
friend class LLUICtrlFactory;
@ -87,8 +99,6 @@ private:
void onDownBtn();
void onTextEntry(LLLineEditor* line_editor);
bool isTimeStringValid(const LLWString& wstr);
void increaseMinutes();
void increaseHours();
@ -102,18 +112,6 @@ private:
EEditingPart getEditingPart();
static std::string getHoursString(const std::string& str);
static std::string getMinutesString(const std::string& str);
static std::string getAMPMString(const std::string& str);
static bool isHoursStringValid(const std::string& str);
static bool isMinutesStringValid(const std::string& str);
static bool isPMAMStringValid(const std::string& str);
static U32 parseHours(const std::string& str);
static U32 parseMinutes(const std::string& str);
static bool parseAMPM(const std::string& str);
class LLTextBox* mLabelBox;
class LLLineEditor* mEditor;

View File

@ -44,12 +44,12 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<s
bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root, LLDir::ALL_SKINS);
if (!success)
{
//gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
const std::string error_string =
"Firestorm couldn't access some of the files it needs and will be closed."
"\n\nPlease reinstall viewer from https://www.firestormviewer.org/download and "
"contact https://www.firestormviewer.org/support if issue persists after reinstall.";
LLError::LLUserWarningMsg::show(error_string);
gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << LL_ENDL;
return false;
}

View File

@ -399,8 +399,8 @@ void FloaterAO::onRenameSet()
if (!name.empty())
{
if (
LLTextValidate::validateASCIIPrintableNoPipe(new_set_name.getWString()) && // only allow ASCII
name.find_first_of(":|") == std::string::npos) // don't allow : or |
LLTextValidate::validateASCIIPrintableNoPipe.validate(new_set_name.getWString()) && // only allow ASCII
name.find_first_of(":|") == std::string::npos) // don't allow : or |
{
if (AOEngine::instance().renameSet(mSelectedSet, name))
{
@ -523,8 +523,8 @@ bool FloaterAO::newSetCallback(const LLSD& notification, const LLSD& response)
return false;
}
else if (
!LLTextValidate::validateASCIIPrintableNoPipe(new_set_name.getWString()) || // only allow ASCII
newSetName.find_first_of(":|") != std::string::npos) // don't allow : or |
!LLTextValidate::validateASCIIPrintableNoPipe.validate(new_set_name.getWString()) || // only allow ASCII
newSetName.find_first_of(":|") != std::string::npos) // don't allow : or |
{
LLSD args;
args["AO_SET_NAME"] = newSetName;

View File

@ -40,6 +40,7 @@
#include "llscrolllistitem.h"
#include "llsdserialize.h"
#include "lltextbox.h"
#include "lltrans.h"
#include "llviewerchat.h"
#include "llviewercontrol.h" // <FS:Beq/> Add B&W emoji font support
@ -401,9 +402,12 @@ void LLFloaterEmojiPicker::initialize()
}
else
{
const std::string prompt("No emoji found for ");
std::string title(prompt + '"' + mFilterPattern.substr(1) + '"');
mPreview->setData(EMPTY_LIST_IMAGE_INDEX, title, prompt.size() + 1, title.size() - 1);
std::size_t begin, end;
LLStringUtil::format_map_t args;
args["[FILTER]"] = mFilterPattern.substr(1);
std::string title(getString("text_no_emoji_for_filter", args));
LLEmojiDictionary::searchInShortCode(begin, end, title, mFilterPattern);
mPreview->setData(EMPTY_LIST_IMAGE_INDEX, title, begin, end);
showPreview(true);
}
return;

View File

@ -285,9 +285,7 @@ void LLFloaterSellLandUI::refreshUI()
getChild<LLUICtrl>("info_size")->setTextArg("[AREA]", llformat("%d", mParcelActualArea));
std::string price_str = getChild<LLUICtrl>("price")->getValue().asString();
bool valid_price = false;
valid_price = (price_str != "") && LLTextValidate::validateNonNegativeS32(utf8str_to_wstring(price_str));
bool valid_price = !price_str.empty() && LLTextValidate::validateNonNegativeS32.validate(price_str);
if (valid_price && mParcelActualArea > 0)
{
F32 per_meter_price = 0;
@ -301,7 +299,7 @@ void LLFloaterSellLandUI::refreshUI()
{
getChildView("price_per_m")->setVisible(FALSE);
if ("" == price_str)
if (price_str.empty())
{
setBadge("step_price", BADGE_NOTE);
}
@ -333,9 +331,7 @@ void LLFloaterSellLandUI::refreshUI()
// Must select Sell To: Anybody, or User (with a specified username)
std::string sell_to = getChild<LLUICtrl>("sell_to")->getValue().asString();
bool valid_sell_to = "select" != sell_to &&
("user" != sell_to || mAuthorizedBuyer.notNull());
bool valid_sell_to = "select" != sell_to && ("user" != sell_to || mAuthorizedBuyer.notNull());
if (!valid_sell_to)
{
setBadge("step_sell_to", BADGE_NOTE);
@ -346,7 +342,6 @@ void LLFloaterSellLandUI::refreshUI()
}
bool valid_sell_objects = ("none" != getChild<LLUICtrl>("sell_objects")->getValue().asString());
if (!valid_sell_objects)
{
setBadge("step_sell_objects", BADGE_NOTE);

View File

@ -62,7 +62,7 @@ void LLURLLineEditor::cut()
deleteSelection();
// Validate new string and rollback the if needed.
BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString());
if( need_to_rollback )
{
rollback.doRollback( this );

View File

@ -260,7 +260,7 @@
left="10"
max_length_bytes="63"
name="description"
prevalidate_callback="ascii"
prevalidator="ascii"
select_on_focus="true"
text_color="Black"
top_pad="3"

View File

@ -38,7 +38,7 @@
layout="topleft"
max_length_bytes="63"
name="title_editor"
prevalidate_callback="ascii"
prevalidator="ascii"
text_readonly_color="white"
top_pad="5"
width="290" />
@ -86,7 +86,7 @@
name="notes_editor"
spellcheck="true"
text_readonly_color="white"
text_type="ascii_with_newline"
prevalidator="ascii_with_newline"
commit_on_focus_lost="true"
top_pad="5"
width="290"

View File

@ -60,7 +60,7 @@
left_pad="10"
max_length_bytes="100"
name="day_cycle_name"
prevalidate_callback="ascii"
prevalidator="ascii"
top="5"
width="200"
height="21" />

View File

@ -15,6 +15,7 @@
width="304">
<floater.string name="title_for_recently_used" value="Recently used"/>
<floater.string name="title_for_frequently_used" value="Frequently used"/>
<floater.string name="text_no_emoji_for_filter" value="No emoji found for '[FILTER]'"/>
<scroll_container
name="EmojiGridContainer"
layout="topleft"

View File

@ -44,7 +44,7 @@
left_delta="45"
width="250"
name="settings_name"
prevalidate_callback="ascii"
prevalidator="ascii"
max_length_chars="63"
height="20"/>
<button

View File

@ -98,7 +98,7 @@
height="19"
max_length_bytes="63"
name="description_form"
prevalidate_callback="ascii"
prevalidator="ascii"
top_pad="5"
width="290" />
</panel>

View File

@ -23,7 +23,7 @@
layout="topleft"
left_delta="0"
name="ascii_line_editor"
prevalidate_callback="ascii"
prevalidator="ascii"
tool_tip="ascii line editor"
top_pad="10"
width="200">

View File

@ -38,7 +38,7 @@
name="numeric_text_editor"
tool_tip="text editor for numeric text entry only"
top_pad="10"
text_type="int"
prevalidator="int"
width="200">
This is text that is NOT a number, so shouldn't appear
</text_editor>

View File

@ -414,6 +414,15 @@ Initialization with the Marketplace failed because of a system or network error.
yestext="OK"/>
</notification>
<notification
icon="notifytip.tga"
name="InvalidKeystroke"
type="notifytip">
There was an invalid keystroke entered.
[REASON].
Please input a valid text.
</notification>
<notification
icon="alertmodal.tga"
name="MerchantForceValidateListing"

View File

@ -260,7 +260,7 @@
left="10"
max_length_bytes="63"
name="description"
prevalidate_callback="ascii"
prevalidator="ascii"
select_on_focus="true"
text_color="Black"
top_pad="3"

View File

@ -97,7 +97,7 @@
max_chars="128"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
tool_tip="The account name you chose when you registered, like bobsmith420 or Steller Sunshine"
top_delta="0"
name="username_combo"
@ -196,7 +196,7 @@
max_chars="256"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
name="server_combo"
width="135"
combo_button.scale_image="true" >

View File

@ -105,7 +105,7 @@
max_chars="128"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
name="username_combo"
width="201">
@ -273,7 +273,7 @@
left_pad="5"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
layout="topleft"
top_pad="-32"
name="server_combo"

View File

@ -157,7 +157,7 @@ Maximum 200 per group daily
left_pad="-1"
max_length_chars="63"
name="create_subject"
prevalidate_callback="ascii"
prevalidator="ascii"
spellcheck="true"
width="371" />

View File

@ -337,7 +337,7 @@
height="22"
layout="topleft"
name="title_editor"
prevalidate_callback="ascii"
prevalidator="ascii"
text_readonly_color="white"
top_delta="0"
right="-1" />

View File

@ -54,7 +54,7 @@
combo_editor.font="SansSerifLarge"
max_chars="128"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
name="username_combo"
width="206">

View File

@ -111,7 +111,7 @@
combo_editor.font="SansSerifLarge"
max_chars="128"
top="0"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
name="username_combo"
width="232">

View File

@ -483,7 +483,7 @@
layout="topleft"
font="SansSerif"
max_length_bytes="30"
prevalidate_callback="ascii"
prevalidator="ascii"
commit_on_focus_lost="false"
text_color="black"
/>

View File

@ -208,7 +208,7 @@ TestString PleaseIgnore
Description:
</text>
<text_editor
text_type="ascii_printable_no_pipe"
prevalidator="ascii_printable_no_pipe"
commit_on_focus_lost="true"
word_wrap="true"
use_ellipses="false"

View File

@ -666,6 +666,21 @@ https://www.firestormviewer.org/support for help fixing this problem.
<string name="executable_files">Executable Program Files</string>
<!-- LSL Usage Hover Tips -->
<!-- Text validator error messages -->
<string name="Validator_InvalidNumericString">Invalid numeric string: "[STR]"</string>
<string name="Validator_ShouldNotBeMinus">Invalid initial character: '[CH]' (shouldn't be a minus)</string>
<string name="Validator_ShouldNotBeMinusOrZero">Invalid initial character: '[CH]' (shouldn't be either a minus or a zero)</string>
<string name="Validator_ShouldBeDigit">Invalid character [NR]: '[CH]' (should only be a digit)</string>
<string name="Validator_ShouldBeDigitOrDot">Invalid character [NR]: '[CH]' (should only be a digit or a decimal point)</string>
<string name="Validator_ShouldBeDigitOrAlpha">Invalid character [NR]: '[CH]' (should only be a digit or an alpha-numeric ASCII character)</string>
<string name="Validator_ShouldBeDigitOrAlphaOrSpace">Invalid character [NR]: '[CH]' (should only be a digit or an alpha-numeric ASCII character or a space)</string>
<string name="Validator_ShouldBeDigitOrAlphaOrPunct">Invalid character [NR]: '[CH]' (should only be a digit or an alpha-numeric ASCII character or a punctuation)</string>
<string name="Validator_ShouldBeDigitOrAlphaOrPunctNotSpace">Invalid character [NR]: '[CH]' (should only be a digit or an alpha-numeric ASCII character or a punctuation with no space)</string>
<string name="Validator_ShouldBeDigitNotSpace">Invalid character [NR]: '[CH]' (should only be a digit with no space)</string>
<string name="Validator_ShouldBeASCII">Invalid character [NR]: '[CH]' (should only be an ASCII character)</string>
<string name="Validator_ShouldBeNewLineOrASCII">Invalid character [NR]: '[CH]' (should only be an ASCII character or a new line)</string>
<!-- LSL Usage Hover Tips -->
<string name="LSLTipSleepTime" translate="false">Sleeps script for [SLEEP_TIME] seconds.</string>
<!-- (FS:CR) LSL Hover Tips have been moved into scriptlibrary_*.xml so they can be dynamically updated -->

View File

@ -3,7 +3,7 @@
<line_editor name="enabled_line_editor" tool_tip="有効なラインエディタ">
ラインエディタを有効化
</line_editor>
<line_editor name="ascii_line_editor" prevalidate_callback="ascii" tool_tip="asciiラインエディタ">
<line_editor name="ascii_line_editor" tool_tip="asciiラインエディタ">
ASCIIのみのラインエディタ
</line_editor>
<line_editor name="disabled_line_editor" tool_tip="無効なラインエディタ">

View File

@ -23,7 +23,7 @@
layout="topleft"
left_delta="0"
name="ascii_line_editor"
prevalidate_callback="ascii"
prevalidator="ascii"
tool_tip="ascii line editor"
top_pad="10"
width="200">

View File

@ -125,7 +125,7 @@
top_pad="2"
max_length_bytes="63"
name="classified_name"
prevalidate_callback="ascii"
prevalidator="ascii"
text_color="SL-Black"
width="273" />
<text

View File

@ -260,7 +260,7 @@
left="10"
max_length_bytes="63"
name="description"
prevalidate_callback="ascii"
prevalidator="ascii"
select_on_focus="true"
text_color="SL-Black"
top_pad="3"

View File

@ -97,7 +97,7 @@
max_chars="128"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
tool_tip="The account name you chose when you registered, like bobsmith420 or Steller Sunshine"
top_delta="0"
name="username_combo"
@ -197,7 +197,7 @@
max_chars="256"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
left="10"
top="51"
layout="topleft"

View File

@ -105,7 +105,7 @@
max_chars="128"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
name="username_combo"
width="201">
@ -273,7 +273,7 @@
left_pad="5"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
layout="topleft"
top_pad="-32"
name="server_combo"

View File

@ -143,7 +143,7 @@ Maximum 200 per group daily
left_pad="3"
max_length_chars="63"
name="create_subject"
prevalidate_callback="ascii"
prevalidator="ascii"
width="218" />
<text
follows="left|top"

View File

@ -349,7 +349,7 @@
left="0"
max_length_bytes="63"
name="title_editor"
prevalidate_callback="ascii"
prevalidator="ascii"
text_readonly_color="White"
top_delta="0"
width="290" />

View File

@ -23,7 +23,7 @@
layout="topleft"
left_delta="0"
name="ascii_line_editor"
prevalidate_callback="ascii"
prevalidator="ascii"
tool_tip="ascii line editor"
top_pad="10"
width="200">

View File

@ -125,7 +125,7 @@
top_pad="2"
max_length_bytes="63"
name="classified_name"
prevalidate_callback="ascii"
prevalidator="ascii"
text_color="SL-Black"
width="273" />
<text

View File

@ -260,7 +260,7 @@
left="10"
max_length_bytes="63"
name="description"
prevalidate_callback="ascii"
prevalidator="ascii"
select_on_focus="true"
text_color="SL-Black"
top_pad="3"

View File

@ -83,7 +83,7 @@
left_delta="0"
max_chars="128"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
tool_tip="The account name you chose when you registered, like bobsmith420 or Steller Sunshine"
top_pad="0"
name="username_combo"
@ -196,7 +196,7 @@ tool_tip="The account name you chose when you registered, like bobsmith420 or St
max_chars="256"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
left="10"
top="51"
layout="topleft"

View File

@ -105,7 +105,7 @@
max_chars="128"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
name="username_combo"
width="201">
@ -273,7 +273,7 @@
left_pad="5"
force_disable_fulltext_search="true"
combo_editor.commit_on_focus_lost="false"
combo_editor.prevalidate_callback="ascii"
combo_editor.prevalidator="ascii"
layout="topleft"
top_pad="-32"
name="server_combo"

View File

@ -143,7 +143,7 @@ Maximum 200 per group daily
left_pad="3"
max_length_chars="63"
name="create_subject"
prevalidate_callback="ascii"
prevalidator="ascii"
width="218" />
<text
follows="left|top"

View File

@ -349,7 +349,7 @@
left="0"
max_length_bytes="63"
name="title_editor"
prevalidate_callback="ascii"
prevalidator="ascii"
text_readonly_color="White"
top_delta="0"
width="290" />

View File

@ -458,7 +458,7 @@
follows="left|top|right"
layout="topleft"
max_length_bytes="30"
prevalidate_callback="ascii"
prevalidator="ascii"
commit_on_focus_lost="false"
/>
<text