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