mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 338427 - Spellchecker should respect the langi attribute; r=ehsan
This commit is contained in:
parent
6c668d27a8
commit
56a37f401e
@ -589,6 +589,7 @@ function startTest() {
|
||||
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");
|
||||
|
||||
|
@ -944,6 +944,31 @@ public:
|
||||
*/
|
||||
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<nsIURI> GetBaseURI() const;
|
||||
|
||||
|
@ -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<nsIXULChromeRegistry> 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<nsString> 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<nsIContent> rootContent;
|
||||
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(aEditor);
|
||||
if (htmlEditor) {
|
||||
rootContent = htmlEditor->GetActiveEditingHost();
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMElement> 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<nsIDocument> 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<nsIXULChromeRegistry> 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<nsString> 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<nsString> 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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
};
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -5311,3 +5311,12 @@ nsEditor::BeginKeypressHandling(nsIDOMNSEvent* aEvent)
|
||||
mLastKeypressEventWasTrusted = isTrusted ? eTriTrue : eTriFalse;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::OnFocus(nsIDOMEventTarget* aFocusEventTarget)
|
||||
{
|
||||
InitializeSelection(aFocusEventTarget);
|
||||
if (mInlineSpellChecker) {
|
||||
mInlineSpellChecker->UpdateCurrentDictionary();
|
||||
}
|
||||
}
|
||||
|
@ -719,6 +719,11 @@ public:
|
||||
// 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)
|
||||
|
@ -818,7 +818,7 @@ nsEditorEventListener::Focus(nsIDOMEvent* aEvent)
|
||||
}
|
||||
}
|
||||
|
||||
mEditor->InitializeSelection(target);
|
||||
mEditor->OnFocus(target);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -458,9 +458,6 @@ protected:
|
||||
// @return If the editor has focus, this returns the focused node.
|
||||
// Otherwise, returns null.
|
||||
already_AddRefed<nsINode> 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);
|
||||
|
@ -46,7 +46,6 @@ function append(str) {
|
||||
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 append(str) {
|
||||
|
||||
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.");
|
||||
|
||||
SimpleTest.finish();
|
||||
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();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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++
|
||||
|
@ -142,7 +142,8 @@ public:
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
@ -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<nsISelection> 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<nsIDOMRange> 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<nsIEditor> 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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
7
layout/reftests/editor/338427-1-ref.html
Normal file
7
layout/reftests/editor/338427-1-ref.html
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<textarea spellcheck="false" lang="testing-XX">strangeimpossibleword</textarea>
|
||||
</body>
|
||||
</html>
|
||||
|
6
layout/reftests/editor/338427-1.html
Normal file
6
layout/reftests/editor/338427-1.html
Normal file
@ -0,0 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<textarea lang="testing-XX">strangeimpossibleword</textarea>
|
||||
</body>
|
||||
</html>
|
18
layout/reftests/editor/338427-2-ref.html
Normal file
18
layout/reftests/editor/338427-2-ref.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script>
|
||||
function init() {
|
||||
var editor = document.getElementById('editor');
|
||||
editor.addEventListener("focus", function() {
|
||||
window.setTimeout(function() {
|
||||
document.documentElement.className = '';
|
||||
}, 0);
|
||||
}, false);
|
||||
editor.focus();
|
||||
}
|
||||
</script>
|
||||
<body onload="init()">
|
||||
<div id="editor" lang="testing-XX" contenteditable="true" spellcheck="false">strangeimpossibleword</div>
|
||||
</body>
|
||||
</html>
|
||||
|
17
layout/reftests/editor/338427-2.html
Normal file
17
layout/reftests/editor/338427-2.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script>
|
||||
function init() {
|
||||
var editor = document.getElementById('editor');
|
||||
editor.addEventListener("focus", function() {
|
||||
window.setTimeout(function() {
|
||||
document.documentElement.className = '';
|
||||
}, 0);
|
||||
}, false);
|
||||
editor.focus();
|
||||
}
|
||||
</script>
|
||||
<body onload="init()">
|
||||
<div id="editor" lang="testing-XX" contenteditable="true">strangeimpossibleword</div>
|
||||
</body>
|
||||
</html>
|
18
layout/reftests/editor/338427-3-ref.html
Normal file
18
layout/reftests/editor/338427-3-ref.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script>
|
||||
function init() {
|
||||
var editor = document.getElementById('editor');
|
||||
editor.setAttribute('lang', 'testing-XX');
|
||||
editor.addEventListener("focus", function() {
|
||||
window.setTimeout(function() {
|
||||
document.documentElement.className = '';
|
||||
}, 0);
|
||||
}, false);
|
||||
editor.focus();
|
||||
}
|
||||
</script>
|
||||
<body onload="init()">
|
||||
<textarea id="editor" spellcheck="false" lang="en-US">strangeimpossibleword</textarea>
|
||||
</body>
|
||||
</html>
|
18
layout/reftests/editor/338427-3.html
Normal file
18
layout/reftests/editor/338427-3.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script>
|
||||
function init() {
|
||||
var editor = document.getElementById('editor');
|
||||
editor.setAttribute('lang', 'testing-XX');
|
||||
editor.addEventListener("focus", function() {
|
||||
window.setTimeout(function() {
|
||||
document.documentElement.className = '';
|
||||
}, 0);
|
||||
}, false);
|
||||
editor.focus();
|
||||
}
|
||||
</script>
|
||||
<body onload="init()">
|
||||
<textarea id="editor" lang="en-US">strangeimpossibleword</textarea>
|
||||
</body>
|
||||
</html>
|
@ -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
|
||||
|
26
layout/reftests/unicode/langattribute-ref.html
Normal file
26
layout/reftests/unicode/langattribute-ref.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="dk">
|
||||
<head>
|
||||
<title>testing lang attribute</title>
|
||||
<style>
|
||||
div[lang="fr"] {
|
||||
color: green;
|
||||
}
|
||||
div[lang="de"] > input {
|
||||
color: blue;
|
||||
}
|
||||
div:not([lang]) {
|
||||
color: yellow;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div lang="fr">fr language</div>
|
||||
<div lang="de">
|
||||
<input value="de language">
|
||||
</div>
|
||||
<div>
|
||||
dk language
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
26
layout/reftests/unicode/langattribute.html
Normal file
26
layout/reftests/unicode/langattribute.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="dk">
|
||||
<head>
|
||||
<title>testing lang attribute</title>
|
||||
<style>
|
||||
div:lang(fr) {
|
||||
color: green;
|
||||
}
|
||||
input:lang(de) {
|
||||
color: blue;
|
||||
}
|
||||
div:lang(dk) {
|
||||
color: yellow;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div lang="fr">fr language</div>
|
||||
<div lang="de">
|
||||
<input value="de language">
|
||||
</div>
|
||||
<div>
|
||||
dk language
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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 ++) {
|
||||
|
Loading…
Reference in New Issue
Block a user