home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / vi / v_section.c < prev    next >
C/C++ Source or Header  |  1996-04-27  |  6KB  |  253 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[] = "@(#)v_section.c    10.7 (Berkeley) 3/6/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 <limits.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24.  
  25. #include "../common/common.h"
  26. #include "vi.h"
  27.  
  28. /*
  29.  * !!!
  30.  * In historic vi, the section commands ignored empty lines, unlike the
  31.  * paragraph commands, which was probably okay.  However, they also moved
  32.  * to the start of the last line when there where no more sections instead
  33.  * of the end of the last line like the paragraph commands.  I've changed
  34.  * the latter behavior to match the paragraph commands.
  35.  *
  36.  * In historic vi, a section was defined as the first character(s) of the
  37.  * line matching, which could be followed by anything.  This implementation
  38.  * follows that historic practice.
  39.  *
  40.  * !!!
  41.  * The historic vi documentation (USD:15-10) claimed:
  42.  *    The section commands interpret a preceding count as a different
  43.  *    window size in which to redraw the screen at the new location,
  44.  *    and this window size is the base size for newly drawn windows
  45.  *    until another size is specified.  This is very useful if you are
  46.  *    on a slow terminal ...
  47.  *
  48.  * I can't get the 4BSD vi to do this, it just beeps at me.  For now, a
  49.  * count to the section commands simply repeats the command.
  50.  */
  51.  
  52. /*
  53.  * v_sectionf -- [count]]]
  54.  *    Move forward count sections/functions.
  55.  *
  56.  * !!!
  57.  * Using ]] as a motion command was a bit special, historically.  It could
  58.  * match } as well as the usual { and section values.  If it matched a { or
  59.  * a section, it did NOT include the matched line.  If it matched a }, it
  60.  * did include the line.  No clue why.
  61.  *
  62.  * PUBLIC: int v_sectionf __P((SCR *, VICMD *));
  63.  */
  64. int
  65. v_sectionf(sp, vp)
  66.     SCR *sp;
  67.     VICMD *vp;
  68. {
  69.     recno_t cnt, lno;
  70.     size_t len;
  71.     char *p, *list, *lp;
  72.  
  73.     /* Get the macro list. */
  74.     if ((list = O_STR(sp, O_SECTIONS)) == NULL)
  75.         return (1);
  76.  
  77.     /*
  78.      * !!!
  79.      * If the starting cursor position is at or before any non-blank
  80.      * characters in the line, i.e. the movement is cutting all of the
  81.      * line's text, the buffer is in line mode.  It's a lot easier to
  82.      * check here, because we know that the end is going to be the start
  83.      * or end of a line.
  84.      */
  85.     if (ISMOTION(vp))
  86.         if (vp->m_start.cno == 0)
  87.             F_SET(vp, VM_LMODE);
  88.         else {
  89.             vp->m_stop = vp->m_start;
  90.             vp->m_stop.cno = 0;
  91.             if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
  92.                 return (1);
  93.             if (vp->m_start.cno <= vp->m_stop.cno)
  94.                 F_SET(vp, VM_LMODE);
  95.         }
  96.  
  97.     cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
  98.     for (lno = vp->m_start.lno; !db_get(sp, ++lno, 0, &p, &len);) {
  99.         if (len == 0)
  100.             continue;
  101.         if (p[0] == '{' || ISMOTION(vp) && p[0] == '}') {
  102.             if (!--cnt) {
  103.                 if (p[0] == '{')
  104.                     goto adjust1;
  105.                 goto adjust2;
  106.             }
  107.             continue;
  108.         }
  109.         /*
  110.          * !!!
  111.          * Historic documentation (USD:15-11, 4.2) said that formfeed
  112.          * characters (^L) in the first column delimited sections.
  113.          * The historic code mentions formfeed characters, but never
  114.          * implements them.  Seems reasonable, do it.
  115.          */
  116.         if (p[0] == '\014') {
  117.             if (!--cnt)
  118.                 goto adjust1;
  119.             continue;
  120.         }
  121.         if (p[0] != '.' || len < 2)
  122.             continue;
  123.         for (lp = list; *lp != '\0'; lp += 2 * sizeof(*lp))
  124.             if (lp[0] == p[1] &&
  125.                 (lp[1] == ' ' && len == 2 || lp[1] == p[2]) &&
  126.                 !--cnt) {
  127.                 /*
  128.                  * !!!
  129.                  * If not cutting this line, adjust to the end
  130.                  * of the previous one.  Otherwise, position to
  131.                  * column 0.
  132.                  */
  133. adjust1:            if (ISMOTION(vp))
  134.                     goto ret1;
  135.  
  136. adjust2:            vp->m_stop.lno = lno;
  137.                 vp->m_stop.cno = 0;
  138.                 goto ret2;
  139.             }
  140.     }
  141.  
  142.     /* If moving forward, reached EOF, check to see if we started there. */
  143.     if (vp->m_start.lno == lno - 1) {
  144.         v_eof(sp, NULL);
  145.         return (1);
  146.     }
  147.  
  148. ret1:    if (db_get(sp, --lno, DBG_FATAL, NULL, &len))
  149.         return (1);
  150.     vp->m_stop.lno = lno;
  151.     vp->m_stop.cno = len ? len - 1 : 0;
  152.  
  153.     /*
  154.      * Non-motion commands go to the end of the range.  Delete and
  155.      * yank stay at the start of the range.  Ignore others.
  156.      */
  157. ret2:    if (ISMOTION(vp)) {
  158.         vp->m_final = vp->m_start;
  159.         if (F_ISSET(vp, VM_LMODE))
  160.             vp->m_final.cno = 0;
  161.     } else
  162.         vp->m_final = vp->m_stop;
  163.     return (0);
  164. }
  165.  
  166. /*
  167.  * v_sectionb -- [count][[
  168.  *    Move backward count sections/functions.
  169.  *
  170.  * PUBLIC: int v_sectionb __P((SCR *, VICMD *));
  171.  */
  172. int
  173. v_sectionb(sp, vp)
  174.     SCR *sp;
  175.     VICMD *vp;
  176. {
  177.     size_t len;
  178.     recno_t cnt, lno;
  179.     char *p, *list, *lp;
  180.  
  181.     /* An empty file or starting from line 1 is always illegal. */
  182.     if (vp->m_start.lno <= 1) {
  183.         v_sof(sp, NULL);
  184.         return (1);
  185.     }
  186.  
  187.     /* Get the macro list. */
  188.     if ((list = O_STR(sp, O_SECTIONS)) == NULL)
  189.         return (1);
  190.  
  191.     cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
  192.     for (lno = vp->m_start.lno; !db_get(sp, --lno, 0, &p, &len);) {
  193.         if (len == 0)
  194.             continue;
  195.         if (p[0] == '{') {
  196.             if (!--cnt)
  197.                 goto adjust1;
  198.             continue;
  199.         }
  200.         /*
  201.          * !!!
  202.          * Historic documentation (USD:15-11, 4.2) said that formfeed
  203.          * characters (^L) in the first column delimited sections.
  204.          * The historic code mentions formfeed characters, but never
  205.          * implements them.  Seems reasonable, do it.
  206.          */
  207.         if (p[0] == '\014') {
  208.             if (!--cnt)
  209.                 goto adjust1;
  210.             continue;
  211.         }
  212.         if (p[0] != '.' || len < 2)
  213.             continue;
  214.         for (lp = list; *lp != '\0'; lp += 2 * sizeof(*lp))
  215.             if (lp[0] == p[1] &&
  216.                 (lp[1] == ' ' && len == 2 || lp[1] == p[2]) &&
  217.                 !--cnt) {
  218. adjust1:            vp->m_stop.lno = lno;
  219.                 vp->m_stop.cno = 0;
  220.                 goto ret1;
  221.             }
  222.     }
  223.  
  224.     /*
  225.      * If moving backward, reached SOF, which is a movement sink.
  226.      * We already checked for starting there.
  227.      */
  228.     vp->m_stop.lno = 1;
  229.     vp->m_stop.cno = 0;
  230.  
  231.     /*
  232.      * All commands move to the end of the range.
  233.      *
  234.      * !!!
  235.      * Historic practice is the section cut was in line mode if it started
  236.      * from column 0 and was in the backward direction.  Otherwise, left
  237.      * motion commands adjust the starting point to the character before
  238.      * the current one.  What makes this worse is that if it cut to line
  239.      * mode it also went to the first non-<blank>.
  240.      */
  241. ret1:    if (vp->m_start.cno == 0) {
  242.         F_CLR(vp, VM_RCM_MASK);
  243.         F_SET(vp, VM_RCM_SETFNB);
  244.  
  245.         --vp->m_start.lno;
  246.         F_SET(vp, VM_LMODE);
  247.     } else
  248.         --vp->m_start.cno;
  249.  
  250.     vp->m_final = vp->m_stop;
  251.     return (0);
  252. }
  253.