Usermode/AxWin3 - Cleaner libaxwin WNDMSG handling
[tpg/acess2.git] / Usermode / Applications / axwin3_src / libaxwin3.so_src / r_widget.c
1 /*
2  * AxWin3 Interface Library
3  * - By John Hodge (thePowersGang)
4  *
5  * r_widget.c
6  * - Widget window type interface
7  */
8 #include <axwin3/axwin.h>
9 #include <axwin3/widget.h>
10 #include "include/internal.h"
11 #include <stdlib.h>
12 #include <widget_messages.h>
13 #include <string.h>
14
15 // === STRUCTURES ===
16 struct sAxWin3_Widget
17 {
18         tHWND   Window;
19         uint32_t        ID;
20         // Callbacks
21         tAxWin3_Widget_FireCb   Fire;
22         tAxWin3_Widget_KeyUpDownCb      KeyUpDown;
23         tAxWin3_Widget_KeyFireCb        KeyFire;
24         tAxWin3_Widget_MouseMoveCb      MouseMove;
25         tAxWin3_Widget_MouseBtnCb       MouseButton;
26 };
27
28 typedef struct
29 {
30          int    nElements;
31         tAxWin3_Widget  **Elements;
32          int    FirstFreeID;
33         tAxWin3_Widget  RootElement;
34         // Callbacks for each element
35 } tWidgetWindowInfo;
36
37 // === CODE ===
38 tAxWin3_Widget *AxWin3_Widget_int_GetElementByID(tHWND Window, uint32_t ID)
39 {
40         tWidgetWindowInfo       *info;
41         if(!Window)     return NULL;
42         
43         info = AxWin3_int_GetDataPtr(Window);
44         if(ID >= info->nElements)       return NULL;
45         
46         return info->Elements[ID];
47 }
48
49 uint32_t AxWin3_Widget_int_AllocateID(tWidgetWindowInfo *Info)
50 {
51         uint32_t        newID;
52         // BUG BUG BUG - Double Allocations! (citation needed)
53         // TODO: Atomicity
54         for( newID = Info->FirstFreeID; newID < Info->nElements; newID ++ )
55         {
56                 if( Info->Elements[newID] == NULL )
57                         break;
58         }
59         if( newID == Info->nElements )
60         {
61                 const int size_step = 4;
62                 Info->nElements += 4;
63                 Info->Elements = realloc(Info->Elements, sizeof(*Info->Elements)*Info->nElements);
64                 newID = Info->nElements - 4;
65                 memset( &Info->Elements[newID+1], 0, (size_step-1)*sizeof(Info->Elements));
66                 _SysDebug("Widget: Expanded to %i and allocated %i", Info->nElements, newID);
67         }
68         else
69                 _SysDebug("Widget: Allocated %i", newID);
70         Info->Elements[newID] = (void*)-1;
71         
72         return newID;
73         
74 }
75
76 int AxWin3_Widget_MessageHandler(tHWND Window, int MessageID, int Size, void *Data)
77 {
78         tAxWin3_Widget  *widget;
79
80         switch(MessageID)
81         {
82         case MSG_WIDGET_FIRE: {
83                 tWidgetMsg_Fire *msg = Data;
84                 if(Size < sizeof(*msg)) return -1;
85                 widget = AxWin3_Widget_int_GetElementByID(Window, msg->WidgetID);
86                 if(widget->Fire)        widget->Fire(widget);
87                 
88                 return 1; }
89         default:
90                 return 0;
91         }
92 }
93
94 tHWND AxWin3_Widget_CreateWindow(tHWND Parent, int W, int H, int RootEleFlags)
95 {
96         tHWND   ret;
97         tWidgetWindowInfo       *info;
98         
99         ret = AxWin3_CreateWindow(
100                 Parent, "Widget", RootEleFlags,
101                 sizeof(*info) + sizeof(tAxWin3_Widget), AxWin3_Widget_MessageHandler
102                 );
103         info = AxWin3_int_GetDataPtr(ret);
104
105         info->RootElement.Window = ret;
106         info->RootElement.ID = -1;
107
108         AxWin3_ResizeWindow(ret, W, H);
109         
110         return ret;
111 }
112
113 void AxWin3_Widget_DestroyWindow(tHWND Window)
114 {
115         // Free all element structures
116         
117         // Free array
118         
119         // Request window to be destroyed (will clean up any data stored in tHWND)
120 }
121
122 tAxWin3_Widget *AxWin3_Widget_GetRoot(tHWND Window)
123 {
124         tWidgetWindowInfo       *info = AxWin3_int_GetDataPtr(Window);
125         return &info->RootElement;
126 }
127
128 tAxWin3_Widget *AxWin3_Widget_AddWidget(tAxWin3_Widget *Parent, int Type, int Flags, const char *DebugName)
129 {
130          int    newID;
131         tWidgetWindowInfo       *info;
132         tAxWin3_Widget  *ret;
133
134         if(!Parent)     return NULL;
135
136         info = AxWin3_int_GetDataPtr(Parent->Window);
137         
138         newID = AxWin3_Widget_int_AllocateID(info);
139         
140         // Create new widget structure
141         ret = calloc(sizeof(tAxWin3_Widget), 1);
142         ret->Window = Parent->Window;
143         ret->ID = newID;
144
145         info->Elements[newID] = ret;
146
147         // Send create widget message
148         {
149                 char    tmp[sizeof(tWidgetIPC_Create)+1];
150                 tWidgetIPC_Create       *msg = (void*)tmp;
151                 msg->Parent = Parent->ID;
152                 msg->NewID = newID;
153                 msg->Type = Type;
154                 msg->Flags = Flags;
155                 msg->DebugName[0] = '\0';
156                 AxWin3_SendIPC(ret->Window, IPC_WIDGET_CREATE, sizeof(tmp), tmp);
157         }
158
159         return ret;
160 }
161
162 tAxWin3_Widget *AxWin3_Widget_AddWidget_SubWindow(tAxWin3_Widget *Parent, tHWND Window, int Flags, const char *DbgName)
163 {
164         tWidgetWindowInfo       *info = AxWin3_int_GetDataPtr(Parent->Window);
165         int newID = AxWin3_Widget_int_AllocateID(info);
166         
167         tAxWin3_Widget  *ret = calloc(sizeof(tAxWin3_Widget), 1);
168         ret->Window = Parent->Window;
169         ret->ID = newID;
170         info->Elements[newID] = ret;
171
172         // Send message
173         {
174                 char    tmp[sizeof(tWidgetIPC_CreateSubWin)+1];
175                 tWidgetIPC_CreateSubWin *msg = (void*)tmp;
176                 msg->Parent = Parent->ID;
177                 msg->NewID = newID;
178                 msg->Type = ELETYPE_SUBWIN;
179                 msg->Flags = Flags;     // TODO: Flags
180                 msg->WindowHandle = AxWin3_int_GetWindowID(Window);
181                 msg->DebugName[0] = '\0';
182                 AxWin3_SendIPC(ret->Window, IPC_WIDGET_CREATESUBWIN, sizeof(tmp), tmp);
183         }
184
185         return ret;
186 }
187
188
189 void AxWin3_Widget_DelWidget(tAxWin3_Widget *Widget)
190 {
191         tWidgetIPC_Delete       msg;
192         tWidgetWindowInfo       *info = AxWin3_int_GetDataPtr(Widget->Window);
193         
194         msg.WidgetID = Widget->ID;
195         AxWin3_SendIPC(Widget->Window, IPC_WIDGET_DELETE, sizeof(msg), &msg);
196         
197         info->Elements[Widget->ID] = NULL;
198         if(Widget->ID < info->FirstFreeID)
199                 info->FirstFreeID = Widget->ID;
200         free(Widget);
201 }
202
203 // --- Callbacks
204 void AxWin3_Widget_SetFireHandler(tAxWin3_Widget *Widget, tAxWin3_Widget_FireCb Callback)
205 {
206         if(!Widget)     return;
207         Widget->Fire = Callback;
208 }
209
210 void AxWin3_Widget_SetKeyHandler(tAxWin3_Widget *Widget, tAxWin3_Widget_KeyUpDownCb Callback)
211 {
212         if(!Widget)     return;
213         Widget->KeyUpDown = Callback;
214 }
215
216 void AxWin3_Widget_SetKeyFireHandler(tAxWin3_Widget *Widget, tAxWin3_Widget_KeyFireCb Callback)
217 {
218         if(!Widget)     return;
219         Widget->KeyFire = Callback;
220 }
221
222 void AxWin3_Widget_SetMouseMoveHandler(tAxWin3_Widget *Widget, tAxWin3_Widget_MouseMoveCb Callback)
223 {
224         if(!Widget)     return;
225         Widget->MouseMove = Callback;
226 }
227
228 void AxWin3_Widget_SetMouseButtonHandler(tAxWin3_Widget *Widget, tAxWin3_Widget_MouseBtnCb Callback)
229 {
230         if(!Widget)     return;
231         Widget->MouseButton = Callback;
232 }
233
234 // --- Manipulation
235 void AxWin3_Widget_SetFlags(tAxWin3_Widget *Widget, int FlagSet, int FlagMask)
236 {
237         tWidgetIPC_SetFlags     msg;
238         msg.WidgetID = Widget->ID;
239         msg.Value = FlagSet;
240         msg.Mask = FlagMask;
241         
242         AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETFLAGS, sizeof(msg), &msg);
243 }
244
245 void AxWin3_Widget_SetSize(tAxWin3_Widget *Widget, int Size)
246 {
247         tWidgetIPC_SetSize      msg;
248         
249         msg.WidgetID = Widget->ID;
250         msg.Value = Size;
251         AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETSIZE, sizeof(msg), &msg);
252 }
253
254 void AxWin3_Widget_SetText(tAxWin3_Widget *Widget, const char *Text)
255 {
256         char    buf[sizeof(tWidgetIPC_SetText) + strlen(Text) + 1];
257         tWidgetIPC_SetText      *msg = (void*)buf;
258         
259         msg->WidgetID = Widget->ID;
260         strcpy(msg->Text, Text);
261         
262         AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETTEXT, sizeof(buf), buf);
263 }
264
265 char *AxWin3_Widget_GetText(tAxWin3_Widget *Widget)
266 {
267         char    buf[sizeof(tWidgetIPC_SetText)];
268         tWidgetIPC_SetText      *msg = (void*)buf;
269         size_t  retmsg_size;
270         
271         msg->WidgetID = Widget->ID;
272
273         AxWin3_SendIPC(Widget->Window, IPC_WIDGET_GETTEXT, sizeof(buf), buf);
274
275         msg = AxWin3_WaitIPCMessage(Widget->Window, IPC_WIDGET_GETTEXT, &retmsg_size);
276         if( retmsg_size < sizeof(*msg) ) {
277                 free(msg);
278                 return NULL;
279         }
280
281         char    *ret = strndup(msg->Text, retmsg_size - sizeof(*msg));
282         free(msg);
283         return ret;
284 }
285
286 void AxWin3_Widget_SetColour(tAxWin3_Widget *Widget, int Index, tAxWin3_Colour Colour)
287 {
288         tWidgetIPC_SetColour    msg;
289         
290         msg.WidgetID = Widget->ID;
291         msg.Index = Index;
292         msg.Colour = Colour;
293         AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETCOLOUR, sizeof(msg), &msg);
294 }

UCC git Repository :: git.ucc.asn.au