diff options
144 files changed, 3437 insertions, 2643 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index 6cb0a4e8d9..ed9b2fe146 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -2,25 +2,28 @@ Linden Lab would like to acknowledge source code contributions from the following residents. The Second Life resident name is given below, along with the issue identifier corresponding to the patches we've received from them. To see more about these contributions, visit -http://jira.secondlife.com/ , and enter the issue identifier. +http://jira.secondlife.com/ and enter the issue identifier. Alissa Sabre - VWR-81, VWR-83, VWR-414 blino Nakamura - VWR-17 +bushing Spatula - VWR-424 Drewan Keats - VWR-28 Dylan Haskell - VWR-72 Dzonatas Sol - VWR-198 Eddy Stryker - VWR-15, VWR-23 +Gigs Taggart - VWR-71 Ginko Bayliss - VWR-4 Hikkoshi Sakai - VWR-429 -Hiro Sommambulist - VWR-66, VWR-97, VWR-100, VWR-105, VWR-108, VWR-118 -Jacek Antonelli - VWR-188 +Hiro Sommambulist - VWR-66, VWR-97, VWR-100, VWR-105, VWR-108, VWR-118, VWR-136 +Jacek Antonelli - VWR-165, VWR-188 Joghert LeSabre - VWR-64 Kage Pixel - VWR-11 Kunnis Basiat - VWR-82 Paul Churchill - VWR-20 Paula Innis - VWR-30 Peekay Semyorka - VWR-7, VWR-19, VWR-49 +SignpostMarv Martin - VWR-155 SpacedOut Frye - VWR-57, VWR-94, VWR-121, VWR-123 -Strife Onizuka - VWR-74, VWR-85, SVC-9 +Strife Onizuka - SVC-9, VWR-74, VWR-85, VWR-148 Zipherius Turas - VWR-76, VWR-77 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; |