From d5bf0bbc847763c7b27f2a095606c802dedf25c9 Mon Sep 17 00:00:00 2001
From: Kazuki Sakamoto <sakamoto@splhack.org>
Date: Fri, 26 Jun 2009 06:32:14 +0900
Subject: [PATCH] implemented netbeans_intg

---
 src/MacVim/MMBackend.h   |    5 +++
 src/MacVim/MMBackend.m   |   49 +++++++++++++++++++++++++++++++
 src/MacVim/MacVim.h      |    1 +
 src/MacVim/MacVim.m      |    1 +
 src/MacVim/gui_macvim.m  |   28 ++++++++++++++++++
 src/feature.h            |    3 +-
 src/netbeans.c           |   72 ++++++++++++++++++++++++++++++++++++++++++---
 src/proto/gui_macvim.pro |    3 ++
 src/proto/netbeans.pro   |    1 +
 9 files changed, 157 insertions(+), 6 deletions(-)

diff --git a/src/MacVim/MMBackend.h b/src/MacVim/MMBackend.h
index 3fa4c96..d26d0d0 100644
--- a/src/MacVim/MMBackend.h
+++ b/src/MacVim/MMBackend.h
@@ -50,6 +50,8 @@
     unsigned            numWholeLineChanges;
     unsigned            offsetForDrawDataPrune;
     BOOL                imState;
+    CFSocketRef         netbeansSocket;
+    CFRunLoopSourceRef  netbeansRunLoopSource;
 }
 
 + (MMBackend *)sharedInstance;
@@ -135,6 +137,9 @@
 - (BOOL)imState;
 - (void)setImState:(BOOL)activated;
 
+- (void)messageFromNetbeans;
+- (void)setNetbeansSocket:(int)socket;
+
 @end
 
 
diff --git a/src/MacVim/MMBackend.m b/src/MacVim/MMBackend.m
index d3b3fea..3e61c49 100644
--- a/src/MacVim/MMBackend.m
+++ b/src/MacVim/MMBackend.m
@@ -1472,6 +1472,51 @@ extern GuiFont gui_mch_retain_font(GuiFont font);
     imState = activated;
 }
 
+static void netbeansReadCallback(CFSocketRef s,
+    CFSocketCallBackType callbackType,
+    CFDataRef address, const void *data, void *info)
+{
+    // NetBeans socket is readable.
+    [[MMBackend sharedInstance] messageFromNetbeans];
+}
+
+- (void)messageFromNetbeans
+{
+    [inputQueue addObject:[NSNumber numberWithInt:NetBeansMsgID]];
+    [inputQueue addObject:[NSNull null]];
+}
+
+- (void)setNetbeansSocket:(int)socket
+{
+    // Tell CFRunLoop that we are interested in NetBeans socket input.
+
+    if (socket == -1) {
+        if (netbeansSocket == NULL) {
+            //NSLog(@"double unset NetBeans socket");
+            return;
+        }
+
+        CFRunLoopSourceInvalidate(netbeansRunLoopSource);
+        CFRelease(netbeansRunLoopSource);
+        CFRelease(netbeansSocket);
+        netbeansRunLoopSource = NULL;
+        netbeansSocket = NULL;
+    } else {
+        if (netbeansSocket != NULL) {
+            //NSLog(@"double set NetBeans socket");
+            return;
+        }
+
+        netbeansSocket = CFSocketCreateWithNative(
+            kCFAllocatorDefault, socket, kCFSocketReadCallBack,
+                &netbeansReadCallback, NULL);
+        netbeansRunLoopSource =
+            CFSocketCreateRunLoopSource(NULL, netbeansSocket, 0);
+        CFRunLoopAddSource(CFRunLoopGetCurrent(),
+            netbeansRunLoopSource, kCFRunLoopCommonModes);
+    }
+}
+
 @end // MMBackend
 
 
@@ -1798,6 +1843,10 @@ extern GuiFont gui_mch_retain_font(GuiFont font);
         [self setImState:YES];
     } else if (DeactivatedImMsgID == msgid) {
         [self setImState:NO];
+    } else if (NetBeansMsgID == msgid) {
+#ifdef FEAT_NETBEANS_INTG
+        messageFromNetbeansMacVim();
+#endif
     } else {
         NSLog(@"WARNING: Unknown message received (msgid=%d)", msgid);
     }
