Expand PMF_FN_* macros.
[netbsd-mini2440.git] / distrib / utils / more / input.c
blob4ab19e06726589ddf8dd258480630d0a8a03aa16
1 /* $NetBSD: input.c,v 1.5 2003/08/07 09:27:59 agc Exp $ */
3 /*
4 * Copyright (c) 1988 Mark Nudelman
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 #ifndef lint
35 #if 0
36 static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/6/93";
37 #else
38 __RCSID("$NetBSD: input.c,v 1.5 2003/08/07 09:27:59 agc Exp $");
39 #endif
40 #endif /* not lint */
43 * High level routines dealing with getting lines of input
44 * from the file being viewed.
46 * When we speak of "lines" here, we mean PRINTABLE lines;
47 * lines processed with respect to the screen width.
48 * We use the term "raw line" to refer to lines simply
49 * delimited by newlines; not processed with respect to screen width.
52 #include <sys/types.h>
54 #include "less.h"
55 #include "extern.h"
58 * Get the next line.
59 * A "current" position is passed and a "new" position is returned.
60 * The current position is the position of the first character of
61 * a line. The new position is the position of the first character
62 * of the NEXT line. The line obtained is the line starting at curr_pos.
64 off_t
65 forw_line(curr_pos)
66 off_t curr_pos;
68 off_t new_pos;
69 int c;
71 if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
72 return (NULL_POSITION);
74 c = ch_forw_get();
75 if (c == EOI)
76 return (NULL_POSITION);
78 prewind();
79 for (;;)
81 if (sigs)
82 return (NULL_POSITION);
83 if (c == '\n' || c == EOI)
86 * End of the line.
88 new_pos = ch_tell();
89 break;
93 * Append the char to the line and get the next char.
95 if (pappend(c))
98 * The char won't fit in the line; the line
99 * is too long to print in the screen width.
100 * End the line here.
102 new_pos = ch_tell() - 1;
103 break;
105 c = ch_forw_get();
107 (void) pappend('\0');
109 if (squeeze && *line == '\0')
112 * This line is blank.
113 * Skip down to the last contiguous blank line
114 * and pretend it is the one which we are returning.
116 while ((c = ch_forw_get()) == '\n')
117 if (sigs)
118 return (NULL_POSITION);
119 if (c != EOI)
120 (void) ch_back_get();
121 new_pos = ch_tell();
124 return (new_pos);
128 * Get the previous line.
129 * A "current" position is passed and a "new" position is returned.
130 * The current position is the position of the first character of
131 * a line. The new position is the position of the first character
132 * of the PREVIOUS line. The line obtained is the one starting at new_pos.
134 off_t
135 back_line(curr_pos)
136 off_t curr_pos;
138 off_t new_pos, begin_new_pos;
139 int c;
141 if (curr_pos == NULL_POSITION || curr_pos <= (off_t)0 ||
142 ch_seek(curr_pos-1))
143 return (NULL_POSITION);
145 if (squeeze)
148 * Find out if the "current" line was blank.
150 (void) ch_forw_get(); /* Skip the newline */
151 c = ch_forw_get(); /* First char of "current" line */
152 (void) ch_back_get(); /* Restore our position */
153 (void) ch_back_get();
155 if (c == '\n')
158 * The "current" line was blank.
159 * Skip over any preceding blank lines,
160 * since we skipped them in forw_line().
162 while ((c = ch_back_get()) == '\n')
163 if (sigs)
164 return (NULL_POSITION);
165 if (c == EOI)
166 return (NULL_POSITION);
167 (void) ch_forw_get();
172 * Scan backwards until we hit the beginning of the line.
174 for (;;)
176 if (sigs)
177 return (NULL_POSITION);
178 c = ch_back_get();
179 if (c == '\n')
182 * This is the newline ending the previous line.
183 * We have hit the beginning of the line.
185 new_pos = ch_tell() + 1;
186 break;
188 if (c == EOI)
191 * We have hit the beginning of the file.
192 * This must be the first line in the file.
193 * This must, of course, be the beginning of the line.
195 new_pos = ch_tell();
196 break;
201 * Now scan forwards from the beginning of this line.
202 * We keep discarding "printable lines" (based on screen width)
203 * until we reach the curr_pos.
205 * {{ This algorithm is pretty inefficient if the lines
206 * are much longer than the screen width,
207 * but I don't know of any better way. }}
209 if (ch_seek(new_pos))
210 return (NULL_POSITION);
211 loop:
212 begin_new_pos = new_pos;
213 prewind();
217 c = ch_forw_get();
218 if (c == EOI || sigs)
219 return (NULL_POSITION);
220 new_pos++;
221 if (c == '\n')
222 break;
223 if (pappend(c))
226 * Got a full printable line, but we haven't
227 * reached our curr_pos yet. Discard the line
228 * and start a new one.
230 (void) pappend('\0');
231 (void) ch_back_get();
232 new_pos--;
233 goto loop;
235 } while (new_pos < curr_pos);
237 (void) pappend('\0');
239 return (begin_new_pos);