コード例 #1
0
void VSpanTextParser::GenerateSpanText( const VTreeTextStyle& inStyles, const VString& inPlainText, VString& outTaggedText, VTextStyle* inDefaultStyle)
{
	sLONG begin, end;
	bool vhasForecolore, vistransparent;
	VString fontName, defaultfontName;
	sLONG vbold,vitalic,vunderline, vstrikeout, vdefaultbold,vdefaultitalic,vdefaultunderline,vdefaultstrikeout;
	Real fontSize, defaultfontSize;
	RGBAColor vforecolor, vdefaultforecolor, vbackcolor, vdefaultbackcolor;
	justificationStyle justification, defaultjustification;
	VTextStyle* uniformStyle = inStyles.GetData();
	
	justification = defaultjustification = JST_Left;

	uniformStyle->GetRange(begin, end);
	fontName = uniformStyle->GetFontName();
	fontSize = uniformStyle->GetFontSize();
	vbold = uniformStyle->GetBold();
	vitalic = uniformStyle->GetItalic();
	vunderline = uniformStyle->GetUnderline();
	vstrikeout = uniformStyle->GetStrikeout();
	vhasForecolore = uniformStyle->GetHasForeColor();
	vistransparent = uniformStyle->GetTransparent();
	vforecolor = uniformStyle->GetColor();
	vbackcolor = uniformStyle->GetBackGroundColor();
	justification = uniformStyle->GetJustification();
	VTreeTextStyle* parenttree = inStyles.GetParent();
	bool hasDefaultForeColor = false;
	bool hasDefaultBackColor = false;

	if(inDefaultStyle)
	{
		defaultfontName = inDefaultStyle->GetFontName();
		defaultfontSize = inDefaultStyle->GetFontSize();
		defaultjustification = inDefaultStyle->GetJustification();
		vdefaultbold = inDefaultStyle->GetBold();
		vdefaultitalic = inDefaultStyle->GetItalic();
		vdefaultunderline = inDefaultStyle->GetUnderline();
		vdefaultstrikeout = inDefaultStyle->GetStrikeout();
		hasDefaultForeColor = inDefaultStyle->GetHasForeColor();
		hasDefaultBackColor = !inDefaultStyle->GetTransparent();
		vdefaultforecolor = inDefaultStyle->GetColor();
		vdefaultbackcolor = inDefaultStyle->GetBackGroundColor();
	}
	else
	{
		defaultfontName = "";
		defaultfontSize = -1;
		vdefaultbold = 0;
		vdefaultitalic = 0;
		vdefaultunderline = 0;
		vdefaultstrikeout = 0;
		defaultjustification = JST_Notset;
	}

	//as we inherit styles from parent, -1 or default value should be assumed equal (otherwise comparison would trigger a useless tag)
	if (vdefaultbold < 0)
		vdefaultbold = 0;
	if (vdefaultitalic < 0)
		vdefaultitalic = 0;
	if (vdefaultunderline < 0)
		vdefaultunderline = 0;
	if (vdefaultstrikeout < 0)
		vdefaultstrikeout = 0;
	if (defaultjustification < 0)
		defaultjustification = JST_Default;

	bool addfontag, addfonsizetag, addboldtag, additalictag, addunderlinetag, addstrikeouttag, addforecolortag, addbackcolortag, addjustificationtag;
	addfontag = addfonsizetag = addboldtag = additalictag = addunderlinetag = addstrikeouttag =  addforecolortag = addbackcolortag = addjustificationtag = false;

	//we pass inherited default style to children to avoid to redefine style already defined by parent node:
	//so current inDefaultStyle always inherits parent styles
	VTextStyle *defaultStyleInherit = inStyles.GetChildCount() > 0 ? new VTextStyle( inDefaultStyle) : NULL;
	if( fontName.GetLength() > 0 && fontName != defaultfontName)
	{
		addfontag = true;
		if (defaultStyleInherit)
			defaultStyleInherit->SetFontName( fontName);
	}
	if( fontSize != -1 && fontSize != defaultfontSize)
	{
		addfonsizetag = true;
		if (defaultStyleInherit)
			defaultStyleInherit->SetFontSize( fontSize);
	}
	if( justification != JST_Notset && justification != defaultjustification)
	{
		addjustificationtag = true;
		if (defaultStyleInherit)
			defaultStyleInherit->SetJustification( justification);
	}
	if( vbold != UNDEFINED_STYLE && vbold != vdefaultbold)
	{
		addboldtag = true;
		if (defaultStyleInherit)
			defaultStyleInherit->SetBold( vbold);
	}

	if( vitalic != UNDEFINED_STYLE  && vitalic != vdefaultitalic)
	{
		additalictag = true;
		if (defaultStyleInherit)
			defaultStyleInherit->SetItalic( vitalic);
	}

	if( vunderline != UNDEFINED_STYLE && vunderline != vdefaultunderline)
	{
		addunderlinetag = true;
		if (defaultStyleInherit)
			defaultStyleInherit->SetUnderline( vunderline);
	}

	if( vstrikeout != UNDEFINED_STYLE && vstrikeout != vdefaultstrikeout)
	{
		addstrikeouttag = true;
		if (defaultStyleInherit)
			defaultStyleInherit->SetStrikeout( vstrikeout);
	}

	if( vhasForecolore && ((!hasDefaultForeColor) || vforecolor != vdefaultforecolor))
	{
		addforecolortag = true;
		if (defaultStyleInherit)
		{
			defaultStyleInherit->SetHasForeColor( vhasForecolore);
			defaultStyleInherit->SetColor( vforecolor);
		}
	}

	if( !vistransparent && ((!hasDefaultBackColor) || vbackcolor != vdefaultbackcolor))
	{
		addbackcolortag = true;
		if (defaultStyleInherit)
		{
			defaultStyleInherit->SetTransparent( false);
			defaultStyleInherit->SetBackGroundColor( vbackcolor);
		}
	}

	bool addtag = addfontag || addfonsizetag || addboldtag || additalictag || addunderlinetag || addstrikeouttag || addforecolortag || addbackcolortag || addjustificationtag;

	bool isInitialEmpty = outTaggedText.IsEmpty();
	if(addtag)
	{
		bool addcoma = false;
		outTaggedText += "<SPAN STYLE=\"";
	
		if(addfontag)
		{
			outTaggedText += MS_FONT_NAME;
			outTaggedText += ":'";
			outTaggedText += fontName + "'";
			addcoma = true;
		}

		if(addfonsizetag)
		{
			VString strFontSize;
			//we need to convert from 72dpi font size to the desired dpi (screen dpi for v12 compatibility)
#if VERSIONWIN
			strFontSize.FromReal(floor(fontSize*72.0f/VSpanTextParser::Get()->GetDPI()+0.5f));
#else
			strFontSize.FromReal(fontSize);
#endif
			if(addcoma)
				outTaggedText+=";";
			outTaggedText += MS_FONT_SIZE ;
			outTaggedText += ":";
			outTaggedText += strFontSize;
			outTaggedText += "pt";
			addcoma = true;
		}
		
		if(addjustificationtag)
		{
			VString value;
			JustificationToString(justification,value);
			if(addcoma)
				outTaggedText+=";";
			outTaggedText += MS_JUSTIFICATION;
			outTaggedText += ":";
			outTaggedText += value;
			addcoma = true;
		}

		if(addboldtag)
		{
			VString value;
			if(addcoma)
				outTaggedText+=";";
			vbold ? value = "bold" : value = "normal";
			outTaggedText += MS_BOLD ;
			outTaggedText += ":" + value;
			addcoma = true;
		}

		if(additalictag)
		{
			VString value;
			if(addcoma)
				outTaggedText+=";";
			vitalic ? value = "italic" : value = "normal";
			outTaggedText += MS_ITALIC ;
			outTaggedText += ":"+ value;
			addcoma = true;
		}

		if(addunderlinetag && addstrikeouttag)
		{
			VString value;
			if(addcoma)
				outTaggedText+=";";
			if(!vunderline && !vstrikeout)
				value = "none";
			if(vunderline && vstrikeout)
				value = "underline line-through";
			else if(vunderline)
				value = "underline";
			else if(vstrikeout)
				value = "line-through";				
			outTaggedText += MS_UNDERLINE ;
			outTaggedText += ":"+ value;
			addcoma = true;
		}
		else
		{
			if(addunderlinetag)
			{
				VString value;
				if(addcoma)
					outTaggedText+=";";
				vunderline ? value = "underline" : value = "none";
				outTaggedText += MS_UNDERLINE ;
				outTaggedText += ":"+ value;
				addcoma = true;
			}
					
			if(addstrikeouttag)
			{
				VString value;
				if(addcoma)
					outTaggedText+=";";
				vstrikeout ? value = "line-through" : value = "none";
				outTaggedText += MS_UNDERLINE ;
				outTaggedText += ":"+ value;
				addcoma = true;
			}
		}

		if(addforecolortag)
		{
			VString value;
			if(addcoma)
				outTaggedText+=";";
			ColorToValue(vforecolor,value);
			outTaggedText += MS_COLOR;
			outTaggedText += ":"+ value;
			addcoma = true;
		}

		if(addbackcolortag)
		{
			VString value;
			if(addcoma)
				outTaggedText+=";";
			ColorToValue(vbackcolor,value);
			outTaggedText += MS_BACKGROUND;
			outTaggedText += ":"+ value;
			addcoma = true;
		}

		outTaggedText +="\">";				

	}

	
	VString text;
	VString tmp;

	sLONG count = inStyles.GetChildCount();

	//prevent assert in GetSubString
	if (end > inPlainText.GetLength())
		end = inPlainText.GetLength();
	if (begin > inPlainText.GetLength())
		begin = inPlainText.GetLength();

	if(count == 0)
	{
		if(end>begin)
		{
			inPlainText.GetSubString(begin+1, end-begin, text);
			ToXMLCompatibleText(text, tmp);
			outTaggedText += tmp;
		}
	}
	else
	{
		sLONG start = begin;
		for(sLONG i = 1; i <= count; i++)
		{
			VTreeTextStyle* child = inStyles.GetNthChild(i);
			sLONG b,e;
			child->GetData()->GetRange(b,e);

			//prevent assert in GetSubString
			if (e > inPlainText.GetLength())
				e = inPlainText.GetLength();
			if (b > inPlainText.GetLength())
				b = inPlainText.GetLength();

			//if(start < b-1)
			if(start < b)
			{
				inPlainText.GetSubString(start+1, b-start, text);
				ToXMLCompatibleText(text, tmp);
				outTaggedText += tmp;
			}
			
			GenerateSpanText(*child, inPlainText, outTaggedText, defaultStyleInherit);
			start = e;
		}
		
		if(start < end)
		{
			inPlainText.GetSubString(start+1, end-start, text);
			ToXMLCompatibleText(text, tmp);
			outTaggedText += tmp;
		}

	}

	if (addtag)
		outTaggedText +="</SPAN>";
	//JQ 24/12/2012: ensure tagged text is bracketed with SPAN tag
	else if (isInitialEmpty)
	{
		if (!outTaggedText.BeginsWith(CVSTR("<SPAN"), true))
			outTaggedText = CVSTR("<SPAN>")+outTaggedText+CVSTR("</SPAN>");
	}

	if (defaultStyleInherit)
		delete defaultStyleInherit;
}
コード例 #2
0
void VHTMLSyntax::GetSuggestions( ICodeEditorDocument* inDocument, sLONG inLineNumber, sLONG inPos, ITipInfoArray *outSuggestions, sLONG& outStartOffset, bool inAll )
{
	// Get the text for the line up to the point of insertion, and we'll lex that to see if we can come up 
	// with some rational suggestions for the user.
	VString xstr;
	inDocument->GetLine( inLineNumber, xstr );
	xstr.Truncate( inPos );

	char *lexinput = CreateUTF8String( xstr );
	struct htmlLexeme *list = parseHTML( lexinput );

	// Gin up some line params for tracking state information
	VLineSyntaxParams *currentLineParams = currentLineParams = new VLineSyntaxParams();
	if (inLineNumber > 0) {
		// We're starting where we left off on the previous line
		currentLineParams->CopyState( static_cast< VLineSyntaxParams * >( inDocument->GetLineSyntaxParams( inLineNumber - 1 ) ) );
	}

	// Given the list of HTML tokens, let's walk over the list and try to make some sense
	// of them.  Walk over the list one token at a time, and see if we can make sense of 
	// what we've got.  This is going to be awfully similar to the way we do things in the
	// SetLine method, except that we're not actually updating the line state for the current
	// line.  Instead, we're working on a copy of the existing information.
	struct htmlLexeme *cur = list;
	int lastTokenProcessed = 0;
	while (cur) {
		if (kKeyword == cur->fStyle) {
			lastTokenProcessed = 3;

			// Keywords a bit trickier than you might think because we need to be sure they're actually part of a
			// tag.  If the user types something like: <b>This table rocks</b>, we only want to highlight the b in the
			// begin and end tag, and not the "table" in the user's text.  To deal with this, we have an "in tag" flag
			// that basically turns keyword highlighting on and off.
			if (currentLineParams->IsProcessingTag()) {
				// If we're processing an opening tag, then we want to push the keyword onto the tag stack.  But if we're
				// processing a closing tag, then we want to pop the last keyword off the tag stack and try to match it up
				// to what we just processed.  If they match, we're golden.  If not, we just assume the user's mismatching
				// their tags because they're an idiot.
				VString tagName;
				xstr.GetSubString( cur->fOffset + 1, cur->fLength, tagName );

				if (currentLineParams->IsProcessingStartTag()) {
					currentLineParams->PushTag( tagName );

					// Note that we are no longer processing the start of a tag.  This allows us to handle attributes
					// separately from the tag itself.
					currentLineParams->SetIsProcessingStartTag( false );
				} else {
					VString lastTag;
					currentLineParams->PopTag( lastTag );

					if (!lastTag.EqualTo( tagName, false )) {
						// The tags don't match, so we're just going to ignore the issue
						// TODO: do something more sensible here
					}
				}
			}
		} else if (kTagOpen == cur->fStyle || kEndTagOpen == cur->fStyle) {
			lastTokenProcessed = (kTagOpen == cur->fStyle) ? 1 : 2;

			currentLineParams->SetIsProcessingTag( true );
			currentLineParams->SetIsProcessingStartTag( kTagOpen == cur->fStyle );
		} else if (kTagClose == cur->fStyle || kTagSelfClose == cur->fStyle) {
			lastTokenProcessed = 0;

			currentLineParams->SetIsProcessingTag( false );

			// If we just handled a self-closing tag (like <br />), then we want to pop it from the stack
			// TODO: some tags can't have matching pairs, like <br>, so even if it's not self-closing, we want
			// to pop it off the tag stack.  Handle that here
			if (kTagSelfClose == cur->fStyle) {
				VString toss;
				currentLineParams->PopTag( toss );
			}
		} else {
			lastTokenProcessed = 0;
		}

		cur = cur->fNext;
	}

	if (lastTokenProcessed == 1) {
		// We processed a tag opener, but no keyword for the tag.  So let's make a bunch of suggestions!
	} else if (lastTokenProcessed == 2) {
		// We processed a tag closer, but no keyword for the tag.  Grab the last opened tag from the list
		// and suggest it as the closer
		VString suggestion;
		currentLineParams->LastTag( suggestion );
		outSuggestions->AddTip( new VCodeEditorTipInfo( inDocument, suggestion, htmlcolorShadow[ keyword_col ] ) );
	}

	delete currentLineParams;
	FreeLexemeList( list );
}
コード例 #3
0
/** parse span text element or XHTML fragment 
@param inTaggedText
	tagged text to parse (span element text only if inParseSpanOnly == true, XHTML fragment otherwise)
@param outStyles
	parsed styles
@param outPlainText
	parsed plain text
@param inParseSpanOnly
	true (default): only <span> element(s) with CSS styles are parsed
	false: all XHTML text fragment is parsed (parse also mandatory HTML text styles)
*/
void VSpanTextParser::ParseSpanText( const VString& inTaggedText, VTreeTextStyle*& outStyles, VString& outPlainText, bool inParseSpanOnly)
{
	outPlainText = "";
	if(outStyles)
		outStyles->Release();
	outStyles = NULL;
	if (inTaggedText.IsEmpty())
		return;
	//fixed ACI0076343: for compatibility with older bases which do not have support for multistyle var or field
	//					we need to convert to xml text the text which is not bracketed with SPAN 
	//					otherwise parser would fail
	VString vtext;
	sLONG posStartSPAN = 1; //pos of first SPAN tag
	sLONG posEndSPAN = inTaggedText.GetLength()+1; //pos of character following ending SPAN tag
	if (inParseSpanOnly)
	{
		//search for opening SPAN tag
		posStartSPAN = inTaggedText.Find("<SPAN", 1, false);
		if (!posStartSPAN)
		{
			//convert full text to xml
			inTaggedText.GetXMLString( vtext, XSO_Default); 
			vtext = VString("<SPAN>")+vtext+"</SPAN>";
		}
		else 
		{
			VString before, after;
			if (posStartSPAN > 1)
			{
				//convert to XML text preceeding first SPAN 
				VString temp;
				inTaggedText.GetSubString( 1, posStartSPAN-1, temp);
				temp.GetXMLString( before, XSO_Default);
			}
			//search for ending SPAN tag
			const UniChar *c = inTaggedText.GetCPointer()+inTaggedText.GetLength()-1;
			sLONG pos = inTaggedText.GetLength()-1;
			VString spanEndTag = "</SPAN>";
			VString spanEndTag2 = "</span>";
			do
			{
				while (pos >= 0 && *c != '>')
				{
					pos--;
					if (pos >= 0)
						c--;
				}
				if (pos >= 0)
				{
					if (memcmp( (void*)(c+1-spanEndTag.GetLength()), spanEndTag.GetCPointer(), spanEndTag.GetLength()*sizeof(UniChar)) == 0
						||
						memcmp( (void*)(c+1-spanEndTag2.GetLength()), spanEndTag2.GetCPointer(), spanEndTag2.GetLength()*sizeof(UniChar)) == 0)
					{
						posEndSPAN = pos+2;
						break;
					}	
					else
					{
						pos--;
						if (pos >= 0)
							c--;
					}
				}
			} while (pos >= 0);
			if (posEndSPAN <= inTaggedText.GetLength())
			{
				//convert to XML text following ending SPAN tag
				VString temp;
				inTaggedText.GetSubString( posEndSPAN, inTaggedText.GetLength()-posEndSPAN+1, temp);
				temp.GetXMLString( after, XSO_Default);
			}
			if (!before.IsEmpty() || !after.IsEmpty())
			{
				inTaggedText.GetSubString( posStartSPAN, posEndSPAN-posStartSPAN, vtext);
				vtext = VString("<SPAN>")+before+vtext+after+"</SPAN>";
			}
			else
				vtext = VString("<SPAN>")+inTaggedText+"</SPAN>";
		}
	}
	else
		vtext = inTaggedText;

	vtext.ExchangeAll(0x0B,0x0D);//[MI] le 28/12/2010 ACI0069253
#if VERSIONWIN
	vtext.ConvertCarriageReturns(eCRM_CR); //important here on Windows before parsing because styles are assumed to use one character size for line ending on any platform 
										   //and so pair of 0x0D 0x0A should be treated as a single 0x0D character
#endif											
	VTaggedTextSAXHandler vsaxhandler(outStyles, &outPlainText, inParseSpanOnly);
	VXMLParser vSAXParser;

	vSAXParser.Parse(vtext, &vsaxhandler, XML_ValidateNever);

#if VERSIONWIN
	outPlainText.ConvertCarriageReturns(eCRM_CR); //we need to convert to CR (on any platform but Linux here) because xerces parser has converted all line endings to LF (cf W3C XML line ending uniformization while parsing)
#elif VERSIONMAC
	outPlainText.ConvertCarriageReturns(eCRM_CR); //we need to convert to CR (on any platform but Linux here) because xerces parser has converted all line endings to LF (cf W3C XML line ending uniformization while parsing)
#endif
}
コード例 #4
0
void VHTMLSyntax::SetLine( ICodeEditorDocument *inDocument, sLONG inLineNumber, bool inLoading )
{
#if 0
	VString source;
	inDocument->GetLine( inLineNumber, source );
	
	HTMLParser parser;
	HTMLParser::State *state = NULL;
	HTMLParser::State *prevLineState = NULL;
	if (inLineNumber > 0)	prevLineState = GetStateForLine( inDocument, inLineNumber - 1 );
	ParsingCookie *cookie = new ParsingCookie( inDocument, inLineNumber );
	parser.Parse( source, prevLineState, &state, this, (const void *)cookie );
	SetStateForLine( inDocument, inLineNumber, state );
	cookie->Release();
#else
	// Get the params for the current line so that we can set them up properly
	VLineSyntaxParams *currentLineParams = static_cast< VLineSyntaxParams * >( inDocument->GetLineSyntaxParams( inLineNumber ) );
	if (!currentLineParams) {
		currentLineParams = new VLineSyntaxParams();
		inDocument->AssignLineSyntaxParams( inLineNumber, currentLineParams );
	}
	bool previousOpenCommentState = currentLineParams->IsOpenComment();

	// We also want the params for the preceeding line, in case we're the continuation of
	// a comment.
	VLineSyntaxParams *previousLineParams = NULL;
	if (inLineNumber > 0) {
		previousLineParams = static_cast< VLineSyntaxParams * >( inDocument->GetLineSyntaxParams( inLineNumber - 1 ) );
	}

	VString xstr;
	inDocument->GetLine(inLineNumber,xstr);
	inDocument->SetLineStyle(inLineNumber,0,xstr.GetLength(),0);		//initiate the line

	char *lexinput = CreateUTF8String( xstr );
	struct htmlLexeme *list = parseHTML( lexinput );

	// If we used to be in comment continuation mode, the assumption is that we're still in 
	// comment continuation mode.  We'll switch this off if the comment ends though
	currentLineParams->CopyState( previousLineParams );

	// We are going to keep track of which open and close tags we've seen on the line.  This allows
	// us to determine which unmatched open and close tags exist so we can associate that data with
	// the line.  As we find open tags, we'll push them onto the open tag list.  As we find close tags,
	// we will scan the open tag list and *remove* any that match.  If there's no match, then we'll add
	// the tag to the close list.
	std::vector< VString > openList, closeList;

	// Given the list of HTML tokens, let's walk over the list and try to make some sense
	// of them.  Walk over the list one token at a time, and see if we can make sense of 
	// what we've got.
	struct htmlLexeme *cur = list;
	while (cur) {
		// There are only three types of comments we need to worry about.  Full comments, 
		// open comments and close comments.  We'll get a token representing any one of the
		// three.  However, we need to pay special attention to multi-line comments, since
		// they won't lex out entirely correct.  If the previous line was part of an open
		// comment, then we want to keep walking over the tokens, marking them as part of
		// the comment, until we run out of tokens, or we find a kCommentClose token.
		if (currentLineParams->IsOpenComment()) {
			if (kCommentClose == cur->fStyle) {
				// We found the end of the comment, so we can highlight it appropriately, 
				// and go back to our regularly scheduled lexing
				inDocument->SetLineStyle( inLineNumber, cur->fOffset, cur->fOffset + cur->fLength, htmlcolorShadow[ comment_col ] );

				// We're also done being a part of the comment continuation train
				currentLineParams->SetIsOpenComment( false );
			} else {
				// This is just another part of the comment
				inDocument->SetLineStyle( inLineNumber, cur->fOffset, cur->fOffset + cur->fLength, htmlcolorShadow[ comment_col ] );
			}
			// Advance
			cur = cur->fNext;
			continue;
		}
		if (kCompleteComment == cur->fStyle) {
			// A complete comment is the easiest of the three cases.  Just highlight it
			inDocument->SetLineStyle( inLineNumber, cur->fOffset, cur->fOffset + cur->fLength, htmlcolorShadow[ comment_col ] );
		} else if (kCommentOpen == cur->fStyle) {
			// An open comment must be the last token in the list
			xbox_assert( !cur->fNext );

			// We want to highlight from here to the end of the line
			inDocument->SetLineStyle( inLineNumber, cur->fOffset, cur->fOffset + cur->fLength, htmlcolorShadow[ comment_col ] );
			// We also want to flag that this line ends with an open comment
			currentLineParams->SetIsOpenComment( true );
		} else if (kCommentClose == cur->fStyle) {
			// If we got a close comment token, then something's off.  That means the user put in a close comment
			// token, but they never opened it.  We're going to ignore that state, and flag this as being normal
			inDocument->SetLineStyle( inLineNumber, cur->fOffset, cur->fOffset + cur->fLength, htmlcolorShadow[ scommentend_col ] );
		} else if (kString == cur->fStyle) {
			inDocument->SetLineStyle( inLineNumber, cur->fOffset, cur->fOffset + cur->fLength, htmlcolorShadow[ string_col ] );
		} else if (kKeyword == cur->fStyle) {
			// Keywords a bit trickier than you might think because we need to be sure they're actually part of a
			// tag.  If the user types something like: <b>This table rocks</b>, we only want to highlight the b in the
			// begin and end tag, and not the "table" in the user's text.  To deal with this, we have an "in tag" flag
			// that basically turns keyword highlighting on and off.
			if (currentLineParams->IsProcessingTag()) {
				inDocument->SetLineStyle( inLineNumber, cur->fOffset, cur->fOffset + cur->fLength, htmlcolorShadow[ keyword_col ] );

				// If we're processing an opening tag, then we want to push the keyword onto the tag stack.  But if we're
				// processing a closing tag, then we want to pop the last keyword off the tag stack and try to match it up
				// to what we just processed.  If they match, we're golden.  If not, we just assume the user's mismatching
				// their tags because they're an idiot.
				VString tagName;
				xstr.GetSubString( cur->fOffset + 1, cur->fLength, tagName );

				if (currentLineParams->IsProcessingStartTag()) {
					if (!IsTagWithoutClose( tagName )) {
						openList.push_back( tagName );
					}
					currentLineParams->PushTag( tagName );

					// Note that we are no longer processing the start of a tag.  This allows us to handle attributes
					// separately from the tag itself.
					currentLineParams->SetIsProcessingStartTag( false );
				} else {
					// Check to see if this closed tag is on the open list.  If it is, we want to remove it from the
					// list.  Otherwise, we want to add it to the close list.
					bool bAddToClose = true;
					for (std::vector< VString >::iterator iter = openList.begin(); bAddToClose && iter != openList.end();) {
						if (tagName.EqualTo( *iter, false )) {
							iter = openList.erase( iter );
							bAddToClose = false;
						} else {
							++iter;
						}
					}
					if (bAddToClose)	closeList.push_back( tagName );

					VString lastTag;
					currentLineParams->PopTag( lastTag );

					if (!lastTag.EqualTo( tagName, false )) {
						// The tags don't match, so we're just going to ignore the issue
						// TODO: do something more sensible here
					}
				}
			}
		} else if (kNumber == cur->fStyle) {
			inDocument->SetLineStyle( inLineNumber, cur->fOffset, cur->fOffset + cur->fLength, htmlcolorShadow[ allnum_col ] );
		} else if (kTagOpen == cur->fStyle || kEndTagOpen == cur->fStyle) {
			currentLineParams->SetIsProcessingTag( true );
			currentLineParams->SetIsProcessingStartTag( kTagOpen == cur->fStyle );
		} else if (kTagClose == cur->fStyle || kTagSelfClose == cur->fStyle) {
			currentLineParams->SetIsProcessingTag( false );

			// If we just handled a self-closing tag (like <br />), then we want to pop it from the stack
			VString lastTag;
			currentLineParams->LastTag( lastTag );
			if (kTagSelfClose == cur->fStyle || IsTagWithoutClose( lastTag )) {
				VString toss;
				currentLineParams->PopTag( toss );

				// We also do not want to add it to our list of open tags for the line, since it's self-closed
				for (std::vector< VString >::iterator iter = openList.begin(); iter != openList.end(); ++iter) {
					if (lastTag.EqualTo( *iter, false )) {
						iter = openList.erase( iter );
						break;
					}
				}
			}
		}

		cur = cur->fNext;
	}
	FreeLexemeList( list );

	// Now that we have an open and a close list, we want to associate them with the line.
	for (std::vector< VString >::iterator iter = openList.begin(); iter != openList.end(); ++iter) {
		currentLineParams->AddUnmatchedOpenTag( *iter );
	}
	for (std::vector< VString >::iterator iter = closeList.begin(); iter != closeList.end(); ++iter) {
		currentLineParams->AddUnmatchedCloseTag( *iter );
	}

	// There are two cases we really need to care about.  If the line now ends in
	// an open comment (and didn't used to), we want to colorize down the document.
	// Also, if the line no longer ends in an open comment (but used to), we want to
	// colorize down the document.  In either case, we want to keep colorizing subsequent
	// lines until the comment is ended or the end of the document is reached.
	if ((!previousOpenCommentState && currentLineParams->IsOpenComment() ||		// Now ends with open comment, didn't used to
		previousOpenCommentState && !currentLineParams->IsOpenComment()) &&		// Used to end with an open comment, but no longer does
		inLineNumber + 1 < inDocument->GetNbLines()) {
		SetLine( inDocument, inLineNumber + 1, inLoading );
	}
#endif // old code
}