int32 PA_TagIndex(char *str) { return((int32)pa_tokenize_tag(str)); }
PRIVATE int net_ColorHTMLWrite (NET_StreamClass *stream, CONST char *s, int32 l) { int32 i; int32 last_output_point; char *new_markup=0; char *tmp_markup=0; char tiny_buf[4]; CONST char *cp; int status; DataObject *obj=stream->data_object; last_output_point = 0; for(i = 0, cp = s; i < l; i++, cp++) { switch(obj->state) { case IN_CONTENT: /* do nothing until you find a '<' "<!--" or '&' */ if(*cp == '<') { /* XXX we can miss a comment spanning a block boundary */ if(i+4 <= l && !XP_STRNCMP(cp, "<!--", 4)) { StrAllocCopy(new_markup, BEGIN_COMMENT_MARKUP); StrAllocCat(new_markup, "<"); obj->state = IN_COMMENT; } else { new_markup = net_BeginColorHTMLTag(obj); } } else if(*cp == '&') { StrAllocCopy(new_markup, BEGIN_AMPERSAND_THINGY_MARKUP); StrAllocCat(new_markup, "&"); obj->state = IN_AMPERSAND_THINGY; } break; case IN_SCRIPT: /* do nothing until you find '</SCRIPT>' */ if(*cp == '<') { /* XXX we can miss a </SCRIPT> spanning a block boundary */ if(i+8 <= l && !XP_STRNCASECMP(cp, "</SCRIPT", 8)) { new_markup = net_BeginColorHTMLTag(obj); } } break; case ABOUT_TO_BEGIN_TAG: /* we have seen the first '<' * once we see a non-whitespace character * we will be in the tag identifier */ if(*cp == '>') { StrAllocCopy(new_markup, END_TAG_NAME_MARKUP); tmp_markup = net_EndColorHTMLTag(obj); StrAllocCat(new_markup, tmp_markup); FREE_AND_CLEAR(tmp_markup); } else if(!XP_IS_SPACE(*cp)) { obj->state = IN_BEGIN_TAG; obj->tag_index = 0; obj->tag[obj->tag_index++] = *cp; if(*cp == '<') StrAllocCopy(new_markup, "<"); } break; case IN_BEGIN_TAG: /* go to the IN_TAG state when we see * the first whitespace */ if(XP_IS_SPACE(*cp)) { StrAllocCopy(new_markup, END_TAG_NAME_MARKUP); XP_SPRINTF(tiny_buf, "%c", *cp); StrAllocCat(new_markup, tiny_buf); obj->state = IN_TAG; obj->tag[obj->tag_index] = '\0'; obj->tag_type = pa_tokenize_tag(obj->tag); } else if(*cp == '>') { StrAllocCopy(new_markup, END_TAG_NAME_MARKUP); tmp_markup = net_EndColorHTMLTag(obj); StrAllocCat(new_markup, tmp_markup); FREE_AND_CLEAR(tmp_markup); } else if(*cp == '<') { /* protect ourselves from markup */ if(!obj->in_broken_html) { obj->in_broken_html = TRUE; StrAllocCopy(new_markup, BEGIN_BROKEN_ATTRIBUTE_MARKUP); StrAllocCat(new_markup, "<"); } else { StrAllocCopy(new_markup, "<"); } } else { if (obj->tag_index < MAXTAGLEN) obj->tag[obj->tag_index++] = *cp; } break; case IN_TAG: /* do nothing until you find a opening '=' or end '>' */ if(*cp == '=') { StrAllocCopy(new_markup, "="); StrAllocCat(new_markup, BEGIN_ATTRIBUTE_VALUE_MARKUP); obj->state = BEGIN_ATTRIBUTE_VALUE; } else if(*cp == '>') { new_markup = net_EndColorHTMLTag(obj); } else if(*cp == '<') { /* protect ourselves from markup */ StrAllocCopy(new_markup, "<"); } break; case BEGIN_ATTRIBUTE_VALUE: /* when we reach the first non-whitespace * we will enter the UNQUOTED or the QUOTED * ATTRIBUTE state */ if(!XP_IS_SPACE(*cp)) { if(*cp == '"') { obj->state = IN_QUOTED_ATTRIBUTE_VALUE; /* no need to jump to the quoted attr handler * since this char can't be a dangerous char */ } else { obj->state = IN_UNQUOTED_ATTRIBUTE_VALUE; /* need to jump to the unquoted attr handler * since this char can be a dangerous character */ goto unquoted_attribute_jump_point; } } else if(*cp == '>') { StrAllocCopy(new_markup, END_ATTRIBUTE_VALUE_MARKUP); tmp_markup = net_EndColorHTMLTag(obj); StrAllocCat(new_markup, tmp_markup); FREE_AND_CLEAR(tmp_markup); } else if(*cp == '<') { /* protect ourselves from markup */ StrAllocCopy(new_markup, "<"); } break; case IN_UNQUOTED_ATTRIBUTE_VALUE: unquoted_attribute_jump_point: /* do nothing until you find a whitespace */ if(XP_IS_SPACE(*cp)) { StrAllocCopy(new_markup, END_ATTRIBUTE_VALUE_MARKUP); XP_SPRINTF(tiny_buf, "%c", *cp); StrAllocCat(new_markup, tiny_buf); obj->state = IN_TAG; } else if(*cp == '>') { StrAllocCopy(new_markup, END_ATTRIBUTE_VALUE_MARKUP); tmp_markup = net_EndColorHTMLTag(obj); StrAllocCat(new_markup, tmp_markup); FREE_AND_CLEAR(tmp_markup); } else if(*cp == '<') { /* protect ourselves from markup */ StrAllocCopy(new_markup, "<"); } else if(*cp == '&') { /* protect ourselves from markup */ StrAllocCopy(new_markup, "&"); } break; case IN_QUOTED_ATTRIBUTE_VALUE: /* do nothing until you find a closing '"' */ if(*cp == '\"') { if(obj->in_broken_html) { StrAllocCopy(new_markup, END_BROKEN_ATTRIBUTE_MARKUP); obj->in_broken_html = FALSE; } StrAllocCat(new_markup, "\""); StrAllocCat(new_markup, END_ATTRIBUTE_VALUE_MARKUP); obj->state = IN_TAG; } else if(*cp == '<') { /* protect ourselves from markup */ StrAllocCopy(new_markup, "<"); } else if(*cp == '&') { /* protect ourselves from markup */ StrAllocCopy(new_markup, "&"); } else if(*cp == '>') { /* probably a broken attribute value */ if(!obj->in_broken_html) { obj->in_broken_html = TRUE; StrAllocCopy(new_markup, BEGIN_BROKEN_ATTRIBUTE_MARKUP); StrAllocCat(new_markup, ">"); } } break; case IN_COMMENT: /* do nothing until you find a closing '-->' */ if(!XP_STRNCMP(cp, "-->", 3)) { StrAllocCopy(new_markup, ">"); cp += 2; i += 2; StrAllocCat(new_markup, END_COMMENT_MARKUP); obj->state = IN_CONTENT; } else if(*cp == '<') { /* protect ourselves from markup */ StrAllocCopy(new_markup, "<"); } break; case IN_AMPERSAND_THINGY: /* do nothing until you find a ';' or space */ if(*cp == ';' || XP_IS_SPACE(*cp)) { XP_SPRINTF(tiny_buf, "%c", *cp); StrAllocCopy(new_markup, tiny_buf); StrAllocCat(new_markup, END_AMPERSAND_THINGY_MARKUP); obj->state = IN_CONTENT; } else if(*cp == '<') { /* protect ourselves from markup */ StrAllocCopy(new_markup, "<"); } break; default: XP_ASSERT(0); break; } if(new_markup) { /* push all the way up to but not including *cp */ status = (*obj->next_stream->put_block) (obj->next_stream, &s[last_output_point], i-last_output_point); last_output_point = i+1; if(status < 0) { FREE(new_markup); return(status); } /* add new markup */ status = (*obj->next_stream->put_block) (obj->next_stream, new_markup, XP_STRLEN(new_markup)); if(status < 0) { FREE(new_markup); return(status); } FREE_AND_CLEAR(new_markup); } } if(last_output_point < l) return((*obj->next_stream->put_block)(obj->next_stream, &s[last_output_point], (l-last_output_point))); else return(0); }