Changeset 3245

Show
Ignore:
Timestamp:
06/02/08 12:10:28 (7 months ago)
Author:
hans
Message:

Add mapping for all keys.
Create PDF with layout.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/projects/symbolics-keyboard/make-keymap.lisp

    r3236 r3245  
     1;; -*- Lisp -*- 
     2 
     3;; Layout generation tools for Symbolics kbdbabel. 
     4 
     5;; MAKE-KEYMAP generates a keymap suitable to be included in the kbdbabel assembler source 
     6;; DRAW-KEYBOARD generates a PDF file documenting the mapping as generated 
     7 
     8;; Depends on :CL-PDF, :ALEXANDRIA and :CL-PPCRE 
     9 
     10;; Written 2008 by Hans Huebner 
     11;; Placed in the public domain 
    112 
    213(in-package :cl-user) 
     14 
     15(defpackage :symbolics-keyboard 
     16  (:nicknames "SKBD") 
     17  (:use :cl :alexandria)) 
     18 
     19(in-package :symbolics-keyboard) 
     20 
     21(defparameter *key-map* 
     22  '(("Select"           "F1") 
     23    ("Network"          "F2") 
     24    ("Function"         "F3") 
     25    ("Suspend"          "F4") 
     26    ("Resume"           "F5") 
     27    ("Abort"            "F6") 
     28    ("SuperL"           "F7") 
     29    ("HyperL"           "F8") 
     30    ("Scroll"           "F9"    "PgDn") 
     31    ("ClearInput"       "F10") 
     32    ("SymbolR"          "KP5"   "Up") 
     33    ("Scroll"           "KP3"   "Scroll") 
     34    ("RubOut"           "Del") 
     35    ("Complete"         "F11"   "Home") 
     36    ("Help"             "F12") 
     37    ("End"              "KP1"   "End") 
     38    ("MetaL"            "AltL") 
     39    ("MetaR"            "AltGr" "Left") 
     40    ("SuperR"           "KP."   "Down") 
     41    ("HyperR"           "KP+"   "Right") 
     42    ("Repeat"           "KP/"   "PgUp") 
     43    ("ControlL"         "CtrlL") 
     44    ("ControlR"         "CtrlR") 
     45    ("("                "[") 
     46    (")"                "]") 
     47    ("Triangle"         "KP2") 
     48    ("Circle"           "KP3") 
     49    ("Square"           "KP4") 
     50    ("Refresh"          "KP0") 
     51    ("Page"             "KP6") 
     52    ("Line"             "KP7") 
     53    ("SymbolL"          "KP8") 
     54    ("|"                "KP-") 
     55    (":"                "KP*") 
     56    ("CapsLock"         "Caps")) 
     57  "Mappings for keys.  By default, Symbolics keys which have the same 
     58  name (keycap label) as a PS/2 key are mapped to that corresponding 
     59  key.  Before the default mapping is considered, this list of lists 
     60  is checked for an explicit definition.  Each list consists 
     61  of (KEYNAME PS2-KEYNAME [ F-MODE-PS2-KEYNAME ] ) with KEYNAME being 
     62  the name of the Symbolics key, PS2-KEYNAME the name of the PS/2 key 
     63  name whose PS/2 scancode should be sent and F-MODE-PS2-KEYNAME being 
     64  the name of the PS/2 key whose PS/2 scancode should be sent in 
     65  F-mode.  PS2-KEYNAME may be NIL to indicate that no PS/2 scancode is 
     66  associated to the key when not in F-Mode.  F-MODE-PS2-KEYNAME 
     67  defaults to PS2-KEYNAME if not specified.") 
    368 
    469(defparameter *ps2-map* 
     
    65130    ("Caps"             #x58) 
    66131    ("ShiftR"           #x59) 
     132    ("'y"               #x52) 
    67133    ("Return"           #x5a) 
    68134    ("]"                #x5b) 
     
    104170 
    105171(defparameter *symbolics-map* 
    106   '(("Local"            #x01    0 3 2) 
    107     ("Caps"             #x02    0 1) 
     172  '(("Function"         #x43    0 5 2) 
     173    ("Escape"           #x6f    1 5 2) 
     174    ("Refresh"          #x70    2 5 2) 
     175    ("Square"           #x71    3 5 2) 
     176    ("Circle"           #x72    4 5 2) 
     177    ("Triangle"         #x73    5 5 2) 
     178    ("ClearInput"       #x74    6 5 2) 
     179    ("Suspend"          #x75    7 5 2) 
     180    ("Resume"           #x76    8 5 2) 
     181    ("Abort"            #x1e    9 5 2) 
     182    ("Network"          #x38    0 4 2) 
     183    (":"                #x59    1 4) 
     184    (("1" "!")          #x64    2 4) 
     185    (("2" "@")          #x5a    3 4) 
     186    (("3" "#")          #x65    4 4) 
     187    (("4" "$")          #x5b    5 4) 
     188    (("5" "%")          #x66    6 4) 
     189    (("6" "^")          #x5c    7 4) 
     190    (("7" "&")          #x67    8 4) 
     191    (("8" "*")          #x5d    9 4) 
     192    (("9" "(")          #x68    10 4) 
     193    (("0" ")")          #x5e    11 4) 
     194    (("-" "_")          #x69    12 4) 
     195    (("=" "+")          #x5f    13 4) 
     196    (("`" "~")          #x6a    14 4) 
     197    (("\\" "{")         #x60    15 4) 
     198    (("|" "}")          #x6b    16 4) 
     199    ("Help"             #x29    17 4 2) 
     200    ("Local"            #x01    0 3 2) 
     201    ("Tab"              #x4e    1 3 1.5) 
     202    ("Q"                #x4f    2 3) 
     203    ("W"                #x44    3 3) 
     204    ("E"                #x50    4 3) 
     205    ("R"                #x45    5 3) 
     206    ("T"                #x51    6 3) 
     207    ("Y"                #x46    7 3) 
     208    ("U"                #x52    8 3) 
     209    ("I"                #x47    9 3) 
     210    ("O"                #x53    10 3) 
     211    ("P"                #x48    11 3) 
     212    (("(" "[")          #x54    12 3) 
     213    ((")" "]")          #x49    13 3) 
     214    ("BackSpace"        #x55    14 3) 
     215    ("Page"             #x4a    15 3 1.5) 
     216    ("Complete"         #x34    16 3 2) 
     217    ("Select"           #x0c    0 2 2) 
     218    ("RubOut"           #x2d    1 2 1.75) 
     219    ("A"                #x39    2 2) 
     220    ("S"                #x2e    3 2) 
     221    ("D"                #x3a    4 2) 
     222    ("F"                #x2f    5 2) 
     223    ("G"                #x3b    6 2) 
     224    ("H"                #x30    7 2) 
     225    ("J"                #x3c    8 2) 
     226    ("K"                #x31    9 2) 
     227    ("L"                #x3d    10 2) 
     228    ((";" ":")          #x32    11 2) 
     229    (("'" "\"")         #x3e    12 2) 
     230    ("Return"           #x33    13 2 2) 
     231    ("Line"             #x3f    14 2 1.25) 
     232    ("End"              #x13    15 2 2) 
     233    ("CapsLock"         #x02    0 1) 
     234    ("SymbolL"          #x0d    1 1 1.25) 
     235    ("ShiftL"           #x22    2 1 2) 
     236    ("Z"                #x17    3 1) 
     237    ("X"                #x23    4 1) 
     238    ("C"                #x18    5 1) 
     239    ("V"                #x24    6 1) 
     240    ("B"                #x19    7 1) 
     241    ("N"                #x25    8 1) 
     242    ("M"                #x1a    9 1) 
     243    (("," "<")          #x26    10 1) 
     244    (("." ">")          #x1b    11 1) 
     245    (("/" "?")          #x27    12 1) 
     246    ("ShiftR"           #x1c    13 1 2) 
     247    ("SymbolR"          #x28    14 1 1.25) 
     248    ("Repeat"           #x1d    15 1 1.25) 
     249    ("ModeLock"         #x08    16 1 1.25) 
    108250    ("HyperL"           #x03    0 0) 
     251    ("SuperL"           #x0e    1 0) 
    109252    ("MetaL"            #x04    2 0) 
     253    ("ControlL"         #x0f    3 0 2) 
     254    ("Space"            #x10    4 0 8.5) 
    110255    ("ControlR"         #x05    5 0 2) 
     256    ("MetaR"            #x11    6 0) 
    111257    ("SuperR"           #x06    7 0) 
    112     ("Scroll"           #x07    9 0 1.5) 
    113     ("ModeLock"         #x08    16 1 1.5) 
    114     ("Select"           #x0c    0 2 2) 
    115     ("SymbolL"          #x0d    1 1 1.5) 
    116     ("SuperL"           #x0e    1 0) 
    117     ("ControlL"         #x0f    3 0 2) 
    118     ("Space"            #x10    4 0 9) 
    119     ("MetaR"            #x11    6 0) 
    120     ("HyperR"           #x12    7 0) 
    121     ("End"              #x13    15 2 0) 
    122     ("Z"                #x17    3 1) 
    123     ("C"                #x18    5 1) 
    124     ("B"                #x19    7 1) 
    125     ("M"                #x1a    9 1) 
    126     ("."                #x1b    11 1) 
    127     ("ShiftR"           #x1c    13 1 2) 
    128     ("Repeat"           #x1d    15 1 1.5) 
    129     ("Abort"            #x1e    9 5) 
    130     ("ShiftL"           #x22    2 1 2) 
    131     ("X"                #x23    4 1) 
    132     ("V"                #x24    6 1) 
    133     ("N"                #x25    8 1) 
    134     (","                #x26    10 1) 
    135     ("/"                #x27    12 1) 
    136     ("SymbolR"          #x28    14 1 1.5) 
    137     ("Help"             #x29    17 4 2) 
    138     ("RubOut"           #x2d    1 2 1.75) 
    139     ("S"                #x2e    3 2) 
    140     ("F"                #x2f    5 2) 
    141     ("H"                #x30    7 2) 
    142     ("K"                #x31    9 2) 
    143     (";"                #x32    11 2) 
    144     ("Return"           #x33    13 2) 
    145     ("Complete"         #x34    16 3 2) 
    146     ("Network"          #x38    0 4 2) 
    147     ("A"                #x39    2 2) 
    148     ("D"                #x3a    4 2) 
    149     ("G"                #x3b    6 2) 
    150     ("J"                #x3c    8 2) 
    151     ("L"                #x3d    10 2) 
    152     ("'"                #x3e) 
    153     ("Line"             #x3f) 
    154     ("Function"         #x43) 
    155     ("W"                #x44) 
    156     ("R"                #x45) 
    157     ("Y"                #x46) 
    158     ("I"                #x47) 
    159     ("P"                #x48) 
    160     (")"                #x49) 
    161     ("Page"             #x4a) 
    162     ("Tab"              #x4e) 
    163     ("Q"                #x4f) 
    164     ("E"                #x50) 
    165     ("T"                #x51) 
    166     ("U"                #x52) 
    167     ("O"                #x53) 
    168     ("("                #x54) 
    169     ("BackSpace"        #x55) 
    170     (":"                #x59) 
    171     ("2"                #x5a) 
    172     ("4"                #x5b) 
    173     ("6"                #x5c) 
    174     ("8"                #x5d) 
    175     ("0"                #x5e) 
    176     ("="                #x5f) 
    177     ("\\"               #x60) 
    178     ("1"                #x64) 
    179     ("3"                #x65) 
    180     ("5"                #x66) 
    181     ("7"                #x67) 
    182     ("9"                #x68) 
    183     ("-"                #x69) 
    184     ("`"                #x6a) 
    185     ("|"                #x6b) 
    186     ("Escape"           #x6f) 
    187     ("Refresh"          #x70) 
    188     ("Square"           #x71) 
    189     ("Circle"           #x72) 
    190     ("Triangle"         #x73) 
    191     ("ClearInput"       #x74) 
    192     ("Suspend"          #x75) 
    193     ("Resume"           #x76))) 
    194  
    195 (defparameter *special-key-map* 
    196   '(("Select"           "F1") 
    197     ("Network"          "F2") 
    198     ("Function"         "F3") 
    199     ("Suspend"          "F4") 
    200     ("Resume"           "F5") 
    201     ("Abort"            "F6") 
    202     ("SuperL"           "F7") 
    203     ("HyperL"           "F8") 
    204     ("Scroll"           "F9"    "PgDn") 
    205     ("ClearInput"       "F10") 
    206     ("SymbolR"          "KP5"   "Up") 
    207     ("Scroll"           "KP3"   "Scroll") 
    208     ("RubOut"           "Del") 
    209     ("Complete"         "F11"   "Home") 
    210     ("Help"             "F12") 
    211     ("End"              "KP1"   "End") 
    212     ("MetaL"            "AltL") 
    213     ("MetaR"            "AltGr" "Left") 
    214     ("SuperR"           nil     "Down") 
    215     ("HyperR"           nil     "Right") 
    216     ("Repeat"           nil     "PgUp") 
    217     ("ControlL"         "CtrlL") 
    218     ("ControlR"         "CtrlR") 
    219     ("("                "[") 
    220     (")"                "]") 
    221     ("Triangle"         "KP2") 
    222     ("Circle"           "KP3") 
    223     ("Square"           "KP4") 
    224     ("Refresh"          "KP0") 
    225     ("Page"             "KP6") 
    226     ("Line"             "KP7") 
    227     ("SymbolL"          "KP8") 
    228     ("|"                "KP-") 
    229     (":"                "KP*"))) 
     258    ("HyperR"           #x12    8 0) 
     259    ("Scroll"           #x07    9 0 1.5)) 
     260  "Definition of Symbolics keyboard scan codes.  One list (NAME 
     261  SCANCODE XPOS YPOS [ SIZE ] ) for each key.  NAME is the name of the 
     262  key, as printed on the key cap.  SCANCODE is the scan code.  XPOS is 
     263  the relative X position of the key, counted from the left.  YPOS is 
     264  the relative Y position of the key, counted from the bottom row. 
     265  SIZE is the size of the key relative to a letter key, which has size 
     266  1 and is the default.") 
     267 
     268(defun key-labels (entry) 
     269  (if (listp (first entry)) 
     270      (first entry) 
     271      (list (first entry)))) 
     272 
     273(defun key-name (entry) 
     274  (if (listp (first entry)) 
     275      (first (first entry)) 
     276      (first entry))) 
     277 
     278(defun key-scancode (entry) 
     279  (second entry)) 
     280 
     281(defun key-x (entry) 
     282  (third entry)) 
     283 
     284(defun key-y (entry) 
     285  (fourth entry)) 
     286 
     287(defun key-width (entry) 
     288  (or (fifth entry) 1)) 
     289 
     290(defun group-on (list &key (test #'eql) (key #'identity) (include-key t)) 
     291  (let ((hash (make-hash-table :test test)) 
     292        keys) 
     293    (dolist (el list) 
     294      (let ((key (funcall key el))) 
     295        (unless (nth-value 1 (gethash key hash)) 
     296          (push key keys)) 
     297        (push el (gethash key hash))))     
     298    (mapcar (lambda (key) (let ((keys (nreverse (gethash key hash)))) 
     299                            (if include-key 
     300                                (cons key keys) 
     301                                keys))) 
     302            (nreverse keys)))) 
    230303 
    231304(defun find-explicit-mapping (symbolics-keyname &optional f-mode-p) 
    232   (let ((mapping-entry (assoc symbolics-keyname *special-key-map* :test #'equal))) 
     305  (let ((mapping-entry (assoc symbolics-keyname *key-map* :test #'equal))) 
    233306    (when mapping-entry 
    234307      (let ((mapping (nth (if f-mode-p 2 1) mapping-entry))) 
     
    280353  (setf (aref map symbolics-scancode) (car ps2-keycode)))) 
    281354 
     355(defun map-symbolics-key (symbolics-keyname &optional f-mode) 
     356  "Given the name of a symbolics key, return the corresponding PS/2 scan code(s) as a list." 
     357  (cdr (or (when f-mode 
     358             (find-explicit-mapping symbolics-keyname t)) 
     359           (find-explicit-mapping symbolics-keyname) 
     360           (find-direct-mapping symbolics-keyname)))) 
     361 
     362(defun f-mode-key-p (symbolics-key-entry) 
     363  "Return a true value if the key desribed by SYMBOLICS-KEY-ENTRY is a F-mode switch." 
     364  (member (key-name symbolics-key-entry) '("Local" "ModeLock") :test #'equal)) 
     365 
    282366(defun make-keymap () 
     367  "Print mapping definition arrays in assembler format to 
     368  *standard-output*.  The labels are chosen so that the tables can be 
     369  copied into the kbdlabel assembler source." 
    283370  (let ((normal-map (make-array 128 :initial-element 0)) 
    284371        (f-mode-map (make-array 128 :initial-element 0)) 
     
    290377        (declare (ignore geometry-info)) 
    291378        (cond 
    292           ((member symbolics-keyname '("Local" "ModeLock") :test #'equal
     379          ((f-mode-key-p symbolics-key-entry
    293380           (setf (aref flag-map symbolics-scancode) +f-mode-switch+)) 
    294381          (t 
    295            (let* ((ps2-keycode (cdr (or (find-explicit-mapping symbolics-keyname) 
    296                                         (find-direct-mapping symbolics-keyname)))) 
    297                   (f-mode-ps2-keycode (or (cdr (find-explicit-mapping symbolics-keyname t)) 
    298                                           ps2-keycode))) 
     382           (let* ((ps2-keycode (map-symbolics-key symbolics-keyname)) 
     383                  (f-mode-ps2-keycode (map-symbolics-key symbolics-keyname t))) 
    299384             (cond 
    300385               ((or ps2-keycode f-mode-ps2-keycode) 
     
    314399    (when unmapped-ps2-keys 
    315400      (format t "Unmapped PS/2 keys: ~S~%" (mapcar #'car unmapped-ps2-keys))))) 
     401 
     402(defun draw-keyboard (&optional (label-function #'key-name)) 
     403  (pdf:with-saved-state 
     404    (pdf:translate 70 0) 
     405    (pdf:scale 25 25) 
     406    (pdf:set-line-width .05) 
     407    (pdf:set-rgb-stroke 0.2 0.2 0.2) 
     408    (let ((keys (sort (group-on *symbolics-map* 
     409                                :test #'eql 
     410                                :key #'key-y 
     411                                :include-key nil) 
     412                      #'> :key (compose #'key-y #'car))) 
     413          (helvetica (pdf:get-font "Helvetica"))) 
     414      (do* ((y 0 (incf y))) 
     415           ((> y 5)) 
     416        (let ((row (nth (- 5 y) keys))) 
     417          (pdf:move-to 0 y) 
     418          (pdf:line-to 20 y) 
     419          (do* ((i 0 (incf i)) 
     420                (entry (nth i row) (nth i row)) 
     421                (x 0)) 
     422               ((null (nth i row))) 
     423            (pdf:move-to x y) 
     424            (pdf:line-to x (+ y 1)) 
     425            (pdf:stroke) 
     426            (pdf:in-text-mode 
     427              (pdf:set-font helvetica 0.3) 
     428              (pdf:move-text (+ x 0.1) (+ y 0.6)) 
     429              (let ((label-text (funcall label-function entry))) 
     430                (cond 
     431                  ((null label-text)) 
     432                  ((= 1 (length label-text)) 
     433                   (pdf:move-text 0 -0.4) 
     434                   (pdf:draw-text (first label-text))) 
     435                  ((= 2 (length label-text)) 
     436                   (pdf:draw-text (first label-text)) 
     437                   (pdf:move-text 0 -0.4) 
     438                   (pdf:draw-text (second label-text))) 
     439                  (t 
     440                   (error "unexpected number of elements in labels list ~S returned by label function for entry ~S" 
     441                          label-text entry))))) 
     442            (incf x (key-width entry))))) 
     443      (pdf:move-to 0 6) 
     444      (pdf:line-to 20 6) 
     445      (pdf:stroke) 
     446      (pdf:move-to 20 6) 
     447      (pdf:line-to 20 0) 
     448      (pdf:stroke)))) 
     449 
     450(defun split-label (string) 
     451  "Split camel case label into multiple words." 
     452  (cl-ppcre:split "(?<=[a-z])(?=[A-Z])" string)) 
     453 
     454(defun format-key-name (entry) 
     455  "Given a Symbolics key definition entry, return one or two strings 
     456to be used as label for the key." 
     457  (if (= 1 (length (key-labels entry))) 
     458      (split-label (key-name entry)) 
     459      (reverse (key-labels entry)))) 
     460 
     461(defun format-key-scancodes (entry) 
     462  "Given a Symbolics key definition entry, return one or two strings 
     463representing the PS/2 scan code of the key." 
     464  (list (format nil "~{~2,'0X~^ ~}" (map-symbolics-key (key-name entry))) 
     465        (format nil "~{~2,'0X~^ ~}" (map-symbolics-key (key-name entry) t)))) 
     466 
     467(defun format-key-ps2-name (entry &optional f-mode) 
     468  (cond 
     469    ((equal "ModeLock" (car entry)) 
     470     '("F-Mode" "Lock")) 
     471    ((equal "Local" (car entry)) 
     472     '("F-Mode")) 
     473    (t 
     474     (let ((scan-codes (map-symbolics-key (key-name entry) f-mode))) 
     475       (split-label (or (car (find scan-codes *ps2-map* :key #'cdr :test #'equal)) 
     476                        "")))))) 
     477 
     478(defun draw-label (x y text &key (size 12) (font-name "Helvetica-Bold")) 
     479  (let ((helvetica (pdf:get-font font-name))) 
     480    (pdf:in-text-mode 
     481      (pdf:set-font helvetica size) 
     482      (pdf:move-text x y) 
     483      (pdf:draw-text text)))) 
     484 
     485(defun draw-layout (&optional (pathname #P"layout.pdf")) 
     486  (pdf:with-document () 
     487    (pdf:with-page () 
     488      (pdf:with-outline-level ("Symbolics keyboard layout" (pdf:register-page-reference)) 
     489        (draw-label 70 800 "kbdbabel-symbolics Symbolics to PS/2 Adapter key code mapping" :size 14) 
     490        (draw-label 240 10 "kbdbabel for Symbolics keyboard - by Alexander Kurz and Hans Hübner - http://kbdbabel.net/" 
     491                    :size 8 :font-name "Helvetica") 
     492        (draw-label 70 35 "PS/2 scan codes (top: standard, bottom: F-mode)") 
     493        (pdf:translate 0 50) 
     494        (draw-keyboard #'format-key-scancodes) 
     495        (draw-label 70 175 "F-Mode mapping") 
     496        (pdf:translate 0 190) 
     497        (draw-keyboard (rcurry #'format-key-ps2-name t)) 
     498        (draw-label 70 175 "Standard mapping") 
     499        (pdf:translate 0 190) 
     500        (draw-keyboard #'format-key-ps2-name) 
     501        (draw-label 70 175 "Key caps") 
     502        (pdf:translate 0 190) 
     503        (draw-keyboard #'format-key-name))) 
     504    (pdf:write-document pathname)))