X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;ds=sidebyside;f=mg%2Fword.c;fp=mg%2Fword.c;h=c18b620e672dcb074191d80b8c27da620f33d590;hb=a9843085ec916c175bd245a8398f30e6cc03f984;hp=0000000000000000000000000000000000000000;hpb=26fe4e09c6c3c250334fdeed60ce3061febecde2;p=pd_readline diff --git a/mg/word.c b/mg/word.c new file mode 100644 index 0000000..c18b620 --- /dev/null +++ b/mg/word.c @@ -0,0 +1,346 @@ +/* $OpenBSD: word.c,v 1.15 2008/09/15 16:11:35 kjell Exp $ */ + +/* This file is in the public domain. */ + +/* + * Word mode commands. + * The routines in this file implement commands that work word at a time. + * There are all sorts of word mode commands. + */ + +#include "def.h" + +RSIZE countfword(void); + +/* + * Move the cursor backward by "n" words. All of the details of motion are + * performed by the "backchar" and "forwchar" routines. + */ +/* ARGSUSED */ +int +backword(int f, int n) +{ + if (n < 0) + return (forwword(f | FFRAND, -n)); + if (backchar(FFRAND, 1) == FALSE) + return (FALSE); + while (n--) { + while (inword() == FALSE) { + if (backchar(FFRAND, 1) == FALSE) + return (TRUE); + } + while (inword() != FALSE) { + if (backchar(FFRAND, 1) == FALSE) + return (TRUE); + } + } + return (forwchar(FFRAND, 1)); +} + +/* + * Move the cursor forward by the specified number of words. All of the + * motion is done by "forwchar". + */ +/* ARGSUSED */ +int +forwword(int f, int n) +{ + if (n < 0) + return (backword(f | FFRAND, -n)); + while (n--) { + while (inword() == FALSE) { + if (forwchar(FFRAND, 1) == FALSE) + return (TRUE); + } + while (inword() != FALSE) { + if (forwchar(FFRAND, 1) == FALSE) + return (TRUE); + } + } + return (TRUE); +} + +/* + * Move the cursor forward by the specified number of words. As you move, + * convert any characters to upper case. + */ +/* ARGSUSED */ +int +upperword(int f, int n) +{ + int c, s; + RSIZE size; + + if ((s = checkdirty(curbp)) != TRUE) + return (s); + if (curbp->b_flag & BFREADONLY) { + ewprintf("Buffer is read-only"); + return (FALSE); + } + + if (n < 0) + return (FALSE); + while (n--) { + while (inword() == FALSE) { + if (forwchar(FFRAND, 1) == FALSE) + return (TRUE); + } + size = countfword(); + undo_add_change(curwp->w_dotp, curwp->w_doto, size); + + while (inword() != FALSE) { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (ISLOWER(c) != FALSE) { + c = TOUPPER(c); + lputc(curwp->w_dotp, curwp->w_doto, c); + lchange(WFFULL); + } + if (forwchar(FFRAND, 1) == FALSE) + return (TRUE); + } + } + return (TRUE); +} + +/* + * Move the cursor forward by the specified number of words. As you move + * convert characters to lower case. + */ +/* ARGSUSED */ +int +lowerword(int f, int n) +{ + int c, s; + RSIZE size; + + if ((s = checkdirty(curbp)) != TRUE) + return (s); + if (curbp->b_flag & BFREADONLY) { + ewprintf("Buffer is read-only"); + return (FALSE); + } + if (n < 0) + return (FALSE); + while (n--) { + while (inword() == FALSE) { + if (forwchar(FFRAND, 1) == FALSE) + return (TRUE); + } + size = countfword(); + undo_add_change(curwp->w_dotp, curwp->w_doto, size); + + while (inword() != FALSE) { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (ISUPPER(c) != FALSE) { + c = TOLOWER(c); + lputc(curwp->w_dotp, curwp->w_doto, c); + lchange(WFFULL); + } + if (forwchar(FFRAND, 1) == FALSE) + return (TRUE); + } + } + return (TRUE); +} + +/* + * Move the cursor forward by the specified number of words. As you move + * convert the first character of the word to upper case, and subsequent + * characters to lower case. Error if you try to move past the end of the + * buffer. + */ +/* ARGSUSED */ +int +capword(int f, int n) +{ + int c, s; + RSIZE size; + + if ((s = checkdirty(curbp)) != TRUE) + return (s); + if (curbp->b_flag & BFREADONLY) { + ewprintf("Buffer is read-only"); + return (FALSE); + } + + if (n < 0) + return (FALSE); + while (n--) { + while (inword() == FALSE) { + if (forwchar(FFRAND, 1) == FALSE) + return (TRUE); + } + size = countfword(); + undo_add_change(curwp->w_dotp, curwp->w_doto, size); + + if (inword() != FALSE) { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (ISLOWER(c) != FALSE) { + c = TOUPPER(c); + lputc(curwp->w_dotp, curwp->w_doto, c); + lchange(WFFULL); + } + if (forwchar(FFRAND, 1) == FALSE) + return (TRUE); + while (inword() != FALSE) { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (ISUPPER(c) != FALSE) { + c = TOLOWER(c); + lputc(curwp->w_dotp, curwp->w_doto, c); + lchange(WFFULL); + } + if (forwchar(FFRAND, 1) == FALSE) + return (TRUE); + } + } + } + return (TRUE); +} + +/* + * Count characters in word, from current position + */ +RSIZE +countfword() +{ + RSIZE size; + struct line *dotp; + int doto; + + dotp = curwp->w_dotp; + doto = curwp->w_doto; + size = 0; + + while (inword() != FALSE) { + if (forwchar(FFRAND, 1) == FALSE) + /* hit the end of the buffer */ + goto out; + ++size; + } +out: + curwp->w_dotp = dotp; + curwp->w_doto = doto; + return (size); +} + + +/* + * Kill forward by "n" words. + */ +/* ARGSUSED */ +int +delfword(int f, int n) +{ + RSIZE size; + struct line *dotp; + int doto; + int s; + + if ((s = checkdirty(curbp)) != TRUE) + return (s); + if (curbp->b_flag & BFREADONLY) { + ewprintf("Buffer is read-only"); + return (FALSE); + } + if (n < 0) + return (FALSE); + + /* purge kill buffer */ + if ((lastflag & CFKILL) == 0) + kdelete(); + + thisflag |= CFKILL; + dotp = curwp->w_dotp; + doto = curwp->w_doto; + size = 0; + + while (n--) { + while (inword() == FALSE) { + if (forwchar(FFRAND, 1) == FALSE) + /* hit the end of the buffer */ + goto out; + ++size; + } + while (inword() != FALSE) { + if (forwchar(FFRAND, 1) == FALSE) + /* hit the end of the buffer */ + goto out; + ++size; + } + } +out: + curwp->w_dotp = dotp; + curwp->w_doto = doto; + return (ldelete(size, KFORW)); +} + +/* + * Kill backwards by "n" words. The rules for success and failure are now + * different, to prevent strange behavior at the start of the buffer. The + * command only fails if something goes wrong with the actual delete of the + * characters. It is successful even if no characters are deleted, or if you + * say delete 5 words, and there are only 4 words left. I considered making + * the first call to "backchar" special, but decided that that would just be + * weird. Normally this is bound to "M-Rubout" and to "M-Backspace". + */ +/* ARGSUSED */ +int +delbword(int f, int n) +{ + RSIZE size; + int s; + + if ((s = checkdirty(curbp)) != TRUE) + return (s); + if (curbp->b_flag & BFREADONLY) { + ewprintf("Buffer is read-only"); + return (FALSE); + } + + if (n < 0) + return (FALSE); + + /* purge kill buffer */ + if ((lastflag & CFKILL) == 0) + kdelete(); + thisflag |= CFKILL; + if (backchar(FFRAND, 1) == FALSE) + /* hit buffer start */ + return (TRUE); + + /* one deleted */ + size = 1; + while (n--) { + while (inword() == FALSE) { + if (backchar(FFRAND, 1) == FALSE) + /* hit buffer start */ + goto out; + ++size; + } + while (inword() != FALSE) { + if (backchar(FFRAND, 1) == FALSE) + /* hit buffer start */ + goto out; + ++size; + } + } + if (forwchar(FFRAND, 1) == FALSE) + return (FALSE); + + /* undo assumed delete */ + --size; +out: + return (ldelete(size, KBACK)); +} + +/* + * Return TRUE if the character at dot is a character that is considered to be + * part of a word. The word character list is hard coded. Should be settable. + */ +int +inword(void) +{ + /* can't use lgetc in ISWORD due to bug in OSK cpp */ + return (curwp->w_doto != llength(curwp->w_dotp) && + ISWORD(curwp->w_dotp->l_text[curwp->w_doto])); +}