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