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