editins.c

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

C
1,162
字号
/****************************************************************************
*
*                            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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef M_I86
#include <i86.h>
#endif
#include "vi.h"
#include "keys.h"
#include "source.h"
#include "menu.h"
#include "win.h"

static bool     currLineRepUndo;
static bool     overStrike;
static bool     needNewUndoForLine;
static int      abbrevCnt;
static char     abbrevBuff[MAX_STR];

/*
 * startNewLineUndo - start current line undo stuff
 */
static void startNewLineUndo( void )
{
    if( needNewUndoForLine ) {
        CurrentLineReplaceUndoStart();
        currLineRepUndo = TRUE;
        GetCurrentLine();
        needNewUndoForLine = FALSE;
    }

} /* startNewLineUndo */

/*
 * doneWithCurrentLine - update current line, and update undo record
 */
static void doneWithCurrentLine( void )
{
    startNewLineUndo();
    ReplaceCurrentLine();
    if( currLineRepUndo ) {
        ConditionalCurrentLineReplaceUndoEnd();
        currLineRepUndo = FALSE;
    } else {
        EndUndoGroup( UndoStack );
    }

} /* doneWithCurrentLine */

#define WHITE_SPACE( x ) ( (x) == ' ' || (x) == '\t' )

/*
 * trimWorkLine - remove trailing whitespace from work line
 */
static int trimWorkLine( void )
{
    int i,len;

    len = 0;
    if( EditFlags.CMode ) {
        i = WorkLine->len - 1;
        while( i>=0 && WHITE_SPACE( WorkLine->data[i] ) ) {
            i--;
        }
        if( i == -1 ) {
            len = RealLineLen( WorkLine->data );
        }
        WorkLine->len = i+1;
        WorkLine->data[i+1] = 0;
    }
    return( len );

} /* trimWorkLine */

/*
 * DoneCurrentInsert - finished current insertion of text
 */
void DoneCurrentInsert( bool trim )
{
    if( EditFlags.InsertModeActive ) {
        EditFlags.InsertModeActive = FALSE;
        if( trim ) {
            trimWorkLine();
        }
        if( CurrentColumn > WorkLine->len ) {
            if( EditFlags.Modeless ) {
                GoToColumnOK( WorkLine->len+1 );
            } else {
                GoToColumnOK( WorkLine->len );
            }
        }
        doneWithCurrentLine();
        EndUndoGroup( UndoStack );
        if( !EditFlags.Modeless ) {
            NewCursor( CurrentWindow, NormalCursorType );
            SetWindowCursor();
        }
        EditFlags.EscapedInsertChar = FALSE;
        EditFlags.NoReplaceSearchString = FALSE;
    }
} /* DoneCurrentInsert */

/*
 * UpdateEditStatus - update current editing status
 */
void UpdateEditStatus( void )
{
    if( overStrike ) {
        UpdateCurrentStatus( CSTATUS_OVERSTRIKE );
        EditFlags.WasOverstrike = TRUE;
        NewCursor( CurrentWindow, OverstrikeCursorType );
    } else {
        UpdateCurrentStatus( CSTATUS_INSERT );
        EditFlags.WasOverstrike = FALSE;
        NewCursor( CurrentWindow, InsertCursorType );
    }
    SetWindowCursor();

} /* UpdateEditStatus */

/*
 * addChar - add character to working line
 */
static void addChar( char ch )
{
    char    overChar;
    int     i;

    if( WorkLine->len == 0 ) {
        WorkLine->data[ 0 ] = ch;
        WorkLine->data[ 1 ] = 0;
        WorkLine->len = 1;
        DisplayWorkLine( SSKillsFlags( ch ) );
        return;
    }

    overChar = WorkLine->data[ CurrentColumn - 1 ];
    DisplayWorkLine( SSKillsFlags( ch ) || SSKillsFlags( overChar ) );

    if( !overStrike ) {
        for( i = WorkLine->len; i >= CurrentColumn - 1; i-- ) {
            WorkLine->data[ i + 1 ] = WorkLine->data[ i ];
        }
        WorkLine->data[ CurrentColumn - 1 ] = ch;
        WorkLine->len++;
    } else {
        WorkLine->data[ CurrentColumn - 1] = ch;
        if( CurrentColumn - 1 == WorkLine->len ) {
            WorkLine->len++;
            WorkLine->data[ WorkLine->len ] = 0;
        }
    }
} /* addChar */

