diff options
65 files changed, 760 insertions, 446 deletions
| diff --git a/doc/contributions.txt b/doc/contributions.txt index a2c1218039..8b040d333e 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -368,15 +368,17 @@ JB Kraft  Joghert LeSabre  	VWR-64  Jonathan Yap -	STORM-596  	STORM-523 +	STORM-596 +	STORM-615  	STORM-616  	STORM-679 -	STORM-737 +	STORM-723  	STORM-726 +	STORM-737 +	STORM-785  	STORM-812  	VWR-17801 -	STORM-785  Kage Pixel  	VWR-11  Ken March diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 7ce57a5572..012d3c2ab2 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -10,6 +10,8 @@ if (STANDALONE)    set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-mt)    set(BOOST_REGEX_LIBRARY boost_regex-mt)    set(BOOST_SIGNALS_LIBRARY boost_signals-mt) +  set(BOOST_SYSTEM_LIBRARY boost_system-mt) +  set(BOOST_FILESYSTEM_LIBRARY boost_filesystem-mt)  else (STANDALONE)    use_prebuilt_binary(boost)    set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) @@ -26,6 +28,12 @@ else (STANDALONE)        set(BOOST_SIGNALS_LIBRARY             optimized libboost_signals-vc71-mt-s-${BOOST_VERSION}            debug libboost_signals-vc71-mt-sgd-${BOOST_VERSION}) +      set(BOOST_SYSTEM_LIBRARY  +          optimized libboost_system-vc71-mt-s-${BOOST_VERSION} +          debug libboost_system-vc71-mt-sgd-${BOOST_VERSION}) +      set(BOOST_FILESYSTEM_LIBRARY  +          optimized libboost_filesystem-vc71-mt-s-${BOOST_VERSION} +          debug libboost_filesystem-vc71-mt-sgd-${BOOST_VERSION})      else (MSVC71)        set(BOOST_PROGRAM_OPTIONS_LIBRARY             optimized libboost_program_options-vc80-mt-${BOOST_VERSION} @@ -36,14 +44,24 @@ else (STANDALONE)        set(BOOST_SIGNALS_LIBRARY             optimized libboost_signals-vc80-mt-${BOOST_VERSION}            debug libboost_signals-vc80-mt-gd-${BOOST_VERSION}) +      set(BOOST_SYSTEM_LIBRARY  +          optimized libboost_system-vc80-mt-${BOOST_VERSION} +          debug libboost_system-vc80-mt-gd-${BOOST_VERSION}) +      set(BOOST_FILESYSTEM_LIBRARY  +          optimized libboost_filesystem-vc80-mt-${BOOST_VERSION} +          debug libboost_filesystem-vc80-mt-gd-${BOOST_VERSION})      endif (MSVC71)    elseif (DARWIN)      set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-xgcc40-mt)      set(BOOST_REGEX_LIBRARY boost_regex-xgcc40-mt)      set(BOOST_SIGNALS_LIBRARY boost_signals-xgcc40-mt) +    set(BOOST_SYSTEM_LIBRARY boost_system-xgcc40-mt) +    set(BOOST_FILESYSTEM_LIBRARY boost_filesystem-xgcc40-mt)    elseif (LINUX)      set(BOOST_PROGRAM_OPTIONS_LIBRARY boost_program_options-gcc41-mt)      set(BOOST_REGEX_LIBRARY boost_regex-gcc41-mt)      set(BOOST_SIGNALS_LIBRARY boost_signals-gcc41-mt) +    set(BOOST_SYSTEM_LIBRARY boost_system-gcc41-mt) +    set(BOOST_FILESYSTEM_LIBRARY boost_filesystem-gcc41-mt)    endif (WINDOWS)  endif (STANDALONE) diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp index c34115ee80..217e26c3ca 100644 --- a/indra/integration_tests/llui_libtest/llui_libtest.cpp +++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp @@ -33,6 +33,7 @@  // linden library includes  #include "llcontrol.h"		// LLControlGroup  #include "lldir.h" +#include "lldiriterator.h"  #include "llerrorcontrol.h"  #include "llfloater.h"  #include "llfontfreetype.h" @@ -174,7 +175,9 @@ void export_test_floaters()  	std::string delim = gDirUtilp->getDirDelimiter();  	std::string xui_dir = get_xui_dir() + "en" + delim;  	std::string filename; -	while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename)) + +	LLDirIterator iter(xui_dir, "floater_test_*.xml"); +	while (iter.next(filename))  	{  		if (filename.find("_new.xml") != std::string::npos)  		{ diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp index d909516bf8..808ab3f64f 100644 --- a/indra/linux_updater/linux_updater.cpp +++ b/indra/linux_updater/linux_updater.cpp @@ -33,6 +33,7 @@  #include "llerrorcontrol.h"  #include "llfile.h"  #include "lldir.h" +#include "lldiriterator.h"  #include "llxmlnode.h"  #include "lltrans.h" @@ -55,6 +56,8 @@ typedef struct _updater_app_state {  	std::string strings_dirs;  	std::string strings_file; +	LLDirIterator *image_dir_iter; +  	GtkWidget *window;  	GtkWidget *progress_bar;  	GtkWidget *image; @@ -108,7 +111,7 @@ bool translate_init(std::string comma_delim_path_list,  void updater_app_ui_init(void);  void updater_app_quit(UpdaterAppState *app_state);  void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state); -std::string next_image_filename(std::string& image_path); +std::string next_image_filename(std::string& image_path, LLDirIterator& iter);  void display_error(GtkWidget *parent, std::string title, std::string message);  BOOL install_package(std::string package_file, std::string destination);  BOOL spawn_viewer(UpdaterAppState *app_state); @@ -174,7 +177,7 @@ void updater_app_ui_init(UpdaterAppState *app_state)  		// load the first image  		app_state->image = gtk_image_new_from_file -			(next_image_filename(app_state->image_dir).c_str()); +			(next_image_filename(app_state->image_dir, *app_state->image_dir_iter).c_str());  		gtk_widget_set_size_request(app_state->image, 340, 310);  		gtk_container_add(GTK_CONTAINER(frame), app_state->image); @@ -205,7 +208,7 @@ gboolean rotate_image_cb(gpointer data)  	llassert(data != NULL);  	app_state = (UpdaterAppState *) data; -	filename = next_image_filename(app_state->image_dir); +	filename = next_image_filename(app_state->image_dir, *app_state->image_dir_iter);  	gdk_threads_enter();  	gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str()); @@ -214,10 +217,10 @@ gboolean rotate_image_cb(gpointer data)  	return TRUE;  } -std::string next_image_filename(std::string& image_path) +std::string next_image_filename(std::string& image_path, LLDirIterator& iter)  {  	std::string image_filename; -	gDirUtilp->getNextFileInDir(image_path, "/*.jpg", image_filename); +	iter.next(image_filename);  	return image_path + "/" + image_filename;  } @@ -741,6 +744,7 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)  		else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc))  		{  			app_state->image_dir = argv[i]; +			app_state->image_dir_iter = new LLDirIterator(argv[i], "/*.jpg");  		}  		else if ((!strcmp(argv[i], "--dest")) && (++i < argc))  		{ @@ -825,6 +829,7 @@ int main(int argc, char **argv)  	}  	bool success = !app_state->failure; +	delete app_state->image_dir_iter;  	delete app_state;  	return success ? 0 : 1;  } diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp index b46a6e03d2..3e2c05a6e6 100644 --- a/indra/llmath/llbbox.cpp +++ b/indra/llmath/llbbox.cpp @@ -89,6 +89,19 @@ void LLBBox::addBBoxAgent(const LLBBox& b)  	}  } +LLBBox LLBBox::getAxisAligned() const +{ +	// no rotation = axis aligned rotation +	LLBBox aligned(mPosAgent, LLQuaternion(), LLVector3(), LLVector3()); + +	// add the center point so that it's not empty +	aligned.addPointAgent(mPosAgent); + +	// add our BBox +	aligned.addBBoxAgent(*this); + +	return aligned; +}  void LLBBox::expand( F32 delta )  { @@ -147,6 +160,15 @@ BOOL LLBBox::containsPointAgent(const LLVector3& p) const  	return containsPointLocal(point_local);  } +LLVector3 LLBBox::getMinAgent() const +{ +	return localToAgent(mMinLocal); +} + +LLVector3 LLBBox::getMaxAgent() const +{ +	return localToAgent(mMaxLocal); +}  /*  LLBBox operator*(const LLBBox &a, const LLMatrix4 &b) diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h index 5b911793f0..28e69b75e1 100644 --- a/indra/llmath/llbbox.h +++ b/indra/llmath/llbbox.h @@ -51,9 +51,11 @@ public:  	const LLVector3&	getPositionAgent() const			{ return mPosAgent; }  	const LLQuaternion&	getRotation() const					{ return mRotation; } +	LLVector3           getMinAgent() const;  	const LLVector3&	getMinLocal() const					{ return mMinLocal; }  	void				setMinLocal( const LLVector3& min )	{ mMinLocal = min; } +	LLVector3           getMaxAgent() const;  	const LLVector3&	getMaxLocal() const					{ return mMaxLocal; }  	void				setMaxLocal( const LLVector3& max )	{ mMaxLocal = max; } @@ -80,6 +82,8 @@ public:  	LLVector3			localToAgentBasis(const LLVector3& v) const;  	LLVector3			agentToLocalBasis(const LLVector3& v) const; +	// Get the smallest possible axis aligned bbox that contains this bbox +	LLBBox              getAxisAligned() const;  //	friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b); diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index b9b974ec4f..7b796a0fa8 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -42,9 +42,6 @@ const U32 REGION_FLAGS_RESET_HOME_ON_TELEPORT	= (1 << 3);  // Does the sun move?  const U32 REGION_FLAGS_SUN_FIXED				= (1 << 4); -// Tax free zone (no taxes on objects, land, etc.) -const U32 REGION_FLAGS_TAX_FREE					= (1 << 5); -  // Can't change the terrain heightfield, even on owned parcels,  // but can plant trees and grass.  const U32 REGION_FLAGS_BLOCK_TERRAFORM			= (1 << 6); @@ -54,17 +51,12 @@ const U32 REGION_FLAGS_BLOCK_LAND_RESELL		= (1 << 7);  // All content wiped once per night  const U32 REGION_FLAGS_SANDBOX					= (1 << 8); -const U32 REGION_FLAGS_NULL_LAYER				= (1 << 9); -// const U32 REGION_FLAGS_SKIP_AGENT_ACTION		= (1 << 10); -const U32 REGION_FLAGS_HARD_ALLOW_LAND_TRANSFER	= (1 << 10);	// Region allows land reselling -// const U32 REGION_FLAGS_SKIP_UPDATE_INTEREST_LIST= (1 << 11); -const U32 REGION_FLAGS_HARD_ALLOW_POST_CLASSIFIED	= (1 << 11);	// Region allows posting of classified ads  const U32 REGION_FLAGS_SKIP_COLLISIONS			= (1 << 12); // Pin all non agent rigid bodies  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_PUBLIC_ALLOWED			= (1 << 17); +const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16); +const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17);  const U32 REGION_FLAGS_BLOCK_DWELL				= (1 << 18);  // Is flight allowed? @@ -81,18 +73,13 @@ const U32 REGION_FLAGS_ESTATE_SKIP_SCRIPTS		= (1 << 21);  const U32 REGION_FLAGS_RESTRICT_PUSHOBJECT		= (1 << 22);  const U32 REGION_FLAGS_DENY_ANONYMOUS			= (1 << 23); -// const U32 REGION_FLAGS_DENY_IDENTIFIED			= (1 << 24); -// const U32 REGION_FLAGS_DENY_TRANSACTED			= (1 << 25);  const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES		= (1 << 26); -// const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); // We no longer support ELAR -  const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28);  const U32 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29);  const U32 REGION_FLAGS_DENY_AGEUNVERIFIED	= (1 << 30); -const U32 REGION_FLAGS_SKIP_MONO_SCRIPTS	= (1 << 31);  const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK |  								 REGION_FLAGS_ALLOW_SET_HOME | @@ -105,7 +92,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_PUBLIC_ALLOWED	  									 | REGION_FLAGS_SUN_FIXED  									 | REGION_FLAGS_DENY_ANONYMOUS  									 | REGION_FLAGS_DENY_AGEUNVERIFIED; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index d30697e178..c425782715 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -272,9 +272,6 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)  	initFromParams(p); -	// chrome floaters don't take focus at all -	setFocusRoot(!getIsChrome()); -  	initFloater(p);  } @@ -2910,8 +2907,6 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str  	params.from_xui = true;  	applyXUILayout(params, parent);   	initFromParams(params); -	// chrome floaters don't take focus at all -	setFocusRoot(!getIsChrome());  	initFloater(params); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 6c0d47ef63..32d7be377a 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1637,6 +1637,10 @@ LLMenuScrollItem::LLMenuScrollItem(const Params& p)  	}  	LLButton::Params bparams; + +	// Disabled the Return key handling by LLMenuScrollItem instead of +	// passing the key press to the currently selected menu item. See STORM-385. +	bparams.commit_on_return(false);  	bparams.mouse_opaque(true);  	bparams.scale_image(false);  	bparams.click_callback(p.scroll_callback); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 4f7b4be526..9db1feafd1 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -36,6 +36,7 @@  #include "llcachename.h"  #include "lltrans.h"  #include "lluicolortable.h" +#include "message.h"  #define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))" @@ -684,8 +685,8 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa  LLStyle::Params LLUrlEntryGroup::getStyle() const  {  	LLStyle::Params style_params = LLUrlEntryBase::getStyle(); -	style_params.color = LLUIColorTable::instance().getColor("GroupLinkColor"); -	style_params.readonly_color = LLUIColorTable::instance().getColor("GroupLinkColor"); +	style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor"); +	style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");  	return style_params;  } @@ -740,6 +741,13 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const  	return LLUrlEntryBase::getLocation(url);  } +// LLUrlEntryParcel statics. +LLUUID	LLUrlEntryParcel::sAgentID(LLUUID::null); +LLUUID	LLUrlEntryParcel::sSessionID(LLUUID::null); +LLHost	LLUrlEntryParcel::sRegionHost(LLHost::invalid); +bool	LLUrlEntryParcel::sDisconnected(false); +std::set<LLUrlEntryParcel*> LLUrlEntryParcel::sParcelInfoObservers; +  ///  /// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,  /// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about @@ -751,13 +759,88 @@ LLUrlEntryParcel::LLUrlEntryParcel()  							boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_parcel.xml";  	mTooltip = LLTrans::getString("TooltipParcelUrl"); + +	sParcelInfoObservers.insert(this); +} + +LLUrlEntryParcel::~LLUrlEntryParcel() +{ +	sParcelInfoObservers.erase(this);  }  std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)  { +	LLSD path_array = LLURI(url).pathArray(); +	S32 path_parts = path_array.size(); + +	if (path_parts < 3) // no parcel id +	{ +		llwarns << "Failed to parse url [" << url << "]" << llendl; +		return url; +	} + +	std::string parcel_id_string = unescapeUrl(path_array[2]); // parcel id + +	// Add an observer to call LLUrlLabelCallback when we have parcel name. +	addObserver(parcel_id_string, url, cb); + +	LLUUID parcel_id(parcel_id_string); + +	sendParcelInfoRequest(parcel_id); +  	return unescapeUrl(url);  } +void LLUrlEntryParcel::sendParcelInfoRequest(const LLUUID& parcel_id) +{ +	if (sRegionHost == LLHost::invalid || sDisconnected) return; + +	LLMessageSystem *msg = gMessageSystem; +	msg->newMessage("ParcelInfoRequest"); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, sAgentID ); +	msg->addUUID("SessionID", sSessionID); +	msg->nextBlock("Data"); +	msg->addUUID("ParcelID", parcel_id); +	msg->sendReliable(sRegionHost); +} + +void LLUrlEntryParcel::onParcelInfoReceived(const std::string &id, const std::string &label) +{ +	callObservers(id, label.empty() ? LLTrans::getString("RegionInfoError") : label, mIcon); +} + +// static +void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data) +{ +	std::string label(LLStringUtil::null); +	if (!parcel_data.name.empty()) +	{ +		label = parcel_data.name; +	} +	// If parcel name is empty use Sim_name (x, y, z) for parcel label. +	else if (!parcel_data.sim_name.empty()) +	{ +		S32 region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS; +		S32 region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS; +		S32 region_z = llround(parcel_data.global_z); + +		label = llformat("%s (%d, %d, %d)", +				parcel_data.sim_name.c_str(), region_x, region_y, region_z); +	} + +	for (std::set<LLUrlEntryParcel*>::iterator iter = sParcelInfoObservers.begin(); +			iter != sParcelInfoObservers.end(); +			++iter) +	{ +		LLUrlEntryParcel* url_entry = *iter; +		if (url_entry) +		{ +			url_entry->onParcelInfoReceived(parcel_data.parcel_id.asString(), label); +		} +	} +} +  //  // LLUrlEntryPlace Describes secondlife://<location> URLs  // diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 1791739061..5f82721c0f 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -31,6 +31,9 @@  #include "lluuid.h"  #include "lluicolor.h"  #include "llstyle.h" + +#include "llhost.h" // for resolving parcel name by parcel id +  #include <boost/signals2.hpp>  #include <boost/regex.hpp>  #include <string> @@ -285,8 +288,44 @@ private:  class LLUrlEntryParcel : public LLUrlEntryBase  {  public: +	struct LLParcelData +	{ +		LLUUID		parcel_id; +		std::string	name; +		std::string	sim_name; +		F32			global_x; +		F32			global_y; +		F32			global_z; +	}; +  	LLUrlEntryParcel(); +	~LLUrlEntryParcel();  	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); + +	// Sends a parcel info request to sim. +	void sendParcelInfoRequest(const LLUUID& parcel_id); + +	// Calls observers of certain parcel id providing them with parcel label. +	void onParcelInfoReceived(const std::string &id, const std::string &label); + +	// Processes parcel label and triggers notifying observers. +	static void processParcelInfo(const LLParcelData& parcel_data); + +	// Next 4 setters are used to update agent and viewer connection information +	// upon events like user login, viewer disconnect and user changing region host. +	// These setters are made public to be accessible from newview and should not be +	// used in other cases. +	static void setAgentID(const LLUUID& id) { sAgentID = id; } +	static void setSessionID(const LLUUID& id) { sSessionID = id; } +	static void setRegionHost(const LLHost& host) { sRegionHost = host; } +	static void setDisconnected(bool disconnected) { sDisconnected = disconnected; } + +private: +	static LLUUID						sAgentID; +	static LLUUID						sSessionID; +	static LLHost						sRegionHost; +	static bool							sDisconnected; +	static std::set<LLUrlEntryParcel*>	sParcelInfoObservers;  };  /// diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index f30704cb22..96ebe83826 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -30,6 +30,7 @@  #include "llavatarnamecache.h"  #include "llcachename.h"  #include "lluuid.h" +#include "message.h"  #include <string> @@ -191,3 +192,20 @@ LLFontGL* LLFontGL::getFontDefault()  {  	return NULL;   } + +char* _PREHASH_AgentData = "AgentData"; +char* _PREHASH_AgentID = "AgentID"; + +LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS); + +LLMessageSystem* gMessageSystem = NULL; + +// +// Stub implementation for LLMessageSystem +// +void LLMessageSystem::newMessage(const char *name) { } +void LLMessageSystem::nextBlockFast(const char *blockname) { } +void LLMessageSystem::nextBlock(const char *blockname) { } +void LLMessageSystem::addUUIDFast( const char *varname, const LLUUID& uuid) { } +void LLMessageSystem::addUUID( const char *varname, const LLUUID& uuid) { } +S32 LLMessageSystem::sendReliable(const LLHost &host) { return 0; } diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt index 569674ecf0..b6d1ce61e5 100644 --- a/indra/llvfs/CMakeLists.txt +++ b/indra/llvfs/CMakeLists.txt @@ -12,6 +12,7 @@ include_directories(  set(llvfs_SOURCE_FILES      lldir.cpp +    lldiriterator.cpp      lllfsthread.cpp      llpidlock.cpp      llvfile.cpp @@ -24,6 +25,7 @@ set(llvfs_HEADER_FILES      lldir.h      lldirguard.h +    lldiriterator.h      lllfsthread.h      llpidlock.h      llvfile.h @@ -60,6 +62,11 @@ list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES})  add_library (llvfs ${llvfs_SOURCE_FILES}) +target_link_libraries(llvfs +    ${BOOST_FILESYSTEM_LIBRARY} +    ${BOOST_SYSTEM_LIBRARY} +    ) +  if (DARWIN)    include(CMakeFindFrameworks)    find_library(CARBON_LIBRARY Carbon) diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 64556bcb4c..ab7d15dfef 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -40,6 +40,8 @@  #include "lltimer.h"	// ms_sleep()  #include "lluuid.h" +#include "lldiriterator.h" +  #if LL_WINDOWS  #include "lldir_win32.h"  LLDir_Win32 gDirUtil; @@ -83,7 +85,9 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)  	std::string filename;   	std::string fullpath;  	S32 result; -	while (getNextFileInDir(dirname, mask, filename)) + +	LLDirIterator iter(dirname, mask); +	while (iter.next(filename))  	{  		fullpath = dirname;  		fullpath += getDirDelimiter(); diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 42996fd051..5ee8bdb542 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -75,31 +75,6 @@ class LLDir  // pure virtual functions  	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0; -    /// Walk the files in a directory, with file pattern matching -	virtual BOOL getNextFileInDir(const std::string& dirname, ///< directory path - must end in trailing slash! -                                  const std::string& mask,    ///< file pattern string (use "*" for all) -                                  std::string& fname          ///< output: found file name -                                  ) = 0; -    /**< -     * @returns true if a file was found, false if the entire directory has been scanned. -     * -     * @note that this function is NOT thread safe -     * -     * This function may not be used to scan part of a directory, then start a new search of a different -     * directory, and then restart the first search where it left off; the entire search must run to -     * completion or be abandoned - there is no restart. -     * -     * @bug: See http://jira.secondlife.com/browse/VWR-23697 -     *       and/or the tests in test/lldir_test.cpp -     *       This is known to fail with patterns that have both: -     *       a wildcard left of a . and more than one sequential ? right of a . -     *       the pattern foo.??x appears to work -     *       but *.??x or foo?.??x do not -     * -     * @todo this really should be rewritten as an iterator object, and the -     *       filtering should be done in a platform-independent way. -     */ -  	virtual std::string getCurPath() = 0;  	virtual BOOL fileExists(const std::string &filename) const = 0; diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index 73f2336f94..4ba2f519b0 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -242,68 +242,6 @@ U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &  	return (file_count);  } -// get the next file in the directory -BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ -	glob_t g; -	BOOL result = FALSE; -	fname = ""; -	 -	if(!(dirname == mCurrentDir)) -	{ -		// different dir specified, close old search -		mCurrentDirIndex = -1; -		mCurrentDirCount = -1; -		mCurrentDir = dirname; -	} -	 -	std::string tmp_str; -	tmp_str = dirname; -	tmp_str += mask; - -	if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) -	{ -		if(g.gl_pathc > 0) -		{ -			if((int)g.gl_pathc != mCurrentDirCount) -			{ -				// Number of matches has changed since the last search, meaning a file has been added or deleted. -				// Reset the index. -				mCurrentDirIndex = -1; -				mCurrentDirCount = g.gl_pathc; -			} -	 -			mCurrentDirIndex++; -	 -			if(mCurrentDirIndex < (int)g.gl_pathc) -			{ -//				llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; - -				// The API wants just the filename, not the full path. -				//fname = g.gl_pathv[mCurrentDirIndex]; - -				char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); -				 -				if(s == NULL) -					s = g.gl_pathv[mCurrentDirIndex]; -				else if(s[0] == '/') -					s++; -					 -				fname = s; -				 -				result = TRUE; -			} -		} -		 -		globfree(&g); -	} -	 -	return(result); -} - - - -  std::string LLDir_Linux::getCurPath()  {  	char tmp_str[LL_MAX_PATH];	/* Flawfinder: ignore */  diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h index 451e81ae93..ff4c48759a 100644 --- a/indra/llvfs/lldir_linux.h +++ b/indra/llvfs/lldir_linux.h @@ -43,7 +43,6 @@ public:  public:	  	virtual std::string getCurPath();  	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); -	virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);  	/*virtual*/ BOOL fileExists(const std::string &filename) const;  	/*virtual*/ std::string getLLPluginLauncher(); diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 445285aa43..2d039527c0 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -258,67 +258,6 @@ U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &ma  	return (file_count);  } -// get the next file in the directory -BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ -	glob_t g; -	BOOL result = FALSE; -	fname = ""; -	 -	if(!(dirname == mCurrentDir)) -	{ -		// different dir specified, close old search -		mCurrentDirIndex = -1; -		mCurrentDirCount = -1; -		mCurrentDir = dirname; -	} -	 -	std::string tmp_str; -	tmp_str = dirname; -	tmp_str += mask; - -	if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) -	{ -		if(g.gl_pathc > 0) -		{ -			if(g.gl_pathc != mCurrentDirCount) -			{ -				// Number of matches has changed since the last search, meaning a file has been added or deleted. -				// Reset the index. -				mCurrentDirIndex = -1; -				mCurrentDirCount = g.gl_pathc; -			} -	 -			mCurrentDirIndex++; -	 -			if(mCurrentDirIndex < g.gl_pathc) -			{ -//				llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; - -				// The API wants just the filename, not the full path. -				//fname = g.gl_pathv[mCurrentDirIndex]; - -				char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); -				 -				if(s == NULL) -					s = g.gl_pathv[mCurrentDirIndex]; -				else if(s[0] == '/') -					s++; -					 -				fname = s; -				 -				result = TRUE; -			} -		} -		 -		globfree(&g); -	} -	 -	return(result); -} - - -  S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask)  {  	glob_t g; diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h index 4eac3c3ae6..e60d5e41c2 100644 --- a/indra/llvfs/lldir_mac.h +++ b/indra/llvfs/lldir_mac.h @@ -43,7 +43,6 @@ public:  	virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);  	virtual std::string getCurPath();  	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); -	virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);  	virtual BOOL fileExists(const std::string &filename) const;  	/*virtual*/ std::string getLLPluginLauncher(); diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp index 515fd66b6e..21f8c3acdb 100644 --- a/indra/llvfs/lldir_solaris.cpp +++ b/indra/llvfs/lldir_solaris.cpp @@ -260,68 +260,6 @@ U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string  	return (file_count);  } -// get the next file in the directory -BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ -	glob_t g; -	BOOL result = FALSE; -	fname = ""; -	 -	if(!(dirname == mCurrentDir)) -	{ -		// different dir specified, close old search -		mCurrentDirIndex = -1; -		mCurrentDirCount = -1; -		mCurrentDir = dirname; -	} -	 -	std::string tmp_str; -	tmp_str = dirname; -	tmp_str += mask; - -	if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0) -	{ -		if(g.gl_pathc > 0) -		{ -			if((int)g.gl_pathc != mCurrentDirCount) -			{ -				// Number of matches has changed since the last search, meaning a file has been added or deleted. -				// Reset the index. -				mCurrentDirIndex = -1; -				mCurrentDirCount = g.gl_pathc; -			} -	 -			mCurrentDirIndex++; -	 -			if(mCurrentDirIndex < (int)g.gl_pathc) -			{ -//				llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl; - -				// The API wants just the filename, not the full path. -				//fname = g.gl_pathv[mCurrentDirIndex]; - -				char *s = strrchr(g.gl_pathv[mCurrentDirIndex], '/'); -				 -				if(s == NULL) -					s = g.gl_pathv[mCurrentDirIndex]; -				else if(s[0] == '/') -					s++; -					 -				fname = s; -				 -				result = TRUE; -			} -		} -		 -		globfree(&g); -	} -	 -	return(result); -} - - - -  std::string LLDir_Solaris::getCurPath()  {  	char tmp_str[LL_MAX_PATH];	/* Flawfinder: ignore */  diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h index 4a1794f539..f7e1a6301d 100644 --- a/indra/llvfs/lldir_solaris.h +++ b/indra/llvfs/lldir_solaris.h @@ -43,7 +43,6 @@ public:  public:	  	virtual std::string getCurPath();  	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); -	virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);  	/*virtual*/ BOOL fileExists(const std::string &filename) const;  private: diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 33718e520d..2f96fbbbc1 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -236,67 +236,6 @@ U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &  	return (file_count);  } - -// get the next file in the directory -BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) -{ -    BOOL fileFound = FALSE; -	fname = ""; - -	WIN32_FIND_DATAW FileData; -    llutf16string pathname = utf8str_to_utf16str(dirname) + utf8str_to_utf16str(mask); - -	if (pathname != mCurrentDir) -	{ -		// different dir specified, close old search -		if (mCurrentDir[0]) -		{ -			FindClose(mDirSearch_h); -		} -		mCurrentDir = pathname; - -		// and open new one -		// Check error opening Directory structure -		if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)    -		{ -           fileFound = TRUE; -		} -	} - -    // Loop to skip over the current (.) and parent (..) directory entries -    // (apparently returned in Win7 but not XP) -    do -    { -       if (   fileFound -           && (  (lstrcmp(FileData.cFileName, (LPCTSTR)TEXT(".")) == 0) -               ||(lstrcmp(FileData.cFileName, (LPCTSTR)TEXT("..")) == 0) -               ) -           ) -       { -          fileFound = FALSE; -       } -    } while (   mDirSearch_h != INVALID_HANDLE_VALUE -             && !fileFound -             && (fileFound = FindNextFile(mDirSearch_h, &FileData) -                 ) -             ); - -    if (!fileFound && GetLastError() == ERROR_NO_MORE_FILES) -    { -       // No more files, so reset to beginning of directory -       FindClose(mDirSearch_h); -       mCurrentDir[0] = '\000'; -    } - -    if (fileFound) -    { -        // convert from TCHAR to char -        fname = utf16str_to_utf8str(FileData.cFileName); -	} -     -	return fileFound; -} -  std::string LLDir_Win32::getCurPath()  {  	WCHAR w_str[MAX_PATH]; diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h index 4c932c932c..19c610eb8b 100644 --- a/indra/llvfs/lldir_win32.h +++ b/indra/llvfs/lldir_win32.h @@ -40,15 +40,12 @@ public:  	/*virtual*/ std::string getCurPath();  	/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask); -	/*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);  	/*virtual*/ BOOL fileExists(const std::string &filename) const;  	/*virtual*/ std::string getLLPluginLauncher();  	/*virtual*/ std::string getLLPluginFilename(std::string base_name);  private: -	BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname); -	  	void* mDirSearch_h;  	llutf16string mCurrentDir;  }; diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp new file mode 100644 index 0000000000..5536ed8f69 --- /dev/null +++ b/indra/llvfs/lldiriterator.cpp @@ -0,0 +1,203 @@ +/** + * @file lldiriterator.cpp + * @brief Iterator through directory entries matching the search pattern. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "lldiriterator.h" + +#include <boost/filesystem.hpp> +#include <boost/regex.hpp> + +namespace fs = boost::filesystem; + +static std::string glob_to_regex(const std::string& glob); + +class LLDirIterator::Impl +{ +public: +	Impl(const std::string &dirname, const std::string &mask); +	~Impl(); + +	bool next(std::string &fname); + +private: +	boost::regex			mFilterExp; +	fs::directory_iterator	mIter; +	bool					mIsValid; +}; + +LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) +	: mIsValid(false) +{ +	fs::path dir_path(dirname); + +	// Check if path exists. +	if (!fs::exists(dir_path)) +	{ +		llerrs << "Invalid path: \"" << dir_path.string() << "\"" << llendl; +		return; +	} + +	// Initialize the directory iterator for the given path. +	try +	{ +		mIter = fs::directory_iterator(dir_path); +	} +	catch (fs::basic_filesystem_error<fs::path>& e) +	{ +		llerrs << e.what() << llendl; +		return; +	} + +	// Convert the glob mask to a regular expression +	std::string exp = glob_to_regex(mask); + +	// Initialize boost::regex with the expression converted from +	// the glob mask. +	// An exception is thrown if the expression is not valid. +	try +	{ +		mFilterExp.assign(exp); +	} +	catch (boost::regex_error& e) +	{ +		llerrs << "\"" << exp << "\" is not a valid regular expression: " +				<< e.what() << llendl; +		return; +	} + +	mIsValid = true; +} + +LLDirIterator::Impl::~Impl() +{ +} + +bool LLDirIterator::Impl::next(std::string &fname) +{ +	fname = ""; + +	if (!mIsValid) +	{ +		llerrs << "The iterator is not correctly initialized." << llendl; +		return false; +	} + +	fs::directory_iterator end_itr; // default construction yields past-the-end +	bool found = false; +	while (mIter != end_itr && !found) +	{ +		boost::smatch match; +		std::string name = mIter->path().filename(); +		if (found = boost::regex_match(name, match, mFilterExp)) +		{ +			fname = name; +		} + +		++mIter; +	} + +	return found; +} + +std::string glob_to_regex(const std::string& glob) +{ +	std::string regex; +	regex.reserve(glob.size()<<1); +	S32 braces = 0; +	bool escaped = false; +	bool square_brace_open = false; + +	for (std::string::const_iterator i = glob.begin(); i != glob.end(); ++i) +	{ +		char c = *i; + +		switch (c) +		{ +			case '.': +				regex+="\\."; +				break; +			case '*': +				if (glob.begin() == i) +				{ +					regex+="[^.].*"; +				} +				else +				{ +					regex+= escaped ? "*" : ".*"; +				} +				break; +			case '?': +				regex+= escaped ? '?' : '.'; +				break; +			case '{': +				braces++; +				regex+='('; +				break; +			case '}': +				if (!braces) +				{ +					llerrs << "glob_to_regex: Closing brace without an equivalent opening brace: " << glob << llendl; +				} + +				regex+=')'; +				braces--; +				break; +			case ',': +				regex+= braces ? '|' : c; +				break; +			case '!': +				regex+= square_brace_open ? '^' : c; +				break; +			default: +				regex+=c; +				break; +		} + +		escaped = ('\\' == c); +		square_brace_open = ('[' == c); +	} + +	if (braces) +	{ +		llerrs << "glob_to_regex: Unterminated brace expression: " << glob << llendl; +	} + +	return regex; +} + +LLDirIterator::LLDirIterator(const std::string &dirname, const std::string &mask) +{ +	mImpl = new Impl(dirname, mask); +} + +LLDirIterator::~LLDirIterator() +{ +	delete mImpl; +} + +bool LLDirIterator::next(std::string &fname) +{ +	return mImpl->next(fname); +} diff --git a/indra/llvfs/lldiriterator.h b/indra/llvfs/lldiriterator.h new file mode 100644 index 0000000000..0b48be41b3 --- /dev/null +++ b/indra/llvfs/lldiriterator.h @@ -0,0 +1,87 @@ +/** + * @file lldiriterator.h + * @brief Iterator through directory entries matching the search pattern. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDIRITERATOR_H +#define LL_LLDIRITERATOR_H + +#include "linden_common.h" + +/** + * Class LLDirIterator + * + * Iterates through directory entries matching the search pattern. + */ +class LLDirIterator +{ +public: +	/** +	 * Constructs LLDirIterator object to search for glob pattern +	 * matches in a directory. +	 * +	 * @param dirname - name of a directory to search in. +	 * @param mask - search pattern, a glob expression +	 * +	 * Wildcards supported in glob expressions: +	 * -------------------------------------------------------------- +	 * | Wildcard 	| Matches										| +	 * -------------------------------------------------------------- +	 * | 	* 		|zero or more characters						| +	 * | 	?		|exactly one character							| +	 * | [abcde]	|exactly one character listed					| +	 * | [a-e]		|exactly one character in the given range		| +	 * | [!abcde]	|any character that is not listed				| +	 * | [!a-e]		|any character that is not in the given range	| +	 * | {abc,xyz}	|exactly one entire word in the options given	| +	 * -------------------------------------------------------------- +	 */ +	LLDirIterator(const std::string &dirname, const std::string &mask); + +	~LLDirIterator(); + +	/** +	 * Searches for the next directory entry matching the glob mask +	 * specified upon iterator construction. +	 * Returns true if a match is found, sets fname +	 * parameter to the name of the matched directory entry and +	 * increments the iterator position. +	 * +	 * Typical usage: +	 * <code> +	 * LLDirIterator iter(directory, pattern); +	 * if ( iter.next(scanResult) ) +	 * </code> +	 * +	 * @param fname - name of the matched directory entry. +	 * @return true if a match is found, false otherwise. +	 */ +	bool next(std::string &fname); + +protected: +	class Impl; +	Impl* mImpl; +}; + +#endif //LL_LLDIRITERATOR_H diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp index 8788bd63e8..ea321c5ae9 100644 --- a/indra/llvfs/tests/lldir_test.cpp +++ b/indra/llvfs/tests/lldir_test.cpp @@ -28,6 +28,7 @@  #include "linden_common.h"  #include "../lldir.h" +#include "../lldiriterator.h"  #include "../test/lltut.h" @@ -259,13 +260,12 @@ namespace tut     std::string makeTestFile( const std::string& dir, const std::string& file )     { -      std::string delim = gDirUtilp->getDirDelimiter(); -      std::string path = dir + delim + file; +      std::string path = dir + file;        LLFILE* handle = LLFile::fopen( path, "w" );        ensure("failed to open test file '"+path+"'", handle != NULL );        // Harbison & Steele, 4th ed., p. 366: "If an error occurs, fputs        // returns EOF; otherwise, it returns some other, nonnegative value." -      ensure("failed to write to test file '"+path+"'", fputs("test file", handle) >= 0); +      ensure("failed to write to test file '"+path+"'", EOF != fputs("test file", handle) );        fclose(handle);        return path;     } @@ -290,7 +290,7 @@ namespace tut     }     static const char* DirScanFilename[5] = { "file1.abc", "file2.abc", "file1.xyz", "file2.xyz", "file1.mno" }; -    +     void scanTest(const std::string& directory, const std::string& pattern, bool correctResult[5])     { @@ -300,7 +300,8 @@ namespace tut        bool  filesFound[5] = { false, false, false, false, false };        //std::cerr << "searching '"+directory+"' for '"+pattern+"'\n"; -      while ( found <= 5 && gDirUtilp->getNextFileInDir(directory, pattern, scanResult) ) +      LLDirIterator iter(directory, pattern); +      while ( found <= 5 && iter.next(scanResult) )        {           found++;           //std::cerr << "  found '"+scanResult+"'\n"; @@ -334,15 +335,15 @@ namespace tut     template<> template<>     void LLDirTest_object_t::test<5>() -      // getNextFileInDir +      // LLDirIterator::next     {        std::string delim = gDirUtilp->getDirDelimiter();        std::string dirTemp = LLFile::tmpdir();        // Create the same 5 file names of the two directories -      std::string dir1 = makeTestDir(dirTemp + "getNextFileInDir"); -      std::string dir2 = makeTestDir(dirTemp + "getNextFileInDir"); +      std::string dir1 = makeTestDir(dirTemp + "LLDirIterator"); +      std::string dir2 = makeTestDir(dirTemp + "LLDirIterator");        std::string dir1files[5];        std::string dir2files[5];        for (int i=0; i<5; i++) @@ -380,19 +381,17 @@ namespace tut        scanTest(dir2, "file?.x?z", expected7);        // Scan dir2 and see if any file?.??c files are found -      // THESE FAIL ON Mac and Windows, SO ARE COMMENTED OUT FOR NOW -      //      bool  expected8[5] = { true, true, false, false, false }; -      //      scanTest(dir2, "file?.??c", expected8); -      //      scanTest(dir2, "*.??c", expected8); +      bool  expected8[5] = { true, true, false, false, false }; +      scanTest(dir2, "file?.??c", expected8); +      scanTest(dir2, "*.??c", expected8);        // Scan dir1 and see if any *.?n? files are found        bool  expected9[5] = { false, false, false, false, true };        scanTest(dir1, "*.?n?", expected9);        // Scan dir1 and see if any *.???? files are found -      // THIS ONE FAILS ON WINDOWS (returns three charater suffixes) SO IS COMMENTED OUT FOR NOW -      // bool  expected10[5] = { false, false, false, false, false }; -      // scanTest(dir1, "*.????", expected10); +      bool  expected10[5] = { false, false, false, false, false }; +      scanTest(dir1, "*.????", expected10);        // Scan dir1 and see if any ?????.* files are found        bool  expected11[5] = { true, true, true, true, true }; @@ -402,6 +401,15 @@ namespace tut        bool  expected12[5] = { false, false, true, true, false };        scanTest(dir1, "??l??.xyz", expected12); +      bool expected13[5] = { true, false, true, false, false }; +      scanTest(dir1, "file1.{abc,xyz}", expected13); + +      bool expected14[5] = { true, true, false, false, false }; +      scanTest(dir1, "file[0-9].abc", expected14); + +      bool expected15[5] = { true, true, false, false, false }; +      scanTest(dir1, "file[!a-z].abc", expected15); +        // clean up all test files and directories        for (int i=0; i<5; i++)        { diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3e0b4f9998..de7073be24 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -64,6 +64,7 @@  #include "lltool.h"  #include "lltoolmgr.h"  #include "lltrans.h" +#include "llurlentry.h"  #include "llviewercontrol.h"  #include "llviewerdisplay.h"  #include "llviewerjoystick.h" @@ -649,6 +650,10 @@ void LLAgent::setRegion(LLViewerRegion *regionp)  	}  	mRegionp = regionp; +	// Pass the region host to LLUrlEntryParcel to resolve parcel name +	// with a server request. +	LLUrlEntryParcel::setRegionHost(getRegionHost()); +  	// Must shift hole-covering water object locations because local  	// coordinate frame changed.  	LLWorld::getInstance()->updateWaterObjects(); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 0e080e713b..c45be8b05e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1300,8 +1300,16 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)  		return false;  	} -	// Check whether the outfit contains the full set of body parts (shape+skin+hair+eyes). -	return getCanMakeFolderIntoOutfit(outfit_cat_id); +	// Check whether the outfit contains any wearables we aren't wearing already (STORM-702). +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); +	gInventory.collectDescendentsIf(outfit_cat_id, +		cats, +		items, +		LLInventoryModel::EXCLUDE_TRASH, +		is_worn); +	return items.size() > 0;  }  void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0093279859..8193945f62 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -92,10 +92,12 @@  // Linden library includes  #include "llavatarnamecache.h" +#include "lldiriterator.h"  #include "llimagej2c.h"  #include "llmemory.h"  #include "llprimitive.h"  #include "llurlaction.h" +#include "llurlentry.h"  #include "llvfile.h"  #include "llvfsthread.h"  #include "llvolumemgr.h" @@ -3324,7 +3326,9 @@ void LLAppViewer::migrateCacheDirectory()  			S32 file_count = 0;  			std::string file_name;  			std::string mask = delimiter + "*.*"; -			while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name)) + +			LLDirIterator iter(old_cache_dir, mask); +			while (iter.next(file_name))  			{  				if (file_name == "." || file_name == "..") continue;  				std::string source_path = old_cache_dir + delimiter + file_name; @@ -3543,7 +3547,8 @@ bool LLAppViewer::initCache()  		dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");  		std::string found_file; -		if (gDirUtilp->getNextFileInDir(dir, mask, found_file)) +		LLDirIterator iter(dir, mask); +		if (iter.next(found_file))  		{  			old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file; @@ -4610,6 +4615,10 @@ void LLAppViewer::disconnectViewer()  	cleanup_xfer_manager();  	gDisconnected = TRUE; + +	// Pass the connection state to LLUrlEntryParcel not to attempt +	// parcel info requests while disconnected. +	LLUrlEntryParcel::setDisconnected(gDisconnected);  }  void LLAppViewer::forceErrorLLError() diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 898cc1c0ba..fc7a27e5e0 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -30,6 +30,7 @@  #include "llcommandlineparser.h" +#include "lldiriterator.h"  #include "llmemtype.h"  #include "llurldispatcher.h"		// SLURL from other app instance  #include "llviewernetwork.h" @@ -504,7 +505,9 @@ std::string LLAppViewerLinux::generateSerialNumber()  	// trawl /dev/disk/by-uuid looking for a good-looking UUID to grab  	std::string this_name; -	while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name)) + +	LLDirIterator iter(uuiddir, "*"); +	while (iter.next(this_name))  	{  		if (this_name.length() > best.length() ||  		    (this_name.length() == best.length() && diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 11b3379814..182d3d23f1 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -35,6 +35,7 @@  #include "llfloateruipreview.h"			// Own header  // Internal utility +#include "lldiriterator.h"  #include "lleventtimer.h"  #include "llexternaleditor.h"  #include "llrender.h" @@ -481,9 +482,11 @@ BOOL LLFloaterUIPreview::postBuild()  	std::string language_directory;  	std::string xui_dir = get_xui_dir();	// directory containing localizations -- don't forget trailing delim  	mLanguageSelection->removeall();																				// clear out anything temporarily in list from XML + +	LLDirIterator iter(xui_dir, "*");  	while(found)																									// for every directory  	{ -		if((found = gDirUtilp->getNextFileInDir(xui_dir, "*", language_directory)))							// get next directory +		if((found = iter.next(language_directory)))							// get next directory  		{  			std::string full_path = xui_dir + language_directory;  			if(LLFile::isfile(full_path.c_str()))																	// if it's not a directory, skip it @@ -635,42 +638,51 @@ void LLFloaterUIPreview::refreshList()  	mFileList->clearRows();		// empty list  	std::string name;  	BOOL found = TRUE; + +	LLDirIterator floater_iter(getLocalizedDirectory(), "floater_*.xml");  	while(found)				// for every floater file that matches the pattern  	{ -		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "floater_*.xml", name)))	// get next file matching pattern +		if((found = floater_iter.next(name)))	// get next file matching pattern  		{  			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)  		}  	}  	found = TRUE; + +	LLDirIterator inspect_iter(getLocalizedDirectory(), "inspect_*.xml");  	while(found)				// for every inspector file that matches the pattern  	{ -		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", name)))	// get next file matching pattern +		if((found = inspect_iter.next(name)))	// get next file matching pattern  		{  			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)  		}  	}  	found = TRUE; + +	LLDirIterator menu_iter(getLocalizedDirectory(), "menu_*.xml");  	while(found)				// for every menu file that matches the pattern  	{ -		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", name)))	// get next file matching pattern +		if((found = menu_iter.next(name)))	// get next file matching pattern  		{  			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)  		}  	}  	found = TRUE; + +	LLDirIterator panel_iter(getLocalizedDirectory(), "panel_*.xml");  	while(found)				// for every panel file that matches the pattern  	{ -		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "panel_*.xml", name)))	// get next file matching pattern +		if((found = panel_iter.next(name)))	// get next file matching pattern  		{  			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)  		}  	} -  	found = TRUE; + +	LLDirIterator sidepanel_iter(getLocalizedDirectory(), "sidepanel_*.xml");  	while(found)				// for every sidepanel file that matches the pattern  	{ -		if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name)))	// get next file matching pattern +		if((found = sidepanel_iter.next(name)))	// get next file matching pattern  		{  			addFloaterEntry(name.c_str());	// and add it to the list (file name only; localization code takes care of rest of path)  		} diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1b07aa279b..342d15cf0f 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -686,6 +686,12 @@ bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* it  		return false;  	} +	// Skip broken links. +	if (vitem->getIsBrokenLink()) +	{ +		return false; +	} +  	return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;  } diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 1527f8f4c9..55164f6094 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -547,6 +547,10 @@ void LLLocationInputCtrl::onFocusLost()  {  	LLUICtrl::onFocusLost();  	refreshLocation(); + +	// Setting cursor to 0  to show the left edge of the text. See STORM-370. +	mTextEntry->setCursor(0); +  	if(mTextEntry->hasSelection()){  		mTextEntry->deselect();  	} diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 9adf374c71..b09cfbe907 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -32,6 +32,7 @@  #include "lltrans.h"  #include "llviewercontrol.h" +#include "lldiriterator.h"  #include "llinstantmessage.h"  #include "llsingleton.h" // for LLSingleton @@ -601,7 +602,8 @@ std::string LLLogChat::oldLogFileName(std::string filename)  	//LL_INFOS("") << "Checking:" << directory << " for " << pattern << LL_ENDL;/* uncomment if you want to verify step, delete on commit */  	std::vector<std::string> allfiles; -    while (gDirUtilp->getNextFileInDir(directory, pattern, scanResult)) +	LLDirIterator iter(directory, pattern); +	while (iter.next(scanResult))      {  		//LL_INFOS("") << "Found   :" << scanResult << LL_ENDL;          allfiles.push_back(scanResult); diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index 5ea94e0611..d3c9c3e131 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -76,17 +76,19 @@ void LLPanelMe::onOpen(const LLSD& key)  {  	LLPanelProfile::onOpen(key); -	// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) -	bool opened = gSavedSettings.getBOOL("MePanelOpened"); -	// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this -	// is the last time onOpen() is called -	if( !opened && !LLSideTray::getInstance()->getCollapsed() ) -	{ -		buildEditPanel(); -		openPanel(mEditPanel, getAvatarId()); - -		gSavedSettings.setBOOL("MePanelOpened", true); -	} +	// Removed this action as per SOCIAL-431 The first time a new resident opens the profile tab  +	//                                       in the sidebar, they see the old profile editing panel +	// +	//// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) +	//bool opened = gSavedSettings.getBOOL("MePanelOpened"); +	//// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this +	//// is the last time onOpen() is called +	//if( !opened && !LLSideTray::getInstance()->getCollapsed() ) +	//{ +	//	buildEditPanel(); +	//	openPanel(mEditPanel, getAvatarId()); +	//	gSavedSettings.setBOOL("MePanelOpened", true); +	//}  }  bool LLPanelMe::notifyChildren(const LLSD& info) diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index e5ef51bdd1..3862dac340 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -33,6 +33,7 @@  #include "llpanel.h"  #include "llhttpclient.h"  #include "llsdserialize.h" +#include "llurlentry.h"  #include "llviewerregion.h"  #include "llview.h" @@ -168,6 +169,18 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v  	{  		observers.erase(*i);  	} + +	LLUrlEntryParcel::LLParcelData url_data; +	url_data.parcel_id = parcel_data.parcel_id; +	url_data.name = parcel_data.name; +	url_data.sim_name = parcel_data.sim_name; +	url_data.global_x = parcel_data.global_x; +	url_data.global_y = parcel_data.global_y; +	url_data.global_z = parcel_data.global_z; + +	// Pass the parcel data to LLUrlEntryParcel to render +	// human readable parcel name. +	LLUrlEntryParcel::processParcelInfo(url_data);  }  void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id) diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index aef665a35c..19d1bdee86 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -498,8 +498,8 @@ private:  LLSideTray::Params::Params()  :	collapsed("collapsed",false), -	tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("sidebar_tab_left.tga")), -	tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("button_enabled_selected_32x128.tga")), +	tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Off.png")), +	tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Selected.png")),  	default_button_width("tab_btn_width",32),  	default_button_height("tab_btn_height",32),  	default_button_margin("tab_btn_margin",0) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 5dcbf079a4..029a48480f 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -139,6 +139,7 @@  #include "lltrans.h"  #include "llui.h"  #include "llurldispatcher.h" +#include "llurlentry.h"  #include "llslurl.h"  #include "llurlhistory.h"  #include "llurlwhitelist.h" @@ -2882,9 +2883,17 @@ bool process_login_success_response()  	if(!text.empty()) gAgentID.set(text);  	gDebugInfo["AgentID"] = text; +	// Agent id needed for parcel info request in LLUrlEntryParcel +	// to resolve parcel name. +	LLUrlEntryParcel::setAgentID(gAgentID); +  	text = response["session_id"].asString();  	if(!text.empty()) gAgentSessionID.set(text);  	gDebugInfo["SessionID"] = text; + +	// Session id needed for parcel info request in LLUrlEntryParcel +	// to resolve parcel name. +	LLUrlEntryParcel::setSessionID(gAgentSessionID);  	text = response["secure_session_id"].asString();  	if(!text.empty()) gAgent.mSecureSessionID.set(text); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index cd72e69055..d78eef70bd 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -54,6 +54,7 @@  #include "llfilepicker.h"  #include "llnotifications.h" +#include "lldiriterator.h"  #include "llevent.h"		// LLSimpleListener  #include "llnotificationsutil.h"  #include "lluuid.h" @@ -1115,7 +1116,8 @@ void LLViewerMedia::clearAllCookies()  	}  	// the hard part: iterate over all user directories and delete the cookie file from each one -	while(gDirUtilp->getNextFileInDir(base_dir, "*_*", filename)) +	LLDirIterator dir_iter(base_dir, "*_*"); +	while (dir_iter.next(filename))  	{  		target = base_dir;  		target += filename; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 75531cef8d..0f980986d3 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -4204,9 +4204,9 @@ class LLObjectEnableReturn : public view_listener_t  					{  						virtual bool apply(LLViewerObject* obj)  						{ -							return (obj->isOverAgentOwnedLand() || -									obj->isOverGroupOwnedLand() || -									obj->permModify()); +							return  +								obj->permModify() || +								obj->isReturnable();  						}  					} func;  					const bool firstonly = true; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1209183229..27f371df9c 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -529,20 +529,23 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list)  // This method returns true if the object is over land owned by the  // agent. -BOOL LLViewerObject::isOverAgentOwnedLand() const +bool LLViewerObject::isReturnable()  { -	return mRegionp -		&& mRegionp->getParcelOverlay() -		&& mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion()); -} +	if (isAttachment()) +	{ +		return false; +	} +	std::vector<LLBBox> boxes; +	boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); +	for (child_list_t::iterator iter = mChildList.begin(); +		 iter != mChildList.end(); iter++) +	{ +		LLViewerObject* child = *iter; +		boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); +	} -// This method returns true if the object is over land owned by the -// agent. -BOOL LLViewerObject::isOverGroupOwnedLand() const -{ -	return mRegionp  -		&& mRegionp->getParcelOverlay() -		&& mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion()); +	return mRegionp +		&& mRegionp->objectIsReturnable(getPositionRegion(), boxes);  }  BOOL LLViewerObject::setParent(LLViewerObject* parent) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 3ba51a6448..0b6d8483e9 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -228,12 +228,9 @@ public:  	virtual BOOL hasLightTexture() const			{ return FALSE; }  	// This method returns true if the object is over land owned by -	// the agent. -	BOOL isOverAgentOwnedLand() const; - -	// True if over land owned by group of which the agent is -	// either officer or member. -	BOOL isOverGroupOwnedLand() const; +	// the agent, one of its groups, or it encroaches and  +	// anti-encroachment is enabled +	bool isReturnable();  	/*  	// This method will scan through this object, and then query the diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index eee653b0c1..d07e06f6a7 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -145,6 +145,35 @@ BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const  	return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay);  } +bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) const +{ +	// boxes are expected to already be axis aligned +	for (U32 i = 0; i < boxes.size(); ++i) +	{ +		LLVector3 min = boxes[i].getMinAgent(); +		LLVector3 max = boxes[i].getMaxAgent(); +		 +		S32 left   = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 right  = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 top    = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +	 +		for (S32 row = top; row <= bottom; row++) +		{ +			for (S32 column = left; column <= right; column++) +			{ +				U8 type = ownership(row, column); +				if ((PARCEL_SELF == type) +					|| (PARCEL_GROUP == type)) +				{ +					return true; +				} +			} +		} +	} +	return false; +} +  BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const  {  	S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS); diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 61be220312..c80baedda6 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -30,6 +30,7 @@  // The ownership data for land parcels.  // One of these structures per region. +#include "llbbox.h"  #include "lldarray.h"  #include "llframetimer.h"  #include "lluuid.h" @@ -54,6 +55,12 @@ public:  	BOOL			isOwnedSelf(const LLVector3& pos) const;  	BOOL			isOwnedGroup(const LLVector3& pos) const;  	BOOL			isOwnedOther(const LLVector3& pos) const; + +	// "encroaches" means the prim hangs over the parcel, but its center +	// might be in another parcel. for now, we simply test axis aligned  +	// bounding boxes which isn't perfect, but is close +	bool encroachesOwned(const std::vector<LLBBox>& boxes) const; +	  	BOOL			isSoundLocal(const LLVector3& pos) const;  	BOOL			isBuildCameraAllowed(const LLVector3& pos) const; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index a90c90a774..16aa9069fd 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1410,7 +1410,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("SimConsole");  	capabilityNames.append("SimulatorFeatures");  	capabilityNames.append("SetDisplayName"); -	capabilityNames.append("SimConsole");  	capabilityNames.append("SimConsoleAsync");  	capabilityNames.append("StartGroupProposal");  	capabilityNames.append("TextureStats"); @@ -1509,6 +1508,20 @@ LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)  	return NULL;  } +// the viewer can not yet distinquish between normal- and estate-owned objects +// so we collapse these two bits and enable the UI if either are set +const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT +											| REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; + +bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const +{ +	return (mParcelOverlay != NULL) +		&& (mParcelOverlay->isOwnedSelf(pos) +			|| mParcelOverlay->isOwnedGroup(pos) +			|| ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) +				&& mParcelOverlay->encroachesOwned(boxes)) ); +} +  void LLViewerRegion::showReleaseNotes()  {  	std::string url = this->getCapability("ServerReleaseNotes"); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 8b71998f60..3d3f1d62a6 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -33,6 +33,7 @@  #include "lldarray.h"  #include "llwind.h" +#include "llbbox.h"  #include "llcloud.h"  #include "llstat.h"  #include "v3dmath.h" @@ -293,6 +294,8 @@ public:  	std::string getHttpUrl() const { return mHttpUrl ;}  	LLSpatialPartition* getSpatialPartition(U32 type); + +	bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;  public:  	struct CompareDistance  	{ diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b667dc1af0..b1818ab23f 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2128,31 +2128,6 @@ void LLVOAvatar::computeBodySize()  			gAgent.sendAgentSetAppearance();  		}  	} - -/* debug spam -	std::cout << "skull = " << skull << std::endl;				// adebug -	std::cout << "head = " << head << std::endl;				// adebug -	std::cout << "head_scale = " << head_scale << std::endl;	// adebug -	std::cout << "neck = " << neck << std::endl;				// adebug -	std::cout << "neck_scale = " << neck_scale << std::endl;	// adebug -	std::cout << "chest = " << chest << std::endl;				// adebug -	std::cout << "chest_scale = " << chest_scale << std::endl;	// adebug -	std::cout << "torso = " << torso << std::endl;				// adebug -	std::cout << "torso_scale = " << torso_scale << std::endl;	// adebug -	std::cout << std::endl;	// adebug - -	std::cout << "pelvis_scale = " << pelvis_scale << std::endl;// adebug -	std::cout << std::endl;	// adebug - -	std::cout << "hip = " << hip << std::endl;					// adebug -	std::cout << "hip_scale = " << hip_scale << std::endl;		// adebug -	std::cout << "ankle = " << ankle << std::endl;				// adebug -	std::cout << "ankle_scale = " << ankle_scale << std::endl;	// adebug -	std::cout << "foot = " << foot << std::endl;				// adebug -	std::cout << "mBodySize = " << mBodySize << std::endl;		// adebug -	std::cout << "mPelvisToFoot = " << mPelvisToFoot << std::endl;	// adebug -	std::cout << std::endl;		// adebug -*/  }  //------------------------------------------------------------------------ diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index d239347810..4f6ec4ca61 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -33,6 +33,7 @@  #include "pipeline.h"  #include "llsky.h" +#include "lldiriterator.h"  #include "llfloaterreg.h"  #include "llsliderctrl.h"  #include "llspinctrl.h" @@ -85,11 +86,12 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)  	std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", ""));  	LL_DEBUGS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL; -	bool found = true;			 +	bool found = true; +	LLDirIterator app_settings_iter(path_name, "*.xml");  	while(found)   	{  		std::string name; -		found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name); +		found = app_settings_iter.next(name);  		if(found)  		{ @@ -111,11 +113,12 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)  	std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", ""));  	LL_DEBUGS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL; -	found = true;			 +	found = true; +	LLDirIterator user_settings_iter(path_name2, "*.xml");  	while(found)   	{  		std::string name; -		found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name); +		found = user_settings_iter.next(name);  		if(found)  		{  			name=name.erase(name.length()-4); diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index e5f52dfc97..848efcbb49 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -31,6 +31,7 @@  #include "pipeline.h"  #include "llsky.h" +#include "lldiriterator.h"  #include "llfloaterreg.h"  #include "llsliderctrl.h"  #include "llspinctrl.h" @@ -100,11 +101,12 @@ void LLWLParamManager::loadPresets(const std::string& file_name)  	std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", ""));  	LL_DEBUGS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL; -	bool found = true;			 +	bool found = true; +	LLDirIterator app_settings_iter(path_name, "*.xml");  	while(found)   	{  		std::string name; -		found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name); +		found = app_settings_iter.next(name);  		if(found)  		{ @@ -126,11 +128,12 @@ void LLWLParamManager::loadPresets(const std::string& file_name)  	std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", ""));  	LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL; -	found = true;			 +	found = true; +	LLDirIterator user_settings_iter(path_name2, "*.xml");  	while(found)   	{  		std::string name; -		found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name); +		found = user_settings_iter.next(name);  		if(found)  		{  			name=name.erase(name.length()-4); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index feb6c1bb2a..7d767b9222 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -115,9 +115,6 @@       name="AlertCautionTextColor"       reference="LtYellow" />      <color -     name="AgentLinkColor" -     reference="EmphasisColor" /> -    <color       name="AlertTextColor"       value="0.58 0.66 0.84 1" />      <color @@ -349,9 +346,6 @@       name="GridlineShadowColor"       value="0 0 0 0.31" />      <color -     name="GroupLinkColor" -     reference="White" /> -    <color       name="GroupNotifyBoxColor"       value="0.3344 0.5456 0.5159 1" />      <color diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml index 70299c61b4..593e686d4c 100644 --- a/indra/newview/skins/default/xui/da/notifications.xml +++ b/indra/newview/skins/default/xui/da/notifications.xml @@ -1636,7 +1636,7 @@ Knappen vil blive vist når der er nok plads til den.  	<notification name="ShareItemsConfirmation">  		Er du sikker på at du vil dele følgende genstande: -[ITEMS] +<nolink>[ITEMS]</nolink>  Med følgende beboere: diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 06cc02cd84..a2d0b5a170 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2747,7 +2747,7 @@ Die Schaltfläche wird angezeigt, wenn genügend Platz vorhanden ist.  	<notification name="ShareItemsConfirmation">  		Möchten Sie diese Objekte wirklich für andere freigeben: -[ITEMS] +<nolink>[ITEMS]</nolink>  Für folgende Einwohner: diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml index c751aa4e0c..719509301b 100644 --- a/indra/newview/skins/default/xui/en/menu_object.xml +++ b/indra/newview/skins/default/xui/en/menu_object.xml @@ -100,7 +100,7 @@           name="Object Attach HUD" />     </context_menu>     <context_menu -         label="Remove" +         label="Manage"           name="Remove">     <menu_item_call           enabled="false" @@ -129,15 +129,6 @@           <menu_item_call.on_enable            function="Object.EnableReturn" />       </menu_item_call> -     <menu_item_call -   enabled="false" -   label="Delete" -   name="Delete"> -      <menu_item_call.on_click -       function="Object.Delete" /> -      <menu_item_call.on_enable -       function="Object.EnableDelete" /> -    </menu_item_call>      </context_menu>     <menu_item_separator layout="topleft" />     <menu_item_call @@ -176,4 +167,13 @@        <menu_item_call.on_enable         function="Object.EnableBuy" />     </menu_item_call> +   <menu_item_call +     enabled="false" +     label="Delete" +     name="Delete"> +      <menu_item_call.on_click +       function="Object.Delete" /> +      <menu_item_call.on_enable +       function="Object.EnableDelete" /> +  </menu_item_call>  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b7816b8e25..c9bc617a1a 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -89,7 +89,7 @@           visibility_control="VoiceMorphingEnabled">              <menu_item_check.on_check               function="Floater.Visible" -             parameter="voice_effect" /> +             Parameter="voice_effect" />              <menu_item_check.on_click               function="Floater.Toggle"               parameter="voice_effect" /> @@ -2771,7 +2771,7 @@                   function="Floater.Toggle"                   parameter="region_debug_console" />              </menu_item_check> -  +            <menu_item_check             <menu_item_separator />              <menu_item_check @@ -2790,6 +2790,10 @@              <menu_item_separator />              <menu_item_check + +            <menu_item_separator /> + +            <menu_item_check               label="Debug SelectMgr"               name="Debug SelectMgr">                  <menu_item_check.on_check diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e2fc173f7f..cac25b9312 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6450,7 +6450,7 @@ Select residents to share with.     type="alertmodal">  Are you sure you want to share the following items: -[ITEMS] +<nolink>[ITEMS]</nolink>  With the following Residents: diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index 61d6cbb2d0..eff674c628 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -67,23 +67,23 @@          <scroll_list.columns           label="Parcel"           name="name" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Region"           name="location" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Type"           name="type" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Area"           name="area" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Hidden"           name="hidden" -         width="47" /> +         relative_width="0.2" />      </scroll_list>      <text       type="string" diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml index 85d0c633af..2e5ebafe46 100644 --- a/indra/newview/skins/default/xui/en/widgets/floater.xml +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -21,4 +21,5 @@   tear_off_pressed_image="tearoff_pressed.tga"   dock_pressed_image="Icon_Dock_Press"   help_pressed_image="Icon_Help_Press" + focus_root="true"    /> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 2dd7a6b0f5..14ce39e8fc 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2734,7 +2734,7 @@ Se mostrará cuando haya suficiente espacio.  	<notification name="ShareItemsConfirmation">  		¿Estás seguro de que quieres compartir los elementos siguientes? -[ITEMS] +<nolink>[ITEMS]</nolink>  Con los siguientes residentes: diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index ec362d7f22..f0b0e63af0 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2730,7 +2730,7 @@ Le bouton sera affiché quand il y aura suffisamment de place.  	<notification name="ShareItemsConfirmation">  		Voulez-vous vraiment partager les articles suivants : -[ITEMS] +<nolink>[ITEMS]</nolink>  avec les résidents suivants : diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 32483881b2..5e53080c77 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -2679,7 +2679,7 @@ Il pulsante verrà visualizzato quando lo spazio sarà sufficiente.  	<notification name="ShareItemsConfirmation">  		Sei sicuro di volere condividere gli oggetti -[ITEMS] +<nolink>[ITEMS]</nolink>  Con i seguenti residenti? diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index c0af0e03ff..f133bb361a 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -2731,7 +2731,7 @@ M キーを押して変更します。  	<notification name="ShareItemsConfirmation">  		次のアイテムを共有しますか: -[ITEMS] +<nolink>[ITEMS]</nolink>  次の住人と共有しますか: diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index 8151c7eb93..57a6b8b8ef 100644 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -2691,7 +2691,7 @@ Przycisk zostanie wyświetlony w przypadku dostatecznej ilości przestrzeni.  	<notification name="ShareItemsConfirmation">  		Jesteś pewien/pewna, że chcesz udostępnić następujące obiekty: -[ITEMS] +<nolink>[ITEMS]</nolink>  następującym Rezydentom: diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index dc38b740aa..a1855f2e89 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -477,7 +477,7 @@ Para aumentar a qualidade do vídeo, vá para Preferências > Vídeo.  	</notification>  	<notification name="CannotCopyWarning">  		Você não tem autorização para copiar os itens abaixo: -[ITENS] +[ITEMS]  ao dá-los, você ficará sem eles no seu inventário. Deseja realmente dar estes itens?  		<usetemplate name="okcancelbuttons" notext="Não" yestext="Sim"/>  	</notification> @@ -2714,7 +2714,7 @@ O botão será exibido quando houver espaço suficente.  	<notification name="ShareItemsConfirmation">  		Tem certeza de que quer compartilhar os items abaixo? -[ITENS] +<nolink>[ITEMS]</nolink>  Com os seguintes residentes: diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index dae22521bb..7862cce3a1 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -32,6 +32,7 @@  #include "../llagent.h"  #include "message.h" +#include "llurlentry.h"  namespace {  	LLControlGroup s_saved_settings("dummy_settings"); @@ -72,6 +73,7 @@ LLUIColor::LLUIColor(void) { }  LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { }  LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }  LLControlGroup::~LLControlGroup(void) { } +void LLUrlEntryParcel::processParcelInfo(const LLUrlEntryParcel::LLParcelData& parcel_data) { }  namespace tut  { diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 88ab5a2284..e19d5724f1 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -59,12 +59,6 @@ class LLDir_Mock : public LLDir  		return 0;  	} -	BOOL getNextFileInDir(const std::string &dirname,  -						  const std::string &mask,  -						  std::string &fname)  -	{ -		return false; -	}  	void getRandomFileInDir(const std::string &dirname,   							const std::string &mask,   							std::string &fname) {} | 
