2 * Copyright 2007 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/debug.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(htmlhelp
);
26 void strbuf_init(strbuf_t
*buf
)
30 buf
->buf
= heap_alloc(buf
->size
);
33 void strbuf_zero(strbuf_t
*buf
)
38 void strbuf_free(strbuf_t
*buf
)
43 static void strbuf_append(strbuf_t
*buf
, const char *data
, int len
)
45 if(buf
->len
+len
> buf
->size
) {
46 buf
->size
= buf
->len
+len
;
47 buf
->buf
= heap_realloc(buf
->buf
, buf
->size
);
50 memcpy(buf
->buf
+buf
->len
, data
, len
);
54 void stream_init(stream_t
*stream
, IStream
*str
)
56 memset(stream
, 0, sizeof(stream_t
));
60 static BOOL
stream_chr(stream_t
*stream
, strbuf_t
*buf
, char c
)
66 for(i
=stream
->p
; i
<stream
->size
; i
++) {
67 if(stream
->buf
[i
] == c
) {
73 if(buf
&& i
> stream
->p
)
74 strbuf_append(buf
, stream
->buf
+stream
->p
, i
-stream
->p
);
77 if(stream
->p
== stream
->size
) {
79 IStream_Read(stream
->str
, stream
->buf
, sizeof(stream
->buf
), &stream
->size
);
85 return stream
->size
!= 0;
88 void get_node_name(strbuf_t
*node
, strbuf_t
*name
)
90 const char *ptr
= node
->buf
+1;
94 while(*ptr
!= '>' && !isspace(*ptr
))
97 strbuf_append(name
, node
->buf
+1, ptr
-node
->buf
-1);
98 strbuf_append(name
, "", 1);
101 /* Return the stream content up to the next HTML tag.
103 * Note: the first returned character is the end of the last tag (>).
105 BOOL
next_content(stream_t
*stream
, strbuf_t
*buf
)
107 if(!stream_chr(stream
, buf
, '<'))
113 static BOOL
find_node_end(stream_t
*stream
, strbuf_t
*buf
)
115 int tag_count
= 0, b
= buf
->len
;
120 if(!stream_chr(stream
, buf
, '>'))
125 while((p
= memchr(p
+1, '"', buf
->len
-(p
+1-buf
->buf
))) != NULL
)
128 if(tag_count
% 2 != 0)
130 if(!stream_chr(stream
, buf
, '"'))
140 BOOL
next_node(stream_t
*stream
, strbuf_t
*buf
)
144 /* search through the end of the current node */
145 strbuf_init(&tmpbuf
);
146 if(!find_node_end(stream
, &tmpbuf
))
148 strbuf_free(&tmpbuf
);
151 strbuf_free(&tmpbuf
);
153 /* find the beginning of the next node */
154 if(!stream_chr(stream
, NULL
, '<'))
157 /* read out the data of the next node */
158 if(!find_node_end(stream
, buf
))
161 strbuf_append(buf
, ">", 2);
167 * Find the value of a named HTML attribute.
169 * Note: Attribute names are case insensitive, so it is necessary to
170 * put both the node text and the attribute name in the same case
171 * before attempting a string search.
173 const char *get_attr(const char *node
, const char *name
, int *len
)
175 const char *ptr
, *ptr2
;
176 int name_len
, node_len
;
181 /* Create a lower case copy of the node */
182 node_len
= strlen(node
)+1;
183 node_buf
= heap_alloc(node_len
*sizeof(char));
186 memcpy(node_buf
, node
, node_len
);
187 for(i
=0;i
<node_len
;i
++)
188 node_buf
[i
] = tolower(node_buf
[i
]);
189 /* Create a lower case copy of the attribute name (search string) */
190 name_len
= strlen(name
);
191 memcpy(name_buf
, name
, name_len
);
192 for(i
=0;i
<name_len
;i
++)
193 name_buf
[i
] = tolower(name_buf
[i
]);
194 name_buf
[name_len
++] = '=';
195 name_buf
[name_len
++] = '\"';
196 name_buf
[name_len
] = 0;
198 ptr
= strstr(node_buf
, name_buf
);
200 WARN("name not found\n");
206 ptr2
= strchr(ptr
, '\"');
214 /* Return the pointer offset within the original string */
215 ptr
= node
+(ptr
-node_buf
);