ReactOS 0.4.15-dev-7961-gdcf9eb0
index.c
Go to the documentation of this file.
1/*
2 * Copyright 2007 Jacek Caban for CodeWeavers
3 * Copyright 2010 Erich Hoover
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20#include "hhctrl.h"
21#include "stream.h"
22
23#include "wine/debug.h"
24
26
27/* Fill the TreeView object corresponding to the Index items */
29{
30 int index = 0;
31 LVITEMW lvi;
32
33 while(item) {
34 TRACE("tree debug: %s\n", debugstr_w(item->keyword));
35
36 if(!item->keyword)
37 {
38 FIXME("HTML Help index item has no keyword.\n");
39 item = item->next;
40 continue;
41 }
42 memset(&lvi, 0, sizeof(lvi));
43 lvi.iItem = index++;
45 lvi.iIndent = item->indentLevel;
46 lvi.cchTextMax = lstrlenW(item->keyword)+1;
47 lvi.pszText = item->keyword;
48 lvi.lParam = (LPARAM)item;
50 item = item->next;
51 }
52}
53
54static void item_realloc(IndexItem *item, int num_items)
55{
56 item->nItems = num_items;
57 item->items = heap_realloc(item->items, sizeof(IndexSubItem)*item->nItems);
58 item->items[item->nItems-1].name = NULL;
59 item->items[item->nItems-1].local = NULL;
60 item->itemFlags = 0x00;
61}
62
63/* Parse the attributes correspond to a list item, including sub-topics.
64 *
65 * Each list item has, at minimum, a param of type "keyword" and two
66 * parameters corresponding to a "sub-topic." For each sub-topic there
67 * must be a "name" param and a "local" param, if there is only one
68 * sub-topic then there isn't really a sub-topic, the index will jump
69 * directly to the requested item.
70 */
71static void parse_index_obj_node_param(IndexItem *item, const char *text, UINT code_page)
72{
73 const char *ptr;
75 int len;
76
77 ptr = get_attr(text, "name", &len);
78 if(!ptr) {
79 WARN("name attr not found\n");
80 return;
81 }
82
83 /* Allocate a new sub-item, either on the first run or whenever a
84 * sub-topic has filled out both the "name" and "local" params.
85 */
86 if(item->itemFlags == 0x11 && (!_strnicmp("name", ptr, len) || !_strnicmp("local", ptr, len)))
87 item_realloc(item, item->nItems+1);
88 if(!_strnicmp("keyword", ptr, len)) {
89 param = &item->keyword;
90 }else if(!item->keyword && !_strnicmp("name", ptr, len)) {
91 /* Some HTML Help index files use an additional "name" parameter
92 * rather than the "keyword" parameter. In this case, the first
93 * occurrence of the "name" parameter is the keyword.
94 */
95 param = &item->keyword;
96 }else if(!_strnicmp("name", ptr, len)) {
97 item->itemFlags |= 0x01;
98 param = &item->items[item->nItems-1].name;
99 }else if(!_strnicmp("local", ptr, len)) {
100 item->itemFlags |= 0x10;
101 param = &item->items[item->nItems-1].local;
102 }else {
103 WARN("unhandled param %s\n", debugstr_an(ptr, len));
104 return;
105 }
106
107 ptr = get_attr(text, "value", &len);
108 if(!ptr) {
109 WARN("value attr not found\n");
110 return;
111 }
112
113 *param = decode_html(ptr, len, code_page);
114}
115
116/* Parse the object tag corresponding to a list item.
117 *
118 * At this step we look for all of the "param" child tags, using this information
119 * to build up the information about the list item. When we reach the </object>
120 * tag we know that we've finished parsing this list item.
121 */
123{
124 strbuf_t node, node_name;
126
128 strbuf_init(&node_name);
129
130 item = heap_alloc_zero(sizeof(IndexItem));
131 item->nItems = 0;
132 item->items = heap_alloc_zero(0);
133 item->itemFlags = 0x11;
134
135 while(next_node(stream, &node)) {
136 get_node_name(&node, &node_name);
137
138 TRACE("%s\n", node.buf);
139
140 if(!_strnicmp(node_name.buf, "param", -1)) {
141 parse_index_obj_node_param(item, node.buf, info->pCHMInfo->codePage);
142 }else if(!_strnicmp(node_name.buf, "/object", -1)) {
143 break;
144 }else {
145 WARN("Unhandled tag! %s\n", node_name.buf);
146 }
147
149 }
150
152 strbuf_free(&node_name);
153
154 return item;
155}
156
157/* Parse the HTML list item node corresponding to a specific help entry.
158 *
159 * At this stage we look for the only child tag we expect to find under
160 * the list item: the <OBJECT> tag. We also only expect to find object
161 * tags with the "type" attribute set to "text/sitemap".
162 */
164{
165 strbuf_t node, node_name;
166 IndexItem *ret = NULL;
167
169 strbuf_init(&node_name);
170
171 while(next_node(stream, &node)) {
172 get_node_name(&node, &node_name);
173
174 TRACE("%s\n", node.buf);
175
176 if(!_strnicmp(node_name.buf, "object", -1)) {
177 const char *ptr;
178 int len;
179
180 static const char sz_text_sitemap[] = "text/sitemap";
181
182 ptr = get_attr(node.buf, "type", &len);
183
184 if(ptr && len == sizeof(sz_text_sitemap)-1
185 && !memcmp(ptr, sz_text_sitemap, len)) {
187 break;
188 }
189 }else {
190 WARN("Unhandled tag! %s\n", node_name.buf);
191 }
192
194 }
195 if(!ret)
196 FIXME("Failed to parse <li> tag!\n");
197
199 strbuf_free(&node_name);
200
201 return ret;
202}
203
204/* Parse the HTML Help page corresponding to all of the Index items.
205 *
206 * At this high-level stage we locate out each HTML list item tag.
207 * Since there is no end-tag for the <LI> item, we must hope that
208 * the <LI> entry is parsed correctly or tags might get lost.
209 *
210 * Within each entry it is also possible to encounter an additional
211 * <UL> tag. When this occurs the tag indicates that the topics
212 * contained within it are related to the parent <LI> topic and
213 * should be inset by an indent.
214 */
216{
218 strbuf_t node, node_name;
219 int indent_level = -1;
220
222 strbuf_init(&node_name);
223
225
226 while(next_node(&stream, &node)) {
227 get_node_name(&node, &node_name);
228
229 TRACE("%s\n", node.buf);
230
231 if(!_strnicmp(node_name.buf, "li", -1)) {
232 IndexItem *new_item;
233
234 new_item = parse_li(info, &stream);
235 if(new_item && item->keyword && lstrcmpW(new_item->keyword, item->keyword) == 0) {
236 int num_items = item->nItems;
237
238 item_realloc(item, num_items+1);
239 memcpy(&item->items[num_items], &new_item->items[0], sizeof(IndexSubItem));
240 heap_free(new_item->keyword);
241 heap_free(new_item->items);
242 heap_free(new_item);
243 } else if(new_item) {
244 item->next = new_item;
245 item->next->merge = item->merge;
246 item = item->next;
247 item->indentLevel = indent_level;
248 }
249 }else if(!_strnicmp(node_name.buf, "ul", -1)) {
250 indent_level++;
251 }else if(!_strnicmp(node_name.buf, "/ul", -1)) {
252 indent_level--;
253 }else {
254 WARN("Unhandled tag! %s\n", node_name.buf);
255 }
256
258 }
259
261 strbuf_free(&node_name);
262}
263
264/* Initialize the HTML Help Index tab */
266{
268
269 info->index = heap_alloc_zero(sizeof(IndexItem));
270 info->index->nItems = 0;
271 SetChmPath(&info->index->merge, info->pCHMInfo->szFile, info->WinType.pszIndex);
272
273 stream = GetChmStream(info->pCHMInfo, info->pCHMInfo->szFile, &info->index->merge);
274 if(!stream) {
275 TRACE("Could not get index stream\n");
276 return;
277 }
278
280 IStream_Release(stream);
281
282 fill_index_tree(info->tabs[TAB_INDEX].hwnd, info->index->next);
283}
284
285/* Free all of the Index items, including all of the "sub-items" that
286 * correspond to different sub-topics.
287 */
289{
291 int i;
292
293 if(!item) return;
294 /* Note: item->merge is identical for all items, only free once */
295 heap_free(item->merge.chm_file);
296 heap_free(item->merge.chm_index);
297 while(item) {
298 next = item->next;
299
300 heap_free(item->keyword);
301 for(i=0;i<item->nItems;i++) {
302 heap_free(item->items[i].name);
303 heap_free(item->items[i].local);
304 }
305 heap_free(item->items);
306
307 item = next;
308 }
309}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:71
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
void SetChmPath(ChmPath *file, LPCWSTR base_file, LPCWSTR path)
Definition: chm.c:503
IStream * GetChmStream(CHMInfo *info, LPCWSTR parent_chm, ChmPath *chm_file)
Definition: chm.c:539
#define NULL
Definition: types.h:112
static void strbuf_init(strbuf *buf)
Definition: registrar.c:82
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
#define lstrlenW
Definition: compat.h:750
WCHAR * decode_html(const char *html_fragment, int html_fragment_len, UINT code_page)
Definition: help.c:1902
static void parse_hhindex(HHInfo *info, IStream *str, IndexItem *item)
Definition: index.c:215
static IndexItem * parse_li(HHInfo *info, stream_t *stream)
Definition: index.c:163
void ReleaseIndex(HHInfo *info)
Definition: index.c:288
void InitIndex(HHInfo *info)
Definition: index.c:265
static void parse_index_obj_node_param(IndexItem *item, const char *text, UINT code_page)
Definition: index.c:71
static IndexItem * parse_index_sitemap_object(HHInfo *info, stream_t *stream)
Definition: index.c:122
static void item_realloc(IndexItem *item, int num_items)
Definition: index.c:54
static void fill_index_tree(HWND hwnd, IndexItem *item)
Definition: index.c:28
const char * get_attr(const char *node, const char *name, int *len)
Definition: stream.c:162
void strbuf_free(strbuf_t *buf)
Definition: stream.c:38
BOOL next_node(stream_t *stream, strbuf_t *buf)
Definition: stream.c:140
void strbuf_zero(strbuf_t *buf)
Definition: stream.c:33
void stream_init(stream_t *stream, IStream *str)
Definition: stream.c:54
void get_node_name(strbuf_t *node, strbuf_t *name)
Definition: stream.c:88
const WCHAR * text
Definition: package.c:1799
GLuint index
Definition: glext.h:6031
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define TAB_INDEX
Definition: hhctrl.h:117
#define debugstr_w
Definition: kernel32.h:32
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
static ATOM item
Definition: dde.c:856
unsigned int UINT
Definition: ndis.h:50
#define LVIF_INDENT
Definition: commctrl.h:2313
struct _TREEITEM * HTREEITEM
Definition: commctrl.h:3264
#define LVIF_PARAM
Definition: commctrl.h:2311
#define LVIF_TEXT
Definition: commctrl.h:2309
#define LVM_INSERTITEMW
Definition: commctrl.h:2404
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * str
Console I/O streams.
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
Definition: hhctrl.h:185
IndexSubItem * items
Definition: hhctrl.h:86
LPWSTR keyword
Definition: hhctrl.h:80
unsigned int index
Definition: notification.c:65
char * buf
Definition: stream.h:27
Definition: parse.h:23
LPWSTR pszText
Definition: commctrl.h:2365
int cchTextMax
Definition: commctrl.h:2366
UINT mask
Definition: commctrl.h:2360
LPARAM lParam
Definition: commctrl.h:2368
int iIndent
Definition: commctrl.h:2369
Definition: dlist.c:348
int ret
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
WCHAR * LPWSTR
Definition: xmlstorage.h:184