Usermode/AxWin3 - Working on a bitmap/framebuffer window type
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / renderers / widget.c
1 /*
2  * Acess2 Window Manager v3
3  * - By John Hodge (thePowersGang)
4  *
5  * render_widget.c
6  * - AxWin2 Widget port
7  */
8 #include <common.h>
9 #include <wm_renderer.h>
10 #include <renderer_widget.h>
11 #include <string.h>
12 #include <wm_messages.h>
13 #include <stdlib.h>
14 #include "widget/common.h"
15
16 #define DEFAULT_ELETABLE_SIZE   64
17 #define BORDER_EVERYTHING       0
18
19 // === PROTOTYPES ===
20  int    Renderer_Widget_Init(void);
21 tWindow *Renderer_Widget_Create(int Flags);
22 void    Renderer_Widget_Redraw(tWindow *Window);
23
24 void    Widget_RenderWidget(tWindow *Window, tElement *Element);
25 void    Widget_UpdateDimensions(tElement *Element);
26 void    Widget_UpdatePosition(tElement *Element);
27 // --- Messages
28 tElement        *Widget_GetElementById(tWidgetWin *Info, uint32_t ID);
29 void    Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg);
30 void    Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg);
31 void    Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg);
32 void    Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg);
33  int    Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
34
35 // === GLOBALS ===
36 tWMRenderer     gRenderer_Widget = {
37         .Name = "Widget",
38         .CreateWindow = Renderer_Widget_Create,
39         .Redraw = Renderer_Widget_Redraw,
40         .HandleMessage = Renderer_Widget_HandleMessage
41 };
42         
43 // --- Element callbacks
44 tWidgetDef      *gaWM_WidgetTypes[NUM_ELETYPES];
45 const int       ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]);
46 tWidgetDef      gWidget_NullWidgetDef;
47
48 // === CODE ===
49 int Renderer_Widget_Init(void)
50 {
51          int    i;
52         WM_RegisterRenderer(&gRenderer_Widget); 
53
54         for(i = 0; i < ciWM_NumWidgetTypes; i ++)
55         {
56                 if(gaWM_WidgetTypes[i] != NULL) continue;
57                 
58                 gaWM_WidgetTypes[i] = &gWidget_NullWidgetDef;
59         }
60
61         return 0;
62 }
63
64 void Widget_int_SetTypeDef(int Type, tWidgetDef *Ptr)
65 {
66         if( Type < 0 || Type >= ciWM_NumWidgetTypes ) {
67                 _SysDebug("ERROR - Widget ID %i out of range (from %p)",
68                         Type, __builtin_return_address(0)
69                         );
70                 return ;
71         }
72         
73         if( gaWM_WidgetTypes[Type] && gaWM_WidgetTypes[Type] != &gWidget_NullWidgetDef )
74         {
75                 _SysDebug("ERROR - Widget ID %i redefined by %p",
76                         Type, __builtin_return_address(0)
77                         );
78                 return ;
79         }
80         
81         gaWM_WidgetTypes[Type] = Ptr;
82 }
83
84 tWindow *Renderer_Widget_Create(int Flags)
85 {
86         tWindow *ret;
87         tWidgetWin      *info;
88          int    eletable_size = DEFAULT_ELETABLE_SIZE;
89
90         _SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
91
92         // TODO: Use `Flags` as default element count?
93         // - Actaully, it's taken by the root ele flags
94         // - Use the upper bits?
95
96         ret = WM_CreateWindowStruct( sizeof(tWidgetWin) + sizeof(tElement*)*eletable_size );
97         info = ret->RendererInfo;
98         
99         info->TableSize = eletable_size;
100         info->FocusedElement = &info->RootElement;
101         info->RootElement.Window = ret;
102         info->RootElement.ID = -1;
103         info->RootElement.BackgroundColour = 0xCCCCCC;
104         info->RootElement.Flags = Flags;
105         info->RootElement.PaddingT = 2;
106         info->RootElement.PaddingB = 2;
107         info->RootElement.PaddingL = 2;
108         info->RootElement.PaddingR = 2;
109         
110         return ret;
111 }
112
113 void Renderer_Widget_Redraw(tWindow *Window)
114 {
115         tWidgetWin      *info = Window->RendererInfo;
116         WM_Render_FillRect(Window, 0, 0, Window->W, Window->H, info->RootElement.BackgroundColour);
117
118         Widget_UpdateDimensions(&info->RootElement);
119         Widget_UpdatePosition(&info->RootElement);
120
121         Widget_RenderWidget(Window, &info->RootElement);
122 }
123
124 // --- Render / Resize ---
125 void Widget_RenderWidget(tWindow *Window, tElement *Element)
126 {
127         tElement        *child;
128         
129         if( Element->Flags & ELEFLAG_NORENDER ) return ;
130         if( Element->Flags & ELEFLAG_INVISIBLE )        return ;
131
132         #if BORDER_EVERYTHING
133         WM_Render_DrawRect(
134                 Window,
135                 Element->CachedX, Element->CachedY,
136                 Element->CachedW, Element->CachedH,
137                 0
138                 );
139         #endif  
140
141         if(gaWM_WidgetTypes[Element->Type]->Render)
142         {
143                 gaWM_WidgetTypes[Element->Type]->Render(Window, Element);
144         }
145         
146         for(child = Element->FirstChild; child; child = child->NextSibling)
147         {
148                 Widget_RenderWidget(Window, child);
149         }
150 }
151
152 void Widget_UpdateDimensions(tElement *Element)
153 {
154         tElement        *child;
155          int    nChildren = 0;
156          int    nFixed = 0;
157          int    maxCross = 0;
158          int    fixedSize = 0;
159          int    fullCross, dynWith = 0;
160          int    bVertical = Element->Flags & ELEFLAG_VERTICAL;
161
162         // Check if this element can have children
163         if( (gaWM_WidgetTypes[Element->Type]->Flags & WIDGETTYPE_FLAG_NOCHILDREN) )
164                 return ;
165         
166         // Pass 1
167         // - Get the fixed and minimum sizes of the element
168         for( child = Element->FirstChild; child; child = child->NextSibling )
169         {
170                  int    minWith  = bVertical ? child->MinH : child->MinW;
171                  int    minCross = bVertical ? child->MinW : child->MinH;
172
173                 // Ignore elements that will not be rendered
174                 if( child->Flags & ELEFLAG_NORENDER )   continue ;
175                 
176                 // Absolutely positioned elements don't affect dimensions
177                 if( child->Flags & ELEFLAG_ABSOLUTEPOS )        continue ;
178         
179                 // Fixed width elements 
180                 if( child->FixedWith )
181                 {
182                         nFixed ++;
183                         fixedSize += child->FixedWith;
184                 }
185                 else if( child->Flags & ELEFLAG_NOSTRETCH )
186                 {
187                         nFixed ++;
188                         fixedSize += minWith;
189                 }
190                 
191                 if( maxCross < child->FixedCross )      maxCross = child->FixedCross;
192                 if( maxCross < minCross )       maxCross = minCross;
193                 nChildren ++;
194         }
195
196         // Get the dynamic with size from the unused space in the element
197         if( nChildren > nFixed ) {
198                 if( bVertical )
199                         dynWith = Element->CachedH - Element->PaddingT - Element->PaddingB;
200                 else
201                         dynWith = Element->CachedW - Element->PaddingL - Element->PaddingR;
202                 dynWith -= fixedSize;
203                 dynWith -= Element->GapSize * (nChildren-1);
204                 if( dynWith < 0 )       return ;
205                 dynWith /= nChildren - nFixed;
206         }
207         else {
208                 dynWith = 0;
209         }
210         
211         // Get the cross size
212         if( bVertical )
213                 fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
214         else
215                 fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
216
217         _SysDebug("%i (p=%i) - WxH=%ix%i",
218                 Element->ID, (Element->Parent ? Element->Parent->ID : -1),
219                 Element->CachedW, Element->CachedH
220                 );
221         _SysDebug("  %s dynWith = %i, fullCross = %i",
222                 (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"),
223                 dynWith, fullCross
224                 );
225         
226         // Pass 2 - Set sizes and recurse
227         for( child = Element->FirstChild; child; child = child->NextSibling )
228         {
229                  int    w, h;
230
231                 // Ignore elements that will not be rendered
232                 if( child->Flags & ELEFLAG_NORENDER )   continue ;
233                 // Don't resize floating elements
234                 if( child->Flags & ELEFLAG_ABSOLUTEPOS )        continue ;
235                 
236                 // --- Width ---
237                 if( child->Flags & ELEFLAG_NOEXPAND )
238                         w = child->MinW;
239                 else if( bVertical )
240                         w = child->FixedCross ? child->FixedCross : fullCross;
241                 else
242                         w = child->FixedWith ? child->FixedWith : dynWith;
243         
244                 // --- Height ---
245                 if( child->Flags & ELEFLAG_NOSTRETCH )
246                         h = child->MinH;
247                 else if( bVertical )
248                         h = child->FixedWith ? child->FixedWith : dynWith;
249                 else
250                         h = child->FixedCross ? child->FixedCross : fullCross;
251
252                 if(w < child->MinW)     w = child->MinW;
253                 if(h < child->MinH)     h = child->MinH;
254         
255 //              _SysDebug("Child %ix%i (min %ix%i)", w, h, child->MinW, child->MinH);
256         
257                 // Update the dimensions if they have changed
258                 if( child->CachedW == w && child->CachedH == h )
259                         continue ;
260                 child->CachedW = w;
261                 child->CachedH = h;
262                 
263                 // Force the positions of child elements to be recalculated
264                 child->CachedX = -1;
265         
266                 // Recurse down so the child elements can be updated    
267                 Widget_UpdateDimensions(child);
268         }
269         
270 }
271
272 /**
273  * \brief Update the position of child elements
274  */
275 void Widget_UpdatePosition(tElement *Element)
276 {
277         tElement        *child;
278          int    x, y;
279         
280         if( Element->Flags & ELEFLAG_NORENDER ) return ;
281
282         // Check if this element can have children
283         if( (gaWM_WidgetTypes[Element->Type]->Flags & WIDGETTYPE_FLAG_NOCHILDREN) )
284                 return ;
285
286 //      _SysDebug("Widget_UpdatePosition: (Element=%p(%i Type=%i Flags=0x%x))",
287 //              Element, Element->ID, Element->Type, Element->Flags);
288         
289         // Initialise
290         x = Element->CachedX + Element->PaddingL;
291         y = Element->CachedY + Element->PaddingT;
292         
293         // Update each child
294         for(child = Element->FirstChild; child; child = child->NextSibling)
295         {
296                  int    newX, newY;
297                 // Ignore elements that will not be rendered
298                 if( child->Flags & ELEFLAG_NORENDER )   continue ;
299
300                 newX = x; newY = y;
301                 
302                 // Handle alignment (across parent)
303                 if( Element->Flags & ELEFLAG_ALIGN_CENTER ) {
304                         if(Element->Flags & ELEFLAG_VERTICAL)
305                                 newX += Element->CachedW/2 - child->CachedW/2;
306                         else
307                                 newY += Element->CachedH/2 - child->CachedH/2;
308                 }
309                 else if( Element->Flags & ELEFLAG_ALIGN_END ) {
310                         if(Element->Flags & ELEFLAG_VERTICAL )
311                                 newX += Element->CachedW - child->CachedW
312                                         - Element->PaddingL - Element->PaddingR;
313                         else
314                                 newY += Element->CachedH - child->CachedH
315                                         - Element->PaddingT - Element->PaddingB;
316                 }
317
318 //              _SysDebug(" Widget_UpdatePosition[%i]: newX = %i, newY = %i", Element->ID, newX, newY);
319
320                 // Check for changes, and don't update if there was no change
321                 if( newX != child->CachedX || newY != child->CachedY )
322                 {
323                         child->CachedX = newX;
324                         child->CachedY = newY;
325                         // Update child's children positions
326                         Widget_UpdatePosition(child);
327                 }
328                 
329                 // Increment
330                 if(Element->Flags & ELEFLAG_VERTICAL ) {
331                         y += child->CachedH + Element->GapSize;
332                 }
333                 else {
334                         x += child->CachedW + Element->GapSize;
335                 }
336         }
337 }
338
339 /**
340  * \brief Update the minimum dimensions of the element
341  * \note Called after a child's minimum dimensions have changed
342  */
343 void Widget_UpdateMinDims(tElement *Element)
344 {
345         tElement        *child;
346          int    minW, minH;
347          int    nChildren;
348         
349         if(!Element)    return;
350         
351         minW = 0;
352         minH = 0;
353         nChildren = 0;
354         
355         for(child = Element->FirstChild; child; child = child->NextSibling)
356         {
357                  int    cross;
358                 
359                 if(Element->Flags & ELEFLAG_NORENDER)   continue ;
360                 
361                 if( (Element->Flags & ELEFLAG_VERTICAL) )
362                 {
363                         cross = child->FixedCross ? child->FixedCross : child->MinW;
364                         if(minW < cross)        minW = cross;
365                         minH += child->FixedWith  ? child->FixedWith  : child->MinH;
366                 }
367                 else
368                 {
369                         cross = child->FixedCross ? child->FixedCross : child->MinH;
370                         minW += child->FixedWith  ? child->FixedWith  : child->MinW;
371                         if(minH < cross)        minH = cross;
372                 }
373 //              _SysDebug("%i/%i cross = %i", Element->ID, child->ID, cross);
374         
375                 nChildren ++;
376         }
377         
378         if( Element->Flags & ELEFLAG_VERTICAL )
379                 minH += (nChildren - 1) * Element->GapSize;
380         else
381                 minW += (nChildren - 1) * Element->GapSize;
382
383         Element->MinW = Element->PaddingL + minW + Element->PaddingR;
384         Element->MinH = Element->PaddingT + minH + Element->PaddingB;
385
386         // Recurse upwards
387         Widget_UpdateMinDims(Element->Parent);
388 }
389
390 tElement *Widget_GetElementByPos(tWidgetWin *Info, int X, int Y)
391 {
392         tElement        *ret, *next, *ele;
393         
394         next = &Info->RootElement;
395         do
396         {
397                 ret = next;
398                 next = NULL;
399                 for(ele = ret->FirstChild; ele; ele = ele->NextSibling)
400                 {
401                         if(ele->Flags & ELEFLAG_NORENDER)       continue;
402                         if(X < ele->CachedX)    continue;
403                         if(Y < ele->CachedY)    continue;
404                         if(X >= ele->CachedX + ele->CachedW)    continue;
405                         if(Y >= ele->CachedY + ele->CachedH)    continue;
406                         next = ele;
407                 }
408         } while(next);
409         return ret;
410 }
411
412 // --- Helpers ---
413 tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID)
414 {
415         tElement        *ele;
416
417         if( ID == -1 )  return &Info->RootElement;
418         
419         if( ID < Info->TableSize )      return Info->ElementTable[ID];
420
421         ele = Info->ElementTable[ID % Info->TableSize];
422         while(ele && ele->ID != ID)     ele = ele->ListNext;
423         return ele;
424 }
425
426 // --- Message Handlers ---
427 void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg)
428 {
429         const int       max_debugname_len = Len - sizeof(tWidgetMsg_Create);
430         tElement        *parent, *new;
431
432         // Sanity check
433         if( Len < sizeof(*Msg) )
434                 return ;
435         if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
436                 return ;
437         
438         _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)",
439                 Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags);
440         
441         if(Msg->Type >= ciWM_NumWidgetTypes)
442         {
443                 _SysDebug("Widget_NewWidget - Bad widget type %i", Msg->Type);
444                 return ;
445         }
446
447         // Create
448         parent = Widget_GetElementById(Info, Msg->Parent);
449         if(!parent)
450         {
451                 _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
452                 return ;
453         }
454
455         // Check if the ID is already in use
456         if( Widget_GetElementById(Info, Msg->NewID) )
457                 return ;
458
459         // Create new element
460         new = calloc(sizeof(tElement), 1);
461         new->Window = parent->Window;
462         new->ID = Msg->NewID;
463         new->Type = Msg->Type;
464         new->Parent = parent;
465         new->Flags = Msg->Flags;
466         new->PaddingT = 2;
467         new->PaddingB = 2;
468         new->PaddingL = 2;
469         new->PaddingR = 2;
470         new->CachedX = -1;
471         
472         if( gaWM_WidgetTypes[new->Type]->Init )
473                 gaWM_WidgetTypes[new->Type]->Init(new);
474         
475         // Add to parent's list
476         if(parent->LastChild)
477                 parent->LastChild->NextSibling = new;
478         else
479                 parent->FirstChild = new;
480         parent->LastChild = new;
481
482         // Add to info
483         {
484                 tElement        *ele, *prev = NULL;
485                 for(ele = Info->ElementTable[new->ID % Info->TableSize]; ele; prev = ele, ele = ele->ListNext);
486                 if(prev)
487                         prev->ListNext = new;
488                 else
489                         Info->ElementTable[new->ID % Info->TableSize] = new;
490         }
491
492         Widget_UpdateMinDims(parent);
493 }
494
495 void Widget_SetFocus(tWidgetWin *Info, tElement *Ele)
496 {
497         // TODO: Callbacks
498
499         Info->FocusedElement = Ele;
500 }
501
502 void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg)
503 {
504         tElement        *ele;
505         
506         if( Len < sizeof(*Msg) )
507                 return ;
508
509         _SysDebug("Widget_SetFlags: (%i 0x%x 0x%x)", Msg->WidgetID, Msg->Value, Msg->Mask);
510         
511         ele = Widget_GetElementById(Info, Msg->WidgetID);
512         if(!ele)        return;
513
514         ele->Flags &= ~Msg->Mask;
515         ele->Flags |= Msg->Value & Msg->Mask;
516 }
517
518 void Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg)
519 {
520         tElement        *ele;
521         
522         if( Len < sizeof(*Msg) )
523                 return ;
524         
525         ele = Widget_GetElementById(Info, Msg->WidgetID);
526         if(!ele)        return ;
527         
528         ele->FixedWith = Msg->Value;
529 }
530
531 void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
532 {
533         tElement        *ele;
534         
535         if( Len < sizeof(*Msg) + 1 )
536                 return ;
537         if( Msg->Text[Len - sizeof(*Msg) - 1] != '\0' )
538                 return ;
539
540         ele = Widget_GetElementById(Info, Msg->WidgetID);
541         if(!ele)        return ;
542
543
544         if( gaWM_WidgetTypes[ele->Type]->UpdateText )
545         {
546                 gaWM_WidgetTypes[ele->Type]->UpdateText( ele, Msg->Text );
547         }
548 //      else
549 //      {
550 //              if(ele->Text)   free(ele->Text);
551 //              ele->Text = strdup(Msg->Text);
552 //      }
553 }
554
555 int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
556 {
557         tWidgetWin      *info = Target->RendererInfo;
558         tElement        *ele;
559         switch(Msg)
560         {
561         case WNDMSG_RESIZE: {
562                 const struct sWndMsg_Resize     *msg = Data;
563                 if(Len < sizeof(*msg))  return -1;              
564
565                 info->RootElement.CachedW = msg->W;             
566                 info->RootElement.CachedH = msg->H;
567                 
568                 // TODO: Update dimensions of all child elements?
569                 
570                 return 0; }
571
572         case WNDMSG_MOUSEMOVE: {
573 //              _SysDebug("TODO: Support widget mouse move events");
574                 return 0; }
575
576         case WNDMSG_MOUSEBTN: {
577                 const struct sWndMsg_MouseButton        *msg = Data;
578                 tWidgetMsg_MouseBtn     client_msg;
579                  int    x, y;
580                  int    rv;
581                 
582                 if(Len < sizeof(*msg))  return -1;
583
584                 x = msg->X; y = msg->Y;
585                 client_msg.Button = msg->Button;
586                 client_msg.bPressed = msg->bPressed;
587
588                 ele = Widget_GetElementByPos(info, x, y);
589                 Widget_SetFocus(info, ele);
590                 // Send event to all elements from `ele` upwards
591                 for( ; ele; ele = ele->Parent )
592                 {
593                         if(gaWM_WidgetTypes[ele->Type]->MouseButton)
594                         {
595                                 rv = gaWM_WidgetTypes[ele->Type]->MouseButton(
596                                         ele,
597                                         x - ele->CachedX, y - ele->CachedY,
598                                         msg->Button, msg->bPressed
599                                         );
600                                 // Allow a type to trap the input from going any higher
601                                 if(rv == 0)     break;
602                         }
603                         else
604                         {
605                                 // Pass to user
606                                 client_msg.X = x - ele->CachedX;
607                                 client_msg.Y = y - ele->CachedY;
608                                 client_msg.WidgetID = ele->ID;
609                                 WM_SendMessage(Target, Target, MSG_WIDGET_MOUSEBTN, sizeof(client_msg), &client_msg);
610                         }
611                 }
612                 return 0; }
613
614         case WNDMSG_KEYDOWN: {
615                 const struct sWndMsg_KeyAction  *msg = Data;
616                 if(Len < sizeof(*msg))  return -1;
617                 
618                 if(!info->FocusedElement)       return 0;
619                 ele = info->FocusedElement;
620
621                 if(gaWM_WidgetTypes[ele->Type]->KeyDown)
622                         gaWM_WidgetTypes[ele->Type]->KeyDown(ele, msg->KeySym, msg->UCS32);
623                 else
624                 {
625                         // TODO: Pass to user
626                 }       
627
628                 return 0; }
629         
630         case WNDMSG_KEYFIRE: {
631                 const struct sWndMsg_KeyAction  *msg = Data;
632                 if(Len < sizeof(*msg))  return -1;
633                 
634                 if(!info->FocusedElement)       return 0;
635                 ele = info->FocusedElement;
636
637                 if(gaWM_WidgetTypes[ele->Type]->KeyFire)
638                         gaWM_WidgetTypes[ele->Type]->KeyFire(ele, msg->KeySym, msg->UCS32);
639                 else
640                 {
641                         // TODO: Pass the buck
642                 }
643                 return 0; }
644         
645         case WNDMSG_KEYUP: {
646                 const struct sWndMsg_KeyAction  *msg = Data;
647                 if(Len < sizeof(*msg))  return -1;
648                 
649                 if(!info->FocusedElement)       return 0;
650                 ele = info->FocusedElement;
651
652                 if(gaWM_WidgetTypes[ele->Type]->KeyUp)
653                         gaWM_WidgetTypes[ele->Type]->KeyUp(ele, msg->KeySym);
654                 else
655                 {
656                         // TODO: Pass the buck
657                 }
658                 return 0; }
659
660         // New Widget
661         case MSG_WIDGET_CREATE:
662                 Widget_NewWidget(info, Len, Data);
663                 return 0;
664
665         // Delete a widget
666         case MSG_WIDGET_DELETE:
667                 _SysDebug("TODO: Implement MSG_WIDGET_DELETE");
668                 return 0;
669
670         // Set focused widget
671         case MSG_WIDGET_SETFOCUS: {
672                 tElement        *ele;
673                 const tWidgetMsg_SetFocus       *msg = Data;
674                 if(Len < sizeof(*msg))  return -1;
675                 
676                 ele = Widget_GetElementById(info, msg->WidgetID);
677                 Widget_SetFocus(info, ele);
678                 return 0; }
679
680         // Set Flags
681         case MSG_WIDGET_SETFLAGS:
682                 Widget_SetFlags(info, Len, Data);
683                 return 0;
684         
685         // Set length
686         case MSG_WIDGET_SETSIZE:
687                 Widget_SetSize(info, Len, Data);
688                 return 0;
689         
690         // Set text
691         case MSG_WIDGET_SETTEXT:
692                 Widget_SetText(info, Len, Data);
693                 return 0;
694         
695         // 
696         default:
697                 return 1;       // Unhandled, pass to user
698         }
699 }
700
701 void Widget_Fire(tElement *Element)
702 {
703         tWidgetMsg_Fire msg;
704         msg.WidgetID = Element->ID;
705         WM_SendMessage(Element->Window, Element->Window, MSG_WIDGET_FIRE, sizeof(msg), &msg);
706 }
707

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