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