ifile.c revision 191930
1219974Smav/*
2219974Smav * Copyright (C) 1984-2008  Mark Nudelman
3219974Smav *
4219974Smav * You may distribute under the terms of either the GNU General Public
5219974Smav * License or the Less License, as specified in the README file.
6219974Smav *
7219974Smav * For more information about less, or for information on how to
8219974Smav * contact the author, see the README file.
9219974Smav */
10219974Smav
11219974Smav
12219974Smav/*
13219974Smav * An IFILE represents an input file.
14219974Smav *
15219974Smav * It is actually a pointer to an ifile structure,
16219974Smav * but is opaque outside this module.
17219974Smav * Ifile structures are kept in a linked list in the order they
18219974Smav * appear on the command line.
19219974Smav * Any new file which does not already appear in the list is
20219974Smav * inserted after the current file.
21219974Smav */
22219974Smav
23219974Smav#include "less.h"
24219974Smav
25219974Smavextern IFILE	curr_ifile;
26219974Smav
27219974Smavstruct ifile {
28219974Smav	struct ifile *h_next;		/* Links for command line list */
29219974Smav	struct ifile *h_prev;
30219974Smav	char *h_filename;		/* Name of the file */
31219974Smav	void *h_filestate;		/* File state (used in ch.c) */
32219974Smav	int h_index;			/* Index within command line list */
33219974Smav	int h_hold;			/* Hold count */
34219974Smav	char h_opened;			/* Has this ifile been opened? */
35219974Smav	struct scrpos h_scrpos;		/* Saved position within the file */
36219974Smav};
37219974Smav
38223921Sae/*
39219974Smav * Convert an IFILE (external representation)
40219974Smav * to a struct file (internal representation), and vice versa.
41219974Smav */
42219974Smav#define int_ifile(h)	((struct ifile *)(h))
43219974Smav#define ext_ifile(h)	((IFILE)(h))
44219974Smav
45219974Smav/*
46219974Smav * Anchor for linked list.
47219974Smav */
48219974Smavstatic struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0',
49219974Smav				{ NULL_POSITION, 0 } };
50219974Smavstatic int ifiles = 0;
51219974Smav
52219974Smav	static void
53219974Smavincr_index(p, incr)
54219974Smav	register struct ifile *p;
55219974Smav	int incr;
56219974Smav{
57219974Smav	for (;  p != &anchor;  p = p->h_next)
58219974Smav		p->h_index += incr;
59220790Smav}
60219974Smav
61219974Smav/*
62219974Smav * Link an ifile into the ifile list.
63219974Smav */
64219974Smav	static void
65219974Smavlink_ifile(p, prev)
66219974Smav	struct ifile *p;
67219974Smav	struct ifile *prev;
68219974Smav{
69219974Smav	/*
70219974Smav	 * Link into list.
71219974Smav	 */
72219974Smav	if (prev == NULL)
73219974Smav		prev = &anchor;
74219974Smav	p->h_next = prev->h_next;
75219974Smav	p->h_prev = prev;
76219974Smav	prev->h_next->h_prev = p;
77219974Smav	prev->h_next = p;
78219974Smav	/*
79219974Smav	 * Calculate index for the new one,
80219974Smav	 * and adjust the indexes for subsequent ifiles in the list.
81219974Smav	 */
82219974Smav	p->h_index = prev->h_index + 1;
83219974Smav	incr_index(p->h_next, 1);
84219974Smav	ifiles++;
85219974Smav}
86219974Smav
87219974Smav/*
88219974Smav * Unlink an ifile from the ifile list.
89219974Smav */
90219974Smav	static void
91219974Smavunlink_ifile(p)
92219974Smav	struct ifile *p;
93219974Smav{
94219974Smav	p->h_next->h_prev = p->h_prev;
95219974Smav	p->h_prev->h_next = p->h_next;
96219974Smav	incr_index(p->h_next, -1);
97219974Smav	ifiles--;
98219974Smav}
99219974Smav
100219974Smav/*
101219974Smav * Allocate a new ifile structure and stick a filename in it.
102219974Smav * It should go after "prev" in the list
103219974Smav * (or at the beginning of the list if "prev" is NULL).
104219974Smav * Return a pointer to the new ifile structure.
105219974Smav */
106219974Smav	static struct ifile *
107219974Smavnew_ifile(filename, prev)
108219974Smav	char *filename;
109219974Smav	struct ifile *prev;
110219974Smav{
111219974Smav	register struct ifile *p;
112219974Smav
113219974Smav	/*
114219974Smav	 * Allocate and initialize structure.
115219974Smav	 */
116219974Smav	p = (struct ifile *) ecalloc(1, sizeof(struct ifile));
117219974Smav	p->h_filename = save(filename);
118219974Smav	p->h_scrpos.pos = NULL_POSITION;
119219974Smav	p->h_opened = 0;
120219974Smav	p->h_hold = 0;
121219974Smav	p->h_filestate = NULL;
122219974Smav	link_ifile(p, prev);
123219974Smav	return (p);
124219974Smav}
125219974Smav
126219974Smav/*
127219974Smav * Delete an existing ifile structure.
128219974Smav */
129219974Smav	public void
130219974Smavdel_ifile(h)
131219974Smav	IFILE h;
132219974Smav{
133219974Smav	register struct ifile *p;
134219974Smav
135219974Smav	if (h == NULL_IFILE)
136219974Smav		return;
137219974Smav	/*
138219974Smav	 * If the ifile we're deleting is the currently open ifile,
139219974Smav	 * move off it.
140219974Smav	 */
141219974Smav	unmark(h);
142219974Smav	if (h == curr_ifile)
143219974Smav		curr_ifile = getoff_ifile(curr_ifile);
144219974Smav	p = int_ifile(h);
145219974Smav	unlink_ifile(p);
146219974Smav	free(p->h_filename);
147219974Smav	free(p);
148219974Smav}
149219974Smav
150219974Smav/*
151219974Smav * Get the ifile after a given one in the list.
152219974Smav */
153219974Smav	public IFILE
154219974Smavnext_ifile(h)
155219974Smav	IFILE h;
156219974Smav{
157219974Smav	register struct ifile *p;
158219974Smav
159219974Smav	p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
160219974Smav	if (p->h_next == &anchor)
161219974Smav		return (NULL_IFILE);
162219974Smav	return (ext_ifile(p->h_next));
163219974Smav}
164219974Smav
165219974Smav/*
166219974Smav * Get the ifile before a given one in the list.
167219974Smav */
168219974Smav	public IFILE
169219974Smavprev_ifile(h)
170219974Smav	IFILE h;
171219974Smav{
172219974Smav	register struct ifile *p;
173219974Smav
174219974Smav	p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
175219974Smav	if (p->h_prev == &anchor)
176219974Smav		return (NULL_IFILE);
177219974Smav	return (ext_ifile(p->h_prev));
178219974Smav}
179219974Smav
180219974Smav/*
181219974Smav * Return a different ifile from the given one.
182219974Smav */
183219974Smav	public IFILE
184219974Smavgetoff_ifile(ifile)
185219974Smav	IFILE ifile;
186219974Smav{
187219974Smav	IFILE newifile;
188219974Smav
189219974Smav	if ((newifile = prev_ifile(ifile)) != NULL_IFILE)
190219974Smav		return (newifile);
191219974Smav	if ((newifile = next_ifile(ifile)) != NULL_IFILE)
192219974Smav		return (newifile);
193219974Smav	return (NULL_IFILE);
194219974Smav}
195219974Smav
196219974Smav/*
197219974Smav * Return the number of ifiles.
198219974Smav */
199219974Smav	public int
200219974Smavnifile()
201219974Smav{
202219974Smav	return (ifiles);
203219974Smav}
204219974Smav
205219974Smav/*
206219974Smav * Find an ifile structure, given a filename.
207219974Smav */
208219974Smav	static struct ifile *
209219974Smavfind_ifile(filename)
210219974Smav	char *filename;
211219974Smav{
212219974Smav	register struct ifile *p;
213219974Smav
214219974Smav	for (p = anchor.h_next;  p != &anchor;  p = p->h_next)
215219974Smav		if (strcmp(filename, p->h_filename) == 0)
216219974Smav			return (p);
217219974Smav	return (NULL);
218219974Smav}
219219974Smav
220219974Smav/*
221239175Smav * Get the ifile associated with a filename.
222239175Smav * If the filename has not been seen before,
223219974Smav * insert the new ifile after "prev" in the list.
224219974Smav */
225219974Smav	public IFILE
226219974Smavget_ifile(filename, prev)
227219974Smav	char *filename;
228219974Smav	IFILE prev;
229219974Smav{
230219974Smav	register struct ifile *p;
231219974Smav
232219974Smav	if ((p = find_ifile(filename)) == NULL)
233219974Smav		p = new_ifile(filename, int_ifile(prev));
234219974Smav	return (ext_ifile(p));
235219974Smav}
236219974Smav
237219974Smav/*
238219974Smav * Get the filename associated with a ifile.
239219974Smav */
240219974Smav	public char *
241219974Smavget_filename(ifile)
242219974Smav	IFILE ifile;
243219974Smav{
244219974Smav	if (ifile == NULL)
245219974Smav		return (NULL);
246219974Smav	return (int_ifile(ifile)->h_filename);
247219974Smav}
248219974Smav
249219974Smav/*
250219974Smav * Get the index of the file associated with a ifile.
251219974Smav */
252219974Smav	public int
253219974Smavget_index(ifile)
254219974Smav	IFILE ifile;
255219974Smav{
256219974Smav	return (int_ifile(ifile)->h_index);
257219974Smav}
258219974Smav
259219974Smav/*
260219974Smav * Save the file position to be associated with a given file.
261219974Smav */
262219974Smav	public void
263219974Smavstore_pos(ifile, scrpos)
264219974Smav	IFILE ifile;
265219974Smav	struct scrpos *scrpos;
266219974Smav{
267219974Smav	int_ifile(ifile)->h_scrpos = *scrpos;
268219974Smav}
269219974Smav
270219974Smav/*
271219974Smav * Recall the file position associated with a file.
272219974Smav * If no position has been associated with the file, return NULL_POSITION.
273219974Smav */
274219974Smav	public void
275219974Smavget_pos(ifile, scrpos)
276219974Smav	IFILE ifile;
277219974Smav	struct scrpos *scrpos;
278219974Smav{
279219974Smav	*scrpos = int_ifile(ifile)->h_scrpos;
280219974Smav}
281219974Smav
282234603Smav/*
283234603Smav * Mark the ifile as "opened".
284234603Smav */
285234603Smav	public void
286219974Smavset_open(ifile)
287219974Smav	IFILE ifile;
288234603Smav{
289234610Smav	int_ifile(ifile)->h_opened = 1;
290234603Smav}
291234610Smav
292219974Smav/*
293219974Smav * Return whether the ifile has been opened previously.
294234458Smav */
295234603Smav	public int
296234458Smavopened(ifile)
297234603Smav	IFILE ifile;
298234458Smav{
299234603Smav	return (int_ifile(ifile)->h_opened);
300234458Smav}
301234603Smav
302219974Smav	public void
303219974Smavhold_ifile(ifile, incr)
304234603Smav	IFILE ifile;
305234603Smav	int incr;
306234603Smav{
307234603Smav	int_ifile(ifile)->h_hold += incr;
308234603Smav}
309234603Smav
310234603Smav	public int
311234603Smavheld_ifile(ifile)
312219974Smav	IFILE ifile;
313234603Smav{
314234603Smav	return (int_ifile(ifile)->h_hold);
315234603Smav}
316234603Smav
317234603Smav	public void *
318234603Smavget_filestate(ifile)
319234603Smav	IFILE ifile;
320234603Smav{
321234603Smav	return (int_ifile(ifile)->h_filestate);
322234603Smav}
323219974Smav
324234603Smav	public void
325234603Smavset_filestate(ifile, filestate)
326234603Smav	IFILE ifile;
327234603Smav	void *filestate;
328219974Smav{
329219974Smav	int_ifile(ifile)->h_filestate = filestate;
330219974Smav}
331219974Smav
332219974Smav#if 0
333219974Smav	public void
334234603Smavif_dump()
335234603Smav{
336234603Smav	register struct ifile *p;
337234603Smav
338234603Smav	for (p = anchor.h_next;  p != &anchor;  p = p->h_next)
339234603Smav	{
340234603Smav		printf("%x: %d. <%s> pos %d,%x\n",
341234603Smav			p, p->h_index, p->h_filename,
342219974Smav			p->h_scrpos.ln, p->h_scrpos.pos);
343219974Smav		ch_dump(p->h_filestate);
344234603Smav	}
345234603Smav}
346234603Smav#endif
347234603Smav