ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

content.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.