/* * 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. Added R.D.R Feb. 1986. */ #include #include #include "ed.h" /* Word wrap or fill wrap depending on f flag value. * 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(f, n) register int f, n; { int oldp; oldp = curwp->w_dotp; if (! backwword(NULL, 1)) /* punctuation marks */ return(FALSE); if (oldp != curwp->w_dotp && curwp->w_doto) { if (! backdel(NULL, 1)) return(FALSE); if (! newline(TRUE, 1)) return(FALSE); } if(f) return(forwwword(NULL, 1)); return(forwwword(NULL, 1) && forwchar(NULL, 1) && backdel(NULL, 1)); } /* FILLPAR Meta command Fill paragraph to specified fill column and indent * column. Bound to M-Q. */ fillpar(f, n) register int f, n; { register int s; register short omo; register LINE *omp; if (n > 1) setfillcol(f, n); if(fillcol == 0) { mlwrite("Fill column not set"); (*term.t_beep)(); return(FALSE); } omp = curwp->w_markp; omo = curwp->w_marko; curwp->w_markp = curwp->w_dotp; curwp->w_marko = curwp->w_doto; gotbop(FALSE, 1); forwchar(FALSE, 1); while((n = ltrw(FALSE, 1)) != EOF && n != NULL) forwline(NULL, 1); gotbop(FALSE, 1); forwchar(FALSE, 1); while (TRUE) { if (llength(curwp->w_dotp) == NULL) break; if (curwp->w_dotp == curbp->b_linep) break; if (getccol(FALSE) > fillcol) { if (wrapword(TRUE, NULL) == FALSE) break; continue; } if (curwp->w_doto == llength(curwp->w_dotp) && getccol(FALSE) <= fillcol) { if (forwchar(FALSE, 1) == FALSE) break; if (curwp->w_dotp == curbp->b_linep) break; /* @ EOB */ if (llength(curwp->w_dotp) == NULL) break; /* @ EOP */ if (backchar(FALSE, 1) == FALSE) break; if (clowsp(FALSE, NULL) == FALSE) break; continue; } if (forwchar(FALSE, 1) == FALSE) break; } curwp->w_dotp = curwp->w_markp; curwp->w_doto = curwp->w_marko; curwp->w_markp = omp; curwp->w_marko = omo; curwp->w_flag |= WFHARD; curgoal = getccol(FALSE); return(TRUE); } /* * PRIVATE VERSION OF INWORD() FOR WRAPWORD(), FORWWORD(), AND BACKWWORD() * Return FALSE if the character at dot * is a space character or above 0x7e. * Otherwise return TRUE. Any printing * character below that is not * a space character may appear inside a * word to be wrapped. Using a special version * of inword() allows us to keep the usual meaning * of word for regular movement. */ static inwword() { register int c; if (curwp->w_doto == llength(curwp->w_dotp)) return (FALSE); c = lgetc(curwp->w_dotp, curwp->w_doto); if (isspace(c) || c> '~') return (FALSE); return (TRUE); } /* * PRIVATE VERSION OF BACKWORD() FOR WRAPWORD() AND FORWWWORD() * Move the cursor backward by * "n" words. All of the details of motion * are performed by the "backchar" and "forwchar" * routines. Error if you try to move beyond * the buffers. */ static backwword(f, n) register int f, n; { if (backchar(FALSE, 1) == FALSE) return (FALSE); while (inwword() == FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); } while (inwword() != FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); } return (forwchar(FALSE, 1)); } /* PRIVATE VERSION OF FORWWORD() FOR WRAPWORD() AND BACKWWORD() * Move the cursor forward by * the specified number of words. All of the * motion is done by "forwchar". Error if you * try and move beyond the buffer's end. */ static forwwword(f, n) register int f, n; { while (inwword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } while (inwword() != FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } return (TRUE); } /* * Move the cursor forward by * the specified number of words. All of the * motion is done by "forwchar". Error if you * try and move beyond the buffer's end. */ forwword(f, n) register int f, n; { if (n < 0) return (backword(f, -n)); while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } return (TRUE); } /* * Move the cursor backward by * "n" words. All of the details of motion * are performed by the "backchar" and "forwchar" * routines. Error if you try to move beyond * the buffers. */ backword(f, n) register int f, n; { if (n < 0) return (forwword(f, -n)); if (backchar(FALSE, 1) == FALSE) return (FALSE); while (n--) { while (inword() == FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); } } return (forwchar(FALSE, 1)); } /* * Move the cursor forward by * the specified number of words. As you move, * convert any characters to upper case. Error * if you try and move beyond the end of the * buffer. Bound to "M-U". */ upperword(f, n) register int f, n; { register int c; if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (islower(c)) { c = toupper(c); lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } return (TRUE); } /* * 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) register int f, n; { register int c; if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (isupper(c)) { c = tolower(c); lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } 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 and move past the end of the buffer. * Bound to "M-C". */ capword(f, n) register int f, n; { register int c; if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); } if (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (islower(c)) { c = toupper(c); lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if (isupper(c)) { c = tolower(c); lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFHARD); } if (forwchar(FALSE, 1) == FALSE) return (FALSE); } } } return (TRUE); } /* * Kill forward by "n" words. * Remember the location of dot. Move forward * by the right number of words. Put dot back where * it was and issue the kill command for the * right number of characters. Bound to "M-D". */ delfword(f, n) register int f, n; { register int size; register LINE *dotp; register int doto; if (n < 0) return (FALSE); dotp = curwp->w_dotp; doto = curwp->w_doto; size = 0; while (n--) { while (inword() == FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); ++size; } while (inword() != FALSE) { if (forwchar(FALSE, 1) == FALSE) return (FALSE); ++size; } } curwp->w_dotp = dotp; curwp->w_doto = doto; return (ldelete(size, TRUE)); } /* * Kill backwards by "n" words. * Move backwards by the desired number of * words, counting the characters. When dot is * finally moved to its resting place, fire off * the kill command. Bound to "M-Rubout" and * to "M-Backspace". */ delbword(f, n) register int f, n; { register int size; if (n < 0) return (FALSE); if (backchar(FALSE, 1) == FALSE) return (FALSE); size = 0; while (n--) { while (inword() == FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); ++size; } while (inword() != FALSE) { if (backchar(FALSE, 1) == FALSE) return (FALSE); ++size; } } if (forwchar(FALSE, 1) == FALSE) return (FALSE); return (ldelete(size, TRUE)); } /* * 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 setable. */ inword() { register int c; if (curwp->w_doto == llength(curwp->w_dotp)) return (FALSE); c = lgetc(curwp->w_dotp, curwp->w_doto); if (isalnum(c)) return (TRUE); if (c=='$' || c=='_') /* For identifiers */ return (TRUE); return (FALSE); } /* FTOPUNCT : eXtended Command Move forward to next punctuation mark. Bound * to CTLX - >. */ ftopunct(f, n) register int f, n; { register int c; do { if(forwchar(FALSE, 1) == FALSE) return(FALSE); c = lgetc(curwp->w_dotp, curwp->w_doto); } while (! ispunct(c) || isspace(c)) ; return(TRUE); } /* BTOPUNCT : eXtended Command Move backward to last punctuation mark. Bound * to CTLX - <. */ btopunct(f, n) register int f, n; { register int c; do { if(backchar(FALSE, 1) == FALSE) return(FALSE); c = lgetc(curwp->w_dotp, curwp->w_doto); } while (! ispunct(c) || isspace(c)) ; return(TRUE); } /* FORWSENT : Meta Command Move forward to end punctuation mark. * A sentence is defined by a full stop followed by white space. * Bound to M-E. */ forwsent(f, n) register int f, n; { register int c; if( n < 0) return(backsent(f, -n)); loop: while(n--) { while(forwchar(FALSE, 1) != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); if(llength(curwp->w_dotp) == NULL) goto loop; if(c=='.' || c=='!' || c=='?') { if (forwchar(FALSE, 1) == FALSE) return(FALSE); c = lgetc(curwp->w_dotp, curwp->w_doto); if (c <= ' ' || c == '\"' || curwp->w_doto == llength(curwp->w_dotp)) goto loop; } } return(FALSE); /* EOF or no sentence terminator found */ } return(TRUE); } /* BACKSENT : Meta Command Move backward to last terminal punctuation mark. * A sentence is defined by a full stop followed by white space. This * function has trouble with some sentences at ends of lines. Bound to * M-A. */ backsent(f, n) register int f, n; { register int c; register int d; if (n < 0) return (forwsent(f, -n)); d = 'a'; /* d must begin as an alpha */ loop: while (n--) { while(backchar(FALSE, 1) != FALSE) { if(llength(curwp->w_dotp) == NULL) goto loop; c = lgetc(curwp->w_dotp, curwp->w_doto); if(c=='.' || c=='?' || c=='!') if (d <= ' ' || d == '\"' || curwp->w_doto+1 == llength(curwp->w_dotp) ) { forwchar(FALSE, 1); goto loop; } d = c; /* d becomes the last fetched char */ } return(FALSE); /* BOF or no sentence terminator found */ } return(TRUE); } /* GOTEOP : META command Goto end of paragraph. Each paragraph is a * block of text bordered by blanklines. Bound to M-N. */ goteop(f, n) register f, n; { if ( n < 0) return(gotbop(f, -n)); while (n) { if (curwp->w_dotp != curbp->b_linep) forwline(NULL, 1); else return(FALSE); if (llength(curwp->w_dotp) == NULL) --n; } return(TRUE); } /* GOTBOP : META command Goto beginning of paragraph. Each paragraph is * a block of text bordered by blanklines. Bound to M-P. */ gotbop(f, n) register f, n; { if ( n < 0) return(goteop(f, -n)); while (n) { if (lback(curwp->w_dotp) != curbp->b_linep) backline(NULL, 1); else return(FALSE); if (llength(curwp->w_dotp) == NULL) --n; } return(TRUE); }