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