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

Annotation of src/usr.bin/mg/line.c, Revision 1.9

1.9     ! vincent     1: /*     $OpenBSD: line.c,v 1.8 2001/05/24 03:05:23 mickey Exp $ */
1.5       niklas      2:
1.1       deraadt     3: /*
                      4:  *             Text line handling.
1.8       mickey      5:  *
1.4       millert     6:  * The functions in this file are a general set of line management
1.8       mickey      7:  * utilities. They are the only routines that touch the text. They
                      8:  * also touch the buffer and window structures to make sure that the
                      9:  * necessary updating gets done.  There are routines in this file that
1.4       millert    10:  * handle the kill buffer too.  It isn't here for any good reason.
1.1       deraadt    11:  *
1.8       mickey     12:  * Note that this code only updates the dot and mark values in the window
                     13:  * list.  Since all the code acts on the current window, the buffer that
                     14:  * we are editing must be displayed, which means that "b_nwnd" is non-zero,
                     15:  * which means that the dot and mark values in the buffer headers are
1.1       deraadt    16:  * nonsense.
                     17:  */
                     18:
1.4       millert    19: #include "def.h"
                     20:
                     21: /*
1.8       mickey     22:  * The number of bytes member from the start of the structure type should be
1.4       millert    23:  * computed at compile time.
                     24:  */
1.1       deraadt    25:
                     26: #ifndef OFFSET
                     27: #define OFFSET(type,member) ((char *)&(((type *)0)->member)-(char *)((type *)0))
                     28: #endif
                     29:
                     30: #ifndef NBLOCK
1.3       millert    31: #define NBLOCK 16              /* Line block chunk size         */
1.1       deraadt    32: #endif
                     33:
                     34: #ifndef KBLOCK
1.3       millert    35: #define KBLOCK 256             /* Kill buffer block size.       */
1.1       deraadt    36: #endif
                     37:
1.4       millert    38: static char    *kbufp = NULL;  /* Kill buffer data.             */
                     39: static RSIZE    kused = 0;     /* # of bytes used in KB.        */
                     40: static RSIZE    ksize = 0;     /* # of bytes allocated in KB.   */
                     41: static RSIZE    kstart = 0;    /* # of first used byte in KB.   */
                     42:
                     43: static int      kgrow          __P((int));
1.1       deraadt    44:
                     45: /*
1.9     ! vincent    46:  * Allocate a new line of size `used'.  lrealloc() can be called if the line
        !            47:  * ever needs to grow beyond that.
1.1       deraadt    48:  */
                     49: LINE *
1.9     ! vincent    50: lalloc(int used)
1.3       millert    51: {
1.9     ! vincent    52:        LINE *lp;
1.1       deraadt    53:
1.9     ! vincent    54:        if ((lp = malloc(sizeof *lp)) == NULL)
        !            55:                return FALSE;
        !            56:        lp->l_text = NULL;
        !            57:        lp->l_size = 0;
        !            58:        lp->l_used = used;      /* XXX */
        !            59:        if (lrealloc(lp, used) == FALSE) {
        !            60:                free(lp);
1.7       art        61:                return NULL;
1.1       deraadt    62:        }
                     63:        return lp;
                     64: }
                     65:
1.9     ! vincent    66: int
        !            67: lrealloc(LINE *lp, int newsize)
1.1       deraadt    68: {
1.9     ! vincent    69:        char *tmp;
1.1       deraadt    70:
1.9     ! vincent    71:        if ((tmp = realloc(lp->l_text, newsize)) == NULL)
        !            72:                return FALSE;
        !            73:        lp->l_text = tmp;
        !            74:        lp->l_size = newsize;
        !            75:
        !            76:        return TRUE;
1.1       deraadt    77: }
                     78:
                     79: /*
1.4       millert    80:  * Delete line "lp".  Fix all of the links that might point to it (they are
1.8       mickey     81:  * moved to offset 0 of the next line.  Unlink the line from whatever buffer
                     82:  * it might be in, and release the memory.  The buffers are updated too; the
1.4       millert    83:  * magic conditions described in the above comments don't hold here.
1.1       deraadt    84:  */
1.6       art        85: void
1.3       millert    86: lfree(lp)
1.4       millert    87:        LINE *lp;
1.3       millert    88: {
1.4       millert    89:        BUFFER  *bp;
                     90:        MGWIN   *wp;
1.1       deraadt    91:
1.3       millert    92:        for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
1.1       deraadt    93:                if (wp->w_linep == lp)
                     94:                        wp->w_linep = lp->l_fp;
1.3       millert    95:                if (wp->w_dotp == lp) {
                     96:                        wp->w_dotp = lp->l_fp;
                     97:                        wp->w_doto = 0;
1.1       deraadt    98:                }
                     99:                if (wp->w_markp == lp) {
                    100:                        wp->w_markp = lp->l_fp;
                    101:                        wp->w_marko = 0;
                    102:                }
                    103:        }
