openMSX
UnicodeKeymap.hh
Go to the documentation of this file.
1 #ifndef UNICODEKEYMAP_HH
2 #define UNICODEKEYMAP_HH
3 
4 #include "openmsx.hh"
5 #include <cassert>
6 #include <string_view>
7 #include <utility>
8 #include <vector>
9 
10 namespace openmsx {
11 
12 /** A position (row, column) in a keyboard matrix.
13  */
14 class KeyMatrixPosition final {
15  static constexpr unsigned INVALID = 0xFF;
16 
17 public:
18  /** Rows are in the range [0..NUM_ROWS). */
19  static constexpr unsigned NUM_ROWS = 16;
20  /** Columns are in the range [0..NUM_COLS). */
21  static constexpr unsigned NUM_COLS = 8;
22  /** Combined row and column values are in the range [0..NUM_ROWCOL). */
23  static constexpr unsigned NUM_ROWCOL = 1 << 7;
24 
25  /** Creates an invalid key matrix position, which can be used when
26  * a key does not exist on a particular keyboard.
27  */
28  KeyMatrixPosition() = default;
29 
30  /** Creates a key matrix position from a byte: the row is stored in
31  * the high nibble, the column is stored in the low nibble.
32  */
33  KeyMatrixPosition(byte rowCol_)
34  : KeyMatrixPosition(rowCol_ >> 4, rowCol_ & 0x0F)
35  {
36  }
37 
38  /** Creates a key matrix position with a given row and column.
39  */
40  KeyMatrixPosition(unsigned row, unsigned col)
41  : rowCol((row << 3) | col)
42  {
43  assert(row < NUM_ROWS);
44  assert(col < NUM_COLS);
45  assert(isValid());
46  }
47 
48  /** Returns true iff this position is valid.
49  */
50  bool isValid() const {
51  return rowCol != INVALID;
52  }
53 
54  /** Returns the matrix row.
55  * Must only be called on valid positions.
56  */
57  unsigned getRow() const {
58  assert(isValid());
59  return rowCol >> 3;
60  }
61 
62  /** Returns the matrix column.
63  * Must only be called on valid positions.
64  */
65  unsigned getColumn() const {
66  assert(isValid());
67  return rowCol & 0x07;
68  }
69 
70  /** Returns the matrix row and column combined in a single byte: the column
71  * is stored in the lower 3 bits, the row is stored in the higher bits.
72  * Must only be called on valid positions.
73  */
74  byte getRowCol() const {
75  assert(isValid());
76  return rowCol;
77  }
78 
79  /** Returns a mask with the bit corresponding to this position's
80  * column set, all other bits clear.
81  * Must only be called on valid positions.
82  */
83  unsigned getMask() const {
84  assert(isValid());
85  return 1 << getColumn();
86  }
87 
88  bool operator==(const KeyMatrixPosition& other) const {
89  return rowCol == other.rowCol;
90  }
91 
92 private:
93  byte rowCol = INVALID;
94 };
95 
96 class UnicodeKeymap
97 {
98 public:
99  struct KeyInfo {
101  // Modifier masks:
102  static constexpr byte SHIFT_MASK = 1 << SHIFT;
103  static constexpr byte CTRL_MASK = 1 << CTRL;
104  static constexpr byte GRAPH_MASK = 1 << GRAPH;
105  static constexpr byte CAPS_MASK = 1 << CAPS;
106  static constexpr byte CODE_MASK = 1 << CODE;
107 
108  KeyInfo() = default;
109  KeyInfo(KeyMatrixPosition pos_, byte modmask_)
110  : pos(pos_), modmask(modmask_)
111  {
112  assert(pos.isValid());
113  }
114  bool isValid() const {
115  return pos.isValid();
116  }
117  KeyMatrixPosition pos;
118  byte modmask = 0;
119  };
120 
121  explicit UnicodeKeymap(std::string_view keyboardType);
122 
123  KeyInfo get(unsigned unicode) const;
124  KeyInfo getDeadkey(unsigned n) const;
125 
126  /** Returns a mask in which a bit is set iff the corresponding modifier
127  * is relevant for the given key. A modifier is considered relevant if
128  * there is at least one mapping entry for the key that requires the
129  * modifier to be active.
130  * Must only be called on valid KeyInfos.
131  */
132  byte getRelevantMods(const KeyInfo& keyInfo) const {
133  return relevantMods[keyInfo.pos.getRowCol()];
134  }
135 
136 private:
137  static const unsigned NUM_DEAD_KEYS = 3;
138 
139  void parseUnicodeKeymapfile(std::string_view data);
140 
141  std::vector<std::pair<unsigned, KeyInfo>> mapdata;
142  /** Contains a mask for each key matrix position, which for each modifier
143  * has the corresponding bit set if that modifier that affects the key.
144  */
145  byte relevantMods[KeyMatrixPosition::NUM_ROWCOL];
146  KeyInfo deadKeys[NUM_DEAD_KEYS];
147 };
148 
149 } // namespace openmsx
150 
151 #endif
bool getEnum() const noexcept
Definition: EnumSetting.hh:96
bool isValid() const
Returns true iff this position is valid.
unsigned getMask() const
Returns a mask with the bit corresponding to this position&#39;s column set, all other bits clear...
UnicodeKeymap(std::string_view keyboardType)
byte getRowCol() const
Returns the matrix row and column combined in a single byte: the column is stored in the lower 3 bits...
KeyMatrixPosition()=default
Creates an invalid key matrix position, which can be used when a key does not exist on a particular k...
static constexpr byte CODE_MASK
static constexpr byte GRAPH_MASK
KeyInfo(KeyMatrixPosition pos_, byte modmask_)
static constexpr byte CTRL_MASK
byte getRelevantMods(const KeyInfo &keyInfo) const
Returns a mask in which a bit is set iff the corresponding modifier is relevant for the given key...
bool operator==(const KeyMatrixPosition &other) const
static constexpr unsigned NUM_ROWS
Rows are in the range [0..NUM_ROWS).
KeyInfo getDeadkey(unsigned n) const
static constexpr byte CAPS_MASK
KeyMatrixPosition(unsigned row, unsigned col)
Creates a key matrix position with a given row and column.
static constexpr unsigned NUM_ROWCOL
Combined row and column values are in the range [0..NUM_ROWCOL).
KeyInfo get(unsigned unicode) const
unsigned getRow() const
Returns the matrix row.
static constexpr byte SHIFT_MASK
static constexpr unsigned NUM_COLS
Columns are in the range [0..NUM_COLS).
unsigned getColumn() const
Returns the matrix column.
KeyMatrixPosition(byte rowCol_)
Creates a key matrix position from a byte: the row is stored in the high nibble, the column is stored...