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