home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less3292.zip / ifile.c < prev    next >
C/C++ Source or Header  |  1996-08-13  |  7KB  |  355 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. /*
  29.  * An IFILE represents an input file.
  30.  *
  31.  * It is actually a pointer to an ifile structure,
  32.  * but is opaque outside this module.
  33.  * Ifile structures are kept in a linked list in the order they 
  34.  * appear on the command line.
  35.  * Any new file which does not already appear in the list is
  36.  * inserted after the current file.
  37.  */
  38.  
  39. #include "less.h"
  40.  
  41. extern IFILE    curr_ifile;
  42.  
  43. struct ifile {
  44.     struct ifile *h_next;        /* Links for command line list */
  45.     struct ifile *h_prev;
  46.     char *h_filename;        /* Name of the file */
  47.     void *h_filestate;        /* File state (used in ch.c) */
  48.     int h_index;            /* Index within command line list */
  49.     int h_hold;            /* Hold count */
  50.     char h_opened;            /* Has this ifile been opened? */
  51.     struct scrpos h_scrpos;        /* Saved position within the file */
  52. };
  53.  
  54. /*
  55.  * Convert an IFILE (external representation)
  56.  * to a struct file (internal representation), and vice versa.
  57.  */
  58. #define int_ifile(h)    ((struct ifile *)(h))
  59. #define ext_ifile(h)    ((IFILE)(h))
  60.  
  61. /*
  62.  * Anchor for linked list.
  63.  */
  64. static struct ifile anchor = { &anchor, &anchor, 0 };
  65. static int ifiles = 0;
  66.  
  67.     static void
  68. incr_index(p, incr)
  69.     register struct ifile *p;
  70.     int incr;
  71. {
  72.     for (;  p != &anchor;  p = p->h_next)
  73.         p->h_index += incr;
  74. }
  75.  
  76.     static void
  77. link_ifile(p, prev)
  78.     struct ifile *p;
  79.     struct ifile *prev;
  80. {
  81.     /*
  82.      * Link into list.
  83.      */
  84.     if (prev == NULL)
  85.         prev = &anchor;
  86.     p->h_next = prev->h_next;
  87.     p->h_prev = prev;
  88.     prev->h_next->h_prev = p;
  89.     prev->h_next = p;
  90.     /*
  91.      * Calculate index for the new one,
  92.      * and adjust the indexes for subsequent ifiles in the list.
  93.      */
  94.     p->h_index = prev->h_index + 1;
  95.     incr_index(p->h_next, 1);
  96.     ifiles++;
  97. }
  98.     
  99.     static void
  100. unlink_ifile(p)
  101.     struct ifile *p;
  102. {
  103.     p->h_next->h_prev = p->h_prev;
  104.     p->h_prev->h_next = p->h_next;
  105.     incr_index(p->h_next, -1);
  106.     ifiles--;
  107. }
  108.  
  109. /*
  110.  * Allocate a new ifile structure and stick a filename in it.
  111.  * It should go after "prev" in the list
  112.  * (or at the beginning of the list if "prev" is NULL).
  113.  * Return a pointer to the new ifile structure.
  114.  */
  115.     static struct ifile *
  116. new_ifile(filename, prev)
  117.     char *filename;
  118.     struct ifile *prev;
  119. {
  120.     register struct ifile *p;
  121.  
  122.     /*
  123.      * Allocate and initialize structure.
  124.      */
  125.     p = (struct ifile *) ecalloc(1, sizeof(struct ifile));
  126.     p->h_filename = save(filename);
  127.     p->h_scrpos.pos = NULL_POSITION;
  128.     p->h_opened = 0;
  129.     p->h_hold = 0;
  130.     p->h_filestate = NULL;
  131.     link_ifile(p, prev);
  132.     return (p);
  133. }
  134.  
  135. /*
  136.  * Delete an existing ifile structure.
  137.  */
  138.     public void
  139. del_ifile(h)
  140.     IFILE h;
  141. {
  142.     register struct ifile *p;
  143.  
  144.     if (h == NULL_IFILE)
  145.         return;
  146.     /*
  147.      * If the ifile we're deleting is the currently open ifile,
  148.      * move off it.
  149.      */
  150.     if (h == curr_ifile)
  151.         curr_ifile = getoff_ifile(curr_ifile);
  152.     p = int_ifile(h);
  153.     unlink_ifile(p);
  154.     free(p->h_filename);
  155.     free(p);
  156. }
  157.  
  158. /*
  159.  * Get the ifile after a given one in the list.
  160.  */
  161.     public IFILE
  162. next_ifile(h)
  163.     IFILE h;
  164. {
  165.     register struct ifile *p;
  166.  
  167.     p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
  168.     if (p->h_next == &anchor)
  169.         return (NULL_IFILE);
  170.     return (ext_ifile(p->h_next));
  171. }
  172.  
  173. /*
  174.  * Get the ifile before a given one in the list.
  175.  */
  176.     public IFILE
  177. prev_ifile(h)
  178.     IFILE h;
  179. {
  180.     register struct ifile *p;
  181.  
  182.     p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
  183.     if (p->h_prev == &anchor)
  184.         return (NULL_IFILE);
  185.     return (ext_ifile(p->h_prev));
  186. }
  187.  
  188. /*
  189.  * Return a different ifile from the given one.
  190.  */
  191.     public IFILE
  192. getoff_ifile(ifile)
  193.     IFILE ifile;
  194. {
  195.     IFILE newifile;
  196.     
  197.     if ((newifile = prev_ifile(ifile)) != NULL_IFILE)
  198.         return (newifile);
  199.     if ((newifile = next_ifile(ifile)) != NULL_IFILE)
  200.         return (newifile);
  201.     return (NULL_IFILE);
  202. }
  203.  
  204. /*
  205.  * Return the number of ifiles.
  206.  */
  207.     public int
  208. nifile()
  209. {
  210.     return (ifiles);
  211. }
  212.  
  213. /*
  214.  * Find an ifile structure, given a filename.
  215.  */
  216.     static struct ifile *
  217. find_ifile(filename)
  218.     char *filename;
  219. {
  220.     register struct ifile *p;
  221.  
  222.     for (p = anchor.h_next;  p != &anchor;  p = p->h_next)
  223.         if (strcmp(filename, p->h_filename) == 0)
  224.             return (p);
  225.     return (NULL);
  226. }
  227.  
  228. /*
  229.  * Get the ifile associated with a filename.
  230.  * If the filename has not been seen before,
  231.  * insert the new ifile after "prev" in the list.
  232.  */
  233.     public IFILE
  234. get_ifile(filename, prev)
  235.     char *filename;
  236.     IFILE prev;
  237. {
  238.     register struct ifile *p;
  239.  
  240.     if ((p = find_ifile(filename)) == NULL)
  241.         p = new_ifile(filename, int_ifile(prev));
  242.     return (ext_ifile(p));
  243. }
  244.  
  245. /*
  246.  * Get the filename associated with a ifile.
  247.  */
  248.     public char *
  249. get_filename(ifile)
  250.     IFILE ifile;
  251. {
  252.     if (ifile == NULL)
  253.         return (NULL);
  254.     return (int_ifile(ifile)->h_filename);
  255. }
  256.  
  257. /*
  258.  * Get the index of the file associated with a ifile.
  259.  */
  260.     public int
  261. get_index(ifile)
  262.     IFILE ifile;
  263. {
  264.     return (int_ifile(ifile)->h_index); 
  265. }
  266.  
  267. /*
  268.  * Save the file position to be associated with a given file.
  269.  */
  270.     public void
  271. store_pos(ifile, scrpos)
  272.     IFILE ifile;
  273.     struct scrpos *scrpos;
  274. {
  275.     int_ifile(ifile)->h_scrpos = *scrpos;
  276. }
  277.  
  278. /*
  279.  * Recall the file position associated with a file.
  280.  * If no position has been associated with the file, return NULL_POSITION.
  281.  */
  282.     public void
  283. get_pos(ifile, scrpos)
  284.     IFILE ifile;
  285.     struct scrpos *scrpos;
  286. {
  287.     *scrpos = int_ifile(ifile)->h_scrpos;
  288. }
  289.  
  290. /*
  291.  * Mark the ifile as "opened".
  292.  */
  293.     public void
  294. set_open(ifile)
  295.     IFILE ifile;
  296. {
  297.     int_ifile(ifile)->h_opened = 1;
  298. }
  299.  
  300. /*
  301.  * Return whether the ifile has been opened previously.
  302.  */
  303.     public int
  304. opened(ifile)
  305.     IFILE ifile;
  306. {
  307.     return (int_ifile(ifile)->h_opened);
  308. }
  309.  
  310.     public void
  311. hold_ifile(ifile, incr)
  312.     IFILE ifile;
  313.     int incr;
  314. {
  315.     int_ifile(ifile)->h_hold += incr;
  316. }
  317.  
  318.     public int
  319. held_ifile(ifile)
  320.     IFILE ifile;
  321. {
  322.     return (int_ifile(ifile)->h_hold);
  323. }
  324.  
  325.     public void *
  326. get_filestate(ifile)
  327.     IFILE ifile;
  328. {
  329.     return (int_ifile(ifile)->h_filestate);
  330. }
  331.  
  332.     public void
  333. set_filestate(ifile, filestate)
  334.     IFILE ifile;
  335.     void *filestate;
  336. {
  337.     int_ifile(ifile)->h_filestate = filestate;
  338. }
  339.  
  340. #if 0
  341.     public void
  342. if_dump()
  343. {
  344.     register struct ifile *p;
  345.  
  346.     for (p = anchor.h_next;  p != &anchor;  p = p->h_next)
  347.     {
  348.         printf("%x: %d. <%s> pos %d,%x\n", 
  349.             p, p->h_index, p->h_filename, 
  350.             p->h_scrpos.ln, p->h_scrpos.pos);
  351.         ch_dump(p->h_filestate);
  352.     }
  353. }
  354. #endif
  355.