mshtml: Added handling of right and left arrow keys in editing mode.

This commit is contained in:
Jacek Caban 2006-11-30 23:32:05 +01:00 committed by Alexandre Julliard
parent 93c909a3ad
commit bc71685676
4 changed files with 316 additions and 2 deletions

View File

@ -36,6 +36,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
#define DOM_VK_LEFT VK_LEFT
#define DOM_VK_UP VK_UP
#define DOM_VK_RIGHT VK_RIGHT
#define DOM_VK_DOWN VK_DOWN
static const WCHAR wszFont[] = {'f','o','n','t',0};
static const WCHAR wszSize[] = {'s','i','z','e',0};
@ -231,3 +236,202 @@ void set_font_size(HTMLDocument *This, LPCWSTR size)
nsISelection_Release(nsselection);
nsIDOMDocument_Release(nsdoc);
}
static BOOL is_visible_text_node(nsIDOMNode *node)
{
nsIDOMCharacterData *char_data;
nsAString data_str;
LPCWSTR data, ptr;
PRUint32 len;
nsIDOMNode_QueryInterface(node, &IID_nsIDOMCharacterData, (void**)&char_data);
nsIDOMCharacterData_GetLength(char_data, &len);
nsAString_Init(&data_str, NULL);
nsIDOMCharacterData_GetData(char_data, &data_str);
nsAString_GetData(&data_str, &data, NULL);
if(*data == '\n') {
len--;
for(ptr=data+1; ptr && isspaceW(*ptr); ptr++)
len--;
}
nsAString_Finish(&data_str);
nsIDOMCharacterData_Release(char_data);
return len != 0;
}
static nsIDOMNode *get_child_text_node(nsIDOMNode *node, BOOL first)
{
nsIDOMNode *iter, *iter2;
if(first)
nsIDOMNode_GetFirstChild(node, &iter);
else
nsIDOMNode_GetLastChild(node, &iter);
while(iter) {
PRUint16 node_type;
nsIDOMNode_GetNodeType(iter, &node_type);
switch(node_type) {
case TEXT_NODE:
if(is_visible_text_node(iter))
return iter;
case ELEMENT_NODE:
iter2 = get_child_text_node(iter, first);
if(iter2) {
nsIDOMNode_Release(iter);
return iter2;
}
}
if(first)
nsIDOMNode_GetNextSibling(iter, &iter2);
else
nsIDOMNode_GetPreviousSibling(iter, &iter2);
nsIDOMNode_Release(iter);
iter = iter2;
}
return NULL;
}
static nsIDOMNode *get_next_text_node(nsIDOMNode *node, BOOL next)
{
nsIDOMNode *iter, *iter2 = NULL, *parent = NULL;
PRUint16 node_type;
iter = node;
nsIDOMNode_AddRef(iter);
while(1) {
if(next)
nsIDOMNode_GetNextSibling(iter, &iter2);
else
nsIDOMNode_GetPreviousSibling(iter, &iter2);
while(!iter2) {
nsIDOMNode_GetParentNode(iter, &parent);
nsIDOMNode_Release(iter);
if(!parent)
return NULL;
iter = parent;
if(next)
nsIDOMNode_GetNextSibling(iter, &iter2);
else
nsIDOMNode_GetPreviousSibling(iter, &iter2);
}
nsIDOMNode_Release(iter);
iter = iter2;
nsIDOMNode_GetNodeType(iter, &node_type);
switch(node_type) {
case TEXT_NODE:
if(is_visible_text_node(iter))
return iter;
case ELEMENT_NODE:
iter2 = get_child_text_node(iter, next);
if(iter2) {
nsIDOMNode_Release(iter);
return iter2;
}
}
}
return NULL;
}
static void collapse_end_node(nsISelection *selection, nsIDOMNode *node)
{
nsIDOMCharacterData *char_data;
PRUint32 len;
nsIDOMNode_QueryInterface(node, &IID_nsIDOMCharacterData, (void**)&char_data);
nsIDOMCharacterData_GetLength(char_data, &len);
nsIDOMCharacterData_Release(char_data);
nsISelection_Collapse(selection, node, len);
}
static void collapse_next_char(HTMLDocument *doc, nsIDOMKeyEvent *event, BOOL next)
{
nsISelection *selection = get_ns_selection(doc);
nsIDOMNode *node;
PRBool collapsed, b;
PRUint16 node_type;
nsIDOMNode *text_node;
nsIDOMKeyEvent_GetCtrlKey(event, &b);
if(b) return;
nsIDOMKeyEvent_GetShiftKey(event, &b);
if(b) return;
nsISelection_GetIsCollapsed(selection, &collapsed);
if(!collapsed)
nsISelection_CollapseToEnd(selection);
nsISelection_GetFocusNode(selection, &node);
nsIDOMNode_GetNodeType(node, &node_type);
if(node_type == TEXT_NODE) {
nsIDOMCharacterData *char_data;
PRInt32 offset;
PRUint32 len;
nsISelection_GetFocusOffset(selection, &offset);
nsIDOMNode_QueryInterface(node, &IID_nsIDOMCharacterData, (void**)&char_data);
nsIDOMCharacterData_GetLength(char_data, &len);
nsIDOMCharacterData_Release(char_data);
if(next ? offset != len : offset) {
nsISelection_Collapse(selection, node, offset + (next?1:-1));
return;
}
}
text_node = get_next_text_node(node, next);
if(text_node) {
if(next)
nsISelection_Collapse(selection, text_node, 1);
else
collapse_end_node(selection, text_node);
nsIDOMNode_Release(text_node);
}
nsIDOMNode_Release(node);
nsISelection_Release(selection);
}
void handle_edit_event(HTMLDocument *This, nsIDOMEvent *event)
{
nsIDOMKeyEvent *key_event;
PRUint32 code;
nsIDOMEvent_QueryInterface(event, &IID_nsIDOMKeyEvent, (void**)&key_event);
nsIDOMKeyEvent_GetKeyCode(key_event, &code);
switch(code) {
case DOM_VK_LEFT:
TRACE("left");
collapse_next_char(This, key_event, FALSE);
break;
case DOM_VK_RIGHT:
TRACE("right\n");
collapse_next_char(This, key_event, TRUE);
};
nsIDOMKeyEvent_Release(key_event);
}

