home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / elvis_1.4.tar.Z / elvis_1.4.tar / move1.c < prev    next >
C/C++ Source or Header  |  1990-12-06  |  10KB  |  624 lines

  1. /* move1.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains most movement functions */
  12.  
  13. #include "config.h"
  14. #include <ctype.h>
  15. #include "vi.h"
  16.  
  17. #ifndef isascii
  18. # define isascii(c)    !((c) & ~0x7f)
  19. #endif
  20.  
  21. MARK    m_updnto(m, cnt, cmd)
  22.     MARK    m;    /* movement is relative to this mark */
  23.     long    cnt;    /* a numeric argument */
  24. {
  25.     DEFAULT(cmd == 'G' ? nlines : 1L);
  26.  
  27.     /* move up or down 'cnt' lines */
  28.     switch (cmd)
  29.     {
  30.       case ('P'&0x1f):
  31.       case '-':
  32.       case 'k':
  33.         m -= MARK_AT_LINE(cnt);
  34.         break;
  35.  
  36.       case 'G':
  37.         if (cnt < 1L || cnt > nlines)
  38.         {
  39.             msg("Only %ld lines", nlines);
  40.             return MARK_UNSET;
  41.         }
  42.         m = MARK_AT_LINE(cnt);
  43.         break;
  44.  
  45.       default:
  46.         m += MARK_AT_LINE(cnt);
  47.     }
  48.  
  49.     /* if that left us screwed up, then fail */
  50.     if (m < MARK_FIRST || markline(m) > nlines)
  51.     {
  52.         return MARK_UNSET;
  53.     }
  54.  
  55.     return m;
  56. }
  57.  
  58. /*ARGSUSED*/
  59. MARK    m_right(m, cnt)
  60.     MARK    m;    /* movement is relative to this mark */
  61.     long    cnt;    /* a numeric argument */
  62. {
  63.     int        idx;    /* index of the new cursor position */
  64.  
  65.     DEFAULT(1);
  66.  
  67.     /* move to right, if that's OK */
  68.     pfetch(markline(m));
  69.     idx = markidx(m) + cnt;
  70.     if (idx < plen)
  71.     {
  72.         m += cnt;
  73.     }
  74.     else
  75.     {
  76.         return MARK_UNSET;
  77.     }
  78.  
  79.     return m;
  80. }
  81.  
  82. /*ARGSUSED*/
  83. MARK    m_left(m, cnt)
  84.     MARK    m;    /* movement is relative to this mark */
  85.     long    cnt;    /* a numeric argument */
  86. {
  87.     DEFAULT(1);
  88.  
  89.     /* move to the left, if that's OK */
  90.     if (markidx(m) >= cnt)
  91.     {
  92.         m -= cnt;
  93.     }
  94.     else
  95.     {
  96.         return MARK_UNSET;
  97.     }
  98.  
  99.     return m;
  100. }
  101.  
  102. /*ARGSUSED*/
  103. MARK    m_tocol(m, cnt)
  104.     MARK    m;    /* movement is relative to this mark */
  105.     long    cnt;    /* a numeric argument */
  106. {
  107.     char    *text;    /* text of the line */
  108.     int    col;    /* column number */
  109.     int    idx;    /* index into the line */
  110.  
  111.     DEFAULT(1);
  112.  
  113.     /* internally, columns are numbered 0..COLS-1, not 1..COLS */
  114.     cnt--;
  115.  
  116.     /* if 0, that's easy */
  117.     if (cnt == 0)
  118.     {
  119.         m &= ~(BLKSIZE - 1);
  120.         return m;
  121.     }
  122.  
  123.     /* find that column within the line */
  124.     pfetch(markline(m));
  125.     text = ptext;
  126.     for (col = idx = 0; col < cnt && *text; text++, idx++)
  127.     {
  128.         if (*text == '\t' && !*o_list)
  129.         {
  130.             col += *o_tabstop;
  131.             col -= col % *o_tabstop;
  132.         }
  133.         else if (UCHAR(*text) < ' ' || *text == '\177')
  134.         {
  135.             col += 2;
  136.         }
  137. #ifndef NO_CHARATTR
  138.         else if (text[0] == '\\' && text[1] == 'f' && text[2] && *o_charattr)
  139.         {
  140.             text += 2; /* plus one more as part of for loop */
  141.         }
  142. #endif
  143.         else
  144.         {
  145.             col++;
  146.         }
  147.     }
  148.     if (!*text)
  149.     {
  150.         return MARK_UNSET;
  151.     }
  152.     else
  153.     {
  154.         m = (m & ~(BLKSIZE - 1)) + idx;
  155.     }
  156.     return m;
  157. }
  158.  
  159. /*ARGSUSED*/
  160. MARK    m_front(m, cnt)
  161.     MARK    m;    /* movement is relative to this mark */
  162.     long    cnt;    /* a numeric argument (ignored) */
  163. {
  164.     char    *scan;
  165.  
  166.     /* move to the first non-whitespace character */
  167.     pfetch(markline(m));
  168.     scan = ptext;
  169.     m &= ~(BLKSIZE - 1);
  170.     while (*scan == ' ' || *scan == '\t')
  171.     {
  172.         scan++;
  173.         m++;
  174.     }
  175.  
  176.     return m;
  177. }
  178.  
  179. /*ARGSUSED*/
  180. MARK    m_rear(m, cnt)
  181.     MARK    m;    /* movement is relative to this mark */
  182.     long    cnt;    /* a numeric argument (ignored) */
  183. {
  184.     /* Try to move *EXTREMELY* far to the right.  It is fervently hoped
  185.      * that other code will convert this to a more reasonable MARK before
  186.      * anything tries to actually use it.  (See adjmove() in vi.c)
  187.      */
  188.     return m | (BLKSIZE - 1);
  189. }
  190.  
  191. #ifndef NO_SENTENCE
  192. /*ARGSUSED*/
  193. MARK    m_fsentence(m, cnt)
  194.     MARK    m;    /* movement is relative to this mark */
  195.     long    cnt;    /* a numeric argument */
  196. {
  197.     REG char    *text;
  198.     REG long    l;
  199.  
  200.     DEFAULT(1);
  201.  
  202.     /* get the current line */
  203.     l = markline(m);
  204.     pfetch(l);
  205.     text = ptext + markidx(m);
  206.  
  207.     /* for each requested sentence... */
  208.     while (cnt-- > 0)
  209.     {
  210.         /* search forward for one of [.?!] followed by spaces or EOL */
  211.         do
  212.         {
  213.             /* wrap at end of line */
  214.             if (!text[0])
  215.             {
  216.                 if (l >= nlines)
  217.                 {
  218.                     return MARK_UNSET;
  219.                 }
  220.                 l++;
  221.                 pfetch(l);
  222.                 text = ptext;
  223.             }
  224.             else
  225.             {
  226.                 text++;
  227.             }
  228.         } while (text[0] != '.' && text[0] != '?' && text[0] != '!'
  229.             || text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
  230.     }
  231.  
  232.     /* construct a mark for this location */
  233.     m = buildmark(text);
  234.  
  235.     /* move forward to the first word of the next sentence */
  236.     m = m_fword(m, 1L);
  237.  
  238.     return m;
  239. }
  240.  
  241. /*ARGSUSED*/
  242. MARK    m_bsentence(m, cnt)
  243.     MARK    m;    /* movement is relative to this mark */
  244.     long    cnt;    /* a numeric argument */
  245. {
  246.     REG char    *text;    /* used to scan thru text */
  247.     REG long    l;    /* current line number */
  248.     int        flag;    /* have we passed at least one word? */
  249.  
  250.     DEFAULT(1);
  251.  
  252.     /* get the current line */
  253.     l = markline(m);
  254.     pfetch(l);
  255.     text = ptext + markidx(m);
  256.  
  257.     /* for each requested sentence... */
  258.     flag = TRUE;
  259.     while (cnt-- > 0)
  260.     {
  261.         /* search backward for one of [.?!] followed by spaces or EOL */
  262.         do
  263.         {
  264.             /* wrap at beginning of line */
  265.             if (text == ptext)
  266.             {
  267.                 do
  268.                 {
  269.                     if (l <= 1)
  270.                     {
  271.                         return MARK_UNSET;
  272.                     }
  273.                     l--;
  274.                     pfetch(l);
  275.                 } while (!*ptext);
  276.                 text = ptext + plen - 1;
  277.             }
  278.             else
  279.             {
  280.                 text--;
  281.             }
  282.  
  283.             /* are we moving past a "word"? */
  284.             if (text[0] >= '0')
  285.             {
  286.                 flag = FALSE;
  287.             }
  288.         } while (flag || text[0] != '.' && text[0] != '?' && text[0] != '!'
  289.             || text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
  290.     }
  291.  
  292.     /* construct a mark for this location */
  293.     m = buildmark(text);
  294.  
  295.     /* move to the front of the following sentence */
  296.     m = m_fword(m, 1L);
  297.  
  298.     return m;
  299. }
  300. #endif
  301.  
  302. /*ARGSUSED*/
  303. MARK    m_fparagraph(m, cnt)
  304.     MARK    m;    /* movement is relative to this mark */
  305.     long    cnt;    /* a numeric argument */
  306. {
  307.     char    *text;
  308.     char    *pscn;    /* used to scan thru value of "paragraphs" option */
  309.     long    l;
  310.  
  311.     DEFAULT(1);
  312.  
  313.     for (l = markline(m); cnt > 0 && l++ < nlines; )
  314.     {
  315.         text = fetchline(l);
  316.         if (!*text)
  317.         {
  318.             cnt--;
  319.         }
  320. #ifndef NO_SENTENCE
  321.         else if (*text == '.')
  322.         {
  323.             for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
  324.             {
  325.                 if (pscn[0] == text[1] && pscn[1] == text[2])
  326.                 {
  327.                     cnt--;
  328.                     break;
  329.                 }
  330.             }
  331.         }
  332. #endif
  333.     }
  334.     if (l <= nlines)
  335.     {
  336.         m = MARK_AT_LINE(l);
  337.     }
  338.     else
  339.     {
  340.         m = MARK_LAST;
  341.     }
  342.     return m;
  343. }
  344.  
  345. /*ARGSUSED*/
  346. MARK    m_bparagraph(m, cnt)
  347.     MARK    m;    /* movement is relative to this mark */
  348.     long    cnt;    /* a numeric argument */
  349. {
  350.     char    *text;
  351.     char    *pscn;    /* used to scan thru value of "paragraph" option */
  352.     long    l;
  353.  
  354.     DEFAULT(1);
  355.  
  356.     for (l = markline(m); cnt > 0 && l-- > 1; )
  357.     {
  358.         text = fetchline(l);
  359.         if (!*text)
  360.         {
  361.             cnt--;
  362.         }
  363. #ifndef NO_SENTENCE
  364.         else if (*text == '.')
  365.         {
  366.             for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
  367.             {
  368.                 if (pscn[0] == text[1] && pscn[1] == text[2])
  369.                 {
  370.                     cnt--;
  371.                     break;
  372.                 }
  373.             }
  374.         }
  375. #endif
  376.     }
  377.     if (l >= 1)
  378.     {
  379.         m = MARK_AT_LINE(l);
  380.     }
  381.     else
  382.     {
  383.         m = MARK_FIRST;
  384.     }
  385.     return m;
  386. }
  387.  
  388. /*ARGSUSED*/
  389. MARK    m_fsection(m, cnt, key)
  390.     MARK    m;    /* movement is relative to this mark */
  391.     long    cnt;    /* (ignored) */
  392.     int    key;    /* second key stroke - must be ']' */
  393. {
  394.     char    *text;
  395.     char    *sscn;    /* used to scan thru value of "sections" option */
  396.     long    l;
  397.  
  398.     /* make sure second key was ']' */
  399.     if (key != ']')
  400.     {
  401.         return MARK_UNSET;
  402.     }
  403.  
  404.     for (l = markline(m); l++ < nlines; )
  405.     {
  406.         text = fetchline(l);
  407.         if (*text == '{')
  408.         {
  409.             break;
  410.         }
  411. #ifndef NO_SENTENCE
  412.         else if (*text == '.')
  413.         {
  414.             for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
  415.             {
  416.                 if (sscn[0] == text[1] && sscn[1] == text[2])
  417.                 {
  418.                     goto BreakBreak;
  419.                 }
  420.             }
  421.         }
  422. #endif
  423.     }
  424. BreakBreak:
  425.     if (l <= nlines)
  426.     {
  427.         m = MARK_AT_LINE(l);
  428.     }
  429.     else
  430.     {
  431.         m = MARK_LAST;
  432.     }
  433.     return m;
  434. }
  435.  
  436. /*ARGSUSED*/
  437. MARK    m_bsection(m, cnt, key)
  438.     MARK    m;    /* movement is relative to this mark */
  439.     long    cnt;    /* (ignored) */
  440.     int    key;    /* second key stroke - must be '[' */
  441. {
  442.     char    *text;
  443.     char    *sscn;    /* used to scan thru value of "sections" option */
  444.     long    l;
  445.  
  446.     /* make sure second key was '[' */
  447.     if (key != '[')
  448.     {
  449.         return MARK_UNSET;
  450.     }
  451.  
  452.     for (l = markline(m); l-- > 1; )
  453.     {
  454.         text = fetchline(l);
  455.         if (*text == '{')
  456.         {
  457.             break;
  458.         }
  459. #ifndef NO_SENTENCE
  460.         else if (*text == '.')
  461.         {
  462.             for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
  463.             {
  464.                 if (sscn[0] == text[1] && sscn[1] == text[2])
  465.                 {
  466.                     goto BreakBreak;
  467.                 }
  468.             }
  469.         }
  470. #endif
  471.     }
  472. BreakBreak:
  473.     if (l >= 1)
  474.     {
  475.         m = MARK_AT_LINE(l);
  476.     }
  477.     else
  478.     {
  479.         m = MARK_FIRST;
  480.     }
  481.     return m;
  482. }
  483.  
  484.  
  485. /*ARGSUSED*/
  486. MARK    m_match(m, cnt)
  487.     MARK    m;    /* movement is relative to this mark */
  488.     long    cnt;    /* a numeric argument (ignored) */
  489. {
  490.     long    l;
  491.     REG char    *text;
  492.     REG char    match;
  493.     REG char    nest;
  494.     REG int        count;
  495.  
  496.     /* get the current line */
  497.     l = markline(m);
  498.     pfetch(l);
  499.     text = ptext + markidx(m);
  500.  
  501.     /* search forward within line for one of "[](){}" */
  502.     for (match = '\0'; !match && *text; text++)
  503.     {
  504.         /* tricky way to recognize 'em in ASCII */
  505.         nest = *text;
  506.         if ((nest & 0xdf) == ']' || (nest & 0xdf) == '[')
  507.         {
  508.             match = nest ^ ('[' ^ ']');
  509.         }
  510.         else if ((nest & 0xfe) == '(')
  511.         {
  512.             match = nest ^ ('(' ^ ')');
  513.         }
  514.         else
  515.         {
  516.             match = 0;
  517.         }
  518.     }
  519.     if (!match)
  520.     {
  521.         return MARK_UNSET;
  522.     }
  523.     text--;
  524.  
  525.     /* search forward or backward for match */
  526.     if (match == '(' || match == '[' || match == '{')
  527.     {
  528.         /* search backward */
  529.         for (count = 1; count > 0; )
  530.         {
  531.             /* wrap at beginning of line */
  532.             if (text == ptext)
  533.             {
  534.                 do
  535.                 {
  536.                     if (l <= 1L)
  537.                     {
  538.                         return MARK_UNSET;
  539.                     }
  540.                     l--;
  541.                     pfetch(l);
  542.                 } while (!*ptext);
  543.                 text = ptext + plen - 1;
  544.             }
  545.             else
  546.             {
  547.                 text--;
  548.             }
  549.  
  550.             /* check the char */
  551.             if (*text == match)
  552.                 count--;
  553.             else if (*text == nest)
  554.                 count++;
  555.         }
  556.     }
  557.     else
  558.     {
  559.         /* search forward */
  560.         for (count = 1; count > 0; )
  561.         {
  562.             /* wrap at end of line */
  563.             if (!*text)
  564.             {
  565.                 if (l >= nlines)
  566.                 {
  567.                     return MARK_UNSET;
  568.                 }
  569.                 l++;
  570.                 pfetch(l);
  571.                 text = ptext;
  572.             }
  573.             else
  574.             {
  575.                 text++;
  576.             }
  577.  
  578.             /* check the char */
  579.             if (*text == match)
  580.                 count--;
  581.             else if (*text == nest)
  582.                 count++;
  583.         }
  584.     }
  585.  
  586.     /* construct a mark for this place */
  587.     m = buildmark(text);
  588.     return m;
  589. }
  590.  
  591. /*ARGSUSED*/
  592. MARK    m_tomark(m, cnt, key)
  593.     MARK    m;    /* movement is relative to this mark */
  594.     long    cnt;    /* (ignored) */
  595.     int    key;    /* keystroke - the mark to move to */
  596. {
  597.     /* mark '' is a special case */
  598.     if (key == '\'' || key == '`')
  599.     {
  600.         if (mark[26] == MARK_UNSET)
  601.         {
  602.             return MARK_FIRST;
  603.         }
  604.         else
  605.         {
  606.             return mark[26];
  607.         }
  608.     }
  609.  
  610.     /* if not a valid mark number, don't move */
  611.     if (key < 'a' || key > 'z')
  612.     {
  613.         return MARK_UNSET;
  614.     }
  615.  
  616.     /* return the selected mark -- may be MARK_UNSET */
  617.     if (!mark[key - 'a'])
  618.     {
  619.         msg("mark '%c is unset", key);
  620.     }
  621.     return mark[key - 'a'];
  622. }
  623.  
  624.