зеркало из https://github.com/mozilla/pjs.git
context menu for spellchecking (bug 151040)
This commit is contained in:
Родитель
1c83d1cfc8
Коммит
20f3c55d3b
|
@ -21,7 +21,7 @@
|
||||||
<key>336</key>
|
<key>336</key>
|
||||||
<string>159 679 226 206 0 0 1600 1002 </string>
|
<string>159 679 226 206 0 0 1600 1002 </string>
|
||||||
<key>365</key>
|
<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>
|
<key>463</key>
|
||||||
<string>348 489 213 275 0 0 1600 1002 </string>
|
<string>348 489 213 275 0 0 1600 1002 </string>
|
||||||
<key>56</key>
|
<key>56</key>
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
<string>1074 492 188 64 0 0 1920 1178 </string>
|
<string>1074 492 188 64 0 0 1920 1178 </string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>IBFramework Version</key>
|
<key>IBFramework Version</key>
|
||||||
<string>443.0</string>
|
<string>446.1</string>
|
||||||
<key>IBLockedObjects</key>
|
<key>IBLockedObjects</key>
|
||||||
<array>
|
<array>
|
||||||
<integer>748</integer>
|
<integer>748</integer>
|
||||||
|
@ -40,6 +40,6 @@
|
||||||
<integer>889</integer>
|
<integer>889</integer>
|
||||||
</array>
|
</array>
|
||||||
<key>IBSystem Version</key>
|
<key>IBSystem Version</key>
|
||||||
<string>8G32</string>
|
<string>8I1119</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</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 "nsNetUtil.h"
|
||||||
#include "nsIPref.h"
|
#include "nsIPref.h"
|
||||||
#include "nsISupportsArray.h"
|
#include "nsISupportsArray.h"
|
||||||
|
#include "nsIDOMNSEditableElement.h"
|
||||||
|
|
||||||
#include "nsIClipboardCommands.h"
|
#include "nsIClipboardCommands.h"
|
||||||
#include "nsICommandManager.h"
|
#include "nsICommandManager.h"
|
||||||
|
@ -112,6 +113,13 @@
|
||||||
#include "nsIFocusController.h"
|
#include "nsIFocusController.h"
|
||||||
#include "nsIX509Cert.h"
|
#include "nsIX509Cert.h"
|
||||||
|
|
||||||
|
// for spellchecking
|
||||||
|
#include "nsIEditor.h"
|
||||||
|
#include "nsIInlineSpellChecker.h"
|
||||||
|
#include "nsIEditorSpellCheck.h"
|
||||||
|
#include "nsISelection.h"
|
||||||
|
#include "nsIDOMRange.h"
|
||||||
|
|
||||||
#include "nsAppDirectoryServiceDefs.h"
|
#include "nsAppDirectoryServiceDefs.h"
|
||||||
|
|
||||||
static NSString* const BrowserToolbarIdentifier = @"Browser Window Toolbar Combined";
|
static NSString* const BrowserToolbarIdentifier = @"Browser Window Toolbar Combined";
|
||||||
|
@ -466,6 +474,8 @@ enum BWCOpenDest {
|
||||||
- (IBAction)backMenu:(id)inSender;
|
- (IBAction)backMenu:(id)inSender;
|
||||||
- (IBAction)forwardMenu:(id)inSender;
|
- (IBAction)forwardMenu:(id)inSender;
|
||||||
|
|
||||||
|
- (BOOL)prepareSpellingSuggestionMenu:(NSMenu*)inMenu tag:(int)inTag;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
@ -2603,6 +2613,24 @@ enum BWCOpenDest {
|
||||||
#undef ENSURE_TRUE
|
#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
|
// -isPageTextFieldFocused
|
||||||
//
|
//
|
||||||
|
@ -3337,6 +3365,7 @@ enum BWCOpenDest {
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
BOOL showFrameItems = NO;
|
BOOL showFrameItems = NO;
|
||||||
|
BOOL showSpellingItems = NO;
|
||||||
|
|
||||||
NSMenu* menuPrototype = nil;
|
NSMenu* menuPrototype = nil;
|
||||||
int contextMenuFlags = mDataOwner->mContextMenuFlags;
|
int contextMenuFlags = mDataOwner->mContextMenuFlags;
|
||||||
|
@ -3345,7 +3374,7 @@ enum BWCOpenDest {
|
||||||
unsigned numEmailAddresses = 0;
|
unsigned numEmailAddresses = 0;
|
||||||
|
|
||||||
BOOL hasSelection = [[mBrowserView getBrowserView] canCopy];
|
BOOL hasSelection = [[mBrowserView getBrowserView] canCopy];
|
||||||
|
|
||||||
if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_LINK) != 0)
|
if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_LINK) != 0)
|
||||||
{
|
{
|
||||||
emailAddresses = [self mailAddressesInContextMenuLinkNode];
|
emailAddresses = [self mailAddressesInContextMenuLinkNode];
|
||||||
|
@ -3368,6 +3397,7 @@ enum BWCOpenDest {
|
||||||
else if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_INPUT) != 0 ||
|
else if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_INPUT) != 0 ||
|
||||||
(contextMenuFlags & nsIContextMenuListener::CONTEXT_TEXT) != 0) {
|
(contextMenuFlags & nsIContextMenuListener::CONTEXT_TEXT) != 0) {
|
||||||
menuPrototype = mInputMenu;
|
menuPrototype = mInputMenu;
|
||||||
|
showSpellingItems = YES;
|
||||||
}
|
}
|
||||||
else if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_IMAGE) != 0) {
|
else if ((contextMenuFlags & nsIContextMenuListener::CONTEXT_IMAGE) != 0) {
|
||||||
menuPrototype = mImageMenu;
|
menuPrototype = mImageMenu;
|
||||||
|
@ -3402,7 +3432,18 @@ enum BWCOpenDest {
|
||||||
const int kFrameRelatedItemsTag = 100;
|
const int kFrameRelatedItemsTag = 100;
|
||||||
const int kFrameInapplicableItemsTag = 101;
|
const int kFrameInapplicableItemsTag = 101;
|
||||||
const int kSelectionRelatedItemsTag = 102;
|
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.
|
// 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.
|
// We need a search item to know what the user's preferred search is.
|
||||||
if (!hasSelection) {
|
if (!hasSelection) {
|
||||||
|
@ -3437,7 +3478,112 @@ enum BWCOpenDest {
|
||||||
return result;
|
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
|
// 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
|
- (IBAction)openLinkInNewWindow:(id)aSender
|
||||||
{
|
{
|
||||||
[self openLinkInNewWindowOrTab: YES];
|
[self openLinkInNewWindowOrTab: YES];
|
||||||
|
|
|
@ -52,6 +52,9 @@
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
|
#include "nsIEditor.h"
|
||||||
|
#include "nsISelection.h"
|
||||||
|
|
||||||
#include "nsIDocShell.h"
|
#include "nsIDocShell.h"
|
||||||
#include "nsIDocShellTreeItem.h"
|
#include "nsIDocShellTreeItem.h"
|
||||||
|
|
||||||
|
@ -242,4 +245,23 @@ void GeckoUtils::FindDocShellForURI (nsIURI *aURI, nsIDocShell *aRoot, nsIDocShe
|
||||||
}
|
}
|
||||||
|
|
||||||
// We never found the docshell.
|
// 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 nsIDOMElement;
|
||||||
class nsIDocShell;
|
class nsIDocShell;
|
||||||
class nsIURI;
|
class nsIURI;
|
||||||
|
class nsIEditor;
|
||||||
|
|
||||||
class GeckoUtils
|
class GeckoUtils
|
||||||
{
|
{
|
||||||
|
@ -55,6 +56,9 @@ class GeckoUtils
|
||||||
/* Ouputs the docshell |aDocShell|'s URI as a nsACString. */
|
/* Ouputs the docshell |aDocShell|'s URI as a nsACString. */
|
||||||
static void GetURIForDocShell(nsIDocShell* aDocShell, nsACString& aURI);
|
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 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
|
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!
|
found somewhere in a document's docshell tree. NOTE: Addrefs the found docshell!
|
||||||
|
|
Загрузка…
Ссылка в новой задаче