@@ -113,26 +113,6 @@ int slash_getopt(struct slash *slash, const char *opts)
113113}
114114
115115/* Terminal handling */
116- static size_t slash_escaped_strlen (const char * s )
117- {
118- int len = 0 ;
119- bool escaped = false;
120-
121- while (* s ) {
122- if (escaped ) {
123- if (* s == 'm' )
124- escaped = false;
125- } else if (* s == ESC ) {
126- escaped = true;
127- } else {
128- len ++ ;
129- }
130- s ++ ;
131- }
132-
133- return len ;
134- }
135-
136116static int slash_rawmode_enable (struct slash * slash )
137117{
138118#ifdef SLASH_HAVE_TERMIOS_H
@@ -697,6 +677,7 @@ static void slash_complete(struct slash *slash)
697677 if (command ) {
698678 slash_printf (slash , "\n" );
699679 slash_command_usage (slash , command );
680+ slash -> refresh_full = true;
700681 } else {
701682 slash_bell (slash );
702683 }
@@ -717,6 +698,7 @@ static void slash_complete(struct slash *slash)
717698 slash_command_description (slash , cur );
718699 }
719700 }
701+ slash -> refresh_full = true;
720702 }
721703}
722704
@@ -888,6 +870,7 @@ static bool slash_history_next(struct slash *slash)
888870 slash -> buffer [srclen ] = '\0' ;
889871 slash -> history_cursor = src ;
890872 slash -> cursor = slash -> length = srclen ;
873+ slash -> refresh_buffer = true;
891874
892875 /* Rewind if use to store buffer temporarily */
893876 if (!slash -> history_depth && slash -> history_cursor != slash -> history_tail )
@@ -917,33 +900,64 @@ static bool slash_history_previous(struct slash *slash)
917900 slash -> buffer [srclen ] = '\0' ;
918901 slash -> history_cursor = src ;
919902 slash -> cursor = slash -> length = srclen ;
903+ slash -> refresh_buffer = true;
920904
921905 return true;
922906}
923907
924908/* Line editing */
925909int slash_refresh (struct slash * slash )
926910{
927- char esc [16 ];
911+ const char * esc = ESCAPE ("K" );
912+
913+ if (slash -> refresh_full ) {
914+ slash_putchar (slash , '\r' );
915+ if (slash_write (slash , slash -> prompt , slash -> prompt_length ) < 0 )
916+ return -1 ;
917+ if (slash_write (slash , esc , strlen (esc )) < 0 )
918+ return -1 ;
919+ slash -> cursor_screen = 0 ;
920+ slash -> length_screen = 0 ;
921+ slash -> refresh_full = false;
922+ }
928923
929- /* Ensure line is zero terminated */
930- slash -> buffer [slash -> length ] = '\0' ;
924+ if (slash -> refresh_buffer ) {
925+ while (slash -> cursor_screen > 0 ) {
926+ slash_putchar (slash , '\b' );
927+ slash -> cursor_screen -- ;
928+ }
929+ slash -> refresh_buffer = false;
930+ }
931+
932+ while (slash -> cursor_screen != slash -> cursor ) {
933+ if (slash -> cursor_screen < slash -> cursor ) {
934+ slash_putchar (slash , slash -> buffer [slash -> cursor_screen ]);
935+ slash -> cursor_screen ++ ;
936+ } else if (slash -> cursor_screen > slash -> cursor ) {
937+ slash_putchar (slash , '\b' );
938+ slash -> cursor_screen -- ;
939+ }
940+ }
931941
932- /* Move cursor to left edge */
933- if (slash_putchar (slash , '\r' ) < 0 )
934- return -1 ;
942+ if (slash -> length_screen != slash -> length ) {
943+ if (slash_write (slash ,
944+ & slash -> buffer [slash -> cursor ],
945+ slash -> length - slash -> cursor ) < 0 )
946+ return -1 ;
947+ slash -> cursor_screen = slash -> length ;
935948
936- /* Write the prompt and the current buffer content */
937- if (slash_write (slash , slash -> prompt , slash -> prompt_length ) < 0 )
938- return -1 ;
939- if (slash_write (slash , slash -> buffer , slash -> length ) < 0 )
940- return -1 ;
949+ if (slash -> length_screen > slash -> length ) {
950+ if (slash_write (slash , esc , strlen (esc )) < 0 )
951+ return -1 ;
952+ }
941953
942- /* Erase to the right and move cursor to original position. */
943- snprintf (esc , sizeof (esc ), ESCAPE ("K" ) "\r" ESCAPE ("%uC" ),
944- (unsigned int )(slash -> cursor + slash -> prompt_print_length ));
945- if (slash_write (slash , esc , strlen (esc )) < 0 )
946- return -1 ;
954+ while (slash -> cursor_screen > slash -> cursor ) {
955+ slash_putchar (slash , '\b' );
956+ slash -> cursor_screen -- ;
957+ }
958+
959+ slash -> length_screen = slash -> length ;
960+ }
947961
948962 return 0 ;
949963}
@@ -953,30 +967,21 @@ static void slash_insert(struct slash *slash, int c)
953967 if (slash -> length + 1 > slash -> line_size )
954968 return ;
955969
956- /* Fast path if we're adding a character to the end of the line */
957- if (slash -> cursor == slash -> length ) {
958- slash -> buffer [slash -> cursor ] = c ;
959- slash -> cursor ++ ;
960- slash -> length ++ ;
961- slash -> buffer [slash -> length ] = '\0' ;
962- slash_putchar (slash , slash -> buffer [slash -> cursor - 1 ]);
963- } else {
964- memmove (& slash -> buffer [slash -> cursor + 1 ],
965- & slash -> buffer [slash -> cursor ],
966- slash -> length - slash -> cursor );
967- slash -> buffer [slash -> cursor ] = c ;
968- slash -> cursor ++ ;
969- slash -> length ++ ;
970- slash -> buffer [slash -> length ] = '\0' ;
971- slash_refresh (slash );
972- }
970+ memmove (& slash -> buffer [slash -> cursor + 1 ],
971+ & slash -> buffer [slash -> cursor ],
972+ slash -> length - slash -> cursor );
973+ slash -> buffer [slash -> cursor ] = c ;
974+ slash -> cursor ++ ;
975+ slash -> length ++ ;
976+ slash -> buffer [slash -> length ] = '\0' ;
973977}
974978
975979void slash_reset (struct slash * slash )
976980{
977981 slash -> buffer [0 ] = '\0' ;
978982 slash -> length = 0 ;
979983 slash -> cursor = 0 ;
984+ slash -> refresh_full = true;
980985}
981986
982987static void slash_arrow_up (struct slash * slash )
@@ -1018,6 +1023,7 @@ void slash_clear_screen(struct slash *slash)
10181023{
10191024 const char * esc = ESCAPE ("H" ) ESCAPE ("2J" );
10201025 slash_write (slash , esc , strlen (esc ));
1026+ slash -> refresh_full = true;
10211027}
10221028
10231029static void slash_backspace (struct slash * slash )
@@ -1065,7 +1071,6 @@ void slash_set_prompt(struct slash *slash, const char *prompt)
10651071{
10661072 slash -> prompt = prompt ;
10671073 slash -> prompt_length = strlen (prompt );
1068- slash -> prompt_print_length = slash_escaped_strlen (prompt );
10691074}
10701075
10711076char * slash_readline (struct slash * slash )
@@ -1108,8 +1113,6 @@ char *slash_readline(struct slash *slash)
11081113 slash -> cursor = slash -> length ;
11091114 }
11101115 escaped = false;
1111-
1112- slash_refresh (slash );
11131116 } else if (iscntrl (c )) {
11141117 switch (c ) {
11151118 case CONTROL ('A' ):
@@ -1141,6 +1144,7 @@ char *slash_readline(struct slash *slash)
11411144 break ;
11421145 case CONTROL ('K' ):
11431146 slash -> length = slash -> cursor ;
1147+ slash -> buffer [slash -> length ] = '\0' ;
11441148 break ;
11451149 case CONTROL ('L' ):
11461150 slash_clear_screen (slash );
@@ -1157,6 +1161,7 @@ char *slash_readline(struct slash *slash)
11571161 case CONTROL ('U' ):
11581162 slash -> cursor = 0 ;
11591163 slash -> length = 0 ;
1164+ slash -> buffer [0 ] = '\0' ;
11601165 break ;
11611166 case CONTROL ('W' ):
11621167 slash_delete_word (slash );
@@ -1179,13 +1184,13 @@ char *slash_readline(struct slash *slash)
11791184 /* Unknown control */
11801185 break ;
11811186 }
1182-
1183- slash_refresh (slash );
11841187 } else if (isprint (c )) {
11851188 /* Add to buffer */
11861189 slash_insert (slash , c );
11871190 }
11881191
1192+ slash_refresh (slash );
1193+
11891194 slash -> last_char = c ;
11901195 }
11911196
0 commit comments