home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 036 / less232.zip / MARK.C < prev    next >
C/C++ Source or Header  |  1994-07-26  |  5KB  |  265 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994  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.         m->m_scrpos.pos = ch_tell();
  128.         m->m_scrpos.ln = 0;
  129.         m->m_ifile = curr_ifile;
  130.         break;
  131.     case '\'':
  132.         /*
  133.          * The "last mark".
  134.          */
  135.         m = &lmark;
  136.         break;
  137.     default:
  138.         /*
  139.          * Must be a user-defined mark.
  140.          */
  141.         m = getumark(c);
  142.         if (m == NULL)
  143.             break;
  144.         if (m->m_scrpos.pos == NULL_POSITION)
  145.         {
  146.             error("Mark not set", NULL_PARG);
  147.             return (NULL);
  148.         }
  149.         break;
  150.     }
  151.     return (m);
  152. }
  153.  
  154. /*
  155.  * Is a mark letter is invalid?
  156.  */
  157.     public int
  158. badmark(c)
  159.     int c;
  160. {
  161.     return (getmark(c) == NULL);
  162. }
  163.  
  164. /*
  165.  * Set a user-defined mark.
  166.  */
  167.     public void
  168. setmark(c)
  169.     int c;
  170. {
  171.     register struct mark *m;
  172.     struct scrpos scrpos;
  173.  
  174.     m = getumark(c);
  175.     if (m == NULL)
  176.         return;
  177.     get_scrpos(&scrpos);
  178.     m->m_scrpos = scrpos;
  179.     m->m_ifile = curr_ifile;
  180. }
  181.  
  182. /*
  183.  * Set lmark (the mark named by the apostrophe).
  184.  */
  185.     public void
  186. lastmark()
  187. {
  188.     struct scrpos scrpos;
  189.  
  190.     get_scrpos(&scrpos);
  191.     if (scrpos.pos == NULL_POSITION)
  192.         return;
  193.     lmark.m_scrpos = scrpos;
  194.     lmark.m_ifile = curr_ifile;
  195. }
  196.  
  197. /*
  198.  * Go to a mark.
  199.  */
  200.     public void
  201. gomark(c)
  202.     int c;
  203. {
  204.     register struct mark *m;
  205.     struct scrpos scrpos;
  206.  
  207.     m = getmark(c);
  208.     if (m == NULL)
  209.         return;
  210.  
  211.     /*
  212.      * If we're trying to go to the lastmark and 
  213.      * it has not been set to anything yet,
  214.      * set it to the beginning of the current file.
  215.      */
  216.     if (m == &lmark && m->m_scrpos.pos == NULL_POSITION)
  217.     {
  218.         m->m_ifile = curr_ifile;
  219.         m->m_scrpos.pos = ch_zero();
  220.         m->m_scrpos.ln = jump_sline;
  221.     }
  222.  
  223.     /*
  224.      * If we're using lmark, we must save the screen position now,
  225.      * because if we call edit_ifile() below, lmark will change.
  226.      * (We save the screen position even if we're not using lmark.)
  227.      */
  228.     scrpos = m->m_scrpos;
  229.     if (m->m_ifile != curr_ifile)
  230.     {
  231.         /*
  232.          * Not in the current file; edit the correct file.
  233.          */
  234.         if (edit_ifile(m->m_ifile))
  235.             return;
  236.     }
  237.  
  238.     jump_loc(scrpos.pos, scrpos.ln);
  239. }
  240.  
  241. /*
  242.  * Return the position associated with a given mark letter.
  243.  *
  244.  * We don't return which screen line the position 
  245.  * is associated with, but this doesn't matter much,
  246.  * because it's always the first non-blank line on the screen.
  247.  */
  248.     public POSITION
  249. markpos(c)
  250.     int c;
  251. {
  252.     register struct mark *m;
  253.  
  254.     m = getmark(c);
  255.     if (m == NULL)
  256.         return (NULL_POSITION);
  257.  
  258.     if (m->m_ifile != curr_ifile)
  259.     {
  260.         error("Mark not in current file", NULL_PARG);
  261.         return (NULL_POSITION);
  262.     }
  263.     return (m->m_scrpos.pos);
  264. }
  265.