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

index.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2007 Jacek Caban for CodeWeavers
00003  * Copyright 2010 Erich Hoover
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00018  */
00019 
00020 #define NONAMELESSUNION
00021 #define NONAMELESSSTRUCT
00022 
00023 #include "hhctrl.h"
00024 #include "stream.h"
00025 
00026 #include "wine/debug.h"
00027 
00028 WINE_DEFAULT_DEBUG_CHANNEL(htmlhelp);
00029 
00030 /* Fill the TreeView object corresponding to the Index items */
00031 static void fill_index_tree(HWND hwnd, IndexItem *item)
00032 {
00033     int index = 0;
00034     LVITEMW lvi;
00035 
00036     while(item) {
00037         TRACE("tree debug: %s\n", debugstr_w(item->keyword));
00038 
00039         if(!item->keyword)
00040         {
00041             FIXME("HTML Help index item has no keyword.\n");
00042             item = item->next;
00043             continue;
00044         }
00045         memset(&lvi, 0, sizeof(lvi));
00046         lvi.iItem = index++;
00047         lvi.mask = LVIF_TEXT|LVIF_PARAM|LVIF_INDENT;
00048         lvi.iIndent = item->indentLevel;
00049         lvi.cchTextMax = strlenW(item->keyword)+1;
00050         lvi.pszText = item->keyword;
00051         lvi.lParam = (LPARAM)item;
00052         item->id = (HTREEITEM)SendMessageW(hwnd, LVM_INSERTITEMW, 0, (LPARAM)&lvi);
00053         item = item->next;
00054     }
00055 }
00056 
00057 /* Parse the attributes correspond to a list item, including sub-topics.
00058  *
00059  * Each list item has, at minimum, a param of type "keyword" and two
00060  * parameters corresponding to a "sub-topic."  For each sub-topic there
00061  * must be a "name" param and a "local" param, if there is only one
00062  * sub-topic then there isn't really a sub-topic, the index will jump
00063  * directly to the requested item.
00064  */
00065 static void parse_index_obj_node_param(IndexItem *item, const char *text)
00066 {
00067     const char *ptr;
00068     LPWSTR *param;
00069     int len, wlen;
00070 
00071     ptr = get_attr(text, "name", &len);
00072     if(!ptr) {
00073         WARN("name attr not found\n");
00074         return;
00075     }
00076 
00077     /* Allocate a new sub-item, either on the first run or whenever a
00078      * sub-topic has filled out both the "name" and "local" params.
00079      */
00080     if(item->itemFlags == 0x11 && (!strncasecmp("name", ptr, len) || !strncasecmp("local", ptr, len))) {
00081         item->nItems++;
00082         item->items = heap_realloc(item->items, sizeof(IndexSubItem)*item->nItems);
00083         item->items[item->nItems-1].name = NULL;
00084         item->items[item->nItems-1].local = NULL;
00085         item->itemFlags = 0x00;
00086     }
00087     if(!strncasecmp("keyword", ptr, len)) {
00088         param = &item->keyword;
00089     }else if(!item->keyword && !strncasecmp("name", ptr, len)) {
00090         /* Some HTML Help index files use an additional "name" parameter
00091          * rather than the "keyword" parameter.  In this case, the first
00092          * occurance of the "name" parameter is the keyword.
00093          */
00094         param = &item->keyword;
00095     }else if(!strncasecmp("name", ptr, len)) {
00096         item->itemFlags |= 0x01;
00097         param = &item->items[item->nItems-1].name;
00098     }else if(!strncasecmp("local", ptr, len)) {
00099         item->itemFlags |= 0x10;
00100         param = &item->items[item->nItems-1].local;
00101     }else {
00102         WARN("unhandled param %s\n", debugstr_an(ptr, len));
00103         return;
00104     }
00105 
00106     ptr = get_attr(text, "value", &len);
00107     if(!ptr) {
00108         WARN("value attr not found\n");
00109         return;
00110     }
00111 
00112     wlen = MultiByteToWideChar(CP_ACP, 0, ptr, len, NULL, 0);
00113     *param = heap_alloc((wlen+1)*sizeof(WCHAR));
00114     MultiByteToWideChar(CP_ACP, 0, ptr, len, *param, wlen);
00115     (*param)[wlen] = 0;
00116 }
00117 
00118 /* Parse the object tag corresponding to a list item.
00119  *
00120  * At this step we look for all of the "param" child tags, using this information
00121  * to build up the information about the list item.  When we reach the </object>
00122  * tag we know that we've finished parsing this list item.
00123  */
00124 static IndexItem *parse_index_sitemap_object(HHInfo *info, stream_t *stream)
00125 {
00126     strbuf_t node, node_name;
00127     IndexItem *item;
00128 
00129     strbuf_init(&node);
00130     strbuf_init(&node_name);
00131 
00132     item = heap_alloc_zero(sizeof(IndexItem));
00133     item->nItems = 0;
00134     item->items = heap_alloc_zero(0);
00135     item->itemFlags = 0x11;
00136 
00137     while(next_node(stream, &node)) {
00138         get_node_name(&node, &node_name);
00139 
00140         TRACE("%s\n", node.buf);
00141 
00142         if(!strcasecmp(node_name.buf, "param")) {
00143             parse_index_obj_node_param(item, node.buf);
00144         }else if(!strcasecmp(node_name.buf, "/object")) {
00145             break;
00146         }else {
00147             WARN("Unhandled tag! %s\n", node_name.buf);
00148         }
00149 
00150         strbuf_zero(&node);
00151     }
00152 
00153     strbuf_free(&node);
00154     strbuf_free(&node_name);
00155 
00156     return item;
00157 }
00158 
00159 /* Parse the HTML list item node corresponding to a specific help entry.
00160  *
00161  * At this stage we look for the only child tag we expect to find under
00162  * the list item: the <OBJECT> tag.  We also only expect to find object
00163  * tags with the "type" attribute set to "text/sitemap".
00164  */
00165 static IndexItem *parse_li(HHInfo *info, stream_t *stream)
00166 {
00167     strbuf_t node, node_name;
00168     IndexItem *ret = NULL;
00169 
00170     strbuf_init(&node);
00171     strbuf_init(&node_name);
00172 
00173     while(next_node(stream, &node)) {
00174         get_node_name(&node, &node_name);
00175 
00176         TRACE("%s\n", node.buf);
00177 
00178         if(!strcasecmp(node_name.buf, "object")) {
00179             const char *ptr;
00180             int len;
00181 
00182             static const char sz_text_sitemap[] = "text/sitemap";
00183 
00184             ptr = get_attr(node.buf, "type", &len);
00185 
00186             if(ptr && len == sizeof(sz_text_sitemap)-1
00187                && !memcmp(ptr, sz_text_sitemap, len)) {
00188                 ret = parse_index_sitemap_object(info, stream);
00189                 break;
00190             }
00191         }else {
00192             WARN("Unhandled tag! %s\n", node_name.buf);
00193         }
00194 
00195         strbuf_zero(&node);
00196     }
00197 
00198     strbuf_free(&node);
00199     strbuf_free(&node_name);
00200 
00201     return ret;
00202 }
00203 
00204 /* Parse the HTML Help page corresponding to all of the Index items.
00205  *
00206  * At this high-level stage we locate out each HTML list item tag.
00207  * Since there is no end-tag for the <LI> item, we must hope that
00208  * the <LI> entry is parsed correctly or tags might get lost.
00209  *
00210  * Within each entry it is also possible to encounter an additional
00211  * <UL> tag.  When this occurs the tag indicates that the topics
00212  * contained within it are related to the parent <LI> topic and
00213  * should be inset by an indent.
00214  */
00215 static void parse_hhindex(HHInfo *info, IStream *str, IndexItem *item)
00216 {
00217     stream_t stream;
00218     strbuf_t node, node_name;
00219     int indent_level = -1;
00220 
00221     strbuf_init(&node);
00222     strbuf_init(&node_name);
00223 
00224     stream_init(&stream, str);
00225 
00226     while(next_node(&stream, &node)) {
00227         get_node_name(&node, &node_name);
00228 
00229         TRACE("%s\n", node.buf);
00230 
00231         if(!strcasecmp(node_name.buf, "li")) {
00232             item->next = parse_li(info, &stream);
00233             item->next->merge = item->merge;
00234             item = item->next;
00235             item->indentLevel = indent_level;
00236         }else if(!strcasecmp(node_name.buf, "ul")) {
00237             indent_level++;
00238         }else if(!strcasecmp(node_name.buf, "/ul")) {
00239             indent_level--;
00240         }else {
00241             WARN("Unhandled tag! %s\n", node_name.buf);
00242         }
00243 
00244         strbuf_zero(&node);
00245     }
00246 
00247     strbuf_free(&node);
00248     strbuf_free(&node_name);
00249 }
00250 
00251 /* Initialize the HTML Help Index tab */
00252 void InitIndex(HHInfo *info)
00253 {
00254     IStream *stream;
00255 
00256     info->index = heap_alloc_zero(sizeof(IndexItem));
00257     info->index->nItems = 0;
00258     SetChmPath(&info->index->merge, info->pCHMInfo->szFile, info->WinType.pszIndex);
00259 
00260     stream = GetChmStream(info->pCHMInfo, info->pCHMInfo->szFile, &info->index->merge);
00261     if(!stream) {
00262         TRACE("Could not get index stream\n");
00263         return;
00264     }
00265 
00266     parse_hhindex(info, stream, info->index);
00267     IStream_Release(stream);
00268 
00269     fill_index_tree(info->tabs[TAB_INDEX].hwnd, info->index->next);
00270 }
00271 
00272 /* Free all of the Index items, including all of the "sub-items" that
00273  * correspond to different sub-topics.
00274  */
00275 void ReleaseIndex(HHInfo *info)
00276 {
00277     IndexItem *item = info->index, *next;
00278     int i;
00279 
00280     /* Note: item->merge is identical for all items, only free once */
00281     heap_free(item->merge.chm_file);
00282     heap_free(item->merge.chm_index);
00283     while(item) {
00284         next = item->next;
00285 
00286         heap_free(item->keyword);
00287         for(i=0;i<item->nItems;i++) {
00288             heap_free(item->items[i].name);
00289             heap_free(item->items[i].local);
00290         }
00291         heap_free(item->items);
00292 
00293         item = next;
00294     }
00295 }

Generated on Sat May 26 2012 04:22:22 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.