5 * 14407 SW Teal Blvd. #C
11 /* This file contains the functions that handle VI commands */
29 /* This function puts the editor in EX mode */
37 /* This function causes the screen to be redrawn */
40 redraw(MARK_UNSET, FALSE);
44 /* This function executes a single EX command, and waits for a user keystroke
45 * before returning to the VI screen. If that keystroke is another ':', then
46 * another EX command is read and executed.
50 MARK m; /* the current line */
51 char *text; /* the first command to execute */
53 /* run the command. be careful about modes & output */
54 exwrote = (mode == MODE_COLON);
58 /* if mode is no longer MODE_VI, then we should quit right away! */
59 if (mode != MODE_VI && mode != MODE_COLON)
62 /* The command did some output. Wait for a keystoke. */
66 msg("[Hit <RETURN> to continue]");
72 redraw(MARK_UNSET, FALSE);
78 /* This function undoes the last change */
81 MARK m; /* (ignored) */
85 redraw(MARK_UNSET, FALSE);
90 /* This function deletes the character(s) that the cursor is on */
91 MARK v_xchar(m, cnt, cmd)
92 MARK m; /* where to start deletions */
93 long cnt; /* number of chars to delete */
94 int cmd; /* either 'x' or 'X' */
98 /* for 'X', adjust so chars are deleted *BEFORE* cursor */
101 if (markidx(m) < cnt)
106 /* make sure we don't try to delete more thars than there are */
108 if (markidx(m + cnt) > plen)
110 cnt = plen - markidx(m);
126 /* This function defines a mark */
128 MARK v_mark(m, count, key)
129 MARK m; /* where the mark will be */
130 long count; /* (ignored) */
131 int key; /* the ASCII label of the mark */
133 if (key < 'a' || key > 'z')
135 msg("Marks must be from a to z");
144 /* This function toggles upper & lower case letters */
145 MARK v_ulcase(m, cnt)
146 MARK m; /* where to make the change */
147 long cnt; /* number of chars to flip */
152 "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ[](){}<>";
156 /* fetch the current version of the line */
159 /* for each position in the line */
160 for (j = 0, i = markidx(m); j < cnt && ptext[i]; j++, i++)
164 /* one of the standard chars? */
165 for (pos = flip; *pos && *pos != ptext[i]; pos++)
170 tmpblk.c[j] = flip[(int)(pos - flip) ^ 1];
173 else /* one of the non-standard chars? */
175 for (pos = o_flipcase; *pos && *pos != ptext[i]; pos++)
180 tmpblk.c[j] = o_flipcase[(int)(pos - o_flipcase) ^ 1];
185 /* if nothing special, then don't change it */
186 if (tmpblk.c[j] == 0)
188 tmpblk.c[j] = ptext[i];
192 /* if the new text is different from the old, then change it */
193 if (strncmp(tmpblk.c, &ptext[markidx(m)], j))
198 change(m, m + j, tmpblk.c);
206 MARK v_replace(m, cnt, key)
207 MARK m; /* first char to be replaced */
208 long cnt; /* number of chars to replace */
209 int key; /* what to replace them with */
222 /* make sure the resulting line isn't too long */
223 if (cnt > BLKSIZE - 2 - markidx(m))
225 cnt = BLKSIZE - 2 - markidx(m);
228 /* build a string of the desired character with the desired length */
229 for (text = tmpblk.c, i = cnt; i > 0; i--)
235 /* make sure cnt doesn't extend past EOL */
238 if (key + cnt > plen)
243 /* do the replacement */
246 change(m, m + cnt, tmpblk.c);
249 if (*tmpblk.c == '\n')
251 return (m & ~(BLKSIZE - 1)) + cnt * BLKSIZE;
260 MARK m; /* where to start overtyping */
262 MARK end; /* end of a substitution */
263 static long width; /* width of a single-line replace */
265 /* the "doingdot" version of replace is really a substitution */
268 /* was the last one really repeatable? */
271 msg("Can't repeat a multi-line overtype command");
275 /* replacing nothing by nothing? Don't bother */
281 /* replace some chars by repeated text */
282 return v_subst(m, width);
285 /* Normally, we input starting here, in replace mode */
288 end = input(m, m, WHEN_VIREP);
291 /* if we ended on the same line we started on, then this
292 * overtype is repeatable via the dot key.
294 if (markline(end) == markline(m) && end >= m - 1L)
296 width = end - m + 1L;
298 else /* it isn't repeatable */
307 /* This function selects which cut buffer to use */
309 MARK v_selcut(m, cnt, key)
318 /* This function pastes text from a cut buffer */
320 MARK v_paste(m, cnt, cmd)
321 MARK m; /* where to paste the text */
322 long cnt; /* (ignored) */
323 int cmd; /* either 'p' or 'P' */
327 m = paste(m, cmd == 'p', FALSE);
332 /* This function yanks text into a cut buffer */
334 MARK m, n; /* range of text to yank */
340 /* This function deletes a range of text */
342 MARK m, n; /* range of text to delete */
344 /* illegal to try and delete nothing */
360 /* This starts input mode without deleting anything */
361 MARK v_insert(m, cnt, key)
362 MARK m; /* where to start (sort of) */
363 long cnt; /* repeat how many times? */
364 int key; /* what command is this for? {a,A,i,I,o,O} */
368 int after; /* are we appending or inserting? */
374 /* tweak the insertion point, based on command key */
397 m = (m & ~(BLKSIZE - 1)) + plen;
408 m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
414 /* insert the same text once or more */
415 for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
417 m = input(m, m, WHEN_VIINP);
432 # ifndef NO_EXTENSIONS
433 if (key == 'i' && *o_inputmode && mode == MODE_VI)
435 msg("Now in visual command mode! To return to input mode, hit <i>.");
443 /* This starts input mode with some text deleted */
445 MARK m, n; /* the range of text to change */
447 int lnmode; /* is this a line-mode change? */
449 /* swap them if they're in reverse order */
458 /* for line mode, retain the last newline char */
459 lnmode = (markidx(m) == 0 && markidx(n) == 0 && m != n);
464 n = (n & ~(BLKSIZE - 1)) + plen;
470 m = input(m, n, WHEN_VIINP);
476 /* This function replaces a given number of characters with input */
478 MARK m; /* where substitutions start */
479 long cnt; /* number of chars to replace */
483 /* make sure we don't try replacing past EOL */
485 if (markidx(m) + cnt > plen)
487 cnt = plen - markidx(m);
494 m = input(m, m + cnt, WHEN_VIINP);
499 /* This calls the ex "join" command to join some lines together */
501 MARK m; /* the first line to be joined */
502 long cnt; /* number of other lines to join */
504 MARK joint; /* where the lines were joined */
508 /* figure out where the joint will be */
510 joint = (m & ~(BLKSIZE - 1)) + plen;
513 cmd_join(m, m + MARK_AT_LINE(cnt), CMD_JOIN, 0, "");
516 /* the cursor should be left at the joint */
520 /* This calls the ex shifter command to shift some lines */
521 static MARK shift_help(m, n, excmd)
522 MARK m, n; /* range of lines to shift */
523 CMD excmd; /* which way do we shift? */
525 /* adjust for inclusive endmarks in ex */
528 cmd_shift(m, n, excmd, 0, "");
532 /* This calls the ex "<" command to shift some lines left */
534 MARK m, n; /* range of lines to shift */
536 return shift_help(m, n, CMD_SHIFTL);
539 /* This calls the ex ">" command to shift some lines right */
541 MARK m, n; /* range of lines to shift */
543 return shift_help(m, n, CMD_SHIFTR);
546 /* This runs some lines through a filter program */
548 MARK m, n; /* range of lines to shift */
550 char cmdln[100]; /* a shell command line */
552 /* adjust for inclusive endmarks in ex */
555 if (vgets('!', cmdln, sizeof(cmdln)) > 0)
560 redraw(MARK_UNSET, FALSE);
565 /* This function runs the ex "file" command to show the file's status */
568 cmd_file(cursor, cursor, CMD_FILE, 0, "");
573 /* This function runs the ":&" command to repeat the previous :s// */
577 cmd_substitute(m, n - BLKSIZE, CMD_SUBAGAIN, TRUE, "");
583 /* This function switches to the previous file, if possible */
587 msg("No previous file");
589 { strcpy(tmpblk.c, prevorig);
590 cmd_edit(cursor, cursor, CMD_EDIT, 0, tmpblk.c);
595 /* This function does a tag search on a keyword */
597 MARK v_tag(keyword, m, cnt)
602 /* move the cursor to the start of the tag name, where m is */
605 /* perform the tag search */
606 cmd_tag(cursor, cursor, CMD_TAG, 0, keyword);
611 #ifndef NO_EXTENSIONS
612 /* This function looks up a keyword by calling the helpprog program */
614 MARK v_keyword(keyword, m, cnt)
623 addstr("---------------------------------------------------------\n");
626 sprintf(cmdline, "%s %s", o_keywordprg, keyword);
632 addstr("<<< failed >>>\n");
634 resume_curses(FALSE);
636 redraw(MARK_UNSET, FALSE);
644 MARK v_increment(keyword, m, cnt)
655 /* get one more keystroke, unless doingdot */
661 /* adjust the number, based on that second keystroke */
666 cnt = atol(keyword) + cnt;
670 cnt = atol(keyword) - cnt;
679 sprintf(newval, "%ld", cnt);
683 change(m, m + strlen(keyword), newval);
691 /* This function acts like the EX command "xit" */
693 MARK v_xit(m, cnt, key)
694 MARK m; /* ignored */
695 long cnt; /* ignored */
696 int key; /* must be a second 'Z' */
698 /* if second char wasn't 'Z', fail */
704 /* move the cursor to the bottom of the screen */
708 /* do the xit command */
709 cmd_xit(m, m, CMD_XIT, FALSE, "");
711 /* return the cursor */
716 /* This function undoes changes to a single line, if possible */
718 MARK m; /* where we hope to undo the change */
720 /* make sure we have the right line in the buffer */
721 if (markline(m) != U_line)
729 strcat(U_text, "\n");
730 change(MARK_AT_LINE(U_line), MARK_AT_LINE(U_line + 1), U_text);
733 /* nothing in the buffer anymore */
736 /* return, with the cursor at the front of the line */
737 return m & ~(BLKSIZE - 1);
745 cmd_errlist(m, m, CMD_ERRLIST, FALSE, "");
753 MARK v_at(m, cnt, key)
758 if (!fromcutbuf(key))