1 /* hexedit -- Hexadecimal Editor for Binary Files
2 Copyright (C) 1998 Pixel (Pascal Rigaux)
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, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/
20 static void goto_char(void);
21 static void goto_sector(void);
22 static void save_buffer(void);
23 static void escaped_command(void);
24 static void help(void);
25 static void short_help(void);
28 /*******************************************************************************/
29 /* interactive functions */
30 /*******************************************************************************/
32 static void forward_char(void)
34 if (!hexOrAscii
|| cursorOffset
)
36 if (hexOrAscii
) cursorOffset
= (cursorOffset
+ 1) % 2;
39 static void backward_char(void)
41 if (!hexOrAscii
|| !cursorOffset
)
43 if (hexOrAscii
) cursorOffset
= (cursorOffset
+ 1) % 2;
46 static void next_line(void)
48 move_cursor(+lineLength
);
51 static void previous_line(void)
53 move_cursor(-lineLength
);
56 static void forward_chars(void)
58 move_cursor(+blocSize
);
61 static void backward_chars(void)
63 move_cursor(-blocSize
);
66 static void next_lines(void)
68 move_cursor(+lineLength
* blocSize
);
71 static void previous_lines(void)
73 move_cursor(-lineLength
* blocSize
);
76 static void beginning_of_line(void)
79 move_cursor(-(cursor
% lineLength
));
82 static void end_of_line(void)
85 if (!move_cursor(lineLength
- 1 - cursor
% lineLength
))
86 move_cursor(nbBytes
- cursor
);
89 static void scroll_up(void)
97 static void scroll_down(void)
105 static void beginning_of_buffer(void)
111 static void end_of_buffer(void)
113 off_t s
= getfilesize();
115 if (mode
== bySector
) set_base(myfloor(s
, page
));
119 static void suspend(void) { kill(getpid(), SIGTSTP
); }
120 static void undo(void) { discardEdited(); readFile(); }
121 static void quoted_insert(void) { setTo(getch()); }
122 static void toggle(void) { hexOrAscii
= (hexOrAscii
+ 1) % 2; }
124 static void recenter(void)
127 base
= base
+ cursor
;
133 static void find_file(void)
135 if (!ask_about_save_and_redisplay()) return;
136 if (!findFile()) { displayMessageAndWaitForKey("No such file or directory"); return; }
141 static void redisplay(void) { clear(); }
143 static void delete_backward_char(void)
146 removeFromEdited(base
+ cursor
, 1);
149 if (!tryloc(base
+ cursor
)) end_of_buffer();
152 static void delete_backward_chars(void)
155 removeFromEdited(base
+ cursor
, blocSize
);
158 if (!tryloc(base
+ cursor
)) end_of_buffer();
161 static void truncate_file(void)
163 displayOneLineMessage("Really truncate here? (y/N)");
164 if (tolower(getch()) == 'y') {
165 if (biggestLoc
> base
+cursor
&& ftruncate(fd
, base
+cursor
) == -1)
166 displayMessageAndWaitForKey(strerror(errno
));
168 removeFromEdited(base
+cursor
, lastEditedLoc
- (base
+cursor
));
170 if (mark_min
>= base
+ cursor
|| mark_max
>= base
+ cursor
)
173 if (biggestLoc
> base
+cursor
)
174 biggestLoc
= base
+cursor
;
180 static void firstTimeHelp(void)
182 int firstTime
= TRUE
;
190 static void set_mark_command(void)
193 if ((mark_set
= not(mark_set
))) {
195 mark_min
= mark_max
= base
+ cursor
;
204 if (cursor
> nbBytes
) return FALSE
;
206 if (!isxdigit(c
)) return FALSE
;
207 val
= hexCharToInt(c
);
208 val
= cursorOffset
? setLowBits(buffer
[cursor
], val
) : setHighBits(buffer
[cursor
], val
);
213 displayMessageAndWaitForKey("File is read-only!");
215 setToChar(cursor
, val
);
222 /****************************************************
223 ask_about_* or functions that present a prompt
224 ****************************************************/
227 int ask_about_save(void)
230 displayOneLineMessage("Save changes (Yes/No/Cancel) ?");
232 switch (tolower(getch()))
234 case 'y': save_buffer(); break;
235 case 'n': discardEdited(); break;
245 int ask_about_save_and_redisplay(void)
247 int b
= ask_about_save();
255 void ask_about_save_and_quit(void)
257 if (ask_about_save()) quit();
260 static void goto_char(void)
264 displayOneLineMessage("New position ? ");
266 if (!get_number(&i
) || !set_cursor(i
)) displayMessageAndWaitForKey("Invalid position!");
269 static void goto_sector(void)
273 displayOneLineMessage("New sector ? ");
274 if (get_number(&i
) && set_base(i
* SECTOR_SIZE
))
275 set_cursor(i
* SECTOR_SIZE
);
277 displayMessageAndWaitForKey("Invalid sector!");
282 static void save_buffer(void)
284 int displayedmessage
= FALSE
;
286 for (p
= edited
; p
; p
= q
) {
287 if (LSEEK_(fd
, p
->base
) == -1 || write(fd
, p
->vals
, p
->size
) == -1)
288 if (!displayedmessage
) { /* It would be annoying to display lots of error messages when we can't write. */
289 displayMessageAndWaitForKey(strerror(errno
));
290 displayedmessage
= TRUE
;
296 if (lastEditedLoc
> fileSize
) fileSize
= lastEditedLoc
;
298 memset(bufferAttr
, A_NORMAL
, page
* sizeof(*bufferAttr
));
299 if (displayedmessage
) {
300 displayMessageAndWaitForKey("Unwritten changes have been discarded");
302 if (cursor
> nbBytes
) set_cursor(getfilesize());
304 if (mark_set
) markSelectedRegion();
307 static void help(void)
317 execvp(args
[0], args
);
325 static void short_help(void)
327 displayMessageAndWaitForKey("Unknown command, press F1 for help");
332 /*******************************************************************************/
333 /* key_to_function */
334 /*******************************************************************************/
335 int key_to_function(int key
)
338 oldcursorOffset
= cursorOffset
;
340 /*printf("*******%d******\n", key);*/
404 beginning_of_buffer();
452 if (mode
== bySector
) goto_sector(); else goto_char();
460 case CTRL('['): /* escape */
480 delete_backward_char();
483 case CTRL('H') | 0x80: /* CTRL-ALT-H */
484 delete_backward_chars();
496 case 0x7F: /* found on a sun */
527 ask_about_save_and_quit();
531 if ((key
>= 256 || !setTo(key
))) firstTimeHelp();
539 static void escaped_command(void)
541 char tmp
[BLOCK_SEARCH_SIZE
];
573 beginning_of_buffer();
590 delete_backward_chars();
631 beginning_of_buffer();
638 case 'P': /* F1 on a xterm */
642 case 'Q': /* F2 on a xterm */
646 case 'R': /* F3 on a xterm */
650 case 'S': /* F4 on a xterm */
657 } else firstTimeHelp();
661 for (i
= 0;; i
++) { tmp
[i
] = c
= getch(); if (!isdigit(c
)) break; }
665 else if (streq(tmp
, "2~")) yank();
666 else if (streq(tmp
, "5~")) scroll_down();
667 else if (streq(tmp
, "6~")) scroll_up();
668 else if (streq(tmp
, "7~")) beginning_of_buffer();
669 else if (streq(tmp
, "8~")) end_of_buffer();
670 else if (streq(tmp
, "010q" /* F10 on a sgi's winterm */)) ask_about_save_and_quit();
671 else if (streq(tmp
, "193z")) fill_with_string();
672 else if (streq(tmp
, "214z")) beginning_of_line();
673 else if (streq(tmp
, "216z")) scroll_down();
674 else if (streq(tmp
, "220z")) end_of_line();
675 else if (streq(tmp
, "222z")) scroll_up();
676 else if (streq(tmp
, "233z")) ask_about_save_and_quit();
677 else if (streq(tmp
, "234z" /* F11 on a sun */)) yank_to_a_file();
678 else if (streq(tmp
, "247z")) yank();
679 else if (streq(tmp
, "11~" /* F1 on a rxvt */)) help();
680 else if (streq(tmp
, "12~" /* F2 on a rxvt */)) save_buffer();
681 else if (streq(tmp
, "13~" /* F3 on a rxvt */)) find_file();
682 else if (streq(tmp
, "14~" /* F4 on a rxvt */)) goto_char();
683 else if (streq(tmp
, "15~" /* F5 on a rxvt */)) scroll_down();
684 else if (streq(tmp
, "17~" /* F6 on a rxvt */)) scroll_up();
685 else if (streq(tmp
, "18~" /* F7 on a rxvt */)) copy_region();
686 else if (streq(tmp
, "19~" /* F8 on a rxvt */)) yank();
687 else if (streq(tmp
, "20~" /* F9 on a rxvt */)) set_mark_command();
688 else if (streq(tmp
, "21~" /* F10 on a rxvt */)) ask_about_save_and_quit();
689 else if (streq(tmp
, "23~" /* F11 on a rxvt */)) yank_to_a_file();
690 else if (streq(tmp
, "24~" /* F12 on a rxvt */)) fill_with_string();
691 else firstTimeHelp();