[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.32

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