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[] = "$Id: v_at.c,v 10.11 2001/06/25 15:19:30 skimo Exp $"; 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 #include <string.h> 25 26 #include "../common/common.h" 27 #include "vi.h" 28 29 /* 30 * v_at -- @ 31 * Execute a buffer. 32 * 33 * PUBLIC: int v_at(SCR *, VICMD *); 34 */ 35 int 36 v_at(SCR *sp, VICMD *vp) 37 { 38 CB *cbp; 39 CHAR_T name; 40 TEXT *tp; 41 size_t len; 42 char nbuf[20]; 43 CHAR_T wbuf[20]; 44 CHAR_T *wp; 45 size_t wlen; 46 47 /* 48 * !!! 49 * Historically, [@*]<carriage-return> and [@*][@*] executed the most 50 * recently executed buffer in ex mode. In vi mode, only @@ repeated 51 * the last buffer. We change historic practice and make @* work from 52 * vi mode as well, it's simpler and more consistent. 53 * 54 * My intent is that *[buffer] will, in the future, pass the buffer to 55 * whatever interpreter is loaded. 56 */ 57 name = F_ISSET(vp, VC_BUFFER) ? vp->buffer : '@'; 58 if (name == '@' || name == '*') { 59 if (!F_ISSET(sp, SC_AT_SET)) { 60 ex_emsg(sp, NULL, EXM_NOPREVBUF); 61 return (1); 62 } 63 name = sp->at_lbuf; 64 } 65 F_SET(sp, SC_AT_SET); 66 67 CBNAME(sp, cbp, name); 68 if (cbp == NULL) { 69 ex_emsg(sp, KEY_NAME(sp, name), EXM_EMPTYBUF); 70 return (1); 71 } 72 73 /* Save for reuse. */ 74 sp->at_lbuf = name; 75 76 /* 77 * The buffer is executed in vi mode, while in vi mode, so simply 78 * push it onto the terminal queue and continue. 79 * 80 * !!! 81 * Historic practice is that if the buffer was cut in line mode, 82 * <newlines> were appended to each line as it was pushed onto 83 * the stack. If the buffer was cut in character mode, <newlines> 84 * were appended to all lines but the last one. 85 * 86 * XXX 87 * Historic practice is that execution of an @ buffer could be 88 * undone by a single 'u' command, i.e. the changes were grouped 89 * together. We don't get this right; I'm waiting for the new DB 90 * logging code to be available. 91 */ 92 TAILQ_FOREACH_REVERSE(tp, cbp->textq, _texth, q) { 93 if (((F_ISSET(cbp, CB_LMODE) || 94 TAILQ_NEXT(tp, q) != NULL) && 95 v_event_push(sp, NULL, L("\n"), 1, 0)) || 96 v_event_push(sp, NULL, tp->lb, tp->len, 0)) 97 return (1); 98 } 99 100 /* 101 * !!! 102 * If any count was supplied, it applies to the first command in the 103 * at buffer. 104 */ 105 if (F_ISSET(vp, VC_C1SET)) { 106 len = snprintf(nbuf, sizeof(nbuf), "%lu", vp->count); 107 CHAR2INT(sp, nbuf, len, wp, wlen); 108 MEMCPY(wbuf, wp, wlen); 109 if (v_event_push(sp, NULL, wp, wlen, 0)) 110 return (1); 111 } 112 return (0); 113 } 114