Jacek Caban : mshtml: Reimplemented IHTMLTxtRange:: moveStart using new range point representation.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Dec 29 15:42:43 CST 2014
Module: wine
Branch: master
Commit: 26dd5f5672c8c03d8df93ffd09ce71534e836c4a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=26dd5f5672c8c03d8df93ffd09ce71534e836c4a
Author: Jacek Caban <jacek at codeweavers.com>
Date: Mon Dec 29 15:49:47 2014 +0100
mshtml: Reimplemented IHTMLTxtRange::moveStart using new range point representation.
---
dlls/mshtml/txtrange.c | 288 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 269 insertions(+), 19 deletions(-)
diff --git a/dlls/mshtml/txtrange.c b/dlls/mshtml/txtrange.c
index c6fba3e..8a3ca9a 100644
--- a/dlls/mshtml/txtrange.c
+++ b/dlls/mshtml/txtrange.c
@@ -238,6 +238,68 @@ static BOOL rangepoint_next_node(rangepoint_t *iter)
return TRUE;
}
+static UINT32 get_child_count(nsIDOMNode *node)
+{
+ nsIDOMNodeList *node_list;
+ UINT32 ret;
+ nsresult nsres;
+
+ nsres = nsIDOMNode_GetChildNodes(node, &node_list);
+ assert(nsres == NS_OK);
+
+ nsres = nsIDOMNodeList_GetLength(node_list, &ret);
+ nsIDOMNodeList_Release(node_list);
+ assert(nsres == NS_OK);
+
+ return ret;
+}
+
+static UINT32 get_text_length(nsIDOMNode *node)
+{
+ nsIDOMText *nstext;
+ UINT32 ret;
+ nsresult nsres;
+
+ nsres = nsIDOMNode_QueryInterface(node, &IID_nsIDOMText, (void**)&nstext);
+ assert(nsres == NS_OK);
+
+ nsres = nsIDOMText_GetLength(nstext, &ret);
+ nsIDOMText_Release(nstext);
+ assert(nsres == NS_OK);
+
+ return ret;
+}
+
+static BOOL rangepoint_prev_node(rangepoint_t *iter)
+{
+ nsIDOMNode *node;
+ UINT32 off;
+ nsresult nsres;
+
+ /* Try to move to the child node. */
+ if(iter->off) {
+ node = get_child_node(iter->node, iter->off-1);
+ assert(node != NULL);
+
+ off = get_node_type(node) == TEXT_NODE ? get_text_length(node) : get_child_count(node);
+ free_rangepoint(iter);
+ init_rangepoint(iter, node, off);
+ 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);
+ free_rangepoint(iter);
+ init_rangepoint(iter, node, off);
+ return TRUE;
+}
+
static void get_start_point(HTMLTxtRange *This, rangepoint_t *ret)
{
nsIDOMNode *node;
@@ -264,6 +326,13 @@ static void get_end_point(HTMLTxtRange *This, rangepoint_t *ret)
nsIDOMNode_Release(node);
}
+static void set_start_point(HTMLTxtRange *This, const rangepoint_t *start)
+{
+ nsresult nsres = nsIDOMRange_SetStart(This->nsrange, start->node, start->off);
+ if(NS_FAILED(nsres))
+ ERR("failed: %08x\n", nsres);
+}
+
static BOOL is_elem_tag(nsIDOMNode *node, LPCWSTR istag)
{
nsIDOMElement *elem;
@@ -693,6 +762,200 @@ HRESULT get_node_text(HTMLDOMNode *node, BSTR *ret)
return hres;
}
+static WCHAR move_next_char(rangepoint_t *iter)
+{
+ rangepoint_t last_space;
+ nsIDOMNode *node;
+ WCHAR cspace = 0;
+ const WCHAR *p;
+
+ do {
+ switch(iter->type) {
+ case TEXT_NODE: {
+ const PRUnichar *str;
+ nsAString nsstr;
+ WCHAR c;
+
+ get_text_node_data(iter->node, &nsstr, &str);
+ p = str+iter->off;
+ if(!*p) {
+ nsAString_Finish(&nsstr);
+ break;
+ }
+
+ c = *p;
+ if(isspaceW(c)) {
+ while(isspaceW(*p))
+ p++;
+
+ if(cspace)
+ free_rangepoint(&last_space);
+ else
+ cspace = ' ';
+
+ iter->off = p-str;
+ c = *p;
+ nsAString_Finish(&nsstr);
+ if(!c) { /* continue to skip spaces */
+ init_rangepoint(&last_space, iter->node, iter->off);
+ break;
+ }
+
+ return cspace;
+ }else {
+ nsAString_Finish(&nsstr);
+ }
+
+ /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
+ if(cspace) {
+ free_rangepoint(iter);
+ *iter = last_space;
+ return cspace;
+ }
+
+ iter->off++;
+ return c;
+ }
+ case ELEMENT_NODE:
+ node = get_child_node(iter->node, iter->off);
+ if(!node)
+ break;
+
+ if(is_elem_tag(node, brW)) {
+ if(cspace) {
+ nsIDOMNode_Release(node);
+ free_rangepoint(iter);
+ *iter = last_space;
+ return cspace;
+ }
+
+ cspace = '\n';
+ init_rangepoint(&last_space, iter->node, iter->off+1);
+ }else if(is_elem_tag(node, hrW)) {
+ nsIDOMNode_Release(node);
+ if(cspace) {
+ free_rangepoint(iter);
+ *iter = last_space;
+ return cspace;
+ }
+
+ iter->off++;
+ return '\n';
+ }
+
+ nsIDOMNode_Release(node);
+ }
+ }while(rangepoint_next_node(iter));
+
+ return cspace;
+}
+
+static WCHAR move_prev_char(rangepoint_t *iter)
+{
+ rangepoint_t last_space;
+ nsIDOMNode *node;
+ WCHAR cspace = 0;
+ const WCHAR *p;
+
+ do {
+ switch(iter->type) {
+ case TEXT_NODE: {
+ const PRUnichar *str;
+ nsAString nsstr;
+ WCHAR c;
+
+ if(!iter->off)
+ break;
+
+ get_text_node_data(iter->node, &nsstr, &str);
+
+ p = str+iter->off-1;
+ c = *p;
+
+ if(isspaceW(c)) {
+ while(p > str && isspaceW(*(p-1)))
+ p--;
+
+ if(cspace)
+ free_rangepoint(&last_space);
+ else
+ cspace = ' ';
+
+ iter->off = p-str;
+ nsAString_Finish(&nsstr);
+ if(p == str) { /* continue to skip spaces */
+ init_rangepoint(&last_space, iter->node, iter->off);
+ break;
+ }
+
+ return cspace;
+ }else {
+ nsAString_Finish(&nsstr);
+ }
+
+ /* If we have a non-space char and we're skipping spaces, stop and return the last found space. */
+ if(cspace) {
+ free_rangepoint(iter);
+ *iter = last_space;
+ return cspace;
+ }
+
+ iter->off--;
+ return c;
+ }
+ case ELEMENT_NODE:
+ if(!iter->off)
+ break;
+
+ node = get_child_node(iter->node, iter->off-1);
+ if(!node)
+ break;
+
+ if(is_elem_tag(node, brW)) {
+ if(cspace)
+ free_rangepoint(&last_space);
+ cspace = '\n';
+ init_rangepoint(&last_space, iter->node, iter->off-1);
+ }else if(is_elem_tag(node, hrW)) {
+ nsIDOMNode_Release(node);
+ if(cspace) {
+ free_rangepoint(iter);
+ *iter = last_space;
+ return cspace;
+ }
+
+ iter->off--;
+ return '\n';
+ }
+
+ nsIDOMNode_Release(node);
+ }
+ }while(rangepoint_prev_node(iter));
+
+ if(cspace) {
+ free_rangepoint(iter);
+ *iter = last_space;
+ return cspace;
+ }
+
+ return 0;
+}
+
+static LONG move_by_chars(rangepoint_t *iter, LONG cnt)
+{
+ LONG ret = 0;
+
+ if(cnt >= 0) {
+ while(ret < cnt && move_next_char(iter))
+ ret++;
+ }else {
+ while(ret > cnt && move_prev_char(iter))
+ ret--;
+ }
+
+ return ret;
+}
+
static WCHAR get_pos_char(const dompos_t *pos)
{
switch(pos->type) {
@@ -1593,33 +1856,20 @@ static HRESULT WINAPI HTMLTxtRange_moveStart(IHTMLTxtRange *iface, BSTR Unit,
switch(unit) {
case RU_CHAR: {
- dompos_t start_pos, end_pos, new_pos;
- cpp_bool collapsed;
+ rangepoint_t start;
- get_cur_pos(This, TRUE, &start_pos);
- get_cur_pos(This, FALSE, &end_pos);
- nsIDOMRange_GetCollapsed(This->nsrange, &collapsed);
+ get_start_point(This, &start);
- if(Count > 0) {
- BOOL bounded;
+ *ActualCount = move_by_chars(&start, Count);
- *ActualCount = move_next_chars(Count, &start_pos, collapsed, &end_pos, &bounded, &new_pos);
- set_range_pos(This, !bounded, &new_pos);
- if(bounded)
- IHTMLTxtRange_collapse(&This->IHTMLTxtRange_iface, FALSE);
- }else {
- *ActualCount = -move_prev_chars(This, -Count, &start_pos, FALSE, NULL, NULL, &new_pos);
- set_range_pos(This, TRUE, &new_pos);
- }
-
- dompos_release(&start_pos);
- dompos_release(&end_pos);
- dompos_release(&new_pos);
+ set_start_point(This, &start);
+ free_rangepoint(&start);
break;
}
default:
FIXME("unimplemented unit %s\n", debugstr_w(Unit));
+ return E_NOTIMPL;
}
return S_OK;
More information about the wine-cvs
mailing list