mshtml: Introduced new representation of range point and use that in range_to_string instead of trying to iterate by nodes.

This commit is contained in:
Jacek Caban 2014-12-29 15:49:31 +01:00 committed by Alexandre Julliard
parent 25b13178de
commit 3944fada4b
1 changed files with 173 additions and 47 deletions

View File

@ -55,6 +55,12 @@ typedef struct {
DWORD size;
} wstrbuf_t;
typedef struct {
UINT16 type;
nsIDOMNode *node;
UINT32 off;
} rangepoint_t;
typedef struct {
UINT16 type;
nsIDOMNode *node;
@ -128,6 +134,136 @@ static UINT16 get_node_type(nsIDOMNode *node)
return type;
}
static void get_text_node_data(nsIDOMNode *node, nsAString *nsstr, const PRUnichar **str)
{
nsIDOMText *nstext;
nsresult nsres;
nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
assert(nsres == NS_OK);
nsAString_Init(nsstr, NULL);
nsres = nsIDOMText_GetData(nstext, nsstr);
nsIDOMText_Release(nstext);
if(NS_FAILED(nsres))
ERR("GetData failed: %08x\n", nsres);
nsAString_GetData(nsstr, str);
}
static nsIDOMNode *get_child_node(nsIDOMNode *node, UINT32 off)
{
nsIDOMNodeList *node_list;
nsIDOMNode *ret = NULL;
nsIDOMNode_GetChildNodes(node, &node_list);
nsIDOMNodeList_Item(node_list, off, &ret);
nsIDOMNodeList_Release(node_list);
return ret;
}
/* This is very inefficient, but there is no faster way to compute index in
* child node list using public API. Gecko has internal nsINode::IndexOf
* function that we could consider exporting and use instead. */
static int get_child_index(nsIDOMNode *parent, nsIDOMNode *child)
{
nsIDOMNodeList *node_list;
nsIDOMNode *node;
int ret = 0;
nsresult nsres;
nsres = nsIDOMNode_GetChildNodes(parent, &node_list);
assert(nsres == NS_OK);
while(1) {
nsres = nsIDOMNodeList_Item(node_list, ret, &node);
assert(nsres == NS_OK && node);
if(node == child) {
nsIDOMNode_Release(node);
break;
}
nsIDOMNode_Release(node);
ret++;
}
nsIDOMNodeList_Release(node_list);
return ret;
}
static void init_rangepoint(rangepoint_t *rangepoint, nsIDOMNode *node, UINT32 off)
{
nsIDOMNode_AddRef(node);
rangepoint->type = get_node_type(node);
rangepoint->node = node;
rangepoint->off = off;
}
static inline void free_rangepoint(rangepoint_t *rangepoint)
{
nsIDOMNode_Release(rangepoint->node);
}
static inline BOOL rangepoint_cmp(const rangepoint_t *point1, const rangepoint_t *point2)
{
return point1->node == point2->node && point1->off == point2->off;
}
static BOOL rangepoint_next_node(rangepoint_t *iter)
{
nsIDOMNode *node;
UINT32 off;
nsresult nsres;
/* Try to move to the child node. */
node = get_child_node(iter->node, iter->off);
if(node) {
free_rangepoint(iter);
init_rangepoint(iter, node, 0);
nsIDOMNode_Release(node);
return TRUE;
}
/* There are no more children in the node. Move to parent. */
nsres = nsIDOMNode_GetParentNode(iter->node, &node);
assert(nsres == NS_OK);
if(!node)
return FALSE;
off = get_child_index(node, iter->node)+1;
free_rangepoint(iter);
init_rangepoint(iter, node, off);
nsIDOMNode_Release(node);
return TRUE;
}
static void get_start_point(HTMLTxtRange *This, rangepoint_t *ret)
{
nsIDOMNode *node;
LONG off;
nsIDOMRange_GetStartContainer(This->nsrange, &node);
nsIDOMRange_GetStartOffset(This->nsrange, &off);
init_rangepoint(ret, node, off);
nsIDOMNode_Release(node);
}
static void get_end_point(HTMLTxtRange *This, rangepoint_t *ret)
{
nsIDOMNode *node;
LONG off;
nsIDOMRange_GetEndContainer(This->nsrange, &node);
nsIDOMRange_GetEndOffset(This->nsrange, &off);
init_rangepoint(ret, node, off);
nsIDOMNode_Release(node);
}
static BOOL is_elem_tag(nsIDOMNode *node, LPCWSTR istag)
{
nsIDOMElement *elem;
@ -236,7 +372,7 @@ static void wstrbuf_append_nodetxt(wstrbuf_t *buf, LPCWSTR str, int len)
*d = 0;
}
static void wstrbuf_append_node(wstrbuf_t *buf, nsIDOMNode *node)
static void wstrbuf_append_node(wstrbuf_t *buf, nsIDOMNode *node, BOOL ignore_text)
{
switch(get_node_type(node)) {
@ -245,6 +381,9 @@ static void wstrbuf_append_node(wstrbuf_t *buf, nsIDOMNode *node)
nsAString data_str;
const PRUnichar *data;
if(ignore_text)
break;
nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
nsAString_Init(&data_str, NULL);
@ -272,7 +411,7 @@ static void wstrbuf_append_node_rec(wstrbuf_t *buf, nsIDOMNode *node)
{
nsIDOMNode *iter, *tmp;
wstrbuf_append_node(buf, node);
wstrbuf_append_node(buf, node, FALSE);
nsIDOMNode_GetFirstChild(node, &iter);
while(iter) {
@ -379,18 +518,6 @@ static nsIDOMNode *prev_node(HTMLTxtRange *This, nsIDOMNode *iter)
return NULL;
}
static nsIDOMNode *get_child_node(nsIDOMNode *node, UINT32 off)
{
nsIDOMNodeList *node_list;
nsIDOMNode *ret = NULL;
nsIDOMNode_GetChildNodes(node, &node_list);
nsIDOMNodeList_Item(node_list, off, &ret);
nsIDOMNodeList_Release(node_list);
return ret;
}
static void get_cur_pos(HTMLTxtRange *This, BOOL start, dompos_t *pos)
{
nsIDOMNode *node;
@ -485,8 +612,7 @@ static inline BOOL dompos_cmp(const dompos_t *pos1, const dompos_t *pos2)
static void range_to_string(HTMLTxtRange *This, wstrbuf_t *buf)
{
nsIDOMNode *iter, *tmp;
dompos_t start_pos, end_pos;
rangepoint_t end_pos, iter;
cpp_bool collapsed;
nsIDOMRange_GetCollapsed(This->nsrange, &collapsed);
@ -497,42 +623,42 @@ static void range_to_string(HTMLTxtRange *This, wstrbuf_t *buf)
return;
}
get_cur_pos(This, FALSE, &end_pos);
get_cur_pos(This, TRUE, &start_pos);
get_end_point(This, &end_pos);
get_start_point(This, &iter);
if(start_pos.type == TEXT_NODE) {
if(start_pos.node == end_pos.node) {
wstrbuf_append_nodetxt(buf, start_pos.p+start_pos.off, end_pos.off-start_pos.off+1);
iter = start_pos.node;
nsIDOMNode_AddRef(iter);
do {
if(iter.type == TEXT_NODE) {
const PRUnichar *str;
nsAString nsstr;
get_text_node_data(iter.node, &nsstr, &str);
if(iter.node == end_pos.node) {
wstrbuf_append_nodetxt(buf, str+iter.off, end_pos.off-iter.off);
nsAString_Finish(&nsstr);
break;
}
wstrbuf_append_nodetxt(buf, str+iter.off, strlenW(str+iter.off));
nsAString_Finish(&nsstr);
}else {
wstrbuf_append_nodetxt(buf, start_pos.p+start_pos.off, strlenW(start_pos.p+start_pos.off));
iter = next_node(start_pos.node);
nsIDOMNode *node;
node = get_child_node(iter.node, iter.off);
if(node) {
wstrbuf_append_node(buf, node, TRUE);
nsIDOMNode_Release(node);
}
}
}else {
iter = start_pos.node;
nsIDOMNode_AddRef(iter);
}
while(iter != end_pos.node) {
wstrbuf_append_node(buf, iter);
tmp = next_node(iter);
nsIDOMNode_Release(iter);
iter = tmp;
}
if(!rangepoint_next_node(&iter)) {
ERR("End of document?\n");
break;
}
}while(!rangepoint_cmp(&iter, &end_pos));
nsIDOMNode_AddRef(end_pos.node);
if(start_pos.node != end_pos.node) {
if(end_pos.type == TEXT_NODE)
wstrbuf_append_nodetxt(buf, end_pos.p, end_pos.off+1);
else
wstrbuf_append_node(buf, end_pos.node);
}
nsIDOMNode_Release(iter);
dompos_release(&start_pos);
dompos_release(&end_pos);
free_rangepoint(&iter);
free_rangepoint(&end_pos);
if(buf->len) {
WCHAR *p;