home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / ex / ex_print.c < prev    next >
C/C++ Source or Header  |  1996-05-12  |  7KB  |  353 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_print.c    10.18 (Berkeley) 5/12/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 <string.h>
  24.  
  25. #ifdef __STDC__
  26. #include <stdarg.h>
  27. #else
  28. #include <varargs.h>
  29. #endif
  30.  
  31. #include "../common/common.h"
  32.  
  33. static int ex_prchars __P((SCR *, const char *, size_t *, size_t, u_int, int));
  34.  
  35. /*
  36.  * ex_list -- :[line [,line]] l[ist] [count] [flags]
  37.  *
  38.  *    Display the addressed lines such that the output is unambiguous.
  39.  *
  40.  * PUBLIC: int ex_list __P((SCR *, EXCMD *));
  41.  */
  42. int
  43. ex_list(sp, cmdp)
  44.     SCR *sp;
  45.     EXCMD *cmdp;
  46. {
  47.     if (ex_print(sp, cmdp,
  48.         &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_LIST))
  49.         return (1);
  50.     sp->lno = cmdp->addr2.lno;
  51.     sp->cno = cmdp->addr2.cno;
  52.     return (0);
  53. }
  54.  
  55. /*
  56.  * ex_number -- :[line [,line]] nu[mber] [count] [flags]
  57.  *
  58.  *    Display the addressed lines with a leading line number.
  59.  *
  60.  * PUBLIC: int ex_number __P((SCR *, EXCMD *));
  61.  */
  62. int
  63. ex_number(sp, cmdp)
  64.     SCR *sp;
  65.     EXCMD *cmdp;
  66. {
  67.     if (ex_print(sp, cmdp,
  68.         &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_HASH))
  69.         return (1);
  70.     sp->lno = cmdp->addr2.lno;
  71.     sp->cno = cmdp->addr2.cno;
  72.     return (0);
  73. }
  74.  
  75. /*
  76.  * ex_pr -- :[line [,line]] p[rint] [count] [flags]
  77.  *
  78.  *    Display the addressed lines.
  79.  *
  80.  * PUBLIC: int ex_pr __P((SCR *, EXCMD *));
  81.  */
  82. int
  83. ex_pr(sp, cmdp)
  84.     SCR *sp;
  85.     EXCMD *cmdp;
  86. {
  87.     if (ex_print(sp, cmdp, &cmdp->addr1, &cmdp->addr2, cmdp->iflags))
  88.         return (1);
  89.     sp->lno = cmdp->addr2.lno;
  90.     sp->cno = cmdp->addr2.cno;
  91.     return (0);
  92. }
  93.  
  94. /*
  95.  * ex_print --
  96.  *    Print the selected lines.
  97.  *
  98.  * PUBLIC: int ex_print __P((SCR *, EXCMD *, MARK *, MARK *, u_int32_t));
  99.  */
  100. int
  101. ex_print(sp, cmdp, fp, tp, flags)
  102.     SCR *sp;
  103.     EXCMD *cmdp;
  104.     MARK *fp, *tp;
  105.     u_int32_t flags;
  106. {
  107.     GS *gp;
  108.     recno_t from, to;
  109.     size_t col, len;
  110.     char *p, buf[10];
  111.  
  112.     NEEDFILE(sp, cmdp);
  113.  
  114.     gp = sp->gp;
  115.     for (from = fp->lno, to = tp->lno; from <= to; ++from) {
  116.         col = 0;
  117.  
  118.         /*
  119.          * Display the line number.  The %6 format is specified
  120.          * by POSIX 1003.2, and is almost certainly large enough.
  121.          * Check, though, just in case.
  122.          */
  123.         if (LF_ISSET(E_C_HASH)) {
  124.             if (from <= 999999) {
  125.                 snprintf(buf, sizeof(buf), "%6ld  ", from);
  126.                 p = buf;
  127.             } else
  128.                 p = "TOOBIG  ";
  129.             if (ex_prchars(sp, p, &col, 8, 0, 0))
  130.                 return (1);
  131.         }
  132.  
  133.         /*
  134.          * Display the line.  The format for E_C_PRINT isn't very good,
  135.          * especially in handling end-of-line tabs, but they're almost
  136.          * backward compatible.
  137.          */
  138.         if (db_get(sp, from, DBG_FATAL, &p, &len))
  139.             return (1);
  140.  
  141.         if (len == 0 && !LF_ISSET(E_C_LIST))
  142.             (void)ex_puts(sp, "\n");
  143.         else if (ex_ldisplay(sp, p, len, col, flags))
  144.             return (1);
  145.  
  146.         if (INTERRUPTED(sp))
  147.             break;
  148.     }
  149.     return (0);
  150. }
  151.  
  152. /*
  153.  * ex_ldisplay --
  154.  *    Display a line without any preceding number.
  155.  *
  156.  * PUBLIC: int ex_ldisplay __P((SCR *, const char *, size_t, size_t, u_int));
  157.  */
  158. int
  159. ex_ldisplay(sp, p, len, col, flags)
  160.     SCR *sp;
  161.     const char *p;
  162.     size_t len, col;
  163.     u_int flags;
  164. {
  165.     if (len > 0 && ex_prchars(sp, p, &col, len, LF_ISSET(E_C_LIST), 0))
  166.         return (1);
  167.     if (!INTERRUPTED(sp) && LF_ISSET(E_C_LIST)) {
  168.         p = "$";
  169.         if (ex_prchars(sp, p, &col, 1, LF_ISSET(E_C_LIST), 0))
  170.             return (1);
  171.     }
  172.     if (!INTERRUPTED(sp))
  173.         (void)ex_puts(sp, "\n");
  174.     return (0);
  175. }
  176.  
  177. /*
  178.  * ex_scprint --
  179.  *    Display a line for the substitute with confirmation routine.
  180.  *
  181.  * PUBLIC: int ex_scprint __P((SCR *, MARK *, MARK *));
  182.  */
  183. int
  184. ex_scprint(sp, fp, tp)
  185.     SCR *sp;
  186.     MARK *fp, *tp;
  187. {
  188.     const char *p;
  189.     size_t col, len;
  190.  
  191.     col = 0;
  192.     if (O_ISSET(sp, O_NUMBER)) {
  193.         p = "        ";
  194.         if (ex_prchars(sp, p, &col, 8, 0, 0))
  195.             return (1);
  196.     }
  197.  
  198.     if (db_get(sp, fp->lno, DBG_FATAL, (char **)&p, &len))
  199.         return (1);
  200.  
  201.     if (ex_prchars(sp, p, &col, fp->cno, 0, ' '))
  202.         return (1);
  203.     p += fp->cno;
  204.     if (ex_prchars(sp,
  205.         p, &col, tp->cno == fp->cno ? 1 : tp->cno - fp->cno, 0, '^'))
  206.         return (1);
  207.     if (INTERRUPTED(sp))
  208.         return (1);
  209.     p = "[ynq]";        /* XXX: should be msg_cat. */
  210.     if (ex_prchars(sp, p, &col, 5, 0, 0))
  211.         return (1);
  212.     (void)ex_fflush(sp);
  213.     return (0);
  214. }
  215.  
  216. /*
  217.  * ex_prchars --
  218.  *    Local routine to dump characters to the screen.
  219.  */
  220. static int
  221. ex_prchars(sp, p, colp, len, flags, repeatc)
  222.     SCR *sp;
  223.     const char *p;
  224.     size_t *colp, len;
  225.     u_int flags;
  226.     int repeatc;
  227. {
  228.     CHAR_T ch, *kp;
  229.     GS *gp;
  230.     size_t col, tlen, ts;
  231.  
  232.     if (O_ISSET(sp, O_LIST))
  233.         LF_SET(E_C_LIST);
  234.     gp = sp->gp;
  235.     ts = O_VAL(sp, O_TABSTOP);
  236.     for (col = *colp; len--;)
  237.         if ((ch = *p++) == '\t' && !LF_ISSET(E_C_LIST))
  238.             for (tlen = ts - col % ts;
  239.                 col < sp->cols && tlen--; ++col) {
  240.                 (void)ex_printf(sp,
  241.                     "%c", repeatc ? repeatc : ' ');
  242.                 if (INTERRUPTED(sp))
  243.                     goto intr;
  244.             }
  245.         else {
  246.             kp = KEY_NAME(sp, ch);
  247.             tlen = KEY_LEN(sp, ch);
  248.             if (!repeatc  && col + tlen < sp->cols) {
  249.                 (void)ex_puts(sp, kp);
  250.                 col += tlen;
  251.             } else
  252.                 for (; tlen--; ++kp, ++col) {
  253.                     if (col == sp->cols) {
  254.                         col = 0;
  255.                         (void)ex_puts(sp, "\n");
  256.                     }
  257.                     (void)ex_printf(sp,
  258.                         "%c", repeatc ? repeatc : *kp);
  259.                     if (INTERRUPTED(sp))
  260.                         goto intr;
  261.                 }
  262.         }
  263. intr:    *colp = col;
  264.     return (0);
  265. }
  266.  
  267. /*
  268.  * ex_printf --
  269.  *    Ex's version of printf.
  270.  *
  271.  * PUBLIC: int ex_printf __P((SCR *, const char *, ...));
  272.  */
  273. int
  274. #ifdef __STDC__
  275. ex_printf(SCR *sp, const char *fmt, ...)
  276. #else
  277. ex_printf(sp, fmt, va_alist)
  278.     SCR *sp;
  279.     const char *fmt;
  280.     va_dcl
  281. #endif
  282. {
  283.     EX_PRIVATE *exp;
  284.     va_list ap;
  285.     size_t n;
  286.  
  287.     exp = EXP(sp);
  288.  
  289. #ifdef __STDC__
  290.     va_start(ap, fmt);
  291. #else
  292.     va_start(ap);
  293. #endif
  294.     exp->obp_len += n = vsnprintf(exp->obp + exp->obp_len,
  295.         sizeof(exp->obp) - exp->obp_len, fmt, ap);
  296.     va_end(ap);
  297.  
  298.     /* Flush when reach a <newline> or half the buffer. */
  299.     if (exp->obp[exp->obp_len - 1] == '\n' ||
  300.         exp->obp_len > sizeof(exp->obp) / 2)
  301.         (void)ex_fflush(sp);
  302.     return (n);
  303. }
  304.  
  305. /*
  306.  * ex_puts --
  307.  *    Ex's version of puts.
  308.  *
  309.  * PUBLIC: int ex_puts __P((SCR *, const char *));
  310.  */
  311. int
  312. ex_puts(sp, str)
  313.     SCR *sp;
  314.     const char *str;
  315. {
  316.     EX_PRIVATE *exp;
  317.     int doflush, n;
  318.  
  319.     exp = EXP(sp);
  320.  
  321.     /* Flush when reach a <newline> or the end of the buffer. */
  322.     for (doflush = n = 0; *str != '\0'; ++n) {
  323.         if (exp->obp_len > sizeof(exp->obp))
  324.             (void)ex_fflush(sp);
  325.         if ((exp->obp[exp->obp_len++] = *str++) == '\n')
  326.             doflush = 1;
  327.     }
  328.     if (doflush)
  329.         (void)ex_fflush(sp);
  330.     return (n);
  331. }
  332.  
  333. /*
  334.  * ex_fflush --
  335.  *    Ex's version of fflush.
  336.  *
  337.  * PUBLIC: int ex_fflush __P((SCR *sp));
  338.  */
  339. int
  340. ex_fflush(sp)
  341.     SCR *sp;
  342. {
  343.     EX_PRIVATE *exp;
  344.  
  345.     exp = EXP(sp);
  346.  
  347.     if (exp->obp_len != 0) {
  348.         sp->gp->scr_msg(sp, M_NONE, exp->obp, exp->obp_len);
  349.         exp->obp_len = 0;
  350.     }
  351.     return (0);
  352. }
  353.