wxHtmlTag::ScanParam now returns value
[wxWidgets.git] / src / html / htmltag.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: htmltag.cpp
3 // Purpose: wxHtmlTag class (represents single tag)
4 // Author: Vaclav Slavik
5 // Copyright: (c) 1999 Vaclav Slavik
6 // Licence: wxWindows Licence
7 /////////////////////////////////////////////////////////////////////////////
8
9
10 #ifdef __GNUG__
11 #pragma implementation
12 #endif
13
14 #include <wx/wxprec.h>
15
16 #include "wx/defs.h"
17 #if wxUSE_HTML
18
19 #ifdef __BORDLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WXPRECOMP
24 #include <wx/wx.h>
25 #endif
26
27 #include <wx/html/htmltag.h>
28 #include <stdio.h> // for vsscanf
29 #include <stdarg.h>
30
31
32
33
34 //-----------------------------------------------------------------------------
35 // wxHtmlTagsCache
36 //-----------------------------------------------------------------------------
37
38 IMPLEMENT_CLASS(wxHtmlTagsCache,wxObject)
39
40 #define CACHE_INCREMENT 64
41
42 wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source)
43 {
44 const char *src = source.c_str();
45 int i, tg, pos, stpos;
46 int lng = source.Length();
47 char dummy[256];
48
49 m_Cache = NULL;
50 m_CacheSize = 0;
51 m_CachePos = 0;
52
53 pos = 0;
54 while (pos < lng) {
55 if (src[pos] == '<') { // tag found:
56 if (m_CacheSize % CACHE_INCREMENT == 0)
57 m_Cache = (sCacheItem*) realloc(m_Cache, (m_CacheSize + CACHE_INCREMENT) * sizeof(sCacheItem));
58 tg = m_CacheSize++;
59 m_Cache[tg].Key = stpos = pos++;
60 dummy[0] = 0; i = 0;
61 while ((src[pos] != '>') && (src[pos] != ' ')) {
62 dummy[i] = src[pos++];
63 if ((dummy[i] >= 'a') && (dummy[i] <= 'z')) dummy[i] -= ('a' - 'A');
64 i++;
65 }
66 dummy[i] = 0;
67 m_Cache[tg].Name = new char[i+1];
68 memcpy(m_Cache[tg].Name, dummy, i+1);
69
70 while (src[pos] != '>') pos++;
71
72 if (src[stpos+1] == '/') { // ending tag:
73 m_Cache[tg].End1 = m_Cache[tg].End2 = -2;
74 // find matching begin tag:
75 for (i = tg; i >= 0; i--)
76 if ((m_Cache[i].End1 == -1) && (strcmp(m_Cache[i].Name, dummy+1) == 0)) {
77 m_Cache[i].End1 = stpos;
78 m_Cache[i].End2 = pos + 1;
79 break;
80 }
81 }
82 else {
83 m_Cache[tg].End1 = m_Cache[tg].End2 = -1;
84 }
85 }
86
87 pos++;
88 }
89
90 // ok, we're done, now we'll free .Name members of cache - we don't need it anymore:
91 for (i = 0; i < m_CacheSize; i++) {
92 delete[] m_Cache[i].Name;
93 m_Cache[i].Name = NULL;
94 }
95 }
96
97
98
99 void wxHtmlTagsCache::QueryTag(int at, int* end1, int* end2)
100 {
101 if (m_Cache == NULL) return;
102 if (m_Cache[m_CachePos].Key != at) {
103 int delta = (at < m_Cache[m_CachePos].Key) ? -1 : 1;
104 do {m_CachePos += delta;} while (m_Cache[m_CachePos].Key != at);
105 }
106 *end1 = m_Cache[m_CachePos].End1;
107 *end2 = m_Cache[m_CachePos].End2;
108 }
109
110
111
112
113 //-----------------------------------------------------------------------------
114 // wxHtmlTag
115 //-----------------------------------------------------------------------------
116
117 IMPLEMENT_CLASS(wxHtmlTag,wxObject)
118
119 wxHtmlTag::wxHtmlTag(const wxString& source, int pos, int end_pos, wxHtmlTagsCache* cache) : wxObject()
120 {
121 int i;
122 char c;
123
124 // fill-in name, params and begin pos:
125 m_Name = m_Params = wxEmptyString;
126 i = pos+1;
127 if (source[i] == '/') {m_Ending = TRUE; i++;}
128 else m_Ending = FALSE;
129
130 while ((i < end_pos) && ((c = source[i++]) != ' ') && (c != '>')) {
131 if ((c >= 'a') && (c <= 'z')) c -= ('a' - 'A');
132 m_Name += c;
133 }
134
135 if (source[i-1] != '>')
136 while ((i < end_pos) && ((c = source[i++]) != '>')) {
137 if ((c >= 'a') && (c <= 'z')) c -= ('a' - 'A');
138 m_Params += c;
139 if (c == '"') {
140 while ((i < end_pos) && ((c = source[i++]) != '"')) m_Params += c;
141 m_Params += c;
142 }
143 else if (c == '\'') {
144 while ((i < end_pos) && ((c = source[i++]) != '\'')) m_Params += c;
145 m_Params += c;
146 }
147 }
148 m_Begin = i;
149
150 cache -> QueryTag(pos, &m_End1, &m_End2);
151 if (m_End1 > end_pos) m_End1 = end_pos;
152 if (m_End2 > end_pos) m_End2 = end_pos;
153 }
154
155
156
157 bool wxHtmlTag::HasParam(const wxString& par) const
158 {
159 const char *st = m_Params, *p = par;
160 const char *st2, *p2;
161
162 if (*st == 0) return FALSE;
163 if (*p == 0) return FALSE;
164 for (st2 = st, p2 = p; ; st2++) {
165 if (*p2 == 0) return TRUE;
166 if (*st2 == 0) return FALSE;
167 if (*p2 != *st2) p2 = p;
168 if (*p2 == *st2) p2++;
169 if (*st2 == ' ') p2 = p;
170 else if (*st2 == '=') {
171 p2 = p;
172 while (*st2 != ' ') {
173 if (*st2 == '"') {
174 st2++;
175 while (*st2 != '"') st2++;
176 }
177 st2++;
178 if (*st2 == 0) return FALSE;
179 }
180 }
181 }
182 }
183
184
185
186 wxString wxHtmlTag::GetParam(const wxString& par, bool with_commas) const
187 {
188 const char *st = m_Params, *p = par;
189 const char *st2, *p2;
190 bool comma;
191 char comma_char;
192
193 if (*st == 0) return "";
194 if (*p == 0) return "";
195 for (st2 = st, p2 = p; ; st2++) {
196 if (*p2 == 0) { // found
197 wxString fnd = "";
198 st2++; // '=' character
199 comma = FALSE;
200 comma_char = '\0';
201 if (!with_commas && (*(st2) == '"')) {
202 st2++;
203 comma = TRUE;
204 comma_char = '"';
205 }
206 else if (!with_commas && (*(st2) == '\'')) {
207 st2++;
208 comma = TRUE;
209 comma_char = '\'';
210 }
211 while (*st2 != 0) {
212 if (comma && *st2 == comma_char) comma = FALSE;
213 else if ((*st2 == ' ') && (!comma)) break;
214 fnd += (*(st2++));
215 }
216 if (!with_commas && (*(st2-1) == comma_char)) fnd.RemoveLast();
217 return fnd;
218 }
219 if (*st2 == 0) return "";
220 if (*p2 != *st2) p2 = p;
221 if (*p2 == *st2) p2++;
222 if (*st2 == ' ') p2 = p;
223 else if (*st2 == '=') {
224 p2 = p;
225 while (*st2 != ' ') {
226 if (*st2 == '"') {
227 st2++;
228 while (*st2 != '"') st2++;
229 }
230 else if (*st2 == '\'') {
231 st2++;
232 while (*st2 != '\'') st2++;
233 }
234 st2++;
235 }
236 }
237 }
238 }
239
240
241
242 int wxHtmlTag::ScanParam(const wxString& par, char *format, ...) const
243 {
244 int retval;
245 va_list argptr;
246 wxString parval = GetParam(par);
247
248 va_start(argptr, format);
249
250 //#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__VISUALC__)
251 #ifndef HAVE_VSSCANF
252 retval = sscanf((const char*)parval, format, va_arg(argptr, void *));
253 #else
254 retval = vsscanf((const char*)parval, format, argptr);
255 #endif
256
257 /*
258 --- vsscanf is not defined under some compilers
259 if this module doesn't compile with your compiler,
260 modify the def statement and let me know. Thanks...
261
262 So far wxHtml functions are scanning only _one_ value
263 so I workarounded this by supposing that there is only
264 one ...-parameter
265 */
266
267 va_end(argptr);
268 return retval;
269 }
270
271 #endif