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

search.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Erich Hoover
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 static SearchItem *SearchCHM_Folder(SearchItem *item, IStorage *pStorage,
00030                                     const WCHAR *folder, const char *needle);
00031 
00032 /* Allocate a ListView entry for a search result. */
00033 static SearchItem *alloc_search_item(WCHAR *title, const WCHAR *filename)
00034 {
00035     int filename_len = filename ? (strlenW(filename)+1)*sizeof(WCHAR) : 0;
00036     SearchItem *item;
00037 
00038     item = heap_alloc_zero(sizeof(SearchItem));
00039     if(filename)
00040     {
00041         item->filename = heap_alloc(filename_len);
00042         memcpy(item->filename, filename, filename_len);
00043     }
00044     item->title = title; /* Already allocated */
00045 
00046     return item;
00047 }
00048 
00049 /* Fill the ListView object corresponding to the found Search tab items */
00050 static void fill_search_tree(HWND hwndList, SearchItem *item)
00051 {
00052     int index = 0;
00053     LVITEMW lvi;
00054 
00055     SendMessageW(hwndList, LVM_DELETEALLITEMS, 0, 0);
00056     while(item) {
00057         TRACE("list debug: %s\n", debugstr_w(item->filename));
00058 
00059         memset(&lvi, 0, sizeof(lvi));
00060         lvi.iItem = index++;
00061         lvi.mask = LVIF_TEXT|LVIF_PARAM;
00062         lvi.cchTextMax = strlenW(item->title)+1;
00063         lvi.pszText = item->title;
00064         lvi.lParam = (LPARAM)item;
00065         item->id = (HTREEITEM)SendMessageW(hwndList, LVM_INSERTITEMW, 0, (LPARAM)&lvi);
00066         item = item->next;
00067     }
00068 }
00069 
00070 /* Search the CHM storage stream (an HTML file) for the requested text.
00071  *
00072  * Before searching the HTML file all HTML tags are removed so that only
00073  * the content of the document is scanned.  If the search string is found
00074  * then the title of the document is returned.
00075  */
00076 static WCHAR *SearchCHM_File(IStorage *pStorage, const WCHAR *file, const char *needle)
00077 {
00078     char *buffer = heap_alloc(BLOCK_SIZE);
00079     strbuf_t content, node, node_name;
00080     IStream *temp_stream = NULL;
00081     DWORD i, buffer_size = 0;
00082     WCHAR *title = NULL;
00083     BOOL found = FALSE;
00084     stream_t stream;
00085     HRESULT hres;
00086 
00087     hres = IStorage_OpenStream(pStorage, file, NULL, STGM_READ, 0, &temp_stream);
00088     if(FAILED(hres)) {
00089         FIXME("Could not open '%s' stream: %08x\n", debugstr_w(file), hres);
00090         goto cleanup;
00091     }
00092 
00093     strbuf_init(&node);
00094     strbuf_init(&content);
00095     strbuf_init(&node_name);
00096 
00097     stream_init(&stream, temp_stream);
00098 
00099     /* Remove all HTML formatting and record the title */
00100     while(next_node(&stream, &node)) {
00101         get_node_name(&node, &node_name);
00102 
00103         if(next_content(&stream, &content) && content.len > 1)
00104         {
00105             char *text = &content.buf[1];
00106             int textlen = content.len-1;
00107 
00108             if(!strcasecmp(node_name.buf, "title"))
00109             {
00110                 int wlen = MultiByteToWideChar(CP_ACP, 0, text, textlen, NULL, 0);
00111                 title = heap_alloc((wlen+1)*sizeof(WCHAR));
00112                 MultiByteToWideChar(CP_ACP, 0, text, textlen, title, wlen);
00113                 title[wlen] = 0;
00114             }
00115 
00116             buffer = heap_realloc(buffer, buffer_size + textlen + 1);
00117             memcpy(&buffer[buffer_size], text, textlen);
00118             buffer[buffer_size + textlen] = '\0';
00119             buffer_size += textlen;
00120         }
00121 
00122         strbuf_zero(&node);
00123         strbuf_zero(&content);
00124     }
00125 
00126     /* Convert the buffer to lower case for comparison against the
00127      * requested text (already in lower case).
00128      */
00129     for(i=0;i<buffer_size;i++)
00130         buffer[i] = tolower(buffer[i]);
00131 
00132     /* Search the decoded buffer for the requested text */
00133     if(strstr(buffer, needle))
00134         found = TRUE;
00135 
00136     strbuf_free(&node);
00137     strbuf_free(&content);
00138     strbuf_free(&node_name);
00139 
00140 cleanup:
00141     heap_free(buffer);
00142     if(temp_stream)
00143         IStream_Release(temp_stream);
00144     if(!found)
00145     {
00146         heap_free(title);
00147         return NULL;
00148     }
00149     return title;
00150 }
00151 
00152 /* Search all children of a CHM storage object for the requested text and
00153  * return the last found search item.
00154  */
00155 static SearchItem *SearchCHM_Storage(SearchItem *item, IStorage *pStorage,
00156                                      const char *needle)
00157 {
00158     const WCHAR szHTMext[] = {'.','h','t','m',0};
00159     IEnumSTATSTG *elem = NULL;
00160     WCHAR *filename = NULL;
00161     STATSTG entries;
00162     HRESULT hres;
00163     ULONG retr;
00164 
00165     hres = IStorage_EnumElements(pStorage, 0, NULL, 0, &elem);
00166     if(hres != S_OK)
00167     {
00168         FIXME("Could not enumerate '/' storage elements: %08x\n", hres);
00169         return NULL;
00170     }
00171     while (IEnumSTATSTG_Next(elem, 1, &entries, &retr) == NOERROR)
00172     {
00173         switch(entries.type) {
00174         case STGTY_STORAGE:
00175             item = SearchCHM_Folder(item, pStorage, entries.pwcsName, needle);
00176             break;
00177         case STGTY_STREAM:
00178             filename = entries.pwcsName;
00179             while(strchrW(filename, '/'))
00180                 filename = strchrW(filename, '/')+1;
00181             if(strstrW(filename, szHTMext))
00182             {
00183                 WCHAR *title = SearchCHM_File(pStorage, filename, needle);
00184 
00185                 if(title)
00186                 {
00187                     item->next = alloc_search_item(title, entries.pwcsName);
00188                     item = item->next;
00189                 }
00190             }
00191             break;
00192         default:
00193             FIXME("Unhandled IStorage stream element.\n");
00194         }
00195     }
00196     return item;
00197 }
00198 
00199 /* Open a CHM storage object (folder) by name and find all items with
00200  * the requested text.  The last found item is returned.
00201  */
00202 static SearchItem *SearchCHM_Folder(SearchItem *item, IStorage *pStorage,
00203                                     const WCHAR *folder, const char *needle)
00204 {
00205     IStorage *temp_storage = NULL;
00206     HRESULT hres;
00207 
00208     hres = IStorage_OpenStorage(pStorage, folder, NULL, STGM_READ, NULL, 0, &temp_storage);
00209     if(FAILED(hres))
00210     {
00211         FIXME("Could not open '%s' storage object: %08x\n", debugstr_w(folder), hres);
00212         return NULL;
00213     }
00214     item = SearchCHM_Storage(item, temp_storage, needle);
00215 
00216     IStorage_Release(temp_storage);
00217     return item;
00218 }
00219 
00220 /* Search the entire CHM file for the requested text and add all of
00221  * the found items to a ListView for the user to choose the item
00222  * they want.
00223  */
00224 void InitSearch(HHInfo *info, const char *needle)
00225 {
00226     CHMInfo *chm = info->pCHMInfo;
00227     SearchItem *root_item = alloc_search_item(NULL, NULL);
00228 
00229     SearchCHM_Storage(root_item, chm->pStorage, needle);
00230     fill_search_tree(info->search.hwndList, root_item->next);
00231     if(info->search.root)
00232         ReleaseSearch(info);
00233     info->search.root = root_item;
00234 }
00235 
00236 /* Free all of the found Search items. */
00237 void ReleaseSearch(HHInfo *info)
00238 {
00239     SearchItem *item = info->search.root;
00240 
00241     info->search.root = NULL;
00242     while(item) {
00243         heap_free(item->filename);
00244         item = item->next;
00245     }
00246 }

Generated on Fri May 25 2012 04:21:59 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.