Annotation of src/usr.bin/less/input.c, Revision 1.2
1.2 ! niklas 1: /* $OpenBSD$ */
! 2:
1.1 etheisen 3: /*
4: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice in the documentation and/or other materials provided with
14: * the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
17: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29:
30: /*
31: * High level routines dealing with getting lines of input
32: * from the file being viewed.
33: *
34: * When we speak of "lines" here, we mean PRINTABLE lines;
35: * lines processed with respect to the screen width.
36: * We use the term "raw line" to refer to lines simply
37: * delimited by newlines; not processed with respect to screen width.
38: */
39:
40: #include "less.h"
41:
42: extern int squeeze;
43: extern int chopline;
44: extern int sigs;
45: #if HILITE_SEARCH
46: extern int hilite_search;
47: extern int size_linebuf;
48: #endif
49:
50: /*
51: * Get the next line.
52: * A "current" position is passed and a "new" position is returned.
53: * The current position is the position of the first character of
54: * a line. The new position is the position of the first character
55: * of the NEXT line. The line obtained is the line starting at curr_pos.
56: */
57: public POSITION
58: forw_line(curr_pos)
59: POSITION curr_pos;
60: {
61: POSITION new_pos;
62: register int c;
63: int blankline;
64: int endline;
65:
66: if (curr_pos == NULL_POSITION)
67: {
68: null_line();
69: return (NULL_POSITION);
70: }
71: #if HILITE_SEARCH
72: if (hilite_search == OPT_ONPLUS)
73: prep_hilite(curr_pos, curr_pos + 3*size_linebuf);
74: #endif
75: if (ch_seek(curr_pos))
76: {
77: null_line();
78: return (NULL_POSITION);
79: }
80:
81: prewind();
82: plinenum(curr_pos);
83: (void) ch_seek(curr_pos);
84:
85: c = ch_forw_get();
86: if (c == EOI)
87: {
88: null_line();
89: return (NULL_POSITION);
90: }
91: blankline = (c == '\n' || c == '\r');
92:
93: for (;;)
94: {
95: if (ABORT_SIGS())
96: {
97: null_line();
98: return (NULL_POSITION);
99: }
100: if (c == '\n' || c == EOI)
101: {
102: /*
103: * End of the line.
104: */
105: new_pos = ch_tell();
106: endline = 1;
107: break;
108: }
109:
110: /*
111: * Append the char to the line and get the next char.
112: */
113: if (pappend(c, ch_tell()-1))
114: {
115: /*
116: * The char won't fit in the line; the line
117: * is too long to print in the screen width.
118: * End the line here.
119: */
120: if (chopline)
121: {
122: do
123: {
124: c = ch_forw_get();
125: } while (c != '\n' && c != EOI);
126: new_pos = ch_tell();
127: endline = 1;
128: } else
129: {
130: new_pos = ch_tell() - 1;
131: endline = 0;
132: }
133: break;
134: }
135: c = ch_forw_get();
136: }
137: pdone(endline);
138:
139: if (squeeze && blankline)
140: {
141: /*
142: * This line is blank.
143: * Skip down to the last contiguous blank line
144: * and pretend it is the one which we are returning.
145: */
146: while ((c = ch_forw_get()) == '\n' || c == '\r')
147: if (ABORT_SIGS())
148: {
149: null_line();
150: return (NULL_POSITION);
151: }
152: if (c != EOI)
153: (void) ch_back_get();
154: new_pos = ch_tell();
155: }
156:
157: return (new_pos);
158: }
159:
160: /*
161: * Get the previous line.
162: * A "current" position is passed and a "new" position is returned.
163: * The current position is the position of the first character of
164: * a line. The new position is the position of the first character
165: * of the PREVIOUS line. The line obtained is the one starting at new_pos.
166: */
167: public POSITION
168: back_line(curr_pos)
169: POSITION curr_pos;
170: {
171: POSITION new_pos, begin_new_pos;
172: int c;
173: int endline;
174:
175: if (curr_pos == NULL_POSITION || curr_pos <= ch_zero())
176: {
177: null_line();
178: return (NULL_POSITION);
179: }
180: #if HILITE_SEARCH
181: if (hilite_search == OPT_ONPLUS)
182: prep_hilite((curr_pos < 3*size_linebuf) ?
183: 0 : curr_pos - 3*size_linebuf, curr_pos);
184: #endif
185: if (ch_seek(curr_pos-1))
186: {
187: null_line();
188: return (NULL_POSITION);
189: }
190:
191: if (squeeze)
192: {
193: /*
194: * Find out if the "current" line was blank.
195: */
196: (void) ch_forw_get(); /* Skip the newline */
197: c = ch_forw_get(); /* First char of "current" line */
198: (void) ch_back_get(); /* Restore our position */
199: (void) ch_back_get();
200:
201: if (c == '\n' || c == '\r')
202: {
203: /*
204: * The "current" line was blank.
205: * Skip over any preceding blank lines,
206: * since we skipped them in forw_line().
207: */
208: while ((c = ch_back_get()) == '\n' || c == '\r')
209: if (ABORT_SIGS())
210: {
211: null_line();
212: return (NULL_POSITION);
213: }
214: if (c == EOI)
215: {
216: null_line();
217: return (NULL_POSITION);
218: }
219: (void) ch_forw_get();
220: }
221: }
222:
223: /*
224: * Scan backwards until we hit the beginning of the line.
225: */
226: for (;;)
227: {
228: if (ABORT_SIGS())
229: {
230: null_line();
231: return (NULL_POSITION);
232: }
233: c = ch_back_get();
234: if (c == '\n')
235: {
236: /*
237: * This is the newline ending the previous line.
238: * We have hit the beginning of the line.
239: */
240: new_pos = ch_tell() + 1;
241: break;
242: }
243: if (c == EOI)
244: {
245: /*
246: * We have hit the beginning of the file.
247: * This must be the first line in the file.
248: * This must, of course, be the beginning of the line.
249: */
250: new_pos = ch_tell();
251: break;
252: }
253: }
254:
255: /*
256: * Now scan forwards from the beginning of this line.
257: * We keep discarding "printable lines" (based on screen width)
258: * until we reach the curr_pos.
259: *
260: * {{ This algorithm is pretty inefficient if the lines
261: * are much longer than the screen width,
262: * but I don't know of any better way. }}
263: */
264: if (ch_seek(new_pos))
265: {
266: null_line();
267: return (NULL_POSITION);
268: }
269: endline = 0;
270: loop:
271: begin_new_pos = new_pos;
272: prewind();
273: plinenum(new_pos);
274: (void) ch_seek(new_pos);
275:
276: do
277: {
278: c = ch_forw_get();
279: if (c == EOI || ABORT_SIGS())
280: {
281: null_line();
282: return (NULL_POSITION);
283: }
284: new_pos++;
285: if (c == '\n')
286: {
287: endline = 1;
288: break;
289: }
290: if (pappend(c, ch_tell()-1))
291: {
292: /*
293: * Got a full printable line, but we haven't
294: * reached our curr_pos yet. Discard the line
295: * and start a new one.
296: */
297: if (chopline)
298: {
299: endline = 1;
300: break;
301: }
302: pdone(0);
303: (void) ch_back_get();
304: new_pos--;
305: goto loop;
306: }
307: } while (new_pos < curr_pos);
308:
309: pdone(endline);
310:
311: return (begin_new_pos);
312: }