| File: | keytypes.c |
| Location: | line 600, column 40 |
| Description: | Access to field 'indexVMods' results in a dereference of a null pointer (loaded from variable 'old') |
| 1 | /************************************************************ | ||||
| 2 | Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. | ||||
| 3 | |||||
| 4 | Permission to use, copy, modify, and distribute this | ||||
| 5 | software and its documentation for any purpose and without | ||||
| 6 | fee is hereby granted, provided that the above copyright | ||||
| 7 | notice appear in all copies and that both that copyright | ||||
| 8 | notice and this permission notice appear in supporting | ||||
| 9 | documentation, and that the name of Silicon Graphics not be | ||||
| 10 | used in advertising or publicity pertaining to distribution | ||||
| 11 | of the software without specific prior written permission. | ||||
| 12 | Silicon Graphics makes no representation about the suitability | ||||
| 13 | of this software for any purpose. It is provided "as is" | ||||
| 14 | without any express or implied warranty. | ||||
| 15 | |||||
| 16 | SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS | ||||
| 17 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||||
| 18 | AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON | ||||
| 19 | GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL | ||||
| 20 | DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||||
| 21 | DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE | ||||
| 22 | OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH | ||||
| 23 | THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
| 24 | |||||
| 25 | ********************************************************/ | ||||
| 26 | |||||
| 27 | #include "xkbcomp.h" | ||||
| 28 | #include "tokens.h" | ||||
| 29 | #include "expr.h" | ||||
| 30 | #include "vmod.h" | ||||
| 31 | #include "action.h" | ||||
| 32 | #include "misc.h" | ||||
| 33 | |||||
| 34 | typedef struct _PreserveInfo | ||||
| 35 | { | ||||
| 36 | CommonInfo defs; | ||||
| 37 | short matchingMapIndex; | ||||
| 38 | unsigned char indexMods; | ||||
| 39 | unsigned char preMods; | ||||
| 40 | unsigned short indexVMods; | ||||
| 41 | unsigned short preVMods; | ||||
| 42 | } PreserveInfo; | ||||
| 43 | |||||
| 44 | #define _KT_Name(1<<0) (1<<0) | ||||
| 45 | #define _KT_Mask(1<<1) (1<<1) | ||||
| 46 | #define _KT_Map(1<<2) (1<<2) | ||||
| 47 | #define _KT_Preserve(1<<3) (1<<3) | ||||
| 48 | #define _KT_LevelNames(1<<4) (1<<4) | ||||
| 49 | |||||
| 50 | typedef struct _KeyTypeInfo | ||||
| 51 | { | ||||
| 52 | CommonInfo defs; | ||||
| 53 | Display *dpy; | ||||
| 54 | Atom name; | ||||
| 55 | int fileID; | ||||
| 56 | unsigned mask; | ||||
| 57 | unsigned vmask; | ||||
| 58 | Boolint groupInfo; | ||||
| 59 | int numLevels; | ||||
| 60 | int nEntries; | ||||
| 61 | int szEntries; | ||||
| 62 | XkbKTMapEntryPtr entries; | ||||
| 63 | PreserveInfo *preserve; | ||||
| 64 | int szNames; | ||||
| 65 | Atom *lvlNames; | ||||
| 66 | } KeyTypeInfo; | ||||
| 67 | |||||
| 68 | typedef struct _KeyTypesInfo | ||||
| 69 | { | ||||
| 70 | Display *dpy; | ||||
| 71 | char *name; | ||||
| 72 | int errorCount; | ||||
| 73 | int fileID; | ||||
| 74 | unsigned stdPresent; | ||||
| 75 | int nTypes; | ||||
| 76 | KeyTypeInfo *types; | ||||
| 77 | KeyTypeInfo dflt; | ||||
| 78 | VModInfo vmods; | ||||
| 79 | } KeyTypesInfo; | ||||
| 80 | |||||
| 81 | Atom tok_ONE_LEVEL; | ||||
| 82 | Atom tok_TWO_LEVEL; | ||||
| 83 | Atom tok_ALPHABETIC; | ||||
| 84 | Atom tok_KEYPAD; | ||||
| 85 | |||||
| 86 | /***====================================================================***/ | ||||
| 87 | |||||
| 88 | #define ReportTypeShouldBeArray(t,f)ReportShouldBeArray("key type",(f),XkbAtomText((t)->dpy,(t )->name,3)) \ | ||||
| 89 | ReportShouldBeArray("key type",(f),TypeTxt(t)XkbAtomText((t)->dpy,(t)->name,3)) | ||||
| 90 | #define ReportTypeBadType(t,f,w)ReportBadType("key type",(f),XkbAtomText((t)->dpy,(t)-> name,3),(w)) \ | ||||
| 91 | ReportBadType("key type",(f),TypeTxt(t)XkbAtomText((t)->dpy,(t)->name,3),(w)) | ||||
| 92 | |||||
| 93 | /***====================================================================***/ | ||||
| 94 | |||||
| 95 | extern Boolint AddMapEntry(XkbDescPtr /* xkb */ , | ||||
| 96 | KeyTypeInfo * /* type */ , | ||||
| 97 | XkbKTMapEntryPtr /* new */ , | ||||
| 98 | Boolint /* clobber */ , | ||||
| 99 | Boolint /* report */ | ||||
| 100 | ); | ||||
| 101 | |||||
| 102 | extern Boolint AddPreserve(XkbDescPtr /* xkb */ , | ||||
| 103 | KeyTypeInfo * /* type */ , | ||||
| 104 | PreserveInfo * /* new */ , | ||||
| 105 | Boolint /* clobber */ , | ||||
| 106 | Boolint /* report */ | ||||
| 107 | ); | ||||
| 108 | |||||
| 109 | extern Boolint AddLevelName(KeyTypeInfo * /* type */ , | ||||
| 110 | unsigned /* level */ , | ||||
| 111 | Atom /* name */ , | ||||
| 112 | Boolint /* clobber */ , | ||||
| 113 | Boolint /* report */ | ||||
| 114 | ); | ||||
| 115 | |||||
| 116 | #define MapEntryTxt(t,x,e)XkbVModMaskText((t)->dpy,(x),(e)->mods.real_mods,(e)-> mods.vmods,3) \ | ||||
| 117 | XkbVModMaskText((t)->dpy,(x),(e)->mods.real_mods,(e)->mods.vmods,XkbMessage3) | ||||
| 118 | #define PreserveIndexTxt(t,x,p)XkbVModMaskText((t)->dpy,(x),(p)->indexMods,(p)->indexVMods ,3) \ | ||||
| 119 | XkbVModMaskText((t)->dpy,(x),(p)->indexMods,(p)->indexVMods,XkbMessage3) | ||||
| 120 | #define PreserveTxt(t,x,p)XkbVModMaskText((t)->dpy,(x),(p)->preMods,(p)->preVMods ,3) \ | ||||
| 121 | XkbVModMaskText((t)->dpy,(x),(p)->preMods,(p)->preVMods,XkbMessage3) | ||||
| 122 | #define TypeTxt(t)XkbAtomText((t)->dpy,(t)->name,3) XkbAtomText((t)->dpy,(t)->name,XkbMessage3) | ||||
| 123 | #define TypeMaskTxt(t,x)XkbVModMaskText((t)->dpy,(x),(t)->mask,(t)->vmask,3) \ | ||||
| 124 | XkbVModMaskText((t)->dpy,(x),(t)->mask,(t)->vmask,XkbMessage3) | ||||
| 125 | |||||
| 126 | /***====================================================================***/ | ||||
| 127 | |||||
| 128 | static void | ||||
| 129 | InitKeyTypesInfo(KeyTypesInfo * info, XkbDescPtr xkb, KeyTypesInfo * from) | ||||
| 130 | { | ||||
| 131 | tok_ONE_LEVEL = XkbInternAtom(NULL((void*)0), "ONE_LEVEL", False0); | ||||
| 132 | tok_TWO_LEVEL = XkbInternAtom(NULL((void*)0), "TWO_LEVEL", False0); | ||||
| 133 | tok_ALPHABETIC = XkbInternAtom(NULL((void*)0), "ALPHABETIC", False0); | ||||
| 134 | tok_KEYPAD = XkbInternAtom(NULL((void*)0), "KEYPAD", False0); | ||||
| 135 | info->dpy = NULL((void*)0); | ||||
| 136 | info->name = uStringDup("default")(("default") ? strdup("default") : ((void*)0)); | ||||
| 137 | info->errorCount = 0; | ||||
| 138 | info->stdPresent = 0; | ||||
| 139 | info->nTypes = 0; | ||||
| 140 | info->types = NULL((void*)0); | ||||
| 141 | info->dflt.defs.defined = 0; | ||||
| 142 | info->dflt.defs.fileID = 0; | ||||
| 143 | info->dflt.defs.merge = MergeOverride2; | ||||
| 144 | info->dflt.defs.next = NULL((void*)0); | ||||
| 145 | info->dflt.name = None0L; | ||||
| 146 | info->dflt.mask = 0; | ||||
| 147 | info->dflt.vmask = 0; | ||||
| 148 | info->dflt.groupInfo = False0; | ||||
| 149 | info->dflt.numLevels = 1; | ||||
| 150 | info->dflt.nEntries = info->dflt.szEntries = 0; | ||||
| 151 | info->dflt.entries = NULL((void*)0); | ||||
| 152 | info->dflt.szNames = 0; | ||||
| 153 | info->dflt.lvlNames = NULL((void*)0); | ||||
| 154 | info->dflt.preserve = NULL((void*)0); | ||||
| 155 | InitVModInfo(&info->vmods, xkb); | ||||
| 156 | if (from != NULL((void*)0)) | ||||
| 157 | { | ||||
| 158 | info->dpy = from->dpy; | ||||
| 159 | info->dflt = from->dflt; | ||||
| 160 | if (from->dflt.entries) | ||||
| 161 | { | ||||
| 162 | info->dflt.entries = uTypedCalloc(from->dflt.szEntries,((XkbKTMapEntryRec *)uCalloc((unsigned)from->dflt.szEntries ,(unsigned)sizeof(XkbKTMapEntryRec))) | ||||
| 163 | XkbKTMapEntryRec)((XkbKTMapEntryRec *)uCalloc((unsigned)from->dflt.szEntries ,(unsigned)sizeof(XkbKTMapEntryRec))); | ||||
| 164 | if (info->dflt.entries) | ||||
| 165 | { | ||||
| 166 | unsigned sz = from->dflt.nEntries * sizeof(XkbKTMapEntryRec); | ||||
| 167 | memcpy(info->dflt.entries, from->dflt.entries, sz); | ||||
| 168 | } | ||||
| 169 | } | ||||
| 170 | if (from->dflt.lvlNames) | ||||
| 171 | { | ||||
| 172 | info->dflt.lvlNames = uTypedCalloc(from->dflt.szNames, Atom)((Atom *)uCalloc((unsigned)from->dflt.szNames,(unsigned)sizeof (Atom))); | ||||
| 173 | if (info->dflt.lvlNames) | ||||
| 174 | { | ||||
| 175 | register unsigned sz = from->dflt.szNames * sizeof(Atom); | ||||
| 176 | memcpy(info->dflt.lvlNames, from->dflt.lvlNames, sz); | ||||
| 177 | } | ||||
| 178 | } | ||||
| 179 | if (from->dflt.preserve) | ||||
| 180 | { | ||||
| 181 | PreserveInfo *old, *new, *last; | ||||
| 182 | last = NULL((void*)0); | ||||
| 183 | old = from->dflt.preserve; | ||||
| 184 | for (; old; old = (PreserveInfo *) old->defs.next) | ||||
| 185 | { | ||||
| 186 | new = uTypedAlloc(PreserveInfo)((PreserveInfo *)uAlloc((unsigned)sizeof(PreserveInfo))); | ||||
| 187 | if (!new) | ||||
| 188 | return; | ||||
| 189 | *new = *old; | ||||
| 190 | new->defs.next = NULL((void*)0); | ||||
| 191 | if (last) | ||||
| 192 | last->defs.next = (CommonInfo *) new; | ||||
| 193 | else | ||||
| 194 | info->dflt.preserve = new; | ||||
| 195 | last = new; | ||||
| 196 | } | ||||
| 197 | } | ||||
| 198 | } | ||||
| 199 | return; | ||||
| 200 | } | ||||
| 201 | |||||
| 202 | static void | ||||
| 203 | FreeKeyTypeInfo(KeyTypeInfo * type) | ||||
| 204 | { | ||||
| 205 | if (type->entries != NULL((void*)0)) | ||||
| 206 | { | ||||
| 207 | uFree(type->entries); | ||||
| 208 | type->entries = NULL((void*)0); | ||||
| 209 | } | ||||
| 210 | if (type->lvlNames != NULL((void*)0)) | ||||
| 211 | { | ||||
| 212 | uFree(type->lvlNames); | ||||
| 213 | type->lvlNames = NULL((void*)0); | ||||
| 214 | } | ||||
| 215 | if (type->preserve != NULL((void*)0)) | ||||
| 216 | { | ||||
| 217 | ClearCommonInfo(&type->preserve->defs); | ||||
| 218 | type->preserve = NULL((void*)0); | ||||
| 219 | } | ||||
| 220 | return; | ||||
| 221 | } | ||||
| 222 | |||||
| 223 | static void | ||||
| 224 | FreeKeyTypesInfo(KeyTypesInfo * info) | ||||
| 225 | { | ||||
| 226 | info->dpy = NULL((void*)0); | ||||
| 227 | if (info->name) | ||||
| 228 | uFree(info->name); | ||||
| 229 | info->name = NULL((void*)0); | ||||
| 230 | if (info->types) | ||||
| 231 | { | ||||
| 232 | register KeyTypeInfo *type; | ||||
| 233 | for (type = info->types; type; type = (KeyTypeInfo *) type->defs.next) | ||||
| 234 | { | ||||
| 235 | FreeKeyTypeInfo(type); | ||||
| 236 | } | ||||
| 237 | info->types = (KeyTypeInfo *) ClearCommonInfo(&info->types->defs); | ||||
| 238 | } | ||||
| 239 | FreeKeyTypeInfo(&info->dflt); | ||||
| 240 | return; | ||||
| 241 | } | ||||
| 242 | |||||
| 243 | static KeyTypeInfo * | ||||
| 244 | NextKeyType(KeyTypesInfo * info) | ||||
| 245 | { | ||||
| 246 | KeyTypeInfo *type; | ||||
| 247 | |||||
| 248 | type = uTypedAlloc(KeyTypeInfo)((KeyTypeInfo *)uAlloc((unsigned)sizeof(KeyTypeInfo))); | ||||
| 249 | if (type != NULL((void*)0)) | ||||
| 250 | { | ||||
| 251 | bzero(type, sizeof(KeyTypeInfo))memset(type,0,sizeof(KeyTypeInfo)); | ||||
| 252 | type->defs.fileID = info->fileID; | ||||
| 253 | type->dpy = info->dpy; | ||||
| 254 | info->types = (KeyTypeInfo *) AddCommonInfo(&info->types->defs, | ||||
| 255 | (CommonInfo *) type); | ||||
| 256 | info->nTypes++; | ||||
| 257 | } | ||||
| 258 | return type; | ||||
| 259 | } | ||||
| 260 | |||||
| 261 | static KeyTypeInfo * | ||||
| 262 | FindMatchingKeyType(KeyTypesInfo * info, KeyTypeInfo * new) | ||||
| 263 | { | ||||
| 264 | KeyTypeInfo *old; | ||||
| 265 | |||||
| 266 | for (old = info->types; old; old = (KeyTypeInfo *) old->defs.next) | ||||
| 267 | { | ||||
| 268 | if (old->name == new->name) | ||||
| 269 | return old; | ||||
| 270 | } | ||||
| 271 | return NULL((void*)0); | ||||
| 272 | } | ||||
| 273 | |||||
| 274 | static Boolint | ||||
| 275 | ReportTypeBadWidth(const char *type, int has, int needs) | ||||
| 276 | { | ||||
| 277 | ERROR3uError("Key type \"%s\" has %d levels, must have %d\n", type, has, needs); | ||||
| 278 | ACTIONuAction("Illegal type definition ignored\n"); | ||||
| 279 | return False0; | ||||
| 280 | } | ||||
| 281 | |||||
| 282 | static Boolint | ||||
| 283 | AddKeyType(XkbDescPtr xkb, KeyTypesInfo * info, KeyTypeInfo * new) | ||||
| 284 | { | ||||
| 285 | KeyTypeInfo *old; | ||||
| 286 | |||||
| 287 | if (new->name == tok_ONE_LEVEL) | ||||
| 288 | { | ||||
| 289 | if (new->numLevels > 1) | ||||
| 290 | return ReportTypeBadWidth("ONE_LEVEL", new->numLevels, 1); | ||||
| 291 | info->stdPresent |= XkbOneLevelMask(1<<0); | ||||
| 292 | } | ||||
| 293 | else if (new->name == tok_TWO_LEVEL) | ||||
| 294 | { | ||||
| 295 | if (new->numLevels > 2) | ||||
| 296 | return ReportTypeBadWidth("TWO_LEVEL", new->numLevels, 2); | ||||
| 297 | else if (new->numLevels < 2) | ||||
| 298 | new->numLevels = 2; | ||||
| 299 | info->stdPresent |= XkbTwoLevelMask(1<<1); | ||||
| 300 | } | ||||
| 301 | else if (new->name == tok_ALPHABETIC) | ||||
| 302 | { | ||||
| 303 | if (new->numLevels > 2) | ||||
| 304 | return ReportTypeBadWidth("ALPHABETIC", new->numLevels, 2); | ||||
| 305 | else if (new->numLevels < 2) | ||||
| 306 | new->numLevels = 2; | ||||
| 307 | info->stdPresent |= XkbAlphabeticMask(1<<2); | ||||
| 308 | } | ||||
| 309 | else if (new->name == tok_KEYPAD) | ||||
| 310 | { | ||||
| 311 | if (new->numLevels > 2) | ||||
| 312 | return ReportTypeBadWidth("KEYPAD", new->numLevels, 2); | ||||
| 313 | else if (new->numLevels < 2) | ||||
| 314 | new->numLevels = 2; | ||||
| 315 | info->stdPresent |= XkbKeypadMask(1<<3); | ||||
| 316 | } | ||||
| 317 | |||||
| 318 | old = FindMatchingKeyType(info, new); | ||||
| 319 | if (old != NULL((void*)0)) | ||||
| 320 | { | ||||
| 321 | Boolint report; | ||||
| 322 | if ((new->defs.merge == MergeReplace3) | ||||
| 323 | || (new->defs.merge == MergeOverride2)) | ||||
| 324 | { | ||||
| 325 | KeyTypeInfo *next = (KeyTypeInfo *) old->defs.next; | ||||
| 326 | if (((old->defs.fileID == new->defs.fileID) | ||||
| 327 | && (warningLevel > 0)) || (warningLevel > 9)) | ||||
| 328 | { | ||||
| 329 | WARN1uWarning("Multiple definitions of the %s key type\n", | ||||
| 330 | XkbAtomGetString(NULL((void*)0), new->name)); | ||||
| 331 | ACTIONuAction("Earlier definition ignored\n"); | ||||
| 332 | } | ||||
| 333 | FreeKeyTypeInfo(old); | ||||
| 334 | *old = *new; | ||||
| 335 | new->szEntries = new->nEntries = 0; | ||||
| 336 | new->entries = NULL((void*)0); | ||||
| 337 | new->preserve = NULL((void*)0); | ||||
| 338 | new->lvlNames = NULL((void*)0); | ||||
| 339 | old->defs.next = &next->defs; | ||||
| 340 | return True1; | ||||
| 341 | } | ||||
| 342 | report = (old->defs.fileID == new->defs.fileID) && (warningLevel > 0); | ||||
| 343 | if (report) | ||||
| 344 | { | ||||
| 345 | WARN1uWarning("Multiple definitions of the %s key type\n", | ||||
| 346 | XkbAtomGetString(NULL((void*)0), new->name)); | ||||
| 347 | ACTIONuAction("Later definition ignored\n"); | ||||
| 348 | } | ||||
| 349 | FreeKeyTypeInfo(new); | ||||
| 350 | return True1; | ||||
| 351 | } | ||||
| 352 | old = NextKeyType(info); | ||||
| 353 | if (old == NULL((void*)0)) | ||||
| 354 | return False0; | ||||
| 355 | *old = *new; | ||||
| 356 | old->defs.next = NULL((void*)0); | ||||
| 357 | new->nEntries = new->szEntries = 0; | ||||
| 358 | new->entries = NULL((void*)0); | ||||
| 359 | new->szNames = 0; | ||||
| 360 | new->lvlNames = NULL((void*)0); | ||||
| 361 | new->preserve = NULL((void*)0); | ||||
| 362 | return True1; | ||||
| 363 | } | ||||
| 364 | |||||
| 365 | /***====================================================================***/ | ||||
| 366 | |||||
| 367 | static void | ||||
| 368 | MergeIncludedKeyTypes(KeyTypesInfo * into, | ||||
| 369 | KeyTypesInfo * from, unsigned merge, XkbDescPtr xkb) | ||||
| 370 | { | ||||
| 371 | KeyTypeInfo *type; | ||||
| 372 | |||||
| 373 | if (from->errorCount > 0) | ||||
| 374 | { | ||||
| 375 | into->errorCount += from->errorCount; | ||||
| 376 | return; | ||||
| 377 | } | ||||
| 378 | if (into->name == NULL((void*)0)) | ||||
| 379 | { | ||||
| 380 | into->name = from->name; | ||||
| 381 | from->name = NULL((void*)0); | ||||
| 382 | } | ||||
| 383 | for (type = from->types; type; type = (KeyTypeInfo *) type->defs.next) | ||||
| 384 | { | ||||
| 385 | if (merge != MergeDefault0) | ||||
| 386 | type->defs.merge = merge; | ||||
| 387 | if (!AddKeyType(xkb, into, type)) | ||||
| 388 | into->errorCount++; | ||||
| 389 | } | ||||
| 390 | into->stdPresent |= from->stdPresent; | ||||
| 391 | return; | ||||
| 392 | } | ||||
| 393 | |||||
| 394 | typedef void (*FileHandler) (XkbFile * /* file */ , | ||||
| 395 | XkbDescPtr /* xkb */ , | ||||
| 396 | unsigned /* merge */ , | ||||
| 397 | KeyTypesInfo * /* included */ | ||||
| 398 | ); | ||||
| 399 | |||||
| 400 | static Boolint | ||||
| 401 | HandleIncludeKeyTypes(IncludeStmt * stmt, | ||||
| 402 | XkbDescPtr xkb, KeyTypesInfo * info, FileHandler hndlr) | ||||
| 403 | { | ||||
| 404 | unsigned newMerge; | ||||
| 405 | XkbFile *rtrn; | ||||
| 406 | KeyTypesInfo included; | ||||
| 407 | Boolint haveSelf; | ||||
| 408 | |||||
| 409 | haveSelf = False0; | ||||
| 410 | if ((stmt->file == NULL((void*)0)) && (stmt->map == NULL((void*)0))) | ||||
| 411 | { | ||||
| 412 | haveSelf = True1; | ||||
| 413 | included = *info; | ||||
| 414 | bzero(info, sizeof(KeyTypesInfo))memset(info,0,sizeof(KeyTypesInfo)); | ||||
| 415 | } | ||||
| 416 | else if (ProcessIncludeFile(stmt, XkmTypesIndex0, &rtrn, &newMerge)) | ||||
| 417 | { | ||||
| 418 | InitKeyTypesInfo(&included, xkb, info); | ||||
| 419 | included.fileID = included.dflt.defs.fileID = rtrn->id; | ||||
| 420 | included.dflt.defs.merge = newMerge; | ||||
| 421 | |||||
| 422 | (*hndlr) (rtrn, xkb, newMerge, &included); | ||||
| 423 | if (stmt->stmt != NULL((void*)0)) | ||||
| 424 | { | ||||
| 425 | if (included.name != NULL((void*)0)) | ||||
| 426 | uFree(included.name); | ||||
| 427 | included.name = stmt->stmt; | ||||
| 428 | stmt->stmt = NULL((void*)0); | ||||
| 429 | } | ||||
| 430 | } | ||||
| 431 | else | ||||
| 432 | { | ||||
| 433 | info->errorCount += 10; | ||||
| 434 | return False0; | ||||
| 435 | } | ||||
| 436 | if ((stmt->next != NULL((void*)0)) && (included.errorCount < 1)) | ||||
| 437 | { | ||||
| 438 | IncludeStmt *next; | ||||
| 439 | unsigned op; | ||||
| 440 | KeyTypesInfo next_incl; | ||||
| 441 | |||||
| 442 | for (next = stmt->next; next != NULL((void*)0); next = next->next) | ||||
| 443 | { | ||||
| 444 | if ((next->file == NULL((void*)0)) && (next->map == NULL((void*)0))) | ||||
| 445 | { | ||||
| 446 | haveSelf = True1; | ||||
| 447 | MergeIncludedKeyTypes(&included, info, next->merge, xkb); | ||||
| 448 | FreeKeyTypesInfo(info); | ||||
| 449 | } | ||||
| 450 | else if (ProcessIncludeFile(next, XkmTypesIndex0, &rtrn, &op)) | ||||
| 451 | { | ||||
| 452 | InitKeyTypesInfo(&next_incl, xkb, &included); | ||||
| 453 | next_incl.fileID = next_incl.dflt.defs.fileID = rtrn->id; | ||||
| 454 | next_incl.dflt.defs.merge = op; | ||||
| 455 | (*hndlr) (rtrn, xkb, op, &next_incl); | ||||
| 456 | MergeIncludedKeyTypes(&included, &next_incl, op, xkb); | ||||
| 457 | FreeKeyTypesInfo(&next_incl); | ||||
| 458 | } | ||||
| 459 | else | ||||
| 460 | { | ||||
| 461 | info->errorCount += 10; | ||||
| 462 | return False0; | ||||
| 463 | } | ||||
| 464 | } | ||||
| 465 | } | ||||
| 466 | if (haveSelf) | ||||
| 467 | *info = included; | ||||
| 468 | else | ||||
| 469 | { | ||||
| 470 | MergeIncludedKeyTypes(info, &included, newMerge, xkb); | ||||
| 471 | FreeKeyTypesInfo(&included); | ||||
| 472 | } | ||||
| 473 | return (info->errorCount == 0); | ||||
| 474 | } | ||||
| 475 | |||||
| 476 | /***====================================================================***/ | ||||
| 477 | |||||
| 478 | static XkbKTMapEntryPtr | ||||
| 479 | FindMatchingMapEntry(KeyTypeInfo * type, unsigned mask, unsigned vmask) | ||||
| 480 | { | ||||
| 481 | register int i; | ||||
| 482 | XkbKTMapEntryPtr entry; | ||||
| 483 | |||||
| 484 | for (i = 0, entry = type->entries; i < type->nEntries; i++, entry++) | ||||
| 485 | { | ||||
| 486 | if ((entry->mods.real_mods == mask) && (entry->mods.vmods == vmask)) | ||||
| 487 | return entry; | ||||
| 488 | } | ||||
| 489 | return NULL((void*)0); | ||||
| 490 | } | ||||
| 491 | |||||
| 492 | static void | ||||
| 493 | DeleteLevel1MapEntries(KeyTypeInfo * type) | ||||
| 494 | { | ||||
| 495 | register int i, n; | ||||
| 496 | |||||
| 497 | for (i = 0; i < type->nEntries; i++) | ||||
| 498 | { | ||||
| 499 | if (type->entries[i].level == 0) | ||||
| 500 | { | ||||
| 501 | for (n = i; n < type->nEntries - 1; n++) | ||||
| 502 | { | ||||
| 503 | type->entries[n] = type->entries[n + 1]; | ||||
| 504 | } | ||||
| 505 | type->nEntries--; | ||||
| 506 | } | ||||
| 507 | } | ||||
| 508 | return; | ||||
| 509 | } | ||||
| 510 | |||||
| 511 | /** | ||||
| 512 | * Return a pointer to the next free XkbKTMapEntry, reallocating space if | ||||
| 513 | * necessary. | ||||
| 514 | */ | ||||
| 515 | static XkbKTMapEntryPtr | ||||
| 516 | NextMapEntry(KeyTypeInfo * type) | ||||
| 517 | { | ||||
| 518 | if (type->entries == NULL((void*)0)) | ||||
| 519 | { | ||||
| 520 | type->entries = uTypedCalloc(2, XkbKTMapEntryRec)((XkbKTMapEntryRec *)uCalloc((unsigned)2,(unsigned)sizeof(XkbKTMapEntryRec ))); | ||||
| 521 | if (type->entries == NULL((void*)0)) | ||||
| 522 | { | ||||
| 523 | ERROR1uError("Couldn't allocate map entries for %s\n", TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 524 | ACTIONuAction("Map entries lost\n"); | ||||
| 525 | return NULL((void*)0); | ||||
| 526 | } | ||||
| 527 | type->szEntries = 2; | ||||
| 528 | type->nEntries = 0; | ||||
| 529 | } | ||||
| 530 | else if (type->nEntries >= type->szEntries) | ||||
| 531 | { | ||||
| 532 | type->szEntries *= 2; | ||||
| 533 | type->entries = uTypedRecalloc(type->entries,((XkbKTMapEntryRec *)uRecalloc((Opaque)type->entries,((unsigned )type->nEntries),((unsigned)type->szEntries),sizeof(XkbKTMapEntryRec ))) | ||||
| 534 | type->nEntries, type->szEntries,((XkbKTMapEntryRec *)uRecalloc((Opaque)type->entries,((unsigned )type->nEntries),((unsigned)type->szEntries),sizeof(XkbKTMapEntryRec ))) | ||||
| 535 | XkbKTMapEntryRec)((XkbKTMapEntryRec *)uRecalloc((Opaque)type->entries,((unsigned )type->nEntries),((unsigned)type->szEntries),sizeof(XkbKTMapEntryRec ))); | ||||
| 536 | if (type->entries == NULL((void*)0)) | ||||
| 537 | { | ||||
| 538 | ERROR1uError("Couldn't reallocate map entries for %s\n", TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 539 | ACTIONuAction("Map entries lost\n"); | ||||
| 540 | return NULL((void*)0); | ||||
| 541 | } | ||||
| 542 | } | ||||
| 543 | return &type->entries[type->nEntries++]; | ||||
| 544 | } | ||||
| 545 | |||||
| 546 | Boolint | ||||
| 547 | AddPreserve(XkbDescPtr xkb, | ||||
| 548 | KeyTypeInfo * type, PreserveInfo * new, Boolint clobber, Boolint report) | ||||
| 549 | { | ||||
| 550 | PreserveInfo *old; | ||||
| 551 | |||||
| 552 | old = type->preserve; | ||||
| 553 | while (old != NULL((void*)0)) | ||||
| |||||
| |||||
| 554 | { | ||||
| 555 | if ((old->indexMods != new->indexMods) || | ||||
| 556 | (old->indexVMods != new->indexVMods)) | ||||
| 557 | { | ||||
| 558 | old = (PreserveInfo *) old->defs.next; | ||||
| 559 | continue; | ||||
| 560 | } | ||||
| 561 | if ((old->preMods == new->preMods) | ||||
| 562 | && (old->preVMods == new->preVMods)) | ||||
| 563 | { | ||||
| 564 | if (warningLevel > 9) | ||||
| 565 | { | ||||
| 566 | WARN2uWarning("Identical definitions for preserve[%s] in %s\n", | ||||
| 567 | PreserveIndexTxt(type, xkb, old)XkbVModMaskText((type)->dpy,(xkb),(old)->indexMods,(old )->indexVMods,3), TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 568 | ACTIONuAction("Ignored\n"); | ||||
| 569 | } | ||||
| 570 | return True1; | ||||
| 571 | } | ||||
| 572 | if (report && (warningLevel > 0)) | ||||
| 573 | { | ||||
| 574 | char *str; | ||||
| 575 | WARN2uWarning("Multiple definitions for preserve[%s] in %s\n", | ||||
| 576 | PreserveIndexTxt(type, xkb, old)XkbVModMaskText((type)->dpy,(xkb),(old)->indexMods,(old )->indexVMods,3), TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 577 | |||||
| 578 | if (clobber) | ||||
| 579 | str = PreserveTxt(type, xkb, new)XkbVModMaskText((type)->dpy,(xkb),(new)->preMods,(new)-> preVMods,3); | ||||
| 580 | else | ||||
| 581 | str = PreserveTxt(type, xkb, old)XkbVModMaskText((type)->dpy,(xkb),(old)->preMods,(old)-> preVMods,3); | ||||
| 582 | ACTION1uAction("Using %s, ", str); | ||||
| 583 | if (clobber) | ||||
| 584 | str = PreserveTxt(type, xkb, old)XkbVModMaskText((type)->dpy,(xkb),(old)->preMods,(old)-> preVMods,3); | ||||
| 585 | else | ||||
| 586 | str = PreserveTxt(type, xkb, new)XkbVModMaskText((type)->dpy,(xkb),(new)->preMods,(new)-> preVMods,3); | ||||
| 587 | INFO1uInformation("ignoring %s\n", str); | ||||
| 588 | } | ||||
| 589 | if (clobber) | ||||
| 590 | { | ||||
| 591 | old->preMods = new->preMods; | ||||
| 592 | old->preVMods = new->preVMods; | ||||
| 593 | } | ||||
| 594 | return True1; | ||||
| 595 | } | ||||
| 596 | old = uTypedAlloc(PreserveInfo)((PreserveInfo *)uAlloc((unsigned)sizeof(PreserveInfo))); | ||||
| 597 | if (!old) | ||||
| |||||
| |||||
| 598 | { | ||||
| 599 | WSGO1uInternalError("Couldn't allocate preserve in %s\n", TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 600 | ACTION1uAction("Preserve[%s] lost\n", PreserveIndexTxt(type, xkb, old)XkbVModMaskText((type)->dpy,(xkb),(old)->indexMods,(old )->indexVMods,3)); | ||||
| |||||
| 601 | return False0; | ||||
| 602 | } | ||||
| 603 | *old = *new; | ||||
| 604 | old->matchingMapIndex = -1; | ||||
| 605 | type->preserve = | ||||
| 606 | (PreserveInfo *) AddCommonInfo(&type->preserve->defs, &old->defs); | ||||
| 607 | return True1; | ||||
| 608 | } | ||||
| 609 | |||||
| 610 | /** | ||||
| 611 | * Add a new KTMapEntry to the given key type. If an entry with the same mods | ||||
| 612 | * already exists, the level is updated (if clobber is TRUE). Otherwise, a new | ||||
| 613 | * entry is created. | ||||
| 614 | * | ||||
| 615 | * @param clobber Overwrite existing entry. | ||||
| 616 | * @param report True if a warning is to be printed on. | ||||
| 617 | */ | ||||
| 618 | Boolint | ||||
| 619 | AddMapEntry(XkbDescPtr xkb, | ||||
| 620 | KeyTypeInfo * type, | ||||
| 621 | XkbKTMapEntryPtr new, Boolint clobber, Boolint report) | ||||
| 622 | { | ||||
| 623 | XkbKTMapEntryPtr old; | ||||
| 624 | |||||
| 625 | if ((old = | ||||
| 626 | FindMatchingMapEntry(type, new->mods.real_mods, new->mods.vmods))) | ||||
| 627 | { | ||||
| 628 | if (report && (old->level != new->level)) | ||||
| 629 | { | ||||
| 630 | unsigned use, ignore; | ||||
| 631 | if (clobber) | ||||
| 632 | { | ||||
| 633 | use = new->level + 1; | ||||
| 634 | ignore = old->level + 1; | ||||
| 635 | } | ||||
| 636 | else | ||||
| 637 | { | ||||
| 638 | use = old->level + 1; | ||||
| 639 | ignore = new->level + 1; | ||||
| 640 | } | ||||
| 641 | WARN2uWarning("Multiple map entries for %s in %s\n", | ||||
| 642 | MapEntryTxt(type, xkb, new)XkbVModMaskText((type)->dpy,(xkb),(new)->mods.real_mods ,(new)->mods.vmods,3), TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 643 | ACTION2uAction("Using %d, ignoring %d\n", use, ignore); | ||||
| 644 | } | ||||
| 645 | else if (warningLevel > 9) | ||||
| 646 | { | ||||
| 647 | WARN3uWarning("Multiple occurences of map[%s]= %d in %s\n", | ||||
| 648 | MapEntryTxt(type, xkb, new)XkbVModMaskText((type)->dpy,(xkb),(new)->mods.real_mods ,(new)->mods.vmods,3), new->level + 1, TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 649 | ACTIONuAction("Ignored\n"); | ||||
| 650 | return True1; | ||||
| 651 | } | ||||
| 652 | if (clobber) | ||||
| 653 | old->level = new->level; | ||||
| 654 | return True1; | ||||
| 655 | } | ||||
| 656 | if ((old = NextMapEntry(type)) == NULL((void*)0)) | ||||
| 657 | return False0; /* allocation failure, already reported */ | ||||
| 658 | if (new->level >= type->numLevels) | ||||
| 659 | type->numLevels = new->level + 1; | ||||
| 660 | if (new->mods.vmods == 0) | ||||
| 661 | old->active = True1; | ||||
| 662 | else | ||||
| 663 | old->active = False0; | ||||
| 664 | old->mods.mask = new->mods.real_mods; | ||||
| 665 | old->mods.real_mods = new->mods.real_mods; | ||||
| 666 | old->mods.vmods = new->mods.vmods; | ||||
| 667 | old->level = new->level; | ||||
| 668 | return True1; | ||||
| 669 | } | ||||
| 670 | |||||
| 671 | static LookupEntry lnames[] = { | ||||
| 672 | {"level1", 1}, | ||||
| 673 | {"level2", 2}, | ||||
| 674 | {"level3", 3}, | ||||
| 675 | {"level4", 4}, | ||||
| 676 | {"level5", 5}, | ||||
| 677 | {"level6", 6}, | ||||
| 678 | {"level7", 7}, | ||||
| 679 | {"level8", 8}, | ||||
| 680 | {NULL((void*)0), 0} | ||||
| 681 | }; | ||||
| 682 | |||||
| 683 | static Boolint | ||||
| 684 | SetMapEntry(KeyTypeInfo * type, | ||||
| 685 | XkbDescPtr xkb, ExprDef * arrayNdx, ExprDef * value) | ||||
| 686 | { | ||||
| 687 | ExprResult rtrn; | ||||
| 688 | XkbKTMapEntryRec entry; | ||||
| 689 | |||||
| 690 | if (arrayNdx == NULL((void*)0)) | ||||
| 691 | return ReportTypeShouldBeArray(type, "map entry")ReportShouldBeArray("key type",("map entry"),XkbAtomText((type )->dpy,(type)->name,3)); | ||||
| 692 | if (!ExprResolveModMask(arrayNdx, &rtrn, LookupVModMask, (XPointer) xkb)) | ||||
| 693 | return ReportTypeBadType(type, "map entry", "modifier mask")ReportBadType("key type",("map entry"),XkbAtomText((type)-> dpy,(type)->name,3),("modifier mask")); | ||||
| 694 | entry.mods.real_mods = rtrn.uval & 0xff; /* modifiers < 512 */ | ||||
| 695 | entry.mods.vmods = (rtrn.uval >> 8) & 0xffff; /* modifiers > 512 */ | ||||
| 696 | if ((entry.mods.real_mods & (~type->mask)) || | ||||
| 697 | ((entry.mods.vmods & (~type->vmask)) != 0)) | ||||
| 698 | { | ||||
| 699 | if (warningLevel > 0) | ||||
| 700 | { | ||||
| 701 | WARN1uWarning("Map entry for unused modifiers in %s\n", TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 702 | ACTION1uAction("Using %s instead of ", | ||||
| 703 | XkbVModMaskText(type->dpy, xkb, | ||||
| 704 | entry.mods.real_mods & type->mask, | ||||
| 705 | entry.mods.vmods & type->vmask, | ||||
| 706 | XkbMessage3)); | ||||
| 707 | INFO1uInformation("%s\n", MapEntryTxt(type, xkb, &entry)XkbVModMaskText((type)->dpy,(xkb),(&entry)->mods.real_mods ,(&entry)->mods.vmods,3)); | ||||
| 708 | } | ||||
| 709 | entry.mods.real_mods &= type->mask; | ||||
| 710 | entry.mods.vmods &= type->vmask; | ||||
| 711 | } | ||||
| 712 | if (!ExprResolveInteger(value, &rtrn, SimpleLookup, (XPointer) lnames)) | ||||
| 713 | { | ||||
| 714 | ERRORuError("Level specifications in a key type must be integer\n"); | ||||
| 715 | ACTIONuAction("Ignoring malformed level specification\n"); | ||||
| 716 | return False0; | ||||
| 717 | } | ||||
| 718 | if ((rtrn.ival < 1) || (rtrn.ival > XkbMaxShiftLevel63 + 1)) | ||||
| 719 | { | ||||
| 720 | ERROR3uError("Shift level %d out of range (1..%d) in key type %s\n", | ||||
| 721 | XkbMaxShiftLevel63 + 1, rtrn.ival, TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 722 | ACTION1uAction("Ignoring illegal definition of map[%s]\n", | ||||
| 723 | MapEntryTxt(type, xkb, &entry)XkbVModMaskText((type)->dpy,(xkb),(&entry)->mods.real_mods ,(&entry)->mods.vmods,3)); | ||||
| 724 | return False0; | ||||
| 725 | } | ||||
| 726 | entry.level = rtrn.ival - 1; | ||||
| 727 | return AddMapEntry(xkb, type, &entry, True1, True1); | ||||
| 728 | } | ||||
| 729 | |||||
| 730 | static Boolint | ||||
| 731 | SetPreserve(KeyTypeInfo * type, | ||||
| 732 | XkbDescPtr xkb, ExprDef * arrayNdx, ExprDef * value) | ||||
| 733 | { | ||||
| 734 | ExprResult rtrn; | ||||
| 735 | PreserveInfo new; | ||||
| 736 | |||||
| 737 | if (arrayNdx == NULL((void*)0)) | ||||
| 738 | return ReportTypeShouldBeArray(type, "preserve entry")ReportShouldBeArray("key type",("preserve entry"),XkbAtomText ((type)->dpy,(type)->name,3)); | ||||
| 739 | if (!ExprResolveModMask(arrayNdx, &rtrn, LookupVModMask, (XPointer) xkb)) | ||||
| 740 | return ReportTypeBadType(type, "preserve entry", "modifier mask")ReportBadType("key type",("preserve entry"),XkbAtomText((type )->dpy,(type)->name,3),("modifier mask")); | ||||
| 741 | new.defs = type->defs; | ||||
| 742 | new.defs.next = NULL((void*)0); | ||||
| 743 | new.indexMods = rtrn.uval & 0xff; | ||||
| 744 | new.indexVMods = (rtrn.uval >> 8) & 0xffff; | ||||
| 745 | if ((new.indexMods & (~type->mask)) || (new.indexVMods & (~type->vmask))) | ||||
| 746 | { | ||||
| 747 | if (warningLevel > 0) | ||||
| 748 | { | ||||
| 749 | WARN1uWarning("Preserve for modifiers not used by the %s type\n", | ||||
| 750 | TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 751 | ACTION1uAction("Index %s converted to ", | ||||
| 752 | PreserveIndexTxt(type, xkb, &new)XkbVModMaskText((type)->dpy,(xkb),(&new)->indexMods ,(&new)->indexVMods,3)); | ||||
| 753 | } | ||||
| 754 | new.indexMods &= type->mask; | ||||
| 755 | new.indexVMods &= type->vmask; | ||||
| 756 | if (warningLevel > 0) | ||||
| 757 | INFO1uInformation("%s\n", PreserveIndexTxt(type, xkb, &new)XkbVModMaskText((type)->dpy,(xkb),(&new)->indexMods ,(&new)->indexVMods,3)); | ||||
| 758 | } | ||||
| 759 | if (!ExprResolveModMask(value, &rtrn, LookupVModMask, (XPointer) xkb)) | ||||
| 760 | { | ||||
| 761 | ERRORuError("Preserve value in a key type is not a modifier mask\n"); | ||||
| 762 | ACTION2uAction("Ignoring preserve[%s] in type %s\n", | ||||
| 763 | PreserveIndexTxt(type, xkb, &new)XkbVModMaskText((type)->dpy,(xkb),(&new)->indexMods ,(&new)->indexVMods,3), TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 764 | return False0; | ||||
| 765 | } | ||||
| 766 | new.preMods = rtrn.uval & 0xff; | ||||
| 767 | new.preVMods = (rtrn.uval >> 16) & 0xffff; | ||||
| 768 | if ((new.preMods & (~new.indexMods)) | ||||
| 769 | || (new.preVMods && (~new.indexVMods))) | ||||
| 770 | { | ||||
| 771 | if (warningLevel > 0) | ||||
| 772 | { | ||||
| 773 | WARN2uWarning("Illegal value for preserve[%s] in type %s\n", | ||||
| 774 | PreserveTxt(type, xkb, &new)XkbVModMaskText((type)->dpy,(xkb),(&new)->preMods,( &new)->preVMods,3), TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 775 | ACTION1uAction("Converted %s to ", PreserveIndexTxt(type, xkb, &new)XkbVModMaskText((type)->dpy,(xkb),(&new)->indexMods ,(&new)->indexVMods,3)); | ||||
| 776 | } | ||||
| 777 | new.preMods &= new.indexMods; | ||||
| 778 | new.preVMods &= new.indexVMods; | ||||
| 779 | if (warningLevel > 0) | ||||
| 780 | { | ||||
| 781 | INFO1uInformation("%s\n", PreserveIndexTxt(type, xkb, &new)XkbVModMaskText((type)->dpy,(xkb),(&new)->indexMods ,(&new)->indexVMods,3)); | ||||
| 782 | } | ||||
| 783 | } | ||||
| 784 | return AddPreserve(xkb, type, &new, True1, True1); | ||||
| 785 | } | ||||
| 786 | |||||
| 787 | /***====================================================================***/ | ||||
| 788 | |||||
| 789 | Boolint | ||||
| 790 | AddLevelName(KeyTypeInfo * type, | ||||
| 791 | unsigned level, Atom name, Boolint clobber, Boolint report) | ||||
| 792 | { | ||||
| 793 | if ((type->lvlNames == NULL((void*)0)) || (type->szNames <= level)) | ||||
| 794 | { | ||||
| 795 | type->lvlNames = | ||||
| 796 | uTypedRecalloc(type->lvlNames, type->szNames, level + 1, Atom)((Atom *)uRecalloc((Opaque)type->lvlNames,((unsigned)type-> szNames),((unsigned)level + 1),sizeof(Atom))); | ||||
| 797 | if (type->lvlNames == NULL((void*)0)) | ||||
| 798 | { | ||||
| 799 | ERROR1uError("Couldn't allocate level names for type %s\n", | ||||
| 800 | TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 801 | ACTIONuAction("Level names lost\n"); | ||||
| 802 | type->szNames = 0; | ||||
| 803 | return False0; | ||||
| 804 | } | ||||
| 805 | type->szNames = level + 1; | ||||
| 806 | } | ||||
| 807 | else if (type->lvlNames[level] == name) | ||||
| 808 | { | ||||
| 809 | if (warningLevel > 9) | ||||
| 810 | { | ||||
| 811 | WARN2uWarning("Duplicate names for level %d of key type %s\n", | ||||
| 812 | level + 1, TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 813 | ACTIONuAction("Ignored\n"); | ||||
| 814 | } | ||||
| 815 | return True1; | ||||
| 816 | } | ||||
| 817 | else if (type->lvlNames[level] != None0L) | ||||
| 818 | { | ||||
| 819 | if (warningLevel > 0) | ||||
| 820 | { | ||||
| 821 | char *old, *new; | ||||
| 822 | old = XkbAtomText(type->dpy, type->lvlNames[level], XkbMessage3); | ||||
| 823 | new = XkbAtomText(type->dpy, name, XkbMessage3); | ||||
| 824 | WARN2uWarning("Multiple names for level %d of key type %s\n", | ||||
| 825 | level + 1, TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 826 | if (clobber) | ||||
| 827 | ACTION2uAction("Using %s, ignoring %s\n", new, old); | ||||
| 828 | else | ||||
| 829 | ACTION2uAction("Using %s, ignoring %s\n", old, new); | ||||
| 830 | } | ||||
| 831 | if (!clobber) | ||||
| 832 | return True1; | ||||
| 833 | } | ||||
| 834 | if (level >= type->numLevels) | ||||
| 835 | type->numLevels = level + 1; | ||||
| 836 | type->lvlNames[level] = name; | ||||
| 837 | return True1; | ||||
| 838 | } | ||||
| 839 | |||||
| 840 | static Boolint | ||||
| 841 | SetLevelName(KeyTypeInfo * type, ExprDef * arrayNdx, ExprDef * value) | ||||
| 842 | { | ||||
| 843 | ExprResult rtrn; | ||||
| 844 | unsigned level; | ||||
| 845 | |||||
| 846 | if (arrayNdx == NULL((void*)0)) | ||||
| 847 | return ReportTypeShouldBeArray(type, "level name")ReportShouldBeArray("key type",("level name"),XkbAtomText((type )->dpy,(type)->name,3)); | ||||
| 848 | if (!ExprResolveInteger(arrayNdx, &rtrn, SimpleLookup, (XPointer) lnames)) | ||||
| 849 | return ReportTypeBadType(type, "level name", "integer")ReportBadType("key type",("level name"),XkbAtomText((type)-> dpy,(type)->name,3),("integer")); | ||||
| 850 | if ((rtrn.ival < 1) || (rtrn.ival > XkbMaxShiftLevel63 + 1)) | ||||
| 851 | { | ||||
| 852 | ERROR3uError("Level name %d out of range (1..%d) in key type %s\n", | ||||
| 853 | rtrn.ival, | ||||
| 854 | XkbMaxShiftLevel63 + 1, | ||||
| 855 | XkbAtomText(type->dpy, type->name, XkbMessage3)); | ||||
| 856 | ACTIONuAction("Ignoring illegal level name definition\n"); | ||||
| 857 | return False0; | ||||
| 858 | } | ||||
| 859 | level = rtrn.ival - 1; | ||||
| 860 | if (!ExprResolveString(value, &rtrn, NULL((void*)0), NULL((void*)0))) | ||||
| 861 | { | ||||
| 862 | ERROR2uError("Non-string name for level %d in key type %s\n", level + 1, | ||||
| 863 | XkbAtomText(type->dpy, type->name, XkbMessage3)); | ||||
| 864 | ACTIONuAction("Ignoring illegal level name definition\n"); | ||||
| 865 | return False0; | ||||
| 866 | } | ||||
| 867 | return | ||||
| 868 | AddLevelName(type, level, XkbInternAtom(NULL((void*)0), rtrn.str, False0), True1, | ||||
| 869 | True1); | ||||
| 870 | } | ||||
| 871 | |||||
| 872 | /***====================================================================***/ | ||||
| 873 | |||||
| 874 | /** | ||||
| 875 | * Parses the fields in a type "..." { } description. | ||||
| 876 | * | ||||
| 877 | * @param field The field to parse (e.g. modifiers, map, level_name) | ||||
| 878 | */ | ||||
| 879 | static Boolint | ||||
| 880 | SetKeyTypeField(KeyTypeInfo * type, | ||||
| 881 | XkbDescPtr xkb, | ||||
| 882 | char *field, | ||||
| 883 | ExprDef * arrayNdx, ExprDef * value, KeyTypesInfo * info) | ||||
| 884 | { | ||||
| 885 | ExprResult tmp; | ||||
| 886 | |||||
| 887 | if (uStrCaseCmp(field, "modifiers")(strcasecmp(field,"modifiers")) == 0) | ||||
| 888 | { | ||||
| 889 | unsigned mods, vmods; | ||||
| 890 | if (arrayNdx != NULL((void*)0)) | ||||
| 891 | { | ||||
| 892 | WARNuWarning("The modifiers field of a key type is not an array\n"); | ||||
| 893 | ACTIONuAction("Illegal array subscript ignored\n"); | ||||
| 894 | } | ||||
| 895 | /* get modifier mask for current type */ | ||||
| 896 | if (!ExprResolveModMask(value, &tmp, LookupVModMask, (XPointer) xkb)) | ||||
| 897 | { | ||||
| 898 | ERRORuError("Key type mask field must be a modifier mask\n"); | ||||
| 899 | ACTIONuAction("Key type definition ignored\n"); | ||||
| 900 | return False0; | ||||
| 901 | } | ||||
| 902 | mods = tmp.uval & 0xff; /* core mods */ | ||||
| 903 | vmods = (tmp.uval >> 8) & 0xffff; /* xkb virtual mods */ | ||||
| 904 | if (type->defs.defined & _KT_Mask(1<<1)) | ||||
| 905 | { | ||||
| 906 | WARN1uWarning("Multiple modifier mask definitions for key type %s\n", | ||||
| 907 | XkbAtomText(type->dpy, type->name, XkbMessage3)); | ||||
| 908 | ACTION1uAction("Using %s, ", TypeMaskTxt(type, xkb)XkbVModMaskText((type)->dpy,(xkb),(type)->mask,(type)-> vmask,3)); | ||||
| 909 | INFO1uInformation("ignoring %s\n", XkbVModMaskText(type->dpy, xkb, mods, | ||||
| 910 | vmods, XkbMessage3)); | ||||
| 911 | return False0; | ||||
| 912 | } | ||||
| 913 | type->mask = mods; | ||||
| 914 | type->vmask = vmods; | ||||
| 915 | type->defs.defined |= _KT_Mask(1<<1); | ||||
| 916 | return True1; | ||||
| 917 | } | ||||
| 918 | else if (uStrCaseCmp(field, "map")(strcasecmp(field,"map")) == 0) | ||||
| 919 | { | ||||
| 920 | type->defs.defined |= _KT_Map(1<<2); | ||||
| 921 | return SetMapEntry(type, xkb, arrayNdx, value); | ||||
| 922 | } | ||||
| 923 | else if (uStrCaseCmp(field, "preserve")(strcasecmp(field,"preserve")) == 0) | ||||
| 924 | { | ||||
| 925 | type->defs.defined |= _KT_Preserve(1<<3); | ||||
| 926 | return SetPreserve(type, xkb, arrayNdx, value); | ||||
| 927 | } | ||||
| 928 | else if ((uStrCaseCmp(field, "levelname")(strcasecmp(field,"levelname")) == 0) || | ||||
| 929 | (uStrCaseCmp(field, "level_name")(strcasecmp(field,"level_name")) == 0)) | ||||
| 930 | { | ||||
| 931 | type->defs.defined |= _KT_LevelNames(1<<4); | ||||
| 932 | return SetLevelName(type, arrayNdx, value); | ||||
| 933 | } | ||||
| 934 | ERROR2uError("Unknown field %s in key type %s\n", field, TypeTxt(type)XkbAtomText((type)->dpy,(type)->name,3)); | ||||
| 935 | ACTIONuAction("Definition ignored\n"); | ||||
| 936 | return False0; | ||||
| 937 | } | ||||
| 938 | |||||
| 939 | static Boolint | ||||
| 940 | HandleKeyTypeVar(VarDef * stmt, XkbDescPtr xkb, KeyTypesInfo * info) | ||||
| 941 | { | ||||
| 942 | ExprResult elem, field; | ||||
| 943 | ExprDef *arrayNdx; | ||||
| 944 | |||||
| 945 | if (!ExprResolveLhs(stmt->name, &elem, &field, &arrayNdx)) | ||||
| 946 | return False0; /* internal error, already reported */ | ||||
| 947 | if (elem.str && (uStrCaseCmp(elem.str, "type")(strcasecmp(elem.str,"type")) == 0)) | ||||
| 948 | return SetKeyTypeField(&info->dflt, xkb, field.str, arrayNdx, | ||||
| 949 | stmt->value, info); | ||||
| 950 | if (elem.str != NULL((void*)0)) | ||||
| 951 | { | ||||
| 952 | ERROR1uError("Default for unknown element %s\n", uStringText(elem.str)((elem.str)==((char *)((void*)0))?"<NullString>":(elem. str))); | ||||
| 953 | ACTION1uAction("Value for field %s ignored\n", uStringText(field.str)((field.str)==((char *)((void*)0))?"<NullString>":(field .str))); | ||||
| 954 | } | ||||
| 955 | else if (field.str != NULL((void*)0)) | ||||
| 956 | { | ||||
| 957 | ERROR1uError("Default defined for unknown field %s\n", | ||||
| 958 | uStringText(field.str)((field.str)==((char *)((void*)0))?"<NullString>":(field .str))); | ||||
| 959 | ACTIONuAction("Ignored\n"); | ||||
| 960 | } | ||||
| 961 | return False0; | ||||
| 962 | } | ||||
| 963 | |||||
| 964 | static int | ||||
| 965 | HandleKeyTypeBody(VarDef * def, | ||||
| 966 | XkbDescPtr xkb, KeyTypeInfo * type, KeyTypesInfo * info) | ||||
| 967 | { | ||||
| 968 | int ok = 1; | ||||
| 969 | ExprResult tmp, field; | ||||
| 970 | ExprDef *arrayNdx; | ||||
| 971 | |||||
| 972 | for (; def != NULL((void*)0); def = (VarDef *) def->common.next) | ||||
| 973 | { | ||||
| 974 | if ((def->name) && (def->name->type == ExprFieldRef3)) | ||||
| 975 | { | ||||
| 976 | ok = HandleKeyTypeVar(def, xkb, info); | ||||
| 977 | continue; | ||||
| 978 | } | ||||
| 979 | ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx); | ||||
| 980 | if (ok) | ||||
| 981 | ok = SetKeyTypeField(type, xkb, field.str, arrayNdx, def->value, | ||||
| 982 | info); | ||||
| 983 | } | ||||
| 984 | return ok; | ||||
| 985 | } | ||||
| 986 | |||||
| 987 | /** | ||||
| 988 | * Process a type "XYZ" { } specification in the xkb_types section. | ||||
| 989 | * | ||||
| 990 | */ | ||||
| 991 | static int | ||||
| 992 | HandleKeyTypeDef(KeyTypeDef * def, | ||||
| 993 | XkbDescPtr xkb, unsigned merge, KeyTypesInfo * info) | ||||
| 994 | { | ||||
| 995 | register int i; | ||||
| 996 | KeyTypeInfo type; | ||||
| 997 | |||||
| 998 | if (def->merge != MergeDefault0) | ||||
| 999 | merge = def->merge; | ||||
| 1000 | |||||
| 1001 | type.defs.defined = 0; | ||||
| 1002 | type.defs.fileID = info->fileID; | ||||
| 1003 | type.defs.merge = merge; | ||||
| 1004 | type.defs.next = NULL((void*)0); | ||||
| 1005 | type.dpy = info->dpy; | ||||
| 1006 | type.name = def->name; | ||||
| 1007 | type.mask = info->dflt.mask; | ||||
| 1008 | type.vmask = info->dflt.vmask; | ||||
| 1009 | type.groupInfo = info->dflt.groupInfo; | ||||
| 1010 | type.numLevels = 1; | ||||
| 1011 | type.nEntries = type.szEntries = 0; | ||||
| 1012 | type.entries = NULL((void*)0); | ||||
| 1013 | type.szNames = 0; | ||||
| 1014 | type.lvlNames = NULL((void*)0); | ||||
| 1015 | type.preserve = NULL((void*)0); | ||||
| 1016 | |||||
| 1017 | /* Parse the actual content. */ | ||||
| 1018 | if (!HandleKeyTypeBody(def->body, xkb, &type, info)) | ||||
| 1019 | { | ||||
| 1020 | info->errorCount++; | ||||
| 1021 | return False0; | ||||
| 1022 | } | ||||
| 1023 | |||||
| 1024 | /* now copy any appropriate map, preserve or level names from the */ | ||||
| 1025 | /* default type */ | ||||
| 1026 | for (i = 0; i < info->dflt.nEntries; i++) | ||||
| 1027 | { | ||||
| 1028 | XkbKTMapEntryPtr dflt; | ||||
| 1029 | dflt = &info->dflt.entries[i]; | ||||
| 1030 | if (((dflt->mods.real_mods & type.mask) == dflt->mods.real_mods) && | ||||
| 1031 | ((dflt->mods.vmods & type.vmask) == dflt->mods.vmods)) | ||||
| 1032 | { | ||||
| 1033 | AddMapEntry(xkb, &type, dflt, False0, False0); | ||||
| 1034 | } | ||||
| 1035 | } | ||||
| 1036 | if (info->dflt.preserve) | ||||
| 1037 | { | ||||
| 1038 | PreserveInfo *dflt = info->dflt.preserve; | ||||
| 1039 | while (dflt) | ||||
| 1040 | { | ||||
| 1041 | if (((dflt->indexMods & type.mask) == dflt->indexMods) && | ||||
| 1042 | ((dflt->indexVMods & type.vmask) == dflt->indexVMods)) | ||||
| 1043 | { | ||||
| 1044 | AddPreserve(xkb, &type, dflt, False0, False0); | ||||
| 1045 | } | ||||
| 1046 | dflt = (PreserveInfo *) dflt->defs.next; | ||||
| 1047 | } | ||||
| 1048 | } | ||||
| 1049 | for (i = 0; i < info->dflt.szNames; i++) | ||||
| 1050 | { | ||||
| 1051 | if ((i < type.numLevels) && (info->dflt.lvlNames[i] != None0L)) | ||||
| 1052 | { | ||||
| 1053 | AddLevelName(&type, i, info->dflt.lvlNames[i], False0, False0); | ||||
| 1054 | } | ||||
| 1055 | } | ||||
| 1056 | /* Now add the new keytype to the info struct */ | ||||
| 1057 | if (!AddKeyType(xkb, info, &type)) | ||||
| 1058 | { | ||||
| 1059 | info->errorCount++; | ||||
| 1060 | return False0; | ||||
| 1061 | } | ||||
| 1062 | return True1; | ||||
| 1063 | } | ||||
| 1064 | |||||
| 1065 | /** | ||||
| 1066 | * Process an xkb_types section. | ||||
| 1067 | * | ||||
| 1068 | * @param file The parsed xkb_types section. | ||||
| 1069 | * @param merge Merge Strategy (e.g. MergeOverride) | ||||
| 1070 | * @param info Pointer to memory where the outcome will be stored. | ||||
| 1071 | */ | ||||
| 1072 | static void | ||||
| 1073 | HandleKeyTypesFile(XkbFile * file, | ||||
| 1074 | XkbDescPtr xkb, unsigned merge, KeyTypesInfo * info) | ||||
| 1075 | { | ||||
| 1076 | ParseCommon *stmt; | ||||
| 1077 | |||||
| 1078 | info->name = uStringDup(file->name)((file->name) ? strdup(file->name) : ((void*)0)); | ||||
| 1079 | stmt = file->defs; | ||||
| 1080 | while (stmt) | ||||
| 1081 | { | ||||
| 1082 | switch (stmt->stmtType) | ||||
| 1083 | { | ||||
| 1084 | case StmtInclude1: | ||||
| 1085 | if (!HandleIncludeKeyTypes((IncludeStmt *) stmt, xkb, info, | ||||
| 1086 | HandleKeyTypesFile)) | ||||
| 1087 | info->errorCount++; | ||||
| 1088 | break; | ||||
| 1089 | case StmtKeyTypeDef6: /* e.g. type "ONE_LEVEL" */ | ||||
| 1090 | if (!HandleKeyTypeDef((KeyTypeDef *) stmt, xkb, merge, info)) | ||||
| 1091 | info->errorCount++; | ||||
| 1092 | break; | ||||
| 1093 | case StmtVarDef5: | ||||
| 1094 | if (!HandleKeyTypeVar((VarDef *) stmt, xkb, info)) | ||||
| 1095 | info->errorCount++; | ||||
| 1096 | break; | ||||
| 1097 | case StmtVModDef8: /* virtual_modifiers NumLock, ... */ | ||||
| 1098 | if (!HandleVModDef((VModDef *) stmt, merge, &info->vmods)) | ||||
| 1099 | info->errorCount++; | ||||
| 1100 | break; | ||||
| 1101 | case StmtKeyAliasDef3: | ||||
| 1102 | ERRORuError("Key type files may not include other declarations\n"); | ||||
| 1103 | ACTIONuAction("Ignoring definition of key alias\n"); | ||||
| 1104 | info->errorCount++; | ||||
| 1105 | break; | ||||
| 1106 | case StmtKeycodeDef2: | ||||
| 1107 | ERRORuError("Key type files may not include other declarations\n"); | ||||
| 1108 | ACTIONuAction("Ignoring definition of key name\n"); | ||||
| 1109 | info->errorCount++; | ||||
| 1110 | break; | ||||
| 1111 | case StmtInterpDef7: | ||||
| 1112 | ERRORuError("Key type files may not include other declarations\n"); | ||||
| 1113 | ACTIONuAction("Ignoring definition of symbol interpretation\n"); | ||||
| 1114 | info->errorCount++; | ||||
| 1115 | break; | ||||
| 1116 | default: | ||||
| 1117 | WSGO1uInternalError("Unexpected statement type %d in HandleKeyTypesFile\n", | ||||
| 1118 | stmt->stmtType); | ||||
| 1119 | break; | ||||
| 1120 | } | ||||
| 1121 | stmt = stmt->next; | ||||
| 1122 | if (info->errorCount > 10) | ||||
| 1123 | { | ||||
| 1124 | #ifdef NOISY | ||||
| 1125 | ERRORuError("Too many errors\n"); | ||||
| 1126 | #endif | ||||
| 1127 | ACTION1uAction("Abandoning keytypes file \"%s\"\n", file->topName); | ||||
| 1128 | break; | ||||
| 1129 | } | ||||
| 1130 | } | ||||
| 1131 | return; | ||||
| 1132 | } | ||||
| 1133 | |||||
| 1134 | static Boolint | ||||
| 1135 | CopyDefToKeyType(XkbDescPtr xkb, XkbKeyTypePtr type, KeyTypeInfo * def) | ||||
| 1136 | { | ||||
| 1137 | register int i; | ||||
| 1138 | PreserveInfo *pre; | ||||
| 1139 | |||||
| 1140 | for (pre = def->preserve; pre != NULL((void*)0); | ||||
| 1141 | pre = (PreserveInfo *) pre->defs.next) | ||||
| 1142 | { | ||||
| 1143 | XkbKTMapEntryPtr match; | ||||
| 1144 | XkbKTMapEntryRec tmp; | ||||
| 1145 | tmp.mods.real_mods = pre->indexMods; | ||||
| 1146 | tmp.mods.vmods = pre->indexVMods; | ||||
| 1147 | tmp.level = 0; | ||||
| 1148 | AddMapEntry(xkb, def, &tmp, False0, False0); | ||||
| 1149 | match = FindMatchingMapEntry(def, pre->indexMods, pre->indexVMods); | ||||
| 1150 | if (!match) | ||||
| 1151 | { | ||||
| 1152 | WSGOuInternalError("Couldn't find matching entry for preserve\n"); | ||||
| 1153 | ACTIONuAction("Aborting\n"); | ||||
| 1154 | return False0; | ||||
| 1155 | } | ||||
| 1156 | pre->matchingMapIndex = match - def->entries; | ||||
| 1157 | } | ||||
| 1158 | type->mods.real_mods = def->mask; | ||||
| 1159 | type->mods.vmods = def->vmask; | ||||
| 1160 | type->num_levels = def->numLevels; | ||||
| 1161 | type->map_count = def->nEntries; | ||||
| 1162 | type->map = def->entries; | ||||
| 1163 | if (def->preserve) | ||||
| 1164 | { | ||||
| 1165 | type->preserve = uTypedCalloc(type->map_count, XkbModsRec)((XkbModsRec *)uCalloc((unsigned)type->map_count,(unsigned )sizeof(XkbModsRec))); | ||||
| 1166 | if (!type->preserve) | ||||
| 1167 | { | ||||
| 1168 | WARNuWarning("Couldn't allocate preserve array in CopyDefToKeyType\n"); | ||||
| 1169 | ACTION1uAction("Preserve setting for type %s lost\n", | ||||
| 1170 | XkbAtomText(def->dpy, def->name, XkbMessage3)); | ||||
| 1171 | } | ||||
| 1172 | else | ||||
| 1173 | { | ||||
| 1174 | pre = def->preserve; | ||||
| 1175 | for (; pre != NULL((void*)0); pre = (PreserveInfo *) pre->defs.next) | ||||
| 1176 | { | ||||
| 1177 | int ndx = pre->matchingMapIndex; | ||||
| 1178 | type->preserve[ndx].mask = pre->preMods; | ||||
| 1179 | type->preserve[ndx].real_mods = pre->preMods; | ||||
| 1180 | type->preserve[ndx].vmods = pre->preVMods; | ||||
| 1181 | } | ||||
| 1182 | } | ||||
| 1183 | } | ||||
| 1184 | else | ||||
| 1185 | type->preserve = NULL((void*)0); | ||||
| 1186 | type->name = (Atom) def->name; | ||||
| 1187 | if (def->szNames > 0) | ||||
| 1188 | { | ||||
| 1189 | type->level_names = uTypedCalloc(def->numLevels, Atom)((Atom *)uCalloc((unsigned)def->numLevels,(unsigned)sizeof (Atom))); | ||||
| 1190 | |||||
| 1191 | /* assert def->szNames<=def->numLevels */ | ||||
| 1192 | for (i = 0; i < def->szNames; i++) | ||||
| 1193 | { | ||||
| 1194 | type->level_names[i] = (Atom) def->lvlNames[i]; | ||||
| 1195 | } | ||||
| 1196 | } | ||||
| 1197 | else | ||||
| 1198 | { | ||||
| 1199 | type->level_names = NULL((void*)0); | ||||
| 1200 | } | ||||
| 1201 | |||||
| 1202 | def->nEntries = def->szEntries = 0; | ||||
| 1203 | def->entries = NULL((void*)0); | ||||
| 1204 | return XkbComputeEffectiveMap(xkb, type, NULL((void*)0)); | ||||
| 1205 | } | ||||
| 1206 | |||||
| 1207 | Boolint | ||||
| 1208 | CompileKeyTypes(XkbFile * file, XkbFileInfo * result, unsigned merge) | ||||
| 1209 | { | ||||
| 1210 | KeyTypesInfo info; | ||||
| 1211 | XkbDescPtr xkb; | ||||
| 1212 | |||||
| 1213 | xkb = result->xkb; | ||||
| 1214 | InitKeyTypesInfo(&info, xkb, NULL((void*)0)); | ||||
| 1215 | info.fileID = file->id; | ||||
| 1216 | HandleKeyTypesFile(file, xkb, merge, &info); | ||||
| 1217 | |||||
| 1218 | if (info.errorCount == 0) | ||||
| 1219 | { | ||||
| 1220 | register int i; | ||||
| 1221 | register KeyTypeInfo *def; | ||||
| 1222 | register XkbKeyTypePtr type, next; | ||||
| 1223 | |||||
| 1224 | if (info.name != NULL((void*)0)) | ||||
| 1225 | { | ||||
| 1226 | if (XkbAllocNames(xkb, XkbTypesNameMask(1<<4), 0, 0) == Success0) | ||||
| 1227 | xkb->names->types = XkbInternAtom(xkb->dpy, info.name, False0); | ||||
| 1228 | else | ||||
| 1229 | { | ||||
| 1230 | WSGOuInternalError("Couldn't allocate space for types name\n"); | ||||
| 1231 | ACTION2uAction("Name \"%s\" (from %s) NOT assigned\n", | ||||
| 1232 | scanFile, info.name); | ||||
| 1233 | } | ||||
| 1234 | } | ||||
| 1235 | i = info.nTypes; | ||||
| 1236 | if ((info.stdPresent & XkbOneLevelMask(1<<0)) == 0) | ||||
| 1237 | i++; | ||||
| 1238 | if ((info.stdPresent & XkbTwoLevelMask(1<<1)) == 0) | ||||
| 1239 | i++; | ||||
| 1240 | if ((info.stdPresent & XkbKeypadMask(1<<3)) == 0) | ||||
| 1241 | i++; | ||||
| 1242 | if ((info.stdPresent & XkbAlphabeticMask(1<<2)) == 0) | ||||
| 1243 | i++; | ||||
| 1244 | if (XkbAllocClientMap(xkb, XkbKeyTypesMask(1<<0), i) != Success0) | ||||
| 1245 | { | ||||
| 1246 | WSGOuInternalError("Couldn't allocate client map\n"); | ||||
| 1247 | ACTIONuAction("Exiting\n"); | ||||
| 1248 | return False0; | ||||
| 1249 | } | ||||
| 1250 | xkb->map->num_types = i; | ||||
| 1251 | if (XkbAllRequiredTypes(0xf) & (~info.stdPresent)) | ||||
| 1252 | { | ||||
| 1253 | unsigned missing, keypadVMod; | ||||
| 1254 | |||||
| 1255 | missing = XkbAllRequiredTypes(0xf) & (~info.stdPresent); | ||||
| 1256 | keypadVMod = FindKeypadVMod(xkb); | ||||
| 1257 | if (XkbInitCanonicalKeyTypes(xkb, missing, keypadVMod) != Success0) | ||||
| 1258 | { | ||||
| 1259 | WSGOuInternalError("Couldn't initialize canonical key types\n"); | ||||
| 1260 | ACTIONuAction("Exiting\n"); | ||||
| 1261 | return False0; | ||||
| 1262 | } | ||||
| 1263 | if (missing & XkbOneLevelMask(1<<0)) | ||||
| 1264 | xkb->map->types[XkbOneLevelIndex0].name = tok_ONE_LEVEL; | ||||
| 1265 | if (missing & XkbTwoLevelMask(1<<1)) | ||||
| 1266 | xkb->map->types[XkbTwoLevelIndex1].name = tok_TWO_LEVEL; | ||||
| 1267 | if (missing & XkbAlphabeticMask(1<<2)) | ||||
| 1268 | xkb->map->types[XkbAlphabeticIndex2].name = tok_ALPHABETIC; | ||||
| 1269 | if (missing & XkbKeypadMask(1<<3)) | ||||
| 1270 | xkb->map->types[XkbKeypadIndex3].name = tok_KEYPAD; | ||||
| 1271 | } | ||||
| 1272 | next = &xkb->map->types[XkbLastRequiredType3 + 1]; | ||||
| 1273 | for (i = 0, def = info.types; i < info.nTypes; i++) | ||||
| 1274 | { | ||||
| 1275 | if (def->name == tok_ONE_LEVEL) | ||||
| 1276 | type = &xkb->map->types[XkbOneLevelIndex0]; | ||||
| 1277 | else if (def->name == tok_TWO_LEVEL) | ||||
| 1278 | type = &xkb->map->types[XkbTwoLevelIndex1]; | ||||
| 1279 | else if (def->name == tok_ALPHABETIC) | ||||
| 1280 | type = &xkb->map->types[XkbAlphabeticIndex2]; | ||||
| 1281 | else if (def->name == tok_KEYPAD) | ||||
| 1282 | type = &xkb->map->types[XkbKeypadIndex3]; | ||||
| 1283 | else | ||||
| 1284 | type = next++; | ||||
| 1285 | DeleteLevel1MapEntries(def); | ||||
| 1286 | if (!CopyDefToKeyType(xkb, type, def)) | ||||
| 1287 | return False0; | ||||
| 1288 | def = (KeyTypeInfo *) def->defs.next; | ||||
| 1289 | } | ||||
| 1290 | return True1; | ||||
| 1291 | } | ||||
| 1292 | return False0; | ||||
| 1293 | } |