Commit | Line | Data |
---|---|---|
805e021f CE |
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 | } |