readstr.c

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

C
870
字号
 * GetTextForSpecialKey - get text for ^D,^E,^W, ALT_L, ^L, ^R
 */
bool GetTextForSpecialKey( int str_max, int event, char *tmp )
{
    int         i, l;
    #ifndef __WIN__
    int         str_len;
    #endif

    switch( event ) {
    #ifndef __WIN__
    /* these commands are no longer safe under windows, since events
     * don't fit into a char any more
     */
    case VI_KEY( CTRL_F ):
        str_len = AltDotDigits;
        if( str_len > str_max ) {
            str_len = str_max;
        }
        for( i=0; i < str_len; i++ ) {
            tmp[i] = (char)(AltDotBuffer[i]);
        }
        tmp[ str_len ] = 0;
        break;
    case VI_KEY( CTRL_D ):
        str_len = DotCmdCount;
        if( str_len > str_max ) {
            str_len = str_max;
        }
        for( i=0; i < str_len; i++ ) {
            tmp[i] = (char)(DotCmd[i]);
        }
        tmp[ str_len ] = 0;
        break;
    #endif
    case VI_KEY( CTRL_E ):
    case VI_KEY( CTRL_W ):
        tmp[ 0 ] = 0;
        GimmeCurrentWord( tmp, str_max, event == VI_KEY( CTRL_E ) );
        tmp[ str_max ] = 0;
        break;
    case VI_KEY( ALT_L ):
        i = CurrentColumn - 1;
        i = ( i > 0 ) ? i : 0;
    case VI_KEY( CTRL_L ):
        if( CurrentLine == NULL ) {
            break;
        }
        if( event == VI_KEY( CTRL_L ) ) {
            i = 0;
        }
        ExpandTabsInABuffer( &CurrentLine->data[ i ], CurrentLine->len - i,
                tmp, str_max );
        break;
    case VI_KEY( CTRL_R ):
        if( CurrentLine == NULL ) {
            break;
        }
        if( SelRgn.lines ) {
            assert( SelRgn.start_line == SelRgn.end_line );
            i = 1;
            l = CurrentLine->len + 1;
        } else {
            if( SelRgn.start_col < SelRgn.end_col ) {
                i = SelRgn.start_col;
                l = SelRgn.end_col - SelRgn.start_col + 1;
            } else {
                i = SelRgn.end_col;
                l = SelRgn.start_col - SelRgn.end_col + 1;
            }
        }
        ExpandTabsInABuffer( &CurrentLine->data[ i - 1 ], l, tmp, str_max );
        tmp[ l ] = 0;
    default:
        return( FALSE );
    }
    return( TRUE );

} /* GetTextForSpecialKey */

/*
 * InsertTextForSpecialKey - insert text for ^O, ALT_O
 */
void InsertTextForSpecialKey( int event, char *buff )
{
    linenum     line;
    int         type;

    if( CurrentFile == NULL ) {
        return;
    }

    line = CurrentLineNumber;
    type = INSERT_BEFORE;
    if( event == VI_KEY( CTRL_O ) ) {
        type = INSERT_AFTER;
        line += 1;
    }
    Modified( TRUE );
    StartUndoGroup( UndoStack );
    UndoInsert( line, line, UndoStack );
    AddNewLineAroundCurrent( buff, strlen( buff ), type );
    EndUndoGroup( UndoStack );
    DCDisplayAllLines();
    DCUpdate();

} /* InsertTextForSpecialKey */

static int specialKeyFilter( input_buffer *input, int event )
{
    char        *tmp;

    switch( event ) {
    case VI_KEY( ALT_O ):
    case VI_KEY( CTRL_O ):
        InsertTextForSpecialKey( event, input->buffer );
        break;
    case VI_KEY( CTRL_R ):
        if( !SelRgn.selected ||
            ( SelRgn.lines &&
            ( SelRgn.start_line != SelRgn.end_line ) ) ) {
            MyBeep();
            break;
        }
    case VI_KEY( CTRL_W ):
    case VI_KEY( CTRL_E ):
    case VI_KEY( ALT_L ):
    case VI_KEY( CTRL_L ):
    case VI_KEY( CTRL_D ):
    case VI_KEY( CTRL_F ):
        if( input->curr_pos != strlen( input->buffer ) ) {
            MyBeep();
        } else {
            tmp = MemAlloc( input->buffer_length );
            assert( tmp != NULL );
            GetTextForSpecialKey( input->buffer_length - strlen( input->buffer ) - 1,
                                        event, tmp );
            saveStr( input );
            insertString( input, tmp );
            MemFree( tmp );
        }
        break;
    default:
        return( event );
        break;
    }
    return( HANDLED );

} /* specialKeyFilter */

