+(defcustom shifted-motion-keys-select-region t
+ "*If non-nil, shifted motion keys select text, like in MS Windows.
+See also `unshifted-motion-keys-deselect-region'."
+ :type 'boolean
+ :group 'editing-basics)
+
+(defcustom unshifted-motion-keys-deselect-region t
+ "*If non-nil, unshifted motion keys deselect a shifted-motion region.
+This only occurs after a region has been selected using shifted motion keys
+(not when using the traditional set-mark-then-move method), and has no effect
+if `shifted-motion-keys-select-region' is nil."
+ :type 'boolean
+ :group 'editing-basics)
+
+(defun handle-pre-motion-command-current-command-is-motion ()
+ (and (key-press-event-p last-input-event)
+ (memq (event-key last-input-event)
+ '(left right up down home end prior next
+ kp-left kp-right kp-up kp-down
+ kp-home kp-end kp-prior kp-next))))
+
+(defun handle-pre-motion-command ()
+ (if
+ (and
+ (handle-pre-motion-command-current-command-is-motion)
+ zmacs-regions
+ shifted-motion-keys-select-region
+ (not (region-active-p))
+ (memq 'shift (event-modifiers last-input-event)))
+ (let ((in-shifted-motion-command t))
+ (push-mark nil nil t))))
+
+(defun handle-post-motion-command ()
+ (if
+ (and
+ (handle-pre-motion-command-current-command-is-motion)
+ zmacs-regions
+ (region-active-p))
+ (cond ((memq 'shift (event-modifiers last-input-event))
+ (if shifted-motion-keys-select-region
+ (putf this-command-properties 'shifted-motion-command t))
+ (setq zmacs-region-stays t))
+ ((and (getf last-command-properties 'shifted-motion-command)
+ unshifted-motion-keys-deselect-region)
+ (setq zmacs-region-stays nil))
+ (t
+ (setq zmacs-region-stays t)))))
+