Jacek Caban : mshtml: Added support for conditional comments.

Alexandre Julliard julliard at winehq.org
Thu Oct 16 06:07:06 CDT 2008


Module: wine
Branch: master
Commit: a1a25c534a22c0d6a868f9fcd62176dda65250c2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a1a25c534a22c0d6a868f9fcd62176dda65250c2

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Oct 15 15:22:29 2008 -0500

mshtml: Added support for conditional comments.

---

 dlls/mshtml/nsevents.c  |  191 ++++++++++++++++++++++++++++++++++++++++++++---
 dlls/mshtml/tests/dom.c |   24 ++++++
 2 files changed, 204 insertions(+), 11 deletions(-)

diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c
index dc54322..806e9eb 100644
--- a/dlls/mshtml/nsevents.c
+++ b/dlls/mshtml/nsevents.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Jacek Caban for CodeWeavers
+ * Copyright 2007-2008 Jacek Caban for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -175,11 +175,149 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event
     return NS_OK;
 }
 
+#define IE_MAJOR_VERSION 7
+#define IE_MINOR_VERSION 0
+
+static BOOL handle_insert_comment(HTMLDocument *doc, const PRUnichar *comment)
+{
+    DWORD len;
+    int majorv = 0, minorv = 0;
+    const PRUnichar *ptr, *end;
+    nsAString nsstr;
+    PRUnichar *buf;
+    nsresult nsres;
+
+    enum {
+        CMP_EQ,
+        CMP_LT,
+        CMP_LTE,
+        CMP_GT,
+        CMP_GTE
+    } cmpt = CMP_EQ;
+
+    static const PRUnichar endifW[] = {'<','!','[','e','n','d','i','f',']'};
+
+    if(comment[0] != '[' || comment[1] != 'i' || comment[2] != 'f')
+        return FALSE;
+
+    ptr = comment+3;
+    while(isspaceW(*ptr))
+        ptr++;
+
+    if(ptr[0] == 'l' && ptr[1] == 't') {
+        ptr += 2;
+        if(*ptr == 'e') {
+            cmpt = CMP_LTE;
+            ptr++;
+        }else {
+            cmpt = CMP_LT;
+        }
+    }else if(ptr[0] == 'g' && ptr[1] == 't') {
+        ptr += 2;
+        if(*ptr == 'e') {
+            cmpt = CMP_GTE;
+            ptr++;
+        }else {
+            cmpt = CMP_GT;
+        }
+    }
+
+    if(!isspaceW(*ptr++))
+        return FALSE;
+    while(isspaceW(*ptr))
+        ptr++;
+
+    if(ptr[0] != 'I' || ptr[1] != 'E')
+        return FALSE;
+
+    ptr +=2;
+    if(!isspaceW(*ptr++))
+        return FALSE;
+    while(isspaceW(*ptr))
+        ptr++;
+
+    if(!isdigitW(*ptr))
+        return FALSE;
+    while(isdigitW(*ptr))
+        majorv = majorv*10 + (*ptr++ - '0');
+
+    if(*ptr == '.') {
+        if(!isdigitW(*ptr))
+            return FALSE;
+        while(isdigitW(*ptr))
+            minorv = minorv*10 + (*ptr++ - '0');
+    }
+
+    while(isspaceW(*ptr))
+        ptr++;
+    if(ptr[0] != ']' || ptr[1] != '>')
+        return FALSE;
+    ptr += 2;
+
+    len = strlenW(ptr);
+    if(len < sizeof(endifW)/sizeof(WCHAR))
+        return FALSE;
+
+    end = ptr + len-sizeof(endifW)/sizeof(WCHAR);
+    if(memcmp(end, endifW, sizeof(endifW)))
+        return FALSE;
+
+    switch(cmpt) {
+    case CMP_EQ:
+        if(majorv == IE_MAJOR_VERSION && minorv == IE_MINOR_VERSION)
+            break;
+        return FALSE;
+    case CMP_LT:
+        if(majorv > IE_MAJOR_VERSION)
+            break;
+        if(majorv == IE_MAJOR_VERSION && minorv > IE_MINOR_VERSION)
+            break;
+        return FALSE;
+    case CMP_LTE:
+        if(majorv > IE_MAJOR_VERSION)
+            break;
+        if(majorv == IE_MAJOR_VERSION && minorv >= IE_MINOR_VERSION)
+            break;
+        return FALSE;
+    case CMP_GT:
+        if(majorv < IE_MAJOR_VERSION)
+            break;
+        if(majorv == IE_MAJOR_VERSION && minorv < IE_MINOR_VERSION)
+            break;
+        return FALSE;
+    case CMP_GTE:
+        if(majorv < IE_MAJOR_VERSION)
+            break;
+        if(majorv == IE_MAJOR_VERSION && minorv <= IE_MINOR_VERSION)
+            break;
+        return FALSE;
+    }
+
+    buf = heap_alloc((end-ptr+1)*sizeof(WCHAR));
+    if(!buf)
+        return FALSE;
+
+    memcpy(buf, ptr, (end-ptr)*sizeof(WCHAR));
+    buf[end-ptr] = 0;
+    nsAString_Init(&nsstr, buf);
+    heap_free(buf);
+
+    /* FIXME: Find better way to insert HTML to document. */
+    nsres = nsIDOMHTMLDocument_Write(doc->nsdoc, &nsstr);
+    nsAString_Finish(&nsstr);
+    if(NS_FAILED(nsres)) {
+        ERR("Write failed: %08x\n", nsres);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 static nsresult NSAPI handle_node_insert(nsIDOMEventListener *iface, nsIDOMEvent *event)
 {
     NSContainer *This = NSEVENTLIST_THIS(iface)->This;
-    nsIDOMHTMLScriptElement *script;
     nsIDOMEventTarget *target;
+    nsIDOMComment *nscomment;
     nsIDOMElement *elem;
     nsresult nsres;
 
@@ -192,19 +330,50 @@ static nsresult NSAPI handle_node_insert(nsIDOMEventListener *iface, nsIDOMEvent
     }
 
     nsres = nsIDOMEventTarget_QueryInterface(target, &IID_nsIDOMElement, (void**)&elem);
-    nsIDOMEventTarget_Release(target);
-    if(NS_FAILED(nsres))
-        return NS_OK;
+    if(NS_SUCCEEDED(nsres)) {
+        nsIDOMHTMLScriptElement *script;
+
+        nsres = nsIDOMElement_QueryInterface(elem, &IID_nsIDOMHTMLScriptElement, (void**)&script);
+        if(NS_SUCCEEDED(nsres)) {
+            doc_insert_script(This->doc, script);
+            nsIDOMHTMLScriptElement_Release(script);
+        }
 
-    nsres = nsIDOMElement_QueryInterface(elem, &IID_nsIDOMHTMLScriptElement, (void**)&script);
-    if(SUCCEEDED(nsres)) {
-        doc_insert_script(This->doc, script);
-        nsIDOMHTMLScriptElement_Release(script);
+        check_event_attr(This->doc, elem);
+
+        nsIDOMEventTarget_Release(target);
+        nsIDOMNode_Release(elem);
+        return NS_OK;
     }
 
-    check_event_attr(This->doc, elem);
+    nsres = nsIDOMEventTarget_QueryInterface(target, &IID_nsIDOMComment, (void**)&nscomment);
+    if(NS_SUCCEEDED(nsres)) {
+        nsAString comment_str;
+        BOOL remove_comment = FALSE;
+
+        nsAString_Init(&comment_str, NULL);
+        nsres = nsIDOMComment_GetData(nscomment, &comment_str);
+        if(NS_SUCCEEDED(nsres)) {
+            const PRUnichar *comment;
+
+            nsAString_GetData(&comment_str, &comment);
+            remove_comment = handle_insert_comment(This->doc, comment);
+        }
+
+        nsAString_Finish(&comment_str);
+
+        if(remove_comment) {
+            nsIDOMNode *nsparent, *tmp;
+
+            nsIDOMComment_GetParentNode(nscomment, &nsparent);
+            nsIDOMNode_RemoveChild(nsparent, (nsIDOMNode*)nscomment, &tmp);
+            nsIDOMNode_Release(nsparent);
+            nsIDOMNode_Release(tmp);
+        }
+
+        nsIDOMComment_Release(nscomment);
+    }
 
-    nsIDOMNode_Release(elem);
     return NS_OK;
 }
 
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index 4388048..75538fe 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -53,6 +53,10 @@ static const char elem_test_str[] =
     "</body></html>";
 static const char indent_test_str[] =
     "<html><head><title>test</title></head><body>abc<br /><a href=\"about:blank\">123</a></body></html>";
+static const char cond_comment_str[] =
+    "<html><head><title>test</title></head><body>"
+    "<!--[if gte IE 4]> <br> <![endif]-->"
+    "</body></html>";
 
 static const WCHAR noneW[] = {'N','o','n','e',0};
 
@@ -3373,6 +3377,25 @@ static void test_indent(IHTMLDocument2 *doc)
     IHTMLElementCollection_Release(col);
 }
 
+static void test_cond_comment(IHTMLDocument2 *doc)
+{
+    IHTMLElementCollection *col;
+    HRESULT hres;
+
+    static const elem_type_t all_types[] = {
+        ET_HTML,
+        ET_HEAD,
+        ET_TITLE,
+        ET_BODY,
+        ET_BR
+    };
+
+    hres = IHTMLDocument2_get_all(doc, &col);
+    ok(hres == S_OK, "get_all failed: %08x\n", hres);
+    test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
+    IHTMLElementCollection_Release(col);
+}
+
 static IHTMLDocument2 *notif_doc;
 static BOOL doc_complete;
 
@@ -3556,6 +3579,7 @@ START_TEST(dom)
     run_domtest(doc_blank, test_create_elems);
     run_domtest(doc_blank, test_defaults);
     run_domtest(indent_test_str, test_indent);
+    run_domtest(cond_comment_str, test_cond_comment);
 
     CoUninitialize();
     gecko_installer_workaround(FALSE);




More information about the wine-cvs mailing list