Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/mshtml/htmlelem.c | 55 ++++++++++++++++++++++++---- dlls/mshtml/mshtml_private_iface.idl | 2 + dlls/mshtml/tests/dom.js | 43 ++++++++++++++++++++++ 3 files changed, 92 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index b5b0daa2539..4506f170616 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -6515,11 +6515,12 @@ static const WCHAR *find_token(const WCHAR *list, const WCHAR *token, unsigned i return NULL; }
-static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_array) +static HRESULT WINAPI token_list_add_remove(IWineDOMTokenList *iface, SAFEARRAY *token_array, BOOL remove) { struct token_list *token_list = impl_from_IWineDOMTokenList(iface); unsigned int i, len, old_len, new_len; WCHAR *token, *old, *new; + const WCHAR *old_pos; VARIANT *var, tmp; HRESULT hr;
@@ -6578,7 +6579,8 @@ static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_
TRACE("old %s.\n", debugstr_w(old));
- if (find_token(old, token, len)) + if (((old_pos = find_token(old, token, len)) && !remove) + || (!old_pos && remove)) { SysFreeString(old); hr = S_OK; @@ -6586,7 +6588,25 @@ static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_ }
old_len = old ? lstrlenW(old) : 0; - new_len = old_len + len + !!old_len; + if (remove) + { + while (old_pos != old && iswspace(old_pos[-1])) + { + --old_pos; + ++len; + } + while (iswspace(old_pos[len])) + ++len; + + if (old_pos != old && old_pos[len]) + --len; + + new_len = old_len - len; + } + else + { + new_len = old_len + len + !!old_len; + }
if (!(new = heap_alloc(sizeof(*new) * (new_len + 1)))) { @@ -6596,11 +6616,19 @@ static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_ goto done; }
- memcpy(new, old, sizeof(*new) * old_len); - if (old_len) - new[old_len++]= L' '; - memcpy(new + old_len, token, sizeof(*new) * len); - new[old_len + len] = 0; + if (remove) + { + memcpy(new, old, sizeof(*new) * (old_pos - old)); + memcpy(new + (old_pos - old), old_pos + len, sizeof(*new) * (old_len - (old_pos - old) - len + 1)); + } + else + { + memcpy(new, old, sizeof(*new) * old_len); + if (old_len) + new[old_len++]= L' '; + memcpy(new + old_len, token, sizeof(*new) * len); + new[old_len + len] = 0; + }
SysFreeString(old);
@@ -6616,6 +6644,16 @@ done: return hr; }
+static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_array) +{ + return token_list_add_remove(iface, token_array, FALSE); +} + +static HRESULT WINAPI token_list_remove(IWineDOMTokenList *iface, SAFEARRAY *token_array) +{ + return token_list_add_remove(iface, token_array, TRUE); +} + static const IWineDOMTokenListVtbl WineDOMTokenListVtbl = { token_list_QueryInterface, token_list_AddRef, @@ -6625,6 +6663,7 @@ static const IWineDOMTokenListVtbl WineDOMTokenListVtbl = { token_list_GetIDsOfNames, token_list_Invoke, token_list_add, + token_list_remove, };
static const tid_t token_list_iface_tids[] = { diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl index b50d2f9502b..7dc4928aab8 100644 --- a/dlls/mshtml/mshtml_private_iface.idl +++ b/dlls/mshtml/mshtml_private_iface.idl @@ -113,6 +113,8 @@ interface IWineDOMTokenList : IDispatch { [vararg, id(1)] HRESULT add([in] SAFEARRAY(VARIANT) token); + [vararg, id(2)] + HRESULT remove([in] SAFEARRAY(VARIANT) token); }
} /* library MSHTML_private */ diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js index ae6d49da26c..f3fe245d250 100644 --- a/dlls/mshtml/tests/dom.js +++ b/dlls/mshtml/tests/dom.js @@ -562,4 +562,47 @@ sync_test("classList", function() { exception = true; } ok(exception, "Expected exception for classList.add("e f")"); + + classList.remove("e"); + ok(elem.className === "a b c 4", "remove: expected className 'a b c 4', got " + elem.className); + + exception = false + try + { + classList.remove("e f"); + } + catch(e) + { + exception = true; + } + ok(exception, "remove: expected exception for classList.remove("e f")"); + + exception = false + try + { + classList.remove(""); + } + catch(e) + { + exception = true; + } + ok(exception, "remove: expected exception for classList.remove("")"); + + classList.remove("d"); + ok(elem.className === "a b c 4", "remove: expected className 'a b c 4', got " + elem.className); + + classList.remove("c", 4); + ok(elem.className === "a b 4", "remove: expected className 'a b 4', got " + elem.className); + + classList.remove(4); + ok(elem.className === "a b", "remove: expected className 'a b', got " + elem.className); + + classList.remove('a'); + ok(elem.className === "b", "remove: expected className 'b', got " + elem.className); + + classList.remove("a"); + ok(elem.className === "b", "remove (2): expected className 'b', got " + elem.className); + + classList.remove("b"); + ok(elem.className === "", "remove: expected className '', got " + elem.className); });