1.3       millert   104:        for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
1.1       deraadt   105:                if (bp->b_nwnd == 0) {
1.3       millert   106:                        if (bp->b_dotp == lp) {
1.1       deraadt   107:                                bp->b_dotp = lp->l_fp;
                    108:                                bp->b_doto = 0;
                    109:                        }
                    110:                        if (bp->b_markp == lp) {
                    111:                                bp->b_markp = lp->l_fp;
                    112:                                bp->b_marko = 0;
                    113:                        }
                    114:                }
                    115:        }
                    116:        lp->l_bp->l_fp = lp->l_fp;
                    117:        lp->l_fp->l_bp = lp->l_bp;
1.9     ! vincent   118:        if (lp->l_text != NULL)
        !           119:                free(lp->l_text);
        !           120:        free(lp);
1.1       deraadt   121: }
                    122:
                    123: /*
1.8       mickey    124:  * This routine is called when a character changes in place in the current
                    125:  * buffer. It updates all of the required flags in the buffer and window
                    126:  * system. The flag used is passed as an argument; if the buffer is being
                    127:  * displayed in more than 1 window we change EDIT to HARD. Set MODE if the
1.4       millert   128:  * mode line needs to be updated (the "*" has to be set).
1.1       deraadt   129:  */
1.6       art       130: void
1.3       millert   131: lchange(flag)
1.4       millert   132:        int flag;
1.3       millert   133: {
1.4       millert   134:        MGWIN   *wp;
1.1       deraadt   135:
1.4       millert   136:        /* update mode lines if this is the first change. */
                    137:        if ((curbp->b_flag & BFCHG) == 0) {
                    138:                flag |= WFMODE;
1.1       deraadt   139:                curbp->b_flag |= BFCHG;
                    140:        }
1.3       millert   141:        for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
1.1       deraadt   142:                if (wp->w_bufp == curbp) {
                    143:                        wp->w_flag |= flag;
1.3       millert   144:                        if (wp != curwp)
                    145:                                wp->w_flag |= WFHARD;
1.1       deraadt   146:                }
                    147:        }
                    148: }
                    149:
                    150: /*
1.8       mickey    151:  * Insert "n" copies of the character "c" at the current location of dot.
                    152:  * In the easy case all that happens is the text is stored in the line.
                    153:  * In the hard case, the line has to be reallocated.  When the window list
                    154:  * is updated, take special care; I screwed it up once.  You always update
1.4       millert   155:  * dot in the current window.  You update mark and a dot in another window
                    156:  * if it is greater than the place where you did the insert. Return TRUE
1.1       deraadt   157:  * if all is well, and FALSE on errors.
                    158:  */