/*
 * checkWrapMargin - see if we have moved past the wrap margin
 */
static void checkWrapMargin( void )
{
    int         i;
    int         width;
    int         pos;
    bool        old_ai;

    if( WrapMargin != 0 ) {
        if( WrapMargin < 0 ) {
            width = -WrapMargin;
        } else {
            width = WindowAuxInfo( CurrentWindow, WIND_INFO_WIDTH ) - WrapMargin;
        }
        if( CurrentColumn > width ) {
            for( i = CurrentColumn - 1;i>=0;i-- ) {
                if( isspace( WorkLine->data[ i ] ) ) {
                    pos = CurrentColumn -1 - i;
                    CurrentColumn = i+2;
                    old_ai = EditFlags.AutoIndent;
                    EditFlags.AutoIndent = FALSE;
                    IMEnter();
                    EditFlags.AutoIndent = old_ai;
                    GoToColumnOK( pos );
                    return;
                }
            }
        }
    }

} /* checkWrapMargin */

/*
 * insertChar - insert a char into the working line
 */
static int insertChar( bool add_to_abbrev, bool move_to_new_col )
{
    if( WorkLine->len == MaxLine ) {
        return( ERR_NO_ERR );
    }
    addChar( LastEvent );
    if( move_to_new_col ) {
        GoToColumn( CurrentColumn+1, WorkLine->len+1 );
    }
    if( abbrevCnt < sizeof( abbrevBuff ) && add_to_abbrev ) {
        abbrevBuff[abbrevCnt++] = LastEvent;
    }
    checkWrapMargin();
    return( ERR_NO_ERR );

} /* insertChar */

/*
 * IMChar - insert a character in insert mode
 */
int IMChar( void )
{
    if( CurrentFile == NULL ) {
        return( ERR_NO_ERR );
    }
    CurrentFile->need_autosave = TRUE;

    startNewLineUndo();
    if( EditFlags.EscapedInsertChar ) {
        DisplayWorkLine( SSKillsFlags( LastEvent ) ||
                         SSKillsFlags( WorkLine->data[CurrentColumn-1] ) );
        WorkLine->data[CurrentColumn-1] = LastEvent;
        GoToColumn( CurrentColumn +1, WorkLine->len+1 );
        EditFlags.EscapedInsertChar = FALSE;
        return( ERR_NO_ERR );
    }

    return( insertChar( TRUE, TRUE ) );

} /* IMChar */

/*
 * IMEsc - handle ESC from insert mode
 */
int IMEsc( void )
{
    DoneCurrentInsert( TRUE );
    return( ERR_NO_ERR );

} /* IMEsc */

/*
 * IMEnter - process the enter key in insert mode
 */
