Browse code

Rewrite cursor implementation

Index the cursor from the beginning instead of the end, which is easier
(at least for me) to think about.

This also fixes issues with Ctrl-W in the previous implementation.

John Hawthorn authored on 16/10/2017 06:32:41
Showing 2 changed files

... ...
@@ -95,8 +95,7 @@ static void draw(tty_interface_t *state) {
95 95
 		tty_moveup(tty, num_lines);
96 96
 	}
97 97
 
98
-	int length = strlen(options->prompt) + strlen(state->search);
99
-	tty_setcol(tty, length + state->offset);
98
+	tty_setcol(tty, strlen(options->prompt) + state->cursor);
100 99
 	tty_flush(tty);
101 100
 }
102 101
 
... ...
@@ -135,26 +134,33 @@ static void action_emit(tty_interface_t *state) {
135 134
 
136 135
 static void action_del_char(tty_interface_t *state) {
137 136
 	if (*state->search) {
138
-		int length = strlen(state->search);
139
-		int index = length + state->offset - 1;
140
-		if (index < 0) {
137
+		size_t length = strlen(state->search);
138
+		if(state->cursor == 0) {
141 139
 			return;
142 140
 		}
143 141
 
144
-		memmove(&state->search[index], &state->search[index + 1], length - index);
142
+		state->cursor--;
143
+		memmove(&state->search[state->cursor], &state->search[state->cursor + 1], length - state->cursor);
145 144
 	}
146 145
 }
147 146
 
148 147
 static void action_del_word(tty_interface_t *state) {
149
-	size_t search_size = strlen(state->search);
150
-	if (search_size)
151
-		state->search[--search_size] = '\0';
152
-	while (search_size && !isspace(state->search[--search_size]))
153
-		state->search[search_size] = '\0';
148
+	size_t original_cursor = state->cursor;
149
+	size_t cursor = state->cursor;
150
+
151
+	while (cursor && isspace(state->search[cursor - 1]))
152
+		cursor--;
153
+
154
+	while (cursor && !isspace(state->search[cursor - 1]))
155
+		cursor--;
156
+
157
+	memmove(&state->search[cursor], &state->search[original_cursor], strlen(state->search) - original_cursor + 1);
158
+	state->cursor = cursor;
154 159
 }
155 160
 
156 161
 static void action_del_all(tty_interface_t *state) {
157
-	strcpy(state->search, "");
162
+	memmove(state->search, &state->search[state->cursor], strlen(state->search) - state->cursor + 1);
163
+	state->cursor = 0;
158 164
 }
159 165
 
160 166
 static void action_prev(tty_interface_t *state) {
... ...
@@ -172,21 +178,21 @@ static void action_next(tty_interface_t *state) {
172 178
 }
173 179
 
174 180
 static void action_left(tty_interface_t *state) {
175
-	if ((unsigned long)abs(state->offset) < strlen(state->search))
176
-		state->offset--;
181
+	if (state->cursor > 0)
182
+		state->cursor--;
177 183
 }
178 184
 
179 185
 static void action_right(tty_interface_t *state) {
180
-	if (state->offset < 0)
181
-		state->offset++;
186
+	if (state->cursor < strlen(state->search))
187
+		state->cursor++;
182 188
 }
183 189
 
184 190
 static void action_beginning(tty_interface_t *state) {
185
-	state->offset = -strlen(state->search);
191
+	state->cursor = 0;
186 192
 }
187 193
 
188 194
 static void action_end(tty_interface_t *state) {
189
-	state->offset = 0;
195
+	state->cursor = strlen(state->search);
190 196
 }
191 197
 
192 198
 static void action_pageup(tty_interface_t *state) {
... ...
@@ -206,6 +212,7 @@ static void action_autocomplete(tty_interface_t *state) {
206 212
 	const char *current_selection = choices_get(state->choices, state->choices->selection);
207 213
 	if (current_selection) {
208 214
 		strncpy(state->search, choices_get(state->choices, state->choices->selection), SEARCH_SIZE_MAX);
215
+		state->cursor = strlen(state->search);
209 216
 	}
210 217
 }
211 218
 
... ...
@@ -220,14 +227,10 @@ static void append_search(tty_interface_t *state, char ch) {
220 227
 	char *search = state->search;
221 228
 	size_t search_size = strlen(search);
222 229
 	if (search_size < SEARCH_SIZE_MAX) {
223
-		int location = state->offset + search_size;
224
-		for (int i = search_size; i >= 0; i--) {
225
-			if (i >= location) {
226
-				search[i + 1] = search[i];
227
-			}
228
-		}
230
+		memmove(&search[state->cursor+1], &search[state->cursor], search_size - state->cursor + 1);
231
+		search[state->cursor] = ch;
229 232
 
230
-		search[location] = ch;
233
+		state->cursor++;
231 234
 	}
232 235
 }
233 236
 
... ...
@@ -235,7 +238,6 @@ void tty_interface_init(tty_interface_t *state, tty_t *tty, choices_t *choices,
235 238
 	state->tty = tty;
236 239
 	state->choices = choices;
237 240
 	state->options = options;
238
-	state->offset = 0;
239 241
 
240 242
 	strcpy(state->input, "");
241 243
 	strcpy(state->search, "");
... ...
@@ -246,6 +248,8 @@ void tty_interface_init(tty_interface_t *state, tty_t *tty, choices_t *choices,
246 248
 	if (options->init_search)
247 249
 		strncpy(state->search, options->init_search, SEARCH_SIZE_MAX);
248 250
 
251
+	state->cursor = strlen(state->search);
252
+
249 253
 	update_search(state);
250 254
 }
251 255
 
... ...
@@ -14,7 +14,7 @@ typedef struct {
14 14
 
15 15
 	char search[SEARCH_SIZE_MAX + 1];
16 16
 	char last_search[SEARCH_SIZE_MAX + 1];
17
-	int offset;
17
+	size_t cursor;
18 18
 
19 19
 	char input[32]; /* Pending input buffer */
20 20