home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / LESS177.ZIP / src / mark.c < prev    next >
C/C++ Source or Header  |  1992-07-18  |  4KB  |  238 lines

  1. #include "less.h"
  2. #include "position.h"
  3.  
  4. extern IFILE curr_ifile;
  5. extern int sc_height;
  6. extern int jump_sline;
  7.  
  8. /*
  9.  * A mark is an ifile (input file) plus a position within the file.
  10.  */
  11. struct mark {
  12.     IFILE m_ifile;
  13.     struct scrpos m_scrpos;
  14. };
  15.  
  16. /*
  17.  * The table of marks.
  18.  * Each mark is identified by a lowercase or uppercase letter.
  19.  */
  20. #define    NMARKS        (2*26)        /* a-z, A-Z */
  21. static struct mark marks[NMARKS];
  22.  
  23. /*
  24.  * Special mark for the "last mark"; addressed by the apostrophe.
  25.  */
  26. static struct mark lmark;
  27.  
  28. /*
  29.  * Initialize the mark table to show no marks are set.
  30.  */
  31.     public void
  32. init_mark()
  33. {
  34.     int i;
  35.  
  36.     for (i = 0;  i < NMARKS;  i++)
  37.         marks[i].m_scrpos.pos = NULL_POSITION;
  38.     lmark.m_scrpos.pos = NULL_POSITION;
  39. }
  40.  
  41. /*
  42.  * See if a mark letter is valid (between a and z).
  43.  */
  44.     static struct mark *
  45. getumark(c)
  46.     int c;
  47. {
  48.     if (c >= 'a' && c <= 'z')
  49.         return (&marks[c-'a']);
  50.  
  51.     if (c >= 'A' && c <= 'Z')
  52.         return (&marks[c-'A'+26]);
  53.  
  54.     error("Invalid mark letter", NULL_PARG);
  55.     return (NULL);
  56. }
  57.  
  58. /*
  59.  * Get the mark structure identified by a character.
  60.  * The mark struct may come either from the mark table
  61.  * or may be constructed on the fly for certain characters like ^, $.
  62.  */
  63.     static struct mark *
  64. getmark(c)
  65.     int c;
  66. {
  67.     register struct mark *m;
  68.     static struct mark sm;
  69.  
  70.     switch (c)
  71.     {
  72.     case '^':
  73.         /*
  74.          * Beginning of the current file.
  75.          */
  76.         m = &sm;
  77.         m->m_scrpos.pos = ch_zero();
  78.         m->m_scrpos.ln = 0;
  79.         m->m_ifile = curr_ifile;
  80.         break;
  81.     case '$':
  82.         /*
  83.          * End of the current file.
  84.          */
  85.         if (ch_end_seek())
  86.         {
  87.             error("Cannot seek to end of file", NULL_PARG);
  88.             return (NULL);
  89.         }
  90.         m = &sm;
  91.         m->m_scrpos.pos = ch_tell();
  92.         m->m_scrpos.ln = sc_height-1;
  93.         m->m_ifile = curr_ifile;
  94.         break;
  95.     case '.':
  96.         /*
  97.          * Current position in the current file.
  98.          */
  99.         m = &sm;
  100.         m->m_scrpos.pos = ch_tell();
  101.         m->m_scrpos.ln = 0;
  102.         m->m_ifile = curr_ifile;
  103.         break;
  104.     case '\'':
  105.         /*
  106.          * The "last mark".
  107.          */
  108.         m = &lmark;
  109.         break;
  110.     default:
  111.         /*
  112.          * Must be a user-defined mark.
  113.          */
  114.         m = getumark(c);
  115.         if (m == NULL)
  116.             break;
  117.         if (m->m_scrpos.pos == NULL_POSITION)
  118.         {
  119.             error("Mark not set", NULL_PARG);
  120.             return (NULL);
  121.         }
  122.         break;
  123.     }
  124.     return (m);
  125. }
  126.  
  127. /*
  128.  * Is a mark letter is invalid?
  129.  */
  130.     public int
  131. badmark(c)
  132.     int c;
  133. {
  134.     return (getmark(c) == NULL);
  135. }
  136.  
  137. /*
  138.  * Set a user-defined mark.
  139.  */
  140.     public void
  141. setmark(c)
  142.     int c;
  143. {
  144.     register struct mark *m;
  145.     struct scrpos scrpos;
  146.  
  147.     m = getumark(c);
  148.     if (m == NULL)
  149.         return;
  150.     get_scrpos(&scrpos);
  151.     m->m_scrpos = scrpos;
  152.     m->m_ifile = curr_ifile;
  153. }
  154.  
  155. /*
  156.  * Set lmark (the mark named by the apostrophe).
  157.  */
  158.     public void
  159. lastmark()
  160. {
  161.     struct scrpos scrpos;
  162.  
  163.     get_scrpos(&scrpos);
  164.     if (scrpos.pos == NULL_POSITION)
  165.         return;
  166.     lmark.m_scrpos = scrpos;
  167.     lmark.m_ifile = curr_ifile;
  168. }
  169.  
  170. /*
  171.  * Go to a mark.
  172.  */
  173.     public void
  174. gomark(c)
  175.     int c;
  176. {
  177.     register struct mark *m;
  178.     struct scrpos scrpos;
  179.  
  180.     m = getmark(c);
  181.     if (m == NULL)
  182.         return;
  183.  
  184.     /*
  185.      * If we're trying to go to the lastmark and 
  186.      * it has not been set to anything yet,
  187.      * set it to the beginning of the current file.
  188.      */
  189.     if (m == &lmark && m->m_scrpos.pos == NULL_POSITION)
  190.     {
  191.         m->m_ifile = curr_ifile;
  192.         m->m_scrpos.pos = ch_zero();
  193.         m->m_scrpos.ln = jump_sline;
  194.     }
  195.  
  196.     /*
  197.      * If we're using lmark, we must save the screen position now,
  198.      * because if we call edit() below, lmark will change.
  199.      * (We save the screen position even if we're not using lmark.)
  200.      */
  201.     scrpos = m->m_scrpos;
  202.     if (m->m_ifile != curr_ifile)
  203.     {
  204.         /*
  205.          * Not in the current file; edit the correct file.
  206.          */
  207.         if (edit(get_filename(m->m_ifile), 0))
  208.             return;
  209.     }
  210.  
  211.     jump_loc(scrpos.pos, scrpos.ln);
  212. }
  213.  
  214. /*
  215.  * Return the position associated with a given mark letter.
  216.  *
  217.  * We don't return which screen line the position 
  218.  * is associated with, but this doesn't matter much,
  219.  * because it's always the first non-blank line on the screen.
  220.  */
  221.     public POSITION
  222. markpos(c)
  223.     int c;
  224. {
  225.     register struct mark *m;
  226.  
  227.     m = getmark(c);
  228.     if (m == NULL)
  229.         return (NULL_POSITION);
  230.  
  231.     if (m->m_ifile != curr_ifile)
  232.     {
  233.         error("Mark not in current file", NULL_PARG);
  234.         return (NULL_POSITION);
  235.     }
  236.     return (m->m_scrpos.pos);
  237. }
  238.