help.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,490 行 · 第 1/3 页

C
1,490
字号
            switch( buffer[i+1] ) {
            case H_UNDERLINE:
                currentColour |= C_ULINE;
                ++i;
                break;
            case H_UNDERLINE_END:
                currentColour &= ~C_ULINE;
                ++i;
                break;
            case H_BOLD:
                currentColour |= C_BOLD;
                ++i;
                break;
            case H_BOLD_END:
                currentColour &= ~C_BOLD;
                ++i;
                break;
            }
            ++i;
            switch( currentColour ) {
            case C_PLAIN:
                currentAttr = AT( ATTR_NORMAL );
                break;
            case C_ULINE:
                currentAttr = AT( ATTR_BRIGHT );
                break;
            case C_BOLD:
                currentAttr = AT( ATTR_BRIGHT );
                break;
            case C_ULBOLD:
                currentAttr = AT( ATTR_BRIGHT );
                break;
            }
        }
    }
}

static void save_line( int line, long offset )
/* Assumption:  line <= lastHelpLine + 1 */
{
    if( line >= maxPos ) {
        maxPos = line + 10;
        helpPos = HelpMemRealloc( helpPos, maxPos * sizeof( *helpPos ) );
    }
    if( line > lastHelpLine ) {
        lastHelpLine = line;
    }
    if( offset == -1 ) {
        helpPos[line] = -1;
    } else {
        helpPos[line] = offset - topPos;
    }
}

static void seek_line( int line )
{
    int                 i;

    if( line > lastHelpLine ) {
        HelpSeek( helpFileHdl, topPos + helpPos[lastHelpLine], HELP_SEEK_SET );
        for( i = lastHelpLine; ; ++i ) {
            save_line( i, HelpTell( helpFileHdl ) );
            if( i == line ) break;
            if( !getline() || strnicmp( helpInBuf, "::::", 4 ) == 0 ) {
                maxLine = i;
                break;
            }
        }
    } else if( line >= 0 ) {
        HelpSeek( helpFileHdl, topPos + helpPos[line], HELP_SEEK_SET );
    }
}

static void set_slider( int pos )
{
    uisetgadget( &vGadget, pos );
}


/*
 * handleFooter - scan through and process footer information
 */
static void handleFooter( int *startline, SAREA *use, SAREA *line )
{
    int         start;

    start = *startline;
    if( strnicmp( helpInBuf, ":t", 2 ) == 0 ) {
        ++start;        /* leave room for line */
        for( ;; ) {
            if( !getline() ) break;
            if( strnicmp( helpInBuf, ":et", 3 ) == 0 ) break;
            processLine( helpInBuf, helpOutBuf, start, FALSE );
            putline( helpOutBuf, start );
            ++start;
        }
        vscroll_fields( &helpTab, *use, start - use->row - use->height );
        vvscroll( &helpScreen, *use, start - use->row - use->height );
        use->height -= start - use->row;
        line->row = use->row + use->height;
        uivfill( &helpScreen, *line, AT( ATTR_NORMAL ), UiGChar[UI_SBOX_HORIZ_LINE] );
        topPos = HelpTell( helpFileHdl );
    }
    *startline = start;
}

/*
 * handleHeader - scan through and process header information
 */
static void handleHeader( int *start, SAREA *line )
{
    int         cur;

    cur = 0;
    if( strnicmp( helpInBuf, ":h", 2 ) == 0 ) {
        for( ;; ) {
            if( !getline() ) break;
            if( strnicmp( helpInBuf, ":t", 2 ) == 0 ) break;
            if( strnicmp( helpInBuf, ":eh", 3 ) == 0 ) break;
            processLine( helpInBuf, helpOutBuf, cur, FALSE );
            putline( helpOutBuf, cur );
            cur ++;
        }
        line->row = cur;
        uivfill( &helpScreen, *line, AT( ATTR_NORMAL ), UiGChar[UI_SBOX_HORIZ_LINE] );
        cur++;
        topPos = HelpTell( helpFileHdl );
        if( strnicmp( helpInBuf, ":eh", 3 ) == 0 ) {
            getline();
        }
    }
    *start = cur;
}

