static char rcsid[] = "$Id: word.c,v 1.1 1992/09/05 01:13:32 mike Exp $"; /* $Log: word.c,v $ * Revision 1.1 1992/09/05 01:13:32 mike * Initial revision * */ /* * * WORD.C MODULE * * The routines in this file implement commands that work word at a time. * There are all sorts of word mode commands. If I do any sentence and/or * paragraph mode commands, they are likely to be put in this file. */ /* Copyright 1990, 1991, 1992 Craig Durland * Distributed under the terms of the GNU General Public License. * Distributed "as is", without warranties of any kind, but comments, * suggestions and bug reports are welcome. */ #include #include "me2.h" static int inword(); /* Word wrap: Special case for typing in text. * The following must be true: At end of line. * Back-over whatever precedes the point on the current line and stop on the * first word-break or the beginning of the line. If we reach the * beginning of the line, jump back to the end of the word and start a new * line. Otherwise, break the line at the word-break, eat it, and jump * back to the end of the word. * Returns TRUE on success, FALSE on errors. */ wrapword() { register int i; int s; Line *line; line = the_dot->line; i = llength(line) -1; while (i >= 0 && !isspace(lgetc(line,i))) i--; /* backup over word */ if (i < 0) return FALSE; /* no white space */ while (i >= 0 && isspace(lgetc(line,i))) i--; /* backup over white space */ the_dot->offset = i +1; /* set cursor between words */ run_key((KeyCode)(CTRL|'M'), FALSE,1, &s); /* del leading ws */ while (the_dot->offset < llength(the_dot->line) && isspace(lgetc(the_dot->line,the_dot->offset))) ldelete((int32)1,FALSE); goto_EoL(FALSE,1); return TRUE; } /* Move over words. If n is less than zero, move backwords. * Input: * nwords: number of words to move over. * n : pointer to a int. * Output: * n : number of characters moved over. Only valid if TRUE is * returned. * Returns: * TRUE: Everything went as expected. * FALSE: Hit the end or begining of the buffer before moved over * nwords. */ static int next_word(nwords,n) int nwords, *n; { int x = 0, tick = 1, backwards = FALSE; if (nwords == 0) { *n = 0; return TRUE; } /* easy to move over no words */ if (nwords < 0) { backwards = TRUE; tick = -1; nwords = -nwords; if (!next_character(-1)) return FALSE; } while (nwords--) { while (!inword()) /* move over white space */ { if (!next_character(tick)) return FALSE; x++; } while (inword()) /* move over word */ { if (!next_character(tick)) /* hit buffer edge */ { *n = x; return (nwords == 0); /* OK if last word butts upto edge */ } x++; } } *n = x; if (backwards) return next_character(1); return TRUE; } /* * Move the cursor forward by the specified number of words. * Error if you try and move beyond the buffer's end. */ forwword(f,n) int f,n; { return next_word(n,&n); } /* * Move the cursor backward by n words. * Returns: * TRUE: OK * FALSE: stuck at the start of the buffer. */ backword(f,n) int f,n; { return next_word(-n,&n); } /* Delete n words starting from the dot. If n is less than zero, delete * backwards. * To delete forward: Remember the location of dot. Move forward by the * right number of words. Put dot back where it was and delete the * right number of characters. * To delete backwards: Move backwards by the desired number of words, * counting the characters. When dot is finally moved to its resting * place, fire off the delete characters command. * The deleted words are put into the cut buffer. */ delete_words(n) int n; { if (n == 0) return TRUE; /* delete no words */ if (n < 0) /* delete back words */ { if (!next_word(n,&n)) return FALSE; } else /* delete fore words */ { register Mark save_dot; save_dot = *the_dot; if (!next_word(n,&n)) return FALSE; *the_dot = save_dot; } if (!(lastflag & CFCUT)) clear_bag(cut_buffer); thisflag |= CFCUT; return ldelete((int32)n,TRUE); } /* * Delete forward by n words. * Bound to "M-d". */ delfword(f,n) int f,n; { return delete_words(n); } /* * Delete backwards by n words. * Bound to "M-Rubout" and to "M-Backspace". */ delbword(f,n) int f,n; { return delete_words(-n); } /* * Return TRUE if the character at dot is a character that is considered to be * part of a word. */ static int inword() { if (the_dot->offset == llength(the_dot->line)) return FALSE; return (int)isword(lgetc(the_dot->line, the_dot->offset)); } #if 0 /* Munge n words. Only works in the forward direction. * Input: * n : number of words to munge. * munge_char : a pointer to a routine that munges a character. It is * called like so: munge_char(c,flag,start_word) where c is the * character to munge, flag is described below, start_word is TRUE if * c is the first character of a word. munge_char() return a char to * replace c with. * flag: a arbitrary int passed to munge_char(). * Output: * Munged chars. * Returns: * TRUE : OK * FALSE : Hit end of buffer. */ static int munge_word(n,munge_char,flag) int n; char (*munge_char)(); int flag; { register unsigned char c; register int start_word; if (n < 0) return FALSE; lchange(WFHARD); /* assume lines are going to change */ while (n--) { while (!inword()) if (!next_character(1)) return FALSE; start_word = TRUE; do { lputc(the_dot->line,the_dot->offset, (*munge_char) (lgetc(the_dot->line,the_dot->offset), flag, start_word)); start_word = FALSE; if (!next_character(1)) return FALSE; } while (inword()); } return TRUE; } static char casechar(c,lower,ignore) char c; int lower, ignore; { return (lower ? tolower(c) : toupper(c)); } static char capchar(c,ignore,start_word) char c; int ignore, start_word; { return (start_word ? toupper(c) : tolower(c)); } /* * Move the cursor forward by the specified number of words. As you move * convert characters to lower case. Error if you try and move over the * end of the buffer. * Bound to "M-l". */ lowerword(f,n) { return munge_word(n,casechar,TRUE); } /* * Move the cursor forward by the specified number of words. As you move, * convert any characters to uppercase. Error if you try and move beyond * the end of the buffer. * Bound to "M-u". */ upperword(f,n) { return munge_word(n,casechar,FALSE); } /* * 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 and move past the end of * the buffer. * Bound to "M-c". */ capword(f,n) int f,n; { return munge_word(n,capchar,TRUE); } #endif