1 #if HAVE_UNISTD_H
2 #   include <unistd.h>
3 #endif
4 #include "deco.h"
5 #include "scr.h"
6 #include "rec.h"
7 
8 #define GETHEX(x)      ((x)>='A' ? ((x)&15)+9 : (x)&15)
9 
10 extern viewfd;
11 extern viewraw;                         /* raw mode */
12 extern viewhlen;                        /* number of hex lines */
13 extern char viewsrch [SEARCHSZ];        /* search string */
14 extern char viewsbuf [SEARCHSZ];        /* search string buffer */
15 extern viewsbsz;                        /* search string size */
16 extern long viewseek;
17 extern REC *viewrec;
18 
19 static void viewhhead (char *filename, int line);
20 static void viewhline (int line, int i);
21 static void viewhpage (int line);
22 static void prhline (char *p, int len);
23 static int hsearch (int l, int c, int *pline, int *pcol);
24 static int cvtsrch (char *from, char *to);
25 
hexview(char * filename)26 int hexview (char *filename)            /* hexadecimal viewer */
27 {
28 	register baseline;
29 	register char *p;
30 	int stepud = LINES-3;                   /* step up-down */
31 	int sline, soff;                        /* search position */
32 	int hexcursor;                          /* hex cursor mode */
33 
34 	baseline = (viewseek+15)/16;
35 	hexcursor = 0;
36 	sline = soff = -1;
37 	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\16      \01710\16Quit \17\2");
38 	for (;;) {
39 		viewhpage (baseline);
40 		for (;;) {
41 			viewhhead (filename, baseline);
42 			if (sline>=baseline && sline<baseline+LINES-2)
43 				VMove (sline-baseline+1,
44 					hexcursor ? soff*3 : soff*2+48);
45 			else {
46 				hidecursor ();
47 				sline = -1;
48 			}
49 			VSync ();
50 			switch (KeyGet ()) {
51 			case meta ('A'):        /* f1 */
52 				runhelp ("hexview");
53 				continue;
54 			default:
55 				VBeep ();
56 				continue;
57 			case cntrl ('I'):       /* hex/text cursor */
58 				hexcursor ^= 1;
59 				continue;
60 			case cntrl (']'):       /* redraw screen */
61 				VRedraw ();
62 				continue;
63 			case meta ('C'):        /* f3 - raw */
64 				viewraw ^= 1;
65 				break;
66 			case meta ('D'):        /* f4 - hex */
67 				viewseek = baseline*16L;
68 				return (1);
69 			case cntrl ('C'):
70 			case cntrl ('['):
71 			case meta ('J'):        /* f0 - quit */
72 				return (0);
73 			case meta ('u'):        /* up */
74 				if (baseline <= 0)
75 					continue;
76 				--baseline;
77 				VDelLine (LINES-2);
78 				VInsLine (1);
79 				viewhline (baseline, 1);
80 				continue;
81 			case cntrl ('M'):       /* down */
82 			case cntrl ('J'):       /* down */
83 			case meta ('d'):        /* down */
84 				if (baseline >= viewhlen - (LINES-2))
85 					continue;
86 				VDelLine (1);
87 				VInsLine (LINES-2);
88 				viewhline (++baseline+LINES-3, LINES-2);
89 				continue;
90 			case meta ('n'):        /* next page */
91 				if (baseline >= viewhlen - (LINES-2))
92 					continue;
93 				baseline += stepud;
94 				if (baseline > viewhlen - (LINES-2))
95 					baseline = viewhlen - (LINES-2);
96 				break;
97 			case meta ('p'):        /* prev page */
98 				if (baseline <= 0)
99 					continue;
100 				baseline -= stepud;
101 				if (baseline < 0)
102 					baseline = 0;
103 				break;
104 			case meta ('E'):        /* top */
105 			case meta ('h'):        /* home */
106 				if (baseline == 0)
107 					continue;
108 				baseline = 0;
109 				break;
110 			case meta ('F'):        /* bottom */
111 			case meta ('e'):        /* end */
112 				if (baseline >= viewhlen - (LINES-2))
113 					continue;
114 				baseline = viewhlen - (LINES-2);
115 				break;
116 			case meta ('G'):        /* f7 - search */
117 				if (! (p = getstring (SEARCHSZ-1, viewsrch, " Search ", "Search for the string")))
118 					continue;
119 				strcpy (viewsrch, p);
120 				viewsbsz = cvtsrch (viewsrch, viewsbuf);
121 				if (sline < 0) {
122 					sline = baseline;
123 					soff = -1;
124 				}
125 				if (hsearch (sline, soff+1, &sline, &soff)) {
126 					if (baseline>sline || baseline+LINES-2<=sline)
127 						baseline = sline;
128 					if (baseline > viewhlen - (LINES-2))
129 						baseline = viewhlen - (LINES-2);
130 					if (baseline < 0)
131 						baseline = 0;
132 					break;
133 				}
134 				sline = -1;
135 				continue;
136 			}
137 			break;
138 		}
139 	}
140 }
141 
viewhhead(char * filename,int line)142 static void viewhhead (char *filename, int line)
143 {
144 	register i;
145 
146 	VSetDim ();
147 	VStandOut ();
148 	VMove (0, 0);
149 	for (i=80; --i>=0; VPutChar (' '));
150 	VMPutString (0, 1, "File ");
151 	VPutString (filename);
152 	VMove (0, 22);
153 	VPrint ("Lines %-5d Bytes %ld", viewrec->len, viewrec->size);
154 	VMove (0, 68);
155 	VPrint ("Byte %ld", line*16L);
156 	VSetNormal ();
157 	VStandEnd ();
158 }
159 
viewhline(int line,int i)160 static void viewhline (int line, int i)
161 {
162 	char buf [16], *p;
163 	int n;
164 
165 	lseek (viewfd, line*16L, 0);
166 	n = read (viewfd, buf, sizeof (buf));
167 	p = buf;
168 	VMove (i, 0);                           /* move to line */
169 	if (n > 0)
170 		prhline (p, n);
171 	VClearLine ();                          /* clear it */
172 }
173 
viewhpage(int line)174 static void viewhpage (int line)
175 {
176 	char buf [1024], *p;
177 	register i;
178 	int n;
179 
180 	lseek (viewfd, line*16L, 0);
181 	n = read (viewfd, buf, (unsigned) LINES*16);
182 	p = buf;
183 	for (i=1; i<LINES-1; ++i, n-=16, p+=16) {
184 		VMove (i, 0);                   /* move to line */
185 		if (n > 0)
186 			prhline (p, n);
187 		VClearLine ();          /* clear rest of line */
188 	}
189 }
190 
prhline(char * p,int len)191 static void prhline (char *p, int len)
192 {
193 	register i, c;
194 
195 	if (len > 16)
196 		len = 16;
197 	for (i=0; i<16; ++i)
198 		if (i < len) {
199 			c = p [i];
200 			VPutChar ("0123456789abcdef" [c>>4&0xf]);
201 			VPutChar ("0123456789abcdef" [c&0xf]);
202 			VPutChar (' ');
203 		} else {
204 			VPutChar (' ');
205 			VPutChar (' ');
206 			VPutChar (' ');
207 		}
208 	for (i=0; i<len; ++i) {
209 		viewchar (*p++);
210 		if (i < len-1)
211 			VPutChar (' ');
212 	}
213 }
214 
hsearch(int l,int c,int * pline,int * pcol)215 static int hsearch (int l, int c, int *pline, int *pcol)
216 {
217 	char buf [2*SEARCHSZ], *p;
218 	register char *s, *e;
219 	int n;
220 
221 	for (;;) {
222 		lseek (viewfd, l*16L, 0);
223 		n = read (viewfd, buf, sizeof (buf));
224 		if (n <= 0)
225 			break;
226 		p = buf;
227 		e = buf + SEARCHSZ;
228 		for (s=p+c; s<e; ++s)
229 			if (! memcmp (s, viewsbuf, n<viewsbsz ? n : viewsbsz)) {
230 				*pline = l + (s - p) / 16;
231 				*pcol = (s - p) % 16;
232 				return (1);
233 			}
234 		if (n < sizeof (buf))
235 			break;
236 		l += SEARCHSZ / 16;
237 		c = 0;
238 	}
239 	error ("String not found");
240 	return (0);
241 }
242 
cvtsrch(char * from,char * to)243 static int cvtsrch (char *from, char *to)
244 {
245 	register c, x, count;
246 
247 	count = 0;
248 	for (count=0; (c= *from++); *to++=c, ++count)
249 		if (c == '\\' && (x = *from)) {
250 			++from;
251 			if (x != '\\') {
252 				c = GETHEX (x);
253 				if ((x = *from) && x!='\\') {
254 					++from;
255 					c = c<<4 | GETHEX (x);
256 				}
257 			}
258 		}
259 	return (count);
260 }
261