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: }