void HandleMessage_PushData(CClient& client, CDeserialiser& message) { uint16_t win_id = message.ReadU16(); uint16_t x = message.ReadU16(); uint16_t y = message.ReadU16(); uint16_t w = message.ReadU16(); uint16_t h = message.ReadU16(); _SysDebug("_PushData: (%i, (%i,%i) %ix%i)", win_id, x, y, w, h); CWindow* win = client.GetWindow(win_id); if(!win) { throw IPC::CClientFailure("_PushData: Bad window"); } for( unsigned int row = 0; row < h; row ++ ) { const ::std::vector<uint8_t> scanline_data = message.ReadBuffer(); if( scanline_data.size() != w * 4 ) { _SysDebug("ERROR _PushData: Scanline buffer size mismatch (%i,%i)", scanline_data.size(), w*4); continue ; } win->DrawScanline(y+row, x, w, scanline_data.data()); } }
void IPC_int_DropClient(tIPC_Client *Client) { // Remove from client list int pos; if( !IPC_int_BSearchClients(Client, &pos) ) { _SysDebug("IPC_int_DropClient: Can't find client %p", Client); return ; } giIPC_ClientCount --; memmove(&gIPC_Clients[pos], &gIPC_Clients[pos+1], (giIPC_ClientCount-pos)*sizeof(tIPC_Client*)); // Terminate client's windows // - If there were active windows, show an error? int nWindowsDestroyed = 0; for(int i = 0; i < Client->nWindows; i ++) { if( Client->Windows[i] ) { _SysDebug("Window %p:%i %p still exists", Client, i, Client->Windows[i]); WM_DestroyWindow(Client->Windows[i]); nWindowsDestroyed ++; } } if( nWindowsDestroyed ) { _SysDebug("TODO: Show notice that application exited without destroying windows"); } // Free client structure free(Client); _SysDebug("Dropped client %p", Client); }
int AxWin3_int_DefaultMessageHandler(tWindow *Win, int ID, size_t Len, const void *Data) { switch(ID) { case WNDMSG_HOTKEY: { const struct sWndMsg_Hotkey *mi = Data; if( Len < sizeof(*mi) ) return -1; if( mi->ID >= MAX_HOTKEYS ) _SysDebug("--- Out of range hotkey %i fired", mi->ID); else if( gAxWin3_Hotkeys[mi->ID] == 0 ) _SysDebug("--- Unmapped hotkey ID %i fired", mi->ID); else gAxWin3_Hotkeys[mi->ID](); } return 1; // Honour a close message by default case WNDMSG_CLOSE: AxWin3_DestroyWindow(Win); return 1; // Zero f***s given? case WNDMSG_DESTROY: _SysDebug("TODO: Check that WNDMSG_DESTROY was from us calling _DestroyWindow"); // TODO: Finalise cleanup of window, this will be the last message sent to this window AxWin3_int_DelWindowByID(Win->ServerID); return 1; default: return 0; } }
void AxWin3_int_SendIPCMessage(tAxWin_IPCMessage *Msg) { int size = sizeof(tAxWin_IPCMessage) + Msg->Size; switch(giConnectionType) { case CONNTYPE_SENDMESSAGE: _SysSendMessage(giConnectionNum, size, Msg); break; case CONNTYPE_UDP: { // Create UDP header char tmpbuf[giAxWin3_int_UDPHeaderLen + size]; memcpy(tmpbuf, gaAxWin3_int_UDPHeader, giAxWin3_int_UDPHeaderLen); memcpy(tmpbuf + giAxWin3_int_UDPHeaderLen, Msg, size); size_t rv = _SysWrite(giConnectionNum, tmpbuf, sizeof(tmpbuf)); if( rv == -1 ) { _SysDebug("AxWin3 SendIPCMessage: UDP Write Failed %s", strerror(errno)); exit(1); } } break; case CONNTYPE_IPCPIPE: case CONNTYPE_TCP: { size_t rv = _SysWrite(giConnectionNum, Msg, size); if( rv != size ) { _SysDebug("AxWin3 SendIPCMessage: Write Failed %s - sent %i want %i", strerror(errno), rv, size); exit(1); } } break; default: break; } }
// -------------------------------------------------------------------- // "Run" Dialog box // -------------------------------------------------------------------- int run_dorun(tAxWin3_Widget *unused) { _SysDebug("DoRun pressed"); char *cmd = AxWin3_Widget_GetText(gRunInput); _SysDebug("Command string '%s'", cmd); // TODO: Parse the command string into components // TODO: Call _SysSpawn AxWin3_ShowWindow(gRunDialog, 0); return 0; }
void IPC_Handle(tIPC_Client *Client, size_t MsgLen, tAxWin_IPCMessage *Msg) { int rv = 0; // _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)", // IPCType, Ident, MsgLen, Msg); if( MsgLen < sizeof(tAxWin_IPCMessage) ) return ; if( MsgLen < sizeof(tAxWin_IPCMessage) + Msg->Size ) return ; if( Msg->Flags & IPCMSG_FLAG_RENDERER ) { tWindow *win = IPC_int_GetWindow(Client, Msg->Window); if( !win ) { _SysDebug("WARNING: NULL window in message %i (%x)", Msg->ID, Msg->Window); return ; } tWMRenderer *renderer = win->Renderer; if( Msg->ID >= renderer->nIPCHandlers ) { _SysDebug("WARNING: Message %i out of range in %s", Msg->ID, renderer->Name); return ; } if( !renderer->IPCHandlers[Msg->ID] ) { _SysDebug("WARNING: Message %i has no handler in %s", Msg->ID, renderer->Name); return ; } _SysDebug("IPC_Handle: Call %s-%i", renderer->Name, Msg->ID); rv = renderer->IPCHandlers[Msg->ID](win, Msg->Size, Msg->Data); if( rv ) _SysDebug("IPC_Handle: rv != 0 (%i)", rv); } else { if( Msg->ID >= giIPC_NumMessageHandlers ) { fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, Client); _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, Client); return ; } if( !gIPC_MessageHandlers[ Msg->ID ] ) { fprintf(stderr, "WARNING: Message %i does not have a handler\n", Msg->ID); _SysDebug("WARNING: Message %i does not have a handler", Msg->ID); return ; } _SysDebug("IPC_Handle: Call WM-%i", Msg->ID); rv = gIPC_MessageHandlers[Msg->ID](Client, Msg); if( rv ) _SysDebug("IPC_Handle: rv != 0 (%i)", rv); } }
bool ACurses_GetDims_SerialTermHack(void) { _SysDebug("ACurses_GetDims_SerialTermHack: Trying"); // Set cursor to 1000,1000 , request cursor position, reset cursor to 0,0 static const char req[] = "\033[1000;1000H\033[6n\033[H"; fflush(stdin); _SysWrite(1, req, sizeof(req)); int64_t timeout = 1000; fd_set fds; FD_ZERO(&fds); FD_SET(0, &fds); _SysSelect(1, &fds, NULL, NULL, &timeout, 0); if( !FD_ISSET(0, &fds) ) return false; if( fgetc(stdin) != '\x1b' ) return false; if( fgetc(stdin) != '[' ) return false; if( fscanf(stdin, "%i;%i", &giTerminal_Width, &giTerminal_Height) != 2 ) return false; if( fgetc(stdin) != 'R' ) return false; return true; }
void HandleMessage_DrawRect(CClient& client, CDeserialiser& message) { uint16_t win_id = message.ReadU16(); uint16_t x = message.ReadU16(); uint16_t y = message.ReadU16(); uint16_t w = message.ReadU16(); uint16_t h = message.ReadU16(); uint32_t colour = message.ReadU32(); _SysDebug("_DrawRect: (%i (%i,%i) %ix%i %06x)", win_id, x, y, w, h, colour); CWindow* win = client.GetWindow(win_id); if(!win) { throw IPC::CClientFailure("_DrawRect: Bad window"); } if(h == 0) { } else if(h == 1) { win->FillScanline(y, x, w, colour); } else if(h == 2) { win->FillScanline(y++, x, w, colour); win->FillScanline(y++, x, w, colour); } else { win->FillScanline(y++, x, w, colour); while( h -- > 2 ) { win->FillScanline(y, x, 1, colour); win->FillScanline(y, x+w-1, 1, colour); y ++; } win->FillScanline(y++, x, w, colour); } }
int IPC_int_BSearchClients(const tIPC_Client *TargetClient, int *Pos) { int div; int cmp = -1; int pos = 0; div = giIPC_ClientCount; pos = div/2; while(div > 0) { div /= 2; _SysDebug("Cmp with %i [%i] (%p)", pos, div, gIPC_Clients[pos]); cmp = _CompareClientPtrs(&TargetClient, &gIPC_Clients[pos]); // _SysDebug("Checking against %i gives %i", pos, cmp); if(cmp == 0) break; if(cmp < 0) pos -= div; else pos += div; } // - Return if found if(cmp == 0) { *Pos = pos; return 1; } // Adjust pos to be the index where the new client will be placed if(cmp > 0) pos ++; *Pos = pos; return 0; }
tHWND AxWin3_CreateWindow( tHWND Parent, const char *Renderer, int RendererArg, int DataBytes, tAxWin3_WindowMessageHandler MessageHandler ) { tWindow *ret; int newWinID; int dataSize = sizeof(tIPCMsg_CreateWin) + strlen(Renderer) + 1; tAxWin_IPCMessage *msg; tIPCMsg_CreateWin *create_win; // Allocate a window ID ret = AxWin3_int_AllocateWindowInfo(DataBytes, &newWinID); if(!ret) return NULL; ret->Handler = MessageHandler; // Create message msg = AxWin3_int_AllocateIPCMessage(Parent, IPCMSG_CREATEWIN, 0, dataSize); create_win = (void*)msg->Data; create_win->NewWinID = newWinID; create_win->RendererArg = RendererArg; strcpy(create_win->Renderer, Renderer); // Send and clean up AxWin3_int_SendIPCMessage(msg); free(msg); _SysDebug("AxWin3_CreateWindow: %i :: '%s'", newWinID, Renderer); // TODO: Detect and handle possible errors // Return success return ret; }
void Display_AddText(int Length, const char *UTF8Text) { _SysDebug("%i '%.*s'", Length, Length, UTF8Text); // Copy as many characters (not bytes, have to trim off the last char) as we can to the current line // - then roll over to the next line while( Length > 0 ) { int space = giDisplayCols - giCurrentCol; int bytes = 0; while( space && bytes < Length ) { uint32_t cp; bytes += ReadUTF8(UTF8Text+bytes, &cp); if( Unicode_IsPrinting(cp) ) { space --; giCurrentCol ++; } } Display_int_PushString(bytes, UTF8Text); UTF8Text += bytes; Length -= bytes; if( Length != 0 ) { // Next line giCurrentLinePos = 0; giCurrentCol = 0; giCurrentLine ++; } } }
int Net_OpenSocket(int AddrType, const void *Addr, const char *Filename) { int addrLen = Net_GetAddressSize(AddrType); char hexAddr[addrLen*2+1]; { const uint8_t *addrBuffer = Addr; for( unsigned int i = 0; i < addrLen; i ++ ) sprintf(hexAddr+i*2, "%02x", addrBuffer[i]); } if(Filename) { int len = snprintf(NULL, 0, "/Devices/ip/routes/@%i:%s/%s", AddrType, hexAddr, Filename); char path[len+1]; snprintf(path, len+1, "/Devices/ip/routes/@%i:%s/%s", AddrType, hexAddr, Filename); _SysDebug("%s", path); return _SysOpen(path, OPENFLAG_READ|OPENFLAG_WRITE); } else { int len = snprintf(NULL, 0, "/Devices/ip/routes/@%i:%s", AddrType, hexAddr); char path[len+1]; snprintf(path, len+1, "/Devices/ip/routes/@%i:%s", AddrType, hexAddr); return _SysOpen(path, OPENFLAG_READ); } }
void IPC_int_SetWindow(tIPC_Client *Client, uint32_t WindowID, tWindow *WindowPtr) { if( WindowID >= MAX_WINDOWS_PER_APP ) return ; if( WindowID >= Client->nWindows ) { int oldCount = Client->nWindows; Client->nWindows = WindowID + 1; Client->Windows = realloc(Client->Windows, Client->nWindows*sizeof(tWindow*)); memset( &Client->Windows[oldCount], 0, (Client->nWindows-oldCount)*sizeof(tWindow*) ); _SysDebug("Expanded %p's window list from %i to %i", Client, oldCount, Client->nWindows); } _SysDebug("Assigned %p to window %i for %p", WindowPtr, WindowID, Client); Client->Windows[WindowID] = WindowPtr; }
// === CODE === int fcntl(int fd, int cmd, ...) { int ret; va_list args; va_start(args, cmd); switch(cmd) { case F_GETFL: { int a_flags = _SysFDFlags(fd, 0, 0); if( a_flags == -1 ) return -1; ret = 0; if(a_flags & OPENFLAG_READ) ret |= O_RDONLY; if(a_flags & OPENFLAG_WRITE) ret |= O_WRONLY; if(a_flags & OPENFLAG_NONBLOCK) ret |= O_NONBLOCK; if(a_flags & OPENFLAG_APPEND) ret |= O_APPEND; // TODO: Extra flags for F_GETFL break; } case F_SETFL: { long p_flags = va_arg(args, long); int a_flags = 0; const int mask = OPENFLAG_NONBLOCK|OPENFLAG_APPEND; if(p_flags & O_NONBLOCK) a_flags |= OPENFLAG_NONBLOCK; if(p_flags & O_APPEND) a_flags |= OPENFLAG_APPEND; // TODO: Extra flags for F_SETFL ret = _SysFDFlags(fd, mask, a_flags); _SysDebug("fcntl(%i, F_SETFL, %li) = %i", fd, p_flags, ret); if(ret != -1) ret = 0; break; } default: _SysDebug("fcntl(%i) unknown or unimplimented", cmd); errno = EINVAL; ret = -1; break; } va_end(args); return ret; }
void HandleOptionRequest(tClient *Client, int Option, bool Value, bool IsRequest) { switch(Option) { default: _SysDebug("Unknown option %i", Option); break; } }
void CClient::HandleMessage(CDeserialiser& message) { try { IPC::HandleMessage(*this, message); if( !message.IsConsumed() ) { _SysDebug("NOTICE - CClient::HandleMessage - Trailing data in message"); } } catch( const ::std::exception& e ) { _SysDebug("ERROR - Exception while processing message from client: %s", e.what()); } catch( ... ) { _SysDebug("ERROR - Unknown exception while processing message from client"); } }
IFontFace& CClient::GetFont(unsigned int id) { static CFontFallback fallback_font; if( id == 0 ) { _SysDebug("GetFont: %i = %p", id, &fallback_font); return fallback_font; } assert(!"TODO: CClient::GetFont id != 0"); }
void CClient::SetWindow(int ID, CWindow* window) { //_SysDebug("SetWindow(ID=%i,window=%p)", ID, window); auto it = m_windows.find(ID); if( it != m_windows.end() ) { _SysDebug("CLIENT BUG: Window ID %i is already used by %p", ID, it->second); } else { m_windows[ID] = window; } }
void HandleMessage(CClient& client, CDeserialiser& message) { const unsigned int num_commands = sizeof(message_handlers)/sizeof(IPC::MessageHandler_op_t*); unsigned int command = message.ReadU8(); if( command >= num_commands ) { // Drop, invalid command _SysDebug("HandleMessage: Command %u is invalid (out of range for %u)", command, num_commands); return ; } (message_handlers[command])(client, message); }
// === CODE === void ACurses_Init(void) { if( ACurses_GetDims_Acess() ) { } else if( ACurses_GetDims_SerialTermHack() ) { } else { _SysDebug("note: assuming 80x25, can't get terminal dimensions"); giTerminal_Width = 80; giTerminal_Height = 25; } }
void AxWin3_int_DelWindowByID(uint32_t ServerID) { int orig_id = ServerID; tWindowBlock *block = &gAxWin3_WindowList; while(block && ServerID > WINDOWS_PER_ALLOC) { block = block->Next; ServerID -= WINDOWS_PER_ALLOC; } if( !block || !block->Windows[ServerID] ) _SysDebug("AxWin3_int_DelWindowByID - Id %i out of range", orig_id); else block->Windows[ServerID] = NULL; }
void AxWin3_int_HandleMessage(tAxWin_IPCMessage *Msg) { tWindow *dest; dest = AxWin3_int_GetWindowFromID(Msg->Window); switch(Msg->ID) { case IPCMSG_SENDMSG: { tIPCMsg_SendMsg *info = (void*)Msg->Data; if(Msg->Size < sizeof(*info) || Msg->Size < sizeof(*info) + info->Length) { _SysDebug("Message is undersized (%i < %i + %i)", Msg->Size < sizeof(*info), info->Length); return ; } if(!dest || !dest->Handler) { _SysDebug("No handler for destination %p", dest); return ; } _SysDebug("IPC Message 0x%x - %i bytes", info->ID, info->Length); if( dest->Handler(dest, info->ID, info->Length, info->Data) ) ; else if( AxWin3_int_DefaultMessageHandler(dest, info->ID, info->Length, info->Data) ) ; else _SysDebug("--- Unhandled SENDMSG 0x%x win %i", info->ID, Msg->Window); break; } case IPCMSG_DESTROYWIN: // Clean up resources associated with this window break; default: _SysDebug("Unknow message ID %i", Msg->ID); break; } free(Msg); }
void Display_Flush(void) { int i; for( i = 0; i < giDisplayCols; i ++ ) { int line = (giFirstLine + i) % giDisplayTotalLines; if( !gabDisplayLinesDirty[line] ) continue; _SysDebug("Line %i+%i '%s'", giFirstLine, i, gasDisplayLines[line]); AxWin3_RichText_SendLine(gMainWindow, giFirstLine + i, gasDisplayLines[line] ); gabDisplayLinesDirty[line] = 0; } AxWin3_RichText_SetCursorPos(gMainWindow, giCurrentLine, giCurrentCol); }
void HandleMessage_DestroyWindow(CClient& client, CDeserialiser& message) { uint16_t win_id = message.ReadU16(); _SysDebug("_DestroyWindow: (%i)", win_id); CWindow* win = client.GetWindow(win_id); if(!win) { throw IPC::CClientFailure("_DestroyWindow: Bad window"); } client.SetWindow(win_id, 0); // TODO: Directly inform compositor? delete win; }
void HandleMessage_SetWindowAttr(CClient& client, CDeserialiser& message) { uint16_t win_id = message.ReadU16(); uint16_t attr_id = message.ReadU16(); _SysDebug("_SetWindowAttr: (Win=%i, ID=%i)", win_id, attr_id); CWindow* win = client.GetWindow(win_id); if(!win) { throw IPC::CClientFailure("_SetWindowAttr - Bad window"); } switch(attr_id) { case IPC_WINATTR_DIMENSIONS: { uint16_t new_w = message.ReadU16(); uint16_t new_h = message.ReadU16(); win->Resize(new_w, new_h); break; } case IPC_WINATTR_POSITION: { int16_t new_x = message.ReadS16(); int16_t new_y = message.ReadS16(); win->Move(new_x, new_y); break; } case IPC_WINATTR_SHOW: win->Show( message.ReadU8() != 0 ); break; case IPC_WINATTR_FLAGS: win->SetFlags( message.ReadU8() ); // TODO: U8? why so small? break; case IPC_WINATTR_TITLE: assert(!"TODO: IPC_WINATTR_TITLE"); break; default: _SysDebug("HandleMessage_SetWindowAttr - Bad attr %u", attr_id); throw IPC::CClientFailure("Bad window attr"); } }
void Display_int_PushString(int Length, const char *Text) { _SysDebug("Line %i += %i '%*C'", giCurrentLine, Length, Length, Text); if( !gasDisplayLines[giCurrentLine] || giCurrentLinePos + Length >= gaiDisplayLineSizes[giCurrentLine] ) { int reqsize = giCurrentLinePos + Length; gaiDisplayLineSizes[giCurrentLine] = (reqsize + 32-1) & ~(32-1); void *tmp = realloc(gasDisplayLines[giCurrentLine], gaiDisplayLineSizes[giCurrentLine]); if( !tmp ) perror("Display_AddText - realloc"); gasDisplayLines[giCurrentLine] = tmp; } memcpy(gasDisplayLines[giCurrentLine]+giCurrentLinePos, Text, Length); gabDisplayLinesDirty[giCurrentLine] = 1; gasDisplayLines[giCurrentLine][giCurrentLinePos+Length] = 0; giCurrentLinePos += Length; }
void RegisterClient(CClient& client) { _SysDebug("RegisterClient(&client=%p)", &client); // allocate a client ID, and save for( int i = 0; i < 100; i ++ ) { uint16_t id = giNextClient++; if(giNextClient == 0) giNextClient = 1; auto r = glClients.insert( ::std::pair<uint16_t,CClient*>(id, &client) ); if( r.second == true ) { client.set_id(id); return; } } // Wut? 100 attempts and fail! assert(!"Todo - Better way of handling client ID reuse"); }
void HandleMessage_GetWindowBuffer(CClient& client, CDeserialiser& message) { uint16_t win_id = message.ReadU16(); _SysDebug("_GetWindowBuffer: (%i)", win_id); CWindow* win = client.GetWindow(win_id); if(!win) { throw IPC::CClientFailure("_PushData: Bad window"); } uint64_t handle = win->m_surface.GetSHMHandle(); CSerialiser reply; reply.WriteU8(IPCMSG_REPLY); reply.WriteU8(IPCMSG_GETWINBUF); reply.WriteU16(win_id); reply.WriteU64(handle); client.SendMessage(reply); }
void HandleMessage_DamageRect(CClient& client, CDeserialiser& message) { uint16_t winid = message.ReadU16(); uint16_t x = message.ReadU16(); uint16_t y = message.ReadU16(); uint16_t w = message.ReadU16(); uint16_t h = message.ReadU16(); _SysDebug("_DamageRect: (%i %i,%i %ix%i)", winid, x, y, w, h); CWindow* win = client.GetWindow(winid); if(!win) { throw IPC::CClientFailure("_PushData: Bad window"); } CRect area(x,y,w,h); win->Repaint(area); }
// === CODE === void AxWin3_Connect(const char *ServerDesc) { if( !ServerDesc ) { ServerDesc = gsAxWin3_int_ServerDesc; } _SysDebug("ServerDesc = %s", ServerDesc); if( !ServerDesc ) { // TODO: Error out return ; } switch(ServerDesc[0]) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': giConnectionType = CONNTYPE_SENDMESSAGE; giConnectionNum = atoi(ServerDesc); if( giConnectionNum == 0 ) { _SysDebug("Invalid server PID"); exit(-1); } break; case 'u': assert( strncmp(ServerDesc, "udp:", 4) == 0 ); ServerDesc += 4; _SysDebug("TODO: UDP connection to '%s'", ServerDesc); // TODO: Open socket and create UDP header break; case 't': assert( strncmp(ServerDesc, "tcp:", 4) == 0 ); ServerDesc += 4; _SysDebug("TODO: TCP connection to '%s'", ServerDesc); // TODO: Open socket break; case 'p': assert( strncmp(ServerDesc, "pipe:", 5) == 0 ); ServerDesc += 5; giConnectionType = CONNTYPE_IPCPIPE; giConnectionNum = _SysOpen(ServerDesc, OPENFLAG_READ|OPENFLAG_WRITE); if( giConnectionNum == -1 ) { _SysDebug("Cannot open IPC Pipe '%s'", ServerDesc); exit(-1); } break; default: _SysDebug("Unknown server desc format '%s'", ServerDesc); exit(-1); break; } }