2 * Copyright (C) 1984-2007 Mark Nudelman
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.
7 * For more information about less, or for information on how to
8 * contact the author, see the README file.
13 * An IFILE represents an input file.
15 * It is actually a pointer to an ifile structure,
16 * but is opaque outside this module.
17 * Ifile structures are kept in a linked list in the order they
18 * appear on the command line.
19 * Any new file which does not already appear in the list is
20 * inserted after the current file.
25 extern IFILE curr_ifile
;
28 struct ifile
*h_next
; /* Links for command line list */
30 char *h_filename
; /* Name of the file */
31 void *h_filestate
; /* File state (used in ch.c) */
32 int h_index
; /* Index within command line list */
33 int h_hold
; /* Hold count */
34 char h_opened
; /* Has this ifile been opened? */
35 struct scrpos h_scrpos
; /* Saved position within the file */
39 * Convert an IFILE (external representation)
40 * to a struct file (internal representation), and vice versa.
42 #define int_ifile(h) ((struct ifile *)(h))
43 #define ext_ifile(h) ((IFILE)(h))
46 * Anchor for linked list.
48 static struct ifile anchor
= { &anchor
, &anchor
, NULL
, NULL
, 0, 0, '\0',
49 { NULL_POSITION
, 0 } };
50 static int ifiles
= 0;
54 register struct ifile
*p
;
57 for (; p
!= &anchor
; p
= p
->h_next
)
62 * Link an ifile into the ifile list.
74 p
->h_next
= prev
->h_next
;
76 prev
->h_next
->h_prev
= p
;
79 * Calculate index for the new one,
80 * and adjust the indexes for subsequent ifiles in the list.
82 p
->h_index
= prev
->h_index
+ 1;
83 incr_index(p
->h_next
, 1);
88 * Unlink an ifile from the ifile list.
94 p
->h_next
->h_prev
= p
->h_prev
;
95 p
->h_prev
->h_next
= p
->h_next
;
96 incr_index(p
->h_next
, -1);
101 * Allocate a new ifile structure and stick a filename in it.
102 * It should go after "prev" in the list
103 * (or at the beginning of the list if "prev" is NULL).
104 * Return a pointer to the new ifile structure.
106 static struct ifile
*
107 new_ifile(filename
, prev
)
111 register struct ifile
*p
;
114 * Allocate and initialize structure.
116 p
= (struct ifile
*) ecalloc(1, sizeof(struct ifile
));
117 p
->h_filename
= save(filename
);
118 p
->h_scrpos
.pos
= NULL_POSITION
;
121 p
->h_filestate
= NULL
;
127 * Delete an existing ifile structure.
133 register struct ifile
*p
;
138 * If the ifile we're deleting is the currently open ifile,
143 curr_ifile
= getoff_ifile(curr_ifile
);
151 * Get the ifile after a given one in the list.
157 register struct ifile
*p
;
159 p
= (h
== NULL_IFILE
) ? &anchor
: int_ifile(h
);
160 if (p
->h_next
== &anchor
)
162 return (ext_ifile(p
->h_next
));
166 * Get the ifile before a given one in the list.
172 register struct ifile
*p
;
174 p
= (h
== NULL_IFILE
) ? &anchor
: int_ifile(h
);
175 if (p
->h_prev
== &anchor
)
177 return (ext_ifile(p
->h_prev
));
181 * Return a different ifile from the given one.
189 if ((newifile
= prev_ifile(ifile
)) != NULL_IFILE
)
191 if ((newifile
= next_ifile(ifile
)) != NULL_IFILE
)
197 * Return the number of ifiles.
206 * Find an ifile structure, given a filename.
208 static struct ifile
*
212 register struct ifile
*p
;
214 for (p
= anchor
.h_next
; p
!= &anchor
; p
= p
->h_next
)
215 if (strcmp(filename
, p
->h_filename
) == 0)
221 * Get the ifile associated with a filename.
222 * If the filename has not been seen before,
223 * insert the new ifile after "prev" in the list.
226 get_ifile(filename
, prev
)
230 register struct ifile
*p
;
232 if ((p
= find_ifile(filename
)) == NULL
)
233 p
= new_ifile(filename
, int_ifile(prev
));
234 return (ext_ifile(p
));
238 * Get the filename associated with a ifile.
246 return (int_ifile(ifile
)->h_filename
);
250 * Get the index of the file associated with a ifile.
256 return (int_ifile(ifile
)->h_index
);
260 * Save the file position to be associated with a given file.
263 store_pos(ifile
, scrpos
)
265 struct scrpos
*scrpos
;
267 int_ifile(ifile
)->h_scrpos
= *scrpos
;
271 * Recall the file position associated with a file.
272 * If no position has been associated with the file, return NULL_POSITION.
275 get_pos(ifile
, scrpos
)
277 struct scrpos
*scrpos
;
279 *scrpos
= int_ifile(ifile
)->h_scrpos
;
283 * Mark the ifile as "opened".
289 int_ifile(ifile
)->h_opened
= 1;
293 * Return whether the ifile has been opened previously.
299 return (int_ifile(ifile
)->h_opened
);
303 hold_ifile(ifile
, incr
)
307 int_ifile(ifile
)->h_hold
+= incr
;
314 return (int_ifile(ifile
)->h_hold
);
321 return (int_ifile(ifile
)->h_filestate
);
325 set_filestate(ifile
, filestate
)
329 int_ifile(ifile
)->h_filestate
= filestate
;
336 register struct ifile
*p
;
338 for (p
= anchor
.h_next
; p
!= &anchor
; p
= p
->h_next
)
340 printf("%x: %d. <%s> pos %d,%x\n",
341 p
, p
->h_index
, p
->h_filename
,
342 p
->h_scrpos
.ln
, p
->h_scrpos
.pos
);
343 ch_dump(p
->h_filestate
);