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

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