home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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.
- */
-
- #include <stdio.h>
- #include "ed.h"
-
- #define WPNULL -1 /* null word pointer */
-
- /* Paragraph fill. Retain indenting of first line of paragraph. Remove
- * leading spaces from other lines. Remove extra space between words.
- * Fill each line to fillcol, breaking at word boundaries.
- * Delete trailing space from all lines.
- */
- parafill( f, n)
- {
- register int c; /* current char */
- register short spo; /* space offset */
- register short count;
- short wo; /* word offset */
- WINDOW *wp;
- LINE *flp, /* first line of paragraph */
- *clp; /* current line of paragraph */
-
- /* save old context */
- /* we do this by creating a fake window which retains the context.
- * this will be updated by the editing commands.
- */
- if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
- mlwrite("Cannot allocate WINDOW block");
- return (FALSE);
- }
- wp->w_bufp = curbp;
- wp->w_dotp = curwp->w_dotp;
- wp->w_doto = curwp->w_doto;
- wp->w_markp = curwp->w_markp;
- wp->w_marko = curwp->w_marko;
- wp->w_flag = 0;
- wp->w_force = 0;
- wp->w_wndp = wheadp;
- wheadp = wp;
-
- /* get first line of paragraph */
-
- for( flp = curwp->w_dotp; flp != curbp->b_linep; flp = lback( flp)) {
- if( llength( flp) == 0) /* blank line, found it */
- break;
- }
- flp = lforw( flp);
- if( llength( flp) == 0) /* nothing to do */
- return( TRUE);
-
- /* initialize */
- count = 0;
- curwp->w_dotp = clp = flp;
-
- for(;;) { /* go through all lines */
- spo = count; /* set space offset at current spot */
-
- /* get to end of spaces */
- for( ;; count++) {
- c = wgetc( &clp, count);
- if( (c != ' ') || (c == EOF)) break;
- }
- wo = count;
-
- /* get to end of word */
- for( ;; count++) {
- c = wgetc( &clp, count);
- if( (c == ' ') || (c == EOF)) break;
- }
-
- if(((clp != flp) || spo) && (spo != wo)) {
- /* adjust spaces. if at beginning of line, delete all spaces */
- curwp->w_doto = spo;
- if( spo) { /* past begin of line */
- count += adjsp( &clp, spo, &wo);
- } else { /* at begin of line */
- ldelete( wo - spo, FALSE);
- wo = count = 0;
- }
- }
-
- if( count > fillcol) { /* if past fill column, break. */
- if(((clp != flp) || spo) && (spo != wo)) {
- /* collapse the spaces */
- curwp->w_doto = spo;
- ldelete( wo - spo, FALSE);
- wo = spo;
- }
- if( wo > 0) { /* break at beginning of word */
- curwp->w_doto = wo;
- } else { /* break at end of word */
- curwp->w_doto = count;
- }
- newline( FALSE, 1);
- count = 0;
- clp = curwp->w_dotp; /* updated by newline */
- }
- if( c == EOF) break;
- }
- /* restore context and delete fake window */
- curwp->w_dotp = wp->w_dotp;
- curwp->w_doto = wp->w_doto;
- curwp->w_markp = wp->w_markp;
- curwp->w_marko = wp->w_marko;
- wheadp = wp->w_wndp;
- free( (char *) wp);
-
- return( TRUE);
- }
-
- /* adjust the spacing between words. check for colons and periods.
- * assumes spo > 0 and doto is set to spo.
- */
- adjsp( lp, spo, wo)
- register LINE **lp;
- register short spo, *wo;
- {
- short result, spaces, n, c;
-
- /* decide on number of spaces */
- switch( lgetc( *lp, spo -1)) {
- case ':':
- spaces = 2;
- break;
-
- case '.':
- spaces = 1; /* just a guess */
- n = spo -2;
- if( n == 0) /* period at beginning of line */
- break;
- else {
- c = lgetc( *lp, n);
- if((('a' <= c) && (c <= 'z'))
- || (('A' <= c) && (c <= 'Z'))) { /* letter */
- n -= 1;
- if( n == 0) /* single letter followed by . */
- break;
- else {
- c = lgetc( *lp, n);
- if((c == ' ')
- || (c == '.'))/* single letter followed by . */
- break;
- }
- } else /* not a letter */
- break;
- }
- if( *wo < llength( *lp)) {
- c = lgetc( *lp, *wo);
- if((c < 'A') || ('Z' < c)) /* not a cap letter */
- break;
- }
- spaces = 2;
- break;
-
- default:
- spaces = 1;
- break;
- }
-
- /* adjust them */
- if( (*wo - spo) == spaces) /* perfect */
- return( 0);
- else if( (*wo - spo) > spaces) { /* delete extras */
- result = *wo - spo - spaces;
- ldelete( result, FALSE);
- result = - result;
- } else { /* pad with spaces */
- result = spaces - (*wo - spo);
- linsert( result, ' ');
- }
- *lp = curwp->w_dotp;
- *wo = spo + spaces;
- return( result);
- }
-
- /* Get next char, word-oriented style. If at end of line, append next
- * line by replacing newline with a space. Return EOF
- * when there is nothing left.
- */
- wgetc( clp, n)
- LINE **clp;
- int n;
- {
- LINE *newlp;
-
- if( n > llength( *clp)) {
- mlwrite( "Bad para fill");
- return( EOF);
- }
- if( n == llength( *clp)) {
- newlp = lforw( *clp);
- if( llength( newlp) == 0) return( EOF);
- curwp->w_doto = n;
- ldelete( 1, FALSE);
- linsert( 1, ' ');
- *clp = curwp->w_dotp;
- }
- return( lgetc( *clp, n));
- }
-
- /* Break line on spaces. Back-over whatever precedes the point on the current
- * line and stop on the first space or the beginning of the line. If we
- * reach the beginning of the line, do nothing.
- * Otherwise, break the line at the space, eat previous spaces, and jump
- * back to the end of the word.
- * Returns TRUE on success, FALSE on errors.
- */
- wrapword()
- {
- register int wo, spo, oldo;
- LINE *oldp;
-
- oldp = curwp->w_dotp;
- oldo = curwp->w_doto;
- for( spo = oldo; spo > 0; --spo) {
- if( lgetc( oldp, spo) == ' ') break;
- }
- if( spo) wo = spo + 1; /* wo points at start of word */
- else /* can't do it */
- return( FALSE);
- for( ; spo > 0; --spo) {
- if( lgetc( oldp, spo) != ' ') break;
- }
- if( spo) spo = spo + 1; /* spo points at start of spaces */
- else /* can't do it */
- return( FALSE);
-
- /* delete spaces and insert new line */
- curwp->w_doto = spo;
- forwdel( FALSE, wo - spo);
- newline( FALSE, 1);
-
- if( oldo > spo) /* adjust point */
- curwp->w_doto = oldo - wo;
-
- 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)
- {
- 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. All of the motion
- * is done by "forwchar". Error if you try and move beyond the buffer's end.
- */
- forwword(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 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 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 (c>='a' && c<='z') {
- c -= 'a'-'A';
- 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 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 (c>='A' && c<='Z') {
- c += 'a'-'A';
- 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 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 (c>='a' && c<='z') {
- c -= 'a'-'A';
- 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 (c>='A' && c<='Z') {
- c += 'a'-'A';
- 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 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 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 (c>='a' && c<='z')
- return (TRUE);
- if (c>='A' && c<='Z')
- return (TRUE);
- if (c>='0' && c<='9')
- return (TRUE);
- if (c=='$' || c=='_') /* For identifiers */
- return (TRUE);
- return (FALSE);
- }
-
-