www.pudn.com > pueblo.zip > ChHtmSym.cpp


/*---------------------------------------------------------------------------- 
                        _                              _ _        
        /\             | |                            | (_)       
       /  \   _ __   __| |_ __ ___  _ __ ___   ___  __| |_  __ _  
      / /\ \ | '_ \ / _` | '__/ _ \| '_ ` _ \ / _ \/ _` | |/ _` | 
     / ____ \| | | | (_| | | | (_) | | | | | |  __/ (_| | | (_| | 
    /_/    \_\_| |_|\__,_|_|  \___/|_| |_| |_|\___|\__,_|_|\__,_| 
 
    The contents of this file are subject to the Andromedia Public 
	License Version 1.0 (the "License"); you may not use this file 
	except in compliance with the License. You may obtain a copy of 
	the License at http://www.andromedia.com/APL/ 
 
    Software distributed under the License is distributed on an 
	"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 
	implied. See the License for the specific language governing 
	rights and limitations under the License. 
 
    The Original Code is Pueblo client code, released November 4, 1998. 
 
    The Initial Developer of the Original Code is Andromedia Incorporated. 
	Portions created by Andromedia are Copyright (C) 1998 Andromedia 
	Incorporated.  All Rights Reserved. 
 
	Andromedia Incorporated                         415.365.6700 
	818 Mission Street - 2nd Floor                  415.365.6701 fax 
	San Francisco, CA 94103 
 
    Contributor(s): 
	-------------------------------------------------------------------------- 
	   Chaco team:  Dan Greening, Glenn Crocker, Jim Doubek, 
	                Coyote Lussier, Pritham Shetty. 
 
					Wrote and designed original codebase. 
 
------------------------------------------------------------------------------ 
 
	This file consists of the implementation of the ChHtmWnd  class. 
	Formas implementation 
 
----------------------------------------------------------------------------*/ 
 
#include "headers.h" 
 
#include  
 
#ifdef CH_UNIX 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#endif 
 
#include "ChHtmlView.h" 
 
#include "ChHtmSym.h" 
#include "ChHtmlParser.h" 
 
 
/*---------------------------------------------------------------------------- 
	Constants 
----------------------------------------------------------------------------*/  
 
 
 
