[BACK]Return to paragraph.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/paragraph.c, Revision 1.37

1.37    ! lum         1: /*     $OpenBSD: paragraph.c,v 1.36 2015/03/19 21:22:15 bcallah Exp $  */
1.11      kjell       2:
                      3: /* This file is in the public domain. */
1.4       niklas      4:
1.1       deraadt     5: /*
                      6:  * Code for dealing with paragraphs and filling. Adapted from MicroEMACS 3.6
                      7:  * and GNU-ified by mwm@ucbvax.         Several bug fixes by blarson@usc-oberon.
                      8:  */
1.3       millert     9:
1.36      bcallah    10: #include <sys/queue.h>
1.24      lum        11: #include <ctype.h>
1.35      guenther   12: #include <limits.h>
1.36      bcallah    13: #include <signal.h>
                     14: #include <stdio.h>
                     15: #include <stdlib.h>
1.24      lum        16:
1.1       deraadt    17: #include "def.h"
                     18:
1.3       millert    19: static int     fillcol = 70;
                     20:
1.1       deraadt    21: #define MAXWORD 256
                     22:
1.37    ! lum        23: static int     findpara(void);
        !            24:
1.1       deraadt    25: /*
1.27      lum        26:  * Move to start of paragraph.
                     27:  * Move backwards by line, checking from the 1st character forwards for the
                     28:  * existence a non-space. If a non-space character is found, move to the
                     29:  * preceding line. Keep doing this until a line with only spaces is found or
                     30:  * the start of buffer.
1.1       deraadt    31:  */
1.2       millert    32: /* ARGSUSED */
1.3       millert    33: int
1.8       cloder     34: gotobop(int f, int n)
1.1       deraadt    35: {
1.26      lum        36:        int col, nospace;
1.24      lum        37:
1.3       millert    38:        /* the other way... */
                     39:        if (n < 0)
1.10      db         40:                return (gotoeop(f, -n));
1.1       deraadt    41:
1.3       millert    42:        while (n-- > 0) {
1.31      florian    43:                nospace = 0;
1.24      lum        44:                while (lback(curwp->w_dotp) != curbp->b_headp) {
                     45:                        curwp->w_doto = 0;
                     46:                        col = 0;
                     47:
                     48:                        while (col < llength(curwp->w_dotp) &&
                     49:                            (isspace(lgetc(curwp->w_dotp, col))))
                     50:                                col++;
                     51:
                     52:                        if (col >= llength(curwp->w_dotp)) {
                     53:                                if (nospace)
                     54:                                        break;
                     55:                        } else
                     56:                                nospace = 1;
1.32      lum        57:
                     58:                        curwp->w_dotline--;
                     59:                        curwp->w_dotp = lback(curwp->w_dotp);
1.24      lum        60:                }
1.1       deraadt    61:        }
1.3       millert    62:        /* force screen update */
1.19      kjell      63:        curwp->w_rflag |= WFMOVE;
1.10      db         64:        return (TRUE);
1.1       deraadt    65: }
                     66:
                     67: /*
1.27      lum        68:  * Move to end of paragraph.
                     69:  * See comments for gotobop(). Same, but moving forwards.
1.1       deraadt    70:  */
1.2       millert    71: /* ARGSUSED */
1.3       millert    72: int
1.8       cloder     73: gotoeop(int f, int n)
1.1       deraadt    74: {
1.26      lum        75:        int col, nospace;
1.25      lum        76:
1.3       millert    77:        /* the other way... */
                     78:        if (n < 0)
1.10      db         79:                return (gotobop(f, -n));
1.1       deraadt    80:
1.3       millert    81:        /* for each one asked for */
                     82:        while (n-- > 0) {
1.31      florian    83:                nospace = 0;
1.25      lum        84:                while (lforw(curwp->w_dotp) != curbp->b_headp) {
                     85:                        col = 0;
                     86:                        curwp->w_doto = 0;
                     87:
                     88:                        while (col < llength(curwp->w_dotp) &&
                     89:                            (isspace(lgetc(curwp->w_dotp, col))))
                     90:                                col++;
                     91:
                     92:                        if (col >= llength(curwp->w_dotp)) {
                     93:                                if (nospace)
                     94:                                        break;
1.23      lum        95:                        } else
1.25      lum        96:                                nospace = 1;
                     97:
                     98:                        curwp->w_dotp = lforw(curwp->w_dotp);
                     99:                        curwp->w_dotline++;
1.34      lum       100:
                    101:                        /* do not continue after end of buffer */
                    102:                        if (lforw(curwp->w_dotp) == curbp->b_headp) {
                    103:                                gotoeol(FFRAND, 1);
                    104:                                curwp->w_rflag |= WFMOVE;
                    105:                                return (FALSE);
                    106:                        }
1.1       deraadt   107:                }
                    108:        }
1.33      lum       109:
1.3       millert   110:        /* force screen update */
1.19      kjell     111:        curwp->w_rflag |= WFMOVE;
1.10      db        112:        return (TRUE);
1.1       deraadt   113: }
                    114:
                    115: /*
1.6       mickey    116:  * Justify a paragraph.  Fill the current paragraph according to the current
1.3       millert   117:  * fill column.
1.1       deraadt   118:  */
1.2       millert   119: /* ARGSUSED */
1.3       millert   120: int
1.8       cloder    121: fillpara(int f, int n)
1.1       deraadt   122: {
1.10      db        123:        int      c;             /* current char during scan             */
1.3       millert   124:        int      wordlen;       /* length of current word               */
                    125:        int      clength;       /* position on line during fill         */
                    126:        int      i;             /* index during word copy               */
                    127:        int      eopflag;       /* Are we at the End-Of-Paragraph?      */
                    128:        int      firstflag;     /* first word? (needs no space)         */
                    129:        int      newlength;     /* tentative new line length            */
                    130:        int      eolflag;       /* was at end of line                   */
1.12      kjell     131:        int      retval;        /* return value                         */
1.13      deraadt   132:        struct line     *eopline;       /* pointer to line just past EOP        */
1.3       millert   133:        char     wbuf[MAXWORD]; /* buffer for current word              */
1.1       deraadt   134:
1.17      kjell     135:        undo_boundary_enable(FFRAND, 0);
1.12      kjell     136:
1.1       deraadt   137:        /* record the pointer to the line just past the EOP */
1.5       art       138:        (void)gotoeop(FFRAND, 1);
1.2       millert   139:        if (curwp->w_doto != 0) {
1.1       deraadt   140:                /* paragraph ends at end of buffer */
1.5       art       141:                (void)lnewline();
1.1       deraadt   142:                eopline = lforw(curwp->w_dotp);
1.2       millert   143:        } else
                    144:                eopline = curwp->w_dotp;
1.1       deraadt   145:
                    146:        /* and back top the begining of the paragraph */
1.5       art       147:        (void)gotobop(FFRAND, 1);
1.1       deraadt   148:
                    149:        /* initialize various info */
1.9       avsm      150:        while (inword() == 0 && forwchar(FFRAND, 1));
1.3       millert   151:
1.1       deraadt   152:        clength = curwp->w_doto;
                    153:        wordlen = 0;
                    154:
                    155:        /* scan through lines, filling words */
                    156:        firstflag = TRUE;
                    157:        eopflag = FALSE;
                    158:        while (!eopflag) {
1.3       millert   159:
1.1       deraadt   160:                /* get the next character in the paragraph */
1.3       millert   161:                if ((eolflag = (curwp->w_doto == llength(curwp->w_dotp)))) {
1.1       deraadt   162:                        c = ' ';
                    163:                        if (lforw(curwp->w_dotp) == eopline)
                    164:                                eopflag = TRUE;
                    165:                } else
                    166:                        c = lgetc(curwp->w_dotp, curwp->w_doto);
                    167:
                    168:                /* and then delete it */
1.12      kjell     169:                if (ldelete((RSIZE) 1, KNONE) == FALSE && !eopflag) {
                    170:                        retval = FALSE;
                    171:                        goto cleanup;
                    172:                }
1.1       deraadt   173:
                    174:                /* if not a separator, just add it in */
                    175:                if (c != ' ' && c != '\t') {
                    176:                        if (wordlen < MAXWORD - 1)
                    177:                                wbuf[wordlen++] = c;
                    178:                        else {
1.2       millert   179:                                /*
1.21      matthew   180:                                 * You lose chars beyond MAXWORD if the word
                    181:                                 * is too long. I'm too lazy to fix it now; it
1.2       millert   182:                                 * just silently truncated the word before,
                    183:                                 * so I get to feel smug.
1.1       deraadt   184:                                 */
                    185:                                ewprintf("Word too long!");
                    186:                        }
                    187:                } else if (wordlen) {
1.3       millert   188:
1.10      db        189:                        /* calculate tentative new length with word added */
1.1       deraadt   190:                        newlength = clength + 1 + wordlen;
1.3       millert   191:
1.2       millert   192:                        /*
                    193:                         * if at end of line or at doublespace and previous
1.1       deraadt   194:                         * character was one of '.','?','!' doublespace here.
1.20      lum       195:                         * behave the same way if a ')' is preceded by a
                    196:                         * [.?!] and followed by a doublespace.
1.1       deraadt   197:                         */
1.6       mickey    198:                        if ((eolflag ||
                    199:                            curwp->w_doto == llength(curwp->w_dotp) ||
1.3       millert   200:                            (c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' '
1.20      lum       201:                            || c == '\t') && (ISEOSP(wbuf[wordlen - 1]) ||
1.22      lum       202:                            (wbuf[wordlen - 1] == ')' && wordlen >= 2 &&
1.20      lum       203:                            ISEOSP(wbuf[wordlen - 2]))) &&
1.3       millert   204:                            wordlen < MAXWORD - 1)
1.1       deraadt   205:                                wbuf[wordlen++] = ' ';
1.3       millert   206:
1.1       deraadt   207:                        /* at a word break with a word waiting */
                    208:                        if (newlength <= fillcol) {
                    209:                                /* add word to current line */
                    210:                                if (!firstflag) {
1.5       art       211:                                        (void)linsert(1, ' ');
1.1       deraadt   212:                                        ++clength;
                    213:                                }
                    214:                                firstflag = FALSE;
                    215:                        } else {
1.2       millert   216:                                if (curwp->w_doto > 0 &&
                    217:                                    lgetc(curwp->w_dotp, curwp->w_doto - 1) == ' ') {
1.1       deraadt   218:                                        curwp->w_doto -= 1;
1.5       art       219:                                        (void)ldelete((RSIZE) 1, KNONE);
1.1       deraadt   220:                                }
                    221:                                /* start a new line */
1.5       art       222:                                (void)lnewline();
1.1       deraadt   223:                                clength = 0;
                    224:                        }
                    225:
                    226:                        /* and add the word in in either case */
1.2       millert   227:                        for (i = 0; i < wordlen; i++) {
1.5       art       228:                                (void)linsert(1, wbuf[i]);
1.1       deraadt   229:                                ++clength;
                    230:                        }
                    231:                        wordlen = 0;
                    232:                }
                    233:        }
                    234:        /* and add a last newline for the end of our new paragraph */
1.5       art       235:        (void)lnewline();
1.3       millert   236:
1.2       millert   237:        /*
1.10      db        238:         * We really should wind up where we started, (which is hard to keep
1.1       deraadt   239:         * track of) but I think the end of the last line is better than the
1.10      db        240:         * beginning of the blank line.
1.2       millert   241:         */
1.5       art       242:        (void)backchar(FFRAND, 1);
1.12      kjell     243:        retval = TRUE;
                    244: cleanup:
1.17      kjell     245:        undo_boundary_enable(FFRAND, 1);
1.12      kjell     246:        return (retval);
1.1       deraadt   247: }
                    248:
1.6       mickey    249: /*
1.3       millert   250:  * Delete a paragraph.  Delete n paragraphs starting with the current one.
                    251:  */
1.2       millert   252: /* ARGSUSED */
1.3       millert   253: int
1.8       cloder    254: killpara(int f, int n)
1.1       deraadt   255: {
1.37    ! lum       256:        int     lineno, status;
        !           257:
        !           258:        if (findpara() == FALSE)
        !           259:                return (TRUE);
        !           260:
        !           261:        /* go to the beginning of the paragraph */
        !           262:        (void)gotobop(FFRAND, 1);
1.1       deraadt   263:
1.37    ! lum       264:        /* take a note of the line number for after deletions and set mark */
        !           265:        lineno = curwp->w_dotline;
        !           266:        curwp->w_markp = curwp->w_dotp;
        !           267:        curwp->w_marko = curwp->w_doto;
1.1       deraadt   268:
1.37    ! lum       269:        (void)gotoeop(FFRAND, n);
1.1       deraadt   270:
1.37    ! lum       271:        if ((status = killregion(FFRAND, 1)) != TRUE)
        !           272:                return (status);
1.1       deraadt   273:
1.37    ! lum       274:        curwp->w_dotline = lineno;
        !           275:        return (TRUE);
        !           276: }
        !           277:
        !           278: /*
        !           279:  * Go down the buffer until we find text.
        !           280:  */
        !           281: int
        !           282: findpara(void)
        !           283: {
        !           284:        int     col, nospace = 0;
1.3       millert   285:
1.37    ! lum       286:        /* we move forward to find a para to mark */
        !           287:        do {
1.3       millert   288:                curwp->w_doto = 0;
1.37    ! lum       289:                col = 0;
        !           290:
        !           291:                /* check if we are on a blank line */
        !           292:                while (col < llength(curwp->w_dotp)) {
        !           293:                        if (!isspace(lgetc(curwp->w_dotp, col)))
        !           294:                                nospace = 1;
        !           295:                        col++;
        !           296:                }
        !           297:                if (nospace)
        !           298:                        break;
1.1       deraadt   299:
1.37    ! lum       300:                if (lforw(curwp->w_dotp) == curbp->b_headp)
        !           301:                        return (FALSE);
        !           302:
        !           303:                curwp->w_dotp = lforw(curwp->w_dotp);
        !           304:                curwp->w_dotline++;
        !           305:        } while (1);
1.34      lum       306:
1.10      db        307:        return (TRUE);
1.1       deraadt   308: }
                    309:
                    310: /*
1.3       millert   311:  * Insert char with work wrap.  Check to see if we're past fillcol, and if so,
                    312:  * justify this line.  As a last step, justify the line.
1.1       deraadt   313:  */
1.2       millert   314: /* ARGSUSED */
1.3       millert   315: int
1.8       cloder    316: fillword(int f, int n)
1.1       deraadt   317: {
1.3       millert   318:        char    c;
                    319:        int     col, i, nce;
1.1       deraadt   320:
                    321:        for (i = col = 0; col <= fillcol; ++i, ++col) {
1.2       millert   322:                if (i == curwp->w_doto)
                    323:                        return selfinsert(f, n);
1.1       deraadt   324:                c = lgetc(curwp->w_dotp, i);
                    325:                if (c == '\t'
1.3       millert   326: #ifdef NOTAB
1.2       millert   327:                    && !(curbp->b_flag & BFNOTAB)
1.1       deraadt   328: #endif
1.2       millert   329:                        )
                    330:                        col |= 0x07;
                    331:                else if (ISCTRL(c) != FALSE)
                    332:                        ++col;
1.1       deraadt   333:        }
                    334:        if (curwp->w_doto != llength(curwp->w_dotp)) {
1.5       art       335:                (void)selfinsert(f, n);
1.1       deraadt   336:                nce = llength(curwp->w_dotp) - curwp->w_doto;
1.2       millert   337:        } else
                    338:                nce = 0;
1.1       deraadt   339:        curwp->w_doto = i;
                    340:
                    341:        if ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' && c != '\t')
                    342:                do {
1.5       art       343:                        (void)backchar(FFRAND, 1);
1.7       deraadt   344:                } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' &&
                    345:                    c != '\t' && curwp->w_doto > 0);
1.1       deraadt   346:
                    347:        if (curwp->w_doto == 0)
                    348:                do {
1.5       art       349:                        (void)forwchar(FFRAND, 1);
1.7       deraadt   350:                } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' &&
                    351:                    c != '\t' && curwp->w_doto < llength(curwp->w_dotp));