diff --git a/src/MacVim/MacVim.h b/src/MacVim/MacVim.h
index 359803d..895b4b9 100644
--- a/src/MacVim/MacVim.h
+++ b/src/MacVim/MacVim.h
@@ -177,6 +177,7 @@ enum {
     DeactivatedImMsgID,
     BrowseForFileMsgID,
     ShowDialogMsgID,
+    NetBeansMsgID,
     LastMsgID   // NOTE: MUST BE LAST MESSAGE IN ENUM!
 };
 
diff --git a/src/MacVim/MacVim.m b/src/MacVim/MacVim.m
index a7c586b..058ce66 100644
--- a/src/MacVim/MacVim.m
+++ b/src/MacVim/MacVim.m
@@ -92,6 +92,7 @@ char *MessageStrings[] =
     "DeactivatedImMsgID",
     "BrowseForFileMsgID",
     "ShowDialogMsgID",
+    "NetBeansMsgID",
     "END OF MESSAGE IDs"     // NOTE: Must be last!
 };
 
diff --git a/src/MacVim/gui_macvim.m b/src/MacVim/gui_macvim.m
index fb0f6c3..91ad785 100644
--- a/src/MacVim/gui_macvim.m
+++ b/src/MacVim/gui_macvim.m
@@ -74,6 +74,19 @@ gui_mch_prepare(int *argc, char **argv)
             break;
         }
     }
+
+#ifdef FEAT_NETBEANS_INTG
+    for (i = 0; i < *argc; ++i) {
+        if (strncmp(argv[i], "-nb", 3) == 0) {
+            usingNetbeans++;
+            netbeansArg = argv[i];
+            --*argc;
+            if (*argc > i)
+                mch_memmove(&argv[i], &argv[i+1], (*argc-i) * sizeof(char*));
+            break;
+        }
+    }
+#endif
 }
 
 
@@ -2180,3 +2193,18 @@ static int vimModMaskToEventModifierFlags(int mods)
 
     return flags;
 }
+
+
+
+// -- NetBeans Support ------------------------------------------------------
+
+#ifdef FEAT_NETBEANS_INTG
+
+/* Set NetBeans socket to CFRunLoop */
+    void
+gui_macvim_set_netbeans_socket(int socket)
+{
+    [[MMBackend sharedInstance] setNetbeansSocket:socket];
+}
+
+#endif // FEAT_NETBEANS_INTG
diff --git a/src/feature.h b/src/feature.h
index 1854b67..ca8cc35 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -1203,7 +1203,8 @@
  * The Netbeans features currently only work with Motif and GTK and Win32.
  * It also requires +listcmds and +eval.
  */
-#if ((!defined(FEAT_GUI_MOTIF) && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_W32)) \
+#if ((!defined(FEAT_GUI_MOTIF) && !defined(FEAT_GUI_GTK) \
+		&& !defined(FEAT_GUI_W32) && !defined(FEAT_GUI_MACVIM)) \
 		|| !defined(FEAT_LISTCMDS) || !defined(FEAT_EVAL)) \
 	&& defined(FEAT_NETBEANS_INTG)
 # undef FEAT_NETBEANS_INTG
diff --git a/src/netbeans.c b/src/netbeans.c
index fe3a70c..47ca2fa 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -118,6 +118,10 @@ static void netbeans_gtk_connect __ARGS((void));
 #ifdef FEAT_GUI_W32
 static void netbeans_w32_connect __ARGS((void));
 #endif
+#ifdef FEAT_GUI_MACVIM
+static void netbeans_macvim_connect __ARGS((void));
+static int sock_select(int s);
+#endif
 
 static int dosetvisible = FALSE;
 
@@ -225,6 +229,50 @@ netbeans_disconnect(void)
 }
 #endif /* FEAT_GUI_W32 */
 