CH_GLOBAL_VAR  SymbolMap aHtmlTokens[] = 
{ 
	{ "!unknown", HTML_UNKNOWN 	},	// style for unknown tags 
 
	{ "h1",	HTML_H1	},				// heading 1 
	{ "h2",	HTML_H2 },		// heading 2 
	{ "h3",	HTML_H3	},				// heading 3 
	{ "h4", HTML_H4	},		// heading 4 
	{ "h5",	HTML_H5	},				// heading 5 
	{ "h6",	HTML_H6	},		// heading 6 
 
	{ "blockquote",	HTML_BLKQUOTE	}, // blockquote 
	{ "address", HTML_ADDRESS			},	// address 
	{ "p",	HTML_PARAGRAPH			},	// paragraph 
	{ "!",	HTML_COMMENT			}, // comments},	 
	{ "pre", HTML_PREFORMAT				},	// preformat text 
	 
	{ "ul",	HTML_BULLETLINE			},	// bulleted list 
	{ "ol",	HTML_NUMLIST			},	// numbered list 
	{ "dl",	HTML_DEFNLIST			},	// Definition list 
	{ "dir", HTML_DIR				},	// directory list of items 
 
	{ "menu",	HTML_MENU			},	// menu : we render it as dir 
	 
	{ "quote",	HTML_QUOTE		},	// quoted text 
 
	{ "strike",	HTML_STRIKETHROUGH		},	// strikethrough 
 	{ "b",	HTML_BOLD			},	// bold 
	{ "i", 	HTML_ITALIC			},	// italic 
	{ "u",	HTML_UNDERLINE			},	// underline 
 
	{ "tt",	HTML_TYPEWRITER			},	// typewriter font 
 
	{ "em",	HTML_EMPHASIS			},	// emphasis 
	{ "cite", HTML_CITE				},	// citation 
	{ "strong",	HTML_STRONG		},	// stronger emphasis 
 
	{ "code",   HTML_CODE		},	// HTML directive 
	{ "samp",	HTML_SAMP			},	// sample output 
 
	{ "hr",	HTML_HORZRULE			},	// embedded line 
 
	{ "br",	HTML_LINEBREAK			},	// Line break  
 
	{ "li",	HTML_LINEITEM			},	// non-wraped line 
 
	{ "a",	HTML_LINK			},	// Link 
 
	{ "dd",	HTML_DEFNTEXT			},	// definition text 
	{ "dt",	HTML_DEFNTERM			},	// definiton term 
 
	{ "center",	HTML_CENTER		},	// center text 
 
	{ "html",	HTML_HTML			},	// html 
	{ "head",	HTML_HEAD			},// head 
 	{ "body",HTML_BODY				},	// body 
 	{ "title", HTML_TITLE 			},	// title 
	{ "xch_page",	HTML_PAGE		},	// reformat page 
	{ "xch_prefetch", HTML_PREFETCH	},	// prefetch tag 
 	{ "img",	HTML_IMAGE			},	// Image 
 
	{ "basefont",	HTML_BASEFONT		},	// basefont : Netscape additions 
	{ "font",	HTML_FONT			},	// font 
 
	{ "form",	HTML_FORM			},	// form 
	{ "input",	HTML_INPUT		},	// input control 
	{ "option",	HTML_OPTION		},	// options for form items 
	{ "select",	HTML_SELECT		},	// multiple choice items 
	{ "textarea",	HTML_TEXTAREA		},	// multiline text control	 
 
	{ "xch_mudtext",	HTML_MUDTEXT	},	// mud text extension		 
 
	{ "xmp",	HTML_XMP			},	// alternate to plaintext 
 
	{ "listing",	HTML_LISTING		},	// alternate to plaintext 
	{ "plaintext",	HTML_PLAINTEXT	},	// unformatted text 
	{ "nobr",	HTML_NOBR	},	// unformatted text 
	{ "base",	HTML_BASE	},	// unformatted text 
	{ "xch_pane",	HTML_XCHPANE	},	// chaco pane tag 
	{ "embed",	HTML_EMBED	},	// chaco pane tag 
}; 
 
 
 
											/* Argument map table, this table 
												shows all the arguments that 
												are processed for HTML tags. 
												Any arguments not in this list 
												are ignored. */ 
