(menu-bar-options-menu): Delete "Syntax
[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
TTN
3;; Copyright (C) 1989, 1994, 1998, 2001, 2002, 2003, 2004,
4;; 2005 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
41;; ASCII region of the screen (if your emacs supports this) instead of
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 ""
a2535589 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
172Movement is as simple as movement in a normal emacs text buffer. Most
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
RS
231 (hexlify-buffer)
232 (set-buffer-modified-p modified))
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)
303 (if (> (length string) 80)
304 (regexp-quote string)
305 (mapconcat 'string string "\\(?:\n\\(?:[:a-f0-9]+ \\)+ \\)?"))
306 bound noerror count))
307 (let ((isearch-search-fun-function nil))
308 (isearch-search-fun))))
309
c3de2bf0 310(defun hexl-after-revert-hook ()
059c2e18 311 (setq hexl-max-address (1- (buffer-size)))
c3de2bf0
RS
312 (hexlify-buffer)
313 (set-buffer-modified-p nil))
314
ac2e902d
JB
315(defvar hexl-in-save-buffer nil)
316
a2535589
JA
317(defun hexl-save-buffer ()
318 "Save a hexl format buffer as binary in visited file if modified."
319 (interactive)
ac2e902d
JB
320 (if hexl-in-save-buffer nil
321 (set-buffer-modified-p (if (buffer-modified-p)
322 (save-excursion
323 (let ((buf (generate-new-buffer " hexl"))
324 (name (buffer-name))
325 (file-name (buffer-file-name))
326 (start (point-min))
327 (end (point-max))
328 modified)
329 (set-buffer buf)
330 (insert-buffer-substring name start end)
331 (set-buffer name)
332 (dehexlify-buffer)
333 ;; Prevent infinite recursion.
338992a5 334 (let ((hexl-in-save-buffer t))
ac2e902d
JB
335 (save-buffer))
336 (setq modified (buffer-modified-p))
337 (delete-region (point-min) (point-max))
338 (insert-buffer-substring buf start end)
339 (kill-buffer buf)
340 modified))
341 (message "(No changes need to be saved)")
342 nil))
343 ;; Return t to indicate we have saved t
344 t))
a2535589 345
31c75fa7 346;;;###autoload
a2535589
JA
347(defun hexl-find-file (filename)
348 "Edit file FILENAME in hexl-mode.
a2535589 349Switch to a buffer visiting file FILENAME, creating one in none exists."
e49a45ad
MB
350 (interactive
351 (list
352 (let ((completion-ignored-extensions nil))
353 (read-file-name "Filename: " nil nil 'ret-must-match))))
3db6aff6 354 ;; Ignore the user's setting of default-major-mode.
45e8e6e7 355 (let ((default-major-mode 'fundamental-mode))
3db6aff6 356 (find-file-literally filename))
a2535589
JA
357 (if (not (eq major-mode 'hexl-mode))
358 (hexl-mode)))
359
360(defun hexl-mode-exit (&optional arg)
31c75fa7 361 "Exit Hexl mode, returning to previous mode.
a2535589
JA
362With arg, don't unhexlify buffer."
363 (interactive "p")
364 (if (or (eq arg 1) (not arg))
365 (let ((modified (buffer-modified-p))
900014dd 366 (inhibit-read-only t)
a2535589 367 (original-point (1+ (hexl-current-address))))
a2535589 368 (dehexlify-buffer)
87b3b78a 369 (remove-hook 'write-contents-functions 'hexl-save-buffer t)
a2535589 370 (set-buffer-modified-p modified)
7851eb98
EZ
371 (goto-char original-point)
372 ;; Maybe adjust point for the removed CR characters.
373 (when (eq (coding-system-eol-type buffer-file-coding-system) 1)
374 (setq original-point (- original-point
375 (count-lines (point-min) (point))))
376 (or (bobp) (setq original-point (1+ original-point))))
a2535589 377 (goto-char original-point)))
0e4889b2
RS
378
379 (remove-hook 'after-revert-hook 'hexl-after-revert-hook t)
380 (remove-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer t)
8e7df2e6
SE
381 (remove-hook 'post-command-hook 'hexl-follow-ascii-find t)
382 (setq hexl-ascii-overlay nil)
0e4889b2 383
b27ce24f
RS
384 (if (and (boundp 'ruler-mode) ruler-mode (not hexl-mode-old-ruler-mode))
385 (ruler-mode 0))
386 (if (and (boundp 'hl-line-mode) hl-line-mode (not hexl-mode-old-hl-line-mode))
387 (hl-line-mode 0))
0e4889b2 388 (setq require-final-newline hexl-mode-old-require-final-newline)
a2535589 389 (setq mode-name hexl-mode-old-mode-name)
87b3b78a 390 (setq isearch-search-fun-function hexl-mode-old-isearch-search-fun-function)
a2535589 391 (use-local-map hexl-mode-old-local-map)
0e4889b2 392 (set-syntax-table hexl-mode-old-syntax-table)
639b8e4d 393 (setq font-lock-defaults hexl-mode-old-font-lock-keywords)
a2535589 394 (setq major-mode hexl-mode-old-major-mode)
8eeac2ce
RS
395 (force-mode-line-update))
396
397(defun hexl-maybe-dehexlify-buffer ()
398 "Convert a hexl format buffer to binary.
399Ask the user for confirmation."
400 (if (y-or-n-p "Convert contents back to binary format? ")
401 (let ((modified (buffer-modified-p))
402 (inhibit-read-only t)
403 (original-point (1+ (hexl-current-address))))
404 (dehexlify-buffer)
87b3b78a 405 (remove-hook 'write-contents-functions 'hexl-save-buffer t)
8eeac2ce
RS
406 (set-buffer-modified-p modified)
407 (goto-char original-point))))
a2535589 408
6bbb008e 409(defun hexl-current-address (&optional validate)
a2535589
JA
410 "Return current hexl-address."
411 (interactive)
87b3b78a 412 (let ((current-column (- (% (- (point) (point-min) -1) 68) 11))
a2535589 413 (hexl-address 0))
6bbb008e
RS
414 (if (< current-column 0)
415 (if validate
416 (error "Point is not on a character in the file")
417 (setq current-column 0)))
418 (setq hexl-address
87b3b78a 419 (+ (* (/ (- (point) (point-min) -1) 68) 16)
6bbb008e
RS
420 (if (>= current-column 41)
421 (- current-column 41)
422 (/ (- current-column (/ current-column 5)) 2))))
48f56596 423 (when (interactive-p)
01ff9136 424 (message "Current address is %d/0x%08x" hexl-address hexl-address))
a2535589
JA
425 hexl-address))
426
01ff9136
MY
427(defun hexl-print-current-point-info ()
428 "Return current hexl-address in string.
12d96c20 429This function is intended to be used as eldoc callback."
01ff9136
MY
430 (let ((addr (hexl-current-address)))
431 (format "Current address is %d/0x%08x" addr addr)))
432
a2535589 433(defun hexl-address-to-marker (address)
059c2e18 434 "Return buffer position for ADDRESS."
a2535589 435 (interactive "nAddress: ")
87b3b78a 436 (+ (* (/ address 16) 68) 10 (point-min) (/ (* (% address 16) 5) 2)))
a2535589
JA
437
438(defun hexl-goto-address (address)
439 "Goto hexl-mode (decimal) address ADDRESS.
a2535589
JA
440Signal error if ADDRESS out of range."
441 (interactive "nAddress: ")
442 (if (or (< address 0) (> address hexl-max-address))
55391f5e 443 (error "Out of hexl region"))
a2535589
JA
444 (goto-char (hexl-address-to-marker address)))
445
446(defun hexl-goto-hex-address (hex-address)
4c8c7ae9 447 "Go to hexl-mode address (hex string) HEX-ADDRESS.
a2535589
JA
448Signal error if HEX-ADDRESS is out of range."
449 (interactive "sHex Address: ")
450 (hexl-goto-address (hexl-hex-string-to-integer hex-address)))
451
452(defun hexl-hex-string-to-integer (hex-string)
453 "Return decimal integer for HEX-STRING."
454 (interactive "sHex number: ")
455 (let ((hex-num 0))
456 (while (not (equal hex-string ""))
457 (setq hex-num (+ (* hex-num 16)
458 (hexl-hex-char-to-integer (string-to-char hex-string))))
459 (setq hex-string (substring hex-string 1)))
460 hex-num))
461
462(defun hexl-octal-string-to-integer (octal-string)
463 "Return decimal integer for OCTAL-STRING."
464 (interactive "sOctal number: ")
465 (let ((oct-num 0))
466 (while (not (equal octal-string ""))
467 (setq oct-num (+ (* oct-num 8)
468 (hexl-oct-char-to-integer
469 (string-to-char octal-string))))
470 (setq octal-string (substring octal-string 1)))
471 oct-num))
472
473;; move point functions
474
475(defun hexl-backward-char (arg)
476 "Move to left ARG bytes (right if ARG negative) in hexl-mode."
477 (interactive "p")
478 (hexl-goto-address (- (hexl-current-address) arg)))
479
480(defun hexl-forward-char (arg)
481 "Move right ARG bytes (left if ARG negative) in hexl-mode."
482 (interactive "p")
483 (hexl-goto-address (+ (hexl-current-address) arg)))
484
485(defun hexl-backward-short (arg)
486 "Move to left ARG shorts (right if ARG negative) in hexl-mode."
487 (interactive "p")
488 (hexl-goto-address (let ((address (hexl-current-address)))
489 (if (< arg 0)
490 (progn
491 (setq arg (- arg))
492 (while (> arg 0)
493 (if (not (equal address (logior address 3)))
494 (if (> address hexl-max-address)
495 (progn
496 (message "End of buffer.")
497 (setq address hexl-max-address))
498 (setq address (logior address 3)))
499 (if (> address hexl-max-address)
500 (progn
501 (message "End of buffer.")
502 (setq address hexl-max-address))
503 (setq address (+ address 4))))
504 (setq arg (1- arg)))
505 (if (> address hexl-max-address)
506 (progn
507 (message "End of buffer.")
508 (setq address hexl-max-address))
509 (setq address (logior address 3))))
510 (while (> arg 0)
511 (if (not (equal address (logand address -4)))
512 (setq address (logand address -4))
513 (if (not (equal address 0))
514 (setq address (- address 4))
515 (message "Beginning of buffer.")))
516 (setq arg (1- arg))))
517 address)))
518
519(defun hexl-forward-short (arg)
520 "Move right ARG shorts (left if ARG negative) in hexl-mode."
521 (interactive "p")
522 (hexl-backward-short (- arg)))
523
524(defun hexl-backward-word (arg)
525 "Move to left ARG words (right if ARG negative) in hexl-mode."
526 (interactive "p")
527 (hexl-goto-address (let ((address (hexl-current-address)))
528 (if (< arg 0)
529 (progn
530 (setq arg (- arg))
531 (while (> arg 0)
532 (if (not (equal address (logior address 7)))
533 (if (> address hexl-max-address)
534 (progn
535 (message "End of buffer.")
536 (setq address hexl-max-address))
537 (setq address (logior address 7)))
538 (if (> address hexl-max-address)
539 (progn
540 (message "End of buffer.")
541 (setq address hexl-max-address))
542 (setq address (+ address 8))))
543 (setq arg (1- arg)))
544 (if (> address hexl-max-address)
545 (progn
546 (message "End of buffer.")
547 (setq address hexl-max-address))
548 (setq address (logior address 7))))
549 (while (> arg 0)
550 (if (not (equal address (logand address -8)))
551 (setq address (logand address -8))
552 (if (not (equal address 0))
553 (setq address (- address 8))
554 (message "Beginning of buffer.")))
555 (setq arg (1- arg))))
556 address)))
557
558(defun hexl-forward-word (arg)
559 "Move right ARG words (left if ARG negative) in hexl-mode."
560 (interactive "p")
561 (hexl-backward-word (- arg)))
562
563(defun hexl-previous-line (arg)
4c8c7ae9
JB
564 "Move vertically up ARG lines [16 bytes] (down if ARG negative) in hexl-mode.
565If there is byte at the target address move to the last byte in that line."
a2535589
JA
566 (interactive "p")
567 (hexl-next-line (- arg)))
568
569(defun hexl-next-line (arg)
4c8c7ae9
JB
570 "Move vertically down ARG lines [16 bytes] (up if ARG negative) in hexl-mode.
571If there is no byte at the target address move to the last byte in that line."
a2535589 572 (interactive "p")
e8a57935 573 (hexl-goto-address (let ((address (+ (hexl-current-address) (* arg 16))))
a2535589
JA
574 (if (and (< arg 0) (< address 0))
575 (progn (message "Out of hexl region.")
576 (setq address
577 (% (hexl-current-address) 16)))
578 (if (and (> address hexl-max-address)
579 (< (% hexl-max-address 16) (% address 16)))
580 (setq address hexl-max-address)
581 (if (> address hexl-max-address)
582 (progn (message "Out of hexl region.")
583 (setq
584 address
585 (+ (logand hexl-max-address -16)
586 (% (hexl-current-address) 16)))))))
587 address)))
588
589(defun hexl-beginning-of-buffer (arg)
4c8c7ae9
JB
590 "Move to the beginning of the hexl buffer.
591Leaves `hexl-mark' at previous position.
592With prefix arg N, puts point N bytes of the way from the true beginning."
a2535589
JA
593 (interactive "p")
594 (push-mark (point))
595 (hexl-goto-address (+ 0 (1- arg))))
596
597(defun hexl-end-of-buffer (arg)
4c8c7ae9 598 "Go to `hexl-max-address' minus ARG."
a2535589
JA
599 (interactive "p")
600 (push-mark (point))
601 (hexl-goto-address (- hexl-max-address (1- arg))))
602
603(defun hexl-beginning-of-line ()
604 "Goto beginning of line in hexl mode."
605 (interactive)
606 (goto-char (+ (* (/ (point) 68) 68) 11)))
607
608(defun hexl-end-of-line ()
609 "Goto end of line in hexl mode."
610 (interactive)
611 (hexl-goto-address (let ((address (logior (hexl-current-address) 15)))
612 (if (> address hexl-max-address)
613 (setq address hexl-max-address))
614 address)))
615
616(defun hexl-scroll-down (arg)
617 "Scroll hexl buffer window upward ARG lines; or near full window if no ARG."
618 (interactive "P")
619 (if (null arg)
620 (setq arg (1- (window-height)))
621 (setq arg (prefix-numeric-value arg)))
622 (hexl-scroll-up (- arg)))
623
624(defun hexl-scroll-up (arg)
d565f6aa
EZ
625 "Scroll hexl buffer window upward ARG lines; or near full window if no ARG.
626If there's no byte at the target address, move to the first or last line."
a2535589
JA
627 (interactive "P")
628 (if (null arg)
629 (setq arg (1- (window-height)))
630 (setq arg (prefix-numeric-value arg)))
d565f6aa
EZ
631 (let* ((movement (* arg 16))
632 (address (hexl-current-address))
633 (dest (+ address movement)))
634 (cond
635 ;; If possible, try to stay at the same offset from the beginning
636 ;; of the 16-byte group, even if we move to the first or last
637 ;; group.
638 ((and (> dest hexl-max-address)
639 (>= (% hexl-max-address 16) (% address 16)))
640 (setq dest (+ (logand hexl-max-address -16) (% address 16))))
641 ((> dest hexl-max-address)
642 (setq dest hexl-max-address))
643 ((< dest 0)
644 (setq dest (% address 16))))
645 (if (/= dest (+ address movement))
646 (message "Out of hexl region."))
647 (hexl-goto-address dest)
648 (recenter 0)))
a2535589
JA
649
650(defun hexl-beginning-of-1k-page ()
65e5f4bc 651 "Go to beginning of 1k boundary."
a2535589
JA
652 (interactive)
653 (hexl-goto-address (logand (hexl-current-address) -1024)))
654
655(defun hexl-end-of-1k-page ()
65e5f4bc 656 "Go to end of 1k boundary."
a2535589
JA
657 (interactive)
658 (hexl-goto-address (let ((address (logior (hexl-current-address) 1023)))
659 (if (> address hexl-max-address)
660 (setq address hexl-max-address))
661 address)))
662
663(defun hexl-beginning-of-512b-page ()
65e5f4bc 664 "Go to beginning of 512 byte boundary."
a2535589
JA
665 (interactive)
666 (hexl-goto-address (logand (hexl-current-address) -512)))
667
668(defun hexl-end-of-512b-page ()
65e5f4bc 669 "Go to end of 512 byte boundary."
a2535589
JA
670 (interactive)
671 (hexl-goto-address (let ((address (logior (hexl-current-address) 511)))
672 (if (> address hexl-max-address)
673 (setq address hexl-max-address))
674 address)))
675
676(defun hexl-quoted-insert (arg)
677 "Read next input character and insert it.
02aec07b
EZ
678Useful for inserting control characters and non-ASCII characters given their
679numerical code.
680You may also type octal digits, to insert a character with that code."
a2535589 681 (interactive "p")
02aec07b 682 (hexl-insert-multibyte-char (read-quoted-char) arg))
a2535589
JA
683
684;00000000: 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789ABCDEF
685
f4e3d4eb 686;;;###autoload
a2535589 687(defun hexlify-buffer ()
aa3757b8
RS
688 "Convert a binary buffer to hexl format.
689This discards the buffer's undo information."
a2535589 690 (interactive)
aa3757b8
RS
691 (and buffer-undo-list
692 (or (y-or-n-p "Converting to hexl format discards undo info; ok? ")
693 (error "Aborted")))
694 (setq buffer-undo-list nil)
a749e5e5
EZ
695 ;; Don't decode text in the ASCII part of `hexl' program output.
696 (let ((coding-system-for-read 'raw-text)
0716afa2 697 (coding-system-for-write buffer-file-coding-system)
aa3757b8 698 (buffer-undo-list t))
b8c49a19
SM
699 (apply 'call-process-region (point-min) (point-max)
700 (expand-file-name hexl-program exec-directory)
701 t t nil (split-string hexl-options))
059c2e18
PR
702 (if (> (point) (hexl-address-to-marker hexl-max-address))
703 (hexl-goto-address hexl-max-address))))
a2535589
JA
704
705(defun dehexlify-buffer ()
aa3757b8
RS
706 "Convert a hexl format buffer to binary.
707This discards the buffer's undo information."
a2535589 708 (interactive)
aa3757b8
RS
709 (and buffer-undo-list
710 (or (y-or-n-p "Converting from hexl format discards undo info; ok? ")
711 (error "Aborted")))
712 (setq buffer-undo-list nil)
a749e5e5 713 (let ((coding-system-for-write 'raw-text)
0716afa2 714 (coding-system-for-read buffer-file-coding-system)
aa3757b8 715 (buffer-undo-list t))
b8c49a19
SM
716 (apply 'call-process-region (point-min) (point-max)
717 (expand-file-name hexl-program exec-directory)
718 t t nil "-de" (split-string hexl-options))))
a2535589
JA
719
720(defun hexl-char-after-point ()
721 "Return char for ASCII hex digits at point."
686fc9ab
RS
722 (hexl-htoi (char-after (point))
723 (char-after (1+ (point)))))
a2535589
JA
724
725(defun hexl-htoi (lh rh)
726 "Hex (char) LH (char) RH to integer."
727 (+ (* (hexl-hex-char-to-integer lh) 16)
728 (hexl-hex-char-to-integer rh)))
729
730(defun hexl-hex-char-to-integer (character)
731 "Take a char and return its value as if it was a hex digit."
732 (if (and (>= character ?0) (<= character ?9))
733 (- character ?0)
734 (let ((ch (logior character 32)))
735 (if (and (>= ch ?a) (<= ch ?f))
736 (- ch (- ?a 10))
19e31f7c 737 (error "Invalid hex digit `%c'" ch)))))
a2535589
JA
738
739(defun hexl-oct-char-to-integer (character)
740 "Take a char and return its value as if it was a octal digit."
741 (if (and (>= character ?0) (<= character ?7))
742 (- character ?0)
19e31f7c 743 (error "Invalid octal digit `%c'" character)))
a2535589
JA
744
745(defun hexl-printable-character (ch)
746 "Return a displayable string for character CH."
747 (format "%c" (if hexl-iso
748 (if (or (< ch 32) (and (>= ch 127) (< ch 160)))
749 46
750 ch)
751 (if (or (< ch 32) (>= ch 127))
752 46
753 ch))))
754
02aec07b
EZ
755(defun hexl-insert-multibyte-char (ch num)
756 "Insert a possibly multibyte character CH NUM times.
757
758Non-ASCII characters are first encoded with `buffer-file-coding-system',
759and their encoded form is inserted byte by byte."
760 (let ((charset (char-charset ch))
761 (coding (if (or (null buffer-file-coding-system)
762 ;; coding-system-type equals t means undecided.
763 (eq (coding-system-type buffer-file-coding-system) t))
764 default-buffer-file-coding-system
765 buffer-file-coding-system)))
766 (cond ((and (> ch 0) (< ch 256))
767 (hexl-insert-char ch num))
768 ((eq charset 'unknown)
769 (error
165b4283 770 "0x%x -- invalid character code; use \\[hexl-insert-hex-string]"
02aec07b
EZ
771 ch))
772 (t
773 (let ((encoded (encode-coding-char ch coding))
774 (internal (string-as-unibyte (char-to-string ch)))
775 internal-hex)
776 ;; If encode-coding-char returns nil, it means our character
777 ;; cannot be safely encoded with buffer-file-coding-system.
778 ;; In that case, we offer to insert the internal representation
779 ;; of that character, byte by byte.
780 (when (null encoded)
781 (setq internal-hex
782 (mapconcat (function (lambda (c) (format "%x" c)))
783 internal " "))
784 (if (yes-or-no-p
785 (format
786 "Insert char 0x%x's internal representation \"%s\"? "
787 ch internal-hex))
788 (setq encoded internal)
789 (error
165b4283 790 "Can't encode `0x%x' with this buffer's coding system; try \\[hexl-insert-hex-string]"
02aec07b
EZ
791 ch)))
792 (while (> num 0)
793 (mapc
794 (function (lambda (c) (hexl-insert-char c 1))) encoded)
795 (setq num (1- num))))))))
796
a2535589 797(defun hexl-self-insert-command (arg)
02aec07b
EZ
798 "Insert this character.
799Interactively, with a numeric argument, insert this character that many times.
800
801Non-ASCII characters are first encoded with `buffer-file-coding-system',
802and their encoded form is inserted byte by byte."
a2535589 803 (interactive "p")
02aec07b 804 (hexl-insert-multibyte-char last-command-char arg))
a2535589
JA
805
806(defun hexl-insert-char (ch num)
02aec07b
EZ
807 "Insert the character CH NUM times in a hexl buffer.
808
809CH must be a unibyte character whose value is between 0 and 255."
810 (if (or (< ch 0) (> ch 255))
45ad49ba 811 (error "Invalid character 0x%x -- must be in the range [0..255]" ch))
6bbb008e 812 (let ((address (hexl-current-address t)))
a2535589 813 (while (> num 0)
6bbb008e
RS
814 (let ((hex-position
815 (+ (* (/ address 16) 68)
87b3b78a 816 10 (point-min)
6bbb008e
RS
817 (* 2 (% address 16))
818 (/ (% address 16) 2)))
819 (ascii-position
87b3b78a 820 (+ (* (/ address 16) 68) 51 (point-min) (% address 16)))
6bbb008e
RS
821 at-ascii-position)
822 (if (= (point) ascii-position)
823 (setq at-ascii-position t))
824 (goto-char hex-position)
825 (delete-char 2)
826 (insert (format "%02x" ch))
827 (goto-char ascii-position)
828 (delete-char 1)
829 (insert (hexl-printable-character ch))
830 (or (eq address hexl-max-address)
831 (setq address (1+ address)))
832 (hexl-goto-address address)
833 (if at-ascii-position
834 (progn
835 (beginning-of-line)
836 (forward-char 51)
837 (forward-char (% address 16)))))
a2535589
JA
838 (setq num (1- num)))))
839
840;; hex conversion
841
842(defun hexl-insert-hex-char (arg)
02aec07b 843 "Insert a character given by its hexadecimal code ARG times at point."
a2535589
JA
844 (interactive "p")
845 (let ((num (hexl-hex-string-to-integer (read-string "Hex number: "))))
02aec07b 846 (if (< num 0)
19e31f7c 847 (error "Hex number out of range")
02aec07b 848 (hexl-insert-multibyte-char num arg))))
a2535589 849
9f6bff44
GM
850(defun hexl-insert-hex-string (str arg)
851 "Insert hexadecimal string STR at point ARG times.
852Embedded whitespace, dashes, and periods in the string are ignored."
853 (interactive "sHex string: \np")
854 (setq str (replace-regexp-in-string "[- \t.]" "" str))
855 (let ((chars '()))
856 (let ((len (length str))
857 (idx 0))
858 (if (eq (logand len 1) 1)
859 (let ((num (hexl-hex-string-to-integer (substring str 0 1))))
860 (setq chars (cons num chars))
861 (setq idx 1)))
862 (while (< idx len)
863 (let* ((nidx (+ idx 2))
864 (num (hexl-hex-string-to-integer (substring str idx nidx))))
865 (setq chars (cons num chars))
866 (setq idx nidx))))
867 (setq chars (nreverse chars))
868 (while (> arg 0)
869 (let ((chars chars))
870 (while chars
871 (hexl-insert-char (car chars) 1)
872 (setq chars (cdr chars))))
873 (setq arg (- arg 1)))))
874
a2535589 875(defun hexl-insert-decimal-char (arg)
02aec07b 876 "Insert a character given by its decimal code ARG times at point."
a2535589 877 (interactive "p")
027a4b6b 878 (let ((num (string-to-number (read-string "Decimal Number: "))))
02aec07b 879 (if (< num 0)
19e31f7c 880 (error "Decimal number out of range")
02aec07b 881 (hexl-insert-multibyte-char num arg))))
a2535589
JA
882
883(defun hexl-insert-octal-char (arg)
02aec07b 884 "Insert a character given by its octal code ARG times at point."
a2535589
JA
885 (interactive "p")
886 (let ((num (hexl-octal-string-to-integer (read-string "Octal Number: "))))
02aec07b 887 (if (< num 0)
19e31f7c 888 (error "Decimal number out of range")
02aec07b 889 (hexl-insert-multibyte-char num arg))))
a2535589 890
db6c5b92
SE
891(defun hexl-follow-ascii (&optional arg)
892 "Toggle following ASCII in Hexl buffers.
893With prefix ARG, turn on following if and only if ARG is positive.
894When following is enabled, the ASCII character corresponding to the
895element under the point is highlighted.
896Customize the variable `hexl-follow-ascii' to disable this feature."
897 (interactive "P")
71296446 898 (let ((on-p (if arg
db6c5b92
SE
899 (> (prefix-numeric-value arg) 0)
900 (not hexl-ascii-overlay))))
901
db6c5b92
SE
902 (if on-p
903 ;; turn it on
904 (if (not hexl-ascii-overlay)
905 (progn
906 (setq hexl-ascii-overlay (make-overlay 1 1)
907 hexl-follow-ascii t)
908 (overlay-put hexl-ascii-overlay 'face 'highlight)
909 (add-hook 'post-command-hook 'hexl-follow-ascii-find nil t)))
910 ;; turn it off
911 (if hexl-ascii-overlay
912 (progn
913 (delete-overlay hexl-ascii-overlay)
914 (setq hexl-ascii-overlay nil
915 hexl-follow-ascii nil)
916 (remove-hook 'post-command-hook 'hexl-follow-ascii-find t)
917 )))))
918
9fd76d04
MY
919(defun hexl-activate-ruler ()
920 "Activate `ruler-mode'"
921 (require 'ruler-mode)
625c1523 922 (set (make-local-variable 'ruler-mode-ruler-function)
9fd76d04
MY
923 'hexl-mode-ruler)
924 (ruler-mode 1))
925
926(defun hexl-follow-line ()
927 "Activate `hl-line-mode'"
928 (require 'frame)
9fd76d04 929 (require 'hl-line)
9bbe3927
RS
930 (with-no-warnings
931 (set (make-local-variable 'hl-line-range-function)
932 'hexl-highlight-line-range)
625c1523 933 (set (make-local-variable 'hl-line-face)
9bbe3927 934 'highlight))
9fd76d04
MY
935 (hl-line-mode 1))
936
937(defun hexl-highlight-line-range ()
2d77d354 938 "Return the range of address region for the point.
9fd76d04
MY
939This function is assumed to be used as call back function for `hl-line-mode'."
940 (cons
941 (line-beginning-position)
942 ;; 9 stands for (length "87654321:")
943 (+ (line-beginning-position) 9)))
944
db6c5b92
SE
945(defun hexl-follow-ascii-find ()
946 "Find and highlight the ASCII element corresponding to current point."
d565f6aa 947 (let ((pos (+ 51
db6c5b92
SE
948 (- (point) (current-column))
949 (mod (hexl-current-address) 16))))
950 (move-overlay hexl-ascii-overlay pos (1+ pos))
951 ))
952
9fd76d04
MY
953(defun hexl-mode-ruler ()
954 "Return a string ruler for hexl mode."
955 (let* ((highlight (mod (hexl-current-address) 16))
4c4ac516
KS
956 (s " 87654321 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789abcdef")
957 (pos 0))
9fd76d04
MY
958 (set-text-properties 0 (length s) nil s)
959 ;; Turn spaces in the header into stretch specs so they work
960 ;; regardless of the header-line face.
961 (while (string-match "[ \t]+" s pos)
962 (setq pos (match-end 0))
963 (put-text-property (match-beginning 0) pos 'display
964 ;; Assume fixed-size chars
4c4ac516 965 `(space :align-to ,(1- pos))
9fd76d04
MY
966 s))
967 ;; Highlight the current column.
4c4ac516
KS
968 (put-text-property (+ 11 (/ (* 5 highlight) 2))
969 (+ 13 (/ (* 5 highlight) 2))
9fd76d04
MY
970 'face 'highlight s)
971 ;; Highlight the current ascii column
4c4ac516 972 (put-text-property (+ 13 39 highlight) (+ 13 40 highlight)
9fd76d04 973 'face 'highlight s)
4c4ac516 974 s))
9fd76d04 975
a2535589
JA
976;; startup stuff.
977
978(if hexl-mode-map
979 nil
4b7dd7e2 980 (setq hexl-mode-map (make-keymap))
02aec07b
EZ
981 ;; Make all self-inserting keys go through hexl-self-insert-command,
982 ;; because we need to convert them to unibyte characters before
983 ;; inserting them into the buffer.
340c4d85 984 (define-key hexl-mode-map [remap self-insert-command] 'hexl-self-insert-command)
ae2d451b 985
d9c8518d 986 (define-key hexl-mode-map "\C-m" 'hexl-self-insert-command)
ae2d451b
RS
987 (define-key hexl-mode-map [left] 'hexl-backward-char)
988 (define-key hexl-mode-map [right] 'hexl-forward-char)
989 (define-key hexl-mode-map [up] 'hexl-previous-line)
990 (define-key hexl-mode-map [down] 'hexl-next-line)
991 (define-key hexl-mode-map [M-left] 'hexl-backward-short)
480c8cd3 992 (define-key hexl-mode-map [?\e left] 'hexl-backward-short)
ae2d451b 993 (define-key hexl-mode-map [M-right] 'hexl-forward-short)
480c8cd3 994 (define-key hexl-mode-map [?\e right] 'hexl-forward-short)
ae2d451b
RS
995 (define-key hexl-mode-map [next] 'hexl-scroll-up)
996 (define-key hexl-mode-map [prior] 'hexl-scroll-down)
d565f6aa
EZ
997 (define-key hexl-mode-map [home] 'hexl-beginning-of-line)
998 (define-key hexl-mode-map [end] 'hexl-end-of-line)
999 (define-key hexl-mode-map [C-home] 'hexl-beginning-of-buffer)
1000 (define-key hexl-mode-map [C-end] 'hexl-end-of-buffer)
ae2d451b
RS
1001 (define-key hexl-mode-map [deletechar] 'undefined)
1002 (define-key hexl-mode-map [deleteline] 'undefined)
1003 (define-key hexl-mode-map [insertline] 'undefined)
1004 (define-key hexl-mode-map [S-delete] 'undefined)
1005 (define-key hexl-mode-map "\177" 'undefined)
1006
1007 (define-key hexl-mode-map "\C-a" 'hexl-beginning-of-line)
1008 (define-key hexl-mode-map "\C-b" 'hexl-backward-char)
1009 (define-key hexl-mode-map "\C-d" 'undefined)
1010 (define-key hexl-mode-map "\C-e" 'hexl-end-of-line)
1011 (define-key hexl-mode-map "\C-f" 'hexl-forward-char)
1012
625c1523
JB
1013 (if (not (memq (key-binding (char-to-string help-char))
1014 '(help-command ehelp-command)))
ae2d451b
RS
1015 (define-key hexl-mode-map (char-to-string help-char) 'undefined))
1016
ae2d451b 1017 (define-key hexl-mode-map "\C-k" 'undefined)
ae2d451b
RS
1018 (define-key hexl-mode-map "\C-n" 'hexl-next-line)
1019 (define-key hexl-mode-map "\C-o" 'undefined)
1020 (define-key hexl-mode-map "\C-p" 'hexl-previous-line)
1021 (define-key hexl-mode-map "\C-q" 'hexl-quoted-insert)
1022 (define-key hexl-mode-map "\C-t" 'undefined)
1023 (define-key hexl-mode-map "\C-v" 'hexl-scroll-up)
1024 (define-key hexl-mode-map "\C-w" 'undefined)
1025 (define-key hexl-mode-map "\C-y" 'undefined)
1026
02aec07b
EZ
1027 (fset 'hexl-ESC-prefix (copy-keymap 'ESC-prefix))
1028 (define-key hexl-mode-map "\e" 'hexl-ESC-prefix)
ae2d451b
RS
1029 (define-key hexl-mode-map "\e\C-a" 'hexl-beginning-of-512b-page)
1030 (define-key hexl-mode-map "\e\C-b" 'hexl-backward-short)
ae2d451b
RS
1031 (define-key hexl-mode-map "\e\C-d" 'hexl-insert-decimal-char)
1032 (define-key hexl-mode-map "\e\C-e" 'hexl-end-of-512b-page)
1033 (define-key hexl-mode-map "\e\C-f" 'hexl-forward-short)
ae2d451b
RS
1034 (define-key hexl-mode-map "\e\C-i" 'undefined)
1035 (define-key hexl-mode-map "\e\C-j" 'undefined)
1036 (define-key hexl-mode-map "\e\C-k" 'undefined)
ae2d451b 1037 (define-key hexl-mode-map "\e\C-o" 'hexl-insert-octal-char)
ae2d451b 1038 (define-key hexl-mode-map "\e\C-q" 'undefined)
ae2d451b 1039 (define-key hexl-mode-map "\e\C-t" 'undefined)
ae2d451b 1040 (define-key hexl-mode-map "\e\C-x" 'hexl-insert-hex-char)
ae2d451b
RS
1041 (define-key hexl-mode-map "\eb" 'hexl-backward-word)
1042 (define-key hexl-mode-map "\ec" 'undefined)
1043 (define-key hexl-mode-map "\ed" 'undefined)
ae2d451b
RS
1044 (define-key hexl-mode-map "\ef" 'hexl-forward-word)
1045 (define-key hexl-mode-map "\eg" 'hexl-goto-hex-address)
ae2d451b
RS
1046 (define-key hexl-mode-map "\ei" 'undefined)
1047 (define-key hexl-mode-map "\ej" 'hexl-goto-address)
1048 (define-key hexl-mode-map "\ek" 'undefined)
1049 (define-key hexl-mode-map "\el" 'undefined)
ae2d451b 1050 (define-key hexl-mode-map "\eq" 'undefined)
ae2d451b
RS
1051 (define-key hexl-mode-map "\es" 'undefined)
1052 (define-key hexl-mode-map "\et" 'undefined)
1053 (define-key hexl-mode-map "\eu" 'undefined)
1054 (define-key hexl-mode-map "\ev" 'hexl-scroll-down)
1055 (define-key hexl-mode-map "\ey" 'undefined)
1056 (define-key hexl-mode-map "\ez" 'undefined)
1057 (define-key hexl-mode-map "\e<" 'hexl-beginning-of-buffer)
1058 (define-key hexl-mode-map "\e>" 'hexl-end-of-buffer)
1059
02aec07b
EZ
1060 (fset 'hexl-C-c-prefix (copy-keymap mode-specific-map))
1061 (define-key hexl-mode-map "\C-c" 'hexl-C-c-prefix)
ae2d451b
RS
1062 (define-key hexl-mode-map "\C-c\C-c" 'hexl-mode-exit)
1063
02aec07b
EZ
1064 (fset 'hexl-C-x-prefix (copy-keymap 'Control-X-prefix))
1065 (define-key hexl-mode-map "\C-x" 'hexl-C-x-prefix)
ae2d451b
RS
1066 (define-key hexl-mode-map "\C-x[" 'hexl-beginning-of-1k-page)
1067 (define-key hexl-mode-map "\C-x]" 'hexl-end-of-1k-page)
1068 (define-key hexl-mode-map "\C-x\C-p" 'undefined)
1069 (define-key hexl-mode-map "\C-x\C-s" 'hexl-save-buffer)
1070 (define-key hexl-mode-map "\C-x\C-t" 'undefined))
a2535589 1071
19e31f7c
RS
1072(provide 'hexl)
1073
ab5796a9 1074;;; arch-tag: d5a7aa8a-9bce-480b-bcff-6c4c7ca5ea4a
1a06eabd 1075;;; hexl.el ends here