/*
 * setupScroolBar - setup the size and position of the vertical scrollbar
 */
static void setupScrollBar( SAREA *use )
{
    vGadget.start = use->row + 1;
    vGadget.end = vGadget.start + use->height - 1;
    vGadget.anchor = helpScreen.area.width + 1;
    vGadget.win = &helpScreen;
    vGadget.total_size = helpLines;
    vGadget.page_size = use->height;
    vGadget.pos = 0;
    vGadget.slider = EV_SCROLL_VERTICAL;
    uiinitgadget( &vGadget );
}

/*
 * scrollHelp - refresh the displayed help after a scrolling operation
 */
static int scrollHelp( SAREA *use, int lastline, bool changecurr )
{
    int         useline;
    int         scroll;
    int         start;
    int         end;

    scroll = currLine - lastline;
    vscroll_fields( &helpTab, *use, scroll );
    vvscroll( &helpScreen, *use, scroll );
    currentAttr = AT( ATTR_NORMAL );
    if( abs(scroll) >= use->height ) {
        start = currLine;
        end = start + use->height;
    } else if( scroll < 0 ) {
        start = currLine;
        end = start - scroll;
    } else {
        start = currLine + use->height - scroll;
        end = start + scroll;
    }
    seek_line( start );
    for( ;; ++start ) {
        save_line( start, HelpTell( helpFileHdl ) );
        if( !getline()  ||  strncmp( helpInBuf, "::::", 4 ) == 0  ) {
            maxLine = start;
            break;
        }
        useline = start - currLine;
        if( useline >= use->height || start >= end ) {
            break;
        }
        /* if it is the first time in,
           then the old currfield is right
        */
        processLine( helpInBuf, helpOutBuf, useline + use->row, changecurr );
        putline( helpOutBuf, useline + use->row );
    }
    end = currLine + use->height;
    if( maxLine != 0 && end > maxLine ) {
        end = maxLine;
    }
    display_fields();
    hotSpots[1].startcol = ( helpScreen.area.width - hotSpots[1].length )
                           / 2;
    addSearchButton( helpSearchHdl != NULL );
    uiposnhotspots( &helpScreen, hotSpotFields );
    uiprinthotspots( &helpScreen, hotSpotFields );
    set_slider( currLine );
    uirefresh();
    return( currLine );
}

/*
 * dispHelp
 */
static int dispHelp( char *str, VTAB *tab )
{
    EVENT               ev;
    bool                done;
    int                 lastline;
    int                 start;
    SAREA               use;
    SAREA               line;
    char                helpname[81];

    ignoreMouseRelease = TRUE;
    helpSet( str, helpname, sizeof( helpname ) );
    if( uivopen( &helpScreen ) == NULL ) return( HELP_NO_VOPEN );

    use.height = helpScreen.area.height - 3;
    use.width = helpScreen.area.width;
    use.col = 0;

    line.height = 1;
    line.width = helpScreen.area.width;
    line.col = 0;

    topPos = HelpTell( helpFileHdl );
    getline();

    handleHeader( &start, &line );
    use.row = start;
    use.height -= start;
    handleFooter( &start, &use, &line );
    setupScrollBar( &use );

    if( helpLines > 0 ) {
        maxPos = helpLines + 1;
        helpPos = HelpMemAlloc( maxPos * sizeof(*helpPos) );
    } else {
        maxPos = 0;
        helpPos = NULL;
    }
    maxLine = 0;
    lastHelpLine = 0;
    save_line( 0, topPos );
    currLine = helpStack->line;
    seek_line( currLine );
    lastline = currLine + use.height;
    done = FALSE;
    ev = EV_NO_EVENT;
    while( !done ) {
        currentColour = C_PLAIN;
        currentAttr = AT( ATTR_NORMAL );
        if( lastline != currLine ) {
            lastline = scrollHelp( &use, lastline, ev != EV_NO_EVENT );
        }
        ev = hlpwait( tab );
        switch( ev ) {
        case E_UP:
        case EV_CURSOR_UP:
        case EV_TOP:
            if( currLine > 0 ) {
                --currLine;
            }
            break;
        case E_DOWN:
        case EV_CURSOR_DOWN:
        case EV_BOTTOM:
            ++currLine;
            if( maxLine != 0  &&  currLine+use.height > maxLine ) {
                --currLine;
            }
            break;
        case EV_SCROLL_VERTICAL:
            currLine = vGadget.pos;
            break;
        case EV_PAGE_UP:
            currLine -= use.height;
            if( currLine < 0 ) {
                currLine = 0;
            }
            break;
        case EV_PAGE_DOWN:
            currLine += use.height;
            if( maxLine != 0  &&  currLine >= maxLine ) {
                currLine -= use.height;
            }
            break;
        default:
            done = TRUE;
            break;
        }
    }
    clearline();
    uivclose( &helpScreen );
    if( helpPos != NULL ) {
        HelpMemFree( helpPos );
        helpPos = NULL;
    }
    return( HELP_OK );
}

