\brief Handle backspace with line wrapping support
| 1196 | |
| 1197 | /// \brief Handle backspace with line wrapping support |
| 1198 | void CLIWide::handle_backspace_with_wrapping(InputState& state) { |
| 1199 | if (state.cursor_pos > 0) { |
| 1200 | // Normal backspace within the same line |
| 1201 | std::string& current_line = state.lines[state.current_line_index]; |
| 1202 | |
| 1203 | // Check if we're deleting a tab character |
| 1204 | if (current_line[state.cursor_pos - 1] == '\t') { |
| 1205 | current_line.erase(state.cursor_pos - 1, 1); |
| 1206 | state.cursor_pos--; |
| 1207 | } else { |
| 1208 | // Find the start of the character to delete |
| 1209 | size_t delete_start = state.cursor_pos - 1; |
| 1210 | // Handle UTF-8 continuation bytes |
| 1211 | while (delete_start > 0 && (static_cast<unsigned char>(current_line[delete_start]) & 0xC0) == 0x80) { |
| 1212 | delete_start--; |
| 1213 | } |
| 1214 | |
| 1215 | current_line.erase(delete_start, state.cursor_pos - delete_start); |
| 1216 | state.cursor_pos = delete_start; |
| 1217 | } |
| 1218 | |
| 1219 | // Redraw line from cursor position with tab visualization |
| 1220 | int visual_cursor_col = state.prompt_len + get_visual_cursor_position(current_line, state.cursor_pos); |
| 1221 | |
| 1222 | // Get current cursor position and move to correct position |
| 1223 | CONSOLE_SCREEN_BUFFER_INFO csbi; |
| 1224 | if (GetConsoleScreenBufferInfo(hConsoleOutput, &csbi)) { |
| 1225 | COORD pos = {static_cast<SHORT>(visual_cursor_col), csbi.dwCursorPosition.Y}; |
| 1226 | SetConsoleCursorPosition(hConsoleOutput, pos); |
| 1227 | clear_line_from_cursor(); |
| 1228 | std::cout << visualize_tabs(current_line.substr(state.cursor_pos)); |
| 1229 | |
| 1230 | // Position cursor at the correct final position |
| 1231 | COORD final_pos = {static_cast<SHORT>(visual_cursor_col), csbi.dwCursorPosition.Y}; |
| 1232 | SetConsoleCursorPosition(hConsoleOutput, final_pos); |
| 1233 | } |
| 1234 | } else if (state.current_line_index > 0) { |
| 1235 | // Backspace at beginning of line - delete last character of previous line and current line |
| 1236 | std::string& current_line = state.lines[state.current_line_index]; |
| 1237 | std::string& prev_line = state.lines[state.current_line_index - 1]; |
| 1238 | |
| 1239 | // Remove the current line first |
| 1240 | state.lines.erase(state.lines.begin() + state.current_line_index); |
| 1241 | state.is_wrapped_line.erase(state.is_wrapped_line.begin() + state.current_line_index); |
| 1242 | |
| 1243 | // Move to previous line |
| 1244 | state.current_line_index--; |
| 1245 | state.prompt_len = (state.current_line_index == 0) ? 4 : 4; // ">>> " or "... " |
| 1246 | |
| 1247 | // Delete the last character of the previous line |
| 1248 | if (!prev_line.empty()) { |
| 1249 | // Find the start of the last character to delete |
| 1250 | size_t delete_start = prev_line.length() - 1; |
| 1251 | // Handle UTF-8 continuation bytes |
| 1252 | while (delete_start > 0 && (static_cast<unsigned char>(prev_line[delete_start]) & 0xC0) == 0x80) { |
| 1253 | delete_start--; |
| 1254 | } |
| 1255 |