File indexing completed on 2024-11-24 05:00:23
0001 /* 0002 GDK - The GIMP Drawing Kit 0003 SPDX-FileCopyrightText: 1995-1997 Peter Mattis 0004 SPDX-FileCopyrightText: 1995-1997 Spencer Kimball 0005 SPDX-FileCopyrightText: 1995-1997 Josh MacDonald 0006 SPDX-FileCopyrightText: 2005, 2006, 2007, 2009 GNOME Foundation 0007 0008 SPDX-License-Identifier: LGPL-2.0-or-later 0009 */ 0010 #include <glib.h> 0011 #include <string.h> 0012 #include <stdlib.h> 0013 #include "gdkkeysyms_p.h" 0014 #include "gtkaccelparse_p.h" 0015 #include "gdkkeynames_p.h" 0016 0017 static inline gboolean 0018 is_alt (const gchar *string) 0019 { 0020 // clang-format off 0021 return ((string[0] == '<') && 0022 (string[1] == 'a' || string[1] == 'A') && 0023 (string[2] == 'l' || string[2] == 'L') && 0024 (string[3] == 't' || string[3] == 'T') && 0025 (string[4] == '>')); 0026 // clang-format on 0027 } 0028 0029 static inline gboolean 0030 is_ctl (const gchar *string) 0031 { 0032 // clang-format off 0033 return ((string[0] == '<') && 0034 (string[1] == 'c' || string[1] == 'C') && 0035 (string[2] == 't' || string[2] == 'T') && 0036 (string[3] == 'l' || string[3] == 'L') && 0037 (string[4] == '>')); 0038 // clang-format on 0039 } 0040 0041 static inline gboolean 0042 is_modx (const gchar *string) 0043 { 0044 // clang-format off 0045 return ((string[0] == '<') && 0046 (string[1] == 'm' || string[1] == 'M') && 0047 (string[2] == 'o' || string[2] == 'O') && 0048 (string[3] == 'd' || string[3] == 'D') && 0049 (string[4] >= '1' && string[4] <= '5') && 0050 (string[5] == '>')); 0051 // clang-format on 0052 } 0053 0054 static inline gboolean 0055 is_ctrl (const gchar *string) 0056 { 0057 // clang-format off 0058 return ((string[0] == '<') && 0059 (string[1] == 'c' || string[1] == 'C') && 0060 (string[2] == 't' || string[2] == 'T') && 0061 (string[3] == 'r' || string[3] == 'R') && 0062 (string[4] == 'l' || string[4] == 'L') && 0063 (string[5] == '>')); 0064 // clang-format on 0065 } 0066 0067 static inline gboolean 0068 is_shft (const gchar *string) 0069 { 0070 // clang-format off 0071 return ((string[0] == '<') && 0072 (string[1] == 's' || string[1] == 'S') && 0073 (string[2] == 'h' || string[2] == 'H') && 0074 (string[3] == 'f' || string[3] == 'F') && 0075 (string[4] == 't' || string[4] == 'T') && 0076 (string[5] == '>')); 0077 // clang-format on 0078 } 0079 0080 static inline gboolean 0081 is_shift (const gchar *string) 0082 { 0083 // clang-format off 0084 return ((string[0] == '<') && 0085 (string[1] == 's' || string[1] == 'S') && 0086 (string[2] == 'h' || string[2] == 'H') && 0087 (string[3] == 'i' || string[3] == 'I') && 0088 (string[4] == 'f' || string[4] == 'F') && 0089 (string[5] == 't' || string[5] == 'T') && 0090 (string[6] == '>')); 0091 // clang-format on 0092 } 0093 0094 static inline gboolean 0095 is_control (const gchar *string) 0096 { 0097 // clang-format off 0098 return ((string[0] == '<') && 0099 (string[1] == 'c' || string[1] == 'C') && 0100 (string[2] == 'o' || string[2] == 'O') && 0101 (string[3] == 'n' || string[3] == 'N') && 0102 (string[4] == 't' || string[4] == 'T') && 0103 (string[5] == 'r' || string[5] == 'R') && 0104 (string[6] == 'o' || string[6] == 'O') && 0105 (string[7] == 'l' || string[7] == 'L') && 0106 (string[8] == '>')); 0107 // clang-format on 0108 } 0109 0110 static inline gboolean 0111 is_release (const gchar *string) 0112 { 0113 // clang-format off 0114 return ((string[0] == '<') && 0115 (string[1] == 'r' || string[1] == 'R') && 0116 (string[2] == 'e' || string[2] == 'E') && 0117 (string[3] == 'l' || string[3] == 'L') && 0118 (string[4] == 'e' || string[4] == 'E') && 0119 (string[5] == 'a' || string[5] == 'A') && 0120 (string[6] == 's' || string[6] == 'S') && 0121 (string[7] == 'e' || string[7] == 'E') && 0122 (string[8] == '>')); 0123 // clang-format on 0124 } 0125 0126 static inline gboolean 0127 is_meta (const gchar *string) 0128 { 0129 // clang-format off 0130 return ((string[0] == '<') && 0131 (string[1] == 'm' || string[1] == 'M') && 0132 (string[2] == 'e' || string[2] == 'E') && 0133 (string[3] == 't' || string[3] == 'T') && 0134 (string[4] == 'a' || string[4] == 'A') && 0135 (string[5] == '>')); 0136 // clang-format on 0137 } 0138 0139 static inline gboolean 0140 is_super (const gchar *string) 0141 { 0142 // clang-format off 0143 return ((string[0] == '<') && 0144 (string[1] == 's' || string[1] == 'S') && 0145 (string[2] == 'u' || string[2] == 'U') && 0146 (string[3] == 'p' || string[3] == 'P') && 0147 (string[4] == 'e' || string[4] == 'E') && 0148 (string[5] == 'r' || string[5] == 'R') && 0149 (string[6] == '>')); 0150 // clang-format on 0151 } 0152 0153 static inline gboolean 0154 is_hyper (const gchar *string) 0155 { 0156 // clang-format off 0157 return ((string[0] == '<') && 0158 (string[1] == 'h' || string[1] == 'H') && 0159 (string[2] == 'y' || string[2] == 'Y') && 0160 (string[3] == 'p' || string[3] == 'P') && 0161 (string[4] == 'e' || string[4] == 'E') && 0162 (string[5] == 'r' || string[5] == 'R') && 0163 (string[6] == '>')); 0164 // clang-format on 0165 } 0166 0167 static inline gboolean 0168 is_keycode (const gchar *string) 0169 { 0170 // clang-format off 0171 return (string[0] == '0' && 0172 string[1] == 'x' && 0173 g_ascii_isxdigit (string[2]) && 0174 g_ascii_isxdigit (string[3])); 0175 // clang-format on 0176 } 0177 0178 void 0179 _gtk_accelerator_parse (const gchar *accelerator, 0180 guint *accelerator_key, 0181 GdkModifierType *accelerator_mods) 0182 { 0183 guint keyval; 0184 GdkModifierType mods; 0185 gint len; 0186 gboolean error; 0187 0188 if (accelerator_key) 0189 *accelerator_key = 0; 0190 if (accelerator_mods) 0191 *accelerator_mods = 0; 0192 0193 g_return_if_fail (accelerator != NULL); 0194 0195 error = FALSE; 0196 keyval = 0; 0197 mods = 0; 0198 len = strlen (accelerator); 0199 while (len) 0200 { 0201 if (*accelerator == '<') 0202 { 0203 if (len >= 9 && is_release (accelerator)) 0204 { 0205 accelerator += 9; 0206 len -= 9; 0207 mods |= GDK_RELEASE_MASK; 0208 } 0209 else if (len >= 9 && is_control (accelerator)) 0210 { 0211 accelerator += 9; 0212 len -= 9; 0213 mods |= GDK_CONTROL_MASK; 0214 } 0215 else if (len >= 7 && is_shift (accelerator)) 0216 { 0217 accelerator += 7; 0218 len -= 7; 0219 mods |= GDK_SHIFT_MASK; 0220 } 0221 else if (len >= 6 && is_shft (accelerator)) 0222 { 0223 accelerator += 6; 0224 len -= 6; 0225 mods |= GDK_SHIFT_MASK; 0226 } 0227 else if (len >= 6 && is_ctrl (accelerator)) 0228 { 0229 accelerator += 6; 0230 len -= 6; 0231 mods |= GDK_CONTROL_MASK; 0232 } 0233 else if (len >= 6 && is_modx (accelerator)) 0234 { 0235 static const guint mod_vals[] = { 0236 GDK_MOD1_MASK, GDK_MOD2_MASK, GDK_MOD3_MASK, 0237 GDK_MOD4_MASK, GDK_MOD5_MASK 0238 }; 0239 0240 len -= 6; 0241 accelerator += 4; 0242 mods |= mod_vals[*accelerator - '1']; 0243 accelerator += 2; 0244 } 0245 else if (len >= 5 && is_ctl (accelerator)) 0246 { 0247 accelerator += 5; 0248 len -= 5; 0249 mods |= GDK_CONTROL_MASK; 0250 } 0251 else if (len >= 5 && is_alt (accelerator)) 0252 { 0253 accelerator += 5; 0254 len -= 5; 0255 mods |= GDK_MOD1_MASK; 0256 } 0257 else if (len >= 6 && is_meta (accelerator)) 0258 { 0259 accelerator += 6; 0260 len -= 6; 0261 // mods |= GDK_META_MASK; 0262 } 0263 else if (len >= 7 && is_hyper (accelerator)) 0264 { 0265 accelerator += 7; 0266 len -= 7; 0267 mods |= GDK_MOD4_MASK; 0268 } 0269 else if (len >= 7 && is_super (accelerator)) 0270 { 0271 accelerator += 7; 0272 len -= 7; 0273 mods |= GDK_MOD4_MASK; 0274 } 0275 else 0276 { 0277 gchar last_ch; 0278 0279 last_ch = *accelerator; 0280 while (last_ch && last_ch != '>') 0281 { 0282 last_ch = *accelerator; 0283 accelerator += 1; 0284 len -= 1; 0285 } 0286 } 0287 } 0288 else 0289 { 0290 if (len >= 4 && is_keycode (accelerator)) 0291 { 0292 char keystring[5]; 0293 gchar *endptr; 0294 0295 memcpy (keystring, accelerator, 4); 0296 keystring [4] = '\000'; 0297 0298 strtol (keystring, &endptr, 16); 0299 0300 if (endptr == NULL || *endptr != '\000') 0301 { 0302 error = TRUE; 0303 goto out; 0304 } 0305 else 0306 { 0307 /* There was a keycode in the string, but 0308 * we cannot store it, so we have an error */ 0309 error = TRUE; 0310 goto out; 0311 } 0312 } 0313 else 0314 { 0315 keyval = _gdk_keyval_from_name (accelerator); 0316 if (keyval == GDK_KEY_VoidSymbol) 0317 { 0318 error = TRUE; 0319 goto out; 0320 } 0321 } 0322 0323 accelerator += len; 0324 len -= len; 0325 } 0326 } 0327 0328 out: 0329 if (error) 0330 keyval = mods = 0; 0331 0332 if (accelerator_key) 0333 *accelerator_key = keyval; 0334 if (accelerator_mods) 0335 *accelerator_mods = mods; 0336 }