1.1       deraadt   352:
1.5       art       353:        (void)delwhite(FFRAND, 1);
                    354:        (void)lnewline();
1.1       deraadt   355:        i = llength(curwp->w_dotp) - nce;
1.2       millert   356:        curwp->w_doto = i > 0 ? i : 0;
1.19      kjell     357:        curwp->w_rflag |= WFMOVE;
1.2       millert   358:        if (nce == 0 && curwp->w_doto != 0)
1.10      db        359:                return (fillword(f, n));
                    360:        return (TRUE);
1.1       deraadt   361: }
                    362:
1.3       millert   363: /*
                    364:  * Set fill column to n for justify.
                    365:  */
                    366: int
1.8       cloder    367: setfillcol(int f, int n)
1.2       millert   368: {
1.16      kjell     369:        char buf[32], *rep;
                    370:        const char *es;
1.18      kjell     371:        int nfill;
1.16      kjell     372:
                    373:        if ((f & FFARG) != 0) {
                    374:                fillcol = n;
                    375:        } else {
                    376:                if ((rep = eread("Set fill-column: ", buf, sizeof(buf),
                    377:                    EFNEW | EFCR)) == NULL)
                    378:                        return (ABORT);
                    379:                else if (rep[0] == '\0')
                    380:                        return (FALSE);
1.18      kjell     381:                nfill = strtonum(rep, 0, INT_MAX, &es);
                    382:                if (es != NULL) {
1.30      lum       383:                        dobeep();
1.18      kjell     384:                        ewprintf("Invalid fill column: %s", rep);
1.16      kjell     385:                        return (FALSE);
1.18      kjell     386:                }
                    387:                fillcol = nfill;
1.16      kjell     388:                ewprintf("Fill column set to %d", fillcol);
                    389:        }
1.10      db        390:        return (TRUE);
1.1       deraadt   391: }