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