home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / less373.zip / mark.c < prev    next >
C/C++ Source or Header  |  2002-01-14  |  5KB  |  259 lines

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