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