readstr.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 870 行 · 第 1/2 页
C
870 行
/****************************************************************************
*
* 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 <stdarg.h>
#include <string.h>
#include "walloca.h"
#include "vi.h"
#include "keys.h"
#include "win.h"
#include "source.h"
#include "mouse.h"
#ifdef __WIN__
#include "winvi.h"
#include "utils.h"
#endif
#define HANDLED 0
typedef struct input_win_info {
window_id id;
type_style style;
int width;
int line; /* we don't support multi-line input yet */
} input_win_info;
typedef struct input_buffer {
char *prompt;
char *buffer;
#ifdef __WIN__
char *cache;
#endif
char *last_str;
int buffer_length;
history_data *history;
int curr_hist;
input_win_info window;
type_style style;
int curr_pos;
int left_column;
int line;
unsigned overstrike:1;
} input_buffer;
/*
* This is half of a kluge connected with the window proc for the
* command window under the __WIN__ environs. Puke...
*/
bool ReadingAString = FALSE;
/*
* General utility funtions:
* insertChar( input_buffer *, char ) - insert the given character at the
* current position paying attention to overstrike mode. This
* function will update curr_pos.
* deleteChar( input_buffer *, backwards ) - deletes the character at the
* current position if possible and updates curr_pos.
* displayLine( input_buffer * ) - displays the line in the window and
* sets the cursor to curr_pos.
* saveStr( input_buffer *, str ) - saves the string in the input buffer
* to the location given. Enough memory to hold string is assumed.
*/
static bool insertChar( input_buffer *input, int ch )
{
char *ptr;
int len;
if( input->curr_pos >= input->buffer_length - 1 ) {
return( FALSE );
}
/* if we are in overstrike more or at the end of the line... */
if( input->overstrike ) {
len = strlen( input->buffer ) + 1;
input->buffer[ input->curr_pos++ ] = ch;
if( input->curr_pos == len ) {
input->buffer[ input->curr_pos ] = 0;
}
} else {
if( strlen( input->buffer ) >= input->buffer_length - 1 ) {
return( FALSE );
}
ptr = &input->buffer[ input->curr_pos++ ];
memmove( ptr + 1, ptr, strlen( ptr ) + 1 );
*ptr = ch;
}
if( input->curr_pos >= input->left_column + input->window.width - 1 ) {
input->left_column += 1;
}
return( TRUE );
} /* insertChar */
static bool deleteChar( input_buffer *input, bool backwards )
{
char *ptr;
if( backwards ) {
if( input->curr_pos == 0 ) {
return( FALSE );
}
input->curr_pos -= 1;
if( input->curr_pos < input->left_column ) {
input->left_column -= 1;
}
}
ptr = &input->buffer[ input->curr_pos ];
memmove( ptr, ptr + 1, strlen( ptr + 1 ) + 1 );
return( TRUE );
} /* deleteChar */
static void displayLine( input_buffer *input )
{
char display[ MAX_STR ];
char *buffer, *dest;
unsigned length;
int cursor_pos;
if( EditFlags.NoInputWindow ) {
return;
}
assert( strlen( input->prompt ) < MAX_STR );
strcpy( display, input->prompt );
length = strlen( display );
dest = &display[ length ];
buffer = input->buffer + input->left_column;
while( *buffer && length < input->window.width ) {
*dest++ = *buffer++;
length += 1;
}
*dest = 0;
cursor_pos = input->curr_pos - input->left_column + 1;
cursor_pos += strlen( input->prompt );
#ifdef __WIN__
{
RECT rect;
char *ptr, *c;
int len, x;
HWND id;
id = (HWND) input->window.id;
MyHideCaret( id );
GetClientRect( id, &rect );
// BlankRectIndirect( input->window.id, input->window.style.background, &rect );
c = input->cache;
for( len = 0, ptr = input->buffer; *ptr; ptr++, len++ ) {
if( *c != *ptr ) {
break;
}
c++;
}
x = MyTextExtent( id, &input->window.style, input->cache, len );
WriteString( id, x, 0, &input->window.style, display + len );
rect.left = MyTextExtent( id, &input->window.style, display, strlen( display ) );
BlankRectIndirect( id, input->window.style.background, &rect );
MyShowCaret( id );
SetCursorOnLine( input->window.id, cursor_pos, display, &input->window.style );
}
#else
DisplayLineInWindowWithColor( input->window.id, input->window.line,
display, &input->window.style, 0 );
SetGenericWindowCursor( input->window.id, input->window.line, cursor_pos );
#endif
} /* displayLine */
static bool endColumn( input_buffer *input )
{
int width, left;
int column;
column = strlen( input->buffer );
width = input->window.width - strlen( input->prompt );
left = input->left_column;
if( column >= left + width || column < left ) {
left = column - width + 1;
if( left < 0 ) {
left = 0;
}
}
input->curr_pos = column;
input->left_column = left;
return( TRUE );
} /* endColumn */
static bool saveStr( input_buffer *input )
{
strcpy( input->last_str, input->buffer );
return( TRUE );
} /* saveStr */
static bool swapString( input_buffer *input )
{
char *tmp;
tmp = alloca( strlen( input->last_str ) + 1 );
strcpy( tmp, input->last_str );
strcpy( input->last_str, input->buffer );
strcpy( input->buffer, tmp );
endColumn( input );
return( TRUE );
} /* swapString */
static int cursorKeyFilter( input_buffer *input, int event )
{
int max_pos;
max_pos = strlen( input->buffer );
switch( event ) {
case HANDLED:
break;
case VI_KEY( HOME ):
input->curr_pos = 0;
input->left_column = 0;
break;
case VI_KEY( END ):
endColumn( input );
break;
case VI_KEY( RIGHT ):
if( input->curr_pos < max_pos ) {
input->curr_pos += 1;
if( input->curr_pos > input->left_column + input->window.width ) {
input->left_column += 1;
}
} else {
MyBeep();
}
break;
case VI_KEY( LEFT ):
if( input->curr_pos > 0 ) {
input->curr_pos -= 1;
if( input->left_column > input->curr_pos ) {
input->left_column = input->curr_pos;
}
}
break;
case VI_KEY( DEL ):
case VI_KEY( BS ):
saveStr( input );
if( !deleteChar( input, event == VI_KEY( BS )
|| input->curr_pos == max_pos ) ) {
MyBeep();
}
break;
default:
return( event );
}
return( HANDLED );
} /* cursorKeyFilter */
/*
* History functions:
* getHistory( input_buffer * ) - replace the input buffer with the
* currently selected history line (input->curr_hist).
* addHistory( input_buffer * ) - adds the current buffer to the
* history list associated with the input_buffer.
* searchHistory( input_buffer *, char *, int ) - starts searching
* at the specified index and returns the index of the first
* matching line in the history buffer or -1 if there are none.
* historyFilter( input_buffer *, int ) - pick out and take care of
* events which deal with the command line history.
*/
static bool getHistory( input_buffer *input )
{
int offset;
char *cmd;
offset = input->curr_hist % input->history->max;
cmd = input->history->data[ offset ];
if( cmd != NULL ) {
saveStr( input );
strcpy( input->buffer, cmd );
endColumn( input );
return( TRUE );
}
return( FALSE );
} /* getHistory */
static bool addHistory( input_buffer *input )
{
history_data *h;
h = input->history;
if( h != NULL && input->buffer[ 0 ] != 0 ) {
AddString2( &(h->data[ h->curr % h->max ] ), input->buffer );
h->curr += 1;
return( TRUE );
}
return( FALSE );
} /* addHistory */
static int searchHistory( input_buffer *input, char *str, int curr )
{
int index, i, len;
history_data *h;
h = input->history;
len = strlen( str );
for( i = 0; i < h->max; i++ ) {
curr -= 1;
if( curr < 0 || curr < h->curr - h->max ) {
curr = h->curr - 1;
}
index = curr % h->max;
if( !strnicmp( str, h->data[ index ], len ) ) {
strcpy( input->buffer, h->data[ index ] );
endColumn( input );
return( curr );
}
}
MyBeep();
return( -1 );
} /* searchHistory */
static void doHistorySearch( input_buffer *input )
{
int curr;
char *str;
int event;
curr = input->history->curr;
str = alloca( strlen( input->buffer ) + 1 );
strcpy( str, input->buffer );
event = VI_KEY( CTRL_TAB );
while( curr != -1 ) {
if( event == VI_KEY( ALT_TAB ) || event == VI_KEY( CTRL_TAB ) ) {
saveStr( input );
curr = searchHistory( input, str, curr );
displayLine( input );
event = GetNextEvent( TRUE );
continue;
}
KeyAdd( event );
return;
}
} /* doHistorySearch */
static int historyFilter( input_buffer *input, int event )
{
history_data *h;
if( input->history == NULL || input->history->curr == 0 ) {
return( event );
}
h = input->history;
switch( event ) {
case VI_KEY( UP ):
input->curr_hist -= 1;
if( input->curr_hist < 0 || input->curr_hist < h->curr - h->max ) {
input->curr_hist = h->curr - 1;
}
getHistory( input );
break;
case VI_KEY( DOWN ):
input->curr_hist += 1;
if( input->curr_hist >= h->curr ) {
input->curr_hist = h->curr - h->max;
if( input->curr_hist < 0 ) {
input->curr_hist = 0;
}
}
getHistory( input );
break;
case VI_KEY( CTRL_TAB ):
case VI_KEY( ALT_TAB ):
doHistorySearch( input );
break;
default:
return( event );
}
return( HANDLED );
} /* historyFilter */
/*
* Special key (ALT_L etc... ) functions:
* insertString( input_buffer *, char * ) - insert the given string at
* the current location and bump the current position.
* specialKeyFilter( input_buffer *, int ) - pick out and handle any
* events which map to special keys.
*/
static bool insertString( input_buffer *input, char *str )
{
while( *str ) {
if( !insertChar( input, *str++ ) ) {
return( FALSE );
}
}
return( TRUE );
} /* insertString */
/*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?