int IMEnter( void )
{
    char        *buff,*buffx;
    int         len,col,el;

    if( CurrentFile == NULL ) {
        return( ERR_NO_FILE );
    }
    CurrentFile->need_autosave = TRUE;

    startNewLineUndo();
    CheckAbbrev( abbrevBuff, &abbrevCnt );
    abbrevCnt = 0;

    /*
     * truncate the working line
     */
    buff = StaticAlloc();
    buffx = StaticAlloc();
    el = WorkLine->len - CurrentColumn+1;
    if( el > 0 && WorkLine->len > 0 ) {
        memcpy( buff, &WorkLine->data[CurrentColumn-1], el + 1 );
        WorkLine->len -= el;
        WorkLine->data[CurrentColumn-1] = 0;
    } else {
        el = 0;
        buff[0] = 0;
    }

    len = trimWorkLine();

    /*
     * replace the current line with the working copy
     */
    ReplaceCurrentLine();
    if( currLineRepUndo ) {
        CurrentLineReplaceUndoEnd( FALSE );
        currLineRepUndo = FALSE;
    }

    /*
     * create a new line, insert leading spaces if needed
     * and copy in the truncation
     */
    if( EditFlags.AutoIndent ) {
        len = GetAutoIndentAmount( buffx, len, FALSE );
        el += len;
        strcat( buffx, buff );
        AddNewLineAroundCurrent( buffx,el, INSERT_AFTER );
        col = len+1;
    } else {
        AddNewLineAroundCurrent( buff,el, INSERT_AFTER );
        col = 1;
    }
    UndoInsert( CurrentLineNumber+1, CurrentLineNumber+1, UndoStack );

    /*
     * display the result
     */
    DCDisplayAllLines();
    GoToLineRelCurs( CurrentLineNumber + 1 );
    GoToColumnOK( col );
    GetCurrentLine();
    StaticFree( buff );
    StaticFree( buffx );
    return( ERR_NO_ERR );

} /* IMEnter */

/*
 * IMBackSpace - process the backspace key in insert mode
 */
int IMBackSpace( void )
{
    char        killedChar, overChar;
    bool        mv_right;
    bool        stay_at_end;
    int         i;

    if( CurrentFile == NULL ) {
        return( ERR_NO_FILE );
    }

    startNewLineUndo();
    if( abbrevCnt > 0 ) {
        abbrevCnt--;
    }
    if( CurrentColumn == 1 ) {

        if( !EditFlags.WrapBackSpace ) {
            return( ERR_NO_ERR );
        }
        if( CurrentLineNumber ==1 ) {
            return( ERR_NO_ERR );
        }
        stay_at_end = FALSE;
        if( WorkLine->len == 0 ) {
            stay_at_end = TRUE;
        }
        doneWithCurrentLine();
        abbrevCnt = 0;
        GoToLineRelCurs( CurrentLineNumber - 1 );
        GoToColumnOnCurrentLine( CurrentLine->len );
        mv_right = TRUE;
        if( CurrentLine->len == 0 ) {
            mv_right = FALSE;
        }
        GenericJoinCurrentLineToNext( FALSE );
        if( mv_right && !stay_at_end ) {
            GoToColumnOnCurrentLine( CurrentColumn + 1 );
        }
        if( stay_at_end ) {
            GoToColumnOK( CurrentLine->len+1 );
        }
        CurrentLineReplaceUndoStart();
        currLineRepUndo = TRUE;
        GetCurrentLine();
        return( ERR_NO_ERR );
    }
    killedChar = WorkLine->data[ CurrentColumn - 2 ];
    overChar = WorkLine->data[ CurrentColumn - 1 ];
    for( i = CurrentColumn-1; i <= WorkLine->len+1; i++ ) {
        WorkLine->data[i-1] = WorkLine->data[i];
    }
    WorkLine->len--;
    GoToColumn( CurrentColumn - 1, WorkLine->len+1 );
    DisplayWorkLine( SSKillsFlags( killedChar ) || SSKillsFlags( overChar ) );
    return( ERR_NO_ERR );

} /* IMBackSpace */

/*
 * IMDelete - handle DEL key pressed in insert mode
 */
int IMDelete( void )
{
    int wlen;

    if( CurrentFile == NULL ) {
        return( ERR_NO_FILE );
    }

    startNewLineUndo();
    wlen = WorkLine->len+1;
    if( wlen == 0 ) {
        wlen = CurrentLine->len+1;
    }
    if( EditFlags.Modeless && CurrentColumn == wlen && CurrentLine->next ) {
        /* go to beginning of next line
        */
        GoToLineRelCurs( CurrentLineNumber + 1 );
        GoToColumnOK( 1 );
        GetCurrentLine();
    } else {
        GoToColumn( CurrentColumn + 1, wlen );
        if( CurrentColumn != wlen-1 || abbrevCnt == 0 ) {
            abbrevCnt++;        /* gets subtracted by IMBackSpace */
        }
    }
    return( IMBackSpace() );

} /* IMDelete */

