1 #include <cdk_int.h>
2
3 /*
4 * $Author: tom $
5 * $Date: 2019/02/19 10:12:38 $
6 * $Revision: 1.57 $
7 *
8 * Notes:
9 *
10 * The cdktype parameter passed to bindCDKObject, etc., is redundant since
11 * the object parameter also has the same information. For compatibility
12 * just use it for a sanity check.
13 */
14
15 #ifndef KEY_MAX
16 #define KEY_MAX 512
17 #endif
18
bindableObject(EObjectType * cdktype,void * object)19 static CDKOBJS *bindableObject (EObjectType * cdktype, void *object)
20 {
21 CDKOBJS *obj = (CDKOBJS *)object;
22
23 if (obj != 0 && *cdktype == ObjTypeOf (obj))
24 {
25 if (*cdktype == vFSELECT)
26 {
27 *cdktype = vENTRY;
28 object = ((CDKFSELECT *)object)->entryField;
29 }
30 else if (*cdktype == vALPHALIST)
31 {
32 *cdktype = vENTRY;
33 object = ((CDKALPHALIST *)object)->entryField;
34 }
35 }
36 else
37 {
38 object = 0;
39 }
40 return (CDKOBJS *)object;
41 }
42
43 /*
44 * This inserts a binding.
45 */
bindCDKObject(EObjectType cdktype,void * object,chtype key,BINDFN function,void * data)46 void bindCDKObject (EObjectType cdktype,
47 void *object,
48 chtype key,
49 BINDFN function,
50 void *data)
51 {
52 CDKOBJS *obj = bindableObject (&cdktype, object);
53
54 if ((key < KEY_MAX) && obj != 0)
55 {
56 if (key != 0 && (unsigned)key >= obj->bindingCount)
57 {
58 unsigned next = (unsigned) (key + 1);
59
60 if (obj->bindingList != 0)
61 obj->bindingList = typeReallocN (CDKBINDING, obj->bindingList, next);
62 else
63 obj->bindingList = typeMallocN (CDKBINDING, next);
64
65 memset (&(obj->bindingList[obj->bindingCount]), 0,
66 (next - obj->bindingCount) * sizeof (CDKBINDING));
67 obj->bindingCount = next;
68 }
69
70 if (obj->bindingList != 0)
71 {
72 obj->bindingList[key].bindFunction = function;
73 obj->bindingList[key].bindData = data;
74 }
75 }
76 }
77
78 /*
79 * This removes a binding on an object.
80 */
unbindCDKObject(EObjectType cdktype,void * object,chtype key)81 void unbindCDKObject (EObjectType cdktype, void *object, chtype key)
82 {
83 CDKOBJS *obj = bindableObject (&cdktype, object);
84
85 if (obj != 0 && ((unsigned)key < obj->bindingCount))
86 {
87 obj->bindingList[key].bindFunction = 0;
88 obj->bindingList[key].bindData = 0;
89 }
90 }
91
92 /*
93 * This removes all the bindings for the given objects.
94 */
cleanCDKObjectBindings(EObjectType cdktype,void * object)95 void cleanCDKObjectBindings (EObjectType cdktype, void *object)
96 {
97 CDKOBJS *obj = bindableObject (&cdktype, object);
98
99 if (obj != 0 && obj->bindingList != 0)
100 {
101 unsigned x;
102
103 for (x = 0; x < obj->bindingCount; x++)
104 {
105 (obj)->bindingList[x].bindFunction = 0;
106 (obj)->bindingList[x].bindData = 0;
107 }
108 freeAndNull ((obj)->bindingList);
109 }
110 }
111
112 /*
113 * This checks to see if the binding for the key exists:
114 * If it does then it runs the command and returns its value, normally TRUE.
115 * If it doesn't it returns a FALSE. This way we can 'overwrite' coded
116 * bindings.
117 */
checkCDKObjectBind(EObjectType cdktype,void * object,chtype key)118 int checkCDKObjectBind (EObjectType cdktype, void *object, chtype key)
119 {
120 CDKOBJS *obj = bindableObject (&cdktype, object);
121
122 if (obj != 0 && ((unsigned)key < obj->bindingCount))
123 {
124 if ((obj)->bindingList[key].bindFunction != 0)
125 {
126 BINDFN function = obj->bindingList[key].bindFunction;
127 void *data = obj->bindingList[key].bindData;
128
129 return function (cdktype, object, data, key);
130 }
131 }
132 return (FALSE);
133 }
134
135 /*
136 * This checks to see if the binding for the key exists.
137 */
isCDKObjectBind(EObjectType cdktype,void * object,chtype key)138 bool isCDKObjectBind (EObjectType cdktype, void *object, chtype key)
139 {
140 bool result = FALSE;
141 CDKOBJS *obj = bindableObject (&cdktype, object);
142
143 if (obj != 0 && ((unsigned)key < obj->bindingCount))
144 {
145 if ((obj)->bindingList[key].bindFunction != 0)
146 result = TRUE;
147 }
148 return (result);
149 }
150
151 /*
152 * This is a dummy function used to ensure that the constant for mapping has
153 * a distinct address.
154 */
getcCDKBind(EObjectType cdktype GCC_UNUSED,void * object GCC_UNUSED,void * clientData GCC_UNUSED,chtype input GCC_UNUSED)155 int getcCDKBind (EObjectType cdktype GCC_UNUSED,
156 void *object GCC_UNUSED,
157 void *clientData GCC_UNUSED,
158 chtype input GCC_UNUSED)
159 {
160 return 0;
161 }
162
163 /*
164 * Read from the input window, filtering keycodes as needed.
165 */
getcCDKObject(CDKOBJS * obj)166 int getcCDKObject (CDKOBJS *obj)
167 {
168 EObjectType cdktype = ObjTypeOf (obj);
169 CDKOBJS *test = bindableObject (&cdktype, obj);
170 int result = wgetch (InputWindowOf (obj));
171
172 if (result >= 0
173 && test != 0
174 && (unsigned)result < test->bindingCount
175 && test->bindingList[result].bindFunction == getcCDKBind)
176 {
177 result = (int)(long)test->bindingList[result].bindData;
178 }
179 else if (test == 0
180 || (unsigned)result >= test->bindingCount
181 || test->bindingList[result].bindFunction == 0)
182 {
183 switch (result)
184 {
185 case '\r':
186 case '\n':
187 result = KEY_ENTER;
188 break;
189 case '\t':
190 result = KEY_TAB;
191 break;
192 case DELETE:
193 result = KEY_DC;
194 break;
195 case '\b': /* same as CTRL('H'), for ASCII */
196 result = KEY_BACKSPACE;
197 break;
198 case CDK_BEGOFLINE:
199 result = KEY_HOME;
200 break;
201 case CDK_ENDOFLINE:
202 result = KEY_END;
203 break;
204 case CDK_FORCHAR:
205 result = KEY_RIGHT;
206 break;
207 case CDK_BACKCHAR:
208 result = KEY_LEFT;
209 break;
210 case CDK_NEXT:
211 result = KEY_TAB;
212 break;
213 case CDK_PREV:
214 result = KEY_BTAB;
215 break;
216 }
217 }
218 return result;
219 }
220
221 /*
222 * Use this function rather than getcCDKObject(), since we can extend it to
223 * handle wide-characters.
224 */
getchCDKObject(CDKOBJS * obj,boolean * functionKey)225 int getchCDKObject (CDKOBJS *obj, boolean *functionKey)
226 {
227 int key = getcCDKObject (obj);
228 if (functionKey != NULL)
229 {
230 *functionKey = (key >= KEY_MIN && key <= KEY_MAX);
231 }
232 return key;
233 }
234