47
47
#include <string.h>
48
48
#include <unistd.h> //for read and write
49
49
#include <errno.h>
50
+ #include <wchar.h>
50
51
51
52
#include "reb-c.h"
52
53
@@ -87,7 +88,7 @@ static const char trailingBytesForUTF8[256] = {
87
88
#define CHAR_LEN (c ) (1 + trailingBytesForUTF8[c])
88
89
89
90
#define STEP_FORWARD (term ) term->pos += 1 + trailingBytesForUTF8[term->buffer[term->pos]];
90
- #define STEP_BACKWARD (term ) do {--term->pos;} while ((term->buffer[term->pos] & 0xC0) == 0x80);
91
+ #define STEP_BACKWARD (term ) while ((term->buffer[-- term->pos] & 0xC0) == 0x80);
91
92
// Stepping backwards in UTF8 just means to keep going back so long
92
93
// as you are looking at a byte with bit 7 set and bit 6 clear:
93
94
// https://stackoverflow.com/a/22257843/211160
@@ -190,24 +191,41 @@ static struct termios Term_Attrs; // Initial settings, restored on exit
190
191
Term_Init = FALSE;
191
192
}
192
193
193
-
194
194
/***********************************************************************
195
195
**
196
- */ static int Get_UTF8_Chars (unsigned char * buffer , int byte_count )
196
+ */ static int Get_UTF8_Chars (unsigned char * buffer , int byte_count )
197
197
/*
198
- ** Count number of characters (not bytes) of a UTF-8 string.
198
+ ** Count number of character's columns of a UTF-8 string.
199
199
** Used to count number of BS chars needed to clear the line,
200
200
** or set cursor position
201
201
** Note: does not checks char's validity
202
202
**
203
203
***********************************************************************/
204
204
{
205
- int i , char_count = 0 ;
206
- for (i = 0 ; i < byte_count ; i ++ )
207
- if ((buffer [i ] & 0xC0 ) != 0x80 )
208
- char_count ++ ;
209
-
210
- return char_count ;
205
+ wchar_t wideChar = 0 ;
206
+ int n , width_count = 0 ;
207
+
208
+ while (byte_count > 0 ) {
209
+ n = mbtowc (& wideChar , buffer , byte_count );
210
+ if (n <= 0 ) break ;
211
+ buffer += n ;
212
+ byte_count -= n ;
213
+ width_count += wcwidth (wideChar );
214
+ }
215
+ return width_count ;
216
+ }
217
+
218
+ /***********************************************************************
219
+ **
220
+ */ static int Get_Char_Width (REBYTE * buffer )
221
+ /*
222
+ ** Return width of the current char in columns.
223
+ **
224
+ ***********************************************************************/
225
+ {
226
+ wchar_t wideChar = 0 ;
227
+ mbtowc (& wideChar , buffer , MB_CUR_MAX );
228
+ return wcwidth (wideChar );
211
229
}
212
230
213
231
@@ -417,7 +435,7 @@ static struct termios Term_Attrs; // Initial settings, restored on exit
417
435
return ++ cp ;
418
436
}
419
437
420
- bytes = 1 + trailingBytesForUTF8 [ * cp ] ;
438
+ bytes = CHAR_LEN ( * cp ) ;
421
439
if (term -> end < TERM_BUF_LEN - bytes ) { // avoid buffer overrun
422
440
423
441
if (term -> pos < term -> end ) { // open space for it:
@@ -456,14 +474,18 @@ static struct termios Term_Attrs; // Initial settings, restored on exit
456
474
if ( (term -> pos == term -> end ) && back == 0 ) return ; //Ctrl-D at EOL
457
475
if ( term -> pos == 0 && back ) return ; // backspace at beginning of line
458
476
459
- if (back ) STEP_BACKWARD (term );
477
+ if (back ) {
478
+ STEP_BACKWARD (term );
479
+ back = Get_Char_Width (term -> buffer + term -> pos );
480
+ }
481
+
482
+ encoded_len = CHAR_LEN (term -> buffer [term -> pos ]);
460
483
461
- encoded_len = 1 + trailingBytesForUTF8 [term -> buffer [term -> pos ]];
462
484
len = encoded_len + term -> end - term -> pos ;
463
485
464
486
if (term -> pos >= 0 && len > 0 ) {
465
487
MOVE_MEM (term -> buffer + term -> pos , term -> buffer + term -> pos + encoded_len , len );
466
- if (back ) Write_Char (BS , 1 );
488
+ if (back ) Write_Char (BS , back );
467
489
term -> end -= encoded_len ;
468
490
Show_Line (term , 1 );
469
491
}
@@ -482,7 +504,7 @@ static struct termios Term_Attrs; // Initial settings, restored on exit
482
504
if (count < 0 ) {
483
505
if (term -> pos > 0 ) {
484
506
STEP_BACKWARD (term );
485
- Write_Char (BS , 1 );
507
+ Write_Char (BS , Get_Char_Width ( term -> buffer + term -> pos ) );
486
508
}
487
509
}
488
510
else {
@@ -508,7 +530,7 @@ static struct termios Term_Attrs; // Initial settings, restored on exit
508
530
if (term -> buffer [term -> pos - 1 ] == ' ' ) {
509
531
for (;term -> pos > 0 ;){
510
532
STEP_BACKWARD (term );
511
- Write_Char (BS , 1 );
533
+ Write_Char (BS , Get_Char_Width ( term -> buffer + term -> pos ) );
512
534
if (term -> buffer [term -> pos ] != ' ' ) break ;
513
535
}
514
536
}
@@ -519,7 +541,7 @@ static struct termios Term_Attrs; // Initial settings, restored on exit
519
541
term -> pos = pos ;
520
542
break ;
521
543
}
522
- Write_Char (BS , 1 );
544
+ Write_Char (BS , Get_Char_Width ( term -> buffer + term -> pos ) );
523
545
}
524
546
}
525
547
else {
@@ -575,7 +597,6 @@ static struct termios Term_Attrs; // Initial settings, restored on exit
575
597
return cp ;
576
598
}
577
599
else if (* cp == '[' || * cp == 'O' ) {
578
-
579
600
// Special key:
580
601
switch (* ++ cp ) {
581
602
0 commit comments