1f46a6179Smrg/************************************************************ 2f46a6179Smrg Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 3f46a6179Smrg 4f46a6179Smrg Permission to use, copy, modify, and distribute this 5f46a6179Smrg software and its documentation for any purpose and without 6f46a6179Smrg fee is hereby granted, provided that the above copyright 7f46a6179Smrg notice appear in all copies and that both that copyright 8f46a6179Smrg notice and this permission notice appear in supporting 9bfe6082cSmrg documentation, and that the name of Silicon Graphics not be 10bfe6082cSmrg used in advertising or publicity pertaining to distribution 11f46a6179Smrg of the software without specific prior written permission. 12bfe6082cSmrg Silicon Graphics makes no representation about the suitability 13f46a6179Smrg of this software for any purpose. It is provided "as is" 14f46a6179Smrg without any express or implied warranty. 15bfe6082cSmrg 16bfe6082cSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17bfe6082cSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19bfe6082cSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20bfe6082cSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21bfe6082cSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 24f46a6179Smrg 25f46a6179Smrg ********************************************************/ 26f46a6179Smrg 27f46a6179Smrg#include "xkbcomp.h" 28f46a6179Smrg#include "misc.h" 29f46a6179Smrg#include "alias.h" 30f46a6179Smrg#include "keycodes.h" 31f46a6179Smrg 32f46a6179Smrg#include <X11/extensions/XKBgeom.h> 33f46a6179Smrg 34f46a6179Smrgstatic void 3534345a63SmrgHandleCollision(AliasInfo * old, AliasInfo * new) 36f46a6179Smrg{ 3734345a63Smrg if (strncmp(new->real, old->real, XkbKeyNameLength) == 0) 3834345a63Smrg { 3934345a63Smrg if (((new->def.fileID == old->def.fileID) && (warningLevel > 0)) || 4034345a63Smrg (warningLevel > 9)) 4134345a63Smrg { 42bfe6082cSmrg WARN("Alias of %s for %s declared more than once\n", 4334345a63Smrg XkbKeyNameText(new->alias, XkbMessage), 4434345a63Smrg XkbKeyNameText(new->real, XkbMessage)); 4534345a63Smrg ACTION("First definition ignored\n"); 4634345a63Smrg } 47f46a6179Smrg } 4834345a63Smrg else 4934345a63Smrg { 5034345a63Smrg char *use, *ignore; 5134345a63Smrg if (new->def.merge == MergeAugment) 5234345a63Smrg { 5334345a63Smrg use = old->real; 5434345a63Smrg ignore = new->real; 5534345a63Smrg } 5634345a63Smrg else 5734345a63Smrg { 5834345a63Smrg use = new->real; 5934345a63Smrg ignore = old->real; 6034345a63Smrg } 6134345a63Smrg if (((old->def.fileID == new->def.fileID) && (warningLevel > 0)) || 6234345a63Smrg (warningLevel > 9)) 6334345a63Smrg { 64bfe6082cSmrg WARN("Multiple definitions for alias %s\n", 6534345a63Smrg XkbKeyNameText(old->alias, XkbMessage)); 66bfe6082cSmrg ACTION("Using %s, ignoring %s\n", 6734345a63Smrg XkbKeyNameText(use, XkbMessage), 6834345a63Smrg XkbKeyNameText(ignore, XkbMessage)); 6934345a63Smrg } 7034345a63Smrg if (use != old->real) 7134345a63Smrg memcpy(old->real, use, XkbKeyNameLength); 72f46a6179Smrg } 7334345a63Smrg old->def.fileID = new->def.fileID; 7434345a63Smrg old->def.merge = new->def.merge; 75f46a6179Smrg return; 76f46a6179Smrg} 77f46a6179Smrg 78f46a6179Smrgstatic void 796930ead5SmrgInitAliasInfo(AliasInfo *info, unsigned merge, unsigned file_id, 806930ead5Smrg const char *alias, const char *real) 81f46a6179Smrg{ 8234345a63Smrg bzero(info, sizeof(AliasInfo)); 8334345a63Smrg info->def.merge = merge; 8434345a63Smrg info->def.fileID = file_id; 8534345a63Smrg strncpy(info->alias, alias, XkbKeyNameLength); 8634345a63Smrg strncpy(info->real, real, XkbKeyNameLength); 87f46a6179Smrg return; 88f46a6179Smrg} 89f46a6179Smrg 9034345a63Smrgint 916930ead5SmrgHandleAliasDef(const KeyAliasDef *def, 926930ead5Smrg unsigned merge, unsigned file_id, AliasInfo **info_in) 93f46a6179Smrg{ 9434345a63Smrg AliasInfo *info; 95f46a6179Smrg 9634345a63Smrg for (info = *info_in; info != NULL; info = (AliasInfo *) info->def.next) 9734345a63Smrg { 9834345a63Smrg if (strncmp(info->alias, def->alias, XkbKeyNameLength) == 0) 9934345a63Smrg { 10034345a63Smrg AliasInfo new; 10134345a63Smrg InitAliasInfo(&new, merge, file_id, def->alias, def->real); 10234345a63Smrg HandleCollision(info, &new); 10334345a63Smrg return True; 10434345a63Smrg } 105f46a6179Smrg } 1066930ead5Smrg info = calloc(1, sizeof(AliasInfo)); 10734345a63Smrg if (info == NULL) 10834345a63Smrg { 10934345a63Smrg WSGO("Allocation failure in HandleAliasDef\n"); 11034345a63Smrg return False; 111f46a6179Smrg } 11234345a63Smrg info->def.fileID = file_id; 11334345a63Smrg info->def.merge = merge; 11434345a63Smrg info->def.next = (CommonInfo *) * info_in; 11534345a63Smrg memcpy(info->alias, def->alias, XkbKeyNameLength); 11634345a63Smrg memcpy(info->real, def->real, XkbKeyNameLength); 11734345a63Smrg *info_in = (AliasInfo *) AddCommonInfo(&(*info_in)->def, &info->def); 118f46a6179Smrg return True; 119f46a6179Smrg} 120f46a6179Smrg 121f46a6179Smrgvoid 12234345a63SmrgClearAliases(AliasInfo ** info_in) 123f46a6179Smrg{ 12434345a63Smrg if ((info_in) && (*info_in)) 12534345a63Smrg ClearCommonInfo(&(*info_in)->def); 126f46a6179Smrg return; 127f46a6179Smrg} 128f46a6179Smrg 129f46a6179SmrgBool 13034345a63SmrgMergeAliases(AliasInfo ** into, AliasInfo ** merge, unsigned how_merge) 131f46a6179Smrg{ 13234345a63Smrg AliasInfo *tmp; 13334345a63Smrg KeyAliasDef def; 134f46a6179Smrg 13534345a63Smrg if ((*merge) == NULL) 13634345a63Smrg return True; 13734345a63Smrg if ((*into) == NULL) 13834345a63Smrg { 13934345a63Smrg *into = *merge; 14034345a63Smrg *merge = NULL; 14134345a63Smrg return True; 14234345a63Smrg } 1436930ead5Smrg bzero(&def, sizeof(KeyAliasDef)); 14434345a63Smrg for (tmp = *merge; tmp != NULL; tmp = (AliasInfo *) tmp->def.next) 14534345a63Smrg { 14634345a63Smrg if (how_merge == MergeDefault) 14734345a63Smrg def.merge = tmp->def.merge; 14834345a63Smrg else 14934345a63Smrg def.merge = how_merge; 15034345a63Smrg memcpy(def.alias, tmp->alias, XkbKeyNameLength); 15134345a63Smrg memcpy(def.real, tmp->real, XkbKeyNameLength); 15234345a63Smrg if (!HandleAliasDef(&def, def.merge, tmp->def.fileID, into)) 15334345a63Smrg return False; 154f46a6179Smrg } 155f46a6179Smrg return True; 156f46a6179Smrg} 157f46a6179Smrg 158f46a6179Smrgint 15934345a63SmrgApplyAliases(XkbDescPtr xkb, Bool toGeom, AliasInfo ** info_in) 160f46a6179Smrg{ 1616930ead5Smrg int i; 16234345a63Smrg XkbKeyAliasPtr old, a; 16334345a63Smrg AliasInfo *info; 16434345a63Smrg int nNew, nOld; 16534345a63Smrg Status status; 166f46a6179Smrg 16734345a63Smrg if (*info_in == NULL) 16834345a63Smrg return True; 16934345a63Smrg if (toGeom) 17034345a63Smrg { 17134345a63Smrg nOld = (xkb->geom ? xkb->geom->num_key_aliases : 0); 17234345a63Smrg old = (xkb->geom ? xkb->geom->key_aliases : NULL); 173f46a6179Smrg } 17434345a63Smrg else 17534345a63Smrg { 17634345a63Smrg nOld = (xkb->names ? xkb->names->num_key_aliases : 0); 17734345a63Smrg old = (xkb->names ? xkb->names->key_aliases : NULL); 178f46a6179Smrg } 17934345a63Smrg for (nNew = 0, info = *info_in; info != NULL; 18034345a63Smrg info = (AliasInfo *) info->def.next) 18134345a63Smrg { 18234345a63Smrg unsigned long lname; 18334345a63Smrg unsigned int kc; 184f46a6179Smrg 18534345a63Smrg lname = KeyNameToLong(info->real); 18634345a63Smrg if (!FindNamedKey(xkb, lname, &kc, False, CreateKeyNames(xkb), 0)) 18734345a63Smrg { 18834345a63Smrg if (warningLevel > 4) 18934345a63Smrg { 190bfe6082cSmrg WARN("Attempt to alias %s to non-existent key %s\n", 19134345a63Smrg XkbKeyNameText(info->alias, XkbMessage), 19234345a63Smrg XkbKeyNameText(info->real, XkbMessage)); 19334345a63Smrg ACTION("Ignored\n"); 19434345a63Smrg } 19534345a63Smrg info->alias[0] = '\0'; 19634345a63Smrg continue; 19734345a63Smrg } 19834345a63Smrg lname = KeyNameToLong(info->alias); 19934345a63Smrg if (FindNamedKey(xkb, lname, &kc, False, False, 0)) 20034345a63Smrg { 20134345a63Smrg if (warningLevel > 4) 20234345a63Smrg { 20334345a63Smrg WARN("Attempt to create alias with the name of a real key\n"); 204bfe6082cSmrg ACTION("Alias \"%s = %s\" ignored\n", 20534345a63Smrg XkbKeyNameText(info->alias, XkbMessage), 20634345a63Smrg XkbKeyNameText(info->real, XkbMessage)); 20734345a63Smrg } 20834345a63Smrg info->alias[0] = '\0'; 20934345a63Smrg continue; 21034345a63Smrg } 21134345a63Smrg nNew++; 21234345a63Smrg if (old) 21334345a63Smrg { 21434345a63Smrg for (i = 0, a = old; i < nOld; i++, a++) 21534345a63Smrg { 21634345a63Smrg if (strncmp(a->alias, info->alias, XkbKeyNameLength) == 0) 21734345a63Smrg { 2181d8c7986Smrg AliasInfo oldai; 2191d8c7986Smrg InitAliasInfo(&oldai, MergeAugment, 0, a->alias, a->real); 2201d8c7986Smrg HandleCollision(&oldai, info); 2211d8c7986Smrg memcpy(oldai.real, a->real, XkbKeyNameLength); 22234345a63Smrg info->alias[0] = '\0'; 22334345a63Smrg nNew--; 22434345a63Smrg break; 22534345a63Smrg } 22634345a63Smrg } 22734345a63Smrg } 228f46a6179Smrg } 22934345a63Smrg if (nNew == 0) 23034345a63Smrg { 23134345a63Smrg ClearCommonInfo(&(*info_in)->def); 23234345a63Smrg *info_in = NULL; 23334345a63Smrg return True; 234f46a6179Smrg } 23534345a63Smrg status = Success; 23634345a63Smrg if (toGeom) 23734345a63Smrg { 23834345a63Smrg if (!xkb->geom) 23934345a63Smrg { 2406930ead5Smrg XkbGeometrySizesRec sizes = { 2416930ead5Smrg .which = XkbGeomKeyAliasesMask, 2426930ead5Smrg .num_key_aliases = nOld + nNew 2436930ead5Smrg }; 24434345a63Smrg status = XkbAllocGeometry(xkb, &sizes); 24534345a63Smrg } 24634345a63Smrg else 24734345a63Smrg { 24834345a63Smrg status = XkbAllocGeomKeyAliases(xkb->geom, nOld + nNew); 24934345a63Smrg } 25034345a63Smrg if (xkb->geom) 25134345a63Smrg old = xkb->geom->key_aliases; 252f46a6179Smrg } 25334345a63Smrg else 25434345a63Smrg { 25534345a63Smrg status = XkbAllocNames(xkb, XkbKeyAliasesMask, 0, nOld + nNew); 25634345a63Smrg if (xkb->names) 25734345a63Smrg old = xkb->names->key_aliases; 258f46a6179Smrg } 25934345a63Smrg if (status != Success) 26034345a63Smrg { 26134345a63Smrg WSGO("Allocation failure in ApplyAliases\n"); 26234345a63Smrg return False; 263f46a6179Smrg } 26434345a63Smrg if (toGeom) 26534345a63Smrg a = &xkb->geom->key_aliases[nOld]; 26634345a63Smrg else 26734345a63Smrg a = &xkb->names->key_aliases[nOld]; 26834345a63Smrg for (info = *info_in; info != NULL; info = (AliasInfo *) info->def.next) 26934345a63Smrg { 27034345a63Smrg if (info->alias[0] != '\0') 27134345a63Smrg { 27234345a63Smrg strncpy(a->alias, info->alias, XkbKeyNameLength); 27334345a63Smrg strncpy(a->real, info->real, XkbKeyNameLength); 27434345a63Smrg a++; 27534345a63Smrg } 276f46a6179Smrg } 277f46a6179Smrg#ifdef DEBUG 27834345a63Smrg if ((a - old) != (nOld + nNew)) 27934345a63Smrg { 280bfe6082cSmrg WSGO("Expected %d aliases total but created %d\n", nOld + nNew, 2811d8c7986Smrg (int)(a - old)); 282f46a6179Smrg } 283f46a6179Smrg#endif 28434345a63Smrg if (toGeom) 28534345a63Smrg xkb->geom->num_key_aliases += nNew; 286f46a6179Smrg ClearCommonInfo(&(*info_in)->def); 28734345a63Smrg *info_in = NULL; 288f46a6179Smrg return True; 289f46a6179Smrg} 290