⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dom2_rangeimpl.cpp

📁 konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版本源码包.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
     *     * The simplest is the start and endContainer is a text node.  The start and end offset is the     * number of characters into the text to remove/truncate.     *     * The next case is the start and endContainer is, well, a container, such a P tag or DIV tag.     * In this case the start and end offset is the number of children into the container to start     * from and end at.     *     * The other cases are different arrangements of the first two.     *     * psuedo code:     *     * if start container is not text:     *     count through the children to find where we start (m_startOffset children)     *     * loop from the start position:     *     if the current node is text, add the text to our variable 'text', truncating/removing if at the end/start.     *          *     if the node has children, step to the first child.     *     if the node has no children but does have siblings, step to the next sibling     *     until we find a sibling, go to next the parent but:     *         make sure this sibling isn't past the end of where we are supposed to go. (position > endOffset and the parent is the endContainer)     *              */        if( m_startContainer == m_endContainer && m_startOffset >= m_endOffset)	return text;        if(n->firstChild()) {	n = n->firstChild();   	int current_offset = m_startOffset;	while(current_offset-- && n) {	    n = n->nextSibling();	}    }        while(n) {        if(n->nodeType() == DOM::Node::TEXT_NODE ||           n->nodeType() == DOM::Node::CDATA_SECTION_NODE) {            DOMString str;            str = static_cast<TextImpl *>(n)->string();	    if( n == m_endContainer || n == m_startContainer)	    	        str = str.copy();  //copy if we are going to modify.            if (n == m_endContainer)                str.truncate(m_endOffset);            if (n == m_startContainer)                str.remove(0,m_startOffset);	    text += str;	    if (n == m_endContainer)                break;        }        	NodeImpl *next = n->firstChild();	if(!next)            next = n->nextSibling();        while( !next && n->parentNode() ) {            if (n == m_endContainer) return text;            n = n->parentNode();            if (n == m_endContainer) return text;            next = n->nextSibling();        }        if(n->parentNode() == m_endContainer) {            if(!next) break;	    unsigned long current_offset = 0;	    NodeImpl *it = n;	    while((it = it->previousSibling())) ++current_offset;	    if(current_offset >= m_endOffset) {	        break;	    }	}        n = next;    }    return text;}DOMString RangeImpl::toHTML( int &exceptioncode ){    bool hasHtmlTag = false;    bool hasBodyTag = false;    //FIXME:  What is this section of code below exactly?  Do I want it here?    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return DOMString();    }    DOMString text = "";    NodeImpl *n = m_startContainer;    int num_tables=0;    bool in_li = false; //whether we have an li in the text, without an ol/ul    int depth_difference = 0;    int lowest_depth_difference = 0;     if( m_startContainer == m_endContainer && m_startOffset >= m_endOffset)	return text;        while(n) {        /* First, we could have an tag <tagname key=value>otherstuff</tagname> */	if(n->nodeType() == DOM::Node::ELEMENT_NODE) {	    int elementId = static_cast<ElementImpl *>(n)->id();            if(elementId == ID_TABLE) num_tables++;	    if(elementId == ID_BODY) hasBodyTag = true;	    if(elementId == ID_HTML) hasHtmlTag = true;	    if(elementId == ID_LI) in_li=true;	    if(num_tables==0 && ( elementId == ID_TD || elementId == ID_TR || elementId == ID_TH || elementId == ID_TBODY || elementId == ID_TFOOT || elementId == ID_THEAD)) num_tables++;	    if(!( !n->hasChildNodes() && (elementId == ID_H1 || elementId == ID_H2 || elementId == ID_H3 || elementId == ID_H4 || elementId ==ID_H5))) {  //Don't add <h1/>  etc.  Just skip these nodes just to make the output html a bit nicer.	       text += static_cast<ElementImpl *>(n)->openTagStartToString(true /*safely expand img urls*/); // adds "<tagname key=value"	       if(n->hasChildNodes()) {	            depth_difference++;   	            text += ">";                } else {          	    text += "/>";	        }	    }	} else         if(n->nodeType() == DOM::Node::TEXT_NODE ||           n->nodeType() == DOM::Node::CDATA_SECTION_NODE) {            if(n->nodeType() == DOM::Node::CDATA_SECTION_NODE) text += "<![CDATA[ ";	    long long startOffset = (n == m_startContainer)?(long long)m_startOffset:-1;	    long long endOffset = (n == m_endContainer)?(long long) m_endOffset:-1;            text += static_cast<TextImpl *>(n)->toString(startOffset, endOffset); //Note this should always work since CDataImpl inherits TextImpl	    if(n->nodeType() == DOM::Node::CDATA_SECTION_NODE) text += " ]]>";	    if(n == m_endContainer) {		    break;	    }        }        if(n->parentNode() == m_endContainer && !n->nextSibling()) {            break;        }        //if (n == m_endContainer) break;        NodeImpl *next = n->firstChild();	if(next) {	    if(n == m_startContainer) {                //This is the start of our selection, so we have to move to where we have started selecting.		//For example, if 'n' is "hello <img src='hello.png'> how are you? <img src='goodbye.png'>"		//then this has four children.  If our selection started on the image, then we need to start from there.		unsigned long current_offset = 0;		while(current_offset < m_startOffset && next) {		    next = next->nextSibling();		    ++current_offset;		}	    }	} else {            next = n->nextSibling();			    if(n->parentNode() == m_endContainer) {	        unsigned long current_offset = 1;	        NodeImpl *it = n;	        while((it = it->previousSibling())) ++current_offset;	        if(current_offset >= m_endOffset) {	            break;	        }	    }	}        while( !next && n->parentNode() ) {            n = n->parentNode();  	    if(n->nodeType() == DOM::Node::ELEMENT_NODE) {  		text += "</";	        text += static_cast<ElementImpl *>(n)->tagName();	        int elementId = static_cast<ElementImpl *>(n)->id();                if(elementId == ID_TABLE) num_tables--;	        depth_difference--;		if(lowest_depth_difference > depth_difference) lowest_depth_difference=depth_difference;	        if(num_tables==0 && ( elementId == ID_TD || elementId == ID_TR || elementId == ID_TH || elementId == ID_TBODY || elementId == ID_TFOOT || elementId == ID_THEAD)) num_tables--;	        if(elementId == ID_OL || elementId == ID_UL) in_li=false; 	        text += ">";	    }            next = n->nextSibling();        }        n = next;    }    	//We have the html in the selection.  But now we need to properly add the opening and closing tags.    //For example say we have:   "Hello <b>Mr. John</b> How are you?"  and we select "John" or even    //"John</b> How"  and copy.  We want to return "<b>John</b>" and "<b>John</b> How" respectively    //To do this, we need to go up the tree from the start, and prepend those tags.    //Imagine our selection was this:    //    //  hello</b></p><p>there    //    //  The difference in depths between the start and end is -1, and the lowest depth    //  difference from the starting point is -2    //      //  So from the start of the selection, we want to go down to the lowest_depth_difference    //  and prepend those tags.  (<p><b>)    //    //  From the end of the selection, we want to also go down to the lowest_depth_difference.    //  We know the depth of the end of the selection - i.e. depth_difference.    //    //      n = m_startContainer;    int startdepth = 0; //by definition - we are counting from zero.    while((n = n->parentNode()) && startdepth>lowest_depth_difference) {      if(n->nodeType() == DOM::Node::ELEMENT_NODE) { //This should always be true.. right? 	  switch (static_cast<ElementImpl *>(n)->id()) {	      case ID_TABLE:		 num_tables--;		 break;	      case ID_BODY:	         hasBodyTag = true;		 break;	      case ID_HTML: 	         hasHtmlTag = true;		 break;	      case ID_LI:		 in_li = true;		 break;	  }          text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text; // prepends "<tagname key=value>"      }      startdepth--;    }    n = m_endContainer;    while( depth_difference>lowest_depth_difference && (n = n->parentNode())) {      if(n->nodeType() == DOM::Node::ELEMENT_NODE) { //This should always be true.. right?	  switch (static_cast<ElementImpl *>(n)->id()) {	      case ID_TABLE:		num_tables++;		break;	      case ID_OL:	      case ID_UL:		in_li=false;		break;	  }	  text += "</";	  text += static_cast<ElementImpl *>(n)->tagName(); 	  text += ">";      }      depth_difference--;    }    // Now our text string is the same depth on both sides, with nothing lower (in other words all the    // tags in it match up.)  This also means that the end value for n in the first loop is a sibling of the    // end value for n in the second loop.    //     // We now need to go down the tree, and for certain tags, add them in on both ends of the text.    // For example, if have:  "<b>hello</b>"  and we select "ll", then we want to go down the tree and     // add "<b>" and "</b>" to it, to produce "<b>ll</b>".    //    // I just guessed at which tags you'd want to keep (bold, italic etc) and which you wouldn't (tables etc).    // It's just wild guessing.  feel free to change.    //    // Note we can carry on with the value of n    if(n) {      while((n = n->parentNode())) {          if(n->nodeType() == DOM::Node::ELEMENT_NODE) { //This should always be true.. right?	      int elementId = static_cast<ElementImpl *>(n)->id();	      switch (elementId) { 	        case ID_TABLE:		case ID_TD:		case ID_TR:		case ID_TH:		case ID_TBODY:		case ID_TFOOT:		case ID_THEAD:		    if(num_tables>0) {		        if(elementId == ID_TABLE) num_tables--;			text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text;			text += "</";			text += static_cast<ElementImpl *>(n)->tagName();			text += ">";		    }		    break;                case ID_LI:		    if(!in_li) break;                    text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text;		    text += "</";		    text += static_cast<ElementImpl *>(n)->tagName();		    text += ">";                    break;		    		case ID_UL:		case ID_OL:		    if(!in_li) break;		    in_li = false;		case ID_B:		case ID_I:		case ID_U:		case ID_FONT:		case ID_S:		case ID_STRONG:		case ID_STRIKE:		case ID_DEL:		case ID_A:		case ID_H1:		case ID_H2:		case ID_H3:		case ID_H4:		case ID_H5:		    //should small, etc be here?   so hard to decide.  this is such a hack :(		    //There's probably tons of others you'd want here.                    text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text;		    text += "</";		    text += static_cast<ElementImpl *>(n)->tagName();		    text += ">";                    break;	      }	    	  }      }    }    if(!hasBodyTag) text = DOMString("<body>") + text + "</body>";    else if(!hasHtmlTag) {       text = DOMString("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"		      "<head>\n"		      "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"		      "<meta name=\"Generator\" content=\"KHTML, the KDE Web Page Viewer\" />\n"		      "</head>\n") +	    text +	    "</html>";    }    text = DOMString("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n") + text;	        return text;}DocumentFragment RangeImpl::createContextualFragment ( const DOMString &html, int &exceptioncode ){   if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return DocumentFragment();    }    if (! m_startContainer->isHTMLElement()) {	exceptioncode = DOMException::NOT_SUPPORTED_ERR;	return DocumentFragment();    }    HTMLElementImpl *e = static_cast<HTMLElementImpl *>(m_startContainer);    DocumentFragment fragment = e->createContextualFragment(html);    if (fragment.isNull()) {	exceptioncode = DOMException::NOT_SUPPORTED_ERR;	return DocumentFragment();    }    return fragment;}void RangeImpl::detach( int &exceptioncode ){    if (m_detached) {        exceptioncode = DOMException::INVALID_STATE_ERR;        return;    }    if (m_startContainer)        m_startContainer->deref();    m_startContainer = 0;    if (m_endContainer)        m_endContainer->deref();    m_endContainer = 0;    m_detached = true;}bool RangeImpl::isDetached() const{    return m_detached;}void RangeImpl::checkNodeWOffset( NodeImpl *n, int offset, int &exceptioncode) const{    if( offset < 0 ) {        exceptioncode = DOMException::INDEX_SIZE_ERR;    }    switch (n->nodeType()) {	case Node::ENTITY_NODE:	case Node::NOTATION_NODE:	case Node::DOCUMENT_TYPE_NODE:            exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;	    break;        case Node::TEXT_NODE:        case Node::COMMENT_NODE:        case Node::CDATA_SECTION_NODE:            if ( (unsigned long)offset > static_cast<CharacterDataImpl*>(n)->length() )                exceptioncode = DOMException::INDEX_SIZE_ERR;            break;        case Node::PROCESSING_INSTRUCTION_NODE:            // ### are we supposed to check with just data or the whole contents?            if ( (unsigned long)offset > static_cast<ProcessingInstructionImpl*>(n)->data().length() )                exceptioncode = DOMException::INDEX_SIZE_ERR;            break;        default:            if ( (unsigned long)offset > n->childNodeCount() )                exceptioncode = DOMException::INDEX_SIZE_ERR;            break;    }}void RangeImpl::checkNodeBA( NodeImpl *n, int &exceptioncode ) const{    // INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an    // Attr, Document or DocumentFragment node or if refNode is a Document,    // DocumentFragment, Attr, Entity, or Notation node.    NodeImpl *root = n;    while (root->parentNode())

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -