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