home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less3292.zip / mark.c < prev    next >
C/C++ Source or Header  |  1996-05-30  |  5KB  |  264 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995,1996  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. #include "less.h"
  29. #include "position.h"
  30.  
  31. extern IFILE curr_ifile;
  32. extern int sc_height;
  33. extern int jump_sline;
  34.  
  35. /*
  36.  * A mark is an ifile (input file) plus a position within the file.
  37.  */
  38. struct mark {
  39.     IFILE m_ifile;
  40.     struct scrpos m_scrpos;
  41. };
  42.  
  43. /*
  44.  * The table of marks.
  45.  * Each mark is identified by a lowercase or uppercase letter.
  46.  */
  47. #define    NMARKS        (2*26)        /* a-z, A-Z */
  48. static struct mark marks[NMARKS];
  49.  
  50. /*
  51.  * Special mark for the "last mark"; addressed by the apostrophe.
  52.  */
  53. static struct mark lmark;
  54.  
  55. /*
  56.  * Initialize the mark table to show no marks are set.
  57.  */
  58.     public void
  59. init_mark()
  60. {
  61.     int i;
  62.  
  63.     for (i = 0;  i < NMARKS;  i++)
  64.         marks[i].m_scrpos.pos = NULL_POSITION;
  65.     lmark.m_scrpos.pos = NULL_POSITION;
  66. }
  67.  
  68. /*
  69.  * See if a mark letter is valid (between a and z).
  70.  */
  71.     static struct mark *
  72. getumark(c)
  73.     int c;
  74. {
  75.     if (c >= 'a' && c <= 'z')
  76.         return (&marks[c-'a']);
  77.  
  78.     if (c >= 'A' && c <= 'Z')
  79.         return (&marks[c-'A'+26]);
  80.  
  81.     error("Invalid mark letter", NULL_PARG);
  82.     return (NULL);
  83. }
  84.  
  85. /*
  86.  * Get the mark structure identified by a character.
  87.  * The mark struct may come either from the mark table
  88.  * or may be constructed on the fly for certain characters like ^, $.
  89.  */
  90.     static struct mark *
  91. getmark(c)
  92.     int c;
  93. {
  94.     register struct mark *m;
  95.     static struct mark sm;
  96.  
  97.     switch (c)
  98.     {
  99.     case '^':
  100.         /*
  101.          * Beginning of the current file.
  102.          */
  103.         m = &sm;
  104.         m->m_scrpos.pos = ch_zero();
  105.         m->m_scrpos.ln = 0;
  106.         m->m_ifile = curr_ifile;
  107.         break;
  108.     case '$':
  109.         /*
  110.          * End of the current file.
  111.          */
  112.         if (ch_end_seek())
  113.         {
  114.             error("Cannot seek to end of file", NULL_PARG);
  115.             return (NULL);
  116.         }
  117.         m = &sm;
  118.         m->m_scrpos.pos = ch_tell();
  119.         m->m_scrpos.ln = sc_height-1;
  120.         m->m_ifile = curr_ifile;
  121.         break;
  122.     case '.':
  123.         /*
  124.          * Current position in the current file.
  125.          */
  126.         m = &sm;
  127.         get_scrpos(&m->m_scrpos);
  128.         m->m_ifile = curr_ifile;
  129.         break;
  130.     case '\'':
  131.         /*
  132.          * The "last mark".
  133.          */
  134.         m = &lmark;
  135.         break;
  136.     default:
  137.         /*
  138.          * Must be a user-defined mark.
  139.          */
  140.         m = getumark(c);
  141.         if (m == NULL)
  142.             break;
  143.         if (m->m_scrpos.pos == NULL_POSITION)
  144.         {
  145.             error("Mark not set", NULL_PARG);
  146.             return (NULL);
  147.         }
  148.         break;
  149.     }
  150.     return (m);
  151. }
  152.  
  153. /*
  154.  * Is a mark letter is invalid?
  155.  */
  156.     public int
  157. badmark(c)
  158.     int c;
  159. {
  160.     return (getmark(c) == NULL);
  161. }
  162.  
  163. /*
  164.  * Set a user-defined mark.
  165.  */
  166.     public void
  167. setmark(c)
  168.     int c;
  169. {
  170.     register struct mark *m;
  171.     struct scrpos scrpos;
  172.  
  173.     m = getumark(c);
  174.     if (m == NULL)
  175.         return;
  176.     get_scrpos(&scrpos);
  177.     m->m_scrpos = scrpos;
  178.     m->m_ifile = curr_ifile;
  179. }
  180.  
  181. /*
  182.  * Set lmark (the mark named by the apostrophe).
  183.  */
  184.     public void
  185. lastmark()
  186. {
  187.     struct scrpos scrpos;
  188.  
  189.     get_scrpos(&scrpos);
  190.     if (scrpos.pos == NULL_POSITION)
  191.         return;
  192.     lmark.m_scrpos = scrpos;
  193.     lmark.m_ifile = curr_ifile;
  194. }
  195.  
  196. /*
  197.  * Go to a mark.
  198.  */
  199.     public void
  200. gomark(c)
  201.     int c;
  202. {
  203.     register struct mark *m;
  204.     struct scrpos scrpos;
  205.  
  206.     m = getmark(c);
  207.     if (m == NULL)
  208.         return;
  209.  
  210.     /*
  211.      * If we're trying to go to the lastmark and 
  212.      * it has not been set to anything yet,
  213.      * set it to the beginning of the current file.
  214.      */
  215.     if (m == &lmark && m->m_scrpos.pos == NULL_POSITION)
  216.     {
  217.         m->m_ifile = curr_ifile;
  218.         m->m_scrpos.pos = ch_zero();
  219.         m->m_scrpos.ln = jump_sline;
  220.     }
  221.  
  222.     /*
  223.      * If we're using lmark, we must save the screen position now,
  224.      * because if we call edit_ifile() below, lmark will change.
  225.      * (We save the screen position even if we're not using lmark.)
  226.      */
  227.     scrpos = m->m_scrpos;
  228.     if (m->m_ifile != curr_ifile)
  229.     {
  230.         /*
  231.          * Not in the current file; edit the correct file.
  232.          */
  233.         if (edit_ifile(m->m_ifile))
  234.             return;
  235.     }
  236.  
  237.     jump_loc(scrpos.pos, scrpos.ln);
  238. }
  239.  
  240. /*
  241.  * Return the position associated with a given mark letter.
  242.  *
  243.  * We don't return which screen line the position 
  244.  * is associated with, but this doesn't matter much,
  245.  * because it's always the first non-blank line on the screen.
  246.  */
  247.     public POSITION
  248. markpos(c)
  249.     int c;
  250. {
  251.     register struct mark *m;
  252.  
  253.     m = getmark(c);
  254.     if (m == NULL)
  255.         return (NULL_POSITION);
  256.  
  257.     if (m->m_ifile != curr_ifile)
  258.     {
  259.         error("Mark not in current file", NULL_PARG);
  260.         return (NULL_POSITION);
  261.     }
  262.     return (m->m_scrpos.pos);
  263. }
  264.