X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/04dbb6467be8f564f380bd9a1106fbdecbd26a98..65dc921d3f1080b8b5c6ca49d2cce228d6924480:/src/html/htmltag.cpp diff --git a/src/html/htmltag.cpp b/src/html/htmltag.cpp index 05cdc2aba5..0b0b894f5b 100644 --- a/src/html/htmltag.cpp +++ b/src/html/htmltag.cpp @@ -9,7 +9,7 @@ #ifdef __GNUG__ -#pragma implementation +#pragma implementation "htmltag.h" #endif #include "wx/wxprec.h" @@ -17,7 +17,7 @@ #include "wx/defs.h" #if wxUSE_HTML -#ifdef __BORDLANDC__ +#ifdef __BORLANDC__ #pragma hdrstop #endif @@ -26,6 +26,7 @@ #include "wx/html/htmltag.h" #include "wx/html/htmlpars.h" +#include "wx/colour.h" #include // for vsscanf #include @@ -56,19 +57,25 @@ IMPLEMENT_CLASS(wxHtmlTagsCache,wxObject) #define CACHE_INCREMENT 64 +bool wxIsCDATAElement(const wxChar *tag) +{ + return (wxStrcmp(tag, _T("SCRIPT")) == 0) || + (wxStrcmp(tag, _T("STYLE")) == 0); +} + wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source) { const wxChar *src = source.c_str(); - int i, tg, pos, stpos; + int tg, stpos; int lng = source.Length(); - wxChar dummy[256]; + wxChar tagBuffer[256]; m_Cache = NULL; m_CacheSize = 0; m_CachePos = 0; - pos = 0; - while (pos < lng) + int pos = 0; + while (pos < lng) { if (src[pos] == wxT('<')) // tag found: { @@ -76,19 +83,19 @@ wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source) m_Cache = (wxHtmlCacheItem*) realloc(m_Cache, (m_CacheSize + CACHE_INCREMENT) * sizeof(wxHtmlCacheItem)); tg = m_CacheSize++; m_Cache[tg].Key = stpos = pos++; - dummy[0] = 0; i = 0; - while (pos < lng && - src[pos] != wxT('>') && - src[pos] != wxT(' ') && src[pos] != wxT('\r') && - src[pos] != wxT('\n') && src[pos] != wxT('\t')) + + int i; + for ( i = 0; + pos < lng && i < (int)WXSIZEOF(tagBuffer) - 1 && + src[pos] != wxT('>') && !wxIsspace(src[pos]); + i++, pos++ ) { - dummy[i] = src[pos++]; - if ((dummy[i] >= wxT('a')) && (dummy[i] <= wxT('z'))) dummy[i] -= (wxT('a') - wxT('A')); - i++; + tagBuffer[i] = wxToupper(src[pos]); } - dummy[i] = 0; + tagBuffer[i] = _T('\0'); + m_Cache[tg].Name = new wxChar[i+1]; - memcpy(m_Cache[tg].Name, dummy, (i+1)*sizeof(wxChar)); + memcpy(m_Cache[tg].Name, tagBuffer, (i+1)*sizeof(wxChar)); while (pos < lng && src[pos] != wxT('>')) pos++; @@ -97,16 +104,57 @@ wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source) m_Cache[tg].End1 = m_Cache[tg].End2 = -2; // find matching begin tag: for (i = tg; i >= 0; i--) - if ((m_Cache[i].End1 == -1) && (wxStrcmp(m_Cache[i].Name, dummy+1) == 0)) + if ((m_Cache[i].End1 == -1) && (wxStrcmp(m_Cache[i].Name, tagBuffer+1) == 0)) { m_Cache[i].End1 = stpos; m_Cache[i].End2 = pos + 1; break; } } - else + else { m_Cache[tg].End1 = m_Cache[tg].End2 = -1; + + if (wxIsCDATAElement(tagBuffer)) + { + // find next matching tag + int tag_len = wxStrlen(tagBuffer); + while (pos < lng) + { + // find the ending tag + while (pos + 1 < lng && + (src[pos] != '<' || src[pos+1] != '/')) + ++pos; + if (src[pos] == '<') + ++pos; + + // see if it matches + int match_pos = 0; + while (pos < lng && match_pos < tag_len && src[pos] != '>' && src[pos] != '<') { + if (wxToupper(src[pos]) == tagBuffer[match_pos]) { + ++match_pos; + } + else if (src[pos] == wxT(' ') || src[pos] == wxT('\n') || + src[pos] == wxT('\r') || src[pos] == wxT('\t')) { + // need to skip over these + } + else { + match_pos = 0; + } + ++pos; + } + + // found a match + if (match_pos == tag_len) { + pos = pos - tag_len - 3; + stpos = pos; + break; + } + else { + ++pos; + } + } + } } } @@ -114,7 +162,7 @@ wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source) } // ok, we're done, now we'll free .Name members of cache - we don't need it anymore: - for (i = 0; i < m_CacheSize; i++) + for (int i = 0; i < m_CacheSize; i++) { delete[] m_Cache[i].Name; m_Cache[i].Name = NULL; @@ -124,12 +172,12 @@ wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source) void wxHtmlTagsCache::QueryTag(int at, int* end1, int* end2) { if (m_Cache == NULL) return; - if (m_Cache[m_CachePos].Key != at) + if (m_Cache[m_CachePos].Key != at) { int delta = (at < m_Cache[m_CachePos].Key) ? -1 : 1; - do - { - m_CachePos += delta; + do + { + m_CachePos += delta; } while (m_Cache[m_CachePos].Key != at); } @@ -146,33 +194,49 @@ void wxHtmlTagsCache::QueryTag(int at, int* end1, int* end2) IMPLEMENT_CLASS(wxHtmlTag,wxObject) -wxHtmlTag::wxHtmlTag(const wxString& source, int pos, int end_pos, +wxHtmlTag::wxHtmlTag(wxHtmlTag *parent, + const wxString& source, int pos, int end_pos, wxHtmlTagsCache *cache, wxHtmlEntitiesParser *entParser) : wxObject() { + /* Setup DOM relations */ + + m_Next = NULL; + m_FirstChild = m_LastChild = NULL; + m_Parent = parent; + if (parent) + { + m_Prev = m_Parent->m_LastChild; + if (m_Prev == NULL) + m_Parent->m_FirstChild = this; + else + m_Prev->m_Next = this; + m_Parent->m_LastChild = this; + } + else + m_Prev = NULL; + + /* Find parameters and their values: */ + int i; wxChar c; // fill-in name, params and begin pos: i = pos+1; - if (source[i] == wxT('/')) - { m_Ending = TRUE; i++; } - else - m_Ending = FALSE; // find tag's name and convert it to uppercase: - while ((i < end_pos) && - ((c = source[i++]) != wxT(' ') && c != wxT('\r') && + while ((i < end_pos) && + ((c = source[i++]) != wxT(' ') && c != wxT('\r') && c != wxT('\n') && c != wxT('\t') && - c != wxT('>'))) + c != wxT('>'))) { - if ((c >= wxT('a')) && (c <= wxT('z'))) + if ((c >= wxT('a')) && (c <= wxT('z'))) c -= (wxT('a') - wxT('A')); m_Name << c; } // if the tag has parameters, read them and "normalize" them, - // i.e. convert to uppercase, replace whitespaces by spaces and + // i.e. convert to uppercase, replace whitespaces by spaces and // remove whitespaces around '=': if (source[i-1] != wxT('>')) { @@ -180,22 +244,22 @@ wxHtmlTag::wxHtmlTag(const wxString& source, int pos, int end_pos, c == wxT('\n') || c == wxT('\t')) wxString pname, pvalue; wxChar quote; - enum + enum { - ST_BEFORE_NAME = 1, + ST_BEFORE_NAME = 1, ST_NAME, ST_BEFORE_EQ, ST_BEFORE_VALUE, ST_VALUE } state; - + quote = 0; state = ST_BEFORE_NAME; while (i < end_pos) { c = source[i++]; - if (c == wxT('>') && !(state == ST_VALUE && quote != 0)) + if (c == wxT('>') && !(state == ST_VALUE && quote != 0)) { if (state == ST_BEFORE_EQ || state == ST_NAME) { @@ -272,7 +336,7 @@ wxHtmlTag::wxHtmlTag(const wxString& source, int pos, int end_pos, break; } } - + #undef IS_WHITE } m_Begin = i; @@ -282,6 +346,18 @@ wxHtmlTag::wxHtmlTag(const wxString& source, int pos, int end_pos, if (m_End2 > end_pos) m_End2 = end_pos; } +wxHtmlTag::~wxHtmlTag() +{ + wxHtmlTag *t1, *t2; + t1 = m_FirstChild; + while (t1) + { + t2 = t1->GetNextSibling(); + delete t1; + t1 = t2; + } +} + bool wxHtmlTag::HasParam(const wxString& par) const { return (m_ParamNames.Index(par, FALSE) != wxNOT_FOUND); @@ -303,7 +379,9 @@ wxString wxHtmlTag::GetParam(const wxString& par, bool with_commas) const return m_ParamValues[index]; } -int wxHtmlTag::ScanParam(const wxString& par, wxChar *format, void *param) const +int wxHtmlTag::ScanParam(const wxString& par, + const wxChar *format, + void *param) const { wxString parval = GetParam(par); return wxSscanf(parval, format, param); @@ -312,7 +390,7 @@ int wxHtmlTag::ScanParam(const wxString& par, wxChar *format, void *param) const bool wxHtmlTag::GetParamAsColour(const wxString& par, wxColour *clr) const { wxString str = GetParam(par); - + if (str.IsEmpty()) return FALSE; if (str.GetChar(0) == wxT('#')) { @@ -347,8 +425,9 @@ bool wxHtmlTag::GetParamAsColour(const wxString& par, wxColour *clr) const HTML_COLOUR("teal", 0x00,0x80,0x80) HTML_COLOUR("aqua", 0x00,0xFF,0xFF) #undef HTML_COLOUR - return FALSE; } + + return FALSE; } bool wxHtmlTag::GetParamAsInt(const wxString& par, int *clr) const @@ -362,7 +441,7 @@ bool wxHtmlTag::GetParamAsInt(const wxString& par, int *clr) const wxString wxHtmlTag::GetAllParams() const { - // VS: this function is for backward compatiblity only, + // VS: this function is for backward compatiblity only, // never used by wxHTML wxString s; size_t cnt = m_ParamNames.GetCount(); @@ -378,4 +457,41 @@ wxString wxHtmlTag::GetAllParams() const return s; } +wxHtmlTag *wxHtmlTag::GetFirstSibling() const +{ + if (m_Parent) + return m_Parent->m_FirstChild; + else + { + wxHtmlTag *cur = (wxHtmlTag*)this; + while (cur->m_Prev) + cur = cur->m_Prev; + return cur; + } +} + +wxHtmlTag *wxHtmlTag::GetLastSibling() const +{ + if (m_Parent) + return m_Parent->m_LastChild; + else + { + wxHtmlTag *cur = (wxHtmlTag*)this; + while (cur->m_Next) + cur = cur->m_Next; + return cur; + } +} + +wxHtmlTag *wxHtmlTag::GetNextTag() const +{ + if (m_FirstChild) return m_FirstChild; + if (m_Next) return m_Next; + wxHtmlTag *cur = m_Parent; + if (!cur) return NULL; + while (cur->m_Parent && !cur->m_Next) + cur = cur->m_Parent; + return cur->m_Next; +} + #endif