diff --git a/doc/contributions.txt b/doc/contributions.txt
index c57a2792d99bdbb8805ae4e12f22186418267a8b..8606ad8c6cfd2a597df00b9f7d0abe8a8b924bf1 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -38,6 +38,7 @@ Alissa Sabre
 	VWR-2826
 	VWR-3290
 	VWR-4010
+	VWR-3410
 Angus Boyd
 	VWR-592
 Argent Stonecutter
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index c5bac32e91535401aca53d9d999930c3307387aa..f8b193d643142514cbae22dede2fd757134cf4a8 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -35,7 +35,7 @@
 const S32 LL_VERSION_MAJOR = 1;
 const S32 LL_VERSION_MINOR = 19;
 const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 2;
+const S32 LL_VERSION_BUILD = 4;
 
 const char * const LL_CHANNEL = "Second Life Release";
 
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 391b28a21fb94c597b77585d434d60655a59c2b7..6d5e589b0430de438f97b435845e3701052ac617 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -2317,6 +2317,12 @@ void LLLineEditor::resetPreedit()
 {
 	if (hasPreeditString())
 	{
+		if (hasSelection())
+		{
+			llwarns << "Preedit and selection!" << llendl;
+			deselect();
+		}
+
 		const S32 preedit_pos = mPreeditPositions.front();
 		mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos);
 		mText.insert(preedit_pos, mPreeditOverwrittenWString);
@@ -2326,11 +2332,10 @@ void LLLineEditor::resetPreedit()
 		mPreeditOverwrittenWString.clear();
 		mPreeditPositions.clear();
 
-		mKeystrokeTimer.reset();
-		if (mKeystrokeCallback)
-		{
-			mKeystrokeCallback(this, mCallbackUserData);
-		}
+		// Don't reset key stroke timer nor invoke keystroke callback,
+		// because a call to updatePreedit should be follow soon in 
+		// normal course of operation, and timer and callback will be 
+		// maintained there.  Doing so here made an odd sound.  (VWR-3410) 
 	}
 }
 
@@ -2343,27 +2348,10 @@ void LLLineEditor::updatePreedit(const LLWString &preedit_string,
 		return;
 	}
 
-	if (hasSelection())
-	{
-		if (hasPreeditString())
-		{
-			llwarns << "Preedit and selection!" << llendl;
-			deselect();
-		}
-		else
-		{
-			deleteSelection();
-		}
-	}
+	// Note that call to updatePreedit is always preceeded by resetPreedit,
+	// so we have no existing selection/preedit.
 
 	S32 insert_preedit_at = getCursor();
-	if (hasPreeditString())
-	{
-		insert_preedit_at = mPreeditPositions.front();
-		//mText.replace(insert_preedit_at, mPreeditPositions.back() - insert_preedit_at, mPreeditOverwrittenWString);
-		mText.erase(insert_preedit_at, mPreeditPositions.back() - insert_preedit_at);
-		mText.insert(insert_preedit_at, mPreeditOverwrittenWString);
-	}
 
 	mPreeditWString = preedit_string;
 	mPreeditPositions.resize(preedit_segment_lengths.size() + 1);
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 4c16683704fb88de96d748d4b681553fc1d4c86c..cb732a17c666bdf389608ec93ce871bc5183760e 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -212,10 +212,16 @@ void LLPanel::draw()
 	}
 
 	updateDefaultBtn();
+
+	LLView::draw();
 }
 
 void LLPanel::updateDefaultBtn()
 {
+	// This method does not call LLView::draw() so callers will need
+	// to take care of that themselves at the appropriate place in
+	// their rendering sequence
+
 	if( mDefaultBtn)
 	{
 		if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
@@ -230,8 +236,6 @@ void LLPanel::updateDefaultBtn()
 			mDefaultBtn->setBorderEnabled(FALSE);
 		}
 	}
-
-	LLView::draw();
 }
 
 void LLPanel::refresh()
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index c76576895c0b96d491d6282e12dacf0fda027fd2..0b6f5d75ccbb11ca3b66dd65f239934ec1d17e8f 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -4335,6 +4335,12 @@ void LLTextEditor::resetPreedit()
 {
 	if (hasPreeditString())
 	{
+		if (hasSelection())
+		{
+			llwarns << "Preedit and selection!" << llendl;
+			deselect();
+		}
+
 		mCursorPos = mPreeditPositions.front();
 		removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);
 		insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString);
