context menu for spellchecking (bug 151040)

This commit is contained in:
pinkerton%aol.net 2006-06-30 22:06:23 +00:00
Родитель 1c83d1cfc8
Коммит 20f3c55d3b
5 изменённых файлов: 177 добавлений и 5 удалений

Просмотреть файл

@ -21,7 +21,7 @@
<key>336</key>
<string>159 679 226 206 0 0 1600 1002 </string>
<key>365</key>
<string>149 856 98 168 0 0 1920 1178 </string>
<string>110 602 98 168 0 0 1440 878 </string>
<key>463</key>
<string>348 489 213 275 0 0 1600 1002 </string>
<key>56</key>
@ -32,7 +32,7 @@
<string>1074 492 188 64 0 0 1920 1178 </string>
</dict>
<key>IBFramework Version</key>
<string>443.0</string>
<string>446.1</string>
<key>IBLockedObjects</key>
<array>
<integer>748</integer>
@ -40,6 +40,6 @@
<integer>889</integer>
</array>
<key>IBSystem Version</key>
<string>8G32</string>
<string>8I1119</string>
</dict>
</plist>

Двоичные данные
camino/resources/localized/English.lproj/BrowserWindow.nib/keyedobjects.nib сгенерированный

Двоичный файл не отображается.

Просмотреть файл

@ -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<nsIDOMElement> focusedElement;
[self focusedElement:getter_AddRefs(focusedElement)];
nsCOMPtr<nsIDOMNSEditableElement> 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<nsIEditor> editor;
[self currentEditor:getter_AddRefs(editor)];
ENSURE_TRUE(editor);
nsCOMPtr<nsIInlineSpellChecker> 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<nsIEditorSpellCheck> 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<nsIDOMNode> anchorNode;
PRInt32 anchorOffset = 0;
GeckoUtils::GetAnchorNodeFromSelection(editor, getter_AddRefs(anchorNode), &anchorOffset);
nsCOMPtr<nsIDOMRange> 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<nsIEditor> editor;
[self currentEditor:getter_AddRefs(editor)];
ENSURE_TRUE(editor);
nsCOMPtr<nsIInlineSpellChecker> inlineChecker;
editor->GetInlineSpellChecker(PR_TRUE, getter_AddRefs(inlineChecker));
ENSURE_TRUE(inlineChecker);
nsCOMPtr<nsIDOMNode> 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];

Просмотреть файл

@ -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.
}
}
//
// 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<nsISelection> selection;
inEditor->GetSelection(getter_AddRefs(selection));
if (!selection)
return;
selection->GetAnchorOffset(outOffset);
selection->GetAnchorNode(outAnchorNode);
}

Просмотреть файл

@ -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!