Logo Search packages:      
Sourcecode: xchm version File versions

bool CHMFile::IndexSearch ( const wxString &  text,
bool  wholeWords,
bool  titlesOnly,
CHMSearchResults *  results 
)

Fast search using the $FIftiMain file in the .chm.

Parameters:
text The text we're looking for.
wholeWords Are we looking for whole words only?
titlesOnly Are we looking for titles only?
results A string-string hashmap that will hold the results in case of successful search. The keys are the URLs and the values are the page titles.
Returns:
true if the search succeeded, false otherwise.

Definition at line 290 of file chmfile.cpp.

References GetLeafNodeOffset(), and ProcessWLC().

{
      bool partial = false;

      if(text.IsEmpty())
            return false;

      chmUnitInfo ui, uitopics, uiurltbl, uistrings, uiurlstr;
      if(::chm_resolve_object(_chmFile, "/$FIftiMain", &ui) !=
         CHM_RESOLVE_SUCCESS || 
         ::chm_resolve_object(_chmFile, "/#TOPICS", &uitopics) !=
         CHM_RESOLVE_SUCCESS ||
         ::chm_resolve_object(_chmFile, "/#STRINGS", &uistrings) !=
         CHM_RESOLVE_SUCCESS ||
         ::chm_resolve_object(_chmFile, "/#URLTBL", &uiurltbl) !=
         CHM_RESOLVE_SUCCESS ||
         ::chm_resolve_object(_chmFile, "/#URLSTR", &uiurlstr) !=
         CHM_RESOLVE_SUCCESS)
            return false;

#define FTS_HEADER_LEN 0x32
      unsigned char header[FTS_HEADER_LEN];

      if(::chm_retrieve_object(_chmFile, &ui,
                         header, 0, FTS_HEADER_LEN) == 0)
            return false;
      
      unsigned char doc_index_s = header[0x1E], doc_index_r = header[0x1F];
      unsigned char code_count_s = header[0x20], code_count_r = header[0x21];
      unsigned char loc_codes_s = header[0x22], loc_codes_r = header[0x23];

      if(doc_index_s != 2 || code_count_s != 2 || loc_codes_s != 2) {
            // Don't know how to use values other than 2 yet. Maybe
            // next chmspec.
            return false;
      }

      unsigned char* cursor32 = header + 0x14;
      u_int32_t node_offset = UINT32ARRAY(cursor32);

      cursor32 = header + 0x2e;
      u_int32_t node_len = UINT32ARRAY(cursor32);

      unsigned char* cursor16 = header + 0x18;
      u_int16_t tree_depth = UINT16ARRAY(cursor16);

      unsigned char word_len, pos;
      wxString word;
      u_int32_t i = sizeof(u_int16_t);
      u_int16_t free_space;

      UCharPtr buffer(new unsigned char[node_len]);

      node_offset = GetLeafNodeOffset(text, node_offset, node_len,
                              tree_depth, &ui);

      if(!node_offset) 
            return false;

      do {
            // got a leaf node here.
            if(::chm_retrieve_object(_chmFile, &ui, buffer.get(), 
                               node_offset, node_len) == 0)
                  return false;

            cursor16 = buffer.get() + 6;
            free_space = UINT16ARRAY(cursor16);

            i = sizeof(u_int32_t) + sizeof(u_int16_t) + sizeof(u_int16_t);
            u_int64_t wlc_count, wlc_size;
            u_int32_t wlc_offset;

            while(i < node_len - free_space) {
                  word_len = *(buffer.get() + i);
                  pos = *(buffer.get() + i + 1);

                  char *wrd_buf = new char[word_len];
                  memcpy(wrd_buf, buffer.get() + i + 2, word_len - 1);
                  wrd_buf[word_len - 1] = 0;

                  if(pos == 0)
                        word = CURRENT_CHAR_STRING(wrd_buf);
                  else
                        word = word.Mid(0, pos) +
                              CURRENT_CHAR_STRING(wrd_buf);

                  delete[] wrd_buf;

                  i += 2 + word_len;
                  unsigned char title = *(buffer.get() + i - 1);

                  size_t encsz;
                  wlc_count = be_encint(buffer.get() + i, encsz);
                  i += encsz;
            
                  cursor32 = buffer.get() + i;
                  wlc_offset = UINT32ARRAY(cursor32);

                  i += sizeof(u_int32_t) + sizeof(u_int16_t);
                  wlc_size =  be_encint(buffer.get() + i, encsz);
                  i += encsz;

                  cursor32 = buffer.get();
                  node_offset = UINT32ARRAY(cursor32);
            
                  if(!title && titlesOnly)
                        continue;

                  if(wholeWords && !text.CmpNoCase(word))
                        return ProcessWLC(wlc_count, wlc_size, 
                                      wlc_offset, doc_index_s, 
                                      doc_index_r,code_count_s, 
                                      code_count_r, loc_codes_s, 
                                      loc_codes_r, &ui, &uiurltbl,
                                      &uistrings, &uitopics,
                                      &uiurlstr, results);

                  if(!wholeWords) {
                        if(word.StartsWith(text.c_str())) {
                              partial = true;
                              ProcessWLC(wlc_count, wlc_size, 
                                       wlc_offset, doc_index_s, 
                                       doc_index_r,code_count_s, 
                                       code_count_r, loc_codes_s, 
                                       loc_codes_r, &ui, &uiurltbl,
                                       &uistrings, &uitopics,
                                       &uiurlstr, results);

                        } else if(text.CmpNoCase(
                                      // Mid() might be buggy.
                                      word.Mid(0, text.Length()))
                                < -1)
                              break;
                  }

                  if(results->size() >= MAX_SEARCH_RESULTS)
                        break;
            }     
      } while(!wholeWords && word.StartsWith(text.c_str()) && node_offset);

      return partial;
}


Generated by  Doxygen 1.6.0   Back to index