@@ -4343,9 +4349,10 @@ void LLTextEditor::resetPreedit()
 		mPreeditOverwrittenWString.clear();
 		mPreeditPositions.clear();
 
-		updateLineStartList();
-		setCursorPos(mCursorPos);
-		// updateScrollFromCursor();
+		// A call to updatePreedit should soon follow under a
+		// normal course of operation, so we don't need to 
+		// maintain internal variables such as line start 
+		// positions now.
 	}
 }
 
@@ -4358,28 +4365,9 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,
 		return;
 	}
 
-	if (hasSelection())
-	{
-		if (hasPreeditString())
-		{
-			llwarns << "Preedit and selection!" << llendl;
-			deselect();
-		}
-		else
-		{
-			deleteSelection(TRUE);
-		}
-	}
-
 	getWindow()->hideCursorUntilMouseMove();
 
 	S32 insert_preedit_at = mCursorPos;
-	if (hasPreeditString())
-	{
-		insert_preedit_at = mPreeditPositions.front();
-		removeStringNoUndo(insert_preedit_at, mPreeditPositions.back() - insert_preedit_at);
-		insertStringNoUndo(insert_preedit_at, mPreeditOverwrittenWString);
-	}
 
 	mPreeditWString = preedit_string;
 	mPreeditPositions.resize(preedit_segment_lengths.size() + 1);
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 5184a6caec476a37c8291a242d5b33a1734a2f30..a1d97429e1abb2342d700eb436e5fa1db3e6c29d 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -2102,15 +2102,17 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
 						}
 
 						// Handle preedit string.
-						if (preedit_string.length() > 0)
+						if (preedit_string.length() == 0)
 						{
-							if (preedit_segment_lengths.size() == 0)
-							{
-								preedit_segment_lengths.push_back(preedit_string.length());
-								preedit_standouts.push_back(FALSE);
-							}
-							mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
+							preedit_segment_lengths.clear();
+							preedit_standouts.clear();
+						}
+						else if (preedit_segment_lengths.size() == 0)
+						{
+							preedit_segment_lengths.push_back(preedit_string.length());
+							preedit_standouts.push_back(FALSE);
 						}
+						mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
 
 						result = noErr;
 					}
@@ -3366,6 +3368,8 @@ void LLWindowMacOSX::interruptLanguageTextInput()
 	{
 		FixTSMDocument(mTSMDocument);
 	}
+	// Don't we need to call resetPreedit here?
+	// Well, if Apple's TSM document is correct, we don't.
 }
 
 #endif // LL_DARWIN
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 0bba56f74f515255dc14210f6aabe83e03ec811e..a5367aac8aedef30d1c98ad0f72e31112d9aa344 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -3716,6 +3716,10 @@ void LLWindowWin32::interruptLanguageTextInput()
 			LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
 			LLWinImm::releaseContext(mWindowHandle, himc);
 		}
+
+		// Win32 document says there will be no composition string
+		// after NI_COMPOSITIONSTR returns.  The following call to
+		// resetPreedit should be a NOP unless IME goes mad...
 		mPreeditor->resetPreedit();
 	}
 }
@@ -3859,7 +3863,12 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
 			}
 		}
 
-		if (preedit_string.length() > 0)
+		if (preedit_string.length() == 0)
+ 		{
+			preedit_segment_lengths.clear();
+			preedit_standouts.clear();
+		}
+		else
 		{
 			if (preedit_segment_lengths.size() == 0)
 			{
@@ -3869,8 +3878,8 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
 			{
 				preedit_standouts.assign(preedit_segment_lengths.size(), FALSE);
 			}
-			mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
 		}
+		mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position);
 
 		// Some IME doesn't query char position after WM_IME_COMPOSITION,
 		// so we need to update them actively.
diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings
index 76c69153c926be1ec364bd0249a515955795bc44..7ecd693ba465e4c4a12b208cc64c77da70141860 100644
--- a/indra/newview/English.lproj/InfoPlist.strings
+++ b/indra/newview/English.lproj/InfoPlist.strings
@@ -1,5 +1,5 @@
 /* Localized versions of Info.plist keys */
 
 CFBundleName = "Second Life";
-CFBundleShortVersionString = "Second Life version 1.19.0.2";
-CFBundleGetInfoString = "Second Life version 1.19.0.2, Copyright 2004-2007 Linden Research, Inc.";
+CFBundleShortVersionString = "Second Life version 1.19.0.4";
+CFBundleGetInfoString = "Second Life version 1.19.0.4, Copyright 2004-2007 Linden Research, Inc.";
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index c93fbe0986f044851318f0e5d206e0e55b39261f..50226d84aa856b069f5e833a1808bf7a162b53a5 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -32,7 +32,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>1.19.0.2</string>
+	<string>1.19.0.4</string>
 	<key>CSResourcesFileMapped</key>
 	<true/>
 </dict>