/*
 * File Completion:
 *      fileComplete( input_buffer ) - performs the actual file complete
 *          by spinning in a loop getting characters until the user
 *          selects a file or cancels. Returns TRUE if the getString
 *          routine should exit with the current string.
 */

static bool fileComplete( input_buffer *input, int first_event )
{
    bool        exit, done;
    int         ret, event;
    int         old_len;

    exit = FALSE;
    if( input->curr_pos != strlen( input->buffer ) ) {
        MyBeep();
    } else {
        saveStr( input );
        old_len = strlen( input->buffer ) - 1;
        ret = StartFileComplete( input->buffer, old_len,
                input->buffer_length, first_event );
        if( ret > 0 ) {
            MyBeep();
        } else {
            if( ret != FILE_COMPLETE ) {
                done = FALSE;
                do {
                    endColumn( input );
                    displayLine( input );
                    event = GetNextEvent( TRUE );
                    switch( event ) {
                    case VI_KEY( FAKEMOUSE ):
                    case VI_KEY( MOUSEEVENT ):
                    case VI_KEY( TAB ):
                    case VI_KEY( SHIFT_TAB ):
                    case VI_KEY( UP ):
                    case VI_KEY( DOWN ):
                    case VI_KEY( LEFT ):
                    case VI_KEY( RIGHT ):
                    case VI_KEY( PAGEDOWN ):
                    case VI_KEY( PAGEUP ):
                    case VI_KEY( ALT_END ):
                        ret = ContinueFileComplete( input->buffer,
                            old_len, input->buffer_length, event );
                        if( ret ) {
                            FinishFileComplete();
                            if( ret == FILE_COMPLETE_ENTER ) {
                                exit = TRUE;
                            }
                            done = TRUE;
                        }
                        old_len = strlen( input->buffer );
                        break;
                    default:
                        KeyAdd( event );
                        PauseFileComplete();
                        done = TRUE;
                    }
                } while( !done );
            }
        }
    }
    return( exit );

} /* fileComplete */

/*
 * Setup and Initialization functions:
 *      mouseHandler() - the routine to handle mouse events.
 *      initInput( input_buffer ) - sets the buffer to empty and
 *          initializes variables.
 *      finiInput( input_buffer ) - restores the normal cursor and
 *          removes the mouse handler.
 */

static window_id    thisWindow = -1;

static bool mouseHandler( window_id id, int x, int y )
{
    x = x;
    y = y;
    if( id != thisWindow ) {
        if( LastMouseEvent == MOUSE_PRESS ) {
            KeyAdd( VI_KEY( ESC ) );
            AddCurrentMouseEvent();
        }
    }
    return( FALSE );

} /* mouseHandler */

static void initInput( input_buffer *input )
{
    type_style      *s;
    window_id       id;

    memset( input->buffer, 0, input->buffer_length );
    input->curr_pos = 0;
    if( input->history != NULL ) {
        input->curr_hist = input->history->curr;
    }
    input->left_column = 0;
    input->overstrike = TRUE;
    s = &input->window.style;
    id = input->window.id;
    thisWindow = id;
    s->foreground = WindowAuxInfo( id, WIND_INFO_TEXT_COLOR );
    s->background = WindowAuxInfo( id, WIND_INFO_BACKGROUND_COLOR );
    s->font = WindowAuxInfo( id, WIND_INFO_TEXT_FONT );
    input->window.width = WindowAuxInfo( id, WIND_INFO_TEXT_COLS );
    PushMouseEventHandler( mouseHandler );
    NewCursor( input->window.id, NormalCursorType );
    displayLine( input );

} /* initInput */

static void finiInput( input_buffer *input )
{
    input = input;
    thisWindow = NO_WINDOW;
    PopMouseEventHandler();
    if( !EditFlags.NoInputWindow ) {
        NewCursor( input->window.id, NormalCursorType );
    }

} /* finiInput */

/*
 * getStringInWindow: main routine
 */
