| [8428] | 1 | ;;; -*- Log: hemlock.log; Package: Hemlock-Internals -*-
|
|---|
| [6] | 2 | ;;;
|
|---|
| 3 | ;;; **********************************************************************
|
|---|
| 4 | ;;; This code was written as part of the CMU Common Lisp project at
|
|---|
| 5 | ;;; Carnegie Mellon University, and has been placed in the public domain.
|
|---|
| 6 | ;;;
|
|---|
| 7 | #+CMU (ext:file-comment
|
|---|
| 8 | "$Header$")
|
|---|
| 9 | ;;;
|
|---|
| 10 | ;;; **********************************************************************
|
|---|
| 11 | ;;;
|
|---|
| [8428] | 12 | ;;; This file implements key-events for representing editor input.
|
|---|
| [6] | 13 | ;;;
|
|---|
| 14 | ;;; Written by Blaine Burks and Bill Chiles.
|
|---|
| 15 | ;;;
|
|---|
| 16 |
|
|---|
| [8428] | 17 | (in-package :hemlock-internals)
|
|---|
| 18 |
|
|---|
| 19 | |
|---|
| 20 |
|
|---|
| 21 | ;;; Objects involved in key events:
|
|---|
| 22 | ;;; (1) a KEY-EVENT describes a combination of a KEYSYM and MODIFIERS. KEY-EVENTS
|
|---|
| 23 | ;;; are interned, so there is a unique key-event for each combination of keysym and
|
|---|
| 24 | ;;; modifiers.
|
|---|
| 25 | ;;; (2) A KEYSYM is an object representing a key. It must be declared to be so via
|
|---|
| 26 | ;;; define-keysym. A KEYSYM must be defined before a key-event based on it can be
|
|---|
| 27 | ;;; defined.
|
|---|
| 28 | ;;; (3) A CODE is a system-dependent fixnum value for a KEYSYM. It must be defined
|
|---|
| 29 | ;;; before any events actually occur, but it doesn't need to be defined in order to
|
|---|
| [6] | 30 | ;;; create key-events.
|
|---|
| [8428] | 31 | ;;;
|
|---|
| 32 | ;;; The Keysym can be the same as a code, but separating them deals with a bootstrapping
|
|---|
| 33 | ;;; problem: keysyms cannot be defined before hemlock is loaded, but hemlock wants to
|
|---|
| 34 | ;;; define key events while it's loading. So we define key events using keysyms, and let
|
|---|
| [6] | 35 | ;;; their codes be defined later
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 | ;;;; Keysym <==> Name translation.
|
|---|
| 39 |
|
|---|
| 40 | ;;; Keysyms are named by case-insensitive names. However, if the name
|
|---|
| 41 | ;;; consists of a single character, the name is case-sensitive.
|
|---|
| 42 | ;;;
|
|---|
| 43 |
|
|---|
| 44 | ;;; This table maps a keysym to a list of names. The first name is the
|
|---|
| 45 | ;;; preferred printing name.
|
|---|
| 46 | ;;;
|
|---|
| 47 | (defvar *keysyms-to-names*)
|
|---|
| 48 |
|
|---|
| 49 | ;;; This table maps all keysym names to the appropriate keysym.
|
|---|
| 50 | ;;;
|
|---|
| 51 | (defvar *names-to-keysyms*)
|
|---|
| 52 |
|
|---|
| 53 | (declaim (inline name-keysym keysym-names keysym-preferred-name))
|
|---|
| 54 |
|
|---|
| 55 | (defun name-keysym (name)
|
|---|
| 56 | "This returns the keysym named name. If name is unknown, this returns nil."
|
|---|
| 57 | (gethash (get-name-case-right name) *names-to-keysyms*))
|
|---|
| 58 |
|
|---|
| 59 | (defun keysym-names (keysym)
|
|---|
| 60 | "This returns the list of all names for keysym. If keysym is undefined,
|
|---|
| [6703] | 61 | this returns nil."
|
|---|
| 62 | (or (gethash keysym *keysyms-to-names*)
|
|---|
| 63 | (let* ((name (char-name (code-char keysym))))
|
|---|
| 64 | (when name (setf (gethash keysym *keysyms-to-names*)
|
|---|
| [6] | 65 | (list name))))))
|
|---|
| 66 |
|
|---|
| 67 | (defun keysym-preferred-name (keysym)
|
|---|
| 68 | "This returns the preferred name for keysym, how it is typically printed.
|
|---|
| [6703] | 69 | If keysym is undefined, this returns nil."
|
|---|
| [6] | 70 | (car (keysym-names keysym)))
|
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 | |
|---|
| 74 |
|
|---|
| 75 | ;;;; Character key-event stuff.
|
|---|
| 76 |
|
|---|
| 77 | ;;; GET-NAME-CASE-RIGHT -- Internal.
|
|---|
| 78 | ;;;
|
|---|
| 79 | ;;; This returns the canonical string for a keysym name for use with
|
|---|
| 80 | ;;; hash tables.
|
|---|
| 81 | ;;;
|
|---|
| 82 | (defun get-name-case-right (string)
|
|---|
| [8428] | 83 | (if (= (length string) 1) string (string-downcase string)))
|
|---|
| [6] | 84 |
|
|---|
| 85 | ;;; DEFINE-KEYSYM -- Public
|
|---|
| 86 | ;;;
|
|---|
| 87 | (defun define-keysym (keysym preferred-name &rest other-names)
|
|---|
| 88 | "This establishes a mapping from preferred-name to keysym for purposes of
|
|---|
| 89 | specifying key-events in #k syntax. Other-names also map to keysym, but the
|
|---|
| 90 | system uses preferred-name when printing key-events. The names are
|
|---|
| 91 | case-insensitive simple-strings. Redefining a keysym or re-using names has
|
|---|
| 92 | undefined effects."
|
|---|
| 93 | (setf (gethash keysym *keysyms-to-names*) (cons preferred-name other-names))
|
|---|
| 94 | (dolist (name (cons preferred-name other-names))
|
|---|
| [8428] | 95 | (setf (gethash (get-name-case-right name) *names-to-keysyms*) keysym)))
|
|---|
| 96 |
|
|---|
| 97 | ;;; This is an a-list mapping native modifier bit masks to defined key-event
|
|---|
| [6] | 98 | ;;; modifier names.
|
|---|
| 99 | ;;;
|
|---|
| 100 | (defvar *modifier-translations*)
|
|---|
| 101 |
|
|---|
| 102 | ;;; This is an ordered a-list mapping defined key-event modifier names to the
|
|---|
| 103 | ;;; appropriate mask for the modifier. Modifier names have a short and a long
|
|---|
| 104 | ;;; version. For each pair of names for the same mask, the names are
|
|---|
| 105 | ;;; contiguous in this list, and the short name appears first.
|
|---|
| 106 | ;;; PRINT-PRETTY-KEY-EVENT and KEY-EVENT-BITS-MODIFIERS rely on this.
|
|---|
| 107 | ;;;
|
|---|
| 108 | (defvar *modifiers-to-internal-masks*)
|
|---|
| 109 |
|
|---|
| 110 |
|
|---|
| [6998] | 111 |
|
|---|
| [6] | 112 | |
|---|
| [6998] | 113 |
|
|---|
| 114 | (defvar *mouse-translation-info*)
|
|---|
| 115 |
|
|---|
| 116 | ;;; MOUSE-TRANSLATION-INFO -- Internal.
|
|---|
| 117 | ;;;
|
|---|
| 118 | ;;; This returns the requested information, :keysym or :shifted-modifier-name,
|
|---|
| [9200] | 119 | ;;; for the button cross event-key. If the information is undefined, this
|
|---|
| [6998] | 120 | ;;; signals an error.
|
|---|
| 121 | ;;;
|
|---|
| 122 | #+unused
|
|---|
| 123 | (defun mouse-translation-info (button event-key info)
|
|---|
| 124 | (let ((event-dispatch (svref *mouse-translation-info* button)))
|
|---|
| 125 | (unless event-dispatch
|
|---|
| 126 | (error "No defined mouse translation information for button ~S." button))
|
|---|
| 127 | (let ((data (ecase event-key
|
|---|
| 128 | (:button-press (button-press-info event-dispatch))
|
|---|
| 129 | (:button-release (button-release-info event-dispatch)))))
|
|---|
| 130 | (unless data
|
|---|
| 131 | (error
|
|---|
| 132 | "No defined mouse translation information for button ~S and event ~S."
|
|---|
| 133 | button event-key))
|
|---|
| [6] | 134 | (ecase info
|
|---|
| 135 | (:keysym (button-keysym data))
|
|---|
| [6998] | 136 | (:shifted-modifier-name (button-shifted-modifier-name data))))))
|
|---|
| 137 |
|
|---|
| 138 |
|
|---|
| 139 | (eval-when (:compile-toplevel :execute)
|
|---|
| 140 | (defmacro button-press-info (event-dispatch) `(car ,event-dispatch))
|
|---|
| 141 | (defmacro button-release-info (event-dispatch) `(cdr ,event-dispatch))
|
|---|
| 142 | (defmacro button-keysym (info) `(car ,info))
|
|---|
| 143 | (defmacro button-shifted-modifier-name (info) `(cdr ,info))
|
|---|
| 144 | )
|
|---|
| 145 |
|
|---|
| 146 | ;;; MOUSE-TRANSLATION-INFO -- Internal.
|
|---|
| 147 | ;;;
|
|---|
| 148 | ;;; This returns the requested information, :keysym or :shifted-modifier-name,
|
|---|
| 149 | ;;; for the button cross event-key. If the information is undefined, this
|
|---|
| 150 | ;;; signals an error.
|
|---|
| 151 | ;;;
|
|---|
| 152 | (defun mouse-translation-info (button event-key info)
|
|---|
| 153 | (let ((event-dispatch (svref *mouse-translation-info* button)))
|
|---|
| 154 | (unless event-dispatch
|
|---|
| 155 | (error "No defined mouse translation information for button ~S." button))
|
|---|
| 156 | (let ((data (ecase event-key
|
|---|
| 157 | (:button-press (button-press-info event-dispatch))
|
|---|
| 158 | (:button-release (button-release-info event-dispatch)))))
|
|---|
| 159 | (unless data
|
|---|
| 160 | (error
|
|---|
| 161 | "No defined mouse translation information for button ~S and event ~S."
|
|---|
| 162 | button event-key))
|
|---|
| 163 | (ecase info
|
|---|
| 164 | (:keysym (button-keysym data))
|
|---|
| 165 | (:shifted-modifier-name (button-shifted-modifier-name data))))))
|
|---|
| 166 |
|
|---|
| 167 | ;;; (setf MOUSE-TRANSLATION-INFO) -- Internal.
|
|---|
| 168 | ;;;
|
|---|
| 169 | ;;; This walks into *mouse-translation-info* the same way MOUSE-TRANSLATION-INFO
|
|---|
| 170 | ;;; does, filling in the data structure on an as-needed basis, and stores
|
|---|
| 171 | ;;; the value for the indicated info.
|
|---|
| 172 | ;;;
|
|---|
| 173 | (defun (setf mouse-translation-info) (value button event-key info)
|
|---|
| 174 | (let ((event-dispatch (svref *mouse-translation-info* button)))
|
|---|
| 175 | (unless event-dispatch
|
|---|
| 176 | (setf event-dispatch
|
|---|
| 177 | (setf (svref *mouse-translation-info* button) (cons nil nil))))
|
|---|
| 178 | (let ((data (ecase event-key
|
|---|
| 179 | (:button-press (button-press-info event-dispatch))
|
|---|
| 180 | (:button-release (button-release-info event-dispatch)))))
|
|---|
| 181 | (unless data
|
|---|
| 182 | (setf data
|
|---|
| 183 | (ecase event-key
|
|---|
| 184 | (:button-press
|
|---|
| 185 | (setf (button-press-info event-dispatch) (cons nil nil)))
|
|---|
| 186 | (:button-release
|
|---|
| 187 | (setf (button-release-info event-dispatch) (cons nil nil))))))
|
|---|
| 188 | (ecase info
|
|---|
| 189 | (:keysym
|
|---|
| 190 | (setf (button-keysym data) value))
|
|---|
| 191 | (:shifted-modifier-name
|
|---|
| 192 | (setf (button-shifted-modifier-name data) value))))))
|
|---|
| 193 |
|
|---|
| 194 |
|
|---|
| 195 |
|
|---|
| [8428] | 196 | ;;; DEFINE-MOUSE-KEYSYM -- Public.
|
|---|
| [6998] | 197 | ;;;
|
|---|
| 198 | (defun define-mouse-keysym (button keysym name shifted-bit event-key)
|
|---|
| 199 | "This defines keysym named name for the X button cross the X event-key."
|
|---|
| 200 | (unless (<= 1 button 5)
|
|---|
| 201 | (error "Buttons are number 1-5, not ~D." button))
|
|---|
| 202 | (setf (gethash keysym *keysyms-to-names*) (list name))
|
|---|
| 203 | (setf (gethash (get-name-case-right name) *names-to-keysyms*) keysym)
|
|---|
| 204 | (setf (mouse-translation-info button event-key :keysym) keysym)
|
|---|
| 205 | (setf (mouse-translation-info button event-key :shifted-modifier-name)
|
|---|
| [6] | 206 | shifted-bit))
|
|---|
| 207 |
|
|---|
| 208 |
|
|---|
| [778] | 209 | |
|---|
| 210 |
|
|---|
| [6] | 211 | ;;;; Stuff for parsing #k syntax.
|
|---|
| [778] | 212 |
|
|---|
| [6] | 213 |
|
|---|
| [8428] | 214 |
|
|---|
| [6] | 215 | (defstruct (key-event (:print-function %print-key-event)
|
|---|
| 216 | (:constructor %make-key-event (keysym bits)))
|
|---|
| 217 | (bits nil :type fixnum)
|
|---|
| 218 | (keysym nil))
|
|---|
| [8428] | 219 |
|
|---|
| [6] | 220 | (defun %print-key-event (object stream ignore)
|
|---|
| 221 | (declare (ignore ignore))
|
|---|
| 222 | (write-string "#<Key-Event " stream)
|
|---|
| 223 | (print-pretty-key object stream)
|
|---|
| 224 | (write-char #\> stream))
|
|---|
| [8428] | 225 |
|
|---|
| [6] | 226 | ;;; This maps Common Lisp CHAR-CODE's to character classes for parsing #k
|
|---|
| 227 | ;;; syntax.
|
|---|
| 228 | ;;;
|
|---|
| 229 | (defvar *key-character-classes* (make-array hemlock-char-code-limit
|
|---|
| 230 | :initial-element :other))
|
|---|
| 231 |
|
|---|
| 232 | ;;; These characters are special:
|
|---|
| 233 | ;;; #\< .......... :ISO-start - Signals start of an ISO character.
|
|---|
| 234 | ;;; #\> .......... :ISO-end - Signals end of an ISO character.
|
|---|
| 235 | ;;; #\- .......... :modifier-terminator - Indicates last *id-namestring*
|
|---|
| 236 | ;;; was a modifier.
|
|---|
| 237 | ;;; #\" .......... :EOF - Means we have come to the end of the character.
|
|---|
| 238 | ;;; #\{a-z, A-Z} .. :letter - Means the char is a letter.
|
|---|
| 239 | ;;; #\space ....... :event-terminator- Indicates the last *id-namestring*
|
|---|
| 240 | ;;; was a character name.
|
|---|
| 241 | ;;;
|
|---|
| 242 | ;;; Every other character has class :other.
|
|---|
| 243 | ;;;
|
|---|
| 244 | (hi::do-alpha-chars (char :both)
|
|---|
| 245 | (setf (svref *key-character-classes* (char-code char)) :letter))
|
|---|
| 246 | (setf (svref *key-character-classes* (char-code #\<)) :ISO-start)
|
|---|
| 247 | (setf (svref *key-character-classes* (char-code #\>)) :ISO-end)
|
|---|
| 248 | (setf (svref *key-character-classes* (char-code #\-)) :modifier-terminator)
|
|---|
| 249 | (setf (svref *key-character-classes* (char-code #\space)) :event-terminator)
|
|---|
| 250 | (setf (svref *key-character-classes* (char-code #\")) :EOF)
|
|---|
| 251 |
|
|---|
| 252 | ;;; This holds the characters built up while lexing a potential keysym or
|
|---|
| 253 | ;;; modifier identifier.
|
|---|
| 254 | ;;;
|
|---|
| 255 | (defvar *id-namestring*
|
|---|
| 256 | (make-array 30 :adjustable t :fill-pointer 0 :element-type 'base-char))
|
|---|
| 257 |
|
|---|
| 258 | ;;; PARSE-KEY-FUN -- Internal.
|
|---|
| 259 | ;;;
|
|---|
| [8428] | 260 | ;;; This is the #k dispatch macro character reader. It is a FSM that parses
|
|---|
| [6] | 261 | ;;; key specifications. It returns either a VECTOR form or a MAKE-KEY-EVENT
|
|---|
| 262 | ;;; form. Since key-events are unique at runtime, we cannot create them at
|
|---|
| 263 | ;;; readtime, returning the constant object from READ. Wherever a #k appears,
|
|---|
| 264 | ;;; there's a form that at loadtime or runtime will return the unique key-event
|
|---|
| 265 | ;;; or vector of unique key-events.
|
|---|
| 266 | ;;;
|
|---|
| 267 | (defun parse-key-fun (stream sub-char count)
|
|---|
| 268 | (declare (ignore sub-char count))
|
|---|
| 269 | (setf (fill-pointer *id-namestring*) 0)
|
|---|
| 270 | (prog ((bits 0)
|
|---|
| 271 | (key-event-list ())
|
|---|
| [8428] | 272 | char class)
|
|---|
| [6] | 273 | (unless (char= (read-char stream) #\")
|
|---|
| 274 | (error "Keys must be delimited by ~S." #\"))
|
|---|
| 275 | ;; Skip any leading spaces in the string.
|
|---|
| 276 | (peek-char t stream)
|
|---|
| 277 | (multiple-value-setq (char class) (get-key-char stream))
|
|---|
| 278 | (ecase class
|
|---|
| 279 | ((:letter :other :escaped) (go ID))
|
|---|
| 280 | (:ISO-start (go ISOCHAR))
|
|---|
| 281 | (:ISO-end (error "Angle brackets must be escaped."))
|
|---|
| 282 | (:modifier-terminator (error "Dash must be escaped."))
|
|---|
| 283 | (:EOF (error "No key to read.")))
|
|---|
| 284 | ID
|
|---|
| 285 | (vector-push-extend char *id-namestring*)
|
|---|
| 286 | (multiple-value-setq (char class) (get-key-char stream))
|
|---|
| 287 | (ecase class
|
|---|
| 288 | ((:letter :other :escaped) (go ID))
|
|---|
| 289 | (:event-terminator (go GOT-CHAR))
|
|---|
| 290 | (:modifier-terminator (go GOT-MODIFIER))
|
|---|
| 291 | ((:ISO-start :ISO-end) (error "Angle brackets must be escaped."))
|
|---|
| 292 | (:EOF (go GET-LAST-CHAR)))
|
|---|
| 293 | GOT-CHAR
|
|---|
| 294 | (push `(make-key-event ,(copy-seq *id-namestring*) ,bits)
|
|---|
| [8428] | 295 | key-event-list)
|
|---|
| [6] | 296 | (setf (fill-pointer *id-namestring*) 0)
|
|---|
| 297 | (setf bits 0)
|
|---|
| 298 | ;; Skip any whitespace between characters.
|
|---|
| 299 | (peek-char t stream)
|
|---|
| 300 | (multiple-value-setq (char class) (get-key-char stream))
|
|---|
| 301 | (ecase class
|
|---|
| 302 | ((:letter :other :escaped) (go ID))
|
|---|
| 303 | (:ISO-start (go ISOCHAR))
|
|---|
| 304 | (:ISO-end (error "Angle brackets must be escaped."))
|
|---|
| 305 | (:modifier-terminator (error "Dash must be escaped."))
|
|---|
| 306 | (:EOF (go FINAL)))
|
|---|
| 307 | GOT-MODIFIER
|
|---|
| 308 | (let ((modifier-name (car (assoc *id-namestring*
|
|---|
| 309 | *modifiers-to-internal-masks*
|
|---|
| 310 | :test #'string-equal))))
|
|---|
| 311 | (unless modifier-name
|
|---|
| 312 | (error "~S is not a defined modifier." *id-namestring*))
|
|---|
| 313 | (setf (fill-pointer *id-namestring*) 0)
|
|---|
| 314 | (setf bits (logior bits (key-event-modifier-mask modifier-name))))
|
|---|
| 315 | (multiple-value-setq (char class) (get-key-char stream))
|
|---|
| 316 | (ecase class
|
|---|
| 317 | ((:letter :other :escaped) (go ID))
|
|---|
| 318 | (:ISO-start (go ISOCHAR))
|
|---|
| 319 | (:ISO-end (error "Angle brackets must be escaped."))
|
|---|
| 320 | (:modifier-terminator (error "Dash must be escaped."))
|
|---|
| 321 | (:EOF (error "Expected something naming a key-event, got EOF.")))
|
|---|
| 322 | ISOCHAR
|
|---|
| 323 | (multiple-value-setq (char class) (get-key-char stream))
|
|---|
| 324 | (ecase class
|
|---|
| 325 | ((:letter :event-terminator :other :escaped)
|
|---|
| 326 | (vector-push-extend char *id-namestring*)
|
|---|
| 327 | (go ISOCHAR))
|
|---|
| 328 | (:ISO-start (error "Open Angle must be escaped."))
|
|---|
| 329 | (:modifier-terminator (error "Dash must be escaped."))
|
|---|
| 330 | (:EOF (error "Bad syntax in key specification, hit eof."))
|
|---|
| 331 | (:ISO-end (go GOT-CHAR)))
|
|---|
| 332 | GET-LAST-CHAR
|
|---|
| 333 | (push `(make-key-event ,(copy-seq *id-namestring*) ,bits)
|
|---|
| 334 | key-event-list)
|
|---|
| 335 | FINAL
|
|---|
| 336 | (return (if (cdr key-event-list)
|
|---|
| 337 | `(vector ,@(nreverse key-event-list))
|
|---|
| 338 | `,(car key-event-list)))))
|
|---|
| 339 |
|
|---|
| 340 | (set-dispatch-macro-character #\# #\k #'parse-key-fun)
|
|---|
| 341 |
|
|---|
| 342 | (defconstant key-event-escape-char #\\
|
|---|
| 343 | "The escape character that #k uses.")
|
|---|
| 344 |
|
|---|
| 345 | ;;; GET-KEY-CHAR -- Internal.
|
|---|
| 346 | ;;;
|
|---|
| 347 | ;;; This is used by PARSE-KEY-FUN.
|
|---|
| 348 | ;;;
|
|---|
| 349 | (defun get-key-char (stream)
|
|---|
| 350 | (let ((char (read-char stream t nil t)))
|
|---|
| 351 | (cond ((char= char key-event-escape-char)
|
|---|
| 352 | (let ((char (read-char stream t nil t)))
|
|---|
| 353 | (values char :escaped)))
|
|---|
| 354 | (t (values char (svref *key-character-classes* (char-code char)))))))
|
|---|
| 355 |
|
|---|
| 356 |
|
|---|
| 357 | |
|---|
| 358 |
|
|---|
| 359 | ;;;; Code to deal with modifiers.
|
|---|
| 360 |
|
|---|
| 361 | (defvar *modifier-count* 0
|
|---|
| 362 | "The number of modifiers that is currently defined.")
|
|---|
| 363 |
|
|---|
| 364 | (eval-when (:compile-toplevel :execute :load-toplevel)
|
|---|
| 365 |
|
|---|
| 366 | (defconstant modifier-count-limit 6
|
|---|
| 367 | "The maximum number of modifiers supported.")
|
|---|
| 368 |
|
|---|
| 369 | ); eval-when
|
|---|
| 370 |
|
|---|
| 371 | ;;; This is purely a list for users.
|
|---|
| 372 | ;;;
|
|---|
| 373 | (defvar *all-modifier-names* ()
|
|---|
| 374 | "A list of all the names of defined modifiers.")
|
|---|
| 375 |
|
|---|
| 376 | ;;; Note that short-name is pushed into *modifiers-to-internal-masks* after
|
|---|
| 377 | ;;; long-name. PRINT-PRETTY-KEY-EVENT and KEY-EVENT-BITS-MODIFIERS rely on
|
|---|
| 378 | ;;; this feature.
|
|---|
| 379 | ;;;
|
|---|
| 380 | (defun define-key-event-modifier (long-name short-name)
|
|---|
| 381 | "This establishes long-name and short-name as modifier names for purposes
|
|---|
| 382 | of specifying key-events in #k syntax. The names are case-insensitive and
|
|---|
| 383 | must be strings. If either name is already defined, this signals an error."
|
|---|
| 384 | (when (= *modifier-count* modifier-count-limit)
|
|---|
| 385 | (error "Maximum of ~D modifiers allowed." modifier-count-limit))
|
|---|
| 386 | (let ((long-name (string-capitalize long-name))
|
|---|
| 387 | (short-name (string-capitalize short-name)))
|
|---|
| 388 | (flet ((frob (name)
|
|---|
| 389 | (when (assoc name *modifiers-to-internal-masks*
|
|---|
| 390 | :test #'string-equal)
|
|---|
| 391 | (restart-case
|
|---|
| 392 | (error "Modifier name has already been defined -- ~S" name)
|
|---|
| 393 | (blow-it-off ()
|
|---|
| 394 | :report "Go on without defining this modifier."
|
|---|
| 395 | (return-from define-key-event-modifier nil))))))
|
|---|
| 396 | (frob long-name)
|
|---|
| 397 | (frob short-name))
|
|---|
| 398 | (unwind-protect
|
|---|
| 399 | (let ((new-bits (ash 1 *modifier-count*)))
|
|---|
| 400 | (push (cons long-name new-bits) *modifiers-to-internal-masks*)
|
|---|
| 401 | (push (cons short-name new-bits) *modifiers-to-internal-masks*)
|
|---|
| 402 | (pushnew long-name *all-modifier-names* :test #'string-equal)
|
|---|
| 403 | ;; Sometimes the long-name is the same as the short-name.
|
|---|
| 404 | (pushnew short-name *all-modifier-names* :test #'string-equal))
|
|---|
| 405 | (incf *modifier-count*))))
|
|---|
| 406 |
|
|---|
| [8428] | 407 | ;;;
|
|---|
| [6] | 408 | ;;; RE-INITIALIZE-KEY-EVENTS at the end of this file defines the system
|
|---|
| [8428] | 409 | ;;; default key-event modifiers.
|
|---|
| 410 | ;;;
|
|---|
| [6] | 411 |
|
|---|
| 412 | ;;; DEFINE-MODIFIER-BIT -- Public.
|
|---|
| 413 | ;;;
|
|---|
| [8428] | 414 | (defun define-modifier-bit (bit-mask modifier-name)
|
|---|
| [6] | 415 | "This establishes a mapping from bit-mask to a define key-event modifier-name."
|
|---|
| 416 | (let ((map (assoc modifier-name *modifiers-to-internal-masks*
|
|---|
| 417 | :test #'string-equal)))
|
|---|
| [8428] | 418 | (unless map (error "~S an undefined modifier name." modifier-name))
|
|---|
| [6] | 419 | (push (cons bit-mask (car map)) *modifier-translations*)))
|
|---|
| 420 |
|
|---|
| 421 | ;;;
|
|---|
| 422 | ;;; RE-INITIALIZE-KEY-EVENTS at the end of this file defines the system
|
|---|
| 423 | ;;; default modifiers, mapping them to some system default key-event
|
|---|
| 424 | ;;; modifiers.
|
|---|
| 425 | ;;;
|
|---|
| 426 |
|
|---|
| 427 | (defun make-key-event-bits (&rest modifier-names)
|
|---|
| 428 | "This returns bits suitable for MAKE-KEY-EVENT from the supplied modifier
|
|---|
| 429 | names. If any name is undefined, this signals an error."
|
|---|
| 430 | (let ((mask 0))
|
|---|
| 431 | (dolist (mod modifier-names mask)
|
|---|
| 432 | (let ((this-mask (cdr (assoc mod *modifiers-to-internal-masks*
|
|---|
| 433 | :test #'string-equal))))
|
|---|
| 434 | (unless this-mask (error "~S is an undefined modifier name." mod))
|
|---|
| 435 | (setf mask (logior mask this-mask))))))
|
|---|
| 436 |
|
|---|
| 437 | ;;; KEY-EVENT-BITS-MODIFIERS -- Public.
|
|---|
| 438 | ;;;
|
|---|
| 439 | (defun key-event-bits-modifiers (bits)
|
|---|
| 440 | "This returns a list of key-event modifier names, one for each modifier
|
|---|
| 441 | set in bits."
|
|---|
| 442 | (let ((res nil))
|
|---|
| 443 | (do ((map (cdr *modifiers-to-internal-masks*) (cddr map)))
|
|---|
| 444 | ((null map) res)
|
|---|
| 445 | (when (logtest bits (cdar map))
|
|---|
| 446 | (push (caar map) res)))))
|
|---|
| 447 |
|
|---|
| 448 | ;;; KEY-EVENT-MODIFIER-MASK -- Public.
|
|---|
| 449 | ;;;
|
|---|
| 450 | (defun key-event-modifier-mask (modifier-name)
|
|---|
| 451 | "This function returns a mask for modifier-name. This mask is suitable
|
|---|
| 452 | for use with KEY-EVENT-BITS. If modifier-name is undefined, this signals
|
|---|
| 453 | an error."
|
|---|
| 454 | (let ((res (cdr (assoc modifier-name *modifiers-to-internal-masks*
|
|---|
| 455 | :test #'string-equal))))
|
|---|
| 456 | (unless res (error "Undefined key-event modifier -- ~S." modifier-name))
|
|---|
| 457 | res))
|
|---|
| [8428] | 458 |
|
|---|
| [6] | 459 |
|
|---|
| [8428] | 460 | |
|---|
| [6] | 461 |
|
|---|
| 462 | ;;;; Key event lookup -- GET-KEY-EVENT and MAKE-KEY-EVENT.
|
|---|
| 463 |
|
|---|
| 464 | (defvar *key-events*)
|
|---|
| 465 |
|
|---|
| 466 | ;;; GET-KEY-EVENT* -- Internal.
|
|---|
| 467 | ;;;
|
|---|
| [8428] | 468 | ;;; This finds the key-event specified by keysym and bits. If the key-event
|
|---|
| [7052] | 469 | ;;; does not already exist, this creates it. This assumes keysym is defined,
|
|---|
| 470 | ;;; and if it isn't, this will make a key-event anyway that will cause an
|
|---|
| 471 | ;;; error when the system tries to print it.
|
|---|
| 472 | ;;;
|
|---|
| 473 | (defun get-key-event* (keysym bits)
|
|---|
| [8428] | 474 | (let* ((char (and (fixnump keysym) (code-char keysym))))
|
|---|
| 475 | (when (and char (standard-char-p char))
|
|---|
| 476 | (let* ((mask (key-event-modifier-mask "Shift")))
|
|---|
| [6] | 477 | (when (logtest bits mask)
|
|---|
| 478 | (setq bits (logandc2 bits mask)
|
|---|
| [8428] | 479 | keysym (char-code (char-upcase char)))))))
|
|---|
| 480 | (let* ((data (cons keysym bits)))
|
|---|
| 481 | (or (gethash data *key-events*)
|
|---|
| 482 | (setf (gethash data *key-events*) (%make-key-event keysym bits)))))
|
|---|
| 483 |
|
|---|
| 484 | ;;;
|
|---|
| 485 | (defvar *keysym-to-code*)
|
|---|
| 486 | (defvar *code-to-keysym*)
|
|---|
| 487 |
|
|---|
| 488 | (defmacro define-keysym-code (keysym code)
|
|---|
| 489 | `(progn
|
|---|
| 490 | (setf (gethash ,keysym *keysym-to-code*) ,code)
|
|---|
| 491 | (setf (gethash ,code *code-to-keysym*) ,keysym)))
|
|---|
| 492 |
|
|---|
| 493 | (defun keysym-for-code (code)
|
|---|
| [6] | 494 | (or (gethash code *code-to-keysym*) code))
|
|---|
| 495 |
|
|---|
| 496 | (defun code-for-keysym (keysym)
|
|---|
| 497 | (or (gethash keysym *keysym-to-code*) (and (fixnump keysym) keysym)))
|
|---|
| 498 |
|
|---|
| 499 | ;;;
|
|---|
| 500 | (defun make-key-event (object &optional (bits 0))
|
|---|
| [8428] | 501 | "This returns a key-event described by object with bits. Object is one of
|
|---|
| 502 | keysym, string, or key-event. When object is a key-event, this uses
|
|---|
| 503 | KEY-EVENT-KEYSYM. You can form bits with MAKE-KEY-EVENT-BITS or
|
|---|
| 504 | KEY-EVENT-MODIFIER-MASK."
|
|---|
| [6] | 505 | (etypecase object
|
|---|
| 506 | (integer
|
|---|
| 507 | (let ((keysym (keysym-for-code object)))
|
|---|
| 508 | (unless (keysym-names keysym)
|
|---|
| 509 | (error "~S is an undefined code." object))
|
|---|
| 510 | (get-key-event* keysym bits)))
|
|---|
| 511 | #|(character
|
|---|
| 512 | (let* ((name (char-name object))
|
|---|
| 513 | (keysym (name-keysym (or name (string object)))))
|
|---|
| 514 | (unless keysym
|
|---|
| 515 | (error "~S is an undefined keysym." object))
|
|---|
| 516 | (get-key-event* keysym bits)))|#
|
|---|
| 517 | (string
|
|---|
| 518 | (let ((keysym (name-keysym object)))
|
|---|
| 519 | (unless keysym
|
|---|
| 520 | (error "~S is an undefined keysym." object))
|
|---|
| 521 | (get-key-event* keysym bits)))
|
|---|
| 522 | (key-event
|
|---|
| 523 | (get-key-event* (key-event-keysym object) bits))))
|
|---|
| 524 |
|
|---|
| 525 | ;;; KEY-EVENT-BIT-P -- Public.
|
|---|
| 526 | ;;;
|
|---|
| 527 | (defun key-event-bit-p (key-event bit-name)
|
|---|
| 528 | "This returns whether key-event has the bit set named by bit-name. This
|
|---|
| 529 | signals an error if bit-name is undefined."
|
|---|
| 530 | (let ((mask (cdr (assoc bit-name *modifiers-to-internal-masks*
|
|---|
| 531 | :test #'string-equal))))
|
|---|
| 532 | (unless mask
|
|---|
| 533 | (error "~S is not a defined modifier." bit-name))
|
|---|
| 534 | (not (zerop (logand (key-event-bits key-event) mask)))))
|
|---|
| 535 |
|
|---|
| 536 |
|
|---|
| 537 | |
|---|
| 538 |
|
|---|
| 539 | ;;;; KEY-EVENT-CHAR and CHAR-KEY-EVENT.
|
|---|
| 540 |
|
|---|
| 541 | ;;; This maps key-events to characters. Users modify this by SETF'ing
|
|---|
| [6703] | 542 | ;;; KEY-EVENT-CHAR.
|
|---|
| [8428] | 543 | ;;;
|
|---|
| [6] | 544 | (defvar *key-event-characters*)
|
|---|
| 545 |
|
|---|
| 546 | (defun key-event-char (key-event)
|
|---|
| 547 | "Returns the character associated with key-event. This is SETF'able."
|
|---|
| 548 | (check-type key-event key-event)
|
|---|
| 549 | (or (gethash key-event *key-event-characters*)
|
|---|
| 550 | (code-char (code-for-keysym (key-event-keysym key-event)))))
|
|---|
| 551 |
|
|---|
| 552 | (defun %set-key-event-char (key-event character)
|
|---|
| 553 | (check-type character character)
|
|---|
| 554 | (check-type key-event key-event)
|
|---|
| 555 | (setf (gethash key-event *key-event-characters*) character))
|
|---|
| 556 | ;;;
|
|---|
| 557 | (defsetf key-event-char %set-key-event-char)
|
|---|
| 558 |
|
|---|
| 559 |
|
|---|
| 560 | ;;; This maps characters to key-events. Users modify this by SETF'ing
|
|---|
| 561 | ;;; CHAR-KEY-EVENT.
|
|---|
| 562 | ;;;
|
|---|
| 563 | (defvar *character-key-events*)
|
|---|
| 564 |
|
|---|
| 565 | (defun char-key-event (char)
|
|---|
| 566 | "Returns the key-event associated with char. This is SETF'able."
|
|---|
| 567 | (check-type char character)
|
|---|
| 568 | (svref *character-key-events* (char-code char)))
|
|---|
| 569 |
|
|---|
| 570 | (defun %set-char-key-event (char key-event)
|
|---|
| 571 | (check-type char character)
|
|---|
| 572 | (check-type key-event key-event)
|
|---|
| 573 | (setf (svref *character-key-events* (char-code char)) key-event))
|
|---|
| 574 | ;;;
|
|---|
| 575 | (defsetf char-key-event %set-char-key-event)
|
|---|
| 576 |
|
|---|
| 577 |
|
|---|
| 578 | |
|---|
| 579 |
|
|---|
| 580 | ;;;; DO-ALPHA-KEY-EVENTS.
|
|---|
| 581 |
|
|---|
| 582 | (defmacro alpha-key-events-loop (var start-keysym end-keysym result body)
|
|---|
| 583 | (let ((n (gensym)))
|
|---|
| 584 | `(do ((,n ,start-keysym (1+ ,n)))
|
|---|
| 585 | ((> ,n ,end-keysym) ,result)
|
|---|
| 586 | (let ((,var (make-key-event ,n 0)))
|
|---|
| 587 | (when (alpha-char-p (key-event-char ,var))
|
|---|
| 588 | ,@body)))))
|
|---|
| 589 |
|
|---|
| 590 | (defmacro do-alpha-key-events ((var kind &optional result) &rest forms)
|
|---|
| 591 | "(DO-ALPHA-KEY-EVENTS (var kind [result]) {form}*)
|
|---|
| 592 | This macro evaluates each form with var bound to a key-event representing an
|
|---|
| 593 | alphabetic character. Kind is one of :lower, :upper, or :both, and this
|
|---|
| 594 | binds var to each key-event in order as specified in the X11 protocol
|
|---|
| 595 | specification. When :both is specified, this processes lowercase letters
|
|---|
| 596 | first."
|
|---|
| 597 | (case kind
|
|---|
| 598 | (:both
|
|---|
| 599 | `(progn (alpha-key-events-loop ,var 97 122 nil ,forms)
|
|---|
| 600 | (alpha-key-events-loop ,var 65 90 ,result ,forms)))
|
|---|
| 601 | (:lower
|
|---|
| 602 | `(alpha-key-events-loop ,var 97 122 ,result ,forms))
|
|---|
| 603 | (:upper
|
|---|
| [8428] | 604 | `(alpha-key-events-loop ,var 65 90 ,result ,forms))
|
|---|
| [6] | 605 | (t (error "Kind argument not one of :lower, :upper, or :both -- ~S."
|
|---|
| 606 | kind))))
|
|---|
| 607 |
|
|---|
| 608 |
|
|---|
| 609 | |
|---|
| 610 |
|
|---|
| 611 | ;;;; PRINT-PRETTY-KEY and PRINT-PRETTY-KEY-EVENT.
|
|---|
| 612 |
|
|---|
| 613 | ;;; PRINT-PRETTY-KEY -- Internal
|
|---|
| 614 | ;;;
|
|---|
| 615 | (defun print-pretty-key (key &optional (stream *standard-output*) long-names-p)
|
|---|
| 616 | "This prints key, a key-event or vector of key-events, to stream in a
|
|---|
| 617 | user-expected fashion. Long-names-p indicates whether modifiers should
|
|---|
| 618 | print with their long or short name."
|
|---|
| [8428] | 619 | (etypecase key
|
|---|
| [6] | 620 | (key-event (print-pretty-key-event key stream long-names-p))
|
|---|
| 621 | (vector
|
|---|
| 622 | (let ((length-1 (1- (length key))))
|
|---|
| 623 | (dotimes (i (length key))
|
|---|
| 624 | (let ((key-event (aref key i)))
|
|---|
| 625 | (print-pretty-key-event key-event stream long-names-p)
|
|---|
| 626 | (unless (= i length-1) (write-char #\space stream))))))))
|
|---|
| 627 |
|
|---|
| 628 | ;;; PRINT-PRETTY-KEY-EVENT -- Internal
|
|---|
| 629 | ;;;
|
|---|
| 630 | ;;; Note, this makes use of the ordering in the a-list
|
|---|
| 631 | ;;; *modifiers-to-internal-masks* by CDDR'ing down it by starting on a short
|
|---|
| 632 | ;;; name or a long name.
|
|---|
| 633 | ;;;
|
|---|
| 634 | (defun print-pretty-key-event (key-event &optional (stream *standard-output*)
|
|---|
| 635 | long-names-p)
|
|---|
| 636 | "This prints key-event to stream. Long-names-p indicates whether modifier
|
|---|
| 637 | names should appear using the long name or short name."
|
|---|
| 638 | (do ((map (if long-names-p
|
|---|
| 639 | (cdr *modifiers-to-internal-masks*)
|
|---|
| 640 | *modifiers-to-internal-masks*)
|
|---|
| 641 | (cddr map)))
|
|---|
| 642 | ((null map))
|
|---|
| [8428] | 643 | (when (not (zerop (logand (cdar map) (key-event-bits key-event))))
|
|---|
| 644 | (write-string (caar map) stream)
|
|---|
| 645 | (write-char #\- stream)))
|
|---|
| 646 | (let* ((name (keysym-preferred-name (key-event-keysym key-event)))
|
|---|
| 647 | (spacep (position #\space (the simple-string name))))
|
|---|
| [6] | 648 | (when spacep (write-char #\< stream))
|
|---|
| 649 | (write-string name stream)
|
|---|
| 650 | (when spacep (write-char #\> stream))))
|
|---|
| 651 |
|
|---|
| 652 | ;;; PRETTY-KEY-STRING - Public.
|
|---|
| 653 | ;;;
|
|---|
| 654 | (defun pretty-key-string (key &optional long-names-p)
|
|---|
| 655 | (with-output-to-string (s)
|
|---|
| [8428] | 656 | (print-pretty-key key s long-names-p)))
|
|---|
| [6] | 657 | |
|---|
| 658 |
|
|---|
| 659 | ;;;; Re-initialization.
|
|---|
| 660 |
|
|---|
| 661 | ;;; RE-INITIALIZE-KEY-EVENTS -- Internal.
|
|---|
| 662 | ;;;
|
|---|
| 663 | (defun re-initialize-key-events ()
|
|---|
| [8428] | 664 | "This blows away all data associated with keysyms, modifiers, mouse
|
|---|
| 665 | translations, and key-event/characters mapping. Then it re-establishes
|
|---|
| [6] | 666 | the system defined key-event modifiers and the system defined
|
|---|
| 667 | modifier mappings to some of those key-event modifiers.
|
|---|
| [6998] | 668 |
|
|---|
| [6] | 669 | When recompiling this file, you should load it and call this function
|
|---|
| 670 | before using any part of the key-event interface, especially before
|
|---|
| [8428] | 671 | defining all your keysyms and using #k syntax."
|
|---|
| [6] | 672 | (setf *keysyms-to-names* (make-hash-table :test #'eql))
|
|---|
| 673 | (setf *names-to-keysyms* (make-hash-table :test #'equal))
|
|---|
| [8428] | 674 | (setf *keysym-to-code* (make-hash-table :test #'eql))
|
|---|
| [6] | 675 | (setf *code-to-keysym* (make-hash-table :test #'eql))
|
|---|
| 676 | (setf *modifier-translations* ())
|
|---|
| 677 | (setf *modifiers-to-internal-masks* ())
|
|---|
| 678 | (setf *mouse-translation-info* (make-array 6 :initial-element nil))
|
|---|
| 679 | (setf *modifier-count* 0)
|
|---|
| 680 | (setf *all-modifier-names* ())
|
|---|
| 681 | (setf *key-events* (make-hash-table :test #'equal))
|
|---|
| 682 | (setf *key-event-characters* (make-hash-table))
|
|---|
| [7595] | 683 | (setf *character-key-events*
|
|---|
| [6] | 684 | (make-array hemlock-char-code-limit :initial-element nil))
|
|---|
| 685 |
|
|---|
| 686 | (define-key-event-modifier "Hyper" "H")
|
|---|
| 687 | (define-key-event-modifier "Super" "S")
|
|---|
| 688 | (define-key-event-modifier "Meta" "M")
|
|---|
| 689 | (define-key-event-modifier "Control" "C")
|
|---|
| 690 | (define-key-event-modifier "Shift" "Shift")
|
|---|
| 691 | (define-key-event-modifier "Lock" "Lock")
|
|---|
| 692 |
|
|---|
| 693 | )
|
|---|
| 694 |
|
|---|
| 695 | ;;; Initialize stuff if not already initialized.
|
|---|
| 696 | ;;;
|
|---|
| 697 | (unless (boundp '*keysyms-to-names*)
|
|---|
| 698 | (re-initialize-key-events))
|
|---|