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