CH_GLOBAL_VAR  SymbolMap aArguments[] = 
						{ 
							{ "align",		ARG_ALIGN }, 
							{ "size",		ARG_SIZE }, 
							{ "width",  	ARG_WIDTH}, 
							{ "height", 	ARG_HEIGHT}, 
							{ "href",		ARG_HREF}, 
							{ "src",		ARG_SRC}, 
							{ "clear",		ARG_CLEAR}, 
							{ "xch_cmd",	ARG_XCMD}, 
							{ "type",		ARG_TYPE }, 
							{ "text",   	ARG_TXTCOLOR }, 
							{ "fgcolor", 	ARG_FGCOLOR }, 
							{ "bgcolor", 	ARG_BGCOLOR }, 
							{ "link",    	ARG_LINK }, 
							{ "vlink", 		ARG_VLINK }, 
							{ "action",  	ARG_ACTION }, 
							{ "method",  	ARG_METHOD }, 
							{ "enctype", 	ARG_ENCTYPE }, 
							{ "disabled", 	ARG_DISABLED }, 
							{ "selected", 	ARG_SELECTED }, 
							{ "value", 	  	ARG_VALUE }, 
							{ "checked", 	ARG_CHECKED }, 
							{ "maxlength", 	ARG_MAXLENGTH }, 
							{ "name", 	  	ARG_NAME }, 
							{ "multiple", 	ARG_MULTIPLE }, 
							{ "rows", 	  	ARG_ROWS }, 
							{ "cols", 	  	ARG_COLS }, 
							{ "start", 	  	ARG_START}, 
							{ "xch_world", 	ARG_XWORLD}, 
							{ "xch_prob", 	ARG_XPROBABLITY }, 
							{ "alink",		ARG_ALINK }, 
							{ "xplink",		ARG_PLINK }, 
							{ "hspace",		ARG_HSPACE }, 
							{ "vspace",		ARG_VSPACE }, 
							{ "ismap",		ARG_ISMAP }, 
							{ "background",	ARG_BACKGROUND }, 
							{ "border",		ARG_BORDER }, 
							{ "noshade",	ARG_NOSHADE }, 
							{ "nowrap",		ARG_NOWRAP }, 
							{ "target",  	ARG_TARGET	}, 
							{ "panetitle", 	ARG_PANETITLE	}, 
							{ "minwidth",  	ARG_MINWIDTH	}, 
							{ "minheight", 	ARG_MINHEIGHT	}, 
							{ "options",  	ARG_OPTIONS	}, 
							{ "alignto",  	ARG_ALIGNTO	}, 
							{ "scrolling",  ARG_SCROLLING	}, 
							{ "xch_graph",  ARG_XGRAPH	}, 
							{ "md5",		ARG_MD5 }, 
							{ "color",		ARG_COLOR }, 
 
 
						}; 
 
 
// Possible pre-defined values attributes 
 
CH_GLOBAL_VAR SymbolMap aAttrValueMap[] = 
{ 
	{ "1",  		VAL_NUM },			// default numbers	 1, 2, 3 
	{ "A",			VAL_CHARUPPER },	// capital letters 
	{ "a",			VAL_CHARLOWER },	// small letters 
	{ "I",			VAL_ROMANBIG },		// large roman 
	{ "i", 			VAL_ROMANSMALL },	// small roman 
	{ "disc",		VAL_DISC },			// disc 
	{ "circle",		VAL_CIRCLE },		// circle 
	{ "square",		VAL_SQUARE },		// square 
	{ "checkbox",	VAL_CHECKBOX },		// checkbox 
	{ "hidden",		VAL_HIDDEN },		// hidden control 
	{ "image",		VAL_IMAGE },		// image 
	{ "radio",		VAL_RADIO },		// radio button 
	{ "reset",		VAL_RESET },		// reset 
	{ "submit",		VAL_SUBMIT },		// submit 
	{ "password",	VAL_PASSWORD },		// password 
	{ "text",		VAL_TEXT },			// edittext 
	{ "left",		VAL_LEFT },			// left 
	{ "right", 		VAL_RIGHT },		// right 
	{ "center", 	VAL_CENTER },		// center 
	{ "all",		VAL_CLEAR_ALL },	// clear all 
	{ "links",		VAL_CLEAR_LINK },	// clear links 
	{ "indent",		VAL_INDENT },		// indent 
	{ "middle",		VAL_MIDDLE },		// middle 
	{ "absmiddle",	VAL_ABSMIDDLE },	// abs middle 
	{ "post",		VAL_POST },			// post method 
	{ "get",		VAL_GET },	 		// get method 
	{ "xch_cmd",	VAL_XCHCMD },		// xch_cmd method 
	{ "forms",		VAL_FORMS },		// clear forms 
	{ "plugins",	VAL_PLUGINS },		// clear plugins 
	{ "top",		VAL_TOP },    		// align top 
	{ "bottom",		VAL_BOTTOM },    	// align bottom 
	{ "above",		VAL_ABOVE },    	// align above 
	{ "below",		VAL_BELOW },    	// align below 
	{ "leftof",		VAL_LEFTOF },    	// align leftof 
	{ "rightof",	VAL_RIGHTOF },    	// align rightof 
	{ "images",		VAL_IMAGES },    	// align rightof 
 
	{ "black", 		0x000000 }, 
	{ "white", 		0xffffff }, 
	{ "green", 		0x00ff00 }, 
	{ "maroon", 	0x800000 }, 
	{ "olive", 		0x008000 }, 
	{ "navy", 		0x000080 }, 
	{ "purple", 	0x800080 }, 
	{ "gray", 		0x808080 }, 
	{ "red", 		0xff0000 }, 
	{ "yellow", 	0xffff00 }, 
	{ "blue", 		0x0000ff }, 
	{ "teal", 		0x008080 }, 
	{ "lime", 		0x808000 }, 
	{ "aqua", 		0x00ffff }, 
	{ "fuchsia", 	0xff00ff }, 
	{ "silver", 	0xc0c0c0 }, 
 
}; 
 
 
 
 
// Entity  map table.  
// In addition to the entitiies specified here 
// all the entities of the format &[X]; 
// where X is any value from 1-255 are handled. 
 
