+void HandleMessage_FillRect(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("_FillRect: (%i (%i,%i) %ix%i %06x)", win_id, x, y, w, h, colour);
+
+ CWindow* win = client.GetWindow(win_id);
+ if(!win) {
+ throw IPC::CClientFailure("_FillRect: Bad window");
+ }
+
+ while(h -- ) {
+ win->FillScanline(y++, x, w, colour);
+ }
+}
+
+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);
+ }
+}
+
+typedef void MessageHandler_op_t(CClient& client, CDeserialiser& message);
+
+MessageHandler_op_t *message_handlers[] = {
+ [IPCMSG_NULL] = &HandleMessage_Nop,
+ [IPCMSG_REPLY] = &HandleMessage_Reply,
+ [IPCMSG_PING] = &HandleMessage_Ping,
+ [IPCMSG_GETGLOBAL] = &HandleMessage_GetGlobalAttr,
+ [IPCMSG_SETGLOBAL] = &HandleMessage_SetGlobalAttr,
+
+ [IPCMSG_CREATEWIN] = &HandleMessage_CreateWindow,
+ [IPCMSG_CLOSEWIN] = &HandleMessage_DestroyWindow,
+ [IPCMSG_SETWINATTR] = &HandleMessage_SetWindowAttr,
+ [IPCMSG_GETWINATTR] = &HandleMessage_GetWindowAttr,
+ [IPCMSG_SENDIPC] = &HandleMessage_SendIPC, // Use the GUI server for low-bandwith IPC
+ [IPCMSG_GETWINBUF] = &HandleMessage_GetWindowBuffer,
+ [IPCMSG_DAMAGERECT] = &HandleMessage_DamageRect,
+ [IPCMSG_PUSHDATA] = &HandleMessage_PushData, // to a window's buffer
+ [IPCMSG_BLIT] = &HandleMessage_Blit, // Copy data from one part of the window to another
+ [IPCMSG_DRAWCTL] = &HandleMessage_DrawCtl, // Draw a control
+ [IPCMSG_DRAWTEXT] = &HandleMessage_DrawText, // Draw text
+ [IPCMSG_FILLRECT] = &HandleMessage_FillRect, // Fill a rectangle
+ [IPCMSG_DRAWRECT] = &HandleMessage_DrawRect, // Draw (outline) a rectangle
+};
+
+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);
+}
+
+CClientFailure::CClientFailure(std::string&& what):
+ m_what(what)
+{
+}
+const char *CClientFailure::what() const throw()
+{
+ return m_what.c_str();
+}
+CClientFailure::~CClientFailure() throw()