death to register
[openafs.git] / src / gtx / keymap.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13
14 #include <string.h>
15 #include <stdlib.h>
16
17 #include "gtxkeymap.h"
18
19 struct keymap_map *
20 keymap_Create(void)
21 {
22     struct keymap_map *tmap;
23
24     tmap = (struct keymap_map *)malloc(sizeof(struct keymap_map));
25     if (tmap != (struct keymap_map *)0)
26         memset(tmap, 0, sizeof(*tmap));
27     return (tmap);
28 }
29
30 /* make a copy of a string; generic utility */
31 char *
32 gtx_CopyString(char *aval)
33 {
34     char *tp;
35
36     if (!aval)
37         return NULL;            /* propagate null strings around */
38     tp = (char *)malloc(strlen(aval) + 1);
39     if (tp != NULL)
40         strcpy(tp, aval);
41     return (tp);
42 }
43
44 static int
45 BindIt(struct keymap_map *amap, int aslot, int atype, void *aproc, char *aname, void *arock)
46 {
47     char *tp;
48     struct keymap_entry *tentry;
49
50     if (aslot < 0 || aslot >= KEYMAP_NENTRIES)
51         return -1;
52     tentry = &amap->entries[aslot];
53     tentry->type = atype;
54     if ((tp = tentry->name))
55         free(tp);
56     if (atype == KEYMAP_EMPTY) {
57         tentry->u.generic = NULL;
58         tentry->name = NULL;
59     } else {
60         tentry->name = gtx_CopyString(aname);
61         tentry->u.generic = aproc;
62     }
63     tentry->rock = arock;
64     return 0;
65 }
66
67 int
68 keymap_BindToString(struct keymap_map *amap, char *astring, 
69                     int (*aproc)(void *, void *), 
70                     char *aname, void *arock)
71 {
72     char *cptr;
73     int tc;
74     afs_int32 code;
75     struct keymap_map *tmap;
76
77     cptr = astring;
78     /* walk down string, building submaps if possible, until we get to function
79      * at the end */
80     while ((tc = *cptr++)) {
81         /* see if we should do submap or final function */
82         if (*cptr == 0) {       /* we're peeking: already skipped command char */
83             /* last character, do final function */
84             if (!aproc)         /* delete the entry */
85                 code = BindIt(amap, tc, KEYMAP_EMPTY, NULL, NULL, NULL);
86             else
87                 code =
88                     BindIt(amap, tc, KEYMAP_PROC, aproc, aname, arock);
89             if (code)
90                 return code;
91         } else {
92             /* more characters after this; do submap */
93             if (amap->entries[tc].type != KEYMAP_SUBMAP) {
94                 tmap = keymap_Create();
95                 code =
96                     BindIt(amap, tc, KEYMAP_SUBMAP, tmap, NULL, NULL);
97             } else {
98                 tmap = amap->entries[tc].u.submap;
99                 code = 0;
100             }
101             if (code)
102                 return code;
103             amap = tmap;        /* continue processing this map */
104         }
105     }                           /* while loop */
106     /* here when all characters are gone */
107     return 0;
108 }
109
110 /* delete a keymap and all of its recursively-included maps */
111 int
112 keymap_Delete(struct keymap_map *amap)
113 {
114     int i;
115     struct keymap_entry *tentry;
116
117     for (i = 0; i < KEYMAP_NENTRIES; i++) {
118         tentry = &amap->entries[i];
119         if (tentry->name)
120             free(tentry->name);
121         if (tentry->type == KEYMAP_SUBMAP)
122             keymap_Delete(tentry->u.submap);
123     }
124     free(amap);
125     return 0;
126 }
127
128 int
129 keymap_InitState(struct keymap_state *astate, struct keymap_map *amap)
130 {
131     memset(astate, 0, sizeof(*astate));
132     astate->initMap = amap;
133     astate->currentMap = amap;
134     return 0;
135 }
136
137 int
138 keymap_ProcessKey(struct keymap_state *astate, int akey, void *arock)
139 {
140     struct keymap_entry *tentry;
141     afs_int32 code;
142
143     if (akey < 0 || akey >= KEYMAP_NENTRIES)
144         return -1;
145     tentry = &astate->currentMap->entries[akey];
146     code = 0;
147     switch (tentry->type) {
148     case KEYMAP_EMPTY:
149         keymap_ResetState(astate);
150         return -1;
151         /* break; */
152         /* break commented out because of return above causing compiler warnings */
153
154     case KEYMAP_SUBMAP:
155         astate->currentMap = tentry->u.submap;
156         break;
157
158     case KEYMAP_PROC:
159         code = (*tentry->u.proc) (arock, tentry->rock);
160         keymap_ResetState(astate);
161         break;
162     }
163     return code;
164 }
165
166 int
167 keymap_ResetState(struct keymap_state *astate)
168 {
169     return keymap_InitState(astate, astate->initMap);
170 }