CH_GLOBAL_VAR  SymbolMap aEntityTbl[] = 
						{ 
							{"LT", (unsigned char) '<'}, 
							{"GT", (unsigned char) '>'}, 
							{"AMP", (unsigned char)'&'}, 
							{"QUOT", (unsigned char)'\"'}, 
							{"lt", (unsigned char)'<'}, 
							{"gt", (unsigned char)'>'}, 
							{"amp", (unsigned char)'&'}, 
							{"quot", (unsigned char)'\"'}, 
							{"Aacute", 193}, 
							{"Agrave", 192}, 
							{"Acirc", 194}, 
							{"Atilde", 195}, 
							{"Aring", 197}, 
							{"Auml", 196}, 
							{"AElig", 198}, 
							{"Ccedil", 199}, 
							{"Eacute", 201}, 
							{"Egrave", 200}, 
							{"Ecirc", 202}, 
							{"Euml", 203}, 
							{"Iacute", 205}, 
							{"Igrave", 204}, 
							{"Icirc", 206}, 
							{"Iuml", 207}, 
							{"ETH", 208}, 
							{"Ntilde", 209}, 
							{"Oacute", 211}, 
							{"Ograve", 210}, 
							{"Ocirc", 212}, 
							{"Otilde", 213}, 
							{"Ouml", 214}, 
							{"Oslash", 216}, 
							{"Uacute", 218}, 
							{"Ugrave", 217}, 
							{"Ucirc", 219}, 
							{"Uuml", 220}, 
							{"Yacute", 221}, 
							{"THORN", 222}, 
							{"szlig", 223}, 
							{"aacute", 225}, 
							{"agrave", 224}, 
							{"acirc", 226}, 
							{"atilde", 227}, 
							{"aring", 229}, 
							{"auml", 228}, 
							{"aelig", 230}, 
							{"ccedil", 231}, 
							{"eacute", 233}, 
							{"egrave", 232}, 
							{"ecirc", 234}, 
							{"euml", 235}, 
							{"iacute", 237}, 
							{"igrave", 236}, 
							{"icirc", 238}, 
							{"iuml", 239}, 
							{"eth", 240}, 
							{"ntilde", 241}, 
							{"oacute", 243}, 
							{"ograve", 242}, 
							{"ocirc", 244}, 
							{"otilde", 245}, 
							{"ouml", 246}, 
							{"oslash", 248}, 
							{"uacute", 250}, 
							{"ugrave", 249}, 
							{"ucirc", 251}, 
							{"uuml", 252}, 
							{"yacute", 253}, 
							{"thorn", 254}, 
							{"yuml", 255}, 
												// Netscape additions 
							{ "copy",'©'}, 
							{ "reg", '®' }, 
							{ "trade", '\x99' }, 
							{ "nbsp", ' ' }, 
							{ "tmark", '\x99' },  // Chaco addition 
 
						}; 
 
 
 // Table used to map special characters  
