update copyright notice
[unix-history] / usr / src / usr.bin / more / input.c
CommitLineData
bfe13c81
KB
1/*
2 * Copyright (c) 1988 Mark Nudleman
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
bfe13c81
KB
6 * Redistribution and use in source and binary forms are permitted
7 * provided that the above copyright notice and this paragraph are
8 * duplicated in all such forms and that any documentation,
9 * advertising materials, and other materials related to such
10 * distribution and use acknowledge that the software was developed
a942b40b
KB
11 * by Mark Nudleman and the University of California, Berkeley. The
12 * name of Mark Nudleman or the
bfe13c81
KB
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20#ifndef lint
a942b40b 21static char sccsid[] = "@(#)input.c 5.2 (Berkeley) %G%";
bfe13c81
KB
22#endif /* not lint */
23
24/*
25 * High level routines dealing with getting lines of input
26 * from the file being viewed.
27 *
28 * When we speak of "lines" here, we mean PRINTABLE lines;
29 * lines processed with respect to the screen width.
30 * We use the term "raw line" to refer to lines simply
31 * delimited by newlines; not processed with respect to screen width.
32 */
33
34#include "less.h"
35
36extern int squeeze;
37extern int sigs;
38extern char *line;
39
40/*
41 * Get the next line.
42 * A "current" position is passed and a "new" position is returned.
43 * The current position is the position of the first character of
44 * a line. The new position is the position of the first character
45 * of the NEXT line. The line obtained is the line starting at curr_pos.
46 */
47 public POSITION
48forw_line(curr_pos)
49 POSITION curr_pos;
50{
51 POSITION new_pos;
52 register int c;
53
54 if (curr_pos == NULL_POSITION || ch_seek(curr_pos))
55 return (NULL_POSITION);
56
57 c = ch_forw_get();
58 if (c == EOI)
59 return (NULL_POSITION);
60
61 prewind();
62 for (;;)
63 {
64 if (sigs)
65 return (NULL_POSITION);
66 if (c == '\n' || c == EOI)
67 {
68 /*
69 * End of the line.
70 */
71 new_pos = ch_tell();
72 break;
73 }
74
75 /*
76 * Append the char to the line and get the next char.
77 */
78 if (pappend(c))
79 {
80 /*
81 * The char won't fit in the line; the line
82 * is too long to print in the screen width.
83 * End the line here.
84 */
85 new_pos = ch_tell() - 1;
86 break;
87 }
88 c = ch_forw_get();
89 }
90 (void) pappend('\0');
91
92 if (squeeze && *line == '\0')
93 {
94 /*
95 * This line is blank.
96 * Skip down to the last contiguous blank line
97 * and pretend it is the one which we are returning.
98 */
99 while ((c = ch_forw_get()) == '\n')
100 if (sigs)
101 return (NULL_POSITION);
102 if (c != EOI)
103 (void) ch_back_get();
104 new_pos = ch_tell();
105 }
106
107 return (new_pos);
108}
109
110/*
111 * Get the previous line.
112 * A "current" position is passed and a "new" position is returned.
113 * The current position is the position of the first character of
114 * a line. The new position is the position of the first character
115 * of the PREVIOUS line. The line obtained is the one starting at new_pos.
116 */
117 public POSITION
118back_line(curr_pos)
119 POSITION curr_pos;
120{
121 POSITION new_pos, begin_new_pos;
122 int c;
123
124 if (curr_pos == NULL_POSITION || curr_pos <= (POSITION)0 ||
125 ch_seek(curr_pos-1))
126 return (NULL_POSITION);
127
128 if (squeeze)
129 {
130 /*
131 * Find out if the "current" line was blank.
132 */
133 (void) ch_forw_get(); /* Skip the newline */
134 c = ch_forw_get(); /* First char of "current" line */
135 (void) ch_back_get(); /* Restore our position */
136 (void) ch_back_get();
137
138 if (c == '\n')
139 {
140 /*
141 * The "current" line was blank.
142 * Skip over any preceeding blank lines,
143 * since we skipped them in forw_line().
144 */
145 while ((c = ch_back_get()) == '\n')
146 if (sigs)
147 return (NULL_POSITION);
148 if (c == EOI)
149 return (NULL_POSITION);
150 (void) ch_forw_get();
151 }
152 }
153
154 /*
155 * Scan backwards until we hit the beginning of the line.
156 */
157 for (;;)
158 {
159 if (sigs)
160 return (NULL_POSITION);
161 c = ch_back_get();
162 if (c == '\n')
163 {
164 /*
165 * This is the newline ending the previous line.
166 * We have hit the beginning of the line.
167 */
168 new_pos = ch_tell() + 1;
169 break;
170 }
171 if (c == EOI)
172 {
173 /*
174 * We have hit the beginning of the file.
175 * This must be the first line in the file.
176 * This must, of course, be the beginning of the line.
177 */
178 new_pos = ch_tell();
179 break;
180 }
181 }
182
183 /*
184 * Now scan forwards from the beginning of this line.
185 * We keep discarding "printable lines" (based on screen width)
186 * until we reach the curr_pos.
187 *
188 * {{ This algorithm is pretty inefficient if the lines
189 * are much longer than the screen width,
190 * but I don't know of any better way. }}
191 */
192 if (ch_seek(new_pos))
193 return (NULL_POSITION);
194 loop:
195 begin_new_pos = new_pos;
196 prewind();
197
198 do
199 {
200 c = ch_forw_get();
201 if (c == EOI || sigs)
202 return (NULL_POSITION);
203 new_pos++;
204 if (c == '\n')
205 break;
206 if (pappend(c))
207 {
208 /*
209 * Got a full printable line, but we haven't
210 * reached our curr_pos yet. Discard the line
211 * and start a new one.
212 */
213 (void) pappend('\0');
214 (void) ch_back_get();
215 new_pos--;
216 goto loop;
217 }
218 } while (new_pos < curr_pos);
219
220 (void) pappend('\0');
221
222 return (begin_new_pos);
223}