search.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 412 行
C
412 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Help file searching routines.
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "index.h"
#include "helpmem.h"
#include "helpio.h"
#include "search.h"
#ifndef __WATCOMC__
#include "clibext.h"
#endif
#define DEFAULTTOPIC "TABLE OF CONTENTS"
int curFile = -1;
char curPage[PAGE_SIZE];
HelpPageHeader *pageHeader;
char *stringBlock;
void *pageIndex;
static void loadPage( HelpHdl hdl, unsigned long pagenum )
{
unsigned long offset;
unsigned tmp;
if( curFile == hdl->fp && pageHeader->page_num == pagenum ) return;
if( hdl->header.ver_maj == 1 ) {
tmp = sizeof( HelpHeader ) - sizeof( uint_16 ); // no str_size
} else {
tmp = sizeof( HelpHeader );
}
offset = tmp + hdl->header.str_size + pagenum * PAGE_SIZE
+ hdl->header.datapagecnt * sizeof( uint_16 );
HelpSeek( hdl->fp, offset, HELP_SEEK_SET );
HelpRead( hdl->fp, curPage, PAGE_SIZE );
curFile = hdl->fp;
pageHeader = (HelpPageHeader *)curPage;
pageIndex = curPage + sizeof( HelpPageHeader );
if( pageHeader->type == PAGE_DATA ) {
stringBlock = curPage + sizeof( HelpPageHeader )
+ pageHeader->num_entries * sizeof( PageIndexEntry );
}
}
static void loadNextPage( HelpHdl hdl, const char *name )
{
unsigned i;
HelpIndexEntry *entry;
entry = pageIndex;
for( i = 0; i < pageHeader->num_entries; i++ ) {
if( strnicmp( entry->start, name, INDEX_LEN - 1 ) >= 0 ) {
entry ++;
break;
}
entry++;
}
entry --; /* if we've read through the entire list load the last page */
loadPage( hdl, entry->nextpage );
}
/*
* doFindEntry - find the closest match that is alphabetically before
* name in the current page. If no entry on the current
* page comes before name return the first entry on the
* page.
*/
static char *doFindEntry( const char *name, unsigned *entry_num )
{
unsigned i;
unsigned len;
PageIndexEntry *entry;
int cmpret;
entry = pageIndex;
len = strlen( name );
for( i = 0; i < pageHeader->num_entries; i++ ) {
cmpret = strnicmp( stringBlock + entry[i].name_offset, name, len );
if( cmpret == 0 ) {
break;
}
if( cmpret > 0 ) {
if( i > 0 ) {
i --;
}
break;
}
}
if( i == pageHeader->num_entries ) {
i--;
}
if( entry_num != NULL ) {
*entry_num = i;
}
return( stringBlock + entry[i].name_offset );
}
static char *findEntry( HelpHdl hdl, const char *name, unsigned *entry_num )
{
char *ret;
unsigned pagecnt;
unsigned basepage;
int cmpret;
pagecnt = hdl->header.datapagecnt + hdl->header.indexpagecnt;
basepage = pageHeader->page_num;
ret = doFindEntry( name, entry_num );
cmpret = stricmp( ret, name );
while( cmpret < 0 && pageHeader->page_num < pagecnt - 1 ) {
loadPage( hdl, pageHeader->page_num + 1 );
ret = doFindEntry( name, entry_num );
cmpret = stricmp( ret, name );
}
if( cmpret > 0 && pageHeader->page_num > basepage ) {
loadPage( hdl, pageHeader->page_num - 1 );
ret = doFindEntry( name, entry_num );
}
return( ret );
}
#if 0
char *HelpFindPrev( HelpSrchInfo *info )
{
PageIndexEntry *entry;
char *ret;
if( info->page == 0 && info->entry == 0 ) return( NULL );
if( info->entry == 0 ) {
info->page--;
loadPage( info->hdl, info->page );
info->entry = pageHeader->num_entries - 1;
} else {
info->entry--;
loadPage( info->hdl, info->page );
}
entry = pageIndex;
info->offset = entry[ info->entry ].entry_offset;
ret = stringBlock + entry[ info->entry ].name_offset;
return( ret );
}
unsigned long HelpGetOffset( HelpSrchInfo cursor )
{
return( cursor.offset );
}
char *HelpFindNext( HelpSrchInfo *info )
{
char *ret;
PageIndexEntry *entry;
unsigned pagecnt;
pagecnt = info->hdl->header.datapagecnt + info->hdl->header.indexpagecnt;
if( info->page == pagecnt ) return( NULL );
loadPage( info->hdl, info->page );
info->entry++;
if( info->entry == pageHeader->num_entries ) {
info->page++;
if( info->page == pagecnt ) return( NULL );
loadPage( info->hdl, info->page );
info->entry = 0;
}
entry = pageIndex;
info->offset = entry[ info->entry ].entry_offset;
ret = stringBlock + entry[ info->entry ].name_offset;
return( ret );
}
#endif
unsigned HelpFindFirst( HelpHdl hdl, char *name, HelpSrchInfo *info )
{
unsigned ret;
PageIndexEntry *entry;
loadPage( hdl, 0 );
while( pageHeader->type != PAGE_DATA ) {
loadNextPage( hdl, name );
}
findEntry( hdl, name, &ret );
if( info != NULL ) {
info->hdl = hdl;
info->entry = ret;
info->page = pageHeader->page_num;
entry = pageIndex;
info->offset = entry[ info->entry ].entry_offset;
}
ret += hdl->itemindex[ pageHeader->page_num - hdl->header.indexpagecnt ];
return( ret );
}
char *HelpGetIndexedTopic( HelpHdl hdl, unsigned index )
{
unsigned i;
PageIndexEntry *entry;
if( hdl == NULL || index >= hdl->header.topiccnt ) return( NULL );
for( i=0; i < hdl->header.datapagecnt - 1; i++ ) {
if( hdl->itemindex[i+1] > index ) break;
}
loadPage( hdl, i + hdl->header.indexpagecnt );
index -= hdl->itemindex[i];
entry = pageIndex;
entry += index;
return( stringBlock + entry->name_offset );
}
unsigned long HelpFindTopicOffset( HelpHdl hdl, char *topic )
{
unsigned entry_num;
PageIndexEntry *entry;
char *foundtopic;
if( hdl == NULL ) return( -1 );
loadPage( hdl, 0 );
while( pageHeader->type != PAGE_DATA ) {
loadNextPage( hdl, topic );
}
foundtopic = findEntry( hdl, topic, &entry_num );
if( !stricmp( foundtopic, topic ) ) {
entry = pageIndex;
return( entry[ entry_num ].entry_offset );
} else {
return( -1 );
}
}
HelpHdl InitHelpSearch( HelpFp fp )
{
HelpHdl hdl;
unsigned len;
char *topic;
char *description;
uint_16 str_cnt;
uint_16 *str_len;
char *ptr;
char *buffer;
HelpSeek( fp, 0, HELP_SEEK_SET );
hdl = HelpMemAlloc( sizeof( struct HelpHdl ) );
hdl->fp = fp;
HelpRead( fp, &( hdl->header ), sizeof( HelpHeader ) );
if( hdl->header.sig[0] != HELP_SIG_1
|| hdl->header.sig[1] != HELP_SIG_2
|| hdl->header.ver_min != HELP_MIN_VER ) {
HelpMemFree( hdl );
hdl = NULL;
} else if( hdl->header.ver_maj != HELP_MAJ_VER ) {
if( hdl->header.ver_maj != 1 ) {
HelpMemFree( hdl );
hdl = NULL;
} else {
HelpSeek( fp, -sizeof( uint_16 ), SEEK_CUR ); // no str_size in header
topic = HelpMemAlloc( strlen( DEFAULTTOPIC ) + 1 );
strcpy( topic, DEFAULTTOPIC );
hdl->def_topic = topic;
hdl->desc_str = NULL;
hdl->header.str_size = 0; // no str_size in old header format
len = hdl->header.datapagecnt * sizeof( uint_16 );
hdl->itemindex = HelpMemAlloc( len );
HelpRead( fp, hdl->itemindex, len );
}
} else {
buffer = HelpMemAlloc( hdl->header.str_size );
HelpRead( fp, buffer, hdl->header.str_size );
ptr = buffer;
str_len = (uint_16 *)ptr;
str_cnt = *str_len;
str_len++;
if( *str_len != 0 ) {
topic = HelpMemAlloc( *str_len );
ptr += (str_cnt + 1) * sizeof( uint_16 );
strcpy( topic, ptr); // assume topic is first string
} else {
topic = HelpMemAlloc( strlen( DEFAULTTOPIC ) + 1 );
strcpy( topic, DEFAULTTOPIC );
}
ptr = buffer;
ptr += ( str_cnt + 1 ) * ( sizeof( uint_16 ) );
ptr += ( *str_len ) * ( sizeof( char ) );
str_len++;
if( *str_len != 0 ) {
description = HelpMemAlloc( *str_len );
strcpy( description, ptr );
} else {
description = NULL;
}
HelpMemFree( buffer );
hdl->def_topic = topic;
hdl->desc_str = description;
len = ( hdl->header.datapagecnt ) * ( sizeof( uint_16 ) );
hdl->itemindex = HelpMemAlloc( len );
HelpRead( fp, hdl->itemindex, len );
}
return( hdl );
}
char *GetDefTopic( HelpHdl hdl )
{
char *topic;
if( hdl == NULL ) {
topic = DEFAULTTOPIC;
} else {
topic = hdl->def_topic;
}
return( topic );
}
char *GetDescrip( HelpHdl hdl )
{
char *description;
if( hdl == NULL ) {
description = NULL;
} else {
description = hdl->desc_str;
}
return( description );
}
void FiniHelpSearch( HelpHdl hdl )
{
if( hdl != NULL ) {
if( hdl->itemindex != NULL ) {
HelpMemFree( hdl->itemindex );
}
if( hdl->def_topic != NULL ) {
HelpMemFree( hdl->def_topic );
}
if( hdl->desc_str != NULL ) {
HelpMemFree( hdl->desc_str );
}
HelpMemFree( hdl );
}
}
#ifdef TEST_SEARCH
#include "trmemcvr.h"
void main( int argc, char *argv[] )
{
HelpFp fp;
HelpHdl hdl;
char name[_MAX_PATH];
char *cur;
HelpSrchInfo cursor;
unsigned i;
if( argc != 2 ) {
printf( "USAGE:\n" );
printf( "exename <help file>\n" );
return;
}
fp = HelpOpen( argv[1], HELP_OPEN_RDONLY | HELP_OPEN_BINARY );
if( fp == -1 ) {
printf( "Unable to open %s\n", argv[1] );
return;
}
TRMemOpen();
hdl = InitHelpSearch( fp );
for( ;; ) {
gets( name );
if( !strcmp( name, "bob" ) ) break;
cur = HelpFindFirst( hdl, name, &cursor );
for( i=0; i < 5; i++ ) {
if( cur == NULL ) break;
printf( " %s\n", cur );
HelpMemFree( cur );
cur = HelpFindNext( &cursor );
}
if( cur != NULL ) {
HelpMemFree( cur );
}
}
FiniHelpSearch( hdl );
HelpClose( fp );
TRMemClose();
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?