CH_GLOBAL_VAR CharType aSpecialChar[] = 
				{ 
					CHAR_BULLET, 	 183, 
					CHAR_SQUARE,     0xa8, 
					//CHAR_REGISTER,   0xe2, 
					//CHAR_COPYRIGHT,	 0xe3, 
					//CHAR_TRADEMARK,	 0xe4, 
				}; 
 
 
 
 
 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlStyle::InitHTMLParser() 
 
------------------------------------------------------------------------------ 
	Get the pixel width 
	Read the registry and initialize the font name and size for HTML  
	Sort all tables 
----------------------------------------------------------------------------*/ 
 
 
void ChHtmlParser::InitStatics() 
{ 
 
	static boolInitialized = false; 
 
	if ( !boolInitialized ) 
	{ 
		boolInitialized = true; 
		// Sort all tables 
		SortSymbolMap( aHtmlTokens, (sizeof(aHtmlTokens)/sizeof(SymbolMap)) ); 
 
		SortSymbolMap( aEntityTbl, (sizeof(aEntityTbl)/sizeof(SymbolMap)) ); 
		// Sort attribute type list 
		SortSymbolMap( aArguments, (sizeof(aArguments)/sizeof(SymbolMap)) ); 
 
		// Sort the attribute value table 
		SortSymbolMap( aAttrValueMap, (sizeof(aAttrValueMap)/sizeof(SymbolMap)) ); 
	} 
 
} 
 
 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlStyle::GetToken() 
 
------------------------------------------------------------------------------ 
	Return the HTML token 
----------------------------------------------------------------------------*/ 
int  ChHtmlParser::GetTokenID( const char* pstrToken ) 
{  
	int iToken = FindSymbol( pstrToken, aHtmlTokens, 
				 sizeof( aHtmlTokens)/sizeof( SymbolMap ) ); 
 
	return ( iToken >= 0 ? iToken : 0 ); 
} 
 
 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlStyle::LookUpTag 
 
------------------------------------------------------------------------------ 
This method looks up the HTML table for a given tag treturns the HTML tag code. 
if found else -1. if the tag is terminating HTML tag then boolEnd is set to true. 
 
----------------------------------------------------------------------------*/ 
 
 
int ChHtmlParser::LookUpTag( const char* pstrBuffer, chint32 lStart, 
							chint32 lCount, bool& boolEnd ) 
{ 
	boolEnd = false; 
	int iRet = -1; 
 
	if ( pstrBuffer[lStart] == TEXT( '<' ) ) 
	{ 
		lStart++; 
	} 
	if ( pstrBuffer[lStart] == TEXT( '/' )) 
	{ 
		boolEnd = true; 
		lStart++; 
	} 
 
	if ( pstrBuffer[lStart] == TEXT( '!' )) 
	{ 
		return ( HTML_COMMENT ); 
	} 
 
	string strToken = TEXT( "" ); 
	int i = 0; 
	while( lStart < lCount  && !IS_WHITE_SPACE( pstrBuffer[lStart] ) 
							&&  pstrBuffer[lStart] != TEXT( '>' ) ) 
	{ 
		strToken += pstrBuffer[lStart++]; 
	} 
 
	strToken.MakeLower(); 
	strToken.TrimLeft(); 
	strToken.TrimRight(); 
 
	return GetTokenID( strToken );  
}  
 
 
 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlStyle::GetSpecialCharacter 
 
------------------------------------------------------------------------------ 
This method maps the given character to a symbol character. 
----------------------------------------------------------------------------*/ 
 
char ChHtmlParser::GetSpecialCharacter( UINT uCharType  ) 
{ 
	// get the index to the symbol font   
 
	char chChar; 
	if ( uCharType < sizeof(aSpecialChar)/sizeof(CharType)) 
	{ 
		chChar = aSpecialChar[uCharType].chCharMap; 
	} 
	else 
	{ 
		chChar	= (char)uCharType;		 
	} 
 
	return chChar; 
} 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlParser::MapEntityToChar 
 
