Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 283 lines (254 sloc) 7.154 kb
cf92e3be »
2011-12-10 Import Elvis 2.0 (written by Steve Kirkendall)
1 /* dmhex.c */
2 /* Copyright 1995 by Steve Kirkendall */
3
4 char id_dmhex[] = "$Id: dmhex.c,v 2.13 1996/05/24 00:53:01 steve Exp $";
5
6 #include "elvis.h"
7 #ifdef DISPLAY_HEX
8
9 #ifdef CHAR16
10 "hex mode doesn't support 16-bit characters"
11 #endif
12
13 #if USE_PROTOTYPES
14 static DMINFO *init(WINDOW win);
15 static void term(DMINFO *info);
16 static long mark2col(WINDOW w, MARK mark, BOOLEAN cmd);
17 static MARK move(WINDOW w, MARK from, long linedelta, long column, BOOLEAN cmd);
18 static MARK setup(MARK top, long cursor, MARK bottom, DMINFO *info);
19 static MARK image(WINDOW w, MARK line, DMINFO *info, void (*draw)(CHAR *p, long qty, _char_ font, long offset));
20 #endif
21
22 /* Lines look like this:
23 _offset____0__1__2__3___4__5__6__7___8__9__a__b___c__d__e__f__0123456789abcdef
24 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000000000
25 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000000000
26 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000000000
27 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000000000
28 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000000000
29 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000000000
30 */
31
32 /* This array is used to convert a column number to an offset within a line */
33 static char col2offset[] = "00000000000011122233334445556667777888999aaabbbbcccdddeeeffff00123456789abcdef";
34
35 /* start the mode, and allocate dminfo */
36 static DMINFO *init(win)
37 WINDOW win;
38 {
39 /* inherit some functions from dmnormal */
40 if (!dmhex.wordmove)
41 {
42 dmhex.wordmove = dmnormal.wordmove;
43 dmhex.tagatcursor = dmnormal.tagatcursor;
44 dmhex.tagload = dmnormal.tagload;
45 dmhex.tagnext = dmnormal.tagnext;
46 }
47
48 return NULL;
49 }
50
51 /* end the mode, and free the modeinfo */
52 static void term(info)
53 DMINFO *info; /* window-specific info about mode */
54 {
55 }
56
57 /* Convert a mark to a screen-relative column number */
58 static long mark2col(w, mark, cmd)
59 WINDOW w; /* window where buffer is shown */
60 MARK mark; /* mark to convert */
61 BOOLEAN cmd; /* if True, we're in command mode; else input mode */
62 {
63 return 62 + (markoffset(mark) & 0xf);
64 }
65
66 /* Move vertically, and to a given column (or as close to column as possible) */
67 static MARK move(w, from, linedelta, column, cmd)
68 WINDOW w; /* window where buffer is shown */
69 MARK from; /* old location */
70 long linedelta; /* line movement */
71 long column; /* desired column number */
72 BOOLEAN cmd; /* if True, we're in command mode; else input mode */
73 {
74 static MARKBUF mark;
75 long offset;
76 long coloff;
77
78 /* compute line movement first */
79 offset = (markoffset(from) & ~0xf) + 0x10 * linedelta;
80
81 /* convert requested column to nearest buffer offset */
82 if (column >= (int)strlen(col2offset))
83 {
84 coloff = 0xf;
85 }
86 else if (col2offset[column] >= '0' && col2offset[column] <= '9')
87 {
88 coloff = col2offset[column] - '0';
89 }
90 else
91 {
92 coloff = col2offset[column] - 'a' + 0xa;
93 }
94 offset += coloff;
95
96 /* never return an offset past the end of the buffer, or before the
97 * beginning.
98 */
99 if (offset >= o_bufchars(markbuffer(from)))
100 {
101 if (o_bufchars(markbuffer(from)) == 0)
102 {
103 offset = 0;
104 }
105 else
106 {
107 offset = o_bufchars(markbuffer(from)) - 1;
108 }
109 }
110 else if (offset < 0)
111 {
112 offset = coloff;
113 }
114
115 return marktmp(mark, markbuffer(from), offset);
116 }
117
118 /* Choose a line to appear at the top of the screen, and return its mark.
119 * Also, initialize the info for the next line.
120 */
121 static MARK setup(top, cursor, bottom, info)
122 MARK top; /* where previous image started */
123 long cursor; /* offset of cursor */
124 MARK bottom; /* where previous image ended */
125 DMINFO *info; /* window-specific info about mode */
126 {
127 static MARKBUF mark;
128 long topoff, bottomoff;
129
130 /* extract the offsets. Round down to multiple of 16 */
131 topoff = (top ? (markoffset(top) & ~0xf) : -1);
132 bottomoff = (bottom ? (markoffset(bottom) & ~0xf) : -1);
133 cursor &= ~0xf;
134
135 /* if cursor is on the screen, or very near the bottom, then
136 * keep the current top
137 */
138 if (cursor >= topoff && cursor <= bottomoff + 16)
139 {
140 return marktmp(mark, markbuffer(top), topoff);
141 }
142
143 /* if the cursor is on the line before the top, then make the cursor's
144 * line become the new top line.
145 */
146 if (cursor == topoff - 16)
147 {
148 return marktmp(mark, markbuffer(top), cursor);
149 }
150
151 /* else it is distantly before or after the the old screen. Center
152 * the cursor's line in the screen.
153 */
154 topoff = (cursor - (bottomoff - topoff) / 2) & ~0xf;
155 if (topoff < 0)
156 {
157 topoff = 0;
158 }
159 return marktmp(mark, markbuffer(top), topoff);
160 }
161
162 static MARK image(w, line, info, draw)
163 WINDOW w; /* window where drawing will go */
164 MARK line; /* start of line to draw */
165 DMINFO *info; /* window-specific info about mode */
166 void (*draw)P_((CHAR *p, long qty, _char_ font, long offset));
167 /* function for drawing a single character */
168 {
169 char *c8p;
170 CHAR *cp;
171 CHAR tmp;
172 CHAR space; /* usually a space character, maybe bracket character */
173 char buf[10];
174 int i, j;
175
176 /* output headings, if necessary */
177 if ((markoffset(line) & 0xf0) == 0)
178 {
179 for (c8p = " offset 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef";
180 *c8p; c8p++)
181 {
182 tmp = *c8p;
183 (*draw)(&tmp, 1, 'u', -1);
184 }
185 tmp = '\n';
186 (*draw)(&tmp, 1, 'n', -1);
187 }
188
189 /* output the line offset */
190 sprintf(buf, "%08lx", markoffset(line));
191 for (i = 0; buf[i]; i++)
192 {
193 tmp = buf[i];
194 (*draw)(&tmp, 1, 'n', -1);
195 }
196
197 /* output the hex codes of the line */
198 j = markoffset(w->cursor) - markoffset(line);
199 space = ' ';
200 for ((void)scanalloc(&cp, line), i = 0; i < 16 && cp; scannext(&cp), i++)
201 {
202 if ((i & 0x03) == 0)
203 {
204 (*draw)(&space, 1, 'n', -1);
205 space = ' ';
206 }
207 if (j == i)
208 {
209 tmp = '<';
210 (*draw)(&tmp, 1, 'n', -1);
211 space = '>';
212 }
213 else
214 {
215 (*draw)(&space, 1, 'n', -1);
216 space = ' ';
217 }
218 sprintf(buf, "%02x", *cp);
219 tmp = buf[0];
220 (*draw)(&tmp, 1, (char)(j==i ? 'u' : 'n'), markoffset(line) + i);
221 tmp = buf[1];
222 (*draw)(&tmp, 1, (char)(j==i ? 'u' : 'n'), markoffset(line) + i);
223 }
224 (*draw)(&space, 1, 'n', -1);
225
226 /* pad with blanks, if necessary */
227 space = ' ';
228 while (i < 16)
229 {
230 (*draw)(&space, ((i & 0x03) == 0) ? -4 : -3, 'n', -1);
231 i++;
232 }
233 (*draw)(&space, 1, 'n', -1);
234
235 /* output the characters */
236 tmp = '.';
237 for ((void)scanseek(&cp, line), i = 0; i < 16 && cp; scannext(&cp), i++)
238 {
239 if (*cp < ' ' || *cp == '\177')
240 {
241 (*draw)(&tmp, 1, 'n', markoffset(line) + i);
242 }
243 else
244 {
245 (*draw)(cp, 1, 'n', markoffset(line) + i);
246 }
247 }
248 scanfree(&cp);
249 tmp = '\n';
250 (*draw)(&tmp, 1, 'n', -1);
251
252 /* output a blank line after every 16th data line */
253 if ((markoffset(line) & 0xf0) == 0xf0)
254 {
255 (*draw)(&tmp, 1, 'n', -1);
256 }
257
258 markoffset(line) += i;
259 return line;
260 }
261
262 DISPMODE dmhex =
263 {
264 "hex",
265 "Binary hex dump",
266 False, /* display generating can't be optimized */
267 False, /* shouldn't do normal wordwrap */
268 0, /* no window options */
269 NULL,
270 0, /* no global options */
271 NULL,
272 NULL,
273 init,
274 term,
275 mark2col,
276 move,
277 NULL, /* wordmove will be set to dmnormal.wordmove in init() */
278 setup,
279 image,
280 NULL, /* doesn't need a header */
281 NULL /* no autoindent */
282 };
283 #endif /* DISPLAY_HEX */
Something went wrong with that request. Please try again.