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

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