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

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