static int findhelp( VTAB *tab )
{
    help_file   *fileinfo;
    int         ret;

    fileinfo = help_open( helpInBuf );
    if( fileinfo == NULL ) {
        return( HELP_NO_SUBJECT );
    }
    helpFileHdl = fileinfo->f;
    helpSearchHdl = fileinfo->searchhdl;
    ret = dispHelp( helpStack->word, tab );
    /* if a new help file name exists,
       then link to the new file
    */
    if( helpTab != NULL && helpCur->key2_len != 0 ) {
        curEvent = EV_ESCAPE;
    }
    return( ret );
}

/*
 * fixHelpTopic - escape any special characters in topics that comes from
 *                      the outside world
 */
static char *fixHelpTopic( char *topic )
{
    char        *ptr;
    char        *retptr;
    unsigned    cnt;
    char        *ret;

    ptr = topic;
    cnt = 0;
    while( *ptr != '\0' ) {
        if( *ptr == '<' || *ptr == '>' || *ptr == '"' || *ptr == '{'
            || *ptr == '}' ) {
            cnt++;
        }
        cnt ++;
        ptr ++;
    }
    ret = HelpMemAlloc( cnt + 1 );
    retptr = ret;
    ptr = topic;
    while( *ptr != '\0' ) {
        if( *ptr == '<' || *ptr == '>' || *ptr == '"' || *ptr == '{'
            || *ptr == '}' ) {
            *retptr = HELP_ESCAPE;
            retptr ++;
            *retptr = *ptr;
        } else {
            *retptr = *ptr;
        }
        retptr++;
        ptr++;
    }
    *retptr = '\0';
    return( ret );
}

