51692a64fbbfd45b475762cee8005953a6e59685
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / ipc.c
1 /*
2  * Acess2 GUI (AxWin) Version 3
3  * - By John Hodge (thePowersGang)
4  * 
5  * ipc.c
6  * - Interprocess communication
7  */
8 #include <common.h>
9 #include <acess/sys.h>
10 #include <net.h>
11 #include <string.h>
12 #include <ipcmessages.h>
13 #include <stdio.h>
14 #include <wm.h>
15 #include <wm_internals.h>
16 #include <wm_hotkeys.h> // Hotkey registration
17 #include <wm_renderer.h>        // Renderer IPC messages
18
19 #define AXWIN_PORT      4101
20
21 #define STATICBUF_SIZE  64
22 #define MAX_WINDOWS_PER_APP     128
23
24 // === TYPES ===
25 typedef struct sIPC_Type        tIPC_Type;
26
27 struct sIPC_Type
28 {
29          int    (*GetIdentSize)(const void *Ident);
30          int    (*CompareIdent)(const void *Ident1, const void *Ident2);
31         void    (*SendMessage)(const void *Ident, size_t Length, const void *Data);
32 };
33
34 struct sIPC_Client
35 {
36         const tIPC_Type *IPCType;
37         const void      *Ident; // Stored after structure
38
39          int    nWindows;
40         tWindow **Windows;
41 };
42
43 // === IMPORTS ===
44 extern tWindow  *gpWM_FocusedWindow;    // Needed for _FocusWindow
45
46 // === PROTOTYPES ===
47 void    IPC_Init(void);
48 void    IPC_FillSelect(int *nfds, fd_set *set);
49 void    IPC_HandleSelect(fd_set *set);
50  int    IPC_Type_Datagram_GetSize(const void *Ident);
51  int    IPC_Type_Datagram_Compare(const void *Ident1, const void *Ident2);
52 void    IPC_Type_Datagram_Send(const void *Ident, size_t Length, const void *Data);
53  int    IPC_Type_Sys_GetSize(const void *Ident);
54  int    IPC_Type_Sys_Compare(const void *Ident1, const void *Ident2);
55 void    IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data);
56 void    IPC_Handle(const tIPC_Type *IPCType, const void *Ident, size_t MsgLen, tAxWin_IPCMessage *Msg);
57
58 // === GLOBALS ===
59 const tIPC_Type gIPC_Type_Datagram = {
60         IPC_Type_Datagram_GetSize,
61         IPC_Type_Datagram_Compare, 
62         IPC_Type_Datagram_Send
63 };
64 const tIPC_Type gIPC_Type_SysMessage = {
65         IPC_Type_Sys_GetSize,
66         IPC_Type_Sys_Compare,
67         IPC_Type_Sys_Send
68 };
69  int    giNetworkFileHandle = -1;
70  int    giMessagesFileHandle = -1;
71  int    giIPC_ClientCount;
72 tIPC_Client     **gIPC_Clients;
73
74 // === CODE ===
75 void IPC_Init(void)
76 {
77          int    tmp;
78         // TODO: Check this
79         giNetworkFileHandle = _SysOpen("/Devices/ip/loop/udp", OPENFLAG_READ);
80         if( giNetworkFileHandle != -1 )
81         {
82                 tmp = AXWIN_PORT;
83                 _SysIOCtl(giNetworkFileHandle, 4, &tmp);        // TODO: Don't hard-code IOCtl number
84         }
85 }
86
87 void IPC_FillSelect(int *nfds, fd_set *set)
88 {
89         if( giNetworkFileHandle != -1 )
90         {
91                 if( giNetworkFileHandle > *nfds )       *nfds = giNetworkFileHandle;
92                 FD_SET(giNetworkFileHandle, set);
93         }
94 }
95
96 void IPC_HandleSelect(fd_set *set)
97 {
98         if( giNetworkFileHandle != -1 )
99         {
100                 if( FD_ISSET(giNetworkFileHandle, set) )
101                 {
102                         char    staticBuf[STATICBUF_SIZE];
103                          int    readlen, identlen;
104                         char    *msg;
105         
106                         readlen = _SysRead(giNetworkFileHandle, staticBuf, sizeof(staticBuf));
107                         
108                         identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
109                         msg = staticBuf + identlen;
110         
111                         IPC_Handle(&gIPC_Type_Datagram, staticBuf, readlen - identlen, (void*)msg);
112 //                      _SysDebug("IPC_HandleSelect: UDP handled");
113                 }
114         }
115
116         size_t  len;
117         int     tid;
118         while( (len = _SysGetMessage(&tid, 0, NULL)) )
119         {
120                 char    data[len];
121                 _SysGetMessage(NULL, len, data);
122
123                 IPC_Handle(&gIPC_Type_SysMessage, &tid, len, (void*)data);
124 //              _SysDebug("IPC_HandleSelect: Message handled");
125         }
126 }
127
128 int IPC_Type_Datagram_GetSize(const void *Ident)
129 {
130         return 4 + Net_GetAddressSize( ((const uint16_t*)Ident)[1] );
131 }
132
133 int IPC_Type_Datagram_Compare(const void *Ident1, const void *Ident2)
134 {
135         // Pass the buck :)
136         // - No need to worry about mis-matching sizes, as the size is computed
137         //   from the 3rd/4th bytes, hence it will differ before the size is hit.
138         return memcmp(Ident1, Ident2, IPC_Type_Datagram_GetSize(Ident1));
139 }
140
141 void IPC_Type_Datagram_Send(const void *Ident, size_t Length, const void *Data)
142 {
143          int    identlen = IPC_Type_Datagram_GetSize(Ident);
144         char    tmpbuf[ identlen + Length ];
145         memcpy(tmpbuf, Ident, identlen);        // Header
146         memcpy(tmpbuf + identlen, Data, Length);        // Data
147         // TODO: Handle fragmented packets
148         _SysWrite(giNetworkFileHandle, tmpbuf, sizeof(tmpbuf));
149 }
150
151 int IPC_Type_Sys_GetSize(const void *Ident)
152 {
153         return sizeof(pid_t);
154 }
155
156 int IPC_Type_Sys_Compare(const void *Ident1, const void *Ident2)
157 {
158         return *(const tid_t*)Ident1 - *(const tid_t*)Ident2;
159 }
160
161 void IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data)
162 {
163         _SysSendMessage( *(const tid_t*)Ident, Length, Data );
164 }
165
166 // --- Client -> Window Mappings
167 int _CompareClientPtrs(const void *_a, const void *_b)
168 {
169         tIPC_Client     *a = *(tIPC_Client**)_a;
170         tIPC_Client     *b = *(tIPC_Client**)_b;
171
172         ASSERT(a);
173         ASSERT(b);
174
175         if(a->IPCType < b->IPCType)     return -1;
176         if(a->IPCType > b->IPCType)     return 1;
177         
178         return a->IPCType->CompareIdent(a->Ident, b->Ident);
179 }
180
181 tIPC_Client *IPC_int_GetClient(const tIPC_Type *IPCType, const void *Ident)
182 {
183          int    pos = 0;        // Position where the new client will be inserted
184          int    ident_size;
185         tIPC_Client     *ret;
186
187         // - Search list of registered clients
188         if(giIPC_ClientCount > 0)
189         {
190                 tIPC_Client     target;
191                  int    div;
192                  int    cmp = -1;
193         
194                 target.IPCType = IPCType;
195                 target.Ident = Ident;
196                 ret = &target;  // Abuse ret to get a pointer
197                 
198                 div = giIPC_ClientCount;
199                 pos = div/2;
200                 while(div > 0)
201                 {
202                         div /= 2;
203                         cmp = _CompareClientPtrs(&ret, &gIPC_Clients[pos]);
204 //                      _SysDebug("Checking against %i gives %i", pos, cmp);
205                         if(cmp == 0)    break;
206                         if(cmp < 0)
207                                 pos -= div;
208                         else
209                                 pos += div;
210                 }
211                 
212                 // - Return if found    
213                 if(cmp == 0)
214                         return gIPC_Clients[pos];
215         
216                 // Adjust pos to be the index where the new client will be placed
217                 if(cmp > 0)     pos ++;
218         }
219
220
221         // - Create a new client entry
222         ident_size = IPCType->GetIdentSize(Ident);
223 //      _SysDebug("ident_size = %i", ident_size);
224         ret = malloc( sizeof(tIPC_Client) + ident_size );
225         if(!ret)        return NULL;
226         ret->IPCType = IPCType;
227         ret->Ident = ret + 1;   // Get the end of the structure
228         memcpy( (void*)ret->Ident, Ident, ident_size );
229         ret->nWindows = 0;
230         ret->Windows = NULL;
231         
232         // TODO: Register some way of detecting the client disconnecting
233         //       > Wait on the thread / register with kernel somehow
234         //       > Sockets are easier, but UDP is harder. Might get rid of it
235
236         // - Insert
237         giIPC_ClientCount ++;
238         gIPC_Clients = realloc(gIPC_Clients, giIPC_ClientCount*sizeof(tIPC_Client*));
239         memmove(&gIPC_Clients[pos+1], &gIPC_Clients[pos], (giIPC_ClientCount-pos-1) * sizeof(tIPC_Client*));
240         gIPC_Clients[pos] = ret;
241
242         return ret;
243 }
244
245 tWindow *IPC_int_GetWindow(tIPC_Client *Client, uint32_t WindowID)
246 {
247         if( WindowID == -1 )
248                 return NULL;
249
250         if( WindowID >= Client->nWindows ) {
251                 return NULL;
252         }
253
254         return Client->Windows[WindowID];
255 }
256
257 void IPC_int_SetWindow(tIPC_Client *Client, uint32_t WindowID, tWindow *WindowPtr)
258 {
259         if( WindowID >= MAX_WINDOWS_PER_APP )
260                 return ;
261
262         if( WindowID >= Client->nWindows )
263         {
264                  int    oldCount = Client->nWindows;
265                 Client->nWindows = WindowID + 1;
266                 Client->Windows = realloc(Client->Windows, Client->nWindows*sizeof(tWindow*));
267                 memset( &Client->Windows[oldCount],  0, (Client->nWindows-oldCount)*sizeof(tWindow*) );
268                 _SysDebug("Expanded %p's window list from %i to %i", Client, oldCount, Client->nWindows);
269         }
270
271         _SysDebug("Assigned %p to window %i for %p", WindowPtr, WindowID, Client);      
272         Client->Windows[WindowID] = WindowPtr;
273 }
274
275 // --- IPC Message Handlers ---
276 int IPC_Msg_Ping(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
277 {
278         ASSERT(Msg->ID == IPCMSG_PING);
279         
280         if( !(Msg->Flags & IPCMSG_FLAG_RETURN) )        return 0;
281         
282         if( Msg->Size < 4 )     return -1;
283         
284         tIPCMsg_ReturnInt       *ret = (void*)Msg->Data;
285         Msg->ID = IPCMSG_PING;
286         Msg->Size = sizeof(*ret);
287         ret->Value = AXWIN_VERSION;
288         Client->IPCType->SendMessage(Client->Ident, sizeof(*Msg)+sizeof(*ret), Msg);
289         return 0;
290 }
291
292 int IPC_Msg_GetDisplayCount(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
293 {
294         tAxWin_IPCMessage       *ret_hdr;
295         tIPCMsg_ReturnInt       *ret;
296         char    buf[sizeof(*ret_hdr)+sizeof(*ret)];
297         
298         ASSERT(Msg->ID == IPCMSG_GETDISPLAYCOUNT);
299
300         if( !(Msg->Flags & IPCMSG_FLAG_RETURN) )        return 0;
301         
302         ret_hdr = (void*)buf;
303         ret_hdr->ID = IPCMSG_GETDISPLAYCOUNT;
304         ret_hdr->Flags = 0;
305         ret_hdr->Window = -1;
306         ret_hdr->Size = sizeof(*ret);
307         ret = (void*)ret_hdr->Data;
308         ret->Value = 1; // HARD CODE - Current version only supports one display
309         
310         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
311         return 0;
312 }
313
314 int IPC_Msg_GetDisplayDims(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
315 {
316         tIPCMsg_GetDisplayDims  *info;
317         tAxWin_IPCMessage       *ret_hdr;
318         tIPCMsg_RetDisplayDims  *ret;
319         char    buf[sizeof(*ret_hdr)+sizeof(*ret)];
320         
321         ASSERT(Msg->ID == IPCMSG_GETDISPLAYDIMS);
322
323         if( !(Msg->Flags & IPCMSG_FLAG_RETURN) )        return 0;
324
325         info = (void*)Msg->Data;        
326
327         ret_hdr = (void*)buf;
328         ret_hdr->ID = IPCMSG_GETDISPLAYDIMS;
329         ret_hdr->Flags = 0;
330         ret_hdr->Window = -1;
331         ret_hdr->Size = sizeof(*ret);
332         ret = (void*)ret_hdr->Data;
333         
334         // HARD CODE! Only one display supported
335         if( info->DisplayID == 0 )
336         {
337                 ret->X = 0;
338                 ret->Y = 0;
339                 ret->W = giScreenWidth;
340                 ret->H = giScreenHeight;
341         }
342         else
343         {
344                 ret->X = 0;     ret->Y = 0;
345                 ret->W = 0;     ret->H = 0;
346         }
347         
348         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
349         return 0;
350 }
351
352 int IPC_Msg_SendMsg(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
353 {
354         tIPCMsg_SendMsg *info = (void*)Msg->Data;
355         tWindow *src, *dest;
356
357         ASSERT(Msg->ID == IPCMSG_SENDMSG);
358         
359         // - Sanity checks
360         if( Msg->Size < sizeof(tIPCMsg_SendMsg) )
361                 return -1;
362         if( Msg->Size < sizeof(tIPCMsg_SendMsg) + info->Length )
363                 return -1;
364         
365         src = IPC_int_GetWindow(Client, Msg->Window);
366         if(!src)        return 1;
367         dest = IPC_int_GetWindow(Client, info->Remote);
368         if(!dest)       return 1;
369
370         WM_SendMessage(src, dest, info->ID, info->Length, info->Data);  
371
372         return 0;
373 }
374
375 int IPC_Msg_CreateWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
376 {
377         tIPCMsg_CreateWin       *info = (void*)Msg->Data;
378         tWindow *newwin, *parent;
379
380         ASSERT(Msg->ID == IPCMSG_CREATEWIN);
381
382         // - Sanity checks
383         //  > +1 is for NULL byte on string
384         if( Msg->Size < sizeof(*info) + 1 ) {
385                 _SysDebug("IPC_Msg_CreateWin: Size check 1 failed");
386                 return -1;
387         }
388         if( info->Renderer[Msg->Size - sizeof(*info) - 1] != '\0' ) {
389                 _SysDebug("IPC_Msg_CreateWin: Size check 2 failed");
390                 _SysDebug("info = {");
391                 _SysDebug("  .NewWinID = %i", info->NewWinID);
392                 _SysDebug("  .RendererArg = %i", info->RendererArg);
393                 _SysDebug("  .Renderer = '%.*s'", Msg->Size - sizeof(*info), info->Renderer);
394                 _SysDebug("}");
395                 return -1;
396         }
397         
398         // - Get the parent window ID
399         parent = IPC_int_GetWindow(Client, Msg->Window);
400
401         // Catch creating a window with an existing ID
402         if( IPC_int_GetWindow(Client, info->NewWinID) )
403                 return 1;
404
405         // - Create the new window, and save its pointer
406         newwin = WM_CreateWindow(parent, Client, info->NewWinID, info->RendererArg, info->Renderer);
407         IPC_int_SetWindow(Client, info->NewWinID, newwin);
408
409         return 0;
410 }
411
412 int IPC_Msg_DestroyWin(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
413 {
414         tWindow *win;
415         
416         ASSERT(Msg->ID == IPCMSG_DESTROYWIN);
417
418         win = IPC_int_GetWindow(Client, Msg->Window);
419         if( !win )
420                 return 0;
421         
422         WM_DestroyWindow(win);
423         return 0;
424 }
425
426 int IPC_Msg_SetWindowTitle(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
427 {
428         tWindow *win;
429
430         ASSERT(Msg->ID == IPCMSG_SETWINTITLE);
431         
432         if( Msg->Size < 1 )     return -1;
433         if( Msg->Data[ Msg->Size-1 ] != '\0' )  return -1;      
434
435         win = IPC_int_GetWindow(Client, Msg->Window);
436         if(!win)        return 1;
437
438         WM_SetWindowTitle(win, Msg->Data);
439
440         return 0;
441 }
442
443 int IPC_Msg_ShowWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
444 {
445         tIPCMsg_Boolean *info = (void*)Msg->Data;
446         tWindow *win;
447         
448         ASSERT(Msg->ID == IPCMSG_SHOWWINDOW);
449         
450         if( Msg->Size < sizeof(*info) ) return -1;
451         
452         win = IPC_int_GetWindow(Client, Msg->Window);
453         if(!win)        return 1;
454
455         WM_ShowWindow(win, !!info->Value);
456         
457         return 0;
458 }
459
460 int IPC_Msg_DecorateWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
461 {
462         tIPCMsg_Boolean *info = (void*)Msg->Data;
463         tWindow *win;
464         
465         if( Msg->Size < sizeof(*info) ) return -1;
466         
467         win = IPC_int_GetWindow(Client, Msg->Window);
468         if(!win)        return 1;
469         
470         WM_DecorateWindow(win, !!info->Value);
471         return 0;
472 }
473
474 int IPC_Msg_FocusWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
475 {
476         tWindow *win;
477
478         ASSERT(Msg->ID == IPCMSG_FOCUSWINDOW);
479         
480         // Don't allow the focus to be changed unless the client has the focus
481 //      if(!gpWM_FocusedWindow) return 1;
482 //      if(gpWM_FocusedWindow->Client != Client)        return 1;
483
484         win = IPC_int_GetWindow(Client, Msg->Window);
485         if(!win)        return 1;
486
487         WM_FocusWindow(win);
488
489         return 0;
490 }
491
492 int IPC_Msg_SetWinPos(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
493 {
494         tIPCMsg_SetWindowPos    *info = (void*)Msg->Data;
495         tWindow *win;
496         
497         ASSERT(Msg->ID == IPCMSG_SETWINPOS);
498         
499         if(Msg->Size < sizeof(*info))   return -1;
500         
501         win = IPC_int_GetWindow(Client, Msg->Window);
502         if(!win)        return 1;
503         
504         _SysDebug("info = {..., bSetPos=%i,bSetDims=%i}", info->bSetPos, info->bSetDims);
505         
506         if(info->bSetPos)
507                 WM_MoveWindow(win, info->X, info->Y);
508         if(info->bSetDims)
509                 WM_ResizeWindow(win, info->W, info->H);
510         
511         return 0;
512 }
513
514 int IPC_Msg_RegisterAction(tIPC_Client *Client, tAxWin_IPCMessage *Msg)
515 {
516         tIPCMsg_RegAction       *info = (void*)Msg->Data;
517         tWindow *win;
518         
519         ASSERT(Msg->ID == IPCMSG_REGACTION);
520
521         if( Msg->Size < sizeof(*info) + 1 )
522                 return -1;
523         
524         win = IPC_int_GetWindow(Client, Msg->Window);
525         if(!win)        return 1;
526
527         if( strnlen(info->Action, Msg->Size - sizeof(*info)) == Msg->Size - sizeof(*info) )
528                 return 1;
529
530         _SysDebug("RegisterAction %p:%i [%i]\"%s\"",
531                 Client, Msg->Window, info->Index, info->Action
532                 );
533
534         WM_Hotkey_RegisterAction(info->Action, win, info->Index);
535
536         return 0;
537 }
538
539 int (*gIPC_MessageHandlers[])(tIPC_Client *Client, tAxWin_IPCMessage *Msg) = {
540         IPC_Msg_Ping,
541         IPC_Msg_GetDisplayCount,
542         IPC_Msg_GetDisplayDims,
543         IPC_Msg_SendMsg,
544         IPC_Msg_CreateWin,
545         IPC_Msg_DestroyWin,     // Destroy window
546         IPC_Msg_SetWindowTitle,
547         IPC_Msg_ShowWindow,
548         IPC_Msg_DecorateWindow,
549         IPC_Msg_FocusWindow,
550         IPC_Msg_SetWinPos,
551         IPC_Msg_RegisterAction
552 };
553 const int giIPC_NumMessageHandlers = sizeof(gIPC_MessageHandlers)/sizeof(gIPC_MessageHandlers[0]);
554
555 void IPC_Handle(const tIPC_Type *IPCType, const void *Ident, size_t MsgLen, tAxWin_IPCMessage *Msg)
556 {
557         tIPC_Client     *client;
558          int    rv = 0;
559         
560 //      _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)",
561 //              IPCType, Ident, MsgLen, Msg);
562         
563         if( MsgLen < sizeof(tAxWin_IPCMessage) )
564                 return ;
565         if( MsgLen < sizeof(tAxWin_IPCMessage) + Msg->Size )
566                 return ;
567         
568         client = IPC_int_GetClient(IPCType, Ident);
569         if( !client ) {
570                 // Oops?
571         }
572         
573         if( Msg->Flags & IPCMSG_FLAG_RENDERER )
574         {
575                 tWindow *win = IPC_int_GetWindow(client, Msg->Window);
576                 if( !win ) {
577                         _SysDebug("WARNING: NULL window in message %i", Msg->ID);
578                         return ;
579                 }
580                 tWMRenderer     *renderer = win->Renderer;
581                 if( Msg->ID >= renderer->nIPCHandlers ) {
582                         _SysDebug("WARNING: Message %i out of range in %s", Msg->ID, renderer->Name);
583                         return ;
584                 }
585                 if( !renderer->IPCHandlers[Msg->ID] ) {
586                         _SysDebug("WARNING: Message %i has no handler in %s", Msg->ID, renderer->Name);
587                         return ;
588                 }
589                 _SysDebug("IPC_Handle: Call %s-%i", renderer->Name, Msg->ID);
590                 rv = renderer->IPCHandlers[Msg->ID](win, Msg->Size, Msg->Data);
591                 if( rv )
592                         _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
593         }
594         else
595         {
596                 if( Msg->ID >= giIPC_NumMessageHandlers ) {
597                         fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
598                         _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, IPCType);
599                         return ;
600                 }
601                 
602                 if( !gIPC_MessageHandlers[ Msg->ID ] ) {
603                         fprintf(stderr, "WARNING: Message %i does not have a handler\n", Msg->ID);
604                         _SysDebug("WARNING: Message %i does not have a handler", Msg->ID);
605                         return ;
606                 }
607         
608                 _SysDebug("IPC_Handle: Call WM-%i", Msg->ID);
609                 rv = gIPC_MessageHandlers[Msg->ID](client, Msg);
610                 if( rv )
611                         _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
612         }
613 }
614
615 // Dispatch a message to the client
616 void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int MsgID, int Len, void *Data)
617 {
618         tAxWin_IPCMessage       *hdr;
619         tIPCMsg_SendMsg         *msg;
620         char    buf[sizeof(*hdr)+sizeof(*msg)+Len];
621         
622         hdr = (void*)buf;
623         msg = (void*)hdr->Data;
624         
625         hdr->ID = IPCMSG_SENDMSG;
626         hdr->Flags = 0;
627         hdr->Size = sizeof(*msg) + Len;
628         hdr->Window = Dst;
629         
630         msg->Remote = Src;
631         msg->ID = MsgID;
632         msg->Length = Len;
633         memcpy(msg->Data, Data, Len);
634         
635         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
636 }
637
638 // --- Server->Client replies
639 void IPC_SendReply(tIPC_Client *Client, uint32_t WinID, int MsgID, size_t Len, const void *Data)
640 {
641         tAxWin_IPCMessage       *hdr;
642         char    buf[sizeof(*hdr)+Len];
643         
644         hdr = (void*)buf;
645         
646         hdr->ID = MsgID;
647         hdr->Flags = IPCMSG_FLAG_RENDERER;
648         hdr->Size = Len;
649         hdr->Window = WinID;
650         
651         memcpy(hdr->Data, Data, Len);
652         Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
653 }
654

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