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