home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / d / elvis / Source / c / move1 < prev    next >
Encoding:
Text File  |  1989-12-31  |  15.8 KB  |  958 lines

  1. /* move1.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    16820 SW Tallac Way
  6.  *    Beaverton, OR 97006
  7.  *    kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
  8.  */
  9.  
  10.  
  11. /* This file contains most movement functions */
  12.  
  13. #include <ctype.h>
  14. #include "vi.h"
  15.  
  16.  
  17. MARK    moveup(m, cnt)
  18.     MARK    m;    /* movement is relative to this mark */
  19.     long    cnt;    /* a numeric argument */
  20. {
  21.     DEFAULT(1);
  22.  
  23.     /* if at top already, don't move */
  24.     if (markline(m) - cnt < 1)
  25.     {
  26.         return MARK_UNSET;
  27.     }
  28.  
  29.     /* else move up one line */
  30.     m -= MARK_AT_LINE(cnt);
  31.  
  32.     return m;
  33. }
  34.  
  35. MARK    movedown(m, cnt)
  36.     MARK    m;    /* movement is relative to this mark */
  37.     long    cnt;    /* a numeric argument */
  38. {
  39.     DEFAULT(1);
  40.  
  41.     /* if at bottom already, don't move */
  42.     if (markline(m) + cnt > nlines)
  43.     {
  44.         return MARK_UNSET;
  45.     }
  46.  
  47.     /* else move down one line */
  48.     m += MARK_AT_LINE(cnt);
  49.  
  50.     /* adjust column number */
  51.     if (markidx(m) >= plen)
  52.     {
  53.         m = (m & ~(BLKSIZE - 1));
  54.         if (plen > 0)
  55.         {
  56.             m += plen - 1;
  57.         }
  58.     }
  59.  
  60.     return m;
  61. }
  62.  
  63. MARK    moveright(m, cnt)
  64.     MARK    m;    /* movement is relative to this mark */
  65.     long    cnt;    /* a numeric argument */
  66. {
  67.     int        idx;    /* index of the new cursor position */
  68.  
  69.     DEFAULT(1);
  70.  
  71.     /* move to right, if that's OK */
  72.     pfetch(markline(m));
  73.     idx = markidx(m) + cnt;
  74.     if (idx < plen)
  75.     {
  76.         m += cnt;
  77.     }
  78.     else
  79.     {
  80.         return MARK_UNSET;
  81.     }
  82.  
  83.     return m;
  84. }
  85.  
  86. MARK    moveleft(m, cnt)
  87.     MARK    m;    /* movement is relative to this mark */
  88.     long    cnt;    /* a numeric argument */
  89. {
  90.     DEFAULT(1);
  91.  
  92.     /* move to the left, if that's OK */
  93.     if (markidx(m) >= cnt)
  94.     {
  95.         m -= cnt;
  96.     }
  97.     else
  98.     {
  99.         return MARK_UNSET;
  100.     }
  101.  
  102.     return m;
  103. }
  104.  
  105. MARK    movetoline(m, cnt)
  106.     MARK    m;    /* movement is relative to this mark */
  107.     long    cnt;    /* a numeric line number */
  108. {
  109.     /* if no number specified, assume last line */
  110.     DEFAULT(nlines);
  111.  
  112.     /* if invalid line number, don't move */
  113.     if (cnt > nlines)
  114.     {
  115.         msg("Line numbers range from 1 to %ld", nlines);
  116.         return MARK_UNSET;
  117.     }
  118.  
  119.     /* move to first character of the selected line */
  120.     m = MARK_AT_LINE(cnt);
  121.     return m;
  122. }
  123.  
  124. MARK    movetocol(m, cnt)
  125.     MARK    m;    /* movement is relative to this mark */
  126.     long    cnt;    /* a numeric argument */
  127. {
  128.     char    *text;    /* text of the line */
  129.     int    col;    /* column number */
  130.     int    idx;    /* index into the line */
  131.  
  132.     DEFAULT(1);
  133.  
  134.     /* internally, columns are numbered 0..COLS-1, not 1..COLS */
  135.     cnt--;
  136.  
  137.     /* if 0, that's easy */
  138.     if (cnt == 0)
  139.     {
  140.         m &= ~(BLKSIZE - 1);
  141.         return m;
  142.     }
  143.  
  144.     /* find that column within the line */
  145.     pfetch(markline(m));
  146.     text = ptext;
  147.     for (col = idx = 0; col < cnt && *text; text++, idx++)
  148.     {
  149.         if (*text == '\t')
  150.         {
  151.             col += *o_tabstop;
  152.             col -= col % *o_tabstop;
  153.         }
  154.         else if (*text >= '\0' && *text < ' ' || *text == '\177')
  155.         {
  156.             col += 2;
  157.         }
  158. #ifndef SET_NOCHARATTR
  159.         else if (text[0] == '\\' && text[1] == 'f' && text[2] && *o_charattr)
  160.         {
  161.             text += 2; /* plus one more as part of for loop */
  162.         }
  163. #endif
  164.         else
  165.         {
  166.             col++;
  167.         }
  168.     }
  169.     if (!*text)
  170.     {
  171.         return MARK_UNSET;
  172.     }
  173.     else
  174.     {
  175.         m = (m & ~(BLKSIZE - 1)) + idx;
  176.     }
  177.     return m;
  178. }
  179.  
  180. MARK    movefront(m, cnt)
  181.     MARK    m;    /* movement is relative to this mark */
  182.     long    cnt;    /* a numeric argument (ignored) */
  183. {
  184.     char    *scan;
  185.  
  186.     /* move to the first non-whitespace character */
  187.     pfetch(markline(m));
  188.     scan = ptext;
  189.     m &= ~(BLKSIZE - 1);
  190.     while (*scan == ' ' || *scan == '\t')
  191.     {
  192.         scan++;
  193.         m++;
  194.     }
  195.  
  196.     return m;
  197. }
  198.  
  199. MARK    moverear(m, cnt)
  200.     MARK    m;    /* movement is relative to this mark */
  201.     long    cnt;    /* a numeric argument (ignored) */
  202. {
  203.     /* Try to move *EXTREMELY* far to the right.  It is fervently hoped
  204.      * that other code will convert this to a more reasonable MARK before
  205.      * anything tries to actually use it.  (See adjmove() in vi.c)
  206.      */
  207.     return m | (BLKSIZE - 1);
  208. }
  209.  
  210. MARK    movefword(m, cnt)
  211.     MARK    m;    /* movement is relative to this mark */
  212.     long    cnt;    /* a numeric argument */
  213. {
  214.     register long    l;
  215.     register char    *text;
  216.     register int    i;
  217.  
  218.     DEFAULT(1);
  219.  
  220.     l = markline(m);
  221.     pfetch(l);
  222.     text = ptext + markidx(m);
  223.     while (cnt-- > 0) /* yes, ASSIGNMENT! */
  224.     {
  225.         i = *text++;
  226.         /* if we hit the end of the line, continue with next line */
  227.         if (!isascii(i) || isalnum(i) || i == '_')
  228.         {
  229.             /* include an alphanumeric word */
  230.             while (i && (!isascii(i) || isalnum(i) || i == '_'))
  231.             {
  232.                 i = *text++;
  233.             }
  234.         }
  235.         else
  236.         {
  237.             /* include contiguous punctuation */
  238.             while (i && isascii(i) && !isalnum(i) && !isspace(i))
  239.             {
  240.                 i = *text++;
  241.             }
  242.         }
  243.  
  244.         /* include trailing whitespace */
  245.         while (!i || isascii(i) && isspace(i))
  246.         {
  247.             /* did we hit the end of this line? */
  248.             if (!i)
  249.             {
  250.                 /* move to next line, if there is one */
  251.                 l++;
  252.                 if (l > nlines)
  253.                 {
  254.                     return MARK_UNSET;
  255.                 }
  256.                 pfetch(l);
  257.                 text = ptext;
  258.             }
  259.  
  260.             i = *text++;
  261.         }
  262.         text--;
  263.     }
  264.  
  265.     /* construct a MARK for this place */
  266.     m = buildmark(text);
  267.     return m;
  268. }
  269.  
  270.  
  271. MARK    movebword(m, cnt)
  272.     MARK    m;    /* movement is relative to this mark */
  273.     long    cnt;    /* a numeric argument */
  274. {
  275.     register long    l;
  276.     register char    *text;
  277.  
  278.     DEFAULT(1);
  279.  
  280.     l = markline(m);
  281.     pfetch(l);
  282.     text = ptext + markidx(m);
  283.     while (cnt-- > 0) /* yes, ASSIGNMENT! */
  284.     {
  285.         text--;
  286.  
  287.         /* include preceding whitespace */
  288.         while (text < ptext || isascii(*text) && isspace(*text))
  289.         {
  290.             /* did we hit the end of this line? */
  291.             if (text < ptext)
  292.             {
  293.                 /* move to preceding line, if there is one */
  294.                 l--;
  295.                 if (l <= 0)
  296.                 {
  297.                     return MARK_UNSET;
  298.                 }
  299.                 pfetch(l);
  300.                 text = ptext + plen - 1;
  301.             }
  302.             else
  303.             {
  304.                 text--;
  305.             }
  306.         }
  307.  
  308.         if (!isascii(*text) || isalnum(*text) || *text == '_')
  309.         {
  310.             /* include an alphanumeric word */
  311.             while (text >= ptext && (!isascii(*text) || isalnum(*text) || *text == '_'))
  312.             {
  313.                 text--;
  314.             }
  315.         }
  316.         else
  317.         {
  318.             /* include contiguous punctuation */
  319.             while (text >= ptext && isascii(*text) && !isalnum(*text) && !isspace(*text))
  320.             {
  321.                 text--;
  322.             }
  323.         }
  324.         text++;
  325.     }
  326.  
  327.     /* construct a MARK for this place */
  328.     m = buildmark(text);
  329.     return m;
  330. }
  331.  
  332. MARK    moveeword(m, cnt)
  333.     MARK    m;    /* movement is relative to this mark */
  334.     long    cnt;    /* a numeric argument */
  335. {
  336.     register long    l;
  337.     register char    *text;
  338.     register int    i;
  339.  
  340.     DEFAULT(1);
  341.  
  342.     l = markline(m);
  343.     pfetch(l);
  344.     text = ptext + markidx(m);
  345.     while (cnt-- > 0) /* yes, ASSIGNMENT! */
  346.     {
  347.         text++;
  348.         i = *text++;
  349.  
  350.         /* include preceding whitespace */
  351.         while (!i || isascii(i) && isspace(i))
  352.         {
  353.             /* did we hit the end of this line? */
  354.             if (!i)
  355.             {
  356.                 /* move to next line, if there is one */
  357.                 l++;
  358.                 if (l > nlines)
  359.                 {
  360.                     return MARK_UNSET;
  361.                 }
  362.                 pfetch(l);
  363.                 text = ptext;
  364.             }
  365.  
  366.             i = *text++;
  367.         }
  368.  
  369.         if (!isascii(i) || isalnum(i) || i == '_')
  370.         {
  371.             /* include an alphanumeric word */
  372.             while (i && (!isascii(i) || isalnum(i) || i == '_'))
  373.             {
  374.                 i = *text++;
  375.             }
  376.         }
  377.         else
  378.         {
  379.             /* include contiguous punctuation */
  380.             while (i && isascii(i) && !isalnum(i) && !isspace(i))
  381.             {
  382.                 i = *text++;
  383.             }
  384.         }
  385.         text -= 2;
  386.     }
  387.  
  388.     /* construct a MARK for this place */
  389.     m = buildmark(text);
  390.     return m;
  391. }
  392.  
  393. MARK    movefWord(m, cnt)
  394.     MARK    m;    /* movement is relative to this mark */
  395.     long    cnt;    /* a numeric argument */
  396. {
  397.     register long    l;
  398.     register char    *text;
  399.     register int    i;
  400.  
  401.     DEFAULT(1);
  402.  
  403.     l = markline(m);
  404.     pfetch(l);
  405.     text = ptext + markidx(m);
  406.     while (cnt-- > 0) /* yes, ASSIGNMENT! */
  407.     {
  408.         i = *text++;
  409.         /* if we hit the end of the line, continue with next line */
  410.         /* include contiguous non-space characters */
  411.         while (i && !isspace(i))
  412.         {
  413.             i = *text++;
  414.         }
  415.  
  416.         /* include trailing whitespace */
  417.         while (!i || isascii(i) && isspace(i))
  418.         {
  419.             /* did we hit the end of this line? */
  420.             if (!i)
  421.             {
  422.                 /* move to next line, if there is one */
  423.                 l++;
  424.                 if (l > nlines)
  425.                 {
  426.                     return MARK_UNSET;
  427.                 }
  428.                 pfetch(l);
  429.                 text = ptext;
  430.             }
  431.  
  432.             i = *text++;
  433.         }
  434.         text--;
  435.     }
  436.  
  437.     /* construct a MARK for this place */
  438.     m = buildmark(text);
  439.     return m;
  440. }
  441.  
  442.  
  443. MARK    movebWord(m, cnt)
  444.     MARK    m;    /* movement is relative to this mark */
  445.     long    cnt;    /* a numeric argument */
  446. {
  447.     register long    l;
  448.     register char    *text;
  449.  
  450.     DEFAULT(1);
  451.  
  452.     l = markline(m);
  453.     pfetch(l);
  454.     text = ptext + markidx(m);
  455.     while (cnt-- > 0) /* yes, ASSIGNMENT! */
  456.     {
  457.         text--;
  458.  
  459.         /* include trailing whitespace */
  460.         while (text < ptext || isascii(*text) && isspace(*text))
  461.         {
  462.             /* did we hit the end of this line? */
  463.             if (text < ptext)
  464.             {
  465.                 /* move to next line, if there is one */
  466.                 l--;
  467.                 if (l <= 0)
  468.                 {
  469.                     return MARK_UNSET;
  470.                 }
  471.                 pfetch(l);
  472.                 text = ptext + plen - 1;
  473.             }
  474.             else
  475.             {
  476.                 text--;
  477.             }
  478.         }
  479.  
  480.         /* include contiguous non-whitespace */
  481.         while (text >= ptext && (!isascii(*text) || !isspace(*text)))
  482.         {
  483.             text--;
  484.         }
  485.         text++;
  486.     }
  487.  
  488.     /* construct a MARK for this place */
  489.     m = buildmark(text);
  490.     return m;
  491. }
  492.  
  493. MARK    moveeWord(m, cnt)
  494.     MARK    m;    /* movement is relative to this mark */
  495.     long    cnt;    /* a numeric argument */
  496. {
  497.     register long    l;
  498.     register char    *text;
  499.     register int    i;
  500.  
  501.     DEFAULT(1);
  502.  
  503.     l = markline(m);
  504.     pfetch(l);
  505.     text = ptext + markidx(m);
  506.     while (cnt-- > 0) /* yes, ASSIGNMENT! */
  507.     {
  508.         text++;
  509.         i = *text++;
  510.  
  511.         /* include preceding whitespace */
  512.         while (!i || isascii(i) && isspace(i))
  513.         {
  514.             /* did we hit the end of this line? */
  515.             if (!i)
  516.             {
  517.                 /* move to next line, if there is one */
  518.                 l++;
  519.                 if (l > nlines)
  520.                 {
  521.                     return MARK_UNSET;
  522.                 }
  523.                 pfetch(l);
  524.                 text = ptext;
  525.             }
  526.  
  527.             i = *text++;
  528.         }
  529.  
  530.         /* include contiguous non-whitespace */
  531.         while (i && (!isascii(i) || !isspace(i)))
  532.         {
  533.             i = *text++;
  534.         }
  535.         text -= 2;
  536.     }
  537.  
  538.     /* construct a MARK for this place */
  539.     m = buildmark(text);
  540.     return m;
  541. }
  542.  
  543. MARK    movefsentence(m, cnt)
  544.     MARK    m;    /* movement is relative to this mark */
  545.     long    cnt;    /* a numeric argument */
  546. {
  547.     register char    *text;
  548.     register long    l;
  549.  
  550.     DEFAULT(1);
  551.  
  552.     /* get the current line */
  553.     l = markline(m);
  554.     pfetch(l);
  555.     text = ptext + markidx(m);
  556.  
  557.     /* for each requested sentence... */
  558.     while (cnt-- > 0)
  559.     {
  560.         /* search forward for one of [.?!] followed by spaces or EOL */
  561.         do
  562.         {
  563.             /* wrap at end of line */
  564.             if (!text[0])
  565.             {
  566.                 if (l >= nlines)
  567.                 {
  568.                     return MARK_UNSET;
  569.                 }
  570.                 l++;
  571.                 pfetch(l);
  572.                 text = ptext;
  573.             }
  574.             else
  575.             {
  576.                 text++;
  577.             }
  578.         } while (text[0] != '.' && text[0] != '?' && text[0] != '!'
  579.             || text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
  580.     }
  581.  
  582.     /* construct a mark for this location */
  583.     m = buildmark(text);
  584.  
  585.     /* move forward to the first word of the next sentence */
  586.     m = movefword(m, 1L);
  587.  
  588.     return m;
  589. }
  590.  
  591. MARK    movebsentence(m, cnt)
  592.     MARK    m;    /* movement is relative to this mark */
  593.     long    cnt;    /* a numeric argument */
  594. {
  595.     register char    *text;    /* used to scan thru text */
  596.     register long    l;    /* current line number */
  597.     int        flag;    /* have we passed at least one word? */
  598.  
  599.     DEFAULT(1);
  600.  
  601.     /* get the current line */
  602.     l = markline(m);
  603.     pfetch(l);
  604.     text = ptext + markidx(m);
  605.  
  606.     /* for each requested sentence... */
  607.     flag = TRUE;
  608.     while (cnt-- > 0)
  609.     {
  610.         /* search backward for one of [.?!] followed by spaces or EOL */
  611.         do
  612.         {
  613.             /* wrap at beginning of line */
  614.             if (text == ptext)
  615.             {
  616.                 do
  617.                 {
  618.                     if (l <= 1)
  619.                     {
  620.                         return MARK_UNSET;
  621.                     }
  622.                     l--;
  623.                     pfetch(l);
  624.                 } while (!*ptext);
  625.                 text = ptext + plen - 1;
  626.             }
  627.             else
  628.             {
  629.                 text--;
  630.             }
  631.  
  632.             /* are we moving past a "word"? */
  633.             if (text[0] >= '0')
  634.             {
  635.                 flag = FALSE;
  636.             }
  637.         } while (flag || text[0] != '.' && text[0] != '?' && text[0] != '!'
  638.             || text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
  639.     }
  640.  
  641.     /* construct a mark for this location */
  642.     m = buildmark(text);
  643.  
  644.     /* move to the front of the following sentence */
  645.     m = movefword(m, 1L);
  646.  
  647.     return m;
  648. }
  649.  
  650. MARK    movefparagraph(m, cnt)
  651.     MARK    m;    /* movement is relative to this mark */
  652.     long    cnt;    /* a numeric argument */
  653. {
  654.     char    *text;
  655.     char    *pscn;    /* used to scan thru value of "paragraphs" option */
  656.     long    l;
  657.  
  658.     DEFAULT(1);
  659.  
  660.     for (l = markline(m); cnt > 0 && l++ < nlines; )
  661.     {
  662.         text = fetchline(l);
  663.         if (!*text)
  664.         {
  665.             cnt--;
  666.         }
  667.         else if (*text == '.')
  668.         {
  669.             for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
  670.             {
  671.                 if (pscn[0] == text[1] && pscn[1] == text[2])
  672.                 {
  673.                     cnt--;
  674.                     break;
  675.                 }
  676.             }
  677.         }
  678.     }
  679.     if (l <= nlines)
  680.     {
  681.         m = MARK_AT_LINE(l);
  682.     }
  683.     else
  684.     {
  685.         m = MARK_LAST;
  686.     }
  687.     return m;
  688. }
  689.  
  690. MARK    movebparagraph(m, cnt)
  691.     MARK    m;    /* movement is relative to this mark */
  692.     long    cnt;    /* a numeric argument */
  693. {
  694.     char    *text;
  695.     char    *pscn;    /* used to scan thru value of "paragraph" option */
  696.     long    l;
  697.  
  698.     DEFAULT(1);
  699.  
  700.     for (l = markline(m); cnt > 0 && l-- > 1; )
  701.     {
  702.         text = fetchline(l);
  703.         if (!*text)
  704.         {
  705.             cnt--;
  706.         }
  707.         else if (*text == '.')
  708.         {
  709.             for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
  710.             {
  711.                 if (pscn[0] == text[1] && pscn[1] == text[2])
  712.                 {
  713.                     cnt--;
  714.                     break;
  715.                 }
  716.             }
  717.         }
  718.     }
  719.     if (l >= 1)
  720.     {
  721.         m = MARK_AT_LINE(l);
  722.     }
  723.     else
  724.     {
  725.         m = MARK_FIRST;
  726.     }
  727.     return m;
  728. }
  729.  
  730. MARK    movefsection(m, cnt, key)
  731.     MARK    m;    /* movement is relative to this mark */
  732.     long    cnt;    /* (ignored) */
  733.     int    key;    /* second key stroke - must be ']' */
  734. {
  735.     char    *text;
  736.     char    *sscn;    /* used to scan thru value of "sections" option */
  737.     long    l;
  738.  
  739.     /* make sure second key was ']' */
  740.     if (key != ']')
  741.     {
  742.         return MARK_UNSET;
  743.     }
  744.  
  745.     for (l = markline(m); l++ < nlines; )
  746.     {
  747.         text = fetchline(l);
  748.         if (*text == '{')
  749.         {
  750.             break;
  751.         }
  752.         if (*text == '.')
  753.         {
  754.             for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
  755.             {
  756.                 if (sscn[0] == text[1] && sscn[1] == text[2])
  757.                 {
  758.                     goto BreakBreak;
  759.                 }
  760.             }
  761.         }
  762.     }
  763. BreakBreak:
  764.     if (l <= nlines)
  765.     {
  766.         m = MARK_AT_LINE(l);
  767.     }
  768.     else
  769.     {
  770.         m = MARK_LAST;
  771.     }
  772.     return m;
  773. }
  774.  
  775. MARK    movebsection(m, cnt, key)
  776.     MARK    m;    /* movement is relative to this mark */
  777.     long    cnt;    /* (ignored) */
  778.     int    key;    /* second key stroke - must be '[' */
  779. {
  780.     char    *text;
  781.     char    *sscn;    /* used to scan thru value of "sections" option */
  782.     long    l;
  783.  
  784.     /* make sure second key was '[' */
  785.     if (key != '[')
  786.     {
  787.         return MARK_UNSET;
  788.     }
  789.  
  790.     for (l = markline(m); l-- > 1; )
  791.     {
  792.         text = fetchline(l);
  793.         if (*text == '{')
  794.         {
  795.             break;
  796.         }
  797.         if (*text == '.')
  798.         {
  799.             for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
  800.             {
  801.                 if (sscn[0] == text[1] && sscn[1] == text[2])
  802.                 {
  803.                     goto BreakBreak;
  804.                 }
  805.             }
  806.         }
  807.     }
  808. BreakBreak:
  809.     if (l >= 1)
  810.     {
  811.         m = MARK_AT_LINE(l);
  812.     }
  813.     else
  814.     {
  815.         m = MARK_FIRST;
  816.     }
  817.     return m;
  818. }
  819.  
  820.  
  821. MARK    movematch(m, cnt)
  822.     MARK    m;    /* movement is relative to this mark */
  823.     long    cnt;    /* a numeric argument */
  824. {
  825.     long    l;
  826.     register char    *text;
  827.     register char    match;
  828.     register char    nest;
  829.     register int    count;
  830.  
  831.     /* get the current line */
  832.     l = markline(m);
  833.     pfetch(l);
  834.     text = ptext + markidx(m);
  835.  
  836.     /* search forward within line for one of "[](){}" */
  837.     for (match = '\0'; !match && *text; text++)
  838.     {
  839.         /* tricky way to recognize 'em in ASCII */
  840.         nest = *text;
  841.         if ((nest & 0xdf) == ']' || (nest & 0xdf) == '[')
  842.         {
  843.             match = nest ^ ('[' ^ ']');
  844.         }
  845.         else if ((nest & 0xfe) == '(')
  846.         {
  847.             match = nest ^ ('(' ^ ')');
  848.         }
  849.         else
  850.         {
  851.             match = 0;
  852.         }
  853.     }
  854.     if (!match)
  855.     {
  856.         return MARK_UNSET;
  857.     }
  858.     text--;
  859.  
  860.     /* search forward or backward for match */
  861.     if (match == '(' || match == '[' || match == '{')
  862.     {
  863.         /* search backward */
  864.         for (count = 1; count > 0; )
  865.         {
  866.             /* wrap at beginning of line */
  867.             if (text == ptext)
  868.             {
  869.                 do
  870.                 {
  871.                     if (l <= 1L)
  872.                     {
  873.                         return MARK_UNSET;
  874.                     }
  875.                     l--;
  876.                     pfetch(l);
  877.                 } while (!*ptext);
  878.                 text = ptext + plen - 1;
  879.             }
  880.             else
  881.             {
  882.                 text--;
  883.             }
  884.  
  885.             /* check the char */
  886.             if (*text == match)
  887.                 count--;
  888.             else if (*text == nest)
  889.                 count++;
  890.         }
  891.     }
  892.     else
  893.     {
  894.         /* search forward */
  895.         for (count = 1; count > 0; )
  896.         {
  897.             /* wrap at end of line */
  898.             if (!*text)
  899.             {
  900.                 if (l >= nlines)
  901.                 {
  902.                     return MARK_UNSET;
  903.                 }
  904.                 l++;
  905.                 pfetch(l);
  906.                 text = ptext;
  907.             }
  908.             else
  909.             {
  910.                 text++;
  911.             }
  912.  
  913.             /* check the char */
  914.             if (*text == match)
  915.                 count--;
  916.             else if (*text == nest)
  917.                 count++;
  918.         }
  919.     }
  920.  
  921.     /* construct a mark for this place */
  922.     m = buildmark(text);
  923.     return m;
  924. }
  925.  
  926. MARK    movetomark(m, cnt, key)
  927.     MARK    m;    /* movement is relative to this mark */
  928.     long    cnt;    /* (ignored) */
  929.     int    key;    /* keystroke - the mark to move to */
  930. {
  931.     /* mark '' is a special case */
  932.     if (key == '\'' || key == '`')
  933.     {
  934.         if (mark[26] == MARK_UNSET)
  935.         {
  936.             return MARK_FIRST;
  937.         }
  938.         else
  939.         {
  940.             return mark[26];
  941.         }
  942.     }
  943.  
  944.     /* if not a valid mark number, don't move */
  945.     if (key < 'a' || key > 'z')
  946.     {
  947.         return MARK_UNSET;
  948.     }
  949.  
  950.     /* return the selected mark -- may be MARK_UNSET */
  951.     if (!mark[key - 'a'])
  952.     {
  953.         msg("mark '%c is unset", key);
  954.     }
  955.     return mark[key - 'a'];
  956. }
  957.  
  958.