editmain.c

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

C
616
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <ctype.h>
#include "vi.h"
#include "keys.h"
#include "source.h"
#include "win.h"
#ifdef __WIN__
#include "winrtns.h"
#endif

static event *nextEvent( void )
{
    LastEvent = GetNextEvent( TRUE );
    return( &EventList[ LastEvent ] );
}

static void defaultRange( range *range )
{
    range->start.line = CurrentLineNumber;
    range->start.column = CurrentColumn;
    range->end.line = CurrentLineNumber;
    range->end.column = CurrentColumn;
    range->line_based = FALSE;
    /*
     * we don't fill in hi_start and hi-end - assume that if a routine
     * is going to modify range->highlight then it had better set those
     * other values to something as well.
     */
    range->highlight = FALSE;
    range->fix_range = FALSE;

} /* defaultRange */

/*
 * doOperator - process an operator event
 */
static int doOperator( event *ev )
{
    event       *next;
    int         rc;
    long        count;
    range       range;
    int         next_type;
    bool        is_op_alias;

    rc = ERR_INVALID_OP;
    defaultRange( &range );
    count = GetRepeatCount();
    is_op_alias = ev->b.is_op_alias;
    if( is_op_alias ) {
        ev->rtn.alias( &ev, &next );
    } else {
        next = nextEvent();
        // a count is the only thing allowed to interfere between an op and
        // its argument so we just keep chewing...
        if( next != &EventList[ '0' ] ) {
            while( next->b.is_number ) {
                if( EditFlags.Modeless ) {
                    next->alt_rtn.old();
                } else {
                    next->rtn.old();
                }
                next = nextEvent();
            }
        }
        count *= GetRepeatCount();
    }
    KillRepeatWindow();
    if( EditFlags.Modeless ) {
        range.fix_range = next->alt_b.fix_range;
        next_type = next->alt_b.type;
    } else {
        range.fix_range = next->b.fix_range;
        next_type = next->b.type;
    }
    EditFlags.OperatorWantsMove = TRUE; // was: if( count==1 )
    if( next_type == EVENT_OP ) {
        // op/op only valid when ops are equal
        if( next == ev ) {
            rc = GetLineRange( &range, count, CurrentLineNumber );
        }
    } else {
        // it had better be a move operation
        if( next_type == EVENT_REL_MOVE || next_type == EVENT_ABS_MOVE ) {
            /*
             * Kluge! want 'ce' instead of 'cw' - this sucks.
             *
             * - even better kludge: if we are currently on white
             *   space, then treat 'cw' as 'cw'. arrrrr. cge.
             */
            if( (ev == &EventList[ 'c' ] || ev == &EventList[ VI_KEY(ALT_F1) ]) &&
                        LastEvent == 'w' ) {
                EditFlags.IsChangeWord = TRUE;
                if( CurrentLine != NULL ) {
                    if( !isspace( CurrentLine->data[CurrentColumn-1] ) ) {
                        next = &EventList[ 'e' ];
                        range.fix_range = FALSE;
                    }
                }
            }
            if( EditFlags.Modeless ) {
                rc = next->alt_rtn.move( &range, count );
            } else {
                rc = next->rtn.move( &range, count );
            }
            EditFlags.IsChangeWord = FALSE;
        } else {
            /*
             * Kluge! treat 'r' as a movement command.
             */
            if( LastEvent == 'r' ) {
                rc = GetSelectedRegion( &range );
            } else if( LastEvent == '0' ) {
                rc = MoveLineBegin( &range, 1 );
            } else if( LastEvent == VI_KEY( ESC ) ) {
                rc = RANGE_REQUEST_CANCELLED;
            }
        }
    }
    EditFlags.OperatorWantsMove = FALSE;
    if( rc == ERR_NO_ERR ) {
        if( ev->b.modifies ) {
            rc = ModificationTest();
        }
        if( rc == ERR_NO_ERR ) {
            NormalizeRange( &range );
            if( EditFlags.Modeless ) {
                rc = ev->alt_rtn.op( &range );
            } else {
                rc = ev->rtn.op( &range );
            }
        }
    }
    return( rc );

} /* doOperator */