int showhelp( char *helptopic, EVENT (*rtn)( EVENT ), HelpLangType lang )
{
    bool        first;
    int         err;
    char        filename[_MAX_PATH];
    char        *hfiles[] = { NULL, NULL };
    char        ext[_MAX_EXT];
    char        *buffer;

    first = TRUE;
    err = FALSE;
    switch( lang ) {
    case HELPLANG_FRENCH:
        hotSpots[0].str = "F4=Sujet pr俢俤ent";
        hotSpots[1].str = "Sortir";
        break;
    case HELPLANG_ENGLISH:
        break;
    }
    helpStack = NULL;
    currentColour = C_PLAIN;
    currentAttr = AT( ATTR_NORMAL );
    /* initialize the tab filter */
    tabFilter.tab = (unsigned (*)(void *,void *))help_in_tab;
    tabFilter.next = (a_tab_field *(*)(void *,void *))help_next_field;
    tabFilter.parm = helpTab;
    tabFilter.mousepos = (void *(*)())uivmousepos;
    tabFilter.mouseparm = &helpScreen;
    tabFilter.first = helpTab;
    tabFilter.wrap = FALSE;
    tabFilter.enter = FALSE;
    if( HelpFiles->name == NULL ) {
        return( HELP_NO_FILE );
    }
    _splitpath( HelpFiles->name, NULL, NULL, filename, ext );
    strcat( filename, ext );
    hfiles[ 0 ] = filename;
    while( ( helptopic != NULL || first ) ) {
        if( first || help_reinit( hfiles ) ) {
            err = do_showhelp( &helptopic, hfiles[0], rtn, first );
            if( err == HELP_NO_SUBJECT ) break;
        } else {        // cannot open help file for hyperlink
            buffer = HelpMemAlloc( 28 + strlen( hfiles[0] ) );
            sprintf( buffer, "Unable to open helpfile \"%s\".", hfiles[0] );
            ShowMsgBox( "Error", buffer );
            HelpMemFree( buffer );
            HelpMemFree( helptopic );
            helptopic = HelpMemAlloc( strlen( helpStack->word ) + 1 );
            strcpy( helptopic, helpStack->word );
            strcpy( hfiles[0], helpStack->helpfname );
            prevtopic();
        }
        first = FALSE;
    }
    return( err );
}

int do_showhelp( char **helptopic, char *filename, EVENT (*rtn)( EVENT ),
                 bool first )
{
    int         err;
    char        *ptr;
    unsigned    len;
    char        *htopic;

    eventMapFn = rtn;
    err = TRUE;
    helpTab = NULL;
    helpCur = helpTab;
    strcpy( curFile, filename );
    helpInBuf = HelpMemAlloc( BUF_LEN );
    if( helpInBuf == NULL ) {
        HelpMemFree( helpStack );
        return( HELP_NO_MEM );
    }
    helpOutBuf = HelpMemAlloc( BUF_LEN );
    if( helpOutBuf == NULL ) {
        HelpMemFree( helpStack );
        return( HELP_NO_MEM );
    }
    // don't fix hyperlink topics
    if( *helptopic != NULL && first ) {
        htopic = fixHelpTopic( *helptopic );
    } else if( *helptopic == NULL ) {
        len = 1;
        htopic = HelpMemAlloc( len );
        htopic[0] = '\0';
    } else {
        len = strlen( *helptopic );
        htopic = HelpMemAlloc( len + 1 );
        strcpy( htopic, *helptopic );
    }
    nexttopic( htopic );
    for( ;; ) {
        err = findhelp( &tabFilter );
        if( err != HELP_OK ) break;
        if( curEvent == EV_ESCAPE ) break;
        if( curEvent == EV_KILL_UI ) break;
    }
    SearchDlgFini();
    help_close();
    // This is Not Nice - we're freeing memory that
    // someone else allocated! Just don't do it.
    if( err != HELP_NO_SUBJECT ) {
//        HelpMemFree( *helptopic );
        *helptopic = NULL;
        *filename = '\0';
    }
    HelpMemFree( helpInBuf );
    HelpMemFree( helpOutBuf );
    HelpMemFree( htopic );
    if( helpTab != NULL && helpCur->key2_len != 0 ) { // cross file link
        *helptopic = HelpMemAlloc( helpCur->key1_len + 1 );
        strncpy( *helptopic, helpCur->keyword, helpCur->key1_len );
        (*helptopic)[ helpCur->key1_len ] = '\0';
        ptr = &( helpCur->keyword[ helpCur->key1_len ] );
        strncpy( filename, ptr, helpCur->key2_len );
        filename[ helpCur->key2_len ] = '\0';
        if( helpCur != tabFilter.curr ) { // backwards through cross file link
            prevtopic();
        }
    } else {
        Free_Stack();
    }
    free_fields( &helpTab );
    return( err );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?