X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9f97e26d01003a17b861505d535c89ad73799b7e..9805f81dda38cd541ba8043f44e720e06adf6492:/lisp/hexl.el diff --git a/lisp/hexl.el b/lisp/hexl.el index e2078fceec..538d218e38 100644 --- a/lisp/hexl.el +++ b/lisp/hexl.el @@ -1,7 +1,6 @@ -;;; hexl.el --- edit a file in a hex dump format using the hexl filter +;;; hexl.el --- edit a file in a hex dump format using the hexl filter -*- lexical-binding: t -*- -;; Copyright (C) 1989, 1994, 1998, 2001, 2002, 2003, 2004, -;; 2005, 2006 Free Software Foundation, Inc. +;; Copyright (C) 1989, 1994, 1998, 2001-2012 Free Software Foundation, Inc. ;; Author: Keith Gabryelski ;; Maintainer: FSF @@ -9,10 +8,10 @@ ;; This file is part of GNU Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,9 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. +;; along with GNU Emacs. If not, see . ;;; Commentary: @@ -44,6 +41,7 @@ ;;; Code: (require 'eldoc) +(eval-when-compile (require 'cl)) ;; ;; vars here @@ -87,32 +85,121 @@ Quoting cannot be used, so the arguments cannot themselves contain spaces." (defface hexl-address-region '((t (:inherit header-line))) - "Face used in address are of hexl-mode buffer." + "Face used in address area of hexl-mode buffer." :group 'hexl) (defface hexl-ascii-region '((t (:inherit header-line))) - "Face used in ascii are of hexl-mode buffer." + "Face used in ascii area of hexl-mode buffer." :group 'hexl) (defvar hexl-max-address 0 "Maximum offset into hexl buffer.") -(defvar hexl-mode-map nil) - +(defvar hexl-mode-map + (let ((map (make-keymap))) + ;; Make all self-inserting keys go through hexl-self-insert-command, + ;; because we need to convert them to unibyte characters before + ;; inserting them into the buffer. + (define-key map [remap self-insert-command] 'hexl-self-insert-command) + + (define-key map "\C-m" 'hexl-self-insert-command) + (define-key map [left] 'hexl-backward-char) + (define-key map [right] 'hexl-forward-char) + (define-key map [up] 'hexl-previous-line) + (define-key map [down] 'hexl-next-line) + (define-key map [M-left] 'hexl-backward-short) + (define-key map [?\e left] 'hexl-backward-short) + (define-key map [M-right] 'hexl-forward-short) + (define-key map [?\e right] 'hexl-forward-short) + (define-key map [next] 'hexl-scroll-up) + (define-key map [prior] 'hexl-scroll-down) + (define-key map [home] 'hexl-beginning-of-line) + (define-key map [end] 'hexl-end-of-line) + (define-key map [C-home] 'hexl-beginning-of-buffer) + (define-key map [C-end] 'hexl-end-of-buffer) + (define-key map [deletechar] 'undefined) + (define-key map [deleteline] 'undefined) + (define-key map [insertline] 'undefined) + (define-key map [S-delete] 'undefined) + (define-key map "\177" 'undefined) + + (define-key map "\C-a" 'hexl-beginning-of-line) + (define-key map "\C-b" 'hexl-backward-char) + (define-key map "\C-d" 'undefined) + (define-key map "\C-e" 'hexl-end-of-line) + (define-key map "\C-f" 'hexl-forward-char) + + (if (not (memq (key-binding (char-to-string help-char)) + '(help-command ehelp-command))) + (define-key map (char-to-string help-char) 'undefined)) + + (define-key map "\C-k" 'undefined) + (define-key map "\C-n" 'hexl-next-line) + (define-key map "\C-o" 'undefined) + (define-key map "\C-p" 'hexl-previous-line) + (define-key map "\C-q" 'hexl-quoted-insert) + (define-key map "\C-t" 'undefined) + (define-key map "\C-v" 'hexl-scroll-up) + (define-key map "\C-w" 'undefined) + (define-key map "\C-y" 'undefined) + + (fset 'hexl-ESC-prefix (copy-keymap 'ESC-prefix)) + (define-key map "\e" 'hexl-ESC-prefix) + (define-key map "\e\C-a" 'hexl-beginning-of-512b-page) + (define-key map "\e\C-b" 'hexl-backward-short) + (define-key map "\e\C-d" 'hexl-insert-decimal-char) + (define-key map "\e\C-e" 'hexl-end-of-512b-page) + (define-key map "\e\C-f" 'hexl-forward-short) + (define-key map "\e\C-i" 'undefined) + (define-key map "\e\C-j" 'undefined) + (define-key map "\e\C-k" 'undefined) + (define-key map "\e\C-o" 'hexl-insert-octal-char) + (define-key map "\e\C-q" 'undefined) + (define-key map "\e\C-t" 'undefined) + (define-key map "\e\C-x" 'hexl-insert-hex-char) + (define-key map "\eb" 'hexl-backward-word) + (define-key map "\ec" 'undefined) + (define-key map "\ed" 'undefined) + (define-key map "\ef" 'hexl-forward-word) + (define-key map "\eg" 'hexl-goto-hex-address) + (define-key map "\ei" 'undefined) + (define-key map "\ej" 'hexl-goto-address) + (define-key map "\ek" 'undefined) + (define-key map "\el" 'undefined) + (define-key map "\eq" 'undefined) + (define-key map "\es" 'undefined) + (define-key map "\et" 'undefined) + (define-key map "\eu" 'undefined) + (define-key map "\ev" 'hexl-scroll-down) + (define-key map "\ey" 'undefined) + (define-key map "\ez" 'undefined) + (define-key map "\e<" 'hexl-beginning-of-buffer) + (define-key map "\e>" 'hexl-end-of-buffer) + + (fset 'hexl-C-c-prefix (copy-keymap mode-specific-map)) + (define-key map "\C-c" 'hexl-C-c-prefix) + (define-key map "\C-c\C-c" 'hexl-mode-exit) + + (fset 'hexl-C-x-prefix (copy-keymap 'Control-X-prefix)) + (define-key map "\C-x" 'hexl-C-x-prefix) + (define-key map "\C-x[" 'hexl-beginning-of-1k-page) + (define-key map "\C-x]" 'hexl-end-of-1k-page) + (define-key map "\C-x\C-p" 'undefined) + (define-key map "\C-x\C-s" 'hexl-save-buffer) + (define-key map "\C-x\C-t" 'undefined) + map)) + +;; Variable declarations for suppressing warnings from the byte-compiler. (defvar ruler-mode) (defvar ruler-mode-ruler-function) (defvar hl-line-mode) +(defvar hl-line-range-function) +(defvar hl-line-face) -(defvar hexl-mode-old-hl-line-mode) -(defvar hexl-mode-old-local-map) -(defvar hexl-mode-old-mode-name) -(defvar hexl-mode-old-major-mode) -(defvar hexl-mode-old-ruler-mode) -(defvar hexl-mode-old-isearch-search-fun-function) -(defvar hexl-mode-old-require-final-newline) -(defvar hexl-mode-old-syntax-table) -(defvar hexl-mode-old-font-lock-keywords) +;; Variables where the original values are stored to. +(defvar hexl-mode--old-var-vals ()) +(make-variable-buffer-local 'hexl-mode--old-var-vals) (defvar hexl-ascii-overlay nil "Overlay used to highlight ASCII element corresponding to current point.") @@ -129,6 +216,25 @@ Quoting cannot be used, so the arguments cannot themselves contain spaces." (put 'hexl-mode 'mode-class 'special) + +(defun hexl-mode--minor-mode-p (var) + (memq var '(ruler-mode hl-line-mode))) + +(defun hexl-mode--setq-local (var val) + ;; `var' can be either a symbol or a pair, in which case the `car' + ;; is the getter function and the `cdr' is the corresponding setter. + (unless (or (member var hexl-mode--old-var-vals) + (assoc var hexl-mode--old-var-vals)) + (push (if (or (consp var) (boundp var)) + (cons var + (if (consp var) (funcall (car var)) (symbol-value var))) + var) + hexl-mode--old-var-vals)) + (cond + ((consp var) (funcall (cdr var) val)) + ((hexl-mode--minor-mode-p var) (funcall var (if val 1 -1))) + (t (set (make-local-variable var) val)))) + ;;;###autoload (defun hexl-mode (&optional arg) "\\A mode for editing binary files in hex dump format. @@ -169,7 +275,7 @@ A sample format: 000000b0: 7461 626c 6520 6368 6172 6163 7465 7220 table character 000000c0: 7265 6769 6f6e 2e0a region.. -Movement is as simple as movement in a normal emacs text buffer. Most +Movement is as simple as movement in a normal Emacs text buffer. Most cursor movement bindings are the same (ie. Use \\[hexl-backward-char], \\[hexl-forward-char], \\[hexl-next-line], and \\[hexl-previous-line] to move the cursor left, right, down, and up). @@ -207,86 +313,58 @@ You can use \\[hexl-find-file] to visit a file in Hexl mode. (unless (eq major-mode 'hexl-mode) (let ((modified (buffer-modified-p)) (inhibit-read-only t) - (original-point (- (point) (point-min))) - max-address) + (original-point (- (point) (point-min)))) (and (eobp) (not (bobp)) (setq original-point (1- original-point))) - (if (not (or (eq arg 1) (not arg))) - ;; if no argument then we guess at hexl-max-address - (setq max-address (+ (* (/ (1- (buffer-size)) 68) 16) 15)) - (setq max-address (1- (buffer-size))) + ;; If `hexl-mode' is invoked with an argument the buffer is assumed to + ;; be in hexl format. + (when (memq arg '(1 nil)) ;; If the buffer's EOL type is -dos, we need to account for ;; extra CR characters added when hexlify-buffer writes the ;; buffer to a file. + ;; FIXME: This doesn't take into account multibyte coding systems. (when (eq (coding-system-eol-type buffer-file-coding-system) 1) - (setq max-address (+ (count-lines (point-min) (point-max)) - max-address)) - ;; But if there's no newline at the last line, we are off by - ;; one; adjust. - (or (eq (char-before (point-max)) ?\n) - (setq max-address (1- max-address))) - (setq original-point (+ (count-lines (point-min) (point)) + (setq original-point (+ (count-lines (point-min) (point)) original-point)) (or (bolp) (setq original-point (1- original-point)))) (hexlify-buffer) (restore-buffer-modified-p modified)) - (make-local-variable 'hexl-max-address) - (setq hexl-max-address max-address) + (set (make-local-variable 'hexl-max-address) + (let* ((full-lines (/ (buffer-size) 68)) + (last-line (% (buffer-size) 68)) + (last-line-bytes (% last-line 52))) + (+ last-line-bytes (* full-lines 16) -1))) (condition-case nil (hexl-goto-address original-point) (error nil))) ;; We do not turn off the old major mode; instead we just ;; override most of it. That way, we can restore it perfectly. - (make-local-variable 'hexl-mode-old-local-map) - (setq hexl-mode-old-local-map (current-local-map)) - (use-local-map hexl-mode-map) - - (make-local-variable 'hexl-mode-old-mode-name) - (setq hexl-mode-old-mode-name mode-name) - (setq mode-name "Hexl") - (set (make-local-variable 'hexl-mode-old-isearch-search-fun-function) - isearch-search-fun-function) - (set (make-local-variable 'isearch-search-fun-function) - 'hexl-isearch-search-function) + (hexl-mode--setq-local '(current-local-map . use-local-map) hexl-mode-map) - (make-local-variable 'hexl-mode-old-major-mode) - (setq hexl-mode-old-major-mode major-mode) - (setq major-mode 'hexl-mode) + (hexl-mode--setq-local 'mode-name "Hexl") + (hexl-mode--setq-local 'isearch-search-fun-function + 'hexl-isearch-search-function) + (hexl-mode--setq-local 'major-mode 'hexl-mode) - (make-local-variable 'hexl-mode-old-ruler-mode) - (setq hexl-mode-old-ruler-mode - (and (boundp 'ruler-mode) ruler-mode)) - - (make-local-variable 'hexl-mode-old-hl-line-mode) - (setq hexl-mode-old-hl-line-mode - (and (boundp 'hl-line-mode) hl-line-mode)) - - (make-local-variable 'hexl-mode-old-syntax-table) - (setq hexl-mode-old-syntax-table (syntax-table)) - (set-syntax-table (standard-syntax-table)) + (hexl-mode--setq-local '(syntax-table . set-syntax-table) + (standard-syntax-table)) (add-hook 'write-contents-functions 'hexl-save-buffer nil t) - (make-local-variable 'hexl-mode-old-require-final-newline) - (setq hexl-mode-old-require-final-newline require-final-newline) - (make-local-variable 'require-final-newline) - (setq require-final-newline nil) + (hexl-mode--setq-local 'require-final-newline nil) - (make-local-variable 'hexl-mode-old-font-lock-keywords) - (setq hexl-mode-old-font-lock-keywords font-lock-defaults) - (make-local-variable 'font-lock-defaults) - (setq font-lock-defaults '(hexl-font-lock-keywords t)) - ;; Add hooks to rehexlify or dehexlify on various events. - (add-hook 'after-revert-hook 'hexl-after-revert-hook nil t) + (hexl-mode--setq-local 'font-lock-defaults '(hexl-font-lock-keywords t)) + (hexl-mode--setq-local 'revert-buffer-function + #'hexl-revert-buffer-function) (add-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer nil t) ;; Set a callback function for eldoc. - (set (make-local-variable 'eldoc-documentation-function) - 'hexl-print-current-point-info) + (hexl-mode--setq-local 'eldoc-documentation-function + #'hexl-print-current-point-info) (eldoc-add-command-completions "hexl-") (eldoc-remove-command "hexl-save-buffer" "hexl-current-address") @@ -314,11 +392,6 @@ You can use \\[hexl-find-file] to visit a file in Hexl mode. (let ((isearch-search-fun-function nil)) (isearch-search-fun)))) -(defun hexl-after-revert-hook () - (setq hexl-max-address (1- (buffer-size))) - (hexlify-buffer) - (set-buffer-modified-p nil)) - (defvar hexl-in-save-buffer nil) (defun hexl-save-buffer () @@ -351,18 +424,36 @@ You can use \\[hexl-find-file] to visit a file in Hexl mode. ;;;###autoload (defun hexl-find-file (filename) - "Edit file FILENAME in `hexl-mode'. -Switch to a buffer visiting file FILENAME, creating one in none exists." + "Edit file FILENAME as a binary file in hex dump format. +Switch to a buffer visiting file FILENAME, creating one if none exists, +and edit the file in `hexl-mode'." (interactive (list (let ((completion-ignored-extensions nil)) (read-file-name "Filename: " nil nil 'ret-must-match)))) - ;; Ignore the user's setting of default-major-mode. - (let ((default-major-mode 'fundamental-mode)) + ;; Ignore the user's setting of default major-mode. + (letf (((default-value 'major-mode) 'fundamental-mode)) (find-file-literally filename)) (if (not (eq major-mode 'hexl-mode)) (hexl-mode))) +(defun hexl-revert-buffer-function (_ignore-auto _noconfirm) + (let ((coding-system-for-read 'no-conversion) + revert-buffer-function) + ;; Call the original `revert-buffer' without code conversion; also + ;; prevent it from changing the major mode to normal-mode, which + ;; calls `set-auto-mode'. + (revert-buffer nil nil t) + ;; A couple of hacks are necessary here: + ;; 1. change the major-mode to one other than hexl-mode since the + ;; function `hexl-mode' does nothing if the current major-mode is + ;; already hexl-mode. + ;; 2. reset change-major-mode-hook in case that `hexl-mode' + ;; previously added hexl-maybe-dehexlify-buffer to it. + (remove-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer t) + (setq major-mode 'fundamental-mode) + (hexl-mode))) + (defun hexl-mode-exit (&optional arg) "Exit Hexl mode, returning to previous mode. With arg, don't unhexlify buffer." @@ -382,22 +473,26 @@ With arg, don't unhexlify buffer." (or (bobp) (setq original-point (1+ original-point)))) (goto-char original-point))) - (remove-hook 'after-revert-hook 'hexl-after-revert-hook t) (remove-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer t) (remove-hook 'post-command-hook 'hexl-follow-ascii-find t) (setq hexl-ascii-overlay nil) - (if (and (boundp 'ruler-mode) ruler-mode (not hexl-mode-old-ruler-mode)) - (ruler-mode 0)) - (if (and (boundp 'hl-line-mode) hl-line-mode (not hexl-mode-old-hl-line-mode)) - (hl-line-mode 0)) - (setq require-final-newline hexl-mode-old-require-final-newline) - (setq mode-name hexl-mode-old-mode-name) - (setq isearch-search-fun-function hexl-mode-old-isearch-search-fun-function) - (use-local-map hexl-mode-old-local-map) - (set-syntax-table hexl-mode-old-syntax-table) - (setq font-lock-defaults hexl-mode-old-font-lock-keywords) - (setq major-mode hexl-mode-old-major-mode) + (let ((mms ())) + (dolist (varval hexl-mode--old-var-vals) + (let* ((bound (consp varval)) + (var (if bound (car varval) varval)) + (val (cdr-safe varval))) + (cond + ((consp var) (funcall (cdr var) val)) + ((hexl-mode--minor-mode-p var) (push (cons var val) mms)) + (bound (set (make-local-variable var) val)) + (t (kill-local-variable var))))) + (kill-local-variable 'hexl-mode--old-var-vals) + ;; Enable/disable minor modes. Do it after having reset the other vars, + ;; since some of them may affect the minor modes. + (dolist (mm mms) + (funcall (car mm) (if (cdr mm) 1 -1)))) + (force-mode-line-update)) (defun hexl-maybe-dehexlify-buffer () @@ -426,7 +521,7 @@ Ask the user for confirmation." (if (>= current-column 41) (- current-column 41) (/ (- current-column (/ current-column 5)) 2)))) - (when (interactive-p) + (when (called-interactively-p 'interactive) (message "Current address is %d/0x%08x" hexl-address hexl-address)) hexl-address)) @@ -442,8 +537,8 @@ This function is intended to be used as eldoc callback." (+ (* (/ address 16) 68) 10 (point-min) (/ (* (% address 16) 5) 2))) (defun hexl-goto-address (address) - "Goto hexl-mode (decimal) address ADDRESS. -Signal error if ADDRESS out of range." + "Go to hexl-mode (decimal) address ADDRESS. +Signal error if ADDRESS is out of range." (interactive "nAddress: ") (if (or (< address 0) (> address hexl-max-address)) (error "Out of hexl region")) @@ -484,7 +579,7 @@ Signal error if HEX-ADDRESS is out of range." (hexl-goto-address (- (hexl-current-address) arg))) (defun hexl-forward-char (arg) - "Move right ARG bytes (left if ARG negative) in hexl-mode." + "Move to right ARG bytes (left if ARG negative) in hexl-mode." (interactive "p") (hexl-goto-address (+ (hexl-current-address) arg))) @@ -496,23 +591,21 @@ Signal error if HEX-ADDRESS is out of range." (progn (setq arg (- arg)) (while (> arg 0) - (if (not (equal address (logior address 3))) - (if (> address hexl-max-address) - (progn - (message "End of buffer.") - (setq address hexl-max-address)) - (setq address (logior address 3))) - (if (> address hexl-max-address) - (progn - (message "End of buffer.") - (setq address hexl-max-address)) - (setq address (+ address 4)))) + (setq address + (if (> address hexl-max-address) + (progn + (message "End of buffer.") + hexl-max-address) + (if (equal address (logior address 3)) + (+ address 4) + (logior address 3)))) (setq arg (1- arg))) - (if (> address hexl-max-address) - (progn - (message "End of buffer.") - (setq address hexl-max-address)) - (setq address (logior address 3)))) + (setq address + (if (> address hexl-max-address) + (progn + (message "End of buffer.") + hexl-max-address) + (logior address 3)))) (while (> arg 0) (if (not (equal address (logand address -4))) (setq address (logand address -4)) @@ -523,7 +616,7 @@ Signal error if HEX-ADDRESS is out of range." address))) (defun hexl-forward-short (arg) - "Move right ARG shorts (left if ARG negative) in hexl-mode." + "Move to right ARG shorts (left if ARG negative) in hexl-mode." (interactive "p") (hexl-backward-short (- arg))) @@ -535,23 +628,21 @@ Signal error if HEX-ADDRESS is out of range." (progn (setq arg (- arg)) (while (> arg 0) - (if (not (equal address (logior address 7))) - (if (> address hexl-max-address) - (progn - (message "End of buffer.") - (setq address hexl-max-address)) - (setq address (logior address 7))) - (if (> address hexl-max-address) - (progn - (message "End of buffer.") - (setq address hexl-max-address)) - (setq address (+ address 8)))) + (setq address + (if (> address hexl-max-address) + (progn + (message "End of buffer.") + hexl-max-address) + (if (equal address (logior address 7)) + (+ address 8) + (logior address 7)))) (setq arg (1- arg))) - (if (> address hexl-max-address) - (progn - (message "End of buffer.") - (setq address hexl-max-address)) - (setq address (logior address 7)))) + (setq address + (if (> address hexl-max-address) + (progn + (message "End of buffer.") + hexl-max-address) + (logior address 7)))) (while (> arg 0) (if (not (equal address (logand address -8))) (setq address (logand address -8)) @@ -562,13 +653,13 @@ Signal error if HEX-ADDRESS is out of range." address))) (defun hexl-forward-word (arg) - "Move right ARG words (left if ARG negative) in hexl-mode." + "Move to right ARG words (left if ARG negative) in hexl-mode." (interactive "p") (hexl-backward-word (- arg))) (defun hexl-previous-line (arg) "Move vertically up ARG lines [16 bytes] (down if ARG negative) in hexl-mode. -If there is byte at the target address move to the last byte in that line." +If there is no byte at the target address move to the last byte in that line." (interactive "p") (hexl-next-line (- arg))) @@ -622,18 +713,18 @@ With prefix arg N, puts point N bytes of the way from the true beginning." (defun hexl-scroll-down (arg) "Scroll hexl buffer window upward ARG lines; or near full window if no ARG." (interactive "P") - (if (null arg) - (setq arg (1- (window-height))) - (setq arg (prefix-numeric-value arg))) + (setq arg (if (null arg) + (1- (window-height)) + (prefix-numeric-value arg))) (hexl-scroll-up (- arg))) (defun hexl-scroll-up (arg) "Scroll hexl buffer window upward ARG lines; or near full window if no ARG. If there's no byte at the target address, move to the first or last line." (interactive "P") - (if (null arg) - (setq arg (1- (window-height))) - (setq arg (prefix-numeric-value arg))) + (setq arg (if (null arg) + (1- (window-height)) + (prefix-numeric-value arg))) (let* ((movement (* arg 16)) (address (hexl-current-address)) (dest (+ address movement))) @@ -654,17 +745,15 @@ If there's no byte at the target address, move to the first or last line." (recenter 0))) (defun hexl-beginning-of-1k-page () - "Go to beginning of 1k boundary." + "Go to beginning of 1KB boundary." (interactive) (hexl-goto-address (logand (hexl-current-address) -1024))) (defun hexl-end-of-1k-page () - "Go to end of 1k boundary." + "Go to end of 1KB boundary." (interactive) - (hexl-goto-address (let ((address (logior (hexl-current-address) 1023))) - (if (> address hexl-max-address) - (setq address hexl-max-address)) - address))) + (hexl-goto-address + (max hexl-max-address (logior (hexl-current-address) 1023)))) (defun hexl-beginning-of-512b-page () "Go to beginning of 512 byte boundary." @@ -674,10 +763,8 @@ If there's no byte at the target address, move to the first or last line." (defun hexl-end-of-512b-page () "Go to end of 512 byte boundary." (interactive) - (hexl-goto-address (let ((address (logior (hexl-current-address) 511))) - (if (> address hexl-max-address) - (setq address hexl-max-address)) - address))) + (hexl-goto-address + (max hexl-max-address (logior (hexl-current-address) 511)))) (defun hexl-quoted-insert (arg) "Read next input character and insert it. @@ -694,10 +781,10 @@ You may also type octal digits, to insert a character with that code." "Convert a binary buffer to hexl format. This discards the buffer's undo information." (interactive) - (and buffer-undo-list + (and (consp buffer-undo-list) (or (y-or-n-p "Converting to hexl format discards undo info; ok? ") - (error "Aborted"))) - (setq buffer-undo-list nil) + (error "Aborted")) + (setq buffer-undo-list nil)) ;; Don't decode text in the ASCII part of `hexl' program output. (let ((coding-system-for-read 'raw-text) (coding-system-for-write buffer-file-coding-system) @@ -708,7 +795,9 @@ This discards the buffer's undo information." ;; Manually encode the args, otherwise they're encoded using ;; coding-system-for-write (i.e. buffer-file-coding-system) which ;; may not be what we want (e.g. utf-16 on a non-utf-16 system). - (mapcar (lambda (s) (encode-coding-string s locale-coding-system)) + (mapcar (lambda (s) + (if (not (multibyte-string-p s)) s + (encode-coding-string s locale-coding-system))) (split-string hexl-options))) (if (> (point) (hexl-address-to-marker hexl-max-address)) (hexl-goto-address hexl-max-address)))) @@ -717,10 +806,10 @@ This discards the buffer's undo information." "Convert a hexl format buffer to binary. This discards the buffer's undo information." (interactive) - (and buffer-undo-list + (and (consp buffer-undo-list) (or (y-or-n-p "Converting from hexl format discards undo info; ok? ") - (error "Aborted"))) - (setq buffer-undo-list nil) + (error "Aborted")) + (setq buffer-undo-list nil)) (let ((coding-system-for-write 'raw-text) (coding-system-for-read buffer-file-coding-system) (buffer-undo-list t)) @@ -755,11 +844,11 @@ This discards the buffer's undo information." (defun hexl-printable-character (ch) "Return a displayable string for character CH." - (format "%c" (if hexl-iso - (if (or (< ch 32) (and (>= ch 127) (< ch 160))) + (format "%c" (if (equal hexl-iso "") + (if (or (< ch 32) (>= ch 127)) 46 ch) - (if (or (< ch 32) (>= ch 127)) + (if (or (< ch 32) (and (>= ch 127) (< ch 160))) 46 ch)))) @@ -772,7 +861,7 @@ and their encoded form is inserted byte by byte." (coding (if (or (null buffer-file-coding-system) ;; coding-system-type equals t means undecided. (eq (coding-system-type buffer-file-coding-system) t)) - default-buffer-file-coding-system + (default-value 'buffer-file-coding-system) buffer-file-coding-system))) (cond ((and (> ch 0) (< ch 256)) (hexl-insert-char ch num)) @@ -812,7 +901,7 @@ Interactively, with a numeric argument, insert this character that many times. Non-ASCII characters are first encoded with `buffer-file-coding-system', and their encoded form is inserted byte by byte." (interactive "p") - (hexl-insert-multibyte-char last-command-char arg)) + (hexl-insert-multibyte-char last-command-event arg)) (defun hexl-insert-char (ch num) "Insert the character CH NUM times in a hexl buffer. @@ -930,24 +1019,21 @@ Customize the variable `hexl-follow-ascii' to disable this feature." (defun hexl-activate-ruler () "Activate `ruler-mode'." (require 'ruler-mode) - (set (make-local-variable 'ruler-mode-ruler-function) - 'hexl-mode-ruler) - (ruler-mode 1)) + (hexl-mode--setq-local 'ruler-mode-ruler-function + #'hexl-mode-ruler) + (hexl-mode--setq-local 'ruler-mode t)) (defun hexl-follow-line () "Activate `hl-line-mode'." - (require 'frame) (require 'hl-line) - (with-no-warnings - (set (make-local-variable 'hl-line-range-function) - 'hexl-highlight-line-range) - (set (make-local-variable 'hl-line-face) - 'highlight)) - (hl-line-mode 1)) + (hexl-mode--setq-local 'hl-line-range-function + #'hexl-highlight-line-range) + (hexl-mode--setq-local 'hl-line-face 'highlight) + (hexl-mode--setq-local 'hl-line-mode t)) (defun hexl-highlight-line-range () "Return the range of address region for the point. -This function is assumed to be used as call back function for `hl-line-mode'." +This function is assumed to be used as callback function for `hl-line-mode'." (cons (line-beginning-position) ;; 9 stands for (length "87654321:") @@ -986,101 +1072,43 @@ This function is assumed to be used as call back function for `hl-line-mode'." ;; startup stuff. -(if hexl-mode-map - nil - (setq hexl-mode-map (make-keymap)) - ;; Make all self-inserting keys go through hexl-self-insert-command, - ;; because we need to convert them to unibyte characters before - ;; inserting them into the buffer. - (define-key hexl-mode-map [remap self-insert-command] 'hexl-self-insert-command) - - (define-key hexl-mode-map "\C-m" 'hexl-self-insert-command) - (define-key hexl-mode-map [left] 'hexl-backward-char) - (define-key hexl-mode-map [right] 'hexl-forward-char) - (define-key hexl-mode-map [up] 'hexl-previous-line) - (define-key hexl-mode-map [down] 'hexl-next-line) - (define-key hexl-mode-map [M-left] 'hexl-backward-short) - (define-key hexl-mode-map [?\e left] 'hexl-backward-short) - (define-key hexl-mode-map [M-right] 'hexl-forward-short) - (define-key hexl-mode-map [?\e right] 'hexl-forward-short) - (define-key hexl-mode-map [next] 'hexl-scroll-up) - (define-key hexl-mode-map [prior] 'hexl-scroll-down) - (define-key hexl-mode-map [home] 'hexl-beginning-of-line) - (define-key hexl-mode-map [end] 'hexl-end-of-line) - (define-key hexl-mode-map [C-home] 'hexl-beginning-of-buffer) - (define-key hexl-mode-map [C-end] 'hexl-end-of-buffer) - (define-key hexl-mode-map [deletechar] 'undefined) - (define-key hexl-mode-map [deleteline] 'undefined) - (define-key hexl-mode-map [insertline] 'undefined) - (define-key hexl-mode-map [S-delete] 'undefined) - (define-key hexl-mode-map "\177" 'undefined) - - (define-key hexl-mode-map "\C-a" 'hexl-beginning-of-line) - (define-key hexl-mode-map "\C-b" 'hexl-backward-char) - (define-key hexl-mode-map "\C-d" 'undefined) - (define-key hexl-mode-map "\C-e" 'hexl-end-of-line) - (define-key hexl-mode-map "\C-f" 'hexl-forward-char) - - (if (not (memq (key-binding (char-to-string help-char)) - '(help-command ehelp-command))) - (define-key hexl-mode-map (char-to-string help-char) 'undefined)) - - (define-key hexl-mode-map "\C-k" 'undefined) - (define-key hexl-mode-map "\C-n" 'hexl-next-line) - (define-key hexl-mode-map "\C-o" 'undefined) - (define-key hexl-mode-map "\C-p" 'hexl-previous-line) - (define-key hexl-mode-map "\C-q" 'hexl-quoted-insert) - (define-key hexl-mode-map "\C-t" 'undefined) - (define-key hexl-mode-map "\C-v" 'hexl-scroll-up) - (define-key hexl-mode-map "\C-w" 'undefined) - (define-key hexl-mode-map "\C-y" 'undefined) - - (fset 'hexl-ESC-prefix (copy-keymap 'ESC-prefix)) - (define-key hexl-mode-map "\e" 'hexl-ESC-prefix) - (define-key hexl-mode-map "\e\C-a" 'hexl-beginning-of-512b-page) - (define-key hexl-mode-map "\e\C-b" 'hexl-backward-short) - (define-key hexl-mode-map "\e\C-d" 'hexl-insert-decimal-char) - (define-key hexl-mode-map "\e\C-e" 'hexl-end-of-512b-page) - (define-key hexl-mode-map "\e\C-f" 'hexl-forward-short) - (define-key hexl-mode-map "\e\C-i" 'undefined) - (define-key hexl-mode-map "\e\C-j" 'undefined) - (define-key hexl-mode-map "\e\C-k" 'undefined) - (define-key hexl-mode-map "\e\C-o" 'hexl-insert-octal-char) - (define-key hexl-mode-map "\e\C-q" 'undefined) - (define-key hexl-mode-map "\e\C-t" 'undefined) - (define-key hexl-mode-map "\e\C-x" 'hexl-insert-hex-char) - (define-key hexl-mode-map "\eb" 'hexl-backward-word) - (define-key hexl-mode-map "\ec" 'undefined) - (define-key hexl-mode-map "\ed" 'undefined) - (define-key hexl-mode-map "\ef" 'hexl-forward-word) - (define-key hexl-mode-map "\eg" 'hexl-goto-hex-address) - (define-key hexl-mode-map "\ei" 'undefined) - (define-key hexl-mode-map "\ej" 'hexl-goto-address) - (define-key hexl-mode-map "\ek" 'undefined) - (define-key hexl-mode-map "\el" 'undefined) - (define-key hexl-mode-map "\eq" 'undefined) - (define-key hexl-mode-map "\es" 'undefined) - (define-key hexl-mode-map "\et" 'undefined) - (define-key hexl-mode-map "\eu" 'undefined) - (define-key hexl-mode-map "\ev" 'hexl-scroll-down) - (define-key hexl-mode-map "\ey" 'undefined) - (define-key hexl-mode-map "\ez" 'undefined) - (define-key hexl-mode-map "\e<" 'hexl-beginning-of-buffer) - (define-key hexl-mode-map "\e>" 'hexl-end-of-buffer) - - (fset 'hexl-C-c-prefix (copy-keymap mode-specific-map)) - (define-key hexl-mode-map "\C-c" 'hexl-C-c-prefix) - (define-key hexl-mode-map "\C-c\C-c" 'hexl-mode-exit) - - (fset 'hexl-C-x-prefix (copy-keymap 'Control-X-prefix)) - (define-key hexl-mode-map "\C-x" 'hexl-C-x-prefix) - (define-key hexl-mode-map "\C-x[" 'hexl-beginning-of-1k-page) - (define-key hexl-mode-map "\C-x]" 'hexl-end-of-1k-page) - (define-key hexl-mode-map "\C-x\C-p" 'undefined) - (define-key hexl-mode-map "\C-x\C-s" 'hexl-save-buffer) - (define-key hexl-mode-map "\C-x\C-t" 'undefined)) +(easy-menu-define hexl-menu hexl-mode-map "Hexl Mode menu" + `("Hexl" + :help "Hexl-specific Features" + + ["Backward short" hexl-backward-short + :help "Move to left a short"] + ["Forward short" hexl-forward-short + :help "Move to right a short"] + ["Backward word" hexl-backward-short + :help "Move to left a word"] + ["Forward word" hexl-forward-short + :help "Move to right a word"] + "-" + ["Beginning of 512b page" hexl-beginning-of-512b-page + :help "Go to beginning of 512 byte boundary"] + ["End of 512b page" hexl-end-of-512b-page + :help "Go to end of 512 byte boundary"] + ["Beginning of 1K page" hexl-beginning-of-1k-page + :help "Go to beginning of 1KB boundary"] + ["End of 1K page" hexl-end-of-1k-page + :help "Go to end of 1KB boundary"] + "-" + ["Go to address" hexl-goto-address + :help "Go to hexl-mode (decimal) address"] + ["Go to address" hexl-goto-hex-address + :help "Go to hexl-mode (hex string) address"] + "-" + ["Insert decimal char" hexl-insert-decimal-char + :help "Insert a character given by its decimal code"] + ["Insert hex char" hexl-insert-hex-char + :help "Insert a character given by its hexadecimal code"] + ["Insert octal char" hexl-insert-octal-char + :help "Insert a character given by its octal code"] + "-" + ["Exit hexl mode" hexl-mode-exit + :help "Exit hexl mode returning to previous mode"])) (provide 'hexl) -;; arch-tag: d5a7aa8a-9bce-480b-bcff-6c4c7ca5ea4a ;;; hexl.el ends here