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