*/
#include <axwin3/axwin.h>
#include <stdlib.h>
+#include <string.h>
+#include "include/ipc.h"
+#include "include/internal.h"
+
+#define WINDOWS_PER_ALLOC (63)
+
+typedef struct sWindowBlock tWindowBlock;
+
+typedef struct sAxWin3_Window tWindow;
+
+// === STRUCTURES ===
+struct sWindowBlock
+{
+ tWindowBlock *Next;
+ tWindow *Windows[WINDOWS_PER_ALLOC];
+};
+
+// === GLOBALS ===
+ int giAxWin3_LowestFreeWinID;
+ int giAxWin3_HighestUsedWinID;
+tWindowBlock gAxWin3_WindowList;
// === CODE ===
-tHWND AxWin3_CreateWindow(tHWND Parent, const char *Renderer, int Flags)
+tWindow *AxWin3_int_CreateWindowStruct(uint32_t ServerID, int ExtraBytes)
+{
+ tWindow *ret;
+
+ ret = calloc(sizeof(tWindow) + ExtraBytes, 1);
+ ret->ServerID = ServerID;
+
+ return ret;
+}
+
+tHWND AxWin3_CreateWindow(tHWND Parent, const char *Renderer, int Flags, int DataBytes, void **DataPtr)
{
+ tWindow *ret;
+ int newWinID;
int dataSize = sizeof(tIPCMsg_CreateWin) + strlen(Renderer) + 1;
tAxWin_IPCMessage *msg;
tIPCMsg_CreateWin *create_win;
- msg = alloca( sizeof(tAxWin_IPCMessage) + dataSize );
- create_win = msg->Data;
+ // TODO: Validate `Parent`
- msg->ID = IPCMSG_CREATEWIN;
- msg->Flags = 0;
- msg->Window = Parent; // TODO: Validation
- msg->Size = dataSize;
+ // Allocate a window ID
+ {
+ int idx;
+ tWindowBlock *block, *prev;
+ block = &gAxWin3_WindowList;
+ newWinID = giAxWin3_LowestFreeWinID;
+ for( idx = 0; block; newWinID ++ )
+ {
+ if( block->Windows[idx] == NULL )
+ break;
+ idx ++;
+ if(idx == WINDOWS_PER_ALLOC) {
+ prev = block;
+ block = block->Next;
+ idx = 0;
+ }
+ }
+
+ if( !block )
+ {
+ block = calloc(sizeof(tWindowBlock), 1);
+ prev->Next = block;
+ idx = 0;
+ }
+
+ ret = block->Windows[idx] = AxWin3_int_CreateWindowStruct(newWinID, DataBytes);
- create_win->NewWinID = AxWin3_int_AllocateWindowID();
+ if(newWinID > giAxWin3_HighestUsedWinID)
+ giAxWin3_HighestUsedWinID = newWinID;
+ if(newWinID == giAxWin3_LowestFreeWinID)
+ giAxWin3_HighestUsedWinID ++;
+ }
+
+ // Create message
+ msg = AxWin3_int_AllocateIPCMessage(Parent, IPCMSG_CREATEWIN, 0, dataSize);
+ create_win = (void*)msg->Data;
+ create_win->NewWinID = newWinID;
create_win->Flags = Flags;
strcpy(create_win->Renderer, Renderer);
- return NULL;
+ // Send and clean up
+ AxWin3_int_SendIPCMessage(msg);
+ free(msg);
+
+ // TODO: Detect errors in AxWin3_CreateWindow
+
+ // Return success
+ if(DataPtr) *DataPtr = ret->Data;
+ return ret;
}
void AxWin3_DestroyWindow(tHWND Window)
#ifndef _AXWIN3_AXWIN_H_
#define _AXWIN3_AXWIN_H_
-typedef void *tHWND;
+typedef struct sAxWin3_Window *tHWND;
typedef void (*tAxWin3_MessageCallback)(int SourceTID, int Length);
+typedef int (*tAxWin3_WindowMessageHandler)(tHWND Window, int Length, void *Data);
+
extern void AxWin3_Connect(const char *ServerDesc);
extern tAxWin3_MessageCallback AxWin3_SetMessageCallback(tAxWin3_MessageCallback Callback);
-extern tHWND AxWin3_CreateWindow(tHWND Parent, const char *Renderer, int Flags);
+extern tHWND AxWin3_CreateWindow(tHWND Parent, const char *Renderer, int Flags, int DataBytes, void **DataPtr);
extern void AxWin3_DestroyWindow(tHWND Window);
extern void AxWin3_SendMessage(tHWND Window, int Length, void *Data);