1.4       millert   159: int
1.1       deraadt   160: linsert(n, c)
1.4       millert   161:        int n, c;
1.1       deraadt   162: {
1.9     ! vincent   163:        LINE *lp1;
1.4       millert   164:        MGWIN   *wp;
                    165:        RSIZE    i;
                    166:        int      doto;
1.1       deraadt   167:
                    168:        lchange(WFEDIT);
1.4       millert   169:
                    170:        /* current line */
                    171:        lp1 = curwp->w_dotp;
1.9     ! vincent   172:
1.4       millert   173:        /* special case for the end */
                    174:        if (lp1 == curbp->b_linep) {
1.9     ! vincent   175:                LINE *lp2, *lp3;
        !           176:
1.4       millert   177:                /* now should only happen in empty buffer */
1.1       deraadt   178:                if (curwp->w_doto != 0) {
                    179:                        ewprintf("bug: linsert");
                    180:                        return FALSE;
                    181:                }
1.4       millert   182:                /* allocate a new line */
1.9     ! vincent   183:                if ((lp2 = lalloc(n)) == NULL)
1.1       deraadt   184:                        return FALSE;
1.9     ! vincent   185:
1.4       millert   186:                /* previous line */
                    187:                lp3 = lp1->l_bp;
                    188:                /* link in */
                    189:                lp3->l_fp = lp2;
1.1       deraadt   190:                lp2->l_fp = lp1;
                    191:                lp1->l_bp = lp2;
                    192:                lp2->l_bp = lp3;
1.3       millert   193:                for (i = 0; i < n; ++i)
1.1       deraadt   194:                        lp2->l_text[i] = c;
1.3       millert   195:                for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
1.1       deraadt   196:                        if (wp->w_linep == lp1)
                    197:                                wp->w_linep = lp2;
                    198:                        if (wp->w_dotp == lp1)
                    199:                                wp->w_dotp = lp2;
                    200:                        if (wp->w_markp == lp1)
                    201:                                wp->w_markp = lp2;
                    202:                }
1.9     ! vincent   203:
1.1       deraadt   204:                curwp->w_doto = n;
                    205:                return TRUE;
                    206:        }
1.4       millert   207:        /* save for later */
                    208:        doto = curwp->w_doto;
1.9     ! vincent   209:
        !           210:
        !           211:        if ((lp1->l_used + n) > lp1->l_size) {
        !           212:                if (lrealloc(lp1, lp1->l_used + n) == FALSE)
1.1       deraadt   213:                        return FALSE;
1.9     ! vincent   214:        }
        !           215:        lp1->l_used += n;
        !           216:        if (lp1->l_used != n)
        !           217:                memmove(&lp1->l_text[doto + n], &lp1->l_text[doto],
        !           218:                    lp1->l_used - n - doto);
        !           219:
1.4       millert   220:        /* Add the characters */
                    221:        for (i = 0; i < n; ++i)
1.9     ! vincent   222:                lp1->l_text[doto + i] = c;
1.3       millert   223:        for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
1.1       deraadt   224:                if (wp->w_dotp == lp1) {
1.3       millert   225:                        if (wp == curwp || wp->w_doto > doto)
1.1       deraadt   226:                                wp->w_doto += n;
                    227:                }
                    228:                if (wp->w_markp == lp1) {
                    229:                        if (wp->w_marko > doto)
                    230:                                wp->w_marko += n;
                    231:                }
                    232:        }
1.9     ! vincent   233:
1.1       deraadt   234:        return TRUE;
                    235: }
                    236:
                    237: /*
1.8       mickey    238:  * Insert a newline into the buffer at the current location of dot in the
1.4       millert   239:  * current window.  The funny ass-backwards way is no longer used.
1.1       deraadt   240:  */
1.4       millert   241: int
1.1       deraadt   242: lnewline()
                    243: {
1.4       millert   244:        LINE    *lp1, *lp2;
                    245:        int      doto, nlen;
                    246:        MGWIN   *wp;
1.1       deraadt   247:
                    248:        lchange(WFHARD);
1.4       millert   249:
                    250:        /* Get the address and offset of "." */
                    251:        lp1 = curwp->w_dotp;
                    252:        doto = curwp->w_doto;
                    253:
                    254:        /* avoid unnecessary copying */
                    255:        if (doto == 0) {
                    256:                /* new first part */
1.9     ! vincent   257:                if ((lp2 = lalloc(0)) == NULL)
1.1       deraadt   258:                        return FALSE;
                    259:                lp2->l_bp = lp1->l_bp;
                    260:                lp1->l_bp->l_fp = lp2;
                    261:                lp2->l_fp = lp1;
                    262:                lp1->l_bp = lp2;
1.3       millert   263:                for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
                    264:                        if (wp->w_linep == lp1)
                    265:                                wp->w_linep = lp2;
                    266:                return TRUE;
1.1       deraadt   267:        }
1.4       millert   268:
                    269:        /* length of new part */
                    270:        nlen = llength(lp1) - doto;
                    271:
                    272:        /* new second half line */
1.9     ! vincent   273:        if ((lp2 = lalloc(nlen)) == NULL)
1.1       deraadt   274:                return FALSE;
1.3       millert   275:        if (nlen != 0)
                    276:                bcopy(&lp1->l_text[doto], &lp2->l_text[0], nlen);
1.1       deraadt   277:        lp1->l_used = doto;
                    278:        lp2->l_bp = lp1;
                    279:        lp2->l_fp = lp1->l_fp;
                    280:        lp1->l_fp = lp2;
                    281:        lp2->l_fp->l_bp = lp2;
1.4       millert   282:        /* Windows */
                    283:        for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
1.1       deraadt   284:                if (wp->w_dotp == lp1 && wp->w_doto >= doto) {
                    285:                        wp->w_dotp = lp2;
                    286:                        wp->w_doto -= doto;
                    287:                }
                    288:                if (wp->w_markp == lp1 && wp->w_marko >= doto) {
                    289:                        wp->w_markp = lp2;
                    290:                        wp->w_marko -= doto;
                    291:                }
                    292:        }
                    293:        return TRUE;
                    294: }
                    295:
                    296: /*
1.8       mickey    297:  * This function deletes "n" bytes, starting at dot. It understands how to
                    298:  * deal with end of lines, etc.  It returns TRUE if all of the characters
                    299:  * were deleted, and FALSE if they were not (because dot ran into the end
                    300:  * of the buffer.  The "kflag" indicates either no insertion, or direction
1.4       millert   301:  * of insertion into the kill buffer.
1.1       deraadt   302:  */
1.4       millert   303: int
1.3       millert   304: ldelete(n, kflag)
1.4       millert   305:        RSIZE n;
                    306:        int   kflag;
