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 + -
显示快捷键?