op.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 383 行
C
383 行
/****************************************************************************
*
* 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 <ctype.h>
#include "vi.h"
#include "keys.h"
#include "winaux.h"
#include "win.h"
#ifdef __WIN__
#include "winvi.h"
#endif
int LineLength( linenum l )
{
line *line;
fcb *fcb;
int rc;
rc = CGimmeLinePtr( l, &fcb, &line );
if( rc != ERR_NO_ERR ) {
return( 0 );
}
return( line->len );
}
int GetLineRange( range *result, long count, linenum line )
{
result->line_based = TRUE;
result->start.line = line;
line += count - 1;
CFindLastLine( &result->end.line );
if( line <= result->end.line ) {
result->end.line = line;
}
return( ERR_NO_ERR );
}
int Delete( range *r )
{
int rc;
// need to perform the actual delete
if( r->line_based ) {
rc = DeleteLineRange( r->start.line, r->end.line, SAVEBUF_FLAG );
DCDisplayAllLines();
LineDeleteMessage( r->start.line, r->end.line );
} else if( r->start.line != r->end.line ) {
rc = Cut( r->start.line, r->start.column,
r->end.line, r->end.column, TRUE );
DCDisplayAllLines();
} else {
GoToLineNoRelCurs( r->start.line );
rc = DeleteRangeOnCurrentLine( r->start.column, r->end.column, TRUE );
}
// move cursor to tl corner of region
if( rc == ERR_NO_ERR ) {
GoToLineNoRelCurs( r->start.line );
r->start.column += 1;
if( r->start.column > CurrentLine->len ) {
if( EditFlags.Modeless ) {
r->start.column = CurrentLine->len + 1;
} else {
r->start.column = CurrentLine->len;
}
}
GoToColumnOnCurrentLine( r->start.column );
EditFlags.Dotable = TRUE;
} else {
rc = DO_NOT_CLEAR_MESSAGE_WINDOW;
}
return( rc );
} /* Delete */
int DeleteLines( void )
{
range r;
GetLineRange( &r, GetRepeatCount(), CurrentLineNumber );
return( Delete( &r ) );
} /* DeleteLines */
int Yank( range *r )
{
int rc;
if( r->line_based ) {
rc = YankLineRange( r->start.line, r->end.line );
} else if( r->start.line == r->end.line ) {
assert( CurrentLineNumber == r->start.line );
AddLineToSavebuf( CurrentLine->data, r->start.column, r->end.column );
#ifdef __WIN__
if( LastSavebuf == 0 ) {
Message1( "%d characters copied into the clipboard",
r->end.column - r->start.column + 1 );
} else
#endif
Message1( "%d %s yanked into buffer %c",
r->end.column - r->start.column + 1,
MSG_CHARACTERS, LastSavebuf );
rc = DO_NOT_CLEAR_MESSAGE_WINDOW;
} else {
rc = Cut( r->start.line, r->start.column,
r->end.line, r->end.column, FALSE );
}
if( rc != ERR_NO_ERR ) {
rc = DO_NOT_CLEAR_MESSAGE_WINDOW;
}
return( rc );
} /* Yank */
int YankLines( void )
{
range r;
GetLineRange( &r, GetRepeatCount(), CurrentLineNumber );
return( Yank( &r ) );
} /* YankLines */
int Change( range *r )
{
int scol, ecol;
int tmp, key, vecol;
int rc;
/*
* change line ranges
*/
if( r->start.line != r->end.line ) {
StartUndoGroup( UndoStack );
if( !r->line_based ) {
rc = Cut( r->start.line, r->start.column,
r->end.line, r->end.column, TRUE );
r->end.column = -1;
scol = -1;
ecol = -1;
} else {
if( r->start.line == CurrentLineNumber ) {
r->start.line++;
} else {
r->end.line--;
}
if( r->start.line <= r->end.line ) {
rc = DeleteLineRange( r->start.line, r->end.line, 0 );
if( rc ) {
EndUndoGroup( UndoStack );
return( rc );
}
}
scol = FindStartOfCurrentLine() - 1;
ecol = CurrentLine->len-1;
}
DCDisplayAllLines();
rc = DeleteAndInsertText( scol, ecol );
EndUndoGroup( UndoStack );
return( rc );
}
/*
* change text on current line
*/
rc = ERR_NO_ERR;
GoToLineNoRelCurs( r->start.line );
ecol = r->end.column;
scol = r->start.column;
#ifdef __WIN__
vecol = vecol;
// GetCurrentLine();
strcpy( WorkLine->data, CurrentLine->data );
tmp = WorkLine->data[ ecol ];
WorkLine->data[ ecol ] = '$';
#else
vecol = VirtualCursorPosition2( ecol+1 );
vecol--;
ExpandTabsInABuffer( CurrentLine->data, CurrentLine->len, WorkLine->data, MaxLine );
WorkLine->len = strlen( WorkLine->data );
tmp = WorkLine->data[vecol];
WorkLine->data[vecol] = '$';
#endif
if( WorkLine->len == 0 ) {
WorkLine->data[1] = 0;
}
EditFlags.InsertModeActive = TRUE;
GoToColumn( scol+1, CurrentLine->len );
EditFlags.InsertModeActive = FALSE;
DisplayWorkLine( TRUE );
UnselectRegion();
DCUpdate();
#ifndef __WIN__
HiliteAColumnRange( CurrentLineNumber, scol, ecol );
#endif
/*
* now, get ready to do change
*/
key = GetNextEvent( FALSE );
#ifdef __WIN__
WorkLine->data[ ecol ] = tmp;
#else
WorkLine->data[ vecol ] = tmp;
#endif
DisplayWorkLine( TRUE );
if( key == VI_KEY( ESC ) && !EditFlags.ChangeLikeVI ) {
WorkLine->len = -1;
GoToColumn( scol+1, CurrentLine->len );
} else {
KeyAdd( key );
rc = DeleteAndInsertText( scol, ecol );
}
return( rc );
} /* Change */
/*
* doPush - shove/suck tab spaces in text
*/
static int doPush( range *r, bool shove )
{
int rc;
/*
* get the line range
*/
if( r->start.line == r->end.line && !r->line_based ) {
rc = ERR_INVALID_LINE_RANGE;
} else {
rc = Shift( r->start.line, r->end.line, shove ? '>' : '<', TRUE );
if( rc <= 0 ) {
#if 0
GoToLineNoRelCurs( r->start.line );
#endif
GoToColumnOnCurrentLine( FindStartOfCurrentLine() );
EditFlags.Dotable = TRUE;
}
}
return( rc );
} /* doPush */
int StartShove( range *r )
{
UpdateCurrentStatus( CSTATUS_SHIFT_RIGHT );
return( doPush( r, TRUE ) );
} /* StartShove */
int StartSuck( range *r )
{
UpdateCurrentStatus( CSTATUS_SHIFT_LEFT );
return( doPush( r, FALSE ) );
} /* StartSuck */
/*
* changeOneLine: change the case for each character on the given line
* from the starting column given by start_col (base 0) to the column
* denoted by end_col (base 0).
*/
static int changeOneLine( linenum line_num, int start_col, int end_col )
{
line *line;
fcb *fcb;
int rc, num_cols, i;
char *s;
rc = CGimmeLinePtr( line_num, &fcb, &line );
if( rc == ERR_NO_ERR ) {
assert( end_col < line->len && end_col >= start_col );
num_cols = end_col - start_col + 1;
s = &line->data[ start_col ];
for( i = 0; i < num_cols; i++ ) {
if( isupper( *s ) ) {
*s = tolower( *s );
} else {
*s = toupper( *s );
}
s++;
}
}
return( rc );
}
static int changeToEndOfLine( linenum line, int start )
{
int len, rc;
rc = ERR_NO_ERR;
len = LineLength( line );
if( len ) {
rc = changeOneLine( line, start, len - 1 );
}
return( rc );
}
int ChangeCase( range *r )
{
linenum curr;
int rc;
long total;
char *msg;
UndoReplaceLines( r->start.line, r->end.line );
if( r->start.line == r->end.line ) {
rc = changeOneLine( r->start.line, r->start.column, r->end.column );
msg = MSG_CHARACTERS;
total = r->end.column - r->start.column + 1;
} else {
rc = changeToEndOfLine( r->start.line, r->start.column );
if( rc != ERR_NO_ERR ) {
return( rc );
}
for( curr = r->start.line + 1; curr < r->end.line; curr++ ) {
rc = changeToEndOfLine( curr, 0 );
if( rc != ERR_NO_ERR ) {
return( rc );
}
}
rc = changeOneLine( r->end.line, 0, r->end.column );
msg = MSG_LINES;
total = r->end.line - r->start.line + 1;
}
EditFlags.Dotable = TRUE;
DCDisplayAllLines();
Message1( "case toggled for %l %s", total, msg );
Modified( TRUE );
return( DO_NOT_CLEAR_MESSAGE_WINDOW );
} /* ChangeCase */
int Filter( range *r )
{
int rc;
char cmd[ MAX_STR ];
rc = PromptForString( "Command: ", cmd, sizeof( cmd ), &FilterHist );
if( rc == ERR_NO_ERR ) {
rc = DoGenericFilter( r->start.line, r->end.line, cmd );
} else {
if( rc == NO_VALUE_ENTERED ) {
rc = ERR_NO_ERR;
}
}
return( rc );
} /* Filter */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?