opmove.c

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

C
623
字号
/****************************************************************************
*
*                            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 <ctype.h>
#include "vi.h"
#include "keys.h"
#include "win.h"

static int lastChar[2];

static int checkLine( linenum *ln )
{
    int         rc;
    linenum     last;

    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    rc = ERR_NO_ERR;
    if( (*ln) < 1 ) {
        *ln = 1;
        rc = ERR_NO_SUCH_LINE;
    } else {
        CFindLastLine( &last );
        if( (*ln) > last ) {
            *ln = last;
            rc = ERR_NO_SUCH_LINE;
        }
    }
    if( ( EditFlags.Modeless == TRUE ) && ( rc == ERR_NO_SUCH_LINE ) ) {
        rc = ERR_NO_ERR;
    }
    return( rc );
}

static int checkLeftMove( linenum line, int *col, range *r )
{
    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    if( (*col) < 1 ) {
        if( EditFlags.Modeless ) {
            if( line > 1 ) {
                r->start.line = line - 1;
                r->line_based = TRUE;
                *col = LineLength( line - 1 ) + 1;

            } else {
                *col = 1;
            }
        } else {
            *col = 1;
            return( ERR_NO_SUCH_COLUMN );
        }
    }
    return( ERR_NO_ERR );
}

static int checkRightMove( linenum line, int *col, range *r )
{
    int         len;

    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    len = LineLength( line );
    if( EditFlags.Modeless ) {
        len++;
    }
    if( (*col) > len ) {
        if( EditFlags.Modeless ) {
            if ( !IsPastLastLine( line + 1 ) ) {
                r->start.line = line + 1;
                r->line_based = TRUE;
                *col = 1;
            } else {
                *col = len;
            }
        } else {
            if( EditFlags.OperatorWantsMove ) {
                if( *col == len+1 ) {
                    return( ERR_NO_ERR );
                }
            }
            *col = len;
            return( ERR_NO_SUCH_COLUMN );
        }
    }
    return( ERR_NO_ERR );
}

/*
 * verifyMoveFromPageTop - move a certain amount past the top of page,
 *                         verifying that the end of file is not overrun
 */
static int verifyMoveFromPageTop( range *r, linenum ln )
{
    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    ln += TopOfPage;
    if( IsPastLastLine( ln ) ) {
        CFindLastLine( &ln );
    }
    r->line_based = TRUE;
    r->start.line = ln;
    return( ERR_NO_ERR );

} /* verifyMoveFromPageTop */

/*
 * MovePageMiddle - move to the middle of the page
 */
int MovePageMiddle( range *r, long count )
{
    linenum     ln, lne;

    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    count = count;
    ln = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES ) - 1;
    CFindLastLine( &lne );
    lne = lne - TopOfPage + 1;
    if( ln > lne ) {
        ln = lne;
    }
    return( verifyMoveFromPageTop( r, ln / 2 ) );

} /* MovePageMiddle */

int MovePageTop( range *r, long count )
{
    return( verifyMoveFromPageTop( r, count - 1 ) );

} /* MovePageTop */

int MovePageBottom( range *r, long count )
{
    linenum     ln;
    int         lines;
    int         amt;

    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    lines = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES );
    if( IsPastLastLine( TopOfPage + lines ) ) {
        CFindLastLine( &ln );
        amt = ln - TopOfPage - count + 1;
    } else {
        amt = lines - count;
    }

    return( verifyMoveFromPageTop( r, amt ) );

} /* MovePageBottom */

static int doVerticalMove( range *r, linenum new )
{
    int         rc;

    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    rc = checkLine( &new );
    r->start.line = new;
    r->start.column = CurrentColumn;
    r->line_based = TRUE;
    return( rc );
}

int MoveUp( range *r, long count )
{
    return( doVerticalMove( r, CurrentLineNumber - count ) );
}

int MoveDown( range *r, long count )
{
    return( doVerticalMove( r, CurrentLineNumber + count ) );
}


static int newColumnOnCurrentLine( range *r, int new_col )
{
    int   rc;

    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    rc = ERR_NO_ERR;
    r->start.line = CurrentLineNumber;
    r->line_based = FALSE;
    if( new_col < CurrentColumn ) {
        rc = checkLeftMove( CurrentLineNumber, &new_col, r );
    } else {
        rc = checkRightMove( CurrentLineNumber, &new_col, r );
    }
    r->start.column = new_col;
    return( rc );
}

int MoveLineEnd( range *r, long count )
{
    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    count = count;
    if( EditFlags.Modeless ) {
        return( newColumnOnCurrentLine( r, CurrentLine->len + 1 ) );
    } else {
        return( newColumnOnCurrentLine( r, CurrentLine->len ) );
    }
}

int MoveStartOfLine( range *r, long count )
{
    count = count;
    if( CurrentLine == NULL ) {
        return( ERR_NO_FILE );
    }
    return( newColumnOnCurrentLine( r, FindStartOfCurrentLine() ) );
}

int MoveLineBegin( range *r, long count )
{
    int rc;
    count = count;
    rc = newColumnOnCurrentLine( r, 1 );

    // Make "Home" behave like "0"
    LeftColumn = 0;
    DCDisplayAllLines();
    return( rc );
}

int MoveLeft( range *r, long count )
{
    return( newColumnOnCurrentLine( r, CurrentColumn - (int)count ) );
}

int MoveRight( range *r, long count )
{
    return( newColumnOnCurrentLine( r, CurrentColumn + (int)count ) );
}

int MoveToColumn( range *r, long count )
{
    return( newColumnOnCurrentLine( r, RealCursorPosition( (int)count ) ) );
}

/*
 * MoveTab - move forward a tab
 */
int MoveTab( range *r, long count )
{
    int                 i, vc, len;

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

    r->start.line = CurrentLineNumber;
    r->line_based = FALSE;
    len = RealLineLen( CurrentLine->data );
    vc = VirtualCursorPosition();
    while( count ) {
        i = Tab( vc, TabAmount );
        vc += i;
        if( vc > len ) {
            r->start.column = len;
            return( ERR_NO_SUCH_COLUMN );
        }
        count -= 1;
    }
    r->start.column = RealCursorPosition( vc );
    return( ERR_NO_ERR );
} /* MoveTab */

/*

⌨️ 快捷键说明

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