------------------------------------------------------------------------------ 
This method maps a given entity to its charcter equivialent.. 
 
----------------------------------------------------------------------------*/ 
 
 
bool ChHtmlParser::MapEntityToChar(  const char* pstrBuffer, chint32& lStart, chint32 lCount, char& strChar ) 
{ 
	bool		boolTerminated = true; 
	chint32		lTemp = lStart; 
 
	ASSERT( pstrBuffer[lStart] == TEXT( '&' ) ); 
 
	lStart++;  // Skip the '&' 
 
	string strEntity; 
 
	// For faster concat 
	strEntity.GetBuffer( 25 ); 
	strEntity.ReleaseBuffer( 0 ); 
 
 
	while( lStart < lCount && !IS_WHITE_SPACE( pstrBuffer[lStart] )  
								&& pstrBuffer[lStart] != TEXT( ';' )) 
	{ 
		strEntity += pstrBuffer[lStart++]; 
	} 
	 
	if ( pstrBuffer[lStart] == TEXT( ';' ) ) 
	{ 
		lStart++; 
	} 
	else 
	{  
		if (  lStart >= lCount ) 
		{ 
			// buffer '&' and return 
			AddToBuffer( &pstrBuffer[lTemp], lStart - lTemp ); 
			return false; 
		} 
		boolTerminated = false; 
	} 
 
	if ( !strEntity.IsEmpty() ) 
	{ 
		int chChar; 
		if ( strEntity[0]=='#')  
		{ 
			const char* pstrNum = strEntity; 
 
			strChar = (char)strtol(++pstrNum, (char **)NULL, 10); 
		 
			return true; 
		}  
		else  
		{	// Find the map in the entity table 
			chChar = FindSymbol( strEntity, aEntityTbl, 
					 sizeof( aEntityTbl)/sizeof( SymbolMap ) ); 
			if (chChar != -1 ) 
			{ 
				strChar = chChar; 
				return true; 
			} 
			else if ( boolTerminated && strEntity.GetLength() == 1 ) 
			{ 
				strChar = strEntity[0]; 
				return true; 
			}  
		} 
	} 
 
	// not an entity 
	strChar = TEXT( '&' ); 
	lStart = lTemp + 1; 
	return true; 
} 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlParser::MapEntity 
 
------------------------------------------------------------------------------ 
This method maps a given entity to its charcter equivialent.. 
 
----------------------------------------------------------------------------*/ 
 
 
char ChHtmlParser::MapEntity(  const char* pstrBuffer, chint32& lStart, chint32 lCount ) 
{ 
 
	ASSERT( pstrBuffer[lStart] == TEXT( '&' ) ); 
 
	bool boolTerminated = true; 
	 
	chint32 lTemp = lStart;	  
 
	lStart++;  // Skip the '&' 
 
	string strEntity; 
 
	// For faster concat 
	strEntity.GetBuffer( 25 ); 
	strEntity.ReleaseBuffer( 0 ); 
 
 
	while( lStart < lCount && !IS_WHITE_SPACE( pstrBuffer[lStart] )  
								&& pstrBuffer[lStart] != TEXT( ';' )) 
	{ 
		strEntity += pstrBuffer[lStart++]; 
	} 
	 
	if ( pstrBuffer[lStart] == TEXT( ';' ) ) 
	{ 
		lStart++; 
	} 
	else 
	{	// not an entity, return unmodified 
		if (  lStart >= lCount ) 
		{ 
			lStart = lTemp + 1; 
			return TEXT( '&' ); 
		} 
		boolTerminated = false; 
	} 
	 
	if ( !strEntity.IsEmpty() ) 
	{ 
		int chChar; 
		if ( strEntity[0]=='#')  
		{ 
			const char* pstrNum = strEntity; 
 
			chChar = strtol(++pstrNum, (char **)NULL, 10); 
		 
			return ((char)chChar); 
		}  
		else  
		{	// Find the map in the entity table 
			chChar = FindSymbol( strEntity, aEntityTbl, 
					 sizeof( aEntityTbl)/sizeof( SymbolMap ) ); 
			if (chChar != -1 ) 
			{ 
				return ((char)chChar); 
			} 
			else if ( boolTerminated && strEntity.GetLength() == 1 ) 
			{ 
				return ( strEntity[0] ); 
			}  
		} 
	} 
	// restore the index 
	lStart = lTemp + 1; 
 
	return('&'); 
} 
 
 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlStyle::SortSymbolMap() 
 
