all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Vivek Dasmohapatra <vivek@etla.org>
To: emacs-devel@gnu.org
Subject: Re: hexl mode update (variable word size for hexl mode)
Date: Wed, 18 Nov 2009 00:52:13 +0000 (GMT)	[thread overview]
Message-ID: <alpine.DEB.1.10.0911180046450.9073@localhost> (raw)
In-Reply-To: <alpine.DEB.1.10.0907210134440.27813@localhost>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 968 bytes --]

There was no response to this last time, so I'm re-posting it:

The user can select the "word size" hexl will use with defcustom (it 
currently screws up if you change this size behind hexl's back, ie after 
hexlifying a buffer but before unhexlifying it: this could be fixed by
saving the word size used in a a local variable in the hexl buffer, let
me know if you think this is important enough to add). Other than that, 
the hexl code doesn't seem to have changed since I last updated the patch
from emacs 22 to emacs 23.

The word-size could also be chosen at invocation time via a prefix arg, but I 
have not done this yet either: Again, let me know if you think it's
worth adding.

I originally prepared this patch for a friend who was debugging something and 
needed other word sizes: Upon investigation I discovered that the
hexl binary had support for the word sizes 8, 16, 32 and 64 bits but the
hexl mode code only supported one of those - hence this patch.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: TEXT/x-diff; name=hexl.variable-word-size.2009-07-21.patch, Size: 10509 bytes --]

diff --git a/lisp/hexl.el b/lisp/hexl.el
index 2cdd449..0eebe55 100644
--- a/lisp/hexl.el
+++ b/lisp/hexl.el
@@ -51,6 +51,13 @@
   "Edit a file in a hex dump format using the hexl filter."
   :group 'data)
 
+(defcustom hexl-bits 16
+  "The bit grouping that hexl will use"
+  :type '(choice (const 8 )
+                 (const 16)
+                 (const 32)
+                 (const 64))
+  :group 'hexl)
 
 (defcustom hexl-program "hexl"
   "The program that will hexlify and dehexlify its stdin.
@@ -135,6 +142,15 @@ Quoting cannot be used, so the arguments cannot themselves contain spaces."
 
 (put 'hexl-mode 'mode-class 'special)
 
+;; 10 chars for the "address: "
+;; 32 chars for the hexlified bytes
+;; 1 char for the space 
+;; 16 chars for the character display
+;; X chars for the spaces (128 bits divided by the hexl-bits)
+;; 1 char for the newline.
+(defun hexl-line-displen ()
+  (+ 60 (/ 128 (or hexl-bits 16))))
+
 ;;;###autoload
 (defun hexl-mode (&optional arg)
   "\\<hexl-mode-map>A mode for editing binary files in hex dump format.
@@ -213,27 +229,33 @@ 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))))
+	  (original-point (- (point) (point-min)))
+	  max-address)
       (and (eobp) (not (bobp))
 	   (setq original-point (1- original-point)))
