5 * 14407 SW Teal Blvd. #C
11 /* This file contains most movement functions */
17 MARK
m_updnto(m
, cnt
, cmd
)
18 MARK m
; /* movement is relative to this mark */
19 long cnt
; /* a numeric argument */
20 char cmd
; /* the command character */
22 DEFAULT(cmd
== 'G' ? nlines
: 1L);
24 /* move up or down 'cnt' lines */
30 m
-= MARK_AT_LINE(cnt
);
34 if (cnt
< 1L || cnt
> nlines
)
36 msg("Only %ld lines", nlines
);
39 m
= MARK_AT_LINE(cnt
);
47 m
+= MARK_AT_LINE(cnt
);
50 /* if that left us screwed up, then fail */
51 if (m
< MARK_FIRST
|| markline(m
) > nlines
)
60 MARK
m_right(m
, cnt
, key
, prevkey
)
61 MARK m
; /* movement is relative to this mark */
62 long cnt
; /* a numeric argument */
63 int key
; /* movement keystroke */
64 int prevkey
;/* operator keystroke, or 0 if none */
66 int idx
; /* index of the new cursor position */
70 /* If used with an operator, then move 1 less character, since the 'l'
71 * command includes the character that it moves onto.
78 /* move to right, if that's OK */
80 idx
= markidx(m
) + cnt
;
95 MARK m
; /* movement is relative to this mark */
96 long cnt
; /* a numeric argument */
100 /* move to the left, if that's OK */
101 if (markidx(m
) >= cnt
)
114 MARK
m_tocol(m
, cnt
, cmd
)
115 MARK m
; /* movement is relative to this mark */
116 long cnt
; /* a numeric argument */
117 int cmd
; /* either ctrl('X') or '|' */
119 char *text
; /* text of the line */
120 int col
; /* column number */
121 int idx
; /* index into the line */
124 /* if doing ^X, then adjust for sideways scrolling */
125 if (cmd
== ctrl('X'))
127 DEFAULT(*o_columns
& 0xff);
135 /* internally, columns are numbered 0..COLS-1, not 1..COLS */
138 /* if 0, that's easy */
145 /* find that column within the line */
148 for (col
= idx
= 0; col
< cnt
&& *text
; text
++, idx
++)
150 if (*text
== '\t' && !*o_list
)
153 col
-= col
% *o_tabstop
;
155 else if (UCHAR(*text
) < ' ' || *text
== '\177')
160 else if (text
[0] == '\\' && text
[1] == 'f' && text
[2] && *o_charattr
)
162 text
+= 2; /* plus one more as part of for loop */
172 /* the desired column was past the end of the line, so
173 * act like the user pressed "$" instead.
175 return m
| (BLKSIZE
- 1);
179 m
= (m
& ~(BLKSIZE
- 1)) + idx
;
186 MARK m
; /* movement is relative to this mark */
187 long cnt
; /* a numeric argument (ignored) */
191 /* move to the first non-whitespace character */
195 while (*scan
== ' ' || *scan
== '\t')
206 MARK m
; /* movement is relative to this mark */
207 long cnt
; /* a numeric argument (ignored) */
209 /* Try to move *EXTREMELY* far to the right. It is fervently hoped
210 * that other code will convert this to a more reasonable MARK before
211 * anything tries to actually use it. (See adjmove() in vi.c)
213 return m
| (BLKSIZE
- 1);
217 static int isperiod(ptr
)
218 char *ptr
; /* pointer to possible sentence-ender */
220 /* if not '.', '?', or '!', then it isn't a sentence ender */
221 if (*ptr
!= '.' && *ptr
!= '?' && *ptr
!= '!')
226 /* skip any intervening ')', ']', or '"' characters */
230 } while (*ptr
== ')' || *ptr
== ']' || *ptr
== '"');
232 /* do we have two spaces or EOL? */
233 if (!*ptr
|| ptr
[0] == ' ' && ptr
[1] == ' ')
241 MARK
m_sentence(m
, cnt
, cmd
)
242 MARK m
; /* movement is relative to this mark */
243 long cnt
; /* a numeric argument */
244 int cmd
; /* either '(' or ')' */
251 /* If '(' command, then move back one word, so that if we hit '(' at
252 * the start of a sentence we don't simply stop at the end of the
253 * previous sentence and bounce back to the start of this one again.
257 m
= m_bword(m
, 1L, 'b');
264 /* get the current line */
267 text
= ptext
+ markidx(m
);
269 /* for each requested sentence... */
272 /* search forward for one of [.?!] followed by spaces or EOL */
277 /* move forward, wrap at end of line */
295 /* move backward, wrap at beginning of line */
307 text
= ptext
+ plen
- 1;
314 } while (!isperiod(text
));
317 /* construct a mark for this location */
320 /* move forward to the first word of the next sentence */
321 m
= m_fword(m
, 1L, 'w', '\0');
327 MARK
m_paragraph(m
, cnt
, cmd
)
328 MARK m
; /* movement is relative to this mark */
329 long cnt
; /* a numeric argument */
330 int cmd
; /* either '{' or '}' */
332 char *text
; /* text of the current line */
333 char *pscn
; /* used to scan thru value of "paragraphs" option */
334 long l
, ol
; /* current line number, original line number */
335 int dir
; /* -1 if we're moving up, or 1 if down */
336 char col0
; /* character to expect in column 0 */
338 # define SENTENCE(x) (x)
339 char *list
; /* either o_sections or o_paragraph */
346 /* set the direction, based on the command */
352 SENTENCE(list
= o_paragraphs
);
358 SENTENCE(list
= o_paragraphs
);
362 if (getkey(0) != '[')
368 SENTENCE(list
= o_sections
);
372 if (getkey(0) != ']')
378 SENTENCE(list
= o_sections
);
381 ol
= l
= markline(m
);
383 /* for each paragraph that we want to travel through... */
384 while (l
> 0 && l
<= nlines
&& cnt
-- > 0)
386 /* skip blank lines between paragraphs */
387 while (l
> 0 && l
<= nlines
&& col0
== *(text
= fetchline(l
)))
392 /* skip non-blank lines that aren't paragraph separators
397 if (*text
== '.' && l
!= ol
)
399 for (pscn
= list
; pscn
[0] && pscn
[1]; pscn
+= 2)
401 if (pscn
[0] == text
[1] && pscn
[1] == text
[2])
410 } while (l
> 0 && l
<= nlines
&& col0
!= *(text
= fetchline(l
)));
432 MARK m
; /* movement is relative to this mark */
433 long cnt
; /* a numeric argument (normally 0) */
441 #ifndef NO_EXTENSIONS
442 /* if we're given a number, then treat it as a percentage of the file */
445 /* make sure it is a reasonable number */
448 msg("can only be from 1%% to 100%%");
452 /* return the appropriate line number */
453 l
= (nlines
- 1L) * cnt
/ 100L + 1L;
454 return MARK_AT_LINE(l
);
456 #endif /* undef NO_EXTENSIONS */
458 /* get the current line */
461 text
= ptext
+ markidx(m
);
463 /* search forward within line for one of "[](){}" */
464 for (match
= '\0'; !match
&& *text
; text
++)
466 /* tricky way to recognize 'em in ASCII */
468 if ((nest
& 0xdf) == ']' || (nest
& 0xdf) == '[')
470 match
= nest
^ ('[' ^ ']');
472 else if ((nest
& 0xfe) == '(')
474 match
= nest
^ ('(' ^ ')');
487 /* search forward or backward for match */
488 if (match
== '(' || match
== '[' || match
== '{')
490 /* search backward */
491 for (count
= 1; count
> 0; )
493 /* wrap at beginning of line */
505 text
= ptext
+ plen
- 1;
515 else if (*text
== nest
)
522 for (count
= 1; count
> 0; )
524 /* wrap at end of line */
543 else if (*text
== nest
)
548 /* construct a mark for this place */
554 MARK
m_tomark(m
, cnt
, key
)
555 MARK m
; /* movement is relative to this mark */
556 long cnt
; /* (ignored) */
557 int key
; /* keystroke - the mark to move to */
559 /* mark '' is a special case */
560 if (key
== '\'' || key
== '`')
562 if (mark
[26] == MARK_UNSET
)
572 /* if not a valid mark number, don't move */
573 if (key
< 'a' || key
> 'z')
578 /* return the selected mark -- may be MARK_UNSET */
579 if (!mark
[key
- 'a'])
581 msg("mark '%c is unset", key
);
583 return mark
[key
- 'a'];