From f9c4d0325b40965e542550be9e61cd2527d69bb7 Mon Sep 17 00:00:00 2001 From: "pinkerton%aol.net" Date: Fri, 30 Jun 2006 22:06:23 +0000 Subject: [PATCH] context menu for spellchecking (bug 151040) --- .../English.lproj/BrowserWindow.nib/info.nib | 6 +- .../BrowserWindow.nib/keyedobjects.nib | Bin 32181 -> 32271 bytes camino/src/browser/BrowserWindowController.mm | 148 +++++++++++++++++- camino/src/extensions/GeckoUtils.cpp | 24 ++- camino/src/extensions/GeckoUtils.h | 4 + 5 files changed, 177 insertions(+), 5 deletions(-) diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib index 6e429d440428..ee4a18bbd2f9 100644 --- a/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib +++ b/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib @@ -21,7 +21,7 @@ 336 159 679 226 206 0 0 1600 1002 365 - 149 856 98 168 0 0 1920 1178 + 110 602 98 168 0 0 1440 878 463 348 489 213 275 0 0 1600 1002 56 @@ -32,7 +32,7 @@ 1074 492 188 64 0 0 1920 1178 IBFramework Version - 443.0 + 446.1 IBLockedObjects 748 @@ -40,6 +40,6 @@ 889 IBSystem Version - 8G32 + 8I1119 diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/keyedobjects.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/keyedobjects.nib index c1ac718b82edc752ea98ea58d37035c379b490a7..882c3ab7bb1e2110def383d96d9adac126466422 100644 GIT binary patch delta 19173 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 delta 19096 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 diff --git a/camino/src/browser/BrowserWindowController.mm b/camino/src/browser/BrowserWindowController.mm index 6a342323cd3f..0c9c34a6c7af 100644 --- a/camino/src/browser/BrowserWindowController.mm +++ b/camino/src/browser/BrowserWindowController.mm @@ -91,6 +91,7 @@ #include "nsNetUtil.h" #include "nsIPref.h" #include "nsISupportsArray.h" +#include "nsIDOMNSEditableElement.h" #include "nsIClipboardCommands.h" #include "nsICommandManager.h" @@ -112,6 +113,13 @@ #include "nsIFocusController.h" #include "nsIX509Cert.h" +// for spellchecking +#include "nsIEditor.h" +#include "nsIInlineSpellChecker.h" +#include "nsIEditorSpellCheck.h" +#include "nsISelection.h" +#include "nsIDOMRange.h" + #include "nsAppDirectoryServiceDefs.h" static NSString* const BrowserToolbarIdentifier = @"Browser Window Toolbar Combined"; @@ -466,6 +474,8 @@ enum BWCOpenDest { - (IBAction)backMenu:(id)inSender; - (IBAction)forwardMenu:(id)inSender; +- (BOOL)prepareSpellingSuggestionMenu:(NSMenu*)inMenu tag:(int)inTag; + @end #pragma mark - @@ -2603,6 +2613,24 @@ enum BWCOpenDest { #undef ENSURE_TRUE } +// +// -currentEditor: +// +// Returns the nsIEditor of the currently focused text area or input +// +- (void)currentEditor:(nsIEditor**)outEditor +{ + if (!outEditor) + return; + *outEditor = nsnull; + + nsCOMPtr focusedElement; + [self focusedElement:getter_AddRefs(focusedElement)]; + nsCOMPtr editElement = do_QueryInterface(focusedElement); + if (editElement) + editElement->GetEditor(outEditor); +} + // // -isPageTextFieldFocused // @@ -3337,6 +3365,7 @@ enum BWCOpenDest { return nil; BOOL showFrameItems = NO; + BOOL showSpellingItems = NO; NSMenu* menuPrototype = nil; int contextMenuFlags = mDataOwner->mContextMenuFlags; @@ -3345,7 +3374,7 @@ enum BWCOpenDest { unsigned numEmailAddresses = 0; BOOL hasSelection = [[mBrowserView getBrowserView] canCopy]; - + if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_LINK) != 0) { emailAddresses = [self mailAddressesInContextMenuLinkNode]; @@ -3368,6 +3397,7 @@ enum BWCOpenDest { else if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_INPUT) != 0 || (contextMenuFlags & nsIContextMenuListener::CONTEXT_TEXT) != 0) { menuPrototype = mInputMenu; + showSpellingItems = YES; } else if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_IMAGE) != 0) { menuPrototype = mImageMenu; @@ -3402,7 +3432,18 @@ enum BWCOpenDest { const int kFrameRelatedItemsTag = 100; const int kFrameInapplicableItemsTag = 101; const int kSelectionRelatedItemsTag = 102; + const int kSpellingRelatedItemsTag = 103; + if (showSpellingItems) + showSpellingItems = [self prepareSpellingSuggestionMenu:result tag:kSpellingRelatedItemsTag]; + + if (!showSpellingItems) { + // word spelled correctly or not applicable, remove all traces of spelling items + NSMenuItem* selectionItem; + while ((selectionItem = [result itemWithTag:kSpellingRelatedItemsTag]) != nil) + [result removeItem:selectionItem]; + } + // if there's no selection or no search bar in the toolbar, hide the search item. // We need a search item to know what the user's preferred search is. if (!hasSelection) { @@ -3437,7 +3478,112 @@ enum BWCOpenDest { return result; } +// +// -prepareSpellingSuggestionMenu:tag: +// +// Adds suggestions to the top of |inMenu| for the currently mispelled word +// under the insertion point. Starts inserting before the first item in the menu +// with |inTag| and will insert up to |kMaxSuggestions|. +// +- (BOOL)prepareSpellingSuggestionMenu:(NSMenu*)inMenu tag:(int)inTag +{ + #define ENSURE_TRUE(x) if (!x) return NO; + BOOL showSuggestions = YES; + + nsCOMPtr editor; + [self currentEditor:getter_AddRefs(editor)]; + ENSURE_TRUE(editor); + + nsCOMPtr inlineChecker; + editor->GetInlineSpellChecker(PR_TRUE, getter_AddRefs(inlineChecker)); + ENSURE_TRUE(inlineChecker); + + // verify inline spellchecking is "on" before we continue + PRBool enabled = NO; + inlineChecker->GetEnableRealTimeSpell(&enabled); + if (!enabled) + return NO; + + nsCOMPtr spellCheck; + inlineChecker->GetSpellChecker(getter_AddRefs(spellCheck)); + ENSURE_TRUE(spellCheck); + + // if there is a mispelled word, ask the spellchecker to check it, which seems redundant + // but is also used to generate the suggestions list. + PRBool isIncorrect = NO; + nsCOMPtr anchorNode; + PRInt32 anchorOffset = 0; + GeckoUtils::GetAnchorNodeFromSelection(editor, getter_AddRefs(anchorNode), &anchorOffset); + nsCOMPtr mispelledRange; + inlineChecker->GetMispelledWord(anchorNode, (long)anchorOffset, getter_AddRefs(mispelledRange)); + if (mispelledRange) { + nsString currentWord; + mispelledRange->ToString(currentWord); + spellCheck->CheckCurrentWord(currentWord.get(), &isIncorrect); + } + if (isIncorrect) { + // there's still a mispelled word, loop over the suggestions. The spellchecker will return + // an empty string when it's done (NOT nil), so keep going until we get that or our + // max. + const unsigned long insertBase = [inMenu indexOfItemWithTag:inTag]; + const unsigned long kMaxSuggestions = 7; + unsigned long numSuggestions = 0; + do { + PRUnichar* suggestion = nil; + spellCheck->GetSuggestedWord(&suggestion); + if (!nsCRT::strlen(suggestion)) + break; + + NSString* suggStr = [NSString stringWithPRUnichars:suggestion]; + NSMenuItem* item = [inMenu insertItemWithTitle:suggStr action:@selector(replaceMispelledWord:) keyEquivalent:@"" atIndex:numSuggestions + insertBase]; + [item setTarget:self]; + + ++numSuggestions; + nsCRT::free(suggestion); + } while (numSuggestions < kMaxSuggestions); + } + else + showSuggestions = NO; + + return showSuggestions; + #undef ENSURE_TRUE +} + // Context menu methods + +// +// -replaceMispelledWord: +// +// Context menu action for the suggestions in a text field. Replaces the +// current word in the editor with string that's the title of the chosen menu +// item. +// +- (IBAction)replaceMispelledWord:(id)inSender +{ + #define ENSURE_TRUE(x) if (!x) return; + + // it's unfortunate that we have to re-fetch this stuff since we just did it + // when buliding the context menu, but we don't really have any convenient place + // to stash it where we can guarantee it will get cleaned up when the menu goes + // away. + nsCOMPtr editor; + [self currentEditor:getter_AddRefs(editor)]; + ENSURE_TRUE(editor); + + nsCOMPtr inlineChecker; + editor->GetInlineSpellChecker(PR_TRUE, getter_AddRefs(inlineChecker)); + ENSURE_TRUE(inlineChecker); + nsCOMPtr anchorNode; + PRInt32 anchorOffset = 0; + GeckoUtils::GetAnchorNodeFromSelection(editor, getter_AddRefs(anchorNode), &anchorOffset); + + nsString newWord; + [[inSender title] assignTo_nsAString:newWord]; + inlineChecker->ReplaceWord(anchorNode, anchorOffset, newWord); + + #undef ENSURE_TRUE +} + - (IBAction)openLinkInNewWindow:(id)aSender { [self openLinkInNewWindowOrTab: YES]; diff --git a/camino/src/extensions/GeckoUtils.cpp b/camino/src/extensions/GeckoUtils.cpp index dacf44866bf3..c7a2fcffb844 100644 --- a/camino/src/extensions/GeckoUtils.cpp +++ b/camino/src/extensions/GeckoUtils.cpp @@ -52,6 +52,9 @@ #include "nsString.h" #include "nsCOMPtr.h" +#include "nsIEditor.h" +#include "nsISelection.h" + #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" @@ -242,4 +245,23 @@ void GeckoUtils::FindDocShellForURI (nsIURI *aURI, nsIDocShell *aRoot, nsIDocShe } // We never found the docshell. -} \ No newline at end of file +} + +// +// GetAnchorNodeFromSelection +// +// Finds the anchor node for the selection in the given editor +// +void GeckoUtils::GetAnchorNodeFromSelection(nsIEditor* inEditor, nsIDOMNode** outAnchorNode, PRInt32* outOffset) +{ + if (!inEditor || !outAnchorNode) + return; + *outAnchorNode = nsnull; + + nsCOMPtr selection; + inEditor->GetSelection(getter_AddRefs(selection)); + if (!selection) + return; + selection->GetAnchorOffset(outOffset); + selection->GetAnchorNode(outAnchorNode); +} diff --git a/camino/src/extensions/GeckoUtils.h b/camino/src/extensions/GeckoUtils.h index 1d8f68648bcc..80759da51c6b 100644 --- a/camino/src/extensions/GeckoUtils.h +++ b/camino/src/extensions/GeckoUtils.h @@ -44,6 +44,7 @@ class nsIDOMNode; class nsIDOMElement; class nsIDocShell; class nsIURI; +class nsIEditor; class GeckoUtils { @@ -55,6 +56,9 @@ class GeckoUtils /* Ouputs the docshell |aDocShell|'s URI as a nsACString. */ static void GetURIForDocShell(nsIDocShell* aDocShell, nsACString& aURI); + // Finds the anchor node for the selection in the given editor + static void GetAnchorNodeFromSelection(nsIEditor* inEditor, nsIDOMNode** outAnchorNode, PRInt32* outAnchorOffset); + /* Given a URI, and a docshell node, will traverse the tree looking for the docshell with the given URI. This is used for example when unblocking popups, because the popup "windows" are docshells found somewhere in a document's docshell tree. NOTE: Addrefs the found docshell!