diff options
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llcommon/indra_constants.h | 11 | ||||
| -rw-r--r-- | indra/llcommon/llapr.cpp | 151 | ||||
| -rw-r--r-- | indra/llcommon/llapr.h | 7 | ||||
| -rw-r--r-- | indra/llcommon/llcoros.cpp | 2 | ||||
| -rw-r--r-- | indra/llcommon/llkeybind.cpp | 395 | ||||
| -rw-r--r-- | indra/llcommon/llkeybind.h | 106 | ||||
| -rw-r--r-- | indra/llcommon/llsdserialize.cpp | 2 | 
8 files changed, 609 insertions, 67 deletions
| diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index af41b9e460..7e52a620db 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -73,6 +73,7 @@ set(llcommon_SOURCE_FILES      llinitparam.cpp      llinitdestroyclass.cpp      llinstancetracker.cpp +    llkeybind.cpp      llleap.cpp      llleaplistener.cpp      llliveappconfig.cpp @@ -183,6 +184,7 @@ set(llcommon_HEADER_FILES      llinitdestroyclass.h      llinitparam.h      llinstancetracker.h +    llkeybind.h      llkeythrottle.h      llleap.h      llleaplistener.h diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 0fbf4b966b..ef29e7e5cd 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -54,6 +54,17 @@ enum ETerrainBrushType  	E_LANDBRUSH_INVALID = 6  }; +enum EMouseClickType{ +    CLICK_NONE = -1, +    CLICK_LEFT = 0, +    CLICK_MIDDLE, +    CLICK_RIGHT, +    CLICK_BUTTON4, +    CLICK_BUTTON5, +    CLICK_DOUBLELEFT, +    CLICK_COUNT // 'size', CLICK_NONE does not counts +}; +  // keys  // Bit masks for various keyboard modifier keys.  const MASK MASK_NONE =			0x0000; diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 29f0c7da9a..984e90f376 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -242,6 +242,64 @@ void _ll_apr_assert_status(apr_status_t status, const char* file, int line)  //---------------------------------------------------------------------  // +// Scope based pool access +// +//--------------------------------------------------------------------- + +class LLAPRFilePoolScope +{ +public: +    LLAPRFilePoolScope() : pPool(NULL), mInitialized(false) {} +    LLAPRFilePoolScope(LLVolatileAPRPool* poolp) : mInitialized(false) +    {  +        setFilePool(poolp); +    } +    ~LLAPRFilePoolScope() +    { +        reset(); +    } +    apr_pool_t* getVolatileAPRPool(LLVolatileAPRPool* poolp = NULL) +    { +        if (!pPool) +        { +            setFilePool(poolp); +        } +        if (mInitialized) +        { +            // We need one clear per one get +            // At the moment no need to support multiple calls +            LL_ERRS() << "LLAPRFilePoolScope is not supposed to be initialized twice" << LL_ENDL; +        } +        mInitialized = true; +        return pPool->getVolatileAPRPool(); +    } +    void reset() +    { +        if (mInitialized) +        { +            pPool->clearVolatileAPRPool(); +        } +    } + +private: +    void setFilePool(LLVolatileAPRPool* poolp = NULL) +    { +        if (poolp) +        { +            pPool = poolp; +        } +        else +        { +            pPool = LLAPRFile::sAPRFilePoolp; +        } +    } + +    LLVolatileAPRPool *pPool; +    bool mInitialized; +}; + +//--------------------------------------------------------------------- +//  // LLAPRFile functions  //  LLAPRFile::LLAPRFile() @@ -287,9 +345,10 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV  	//check if already open some file  	llassert_always(!mFile) ;  	llassert_always(!mCurrentFilePoolp) ; -	 -	apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ; -	s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool)); + +	mCurrentFilePoolp = pool ? pool : sAPRFilePoolp; +	apr_pool_t* apr_pool = mCurrentFilePoolp->getVolatileAPRPool(); //paired with clear in close() +	s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);  	if (s != APR_SUCCESS || !mFile)  	{ @@ -314,14 +373,10 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV  		*sizep = file_size;  	} -	if(!mCurrentFilePoolp) +	if (!mFile)  	{ -		mCurrentFilePoolp = pool ; - -		if(!mFile) -		{ -			close() ; -		} +		// It will clean pool +		close() ;  	}  	return s ; @@ -348,17 +403,6 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOO  	return s;  } -apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool) -{	 -	if(!pool) -	{ -		mCurrentFilePoolp = sAPRFilePoolp ; -		return mCurrentFilePoolp->getVolatileAPRPool() ; -	} - -	return pool ; -} -  // File I/O  S32 LLAPRFile::read(void *buf, S32 nbytes)  { @@ -415,7 +459,7 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)  //  //static -apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool)  +apr_status_t LLAPRFile::close(apr_file_t* file_handle)   {  	apr_status_t ret = APR_SUCCESS ;  	if(file_handle) @@ -424,29 +468,23 @@ apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool)  		file_handle = NULL ;  	} -	if(pool) -	{ -		pool->clearVolatileAPRPool() ; -	} -  	return ret ;  }  //static -apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags) +apr_file_t* LLAPRFile::open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags)  {  	apr_status_t s;  	apr_file_t* file_handle ; -	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; -	s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool()); +	s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);  	if (s != APR_SUCCESS || !file_handle)  	{  		ll_apr_warn_status(s);  		LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;  		file_handle = NULL ; -		close(file_handle, pool) ; +		close(file_handle) ;  		return NULL;  	} @@ -489,8 +527,9 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)  S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)  {  	//***************************************** -	apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY);  -	//*****************************************	 +	LLAPRFilePoolScope scope(pool); +	apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY);  +	//*****************************************  	if (!file_handle)  	{  		return 0; @@ -523,7 +562,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb  	}  	//***************************************** -	close(file_handle, pool) ;  +	close(file_handle) ;   	//*****************************************  	return (S32)bytes_read;  } @@ -537,9 +576,10 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n  		flags |= APR_APPEND;  		offset = 0;  	} -	 +  	//***************************************** -	apr_file_t* file_handle = open(filename, pool, flags); +	LLAPRFilePoolScope scope(pool); +	apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), flags);  	//*****************************************  	if (!file_handle)  	{ @@ -573,7 +613,7 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n  	}  	//***************************************** -	LLAPRFile::close(file_handle, pool); +	LLAPRFile::close(file_handle);  	//*****************************************  	return (S32)bytes_written; @@ -584,9 +624,8 @@ bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)  {  	apr_status_t s; -	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; -	s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool()); -	pool->clearVolatileAPRPool() ; +	LLAPRFilePoolScope scope(pool); +	s = apr_file_remove(filename.c_str(), scope.getVolatileAPRPool());  	if (s != APR_SUCCESS)  	{ @@ -602,9 +641,8 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname,  {  	apr_status_t s; -	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; -	s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool()); -	pool->clearVolatileAPRPool() ; +	LLAPRFilePoolScope scope(pool); +	s = apr_file_rename(filename.c_str(), newname.c_str(), scope.getVolatileAPRPool());  	if (s != APR_SUCCESS)  	{ @@ -621,18 +659,16 @@ bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, ap  	apr_file_t* apr_file;  	apr_status_t s; -	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; -	s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());	 +	LLAPRFilePoolScope scope(pool); +	s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, scope.getVolatileAPRPool());	  	if (s != APR_SUCCESS || !apr_file)  	{ -		pool->clearVolatileAPRPool() ;  		return false;  	}  	else  	{  		apr_file_close(apr_file) ; -		pool->clearVolatileAPRPool() ;  		return true;  	}  } @@ -643,14 +679,12 @@ S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)  	apr_file_t* apr_file;  	apr_finfo_t info;  	apr_status_t s; -	 -	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; -	s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool()); + +	LLAPRFilePoolScope scope(pool); +	s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, scope.getVolatileAPRPool());  	if (s != APR_SUCCESS || !apr_file) -	{		 -		pool->clearVolatileAPRPool() ; -		 +	{				  		return 0;  	}  	else @@ -658,7 +692,6 @@ S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)  		apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);		  		apr_file_close(apr_file) ; -		pool->clearVolatileAPRPool() ;  		if (s == APR_SUCCESS)  		{ @@ -676,9 +709,8 @@ bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)  {  	apr_status_t s; -	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; -	s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool()); -	pool->clearVolatileAPRPool() ; +	LLAPRFilePoolScope scope(pool); +	s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, scope.getVolatileAPRPool());  	if (s != APR_SUCCESS)  	{ @@ -694,9 +726,8 @@ bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)  {  	apr_status_t s; -	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ; -	s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool()); -	pool->clearVolatileAPRPool() ; +	LLAPRFilePoolScope scope(pool); +	s = apr_file_remove(dirname.c_str(), scope.getVolatileAPRPool());  	if (s != APR_SUCCESS)  	{ diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index da50dda103..0d6637f999 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -180,9 +180,6 @@ public:  	S32 write(const void* buf, S32 nbytes);  	apr_file_t* getFileHandle() {return mFile;}	 - -private: -	apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;	  //  //******************************************************************************************************************************* @@ -192,8 +189,8 @@ public:  	static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.  private: -	static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags); -	static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ; +	static apr_file_t* open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags); +	static apr_status_t close(apr_file_t* file) ;  	static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);  public:  	// returns false if failure: diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 67e9fad1ab..cc775775bf 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -347,7 +347,7 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla      // run the code the caller actually wants in the coroutine      try      { -#if LL_WINDOWS +#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD          winlevel(callable);  #else          callable(); diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp new file mode 100644 index 0000000000..ecfc289cb3 --- /dev/null +++ b/indra/llcommon/llkeybind.cpp @@ -0,0 +1,395 @@ +/**  + * @file llkeybind.cpp + * @brief Information about key combinations. + * + * $LicenseInfo:firstyear=2019&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2019, 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$ + */ + +#include "linden_common.h" + +#include "llkeybind.h" + +#include "llsd.h" +#include "llsdutil.h" + +LLKeyData::LLKeyData() +    : +    mMouse(CLICK_NONE), +    mKey(KEY_NONE), +    mMask(MASK_NONE), +    mIgnoreMasks(false) +{ +} + +LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask) +    : +    mMouse(mouse), +    mKey(key), +    mMask(mask), +    mIgnoreMasks(false) +{ +} + +LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask) +    : +    mMouse(mouse), +    mKey(key), +    mMask(MASK_NONE), +    mIgnoreMasks(ignore_mask) +{ +} + +LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) +    : +    mMouse(mouse), +    mKey(key), +    mMask(mask), +    mIgnoreMasks(ignore_mask) +{ +} + +LLKeyData::LLKeyData(const LLSD &key_data) +{ +    if (key_data.has("mouse")) +    { +        mMouse = (EMouseClickType)key_data["mouse"].asInteger(); +    } +    if (key_data.has("key")) +    { +        mKey = key_data["key"].asInteger(); +    } +    if (key_data.has("ignore_accelerators")) +    { +        mIgnoreMasks = key_data["ignore_accelerators"]; +    } +    if (key_data.has("mask")) +    { +        mMask = key_data["mask"].asInteger(); +    } +} + +LLSD LLKeyData::asLLSD() const +{ +    LLSD data; +    data["mouse"] = (LLSD::Integer)mMouse; +    data["key"] = (LLSD::Integer)mKey; +    data["mask"] = (LLSD::Integer)mMask; +    if (mIgnoreMasks) +    { +        data["ignore_accelerators"] = (LLSD::Boolean)mIgnoreMasks; +    } +    return data; +} + +bool LLKeyData::isEmpty() const +{ +    return mMouse == CLICK_NONE && mKey == KEY_NONE; +} + +void LLKeyData::reset() +{ +    mMouse = CLICK_NONE; +    mKey = KEY_NONE; +    mMask = MASK_NONE; +    mIgnoreMasks = false; +} + +LLKeyData& LLKeyData::operator=(const LLKeyData& rhs) +{ +    mMouse = rhs.mMouse; +    mKey = rhs.mKey; +    mMask = rhs.mMask; +    mIgnoreMasks = rhs.mIgnoreMasks; +    return *this; +} + +bool LLKeyData::operator==(const LLKeyData& rhs) +{ +    if (mMouse != rhs.mMouse) return false; +    if (mKey != rhs.mKey) return false; +    if (mMask != rhs.mMask) return false; +    if (mIgnoreMasks != rhs.mIgnoreMasks) return false; +    return true; +} + +bool LLKeyData::operator!=(const LLKeyData& rhs) +{ +    if (mMouse != rhs.mMouse) return true; +    if (mKey != rhs.mKey) return true; +    if (mMask != rhs.mMask) return true; +    if (mIgnoreMasks != rhs.mIgnoreMasks) return true; +    return false; +} + +bool LLKeyData::canHandle(const LLKeyData& data) const +{ +    if (data.mKey == mKey +        && data.mMouse == mMouse +        && ((mIgnoreMasks && (data.mMask & mMask) == data.mMask) || data.mMask == mMask)) +    { +        return true; +    } +    return false; +} + +bool LLKeyData::canHandle(EMouseClickType mouse, KEY key, MASK mask) const +{ +    if (mouse == mMouse +        && key == mKey +        && ((mIgnoreMasks && (mask & mMask) == mask) || mask == mMask)) +    { +        return true; +    } +    return false; +} + +// LLKeyBind + +LLKeyBind::LLKeyBind(const LLSD &key_bind) +{ +    if (key_bind.isArray()) +    { +        for (LLSD::array_const_iterator data = key_bind.beginArray(), endLists = key_bind.endArray(); +            data != endLists; +            data++ +            ) +        { +            mData.push_back(LLKeyData(*data)); +        } +    } +} + +bool LLKeyBind::operator==(const LLKeyBind& rhs) +{ +    U32 size = mData.size(); +    if (size != rhs.mData.size()) return false; + +    for (U32 i = 0; i < size; i++) +    { +        if (mData[i] != rhs.mData[i]) return false; +    } + +    return true; +} + +bool LLKeyBind::operator!=(const LLKeyBind& rhs) +{ +    U32 size = mData.size(); +    if (size != rhs.mData.size()) return true; + +    for (U32 i = 0; i < size; i++) +    { +        if (mData[i] != rhs.mData[i]) return true; +    } + +    return false; +} + +bool LLKeyBind::isEmpty() const +{ +    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++) +    { +        if (!iter->isEmpty()) return false; +    } +    return true; +} + +LLSD LLKeyBind::asLLSD() const +{ +    S32 last = mData.size() - 1; +    while (mData[last].empty()) +    { +        last--; +    } + +    LLSD data; +    for (S32 i = 0; i <= last; ++i) +    { +        // append even if empty to not affect visual representation +        data.append(mData[i].asLLSD()); +    } +    return data; +} + +bool LLKeyBind::canHandle(EMouseClickType mouse, KEY key, MASK mask) const +{ +    if (mouse == CLICK_NONE && key == KEY_NONE) +    { +        // assume placeholder +        return false; +    } + +    for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++) +    { +        if (iter->canHandle(mouse, key, mask)) +        { +            return true; +        } +    } +    return false; +} + +bool LLKeyBind::canHandleKey(KEY key, MASK mask) const +{ +    return canHandle(CLICK_NONE, key, mask); +} + +bool LLKeyBind::canHandleMouse(EMouseClickType mouse, MASK mask) const +{ +    return canHandle(mouse, KEY_NONE, mask); +} + +bool LLKeyBind::hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const +{ +    if (mouse != CLICK_NONE || key != KEY_NONE) +    { +        for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++) +        { +            if (iter->mKey == key +                && iter->mMask == mask +                && iter->mMouse == mouse +                && iter->mIgnoreMasks == ignore) +            { +                return true; +            } +        } +    } +    return false; +} + +bool LLKeyBind::hasKeyData(const LLKeyData& data) const +{ +    return hasKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks); +} + +bool LLKeyBind::hasKeyData(U32 index) const +{ +    return mData.size() > index; +} + +S32 LLKeyBind::findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const +{ +    if (mouse != CLICK_NONE || key != KEY_NONE) +    { +        for (S32 i = 0; i < mData.size(); ++i) +        { +            if (mData[i].mKey == key +                && mData[i].mMask == mask +                && mData[i].mMouse == mouse +                && mData[i].mIgnoreMasks == ignore) +            { +                return i; +            } +        } +    } +    return -1; +} + +S32 LLKeyBind::findKeyData(const LLKeyData& data) const +{ +    return findKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks); +} + +LLKeyData LLKeyBind::getKeyData(U32 index) const +{ +    if (mData.size() > index) +    { +        return mData[index]; +    } +    return LLKeyData(); +} + +bool LLKeyBind::addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) +{ +    if (!hasKeyData(mouse, key, mask, ignore)) +    { +        mData.push_back(LLKeyData(mouse, key, mask, ignore)); +        return true; +    } +    return false; +} + +bool LLKeyBind::addKeyData(const LLKeyData& data) +{ +    if (!hasKeyData(data)) +    { +        mData.push_back(data); +        return true; +    } +    return false; +} + +void LLKeyBind::replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index) +{ +    replaceKeyData(LLKeyData(mouse, key, mask, ignore), index); +} + +void LLKeyBind::replaceKeyData(const LLKeyData& data, U32 index) +{ +    if (!data.isEmpty()) +    { +        // if both click and key are none (isEmpty()), we are inserting a placeholder, we don't want to reset anything +        // otherwise reset identical key +        for (data_vector_t::iterator iter = mData.begin(); iter != mData.end(); iter++) +        { +            if (iter->mKey == data.mKey +                && iter->mMouse == data.mMouse +                && iter->mIgnoreMasks == data.mIgnoreMasks +                && iter->mMask == data.mMask) +            { +                // Replacing only fully equal combinations even in case 'ignore' is set +                // Reason: Simplicity and user might decide to do a 'move' command as W and Shift+Ctrl+W, and 'run' as Shift+W +                iter->reset(); +                break; +            } +        } +    } +    if (mData.size() <= index) +    { +        mData.resize(index + 1); +    } +    mData[index] = data; +} + +void LLKeyBind::resetKeyData(S32 index) +{ +    if (mData.size() > index) +    { +        mData[index].reset(); +    } +} + +void LLKeyBind::trimEmpty() +{ +    S32 last = mData.size() - 1; +    while (last >= 0 && mData[last].empty()) +    { +        mData.erase(mData.begin() + last); +        last--; +    } +} + +U32 LLKeyBind::getDataCount() +{ +    return mData.size(); +} + diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h new file mode 100644 index 0000000000..ad0ebec67c --- /dev/null +++ b/indra/llcommon/llkeybind.h @@ -0,0 +1,106 @@ +/**  + * @file llkeybind.h + * @brief Information about key combinations. + * + * $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$ + */ + +#ifndef LL_KEYBIND_H +#define LL_KEYBIND_H + +#include "indra_constants.h" + +// KeyData - single key combination (mouse/mask/keyboard) +class LL_COMMON_API LLKeyData +{ +public: +    LLKeyData(); +    LLKeyData(EMouseClickType mouse, KEY key, MASK mask); +    LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask); +    LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask); +    LLKeyData(const LLSD &key_data); + +    LLSD asLLSD() const; +    bool isEmpty() const; +    bool empty() const { return isEmpty(); }; +    void reset(); +    LLKeyData& operator=(const LLKeyData& rhs); +    bool operator==(const LLKeyData& rhs); +    bool operator!=(const LLKeyData& rhs); + +    bool canHandle(const LLKeyData& data) const; +    bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const; + +    EMouseClickType mMouse; +    KEY mKey; +    MASK mMask; +    // Either to expect exact match or ignore not expected masks +    bool mIgnoreMasks;  +}; + +// One function can bind to multiple Key options +class LLKeyBind +{ +public: +    LLKeyBind() {} +    LLKeyBind(const LLSD &key_bind); + +    bool operator==(const LLKeyBind& rhs); +    bool operator!=(const LLKeyBind& rhs); +    bool isEmpty() const; +    bool empty() const { return isEmpty(); }; + +    LLSD asLLSD() const; + +    bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const; +    bool canHandleKey(KEY key, MASK mask) const; +    bool canHandleMouse(EMouseClickType mouse, MASK mask) const; + +    // contains specified combination +    bool hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const; +    bool hasKeyData(const LLKeyData& data) const; +    bool hasKeyData(U32 index) const; + +    // index of contained LLKeyData +    S32 findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const; +    S32 findKeyData(const LLKeyData& data) const; + +    LLKeyData getKeyData(U32 index) const; + +    // these methods enshure there will be no repeats +    bool addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore); +    bool addKeyData(const LLKeyData& data); +    void replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index); +    void replaceKeyData(const LLKeyData& data, U32 index); +    void resetKeyData(S32 index); +    void clear() { mData.clear(); } +    // if there any empty LLKeyData in the end of the array, remove them +    void trimEmpty(); +    U32 getDataCount(); + +private: +    typedef std::vector<LLKeyData> data_vector_t; +    data_vector_t mData; +}; + + +#endif // LL_KEYBIND_H diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 1aaff5628f..0bae59ef4c 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -2241,7 +2241,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,  			return ZR_SIZE_ERROR;  		}  #endif -		catch (std::bad_alloc) +		catch (std::bad_alloc&)  		{  			free(result);  			return ZR_MEM_ERROR; | 