/*
 * IMDeleteML - delete char iff no selection
 */
int IMDeleteML( void )
{
    if( !SelRgn.selected ) {
        return( IMDelete() );
    } else {
        return( ERR_NO_ERR );
    }
} /* IMDeleteML */

/*
 * IMBackSpaceML - backspace iff no selection
 */
int IMBackSpaceML( void )
{
    if( !SelRgn.selected ) {
        return( IMBackSpace() );
    } else {
        return( ERR_NO_ERR );
    }
} /* IMBackSpaceML */

/*
 * IMMouseEvent - handle a mouse event in insert mode
 */
int IMMouseEvent( void )
{
    if( LastMouseEvent == MOUSE_MOVE
        || LastMouseEvent == MOUSE_RELEASE
        || LastMouseEvent == MOUSE_RELEASE_R ) {
        return( ERR_NO_ERR );
    }
    EditFlags.ReturnToInsertMode = TRUE;
    DoneCurrentInsert( TRUE );
    AddCurrentMouseEvent();
    return( ERR_NO_ERR );

} /* IMMouseEvent */

/*
 * IMCursorKey - handle cursor keys in insert mode
 */
int IMCursorKey( void )
{
    int         wlen;
    event       *ev;
    int         type;

    wlen = WorkLine->len+1;
    if( wlen == 0 ) {
        wlen = CurrentLine->len+1;
    }

    /*
     * handle movement on the same line
     */
    switch( LastEvent ) {
    case VI_KEY( HOME ):
        GoToColumn( 1, wlen );
        abbrevCnt = 0;
        return( ERR_NO_ERR );
    case VI_KEY( END ):
        GoToColumnOK( wlen);
        abbrevCnt = 0;
        return( ERR_NO_ERR );
    case VI_KEY( LEFT ):
        GoToColumn( CurrentColumn - 1, wlen);
        abbrevCnt = 0;
        return( ERR_NO_ERR );
    case VI_KEY( RIGHT ):
        GoToColumn( CurrentColumn + 1, wlen);
        abbrevCnt = 0;
        return( ERR_NO_ERR );
    }

    /*
     * handle movement that leaves the current line
     */
    ev = &EventList[ LastEvent ];
    if( EditFlags.Modeless ) {
        type = ev->alt_b.type;
    } else {
        type = ev->b.type;
    }

    if( needNewUndoForLine ) {
        if( type == EVENT_REL_MOVE || type == EVENT_ABS_MOVE ) {
            DoMove( ev );
        } else {
            if( EditFlags.Modeless ) {
                ev->alt_rtn.old();
            } else {
                ev->rtn.old();
            }
        }
        return( ERR_NO_ERR );
    }
    if( CurrentColumn > WorkLine->len ) {
        GoToColumnOK( WorkLine->len+1 );
    }
    doneWithCurrentLine();
    if( type == EVENT_REL_MOVE || type == EVENT_ABS_MOVE ) {
        DoMove( ev );
    } else {
        if( EditFlags.Modeless ) {
            ev->alt_rtn.old();
        } else {
            ev->rtn.old();
        }
    }
    needNewUndoForLine = TRUE;
    abbrevCnt = 0;
    return( ERR_NO_ERR );

} /* IMCursorKey */

/*
 * IMMenuKey - process menu keys from insert mode
 */
int IMMenuKey( void )
{
    if( IsMenuHotKey( LastEvent - VI_KEY( ALT_A ) + 'A' ) ) {
        DoneCurrentInsert( TRUE );
        KeyAdd( LastEvent );
        EditFlags.ReturnToInsertMode = TRUE;
    }
    return( ERR_NO_ERR );

} /* IMMenuKey */

/*
 * IMSpace - handle a space in insert mode
 */
int IMSpace( void )
{
    startNewLineUndo();
    CheckAbbrev( abbrevBuff, &abbrevCnt );
    abbrevCnt = 0;
    return( insertChar( FALSE, TRUE ) );

⌨️ 快捷键说明

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