1
0
mirror of https://github.com/rfivet/uemacs.git synced 2025-01-21 15:46:23 -05:00

Consistent interface to deal with workaround on Cygwin when checking width of unicode character > 0xFFFF.

This commit is contained in:
Renaud 2021-08-15 09:41:35 +08:00
parent 3bce7a4751
commit 109e330861
5 changed files with 174 additions and 207 deletions

View File

@ -44,10 +44,8 @@ static unsigned getgoal( line_p dlp) {
col += 2 ; col += 2 ;
else if( c >= 0x80 && c <= 0xA0) /* \xx */ else if( c >= 0x80 && c <= 0xA0) /* \xx */
col += 3 ; col += 3 ;
else { else
int w = utf8_width( c) ; /* work around */ col += utf8_width( c) ;
col += (w < 0) ? 2 : w ; /* unknown unicode width as \u */
}
if( col > curgoal) if( col > curgoal)
break ; break ;

220
display.c
View File

@ -12,7 +12,6 @@
*/ */
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -28,16 +27,16 @@
#include "utf8.h" #include "utf8.h"
#include "window.h" #include "window.h"
struct video { typedef struct {
int v_flag ; /* Flags */ int v_flag ; /* Flags */
#if COLOR #if COLOR
int v_fcolor; /* current forground color */ int v_fcolor ; /* current foreground color */
int v_bcolor ; /* current background color */ int v_bcolor ; /* current background color */
int v_rfcolor; /* requested forground color */ int v_rfcolor ; /* requested foreground color */
int v_rbcolor ; /* requested background color */ int v_rbcolor ; /* requested background color */
#endif #endif
unicode_t v_text[] ; /* Screen data. */ unicode_t v_text[] ; /* Screen data. */
}; } *video_p ;
#define VFCHG 0x0001 /* Changed flag */ #define VFCHG 0x0001 /* Changed flag */
#define VFEXT 0x0002 /* extended (beyond column 80) */ #define VFEXT 0x0002 /* extended (beyond column 80) */
@ -45,15 +44,16 @@ struct video {
#define VFREQ 0x0008 /* reverse video request */ #define VFREQ 0x0008 /* reverse video request */
#define VFCOL 0x0010 /* color change requested */ #define VFCOL 0x0010 /* color change requested */
static struct video **vscreen; /* Virtual screen. */ static video_p *vscreen ; /* Virtual screen. */
#if MEMMAP == 0 || SCROLLCODE #if MEMMAP == 0 || SCROLLCODE
static struct video **pscreen; /* Physical screen. */ static video_p *pscreen ; /* Physical screen. */
#endif #endif
static int displaying = TRUE; static int displaying = TRUE;
#if UNIX #if UNIX
# include <signal.h> # include <signal.h>
#endif #endif
#ifdef SIGWINCH #ifdef SIGWINCH
# include <sys/ioctl.h> # include <sys/ioctl.h>
/* for window size changes */ /* for window size changes */
@ -73,16 +73,16 @@ int discmd = TRUE ; /* display command flag */
int disinp = TRUE ; /* display input characters (echo) */ int disinp = TRUE ; /* display input characters (echo) */
static int reframe(struct window *wp); static int reframe( window_p wp) ;
static void updone(struct window *wp); static void updone( window_p wp) ;
static void updall(struct window *wp); static void updall( window_p wp) ;
static int scrolls(int inserts); static int scrolls(int inserts);
static void scrscroll(int from, int to, int count); static void scrscroll(int from, int to, int count);
static int texttest(int vrow, int prow); static int texttest(int vrow, int prow);
static int endofline(unicode_t *s, int n); static int endofline(unicode_t *s, int n);
static void updext(void); static void updext(void);
static int updateline(int row, struct video *vp1, struct video *vp2); static int updateline(int row, video_p vp1, video_p vp2);
static void modeline(struct window *wp); static void modeline( window_p wp) ;
static void mlputi(int i, int r); static void mlputi(int i, int r);
static void mlputli(long l, int r); static void mlputli(long l, int r);
static void mlputf(int s); static void mlputf(int s);
@ -91,28 +91,24 @@ static void mlputs( const char *s) ;
static int newscreensize(int h, int w); static int newscreensize(int h, int w);
#endif #endif
/*
* Initialize the data structures used by the display code. The edge vectors
* used to access the screens are set up. The operating system's terminal I/O
* channel is set up. All the other things get initialized at compile time.
* The original window has "WFCHG" set, so that it will get completely
* redrawn on the first call to "update".
*/
void vtinit(void)
{
int i;
struct video *vp;
/* Initialize the data structures used by the display code. The edge
vectors used to access the screens are set up. The operating system's
terminal I/O channel is set up. All the other things get initialized at
compile time. The original window has "WFCHG" set, so that it will get
completely redrawn on the first call to "update".
*/
void vtinit( void) {
TTopen() ; /* open the screen */ TTopen() ; /* open the screen */
TTkopen() ; /* open the keyboard */ TTkopen() ; /* open the keyboard */
TTrev(FALSE) ; TTrev(FALSE) ;
vscreen = xmalloc( term.t_maxrow * sizeof( struct video *)) ; vscreen = xmalloc( term.t_maxrow * sizeof( video_p )) ;
#if MEMMAP == 0 || SCROLLCODE #if MEMMAP == 0 || SCROLLCODE
pscreen = xmalloc( term.t_maxrow * sizeof( struct video *)) ; pscreen = xmalloc( term.t_maxrow * sizeof( video_p )) ;
#endif #endif
for( i = 0 ; i < term.t_maxrow ; ++i) { for( int i = 0 ; i < term.t_maxrow ; ++i) {
vp = xmalloc( sizeof( struct video) + term.t_maxcol * sizeof( unicode_t)) ; video_p vp = xmalloc( sizeof *vp + term.t_maxcol * sizeof( unicode_t)) ;
vp->v_flag = 0 ; vp->v_flag = 0 ;
#if COLOR #if COLOR
vp->v_rfcolor = 7 ; vp->v_rfcolor = 7 ;
@ -120,7 +116,7 @@ void vtinit(void)
#endif #endif
vscreen[ i] = vp ; vscreen[ i] = vp ;
#if MEMMAP == 0 || SCROLLCODE #if MEMMAP == 0 || SCROLLCODE
vp = xmalloc( sizeof( struct video) + term.t_maxcol * sizeof( unicode_t)) ; vp = xmalloc( sizeof *vp + term.t_maxcol * sizeof( unicode_t)) ;
vp->v_flag = 0 ; vp->v_flag = 0 ;
pscreen[ i] = vp ; pscreen[ i] = vp ;
#endif #endif
@ -129,16 +125,14 @@ void vtinit(void)
#if CLEAN #if CLEAN
/* free up all the dynamically allocated video structures */ /* free up all the dynamically allocated video structures */
void vtfree( void) {
void vtfree(void) for( int i = 0 ; i < term.t_maxrow; ++i ) {
{
int i;
for( i = 0 ; i < term.t_maxrow; ++i ) {
free( vscreen[ i]) ; free( vscreen[ i]) ;
#if MEMMAP == 0 || SCROLLCODE #if MEMMAP == 0 || SCROLLCODE
free( pscreen[ i]) ; free( pscreen[ i]) ;
#endif #endif
} }
free( vscreen) ; free( vscreen) ;
#if MEMMAP == 0 || SCROLLCODE #if MEMMAP == 0 || SCROLLCODE
free( pscreen) ; free( pscreen) ;
@ -146,45 +140,41 @@ void vtfree(void)
} }
#endif #endif
/*
* Clean up the virtual terminal system, in anticipation for a return to the /* Clean up the virtual terminal system, in anticipation for a return to
* operating system. Move down to the last line and clear it out (the next the operating system. Move down to the last line and clear it out (the
* system prompt will be written in the line). Shut down the channel to the next system prompt will be written in the line). Shut down the channel
* terminal. to the terminal.
*/ */
void vttidy(void) void vttidy( void) {
{
mlerase() ; /* ends with movecursor( term.t_nrow, 0) and TTflush() */ mlerase() ; /* ends with movecursor( term.t_nrow, 0) and TTflush() */
TTclose() ; TTclose() ;
TTkclose() ; TTkclose() ;
#ifdef PKCODE #ifdef PKCODE
{ int ret = write( 1, "\r", 1) ;
int ret ;
ret = write( 1, "\r", 1) ;
if( ret != 1) { if( ret != 1) {
/* some error handling here */ /* some error handling here */
} }
}
#endif #endif
} }
/*
* Set the virtual cursor to the specified row and column on the virtual /* Set the virtual cursor to the specified row and column on the virtual
* screen. There is no checking for nonsense values; this might be a good screen. There is no checking for nonsense values; this might be a good
* idea during the early stages. idea during the early stages.
*/ */
static void vtmove( int row, int col) { static void vtmove( int row, int col) {
vtrow = row ; vtrow = row ;
vtcol = col ; vtcol = col ;
} }
/*
* Write a character to the virtual screen. The virtual row and /* Write a character to the virtual screen. The virtual row and column are
* column are updated. If we are not yet on left edge, don't print updated. If we are not yet on left edge, don't print it yet. If the
* it yet. If the line is too long put a "$" in the last column. line is too long put a "$" in the last column.
*
* This routine only puts printing characters into the virtual This routine only puts printing characters into the virtual terminal
* terminal buffers. Only column overflow is checked. buffers. Only column overflow is checked.
*/ */
static void sane_vtputc( unicode_t c) { static void sane_vtputc( unicode_t c) {
@ -216,7 +206,7 @@ static void vtputc( unicode_t c) {
sane_vtputc( '\\') ; sane_vtputc( '\\') ;
sane_vtputc( hex[ c >> 4]) ; sane_vtputc( hex[ c >> 4]) ;
sane_vtputc( hex[ c & 15]) ; sane_vtputc( hex[ c & 15]) ;
} else if( utf8_width( c) < 0) { } else if( _utf8_width( c) < 0) {
sane_vtputc( '\\') ; /* show as non printable */ sane_vtputc( '\\') ; /* show as non printable */
sane_vtputc( 'u') ; sane_vtputc( 'u') ;
} else } else
@ -231,7 +221,7 @@ static int vtputs( const char *s) {
s += utf8_to_unicode( s, 0, 4, &c) ; s += utf8_to_unicode( s, 0, 4, &c) ;
vtputc( c) ; vtputc( c) ;
n += utf8_width( c) ; /* To Do: only works if all printable */ n += utf8_width( c) ;
} }
return n ; return n ;
@ -271,8 +261,6 @@ static int scrflags;
boolean force_f ; force update past type ahead? boolean force_f ; force update past type ahead?
*/ */
int update( boolean force_f) { int update( boolean force_f) {
struct window *wp;
#if TYPEAH && ! PKCODE #if TYPEAH && ! PKCODE
if( force_f == FALSE && typahead()) if( force_f == FALSE && typahead())
return TRUE; return TRUE;
@ -286,37 +274,26 @@ int update( boolean force_f) {
#if SCROLLCODE #if SCROLLCODE
/* first, propagate mode line changes to all instances of /* first, propagate mode line changes to all instances of a buffer displayed
a buffer displayed in more than one window */ * in more than one window */
wp = wheadp; window_p wp ;
while (wp != NULL) { for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp)
if (wp->w_flag & WFMODE) { if( wp->w_flag & WFMODE
if (wp->w_bufp->b_nwnd > 1) { && wp->w_bufp->b_nwnd > 1)
/* make sure all previous windows have this */ /* make sure all previous windows have this */
struct window *owp; for( window_p owp = wheadp ; owp != NULL ; owp = owp->w_wndp)
owp = wheadp;
while (owp != NULL) {
if( owp->w_bufp == wp->w_bufp) if( owp->w_bufp == wp->w_bufp)
owp->w_flag |= WFMODE ; owp->w_flag |= WFMODE ;
owp = owp->w_wndp;
}
}
}
wp = wp->w_wndp;
}
#endif #endif
/* update any windows that need refreshing */ /* update any windows that need refreshing */
wp = wheadp; for( wp = wheadp ; wp != NULL ; wp = wp->w_wndp)
while (wp != NULL) {
if( wp->w_flag) { if( wp->w_flag) {
/* if the window has changed, service it */ /* if the window has changed, service it */
reframe( wp) ; /* check the framing */ reframe( wp) ; /* check the framing */
#if SCROLLCODE #if SCROLLCODE
if( wp->w_flag & (WFKILLS | WFINS)) { if( wp->w_flag & (WFKILLS | WFINS)) {
scrflags |= scrflags |= wp->w_flag & (WFINS | WFKILLS) ;
(wp->w_flag & (WFINS | WFKILLS));
wp->w_flag &= ~(WFKILLS | WFINS) ; wp->w_flag &= ~(WFKILLS | WFINS) ;
} }
#endif #endif
@ -333,9 +310,6 @@ int update( boolean force_f) {
wp->w_flag = 0 ; wp->w_flag = 0 ;
wp->w_force = 0 ; wp->w_force = 0 ;
} }
/* on to the next window */
wp = wp->w_wndp;
}
/* recalc the current hardware cursor location */ /* recalc the current hardware cursor location */
updpos() ; updpos() ;
@ -371,9 +345,8 @@ int update( boolean force_f) {
* check to see if the cursor is on in the window * check to see if the cursor is on in the window
* and re-frame it if needed or wanted * and re-frame it if needed or wanted
*/ */
static int reframe(struct window *wp) static int reframe( window_p wp) {
{ line_p lp, lp0 ;
struct line *lp, *lp0;
int i = 0; int i = 0;
/* if not a requested reframe, check for a needed one */ /* if not a requested reframe, check for a needed one */
@ -455,7 +428,7 @@ static int reframe(struct window *wp)
return TRUE; return TRUE;
} }
static void show_line(struct line *lp) static void show_line( line_p lp)
{ {
int i = 0, len = llength(lp); int i = 0, len = llength(lp);
@ -470,11 +443,11 @@ static void show_line(struct line *lp)
* updone: * updone:
* update the current line to the virtual screen * update the current line to the virtual screen
* *
* struct window *wp; window to update current line in * window_p wp; window to update current line in
*/ */
static void updone(struct window *wp) static void updone(window_p wp)
{ {
struct line *lp; /* line to update */ line_p lp; /* line to update */
int sline; /* physical screen line to update */ int sline; /* physical screen line to update */
/* search down the line we want */ /* search down the line we want */
@ -501,11 +474,11 @@ static void updone(struct window *wp)
* updall: * updall:
* update all the lines in a window on the virtual screen * update all the lines in a window on the virtual screen
* *
* struct window *wp; window to update lines in * window_p wp; window to update lines in
*/ */
static void updall(struct window *wp) static void updall(window_p wp)
{ {
struct line *lp; /* line to update */ line_p lp; /* line to update */
int sline; /* physical screen line to update */ int sline; /* physical screen line to update */
/* search down the lines, updating them */ /* search down the lines, updating them */
@ -534,18 +507,14 @@ static void updall(struct window *wp)
} }
/*
* updpos:
* update the position of the hardware cursor and handle extended
* lines. This is the only update for simple moves.
*/
void updpos(void)
{
struct line *lp;
int i;
/* updpos:
update the position of the hardware cursor and handle extended lines.
This is the only update for simple moves.
*/
void updpos(void) {
/* find the current row */ /* find the current row */
lp = curwp->w_linep; line_p lp = curwp->w_linep ;
currow = curwp->w_toprow ; currow = curwp->w_toprow ;
while( lp != curwp->w_dotp) { while( lp != curwp->w_dotp) {
++currow ; ++currow ;
@ -554,7 +523,7 @@ void updpos(void)
/* find the current column */ /* find the current column */
curcol = 0; curcol = 0;
i = 0; int i = 0 ;
while( i < curwp->w_doto) { while( i < curwp->w_doto) {
unicode_t c ; unicode_t c ;
@ -565,10 +534,8 @@ void updpos(void)
curcol += 2 ; /* displayed as ^c */ curcol += 2 ; /* displayed as ^c */
else if( c >= 0x80 && c <= 0xA0) else if( c >= 0x80 && c <= 0xA0)
curcol += 3 ; /* displayed as \xx */ curcol += 3 ; /* displayed as \xx */
else { else
int width = utf8_width( c) ; curcol += utf8_width( c) ; /* non printable are displayed as \u */
curcol += (width < 0) ? 2 : width ; /* non printable are displayed as \u */
}
} }
/* if extended, flag so and update the virtual line image */ /* if extended, flag so and update the virtual line image */
@ -585,8 +552,8 @@ void updpos(void)
*/ */
void upddex(void) void upddex(void)
{ {
struct window *wp; window_p wp;
struct line *lp; line_p lp;
int i; int i;
wp = wheadp; wp = wheadp;
@ -659,7 +626,7 @@ void updgar(void)
*/ */
int updupd(int force) int updupd(int force)
{ {
struct video *vp1; video_p vp1;
int i; int i;
#if SCROLLCODE #if SCROLLCODE
@ -697,8 +664,8 @@ int updupd(int force)
*/ */
static int scrolls(int inserts) static int scrolls(int inserts)
{ /* returns true if it does something */ { /* returns true if it does something */
struct video *vpv; /* virtual screen image */ video_p vpv; /* virtual screen image */
struct video *vpp; /* physical screen image */ video_p vpp; /* physical screen image */
int i, j, k; int i, j, k;
int rows, cols; int rows, cols;
int first, match, count, target, end; int first, match, count, target, end;
@ -834,8 +801,8 @@ static void scrscroll(int from, int to, int count)
*/ */
static int texttest(int vrow, int prow) static int texttest(int vrow, int prow)
{ {
struct video *vpv = vscreen[vrow]; /* virtual screen image */ video_p vpv = vscreen[vrow]; /* virtual screen image */
struct video *vpp = pscreen[prow]; /* physical screen image */ video_p vpp = pscreen[prow]; /* physical screen image */
return !memcmp(vpv->v_text, vpp->v_text, 4*term.t_ncol); return !memcmp(vpv->v_text, vpp->v_text, 4*term.t_ncol);
} }
@ -864,7 +831,7 @@ static int endofline(unicode_t *s, int n)
static void updext(void) static void updext(void)
{ {
int rcursor; /* real cursor location */ int rcursor; /* real cursor location */
struct line *lp; /* pointer to current line */ line_p lp; /* pointer to current line */
/* calculate what column the real cursor will end up in */ /* calculate what column the real cursor will end up in */
rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin; rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
@ -892,7 +859,7 @@ static void updext(void)
#if MEMMAP #if MEMMAP
/* UPDATELINE specific code for the IBM-PC and other compatables */ /* UPDATELINE specific code for the IBM-PC and other compatables */
static int updateline(int row, struct video *vp1, struct video *vp2) static int updateline(int row, video_p vp1, video_p vp2)
{ {
#if SCROLLCODE #if SCROLLCODE
unicode_t *cp1; unicode_t *cp1;
@ -925,15 +892,13 @@ static int updateline(int row, struct video *vp1, struct video *vp2)
#else #else
/* /* updateline()
* updateline()
* *
* int row ; row of screen to update * int row ; row of screen to update
* struct video *vp1; virtual screen image * video_p vp1 ; virtual screen image
* struct video *vp2; physical screen image * video_p vp2 ; physical screen image
*/ */
static int updateline(int row, struct video *vp1, struct video *vp2) static int updateline(int row, video_p vp1, video_p vp2) {
{
/* UPDATELINE code for all other versions */ /* UPDATELINE code for all other versions */
unicode_t *cp1; unicode_t *cp1;
@ -1069,10 +1034,9 @@ static int updateline(int row, struct video *vp1, struct video *vp2)
* change the modeline format by hacking at this routine. Called by "update" * change the modeline format by hacking at this routine. Called by "update"
* any time there is a dirty window. * any time there is a dirty window.
*/ */
static void modeline(struct window *wp) static void modeline( window_p wp) {
{
int n; /* cursor position count */ int n; /* cursor position count */
struct buffer *bp; buffer_p bp ;
int i; /* loop index */ int i; /* loop index */
int lchar; /* character to draw line in buffer with */ int lchar; /* character to draw line in buffer with */
int firstm; /* is this the first mode? */ int firstm; /* is this the first mode? */
@ -1148,7 +1112,7 @@ static void modeline(struct window *wp)
} }
{ /* determine if top line, bottom line, or both are visible */ { /* determine if top line, bottom line, or both are visible */
struct line *lp = wp->w_linep; line_p lp = wp->w_linep;
int rows = wp->w_ntrows; int rows = wp->w_ntrows;
char *msg = NULL; char *msg = NULL;
char tline[ 6] ; /* buffer for part of mode line */ char tline[ 6] ; /* buffer for part of mode line */
@ -1172,7 +1136,7 @@ static void modeline(struct window *wp)
} }
} }
if (!msg) { if (!msg) {
struct line *lp; line_p lp;
int numlines, predlines ; int numlines, predlines ;
lp = lforw(bp->b_linep); lp = lforw(bp->b_linep);
@ -1215,7 +1179,7 @@ static void modeline(struct window *wp)
void upmode(void) void upmode(void)
{ /* update all the mode lines */ { /* update all the mode lines */
struct window *wp; window_p wp;
wp = wheadp; wp = wheadp;
while (wp != NULL) { while (wp != NULL) {

View File

@ -164,8 +164,7 @@ int getccol( int bflg) {
else if (c >= 0x80 && c <= 0xa0) /* displayed as \xx */ else if (c >= 0x80 && c <= 0xa0) /* displayed as \xx */
col += 3 ; col += 3 ;
else { else {
int w = utf8_width( c) ; /* incomplete wc_width */ col += utf8_width( c) ;
col += (w < 0) ? 2 : w ;
} }
} }

21
utf8.c
View File

@ -7,10 +7,9 @@
#include <assert.h> #include <assert.h>
#include <wchar.h> #include <wchar.h>
/*
* Display width of UTF-8 character /* Display width of UTF-8 character */
*/ int _utf8_width( unicode_t c) {
int utf8_width( unicode_t c) {
#if CYGWIN #if CYGWIN
assert( sizeof( wchar_t) == 2) ; /* wcwidth only supports UTF-16 */ assert( sizeof( wchar_t) == 2) ; /* wcwidth only supports UTF-16 */
return (c < 0x10000) ? wcwidth( (wchar_t) c) : -1 ; return (c < 0x10000) ? wcwidth( (wchar_t) c) : -1 ;
@ -19,8 +18,14 @@ int utf8_width( unicode_t c) {
#endif #endif
} }
/*
* utf8_to_unicode() int utf8_width( unicode_t c) {
int w = _utf8_width( c) ;
return (w < 0) ? 2 : w ; /* display \u if can't figure out width */
}
/* utf8_to_unicode()
* *
* Convert a UTF-8 sequence to its unicode value, and return the length of * Convert a UTF-8 sequence to its unicode value, and return the length of
* the sequence in bytes. * the sequence in bytes.
@ -84,8 +89,8 @@ unsigned utf8_to_unicode( const char *line, unsigned index, unsigned len,
return bytes; return bytes;
} }
/*
* unicode_to_utf8() /* unicode_to_utf8()
* *
* Convert a unicode value to its canonical utf-8 sequence. * Convert a unicode value to its canonical utf-8 sequence.
* *

3
utf8.h
View File

@ -4,7 +4,8 @@
typedef unsigned int unicode_t ; typedef unsigned int unicode_t ;
int utf8_width( unicode_t c) ; int _utf8_width( unicode_t c) ; /* straight width */
int utf8_width( unicode_t c) ; /* workaround width */
unsigned utf8_to_unicode( const char *line, unsigned index, unsigned len, unsigned utf8_to_unicode( const char *line, unsigned index, unsigned len,
unicode_t *res) ; unicode_t *res) ;
unsigned utf8_revdelta( unsigned char *buf, unsigned pos) ; unsigned utf8_revdelta( unsigned char *buf, unsigned pos) ;