1.3       millert   307: {
1.4       millert   308:        LINE    *dotp;
                    309:        RSIZE    chunk;
                    310:        MGWIN   *wp;
                    311:        int      doto;
                    312:        char    *cp1, *cp2;
1.1       deraadt   313:
                    314:        /*
                    315:         * HACK - doesn't matter, and fixes back-over-nl bug for empty
                    316:         *      kill buffers.
                    317:         */
1.3       millert   318:        if (kused == kstart)
                    319:                kflag = KFORW;
1.1       deraadt   320:
                    321:        while (n != 0) {
                    322:                dotp = curwp->w_dotp;
                    323:                doto = curwp->w_doto;
1.4       millert   324:                /* Hit the end of the buffer */
                    325:                if (dotp == curbp->b_linep)
1.1       deraadt   326:                        return FALSE;
1.4       millert   327:                /* Size of the chunk */
                    328:                chunk = dotp->l_used - doto;
1.1       deraadt   329:                if (chunk > n)
                    330:                        chunk = n;
1.4       millert   331:                /* End of line, merge */
                    332:                if (chunk == 0) {
1.3       millert   333:                        if (dotp == lback(curbp->b_linep))
1.4       millert   334:                                /* End of buffer */
                    335:                                return FALSE;
1.1       deraadt   336:                        lchange(WFHARD);
1.8       mickey    337:                        if (ldelnewline() == FALSE ||
1.4       millert   338:                            (kflag != KNONE && kinsert('\n', kflag) == FALSE))
1.1       deraadt   339:                                return FALSE;
                    340:                        --n;
                    341:                        continue;
                    342:                }
                    343:                lchange(WFEDIT);
1.4       millert   344:                /* Scrunch text */
                    345:                cp1 = &dotp->l_text[doto];
1.1       deraadt   346:                cp2 = cp1 + chunk;
                    347:                if (kflag == KFORW) {
                    348:                        while (ksize - kused < chunk)
1.3       millert   349:                                if (kgrow(FALSE) == FALSE)
                    350:                                        return FALSE;
1.4       millert   351:                        bcopy(cp1, &(kbufp[kused]), (int)chunk);
1.1       deraadt   352:                        kused += chunk;
                    353:                } else if (kflag == KBACK) {
                    354:                        while (kstart < chunk)
1.3       millert   355:                                if (kgrow(TRUE) == FALSE)
                    356:                                        return FALSE;
1.4       millert   357:                        bcopy(cp1, &(kbufp[kstart - chunk]), (int)chunk);
1.1       deraadt   358:                        kstart -= chunk;
1.3       millert   359:                } else if (kflag != KNONE)
                    360:                        panic("broken ldelete call");
1.1       deraadt   361:                while (cp2 != &dotp->l_text[dotp->l_used])
                    362:                        *cp1++ = *cp2++;
1.4       millert   363:                dotp->l_used -= (int)chunk;
1.3       millert   364:                for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
                    365:                        if (wp->w_dotp == dotp && wp->w_doto >= doto) {
                    366:                                /* NOSTRICT */
1.1       deraadt   367:                                wp->w_doto -= chunk;
                    368:                                if (wp->w_doto < doto)
                    369:                                        wp->w_doto = doto;
                    370:                        }
1.3       millert   371:                        if (wp->w_markp == dotp && wp->w_marko >= doto) {
                    372:                                /* NOSTRICT */
1.1       deraadt   373:                                wp->w_marko -= chunk;
                    374:                                if (wp->w_marko < doto)
                    375:                                        wp->w_marko = doto;
                    376:                        }
                    377:                }
                    378:                n -= chunk;
                    379:        }
                    380:        return TRUE;
                    381: }
                    382:
                    383: /*
1.8       mickey    384:  * Delete a newline and join the current line with the next line. If the next
1.4       millert   385:  * line is the magic header line always return TRUE; merging the last line
1.8       mickey    386:  * with the header line can be thought of as always being a successful
                    387:  * operation.  Even if nothing is done, this makes the kill buffer work
                    388:  * "right".  Easy cases can be done by shuffling data around.  Hard cases
                    389:  * require that lines be moved about in memory.  Return FALSE on error and
1.4       millert   390:  * TRUE if all looks ok.
1.1       deraadt   391:  */
1.4       millert   392: int
1.3       millert   393: ldelnewline()
                    394: {
1.4       millert   395:        LINE    *lp1, *lp2, *lp3;
                    396:        MGWIN   *wp;
1.1       deraadt   397:
                    398:        lp1 = curwp->w_dotp;
                    399:        lp2 = lp1->l_fp;
1.4       millert   400:        /* at the end of the buffer */
                    401:        if (lp2 == curbp->b_linep)
1.1       deraadt   402:                return TRUE;
                    403:        if (lp2->l_used <= lp1->l_size - lp1->l_used) {
                    404:                bcopy(&lp2->l_text[0], &lp1->l_text[lp1->l_used], lp2->l_used);
1.3       millert   405:                for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
1.1       deraadt   406:                        if (wp->w_linep == lp2)
                    407:                                wp->w_linep = lp1;
                    408:                        if (wp->w_dotp == lp2) {
1.3       millert   409:                                wp->w_dotp = lp1;
1.1       deraadt   410:                                wp->w_doto += lp1->l_used;
                    411:                        }
                    412:                        if (wp->w_markp == lp2) {
1.3       millert   413:                                wp->w_markp = lp1;
1.1       deraadt   414:                                wp->w_marko += lp1->l_used;
                    415:                        }
                    416:                }
                    417:                lp1->l_used += lp2->l_used;
                    418:                lp1->l_fp = lp2->l_fp;
                    419:                lp2->l_fp->l_bp = lp1;
1.4       millert   420:                free((char *)lp2);
1.1       deraadt   421:                return TRUE;
                    422:        }
