+++ /dev/null
-/* vi:set ts=8 sts=4 sw=4:
- *
- * if_sniff.c Interface between Vim and SNiFF+
- *
- * See README.txt for an overview of the Vim source code.
- */
-
-#include "vim.h"
-
-#ifdef WIN32
-# include <stdio.h>
-# include <process.h>
-# include <string.h>
-# include <assert.h>
-#else
-# ifdef FEAT_GUI_X11
-# include "gui_x11.pro"
-# endif
-# include "os_unixx.h"
-#endif
-
-static int sniffemacs_pid;
-
-int fd_from_sniff;
-int sniff_connected = 0;
-int sniff_request_waiting = 0;
-int want_sniff_request = 0;
-
-#define MAX_REQUEST_LEN 512
-
-#define NEED_SYMBOL 2
-#define EMPTY_SYMBOL 4
-#define NEED_FILE 8
-#define SILENT 16
-#define DISCONNECT 32
-#define CONNECT 64
-
-#define RQ_NONE 0
-#define RQ_SIMPLE 1
-#define RQ_CONTEXT NEED_FILE + NEED_SYMBOL
-#define RQ_SCONTEXT NEED_FILE + NEED_SYMBOL + EMPTY_SYMBOL
-#define RQ_NOSYMBOL NEED_FILE
-#define RQ_SILENT RQ_NOSYMBOL + SILENT
-#define RQ_CONNECT RQ_NONE + CONNECT
-#define RQ_DISCONNECT RQ_SIMPLE + DISCONNECT
-
-struct sn_cmd
-{
- char *cmd_name;
- char cmd_code;
- char *cmd_msg;
- int cmd_type;
-};
-
-struct sn_cmd_list
-{
- struct sn_cmd* sniff_cmd;
- struct sn_cmd_list* next_cmd;
-};
-
-static struct sn_cmd sniff_cmds[] =
-{
- { "toggle", 'e', N_("Toggle implementation/definition"),RQ_SCONTEXT },
- { "superclass", 's', N_("Show base class of"), RQ_CONTEXT },
- { "overridden", 'm', N_("Show overridden member function"),RQ_SCONTEXT },
- { "retrieve-file", 'r', N_("Retrieve from file"), RQ_CONTEXT },
- { "retrieve-project",'p', N_("Retrieve from project"), RQ_CONTEXT },
- { "retrieve-all-projects",
- 'P', N_("Retrieve from all projects"), RQ_CONTEXT },
- { "retrieve-next", 'R', N_("Retrieve"), RQ_CONTEXT },
- { "goto-symbol", 'g', N_("Show source of"), RQ_CONTEXT },
- { "find-symbol", 'f', N_("Find symbol"), RQ_CONTEXT },
- { "browse-class", 'w', N_("Browse class"), RQ_CONTEXT },
- { "hierarchy", 't', N_("Show class in hierarchy"), RQ_CONTEXT },
- { "restr-hier", 'T', N_("Show class in restricted hierarchy"),RQ_CONTEXT },
- { "xref-to", 'x', N_("Xref refers to"), RQ_CONTEXT },
- { "xref-by", 'X', N_("Xref referred by"), RQ_CONTEXT },
- { "xref-has", 'c', N_("Xref has a"), RQ_CONTEXT },
- { "xref-used-by", 'C', N_("Xref used by"), RQ_CONTEXT },
- { "show-docu", 'd', N_("Show docu of"), RQ_CONTEXT },
- { "gen-docu", 'D', N_("Generate docu for"), RQ_CONTEXT },
- { "connect", 'y', NULL, RQ_CONNECT },
- { "disconnect", 'q', NULL, RQ_DISCONNECT },
- { "font-info", 'z', NULL, RQ_SILENT },
- { "update", 'u', NULL, RQ_SILENT },
- { NULL, '\0', NULL, 0}
-};
-
-
-static char *SniffEmacs[2] = {"sniffemacs", (char *)NULL}; /* Yes, Emacs! */
-static int fd_to_sniff;
-static int sniff_will_disconnect = 0;
-static char msg_sniff_disconnect[] = N_("Cannot connect to SNiFF+. Check environment (sniffemacs must be found in $PATH).\n");
-static char sniff_rq_sep[] = " ";
-static struct sn_cmd_list *sniff_cmd_ext = NULL;
-
-/* Initializing vim commands
- * executed each time vim connects to Sniff
- */
-static char *init_cmds[]= {
- "augroup sniff",
- "autocmd BufWritePost * sniff update",
- "autocmd BufReadPost * sniff font-info",
- "autocmd VimLeave * sniff disconnect",
- "augroup END",
-
- "let g:sniff_connected = 1",
-
- "if ! exists('g:sniff_mappings_sourced')|"
- "if ! exists('g:sniff_mappings')|"
- "if exists('$SNIFF_DIR4')|"
- "let g:sniff_mappings='$SNIFF_DIR4/config/integrations/vim/sniff.vim'|"
- "else|"
- "let g:sniff_mappings='$SNIFF_DIR/config/sniff.vim'|"
- "endif|"
- "endif|"
- "let g:sniff_mappings=expand(g:sniff_mappings)|"
- "if filereadable(g:sniff_mappings)|"
- "execute 'source' g:sniff_mappings|"
- "let g:sniff_mappings_sourced=1|"
- "endif|"
- "endif",
-
- NULL
-};
-
-/*-------- Function Prototypes ----------------------------------*/
-
-static int ConnectToSniffEmacs(void);
-static void sniff_connect(void);
-static void HandleSniffRequest(char* buffer);
-static int get_request(int fd, char *buf, int maxlen);
-static void WriteToSniff(char *str);
-static void SendRequest(struct sn_cmd *command, char* symbol);
-static void vi_msg(char *);
-static void vi_error_msg(char *);
-static char *vi_symbol_under_cursor(void);
-static void vi_open_file(char *);
-static char *vi_buffer_name(void);
-static buf_T *vi_find_buffer(char *);
-static void vi_exec_cmd(char *);
-static void vi_set_cursor_pos(long char_nr);
-static long vi_cursor_pos(void);
-
-/* debug trace */
-#if 0
-static FILE* _tracefile = NULL;
-#define SNIFF_TRACE_OPEN(file) if (!_tracefile) _tracefile = fopen(file, "w")
-#define SNIFF_TRACE(msg) fprintf(_tracefile, msg); fflush(_tracefile);
-#define SNIFF_TRACE1(msg, arg) fprintf(_tracefile, msg,arg); fflush(_tracefile);
-#define SNIFF_TRACE_CLOSE fclose(_tracefile); _tracefile=NULL;
-#else
-#define SNIFF_TRACE_OPEN(file)
-#define SNIFF_TRACE(msg)
-#define SNIFF_TRACE1(msg, arg)
-#define SNIFF_TRACE_CLOSE
-#endif
-
-/*-------- Windows Only Declarations -----------------------------*/
-#ifdef WIN32
-
-static int sniff_request_processed=1;
-static HANDLE sniffemacs_handle=NULL;
-static HANDLE readthread_handle=NULL;
-static HANDLE handle_to_sniff=NULL;
-static HANDLE handle_from_sniff=NULL;
-
-struct sniffBufNode
-{
- struct sniffBufNode *next;
- int bufLen;
- char buf[MAX_REQUEST_LEN];
-};
-static struct sniffBufNode *sniffBufStart=NULL;
-static struct sniffBufNode *sniffBufEnd=NULL;
-static HANDLE hBufferMutex=NULL;
-
-# ifdef FEAT_GUI_W32
- extern HWND s_hwnd; /* gvim's Window handle */
-# endif
-/*
- * some helper functions for Windows port only
- */
-
- static HANDLE
-ExecuteDetachedProgram(char *szBinary, char *szCmdLine,
- HANDLE hStdInput, HANDLE hStdOutput)
-{
- BOOL bResult;
- DWORD nError;
- PROCESS_INFORMATION aProcessInformation;
- PROCESS_INFORMATION *pProcessInformation= &aProcessInformation;
- STARTUPINFO aStartupInfo;
- STARTUPINFO *pStartupInfo= &aStartupInfo;
- DWORD dwCreationFlags= 0;
- char szPath[512];
- HINSTANCE hResult;
-
- hResult = FindExecutable(szBinary, ".", szPath);
- if ((int)hResult <= 32)
- {
- /* can't find the exe file */
- return NULL;
- }
-
- ZeroMemory(pStartupInfo, sizeof(*pStartupInfo));
- pStartupInfo->dwFlags= STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
- pStartupInfo->hStdInput = hStdInput;
- pStartupInfo->hStdOutput = hStdOutput;
- pStartupInfo->wShowWindow= SW_HIDE;
- pStartupInfo->cb = sizeof(STARTUPINFO);
-
- bResult= CreateProcess(
- szPath,
- szCmdLine,
- NULL, /* security attr for process */
- NULL, /* security attr for primary thread */
- TRUE, /* DO inherit stdin and stdout */
- dwCreationFlags, /* creation flags */
- NULL, /* environment */
- ".", /* current directory */
- pStartupInfo, /* startup info: NULL crashes */
- pProcessInformation /* process information: NULL crashes */
- );
- nError= GetLastError();
- if (bResult)
- {
- CloseHandle(pProcessInformation->hThread);
- CloseHandle(hStdInput);
- CloseHandle(hStdOutput);
- return(pProcessInformation->hProcess);
- }
- else
- return(NULL);
-}
-
-/*
- * write to the internal Thread / Thread communications buffer.
- * Return TRUE if successful, FALSE else.
- */
- static BOOL
-writeToBuffer(char *msg, int len)
-{
- DWORD dwWaitResult; /* Request ownership of mutex. */
- struct sniffBufNode *bn;
- int bnSize;
-
- SNIFF_TRACE1("writeToBuffer %d\n", len);
- bnSize = sizeof(struct sniffBufNode) - MAX_REQUEST_LEN + len + 1;
- if (bnSize < 128) bnSize = 128; /* minimum length to avoid fragmentation */
- bn = (struct sniffBufNode *)malloc(bnSize);
- if (!bn)
- return FALSE;
-
- memcpy(bn->buf, msg, len);
- bn->buf[len]='\0'; /* terminate CString for added safety */
- bn->next = NULL;
- bn->bufLen = len;
- /* now, acquire a Mutex for adding the string to our linked list */
- dwWaitResult = WaitForSingleObject(
- hBufferMutex, /* handle of mutex */
- 1000L); /* one-second time-out interval */
- if (dwWaitResult == WAIT_OBJECT_0)
- {
- /* The thread got mutex ownership. */
- if (sniffBufEnd)
- {
- sniffBufEnd->next = bn;
- sniffBufEnd = bn;
- }
- else
- sniffBufStart = sniffBufEnd = bn;
- /* Release ownership of the mutex object. */
- if (! ReleaseMutex(hBufferMutex))
- {
- /* Deal with error. */
- }
- return TRUE;
- }
-
- /* Cannot get mutex ownership due to time-out or mutex object abandoned. */
- free(bn);
- return FALSE;
-}
-
-/*
- * read from the internal Thread / Thread communications buffer.
- * Return TRUE if successful, FALSE else.
- */
- static int
-ReadFromBuffer(char *buf, int maxlen)
-{
- DWORD dwWaitResult; /* Request ownership of mutex. */
- int theLen;
- struct sniffBufNode *bn;
-
- dwWaitResult = WaitForSingleObject(
- hBufferMutex, /* handle of mutex */
- 1000L); /* one-second time-out interval */
- if (dwWaitResult == WAIT_OBJECT_0)
- {
- if (!sniffBufStart)
- {
- /* all pending Requests Processed */
- theLen = 0;
- }
- else
- {
- bn = sniffBufStart;
- theLen = bn->bufLen;
- SNIFF_TRACE1("ReadFromBuffer %d\n", theLen);
- if (theLen >= maxlen)
- {
- /* notify the user of buffer overflow? */
- theLen = maxlen-1;
- }
- memcpy(buf, bn->buf, theLen);
- buf[theLen] = '\0';
- if (! (sniffBufStart = bn->next))
- {
- sniffBufEnd = NULL;
- sniff_request_processed = 1;
- }
- free(bn);
- }
- if (! ReleaseMutex(hBufferMutex))
- {
- /* Deal with error. */
- }
- return theLen;
- }
-
- /* Cannot get mutex ownership due to time-out or mutex object abandoned. */
- return -1;
-}
-
-/* on Win32, a separate Thread reads the input pipe. get_request is not needed here. */
- static void __cdecl
-SniffEmacsReadThread(void *dummy)
-{
- static char ReadThreadBuffer[MAX_REQUEST_LEN];
- int ReadThreadLen=0;
- int result=0;
- int msgLen=0;
- char *msgStart, *msgCur;
-
- SNIFF_TRACE("begin thread\n");
- /* Read from the pipe to SniffEmacs */
- while (sniff_connected)
- {
- if (!ReadFile(handle_from_sniff,
- ReadThreadBuffer + ReadThreadLen, /* acknowledge rest in buffer */
- MAX_REQUEST_LEN - ReadThreadLen,
- &result,
- NULL))
- {
- DWORD err = GetLastError();
- result = -1;
- }
-
- if (result < 0)
- {
- /* probably sniffemacs died... log the Error? */
- sniff_disconnect(1);
- }
- else if (result > 0)
- {
- ReadThreadLen += result-1; /* total length of valid chars */
- for(msgCur=msgStart=ReadThreadBuffer; ReadThreadLen > 0; msgCur++, ReadThreadLen--)
- {
- if (*msgCur == '\0' || *msgCur == '\r' || *msgCur == '\n')
- {
- msgLen = msgCur-msgStart; /* don't add the CR/LF chars */
- if (msgLen > 0)
- writeToBuffer(msgStart, msgLen);
- msgStart = msgCur + 1; /* over-read single CR/LF chars */
- }
- }
-
- /* move incomplete message to beginning of buffer */
- ReadThreadLen = msgCur - msgStart;
- if (ReadThreadLen > 0)
- mch_memmove(ReadThreadBuffer, msgStart, ReadThreadLen);
-
- if (sniff_request_processed)
- {
- /* notify others that new data has arrived */
- sniff_request_processed = 0;
- sniff_request_waiting = 1;
-#ifdef FEAT_GUI_W32
- PostMessage(s_hwnd, WM_USER, (WPARAM)0, (LPARAM)0);
-#endif
- }
- }
- }
- SNIFF_TRACE("end thread\n");
-}
-#endif /* WIN32 */
-/*-------- End of Windows Only Declarations ------------------------*/
-
-
-/* ProcessSniffRequests
- * Function that should be called from outside
- * to process the waiting sniff requests
- */
- void
-ProcessSniffRequests(void)
-{
- static char buf[MAX_REQUEST_LEN];
- int len;
-
- while (sniff_connected)
- {
-#ifdef WIN32
- len = ReadFromBuffer(buf, sizeof(buf));
-#else
- len = get_request(fd_from_sniff, buf, sizeof(buf));
-#endif
- if (len < 0)
- {
- vi_error_msg(_("E274: Sniff: Error during read. Disconnected"));
- sniff_disconnect(1);
- break;
- }
- else if (len > 0)
- HandleSniffRequest( buf );
- else
- break;
- }
-
- if (sniff_will_disconnect) /* Now the last msg has been processed */
- sniff_disconnect(1);
-}
-
- static struct sn_cmd *
-find_sniff_cmd(char *cmd)
-{
- struct sn_cmd *sniff_cmd = NULL;
- int i;
- for(i=0; sniff_cmds[i].cmd_name; i++)
- {
- if (!strcmp(cmd, sniff_cmds[i].cmd_name))
- {
- sniff_cmd = &sniff_cmds[i];
- break;
- }
- }
- if (!sniff_cmd)
- {
- struct sn_cmd_list *list = sniff_cmd_ext;
- while (list)
- {
- if (!strcmp(cmd, list->sniff_cmd->cmd_name))
- {
- sniff_cmd = list->sniff_cmd;
- break;
- }
- list = list->next_cmd;
- }
- }
- return sniff_cmd;
-}
-
- static int
-add_sniff_cmd(char *cmd, char *def, char *msg)
-{
- int rc = 0;
- if (def != NULL && def[0] != NUL && find_sniff_cmd(cmd) == NULL)
- {
- struct sn_cmd_list *list = sniff_cmd_ext;
- struct sn_cmd *sniff_cmd = (struct sn_cmd*)malloc(sizeof(struct sn_cmd));
- struct sn_cmd_list *cmd_node = (struct sn_cmd_list*)malloc(sizeof(struct sn_cmd_list));
- int rq_type = 0;
-
- /* unescape message text */
- char *p = msg;
- char *end = p+strlen(msg);
- while (*p)
- {
- if (*p == '\\')
- mch_memmove(p,p+1,end-p);
- p++;
- }
- SNIFF_TRACE1("request name = %s\n",cmd);
- SNIFF_TRACE1("request def = %s\n",def);
- SNIFF_TRACE1("request msg = %s\n",msg);
-
- while (list && list->next_cmd)
- list = list->next_cmd;
- if (!list)
- sniff_cmd_ext = cmd_node;
- else
- list->next_cmd = cmd_node;
-
- sniff_cmd->cmd_name = cmd;
- sniff_cmd->cmd_code = def[0];
- sniff_cmd->cmd_msg = msg;
- switch(def[1])
- {
- case 'f':
- rq_type = RQ_NOSYMBOL;
- break;
- case 's':
- rq_type = RQ_CONTEXT;
- break;
- case 'S':
- rq_type = RQ_SCONTEXT;
- break;
- default:
- rq_type = RQ_SIMPLE;
- break;
- }
- sniff_cmd->cmd_type = rq_type;
- cmd_node->sniff_cmd = sniff_cmd;
- cmd_node->next_cmd = NULL;
- rc = 1;
- }
- return rc;
-}
-
-/* ex_sniff
- * Handle ":sniff" command
- */
- void
-ex_sniff(exarg_T *eap)
-{
- char_u *arg = eap->arg;
- char_u *symbol = NULL;
- char_u *cmd = NULL;
-
- SNIFF_TRACE_OPEN("if_sniff.log");
- if (ends_excmd(*arg)) /* no request: print available commands */
- {
- int i;
- msg_start();
- msg_outtrans_attr((char_u *)"-- SNiFF+ commands --", hl_attr(HLF_T));
- for(i=0; sniff_cmds[i].cmd_name; i++)
- {
- msg_putchar('\n');
- msg_outtrans((char_u *)":sniff ");
- msg_outtrans((char_u *)sniff_cmds[i].cmd_name);
- }
- msg_putchar('\n');
- msg_outtrans((char_u *)_("SNiFF+ is currently "));
- if (!sniff_connected)
- msg_outtrans((char_u *)_("not "));
- msg_outtrans((char_u *)_("connected"));
- msg_end();
- }
- else /* extract command name and symbol if present */
- {
- symbol = skiptowhite(arg);
- cmd = vim_strnsave(arg, (int)(symbol-arg));
- symbol = skipwhite(symbol);
- if (ends_excmd(*symbol))
- symbol = NULL;
- if (!strcmp((char *)cmd, "addcmd"))
- {
- char_u *def = skiptowhite(symbol);
- char_u *name = vim_strnsave(symbol, (int)(def-symbol));
- char_u *msg;
- def = skipwhite(def);
- msg = skiptowhite(def);
- def = vim_strnsave(def, (int)(msg-def));
- msg = skipwhite(msg);
- if (ends_excmd(*msg))
- msg = vim_strsave(name);
- else
- msg = vim_strnsave(msg, (int)(skiptowhite_esc(msg)-msg));
- if (!add_sniff_cmd((char*)name, (char*)def, (char*)msg))
- {
- vim_free(msg);
- vim_free(def);
- vim_free(name);
- }
- }
- else
- {
- struct sn_cmd* sniff_cmd = find_sniff_cmd((char*)cmd);
- if (sniff_cmd)
- SendRequest(sniff_cmd, (char *)symbol);
- else
- EMSG2(_("E275: Unknown SNiFF+ request: %s"), cmd);
- }
- vim_free(cmd);
- }
-}
-
-
- static void
-sniff_connect(void)
-{
- if (sniff_connected)
- return;
- if (ConnectToSniffEmacs())
- vi_error_msg(_("E276: Error connecting to SNiFF+"));
- else
- {
- int i;
-
- for (i = 0; init_cmds[i]; i++)
- vi_exec_cmd(init_cmds[i]);
- }
-}
-
- void
-sniff_disconnect(int immediately)
-{
- if (!sniff_connected)
- return;
- if (immediately)
- {
- vi_exec_cmd("augroup sniff");
- vi_exec_cmd("au!");
- vi_exec_cmd("augroup END");
- vi_exec_cmd("unlet g:sniff_connected");
- sniff_connected = 0;
- want_sniff_request = 0;
- sniff_will_disconnect = 0;
-#ifdef FEAT_GUI
- if (gui.in_use)
- gui_mch_wait_for_chars(0L);
-#endif
-#ifdef WIN32
- while (sniffBufStart != NULL)
- {
- struct sniffBufNode *node = sniffBufStart;
- sniffBufStart = sniffBufStart->next;
- free(node);
- }
- sniffBufStart = sniffBufEnd = NULL;
- sniff_request_processed = 1;
- CloseHandle(handle_to_sniff);
- CloseHandle(handle_from_sniff);
- WaitForSingleObject(sniffemacs_handle, 1000L);
- CloseHandle(sniffemacs_handle);
- sniffemacs_handle = NULL;
- WaitForSingleObject(readthread_handle, 1000L);
- readthread_handle = NULL;
- CloseHandle(hBufferMutex);
- hBufferMutex = NULL;
- SNIFF_TRACE_CLOSE;
-#else
- close(fd_to_sniff);
- close(fd_from_sniff);
- wait(NULL);
-#endif
- }
- else
- {
-#ifdef WIN32
-# if (defined(_MSC_VER) && _MSC_VER >= 1400)
- Sleep(2);
-# else
- _sleep(2);
-# endif
- if (!sniff_request_processed)
- ProcessSniffRequests();
-#else
- sleep(2); /* Incoming msg could disturb edit */
-#endif
- sniff_will_disconnect = 1; /* We expect disconnect msg in 2 secs */
- }
-}
-
-
-/* ConnectToSniffEmacs
- * Connect to Sniff: returns 1 on error
- */
- static int
-ConnectToSniffEmacs(void)
-{
-#ifdef WIN32 /* Windows Version of the Code */
- HANDLE ToSniffEmacs[2], FromSniffEmacs[2];
- SECURITY_ATTRIBUTES sa;
-
- sa.nLength = sizeof(sa);
- sa.lpSecurityDescriptor = NULL;
- sa.bInheritHandle = TRUE;
-
- if (! CreatePipe(&ToSniffEmacs[0], &ToSniffEmacs[1], &sa, 0))
- return 1;
- if (! CreatePipe(&FromSniffEmacs[0], &FromSniffEmacs[1], &sa, 0))
- return 1;
-
- sniffemacs_handle = ExecuteDetachedProgram(SniffEmacs[0], SniffEmacs[0],
- ToSniffEmacs[0], FromSniffEmacs[1]);
-
- if (sniffemacs_handle)
- {
- handle_to_sniff = ToSniffEmacs[1];
- handle_from_sniff = FromSniffEmacs[0];
- sniff_connected = 1;
- hBufferMutex = CreateMutex(
- NULL, /* no security attributes */
- FALSE, /* initially not owned */
- "SniffReadBufferMutex"); /* name of mutex */
- if (hBufferMutex == NULL)
- {
- /* Check for error. */
- }
- readthread_handle = (HANDLE)_beginthread(SniffEmacsReadThread, 0, NULL);
- return 0;
- }
- else
- {
- /* error in spawn() */
- return 1;
- }
-
-#else /* UNIX Version of the Code */
- int ToSniffEmacs[2], FromSniffEmacs[2];
-
- if (pipe(ToSniffEmacs) != 0)
- return 1;
- if (pipe(FromSniffEmacs) != 0)
- return 1;
-
- /* fork */
- if ((sniffemacs_pid=fork()) == 0)
- {
- /* child */
-
- /* prepare communication pipes */
- close(ToSniffEmacs[1]);
- close(FromSniffEmacs[0]);
-
- dup2(ToSniffEmacs[0],fileno(stdin)); /* write to ToSniffEmacs[1] */
- dup2(FromSniffEmacs[1],fileno(stdout));/* read from FromSniffEmacs[0] */
-
- close(ToSniffEmacs[0]);
- close(FromSniffEmacs[1]);
-
- /* start sniffemacs */
- execvp (SniffEmacs[0], SniffEmacs);
- {
-/* FILE *out = fdopen(FromSniffEmacs[1], "w"); */
- sleep(1);
- fputs(_(msg_sniff_disconnect), stdout);
- fflush(stdout);
- sleep(3);
-#ifdef FEAT_GUI
- if (gui.in_use)
- gui_exit(1);
-#endif
- exit(1);
- }
- return 1;
- }
- else if (sniffemacs_pid > 0)
- {
- /* parent process */
- close(ToSniffEmacs[0]);
- fd_to_sniff = ToSniffEmacs[1];
- close(FromSniffEmacs[1]);
- fd_from_sniff = FromSniffEmacs[0];
- sniff_connected = 1;
- return 0;
- }
- else /* error in fork() */
- return 1;
-#endif /* UNIX Version of the Code */
-}
-
-
-/* HandleSniffRequest
- * Handle one request from SNiFF+
- */
- static void
-HandleSniffRequest(char *buffer)
-{
- char VICommand[MAX_REQUEST_LEN];
- char command;
- char *arguments;
- char *token;
- char *argv[3];
- int argc = 0;
- buf_T *buf;
-
- const char *SetTab = "set tabstop=%d";
- const char *SelectBuf = "buf %s";
- const char *DeleteBuf = "bd %s";
- const char *UnloadBuf = "bun %s";
- const char *GotoLine = "%d";
-
- command = buffer[0];
- arguments = &buffer[1];
- token = strtok(arguments, sniff_rq_sep);
- while (argc <3)
- {
- if (token)
- {
- argv[argc] = (char*)vim_strsave((char_u *)token);
- token = strtok(0, sniff_rq_sep);
- }
- else
- argv[argc] = strdup("");
- argc++;
- }
-
- switch (command)
- {
- case 'o' : /* visit file at char pos */
- case 'O' : /* visit file at line number */
- {
- char *file = argv[0];
- int position = atoi(argv[1]);
-
- buf = vi_find_buffer(file);
- setpcmark(); /* insert current pos in jump list [mark.c]*/
- if (!buf)
- vi_open_file(file);
- else if (buf!=curbuf)
- {
- vim_snprintf(VICommand, sizeof(VICommand),
- (char *)SelectBuf, file);
- vi_exec_cmd(VICommand);
- }
- if (command == 'o')
- vi_set_cursor_pos((long)position);
- else
- {
- vim_snprintf(VICommand, sizeof(VICommand),
- (char *)GotoLine, (int)position);
- vi_exec_cmd(VICommand);
- }
- checkpcmark(); /* [mark.c] */
-#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_W32)
- if (gui.in_use && !gui.in_focus) /* Raise Vim Window */
- {
-# ifdef FEAT_GUI_W32
- SetForegroundWindow(s_hwnd);
-# else
- extern Widget vimShell;
-
- XSetInputFocus(gui.dpy, XtWindow(vimShell), RevertToNone,
- CurrentTime);
- XRaiseWindow(gui.dpy, XtWindow(vimShell));
-# endif
- }
-#endif
- break;
- }
- case 'p' : /* path of file has changed */
- /* when changing from shared to private WS (checkout) */
- {
- char *file = argv[0];
- char *new_path = argv[1];
-
- buf = vi_find_buffer(file);
- if (buf && !buf->b_changed) /* delete buffer only if not modified */
- {
- vim_snprintf(VICommand, sizeof(VICommand),
- (char *)DeleteBuf, file);
- vi_exec_cmd(VICommand);
- }
- vi_open_file(new_path);
- break;
- }
- case 'w' : /* writability has changed */
- /* Sniff sends request twice,
- * but only the last one is the right one */
- {
- char *file = argv[0];
- int writable = atoi(argv[1]);
-
- buf = vi_find_buffer(file);
- if (buf)
- {
- buf->b_p_ro = !writable;
- if (buf != curbuf)
- {
- buf->b_flags |= BF_CHECK_RO + BF_NEVERLOADED;
- if (writable && !buf->b_changed)
- {
- vim_snprintf(VICommand, sizeof(VICommand),
- (char *)UnloadBuf, file);
- vi_exec_cmd(VICommand);
- }
- }
- else if (writable && !buf->b_changed)
- {
- vi_exec_cmd("e");
- }
- }
- break;
- }
- case 'h' : /* highlight info */
- break; /* not implemented */
-
- case 't' : /* Set tab width */
- {
- int tab_width = atoi(argv[1]);
-
- if (tab_width > 0 && tab_width <= 16)
- {
- vim_snprintf(VICommand, sizeof(VICommand),
- (char *)SetTab, tab_width);
- vi_exec_cmd(VICommand);
- }
- break;
- }
- case '|':
- {
- /* change the request separator */
- sniff_rq_sep[0] = arguments[0];
- /* echo the request */
- WriteToSniff(buffer);
- break;
- }
- case 'A' : /* Warning/Info msg */
- vi_msg(arguments);
- if (!strncmp(arguments, "Disconnected", 12))
- sniff_disconnect(1); /* unexpected disconnection */
- break;
- case 'a' : /* Error msg */
- vi_error_msg(arguments);
- if (!strncmp(arguments, "Cannot connect", 14))
- sniff_disconnect(1);
- break;
-
- default :
- break;
- }
- while (argc)
- vim_free(argv[--argc]);
-}
-
-
-#ifndef WIN32
-/* get_request
- * read string from fd up to next newline (excluding the nl),
- * returns length of string
- * 0 if no data available or no complete line
- * <0 on error
- */
- static int
-get_request(int fd, char *buf, int maxlen)
-{
- static char inbuf[1024];
- static int pos = 0, bytes = 0;
- int len;
-#ifdef HAVE_SELECT
- struct timeval tval;
- fd_set rfds;
-
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
- tval.tv_sec = 0;
- tval.tv_usec = 0;
-#else
- struct pollfd fds;
-
- fds.fd = fd;
- fds.events = POLLIN;
-#endif
-
- for (len = 0; len < maxlen; len++)
- {
- if (pos >= bytes) /* end of buffer reached? */
- {
-#ifdef HAVE_SELECT
- if (select(fd + 1, &rfds, NULL, NULL, &tval) > 0)
-#else
- if (poll(&fds, 1, 0) > 0)
-#endif
- {
- pos = 0;
- bytes = read(fd, inbuf, sizeof(inbuf));
- if (bytes <= 0)
- return bytes;
- }
- else
- {
- pos = pos-len;
- buf[0] = '\0';
- return 0;
- }
- }
- if ((buf[len] = inbuf[pos++]) =='\n')
- break;
- }
- buf[len] = '\0';
- return len;
-}
-#endif /* WIN32 */
-
-
- static void
-SendRequest(struct sn_cmd *command, char *symbol)
-{
- int cmd_type = command->cmd_type;
- static char cmdstr[MAX_REQUEST_LEN];
- static char msgtxt[MAX_REQUEST_LEN];
- char *buffer_name = NULL;
-
- if (cmd_type == RQ_CONNECT)
- {
- sniff_connect();
- return;
- }
- if (!sniff_connected && !(cmd_type & SILENT))
- {
- vi_error_msg(_("E278: SNiFF+ not connected"));
- return;
- }
-
- if (cmd_type & NEED_FILE)
- {
- if (!curbuf->b_sniff)
- {
- if (!(cmd_type & SILENT))
- vi_error_msg(_("E279: Not a SNiFF+ buffer"));
- return;
- }
- buffer_name = vi_buffer_name();
- if (buffer_name == NULL)
- return;
- if (cmd_type & NEED_SYMBOL)
- {
- if (cmd_type & EMPTY_SYMBOL)
- symbol = " ";
- else if (!symbol && !(symbol = vi_symbol_under_cursor()))
- return; /* error msg already displayed */
- }
-
- if (symbol)
- vim_snprintf(cmdstr, sizeof(cmdstr), "%c%s%s%ld%s%s\n",
- command->cmd_code,
- buffer_name,
- sniff_rq_sep,
- vi_cursor_pos(),
- sniff_rq_sep,
- symbol
- );
- else
- vim_snprintf(cmdstr, sizeof(cmdstr), "%c%s\n",
- command->cmd_code, buffer_name);
- }
- else /* simple request */
- {
- cmdstr[0] = command->cmd_code;
- cmdstr[1] = '\n';
- cmdstr[2] = '\0';
- }
- if (command->cmd_msg && !(cmd_type & SILENT))
- {
- if ((cmd_type & NEED_SYMBOL) && !(cmd_type & EMPTY_SYMBOL))
- {
- vim_snprintf(msgtxt, sizeof(msgtxt), "%s: %s",
- _(command->cmd_msg), symbol);
- vi_msg(msgtxt);
- }
- else
- vi_msg(_(command->cmd_msg));
- }
- WriteToSniff(cmdstr);
- if (cmd_type & DISCONNECT)
- sniff_disconnect(0);
-}
-
-
-
- static void
-WriteToSniff(char *str)
-{
- int bytes;
-#ifdef WIN32
- if (! WriteFile(handle_to_sniff, str, strlen(str), &bytes, NULL))
- {
- DWORD err=GetLastError();
- bytes = -1;
- }
-#else
- bytes = write(fd_to_sniff, str, strlen(str));
-#endif
- if (bytes<0)
- {
- vi_msg(_("Sniff: Error during write. Disconnected"));
- sniff_disconnect(1);
- }
-}
-
-/*-------- vim helping functions --------------------------------*/
-
- static void
-vi_msg(char *str)
-{
- if (str != NULL && *str != NUL)
- MSG((char_u *)str);
-}
-
- static void
-vi_error_msg(char *str)
-{
- if (str != NULL && *str != NUL)
- EMSG((char_u *)str);
-}
-
- static void
-vi_open_file(char *fname)
-{
- ++no_wait_return;
- do_ecmd(0, (char_u *)fname, NULL, NULL, ECMD_ONE, ECMD_HIDE+ECMD_OLDBUF,
- curwin);
- curbuf->b_sniff = TRUE;
- --no_wait_return; /* [ex_docmd.c] */
-}
-
- static buf_T *
-vi_find_buffer(char *fname)
-{ /* derived from buflist_findname() [buffer.c] */
- buf_T *buf;
-
- for (buf = firstbuf; buf != NULL; buf = buf->b_next)
- if (buf->b_sfname != NULL && fnamecmp(fname, buf->b_sfname) == 0)
- return (buf);
- return NULL;
-}
-
-
- static char *
-vi_symbol_under_cursor(void)
-{
- int len;
- char *symbolp;
- char *p;
- static char sniff_symbol[256];
-
- len = find_ident_under_cursor((char_u **)&symbolp, FIND_IDENT);
- /* [normal.c] */
- if (len <= 0)
- return NULL;
- for (p=sniff_symbol; len; len--)
- *p++ = *symbolp++;
- *p = '\0';
- return sniff_symbol;
-}
-
-
- static char *
-vi_buffer_name(void)
-{
- return (char *)curbuf->b_sfname;
-}
-
- static void
-vi_exec_cmd(char *vicmd)
-{
- do_cmdline_cmd((char_u *)vicmd); /* [ex_docmd.c] */
-}
-
-/*
- * Set cursor on character position
- * derived from cursor_pos_info() [buffer.c]
- */
- static void
-vi_set_cursor_pos(long char_pos)
-{
- linenr_T lnum;
- long char_count = 1; /* first position = 1 */
- int line_size;
- int eol_size;
-
- if (char_pos == 0)
- {
- char_pos = 1;
- }
- if (get_fileformat(curbuf) == EOL_DOS)
- eol_size = 2;
- else
- eol_size = 1;
- for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
- {
- line_size = STRLEN(ml_get(lnum)) + eol_size;
- if (char_count+line_size > char_pos) break;
- char_count += line_size;
- }
- curwin->w_cursor.lnum = lnum;
- curwin->w_cursor.col = char_pos - char_count;
-}
-
- static long
-vi_cursor_pos(void)
-{
- linenr_T lnum;
- long char_count=1; /* sniff starts with pos 1 */
- int line_size;
- int eol_size;
-
- if (curbuf->b_p_tx)
- eol_size = 2;
- else
- eol_size = 1;
- for (lnum = 1; lnum < curwin->w_cursor.lnum; ++lnum)
- {
- line_size = STRLEN(ml_get(lnum)) + eol_size;
- char_count += line_size;
- }
- return char_count + curwin->w_cursor.col;
-}