1 #include "deco.h"
2 #include "scr.h"
3 #include "rec.h"
4
5 int viewfd;
6 int viewraw, viewhex, viewtabs; /* modes */
7 long viewseek; /* current seek for hex/text switches */
8 int viewhlen; /* number of bytes */
9 char viewsrch [SEARCHSZ]; /* search string */
10 char viewsbuf [SEARCHSZ]; /* search string buffer */
11 int viewsbsz; /* search string size */
12 REC *viewrec;
13
14 static int textview (char *filename);
15 static void viewhead (char *filename, int line, int col);
16
viewfile(int d,char * filename)17 void viewfile (int d, char *filename)
18 {
19 viewfd = d;
20 viewrec = RecOpen (viewfd, 0);
21 if (! viewrec)
22 return;
23 viewseek = 0;
24 viewhlen = (viewrec->size + 15) / 16;
25 for (;;) {
26 VClearBox (1, 0, LINES-2, COLS);
27 if (viewhex) {
28 if (! hexview (filename))
29 break;
30 viewhex = 0;
31 } else {
32 if (! textview (filename))
33 break;
34 viewhex = 1;
35 }
36 }
37 VClearBox (1, 0, LINES-2, COLS);
38 RecClose (viewrec);
39 }
40
textview(char * filename)41 static int textview (char *filename)
42 {
43 register baseline, basecol;
44 int steplr = 8 + (COLS-1)/16*8; /* step left-right */
45 int stepud = LINES-3; /* step up-down */
46 int ccol; /* cursor position */
47 int sline, soff; /* search position */
48
49 baseline = basecol = 0;
50 while (viewrec->lindex[baseline].len != -1 && viewrec->lindex[baseline+1].seek < viewseek)
51 ++baseline;
52 while (viewrec->lindex[baseline].seek + offset (baseline, basecol) + 40 < viewseek)
53 basecol += 40;
54 ccol = 0;
55 sline = soff = -1;
56 VMPutString (LINES-1, 0, "\0011\16Help \17 2\16 \17 3\16Raw \17 4\16Hex \17 5\16Top \17 6\16Bottom\17 7\16Search\17 8\16 \17 9\16Spaces\01710\16Quit \17\2");
57 for (;;) {
58 viewpage (baseline, basecol);
59 for (;;) {
60 viewhead (filename, baseline, basecol);
61 if (sline>=baseline && sline<baseline+LINES-2 &&
62 ccol>=basecol && ccol<basecol+80)
63 VMove (sline-baseline+1, ccol-basecol);
64 else {
65 hidecursor ();
66 sline = soff = -1;
67 }
68 VSync ();
69 switch (KeyGet ()) {
70 case meta ('A'): /* f1 */
71 runhelp ("view");
72 continue;
73 default:
74 VBeep ();
75 continue;
76 case cntrl (']'): /* redraw screen */
77 VRedraw ();
78 continue;
79 case meta ('C'): /* f3 - raw */
80 viewraw ^= 1;
81 break;
82 case meta ('D'): /* f4 - hex */
83 viewseek = viewrec->lindex[baseline].seek + offset (baseline, basecol);
84 return (1);
85 case cntrl ('C'):
86 case cntrl ('['):
87 case meta ('J'): /* f0 - quit */
88 return (0);
89 case meta ('I'): /* f9 - spaces */
90 viewtabs ^= 1;
91 break;
92 case meta ('G'): { /* f7 - search */
93 register char *p;
94
95 if (! (p = getstring (SEARCHSZ-1, viewsrch, " Search ", "Search for the string")))
96 continue;
97 strcpy (viewsrch, p);
98 if (sline < 0) {
99 sline = baseline;
100 soff = offset (baseline, basecol) - 1;
101 }
102 if (search (p, sline, soff+1, &sline, &soff)) {
103 if (baseline > sline || baseline + LINES-2 <= sline)
104 baseline = sline;
105 if (baseline > viewrec->len - (LINES-2))
106 baseline = viewrec->len - (LINES-2);
107 if (baseline < 0)
108 baseline = 0;
109 ccol = column (sline, soff);
110 if (ccol >= 40)
111 basecol = (ccol + strlen (p) - 41) / 40 * 40;
112 else
113 basecol = 0;
114 break;
115 } else
116 sline = soff = -1;
117 continue;
118 }
119 case cntrl ('E'):
120 case meta ('u'): /* up */
121 if (baseline <= 0)
122 continue;
123 --baseline;
124 VDelLine (LINES-2);
125 VInsLine (1);
126 viewline (baseline, basecol, 1);
127 continue;
128 case cntrl ('M'):
129 case cntrl ('J'): /* down */
130 if (basecol) {
131 basecol = 0;
132 break;
133 }
134 /* fall through */
135 case cntrl ('X'):
136 case meta ('d'): /* down */
137 if (baseline >= viewrec->len - (LINES-2))
138 continue;
139 VDelLine (1);
140 VInsLine (LINES-2);
141 viewline (++baseline+LINES-3, basecol, LINES-2);
142 continue;
143 case cntrl ('F'):
144 case cntrl ('D'):
145 case meta ('r'): /* right */
146 basecol += steplr;
147 break;
148 case cntrl ('S'):
149 case cntrl ('A'):
150 case cntrl ('W'):
151 case meta ('l'): /* left */
152 if ((basecol -= steplr) < 0)
153 basecol = 0;
154 break;
155 case cntrl ('B'):
156 case meta ('n'): /* next page */
157 if (baseline >= viewrec->len - (LINES-2))
158 continue;
159 baseline += stepud;
160 if (baseline > viewrec->len - (LINES-2))
161 baseline = viewrec->len - (LINES-2);
162 break;
163 case cntrl ('R'):
164 case meta ('p'): /* prev page */
165 if (baseline <= 0)
166 continue;
167 baseline -= stepud;
168 if (baseline < 0)
169 baseline = 0;
170 break;
171 case meta ('E'): /* top */
172 case meta ('h'): /* home */
173 if (baseline==0 && basecol==0)
174 continue;
175 baseline = basecol = 0;
176 break;
177 case meta ('F'): /* bottom */
178 case meta ('e'): /* end */
179 if (baseline >= viewrec->len - (LINES-2) && basecol==0)
180 continue;
181 baseline = viewrec->len - (LINES-2);
182 basecol = 0;
183 break;
184 }
185 break;
186 }
187 }
188 }
189
viewhead(char * filename,int line,int col)190 static void viewhead (char *filename, int line, int col)
191 {
192 register i;
193
194 VSetDim ();
195 VStandOut ();
196 VMove (0, 0);
197 for (i=80; --i>=0; VPutChar (' '));
198 VMPutString (0, 1, "File ");
199 VPutString (filename);
200 VPrint (" Lines %-5d Bytes %ld", viewrec->len, viewrec->size);
201 VMove (0, 57);
202 VPrint ("Line %-5d Col %d", line+1, col);
203 VSetNormal ();
204 VStandEnd ();
205 }
206
viewpage(int line,int col)207 void viewpage (int line, int col)
208 {
209 register i;
210 int len;
211
212 len = viewrec->len - line;
213 if (len > LINES-2)
214 len = LINES-2;
215 for (i=0; i<len; ++i)
216 viewline (i+line, col, i+1);
217 }
218
viewline(int line,int col,int scrline)219 void viewline (int line, int col, int scrline)
220 {
221 register LINE *l;
222 register char *p;
223 char *e;
224 register len;
225
226 VMove (scrline, 0); /* move to line */
227 VClearLine (); /* clear it */
228 l = RecGet (viewrec, line);
229 if (! l || ! l->len) /* get line */
230 return; /* check if empty */
231 p = l->ptr; /* set ptr to line */
232 e = p + l->len; /* set ptr to end */
233 len = COLS; /* width of print */
234 if (col)
235 p += offset (line, col);
236 if (p >= e)
237 return;
238 while (--len >= 0 && p < e) /* print char loop */
239 if (*p == '\t') { /* print tab */
240 if (viewtabs) {
241 VSetDim ();
242 VPutChar ('_');
243 VSetNormal ();
244 }
245 len = len / 8 * 8;
246 VMove (scrline, COLS-len);
247 ++p;
248 } else if (*p == '\b' && !viewtabs && len<COLS-1 && p<e-1 &&
249 p[-1] != '\b' && p[1] != '\b') {
250 VPutChar ('\b'); /* backspace */
251 ++len;
252 ++p;
253 VSetBold ();
254 viewchar (*p++);
255 VSetNormal ();
256 } else
257 viewchar (*p++); /* else print char */
258 if (p < e) { /* put tag */
259 if (len < 0)
260 VMove (scrline, COLS-1);
261 VSetBold ();
262 VPutChar ('>'); /* "continued" */
263 VSetNormal ();
264 } else if (l->noeoln) {
265 VSetBold ();
266 VPutChar ('\\'); /* "broken" */
267 VSetNormal ();
268 }
269 }
270
viewchar(int c)271 void viewchar (int c)
272 {
273 register hibit;
274
275 if (c == ' ') {
276 if (viewhex || viewtabs) {
277 VSetDim ();
278 VPutChar ('.');
279 VSetNormal ();
280 } else
281 VPutChar (' ');
282 } else if (viewraw) {
283 c &= 0377;
284 if (c >= ' ')
285 VPutChar (c);
286 else {
287 VSetDim ();
288 VPutChar ((c + 0100) & 0177);
289 VSetNormal ();
290 }
291 } else {
292 hibit = (c & 0200);
293 if (hibit)
294 VStandOut ();
295 c &= 0177;
296 if (c >= ' ' && c <= '~')
297 VPutChar (c);
298 else {
299 VSetDim ();
300 VPutChar ((c + 0100) & 0177);
301 VSetNormal ();
302 }
303 if (hibit)
304 VStandEnd ();
305 }
306 }
307
strequal(char * a,char * b,int n)308 static int strequal (char *a, char *b, int n)
309 {
310 for (;;) {
311 if (--n < 0)
312 return (1);
313 if (*a++ != *b++)
314 return (0);
315 }
316 }
317
search(char * str,int l,int c,int * pline,int * pcol)318 int search (char *str, int l, int c, int *pline, int *pcol)
319 {
320 LINE *p;
321 register char *s, *e;
322 int len = strlen (str);
323
324 for (; l<viewrec->len && (p = RecGet (viewrec, l)); ++l) {
325 s = p->ptr;
326 e = p->ptr + p->len - len + 1;
327 if (c) {
328 s += c;
329 c = 0;
330 }
331 for (; s<e; ++s)
332 if (strequal (s, str, len)) {
333 *pline = l;
334 *pcol = s - p->ptr;
335 return (1);
336 }
337 }
338 error ("String not found");
339 return (0);
340 }
341
342 /*
343 * Line L is to be printed on screen, shifted by N colunms.
344 * Compute the line offset to start with.
345 */
offset(int l,int n)346 int offset (int l, int n)
347 {
348 LINE *p;
349 register char *s, *e;
350 register len;
351
352 if (! (p = RecGet (viewrec, l)))
353 return (0);
354 s = p->ptr;
355 e = s + p->len;
356 for (len=0; len<n && s<e; ++s) {
357 if (*s == '\t') { /* handle tabs correctly */
358 len = (len + 8) / 8 * 8;
359 continue;
360 }
361 if (*s == '\b' && !viewtabs && len>0 && s<e-1 &&
362 s[-1] != '\b' && s[1] != '\b') {
363 --len;
364 continue;
365 }
366 ++len;
367 if (len > n)
368 break;
369 }
370 return (s - p->ptr);
371 }
372
373 /*
374 * N bytes of line L are printed on screen.
375 * Compute the number of columns it will take.
376 */
column(int l,int n)377 int column (int l, int n)
378 {
379 LINE *p;
380 register char *s, *e;
381 register len;
382
383 if (! (p = RecGet (viewrec, l)))
384 return (0);
385 if (n > p->len)
386 n = p->len;
387 s = p->ptr;
388 e = s + n;
389 /* count length of string as it appears on screen */
390 for (len=0; s<e; ++s)
391 if (*s == '\t') /* handle tabs correctly */
392 len = (len + 8) / 8 * 8;
393 else if (*s == '\b' && !viewtabs && len>0 && s<e-1 &&
394 s[-1] != '\b' && s[1] != '\b')
395 --len;
396 else
397 ++len;
398 return (len);
399 }
400