help.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,490 行 · 第 1/3 页
C
1,490 行
/****************************************************************************
*
* 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 access functions.
*
****************************************************************************/
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include "uidef.h"
#include "helpmem.h"
#include "stdui.h"
#include "uibox.h"
#include "help.h"
#include "hlpuicvr.h"
#include "hlputkys.h"
#include "uidialog.h"
#include "uimenu.h"
#include "uitab.h"
#include "helpscan.h"
#include "msgbox.h"
#include "uigchar.h"
#ifndef __WATCOMC__
#include "clibext.h"
#endif
extern EVENT uivget( VSCREEN * );
static int CheckHelpBlock( HelpFp help_file, char *topic, char *buffer,
long int start );
static void replacetopic( char *word );
int do_showhelp( char **helptopic, char *filename, EVENT (*rtn)( EVENT ),
bool first );
// In normal QNX text files, the record separator is just a LF.
// However, with the new help file format containing both binary and
// text data, we can't do a text conversion, so the record separator
// is still a CR/LF from DOS. So the RSEP_LEN is 2.
#define RSEP_LEN 2
#if defined( QNX )
#define EV_MARK_PRESS EV_CTRL_PRESS
#define EV_MARK_RELEASE EV_CTRL_RELEASE
#else
#define EV_MARK_PRESS EV_SHIFT_PRESS
#define EV_MARK_RELEASE EV_SHIFT_RELEASE
#endif
#define AT(x) UIData->attrs[x]
#define AT_BLINK 0x80
#define TRUE 1
#define FALSE 0
#define C_PLAIN 0
#define C_ULINE 1
#define C_BOLD 2
#define C_ULBOLD 3
#define HELP_MIN_WIDTH 63
#define BUF_LEN 400
enum {
HSTCK_NAME,
HSTCK_OFFSET
};
typedef struct hstackent {
struct hstackent *next;
int cur;
int line;
int type;
char helpfname[_MAX_PATH];
char word[1]; /* dynamic array */
}a_hstackent;
typedef struct a_field {
SAREA area;
struct a_field *next;
unsigned key1_len;
unsigned key2_len;
char keyword[1];
} a_field;
typedef struct {
char *buf;
int pos;
bool changecurr;
int line;
} ScanInfo;
static VSCREEN helpScreen = {
EV_NO_EVENT, /* event number */
NULL, /* screen title */
{0, 0, 0, 0}, /* location and size */
V_NO_ZOOM | V_DIALOGUE, /* flags */
0, 0, /* initial cursor position */
C_OFF /* cursor type */
};
static a_gadget vGadget = {
NULL, /* window */
VERTICAL, /* direction */
0, /* anchor position */
0, /* start of bar */
0, /* end of bar */
E_DOWN, /* forward event */
E_UP, /* backward event */
EV_PAGE_DOWN, /* forward page event */
EV_PAGE_UP, /* backward page event */
EV_NO_EVENT, /* slider event */
0, /* total size */
0, /* page size */
0, /* current position */
FALSE /* lockable */
};
static a_hot_spot hotSpots[] = {
{ "&Back", EV_FUNC(4), -1, 1, 15, 0 },
{ "&Search", EV_ALT_S, -1, 0, 15, 0 },
{ "Cancel", EV_ESCAPE, -1, -2, 15, 0 },
{ NULL, EV_NO_EVENT }
};
#define SEARCH_HOT_SPOT 2
static a_hot_spot_field hotSpotFields[] = {
{{0}, FLD_HOT, &hotSpots[0] },
{{0}, FLD_HOT, &hotSpots[2] },
{{0}, FLD_HOT, &hotSpots[1] },
{{0}, FLD_VOID,NULL }
};
static EVENT keyShift[] = {
EV_NO_EVENT,
EV_ALT_FUNC_12,
EV_MARK_PRESS, EV_MARK_RELEASE,
EV_MOUSE_RELEASE, EV_MOUSE_DRAG,
EV_INSERT, EV_DELETE,
EV_MOUSE_DCLICK,
EV_NO_EVENT
};
static EVENT helpEventList[] = {
EV_NO_EVENT, /* end of event-range pairs */
EV_ALT_B, 'b', 'B',
EV_ALT_S, 's', 'S',
EV_CURSOR_LEFT,
EV_CURSOR_RIGHT,
EV_TAB_FORWARD,
EV_TAB_BACKWARD,
EV_ENTER,
EV_ESCAPE,
EV_HELP,
EV_PAGE_UP,
EV_PAGE_DOWN,
'-','+',
EV_FUNC(4),
EV_FUNC(9),
EV_FUNC(10),
EV_CURSOR_UP,
EV_CURSOR_DOWN,
EV_TOP,
EV_BOTTOM,
EV_SCROLL_VERTICAL,
EV_MOUSE_PRESS,
EV_MOUSE_REPEAT,
EV_MOUSE_RELEASE,
EV_MOUSE_RELEASE_R,
EV_FIELD_CHANGE,
E_UP,
E_DOWN,
EV_NO_EVENT }; /* end of single event list */
static a_hstackent *helpStack;
static a_field *helpTab;
static a_field *helpCur;
static char *helpInBuf;
static char *helpOutBuf;
static char helpWord[] = { "HELP" };
static int helpLines;
static unsigned *helpPos;
static long topPos;
static int maxPos;
static int maxLine;
static int currLine;
static int lastHelpLine;
static int currentAttr;
static int currentColour;
static bool ignoreMouseRelease;
static char curFile[_MAX_PATH];
static HelpFp helpFileHdl;
static HelpHdl helpSearchHdl;
static VTAB tabFilter;
static EVENT curEvent;
static EVENT (*eventMapFn)();
extern a_ui_edit *UIEdit;
static void window_pos( ORD *start, ORD *size, int slack, int pos )
{
ORD bump;
if( slack > 0 ) {
if( pos == 0 ) {
bump = slack / 2;
} else if( pos > 0 ) {
if( --pos > slack ) {
pos = slack;
}
bump = pos;
} else {
pos = -pos;
if( --pos > slack ) {
pos = slack;
}
bump = slack - pos;
}
*start += bump;
*size -= slack;
}
}
SAREA *hlp_ut_screen_area( SAREA *area, bool all, bool framed )
{
area->col = framed;
area->width = UIData->width - 2*framed;
area->row = framed;
area->height = UIData->height - 2*framed;
if( !all && uimenuson() ) {
area->row += 1;
area->height -= 1;
}
return( area );
}
void hlp_ut_position( SAREA *a, ORD h, ORD w, int rpos, int cpos, bool overmenus )
{
hlp_ut_screen_area( a, overmenus, TRUE );
if( h > 0 ) {
window_pos( &a->row, &a->height, a->height - h, rpos );
}
if( w > 0 ) {
window_pos( &a->col, &a->width, a->width - w, cpos );
}
}
static void addSearchButton( bool add )
{
if( add ) {
hotSpotFields[SEARCH_HOT_SPOT].typ = FLD_HOT;
hotSpotFields[SEARCH_HOT_SPOT].ptr = &hotSpots[1];
} else {
hotSpotFields[SEARCH_HOT_SPOT].typ = FLD_VOID;
hotSpotFields[SEARCH_HOT_SPOT].ptr = NULL;
}
}
/*
* helpGetString
*/
static char *helpGetString( char *buf, size_t size, HelpFp fp )
{
long int pos;
int bytesread;
int cnt;
pos = HelpTell( fp );
bytesread = HelpRead( fp, buf, size - 1 );
if( bytesread == 0 || bytesread == -1 ) return( NULL );
cnt = 0;
while( cnt < bytesread ) {
if( buf[cnt] == '\n' ) {
cnt++;
break;
}
cnt ++;
}
HelpSeek( fp, pos + cnt, HELP_SEEK_SET );
buf[cnt] = '\0';
return( buf );
}
/*
* OpenTopicInFile - open a help file and look for a topic
*/
static int OpenTopicInFile( help_file *fileinfo, char *topic, char *buffer )
{
long int start_offset; /* - starting offset in HELP file */
long int size_left; /* - size left to search */
int next_posn; /* - contains indicator for next pos'n */
unsigned long topic_pos;
if( fileinfo->f == -1 ) return( 0 );
if( fileinfo->searchhdl != NULL ) {
/* search by new method */
topic_pos = HelpFindTopicOffset( fileinfo->searchhdl, topic );
if( topic_pos == (unsigned long)-1 ) {
return( 0 );
} else {
HelpSeek( fileinfo->f, topic_pos, HELP_SEEK_SET );
if( helpGetString( buffer, BUF_LEN, fileinfo->f ) == NULL ) {
return( 0 );
} else {
return( 1 );
}
}
} else {
start_offset = 0L;
}
size_left = HelpFileLen( fileinfo->f );
do {
size_left = size_left / 2;
if( size_left <= 8 ) {
if( CheckHelpBlock( fileinfo->f, topic, buffer, start_offset ) != 0 ) {
return( 0 );
} else {
return( 1 );
}
}
next_posn = CheckHelpBlock( fileinfo->f, topic, buffer,
start_offset + size_left );
if( next_posn > 0 ) {
start_offset += size_left;
}
} while( next_posn != 0 );
return( 1 );
}
static char *scanTopic( char *buf, char **theend )
{
char *topic;
char *end;
if( memcmp( buf, "::::", 4 ) != 0 ) return( NULL );
if( buf[4] == '"' ) {
topic = buf + 5;
end = topic;
while( *end != '"' && *end != '\0' ) {
if( *end == HELP_ESCAPE ) end++;
end++;
}
} else {
topic = buf + 5;
while( *topic == ' ' ) topic++;
end = topic;
while( *end != ' ' && *end != '\n' && end != '\0' ) end++;
}
if( theend != NULL ) *theend = end;
return( topic );
}
/*
* CheckHelpBlock - see if a topic is in the 2nd half of a block
*/
static int CheckHelpBlock( HelpFp help_file, char *topic, char *buffer,
long int start )
{
int retn;
char *ftopic;
char *end;
unsigned len;
HelpSeek( help_file, start, HELP_SEEK_SET );
retn = 0;
do {
if( helpGetString( buffer, BUF_LEN, help_file ) == NULL ) {
retn = -1;
break;
}
} while( memcmp( buffer, "::::", 4 ) != 0 );
if( retn == 0 ) {
ftopic = scanTopic( buffer, &end );
len = end - ftopic;
retn = strnicmp( topic, ftopic, len );
if( !retn && topic[ len ] != '\0' ) retn = 1;
}
return( retn );
}
static void help_close( void )
{
help_file *h;
for( h = HelpFiles; h->name != NULL; ++h ) {
if( h->f != 0 ) {
HelpClose( h->f );
FiniHelpSearch( h->searchhdl );
h->searchhdl = NULL;
h->f = 0;
}
}
}
/*
* help_open - open a help file at a topic location
*/
static help_file *help_open( char *buffer )
{
help_file *h;
char *newtopic;
for( h=HelpFiles; h->name != NULL; ++h ) {
if( h->f == 0 ) {
/* text files screw up ctrl z */
h->f = HelpOpen( h->name, HELP_OPEN_RDONLY | HELP_OPEN_BINARY );
h->searchhdl = InitHelpSearch( h->f );
}
if( helpStack->word[0] == '\0' ) {
newtopic = GetDefTopic( h->searchhdl );
replacetopic( newtopic );
}
if( OpenTopicInFile( h, helpStack->word, buffer ) ) {
break;
}
}
if( h->name == NULL ) return( NULL );
return( h );
}
static void add_field( a_field *ht, bool changecurr )
{
a_field **p;
int count;
count = 0;
for( p=&helpTab; ; p = &((*p)->next) ) {
if( *p == NULL
|| (*p)->area.row > ht->area.row
|| ((*p)->area.row == ht->area.row && (*p)->area.col > ht->area.col )
) {
ht->next = *p;
*p = ht;
if( changecurr && count < helpStack->cur ) {
helpStack->cur += 1;
}
break;
}
++count;
}
tabFilter.first = helpTab;
}
static int field_count( a_field *table, a_field *field )
{
int i;
if( field == NULL ) return( 0 );
for( i = 0; table != NULL; table = table->next, ++i ) {
if( table == field ) {
return( i );
}
}
return( 0 );
}
static void del_field( a_field *table, a_field **field, bool changecurr )
{
a_field *next;
int count;
count = field_count( table, *field );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?