diff --git a/indra/newview/linux_tools/client-readme.txt b/indra/newview/linux_tools/client-readme.txt
index 89454e2ade03566db22b3a11f2e1861b3ed0fa18..ff607b778ab0aca60d5acaef6010b45dfad8a750 100644
--- a/indra/newview/linux_tools/client-readme.txt
+++ b/indra/newview/linux_tools/client-readme.txt
@@ -1,5 +1,5 @@
-Second Life - Linux Alpha README
--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Second Life - Linux Beta README
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
 This document contains information about the Second Life Linux
 client, and isn't meant to serve as an introduction to Second
@@ -26,16 +26,14 @@ Life itself - please see <http://www.secondlife.com/whatis/>.
 1. INTRODUCTION
 -=-=-=-=-=-=-=-
 
-Hi!  This is an ALPHA release of the Second Life client for Linux.
-The 'alpha' status means that not everything is implemented yet and
-we're still hard at work on this version of the client, but many
-residents find that it already works well 'out of the box' for accessing
-Second Life.
+Hi!  This is a BETA release of the Second Life client for Linux.
+The 'beta' status means that although we're still smoothing-out a few rough
+edges, this version of the client is functionally complete and should
+work quite well 'out of the box' for accessing Second Life.
 
 We encourage you to try it out and let us know of its compatibility
-with your system.  Be aware that although the client itself is provided
-for testing purposes, any changes you make within the Second Life world
-are permanent.
+with your system.  Be aware that although this is a 'beta' client, it connects
+to the main Second Life world and changes you make there are permanent.
 
 You will have either obtained this client from secondlife.com (the official
 site) or from a third-party packager; if you encounter any problems then
@@ -98,7 +96,7 @@ you wish.
 -=-=-=-=-=-=-=-
 
 These are the most commonly-encountered known issues which are specific to
-the Alpha release of the Linux client.
+the Beta release of the Linux client.
 
 * VISUAL EFFECTS AND PERFORMANCE - many Linux graphics drivers are not as
   robust as their counterparts for other operating systems, so some advanced
@@ -106,9 +104,9 @@ the Alpha release of the Linux client.
   stability.  See PROBLEM 3 in the TROUBLESHOOTING section if you wish to
   turn these on to possibly enhance your experience.
 
-* MISC - The following features are not currently fully implemented on the
-  Linux client and are therefore known not to work properly:
-  * Movie recording
+* MISC - The following features are known to not yet be fully operational on
+  the Linux client:
+  * Movie recording (soon to be deprecated)
   * Full Unicode font rendering
 
 * UPLOAD / SAVE / COLOR-PICKER DIALOGS - These only appear when the client
@@ -214,7 +212,7 @@ configuration options for advanced troubleshooters.
   you disable specific GL extensions, each of which is represented by a
   letter ("a"-"o").  If you can narrow down a stability problem on your system
   to just one or two GL extensions then please post details of your hardware
-  (and drivers) to the Linux Client Alpha Testers forum (see link below) along
+  (and drivers) to the Linux Client Testers forum (see link below) along
   with the minimal LL_GL_BLACKLIST which solves your problems.  This will help
   us to improve stability for your hardware while minimally impacting
   performance.
@@ -256,7 +254,7 @@ bugs in all Second Life releases if you find that the Troubleshooting
 section in this file hasn't helped (please note, however, that this is
 not a support forum).
 
-Linux Client Alpha Testers forum:
+Linux Client Testers forum:
 <http://forums.secondlife.com/forumdisplay.php?forumid=263>
 This is a forum where Linux Client users can help each other out and
 discuss the latest updates.
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index e7c47cbba6a60ef35e8f4ba795aeb1d9c15805de..070d45a5bb5dfdaffa0709b3d95289c188d554a9 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 
-## Here are some configuration options for Linux Client Alpha Testers.
-## These options are for self-assisted troubleshooting during this alpha
+## Here are some configuration options for Linux Client Testers.
+## These options are for self-assisted troubleshooting during this beta
 ## testing phase; you should not usually need to touch them.
 
 ## - Avoids using the ESD audio driver.
@@ -23,14 +23,14 @@
 
 ## - Avoids *all* optional OpenGL extensions.  This is the safest and least-
 ##   exciting option.  Enable this if you experience stability issues, and
