From ef9197f052a147755d76e93dcfc7576a856dfe55 Mon Sep 17 00:00:00 2001
From: Vladimir Ananiev <vovan888 at gmail com>
Date: Sun, 23 Dec 2007 00:51:14 +0300
Subject: [PATCH 10/10] [neuros] add generic MSG interface

Signed-off-by: Vladimir Ananiev <vovan888 at gmail com>
---
 src/include/nano-X.h |   29 +++++++++++++++++++++++++----
 src/nanox/client.c   |   31 +++++++++++++++++++++++++++++++
 src/nanox/nxproto.h  |   11 ++++++++++-
 src/nanox/srvfunc.c  |   43 +++++++++++++++++++++++++++++++++++++++++++
 src/nanox/srvnet.c   |   13 +++++++++++++
 5 files changed, 122 insertions(+), 5 deletions(-)

diff --git a/src/include/nano-X.h b/src/include/nano-X.h
index 2aa8669..da57c30 100644
--- a/src/include/nano-X.h
+++ b/src/include/nano-X.h
@@ -333,6 +333,7 @@ typedef struct {
 #define GR_EVENT_TYPE_SELECTION_CHANGED 20
 #define GR_EVENT_TYPE_TIMER             21
 #define GR_EVENT_TYPE_PORTRAIT_CHANGED  22
+#define GR_EVENT_TYPE_MSG		23
 
 /* Event masks */
 #define	GR_EVENTMASK(n)			(((GR_EVENT_MASK) 1) << (n))
@@ -359,8 +360,9 @@ typedef struct {
 #define GR_EVENT_MASK_CLIENT_DATA_REQ	GR_EVENTMASK(GR_EVENT_TYPE_CLIENT_DATA_REQ)
 #define GR_EVENT_MASK_CLIENT_DATA	GR_EVENTMASK(GR_EVENT_TYPE_CLIENT_DATA)
 #define GR_EVENT_MASK_SELECTION_CHANGED GR_EVENTMASK(GR_EVENT_TYPE_SELECTION_CHANGED)
-#define GR_EVENT_MASK_TIMER             GR_EVENTMASK(GR_EVENT_TYPE_TIMER)
-#define GR_EVENT_MASK_PORTRAIT_CHANGED  GR_EVENTMASK(GR_EVENT_TYPE_PORTRAIT_CHANGED)
+#define GR_EVENT_MASK_TIMER		GR_EVENTMASK(GR_EVENT_TYPE_TIMER)
+#define GR_EVENT_MASK_PORTRAIT_CHANGED	GR_EVENTMASK(GR_EVENT_TYPE_PORTRAIT_CHANGED)
+#define GR_EVENT_MASK_MSG		GR_EVENTMASK(GR_EVENT_TYPE_MSG)
 /* Event mask does not affect GR_EVENT_TYPE_HOTKEY_DOWN and
  * GR_EVENT_TYPE_HOTKEY_UP, hence no masks for those events. */
 
@@ -537,6 +539,25 @@ typedef struct {
 } GR_EVENT_TIMER;
 
 /**
+ * GR_EVENT_TYPE_MSG
+ */
+// MSG_LEN is set to 64 bytes as a reasonable number with follwing factors in 
+// consideration,
+// 1. it accommodates most cases where message does not need to be split.
+// 2. minimize the nano-x server request memory allocation overhead. 
+//    pls note that server allocates EVENT dynamically, and currently GR_EVENT_MSG
+//    dictates the size of the EVENT. With event queue in place, if EVENT is too big,
+//    memory requirement can grow pretty quickly.
+//
+#define NANOX_MAX_MSG_LEN 64
+typedef struct {
+  GR_EVENT_TYPE  type;      /**< event type, GR_EVENT_TYPE_MSG */
+  GR_WINDOW_ID   wid;       /**< ID of window MSG is destined for */
+  int            bytes;     /**< msg length. */
+  unsigned char  msg[NANOX_MAX_MSG_LEN]; /**< msg buffer. */
+} GR_EVENT_MSG;
+
+/**
  * Union of all possible event structures.
  * This is the structure returned by GrGetNextEvent() and similar routines.
  */
@@ -555,6 +576,7 @@ typedef union {
   GR_EVENT_CLIENT_DATA clientdata;	  /**< Client data events */
   GR_EVENT_SELECTION_CHANGED selectionchanged; /**< Selection owner changed */
   GR_EVENT_TIMER timer;                 /**< Timer events */
+  GR_EVENT_MSG msg;             	/**< Generic MSG events. */
 } GR_EVENT;
 
 typedef void (*GR_FNCALLBACKEVENT)(GR_EVENT *);
@@ -916,8 +938,7 @@ void		GrUnregisterInput(int fd);
 void		GrMainLoop(GR_FNCALLBACKEVENT fncb);
 GR_FNCALLBACKEVENT GrSetErrorHandler(GR_FNCALLBACKEVENT fncb);
 void		GrDefaultErrorHandler(GR_EVENT *ep);
-int		GrSnapScreenToImage(const char *path,GR_COORD x, GR_COORD y, 
-					GR_SIZE width,	GR_SIZE height);
+int		GrSendMsg(GR_WINDOW_ID wid, void * msg, int bytes);
 
 /* passive library entry points - available with client/server only*/
 void		GrPrepareSelect(int *maxfd,void *rfdset);
diff --git a/src/nanox/client.c b/src/nanox/client.c
index 80360b4..e7b7605 100644
--- a/src/nanox/client.c
+++ b/src/nanox/client.c
@@ -4868,3 +4868,34 @@ GrSnapScreenToImage(const char *path,GR_COORD x, GR_COORD y,
 	UNLOCK(&nxGlobalLock);
 	return ret;
 }
+
+/** 
+ * Delivers generic message to given window.
+ *
+ * @param wid    target window ID.
+ * @param msg    msg pointer.
+ * @param bytes  msg length in bytes.
+ * @return
+ *              0 if successful, otherwise -1.
+ */
+int
+GrSendMsg(GR_WINDOW_ID wid, void * msg, int bytes)
+{
+	int ret;
+	nxSendMsgReq *req;
+
+	// msg can not be longer than NANOX_MAX_MSG_LEN, see nano-X.h
+	if (bytes > NANOX_MAX_MSG_LEN || bytes < 0 || wid == -1) return -1;
+
+	LOCK(&nxGlobalLock);
+	req = AllocReqExtra(SendMsg, bytes);
+	req->wid = wid;
+	req->bytes = bytes;
+	memcpy(GetReqData(req), msg, bytes);
+
+	if (TypedReadBlock(&ret, sizeof(ret), GrNumSendMsg) == -1)
+		ret = -1;
+
+	UNLOCK(&nxGlobalLock);
+	return ret;
+}
diff --git a/src/nanox/nxproto.h b/src/nanox/nxproto.h
index a4bc274..0af6ef2 100644
--- a/src/nanox/nxproto.h
+++ b/src/nanox/nxproto.h
@@ -1395,5 +1395,14 @@ typedef struct {
 	UINT16  height;
 } nxSnapScreenToImageReq;
 
+#define GrNumSendMsg            127
+typedef struct {
+	BYTE8 reqType;
+	BYTE8 hilength;
+	UINT16 length;
+	IDTYPE wid;
+	UINT32 bytes;
+} nxSendMsgReq;
+
 
-#define GrTotalNumCalls         127
+#define GrTotalNumCalls         128
diff --git a/src/nanox/srvfunc.c b/src/nanox/srvfunc.c
index 1a780cd..0747e7d 100644
--- a/src/nanox/srvfunc.c
+++ b/src/nanox/srvfunc.c
@@ -4347,3 +4347,46 @@ GrSnapScreenToImage(const char *path,GR_COORD x, GR_COORD y,
 	SERVER_UNLOCK();
 	return ret;
 }
+
+/*
+ * Sends generic message to target wid.
+ * return 0 if successful, otherwise -1.
+ */
+int
+GrSendMsg(GR_WINDOW_ID wid, void * msg, int bytes)
+{
+	GR_WINDOW *wp;
+	GR_EVENT_MSG *emp;		/* general msg event */
+	GR_EVENT_CLIENT	*ecp;	/* current event client */
+	int ret = -1;
+
+	SERVER_LOCK();
+
+	if (!(wp = GsFindWindow(wid))) {
+		//mask "GsError", because it can lead nano-x to exit, and application will be exit too.
+		//GsError(GR_ERROR_BAD_WINDOW_ID, wid);
+		DPRINTF("nano-X: ERROR (Bad window id: %d) !\n,",wid);
+		goto bail;
+	}
+
+	// deliver msg to all clients.
+	for (ecp = wp->eventclients; ecp; ecp = ecp->next) {
+		if ((ecp->eventmask & GR_EVENT_MASK_MSG) == 0)
+			continue;
+		
+		emp = (GR_EVENT_MSG *) GsAllocEvent(ecp->client);
+		if (emp == NULL)
+			continue;
+			
+		emp->type = GR_EVENT_TYPE_MSG;
+		emp->wid = wid;
+		emp->bytes = bytes;
+		memcpy(emp->msg, msg, bytes);
+		ret = 0;
+	}
+
+ bail:
+	SERVER_UNLOCK();
+	return ret;
+}
+
diff --git a/src/nanox/srvnet.c b/src/nanox/srvnet.c
index 2b85853..69200a6 100644
--- a/src/nanox/srvnet.c
+++ b/src/nanox/srvnet.c
@@ -1616,6 +1616,18 @@ GrSnapScreenToImageWrapper(void *r)
 
 }
 
+static void
+GrSendMsgWrapper(void *r)
+{
+	nxSendMsgReq *req = r;
+	int ret;
+
+	ret = GrSendMsg(req->wid, GetReqData(req), req->bytes);
+
+ 	GsWriteType(current_fd, GrNumSendMsg);
+	GsWrite(current_fd, &ret, sizeof(ret));
+}
+
 
 void GrShmCmdsFlushWrapper(void *r);
 
@@ -1754,6 +1766,7 @@ static const struct GrFunction GrFunctions[] = {
 	/* 124 */ {GrCopyFontWrapper, "GrCopyFont"},
 	/* 125 */ {GrDrawImagePartToFitWrapper, "GrDrawImagePartToFit"},
 	/* 126 */ {GrSnapScreenToImageWrapper, "GrSnapScreenToImage"},
+	/* 127 */ {GrSendMsgWrapper, "GrSendMsg"},
 };
 
 void
-- 
1.5.1.6