+#if defined(FEAT_GUI_MACVIM) || defined(PROTO)
+    static void
+netbeans_macvim_connect(void)
+{
+    netbeans_connect();
+    if (sd > 0)
+    {
+	/*
+	 * Tell Core Foundation we are interested in being called when there
+	 * is input on the editor connection socket
+	 */
+	gui_macvim_set_netbeans_socket(sd);
+    }
+}
+
+    static void
+netbeans_disconnect(void)
+{
+    if (sd != -1)
+    {
+	sd = -1;
+	gui_macvim_set_netbeans_socket(sd);
+    }
+    haveConnection = FALSE;
+# ifdef FEAT_BEVAL
+    bevalServers &= ~BEVAL_NETBEANS;
+# endif
+}
+
+    static int
+sock_select(int s)
+{
+    fd_set readset;
+    struct timeval timeout;
+
+    FD_ZERO(&readset);
+    FD_SET(s, &readset);
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 0;
+
+    return select(s + 1, &readset, NULL, NULL, &timeout);
+}
+#endif /* FEAT_GUI_MACVIM */
+
 #define NB_DEF_HOST "localhost"
 #define NB_DEF_ADDR "3219"
 #define NB_DEF_PASS "changeme"
@@ -705,19 +753,22 @@ netbeans_parse_messages(void)
 /* Use this one when generating prototypes, the others are static. */
     void
 messageFromNetbeansW32()
-#else
-# ifdef FEAT_GUI_MOTIF
+#endif
+#ifdef FEAT_GUI_MOTIF
     static void
 messageFromNetbeans(XtPointer clientData UNUSED,
 		    int *unused1 UNUSED,
 		    XtInputId *unused2 UNUSED)
-# endif
-# ifdef FEAT_GUI_GTK
+#endif
+#ifdef FEAT_GUI_GTK
     static void
 messageFromNetbeans(gpointer clientData UNUSED,
 		    gint unused1 UNUSED,
 		    GdkInputCondition unused2 UNUSED)
-# endif
+#endif
+#if defined(FEAT_GUI_MACVIM) || defined(PROTO)
+    void
+messageFromNetbeansMacVim()
 #endif
 {
     static char_u	*buf = NULL;
@@ -733,6 +784,13 @@ messageFromNetbeans(gpointer clientData UNUSED,
 	return;
     }
 
+#ifdef FEAT_GUI_MACVIM
+    /* It may happen that socket is not readable because socket has been already
+     * read by timing of CFRunLoop callback. So check socket using select. */
+    if (sock_select(sd) <= 0)
+	return;
+#endif
+
 #ifndef FEAT_GUI_GTK
     ++level;  /* recursion guard; this will be called from the X event loop */
 #endif
@@ -2806,6 +2864,10 @@ netbeans_startup_done(void)
 # else
 #  ifdef FEAT_GUI_W32
 	netbeans_w32_connect();
+#  else
+#   ifdef FEAT_GUI_MACVIM
+	netbeans_macvim_connect();
+#   endif
 #  endif
 # endif
 #endif
diff --git a/src/proto/gui_macvim.pro b/src/proto/gui_macvim.pro
index d6a7a13..95abf99 100644
--- a/src/proto/gui_macvim.pro
+++ b/src/proto/gui_macvim.pro
@@ -216,3 +216,6 @@ gui_mch_find_dialog(exarg_T *eap);
 gui_mch_replace_dialog(exarg_T *eap);
     void
 im_set_control(int enable);
+
+    void
+gui_macvim_set_netbeans_socket(int socket);
diff --git a/src/proto/netbeans.pro b/src/proto/netbeans.pro
index bb1a1b5..0bf469c 100644
--- a/src/proto/netbeans.pro
+++ b/src/proto/netbeans.pro
@@ -1,6 +1,7 @@
 /* netbeans.c */
 void netbeans_parse_messages __ARGS((void));
 void messageFromNetbeansW32 __ARGS((void));
+void messageFromNetbeansMacVim __ARGS((void));
 int isNetbeansBuffer __ARGS((buf_T *bufp));
 int isNetbeansModified __ARGS((buf_T *bufp));
 void netbeans_end __ARGS((void));
-- 
1.6.0.6

