diff --git a/browser/base/content/test/test_contextmenu.html b/browser/base/content/test/test_contextmenu.html index a7df45d18058..4c3757c4ad6b 100644 --- a/browser/base/content/test/test_contextmenu.html +++ b/browser/base/content/test/test_contextmenu.html @@ -589,6 +589,7 @@ iframe = subwindow.document.getElementById("test-iframe"); textarea = subwindow.document.getElementById("test-textarea"); contenteditable = subwindow.document.getElementById("test-contenteditable"); + contenteditable.focus(); // content editable needs to be focused to enable spellcheck inputspell = subwindow.document.getElementById("test-input-spellcheck"); pagemenu = subwindow.document.getElementById("test-pagemenu"); diff --git a/content/base/public/nsIContent.h b/content/base/public/nsIContent.h index a10134ac5630..9af67aba2097 100644 --- a/content/base/public/nsIContent.h +++ b/content/base/public/nsIContent.h @@ -944,6 +944,31 @@ class nsIContent : public nsINode { */ nsIContent* GetEditingHost(); + /** + * Determing language. Look at the nearest ancestor element that has a lang + * attribute in the XML namespace or is an HTML element and has a lang in + * no namespace attribute. + */ + void GetLang(nsAString& aResult) const { + for (const nsIContent* content = this; content; content = content->GetParent()) { + if (content->GetAttrCount() > 0) { + // xml:lang has precedence over lang on HTML elements (see + // XHTML1 section C.7). + PRBool hasAttr = content->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang, + aResult); + if (!hasAttr && content->IsHTML()) { + hasAttr = content->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, + aResult); + } + NS_ASSERTION(hasAttr || aResult.IsEmpty(), + "GetAttr that returns false should not make string non-empty"); + if (hasAttr) { + return; + } + } + } + } + // Overloaded from nsINode virtual already_AddRefed GetBaseURI() const; diff --git a/editor/composer/src/nsEditorSpellCheck.cpp b/editor/composer/src/nsEditorSpellCheck.cpp index 90a1b11f4ab0..9310f4b99132 100644 --- a/editor/composer/src/nsEditorSpellCheck.cpp +++ b/editor/composer/src/nsEditorSpellCheck.cpp @@ -42,11 +42,15 @@ #include "nsEditorSpellCheck.h" +#include "nsStyleUtil.h" +#include "nsIContent.h" +#include "nsIDOMElement.h" #include "nsITextServicesDocument.h" #include "nsISpellChecker.h" #include "nsISelection.h" #include "nsIDOMRange.h" #include "nsIEditor.h" +#include "nsIHTMLEditor.h" #include "nsIComponentManager.h" #include "nsServiceManagerUtils.h" @@ -54,6 +58,7 @@ #include "nsString.h" #include "nsReadableUtils.h" #include "nsITextServicesFilter.h" +#include "nsUnicharUtils.h" #include "mozilla/Services.h" #include "mozilla/Preferences.h" @@ -183,61 +188,9 @@ nsEditorSpellCheck::InitSpellChecker(nsIEditor* aEditor, PRBool aEnableSelection rv = mSpellChecker->SetDocument(tsDoc, PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); - // Tell the spellchecker what dictionary to use: - - nsAdoptingString dictName = - Preferences::GetLocalizedString("spellchecker.dictionary"); - - if (dictName.IsEmpty()) - { - // Prefs didn't give us a dictionary name, so just get the current - // locale and use that as the default dictionary name! - - nsCOMPtr packageRegistry = - mozilla::services::GetXULChromeRegistryService(); - - if (packageRegistry) { - nsCAutoString utf8DictName; - rv = packageRegistry->GetSelectedLocale(NS_LITERAL_CSTRING("global"), - utf8DictName); - AppendUTF8toUTF16(utf8DictName, dictName); - } - } - - PRBool setDictionary = PR_FALSE; - if (NS_SUCCEEDED(rv) && !dictName.IsEmpty()) { - rv = SetCurrentDictionary(dictName.get()); - - // fall back to "en-US" if the current locale doesn't have a dictionary. - if (NS_FAILED(rv)) { - rv = SetCurrentDictionary(NS_LITERAL_STRING("en-US").get()); - } - - if (NS_SUCCEEDED(rv)) - setDictionary = PR_TRUE; - } - - // If there was no dictionary specified by spellchecker.dictionary and setting it to the - // locale dictionary didn't work, try to use the first dictionary we find. This helps when - // the first dictionary is installed - if (! setDictionary) { - nsTArray dictList; - rv = mSpellChecker->GetDictionaryList(&dictList); - NS_ENSURE_SUCCESS(rv, rv); - if (dictList.Length() > 0) { - rv = SetCurrentDictionary(dictList[0].get()); - if (NS_SUCCEEDED(rv)) - SaveDefaultDictionary(); - } - } - - // If an error was thrown while checking the dictionary pref, just - // fail silently so that the spellchecker dialog is allowed to come - // up. The user can manually reset the language to their choice on - // the dialog if it is wrong. - - DeleteSuggestedWordList(); - + // do not fail if UpdateCurrentDictionary fails because this method may + // succeed later. + UpdateCurrentDictionary(aEditor); return NS_OK; } @@ -439,14 +392,6 @@ nsEditorSpellCheck::UninitSpellChecker() { NS_ENSURE_TRUE(mSpellChecker, NS_ERROR_NOT_INITIALIZED); - // we preserve the last selected language, but ignore errors so we continue - // to uninitialize -#ifdef DEBUG - nsresult rv = -#endif - SaveDefaultDictionary(); - NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to set default dictionary"); - // Cleanup - kill the spell checker DeleteSuggestedWordList(); mDictionaryList.Clear(); @@ -489,3 +434,124 @@ nsEditorSpellCheck::DeleteSuggestedWordList() mSuggestedWordIndex = 0; return NS_OK; } + +NS_IMETHODIMP +nsEditorSpellCheck::UpdateCurrentDictionary(nsIEditor* aEditor) +{ + nsresult rv; + + // Tell the spellchecker what dictionary to use: + nsAutoString dictName; + + // First, try to get language with html5 algorithm + nsAutoString editorLang; + + nsCOMPtr rootContent; + + nsCOMPtr htmlEditor = do_QueryInterface(aEditor); + if (htmlEditor) { + rootContent = htmlEditor->GetActiveEditingHost(); + } else { + nsCOMPtr rootElement; + rv = aEditor->GetRootElement(getter_AddRefs(rootElement)); + NS_ENSURE_SUCCESS(rv, rv); + rootContent = do_QueryInterface(rootElement); + } + NS_ENSURE_TRUE(rootContent, NS_ERROR_FAILURE); + + rootContent->GetLang(editorLang); + + if (editorLang.IsEmpty()) { + nsCOMPtr doc = rootContent->GetCurrentDoc(); + NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); + doc->GetContentLanguage(editorLang); + } + + if (!editorLang.IsEmpty()) { + dictName.Assign(editorLang); + } + + // otherwise, get language from preferences + if (dictName.IsEmpty()) { + dictName.Assign(Preferences::GetLocalizedString("spellchecker.dictionary")); + } + + if (dictName.IsEmpty()) + { + // Prefs didn't give us a dictionary name, so just get the current + // locale and use that as the default dictionary name! + + nsCOMPtr packageRegistry = + mozilla::services::GetXULChromeRegistryService(); + + if (packageRegistry) { + nsCAutoString utf8DictName; + rv = packageRegistry->GetSelectedLocale(NS_LITERAL_CSTRING("global"), + utf8DictName); + AppendUTF8toUTF16(utf8DictName, dictName); + } + } + + SetCurrentDictionary(NS_LITERAL_STRING("").get()); + + if (NS_SUCCEEDED(rv) && !dictName.IsEmpty()) { + rv = SetCurrentDictionary(dictName.get()); + if (NS_FAILED(rv)) { + // required dictionary was not available. Try to get a dictionary + // matching at least language part of dictName: If required dictionary is + // "aa-bb", we try "aa", then we try any available dictionary aa-XX + nsAutoString langCode; + PRInt32 dashIdx = dictName.FindChar('-'); + if (dashIdx != -1) { + langCode.Assign(Substring(dictName, 0, dashIdx)); + // try to use langCode + rv = SetCurrentDictionary(langCode.get()); + } else { + langCode.Assign(dictName); + } + if (NS_FAILED(rv)) { + // loop over avaible dictionaries; if we find one with required + // language, use it + nsTArray dictList; + rv = mSpellChecker->GetDictionaryList(&dictList); + NS_ENSURE_SUCCESS(rv, rv); + nsDefaultStringComparator comparator; + PRInt32 i, count = dictList.Length(); + for (i = 0; i < count; i++) { + nsAutoString dictStr(dictList.ElementAt(i)); + if (nsStyleUtil::DashMatchCompare(dictStr, langCode, comparator) && + NS_SUCCEEDED(SetCurrentDictionary(dictStr.get()))) { + break; + } + } + } + } + } + + // If we have not set dictionary, and the editable element doesn't have a + // lang attribute, we try to get a dictionary. First try, en-US. If it does + // not work, pick the first one. + if (editorLang.IsEmpty()) { + nsAutoString currentDictonary; + rv = mSpellChecker->GetCurrentDictionary(currentDictonary); + if (NS_FAILED(rv) || currentDictonary.IsEmpty()) { + rv = SetCurrentDictionary(NS_LITERAL_STRING("en-US").get()); + if (NS_FAILED(rv)) { + nsTArray dictList; + rv = mSpellChecker->GetDictionaryList(&dictList); + if (NS_SUCCEEDED(rv) && dictList.Length() > 0) { + SetCurrentDictionary(dictList[0].get()); + } + } + } + } + + // If an error was thrown while setting the dictionary, just + // fail silently so that the spellchecker dialog is allowed to come + // up. The user can manually reset the language to their choice on + // the dialog if it is wrong. + + DeleteSuggestedWordList(); + + return NS_OK; +} diff --git a/editor/idl/nsIEditorSpellCheck.idl b/editor/idl/nsIEditorSpellCheck.idl index 02da2b10d29e..0370b1c3cb3c 100644 --- a/editor/idl/nsIEditorSpellCheck.idl +++ b/editor/idl/nsIEditorSpellCheck.idl @@ -41,7 +41,7 @@ interface nsIEditor; interface nsITextServicesFilter; -[scriptable, uuid(90c93610-c116-44ab-9793-62dccb9f43ce)] +[scriptable, uuid(803ff0dd-07f2-4438-b3a6-ab9c2fe4e1dd)] interface nsIEditorSpellCheck : nsISupports { @@ -188,4 +188,10 @@ interface nsIEditorSpellCheck : nsISupports */ boolean CheckCurrentWordNoSuggest(in wstring suggestedWord); + /** + * Update the dictionary in use to be sure it corresponds to what the editor + * needs. + */ + void UpdateCurrentDictionary(in nsIEditor editor); + }; diff --git a/editor/idl/nsIHTMLEditor.idl b/editor/idl/nsIHTMLEditor.idl index a9ba99250b2f..f43529dc3839 100644 --- a/editor/idl/nsIHTMLEditor.idl +++ b/editor/idl/nsIHTMLEditor.idl @@ -42,6 +42,7 @@ #include "domstubs.idl" interface nsIAtom; +interface nsIContent; interface nsISupportsArray; interface nsISelection; interface nsIContentFilter; @@ -51,7 +52,7 @@ interface nsIContentFilter; NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_EDITOR, 1) %} -[scriptable, uuid(c964b8b0-e9e8-11df-9492-0800200c9a66)] +[scriptable, uuid(d58f35a7-c269-4292-b9aa-a79e200a7c99)] interface nsIHTMLEditor : nsISupports { @@ -613,5 +614,11 @@ interface nsIHTMLEditor : nsISupports * Checks whether a BR node is visible to the user. */ boolean breakIsVisible(in nsIDOMNode aNode); + + /** + * Get an active editor's editing host in DOM window. If this editor isn't + * active in the DOM window, this returns NULL. + */ + [noscript, notxpcom] nsIContent GetActiveEditingHost(); }; diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index a59214afc372..ef7c89f94f03 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -5311,3 +5311,12 @@ nsEditor::BeginKeypressHandling(nsIDOMNSEvent* aEvent) mLastKeypressEventWasTrusted = isTrusted ? eTriTrue : eTriFalse; } } + +void +nsEditor::OnFocus(nsIDOMEventTarget* aFocusEventTarget) +{ + InitializeSelection(aFocusEventTarget); + if (mInlineSpellChecker) { + mInlineSpellChecker->UpdateCurrentDictionary(); + } +} diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index cfcb88dfe2e4..1ef527abf67f 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -719,6 +719,11 @@ class nsEditor : public nsIEditor, // nothing. nsresult InitializeSelection(nsIDOMEventTarget* aFocusEventTarget); + // This method has to be called by nsEditorEventListener::Focus. + // All actions that have to be done when the editor is focused needs to be + // added here. + void OnFocus(nsIDOMEventTarget* aFocusEventTarget); + protected: PRUint32 mModCount; // number of modifications (for undo/redo stack) diff --git a/editor/libeditor/base/nsEditorEventListener.cpp b/editor/libeditor/base/nsEditorEventListener.cpp index d9dfc2462381..b17d3145c1b2 100644 --- a/editor/libeditor/base/nsEditorEventListener.cpp +++ b/editor/libeditor/base/nsEditorEventListener.cpp @@ -818,7 +818,7 @@ nsEditorEventListener::Focus(nsIDOMEvent* aEvent) } } - mEditor->InitializeSelection(target); + mEditor->OnFocus(target); return NS_OK; } diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index efd7a641798d..d209bc1b5dcb 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -458,9 +458,6 @@ class nsHTMLEditor : public nsPlaintextEditor, // @return If the editor has focus, this returns the focused node. // Otherwise, returns null. already_AddRefed GetFocusedNode(); - // Get an active editor's editing host in DOM window. If this editor isn't - // active in the DOM window, this returns NULL. - nsIContent* GetActiveEditingHost(); // Return TRUE if aElement is a table-related elemet and caret was set PRBool SetCaretInTableCell(nsIDOMElement* aElement); diff --git a/editor/libeditor/html/tests/test_bug484181.html b/editor/libeditor/html/tests/test_bug484181.html index b5d8651c9368..62b40cc588a2 100644 --- a/editor/libeditor/html/tests/test_bug484181.html +++ b/editor/libeditor/html/tests/test_bug484181.html @@ -46,7 +46,6 @@ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var edit = document.getElementById("edit"); - edit.focus(); var editor = getEditor(); var sel = editor.selection; sel.selectAllChildren(edit); @@ -59,16 +58,19 @@ function runTest() { gMisspeltWords = ["haz", "cheezburger"]; - is(isSpellingCheckOk(), true, "All misspellings before editing are accounted for."); - var edit = document.getElementById("edit"); - append(" becaz I'm a lolcat!"); + edit.focus(); SimpleTest.executeSoon(function() { - gMisspeltWords.push("becaz"); - gMisspeltWords.push("lolcat"); - is(isSpellingCheckOk(), true, "All misspellings after typing are accounted for."); + is(isSpellingCheckOk(), true, "All misspellings before editing are accounted for."); + + append(" becaz I'm a lolcat!"); + SimpleTest.executeSoon(function() { + gMisspeltWords.push("becaz"); + gMisspeltWords.push("lolcat"); + is(isSpellingCheckOk(), true, "All misspellings after typing are accounted for."); - SimpleTest.finish(); + SimpleTest.finish(); + }); }); } diff --git a/editor/txtsvc/public/nsIInlineSpellChecker.idl b/editor/txtsvc/public/nsIInlineSpellChecker.idl index 32735e8290b3..b34f6f57d54c 100644 --- a/editor/txtsvc/public/nsIInlineSpellChecker.idl +++ b/editor/txtsvc/public/nsIInlineSpellChecker.idl @@ -43,7 +43,7 @@ interface nsISelection; interface nsIEditor; interface nsIEditorSpellCheck; -[scriptable, uuid(07be036a-2355-4a92-b150-5c9b7e9fdf2f)] +[scriptable, uuid(f456dda1-965d-470c-8c55-e51b38e45212)] interface nsIInlineSpellChecker : nsISupports { @@ -71,6 +71,7 @@ interface nsIInlineSpellChecker : nsISupports void ignoreWord(in AString aWord); void ignoreWords([array, size_is(aCount)] in wstring aWordsToIgnore, in unsigned long aCount); + void updateCurrentDictionary(); }; %{C++ diff --git a/editor/txtsvc/public/nsISpellChecker.h b/editor/txtsvc/public/nsISpellChecker.h index 66765e9f26be..d1644df77fea 100644 --- a/editor/txtsvc/public/nsISpellChecker.h +++ b/editor/txtsvc/public/nsISpellChecker.h @@ -142,7 +142,8 @@ class nsISpellChecker : public nsISupports{ /** * Tells the spellchecker to use a specific dictionary. * @param aDictionary a string that is in the list returned - * by GetDictionaryList(). + * by GetDictionaryList() or an empty string. If aDictionary is + * empty string, spellchecker will be disabled. */ NS_IMETHOD SetCurrentDictionary(const nsAString &aDictionary) = 0; }; diff --git a/extensions/spellcheck/src/mozInlineSpellChecker.cpp b/extensions/spellcheck/src/mozInlineSpellChecker.cpp index 1aa11eecd689..21c9340b0aca 100644 --- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp +++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp @@ -1384,6 +1384,9 @@ nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil, PRBool isMisspelled; aWordUtil.NormalizeWord(wordText); rv = mSpellCheck->CheckCurrentWordNoSuggest(wordText.get(), &isMisspelled); + if (NS_FAILED(rv)) + continue; + if (isMisspelled) { // misspelled words count extra toward the max wordsSinceTimeCheck += MISSPELLED_WORD_COUNT_PENALTY; @@ -1441,6 +1444,23 @@ mozInlineSpellChecker::ResumeCheck(mozInlineSpellStatus* aStatus) nsCOMPtr spellCheckSelection; rv = GetSpellCheckSelection(getter_AddRefs(spellCheckSelection)); NS_ENSURE_SUCCESS(rv, rv); + + PRUnichar *currentDictionary = nsnull; + rv = mSpellCheck->GetCurrentDictionary(¤tDictionary); + if (NS_FAILED(rv)) { + // no active dictionary + PRInt32 count; + spellCheckSelection->GetRangeCount(&count); + for (PRInt32 index = count - 1; index >= 0; index--) { + nsCOMPtr checkRange; + spellCheckSelection->GetRangeAt(index, getter_AddRefs(checkRange)); + if (checkRange) { + RemoveRange(spellCheckSelection, checkRange); + } + } + return NS_OK; + } + CleanupRangesInSelection(spellCheckSelection); rv = aStatus->FinishInitOnEvent(wordUtil); @@ -1733,3 +1753,38 @@ nsresult mozInlineSpellChecker::KeyPress(nsIDOMEvent* aKeyEvent) return NS_OK; } + +NS_IMETHODIMP mozInlineSpellChecker::UpdateCurrentDictionary() +{ + if (!mSpellCheck) { + return NS_OK; + } + + PRUnichar *previousDictionary = nsnull; + nsDependentString previousDictionaryStr; + if (NS_SUCCEEDED(mSpellCheck->GetCurrentDictionary(&previousDictionary))) { + previousDictionaryStr.Assign(previousDictionary); + } + + nsCOMPtr editor (do_QueryReferent(mEditor)); + nsresult rv = mSpellCheck->UpdateCurrentDictionary(editor); + + PRUnichar *currentDictionary = nsnull; + nsDependentString currentDictionaryStr; + if (NS_SUCCEEDED(mSpellCheck->GetCurrentDictionary(¤tDictionary))) { + currentDictionaryStr.Assign(currentDictionary); + } + + if (!previousDictionary || !currentDictionary || !previousDictionaryStr.Equals(currentDictionaryStr)) { + rv = SpellCheckRange(nsnull); + } + + if (previousDictionary) { + nsMemory::Free(previousDictionary); + } + if (currentDictionary) { + nsMemory::Free(currentDictionary); + } + + return rv; +} diff --git a/extensions/spellcheck/src/mozSpellChecker.cpp b/extensions/spellcheck/src/mozSpellChecker.cpp index ee79054c5956..3ada4c029b57 100644 --- a/extensions/spellcheck/src/mozSpellChecker.cpp +++ b/extensions/spellcheck/src/mozSpellChecker.cpp @@ -369,6 +369,12 @@ mozSpellChecker::SetCurrentDictionary(const nsAString &aDictionary) nsresult rv; nsCString *contractId; + if (aDictionary.IsEmpty()) { + mCurrentEngineContractId = nsnull; + mSpellCheckingEngine = nsnull; + return NS_OK; + } + if (!mDictionariesMap.Get(aDictionary, &contractId)){ NS_WARNING("Dictionary not found"); return NS_ERROR_NOT_AVAILABLE; diff --git a/layout/reftests/editor/338427-1-ref.html b/layout/reftests/editor/338427-1-ref.html new file mode 100644 index 000000000000..d645ad9fb18d --- /dev/null +++ b/layout/reftests/editor/338427-1-ref.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/layout/reftests/editor/338427-1.html b/layout/reftests/editor/338427-1.html new file mode 100644 index 000000000000..17b6c391d694 --- /dev/null +++ b/layout/reftests/editor/338427-1.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/layout/reftests/editor/338427-2-ref.html b/layout/reftests/editor/338427-2-ref.html new file mode 100644 index 000000000000..e13b9114c3ce --- /dev/null +++ b/layout/reftests/editor/338427-2-ref.html @@ -0,0 +1,18 @@ + + + + +
strangeimpossibleword
+ + + diff --git a/layout/reftests/editor/338427-2.html b/layout/reftests/editor/338427-2.html new file mode 100644 index 000000000000..af5d3506e236 --- /dev/null +++ b/layout/reftests/editor/338427-2.html @@ -0,0 +1,17 @@ + + + + +
strangeimpossibleword
+ + diff --git a/layout/reftests/editor/338427-3-ref.html b/layout/reftests/editor/338427-3-ref.html new file mode 100644 index 000000000000..e8949f3851df --- /dev/null +++ b/layout/reftests/editor/338427-3-ref.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/layout/reftests/editor/338427-3.html b/layout/reftests/editor/338427-3.html new file mode 100644 index 000000000000..7066ba662f34 --- /dev/null +++ b/layout/reftests/editor/338427-3.html @@ -0,0 +1,18 @@ + + + + + + + diff --git a/layout/reftests/editor/reftest.list b/layout/reftests/editor/reftest.list index d2bc3698710b..9e37ed5d507b 100644 --- a/layout/reftests/editor/reftest.list +++ b/layout/reftests/editor/reftest.list @@ -64,3 +64,6 @@ fails-if(Android) != spellcheck-hyphen-multiple-invalid.html spellcheck-hyphen-m != selection_visibility_after_reframe-2.html selection_visibility_after_reframe-ref.html != selection_visibility_after_reframe-3.html selection_visibility_after_reframe-ref.html == 672709.html 672709-ref.html +== 338427-1.html 338427-1-ref.html +skip-if(Android) == 338427-2.html 338427-2-ref.html +skip-if(Android) == 338427-3.html 338427-3-ref.html diff --git a/layout/reftests/unicode/langattribute-ref.html b/layout/reftests/unicode/langattribute-ref.html new file mode 100644 index 000000000000..d3908825a681 --- /dev/null +++ b/layout/reftests/unicode/langattribute-ref.html @@ -0,0 +1,26 @@ + + + + testing lang attribute + + + +
fr language
+
+ +
+
+ dk language +
+ + diff --git a/layout/reftests/unicode/langattribute.html b/layout/reftests/unicode/langattribute.html new file mode 100644 index 000000000000..9630eb86ade2 --- /dev/null +++ b/layout/reftests/unicode/langattribute.html @@ -0,0 +1,26 @@ + + + + testing lang attribute + + + +
fr language
+
+ +
+
+ dk language +
+ + diff --git a/layout/reftests/unicode/reftest.list b/layout/reftests/unicode/reftest.list index c3b950dd111f..45a98b1c85d3 100644 --- a/layout/reftests/unicode/reftest.list +++ b/layout/reftests/unicode/reftest.list @@ -4,3 +4,4 @@ == unicode-media-query-media-type.html unicode-ref-print.html == unicode-media-query-query.html unicode-ref-print.html == unicode-pseudo-selector.html unicode-ref.html +== langattribute.html langattribute-ref.html diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index af501b3306ce..b808d9751e33 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -1195,29 +1195,6 @@ nsCSSRuleProcessor::GetWindowsThemeIdentifier() } #endif -// If we have a useful @lang, then aLang will end up nonempty. -static void GetLang(nsIContent* aContent, nsString& aLang) -{ - for (nsIContent* content = aContent; content; - content = content->GetParent()) { - if (content->GetAttrCount() > 0) { - // xml:lang has precedence over lang on HTML elements (see - // XHTML1 section C.7). - PRBool hasAttr = content->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang, - aLang); - if (!hasAttr && content->IsHTML()) { - hasAttr = content->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, - aLang); - } - NS_ASSERTION(hasAttr || aLang.IsEmpty(), - "GetAttr that returns false should not make string non-empty"); - if (hasAttr) { - return; - } - } - } -} - /* static */ nsEventStates nsCSSRuleProcessor::GetContentState(Element* aElement) @@ -1697,7 +1674,7 @@ static PRBool SelectorMatches(Element* aElement, // from the parent we have to be prepared to look at all parent // nodes. The language itself is encoded in the LANG attribute. nsAutoString language; - GetLang(aElement, language); + aElement->GetLang(language); if (!language.IsEmpty()) { if (!nsStyleUtil::DashMatchCompare(language, nsDependentString(pseudoClass->u.mString), diff --git a/toolkit/content/InlineSpellChecker.jsm b/toolkit/content/InlineSpellChecker.jsm index e4b0939e5889..010fbf400dbf 100644 --- a/toolkit/content/InlineSpellChecker.jsm +++ b/toolkit/content/InlineSpellChecker.jsm @@ -131,8 +131,12 @@ InlineSpellChecker.prototype = { return 0; // nothing to do var spellchecker = this.mInlineSpellChecker.spellChecker; - if (! spellchecker.CheckCurrentWord(this.mMisspelling)) - return 0; // word seems not misspelled after all (?) + try { + if (! spellchecker.CheckCurrentWord(this.mMisspelling)) + return 0; // word seems not misspelled after all (?) + } catch(e) { + return 0; + } this.mMenu = menu; this.mSpellSuggestions = []; @@ -192,7 +196,10 @@ InlineSpellChecker.prototype = { spellchecker.GetDictionaryList(o1, o2); var list = o1.value; var listcount = o2.value; - var curlang = spellchecker.GetCurrentDictionary(); + var curlang = ""; + try { + curlang = spellchecker.GetCurrentDictionary(); + } catch(e) {} var isoStrArray; for (var i = 0; i < list.length; i ++) {