1.3       millert   423:        if ((lp3 = lalloc(lp1->l_used + lp2->l_used)) == NULL)
1.1       deraadt   424:                return FALSE;
                    425:        bcopy(&lp1->l_text[0], &lp3->l_text[0], lp1->l_used);
                    426:        bcopy(&lp2->l_text[0], &lp3->l_text[lp1->l_used], lp2->l_used);
                    427:        lp1->l_bp->l_fp = lp3;
                    428:        lp3->l_fp = lp2->l_fp;
                    429:        lp2->l_fp->l_bp = lp3;
                    430:        lp3->l_bp = lp1->l_bp;
1.3       millert   431:        for (wp = wheadp; wp != NULL; wp = wp->w_wndp) {
                    432:                if (wp->w_linep == lp1 || wp->w_linep == lp2)
1.1       deraadt   433:                        wp->w_linep = lp3;
                    434:                if (wp->w_dotp == lp1)
1.3       millert   435:                        wp->w_dotp = lp3;
1.1       deraadt   436:                else if (wp->w_dotp == lp2) {
1.3       millert   437:                        wp->w_dotp = lp3;
1.1       deraadt   438:                        wp->w_doto += lp1->l_used;
                    439:                }
                    440:                if (wp->w_markp == lp1)
1.3       millert   441:                        wp->w_markp = lp3;
1.1       deraadt   442:                else if (wp->w_markp == lp2) {
1.3       millert   443:                        wp->w_markp = lp3;
1.1       deraadt   444:                        wp->w_marko += lp1->l_used;
                    445:                }
                    446:        }
