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