branch: master commit fa31d3a8482c220f2f850ce33d244be108dfaae5 Author: Stefan Monnier <monn...@iro.umontreal.ca> Commit: Stefan Monnier <monn...@iro.umontreal.ca>
* nhexl-mode.el: Improve handling of mouse events (nhexl--posn-hexadjust): New function extracted from nhexl-mouse-set-point. (nhexl-mouse-set-point): Use it. (nhexl-mouse-drag-region, nhexl-mouse-set-region): New commands. (nhexl-mode-map): Remap to them. (nhexl--make-line): Circumvent some misbehavior in the presence of buttons. --- packages/nhexl-mode/nhexl-mode.el | 72 ++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/packages/nhexl-mode/nhexl-mode.el b/packages/nhexl-mode/nhexl-mode.el index b7221bf..b58b81d 100644 --- a/packages/nhexl-mode/nhexl-mode.el +++ b/packages/nhexl-mode/nhexl-mode.el @@ -328,6 +328,8 @@ existing text, if needed with `nhexl-overwrite-clear-byte'." (define-key map [remap scroll-up-command] #'nhexl-scroll-up) (define-key map [remap scroll-down-command] #'nhexl-scroll-down) (define-key map [remap mouse-set-point] #'nhexl-mouse-set-point) + (define-key map [remap mouse-drag-region] #'nhexl-mouse-drag-region) + (define-key map [remap mouse-set-region] #'nhexl-mouse-set-region) ;; FIXME: Find a key binding for nhexl-nibble-edit-mode! map)) @@ -466,35 +468,55 @@ existing text, if needed with `nhexl-overwrite-clear-byte'." (eval-and-compile (defvar nhexl--put-LF-in-string nil)) -(defun nhexl-mouse-set-point (event) - "Move point to the position clicked on with the mouse." - (interactive "e") - ;; (cl-assert (eq last-)) - (let* ((posn (event-end event)) - (str-data (posn-string posn)) +(defun nhexl--posn-hexadjust (posn) + "Adjust POSN when clicking on the hex area. +Return the corresponding nibble, if applicable." + ;; When clicking in the hex area, (nth 1 posn) contains the first position + ;; covered by the before-string, and (nth 5 posn) as well. Improve this by + ;; setting nth-5 (the one used by `posn-point') to the closest buffer + ;; position corresponding to the hex on which we clicked. + (let* ((str-data (posn-string posn)) + (base-pos (nth 1 posn)) (addr-offset (eval-when-compile (+ (if nhexl--put-LF-in-string 1 0) - 9 ;for "<address>:" - 1)))) ;for the following (stretch)space + 9 ;for "<address>:" + 1)))) ;for the following (stretch)space ;; (message "NMSP: strdata=%S" str-data) - (cond - ((and (consp str-data) (stringp (car str-data)) - (integerp (cdr str-data)) (> (cdr str-data) addr-offset)) + (when (and (consp str-data) (stringp (car str-data)) (integerp base-pos) + (integerp (cdr str-data)) (> (cdr str-data) addr-offset)) (let* ((hexchars (- (cdr str-data) addr-offset)) ;; FIXME: Calculations here go wrong in the presence of ;; chars with code > 255. (hex-no-spaces (- hexchars (/ (1+ hexchars) 5))) (bytes (min (/ hex-no-spaces 2) ;; Bound, for clicks between the hex and ascii areas. - (1- (nhexl--line-width))))) - ;; This will select the window if needed and move point to the - ;; beginning of the line. - (posn-set-point posn) - (forward-char bytes) - (when nhexl-nibble-edit-mode - (let* ((nibble (- hex-no-spaces (* bytes 2)))) - (nhexl--nibble-set (min nibble 1)))))) - (t (call-interactively #'mouse-set-point))))) + (1- (nhexl--line-width)))) + (newpos (min (+ base-pos bytes) (point-max)))) + (setf (nth 5 posn) newpos) + (let* ((nibble (- hex-no-spaces (* bytes 2)))) + (min nibble 1)))))) + +(defun nhexl-mouse-set-point (event) + "Move point to the position clicked on with the mouse." + (interactive "e") + (let* ((nibble (nhexl--posn-hexadjust (event-end event)))) + (call-interactively #'mouse-set-point) + (when (and nibble nhexl-nibble-edit-mode) + (nhexl--nibble-set nibble) + (nhexl--refresh-cursor)))) + +(defun nhexl-mouse-drag-region (event) + "Set the region to the text that the mouse is dragged over." + (interactive "e") + (nhexl--posn-hexadjust (event-start event)) + (call-interactively #'mouse-drag-region)) + +(defun nhexl-mouse-set-region (event) + "Set the region to the text dragged over, and copy to kill ring." + (interactive "e") + (nhexl--posn-hexadjust (event-start event)) + (nhexl--posn-hexadjust (event-end event)) + (call-interactively #'mouse-set-region)) (defun nhexl--change-function (beg end len) ;; Round modifications up-to the hexl-line length since nhexl--jit will need @@ -616,6 +638,16 @@ existing text, if needed with `nhexl-overwrite-clear-byte'." ,(+ (/ (* lw 5) 2) 12 3)))))) (font-lock-append-text-property 0 (length s) prop 'default s) + ;; If the first char of the text has a button (e.g. it's part of + ;; a hyperlink), clicking in the hex part of the display might signal + ;; an error because it thinks we're clicking on the hyperlink. + ;; So override the relevant properties. + (put-text-property 0 (length s) 'keymap (make-sparse-keymap) s) + (put-text-property 0 (length s) 'follow-link #'ignore s) + ;; Override any `category' property that might otherwise be inherited from + ;; the text (e.g. that of some button). + ;; FIXME: This doesn't have the intended effect! + (put-text-property 0 (length s) 'category t s) s)) (defun nhexl--jit (from to)