home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / ex / ex_at.c < prev    next >
C/C++ Source or Header  |  1996-09-15  |  3KB  |  127 lines

  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[] = "@(#)ex_at.c    10.12 (Berkeley) 9/15/96";
  14. #endif /* not lint */
  15.  
  16. #include <sys/types.h>
  17. #include <sys/queue.h>
  18.  
  19. #include <bitstring.h>
  20. #include <ctype.h>
  21. #include <limits.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25.  
  26. #include "../common/common.h"
  27.  
  28. /*
  29.  * ex_at -- :@[@ | buffer]
  30.  *        :*[* | buffer]
  31.  *
  32.  *    Execute the contents of the buffer.
  33.  *
  34.  * PUBLIC: int ex_at __P((SCR *, EXCMD *));
  35.  */
  36. int
  37. ex_at(sp, cmdp)
  38.     SCR *sp;
  39.     EXCMD *cmdp;
  40. {
  41.     CB *cbp;
  42.     CHAR_T name;
  43.     EXCMD *ecp;
  44.     RANGE *rp;
  45.     TEXT *tp;
  46.     size_t len;
  47.     char *p;
  48.  
  49.     /*
  50.      * !!!
  51.      * Historically, [@*]<carriage-return> and [@*][@*] executed the most
  52.      * recently executed buffer in ex mode.
  53.      */
  54.     name = FL_ISSET(cmdp->iflags, E_C_BUFFER) ? cmdp->buffer : '@';
  55.     if (name == '@' || name == '*') {
  56.         if (!F_ISSET(sp, SC_AT_SET)) {
  57.             ex_emsg(sp, NULL, EXM_NOPREVBUF);
  58.             return (1);
  59.         }
  60.         name = sp->at_lbuf;
  61.     }
  62.     sp->at_lbuf = name;
  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.     /*
  72.      * !!!
  73.      * Historically the @ command took a range of lines, and the @ buffer
  74.      * was executed once per line.  The historic vi could be trashed by
  75.      * this because it didn't notice if the underlying file changed, or,
  76.      * for that matter, if there were no more lines on which to operate.
  77.      * For example, take a 10 line file, load "%delete" into a buffer,
  78.      * and enter :8,10@<buffer>.
  79.      *
  80.      * The solution is a bit tricky.  If the user specifies a range, take
  81.      * the same approach as for global commands, and discard the command
  82.      * if exit or switch to a new file/screen.  If the user doesn't specify
  83.      * the  range, continue to execute after a file/screen switch, which
  84.      * means @ buffers are still useful in a multi-screen environment.
  85.      */
  86.     CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
  87.     CIRCLEQ_INIT(&ecp->rq);
  88.     CALLOC_RET(sp, rp, RANGE *, 1, sizeof(RANGE));
  89.     rp->start = cmdp->addr1.lno;
  90.     if (F_ISSET(cmdp, E_ADDR_DEF)) {
  91.         rp->stop = rp->start;
  92.         FL_SET(ecp->agv_flags, AGV_AT_NORANGE);
  93.     } else {
  94.         rp->stop = cmdp->addr2.lno;
  95.         FL_SET(ecp->agv_flags, AGV_AT);
  96.     }
  97.     CIRCLEQ_INSERT_HEAD(&ecp->rq, rp, q);
  98.  
  99.     /*
  100.      * Buffers executed in ex mode or from the colon command line in vi
  101.      * were ex commands.  We can't push it on the terminal queue, since
  102.      * it has to be executed immediately, and we may be in the middle of
  103.      * an ex command already.  Push the command on the ex command stack.
  104.      * Build two copies of the command.  We need two copies because the
  105.      * ex parser may step on the command string when it's parsing it.
  106.      */
  107.     for (len = 0, tp = cbp->textq.cqh_last;
  108.         tp != (void *)&cbp->textq; tp = tp->q.cqe_prev)
  109.         len += tp->len + 1;
  110.  
  111.     MALLOC_RET(sp, ecp->cp, char *, len * 2);
  112.     ecp->o_cp = ecp->cp;
  113.     ecp->o_clen = len;
  114.     ecp->cp[len] = '\0';
  115.  
  116.     /* Copy the buffer into the command space. */
  117.     for (p = ecp->cp + len, tp = cbp->textq.cqh_last;
  118.         tp != (void *)&cbp->textq; tp = tp->q.cqe_prev) {
  119.         memcpy(p, tp->lb, tp->len);
  120.         p += tp->len;
  121.         *p++ = '\n';
  122.     }
  123.  
  124.     LIST_INSERT_HEAD(&sp->gp->ecq, ecp, q);
  125.     return (0);
  126. }
  127.