]> git.saurik.com Git - wxWidgets.git/blame - src/html/htmltag.cpp
Some OS/2 catching up.
[wxWidgets.git] / src / html / htmltag.cpp
CommitLineData
5526e819
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: htmltag.cpp
3// Purpose: wxHtmlTag class (represents single tag)
4// Author: Vaclav Slavik
69941f05 5// RCS-ID: $Id$
5526e819
VS
6// Copyright: (c) 1999 Vaclav Slavik
7// Licence: wxWindows Licence
8/////////////////////////////////////////////////////////////////////////////
9
10
11#ifdef __GNUG__
12#pragma implementation
13#endif
14
3096bd2f 15#include "wx/wxprec.h"
5526e819
VS
16
17#include "wx/defs.h"
18#if wxUSE_HTML
19
20#ifdef __BORDLANDC__
21#pragma hdrstop
22#endif
23
24#ifndef WXPRECOMP
3096bd2f 25#include "wx/wx.h"
5526e819
VS
26#endif
27
69941f05 28#include "wx/html/htmltag.h"
7e1e0960 29#include <stdio.h> // for vsscanf
5526e819
VS
30#include <stdarg.h>
31
32
5526e819
VS
33//-----------------------------------------------------------------------------
34// wxHtmlTagsCache
35//-----------------------------------------------------------------------------
36
5e8e25e7
VS
37struct wxHtmlCacheItem
38{
39 // this is "pos" value passed to wxHtmlTag's constructor.
40 // it is position of '<' character of the tag
41 int Key;
42
43 // end positions for the tag:
44 // end1 is '<' of ending tag,
45 // end2 is '>' or both are
46 // -1 if there is no ending tag for this one...
47 // or -2 if this is ending tag </...>
48 int End1, End2;
49
50 // name of this tag
51 wxChar *Name;
52};
53
54
5526e819
VS
55IMPLEMENT_CLASS(wxHtmlTagsCache,wxObject)
56
57#define CACHE_INCREMENT 64
58
59wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source)
60{
66a77a74 61 const wxChar *src = source.c_str();
5526e819
VS
62 int i, tg, pos, stpos;
63 int lng = source.Length();
66a77a74 64 wxChar dummy[256];
5526e819
VS
65
66 m_Cache = NULL;
67 m_CacheSize = 0;
68 m_CachePos = 0;
69
70 pos = 0;
4f9297b0
VS
71 while (pos < lng)
72 {
73 if (src[pos] == wxT('<')) // tag found:
74 {
5526e819 75 if (m_CacheSize % CACHE_INCREMENT == 0)
5e8e25e7 76 m_Cache = (wxHtmlCacheItem*) realloc(m_Cache, (m_CacheSize + CACHE_INCREMENT) * sizeof(wxHtmlCacheItem));
5526e819
VS
77 tg = m_CacheSize++;
78 m_Cache[tg].Key = stpos = pos++;
79 dummy[0] = 0; i = 0;
15db3cf5
VS
80 while (pos < lng &&
81 src[pos] != wxT('>') &&
f6bcfd97 82 src[pos] != wxT(' ') && src[pos] != wxT('\r') &&
4f9297b0
VS
83 src[pos] != wxT('\n') && src[pos] != wxT('\t'))
84 {
5526e819 85 dummy[i] = src[pos++];
66a77a74 86 if ((dummy[i] >= wxT('a')) && (dummy[i] <= wxT('z'))) dummy[i] -= (wxT('a') - wxT('A'));
5526e819
VS
87 i++;
88 }
89 dummy[i] = 0;
66a77a74
OK
90 m_Cache[tg].Name = new wxChar[i+1];
91 memcpy(m_Cache[tg].Name, dummy, (i+1)*sizeof(wxChar));
5526e819 92
15db3cf5 93 while (pos < lng && src[pos] != wxT('>')) pos++;
5526e819 94
4f9297b0
VS
95 if (src[stpos+1] == wxT('/')) // ending tag:
96 {
5526e819
VS
97 m_Cache[tg].End1 = m_Cache[tg].End2 = -2;
98 // find matching begin tag:
99 for (i = tg; i >= 0; i--)
4f9297b0
VS
100 if ((m_Cache[i].End1 == -1) && (wxStrcmp(m_Cache[i].Name, dummy+1) == 0))
101 {
5526e819
VS
102 m_Cache[i].End1 = stpos;
103 m_Cache[i].End2 = pos + 1;
104 break;
105 }
106 }
4f9297b0
VS
107 else
108 {
5526e819
VS
109 m_Cache[tg].End1 = m_Cache[tg].End2 = -1;
110 }
111 }
112
113 pos++;
114 }
115
116 // ok, we're done, now we'll free .Name members of cache - we don't need it anymore:
4f9297b0
VS
117 for (i = 0; i < m_CacheSize; i++)
118 {
2776d7c3 119 delete[] m_Cache[i].Name;
5526e819
VS
120 m_Cache[i].Name = NULL;
121 }
122}
123
124
125
126void wxHtmlTagsCache::QueryTag(int at, int* end1, int* end2)
127{
128 if (m_Cache == NULL) return;
4f9297b0
VS
129 if (m_Cache[m_CachePos].Key != at)
130 {
5526e819
VS
131 int delta = (at < m_Cache[m_CachePos].Key) ? -1 : 1;
132 do {m_CachePos += delta;} while (m_Cache[m_CachePos].Key != at);
133 }
134 *end1 = m_Cache[m_CachePos].End1;
135 *end2 = m_Cache[m_CachePos].End2;
136}
137
138
139
140
141//-----------------------------------------------------------------------------
142// wxHtmlTag
143//-----------------------------------------------------------------------------
144
145IMPLEMENT_CLASS(wxHtmlTag,wxObject)
146
147wxHtmlTag::wxHtmlTag(const wxString& source, int pos, int end_pos, wxHtmlTagsCache* cache) : wxObject()
148{
149 int i;
150 char c;
151
152 // fill-in name, params and begin pos:
153 m_Name = m_Params = wxEmptyString;
154 i = pos+1;
c9893146 155 if (source[i] == wxT('/')) { m_Ending = TRUE; i++; }
5526e819
VS
156 else m_Ending = FALSE;
157
b076dc01 158 // find tag's name and convert it to uppercase:
f6bcfd97 159 while ((i < end_pos) &&
c9893146
VS
160 ((c = source[i++]) != wxT(' ') && c != wxT('\r') &&
161 c != wxT('\n') && c != wxT('\t') &&
162 c != wxT('>')))
4f9297b0 163 {
c9893146 164 if ((c >= wxT('a')) && (c <= wxT('z'))) c -= (wxT('a') - wxT('A'));
5526e819
VS
165 m_Name += c;
166 }
167
b076dc01
VS
168 // if the tag has parameters, read them and "normalize" them,
169 // i.e. convert to uppercase, replace whitespaces by spaces and
170 // remove whitespaces around '=':
c9893146
VS
171 if (source[i-1] != wxT('>'))
172 while ((i < end_pos) && ((c = source[i++]) != wxT('>')))
4f9297b0 173 {
c9893146
VS
174 if ((c >= wxT('a')) && (c <= wxT('z')))
175 c -= (wxT('a') - wxT('A'));
176 if (c == wxT('\r') || c == wxT('\n') || c == wxT('\t'))
177 c = wxT(' '); // make future parsing a bit simpler
5526e819 178 m_Params += c;
c9893146 179 if (c == wxT('"'))
4f9297b0 180 {
b076dc01
VS
181 // remove spaces around the '=' character:
182 if (m_Params.Length() > 1 &&
c9893146 183 m_Params[m_Params.Length()-2] == wxT(' '))
b076dc01
VS
184 {
185 m_Params.RemoveLast();
c9893146 186 while (m_Params.Length() > 0 && m_Params.Last() == wxT(' '))
b076dc01 187 m_Params.RemoveLast();
c9893146 188 m_Params += wxT('"');
b076dc01 189 }
c9893146 190 while ((i < end_pos) && (source[i++] == wxT(' '))) {}
b076dc01
VS
191 if (i < end_pos) i--;
192
193 // ...and copy the value to m_Params:
c9893146
VS
194 while ((i < end_pos) && ((c = source[i++]) != wxT('"')))
195 m_Params += c;
5526e819
VS
196 m_Params += c;
197 }
c9893146 198 else if (c == wxT('\''))
4f9297b0 199 {
c9893146
VS
200 while ((i < end_pos) && ((c = source[i++]) != wxT('\'')))
201 m_Params += c;
72aa4a98
VS
202 m_Params += c;
203 }
5526e819
VS
204 }
205 m_Begin = i;
206
4f9297b0 207 cache->QueryTag(pos, &m_End1, &m_End2);
5526e819
VS
208 if (m_End1 > end_pos) m_End1 = end_pos;
209 if (m_End2 > end_pos) m_End2 = end_pos;
210}
211
212
213
214bool wxHtmlTag::HasParam(const wxString& par) const
215{
66a77a74
OK
216 const wxChar *st = m_Params, *p = par;
217 const wxChar *st2, *p2;
161f4f73 218 const wxChar invalid = wxT('\1');
5526e819
VS
219
220 if (*st == 0) return FALSE;
221 if (*p == 0) return FALSE;
4f9297b0
VS
222 for (st2 = st, p2 = p; ; st2++)
223 {
5526e819
VS
224 if (*p2 == 0) return TRUE;
225 if (*st2 == 0) return FALSE;
c9893146 226 if (*p2 != *st2) p2 = &invalid;
5526e819 227 if (*p2 == *st2) p2++;
c9893146
VS
228 if (*st2 == wxT(' ')) p2 = p;
229 else if (*st2 == wxT('='))
4f9297b0 230 {
5526e819 231 p2 = p;
c9893146 232 while (*st2 != wxT(' '))
4f9297b0 233 {
c9893146 234 if (*st2 == wxT('"'))
4f9297b0 235 {
5526e819 236 st2++;
c9893146 237 while (*st2 != wxT('"')) st2++;
5526e819
VS
238 }
239 st2++;
240 if (*st2 == 0) return FALSE;
241 }
242 }
243 }
244}
245
246
247
248wxString wxHtmlTag::GetParam(const wxString& par, bool with_commas) const
249{
66a77a74
OK
250 const wxChar *st = m_Params, *p = par;
251 const wxChar *st2, *p2;
161f4f73 252 const wxChar invalid = wxT('\1');
5526e819 253 bool comma;
c9893146 254 wxChar comma_char;
5526e819 255
c9893146
VS
256 if (*st == 0) return wxEmptyString;
257 if (*p == 0) return wxEmptyString;
4f9297b0
VS
258 for (st2 = st, p2 = p; ; st2++)
259 {
260 if (*p2 == 0) // found
261 {
c9893146 262 wxString fnd = wxEmptyString;
5526e819
VS
263 st2++; // '=' character
264 comma = FALSE;
c9893146
VS
265 comma_char = wxT('\0');
266 if (!with_commas && (*(st2) == wxT('"')))
4f9297b0
VS
267 {
268 st2++;
269 comma = TRUE;
c9893146 270 comma_char = wxT('"');
4f9297b0 271 }
c9893146 272 else if (!with_commas && (*(st2) == wxT('\'')))
4f9297b0
VS
273 {
274 st2++;
275 comma = TRUE;
c9893146 276 comma_char = wxT('\'');
4f9297b0
VS
277 }
278
279 while (*st2 != 0)
280 {
72aa4a98 281 if (comma && *st2 == comma_char) comma = FALSE;
c9893146 282 else if ((*st2 == wxT(' ')) && (!comma)) break;
5526e819
VS
283 fnd += (*(st2++));
284 }
72aa4a98 285 if (!with_commas && (*(st2-1) == comma_char)) fnd.RemoveLast();
5526e819
VS
286 return fnd;
287 }
c9893146
VS
288 if (*st2 == 0) return wxEmptyString;
289 if (*p2 != *st2) p2 = &invalid;
5526e819 290 if (*p2 == *st2) p2++;
c9893146
VS
291 if (*st2 == wxT(' ')) p2 = p;
292 else if (*st2 == wxT('='))
4f9297b0 293 {
5526e819 294 p2 = p;
c9893146 295 while (*st2 != wxT(' '))
4f9297b0 296 {
c9893146 297 if (*st2 == wxT('"'))
4f9297b0 298 {
5526e819 299 st2++;
c9893146 300 while (*st2 != wxT('"')) st2++;
5526e819 301 }
c9893146 302 else if (*st2 == wxT('\''))
4f9297b0 303 {
72aa4a98 304 st2++;
c9893146 305 while (*st2 != wxT('\'')) st2++;
72aa4a98 306 }
5526e819
VS
307 st2++;
308 }
309 }
310 }
311}
312
313
314
66a77a74 315int wxHtmlTag::ScanParam(const wxString& par, wxChar *format, void *param) const
5526e819 316{
5526e819 317 wxString parval = GetParam(par);
161f4f73 318 return wxSscanf(parval, format, param);
5526e819
VS
319}
320
4d223b67 321#endif