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