jcs's openbsd hax
openbsd
at jcs 144 lines 4.1 kB view raw
1/* $OpenBSD: undo.c,v 1.15 2026/01/05 03:34:18 jsg Exp $ */ 2/* $NetBSD: undo.c,v 1.2 1995/03/21 09:04:52 cgd Exp $ */ 3 4/* undo.c: This file contains the undo routines for the ed line editor */ 5/*- 6 * Copyright (c) 1993 Andrew Moore, Talke Studio. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31#include <stdio.h> 32#include <stdlib.h> 33 34#include "ed.h" 35 36#define USIZE 100 /* undo stack size */ 37static undo_t *ustack = NULL; /* undo stack */ 38static int usize = 0; /* stack size variable */ 39static int u_p = 0; /* undo stack pointer */ 40 41/* push_undo_stack: return pointer to initialized undo node */ 42undo_t * 43push_undo_stack(int type, int from, int to) 44{ 45 undo_t *t; 46 47 t = ustack; 48 if (u_p < usize || 49 (t = reallocarray(ustack, (usize += USIZE), sizeof(undo_t))) != NULL) { 50 ustack = t; 51 ustack[u_p].type = type; 52 ustack[u_p].t = get_addressed_line_node(to); 53 ustack[u_p].h = get_addressed_line_node(from); 54 return ustack + u_p++; 55 } 56 /* out of memory - release undo stack */ 57 perror(NULL); 58 seterrmsg("out of memory"); 59 clear_undo_stack(); 60 free(ustack); 61 ustack = NULL; 62 usize = 0; 63 return NULL; 64} 65 66 67/* USWAP: swap undo nodes */ 68#define USWAP(x,y) { \ 69 undo_t utmp; \ 70 utmp = x, x = y, y = utmp; \ 71} 72 73 74int u_current_addr = -1; /* if >= 0, undo enabled */ 75int u_addr_last = -1; /* if >= 0, undo enabled */ 76 77/* pop_undo_stack: undo last change to the editor buffer */ 78int 79pop_undo_stack(void) 80{ 81 int n; 82 int o_current_addr = current_addr; 83 int o_addr_last = addr_last; 84 85 if (u_current_addr == -1 || u_addr_last == -1) { 86 seterrmsg("nothing to undo"); 87 return ERR; 88 } else if (u_p) 89 modified = 1; 90 get_addressed_line_node(0); /* this get_addressed_line_node last! */ 91 SPL1(); 92 for (n = u_p; n-- > 0;) { 93 switch(ustack[n].type) { 94 case UADD: 95 REQUE(ustack[n].h->q_back, ustack[n].t->q_forw); 96 break; 97 case UDEL: 98 REQUE(ustack[n].h->q_back, ustack[n].h); 99 REQUE(ustack[n].t, ustack[n].t->q_forw); 100 break; 101 case UMOV: 102 case VMOV: 103 REQUE(ustack[n - 1].h, ustack[n].h->q_forw); 104 REQUE(ustack[n].t->q_back, ustack[n - 1].t); 105 REQUE(ustack[n].h, ustack[n].t); 106 n--; 107 break; 108 default: 109 /*NOTREACHED*/ 110 ; 111 } 112 ustack[n].type ^= 1; 113 } 114 /* reverse undo stack order */ 115 for (n = u_p; n-- > (u_p + 1)/ 2;) 116 USWAP(ustack[n], ustack[u_p - 1 - n]); 117 if (isglobal) 118 clear_active_list(); 119 current_addr = u_current_addr, u_current_addr = o_current_addr; 120 addr_last = u_addr_last, u_addr_last = o_addr_last; 121 SPL0(); 122 return 0; 123} 124 125 126/* clear_undo_stack: clear the undo stack */ 127void 128clear_undo_stack(void) 129{ 130 line_t *lp, *ep, *tl; 131 132 while (u_p--) 133 if (ustack[u_p].type == UDEL) { 134 ep = ustack[u_p].t->q_forw; 135 for (lp = ustack[u_p].h; lp != ep; lp = tl) { 136 unmark_line_node(lp); 137 tl = lp->q_forw; 138 free(lp); 139 } 140 } 141 u_p = 0; 142 u_current_addr = current_addr; 143 u_addr_last = addr_last; 144}