Home | History | Annotate | Line # | Download | only in common
delete.c revision 1.3.4.2
      1  1.3.4.2  yamt /*	$NetBSD: delete.c,v 1.3.4.2 2014/05/22 15:50:33 yamt Exp $ */
      2  1.3.4.2  yamt /*-
      3  1.3.4.2  yamt  * Copyright (c) 1992, 1993, 1994
      4  1.3.4.2  yamt  *	The Regents of the University of California.  All rights reserved.
      5  1.3.4.2  yamt  * Copyright (c) 1992, 1993, 1994, 1995, 1996
      6  1.3.4.2  yamt  *	Keith Bostic.  All rights reserved.
      7  1.3.4.2  yamt  *
      8  1.3.4.2  yamt  * See the LICENSE file for redistribution information.
      9  1.3.4.2  yamt  */
     10  1.3.4.2  yamt 
     11  1.3.4.2  yamt #include "config.h"
     12  1.3.4.2  yamt 
     13  1.3.4.2  yamt #include <sys/cdefs.h>
     14  1.3.4.2  yamt #if 0
     15  1.3.4.2  yamt #ifndef lint
     16  1.3.4.2  yamt static const char sccsid[] = "Id: delete.c,v 10.17 2001/06/25 15:19:09 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:09 ";
     17  1.3.4.2  yamt #endif /* not lint */
     18  1.3.4.2  yamt #else
     19  1.3.4.2  yamt __RCSID("$NetBSD: delete.c,v 1.3.4.2 2014/05/22 15:50:33 yamt Exp $");
     20  1.3.4.2  yamt #endif
     21  1.3.4.2  yamt 
     22  1.3.4.2  yamt #include <sys/types.h>
     23  1.3.4.2  yamt #include <sys/queue.h>
     24  1.3.4.2  yamt 
     25  1.3.4.2  yamt #include <bitstring.h>
     26  1.3.4.2  yamt #include <errno.h>
     27  1.3.4.2  yamt #include <limits.h>
     28  1.3.4.2  yamt #include <stdio.h>
     29  1.3.4.2  yamt #include <stdlib.h>
     30  1.3.4.2  yamt #include <string.h>
     31  1.3.4.2  yamt 
     32  1.3.4.2  yamt #include "common.h"
     33  1.3.4.2  yamt 
     34  1.3.4.2  yamt /*
     35  1.3.4.2  yamt  * del --
     36  1.3.4.2  yamt  *	Delete a range of text.
     37  1.3.4.2  yamt  *
     38  1.3.4.2  yamt  * PUBLIC: int del __P((SCR *, MARK *, MARK *, int));
     39  1.3.4.2  yamt  */
     40  1.3.4.2  yamt int
     41  1.3.4.2  yamt del(SCR *sp, MARK *fm, MARK *tm, int lmode)
     42  1.3.4.2  yamt {
     43  1.3.4.2  yamt 	db_recno_t lno;
     44  1.3.4.2  yamt 	size_t blen, len, nlen, tlen;
     45  1.3.4.2  yamt 	CHAR_T *bp, *p;
     46  1.3.4.2  yamt 	int eof, rval;
     47  1.3.4.2  yamt 
     48  1.3.4.2  yamt 	bp = NULL;
     49  1.3.4.2  yamt 
     50  1.3.4.2  yamt 	/* Case 1 -- delete in line mode. */
     51  1.3.4.2  yamt 	if (lmode) {
     52  1.3.4.2  yamt 		for (lno = tm->lno; lno >= fm->lno; --lno) {
     53  1.3.4.2  yamt 			if (db_delete(sp, lno))
     54  1.3.4.2  yamt 				return (1);
     55  1.3.4.2  yamt 			++sp->rptlines[L_DELETED];
     56  1.3.4.2  yamt 			if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
     57  1.3.4.2  yamt 				break;
     58  1.3.4.2  yamt 		}
     59  1.3.4.2  yamt 		goto done;
     60  1.3.4.2  yamt 	}
     61  1.3.4.2  yamt 
     62  1.3.4.2  yamt 	/*
     63  1.3.4.2  yamt 	 * Case 2 -- delete to EOF.  This is a special case because it's
     64  1.3.4.2  yamt 	 * easier to pick it off than try and find it in the other cases.
     65  1.3.4.2  yamt  	 */
     66  1.3.4.2  yamt 	if (db_last(sp, &lno))
     67  1.3.4.2  yamt 		return (1);
     68  1.3.4.2  yamt 	if (tm->lno >= lno) {
     69  1.3.4.2  yamt 		if (tm->lno == lno) {
     70  1.3.4.2  yamt 			if (db_get(sp, lno, DBG_FATAL, &p, &len))
     71  1.3.4.2  yamt 				return (1);
     72  1.3.4.2  yamt 			eof = tm->cno != ENTIRE_LINE && tm->cno >= len ? 1 : 0;
     73  1.3.4.2  yamt 		} else
     74  1.3.4.2  yamt 			eof = 1;
     75  1.3.4.2  yamt 		if (eof) {
     76  1.3.4.2  yamt 			for (lno = tm->lno; lno > fm->lno; --lno) {
     77  1.3.4.2  yamt 				if (db_delete(sp, lno))
     78  1.3.4.2  yamt 					return (1);
     79  1.3.4.2  yamt 				++sp->rptlines[L_DELETED];
     80  1.3.4.2  yamt 				if (lno %
     81  1.3.4.2  yamt 				    INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
     82  1.3.4.2  yamt 					break;
     83  1.3.4.2  yamt 			}
     84  1.3.4.2  yamt 			if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
     85  1.3.4.2  yamt 				return (1);
     86  1.3.4.2  yamt 			GET_SPACE_RETW(sp, bp, blen, fm->cno);
     87  1.3.4.2  yamt 			MEMCPYW(bp, p, fm->cno);
     88  1.3.4.2  yamt 			if (db_set(sp, fm->lno, bp, fm->cno))
     89  1.3.4.2  yamt 				return (1);
     90  1.3.4.2  yamt 			goto done;
     91  1.3.4.2  yamt 		}
     92  1.3.4.2  yamt 	}
     93  1.3.4.2  yamt 
     94  1.3.4.2  yamt 	/* Case 3 -- delete within a single line. */
     95  1.3.4.2  yamt 	if (tm->lno == fm->lno) {
     96  1.3.4.2  yamt 		if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
     97  1.3.4.2  yamt 			return (1);
     98  1.3.4.2  yamt 		GET_SPACE_RETW(sp, bp, blen, len);
     99  1.3.4.2  yamt 		if (fm->cno != 0)
    100  1.3.4.2  yamt 			MEMCPYW(bp, p, fm->cno);
    101  1.3.4.2  yamt 		MEMCPYW(bp + fm->cno, p + (tm->cno + 1),
    102  1.3.4.2  yamt 			len - (tm->cno + 1));
    103  1.3.4.2  yamt 		if (db_set(sp, fm->lno,
    104  1.3.4.2  yamt 		    bp, len - ((tm->cno - fm->cno) + 1)))
    105  1.3.4.2  yamt 			goto err;
    106  1.3.4.2  yamt 		goto done;
    107  1.3.4.2  yamt 	}
    108  1.3.4.2  yamt 
    109  1.3.4.2  yamt 	/*
    110  1.3.4.2  yamt 	 * Case 4 -- delete over multiple lines.
    111  1.3.4.2  yamt 	 *
    112  1.3.4.2  yamt 	 * Copy the start partial line into place.
    113  1.3.4.2  yamt 	 */
    114  1.3.4.2  yamt 	if ((tlen = fm->cno) != 0) {
    115  1.3.4.2  yamt 		if (db_get(sp, fm->lno, DBG_FATAL, &p, NULL))
    116  1.3.4.2  yamt 			return (1);
    117  1.3.4.2  yamt 		GET_SPACE_RETW(sp, bp, blen, tlen + 256);
    118  1.3.4.2  yamt 		MEMCPYW(bp, p, tlen);
    119  1.3.4.2  yamt 	}
    120  1.3.4.2  yamt 
    121  1.3.4.2  yamt 	/* Copy the end partial line into place. */
    122  1.3.4.2  yamt 	if (db_get(sp, tm->lno, DBG_FATAL, &p, &len))
    123  1.3.4.2  yamt 		goto err;
    124  1.3.4.2  yamt 	if (len != 0 && tm->cno != len - 1) {
    125  1.3.4.2  yamt 		/*
    126  1.3.4.2  yamt 		 * XXX
    127  1.3.4.2  yamt 		 * We can overflow memory here, if the total length is greater
    128  1.3.4.2  yamt 		 * than SIZE_T_MAX.  The only portable way I've found to test
    129  1.3.4.2  yamt 		 * is depending on the overflow being less than the value.
    130  1.3.4.2  yamt 		 */
    131  1.3.4.2  yamt 		nlen = (len - (tm->cno + 1)) + tlen;
    132  1.3.4.2  yamt 		if (tlen > nlen) {
    133  1.3.4.2  yamt 			msgq(sp, M_ERR, "002|Line length overflow");
    134  1.3.4.2  yamt 			goto err;
    135  1.3.4.2  yamt 		}
    136  1.3.4.2  yamt 		if (tlen == 0) {
    137  1.3.4.2  yamt 			GET_SPACE_RETW(sp, bp, blen, nlen);
    138  1.3.4.2  yamt 		} else
    139  1.3.4.2  yamt 			ADD_SPACE_RETW(sp, bp, blen, nlen);
    140  1.3.4.2  yamt 
    141  1.3.4.2  yamt 		MEMCPYW(bp + tlen, p + (tm->cno + 1), len - (tm->cno + 1));
    142  1.3.4.2  yamt 		tlen += len - (tm->cno + 1);
    143  1.3.4.2  yamt 	}
    144  1.3.4.2  yamt 
    145  1.3.4.2  yamt 	/* Set the current line. */
    146  1.3.4.2  yamt 	if (db_set(sp, fm->lno, bp, tlen))
    147  1.3.4.2  yamt 		goto err;
    148  1.3.4.2  yamt 
    149  1.3.4.2  yamt 	/* Delete the last and intermediate lines. */
    150  1.3.4.2  yamt 	for (lno = tm->lno; lno > fm->lno; --lno) {
    151  1.3.4.2  yamt 		if (db_delete(sp, lno))
    152  1.3.4.2  yamt 			goto err;
    153  1.3.4.2  yamt 		++sp->rptlines[L_DELETED];
    154  1.3.4.2  yamt 		if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
    155  1.3.4.2  yamt 			break;
    156  1.3.4.2  yamt 	}
    157  1.3.4.2  yamt 
    158  1.3.4.2  yamt done:	rval = 0;
    159  1.3.4.2  yamt 	if (0)
    160  1.3.4.2  yamt err:		rval = 1;
    161  1.3.4.2  yamt 	if (bp != NULL)
    162  1.3.4.2  yamt 		FREE_SPACEW(sp, bp, blen);
    163  1.3.4.2  yamt 	return (rval);
    164  1.3.4.2  yamt }
    165