diff options
23 files changed, 440 insertions, 128 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index cdda70a5c2..208bc534bf 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -95,6 +95,7 @@ Gigs Taggart VWR-101 VWR-166 VWR-234 + VWR-315 VWR-326 VWR-493 VWR-1203 diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index bef5ea5dbb..83f16e1556 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -743,6 +743,10 @@ void LLMotionController::updateMotion() { motion_set_t::iterator curiter = iter++; LLMotion* motionp = *curiter; + if( !motionp) + { + continue; // maybe shouldn't happen but i've seen it -MG + } LLMotion::LLMotionInitStatus status = motionp->onInitialize(mCharacter); if (status == LLMotion::STATUS_SUCCESS) { diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index 9a200cdf61..75cf24947d 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -79,10 +79,7 @@ bool LLImageWorker::doWork(S32 param) } else { - S32 nc = param ? 1 : mFormattedImage->getComponents(); - mDecodedImage = new LLImageRaw(mFormattedImage->getWidth(), - mFormattedImage->getHeight(), - nc); + mDecodedImage = new LLImageRaw(); // allow possibly smaller size set during decoding } } if (!decoded) diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 68a3152f0a..7def8ca07f 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -10,7 +10,6 @@ #include "llimagej2coj.h" // this is defined so that we get static linking. -#define OPJ_STATIC #include "openjpeg/openjpeg.h" #include "lltimer.h" diff --git a/indra/llmath/llquantize.h b/indra/llmath/llquantize.h index 8aa03628f2..93cd16c13a 100644 --- a/indra/llmath/llquantize.h +++ b/indra/llmath/llquantize.h @@ -20,6 +20,18 @@ const U8 FIRSTVALIDCHAR = 54; const U8 MAXSTRINGVAL = U8MAX - FIRSTVALIDCHAR; //we don't allow newline or null +inline U16 F32_to_U16_ROUND(F32 val, F32 lower, F32 upper) +{ + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); + + // round the value. Sreturn the U16 + return (U16)(llround(val*U16MAX)); +} + + inline U16 F32_to_U16(F32 val, F32 lower, F32 upper) { val = llclamp(val, lower, upper); @@ -47,6 +59,19 @@ inline F32 U16_to_F32(U16 ival, F32 lower, F32 upper) return val; } + +inline U8 F32_to_U8_ROUND(F32 val, F32 lower, F32 upper) +{ + val = llclamp(val, lower, upper); + // make sure that the value is positive and normalized to <0, 1> + val -= lower; + val /= (upper - lower); + + // return the rounded U8 + return (U8)(llround(val*U8MAX)); +} + + inline U8 F32_to_U8(F32 val, F32 lower, F32 upper) { val = llclamp(val, lower, upper); diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp index 8b2808164f..d5fe931187 100644 --- a/indra/llmath/llquaternion.cpp +++ b/indra/llmath/llquaternion.cpp @@ -87,23 +87,27 @@ void LLQuaternion::quantize16(F32 lower, F32 upper) F32 z = mQ[VZ]; F32 s = mQ[VS]; - x = U16_to_F32(F32_to_U16(x, lower, upper), lower, upper); - y = U16_to_F32(F32_to_U16(y, lower, upper), lower, upper); - z = U16_to_F32(F32_to_U16(z, lower, upper), lower, upper); - s = U16_to_F32(F32_to_U16(s, lower, upper), lower, upper); + x = U16_to_F32(F32_to_U16_ROUND(x, lower, upper), lower, upper); + y = U16_to_F32(F32_to_U16_ROUND(y, lower, upper), lower, upper); + z = U16_to_F32(F32_to_U16_ROUND(z, lower, upper), lower, upper); + s = U16_to_F32(F32_to_U16_ROUND(s, lower, upper), lower, upper); mQ[VX] = x; mQ[VY] = y; mQ[VZ] = z; mQ[VS] = s; + + normQuat(); } void LLQuaternion::quantize8(F32 lower, F32 upper) { - mQ[VX] = U8_to_F32(F32_to_U8(mQ[VX], lower, upper), lower, upper); - mQ[VY] = U8_to_F32(F32_to_U8(mQ[VY], lower, upper), lower, upper); - mQ[VZ] = U8_to_F32(F32_to_U8(mQ[VZ], lower, upper), lower, upper); - mQ[VS] = U8_to_F32(F32_to_U8(mQ[VS], lower, upper), lower, upper); + mQ[VX] = U8_to_F32(F32_to_U8_ROUND(mQ[VX], lower, upper), lower, upper); + mQ[VY] = U8_to_F32(F32_to_U8_ROUND(mQ[VY], lower, upper), lower, upper); + mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper); + mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper); + + normQuat(); } // LLVector3 Magnitude and Normalization Functions diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 7b07dfd0e0..142e6a50e8 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -316,7 +316,7 @@ size_t LLHTTPAssetRequest::readCompressedData(void* data, size_t size) while (mZStream.avail_out > 0) { - if (mZStream.avail_in == 0 && !mZInputExhausted) + if (mZStream.avail_in == 0 && !mZInputExhausted) { S32 to_read = llmin(COMPRESSED_INPUT_BUFFER_SIZE, (S32)(mVFile->getSize() - mVFile->tell())); @@ -324,14 +324,9 @@ size_t LLHTTPAssetRequest::readCompressedData(void* data, size_t size) if ( to_read > 0 ) { mVFile->read((U8*)mZInputBuffer, to_read); /*Flawfinder: ignore*/ + mZStream.next_in = (Bytef*)mZInputBuffer; + mZStream.avail_in = mVFile->getLastBytesRead(); } - else - { - llwarns << "LLHTTPAssetRequest::readCompressedData has zero read length" << llendl; - break; - } - mZStream.next_in = (Bytef*)mZInputBuffer; - mZStream.avail_in = mVFile->getLastBytesRead(); mZInputExhausted = mZStream.avail_in == 0; } @@ -339,8 +334,13 @@ size_t LLHTTPAssetRequest::readCompressedData(void* data, size_t size) int r = deflate(&mZStream, mZInputExhausted ? Z_FINISH : Z_NO_FLUSH); - if (r == Z_STREAM_END || r < 0) + if (r == Z_STREAM_END || r < 0 || mZInputExhausted) { + if (r < 0) + { + llwarns << "LLHTTPAssetRequest::readCompressedData: deflate returned error code " + << (S32) r << llendl; + } break; } } diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index ccf18a3506..30feb85b2c 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -135,7 +135,8 @@ LLLineEditor::LLLineEditor(const LLString& name, const LLRect& rect, mHandleEditKeysDirectly( FALSE ), mSelectAllonFocusReceived( FALSE ), mPassDelete(FALSE), - mReadOnly(FALSE) + mReadOnly(FALSE), + mLastIMEPosition( -1, -1 ) { llassert( max_length_bytes > 0 ); @@ -1609,6 +1610,17 @@ void LLLineEditor::draw() LLFontGL::NORMAL, 1); } + + // Make sure the IME is in the right place + S32 pixels_after_scroll = findPixelNearestPos(); // RCalculcate for IME position + LLRect screen_pos = getScreenRect(); + LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - UI_LINEEDITOR_V_PAD ); + if ( ime_pos.mX != mLastIMEPosition.mX || ime_pos.mY != mLastIMEPosition.mY ) + { + mLastIMEPosition.mX = ime_pos.mX; + mLastIMEPosition.mY = ime_pos.mY; + getWindow()->setLanguageTextInput( ime_pos ); + } } } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index db6aea8432..6de2fc3eba 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -256,6 +256,8 @@ protected: S32 mBorderThickness; + LLCoordGL mLastIMEPosition; // Last screen position used for the IME editor + BOOL mIgnoreArrowKeys; BOOL mIgnoreTab; BOOL mDrawAsterixes; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 52f8c19ebd..1ec62f6927 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -286,7 +286,8 @@ LLTextEditor::LLTextEditor( mMouseDownX(0), mMouseDownY(0), mLastSelectionX(-1), - mLastSelectionY(-1) + mLastSelectionY(-1), + mLastIMEPosition(-1,-1) { mSourceID.generate(); @@ -2799,7 +2800,15 @@ void LLTextEditor::drawCursor() 1); } - + // Make sure the IME is in the right place + LLRect screen_pos = getScreenRect(); + LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_left), screen_pos.mBottom + llfloor(cursor_top) ); + if ( ime_pos.mX != mLastIMEPosition.mX || ime_pos.mY != mLastIMEPosition.mY ) + { + mLastIMEPosition.mX = ime_pos.mX; + mLastIMEPosition.mY = ime_pos.mY; + getWindow()->setLanguageTextInput( ime_pos ); + } } } } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 7c7ec9c13b..e19e799033 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -414,6 +414,8 @@ protected: BOOL mParseHTML; LLString mHTML; + + LLCoordGL mLastIMEPosition; // Last position of the IME editor }; class LLTextSegment diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 1347d8e94c..f1c188f8e9 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -200,7 +200,7 @@ public: // control platform's Language Text Input mechanisms. virtual void allowLanguageTextInput( BOOL b ) {}; - virtual void setLanguageTextInput( LLCoordWindow pos ) {}; + virtual void setLanguageTextInput( const LLCoordGL & pos ) {}; protected: LLWindow(BOOL fullscreen, U32 flags); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 299ccc39f3..cb108143f4 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -65,11 +65,10 @@ void show_window_creation_error(const char* title) //static BOOL LLWindowWin32::sIsClassRegistered = FALSE; -BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE; /* XXX */ -BOOL LLWindowWin32::sWinIMEOpened = FALSE; -HKL LLWindowWin32::sWinInputLocale; -DWORD LLWindowWin32::sWinIMEConversionMode; -DWORD LLWindowWin32::sWinIMESentenceMode; +BOOL LLWindowWin32::sLanguageTextInputAllowed = TRUE; +HKL LLWindowWin32::sWinInputLocale = 0; +DWORD LLWindowWin32::sWinIMEConversionMode = IME_CMODE_NATIVE; +DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC; // The following class LLWinImm delegates Windows IMM APIs. // We need this because some language versions of Windows, @@ -87,13 +86,15 @@ public: public: // Wrappers for IMM API. - static BOOL isIME(HKL hkl) { return sTheInstance.mImmIsIME(hkl); } - static HIMC getContext(HWND hwnd) { return sTheInstance.mImmGetContext(hwnd); } - static BOOL releaseContext(HWND hwnd, HIMC himc) { return sTheInstance.mImmReleaseContext(hwnd, himc); } - static BOOL getOpenStatus(HIMC himc) { return sTheInstance.mImmGetOpenStatus(himc); } - static BOOL setOpenStatus(HIMC himc, BOOL status) { return sTheInstance.mImmSetOpenStatus(himc, status); } - static BOOL getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence) { return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); } - static BOOL setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence) { return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); } + static BOOL isIME(HKL hkl); + static HIMC getContext(HWND hwnd); + static BOOL releaseContext(HWND hwnd, HIMC himc); + static BOOL getOpenStatus(HIMC himc); + static BOOL setOpenStatus(HIMC himc, BOOL status); + static BOOL getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence); + static BOOL setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence); + static BOOL getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form); + static BOOL setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form); private: LLWinImm(); @@ -108,6 +109,8 @@ private: BOOL (WINAPI *mImmSetOpenStatus)(HIMC, BOOL); BOOL (WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD); BOOL (WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD); + BOOL (WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); + BOOL (WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM); private: HMODULE mHImmDll; @@ -116,8 +119,13 @@ private: LLWinImm LLWinImm::sTheInstance; -LLWinImm::LLWinImm() +LLWinImm::LLWinImm() : mHImmDll(NULL) { + // Check system metrics + if ( !GetSystemMetrics( SM_DBCSENABLED ) ) + return; + + mHImmDll = LoadLibraryA("Imm32"); if (mHImmDll != NULL) { @@ -128,13 +136,18 @@ LLWinImm::LLWinImm() mImmSetOpenStatus = (BOOL (WINAPI *)(HIMC, BOOL)) GetProcAddress(mHImmDll, "ImmSetOpenStatus"); mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus"); mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmSetConversionStatus"); + mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmGetCompositionWindow"); + mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmSetCompositionWindow"); + if (mImmIsIME == NULL || mImmGetContext == NULL || mImmReleaseContext == NULL || mImmGetOpenStatus == NULL || mImmSetOpenStatus == NULL || mImmGetConversionStatus == NULL || - mImmSetConversionStatus == NULL) + mImmSetConversionStatus == NULL || + mImmGetCompostitionWindow == NULL || + mImmSetCompostitionWindow == NULL) { // If any of the above API entires are not found, we can't use IMM API. // So, turn off the IMM support. We should log some warning message in @@ -145,10 +158,96 @@ LLWinImm::LLWinImm() // is one of disadvantages to use static constraction to DLL loading. FreeLibrary(mHImmDll); mHImmDll = NULL; + + // If we unload the library, make sure all the function pointers are cleared + mImmIsIME = NULL; + mImmGetContext = NULL; + mImmReleaseContext = NULL; + mImmGetOpenStatus = NULL; + mImmSetOpenStatus = NULL; + mImmGetConversionStatus = NULL; + mImmSetConversionStatus = NULL; + mImmGetCompostitionWindow = NULL; + mImmSetCompostitionWindow = NULL; } } } + +// static +BOOL LLWinImm::isIME(HKL hkl) +{ + if ( sTheInstance.mImmIsIME ) + return sTheInstance.mImmIsIME(hkl); + return FALSE; +} + +// static +HIMC LLWinImm::getContext(HWND hwnd) +{ + if ( sTheInstance.mImmGetContext ) + return sTheInstance.mImmGetContext(hwnd); + return 0; +} + +//static +BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc) +{ + if ( sTheInstance.mImmIsIME ) + return sTheInstance.mImmReleaseContext(hwnd, himc); + return FALSE; +} + +// static +BOOL LLWinImm::getOpenStatus(HIMC himc) +{ + if ( sTheInstance.mImmGetOpenStatus ) + return sTheInstance.mImmGetOpenStatus(himc); + return FALSE; +} + +// static +BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status) +{ + if ( sTheInstance.mImmSetOpenStatus ) + return sTheInstance.mImmSetOpenStatus(himc, status); + return FALSE; +} + +// static +BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence) +{ + if ( sTheInstance.mImmGetConversionStatus ) + return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence); + return FALSE; +} + +// static +BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence) +{ + if ( sTheInstance.mImmSetConversionStatus ) + return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence); + return FALSE; +} + +// static +BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) +{ + if ( sTheInstance.mImmGetCompostitionWindow ) + return sTheInstance.mImmGetCompostitionWindow(himc, form); + return FALSE; +} + +// static +BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form) +{ + if ( sTheInstance.mImmSetCompostitionWindow ) + return sTheInstance.mImmSetCompostitionWindow(himc, form); + return FALSE; +} + + +// ---------------------------------------------------------------------------------------- LLWinImm::~LLWinImm() { if (mHImmDll != NULL) @@ -3202,53 +3301,74 @@ void LLWindowWin32::focusClient() void LLWindowWin32::allowLanguageTextInput(BOOL b) { - if (b == sLanguageTextInputAllowed || !LLWinImm::isAvailable()) + if ( !LLWinImm::isAvailable() ) { - /* Not actually allowing/disallowing. Do nothing. */ return; } sLanguageTextInputAllowed = b; if (b) { - /* Allowing: Restore the previous IME status, - so that the user has a feeling that the previous - text input continues naturally. Be careful, however, - the IME status is meaningful only during the user keeps - using same Input Locale (aka Keyboard Layout). */ - if (sWinIMEOpened && GetKeyboardLayout(0) == sWinInputLocale) + // Allowing: Restore the previous IME status, so that the user has a feeling that the previous + // text input continues naturally. Be careful, however, the IME status is meaningful only during the user keeps + // using same Input Locale (aka Keyboard Layout). + HIMC himc = LLWinImm::getContext(mWindowHandle); + LLWinImm::setOpenStatus(himc, TRUE); + if (GetKeyboardLayout(0) == sWinInputLocale && sWinIMEConversionMode != IME_CMODE_RESERVED) { - HIMC himc = LLWinImm::getContext(mWindowHandle); - LLWinImm::setOpenStatus(himc, TRUE); LLWinImm::setConversionStatus(himc, sWinIMEConversionMode, sWinIMESentenceMode); - LLWinImm::releaseContext(mWindowHandle, himc); + sWinIMEConversionMode = IME_CMODE_RESERVED; // Set saved state so we won't do this repeatedly } + LLWinImm::releaseContext(mWindowHandle, himc); } else { - /* Disallowing: Turn off the IME so that succeeding - key events bypass IME and come to us directly. - However, do it after saving the current IME - status. We need to restore the status when - allowing language text input again. */ + // Disallowing: Turn off the IME so that succeeding key events bypass IME and come to us directly. + // However, do it after saving the current IME status. We need to restore the status when + // allowing language text input again. sWinInputLocale = GetKeyboardLayout(0); - sWinIMEOpened = LLWinImm::isIME(sWinInputLocale); - if (sWinIMEOpened) + if ( LLWinImm::isIME(sWinInputLocale) ) { HIMC himc = LLWinImm::getContext(mWindowHandle); - sWinIMEOpened = LLWinImm::getOpenStatus(himc); - if (sWinIMEOpened) + if ( LLWinImm::getOpenStatus(himc) ) { LLWinImm::getConversionStatus(himc, &sWinIMEConversionMode, &sWinIMESentenceMode); - /* We need both ImmSetConversionStatus and ImmSetOpenStatus here - to surely disable IME's keyboard hooking, because Some IME reacts - only on the former and some other on the latter... */ + // We need both ImmSetConversionStatus and ImmSetOpenStatus here to surely disable IME's + // keyboard hooking, because Some IME reacts only on the former and some other on the latter... LLWinImm::setConversionStatus(himc, IME_CMODE_NOCONVERSION, sWinIMESentenceMode); LLWinImm::setOpenStatus(himc, FALSE); } LLWinImm::releaseContext(mWindowHandle, himc); + } + } + +} + + +// Put the IME window at the right place (near current text input). Point coordinates should be the top of the current text line. +void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position ) +{ + if (sLanguageTextInputAllowed && LLWinImm::isAvailable()) + { + HIMC himc = LLWinImm::getContext(mWindowHandle); + + LLCoordWindow win_pos; + convertCoords( position, &win_pos ); + + if ( win_pos.mX >= 0 && win_pos.mY >= 0 ) + { + COMPOSITIONFORM ime_form; + memset( &ime_form, 0, sizeof(ime_form) ); + ime_form.dwStyle = CFS_POINT; + ime_form.ptCurrentPos.x = win_pos.mX; + ime_form.ptCurrentPos.y = win_pos.mY; + + LLWinImm::setCompositionWindow( himc, &ime_form ); } + + LLWinImm::releaseContext(mWindowHandle, himc); + } } diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 5eb2cfbb79..cb105c2128 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -87,6 +87,7 @@ public: /*virtual*/ void focusClient(); /*virtual*/ void allowLanguageTextInput(BOOL b); + /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos ); protected: LLWindowWin32( @@ -156,11 +157,10 @@ protected: BOOL mMousePositionModified; BOOL mInputProcessingPaused; - // The following five variables are for Language Text Input control. + // The following variables are for Language Text Input control. // They are all static, since one context is shared by all LLWindowWin32 // instances. static BOOL sLanguageTextInputAllowed; - static BOOL sWinIMEOpened; static HKL sWinInputLocale; static DWORD sWinIMEConversionMode; static DWORD sWinIMESentenceMode; diff --git a/indra/lscript/lscript_byteconvert.h b/indra/lscript/lscript_byteconvert.h index d30c84b28c..d960eb8c66 100644 --- a/indra/lscript/lscript_byteconvert.h +++ b/indra/lscript/lscript_byteconvert.h @@ -761,9 +761,17 @@ inline S32 get_state_event_opcoode_start(U8 *stream, S32 state, LSCRIPTStateEven major_version = LSL2_MAJOR_VERSION_TWO; state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*3*state; } + if ( state_offset_offset < 0 || state_offset_offset > TOP_OF_MEMORY ) + { + return -1; + } // get the actual position in memory of the desired state S32 state_offset = sr + bytestream2integer(stream, state_offset_offset); + if ( state_offset < 0 || state_offset > TOP_OF_MEMORY ) + { + return -1; + } // save that value S32 state_offset_base = state_offset; @@ -773,18 +781,32 @@ inline S32 get_state_event_opcoode_start(U8 *stream, S32 state, LSCRIPTStateEven // get the location of the event offset S32 event_offset = event_jump_offset + LSCRIPTDataSize[LST_INTEGER]*2*get_event_handler_jump_position(get_event_register(stream, LREG_ER, major_version), event); + if ( event_offset < 0 || event_offset > TOP_OF_MEMORY ) + { + return -1; + } // now, jump to the event S32 event_start = bytestream2integer(stream, event_offset); + if ( event_start < 0 || event_start > TOP_OF_MEMORY ) + { + return -1; + } event_start += event_jump_offset; S32 event_start_original = event_start; // now skip past the parameters S32 opcode_offset = bytestream2integer(stream, event_start); + if ( opcode_offset < 0 || opcode_offset > TOP_OF_MEMORY ) + { + return -1; + } + return opcode_offset + event_start_original; } + inline U64 get_handled_events(U8 *stream, S32 state) { U64 retvalue = 0; @@ -809,6 +831,7 @@ inline U64 get_handled_events(U8 *stream, S32 state) return retvalue; } +// Returns -1 on error inline S32 get_event_stack_size(U8 *stream, S32 state, LSCRIPTStateEventType event) { // get the start of the state table @@ -829,21 +852,39 @@ inline S32 get_event_stack_size(U8 *stream, S32 state, LSCRIPTStateEventType eve state_offset_offset = sr + LSCRIPTDataSize[LST_INTEGER] + LSCRIPTDataSize[LST_INTEGER]*3*state; } + if ( state_offset_offset < 0 || state_offset_offset > TOP_OF_MEMORY ) + { + return -1; + } + S32 state_offset = bytestream2integer(stream, state_offset_offset); state_offset += sr; state_offset_offset = state_offset; + if ( state_offset_offset < 0 || state_offset_offset > TOP_OF_MEMORY ) + { + return -1; + } // skip to jump table S32 jump_table = bytestream2integer(stream, state_offset_offset); jump_table += state_offset; + if ( jump_table < 0 || jump_table > TOP_OF_MEMORY ) + { + return -1; + } // get the position of the jump to the desired state S32 stack_size_offset = jump_table + LSCRIPTDataSize[LST_INTEGER]*2*get_event_handler_jump_position(get_event_register(stream, LREG_ER, major_version), event) + LSCRIPTDataSize[LST_INTEGER]; // get the handled events S32 stack_size = bytestream2integer(stream, stack_size_offset); + if ( stack_size < 0 || stack_size > TOP_OF_MEMORY ) + { + return -1; + } + return stack_size; } diff --git a/indra/lscript/lscript_execute.h b/indra/lscript/lscript_execute.h index 84cd6e3b0a..1c2952f5ae 100644 --- a/indra/lscript/lscript_execute.h +++ b/indra/lscript/lscript_execute.h @@ -359,6 +359,10 @@ public: LLScriptEventData mEventData; static S64 sGlobalInstructionCount; + +private: + void recordBoundaryError( const LLUUID &id ); + void setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEventType event, const LLUUID &id ); }; #endif diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp index b166e922a2..d00d3372ce 100644 --- a/indra/lscript/lscript_execute/lscript_execute.cpp +++ b/indra/lscript/lscript_execute/lscript_execute.cpp @@ -245,6 +245,32 @@ void LLScriptExecute::init() } + +// Utility routine for when there's a boundary error parsing bytecode +void LLScriptExecute::recordBoundaryError( const LLUUID &id ) +{ + set_fault(mBuffer, LSRF_BOUND_CHECK_ERROR); + llwarns << "Script boundary error for ID " << id << llendl; +} + + +// set IP to the event handler with some error checking +void LLScriptExecute::setStateEventOpcoodeStartSafely( S32 state, LSCRIPTStateEventType event, const LLUUID &id ) +{ + S32 opcode_start = get_state_event_opcoode_start( mBuffer, state, event ); + if ( opcode_start == -1 ) + { + recordBoundaryError( id ); + } + else + { + set_ip( mBuffer, opcode_start ); + } +} + + + + S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer); U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, char **errorstr, BOOL &state_transition) @@ -353,14 +379,20 @@ U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, char **errorstr, BOOL & // now, push any additional stack space S32 additional_size = get_event_stack_size(mBuffer, current_state, LSTT_STATE_EXIT); - lscript_pusharge(mBuffer, additional_size); - - sp = get_register(mBuffer, LREG_SP); - sp += additional_size; - set_bp(mBuffer, sp); - // set IP to the event handler - S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, LSTT_STATE_EXIT); - set_ip(mBuffer, opcode_start); + if ( additional_size == -1 ) + { + recordBoundaryError( id ); + } + else + { + lscript_pusharge(mBuffer, additional_size); + + sp = get_register(mBuffer, LREG_SP); + sp += additional_size; + set_bp(mBuffer, sp); + // set IP to the event handler + setStateEventOpcoodeStartSafely( current_state, LSTT_STATE_EXIT, id ); + } return NO_DELETE_FLAG; } } @@ -411,20 +443,27 @@ U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, char **errorstr, BOOL & current_events &= ~LSCRIPTStateBitField[event]; set_event_register(mBuffer, LREG_CE, current_events, major_version); // now, push any additional stack space - S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size; - lscript_pusharge(mBuffer, additional_size); + S32 additional_size = get_event_stack_size(mBuffer, current_state, event); + if ( additional_size == -1 ) + { // b_done will be set, so we'll exit the loop at the bottom + recordBoundaryError( id ); + } + else + { + additional_size -= size; + lscript_pusharge(mBuffer, additional_size); // now set the bp correctly - sp = get_register(mBuffer, LREG_SP); - sp += additional_size + size; - set_bp(mBuffer, sp); + sp = get_register(mBuffer, LREG_SP); + sp += additional_size + size; + set_bp(mBuffer, sp); // set IP to the function - S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event); - set_ip(mBuffer, opcode_start); + setStateEventOpcoodeStartSafely( current_state, event, id ); + } b_done = TRUE; } else if ( (current_events & LSCRIPTStateBitField[LSTT_REZ]) - &&(current_events & event_register)) + &&(current_events & event_register)) { for (eventdata = mEventData.mEventDataList.getFirstData(); eventdata; eventdata = mEventData.mEventDataList.getNextData()) { @@ -449,17 +488,24 @@ U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, char **errorstr, BOOL & data++; } // now, push any additional stack space - S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size; - lscript_pusharge(mBuffer, additional_size); - - // now set the bp correctly - sp = get_register(mBuffer, LREG_SP); - sp += additional_size + size; - set_bp(mBuffer, sp); - // set IP to the function - S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event); - set_ip(mBuffer, opcode_start); - mEventData.mEventDataList.deleteCurrentData(); + S32 additional_size = get_event_stack_size(mBuffer, current_state, event); + if ( additional_size == -1 ) + { // b_done will be set, so we'll exit the loop at the bottom + recordBoundaryError( id ); + } + else + { + additional_size -= size; + lscript_pusharge(mBuffer, additional_size); + + // now set the bp correctly + sp = get_register(mBuffer, LREG_SP); + sp += additional_size + size; + set_bp(mBuffer, sp); + // set IP to the function + setStateEventOpcoodeStartSafely( current_state, event, id ); + mEventData.mEventDataList.deleteCurrentData(); + } b_done = TRUE; break; } @@ -496,16 +542,23 @@ U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, char **errorstr, BOOL & } b_done = TRUE; // now, push any additional stack space - S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size; - lscript_pusharge(mBuffer, additional_size); - - // now set the bp correctly - sp = get_register(mBuffer, LREG_SP); - sp += additional_size + size; - set_bp(mBuffer, sp); - // set IP to the function - S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event); - set_ip(mBuffer, opcode_start); + S32 additional_size = get_event_stack_size(mBuffer, current_state, event); + if ( additional_size == -1 ) + { // b_done was just set, so we'll exit the loop at the bottom + recordBoundaryError( id ); + } + else + { + additional_size -= size; + lscript_pusharge(mBuffer, additional_size); + + // now set the bp correctly + sp = get_register(mBuffer, LREG_SP); + sp += additional_size + size; + set_bp(mBuffer, sp); + // set IP to the function + setStateEventOpcoodeStartSafely( current_state, event, id ); + } } else { @@ -530,23 +583,30 @@ U32 LLScriptExecute::run(BOOL b_print, const LLUUID &id, char **errorstr, BOOL & current_events &= ~LSCRIPTStateBitField[event]; set_event_register(mBuffer, LREG_CE, current_events, major_version); // now, push any additional stack space - S32 additional_size = get_event_stack_size(mBuffer, current_state, event) - size; - lscript_pusharge(mBuffer, additional_size); - - // now set the bp correctly - sp = get_register(mBuffer, LREG_SP); - sp += additional_size + size; - set_bp(mBuffer, sp); - // set IP to the function - S32 opcode_start = get_state_event_opcoode_start(mBuffer, current_state, event); - set_ip(mBuffer, opcode_start); + S32 additional_size = get_event_stack_size(mBuffer, current_state, event); + if ( additional_size == -1 ) + { // b_done will be set, so we'll exit the loop at the bottom + recordBoundaryError( id ); + } + else + { + additional_size -= size; + lscript_pusharge(mBuffer, additional_size); + + // now set the bp correctly + sp = get_register(mBuffer, LREG_SP); + sp += additional_size + size; + set_bp(mBuffer, sp); + // set IP to the function + setStateEventOpcoodeStartSafely( current_state, event, id ); + } } b_done = TRUE; } - } + } // while (!b_done) + } // end of else ... in state processing code - return NO_DELETE_FLAG; - } + return NO_DELETE_FLAG; } BOOL run_noop(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id) diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index ac967c4853..f720fc0ec1 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -84,7 +84,30 @@ export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime- export SL_CMD='$LL_WRAPPER bin/do-not-directly-run-secondlife-bin' export SL_OPT="`cat gridargs.dat` $@" -eval ${SL_ENV} ${SL_CMD} ${SL_OPT} || echo Unclean shutdown. +# Run the program +eval ${SL_ENV} ${SL_CMD} ${SL_OPT} || LL_RUN_ERR=runerr + +# Handle any resulting errors +if [ -n "$LL_RUN_ERR" ]; then + LL_RUN_ERR_MSG="" + if [ "$LL_RUN_ERR" = "runerr" ]; then + # generic error running the binary + echo '*** Unclean shutdown. ***' + if [ "`arch`" = "x86_64" ]; then + echo + cat << EOFMARKER +You are running the Second Life Viewer on a x86_64 platform. The +most common problems when launching the Viewer (particularly +'bin/do-not-directly-run-secondlife-bin: not found' and 'error while +loading shared libraries') may be solved by installing your Linux +distribution's 32-bit compatibility packages. +For example, on Ubuntu and other Debian-based Linuxes you might run: +$ sudo apt-get install ia32-libs ia32-libs-gtk ia32-libs-kde ia32-libs-sdl +EOFMARKER + fi + fi +fi + echo echo '*********************************************************' diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ead985a992..a37044f364 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -306,7 +306,7 @@ LLUUID LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type) } // Convenience function to create a new category. You could call -// updateCatgory() with a newly generated UUID category, but this +// updateCategory() with a newly generated UUID category, but this // version will take care of details like what the name should be // based on preferred type. Returns the UUID of the new category. LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index a2cc0f5a81..844afca629 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -495,7 +495,6 @@ bool LLPanelGroupGeneral::apply(LLString& mesg) gAgent.setUserGroupFlags(mGroupID, receive_notices, list_in_profile); mChanged = FALSE; - notifyObservers(); return true; } @@ -810,6 +809,7 @@ void LLPanelGroupGeneral::updateChanged() mSpinEnrollmentFee, mCtrlReceiveNotices, mCtrlListGroup, + mActiveTitleLabel, mComboActiveTitle }; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 0fbcd93b0b..5fbe3f0c8e 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -4783,19 +4783,17 @@ void LLSelectMgr::updateSilhouettes() iter != roots.end(); iter++) { LLViewerObject* objectp = *iter; - LLSelectNode* rect_select_node = new LLSelectNode(objectp, TRUE); - rect_select_node->selectAllTEs(TRUE); + LLSelectNode* rect_select_root_node = new LLSelectNode(objectp, TRUE); + rect_select_root_node->selectAllTEs(TRUE); if (!canSelectObject(objectp)) { continue; } - mHighlightedObjects->addNode(rect_select_node); - if (!select_linked_set) { - rect_select_node->mIndividualSelection = TRUE; + rect_select_root_node->mIndividualSelection = TRUE; } else { @@ -4808,11 +4806,14 @@ void LLSelectMgr::updateSilhouettes() continue; } - rect_select_node = new LLSelectNode(objectp->mChildList[i], TRUE); + LLSelectNode* rect_select_node = new LLSelectNode(objectp->mChildList[i], TRUE); rect_select_node->selectAllTEs(TRUE); - mHighlightedObjects->addNode(rect_select_node); + mHighlightedObjects->addNodeAtEnd(rect_select_node); } } + + // Add the root last, to preserve order for link operations. + mHighlightedObjects->addNodeAtEnd(rect_select_root_node); } num_sils_genned = 0; diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp index cdfc6c2ebf..d5abfbdab6 100644 --- a/indra/newview/lltoolfocus.cpp +++ b/indra/newview/lltoolfocus.cpp @@ -262,9 +262,11 @@ BOOL LLToolCamera::handleMouseUp(S32 x, S32 y, MASK mask) { LLCoordGL mouse_pos; LLVector3 focus_pos = gAgent.getPosAgentFromGlobal(gAgent.getFocusGlobal()); - gCamera->projectPosAgentToScreen(focus_pos, mouse_pos); - - LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY); + BOOL success = gCamera->projectPosAgentToScreen(focus_pos, mouse_pos); + if (success) + { + LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY); + } } else if (mMouseSteering) { diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 6b38bd1765..2078bd47f5 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -140,6 +140,11 @@ class WindowsManifest(ViewerManifest): # For using FMOD for sound... DJS self.path("fmod.dll") + # For textures + if self.prefix(src="../../libraries/i686-win32/lib_release", dst=""): + self.path("openjpeg.dll") + self.end_prefix() + # Mozilla appears to force a dependency on these files so we need to ship it (CP) self.path("msvcr71.dll") self.path("msvcp71.dll") @@ -482,6 +487,7 @@ class Linux_i686Manifest(LinuxManifest): self.path("libuuid.so", "libuuid.so.1") self.path("libSDL-1.2.so.0") self.path("libELFIO.so") + self.path("libopenjpeg.so.2") #self.path("libtcmalloc.so.0") - bugged #self.path("libstacktrace.so.0") - probably bugged self.path("libllkdu.so", "../bin/libllkdu.so") # llkdu goes in bin for some reason |