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