1 /*- 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1992, 1993, 1994, 1995, 1996 5 * Keith Bostic. All rights reserved. 6 * 7 * See the LICENSE file for redistribution information. 8 */ 9 10 #include "config.h" 11 12 #ifndef lint 13 static const char sccsid[] = "@(#)v_at.c 10.8 (Berkeley) 4/27/96"; 14 #endif /* not lint */ 15 16 #include <sys/types.h> 17 #include <sys/queue.h> 18 #include <sys/time.h> 19 20 #include <bitstring.h> 21 #include <ctype.h> 22 #include <limits.h> 23 #include <stdio.h> 24 25 #include "../common/common.h" 26 #include "vi.h" 27 28 /* 29 * v_at -- @ 30 * Execute a buffer. 31 * 32 * PUBLIC: int v_at __P((SCR *, VICMD *)); 33 */ 34 int 35 v_at(sp, vp) 36 SCR *sp; 37 VICMD *vp; 38 { 39 CB *cbp; 40 CHAR_T name; 41 TEXT *tp; 42 size_t len; 43 char nbuf[20]; 44 45 /* 46 * !!! 47 * Historically, [@*]<carriage-return> and [@*][@*] executed the most 48 * recently executed buffer in ex mode. In vi mode, only @@ repeated 49 * the last buffer. We change historic practice and make @* work from 50 * vi mode as well, it's simpler and more consistent. 51 * 52 * My intent is that *[buffer] will, in the future, pass the buffer to 53 * whatever interpreter is loaded. 54 */ 55 name = F_ISSET(vp, VC_BUFFER) ? vp->buffer : '@'; 56 if (name == '@' || name == '*') { 57 if (!F_ISSET(sp, SC_AT_SET)) { 58 ex_emsg(sp, NULL, EXM_NOPREVBUF); 59 return (1); 60 } 61 name = sp->at_lbuf; 62 } 63 F_SET(sp, SC_AT_SET); 64 65 CBNAME(sp, cbp, name); 66 if (cbp == NULL) { 67 ex_emsg(sp, KEY_NAME(sp, name), EXM_EMPTYBUF); 68 return (1); 69 } 70 71 /* Save for reuse. */ 72 sp->at_lbuf = name; 73 74 /* 75 * The buffer is executed in vi mode, while in vi mode, so simply 76 * push it onto the terminal queue and continue. 77 * 78 * !!! 79 * Historic practice is that if the buffer was cut in line mode, 80 * <newlines> were appended to each line as it was pushed onto 81 * the stack. If the buffer was cut in character mode, <newlines> 82 * were appended to all lines but the last one. 83 * 84 * XXX 85 * Historic practice is that execution of an @ buffer could be 86 * undone by a single 'u' command, i.e. the changes were grouped 87 * together. We don't get this right; I'm waiting for the new DB 88 * logging code to be available. 89 */ 90 for (tp = cbp->textq.cqh_last; 91 tp != (void *)&cbp->textq; tp = tp->q.cqe_prev) 92 if ((F_ISSET(cbp, CB_LMODE) || 93 tp->q.cqe_next != (void *)&cbp->textq) && 94 v_event_push(sp, NULL, "\n", 1, 0) || 95 v_event_push(sp, NULL, tp->lb, tp->len, 0)) 96 return (1); 97 98 /* 99 * !!! 100 * If any count was supplied, it applies to the first command in the 101 * at buffer. 102 */ 103 if (F_ISSET(vp, VC_C1SET)) { 104 len = snprintf(nbuf, sizeof(nbuf), "%lu", vp->count); 105 if (v_event_push(sp, NULL, nbuf, len, 0)) 106 return (1); 107 } 108 return (0); 109 } 110