1 /* edit.c by Adam Rogoyski <apoc@laker.net> Temperanc on EFNet irc
2 * Copyright (C) 1998, 1999 Adam Rogoyski
3 * --- GNU General Public License Disclamer ---
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14
15 #include <assert.h>
16 #include "hexedit.h"
17
18 /* The routines in this file are very messy and ugly and not much thought
19 * went into thinking how to minimize the amount of code, I only did it
20 * real fast, making every case I could think of a seperate code block,
21 * so this may be someplace someone may want to improve, especially since
22 * all the hard coded screen positions make it hard to add new viewing
23 * modes.
24 */
25
26
27 /* Table for translating an ASCII character into an EBCDIC char. Index into
28 * the array with an ASCII char value, at that index is the EBCDIC char value
29 * of that character.
30 */
31 const unsigned char ASCII_to_EBCDIC[] = {
32 0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,
33 0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,0x2e,
34 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d,0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x00,0x61,
35 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,
36 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,
37 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xad,0xe0,0xbd,0x5f,0x6d,
38 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,
39 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0x8b,0x4f,0x9b,0xa1,0x2e
40 };
41
42
43
44 void
insertByte(unsigned char c,int in_undo)45 insertByte (unsigned char c, int in_undo)
46 {
47 unsigned long off = 0;
48 if (extrabuf <= 0)
49 /* allocate extra chunks to use for inserting when full */
50 {
51 extrabuf = EXTRA_BUF;
52 filebuf = realloc (filebuf, Globals.filesize + 1 + extrabuf);
53 if (!filebuf)
54 die_horribly ("\nNot enough Memory! file not saved", NULL);
55
56 memset (filebuf + Globals.filesize, 0, extrabuf);
57 }
58 memmove (filebuf + offset + 1, filebuf + offset, Globals.filesize -
59 offset + 1);
60 if (!in_undo)
61 pushUndo (INSERT, offset, filebuffer (offset), c);
62
63 *(filebuf + offset) = c;
64 clear_hash ();
65 off = offset & M_0xFFFFFFF0;
66 off -= (cursor_y - MAIN_TOP_LINE) * 0x10;
67 Globals.filesize++;
68 Globals.buffsize++;
69 Globals.buf_end++;
70 extrabuf--;
71 Globals.modified = MODIFIED;
72
73 printStatusWindow ();
74 drawdump (off);
75 wmove (Globals.wmain, cursor_y, cursor_x);
76 wrefresh (Globals.wmain);
77 refresh ();
78 }
79
80
81 void
deleteByte(int in_undo)82 deleteByte (int in_undo)
83 {
84 unsigned long off = 0;
85 if (Globals.filesize <= 0x00)
86 {
87 off = 0;
88 if (*filebuf)
89 pushUndo (CHANGE, 0x00, filebuffer (0x00), filebuffer (0x00));
90 *filebuf = 0;
91 cursor_x = 10;
92 Globals.filesize = 0x00;
93 Globals.buf_front = 0;
94 Globals.buf_end = 0;
95 do_beep ();
96 printStatusWindow ();
97 drawdump (off);
98 if (Globals.tabb)
99 move (cursor_y, COLS - M_0x10 + mapcur (cursor_x));
100 else
101 move (cursor_y, cursor_x);
102 wrefresh (Globals.wmain);
103 refresh ();
104 return;
105 }
106
107 if (offset < Globals.filesize)
108 {
109 if (!in_undo)
110 pushUndo (DELETE, offset, filebuffer (offset), filebuffer (offset));
111 memmove (filebuf + offset, filebuf + offset + 1,
112 Globals.filesize - offset);
113 }
114 else if (offset == Globals.filesize)
115 {
116 if (!in_undo)
117 pushUndo (DELETE, offset, filebuffer (offset), filebuffer (offset));
118 *(filebuf + offset) = 0;
119 if (!mapcur (cursor_x))
120 {
121 if (Globals.spacing)
122 cursor_x = 59;
123 else
124 cursor_x = 43;
125 if (cursor_y > MAIN_TOP_LINE)
126 cursor_y--;
127 }
128 else
129 cursor_x = mappos (mapcur (cursor_x) - 1);
130 offset--;
131 }
132 else /* this had better not ever happen */
133 {
134 offset = Globals.filesize;
135 cursor_x = mappos (offset & M_0x0F);
136 do_beep ();
137 die_horribly ("Died a horrible, horrible death. Mail maintainer", NULL);
138 return;
139 }
140
141 *(filebuf + Globals.filesize) = 0;
142 clear_hash ();
143 Globals.filesize--;
144 Globals.buffsize--;
145 Globals.buf_end--;
146 off = offset & M_0xFFFFFFF0;
147 off -= (cursor_y - MAIN_TOP_LINE) * 0x10;
148 if (off < 0x00)
149 off = 0;
150 extrabuf++;
151 Globals.modified = MODIFIED;
152 printStatusWindow ();
153 drawdump (off);
154 if (Globals.tabb)
155 move (cursor_y, COLS - M_0x10 + mapcur (cursor_x));
156 else
157 move (cursor_y, cursor_x);
158 wrefresh (Globals.wmain);
159 refresh ();
160 }
161
162
163 void
over_write(wchar_t in)164 over_write (wchar_t in)
165 {
166 unsigned long off = 0;
167
168 if (!isprintable (in))
169 return;
170 if (Globals.tabb)
171 {
172 if ((cursor_y == BOTTOM_LINE) && (mapcur (cursor_x) == 15))
173 /* Bottom right corner */
174 {
175 pushUndo (CHANGE, offset, filebuffer (offset), in);
176 if (Globals.charset == ASCII_CHAR_SET)
177 filebuff_modify (offset, in);
178 else /* EBCDIC */
179 filebuff_modify (offset, findEBCDIC (in));
180 if (offset < Globals.filesize)
181 /* data below, scroll screen */
182 {
183 offset++;
184 cursor_x = mappos (0);
185 }
186 else
187 /* just overwrite character */
188 {
189 do_beep ();
190 }
191 }
192 else if (offset == Globals.filesize)
193 {
194 pushUndo (CHANGE, offset, filebuffer (offset), in);
195 if (Globals.charset == ASCII_CHAR_SET)
196 filebuff_modify (offset, in);
197 else /* EBCDIC */
198 filebuff_modify (offset, findEBCDIC (in));
199 do_beep ();
200 }
201 else if (mapcur (cursor_x) == 15)
202 /* right edge of screen, not bottom corner */
203 {
204 pushUndo (CHANGE, offset, filebuffer (offset), in);
205 if (Globals.charset == ASCII_CHAR_SET)
206 filebuff_modify (offset, in);
207 else /* EBCDIC */
208 filebuff_modify (offset, findEBCDIC (in));
209 offset++;
210 cursor_x = mappos (0);
211 cursor_y++;
212 }
213 else
214 {
215 pushUndo (CHANGE, offset, filebuffer (offset), in);
216 if (Globals.charset == ASCII_CHAR_SET)
217 filebuff_modify (offset, in);
218 else /* EBCDIC */
219 filebuff_modify (offset, findEBCDIC (in));
220 offset++;
221 cursor_x = mappos (mapcur (cursor_x) + 1);
222 }
223 off = offset & M_0xFFFFFFF0;
224 off -= (cursor_y - 1) * M_0x10;
225 Globals.modified = MODIFIED;
226 drawdump (off);
227 printStatusWindow ();
228 wrefresh (Globals.wmain);
229 wrefresh (Globals.wstatus);
230 move (cursor_y, COLS - M_0x10 + mapcur (cursor_x));
231 refresh ();
232 }
233
234 else if (isHexChar (in) && Globals.spacing)
235 {
236 if ((cursor_y == BOTTOM_LINE) && (cursor_x == 60))
237 /* Bottom right corner */
238 {
239 unsigned char old_value = filebuffer (offset);
240 unsigned char nc = (filebuffer (offset) & M_0xF0) |
241 getHexValue (in);
242 filebuff_modify (offset, nc);
243 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
244 if (offset < Globals.filesize)
245 {
246 offset++;
247 cursor_x = mappos (0);
248 }
249 else
250 {
251 do_beep ();
252 }
253 }
254 else if (offset == Globals.filesize)
255 {
256 if (
257 cursor_x == 10 || cursor_x == 13
258 || cursor_x == 16 || cursor_x == 19
259 || cursor_x == 23 || cursor_x == 26
260 || cursor_x == 29 || cursor_x == 32
261 || cursor_x == 37 || cursor_x == 40
262 || cursor_x == 43 || cursor_x == 46
263 || cursor_x == 50 || cursor_x == 53
264 || cursor_x == 56 || cursor_x == 59)
265 {
266 unsigned char old_value = filebuffer (offset);
267 unsigned char nc = (getHexValue (in) << 4) |
268 (filebuffer (offset) & M_0x0F);
269 filebuff_modify (offset, nc);
270 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
271 cursor_x++;
272 }
273 else
274 {
275 unsigned char old_value = filebuffer (offset);
276 unsigned char nc = (filebuffer (offset) & M_0xF0) |
277 getHexValue (in);
278 filebuff_modify (offset, nc);
279 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
280 do_beep ();
281 }
282 }
283 else if (cursor_x == 60)
284 {
285 unsigned char old_value = filebuffer (offset);
286 unsigned char nc = (filebuffer (offset) & M_0xF0) |
287 getHexValue (in);
288 filebuff_modify (offset, nc);
289 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
290 offset++;
291 cursor_x = mappos (0);
292 cursor_y++;
293 }
294 else if (
295 cursor_x == 10 || cursor_x == 13
296 || cursor_x == 16 || cursor_x == 19
297 || cursor_x == 23 || cursor_x == 26
298 || cursor_x == 29 || cursor_x == 32
299 || cursor_x == 37 || cursor_x == 40
300 || cursor_x == 43 || cursor_x == 46
301 || cursor_x == 50 || cursor_x == 53
302 || cursor_x == 56 || cursor_x == 59)
303 {
304 unsigned char old_value = filebuffer (offset);
305 unsigned char nc = (getHexValue (in) << 4) |
306 (filebuffer (offset) & M_0x0F);
307 filebuff_modify (offset, nc);
308 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
309 cursor_x++;
310 }
311 else
312 {
313 unsigned char old_value = filebuffer (offset);
314 unsigned char nc = (filebuffer (offset) & M_0xF0) |
315 getHexValue (in);
316 filebuff_modify (offset, nc);
317 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
318 offset++;
319 cursor_x = mappos (mapcur (cursor_x) + 1);
320 }
321 off = offset & M_0xFFFFFFF0;
322 off -= (cursor_y - 1) * M_0x10;
323 Globals.modified = MODIFIED;
324 drawdump (off);
325 printStatusWindow ();
326 wrefresh (Globals.wmain);
327 wrefresh (Globals.wstatus);
328 move (cursor_y, cursor_x);
329 refresh ();
330 }
331 else if (isHexChar (in) && !Globals.spacing)
332 {
333 if ((cursor_y == BOTTOM_LINE) && (cursor_x == 44))
334 /* Bottom right corner */
335 {
336 unsigned char old_value = filebuffer (offset);
337 unsigned char nc = (filebuffer (offset) & M_0xF0) |
338 getHexValue (in);
339 filebuff_modify (offset, nc);
340 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
341 if (offset < Globals.filesize)
342 {
343 offset++;
344 cursor_x = mappos (0);
345 }
346 else
347 {
348 do_beep ();
349 }
350 }
351 else if (offset == Globals.filesize)
352 {
353 if (
354 cursor_x == 10 || cursor_x == 12
355 || cursor_x == 14 || cursor_x == 16
356 || cursor_x == 19 || cursor_x == 21
357 || cursor_x == 23 || cursor_x == 25
358 || cursor_x == 28 || cursor_x == 30
359 || cursor_x == 32 || cursor_x == 34
360 || cursor_x == 37 || cursor_x == 39
361 || cursor_x == 41 || cursor_x == 43)
362 {
363 unsigned char old_value = filebuffer (offset);
364 unsigned char nc = (getHexValue (in) << 4) |
365 (filebuffer (offset) & M_0x0F);
366 filebuff_modify (offset, nc);
367 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
368 cursor_x++;
369 }
370 else
371 {
372 unsigned char old_value = filebuffer (offset);
373 unsigned char nc = (filebuffer (offset) & M_0xF0) |
374 getHexValue (in);
375 filebuff_modify (offset, nc);
376 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
377 do_beep ();
378 }
379 }
380 else if (cursor_x == 44)
381 {
382 unsigned char old_value = filebuffer (offset);
383 unsigned char nc = (filebuffer (offset) & M_0xF0) |
384 getHexValue (in);
385 filebuff_modify (offset, nc);
386 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
387 offset++;
388 cursor_x = mappos (0);
389 cursor_y++;
390 }
391 else if (
392 cursor_x == 10 || cursor_x == 12
393 || cursor_x == 14 || cursor_x == 16
394 || cursor_x == 19 || cursor_x == 21
395 || cursor_x == 23 || cursor_x == 25
396 || cursor_x == 28 || cursor_x == 30
397 || cursor_x == 32 || cursor_x == 34
398 || cursor_x == 37 || cursor_x == 39
399 || cursor_x == 41 || cursor_x == 43)
400 {
401 unsigned char old_value = filebuffer (offset);
402 unsigned char nc = (getHexValue (in) << 4) |
403 (filebuffer (offset) & M_0x0F);
404 filebuff_modify (offset, nc);
405 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
406 cursor_x++;
407 }
408 else
409 {
410 unsigned char old_value = filebuffer (offset);
411 unsigned char nc = (filebuffer (offset) & M_0xF0) |
412 getHexValue (in);
413 filebuff_modify (offset, nc);
414 pushUndo (CHANGE, offset, old_value, filebuffer (offset));
415 offset++;
416 cursor_x = mappos (mapcur (cursor_x) + 1);
417 }
418 off = offset & M_0xFFFFFFF0;
419 off -= (cursor_y - 1) * M_0x10;
420 Globals.modified = MODIFIED;
421 drawdump (off);
422 printStatusWindow ();
423 wrefresh (Globals.wmain);
424 wrefresh (Globals.wstatus);
425 move (cursor_y, cursor_x);
426 refresh ();
427 }
428 }
429
430
431 wchar_t
findEBCDIC(wchar_t in)432 findEBCDIC (wchar_t in)
433 {
434 /*
435 wchar_t i = 0;
436 for (i = 0; i < 256; i++)
437 {
438 if (in == EBCDIC[i])
439 return i;
440 }
441 do_beep ();
442 assert (0);
443 return 0;
444 */
445
446 return ASCII_to_EBCDIC[in];
447 }
448
449
450 void
filebuff_modify(unsigned long offs,unsigned char c)451 filebuff_modify (unsigned long offs, unsigned char c)
452 {
453 /* If the whole buffer isn't in memory, we need to adjust where
454 * our offset is actually in filebuf, and also hash the change.
455 * The actual offset in filebuf will be (offset - buf_front),
456 * Assuming of course that the place being modified is always
457 * in the current buffer. This should always be true. So
458 * should (offset >= buf_front);
459 */
460 if (!Globals.fullsize)
461 {
462 assert (offset >= Globals.buf_front);
463 *(filebuf + offset - Globals.buf_front) = c;
464 insert_hash_entry (offset, c);
465 }
466 /* If the whole buffer Is in memory, we just change at that offset
467 * in filebuf.
468 */
469 else
470 {
471 *(filebuf + offset) = c;
472 insert_hash_entry (offset, c);
473 }
474 }
475