aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMcCabe Maxsted2010-09-29 16:16:59 -0700
committerMcCabe Maxsted2010-09-29 16:16:59 -0700
commitc9b90f87a6837ba05465bca8cf245d63b0a1506a (patch)
tree18c65158095501fcb73ef4ab6389933f9b3d93f8
parentFix for Bug #544 (diff)
parentContext menu translator: (diff)
downloadmeta-impy-c9b90f87a6837ba05465bca8cf245d63b0a1506a.zip
meta-impy-c9b90f87a6837ba05465bca8cf245d63b0a1506a.tar.gz
meta-impy-c9b90f87a6837ba05465bca8cf245d63b0a1506a.tar.bz2
meta-impy-c9b90f87a6837ba05465bca8cf245d63b0a1506a.tar.xz
Merge remote branch 'thickbrick/translate_fixes_b' into weekly
-rw-r--r--linden/indra/llui/lllineeditor.cpp251
-rw-r--r--linden/indra/llui/lllineeditor.h24
-rw-r--r--linden/indra/llui/lltexteditor.cpp236
-rw-r--r--linden/indra/llui/lltexteditor.h17
-rw-r--r--linden/indra/newview/lgghunspell_wrapper.cpp18
-rw-r--r--linden/indra/newview/lgghunspell_wrapper.h4
-rwxr-xr-xlinden/indra/newview/llviewermessage.cpp45
-rw-r--r--linden/indra/newview/llviewermessage.h2
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/panel_login.xml9
9 files changed, 410 insertions, 196 deletions
diff --git a/linden/indra/llui/lllineeditor.cpp b/linden/indra/llui/lllineeditor.cpp
index 66ef4c6..49fe3be 100644
--- a/linden/indra/llui/lllineeditor.cpp
+++ b/linden/indra/llui/lllineeditor.cpp
@@ -96,23 +96,23 @@ static LLRegisterWidget<LLLineEditor> r1("line_editor");
96class LineChatTranslationReceiver : public LLTranslate::TranslationReceiver 96class LineChatTranslationReceiver : public LLTranslate::TranslationReceiver
97{ 97{
98public : 98public :
99 LineChatTranslationReceiver(const std::string &toLang, LLLineEditor* line): LLTranslate::TranslationReceiver("", toLang), 99 LineChatTranslationReceiver(const std::string &toLang, LLLineEditor* line, const S32 start, const S32 len):
100 m_line(line) 100 LLTranslate::TranslationReceiver("", toLang),
101 m_line(line),
102 m_position(start),
103 m_origLength(len)
101 { 104 {
102 } 105 }
103 106
104 static boost::intrusive_ptr<LineChatTranslationReceiver> build(const std::string &toLang,LLLineEditor* line) 107 static boost::intrusive_ptr<LineChatTranslationReceiver> build(const std::string &toLang,LLLineEditor* line, const S32 start, const S32 len)
105 { 108 {
106 return boost::intrusive_ptr<LineChatTranslationReceiver>(new LineChatTranslationReceiver(toLang,line)); 109 return boost::intrusive_ptr<LineChatTranslationReceiver>(new LineChatTranslationReceiver(toLang, line, start, len));
107 } 110 }
108 111
109protected: 112protected:
110 void handleResponse(const std::string &translation, const std::string &detectedLanguage) 113 void handleResponse(const std::string &translation, const std::string &detectedLanguage)
111 { 114 {
112 static BOOL* rep = rebind_llcontrol<BOOL>("EmeraldTranslateReplace", &gSavedSettings, true); 115 m_line->translationReplace(translation, m_position, m_origLength);
113 if(*rep)
114 m_line->deleteSelection();
115 m_line->insert(((*rep)?"":" (") + translation + ((*rep)?"":")"),m_line->getCursor());
116 } 116 }
117 void handleFailure() 117 void handleFailure()
118 { 118 {
@@ -120,6 +120,8 @@ protected:
120 } 120 }
121private: 121private:
122 LLLineEditor* m_line; 122 LLLineEditor* m_line;
123 S32 m_position;
124 S32 m_origLength;
123}; 125};
124 126
125LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect, 127LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
@@ -151,6 +153,7 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
151 mLastSelectionY(-1), 153 mLastSelectionY(-1),
152 mLastSelectionStart(-1), 154 mLastSelectionStart(-1),
153 mLastSelectionEnd(-1), 155 mLastSelectionEnd(-1),
156 mLastContextMenuX(-1),
154 mPrevalidateFunc( prevalidate_func ), 157 mPrevalidateFunc( prevalidate_func ),
155 mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ), 158 mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ),
156 mFgColor( LLUI::sColorsGroup->getColor( "TextFgColor" ) ), 159 mFgColor( LLUI::sColorsGroup->getColor( "TextFgColor" ) ),
@@ -172,7 +175,7 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
172 mImage( sImage ), 175 mImage( sImage ),
173 mReplaceNewlinesWithSpaces( TRUE ), 176 mReplaceNewlinesWithSpaces( TRUE ),
174 mSpellCheckable( FALSE ), 177 mSpellCheckable( FALSE ),
175 mShowMisspellings(FALSE) 178 mAllowTranslate(TRUE)
176{ 179{
177 llassert( max_length_bytes > 0 ); 180 llassert( max_length_bytes > 0 );
178 181
@@ -211,12 +214,6 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
211 } 214 }
212 mImage = sImage; 215 mImage = sImage;
213 216
214 // in other words, highlighting requires a restart
215 if (glggHunSpell->getSpellCheckHighlight())
216 {
217 mShowMisspellings = TRUE;
218 }
219
220 // make the popup menu available 217 // make the popup menu available
221 //LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_texteditor.xml", parent_view); 218 //LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_texteditor.xml", parent_view);
222 LLMenuGL* menu = new LLMenuGL("wot"); 219 LLMenuGL* menu = new LLMenuGL("wot");
@@ -224,46 +221,49 @@ LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
224 { 221 {
225 menu = new LLMenuGL(LLStringUtil::null); 222 menu = new LLMenuGL(LLStringUtil::null);
226 }*/ 223 }*/
227 menu->append(new LLMenuItemCallGL("Cut", context_cut, NULL, this)); 224
228 menu->append(new LLMenuItemCallGL("Copy", context_copy, NULL, this)); 225 menu->append(new LLMenuItemCallGL("Cut", context_cut, context_enable_cut, this));
229 menu->append(new LLMenuItemCallGL("Paste", context_paste, NULL, this)); 226 menu->append(new LLMenuItemCallGL("Copy", context_copy, context_enable_copy, this));
230 menu->append(new LLMenuItemCallGL("Delete", context_delete, NULL, this)); 227 menu->append(new LLMenuItemCallGL("Paste", context_paste, context_enable_paste, this));
231 menu->append(new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); 228 menu->append(new LLMenuItemCallGL("Delete", context_delete, context_enable_delete, this));
229 menu->append(new LLMenuItemCallGL("Select All", context_selectall, context_enable_selectall, this));
230
232 menu->appendSeparator("Transep"); 231 menu->appendSeparator("Transep");
233 LLMenuGL* translatemenu = new LLMenuGL("Translate To"); 232 LLMenuGL* translatemenu = new LLMenuGL("Translate To");
234 translatemenu->setCanTearOff(FALSE); 233 translatemenu->setCanTearOff(FALSE);
235 SpellMenuBind* t=new SpellMenuBind;t->origin=this;t->word="en"; 234 SpellMenuBind* t=new SpellMenuBind;t->origin=this;t->word="en";
236 translatemenu->append(new LLMenuItemCallGL("English",translateText, NULL, t)); 235 translatemenu->append(new LLMenuItemCallGL("English", context_translate, context_enable_translate, t));
237 t=new SpellMenuBind;t->origin=this;t->word="da"; 236 t=new SpellMenuBind;t->origin=this;t->word="da";
238 translatemenu->append(new LLMenuItemCallGL("Danish",translateText, NULL, t)); 237 translatemenu->append(new LLMenuItemCallGL("Danish", context_translate, context_enable_translate, t));
239 t=new SpellMenuBind;t->origin=this;t->word="de"; 238 t=new SpellMenuBind;t->origin=this;t->word="de";
240 translatemenu->append(new LLMenuItemCallGL("Deutsch(German)",translateText, NULL, t)); 239 translatemenu->append(new LLMenuItemCallGL("Deutsch(German)", context_translate, context_enable_translate, t));
241 t=new SpellMenuBind;t->origin=this;t->word="es"; 240 t=new SpellMenuBind;t->origin=this;t->word="es";
242 translatemenu->append(new LLMenuItemCallGL("Spanish",translateText, NULL, t)); 241 translatemenu->append(new LLMenuItemCallGL("Spanish", context_translate, context_enable_translate, t));
243 t=new SpellMenuBind;t->origin=this;t->word="fr"; 242 t=new SpellMenuBind;t->origin=this;t->word="fr";
244 translatemenu->append(new LLMenuItemCallGL("French",translateText, NULL, t)); 243 translatemenu->append(new LLMenuItemCallGL("French", context_translate, context_enable_translate, t));
245 t=new SpellMenuBind;t->origin=this;t->word="it"; 244 t=new SpellMenuBind;t->origin=this;t->word="it";
246 translatemenu->append(new LLMenuItemCallGL("Italian",translateText, NULL, t)); 245 translatemenu->append(new LLMenuItemCallGL("Italian", context_translate, context_enable_translate, t));
247 t=new SpellMenuBind;t->origin=this;t->word="hu"; 246 t=new SpellMenuBind;t->origin=this;t->word="hu";
248 translatemenu->append(new LLMenuItemCallGL("Hungarian",translateText, NULL, t)); 247 translatemenu->append(new LLMenuItemCallGL("Hungarian", context_translate, context_enable_translate, t));
249 t=new SpellMenuBind;t->origin=this;t->word="nl"; 248 t=new SpellMenuBind;t->origin=this;t->word="nl";
250 translatemenu->append(new LLMenuItemCallGL("Dutch",translateText, NULL, t)); 249 translatemenu->append(new LLMenuItemCallGL("Dutch", context_translate, context_enable_translate, t));
251 t=new SpellMenuBind;t->origin=this;t->word="pl"; 250 t=new SpellMenuBind;t->origin=this;t->word="pl";
252 translatemenu->append(new LLMenuItemCallGL("Polish",translateText, NULL, t)); 251 translatemenu->append(new LLMenuItemCallGL("Polish", context_translate, context_enable_translate, t));
253 t=new SpellMenuBind;t->origin=this;t->word="pt"; 252 t=new SpellMenuBind;t->origin=this;t->word="pt";
254 translatemenu->append(new LLMenuItemCallGL("Portugese",translateText, NULL, t)); 253 translatemenu->append(new LLMenuItemCallGL("Portugese", context_translate, context_enable_translate, t));
255 t=new SpellMenuBind;t->origin=this;t->word="ru"; 254 t=new SpellMenuBind;t->origin=this;t->word="ru";
256 translatemenu->append(new LLMenuItemCallGL("Russian",translateText, NULL, t)); 255 translatemenu->append(new LLMenuItemCallGL("Russian", context_translate, context_enable_translate, t));
257 t=new SpellMenuBind;t->origin=this;t->word="tr"; 256 t=new SpellMenuBind;t->origin=this;t->word="tr";
258 translatemenu->append(new LLMenuItemCallGL("Turkish",translateText, NULL, t)); 257 translatemenu->append(new LLMenuItemCallGL("Turkish", context_translate, context_enable_translate, t));
259 t=new SpellMenuBind;t->origin=this;t->word="uk"; 258 t=new SpellMenuBind;t->origin=this;t->word="uk";
260 translatemenu->append(new LLMenuItemCallGL("Ukrainian",translateText, NULL, t)); 259 translatemenu->append(new LLMenuItemCallGL("Ukrainian", context_translate, context_enable_translate, t));
261 t=new SpellMenuBind;t->origin=this;t->word="zh"; 260 t=new SpellMenuBind;t->origin=this;t->word="zh";
262 translatemenu->append(new LLMenuItemCallGL("Chinese",translateText, NULL, t)); 261 translatemenu->append(new LLMenuItemCallGL("Chinese", context_translate, context_enable_translate, t));
263 t=new SpellMenuBind;t->origin=this;t->word="ja"; 262 t=new SpellMenuBind;t->origin=this;t->word="ja";
264 translatemenu->append(new LLMenuItemCallGL("Japanese",translateText, NULL, t)); 263 translatemenu->append(new LLMenuItemCallGL("Japanese", context_translate, context_enable_translate, t));
265 t=new SpellMenuBind;t->origin=this;t->word="ko"; 264 t=new SpellMenuBind;t->origin=this;t->word="ko";
266 translatemenu->append(new LLMenuItemCallGL("Korean",translateText, NULL, t)); 265 translatemenu->append(new LLMenuItemCallGL("Korean", context_translate, context_enable_translate, t));
266
267 menu->appendMenu(translatemenu); 267 menu->appendMenu(translatemenu);
268 menu->appendSeparator("Spelsep"); 268 menu->appendSeparator("Spelsep");
269 //menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor")); 269 //menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor"));
@@ -439,7 +439,7 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
439 439
440 440
441// Picks a new cursor position based on the actual screen size of text being drawn. 441// Picks a new cursor position based on the actual screen size of text being drawn.
442S32 LLLineEditor::calculateCursorFromMouse( S32 local_mouse_x ) 442S32 LLLineEditor::calculateCursorFromMouse( S32 local_mouse_x ) const
443{ 443{
444 const llwchar* wtext = mText.getWString().c_str(); 444 const llwchar* wtext = mText.getWString().c_str();
445 LLWString asterix_text; 445 LLWString asterix_text;
@@ -517,17 +517,30 @@ void LLLineEditor::deselect()
517 mIsSelecting = FALSE; 517 mIsSelecting = FALSE;
518} 518}
519 519
520BOOL LLLineEditor::context_enable_cut(void* data)
521{
522 LLLineEditor* line = (LLLineEditor*)data;
523 return (line && line->canCut());
524}
520 525
521void LLLineEditor::context_cut(void* data) 526void LLLineEditor::context_cut(void* data)
522{ 527{
523 LLLineEditor* line = (LLLineEditor*)data; 528 LLLineEditor* line = (LLLineEditor*)data;
524 if(line)line->cut(); 529 if(line)line->cut();
525} 530}
531
532BOOL LLLineEditor::context_enable_copy(void* data)
533{
534 LLLineEditor* line = (LLLineEditor*)data;
535 return (line &&line->canCopy());
536}
537
526void LLLineEditor::context_copy(void* data) 538void LLLineEditor::context_copy(void* data)
527{ 539{
528 LLLineEditor* line = (LLLineEditor*)data; 540 LLLineEditor* line = (LLLineEditor*)data;
529 if(line)line->copy(); 541 if(line)line->copy();
530} 542}
543
531void LLLineEditor::spell_correct(void* data) 544void LLLineEditor::spell_correct(void* data)
532{ 545{
533 SpellMenuBind* tempBind = (SpellMenuBind*)data; 546 SpellMenuBind* tempBind = (SpellMenuBind*)data;
@@ -539,31 +552,52 @@ void LLLineEditor::spell_correct(void* data)
539 552
540 } 553 }
541} 554}
542void LLLineEditor::translateText(void * data) 555
556BOOL LLLineEditor::context_enable_translate(void* data)
557{
558 SpellMenuBind* t = (SpellMenuBind*)data;
559 return (t && t->origin && t->origin->canTranslate());
560}
561
562void LLLineEditor::context_translate(void * data)
543{ 563{
544 SpellMenuBind* t = (SpellMenuBind*)data; 564 SpellMenuBind* t = (SpellMenuBind*)data;
545 LLLineEditor* line = t->origin; 565 LLLineEditor* line = t->origin;
546 const std::string &toLang = t->word;//LLTranslate::getTranslateLanguage(); 566 const std::string &toLang = t->word;//LLTranslate::getTranslateLanguage();
547 LLHTTPClient::ResponderPtr result = LineChatTranslationReceiver::build(toLang,line); 567
548 S32 left_pos = llmin( line->mSelectionStart, line->mSelectionEnd ); 568 bool has_text = false;
549 S32 length = abs( line->mSelectionStart - line->mSelectionEnd ); 569 S32 start, length;
550 LLTranslate::translateMessage(result,"", toLang, line->mText.getString().substr(left_pos, length)); 570 if (line->hasSelection())
571 {
572 // translate selection
573 start = llmin(line->mSelectionStart, line->mSelectionEnd);
574 length = abs(line->mSelectionEnd - line->mSelectionStart);
575 has_text = length > 0;
576 }
577 else
578 {
579 // translate one word at click position
580 S32 at = line->calculateCursorFromMouse(line->mLastContextMenuX);
581 has_text = line->getWordBoundriesAt(at, &start, &length);
582 }
583
584 if (has_text)
585 {
586 std::string to_translate = wstring_to_utf8str(line->getWText().substr(start, length));
587 LLHTTPClient::ResponderPtr result = LineChatTranslationReceiver::build(toLang, line, start, length);
588 LLTranslate::translateMessage(result,"", toLang, to_translate);
589 }
551} 590}
591
552void LLLineEditor::spell_show(void * data) 592void LLLineEditor::spell_show(void * data)
553{ 593{
554 SpellMenuBind* tempBind = (SpellMenuBind*)data; 594 SpellMenuBind* tempBind = (SpellMenuBind*)data;
555 LLLineEditor* line = tempBind->origin; 595 LLLineEditor* line = tempBind->origin;
556 596
557 if( tempBind && line) 597 if (tempBind && line)
558 { 598 {
559 if (tempBind->word == "Show Misspellings") 599 BOOL show = (tempBind->word == "Show Misspellings");
560 { 600 glggHunSpell->setSpellCheckHighlight(show);
561 line->mShowMisspellings = TRUE;
562 }
563 else
564 {
565 line->mShowMisspellings = FALSE;
566 }
567 } 601 }
568} 602}
569 603
@@ -623,18 +657,36 @@ void LLLineEditor::spell_add(void* data)
623 } 657 }
624} 658}
625 659
660BOOL LLLineEditor::context_enable_paste(void* data)
661{
662 LLLineEditor* line = (LLLineEditor*)data;
663 return (line && line->canPaste());
664}
665
626void LLLineEditor::context_paste(void* data) 666void LLLineEditor::context_paste(void* data)
627{ 667{
628 LLLineEditor* line = (LLLineEditor*)data; 668 LLLineEditor* line = (LLLineEditor*)data;
629 if(line)line->paste(); 669 if(line)line->paste();
630} 670}
631 671
672BOOL LLLineEditor::context_enable_delete(void* data)
673{
674 LLLineEditor* line = (LLLineEditor*)data;
675 return (line && line->canDoDelete());
676}
677
632void LLLineEditor::context_delete(void* data) 678void LLLineEditor::context_delete(void* data)
633{ 679{
634 LLLineEditor* line = (LLLineEditor*)data; 680 LLLineEditor* line = (LLLineEditor*)data;
635 if(line)line->doDelete(); 681 if(line)line->doDelete();
636} 682}
637 683
684BOOL LLLineEditor::context_enable_selectall(void* data)
685{
686 LLLineEditor* line = (LLLineEditor*)data;
687 return (line && line->canSelectAll());
688}
689
638void LLLineEditor::context_selectall(void* data) 690void LLLineEditor::context_selectall(void* data)
639{ 691{
640 LLLineEditor* line = (LLLineEditor*)data; 692 LLLineEditor* line = (LLLineEditor*)data;
@@ -738,7 +790,8 @@ BOOL LLLineEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
738 790
739 //setCursorAtLocalPos( x); 791 //setCursorAtLocalPos( x);
740 S32 wordStart = 0; 792 S32 wordStart = 0;
741 S32 wordEnd = calculateCursorFromMouse(x); 793 S32 wordEnd = 0;
794 S32 pos = calculateCursorFromMouse(x);
742 795
743 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); 796 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
744 if (menu) 797 if (menu)
@@ -761,36 +814,21 @@ BOOL LLLineEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
761 } 814 }
762 suggestionMenuItems.clear(); 815 suggestionMenuItems.clear();
763 816
764 menu->setItemVisible("Translate To", !mReadOnly);
765 menu->setItemVisible("Transep", !mReadOnly);
766
767 // spell_check="true" in xui 817 // spell_check="true" in xui
818 menu->setItemVisible("Spelsep", !mReadOnly && mSpellCheckable);
768 if (!mReadOnly && mSpellCheckable) 819 if (!mReadOnly && mSpellCheckable)
769 { 820 {
770 const LLWString& text = mText.getWString();
771
772 // search for word matches 821 // search for word matches
773 if (LLTextEditor::isPartOfWord(text[wordEnd])) 822 bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordEnd);
823 if (is_word_part)
774 { 824 {
775 // Select word the cursor is over 825 const LLWString& text = mText.getWString();
776 while ((wordEnd > 0) && LLTextEditor::isPartOfWord(text[wordEnd-1]))
777 {
778 wordEnd--;
779 }
780 wordStart = wordEnd;
781 //startSelection();
782
783 while ((wordEnd < (S32)text.length()) && LLTextEditor::isPartOfWord( text[wordEnd] ) )
784 {
785 wordEnd++;
786 }
787 std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordEnd-wordStart)); 826 std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordEnd-wordStart));
788 827
789 if (!glggHunSpell->isSpelledRight(selectedWord)) 828 if (!glggHunSpell->isSpelledRight(selectedWord))
790 { 829 {
791 //misspelled word here, and you have just right clicked on it! 830 //misspelled word here, and you have just right clicked on it!
792 std::vector<std::string> suggs = glggHunSpell->getSuggestionList(selectedWord); 831 std::vector<std::string> suggs = glggHunSpell->getSuggestionList(selectedWord);
793 //menu->setItemVisible("Transep",(suggs.size()>0));
794 832
795 for (int i = 0; i<(int)suggs.size() ;i++) 833 for (int i = 0; i<(int)suggs.size() ;i++)
796 { 834 {
@@ -821,7 +859,7 @@ BOOL LLLineEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
821 859
822 SpellMenuBind * tempStruct = new SpellMenuBind; 860 SpellMenuBind * tempStruct = new SpellMenuBind;
823 tempStruct->origin = this; 861 tempStruct->origin = this;
824 if (mShowMisspellings) 862 if (glggHunSpell->getSpellCheckHighlight())
825 { 863 {
826 tempStruct->word = "Hide Misspellings"; 864 tempStruct->word = "Hide Misspellings";
827 } 865 }
@@ -836,6 +874,7 @@ BOOL LLLineEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
836 menu->append(suggMenuItem); 874 menu->append(suggMenuItem);
837 } 875 }
838 876
877 mLastContextMenuX = x;
839 menu->buildDrawLabels(); 878 menu->buildDrawLabels();
840 menu->updateParent(LLMenuGL::sMenuContainer); 879 menu->updateParent(LLMenuGL::sMenuContainer);
841 LLMenuGL::showPopup(this, menu, x, y); 880 LLMenuGL::showPopup(this, menu, x, y);
@@ -1109,13 +1148,9 @@ void LLLineEditor::setSelection(S32 start, S32 end)
1109{ 1148{
1110 S32 len = mText.length(); 1149 S32 len = mText.length();
1111 1150
1112 mIsSelecting = TRUE; 1151 mSelectionStart = llclamp(start, 0, len);
1113 1152 mSelectionEnd = llclamp(end, 0, len);
1114 // JC, yes, this seems odd, but I think you have to presume a 1153 setCursor(end);
1115 // selection dragged from the end towards the start.
1116 mSelectionStart = llclamp(end, 0, len);
1117 mSelectionEnd = llclamp(start, 0, len);
1118 setCursor(start);
1119} 1154}
1120 1155
1121void LLLineEditor::setDrawAsterixes(BOOL b) 1156void LLLineEditor::setDrawAsterixes(BOOL b)
@@ -1152,6 +1187,26 @@ S32 LLLineEditor::nextWordPos(S32 cursorPos) const
1152 return cursorPos; 1187 return cursorPos;
1153} 1188}
1154 1189
1190BOOL LLLineEditor::getWordBoundriesAt(const S32 at, S32* word_begin, S32* word_length) const
1191{
1192 const LLWString& wtext = mText.getWString();
1193 S32 pos = at;
1194 if (LLTextEditor::isPartOfWord(wtext[pos]))
1195 {
1196 while ( (pos > 0) && LLTextEditor::isPartOfWord(wtext[pos - 1]) )
1197 {
1198 pos--;
1199 }
1200 *word_begin = pos;
1201 while ( (pos < wtext.length()) && LLTextEditor::isPartOfWord(wtext[pos]) )
1202 {
1203 pos++;
1204 }
1205 *word_length = pos - *word_begin;
1206 return TRUE;
1207 }
1208 return FALSE;
1209}
1155 1210
1156BOOL LLLineEditor::handleSelectionKey(KEY key, MASK mask) 1211BOOL LLLineEditor::handleSelectionKey(KEY key, MASK mask)
1157{ 1212{
@@ -1315,6 +1370,37 @@ void LLLineEditor::spellReplace(SpellMenuBind* spellData)
1315 1370
1316 1371
1317} 1372}
1373
1374void LLLineEditor::translationReplace(const std::string &translation, const S32 orig_start, const S32 orig_length)
1375{
1376 //*TODO: should probably check if the content was modified since the http query
1377 // was made, so we don't insert text in the wrong place.
1378 BOOL replace = gSavedSettings.getBOOL("EmeraldTranslateReplace");
1379 std::string text = replace ? translation : " (" + translation + ")";
1380 S32 pos = replace ? orig_start : orig_start + orig_length;
1381 if (replace)
1382 {
1383 mText.erase(orig_start, orig_length);
1384 }
1385 insert(text, pos);
1386
1387 S32 text_wlen = utf8str_to_wstring(text).length();
1388 if (hasSelection())
1389 {
1390 setSelection(pos, pos + text_wlen);
1391 }
1392 setCursor(pos + text_wlen);
1393}
1394
1395BOOL LLLineEditor::canTranslate() const
1396{
1397 // if allow_translate="true" in xui, and if other factors permit, we allow it
1398 S32 pos = calculateCursorFromMouse(mLastContextMenuX);
1399 const LLWString& wtext = getWText();
1400 bool is_word_part = (pos > -1) && LLTextEditor::isPartOfWord(wtext[pos]);
1401 return (mAllowTranslate && !mReadOnly && (is_word_part || hasSelection()));
1402}
1403
1318void LLLineEditor::insert(std::string what, S32 wher) 1404void LLLineEditor::insert(std::string what, S32 wher)
1319{ 1405{
1320 LLLineEditorRollback rollback(this); 1406 LLLineEditorRollback rollback(this);
@@ -1925,7 +2011,7 @@ void LLLineEditor::drawMisspelled(LLRect background)
1925 } 2011 }
1926 } 2012 }
1927 2013
1928 if (mShowMisspellings) 2014 if (glggHunSpell->getSpellCheckHighlight())
1929 { 2015 {
1930 for (int i =0; i<(int)misspellLocations.size(); i++) 2016 for (int i =0; i<(int)misspellLocations.size(); i++)
1931 { 2017 {
@@ -2830,6 +2916,11 @@ LLView* LLLineEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
2830 { 2916 {
2831 line_editor->setSpellCheckable(spell_checking); 2917 line_editor->setSpellCheckable(spell_checking);
2832 } 2918 }
2919 BOOL allow_translate = TRUE;
2920 if (node->getAttributeBOOL("allow_translate", allow_translate))
2921 {
2922 line_editor->setAllowTranslate(allow_translate);
2923 }
2833 2924
2834 line_editor->setColorParameters(node); 2925 line_editor->setColorParameters(node);
2835 2926
diff --git a/linden/indra/llui/lllineeditor.h b/linden/indra/llui/lllineeditor.h
index 147b232..f9e0621 100644
--- a/linden/indra/llui/lllineeditor.h
+++ b/linden/indra/llui/lllineeditor.h
@@ -107,6 +107,8 @@ public:
107 }; 107 };
108 108
109 virtual void spellReplace(SpellMenuBind* spellData); 109 virtual void spellReplace(SpellMenuBind* spellData);
110 virtual void translationReplace(const std::string &translation, const S32 orig_start, const S32 orig_length);
111 virtual BOOL canTranslate() const;
110 virtual void insert(std::string what,S32 wher); 112 virtual void insert(std::string what,S32 wher);
111 113
112 // LLEditMenuHandler overrides 114 // LLEditMenuHandler overrides
@@ -133,15 +135,22 @@ public:
133 virtual void deselect(); 135 virtual void deselect();
134 virtual BOOL canDeselect() const; 136 virtual BOOL canDeselect() const;
135 137
138 static BOOL context_enable_cut(void* data);
136 static void context_cut(void* data); 139 static void context_cut(void* data);
140 static BOOL context_enable_copy(void* data);
137 static void context_copy(void* data); 141 static void context_copy(void* data);
138 static void spell_correct(void* data); 142 static BOOL context_enable_paste(void* data);
139 static void spell_show(void* data);
140 static void translateText(void * data);
141 static void spell_add(void* data);
142 static void context_paste(void* data); 143 static void context_paste(void* data);
144 static BOOL context_enable_delete(void* data);
143 static void context_delete(void* data); 145 static void context_delete(void* data);
146 static BOOL context_enable_selectall(void* data);
144 static void context_selectall(void* data); 147 static void context_selectall(void* data);
148 static BOOL context_enable_translate(void * data);
149 static void context_translate(void * data);
150 static void spell_correct(void* data);
151 static void spell_show(void* data);
152 static void spell_add(void* data);
153
145 std::vector<S32> getMisspelledWordsPositions(); 154 std::vector<S32> getMisspelledWordsPositions();
146 // view overrides 155 // view overrides
147 virtual void draw(); 156 virtual void draw();
@@ -199,6 +208,7 @@ public:
199 void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; } 208 void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; }
200 void setFocusBgColor(const LLColor4& c) { mFocusBgColor = c; } 209 void setFocusBgColor(const LLColor4& c) { mFocusBgColor = c; }
201 void setSpellCheckable(BOOL b) { mSpellCheckable = b; } 210 void setSpellCheckable(BOOL b) { mSpellCheckable = b; }
211 void setAllowTranslate(BOOL b) { mAllowTranslate = b; }
202 212
203 const LLColor4& getFgColor() const { return mFgColor; } 213 const LLColor4& getFgColor() const { return mFgColor; }
204 const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor; } 214 const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor; }
@@ -215,6 +225,7 @@ public:
215 // get the cursor position of the beginning/end of the prev/next word in the text 225 // get the cursor position of the beginning/end of the prev/next word in the text
216 S32 prevWordPos(S32 cursorPos) const; 226 S32 prevWordPos(S32 cursorPos) const;
217 S32 nextWordPos(S32 cursorPos) const; 227 S32 nextWordPos(S32 cursorPos) const;
228 BOOL getWordBoundriesAt(const S32 at, S32* word_begin, S32* word_length) const;
218 229
219 BOOL hasSelection() const { return (mSelectionStart != mSelectionEnd); } 230 BOOL hasSelection() const { return (mSelectionStart != mSelectionEnd); }
220 void startSelection(); 231 void startSelection();
@@ -261,7 +272,7 @@ private:
261 void removeChar(); 272 void removeChar();
262 void addChar(const llwchar c); 273 void addChar(const llwchar c);
263 void setCursorAtLocalPos(S32 local_mouse_x); 274 void setCursorAtLocalPos(S32 local_mouse_x);
264 S32 calculateCursorFromMouse(S32 local_mouse_x); 275 S32 calculateCursorFromMouse(S32 local_mouse_x) const;
265 S32 findPixelNearestPos(S32 cursor_offset = 0) const; 276 S32 findPixelNearestPos(S32 cursor_offset = 0) const;
266 void reportBadKeystroke(); 277 void reportBadKeystroke();
267 BOOL handleSpecialKey(KEY key, MASK mask); 278 BOOL handleSpecialKey(KEY key, MASK mask);
@@ -294,10 +305,11 @@ protected:
294 S32 mStartSpellHere; // the position of the first char on the screen, stored so we know when to update 305 S32 mStartSpellHere; // the position of the first char on the screen, stored so we know when to update
295 S32 mEndSpellHere; // the location of the last char on the screen 306 S32 mEndSpellHere; // the location of the last char on the screen
296 BOOL mSpellCheckable; // set in xui as "spell_check". Default value for a field 307 BOOL mSpellCheckable; // set in xui as "spell_check". Default value for a field
297 BOOL mShowMisspellings; // show misspellings as highlighted (initialized in the ctor)
298 LLFrameTimer mSpellTimer; 308 LLFrameTimer mSpellTimer;
299 //to keep track of what we have to remove before showing menu 309 //to keep track of what we have to remove before showing menu
300 std::vector<SpellMenuBind* > suggestionMenuItems; 310 std::vector<SpellMenuBind* > suggestionMenuItems;
311 S32 mLastContextMenuX;
312 BOOL mAllowTranslate; // set in xui as "allow_translate".
301 313
302 // line history support: 314 // line history support:
303 BOOL mHaveHistory; // flag for enabled line history 315 BOOL mHaveHistory; // flag for enabled line history
diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp
index b101588..8dcb014 100644
--- a/linden/indra/llui/lltexteditor.cpp
+++ b/linden/indra/llui/lltexteditor.cpp
@@ -105,21 +105,23 @@ bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) =
105class TextChatTranslationReceiver : public LLTranslate::TranslationReceiver 105class TextChatTranslationReceiver : public LLTranslate::TranslationReceiver
106{ 106{
107public : 107public :
108 TextChatTranslationReceiver(const std::string &toLang, LLTextEditor* line): LLTranslate::TranslationReceiver("", toLang), 108 TextChatTranslationReceiver(const std::string &toLang, LLTextEditor* line, const S32 start, const S32 len):
109 m_line(line) 109 LLTranslate::TranslationReceiver("", toLang),
110 m_line(line),
111 m_position(start),
112 m_origLength(len)
110 { 113 {
111 } 114 }
112 115
113 static boost::intrusive_ptr<TextChatTranslationReceiver> build(const std::string &toLang,LLTextEditor* line) 116 static boost::intrusive_ptr<TextChatTranslationReceiver> build(const std::string &toLang,LLTextEditor* line, const S32 start, const S32 len)
114 { 117 {
115 return boost::intrusive_ptr<TextChatTranslationReceiver>(new TextChatTranslationReceiver(toLang,line)); 118 return boost::intrusive_ptr<TextChatTranslationReceiver>(new TextChatTranslationReceiver(toLang, line, start, len));
116 } 119 }
117 120
118protected: 121protected:
119 void handleResponse(const std::string &translation, const std::string &detectedLanguage) 122 void handleResponse(const std::string &translation, const std::string &detectedLanguage)
120 { 123 {
121 BOOL rep = gSavedSettings.getBOOL("EmeraldTranslateReplace"); 124 m_line->translationReplace(translation, m_position, m_origLength);
122 m_line->insertText((rep?"":" (") + translation +(rep?"":")"),rep);
123 } 125 }
124 void handleFailure() 126 void handleFailure()
125 { 127 {
@@ -127,6 +129,8 @@ protected:
127 } 129 }
128private: 130private:
129 LLTextEditor* m_line; 131 LLTextEditor* m_line;
132 S32 m_position;
133 S32 m_origLength;
130}; 134};
131 135
132/////////////////////////////////////////////////////////////////// 136///////////////////////////////////////////////////////////////////
@@ -321,10 +325,12 @@ LLTextEditor::LLTextEditor(
321 mMouseDownY(0), 325 mMouseDownY(0),
322 mLastSelectionX(-1), 326 mLastSelectionX(-1),
323 mLastSelectionY(-1), 327 mLastSelectionY(-1),
328 mLastContextMenuX(-1),
329 mLastContextMenuY(-1),
324 mReflowNeeded(FALSE), 330 mReflowNeeded(FALSE),
325 mScrollNeeded(FALSE), 331 mScrollNeeded(FALSE),
326 mSpellCheckable(FALSE), 332 mSpellCheckable(FALSE),
327 mShowMisspellings(FALSE) 333 mAllowTranslate(TRUE)
328{ 334{
329 mSourceID.generate(); 335 mSourceID.generate();
330 336
@@ -377,12 +383,6 @@ LLTextEditor::LLTextEditor(
377 mParseHTML=FALSE; 383 mParseHTML=FALSE;
378 mHTML.clear(); 384 mHTML.clear();
379 385
380 // in other words, highlighting requires a restart
381 if (glggHunSpell->getSpellCheckHighlight())
382 {
383 mShowMisspellings = TRUE;
384 }
385
386 // make the popup menu available 386 // make the popup menu available
387 //LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_texteditor.xml", parent_view); 387 //LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_texteditor.xml", parent_view);
388 LLMenuGL* menu = new LLMenuGL("wot"); 388 LLMenuGL* menu = new LLMenuGL("wot");
@@ -390,46 +390,46 @@ LLTextEditor::LLTextEditor(
390 { 390 {
391 menu = new LLMenuGL(LLStringUtil::null); 391 menu = new LLMenuGL(LLStringUtil::null);
392 }*/ 392 }*/
393 menu->append(new LLMenuItemCallGL("Cut", context_cut, NULL, this)); 393 menu->append(new LLMenuItemCallGL("Cut", context_cut, context_enable_cut, this));
394 menu->append(new LLMenuItemCallGL("Copy", context_copy, NULL, this)); 394 menu->append(new LLMenuItemCallGL("Copy", context_copy, context_enable_copy, this));
395 menu->append(new LLMenuItemCallGL("Paste", context_paste, NULL, this)); 395 menu->append(new LLMenuItemCallGL("Paste", context_paste, context_enable_paste, this));
396 menu->append(new LLMenuItemCallGL("Delete", context_delete, NULL, this)); 396 menu->append(new LLMenuItemCallGL("Delete", context_delete, context_enable_delete, this));
397 menu->append(new LLMenuItemCallGL("Select All", context_selectall, NULL, this)); 397 menu->append(new LLMenuItemCallGL("Select All", context_selectall, context_enable_selectall, this));
398 menu->appendSeparator("transep"); 398 menu->appendSeparator("Transep");
399 LLMenuGL* translatemenu = new LLMenuGL("Translate To"); 399 LLMenuGL* translatemenu = new LLMenuGL("Translate To");
400 translatemenu->setCanTearOff(FALSE); 400 translatemenu->setCanTearOff(FALSE);
401 SpellMenuBind* t=new SpellMenuBind;t->origin=this;t->word="en"; 401 SpellMenuBind* t=new SpellMenuBind;t->origin=this;t->word="en";
402 translatemenu->append(new LLMenuItemCallGL("English",translateText, NULL, t)); 402 translatemenu->append(new LLMenuItemCallGL("English", context_translate, context_enable_translate, t));
403 t=new SpellMenuBind;t->origin=this;t->word="da"; 403 t=new SpellMenuBind;t->origin=this;t->word="da";
404 translatemenu->append(new LLMenuItemCallGL("Danish",translateText, NULL, t)); 404 translatemenu->append(new LLMenuItemCallGL("Danish", context_translate, context_enable_translate, t));
405 t=new SpellMenuBind;t->origin=this;t->word="de"; 405 t=new SpellMenuBind;t->origin=this;t->word="de";
406 translatemenu->append(new LLMenuItemCallGL("Deutsch(German)",translateText, NULL, t)); 406 translatemenu->append(new LLMenuItemCallGL("Deutsch(German)", context_translate, context_enable_translate, t));
407 t=new SpellMenuBind;t->origin=this;t->word="es"; 407 t=new SpellMenuBind;t->origin=this;t->word="es";
408 translatemenu->append(new LLMenuItemCallGL("Spanish",translateText, NULL, t)); 408 translatemenu->append(new LLMenuItemCallGL("Spanish", context_translate, context_enable_translate, t));
409 t=new SpellMenuBind;t->origin=this;t->word="fr"; 409 t=new SpellMenuBind;t->origin=this;t->word="fr";
410 translatemenu->append(new LLMenuItemCallGL("French",translateText, NULL, t)); 410 translatemenu->append(new LLMenuItemCallGL("French", context_translate, context_enable_translate, t));
411 t=new SpellMenuBind;t->origin=this;t->word="it"; 411 t=new SpellMenuBind;t->origin=this;t->word="it";
412 translatemenu->append(new LLMenuItemCallGL("Italian",translateText, NULL, t)); 412 translatemenu->append(new LLMenuItemCallGL("Italian", context_translate, context_enable_translate, t));
413 t=new SpellMenuBind;t->origin=this;t->word="hu"; 413 t=new SpellMenuBind;t->origin=this;t->word="hu";
414 translatemenu->append(new LLMenuItemCallGL("Hungarian",translateText, NULL, t)); 414 translatemenu->append(new LLMenuItemCallGL("Hungarian", context_translate, context_enable_translate, t));
415 t=new SpellMenuBind;t->origin=this;t->word="nl"; 415 t=new SpellMenuBind;t->origin=this;t->word="nl";
416 translatemenu->append(new LLMenuItemCallGL("Dutch",translateText, NULL, t)); 416 translatemenu->append(new LLMenuItemCallGL("Dutch", context_translate, context_enable_translate, t));
417 t=new SpellMenuBind;t->origin=this;t->word="pl"; 417 t=new SpellMenuBind;t->origin=this;t->word="pl";
418 translatemenu->append(new LLMenuItemCallGL("Polish",translateText, NULL, t)); 418 translatemenu->append(new LLMenuItemCallGL("Polish", context_translate, context_enable_translate, t));
419 t=new SpellMenuBind;t->origin=this;t->word="pt"; 419 t=new SpellMenuBind;t->origin=this;t->word="pt";
420 translatemenu->append(new LLMenuItemCallGL("Portugese",translateText, NULL, t)); 420 translatemenu->append(new LLMenuItemCallGL("Portugese", context_translate, context_enable_translate, t));
421 t=new SpellMenuBind;t->origin=this;t->word="ru"; 421 t=new SpellMenuBind;t->origin=this;t->word="ru";
422 translatemenu->append(new LLMenuItemCallGL("Russian",translateText, NULL, t)); 422 translatemenu->append(new LLMenuItemCallGL("Russian", context_translate, context_enable_translate, t));
423 t=new SpellMenuBind;t->origin=this;t->word="tr"; 423 t=new SpellMenuBind;t->origin=this;t->word="tr";
424 translatemenu->append(new LLMenuItemCallGL("Turkish",translateText, NULL, t)); 424 translatemenu->append(new LLMenuItemCallGL("Turkish", context_translate, context_enable_translate, t));
425 t=new SpellMenuBind;t->origin=this;t->word="uk"; 425 t=new SpellMenuBind;t->origin=this;t->word="uk";
426 translatemenu->append(new LLMenuItemCallGL("Ukrainian",translateText, NULL, t)); 426 translatemenu->append(new LLMenuItemCallGL("Ukrainian", context_translate, context_enable_translate, t));
427 t=new SpellMenuBind;t->origin=this;t->word="zh"; 427 t=new SpellMenuBind;t->origin=this;t->word="zh";
428 translatemenu->append(new LLMenuItemCallGL("Chinese",translateText, NULL, t)); 428 translatemenu->append(new LLMenuItemCallGL("Chinese", context_translate, context_enable_translate, t));
429 t=new SpellMenuBind;t->origin=this;t->word="ja"; 429 t=new SpellMenuBind;t->origin=this;t->word="ja";
430 translatemenu->append(new LLMenuItemCallGL("Japanese",translateText, NULL, t)); 430 translatemenu->append(new LLMenuItemCallGL("Japanese", context_translate, context_enable_translate, t));
431 t=new SpellMenuBind;t->origin=this;t->word="ko"; 431 t=new SpellMenuBind;t->origin=this;t->word="ko";
432 translatemenu->append(new LLMenuItemCallGL("Korean",translateText, NULL, t)); 432 translatemenu->append(new LLMenuItemCallGL("Korean", context_translate, context_enable_translate, t));
433 433
434 menu->appendMenu(translatemenu); 434 menu->appendMenu(translatemenu);
435 menu->appendSeparator("Spelsep"); 435 menu->appendSeparator("Spelsep");
@@ -439,7 +439,6 @@ LLTextEditor::LLTextEditor(
439 mPopupMenuHandle = menu->getHandle(); 439 mPopupMenuHandle = menu->getHandle();
440} 440}
441 441
442
443LLTextEditor::~LLTextEditor() 442LLTextEditor::~LLTextEditor()
444{ 443{
445 gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() 444 gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
@@ -457,27 +456,67 @@ LLTextEditor::~LLTextEditor()
457 std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); 456 std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
458 LLView::deleteViewByHandle(mPopupMenuHandle); 457 LLView::deleteViewByHandle(mPopupMenuHandle);
459} 458}
459
460BOOL LLTextEditor::context_enable_cut(void* data)
461{
462 LLTextEditor* line = (LLTextEditor*)data;
463 return (line && line->canCut());
464}
465
460void LLTextEditor::context_cut(void* data) 466void LLTextEditor::context_cut(void* data)
461{ 467{
462 LLTextEditor* line = (LLTextEditor*)data; 468 LLTextEditor* line = (LLTextEditor*)data;
463 if(line)line->cut(); 469 if(line)line->cut();
464} 470}
471
472BOOL LLTextEditor::context_enable_copy(void* data)
473{
474 LLTextEditor* line = (LLTextEditor*)data;
475 return (line && line->canCopy());
476}
477
465void LLTextEditor::context_copy(void* data) 478void LLTextEditor::context_copy(void* data)
466{ 479{
467 LLTextEditor* line = (LLTextEditor*)data; 480 LLTextEditor* line = (LLTextEditor*)data;
468 if(line)line->copy(); 481 if(line)line->copy();
469} 482}
470void LLTextEditor::translateText(void * data) 483
484BOOL LLTextEditor::context_enable_translate(void * data)
485{
486 SpellMenuBind* t = (SpellMenuBind*)data;
487 return (t && t->origin && t->origin->canTranslate());
488}
489
490void LLTextEditor::context_translate(void * data)
471{ 491{
472 SpellMenuBind* t = (SpellMenuBind*)data; 492 SpellMenuBind* t = (SpellMenuBind*)data;
473 LLTextEditor* line = t->origin; 493 LLTextEditor* line = t->origin;
474 const std::string &toLang = t->word;//LLTranslate::getTranslateLanguage(); 494 const std::string &toLang = t->word;//LLTranslate::getTranslateLanguage();
475 LLHTTPClient::ResponderPtr result = TextChatTranslationReceiver::build(toLang,line);
476 495
477 S32 left_pos = llmin( line->mSelectionStart, line->mSelectionEnd ); 496 bool has_text = false;
478 S32 length = abs( line->mSelectionStart - line->mSelectionEnd ); 497 S32 start, length;
479 LLTranslate::translateMessage(result,"", toLang, line->getText().substr(left_pos, length)); 498 if (line->hasSelection())
499 {
500 // translate selection
501 start = llmin(line->mSelectionStart, line->mSelectionEnd);
502 length = abs(line->mSelectionEnd - line->mSelectionStart);
503 has_text = length > 0;
504 }
505 else
506 {
507 // translate one word as click position
508 S32 at = line->getCursorPosFromLocalCoord(line->mLastContextMenuX, line->mLastContextMenuY, TRUE);
509 has_text = line->getWordBoundriesAt(at, &start, &length);
510 }
511
512 if (has_text)
513 {
514 const std::string to_translate = wstring_to_utf8str(line->getWText().substr(start, length));
515 LLHTTPClient::ResponderPtr result = TextChatTranslationReceiver::build(toLang, line, start, length);
516 LLTranslate::translateMessage(result,"", toLang, to_translate);
517 }
480} 518}
519
481void LLTextEditor::spell_correct(void* data) 520void LLTextEditor::spell_correct(void* data)
482{ 521{
483 SpellMenuBind* tempBind = (SpellMenuBind*)data; 522 SpellMenuBind* tempBind = (SpellMenuBind*)data;
@@ -496,14 +535,8 @@ void LLTextEditor::spell_show(void * data)
496 535
497 if (tempBind && line) 536 if (tempBind && line)
498 { 537 {
499 if (tempBind->word == "Show Misspellings") 538 BOOL show = (tempBind->word == "Show Misspellings");
500 { 539 glggHunSpell->setSpellCheckHighlight(show);
501 glggHunSpell->setSpellCheckHighlight(TRUE);
502 }
503 else
504 {
505 glggHunSpell->setSpellCheckHighlight(FALSE);
506 }
507 } 540 }
508} 541}
509 542
@@ -555,16 +588,37 @@ void LLTextEditor::spell_add(void* data)
555 tempBind->origin->mPrevSpelledText.erase();//make it update 588 tempBind->origin->mPrevSpelledText.erase();//make it update
556 } 589 }
557} 590}
591
592BOOL LLTextEditor::context_enable_paste(void* data)
593{
594 LLTextEditor* line = (LLTextEditor*)data;
595 return(line && line->canPaste());
596}
597
558void LLTextEditor::context_paste(void* data) 598void LLTextEditor::context_paste(void* data)
559{ 599{
560 LLTextEditor* line = (LLTextEditor*)data; 600 LLTextEditor* line = (LLTextEditor*)data;
561 if(line)line->paste(); 601 if(line)line->paste();
562} 602}
603
604BOOL LLTextEditor::context_enable_delete(void* data)
605{
606 LLTextEditor* line = (LLTextEditor*)data;
607 return (line && line->canDoDelete());
608}
609
563void LLTextEditor::context_delete(void* data) 610void LLTextEditor::context_delete(void* data)
564{ 611{
565 LLTextEditor* line = (LLTextEditor*)data; 612 LLTextEditor* line = (LLTextEditor*)data;
566 if(line)line->doDelete(); 613 if(line)line->doDelete();
567} 614}
615
616BOOL LLTextEditor::context_enable_selectall(void* data)
617{
618 LLTextEditor* line = (LLTextEditor*)data;
619 return (line && line->canSelectAll());
620}
621
568void LLTextEditor::context_selectall(void* data) 622void LLTextEditor::context_selectall(void* data)
569{ 623{
570 LLTextEditor* line = (LLTextEditor*)data; 624 LLTextEditor* line = (LLTextEditor*)data;
@@ -947,6 +1001,26 @@ S32 LLTextEditor::nextWordPos(S32 cursorPos) const
947 return cursorPos; 1001 return cursorPos;
948} 1002}
949 1003
1004BOOL LLTextEditor::getWordBoundriesAt(const S32 at, S32* word_begin, S32* word_length) const
1005{
1006 S32 pos = at;
1007 if (isPartOfWord(mWText[pos]))
1008 {
1009 while ( (pos > 0) && isPartOfWord(mWText[pos - 1]) )
1010 {
1011 pos--;
1012 }
1013 *word_begin = pos;
1014 while ( (pos < getLength()) && isPartOfWord(mWText[pos]) )
1015 {
1016 pos++;
1017 }
1018 *word_length = pos - *word_begin;
1019 return TRUE;
1020 }
1021 return FALSE;
1022}
1023
950S32 LLTextEditor::getLineStart( S32 line ) const 1024S32 LLTextEditor::getLineStart( S32 line ) const
951{ 1025{
952 S32 num_lines = getLineCount(); 1026 S32 num_lines = getLineCount();
@@ -1439,7 +1513,8 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
1439 1513
1440 //setCursorAtLocalPos( x, y, TRUE ); 1514 //setCursorAtLocalPos( x, y, TRUE );
1441 S32 wordStart = 0; 1515 S32 wordStart = 0;
1442 S32 wordEnd = getCursorPosFromLocalCoord(x,y,TRUE); 1516 S32 wordEnd = 0;
1517 S32 pos = getCursorPosFromLocalCoord(x,y,TRUE);
1443 1518
1444 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); 1519 LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
1445 if (menu) 1520 if (menu)
@@ -1458,35 +1533,21 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
1458 } 1533 }
1459 suggestionMenuItems.clear(); 1534 suggestionMenuItems.clear();
1460 1535
1461 menu->setItemVisible("Translate To", !mReadOnly);
1462 menu->setItemVisible("Transep", !mReadOnly);
1463
1464 // spell_check="true" in xui 1536 // spell_check="true" in xui
1537 menu->setItemVisible("Spelsep", !mReadOnly && mSpellCheckable);
1465 if (!mReadOnly && mSpellCheckable) 1538 if (!mReadOnly && mSpellCheckable)
1466 { 1539 {
1467 const LLWString &text = mWText; 1540 bool is_word_part = getWordBoundriesAt(pos, &wordStart, &wordEnd);
1468 1541 if (is_word_part)
1469 if (isPartOfWord(text[wordEnd]) && !mReadOnly)
1470 { 1542 {
1471 // Select word the cursor is over 1543 const LLWString &text = mWText;
1472 while ((wordEnd > 0) && isPartOfWord(text[wordEnd-1]))
1473 {
1474 wordEnd--;
1475 }
1476 wordStart = wordEnd;
1477 //startSelection();
1478
1479 while ((wordEnd < (S32)text.length()) && isPartOfWord( text[wordEnd] ) )
1480 {
1481 wordEnd++;
1482 }
1483 std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordEnd-wordStart)); 1544 std::string selectedWord(std::string(text.begin(), text.end()).substr(wordStart,wordEnd-wordStart));
1545
1484 if (!glggHunSpell->isSpelledRight(selectedWord)) 1546 if (!glggHunSpell->isSpelledRight(selectedWord))
1485 { 1547 {
1486 //misspelled word here, and you have just right clicked on it! 1548 //misspelled word here, and you have just right clicked on it!
1487 std::vector<std::string> suggs = glggHunSpell->getSuggestionList(selectedWord); 1549 std::vector<std::string> suggs = glggHunSpell->getSuggestionList(selectedWord);
1488 1550
1489 //menu->setItemVisible("Transep",(suggs.size()>0));
1490 for (int i = 0; i<(int)suggs.size(); i++) 1551 for (int i = 0; i<(int)suggs.size(); i++)
1491 { 1552 {
1492 SpellMenuBind * tempStruct = new SpellMenuBind; 1553 SpellMenuBind * tempStruct = new SpellMenuBind;
@@ -1517,7 +1578,7 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
1517 1578
1518 SpellMenuBind * tempStruct = new SpellMenuBind; 1579 SpellMenuBind * tempStruct = new SpellMenuBind;
1519 tempStruct->origin = this; 1580 tempStruct->origin = this;
1520 if (mShowMisspellings) 1581 if (glggHunSpell->getSpellCheckHighlight())
1521 { 1582 {
1522 tempStruct->word = "Hide Misspellings"; 1583 tempStruct->word = "Hide Misspellings";
1523 } 1584 }
@@ -1531,6 +1592,8 @@ BOOL LLTextEditor::handleRightMouseDown( S32 x, S32 y, MASK mask )
1531 suggestionMenuItems.push_back(tempStruct); 1592 suggestionMenuItems.push_back(tempStruct);
1532 menu->append(suggMenuItem); 1593 menu->append(suggMenuItem);
1533 } 1594 }
1595 mLastContextMenuX = x;
1596 mLastContextMenuY = y;
1534 menu->buildDrawLabels(); 1597 menu->buildDrawLabels();
1535 menu->updateParent(LLMenuGL::sMenuContainer); 1598 menu->updateParent(LLMenuGL::sMenuContainer);
1536 LLMenuGL::showPopup(this, menu, x, y); 1599 LLMenuGL::showPopup(this, menu, x, y);
@@ -2238,6 +2301,35 @@ void LLTextEditor::spellReplace(SpellMenuBind* spellData)
2238 needsReflow(); 2301 needsReflow();
2239} 2302}
2240 2303
2304void LLTextEditor::translationReplace(const std::string &translation, const S32 orig_start, const S32 orig_length)
2305{
2306 //*TODO: should probably check if the content was modified since the http query
2307 // was made, so we don't insert text in the wrong place.
2308 BOOL replace = gSavedSettings.getBOOL("EmeraldTranslateReplace");
2309 LLWString wtext = utf8str_to_wstring(replace ? translation : " (" + translation + ")");
2310 S32 pos = replace ? orig_start : orig_start + orig_length;
2311 if (replace)
2312 {
2313 remove(orig_start, orig_length, FALSE);
2314 }
2315 S32 inserted = insert(pos, wtext, FALSE);
2316 if (hasSelection())
2317 {
2318 mSelectionStart = llclamp(pos, 0, getLength());
2319 mSelectionEnd = llclamp(pos + inserted, mSelectionStart, getLength());
2320 }
2321 setCursorPos(pos + inserted);
2322 needsReflow();
2323}
2324
2325BOOL LLTextEditor::canTranslate() const
2326{
2327 // if allow_translate="true" in xui, and if other factors permit, we allow it
2328 S32 pos = getCursorPosFromLocalCoord(mLastContextMenuX, mLastContextMenuY, TRUE);
2329 bool is_word_part = (pos > -1) && isPartOfWord(mWText[pos]);
2330 return (mAllowTranslate && !mReadOnly && (is_word_part || hasSelection()));
2331}
2332
2241// paste from clipboard 2333// paste from clipboard
2242void LLTextEditor::paste() 2334void LLTextEditor::paste()
2243{ 2335{
@@ -3162,7 +3254,7 @@ void LLTextEditor::drawMisspelled()
3162 } 3254 }
3163 } 3255 }
3164 //draw 3256 //draw
3165 if (mShowMisspellings) 3257 if (glggHunSpell->getSpellCheckHighlight())
3166 { 3258 {
3167 for (int i = 0; i<(int)misspellLocations.size() ;i++) 3259 for (int i = 0; i<(int)misspellLocations.size() ;i++)
3168 { 3260 {
@@ -4901,6 +4993,8 @@ void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node)
4901 4993
4902 node->getAttributeBOOL("spell_check", mSpellCheckable); 4994 node->getAttributeBOOL("spell_check", mSpellCheckable);
4903 4995
4996 node->getAttributeBOOL("allow_translate", mAllowTranslate);
4997
4904 LLColor4 color; 4998 LLColor4 color;
4905 if (LLUICtrlFactory::getAttributeColor(node,"cursor_color", color)) 4999 if (LLUICtrlFactory::getAttributeColor(node,"cursor_color", color))
4906 { 5000 {
diff --git a/linden/indra/llui/lltexteditor.h b/linden/indra/llui/lltexteditor.h
index 57a6bbd..f2a831b 100644
--- a/linden/indra/llui/lltexteditor.h
+++ b/linden/indra/llui/lltexteditor.h
@@ -136,6 +136,8 @@ public:
136 virtual BOOL canPaste() const; 136 virtual BOOL canPaste() const;
137 137
138 virtual void spellReplace(SpellMenuBind* spellData); 138 virtual void spellReplace(SpellMenuBind* spellData);
139 virtual void translationReplace(const std::string &translation, const S32 orig_start, const S32 orig_length);
140 virtual BOOL canTranslate() const;
139 141
140 virtual void updatePrimary(); 142 virtual void updatePrimary();
141 virtual void copyPrimary(); 143 virtual void copyPrimary();
@@ -148,13 +150,19 @@ public:
148 virtual BOOL canSelectAll() const; 150 virtual BOOL canSelectAll() const;
149 virtual void deselect(); 151 virtual void deselect();
150 virtual BOOL canDeselect() const; 152 virtual BOOL canDeselect() const;
151 static void context_cut(void* data);
152 153
154 static BOOL context_enable_cut(void* data);
155 static void context_cut(void* data);
156 static BOOL context_enable_copy(void* data);
153 static void context_copy(void* data); 157 static void context_copy(void* data);
158 static BOOL context_enable_paste(void* data);
154 static void context_paste(void* data); 159 static void context_paste(void* data);
160 static BOOL context_enable_delete(void* data);
155 static void context_delete(void* data); 161 static void context_delete(void* data);
162 static BOOL context_enable_selectall(void* data);
156 static void context_selectall(void* data); 163 static void context_selectall(void* data);
157 static void translateText(void * data); 164 static BOOL context_enable_translate(void * data);
165 static void context_translate(void * data);
158 static void spell_correct(void* data); 166 static void spell_correct(void* data);
159 static void spell_add(void* data); 167 static void spell_add(void* data);
160 static void spell_show(void* data); 168 static void spell_show(void* data);
@@ -352,6 +360,7 @@ public:
352 360
353 S32 prevWordPos(S32 cursorPos) const; 361 S32 prevWordPos(S32 cursorPos) const;
354 S32 nextWordPos(S32 cursorPos) const; 362 S32 nextWordPos(S32 cursorPos) const;
363 BOOL getWordBoundriesAt(const S32 at, S32* word_begin, S32* word_length) const;
355 364
356 S32 getLineCount() const { return mLineStartList.size(); } 365 S32 getLineCount() const { return mLineStartList.size(); }
357 S32 getLineStart( S32 line ) const; 366 S32 getLineStart( S32 line ) const;
@@ -527,7 +536,7 @@ private:
527 S32 spellEnd; 536 S32 spellEnd;
528 std::vector<S32> misspellLocations; // where all the mispelled words are 537 std::vector<S32> misspellLocations; // where all the mispelled words are
529 BOOL mSpellCheckable; // set in xui as "spell_check". Default value for a field 538 BOOL mSpellCheckable; // set in xui as "spell_check". Default value for a field
530 BOOL mShowMisspellings; // show misspellings as highlighted (initialized in the ctor) 539 BOOL mAllowTranslate; // set in xui as "allow_translate".
531 540
532 S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes 541 S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
533 542
@@ -568,6 +577,8 @@ private:
568 577
569 //to keep track of what we have to remove before showing menu 578 //to keep track of what we have to remove before showing menu
570 std::vector<SpellMenuBind* > suggestionMenuItems; 579 std::vector<SpellMenuBind* > suggestionMenuItems;
580 S32 mLastContextMenuX;
581 S32 mLastContextMenuY;
571 582
572 line_list_t mLineStartList; 583 line_list_t mLineStartList;
573 BOOL mReflowNeeded; 584 BOOL mReflowNeeded;
diff --git a/linden/indra/newview/lgghunspell_wrapper.cpp b/linden/indra/newview/lgghunspell_wrapper.cpp
index f800043..aa4507c 100644
--- a/linden/indra/newview/lgghunspell_wrapper.cpp
+++ b/linden/indra/newview/lgghunspell_wrapper.cpp
@@ -72,7 +72,7 @@ static char * countryCodesraw[] = {
72 (char*)"CF",(char*)"Central African Republic", 72 (char*)"CF",(char*)"Central African Republic",
73 (char*)"CG",(char*)"Congo", 73 (char*)"CG",(char*)"Congo",
74 (char*)"CH",(char*)"Switzerland", 74 (char*)"CH",(char*)"Switzerland",
75 (char*)"CI",(char*)"Côte D'ivoire (Ivory Coast)", 75 (char*)"CI",(char*)"Côte D'ivoire (Ivory Coast)",
76 (char*)"CK",(char*)"Cook Iislands", 76 (char*)"CK",(char*)"Cook Iislands",
77 (char*)"CL",(char*)"Chile", 77 (char*)"CL",(char*)"Chile",
78 (char*)"CM",(char*)"Cameroon", 78 (char*)"CM",(char*)"Cameroon",
@@ -212,7 +212,7 @@ static char * countryCodesraw[] = {
212 (char*)"PW",(char*)"Palau", 212 (char*)"PW",(char*)"Palau",
213 (char*)"PY",(char*)"Paraguay", 213 (char*)"PY",(char*)"Paraguay",
214 (char*)"QA",(char*)"Qatar", 214 (char*)"QA",(char*)"Qatar",
215 (char*)"RE",(char*)"Réunion", 215 (char*)"RE",(char*)"Réunion",
216 (char*)"RO",(char*)"Romania", 216 (char*)"RO",(char*)"Romania",
217 (char*)"RU",(char*)"Russian Federation", 217 (char*)"RU",(char*)"Russian Federation",
218 (char*)"RW",(char*)"Rwanda", 218 (char*)"RW",(char*)"Rwanda",
@@ -333,7 +333,7 @@ static char * languageCodesraw[]={
333 (char*)"ga",(char*)"Irish", 333 (char*)"ga",(char*)"Irish",
334 (char*)"gd",(char*)"Gaelic", 334 (char*)"gd",(char*)"Gaelic",
335 (char*)"gl",(char*)"Galician", 335 (char*)"gl",(char*)"Galician",
336 (char*)"gn",(char*)"Guaraní", 336 (char*)"gn",(char*)"Guaraní",
337 (char*)"gu",(char*)"Gujarati", 337 (char*)"gu",(char*)"Gujarati",
338 (char*)"gv",(char*)"Manx", 338 (char*)"gv",(char*)"Manx",
339 (char*)"ha",(char*)"Hausa", 339 (char*)"ha",(char*)"Hausa",
@@ -456,7 +456,7 @@ static char * languageCodesraw[]={
456 (char*)"uz",(char*)"Uzbek", 456 (char*)"uz",(char*)"Uzbek",
457 (char*)"ve",(char*)"Venda", 457 (char*)"ve",(char*)"Venda",
458 (char*)"vi",(char*)"Vietnamese", 458 (char*)"vi",(char*)"Vietnamese",
459 (char*)"vo",(char*)"Volapük", 459 (char*)"vo",(char*)"Volapük",
460 (char*)"wa",(char*)"Walloon", 460 (char*)"wa",(char*)"Walloon",
461 (char*)"wo",(char*)"Wolof", 461 (char*)"wo",(char*)"Wolof",
462 (char*)"xh",(char*)"Xhosa", 462 (char*)"xh",(char*)"Xhosa",
@@ -470,10 +470,9 @@ static char * languageCodesraw[]={
470#define LANGUAGE_CODES_RAW_SIZE 368 470#define LANGUAGE_CODES_RAW_SIZE 368
471 471
472lggHunSpell_Wrapper::lggHunSpell_Wrapper() 472lggHunSpell_Wrapper::lggHunSpell_Wrapper()
473 :
474 mSpellCheckHighlight(false)
475{ 473{
476 //languageCodes(begin(languageCodesraw), end(languageCodesraw)); 474 //languageCodes(begin(languageCodesraw), end(languageCodesraw));
475 mSpellCheckHighlight = rebind_llcontrol<BOOL>("EmeraldSpellDisplay", &gSavedSettings, false);
477} 476}
478 477
479lggHunSpell_Wrapper::~lggHunSpell_Wrapper() 478lggHunSpell_Wrapper::~lggHunSpell_Wrapper()
@@ -638,8 +637,6 @@ void lggHunSpell_Wrapper::processSettings()
638 //expects everything to already be in saved settings 637 //expects everything to already be in saved settings
639 //this will also reload and read the installed dicts 638 //this will also reload and read the installed dicts
640 setNewDictionary(gSavedSettings.getString("EmeraldSpellBase")); 639 setNewDictionary(gSavedSettings.getString("EmeraldSpellBase"));
641 mSpellCheckHighlight = gSavedSettings.getBOOL("EmeraldSpellDisplay");
642
643} 640}
644 641
645void lggHunSpell_Wrapper::addDictionary(std::string additionalDictionary) 642void lggHunSpell_Wrapper::addDictionary(std::string additionalDictionary)
@@ -966,5 +963,8 @@ void lggHunSpell_Wrapper::editCustomButton()
966 963
967void lggHunSpell_Wrapper::setSpellCheckHighlight(BOOL highlight) 964void lggHunSpell_Wrapper::setSpellCheckHighlight(BOOL highlight)
968{ 965{
969 mSpellCheckHighlight = highlight; 966 if (mSpellCheckHighlight)
967 {
968 *mSpellCheckHighlight = highlight;
969 }
970} 970}
diff --git a/linden/indra/newview/lgghunspell_wrapper.h b/linden/indra/newview/lgghunspell_wrapper.h
index b5f3ddb..71b2f14 100644
--- a/linden/indra/newview/lgghunspell_wrapper.h
+++ b/linden/indra/newview/lgghunspell_wrapper.h
@@ -55,7 +55,7 @@ public:
55 std::string VEC2CSV(std::vector<std::string> vec); 55 std::string VEC2CSV(std::vector<std::string> vec);
56 56
57 void setSpellCheckHighlight(BOOL highlight); 57 void setSpellCheckHighlight(BOOL highlight);
58 BOOL getSpellCheckHighlight() { return mSpellCheckHighlight; } 58 BOOL getSpellCheckHighlight() { return mSpellCheckHighlight && *mSpellCheckHighlight; }
59 59
60private: 60private:
61 void createCustomDic(); 61 void createCustomDic();
@@ -67,7 +67,7 @@ private:
67 std::string currentBaseDic; 67 std::string currentBaseDic;
68 //std::vector<std::string> languageCodes; 68 //std::vector<std::string> languageCodes;
69 //std::vector<std::string> countryCodes; 69 //std::vector<std::string> countryCodes;
70 BOOL mSpellCheckHighlight; 70 BOOL* mSpellCheckHighlight;
71}; 71};
72 72
73extern lggHunSpell_Wrapper* glggHunSpell; // the singleton hunspell wrapper 73extern lggHunSpell_Wrapper* glggHunSpell; // the singleton hunspell wrapper
diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp
index 35fd395..6322d27 100755
--- a/linden/indra/newview/llviewermessage.cpp
+++ b/linden/indra/newview/llviewermessage.cpp
@@ -2716,43 +2716,46 @@ void process_decline_callingcard(LLMessageSystem* msg, void**)
2716class ChatTranslationReceiver : public LLTranslate::TranslationReceiver 2716class ChatTranslationReceiver : public LLTranslate::TranslationReceiver
2717{ 2717{
2718public : 2718public :
2719 ChatTranslationReceiver(const std::string &fromLang, const std::string &toLang, LLChat *chat, 2719 ChatTranslationReceiver(const std::string &fromLang, const std::string &toLang, const LLChat &chat,
2720 const BOOL history) 2720 const std::string &orig_mesg, const BOOL history)
2721 : LLTranslate::TranslationReceiver(fromLang, toLang), 2721 : LLTranslate::TranslationReceiver(fromLang, toLang),
2722 m_chat(chat), 2722 m_chat(chat),
2723 m_origMesg(orig_mesg),
2723 m_history(history) 2724 m_history(history)
2724 { 2725 {
2725 } 2726 }
2726 2727
2727 static boost::intrusive_ptr<ChatTranslationReceiver> build(const std::string &fromLang, const std::string &toLang, LLChat *chat, const BOOL history) 2728 static boost::intrusive_ptr<ChatTranslationReceiver> build(const std::string &fromLang, const std::string &toLang, const LLChat &chat, const std::string &orig_mesg, const BOOL history)
2728 { 2729 {
2729 return boost::intrusive_ptr<ChatTranslationReceiver>(new ChatTranslationReceiver(fromLang, toLang, chat, history)); 2730 return boost::intrusive_ptr<ChatTranslationReceiver>(new ChatTranslationReceiver(fromLang, toLang, chat, orig_mesg, history));
2730 } 2731 }
2731 2732
2732protected: 2733protected:
2733 void handleResponse(const std::string &translation, const std::string &detectedLanguage) 2734 void handleResponse(const std::string &translation, const std::string &detected_language)
2734 { 2735 {
2735 if (m_toLang != detectedLanguage) 2736 // filter out non-interesting responeses
2736 m_chat->mText += " (" + translation + ")"; 2737 if ( !translation.empty()
2737 2738 && (m_toLang != detected_language)
2738 add_floater_chat(*m_chat, m_history); 2739 && (LLStringUtil::compareInsensitive(translation, m_origMesg) != 0) )
2740 {
2741 m_chat.mText += " (" + translation + ")";
2742 }
2739 2743
2740 delete m_chat; 2744 add_floater_chat(m_chat, m_history);
2741 } 2745 }
2742 2746
2743 void handleFailure() 2747 void handleFailure()
2744 { 2748 {
2745 LLTranslate::TranslationReceiver::handleFailure(); 2749 LLTranslate::TranslationReceiver::handleFailure();
2746 2750
2747 m_chat->mText += " (?)"; 2751 m_chat.mText += " (?)";
2748 2752
2749 add_floater_chat(*m_chat, m_history); 2753 add_floater_chat(m_chat, m_history);
2750
2751 delete m_chat;
2752 } 2754 }
2753 2755
2754private: 2756private:
2755 LLChat *m_chat; 2757 LLChat m_chat;
2758 std::string m_origMesg;
2756 const BOOL m_history; 2759 const BOOL m_history;
2757}; 2760};
2758 2761
@@ -2770,9 +2773,9 @@ void add_floater_chat(const LLChat &chat, const BOOL history)
2770 } 2773 }
2771} 2774}
2772 2775
2773void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL history) 2776void check_translate_chat(const std::string &mesg, const LLChat &chat, const BOOL history)
2774{ 2777{
2775 const bool translate = LLUI::sConfigGroup->getBOOL("TranslateChat"); 2778 const bool translate = gSavedSettings.getBOOL("TranslateChat");
2776 2779
2777 if (translate && chat.mSourceType != CHAT_SOURCE_SYSTEM) 2780 if (translate && chat.mSourceType != CHAT_SOURCE_SYSTEM)
2778 { 2781 {
@@ -2780,9 +2783,8 @@ void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL hist
2780 // SVC-4879 2783 // SVC-4879
2781 const std::string &fromLang = ""; 2784 const std::string &fromLang = "";
2782 const std::string &toLang = LLTranslate::getTranslateLanguage(); 2785 const std::string &toLang = LLTranslate::getTranslateLanguage();
2783 LLChat *newChat = new LLChat(chat);
2784 2786
2785 LLHTTPClient::ResponderPtr result = ChatTranslationReceiver::build(fromLang, toLang, newChat, history); 2787 LLHTTPClient::ResponderPtr result = ChatTranslationReceiver::build(fromLang, toLang, chat, mesg, history);
2786 LLTranslate::translateMessage(result, fromLang, toLang, mesg); 2788 LLTranslate::translateMessage(result, fromLang, toLang, mesg);
2787 } 2789 }
2788 else 2790 else
@@ -2961,8 +2963,9 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
2961 std::string prefix = mesg.substr(0, 4); 2963 std::string prefix = mesg.substr(0, 4);
2962 if (prefix == "/me " || prefix == "/me'") 2964 if (prefix == "/me " || prefix == "/me'")
2963 { 2965 {
2964 chat.mText = from_name; 2966 const std::string spacer = mesg.substr(3,1);
2965 chat.mText += mesg.substr(3); 2967 mesg = mesg.substr(4);
2968 chat.mText = from_name + spacer + mesg;
2966 ircstyle = TRUE; 2969 ircstyle = TRUE;
2967 } 2970 }
2968 else 2971 else
diff --git a/linden/indra/newview/llviewermessage.h b/linden/indra/newview/llviewermessage.h
index 1a6c03b..11a3554 100644
--- a/linden/indra/newview/llviewermessage.h
+++ b/linden/indra/newview/llviewermessage.h
@@ -76,7 +76,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data);
76void process_chat_from_simulator(LLMessageSystem *mesgsys, void **user_data); 76void process_chat_from_simulator(LLMessageSystem *mesgsys, void **user_data);
77 77
78void add_floater_chat(const LLChat &chat, const BOOL history); 78void add_floater_chat(const LLChat &chat, const BOOL history);
79void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL history); 79void check_translate_chat(const std::string &mesg, const LLChat &chat, const BOOL history);
80 80
81//void process_agent_to_new_region(LLMessageSystem *mesgsys, void **user_data); 81//void process_agent_to_new_region(LLMessageSystem *mesgsys, void **user_data);
82void send_agent_update(BOOL force_send, BOOL send_reliable = FALSE); 82void send_agent_update(BOOL force_send, BOOL send_reliable = FALSE);
diff --git a/linden/indra/newview/skins/default/xui/en-us/panel_login.xml b/linden/indra/newview/skins/default/xui/en-us/panel_login.xml
index dda5e4d..96f3f77 100644
--- a/linden/indra/newview/skins/default/xui/en-us/panel_login.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/panel_login.xml
@@ -58,7 +58,8 @@
58 bevel_style="in" border_style="line" border_thickness="1" 58 bevel_style="in" border_style="line" border_thickness="1"
59 max_length="31" mouse_opaque="true" 59 max_length="31" mouse_opaque="true"
60 handle_edit_keys_directly="true" 60 handle_edit_keys_directly="true"
61 select_all_on_focus_received="true" /> 61 select_all_on_focus_received="true"
62 allow_translate="false" />
62 63
63 64
64 <!-- LAST NAME --> 65 <!-- LAST NAME -->
@@ -77,7 +78,8 @@
77 bevel_style="in" border_style="line" border_thickness="1" 78 bevel_style="in" border_style="line" border_thickness="1"
78 max_length="31" mouse_opaque="true" 79 max_length="31" mouse_opaque="true"
79 handle_edit_keys_directly="true" 80 handle_edit_keys_directly="true"
80 select_all_on_focus_received="true" /> 81 select_all_on_focus_received="true"
82 allow_translate="false" />
81 83
82 84
83 <!-- PASSWORD --> 85 <!-- PASSWORD -->
@@ -96,7 +98,8 @@
96 bevel_style="in" border_style="line" border_thickness="1" 98 bevel_style="in" border_style="line" border_thickness="1"
97 max_length="16" mouse_opaque="true" 99 max_length="16" mouse_opaque="true"
98 handle_edit_keys_directly="true" 100 handle_edit_keys_directly="true"
99 select_all_on_focus_received="true" /> 101 select_all_on_focus_received="true"
102 allow_translate="false" />
100 <check_box name="remember_check" label="Remember password" 103 <check_box name="remember_check" label="Remember password"
101 bottom_delta="-24" left_delta="0" height="16" width="140" 104 bottom_delta="-24" left_delta="0" height="16" width="140"
102 follows="left|bottom" font="SansSerifSmall" control_name="RememberPassword" 105 follows="left|bottom" font="SansSerifSmall" control_name="RememberPassword"