1.4       millert   447:        free((char *)lp1);
                    448:        free((char *)lp2);
1.1       deraadt   449:        return TRUE;
                    450: }
1.9     ! vincent   451:
1.1       deraadt   452:
                    453: /*
1.8       mickey    454:  * Replace plen characters before dot with argument string.  Control-J
                    455:  * characters in st are interpreted as newlines.  There is a casehack
                    456:  * disable flag (normally it likes to match case of replacement to what
1.4       millert   457:  * was there).
1.1       deraadt   458:  */
1.4       millert   459: int
1.1       deraadt   460: lreplace(plen, st, f)
1.8       mickey    461:        RSIZE   plen;   /* length to remove              */
                    462:        char    *st;    /* replacement string            */
                    463:        int     f;      /* case hack disable             */
1.4       millert   464: {
                    465:        RSIZE   rlen;   /* replacement length            */
                    466:        int     rtype;  /* capitalization                */
                    467:        int     c;      /* used for random characters    */
                    468:        int     doto;   /* offset into line              */
1.1       deraadt   469:
                    470:        /*
1.8       mickey    471:         * Find the capitalization of the word that was found.  f says use
                    472:         * exact case of replacement string (same thing that happens with
1.4       millert   473:         * lowercase found), so bypass check.
1.1       deraadt   474:         */
1.3       millert   475:        /* NOSTRICT */
1.6       art       476:        (void)backchar(FFARG | FFRAND, (int)plen);
1.1       deraadt   477:        rtype = _L;
                    478:        c = lgetc(curwp->w_dotp, curwp->w_doto);
1.3       millert   479:        if (ISUPPER(c) != FALSE && f == FALSE) {
                    480:                rtype = _U | _L;
                    481:                if (curwp->w_doto + 1 < llength(curwp->w_dotp)) {
                    482:                        c = lgetc(curwp->w_dotp, curwp->w_doto + 1);
1.1       deraadt   483:                        if (ISUPPER(c) != FALSE) {
                    484:                                rtype = _U;
                    485:                        }
                    486:                }
                    487:        }
                    488:        /*
                    489:         * make the string lengths match (either pad the line
                    490:         * so that it will fit, or scrunch out the excess).
                    491:         * be careful with dot's offset.
                    492:         */
                    493:        rlen = strlen(st);
                    494:        doto = curwp->w_doto;
                    495:        if (plen > rlen)
1.6       art       496:                (void)ldelete((RSIZE) (plen - rlen), KNONE);
1.1       deraadt   497:        else if (plen < rlen) {
1.4       millert   498:                if (linsert((int)(rlen - plen), ' ') == FALSE)
1.1       deraadt   499:                        return FALSE;
                    500:        }
                    501:        curwp->w_doto = doto;
                    502:
                    503:        /*
                    504:         * do the replacement:  If was capital, then place first
                    505:         * char as if upper, and subsequent chars as if lower.
                    506:         * If inserting upper, check replacement for case.
                    507:         */
                    508:        while ((c = CHARMASK(*st++)) != '\0') {
1.3       millert   509:                if ((rtype & _U) != 0 && ISLOWER(c) != 0)
1.1       deraadt   510:                        c = TOUPPER(c);
1.3       millert   511:                if (rtype == (_U | _L))
1.1       deraadt   512:                        rtype = _L;
                    513:                if (c == CCHR('J')) {
                    514:                        if (curwp->w_doto == llength(curwp->w_dotp))
1.6       art       515:                                (void)forwchar(FFRAND, 1);
1.1       deraadt   516:                        else {
                    517:                                if (ldelete((RSIZE) 1, KNONE) != FALSE)
1.6       art       518:                                        (void)lnewline();
1.1       deraadt   519:                        }
                    520:                } else if (curwp->w_dotp == curbp->b_linep) {
1.6       art       521:                        (void)linsert(1, c);
1.1       deraadt   522:                } else if (curwp->w_doto == llength(curwp->w_dotp)) {
                    523:                        if (ldelete((RSIZE) 1, KNONE) != FALSE)
1.6       art       524:                                (void)linsert(1, c);
1.1       deraadt   525:                } else
                    526:                        lputc(curwp->w_dotp, curwp->w_doto++, c);
                    527:        }
                    528:        lchange(WFHARD);
                    529:        return (TRUE);
                    530: }
                    531:
                    532: /*
1.8       mickey    533:  * Delete all of the text saved in the kill buffer.  Called by commands when
                    534:  * a new kill context is created. The kill buffer array is released, just in
1.4       millert   535:  * case the buffer has grown to an immense size.  No errors.
1.1       deraadt   536:  */
1.6       art       537: void
1.3       millert   538: kdelete()
                    539: {
1.1       deraadt   540:        if (kbufp != NULL) {
1.4       millert   541:                free((char *)kbufp);
1.1       deraadt   542:                kbufp = NULL;
                    543:                kstart = kused = ksize = 0;
                    544:        }
                    545: }
                    546:
                    547: /*
1.8       mickey    548:  * Insert a character to the kill buffer, enlarging the buffer if there
                    549:  * isn't any room. Always grow the buffer in chunks, on the assumption
                    550:  * that if you put something in the kill buffer you are going to put more
                    551:  * stuff there too later. Return TRUE if all is well, and FALSE on errors.
1.4       millert   552:  * Print a message on errors.  Dir says whether to put it at back or front.
1.1       deraadt   553:  */
1.4       millert   554: int
1.3       millert   555: kinsert(c, dir)
1.4       millert   556:        int c, dir;
1.3       millert   557: {
1.1       deraadt   558:        if (kused == ksize && dir == KFORW && kgrow(FALSE) == FALSE)
                    559:                return FALSE;
                    560:        if (kstart == 0 && dir == KBACK && kgrow(TRUE) == FALSE)
                    561:                return FALSE;
1.3       millert   562:        if (dir == KFORW)
                    563:                kbufp[kused++] = c;
                    564:        else if (dir == KBACK)
                    565:                kbufp[--kstart] = c;
                    566:        else
                    567:                panic("broken kinsert call");   /* Oh shit! */
1.1       deraadt   568:        return (TRUE);
                    569: }
                    570:
                    571: /*
                    572:  * kgrow - just get more kill buffer for the callee. back is true if
                    573:  * we are trying to get space at the beginning of the kill buffer.
                    574:  */