/*
 * DoMove - handle a movement command
 */
int DoMove( event *ev )
{
    range       range;
    int         rc;
    int         curcol;
    int         type;

    defaultRange( &range );
    if( EditFlags.Modeless ) {
        rc = ev->alt_rtn.move( &range, GetRepeatCount() );
        type = ev->alt_b.type;
    } else {
        rc = ev->rtn.move( &range, GetRepeatCount() );
        type = ev->b.type;
    }
    if( rc == ERR_NO_ERR ) {
        curcol = CurrentColumn;
        if( range.start.line != CurrentLineNumber ) {
            if( type == EVENT_REL_MOVE ) {
                GoToLineRelCurs( range.start.line );
            } else {
                curcol = -1;
                MemorizeCurrentContext();
                GoToLineNoRelCurs( range.start.line );
            }
        }
        if( curcol != range.start.column ) {
            GoToColumnOK( range.start.column );
        }
#ifndef __WIN__
        if( range.highlight ) {
            // don't handle multi-line highlights yet
            assert( range.hi_start.line == range.hi_end.line );
            EditFlags.ResetDisplayLine = TRUE;
            DCUpdate();
            HiliteAColumnRange( range.hi_start.line,
                range.hi_start.column, range.hi_end.column );
        }
#endif
    }
    return( rc );
}

static void ensureCursorDisplayed( void )
{
    int         len, wc, diff;

    if( ( EditFlags.Modeless == TRUE ) && ( CurrentFile != NULL ) ) {
        len = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES );
        if( CurrentLineNumber < TopOfPage ||
            CurrentLineNumber > TopOfPage + len - 1 ) {
                SetCurrentLine( CurrentLineNumber );
        }

        wc = VirtualCursorPosition() - LeftColumn;
        if( !ColumnInWindow( wc, &diff ) ) {
            SetCurrentColumn( CurrentColumn );
        }
    }
}

/*
 * DoLastEvent - process the last keystroke event
 */
int DoLastEvent( void )
{
    event       *event;
    int         rc;
    bool        keep_sel;

    if( LastEvent >= EventCount ) {
        return( InvalidKey() );
    } else {
        if( !EditFlags.InsertModeActive || EditFlags.Modeless ) {
            if( !EditFlags.Modeless && KeyMaps[LastEvent].data != NULL ) {
                if( !KeyMaps[LastEvent].inuse ) {
                    return( DoKeyMap( LastEvent ) );
                }
            }
            event = &EventList[ LastEvent ];
            keep_sel = event->b.keep_selection;
            if( event->b.keep_selection_maybe ) {
                if( SelRgn.selected ) {
                    keep_sel = TRUE;
                }
            }
            if( !keep_sel && !EditFlags.ScrollCommand ) {
                UnselectRegion();
            }
            if( EditFlags.ScrollCommand == FALSE ) {
                ensureCursorDisplayed();
            }
            switch( event->b.type ) {
            case EVENT_INS:
                if( EditFlags.Modeless ) {
                    /* don't allow following cursor movements to affect seln
                     */
                    keep_sel = SelRgn.selected;
                    DeleteSelectedRegion();
                    SelRgn.selected = keep_sel;
                    InsertLikeLast();
                    rc = event->rtn.ins();
                    DoneCurrentInsert( FALSE );
                    SelRgn.selected = FALSE;
                } else {
                    if( !EditFlags.InsertModeActive ) {
                        InsertLikeLast();
                    }
                    rc = event->rtn.ins();
                }
                break;
            case EVENT_OP:
                DoneCurrentInsert( TRUE );
                rc = doOperator( event );
                break;
            case EVENT_REL_MOVE:
            case EVENT_ABS_MOVE:
                DoneCurrentInsert( TRUE );
                rc = DoMove( event );
                break;
            case EVENT_MISC:
                DoneCurrentInsert( TRUE );
                rc = event->rtn.old();
                break;
            }
            return( rc );
        } else {
//          UnselectRegion();
            if( EditFlags.EscapedInsertChar ) {
                return( IMChar() );
            } else {
                if( InputKeyMaps[LastEvent].data != NULL ) {

⌨️ 快捷键说明

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