Mercurial > vim
annotate src/integration.c @ 15089:e428882d6ffb v8.1.0555
patch 8.1.0555: crash when last search pat is set but not last substitute pat
commit https://github.com/vim/vim/commit/2fb8f684d888ad68b283ba8f9505106b5fb725be
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Dec 1 13:14:45 2018 +0100
patch 8.1.0555: crash when last search pat is set but not last substitute pat
Problem: Crash when last search pat is set but not last substitute pat.
Solution: Do not mix up last search pattern and last subtitute pattern.
(closes #3647)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 01 Dec 2018 13:15:04 +0100 |
parents | 27b9a84395b5 |
children | 0fcc1315c061 |
rev | line source |
---|---|
10042
4aead6a9b7a9
commit https://github.com/vim/vim/commit/edf3f97ae2af024708ebb4ac614227327033ca47
Christian Brabandt <cb@256bit.org>
parents:
8247
diff
changeset
|
1 /* vi:set ts=8 sw=8 noet: |
7 | 2 * |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * Visual Workshop integration by Gordon Prieur | |
5 * | |
6 * Do ":help uganda" in Vim to read copying and usage conditions. | |
7 * Do ":help credits" in Vim to see a list of people who contributed. | |
8 * See README.txt for an overview of the Vim source code. | |
9 */ | |
10 | |
11 /* | |
12 * Integration with Sun Workshop. | |
13 * | |
14 * This file should not change much, it's also used by other editors that | |
15 * connect to Workshop. Consider changing workshop.c instead. | |
16 */ | |
17 /* | |
18 -> consider using MakeSelectionVisible instead of gotoLine hacks | |
19 to show the line properly | |
20 -> consider using glue instead of our own message wrapping functions | |
21 (but can only use glue if we don't have to distribute source) | |
22 */ | |
23 | |
24 #include "vim.h" | |
25 | |
26 #include <stdio.h> | |
27 #include <stdlib.h> | |
28 | |
29 #ifdef INET_SOCKETS | |
30 #include <netdb.h> | |
31 #include <netinet/in.h> | |
32 #else | |
33 #include <sys/un.h> | |
34 #endif | |
35 | |
36 #include <sys/types.h> | |
37 #include <sys/socket.h> | |
38 #include <sys/param.h> | |
39 #ifdef HAVE_LIBGEN_H | |
40 # include <libgen.h> | |
41 #endif | |
42 #include <unistd.h> | |
43 #include <string.h> | |
44 | |
45 #include <X11/Intrinsic.h> | |
46 #include <Xm/Xm.h> | |
47 #include <Xm/AtomMgr.h> | |
48 #include <Xm/PushB.h> | |
49 | |
50 #ifdef HAVE_X11_XPM_H | |
51 # include <X11/xpm.h> | |
52 #else | |
53 # ifdef HAVE_XM_XPMP_H | |
54 # include <Xm/XpmP.h> | |
55 # endif | |
56 #endif | |
57 | |
58 #ifdef HAVE_UTIL_DEBUG_H | |
59 # include <util/debug.h> | |
60 #endif | |
61 #ifdef HAVE_UTIL_MSGI18N_H | |
62 # include <util/msgi18n.h> | |
63 #endif | |
64 | |
65 #include "integration.h" /* <EditPlugin/integration.h> */ | |
66 #ifdef HAVE_FRAME_H | |
67 # include <frame.h> | |
68 #endif | |
69 | |
70 #ifndef MAX | |
71 # define MAX(a, b) (a) > (b) ? (a) : (b) | |
72 #endif | |
73 | |
74 #ifndef NOCATGETS | |
75 # define NOCATGETS(x) x | |
76 #endif | |
77 | |
78 /* Functions private to this file */ | |
79 static void workshop_disconnect(void); | |
80 static void workshop_sensitivity(int num, char *table); | |
81 static void adjust_sign_name(char *filename); | |
82 static void process_menuItem(char *); | |
83 static void process_toolbarButton(char *); | |
84 static void workshop_set_option_first(char *name, char *value); | |
85 | |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
86 static size_t dummy; /* to ignore return value of write() */ |
7 | 87 |
88 #define CMDBUFSIZ 2048 | |
89 | |
90 #ifdef DEBUG | |
91 static FILE *dfd; | |
92 static void pldebug(char *, ...); | |
93 static void unrecognised_message(char *); | |
94 | |
95 #define HANDLE_ERRORS(cmd) else unrecognised_message(cmd); | |
96 #else | |
97 #define HANDLE_ERRORS(cmd) | |
98 #endif | |
99 | |
100 /* | |
101 * Version number of the protocol between an editor and eserve. | |
102 * This number should be incremented when the protocol | |
103 * is changed. | |
104 */ | |
105 #define PROTOCOL_VERSION "4.0.0" | |
106 | |
107 static int sd = -1; | |
108 static XtInputId inputHandler; /* Cookie for input */ | |
109 | |
110 Boolean save_files = True; /* When true, save all files before build actions */ | |
111 | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
112 static void |
7 | 113 workshop_connection_closed(void) |
114 { | |
115 /* | |
116 * socket closed on other end | |
117 */ | |
118 XtRemoveInput(inputHandler); | |
119 inputHandler = 0; | |
120 sd = -1; | |
121 } | |
122 | |
123 static char * | |
124 getCommand(void) | |
125 { | |
126 int len; /* length of this command */ | |
127 char lenbuf[7]; /* get the length string here */ | |
128 char *newcb; /* used to realloc cmdbuf */ | |
129 static char *cmdbuf;/* get the command string here */ | |
130 static int cbsize;/* size of cmdbuf */ | |
131 | |
132 if ((len = read(sd, &lenbuf, 6)) == 6) { | |
133 lenbuf[6] = 0; /* Terminate buffer such that atoi() works right */ | |
134 len = atoi(lenbuf); | |
135 if (cbsize < (len + 1)) { | |
136 newcb = (char *) realloc(cmdbuf, | |
137 MAX((len + 256), CMDBUFSIZ)); | |
138 if (newcb != NULL) { | |
139 cmdbuf = newcb; | |
140 cbsize = MAX((len + 256), CMDBUFSIZ); | |
141 } | |
142 } | |
143 if (cbsize >= len && (len = read(sd, cmdbuf, len)) > 0) { | |
144 cmdbuf[len] = 0; | |
145 return cmdbuf; | |
146 } else { | |
147 return NULL; | |
148 } | |
149 } else { | |
150 if (len == 0) { /* EOF */ | |
151 workshop_connection_closed(); | |
152 } | |
153 return NULL; | |
154 } | |
155 | |
156 } | |
157 | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
158 static void |
2031
07de57cbcb25
updated for version 7.2.327
Bram Moolenaar <bram@zimbu.org>
parents:
1619
diff
changeset
|
159 messageFromEserve(XtPointer clientData UNUSED, |
07de57cbcb25
updated for version 7.2.327
Bram Moolenaar <bram@zimbu.org>
parents:
1619
diff
changeset
|
160 int *dum1 UNUSED, |
07de57cbcb25
updated for version 7.2.327
Bram Moolenaar <bram@zimbu.org>
parents:
1619
diff
changeset
|
161 XtInputId *dum2 UNUSED) |
7 | 162 { |
163 char *cmd; /* the 1st word of the command */ | |
164 | |
165 cmd = getCommand(); | |
166 if (cmd == NULL) { | |
167 /* We're being shut down by eserve and the "quit" message | |
168 * didn't arrive before the socket connection got closed */ | |
169 return; | |
170 } | |
171 #ifdef DEBUG | |
172 pldebug("%s\n", cmd); | |
173 #endif | |
174 switch (*cmd) { | |
175 case 'a': | |
176 if (cmd[1] == 'c' && | |
177 strncmp(cmd, NOCATGETS("ack "), 4) == 0) { | |
178 int ackNum; | |
179 char buf[20]; | |
180 | |
181 ackNum = atoi(&cmd[4]); | |
272 | 182 vim_snprintf(buf, sizeof(buf), |
183 NOCATGETS("ack %d\n"), ackNum); | |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
184 dummy = write(sd, buf, strlen(buf)); |
7 | 185 } else if (strncmp(cmd, |
186 NOCATGETS("addMarkType "), 12) == 0) { | |
187 int idx; | |
188 char *color; | |
189 char *sign; | |
190 | |
191 idx = atoi(strtok(&cmd[12], " ")); | |
192 color = strtok(NULL, NOCATGETS("\001")); | |
193 sign = strtok(NULL, NOCATGETS("\001")); | |
194 /* Skip space that separates names */ | |
195 if (color) { | |
196 color++; | |
197 } | |
198 if (sign) { | |
199 sign++; | |
200 } | |
2031
07de57cbcb25
updated for version 7.2.327
Bram Moolenaar <bram@zimbu.org>
parents:
1619
diff
changeset
|
201 /* Change sign name to accommodate a different size? */ |
7 | 202 adjust_sign_name(sign); |
203 workshop_add_mark_type(idx, color, sign); | |
204 } | |
205 HANDLE_ERRORS(cmd); | |
206 break; | |
207 | |
208 case 'b': | |
209 if (strncmp(cmd, | |
210 NOCATGETS("balloon "), 8) == 0) { | |
211 char *tip; | |
212 | |
213 tip = strtok(&cmd[8], NOCATGETS("\001")); | |
214 workshop_show_balloon_tip(tip); | |
215 } | |
216 HANDLE_ERRORS(cmd); | |
217 break; | |
218 | |
219 case 'c': | |
220 if (strncmp(cmd, | |
221 NOCATGETS("changeMarkType "), 15) == 0) { | |
222 char *file; | |
223 int markId; | |
224 int type; | |
225 | |
226 file = strtok(&cmd[15], " "); | |
227 markId = atoi(strtok(NULL, " ")); | |
228 type = atoi(strtok(NULL, " ")); | |
229 workshop_change_mark_type(file, markId, type); | |
230 } | |
231 HANDLE_ERRORS(cmd); | |
232 break; | |
233 | |
234 case 'd': | |
235 if (strncmp(cmd, NOCATGETS("deleteMark "), 11) == 0) { | |
236 char *file; | |
237 int markId; | |
238 | |
239 file = strtok(&cmd[11], " "); | |
240 markId = atoi(strtok(NULL, " ")); | |
241 workshop_delete_mark(file, markId); | |
242 } | |
243 HANDLE_ERRORS(cmd); | |
244 break; | |
245 | |
246 case 'f': | |
247 if (cmd[1] == 'o' && | |
248 strncmp(cmd, NOCATGETS("footerMsg "), 10) == 0) { | |
249 int severity; | |
250 char *message; | |
251 | |
252 severity = | |
253 atoi(strtok(&cmd[10], " ")); | |
254 message = strtok(NULL, NOCATGETS("\001")); | |
255 | |
256 workshop_footer_message(message, severity); | |
257 } else if (strncmp(cmd, | |
258 NOCATGETS("frontFile "), 10) == 0) { | |
259 char *file; | |
260 | |
261 file = strtok(&cmd[10], " "); | |
262 workshop_front_file(file); | |
263 } | |
264 HANDLE_ERRORS(cmd); | |
265 break; | |
266 | |
267 case 'g': | |
268 if (cmd[1] == 'e' && | |
269 strncmp(cmd, NOCATGETS("getMarkLine "), 12) == 0) { | |
270 char *file; | |
271 int markid; | |
272 int line; | |
273 char buf[100]; | |
274 | |
275 file = strtok(&cmd[12], " "); | |
276 markid = atoi(strtok(NULL, " ")); | |
277 line = workshop_get_mark_lineno(file, markid); | |
272 | 278 vim_snprintf(buf, sizeof(buf), |
279 NOCATGETS("markLine %s %d %d\n"), | |
7 | 280 file, markid, line); |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
281 dummy = write(sd, buf, strlen(buf)); |
7 | 282 } else if (cmd[1] == 'o' && cmd[4] == 'L' && |
283 strncmp(cmd, NOCATGETS("gotoLine "), 9) == 0) { | |
284 char *file; | |
285 int lineno; | |
286 | |
287 file = strtok(&cmd[9], " "); | |
288 lineno = atoi(strtok(NULL, " ")); | |
289 workshop_goto_line(file, lineno); | |
290 } else if (strncmp(cmd, | |
291 NOCATGETS("gotoMark "), 9) == 0) { | |
292 char *file; | |
293 int markId; | |
294 char *message; | |
295 | |
296 file = strtok(&cmd[9], " "); | |
297 markId = atoi(strtok(NULL, " ")); | |
298 message = strtok(NULL, NOCATGETS("\001")); | |
299 workshop_goto_mark(file, markId, message); | |
300 #ifdef NOHANDS_SUPPORT_FUNCTIONS | |
301 } else if (strcmp(cmd, NOCATGETS("getCurrentFile")) == 0) { | |
302 char *f = workshop_test_getcurrentfile(); | |
303 char buffer[2*MAXPATHLEN]; | |
272 | 304 vim_snprintf(buffer, sizeof(buffer), |
305 NOCATGETS("currentFile %d %s"), | |
7 | 306 f ? strlen(f) : 0, f ? f : ""); |
307 workshop_send_message(buffer); | |
308 } else if (strcmp(cmd, NOCATGETS("getCursorRow")) == 0) { | |
309 int row = workshop_test_getcursorrow(); | |
310 char buffer[2*MAXPATHLEN]; | |
272 | 311 vim_snprintf(buffer, sizeof(buffer), |
312 NOCATGETS("cursorRow %d"), row); | |
7 | 313 workshop_send_message(buffer); |
314 } else if (strcmp(cmd, NOCATGETS("getCursorCol")) == 0) { | |
315 int col = workshop_test_getcursorcol(); | |
316 char buffer[2*MAXPATHLEN]; | |
272 | 317 vim_snprintf(buffer, sizeof(buffer), |
318 NOCATGETS("cursorCol %d"), col); | |
7 | 319 workshop_send_message(buffer); |
320 } else if (strcmp(cmd, NOCATGETS("getCursorRowText")) == 0) { | |
321 char *t = workshop_test_getcursorrowtext(); | |
322 char buffer[2*MAXPATHLEN]; | |
272 | 323 vim_snprintf(buffer, sizeof(buffer), |
324 NOCATGETS("cursorRowText %d %s"), | |
7 | 325 t ? strlen(t) : 0, t ? t : ""); |
326 workshop_send_message(buffer); | |
327 } else if (strcmp(cmd, NOCATGETS("getSelectedText")) == 0) { | |
328 char *t = workshop_test_getselectedtext(); | |
329 char buffer[2*MAXPATHLEN]; | |
272 | 330 vim_snprintf(buffer, sizeof(buffer), |
331 NOCATGETS("selectedText %d %s"), | |
7 | 332 t ? strlen(t) : 0, t ? t : ""); |
333 workshop_send_message(buffer); | |
334 #endif | |
335 } | |
336 HANDLE_ERRORS(cmd); | |
337 break; | |
338 | |
339 case 'l': | |
340 if (strncmp(cmd, NOCATGETS("loadFile "), 9) == 0) { | |
341 char *file; | |
342 int line; | |
343 char *frameid; | |
344 | |
345 file = strtok(&cmd[9], " "); | |
346 line = atoi(strtok(NULL, " ")); | |
347 frameid = strtok(NULL, " "); | |
348 workshop_load_file(file, line, frameid); | |
349 } | |
350 HANDLE_ERRORS(cmd); | |
351 break; | |
352 | |
353 case 'm': /* Menu, minimize, maximize */ | |
354 if (cmd[1] == 'e' && cmd[4] == 'B' && | |
355 strncmp(cmd, NOCATGETS("menuBegin "), 10) == 0) { | |
356 workshop_menu_begin(&cmd[10]); | |
357 } else if (cmd[1] == 'e' && cmd[4] == 'I' && | |
358 strncmp(cmd, NOCATGETS("menuItem "), 9) == 0) { | |
359 process_menuItem(cmd); | |
360 } else if (cmd[1] == 'e' && cmd[4] == 'E' && | |
361 strcmp(cmd, NOCATGETS("menuEnd")) == 0) { | |
362 workshop_menu_end(); | |
363 } else if (cmd[1] == 'a' && | |
364 strcmp(cmd, NOCATGETS("maximize")) == 0) { | |
365 workshop_maximize(); | |
366 } else if (strcmp(cmd, NOCATGETS("minimize")) == 0) { | |
367 workshop_minimize(); | |
368 } | |
369 HANDLE_ERRORS(cmd); | |
370 break; | |
371 | |
372 case 'o': | |
373 if (cmd[1] == 'p' && | |
374 strcmp(cmd, NOCATGETS("option"))) { | |
375 char *name; | |
376 char *value; | |
377 | |
378 name = strtok(&cmd[7], " "); | |
379 value = strtok(NULL, " "); | |
380 workshop_set_option_first(name, value); | |
381 } | |
382 HANDLE_ERRORS(cmd); | |
383 break; | |
384 | |
385 case 'p': | |
386 if (strcmp(cmd, NOCATGETS("ping")) == 0) { | |
387 #if 0 | |
388 int pingNum; | |
389 | |
390 pingNum = atoi(&cmd[5]); | |
391 workshop_send_ack(ackNum); | |
2520 | 392 /* WHAT DO I DO HERE? */ |
7 | 393 #endif |
394 } | |
395 HANDLE_ERRORS(cmd); | |
396 break; | |
397 | |
398 case 'q': | |
399 if (strncmp(cmd, NOCATGETS("quit"), 4) == 0) { | |
400 | |
401 /* Close the connection. It's important to do | |
402 * that now, since workshop_quit might be | |
403 * looking at open files. For example, if you | |
404 * have modified one of the files without | |
405 * saving, NEdit will ask you what you want to | |
406 * do, and spin loop by calling | |
407 * XtAppProcessEvent while waiting for your | |
408 * reply. In this case, if we still have an | |
409 * input handler and the socket has been | |
410 * closed on the other side when eserve | |
411 * expired, we will hang in IoWait. | |
412 */ | |
413 workshop_disconnect(); | |
414 | |
415 workshop_quit(); | |
416 } | |
417 HANDLE_ERRORS(cmd); | |
418 break; | |
419 | |
420 case 'r': | |
421 if (cmd[1] == 'e' && | |
422 strncmp(cmd, NOCATGETS("reloadFile "), 11) == 0) { | |
423 char *file; | |
424 int line; | |
425 | |
426 file = strtok(&cmd[11], " "); | |
427 line = atoi(strtok(NULL, " ")); | |
428 workshop_reload_file(file, line); | |
429 } | |
430 HANDLE_ERRORS(cmd); | |
431 break; | |
432 | |
433 case 's': | |
434 if (cmd[1] == 'e' && cmd[2] == 't' && | |
435 strncmp(cmd, NOCATGETS("setMark "), 8) == 0) { | |
436 char *file; | |
437 int line; | |
438 int markId; | |
439 int type; | |
440 | |
441 file = strtok(&cmd[8], " "); | |
442 line = atoi(strtok(NULL, " ")); | |
443 markId = atoi(strtok(NULL, " ")); | |
444 type = atoi(strtok(NULL, " ")); | |
445 workshop_set_mark(file, line, markId, type); | |
446 } else if (cmd[1] == 'h' && | |
447 strncmp(cmd, NOCATGETS("showFile "), 9) == 0) { | |
448 workshop_show_file(&cmd[9]); | |
449 } else if (cmd[1] == 'u' && | |
450 strncmp(cmd, NOCATGETS("subMenu "), 8) == 0) { | |
451 char *label; | |
452 | |
453 label = strtok(&cmd[8], NOCATGETS("\001")); | |
454 workshop_submenu_begin(label); | |
455 } else if (cmd[1] == 'u' && | |
456 strcmp(cmd, NOCATGETS("subMenuEnd")) == 0) { | |
457 workshop_submenu_end(); | |
458 } else if (cmd[1] == 'e' && cmd[2] == 'n' && | |
459 strncmp(cmd, NOCATGETS("sensitivity "), 12) == 0) { | |
460 int num; | |
461 char *bracket; | |
462 char *table; | |
463 | |
464 num = atoi(strtok(&cmd[12], " ")); | |
465 bracket = strtok(NULL, " "); | |
466 if (*bracket != '[') { | |
467 fprintf(stderr, NOCATGETS("Parsing " | |
468 "error for sensitivity\n")); | |
469 } else { | |
470 table = strtok(NULL, NOCATGETS("]")); | |
471 workshop_sensitivity(num, table); | |
472 } | |
473 } else if (cmd[1] == 'e' && cmd[2] == 'n' && cmd[3] == 'd' && | |
474 strncmp(cmd, NOCATGETS("sendVerb "), 9) == 0) { | |
475 /* Send the given verb back (used for the | |
476 * debug.lineno callback (such that other tools | |
477 * can obtain the position coordinates or the | |
478 * selection) */ | |
479 char *verb; | |
480 | |
481 verb = strtok(&cmd[9], " "); | |
482 workshop_perform_verb(verb, NULL); | |
483 } else if (cmd[1] == 'a' && | |
484 strncmp(cmd, NOCATGETS("saveFile "), 9) == 0) { | |
485 workshop_save_file(&cmd[9]); | |
486 #ifdef NOHANDS_SUPPORT_FUNCTIONS | |
487 } else if (strncmp(cmd, NOCATGETS("saveSensitivity "), 16) == 0) { | |
488 char *file; | |
489 | |
490 file = strtok(&cmd[16], " "); | |
491 workshop_save_sensitivity(file); | |
492 #endif | |
493 } | |
494 HANDLE_ERRORS(cmd); | |
495 break; | |
496 | |
497 case 't': /* Toolbar */ | |
498 if (cmd[8] == 'e' && | |
499 strncmp(cmd, NOCATGETS("toolbarBegin"), 12) == 0) { | |
500 workshop_toolbar_begin(); | |
501 } else if (cmd[8] == 'u' && | |
502 strncmp(cmd, NOCATGETS("toolbarButton"), 13) == 0) { | |
503 process_toolbarButton(cmd); | |
504 } else if (cmd[7] == 'E' && | |
505 strcmp(cmd, NOCATGETS("toolbarEnd")) == 0) { | |
506 workshop_toolbar_end(); | |
507 } | |
508 HANDLE_ERRORS(cmd); | |
509 break; | |
510 | |
511 #ifdef DEBUG | |
512 default: | |
513 unrecognised_message(cmd); | |
514 break; | |
515 #endif | |
516 } | |
517 } | |
518 | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
519 static void |
7 | 520 process_menuItem( |
521 char *cmd) | |
522 { | |
523 char *label = strtok(&cmd[9], NOCATGETS("\001")); | |
524 char *verb = strtok(NULL, NOCATGETS("\001")); | |
525 char *acc = strtok(NULL, NOCATGETS("\001")); | |
526 char *accText = strtok(NULL, NOCATGETS("\001")); | |
527 char *name = strtok(NULL, NOCATGETS("\001")); | |
528 char *sense = strtok(NULL, NOCATGETS("\n")); | |
529 char *filepos = strtok(NULL, NOCATGETS("\n")); | |
530 if (*acc == '-') { | |
531 acc = NULL; | |
532 } | |
533 if (*accText == '-') { | |
534 accText = NULL; | |
535 } | |
536 workshop_menu_item(label, verb, acc, accText, name, filepos, sense); | |
537 | |
538 } | |
539 | |
540 | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
541 static void |
7 | 542 process_toolbarButton( |
543 char *cmd) /* button definition */ | |
544 { | |
545 char *label = strtok(&cmd[14], NOCATGETS("\001")); | |
546 char *verb = strtok(NULL, NOCATGETS("\001")); | |
547 char *senseVerb = strtok(NULL, NOCATGETS("\001")); | |
548 char *filepos = strtok(NULL, NOCATGETS("\001")); | |
549 char *help = strtok(NULL, NOCATGETS("\001")); | |
550 char *sense = strtok(NULL, NOCATGETS("\001")); | |
551 char *file = strtok(NULL, NOCATGETS("\001")); | |
552 char *left = strtok(NULL, NOCATGETS("\n")); | |
553 | |
554 if (!strcmp(label, NOCATGETS("-"))) { | |
555 label = NULL; | |
556 } | |
557 if (!strcmp(help, NOCATGETS("-"))) { | |
558 help = NULL; | |
559 } | |
560 if (!strcmp(file, NOCATGETS("-"))) { | |
561 file = NULL; | |
562 } | |
563 if (!strcmp(senseVerb, NOCATGETS("-"))) { | |
564 senseVerb = NULL; | |
565 } | |
566 workshop_toolbar_button(label, verb, senseVerb, filepos, help, | |
567 sense, file, left); | |
568 } | |
569 | |
570 | |
571 #ifdef DEBUG | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
572 static void |
7 | 573 unrecognised_message( |
574 char *cmd) | |
575 { | |
576 pldebug("Unrecognised eserve message:\n\t%s\n", cmd); | |
577 /* abort(); */ | |
578 } | |
579 #endif | |
580 | |
581 | |
2031
07de57cbcb25
updated for version 7.2.327
Bram Moolenaar <bram@zimbu.org>
parents:
1619
diff
changeset
|
582 /* Change sign name to accommodate a different size: |
7 | 583 * Create the filename based on the height. The filename format |
584 * of multisize icons are: | |
585 * x.xpm : largest icon | |
586 * x1.xpm : smaller icon | |
587 * x2.xpm : smallest icon */ | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
588 static void |
7 | 589 adjust_sign_name(char *filename) |
590 { | |
591 char *s; | |
592 static int fontSize = -1; | |
593 | |
594 if (fontSize == -1) | |
595 fontSize = workshop_get_font_height(); | |
596 if (fontSize == 0) | |
597 return; | |
598 if (filename[0] == '-') | |
599 return; | |
600 | |
601 /* This is ugly: later we should instead pass the fontheight over | |
602 * to eserve on startup and let eserve just send the right filenames | |
603 * to us in the first place | |
604 | |
605 * I know that the filename will end with 1.xpm (see | |
606 * GuiEditor.cc`LispPrintSign if you wonder why) */ | |
607 s = filename+strlen(filename)-5; | |
608 if (fontSize <= 11) | |
609 strcpy(s, "2.xpm"); | |
610 else if (fontSize <= 15) | |
611 strcpy(s, "1.xpm"); | |
612 else | |
613 strcpy(s, ".xpm"); | |
614 } | |
615 | |
2031
07de57cbcb25
updated for version 7.2.327
Bram Moolenaar <bram@zimbu.org>
parents:
1619
diff
changeset
|
616 #if 0 |
7 | 617 /* Were we invoked by WorkShop? This function can be used early during startup |
618 if you want to do things differently if the editor is started standalone | |
619 or in WorkShop mode. For example, in standalone mode you may not want to | |
620 add a footer/message area or a sign gutter. */ | |
7823
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
2668
diff
changeset
|
621 int |
bcef391c101c
commit https://github.com/vim/vim/commit/68c2f638e65d914dc6e84eb7ce2624f08af525c0
Christian Brabandt <cb@256bit.org>
parents:
2668
diff
changeset
|
622 workshop_invoked(void) |
7 | 623 { |
624 static int result = -1; | |
625 if (result == -1) { | |
626 result = (getenv(NOCATGETS("SPRO_EDITOR_SOCKET")) != NULL); | |
627 } | |
628 return result; | |
629 } | |
2031
07de57cbcb25
updated for version 7.2.327
Bram Moolenaar <bram@zimbu.org>
parents:
1619
diff
changeset
|
630 #endif |
7 | 631 |
632 /* Connect back to eserve */ | |
633 void workshop_connect(XtAppContext context) | |
634 { | |
635 #ifdef INET_SOCKETS | |
636 struct sockaddr_in server; | |
637 struct hostent * host; | |
638 int port; | |
639 #else | |
640 struct sockaddr_un server; | |
641 #endif | |
642 char buf[32]; | |
643 char * address; | |
644 #ifdef DEBUG | |
645 char *file; | |
646 #endif | |
647 | |
648 address = getenv(NOCATGETS("SPRO_EDITOR_SOCKET")); | |
649 if (address == NULL) { | |
650 return; | |
651 } | |
652 | |
653 #ifdef INET_SOCKETS | |
654 port = atoi(address); | |
655 | |
656 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { | |
657 PERROR(NOCATGETS("workshop_connect")); | |
658 return; | |
659 } | |
660 | |
661 /* Get the server internet address and put into addr structure */ | |
662 /* fill in the socket address structure and connect to server */ | |
2215
cccb71c2c5c1
Fix uninit memory read in undo code. Fix uint32_t in proto file.
Bram Moolenaar <bram@vim.org>
parents:
2031
diff
changeset
|
663 vim_memset((char *)&server, '\0', sizeof(server)); |
7 | 664 server.sin_family = AF_INET; |
665 server.sin_port = port; | |
666 if ((host = gethostbyname(NOCATGETS("localhost"))) == NULL) { | |
667 PERROR(NOCATGETS("gethostbyname")); | |
668 sd = -1; | |
669 return; | |
670 } | |
671 memcpy((char *)&server.sin_addr, host->h_addr, host->h_length); | |
672 #else | |
673 if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { | |
674 PERROR(NOCATGETS("workshop_connect")); | |
675 return; | |
676 } | |
677 | |
678 server.sun_family = AF_UNIX; | |
679 strcpy(server.sun_path, address); | |
680 #endif | |
681 /* Connect to server */ | |
682 if (connect(sd, (struct sockaddr *)&server, sizeof(server))) { | |
683 if (errno == ECONNREFUSED) { | |
684 close(sd); | |
685 #ifdef INET_SOCKETS | |
686 if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { | |
687 PERROR(NOCATGETS("workshop_connect")); | |
688 return; | |
689 } | |
690 #else | |
691 if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { | |
692 PERROR(NOCATGETS("workshop_connect")); | |
693 return; | |
694 } | |
695 #endif | |
696 if (connect(sd, (struct sockaddr *)&server, | |
697 sizeof(server))) { | |
698 PERROR(NOCATGETS("workshop_connect")); | |
699 return; | |
700 } | |
701 | |
702 } else { | |
703 PERROR(NOCATGETS("workshop_connect")); | |
704 return; | |
705 } | |
706 } | |
707 | |
708 /* tell notifier we are interested in being called | |
709 * when there is input on the editor connection socket | |
710 */ | |
711 inputHandler = XtAppAddInput(context, sd, (XtPointer) XtInputReadMask, | |
712 messageFromEserve, NULL); | |
713 #ifdef DEBUG | |
714 if ((file = getenv(NOCATGETS("SPRO_PLUGIN_DEBUG"))) != NULL) { | |
715 char buf[BUFSIZ]; | |
716 | |
717 unlink(file); | |
272 | 718 vim_snprintf(buf, sizeof(buf), "date > %s", file); |
7 | 719 system(buf); |
720 dfd = fopen(file, "a"); | |
721 } else { | |
722 dfd = NULL; | |
723 } | |
724 #endif | |
725 | |
272 | 726 vim_snprintf(buf, sizeof(buf), NOCATGETS("connected %s %s %s\n"), |
7 | 727 workshop_get_editor_name(), |
728 PROTOCOL_VERSION, | |
729 workshop_get_editor_version()); | |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
730 dummy = write(sd, buf, strlen(buf)); |
7 | 731 |
272 | 732 vim_snprintf(buf, sizeof(buf), NOCATGETS("ack 1\n")); |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
733 dummy = write(sd, buf, strlen(buf)); |
7 | 734 } |
735 | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
736 static void |
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
737 workshop_disconnect(void) |
7 | 738 { |
739 /* Probably need to send some message here */ | |
740 | |
741 /* | |
742 * socket closed on other end | |
743 */ | |
744 XtRemoveInput(inputHandler); | |
745 close(sd); | |
746 inputHandler = 0; | |
747 sd = -1; | |
748 | |
749 } | |
750 | |
751 /* | |
752 * Utility functions | |
753 */ | |
754 | |
755 | |
756 /* Minimize and maximize shells. From libutil's shell.cc. */ | |
757 | |
758 /* utility functions from libutil's shell.cc */ | |
759 static Boolean | |
760 isWindowMapped(Display *display, Window win) | |
761 { | |
762 XWindowAttributes winAttrs; | |
763 XGetWindowAttributes(display, | |
764 win, | |
765 &winAttrs); | |
766 if (winAttrs.map_state == IsViewable) { | |
767 return(True); | |
768 } else { | |
769 return(False); | |
770 } | |
771 } | |
772 | |
773 static Boolean | |
774 isMapped(Widget widget) | |
775 { | |
776 if (widget == NULL) { | |
777 return(False); | |
778 } | |
779 | |
780 if (XtIsRealized(widget) == False) { | |
781 return(False); | |
782 } | |
783 | |
784 return(isWindowMapped(XtDisplay(widget), XtWindow(widget))); | |
785 } | |
786 | |
787 static Boolean | |
788 widgetIsIconified( | |
789 Widget w) | |
790 { | |
791 Atom wm_state; | |
792 Atom act_type; /* actual Atom type returned */ | |
793 int act_fmt; /* actual format returned */ | |
794 u_long nitems_ret; /* number of items returned */ | |
795 u_long bytes_after; /* number of bytes remaining */ | |
796 u_long *property; /* actual property returned */ | |
797 | |
798 /* | |
799 * If a window is iconified its WM_STATE is set to IconicState. See | |
800 * ICCCM Version 2.0, section 4.1.3.1 for more details. | |
801 */ | |
802 | |
803 wm_state = XmInternAtom(XtDisplay(w), NOCATGETS("WM_STATE"), False); | |
804 if (XtWindow(w) != 0) { /* only check if window exists! */ | |
805 XGetWindowProperty(XtDisplay(w), XtWindow(w), wm_state, 0L, 2L, | |
806 False, AnyPropertyType, &act_type, &act_fmt, &nitems_ret, | |
8247
6ee794dc950e
commit https://github.com/vim/vim/commit/669cac0a805333e69b9e1176425083914eada659
Christian Brabandt <cb@256bit.org>
parents:
7823
diff
changeset
|
807 &bytes_after, (char_u **) &property); |
7 | 808 if (nitems_ret == 2 && property[0] == IconicState) { |
809 return True; | |
810 } | |
811 } | |
812 | |
813 return False; | |
814 | |
815 } /* end widgetIsIconified */ | |
816 | |
817 void | |
818 workshop_minimize_shell(Widget shell) | |
819 { | |
820 if (shell != NULL && | |
821 XtIsObject(shell) && | |
822 XtIsRealized(shell) == True) { | |
823 if (isMapped(shell) == True) { | |
824 XIconifyWindow(XtDisplay(shell), XtWindow(shell), | |
825 XScreenNumberOfScreen(XtScreen(shell))); | |
826 } | |
827 XtVaSetValues(shell, | |
828 XmNiconic, True, | |
829 NULL); | |
830 } | |
831 } | |
832 | |
833 void workshop_maximize_shell(Widget shell) | |
834 { | |
835 if (shell != NULL && | |
836 XtIsRealized(shell) == True && | |
837 widgetIsIconified(shell) == True && | |
838 isMapped(shell) == False) { | |
839 XtMapWidget(shell); | |
840 /* This used to be | |
841 XtPopdown(shell); | |
842 XtPopup(shell, XtGrabNone); | |
843 However, I found that that would drop any transient | |
844 windows that had been iconified with the window. | |
845 According to the ICCCM, XtMapWidget should be used | |
846 to bring a window from Iconic to Normal state. | |
847 However, Rich Mauri did a lot of work on this during | |
848 Bart, and found that XtPopDown,XtPopup was required | |
849 to fix several bugs involving multiple CDE workspaces. | |
850 I've tested it now and things seem to work fine but | |
851 I'm leaving this note for history in case this needs | |
852 to be revisited. | |
853 */ | |
854 } | |
855 } | |
856 | |
857 | |
858 Boolean workshop_get_width_height(int *width, int *height) | |
859 { | |
860 static int wid = 0; | |
861 static int hgt = 0; | |
862 static Boolean firstTime = True; | |
863 static Boolean success = False; | |
864 | |
865 if (firstTime) { | |
866 char *settings; | |
867 | |
868 settings = getenv(NOCATGETS("SPRO_GUI_WIDTH_HEIGHT")); | |
869 if (settings != NULL) { | |
870 wid = atoi(settings); | |
871 settings = strrchr(settings, ':'); | |
872 if (settings++ != NULL) { | |
873 hgt = atoi(settings); | |
874 } | |
875 if (wid > 0 && hgt > 0) { | |
876 success = True; | |
877 } | |
878 firstTime = False; | |
879 } | |
880 } | |
881 | |
882 if (success) { | |
883 *width = wid; | |
884 *height = hgt; | |
885 } | |
886 return success; | |
887 } | |
888 | |
889 /* | |
890 * Toolbar code | |
891 */ | |
892 | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
893 static void |
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
894 workshop_sensitivity(int num, char *table) |
7 | 895 { |
896 /* build up a verb table */ | |
897 VerbSense *vs; | |
898 int i; | |
899 char *s; | |
900 if ((num < 1) || (num > 500)) { | |
901 return; | |
902 } | |
903 | |
904 vs = (VerbSense *)malloc((num+1)*sizeof(VerbSense)); | |
905 | |
906 /* Point to the individual names (destroys the table string, but | |
907 * that's okay -- this is more efficient than duplicating strings) */ | |
908 s = table; | |
909 for (i = 0; i < num; i++) { | |
910 while (*s == ' ') { | |
911 s++; | |
912 } | |
913 vs[i].verb = s; | |
914 while (*s && (*s != ' ') && (*s != '\001')) { | |
915 s++; | |
916 } | |
917 if (*s == 0) { | |
918 vs[i].verb = NULL; | |
919 break; | |
920 } | |
921 if (*s == '\001') { | |
922 *s = 0; | |
923 s++; | |
924 } | |
925 *s = 0; | |
926 s++; | |
927 while (*s == ' ') { | |
928 s++; | |
929 } | |
930 if (*s == '1') { | |
931 vs[i].sense = 1; | |
932 } else { | |
933 vs[i].sense = 0; | |
934 } | |
935 s++; | |
936 } | |
937 vs[i].verb = NULL; | |
938 | |
939 workshop_frame_sensitivities(vs); | |
940 | |
941 free(vs); | |
942 } | |
943 | |
944 /* | |
945 * Options code | |
946 */ | |
947 /* Set an editor option. | |
948 * IGNORE an option if you do not recognize it. | |
949 */ | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
950 static void |
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
951 workshop_set_option_first(char *name, char *value) |
7 | 952 { |
953 /* Currently value can only be on/off. This may change later (for | |
954 * example to set an option like "balloon evaluate delay", but | |
955 * for now just convert it into a boolean */ | |
956 Boolean on = !strcmp(value, "on"); | |
957 | |
958 if (!strcmp(name, "workshopkeys")) { | |
959 workshop_hotkeys(on); | |
960 } else if (!strcmp(name, "savefiles")) { | |
961 save_files = on; | |
962 } else if (!strcmp(name, "balloon")) { | |
963 workshop_balloon_mode(on); | |
964 } else if (!strcmp(name, "balloondelay")) { | |
965 int delay = atoi(value); | |
966 /* Should I validate the number here?? */ | |
967 workshop_balloon_delay(delay); | |
968 } else { | |
969 /* Let editor interpret it */ | |
970 workshop_set_option(name, value); | |
971 } | |
972 } | |
973 | |
974 | |
975 void workshop_file_closed_lineno(char *filename, int lineno) | |
976 { | |
977 char buffer[2*MAXPATHLEN]; | |
272 | 978 vim_snprintf(buffer, sizeof(buffer), |
979 NOCATGETS("deletedFile %s %d\n"), filename, lineno); | |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
980 dummy = write(sd, buffer, strlen(buffer)); |
7 | 981 } |
982 | |
983 void workshop_file_opened(char *filename, int readOnly) | |
984 { | |
985 char buffer[2*MAXPATHLEN]; | |
272 | 986 vim_snprintf(buffer, sizeof(buffer), |
987 NOCATGETS("loadedFile %s %d\n"), filename, readOnly); | |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
988 dummy = write(sd, buffer, strlen(buffer)); |
7 | 989 } |
990 | |
991 | |
992 void workshop_file_saved(char *filename) | |
993 { | |
994 char buffer[2*MAXPATHLEN]; | |
272 | 995 vim_snprintf(buffer, sizeof(buffer), |
996 NOCATGETS("savedFile %s\n"), filename); | |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
997 dummy = write(sd, buffer, strlen(buffer)); |
7 | 998 |
999 /* Let editor report any moved marks that the eserve client | |
1000 * should deal with (for example, moving location-based breakpoints) */ | |
1001 workshop_moved_marks(filename); | |
1002 } | |
1003 | |
1004 void workshop_frame_moved(int new_x, int new_y, int new_w, int new_h) | |
1005 { | |
1006 char buffer[200]; | |
1007 | |
1008 if (sd >= 0) | |
1009 { | |
272 | 1010 vim_snprintf(buffer, sizeof(buffer), |
1011 NOCATGETS("frameAt %d %d %d %d\n"), | |
7 | 1012 new_x, new_y, new_w, new_h); |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
1013 dummy = write(sd, buffer, strlen(buffer)); |
7 | 1014 } |
1015 } | |
1016 | |
1017 /* A button in the toolbar has been pushed. | |
1018 * Clientdata is a pointer used by the editor code to figure out the | |
1019 * positions for this toolbar (probably by storing a window pointer, | |
1020 * and then fetching the current buffer for that window and looking up | |
1021 * cursor and selection positions etc.) */ | |
1022 void workshop_perform_verb(char *verb, void *clientData) | |
1023 { | |
1024 char *filename; | |
1025 int curLine; | |
1026 int curCol; | |
1027 int selStartLine; | |
1028 int selStartCol; | |
1029 int selEndLine; | |
1030 int selEndCol; | |
1031 int selLength; | |
1032 char *selection; | |
1033 | |
1034 char buf[2*MAXPATHLEN]; | |
1035 /* Later: needsFilePos indicates whether or not we need to fetch all this | |
1036 * info for this verb... for now, however, it looks as if | |
1037 * eserve parsing routines depend on it always being present */ | |
1038 | |
1039 if (workshop_get_positions(clientData, | |
1040 &filename, | |
1041 &curLine, | |
1042 &curCol, | |
1043 &selStartLine, | |
1044 &selStartCol, | |
1045 &selEndLine, | |
1046 &selEndCol, | |
1047 &selLength, | |
1048 &selection)) { | |
1049 if (selection == NULL) { | |
1050 selection = NOCATGETS(""); | |
1051 } | |
1052 | |
1053 /* Should I save the files??? This is currently done by checking | |
1054 if the verb is one of a few recognized ones. Later we can pass | |
1055 this list from eserve to the editor (it's currently hardcoded in | |
1056 vi and emacs as well). */ | |
1057 if (save_files) { | |
1058 if (!strcmp(verb, "build.build") || !strcmp(verb, "build.build-file") || | |
1059 !strcmp(verb, "debug.fix") || !strcmp(verb, "debug.fix-all")) { | |
1060 workshop_save_files(); | |
1061 } | |
1062 } | |
1063 | |
272 | 1064 vim_snprintf(buf, sizeof(buf), |
1065 NOCATGETS("toolVerb %s %s %d,%d %d,%d %d,%d %d %s\n"), | |
7 | 1066 verb, |
1067 filename, | |
1068 curLine, curCol, | |
1069 selStartLine, selStartCol, | |
1070 selEndLine, selEndCol, | |
1071 selLength, | |
1072 selection); | |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
1073 dummy = write(sd, buf, strlen(buf)); |
7 | 1074 if (*selection) { |
1075 free(selection); | |
1076 } | |
1077 } | |
1078 } | |
1079 | |
1080 /* Send a message to eserve */ | |
12871
1a450ce6980c
patch 8.0.1312: balloon_show() only works in terminal when compiled with GUI
Christian Brabandt <cb@256bit.org>
parents:
10042
diff
changeset
|
1081 #if defined(NOHANDS_SUPPORT_FUNCTIONS) || defined(FEAT_BEVAL_GUI) |
7 | 1082 void workshop_send_message(char *buf) |
1083 { | |
2250
1bac28a53fae
Add the conceal patch from Vince Negri.
Bram Moolenaar <bram@vim.org>
parents:
2245
diff
changeset
|
1084 dummy = write(sd, buf, strlen(buf)); |
7 | 1085 } |
2031
07de57cbcb25
updated for version 7.2.327
Bram Moolenaar <bram@zimbu.org>
parents:
1619
diff
changeset
|
1086 #endif |
7 | 1087 |
1088 /* Some methods, like currentFile, cursorPos, etc. are missing here. | |
1089 * But it looks like these are used for NoHands testing only so we | |
1090 * won't bother requiring editors to implement these | |
1091 */ | |
1092 | |
1093 | |
1094 #ifdef DEBUG | |
1095 | |
14862
27b9a84395b5
patch 8.1.0443: unnecessary static function prototypes
Christian Brabandt <cb@256bit.org>
parents:
12871
diff
changeset
|
1096 static void |
7 | 1097 pldebug( |
1098 char *fmt, /* a printf style format line */ | |
1099 ...) | |
1100 { | |
1101 va_list ap; | |
1102 | |
1103 if (dfd != NULL) { | |
1104 va_start(ap, fmt); | |
1105 vfprintf(dfd, fmt, ap); | |
1106 va_end(ap); | |
1107 fflush(dfd); | |
1108 } | |
1109 | |
1110 } /* end pldebug */ | |
1111 | |
1112 #endif |