summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Stinson <stinson@lindenlab.com>2012-01-03 10:38:06 -0800
committerTodd Stinson <stinson@lindenlab.com>2012-01-03 10:38:06 -0800
commit3fd7752f1289f67db93e76833cc9804d057bc3c8 (patch)
tree4fe65b7a3c80b065aa19e4904ea8e0d0d0e56940
parentd1e79837d1b07cec0297a20e3cb63a47b136d844 (diff)
parent570d562f5871f40bd7f8c683db5316ffd0133335 (diff)
Pull and merge from https://bitbucket.org/lindenlab/viewer-development.
-rw-r--r--.hgtags8
-rw-r--r--BuildParams20
-rw-r--r--doc/contributions.txt8
-rw-r--r--indra/llcommon/llsys.cpp1
-rw-r--r--indra/llcommon/llthread.h7
-rw-r--r--indra/llmessage/llcurl.cpp131
-rw-r--r--indra/llmessage/llcurl.h5
-rw-r--r--indra/llrender/llfontgl.cpp12
-rw-r--r--indra/newview/llappviewer.cpp2
-rw-r--r--indra/newview/llchiclet.cpp6
-rw-r--r--indra/newview/llcofwearables.cpp14
-rw-r--r--indra/newview/llcofwearables.h2
-rw-r--r--indra/newview/llimview.cpp55
-rw-r--r--indra/newview/llpaneleditwearable.cpp6
-rw-r--r--indra/newview/llscriptfloater.cpp11
-rw-r--r--indra/newview/llsyswellwindow.cpp13
-rw-r--r--indra/newview/llsyswellwindow.h1
-rw-r--r--indra/newview/lltoast.cpp146
-rw-r--r--indra/newview/lltoast.h8
-rwxr-xr-xindra/newview/llviewermessage.cpp40
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml24
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml9
-rw-r--r--indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_cof_wearables.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_skin.xml12
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml5
27 files changed, 380 insertions, 175 deletions
diff --git a/.hgtags b/.hgtags
index 539efb0ffc..d8ece0c865 100644
--- a/.hgtags
+++ b/.hgtags
@@ -229,6 +229,14 @@ c4911ec8cd81e676dfd2af438b3e065407a94a7a 3.2.1-start
a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release
a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-start
+a9abb9633a266c8d2fe62411cfd1c86d32da72bf DRTVWR-60_2.7.1-release
+fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release
+a9abb9633a266c8d2fe62411cfd1c86d32da72bf 2.7.1-release
+fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.1-release
3fe994349fae64fc40874bb59db387131eb35a41 DRTVWR-104_3.2.4-beta1
3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-beta1
8a44ff3d2104269ce76145c2772cf1bdff2a2abe 3.2.5-start
+fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-62_2.7.2-release
+fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.2-release
+bd6bcde2584491fd9228f1fa51c4575f4e764e19 DRTVWR-103_3.2.4-release
+bd6bcde2584491fd9228f1fa51c4575f4e764e19 3.2.4-release
diff --git a/BuildParams b/BuildParams
index 3f5d6f8c6b..c051397853 100644
--- a/BuildParams
+++ b/BuildParams
@@ -145,6 +145,17 @@ oz_viewer-devreview.codeticket_add_context = false
oz_viewer-devreview.build_enforce_coding_policy = true
oz_viewer-devreview.email = oz@lindenlab.com
+oz_viewer-trial.build_debug_release_separately = true
+oz_viewer-trial.codeticket_add_context = false
+oz_viewer-trial.build_enforce_coding_policy = true
+oz_viewer-trial.email = oz@lindenlab.com
+
+oz_viewer-beta-review.build_debug_release_separately = true
+oz_viewer-beta-review.codeticket_add_context = false
+oz_viewer-beta-review.viewer_channel = "Second Life Beta Viewer"
+oz_viewer-beta-review.login_channel = "Second Life Beta Viewer"
+oz_viewer-beta-review.email = oz@lindenlab.com
+
oz_project-1.build_debug_release_separately = true
oz_project-1.codeticket_add_context = false
oz_project-1.email = oz@lindenlab.com
@@ -157,15 +168,6 @@ oz_project-3.email = oz@lindenlab.com
oz_project-4.build_debug_release_separately = true
oz_project-4.codeticket_add_context = false
oz_project-4.email = oz@lindenlab.com
-oz_project-5.build_debug_release_separately = true
-oz_project-5.codeticket_add_context = false
-oz_project-5.email = oz@lindenlab.com
-
-oz_viewer-beta-review.build_debug_release_separately = true
-oz_viewer-beta-review.codeticket_add_context = false
-oz_viewer-beta-review.viewer_channel = "Second Life Beta Viewer"
-oz_viewer-beta-review.login_channel = "Second Life Beta Viewer"
-oz_viewer-beta-review.email = oz@lindenlab.com
# =================================================================
# asset delivery 2010 projects
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 274632a804..1a3fc680bc 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -159,6 +159,7 @@ Alissa Sabre
VWR-12620
VWR-12789
SNOW-322
+ STORM-1723
Alliez Mysterio
Angus Boyd
VWR-592
@@ -583,6 +584,7 @@ Jonathan Yap
STORM-976
STORM-1639
STORM-910
+ STORM-1653
STORM-1642
STORM-591
STORM-1105
@@ -595,6 +597,12 @@ Jonathan Yap
STORM-1719
STORM-1712
STORM-1728
+ STORM-1736
+ STORM-1734
+ STORM-1731
+ STORM-653
+ STORM-1737
+ STORM-1733
Kadah Coba
STORM-1060
Jondan Lundquist
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index d781687175..19075afa68 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -608,6 +608,7 @@ LLCPUInfo::LLCPUInfo()
out << " (" << mCPUMHz << " MHz)";
}
mCPUString = out.str();
+ LLStringUtil::trim(mCPUString);
}
bool LLCPUInfo::hasAltivec() const
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 40291a2569..f0e0de6173 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -187,11 +187,14 @@ public:
LLMutexLock(LLMutex* mutex)
{
mMutex = mutex;
- mMutex->lock();
+
+ if(mMutex)
+ mMutex->lock();
}
~LLMutexLock()
{
- mMutex->unlock();
+ if(mMutex)
+ mMutex->unlock();
}
private:
LLMutex* mMutex;
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 7ca25d07fc..f569630766 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -219,11 +219,15 @@ namespace boost
std::set<CURL*> LLCurl::Easy::sFreeHandles;
std::set<CURL*> LLCurl::Easy::sActiveHandles;
+LLMutex* LLCurl::Easy::sHandleMutexp = NULL ;
//static
CURL* LLCurl::Easy::allocEasyHandle()
{
CURL* ret = NULL;
+
+ LLMutexLock lock(sHandleMutexp) ;
+
if (sFreeHandles.empty())
{
ret = curl_easy_init();
@@ -251,6 +255,7 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle)
llerrs << "handle cannot be NULL!" << llendl;
}
+ LLMutexLock lock(sHandleMutexp) ;
if (sActiveHandles.find(handle) != sActiveHandles.end())
{
sActiveHandles.erase(handle);
@@ -512,20 +517,21 @@ void LLCurl::Easy::prepRequest(const std::string& url,
}
////////////////////////////////////////////////////////////////////////////
-
+LLMutex* LLCurl::Multi::sMultiInitMutexp = NULL ;
LLCurl::Multi::Multi()
: mQueued(0),
mErrorCount(0),
mState(STATE_READY),
mDead(FALSE),
mMutexp(NULL),
- mDeletionMutexp(NULL)
+ mDeletionMutexp(NULL),
+ mEasyMutexp(NULL)
{
- mCurlMultiHandle = curl_multi_init();
+ mCurlMultiHandle = initMulti();
if (!mCurlMultiHandle)
{
llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
- mCurlMultiHandle = curl_multi_init();
+ mCurlMultiHandle = initMulti();
}
llassert_always(mCurlMultiHandle);
@@ -534,6 +540,7 @@ LLCurl::Multi::Multi()
{
mMutexp = new LLMutex(NULL) ;
mDeletionMutexp = new LLMutex(NULL) ;
+ mEasyMutexp = new LLMutex(NULL) ;
}
LLCurl::getCurlThread()->addMulti(this) ;
@@ -563,10 +570,19 @@ LLCurl::Multi::~Multi()
mMutexp = NULL ;
delete mDeletionMutexp ;
mDeletionMutexp = NULL ;
+ delete mEasyMutexp ;
+ mEasyMutexp = NULL ;
--gCurlMultiCount;
}
+CURLM* LLCurl::Multi::initMulti()
+{
+ LLMutexLock lock(sMultiInitMutexp) ;
+
+ return curl_multi_init() ;
+}
+
void LLCurl::Multi::lock()
{
if(mMutexp)
@@ -585,39 +601,26 @@ void LLCurl::Multi::unlock()
void LLCurl::Multi::markDead()
{
- if(mDeletionMutexp)
- {
- mDeletionMutexp->lock() ;
- }
-
+ LLMutexLock lock(mDeletionMutexp) ;
+
mDead = TRUE ;
-
- if(mDeletionMutexp)
- {
- mDeletionMutexp->unlock() ;
- }
}
void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
{
lock() ;
mState = state ;
+ unlock() ;
+
if(mState == STATE_READY)
{
LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ;
- }
- unlock() ;
+ }
}
LLCurl::Multi::ePerformState LLCurl::Multi::getState()
{
- ePerformState state ;
-
- lock() ;
- state = mState ;
- unlock() ;
-
- return state ;
+ return mState;
}
bool LLCurl::Multi::isCompleted()
@@ -633,21 +636,19 @@ bool LLCurl::Multi::waitToComplete()
return true ;
}
- bool completed ;
-
- lock() ;
- completed = (STATE_COMPLETED == mState) ;
+ bool completed = (STATE_COMPLETED == mState) ;
if(!completed)
{
LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;
}
- unlock() ;
-
+
return completed;
}
CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
{
+ LLMutexLock lock(mMutexp) ;
+
CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue);
return curlmsg;
}
@@ -655,10 +656,8 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
//return true if dead
bool LLCurl::Multi::doPerform()
{
- if(mDeletionMutexp)
- {
- mDeletionMutexp->lock() ;
- }
+ LLMutexLock lock(mDeletionMutexp) ;
+
bool dead = mDead ;
if(mDead)
@@ -675,6 +674,7 @@ bool LLCurl::Multi::doPerform()
call_count < MULTI_PERFORM_CALL_REPEAT;
call_count++)
{
+ LLMutexLock lock(mMutexp) ;
CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
{
@@ -688,11 +688,6 @@ bool LLCurl::Multi::doPerform()
setState(STATE_COMPLETED) ;
}
- if(mDeletionMutexp)
- {
- mDeletionMutexp->unlock() ;
- }
-
return dead ;
}
@@ -715,10 +710,19 @@ S32 LLCurl::Multi::process()
if (msg->msg == CURLMSG_DONE)
{
U32 response = 0;
- easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle);
- if (iter != mEasyActiveMap.end())
+ Easy* easy = NULL ;
+
+ {
+ LLMutexLock lock(mEasyMutexp) ;
+ easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle);
+ if (iter != mEasyActiveMap.end())
+ {
+ easy = iter->second;
+ }
+ }
+
+ if(easy)
{
- Easy* easy = iter->second;
response = easy->report(msg->data.result);
removeEasy(easy);
}
@@ -743,19 +747,21 @@ S32 LLCurl::Multi::process()
LLCurl::Easy* LLCurl::Multi::allocEasy()
{
- Easy* easy = 0;
+ Easy* easy = 0;
if (mEasyFreeList.empty())
- {
+ {
easy = Easy::getEasy();
}
else
{
+ LLMutexLock lock(mEasyMutexp) ;
easy = *(mEasyFreeList.begin());
mEasyFreeList.erase(easy);
}
if (easy)
{
+ LLMutexLock lock(mEasyMutexp) ;
mEasyActiveList.insert(easy);
mEasyActiveMap[easy->getCurlHandle()] = easy;
}
@@ -764,6 +770,7 @@ LLCurl::Easy* LLCurl::Multi::allocEasy()
bool LLCurl::Multi::addEasy(Easy* easy)
{
+ LLMutexLock lock(mMutexp) ;
CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle());
check_curl_multi_code(mcode);
//if (mcode != CURLM_OK)
@@ -776,22 +783,41 @@ bool LLCurl::Multi::addEasy(Easy* easy)
void LLCurl::Multi::easyFree(Easy* easy)
{
+ if(mEasyMutexp)
+ {
+ mEasyMutexp->lock() ;
+ }
+
mEasyActiveList.erase(easy);
mEasyActiveMap.erase(easy->getCurlHandle());
+
if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE)
- {
- easy->resetState();
+ {
mEasyFreeList.insert(easy);
+
+ if(mEasyMutexp)
+ {
+ mEasyMutexp->unlock() ;
+ }
+
+ easy->resetState();
}
else
{
+ if(mEasyMutexp)
+ {
+ mEasyMutexp->unlock() ;
+ }
delete easy;
}
}
void LLCurl::Multi::removeEasy(Easy* easy)
{
- check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
+ {
+ LLMutexLock lock(mMutexp) ;
+ check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
+ }
easyFree(easy);
}
@@ -834,11 +860,17 @@ void LLCurlThread::CurlRequest::finishRequest(bool completed)
LLCurlThread::LLCurlThread(bool threaded) :
LLQueuedThread("curlthread", threaded)
{
+ if(!LLCurl::Multi::sMultiInitMutexp)
+ {
+ LLCurl::Multi::sMultiInitMutexp = new LLMutex(NULL) ;
+ }
}
//virtual
LLCurlThread::~LLCurlThread()
{
+ delete LLCurl::Multi::sMultiInitMutexp ;
+ LLCurl::Multi::sMultiInitMutexp = NULL ;
}
S32 LLCurlThread::update(U32 max_time_ms)
@@ -1290,6 +1322,10 @@ void LLCurl::initClass(bool multi_threaded)
#endif
sCurlThread = new LLCurlThread(multi_threaded) ;
+ if(multi_threaded)
+ {
+ Easy::sHandleMutexp = new LLMutex(NULL) ;
+ }
}
void LLCurl::cleanupClass()
@@ -1319,6 +1355,9 @@ void LLCurl::cleanupClass()
Easy::sFreeHandles.clear();
+ delete Easy::sHandleMutexp ;
+ Easy::sHandleMutexp = NULL ;
+
llassert(Easy::sActiveHandles.empty());
}
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index a275db3e53..705cdcbbcc 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -253,6 +253,7 @@ private:
static std::set<CURL*> sFreeHandles;
static std::set<CURL*> sActiveHandles;
+ static LLMutex* sHandleMutexp ;
};
class LLCurl::Multi
@@ -298,6 +299,7 @@ public:
S32 mQueued;
S32 mErrorCount;
+ static CURLM* initMulti() ;
private:
void easyFree(LLCurl::Easy*);
@@ -316,6 +318,9 @@ private:
BOOL mDead ;
LLMutex* mMutexp ;
LLMutex* mDeletionMutexp ;
+ LLMutex* mEasyMutexp ;
+
+ static LLMutex* sMultiInitMutexp ;
};
class LLCurlThread : public LLQueuedThread
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 607473d416..82e8227ffe 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -304,6 +304,18 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
S32 next_bitmap_num = fgi->mBitmapNum;
if (next_bitmap_num != bitmap_num)
{
+ // Actually draw the queued glyphs before switching their texture;
+ // otherwise the queued glyphs will be taken from wrong textures.
+ if (glyph_count > 0)
+ {
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
+ }
+ gGL.end();
+ glyph_count = 0;
+ }
+
bitmap_num = next_bitmap_num;
LLImageGL *font_image = font_bitmap_cache->getImageGL(bitmap_num);
gGL.getTexUnit(0)->bind(font_image);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b45f9c55fb..0861fe85a8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -75,6 +75,7 @@
//#include "llfirstuse.h"
#include "llrender.h"
#include "llteleporthistory.h"
+#include "lltoast.h"
#include "lllocationhistory.h"
#include "llfasttimerview.h"
#include "llvector4a.h"
@@ -4051,6 +4052,7 @@ void LLAppViewer::idle()
LLFrameTimer::updateFrameTime();
LLFrameTimer::updateFrameCount();
LLEventTimer::updateClass();
+ LLNotificationsUI::LLToast::updateClass();
LLCriticalDamp::updateInterpolants();
LLMortician::updateClass();
LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify()
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index a076374903..045c9017be 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -250,6 +250,12 @@ LLIMWellChiclet::LLIMWellChiclet(const Params& p)
LLIMWellChiclet::~LLIMWellChiclet()
{
+ LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance();
+ if (im_well_window)
+ {
+ im_well_window->setSysWellChiclet(NULL);
+ }
+
LLIMMgr::getInstance()->removeSessionObserver(this);
}
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index 54598f90c8..e9c7a3fa03 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -328,6 +328,19 @@ BOOL LLCOFWearables::postBuild()
return LLPanel::postBuild();
}
+void LLCOFWearables::setAttachmentsTitle()
+{
+ if (mAttachmentsTab)
+ {
+ U32 free_slots = MAX_AGENT_ATTACHMENTS - mAttachments->size();
+
+ LLStringUtil::format_map_t args_attachments;
+ args_attachments["[COUNT]"] = llformat ("%d", free_slots);
+ std::string attachments_title = LLTrans::getString("Attachments remain", args_attachments);
+ mAttachmentsTab->setTitle(attachments_title);
+ }
+}
+
void LLCOFWearables::onSelectionChange(LLFlatListView* selected_list)
{
if (!selected_list) return;
@@ -490,6 +503,7 @@ void LLCOFWearables::populateAttachmentsAndBodypartsLists(const LLInventoryModel
{
mAttachments->sort();
mAttachments->notify(REARRANGE); //notifying the parent about the list's size change (cause items were added with rearrange=false)
+ setAttachmentsTitle();
}
else
{
diff --git a/indra/newview/llcofwearables.h b/indra/newview/llcofwearables.h
index 1f8d6d0c94..9957d6a64e 100644
--- a/indra/newview/llcofwearables.h
+++ b/indra/newview/llcofwearables.h
@@ -91,6 +91,8 @@ public:
*/
void selectClothing(LLWearableType::EType clothing_type);
+ void setAttachmentsTitle();
+
protected:
void populateAttachmentsAndBodypartsLists(const LLInventoryModel::item_array_t& cof_items);
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index ed4bb727cd..a856bd0bdc 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -2403,15 +2403,6 @@ void LLIMMgr::addMessage(
bool link_name) // If this is true, then we insert the name and link it to a profile
{
LLUUID other_participant_id = target_id;
-
- // don't process muted IMs
- if (LLMuteList::getInstance()->isMuted(
- other_participant_id,
- LLMute::flagTextChat) && !LLMuteList::getInstance()->isLinden(from))
- {
- return;
- }
-
LLUUID new_session_id = session_id;
if (new_session_id.isNull())
{
@@ -2452,10 +2443,25 @@ void LLIMMgr::addMessage(
LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str());
}
+ // Logically it would make more sense to reject the session sooner, in another area of the
+ // code, but the session has to be established inside the server before it can be left.
+ if (LLMuteList::getInstance()->isMuted(other_participant_id) && !LLMuteList::getInstance()->isLinden(from))
+ {
+ llwarns << "Leaving IM session from initiating muted resident " << from << llendl;
+ if(!gIMMgr->leaveSession(new_session_id))
+ {
+ llinfos << "Session " << new_session_id << " does not exist." << llendl;
+ }
+ return;
+ }
+
make_ui_sound("UISndNewIncomingIMSession");
}
- LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
+ if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat))
+ {
+ LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
+ }
}
void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args)
@@ -2661,18 +2667,15 @@ void LLIMMgr::inviteToSession(
const std::string& session_handle,
const std::string& session_uri)
{
- //ignore invites from muted residents
- if (LLMuteList::getInstance()->isMuted(caller_id))
- {
- return;
- }
-
std::string notify_box_type;
// voice invite question is different from default only for group call (EXT-7118)
std::string question_type = "VoiceInviteQuestionDefault";
BOOL ad_hoc_invite = FALSE;
BOOL voice_invite = FALSE;
+ bool is_linden = LLMuteList::getInstance()->isLinden(caller_name);
+
+
if(type == IM_SESSION_P2P_INVITE)
{
//P2P is different...they only have voice invitations
@@ -2711,7 +2714,18 @@ void LLIMMgr::inviteToSession(
payload["session_uri"] = session_uri;
payload["notify_box_type"] = notify_box_type;
payload["question_type"] = question_type;
-
+
+ //ignore invites from muted residents
+ if (LLMuteList::getInstance()->isMuted(caller_id) && !is_linden)
+ {
+ if (voice_invite && "VoiceInviteQuestionDefault" == question_type)
+ {
+ llinfos << "Rejecting voice call from initiating muted resident " << caller_name << llendl;
+ LLIncomingCallDialog::processCallResponse(1, payload);
+ }
+ return;
+ }
+
LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(session_id);
if (channelp && channelp->callStarted())
{
@@ -3234,7 +3248,7 @@ public:
chat.mFromID = from_id;
chat.mFromName = name;
- if (!is_linden && (is_busy || is_muted))
+ if (!is_linden && is_busy)
{
return;
}
@@ -3266,6 +3280,11 @@ public:
ll_vector3_from_sd(message_params["position"]),
true);
+ if (LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat))
+ {
+ return;
+ }
+
//K now we want to accept the invitation
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index b73d97e4c4..03404e816b 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -356,9 +356,9 @@ LLEditWearableDictionary::ColorSwatchCtrls::ColorSwatchCtrls()
LLEditWearableDictionary::TextureCtrls::TextureCtrls()
{
- addEntry ( TEX_HEAD_BODYPAINT, new PickerControlEntry (TEX_HEAD_BODYPAINT, "Head Tattoos", LLUUID::null, TRUE ));
- addEntry ( TEX_UPPER_BODYPAINT, new PickerControlEntry (TEX_UPPER_BODYPAINT, "Upper Tattoos", LLUUID::null, TRUE ));
- addEntry ( TEX_LOWER_BODYPAINT, new PickerControlEntry (TEX_LOWER_BODYPAINT, "Lower Tattoos", LLUUID::null, TRUE ));
+ addEntry ( TEX_HEAD_BODYPAINT, new PickerControlEntry (TEX_HEAD_BODYPAINT, "Head", LLUUID::null, TRUE ));
+ addEntry ( TEX_UPPER_BODYPAINT, new PickerControlEntry (TEX_UPPER_BODYPAINT, "Upper Body", LLUUID::null, TRUE ));
+ addEntry ( TEX_LOWER_BODYPAINT, new PickerControlEntry (TEX_LOWER_BODYPAINT, "Lower Body", LLUUID::null, TRUE ));
addEntry ( TEX_HAIR, new PickerControlEntry (TEX_HAIR, "Texture", LLUUID( gSavedSettings.getString( "UIImgDefaultHairUUID" ) ), FALSE ));
addEntry ( TEX_EYES_IRIS, new PickerControlEntry (TEX_EYES_IRIS, "Iris", LLUUID( gSavedSettings.getString( "UIImgDefaultEyesUUID" ) ), FALSE ));
addEntry ( TEX_UPPER_SHIRT, new PickerControlEntry (TEX_UPPER_SHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShirtUUID" ) ), FALSE ));
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 85a7e75271..6f98be1cb8 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -408,9 +408,16 @@ void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id)
}
// remove related chiclet
- LLChicletBar::getInstance()->getChicletPanel()->removeChiclet(notification_id);
+ if (LLChicletBar::instanceExists())
+ {
+ LLChicletBar::getInstance()->getChicletPanel()->removeChiclet(notification_id);
+ }
- LLIMWellWindow::getInstance()->removeObjectRow(notification_id);
+ LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance();
+ if (im_well_window)
+ {
+ im_well_window->removeObjectRow(notification_id);
+ }
mNotifications.erase(notification_id);
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 3aa6a3b7e5..0cb6c85012 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -159,6 +159,7 @@ void LLSysWellWindow::setVisible(BOOL visible)
LLTransientDockableFloater::setVisible(visible);
// update notification channel state
+ initChannel(); // make sure the channel still exists
if(mChannel)
{
mChannel->updateShowToastsState();
@@ -598,6 +599,13 @@ LLIMWellWindow* LLIMWellWindow::getInstance(const LLSD& key /*= LLSD()*/)
return LLFloaterReg::getTypedInstance<LLIMWellWindow>("im_well_window", key);
}
+
+// static
+LLIMWellWindow* LLIMWellWindow::findInstance(const LLSD& key /*= LLSD()*/)
+{
+ return LLFloaterReg::findTypedInstance<LLIMWellWindow>("im_well_window", key);
+}
+
BOOL LLIMWellWindow::postBuild()
{
BOOL rv = LLSysWellWindow::postBuild();
@@ -751,7 +759,10 @@ void LLIMWellWindow::removeObjectRow(const LLUUID& notification_id)
{
if (mMessageList->removeItemByValue(notification_id))
{
- mSysWellChiclet->updateWidget(isWindowEmpty());
+ if (mSysWellChiclet)
+ {
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+ }
}
else
{
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 52e5370505..272e9cfcb1 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -153,6 +153,7 @@ public:
~LLIMWellWindow();
static LLIMWellWindow* getInstance(const LLSD& key = LLSD());
+ static LLIMWellWindow* findInstance(const LLSD& key = LLSD());
static void initClass() { getInstance(); }
/*virtual*/ BOOL postBuild();
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index c4b226b70b..da691a2d0c 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -140,7 +140,9 @@ LLToast::LLToast(const LLToast::Params& p)
// init callbacks if present
if(!p.on_delete_toast().empty())
+ {
mOnDeleteToastSignal.connect(p.on_delete_toast());
+ }
}
void LLToast::reshape(S32 width, S32 height, BOOL called_from_parent)
@@ -236,7 +238,9 @@ void LLToast::setCanFade(bool can_fade)
{
mCanFade = can_fade;
if(!mCanFade)
+ {
mTimer->stop();
+ }
}
//--------------------------------------------------------------------------
@@ -328,55 +332,6 @@ void LLToast::draw()
drawChild(mHideBtn);
}
}
-
- updateHoveredState();
-
- LLToastLifeTimer* timer = getTimer();
- if (!timer)
- {
- return;
- }
-
- // Started timer means the mouse had left the toast previously.
- // If toast is hovered in the current frame we should handle
- // a mouse enter event.
- if(timer->getStarted() && mIsHovered)
- {
- mOnToastHoverSignal(this, MOUSE_ENTER);
-
- updateTransparency();
-
- //toasts fading is management by Screen Channel
-
- sendChildToFront(mHideBtn);
- if(mHideBtn && mHideBtn->getEnabled())
- {
- mHideBtn->setVisible(TRUE);
- }
- mToastMouseEnterSignal(this, getValue());
- }
- // Stopped timer means the mouse had entered the toast previously.
- // If the toast is not hovered in the current frame we should handle
- // a mouse leave event.
- else if(!timer->getStarted() && !mIsHovered)
- {
- mOnToastHoverSignal(this, MOUSE_LEAVE);
-
- updateTransparency();
-
- //toasts fading is management by Screen Channel
-
- if(mHideBtn && mHideBtn->getEnabled())
- {
- if( mHideBtnPressed )
- {
- mHideBtnPressed = false;
- return;
- }
- mHideBtn->setVisible(FALSE);
- }
- mToastMouseLeaveSignal(this, getValue());
- }
}
//--------------------------------------------------------------------------
@@ -440,28 +395,80 @@ void LLToast::updateHoveredState()
{
// mouse is not over this toast
mIsHovered = false;
- return;
}
+ else
+ {
+ bool is_overlapped_by_other_floater = false;
- bool is_overlapped_by_other_floater = false;
-
- const child_list_t* child_list = gFloaterView->getChildList();
+ const child_list_t* child_list = gFloaterView->getChildList();
- // find this toast in gFloaterView child list to check whether any floater
- // with higher Z-order is visible under the mouse pointer overlapping this toast
- child_list_const_reverse_iter_t r_iter = std::find(child_list->rbegin(), child_list->rend(), this);
- if (r_iter != child_list->rend())
- {
- // skip this toast and proceed to views above in Z-order
- for (++r_iter; r_iter != child_list->rend(); ++r_iter)
+ // find this toast in gFloaterView child list to check whether any floater
+ // with higher Z-order is visible under the mouse pointer overlapping this toast
+ child_list_const_reverse_iter_t r_iter = std::find(child_list->rbegin(), child_list->rend(), this);
+ if (r_iter != child_list->rend())
{
- LLView* view = *r_iter;
- is_overlapped_by_other_floater = view->isInVisibleChain() && view->calcScreenRect().pointInRect(x, y);
- if (is_overlapped_by_other_floater) break;
+ // skip this toast and proceed to views above in Z-order
+ for (++r_iter; r_iter != child_list->rend(); ++r_iter)
+ {
+ LLView* view = *r_iter;
+ is_overlapped_by_other_floater = view->isInVisibleChain() && view->calcScreenRect().pointInRect(x, y);
+ if (is_overlapped_by_other_floater)
+ {
+ break;
+ }
+ }
}
+
+ mIsHovered = !is_overlapped_by_other_floater;
}
- mIsHovered = !is_overlapped_by_other_floater;
+ LLToastLifeTimer* timer = getTimer();
+
+ if (timer)
+ {
+ // Started timer means the mouse had left the toast previously.
+ // If toast is hovered in the current frame we should handle
+ // a mouse enter event.
+ if(timer->getStarted() && mIsHovered)
+ {
+ mOnToastHoverSignal(this, MOUSE_ENTER);
+
+ updateTransparency();
+
+ //toasts fading is management by Screen Channel
+
+ sendChildToFront(mHideBtn);
+ if(mHideBtn && mHideBtn->getEnabled())
+ {
+ mHideBtn->setVisible(TRUE);
+ }
+
+ mToastMouseEnterSignal(this, getValue());
+ }
+ // Stopped timer means the mouse had entered the toast previously.
+ // If the toast is not hovered in the current frame we should handle
+ // a mouse leave event.
+ else if(!timer->getStarted() && !mIsHovered)
+ {
+ mOnToastHoverSignal(this, MOUSE_LEAVE);
+
+ updateTransparency();
+
+ //toasts fading is management by Screen Channel
+
+ if(mHideBtn && mHideBtn->getEnabled())
+ {
+ if( mHideBtnPressed )
+ {
+ mHideBtnPressed = false;
+ return;
+ }
+ mHideBtn->setVisible(FALSE);
+ }
+
+ mToastMouseLeaveSignal(this, getValue());
+ }
+ }
}
void LLToast::setBackgroundOpaque(BOOL b)
@@ -553,3 +560,14 @@ S32 LLToast::notifyParent(const LLSD& info)
return LLModalDialog::notifyParent(info);
}
+
+//static
+void LLToast::updateClass()
+{
+ for (LLInstanceTracker<LLToast>::instance_iter iter = LLInstanceTracker<LLToast>::beginInstances(); iter != LLInstanceTracker<LLToast>::endInstances(); )
+ {
+ LLToast& toast = *iter++;
+
+ toast.updateHoveredState();
+ }
+}
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 77229e7beb..0b06728935 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -27,7 +27,7 @@
#ifndef LL_LLTOAST_H
#define LL_LLTOAST_H
-
+#include "llinstancetracker.h"
#include "llpanel.h"
#include "llmodaldialog.h"
#include "lleventtimer.h"
@@ -69,7 +69,7 @@ private :
* Represents toast pop-up.
* This is a parent view for all toast panels.
*/
-class LLToast : public LLModalDialog
+class LLToast : public LLModalDialog, public LLInstanceTracker<LLToast>
{
friend class LLToastLifeTimer;
public:
@@ -102,6 +102,8 @@ public:
Params();
};
+
+ static void updateClass();
LLToast(const LLToast::Params& p);
virtual ~LLToast();
@@ -221,7 +223,7 @@ private:
F32 mToastLifetime; // in seconds
F32 mToastFadingTime; // in seconds
-
+
LLPanel* mPanel;
LLButton* mHideBtn;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index ad333a71ff..3c6770df43 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2235,6 +2235,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
name = LLTrans::getString("Unnamed");
}
+
+ // Preserve the unaltered name for use in group notice mute checking.
+ std::string original_name = name;
+
// IDEVO convert new-style "Resident" names for display
name = clean_name_from_im(name, dialog);
@@ -2441,6 +2445,26 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
break;
}
+ // The group notice packet does not have an AgentID. Obtain one from the name cache.
+ // If last name is "Resident" strip it out so the cache name lookup works.
+ U32 index = original_name.find(" Resident");
+ if (index != std::string::npos)
+ {
+ original_name = original_name.substr(0, index);
+ }
+ std::string legacy_name = gCacheName->buildLegacyName(original_name);
+ LLUUID agent_id;
+ gCacheName->getUUID(legacy_name, agent_id);
+
+ if (agent_id.isNull())
+ {
+ LL_WARNS("Messaging") << "buildLegacyName returned null while processing " << original_name << LL_ENDL;
+ }
+ else if (LLMuteList::getInstance()->isMuted(agent_id))
+ {
+ break;
+ }
+
notice_bin_bucket = (struct notice_bucket_full_t*) &binary_bucket[0];
U8 has_inventory = notice_bin_bucket->header.has_inventory;
U8 asset_type = notice_bin_bucket->header.asset_type;
@@ -5206,6 +5230,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
BOOL is_dest_group = FALSE;
S32 amount = 0;
std::string item_description;
+ BOOL success = FALSE;
msg->getS32("TransactionInfo", "TransactionType", transaction_type);
msg->getUUID("TransactionInfo", "SourceID", source_id);
@@ -5214,6 +5239,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
msg->getBOOL("TransactionInfo", "IsDestGroup", is_dest_group);
msg->getS32("TransactionInfo", "Amount", amount);
msg->getString("TransactionInfo", "ItemDescription", item_description);
+ msg->getBOOL("MoneyData", "TransactionSuccess", success);
LL_INFOS("Money") << "MoneyBalanceReply source " << source_id
<< " dest " << dest_id
<< " type " << transaction_type
@@ -5275,28 +5301,32 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
{
if (dest_id.notNull())
{
- message = LLTrans::getString("you_paid_ldollars", args);
+ message = success ? LLTrans::getString("you_paid_ldollars", args) :
+ LLTrans::getString("you_paid_failure_ldollars", args);
}
else
{
// transaction fee to the system, eg, to create a group
- message = LLTrans::getString("you_paid_ldollars_no_name", args);
+ message = success ? LLTrans::getString("you_paid_ldollars_no_name", args) :
+ LLTrans::getString("you_paid_failure_ldollars_no_name", args);
}
}
else
{
if (dest_id.notNull())
{
- message = LLTrans::getString("you_paid_ldollars_no_reason", args);
+ message = success ? LLTrans::getString("you_paid_ldollars_no_reason", args) :
+ LLTrans::getString("you_paid_failure_ldollars_no_reason", args);
}
else
{
// no target, no reason, you just paid money
- message = LLTrans::getString("you_paid_ldollars_no_info", args);
+ message = success ? LLTrans::getString("you_paid_ldollars_no_info", args) :
+ LLTrans::getString("you_paid_failure_ldollars_no_info", args);
}
}
final_args["MESSAGE"] = message;
- notification = "PaymentSent";
+ notification = success ? "PaymentSent" : "PaymentFailure";
}
else {
// ...someone paid you
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 5fe8f3c114..a2739a8339 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -3,7 +3,7 @@
legacy_header_height="18"
background_visible="true"
default_tab_group="1"
- height="350"
+ height="355"
help_topic="floater_im_box"
layout="topleft"
name="panel_im"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index b90d65b83a..d52b05d77c 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1730,7 +1730,17 @@
function="ToggleControl"
parameter="MouseSmooth" />
</menu_item_check>
-
+ <menu_item_call
+ enabled="false"
+ label="Release Keys"
+ name="Release Keys">
+ <menu_item_call.on_click
+ function="Tools.ReleaseKeys"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="Tools.EnableReleaseKeys"
+ parameter="" />
+ </menu_item_call>
<menu_item_separator/>
<menu
@@ -1760,17 +1770,7 @@
function="Floater.Toggle"
parameter="search" />
</menu_item_check>
- <menu_item_call
- enabled="false"
- label="Release Keys"
- name="Release Keys">
- <menu_item_call.on_click
- function="Tools.ReleaseKeys"
- parameter="" />
- <menu_item_call.on_enable
- function="Tools.EnableReleaseKeys"
- parameter="" />
- </menu_item_call>
+
<!-- This second, alternative shortcut for Show Advanced Menu is for backward compatibility. The main shortcut has been changed so it's Linux-friendly, where the old shortcut is typically eaten by the window manager. -->
<menu_item_check
label="Show Advanced Menu - legacy shortcut"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 0ba4b84abe..a7705c8bac 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5516,6 +5516,15 @@ Please select at least one type of content to search (General, Moderate, or Adul
[MESSAGE]
</notification>
+ <notification
+ icon="notify.tga"
+ name="PaymentFailure"
+ persist="true"
+ type="notify">
+ <tag>funds</tag>
+[MESSAGE]
+ </notification>
+
<!-- EventNotification couldn't be persist since server decide is it necessary to notify
user about subscribed event via LLEventNotifier-->
<notification
diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
index e70abc0975..93cafd4a53 100644
--- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
@@ -58,7 +58,7 @@
label="Call"
name="call_btn"
width="130"
- top="5" />
+ top="0" />
</layout_panel>
<layout_panel
auto_resize="false"
@@ -75,7 +75,7 @@
height="20"
label="Leave Call"
name="end_call_btn"
- top="5"/>
+ top="0"/>
</layout_panel>
<layout_panel
auto_resize="false"
@@ -92,7 +92,7 @@
height="20"
label="Voice Controls"
name="voice_ctrls_btn"
- top="5"
+ top="0"
use_ellipses="true" />
</layout_panel>
</layout_stack>
diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml
index beea53437a..aa8e3d07a6 100644
--- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml
+++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml
@@ -37,6 +37,7 @@
top="0"
width="311" />
</accordion_tab>
+ <!-- The Attachments title is overwritten by the definition of "Attachments remain" in strings.xml -->
<accordion_tab
layout="topleft"
name="tab_attachments"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_skin.xml b/indra/newview/skins/default/xui/en/panel_edit_skin.xml
index 45591ba2ad..b61f65a3d1 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_skin.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_skin.xml
@@ -27,10 +27,10 @@
default_image_name="Default"
follows="left|top"
height="80"
- label="Head Tattoos"
+ label="Head"
layout="topleft"
left="25"
- name="Head Tattoos"
+ name="Head"
tool_tip="Click to choose a picture"
top="10"
width="74" >
@@ -43,10 +43,10 @@
default_image_name="Default"
follows="left|top"
height="80"
- label="Upper Tattoos"
+ label="Upper body"
layout="topleft"
left_pad="20"
- name="Upper Tattoos"
+ name="Upper Body"
tool_tip="Click to choose a picture"
top="10"
width="74" >
@@ -59,10 +59,10 @@
default_image_name="Default"
follows="left|top"
height="80"
- label="Lower Tattoos"
+ label="Lower body"
layout="topleft"
left_pad="20"
- name="Lower Tattoos"
+ name="Lower Body"
tool_tip="Click to choose a picture"
top="10"
width="74" >
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 664d60f8b5..0b878768ec 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2133,6 +2133,7 @@ Returns a string with the requested data about the region
<string name="InvFolder All">All</string>
<string name="no_attachments">No attachments worn</string>
+ <string name="Attachments remain">Attachments ([COUNT] slots remain)</string>
<!-- inventory FVBridge -->
<!-- This is used in llpanelinventory.cpp when constructing a context menu for an item for Sale -->
@@ -3358,6 +3359,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="you_paid_ldollars_no_info">You paid L$[AMOUNT].</string>
<string name="you_paid_ldollars_no_reason">You paid [NAME] L$[AMOUNT].</string>
<string name="you_paid_ldollars_no_name">You paid L$[AMOUNT] [REASON].</string>
+ <string name="you_paid_failure_ldollars">You failed to pay [NAME] L$[AMOUNT] [REASON].</string>
+ <string name="you_paid_failure_ldollars_no_info">You failed to pay L$[AMOUNT].</string>
+ <string name="you_paid_failure_ldollars_no_reason">You failed to pay [NAME] L$[AMOUNT].</string>
+ <string name="you_paid_failure_ldollars_no_name">You failed to pay L$[AMOUNT] [REASON].</string>
<string name="for item">for [ITEM]</string>
<string name="for a parcel of land">for a parcel of land</string>
<string name="for a land access pass">for a land access pass</string>