blob: 9a9181c0ac42771d53760a33794bb722f884c05b [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 * Netbeans integration by David Weatherford
5 * Adopted for Win32 by Sergey Khorev
6 *
7 * Do ":help uganda" in Vim to read copying and usage conditions.
8 * Do ":help credits" in Vim to see a list of people who contributed.
9 */
10
11/*
12 * Implements client side of org.netbeans.modules.emacs editor
13 * integration protocol. Be careful! The protocol uses offsets
14 * which are *between* characters, whereas vim uses line number
15 * and column number which are *on* characters.
16 * See ":help netbeans-protocol" for explanation.
Bram Moolenaare3cc6d42011-10-20 21:58:34 +020017 *
18 * The Netbeans messages are received and queued in the gui event loop, or in
19 * the select loop when Vim runs in a terminal. These messages are processed
20 * by netbeans_parse_messages() which is invoked in the idle loop when Vim is
21 * waiting for user input. The function netbeans_parse_messages() is also
22 * called from the ":sleep" command, to allow the execution of test cases that
23 * may not invoke the idle loop.
Bram Moolenaar071d4272004-06-13 20:20:40 +000024 */
25
26#include "vim.h"
27
28#if defined(FEAT_NETBEANS_INTG) || defined(PROTO)
29
Bram Moolenaard04a0202016-01-26 23:30:18 +010030#ifndef WIN32
Bram Moolenaar3e53c702016-01-24 22:17:03 +010031# include <netdb.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000032# ifdef HAVE_LIBGEN_H
33# include <libgen.h>
34# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000035#endif
36
37#include "version.h"
38
Bram Moolenaar071d4272004-06-13 20:20:40 +000039#define GUARDED 10000 /* typenr for "guarded" annotation */
40#define GUARDEDOFFSET 1000000 /* base for "guarded" sign id's */
Bram Moolenaar67c53842010-05-22 18:28:27 +020041#define MAX_COLOR_LENGTH 32 /* max length of color name in defineAnnoType */
Bram Moolenaar071d4272004-06-13 20:20:40 +000042
43/* The first implementation (working only with Netbeans) returned "1.1". The
44 * protocol implemented here also supports A-A-P. */
Bram Moolenaar67c53842010-05-22 18:28:27 +020045static char *ExtEdProtocolVersion = "2.5";
Bram Moolenaar071d4272004-06-13 20:20:40 +000046
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010047static long pos2off(buf_T *, pos_T *);
48static pos_T *off2pos(buf_T *, long);
49static pos_T *get_off_or_lnum(buf_T *buf, char_u **argp);
50static long get_buf_size(buf_T *);
51static int netbeans_keystring(char_u *keystr);
52static void postpone_keycommand(char_u *keystr);
53static void special_keys(char_u *args);
Bram Moolenaar071d4272004-06-13 20:20:40 +000054
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010055static int netbeans_connect(char *, int);
56static int getConnInfo(char *file, char **host, char **port, char **password);
Bram Moolenaar071d4272004-06-13 20:20:40 +000057
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +010058static void nb_init_graphics(void);
59static void coloncmd(char *cmd, ...);
60static void nb_set_curbuf(buf_T *buf);
61static void nb_parse_cmd(char_u *);
62static int nb_do_cmd(int, char_u *, int, int, char_u *);
63static void nb_send(char *buf, char *fun);
64static void nb_free(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +000065
Bram Moolenaar77073442016-02-13 23:23:53 +010066#define NETBEANS_OPEN (channel_can_write_to(nb_channel))
67static channel_T *nb_channel = NULL;
Bram Moolenaar67c53842010-05-22 18:28:27 +020068
Bram Moolenaar89d40322006-08-29 15:30:07 +000069static int r_cmdno; /* current command number for reply */
Bram Moolenaar009b2592004-10-24 19:18:58 +000070static int dosetvisible = FALSE;
71
Bram Moolenaar071d4272004-06-13 20:20:40 +000072/*
73 * Include the debugging code if wanted.
74 */
75#ifdef NBDEBUG
76# include "nbdebug.c"
77#endif
78
Bram Moolenaarb26e6322010-05-22 21:34:09 +020079static int needupdate = 0;
80static int inAtomic = 0;
81
Bram Moolenaar7ad7d012010-11-16 15:49:02 +010082/*
Bram Moolenaard04a0202016-01-26 23:30:18 +010083 * Callback invoked when the channel is closed.
Bram Moolenaar7ad7d012010-11-16 15:49:02 +010084 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000085 static void
Bram Moolenaard04a0202016-01-26 23:30:18 +010086nb_channel_closed(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +000087{
Bram Moolenaar77073442016-02-13 23:23:53 +010088 nb_channel = NULL;
Bram Moolenaar7ad7d012010-11-16 15:49:02 +010089}
90
91/*
92 * Close the connection and cleanup.
Bram Moolenaard04a0202016-01-26 23:30:18 +010093 * May be called when the socket was closed earlier.
Bram Moolenaar7ad7d012010-11-16 15:49:02 +010094 */
95 static void
96netbeans_close(void)
97{
98 if (NETBEANS_OPEN)
99 {
100 netbeans_send_disconnect();
Bram Moolenaar77073442016-02-13 23:23:53 +0100101 if (nb_channel != NULL)
Bram Moolenaar187db502016-02-27 14:44:26 +0100102 {
Bram Moolenaard04a0202016-01-26 23:30:18 +0100103 /* Close the socket and remove the input handlers. */
Bram Moolenaar8b374212016-02-24 20:43:06 +0100104 channel_close(nb_channel, TRUE);
Bram Moolenaar187db502016-02-27 14:44:26 +0100105 channel_clear(nb_channel);
106 }
Bram Moolenaar77073442016-02-13 23:23:53 +0100107 nb_channel = NULL;
Bram Moolenaar7ad7d012010-11-16 15:49:02 +0100108 }
109
Bram Moolenaar67c53842010-05-22 18:28:27 +0200110#ifdef FEAT_BEVAL
Bram Moolenaard62bec82005-03-07 22:56:57 +0000111 bevalServers &= ~BEVAL_NETBEANS;
Bram Moolenaar67c53842010-05-22 18:28:27 +0200112#endif
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200113
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200114 needupdate = 0;
115 inAtomic = 0;
116 nb_free();
117
118 /* remove all signs and update the screen after gutter removal */
119 coloncmd(":sign unplace *");
120 changed_window_setting();
121 update_screen(CLEAR);
122 setcursor();
Bram Moolenaar96bcc5e2011-04-01 15:33:59 +0200123 cursor_on();
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200124 out_flush();
125#ifdef FEAT_GUI
Bram Moolenaard54a6882010-08-09 22:49:00 +0200126 if (gui.in_use)
127 {
128 gui_update_cursor(TRUE, FALSE);
129 gui_mch_flush();
130 }
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200131#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000132}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000133
134#define NB_DEF_HOST "localhost"
135#define NB_DEF_ADDR "3219"
136#define NB_DEF_PASS "changeme"
137
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200138 static int
Bram Moolenaarf506c5b2010-06-22 06:28:58 +0200139netbeans_connect(char *params, int doabort)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140{
Bram Moolenaard04a0202016-01-26 23:30:18 +0100141 int port;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000142 char buf[32];
143 char *hostname = NULL;
144 char *address = NULL;
145 char *password = NULL;
146 char *fname;
147 char *arg = NULL;
148
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200149 if (*params == '=')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000150 {
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200151 /* "=fname": Read info from specified file. */
Bram Moolenaare0874f82016-01-24 20:36:41 +0100152 if (getConnInfo(params + 1, &hostname, &address, &password) == FAIL)
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200153 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000154 }
155 else
156 {
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200157 if (*params == ':')
158 /* ":<host>:<addr>:<password>": get info from argument */
159 arg = params + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000160 if (arg == NULL && (fname = getenv("__NETBEANS_CONINFO")) != NULL)
161 {
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200162 /* "": get info from file specified in environment */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000163 if (getConnInfo(fname, &hostname, &address, &password) == FAIL)
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200164 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000165 }
166 else
167 {
168 if (arg != NULL)
169 {
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200170 /* ":<host>:<addr>:<password>": get info from argument */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000171 hostname = arg;
172 address = strchr(hostname, ':');
173 if (address != NULL)
174 {
175 *address++ = '\0';
176 password = strchr(address, ':');
177 if (password != NULL)
178 *password++ = '\0';
179 }
180 }
181
182 /* Get the missing values from the environment. */
183 if (hostname == NULL || *hostname == '\0')
184 hostname = getenv("__NETBEANS_HOST");
185 if (address == NULL)
186 address = getenv("__NETBEANS_SOCKET");
187 if (password == NULL)
188 password = getenv("__NETBEANS_VIM_PASSWORD");
189
190 /* Move values to allocated memory. */
191 if (hostname != NULL)
192 hostname = (char *)vim_strsave((char_u *)hostname);
193 if (address != NULL)
194 address = (char *)vim_strsave((char_u *)address);
195 if (password != NULL)
196 password = (char *)vim_strsave((char_u *)password);
197 }
198 }
199
200 /* Use the default when a value is missing. */
201 if (hostname == NULL || *hostname == '\0')
202 {
203 vim_free(hostname);
204 hostname = (char *)vim_strsave((char_u *)NB_DEF_HOST);
205 }
206 if (address == NULL || *address == '\0')
207 {
208 vim_free(address);
209 address = (char *)vim_strsave((char_u *)NB_DEF_ADDR);
210 }
211 if (password == NULL || *password == '\0')
212 {
213 vim_free(password);
214 password = (char *)vim_strsave((char_u *)NB_DEF_PASS);
215 }
Bram Moolenaard04a0202016-01-26 23:30:18 +0100216 if (hostname != NULL && address != NULL && password != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000217 {
Bram Moolenaard04a0202016-01-26 23:30:18 +0100218 port = atoi(address);
Bram Moolenaar81661fb2016-02-18 22:23:34 +0100219 nb_channel = channel_open(hostname, port, 3000, nb_channel_closed);
Bram Moolenaar77073442016-02-13 23:23:53 +0100220 if (nb_channel != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000221 {
Bram Moolenaard04a0202016-01-26 23:30:18 +0100222 /* success */
223# ifdef FEAT_BEVAL
224 bevalServers |= BEVAL_NETBEANS;
225# endif
Bram Moolenaarc39125d2010-05-23 12:06:58 +0200226
Bram Moolenaard04a0202016-01-26 23:30:18 +0100227 /* success, login */
228 vim_snprintf(buf, sizeof(buf), "AUTH %s\n", password);
229 nb_send(buf, "netbeans_connect");
230
231 sprintf(buf, "0:version=0 \"%s\"\n", ExtEdProtocolVersion);
232 nb_send(buf, "externaleditor_version");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000233 }
234 }
235
Bram Moolenaar77073442016-02-13 23:23:53 +0100236 if (nb_channel == NULL && doabort)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100237 getout(1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000238
Bram Moolenaar071d4272004-06-13 20:20:40 +0000239 vim_free(hostname);
240 vim_free(address);
241 vim_free(password);
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200242 return NETBEANS_OPEN ? OK : FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000243}
244
245/*
246 * Obtain the NetBeans hostname, port address and password from a file.
247 * Return the strings in allocated memory.
248 * Return FAIL if the file could not be read, OK otherwise (no matter what it
249 * contains).
250 */
251 static int
252getConnInfo(char *file, char **host, char **port, char **auth)
253{
254 FILE *fp;
255 char_u buf[BUFSIZ];
256 char_u *lp;
Bram Moolenaar309cbc32012-01-10 22:31:31 +0100257 char_u *nlp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000258#ifdef UNIX
259 struct stat st;
260
261 /*
262 * For Unix only accept the file when it's not accessible by others.
263 * The open will then fail if we don't own the file.
264 */
265 if (mch_stat(file, &st) == 0 && (st.st_mode & 0077) != 0)
266 {
Bram Moolenaarf2330482008-06-24 20:19:36 +0000267 nbdebug(("Wrong access mode for NetBeans connection info file: \"%s\"\n",
268 file));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000269 EMSG2(_("E668: Wrong access mode for NetBeans connection info file: \"%s\""),
270 file);
271 return FAIL;
272 }
273#endif
274
275 fp = mch_fopen(file, "r");
276 if (fp == NULL)
277 {
Bram Moolenaarf2330482008-06-24 20:19:36 +0000278 nbdebug(("Cannot open NetBeans connection info file\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000279 PERROR("E660: Cannot open NetBeans connection info file");
280 return FAIL;
281 }
282
283 /* Read the file. There should be one of each parameter */
284 while ((lp = (char_u *)fgets((char *)buf, BUFSIZ, fp)) != NULL)
285 {
Bram Moolenaar309cbc32012-01-10 22:31:31 +0100286 if ((nlp = vim_strchr(lp, '\n')) != NULL)
287 *nlp = 0; /* strip off the trailing newline */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000288
289 if (STRNCMP(lp, "host=", 5) == 0)
290 {
291 vim_free(*host);
292 *host = (char *)vim_strsave(&buf[5]);
293 }
294 else if (STRNCMP(lp, "port=", 5) == 0)
295 {
296 vim_free(*port);
297 *port = (char *)vim_strsave(&buf[5]);
298 }
299 else if (STRNCMP(lp, "auth=", 5) == 0)
300 {
301 vim_free(*auth);
302 *auth = (char *)vim_strsave(&buf[5]);
303 }
304 }
305 fclose(fp);
306
307 return OK;
308}
309
310
311struct keyqueue
312{
Bram Moolenaar8065d7f2010-01-19 15:13:14 +0100313 char_u *keystr;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000314 struct keyqueue *next;
315 struct keyqueue *prev;
316};
317
318typedef struct keyqueue keyQ_T;
319
320static keyQ_T keyHead; /* dummy node, header for circular queue */
321
322
323/*
324 * Queue up key commands sent from netbeans.
Bram Moolenaar8065d7f2010-01-19 15:13:14 +0100325 * We store the string, because it may depend on the global mod_mask and
326 * :nbkey doesn't have a key number.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000327 */
328 static void
Bram Moolenaar8065d7f2010-01-19 15:13:14 +0100329postpone_keycommand(char_u *keystr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000330{
331 keyQ_T *node;
332
333 node = (keyQ_T *)alloc(sizeof(keyQ_T));
Bram Moolenaar8065d7f2010-01-19 15:13:14 +0100334 if (node == NULL)
335 return; /* out of memory, drop the key */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000336
337 if (keyHead.next == NULL) /* initialize circular queue */
338 {
339 keyHead.next = &keyHead;
340 keyHead.prev = &keyHead;
341 }
342
343 /* insert node at tail of queue */
344 node->next = &keyHead;
345 node->prev = keyHead.prev;
346 keyHead.prev->next = node;
347 keyHead.prev = node;
348
Bram Moolenaar8065d7f2010-01-19 15:13:14 +0100349 node->keystr = vim_strsave(keystr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000350}
351
352/*
353 * Handle any queued-up NetBeans keycommands to be send.
354 */
355 static void
356handle_key_queue(void)
357{
Bram Moolenaar8065d7f2010-01-19 15:13:14 +0100358 int postponed = FALSE;
359
360 while (!postponed && keyHead.next && keyHead.next != &keyHead)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000361 {
362 /* first, unlink the node */
363 keyQ_T *node = keyHead.next;
364 keyHead.next = node->next;
365 node->next->prev = node->prev;
366
Bram Moolenaar8065d7f2010-01-19 15:13:14 +0100367 /* Now, send the keycommand. This may cause it to be postponed again
368 * and change keyHead. */
369 if (node->keystr != NULL)
370 postponed = !netbeans_keystring(node->keystr);
371 vim_free(node->keystr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000372
373 /* Finally, dispose of the node */
374 vim_free(node);
375 }
376}
377
378
Bram Moolenaar071d4272004-06-13 20:20:40 +0000379/*
380 * While there's still a command in the work queue, parse and execute it.
381 */
Bram Moolenaarf2330482008-06-24 20:19:36 +0000382 void
383netbeans_parse_messages(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000384{
Bram Moolenaar5f1032d2016-06-07 22:16:36 +0200385 readq_T *node;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100386 char_u *buffer;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000387 char_u *p;
Bram Moolenaar863053d2010-12-02 17:09:54 +0100388 int own_node;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000389
Bram Moolenaar77073442016-02-13 23:23:53 +0100390 while (nb_channel != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000391 {
Bram Moolenaar5f1032d2016-06-07 22:16:36 +0200392 node = channel_peek(nb_channel, PART_SOCK);
393 if (node == NULL)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100394 break; /* nothing to read */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395
396 /* Locate the first line in the first buffer. */
Bram Moolenaar5f1032d2016-06-07 22:16:36 +0200397 p = channel_first_nl(node);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000398 if (p == NULL)
399 {
400 /* Command isn't complete. If there is no following buffer,
401 * return (wait for more). If there is another buffer following,
402 * prepend the text to that buffer and delete this one. */
Bram Moolenaar9ed96ef2016-06-04 17:17:11 +0200403 if (channel_collapse(nb_channel, PART_SOCK, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000404 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000405 }
406 else
407 {
408 /* There is a complete command at the start of the buffer.
409 * Terminate it with a NUL. When no more text is following unlink
410 * the buffer. Do this before executing, because new buffers can
411 * be added while busy handling the command. */
412 *p++ = NUL;
413 if (*p == NUL)
414 {
Bram Moolenaar863053d2010-12-02 17:09:54 +0100415 own_node = TRUE;
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100416 channel_get(nb_channel, PART_SOCK);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000417 }
Bram Moolenaar863053d2010-12-02 17:09:54 +0100418 else
419 own_node = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000420
421 /* now, parse and execute the commands */
Bram Moolenaar5f1032d2016-06-07 22:16:36 +0200422 nb_parse_cmd(node->rq_buffer);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000423
Bram Moolenaar863053d2010-12-02 17:09:54 +0100424 if (own_node)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100425 /* buffer finished, dispose of it */
Bram Moolenaar5f1032d2016-06-07 22:16:36 +0200426 vim_free(node->rq_buffer);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100427 else
428 /* more follows, move it to the start */
Bram Moolenaar5f1032d2016-06-07 22:16:36 +0200429 channel_consume(nb_channel, PART_SOCK, (int)(p - buffer));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430 }
431 }
432}
433
Bram Moolenaar071d4272004-06-13 20:20:40 +0000434/*
435 * Handle one NUL terminated command.
436 *
437 * format of a command from netbeans:
438 *
439 * 6:setTitle!84 "a.c"
440 *
441 * bufno
442 * colon
443 * cmd
444 * !
445 * cmdno
446 * args
447 *
448 * for function calls, the ! is replaced by a /
449 */
450 static void
451nb_parse_cmd(char_u *cmd)
452{
Bram Moolenaar349b2f62004-10-11 10:00:50 +0000453 char *verb;
454 char *q;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000455 int bufno;
456 int isfunc = -1;
457
458 if (STRCMP(cmd, "DISCONNECT") == 0)
459 {
460 /* We assume the server knows that we can safely exit! */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000461 /* Disconnect before exiting, Motif hangs in a Select error
462 * message otherwise. */
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200463 netbeans_close();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000464 getout(0);
465 /* NOTREACHED */
466 }
467
Bram Moolenaareed284a2016-02-22 23:13:33 +0100468 if (STRCMP(cmd, "DETACH") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000469 {
Bram Moolenaard04a0202016-01-26 23:30:18 +0100470 buf_T *buf;
471
472 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
473 buf->b_has_sign_column = FALSE;
474
Bram Moolenaar071d4272004-06-13 20:20:40 +0000475 /* The IDE is breaking the connection. */
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200476 netbeans_close();
Bram Moolenaar071d4272004-06-13 20:20:40 +0000477 return;
478 }
479
Bram Moolenaar349b2f62004-10-11 10:00:50 +0000480 bufno = strtol((char *)cmd, &verb, 10);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000481
482 if (*verb != ':')
483 {
Bram Moolenaarf2330482008-06-24 20:19:36 +0000484 nbdebug((" missing colon: %s\n", cmd));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000485 EMSG2("E627: missing colon: %s", cmd);
486 return;
487 }
488 ++verb; /* skip colon */
489
490 for (q = verb; *q; q++)
491 {
492 if (*q == '!')
493 {
494 *q++ = NUL;
495 isfunc = 0;
496 break;
497 }
498 else if (*q == '/')
499 {
500 *q++ = NUL;
501 isfunc = 1;
502 break;
503 }
504 }
505
506 if (isfunc < 0)
507 {
Bram Moolenaarf2330482008-06-24 20:19:36 +0000508 nbdebug((" missing ! or / in: %s\n", cmd));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000509 EMSG2("E628: missing ! or / in: %s", cmd);
510 return;
511 }
512
Bram Moolenaar89d40322006-08-29 15:30:07 +0000513 r_cmdno = strtol(q, &q, 10);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000514
Bram Moolenaar349b2f62004-10-11 10:00:50 +0000515 q = (char *)skipwhite((char_u *)q);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000516
Bram Moolenaar89d40322006-08-29 15:30:07 +0000517 if (nb_do_cmd(bufno, (char_u *)verb, isfunc, r_cmdno, (char_u *)q) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000518 {
Bram Moolenaar009b2592004-10-24 19:18:58 +0000519#ifdef NBDEBUG
520 /*
Bram Moolenaar2660c0e2010-01-19 14:59:56 +0100521 * This happens because the ExtEd can send a command or 2 after
Bram Moolenaar009b2592004-10-24 19:18:58 +0000522 * doing a stopDocumentListen command. It doesn't harm anything
523 * so I'm disabling it except for debugging.
524 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000525 nbdebug(("nb_parse_cmd: Command error for \"%s\"\n", cmd));
526 EMSG("E629: bad return from nb_do_cmd");
Bram Moolenaar009b2592004-10-24 19:18:58 +0000527#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000528 }
529}
530
531struct nbbuf_struct
532{
533 buf_T *bufp;
534 unsigned int fireChanges:1;
535 unsigned int initDone:1;
Bram Moolenaar009b2592004-10-24 19:18:58 +0000536 unsigned int insertDone:1;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000537 unsigned int modified:1;
Bram Moolenaar009b2592004-10-24 19:18:58 +0000538 int nbbuf_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000539 char *displayname;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000540 int *signmap;
541 short_u signmaplen;
542 short_u signmapused;
543};
544
545typedef struct nbbuf_struct nbbuf_T;
546
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200547static nbbuf_T *buf_list = NULL;
Bram Moolenaard857f0e2005-06-21 22:37:39 +0000548static int buf_list_size = 0; /* size of buf_list */
549static int buf_list_used = 0; /* nr of entries in buf_list actually in use */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000550
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200551static char **globalsignmap = NULL;
552static int globalsignmaplen = 0;
553static int globalsignmapused = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000554
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +0100555static int mapsigntype(nbbuf_T *, int localsigntype);
556static void addsigntype(nbbuf_T *, int localsigntype, char_u *typeName,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000557 char_u *tooltip, char_u *glyphfile,
Bram Moolenaar92b8b2d2016-01-29 22:36:45 +0100558 char_u *fg, char_u *bg);
559static void print_read_msg(nbbuf_T *buf);
560static void print_save_msg(nbbuf_T *buf, off_t nchars);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000561
562static int curPCtype = -1;
563
564/*
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200565 * Free netbeans resources.
566 */
567 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +0100568nb_free(void)
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200569{
570 keyQ_T *key_node = keyHead.next;
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200571 nbbuf_T buf;
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200572 int i;
573
574 /* free the netbeans buffer list */
575 for (i = 0; i < buf_list_used; i++)
576 {
577 buf = buf_list[i];
578 vim_free(buf.displayname);
579 vim_free(buf.signmap);
Bram Moolenaare980d8a2010-12-08 13:11:21 +0100580 if (buf.bufp != NULL)
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200581 {
582 buf.bufp->b_netbeans_file = FALSE;
583 buf.bufp->b_was_netbeans_file = FALSE;
584 }
585 }
586 vim_free(buf_list);
587 buf_list = NULL;
588 buf_list_size = 0;
589 buf_list_used = 0;
590
591 /* free the queued key commands */
Bram Moolenaar8d4eecc2012-11-20 17:19:01 +0100592 while (key_node != NULL && key_node != &keyHead)
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200593 {
594 keyQ_T *next = key_node->next;
595 vim_free(key_node->keystr);
596 vim_free(key_node);
597 if (next == &keyHead)
598 {
599 keyHead.next = &keyHead;
600 keyHead.prev = &keyHead;
601 break;
602 }
603 key_node = next;
604 }
605
606 /* free the queued netbeans commands */
Bram Moolenaar77073442016-02-13 23:23:53 +0100607 if (nb_channel != NULL)
608 channel_clear(nb_channel);
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200609}
610
611/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000612 * Get the Netbeans buffer number for the specified buffer.
613 */
614 static int
615nb_getbufno(buf_T *bufp)
616{
617 int i;
618
619 for (i = 0; i < buf_list_used; i++)
620 if (buf_list[i].bufp == bufp)
621 return i;
622 return -1;
623}
624
625/*
626 * Is this a NetBeans-owned buffer?
627 */
628 int
629isNetbeansBuffer(buf_T *bufp)
630{
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200631 return NETBEANS_OPEN && bufp->b_netbeans_file;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000632}
633
634/*
635 * NetBeans and Vim have different undo models. In Vim, the file isn't
636 * changed if changes are undone via the undo command. In NetBeans, once
637 * a change has been made the file is marked as modified until saved. It
638 * doesn't matter if the change was undone.
639 *
640 * So this function is for the corner case where Vim thinks a buffer is
641 * unmodified but NetBeans thinks it IS modified.
642 */
643 int
644isNetbeansModified(buf_T *bufp)
645{
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200646 if (isNetbeansBuffer(bufp))
Bram Moolenaar009b2592004-10-24 19:18:58 +0000647 {
648 int bufno = nb_getbufno(bufp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649
Bram Moolenaar009b2592004-10-24 19:18:58 +0000650 if (bufno > 0)
651 return buf_list[bufno].modified;
652 else
653 return FALSE;
654 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000655 else
656 return FALSE;
657}
658
659/*
660 * Given a Netbeans buffer number, return the netbeans buffer.
661 * Returns NULL for 0 or a negative number. A 0 bufno means a
662 * non-buffer related command has been sent.
663 */
664 static nbbuf_T *
665nb_get_buf(int bufno)
666{
667 /* find or create a buffer with the given number */
668 int incr;
669
670 if (bufno <= 0)
671 return NULL;
672
673 if (!buf_list)
674 {
675 /* initialize */
676 buf_list = (nbbuf_T *)alloc_clear(100 * sizeof(nbbuf_T));
677 buf_list_size = 100;
678 }
679 if (bufno >= buf_list_used) /* new */
680 {
681 if (bufno >= buf_list_size) /* grow list */
682 {
Bram Moolenaar9abd5c62015-02-10 18:34:01 +0100683 nbbuf_T *t_buf_list = buf_list;
684
Bram Moolenaar071d4272004-06-13 20:20:40 +0000685 incr = bufno - buf_list_size + 90;
686 buf_list_size += incr;
687 buf_list = (nbbuf_T *)vim_realloc(
688 buf_list, buf_list_size * sizeof(nbbuf_T));
Bram Moolenaar9abd5c62015-02-10 18:34:01 +0100689 if (buf_list == NULL)
690 {
691 vim_free(t_buf_list);
692 buf_list_size = 0;
693 return NULL;
694 }
Bram Moolenaar7db5fc82010-05-24 11:59:29 +0200695 vim_memset(buf_list + buf_list_size - incr, 0,
696 incr * sizeof(nbbuf_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000697 }
698
699 while (buf_list_used <= bufno)
700 {
701 /* Default is to fire text changes. */
702 buf_list[buf_list_used].fireChanges = 1;
703 ++buf_list_used;
704 }
705 }
706
707 return buf_list + bufno;
708}
709
710/*
711 * Return the number of buffers that are modified.
712 */
713 static int
714count_changed_buffers(void)
715{
716 buf_T *bufp;
717 int n;
718
719 n = 0;
720 for (bufp = firstbuf; bufp != NULL; bufp = bufp->b_next)
721 if (bufp->b_changed)
722 ++n;
723 return n;
724}
725
726/*
727 * End the netbeans session.
728 */
729 void
730netbeans_end(void)
731{
732 int i;
733 static char buf[128];
734
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200735 if (!NETBEANS_OPEN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000736 return;
737
738 for (i = 0; i < buf_list_used; i++)
739 {
740 if (!buf_list[i].bufp)
741 continue;
742 if (netbeansForcedQuit)
743 {
744 /* mark as unmodified so NetBeans won't put up dialog on "killed" */
Bram Moolenaar89d40322006-08-29 15:30:07 +0000745 sprintf(buf, "%d:unmodified=%d\n", i, r_cmdno);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000746 nbdebug(("EVT: %s", buf));
747 nb_send(buf, "netbeans_end");
748 }
Bram Moolenaar89d40322006-08-29 15:30:07 +0000749 sprintf(buf, "%d:killed=%d\n", i, r_cmdno);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000750 nbdebug(("EVT: %s", buf));
Bram Moolenaarb26e6322010-05-22 21:34:09 +0200751 /* nb_send(buf, "netbeans_end"); avoid "write failed" messages */
Bram Moolenaard04a0202016-01-26 23:30:18 +0100752 nb_send(buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000753 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000754}
755
756/*
757 * Send a message to netbeans.
Bram Moolenaard04a0202016-01-26 23:30:18 +0100758 * When "fun" is NULL no error is given.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000759 */
760 static void
761nb_send(char *buf, char *fun)
762{
Bram Moolenaar77073442016-02-13 23:23:53 +0100763 if (nb_channel != NULL)
Bram Moolenaar42d38a22016-02-20 18:18:59 +0100764 channel_send(nb_channel, PART_SOCK, (char_u *)buf, fun);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000765}
766
767/*
768 * Some input received from netbeans requires a response. This function
769 * handles a response with no information (except the command number).
770 */
771 static void
772nb_reply_nil(int cmdno)
773{
774 char reply[32];
775
Bram Moolenaar009b2592004-10-24 19:18:58 +0000776 nbdebug(("REP %d: <none>\n", cmdno));
777
Bram Moolenaar7ad7d012010-11-16 15:49:02 +0100778 /* Avoid printing an annoying error message. */
779 if (!NETBEANS_OPEN)
780 return;
781
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782 sprintf(reply, "%d\n", cmdno);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000783 nb_send(reply, "nb_reply_nil");
784}
785
786
787/*
788 * Send a response with text.
789 * "result" must have been quoted already (using nb_quote()).
790 */
791 static void
792nb_reply_text(int cmdno, char_u *result)
793{
794 char_u *reply;
795
Bram Moolenaar009b2592004-10-24 19:18:58 +0000796 nbdebug(("REP %d: %s\n", cmdno, (char *)result));
797
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000798 reply = alloc((unsigned)STRLEN(result) + 32);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000799 sprintf((char *)reply, "%d %s\n", cmdno, (char *)result);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800 nb_send((char *)reply, "nb_reply_text");
801
802 vim_free(reply);
803}
804
805
806/*
807 * Send a response with a number result code.
808 */
809 static void
810nb_reply_nr(int cmdno, long result)
811{
812 char reply[32];
813
Bram Moolenaar009b2592004-10-24 19:18:58 +0000814 nbdebug(("REP %d: %ld\n", cmdno, result));
815
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 sprintf(reply, "%d %ld\n", cmdno, result);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000817 nb_send(reply, "nb_reply_nr");
818}
819
820
821/*
822 * Encode newline, ret, backslash, double quote for transmission to NetBeans.
823 */
824 static char_u *
825nb_quote(char_u *txt)
826{
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000827 char_u *buf = alloc((unsigned)(2 * STRLEN(txt) + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 char_u *p = txt;
829 char_u *q = buf;
830
831 if (buf == NULL)
832 return NULL;
833 for (; *p; p++)
834 {
835 switch (*p)
836 {
837 case '\"':
838 case '\\':
839 *q++ = '\\'; *q++ = *p; break;
840 /* case '\t': */
841 /* *q++ = '\\'; *q++ = 't'; break; */
842 case '\n':
843 *q++ = '\\'; *q++ = 'n'; break;
844 case '\r':
845 *q++ = '\\'; *q++ = 'r'; break;
846 default:
847 *q++ = *p;
848 break;
849 }
850 }
Bram Moolenaar2660c0e2010-01-19 14:59:56 +0100851 *q = '\0';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852
853 return buf;
854}
855
856
857/*
858 * Remove top level double quotes; convert backslashed chars.
859 * Returns an allocated string (NULL for failure).
860 * If "endp" is not NULL it is set to the character after the terminating
861 * quote.
862 */
863 static char *
864nb_unquote(char_u *p, char_u **endp)
865{
866 char *result = 0;
867 char *q;
868 int done = 0;
869
870 /* result is never longer than input */
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000871 result = (char *)alloc_clear((unsigned)STRLEN(p) + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000872 if (result == NULL)
873 return NULL;
874
875 if (*p++ != '"')
876 {
877 nbdebug(("nb_unquote called with string that doesn't start with a quote!: %s\n",
878 p));
879 result[0] = NUL;
880 return result;
881 }
882
883 for (q = result; !done && *p != NUL;)
884 {
885 switch (*p)
886 {
887 case '"':
888 /*
889 * Unbackslashed dquote marks the end, if first char was dquote.
890 */
891 done = 1;
892 break;
893
894 case '\\':
895 ++p;
896 switch (*p)
897 {
898 case '\\': *q++ = '\\'; break;
899 case 'n': *q++ = '\n'; break;
900 case 't': *q++ = '\t'; break;
901 case 'r': *q++ = '\r'; break;
902 case '"': *q++ = '"'; break;
903 case NUL: --p; break;
904 /* default: skip over illegal chars */
905 }
906 ++p;
907 break;
908
909 default:
910 *q++ = *p++;
911 }
912 }
913
914 if (endp != NULL)
915 *endp = p;
916
917 return result;
918}
919
Bram Moolenaar5eaf8722008-01-05 17:07:13 +0000920/*
921 * Remove from "first" byte to "last" byte (inclusive), at line "lnum" of the
922 * current buffer. Remove to end of line when "last" is MAXCOL.
923 */
924 static void
925nb_partialremove(linenr_T lnum, colnr_T first, colnr_T last)
926{
927 char_u *oldtext, *newtext;
928 int oldlen;
929 int lastbyte = last;
930
931 oldtext = ml_get(lnum);
Bram Moolenaarcb4cef22008-03-16 15:04:34 +0000932 oldlen = (int)STRLEN(oldtext);
Bram Moolenaarb3c70982008-01-18 10:40:55 +0000933 if (first >= (colnr_T)oldlen || oldlen == 0) /* just in case */
Bram Moolenaar5eaf8722008-01-05 17:07:13 +0000934 return;
935 if (lastbyte >= oldlen)
936 lastbyte = oldlen - 1;
937 newtext = alloc(oldlen - (int)(lastbyte - first));
938 if (newtext != NULL)
939 {
940 mch_memmove(newtext, oldtext, first);
Bram Moolenaarf2330482008-06-24 20:19:36 +0000941 STRMOVE(newtext + first, oldtext + lastbyte + 1);
Bram Moolenaar5eaf8722008-01-05 17:07:13 +0000942 nbdebug((" NEW LINE %d: %s\n", lnum, newtext));
943 ml_replace(lnum, newtext, FALSE);
944 }
945}
946
947/*
948 * Replace the "first" line with the concatenation of the "first" and
949 * the "other" line. The "other" line is not removed.
950 */
951 static void
952nb_joinlines(linenr_T first, linenr_T other)
953{
954 int len_first, len_other;
955 char_u *p;
956
Bram Moolenaarcb4cef22008-03-16 15:04:34 +0000957 len_first = (int)STRLEN(ml_get(first));
958 len_other = (int)STRLEN(ml_get(other));
Bram Moolenaar5eaf8722008-01-05 17:07:13 +0000959 p = alloc((unsigned)(len_first + len_other + 1));
960 if (p != NULL)
961 {
962 mch_memmove(p, ml_get(first), len_first);
963 mch_memmove(p + len_first, ml_get(other), len_other + 1);
964 ml_replace(first, p, FALSE);
965 }
966}
967
Bram Moolenaar071d4272004-06-13 20:20:40 +0000968#define SKIP_STOP 2
969#define streq(a,b) (strcmp(a,b) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970
971/*
972 * Do the actual processing of a single netbeans command or function.
Bram Moolenaar143c38c2007-05-10 16:41:10 +0000973 * The difference between a command and function is that a function
974 * gets a response (it's required) but a command does not.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000975 * For arguments see comment for nb_parse_cmd().
976 */
977 static int
978nb_do_cmd(
979 int bufno,
980 char_u *cmd,
981 int func,
982 int cmdno,
983 char_u *args) /* points to space before arguments or NUL */
984{
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100985 int do_update = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986 long off = 0;
987 nbbuf_T *buf = nb_get_buf(bufno);
988 static int skip = 0;
989 int retval = OK;
Bram Moolenaar349b2f62004-10-11 10:00:50 +0000990 char *cp; /* for when a char pointer is needed */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000991
992 nbdebug(("%s %d: (%d) %s %s\n", (func) ? "FUN" : "CMD", cmdno, bufno, cmd,
993 STRCMP(cmd, "insert") == 0 ? "<text>" : (char *)args));
994
995 if (func)
996 {
997/* =====================================================================*/
998 if (streq((char *)cmd, "getModified"))
999 {
1000 if (buf == NULL || buf->bufp == NULL)
1001 /* Return the number of buffers that are modified. */
1002 nb_reply_nr(cmdno, (long)count_changed_buffers());
1003 else
1004 /* Return whether the buffer is modified. */
1005 nb_reply_nr(cmdno, (long)(buf->bufp->b_changed
1006 || isNetbeansModified(buf->bufp)));
1007/* =====================================================================*/
1008 }
1009 else if (streq((char *)cmd, "saveAndExit"))
1010 {
1011 /* Note: this will exit Vim if successful. */
1012 coloncmd(":confirm qall");
1013
1014 /* We didn't exit: return the number of changed buffers. */
1015 nb_reply_nr(cmdno, (long)count_changed_buffers());
1016/* =====================================================================*/
1017 }
1018 else if (streq((char *)cmd, "getCursor"))
1019 {
1020 char_u text[200];
1021
1022 /* Note: nb_getbufno() may return -1. This indicates the IDE
1023 * didn't assign a number to the current buffer in response to a
1024 * fileOpened event. */
1025 sprintf((char *)text, "%d %ld %d %ld",
1026 nb_getbufno(curbuf),
1027 (long)curwin->w_cursor.lnum,
1028 (int)curwin->w_cursor.col,
1029 pos2off(curbuf, &curwin->w_cursor));
1030 nb_reply_text(cmdno, text);
1031/* =====================================================================*/
1032 }
Bram Moolenaarc65c4912006-11-14 17:29:46 +00001033 else if (streq((char *)cmd, "getAnno"))
1034 {
1035 long linenum = 0;
1036#ifdef FEAT_SIGNS
1037 if (buf == NULL || buf->bufp == NULL)
1038 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001039 nbdebug((" Invalid buffer identifier in getAnno\n"));
1040 EMSG("E652: Invalid buffer identifier in getAnno");
Bram Moolenaarc65c4912006-11-14 17:29:46 +00001041 retval = FAIL;
1042 }
1043 else
1044 {
1045 int serNum;
1046
1047 cp = (char *)args;
1048 serNum = strtol(cp, &cp, 10);
1049 /* If the sign isn't found linenum will be zero. */
1050 linenum = (long)buf_findsign(buf->bufp, serNum);
1051 }
1052#endif
1053 nb_reply_nr(cmdno, linenum);
1054/* =====================================================================*/
1055 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001056 else if (streq((char *)cmd, "getLength"))
1057 {
1058 long len = 0;
1059
1060 if (buf == NULL || buf->bufp == NULL)
1061 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001062 nbdebug((" invalid buffer identifier in getLength\n"));
1063 EMSG("E632: invalid buffer identifier in getLength");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001064 retval = FAIL;
1065 }
1066 else
1067 {
1068 len = get_buf_size(buf->bufp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001069 }
1070 nb_reply_nr(cmdno, len);
1071/* =====================================================================*/
1072 }
1073 else if (streq((char *)cmd, "getText"))
1074 {
1075 long len;
1076 linenr_T nlines;
1077 char_u *text = NULL;
1078 linenr_T lno = 1;
1079 char_u *p;
1080 char_u *line;
1081
1082 if (buf == NULL || buf->bufp == NULL)
1083 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001084 nbdebug((" invalid buffer identifier in getText\n"));
1085 EMSG("E633: invalid buffer identifier in getText");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001086 retval = FAIL;
1087 }
1088 else
1089 {
1090 len = get_buf_size(buf->bufp);
1091 nlines = buf->bufp->b_ml.ml_line_count;
1092 text = alloc((unsigned)((len > 0)
1093 ? ((len + nlines) * 2) : 4));
1094 if (text == NULL)
1095 {
1096 nbdebug((" nb_do_cmd: getText has null text field\n"));
1097 retval = FAIL;
1098 }
1099 else
1100 {
1101 p = text;
1102 *p++ = '\"';
1103 for (; lno <= nlines ; lno++)
1104 {
1105 line = nb_quote(ml_get_buf(buf->bufp, lno, FALSE));
1106 if (line != NULL)
1107 {
1108 STRCPY(p, line);
1109 p += STRLEN(line);
1110 *p++ = '\\';
1111 *p++ = 'n';
Bram Moolenaar009b2592004-10-24 19:18:58 +00001112 vim_free(line);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001113 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001114 }
1115 *p++ = '\"';
1116 *p = '\0';
1117 }
1118 }
1119 if (text == NULL)
1120 nb_reply_text(cmdno, (char_u *)"");
1121 else
1122 {
1123 nb_reply_text(cmdno, text);
1124 vim_free(text);
1125 }
1126/* =====================================================================*/
1127 }
1128 else if (streq((char *)cmd, "remove"))
1129 {
1130 long count;
1131 pos_T first, last;
1132 pos_T *pos;
Bram Moolenaar5eaf8722008-01-05 17:07:13 +00001133 pos_T *next;
1134 linenr_T del_from_lnum, del_to_lnum; /* lines to be deleted as a whole */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001135 int oldFire = netbeansFireChanges;
1136 int oldSuppress = netbeansSuppressNoLines;
1137 int wasChanged;
1138
1139 if (skip >= SKIP_STOP)
1140 {
1141 nbdebug((" Skipping %s command\n", (char *) cmd));
1142 nb_reply_nil(cmdno);
1143 return OK;
1144 }
1145
1146 if (buf == NULL || buf->bufp == NULL)
1147 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001148 nbdebug((" invalid buffer identifier in remove\n"));
1149 EMSG("E634: invalid buffer identifier in remove");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001150 retval = FAIL;
1151 }
1152 else
1153 {
1154 netbeansFireChanges = FALSE;
1155 netbeansSuppressNoLines = TRUE;
1156
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001157 nb_set_curbuf(buf->bufp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001158 wasChanged = buf->bufp->b_changed;
Bram Moolenaar349b2f62004-10-11 10:00:50 +00001159 cp = (char *)args;
1160 off = strtol(cp, &cp, 10);
1161 count = strtol(cp, &cp, 10);
1162 args = (char_u *)cp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001163 /* delete "count" chars, starting at "off" */
1164 pos = off2pos(buf->bufp, off);
1165 if (!pos)
1166 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001167 nbdebug((" !bad position\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001168 nb_reply_text(cmdno, (char_u *)"!bad position");
1169 netbeansFireChanges = oldFire;
1170 netbeansSuppressNoLines = oldSuppress;
1171 return FAIL;
1172 }
1173 first = *pos;
Bram Moolenaarfa68b0f2009-09-11 12:19:51 +00001174 nbdebug((" FIRST POS: line %d, col %d\n",
1175 first.lnum, first.col));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001176 pos = off2pos(buf->bufp, off+count-1);
1177 if (!pos)
1178 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001179 nbdebug((" !bad count\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001180 nb_reply_text(cmdno, (char_u *)"!bad count");
1181 netbeansFireChanges = oldFire;
1182 netbeansSuppressNoLines = oldSuppress;
1183 return FAIL;
1184 }
1185 last = *pos;
Bram Moolenaarfa68b0f2009-09-11 12:19:51 +00001186 nbdebug((" LAST POS: line %d, col %d\n",
1187 last.lnum, last.col));
Bram Moolenaar5eaf8722008-01-05 17:07:13 +00001188 del_from_lnum = first.lnum;
1189 del_to_lnum = last.lnum;
Bram Moolenaar70b2a562012-01-10 22:26:17 +01001190 do_update = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001191
Bram Moolenaar5eaf8722008-01-05 17:07:13 +00001192 /* Get the position of the first byte after the deleted
1193 * section. "next" is NULL when deleting to the end of the
1194 * file. */
1195 next = off2pos(buf->bufp, off + count);
1196
1197 /* Remove part of the first line. */
Bram Moolenaarfa68b0f2009-09-11 12:19:51 +00001198 if (first.col != 0
1199 || (next != NULL && first.lnum == next->lnum))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001200 {
Bram Moolenaar5eaf8722008-01-05 17:07:13 +00001201 if (first.lnum != last.lnum
1202 || (next != NULL && first.lnum != next->lnum))
1203 {
1204 /* remove to the end of the first line */
1205 nb_partialremove(first.lnum, first.col,
1206 (colnr_T)MAXCOL);
1207 if (first.lnum == last.lnum)
1208 {
1209 /* Partial line to remove includes the end of
1210 * line. Join the line with the next one, have
1211 * the next line deleted below. */
1212 nb_joinlines(first.lnum, next->lnum);
1213 del_to_lnum = next->lnum;
1214 }
1215 }
1216 else
1217 {
1218 /* remove within one line */
1219 nb_partialremove(first.lnum, first.col, last.col);
1220 }
1221 ++del_from_lnum; /* don't delete the first line */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001222 }
1223
Bram Moolenaar5eaf8722008-01-05 17:07:13 +00001224 /* Remove part of the last line. */
1225 if (first.lnum != last.lnum && next != NULL
1226 && next->col != 0 && last.lnum == next->lnum)
1227 {
1228 nb_partialremove(last.lnum, 0, last.col);
1229 if (del_from_lnum > first.lnum)
1230 {
1231 /* Join end of last line to start of first line; last
1232 * line is deleted below. */
1233 nb_joinlines(first.lnum, last.lnum);
1234 }
1235 else
1236 /* First line is deleted as a whole, keep the last
1237 * line. */
1238 --del_to_lnum;
1239 }
1240
1241 /* First is partial line; last line to remove includes
1242 * the end of line; join first line to line following last
1243 * line; line following last line is deleted below. */
1244 if (first.lnum != last.lnum && del_from_lnum > first.lnum
1245 && next != NULL && last.lnum != next->lnum)
1246 {
1247 nb_joinlines(first.lnum, next->lnum);
1248 del_to_lnum = next->lnum;
1249 }
1250
1251 /* Delete whole lines if there are any. */
1252 if (del_to_lnum >= del_from_lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001253 {
1254 int i;
1255
1256 /* delete signs from the lines being deleted */
Bram Moolenaar5eaf8722008-01-05 17:07:13 +00001257 for (i = del_from_lnum; i <= del_to_lnum; i++)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001258 {
1259 int id = buf_findsign_id(buf->bufp, (linenr_T)i);
1260 if (id > 0)
1261 {
Bram Moolenaarfa68b0f2009-09-11 12:19:51 +00001262 nbdebug((" Deleting sign %d on line %d\n",
1263 id, i));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001264 buf_delsign(buf->bufp, id);
1265 }
1266 else
Bram Moolenaarb85cb212009-05-17 14:24:23 +00001267 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001268 nbdebug((" No sign on line %d\n", i));
Bram Moolenaarb85cb212009-05-17 14:24:23 +00001269 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001270 }
1271
Bram Moolenaarfa68b0f2009-09-11 12:19:51 +00001272 nbdebug((" Deleting lines %d through %d\n",
1273 del_from_lnum, del_to_lnum));
Bram Moolenaar5eaf8722008-01-05 17:07:13 +00001274 curwin->w_cursor.lnum = del_from_lnum;
1275 curwin->w_cursor.col = 0;
1276 del_lines(del_to_lnum - del_from_lnum + 1, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001277 }
Bram Moolenaar5eaf8722008-01-05 17:07:13 +00001278
1279 /* Leave cursor at first deleted byte. */
1280 curwin->w_cursor = first;
1281 check_cursor_lnum();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001282 buf->bufp->b_changed = wasChanged; /* logically unchanged */
1283 netbeansFireChanges = oldFire;
1284 netbeansSuppressNoLines = oldSuppress;
1285
1286 u_blockfree(buf->bufp);
1287 u_clearall(buf->bufp);
1288 }
1289 nb_reply_nil(cmdno);
1290/* =====================================================================*/
1291 }
1292 else if (streq((char *)cmd, "insert"))
1293 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001294 char_u *to_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001295
1296 if (skip >= SKIP_STOP)
1297 {
1298 nbdebug((" Skipping %s command\n", (char *) cmd));
1299 nb_reply_nil(cmdno);
1300 return OK;
1301 }
1302
1303 /* get offset */
Bram Moolenaar349b2f62004-10-11 10:00:50 +00001304 cp = (char *)args;
1305 off = strtol(cp, &cp, 10);
1306 args = (char_u *)cp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001307
1308 /* get text to be inserted */
1309 args = skipwhite(args);
1310 args = to_free = (char_u *)nb_unquote(args, NULL);
Bram Moolenaar009b2592004-10-24 19:18:58 +00001311 /*
1312 nbdebug((" CHUNK[%d]: %d bytes at offset %d\n",
1313 buf->bufp->b_ml.ml_line_count, STRLEN(args), off));
1314 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001315
1316 if (buf == NULL || buf->bufp == NULL)
1317 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001318 nbdebug((" invalid buffer identifier in insert\n"));
1319 EMSG("E635: invalid buffer identifier in insert");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001320 retval = FAIL;
1321 }
1322 else if (args != NULL)
1323 {
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001324 int ff_detected = EOL_UNKNOWN;
1325 int buf_was_empty = (buf->bufp->b_ml.ml_flags & ML_EMPTY);
1326 size_t len = 0;
1327 int added = 0;
1328 int oldFire = netbeansFireChanges;
1329 int old_b_changed;
Bram Moolenaar309cbc32012-01-10 22:31:31 +01001330 char_u *nlp;
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001331 linenr_T lnum;
1332 linenr_T lnum_start;
1333 pos_T *pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001334
Bram Moolenaar071d4272004-06-13 20:20:40 +00001335 netbeansFireChanges = 0;
1336
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001337 /* Jump to the buffer where we insert. After this "curbuf"
1338 * can be used. */
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001339 nb_set_curbuf(buf->bufp);
Bram Moolenaara3227e22006-03-08 21:32:40 +00001340 old_b_changed = curbuf->b_changed;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001341
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001342 /* Convert the specified character offset into a lnum/col
1343 * position. */
Bram Moolenaara3227e22006-03-08 21:32:40 +00001344 pos = off2pos(curbuf, off);
1345 if (pos != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001346 {
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001347 if (pos->lnum <= 0)
1348 lnum_start = 1;
1349 else
1350 lnum_start = pos->lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001351 }
1352 else
1353 {
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001354 /* If the given position is not found, assume we want
Bram Moolenaar071d4272004-06-13 20:20:40 +00001355 * the end of the file. See setLocAndSize HACK. */
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001356 if (buf_was_empty)
1357 lnum_start = 1; /* above empty line */
1358 else
1359 lnum_start = curbuf->b_ml.ml_line_count + 1;
Bram Moolenaar009b2592004-10-24 19:18:58 +00001360 }
1361
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001362 /* "lnum" is the line where we insert: either append to it or
1363 * insert a new line above it. */
1364 lnum = lnum_start;
1365
1366 /* Loop over the "\n" separated lines of the argument. */
Bram Moolenaar70b2a562012-01-10 22:26:17 +01001367 do_update = 1;
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001368 while (*args != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001369 {
Bram Moolenaar309cbc32012-01-10 22:31:31 +01001370 nlp = vim_strchr(args, '\n');
1371 if (nlp == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001372 {
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001373 /* Incomplete line, probably truncated. Next "insert"
1374 * command should append to this one. */
1375 len = STRLEN(args);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001376 }
Bram Moolenaar009b2592004-10-24 19:18:58 +00001377 else
1378 {
Bram Moolenaar309cbc32012-01-10 22:31:31 +01001379 len = nlp - args;
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001380
1381 /*
1382 * We need to detect EOL style, because the commands
1383 * use a character offset.
1384 */
Bram Moolenaar309cbc32012-01-10 22:31:31 +01001385 if (nlp > args && nlp[-1] == '\r')
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001386 {
1387 ff_detected = EOL_DOS;
1388 --len;
1389 }
1390 else
1391 ff_detected = EOL_UNIX;
1392 }
1393 args[len] = NUL;
1394
1395 if (lnum == lnum_start
1396 && ((pos != NULL && pos->col > 0)
1397 || (lnum == 1 && buf_was_empty)))
1398 {
1399 char_u *oldline = ml_get(lnum);
1400 char_u *newline;
1401
Bram Moolenaare4365282012-04-20 19:47:05 +02001402 /* Insert halfway a line. */
Bram Moolenaar309cbc32012-01-10 22:31:31 +01001403 newline = alloc_check(
1404 (unsigned)(STRLEN(oldline) + len + 1));
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001405 if (newline != NULL)
1406 {
Bram Moolenaare4365282012-04-20 19:47:05 +02001407 mch_memmove(newline, oldline, (size_t)pos->col);
1408 newline[pos->col] = NUL;
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001409 STRCAT(newline, args);
Bram Moolenaare4365282012-04-20 19:47:05 +02001410 STRCAT(newline, oldline + pos->col);
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001411 ml_replace(lnum, newline, FALSE);
1412 }
1413 }
1414 else
1415 {
1416 /* Append a new line. Not that we always do this,
1417 * also when the text doesn't end in a "\n". */
Bram Moolenaar309cbc32012-01-10 22:31:31 +01001418 ml_append((linenr_T)(lnum - 1), args,
1419 (colnr_T)(len + 1), FALSE);
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001420 ++added;
Bram Moolenaar009b2592004-10-24 19:18:58 +00001421 }
1422
Bram Moolenaar309cbc32012-01-10 22:31:31 +01001423 if (nlp == NULL)
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001424 break;
1425 ++lnum;
Bram Moolenaar309cbc32012-01-10 22:31:31 +01001426 args = nlp + 1;
Bram Moolenaar009b2592004-10-24 19:18:58 +00001427 }
1428
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001429 /* Adjust the marks below the inserted lines. */
1430 appended_lines_mark(lnum_start - 1, (long)added);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001431
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001432 /*
1433 * When starting with an empty buffer set the fileformat.
1434 * This is just guessing...
Bram Moolenaar071d4272004-06-13 20:20:40 +00001435 */
1436 if (buf_was_empty)
1437 {
1438 if (ff_detected == EOL_UNKNOWN)
Bram Moolenaar48e330a2016-02-23 14:53:34 +01001439#if defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001440 ff_detected = EOL_DOS;
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001441#else
1442 ff_detected = EOL_UNIX;
1443#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001444 set_fileformat(ff_detected, OPT_LOCAL);
Bram Moolenaara3227e22006-03-08 21:32:40 +00001445 curbuf->b_start_ffc = *curbuf->b_p_ff;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001446 }
1447
Bram Moolenaar071d4272004-06-13 20:20:40 +00001448 /*
1449 * XXX - GRP - Is the next line right? If I've inserted
1450 * text the buffer has been updated but not written. Will
1451 * netbeans guarantee to write it? Even if I do a :q! ?
1452 */
Bram Moolenaara3227e22006-03-08 21:32:40 +00001453 curbuf->b_changed = old_b_changed; /* logically unchanged */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001454 netbeansFireChanges = oldFire;
1455
Bram Moolenaar0fd92892006-03-09 22:27:48 +00001456 /* Undo info is invalid now... */
Bram Moolenaara3227e22006-03-08 21:32:40 +00001457 u_blockfree(curbuf);
1458 u_clearall(curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001459 }
1460 vim_free(to_free);
1461 nb_reply_nil(cmdno); /* or !error */
1462 }
1463 else
1464 {
1465 nbdebug(("UNIMPLEMENTED FUNCTION: %s\n", cmd));
1466 nb_reply_nil(cmdno);
1467 retval = FAIL;
1468 }
1469 }
1470 else /* Not a function; no reply required. */
1471 {
1472/* =====================================================================*/
1473 if (streq((char *)cmd, "create"))
1474 {
1475 /* Create a buffer without a name. */
1476 if (buf == NULL)
1477 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001478 nbdebug((" invalid buffer identifier in create\n"));
1479 EMSG("E636: invalid buffer identifier in create");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001480 return FAIL;
1481 }
1482 vim_free(buf->displayname);
1483 buf->displayname = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001484
1485 netbeansReadFile = 0; /* don't try to open disk file */
Bram Moolenaar701f7af2008-11-15 13:12:07 +00001486 do_ecmd(0, NULL, 0, 0, ECMD_ONE, ECMD_HIDE + ECMD_OLDBUF, curwin);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001487 netbeansReadFile = 1;
1488 buf->bufp = curbuf;
1489 maketitle();
Bram Moolenaar009b2592004-10-24 19:18:58 +00001490 buf->insertDone = FALSE;
Bram Moolenaar67c53842010-05-22 18:28:27 +02001491#if defined(FEAT_MENU) && defined(FEAT_GUI)
Bram Moolenaard54a6882010-08-09 22:49:00 +02001492 if (gui.in_use)
1493 gui_update_menus(0);
Bram Moolenaar67c53842010-05-22 18:28:27 +02001494#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001495/* =====================================================================*/
1496 }
Bram Moolenaar009b2592004-10-24 19:18:58 +00001497 else if (streq((char *)cmd, "insertDone"))
1498 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001499 if (buf == NULL || buf->bufp == NULL)
1500 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001501 nbdebug((" invalid buffer identifier in insertDone\n"));
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001502 }
1503 else
1504 {
1505 buf->bufp->b_start_eol = *args == 'T';
1506 buf->insertDone = TRUE;
1507 args += 2;
1508 buf->bufp->b_p_ro = *args == 'T';
1509 print_read_msg(buf);
1510 }
Bram Moolenaar009b2592004-10-24 19:18:58 +00001511/* =====================================================================*/
1512 }
1513 else if (streq((char *)cmd, "saveDone"))
1514 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001515 long savedChars = atol((char *)args);
1516
1517 if (buf == NULL || buf->bufp == NULL)
1518 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001519 nbdebug((" invalid buffer identifier in saveDone\n"));
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001520 }
1521 else
1522 print_save_msg(buf, savedChars);
Bram Moolenaar009b2592004-10-24 19:18:58 +00001523/* =====================================================================*/
1524 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001525 else if (streq((char *)cmd, "startDocumentListen"))
1526 {
1527 if (buf == NULL)
1528 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001529 nbdebug((" invalid buffer identifier in startDocumentListen\n"));
1530 EMSG("E637: invalid buffer identifier in startDocumentListen");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001531 return FAIL;
1532 }
1533 buf->fireChanges = 1;
1534/* =====================================================================*/
1535 }
1536 else if (streq((char *)cmd, "stopDocumentListen"))
1537 {
1538 if (buf == NULL)
1539 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001540 nbdebug((" invalid buffer identifier in stopDocumentListen\n"));
1541 EMSG("E638: invalid buffer identifier in stopDocumentListen");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001542 return FAIL;
1543 }
1544 buf->fireChanges = 0;
Bram Moolenaar24c088a2005-02-02 22:55:47 +00001545 if (buf->bufp != NULL && buf->bufp->b_was_netbeans_file)
Bram Moolenaar009b2592004-10-24 19:18:58 +00001546 {
Bram Moolenaar24c088a2005-02-02 22:55:47 +00001547 if (!buf->bufp->b_netbeans_file)
Bram Moolenaarf2330482008-06-24 20:19:36 +00001548 {
1549 nbdebug(("E658: NetBeans connection lost for buffer %ld\n", buf->bufp->b_fnum));
Bram Moolenaar009b2592004-10-24 19:18:58 +00001550 EMSGN(_("E658: NetBeans connection lost for buffer %ld"),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001551 buf->bufp->b_fnum);
Bram Moolenaarf2330482008-06-24 20:19:36 +00001552 }
Bram Moolenaar009b2592004-10-24 19:18:58 +00001553 else
1554 {
Bram Moolenaar24c088a2005-02-02 22:55:47 +00001555 /* NetBeans uses stopDocumentListen when it stops editing
1556 * a file. It then expects the buffer in Vim to
1557 * disappear. */
1558 do_bufdel(DOBUF_DEL, (char_u *)"", 1,
1559 buf->bufp->b_fnum, buf->bufp->b_fnum, TRUE);
Bram Moolenaar009b2592004-10-24 19:18:58 +00001560 vim_memset(buf, 0, sizeof(nbbuf_T));
1561 }
1562 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001563/* =====================================================================*/
1564 }
1565 else if (streq((char *)cmd, "setTitle"))
1566 {
1567 if (buf == NULL)
1568 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001569 nbdebug((" invalid buffer identifier in setTitle\n"));
1570 EMSG("E639: invalid buffer identifier in setTitle");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001571 return FAIL;
1572 }
1573 vim_free(buf->displayname);
1574 buf->displayname = nb_unquote(args, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001575/* =====================================================================*/
1576 }
1577 else if (streq((char *)cmd, "initDone"))
1578 {
1579 if (buf == NULL || buf->bufp == NULL)
1580 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001581 nbdebug((" invalid buffer identifier in initDone\n"));
1582 EMSG("E640: invalid buffer identifier in initDone");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001583 return FAIL;
1584 }
Bram Moolenaar70b2a562012-01-10 22:26:17 +01001585 do_update = 1;
Bram Moolenaar009b2592004-10-24 19:18:58 +00001586 buf->initDone = TRUE;
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001587 nb_set_curbuf(buf->bufp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001588#if defined(FEAT_AUTOCMD)
1589 apply_autocmds(EVENT_BUFREADPOST, 0, 0, FALSE, buf->bufp);
1590#endif
1591
1592 /* handle any postponed key commands */
1593 handle_key_queue();
1594/* =====================================================================*/
1595 }
1596 else if (streq((char *)cmd, "setBufferNumber")
1597 || streq((char *)cmd, "putBufferNumber"))
1598 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00001599 char_u *path;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001600 buf_T *bufp;
1601
1602 if (buf == NULL)
1603 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001604 nbdebug((" invalid buffer identifier in setBufferNumber\n"));
1605 EMSG("E641: invalid buffer identifier in setBufferNumber");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001606 return FAIL;
1607 }
Bram Moolenaar009b2592004-10-24 19:18:58 +00001608 path = (char_u *)nb_unquote(args, NULL);
1609 if (path == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001610 return FAIL;
Bram Moolenaar009b2592004-10-24 19:18:58 +00001611 bufp = buflist_findname(path);
1612 vim_free(path);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001613 if (bufp == NULL)
1614 {
Bram Moolenaarec906222009-02-21 21:14:00 +00001615 nbdebug((" File %s not found in setBufferNumber\n", args));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001616 EMSG2("E642: File %s not found in setBufferNumber", args);
1617 return FAIL;
1618 }
1619 buf->bufp = bufp;
Bram Moolenaar009b2592004-10-24 19:18:58 +00001620 buf->nbbuf_number = bufp->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001621
1622 /* "setBufferNumber" has the side effect of jumping to the buffer
1623 * (don't know why!). Don't do that for "putBufferNumber". */
1624 if (*cmd != 'p')
1625 coloncmd(":buffer %d", bufp->b_fnum);
1626 else
1627 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00001628 buf->initDone = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001629
1630 /* handle any postponed key commands */
1631 handle_key_queue();
1632 }
1633
Bram Moolenaar071d4272004-06-13 20:20:40 +00001634/* =====================================================================*/
1635 }
1636 else if (streq((char *)cmd, "setFullName"))
1637 {
1638 if (buf == NULL)
1639 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001640 nbdebug((" invalid buffer identifier in setFullName\n"));
1641 EMSG("E643: invalid buffer identifier in setFullName");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001642 return FAIL;
1643 }
1644 vim_free(buf->displayname);
1645 buf->displayname = nb_unquote(args, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001646
1647 netbeansReadFile = 0; /* don't try to open disk file */
1648 do_ecmd(0, (char_u *)buf->displayname, 0, 0, ECMD_ONE,
Bram Moolenaar701f7af2008-11-15 13:12:07 +00001649 ECMD_HIDE + ECMD_OLDBUF, curwin);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001650 netbeansReadFile = 1;
1651 buf->bufp = curbuf;
1652 maketitle();
Bram Moolenaar67c53842010-05-22 18:28:27 +02001653#if defined(FEAT_MENU) && defined(FEAT_GUI)
Bram Moolenaard54a6882010-08-09 22:49:00 +02001654 if (gui.in_use)
1655 gui_update_menus(0);
Bram Moolenaar67c53842010-05-22 18:28:27 +02001656#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001657/* =====================================================================*/
1658 }
1659 else if (streq((char *)cmd, "editFile"))
1660 {
1661 if (buf == NULL)
1662 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001663 nbdebug((" invalid buffer identifier in editFile\n"));
1664 EMSG("E644: invalid buffer identifier in editFile");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001665 return FAIL;
1666 }
1667 /* Edit a file: like create + setFullName + read the file. */
1668 vim_free(buf->displayname);
1669 buf->displayname = nb_unquote(args, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001670 do_ecmd(0, (char_u *)buf->displayname, NULL, NULL, ECMD_ONE,
Bram Moolenaar701f7af2008-11-15 13:12:07 +00001671 ECMD_HIDE + ECMD_OLDBUF, curwin);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001672 buf->bufp = curbuf;
Bram Moolenaar009b2592004-10-24 19:18:58 +00001673 buf->initDone = TRUE;
Bram Moolenaar70b2a562012-01-10 22:26:17 +01001674 do_update = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001675#if defined(FEAT_TITLE)
1676 maketitle();
1677#endif
Bram Moolenaar67c53842010-05-22 18:28:27 +02001678#if defined(FEAT_MENU) && defined(FEAT_GUI)
Bram Moolenaard54a6882010-08-09 22:49:00 +02001679 if (gui.in_use)
1680 gui_update_menus(0);
Bram Moolenaar67c53842010-05-22 18:28:27 +02001681#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001682/* =====================================================================*/
1683 }
1684 else if (streq((char *)cmd, "setVisible"))
1685 {
1686 if (buf == NULL || buf->bufp == NULL)
1687 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001688 nbdebug((" invalid buffer identifier in setVisible\n"));
1689 /* This message was commented out, probably because it can
1690 * happen when shutting down. */
1691 if (p_verbose > 0)
1692 EMSG("E645: invalid buffer identifier in setVisible");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001693 return FAIL;
1694 }
Bram Moolenaar009b2592004-10-24 19:18:58 +00001695 if (streq((char *)args, "T") && buf->bufp != curbuf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001696 {
1697 exarg_T exarg;
1698 exarg.cmd = (char_u *)"goto";
1699 exarg.forceit = FALSE;
Bram Moolenaar009b2592004-10-24 19:18:58 +00001700 dosetvisible = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001701 goto_buffer(&exarg, DOBUF_FIRST, FORWARD, buf->bufp->b_fnum);
Bram Moolenaar70b2a562012-01-10 22:26:17 +01001702 do_update = 1;
Bram Moolenaar009b2592004-10-24 19:18:58 +00001703 dosetvisible = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001704
Bram Moolenaar67c53842010-05-22 18:28:27 +02001705#ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00001706 /* Side effect!!!. */
Bram Moolenaard54a6882010-08-09 22:49:00 +02001707 if (gui.in_use)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001708 gui_mch_set_foreground();
Bram Moolenaar67c53842010-05-22 18:28:27 +02001709#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001710 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001711/* =====================================================================*/
1712 }
1713 else if (streq((char *)cmd, "raise"))
1714 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02001715#ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00001716 /* Bring gvim to the foreground. */
Bram Moolenaard54a6882010-08-09 22:49:00 +02001717 if (gui.in_use)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001718 gui_mch_set_foreground();
Bram Moolenaar67c53842010-05-22 18:28:27 +02001719#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001720/* =====================================================================*/
1721 }
1722 else if (streq((char *)cmd, "setModified"))
1723 {
Bram Moolenaarff064e12008-06-09 13:10:45 +00001724 int prev_b_changed;
1725
Bram Moolenaar071d4272004-06-13 20:20:40 +00001726 if (buf == NULL || buf->bufp == NULL)
1727 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001728 nbdebug((" invalid buffer identifier in setModified\n"));
1729 /* This message was commented out, probably because it can
1730 * happen when shutting down. */
1731 if (p_verbose > 0)
1732 EMSG("E646: invalid buffer identifier in setModified");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001733 return FAIL;
1734 }
Bram Moolenaarff064e12008-06-09 13:10:45 +00001735 prev_b_changed = buf->bufp->b_changed;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001736 if (streq((char *)args, "T"))
Bram Moolenaarff064e12008-06-09 13:10:45 +00001737 buf->bufp->b_changed = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001738 else
1739 {
1740 struct stat st;
1741
1742 /* Assume NetBeans stored the file. Reset the timestamp to
1743 * avoid "file changed" warnings. */
1744 if (buf->bufp->b_ffname != NULL
1745 && mch_stat((char *)buf->bufp->b_ffname, &st) >= 0)
1746 buf_store_time(buf->bufp, &st, buf->bufp->b_ffname);
Bram Moolenaarff064e12008-06-09 13:10:45 +00001747 buf->bufp->b_changed = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001748 }
1749 buf->modified = buf->bufp->b_changed;
Bram Moolenaarff064e12008-06-09 13:10:45 +00001750 if (prev_b_changed != buf->bufp->b_changed)
1751 {
1752#ifdef FEAT_WINDOWS
1753 check_status(buf->bufp);
1754 redraw_tabline = TRUE;
1755#endif
1756#ifdef FEAT_TITLE
1757 maketitle();
1758#endif
1759 update_screen(0);
1760 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001761/* =====================================================================*/
1762 }
Bram Moolenaar009b2592004-10-24 19:18:58 +00001763 else if (streq((char *)cmd, "setModtime"))
1764 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001765 if (buf == NULL || buf->bufp == NULL)
Bram Moolenaarf2330482008-06-24 20:19:36 +00001766 nbdebug((" invalid buffer identifier in setModtime\n"));
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001767 else
1768 buf->bufp->b_mtime = atoi((char *)args);
Bram Moolenaar009b2592004-10-24 19:18:58 +00001769/* =====================================================================*/
1770 }
1771 else if (streq((char *)cmd, "setReadOnly"))
1772 {
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001773 if (buf == NULL || buf->bufp == NULL)
Bram Moolenaarf2330482008-06-24 20:19:36 +00001774 nbdebug((" invalid buffer identifier in setReadOnly\n"));
Bram Moolenaareb3593b2006-04-22 22:33:57 +00001775 else if (streq((char *)args, "T"))
Bram Moolenaar009b2592004-10-24 19:18:58 +00001776 buf->bufp->b_p_ro = TRUE;
1777 else
1778 buf->bufp->b_p_ro = FALSE;
1779/* =====================================================================*/
1780 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001781 else if (streq((char *)cmd, "setMark"))
1782 {
1783 /* not yet */
1784/* =====================================================================*/
1785 }
1786 else if (streq((char *)cmd, "showBalloon"))
1787 {
1788#if defined(FEAT_BEVAL)
1789 static char *text = NULL;
1790
1791 /*
1792 * Set up the Balloon Expression Evaluation area.
1793 * Ignore 'ballooneval' here.
1794 * The text pointer must remain valid for a while.
1795 */
1796 if (balloonEval != NULL)
1797 {
1798 vim_free(text);
1799 text = nb_unquote(args, NULL);
1800 if (text != NULL)
1801 gui_mch_post_balloon(balloonEval, (char_u *)text);
1802 }
1803#endif
1804/* =====================================================================*/
1805 }
1806 else if (streq((char *)cmd, "setDot"))
1807 {
1808 pos_T *pos;
1809#ifdef NBDEBUG
1810 char_u *s;
1811#endif
1812
1813 if (buf == NULL || buf->bufp == NULL)
1814 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001815 nbdebug((" invalid buffer identifier in setDot\n"));
1816 EMSG("E647: invalid buffer identifier in setDot");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001817 return FAIL;
1818 }
1819
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00001820 nb_set_curbuf(buf->bufp);
1821
Bram Moolenaar071d4272004-06-13 20:20:40 +00001822 /* Don't want Visual mode now. */
1823 if (VIsual_active)
1824 end_visual_mode();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001825#ifdef NBDEBUG
1826 s = args;
1827#endif
1828 pos = get_off_or_lnum(buf->bufp, &args);
1829 if (pos)
1830 {
1831 curwin->w_cursor = *pos;
1832 check_cursor();
1833#ifdef FEAT_FOLDING
1834 foldOpenCursor();
1835#endif
1836 }
1837 else
Bram Moolenaarb85cb212009-05-17 14:24:23 +00001838 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001839 nbdebug((" BAD POSITION in setDot: %s\n", s));
Bram Moolenaarb85cb212009-05-17 14:24:23 +00001840 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001841
1842 /* gui_update_cursor(TRUE, FALSE); */
1843 /* update_curbuf(NOT_VALID); */
1844 update_topline(); /* scroll to show the line */
1845 update_screen(VALID);
1846 setcursor();
Bram Moolenaar96bcc5e2011-04-01 15:33:59 +02001847 cursor_on();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001848 out_flush();
Bram Moolenaar67c53842010-05-22 18:28:27 +02001849#ifdef FEAT_GUI
Bram Moolenaard54a6882010-08-09 22:49:00 +02001850 if (gui.in_use)
1851 {
1852 gui_update_cursor(TRUE, FALSE);
1853 gui_mch_flush();
1854 }
Bram Moolenaar67c53842010-05-22 18:28:27 +02001855#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001856 /* Quit a hit-return or more prompt. */
1857 if (State == HITRETURN || State == ASKMORE)
1858 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001859#ifdef FEAT_GUI_GTK
Bram Moolenaard54a6882010-08-09 22:49:00 +02001860 if (gui.in_use && gtk_main_level() > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001861 gtk_main_quit();
1862#endif
1863 }
1864/* =====================================================================*/
1865 }
1866 else if (streq((char *)cmd, "close"))
1867 {
1868#ifdef NBDEBUG
1869 char *name = "<NONE>";
1870#endif
1871
1872 if (buf == NULL)
1873 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001874 nbdebug((" invalid buffer identifier in close\n"));
1875 EMSG("E648: invalid buffer identifier in close");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876 return FAIL;
1877 }
1878
1879#ifdef NBDEBUG
1880 if (buf->displayname != NULL)
1881 name = buf->displayname;
1882#endif
Bram Moolenaarf2330482008-06-24 20:19:36 +00001883 if (buf->bufp == NULL)
1884 {
1885 nbdebug((" invalid buffer identifier in close\n"));
1886 /* This message was commented out, probably because it can
1887 * happen when shutting down. */
1888 if (p_verbose > 0)
1889 EMSG("E649: invalid buffer identifier in close");
1890 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001891 nbdebug((" CLOSE %d: %s\n", bufno, name));
Bram Moolenaar67c53842010-05-22 18:28:27 +02001892#ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00001893 need_mouse_correct = TRUE;
Bram Moolenaar67c53842010-05-22 18:28:27 +02001894#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001895 if (buf->bufp != NULL)
1896 do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD,
1897 buf->bufp->b_fnum, TRUE);
Bram Moolenaar8d602722006-08-08 19:34:19 +00001898 buf->bufp = NULL;
1899 buf->initDone = FALSE;
Bram Moolenaar70b2a562012-01-10 22:26:17 +01001900 do_update = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001901/* =====================================================================*/
1902 }
1903 else if (streq((char *)cmd, "setStyle")) /* obsolete... */
1904 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001905 nbdebug((" setStyle is obsolete!\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001906/* =====================================================================*/
1907 }
1908 else if (streq((char *)cmd, "setExitDelay"))
1909 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00001910 /* Only used in version 2.1. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001911/* =====================================================================*/
1912 }
1913 else if (streq((char *)cmd, "defineAnnoType"))
1914 {
1915#ifdef FEAT_SIGNS
1916 int typeNum;
1917 char_u *typeName;
1918 char_u *tooltip;
1919 char_u *p;
1920 char_u *glyphFile;
Bram Moolenaar67c53842010-05-22 18:28:27 +02001921 int parse_error = FALSE;
1922 char_u *fg;
1923 char_u *bg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001924
1925 if (buf == NULL)
1926 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001927 nbdebug((" invalid buffer identifier in defineAnnoType\n"));
1928 EMSG("E650: invalid buffer identifier in defineAnnoType");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001929 return FAIL;
1930 }
1931
Bram Moolenaar349b2f62004-10-11 10:00:50 +00001932 cp = (char *)args;
1933 typeNum = strtol(cp, &cp, 10);
1934 args = (char_u *)cp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001935 args = skipwhite(args);
1936 typeName = (char_u *)nb_unquote(args, &args);
1937 args = skipwhite(args + 1);
1938 tooltip = (char_u *)nb_unquote(args, &args);
1939 args = skipwhite(args + 1);
1940
1941 p = (char_u *)nb_unquote(args, &args);
1942 glyphFile = vim_strsave_escaped(p, escape_chars);
1943 vim_free(p);
1944
1945 args = skipwhite(args + 1);
Bram Moolenaar67c53842010-05-22 18:28:27 +02001946 p = skiptowhite(args);
1947 if (*p != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001948 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02001949 *p = NUL;
1950 p = skipwhite(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001951 }
Bram Moolenaar67c53842010-05-22 18:28:27 +02001952 fg = vim_strsave(args);
1953 bg = vim_strsave(p);
1954 if (STRLEN(fg) > MAX_COLOR_LENGTH || STRLEN(bg) > MAX_COLOR_LENGTH)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001955 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02001956 EMSG("E532: highlighting color name too long in defineAnnoType");
1957 vim_free(typeName);
1958 parse_error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001959 }
Bram Moolenaar67c53842010-05-22 18:28:27 +02001960 else if (typeName != NULL && tooltip != NULL && glyphFile != NULL)
1961 addsigntype(buf, typeNum, typeName, tooltip, glyphFile, fg, bg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001962 else
1963 vim_free(typeName);
1964
1965 /* don't free typeName; it's used directly in addsigntype() */
Bram Moolenaar67c53842010-05-22 18:28:27 +02001966 vim_free(fg);
1967 vim_free(bg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001968 vim_free(tooltip);
1969 vim_free(glyphFile);
Bram Moolenaar67c53842010-05-22 18:28:27 +02001970 if (parse_error)
1971 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001972
1973#endif
1974/* =====================================================================*/
1975 }
1976 else if (streq((char *)cmd, "addAnno"))
1977 {
1978#ifdef FEAT_SIGNS
1979 int serNum;
1980 int localTypeNum;
1981 int typeNum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001982 pos_T *pos;
1983
1984 if (buf == NULL || buf->bufp == NULL)
1985 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00001986 nbdebug((" invalid buffer identifier in addAnno\n"));
1987 EMSG("E651: invalid buffer identifier in addAnno");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001988 return FAIL;
1989 }
1990
Bram Moolenaar70b2a562012-01-10 22:26:17 +01001991 do_update = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001992
Bram Moolenaar349b2f62004-10-11 10:00:50 +00001993 cp = (char *)args;
1994 serNum = strtol(cp, &cp, 10);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001995
1996 /* Get the typenr specific for this buffer and convert it to
1997 * the global typenumber, as used for the sign name. */
Bram Moolenaar349b2f62004-10-11 10:00:50 +00001998 localTypeNum = strtol(cp, &cp, 10);
1999 args = (char_u *)cp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002000 typeNum = mapsigntype(buf, localTypeNum);
2001
2002 pos = get_off_or_lnum(buf->bufp, &args);
2003
Bram Moolenaar349b2f62004-10-11 10:00:50 +00002004 cp = (char *)args;
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00002005 ignored = (int)strtol(cp, &cp, 10);
Bram Moolenaar349b2f62004-10-11 10:00:50 +00002006 args = (char_u *)cp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002007# ifdef NBDEBUG
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00002008 if (ignored != -1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002009 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00002010 nbdebug((" partial line annotation -- Not Yet Implemented!\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002011 }
2012# endif
2013 if (serNum >= GUARDEDOFFSET)
2014 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00002015 nbdebug((" too many annotations! ignoring...\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002016 return FAIL;
2017 }
2018 if (pos)
2019 {
Bram Moolenaarec906222009-02-21 21:14:00 +00002020 coloncmd(":sign place %d line=%ld name=%d buffer=%d",
Bram Moolenaar071d4272004-06-13 20:20:40 +00002021 serNum, pos->lnum, typeNum, buf->bufp->b_fnum);
2022 if (typeNum == curPCtype)
2023 coloncmd(":sign jump %d buffer=%d", serNum,
2024 buf->bufp->b_fnum);
2025 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002026#endif
2027/* =====================================================================*/
2028 }
2029 else if (streq((char *)cmd, "removeAnno"))
2030 {
2031#ifdef FEAT_SIGNS
2032 int serNum;
2033
2034 if (buf == NULL || buf->bufp == NULL)
2035 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00002036 nbdebug((" invalid buffer identifier in removeAnno\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002037 return FAIL;
2038 }
Bram Moolenaar70b2a562012-01-10 22:26:17 +01002039 do_update = 1;
Bram Moolenaar349b2f62004-10-11 10:00:50 +00002040 cp = (char *)args;
2041 serNum = strtol(cp, &cp, 10);
2042 args = (char_u *)cp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002043 coloncmd(":sign unplace %d buffer=%d",
2044 serNum, buf->bufp->b_fnum);
2045 redraw_buf_later(buf->bufp, NOT_VALID);
2046#endif
2047/* =====================================================================*/
2048 }
2049 else if (streq((char *)cmd, "moveAnnoToFront"))
2050 {
2051#ifdef FEAT_SIGNS
Bram Moolenaarf2330482008-06-24 20:19:36 +00002052 nbdebug((" moveAnnoToFront: Not Yet Implemented!\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002053#endif
2054/* =====================================================================*/
2055 }
2056 else if (streq((char *)cmd, "guard") || streq((char *)cmd, "unguard"))
2057 {
2058 int len;
2059 pos_T first;
2060 pos_T last;
2061 pos_T *pos;
2062 int un = (cmd[0] == 'u');
2063 static int guardId = GUARDEDOFFSET;
2064
2065 if (skip >= SKIP_STOP)
2066 {
2067 nbdebug((" Skipping %s command\n", (char *) cmd));
2068 return OK;
2069 }
2070
2071 nb_init_graphics();
2072
2073 if (buf == NULL || buf->bufp == NULL)
2074 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00002075 nbdebug((" invalid buffer identifier in %s command\n", cmd));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002076 return FAIL;
2077 }
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002078 nb_set_curbuf(buf->bufp);
Bram Moolenaar349b2f62004-10-11 10:00:50 +00002079 cp = (char *)args;
2080 off = strtol(cp, &cp, 10);
2081 len = strtol(cp, NULL, 10);
2082 args = (char_u *)cp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002083 pos = off2pos(buf->bufp, off);
Bram Moolenaar70b2a562012-01-10 22:26:17 +01002084 do_update = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002085 if (!pos)
2086 nbdebug((" no such start pos in %s, %ld\n", cmd, off));
2087 else
2088 {
2089 first = *pos;
2090 pos = off2pos(buf->bufp, off + len - 1);
Bram Moolenaar009b2592004-10-24 19:18:58 +00002091 if (pos != NULL && pos->col == 0)
2092 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002093 /*
2094 * In Java Swing the offset is a position between 2
2095 * characters. If col == 0 then we really want the
2096 * previous line as the end.
2097 */
2098 pos = off2pos(buf->bufp, off + len - 2);
2099 }
2100 if (!pos)
2101 nbdebug((" no such end pos in %s, %ld\n",
2102 cmd, off + len - 1));
2103 else
2104 {
2105 long lnum;
2106 last = *pos;
2107 /* set highlight for region */
2108 nbdebug((" %sGUARD %ld,%d to %ld,%d\n", (un) ? "UN" : "",
2109 first.lnum, first.col,
2110 last.lnum, last.col));
2111#ifdef FEAT_SIGNS
2112 for (lnum = first.lnum; lnum <= last.lnum; lnum++)
2113 {
2114 if (un)
2115 {
2116 /* never used */
2117 }
2118 else
2119 {
2120 if (buf_findsigntype_id(buf->bufp, lnum,
2121 GUARDED) == 0)
2122 {
2123 coloncmd(
Bram Moolenaarec906222009-02-21 21:14:00 +00002124 ":sign place %d line=%ld name=%d buffer=%d",
Bram Moolenaar071d4272004-06-13 20:20:40 +00002125 guardId++, lnum, GUARDED,
2126 buf->bufp->b_fnum);
2127 }
2128 }
2129 }
2130#endif
2131 redraw_buf_later(buf->bufp, NOT_VALID);
2132 }
2133 }
2134/* =====================================================================*/
2135 }
2136 else if (streq((char *)cmd, "startAtomic"))
2137 {
2138 inAtomic = 1;
2139/* =====================================================================*/
2140 }
2141 else if (streq((char *)cmd, "endAtomic"))
2142 {
2143 inAtomic = 0;
2144 if (needupdate)
2145 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +01002146 do_update = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002147 needupdate = 0;
2148 }
2149/* =====================================================================*/
2150 }
2151 else if (streq((char *)cmd, "save"))
2152 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00002153 /*
2154 * NOTE - This command is obsolete wrt NetBeans. Its left in
2155 * only for historical reasons.
2156 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002157 if (buf == NULL || buf->bufp == NULL)
2158 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00002159 nbdebug((" invalid buffer identifier in %s command\n", cmd));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002160 return FAIL;
2161 }
2162
2163 /* the following is taken from ex_cmds.c (do_wqall function) */
2164 if (bufIsChanged(buf->bufp))
2165 {
2166 /* Only write if the buffer can be written. */
2167 if (p_write
2168 && !buf->bufp->b_p_ro
2169 && buf->bufp->b_ffname != NULL
2170#ifdef FEAT_QUICKFIX
2171 && !bt_dontwrite(buf->bufp)
2172#endif
2173 )
2174 {
2175 buf_write_all(buf->bufp, FALSE);
2176#ifdef FEAT_AUTOCMD
2177 /* an autocommand may have deleted the buffer */
2178 if (!buf_valid(buf->bufp))
2179 buf->bufp = NULL;
2180#endif
2181 }
2182 }
Bram Moolenaarf2330482008-06-24 20:19:36 +00002183 else
2184 {
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002185 nbdebug((" Buffer has no changes!\n"));
Bram Moolenaarf2330482008-06-24 20:19:36 +00002186 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002187/* =====================================================================*/
2188 }
2189 else if (streq((char *)cmd, "netbeansBuffer"))
2190 {
2191 if (buf == NULL || buf->bufp == NULL)
2192 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00002193 nbdebug((" invalid buffer identifier in %s command\n", cmd));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002194 return FAIL;
2195 }
2196 if (*args == 'T')
2197 {
2198 buf->bufp->b_netbeans_file = TRUE;
2199 buf->bufp->b_was_netbeans_file = TRUE;
2200 }
2201 else
2202 buf->bufp->b_netbeans_file = FALSE;
2203/* =====================================================================*/
2204 }
Bram Moolenaar009b2592004-10-24 19:18:58 +00002205 else if (streq((char *)cmd, "specialKeys"))
2206 {
2207 special_keys(args);
2208/* =====================================================================*/
2209 }
2210 else if (streq((char *)cmd, "actionMenuItem"))
2211 {
2212 /* not used yet */
2213/* =====================================================================*/
2214 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002215 else if (streq((char *)cmd, "version"))
2216 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00002217 /* not used yet */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002218 }
Bram Moolenaarf2330482008-06-24 20:19:36 +00002219 else
2220 {
2221 nbdebug(("Unrecognised command: %s\n", cmd));
2222 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002223 /*
2224 * Unrecognized command is ignored.
2225 */
2226 }
Bram Moolenaar70b2a562012-01-10 22:26:17 +01002227 if (inAtomic && do_update)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002228 {
2229 needupdate = 1;
Bram Moolenaar70b2a562012-01-10 22:26:17 +01002230 do_update = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002231 }
2232
Bram Moolenaar009b2592004-10-24 19:18:58 +00002233 /*
2234 * Is this needed? I moved the netbeans_Xt_connect() later during startup
2235 * and it may no longer be necessary. If its not needed then needupdate
Bram Moolenaar70b2a562012-01-10 22:26:17 +01002236 * and do_update can also be removed.
Bram Moolenaar009b2592004-10-24 19:18:58 +00002237 */
Bram Moolenaar70b2a562012-01-10 22:26:17 +01002238 if (buf != NULL && buf->initDone && do_update)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002239 {
2240 update_screen(NOT_VALID);
2241 setcursor();
Bram Moolenaar96bcc5e2011-04-01 15:33:59 +02002242 cursor_on();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002243 out_flush();
Bram Moolenaar67c53842010-05-22 18:28:27 +02002244#ifdef FEAT_GUI
Bram Moolenaard54a6882010-08-09 22:49:00 +02002245 if (gui.in_use)
2246 {
2247 gui_update_cursor(TRUE, FALSE);
2248 gui_mch_flush();
2249 }
Bram Moolenaar67c53842010-05-22 18:28:27 +02002250#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002251 /* Quit a hit-return or more prompt. */
2252 if (State == HITRETURN || State == ASKMORE)
2253 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002254#ifdef FEAT_GUI_GTK
Bram Moolenaard54a6882010-08-09 22:49:00 +02002255 if (gui.in_use && gtk_main_level() > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002256 gtk_main_quit();
2257#endif
2258 }
2259 }
2260
2261 return retval;
2262}
2263
2264
2265/*
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002266 * If "buf" is not the current buffer try changing to a window that edits this
2267 * buffer. If there is no such window then close the current buffer and set
2268 * the current buffer as "buf".
2269 */
2270 static void
Bram Moolenaar5eaf8722008-01-05 17:07:13 +00002271nb_set_curbuf(buf_T *buf)
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002272{
Bram Moolenaar404c9422015-03-14 15:35:52 +01002273 if (curbuf != buf) {
2274 if (buf_jump_open_win(buf) != NULL)
2275 return;
2276# ifdef FEAT_WINDOWS
2277 if ((swb_flags & SWB_USETAB) && buf_jump_open_tab(buf) != NULL)
2278 return;
2279# endif
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002280 set_curbuf(buf, DOBUF_GOTO);
Bram Moolenaar404c9422015-03-14 15:35:52 +01002281 }
Bram Moolenaar8b6144b2006-02-08 09:20:24 +00002282}
2283
2284/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002285 * Process a vim colon command.
2286 */
2287 static void
2288coloncmd(char *cmd, ...)
2289{
2290 char buf[1024];
2291 va_list ap;
2292
2293 va_start(ap, cmd);
Bram Moolenaar0dc79e82009-06-24 14:50:12 +00002294 vim_vsnprintf(buf, sizeof(buf), cmd, ap, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002295 va_end(ap);
2296
2297 nbdebug((" COLONCMD %s\n", buf));
2298
2299/* ALT_INPUT_LOCK_ON; */
2300 do_cmdline((char_u *)buf, NULL, NULL, DOCMD_NOWAIT | DOCMD_KEYTYPED);
2301/* ALT_INPUT_LOCK_OFF; */
2302
2303 setcursor(); /* restore the cursor position */
2304 out_flush(); /* make sure output has been written */
2305
Bram Moolenaar67c53842010-05-22 18:28:27 +02002306#ifdef FEAT_GUI
Bram Moolenaard54a6882010-08-09 22:49:00 +02002307 if (gui.in_use)
2308 {
2309 gui_update_cursor(TRUE, FALSE);
2310 gui_mch_flush();
2311 }
Bram Moolenaar67c53842010-05-22 18:28:27 +02002312#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002313}
2314
2315
2316/*
Bram Moolenaar009b2592004-10-24 19:18:58 +00002317 * Parse the specialKeys argument and issue the appropriate map commands.
2318 */
2319 static void
2320special_keys(char_u *args)
2321{
2322 char *save_str = nb_unquote(args, NULL);
2323 char *tok = strtok(save_str, " ");
2324 char *sep;
2325 char keybuf[64];
2326 char cmdbuf[256];
2327
2328 while (tok != NULL)
2329 {
2330 int i = 0;
2331
2332 if ((sep = strchr(tok, '-')) != NULL)
2333 {
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00002334 *sep = NUL;
Bram Moolenaar009b2592004-10-24 19:18:58 +00002335 while (*tok)
2336 {
2337 switch (*tok)
2338 {
2339 case 'A':
2340 case 'M':
2341 case 'C':
2342 case 'S':
2343 keybuf[i++] = *tok;
2344 keybuf[i++] = '-';
2345 break;
2346 }
2347 tok++;
2348 }
2349 tok++;
2350 }
2351
2352 strcpy(&keybuf[i], tok);
Bram Moolenaar9c13b352005-05-19 20:53:52 +00002353 vim_snprintf(cmdbuf, sizeof(cmdbuf),
2354 "<silent><%s> :nbkey %s<CR>", keybuf, keybuf);
Bram Moolenaar009b2592004-10-24 19:18:58 +00002355 do_map(0, (char_u *)cmdbuf, NORMAL, FALSE);
2356 tok = strtok(NULL, " ");
2357 }
2358 vim_free(save_str);
2359}
2360
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002361 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002362ex_nbclose(exarg_T *eap UNUSED)
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002363{
2364 netbeans_close();
2365}
Bram Moolenaar009b2592004-10-24 19:18:58 +00002366
2367 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002368ex_nbkey(exarg_T *eap)
Bram Moolenaar009b2592004-10-24 19:18:58 +00002369{
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002370 (void)netbeans_keystring(eap->arg);
Bram Moolenaar009b2592004-10-24 19:18:58 +00002371}
2372
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002373 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002374ex_nbstart(
2375 exarg_T *eap)
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002376{
Bram Moolenaarc2a406b2010-09-30 21:03:26 +02002377#ifdef FEAT_GUI
2378# if !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK) \
Bram Moolenaar7ad7d012010-11-16 15:49:02 +01002379 && !defined(FEAT_GUI_W32)
Bram Moolenaarc2a406b2010-09-30 21:03:26 +02002380 if (gui.in_use)
2381 {
Bram Moolenaar7ad7d012010-11-16 15:49:02 +01002382 EMSG(_("E838: netbeans is not supported with this GUI"));
2383 return;
Bram Moolenaarc2a406b2010-09-30 21:03:26 +02002384 }
2385# endif
2386#endif
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002387 netbeans_open((char *)eap->arg, FALSE);
2388}
Bram Moolenaar009b2592004-10-24 19:18:58 +00002389
2390/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002391 * Initialize highlights and signs for use by netbeans (mostly obsolete)
2392 */
2393 static void
2394nb_init_graphics(void)
2395{
2396 static int did_init = FALSE;
2397
2398 if (!did_init)
2399 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02002400 coloncmd(":highlight NBGuarded guibg=Cyan guifg=Black"
2401 " ctermbg=LightCyan ctermfg=Black");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002402 coloncmd(":sign define %d linehl=NBGuarded", GUARDED);
2403
2404 did_init = TRUE;
2405 }
2406}
2407
2408/*
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002409 * Convert key to netbeans name. This uses the global "mod_mask".
Bram Moolenaar071d4272004-06-13 20:20:40 +00002410 */
2411 static void
2412netbeans_keyname(int key, char *buf)
2413{
2414 char *name = 0;
2415 char namebuf[2];
2416 int ctrl = 0;
2417 int shift = 0;
2418 int alt = 0;
2419
2420 if (mod_mask & MOD_MASK_CTRL)
2421 ctrl = 1;
2422 if (mod_mask & MOD_MASK_SHIFT)
2423 shift = 1;
2424 if (mod_mask & MOD_MASK_ALT)
2425 alt = 1;
2426
2427
2428 switch (key)
2429 {
2430 case K_F1: name = "F1"; break;
2431 case K_S_F1: name = "F1"; shift = 1; break;
2432 case K_F2: name = "F2"; break;
2433 case K_S_F2: name = "F2"; shift = 1; break;
2434 case K_F3: name = "F3"; break;
2435 case K_S_F3: name = "F3"; shift = 1; break;
2436 case K_F4: name = "F4"; break;
2437 case K_S_F4: name = "F4"; shift = 1; break;
2438 case K_F5: name = "F5"; break;
2439 case K_S_F5: name = "F5"; shift = 1; break;
2440 case K_F6: name = "F6"; break;
2441 case K_S_F6: name = "F6"; shift = 1; break;
2442 case K_F7: name = "F7"; break;
2443 case K_S_F7: name = "F7"; shift = 1; break;
2444 case K_F8: name = "F8"; break;
2445 case K_S_F8: name = "F8"; shift = 1; break;
2446 case K_F9: name = "F9"; break;
2447 case K_S_F9: name = "F9"; shift = 1; break;
2448 case K_F10: name = "F10"; break;
2449 case K_S_F10: name = "F10"; shift = 1; break;
2450 case K_F11: name = "F11"; break;
2451 case K_S_F11: name = "F11"; shift = 1; break;
2452 case K_F12: name = "F12"; break;
2453 case K_S_F12: name = "F12"; shift = 1; break;
2454 default:
2455 if (key >= ' ' && key <= '~')
2456 {
2457 /* Allow ASCII characters. */
2458 name = namebuf;
2459 namebuf[0] = key;
2460 namebuf[1] = NUL;
2461 }
2462 else
2463 name = "X";
2464 break;
2465 }
2466
2467 buf[0] = '\0';
2468 if (ctrl)
2469 strcat(buf, "C");
2470 if (shift)
2471 strcat(buf, "S");
2472 if (alt)
2473 strcat(buf, "M"); /* META */
2474 if (ctrl || shift || alt)
2475 strcat(buf, "-");
2476 strcat(buf, name);
2477}
2478
Bram Moolenaar67c53842010-05-22 18:28:27 +02002479#if defined(FEAT_BEVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002480/*
2481 * Function to be called for balloon evaluation. Grabs the text under the
2482 * cursor and sends it to the debugger for evaluation. The debugger should
2483 * respond with a showBalloon command when there is a useful result.
2484 */
Bram Moolenaard62bec82005-03-07 22:56:57 +00002485 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00002486netbeans_beval_cb(
2487 BalloonEval *beval,
Bram Moolenaarb85cb212009-05-17 14:24:23 +00002488 int state UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002489{
Bram Moolenaard62bec82005-03-07 22:56:57 +00002490 win_T *wp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002491 char_u *text;
Bram Moolenaard62bec82005-03-07 22:56:57 +00002492 linenr_T lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002493 int col;
Bram Moolenaard9462e32011-04-11 21:35:11 +02002494 char *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002495 char_u *p;
2496
2497 /* Don't do anything when 'ballooneval' is off, messages scrolled the
2498 * windows up or we have no connection. */
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002499 if (!p_beval || msg_scrolled > 0 || !NETBEANS_OPEN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002500 return;
2501
Bram Moolenaard62bec82005-03-07 22:56:57 +00002502 if (get_beval_info(beval, TRUE, &wp, &lnum, &text, &col) == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002503 {
2504 /* Send debugger request. Only when the text is of reasonable
2505 * length. */
2506 if (text != NULL && text[0] != NUL && STRLEN(text) < MAXPATHL)
2507 {
Bram Moolenaard9462e32011-04-11 21:35:11 +02002508 buf = (char *)alloc(MAXPATHL * 2 + 25);
2509 if (buf != NULL)
Bram Moolenaar009b2592004-10-24 19:18:58 +00002510 {
Bram Moolenaard9462e32011-04-11 21:35:11 +02002511 p = nb_quote(text);
2512 if (p != NULL)
2513 {
2514 vim_snprintf(buf, MAXPATHL * 2 + 25,
2515 "0:balloonText=%d \"%s\"\n", r_cmdno, p);
2516 vim_free(p);
2517 }
2518 nbdebug(("EVT: %s", buf));
2519 nb_send(buf, "netbeans_beval_cb");
2520 vim_free(buf);
Bram Moolenaar009b2592004-10-24 19:18:58 +00002521 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002522 }
2523 vim_free(text);
2524 }
2525}
2526#endif
2527
2528/*
Bram Moolenaare0874f82016-01-24 20:36:41 +01002529 * Return TRUE when the netbeans connection is active.
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002530 */
2531 int
2532netbeans_active(void)
2533{
2534 return NETBEANS_OPEN;
2535}
2536
Bram Moolenaar67c53842010-05-22 18:28:27 +02002537/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002538 * Tell netbeans that the window was opened, ready for commands.
2539 */
2540 void
Bram Moolenaarf506c5b2010-06-22 06:28:58 +02002541netbeans_open(char *params, int doabort)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002542{
2543 char *cmd = "0:startupDone=0\n";
2544
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002545 if (NETBEANS_OPEN)
2546 {
2547 EMSG(_("E511: netbeans already connected"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002548 return;
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002549 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002550
Bram Moolenaarf506c5b2010-06-22 06:28:58 +02002551 if (netbeans_connect(params, doabort) != OK)
Bram Moolenaar67c53842010-05-22 18:28:27 +02002552 return;
Bram Moolenaard62bec82005-03-07 22:56:57 +00002553
Bram Moolenaar071d4272004-06-13 20:20:40 +00002554 nbdebug(("EVT: %s", cmd));
2555 nb_send(cmd, "netbeans_startup_done");
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002556
2557 /* update the screen after having added the gutter */
2558 changed_window_setting();
2559 update_screen(CLEAR);
2560 setcursor();
Bram Moolenaar96bcc5e2011-04-01 15:33:59 +02002561 cursor_on();
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002562 out_flush();
2563#ifdef FEAT_GUI
Bram Moolenaard54a6882010-08-09 22:49:00 +02002564 if (gui.in_use)
2565 {
2566 gui_update_cursor(TRUE, FALSE);
2567 gui_mch_flush();
2568 }
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002569#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002570}
2571
Bram Moolenaar009b2592004-10-24 19:18:58 +00002572/*
2573 * Tell netbeans that we're exiting. This should be called right
2574 * before calling exit.
2575 */
2576 void
Bram Moolenaar9b578142016-01-30 19:39:49 +01002577netbeans_send_disconnect(void)
Bram Moolenaar009b2592004-10-24 19:18:58 +00002578{
2579 char buf[128];
2580
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002581 if (NETBEANS_OPEN)
Bram Moolenaar009b2592004-10-24 19:18:58 +00002582 {
Bram Moolenaar89d40322006-08-29 15:30:07 +00002583 sprintf(buf, "0:disconnect=%d\n", r_cmdno);
Bram Moolenaar009b2592004-10-24 19:18:58 +00002584 nbdebug(("EVT: %s", buf));
2585 nb_send(buf, "netbeans_disconnect");
2586 }
2587}
2588
Bram Moolenaar3266c852016-04-30 18:07:05 +02002589#if defined(FEAT_EVAL) || defined(PROTO)
2590 int
2591set_ref_in_nb_channel(int copyID)
2592{
2593 int abort = FALSE;
2594 typval_T tv;
2595
2596 if (nb_channel != NULL)
2597 {
2598 tv.v_type = VAR_CHANNEL;
2599 tv.vval.v_channel = nb_channel;
2600 abort = set_ref_in_item(&tv, copyID, NULL, NULL);
2601 }
2602 return abort;
2603}
2604#endif
2605
Bram Moolenaar173c9852010-09-29 17:27:01 +02002606#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_W32) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002607/*
2608 * Tell netbeans that the window was moved or resized.
2609 */
2610 void
2611netbeans_frame_moved(int new_x, int new_y)
2612{
2613 char buf[128];
2614
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002615 if (!NETBEANS_OPEN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002616 return;
2617
2618 sprintf(buf, "0:geometry=%d %d %d %d %d\n",
Bram Moolenaar89d40322006-08-29 15:30:07 +00002619 r_cmdno, (int)Columns, (int)Rows, new_x, new_y);
Bram Moolenaar009b2592004-10-24 19:18:58 +00002620 /*nbdebug(("EVT: %s", buf)); happens too many times during a move */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002621 nb_send(buf, "netbeans_frame_moved");
2622}
2623#endif
2624
2625/*
Bram Moolenaar009b2592004-10-24 19:18:58 +00002626 * Tell netbeans the user opened or activated a file.
2627 */
2628 void
2629netbeans_file_activated(buf_T *bufp)
2630{
2631 int bufno = nb_getbufno(bufp);
2632 nbbuf_T *bp = nb_get_buf(bufno);
2633 char buffer[2*MAXPATHL];
2634 char_u *q;
2635
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002636 if (!NETBEANS_OPEN || !bufp->b_netbeans_file || dosetvisible)
Bram Moolenaar009b2592004-10-24 19:18:58 +00002637 return;
2638
2639 q = nb_quote(bufp->b_ffname);
Bram Moolenaareb3593b2006-04-22 22:33:57 +00002640 if (q == NULL || bp == NULL)
Bram Moolenaar009b2592004-10-24 19:18:58 +00002641 return;
2642
Bram Moolenaar9c13b352005-05-19 20:53:52 +00002643 vim_snprintf(buffer, sizeof(buffer), "%d:fileOpened=%d \"%s\" %s %s\n",
Bram Moolenaar009b2592004-10-24 19:18:58 +00002644 bufno,
2645 bufno,
2646 (char *)q,
2647 "T", /* open in NetBeans */
2648 "F"); /* modified */
2649
2650 vim_free(q);
2651 nbdebug(("EVT: %s", buffer));
2652
2653 nb_send(buffer, "netbeans_file_opened");
2654}
2655
2656/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002657 * Tell netbeans the user opened a file.
2658 */
2659 void
Bram Moolenaar009b2592004-10-24 19:18:58 +00002660netbeans_file_opened(buf_T *bufp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002661{
Bram Moolenaar009b2592004-10-24 19:18:58 +00002662 int bufno = nb_getbufno(bufp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002663 char buffer[2*MAXPATHL];
2664 char_u *q;
Bram Moolenaar009b2592004-10-24 19:18:58 +00002665 nbbuf_T *bp = nb_get_buf(nb_getbufno(bufp));
2666 int bnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002667
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002668 if (!NETBEANS_OPEN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002669 return;
2670
Bram Moolenaar009b2592004-10-24 19:18:58 +00002671 q = nb_quote(bufp->b_ffname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002672 if (q == NULL)
2673 return;
Bram Moolenaar009b2592004-10-24 19:18:58 +00002674 if (bp != NULL)
2675 bnum = bufno;
2676 else
2677 bnum = 0;
2678
Bram Moolenaar9c13b352005-05-19 20:53:52 +00002679 vim_snprintf(buffer, sizeof(buffer), "%d:fileOpened=%d \"%s\" %s %s\n",
Bram Moolenaar009b2592004-10-24 19:18:58 +00002680 bnum,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002681 0,
2682 (char *)q,
2683 "T", /* open in NetBeans */
2684 "F"); /* modified */
2685
2686 vim_free(q);
2687 nbdebug(("EVT: %s", buffer));
2688
2689 nb_send(buffer, "netbeans_file_opened");
Bram Moolenaar009b2592004-10-24 19:18:58 +00002690 if (p_acd && vim_chdirfile(bufp->b_ffname) == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002691 shorten_fnames(TRUE);
2692}
2693
2694/*
Bram Moolenaard7f8f5c2009-01-06 15:14:30 +00002695 * Tell netbeans that a file was deleted or wiped out.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002696 */
2697 void
Bram Moolenaard7f8f5c2009-01-06 15:14:30 +00002698netbeans_file_killed(buf_T *bufp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002699{
2700 int bufno = nb_getbufno(bufp);
2701 nbbuf_T *nbbuf = nb_get_buf(bufno);
2702 char buffer[2*MAXPATHL];
2703
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002704 if (!NETBEANS_OPEN || bufno == -1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002705 return;
2706
Bram Moolenaard7f8f5c2009-01-06 15:14:30 +00002707 nbdebug(("netbeans_file_killed:\n"));
2708 nbdebug((" Killing bufno: %d", bufno));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002709
Bram Moolenaar89d40322006-08-29 15:30:07 +00002710 sprintf(buffer, "%d:killed=%d\n", bufno, r_cmdno);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002711
2712 nbdebug(("EVT: %s", buffer));
2713
Bram Moolenaard7f8f5c2009-01-06 15:14:30 +00002714 nb_send(buffer, "netbeans_file_killed");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002715
2716 if (nbbuf != NULL)
2717 nbbuf->bufp = NULL;
2718}
2719
2720/*
2721 * Get a pointer to the Netbeans buffer for Vim buffer "bufp".
2722 * Return NULL if there is no such buffer or changes are not to be reported.
2723 * Otherwise store the buffer number in "*bufnop".
2724 */
2725 static nbbuf_T *
2726nb_bufp2nbbuf_fire(buf_T *bufp, int *bufnop)
2727{
2728 int bufno;
2729 nbbuf_T *nbbuf;
2730
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002731 if (!NETBEANS_OPEN || !netbeansFireChanges)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002732 return NULL; /* changes are not reported at all */
2733
2734 bufno = nb_getbufno(bufp);
2735 if (bufno <= 0)
2736 return NULL; /* file is not known to NetBeans */
2737
2738 nbbuf = nb_get_buf(bufno);
2739 if (nbbuf != NULL && !nbbuf->fireChanges)
2740 return NULL; /* changes in this buffer are not reported */
2741
2742 *bufnop = bufno;
2743 return nbbuf;
2744}
2745
2746/*
2747 * Tell netbeans the user inserted some text.
2748 */
2749 void
2750netbeans_inserted(
2751 buf_T *bufp,
2752 linenr_T linenr,
2753 colnr_T col,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002754 char_u *txt,
2755 int newlen)
2756{
2757 char_u *buf;
2758 int bufno;
2759 nbbuf_T *nbbuf;
2760 pos_T pos;
2761 long off;
2762 char_u *p;
2763 char_u *newtxt;
2764
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002765 if (!NETBEANS_OPEN)
2766 return;
2767
Bram Moolenaar071d4272004-06-13 20:20:40 +00002768 nbbuf = nb_bufp2nbbuf_fire(bufp, &bufno);
2769 if (nbbuf == NULL)
2770 return;
2771
Bram Moolenaar009b2592004-10-24 19:18:58 +00002772 /* Don't mark as modified for initial read */
2773 if (nbbuf->insertDone)
2774 nbbuf->modified = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002775
2776 pos.lnum = linenr;
2777 pos.col = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002778 off = pos2off(bufp, &pos);
2779
Bram Moolenaar071d4272004-06-13 20:20:40 +00002780 /* send the "insert" EVT */
2781 newtxt = alloc(newlen + 1);
Bram Moolenaarb6356332005-07-18 21:40:44 +00002782 vim_strncpy(newtxt, txt, newlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002783 p = nb_quote(newtxt);
2784 if (p != NULL)
2785 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00002786 buf = alloc(128 + 2*newlen);
Bram Moolenaar89d40322006-08-29 15:30:07 +00002787 sprintf((char *)buf, "%d:insert=%d %ld \"%s\"\n",
2788 bufno, r_cmdno, off, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002789 nbdebug(("EVT: %s", buf));
2790 nb_send((char *)buf, "netbeans_inserted");
Bram Moolenaar009b2592004-10-24 19:18:58 +00002791 vim_free(p);
2792 vim_free(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002793 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002794 vim_free(newtxt);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002795}
2796
2797/*
2798 * Tell netbeans some bytes have been removed.
2799 */
2800 void
2801netbeans_removed(
2802 buf_T *bufp,
2803 linenr_T linenr,
2804 colnr_T col,
2805 long len)
2806{
2807 char_u buf[128];
2808 int bufno;
2809 nbbuf_T *nbbuf;
2810 pos_T pos;
2811 long off;
2812
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002813 if (!NETBEANS_OPEN)
2814 return;
2815
Bram Moolenaar071d4272004-06-13 20:20:40 +00002816 nbbuf = nb_bufp2nbbuf_fire(bufp, &bufno);
2817 if (nbbuf == NULL)
2818 return;
2819
2820 if (len < 0)
2821 {
Bram Moolenaarf2330482008-06-24 20:19:36 +00002822 nbdebug(("Negative len %ld in netbeans_removed()!\n", len));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002823 return;
2824 }
2825
2826 nbbuf->modified = 1;
2827
2828 pos.lnum = linenr;
2829 pos.col = col;
2830
2831 off = pos2off(bufp, &pos);
2832
Bram Moolenaar89d40322006-08-29 15:30:07 +00002833 sprintf((char *)buf, "%d:remove=%d %ld %ld\n", bufno, r_cmdno, off, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002834 nbdebug(("EVT: %s", buf));
2835 nb_send((char *)buf, "netbeans_removed");
2836}
2837
2838/*
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01002839 * Send netbeans an unmodified command.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002840 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002841 void
Bram Moolenaarb85cb212009-05-17 14:24:23 +00002842netbeans_unmodified(buf_T *bufp UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002843{
Bram Moolenaar09092152010-08-08 16:38:42 +02002844 /* This is a no-op, because NetBeans considers a buffer modified
Bram Moolenaar071d4272004-06-13 20:20:40 +00002845 * even when all changes have been undone. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002846}
2847
2848/*
2849 * Send a button release event back to netbeans. Its up to netbeans
2850 * to decide what to do (if anything) with this event.
2851 */
2852 void
2853netbeans_button_release(int button)
2854{
2855 char buf[128];
2856 int bufno;
2857
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002858 if (!NETBEANS_OPEN)
2859 return;
2860
Bram Moolenaar071d4272004-06-13 20:20:40 +00002861 bufno = nb_getbufno(curbuf);
2862
2863 if (bufno >= 0 && curwin != NULL && curwin->w_buffer == curbuf)
2864 {
Bram Moolenaar64486672010-05-16 15:46:46 +02002865 int col = mouse_col - W_WINCOL(curwin)
Bram Moolenaar67c53842010-05-22 18:28:27 +02002866 - ((curwin->w_p_nu || curwin->w_p_rnu) ? 9 : 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002867 long off = pos2off(curbuf, &curwin->w_cursor);
2868
2869 /* sync the cursor position */
Bram Moolenaar89d40322006-08-29 15:30:07 +00002870 sprintf(buf, "%d:newDotAndMark=%d %ld %ld\n", bufno, r_cmdno, off, off);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002871 nbdebug(("EVT: %s", buf));
2872 nb_send(buf, "netbeans_button_release[newDotAndMark]");
2873
Bram Moolenaar89d40322006-08-29 15:30:07 +00002874 sprintf(buf, "%d:buttonRelease=%d %d %ld %d\n", bufno, r_cmdno,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002875 button, (long)curwin->w_cursor.lnum, col);
2876 nbdebug(("EVT: %s", buf));
2877 nb_send(buf, "netbeans_button_release");
2878 }
2879}
2880
2881
2882/*
Bram Moolenaar143c38c2007-05-10 16:41:10 +00002883 * Send a keypress event back to netbeans. This usually simulates some
Bram Moolenaar009b2592004-10-24 19:18:58 +00002884 * kind of function key press. This function operates on a key code.
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002885 * Return TRUE when the key was sent, FALSE when the command has been
2886 * postponed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002887 */
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002888 int
Bram Moolenaar071d4272004-06-13 20:20:40 +00002889netbeans_keycommand(int key)
2890{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002891 char keyName[60];
Bram Moolenaar009b2592004-10-24 19:18:58 +00002892
2893 netbeans_keyname(key, keyName);
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002894 return netbeans_keystring((char_u *)keyName);
Bram Moolenaar009b2592004-10-24 19:18:58 +00002895}
2896
2897
2898/*
Bram Moolenaar143c38c2007-05-10 16:41:10 +00002899 * Send a keypress event back to netbeans. This usually simulates some
Bram Moolenaar009b2592004-10-24 19:18:58 +00002900 * kind of function key press. This function operates on a key string.
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002901 * Return TRUE when the key was sent, FALSE when the command has been
2902 * postponed.
Bram Moolenaar009b2592004-10-24 19:18:58 +00002903 */
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002904 static int
2905netbeans_keystring(char_u *keyName)
Bram Moolenaar009b2592004-10-24 19:18:58 +00002906{
2907 char buf[2*MAXPATHL];
2908 int bufno = nb_getbufno(curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002909 long off;
2910 char_u *q;
2911
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002912 if (!NETBEANS_OPEN)
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002913 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002914
Bram Moolenaar071d4272004-06-13 20:20:40 +00002915 if (bufno == -1)
2916 {
2917 nbdebug(("got keycommand for non-NetBeans buffer, opening...\n"));
2918 q = curbuf->b_ffname == NULL ? (char_u *)""
2919 : nb_quote(curbuf->b_ffname);
2920 if (q == NULL)
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002921 return TRUE;
Bram Moolenaar9c13b352005-05-19 20:53:52 +00002922 vim_snprintf(buf, sizeof(buf), "0:fileOpened=%d \"%s\" %s %s\n", 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002923 q,
2924 "T", /* open in NetBeans */
2925 "F"); /* modified */
2926 if (curbuf->b_ffname != NULL)
2927 vim_free(q);
2928 nbdebug(("EVT: %s", buf));
2929 nb_send(buf, "netbeans_keycommand");
2930
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002931 postpone_keycommand(keyName);
2932 return FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002933 }
2934
2935 /* sync the cursor position */
2936 off = pos2off(curbuf, &curwin->w_cursor);
Bram Moolenaar89d40322006-08-29 15:30:07 +00002937 sprintf(buf, "%d:newDotAndMark=%d %ld %ld\n", bufno, r_cmdno, off, off);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002938 nbdebug(("EVT: %s", buf));
2939 nb_send(buf, "netbeans_keycommand");
2940
2941 /* To work on Win32 you must apply patch to ExtEditor module
2942 * from ExtEdCaret.java.diff - make EVT_newDotAndMark handler
2943 * more synchronous
2944 */
2945
2946 /* now send keyCommand event */
Bram Moolenaar9c13b352005-05-19 20:53:52 +00002947 vim_snprintf(buf, sizeof(buf), "%d:keyCommand=%d \"%s\"\n",
Bram Moolenaar89d40322006-08-29 15:30:07 +00002948 bufno, r_cmdno, keyName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002949 nbdebug(("EVT: %s", buf));
2950 nb_send(buf, "netbeans_keycommand");
2951
2952 /* New: do both at once and include the lnum/col. */
Bram Moolenaar9c13b352005-05-19 20:53:52 +00002953 vim_snprintf(buf, sizeof(buf), "%d:keyAtPos=%d \"%s\" %ld %ld/%ld\n",
Bram Moolenaar89d40322006-08-29 15:30:07 +00002954 bufno, r_cmdno, keyName,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002955 off, (long)curwin->w_cursor.lnum, (long)curwin->w_cursor.col);
2956 nbdebug(("EVT: %s", buf));
2957 nb_send(buf, "netbeans_keycommand");
Bram Moolenaar8065d7f2010-01-19 15:13:14 +01002958 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002959}
2960
2961
2962/*
2963 * Send a save event to netbeans.
2964 */
2965 void
2966netbeans_save_buffer(buf_T *bufp)
2967{
2968 char_u buf[64];
2969 int bufno;
2970 nbbuf_T *nbbuf;
2971
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002972 if (!NETBEANS_OPEN)
2973 return;
2974
Bram Moolenaar071d4272004-06-13 20:20:40 +00002975 nbbuf = nb_bufp2nbbuf_fire(bufp, &bufno);
2976 if (nbbuf == NULL)
2977 return;
2978
2979 nbbuf->modified = 0;
2980
Bram Moolenaar89d40322006-08-29 15:30:07 +00002981 sprintf((char *)buf, "%d:save=%d\n", bufno, r_cmdno);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002982 nbdebug(("EVT: %s", buf));
2983 nb_send((char *)buf, "netbeans_save_buffer");
2984}
2985
2986
2987/*
2988 * Send remove command to netbeans (this command has been turned off).
2989 */
2990 void
2991netbeans_deleted_all_lines(buf_T *bufp)
2992{
2993 char_u buf[64];
2994 int bufno;
2995 nbbuf_T *nbbuf;
2996
Bram Moolenaarb26e6322010-05-22 21:34:09 +02002997 if (!NETBEANS_OPEN)
2998 return;
2999
Bram Moolenaar071d4272004-06-13 20:20:40 +00003000 nbbuf = nb_bufp2nbbuf_fire(bufp, &bufno);
3001 if (nbbuf == NULL)
3002 return;
3003
Bram Moolenaar009b2592004-10-24 19:18:58 +00003004 /* Don't mark as modified for initial read */
3005 if (nbbuf->insertDone)
3006 nbbuf->modified = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003007
Bram Moolenaar89d40322006-08-29 15:30:07 +00003008 sprintf((char *)buf, "%d:remove=%d 0 -1\n", bufno, r_cmdno);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003009 nbdebug(("EVT(suppressed): %s", buf));
3010/* nb_send(buf, "netbeans_deleted_all_lines"); */
3011}
3012
3013
3014/*
3015 * See if the lines are guarded. The top and bot parameters are from
3016 * u_savecommon(), these are the line above the change and the line below the
3017 * change.
3018 */
3019 int
3020netbeans_is_guarded(linenr_T top, linenr_T bot)
3021{
3022 signlist_T *p;
3023 int lnum;
3024
Bram Moolenaarb26e6322010-05-22 21:34:09 +02003025 if (!NETBEANS_OPEN)
3026 return FALSE;
3027
Bram Moolenaar071d4272004-06-13 20:20:40 +00003028 for (p = curbuf->b_signlist; p != NULL; p = p->next)
3029 if (p->id >= GUARDEDOFFSET)
3030 for (lnum = top + 1; lnum < bot; lnum++)
3031 if (lnum == p->lnum)
3032 return TRUE;
3033
3034 return FALSE;
3035}
3036
Bram Moolenaar173c9852010-09-29 17:27:01 +02003037#if defined(FEAT_GUI_X11) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003038/*
3039 * We have multiple signs to draw at the same location. Draw the
3040 * multi-sign indicator instead. This is the Motif version.
3041 */
3042 void
3043netbeans_draw_multisign_indicator(int row)
3044{
3045 int i;
3046 int y;
3047 int x;
3048
Bram Moolenaarb26e6322010-05-22 21:34:09 +02003049 if (!NETBEANS_OPEN)
3050 return;
3051
Bram Moolenaar071d4272004-06-13 20:20:40 +00003052 x = 0;
3053 y = row * gui.char_height + 2;
3054
3055 for (i = 0; i < gui.char_height - 3; i++)
3056 XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+2, y++);
3057
3058 XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+0, y);
3059 XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+2, y);
3060 XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+4, y++);
3061 XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+1, y);
3062 XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+2, y);
3063 XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+3, y++);
3064 XDrawPoint(gui.dpy, gui.wid, gui.text_gc, x+2, y);
3065}
Bram Moolenaar173c9852010-09-29 17:27:01 +02003066#endif /* FEAT_GUI_X11 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003067
Bram Moolenaar64404472010-06-26 06:24:45 +02003068#if defined(FEAT_GUI_GTK) && !defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003069/*
3070 * We have multiple signs to draw at the same location. Draw the
3071 * multi-sign indicator instead. This is the GTK/Gnome version.
3072 */
3073 void
3074netbeans_draw_multisign_indicator(int row)
3075{
3076 int i;
3077 int y;
3078 int x;
Bram Moolenaar98921892016-02-23 17:14:37 +01003079#if GTK_CHECK_VERSION(3,0,0)
3080 cairo_t *cr = NULL;
3081#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003082 GdkDrawable *drawable = gui.drawarea->window;
Bram Moolenaar98921892016-02-23 17:14:37 +01003083#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003084
Bram Moolenaarb26e6322010-05-22 21:34:09 +02003085 if (!NETBEANS_OPEN)
3086 return;
3087
Bram Moolenaar98921892016-02-23 17:14:37 +01003088#if GTK_CHECK_VERSION(3,0,0)
3089 cr = cairo_create(gui.surface);
3090 {
3091 GdkVisual *visual = NULL;
3092 guint32 r_mask, g_mask, b_mask;
3093 gint r_shift, g_shift, b_shift;
3094
3095 visual = gdk_window_get_visual(gtk_widget_get_window(gui.drawarea));
3096 if (visual != NULL)
3097 {
3098 gdk_visual_get_red_pixel_details(visual, &r_mask, &r_shift, NULL);
3099 gdk_visual_get_green_pixel_details(visual, &g_mask, &g_shift, NULL);
3100 gdk_visual_get_blue_pixel_details(visual, &b_mask, &b_shift, NULL);
3101
3102 cairo_set_source_rgb(cr,
3103 ((gui.fgcolor->red & r_mask) >> r_shift) / 255.0,
3104 ((gui.fgcolor->green & g_mask) >> g_shift) / 255.0,
3105 ((gui.fgcolor->blue & b_mask) >> b_shift) / 255.0);
3106 }
3107 }
3108#endif
3109
Bram Moolenaar071d4272004-06-13 20:20:40 +00003110 x = 0;
3111 y = row * gui.char_height + 2;
3112
3113 for (i = 0; i < gui.char_height - 3; i++)
Bram Moolenaar98921892016-02-23 17:14:37 +01003114#if GTK_CHECK_VERSION(3,0,0)
3115 cairo_rectangle(cr, x+2, y++, 1, 1);
3116#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003117 gdk_draw_point(drawable, gui.text_gc, x+2, y++);
Bram Moolenaar98921892016-02-23 17:14:37 +01003118#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003119
Bram Moolenaar98921892016-02-23 17:14:37 +01003120#if GTK_CHECK_VERSION(3,0,0)
3121 cairo_rectangle(cr, x+0, y, 1, 1);
3122 cairo_rectangle(cr, x+2, y, 1, 1);
3123 cairo_rectangle(cr, x+4, y++, 1, 1);
3124 cairo_rectangle(cr, x+1, y, 1, 1);
3125 cairo_rectangle(cr, x+2, y, 1, 1);
3126 cairo_rectangle(cr, x+3, y++, 1, 1);
3127 cairo_rectangle(cr, x+2, y, 1, 1);
3128#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003129 gdk_draw_point(drawable, gui.text_gc, x+0, y);
3130 gdk_draw_point(drawable, gui.text_gc, x+2, y);
3131 gdk_draw_point(drawable, gui.text_gc, x+4, y++);
3132 gdk_draw_point(drawable, gui.text_gc, x+1, y);
3133 gdk_draw_point(drawable, gui.text_gc, x+2, y);
3134 gdk_draw_point(drawable, gui.text_gc, x+3, y++);
3135 gdk_draw_point(drawable, gui.text_gc, x+2, y);
Bram Moolenaar98921892016-02-23 17:14:37 +01003136#endif
3137
3138#if GTK_CHECK_VERSION(3,0,0)
3139 cairo_destroy(cr);
3140#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003141}
3142#endif /* FEAT_GUI_GTK */
3143
3144/*
3145 * If the mouse is clicked in the gutter of a line with multiple
3146 * annotations, cycle through the set of signs.
3147 */
3148 void
3149netbeans_gutter_click(linenr_T lnum)
3150{
3151 signlist_T *p;
3152
Bram Moolenaarb26e6322010-05-22 21:34:09 +02003153 if (!NETBEANS_OPEN)
3154 return;
3155
Bram Moolenaar071d4272004-06-13 20:20:40 +00003156 for (p = curbuf->b_signlist; p != NULL; p = p->next)
3157 {
3158 if (p->lnum == lnum && p->next && p->next->lnum == lnum)
3159 {
3160 signlist_T *tail;
3161
3162 /* remove "p" from list, reinsert it at the tail of the sublist */
3163 if (p->prev)
3164 p->prev->next = p->next;
3165 else
3166 curbuf->b_signlist = p->next;
3167 p->next->prev = p->prev;
3168 /* now find end of sublist and insert p */
3169 for (tail = p->next;
3170 tail->next && tail->next->lnum == lnum
3171 && tail->next->id < GUARDEDOFFSET;
3172 tail = tail->next)
3173 ;
3174 /* tail now points to last entry with same lnum (except
3175 * that "guarded" annotations are always last) */
3176 p->next = tail->next;
3177 if (tail->next)
3178 tail->next->prev = p;
3179 p->prev = tail;
3180 tail->next = p;
3181 update_debug_sign(curbuf, lnum);
3182 break;
3183 }
3184 }
3185}
3186
Bram Moolenaar071d4272004-06-13 20:20:40 +00003187/*
Bram Moolenaar2660c0e2010-01-19 14:59:56 +01003188 * Add a sign of the requested type at the requested location.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003189 *
3190 * Reverse engineering:
3191 * Apparently an annotation is defined the first time it is used in a buffer.
3192 * When the same annotation is used in two buffers, the second time we do not
3193 * need to define a new sign name but reuse the existing one. But since the
3194 * ID number used in the second buffer starts counting at one again, a mapping
3195 * is made from the ID specifically for the buffer to the global sign name
3196 * (which is a number).
3197 *
3198 * globalsignmap[] stores the signs that have been defined globally.
3199 * buf->signmapused[] maps buffer-local annotation IDs to an index in
3200 * globalsignmap[].
3201 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003202 static void
3203addsigntype(
3204 nbbuf_T *buf,
3205 int typeNum,
3206 char_u *typeName,
Bram Moolenaarb85cb212009-05-17 14:24:23 +00003207 char_u *tooltip UNUSED,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003208 char_u *glyphFile,
Bram Moolenaar67c53842010-05-22 18:28:27 +02003209 char_u *fg,
3210 char_u *bg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003211{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003212 int i, j;
Bram Moolenaar67c53842010-05-22 18:28:27 +02003213 int use_fg = (*fg && STRCMP(fg, "none") != 0);
3214 int use_bg = (*bg && STRCMP(bg, "none") != 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003215
3216 for (i = 0; i < globalsignmapused; i++)
3217 if (STRCMP(typeName, globalsignmap[i]) == 0)
3218 break;
3219
3220 if (i == globalsignmapused) /* not found; add it to global map */
3221 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02003222 nbdebug(("DEFINEANNOTYPE(%d,%s,%s,%s,%s,%s)\n",
Bram Moolenaar071d4272004-06-13 20:20:40 +00003223 typeNum, typeName, tooltip, glyphFile, fg, bg));
3224 if (use_fg || use_bg)
3225 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02003226 char fgbuf[2 * (8 + MAX_COLOR_LENGTH) + 1];
3227 char bgbuf[2 * (8 + MAX_COLOR_LENGTH) + 1];
3228 char *ptr;
3229 int value;
3230
3231 value = strtol((char *)fg, &ptr, 10);
3232 if (ptr != (char *)fg)
3233 sprintf(fgbuf, "guifg=#%06x", value & 0xFFFFFF);
3234 else
3235 sprintf(fgbuf, "guifg=%s ctermfg=%s", fg, fg);
3236
3237 value = strtol((char *)bg, &ptr, 10);
3238 if (ptr != (char *)bg)
3239 sprintf(bgbuf, "guibg=#%06x", value & 0xFFFFFF);
3240 else
3241 sprintf(bgbuf, "guibg=%s ctermbg=%s", bg, bg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003242
3243 coloncmd(":highlight NB_%s %s %s", typeName, (use_fg) ? fgbuf : "",
3244 (use_bg) ? bgbuf : "");
3245 if (*glyphFile == NUL)
3246 /* no glyph, line highlighting only */
3247 coloncmd(":sign define %d linehl=NB_%s", i + 1, typeName);
3248 else if (vim_strsize(glyphFile) <= 2)
3249 /* one- or two-character glyph name, use as text glyph with
3250 * texthl */
3251 coloncmd(":sign define %d text=%s texthl=NB_%s", i + 1,
3252 glyphFile, typeName);
3253 else
3254 /* glyph, line highlighting */
3255 coloncmd(":sign define %d icon=%s linehl=NB_%s", i + 1,
3256 glyphFile, typeName);
3257 }
3258 else
3259 /* glyph, no line highlighting */
3260 coloncmd(":sign define %d icon=%s", i + 1, glyphFile);
3261
3262 if (STRCMP(typeName,"CurrentPC") == 0)
3263 curPCtype = typeNum;
3264
3265 if (globalsignmapused == globalsignmaplen)
3266 {
3267 if (globalsignmaplen == 0) /* first allocation */
3268 {
3269 globalsignmaplen = 20;
3270 globalsignmap = (char **)alloc_clear(globalsignmaplen*sizeof(char *));
3271 }
3272 else /* grow it */
3273 {
3274 int incr;
3275 int oldlen = globalsignmaplen;
Bram Moolenaar9abd5c62015-02-10 18:34:01 +01003276 char **t_globalsignmap = globalsignmap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003277
3278 globalsignmaplen *= 2;
3279 incr = globalsignmaplen - oldlen;
3280 globalsignmap = (char **)vim_realloc(globalsignmap,
3281 globalsignmaplen * sizeof(char *));
Bram Moolenaar9abd5c62015-02-10 18:34:01 +01003282 if (globalsignmap == NULL)
3283 {
3284 vim_free(t_globalsignmap);
3285 globalsignmaplen = 0;
3286 return;
3287 }
Bram Moolenaar7db5fc82010-05-24 11:59:29 +02003288 vim_memset(globalsignmap + oldlen, 0, incr * sizeof(char *));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003289 }
3290 }
3291
3292 globalsignmap[i] = (char *)typeName;
3293 globalsignmapused = i + 1;
3294 }
3295
3296 /* check local map; should *not* be found! */
3297 for (j = 0; j < buf->signmapused; j++)
3298 if (buf->signmap[j] == i + 1)
3299 return;
3300
3301 /* add to local map */
3302 if (buf->signmapused == buf->signmaplen)
3303 {
3304 if (buf->signmaplen == 0) /* first allocation */
3305 {
3306 buf->signmaplen = 5;
Bram Moolenaara9d52e32010-07-31 16:44:19 +02003307 buf->signmap = (int *)alloc_clear(buf->signmaplen * sizeof(int));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003308 }
3309 else /* grow it */
3310 {
3311 int incr;
3312 int oldlen = buf->signmaplen;
Bram Moolenaar9abd5c62015-02-10 18:34:01 +01003313 int *t_signmap = buf->signmap;
Bram Moolenaara9d52e32010-07-31 16:44:19 +02003314
Bram Moolenaar071d4272004-06-13 20:20:40 +00003315 buf->signmaplen *= 2;
3316 incr = buf->signmaplen - oldlen;
3317 buf->signmap = (int *)vim_realloc(buf->signmap,
Bram Moolenaara9d52e32010-07-31 16:44:19 +02003318 buf->signmaplen * sizeof(int));
Bram Moolenaar9abd5c62015-02-10 18:34:01 +01003319 if (buf->signmap == NULL)
3320 {
3321 vim_free(t_signmap);
3322 buf->signmaplen = 0;
3323 return;
3324 }
Bram Moolenaara9d52e32010-07-31 16:44:19 +02003325 vim_memset(buf->signmap + oldlen, 0, incr * sizeof(int));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003326 }
3327 }
3328
3329 buf->signmap[buf->signmapused++] = i + 1;
3330
3331}
3332
3333
3334/*
3335 * See if we have the requested sign type in the buffer.
3336 */
3337 static int
3338mapsigntype(nbbuf_T *buf, int localsigntype)
3339{
3340 if (--localsigntype >= 0 && localsigntype < buf->signmapused)
3341 return buf->signmap[localsigntype];
3342
3343 return 0;
3344}
3345
3346
3347/*
3348 * Compute length of buffer, don't print anything.
3349 */
3350 static long
3351get_buf_size(buf_T *bufp)
3352{
3353 linenr_T lnum;
3354 long char_count = 0;
3355 int eol_size;
3356 long last_check = 100000L;
3357
3358 if (bufp->b_ml.ml_flags & ML_EMPTY)
3359 return 0;
3360 else
3361 {
3362 if (get_fileformat(bufp) == EOL_DOS)
3363 eol_size = 2;
3364 else
3365 eol_size = 1;
3366 for (lnum = 1; lnum <= bufp->b_ml.ml_line_count; ++lnum)
3367 {
Bram Moolenaarfa68b0f2009-09-11 12:19:51 +00003368 char_count += (long)STRLEN(ml_get_buf(bufp, lnum, FALSE))
3369 + eol_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003370 /* Check for a CTRL-C every 100000 characters */
3371 if (char_count > last_check)
3372 {
3373 ui_breakcheck();
3374 if (got_int)
3375 return char_count;
3376 last_check = char_count + 100000L;
3377 }
3378 }
3379 /* Correction for when last line doesn't have an EOL. */
Bram Moolenaar34d72d42015-07-17 14:18:08 +02003380 if (!bufp->b_p_eol && (bufp->b_p_bin || !bufp->b_p_fixeol))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003381 char_count -= eol_size;
3382 }
3383
3384 return char_count;
3385}
3386
3387/*
3388 * Convert character offset to lnum,col
3389 */
3390 static pos_T *
3391off2pos(buf_T *buf, long offset)
3392{
3393 linenr_T lnum;
3394 static pos_T pos;
3395
3396 pos.lnum = 0;
3397 pos.col = 0;
3398#ifdef FEAT_VIRTUALEDIT
3399 pos.coladd = 0;
3400#endif
3401
3402 if (!(buf->b_ml.ml_flags & ML_EMPTY))
3403 {
3404 if ((lnum = ml_find_line_or_offset(buf, (linenr_T)0, &offset)) < 0)
3405 return NULL;
3406 pos.lnum = lnum;
3407 pos.col = offset;
3408 }
3409
3410 return &pos;
3411}
3412
3413/*
3414 * Convert an argument in the form "1234" to an offset and compute the
3415 * lnum/col from it. Convert an argument in the form "123/12" directly to a
3416 * lnum/col.
3417 * "argp" is advanced to after the argument.
3418 * Return a pointer to the position, NULL if something is wrong.
3419 */
3420 static pos_T *
3421get_off_or_lnum(buf_T *buf, char_u **argp)
3422{
3423 static pos_T mypos;
3424 long off;
3425
3426 off = strtol((char *)*argp, (char **)argp, 10);
3427 if (**argp == '/')
3428 {
3429 mypos.lnum = (linenr_T)off;
3430 ++*argp;
3431 mypos.col = strtol((char *)*argp, (char **)argp, 10);
3432#ifdef FEAT_VIRTUALEDIT
3433 mypos.coladd = 0;
3434#endif
3435 return &mypos;
3436 }
3437 return off2pos(buf, off);
3438}
3439
3440
3441/*
Bram Moolenaar1d2ba7f2006-02-14 22:29:30 +00003442 * Convert (lnum,col) to byte offset in the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003443 */
3444 static long
3445pos2off(buf_T *buf, pos_T *pos)
3446{
3447 long offset = 0;
3448
3449 if (!(buf->b_ml.ml_flags & ML_EMPTY))
3450 {
3451 if ((offset = ml_find_line_or_offset(buf, pos->lnum, 0)) < 0)
3452 return 0;
3453 offset += pos->col;
3454 }
3455
3456 return offset;
3457}
3458
3459
Bram Moolenaar009b2592004-10-24 19:18:58 +00003460/*
3461 * This message is printed after NetBeans opens a new file. Its
3462 * similar to the message readfile() uses, but since NetBeans
3463 * doesn't normally call readfile, we do our own.
3464 */
3465 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01003466print_read_msg(nbbuf_T *buf)
Bram Moolenaar009b2592004-10-24 19:18:58 +00003467{
3468 int lnum = buf->bufp->b_ml.ml_line_count;
Bram Moolenaar914703b2010-05-31 21:59:46 +02003469 off_t nchars = buf->bufp->b_orig_size;
Bram Moolenaar009b2592004-10-24 19:18:58 +00003470 char_u c;
3471
3472 msg_add_fname(buf->bufp, buf->bufp->b_ffname);
3473 c = FALSE;
3474
3475 if (buf->bufp->b_p_ro)
3476 {
3477 STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
3478 c = TRUE;
3479 }
3480 if (!buf->bufp->b_start_eol)
3481 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02003482 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]")
3483 : _("[Incomplete last line]"));
Bram Moolenaar009b2592004-10-24 19:18:58 +00003484 c = TRUE;
3485 }
3486 msg_add_lines(c, (long)lnum, nchars);
3487
3488 /* Now display it */
3489 vim_free(keep_msg);
3490 keep_msg = NULL;
3491 msg_scrolled_ign = TRUE;
3492 msg_trunc_attr(IObuff, FALSE, 0);
3493 msg_scrolled_ign = FALSE;
3494}
3495
3496
3497/*
Bram Moolenaar67c53842010-05-22 18:28:27 +02003498 * Print a message after NetBeans writes the file. This message should be
3499 * identical to the standard message a non-netbeans user would see when
3500 * writing a file.
Bram Moolenaar009b2592004-10-24 19:18:58 +00003501 */
3502 static void
Bram Moolenaar9b578142016-01-30 19:39:49 +01003503print_save_msg(nbbuf_T *buf, off_t nchars)
Bram Moolenaar009b2592004-10-24 19:18:58 +00003504{
3505 char_u c;
3506 char_u *p;
3507
3508 if (nchars >= 0)
3509 {
Bram Moolenaar67c53842010-05-22 18:28:27 +02003510 /* put fname in IObuff with quotes */
3511 msg_add_fname(buf->bufp, buf->bufp->b_ffname);
Bram Moolenaar009b2592004-10-24 19:18:58 +00003512 c = FALSE;
3513
3514 msg_add_lines(c, buf->bufp->b_ml.ml_line_count,
Bram Moolenaar914703b2010-05-31 21:59:46 +02003515 buf->bufp->b_orig_size);
Bram Moolenaar009b2592004-10-24 19:18:58 +00003516
3517 vim_free(keep_msg);
3518 keep_msg = NULL;
3519 msg_scrolled_ign = TRUE;
3520 p = msg_trunc_attr(IObuff, FALSE, 0);
3521 if ((msg_scrolled && !need_wait_return) || !buf->initDone)
3522 {
3523 /* Need to repeat the message after redrawing when:
3524 * - When reading from stdin (the screen will be cleared next).
3525 * - When restart_edit is set (otherwise there will be a delay
3526 * before redrawing).
3527 * - When the screen was scrolled but there is no wait-return
3528 * prompt. */
Bram Moolenaar030f0df2006-02-21 22:02:53 +00003529 set_keep_msg(p, 0);
Bram Moolenaar009b2592004-10-24 19:18:58 +00003530 }
3531 msg_scrolled_ign = FALSE;
3532 /* add_to_input_buf((char_u *)"\f", 1); */
3533 }
3534 else
3535 {
Bram Moolenaaref9d6aa2011-04-11 16:56:35 +02003536 char_u msgbuf[IOSIZE];
Bram Moolenaar009b2592004-10-24 19:18:58 +00003537
Bram Moolenaaref9d6aa2011-04-11 16:56:35 +02003538 vim_snprintf((char *)msgbuf, IOSIZE,
3539 _("E505: %s is read-only (add ! to override)"), IObuff);
3540 nbdebug((" %s\n", msgbuf));
3541 emsg(msgbuf);
Bram Moolenaar009b2592004-10-24 19:18:58 +00003542 }
3543}
3544
Bram Moolenaar071d4272004-06-13 20:20:40 +00003545#endif /* defined(FEAT_NETBEANS_INTG) */