160786Sps/* 2240121Sdelphij * Copyright (C) 1984-2012 Mark Nudelman 360786Sps * 460786Sps * You may distribute under the terms of either the GNU General Public 560786Sps * License or the Less License, as specified in the README file. 660786Sps * 7240121Sdelphij * For more information, see the README file. 860786Sps */ 960786Sps 1060786Sps 1160786Sps/* 1260786Sps * An IFILE represents an input file. 1360786Sps * 1460786Sps * It is actually a pointer to an ifile structure, 1560786Sps * but is opaque outside this module. 1660786Sps * Ifile structures are kept in a linked list in the order they 1760786Sps * appear on the command line. 1860786Sps * Any new file which does not already appear in the list is 1960786Sps * inserted after the current file. 2060786Sps */ 2160786Sps 2260786Sps#include "less.h" 2360786Sps 2460786Spsextern IFILE curr_ifile; 2560786Sps 2660786Spsstruct ifile { 2760786Sps struct ifile *h_next; /* Links for command line list */ 2860786Sps struct ifile *h_prev; 2960786Sps char *h_filename; /* Name of the file */ 3060786Sps void *h_filestate; /* File state (used in ch.c) */ 3160786Sps int h_index; /* Index within command line list */ 3260786Sps int h_hold; /* Hold count */ 3360786Sps char h_opened; /* Has this ifile been opened? */ 3460786Sps struct scrpos h_scrpos; /* Saved position within the file */ 3560786Sps}; 3660786Sps 3760786Sps/* 3860786Sps * Convert an IFILE (external representation) 3960786Sps * to a struct file (internal representation), and vice versa. 4060786Sps */ 4160786Sps#define int_ifile(h) ((struct ifile *)(h)) 4260786Sps#define ext_ifile(h) ((IFILE)(h)) 4360786Sps 4460786Sps/* 4560786Sps * Anchor for linked list. 4660786Sps */ 4760786Spsstatic struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0', 4860786Sps { NULL_POSITION, 0 } }; 4960786Spsstatic int ifiles = 0; 5060786Sps 5160786Sps static void 5260786Spsincr_index(p, incr) 5360786Sps register struct ifile *p; 5460786Sps int incr; 5560786Sps{ 5660786Sps for (; p != &anchor; p = p->h_next) 5760786Sps p->h_index += incr; 5860786Sps} 5960786Sps 6060786Sps/* 6160786Sps * Link an ifile into the ifile list. 6260786Sps */ 6360786Sps static void 6460786Spslink_ifile(p, prev) 6560786Sps struct ifile *p; 6660786Sps struct ifile *prev; 6760786Sps{ 6860786Sps /* 6960786Sps * Link into list. 7060786Sps */ 7160786Sps if (prev == NULL) 7260786Sps prev = &anchor; 7360786Sps p->h_next = prev->h_next; 7460786Sps p->h_prev = prev; 7560786Sps prev->h_next->h_prev = p; 7660786Sps prev->h_next = p; 7760786Sps /* 7860786Sps * Calculate index for the new one, 7960786Sps * and adjust the indexes for subsequent ifiles in the list. 8060786Sps */ 8160786Sps p->h_index = prev->h_index + 1; 8260786Sps incr_index(p->h_next, 1); 8360786Sps ifiles++; 8460786Sps} 8560786Sps 8660786Sps/* 8760786Sps * Unlink an ifile from the ifile list. 8860786Sps */ 8960786Sps static void 9060786Spsunlink_ifile(p) 9160786Sps struct ifile *p; 9260786Sps{ 9360786Sps p->h_next->h_prev = p->h_prev; 9460786Sps p->h_prev->h_next = p->h_next; 9560786Sps incr_index(p->h_next, -1); 9660786Sps ifiles--; 9760786Sps} 9860786Sps 9960786Sps/* 10060786Sps * Allocate a new ifile structure and stick a filename in it. 10160786Sps * It should go after "prev" in the list 10260786Sps * (or at the beginning of the list if "prev" is NULL). 10360786Sps * Return a pointer to the new ifile structure. 10460786Sps */ 10560786Sps static struct ifile * 10660786Spsnew_ifile(filename, prev) 10760786Sps char *filename; 10860786Sps struct ifile *prev; 10960786Sps{ 11060786Sps register struct ifile *p; 11160786Sps 11260786Sps /* 11360786Sps * Allocate and initialize structure. 11460786Sps */ 11560786Sps p = (struct ifile *) ecalloc(1, sizeof(struct ifile)); 11660786Sps p->h_filename = save(filename); 11760786Sps p->h_scrpos.pos = NULL_POSITION; 11860786Sps p->h_opened = 0; 11960786Sps p->h_hold = 0; 12060786Sps p->h_filestate = NULL; 12160786Sps link_ifile(p, prev); 12260786Sps return (p); 12360786Sps} 12460786Sps 12560786Sps/* 12660786Sps * Delete an existing ifile structure. 12760786Sps */ 12860786Sps public void 12960786Spsdel_ifile(h) 13060786Sps IFILE h; 13160786Sps{ 13260786Sps register struct ifile *p; 13360786Sps 13460786Sps if (h == NULL_IFILE) 13560786Sps return; 13660786Sps /* 13760786Sps * If the ifile we're deleting is the currently open ifile, 13860786Sps * move off it. 13960786Sps */ 14060786Sps unmark(h); 14160786Sps if (h == curr_ifile) 14260786Sps curr_ifile = getoff_ifile(curr_ifile); 14360786Sps p = int_ifile(h); 14460786Sps unlink_ifile(p); 14560786Sps free(p->h_filename); 14660786Sps free(p); 14760786Sps} 14860786Sps 14960786Sps/* 15060786Sps * Get the ifile after a given one in the list. 15160786Sps */ 15260786Sps public IFILE 15360786Spsnext_ifile(h) 15460786Sps IFILE h; 15560786Sps{ 15660786Sps register struct ifile *p; 15760786Sps 15860786Sps p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 15960786Sps if (p->h_next == &anchor) 16060786Sps return (NULL_IFILE); 16160786Sps return (ext_ifile(p->h_next)); 16260786Sps} 16360786Sps 16460786Sps/* 16560786Sps * Get the ifile before a given one in the list. 16660786Sps */ 16760786Sps public IFILE 16860786Spsprev_ifile(h) 16960786Sps IFILE h; 17060786Sps{ 17160786Sps register struct ifile *p; 17260786Sps 17360786Sps p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 17460786Sps if (p->h_prev == &anchor) 17560786Sps return (NULL_IFILE); 17660786Sps return (ext_ifile(p->h_prev)); 17760786Sps} 17860786Sps 17960786Sps/* 18060786Sps * Return a different ifile from the given one. 18160786Sps */ 18260786Sps public IFILE 18360786Spsgetoff_ifile(ifile) 18460786Sps IFILE ifile; 18560786Sps{ 18660786Sps IFILE newifile; 18760786Sps 18860786Sps if ((newifile = prev_ifile(ifile)) != NULL_IFILE) 18960786Sps return (newifile); 19060786Sps if ((newifile = next_ifile(ifile)) != NULL_IFILE) 19160786Sps return (newifile); 19260786Sps return (NULL_IFILE); 19360786Sps} 19460786Sps 19560786Sps/* 19660786Sps * Return the number of ifiles. 19760786Sps */ 19860786Sps public int 19960786Spsnifile() 20060786Sps{ 20160786Sps return (ifiles); 20260786Sps} 20360786Sps 20460786Sps/* 20560786Sps * Find an ifile structure, given a filename. 20660786Sps */ 20760786Sps static struct ifile * 20860786Spsfind_ifile(filename) 20960786Sps char *filename; 21060786Sps{ 21160786Sps register struct ifile *p; 21260786Sps 21360786Sps for (p = anchor.h_next; p != &anchor; p = p->h_next) 21460786Sps if (strcmp(filename, p->h_filename) == 0) 21560786Sps return (p); 21660786Sps return (NULL); 21760786Sps} 21860786Sps 21960786Sps/* 22060786Sps * Get the ifile associated with a filename. 22160786Sps * If the filename has not been seen before, 22260786Sps * insert the new ifile after "prev" in the list. 22360786Sps */ 22460786Sps public IFILE 22560786Spsget_ifile(filename, prev) 22660786Sps char *filename; 22760786Sps IFILE prev; 22860786Sps{ 22960786Sps register struct ifile *p; 23060786Sps 23160786Sps if ((p = find_ifile(filename)) == NULL) 23260786Sps p = new_ifile(filename, int_ifile(prev)); 23360786Sps return (ext_ifile(p)); 23460786Sps} 23560786Sps 23660786Sps/* 23760786Sps * Get the filename associated with a ifile. 23860786Sps */ 23960786Sps public char * 24060786Spsget_filename(ifile) 24160786Sps IFILE ifile; 24260786Sps{ 24360786Sps if (ifile == NULL) 24460786Sps return (NULL); 24560786Sps return (int_ifile(ifile)->h_filename); 24660786Sps} 24760786Sps 24860786Sps/* 24960786Sps * Get the index of the file associated with a ifile. 25060786Sps */ 25160786Sps public int 25260786Spsget_index(ifile) 25360786Sps IFILE ifile; 25460786Sps{ 25560786Sps return (int_ifile(ifile)->h_index); 25660786Sps} 25760786Sps 25860786Sps/* 25960786Sps * Save the file position to be associated with a given file. 26060786Sps */ 26160786Sps public void 26260786Spsstore_pos(ifile, scrpos) 26360786Sps IFILE ifile; 26460786Sps struct scrpos *scrpos; 26560786Sps{ 26660786Sps int_ifile(ifile)->h_scrpos = *scrpos; 26760786Sps} 26860786Sps 26960786Sps/* 27060786Sps * Recall the file position associated with a file. 27160786Sps * If no position has been associated with the file, return NULL_POSITION. 27260786Sps */ 27360786Sps public void 27460786Spsget_pos(ifile, scrpos) 27560786Sps IFILE ifile; 27660786Sps struct scrpos *scrpos; 27760786Sps{ 27860786Sps *scrpos = int_ifile(ifile)->h_scrpos; 27960786Sps} 28060786Sps 28160786Sps/* 28260786Sps * Mark the ifile as "opened". 28360786Sps */ 28460786Sps public void 28560786Spsset_open(ifile) 28660786Sps IFILE ifile; 28760786Sps{ 28860786Sps int_ifile(ifile)->h_opened = 1; 28960786Sps} 29060786Sps 29160786Sps/* 29260786Sps * Return whether the ifile has been opened previously. 29360786Sps */ 29460786Sps public int 29560786Spsopened(ifile) 29660786Sps IFILE ifile; 29760786Sps{ 29860786Sps return (int_ifile(ifile)->h_opened); 29960786Sps} 30060786Sps 30160786Sps public void 30260786Spshold_ifile(ifile, incr) 30360786Sps IFILE ifile; 30460786Sps int incr; 30560786Sps{ 30660786Sps int_ifile(ifile)->h_hold += incr; 30760786Sps} 30860786Sps 30960786Sps public int 31060786Spsheld_ifile(ifile) 31160786Sps IFILE ifile; 31260786Sps{ 31360786Sps return (int_ifile(ifile)->h_hold); 31460786Sps} 31560786Sps 31660786Sps public void * 31760786Spsget_filestate(ifile) 31860786Sps IFILE ifile; 31960786Sps{ 32060786Sps return (int_ifile(ifile)->h_filestate); 32160786Sps} 32260786Sps 32360786Sps public void 32460786Spsset_filestate(ifile, filestate) 32560786Sps IFILE ifile; 32660786Sps void *filestate; 32760786Sps{ 32860786Sps int_ifile(ifile)->h_filestate = filestate; 32960786Sps} 33060786Sps 33160786Sps#if 0 33260786Sps public void 33360786Spsif_dump() 33460786Sps{ 33560786Sps register struct ifile *p; 33660786Sps 33760786Sps for (p = anchor.h_next; p != &anchor; p = p->h_next) 33860786Sps { 33960786Sps printf("%x: %d. <%s> pos %d,%x\n", 34060786Sps p, p->h_index, p->h_filename, 34160786Sps p->h_scrpos.ln, p->h_scrpos.pos); 34260786Sps ch_dump(p->h_filestate); 34360786Sps } 34460786Sps} 34560786Sps#endif 346