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