alias.c revision 34345a63
1/************************************************************ 2 Copyright (c) 1995 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 "misc.h" 29#include "alias.h" 30#include "keycodes.h" 31 32#include <X11/extensions/XKBgeom.h> 33 34static void 35HandleCollision(AliasInfo * old, AliasInfo * new) 36{ 37 if (strncmp(new->real, old->real, XkbKeyNameLength) == 0) 38 { 39 if (((new->def.fileID == old->def.fileID) && (warningLevel > 0)) || 40 (warningLevel > 9)) 41 { 42 WARN2("Alias of %s for %s declared more than once\n", 43 XkbKeyNameText(new->alias, XkbMessage), 44 XkbKeyNameText(new->real, XkbMessage)); 45 ACTION("First definition ignored\n"); 46 } 47 } 48 else 49 { 50 char *use, *ignore; 51 if (new->def.merge == MergeAugment) 52 { 53 use = old->real; 54 ignore = new->real; 55 } 56 else 57 { 58 use = new->real; 59 ignore = old->real; 60 } 61 if (((old->def.fileID == new->def.fileID) && (warningLevel > 0)) || 62 (warningLevel > 9)) 63 { 64 WARN1("Multiple definitions for alias %s\n", 65 XkbKeyNameText(old->alias, XkbMessage)); 66 ACTION2("Using %s, ignoring %s\n", 67 XkbKeyNameText(use, XkbMessage), 68 XkbKeyNameText(ignore, XkbMessage)); 69 } 70 if (use != old->real) 71 memcpy(old->real, use, XkbKeyNameLength); 72 } 73 old->def.fileID = new->def.fileID; 74 old->def.merge = new->def.merge; 75 return; 76} 77 78static void 79InitAliasInfo(AliasInfo * info, 80 unsigned merge, unsigned file_id, char *alias, char *real) 81{ 82 bzero(info, sizeof(AliasInfo)); 83 info->def.merge = merge; 84 info->def.fileID = file_id; 85 strncpy(info->alias, alias, XkbKeyNameLength); 86 strncpy(info->real, real, XkbKeyNameLength); 87 return; 88} 89 90int 91HandleAliasDef(KeyAliasDef * def, 92 unsigned merge, unsigned file_id, AliasInfo ** info_in) 93{ 94 AliasInfo *info; 95 96 for (info = *info_in; info != NULL; info = (AliasInfo *) info->def.next) 97 { 98 if (strncmp(info->alias, def->alias, XkbKeyNameLength) == 0) 99 { 100 AliasInfo new; 101 InitAliasInfo(&new, merge, file_id, def->alias, def->real); 102 HandleCollision(info, &new); 103 return True; 104 } 105 } 106 info = uTypedCalloc(1, AliasInfo); 107 if (info == NULL) 108 { 109 WSGO("Allocation failure in HandleAliasDef\n"); 110 return False; 111 } 112 info->def.fileID = file_id; 113 info->def.merge = merge; 114 info->def.next = (CommonInfo *) * info_in; 115 memcpy(info->alias, def->alias, XkbKeyNameLength); 116 memcpy(info->real, def->real, XkbKeyNameLength); 117 *info_in = (AliasInfo *) AddCommonInfo(&(*info_in)->def, &info->def); 118 return True; 119} 120 121void 122ClearAliases(AliasInfo ** info_in) 123{ 124 if ((info_in) && (*info_in)) 125 ClearCommonInfo(&(*info_in)->def); 126 return; 127} 128 129Bool 130MergeAliases(AliasInfo ** into, AliasInfo ** merge, unsigned how_merge) 131{ 132 AliasInfo *tmp; 133 KeyAliasDef def; 134 135 if ((*merge) == NULL) 136 return True; 137 if ((*into) == NULL) 138 { 139 *into = *merge; 140 *merge = NULL; 141 return True; 142 } 143 bzero((char *) &def, sizeof(KeyAliasDef)); 144 for (tmp = *merge; tmp != NULL; tmp = (AliasInfo *) tmp->def.next) 145 { 146 if (how_merge == MergeDefault) 147 def.merge = tmp->def.merge; 148 else 149 def.merge = how_merge; 150 memcpy(def.alias, tmp->alias, XkbKeyNameLength); 151 memcpy(def.real, tmp->real, XkbKeyNameLength); 152 if (!HandleAliasDef(&def, def.merge, tmp->def.fileID, into)) 153 return False; 154 } 155 return True; 156} 157 158int 159ApplyAliases(XkbDescPtr xkb, Bool toGeom, AliasInfo ** info_in) 160{ 161 register int i; 162 XkbKeyAliasPtr old, a; 163 AliasInfo *info; 164 int nNew, nOld; 165 Status status; 166 167 if (*info_in == NULL) 168 return True; 169 if (toGeom) 170 { 171 nOld = (xkb->geom ? xkb->geom->num_key_aliases : 0); 172 old = (xkb->geom ? xkb->geom->key_aliases : NULL); 173 } 174 else 175 { 176 nOld = (xkb->names ? xkb->names->num_key_aliases : 0); 177 old = (xkb->names ? xkb->names->key_aliases : NULL); 178 } 179 for (nNew = 0, info = *info_in; info != NULL; 180 info = (AliasInfo *) info->def.next) 181 { 182 unsigned long lname; 183 unsigned int kc; 184 185 lname = KeyNameToLong(info->real); 186 if (!FindNamedKey(xkb, lname, &kc, False, CreateKeyNames(xkb), 0)) 187 { 188 if (warningLevel > 4) 189 { 190 WARN2("Attempt to alias %s to non-existent key %s\n", 191 XkbKeyNameText(info->alias, XkbMessage), 192 XkbKeyNameText(info->real, XkbMessage)); 193 ACTION("Ignored\n"); 194 } 195 info->alias[0] = '\0'; 196 continue; 197 } 198 lname = KeyNameToLong(info->alias); 199 if (FindNamedKey(xkb, lname, &kc, False, False, 0)) 200 { 201 if (warningLevel > 4) 202 { 203 WARN("Attempt to create alias with the name of a real key\n"); 204 ACTION2("Alias \"%s = %s\" ignored\n", 205 XkbKeyNameText(info->alias, XkbMessage), 206 XkbKeyNameText(info->real, XkbMessage)); 207 } 208 info->alias[0] = '\0'; 209 continue; 210 } 211 nNew++; 212 if (old) 213 { 214 for (i = 0, a = old; i < nOld; i++, a++) 215 { 216 if (strncmp(a->alias, info->alias, XkbKeyNameLength) == 0) 217 { 218 AliasInfo old; 219 InitAliasInfo(&old, MergeAugment, 0, a->alias, a->real); 220 HandleCollision(&old, info); 221 memcpy(old.real, a->real, XkbKeyNameLength); 222 info->alias[0] = '\0'; 223 nNew--; 224 break; 225 } 226 } 227 } 228 } 229 if (nNew == 0) 230 { 231 ClearCommonInfo(&(*info_in)->def); 232 *info_in = NULL; 233 return True; 234 } 235 status = Success; 236 if (toGeom) 237 { 238 if (!xkb->geom) 239 { 240 XkbGeometrySizesRec sizes; 241 bzero((char *) &sizes, sizeof(XkbGeometrySizesRec)); 242 sizes.which = XkbGeomKeyAliasesMask; 243 sizes.num_key_aliases = nOld + nNew; 244 status = XkbAllocGeometry(xkb, &sizes); 245 } 246 else 247 { 248 status = XkbAllocGeomKeyAliases(xkb->geom, nOld + nNew); 249 } 250 if (xkb->geom) 251 old = xkb->geom->key_aliases; 252 } 253 else 254 { 255 status = XkbAllocNames(xkb, XkbKeyAliasesMask, 0, nOld + nNew); 256 if (xkb->names) 257 old = xkb->names->key_aliases; 258 } 259 if (status != Success) 260 { 261 WSGO("Allocation failure in ApplyAliases\n"); 262 return False; 263 } 264 if (toGeom) 265 a = &xkb->geom->key_aliases[nOld]; 266 else 267 a = &xkb->names->key_aliases[nOld]; 268 for (info = *info_in; info != NULL; info = (AliasInfo *) info->def.next) 269 { 270 if (info->alias[0] != '\0') 271 { 272 strncpy(a->alias, info->alias, XkbKeyNameLength); 273 strncpy(a->real, info->real, XkbKeyNameLength); 274 a++; 275 } 276 } 277#ifdef DEBUG 278 if ((a - old) != (nOld + nNew)) 279 { 280 WSGO2("Expected %d aliases total but created %d\n", nOld + nNew, 281 a - old); 282 } 283#endif 284 if (toGeom) 285 xkb->geom->num_key_aliases += nNew; 286 ClearCommonInfo(&(*info_in)->def); 287 *info_in = NULL; 288 return True; 289} 290