1 /** 2 * Key module for dcell containing definitiosn for various key strokes. 3 * 4 * Copyright: Copyright 2022 Garrett D'Amore 5 * Authors: Garrett D'Amore 6 * License: 7 * Distributed under the Boost Software License, Version 1.0. 8 * (See accompanying file LICENSE or https://www.boost.org/LICENSE_1_0.txt) 9 * SPDX-License-Identifier: BSL-1.0 10 */ 11 module dcell.key; 12 13 import std.string; 14 import std.algorithm; 15 16 /** 17 * Key represents a single, unmodified key stroke. Modifier keys are 18 * not considered as Keys. 19 */ 20 enum Key 21 { 22 none = 0, 23 24 // control keys are assigned their ASCII values 25 // these definitions should not be used by apps, but instead 26 // by using key rune, the character, and a modifier. 27 // TODO: consider just removing these. 28 ctrlSpace = 0, 29 ctrlA, 30 ctrlB, 31 ctrlC, 32 ctrlD, 33 ctrlE, 34 ctrlF, 35 ctrlG, 36 ctrlH, 37 ctrlI, 38 ctrlJ, 39 ctrlK, 40 ctrlL, 41 ctrlM, 42 ctrlN, 43 ctrlO, 44 ctrlP, 45 ctrlQ, 46 ctrlR, 47 ctrlS, 48 ctrlT, 49 ctrlU, 50 ctrlV, 51 ctrlW, 52 ctrlX, 53 ctrlY, 54 ctrlZ, 55 ctrlLeftSq, // Escape 56 ctrlBackslash, 57 ctrlRightSq, 58 ctrlCarat, 59 ctrlUnderscore, 60 61 rune = 256, // start of defined keys, numbered high to avoid conflicts 62 up, 63 down, 64 right, 65 left, 66 upLeft, 67 upRight, 68 downLeft, 69 downRight, 70 center, 71 pgUp, 72 pgDn, 73 home, 74 end, 75 insert, 76 del2, // secondary delete button, apart from DEL 77 help, 78 exit, 79 clear, 80 cancel, 81 print, 82 pause, 83 backtab, 84 f1, 85 f2, 86 f3, 87 f4, 88 f5, 89 f6, 90 f7, 91 f8, 92 f9, 93 f10, 94 f11, 95 f12, 96 f13, 97 f14, 98 f15, 99 f16, 100 f17, 101 f18, 102 f19, 103 f20, 104 f21, 105 f22, 106 f23, 107 f24, 108 f25, 109 f26, 110 f27, 111 f28, 112 f29, 113 f30, 114 f31, 115 f32, 116 f33, 117 f34, 118 f35, 119 f36, 120 f37, 121 f38, 122 f39, 123 f40, 124 f41, 125 f42, 126 f43, 127 f44, 128 f45, 129 f46, 130 f47, 131 f48, 132 f49, 133 f50, 134 f51, 135 f52, 136 f53, 137 f54, 138 f55, 139 f56, 140 f57, 141 f58, 142 f59, 143 f60, 144 f61, 145 f62, 146 f63, 147 f64, 148 149 // convenience aliases 150 backspace = ctrlH, 151 tab = ctrlI, 152 esc = ctrlLeftSq, 153 enter = ctrlM, 154 del = 0x7F, // Note del2 has a different value 155 } 156 157 static immutable dstring[Key] keyNames; 158 shared static this() 159 { 160 keyNames[Key.enter] = "Enter"; 161 keyNames[Key.backspace] = "Backspace"; 162 keyNames[Key.tab] = "Tab"; 163 keyNames[Key.backtab] = "Backtab"; 164 keyNames[Key.esc] = "Esc"; 165 keyNames[Key.del2] = "Delete2"; 166 keyNames[Key.del] = "Delete"; 167 keyNames[Key.insert] = "Insert"; 168 keyNames[Key.up] = "Up"; 169 keyNames[Key.down] = "Down"; 170 keyNames[Key.left] = "Left"; 171 keyNames[Key.right] = "Right"; 172 keyNames[Key.home] = "Home"; 173 keyNames[Key.end] = "End"; 174 keyNames[Key.upLeft] = "UpLeft"; 175 keyNames[Key.upRight] = "UpRight"; 176 keyNames[Key.downLeft] = "DownLeft"; 177 keyNames[Key.downRight] = "DownRight"; 178 keyNames[Key.center] = "Center"; 179 keyNames[Key.pgDn] = "PgDn"; 180 keyNames[Key.pgUp] = "PgUp"; 181 keyNames[Key.clear] = "Clear"; 182 keyNames[Key.exit] = "Exit"; 183 keyNames[Key.cancel] = "Cancel"; 184 keyNames[Key.pause] = "Pause"; 185 keyNames[Key.print] = "Print"; 186 keyNames[Key.f1] = "F1"; 187 keyNames[Key.f2] = "F2"; 188 keyNames[Key.f3] = "F3"; 189 keyNames[Key.f4] = "F4"; 190 keyNames[Key.f5] = "F5"; 191 keyNames[Key.f6] = "F6"; 192 keyNames[Key.f7] = "F7"; 193 keyNames[Key.f8] = "F8"; 194 keyNames[Key.f9] = "F9"; 195 keyNames[Key.f10] = "F10"; 196 keyNames[Key.f11] = "F11"; 197 keyNames[Key.f12] = "F12"; 198 keyNames[Key.f13] = "F13"; 199 keyNames[Key.f14] = "F14"; 200 keyNames[Key.f15] = "F15"; 201 keyNames[Key.f16] = "F16"; 202 keyNames[Key.f17] = "F17"; 203 keyNames[Key.f18] = "F18"; 204 keyNames[Key.f19] = "F19"; 205 keyNames[Key.f20] = "F20"; 206 keyNames[Key.f21] = "F21"; 207 keyNames[Key.f22] = "F22"; 208 keyNames[Key.f23] = "F23"; 209 keyNames[Key.f24] = "F24"; 210 keyNames[Key.f25] = "F25"; 211 keyNames[Key.f26] = "F26"; 212 keyNames[Key.f27] = "F27"; 213 keyNames[Key.f28] = "F28"; 214 keyNames[Key.f29] = "F29"; 215 keyNames[Key.f30] = "F30"; 216 keyNames[Key.f31] = "F31"; 217 keyNames[Key.f32] = "F32"; 218 keyNames[Key.f33] = "F33"; 219 keyNames[Key.f34] = "F34"; 220 keyNames[Key.f35] = "F35"; 221 keyNames[Key.f36] = "F36"; 222 keyNames[Key.f37] = "F37"; 223 keyNames[Key.f38] = "F38"; 224 keyNames[Key.f39] = "F39"; 225 keyNames[Key.f40] = "F40"; 226 keyNames[Key.f41] = "F41"; 227 keyNames[Key.f42] = "F42"; 228 keyNames[Key.f43] = "F43"; 229 keyNames[Key.f44] = "F44"; 230 keyNames[Key.f45] = "F45"; 231 keyNames[Key.f46] = "F46"; 232 keyNames[Key.f47] = "F47"; 233 keyNames[Key.f48] = "F48"; 234 keyNames[Key.f49] = "F49"; 235 keyNames[Key.f50] = "F50"; 236 keyNames[Key.f51] = "F51"; 237 keyNames[Key.f52] = "F52"; 238 keyNames[Key.f53] = "F53"; 239 keyNames[Key.f54] = "F54"; 240 keyNames[Key.f55] = "F55"; 241 keyNames[Key.f56] = "F56"; 242 keyNames[Key.f57] = "F57"; 243 keyNames[Key.f58] = "F58"; 244 keyNames[Key.f59] = "F59"; 245 keyNames[Key.f60] = "F60"; 246 keyNames[Key.f61] = "F61"; 247 keyNames[Key.f62] = "F62"; 248 keyNames[Key.f63] = "F63"; 249 keyNames[Key.f64] = "F64"; 250 keyNames[Key.ctrlA] = "Ctrl-A"; 251 keyNames[Key.ctrlB] = "Ctrl-B"; 252 keyNames[Key.ctrlC] = "Ctrl-C"; 253 keyNames[Key.ctrlD] = "Ctrl-D"; 254 keyNames[Key.ctrlE] = "Ctrl-E"; 255 keyNames[Key.ctrlF] = "Ctrl-F"; 256 keyNames[Key.ctrlG] = "Ctrl-G"; 257 keyNames[Key.ctrlJ] = "Ctrl-J"; 258 keyNames[Key.ctrlK] = "Ctrl-K"; 259 keyNames[Key.ctrlL] = "Ctrl-L"; 260 keyNames[Key.ctrlN] = "Ctrl-N"; 261 keyNames[Key.ctrlO] = "Ctrl-O"; 262 keyNames[Key.ctrlP] = "Ctrl-P"; 263 keyNames[Key.ctrlQ] = "Ctrl-Q"; 264 keyNames[Key.ctrlR] = "Ctrl-R"; 265 keyNames[Key.ctrlS] = "Ctrl-S"; 266 keyNames[Key.ctrlT] = "Ctrl-T"; 267 keyNames[Key.ctrlU] = "Ctrl-U"; 268 keyNames[Key.ctrlV] = "Ctrl-V"; 269 keyNames[Key.ctrlW] = "Ctrl-W"; 270 keyNames[Key.ctrlX] = "Ctrl-X"; 271 keyNames[Key.ctrlY] = "Ctrl-Y"; 272 keyNames[Key.ctrlZ] = "Ctrl-Z"; 273 keyNames[Key.ctrlSpace] = "Ctrl-Space"; 274 keyNames[Key.ctrlUnderscore] = "Ctrl-_"; 275 keyNames[Key.ctrlRightSq] = "Ctrl-]"; 276 keyNames[Key.ctrlBackslash] = "Ctrl-\\"; 277 keyNames[Key.ctrlCarat] = "Ctrl-^"; 278 } 279 280 /** 281 * Modifiers are special keys that when combined with other keys 282 * change their meaning. 283 */ 284 enum Modifiers 285 { 286 none = 0, 287 shift = 1 << 0, 288 ctrl = 1 << 1, 289 alt = 1 << 2, 290 meta = 1 << 3, 291 } 292 293 /** 294 * KeyEvent represents a single pressed key, possibly with modifiers. 295 */ 296 struct KeyEvent 297 { 298 Key key; /// Key pressed. 299 dchar ch; /// Set if key == rune. 300 Modifiers mod; /// Any modifiers pressed together. 301 302 dstring toString() const pure 303 { 304 dstring s = ""; 305 if (mod & Modifiers.meta) 306 { 307 s ~= "Meta-"; 308 } 309 if (mod & Modifiers.alt) 310 { 311 s ~= "Alt-"; 312 } 313 dstring kn = ""; 314 if (key in keyNames) 315 { 316 kn = keyNames[key]; 317 } 318 else if (key == Key.rune) 319 { 320 kn = [ch]; 321 } 322 else 323 { 324 325 kn = format("Key[%02X]"d, key); 326 } 327 if ((mod & Modifiers.ctrl) && !startsWith(kn, "Ctrl-")) 328 { 329 s ~= "Ctrl-"; 330 } 331 332 return s ~ kn; 333 } 334 }