Commit | Line | Data |
---|---|---|
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 | 10 | static 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 | |
26 | extern int squeeze; | |
27 | extern int sigs; | |
28 | extern char *line; | |
29 | ||
bc258617 KB |
30 | off_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 | 39 | off_t |
bfe13c81 | 40 | forw_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 | 109 | off_t |
bfe13c81 | 110 | back_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 | } |