-##   report whether it helps in the Linux Client Alpha Testers forum.
+##   report whether it helps in the Linux Client Testers forum.
 #export LL_GL_NOEXT=x
 
 ## - For advanced troubleshooters, this lets you disable specific GL
 ##   extensions, each of which is represented by a letter a-o.  If you can
 ##   narrow down a stability problem on your system to just one or two
 ##   extensions then please post details of your hardware (and drivers) to
-##   the Linux Client Alpha Testers forum along with the minimal
+##   the Linux Client Testers forum along with the minimal
 ##   LL_GL_BLACKLIST which solves your problems.
 #export LL_GL_BLACKLIST=abcdefghijklmno
 
@@ -122,8 +122,8 @@ fi
 	
 
 echo
-echo '*********************************************************'
-echo 'This is an ALPHA release of the Second Life linux client.'
+echo '*******************************************************'
+echo 'This is a BETA release of the Second Life linux client.'
 echo 'Thank you for testing!'
 echo 'Please see README-linux.txt before reporting problems.'
 echo
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 106b2b1517fcb9c892237e58a213b05f8d0795c1..666fcd130171f40e6421f5afe65999c970e6c7c1 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2599,43 +2599,36 @@ void LLAppViewer::setCrashBehavior(S32 cb)
 
 bool LLAppViewer::anotherInstanceRunning()
 {
-		// We create a marker file when the program starts and remove the file when it finishes.
+	// We create a marker file when the program starts and remove the file when it finishes.
 	// If the file is currently locked, that means another process is already running.
 
 	std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, MARKER_FILE_NAME);
 	llinfos << "Checking marker file for lock..." << llendl;
 
-	// If file doesn't exist, we create it
-	// If file does exist, try to get writing privileges
-	FILE* fMarker = LLFile::fopen(marker_file.c_str(), "rb");		// Flawfinder: ignore
+	//Freeze case checks
+	apr_file_t* fMarker = ll_apr_file_open(marker_file, LL_APR_RB);		
 	if (fMarker != NULL)
 	{
 		// File exists, try opening with write permissions
-		fclose(fMarker);
-		fMarker = LLFile::fopen(marker_file.c_str(), "wb");		// Flawfinder: ignore
+		apr_file_close(fMarker);
+		fMarker = ll_apr_file_open(marker_file, LL_APR_WB);
 		if (fMarker == NULL)
 		{
+			// Another instance is running. Skip the rest of these operations.
 			llinfos << "Marker file is locked." << llendl;
 			return TRUE;
 		}
-
-		// *FIX:Mani - rather than have this exception here, 
-		// LLFile::fopen() have consistent behavior across platforms?
-#if LL_DARWIN || LL_LINUX || LL_SOLARIS
-		// Try to lock it. On Mac, this is the only way to test if it's actually locked.
-		if (flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1)
+		if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1)
 		{
-			// Lock failed - somebody else has it.
-			fclose(fMarker);
+			apr_file_close(fMarker);
 			llinfos << "Marker file is locked." << llendl;
 			return TRUE;
 		}
-#endif
-		fclose(fMarker);
+		// No other instances; we'll lock this file now & delete on quit.
+		apr_file_close(fMarker);
 	}
 	llinfos << "Marker file isn't locked." << llendl;
 	return FALSE;
-
 }
 
 void LLAppViewer::initMarkerFile()
@@ -2677,25 +2670,10 @@ void LLAppViewer::initMarkerFile()
 	ll_apr_file_remove(error_marker_file);
 	
 	//Freeze case checks
+	if(anotherInstanceRunning()) return;
 	fMarker = ll_apr_file_open(mMarkerFileName, LL_APR_RB);		
 	if (fMarker != NULL)
 	{
-		// File exists, try opening with write permissions
-		apr_file_close(fMarker);
-		fMarker = ll_apr_file_open(mMarkerFileName, LL_APR_WB);
-		if (fMarker == NULL)
-		{
-			// Another instance is running. Skip the rest of these operations.
-			llinfos << "Marker file is locked." << llendl;
-			return;
-		}
-		if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1)
-		{
-			apr_file_close(fMarker);
-			llinfos << "Marker file is locked." << llendl;
-			return;
-		}
-		// No other instances; we'll lock this file now & delete on quit.
 		apr_file_close(fMarker);
 		gLastExecEvent = LAST_EXEC_FROZE;
 		llinfos << "Exec marker found: program froze on previous execution" << llendl;