зеркало из https://github.com/mozilla/gecko-dev.git
context menu for spellchecking (bug 151040)
This commit is contained in:
Родитель
6db3916123
Коммит
f9c4d0325b
|
@ -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
сгенерированный
Двоичные данные
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!
|
||||
|
|
Загрузка…
Ссылка в новой задаче