-      ;; If `hexl-mode' is invoked with an argument the buffer is assumed to
-      ;; be in hexl format.
-      (when (memq arg '(1 nil))
+      (if (not (memq arg '(1 nil)))
+	  ;; if no argument then we guess at hexl-max-address
+          (setq max-address 
+                (+ (* (/ (1- (buffer-size)) (hexl-line-displen)) 16) 15))
+        (setq max-address (1- (buffer-size)))
 	;; 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 original-point (+ (count-lines (point-min) (point))
+          (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))
 				  original-point))
 	  (or (bolp) (setq original-point (1- original-point))))
         (hexlify-buffer)
         (restore-buffer-modified-p modified))
-      (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)))
+      (make-local-variable 'hexl-max-address)
+      (setq hexl-max-address max-address)
       (condition-case nil
 	  (hexl-goto-address original-point)
 	(error nil)))
@@ -436,19 +458,23 @@ Ask the user for confirmation."
 (defun hexl-current-address (&optional validate)
   "Return current hexl-address."
   (interactive)
-  (let ((current-column (- (% (- (point) (point-min) -1) 68) 11))
+  (let ((current-column 
+         (- (% (- (point) (point-min) -1) (hexl-line-displen)) 11))
 	(hexl-address 0))
     (if (< current-column 0)
 	(if validate
 	    (error "Point is not on a character in the file")
 	  (setq current-column 0)))
     (setq hexl-address
-	  (+ (* (/ (- (point) (point-min) -1) 68) 16)
-	     (if (>= current-column 41)
-		 (- current-column 41)
-	       (/ (- current-column  (/ current-column 5)) 2))))
+	  (+ (* (/ (- (point) (point-min) -1) 
+                   (hexl-line-displen)) 16)
+	     (if (>= current-column (- (hexl-ascii-start-column) 10))
+		 (- current-column (- (hexl-ascii-start-column) 10))
+               (/ (- current-column 
+                     (/ current-column (1+ (/ hexl-bits 4)))) 2) )) )
     (when (interactive-p)
-      (message "Current address is %d/0x%08x" hexl-address hexl-address))
+      (message "Current address is [column: %d] %d/0x%08x" 
+               current-column hexl-address hexl-address))
     hexl-address))
 
 (defun hexl-print-current-point-info ()
@@ -457,10 +483,18 @@ This function is intended to be used as eldoc callback."
   (let ((addr (hexl-current-address)))
     (format "Current address is %d/0x%08x" addr addr)))
 
+(defun hexl-ascii-start-column () 
+  "Column at which the ascii display starts."
+  (+ 43 (/ 128 hexl-bits)))
+
 (defun hexl-address-to-marker (address)
   "Return buffer position for ADDRESS."
   (interactive "nAddress: ")
-  (+ (* (/ address 16) 68) 10 (point-min) (/ (* (% address 16) 5) 2)))
+  (let ((N (* (% address 16) 2)))
+    (+ (* (/ address 16) (hexl-line-displen)) ; hexl line no * display length
+       10                      ; 10 chars for the "address: " prefix
+       (point-min)             ; base offset (point usually starts at 1, not 0)
+       (+ N (/ N (/ hexl-bits 4))) )) ) ; char offset into hexl display line
 
 (defun hexl-goto-address (address)
   "Go to hexl-mode (decimal) address ADDRESS.
@@ -505,7 +539,7 @@ Signal error if HEX-ADDRESS is out of range."
   (hexl-goto-address (- (hexl-current-address) arg)))
 
 (defun hexl-forward-char (arg)
-  "Move to right ARG bytes (left if ARG negative) in hexl-mode."
+  "Move right ARG bytes (left if ARG negative) in hexl-mode."
   (interactive "p")
   (hexl-goto-address (+ (hexl-current-address) arg)))
 
@@ -544,7 +578,7 @@ Signal error if HEX-ADDRESS is out of range."
 		       address)))
 
 (defun hexl-forward-short (arg)
-  "Move to right ARG shorts (left if ARG negative) in hexl-mode."
+  "Move right ARG shorts (left if ARG negative) in hexl-mode."
   (interactive "p")
   (hexl-backward-short (- arg)))
 
@@ -583,7 +617,7 @@ Signal error if HEX-ADDRESS is out of range."
 		       address)))
 
 (defun hexl-forward-word (arg)
-  "Move to right ARG words (left if ARG negative) in hexl-mode."
+  "Move right ARG words (left if ARG negative) in hexl-mode."
   (interactive "p")
   (hexl-backward-word (- arg)))
 
@@ -630,7 +664,7 @@ With prefix arg N, puts point N bytes of the way from the true beginning."
 (defun hexl-beginning-of-line ()
   "Goto beginning of line in hexl mode."
   (interactive)
-  (goto-char (+ (* (/ (point) 68) 68) 11)))
+  (goto-char (+ (* (/ (point) (hexl-line-displen)) (hexl-line-displen)) 11)))
 
 (defun hexl-end-of-line ()
   "Goto end of line in hexl mode."
@@ -675,12 +709,12 @@ 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 1KB boundary."
+  "Go to the beginning of the current 1 KiB block"
   (interactive)
   (hexl-goto-address (logand (hexl-current-address) -1024)))
 
 (defun hexl-end-of-1k-page ()
-  "Go to end of 1KB boundary."
+  "Go to the end of the current 1 KiB block."
   (interactive)
   (hexl-goto-address (let ((address (logior (hexl-current-address) 1023)))
 		       (if (> address hexl-max-address)
@@ -710,6 +744,15 @@ You may also type octal digits, to insert a character with that code."
 
 ;00000000: 0011 2233 4455 6677 8899 aabb ccdd eeff  0123456789ABCDEF
 
+(defun hexl-options (&optional test)
+  (let ((opts (or test hexl-options)))
+    (when (memq hexl-bits '(8 16 32 64))
+      (when (string-match "\\(.*\\)-group-by-[0-9]+-bits\\(.*\\)" opts)
+        (setq opts (concat (match-string 1 opts) 
+                           (match-string 2 opts))) ) 
+      (setq opts (format "%s -group-by-%d-bits " opts hexl-bits)) )
+    opts))
+
 ;;;###autoload
 (defun hexlify-buffer ()
   "Convert a binary buffer to hexl format.
@@ -732,7 +775,7 @@ This discards the buffer's undo information."
            (mapcar (lambda (s)
                      (if (not (multibyte-string-p s)) s
                        (encode-coding-string s locale-coding-system)))
-                   (split-string hexl-options)))
+                   (split-string (hexl-options))))
     (if (> (point) (hexl-address-to-marker hexl-max-address))
 	(hexl-goto-address hexl-max-address))))
 
@@ -749,7 +792,7 @@ This discards the buffer's undo information."
 	(buffer-undo-list t))
     (apply 'call-process-region (point-min) (point-max)
 	   (expand-file-name hexl-program exec-directory)
-	   t t nil "-de" (split-string hexl-options))))
+	   t t nil "-de" (split-string (hexl-options)))))
 
 (defun hexl-char-after-point ()
   "Return char for ASCII hex digits at point."
@@ -846,12 +889,15 @@ CH must be a unibyte character whose value is between 0 and 255."
   (let ((address (hexl-current-address t)))
     (while (> num 0)
       (let ((hex-position
-	     (+ (* (/ address 16) 68)
+	     (+ (* (/ address 16) (hexl-line-displen))
 		10 (point-min)
 		(* 2 (% address 16))
 		(/ (% address 16) 2)))
 	    (ascii-position
-	     (+ (* (/ address 16) 68) 51 (point-min) (% address 16)))
+	     (+ (* (/ address 16) (hexl-line-displen)) 
+                (hexl-ascii-start-column) 
+                (point-min) 
+                (% address 16)))
 	    at-ascii-position)
 	(if (= (point) ascii-position)
 	    (setq at-ascii-position t))
@@ -867,7 +913,7 @@ CH must be a unibyte character whose value is between 0 and 255."
 	(if at-ascii-position
 	    (progn
 	      (beginning-of-line)
-	      (forward-char 51)
+	      (forward-char (hexl-ascii-start-column))
 	      (forward-char (% address 16)))))
       (setq num (1- num)))))
 
@@ -985,7 +1031,7 @@ This function is assumed to be used as callback function for `hl-line-mode'."
 
 (defun hexl-follow-ascii-find ()
   "Find and highlight the ASCII element corresponding to current point."
-  (let ((pos (+ 51
+  (let ((pos (+ (hexl-ascii-start-column)
 		(- (point) (current-column))
 		(mod (hexl-current-address) 16))))
     (move-overlay hexl-ascii-overlay pos (1+ pos))

  reply	other threads:[~2009-11-18  0:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-07  1:20 hexl mode update Vivek Dasmohapatra
     [not found] ` <jwvljmo364c.fsf-monnier+emacs@gnu.org>
     [not found]   ` <alpine.DEB.2.00.0907161901001.28562@octopus.pepperfish.net>
     [not found]     ` <jwvocrkc9hs.fsf-monnier+emacs@gnu.org>
2009-07-21  0:44       ` Vivek Dasmohapatra
2009-11-18  0:52         ` Vivek Dasmohapatra [this message]
2009-11-18  1:35           ` hexl mode update (variable word size for hexl mode) Glenn Morris

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.DEB.1.10.0911180046450.9073@localhost \
    --to=vivek@etla.org \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.