Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencontent.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2007 Jacek Caban for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #define NONAMELESSUNION 00020 #define NONAMELESSSTRUCT 00021 00022 #include "hhctrl.h" 00023 #include "stream.h" 00024 00025 #include "wine/debug.h" 00026 00027 WINE_DEFAULT_DEBUG_CHANNEL(htmlhelp); 00028 00029 typedef enum { 00030 INSERT_NEXT, 00031 INSERT_CHILD 00032 } insert_type_t; 00033 00034 static void free_content_item(ContentItem *item) 00035 { 00036 ContentItem *next; 00037 00038 while(item) { 00039 next = item->next; 00040 00041 free_content_item(item->child); 00042 00043 heap_free(item->name); 00044 heap_free(item->local); 00045 heap_free(item->merge.chm_file); 00046 heap_free(item->merge.chm_index); 00047 00048 item = next; 00049 } 00050 } 00051 00052 static void parse_obj_node_param(ContentItem *item, ContentItem *hhc_root, const char *text) 00053 { 00054 const char *ptr; 00055 LPWSTR *param, merge; 00056 int len, wlen; 00057 00058 ptr = get_attr(text, "name", &len); 00059 if(!ptr) { 00060 WARN("name attr not found\n"); 00061 return; 00062 } 00063 00064 if(!strncasecmp("name", ptr, len)) { 00065 param = &item->name; 00066 }else if(!strncasecmp("merge", ptr, len)) { 00067 param = &merge; 00068 }else if(!strncasecmp("local", ptr, len)) { 00069 param = &item->local; 00070 }else { 00071 WARN("unhandled param %s\n", debugstr_an(ptr, len)); 00072 return; 00073 } 00074 00075 ptr = get_attr(text, "value", &len); 00076 if(!ptr) { 00077 WARN("value attr not found\n"); 00078 return; 00079 } 00080 00081 wlen = MultiByteToWideChar(CP_ACP, 0, ptr, len, NULL, 0); 00082 *param = heap_alloc((wlen+1)*sizeof(WCHAR)); 00083 MultiByteToWideChar(CP_ACP, 0, ptr, len, *param, wlen); 00084 (*param)[wlen] = 0; 00085 00086 if(param == &merge) { 00087 SetChmPath(&item->merge, hhc_root->merge.chm_file, merge); 00088 heap_free(merge); 00089 } 00090 } 00091 00092 static ContentItem *parse_hhc(HHInfo*,IStream*,ContentItem*,insert_type_t*); 00093 00094 static ContentItem *insert_item(ContentItem *item, ContentItem *new_item, insert_type_t insert_type) 00095 { 00096 if(!item) 00097 return new_item; 00098 00099 if(!new_item) 00100 return item; 00101 00102 switch(insert_type) { 00103 case INSERT_NEXT: 00104 item->next = new_item; 00105 return new_item; 00106 case INSERT_CHILD: 00107 if(item->child) { 00108 ContentItem *iter = item->child; 00109 while(iter->next) 00110 iter = iter->next; 00111 iter->next = new_item; 00112 }else { 00113 item->child = new_item; 00114 } 00115 return item; 00116 } 00117 00118 return NULL; 00119 } 00120 00121 static ContentItem *parse_sitemap_object(HHInfo *info, stream_t *stream, ContentItem *hhc_root, 00122 insert_type_t *insert_type) 00123 { 00124 strbuf_t node, node_name; 00125 ContentItem *item; 00126 00127 *insert_type = INSERT_NEXT; 00128 00129 strbuf_init(&node); 00130 strbuf_init(&node_name); 00131 00132 item = heap_alloc_zero(sizeof(ContentItem)); 00133 00134 while(next_node(stream, &node)) { 00135 get_node_name(&node, &node_name); 00136 00137 TRACE("%s\n", node.buf); 00138 00139 if(!strcasecmp(node_name.buf, "/object")) 00140 break; 00141 if(!strcasecmp(node_name.buf, "param")) 00142 parse_obj_node_param(item, hhc_root, node.buf); 00143 00144 strbuf_zero(&node); 00145 } 00146 00147 strbuf_free(&node); 00148 strbuf_free(&node_name); 00149 00150 if(item->merge.chm_index) { 00151 IStream *merge_stream; 00152 00153 merge_stream = GetChmStream(info->pCHMInfo, item->merge.chm_file, &item->merge); 00154 if(merge_stream) { 00155 item->child = parse_hhc(info, merge_stream, hhc_root, insert_type); 00156 IStream_Release(merge_stream); 00157 }else { 00158 WARN("Could not get %s::%s stream\n", debugstr_w(item->merge.chm_file), 00159 debugstr_w(item->merge.chm_file)); 00160 00161 if(!item->name) { 00162 free_content_item(item); 00163 item = NULL; 00164 } 00165 } 00166 00167 } 00168 00169 return item; 00170 } 00171 00172 static ContentItem *parse_ul(HHInfo *info, stream_t *stream, ContentItem *hhc_root) 00173 { 00174 strbuf_t node, node_name; 00175 ContentItem *ret = NULL, *prev = NULL, *new_item = NULL; 00176 insert_type_t it; 00177 00178 strbuf_init(&node); 00179 strbuf_init(&node_name); 00180 00181 while(next_node(stream, &node)) { 00182 get_node_name(&node, &node_name); 00183 00184 TRACE("%s\n", node.buf); 00185 00186 if(!strcasecmp(node_name.buf, "object")) { 00187 const char *ptr; 00188 int len; 00189 00190 static const char sz_text_sitemap[] = "text/sitemap"; 00191 00192 ptr = get_attr(node.buf, "type", &len); 00193 00194 if(ptr && len == sizeof(sz_text_sitemap)-1 00195 && !memcmp(ptr, sz_text_sitemap, len)) { 00196 new_item = parse_sitemap_object(info, stream, hhc_root, &it); 00197 prev = insert_item(prev, new_item, it); 00198 if(!ret) 00199 ret = prev; 00200 } 00201 }else if(!strcasecmp(node_name.buf, "ul")) { 00202 new_item = parse_ul(info, stream, hhc_root); 00203 insert_item(prev, new_item, INSERT_CHILD); 00204 }else if(!strcasecmp(node_name.buf, "/ul")) { 00205 break; 00206 } 00207 00208 strbuf_zero(&node); 00209 } 00210 00211 strbuf_free(&node); 00212 strbuf_free(&node_name); 00213 00214 return ret; 00215 } 00216 00217 static ContentItem *parse_hhc(HHInfo *info, IStream *str, ContentItem *hhc_root, 00218 insert_type_t *insert_type) 00219 { 00220 stream_t stream; 00221 strbuf_t node, node_name; 00222 ContentItem *ret = NULL, *prev = NULL; 00223 00224 *insert_type = INSERT_NEXT; 00225 00226 strbuf_init(&node); 00227 strbuf_init(&node_name); 00228 00229 stream_init(&stream, str); 00230 00231 while(next_node(&stream, &node)) { 00232 get_node_name(&node, &node_name); 00233 00234 TRACE("%s\n", node.buf); 00235 00236 if(!strcasecmp(node_name.buf, "ul")) { 00237 ContentItem *item = parse_ul(info, &stream, hhc_root); 00238 prev = insert_item(prev, item, INSERT_CHILD); 00239 if(!ret) 00240 ret = prev; 00241 *insert_type = INSERT_CHILD; 00242 } 00243 00244 strbuf_zero(&node); 00245 } 00246 00247 strbuf_free(&node); 00248 strbuf_free(&node_name); 00249 00250 return ret; 00251 } 00252 00253 static void insert_content_item(HWND hwnd, ContentItem *parent, ContentItem *item) 00254 { 00255 TVINSERTSTRUCTW tvis; 00256 00257 memset(&tvis, 0, sizeof(tvis)); 00258 tvis.u.item.mask = TVIF_TEXT|TVIF_PARAM; 00259 tvis.u.item.cchTextMax = strlenW(item->name)+1; 00260 tvis.u.item.pszText = item->name; 00261 tvis.u.item.lParam = (LPARAM)item; 00262 tvis.hParent = parent ? parent->id : 0; 00263 tvis.hInsertAfter = TVI_LAST; 00264 00265 item->id = (HTREEITEM)SendMessageW(hwnd, TVM_INSERTITEMW, 0, (LPARAM)&tvis); 00266 } 00267 00268 static void fill_content_tree(HWND hwnd, ContentItem *parent, ContentItem *item) 00269 { 00270 while(item) { 00271 if(item->name) { 00272 insert_content_item(hwnd, parent, item); 00273 fill_content_tree(hwnd, item, item->child); 00274 }else { 00275 fill_content_tree(hwnd, parent, item->child); 00276 } 00277 item = item->next; 00278 } 00279 } 00280 00281 static void set_item_parents(ContentItem *parent, ContentItem *item) 00282 { 00283 while(item) { 00284 item->parent = parent; 00285 set_item_parents(item, item->child); 00286 item = item->next; 00287 } 00288 } 00289 00290 void InitContent(HHInfo *info) 00291 { 00292 IStream *stream; 00293 insert_type_t insert_type; 00294 00295 info->content = heap_alloc_zero(sizeof(ContentItem)); 00296 SetChmPath(&info->content->merge, info->pCHMInfo->szFile, info->WinType.pszToc); 00297 00298 stream = GetChmStream(info->pCHMInfo, info->pCHMInfo->szFile, &info->content->merge); 00299 if(!stream) { 00300 TRACE("Could not get content stream\n"); 00301 return; 00302 } 00303 00304 info->content->child = parse_hhc(info, stream, info->content, &insert_type); 00305 IStream_Release(stream); 00306 00307 set_item_parents(NULL, info->content); 00308 fill_content_tree(info->tabs[TAB_CONTENTS].hwnd, NULL, info->content); 00309 } 00310 00311 void ReleaseContent(HHInfo *info) 00312 { 00313 free_content_item(info->content); 00314 } Generated on Sat May 26 2012 04:19:44 for ReactOS by
1.7.6.1
|