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