Refactor getstring to be more robust when doing filename completion with Unicode characters.

This commit is contained in:
Renaud 2019-08-07 16:51:00 +08:00
parent 8c1a8f16bf
commit 3e12643077
3 changed files with 118 additions and 134 deletions

View File

@ -1557,8 +1557,10 @@ static int newscreensize(int h, int w)
* char c ; character to output * char c ; character to output
*/ */
void echoc( unicode_t c) { void echoc( unicode_t c) {
if( disinp) if( disinp) {
TTputc( c) ; TTputc( c) ;
ttcol += 1 ;
}
} }
/* /*
@ -1567,10 +1569,22 @@ void echoc( unicode_t c) {
* char *s; string to output * char *s; string to output
*/ */
void echos( char *s) { void echos( char *s) {
char c ;
if( disinp) if( disinp)
while( *s) while( (c = *s++)) {
TTputc( *s++) ; TTputc( c) ;
ttcol += 1 ;
}
} }
void rubout( void) {
if( disinp) {
TTputc( '\b') ;
TTputc( ' ') ;
TTputc( '\b') ;
ttcol -= 1 ;
}
}
/* end of display.c */ /* end of display.c */

View File

@ -31,6 +31,7 @@ void mlwrite( const char *fmt, ...) ;
void ostring( char *s) ; void ostring( char *s) ;
void echoc( unicode_t c) ; void echoc( unicode_t c) ;
void echos( char *s) ; void echos( char *s) ;
void rubout( void) ;
void getscreensize( int *widthp, int *heightp) ; void getscreensize( int *widthp, int *heightp) ;
#if UNIX #if UNIX

231
input.c
View File

