diff options
Diffstat (limited to 'indra')
143 files changed, 3430 insertions, 2639 deletions
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index 7c8a7160e7..444007bf07 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1389,6 +1389,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (!success) { llwarns << "can't read rotation key (" << k << ")" << llendl; + delete rot_key; return FALSE; } @@ -1507,6 +1508,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (!dp.unpackU8(byte, "chain_length")) { llwarns << "can't read constraint chain length" << llendl; + delete constraintp; return FALSE; } constraintp->mChainLength = (S32) byte; @@ -1514,6 +1516,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (!dp.unpackU8(byte, "constraint_type")) { llwarns << "can't read constraint type" << llendl; + delete constraintp; return FALSE; } constraintp->mConstraintType = (EConstraintType)byte; @@ -1523,6 +1526,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (!dp.unpackBinaryDataFixed(bin_data, BIN_DATA_LENGTH, "source_volume")) { llwarns << "can't read source volume name" << llendl; + delete constraintp; return FALSE; } @@ -1533,12 +1537,14 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (!dp.unpackVector3(constraintp->mSourceConstraintOffset, "source_offset")) { llwarns << "can't read constraint source offset" << llendl; + delete constraintp; return FALSE; } if (!dp.unpackBinaryDataFixed(bin_data, BIN_DATA_LENGTH, "target_volume")) { llwarns << "can't read target volume name" << llendl; + delete constraintp; return FALSE; } @@ -1558,12 +1564,14 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (!dp.unpackVector3(constraintp->mTargetConstraintOffset, "target_offset")) { llwarns << "can't read constraint target offset" << llendl; + delete constraintp; return FALSE; } if (!dp.unpackVector3(constraintp->mTargetConstraintDir, "target_dir")) { llwarns << "can't read constraint target direction" << llendl; + delete constraintp; return FALSE; } @@ -1576,24 +1584,28 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (!dp.unpackF32(constraintp->mEaseInStartTime, "ease_in_start")) { llwarns << "can't read constraint ease in start time" << llendl; + delete constraintp; return FALSE; } if (!dp.unpackF32(constraintp->mEaseInStopTime, "ease_in_stop")) { llwarns << "can't read constraint ease in stop time" << llendl; + delete constraintp; return FALSE; } if (!dp.unpackF32(constraintp->mEaseOutStartTime, "ease_out_start")) { llwarns << "can't read constraint ease out start time" << llendl; + delete constraintp; return FALSE; } if (!dp.unpackF32(constraintp->mEaseOutStopTime, "ease_out_stop")) { llwarns << "can't read constraint ease out stop time" << llendl; + delete constraintp; return FALSE; } @@ -1947,39 +1959,46 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs, // create an instance of this motion (it may or may not already exist) LLKeyframeMotion* motionp = (LLKeyframeMotion*) character->createMotion(asset_uuid); - if (0 == status && motionp) + if (motionp) { - if (motionp->mAssetStatus == ASSET_LOADED) + if (0 == status) { - // asset already loaded - return; - } - LLVFile file(vfs, asset_uuid, type, LLVFile::READ); - S32 size = file.getSize(); - - U8* buffer = new U8[size]; - file.read((U8*)buffer, size); /*Flawfinder: ignore*/ - - lldebugs << "Loading keyframe data for: " << motionp->getName() << ":" << motionp->getID() << " (" << size << " bytes)" << llendl; - - LLDataPackerBinaryBuffer dp(buffer, size); - if (motionp->deserialize(dp)) - { - motionp->mAssetStatus = ASSET_LOADED; + if (motionp->mAssetStatus == ASSET_LOADED) + { + // asset already loaded + return; + } + LLVFile file(vfs, asset_uuid, type, LLVFile::READ); + S32 size = file.getSize(); + + U8* buffer = new U8[size]; + file.read((U8*)buffer, size); /*Flawfinder: ignore*/ + + lldebugs << "Loading keyframe data for: " << motionp->getName() << ":" << motionp->getID() << " (" << size << " bytes)" << llendl; + + LLDataPackerBinaryBuffer dp(buffer, size); + if (motionp->deserialize(dp)) + { + motionp->mAssetStatus = ASSET_LOADED; + } + else + { + llwarns << "Failed to decode asset for animation " << motionp->getName() << ":" << motionp->getID() << llendl; + motionp->mAssetStatus = ASSET_FETCH_FAILED; + } + + delete []buffer; } else { - llwarns << "Failed to decode asset for animation " << motionp->getName() << ":" << motionp->getID() << llendl; + llwarns << "Failed to load asset for animation " << motionp->getName() << ":" << motionp->getID() << llendl; motionp->mAssetStatus = ASSET_FETCH_FAILED; } - - delete []buffer; - } else { - llwarns << "Failed to load asset for animation " << motionp->getName() << ":" << motionp->getID() << llendl; - motionp->mAssetStatus = ASSET_FETCH_FAILED; + // motionp is NULL + llwarns << "Failed to createMotion() for asset UUID " << asset_uuid << llendl; } } diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp index a4d61c35c5..6643b959a2 100644 --- a/indra/llcharacter/llkeyframemotionparam.cpp +++ b/indra/llcharacter/llkeyframemotionparam.cpp @@ -167,6 +167,12 @@ BOOL LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask) ParameterizedMotion* firstMotion = NULL; ParameterizedMotion* secondMotion = NULL; + if (NULL == paramValue) // unexpected, but... + { + llwarns << "paramValue == NULL" << llendl; + continue; + } + for (ParameterizedMotion* paramMotion = motionList->getFirstData(); paramMotion; paramMotion = motionList->getNextData()) { paramMotion->first->onUpdate(time, joint_mask); diff --git a/indra/llcharacter/llstatemachine.cpp b/indra/llcharacter/llstatemachine.cpp index d51b2f75aa..9fd043bdbf 100644 --- a/indra/llcharacter/llstatemachine.cpp +++ b/indra/llcharacter/llstatemachine.cpp @@ -342,28 +342,28 @@ void LLStateMachine::processTransition(LLFSMTransition& transition, void* user_d { llassert(mStateDiagram); + if (NULL == mCurrentState) + { + llwarns << "mCurrentState == NULL; aborting processTransition()" << llendl; + return; + } + LLFSMState* new_state = mStateDiagram->processTransition(*mCurrentState, transition); + if (NULL == new_state) + { + llwarns << "new_state == NULL; aborting processTransition()" << llendl; + return; + } + mLastTransition = &transition; mLastState = mCurrentState; if (*mCurrentState != *new_state) { - if (mCurrentState && new_state && *mCurrentState != *new_state) - { - mCurrentState->onExit(user_data); - } - if (new_state) - { - if (!mCurrentState || *mCurrentState != *new_state) - { - mCurrentState = new_state; - if (mCurrentState) - { - mCurrentState->onEntry(user_data); - } - } - } + mCurrentState->onExit(user_data); + mCurrentState = new_state; + mCurrentState->onEntry(user_data); #if FSM_PRINT_STATE_TRANSITIONS llinfos << "Entering state " << mCurrentState->getName() << " on transition " << transition.getName() << " from state " << diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp index a6fd9b974f..e29800ee4a 100644 --- a/indra/llcharacter/llvisualparam.cpp +++ b/indra/llcharacter/llvisualparam.cpp @@ -212,16 +212,16 @@ void LLVisualParam::setWeight(F32 weight, BOOL set_by_user) //----------------------------------------------------------------------------- void LLVisualParam::setAnimationTarget(F32 target_value, BOOL set_by_user) { - if (getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) + if (mInfo) { - if (mInfo) + if (getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) { mTargetWeight = llclamp(target_value, mInfo->mMinWeight, mInfo->mMaxWeight); } - else - { - mTargetWeight = target_value; - } + } + else + { + mTargetWeight = target_value; } mIsAnimating = TRUE; diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index 3d9cbaf64f..446c33bf02 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -99,9 +99,9 @@ void LLStatAccum::impl::sum(F64 value, U64 when) } if (when < mLastTime) { - // JAMESDEBUG spams on Athlon - //llwarns << "LLStatAccum::sum clock has gone backwards from " - // << mLastTime << " to " << when << ", resetting" << llendl; + // This happens a LOT on some dual core systems. + lldebugs << "LLStatAccum::sum clock has gone backwards from " + << mLastTime << " to " << when << ", resetting" << llendl; reset(when); return; diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h index f293045119..226df74f5d 100644 --- a/indra/llcommon/llstringtable.h +++ b/indra/llcommon/llstringtable.h @@ -28,12 +28,6 @@ #include <hash_map> #endif -// string_table.h -// LLStringTable class header file -// Provides a _fast_ method for finding unique copies of strings -// -// Copyright 2001-2002, Linden Research, Inc. - const U32 MAX_STRINGS_LENGTH = 256; class LLStringTableEntry diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index ee14028ec9..fc29e760be 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -94,6 +94,13 @@ namespace { return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@" } +// TODO: USE CURL!! After http textures gets merged everywhere. +// static +std::string LLURI::escape(const std::string& str) +{ + return escape(str,unreserved() + ":@!$'()*+,="); +} + LLURI::LLURI() { } diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h index 78ffcf0a87..0665255676 100644 --- a/indra/llcommon/lluri.h +++ b/indra/llcommon/lluri.h @@ -74,6 +74,7 @@ public: // Escaping Utilities // Escape a string by urlencoding all the characters that aren't in the allowed string. + static std::string escape(const std::string& str); static std::string escape(const std::string& str, const std::string & allowed); static std::string unescape(const std::string& str); diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 9b37cdade5..b6f6cdfc24 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1402,7 +1402,7 @@ void LLImageFormatted::sanityCheck() BOOL LLImageFormatted::copyData(U8 *data, S32 size) { - if ( (data && data != getData()) || (size != getDataSize()) ) + if ( data && ((data != getData()) || (size != getDataSize())) ) { deleteData(); allocateData(size); diff --git a/indra/llinventory/lleconomy.cpp b/indra/llinventory/lleconomy.cpp index f7442380b0..90d7103065 100644 --- a/indra/llinventory/lleconomy.cpp +++ b/indra/llinventory/lleconomy.cpp @@ -12,6 +12,8 @@ #include "message.h" #include "v3math.h" +LLGlobalEconomy *gGlobalEconomy = NULL; + LLGlobalEconomy::LLGlobalEconomy() : mObjectCount( -1 ), mObjectCapacity( -1 ), diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h index c71fc9e6d0..354815cde5 100644 --- a/indra/llinventory/lleconomy.h +++ b/indra/llinventory/lleconomy.h @@ -113,4 +113,6 @@ private: }; +extern LLGlobalEconomy* gGlobalEconomy; + #endif diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 6164dae22f..36b7ab0680 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -20,8 +20,6 @@ #include "llsdutil.h" -#include "llsdutil.h" - ///---------------------------------------------------------------------------- /// exported functions ///---------------------------------------------------------------------------- @@ -47,187 +45,8 @@ static const std::string INV_CREATION_DATE_LABEL("created_at"); const U8 TASK_INVENTORY_ITEM_KEY = 0; const U8 TASK_INVENTORY_ASSET_KEY = 1; -const LLUUID MAGIC_ID("3c115e51-04f4-523c-9fa6-98aff1034730"); - -// helper function which returns true if inventory type and asset type -// are potentially compatible. For example, an attachment must be an -// object, but a wearable can be a bodypart or clothing asset. -bool inventory_and_asset_types_match( - LLInventoryType::EType inventory_type, - LLAssetType::EType asset_type); - +const LLUUID MAGIC_ID("3c115e51-04f4-523c-9fa6-98aff1034730"); -///---------------------------------------------------------------------------- -/// Class LLInventoryType -///---------------------------------------------------------------------------- - -// Unlike asset type names, not limited to 8 characters. -// Need not match asset type names. -static const char* INVENTORY_TYPE_NAMES[LLInventoryType::IT_COUNT] = -{ - "texture", // 0 - "sound", - "callcard", - "landmark", - NULL, - NULL, // 5 - "object", - "notecard", - "category", - "root", - "script", // 10 - NULL, - NULL, - NULL, - NULL, - "snapshot", // 15 - NULL, - "attach", - "wearable", - "animation", - "gesture", // 20 -}; - -// This table is meant for decoding to human readable form. Put any -// and as many printable characters you want in each one. -// See also LLAssetType::mAssetTypeHumanNames -static const char* INVENTORY_TYPE_HUMAN_NAMES[LLInventoryType::IT_COUNT] = -{ - "texture", // 0 - "sound", - "calling card", - "landmark", - NULL, - NULL, // 5 - "object", - "note card", - "folder", - "root", - "script", // 10 - NULL, - NULL, - NULL, - NULL, - "snapshot", // 15 - NULL, - "attachment", - "wearable", - "animation", - "gesture", // 20 -}; - -// Maps asset types to the default inventory type for that kind of asset. -// Thus, "Lost and Found" is a "Category" -static const LLInventoryType::EType -DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = -{ - LLInventoryType::IT_TEXTURE, // AT_TEXTURE - LLInventoryType::IT_SOUND, // AT_SOUND - LLInventoryType::IT_CALLINGCARD, // AT_CALLINGCARD - LLInventoryType::IT_LANDMARK, // AT_LANDMARK - LLInventoryType::IT_LSL, // AT_SCRIPT - LLInventoryType::IT_WEARABLE, // AT_CLOTHING - LLInventoryType::IT_OBJECT, // AT_OBJECT - LLInventoryType::IT_NOTECARD, // AT_NOTECARD - LLInventoryType::IT_CATEGORY, // AT_CATEGORY - LLInventoryType::IT_ROOT_CATEGORY, // AT_ROOT_CATEGORY - LLInventoryType::IT_LSL, // AT_LSL_TEXT - LLInventoryType::IT_LSL, // AT_LSL_BYTECODE - LLInventoryType::IT_TEXTURE, // AT_TEXTURE_TGA - LLInventoryType::IT_WEARABLE, // AT_BODYPART - LLInventoryType::IT_CATEGORY, // AT_TRASH - LLInventoryType::IT_CATEGORY, // AT_SNAPSHOT_CATEGORY - LLInventoryType::IT_CATEGORY, // AT_LOST_AND_FOUND - LLInventoryType::IT_SOUND, // AT_SOUND_WAV - LLInventoryType::IT_NONE, // AT_IMAGE_TGA - LLInventoryType::IT_NONE, // AT_IMAGE_JPEG - LLInventoryType::IT_ANIMATION, // AT_ANIMATION - LLInventoryType::IT_GESTURE, // AT_GESTURE -}; - -static const int MAX_POSSIBLE_ASSET_TYPES = 2; -static const LLAssetType::EType -INVENTORY_TO_ASSET_TYPE[LLInventoryType::IT_COUNT][MAX_POSSIBLE_ASSET_TYPES] = -{ - { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_TEXTURE - { LLAssetType::AT_SOUND, LLAssetType::AT_NONE }, // IT_SOUND - { LLAssetType::AT_CALLINGCARD, LLAssetType::AT_NONE }, // IT_CALLINGCARD - { LLAssetType::AT_LANDMARK, LLAssetType::AT_NONE }, // IT_LANDMARK - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_OBJECT - { LLAssetType::AT_NOTECARD, LLAssetType::AT_NONE }, // IT_NOTECARD - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_CATEGORY - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_ROOT_CATEGORY - { LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE }, // IT_LSL - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_SNAPSHOT - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_ATTACHMENT - { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART }, // IT_WEARABLE - { LLAssetType::AT_ANIMATION, LLAssetType::AT_NONE }, // IT_ANIMATION - { LLAssetType::AT_GESTURE, LLAssetType::AT_NONE }, // IT_GESTURE -}; - -// static -const char* LLInventoryType::lookup(EType type) -{ - if((type >= 0) && (type < IT_COUNT)) - { - return INVENTORY_TYPE_NAMES[S32(type)]; - } - else - { - return NULL; - } -} - -// static -LLInventoryType::EType LLInventoryType::lookup(const char* name) -{ - for(S32 i = 0; i < IT_COUNT; ++i) - { - if((INVENTORY_TYPE_NAMES[i]) - && (0 == strcmp(name, INVENTORY_TYPE_NAMES[i]))) - { - // match - return (EType)i; - } - } - return IT_NONE; -} - -// XUI:translate -// translation from a type to a human readable form. -// static -const char* LLInventoryType::lookupHumanReadable(EType type) -{ - if((type >= 0) && (type < IT_COUNT)) - { - return INVENTORY_TYPE_HUMAN_NAMES[S32(type)]; - } - else - { - return NULL; - } -} - -// return the default inventory for the given asset type. -// static -LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType asset_type) -{ - if((asset_type >= 0) && (asset_type < LLAssetType::AT_COUNT)) - { - return DEFAULT_ASSET_FOR_INV_TYPE[S32(asset_type)]; - } - else - { - return IT_NONE; - } -} ///---------------------------------------------------------------------------- /// Class LLInventoryObject @@ -331,10 +150,6 @@ BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream) { input_stream.getline(buffer, MAX_STRING); sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */ - if(!keyword) - { - continue; - } if(0 == strcmp("{",keyword)) { continue; @@ -702,10 +517,6 @@ BOOL LLInventoryItem::importFile(FILE* fp) { fgets(buffer, MAX_STRING, fp); sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */ - if(!keyword) - { - continue; - } if(0 == strcmp("{",keyword)) { continue; @@ -907,10 +718,6 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream) buffer, " %254s %254s", keyword, valuestr); - if(!keyword) - { - continue; - } if(0 == strcmp("{",keyword)) { continue; @@ -1399,7 +1206,8 @@ void LLInventoryItem::unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size) } else { - llerrs << "unpackBinaryBucket failed. item_buffer or bin_bucket is Null." << llendl; + llerrs << "unpackBinaryBucket failed. item_buffer or bin_bucket is Null." << llendl; + delete[] item_buffer; return; } item_buffer[bin_bucket_size] = '\0'; @@ -1568,10 +1376,6 @@ BOOL LLInventoryCategory::importFile(FILE* fp) buffer, " %254s %254s", keyword, valuestr); - if(!keyword) - { - continue; - } if(0 == strcmp("{",keyword)) { continue; @@ -1651,10 +1455,6 @@ BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream) buffer, " %254s %254s", keyword, valuestr); - if(!keyword) - { - continue; - } if(0 == strcmp("{",keyword)) { continue; @@ -1719,25 +1519,6 @@ BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL) /// Local function definitions ///---------------------------------------------------------------------------- -bool inventory_and_asset_types_match( - LLInventoryType::EType inventory_type, - LLAssetType::EType asset_type) -{ - bool rv = false; - if((inventory_type >= 0) && (inventory_type < LLInventoryType::IT_COUNT)) - { - for(S32 i = 0; i < MAX_POSSIBLE_ASSET_TYPES; ++i) - { - if(INVENTORY_TO_ASSET_TYPE[inventory_type][i] == asset_type) - { - rv = true; - break; - } - } - } - return rv; -} - LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item) { LLSD rv; diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 95d9ae1288..5ee93137f8 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -13,6 +13,7 @@ #include "llassetstorage.h" #include "lldarray.h" +#include "llinventorytype.h" #include "llmemtype.h" #include "llpermissions.h" #include "llsaleinfo.h" @@ -31,63 +32,6 @@ enum MAX_INVENTORY_BUFFER_SIZE = 1024 }; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryType -// -// Class used to encapsulate operations around inventory type. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLInventoryType -{ -public: - enum EType - { - IT_TEXTURE = 0, - IT_SOUND = 1, - IT_CALLINGCARD = 2, - IT_LANDMARK = 3, - //IT_SCRIPT = 4, - //IT_CLOTHING = 5, - IT_OBJECT = 6, - IT_NOTECARD = 7, - IT_CATEGORY = 8, - IT_ROOT_CATEGORY = 9, - IT_LSL = 10, - //IT_LSL_BYTECODE = 11, - //IT_TEXTURE_TGA = 12, - //IT_BODYPART = 13, - //IT_TRASH = 14, - IT_SNAPSHOT = 15, - //IT_LOST_AND_FOUND = 16, - IT_ATTACHMENT = 17, - IT_WEARABLE = 18, - IT_ANIMATION = 19, - IT_GESTURE = 20, - IT_COUNT = 21, - - IT_NONE = -1 - }; - - // machine transation between type and strings - static EType lookup(const char* name); - static const char* lookup(EType type); - - // translation from a type to a human readable form. - static const char* lookupHumanReadable(EType type); - - // return the default inventory for the given asset type. - static EType defaultForAssetType(LLAssetType::EType asset_type); - -private: - // don't instantiate or derive one of these objects - LLInventoryType( void ) {} - ~LLInventoryType( void ) {} - -//private: -// static const char* mInventoryTypeNames[]; -// static const char* mInventoryTypeHumanNames[]; -// static LLInventoryType::EType mInventoryAssetType[]; -}; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp new file mode 100644 index 0000000000..84a93d807a --- /dev/null +++ b/indra/llinventory/llinventorytype.cpp @@ -0,0 +1,202 @@ +/** + * @file llinventorytype.cpp + * @brief Inventory item type, more specific than an asset type. + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include "llinventorytype.h" + +///---------------------------------------------------------------------------- +/// Class LLInventoryType +///---------------------------------------------------------------------------- + +// Unlike asset type names, not limited to 8 characters. +// Need not match asset type names. +static const char* INVENTORY_TYPE_NAMES[LLInventoryType::IT_COUNT] = +{ + "texture", // 0 + "sound", + "callcard", + "landmark", + NULL, + NULL, // 5 + "object", + "notecard", + "category", + "root", + "script", // 10 + NULL, + NULL, + NULL, + NULL, + "snapshot", // 15 + NULL, + "attach", + "wearable", + "animation", + "gesture", // 20 +}; + +// This table is meant for decoding to human readable form. Put any +// and as many printable characters you want in each one. +// See also LLAssetType::mAssetTypeHumanNames +static const char* INVENTORY_TYPE_HUMAN_NAMES[LLInventoryType::IT_COUNT] = +{ + "texture", // 0 + "sound", + "calling card", + "landmark", + NULL, + NULL, // 5 + "object", + "note card", + "folder", + "root", + "script", // 10 + NULL, + NULL, + NULL, + NULL, + "snapshot", // 15 + NULL, + "attachment", + "wearable", + "animation", + "gesture", // 20 +}; + +// Maps asset types to the default inventory type for that kind of asset. +// Thus, "Lost and Found" is a "Category" +static const LLInventoryType::EType +DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = +{ + LLInventoryType::IT_TEXTURE, // AT_TEXTURE + LLInventoryType::IT_SOUND, // AT_SOUND + LLInventoryType::IT_CALLINGCARD, // AT_CALLINGCARD + LLInventoryType::IT_LANDMARK, // AT_LANDMARK + LLInventoryType::IT_LSL, // AT_SCRIPT + LLInventoryType::IT_WEARABLE, // AT_CLOTHING + LLInventoryType::IT_OBJECT, // AT_OBJECT + LLInventoryType::IT_NOTECARD, // AT_NOTECARD + LLInventoryType::IT_CATEGORY, // AT_CATEGORY + LLInventoryType::IT_ROOT_CATEGORY, // AT_ROOT_CATEGORY + LLInventoryType::IT_LSL, // AT_LSL_TEXT + LLInventoryType::IT_LSL, // AT_LSL_BYTECODE + LLInventoryType::IT_TEXTURE, // AT_TEXTURE_TGA + LLInventoryType::IT_WEARABLE, // AT_BODYPART + LLInventoryType::IT_CATEGORY, // AT_TRASH + LLInventoryType::IT_CATEGORY, // AT_SNAPSHOT_CATEGORY + LLInventoryType::IT_CATEGORY, // AT_LOST_AND_FOUND + LLInventoryType::IT_SOUND, // AT_SOUND_WAV + LLInventoryType::IT_NONE, // AT_IMAGE_TGA + LLInventoryType::IT_NONE, // AT_IMAGE_JPEG + LLInventoryType::IT_ANIMATION, // AT_ANIMATION + LLInventoryType::IT_GESTURE, // AT_GESTURE +}; + +static const int MAX_POSSIBLE_ASSET_TYPES = 2; +static const LLAssetType::EType +INVENTORY_TO_ASSET_TYPE[LLInventoryType::IT_COUNT][MAX_POSSIBLE_ASSET_TYPES] = +{ + { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_TEXTURE + { LLAssetType::AT_SOUND, LLAssetType::AT_NONE }, // IT_SOUND + { LLAssetType::AT_CALLINGCARD, LLAssetType::AT_NONE }, // IT_CALLINGCARD + { LLAssetType::AT_LANDMARK, LLAssetType::AT_NONE }, // IT_LANDMARK + { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, + { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, + { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_OBJECT + { LLAssetType::AT_NOTECARD, LLAssetType::AT_NONE }, // IT_NOTECARD + { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_CATEGORY + { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_ROOT_CATEGORY + { LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE }, // IT_LSL + { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, + { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, + { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, + { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, + { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_SNAPSHOT + { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, + { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_ATTACHMENT + { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART }, // IT_WEARABLE + { LLAssetType::AT_ANIMATION, LLAssetType::AT_NONE }, // IT_ANIMATION + { LLAssetType::AT_GESTURE, LLAssetType::AT_NONE }, // IT_GESTURE +}; + +// static +const char* LLInventoryType::lookup(EType type) +{ + if((type >= 0) && (type < IT_COUNT)) + { + return INVENTORY_TYPE_NAMES[S32(type)]; + } + else + { + return NULL; + } +} + +// static +LLInventoryType::EType LLInventoryType::lookup(const char* name) +{ + for(S32 i = 0; i < IT_COUNT; ++i) + { + if((INVENTORY_TYPE_NAMES[i]) + && (0 == strcmp(name, INVENTORY_TYPE_NAMES[i]))) + { + // match + return (EType)i; + } + } + return IT_NONE; +} + +// XUI:translate +// translation from a type to a human readable form. +// static +const char* LLInventoryType::lookupHumanReadable(EType type) +{ + if((type >= 0) && (type < IT_COUNT)) + { + return INVENTORY_TYPE_HUMAN_NAMES[S32(type)]; + } + else + { + return NULL; + } +} + +// return the default inventory for the given asset type. +// static +LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType asset_type) +{ + if((asset_type >= 0) && (asset_type < LLAssetType::AT_COUNT)) + { + return DEFAULT_ASSET_FOR_INV_TYPE[S32(asset_type)]; + } + else + { + return IT_NONE; + } +} + +bool inventory_and_asset_types_match( + LLInventoryType::EType inventory_type, + LLAssetType::EType asset_type) +{ + bool rv = false; + if((inventory_type >= 0) && (inventory_type < LLInventoryType::IT_COUNT)) + { + for(S32 i = 0; i < MAX_POSSIBLE_ASSET_TYPES; ++i) + { + if(INVENTORY_TO_ASSET_TYPE[inventory_type][i] == asset_type) + { + rv = true; + break; + } + } + } + return rv; +} diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h new file mode 100644 index 0000000000..fc132d455a --- /dev/null +++ b/indra/llinventory/llinventorytype.h @@ -0,0 +1,74 @@ +/** + * @file llinventorytype.h + * @brief Inventory item type, more specific than an asset type. + * + * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LLINVENTORYTYPE_H +#define LLINVENTORYTYPE_H + +#include "llassettype.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryType +// +// Class used to encapsulate operations around inventory type. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryType +{ +public: + enum EType + { + IT_TEXTURE = 0, + IT_SOUND = 1, + IT_CALLINGCARD = 2, + IT_LANDMARK = 3, + //IT_SCRIPT = 4, + //IT_CLOTHING = 5, + IT_OBJECT = 6, + IT_NOTECARD = 7, + IT_CATEGORY = 8, + IT_ROOT_CATEGORY = 9, + IT_LSL = 10, + //IT_LSL_BYTECODE = 11, + //IT_TEXTURE_TGA = 12, + //IT_BODYPART = 13, + //IT_TRASH = 14, + IT_SNAPSHOT = 15, + //IT_LOST_AND_FOUND = 16, + IT_ATTACHMENT = 17, + IT_WEARABLE = 18, + IT_ANIMATION = 19, + IT_GESTURE = 20, + IT_COUNT = 21, + + IT_NONE = -1 + }; + + // machine transation between type and strings + static EType lookup(const char* name); + static const char* lookup(EType type); + + // translation from a type to a human readable form. + static const char* lookupHumanReadable(EType type); + + // return the default inventory for the given asset type. + static EType defaultForAssetType(LLAssetType::EType asset_type); + +private: + // don't instantiate or derive one of these objects + LLInventoryType( void ); + ~LLInventoryType( void ); +}; + +// helper function which returns true if inventory type and asset type +// are potentially compatible. For example, an attachment must be an +// object, but a wearable can be a bodypart or clothing asset. +bool inventory_and_asset_types_match( + LLInventoryType::EType inventory_type, + LLAssetType::EType asset_type); + +#endif diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index 7ea83f6e5e..c2b2eb27de 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -1194,6 +1194,24 @@ BOOL LLParcel::exportStream(std::ostream& output_stream) return TRUE; } +// virtual +LLSD LLParcel::asLLSD() const +{ + LLSD p; + p["parcel-id"] = getID(); + p["name"] = getName(); + p["desc"] = getDesc(); + p["owner-id"] = getOwnerID(); + p["group-id"] = getGroupID(); + p["group-owned"] = (bool)getIsGroupOwned(); + p["auction-id"] = (S32)getAuctionID(); + p["snapshot-id"] = getSnapshotID(); + p["authorized-buyer-id"] = getAuthorizedBuyerID(); + p["sale-price"] = getSalePrice(); + p["parcel-flags"] = (S32)getParcelFlags(); + // NOTE: This list is incomplete, as this is used only for search. JC + return p; +} // Assumes we are in a block "ParcelData" void LLParcel::packMessage(LLMessageSystem* msg) @@ -1766,7 +1784,7 @@ const char* category_to_ui_string(LLParcel::ECategory category) else { // C_ANY = -1 , but the "Any" string is at the end of the list - index = ((S32) LLParcel::C_COUNT) + 1; + index = ((S32) LLParcel::C_COUNT); } return PARCEL_CATEGORY_UI_STRING[index]; } diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 131bcdd55d..46c7a99400 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -226,6 +226,7 @@ public: BOOL importStream(std::istream& input_stream); BOOL importAccessEntry(std::istream& input_stream, LLAccessEntry* entry); BOOL exportStream(std::ostream& output_stream); + virtual LLSD asLLSD() const; void packMessage(LLMessageSystem* msg); void unpackMessage(LLMessageSystem* msg); @@ -254,7 +255,7 @@ public: BOOL removeFromBanList(const LLUUID& agent_id); // ACCESSORS - const LLUUID& getID() { return mID; } + const LLUUID& getID() const { return mID; } const char* getName() const { return mName.c_str(); } const char* getDesc() const { return mDesc.c_str(); } const char* getMusicURL() const { return mMusicURL.c_str(); } @@ -263,14 +264,13 @@ public: const U8 getMediaAutoScale() const { return mMediaAutoScale; } S32 getLocalID() const { return mLocalID; } const LLUUID& getOwnerID() const { return mOwnerID; } - const LLUUID& getGroupID() const { return mGroupID; } - //const char* getGroupName() const { return mGroupName.c_str(); } + const LLUUID& getGroupID() const { return mGroupID; } S32 getPassPrice() const { return mPassPrice; } F32 getPassHours() const { return mPassHours; } BOOL getIsGroupOwned() const { return mGroupOwned; } - U32 getAuctionID() { return mAuctionID; } - bool isInEscrow() const { return mInEscrow; } + U32 getAuctionID() const { return mAuctionID; } + bool isInEscrow() const { return mInEscrow; } BOOL isPublic() const; diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index 7daab177a4..e0e8036d42 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -511,10 +511,6 @@ BOOL LLPermissions::importFile(FILE* fp) buffer, " %255s %255s", keyword, valuestr); - if (!keyword) - { - continue; - } if (!strcmp("{", keyword)) { continue; @@ -649,10 +645,6 @@ BOOL LLPermissions::importLegacyStream(std::istream& input_stream) buffer, " %255s %255s", keyword, valuestr); - if (!keyword) - { - continue; - } if (!strcmp("{", keyword)) { continue; diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index eaeb83f625..920d07f361 100644 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -486,7 +486,7 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust) mAgentPlanes[3] = planeFromPoints(frust[1], frust[0], frust[4]); //cache plane octant facing mask for use in AABBInFrustum - for (int i = 0; i < 8; i++) + for (int i = 0; i < 6; i++) { U8 mask = 0; LLPlane p = mAgentPlanes[i]; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index c5d105c9ee..20d07064e3 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -722,10 +722,6 @@ BOOL LLProfileParams::importFile(FILE *fp) buffer, " %255s %255s", keyword, valuestr); - if (!keyword) - { - continue; - } if (!strcmp("{", keyword)) { continue; @@ -798,10 +794,6 @@ BOOL LLProfileParams::importLegacyStream(std::istream& input_stream) " %255s %255s", keyword, valuestr); - if (!keyword) - { - continue; - } if (!strcmp("{", keyword)) { continue; @@ -1225,10 +1217,6 @@ BOOL LLPathParams::importFile(FILE *fp) buffer, " %255s %255s", keyword, valuestr); - if (!keyword) - { - continue; - } if (!strcmp("{", keyword)) { continue; @@ -1369,10 +1357,6 @@ BOOL LLPathParams::importLegacyStream(std::istream& input_stream) buffer, " %255s %255s", keyword, valuestr); - if (!keyword) - { - continue; - } if (!strcmp("{", keyword)) { continue; @@ -3267,6 +3251,9 @@ BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices, if (new_num_triangles == 0) { llwarns << "Created volume object with 0 faces." << llendl; + delete[] new_triangles; + delete[] vertex_mapping; + delete[] new_vertices; return FALSE; } @@ -3361,10 +3348,6 @@ BOOL LLVolumeParams::importFile(FILE *fp) { fgets(buffer, BUFSIZE, fp); sscanf(buffer, " %255s", keyword); /* Flawfinder: ignore */ - if (!keyword) - { - continue; - } if (!strcmp("{", keyword)) { continue; @@ -3415,10 +3398,6 @@ BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream) { input_stream.getline(buffer, BUFSIZE); sscanf(buffer, " %255s", keyword); - if (!keyword) - { - continue; - } if (!strcmp("{", keyword)) { continue; diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 5b758c88b4..b05636a45c 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -37,10 +37,6 @@ LLAssetStorage *gAssetStorage = NULL; const LLUUID CATEGORIZE_LOST_AND_FOUND_ID("00000000-0000-0000-0000-000000000010"); -const F32 LL_ASSET_STORAGE_TIMEOUT = 300.0f; // anything that takes longer than this will abort - - - ///---------------------------------------------------------------------------- /// LLAssetInfo ///---------------------------------------------------------------------------- @@ -817,43 +813,6 @@ void LLAssetStorage::downloadInvItemCompleteCallback( // Store routines ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// virtual -void LLAssetStorage::cancelStoreAsset( - const LLUUID& uuid, - LLAssetType::EType atype) -{ - bool do_callback = true; - LLAssetRequest* req = NULL; - - if(mPendingUploads.size() > 0) - { - req = mPendingUploads.front(); - if((req->getUUID() == uuid) && (req->getType() == atype)) - { - // This is probably because the request is in progress - do - // not attempt to cancel. - do_callback = false; - } - } - - if (mPendingLocalUploads.size() > 0) - { - req = mPendingLocalUploads.front(); - if((req->getUUID() == uuid) && (req->getType() == atype)) - { - // This is probably because the request is in progress - do - // not attempt to cancel. - do_callback = false; - } - } - - if (do_callback) - { - // clear it out of the upload queue if it is there. - _callUploadCallbacks(uuid, atype, FALSE); - } -} - // static void LLAssetStorage::uploadCompleteCallback(const LLUUID& uuid, void *user_data, S32 result) // StoreAssetData callback (fixed) { diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 9d73bf71eb..9777b8f1e4 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -28,6 +28,10 @@ class LLAssetStorage; class LLVFS; class LLSD; +// anything that takes longer than this to download will abort. +// HTTP Uploads also timeout if they take longer than this. +const F32 LL_ASSET_STORAGE_TIMEOUT = 5 * 60.0f; + class LLAssetInfo { protected: @@ -244,13 +248,6 @@ public: bool store_local = false, const LLUUID& requesting_agent_id = LLUUID::null); - // This call will attempt to clear a store asset. This will only - // attempt to cancel an upload that has not yet begun. The - // callback will be called with an error code. - virtual void cancelStoreAsset( - const LLUUID& uuid, - LLAssetType::EType oatype); - virtual void checkForTimeouts(); void getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id, diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp index 451fb2e807..e9a60e4eb8 100644 --- a/indra/llmessage/llcircuit.cpp +++ b/indra/llmessage/llcircuit.cpp @@ -1147,13 +1147,13 @@ std::ostream& operator<<(std::ostream& s, LLCircuitData& circuit) return s; } -const char* LLCircuitData::getInfoString() const +const LLString LLCircuitData::getInfoString() const { std::ostringstream info; info << "Circuit: " << mHost << std::endl << (mbAlive ? "Alive" : "Not Alive") << std::endl << "Age: " << mExistenceTimer.getElapsedTimeF32() << std::endl; - return info.str().c_str(); + return LLString(info.str()); } void LLCircuitData::dumpResendCountAndReset() @@ -1177,7 +1177,7 @@ std::ostream& operator<<(std::ostream& s, LLCircuit &circuit) return s; } -const char* LLCircuit::getInfoString() const +const LLString LLCircuit::getInfoString() const { std::ostringstream info; info << "Circuit Info:" << std::endl; @@ -1187,7 +1187,7 @@ const char* LLCircuit::getInfoString() const { info << (*it).second->getInfoString() << std::endl; } - return info.str().c_str(); + return LLString(info.str()); } void LLCircuit::getCircuitRange( diff --git a/indra/llmessage/llcircuit.h b/indra/llmessage/llcircuit.h index 003734df29..a02c67e41d 100644 --- a/indra/llmessage/llcircuit.h +++ b/indra/llmessage/llcircuit.h @@ -131,7 +131,7 @@ public: // void checkPeriodTime(); // Reset per-period counters if necessary. friend std::ostream& operator<<(std::ostream& s, LLCircuitData &circuit); - const char* getInfoString() const; + const LLString getInfoString() const; friend class LLCircuit; friend class LLMessageSystem; @@ -277,7 +277,7 @@ public: void sendAcks(); friend std::ostream& operator<<(std::ostream& s, LLCircuit &circuit); - const char* getInfoString() const; + const LLString getInfoString() const; void dumpResends(); diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 7cb6f5f95a..bca4e2364d 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -14,6 +14,7 @@ #include <sys/stat.h> #include "indra_constants.h" +#include "message.h" #include "llvfile.h" #include "llvfs.h" @@ -497,6 +498,8 @@ void LLHTTPAssetStorage::storeAssetData( callback(LLUUID::null, user_data, LL_ERR_CANNOT_OPEN_FILE); } } + // Coverity CID-269 says there's a leak of 'legacy' here, but + // legacyStoreDataCallback() will delete it somewhere down the line. } // virtual @@ -917,9 +920,45 @@ void LLHTTPAssetStorage::checkForTimeouts() } while (curl_msg && queue_length > 0); + // Cleanup + // We want to bump to the back of the line any running uploads that have timed out. + bumpTimedOutUploads(); + LLAssetStorage::checkForTimeouts(); } +void LLHTTPAssetStorage::bumpTimedOutUploads() +{ + // No point bumping currently running uploads if there are no others in line. + if (!(mPendingUploads.size() > mRunningUploads.size())) + { + return; + } + + F64 mt_secs = LLMessageSystem::getMessageTimeSeconds(); + + // deletePendingRequest will modify the mRunningUploads list so we don't want to iterate over it. + request_list_t temp_running = mRunningUploads; + + request_list_t::iterator it = temp_running.begin(); + request_list_t::iterator end = temp_running.end(); + for ( ; it != end; ++it) + { + //request_list_t::iterator curiter = iter++; + LLAssetRequest* req = *it; + + if ( LL_ASSET_STORAGE_TIMEOUT < (mt_secs - req->mTime) ) + { + llwarns << "Asset upload request timed out for " + << req->getUUID() << "." + << LLAssetType::lookup(req->getType()) + << ", bumping to the back of the line!" << llendl; + + deletePendingRequest(RT_UPLOAD, req->getType(), req->getUUID()); + } + } +} + // static size_t LLHTTPAssetStorage::curlDownCallback(void *data, size_t size, size_t nmemb, void *user_data) { diff --git a/indra/llmessage/llhttpassetstorage.h b/indra/llmessage/llhttpassetstorage.h index b1be7431b9..a9cd88d629 100644 --- a/indra/llmessage/llhttpassetstorage.h +++ b/indra/llmessage/llhttpassetstorage.h @@ -113,6 +113,10 @@ private: // This will return the correct base URI for any http asset request std::string getBaseURL(const LLUUID& asset_id, LLAssetType::EType asset_type); + // Check for running uploads that have timed out + // Bump these to the back of the line to let other uploads complete. + void bumpTimedOutUploads(); + protected: std::string mBaseURL; std::string mLocalBaseURL; diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 869012e431..ca5fe849f7 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -9,9 +9,8 @@ */ #include "linden_common.h" -#include "lliohttpserver.h" -#include "boost/tokenizer.hpp" +#include "lliohttpserver.h" #include "llapr.h" #include "llbuffer.h" @@ -26,9 +25,12 @@ #include "llsd.h" #include "llsdserialize_xml.h" #include "llstl.h" +#include "lltimer.h" #include <sstream> +#include "boost/tokenizer.hpp" + static const char HTTP_VERSION_STR[] = "HTTP/1.0"; static const std::string CONTEXT_REQUEST("request"); static const std::string HTTP_VERB_GET("GET"); @@ -36,6 +38,8 @@ static const std::string HTTP_VERB_PUT("PUT"); static const std::string HTTP_VERB_POST("POST"); static const std::string HTTP_VERB_DELETE("DELETE"); +static LLIOHTTPServer::timing_callback_t sTimingCallback = NULL; +static void* sTimingCallbackData = NULL; class LLHTTPPipe : public LLIOPipe { @@ -131,6 +135,12 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( // TODO: Babbage: Parameterize parser? LLBufferStream istr(channels, buffer.get()); + static LLTimer timer; + if (sTimingCallback) + { + timer.reset(); + } + std::string verb = context[CONTEXT_REQUEST]["verb"]; if(verb == HTTP_VERB_GET) { @@ -159,6 +169,18 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( mResponse->methodNotAllowed(); } + if (sTimingCallback) + { + LLHTTPNode::Description desc; + mNode.describe(desc); + LLSD info = desc.getInfo(); + std::string timing_name = info["description"]; + timing_name += " "; + timing_name += verb; + F32 delta = timer.getElapsedTimeF32(); + sTimingCallback(timing_name.c_str(), delta, sTimingCallbackData); + } + // Log Internal Server Errors if(mStatusCode == 500) { @@ -799,9 +821,9 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( } - -void LLCreateHTTPPipe(LLPumpIO::chain_t& chain, - const LLHTTPNode& root, const LLSD& ctx) +// static +void LLIOHTTPServer::createPipe(LLPumpIO::chain_t& chain, + const LLHTTPNode& root, const LLSD& ctx) { chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root, ctx))); } @@ -812,7 +834,7 @@ class LLHTTPResponseFactory : public LLChainIOFactory public: bool build(LLPumpIO::chain_t& chain, LLSD ctx) const { - LLCreateHTTPPipe(chain, mTree, ctx); + LLIOHTTPServer::createPipe(chain, mTree, ctx); return true; } @@ -823,7 +845,8 @@ private: }; -LLHTTPNode& LLCreateHTTPServer( +// static +LLHTTPNode& LLIOHTTPServer::create( apr_pool_t* pool, LLPumpIO& pump, U16 port) { LLSocket::ptr_t socket = LLSocket::create( @@ -847,3 +870,10 @@ LLHTTPNode& LLCreateHTTPServer( return factory->getRootNode(); } +// static +void LLIOHTTPServer::setTimingCallback(timing_callback_t callback, + void* data) +{ + sTimingCallback = callback; + sTimingCallbackData = data; +} diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h index f11a1eccf6..4f788db377 100644 --- a/indra/llmessage/lliohttpserver.h +++ b/indra/llmessage/lliohttpserver.h @@ -16,7 +16,12 @@ class LLPumpIO; -LLHTTPNode& LLCreateHTTPServer(apr_pool_t* pool, LLPumpIO& pump, U16 port); +class LLIOHTTPServer +{ +public: + typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data); + + static LLHTTPNode& create(apr_pool_t* pool, LLPumpIO& pump, U16 port); /**< Creates an HTTP wire server on the pump for the given TCP port. * * Returns the root node of the new server. Add LLHTTPNode instances @@ -31,14 +36,23 @@ LLHTTPNode& LLCreateHTTPServer(apr_pool_t* pool, LLPumpIO& pump, U16 port); * for example), use the helper templates below. */ -void LLCreateHTTPPipe(LLPumpIO::chain_t& chain, - const LLHTTPNode& root, const LLSD& ctx); + static void createPipe(LLPumpIO::chain_t& chain, + const LLHTTPNode& root, const LLSD& ctx); /**< Create a pipe on the chain that handles HTTP requests. * The requests are served by the node tree given at root. * * This is primarily useful for unit testing. */ + static void setTimingCallback(timing_callback_t callback, void* data); + /**< Register a callback function that will be called every time + * a GET, PUT, POST, or DELETE is handled. + * + * This is used to time the LLHTTPNode handler code, which often hits + * the database or does other, slow operations. JC + */ +}; + /* @name Helper Templates * * These templates make it easy to create nodes that use thier own protocol diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 7c33153086..6ccaa7fb1a 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -403,23 +403,35 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( bool done = false; while(it != end) { + PUMP_DEBUG; if((*it).isOnChannel(channels.in())) { PUMP_DEBUG; // *FIX: check return code - sockets will fail (broken, etc.) len = (apr_size_t)segment.size(); - apr_socket_send( + apr_status_t status = apr_socket_send( mDestination->getSocket(), (const char*)segment.data(), &len); + // We sometimes get a 'non-blocking socket operation could not be + // completed immediately' error from apr_socket_send. In this + // case we break and the data will be sent the next time the chain + // is pumped. +#if LL_WINDOWS + if (status == 730035) + break; +#endif mLastWritten = segment.data() + len - 1; + PUMP_DEBUG; if((S32)len < segment.size()) { break; } + } + ++it; if(it != end) { @@ -429,6 +441,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl( { done = true; } + } PUMP_DEBUG; if(done && eos) diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp index dd878e1679..c694bc3530 100644 --- a/indra/llmessage/llmail.cpp +++ b/indra/llmessage/llmail.cpp @@ -44,7 +44,7 @@ static apr_sockaddr_t* gSockAddr; static apr_socket_t* gMailSocket; // According to RFC2822 -static const boost::regex valid_subject_chars("[\\x1-\\x9\\xb\\xc\\xe-\\x7f]+"); +static const boost::regex valid_subject_chars("[\\x1-\\x9\\xb\\xc\\xe-\\x7f]*"); bool connect_smtp(); void disconnect_smtp(); diff --git a/indra/llmessage/llpacketbuffer.cpp b/indra/llmessage/llpacketbuffer.cpp index d5796c131b..405a5241cd 100644 --- a/indra/llmessage/llpacketbuffer.cpp +++ b/indra/llmessage/llpacketbuffer.cpp @@ -22,11 +22,13 @@ LLPacketBuffer::LLPacketBuffer(const LLHost &host, const char *datap, const S32 { llerrs << "Sending packet > " << NET_BUFFER_SIZE << " of size " << size << llendl; } - - if (datap != NULL) + else // we previously relied on llerrs being fatal to not get here... { - memcpy(mData, datap, size); /*Flawfinder: ignore*/ - mSize = size; + if (datap != NULL) + { + memcpy(mData, datap, size); + mSize = size; + } } } diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index e7797ea158..15e7a32257 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -43,7 +43,7 @@ const U32 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid const U32 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13); const U32 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics const U32 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15); -const U32 REGION_FLAGS_MAINLAND_VISIBLE = (1 << 16); +//const U32 REGION_FLAGS_MAINLAND_VISIBLE = (1 << 16); const U32 REGION_FLAGS_PUBLIC_ALLOWED = (1 << 17); const U32 REGION_FLAGS_BLOCK_DWELL = (1 << 18); @@ -79,7 +79,6 @@ const U32 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK | REGION_FLAGS_ALLOW_SET_HOME; const U32 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE - | REGION_FLAGS_MAINLAND_VISIBLE | REGION_FLAGS_PUBLIC_ALLOWED | REGION_FLAGS_SUN_FIXED | REGION_FLAGS_DENY_ANONYMOUS diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp index bddd79367a..36553f8cf1 100644 --- a/indra/llmessage/lltransfermanager.cpp +++ b/indra/llmessage/lltransfermanager.cpp @@ -938,6 +938,7 @@ void LLTransferTargetChannel::requestTransfer( if (!ttp) { llwarns << "LLTransferManager::requestTransfer aborting due to target creation failure!" << llendl; + return; } ttp->applyParams(target_params); diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index df9c0149d4..a7b8573b0d 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -524,7 +524,10 @@ size_t headerCallback(void* data, size_t size, size_t nmemb, void* user) int statusCode = atoi(status.c_str()); if (statusCode > 0) { - complete->httpStatus((U32)statusCode, reason); + if (complete) + { + complete->httpStatus((U32)statusCode, reason); + } } } diff --git a/indra/llmessage/llxfer_file.cpp b/indra/llmessage/llxfer_file.cpp index 14c266950d..299c043d93 100644 --- a/indra/llmessage/llxfer_file.cpp +++ b/indra/llmessage/llxfer_file.cpp @@ -62,7 +62,8 @@ void LLXfer_File::init (const LLString& local_filename, BOOL delete_local_on_com if (!local_filename.empty()) { - strncpy(mLocalFilename, local_filename.c_str(), LL_MAX_PATH); /* Flawfinder : ignore */ + strncpy(mLocalFilename, local_filename.c_str(), LL_MAX_PATH-1); + mLocalFilename[LL_MAX_PATH-1] = '\0'; // stupid strncpy. // You can only automatically delete .tmp file as a safeguard against nasty messages. mDeleteLocalOnCompletion = (delete_local_on_completion && (strstr(mLocalFilename,".tmp") == &mLocalFilename[strlen(mLocalFilename)-4])); /* Flawfinder : ignore */ @@ -97,19 +98,21 @@ void LLXfer_File::free () /////////////////////////////////////////////////////////// S32 LLXfer_File::initializeRequest(U64 xfer_id, - const LLString& local_filename, - const LLString& remote_filename, - ELLPath remote_path, - const LLHost& remote_host, - BOOL delete_remote_on_completion, - void (*callback)(void**,S32), - void** user_data) + const LLString& local_filename, + const LLString& remote_filename, + ELLPath remote_path, + const LLHost& remote_host, + BOOL delete_remote_on_completion, + void (*callback)(void**,S32), + void** user_data) { S32 retval = 0; // presume success mID = xfer_id; - strncpy(mLocalFilename, local_filename.c_str(), LL_MAX_PATH); /* Flawfinder : ignore */ - strncpy(mRemoteFilename,remote_filename.c_str(), LL_MAX_PATH); /* Flawfinder : ignore */ + strncpy(mLocalFilename, local_filename.c_str(), LL_MAX_PATH-1); + mLocalFilename[LL_MAX_PATH-1] = '\0'; // stupid strncpy. + strncpy(mRemoteFilename,remote_filename.c_str(), LL_MAX_PATH-1); + mRemoteFilename[LL_MAX_PATH-1] = '\0'; // stupid strncpy. mRemotePath = remote_path; mRemoteHost = remote_host; mDeleteRemoteOnCompletion = delete_remote_on_completion; diff --git a/indra/llmessage/llxfer_mem.cpp b/indra/llmessage/llxfer_mem.cpp index 8f48247e20..ff878dc9f2 100644 --- a/indra/llmessage/llxfer_mem.cpp +++ b/indra/llmessage/llxfer_mem.cpp @@ -142,7 +142,8 @@ S32 LLXfer_Mem::initializeRequest(U64 xfer_id, mCallbackDataHandle = user_data; mCallbackResult = LL_ERR_NOERR; - strncpy(mRemoteFilename, remote_filename.c_str(), LL_MAX_PATH); /* Flawfinder : ignore */ + strncpy(mRemoteFilename, remote_filename.c_str(), LL_MAX_PATH-1); + mRemoteFilename[LL_MAX_PATH-1] = '\0'; // stupid strncpy. mRemotePath = remote_path; mDeleteRemoteOnCompletion = delete_remote_on_completion; diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index bafa783799..98d8a626e5 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -203,8 +203,8 @@ LLXfer *LLXferManager::findXfer (U64 id, LLXfer *list_head) void LLXferManager::removeXfer (LLXfer *delp, LLXfer **list_head) { - LLXfer *xferp; - + // This function assumes that delp will only occur in the list + // zero or one times. if (delp) { if (*list_head == delp) @@ -214,14 +214,14 @@ void LLXferManager::removeXfer (LLXfer *delp, LLXfer **list_head) } else { - xferp = *list_head; + LLXfer *xferp = *list_head; while (xferp->mNext) { if (xferp->mNext == delp) { xferp->mNext = delp->mNext; delete (delp); - continue; + break; } xferp = xferp->mNext; } diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 78d12cbda9..dfc18e0b2e 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -515,6 +515,8 @@ void LLMessageSystem::loadTemplateFile(const char* filename) if(!filename) { llerrs << "No template filename specified" << llendl; + mbError = TRUE; + return; } char token[MAX_MESSAGE_INTERNAL_NAME_SIZE]; /* Flawfinder: ignore */ @@ -635,6 +637,13 @@ void LLMessageSystem::loadTemplateFile(const char* filename) // add data! // we've gotten a complete variable! hooray! // add it! + if (NULL == templatep) + { + llerrs << "Trying to addTemplate a NULL templatep during load." << llendl; + mbError = TRUE; + fclose(messagefilep); + return; + } addTemplate(templatep); //llinfos << "Read template: "templatep->mNametemp_str @@ -652,7 +661,13 @@ void LLMessageSystem::loadTemplateFile(const char* filename) // add data! // we've gotten a complete variable! hooray! // add it to template - + if (NULL == templatep) + { + llerrs << "Trying to addBlock to NULL templatep during load." << llendl; + mbError = TRUE; + fclose(messagefilep); + return; + } templatep->addBlock(blockp); // start working on it! @@ -856,10 +871,24 @@ void LLMessageSystem::loadTemplateFile(const char* filename) if (strcmp(token, "Trusted") == 0) { + if (NULL == templatep) + { + llerrs << "Trying to setTrust for NULL templatep during load." << llendl; + mbError = TRUE; + fclose(messagefilep); + return; + } templatep->setTrust(MT_TRUST); } else if (strcmp(token, "NotTrusted") == 0) { + if (NULL == templatep) + { + llerrs << "Trying to setTrust for NULL templatep during load." << llendl; + mbError = TRUE; + fclose(messagefilep); + return; + } templatep->setTrust(MT_NOTRUST); } else @@ -892,10 +921,24 @@ void LLMessageSystem::loadTemplateFile(const char* filename) if(0 == strcmp(token, "Unencoded")) { + if (NULL == templatep) + { + llerrs << "Trying to setEncoding for NULL templatep during load." << llendl; + mbError = TRUE; + fclose(messagefilep); + return; + } templatep->setEncoding(ME_UNENCODED); } else if(0 == strcmp(token, "Zerocoded")) { + if (NULL == templatep) + { + llerrs << "Trying to setEncoding for NULL templatep during load." << llendl; + mbError = TRUE; + fclose(messagefilep); + return; + } templatep->setEncoding(ME_ZEROCODED); } else diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index fa0b4747e6..13719d0a62 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -777,14 +777,14 @@ const char * LLPrimitive::pCodeToString(const LLPCode pcode) { snprintf(mask, sizeof(mask), "hemi"); /* Flawfinder: ignore */ } - else if (mask != 0) + else { snprintf(mask, sizeof(mask), "%x", mask_code); /* Flawfinder: ignore */ } - else - { - mask[0] = 0; - } + + // extra sanity against snprintf() being naturally crap + mask[sizeof(mask)-1] = '\0'; + shape[sizeof(shape)-1] = '\0'; if (mask[0]) { @@ -795,6 +795,11 @@ const char * LLPrimitive::pCodeToString(const LLPCode pcode) snprintf(pcode_string, sizeof(pcode_string), "%s", shape); /* Flawfinder: ignore */ } } + + // Be really sure that pcode_string is nul-terminated after we've + // been using crappy snprintf() to build it. + pcode_string[sizeof(pcode_string)-1] = '\0'; + return pcode_string; } diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index f347219f7f..73459facc9 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -749,6 +749,7 @@ S32 LLFontGL::render(const LLWString &wstr, if (!fgi) { llerrs << "Missing Glyph Info" << llendl; + break; } if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) { diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index a36dfd2269..0ec161b232 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -109,19 +109,27 @@ void LLImageGL::bindExternalTexture(LLGLuint gl_name, S32 stage, LLGLenum bind_t // static void LLImageGL::unbindTexture(S32 stage, LLGLenum bind_target) { - glActiveTextureARB(GL_TEXTURE0_ARB + stage); - glClientActiveTextureARB(GL_TEXTURE0_ARB + stage); - glBindTexture(bind_target, 0); - sCurrentBoundTextures[stage] = 0; + // LLGLSLShader can return -1 + if (stage >= 0) + { + glActiveTextureARB(GL_TEXTURE0_ARB + stage); + glClientActiveTextureARB(GL_TEXTURE0_ARB + stage); + glBindTexture(bind_target, 0); + sCurrentBoundTextures[stage] = 0; + } } // static (duplicated for speed and to avoid GL_TEXTURE_2D default argument which requires GL header dependency) void LLImageGL::unbindTexture(S32 stage) { - glActiveTextureARB(GL_TEXTURE0_ARB + stage); - glClientActiveTextureARB(GL_TEXTURE0_ARB + stage); - glBindTexture(GL_TEXTURE_2D, 0); - sCurrentBoundTextures[stage] = 0; + // LLGLSLShader can return -1 + if (stage >= 0) + { + glActiveTextureARB(GL_TEXTURE0_ARB + stage); + glClientActiveTextureARB(GL_TEXTURE0_ARB + stage); + glBindTexture(GL_TEXTURE_2D, 0); + sCurrentBoundTextures[stage] = 0; + } } // static diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index f548045474..fae13dd700 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -35,8 +35,7 @@ S32 LLCOMBOBOX_WIDTH = 0; LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString& label, void (*commit_callback)(LLUICtrl*,void*), - void *callback_userdata, - S32 list_width + void *callback_userdata ) : LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata, FOLLOWS_LEFT | FOLLOWS_TOP), @@ -79,10 +78,7 @@ LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString addChild(mButton); // Default size, will be set by arrange() call in button callback. - if (list_width == 0) - { - list_width = mRect.getWidth() + SCROLLBAR_SIZE; - } + S32 list_width = mRect.getWidth() + SCROLLBAR_SIZE; r.setOriginAndSize(0, 16, list_width, 220); // disallow multiple selection @@ -483,12 +479,14 @@ void LLComboBox::showList() LLRect rect = mList->getRect(); + S32 list_width = mRect.getWidth() + SCROLLBAR_SIZE; + if (mListPosition == BELOW) { if (rect.getHeight() <= -root_view_local.mBottom) { // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, rect.getWidth(), rect.getHeight() ); + rect.setLeftTopAndSize(0, 0, list_width, rect.getHeight() ); } else { @@ -496,12 +494,12 @@ void LLComboBox::showList() if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight()) { // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-root_view_local.mBottom, rect.getHeight())); + rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); } else { // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); + rect.setOriginAndSize(0, mRect.getHeight(), list_width, llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); } } } @@ -510,7 +508,7 @@ void LLComboBox::showList() if (rect.getHeight() <= root_view_local.mTop - mRect.getHeight()) { // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); + rect.setOriginAndSize(0, mRect.getHeight(), list_width, llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); } else { @@ -518,12 +516,12 @@ void LLComboBox::showList() if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight()) { // Move rect so it hangs off the bottom of this view - rect.setLeftTopAndSize(0, 0, rect.getWidth(), llmin(-root_view_local.mBottom, rect.getHeight())); + rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight())); } else { // move rect so it stacks on top of this view (clipped to size of screen) - rect.setOriginAndSize(0, mRect.getHeight(), rect.getWidth(), llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); + rect.setOriginAndSize(0, mRect.getHeight(), list_width, llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight())); } } diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 2b19c3c2e5..02aa0084ed 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -45,8 +45,7 @@ public: const LLRect &rect, const LLString& label, void (*commit_callback)(LLUICtrl*, void*) = NULL, - void *callback_userdata = NULL, - S32 list_width = 0 + void *callback_userdata = NULL ); virtual ~LLComboBox(); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index c3364a7a35..40c11c69cc 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -676,7 +676,13 @@ void LLFloater::translate(S32 x, S32 y) BOOL LLFloater::canSnapTo(LLView* other_view) { - if (other_view && other_view != getParent()) + if (NULL == other_view) + { + llwarns << "other_view is NULL" << llendl; + return FALSE; + } + + if (other_view != getParent()) { LLFloater* other_floaterp = (LLFloater*)other_view; @@ -2535,6 +2541,7 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, if (!mTabContainer) { llerrs << "Tab Container used without having been initialized." << llendl; + return; } if (floaterp->getHost() == this) @@ -2698,7 +2705,7 @@ void LLMultiFloater::setVisible(BOOL visible) BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) { if (getEnabled() - && mask == (MASK_CONTROL|MASK_SHIFT)) + && mask == MASK_CONTROL) { if (key == 'W') { diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 7422a039dd..43ea584aa1 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -691,11 +691,11 @@ S32 LLLineEditor::prevWordPos(S32 cursorPos) const S32 LLLineEditor::nextWordPos(S32 cursorPos) const { const LLWString& wtext = mText.getWString(); - while( (cursorPos < getLength()) && isPartOfWord( wtext[cursorPos+1] ) ) + while( (cursorPos < getLength()) && isPartOfWord( wtext[cursorPos] ) ) { cursorPos++; } - while( (cursorPos < getLength()) && (wtext[cursorPos+1] == ' ') ) + while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') ) { cursorPos++; } @@ -1015,7 +1015,8 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) break; case KEY_LEFT: - if (!mIgnoreArrowKeys) + if (!mIgnoreArrowKeys + && mask != MASK_ALT) { if( hasSelection() ) { @@ -1040,7 +1041,8 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask) break; case KEY_RIGHT: - if (!mIgnoreArrowKeys) + if (!mIgnoreArrowKeys + && mask != MASK_ALT) { if (hasSelection()) { diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 79c38a87c0..f5dcae5787 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -709,14 +709,18 @@ void LLMenuItemTearOffGL::doIt() LLFloater* parent_floater = LLFloater::getFloaterByHandle(mParentHandle); LLFloater* tear_off_menu = LLTearOffMenu::create(getMenu()); - if (parent_floater && tear_off_menu) + + if (tear_off_menu) { - parent_floater->addDependentFloater(tear_off_menu, FALSE); - } + if (parent_floater) + { + parent_floater->addDependentFloater(tear_off_menu, FALSE); + } - // give focus to torn off menu because it will have been taken away - // when parent menu closes - tear_off_menu->setFocus(TRUE); + // give focus to torn off menu because it will have + // been taken away when parent menu closes + tear_off_menu->setFocus(TRUE); + } } LLMenuItemGL::doIt(); } diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 406b5ef571..316764474b 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -342,7 +342,7 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent ) // If we have a default button, click it when // return is pressed, unless current focus is a return-capturing button // in which case *that* button will handle the return key - if (!(cur_focus->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast<LLButton *>(cur_focus)->getCommitOnReturn())) + if (cur_focus && !(cur_focus->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast<LLButton *>(cur_focus)->getCommitOnReturn())) { // RETURN key means hit default button in this case if (key == KEY_RETURN && mask == MASK_NONE diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index a3353d2028..a5bad91670 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -921,8 +921,8 @@ void LLTabContainer::addTabPanel(LLPanel* child, else { LLString tooltip = trimmed_label; - tooltip += "\nCtrl-[ for previous tab"; - tooltip += "\nCtrl-] for next tab"; + tooltip += "\nAlt-Left arrow for previous tab"; + tooltip += "\nAlt-Right arrow for next tab"; LLButton* btn = new LLButton( LLString(child->getName()) + " tab", @@ -1466,12 +1466,12 @@ BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) if (!gFocusMgr.childHasKeyboardFocus(this)) return FALSE; BOOL handled = FALSE; - if (key == '[' && mask == MASK_CONTROL) + if (key == KEY_LEFT && mask == MASK_ALT) { selectPrevTab(); handled = TRUE; } - else if (key == ']' && mask == MASK_CONTROL) + else if (key == KEY_RIGHT && mask == MASK_ALT) { selectNextTab(); handled = TRUE; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 651a421742..2b588cacce 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -703,11 +703,11 @@ S32 LLTextEditor::prevWordPos(S32 cursorPos) const S32 LLTextEditor::nextWordPos(S32 cursorPos) const { const LLWString& wtext = mWText; - while( (cursorPos < getLength()) && isPartOfWord( wtext[cursorPos+1] ) ) + while( (cursorPos < getLength()) && isPartOfWord( wtext[cursorPos] ) ) { cursorPos++; } - while( (cursorPos < getLength()) && (wtext[cursorPos+1] == ' ') ) + while( (cursorPos < getLength()) && (wtext[cursorPos] == ' ') ) { cursorPos++; } @@ -3647,10 +3647,18 @@ void LLTextEditor::pruneSegments() break; // done } } - // erase invalid segments - ++iter; - std::for_each(iter, mSegments.end(), DeletePointer()); - mSegments.erase(iter, mSegments.end()); + if (iter != mSegments.end()) + { + // erase invalid segments + ++iter; + std::for_each(iter, mSegments.end(), DeletePointer()); + mSegments.erase(iter, mSegments.end()); + } + else + { + llwarns << "Tried to erase end of empty LLTextEditor" + << llendl; + } } void LLTextEditor::findEmbeddedItemSegments() diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index c9a506756a..c65500b56c 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -401,6 +401,12 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border stop_glerror(); F32 border_scale = 1.f; + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + if (border_height * 2 > height) { border_scale = (F32)height / ((F32)border_height * 2.f); @@ -579,6 +585,12 @@ void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LL void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLImageGL* image, const LLColor4& color) { + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + LLGLSUIDefault gls_ui; glPushMatrix(); @@ -619,6 +631,12 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color) { + if (NULL == image) + { + llwarns << "image == NULL; aborting function" << llendl; + return; + } + LLGLSUIDefault gls_ui; glPushMatrix(); diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp index 24cc57e709..e85095b5fd 100644 --- a/indra/llui/llviewborder.cpp +++ b/indra/llui/llviewborder.cpp @@ -39,7 +39,7 @@ LLViewBorder::LLViewBorder( const LLString& name, const LLRect& rect, EBevel bev } // virtual -BOOL LLViewBorder::isCtrl() +BOOL LLViewBorder::isCtrl() const { return FALSE; } diff --git a/indra/llui/llviewborder.h b/indra/llui/llviewborder.h index 946c6b9f74..0a8bfff8e4 100644 --- a/indra/llui/llviewborder.h +++ b/indra/llui/llviewborder.h @@ -34,7 +34,7 @@ public: virtual EWidgetType getWidgetType() const; virtual LLString getWidgetTag() const; - virtual BOOL isCtrl(); + virtual BOOL isCtrl() const; // llview functionality virtual void draw(); diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index e4749041ee..0ec71bfcb6 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -287,6 +287,8 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r { llwarns << "Couldn't open vfs data file after trying many alternates" << llendl; mValid = VFSVALID_BAD_CANNOT_CREATE; + delete[] temp_index; + delete[] temp_data; return; } @@ -374,7 +376,6 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r // to heal after some errors. JC if (block->mLength > 0 && (U32)block->mLength <= data_size && - block->mLocation >= 0 && block->mLocation < data_size && block->mSize > 0 && block->mSize <= block->mLength && @@ -415,7 +416,7 @@ LLVFS::LLVFS(const char *index_filename, const char *data_filename, const BOOL r delete block; } - tmp_ptr += block->SERIAL_SIZE; + tmp_ptr += LLVFSFileBlock::SERIAL_SIZE; } delete[] buffer; @@ -638,6 +639,7 @@ void LLVFS::presizeDataFile(const U32 size) if (!mDataFP) { llerrs << "LLVFS::presizeDataFile() with no data file open" << llendl; + return; } // we're creating this file for the first time, size it @@ -1711,7 +1713,6 @@ void LLVFS::audit() // do sanity check on this block if (block->mLength >= 0 && - block->mLocation >= 0 && block->mSize >= 0 && block->mSize <= block->mLength && block->mFileType >= LLAssetType::AT_NONE && diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 697b8f2175..a589bf29f9 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1626,7 +1626,7 @@ void LLWindowWin32::setCursor(ECursorType cursor) } } -ECursorType LLWindowWin32::getCursor() +ECursorType LLWindowWin32::getCursor() const { return mCurrentCursor; } @@ -2279,7 +2279,7 @@ BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to) BOOL LLWindowWin32::isClipboardTextAvailable() { - return IsClipboardFormatAvailable(CF_UNICODETEXT) || IsClipboardFormatAvailable( CF_TEXT ); + return IsClipboardFormatAvailable(CF_UNICODETEXT); } @@ -2306,27 +2306,6 @@ BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst) CloseClipboard(); } } - else if (IsClipboardFormatAvailable(CF_TEXT)) - { - // This must be an OLD OS. We don't do non-ASCII for old OSes - if (OpenClipboard(mWindowHandle)) - { - HGLOBAL h_data = GetClipboardData(CF_TEXT); - if (h_data) - { - char* str = (char*) GlobalLock(h_data); - if (str) - { - // Strip non-ASCII characters - dst = utf8str_to_wstring(mbcsstring_makeASCII(str)); - LLWString::removeCRLF(dst); - GlobalUnlock(h_data); - success = TRUE; - } - } - CloseClipboard(); - } - } return success; } @@ -2363,30 +2342,6 @@ BOOL LLWindowWin32::copyTextToClipboard(const LLWString& wstr) } } - // Also provide a copy as raw ASCII text. - LLWString ascii_string(wstr); - LLWString::_makeASCII(ascii_string); - LLWString::addCRLF(ascii_string); - std::string out_s = wstring_to_utf8str(ascii_string); - const size_t size = (out_s.length() + 1) * sizeof(char); - - // Memory is allocated and then ownership of it is transfered to the system. - HGLOBAL hglobal_copy = GlobalAlloc(GMEM_MOVEABLE, size); - if (hglobal_copy) - { - char* copy = (char*) GlobalLock(hglobal_copy); - if( copy ) - { - memcpy(copy, out_s.c_str(), size); /* Flawfinder: ignore */ - GlobalUnlock(hglobal_copy); - - if (SetClipboardData(CF_TEXT, hglobal_copy)) - { - success = TRUE; - } - } - } - CloseClipboard(); } diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index c4391ef41f..487c1f09e7 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -45,7 +45,7 @@ public: /*virtual*/ void hideCursorUntilMouseMove(); /*virtual*/ BOOL isCursorHidden(); /*virtual*/ void setCursor(ECursorType cursor); - /*virtual*/ ECursorType getCursor(); + /*virtual*/ ECursorType getCursor() const; /*virtual*/ void captureMouse(); /*virtual*/ void releaseMouse(); /*virtual*/ void setMouseClipping( BOOL b ); diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 0415be8206..0b0385d92f 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -291,6 +291,12 @@ void XMLCALL StartXMLNode(void *userData, // Set the parent-child relationship with the current active node LLXMLNode* parent = (LLXMLNode *)userData; + if (NULL == parent) + { + llwarns << "parent (userData) is NULL; aborting function" << llendl; + return; + } + new_node_ptr->mParser = parent->mParser; // Set the current active node to the new node diff --git a/indra/lscript/lscript_alloc.h b/indra/lscript/lscript_alloc.h index 2870364a9c..c9eca7cd81 100644 --- a/indra/lscript/lscript_alloc.h +++ b/indra/lscript/lscript_alloc.h @@ -267,7 +267,9 @@ inline LLScriptLibData *lsa_bubble_sort(LLScriptLibData *src, S32 stride, S32 as src->mListp = NULL; - return sortarray[0]; + temp = sortarray[0]; + delete[] sortarray; + return temp; } diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp index ae2a0c8afe..4f54bdd7b7 100644 --- a/indra/lscript/lscript_compile/lscript_tree.cpp +++ b/indra/lscript/lscript_compile/lscript_tree.cpp @@ -9916,6 +9916,8 @@ void LLScriptScript::recurse(FILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass code->build(fp, bcfp); fclose(bcfp); + + delete code; } break; case LSCP_EMIT_CIL_ASSEMBLY: diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp index 9f123025ff..94dc9329b1 100644 --- a/indra/lscript/lscript_execute/lscript_execute.cpp +++ b/indra/lscript/lscript_execute/lscript_execute.cpp @@ -1,4 +1,4 @@ -/** +/** * @file lscript_execute.cpp * @brief classes to execute bytecode * @@ -55,7 +55,7 @@ LLScriptExecute::LLScriptExecute(FILE *fp) LLScriptExecute::LLScriptExecute(U8 *buffer) { - mBuffer = buffer; + mBuffer = buffer; init(); } @@ -981,7 +981,7 @@ BOOL run_loadgsp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) S32 address = lscript_global_get(buffer, arg); if (address) lsa_decrease_ref_count(buffer, address); - + lscript_global_store(buffer, arg, value); return FALSE; } @@ -999,7 +999,7 @@ BOOL run_loadglp(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) S32 address = lscript_global_get(buffer, arg); if (address) lsa_decrease_ref_count(buffer, address); - + lscript_global_store(buffer, arg, value); return FALSE; } @@ -1366,14 +1366,31 @@ void integer_integer_operation(U8 *buffer, LSCRIPTOpCodesEnum opcode) result = lside * rside; break; case LOPC_DIV: - if (rside) - result = lside / rside; + if (rside){ + if( ( rside == -1 ) || ( rside == 0xffffffff ) )// division by -1 can have funny results: multiplication is OK: SL-31252 + { + result = -1 * lside; + } + else + { + result = lside / rside; + } + } else set_fault(buffer, LSRF_MATH); break; case LOPC_MOD: if (rside) - result = lside % rside; + { + if (rside == -1 || rside == 1 ) // mod(1) = mod(-1) = 0: SL-31252 + { + result = 0; + } + else + { + result = lside % rside; + } + } else set_fault(buffer, LSRF_MATH); break; @@ -2925,14 +2942,14 @@ BOOL run_return(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) return FALSE; } -S32 axtoi(char *hexStg) +S32 axtoi(char *hexStg) { S32 n = 0; // position in string S32 m = 0; // position in digit[] to shift S32 count; // loop index S32 intValue = 0; // integer value of hex string S32 digit[9]; // hold values to convert - while (n < 8) + while (n < 8) { if (hexStg[n]=='\0') break; @@ -2948,7 +2965,7 @@ S32 axtoi(char *hexStg) count = n; m = n - 1; n = 0; - while(n < count) + while(n < count) { // digit[n] is value of hex digit at position n // (m << 2) is the number of positions to shift @@ -3120,7 +3137,7 @@ BOOL run_cast(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) bytestream2char(arg, buffer, string); F32 dest = (F32)atof(arg); - + lscript_push(buffer, dest); delete [] arg; } @@ -3318,7 +3335,7 @@ BOOL run_cast(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) delete list_root; char *tmp = strdup(dest.str().c_str()); LLScriptLibData *string = new LLScriptLibData(tmp); - free(tmp); + free(tmp); tmp = NULL; S32 destaddress = lsa_heap_add_data(buffer, string, get_max_heap_size(buffer), TRUE); lscript_push(buffer, destaddress); @@ -3373,7 +3390,7 @@ void lscript_stacktol_pop_variable(LLScriptLibData *data, U8 *buffer, char type) break; case LST_KEY: data->mType = LST_KEY; - + base_address = lscript_pop_int(buffer); // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization // and function clean up of ref counts isn't based on scope (a mistake, I know) @@ -3597,48 +3614,53 @@ BOOL run_print(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) void lscript_run(char *filename, BOOL b_debug) { LLTimer timer; - char *error; - BOOL b_state; - LLScriptExecute *execute = NULL; if (filename == NULL) { - llerrs << "filename is empty" << llendl; + llerrs << "filename is NULL" << llendl; // Just reporting error is likely not enough. Need // to check how to abort or error out gracefully // from this function. XXXTBD } - FILE* file = LLFile::fopen(filename, "r"); /* Flawfinder: ignore */ - if (file) - { - execute = new LLScriptExecute(file); - fclose(file); - } - file = LLFile::fopen(filename, "r"); /* Flawfinder: ignore */ - if (file) - { - FILE* fp = LLFile::fopen("lscript.parse", "w"); /*Flawfinder: ignore*/ - LLScriptLSOParse *parse = new LLScriptLSOParse(file); - parse->printData(fp); - fclose(file); - fclose(fp); - } - file = LLFile::fopen(filename, "r"); /*Flawfinder: ignore*/ - if (file && execute) + else { - timer.reset(); - while (!execute->run(b_debug, LLUUID::null, &error, b_state)) - ; - F32 time = timer.getElapsedTimeF32(); - F32 ips = execute->mInstructionCount / time; - llinfos << execute->mInstructionCount << " instructions in " << time << " seconds" << llendl; - llinfos << ips/1000 << "K instructions per second" << llendl; - printf("ip: 0x%X\n", get_register(execute->mBuffer, LREG_IP)); - printf("sp: 0x%X\n", get_register(execute->mBuffer, LREG_SP)); - printf("bp: 0x%X\n", get_register(execute->mBuffer, LREG_BP)); - printf("hr: 0x%X\n", get_register(execute->mBuffer, LREG_HR)); - printf("hp: 0x%X\n", get_register(execute->mBuffer, LREG_HP)); - delete execute; - fclose(file); + char *error; + BOOL b_state; + LLScriptExecute *execute = NULL; + + FILE* file = LLFile::fopen(filename, "r"); + if (file) + { + execute = new LLScriptExecute(file); + // note: LLScriptExecute() closes file for us + } + file = LLFile::fopen(filename, "r"); + if (file) + { + FILE* fp = LLFile::fopen("lscript.parse", "w"); /*Flawfinder: ignore*/ + LLScriptLSOParse *parse = new LLScriptLSOParse(file); + parse->printData(fp); + delete parse; + fclose(file); + fclose(fp); + } + file = LLFile::fopen(filename, "r"); + if (file && execute) + { + timer.reset(); + while (!execute->run(b_debug, LLUUID::null, &error, b_state)) + ; + F32 time = timer.getElapsedTimeF32(); + F32 ips = execute->mInstructionCount / time; + llinfos << execute->mInstructionCount << " instructions in " << time << " seconds" << llendl; + llinfos << ips/1000 << "K instructions per second" << llendl; + printf("ip: 0x%X\n", get_register(execute->mBuffer, LREG_IP)); + printf("sp: 0x%X\n", get_register(execute->mBuffer, LREG_SP)); + printf("bp: 0x%X\n", get_register(execute->mBuffer, LREG_BP)); + printf("hr: 0x%X\n", get_register(execute->mBuffer, LREG_HR)); + printf("hp: 0x%X\n", get_register(execute->mBuffer, LREG_HP)); + delete execute; + fclose(file); + } } } @@ -3659,7 +3681,7 @@ void lscript_pop_variable(LLScriptLibData *data, U8 *buffer, char type) break; case 'k': data->mType = LST_KEY; - + base_address = lscript_pop_int(buffer); // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization // and function clean up of ref counts isn't based on scope (a mistake, I know) diff --git a/indra/lscript/lscript_execute/lscript_readlso.cpp b/indra/lscript/lscript_execute/lscript_readlso.cpp index e92c1d2312..669a9b6a06 100644 --- a/indra/lscript/lscript_execute/lscript_readlso.cpp +++ b/indra/lscript/lscript_execute/lscript_readlso.cpp @@ -22,7 +22,6 @@ LLScriptLSOParse::LLScriptLSOParse(FILE *fp) mRawData = new U8[filesize]; fseek(fp, 0, SEEK_SET); fread(mRawData, 1, filesize, fp); - fclose(fp); initOpCodePrinting(); } diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp index 520f0d6266..fda6d0e3f3 100644 --- a/indra/lscript/lscript_library/lscript_library.cpp +++ b/indra/lscript/lscript_library/lscript_library.cpp @@ -381,7 +381,7 @@ void LLScriptLibrary::init() addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCameraParams", NULL, "l", "llSetCameraParams(list rules)\nSets multiple camera parameters at once.\nList format is [ rule1, data1, rule2, data2 . . . rulen, datan ]")); addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llClearCameraParams", NULL, NULL, "llClearCameraParams()\nResets all camera parameters to default values and turns off scripted camera control.")); - addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListStatistics", "f", "il", "integer llListStatistics(integer operation, list l)\nPerform statistical aggregate functions on list l using LIST_STAT_* operations.")); + addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListStatistics", "f", "il", "float llListStatistics(integer operation, list l)\nPerform statistical aggregate functions on list l using LIST_STAT_* operations.")); addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetUnixTime", "i", NULL, "integer llGetUnixTime()\nGet the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock.")); addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetParcelFlags", "i", "v", "integer llGetParcelFlags(vector pos)\nGet the parcel flags (PARCEL_FLAG_*) for the parcel including the point pos.")); addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRegionFlags", "i", NULL, "integer llGetRegionFlags()\nGet the region flags (REGION_FLAG_*) for the region the object is in.")); @@ -528,12 +528,7 @@ void LLScriptLibData::print_separator(std::ostream& ostr, BOOL b_prepend_sep, ch } //print(ostr, FALSE); { - BOOL b_prepend_comma = FALSE; char tmp[1024]; /* Flawfinder: ignore */ - if (b_prepend_comma) - { - ostr << ", "; - } switch (mType) { case LST_INTEGER: diff --git a/indra/newview/app_settings/keys.ini b/indra/newview/app_settings/keys.ini index b7fc6f9286..3a1e9ead36 100644 --- a/indra/newview/app_settings/keys.ini +++ b/indra/newview/app_settings/keys.ini @@ -235,6 +235,13 @@ EDIT PAD_PGUP ALT jump EDIT PAD_PGDN ALT push_down EDIT PAD_ENTER ALT start_chat +SITTING A ALT spin_around_cw +SITTING D ALT spin_around_ccw +SITTING W ALT move_forward +SITTING S ALT move_backward +SITTING E ALT spin_over_sitting +SITTING C ALT spin_under_sitting + SITTING LEFT ALT spin_around_cw SITTING RIGHT ALT spin_around_ccw SITTING UP ALT move_forward @@ -242,6 +249,21 @@ SITTING DOWN ALT move_backward SITTING PGUP ALT spin_over SITTING PGDN ALT spin_under +SITTING A CTL_ALT spin_around_cw +SITTING D CTL_ALT spin_around_ccw +SITTING W CTL_ALT spin_over +SITTING S CTL_ALT spin_under +SITTING E CTL_ALT spin_over +SITTING C CTL_ALT spin_under + +SITTING LEFT CTL_ALT spin_around_cw +SITTING RIGHT CTL_ALT spin_around_ccw +SITTING UP CTL_ALT spin_over +SITTING DOWN CTL_ALT spin_under +SITTING PGUP CTL_ALT spin_over +SITTING PGDN CTL_ALT spin_under + + SITTING A NONE spin_around_cw_sitting SITTING D NONE spin_around_ccw_sitting SITTING W NONE move_forward_sitting diff --git a/indra/newview/linux_tools/launch_url.sh b/indra/newview/linux_tools/launch_url.sh index 564e834939..a1c6f5dbd9 100755 --- a/indra/newview/linux_tools/launch_url.sh +++ b/indra/newview/linux_tools/launch_url.sh @@ -1,5 +1,5 @@ #!/bin/sh -# bash v1.14+ expected +# Script tested with: bash 1.14, bash 3.1.17, zsh 4.2.5, ksh 1993-12-28 # This script loads a web page in the 'default' graphical web browser. # It MUST return immediately (or soon), so the browser should be diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index cdc36a8375..5f128e8e41 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -1,4 +1,6 @@ #!/bin/sh +# Script tested with: bash 1.14, bash 3.1.17, zsh 4.2.5, ksh 1993-12-28 + ## Here are some configuration options for Linux Client Alpha Testers. ## These options are for self-assisted troubleshooting during this alpha ## testing phase; you should not usually need to touch them. diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 821bb2a69f..26c606fc31 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -21,7 +21,7 @@ #include "lluploaddialog.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" -#include "llviewermenu.h" +#include "llviewermenufile.h" #include "llviewerwindow.h" #include "viewer.h" diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index ddf0b83e73..c5e7eaa1e9 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -98,9 +98,10 @@ LLChatBar::LLChatBar(const std::string& name, const LLRect& rect) mInputEditor->setRevertOnEsc( FALSE ); mInputEditor->setIgnoreTab(TRUE); mInputEditor->setPassDelete(TRUE); + + mInputEditor->setMaxTextLength(1023); } - mInputEditor->setMaxTextLength(1023); // Build the list of gestures refreshGestures(); diff --git a/indra/newview/lldebugmessagebox.cpp b/indra/newview/lldebugmessagebox.cpp index 0ce745a373..938a6ebd11 100644 --- a/indra/newview/lldebugmessagebox.cpp +++ b/indra/newview/lldebugmessagebox.cpp @@ -205,21 +205,21 @@ void LLDebugVarMessageBox::draw() if(mAnimate) { - F32 animated_val = clamp_rescale(fmodf((F32)LLFrameTimer::getElapsedSeconds() / 5.f, 1.f), 0.f, 1.f, 0.f, mSlider1->getMaxValue()); if (mSlider1) { + F32 animated_val = clamp_rescale(fmodf((F32)LLFrameTimer::getElapsedSeconds() / 5.f, 1.f), 0.f, 1.f, 0.f, mSlider1->getMaxValue()); mSlider1->setValue(animated_val); slider_changed(mSlider1, this); - } - if (mSlider2) - { - mSlider2->setValue(animated_val); - slider_changed(mSlider2, this); - } - if (mSlider3) - { - mSlider3->setValue(animated_val); - slider_changed(mSlider3, this); + if (mSlider2) + { + mSlider2->setValue(animated_val); + slider_changed(mSlider2, this); + } + if (mSlider3) + { + mSlider3->setValue(animated_val); + slider_changed(mSlider3, this); + } } } LLFloater::draw(); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index d8b923c271..ee0ed22e35 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -82,7 +82,8 @@ BOOL gRenderAvatar = TRUE; S32 LLDrawPoolAvatar::getVertexShaderLevel() const { - return (S32) LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR); + return sShaderLevel; + //return (S32) LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR); } void LLDrawPoolAvatar::prerender() @@ -177,20 +178,22 @@ void LLDrawPoolAvatar::endFootShadow() void LLDrawPoolAvatar::beginRigid() { - sVertexProgram = &gAvatarEyeballProgram; + sVertexProgram = NULL; + sShaderLevel = 0; glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - if (sShaderLevel > 0) + /*if (sShaderLevel > 0) { //eyeballs render with the specular shader gAvatarEyeballProgram.bind(); gMaterialIndex = gAvatarEyeballProgram.mAttribute[LLShaderMgr::MATERIAL_COLOR]; gSpecularIndex = gAvatarEyeballProgram.mAttribute[LLShaderMgr::SPECULAR_COLOR]; - } + }*/ } void LLDrawPoolAvatar::endRigid() { + sShaderLevel = mVertexShaderLevel; glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index e0d1792e6c..d96ebc3094 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -326,7 +326,7 @@ const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_ // We're already in the middle of a param's distortions, so get the next one. const LLVector3* v = driven->mParam->getNextDistortion( index, poly_mesh ); - if( !v ) + if( (!v) && (iter != mDriven.end()) ) { // This param is finished, so start the next param. It might not have any // distortions, though, so we have to loop to find the next param that does. diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index cbcdfaa55c..f5e6545369 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -1088,6 +1088,15 @@ F64 LLFastTimerView::getTime(LLFastTimer::EFastTimerType tidx) break; } } + + if (i == FTV_DISPLAY_NUM) + { + // walked off the end of ft_display_table without finding + // the desired timer type + llwarns << "Timer type " << tidx << " not known." << llendl; + return F64(0.0); + } + S32 table_idx = i; // Add child ticks to parent diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 4a69286493..6f43460f70 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -431,8 +431,9 @@ void LLFilePicker::reset() void LLFilePicker::buildFilename( void ) { - strncpy( mFilename, mFiles, LL_MAX_PATH ); /*Flawfinder: ignore*/ - S32 len = strlen( mFilename ); /*Flawfinder: ignore*/ + strncpy( mFilename, mFiles, LL_MAX_PATH ); + mFilename[LL_MAX_PATH-1] = '\0'; // stupid strncpy + S32 len = strlen( mFilename ); strncat(mFilename,gDirUtilp->getDirDelimiter().c_str(), sizeof(mFilename)-len+1); /*Flawfinder: ignore*/ len += strlen(gDirUtilp->getDirDelimiter().c_str()); /*Flawfinder: ignore*/ @@ -838,7 +839,10 @@ void LLFilePicker::getFilePath(SInt32 index) { mFiles[0] = 0; if (mFileVector.size()) - strncpy(mFiles, mFileVector[index].c_str(), sizeof(mFiles)); /*Flawfinder: ignore*/ + { + strncpy(mFiles, mFileVector[index].c_str(), sizeof(mFiles)); + mFiles[sizeof(mFiles)-1] = '\0'; // stupid strncpy + } } void LLFilePicker::getFileName(SInt32 index) @@ -848,7 +852,10 @@ void LLFilePicker::getFileName(SInt32 index) { char *start = strrchr(mFileVector[index].c_str(), '/'); if (start && ((start + 1 - mFileVector[index].c_str()) < (mFileVector[index].size()))) - strncpy(mFilename, start + 1, sizeof(mFilename)); /*Flawfinder: ignore*/ + { + strncpy(mFilename, start + 1, sizeof(mFilename)); + mFilename[sizeof(mFilename)-1] = '\0';// stupid strncpy + } } } diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 22617a7fcc..7085407999 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -34,7 +34,7 @@ #include "llviewercamera.h" #include "llviewerobjectlist.h" #include "llviewerwindow.h" -#include "llviewermenu.h" +#include "llviewermenufile.h" // upload_new_resource() #include "llvoavatar.h" #include "pipeline.h" #include "viewer.h" @@ -201,7 +201,7 @@ BOOL LLFloaterAnimPreview::postBuild() } apr_file_close(fp); - delete file_buffer; + delete[] file_buffer; } } @@ -227,11 +227,11 @@ BOOL LLFloaterAnimPreview::postBuild() // pass animation data through memory buffer loaderp->serialize(dp); dp.reset(); - BOOL success = motionp->deserialize(dp); + BOOL success = motionp && motionp->deserialize(dp); delete []buffer; - if (motionp && success) + if (success) { const LLBBoxLocal &pelvis_bbox = motionp->getPelvisBBox(); diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 1e65ae5620..4f1da916fc 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -267,6 +267,7 @@ void LLFloaterFriends::refreshRightsChangeList(U8 state) bool can_change_online_multiple = true; bool can_change_map_multiple = true; LLTextBox* processing_label = LLUICtrlFactory::getTextBoxByName(this, "process_rights_label"); + if(!mAllowRightsChange) { if(processing_label) @@ -282,9 +283,10 @@ void LLFloaterFriends::refreshRightsChangeList(U8 state) processing_label->setVisible(false); } } + if(state == 1) { - if(!friend_status->isOnline()) + if(friend_status && !friend_status->isOnline()) { childSetEnabled("offer_teleport_btn", false); } diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index 1548c0e5d6..80da7b63ed 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -64,42 +64,54 @@ void LLFloaterInspect::show(void* ignored) void LLFloaterInspect::onClickCreatorProfile(void* ctrl) { if(sInstance->mObjectList->getAllSelected().size() == 0) return; - LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode(); - LLUUID obj_id, creator_id; - obj_id = sInstance->mObjectList->getFirstSelected()->getUUID(); - while(obj) + LLScrollListItem* first_selected = + sInstance->mObjectList->getFirstSelected(); + + if (first_selected) { - if(obj_id == obj->getObject()->getID()) + LLSelectNode* obj= sInstance->mObjectSelection->getFirstNode(); + LLUUID obj_id, creator_id; + obj_id = first_selected->getUUID(); + while(obj) { - creator_id = obj->mPermissions->getCreator(); - break; + if(obj_id == obj->getObject()->getID()) + { + creator_id = obj->mPermissions->getCreator(); + break; + } + obj = sInstance->mObjectSelection->getNextNode(); + } + if(obj) + { + LLFloaterAvatarInfo::showFromDirectory(creator_id); } - obj = sInstance->mObjectSelection->getNextNode(); - } - if(obj) - { - LLFloaterAvatarInfo::showFromDirectory(creator_id); } } void LLFloaterInspect::onClickOwnerProfile(void* ctrl) { if(sInstance->mObjectList->getAllSelected().size() == 0) return; - LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode(); - LLUUID obj_id, owner_id; - obj_id = sInstance->mObjectList->getFirstSelected()->getUUID(); - while(obj) + LLScrollListItem* first_selected = + sInstance->mObjectList->getFirstSelected(); + + if (first_selected) { - if(obj_id == obj->getObject()->getID()) + LLSelectNode* obj= sInstance->mObjectSelection->getFirstNode(); + LLUUID obj_id, owner_id; + obj_id = first_selected->getUUID(); + while(obj) { - owner_id = obj->mPermissions->getOwner(); - break; + if(obj_id == obj->getObject()->getID()) + { + owner_id = obj->mPermissions->getOwner(); + break; + } + obj = sInstance->mObjectSelection->getNextNode(); + } + if(obj) + { + LLFloaterAvatarInfo::showFromDirectory(owner_id); } - obj = sInstance->mObjectSelection->getNextNode(); - } - if(obj) - { - LLFloaterAvatarInfo::showFromDirectory(owner_id); } } @@ -125,7 +137,15 @@ LLUUID LLFloaterInspect::getSelectedUUID() { if(sInstance) { - if(sInstance->mObjectList->getAllSelected().size() > 0) return sInstance->mObjectList->getFirstSelected()->getUUID(); + if(sInstance->mObjectList->getAllSelected().size() > 0) + { + LLScrollListItem* first_selected = + sInstance->mObjectList->getFirstSelected(); + if (first_selected) + { + return first_selected->getUUID(); + } + } } return LLUUID::null; } @@ -139,7 +159,15 @@ void LLFloaterInspect::refresh() childSetEnabled("button creator", false); LLUUID selected_uuid; S32 selected_index = mObjectList->getFirstSelectedIndex(); - if(selected_index > -1) selected_uuid = mObjectList->getFirstSelected()->getUUID(); + if(selected_index > -1) + { + LLScrollListItem* first_selected = + mObjectList->getFirstSelected(); + if (first_selected) + { + selected_uuid = first_selected->getUUID(); + } + } mObjectList->operateOnAll(LLScrollListCtrl::OP_DELETE); //List all transient objects, then all linked objects LLSelectNode* obj = mObjectSelection->getFirstNode(); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 51a1a99d71..9f990d47b7 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1976,12 +1976,18 @@ BOOL LLPanelLandOptions::postBuild() mSnapshotCtrl = LLUICtrlFactory::getTexturePickerByName(this, "snapshot_ctrl"); - mSnapshotCtrl->setCommitCallback( onCommitAny ); - mSnapshotCtrl->setCallbackUserData( this ); - mSnapshotCtrl->setAllowNoTexture ( TRUE ); - mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - + if (mSnapshotCtrl) + { + mSnapshotCtrl->setCommitCallback( onCommitAny ); + mSnapshotCtrl->setCallbackUserData( this ); + mSnapshotCtrl->setAllowNoTexture ( TRUE ); + mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + else + { + llwarns << "LLUICtrlFactory::getTexturePickerByName() returned NULL for 'snapshot_ctrl'" << llendl; + } mLocationText = LLUICtrlFactory::getTextBoxByName(this, "Landing Point: (none)"); @@ -2313,12 +2319,19 @@ BOOL LLPanelLandMedia::postBuild() mMediaTextureCtrl = LLUICtrlFactory::getTexturePickerByName(this, "media texture"); - mMediaTextureCtrl->setCommitCallback( onCommitAny ); - mMediaTextureCtrl->setCallbackUserData( this ); - mMediaTextureCtrl->setAllowNoTexture ( TRUE ); - mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - + if (mMediaTextureCtrl) + { + mMediaTextureCtrl->setCommitCallback( onCommitAny ); + mMediaTextureCtrl->setCallbackUserData( this ); + mMediaTextureCtrl->setAllowNoTexture ( TRUE ); + mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + else + { + llwarns << "LLUICtrlFactory::getTexturePickerByName() returned NULL for 'media texure'" << llendl; + } + mMediaAutoScaleCheck = LLUICtrlFactory::getCheckBoxByName(this, "media_auto_scale"); childSetCommitCallback("media_auto_scale", onCommitAny, this); diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index 6b2562e73c..602a198a03 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -9,6 +9,8 @@ #include "llviewerprecompiledheaders.h" #include "llfloaternamedesc.h" + +// project includes #include "lllineeditor.h" #include "llresmgr.h" #include "lltextbox.h" @@ -16,13 +18,16 @@ #include "llviewerwindow.h" #include "llfocusmgr.h" #include "llradiogroup.h" -#include "llassetstorage.h" #include "lldbstrings.h" #include "lldir.h" #include "llviewercontrol.h" -#include "llviewermenu.h" +#include "llviewermenufile.h" // upload_new_resource() #include "llvieweruictrlfactory.h" +// linden includes +#include "llassetstorage.h" +#include "llinventorytype.h" + const S32 PREVIEW_LINE_HEIGHT = 19; const S32 PREVIEW_CLOSE_BOX_SIZE = 16; const S32 PREVIEW_BORDER_WIDTH = 2; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3a56eab2e2..5364b7da85 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -155,6 +155,66 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainerCommon* tab_container, LLButton // addTabPanel(mWebPanel, "Web", FALSE, onTabChanged, this); } +LLPreferenceCore::~LLPreferenceCore() +{ + if (mGeneralPanel) + { + delete mGeneralPanel; + mGeneralPanel = NULL; + } + if (mInputPanel) + { + delete mInputPanel; + mInputPanel = NULL; + } + if (mNetworkPanel) + { + delete mNetworkPanel; + mNetworkPanel = NULL; + } + if (mDisplayPanel) + { + delete mDisplayPanel; + mDisplayPanel = NULL; + } + if (mDisplayPanel2) + { + delete mDisplayPanel2; + mDisplayPanel2 = NULL; + } + if (mDisplayPanel3) + { + delete mDisplayPanel3; + mDisplayPanel3 = NULL; + } + if (mAudioPanel) + { + delete mAudioPanel; + mAudioPanel = NULL; + } + if (mPrefsChat) + { + delete mPrefsChat; + mPrefsChat = NULL; + } + if (mPrefsIM) + { + delete mPrefsIM; + mPrefsIM = NULL; + } + if (mMsgPanel) + { + delete mMsgPanel; + mMsgPanel = NULL; + } + //if (mWebPanel) + //{ + // delete mWebPanel; + // mWebPanel = NULL; + //} +} + + void LLPreferenceCore::apply() { mGeneralPanel->apply(); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 9988d0c353..8d4078cc9b 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -39,6 +39,7 @@ class LLPreferenceCore public: LLPreferenceCore(LLTabContainerCommon* tab_container, LLButton * default_btn); + ~LLPreferenceCore(); void apply(); void cancel(); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4cc00b12d1..32923e2f11 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -54,7 +54,6 @@ const S32 TERRAIN_TEXTURE_COUNT = 4; const S32 CORNER_COUNT = 4; -#define LL_ENABLE_MAINLAND_VISIBLE_CONTROL 0 ///---------------------------------------------------------------------------- /// Local class declaration @@ -1900,9 +1899,6 @@ BOOL LLPanelEstateInfo::postBuild() { // set up the callbacks for the generic controls initCtrl("externally_visible_check"); -#if LL_ENABLE_MAINLAND_VISIBLE_CONTROL - initCtrl("mainland_visible_check"); -#endif initCtrl("use_global_time_check"); initCtrl("fixed_sun_check"); initCtrl("allow_direct_teleport"); @@ -1914,9 +1910,6 @@ BOOL LLPanelEstateInfo::postBuild() initHelpBtn("use_global_time_help", "HelpEstateUseGlobalTime"); initHelpBtn("fixed_sun_help", "HelpEstateFixedSun"); initHelpBtn("externally_visible_help", "HelpEstateExternallyVisible"); -#if LL_ENABLE_MAINLAND_VISIBLE_CONTROL - initHelpBtn("mainland_visible_help", "HelpEstateMainlandVisible"); -#endif initHelpBtn("allow_direct_teleport_help", "HelpEstateAllowDirectTeleport"); initHelpBtn("allow_resident_help", "HelpEstateAllowResident"); initHelpBtn("allow_group_help", "HelpEstateAllowGroup"); @@ -2085,9 +2078,6 @@ void LLPanelEstateInfo::commitEstateInfo() void LLPanelEstateInfo::setEstateFlags(U32 flags) { childSetValue("externally_visible_check", LLSD(flags & REGION_FLAGS_EXTERNALLY_VISIBLE ? TRUE : FALSE) ); -#if LL_ENABLE_MAINLAND_VISIBLE_CONTROL - childSetValue("mainland_visible_check", LLSD(flags & REGION_FLAGS_MAINLAND_VISIBLE ? TRUE : FALSE) ); -#endif childSetValue("fixed_sun_check", LLSD(flags & REGION_FLAGS_SUN_FIXED ? TRUE : FALSE) ); childSetValue("allow_direct_teleport", LLSD(flags & REGION_FLAGS_ALLOW_DIRECT_TELEPORT ? TRUE : FALSE) ); childSetValue("deny_anonymous", LLSD(flags & REGION_FLAGS_DENY_ANONYMOUS ? TRUE : FALSE) ); @@ -2104,15 +2094,6 @@ U32 LLPanelEstateInfo::computeEstateFlags() { flags |= REGION_FLAGS_EXTERNALLY_VISIBLE; } -#if LL_ENABLE_MAINLAND_VISIBLE_CONTROL - // This flag is ignored by everything. 2006-11-17 Phoenix. - if (childGetValue("mainland_visible_check").asBoolean()) - { - flags |= REGION_FLAGS_MAINLAND_VISIBLE; - } -#else - flags |= REGION_FLAGS_MAINLAND_VISIBLE; -#endif if (childGetValue("allow_direct_teleport").asBoolean()) { diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 8968da9720..f377fae8af 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -46,10 +46,9 @@ #include "lluploaddialog.h" #include "llcallingcard.h" #include "llviewerobjectlist.h" -#include "llagent.h" #include "lltoolobjpicker.h" #include "lltoolmgr.h" -#include "llviewermenu.h" // for LLResourceData +#include "llresourcedata.h" // for LLResourceData #include "llviewerwindow.h" #include "llviewerimagelist.h" #include "llworldmap.h" @@ -945,8 +944,8 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, self->mScreenID = uuid; llinfos << "Got screen shot " << uuid << llendl; self->sendReportViaLegacy(self->gatherReport()); + self->close(); } - self->close(); } diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 92e005c0bb..b47ec270e3 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -33,7 +33,7 @@ #include "llviewerstats.h" #include "llviewercamera.h" #include "llviewerwindow.h" -#include "llviewermenu.h" +#include "llviewermenufile.h" // upload_new_resource() #include "llfloaterpostcard.h" #include "llcheckboxctrl.h" #include "llradiogroup.h" diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 0529507c35..224bd4650f 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -294,8 +294,8 @@ BOOL LLFloaterTools::postBuild() mTab->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT); mTab->setVisible( gSavedSettings.getBOOL("ToolboxShowMore") ); mTab->setBorderVisible(FALSE); + mTab->selectFirstTab(); } - mTab->selectFirstTab(); return TRUE; } diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 31668b6d80..21b2bbb02e 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -209,6 +209,16 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) return itemp; } +// is this item something we think we should be showing? +// for example, if we haven't gotten around to filtering it yet, then the answer is yes +// until we find out otherwise +BOOL LLFolderViewItem::potentiallyVisible() +{ + // we haven't been checked against min required filter + // or we have and we passed + return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); +} + BOOL LLFolderViewItem::getFiltered() { return mFiltered && mLastFilterGeneration >= mRoot->getFilter()->getMinRequiredGeneration(); @@ -315,8 +325,7 @@ void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, } // helper function to change the selection from the root. -void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, - BOOL selected) +void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected) { getRoot()->changeSelection(selection, selected); } @@ -338,6 +347,11 @@ LLString LLFolderViewItem::getWidgetTag() const return LL_FOLDER_VIEW_ITEM_TAG; } +EInventorySortGroup LLFolderViewItem::getSortGroup() +{ + return SG_ITEM; +} + // addToFolder() returns TRUE if it succeeds. FALSE otherwise BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) { @@ -407,8 +421,7 @@ void LLFolderViewItem::dirtyFilter() // means 'deselect' for a leaf item. Do this optimization after // multiple selection is implemented to make sure it all plays nice // together. -BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL open, - BOOL take_keyboard_focus) +BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL open, BOOL take_keyboard_focus) { if( selection == this ) { @@ -425,8 +438,7 @@ BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL open, return mIsSelected; } -BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, - BOOL selected) +BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected) { if(selection == this && mIsSelected != selected) { @@ -768,182 +780,174 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderViewItem::draw() { - if( getVisible() ) + bool possibly_has_children = false; + bool up_to_date = mListener && mListener->isUpToDate(); + if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter... + (!up_to_date && mListener && mListener->hasChildren())) // ...or we know we have children but haven't fetched them (doesn't obey filter) { - bool possibly_has_children = false; - bool up_to_date = mListener && mListener->isUpToDate(); - if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter... - (!up_to_date && mListener && mListener->hasChildren())) // ...or we know we have children but haven't fetched them (doesn't obey filter) - { - possibly_has_children = true; - } - if(/*mControlLabel[0] != '\0' && */possibly_has_children) + possibly_has_children = true; + } + if(/*mControlLabel[0] != '\0' && */possibly_has_children) + { + LLGLSTexture gls_texture; + if (mArrowImage) { - LLGLSTexture gls_texture; - if (mArrowImage) - { - gl_draw_scaled_rotated_image(mIndentation, mRect.getHeight() - ARROW_SIZE - TEXT_PAD, - ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, mArrowImage, sFgColor); - } + gl_draw_scaled_rotated_image(mIndentation, mRect.getHeight() - ARROW_SIZE - TEXT_PAD, + ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, mArrowImage, sFgColor); } + } - F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); + F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); - // If we have keyboard focus, draw selection filled - BOOL show_context = getRoot()->getShowSelectionContext(); - BOOL filled = show_context || (gFocusMgr.getKeyboardFocus() == getRoot()); + // If we have keyboard focus, draw selection filled + BOOL show_context = getRoot()->getShowSelectionContext(); + BOOL filled = show_context || (gFocusMgr.getKeyboardFocus() == getRoot()); - // always render "current" item, only render other selected items if - // mShowSingleSelection is FALSE - if( mIsSelected ) + // always render "current" item, only render other selected items if + // mShowSingleSelection is FALSE + if( mIsSelected ) + { + LLGLSNoTexture gls_no_texture; + LLColor4 bg_color = sHighlightBgColor; + //const S32 TRAILING_PAD = 5; // It just looks better with this. + if (!mIsCurSelection) { - LLGLSNoTexture gls_no_texture; - LLColor4 bg_color = sHighlightBgColor; - //const S32 TRAILING_PAD = 5; // It just looks better with this. - if (!mIsCurSelection) + // do time-based fade of extra objects + F32 fade_time = getRoot()->getSelectionFadeElapsedTime(); + if (getRoot()->getShowSingleSelection()) { - // do time-based fade of extra objects - F32 fade_time = getRoot()->getSelectionFadeElapsedTime(); - if (getRoot()->getShowSingleSelection()) - { - // fading out - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); - } - else - { - // fading in - bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); - } + // fading out + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f); } + else + { + // fading in + bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); + } + } + gl_rect_2d( + 0, + mRect.getHeight(), + mRect.getWidth() - 2, + llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), + bg_color, filled); + if (mIsCurSelection) + { gl_rect_2d( 0, mRect.getHeight(), mRect.getWidth() - 2, llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), - bg_color, filled); - if (mIsCurSelection) - { - gl_rect_2d( - 0, - mRect.getHeight(), - mRect.getWidth() - 2, - llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), - sHighlightFgColor, FALSE); - } - if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) - { - gl_rect_2d( - 0, - llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, - mRect.getWidth() - 2, - 2, - sHighlightFgColor, FALSE); - if (show_context) - { - gl_rect_2d( - 0, - llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, - mRect.getWidth() - 2, - 2, - sHighlightBgColor, TRUE); - } - } + sHighlightFgColor, FALSE); } - if (mDragAndDropTarget) + if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) { - LLGLSNoTexture gls_no_texture; gl_rect_2d( 0, - mRect.getHeight(), + llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, mRect.getWidth() - 2, - llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), - sHighlightBgColor, FALSE); - - if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) + 2, + sHighlightFgColor, FALSE); + if (show_context) { gl_rect_2d( 0, llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, mRect.getWidth() - 2, 2, - sHighlightBgColor, FALSE); + sHighlightBgColor, TRUE); } - mDragAndDropTarget = FALSE; } + } + if (mDragAndDropTarget) + { + LLGLSNoTexture gls_no_texture; + gl_rect_2d( + 0, + mRect.getHeight(), + mRect.getWidth() - 2, + llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD), + sHighlightBgColor, FALSE); - - if(mIcon) + if (mRect.getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2) { - gl_draw_image(mIndentation + ARROW_SIZE + TEXT_PAD, mRect.getHeight() - mIcon->getHeight(), mIcon); - mIcon->addTextureStats( (F32)(mIcon->getWidth() * mIcon->getHeight())); + gl_rect_2d( + 0, + llfloor(mRect.getHeight() - sFont->getLineHeight() - ICON_PAD) - 2, + mRect.getWidth() - 2, + 2, + sHighlightBgColor, FALSE); } + mDragAndDropTarget = FALSE; + } - if (!mLabel.empty()) - { - // highlight filtered text - BOOL debug_filters = getRoot()->getDebugFilters(); - LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor ); - F32 right_x; - F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; - if (debug_filters) - { - if (!getFiltered() && !possibly_has_children) - { - color.mV[VALPHA] *= 0.5f; - } - - LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f); - sSmallFont->renderUTF8(mStatusText, 0, text_left, y, filter_color, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, - S32_MAX, S32_MAX, &right_x, FALSE ); - text_left = right_x; - } + if(mIcon) + { + gl_draw_image(mIndentation + ARROW_SIZE + TEXT_PAD, mRect.getHeight() - mIcon->getHeight(), mIcon); + mIcon->addTextureStats( (F32)(mIcon->getWidth() * mIcon->getHeight())); + } - sFont->renderUTF8( mLabel, 0, text_left, y, color, - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, - S32_MAX, S32_MAX, &right_x, FALSE ); - if (!mLabelSuffix.empty()) - { - sFont->renderUTF8( mLabelSuffix, 0, right_x, y, LLColor4(0.75f, 0.85f, 0.85f, 1.f), - LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, - S32_MAX, S32_MAX, &right_x, FALSE ); - } + if (!mLabel.empty()) + { + // highlight filtered text + BOOL debug_filters = getRoot()->getDebugFilters(); + LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor ); + F32 right_x; + F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; - if (mBoxImage.notNull() && mStringMatchOffset != LLString::npos) + if (debug_filters) + { + if (!getFiltered() && !possibly_has_children) { - // don't draw backgrounds for zero-length strings - S32 filter_string_length = mRoot->getFilterSubString().size(); - if (filter_string_length > 0) - { - LLString combined_string = mLabel + mLabelSuffix; - S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1; - S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - S32 bottom = llfloor(mRect.getHeight() - sFont->getLineHeight() - 3); - S32 top = mRect.getHeight(); - - LLViewerImage::bindTexture(mBoxImage); - glColor4fv(sFilterBGColor.mV); - gl_segmented_rect_2d_tex(left, top, right, bottom, mBoxImage->getWidth(), mBoxImage->getHeight(), 16); - F32 match_string_left = text_left + sFont->getWidthF32(combined_string, 0, mStringMatchOffset); - F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; - sFont->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, - filter_string_length, S32_MAX, &right_x, FALSE ); - } + color.mV[VALPHA] *= 0.5f; } + + LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f); + sSmallFont->renderUTF8(mStatusText, 0, text_left, y, filter_color, + LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, + S32_MAX, S32_MAX, &right_x, FALSE ); + text_left = right_x; } - if( sDebugRects ) + sFont->renderUTF8( mLabel, 0, text_left, y, color, + LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, + S32_MAX, S32_MAX, &right_x, FALSE ); + if (!mLabelSuffix.empty()) { - drawDebugRect(); + sFont->renderUTF8( mLabelSuffix, 0, right_x, y, LLColor4(0.75f, 0.85f, 0.85f, 1.f), + LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, + S32_MAX, S32_MAX, &right_x, FALSE ); + } + + if (mBoxImage.notNull() && mStringMatchOffset != LLString::npos) + { + // don't draw backgrounds for zero-length strings + S32 filter_string_length = mRoot->getFilterSubString().size(); + if (filter_string_length > 0) + { + LLString combined_string = mLabel + mLabelSuffix; + S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1; + S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; + S32 bottom = llfloor(mRect.getHeight() - sFont->getLineHeight() - 3); + S32 top = mRect.getHeight(); + + LLViewerImage::bindTexture(mBoxImage); + glColor4fv(sFilterBGColor.mV); + gl_segmented_rect_2d_tex(left, top, right, bottom, mBoxImage->getWidth(), mBoxImage->getHeight(), 16); + F32 match_string_left = text_left + sFont->getWidthF32(combined_string, 0, mStringMatchOffset); + F32 y = (F32)mRect.getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD; + sFont->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y, + sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, + filter_string_length, S32_MAX, &right_x, FALSE ); + } } } - else if (mStatusText.size()) + + if( sDebugRects ) { - // just draw status text - sFont->renderUTF8( mStatusText, 0, 0, 1, sFgColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, S32_MAX, S32_MAX, NULL, FALSE ); + drawDebugRect(); } } @@ -957,7 +961,6 @@ LLFolderViewFolder::LLFolderViewFolder( const LLString& name, LLViewerImage* ico LLFolderView* root, LLFolderViewEventListener* listener ): LLFolderViewItem( name, icon, 0, root, listener ), // 0 = no create time - mSortFunction(sort_item_name), mIsOpen(FALSE), mExpanderHighlighted(FALSE), mCurHeight(0.f), @@ -1226,7 +1229,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) } // when applying a filter, matching folders get their contents downloaded first - if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && !gInventory.isCategoryComplete(mListener->getUUID())) + if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID()))) { gInventory.startBackgroundFetch(mListener->getUUID()); } @@ -1647,7 +1650,8 @@ BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) { if(item->remove()) { - removeView(item); + //RN: this seem unneccessary as remove() moves to trash + //removeView(item); return TRUE; } return FALSE; @@ -1657,7 +1661,7 @@ BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item) // listeners. void LLFolderViewFolder::removeView(LLFolderViewItem* item) { - if (!item) + if (!item || item->getParentFolder() != this) { return; } @@ -1702,23 +1706,8 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) // This is only called for renaming an object because it won't work for date void LLFolderViewFolder::resort(LLFolderViewItem* item) { - std::sort(mItems.begin(), mItems.end(), *mSortFunction); - std::sort(mFolders.begin(), mFolders.end(), *mSortFunction); - //if(mItems.removeData(item)) - //{ - // mItems.addDataSorted(item); - //} - //else - //{ - // // This is an evil downcast. However, it's only doing - // // pointer comparison to find if (which it should be ) the - // // item is in the container, so it's pretty safe. - // LLFolderViewFolder* f = reinterpret_cast<LLFolderViewFolder*>(item); - // if(mFolders.removeData(f)) - // { - // mFolders.addDataSorted(f); - // } - //} + std::sort(mItems.begin(), mItems.end(), mSortFunction); + std::sort(mFolders.begin(), mFolders.end(), mSortFunction); } bool LLFolderViewFolder::isTrash() @@ -1732,65 +1721,22 @@ bool LLFolderViewFolder::isTrash() void LLFolderViewFolder::sortBy(U32 order) { - BOOL sort_order_changed = FALSE; - if (!(order & LLInventoryFilter::SO_DATE)) - { - if (mSortFunction != sort_item_name) - { - mSortFunction = sort_item_name; - sort_order_changed = TRUE; - } - } - else + if (!mSortFunction.updateSort(order)) { - if (mSortFunction != sort_item_date) - { - mSortFunction = sort_item_date; - sort_order_changed = TRUE; - } + // No changes. + return; } + // Propegate this change to sub folders for (folders_t::iterator iter = mFolders.begin(); iter != mFolders.end();) { folders_t::iterator fit = iter++; (*fit)->sortBy(order); } - if (order & LLInventoryFilter::SO_FOLDERS_BY_NAME) - { - // sort folders by name if always by name - std::sort(mFolders.begin(), mFolders.end(), sort_item_name); - } - else - { - // sort folders by the default sort ordering - std::sort(mFolders.begin(), mFolders.end(), *mSortFunction); - // however, if we are at the root of the inventory and we are sorting by date - if (mListener->getUUID() == gAgent.getInventoryRootID() && order & LLInventoryFilter::SO_DATE) - { - // pull the trash folder and stick it on the end of the list - LLFolderViewFolder *t = NULL; - for (folders_t::iterator fit = mFolders.begin(); - fit != mFolders.end(); ++fit) - { - if ((*fit)->isTrash()) - { - t = *fit; - mFolders.erase(fit); - break; - } - } - if (t) - { - mFolders.push_back(t); - } - } - } - if (sort_order_changed) - { - std::sort(mItems.begin(), mItems.end(), *mSortFunction); - } + std::sort(mFolders.begin(), mFolders.end(), mSortFunction); + std::sort(mItems.begin(), mItems.end(), mSortFunction); if (order & LLInventoryFilter::SO_DATE) { @@ -1814,19 +1760,39 @@ void LLFolderViewFolder::sortBy(U32 order) } } -void LLFolderViewFolder::setItemSortFunction(sort_order_f ordering) +void LLFolderViewFolder::setItemSortOrder(U32 ordering) { - mSortFunction = ordering; + if (mSortFunction.updateSort(ordering)) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + (*fit)->setItemSortOrder(ordering); + } - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + std::sort(mFolders.begin(), mFolders.end(), mSortFunction); + std::sort(mItems.begin(), mItems.end(), mSortFunction); + } +} + +EInventorySortGroup LLFolderViewFolder::getSortGroup() +{ + if (isTrash()) { - folders_t::iterator fit = iter++; - (*fit)->setItemSortFunction(ordering); + return SG_TRASH_FOLDER; } - std::sort(mFolders.begin(), mFolders.end(), *mSortFunction); - std::sort(mItems.begin(), mItems.end(), *mSortFunction); + // Folders that can't be moved are 'system' folders. + if( mListener ) + { + if( !(mListener->isItemMovable()) ) + { + return SG_SYSTEM_FOLDER; + } + } + + return SG_NORMAL_FOLDER; } BOOL LLFolderViewFolder::isMovable() @@ -1897,6 +1863,7 @@ BOOL LLFolderViewFolder::isRemovable() // this is an internal method used for adding items to folders. BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) { + items_t::iterator it = std::lower_bound( mItems.begin(), mItems.end(), @@ -1925,18 +1892,29 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) folder->setVisible(FALSE); addChild( folder ); folder->dirtyFilter(); - requestArrange(); + // rearrange all descendants too, as our indentation level might have changed + folder->requestArrange(TRUE); return TRUE; } -void LLFolderViewFolder::requestArrange() +void LLFolderViewFolder::requestArrange(BOOL include_descendants) { mLastArrangeGeneration = -1; // flag all items up to root - if (mParentFolder) + if (mParentFolder && !mParentFolder->needsArrange()) { mParentFolder->requestArrange(); } + + if (include_descendants) + { + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end(); + ++iter) + { + (*iter)->requestArrange(TRUE); + } + } } void LLFolderViewFolder::toggleOpen() @@ -1982,11 +1960,11 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL open, ERecurseType recur } BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, - BOOL drop, - EDragAndDropType c_type, - void* cargo_data, - EAcceptance* accept, - LLString& tooltip_msg) + BOOL drop, + EDragAndDropType c_type, + void* cargo_data, + EAcceptance* accept, + LLString& tooltip_msg) { BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data); if (accepted) @@ -2198,16 +2176,13 @@ void LLFolderViewFolder::draw() } LLFolderViewItem::draw(); - if( mIsOpen ) + + // draw children if root folder, or any other folder that is open or animating to closed state + if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight )) { LLView::draw(); } -// if (mExpanderHighlighted) -// { -// gl_rect_2d(mIndentation - TEXT_PAD, llfloor(mRect.getHeight() - TEXT_PAD), mIndentation + sFont->getWidth(mControlLabel) + TEXT_PAD, llfloor(mRect.getHeight() - sFont->getLineHeight() - TEXT_PAD), sFgColor, FALSE); -// //sFont->renderUTF8( mControlLabel, 0, mIndentation, llfloor(mRect.getHeight() - sFont->getLineHeight() - TEXT_PAD), sFgColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, S32_MAX, S32_MAX, NULL, FALSE ); -// } mExpanderHighlighted = FALSE; } @@ -2217,6 +2192,16 @@ U32 LLFolderViewFolder::getCreationDate() const } +BOOL LLFolderViewFolder::potentiallyVisible() +{ + // folder should be visible by it's own filter status + return LLFolderViewItem::potentiallyVisible() + // or one or more of its descendants have passed the minimum filter requirement + || hasFilteredDescendants(mRoot->getFilter()->getMinRequiredGeneration()) + // or not all of its descendants have been checked against minimum filter requirement + || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration(); +} + // this does prefix traversal, as folders are listed above their contents LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children ) { @@ -2436,20 +2421,20 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it class LLSetItemSortFunction : public LLFolderViewFunctor { public: - LLSetItemSortFunction(sort_order_f ordering) - : mSortFunction(ordering) {} + LLSetItemSortFunction(U32 ordering) + : mSortOrder(ordering) {} virtual ~LLSetItemSortFunction() {} virtual void doFolder(LLFolderViewFolder* folder); virtual void doItem(LLFolderViewItem* item); - sort_order_f mSortFunction; + U32 mSortOrder; }; // Set the sort order. void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder) { - folder->setItemSortFunction(mSortFunction); + folder->setItemSortOrder(mSortOrder); } // Do nothing. @@ -2676,6 +2661,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) folder->setVisible(FALSE); addChild( folder ); folder->dirtyFilter(); + folder->requestArrange(); return TRUE; } @@ -2896,8 +2882,8 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL open, /* Flaw addToSelectionList(selection); } - BOOL rv = LLFolderViewFolder::setSelection(selection, open, take_keyboard_focus); /* Flawfinder: ignore */ - if(open) /* Flawfinder: ignore */ + BOOL rv = LLFolderViewFolder::setSelection(selection, open, take_keyboard_focus); + if(open && selection) { selection->getParentFolder()->requestArrange(); } @@ -2934,11 +2920,6 @@ BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) } BOOL on_list = (item_iter != mSelectedItems.end()); - if (on_list && mSelectedItems.size() == 1) - { - // we are trying to select/deselect the only selected item - return FALSE; - } if(selected && !on_list) { @@ -2985,48 +2966,46 @@ S32 LLFolderView::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* void LLFolderView::sanitizeSelection() { + // store off current item in case it is automatically deselected + // and we want to preserve context + LLFolderViewItem* original_selected_item = getCurSelectedItem(); + std::vector<LLFolderViewItem*> items_to_remove; selected_items_t::iterator item_iter; for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) { LLFolderViewItem* item = *item_iter; - BOOL visible = item->getVisible(); + // ensure that each ancestor is open and potentially passes filtering + BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item + // modify with parent open and filters states LLFolderViewFolder* parent_folder = item->getParentFolder(); - while(visible && parent_folder) + while(parent_folder) { - visible = visible && parent_folder->isOpen() && parent_folder->getVisible(); + visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); parent_folder = parent_folder->getParentFolder(); } - if (!visible || item->getNumSelectedDescendants() > 0) + + // deselect item if any ancestor is closed or didn't pass filter requirements. + if (!visible) { - // only deselect self if not visible - // check to see if item failed the filter but was checked against most recent generation - if ((!item->getFiltered() && item->getLastFilterGeneration() >= getFilter()->getMinRequiredGeneration()) - || (item->getParentFolder() && !item->getParentFolder()->isOpen())) - { - item->recursiveDeselect(TRUE); - items_to_remove.push_back(item); - } - else - { - item->recursiveDeselect(FALSE); - } + items_to_remove.push_back(item); + } - selected_items_t::iterator other_item_iter; - for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) + // disallow nested selections (i.e. folder items plus one or more ancestors) + // could check cached mum selections count and only iterate if there are any + // but that may be a premature optimization. + selected_items_t::iterator other_item_iter; + for (other_item_iter = mSelectedItems.begin(); other_item_iter != mSelectedItems.end(); ++other_item_iter) + { + LLFolderViewItem* other_item = *other_item_iter; + for(LLFolderViewFolder* parent_folder = other_item->getParentFolder(); parent_folder; parent_folder = parent_folder->getParentFolder()) { - LLFolderViewItem* other_item = *other_item_iter; - LLFolderViewFolder* parent_folder = other_item->getParentFolder(); - while (parent_folder) + if (parent_folder == item) { - if (parent_folder == item) - { - // this is a descendent of the current folder, remove from list - items_to_remove.push_back(other_item); - break; - } - parent_folder = parent_folder->getParentFolder(); + // this is a descendent of the current folder, remove from list + items_to_remove.push_back(other_item); + break; } } } @@ -3035,7 +3014,47 @@ void LLFolderView::sanitizeSelection() std::vector<LLFolderViewItem*>::iterator item_it; for (item_it = items_to_remove.begin(); item_it != items_to_remove.end(); ++item_it ) { - removeFromSelectionList(*item_it); + changeSelection(*item_it, FALSE); // toggle selection (also removes from list) + } + + // if nothing selected after prior constraints... + if (mSelectedItems.empty()) + { + // ...select first available parent of original selection, or "My Inventory" otherwise + LLFolderViewItem* new_selection = NULL; + if (original_selected_item) + { + for(LLFolderViewFolder* parent_folder = original_selected_item->getParentFolder(); + parent_folder; + parent_folder = parent_folder->getParentFolder()) + { + if (parent_folder->potentiallyVisible()) + { + // give initial selection to first ancestor folder that potentially passes the filter + if (!new_selection) + { + new_selection = parent_folder; + } + + // if any ancestor folder of original item is closed, move the selection up + // to the highest closed + if (!parent_folder->isOpen()) + { + new_selection = parent_folder; + } + } + } + } + else + { + // nothing selected to start with, so pick "My Inventory" as best guess + new_selection = getItemByID(gAgent.getInventoryRootID()); + } + + if (new_selection) + { + setSelection(new_selection, FALSE, FALSE); + } } } @@ -3212,7 +3231,7 @@ void LLFolderView::removeSelectedItems( void ) // create a temporary structure which we will use to remove // items, since the removal will futz with internal data // structures. - LLDynamicArray<LLFolderViewItem*> items; + std::vector<LLFolderViewItem*> items; S32 count = mSelectedItems.size(); if(count == 0) return; LLFolderViewItem* item = NULL; @@ -3222,7 +3241,7 @@ void LLFolderView::removeSelectedItems( void ) item = *item_it; if(item->isRemovable()) { - items.put(item); + items.push_back(item); } else { @@ -3232,11 +3251,11 @@ void LLFolderView::removeSelectedItems( void ) } // iterate through the new container. - count = items.count(); + count = items.size(); LLUUID new_selection_id; if(count == 1) { - LLFolderViewItem* item_to_delete = items.get(0); + LLFolderViewItem* item_to_delete = items[0]; LLFolderViewFolder* parent = item_to_delete->getParentFolder(); LLFolderViewItem* new_selection = item_to_delete->getNextOpenNode(FALSE); if (!new_selection) @@ -3264,7 +3283,7 @@ void LLFolderView::removeSelectedItems( void ) { LLDynamicArray<LLFolderViewEventListener*> listeners; LLFolderViewEventListener* listener; - LLFolderViewItem* last_item = items.get(count - 1); + LLFolderViewItem* last_item = items[count - 1]; LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); while(new_selection && new_selection->isSelected()) { @@ -3289,7 +3308,7 @@ void LLFolderView::removeSelectedItems( void ) for(S32 i = 0; i < count; ++i) { - listener = items.get(i)->getListener(); + listener = items[i]->getListener(); if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL)) { listeners.put(listener); @@ -3600,21 +3619,6 @@ void LLFolderView::setFocus(BOOL focus) { if (focus) { - // select "My Inventory" if nothing selected - if (!getCurSelectedItem()) - { - LLFolderViewItem* itemp = getItemByID(gAgent.getInventoryRootID()); - if (itemp) - { - setSelection(itemp, FALSE, FALSE); - } - } - - if (mRenamer->getVisible()) - { - //RN: commit rename changes when focus is moved, only revert on ESC - finishRenamingItem(); - } if(!hasFocus()) { gEditMenuHandler = this; @@ -3934,10 +3938,10 @@ BOOL LLFolderView::search(LLFolderViewItem* first_item, const LLString &search_s LLString::toUpper(upper_case_string); // if nothing selected, select first item in folder - if (!first_item) + if (!search_item) { // start from first item - first_item = getNextFromChild(NULL); + search_item = getNextFromChild(NULL); } // search over all open nodes for first substring match (with wrapping) @@ -4228,8 +4232,6 @@ void LLFolderView::idle(void* user_data) // filter to determine visiblity before arranging self->filterFromRoot(); - self->sanitizeSelection(); - // automatically show matching items, and select first one // do this every frame until user puts keyboard focus into the inventory window // signaling the end of the automatic update @@ -4249,6 +4251,8 @@ void LLFolderView::idle(void* user_data) self->scrollToShowSelection(); } + self->sanitizeSelection(); + if( self->needsArrange() && self->isInVisibleChain()) { self->arrangeFromRoot(); @@ -4287,45 +4291,71 @@ void LLFolderView::dumpSelectionInformation() ///---------------------------------------------------------------------------- /// Local function definitions ///---------------------------------------------------------------------------- - -bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b) +bool LLInventorySort::updateSort(U32 order) { - // Sort 'system' / unmovable folders to the top. - if (a->isMovable() != b->isMovable()) - { - return b->isMovable(); - } - - S32 compare = LLString::compareDict(a->getLabel(), b->getLabel()); - if (0 == compare) - { - return (a->getCreationDate() > b->getCreationDate()); - } - else + if (order != mSortOrder) { - return (compare < 0); + mSortOrder = order; + mByDate = (order & LLInventoryFilter::SO_DATE); + mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); + mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + return true; } + return false; } -// BUG: This is very very slow. The getCreationDate() is log n in number -// of inventory items. -bool sort_item_date(LLFolderViewItem* a, LLFolderViewItem* b) +bool LLInventorySort::operator()(LLFolderViewItem* a, LLFolderViewItem* b) { - // Sort 'system' / unmovable folders to the top. - if (a->isMovable() != b->isMovable()) + // We sort by name if we aren't sorting by date + // OR if these are folders and we are sorting folders by name. + bool by_name = (!mByDate + || (mFoldersByName + && (a->getSortGroup() != SG_ITEM))); + + if (a->getSortGroup() != b->getSortGroup()) { - return b->isMovable(); + if (mSystemToTop) + { + // Group order is System Folders, Trash, Normal Folders, Items + return (a->getSortGroup() < b->getSortGroup()); + } + else if (mByDate) + { + // Trash needs to go to the bottom if we are sorting by date + if ( (a->getSortGroup() == SG_TRASH_FOLDER) + || (b->getSortGroup() == SG_TRASH_FOLDER)) + { + return (b->getSortGroup() == SG_TRASH_FOLDER); + } + } } - U32 first_create = a->getCreationDate(); - U32 second_create = b->getCreationDate(); - if (first_create == second_create) + if (by_name) { - return (LLString::compareDict(a->getLabel(), b->getLabel()) < 0); + S32 compare = LLString::compareDict(a->getLabel(), b->getLabel()); + if (0 == compare) + { + return (a->getCreationDate() > b->getCreationDate()); + } + else + { + return (compare < 0); + } } else { - return (first_create > second_create); + // BUG: This is very very slow. The getCreationDate() is log n in number + // of inventory items. + U32 first_create = a->getCreationDate(); + U32 second_create = b->getCreationDate(); + if (first_create == second_create) + { + return (LLString::compareDict(a->getLabel(), b->getLabel()) < 0); + } + else + { + return (first_create > second_create); + } } } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 76784f1ac9..248118dfdf 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -161,6 +161,7 @@ public: static const U32 SO_DATE = 1; static const U32 SO_FOLDERS_BY_NAME = 2; + static const U32 SO_SYSTEM_FOLDERS_TO_TOP = 4; LLInventoryFilter(const LLString& name); virtual ~LLInventoryFilter(); @@ -245,6 +246,34 @@ private: LLString mFilterText; }; +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM +}; + +class LLInventorySort +{ +public: + LLInventorySort() + : mSortOrder(0) { } + + // Returns true if order has changed + bool updateSort(U32 order); + U32 getSort() { return mSortOrder; } + + bool operator()(LLFolderViewItem* a, LLFolderViewItem* b); +private: + U32 mSortOrder; + bool mByDate; + bool mSystemToTop; + bool mFoldersByName; +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewItem // @@ -331,6 +360,8 @@ public: enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); + virtual EInventorySortGroup getSortGroup(); + // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); @@ -429,8 +460,10 @@ public: virtual void setStatusText(const LLString& text) { mStatusText = text; } - BOOL getFiltered(); - BOOL getFiltered(S32 filter_generation); + virtual BOOL potentiallyVisible(); // do we know for a fact that this item has been filtered out? + + virtual BOOL getFiltered(); + virtual BOOL getFiltered(S32 filter_generation); virtual void setFiltered(BOOL filtered, S32 filter_generation); // change the icon @@ -484,7 +517,7 @@ protected: typedef std::vector<LLFolderViewFolder*> folders_t; items_t mItems; folders_t mFolders; - sort_order_f mSortFunction; + LLInventorySort mSortFunction; BOOL mIsOpen; BOOL mExpanderHighlighted; @@ -514,6 +547,8 @@ public: virtual EWidgetType getWidgetType() const; virtual LLString getWidgetTag() const; + virtual BOOL potentiallyVisible(); + LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); @@ -526,6 +561,9 @@ public: BOOL needsArrange(); + // Returns the sort group (system, trash, folder) for this folder. + virtual EInventorySortGroup getSortGroup(); + virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up); virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; } @@ -583,7 +621,7 @@ public: // This function is called by a child that needs to be resorted. void resort(LLFolderViewItem* item); - void setItemSortFunction(sort_order_f ordering); + void setItemSortOrder(U32 ordering); void sortBy(U32); //BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b)); @@ -597,7 +635,8 @@ public: virtual void setOpen(BOOL open = TRUE); /* Flawfinder: ignore */ // Called when a child is refreshed. - virtual void requestArrange(); + // don't rearrange child folder contents unless explicitly requested + virtual void requestArrange(BOOL include_descendants = FALSE); // internal method which doesn't update the entire view. This // method was written because the list iterators destroy the state diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 7a6b7b1bf3..39601eca25 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -1114,5 +1114,5 @@ void post_show_depth_buffer() } glDrawPixels(xsize,ysize,GL_RED,GL_UNSIGNED_BYTE,buf); - delete buf; + delete [] buf; } diff --git a/indra/newview/llhudeffecttrail.cpp b/indra/newview/llhudeffecttrail.cpp index 05da40f214..1ce443fd00 100644 --- a/indra/newview/llhudeffecttrail.cpp +++ b/indra/newview/llhudeffecttrail.cpp @@ -92,17 +92,19 @@ void LLHUDEffectSpiral::packData(LLMessageSystem *mesgsys) void LLHUDEffectSpiral::unpackData(LLMessageSystem *mesgsys, S32 blocknum) { - U8 packed_data[56]; + const size_t EFFECT_SIZE = 56; + U8 packed_data[EFFECT_SIZE]; LLHUDEffect::unpackData(mesgsys, blocknum); LLUUID object_id, target_object_id; S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); - if (size != 56) + if (size != EFFECT_SIZE) { llwarns << "Spiral effect with bad size " << size << llendl; return; } - mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 56, blocknum); + mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, + packed_data, EFFECT_SIZE, blocknum, EFFECT_SIZE); htonmemcpy(object_id.mData, packed_data, MVT_LLUUID, 16); htonmemcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16); diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 72c114d966..9b74b3963b 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -77,9 +77,12 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, LLVector3 render_pos = pos_agent + (floorf(x_offset) * right_axis) + (floorf(y_offset) * up_axis); //get the render_pos in screen space - F64* modelview = gGLModelView; - F64* projection = gGLProjection; - GLint* viewport = (GLint*) gGLViewport; + F64 modelview[16]; + F64 projection[16]; + GLint viewport[4]; + glGetDoublev(GL_MODELVIEW_MATRIX, modelview); + glGetDoublev(GL_PROJECTION_MATRIX, projection); + glGetIntegerv(GL_VIEWPORT, viewport); F64 winX, winY, winZ; gluProject(render_pos.mV[0], render_pos.mV[1], render_pos.mV[2], diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index f90fe340b4..13d13031b6 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -549,10 +549,10 @@ const char* safe_inv_type_lookup(LLInventoryType::EType inv_type) } LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - const LLUUID& uuid, - U32 flags) + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + const LLUUID& uuid, + U32 flags) { LLInvFVBridge* new_listener = NULL; switch(asset_type) @@ -657,7 +657,11 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, break; } - new_listener->mInvType = inv_type; + if (new_listener) + { + new_listener->mInvType = inv_type; + } + return new_listener; } @@ -887,16 +891,20 @@ BOOL LLItemBridge::removeItem() if(!model) return FALSE; LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); LLViewerInventoryItem* item = getItem(); - if(item) + + // if item is not already in trash + if(item && !model->isObjectDescendentOf(mUUID, trash_id)) { - // restamp on move to trash. + // move to trash, and restamp LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); + // delete was successful + return TRUE; + } + else + { + // tried to delete already item in trash (should purge?) + return FALSE; } - - // return false anyway, so that if it's called from the folder - // view, it doesn't remove the view - it's just being moved to the - // trash. - return FALSE; } BOOL LLItemBridge::isItemCopyable() const @@ -1442,11 +1450,20 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) { LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); - if (category->getDescendentCount() == mContentsCount) + if (NULL == category) { - gInventory.removeObserver(this); - wear_inventory_category(category, FALSE, TRUE); - delete this; + llwarns << "gInventory.getCategory(" << mCatID + << ") was NULL" << llendl; + } + else + { + if (category->getDescendentCount() == + mContentsCount) + { + gInventory.removeObserver(this); + wear_inventory_category(category, FALSE, TRUE); + delete this; + } } } @@ -1662,11 +1679,7 @@ BOOL LLFolderBridge::removeItem() LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); } - // return false anyway, so that if it's called from the folder - // view, it doesn't remove the view - it's just being moved to the - // trash. - return FALSE; - + return TRUE; } BOOL LLFolderBridge::isClipboardPasteable() const @@ -2158,10 +2171,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // everything in the active window so that we don't follow // the selection to its new location (which is very // annoying). - LLInventoryPanel* active_panel = LLInventoryView::getActiveInventory()->getPanel(); - if (mInventoryPanel != active_panel) + if (LLInventoryView::getActiveInventory()) { - active_panel->unSelectAll(); + LLInventoryPanel* active_panel = LLInventoryView::getActiveInventory()->getPanel(); + if (active_panel && (mInventoryPanel != active_panel)) + { + active_panel->unSelectAll(); + } } // restamp if the move is into the trash. @@ -3097,7 +3113,16 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); } // this object might have been selected, so let the selection manager know it's gone now - gSelectMgr->remove(gObjectList.findObject(item->getUUID())); + LLViewerObject *found_obj = + gObjectList.findObject(item->getUUID()); + if (found_obj) + { + gSelectMgr->remove(found_obj); + } + else + { + llwarns << "object not found - ignoring" << llendl; + } } else LLItemBridge::performAction(folder, model, action); } @@ -4007,7 +4032,15 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata) gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); // this object might have been selected, so let the selection manager know it's gone now - gSelectMgr->remove(gObjectList.findObject( obj_item_array.get(i)->getUUID()) ); + LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID()); + if (found_obj) + { + gSelectMgr->remove(found_obj); + } + else + { + llwarns << "object not found, ignoring" << llendl; + } } } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index edc4ba0ca6..8be81c944e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -7,6 +7,7 @@ */ #include "llviewerprecompiledheaders.h" + #include "llinventorymodel.h" #include "llassetstorage.h" @@ -21,6 +22,7 @@ #include "llfocusmgr.h" #include "llinventoryview.h" #include "llviewerinventory.h" +#include "llviewermessage.h" #include "llviewerwindow.h" #include "viewer.h" #include "lldbstrings.h" @@ -2262,7 +2264,7 @@ void LLInventoryModel::processUseCachedInventory(LLMessageSystem* msg, void**) void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, void**) { // do accounting and highlight new items if they arrive - if (gInventory.messageUpdateCore(msg, true, true)) + if (gInventory.messageUpdateCore(msg, true)) { U32 callback_id; LLUUID item_id; @@ -2278,12 +2280,15 @@ void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, vo void LLInventoryModel::processFetchInventoryReply(LLMessageSystem* msg, void**) { // no accounting - gInventory.messageUpdateCore(msg, false, false); + gInventory.messageUpdateCore(msg, false); } -bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, bool highlight_new) +bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account) { + //make sure our added inventory observer is active -Gigs + start_new_inventory_observer(); + LLUUID agent_id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); if(agent_id != gAgent.getID()) @@ -2292,16 +2297,15 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo << llendl; return false; } - LLPointer<LLViewerInventoryItem> lastitem; // hack item_array_t items; update_map_t update; S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); bool all_one_folder = true; LLUUID folder_id; + // Does this loop ever execute more than once? -Gigs for(S32 i = 0; i < count; ++i) { LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; - lastitem = titem; titem->unpackMessage(msg, _PREHASH_InventoryData, i); lldebugs << "LLInventoryModel::messageUpdateCore() item id:" << titem->getUUID() << llendl; @@ -2339,6 +2343,7 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo } U32 changes = 0x0; + //as above, this loop never seems to loop more than once per call for (item_array_t::iterator it = items.begin(); it != items.end(); ++it) { changes |= gInventory.updateItem(*it); @@ -2346,88 +2351,6 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo gInventory.notifyObservers(); gViewerWindow->getWindow()->decBusyCount(); - // *HACK: Do the 'show' logic for a new item in the inventory if - // it is a newly created item. - if (highlight_new - && (changes & LLInventoryObserver::ADD) == LLInventoryObserver::ADD) - { - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); - if(!gInventory.isObjectDescendentOf(lastitem->getUUID(), trash_id)) - { - LLMultiPreview* multi_previewp = LLMultiPreview::getAutoOpenInstance(folder_id); - if (!multi_previewp && all_one_folder && count > 1) - { - S32 left, top; - gFloaterView->getNewFloaterPosition(&left, &top); - - multi_previewp = new LLMultiPreview(LLRect(left, top, left + 300, top - 100)); - LLMultiPreview::setAutoOpenInstance(multi_previewp, folder_id); - } - - LLFloater::setFloaterHost(multi_previewp); - - bool show_keep_discard = lastitem->getPermissions().getCreator() != gAgent.getID(); - switch(lastitem->getType()) - { - case LLAssetType::AT_NOTECARD: - open_notecard( - lastitem->getUUID(), - LLString("Note: ") + lastitem->getName(), - show_keep_discard, - LLUUID::null, - FALSE); - break; - case LLAssetType::AT_LANDMARK: - open_landmark( - lastitem->getUUID(), - LLString(" ") + lastitem->getName(), - show_keep_discard, - LLUUID::null, - FALSE); - break; - case LLAssetType::AT_TEXTURE: - open_texture( - lastitem->getUUID(), - LLString("Texture: ") + lastitem->getName(), - show_keep_discard, - LLUUID::null, - FALSE); - break; - default: - break; - } - - LLFloater::setFloaterHost(NULL); - if (multi_previewp) - { - multi_previewp->open(); - } - - LLInventoryView* view = LLInventoryView::getActiveInventory(); - if(view) - { - LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); - BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view); - BOOL user_is_away = gAwayTimer.getStarted(); - - // don't select lost and found items if an active user is working in the inventory - if (!gInventory.isObjectDescendentOf(lastitem->getUUID(), lost_and_found_id) || - !inventory_has_focus || - user_is_away) - { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback(); - view->getPanel()->setSelection(lastitem->getUUID(), TAKE_FOCUS_NO); - // HACK to open inventory offers that are - // accepted. This information really needs to - // flow through the instant messages and - // inventory restore keyboard focus - gFocusMgr.setKeyboardFocus(focus_ctrl, callback); - } - } - } - } return true; } @@ -3432,6 +3355,43 @@ void LLInventoryExistenceObserver::changed(U32 mask) } } +void LLInventoryAddedObserver::changed(U32 mask) +{ + if(!(mask & LLInventoryObserver::ADD)) + { + return; + } + + // *HACK: If this was in response to a packet off + // the network, figure out which item was updated. + // Code from Gigs Taggert, sin allowed by JC. + LLMessageSystem* msg = gMessageSystem; + const char* msg_name = msg->getMessageName(); + if (!msg_name) return; + + if (!(!strcmp(msg_name, "UpdateCreateInventoryItem") + || !strcmp(msg_name, "FetchInventoryReply"))) + { + return; + } + + LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; + S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); + for(S32 i = 0; i < num_blocks; ++i) + { + titem->unpackMessage(msg, _PREHASH_InventoryData, i); + if (!(titem->getUUID().isNull())) + { + //we don't do anything with null keys + mAdded.push_back(titem->getUUID()); + } + } + if (!mAdded.empty()) + { + done(); + } +} + LLInventoryTransactionObserver::LLInventoryTransactionObserver( const LLTransactionID& transaction_id) : mTransactionID(transaction_id) diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index b8bd559704..514448d1b1 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -9,10 +9,8 @@ #ifndef LL_LLINVENTORYMODEL_H #define LL_LLINVENTORYMODEL_H -#include "llassetstorage.h" +#include "llassettype.h" #include "lldarray.h" -//#include "llskiplist.h" -//#include "llptrskipmap.h" #include "lluuid.h" #include "llpermissionsflags.h" #include "llstring.h" @@ -367,7 +365,7 @@ protected: static void processMoveInventoryItem(LLMessageSystem* msg, void**); static void processFetchInventoryReply(LLMessageSystem* msg, void**); - bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting, bool highlight_new); + bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting); protected: // Varaibles used to track what has changed since the last notify. @@ -731,6 +729,29 @@ protected: }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryAddedObserver +// +// This class is used as a base class for doing something when +// a new item arrives in inventory. +// It does not watch for a certain UUID, rather it acts when anything is added +// Derive a class from this class and implement the done() method to do +// something useful. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryAddedObserver : public LLInventoryObserver +{ +public: + LLInventoryAddedObserver() : mAdded() {} + virtual void changed(U32 mask); + +protected: + virtual void done() = 0; + + typedef std::vector<LLUUID> item_ref_t; + item_ref_t mAdded; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryTransactionObserver // // Class which can be used as a base class for doing something when an diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 383d2846c0..b2fc91f536 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -1502,40 +1502,43 @@ void LLPanelAvatar::resetGroupList() { return; } - LLScrollListCtrl* group_list = LLUICtrlFactory::getScrollListByName(mPanelSecondLife,"groups"); - if (mPanelSecondLife && group_list) + if (mPanelSecondLife) { - group_list->deleteAllItems(); - - S32 count = gAgent.mGroups.count(); - LLUUID id; - - for(S32 i = 0; i < count; ++i) + LLScrollListCtrl* group_list = LLUICtrlFactory::getScrollListByName(mPanelSecondLife,"groups"); + if (group_list) { - LLGroupData group_data = gAgent.mGroups.get(i); - id = group_data.mID; - std::string group_string; - /* Show group title? DUMMY_POWER for Don Grep - if(group_data.mOfficer) - { - group_string = "Officer of "; - } - else + group_list->deleteAllItems(); + + S32 count = gAgent.mGroups.count(); + LLUUID id; + + for(S32 i = 0; i < count; ++i) { - group_string = "Member of "; - } - */ + LLGroupData group_data = gAgent.mGroups.get(i); + id = group_data.mID; + std::string group_string; + /* Show group title? DUMMY_POWER for Don Grep + if(group_data.mOfficer) + { + group_string = "Officer of "; + } + else + { + group_string = "Member of "; + } + */ + + group_string += group_data.mName; - group_string += group_data.mName; - - LLSD row; - row["columns"][0]["value"] = group_string; - row["columns"][0]["font"] = "SANSSERIF_SMALL"; - row["columns"][0]["width"] = 0; - group_list->addElement(row); + LLSD row; + row["columns"][0]["value"] = group_string; + row["columns"][0]["font"] = "SANSSERIF_SMALL"; + row["columns"][0]["width"] = 0; + group_list->addElement(row); + } + group_list->sortByColumn(0, TRUE); } - group_list->sortByColumn(0, TRUE); } } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index cdcaed43f9..158421f7a0 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -485,7 +485,16 @@ void LLPanelFace::getState() { F32 shinyf = 0.f; identical = allFacesSameValue( &LLPanelFace::valueShiny, &shinyf ); - childGetSelectionInterface("combobox shininess")->selectNthItem((S32)shinyf); + LLCtrlSelectionInterface* combobox_shininess = + childGetSelectionInterface("combobox shininess"); + if (combobox_shininess) + { + combobox_shininess->selectNthItem((S32)shinyf); + } + else + { + llwarns << "failed childGetSelectionInterface for 'combobox shininess'" << llendl; + } childSetEnabled("combobox shininess",editable); childSetTentative("combobox shininess",!identical); childSetEnabled("label shininess",editable); @@ -494,7 +503,16 @@ void LLPanelFace::getState() { F32 bumpf = 0.f; identical = allFacesSameValue( &LLPanelFace::valueBump, &bumpf ); - childGetSelectionInterface("combobox bumpiness")->selectNthItem((S32)bumpf); + LLCtrlSelectionInterface* combobox_bumpiness = + childGetSelectionInterface("combobox bumpiness"); + if (combobox_bumpiness) + { + combobox_bumpiness->selectNthItem((S32)bumpf); + } + else + { + llwarns << "failed childGetSelectionInterface for 'combobox bumpiness'" << llendl; + } childSetEnabled("combobox bumpiness",editable); childSetTentative("combobox bumpiness",!identical); childSetEnabled("label bumpiness",editable); @@ -503,8 +521,17 @@ void LLPanelFace::getState() { F32 genf = 0.f; identical = allFacesSameValue( &LLPanelFace::valueTexGen, &genf); - S32 selected_texgen = ((S32) genf) >> TEM_TEX_GEN_SHIFT; - childGetSelectionInterface("combobox texgen")->selectNthItem(selected_texgen); + S32 selected_texgen = ((S32) genf) >> TEM_TEX_GEN_SHIFT; + LLCtrlSelectionInterface* combobox_texgen = + childGetSelectionInterface("combobox texgen"); + if (combobox_texgen) + { + combobox_texgen->selectNthItem(selected_texgen); + } + else + { + llwarns << "failed childGetSelectionInterface for 'combobox texgen'" << llendl; + } childSetEnabled("combobox texgen",editable); childSetTentative("combobox texgen",!identical); childSetEnabled("tex gen",editable); diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 121dc4c67e..4962329619 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -640,7 +640,7 @@ void LLPanelGroup::showNotice(const char* subject, // We need to clean up that inventory offer. if (inventory_offer) { - inventory_offer_callback( 1 , inventory_offer); + inventory_offer_callback( IOR_DECLINE , inventory_offer); } return; } diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 610bfec8ae..161b46a17c 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -25,10 +25,10 @@ #include "llnamebox.h" #include "llnamelistctrl.h" #include "llspinctrl.h" +#include "llstatusbar.h" // can_afford_transaction() #include "lltextbox.h" #include "lltexteditor.h" #include "lltexturectrl.h" -#include "llviewermessage.h" #include "llviewerwindow.h" // static @@ -302,19 +302,27 @@ void LLPanelGroupGeneral::onClickJoin(void *userdata) LLGroupMgrGroupData* gdatap = gGroupMgr->getGroupData(self->mGroupID); - S32 cost = gdatap->mMembershipFee; - LLString::format_map_t args; - args["[COST]"] = llformat("%d", cost); - - if (can_afford_transaction(cost)) + if (gdatap) { - gViewerWindow->alertXml("JoinGroupCanAfford", args, - LLPanelGroupGeneral::joinDlgCB, - self); + S32 cost = gdatap->mMembershipFee; + LLString::format_map_t args; + args["[COST]"] = llformat("%d", cost); + + if (can_afford_transaction(cost)) + { + gViewerWindow->alertXml("JoinGroupCanAfford", args, + LLPanelGroupGeneral::joinDlgCB, + self); + } + else + { + gViewerWindow->alertXml("JoinGroupCannotAfford", args); + } } else { - gViewerWindow->alertXml("JoinGroupCannotAfford", args); + llwarns << "gGroupMgr->getGroupData(" << self->mGroupID + << ") was NULL" << llendl; } } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index b03747c68b..b0fc26f22a 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -184,7 +184,7 @@ LLPanelGroupNotices::~LLPanelGroupNotices() if (mInventoryOffer) { // Cancel the inventory offer. - inventory_offer_callback( 1 , mInventoryOffer); + inventory_offer_callback( IOR_DECLINE , mInventoryOffer); mInventoryOffer = NULL; } } @@ -339,7 +339,7 @@ void LLPanelGroupNotices::onClickOpenAttachment(void* data) { LLPanelGroupNotices* self = (LLPanelGroupNotices*)data; - inventory_offer_callback( 0 , self->mInventoryOffer); + inventory_offer_callback( IOR_ACCEPT , self->mInventoryOffer); self->mInventoryOffer = NULL; self->mBtnOpenAttachment->setEnabled(FALSE); } @@ -378,7 +378,7 @@ void LLPanelGroupNotices::onClickNewMessage(void* data) if (self->mInventoryOffer) { - inventory_offer_callback( 1 , self->mInventoryOffer); + inventory_offer_callback( IOR_DECLINE , self->mInventoryOffer); self->mInventoryOffer = NULL; } @@ -528,7 +528,7 @@ void LLPanelGroupNotices::showNotice(const char* subject, if (mInventoryOffer) { // Cancel the inventory offer for the previously viewed notice - inventory_offer_callback( 1 , mInventoryOffer); + inventory_offer_callback( IOR_DECLINE , mInventoryOffer); mInventoryOffer = NULL; } diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index bda962ca56..30a86a40b2 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1303,13 +1303,17 @@ void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data) LLCheckBoxCtrl* check_box = static_cast<LLCheckBoxCtrl*>(ctrl); if (!check_box || !self) return; - - LLUUID role_id = self->mAssignedRolesList->getFirstSelected()->getUUID(); - LLRoleMemberChangeType change_type = (check_box->get() ? - RMC_ADD : - RMC_REMOVE); - - self->handleRoleCheck(role_id, change_type); + LLScrollListItem* first_selected = + self->mAssignedRolesList->getFirstSelected(); + if (first_selected) + { + LLUUID role_id = first_selected->getUUID(); + LLRoleMemberChangeType change_type = (check_box->get() ? + RMC_ADD : + RMC_REMOVE); + + self->handleRoleCheck(role_id, change_type); + } } void LLPanelGroupMembersSubTab::handleMemberDoubleClick() @@ -2036,8 +2040,9 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc) } if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc) - && gdatap->isMemberDataComplete() - && gdatap->isRoleMemberDataComplete()) + && gdatap + && gdatap->isMemberDataComplete() + && gdatap->isRoleMemberDataComplete()) { buildMembersList(); } diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 9526965334..da7fc16cef 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -706,14 +706,17 @@ void LLPanelPermissions::refresh() LLSaleInfo::EForSale sale_type = sale_info.getSaleType(); LLRadioGroup* RadioSaleType = gUICtrlFactory->getRadioGroupByName(this,"sale type"); - if(RadioSaleType && valid_sale_info) + if(RadioSaleType) { - RadioSaleType->setSelectedIndex((S32)sale_type - 1); - } - else - { - // default option is sell copy, determined to be safest - RadioSaleType->setSelectedIndex((S32)LLSaleInfo::FS_COPY - 1); + if (valid_sale_info) + { + RadioSaleType->setSelectedIndex((S32)sale_type - 1); + } + else + { + // default option is sell copy, determined to be safest + RadioSaleType->setSelectedIndex((S32)LLSaleInfo::FS_COPY - 1); + } } if (is_for_sale) diff --git a/indra/newview/llpatchvertexarray.cpp b/indra/newview/llpatchvertexarray.cpp index 62f8ac87bb..0278ba32f8 100644 --- a/indra/newview/llpatchvertexarray.cpp +++ b/indra/newview/llpatchvertexarray.cpp @@ -106,8 +106,16 @@ void LLPatchVertexArray::create(U32 surface_width, U32 patch_width, F32 meters_p mRenderStridep = new U32 [mPatchOrder + 1]; } + if (NULL == mRenderLevelp || NULL == mRenderStridep) + { + // init() and some other things all want to deref these + // pointers, so this is serious. + llerrs << "mRenderLevelp or mRenderStridep was NULL; we'd crash soon." << llendl; + return; + } - // Now that we've allocated memory, we can initialize the arrays... + // Now that we've allocated memory, we can initialize + // the arrays... init(); } diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index c49fee6d4a..125e1d211f 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -281,6 +281,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read HasWeights flag from " << fileName << llendl; + return FALSE; } if (!isLOD()) { @@ -295,6 +296,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read HasDetailTexCoords flag from " << fileName << llendl; + return FALSE; } //---------------------------------------------------------------- @@ -306,6 +308,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 3) { llerrs << "can't read Position from " << fileName << llendl; + return FALSE; } setPosition( position ); @@ -318,6 +321,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 3) { llerrs << "can't read RotationAngles from " << fileName << llendl; + return FALSE; } U8 rotationOrder; @@ -326,6 +330,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read RotationOrder from " << fileName << llendl; + return FALSE; } rotationOrder = 0; @@ -344,6 +349,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 3) { llerrs << "can't read Scale from " << fileName << llendl; + return FALSE; } setScale( scale ); @@ -364,6 +370,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read NumVertices from " << fileName << llendl; + return FALSE; } allocateVertexData( numVertices ); @@ -376,6 +383,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << "can't read Coordinates from " << fileName << llendl; + return FALSE; } //---------------------------------------------------------------- @@ -386,6 +394,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << " can't read Normals from " << fileName << llendl; + return FALSE; } //---------------------------------------------------------------- @@ -396,6 +405,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << " can't read Binormals from " << fileName << llendl; + return FALSE; } @@ -407,6 +417,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << "can't read TexCoords from " << fileName << llendl; + return FALSE; } //---------------------------------------------------------------- @@ -419,6 +430,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << "can't read DetailTexCoords from " << fileName << llendl; + return FALSE; } } @@ -432,6 +444,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != numVertices) { llerrs << "can't read Weights from " << fileName << llendl; + return FALSE; } } } @@ -445,6 +458,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read NumFaces from " << fileName << llendl; + return FALSE; } allocateFaceData( numFaces ); @@ -462,6 +476,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 3) { llerrs << "can't read Face[" << i << "] from " << fileName << llendl; + return FALSE; } if (mReferenceData) { @@ -518,6 +533,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) if (numRead != 1) { llerrs << "can't read NumSkinJoints from " << fileName << llendl; + return FALSE; } allocateJointNames( numSkinJoints ); } @@ -527,11 +543,13 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) //---------------------------------------------------------------- for (i=0; i < numSkinJoints; i++) { - char jointName[64]; /*Flawfinder: ignore*/ - numRead = fread(jointName, sizeof(jointName), 1, fp); + char jointName[64+1]; + numRead = fread(jointName, sizeof(jointName)-1, 1, fp); + jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination if (numRead != 1) { llerrs << "can't read Skin[" << i << "].Name from " << fileName << llendl; + return FALSE; } std::string *jn = &mJointNames[i]; @@ -541,7 +559,8 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) //------------------------------------------------------------------------- // look for morph section //------------------------------------------------------------------------- - char morphName[64]; /*Flawfinder: ignore*/ + char morphName[64+1]; + morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination while(fread(&morphName, sizeof(char), 64, fp) == 64) { if (!strcmp(morphName, "End Morphs")) @@ -971,6 +990,13 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton"); + if (NULL == skeletalParam) + { + llwarns << "Failed to getChildByName(\"param_skeleton\")" + << llendl; + return FALSE; + } + for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() ) { if (bone->hasName("bone")) diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index 9cbe6522cb..f531624830 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -194,6 +194,13 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) LLXmlTreeNode *paramNode = node->getChildByName("param_morph"); + if (NULL == paramNode) + { + llwarns << "Failed to getChildByName(\"param_morph\")" + << llendl; + return FALSE; + } + for (LLXmlTreeNode* child_node = paramNode->getFirstChild(); child_node; child_node = paramNode->getNextChild()) @@ -236,7 +243,10 @@ LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh) //----------------------------------------------------------------------------- LLPolyMorphTarget::~LLPolyMorphTarget() { - delete mVertMask; + if (mVertMask) + { + delete mVertMask; + } } //----------------------------------------------------------------------------- diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index 52ce263e59..39cc290b0f 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -40,6 +40,7 @@ LLPreview::LLPreview(const std::string& name) : LLFloater(name), mCopyToInvBtn(NULL), mForceClose(FALSE), + mUserResized(FALSE), mCloseAfterSave(FALSE), mAssetStatus(PREVIEW_ASSET_UNLOADED) { @@ -56,6 +57,7 @@ LLPreview::LLPreview(const std::string& name, const LLRect& rect, const std::str mObjectUUID(object_uuid), mCopyToInvBtn( NULL ), mForceClose( FALSE ), + mUserResized(FALSE), mCloseAfterSave(FALSE), mAssetStatus(PREVIEW_ASSET_UNLOADED) { @@ -169,8 +171,6 @@ void LLPreview::onCommit() } LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - BOOL has_sale_info = FALSE; - LLSaleInfo sale_info; new_item->setDescription(childGetText("desc")); if(mObjectUUID.notNull()) { @@ -202,11 +202,6 @@ void LLPreview::onCommit() gSelectMgr->deselectAll(); gSelectMgr->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); gSelectMgr->selectionSetObjectDescription( childGetText("desc") ); - - if( has_sale_info ) - { - gSelectMgr->selectionSetObjectSaleInfo( sale_info ); - } gSelectMgr->deselectAll(); } @@ -467,6 +462,12 @@ LLPreview* LLPreview::getFirstPreviewForSource(const LLUUID& source_id) return NULL; } +void LLPreview::userSetShape(const LLRect& new_rect) +{ + userResized(); + LLView::userSetShape(new_rect); +} + // // LLMultiPreview // @@ -486,6 +487,15 @@ void LLMultiPreview::open() /*Flawfinder: ignore*/ } } + +void LLMultiPreview::userSetShape(const LLRect& new_rect) +{ + LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel(); + if (frontmost_preview) frontmost_preview->userResized(); + LLView::userSetShape(new_rect); +} + + void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click) { LLPreview* opened_preview = (LLPreview*)opened_floater; diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index ac3f4da996..5c7d6f30d0 100644 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -28,6 +28,7 @@ public: /*virtual*/void open(); /*Flawfinder: ignore*/ /*virtual*/void tabOpen(LLFloater* opened_floater, bool from_click); + /*virtual*/ void userSetShape(const LLRect& new_rect); static LLMultiPreview* getAutoOpenInstance(const LLUUID& id); static void setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id); @@ -81,6 +82,9 @@ public: void addKeepDiscardButtons(); static void onKeepBtn(void* data); static void onDiscardBtn(void* data); + /*virtual*/ void userSetShape(const LLRect& new_rect); + + void userResized() { mUserResized = TRUE; }; virtual void loadAsset() { mAssetStatus = PREVIEW_ASSET_LOADED; } virtual EAssetStatus getAssetStatus() { return mAssetStatus;} @@ -115,6 +119,8 @@ protected: // Close without saving changes BOOL mForceClose; + BOOL mUserResized; + // When closing springs a "Want to save?" dialog, we want // to keep the preview open until the save completes. BOOL mCloseAfterSave; diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 39e32c31f5..9710fc8bf2 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -1570,6 +1570,11 @@ LLScrollListItem* LLPreviewGesture::addStep(const std::string& library_text) { step = new LLGestureStepWait(); } + else + { + llerrs << "Unknown step type: " << library_text << llendl;; + return NULL; + } // Create an enabled item with this step LLSD row; @@ -1625,7 +1630,7 @@ void LLPreviewGesture::onClickDelete(void* data) LLScrollListItem* item = self->mStepList->getFirstSelected(); S32 selected_index = self->mStepList->getFirstSelectedIndex(); - if (selected_index >= 0) + if (item && selected_index >= 0) { LLGestureStep* step = (LLGestureStep*)item->getUserdata(); delete step; diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index a44a89dc19..1cba69b566 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -276,11 +276,12 @@ void LLPreviewNotecard::loadAsset() { // The object that we're trying to look at disappeared, bail. llwarns << "Can't find object " << mObjectUUID << " associated with notecard." << llendl; - mAssetID.setNull(); - editor->setText("Unable to find object containing this note."); - editor->makePristine(); - editor->setEnabled(FALSE); - mAssetStatus = PREVIEW_ASSET_LOADED; + mAssetID.setNull(); + editor->setText("Unable to find object containing this note."); + editor->makePristine(); + editor->setEnabled(FALSE); + mAssetStatus = PREVIEW_ASSET_LOADED; + delete new_uuid; return; } } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 6a9965dbfb..4cf103508d 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -450,12 +450,14 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) LLFloater* help_floater = LLFloater::getFloaterByHandle(mLiveHelpHandle); if (!help_floater) return; +#if LL_LIBXUL_ENABLED // update back and forward buttons LLButton* fwd_button = LLUICtrlFactory::getButtonByName(help_floater, "fwd_btn"); LLButton* back_button = LLUICtrlFactory::getButtonByName(help_floater, "back_btn"); LLWebBrowserCtrl* browser = LLUICtrlFactory::getWebBrowserCtrlByName(help_floater, "lsl_guide_html"); back_button->setEnabled(browser->canNavigateBack()); fwd_button->setEnabled(browser->canNavigateForward()); +#endif // LL_LIBXUL_ENABLED if (!immediate && !gSavedSettings.getBOOL("ScriptHelpFollowsCursor")) { @@ -523,7 +525,9 @@ void LLScriptEdCore::setHelpPage(const LLString& help_string) url_string.setArg("[LSL_STRING]", help_string); addHelpItemToHistory(help_string); +#if LL_LIBXUL_ENABLED web_browser->navigateTo(url_string); +#endif // LL_LIBXUL_ENABLED } void LLScriptEdCore::addHelpItemToHistory(const LLString& help_string) @@ -655,8 +659,10 @@ void LLScriptEdCore::onBtnDynamicHelp(void* userdata) live_help_floater->childSetAction("back_btn", onClickBack, userdata); live_help_floater->childSetAction("fwd_btn", onClickForward, userdata); +#if LL_LIBXUL_ENABLED LLWebBrowserCtrl* browser = LLUICtrlFactory::getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html"); browser->setAlwaysRefresh(TRUE); +#endif // LL_LIBXUL_ENABLED LLComboBox* help_combo = LLUICtrlFactory::getComboBoxByName(live_help_floater, "history_combo"); LLKeywordToken *token; @@ -680,6 +686,7 @@ void LLScriptEdCore::onBtnDynamicHelp(void* userdata) //static void LLScriptEdCore::onClickBack(void* userdata) { +#if LL_LIBXUL_ENABLED LLScriptEdCore* corep = (LLScriptEdCore*)userdata; LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle); if (live_help_floater) @@ -690,11 +697,13 @@ void LLScriptEdCore::onClickBack(void* userdata) browserp->navigateBack(); } } +#endif // LL_LIBXUL_ENABLED } //static void LLScriptEdCore::onClickForward(void* userdata) { +#if LL_LIBXUL_ENABLED LLScriptEdCore* corep = (LLScriptEdCore*)userdata; LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle); if (live_help_floater) @@ -705,6 +714,7 @@ void LLScriptEdCore::onClickForward(void* userdata) browserp->navigateForward(); } } +#endif // LL_LIBXUL_ENABLED } // static @@ -737,16 +747,17 @@ void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata) LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle); if (live_help_floater) { - LLWebBrowserCtrl* web_browser = gUICtrlFactory->getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html"); - LLString help_string = ctrl->getValue().asString(); corep->addHelpItemToHistory(help_string); +#if LL_LIBXUL_ENABLED + LLWebBrowserCtrl* web_browser = gUICtrlFactory->getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html"); LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); url_string.setArg("[APP_DIRECTORY]", gDirUtilp->getWorkingDir()); url_string.setArg("[LSL_STRING]", help_string); web_browser->navigateTo(url_string); +#endif // LL_LIBXUL_ENABLED } } @@ -1316,10 +1327,6 @@ void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, { break; } - else if(!buffer) - { - continue; - } else { line.assign(buffer); @@ -1689,7 +1696,7 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) mScriptEd->mEditor->setEnabled(FALSE); mAssetStatus = PREVIEW_ASSET_LOADED; } - else if(mItem.notNull()) + else if(item && mItem.notNull()) { // request the text from the object LLUUID* user_data = new LLUUID(mItemID ^ mObjectID); @@ -1815,6 +1822,7 @@ void LLLiveLSLEditor::loadScriptText(const char* filename) if(!filename) { llerrs << "Filename is Empty!" << llendl; + return; } FILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ if(file) @@ -2095,10 +2103,6 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, { break; } - else if(!buffer) - { - continue; - } else { line.assign(buffer); diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index b8f1e51e9e..214b3e38f8 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -368,29 +368,23 @@ void LLPreviewTexture::updateAspectRatio() // If that fails, cut width by half. S32 client_width = image_width; S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE; + S32 vert_pad = PREVIEW_HEADER_SIZE + 2 * CLIENT_RECT_VPAD + LLPANEL_BORDER_WIDTH; S32 screen_width = gViewerWindow->getWindowWidth(); S32 max_client_width = screen_width - horiz_pad; + S32 max_client_height = gViewerWindow->getWindowHeight() - vert_pad; + F32 inv_aspect_ratio = (F32) image_height / (F32) image_width; - while (client_width > max_client_width) + while ((client_width > max_client_width) || ( llround(client_width * inv_aspect_ratio) > max_client_height ) ) { client_width /= 2; } - // Demand width at least 128 - if (client_width < 128) - { - client_width = 128; - } - S32 view_width = client_width + horiz_pad; // Adjust the height based on the width computed above. - F32 inv_aspect_ratio = (F32) image_height / (F32) image_width; S32 client_height = llround(client_width * inv_aspect_ratio); - S32 view_height = - PREVIEW_HEADER_SIZE + // header (includes top border) - client_height + 2 * CLIENT_RECT_VPAD + // texture plus uniform spacing (which leaves room for resize handle) - LLPANEL_BORDER_WIDTH; // bottom border + S32 view_height = client_height + vert_pad; + // set text on dimensions display (should be moved out of here and into a callback of some sort) childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->mFullWidth)); @@ -433,28 +427,43 @@ void LLPreviewTexture::updateAspectRatio() } } - // clamp texture size to fit within actual size of floater after attempting resize - client_width = llmin(client_width, mRect.getWidth() - horiz_pad); - client_height = llmin(client_height, mRect.getHeight() - PREVIEW_HEADER_SIZE - (2 * CLIENT_RECT_VPAD) - LLPANEL_BORDER_WIDTH - info_height); - - LLRect window_rect(0, mRect.getHeight(), mRect.getWidth(), 0); - window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); - window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD; - - if (getHost()) + + if (!mUserResized) { - // try to keep aspect ratio when hosted, as hosting view can resize without user input - mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height); + // clamp texture size to fit within actual size of floater after attempting resize + client_width = llmin(client_width, mRect.getWidth() - horiz_pad); + client_height = llmin(client_height, mRect.getHeight() - PREVIEW_HEADER_SIZE + - (2 * CLIENT_RECT_VPAD) - LLPANEL_BORDER_WIDTH - info_height); + + } else { - mClientRect.setLeftTopAndSize(LLPANEL_BORDER_WIDTH + PREVIEW_PAD + 6, - mRect.getHeight() - (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD), - mRect.getWidth() - horiz_pad, - client_height); + client_width = mRect.getWidth() - horiz_pad; + client_height = llround(client_width * inv_aspect_ratio); + } + + + S32 max_height = mRect.getHeight() - PREVIEW_BORDER - button_height + - CLIENT_RECT_VPAD - info_height - CLIENT_RECT_VPAD - PREVIEW_HEADER_SIZE; + max_height = llmax(max_height, 1); + + if (client_height > max_height) + { + F32 aspect_ratio = (F32) image_width / (F32) image_height; + client_height = max_height; + client_width = llround(client_height * aspect_ratio); } + + LLRect window_rect(0, mRect.getHeight(), mRect.getWidth(), 0); + window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); + window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD; + + // try to keep aspect ratio when hosted, as hosting view can resize without user input + mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height); } + void LLPreviewTexture::loadAsset() { mImage = gImageList.getImage(mImageID, MIPMAP_TRUE, FALSE); diff --git a/indra/newview/llresourcedata.h b/indra/newview/llresourcedata.h new file mode 100644 index 0000000000..20a8df4c22 --- /dev/null +++ b/indra/newview/llresourcedata.h @@ -0,0 +1,24 @@ +/** + * @file llresourcedata.h + * @brief Tracking object for uploads. + * + * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LLRESOURCEDATA_H +#define LLRESOURCEDATA_H + +#include "llassetstorage.h" +#include "llinventorytype.h" + +struct LLResourceData +{ + LLAssetInfo mAssetInfo; + LLAssetType::EType mPreferredLocation; + LLInventoryType::EType mInventoryType; + U32 mNextOwnerPerm; + void *mUserData; +}; + +#endif diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index a02dd912e3..98f842902d 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -71,7 +71,6 @@ const S32 MAX_ACTION_QUEUE_SIZE = 20; const S32 MAX_SILS_PER_FRAME = 50; const S32 MAX_OBJECTS_PER_PACKET = 254; -extern LLGlobalEconomy *gGlobalEconomy; extern LLUUID gLastHitObjectID; extern LLVector3d gLastHitObjectOffset; @@ -188,6 +187,20 @@ LLSelectMgr::~LLSelectMgr() void LLSelectMgr::updateEffects() { + + //keep reference grid objects active + for (LLSelectNode* grid_nodep = mGridObjects.getFirstNode(); + grid_nodep; + grid_nodep = mGridObjects.getNextNode()) + { + LLViewerObject* grid_object = grid_nodep->getObject(); + LLDrawable* drawable = grid_object->mDrawable; + if (drawable) + { + gPipeline.markMoved(drawable); + } + } + if (mEffectsTimer.getElapsedTimeF32() > 1.f) { mSelectedObjects->updateEffects(); @@ -973,7 +986,7 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & LLVector3 first_grid_obj_pos = grid_object->getRenderPosition(); LLVector3 min_extents(F32_MAX, F32_MAX, F32_MAX); - LLVector3 max_extents(F32_MIN, F32_MIN, F32_MIN); + LLVector3 max_extents(-min_extents); BOOL grid_changed = FALSE; LLSelectNode* grid_nodep; for (grid_nodep = mGridObjects.getFirstNode(); @@ -981,34 +994,23 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & grid_nodep = mGridObjects.getNextNode()) { grid_object = grid_nodep->getObject(); - - LLVector3 local_min_extents(F32_MAX, F32_MAX, F32_MAX); - LLVector3 local_max_extents(F32_MIN, F32_MIN, F32_MIN); - - // *FIX: silhouette flag is insufficient as it gets - // cleared by view update. - if (!mGridValid || - grid_object->isChanged(LLXform::SILHOUETTE) - || (grid_object->getParent() && grid_object->getParent()->isChanged(LLXform::SILHOUETTE))) + LLDrawable* drawable = grid_object->mDrawable; + if (drawable) { - getSilhouetteExtents(grid_nodep, mGridRotation, local_min_extents, local_max_extents); + const LLVector3* ext = drawable->getSpatialExtents(); + update_min_max(min_extents, max_extents, ext[0]); + update_min_max(min_extents, max_extents, ext[1]); grid_changed = TRUE; - LLVector3 object_offset = (grid_object->getRenderPosition() - first_grid_obj_pos) * ~mGridRotation; - local_min_extents += object_offset; - local_max_extents += object_offset; } - min_extents.mV[VX] = llmin(min_extents.mV[VX], local_min_extents.mV[VX]); - min_extents.mV[VY] = llmin(min_extents.mV[VY], local_min_extents.mV[VY]); - min_extents.mV[VZ] = llmin(min_extents.mV[VZ], local_min_extents.mV[VZ]); - max_extents.mV[VX] = llmax(max_extents.mV[VX], local_max_extents.mV[VX]); - max_extents.mV[VY] = llmax(max_extents.mV[VY], local_max_extents.mV[VY]); - max_extents.mV[VZ] = llmax(max_extents.mV[VZ], local_max_extents.mV[VZ]); } if (grid_changed) { mGridOrigin = lerp(min_extents, max_extents, 0.5f); - mGridOrigin = mGridOrigin * ~mGridRotation; - mGridOrigin += first_grid_obj_pos; + LLDrawable* drawable = grid_object->mDrawable; + if (drawable && drawable->isActive()) + { + mGridOrigin = mGridOrigin * grid_object->getRenderMatrix(); + } mGridScale = (max_extents - min_extents) * 0.5f; } } @@ -4919,66 +4921,6 @@ void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_ } } -void LLSelectMgr::getSilhouetteExtents(LLSelectNode* nodep, const LLQuaternion& orientation, LLVector3& min_extents, LLVector3& max_extents) -{ - LLViewerObject* objectp = nodep->getObject(); - - if (objectp->mDrawable.isNull()) - { - return; - } - - LLQuaternion test_rot = orientation * ~objectp->getRenderRotation(); - LLVector3 x_axis_rot = LLVector3::x_axis * test_rot; - LLVector3 y_axis_rot = LLVector3::y_axis * test_rot; - LLVector3 z_axis_rot = LLVector3::z_axis * test_rot; - - x_axis_rot.scaleVec(objectp->mDrawable->getScale()); - y_axis_rot.scaleVec(objectp->mDrawable->getScale()); - z_axis_rot.scaleVec(objectp->mDrawable->getScale()); - - generateSilhouette(nodep, objectp->mDrawable->getPositionAgent() + x_axis_rot * 100.f); - - S32 num_vertices = nodep->mSilhouetteVertices.size(); - if (num_vertices) - { - min_extents.mV[VY] = llmin(min_extents.mV[VY], nodep->mSilhouetteVertices[0] * y_axis_rot); - max_extents.mV[VY] = llmax(max_extents.mV[VY], nodep->mSilhouetteVertices[0] * y_axis_rot); - - min_extents.mV[VZ] = llmin(min_extents.mV[VZ], nodep->mSilhouetteVertices[0] * z_axis_rot); - max_extents.mV[VZ] = llmax(min_extents.mV[VZ], nodep->mSilhouetteVertices[0] * z_axis_rot); - - for (S32 vert = 1; vert < num_vertices; vert++) - { - F32 y_pos = nodep->mSilhouetteVertices[vert] * y_axis_rot; - F32 z_pos = nodep->mSilhouetteVertices[vert] * z_axis_rot; - min_extents.mV[VY] = llmin(y_pos, min_extents.mV[VY]); - max_extents.mV[VY] = llmax(y_pos, max_extents.mV[VY]); - min_extents.mV[VZ] = llmin(z_pos, min_extents.mV[VZ]); - max_extents.mV[VZ] = llmax(z_pos, max_extents.mV[VZ]); - } - } - - generateSilhouette(nodep, objectp->mDrawable->getPositionAgent() + y_axis_rot * 100.f); - - num_vertices = nodep->mSilhouetteVertices.size(); - if (num_vertices) - { - min_extents.mV[VX] = llmin(min_extents.mV[VX], nodep->mSilhouetteVertices[0] * x_axis_rot); - max_extents.mV[VX] = llmax(max_extents.mV[VX], nodep->mSilhouetteVertices[0] * x_axis_rot); - - for (S32 vert = 1; vert < num_vertices; vert++) - { - F32 x_pos = nodep->mSilhouetteVertices[vert] * x_axis_rot; - min_extents.mV[VX] = llmin(x_pos, min_extents.mV[VX]); - max_extents.mV[VX] = llmax(x_pos, max_extents.mV[VX]); - } - } - - generateSilhouette(nodep, gCamera->getOrigin()); -} - - // // Utility classes // @@ -6459,6 +6401,8 @@ LLViewerObject* LLObjectSelection::getFirstDeleteableObject(BOOL get_root) } else { + // We've avoided this path for a while. It may not work. + llwarns << "!get_root code path may have bitrotted." << llendl; for(LLViewerObject* current = getFirstObject(); current != NULL; current = getNextObject()) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 04d55dcf7d..0b4392f318 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -472,7 +472,6 @@ private: ESelectType getSelectTypeForObject(LLViewerObject* object); void addAsFamily(LLDynamicArray<LLViewerObject*>& objects, BOOL add_to_end = FALSE); void generateSilhouette(LLSelectNode *nodep, const LLVector3& view_point); - void getSilhouetteExtents(LLSelectNode* nodep, const LLQuaternion& orientation, LLVector3& min_extents, LLVector3& max_extents); // Send one message to each region containing an object on selection list. void sendListToRegions( const LLString& message_name, void (*pack_header)(void *user_data), diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 333ed91e4a..315a8e2828 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1160,6 +1160,13 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE); + + // sanity check submitted by open source user bushing Spatula + // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne) + if (!drawablep) { + OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << llendl; + return; + } BOOL was_visible = curp ? curp->isVisible() : FALSE; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4bbdca521c..44b4d77c1e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -183,6 +183,7 @@ LLPointer<LLImageGL> gStartImageGL; static LLHost gAgentSimHost; static BOOL gSkipOptionalUpdate = FALSE; +bool gUseQuickTime = true; bool gQuickTimeInitialized = false; static bool gGotUseCircuitCodeAck = false; LLString gInitialOutfit; @@ -1847,7 +1848,8 @@ BOOL idle_startup() } #if LL_QUICKTIME_ENABLED // windows only right now but will be ported to mac - if (!gQuickTimeInitialized) + if (gUseQuickTime + && !gQuickTimeInitialized) { // initialize quicktime libraries (fails gracefully if quicktime not installed ($QUICKTIME) llinfos << "Initializing QuickTime...." << llendl; diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 7d64640fb0..75a525f241 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -62,6 +62,7 @@ enum EStartupState{ // exorted symbol extern S32 gStartupState; extern BOOL gAgentMovementCompleted; +extern bool gUseQuickTime; extern bool gQuickTimeInitialized; extern LLPointer<LLImageGL> gStartImageGL; diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 59fd8e0a3a..6990102d24 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -686,3 +686,8 @@ void LLStatusBar::onClickBuyLand(void*) gParcelMgr->selectParcelAt(gAgent.getPositionGlobal()); gParcelMgr->startBuyLand(); } + +BOOL can_afford_transaction(S32 cost) +{ + return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost))); +} diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 7e9f05cf1e..f33a5d93e1 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -123,6 +123,9 @@ protected: LLFrameTimer* mHealthTimer; }; +// *HACK: Status bar owns your cached money balance. JC +BOOL can_afford_transaction(S32 cost); + extern LLStatusBar *gStatusBar; #endif diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index fcabdc8450..178c83f61e 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -257,7 +257,7 @@ BOOL LLTexLayerSetBuffer::render() { if (!success) { - delete baked_bump_data; + delete [] baked_bump_data; llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegion() << llendl; mUploadPending = FALSE; } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index bc5efa20aa..958635c796 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -390,32 +390,35 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask, BOOL called_from_ { LLFolderView* root_folder = mInventoryPanel->getRootFolder(); - if (!called_from_parent && root_folder && - mSearchEdit && mSearchEdit->hasFocus() && - (key == KEY_RETURN || key == KEY_DOWN) && mask == MASK_NONE) + if (root_folder && mSearchEdit) { - if (!root_folder->getCurSelectedItem()) + if (!called_from_parent && mSearchEdit->hasFocus() && + (key == KEY_RETURN || key == KEY_DOWN) && + mask == MASK_NONE) { - LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID()); - if (itemp) + if (!root_folder->getCurSelectedItem()) { - root_folder->setSelection(itemp, FALSE, FALSE); + LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID()); + if (itemp) + { + root_folder->setSelection(itemp, FALSE, FALSE); + } } + root_folder->scrollToShowSelection(); + + // move focus to inventory proper + root_folder->setFocus(TRUE); + + // treat this as a user selection of the first filtered result + commitIfImmediateSet(); + + return TRUE; } - root_folder->scrollToShowSelection(); - - // move focus to inventory proper - root_folder->setFocus(TRUE); - // treat this as a user selection of the first filtered result - commitIfImmediateSet(); - - return TRUE; - } - - if (root_folder->hasFocus() && key == KEY_UP) - { - mSearchEdit->focusFirstItem(TRUE); + if (root_folder->hasFocus() && key == KEY_UP) + { + mSearchEdit->focusFirstItem(TRUE); + } } return LLFloater::handleKeyHere(key, mask, called_from_parent); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 64ec8f0b2f..930d6fa5f2 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -2555,7 +2555,13 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( LLViewerObject* obj, S32 face, MASK mask, BOOL drop) { lldebugs << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << llendl; - if(mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY) + if (NULL==obj) + { + llwarns << "obj is NULL; aborting func with ACCEPT_NO" << llendl; + return ACCEPT_NO; + } + + if (mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY) { return ACCEPT_NO; } @@ -2571,17 +2577,17 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; gInventory.collectDescendentsIf(cat->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - droppable); + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + droppable); cats.put(cat); if(droppable.countNoCopy() > 0) { llwarns << "*** Need to confirm this step" << llendl; } LLViewerObject* root_object = obj; - if (obj && obj->getParent()) + if (obj->getParent()) { LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent(); if (!parent_obj->isAvatar()) diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index 549719250c..3250e42232 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -160,6 +160,12 @@ BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mas llinfos << "LLToolGrab handleObjectHit " << mMouseDownX << "," << mMouseDownY << llendl; } + if (NULL == objectp) // unexpected + { + llwarns << "objectp was NULL; returning FALSE" << llendl; + return FALSE; + } + if (objectp->isAvatar()) { if (gGrabTransientTool) @@ -178,7 +184,7 @@ BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mas // objectp = (LLViewerObject *)objectp->getRoot(); LLViewerObject* parent = objectp->getRootEdit(); - BOOL script_touch = (objectp && objectp->flagHandleTouch()) || (parent && parent->flagHandleTouch()); + BOOL script_touch = (objectp->flagHandleTouch()) || (parent && parent->flagHandleTouch()); // Clicks on scripted or physical objects are temporary grabs, so // not "Build mode" diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index f9511f72a5..68eec329aa 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -370,11 +370,11 @@ U8 final_click_action(LLViewerObject* obj) if (obj->isAttachment()) return CLICK_ACTION_NONE; U8 click_action = CLICK_ACTION_TOUCH; - LLViewerObject* parent = (obj ? obj->getRootEdit() : NULL); - if ((obj && obj->getClickAction()) - || (parent && parent->getClickAction())) + LLViewerObject* parent = obj->getRootEdit(); + if (obj->getClickAction() + || (parent && parent->getClickAction())) { - if (obj && obj->getClickAction()) + if (obj->getClickAction()) { click_action = obj->getClickAction(); } diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 88ffd016cf..e0a6786cb8 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -146,21 +146,22 @@ void LLViewerAssetStorage::storeAssetData( if(!filename) { llerrs << "No filename specified" << llendl; + return; } LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); llinfos << "LLViewerAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << llendl; - LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest; - llinfos << "ASSET_ID: " << asset_id << llendl; - legacy->mUpCallback = callback; - legacy->mUserData = user_data; - - FILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ + FILE* fp = LLFile::fopen(filename, "rb"); if (fp) { + LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest; + + legacy->mUpCallback = callback; + legacy->mUserData = user_data; + LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE); fseek(fp, 0, SEEK_END); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 225d599838..3dedaa3182 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -220,6 +220,14 @@ void LLFloaterSettingsDebug::updateControl(LLControlBase* controlp) LLSpinCtrl* spinner3 = LLUICtrlFactory::getSpinnerByName(this, "val_spinner_3"); LLSpinCtrl* spinner4 = LLUICtrlFactory::getSpinnerByName(this, "val_spinner_4"); LLColorSwatchCtrl* color_swatch = LLUICtrlFactory::getColorSwatchByName(this, "color_swatch"); + + if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch) + { + llwarns << "Could not find all desired controls by name" + << llendl; + return; + } + spinner1->setVisible(FALSE); spinner2->setVisible(FALSE); spinner3->setVisible(FALSE); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index cbb37e5fe4..fa2a12b34a 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -544,6 +544,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); + if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices(FALSE)) { LLCamera hud_cam = *gCamera; @@ -578,7 +579,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) LLFastTimer ftm(LLFastTimer::FTM_REBUILD); gPipeline.stateSort(hud_cam); } - + gPipeline.renderGeom(hud_cam); //restore type mask @@ -637,6 +638,7 @@ BOOL setup_hud_matrices(BOOL for_select) } LLBBox hud_bbox = my_avatarp->getHUDBBox(); + // set up transform to encompass bounding box of HUD glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -665,7 +667,7 @@ BOOL setup_hud_matrices(BOOL for_select) glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f); glScalef(zoom_level, zoom_level, zoom_level); - + return TRUE; } else diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 240100be61..d1a0b3724d 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -442,10 +442,6 @@ bool LLViewerInventoryCategory::importFileLocal(FILE* fp) fgets(buffer, MAX_STRING, fp); sscanf( /* Flawfinder: ignore */ buffer, " %254s %254s", keyword, valuestr); - if(!keyword) - { - continue; - } if(0 == strcmp("{",keyword)) { continue; diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 9bb4aa4cf9..150943465d 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -196,11 +196,11 @@ S32 LLViewerJointMesh::getBoundJointsByIndex(S32 index, S32 &joint_a, S32& joint if (render_datap->mSkinJoint) { joint_b = render_datap->mSkinJoint->mJoint->mJointNum; - } - if (joint_a == -1) - { - joint_a = render_datap->mSkinJoint->mJoint->getParent()->mJointNum; + if (joint_a == -1) + { + joint_a = render_datap->mSkinJoint->mJoint->getParent()->mJointNum; + } } num_joints++; } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index d970d1d086..17c9a1fc10 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -697,15 +697,16 @@ S32 LLViewerKeyboard::loadBindings(const char *filename) S32 binding_count = 0; S32 line_count = 0; - fp = LLFile::fopen(filename, "r"); /* Flawfinder: ignore */ + if(!filename) + { + llerrs << " No filename specified" << llendl; + return 0; + } + + fp = LLFile::fopen(filename, "r"); if (!fp) { - if(!filename) - { - llerrs << " No filename specified" << llendl; - return 0; - } return 0; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 2ac1c30ae5..5a6ff851c4 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -14,15 +14,12 @@ #include <iostream> #include <fstream> #include <sstream> -#include <boost/tokenizer.hpp> // linden library includes #include "audioengine.h" #include "indra_constants.h" -#include "llassetuploadresponders.h" #include "llassetstorage.h" #include "llchat.h" -#include "lleconomy.h" #include "llfocusmgr.h" #include "llfontgl.h" #include "llinstantmessage.h" @@ -37,7 +34,6 @@ #include "raytrace.h" #include "llsdserialize.h" #include "lltimer.h" -#include "vorbisencode.h" #include "llvfile.h" #include "llvolumemgr.h" #include "llwindow.h" // for shell_open() @@ -63,7 +59,6 @@ #include "llfloater.h" #include "llfloaterabout.h" #include "llfloaterbuycurrency.h" -#include "llfloateranimpreview.h" #include "llfloateravatarinfo.h" #include "llfloateravatartextures.h" #include "llfloaterbuildoptions.h" @@ -84,21 +79,17 @@ #include "llfloaterhtml.h" #include "llfloaterhtmlhelp.h" #include "llfloaterhtmlfind.h" -#include "llfloaterimport.h" #include "llfloaterinspect.h" #include "llfloaterland.h" #include "llfloaterlandholdings.h" #include "llfloatermap.h" -#include "llfloaterimagepreview.h" #include "llfloatermute.h" -#include "llfloaternamedesc.h" #include "llfloateropenobject.h" #include "llfloaterpermissionsmgr.h" #include "llfloaterpreference.h" #include "llfloaterregioninfo.h" #include "llfloaterreporter.h" #include "llfloaterscriptdebug.h" -#include "llfloatersnapshot.h" #include "llfloatertest.h" #include "llfloatertools.h" #include "llfloaterworldmap.h" @@ -127,8 +118,6 @@ #include "llnotify.h" #include "llpanelobject.h" #include "llparcel.h" -#include "llpreviewscript.h" -#include "llpreviewtexture.h" #include "llprimitive.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -156,8 +145,8 @@ #include "llviewercamera.h" #include "llviewergenericmessage.h" #include "llviewergesture.h" -#include "llviewerimagelist.h" #include "llviewerinventory.h" +#include "llviewermenufile.h" // init_menu_file() #include "llviewermessage.h" #include "llviewernetwork.h" #include "llviewerobjectlist.h" @@ -382,7 +371,6 @@ void handle_god_request_avatar_geometry(void *); // Hack for easy testing of new void reload_personal_settings_overrides(void *); void force_breakpoint(void *); void reload_vertex_shader(void *); -void flush_animations(void *); void slow_mo_animations(void *); void handle_disconnect_viewer(void *); @@ -447,6 +435,7 @@ void handle_dump_avatar_local_textures(void*); void handle_debug_avatar_textures(void*); void handle_grab_texture(void*); BOOL enable_grab_texture(void*); +void handle_dump_region_object_cache(void*); BOOL menu_ui_enabled(void *user_data); void check_toggle_control( LLUICtrl *, void* user_data ); @@ -517,7 +506,7 @@ void pre_init_menus() LLMenuItemGL::setHighlightFGColor( color ); } -void initialize_menu_actions(); +void initialize_menus(); //----------------------------------------------------------------------------- // Initialize main menus @@ -545,7 +534,7 @@ void init_menus() LLMenuGL::sMenuContainer = gMenuHolder; // Initialize actions - initialize_menu_actions(); + initialize_menus(); /// /// Popup menu @@ -945,6 +934,8 @@ void init_debug_world_menu(LLMenuGL* menu) NULL, &menu_check_control, (void*)"FixedWeather")); + menu->append(new LLMenuItemCallGL("Dump Region Object Cache", + &handle_dump_region_object_cache, NULL, NULL)); menu->createJumpKeys(); } @@ -1273,7 +1264,6 @@ void init_debug_avatar_menu(LLMenuGL* menu) menu->append(new LLMenuItemCallGL("Force Params to Default", &LLAgent::clearVisualParams, NULL)); menu->append(new LLMenuItemCallGL("Reload Vertex Shader", &reload_vertex_shader, NULL)); menu->append(new LLMenuItemToggleGL("Animation Info", &LLVOAvatar::sShowAnimationDebug)); - menu->append(new LLMenuItemCallGL("Flush Animations", &flush_animations, NULL)); menu->append(new LLMenuItemCallGL("Slow Motion Animations", &slow_mo_animations, NULL)); menu->append(new LLMenuItemToggleGL("Show Look At", &LLHUDEffectLookAt::sDebugLookAt)); menu->append(new LLMenuItemToggleGL("Show Point At", &LLHUDEffectPointAt::sDebugPointAt)); @@ -2021,13 +2011,13 @@ class LLAvatarDebug : public view_listener_t if( avatar ) { avatar->dumpLocalTextures(); + llinfos << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << llendl; + std::vector<std::string> strings; + strings.push_back(avatar->getID().asString()); + LLUUID invoice; + send_generic_message("dumptempassetdata", strings, invoice); + LLFloaterAvatarTextures::show( avatar->getID() ); } - llinfos << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << llendl; - std::vector<std::string> strings; - strings.push_back(avatar->getID().asString()); - LLUUID invoice; - send_generic_message("dumptempassetdata", strings, invoice); - LLFloaterAvatarTextures::show( avatar->getID() ); return true; } }; @@ -2317,16 +2307,6 @@ void handle_buy_contents(LLSaleInfo sale_info) LLFloaterBuyContents::show(sale_info); } -class LLFileEnableSaveAs : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - bool new_value = gFloaterView->getFrontmost() && gFloaterView->getFrontmost()->canSaveAs(); - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - void handle_region_dump_temp_asset_data(void*) { llinfos << "Dumping temporary asset data to simulator logs" << llendl; @@ -2377,6 +2357,15 @@ void handle_dump_capabilities_info(void *) } } +void handle_dump_region_object_cache(void*) +{ + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + regionp->dumpCache(); + } +} + void handle_dump_focus(void *) { LLView *view = gFocusMgr.getKeyboardFocus(); @@ -4259,7 +4248,10 @@ void show_buy_currency(const char* extra) mesg << "Go to " << BUY_CURRENCY_URL << "\nfor information on purchasing currency?"; LLString::format_map_t args; - args["[EXTRA]"] = extra; + if (extra != NULL) + { + args["[EXTRA]"] = extra; + } args["[URL]"] = BUY_CURRENCY_URL; gViewerWindow->alertXml("PromptGoToCurrencyPage", args, callback_show_buy_currency); @@ -4856,906 +4848,6 @@ void toggle_map( void* user_data ) } } -/** - char* upload_pick(void* data) - - If applicable, brings up a file chooser in which the user selects a file - to upload for a particular task. If the file is valid for the given action, - returns the string to the full path filename, else returns NULL. - Data is the load filter for the type of file as defined in LLFilePicker. -**/ -const char* upload_pick(void* data) -{ - if( gAgent.cameraMouselook() ) - { - gAgent.changeCameraToDefault(); - // This doesn't seem necessary. JC - // display(); - } - - LLFilePicker::ELoadFilter type; - if(data) - { - type = (LLFilePicker::ELoadFilter)((intptr_t)data); - } - else - { - type = LLFilePicker::FFLOAD_ALL; - } - - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getOpenFile(type)) - { - llinfos << "Couldn't import objects from file" << llendl; - return NULL; - } - - const char* filename = picker.getFirstFile(); - const char* ext = strrchr(filename, '.'); - - //strincmp doesn't like NULL pointers - if (ext == NULL) - { - const char* short_name = strrchr(filename, - *gDirUtilp->getDirDelimiter().c_str()); - - // No extension - LLStringBase<char>::format_map_t args; - args["[FILE]"] = LLString(short_name + 1); - gViewerWindow->alertXml("NoFileExtension", args); - return NULL; - } - else - { - //so there is an extension - //loop over the valid extensions and compare to see - //if the extension is valid - - //now grab the set of valid file extensions - const char* valids = build_extensions_string(type); - std::string valid_extensions = std::string(valids); - - BOOL ext_valid = FALSE; - - typedef boost::tokenizer<boost::char_separator<char> > tokenizer; - boost::char_separator<char> sep(" "); - tokenizer tokens(valid_extensions, sep); - tokenizer::iterator token_iter; - - //now loop over all valid file extensions - //and compare them to the extension of the file - //to be uploaded - for( token_iter = tokens.begin(); - token_iter != tokens.end() && ext_valid != TRUE; - ++token_iter) - { - const char* cur_token = token_iter->c_str(); - - if (0 == strnicmp(cur_token, ext, strlen(cur_token)) || /* Flawfinder: ignore */ - 0 == strnicmp(cur_token, "*.*", strlen(cur_token))) /* Flawfinder: ignore */ - { - //valid extension - //or the acceptable extension is any - ext_valid = TRUE; - } - }//end for (loop over all tokens) - - if (ext_valid == FALSE) - { - //should only get here if the extension exists - //but is invalid - LLStringBase<char>::format_map_t args; - args["[EXTENSION]"] = ext; - args["[VALIDS]"] = valids; - gViewerWindow->alertXml("InvalidFileExtension", args); - return NULL; - } - }//end else (non-null extension) - - //valid file extension - - //now we check to see - //if the file is actually a valid image/sound/etc. - if (type == LLFilePicker::FFLOAD_WAV) - { - // pre-qualify wavs to make sure the format is acceptable - char error_msg[MAX_STRING]; /* Flawfinder: ignore */ - if (check_for_invalid_wav_formats(filename,error_msg)) - { - llinfos << error_msg << ": " << filename << llendl; - LLStringBase<char>::format_map_t args; - args["[FILE]"] = filename; - gViewerWindow->alertXml( error_msg, args ); - return NULL; - } - }//end if a wave/sound file - - - return filename; -} - -void handle_upload_object(void* data) -{ - const char* filename = upload_pick(data); - if (filename) - { - // start the import - LLFloaterImport* floaterp = new LLFloaterImport(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_import.xml"); - } -} - -class LLFileUploadImage : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - const char* filename = upload_pick((void *)(S32)LLFilePicker::FFLOAD_IMAGE); - if (filename) - { - LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_image_preview.xml"); - } - return TRUE; - } -}; - -class LLFileUploadSound : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_WAV)); - if (filename) - { - LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_sound_preview.xml"); - } - return true; - } -}; - -class LLFileUploadAnim : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_ANIM)); - if (filename) - { - LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_animation_preview.xml"); - } - return true; - } -}; - -class LLFileUploadBulk : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - if( gAgent.cameraMouselook() ) - { - gAgent.changeCameraToDefault(); - } - - // TODO: - // Iterate over all files - // Check extensions for uploadability, cost - // Check user balance for entire cost - // Charge user entire cost - // Loop, uploading - // If an upload fails, refund the user for that one - // - // Also fix single upload to charge first, then refund - - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getMultipleOpenFiles()) - { - const char* filename = picker.getFirstFile(); - const char* name = picker.getDirname(); - - LLString asset_name = name; - LLString::replaceNonstandardASCII( asset_name, '?' ); - LLString::replaceChar(asset_name, '|', '?'); - LLString::stripNonprintable(asset_name); - LLString::trim(asset_name); - - char* asset_name_str = (char*)asset_name.c_str(); - char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists - if( !end_p ) - { - end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ - } - - S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); - - asset_name = asset_name.substr( 0, len ); - - upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); // file - } - else - { - llinfos << "Couldn't import objects from file" << llendl; - } - return true; - } -}; - -void upload_error(const char* error_message, const char* label, const std::string filename, const LLStringBase<char>::format_map_t args) -{ - llwarns << error_message << llendl; - gViewerWindow->alertXml(label, args); - if(remove(filename.c_str()) == -1) - { - lldebugs << "unable to remove temp file" << llendl; - } - LLFilePicker::instance().reset(); -} - -class LLFileEnableCloseWindow : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - bool new_value = gFloaterView->getFocusedFloater() != NULL || gSnapshotFloaterView->getFocusedFloater() != NULL; - // horrendously opaque, this code - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - -class LLFileCloseWindow : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLFloater::closeFocusedFloater(); - - return true; - } -}; - -class LLFileSaveTexture : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLFloater* top = gFloaterView->getFrontmost(); - if (top) - { - top->saveAs(); - } - return true; - } -}; - -class LLFileTakeSnapshot : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLFloaterSnapshot::show(NULL); - return true; - } -}; - -class LLFileTakeSnapshotToDisk : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLPointer<LLImageRaw> raw = new LLImageRaw; - - S32 width = gViewerWindow->getWindowDisplayWidth(); - S32 height = gViewerWindow->getWindowDisplayHeight(); - - if (gSavedSettings.getBOOL("HighResSnapshot")) - { - width *= 2; - height *= 2; - } - - if (gViewerWindow->rawSnapshot(raw, - width, - height, - TRUE, - gSavedSettings.getBOOL("RenderUIInSnapshot"), - FALSE)) - { - if (!gQuietSnapshot) - { - gViewerWindow->playSnapshotAnimAndSound(); - } - LLImageBase::setSizeOverride(TRUE); - gViewerWindow->saveImageNumbered(raw); - LLImageBase::setSizeOverride(FALSE); - } - return true; - } -}; - -class LLFileSaveMovie : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLViewerWindow::saveMovieNumbered(NULL); - return true; - } -}; - -class LLFileSetWindowSize : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - LLString size = userdata.asString(); - S32 width, height; - sscanf(size.c_str(), "%d,%d", &width, &height); - LLViewerWindow::movieSize(width, height); - return true; - } -}; - -class LLFileQuit : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - app_request_quit(); - return true; - } -}; - -void handle_upload(void* data) -{ - const char* filename = upload_pick(data); - if (filename) - { - LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); - gUICtrlFactory->buildFloater(floaterp, "floater_name_description.xml"); - } -} - -void handle_compress_image(void*) -{ - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE)) - { - std::string infile(picker.getFirstFile()); - std::string outfile = infile + ".j2c"; - - llinfos << "Input: " << infile << llendl; - llinfos << "Output: " << outfile << llendl; - - BOOL success; - - success = LLViewerImageList::createUploadFile(infile, outfile, IMG_CODEC_TGA); - - if (success) - { - llinfos << "Compression complete" << llendl; - } - else - { - llinfos << "Compression failed: " << LLImageBase::getLastError() << llendl; - } - } -} - -void upload_new_resource(const LLString& src_filename, std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perm, - const LLString& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - void *userdata) -{ - // Generate the temporary UUID. - LLString filename = gDirUtilp->getTempFilename(); - LLTransactionID tid; - LLAssetID uuid; - - LLStringBase<char>::format_map_t args; - - LLString ext = src_filename.substr(src_filename.find_last_of('.')); - LLAssetType::EType asset_type = LLAssetType::AT_NONE; - char error_message[MAX_STRING]; /* Flawfinder: ignore */ - error_message[0] = '\0'; - LLString temp_str; - - BOOL error = FALSE; - - if (ext.empty()) - { - LLString::size_type offset = filename.find_last_of(gDirUtilp->getDirDelimiter()); - if (offset != LLString::npos) - offset++; - LLString short_name = filename.substr(offset); - - // No extension - snprintf(error_message, /* Flawfinder: ignore */ - MAX_STRING, - "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension", - short_name.c_str()); - args["[FILE]"] = short_name; - upload_error(error_message, "NofileExtension", filename, args); - return; - } - else if( LLString::compareInsensitive(ext.c_str(),".bmp") == 0 ) - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerImageList::createUploadFile(src_filename, - filename, - IMG_CODEC_BMP )) - { - snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ - src_filename.c_str(), LLImageBase::getLastError().c_str()); - args["[FILE]"] = src_filename; - args["[ERROR]"] = LLImageBase::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return; - } - } - else if( LLString::compareInsensitive(ext.c_str(),".tga") == 0 ) - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerImageList::createUploadFile(src_filename, - filename, - IMG_CODEC_TGA )) - { - snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ - src_filename.c_str(), LLImageBase::getLastError().c_str()); - args["[FILE]"] = src_filename; - args["[ERROR]"] = LLImageBase::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return; - } - } - else if( LLString::compareInsensitive(ext.c_str(),".jpg") == 0 || LLString::compareInsensitive(ext.c_str(),".jpeg") == 0) - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerImageList::createUploadFile(src_filename, - filename, - IMG_CODEC_JPEG )) - { - snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ - src_filename.c_str(), LLImageBase::getLastError().c_str()); - args["[FILE]"] = src_filename; - args["[ERROR]"] = LLImageBase::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return; - } - } - else if(LLString::compareInsensitive(ext.c_str(),".wav") == 0) - { - asset_type = LLAssetType::AT_SOUND; // tag it as audio - S32 encode_result = 0; - - S32 bitrate = 128; - - if (compression_info) - { - bitrate = compression_info; - } - llinfos << "Attempting to encode wav as an ogg file at " << bitrate << "kbps" << llendl; - - encode_result = encode_vorbis_file_at(src_filename.c_str(), filename.c_str(), bitrate*1000); - - if (LLVORBISENC_NOERR != encode_result) - { - switch(encode_result) - { - case LLVORBISENC_DEST_OPEN_ERR: - snprintf(error_message, MAX_STRING, "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = filename; - upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args); - break; - - default: - snprintf(error_message, MAX_STRING, "Unknown vorbis encode failure on: %s\n", src_filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = src_filename; - upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args); - break; - } - return; - } - } - else if(LLString::compareInsensitive(ext.c_str(),".tmp") == 0) - { - // This is a generic .lin resource file - asset_type = LLAssetType::AT_OBJECT; - FILE* in = LLFile::fopen(src_filename.c_str(), "rb"); /* Flawfinder: ignore */ - if (in) - { - // read in the file header - char buf[16384]; /* Flawfinder: ignore */ - S32 read; /* Flawfinder: ignore */ - S32 version; - if (fscanf(in, "LindenResource\nversion %d\n", &version)) - { - if (2 == version) - { - // *NOTE: This buffer size is hard coded into scanf() below. - char label[MAX_STRING]; /* Flawfinder: ignore */ - char value[MAX_STRING]; /* Flawfinder: ignore */ - S32 tokens_read; - while (fgets(buf, 1024, in)) - { - label[0] = '\0'; - value[0] = '\0'; - tokens_read = sscanf( /* Flawfinder: ignore */ - buf, - "%254s %254s\n", - label, value); - - llinfos << "got: " << label << " = " << value - << llendl; - - if (EOF == tokens_read) - { - fclose(in); - snprintf(error_message, MAX_STRING, "corrupt resource file: %s", src_filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = src_filename; - upload_error(error_message, "CorruptResourceFile", filename, args); - return; - } - - if (2 == tokens_read) - { - if (! strcmp("type", label)) - { - asset_type = (LLAssetType::EType)(atoi(value)); - } - } - else - { - if (! strcmp("_DATA_", label)) - { - // below is the data section - break; - } - } - // other values are currently discarded - } - - } - else - { - fclose(in); - snprintf(error_message, MAX_STRING, "unknown linden resource file version in file: %s", src_filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = src_filename; - upload_error(error_message, "UnknownResourceFileVersion", filename, args); - return; - } - } - else - { - // this is an original binary formatted .lin file - // start over at the beginning of the file - fseek(in, 0, SEEK_SET); - - const S32 MAX_ASSET_DESCRIPTION_LENGTH = 256; - const S32 MAX_ASSET_NAME_LENGTH = 64; - S32 header_size = 34 + MAX_ASSET_DESCRIPTION_LENGTH + MAX_ASSET_NAME_LENGTH; - S16 type_num; - - // read in and throw out most of the header except for the type - fread(buf, header_size, 1, in); - memcpy(&type_num, buf + 16, sizeof(S16)); /* Flawfinder: ignore */ - asset_type = (LLAssetType::EType)type_num; - } - - // copy the file's data segment into another file for uploading - FILE* out = LLFile::fopen(filename.c_str(), "wb"); /* Flawfinder: ignore */ - if (out) - { - while((read = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */ - { - fwrite(buf, 1, read, out); /* Flawfinder: ignore */ - } - fclose(out); - } - else - { - fclose(in); - snprintf(error_message, MAX_STRING, "Unable to create output file: %s", filename.c_str()); /* Flawfinder: ignore */ - args["[FILE]"] = filename; - upload_error(error_message, "UnableToCreateOutputFile", filename, args); - return; - } - - fclose(in); - } - else - { - llinfos << "Couldn't open .lin file " << src_filename << llendl; - } - } - else if (LLString::compareInsensitive(ext.c_str(),".bvh") == 0) - { - snprintf(error_message, MAX_STRING, "We do not currently support bulk upload of animation files\n"); /* Flawfinder: ignore */ - upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args); - return; - } - else - { - // Unknown extension - snprintf(error_message, MAX_STRING, "Unknown file extension %s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", ext.c_str()); /* Flawfinder: ignore */ - error = TRUE;; - } - - // gen a new transaction ID for this asset - tid.generate(); - - if (!error) - { - uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - // copy this file into the vfs for upload - S32 file_size; - apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size); - if (fp) - { - LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE); - - file.setMaxSize(file_size); - - const S32 buf_size = 65536; - U8 copy_buf[buf_size]; - while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size))) - { - file.write(copy_buf, file_size); - } - apr_file_close(fp); - } - else - { - snprintf(error_message, MAX_STRING, "Unable to access output file: %s", filename.c_str()); /* Flawfinder: ignore */ - error = TRUE; - } - } - - if (!error) - { - LLString t_disp_name = display_name; - if (t_disp_name.empty()) - { - t_disp_name = src_filename; - } - upload_new_resource(tid, asset_type, name, desc, compression_info, // tid - destination_folder_type, inv_type, next_owner_perm, - display_name, callback, userdata); - } - else - { - llwarns << error_message << llendl; - LLStringBase<char>::format_map_t args; - args["[ERROR_MESSAGE]"] = error_message; - gViewerWindow->alertXml("ErrorMessage", args); - if(LLFile::remove(filename.c_str()) == -1) - { - lldebugs << "unable to remove temp file" << llendl; - } - LLFilePicker::instance().reset(); - } -} - -void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, - std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perm, - const LLString& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - void *userdata) -{ - LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - - if( LLAssetType::AT_SOUND == asset_type ) - { - gViewerStats->incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT ); - } - else - if( LLAssetType::AT_TEXTURE == asset_type ) - { - gViewerStats->incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); - } - else - if( LLAssetType::AT_ANIMATION == asset_type) - { - gViewerStats->incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT ); - } - - if(LLInventoryType::IT_NONE == inv_type) - { - inv_type = LLInventoryType::defaultForAssetType(asset_type); - } - LLString::stripNonprintable(name); - LLString::stripNonprintable(desc); - if(name.empty()) - { - name = "(No Name)"; - } - if(desc.empty()) - { - desc = "(No Description)"; - } - - // At this point, we're ready for the upload. - LLString upload_message = "Uploading...\n\n"; - upload_message.append(display_name); - LLUploadDialog::modalUploadDialog(upload_message); - - llinfos << "*** Uploading: " << llendl; - llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl; - llinfos << "UUID: " << uuid << llendl; - llinfos << "Name: " << name << llendl; - llinfos << "Desc: " << desc << llendl; - lldebugs << "Folder: " << gInventory.findCategoryUUIDForType(destination_folder_type) << llendl; - lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; - std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); - if (!url.empty()) - { - llinfos << "New Agent Inventory via capability" << llendl; - LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type); - body["asset_type"] = LLAssetType::lookup(asset_type); - body["inventory_type"] = LLInventoryType::lookup(inv_type); - body["name"] = name; - body["description"] = desc; - - std::ostringstream llsdxml; - LLSDSerialize::toXML(body, llsdxml); - lldebugs << "posting body to capability: " << llsdxml.str() << llendl; - LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); - } - else - { - llinfos << "NewAgentInventory capability not found, new agent inventory via asset system." << llendl; - // check for adequate funds - // TODO: do this check on the sim - if (LLAssetType::AT_SOUND == asset_type || - LLAssetType::AT_TEXTURE == asset_type || - LLAssetType::AT_ANIMATION == asset_type) - { - S32 upload_cost = gGlobalEconomy->getPriceUpload(); - S32 balance = gStatusBar->getBalance(); - if (balance < upload_cost) - { - // insufficient funds, bail on this upload - LLFloaterBuyCurrency::buyCurrency("Uploading costs", upload_cost); - return; - } - } - - LLResourceData* data = new LLResourceData; - data->mAssetInfo.mTransactionID = tid; - data->mAssetInfo.mUuid = uuid; - data->mAssetInfo.mType = asset_type; - data->mAssetInfo.mCreatorID = gAgentID; - data->mInventoryType = inv_type; - data->mNextOwnerPerm = next_owner_perm; - data->mUserData = userdata; - data->mAssetInfo.setName(name); - data->mAssetInfo.setDescription(desc); - data->mPreferredLocation = destination_folder_type; - - LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback; - if (callback) - { - asset_callback = callback; - } - gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType, - asset_callback, - (void*)data, - FALSE); - } -} - -void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result) // StoreAssetData callback (fixed) -{ - LLResourceData* data = (LLResourceData*)user_data; - //LLAssetType::EType pref_loc = data->mPreferredLocation; - BOOL is_balance_sufficient = TRUE; - if(result >= 0) - { - LLAssetType::EType dest_loc = (data->mPreferredLocation == LLAssetType::AT_NONE) ? data->mAssetInfo.mType : data->mPreferredLocation; - - if (LLAssetType::AT_SOUND == data->mAssetInfo.mType || - LLAssetType::AT_TEXTURE == data->mAssetInfo.mType || - LLAssetType::AT_ANIMATION == data->mAssetInfo.mType) - { - // Charge the user for the upload. - LLViewerRegion* region = gAgent.getRegion(); - S32 upload_cost = gGlobalEconomy->getPriceUpload(); - - if(!(can_afford_transaction(upload_cost))) - { - LLFloaterBuyCurrency::buyCurrency( - llformat("Uploading %s costs", - data->mAssetInfo.getName().c_str()), - upload_cost); - is_balance_sufficient = FALSE; - } - else if(region) - { - // Charge user for upload - gStatusBar->debitBalance(upload_cost); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MoneyTransferRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_MoneyData); - msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_DestID, LLUUID::null); - msg->addU8("Flags", 0); - msg->addS32Fast(_PREHASH_Amount, upload_cost); - msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY); - msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY); - msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE); - msg->addStringFast(_PREHASH_Description, NULL); - msg->sendReliable(region->getHost()); - } - } - - if(is_balance_sufficient) - { - // Actually add the upload to inventory - llinfos << "Adding " << uuid << " to inventory." << llendl; - LLUUID folder_id(gInventory.findCategoryUUIDForType(dest_loc)); - if(folder_id.notNull()) - { - U32 next_owner_perm = data->mNextOwnerPerm; - if(PERM_NONE == next_owner_perm) - { - next_owner_perm = PERM_MOVE | PERM_TRANSFER; - } - create_inventory_item(gAgent.getID(), gAgent.getSessionID(), - folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(), - data->mAssetInfo.getDescription(), data->mAssetInfo.mType, - data->mInventoryType, NOT_WEARABLE, next_owner_perm, - LLPointer<LLInventoryCallback>(NULL)); - } - else - { - llwarns << "Can't find a folder to put it in" << llendl; - } - } - } - else // if(result >= 0) - { - LLStringBase<char>::format_map_t args; - args["[FILE]"] = LLInventoryType::lookupHumanReadable(data->mInventoryType); - args["[REASON]"] = LLString(LLAssetStorage::getErrorString(result)); - gViewerWindow->alertXml("CannotUploadReason", args); - } - - LLUploadDialog::modalUploadFinished(); - delete data; - - // *NOTE: This is a pretty big hack. What this does is check the - // file picker if there are any more pending uploads. If so, - // upload that file. - const char* next_file = LLFilePicker::instance().getNextFile(); - if(is_balance_sufficient && next_file) - { - const char* name = LLFilePicker::instance().getDirname(); - - LLString asset_name = name; - LLString::replaceNonstandardASCII( asset_name, '?' ); - LLString::replaceChar(asset_name, '|', '?'); - LLString::stripNonprintable(asset_name); - LLString::trim(asset_name); - - char* asset_name_str = (char*)asset_name.c_str(); - char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists - if( !end_p ) - { - end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ - } - - S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); - - asset_name = asset_name.substr( 0, len ); - - upload_new_resource(next_file, asset_name, asset_name, // file - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); - } -} LLUUID gExporterRequestID; LLString gExportDirectory; @@ -7614,15 +6706,6 @@ BOOL enable_not_thirdperson(void*) return !gAgent.cameraThirdPerson(); } -class LLFileEnableUpload : public view_listener_t -{ - bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - bool new_value = gStatusBar && gGlobalEconomy && (gStatusBar->getBalance() >= gGlobalEconomy->getPriceUpload()); - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; BOOL enable_export_selected(void *) { @@ -7837,14 +6920,6 @@ void reload_vertex_shader(void *) //THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought - DaveP } -void flush_animations(void *) -{ - if (gAgent.getAvatarObject()) - { - gAgent.getAvatarObject()->resetAnimations(); - } -} - void slow_mo_animations(void*) { static BOOL slow_mo = FALSE; @@ -8430,24 +7505,10 @@ class LLToolsSelectTool : public view_listener_t } }; -void initialize_menu_actions() +void initialize_menus() { // File menu - (new LLFileUploadImage())->registerListener(gMenuHolder, "File.UploadImage"); - (new LLFileUploadSound())->registerListener(gMenuHolder, "File.UploadSound"); - (new LLFileUploadAnim())->registerListener(gMenuHolder, "File.UploadAnim"); - (new LLFileUploadBulk())->registerListener(gMenuHolder, "File.UploadBulk"); - (new LLFileCloseWindow())->registerListener(gMenuHolder, "File.CloseWindow"); - (new LLFileEnableCloseWindow())->registerListener(gMenuHolder, "File.EnableCloseWindow"); - (new LLFileSaveTexture())->registerListener(gMenuHolder, "File.SaveTexture"); - (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot"); - (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk"); - (new LLFileSaveMovie())->registerListener(gMenuHolder, "File.SaveMovie"); - (new LLFileSetWindowSize())->registerListener(gMenuHolder, "File.SetWindowSize"); - (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit"); - - (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload"); - (new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs"); + init_menu_file(); // Edit menu (new LLEditUndo())->registerListener(gMenuHolder, "Edit.Undo"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 70d34c73c3..2c6cbe7734 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -9,8 +9,6 @@ #ifndef LL_LLVIEWERMENU_H #define LL_LLVIEWERMENU_H -#include "llassetstorage.h" -#include "llinventory.h" #include "llmenugl.h" //newview includes @@ -21,14 +19,6 @@ class LLView; class LLParcelSelection; class LLObjectSelection; -struct LLResourceData -{ - LLAssetInfo mAssetInfo; - LLAssetType::EType mPreferredLocation; - LLInventoryType::EType mInventoryType; - U32 mNextOwnerPerm; - void *mUserData; -}; void pre_init_menus(); void init_menus(); @@ -94,25 +84,6 @@ bool handle_give_money_dialog(); bool handle_object_open(); bool handle_go_to(); -void upload_new_resource(const LLString& src_filename, std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perm = PERM_NONE, - const LLString& display_name = LLString::null, - LLAssetStorage::LLStoreAssetCallback callback = NULL, - void *userdata = NULL); - -void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType type, - std::string name, - std::string desc, S32 compression_info, - LLAssetType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perm = PERM_NONE, - const LLString& display_name = LLString::null, - LLAssetStorage::LLStoreAssetCallback callback = NULL, - void *userdata = NULL); - // Export to XML or Collada void handle_export_selected( void * ); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp new file mode 100644 index 0000000000..eec6c8f481 --- /dev/null +++ b/indra/newview/llviewermenufile.cpp @@ -0,0 +1,1002 @@ +/** + * @file llviewermenufile.cpp + * @brief "File" menu in the main menu bar. + * + * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewermenufile.h" + +// project includes +#include "llagent.h" +#include "llfilepicker.h" +#include "llfloateranimpreview.h" +#include "llfloaterbuycurrency.h" +#include "llfloaterimagepreview.h" +#include "llfloaterimport.h" +#include "llfloaternamedesc.h" +#include "llfloatersnapshot.h" +#include "llinventorymodel.h" // gInventory +#include "llresourcedata.h" +#include "llstatusbar.h" +#include "llviewercontrol.h" // gSavedSettings +#include "llviewerimagelist.h" +#include "llvieweruictrlfactory.h" +#include "llviewermenu.h" // gMenuHolder +#include "llviewerregion.h" +#include "llviewerstats.h" +#include "llviewerwindow.h" +#include "viewer.h" // app_request_quit() + +// linden libraries +#include "llassetuploadresponders.h" +#include "lleconomy.h" +#include "llhttpclient.h" +#include "llmemberlistener.h" +#include "llsdserialize.h" +#include "llstring.h" +#include "lltransactiontypes.h" +#include "lluuid.h" +#include "vorbisencode.h" + +// system libraries +#include <boost/tokenizer.hpp> + +typedef LLMemberListener<LLView> view_listener_t; + + +class LLFileEnableSaveAs : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + bool new_value = gFloaterView->getFrontmost() && gFloaterView->getFrontmost()->canSaveAs(); + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + return true; + } +}; + +class LLFileEnableUpload : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + bool new_value = gStatusBar && gGlobalEconomy && (gStatusBar->getBalance() >= gGlobalEconomy->getPriceUpload()); + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + return true; + } +}; + +/** + char* upload_pick(void* data) + + If applicable, brings up a file chooser in which the user selects a file + to upload for a particular task. If the file is valid for the given action, + returns the string to the full path filename, else returns NULL. + Data is the load filter for the type of file as defined in LLFilePicker. +**/ +const char* upload_pick(void* data) +{ + if( gAgent.cameraMouselook() ) + { + gAgent.changeCameraToDefault(); + // This doesn't seem necessary. JC + // display(); + } + + LLFilePicker::ELoadFilter type; + if(data) + { + type = (LLFilePicker::ELoadFilter)((intptr_t)data); + } + else + { + type = LLFilePicker::FFLOAD_ALL; + } + + LLFilePicker& picker = LLFilePicker::instance(); + if (!picker.getOpenFile(type)) + { + llinfos << "Couldn't import objects from file" << llendl; + return NULL; + } + + const char* filename = picker.getFirstFile(); + const char* ext = strrchr(filename, '.'); + + //strincmp doesn't like NULL pointers + if (ext == NULL) + { + const char* short_name = strrchr(filename, + *gDirUtilp->getDirDelimiter().c_str()); + + // No extension + LLStringBase<char>::format_map_t args; + args["[FILE]"] = LLString(short_name + 1); + gViewerWindow->alertXml("NoFileExtension", args); + return NULL; + } + else + { + //so there is an extension + //loop over the valid extensions and compare to see + //if the extension is valid + + //now grab the set of valid file extensions + const char* valids = build_extensions_string(type); + std::string valid_extensions = std::string(valids); + + BOOL ext_valid = FALSE; + + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep(" "); + tokenizer tokens(valid_extensions, sep); + tokenizer::iterator token_iter; + + //now loop over all valid file extensions + //and compare them to the extension of the file + //to be uploaded + for( token_iter = tokens.begin(); + token_iter != tokens.end() && ext_valid != TRUE; + ++token_iter) + { + const char* cur_token = token_iter->c_str(); + + if (0 == strnicmp(cur_token, ext, strlen(cur_token)) || /* Flawfinder: ignore */ + 0 == strnicmp(cur_token, "*.*", strlen(cur_token))) /* Flawfinder: ignore */ + { + //valid extension + //or the acceptable extension is any + ext_valid = TRUE; + } + }//end for (loop over all tokens) + + if (ext_valid == FALSE) + { + //should only get here if the extension exists + //but is invalid + LLStringBase<char>::format_map_t args; + args["[EXTENSION]"] = ext; + args["[VALIDS]"] = valids; + gViewerWindow->alertXml("InvalidFileExtension", args); + return NULL; + } + }//end else (non-null extension) + + //valid file extension + + //now we check to see + //if the file is actually a valid image/sound/etc. + if (type == LLFilePicker::FFLOAD_WAV) + { + // pre-qualify wavs to make sure the format is acceptable + char error_msg[MAX_STRING]; /* Flawfinder: ignore */ + if (check_for_invalid_wav_formats(filename,error_msg)) + { + llinfos << error_msg << ": " << filename << llendl; + LLStringBase<char>::format_map_t args; + args["[FILE]"] = filename; + gViewerWindow->alertXml( error_msg, args ); + return NULL; + } + }//end if a wave/sound file + + + return filename; +} + +void handle_upload_object(void* data) +{ + const char* filename = upload_pick(data); + if (filename) + { + // start the import + LLFloaterImport* floaterp = new LLFloaterImport(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_import.xml"); + } +} + +class LLFileUploadImage : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + const char* filename = upload_pick((void *)(S32)LLFilePicker::FFLOAD_IMAGE); + if (filename) + { + LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_image_preview.xml"); + } + return TRUE; + } +}; + +class LLFileUploadSound : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_WAV)); + if (filename) + { + LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_sound_preview.xml"); + } + return true; + } +}; + +class LLFileUploadAnim : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + const char* filename = upload_pick((void*)((S32)LLFilePicker::FFLOAD_ANIM)); + if (filename) + { + LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_animation_preview.xml"); + } + return true; + } +}; + +class LLFileUploadBulk : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + if( gAgent.cameraMouselook() ) + { + gAgent.changeCameraToDefault(); + } + + // TODO: + // Iterate over all files + // Check extensions for uploadability, cost + // Check user balance for entire cost + // Charge user entire cost + // Loop, uploading + // If an upload fails, refund the user for that one + // + // Also fix single upload to charge first, then refund + + LLFilePicker& picker = LLFilePicker::instance(); + if (picker.getMultipleOpenFiles()) + { + const char* filename = picker.getFirstFile(); + const char* name = picker.getDirname(); + + LLString asset_name = name; + LLString::replaceNonstandardASCII( asset_name, '?' ); + LLString::replaceChar(asset_name, '|', '?'); + LLString::stripNonprintable(asset_name); + LLString::trim(asset_name); + + char* asset_name_str = (char*)asset_name.c_str(); + char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists + if( !end_p ) + { + end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ + } + + S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); + + asset_name = asset_name.substr( 0, len ); + + upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); // file + } + else + { + llinfos << "Couldn't import objects from file" << llendl; + } + return true; + } +}; + +void upload_error(const char* error_message, const char* label, const std::string filename, const LLStringBase<char>::format_map_t args) +{ + llwarns << error_message << llendl; + gViewerWindow->alertXml(label, args); + if(remove(filename.c_str()) == -1) + { + lldebugs << "unable to remove temp file" << llendl; + } + LLFilePicker::instance().reset(); +} + +class LLFileEnableCloseWindow : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + bool new_value = gFloaterView->getFocusedFloater() != NULL || gSnapshotFloaterView->getFocusedFloater() != NULL; + // horrendously opaque, this code + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + return true; + } +}; + +class LLFileCloseWindow : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLFloater::closeFocusedFloater(); + + return true; + } +}; + +class LLFileCloseAllWindows : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + bool app_quitting = false; + gFloaterView->closeAllChildren(app_quitting); + + return true; + } +}; + +class LLFileSaveTexture : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLFloater* top = gFloaterView->getFrontmost(); + if (top) + { + top->saveAs(); + } + return true; + } +}; + +class LLFileTakeSnapshot : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLFloaterSnapshot::show(NULL); + return true; + } +}; + +class LLFileTakeSnapshotToDisk : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLPointer<LLImageRaw> raw = new LLImageRaw; + + S32 width = gViewerWindow->getWindowDisplayWidth(); + S32 height = gViewerWindow->getWindowDisplayHeight(); + + if (gSavedSettings.getBOOL("HighResSnapshot")) + { + width *= 2; + height *= 2; + } + + if (gViewerWindow->rawSnapshot(raw, + width, + height, + TRUE, + gSavedSettings.getBOOL("RenderUIInSnapshot"), + FALSE)) + { + if (!gQuietSnapshot) + { + gViewerWindow->playSnapshotAnimAndSound(); + } + LLImageBase::setSizeOverride(TRUE); + gViewerWindow->saveImageNumbered(raw); + LLImageBase::setSizeOverride(FALSE); + } + return true; + } +}; + +class LLFileSaveMovie : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLViewerWindow::saveMovieNumbered(NULL); + return true; + } +}; + +class LLFileSetWindowSize : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + LLString size = userdata.asString(); + S32 width, height; + sscanf(size.c_str(), "%d,%d", &width, &height); + LLViewerWindow::movieSize(width, height); + return true; + } +}; + +class LLFileQuit : public view_listener_t +{ + bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) + { + app_request_quit(); + return true; + } +}; + +void handle_upload(void* data) +{ + const char* filename = upload_pick(data); + if (filename) + { + LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); + gUICtrlFactory->buildFloater(floaterp, "floater_name_description.xml"); + } +} + +void handle_compress_image(void*) +{ + LLFilePicker& picker = LLFilePicker::instance(); + if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE)) + { + std::string infile(picker.getFirstFile()); + std::string outfile = infile + ".j2c"; + + llinfos << "Input: " << infile << llendl; + llinfos << "Output: " << outfile << llendl; + + BOOL success; + + success = LLViewerImageList::createUploadFile(infile, outfile, IMG_CODEC_TGA); + + if (success) + { + llinfos << "Compression complete" << llendl; + } + else + { + llinfos << "Compression failed: " << LLImageBase::getLastError() << llendl; + } + } +} + +void upload_new_resource(const LLString& src_filename, std::string name, + std::string desc, S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perm, + const LLString& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + void *userdata) +{ + // Generate the temporary UUID. + LLString filename = gDirUtilp->getTempFilename(); + LLTransactionID tid; + LLAssetID uuid; + + LLStringBase<char>::format_map_t args; + + LLString ext = src_filename.substr(src_filename.find_last_of('.')); + LLAssetType::EType asset_type = LLAssetType::AT_NONE; + char error_message[MAX_STRING]; /* Flawfinder: ignore */ + error_message[0] = '\0'; + LLString temp_str; + + BOOL error = FALSE; + + if (ext.empty()) + { + LLString::size_type offset = filename.find_last_of(gDirUtilp->getDirDelimiter()); + if (offset != LLString::npos) + offset++; + LLString short_name = filename.substr(offset); + + // No extension + snprintf(error_message, /* Flawfinder: ignore */ + MAX_STRING, + "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension", + short_name.c_str()); + args["[FILE]"] = short_name; + upload_error(error_message, "NofileExtension", filename, args); + return; + } + else if( LLString::compareInsensitive(ext.c_str(),".bmp") == 0 ) + { + asset_type = LLAssetType::AT_TEXTURE; + if (!LLViewerImageList::createUploadFile(src_filename, + filename, + IMG_CODEC_BMP )) + { + snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ + src_filename.c_str(), LLImageBase::getLastError().c_str()); + args["[FILE]"] = src_filename; + args["[ERROR]"] = LLImageBase::getLastError(); + upload_error(error_message, "ProblemWithFile", filename, args); + return; + } + } + else if( LLString::compareInsensitive(ext.c_str(),".tga") == 0 ) + { + asset_type = LLAssetType::AT_TEXTURE; + if (!LLViewerImageList::createUploadFile(src_filename, + filename, + IMG_CODEC_TGA )) + { + snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ + src_filename.c_str(), LLImageBase::getLastError().c_str()); + args["[FILE]"] = src_filename; + args["[ERROR]"] = LLImageBase::getLastError(); + upload_error(error_message, "ProblemWithFile", filename, args); + return; + } + } + else if( LLString::compareInsensitive(ext.c_str(),".jpg") == 0 || LLString::compareInsensitive(ext.c_str(),".jpeg") == 0) + { + asset_type = LLAssetType::AT_TEXTURE; + if (!LLViewerImageList::createUploadFile(src_filename, + filename, + IMG_CODEC_JPEG )) + { + snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ + src_filename.c_str(), LLImageBase::getLastError().c_str()); + args["[FILE]"] = src_filename; + args["[ERROR]"] = LLImageBase::getLastError(); + upload_error(error_message, "ProblemWithFile", filename, args); + return; + } + } + else if(LLString::compareInsensitive(ext.c_str(),".wav") == 0) + { + asset_type = LLAssetType::AT_SOUND; // tag it as audio + S32 encode_result = 0; + + S32 bitrate = 128; + + if (compression_info) + { + bitrate = compression_info; + } + llinfos << "Attempting to encode wav as an ogg file at " << bitrate << "kbps" << llendl; + + encode_result = encode_vorbis_file_at(src_filename.c_str(), filename.c_str(), bitrate*1000); + + if (LLVORBISENC_NOERR != encode_result) + { + switch(encode_result) + { + case LLVORBISENC_DEST_OPEN_ERR: + snprintf(error_message, MAX_STRING, "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = filename; + upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args); + break; + + default: + snprintf(error_message, MAX_STRING, "Unknown vorbis encode failure on: %s\n", src_filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = src_filename; + upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args); + break; + } + return; + } + } + else if(LLString::compareInsensitive(ext.c_str(),".tmp") == 0) + { + // This is a generic .lin resource file + asset_type = LLAssetType::AT_OBJECT; + FILE* in = LLFile::fopen(src_filename.c_str(), "rb"); /* Flawfinder: ignore */ + if (in) + { + // read in the file header + char buf[16384]; /* Flawfinder: ignore */ + S32 read; /* Flawfinder: ignore */ + S32 version; + if (fscanf(in, "LindenResource\nversion %d\n", &version)) + { + if (2 == version) + { + // *NOTE: This buffer size is hard coded into scanf() below. + char label[MAX_STRING]; /* Flawfinder: ignore */ + char value[MAX_STRING]; /* Flawfinder: ignore */ + S32 tokens_read; + while (fgets(buf, 1024, in)) + { + label[0] = '\0'; + value[0] = '\0'; + tokens_read = sscanf( /* Flawfinder: ignore */ + buf, + "%254s %254s\n", + label, value); + + llinfos << "got: " << label << " = " << value + << llendl; + + if (EOF == tokens_read) + { + fclose(in); + snprintf(error_message, MAX_STRING, "corrupt resource file: %s", src_filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = src_filename; + upload_error(error_message, "CorruptResourceFile", filename, args); + return; + } + + if (2 == tokens_read) + { + if (! strcmp("type", label)) + { + asset_type = (LLAssetType::EType)(atoi(value)); + } + } + else + { + if (! strcmp("_DATA_", label)) + { + // below is the data section + break; + } + } + // other values are currently discarded + } + + } + else + { + fclose(in); + snprintf(error_message, MAX_STRING, "unknown linden resource file version in file: %s", src_filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = src_filename; + upload_error(error_message, "UnknownResourceFileVersion", filename, args); + return; + } + } + else + { + // this is an original binary formatted .lin file + // start over at the beginning of the file + fseek(in, 0, SEEK_SET); + + const S32 MAX_ASSET_DESCRIPTION_LENGTH = 256; + const S32 MAX_ASSET_NAME_LENGTH = 64; + S32 header_size = 34 + MAX_ASSET_DESCRIPTION_LENGTH + MAX_ASSET_NAME_LENGTH; + S16 type_num; + + // read in and throw out most of the header except for the type + fread(buf, header_size, 1, in); + memcpy(&type_num, buf + 16, sizeof(S16)); /* Flawfinder: ignore */ + asset_type = (LLAssetType::EType)type_num; + } + + // copy the file's data segment into another file for uploading + FILE* out = LLFile::fopen(filename.c_str(), "wb"); /* Flawfinder: ignore */ + if (out) + { + while((read = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */ + { + fwrite(buf, 1, read, out); /* Flawfinder: ignore */ + } + fclose(out); + } + else + { + fclose(in); + snprintf(error_message, MAX_STRING, "Unable to create output file: %s", filename.c_str()); /* Flawfinder: ignore */ + args["[FILE]"] = filename; + upload_error(error_message, "UnableToCreateOutputFile", filename, args); + return; + } + + fclose(in); + } + else + { + llinfos << "Couldn't open .lin file " << src_filename << llendl; + } + } + else if (LLString::compareInsensitive(ext.c_str(),".bvh") == 0) + { + snprintf(error_message, MAX_STRING, "We do not currently support bulk upload of animation files\n"); /* Flawfinder: ignore */ + upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args); + return; + } + else + { + // Unknown extension + snprintf(error_message, MAX_STRING, "Unknown file extension %s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", ext.c_str()); /* Flawfinder: ignore */ + error = TRUE;; + } + + // gen a new transaction ID for this asset + tid.generate(); + + if (!error) + { + uuid = tid.makeAssetID(gAgent.getSecureSessionID()); + // copy this file into the vfs for upload + S32 file_size; + apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size); + if (fp) + { + LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE); + + file.setMaxSize(file_size); + + const S32 buf_size = 65536; + U8 copy_buf[buf_size]; + while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size))) + { + file.write(copy_buf, file_size); + } + apr_file_close(fp); + } + else + { + snprintf(error_message, MAX_STRING, "Unable to access output file: %s", filename.c_str()); /* Flawfinder: ignore */ + error = TRUE; + } + } + + if (!error) + { + LLString t_disp_name = display_name; + if (t_disp_name.empty()) + { + t_disp_name = src_filename; + } + upload_new_resource(tid, asset_type, name, desc, compression_info, // tid + destination_folder_type, inv_type, next_owner_perm, + display_name, callback, userdata); + } + else + { + llwarns << error_message << llendl; + LLStringBase<char>::format_map_t args; + args["[ERROR_MESSAGE]"] = error_message; + gViewerWindow->alertXml("ErrorMessage", args); + if(LLFile::remove(filename.c_str()) == -1) + { + lldebugs << "unable to remove temp file" << llendl; + } + LLFilePicker::instance().reset(); + } +} + +void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result) // StoreAssetData callback (fixed) +{ + LLResourceData* data = (LLResourceData*)user_data; + //LLAssetType::EType pref_loc = data->mPreferredLocation; + BOOL is_balance_sufficient = TRUE; + if(result >= 0) + { + LLAssetType::EType dest_loc = (data->mPreferredLocation == LLAssetType::AT_NONE) ? data->mAssetInfo.mType : data->mPreferredLocation; + + if (LLAssetType::AT_SOUND == data->mAssetInfo.mType || + LLAssetType::AT_TEXTURE == data->mAssetInfo.mType || + LLAssetType::AT_ANIMATION == data->mAssetInfo.mType) + { + // Charge the user for the upload. + LLViewerRegion* region = gAgent.getRegion(); + S32 upload_cost = gGlobalEconomy->getPriceUpload(); + + if(!(can_afford_transaction(upload_cost))) + { + LLFloaterBuyCurrency::buyCurrency( + llformat("Uploading %s costs", + data->mAssetInfo.getName().c_str()), + upload_cost); + is_balance_sufficient = FALSE; + } + else if(region) + { + // Charge user for upload + gStatusBar->debitBalance(upload_cost); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MoneyTransferRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_MoneyData); + msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_DestID, LLUUID::null); + msg->addU8("Flags", 0); + msg->addS32Fast(_PREHASH_Amount, upload_cost); + msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY); + msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY); + msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE); + msg->addStringFast(_PREHASH_Description, NULL); + msg->sendReliable(region->getHost()); + } + } + + if(is_balance_sufficient) + { + // Actually add the upload to inventory + llinfos << "Adding " << uuid << " to inventory." << llendl; + LLUUID folder_id(gInventory.findCategoryUUIDForType(dest_loc)); + if(folder_id.notNull()) + { + U32 next_owner_perm = data->mNextOwnerPerm; + if(PERM_NONE == next_owner_perm) + { + next_owner_perm = PERM_MOVE | PERM_TRANSFER; + } + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(), + data->mAssetInfo.getDescription(), data->mAssetInfo.mType, + data->mInventoryType, NOT_WEARABLE, next_owner_perm, + LLPointer<LLInventoryCallback>(NULL)); + } + else + { + llwarns << "Can't find a folder to put it in" << llendl; + } + } + } + else // if(result >= 0) + { + LLStringBase<char>::format_map_t args; + args["[FILE]"] = LLInventoryType::lookupHumanReadable(data->mInventoryType); + args["[REASON]"] = LLString(LLAssetStorage::getErrorString(result)); + gViewerWindow->alertXml("CannotUploadReason", args); + } + + LLUploadDialog::modalUploadFinished(); + delete data; + + // *NOTE: This is a pretty big hack. What this does is check the + // file picker if there are any more pending uploads. If so, + // upload that file. + const char* next_file = LLFilePicker::instance().getNextFile(); + if(is_balance_sufficient && next_file) + { + const char* name = LLFilePicker::instance().getDirname(); + + LLString asset_name = name; + LLString::replaceNonstandardASCII( asset_name, '?' ); + LLString::replaceChar(asset_name, '|', '?'); + LLString::stripNonprintable(asset_name); + LLString::trim(asset_name); + + char* asset_name_str = (char*)asset_name.c_str(); + char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists + if( !end_p ) + { + end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ + } + + S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); + + asset_name = asset_name.substr( 0, len ); + + upload_new_resource(next_file, asset_name, asset_name, // file + 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); + } +} + +void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, + std::string name, + std::string desc, S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perm, + const LLString& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + void *userdata) +{ + LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID()); + + if( LLAssetType::AT_SOUND == asset_type ) + { + gViewerStats->incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT ); + } + else + if( LLAssetType::AT_TEXTURE == asset_type ) + { + gViewerStats->incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); + } + else + if( LLAssetType::AT_ANIMATION == asset_type) + { + gViewerStats->incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT ); + } + + if(LLInventoryType::IT_NONE == inv_type) + { + inv_type = LLInventoryType::defaultForAssetType(asset_type); + } + LLString::stripNonprintable(name); + LLString::stripNonprintable(desc); + if(name.empty()) + { + name = "(No Name)"; + } + if(desc.empty()) + { + desc = "(No Description)"; + } + + // At this point, we're ready for the upload. + LLString upload_message = "Uploading...\n\n"; + upload_message.append(display_name); + LLUploadDialog::modalUploadDialog(upload_message); + + llinfos << "*** Uploading: " << llendl; + llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl; + llinfos << "UUID: " << uuid << llendl; + llinfos << "Name: " << name << llendl; + llinfos << "Desc: " << desc << llendl; + lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type) << llendl; + lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; + std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); + if (!url.empty()) + { + llinfos << "New Agent Inventory via capability" << llendl; + LLSD body; + body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type); + body["asset_type"] = LLAssetType::lookup(asset_type); + body["inventory_type"] = LLInventoryType::lookup(inv_type); + body["name"] = name; + body["description"] = desc; + + std::ostringstream llsdxml; + LLSDSerialize::toXML(body, llsdxml); + lldebugs << "posting body to capability: " << llsdxml.str() << llendl; + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); + } + else + { + llinfos << "NewAgentInventory capability not found, new agent inventory via asset system." << llendl; + // check for adequate funds + // TODO: do this check on the sim + if (LLAssetType::AT_SOUND == asset_type || + LLAssetType::AT_TEXTURE == asset_type || + LLAssetType::AT_ANIMATION == asset_type) + { + S32 upload_cost = gGlobalEconomy->getPriceUpload(); + S32 balance = gStatusBar->getBalance(); + if (balance < upload_cost) + { + // insufficient funds, bail on this upload + LLFloaterBuyCurrency::buyCurrency("Uploading costs", upload_cost); + return; + } + } + + LLResourceData* data = new LLResourceData; + data->mAssetInfo.mTransactionID = tid; + data->mAssetInfo.mUuid = uuid; + data->mAssetInfo.mType = asset_type; + data->mAssetInfo.mCreatorID = gAgentID; + data->mInventoryType = inv_type; + data->mNextOwnerPerm = next_owner_perm; + data->mUserData = userdata; + data->mAssetInfo.setName(name); + data->mAssetInfo.setDescription(desc); + data->mPreferredLocation = destination_folder_type; + + LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback; + if (callback) + { + asset_callback = callback; + } + gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType, + asset_callback, + (void*)data, + FALSE); + } +} + + +void init_menu_file() +{ + (new LLFileUploadImage())->registerListener(gMenuHolder, "File.UploadImage"); + (new LLFileUploadSound())->registerListener(gMenuHolder, "File.UploadSound"); + (new LLFileUploadAnim())->registerListener(gMenuHolder, "File.UploadAnim"); + (new LLFileUploadBulk())->registerListener(gMenuHolder, "File.UploadBulk"); + (new LLFileCloseWindow())->registerListener(gMenuHolder, "File.CloseWindow"); + (new LLFileCloseAllWindows())->registerListener(gMenuHolder, "File.CloseAllWindows"); + (new LLFileEnableCloseWindow())->registerListener(gMenuHolder, "File.EnableCloseWindow"); + (new LLFileSaveTexture())->registerListener(gMenuHolder, "File.SaveTexture"); + (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot"); + (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk"); + (new LLFileSaveMovie())->registerListener(gMenuHolder, "File.SaveMovie"); + (new LLFileSetWindowSize())->registerListener(gMenuHolder, "File.SetWindowSize"); + (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit"); + + (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload"); + (new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs"); +} diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h new file mode 100644 index 0000000000..77861f8c48 --- /dev/null +++ b/indra/newview/llviewermenufile.h @@ -0,0 +1,39 @@ +/** + * @file llviewermenufile.h + * @brief "File" menu in the main menu bar. + * + * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LLVIEWERMENUFILE_H +#define LLVIEWERMENUFILE_H + +#include "llassettype.h" +#include "llinventorytype.h" + +class LLTransactionID; + + +void init_menu_file(); + +void upload_new_resource(const LLString& src_filename, std::string name, + std::string desc, S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perm = 0x0, // PERM_NONE + const LLString& display_name = LLString::null, + LLAssetStorage::LLStoreAssetCallback callback = NULL, + void *userdata = NULL); + +void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType type, + std::string name, + std::string desc, S32 compression_info, + LLAssetType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perm = 0x0, // PERM_NONE + const LLString& display_name = LLString::null, + LLAssetStorage::LLStoreAssetCallback callback = NULL, + void *userdata = NULL); + +#endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 316de37ce1..cb4077b21b 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -125,8 +125,14 @@ extern BOOL gDebugClicks; extern void bad_network_handler(); // function prototypes -void open_offer(const std::vector<LLUUID>& items); +void open_offer(const std::vector<LLUUID>& items, const std::string& from_name); void friendship_offer_callback(S32 option, void* user_data); +bool check_offer_throttle(const std::string& from_name, bool check_only); + +//inventory offer throttle globals +LLFrameTimer gThrottleTimer; +const U32 OFFER_THROTTLE_MAX_COUNT=5; //number of items per time period +const F32 OFFER_THROTTLE_TIME=10.f; //time period in seconds struct LLFriendshipOffer { @@ -175,11 +181,6 @@ void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_ } } -BOOL can_afford_transaction(S32 cost) -{ - return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost))); -} - void send_complete_agent_movement(const LLHost& sim_host) { LLMessageSystem* msg = gMessageSystem; @@ -255,11 +256,19 @@ void process_layer_data(LLMessageSystem *mesgsys, void **user_data) mesgsys->getS8Fast(_PREHASH_LayerID, _PREHASH_Type, type); size = mesgsys->getSizeFast(_PREHASH_LayerData, _PREHASH_Data); - if(!size) + if (0 == size) { llwarns << "Layer data has zero size." << llendl; return; } + if (size < 0) + { + // getSizeFast() is probably trying to tell us about an error + llwarns << "getSizeFast() returned negative result: " + << size + << llendl; + return; + } U8 *datap = new U8[size]; mesgsys->getBinaryDataFast(_PREHASH_LayerData, _PREHASH_Data, datap, size); LLVLData *vl_datap = new LLVLData(regionp, type, datap, size); @@ -306,25 +315,29 @@ void export_complete() while ((pos = strstr(pos+1, "<sl:image ")) != 0) { char *pos_check = strstr(pos, "checksum=\""); - char *pos_uuid = strstr(pos_check, "\">"); - if (pos_check && pos_uuid) + if (pos_check) { - char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */ - memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */ - image_uuid_str[UUID_STR_SIZE-1] = 0; + char *pos_uuid = strstr(pos_check, "\">"); - LLUUID image_uuid(image_uuid_str); + if (pos_uuid) + { + char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */ + memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */ + image_uuid_str[UUID_STR_SIZE-1] = 0; + + LLUUID image_uuid(image_uuid_str); - llinfos << "Found UUID: " << image_uuid << llendl; + llinfos << "Found UUID: " << image_uuid << llendl; - std::map<LLUUID, LLString>::iterator itor = gImageChecksums.find(image_uuid); - if (itor != gImageChecksums.end()) - { - llinfos << "Replacing with checksum: " << itor->second << llendl; - if (itor->second.c_str() != NULL) + std::map<LLUUID, LLString>::iterator itor = gImageChecksums.find(image_uuid); + if (itor != gImageChecksums.end()) { - memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */ + llinfos << "Replacing with checksum: " << itor->second << llendl; + if (itor->second.c_str() != NULL) + { + memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */ + } } } } @@ -334,7 +347,7 @@ void export_complete() fwrite(buffer, 1, length, fXMLOut); fclose(fXMLOut); - delete buffer; + delete [] buffer; } @@ -412,7 +425,7 @@ void exported_j2c_complete(const LLTSCode status, void *user_data) char *end = strrchr(file_path, gDirUtilp->getDirDelimiter()[0]); end[0] = 0; LLString output_file = llformat("%s/image-%03d.tga", file_path, image_num);//filename; - delete file_path; + delete [] file_path; //S32 name_len = output_file.length(); //strcpy(&output_file[name_len-3], "tga"); FILE* fOut = LLFile::fopen(output_file.c_str(), "wb"); /* Flawfinder: ignore */ @@ -579,31 +592,44 @@ void join_group_callback(S32 option, void* user_data) class LLOpenAgentOffer : public LLInventoryFetchObserver { public: - LLOpenAgentOffer() {} - virtual ~LLOpenAgentOffer() {} - - virtual void done() + LLOpenAgentOffer(const std::string& from_name) : mFromName(from_name) {} + /*virtual*/ void done() { - open_offer(mComplete); + open_offer(mComplete, mFromName); gInventory.removeObserver(this); delete this; } +private: + std::string mFromName; }; -class LLOpenTaskOffer : public LLInventoryExistenceObserver +//unlike the FetchObserver for AgentOffer, we only make one +//instance of the AddedObserver for TaskOffers +//and it never dies. We do this because we don't know the UUID of +//task offers until they are accepted, so we don't wouldn't +//know what to watch for, so instead we just watch for all additions. -Gigs +class LLOpenTaskOffer : public LLInventoryAddedObserver { -public: - LLOpenTaskOffer() {} - virtual ~LLOpenTaskOffer() {} - protected: - virtual void done() + /*virtual*/ void done() { - open_offer(mExist); - gInventory.removeObserver(this); - delete this; + open_offer(mAdded, ""); + mAdded.clear(); } -}; + }; + +//one global instance to bind them +LLOpenTaskOffer* gNewInventoryObserver=NULL; + +void start_new_inventory_observer() +{ + if (!gNewInventoryObserver) //task offer observer + { + // Observer is deleted by gInventory + gNewInventoryObserver = new LLOpenTaskOffer; + gInventory.addObserver(gNewInventoryObserver); + } +} class LLDiscardAgentOffer : public LLInventoryFetchComboObserver { @@ -655,7 +681,71 @@ protected: }; -void open_offer(const std::vector<LLUUID>& items) +//Returns TRUE if we are OK, FALSE if we are throttled +//Set check_only true if you want to know the throttle status +//without registering a hit -Gigs +bool check_offer_throttle(const std::string& from_name, bool check_only) +{ + static U32 throttle_count; + static bool throttle_logged; + LLChat chat; + LLString log_message; + + if (!gSavedSettings.getBOOL("ShowNewInventory")) + return false; + + if (check_only) + { + return gThrottleTimer.hasExpired(); + } + + if(gThrottleTimer.checkExpirationAndReset(OFFER_THROTTLE_TIME)) + { + //llinfos << "Throttle Expired" << llendl; + throttle_count=1; + throttle_logged=false; + return true; + } + else //has not expired + { + //llinfos << "Throttle Not Expired, Count: " << throttle_count << llendl; + // When downloading the initial inventory we get a lot of new items + // coming in and can't tell that from spam. JC + if (gStartupState >= STATE_STARTED + && throttle_count >= OFFER_THROTTLE_MAX_COUNT) + { + if (!throttle_logged) + { + // Use the name of the last item giver, who is probably the person + // spamming you. JC + std::ostringstream message; + message << gSecondLife; + if (!from_name.empty()) + { + message << ": Items coming in too fast from " << from_name; + } + else + { + message << ": Items coming in too fast"; + } + message << ", automatic preview disabled for " + << OFFER_THROTTLE_TIME << " seconds."; + chat.mText = message.str(); + //this is kinda important, so actually put it on screen + LLFloaterChat::addChat(chat, FALSE, FALSE); + throttle_logged=true; + } + return false; + } + else + { + throttle_count++; + return true; + } + } +} + +void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) { std::vector<LLUUID>::const_iterator it = items.begin(); std::vector<LLUUID>::const_iterator end = items.end(); @@ -673,33 +763,66 @@ void open_offer(const std::vector<LLUUID>& items) { continue; } - switch(item->getType()) - { - case LLAssetType::AT_NOTECARD: - open_notecard(*it, LLString("Note: ") + item->getName(), TRUE, LLUUID::null, FALSE); - break; - case LLAssetType::AT_LANDMARK: - open_landmark(*it, LLString("Landmark: ") + item->getName(), TRUE, LLUUID::null, FALSE); - break; - case LLAssetType::AT_TEXTURE: - open_texture(*it, LLString("Texture: ") + item->getName(), TRUE, LLUUID::null, FALSE); - break; - default: + //if we are throttled, don't display them - Gigs + if (check_offer_throttle(from_name, false)) { - // Don't auto-open the inventory - just select it if we - // already have an active inventory. - LLInventoryView* view = LLInventoryView::getActiveInventory(); - if(view) + // I'm not sure this is a good idea. JC + // bool show_keep_discard = item->getPermissions().getCreator() != gAgent.getID(); + bool show_keep_discard = true; + switch(item->getType()) { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLFocusMgr::FocusLostCallback callback; - callback = gFocusMgr.getFocusCallback(); - view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); - gFocusMgr.setKeyboardFocus(focus_ctrl, callback); + case LLAssetType::AT_NOTECARD: + open_notecard(*it, LLString("Note: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); + break; + case LLAssetType::AT_LANDMARK: + open_landmark(*it, LLString("Landmark: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); + break; + case LLAssetType::AT_TEXTURE: + open_texture(*it, LLString("Texture: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); + break; + default: break; } } + //highlight item, if it's not in the trash or lost+found + + // Don't auto-open the inventory floater + LLInventoryView* view = LLInventoryView::getActiveInventory(); + if(!view) + { + return; + } + + //Trash Check + LLUUID trash_id; + trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); + if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) + { + return; } + LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + //BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view); + BOOL user_is_away = gAwayTimer.getStarted(); + + // don't select lost and found items if the user is active + if (gInventory.isObjectDescendentOf(item->getUUID(), lost_and_found_id) + && !user_is_away) + { + return; + } + + //Not sure about this check. Could make it easy to miss incoming items. -Gigs + //don't dick with highlight while the user is working + //if(inventory_has_focus && !user_is_away) + // break; + //llinfos << "Highlighting" << item->getUUID() << llendl; + //highlight item + + LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); + LLFocusMgr::FocusLostCallback callback; + callback = gFocusMgr.getFocusCallback(); + view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); + gFocusMgr.setKeyboardFocus(focus_ctrl, callback); } } @@ -787,11 +910,11 @@ void inventory_offer_callback(S32 option, void* user_data) char group_name[MAX_STRING]; /* Flawfinder: ignore */ if (gCacheName->getGroupName(info->mFromID, group_name)) { - from_string = LLString("An object named ") + info->mFromName + " owned by the group '" + group_name + "'"; + from_string = LLString("An object named '") + info->mFromName + "' owned by the group '" + group_name + "'"; } else { - from_string = LLString("An object named ") + info->mFromName + " owned by an unknown group"; + from_string = LLString("An object named '") + info->mFromName + "' owned by an unknown group"; } } else @@ -800,11 +923,11 @@ void inventory_offer_callback(S32 option, void* user_data) char last_name[MAX_STRING]; /* Flawfinder: ignore */ if (gCacheName->getName(info->mFromID, first_name, last_name)) { - from_string = LLString("An object named ") + info->mFromName + " owned by " + first_name + " " + last_name; + from_string = LLString("An object named '") + info->mFromName + "' owned by " + first_name + " " + last_name; } else { - from_string = LLString("An object named ") + info->mFromName + " owned by an unknown user"; + from_string = LLString("An object named '") + info->mFromName + "' owned by an unknown user"; } } } @@ -813,9 +936,11 @@ void inventory_offer_callback(S32 option, void* user_data) from_string = info->mFromName; } + bool busy=FALSE; + switch(option) { - case 0: + case IOR_ACCEPT: // ACCEPT. The math for the dialog works, because the accept // for inventory_offered, task_inventory_offer or // group_notice_inventory is 1 greater than the offer integer value. @@ -826,9 +951,15 @@ void inventory_offer_callback(S32 option, void* user_data) sizeof(info->mFolderID.mData)); // send the message msg->sendReliable(info->mHost); - log_message = info->mFromName + " gave you " + info->mDesc + "."; - chat.mText = log_message; - LLFloaterChat::addChatHistory(chat); + + //don't spam them if they are getting flooded + if (check_offer_throttle(info->mFromName, true)) + { + log_message = info->mFromName + " gave you " + info->mDesc + "."; + chat.mText = log_message; + LLFloaterChat::addChatHistory(chat); + } + // we will want to open this item when it comes back. lldebugs << "Initializing an opener for tid: " << info->mTransactionID << llendl; @@ -841,7 +972,7 @@ void inventory_offer_callback(S32 option, void* user_data) // so we can fetch it out of our inventory. LLInventoryFetchObserver::item_ref_t items; items.push_back(info->mObjectID); - LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer; + LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string); open_agent_offer->fetchItems(items); if(catp || (itemp && itemp->isComplete())) { @@ -857,22 +988,10 @@ void inventory_offer_callback(S32 option, void* user_data) case IM_GROUP_NOTICE: case IM_GROUP_NOTICE_REQUESTED: { - // This is an offer from a task or group. - // Because it would be easy - // to write a task which would overload your inventory, we - // force the offer to stay in an instant message until - // accepted. Thus, we have to respond, and then wait for - // the update to come back before we open the item. - LLOpenTaskOffer* open_task_offer = new LLOpenTaskOffer; - open_task_offer->watchItem(info->mObjectID); - if(itemp && itemp->isComplete()) - { - opener->changed(0x0); - } - else - { - opener = open_task_offer; - } + // This is an offer from a task or group. + // We don't use a new instance of an opener + // We instead use the singular observer gOpenTaskOffer + // Since it already exists, we don't need to actually do anything } break; default: @@ -881,9 +1000,12 @@ void inventory_offer_callback(S32 option, void* user_data) } break; - case 2: + case IOR_BUSY: + //Busy falls through to decline. Says to make busy message. + busy=TRUE; + case IOR_MUTE: // MUTE falls through to decline - case 1: + case IOR_DECLINE: // DECLINE. The math for the dialog works, because the decline // for inventory_offered, task_inventory_offer or // group_notice_inventory is 2 greater than the offer integer value. @@ -921,7 +1043,7 @@ void inventory_offer_callback(S32 option, void* user_data) } } - if (!info->mFromGroup && !info->mFromObject) + if (busy || (!info->mFromGroup && !info->mFromObject)) { busy_message(msg,info->mFromID); } @@ -944,88 +1066,81 @@ void inventory_offer_callback(S32 option, void* user_data) void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) { - switch(info->mType) + + //Until throttling is implmented, busy mode should reject inventory instead of silently + //accepting it. SEE SL-39554 + if (gAgent.getBusy()) + { + inventory_offer_callback(IOR_BUSY, info); + return; + } + + //If muted, don't even go through the messaging stuff. Just curtail the offer here. + if (gMuteListp->isMuted(info->mFromID, info->mFromName)) + { + inventory_offer_callback(IOR_MUTE, info); + return; + } + + if (gSavedSettings.getBOOL("ShowNewInventory") + && (info->mType == LLAssetType::AT_NOTECARD + || info->mType == LLAssetType::AT_LANDMARK + || info->mType == LLAssetType::AT_TEXTURE)) { // For certain types, just accept the items into the inventory, // and we'll automatically open them on receipt. - case LLAssetType::AT_NOTECARD: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_TEXTURE: - { - // 0 = accept button - inventory_offer_callback(0, info); - //LLInventoryView::sOpenNextNewItem = TRUE; - } - break; - - case LLAssetType::AT_SOUND: - case LLAssetType::AT_CALLINGCARD: - case LLAssetType::AT_SCRIPT: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_OBJECT: - case LLAssetType::AT_CATEGORY: - case LLAssetType::AT_ROOT_CATEGORY: - case LLAssetType::AT_LSL_TEXT: - case LLAssetType::AT_LSL_BYTECODE: - case LLAssetType::AT_TEXTURE_TGA: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_TRASH: - case LLAssetType::AT_SNAPSHOT_CATEGORY: - case LLAssetType::AT_LOST_AND_FOUND: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - default: - { - LLString::format_map_t args; - args["[OBJECTNAME]"] = info->mDesc; - args["[OBJECTTYPE]"] = LLAssetType::lookupHumanReadable(info->mType); - - // Name cache callbacks don't store userdata, so can't save - // off the LLOfferInfo. Argh. JC - BOOL name_found = FALSE; - char first_name[MAX_STRING]; /* Flawfinder: ignore */ - char last_name[MAX_STRING]; /* Flawfinder: ignore */ - if (info->mFromGroup) - { - if (gCacheName->getGroupName(info->mFromID, first_name)) - { - args["[FIRST]"] = first_name; - args["[LAST]"] = ""; - name_found = TRUE; - } - } - else - { - if (gCacheName->getName(info->mFromID, first_name, last_name)) - { - args["[FIRST]"] = first_name; - args["[LAST]"] = last_name; - name_found = TRUE; - } - } - if (from_task) - { - args["[OBJECTFROMNAME]"] = info->mFromName; - if (name_found) - { - LLNotifyBox::showXml("ObjectGiveItem", args, - &inventory_offer_callback, (void*)info); - } - else - { - LLNotifyBox::showXml("ObjectGiveItemUnknownUser", args, - &inventory_offer_callback, (void*)info); - } - } - else - { - // XUI:translate -> [FIRST] [LAST] - args["[NAME]"] = info->mFromName; - LLNotifyBox::showXml("UserGiveItem", args, - &inventory_offer_callback, (void*)info); - } - break; - } + // 0 = accept button + inventory_offer_callback(IOR_ACCEPT, info); + return; + } + + LLString::format_map_t args; + args["[OBJECTNAME]"] = info->mDesc; + args["[OBJECTTYPE]"] = LLAssetType::lookupHumanReadable(info->mType); + + // Name cache callbacks don't store userdata, so can't save + // off the LLOfferInfo. Argh. JC + BOOL name_found = FALSE; + char first_name[MAX_STRING]; /* Flawfinder: ignore */ + char last_name[MAX_STRING]; /* Flawfinder: ignore */ + if (info->mFromGroup) + { + if (gCacheName->getGroupName(info->mFromID, first_name)) + { + args["[FIRST]"] = first_name; + args["[LAST]"] = ""; + name_found = TRUE; + } + } + else + { + if (gCacheName->getName(info->mFromID, first_name, last_name)) + { + args["[FIRST]"] = first_name; + args["[LAST]"] = last_name; + name_found = TRUE; + } + } + if (from_task) + { + args["[OBJECTFROMNAME]"] = info->mFromName; + if (name_found) + { + LLNotifyBox::showXml("ObjectGiveItem", args, + &inventory_offer_callback, (void*)info); + } + else + { + LLNotifyBox::showXml("ObjectGiveItemUnknownUser", args, + &inventory_offer_callback, (void*)info); + } + } + else + { + // XUI:translate -> [FIRST] [LAST] + args["[NAME]"] = info->mFromName; + LLNotifyBox::showXml("UserGiveItem", args, + &inventory_offer_callback, (void*)info); } } @@ -1740,6 +1855,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_GOTO_URL: { + if (binary_bucket_size <= 0) + { + llwarns << "bad binary_bucket_size: " + << binary_bucket_size + << " - aborting function." << llendl; + return; + } + char* url = new char[binary_bucket_size]; if (url == NULL) { @@ -1965,16 +2088,22 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) { // automatically decline offer callingcard_offer_callback(1, (void*)offerdata); - return; + offerdata = NULL; // pointer was freed by callback + } + else + { + LLNotifyBox::showXml("OfferCallingCard", args, + &callingcard_offer_callback, (void*)offerdata); + offerdata = NULL; // pointer ownership transferred } - - LLNotifyBox::showXml("OfferCallingCard", args, - &callingcard_offer_callback, (void*)offerdata); } else { llwarns << "Calling card offer from an unknown source." << llendl; } + + delete offerdata; // !=NULL if we didn't give ownership away + offerdata = NULL; } void process_accept_callingcard(LLMessageSystem* msg, void**) @@ -3589,7 +3718,7 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) if (object) { LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation()); - if (!use_autopilot || (avatar->mIsSitting && avatar->getRoot() == object->getRoot())) + if (!use_autopilot || (avatar && avatar->mIsSitting && avatar->getRoot() == object->getRoot())) { //we're already sitting on this object, so don't autopilot } @@ -4982,9 +5111,10 @@ void onCovenantLoadComplete(LLVFS *vfs, if( (file_length > 19) && !strncmp( buffer, "Linden text version", 19 ) ) { - LLViewerTextEditor* editor = new LLViewerTextEditor("temp", - LLRect(0,0,0,0), - file_length+1); + LLViewerTextEditor* editor = + new LLViewerTextEditor("temp", + LLRect(0,0,0,0), + file_length+1); if( !editor->importBuffer( buffer ) ) { llwarns << "Problem importing estate covenant." << llendl; @@ -5000,27 +5130,32 @@ void onCovenantLoadComplete(LLVFS *vfs, } else { - if( gViewerStats ) - { - gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - } - - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || - LL_ERR_FILE_EMPTY == status) - { - covenant_text = "Estate covenant notecard is missing from database."; - } - else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) - { - covenant_text = "Insufficient permissions to view estate covenant."; - } - else - { - covenant_text = "Unable to load estate covenant at this time."; - } - - llwarns << "Problem loading notecard: " << status << llendl; + llwarns << "Problem importing estate covenant: Covenant file format error." << llendl; + covenant_text = "Problem importing estate covenant: Covenant file format error."; + } + } + else + { + if( gViewerStats ) + { + gViewerStats->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); } + + if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || + LL_ERR_FILE_EMPTY == status) + { + covenant_text = "Estate covenant notecard is missing from database."; + } + else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) + { + covenant_text = "Insufficient permissions to view estate covenant."; + } + else + { + covenant_text = "Unable to load estate covenant at this time."; + } + + llwarns << "Problem loading notecard: " << status << llendl; } LLPanelEstateCovenant::updateCovenantText(covenant_text, asset_uuid); LLPanelLandCovenant::updateCovenantText(covenant_text); diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 04fb668aba..ccfd1f7277 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -28,6 +28,14 @@ class LLViewerRegion; // Prototypes // +enum InventoryOfferResponse +{ + IOR_ACCEPT, + IOR_DECLINE, + IOR_MUTE, + IOR_BUSY +}; + BOOL can_afford_transaction(S32 cost); void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group = FALSE, S32 trx_type = TRANS_GIFT, const LLString& desc = LLString::null); @@ -170,6 +178,7 @@ void invalid_message_callback(LLMessageSystem*, void*, EMessageException); void process_initiate_download(LLMessageSystem* msg, void**); void inventory_offer_callback(S32 option, void* user_data); +void start_new_inventory_observer(); struct LLOfferInfo { diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 7ae166849b..bf4ad172e6 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -619,10 +619,10 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) } U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp) + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp) { LLMemType mt(LLMemType::MTYPE_OBJECT); @@ -638,6 +638,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, from_region_handle(region_handle, &x, &y); llerrs << "Object has invalid region " << x << ":" << y << "!" << llendl; + return retval; } U16 time_dilation16; @@ -914,7 +915,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Check for appended generic data S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data); - if (data_size == 0) + if (data_size <= 0) { mData = NULL; } @@ -1737,9 +1738,16 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, if (gPingInterpolate) { LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); - F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped); - LLVector3 diff = getVelocity() * (0.5f*mTimeDilation*(gFrameDTClamped + ((F32)ping_delay)*0.001f)); - new_pos_parent += diff; + if (cdp) + { + F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped); + LLVector3 diff = getVelocity() * (0.5f*mTimeDilation*(gFrameDTClamped + ((F32)ping_delay)*0.001f)); + new_pos_parent += diff; + } + else + { + llwarns << "findCircuit() returned NULL; skipping interpolation" << llendl; + } } ////////////////////////// @@ -4114,7 +4122,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow { return; } - + if (audio_uuid.isNull()) { if (mAudioSourcep && mAudioSourcep->isLoop() && !mAudioSourcep->hasPendingPreloads()) @@ -4149,7 +4157,8 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow } } - if ( mAudioSourcep ) + // don't clean up before previous sound is done. Solves: SL-33486 + if ( mAudioSourcep && mAudioSourcep->isDone() ) { gAudiop->cleanupAudioSource(mAudioSourcep); mAudioSourcep = NULL; diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index f5d7aa1094..58785805b2 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -465,20 +465,21 @@ void LLViewerParcelOverlay::updatePropertyLines() // shuffling. S32 new_vertex_count = new_vertex_array.count(); - // NOTE: If the new_vertex_count is 0 and wasn't 0 previously - // the arrays are still allocated as the arrays aren't set to NULL, etc. - // This won't cause any problems, but might waste a few cycles copying over - // old data. - jwolk - if ( !(mVertexArray && mColorArray && new_vertex_count == mVertexCount) && new_vertex_count > 0 ) + if (!(mVertexArray && mColorArray && new_vertex_count == mVertexCount)) { // ...need new arrays delete[] mVertexArray; + mVertexArray = NULL; delete[] mColorArray; + mColorArray = NULL; mVertexCount = new_vertex_count; - mVertexArray = new F32[3 * mVertexCount]; - mColorArray = new U8 [4 * mVertexCount]; + if (new_vertex_count > 0) + { + mVertexArray = new F32[3 * mVertexCount]; + mColorArray = new U8 [4 * mVertexCount]; + } } // Copy the new data into the arrays diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index de67506e3f..f2cf4b3dc6 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -106,6 +106,13 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, } llassert(mSurfacep); + + if (!mSurfacep || !mSurfacep->getRegion()) + { + // We don't always have the region yet here.... + return FALSE; + } + S32 x_begin, y_begin, x_end, y_end; x_begin = llround( x * mScaleInv ); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 2b821bed9f..1f1145624b 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1466,6 +1466,7 @@ void LLVOAvatar::initClass() if (!root) { llerrs << "No root node found in avatar configuration file: " << xmlFile << llendl; + return; } //------------------------------------------------------------------------- @@ -1873,6 +1874,7 @@ void LLVOAvatar::buildCharacter() mEyeRightp)) { llerrs << "Failed to create avatar." << llendl; + return; } //------------------------------------------------------------------------- @@ -2441,7 +2443,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) if (LLVOAvatar::sJointDebug) { - llinfos << getNVPair("FirstName")->getString() << getNVPair("LastName")->getString() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl; + llinfos << getFullname() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl; } LLJoint::sNumUpdates = 0; @@ -4789,7 +4791,7 @@ BOOL LLVOAvatar::allocateCollisionVolumes( U32 num ) LLJoint *LLVOAvatar::getCharacterJoint( U32 num ) { if ((S32)num >= mNumJoints - || num < 0) + || (S32)num < 0) { return NULL; } diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index 1e5caa17d4..7fc96975c9 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -106,6 +106,12 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) for ( ; face_indx < num_faces; face_indx++) { facep = drawable->getFace(face_indx); + if (!facep) + { + llwarns << "No facep for index " << face_indx << llendl; + continue; + } + if (isParticle()) { facep->setSize(1,1); @@ -123,6 +129,12 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) for ( ; face_indx < drawable->getNumFaces(); face_indx++) { facep = drawable->getFace(face_indx); + if (!facep) + { + llwarns << "No facep for index " << face_indx << llendl; + continue; + } + facep->setTEOffset(face_indx); facep->setSize(0,0); } diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index b641bf6f27..c0df55b670 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -131,7 +131,7 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) if (!num_parts) { - if (drawable->getNumFaces()) + if (group && drawable->getNumFaces()) { group->dirtyGeom(); } @@ -186,6 +186,12 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) count++; facep = drawable->getFace(i); + if (!facep) + { + llwarns << "No face found for index " << i << "!" << llendl; + continue; + } + facep->setTEOffset(i); const F32 NEAR_PART_DIST_SQ = 5.f*5.f; // Only discard particles > 5 m from the camera const F32 MIN_PART_AREA = .005f*.005f; // only less than 5 mm x 5 mm at 1 m from camera @@ -239,6 +245,11 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) for (i = count; i < drawable->getNumFaces(); i++) { LLFace* facep = drawable->getFace(i); + if (!facep) + { + llwarns << "No face found for index " << i << "!" << llendl; + continue; + } facep->setTEOffset(i); facep->setSize(0,0); } diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp index 428df0b45a..b24e222570 100644 --- a/indra/newview/llwindebug.cpp +++ b/indra/newview/llwindebug.cpp @@ -111,6 +111,8 @@ BOOL LLWinDebug::setupExceptionHandler() if (!f_mdwp) { write_debug("No MiniDumpWriteDump!\n"); + FreeLibrary(hDll); + hDll = NULL; ok = FALSE; } } diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 59587ef13c..e61b5f1af5 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -471,7 +471,7 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) U32 agent_flags; msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags); - if (agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES) + if ((S32)agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES) { llwarns << "Invalid map image type returned! " << agent_flags << llendl; return; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 43c587ed92..bb0efb48e1 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -748,6 +748,7 @@ void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) if (!drawablep) { llerrs << "updateMove called with NULL drawablep" << llendl; + return; } if (drawablep->isState(LLDrawable::EARLY_MOVE)) { @@ -1104,7 +1105,7 @@ void LLPipeline::updateGeom(F32 max_dtime) last_bridge = bridge; BOOL update_complete = TRUE; - if (drawablep && !drawablep->isDead()) + if (!drawablep->isDead()) { update_complete = updateDrawableGeom(drawablep, FALSE); count++; @@ -1378,7 +1379,9 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) LLMemType mt(LLMemType::MTYPE_PIPELINE); LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE); - if (drawablep->isDead() || !hasRenderType(drawablep->getRenderType())) + if (!drawablep + || drawablep->isDead() + || !hasRenderType(drawablep->getRenderType())) { return; } @@ -1392,7 +1395,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } } - if (drawablep && (hasRenderType(drawablep->mRenderType))) + if (hasRenderType(drawablep->mRenderType)) { if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE)) { @@ -1815,6 +1818,7 @@ void LLPipeline::renderHighlights() if (!facep || facep->getDrawable()->isDead()) { llerrs << "Bad face on selection" << llendl; + return; } facep->renderSelected(mFaceSelectImagep, color); @@ -4025,4 +4029,4 @@ void LLPipeline::renderBloom(GLuint source, GLuint dest, GLuint buffer, U32 res, glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); -}
\ No newline at end of file +} diff --git a/indra/test/llhttpclient_tut.cpp b/indra/test/llhttpclient_tut.cpp index b169499543..17bad4bc14 100644 --- a/indra/test/llhttpclient_tut.cpp +++ b/indra/test/llhttpclient_tut.cpp @@ -78,7 +78,7 @@ namespace tut void setupTheServer() { - LLHTTPNode& root = LLCreateHTTPServer(mPool, *mServerPump, 8888); + LLHTTPNode& root = LLIOHTTPServer::create(mPool, *mServerPump, 8888); LLHTTPStandardServices::useServices(); LLHTTPRegistrar::buildAllServices(root); diff --git a/indra/test/lliohttpserver_tut.cpp b/indra/test/lliohttpserver_tut.cpp index 2f64cc81d7..e0001438c7 100644 --- a/indra/test/lliohttpserver_tut.cpp +++ b/indra/test/lliohttpserver_tut.cpp @@ -97,7 +97,7 @@ namespace tut LLSD context; chain.push_back(LLIOPipe::ptr_t(injector)); - LLCreateHTTPPipe(chain, mRoot, LLSD()); + LLIOHTTPServer::createPipe(chain, mRoot, LLSD()); chain.push_back(LLIOPipe::ptr_t(extractor)); pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS); diff --git a/indra/win_crash_logger/win_crash_logger.cpp b/indra/win_crash_logger/win_crash_logger.cpp index 848d4006fd..8760ae43f8 100644 --- a/indra/win_crash_logger/win_crash_logger.cpp +++ b/indra/win_crash_logger/win_crash_logger.cpp @@ -180,7 +180,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, { i++; - mbstowcs(gProductName, argv[i], sizeof(gProductName)); + mbstowcs(gProductName, argv[i], sizeof(gProductName)/sizeof(gProductName[0])); + gProductName[ sizeof(gProductName)/sizeof(gProductName[0]) - 1 ] = 0; llinfos << "Got product name " << argv[i] << llendl; } } @@ -369,6 +370,7 @@ class LLFileEncoder { public: LLFileEncoder(const char *formname, const char *filename); + ~LLFileEncoder(); BOOL isValid() const { return mIsValid; } LLString encodeURL(const S32 max_length = 0); @@ -817,6 +819,15 @@ LLFileEncoder::LLFileEncoder(const char *form_name, const char *filename) mIsValid = TRUE; } +LLFileEncoder::~LLFileEncoder() +{ + if (mBuf) + { + delete mBuf; + mBuf = NULL; + } +} + LLString LLFileEncoder::encodeURL(const S32 max_length) { LLString result = mFormname; |