msxml3/tests: Run IXMLDOMNode::get_text whitespace tests on other msxml versions.
Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e0d8003a9a
commit
1f2c20cff3
|
@ -4137,36 +4137,41 @@ static void test_IXMLDOMDocument2(void)
|
|||
ok_(__FILE__, line)(r == S_OK, "=> %i: " #expr " returned %08x\n", __LINE__, r); \
|
||||
}
|
||||
|
||||
#define helper_ole_check_ver(expr) { \
|
||||
HRESULT r = expr; \
|
||||
ok_(__FILE__, line)(r == S_OK, "-> %i (%s): " #expr " returned %08x\n", __LINE__, ver, r); \
|
||||
}
|
||||
|
||||
#define helper_expect_list_and_release(list, expstr) { \
|
||||
char *str = list_to_string(list); \
|
||||
ok_(__FILE__, line)(strcmp(str, expstr)==0, "=> %i: Invalid node list: %s, expected %s\n", __LINE__, str, expstr); \
|
||||
ok_(__FILE__, line)(strcmp(str, expstr)==0, "=> %i (%s): Invalid node list: %s, expected %s\n", __LINE__, ver, str, expstr); \
|
||||
if (list) IXMLDOMNodeList_Release(list); \
|
||||
}
|
||||
|
||||
#define helper_expect_bstr_and_release(bstr, str) { \
|
||||
ok_(__FILE__, line)(lstrcmpW(bstr, _bstr_(str)) == 0, \
|
||||
"=> %i: got %s\n", __LINE__, wine_dbgstr_w(bstr)); \
|
||||
"=> %i (%s): got %s\n", __LINE__, ver, wine_dbgstr_w(bstr)); \
|
||||
SysFreeString(bstr); \
|
||||
}
|
||||
|
||||
#define check_ws_ignored(doc, str) _check_ws_ignored(__LINE__, doc, str)
|
||||
static inline void _check_ws_ignored(int line, IXMLDOMDocument2* doc, char const* str)
|
||||
#define check_ws_ignored(ver, doc, str) _check_ws_ignored(__LINE__, ver, doc, str)
|
||||
static inline void _check_ws_ignored(int line, const char *ver, IXMLDOMDocument2* doc, char const* str)
|
||||
{
|
||||
IXMLDOMNode *node1, *node2;
|
||||
IXMLDOMNodeList *list;
|
||||
BSTR bstr;
|
||||
|
||||
helper_ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
|
||||
helper_ole_check(IXMLDOMNodeList_get_item(list, 0, &node1));
|
||||
helper_ole_check(IXMLDOMNodeList_get_item(list, 1, &node2));
|
||||
helper_ole_check(IXMLDOMNodeList_reset(list));
|
||||
helper_ole_check_ver(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
|
||||
helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 0, &node1));
|
||||
helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 1, &node2));
|
||||
helper_ole_check_ver(IXMLDOMNodeList_reset(list));
|
||||
helper_expect_list_and_release(list, "E1.E5.E1.E2.D1 E2.E5.E1.E2.D1");
|
||||
|
||||
helper_ole_check(IXMLDOMNode_get_childNodes(node1, &list));
|
||||
helper_ole_check_ver(IXMLDOMNode_get_childNodes(node1, &list));
|
||||
helper_expect_list_and_release(list,
|
||||
"[4]1.E1.E5.E1.E2.D1 T2.E1.E5.E1.E2.D1 E3.E1.E5.E1.E2.D1 "
|
||||
"E4.E1.E5.E1.E2.D1 E5.E1.E5.E1.E2.D1 E6.E1.E5.E1.E2.D1");
|
||||
helper_ole_check(IXMLDOMNode_get_text(node1, &bstr));
|
||||
helper_ole_check_ver(IXMLDOMNode_get_text(node1, &bstr));
|
||||
if (str)
|
||||
{
|
||||
todo_wine helper_expect_bstr_and_release(bstr, str);
|
||||
|
@ -4177,32 +4182,35 @@ static inline void _check_ws_ignored(int line, IXMLDOMDocument2* doc, char const
|
|||
}
|
||||
IXMLDOMNode_Release(node1);
|
||||
|
||||
helper_ole_check(IXMLDOMNode_get_childNodes(node2, &list));
|
||||
helper_expect_list_and_release(list, "T1.E2.E5.E1.E2.D1 E2.E2.E5.E1.E2.D1 T3.E2.E5.E1.E2.D1 E4.E2.E5.E1.E2.D1 T5.E2.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1 T7.E2.E5.E1.E2.D1");
|
||||
helper_ole_check(IXMLDOMNode_get_text(node2, &bstr));
|
||||
helper_expect_bstr_and_release(bstr, "\n This is a description with preserved whitespace. \n ");
|
||||
helper_ole_check_ver(IXMLDOMNode_get_childNodes(node2, &list));
|
||||
helper_expect_list_and_release(list,
|
||||
"T1.E2.E5.E1.E2.D1 E2.E2.E5.E1.E2.D1 T3.E2.E5.E1.E2.D1 "
|
||||
"E4.E2.E5.E1.E2.D1 T5.E2.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1 T7.E2.E5.E1.E2.D1");
|
||||
helper_ole_check_ver(IXMLDOMNode_get_text(node2, &bstr));
|
||||
helper_expect_bstr_and_release(bstr,
|
||||
"\n This is a description with preserved whitespace. \n ");
|
||||
IXMLDOMNode_Release(node2);
|
||||
}
|
||||
|
||||
#define check_ws_preserved(doc, str) _check_ws_preserved(__LINE__, doc, str)
|
||||
static inline void _check_ws_preserved(int line, IXMLDOMDocument2* doc, char const* str)
|
||||
#define check_ws_preserved(ver, doc, str) _check_ws_preserved(__LINE__, ver, doc, str)
|
||||
static inline void _check_ws_preserved(int line, const char *ver, IXMLDOMDocument2* doc, char const* str)
|
||||
{
|
||||
IXMLDOMNode *node1, *node2;
|
||||
IXMLDOMNodeList *list;
|
||||
BSTR bstr;
|
||||
|
||||
helper_ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
|
||||
helper_ole_check(IXMLDOMNodeList_get_item(list, 0, &node1));
|
||||
helper_ole_check(IXMLDOMNodeList_get_item(list, 1, &node2));
|
||||
helper_ole_check(IXMLDOMNodeList_reset(list));
|
||||
helper_ole_check_ver(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
|
||||
helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 0, &node1));
|
||||
helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 1, &node2));
|
||||
helper_ole_check_ver(IXMLDOMNodeList_reset(list));
|
||||
helper_expect_list_and_release(list, "E2.E10.E2.E2.D1 E4.E10.E2.E2.D1");
|
||||
|
||||
helper_ole_check(IXMLDOMNode_get_childNodes(node1, &list));
|
||||
helper_ole_check_ver(IXMLDOMNode_get_childNodes(node1, &list));
|
||||
helper_expect_list_and_release(list,
|
||||
"T1.E2.E10.E2.E2.D1 [4]2.E2.E10.E2.E2.D1 T3.E2.E10.E2.E2.D1 "
|
||||
"E4.E2.E10.E2.E2.D1 T5.E2.E10.E2.E2.D1 E6.E2.E10.E2.E2.D1 "
|
||||
"E7.E2.E10.E2.E2.D1 E8.E2.E10.E2.E2.D1 T9.E2.E10.E2.E2.D1");
|
||||
helper_ole_check(IXMLDOMNode_get_text(node1, &bstr));
|
||||
helper_ole_check_ver(IXMLDOMNode_get_text(node1, &bstr));
|
||||
if (str)
|
||||
{
|
||||
todo_wine helper_expect_bstr_and_release(bstr, str);
|
||||
|
@ -4213,10 +4221,13 @@ static inline void _check_ws_preserved(int line, IXMLDOMDocument2* doc, char con
|
|||
}
|
||||
IXMLDOMNode_Release(node1);
|
||||
|
||||
helper_ole_check(IXMLDOMNode_get_childNodes(node2, &list));
|
||||
helper_expect_list_and_release(list, "T1.E4.E10.E2.E2.D1 E2.E4.E10.E2.E2.D1 T3.E4.E10.E2.E2.D1 E4.E4.E10.E2.E2.D1 T5.E4.E10.E2.E2.D1 E6.E4.E10.E2.E2.D1 T7.E4.E10.E2.E2.D1");
|
||||
helper_ole_check(IXMLDOMNode_get_text(node2, &bstr));
|
||||
helper_expect_bstr_and_release(bstr, "\n This is a description with preserved whitespace. \n ");
|
||||
helper_ole_check_ver(IXMLDOMNode_get_childNodes(node2, &list));
|
||||
helper_expect_list_and_release(list,
|
||||
"T1.E4.E10.E2.E2.D1 E2.E4.E10.E2.E2.D1 T3.E4.E10.E2.E2.D1 "
|
||||
"E4.E4.E10.E2.E2.D1 T5.E4.E10.E2.E2.D1 E6.E4.E10.E2.E2.D1 T7.E4.E10.E2.E2.D1");
|
||||
helper_ole_check_ver(IXMLDOMNode_get_text(node2, &bstr));
|
||||
helper_expect_bstr_and_release(bstr,
|
||||
"\n This is a description with preserved whitespace. \n ");
|
||||
IXMLDOMNode_Release(node2);
|
||||
}
|
||||
|
||||
|
@ -4268,110 +4279,142 @@ static void test_preserve_charref(IXMLDOMDocument2 *doc, VARIANT_BOOL preserve)
|
|||
IXMLDOMNodeList_Release(list);
|
||||
}
|
||||
|
||||
struct whitespace_t {
|
||||
const CLSID *clsid;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct whitespace_t whitespace_test_data[] = {
|
||||
{ &CLSID_DOMDocument, "CLSID_DOMDocument" },
|
||||
{ &CLSID_DOMDocument2, "CLSID_DOMDocument2" },
|
||||
{ &CLSID_DOMDocument26, "CLSID_DOMDocument26" },
|
||||
{ &CLSID_DOMDocument30, "CLSID_DOMDocument30" },
|
||||
{ &CLSID_DOMDocument40, "CLSID_DOMDocument40" },
|
||||
{ &CLSID_DOMDocument60, "CLSID_DOMDocument60" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void test_whitespace(void)
|
||||
{
|
||||
IXMLDOMDocument2 *doc1, *doc2, *doc3, *doc4;
|
||||
IXMLDOMNodeList *list;
|
||||
IXMLDOMElement *root;
|
||||
VARIANT_BOOL b;
|
||||
HRESULT hr;
|
||||
LONG len;
|
||||
const struct whitespace_t *class_ptr = whitespace_test_data;
|
||||
|
||||
if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
|
||||
doc1 = create_document(&IID_IXMLDOMDocument2);
|
||||
doc2 = create_document(&IID_IXMLDOMDocument2);
|
||||
while (class_ptr->clsid)
|
||||
{
|
||||
IXMLDOMDocument2 *doc1, *doc2, *doc3, *doc4;
|
||||
IXMLDOMNodeList *list;
|
||||
IXMLDOMElement *root;
|
||||
VARIANT_BOOL b;
|
||||
HRESULT hr;
|
||||
LONG len;
|
||||
|
||||
ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_TRUE));
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
|
||||
ok(b == VARIANT_FALSE, "expected false\n");
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
|
||||
ok(b == VARIANT_TRUE, "expected true\n");
|
||||
if (!is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument2))
|
||||
{
|
||||
class_ptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML string\n");
|
||||
ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML string\n");
|
||||
hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IXMLDOMDocument2, (void**)&doc1);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
/* switch to XPath */
|
||||
ole_check(IXMLDOMDocument2_setProperty(doc1, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
|
||||
ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
|
||||
hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IXMLDOMDocument2, (void**)&doc2);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
check_ws_ignored(doc1, NULL);
|
||||
check_ws_preserved(doc2, NULL);
|
||||
ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_TRUE));
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
|
||||
ok(b == VARIANT_FALSE, "expected false\n");
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
|
||||
ok(b == VARIANT_TRUE, "expected true\n");
|
||||
|
||||
/* new instances copy the property */
|
||||
ole_check(IXMLDOMDocument2_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**) &doc3));
|
||||
ole_check(IXMLDOMDocument2_QueryInterface(doc2, &IID_IXMLDOMDocument2, (void**) &doc4));
|
||||
ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML string\n");
|
||||
ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML string\n");
|
||||
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
|
||||
ok(b == VARIANT_FALSE, "expected false\n");
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
|
||||
ok(b == VARIANT_TRUE, "expected true\n");
|
||||
/* switch to XPath */
|
||||
ole_check(IXMLDOMDocument2_setProperty(doc1, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
|
||||
ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
|
||||
|
||||
check_ws_ignored(doc3, NULL);
|
||||
check_ws_preserved(doc4, NULL);
|
||||
check_ws_ignored(class_ptr->name, doc1, NULL);
|
||||
check_ws_preserved(class_ptr->name, doc2, NULL);
|
||||
|
||||
/* setting after loading xml affects trimming of leading/trailing ws only */
|
||||
ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_TRUE));
|
||||
ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_FALSE));
|
||||
/* new instances copy the property */
|
||||
ole_check(IXMLDOMDocument2_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**) &doc3));
|
||||
ole_check(IXMLDOMDocument2_QueryInterface(doc2, &IID_IXMLDOMDocument2, (void**) &doc4));
|
||||
|
||||
/* the trailing "\n " isn't there, because it was ws-only node */
|
||||
check_ws_ignored(doc1, " This is a description. ");
|
||||
check_ws_preserved(doc2, " This is a description.");
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
|
||||
ok(b == VARIANT_FALSE, "expected false\n");
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
|
||||
ok(b == VARIANT_TRUE, "expected true\n");
|
||||
|
||||
/* it takes effect on reload */
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
|
||||
ok(b == VARIANT_TRUE, "expected true\n");
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
|
||||
ok(b == VARIANT_FALSE, "expected false\n");
|
||||
check_ws_ignored(class_ptr->name, doc3, NULL);
|
||||
check_ws_preserved(class_ptr->name, doc4, NULL);
|
||||
|
||||
ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML string\n");
|
||||
ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML string\n");
|
||||
/* setting after loading xml affects trimming of leading/trailing ws only */
|
||||
ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_TRUE));
|
||||
ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_FALSE));
|
||||
|
||||
check_ws_preserved(doc1, NULL);
|
||||
check_ws_ignored(doc2, NULL);
|
||||
/* the trailing "\n " isn't there, because it was ws-only node */
|
||||
check_ws_ignored(class_ptr->name, doc1, " This is a description. ");
|
||||
check_ws_preserved(class_ptr->name, doc2, " This is a description.");
|
||||
|
||||
/* other instances follow suit */
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
|
||||
ok(b == VARIANT_TRUE, "expected true\n");
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
|
||||
ok(b == VARIANT_FALSE, "expected false\n");
|
||||
/* it takes effect on reload */
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
|
||||
ok(b == VARIANT_TRUE, "expected true\n");
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
|
||||
ok(b == VARIANT_FALSE, "expected false\n");
|
||||
|
||||
check_ws_preserved(doc3, NULL);
|
||||
check_ws_ignored(doc4, NULL);
|
||||
ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML string\n");
|
||||
ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML string\n");
|
||||
|
||||
IXMLDOMDocument2_Release(doc2);
|
||||
IXMLDOMDocument2_Release(doc3);
|
||||
IXMLDOMDocument2_Release(doc4);
|
||||
check_ws_preserved(class_ptr->name, doc1, NULL);
|
||||
check_ws_ignored(class_ptr->name, doc2, NULL);
|
||||
|
||||
/* text with char references */
|
||||
test_preserve_charref(doc1, VARIANT_TRUE);
|
||||
test_preserve_charref(doc1, VARIANT_FALSE);
|
||||
/* other instances follow suit */
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
|
||||
ok(b == VARIANT_TRUE, "expected true\n");
|
||||
ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
|
||||
ok(b == VARIANT_FALSE, "expected false\n");
|
||||
|
||||
/* formatting whitespaces */
|
||||
hr = IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_FALSE);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
check_ws_preserved(class_ptr->name, doc3, NULL);
|
||||
check_ws_ignored(class_ptr->name, doc4, NULL);
|
||||
|
||||
hr = IXMLDOMDocument2_loadXML(doc1, _bstr_(complete7), &b);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(b == VARIANT_TRUE, "for %x\n", b);
|
||||
IXMLDOMDocument2_Release(doc2);
|
||||
IXMLDOMDocument2_Release(doc3);
|
||||
IXMLDOMDocument2_Release(doc4);
|
||||
|
||||
hr = IXMLDOMDocument2_get_documentElement(doc1, &root);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
hr = IXMLDOMElement_get_childNodes(root, &list);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
len = 0;
|
||||
hr = IXMLDOMNodeList_get_length(list, &len);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(len == 3, "got %d\n", len);
|
||||
IXMLDOMNodeList_Release(list);
|
||||
IXMLDOMElement_Release(root);
|
||||
/* text with char references */
|
||||
test_preserve_charref(doc1, VARIANT_TRUE);
|
||||
test_preserve_charref(doc1, VARIANT_FALSE);
|
||||
|
||||
IXMLDOMDocument2_Release(doc1);
|
||||
/* formatting whitespaces */
|
||||
hr = IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_FALSE);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
free_bstrs();
|
||||
hr = IXMLDOMDocument2_loadXML(doc1, _bstr_(complete7), &b);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(b == VARIANT_TRUE, "for %x\n", b);
|
||||
|
||||
hr = IXMLDOMDocument2_get_documentElement(doc1, &root);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
hr = IXMLDOMElement_get_childNodes(root, &list);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
len = 0;
|
||||
hr = IXMLDOMNodeList_get_length(list, &len);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
ok(len == 3, "got %d\n", len);
|
||||
IXMLDOMNodeList_Release(list);
|
||||
IXMLDOMElement_Release(root);
|
||||
|
||||
IXMLDOMDocument2_Release(doc1);
|
||||
|
||||
free_bstrs();
|
||||
|
||||
class_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
|
Loading…
Reference in New Issue