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