@@ -153,6 +153,29 @@ grid_reader_cursor_end_of_line(struct grid_reader *gr, int wrap, int all)
153
153
gr -> cx = grid_reader_line_length (gr );
154
154
}
155
155
156
+ /* Handle line wrapping while moving the cursor. */
157
+ static int
158
+ grid_reader_handle_wrap (struct grid_reader * gr , u_int * xx , u_int * yy )
159
+ {
160
+ /*
161
+ * Make sure the cursor lies within the grid reader's bounding area,
162
+ * wrapping to the next line as necessary. Return zero if the cursor
163
+ * would wrap past the bottom of the grid.
164
+ */
165
+ while (gr -> cx > * xx ) {
166
+ if (gr -> cy == * yy )
167
+ return (0 );
168
+ grid_reader_cursor_start_of_line (gr , 0 );
169
+ grid_reader_cursor_down (gr );
170
+
171
+ if (grid_get_line (gr -> gd , gr -> cy )-> flags & GRID_LINE_WRAPPED )
172
+ * xx = gr -> gd -> sx - 1 ;
173
+ else
174
+ * xx = grid_reader_line_length (gr );
175
+ }
176
+ return (1 );
177
+ }
178
+
156
179
/* Check if character under cursor is in set. */
157
180
int
158
181
grid_reader_in_set (struct grid_reader * gr , const char * set )
170
193
grid_reader_cursor_next_word (struct grid_reader * gr , const char * separators )
171
194
{
172
195
u_int xx , yy ;
173
- int expected = 0 ;
174
196
175
197
/* Do not break up wrapped words. */
176
198
if (grid_get_line (gr -> gd , gr -> cy )-> flags & GRID_LINE_WRAPPED )
@@ -180,41 +202,42 @@ grid_reader_cursor_next_word(struct grid_reader *gr, const char *separators)
180
202
yy = gr -> gd -> hsize + gr -> gd -> sy - 1 ;
181
203
182
204
/*
183
- * If we started inside a word, skip over word characters. Then skip
184
- * over separators till the next word .
205
+ * When navigating via spaces (for example with next-space) separators
206
+ * should be empty .
185
207
*
186
- * expected is initially set to 0 for the former and then 1 for the
187
- * latter. It is finally set to 0 when the beginning of the next word is
188
- * found.
208
+ * If we started on a separator that is not whitespace, skip over
209
+ * subsequent separators that are not whitespace. Otherwise, if we
210
+ * started on a non-whitespace character, skip over subsequent
211
+ * characters that are neither whitespace nor separators. Then, skip
212
+ * over whitespace (if any) until the next non-whitespace character.
189
213
*/
190
- do {
191
- while (gr -> cx > xx ||
192
- grid_reader_in_set (gr , separators ) == expected ) {
193
- /* Move down if we are past the end of the line. */
194
- if (gr -> cx > xx ) {
195
- if (gr -> cy == yy )
196
- return ;
197
- grid_reader_cursor_start_of_line (gr , 0 );
198
- grid_reader_cursor_down (gr );
199
-
200
- if (grid_get_line (gr -> gd , gr -> cy )-> flags &
201
- GRID_LINE_WRAPPED )
202
- xx = gr -> gd -> sx - 1 ;
203
- else
204
- xx = grid_reader_line_length (gr );
205
- } else
214
+ if (!grid_reader_handle_wrap (gr , & xx , & yy ))
215
+ return ;
216
+ if (!grid_reader_in_set (gr , WHITESPACE )) {
217
+ if (grid_reader_in_set (gr , separators )) {
218
+ do
206
219
gr -> cx ++ ;
220
+ while (grid_reader_handle_wrap (gr , & xx , & yy ) &&
221
+ grid_reader_in_set (gr , separators ) &&
222
+ !grid_reader_in_set (gr , WHITESPACE ));
223
+ } else {
224
+ do
225
+ gr -> cx ++ ;
226
+ while (grid_reader_handle_wrap (gr , & xx , & yy ) &&
227
+ !(grid_reader_in_set (gr , separators ) ||
228
+ grid_reader_in_set (gr , WHITESPACE )));
207
229
}
208
- expected = !expected ;
209
- } while (expected == 1 );
230
+ }
231
+ while (grid_reader_handle_wrap (gr , & xx , & yy ) &&
232
+ grid_reader_in_set (gr , WHITESPACE ))
233
+ gr -> cx ++ ;
210
234
}
211
235
212
236
/* Move cursor to the end of the next word. */
213
237
void
214
238
grid_reader_cursor_next_word_end (struct grid_reader * gr , const char * separators )
215
239
{
216
240
u_int xx , yy ;
217
- int expected = 1 ;
218
241
219
242
/* Do not break up wrapped words. */
220
243
if (grid_get_line (gr -> gd , gr -> cy )-> flags & GRID_LINE_WRAPPED )
@@ -224,83 +247,93 @@ grid_reader_cursor_next_word_end(struct grid_reader *gr, const char *separators)
224
247
yy = gr -> gd -> hsize + gr -> gd -> sy - 1 ;
225
248
226
249
/*
227
- * If we started on a separator, skip over separators. Then skip over
228
- * word characters till the next separator .
250
+ * When navigating via spaces (for example with next-space), separators
251
+ * should be empty in both modes .
229
252
*
230
- * expected is initially set to 1 for the former and then 1 for the
231
- * latter. It is finally set to 1 when the end of the next word is
232
- * found.
253
+ * If we started on a whitespace, move until reaching the first
254
+ * non-whitespace character. If that character is a separator, treat
255
+ * subsequent separators as a word, and continue moving until the first
256
+ * non-separator. Otherwise, continue moving until the first separator
257
+ * or whitespace.
233
258
*/
234
- do {
235
- while (gr -> cx > xx ||
236
- grid_reader_in_set (gr , separators ) == expected ) {
237
- /* Move down if we are past the end of the line. */
238
- if (gr -> cx > xx ) {
239
- if (gr -> cy == yy )
240
- return ;
241
- grid_reader_cursor_start_of_line (gr , 0 );
242
- grid_reader_cursor_down (gr );
243
-
244
- if (grid_get_line (gr -> gd , gr -> cy )-> flags &
245
- GRID_LINE_WRAPPED )
246
- xx = gr -> gd -> sx - 1 ;
247
- else
248
- xx = grid_reader_line_length (gr );
249
- } else
259
+
260
+ while (grid_reader_handle_wrap (gr , & xx , & yy )) {
261
+ if (grid_reader_in_set (gr , WHITESPACE ))
262
+ gr -> cx ++ ;
263
+ else if (grid_reader_in_set (gr , separators )) {
264
+ do
265
+ gr -> cx ++ ;
266
+ while (grid_reader_handle_wrap (gr , & xx , & yy ) &&
267
+ grid_reader_in_set (gr , separators ) &&
268
+ !grid_reader_in_set (gr , WHITESPACE ));
269
+ return ;
270
+ } else {
271
+ do
250
272
gr -> cx ++ ;
273
+ while (grid_reader_handle_wrap (gr , & xx , & yy ) &&
274
+ !(grid_reader_in_set (gr , WHITESPACE ) ||
275
+ grid_reader_in_set (gr , separators )));
276
+ return ;
251
277
}
252
- expected = !expected ;
253
- } while (expected == 0 );
278
+ }
254
279
}
255
280
256
281
/* Move to the previous place where a word begins. */
257
282
void
258
283
grid_reader_cursor_previous_word (struct grid_reader * gr , const char * separators ,
259
- int already )
284
+ int already , int stop_at_eol )
260
285
{
261
- int oldx , oldy , r ;
286
+ int oldx , oldy , at_eol , word_is_letters ;
262
287
263
288
/* Move back to the previous word character. */
264
- if (already || grid_reader_in_set (gr , separators )) {
289
+ if (already || grid_reader_in_set (gr , WHITESPACE )) {
265
290
for (;;) {
266
291
if (gr -> cx > 0 ) {
267
292
gr -> cx -- ;
268
- if (!grid_reader_in_set (gr , separators ))
293
+ if (!grid_reader_in_set (gr , WHITESPACE )) {
294
+ word_is_letters =
295
+ !grid_reader_in_set (gr , separators );
269
296
break ;
297
+ }
270
298
} else {
271
299
if (gr -> cy == 0 )
272
300
return ;
273
301
grid_reader_cursor_up (gr );
274
302
grid_reader_cursor_end_of_line (gr , 0 , 0 );
275
303
276
304
/* Stop if separator at EOL. */
277
- if (gr -> cx > 0 ) {
305
+ if (stop_at_eol && gr -> cx > 0 ) {
278
306
oldx = gr -> cx ;
279
307
gr -> cx -- ;
280
- r = grid_reader_in_set (gr , separators );
308
+ at_eol = grid_reader_in_set (gr ,
309
+ WHITESPACE );
281
310
gr -> cx = oldx ;
282
- if (r )
311
+ if (at_eol ) {
312
+ word_is_letters = 0 ;
283
313
break ;
314
+ }
284
315
}
285
316
}
286
317
}
287
- }
318
+ } else
319
+ word_is_letters = !grid_reader_in_set (gr , separators );
288
320
289
321
/* Move back to the beginning of this word. */
290
322
do {
291
323
oldx = gr -> cx ;
292
324
oldy = gr -> cy ;
293
325
if (gr -> cx == 0 ) {
294
326
if (gr -> cy == 0 ||
295
- ~grid_get_line (gr -> gd , gr -> cy - 1 )-> flags &
296
- GRID_LINE_WRAPPED )
327
+ ( ~grid_get_line (gr -> gd , gr -> cy - 1 )-> flags &
328
+ GRID_LINE_WRAPPED ) )
297
329
break ;
298
330
grid_reader_cursor_up (gr );
299
331
grid_reader_cursor_end_of_line (gr , 0 , 1 );
300
332
}
301
333
if (gr -> cx > 0 )
302
334
gr -> cx -- ;
303
- } while (!grid_reader_in_set (gr , separators ));
335
+ } while (!grid_reader_in_set (gr , WHITESPACE ) &&
336
+ word_is_letters != grid_reader_in_set (gr , separators ));
304
337
gr -> cx = oldx ;
305
338
gr -> cy = oldy ;
306
339
}
@@ -324,17 +357,17 @@ grid_reader_cursor_jump(struct grid_reader *gr, const struct utf8_data *jc)
324
357
memcmp (gc .data .data , jc -> data , gc .data .size ) == 0 ) {
325
358
gr -> cx = px ;
326
359
gr -> cy = py ;
327
- return 1 ;
360
+ return ( 1 ) ;
328
361
}
329
362
px ++ ;
330
363
}
331
364
332
365
if (py == yy ||
333
366
!(grid_get_line (gr -> gd , py )-> flags & GRID_LINE_WRAPPED ))
334
- return 0 ;
367
+ return ( 0 ) ;
335
368
px = 0 ;
336
369
}
337
- return 0 ;
370
+ return ( 0 ) ;
338
371
}
339
372
340
373
/* Jump back to character. */
@@ -354,16 +387,16 @@ grid_reader_cursor_jump_back(struct grid_reader *gr, const struct utf8_data *jc)
354
387
memcmp (gc .data .data , jc -> data , gc .data .size ) == 0 ) {
355
388
gr -> cx = px - 1 ;
356
389
gr -> cy = py - 1 ;
357
- return 1 ;
390
+ return ( 1 ) ;
358
391
}
359
392
}
360
393
361
394
if (py == 1 ||
362
395
!(grid_get_line (gr -> gd , py - 2 )-> flags & GRID_LINE_WRAPPED ))
363
- return 0 ;
396
+ return ( 0 ) ;
364
397
xx = grid_line_length (gr -> gd , py - 2 );
365
398
}
366
- return 0 ;
399
+ return ( 0 ) ;
367
400
}
368
401
369
402
/* Jump back to the first non-blank character of the line. */
0 commit comments