ReactOS  0.4.14-dev-554-g2f8d847
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 
54 static 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  */
71 static void parse_index_obj_node_param(IndexItem *item, const char *text, UINT code_page)
72 {
73  const char *ptr;
74  LPWSTR *param;
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;
125  IndexItem *item;
126 
127  strbuf_init(&node);
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 
148  strbuf_zero(&node);
149  }
150 
151  strbuf_free(&node);
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 
168  strbuf_init(&node);
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 
193  strbuf_zero(&node);
194  }
195  if(!ret)
196  FIXME("Failed to parse <li> tag!\n");
197 
198  strbuf_free(&node);
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 
221  strbuf_init(&node);
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 
257  strbuf_zero(&node);
258  }
259 
260  strbuf_free(&node);
261  strbuf_free(&node_name);
262 }
263 
264 /* Initialize the HTML Help Index tab */
266 {
267  IStream *stream;
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 {
290  IndexItem *item = info->index, *next;
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 }
WINE_DEFAULT_DEBUG_CHANNEL(htmlhelp)
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
void get_node_name(strbuf_t *node, strbuf_t *name)
Definition: stream.c:88
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
const WCHAR * text
Definition: package.c:1827
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
const char * get_attr(const char *node, const char *name, int *len)
Definition: stream.c:162
#define WARN(fmt,...)
Definition: debug.h:111
struct _TREEITEM * HTREEITEM
Definition: commctrl.h:3260
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
BOOL next_node(stream_t *stream, strbuf_t *buf)
Definition: stream.c:140
#define lstrlenW
Definition: compat.h:415
static void * heap_realloc(void *mem, size_t len)
Definition: appwiz.h:70
void InitIndex(HHInfo *info)
Definition: index.c:265
#define LVIF_TEXT
Definition: commctrl.h:2305
int cchTextMax
Definition: commctrl.h:2362
struct node node
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 debugstr_w
Definition: kernel32.h:32
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
LPARAM lParam
Definition: commctrl.h:2364
#define FIXME(fmt,...)
Definition: debug.h:110
static PVOID ptr
Definition: dispmode.c:27
void strbuf_free(strbuf_t *buf)
Definition: stream.c:38
void ReleaseIndex(HHInfo *info)
Definition: index.c:288
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
LONG_PTR LPARAM
Definition: windef.h:208
#define LVIF_INDENT
Definition: commctrl.h:2309
GLuint index
Definition: glext.h:6031
static void parse_index_obj_node_param(IndexItem *item, const char *text, UINT code_page)
Definition: index.c:71
#define TRACE(s)
Definition: solgame.cpp:4
WCHAR * decode_html(const char *html_fragment, int html_fragment_len, UINT code_page)
Definition: help.c:1890
Definition: hhctrl.h:185
LPWSTR pszText
Definition: commctrl.h:2361
GLfloat param
Definition: glext.h:5796
static void strbuf_init(strbuf *buf)
Definition: registrar.c:82
UINT mask
Definition: commctrl.h:2356
int ret
Definition: parse.h:22
LPWSTR keyword
Definition: hhctrl.h:80
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:47
GLuint GLuint stream
Definition: glext.h:7522
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define TAB_INDEX
Definition: hhctrl.h:117
void stream_init(stream_t *stream, IStream *str)
Definition: stream.c:54
void SetChmPath(ChmPath *file, LPCWSTR base_file, LPCWSTR path)
Definition: chm.c:496
#define LVM_INSERTITEMW
Definition: commctrl.h:2400
static unsigned __int64 next
Definition: rand_nt.c:6
static ATOM item
Definition: dde.c:856
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
unsigned int UINT
Definition: ndis.h:50
IStream * GetChmStream(CHMInfo *info, LPCWSTR parent_chm, ChmPath *chm_file)
Definition: chm.c:532
static IndexItem * parse_li(HHInfo *info, stream_t *stream)
Definition: index.c:163
#define LVIF_PARAM
Definition: commctrl.h:2307
IndexSubItem * items
Definition: hhctrl.h:86
static void fill_index_tree(HWND hwnd, IndexItem *item)
Definition: index.c:28
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static void parse_hhindex(HHInfo *info, IStream *str, IndexItem *item)
Definition: index.c:215
#define memset(x, y, z)
Definition: compat.h:39
void strbuf_zero(strbuf_t *buf)
Definition: stream.c:33
unsigned int index
Definition: notification.c:65
int iIndent
Definition: commctrl.h:2365
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
Definition: dlist.c:348
char * buf
Definition: stream.h:27