]> git.saurik.com Git - wxWidgets.git/blame - src/html/htmltag.cpp
Applied patch #403856 (utilscmn.cpp should translate special key names)
[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;
4f9297b0 155 if (source[i] == '/') { m_Ending = TRUE; i++; }
5526e819
VS
156 else m_Ending = FALSE;
157
b076dc01 158 // find tag's name and convert it to uppercase:
f6bcfd97
BP
159 while ((i < end_pos) &&
160 ((c = source[i++]) != ' ' && c != '\r' && c != '\n' && c != '\t' &&
4f9297b0
VS
161 c != '>'))
162 {
5526e819
VS
163 if ((c >= 'a') && (c <= 'z')) c -= ('a' - 'A');
164 m_Name += c;
165 }
166
b076dc01
VS
167 // if the tag has parameters, read them and "normalize" them,
168 // i.e. convert to uppercase, replace whitespaces by spaces and
169 // remove whitespaces around '=':
5526e819 170 if (source[i-1] != '>')
4f9297b0
VS
171 while ((i < end_pos) && ((c = source[i++]) != '>'))
172 {
5526e819 173 if ((c >= 'a') && (c <= 'z')) c -= ('a' - 'A');
f6bcfd97 174 if (c == '\r' || c == '\n' || c == '\t') c = ' '; // make future parsing a bit simpler
5526e819 175 m_Params += c;
4f9297b0
VS
176 if (c == '"')
177 {
b076dc01
VS
178 // remove spaces around the '=' character:
179 if (m_Params.Length() > 1 &&
180 m_Params[m_Params.Length()-2] == ' ')
181 {
182 m_Params.RemoveLast();
183 while (m_Params.Length() > 0 && m_Params.Last() == ' ')
184 m_Params.RemoveLast();
185 m_Params += '"';
186 }
187 while ((i < end_pos) && (source[i++] == ' ')) {}
188 if (i < end_pos) i--;
189
190 // ...and copy the value to m_Params:
5526e819
VS
191 while ((i < end_pos) && ((c = source[i++]) != '"')) m_Params += c;
192 m_Params += c;
193 }
4f9297b0
VS
194 else if (c == '\'')
195 {
72aa4a98
VS
196 while ((i < end_pos) && ((c = source[i++]) != '\'')) m_Params += c;
197 m_Params += c;
198 }
5526e819
VS
199 }
200 m_Begin = i;
201
4f9297b0 202 cache->QueryTag(pos, &m_End1, &m_End2);
5526e819
VS
203 if (m_End1 > end_pos) m_End1 = end_pos;
204 if (m_End2 > end_pos) m_End2 = end_pos;
205}
206
207
208
209bool wxHtmlTag::HasParam(const wxString& par) const
210{
66a77a74
OK
211 const wxChar *st = m_Params, *p = par;
212 const wxChar *st2, *p2;
5526e819
VS
213
214 if (*st == 0) return FALSE;
215 if (*p == 0) return FALSE;
4f9297b0
VS
216 for (st2 = st, p2 = p; ; st2++)
217 {
5526e819
VS
218 if (*p2 == 0) return TRUE;
219 if (*st2 == 0) return FALSE;
220 if (*p2 != *st2) p2 = p;
221 if (*p2 == *st2) p2++;
222 if (*st2 == ' ') p2 = p;
4f9297b0
VS
223 else if (*st2 == '=')
224 {
5526e819 225 p2 = p;
4f9297b0
VS
226 while (*st2 != ' ')
227 {
228 if (*st2 == '"')
229 {
5526e819
VS
230 st2++;
231 while (*st2 != '"') st2++;
232 }
233 st2++;
234 if (*st2 == 0) return FALSE;
235 }
236 }
237 }
238}
239
240
241
242wxString wxHtmlTag::GetParam(const wxString& par, bool with_commas) const
243{
66a77a74
OK
244 const wxChar *st = m_Params, *p = par;
245 const wxChar *st2, *p2;
5526e819 246 bool comma;
72aa4a98 247 char comma_char;
5526e819
VS
248
249 if (*st == 0) return "";
250 if (*p == 0) return "";
4f9297b0
VS
251 for (st2 = st, p2 = p; ; st2++)
252 {
253 if (*p2 == 0) // found
254 {
5526e819
VS
255 wxString fnd = "";
256 st2++; // '=' character
257 comma = FALSE;
4f9297b0
VS
258 comma_char = '\0';
259 if (!with_commas && (*(st2) == '"'))
260 {
261 st2++;
262 comma = TRUE;
263 comma_char = '"';
264 }
265 else if (!with_commas && (*(st2) == '\''))
266 {
267 st2++;
268 comma = TRUE;
269 comma_char = '\'';
270 }
271
272 while (*st2 != 0)
273 {
72aa4a98 274 if (comma && *st2 == comma_char) comma = FALSE;
5526e819
VS
275 else if ((*st2 == ' ') && (!comma)) break;
276 fnd += (*(st2++));
277 }
72aa4a98 278 if (!with_commas && (*(st2-1) == comma_char)) fnd.RemoveLast();
5526e819
VS
279 return fnd;
280 }
281 if (*st2 == 0) return "";
282 if (*p2 != *st2) p2 = p;
283 if (*p2 == *st2) p2++;
284 if (*st2 == ' ') p2 = p;
4f9297b0
VS
285 else if (*st2 == '=')
286 {
5526e819 287 p2 = p;
4f9297b0
VS
288 while (*st2 != ' ')
289 {
290 if (*st2 == '"')
291 {
5526e819
VS
292 st2++;
293 while (*st2 != '"') st2++;
294 }
4f9297b0
VS
295 else if (*st2 == '\'')
296 {
72aa4a98
VS
297 st2++;
298 while (*st2 != '\'') st2++;
299 }
5526e819
VS
300 st2++;
301 }
302 }
303 }
304}
305
306
307
66a77a74 308int wxHtmlTag::ScanParam(const wxString& par, wxChar *format, void *param) const
5526e819 309{
5526e819 310 wxString parval = GetParam(par);
66a77a74 311 return wxSscanf((const wxChar*)parval, format, param);
5526e819
VS
312}
313
4d223b67 314#endif