View File

@ -117,6 +117,7 @@ struct NSContainer {
const nsIInterfaceRequestorVtbl *lpInterfaceRequestorVtbl;
const nsIWeakReferenceVtbl *lpWeakReferenceVtbl;
const nsISupportsWeakReferenceVtbl *lpSupportsWeakReferenceVtbl;
const nsIDOMEventListenerVtbl *lpDOMEventListenerVtbl;
nsIWebBrowser *webbrowser;
nsIWebNavigation *navigation;
@ -253,6 +254,7 @@ typedef struct {
#define NSEMBWNDS(x) ((nsIEmbeddingSiteWindow*) &(x)->lpEmbeddingSiteWindowVtbl)
#define NSIFACEREQ(x) ((nsIInterfaceRequestor*) &(x)->lpInterfaceRequestorVtbl)
#define NSTOOLTIP(x) ((nsITooltipListener*) &(x)->lpTooltipListenerVtbl)
#define NSEVENTLIST(x) ((nsIDOMEventListener*) &(x)->lpDOMEventListenerVtbl)
#define NSWEAKREF(x) ((nsIWeakReference*) &(x)->lpWeakReferenceVtbl)
#define NSSUPWEAKREF(x) ((nsISupportsWeakReference*) &(x)->lpSupportsWeakReferenceVtbl)
@ -351,6 +353,8 @@ void release_nodes(HTMLDocument*);
void install_wine_gecko(void);
/* editor */
void handle_edit_event(HTMLDocument*,nsIDOMEvent*);
void get_font_size(HTMLDocument*,WCHAR*);
void set_font_size(HTMLDocument*,LPCWSTR);

View File

@ -640,6 +640,9 @@ static nsresult NSAPI nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome *ifa
}else if(IsEqualGUID(&IID_nsITooltipListener, riid)) {
TRACE("(%p)->(IID_nsITooltipListener %p)\n", This, result);
*result = NSTOOLTIP(This);
}else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
*result = NSEVENTLIST(This);
}else if(IsEqualGUID(&IID_nsIInterfaceRequestor, riid)) {
TRACE("(%p)->(IID_nsIInterfaceRequestor %p)\n", This, result);
*result = NSIFACEREQ(This);
@ -1227,6 +1230,48 @@ static const nsITooltipListenerVtbl nsTooltipListenerVtbl = {
nsTooltipListener_OnHideTooltip
};
#define NSEVENTLIST_THIS(iface) DEFINE_THIS(NSContainer, DOMEventListener, iface)
static nsresult NSAPI nsDOMEventListener_QueryInterface(nsIDOMEventListener *iface,
nsIIDRef riid, nsQIResult result)
{
NSContainer *This = NSEVENTLIST_THIS(iface);
return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
}
static nsrefcnt NSAPI nsDOMEventListener_AddRef(nsIDOMEventListener *iface)
{
NSContainer *This = NSEVENTLIST_THIS(iface);
return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
}
static nsrefcnt NSAPI nsDOMEventListener_Release(nsIDOMEventListener *iface)
{
NSContainer *This = NSEVENTLIST_THIS(iface);
return nsIWebBrowserChrome_Release(NSWBCHROME(This));
}
static nsresult NSAPI nsDOMEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *event)
{
NSContainer *This = NSEVENTLIST_THIS(iface);
TRACE("(%p)->(%p)\n", This, event);
if(This->doc->usermode == EDITMODE)
handle_edit_event(This->doc, event);
return NS_OK;
}
#undef NSEVENTLIST_THIS
static const nsIDOMEventListenerVtbl nsDOMEventListenerVtbl = {
nsDOMEventListener_QueryInterface,
nsDOMEventListener_AddRef,
nsDOMEventListener_Release,
nsDOMEventListener_HandleEvent
};
#define NSIFACEREQ_THIS(iface) DEFINE_THIS(NSContainer, InterfaceRequestor, iface)
static nsresult NSAPI nsInterfaceRequestor_QueryInterface(nsIInterfaceRequestor *iface,
@ -1352,6 +1397,7 @@ const nsISupportsWeakReferenceVtbl nsSupportsWeakReferenceVtbl = {
NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent)
{
nsIDOMWindow *dom_window;
nsIWebBrowserSetup *wbsetup;
NSContainer *ret;
nsresult nsres;
@ -1369,7 +1415,7 @@ NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent)
ret->lpInterfaceRequestorVtbl = &nsInterfaceRequestorVtbl;
ret->lpWeakReferenceVtbl = &nsWeakReferenceVtbl;
ret->lpSupportsWeakReferenceVtbl = &nsSupportsWeakReferenceVtbl;
ret->lpDOMEventListenerVtbl = &nsDOMEventListenerVtbl;
ret->doc = doc;
ret->ref = 1;
@ -1438,6 +1484,28 @@ NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent)
if(NS_FAILED(nsres))
ERR("SetParentURIContentListener failed: %08x\n", nsres);
nsres = nsIWebBrowser_GetContentDOMWindow(ret->webbrowser, &dom_window);
if(NS_SUCCEEDED(nsres)) {
nsIDOMEventTarget *target;
nsres = nsIDOMWindow_QueryInterface(dom_window, &IID_nsIDOMEventTarget, (void**)&target);
nsIDOMWindow_Release(dom_window);
if(NS_SUCCEEDED(nsres)) {
nsAString keypress_str;
static const PRUnichar wsz_keypress[] = {'k','e','y','p','r','e','s','s',0};
nsAString_Init(&keypress_str, wsz_keypress);
nsres = nsIDOMEventTarget_AddEventListener(target, &keypress_str, NSEVENTLIST(ret), TRUE);
nsAString_Finish(&keypress_str);
nsIDOMEventTarget_Release(target);
if(NS_FAILED(nsres))
ERR("AddEventTarget failed: %08x\n", nsres);
}else {
ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres);
}
}else {
ERR("GetContentDOMWindow failed: %08x\n", nsres);
}
return ret;
}

