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