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