@@ -198,6 +198,19 @@ static int slash_getchar(struct slash *slash)
198198 return c ;
199199}
200200
201+ static void slash_mark_changed (struct slash * slash , size_t start , size_t end )
202+ {
203+ if (slash -> change_start == slash -> change_end ) {
204+ slash -> change_start = start ;
205+ slash -> change_end = end ;
206+ } else {
207+ if (start < slash -> change_start )
208+ slash -> change_start = start ;
209+ if (end > slash -> change_end )
210+ slash -> change_end = end ;
211+ }
212+ }
213+
201214#ifdef SLASH_HAVE_SELECT
202215static int slash_wait_select (struct slash * slash , unsigned int ms )
203216{
@@ -622,7 +635,9 @@ static void slash_set_completion(struct slash *slash,
622635 complete [len ] = '\0' ;
623636 if (space )
624637 strncat (complete , " " , slash -> line_size - 1 );
625- slash -> cursor = slash -> length = strlen (slash -> buffer );
638+ slash -> length = strlen (slash -> buffer );
639+ slash_mark_changed (slash , slash -> cursor , slash -> length );
640+ slash -> cursor = slash -> length ;
626641}
627642
628643static bool slash_complete_matches (struct slash * slash ,
@@ -875,7 +890,7 @@ static bool slash_history_next(struct slash *slash)
875890 slash -> buffer [srclen ] = '\0' ;
876891 slash -> history_cursor = src ;
877892 slash -> cursor = slash -> length = srclen ;
878- slash -> refresh_buffer = true ;
893+ slash_mark_changed ( slash , 0 , slash -> length ) ;
879894
880895 /* Rewind if use to store buffer temporarily */
881896 if (!slash -> history_depth && slash -> history_cursor != slash -> history_tail )
@@ -905,28 +920,64 @@ static bool slash_history_previous(struct slash *slash)
905920 slash -> buffer [srclen ] = '\0' ;
906921 slash -> history_cursor = src ;
907922 slash -> cursor = slash -> length = srclen ;
908- slash -> refresh_buffer = true ;
923+ slash_mark_changed ( slash , 0 , slash -> length ) ;
909924
910925 return true;
911926}
912927
913928/* Line editing */
914- static int slash_cursor_back (struct slash * slash , size_t n )
929+ static int slash_screen_cursor_back (struct slash * slash , size_t n )
915930{
916931 /* If we need to move more than 3 colums, CUB uses fewer bytes */
917932 if (n > 3 ) {
918933 slash_printf (slash , ESCAPE ("%zuD" ), n );
934+ slash -> cursor_screen -= n ;
919935 } else {
920- while (n -- )
936+ while (n -- ) {
921937 slash_putchar (slash , '\b' );
938+ slash -> cursor_screen -- ;
939+ }
940+ }
941+
942+ return 0 ;
943+ }
944+
945+ static int slash_screen_cursor_forward (struct slash * slash , size_t n )
946+ {
947+ /* If we need to move more than 3 colums, CUF uses fewer bytes */
948+ if (n > 3 ) {
949+ slash_printf (slash , ESCAPE ("%zuC" ), n );
950+ slash -> cursor_screen += n ;
951+ } else {
952+ while (n -- ) {
953+ slash_putchar (slash , slash -> buffer [slash -> cursor_screen ]);
954+ slash -> cursor_screen ++ ;
955+ }
956+ }
957+
958+ return 0 ;
959+ }
960+
961+ static int slash_screen_cursor_to_column (struct slash * slash , size_t col )
962+ {
963+ size_t diff ;
964+
965+ if (col > slash -> cursor_screen ) {
966+ diff = col - slash -> cursor_screen ;
967+ return slash_screen_cursor_forward (slash , diff );
968+ } else if (col < slash -> cursor_screen ) {
969+ diff = slash -> cursor_screen - col ;
970+ return slash_screen_cursor_back (slash , diff );
922971 }
923972
924973 return 0 ;
925974}
975+
926976int slash_refresh (struct slash * slash )
927977{
928978 const char * esc = ESCAPE ("K" );
929979
980+ /* Full refresh with prompt */
930981 if (slash -> refresh_full ) {
931982 slash_putchar (slash , '\r' );
932983 if (slash_write (slash , esc , strlen (esc )) < 0 )
@@ -935,61 +986,64 @@ int slash_refresh(struct slash *slash)
935986 return -1 ;
936987 slash -> cursor_screen = 0 ;
937988 slash -> length_screen = 0 ;
989+ slash -> change_start = 0 ;
990+ slash -> change_end = slash -> length ;
938991 slash -> refresh_full = false;
939992 }
940993
941- if (slash -> refresh_buffer ) {
942- slash_cursor_back (slash , slash -> cursor_screen );
943- slash -> cursor_screen = 0 ;
944- slash -> refresh_buffer = false;
945- }
946-
947- while (slash -> cursor_screen < slash -> cursor ) {
948- slash_putchar (slash , slash -> buffer [slash -> cursor_screen ]);
949- slash -> cursor_screen ++ ;
950- }
951-
952- if (slash -> cursor_screen > slash -> cursor ) {
953- slash_cursor_back (slash ,
954- slash -> cursor_screen - slash -> cursor );
955- slash -> cursor_screen = slash -> cursor ;
956- }
957-
958- if (slash -> length_screen != slash -> length ) {
994+ /* Buffer contents have changed */
995+ if (slash -> change_start != slash -> change_end ) {
996+ if (slash_screen_cursor_to_column (slash , slash -> change_start ) < 0 )
997+ return -1 ;
959998 if (slash_write (slash ,
960- & slash -> buffer [slash -> cursor ],
961- slash -> length - slash -> cursor ) < 0 )
999+ & slash -> buffer [slash -> change_start ],
1000+ slash -> change_end - slash -> change_start ) < 0 )
9621001 return -1 ;
963- slash -> cursor_screen = slash -> length ;
964-
965- if (slash -> length_screen > slash -> length ) {
966- if (slash_write (slash , esc , strlen (esc )) < 0 )
967- return -1 ;
968- }
969-
970- if (slash -> cursor_screen > slash -> cursor ) {
971- slash_cursor_back (slash ,
972- slash -> cursor_screen - slash -> cursor );
973- slash -> cursor_screen = slash -> cursor ;
974- }
1002+ slash -> cursor_screen = slash -> change_end ;
1003+ slash -> change_start = slash -> change_end = 0 ;
1004+ }
9751005
976- slash -> length_screen = slash -> length ;
1006+ /* If screen contents were truncated, erase remainder */
1007+ if (slash -> length_screen > slash -> length ) {
1008+ if (slash_screen_cursor_to_column (slash , slash -> length ) < 0 )
1009+ return -1 ;
1010+ if (slash_write (slash , esc , strlen (esc )) < 0 )
1011+ return -1 ;
9771012 }
1013+ slash -> length_screen = slash -> length ;
1014+
1015+ /* Restore screen cursor position */
1016+ if (slash_screen_cursor_to_column (slash , slash -> cursor ) < 0 )
1017+ return -1 ;
9781018
9791019 return slash_write_flush (slash );
9801020}
9811021
9821022static void slash_insert (struct slash * slash , int c )
9831023{
984- if (slash -> length + 1 > slash -> line_size )
1024+ if (slash -> length >= slash -> line_size )
9851025 return ;
9861026
9871027 memmove (& slash -> buffer [slash -> cursor + 1 ],
9881028 & slash -> buffer [slash -> cursor ],
9891029 slash -> length - slash -> cursor );
9901030 slash -> buffer [slash -> cursor ] = c ;
991- slash -> cursor ++ ;
9921031 slash -> length ++ ;
1032+ slash_mark_changed (slash , slash -> cursor , slash -> length );
1033+ slash -> cursor ++ ;
1034+ slash -> buffer [slash -> length ] = '\0' ;
1035+ }
1036+
1037+ static void slash_delete (struct slash * slash )
1038+ {
1039+ if (slash -> cursor >= slash -> length )
1040+ return ;
1041+
1042+ slash -> length -- ;
1043+ memmove (& slash -> buffer [slash -> cursor ],
1044+ & slash -> buffer [slash -> cursor + 1 ],
1045+ slash -> length - slash -> cursor );
1046+ slash_mark_changed (slash , slash -> cursor , slash -> length );
9931047 slash -> buffer [slash -> length ] = '\0' ;
9941048}
9951049
@@ -998,6 +1052,8 @@ void slash_reset(struct slash *slash)
9981052 slash -> buffer [0 ] = '\0' ;
9991053 slash -> length = 0 ;
10001054 slash -> cursor = 0 ;
1055+ slash -> change_start = 0 ;
1056+ slash -> change_end = 0 ;
10011057 slash -> refresh_full = true;
10021058}
10031059
@@ -1025,17 +1081,6 @@ static void slash_arrow_left(struct slash *slash)
10251081 slash -> cursor -- ;
10261082}
10271083
1028- static void slash_delete (struct slash * slash )
1029- {
1030- if (slash -> cursor < slash -> length ) {
1031- slash -> length -- ;
1032- memmove (& slash -> buffer [slash -> cursor ],
1033- & slash -> buffer [slash -> cursor + 1 ],
1034- slash -> length - slash -> cursor );
1035- slash -> buffer [slash -> length ] = '\0' ;
1036- }
1037- }
1038-
10391084void slash_clear_screen (struct slash * slash )
10401085{
10411086 const char * esc = ESCAPE ("H" ) ESCAPE ("2J" );
@@ -1045,14 +1090,16 @@ void slash_clear_screen(struct slash *slash)
10451090
10461091static void slash_backspace (struct slash * slash )
10471092{
1048- if (slash -> cursor > 0 ) {
1049- slash -> cursor -- ;
1050- slash -> length -- ;
1051- memmove (& slash -> buffer [slash -> cursor ],
1052- & slash -> buffer [slash -> cursor + 1 ],
1053- slash -> length - slash -> cursor );
1054- slash -> buffer [slash -> length ] = '\0' ;
1055- }
1093+ if (slash -> cursor == 0 )
1094+ return ;
1095+
1096+ slash -> cursor -- ;
1097+ slash -> length -- ;
1098+ memmove (& slash -> buffer [slash -> cursor ],
1099+ & slash -> buffer [slash -> cursor + 1 ],
1100+ slash -> length - slash -> cursor );
1101+ slash_mark_changed (slash , slash -> cursor , slash -> length );
1102+ slash -> buffer [slash -> length ] = '\0' ;
10561103}
10571104
10581105static void slash_delete_word (struct slash * slash )
@@ -1068,6 +1115,7 @@ static void slash_delete_word(struct slash *slash)
10681115 memmove (& slash -> buffer [slash -> cursor ],
10691116 & slash -> buffer [old_cursor ],
10701117 slash -> length - slash -> cursor );
1118+ slash_mark_changed (slash , slash -> cursor , slash -> length );
10711119 slash -> buffer [slash -> length ] = '\0' ;
10721120}
10731121
0 commit comments