@ -48,8 +48,6 @@ int abortc = CONTROL | 'G' ; /* current abort command char */
const int nlc = CONTROL | 'J' ; /* end of input char */ const int nlc = CONTROL | 'J' ; /* end of input char */
static const int quotec = 0x11 ; /* quote char during getstring() */
void ue_system( const char *cmd) { void ue_system( const char *cmd) {
int ret ; int ret ;
@ -201,17 +199,15 @@ fn_t getname(void)
} else if (c == 0x7F || c == 0x08) { /* rubout/erase */ } else if (c == 0x7F || c == 0x08) { /* rubout/erase */
if (cpos != 0) { if (cpos != 0) {
echos( "\b \b") ; rubout() ;
--ttcol;
--cpos; --cpos;
TTflush(); TTflush();
} }
} else if (c == 0x15) { /* C-U, kill */ } else if (c == 0x15) { /* C-U, kill */
while (cpos != 0) { while (cpos != 0) {
echos( "\b \b") ; rubout() ;
--cpos; --cpos;
--ttcol;
} }
TTflush(); TTflush();
@ -291,10 +287,8 @@ fn_t getname(void)
if (cpos < NSTRING - 1 && c > ' ') { if (cpos < NSTRING - 1 && c > ' ') {
buf[cpos++] = c; buf[cpos++] = c;
echoc( c) ; echoc( c) ;
TTflush();
} }
++ttcol;
TTflush();
} }
} }
} }
@ -508,14 +502,42 @@ handle_CSI:
/* A more generalized prompt/reply function allowing the caller /* A more generalized prompt/reply function allowing the caller
to specify the proper terminator. If the terminator is not to specify the proper terminator. If the terminator is not
a return ('\n') it will echo as "<NL>" a return ('\n') it will echo as "<NL>"
*/ */
static void echov( int c) {
/* verbose echo of a character */
if( c == '\n') /* put out <NL> for <ret> */
echos( "<NL>") ;
else {
if( c < ' ') {
echoc( '^') ;
c ^= 0x40 ;
}
echoc( c) ;
}
}
static void rubc( char c) {
rubout() ;
if( c < ' ') {
rubout() ;
if( c == '\n') {
rubout() ;
rubout() ;
}
}
}
int getstring( const char *prompt, char *buf, int nbuf, int eolchar) int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
{ {
int cpos; /* current character position in string */ int cpos; /* current character position in string */
int c; int c;
boolean quotef ; /* are we quoting the next char? */ boolean quote_f ; /* are we quoting the next char? */
int retval ; /* TRUE, FALSE, ABORT */
#if COMPLC #if COMPLC
int ffile, ocpos, nskip = 0, didtry = 0; boolean file_f ;
int ocpos, nskip = 0, didtry = 0;
#if MSDOS #if MSDOS
struct ffblk ffblk; struct ffblk ffblk;
char *fcp; char *fcp;
@ -526,11 +548,11 @@ int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
#endif #endif
/* Look for "Find file: ", "View file: ", "Insert file: ", "Write file: ", /* Look for "Find file: ", "View file: ", "Insert file: ", "Write file: ",
** "Read file: ", "Execute file: " */ ** "Read file: ", "Execute file: " */
ffile = NULL != strstr( prompt, " file: ") ; file_f = NULL != strstr( prompt, " file: ") ;
#endif #endif
cpos = 0; cpos = 0;
quotef = FALSE; quote_f = FALSE;
/* prompt the user for the input string */ /* prompt the user for the input string */
mlwrite( "%s", prompt); mlwrite( "%s", prompt);
@ -541,89 +563,62 @@ int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
nskip = -1; nskip = -1;
didtry = 0; didtry = 0;
#endif #endif
/* get a character from the user */ /* get a character from the user */
c = get1key(); c = get1key();
/* If it is a <ret>, change it to a <NL> */ /* Quoting? Store as it is */
#if PKCODE if( quote_f == TRUE) {
if (c == (CONTROL | 0x4d) && !quotef) quote_f = FALSE ;
#else if( cpos < nbuf - 1) {
if (c == (CONTROL | 0x4d)) c = ectoc( c) ;
#endif buf[ cpos++] = c ;
c = CONTROL | 0x40 | '\n'; echov( c) ;
TTflush() ;
}
/* if they hit the line terminate, wrap it up */ continue ;
if (c == eolchar && quotef == FALSE) { }
buf[cpos++] = 0;
/* clear the message line */ /* If it is a <ret>, change it to a <NL> */
if( c == (CONTROL | 'M'))
c = CONTROL | 0x40 | '\n' ;
if( c == eolchar) {
/* if they hit the line terminator, wrap it up */
buf[ cpos] = 0 ;
/* clear the message line */
mlwrite(""); mlwrite("");
TTflush();
if( tmpf != NULL) { /* if we default the buffer, return FALSE */
fclose( tmpf) ; retval = cpos != 0 ;
unlink( tmp) ; break ;
} } else if( c == abortc) {
/* Abort the input? */
ctrlg( FALSE, 0) ;
retval = ABORT ;
break ;
}
/* if we default the buffer, return FALSE */ /* change from command form back to character form */
if (buf[0] == 0) c = ectoc( c) ;
return FALSE;
return TRUE; if( c == 0x7F || c == 0x08) {
} /* rubout/erase */
/* change from command form back to character form */
c = ectoc(c);
if (c == ectoc(abortc) && quotef == FALSE) {
/* Abort the input? */
ctrlg(FALSE, 0);
TTflush();
if( tmpf != NULL) {
fclose( tmpf) ;
unlink( tmp) ;
}
return ABORT;
} else if ((c == 0x7F || c == 0x08) && quotef == FALSE) {
/* rubout/erase */
if (cpos != 0) { if (cpos != 0) {
echos("\b \b"); rubc( buf[ --cpos]) ;
--ttcol;
if (buf[--cpos] < 0x20) {
echos("\b \b");
--ttcol;
}
if (buf[cpos] == '\n') {
echos("\b\b \b\b");
ttcol -= 2;
}
TTflush(); TTflush();
} }
} else if( c == 0x15) {
/* C-U, kill */
while (cpos != 0)
rubc( buf[ --cpos]) ;
} else if (c == 0x15 && quotef == FALSE) {
/* C-U, kill */
while (cpos != 0) {
echos("\b \b");
--ttcol;
if (buf[--cpos] < 0x20) {
echos("\b \b");
--ttcol;
}
if (buf[cpos] == '\n') {
echos("\b\b \b\b");
ttcol -= 2;
}
}
TTflush(); TTflush();
#if COMPLC #if COMPLC
} else if ((c == 0x09 || c == ' ') && quotef == FALSE } else if( (c == 0x09 || c == ' ') && file_f) {
&& ffile) { /* TAB, complete file name */
/* TAB, complete file name */
char ffbuf[255]; char ffbuf[255];
#if MSDOS #if MSDOS
char sffbuf[128]; char sffbuf[128];
@ -634,17 +629,7 @@ int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
didtry = 1; didtry = 1;
ocpos = cpos; ocpos = cpos;
while (cpos != 0) { while (cpos != 0) {
echos("\b \b"); rubc( buf[ --cpos]) ;
--ttcol;
if (buf[--cpos] < 0x20) {
echos("\b \b");
--ttcol;
}
if (buf[cpos] == '\n') {
echos("\b\b \b\b");
ttcol -= 2;
}
if (buf[cpos] == '*' || buf[cpos] == '?') if (buf[cpos] == '*' || buf[cpos] == '?')
iswild = 1; iswild = 1;
#if MSDOS #if MSDOS
@ -726,50 +711,34 @@ int getstring( const char *prompt, char *buf, int nbuf, int eolchar)
TTbeep(); TTbeep();
#endif #endif
for (n = 0; n < cpos; n++) { for( n = 0 ; n < cpos ; n++) {
c = buf[n]; c = buf[ n] & 0xFF ; /* NEED better Unicode handling */
if ((c < ' ') && (c != '\n')) { echov( c) ;
echoc( '^') ;
++ttcol;
c ^= 0x40;
}
if( c != '\n')
echoc( c) ;
else { /* put out <NL> for <ret> */
echos("<NL>");
ttcol += 3;
}
++ttcol;
} }
TTflush();
TTflush() ;
#if UNIX #if UNIX
rewind(tmpf); rewind(tmpf);
#endif #endif
#endif #endif
} else if ((c == quotec || c == 0x16) && quotef == FALSE) { } else if( c == 0x11 || c == 0x16)
quotef = TRUE; /* ^Q or ^V */
} else { quote_f = TRUE ;
quotef = FALSE; else
if (cpos < nbuf - 1) { /* store as it is */
buf[cpos++] = c; if( cpos < nbuf - 1) {
buf[ cpos++] = c ;
if ((c < ' ') && (c != '\n')) { echov( c) ;
echoc( '^') ; TTflush() ;
++ttcol;
c ^= 0x40;
}
if( c != '\n')
echoc( c) ;
else { /* put out <NL> for <ret> */
echos("<NL>");
ttcol += 3;
}
++ttcol;
TTflush();
} }
}
} }
TTflush() ;
if( tmpf != NULL) {
fclose( tmpf) ;
unlink( tmp) ;
}
return retval ;
} }