2004-03-15 Masatake YAMATO <jet@gyve.org>
[bpt/emacs.git] / lisp / hexl.el
CommitLineData
55535639 1;;; hexl.el --- edit a file in a hex dump format using the hexl filter
e5167999 2
45ad49ba 3;; Copyright (C) 1989, 1994, 1998, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
a2535589 4
3a801d0c 5;; Author: Keith Gabryelski <ag@wheaties.ai.mit.edu>
b7f66977
RS
6;; Maintainer: FSF
7;; Keywords: data
3a801d0c 8
a2535589
JA
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
e5167999 13;; the Free Software Foundation; either version 2, or (at your option)
a2535589
JA
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
a2535589 25
e5167999
ER
26;;; Commentary:
27
e41b2db1
ER
28;; This package implements a major mode for editing binary files. It uses
29;; a program called hexl, supplied with the GNU Emacs distribution, that
30;; can filter a binary into an editable format or from the format back into
31;; binary. For full instructions, invoke `hexl-mode' on an empty buffer and
a0164df5 32;; do M-x `describe-mode'.
e41b2db1 33;;
a0164df5 34;; NOTE: Remember to change `hexl-program' or `hexl-options' if needed.
a2535589
JA
35;;
36;; Currently hexl only supports big endian hex output with 16 bit
37;; grouping.
38;;
39;; -iso in `hexl-options' will allow iso characters to display in the
40;; ASCII region of the screen (if your emacs supports this) instead of
41;; changing them to dots.
42
e5167999
ER
43;;; Code:
44
01ff9136
MY
45(require 'eldoc)
46
a2535589
JA
47;;
48;; vars here
49;;
50
00ed33e7
RS
51(defgroup hexl nil
52 "Edit a file in a hex dump format using the hexl filter."
53 :group 'data)
54
55
56(defcustom hexl-program "hexl"
65e5f4bc 57 "The program that will hexlify and dehexlify its stdin.
57f07931 58`hexl-program' will always be concatenated with `hexl-options'
00ed33e7
RS
59and \"-de\" when dehexlifying a buffer."
60 :type 'string
61 :group 'hexl)
a2535589 62
00ed33e7 63(defcustom hexl-iso ""
a2535589 64 "If your emacs can handle ISO characters, this should be set to
00ed33e7
RS
65\"-iso\" otherwise it should be \"\"."
66 :type 'string
67 :group 'hexl)
a2535589 68
00ed33e7 69(defcustom hexl-options (format "-hex %s" hexl-iso)
b8c49a19
SM
70 "Space separated options to `hexl-program' that suit your needs.
71Quoting cannot be used, so the arguments cannot themselves contain spaces."
00ed33e7
RS
72 :type 'string
73 :group 'hexl)
a2535589 74
db6c5b92
SE
75(defcustom hexl-follow-ascii t
76 "If non-nil then highlight the ASCII character corresponding to point."
77 :type 'boolean
cd32a7ba
DN
78 :group 'hexl
79 :version "20.3")
db6c5b92 80
9fd76d04
MY
81(defcustom hexl-mode-hook '(hexl-follow-line hexl-activate-ruler)
82 "Normal hook run when entering Hexl mode."
83 :type 'hook
84 :options '(hexl-follow-line hexl-activate-ruler turn-on-eldoc-mode)
85 :group 'hexl)
86
87(defface hexl-address-area
88 '((t (:inherit header-line)))
89 "Face used in address are of hexl-mode buffer."
90 :group 'hexl)
91
92(defface hexl-ascii-area
93 '((t (:inherit header-line)))
94 "Face used in ascii are of hexl-mode buffer."
95 :group 'hexl)
96
a2535589
JA
97(defvar hexl-max-address 0
98 "Maximum offset into hexl buffer.")
99
100(defvar hexl-mode-map nil)
101
f39c6650
RS
102(defvar hexl-mode-old-local-map)
103(defvar hexl-mode-old-mode-name)
104(defvar hexl-mode-old-major-mode)
87b3b78a 105(defvar hexl-mode-old-isearch-search-fun-function)
0e4889b2
RS
106(defvar hexl-mode-old-require-final-newline)
107(defvar hexl-mode-old-syntax-table)
f39c6650 108
db6c5b92
SE
109(defvar hexl-ascii-overlay nil
110 "Overlay used to highlight ASCII element corresponding to current point.")
111(make-variable-buffer-local 'hexl-ascii-overlay)
112
a2535589
JA
113;; routines
114
2d902813
RS
115(put 'hexl-mode 'mode-class 'special)
116
31c75fa7 117;;;###autoload
a2535589 118(defun hexl-mode (&optional arg)
330bd7c3
PR
119 "\\<hexl-mode-map>A mode for editing binary files in hex dump format.
120This is not an ordinary major mode; it alters some aspects
fe0a77c6 121of the current mode's behavior, but not all; also, you can exit
330bd7c3 122Hexl mode and return to the previous mode using `hexl-mode-exit'.
a2535589
JA
123
124This function automatically converts a buffer into the hexl format
125using the function `hexlify-buffer'.
126
8a1281b5 127Each line in the buffer has an \"address\" (displayed in hexadecimal)
a2535589
JA
128representing the offset into the file that the characters on this line
129are at and 16 characters from the file (displayed as hexadecimal
130values grouped every 16 bits) and as their ASCII values.
131
132If any of the characters (displayed as ASCII characters) are
133unprintable (control or meta characters) they will be replaced as
134periods.
135
8a1281b5
RS
136If `hexl-mode' is invoked with an argument the buffer is assumed to be
137in hexl format.
a2535589
JA
138
139A sample format:
140
141 HEX ADDR: 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f ASCII-TEXT
142 -------- ---- ---- ---- ---- ---- ---- ---- ---- ----------------
143 00000000: 5468 6973 2069 7320 6865 786c 2d6d 6f64 This is hexl-mod
144 00000010: 652e 2020 4561 6368 206c 696e 6520 7265 e. Each line re
145 00000020: 7072 6573 656e 7473 2031 3620 6279 7465 presents 16 byte
146 00000030: 7320 6173 2068 6578 6164 6563 696d 616c s as hexadecimal
147 00000040: 2041 5343 4949 0a61 6e64 2070 7269 6e74 ASCII.and print
148 00000050: 6162 6c65 2041 5343 4949 2063 6861 7261 able ASCII chara
149 00000060: 6374 6572 732e 2020 416e 7920 636f 6e74 cters. Any cont
150 00000070: 726f 6c20 6f72 206e 6f6e 2d41 5343 4949 rol or non-ASCII
71296446 151 00000080: 2063 6861 7261 6374 6572 730a 6172 6520 characters.are
a2535589
JA
152 00000090: 6469 7370 6c61 7965 6420 6173 2070 6572 displayed as per
153 000000a0: 696f 6473 2069 6e20 7468 6520 7072 696e iods in the prin
71296446 154 000000b0: 7461 626c 6520 6368 6172 6163 7465 7220 table character
a2535589
JA
155 000000c0: 7265 6769 6f6e 2e0a region..
156
157Movement is as simple as movement in a normal emacs text buffer. Most
158cursor movement bindings are the same (ie. Use \\[hexl-backward-char], \\[hexl-forward-char], \\[hexl-next-line], and \\[hexl-previous-line]
159to move the cursor left, right, down, and up).
160
161Advanced cursor movement commands (ala \\[hexl-beginning-of-line], \\[hexl-end-of-line], \\[hexl-beginning-of-buffer], and \\[hexl-end-of-buffer]) are
162also supported.
163
164There are several ways to change text in hexl mode:
165
166ASCII characters (character between space (0x20) and tilde (0x7E)) are
167bound to self-insert so you can simply type the character and it will
168insert itself (actually overstrike) into the buffer.
169
170\\[hexl-quoted-insert] followed by another keystroke allows you to insert the key even if
171it isn't bound to self-insert. An octal number can be supplied in place
172of another key to insert the octal number's ASCII representation.
173
174\\[hexl-insert-hex-char] will insert a given hexadecimal value (if it is between 0 and 0xFF)
175into the buffer at the current point.
176
177\\[hexl-insert-octal-char] will insert a given octal value (if it is between 0 and 0377)
178into the buffer at the current point.
179
180\\[hexl-insert-decimal-char] will insert a given decimal value (if it is between 0 and 255)
181into the buffer at the current point.
182
a2535589
JA
183\\[hexl-mode-exit] will exit hexl-mode.
184
31c75fa7
RS
185Note: saving the file with any of the usual Emacs commands
186will actually convert it back to binary format while saving.
a2535589 187
330bd7c3 188You can use \\[hexl-find-file] to visit a file in Hexl mode.
a2535589
JA
189
190\\[describe-bindings] for advanced commands."
191 (interactive "p")
330bd7c3 192 (unless (eq major-mode 'hexl-mode)
753c1309
RS
193 (let ((modified (buffer-modified-p))
194 (inhibit-read-only t)
87b3b78a 195 (original-point (- (point) (point-min)))
753c1309
RS
196 max-address)
197 (and (eobp) (not (bobp))
198 (setq original-point (1- original-point)))
199 (if (not (or (eq arg 1) (not arg)))
200 ;; if no argument then we guess at hexl-max-address
201 (setq max-address (+ (* (/ (1- (buffer-size)) 68) 16) 15))
202 (setq max-address (1- (buffer-size)))
7851eb98
EZ
203 ;; If the buffer's EOL type is -dos, we need to account for
204 ;; extra CR characters added when hexlify-buffer writes the
205 ;; buffer to a file.
206 (when (eq (coding-system-eol-type buffer-file-coding-system) 1)
207 (setq max-address (+ (count-lines (point-min) (point-max))
208 max-address))
209 ;; But if there's no newline at the last line, we are off by
210 ;; one; adjust.
211 (or (eq (char-before (point-max)) ?\n)
212 (setq max-address (1- max-address)))
213 (setq original-point (+ (count-lines (point-min) (point))
214 original-point))
215 (or (bolp) (setq original-point (1- original-point))))
753c1309
RS
216 (hexlify-buffer)
217 (set-buffer-modified-p modified))
218 (make-local-variable 'hexl-max-address)
219 (setq hexl-max-address max-address)
220 (hexl-goto-address original-point))
221
0e4889b2
RS
222 ;; We do not turn off the old major mode; instead we just
223 ;; override most of it. That way, we can restore it perfectly.
a2535589
JA
224 (make-local-variable 'hexl-mode-old-local-map)
225 (setq hexl-mode-old-local-map (current-local-map))
226 (use-local-map hexl-mode-map)
227
228 (make-local-variable 'hexl-mode-old-mode-name)
229 (setq hexl-mode-old-mode-name mode-name)
230 (setq mode-name "Hexl")
231
87b3b78a
SM
232 (set (make-local-variable 'hexl-mode-old-isearch-search-fun-function)
233 isearch-search-fun-function)
234 (set (make-local-variable 'isearch-search-fun-function)
235 'hexl-isearch-search-function)
236
a2535589
JA
237 (make-local-variable 'hexl-mode-old-major-mode)
238 (setq hexl-mode-old-major-mode major-mode)
239 (setq major-mode 'hexl-mode)
240
0e4889b2
RS
241 (make-local-variable 'hexl-mode-old-syntax-table)
242 (setq hexl-mode-old-syntax-table (syntax-table))
243 (set-syntax-table (standard-syntax-table))
244
87b3b78a 245 (add-hook 'write-contents-functions 'hexl-save-buffer nil t)
31c75fa7 246
0e4889b2
RS
247 (make-local-variable 'hexl-mode-old-require-final-newline)
248 (setq hexl-mode-old-require-final-newline require-final-newline)
249 (make-local-variable 'require-final-newline)
250 (setq require-final-newline nil)
251
252 ;; Add hooks to rehexlify or dehexlify on various events.
c3de2bf0
RS
253 (add-hook 'after-revert-hook 'hexl-after-revert-hook nil t)
254
db6c5b92
SE
255 (add-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer nil t)
256
01ff9136 257 ;; Set a callback function for eldoc.
4f918f60 258 (set (make-local-variable 'eldoc-print-current-symbol-info-function)
01ff9136
MY
259 'hexl-print-current-point-info)
260 (eldoc-add-command-completions "hexl-")
261 (eldoc-remove-command "hexl-save-buffer"
262 "hexl-current-address")
263
db6c5b92 264 (if hexl-follow-ascii (hexl-follow-ascii 1)))
7bfff21e 265 (run-hooks 'hexl-mode-hook))
a2535589 266
87b3b78a
SM
267
268(defun hexl-isearch-search-function ()
269 (if (and (not isearch-regexp) (not isearch-word))
270 (lambda (string &optional bound noerror count)
271 (funcall
272 (if isearch-forward 're-search-forward 're-search-backward)
273 (if (> (length string) 80)
274 (regexp-quote string)
275 (mapconcat 'string string "\\(?:\n\\(?:[:a-f0-9]+ \\)+ \\)?"))
276 bound noerror count))
277 (let ((isearch-search-fun-function nil))
278 (isearch-search-fun))))
279
c3de2bf0 280(defun hexl-after-revert-hook ()
059c2e18 281 (setq hexl-max-address (1- (buffer-size)))
c3de2bf0
RS
282 (hexlify-buffer)
283 (set-buffer-modified-p nil))
284
ac2e902d
JB
285(defvar hexl-in-save-buffer nil)
286
a2535589
JA
287(defun hexl-save-buffer ()
288 "Save a hexl format buffer as binary in visited file if modified."
289 (interactive)
ac2e902d
JB
290 (if hexl-in-save-buffer nil
291 (set-buffer-modified-p (if (buffer-modified-p)
292 (save-excursion
293 (let ((buf (generate-new-buffer " hexl"))
294 (name (buffer-name))
295 (file-name (buffer-file-name))
296 (start (point-min))
297 (end (point-max))
298 modified)
299 (set-buffer buf)
300 (insert-buffer-substring name start end)
301 (set-buffer name)
302 (dehexlify-buffer)
303 ;; Prevent infinite recursion.
338992a5 304 (let ((hexl-in-save-buffer t))
ac2e902d
JB
305 (save-buffer))
306 (setq modified (buffer-modified-p))
307 (delete-region (point-min) (point-max))
308 (insert-buffer-substring buf start end)
309 (kill-buffer buf)
310 modified))
311 (message "(No changes need to be saved)")
312 nil))
313 ;; Return t to indicate we have saved t
314 t))
a2535589 315
31c75fa7 316;;;###autoload
a2535589
JA
317(defun hexl-find-file (filename)
318 "Edit file FILENAME in hexl-mode.
a2535589 319Switch to a buffer visiting file FILENAME, creating one in none exists."
e49a45ad
MB
320 (interactive
321 (list
322 (let ((completion-ignored-extensions nil))
323 (read-file-name "Filename: " nil nil 'ret-must-match))))
3db6aff6 324 ;; Ignore the user's setting of default-major-mode.
45e8e6e7 325 (let ((default-major-mode 'fundamental-mode))
3db6aff6 326 (find-file-literally filename))
a2535589
JA
327 (if (not (eq major-mode 'hexl-mode))
328 (hexl-mode)))
329
330(defun hexl-mode-exit (&optional arg)
31c75fa7 331 "Exit Hexl mode, returning to previous mode.
a2535589
JA
332With arg, don't unhexlify buffer."
333 (interactive "p")
334 (if (or (eq arg 1) (not arg))
335 (let ((modified (buffer-modified-p))
900014dd 336 (inhibit-read-only t)
a2535589 337 (original-point (1+ (hexl-current-address))))
a2535589 338 (dehexlify-buffer)
87b3b78a 339 (remove-hook 'write-contents-functions 'hexl-save-buffer t)
a2535589 340 (set-buffer-modified-p modified)
7851eb98
EZ
341 (goto-char original-point)
342 ;; Maybe adjust point for the removed CR characters.
343 (when (eq (coding-system-eol-type buffer-file-coding-system) 1)
344 (setq original-point (- original-point
345 (count-lines (point-min) (point))))
346 (or (bobp) (setq original-point (1+ original-point))))
a2535589 347 (goto-char original-point)))
0e4889b2
RS
348
349 (remove-hook 'after-revert-hook 'hexl-after-revert-hook t)
350 (remove-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer t)
8e7df2e6
SE
351 (remove-hook 'post-command-hook 'hexl-follow-ascii-find t)
352 (setq hexl-ascii-overlay nil)
0e4889b2 353
0e4889b2 354 (setq require-final-newline hexl-mode-old-require-final-newline)
a2535589 355 (setq mode-name hexl-mode-old-mode-name)
87b3b78a 356 (setq isearch-search-fun-function hexl-mode-old-isearch-search-fun-function)
a2535589 357 (use-local-map hexl-mode-old-local-map)
0e4889b2 358 (set-syntax-table hexl-mode-old-syntax-table)
a2535589 359 (setq major-mode hexl-mode-old-major-mode)
8eeac2ce
RS
360 (force-mode-line-update))
361
362(defun hexl-maybe-dehexlify-buffer ()
363 "Convert a hexl format buffer to binary.
364Ask the user for confirmation."
365 (if (y-or-n-p "Convert contents back to binary format? ")
366 (let ((modified (buffer-modified-p))
367 (inhibit-read-only t)
368 (original-point (1+ (hexl-current-address))))
369 (dehexlify-buffer)
87b3b78a 370 (remove-hook 'write-contents-functions 'hexl-save-buffer t)
8eeac2ce
RS
371 (set-buffer-modified-p modified)
372 (goto-char original-point))))
a2535589 373
6bbb008e 374(defun hexl-current-address (&optional validate)
a2535589
JA
375 "Return current hexl-address."
376 (interactive)
87b3b78a 377 (let ((current-column (- (% (- (point) (point-min) -1) 68) 11))
a2535589 378 (hexl-address 0))
6bbb008e
RS
379 (if (< current-column 0)
380 (if validate
381 (error "Point is not on a character in the file")
382 (setq current-column 0)))
383 (setq hexl-address
87b3b78a 384 (+ (* (/ (- (point) (point-min) -1) 68) 16)
6bbb008e
RS
385 (if (>= current-column 41)
386 (- current-column 41)
387 (/ (- current-column (/ current-column 5)) 2))))
48f56596 388 (when (interactive-p)
01ff9136 389 (message "Current address is %d/0x%08x" hexl-address hexl-address))
a2535589
JA
390 hexl-address))
391
01ff9136
MY
392(defun hexl-print-current-point-info ()
393 "Return current hexl-address in string.
394This function is indented to be used as eldoc callback."
395 (let ((addr (hexl-current-address)))
396 (format "Current address is %d/0x%08x" addr addr)))
397
a2535589 398(defun hexl-address-to-marker (address)
059c2e18 399 "Return buffer position for ADDRESS."
a2535589 400 (interactive "nAddress: ")
87b3b78a 401 (+ (* (/ address 16) 68) 10 (point-min) (/ (* (% address 16) 5) 2)))
a2535589
JA
402
403(defun hexl-goto-address (address)
404 "Goto hexl-mode (decimal) address ADDRESS.
a2535589
JA
405Signal error if ADDRESS out of range."
406 (interactive "nAddress: ")
407 (if (or (< address 0) (> address hexl-max-address))
19e31f7c 408 (error "Out of hexl region"))
a2535589
JA
409 (goto-char (hexl-address-to-marker address)))
410
411(defun hexl-goto-hex-address (hex-address)
4c8c7ae9 412 "Go to hexl-mode address (hex string) HEX-ADDRESS.
a2535589
JA
413Signal error if HEX-ADDRESS is out of range."
414 (interactive "sHex Address: ")
415 (hexl-goto-address (hexl-hex-string-to-integer hex-address)))
416
417(defun hexl-hex-string-to-integer (hex-string)
418 "Return decimal integer for HEX-STRING."
419 (interactive "sHex number: ")
420 (let ((hex-num 0))
421 (while (not (equal hex-string ""))
422 (setq hex-num (+ (* hex-num 16)
423 (hexl-hex-char-to-integer (string-to-char hex-string))))
424 (setq hex-string (substring hex-string 1)))
425 hex-num))
426
427(defun hexl-octal-string-to-integer (octal-string)
428 "Return decimal integer for OCTAL-STRING."
429 (interactive "sOctal number: ")
430 (let ((oct-num 0))
431 (while (not (equal octal-string ""))
432 (setq oct-num (+ (* oct-num 8)
433 (hexl-oct-char-to-integer
434 (string-to-char octal-string))))
435 (setq octal-string (substring octal-string 1)))
436 oct-num))
437
438;; move point functions
439
440(defun hexl-backward-char (arg)
441 "Move to left ARG bytes (right if ARG negative) in hexl-mode."
442 (interactive "p")
443 (hexl-goto-address (- (hexl-current-address) arg)))
444
445(defun hexl-forward-char (arg)
446 "Move right ARG bytes (left if ARG negative) in hexl-mode."
447 (interactive "p")
448 (hexl-goto-address (+ (hexl-current-address) arg)))
449
450(defun hexl-backward-short (arg)
451 "Move to left ARG shorts (right if ARG negative) in hexl-mode."
452 (interactive "p")
453 (hexl-goto-address (let ((address (hexl-current-address)))
454 (if (< arg 0)
455 (progn
456 (setq arg (- arg))
457 (while (> arg 0)
458 (if (not (equal address (logior address 3)))
459 (if (> address hexl-max-address)
460 (progn
461 (message "End of buffer.")
462 (setq address hexl-max-address))
463 (setq address (logior address 3)))
464 (if (> address hexl-max-address)
465 (progn
466 (message "End of buffer.")
467 (setq address hexl-max-address))
468 (setq address (+ address 4))))
469 (setq arg (1- arg)))
470 (if (> address hexl-max-address)
471 (progn
472 (message "End of buffer.")
473 (setq address hexl-max-address))
474 (setq address (logior address 3))))
475 (while (> arg 0)
476 (if (not (equal address (logand address -4)))
477 (setq address (logand address -4))
478 (if (not (equal address 0))
479 (setq address (- address 4))
480 (message "Beginning of buffer.")))
481 (setq arg (1- arg))))
482 address)))
483
484(defun hexl-forward-short (arg)
485 "Move right ARG shorts (left if ARG negative) in hexl-mode."
486 (interactive "p")
487 (hexl-backward-short (- arg)))
488
489(defun hexl-backward-word (arg)
490 "Move to left ARG words (right if ARG negative) in hexl-mode."
491 (interactive "p")
492 (hexl-goto-address (let ((address (hexl-current-address)))
493 (if (< arg 0)
494 (progn
495 (setq arg (- arg))
496 (while (> arg 0)
497 (if (not (equal address (logior address 7)))
498 (if (> address hexl-max-address)
499 (progn
500 (message "End of buffer.")
501 (setq address hexl-max-address))
502 (setq address (logior address 7)))
503 (if (> address hexl-max-address)
504 (progn
505 (message "End of buffer.")
506 (setq address hexl-max-address))
507 (setq address (+ address 8))))
508 (setq arg (1- arg)))
509 (if (> address hexl-max-address)
510 (progn
511 (message "End of buffer.")
512 (setq address hexl-max-address))
513 (setq address (logior address 7))))
514 (while (> arg 0)
515 (if (not (equal address (logand address -8)))
516 (setq address (logand address -8))
517 (if (not (equal address 0))
518 (setq address (- address 8))
519 (message "Beginning of buffer.")))
520 (setq arg (1- arg))))
521 address)))
522
523(defun hexl-forward-word (arg)
524 "Move right ARG words (left if ARG negative) in hexl-mode."
525 (interactive "p")
526 (hexl-backward-word (- arg)))
527
528(defun hexl-previous-line (arg)
4c8c7ae9
JB
529 "Move vertically up ARG lines [16 bytes] (down if ARG negative) in hexl-mode.
530If there is byte at the target address move to the last byte in that line."
a2535589
JA
531 (interactive "p")
532 (hexl-next-line (- arg)))
533
534(defun hexl-next-line (arg)
4c8c7ae9
JB
535 "Move vertically down ARG lines [16 bytes] (up if ARG negative) in hexl-mode.
536If there is no byte at the target address move to the last byte in that line."
a2535589 537 (interactive "p")
e8a57935 538 (hexl-goto-address (let ((address (+ (hexl-current-address) (* arg 16))))
a2535589
JA
539 (if (and (< arg 0) (< address 0))
540 (progn (message "Out of hexl region.")
541 (setq address
542 (% (hexl-current-address) 16)))
543 (if (and (> address hexl-max-address)
544 (< (% hexl-max-address 16) (% address 16)))
545 (setq address hexl-max-address)
546 (if (> address hexl-max-address)
547 (progn (message "Out of hexl region.")
548 (setq
549 address
550 (+ (logand hexl-max-address -16)
551 (% (hexl-current-address) 16)))))))
552 address)))
553
554(defun hexl-beginning-of-buffer (arg)
4c8c7ae9
JB
555 "Move to the beginning of the hexl buffer.
556Leaves `hexl-mark' at previous position.
557With prefix arg N, puts point N bytes of the way from the true beginning."
a2535589
JA
558 (interactive "p")
559 (push-mark (point))
560 (hexl-goto-address (+ 0 (1- arg))))
561
562(defun hexl-end-of-buffer (arg)
4c8c7ae9 563 "Go to `hexl-max-address' minus ARG."
a2535589
JA
564 (interactive "p")
565 (push-mark (point))
566 (hexl-goto-address (- hexl-max-address (1- arg))))
567
568(defun hexl-beginning-of-line ()
569 "Goto beginning of line in hexl mode."
570 (interactive)
571 (goto-char (+ (* (/ (point) 68) 68) 11)))
572
573(defun hexl-end-of-line ()
574 "Goto end of line in hexl mode."
575 (interactive)
576 (hexl-goto-address (let ((address (logior (hexl-current-address) 15)))
577 (if (> address hexl-max-address)
578 (setq address hexl-max-address))
579 address)))
580
581(defun hexl-scroll-down (arg)
582 "Scroll hexl buffer window upward ARG lines; or near full window if no ARG."
583 (interactive "P")
584 (if (null arg)
585 (setq arg (1- (window-height)))
586 (setq arg (prefix-numeric-value arg)))
587 (hexl-scroll-up (- arg)))
588
589(defun hexl-scroll-up (arg)
d565f6aa
EZ
590 "Scroll hexl buffer window upward ARG lines; or near full window if no ARG.
591If there's no byte at the target address, move to the first or last line."
a2535589
JA
592 (interactive "P")
593 (if (null arg)
594 (setq arg (1- (window-height)))
595 (setq arg (prefix-numeric-value arg)))
d565f6aa
EZ
596 (let* ((movement (* arg 16))
597 (address (hexl-current-address))
598 (dest (+ address movement)))
599 (cond
600 ;; If possible, try to stay at the same offset from the beginning
601 ;; of the 16-byte group, even if we move to the first or last
602 ;; group.
603 ((and (> dest hexl-max-address)
604 (>= (% hexl-max-address 16) (% address 16)))
605 (setq dest (+ (logand hexl-max-address -16) (% address 16))))
606 ((> dest hexl-max-address)
607 (setq dest hexl-max-address))
608 ((< dest 0)
609 (setq dest (% address 16))))
610 (if (/= dest (+ address movement))
611 (message "Out of hexl region."))
612 (hexl-goto-address dest)
613 (recenter 0)))
a2535589
JA
614
615(defun hexl-beginning-of-1k-page ()
65e5f4bc 616 "Go to beginning of 1k boundary."
a2535589
JA
617 (interactive)
618 (hexl-goto-address (logand (hexl-current-address) -1024)))
619
620(defun hexl-end-of-1k-page ()
65e5f4bc 621 "Go to end of 1k boundary."
a2535589
JA
622 (interactive)
623 (hexl-goto-address (let ((address (logior (hexl-current-address) 1023)))
624 (if (> address hexl-max-address)
625 (setq address hexl-max-address))
626 address)))
627
628(defun hexl-beginning-of-512b-page ()
65e5f4bc 629 "Go to beginning of 512 byte boundary."
a2535589
JA
630 (interactive)
631 (hexl-goto-address (logand (hexl-current-address) -512)))
632
633(defun hexl-end-of-512b-page ()
65e5f4bc 634 "Go to end of 512 byte boundary."
a2535589
JA
635 (interactive)
636 (hexl-goto-address (let ((address (logior (hexl-current-address) 511)))
637 (if (> address hexl-max-address)
638 (setq address hexl-max-address))
639 address)))
640
641(defun hexl-quoted-insert (arg)
642 "Read next input character and insert it.
02aec07b
EZ
643Useful for inserting control characters and non-ASCII characters given their
644numerical code.
645You may also type octal digits, to insert a character with that code."
a2535589 646 (interactive "p")
02aec07b 647 (hexl-insert-multibyte-char (read-quoted-char) arg))
a2535589
JA
648
649;00000000: 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789ABCDEF
650
f4e3d4eb 651;;;###autoload
a2535589 652(defun hexlify-buffer ()
aa3757b8
RS
653 "Convert a binary buffer to hexl format.
654This discards the buffer's undo information."
a2535589 655 (interactive)
aa3757b8
RS
656 (and buffer-undo-list
657 (or (y-or-n-p "Converting to hexl format discards undo info; ok? ")
658 (error "Aborted")))
659 (setq buffer-undo-list nil)
a749e5e5
EZ
660 ;; Don't decode text in the ASCII part of `hexl' program output.
661 (let ((coding-system-for-read 'raw-text)
0716afa2 662 (coding-system-for-write buffer-file-coding-system)
aa3757b8 663 (buffer-undo-list t))
b8c49a19
SM
664 (apply 'call-process-region (point-min) (point-max)
665 (expand-file-name hexl-program exec-directory)
666 t t nil (split-string hexl-options))
9fd76d04
MY
667 (save-excursion
668 (goto-char (point-min))
669 (while (re-search-forward "^[0-9a-f]+:" nil t)
670 (put-text-property (match-beginning 0) (match-end 0)
671 'font-lock-face 'hexl-address-area))
672 (goto-char (point-min))
673 (while (re-search-forward " \\(.+$\\)" nil t)
674 (put-text-property (match-beginning 1) (match-end 1)
675 'font-lock-face 'hexl-ascii-area)))
059c2e18
PR
676 (if (> (point) (hexl-address-to-marker hexl-max-address))
677 (hexl-goto-address hexl-max-address))))
a2535589
JA
678
679(defun dehexlify-buffer ()
aa3757b8
RS
680 "Convert a hexl format buffer to binary.
681This discards the buffer's undo information."
a2535589 682 (interactive)
aa3757b8
RS
683 (and buffer-undo-list
684 (or (y-or-n-p "Converting from hexl format discards undo info; ok? ")
685 (error "Aborted")))
686 (setq buffer-undo-list nil)
a749e5e5 687 (let ((coding-system-for-write 'raw-text)
0716afa2 688 (coding-system-for-read buffer-file-coding-system)
aa3757b8 689 (buffer-undo-list t))
b8c49a19
SM
690 (apply 'call-process-region (point-min) (point-max)
691 (expand-file-name hexl-program exec-directory)
692 t t nil "-de" (split-string hexl-options))))
a2535589
JA
693
694(defun hexl-char-after-point ()
695 "Return char for ASCII hex digits at point."
686fc9ab
RS
696 (hexl-htoi (char-after (point))
697 (char-after (1+ (point)))))
a2535589
JA
698
699(defun hexl-htoi (lh rh)
700 "Hex (char) LH (char) RH to integer."
701 (+ (* (hexl-hex-char-to-integer lh) 16)
702 (hexl-hex-char-to-integer rh)))
703
704(defun hexl-hex-char-to-integer (character)
705 "Take a char and return its value as if it was a hex digit."
706 (if (and (>= character ?0) (<= character ?9))
707 (- character ?0)
708 (let ((ch (logior character 32)))
709 (if (and (>= ch ?a) (<= ch ?f))
710 (- ch (- ?a 10))
19e31f7c 711 (error "Invalid hex digit `%c'" ch)))))
a2535589
JA
712
713(defun hexl-oct-char-to-integer (character)
714 "Take a char and return its value as if it was a octal digit."
715 (if (and (>= character ?0) (<= character ?7))
716 (- character ?0)
19e31f7c 717 (error "Invalid octal digit `%c'" character)))
a2535589
JA
718
719(defun hexl-printable-character (ch)
720 "Return a displayable string for character CH."
721 (format "%c" (if hexl-iso
722 (if (or (< ch 32) (and (>= ch 127) (< ch 160)))
723 46
724 ch)
725 (if (or (< ch 32) (>= ch 127))
726 46
727 ch))))
728
02aec07b
EZ
729(defun hexl-insert-multibyte-char (ch num)
730 "Insert a possibly multibyte character CH NUM times.
731
732Non-ASCII characters are first encoded with `buffer-file-coding-system',
733and their encoded form is inserted byte by byte."
734 (let ((charset (char-charset ch))
735 (coding (if (or (null buffer-file-coding-system)
736 ;; coding-system-type equals t means undecided.
737 (eq (coding-system-type buffer-file-coding-system) t))
738 default-buffer-file-coding-system
739 buffer-file-coding-system)))
740 (cond ((and (> ch 0) (< ch 256))
741 (hexl-insert-char ch num))
742 ((eq charset 'unknown)
743 (error
165b4283 744 "0x%x -- invalid character code; use \\[hexl-insert-hex-string]"
02aec07b
EZ
745 ch))
746 (t
747 (let ((encoded (encode-coding-char ch coding))
748 (internal (string-as-unibyte (char-to-string ch)))
749 internal-hex)
750 ;; If encode-coding-char returns nil, it means our character
751 ;; cannot be safely encoded with buffer-file-coding-system.
752 ;; In that case, we offer to insert the internal representation
753 ;; of that character, byte by byte.
754 (when (null encoded)
755 (setq internal-hex
756 (mapconcat (function (lambda (c) (format "%x" c)))
757 internal " "))
758 (if (yes-or-no-p
759 (format
760 "Insert char 0x%x's internal representation \"%s\"? "
761 ch internal-hex))
762 (setq encoded internal)
763 (error
165b4283 764 "Can't encode `0x%x' with this buffer's coding system; try \\[hexl-insert-hex-string]"
02aec07b
EZ
765 ch)))
766 (while (> num 0)
767 (mapc
768 (function (lambda (c) (hexl-insert-char c 1))) encoded)
769 (setq num (1- num))))))))
770
a2535589 771(defun hexl-self-insert-command (arg)
02aec07b
EZ
772 "Insert this character.
773Interactively, with a numeric argument, insert this character that many times.
774
775Non-ASCII characters are first encoded with `buffer-file-coding-system',
776and their encoded form is inserted byte by byte."
a2535589 777 (interactive "p")
02aec07b 778 (hexl-insert-multibyte-char last-command-char arg))
a2535589
JA
779
780(defun hexl-insert-char (ch num)
02aec07b
EZ
781 "Insert the character CH NUM times in a hexl buffer.
782
783CH must be a unibyte character whose value is between 0 and 255."
784 (if (or (< ch 0) (> ch 255))
45ad49ba 785 (error "Invalid character 0x%x -- must be in the range [0..255]" ch))
6bbb008e 786 (let ((address (hexl-current-address t)))
a2535589 787 (while (> num 0)
6bbb008e
RS
788 (let ((hex-position
789 (+ (* (/ address 16) 68)
87b3b78a 790 10 (point-min)
6bbb008e
RS
791 (* 2 (% address 16))
792 (/ (% address 16) 2)))
793 (ascii-position
87b3b78a 794 (+ (* (/ address 16) 68) 51 (point-min) (% address 16)))
6bbb008e
RS
795 at-ascii-position)
796 (if (= (point) ascii-position)
797 (setq at-ascii-position t))
798 (goto-char hex-position)
799 (delete-char 2)
800 (insert (format "%02x" ch))
801 (goto-char ascii-position)
802 (delete-char 1)
803 (insert (hexl-printable-character ch))
804 (or (eq address hexl-max-address)
805 (setq address (1+ address)))
806 (hexl-goto-address address)
807 (if at-ascii-position
808 (progn
809 (beginning-of-line)
810 (forward-char 51)
811 (forward-char (% address 16)))))
a2535589
JA
812 (setq num (1- num)))))
813
814;; hex conversion
815
816(defun hexl-insert-hex-char (arg)
02aec07b 817 "Insert a character given by its hexadecimal code ARG times at point."
a2535589
JA
818 (interactive "p")
819 (let ((num (hexl-hex-string-to-integer (read-string "Hex number: "))))
02aec07b 820 (if (< num 0)
19e31f7c 821 (error "Hex number out of range")
02aec07b 822 (hexl-insert-multibyte-char num arg))))
a2535589 823
9f6bff44
GM
824(defun hexl-insert-hex-string (str arg)
825 "Insert hexadecimal string STR at point ARG times.
826Embedded whitespace, dashes, and periods in the string are ignored."
827 (interactive "sHex string: \np")
828 (setq str (replace-regexp-in-string "[- \t.]" "" str))
829 (let ((chars '()))
830 (let ((len (length str))
831 (idx 0))
832 (if (eq (logand len 1) 1)
833 (let ((num (hexl-hex-string-to-integer (substring str 0 1))))
834 (setq chars (cons num chars))
835 (setq idx 1)))
836 (while (< idx len)
837 (let* ((nidx (+ idx 2))
838 (num (hexl-hex-string-to-integer (substring str idx nidx))))
839 (setq chars (cons num chars))
840 (setq idx nidx))))
841 (setq chars (nreverse chars))
842 (while (> arg 0)
843 (let ((chars chars))
844 (while chars
845 (hexl-insert-char (car chars) 1)
846 (setq chars (cdr chars))))
847 (setq arg (- arg 1)))))
848
a2535589 849(defun hexl-insert-decimal-char (arg)
02aec07b 850 "Insert a character given by its decimal code ARG times at point."
a2535589
JA
851 (interactive "p")
852 (let ((num (string-to-int (read-string "Decimal Number: "))))
02aec07b 853 (if (< num 0)
19e31f7c 854 (error "Decimal number out of range")
02aec07b 855 (hexl-insert-multibyte-char num arg))))
a2535589
JA
856
857(defun hexl-insert-octal-char (arg)
02aec07b 858 "Insert a character given by its octal code ARG times at point."
a2535589
JA
859 (interactive "p")
860 (let ((num (hexl-octal-string-to-integer (read-string "Octal Number: "))))
02aec07b 861 (if (< num 0)
19e31f7c 862 (error "Decimal number out of range")
02aec07b 863 (hexl-insert-multibyte-char num arg))))
a2535589 864
db6c5b92
SE
865(defun hexl-follow-ascii (&optional arg)
866 "Toggle following ASCII in Hexl buffers.
867With prefix ARG, turn on following if and only if ARG is positive.
868When following is enabled, the ASCII character corresponding to the
869element under the point is highlighted.
870Customize the variable `hexl-follow-ascii' to disable this feature."
871 (interactive "P")
71296446 872 (let ((on-p (if arg
db6c5b92
SE
873 (> (prefix-numeric-value arg) 0)
874 (not hexl-ascii-overlay))))
875
db6c5b92
SE
876 (if on-p
877 ;; turn it on
878 (if (not hexl-ascii-overlay)
879 (progn
880 (setq hexl-ascii-overlay (make-overlay 1 1)
881 hexl-follow-ascii t)
882 (overlay-put hexl-ascii-overlay 'face 'highlight)
883 (add-hook 'post-command-hook 'hexl-follow-ascii-find nil t)))
884 ;; turn it off
885 (if hexl-ascii-overlay
886 (progn
887 (delete-overlay hexl-ascii-overlay)
888 (setq hexl-ascii-overlay nil
889 hexl-follow-ascii nil)
890 (remove-hook 'post-command-hook 'hexl-follow-ascii-find t)
891 )))))
892
9fd76d04
MY
893(defun hexl-activate-ruler ()
894 "Activate `ruler-mode'"
895 (require 'ruler-mode)
896 (set (make-local-variable 'ruler-mode-ruler-function)
897 'hexl-mode-ruler)
898 (ruler-mode 1))
899
900(defun hexl-follow-line ()
901 "Activate `hl-line-mode'"
902 (require 'frame)
903 (require 'fringe)
904 (require 'hl-line)
905 (set (make-local-variable 'hl-line-range-function)
906 'hexl-highlight-line-range)
907 (set (make-local-variable 'hl-line-face)
908 'highlight)
909 (hl-line-mode 1))
910
911(defun hexl-highlight-line-range ()
912 "Return the range of address area for the point.
913This function is assumed to be used as call back function for `hl-line-mode'."
914 (cons
915 (line-beginning-position)
916 ;; 9 stands for (length "87654321:")
917 (+ (line-beginning-position) 9)))
918
db6c5b92
SE
919(defun hexl-follow-ascii-find ()
920 "Find and highlight the ASCII element corresponding to current point."
d565f6aa 921 (let ((pos (+ 51
db6c5b92
SE
922 (- (point) (current-column))
923 (mod (hexl-current-address) 16))))
924 (move-overlay hexl-ascii-overlay pos (1+ pos))
925 ))
926
9fd76d04
MY
927(defun hexl-mode-ruler ()
928 "Return a string ruler for hexl mode."
929 (let* ((highlight (mod (hexl-current-address) 16))
930 (s "87654321 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789abcdef")
931 (pos 0)
932 (spaces (+ (scroll-bar-columns 'left)
933 (fringe-columns 'left)
934 (or (car (window-margins)) 0))))
935 (set-text-properties 0 (length s) nil s)
936 ;; Turn spaces in the header into stretch specs so they work
937 ;; regardless of the header-line face.
938 (while (string-match "[ \t]+" s pos)
939 (setq pos (match-end 0))
940 (put-text-property (match-beginning 0) pos 'display
941 ;; Assume fixed-size chars
942 `(space :align-to (+ (scroll-bar . left)
943 left-fringe left-margin
944 ,pos))
945 s))
946 ;; Highlight the current column.
947 (put-text-property (+ 10 (/ (* 5 highlight) 2))
948 (+ 12 (/ (* 5 highlight) 2))
949 'face 'highlight s)
950 ;; Highlight the current ascii column
951 (put-text-property (+ 12 39 highlight) (+ 12 40 highlight)
952 'face 'highlight s)
953 ;; Add the leading space.
954 (concat (propertize (make-string (floor spaces) ? )
955 'display `(space :width ,spaces))
956 s)))
957
a2535589
JA
958;; startup stuff.
959
960(if hexl-mode-map
961 nil
4b7dd7e2 962 (setq hexl-mode-map (make-keymap))
02aec07b
EZ
963 ;; Make all self-inserting keys go through hexl-self-insert-command,
964 ;; because we need to convert them to unibyte characters before
965 ;; inserting them into the buffer.
340c4d85 966 (define-key hexl-mode-map [remap self-insert-command] 'hexl-self-insert-command)
ae2d451b 967
d9c8518d 968 (define-key hexl-mode-map "\C-m" 'hexl-self-insert-command)
ae2d451b
RS
969 (define-key hexl-mode-map [left] 'hexl-backward-char)
970 (define-key hexl-mode-map [right] 'hexl-forward-char)
971 (define-key hexl-mode-map [up] 'hexl-previous-line)
972 (define-key hexl-mode-map [down] 'hexl-next-line)
973 (define-key hexl-mode-map [M-left] 'hexl-backward-short)
974 (define-key hexl-mode-map [M-right] 'hexl-forward-short)
975 (define-key hexl-mode-map [next] 'hexl-scroll-up)
976 (define-key hexl-mode-map [prior] 'hexl-scroll-down)
d565f6aa
EZ
977 (define-key hexl-mode-map [home] 'hexl-beginning-of-line)
978 (define-key hexl-mode-map [end] 'hexl-end-of-line)
979 (define-key hexl-mode-map [C-home] 'hexl-beginning-of-buffer)
980 (define-key hexl-mode-map [C-end] 'hexl-end-of-buffer)
ae2d451b
RS
981 (define-key hexl-mode-map [deletechar] 'undefined)
982 (define-key hexl-mode-map [deleteline] 'undefined)
983 (define-key hexl-mode-map [insertline] 'undefined)
984 (define-key hexl-mode-map [S-delete] 'undefined)
985 (define-key hexl-mode-map "\177" 'undefined)
986
987 (define-key hexl-mode-map "\C-a" 'hexl-beginning-of-line)
988 (define-key hexl-mode-map "\C-b" 'hexl-backward-char)
989 (define-key hexl-mode-map "\C-d" 'undefined)
990 (define-key hexl-mode-map "\C-e" 'hexl-end-of-line)
991 (define-key hexl-mode-map "\C-f" 'hexl-forward-char)
992
993 (if (not (eq (key-binding (char-to-string help-char)) 'help-command))
994 (define-key hexl-mode-map (char-to-string help-char) 'undefined))
995
ae2d451b 996 (define-key hexl-mode-map "\C-k" 'undefined)
ae2d451b
RS
997 (define-key hexl-mode-map "\C-n" 'hexl-next-line)
998 (define-key hexl-mode-map "\C-o" 'undefined)
999 (define-key hexl-mode-map "\C-p" 'hexl-previous-line)
1000 (define-key hexl-mode-map "\C-q" 'hexl-quoted-insert)
1001 (define-key hexl-mode-map "\C-t" 'undefined)
1002 (define-key hexl-mode-map "\C-v" 'hexl-scroll-up)
1003 (define-key hexl-mode-map "\C-w" 'undefined)
1004 (define-key hexl-mode-map "\C-y" 'undefined)
1005
02aec07b
EZ
1006 (fset 'hexl-ESC-prefix (copy-keymap 'ESC-prefix))
1007 (define-key hexl-mode-map "\e" 'hexl-ESC-prefix)
ae2d451b
RS
1008 (define-key hexl-mode-map "\e\C-a" 'hexl-beginning-of-512b-page)
1009 (define-key hexl-mode-map "\e\C-b" 'hexl-backward-short)
ae2d451b
RS
1010 (define-key hexl-mode-map "\e\C-d" 'hexl-insert-decimal-char)
1011 (define-key hexl-mode-map "\e\C-e" 'hexl-end-of-512b-page)
1012 (define-key hexl-mode-map "\e\C-f" 'hexl-forward-short)
ae2d451b
RS
1013 (define-key hexl-mode-map "\e\C-i" 'undefined)
1014 (define-key hexl-mode-map "\e\C-j" 'undefined)
1015 (define-key hexl-mode-map "\e\C-k" 'undefined)
ae2d451b 1016 (define-key hexl-mode-map "\e\C-o" 'hexl-insert-octal-char)
ae2d451b 1017 (define-key hexl-mode-map "\e\C-q" 'undefined)
ae2d451b 1018 (define-key hexl-mode-map "\e\C-t" 'undefined)
ae2d451b 1019 (define-key hexl-mode-map "\e\C-x" 'hexl-insert-hex-char)
ae2d451b
RS
1020 (define-key hexl-mode-map "\eb" 'hexl-backward-word)
1021 (define-key hexl-mode-map "\ec" 'undefined)
1022 (define-key hexl-mode-map "\ed" 'undefined)
ae2d451b
RS
1023 (define-key hexl-mode-map "\ef" 'hexl-forward-word)
1024 (define-key hexl-mode-map "\eg" 'hexl-goto-hex-address)
ae2d451b
RS
1025 (define-key hexl-mode-map "\ei" 'undefined)
1026 (define-key hexl-mode-map "\ej" 'hexl-goto-address)
1027 (define-key hexl-mode-map "\ek" 'undefined)
1028 (define-key hexl-mode-map "\el" 'undefined)
ae2d451b 1029 (define-key hexl-mode-map "\eq" 'undefined)
ae2d451b
RS
1030 (define-key hexl-mode-map "\es" 'undefined)
1031 (define-key hexl-mode-map "\et" 'undefined)
1032 (define-key hexl-mode-map "\eu" 'undefined)
1033 (define-key hexl-mode-map "\ev" 'hexl-scroll-down)
1034 (define-key hexl-mode-map "\ey" 'undefined)
1035 (define-key hexl-mode-map "\ez" 'undefined)
1036 (define-key hexl-mode-map "\e<" 'hexl-beginning-of-buffer)
1037 (define-key hexl-mode-map "\e>" 'hexl-end-of-buffer)
1038
02aec07b
EZ
1039 (fset 'hexl-C-c-prefix (copy-keymap mode-specific-map))
1040 (define-key hexl-mode-map "\C-c" 'hexl-C-c-prefix)
ae2d451b
RS
1041 (define-key hexl-mode-map "\C-c\C-c" 'hexl-mode-exit)
1042
02aec07b
EZ
1043 (fset 'hexl-C-x-prefix (copy-keymap 'Control-X-prefix))
1044 (define-key hexl-mode-map "\C-x" 'hexl-C-x-prefix)
ae2d451b
RS
1045 (define-key hexl-mode-map "\C-x[" 'hexl-beginning-of-1k-page)
1046 (define-key hexl-mode-map "\C-x]" 'hexl-end-of-1k-page)
1047 (define-key hexl-mode-map "\C-x\C-p" 'undefined)
1048 (define-key hexl-mode-map "\C-x\C-s" 'hexl-save-buffer)
1049 (define-key hexl-mode-map "\C-x\C-t" 'undefined))
a2535589 1050
19e31f7c
RS
1051(provide 'hexl)
1052
ab5796a9 1053;;; arch-tag: d5a7aa8a-9bce-480b-bcff-6c4c7ca5ea4a
1a06eabd 1054;;; hexl.el ends here