static bool getStringInWindow( input_buffer *input )
{
    int         event;
    int         old_mode;

    ReadingAString = TRUE;
    initInput( input );
    input->last_str = alloca( input->buffer_length );
    memset( input->last_str, 0, input->buffer_length );
    if( input->history != NULL ) {
        input->curr_hist = input->history->curr;
    }
    while( TRUE ) {
        event = GetNextEvent( FALSE );
        event = cursorKeyFilter( input, event );
        event = historyFilter( input, event );
        event = specialKeyFilter( input, event );
        switch( event ) {
        case HANDLED:
            break;
        case VI_KEY( SHIFT_TAB ):
        case VI_KEY( TAB ):
            if( !fileComplete( input, event ) ) {
                endColumn( input );
                break;
            }
            /* fall through */
        case VI_KEY( ENTER ):
            if( input->buffer[ 0 ] == NO_ADD_TO_HISTORY_KEY ) {
                strcpy( &input->buffer[ 0 ], &input->buffer[ 1 ] );
            } else {
                addHistory( input );
            }
            /* fall through */
        case VI_KEY( ESC ):
            finiInput( input );
            /*
             * this call may not be necessary if the file complete window has
             * already closed of natural causes but it doesn't harm anything
             * if called when not needed - so we leave it here.
             */
            FinishFileComplete();
            ReadingAString = FALSE;
            return( event != VI_KEY( ESC ) );
        case VI_KEY( INS ):
            input->overstrike = !input->overstrike;
            if( !EditFlags.NoInputWindow ) {
                NewCursor( input->window.id,
                    input->overstrike ? NormalCursorType : InsertCursorType );
            }
            break;
        case VI_KEY( CTRL_END ):
            saveStr( input );
            input->buffer[ input->curr_pos ] = 0;
            break;
        case VI_KEY( CTRL_X ):
        case VI_KEY( CTRL_U ):
            saveStr( input );
            input->buffer[ 0 ] = 0;
            endColumn( input );
            break;
        case VI_KEY( CTRL_INS ):
            swapString( input );
            break;
        case VI_KEY( CTRL_V ):
        case VI_KEY( CTRL_Q ):
            insertChar( input, '^' );
            displayLine( input );
            // here we have a bit of a kluge
            input->curr_pos -= 1;
            event = GetNextEvent( FALSE );
            saveStr( input );
            old_mode = input->overstrike;
            input->overstrike = TRUE;
            insertChar( input, event );
            input->overstrike = old_mode;
            break;
        case VI_KEY( ALT_END ):
            /* just want to redraw the line - for windows */
            break;
        default:
            if( (event >= 32 && event < 128) || event == VI_KEY( CTRL_A ) ) {
                saveStr( input );
                if( !insertChar( input, event ) ) {
                    MyBeep();
                }
            }
        }
        if( !EditFlags.NoInputWindow ) {
            displayLine( input );
        }
    }

} /* getStringInWindow */

bool ReadStringInWindow( window_id id, int line, char *prompt, char *str,
    int max_len, history_data *history )
{
    input_buffer        input;
    int                 rc;

    input.prompt = prompt;
    input.buffer = str;
    input.buffer_length = max_len;
    input.history = history;
    input.window.id = id;
    input.window.line = line;
#ifdef __WIN__
    input.cache = (char *)MemAlloc( max_len );
    input.cache[ 0 ] = 0;
#endif
    rc = getStringInWindow( &input );
#ifdef __WIN__
    MemFree( input.cache );
#endif
    return( rc );

} /* ReadStringInWindow */

int PromptForString( char *prompt, char *buffer,
                        int buffer_length, history_data *history )
{
    int                 err;
    window_id           id;

    if( !EditFlags.NoInputWindow ) {
        err = NewWindow2( &id, &cmdlinew_info );
        if( err ) {
            return( err );
        }
    } else {
        id = NO_WINDOW;
    }

    if( !EditFlags.NoInputWindow &&
        strlen( prompt ) >= WindowAuxInfo( id, WIND_INFO_TEXT_COLS ) ) {
        err = ERR_PROMPT_TOO_LONG;
    } else {
        err = NO_VALUE_ENTERED;
        if( ReadStringInWindow( id, 1, prompt, buffer, buffer_length, history ) ) {
            err = ERR_NO_ERR;
        }
    }

    if( !EditFlags.NoInputWindow ) {
        CloseAWindow( id );
        SetWindowCursor();
    } else {
        EditFlags.NoInputWindow = FALSE;
    }
    return( err );

} /* PromptForString */

⌨️ 快捷键说明

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