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