----------------------------------------------------------------------------*/ 
 
 
void ChHtmlParser::SortSymbolMap( pSymbolMap pmapTbl, int iTblSize ) 
{ 
	SymbolMap			tmp; 
	register SymbolMap	*cp, *np, *lp; 
	register bool		boolDone = 0; 
 
	for (lp = &(pmapTbl[iTblSize - 1]); !boolDone && lp >= pmapTbl; lp--)  
	{ 
		boolDone = 1; 
		for (cp = pmapTbl; cp < lp; cp++)  
		{ 
			np = cp + 1; 
			if (lstrcmp(cp->pstrSymbol, np->pstrSymbol) > 0)  
			{ 
				tmp = *np; 
				*np = *cp; 
				*cp = tmp; 
				boolDone = 0; 
			} 
		} 
	} 
} 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlStyle::FindSymbol() 
 
------------------------------------------------------------------------------ 
----------------------------------------------------------------------------*/ 
 
 
int ChHtmlParser::FindSymbol(const char *pstrSymbol, pSymbolMap pmapTbl, 
													int iTblSize ) 
{ 
	register int	low, high, mid, r; 
 
	low = 0; 
	high = iTblSize-1; 
 
	while ( low <= high )  
	{ 
		mid = (low+high+1)/2; 
 
		r = lstrcmp( pmapTbl[mid].pstrSymbol, pstrSymbol ); 
		if (r < 0)  
		{ 
			low = mid+1; 
		}  
		else if ( r > 0 )  
		{ 
			high = mid-1; 
		}  
		else 
		{ 
			return pmapTbl[mid].iMap; 
		} 
	} 
 
	return -1; 
} 
 
 
 
 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlParser::GetArgType 
 
------------------------------------------------------------------------------ 
This method returns a integer id for a given argument type, it 
the arg type is not processed by us then it returns 0. 
 
----------------------------------------------------------------------------*/ 
int  ChHtmlParser::GetArgType(  string& strArg ) 
{ 
	strArg.MakeLower(); 
 
	int iType = FindSymbol( strArg, aArguments, 
				 sizeof( aArguments)/sizeof( SymbolMap ) ); 
 
	return iType != -1 ? iType : 0; 
} 
 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlParser::MapAttributeValue 
 
------------------------------------------------------------------------------ 
This method maps the given attribute to a integer value, returns -1 if there  
is no map. 
----------------------------------------------------------------------------*/ 
 
int  ChHtmlParser::MapAttributeValue( const char* pstrValue  ) 
{ 
	return 	FindSymbol( pstrValue, aAttrValueMap, 
				 sizeof( aAttrValueMap)/sizeof( SymbolMap ) ); 
} 
 
/*---------------------------------------------------------------------------- 
 
	FUNCTION	||	ChHtmlParser::BreakTag 
 
------------------------------------------------------------------------------ 
----------------------------------------------------------------------------*/ 
 
