From 1fbedd92d453bb5547f03e307cfdd767fcd3f8f3 Mon Sep 17 00:00:00 2001 From: Rob Shearman Date: Wed, 12 Sep 2007 10:41:49 +0100 Subject: [PATCH] mshtml: Implement IDM_HYPERLINK. --- dlls/mshtml/En.rc | 14 +++ dlls/mshtml/editor.c | 216 ++++++++++++++++++++++++++++++++++++++++ dlls/mshtml/nsiface.idl | 66 ++++++++++++ dlls/mshtml/resource.h | 6 ++ 4 files changed, 302 insertions(+) diff --git a/dlls/mshtml/En.rc b/dlls/mshtml/En.rc index cf77ed7bc6d..556a6783f18 100644 --- a/dlls/mshtml/En.rc +++ b/dlls/mshtml/En.rc @@ -39,3 +39,17 @@ FONT 8, "MS Shell Dlg" DEFPUSHBUTTON "&Install", ID_DWL_INSTALL, 200, 60, 50, 15, WS_GROUP | WS_TABSTOP PUSHBUTTON "&Cancel", IDCANCEL, 140, 60, 50, 15, WS_GROUP | WS_TABSTOP } + +IDD_HYPERLINK DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 250, 65 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Hyperlink" +FONT 8, "MS Shell Dlg" +{ + GROUPBOX "Hyperlink Information", IDC_STATIC, 5, 5, 190, 55 + LTEXT "&Type:", IDC_STATIC, 10, 22, 20, 10 + COMBOBOX IDC_TYPE, 35, 20, 45, 100, WS_TABSTOP | WS_GROUP | WS_VSCROLL | CBS_DROPDOWNLIST | CBS_HASSTRINGS + LTEXT "&URL:", IDC_STATIC, 10, 42, 20, 10 + EDITTEXT IDC_URL, 35, 40, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP + PUSHBUTTON "OK", IDOK, 200, 10, 45, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP + PUSHBUTTON "Cancel", IDCANCEL, 200, 28, 45, 14, WS_GROUP | WS_TABSTOP +} diff --git a/dlls/mshtml/editor.c b/dlls/mshtml/editor.c index 6f202e03b12..fa2e75eaf6b 100644 --- a/dlls/mshtml/editor.c +++ b/dlls/mshtml/editor.c @@ -52,6 +52,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); #define NSCMD_FONTFACE "cmd_fontFace" #define NSCMD_INDENT "cmd_indent" #define NSCMD_INSERTHR "cmd_insertHR" +#define NSCMD_INSERTLINKNOUI "cmd_insertLinkNoUI" #define NSCMD_ITALIC "cmd_italic" #define NSCMD_LINENEXT "cmd_lineNext" #define NSCMD_LINEPREVIOUS "cmd_linePrevious" @@ -1120,11 +1121,225 @@ static HRESULT query_edit_status(HTMLDocument *This, OLECMD *cmd) TRACE("CGID_MSHTML: IDM_OUTDENT\n"); cmd->cmdf = query_ns_edit_status(This, NULL); break; + case IDM_HYPERLINK: + TRACE("CGID_MSHTML: IDM_HYPERLINK\n"); + cmd->cmdf = query_ns_edit_status(This, NULL); + break; } return S_OK; } +static INT_PTR CALLBACK hyperlink_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + static const WCHAR wszOther[] = {'(','o','t','h','e','r',')',0}; + + switch (msg) + { + case WM_INITDIALOG: + { + static const WCHAR wszFile[] = {'f','i','l','e',':',0}; + static const WCHAR wszFtp[] = {'f','t','p',':',0}; + static const WCHAR wszHttp[] = {'h','t','t','p',':',0}; + static const WCHAR wszHttps[] = {'h','t','t','p','s',':',0}; + static const WCHAR wszMailto[] = {'m','a','i','l','t','o',':',0}; + static const WCHAR wszNews[] = {'n','e','w','s',':',0}; + INT def_idx; + HWND hwndCB = GetDlgItem(hwnd, IDC_TYPE); + HWND hwndURL = GetDlgItem(hwnd, IDC_URL); + INT len; + + SetWindowLongPtrW(hwnd, DWLP_USER, lparam); + + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszOther); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszFile); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszFtp); + def_idx = SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszHttp); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszHttps); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszMailto); + SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszNews); + SendMessageW(hwndCB, CB_SETCURSEL, def_idx, 0); + + /* force the updating of the URL edit box */ + SendMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_TYPE, CBN_SELCHANGE), (LPARAM)hwndCB); + + SetFocus(hwndURL); + len = SendMessageW(hwndURL, WM_GETTEXTLENGTH, 0, 0); + SendMessageW(hwndURL, EM_SETSEL, 0, len); + + return FALSE; + } + case WM_COMMAND: + switch (wparam) + { + case MAKEWPARAM(IDCANCEL, BN_CLICKED): + EndDialog(hwnd, wparam); + return TRUE; + case MAKEWPARAM(IDOK, BN_CLICKED): + { + BSTR *url = (BSTR *)GetWindowLongPtrW(hwnd, DWLP_USER); + HWND hwndURL = GetDlgItem(hwnd, IDC_URL); + INT len = GetWindowTextLengthW(hwndURL); + *url = SysAllocStringLen(NULL, len + 1); + GetWindowTextW(hwndURL, *url, len + 1); + EndDialog(hwnd, wparam); + return TRUE; + } + case MAKEWPARAM(IDC_TYPE, CBN_SELCHANGE): + { + HWND hwndURL = GetDlgItem(hwnd, IDC_URL); + INT item; + INT len; + LPWSTR type; + LPWSTR url; + LPWSTR p; + static const WCHAR wszSlashSlash[] = {'/','/'}; + + /* get string of currently selected hyperlink type */ + item = SendMessageW((HWND)lparam, CB_GETCURSEL, 0, 0); + len = SendMessageW((HWND)lparam, CB_GETLBTEXTLEN, item, 0); + type = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + SendMessageW((HWND)lparam, CB_GETLBTEXT, item, (LPARAM)type); + + if (!strcmpW(type, wszOther)) + *type = '\0'; + + /* get current URL */ + len = GetWindowTextLengthW(hwndURL); + url = HeapAlloc(GetProcessHeap(), 0, (len + strlenW(type) + 3) * sizeof(WCHAR)); + GetWindowTextW(hwndURL, url, len + 1); + + /* strip off old protocol */ + p = strchrW(url, ':'); + if (p && p[1] == '/' && p[2] == '/') + p += 3; + if (!p) p = url; + memmove(url + (*type != '\0' ? strlenW(type) + 2 : 0), p, (len + 1 - (p - url)) * sizeof(WCHAR)); + + /* add new protocol */ + if (*type != '\0') + { + memcpy(url, type, strlenW(type) * sizeof(WCHAR)); + memcpy(url + strlenW(type), wszSlashSlash, sizeof(wszSlashSlash)); + } + + SetWindowTextW(hwndURL, url); + + HeapFree(GetProcessHeap(), 0, url); + HeapFree(GetProcessHeap(), 0, type); + return TRUE; + } + } + return FALSE; + case WM_CLOSE: + EndDialog(hwnd, IDCANCEL); + return TRUE; + default: + return FALSE; + } +} + +static HRESULT exec_hyperlink(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out) +{ + BSTR url = NULL; + INT ret; + nsAString ns_url; + PRBool insert_link_at_caret; + nsISelection *nsselection; + + FIXME("%p, 0x%x, %p, %p\n", This, cmdexecopt, in, out); + + if (cmdexecopt == OLECMDEXECOPT_DONTPROMPTUSER) + { + if (!in || V_VT(in) != VT_BSTR) + { + WARN("invalid arg\n"); + return E_INVALIDARG; + } + url = V_BSTR(in); + } + else + { + ret = DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_HYPERLINK), NULL /* FIXME */, hyperlink_dlgproc, (LPARAM)&url); + if (ret != IDOK) + return OLECMDERR_E_CANCELED; + } + + nsselection = get_ns_selection(This); + if (!nsselection) + return E_FAIL; + + nsAString_Init(&ns_url, url); + + nsISelection_GetIsCollapsed(nsselection, &insert_link_at_caret); + + if (insert_link_at_caret) + { + static const WCHAR wszA[] = {'a',0}; + static const WCHAR wszHref[] = {'h','r','e','f',0}; + nsIHTMLEditor *html_editor; + nsIDOMDocument *nsdoc; + nsIDOMNode *text_node; + nsIDOMElement *anchor_elem; + nsIDOMNode *unused_node; + nsAString a_str; + nsAString href_str; + nsresult nsres; + + nsres = nsIWebNavigation_GetDocument(This->nscontainer->navigation, &nsdoc); + if(NS_FAILED(nsres)) + return E_FAIL; + + nsAString_Init(&a_str, wszA); + nsAString_Init(&href_str, wszHref); + + /* create an element for the link */ + nsIDOMDocument_CreateElement(nsdoc, &a_str, &anchor_elem); + nsIDOMElement_SetAttribute(anchor_elem, &href_str, &ns_url); + + nsAString_Finish(&href_str); + nsAString_Finish(&a_str); + + /* create an element with text of URL */ + nsIDOMDocument_CreateTextNode(nsdoc, &ns_url, (nsIDOMText **)&text_node); + + /* wrap the tags around the text element */ + nsIDOMElement_AppendChild(anchor_elem, text_node, &unused_node); + nsIDOMNode_Release(text_node); + nsIDOMNode_Release(unused_node); + + nsIEditor_QueryInterface(This->nscontainer->editor, &IID_nsIHTMLEditor, (void **)&html_editor); + if (html_editor) + { + /* add them to the document at the caret position */ + nsres = nsIHTMLEditor_InsertElementAtSelection(html_editor, anchor_elem, FALSE); + nsIHTMLEditor_Release(html_editor); + } + + nsISelection_SelectAllChildren(nsselection, (nsIDOMNode*)anchor_elem); + + nsIDOMElement_Release(anchor_elem); + nsIDOMDocument_Release(nsdoc); + } + else + { + nsICommandParams *nsparam = create_nscommand_params(); + + nsICommandParams_SetStringValue(nsparam, NSSTATE_ATTRIBUTE, &ns_url); + do_ns_command(This->nscontainer, NSCMD_INSERTLINKNOUI, nsparam); + nsICommandParams_Release(nsparam); + } + + nsAString_Finish(&ns_url); + + nsISelection_Release(nsselection); + + if (cmdexecopt != OLECMDEXECOPT_DONTPROMPTUSER) + SysFreeString(url); + + return S_OK; +} + static HRESULT query_selall_status(HTMLDocument *This, OLECMD *cmd) { TRACE("(%p)->(%p)\n", This, cmd); @@ -1151,6 +1366,7 @@ const cmdtable_t editmode_cmds[] = { {IDM_INDENT, query_edit_status, exec_indent}, {IDM_OUTDENT, query_edit_status, exec_outdent}, {IDM_COMPOSESETTINGS, NULL, exec_composesettings}, + {IDM_HYPERLINK, query_edit_status, exec_hyperlink}, {0,NULL,NULL} }; diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 2a01c4bb973..4a3347d0f24 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -1976,6 +1976,72 @@ interface nsIEditor : nsISupports nsresult DebugUnitTests([out] PRInt32 *outNumTests, [out] PRInt32 *outNumTestsFailed); } +[ + object, + uuid(afc36593-5787-4420-93d9-b2c0ccbf0cad) +] +interface nsIHTMLEditor : nsISupports +{ + nsresult AddDefaultProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue); + nsresult RemoveDefaultProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue); + nsresult RemoveAllDefaultProperties(); + nsresult SetCSSInlineProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue); + nsresult SetInlineProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue); + nsresult GetInlineProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue, [out] PRBool *aFirst, [out] PRBool *aAny, [out] PRBool *aAll); + nsresult GetInlinePropertyWithAttrValue([in] nsIAtom *aProperty, [in] nsAString *aAttribute, [in] nsAString *aValue, [out] PRBool *aFirst, [out] PRBool *aAny, [out] PRBool *aAll, [out] nsAString *_retval); + nsresult RemoveAllInlineProperties(); + nsresult RemoveInlineProperty([in] nsIAtom *aProperty, [in] nsAString *aAttribute); + nsresult IncreaseFontSize(); + nsresult DecreaseFontSize(); + nsresult CanDrag([in] nsIDOMEvent *aEvent, [out] PRBool *_retval); + nsresult DoDrag([in] nsIDOMEvent *aEvent); + nsresult InsertFromDrop([in] nsIDOMEvent *aEvent); + nsresult NodeIsBlock([in] nsIDOMNode *node, PRBool *_retval); + nsresult InsertHTML([in] nsAString *aInputString); + nsresult PasteNoFormatting([in] PRInt32 aSelectionType); + nsresult RebuildDocumentFromSource([in] nsAString *aSourceString); + nsresult InsertHTMLWithContext([in] nsAString *aInputString, [in] nsAString *aContextStr, [in] nsAString *aInfoStr, [in] nsAString *aFlavor, [in] nsIDOMDocument *aSourceDoc, [in] nsIDOMNode *aDestinationNode, [in] PRInt32 aDestinationOffset, [in] PRBool aDeleteSelection); + nsresult InsertElementAtSelection([in] nsIDOMElement *aElement, [in] PRBool aDeleteSelection); + nsresult SetDocumentTitle([in] nsAString *aTitle); + nsresult UpdateBaseURL(); + nsresult SelectElement([in] nsIDOMElement *aElement); + nsresult SetCaretAfterElement([in] nsIDOMElement *aElement); + nsresult SetParagraphFormat([in] nsAString *aParagraphFormat); + nsresult GetParagraphState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetFontFaceState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetFontColorState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetBackgroundColorState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetHighlightColorState([out] PRBool *aMixed, [out] nsAString *_retval); + nsresult GetListState([out] PRBool *aMixed, [out] PRBool *aOL, [out] PRBool *aUL, [out] PRBool *aDL); + nsresult GetListItemState([out] PRBool *aMixed, [out] PRBool *aLI, [out] PRBool *aDT, [out] PRBool *aDD); + nsresult GetAlignment([out] PRBool *aMixed, [out] PRInt16 *aAlign); + nsresult GetIndentState([out] PRBool *aCanIndent, [out] PRBool *aCanOutdent); + nsresult MakeOrChangeList([in] nsAString *aListType, [in] PRBool entireList, [in] nsAString *aBulletType); + nsresult RemoveList([in] nsAString *aListType); + nsresult Indent([in] nsAString *aIndent); + nsresult Align([in] nsAString *aAlign); + nsresult GetElementOrParentByTagName([in] nsAString *aTagName, [in] nsIDOMNode *aNode, [out] nsIDOMElement **_retval); + nsresult GetSelectedElement([in] nsAString *aTagName, [out] nsIDOMElement **_retval); + nsresult GetHeadContentsAsHTML([out] nsAString *_retval); + nsresult ReplaceHeadContentsWithHTML([in] nsAString *aSourceToInsert); + nsresult CreateElementWithDefaults([in] nsAString *aTagName, [out] nsIDOMElement **_retval); + nsresult InsertLinkAroundSelection([in] nsIDOMElement *aAnchorElement); + nsresult SetBackgroundColor([in] nsAString *aColor); + nsresult SetBodyAttribute([in] nsAString *aAttr, [in] nsAString *aValue); + nsresult IgnoreSpuriousDragEvent([in] PRBool aIgnoreSpuriousDragEvent); + nsresult GetLinkedObjects([out] nsISupportsArray **_retval); + nsresult GetIsCSSEnabled([out] PRBool *_retval); + nsresult SetIsCSSEnabled([in] PRBool prb); + nsresult AddInsertionListener([in] nsIContentFilter *inFilter); + nsresult RemoveInsertionListener([in] nsIContentFilter *inFilter); + nsresult CreateAnonymousElement([in] nsAString *aTag, [in] nsIDOMNode *aParentNode, [in] nsAString *aAnonClass, [in] PRBool aIsCreatedHidden, [out] nsIDOMElement **_retval); + nsresult GetSelectionContainer([out] nsIDOMElement **_retval); + nsresult CheckSelectionStateForAnonymousButtons([in] nsISelection *aSelection); + nsresult IsAnonymousElement([in] nsIDOMElement *aElement, [out] PRBool *_retval); + nsresult GetReturnInParagraphCreatesNewParagraph([out] PRBool *_retval); + nsresult SetReturnInParagraphCreatesNewParagraph([in] PRBool prb); +} + /* * NOTE: * This is a private Wine interface that is implemented by our implementation diff --git a/dlls/mshtml/resource.h b/dlls/mshtml/resource.h index 27dae83502d..f8415f3c52d 100644 --- a/dlls/mshtml/resource.h +++ b/dlls/mshtml/resource.h @@ -49,3 +49,9 @@ #define IDM_DUMPLAYOUTRECTS 6017 #define _IDM_REFRESH 6042 + +#define IDD_HYPERLINK 8000 + +#define IDC_STATIC 9000 +#define IDC_URL 9001 +#define IDC_TYPE 9002