Added test for vsscanf. GUESSING IS EVIL! Cannot test, my autoconf is too old.
[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 <stdarg.h>
29
30
31
32
33 //-----------------------------------------------------------------------------
34 // wxHtmlTagsCache
35 //-----------------------------------------------------------------------------
36
37 IMPLEMENT_CLASS(wxHtmlTagsCache,wxObject)
38
39 #define CACHE_INCREMENT 64
40
41 wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source)
42 {
43 const char *src = source.c_str();
44 int i, tg, pos, stpos;
45 int lng = source.Length();
46 char dummy[256];
47
48 m_Cache = NULL;
49 m_CacheSize = 0;
50 m_CachePos = 0;
51
52 pos = 0;
53 while (pos < lng) {
54 if (src[pos] == '<') { // tag found:
55 if (m_CacheSize % CACHE_INCREMENT == 0)
56 m_Cache = (sCacheItem*) realloc(m_Cache, (m_CacheSize + CACHE_INCREMENT) * sizeof(sCacheItem));
57 tg = m_CacheSize++;
58 m_Cache[tg].Key = stpos = pos++;
59 dummy[0] = 0; i = 0;
60 while ((src[pos] != '>') && (src[pos] != ' ')) {
61 dummy[i] = src[pos++];
62 if ((dummy[i] >= 'a') && (dummy[i] <= 'z')) dummy[i] -= ('a' - 'A');
63 i++;
64 }
65 dummy[i] = 0;
66 m_Cache[tg].Name = (char*) malloc(i+1);
67 memcpy(m_Cache[tg].Name, dummy, i+1);
68
69 while (src[pos] != '>') pos++;
70
71 if (src[stpos+1] == '/') { // ending tag:
72 m_Cache[tg].End1 = m_Cache[tg].End2 = -2;
73 // find matching begin tag:
74 for (i = tg; i >= 0; i--)
75 if ((m_Cache[i].End1 == -1) && (strcmp(m_Cache[i].Name, dummy+1) == 0)) {
76 m_Cache[i].End1 = stpos;
77 m_Cache[i].End2 = pos + 1;
78 break;
79 }
80 }
81 else {
82 m_Cache[tg].End1 = m_Cache[tg].End2 = -1;
83 }
84 }
85
86 pos++;
87 }
88
89 // ok, we're done, now we'll free .Name members of cache - we don't need it anymore:
90 for (i = 0; i < m_CacheSize; i++) {
91 free(m_Cache[i].Name);
92 m_Cache[i].Name = NULL;
93 }
94 }
95
96
97
98 void wxHtmlTagsCache::QueryTag(int at, int* end1, int* end2)
99 {
100 if (m_Cache == NULL) return;
101 if (m_Cache[m_CachePos].Key != at) {
102 int delta = (at < m_Cache[m_CachePos].Key) ? -1 : 1;
103 do {m_CachePos += delta;} while (m_Cache[m_CachePos].Key != at);
104 }
105 *end1 = m_Cache[m_CachePos].End1;
106 *end2 = m_Cache[m_CachePos].End2;
107 }
108
109
110
111
112 //-----------------------------------------------------------------------------
113 // wxHtmlTag
114 //-----------------------------------------------------------------------------
115
116 IMPLEMENT_CLASS(wxHtmlTag,wxObject)
117
118 wxHtmlTag::wxHtmlTag(const wxString& source, int pos, int end_pos, wxHtmlTagsCache* cache) : wxObject()
119 {
120 int i;
121 char c;
122
123 // fill-in name, params and begin pos:
124 m_Name = m_Params = wxEmptyString;
125 i = pos+1;
126 if (source[i] == '/') {m_Ending = TRUE; i++;}
127 else m_Ending = FALSE;
128
129 while ((i < end_pos) && ((c = source[i++]) != ' ') && (c != '>')) {
130 if ((c >= 'a') && (c <= 'z')) c -= ('a' - 'A');
131 m_Name += c;
132 }
133
134 if (source[i-1] != '>')
135 while ((i < end_pos) && ((c = source[i++]) != '>')) {
136 if ((c >= 'a') && (c <= 'z')) c -= ('a' - 'A');
137 m_Params += c;
138 if (c == '"') {
139 while ((i < end_pos) && ((c = source[i++]) != '"')) m_Params += c;
140 m_Params += c;
141 }
142 }
143 m_Begin = i;
144
145 cache -> QueryTag(pos, &m_End1, &m_End2);
146 if (m_End1 > end_pos) m_End1 = end_pos;
147 if (m_End2 > end_pos) m_End2 = end_pos;
148 }
149
150
151
152 bool wxHtmlTag::HasParam(const wxString& par) const
153 {
154 const char *st = m_Params, *p = par;
155 const char *st2, *p2;
156
157 if (*st == 0) return FALSE;
158 if (*p == 0) return FALSE;
159 for (st2 = st, p2 = p; ; st2++) {
160 if (*p2 == 0) return TRUE;
161 if (*st2 == 0) return FALSE;
162 if (*p2 != *st2) p2 = p;
163 if (*p2 == *st2) p2++;
164 if (*st2 == ' ') p2 = p;
165 else if (*st2 == '=') {
166 p2 = p;
167 while (*st2 != ' ') {
168 if (*st2 == '"') {
169 st2++;
170 while (*st2 != '"') st2++;
171 }
172 st2++;
173 if (*st2 == 0) return FALSE;
174 }
175 }
176 }
177 }
178
179
180
181 wxString wxHtmlTag::GetParam(const wxString& par, bool with_commas) const
182 {
183 const char *st = m_Params, *p = par;
184 const char *st2, *p2;
185 bool comma;
186
187 if (*st == 0) return "";
188 if (*p == 0) return "";
189 for (st2 = st, p2 = p; ; st2++) {
190 if (*p2 == 0) { // found
191 wxString fnd = "";
192 st2++; // '=' character
193 comma = FALSE;
194 if (!with_commas && (*(st2) == '"')) {st2++; comma = TRUE;}
195 while (*st2 != 0) {
196 if (*st2 == '"') comma = !comma;
197 else if ((*st2 == ' ') && (!comma)) break;
198 fnd += (*(st2++));
199 }
200 if (!with_commas && (*(st2-1) == '"')) fnd.RemoveLast();
201 return fnd;
202 }
203 if (*st2 == 0) return "";
204 if (*p2 != *st2) p2 = p;
205 if (*p2 == *st2) p2++;
206 if (*st2 == ' ') p2 = p;
207 else if (*st2 == '=') {
208 p2 = p;
209 while (*st2 != ' ') {
210 if (*st2 == '"') {
211 st2++;
212 while (*st2 != '"') st2++;
213 }
214 st2++;
215 }
216 }
217 }
218 }
219
220
221
222 void wxHtmlTag::ScanParam(const wxString& par, char *format, ...) const
223 {
224 va_list argptr;
225 wxString parval = GetParam(par);
226
227 va_start(argptr, format);
228
229 //#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__VISUALC__)
230 #ifndef HAVE_VSSCANF
231 sscanf((const char*)parval, format, va_arg(argptr, void *));
232 #else
233 vsscanf((const char*)parval, format, argptr);
234 #endif
235
236 /*
237 --- vsscanf is not defined under Cygwin or Mingw32 or M$ Visual C++ environment
238 if this module doesn't compile with your compiler,
239 modify the def statement and let me know. Thanks...
240
241 So far wxHtml functions are scanning only _one_ value
242 so I workarounded this by supposing that there is only
243 one ...-parameter
244 */
245
246 va_end(argptr);
247 }
248
249 #endif