bool ChHtmlParser::BreakTag( const char* pstrBuffer, chint32& lStart, 	chint32  lCount  ) 
{ 
 
	if ( pstrBuffer[lStart] == TEXT( '<' )) 
	{ 
		return true; 
	} 
	else if ( m_pHtmlView->GetAnchorTarget().GetLength() ) 
	{ // check if we need to start a new sub-style  for the current tag 
		bool boolContinue = IS_WHITE_SPACE( GetLastChar() ); 
 
		if ( !boolContinue ) 
		{ 
			switch( GetLastChar() ) 
			{ 
				case '"' : 
				case ':' : 
				case '(' : 
				case ')' : 
				case ',' : 
				case '!' : 
				case ';' : 
				case '{' : 
				case '}' : 
				case '[' : 
				case ']' : 
				case '`' : 
				case '\'' : 
				{ 
					boolContinue = true; 
					break; 
				} 
				default : 
					break; 
			} 
		} 
		if ( ( ( lCount - lStart ) > 7 )  
				&& boolContinue  
				&& !(GetTextStyle()->GetStyle() & ChTxtWnd::textHotSpot) ) 
		{	// we currently look for a URL  
			string strURL; 
			while ( lStart < lCount && !IS_WHITE_SPACE( pstrBuffer[lStart] )  
							&& !( pstrBuffer[lStart] == TEXT( '<' ) 
								  || pstrBuffer[lStart] == TEXT( ')' ) 
								  || pstrBuffer[lStart] == TEXT( '"' ) 
								  || pstrBuffer[lStart] == TEXT( '\'' ) 
								  || pstrBuffer[lStart] == TEXT( '}' ) 
								 || pstrBuffer[lStart] == TEXT( '&' ) ) ) 
			{  	 
				strURL += pstrBuffer[lStart++]; 
			} 
 
			// strip period and , 
			char chLast = strURL[strURL.GetLength() - 1]; 
			if ( chLast == '.' || chLast == ',' ) 
			{ 
				lStart--; 
				strURL = strURL.Left( strURL.GetLength() - 1 ); 
			} 
 
			string strTemp( strURL); 
			strTemp.MakeLower(); 
 
			if ( strTemp.Find( "http://" ) == 0 ) 
			{ 
				// commit the old buffer 
				CommitBuffer(); 
 
				// set the new style 
				chuint32  luOldStyle = GetTextStyle()->GetStyle(); 
				chuint32  luTextColor = GetTextStyle()->GetTextColor();  
			 
				GetTextStyle()->SetTextColor(	GetLinkTextColor() ); 
				GetTextStyle()->SetStyle( luOldStyle | ChTxtWnd::textHotSpot ); 
 
				// create the user data for this link 
				// href=url target=_webtracker 
				char* pstrBuf = new char[30 + strURL.GetLength() +  
									m_pHtmlView->GetAnchorTarget().GetLength() ]; 
				ASSERT( pstrBuf ); 
				lstrcpy( pstrBuf, "href=" ); 
				lstrcat( pstrBuf, strURL ); 
				lstrcat( pstrBuf, " target=" ); 
				lstrcat( pstrBuf, m_pHtmlView->GetAnchorTarget() ); 
				GetTextStyle()->SetUserData( (chparam)pstrBuf );  
				// add all the mem allocation, we will free this on  
				//new page or when the window is destroyed 
				m_pHtmlView->GetAllocList().AddTail( pstrBuf ); 
 
			    for( int i = 0; i < strURL.GetLength(); i++ ) 
				{ 
					AppendChar( strURL[i] ); 
				} 
 
				CommitBuffer(); 
 
				// restore the style 
				GetTextStyle()->SetTextColor(	luTextColor ); 
				GetTextStyle()->SetStyle( luOldStyle ); 
				GetTextStyle()->SetUserData( 0 );  
				 
			} 
			else 
			{ 
			    for( int i = 0; i < strURL.GetLength(); i++ ) 
				{ 
					AppendChar( strURL[i] ); 
				} 
			} 
		} 
		else 
		{ 
			AppendChar( pstrBuffer[lStart++]  ); 
		} 
	} 
	else 
	{ 
		AppendChar( pstrBuffer[lStart++]  ); 
	} 
	return false; 
}