input.c revision 1.2 1 1.2 perry /* $NetBSD: input.c,v 1.2 1998/01/09 08:03:27 perry 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.1 cjs #ifndef lint
38 1.1 cjs static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/6/93";
39 1.1 cjs #endif /* not lint */
40 1.1 cjs
41 1.1 cjs /*
42 1.1 cjs * High level routines dealing with getting lines of input
43 1.1 cjs * from the file being viewed.
44 1.1 cjs *
45 1.1 cjs * When we speak of "lines" here, we mean PRINTABLE lines;
46 1.1 cjs * lines processed with respect to the screen width.
47 1.1 cjs * We use the term "raw line" to refer to lines simply
48 1.1 cjs * delimited by newlines; not processed with respect to screen width.
49 1.1 cjs */
50 1.1 cjs
51 1.1 cjs #include <sys/types.h>
52 1.1 cjs #include <less.h>
53 1.1 cjs
54 1.1 cjs extern int squeeze;
55 1.1 cjs extern int sigs;
56 1.1 cjs extern char *line;
57 1.1 cjs
58 1.1 cjs off_t ch_tell();
59 1.1 cjs
60 1.1 cjs /*
61 1.1 cjs * Get the next line.
62 1.1 cjs * A "current" position is passed and a "new" position is returned.
63 1.1 cjs * The current position is the position of the first character of
64 1.1 cjs * a line. The new position is the position of the first character
65 1.1 cjs * of the NEXT line. The line obtained is the line starting at curr_pos.
66 1.1 cjs */
67 1.1 cjs off_t
68 1.1 cjs forw_line(curr_pos)
69 1.1 cjs off_t curr_pos;
70 1.1 cjs {
71 1.1 cjs off_t new_pos;
72 1.1 cjs register int c;
73 1.1 cjs
74 1.1 cjs if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
75 1.1 cjs return (NULL_POSITION);
76 1.1 cjs
77 1.1 cjs c = ch_forw_get();
78 1.1 cjs if (c == EOI)
79 1.1 cjs return (NULL_POSITION);
80 1.1 cjs
81 1.1 cjs prewind();
82 1.1 cjs for (;;)
83 1.1 cjs {
84 1.1 cjs if (sigs)
85 1.1 cjs return (NULL_POSITION);
86 1.1 cjs if (c == '\n' || c == EOI)
87 1.1 cjs {
88 1.1 cjs /*
89 1.1 cjs * End of the line.
90 1.1 cjs */
91 1.1 cjs new_pos = ch_tell();
92 1.1 cjs break;
93 1.1 cjs }
94 1.1 cjs
95 1.1 cjs /*
96 1.1 cjs * Append the char to the line and get the next char.
97 1.1 cjs */
98 1.1 cjs if (pappend(c))
99 1.1 cjs {
100 1.1 cjs /*
101 1.1 cjs * The char won't fit in the line; the line
102 1.1 cjs * is too long to print in the screen width.
103 1.1 cjs * End the line here.
104 1.1 cjs */
105 1.1 cjs new_pos = ch_tell() - 1;
106 1.1 cjs break;
107 1.1 cjs }
108 1.1 cjs c = ch_forw_get();
109 1.1 cjs }
110 1.1 cjs (void) pappend('\0');
111 1.1 cjs
112 1.1 cjs if (squeeze && *line == '\0')
113 1.1 cjs {
114 1.1 cjs /*
115 1.1 cjs * This line is blank.
116 1.1 cjs * Skip down to the last contiguous blank line
117 1.1 cjs * and pretend it is the one which we are returning.
118 1.1 cjs */
119 1.1 cjs while ((c = ch_forw_get()) == '\n')
120 1.1 cjs if (sigs)
121 1.1 cjs return (NULL_POSITION);
122 1.1 cjs if (c != EOI)
123 1.1 cjs (void) ch_back_get();
124 1.1 cjs new_pos = ch_tell();
125 1.1 cjs }
126 1.1 cjs
127 1.1 cjs return (new_pos);
128 1.1 cjs }
129 1.1 cjs
130 1.1 cjs /*
131 1.1 cjs * Get the previous line.
132 1.1 cjs * A "current" position is passed and a "new" position is returned.
133 1.1 cjs * The current position is the position of the first character of
134 1.1 cjs * a line. The new position is the position of the first character
135 1.1 cjs * of the PREVIOUS line. The line obtained is the one starting at new_pos.
136 1.1 cjs */
137 1.1 cjs off_t
138 1.1 cjs back_line(curr_pos)
139 1.1 cjs off_t curr_pos;
140 1.1 cjs {
141 1.1 cjs off_t new_pos, begin_new_pos;
142 1.1 cjs int c;
143 1.1 cjs
144 1.1 cjs if (curr_pos == NULL_POSITION || curr_pos <= (off_t)0 ||
145 1.1 cjs ch_seek(curr_pos-1))
146 1.1 cjs return (NULL_POSITION);
147 1.1 cjs
148 1.1 cjs if (squeeze)
149 1.1 cjs {
150 1.1 cjs /*
151 1.1 cjs * Find out if the "current" line was blank.
152 1.1 cjs */
153 1.1 cjs (void) ch_forw_get(); /* Skip the newline */
154 1.1 cjs c = ch_forw_get(); /* First char of "current" line */
155 1.1 cjs (void) ch_back_get(); /* Restore our position */
156 1.1 cjs (void) ch_back_get();
157 1.1 cjs
158 1.1 cjs if (c == '\n')
159 1.1 cjs {
160 1.1 cjs /*
161 1.1 cjs * The "current" line was blank.
162 1.1 cjs * Skip over any preceeding blank lines,
163 1.1 cjs * since we skipped them in forw_line().
164 1.1 cjs */
165 1.1 cjs while ((c = ch_back_get()) == '\n')
166 1.1 cjs if (sigs)
167 1.1 cjs return (NULL_POSITION);
168 1.1 cjs if (c == EOI)
169 1.1 cjs return (NULL_POSITION);
170 1.1 cjs (void) ch_forw_get();
171 1.1 cjs }
172 1.1 cjs }
173 1.1 cjs
174 1.1 cjs /*
175 1.1 cjs * Scan backwards until we hit the beginning of the line.
176 1.1 cjs */
177 1.1 cjs for (;;)
178 1.1 cjs {
179 1.1 cjs if (sigs)
180 1.1 cjs return (NULL_POSITION);
181 1.1 cjs c = ch_back_get();
182 1.1 cjs if (c == '\n')
183 1.1 cjs {
184 1.1 cjs /*
185 1.1 cjs * This is the newline ending the previous line.
186 1.1 cjs * We have hit the beginning of the line.
187 1.1 cjs */
188 1.1 cjs new_pos = ch_tell() + 1;
189 1.1 cjs break;
190 1.1 cjs }
191 1.1 cjs if (c == EOI)
192 1.1 cjs {
193 1.1 cjs /*
194 1.1 cjs * We have hit the beginning of the file.
195 1.1 cjs * This must be the first line in the file.
196 1.1 cjs * This must, of course, be the beginning of the line.
197 1.1 cjs */
198 1.1 cjs new_pos = ch_tell();
199 1.1 cjs break;
200 1.1 cjs }
201 1.1 cjs }
202 1.1 cjs
203 1.1 cjs /*
204 1.1 cjs * Now scan forwards from the beginning of this line.
205 1.1 cjs * We keep discarding "printable lines" (based on screen width)
206 1.1 cjs * until we reach the curr_pos.
207 1.1 cjs *
208 1.1 cjs * {{ This algorithm is pretty inefficient if the lines
209 1.1 cjs * are much longer than the screen width,
210 1.1 cjs * but I don't know of any better way. }}
211 1.1 cjs */
212 1.1 cjs if (ch_seek(new_pos))
213 1.1 cjs return (NULL_POSITION);
214 1.1 cjs loop:
215 1.1 cjs begin_new_pos = new_pos;
216 1.1 cjs prewind();
217 1.1 cjs
218 1.1 cjs do
219 1.1 cjs {
220 1.1 cjs c = ch_forw_get();
221 1.1 cjs if (c == EOI || sigs)
222 1.1 cjs return (NULL_POSITION);
223 1.1 cjs new_pos++;
224 1.1 cjs if (c == '\n')
225 1.1 cjs break;
226 1.1 cjs if (pappend(c))
227 1.1 cjs {
228 1.1 cjs /*
229 1.1 cjs * Got a full printable line, but we haven't
230 1.1 cjs * reached our curr_pos yet. Discard the line
231 1.1 cjs * and start a new one.
232 1.1 cjs */
233 1.1 cjs (void) pappend('\0');
234 1.1 cjs (void) ch_back_get();
235 1.1 cjs new_pos--;
236 1.1 cjs goto loop;
237 1.1 cjs }
238 1.1 cjs } while (new_pos < curr_pos);
239 1.1 cjs
240 1.1 cjs (void) pappend('\0');
241 1.1 cjs
242 1.1 cjs return (begin_new_pos);
243 1.1 cjs }
244