1.4       millert   575: static int
1.3       millert   576: kgrow(back)
1.4       millert   577:        int back;
1.3       millert   578: {
1.4       millert   579:        int      nstart;
                    580:        char    *nbufp;
1.1       deraadt   581:
1.4       millert   582:        if ((unsigned)(ksize + KBLOCK) <= (unsigned)ksize) {
1.1       deraadt   583:                /* probably 16 bit unsigned */
                    584:                ewprintf("Kill buffer size at maximum");
                    585:                return FALSE;
                    586:        }
1.4       millert   587:        if ((nbufp = malloc((unsigned)(ksize + KBLOCK))) == NULL) {
                    588:                ewprintf("Can't get %ld bytes", (long)(ksize + KBLOCK));
1.1       deraadt   589:                return FALSE;
                    590:        }
1.3       millert   591:        nstart = (back == TRUE) ? (kstart + KBLOCK) : (KBLOCK / 4);
1.4       millert   592:        bcopy(&(kbufp[kstart]), &(nbufp[nstart]), (int)(kused - kstart));
1.1       deraadt   593:        if (kbufp != NULL)
1.4       millert   594:                free((char *)kbufp);
1.3       millert   595:        kbufp = nbufp;
1.1       deraadt   596:        ksize += KBLOCK;
                    597:        kused = kused - kstart + nstart;
                    598:        kstart = nstart;
                    599:        return TRUE;
                    600: }
                    601:
                    602: /*
1.8       mickey    603:  * This function gets characters from the kill buffer. If the character
                    604:  * index "n" is off the end, it returns "-1". This lets the caller just
1.4       millert   605:  * scan along until it gets a "-1" back.
1.1       deraadt   606:  */
1.4       millert   607: int
1.3       millert   608: kremove(n)
1.4       millert   609:        int n;
1.3       millert   610: {
1.1       deraadt   611:        if (n < 0 || n + kstart >= kused)
                    612:                return -1;
                    613:        return CHARMASK(kbufp[n + kstart]);
                    614: }