1 /* vi:set ts=8 sts=4 sw=4:
3 * if_sniff.c Interface between Vim and SNiFF+
5 * See README.txt for an overview of the Vim source code.
18 # include "gui_x11.pro"
20 # include "os_unixx.h"
23 static int sniffemacs_pid
;
26 int sniff_connected
= 0;
27 int sniff_request_waiting
= 0;
28 int want_sniff_request
= 0;
30 #define MAX_REQUEST_LEN 512
33 #define EMPTY_SYMBOL 4
41 #define RQ_CONTEXT NEED_FILE + NEED_SYMBOL
42 #define RQ_SCONTEXT NEED_FILE + NEED_SYMBOL + EMPTY_SYMBOL
43 #define RQ_NOSYMBOL NEED_FILE
44 #define RQ_SILENT RQ_NOSYMBOL + SILENT
45 #define RQ_CONNECT RQ_NONE + CONNECT
46 #define RQ_DISCONNECT RQ_SIMPLE + DISCONNECT
58 struct sn_cmd
* sniff_cmd
;
59 struct sn_cmd_list
* next_cmd
;
62 static struct sn_cmd sniff_cmds
[] =
64 { "toggle", 'e', N_("Toggle implementation/definition"),RQ_SCONTEXT
},
65 { "superclass", 's', N_("Show base class of"), RQ_CONTEXT
},
66 { "overridden", 'm', N_("Show overridden member function"),RQ_SCONTEXT
},
67 { "retrieve-file", 'r', N_("Retrieve from file"), RQ_CONTEXT
},
68 { "retrieve-project",'p', N_("Retrieve from project"), RQ_CONTEXT
},
69 { "retrieve-all-projects",
70 'P', N_("Retrieve from all projects"), RQ_CONTEXT
},
71 { "retrieve-next", 'R', N_("Retrieve"), RQ_CONTEXT
},
72 { "goto-symbol", 'g', N_("Show source of"), RQ_CONTEXT
},
73 { "find-symbol", 'f', N_("Find symbol"), RQ_CONTEXT
},
74 { "browse-class", 'w', N_("Browse class"), RQ_CONTEXT
},
75 { "hierarchy", 't', N_("Show class in hierarchy"), RQ_CONTEXT
},
76 { "restr-hier", 'T', N_("Show class in restricted hierarchy"),RQ_CONTEXT
},
77 { "xref-to", 'x', N_("Xref refers to"), RQ_CONTEXT
},
78 { "xref-by", 'X', N_("Xref referred by"), RQ_CONTEXT
},
79 { "xref-has", 'c', N_("Xref has a"), RQ_CONTEXT
},
80 { "xref-used-by", 'C', N_("Xref used by"), RQ_CONTEXT
},
81 { "show-docu", 'd', N_("Show docu of"), RQ_CONTEXT
},
82 { "gen-docu", 'D', N_("Generate docu for"), RQ_CONTEXT
},
83 { "connect", 'y', NULL
, RQ_CONNECT
},
84 { "disconnect", 'q', NULL
, RQ_DISCONNECT
},
85 { "font-info", 'z', NULL
, RQ_SILENT
},
86 { "update", 'u', NULL
, RQ_SILENT
},
87 { NULL
, '\0', NULL
, 0}
91 static char *SniffEmacs
[2] = {"sniffemacs", (char *)NULL
}; /* Yes, Emacs! */
92 static int fd_to_sniff
;
93 static int sniff_will_disconnect
= 0;
94 static char msg_sniff_disconnect
[] = N_("Cannot connect to SNiFF+. Check environment (sniffemacs must be found in $PATH).\n");
95 static char sniff_rq_sep
[] = " ";
96 static struct sn_cmd_list
*sniff_cmd_ext
= NULL
;
98 /* Initializing vim commands
99 * executed each time vim connects to Sniff
101 static char *init_cmds
[]= {
103 "autocmd BufWritePost * sniff update",
104 "autocmd BufReadPost * sniff font-info",
105 "autocmd VimLeave * sniff disconnect",
108 "let g:sniff_connected = 1",
110 "if ! exists('g:sniff_mappings_sourced')|"
111 "if ! exists('g:sniff_mappings')|"
112 "if exists('$SNIFF_DIR4')|"
113 "let g:sniff_mappings='$SNIFF_DIR4/config/integrations/vim/sniff.vim'|"
115 "let g:sniff_mappings='$SNIFF_DIR/config/sniff.vim'|"
118 "let g:sniff_mappings=expand(g:sniff_mappings)|"
119 "if filereadable(g:sniff_mappings)|"
120 "execute 'source' g:sniff_mappings|"
121 "let g:sniff_mappings_sourced=1|"
128 /*-------- Function Prototypes ----------------------------------*/
130 static int ConnectToSniffEmacs
__ARGS((void));
131 static void sniff_connect
__ARGS((void));
132 static void HandleSniffRequest
__ARGS((char* buffer
));
133 static int get_request
__ARGS((int fd
, char *buf
, int maxlen
));
134 static void WriteToSniff
__ARGS((char *str
));
135 static void SendRequest
__ARGS((struct sn_cmd
*command
, char* symbol
));
136 static void vi_msg
__ARGS((char *));
137 static void vi_error_msg
__ARGS((char *));
138 static char *vi_symbol_under_cursor
__ARGS((void));
139 static void vi_open_file
__ARGS((char *));
140 static char *vi_buffer_name
__ARGS((void));
141 static buf_T
*vi_find_buffer
__ARGS((char *));
142 static void vi_exec_cmd
__ARGS((char *));
143 static void vi_set_cursor_pos
__ARGS((long char_nr
));
144 static long vi_cursor_pos
__ARGS((void));
148 static FILE* _tracefile
= NULL
;
149 #define SNIFF_TRACE_OPEN(file) if (!_tracefile) _tracefile = fopen(file, "w")
150 #define SNIFF_TRACE(msg) fprintf(_tracefile, msg); fflush(_tracefile);
151 #define SNIFF_TRACE1(msg, arg) fprintf(_tracefile, msg,arg); fflush(_tracefile);
152 #define SNIFF_TRACE_CLOSE fclose(_tracefile); _tracefile=NULL;
154 #define SNIFF_TRACE_OPEN(file)
155 #define SNIFF_TRACE(msg)
156 #define SNIFF_TRACE1(msg, arg)
157 #define SNIFF_TRACE_CLOSE
160 /*-------- Windows Only Declarations -----------------------------*/
163 static int sniff_request_processed
=1;
164 static HANDLE sniffemacs_handle
=NULL
;
165 static HANDLE readthread_handle
=NULL
;
166 static HANDLE handle_to_sniff
=NULL
;
167 static HANDLE handle_from_sniff
=NULL
;
171 struct sniffBufNode
*next
;
173 char buf
[MAX_REQUEST_LEN
];
175 static struct sniffBufNode
*sniffBufStart
=NULL
;
176 static struct sniffBufNode
*sniffBufEnd
=NULL
;
177 static HANDLE hBufferMutex
=NULL
;
180 extern HWND s_hwnd
; /* gvim's Window handle */
183 * some helper functions for Windows port only
187 ExecuteDetachedProgram(char *szBinary
, char *szCmdLine
,
188 HANDLE hStdInput
, HANDLE hStdOutput
)
192 PROCESS_INFORMATION aProcessInformation
;
193 PROCESS_INFORMATION
*pProcessInformation
= &aProcessInformation
;
194 STARTUPINFO aStartupInfo
;
195 STARTUPINFO
*pStartupInfo
= &aStartupInfo
;
196 DWORD dwCreationFlags
= 0;
200 hResult
= FindExecutable(szBinary
, ".", szPath
);
201 if ((int)hResult
<= 32)
203 /* can't find the exe file */
207 ZeroMemory(pStartupInfo
, sizeof(*pStartupInfo
));
208 pStartupInfo
->dwFlags
= STARTF_USESHOWWINDOW
|STARTF_USESTDHANDLES
;
209 pStartupInfo
->hStdInput
= hStdInput
;
210 pStartupInfo
->hStdOutput
= hStdOutput
;
211 pStartupInfo
->wShowWindow
= SW_HIDE
;
212 pStartupInfo
->cb
= sizeof(STARTUPINFO
);
214 bResult
= CreateProcess(
217 NULL
, /* security attr for process */
218 NULL
, /* security attr for primary thread */
219 TRUE
, /* DO inherit stdin and stdout */
220 dwCreationFlags
, /* creation flags */
221 NULL
, /* environment */
222 ".", /* current directory */
223 pStartupInfo
, /* startup info: NULL crashes */
224 pProcessInformation
/* process information: NULL crashes */
226 nError
= GetLastError();
229 CloseHandle(pProcessInformation
->hThread
);
230 CloseHandle(hStdInput
);
231 CloseHandle(hStdOutput
);
232 return(pProcessInformation
->hProcess
);
239 * write to the internal Thread / Thread communications buffer.
240 * Return TRUE if successful, FALSE else.
243 writeToBuffer(char *msg
, int len
)
245 DWORD dwWaitResult
; /* Request ownership of mutex. */
246 struct sniffBufNode
*bn
;
249 SNIFF_TRACE1("writeToBuffer %d\n", len
);
250 bnSize
= sizeof(struct sniffBufNode
) - MAX_REQUEST_LEN
+ len
+ 1;
251 if (bnSize
< 128) bnSize
= 128; /* minimum length to avoid fragmentation */
252 bn
= (struct sniffBufNode
*)malloc(bnSize
);
256 memcpy(bn
->buf
, msg
, len
);
257 bn
->buf
[len
]='\0'; /* terminate CString for added safety */
260 /* now, acquire a Mutex for adding the string to our linked list */
261 dwWaitResult
= WaitForSingleObject(
262 hBufferMutex
, /* handle of mutex */
263 1000L); /* one-second time-out interval */
264 if (dwWaitResult
== WAIT_OBJECT_0
)
266 /* The thread got mutex ownership. */
269 sniffBufEnd
->next
= bn
;
273 sniffBufStart
= sniffBufEnd
= bn
;
274 /* Release ownership of the mutex object. */
275 if (! ReleaseMutex(hBufferMutex
))
277 /* Deal with error. */
282 /* Cannot get mutex ownership due to time-out or mutex object abandoned. */
288 * read from the internal Thread / Thread communications buffer.
289 * Return TRUE if successful, FALSE else.
292 ReadFromBuffer(char *buf
, int maxlen
)
294 DWORD dwWaitResult
; /* Request ownership of mutex. */
296 struct sniffBufNode
*bn
;
298 dwWaitResult
= WaitForSingleObject(
299 hBufferMutex
, /* handle of mutex */
300 1000L); /* one-second time-out interval */
301 if (dwWaitResult
== WAIT_OBJECT_0
)
305 /* all pending Requests Processed */
312 SNIFF_TRACE1("ReadFromBuffer %d\n", theLen
);
313 if (theLen
>= maxlen
)
315 /* notify the user of buffer overflow? */
318 memcpy(buf
, bn
->buf
, theLen
);
320 if (! (sniffBufStart
= bn
->next
))
323 sniff_request_processed
= 1;
327 if (! ReleaseMutex(hBufferMutex
))
329 /* Deal with error. */
334 /* Cannot get mutex ownership due to time-out or mutex object abandoned. */
338 /* on Win32, a separate Thread reads the input pipe. get_request is not needed here. */
340 SniffEmacsReadThread(void *dummy
)
342 static char ReadThreadBuffer
[MAX_REQUEST_LEN
];
346 char *msgStart
, *msgCur
;
348 SNIFF_TRACE("begin thread\n");
349 /* Read from the pipe to SniffEmacs */
350 while (sniff_connected
)
352 if (!ReadFile(handle_from_sniff
,
353 ReadThreadBuffer
+ ReadThreadLen
, /* acknowledge rest in buffer */
354 MAX_REQUEST_LEN
- ReadThreadLen
,
358 DWORD err
= GetLastError();
364 /* probably sniffemacs died... log the Error? */
369 ReadThreadLen
+= result
-1; /* total length of valid chars */
370 for(msgCur
=msgStart
=ReadThreadBuffer
; ReadThreadLen
> 0; msgCur
++, ReadThreadLen
--)
372 if (*msgCur
== '\0' || *msgCur
== '\r' || *msgCur
== '\n')
374 msgLen
= msgCur
-msgStart
; /* don't add the CR/LF chars */
376 writeToBuffer(msgStart
, msgLen
);
377 msgStart
= msgCur
+ 1; /* over-read single CR/LF chars */
381 /* move incomplete message to beginning of buffer */
382 ReadThreadLen
= msgCur
- msgStart
;
383 if (ReadThreadLen
> 0)
384 mch_memmove(ReadThreadBuffer
, msgStart
, ReadThreadLen
);
386 if (sniff_request_processed
)
388 /* notify others that new data has arrived */
389 sniff_request_processed
= 0;
390 sniff_request_waiting
= 1;
392 PostMessage(s_hwnd
, WM_USER
, (WPARAM
)0, (LPARAM
)0);
397 SNIFF_TRACE("end thread\n");
400 /*-------- End of Windows Only Declarations ------------------------*/
403 /* ProcessSniffRequests
404 * Function that should be called from outside
405 * to process the waiting sniff requests
408 ProcessSniffRequests()
410 static char buf
[MAX_REQUEST_LEN
];
413 while (sniff_connected
)
416 len
= ReadFromBuffer(buf
, sizeof(buf
));
418 len
= get_request(fd_from_sniff
, buf
, sizeof(buf
));
422 vi_error_msg(_("E274: Sniff: Error during read. Disconnected"));
427 HandleSniffRequest( buf
);
432 if (sniff_will_disconnect
) /* Now the last msg has been processed */
436 static struct sn_cmd
*
440 struct sn_cmd
*sniff_cmd
= NULL
;
442 for(i
=0; sniff_cmds
[i
].cmd_name
; i
++)
444 if (!strcmp(cmd
, sniff_cmds
[i
].cmd_name
))
446 sniff_cmd
= &sniff_cmds
[i
];
452 struct sn_cmd_list
*list
= sniff_cmd_ext
;
455 if (!strcmp(cmd
, list
->sniff_cmd
->cmd_name
))
457 sniff_cmd
= list
->sniff_cmd
;
460 list
= list
->next_cmd
;
467 add_sniff_cmd(cmd
, def
, msg
)
473 if (def
!= NULL
&& def
[0] != NUL
&& find_sniff_cmd(cmd
) == NULL
)
475 struct sn_cmd_list
*list
= sniff_cmd_ext
;
476 struct sn_cmd
*sniff_cmd
= (struct sn_cmd
*)malloc(sizeof(struct sn_cmd
));
477 struct sn_cmd_list
*cmd_node
= (struct sn_cmd_list
*)malloc(sizeof(struct sn_cmd_list
));
480 /* unescape message text */
482 char *end
= p
+strlen(msg
);
486 mch_memmove(p
,p
+1,end
-p
);
489 SNIFF_TRACE1("request name = %s\n",cmd
);
490 SNIFF_TRACE1("request def = %s\n",def
);
491 SNIFF_TRACE1("request msg = %s\n",msg
);
493 while(list
&& list
->next_cmd
)
494 list
= list
->next_cmd
;
496 sniff_cmd_ext
= cmd_node
;
498 list
->next_cmd
= cmd_node
;
500 sniff_cmd
->cmd_name
= cmd
;
501 sniff_cmd
->cmd_code
= def
[0];
502 sniff_cmd
->cmd_msg
= msg
;
506 rq_type
= RQ_NOSYMBOL
;
509 rq_type
= RQ_CONTEXT
;
512 rq_type
= RQ_SCONTEXT
;
518 sniff_cmd
->cmd_type
= rq_type
;
519 cmd_node
->sniff_cmd
= sniff_cmd
;
520 cmd_node
->next_cmd
= NULL
;
527 * Handle ":sniff" command
533 char_u
*arg
= eap
->arg
;
534 char_u
*symbol
= NULL
;
537 SNIFF_TRACE_OPEN("if_sniff.log");
538 if (ends_excmd(*arg
)) /* no request: print available commands */
542 msg_outtrans_attr((char_u
*)"-- SNiFF+ commands --", hl_attr(HLF_T
));
543 for(i
=0; sniff_cmds
[i
].cmd_name
; i
++)
546 msg_outtrans((char_u
*)":sniff ");
547 msg_outtrans((char_u
*)sniff_cmds
[i
].cmd_name
);
550 msg_outtrans((char_u
*)_("SNiFF+ is currently "));
551 if (!sniff_connected
)
552 msg_outtrans((char_u
*)_("not "));
553 msg_outtrans((char_u
*)_("connected"));
556 else /* extract command name and symbol if present */
558 symbol
= skiptowhite(arg
);
559 cmd
= vim_strnsave(arg
, (int)(symbol
-arg
));
560 symbol
= skipwhite(symbol
);
561 if (ends_excmd(*symbol
))
563 if (!strcmp((char *)cmd
, "addcmd"))
565 char_u
*def
= skiptowhite(symbol
);
566 char_u
*name
= vim_strnsave(symbol
, (int)(def
-symbol
));
568 def
= skipwhite(def
);
569 msg
= skiptowhite(def
);
570 def
= vim_strnsave(def
, (int)(msg
-def
));
571 msg
= skipwhite(msg
);
572 if (ends_excmd(*msg
))
573 msg
= vim_strsave(name
);
575 msg
= vim_strnsave(msg
, (int)(skiptowhite_esc(msg
)-msg
));
576 if (!add_sniff_cmd((char*)name
, (char*)def
, (char*)msg
))
585 struct sn_cmd
* sniff_cmd
= find_sniff_cmd((char*)cmd
);
587 SendRequest(sniff_cmd
, (char *)symbol
);
589 EMSG2(_("E275: Unknown SNiFF+ request: %s"), cmd
);
601 if (ConnectToSniffEmacs())
602 vi_error_msg(_("E276: Error connecting to SNiFF+"));
607 for (i
= 0; init_cmds
[i
]; i
++)
608 vi_exec_cmd(init_cmds
[i
]);
613 sniff_disconnect(immediately
)
616 if (!sniff_connected
)
620 vi_exec_cmd("augroup sniff");
622 vi_exec_cmd("augroup END");
623 vi_exec_cmd("unlet g:sniff_connected");
625 want_sniff_request
= 0;
626 sniff_will_disconnect
= 0;
629 gui_mch_wait_for_chars(0L);
632 while(sniffBufStart
!= NULL
)
634 struct sniffBufNode
*node
= sniffBufStart
;
635 sniffBufStart
= sniffBufStart
->next
;
638 sniffBufStart
= sniffBufEnd
= NULL
;
639 sniff_request_processed
= 1;
640 CloseHandle(handle_to_sniff
);
641 CloseHandle(handle_from_sniff
);
642 WaitForSingleObject(sniffemacs_handle
, 1000L);
643 CloseHandle(sniffemacs_handle
);
644 sniffemacs_handle
= NULL
;
645 WaitForSingleObject(readthread_handle
, 1000L);
646 readthread_handle
= NULL
;
647 CloseHandle(hBufferMutex
);
652 close(fd_from_sniff
);
660 if (!sniff_request_processed
)
661 ProcessSniffRequests();
663 sleep(2); /* Incoming msg could disturb edit */
665 sniff_will_disconnect
= 1; /* We expect disconnect msg in 2 secs */
670 /* ConnectToSniffEmacs
671 * Connect to Sniff: returns 1 on error
674 ConnectToSniffEmacs()
676 #ifdef WIN32 /* Windows Version of the Code */
677 HANDLE ToSniffEmacs
[2], FromSniffEmacs
[2];
678 SECURITY_ATTRIBUTES sa
;
680 sa
.nLength
= sizeof(sa
);
681 sa
.lpSecurityDescriptor
= NULL
;
682 sa
.bInheritHandle
= TRUE
;
684 if (! CreatePipe(&ToSniffEmacs
[0], &ToSniffEmacs
[1], &sa
, 0))
686 if (! CreatePipe(&FromSniffEmacs
[0], &FromSniffEmacs
[1], &sa
, 0))
689 sniffemacs_handle
= ExecuteDetachedProgram(SniffEmacs
[0], SniffEmacs
[0],
690 ToSniffEmacs
[0], FromSniffEmacs
[1]);
692 if (sniffemacs_handle
)
694 handle_to_sniff
= ToSniffEmacs
[1];
695 handle_from_sniff
= FromSniffEmacs
[0];
697 hBufferMutex
= CreateMutex(
698 NULL
, /* no security attributes */
699 FALSE
, /* initially not owned */
700 "SniffReadBufferMutex"); /* name of mutex */
701 if (hBufferMutex
== NULL
)
703 /* Check for error. */
705 readthread_handle
= (HANDLE
)_beginthread(SniffEmacsReadThread
, 0, NULL
);
710 /* error in spawn() */
714 #else /* UNIX Version of the Code */
715 int ToSniffEmacs
[2], FromSniffEmacs
[2];
717 if (pipe(ToSniffEmacs
) != 0)
719 if (pipe(FromSniffEmacs
) != 0)
723 if ((sniffemacs_pid
=fork()) == 0)
727 /* prepare communication pipes */
728 close(ToSniffEmacs
[1]);
729 close(FromSniffEmacs
[0]);
731 dup2(ToSniffEmacs
[0],fileno(stdin
)); /* write to ToSniffEmacs[1] */
732 dup2(FromSniffEmacs
[1],fileno(stdout
));/* read from FromSniffEmacs[0] */
734 close(ToSniffEmacs
[0]);
735 close(FromSniffEmacs
[1]);
737 /* start sniffemacs */
738 execvp (SniffEmacs
[0], SniffEmacs
);
740 /* FILE *out = fdopen(FromSniffEmacs[1], "w"); */
742 fputs(_(msg_sniff_disconnect
), stdout
);
753 else if (sniffemacs_pid
> 0)
756 close(ToSniffEmacs
[0]);
757 fd_to_sniff
= ToSniffEmacs
[1];
758 close(FromSniffEmacs
[1]);
759 fd_from_sniff
= FromSniffEmacs
[0];
763 else /* error in fork() */
765 #endif /* UNIX Version of the Code */
769 /* HandleSniffRequest
770 * Handle one request from SNiFF+
773 HandleSniffRequest(buffer
)
776 char VICommand
[MAX_REQUEST_LEN
];
784 const char *SetTab
= "set tabstop=%d";
785 const char *SelectBuf
= "buf %s";
786 const char *DeleteBuf
= "bd %s";
787 const char *UnloadBuf
= "bun %s";
788 const char *GotoLine
= "%d";
791 arguments
= &buffer
[1];
792 token
= strtok(arguments
, sniff_rq_sep
);
797 argv
[argc
] = (char*)vim_strsave((char_u
*)token
);
798 token
= strtok(0, sniff_rq_sep
);
801 argv
[argc
] = strdup("");
807 case 'o' : /* visit file at char pos */
808 case 'O' : /* visit file at line number */
810 char *file
= argv
[0];
811 int position
= atoi(argv
[1]);
813 buf
= vi_find_buffer(file
);
814 setpcmark(); /* insert current pos in jump list [mark.c]*/
817 else if (buf
!=curbuf
)
819 vim_snprintf(VICommand
, sizeof(VICommand
),
820 (char *)SelectBuf
, file
);
821 vi_exec_cmd(VICommand
);
824 vi_set_cursor_pos((long)position
);
827 vim_snprintf(VICommand
, sizeof(VICommand
),
828 (char *)GotoLine
, (int)position
);
829 vi_exec_cmd(VICommand
);
831 checkpcmark(); /* [mark.c] */
832 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_W32)
833 if (gui
.in_use
&& !gui
.in_focus
) /* Raise Vim Window */
836 SetForegroundWindow(s_hwnd
);
838 extern Widget vimShell
;
840 XSetInputFocus(gui
.dpy
, XtWindow(vimShell
), RevertToNone
,
842 XRaiseWindow(gui
.dpy
, XtWindow(vimShell
));
848 case 'p' : /* path of file has changed */
849 /* when changing from shared to private WS (checkout) */
851 char *file
= argv
[0];
852 char *new_path
= argv
[1];
854 buf
= vi_find_buffer(file
);
855 if (buf
&& !buf
->b_changed
) /* delete buffer only if not modified */
857 vim_snprintf(VICommand
, sizeof(VICommand
),
858 (char *)DeleteBuf
, file
);
859 vi_exec_cmd(VICommand
);
861 vi_open_file(new_path
);
864 case 'w' : /* writability has changed */
865 /* Sniff sends request twice,
866 * but only the last one is the right one */
868 char *file
= argv
[0];
869 int writable
= atoi(argv
[1]);
871 buf
= vi_find_buffer(file
);
874 buf
->b_p_ro
= !writable
;
877 buf
->b_flags
|= BF_CHECK_RO
+ BF_NEVERLOADED
;
878 if (writable
&& !buf
->b_changed
)
880 vim_snprintf(VICommand
, sizeof(VICommand
),
881 (char *)UnloadBuf
, file
);
882 vi_exec_cmd(VICommand
);
885 else if (writable
&& !buf
->b_changed
)
892 case 'h' : /* highlight info */
893 break; /* not implemented */
895 case 't' : /* Set tab width */
897 int tab_width
= atoi(argv
[1]);
899 if (tab_width
> 0 && tab_width
<= 16)
901 vim_snprintf(VICommand
, sizeof(VICommand
),
902 (char *)SetTab
, tab_width
);
903 vi_exec_cmd(VICommand
);
909 /* change the request separator */
910 sniff_rq_sep
[0] = arguments
[0];
911 /* echo the request */
912 WriteToSniff(buffer
);
915 case 'A' : /* Warning/Info msg */
917 if (!strncmp(arguments
, "Disconnected", 12))
918 sniff_disconnect(1); /* unexpected disconnection */
920 case 'a' : /* Error msg */
921 vi_error_msg(arguments
);
922 if (!strncmp(arguments
, "Cannot connect", 14))
930 vim_free(argv
[--argc
]);
936 * read string from fd up to next newline (excluding the nl),
937 * returns length of string
938 * 0 if no data available or no complete line
942 get_request(fd
, buf
, maxlen
)
947 static char inbuf
[1024];
948 static int pos
= 0, bytes
= 0;
965 for (len
= 0; len
< maxlen
; len
++)
967 if (pos
>= bytes
) /* end of buffer reached? */
970 if (select(fd
+ 1, &rfds
, NULL
, NULL
, &tval
) > 0)
972 if (poll(&fds
, 1, 0) > 0)
976 bytes
= read(fd
, inbuf
, sizeof(inbuf
));
987 if ((buf
[len
] = inbuf
[pos
++]) =='\n')
997 SendRequest(command
, symbol
)
998 struct sn_cmd
*command
;
1001 int cmd_type
= command
->cmd_type
;
1002 static char cmdstr
[MAX_REQUEST_LEN
];
1003 static char msgtxt
[MAX_REQUEST_LEN
];
1004 char *buffer_name
= NULL
;
1006 if (cmd_type
== RQ_CONNECT
)
1011 if (!sniff_connected
&& !(cmd_type
& SILENT
))
1013 vi_error_msg(_("E278: SNiFF+ not connected"));
1017 if (cmd_type
& NEED_FILE
)
1019 if (!curbuf
->b_sniff
)
1021 if (!(cmd_type
& SILENT
))
1022 vi_error_msg(_("E279: Not a SNiFF+ buffer"));
1025 buffer_name
= vi_buffer_name();
1026 if (buffer_name
== NULL
)
1028 if (cmd_type
& NEED_SYMBOL
)
1030 if (cmd_type
& EMPTY_SYMBOL
)
1032 else if (!symbol
&& !(symbol
= vi_symbol_under_cursor()))
1033 return; /* error msg already displayed */
1037 vim_snprintf(cmdstr
, sizeof(cmdstr
), "%c%s%s%ld%s%s\n",
1046 vim_snprintf(cmdstr
, sizeof(cmdstr
), "%c%s\n",
1047 command
->cmd_code
, buffer_name
);
1049 else /* simple request */
1051 cmdstr
[0] = command
->cmd_code
;
1055 if (command
->cmd_msg
&& !(cmd_type
& SILENT
))
1057 if ((cmd_type
& NEED_SYMBOL
) && !(cmd_type
& EMPTY_SYMBOL
))
1059 vim_snprintf(msgtxt
, sizeof(msgtxt
), "%s: %s",
1060 _(command
->cmd_msg
), symbol
);
1064 vi_msg(_(command
->cmd_msg
));
1066 WriteToSniff(cmdstr
);
1067 if (cmd_type
& DISCONNECT
)
1068 sniff_disconnect(0);
1079 if (! WriteFile(handle_to_sniff
, str
, strlen(str
), &bytes
, NULL
))
1081 DWORD err
=GetLastError();
1085 bytes
= write(fd_to_sniff
, str
, strlen(str
));
1089 vi_msg(_("Sniff: Error during write. Disconnected"));
1090 sniff_disconnect(1);
1094 /*-------- vim helping functions --------------------------------*/
1100 if (str
!= NULL
&& *str
!= NUL
)
1108 if (str
!= NULL
&& *str
!= NUL
)
1109 EMSG((char_u
*)str
);
1117 do_ecmd(0, (char_u
*)fname
, NULL
, NULL
, ECMD_ONE
, ECMD_HIDE
+ECMD_OLDBUF
,
1119 curbuf
->b_sniff
= TRUE
;
1120 --no_wait_return
; /* [ex_docmd.c] */
1124 vi_find_buffer(fname
)
1126 { /* derived from buflist_findname() [buffer.c] */
1129 for (buf
= firstbuf
; buf
!= NULL
; buf
= buf
->b_next
)
1130 if (buf
->b_sfname
!= NULL
&& fnamecmp(fname
, buf
->b_sfname
) == 0)
1137 vi_symbol_under_cursor()
1142 static char sniff_symbol
[256];
1144 len
= find_ident_under_cursor((char_u
**)&symbolp
, FIND_IDENT
);
1148 for (p
=sniff_symbol
; len
; len
--)
1151 return sniff_symbol
;
1158 return (char *)curbuf
->b_sfname
;
1165 do_cmdline_cmd((char_u
*)vicmd
); /* [ex_docmd.c] */
1169 * Set cursor on character position
1170 * derived from cursor_pos_info() [buffer.c]
1173 vi_set_cursor_pos(char_pos
)
1177 long char_count
= 1; /* first position = 1 */
1185 if (get_fileformat(curbuf
) == EOL_DOS
)
1189 for (lnum
= 1; lnum
<= curbuf
->b_ml
.ml_line_count
; ++lnum
)
1191 line_size
= STRLEN(ml_get(lnum
)) + eol_size
;
1192 if (char_count
+line_size
> char_pos
) break;
1193 char_count
+= line_size
;
1195 curwin
->w_cursor
.lnum
= lnum
;
1196 curwin
->w_cursor
.col
= char_pos
- char_count
;
1203 long char_count
=1; /* sniff starts with pos 1 */
1211 for (lnum
= 1; lnum
< curwin
->w_cursor
.lnum
; ++lnum
)
1213 line_size
= STRLEN(ml_get(lnum
)) + eol_size
;
1214 char_count
+= line_size
;
1216 return char_count
+ curwin
->w_cursor
.col
;