View File

@ -67,6 +67,7 @@ interface nsIWebBrowserChrome;
interface nsILoadGroup;
interface nsIDOMNode;
interface nsIDOMDocument;
interface nsIDOMEvent;
interface IMoniker;
@ -86,7 +87,6 @@ typedef nsISupports nsISHistory;
typedef nsISupports nsISimpleEnumerator;
typedef nsISupports nsIWidget;
typedef nsISupports nsIProtocolHandler;
typedef nsISupports nsIDOMEventTarget;
typedef nsISupports nsIDOMAbstractView;
typedef nsISupports nsIHttpHeaderVisitor;
typedef nsISupports nsIDOMBarProp;
@ -1045,6 +1045,26 @@ interface nsIWebBrowserChrome : nsISupports
nsresult ExitModalEventLoop(nsresult aStatus);
}
[
object,
uuid(df31c120-ded6-11d1-bd85-00805f8ae3f4)
]
interface nsIDOMEventListener : nsISupports
{
nsresult HandleEvent(nsIDOMEvent *event);
}
[
object,
uuid(1c773b30-d1cf-11d2-bd95-00805f8ae3f4)
]
interface nsIDOMEventTarget : nsISupports
{
nsresult AddEventListener(const nsAString *type, nsIDOMEventListener *listener, PRBool useCapture);
nsresult RemoveEventListener(const nsAString *type, nsIDOMEventListener *listener, PRBool useCapture);
nsresult DispatchEvent(nsIDOMEvent *evt, PRBool *_retval);
}
[
object,
uuid(a66b7b80-ff46-bd97-0080-5f8ae38add32)
@ -1115,6 +1135,24 @@ interface nsIDOMMouseEvent : nsIDOMUIEvent
nsIDOMEventTarget *relatedTargetArg);
}
[
object,
uuid(028e0e6e-8b01-11d3-aae7-0010838a3123)
]
interface nsIDOMKeyEvent : nsIDOMUIEvent
{
nsresult GetCharCode(PRUint32 *aCharCode);
nsresult GetKeyCode(PRUint32 *aKeyCode);
nsresult GetAltKey(PRBool *aAltKey);
nsresult GetCtrlKey(PRBool *aCtrlKey);
nsresult GetShiftKey(PRBool *aShiftKey);
nsresult GetMetaKey(PRBool *aMetaKey);
nsresult InitKeyEvent(const nsAString *typeArg, PRBool canBubbleArg,
PRBool cancelableArg, nsIDOMAbstractView *viewArg, PRBool ctrlKeyArg,
PRBool altKeyArg, PRBool shiftKeyArg, PRBool metaKeyArg, PRUint32 keyCodeArg,
PRUint32 charCodeArg);
}
[
object,
uuid(3e5432cd-9568-4bd1-8cbe-d50aba110743)