3 * VIM - Vi IMproved by Bram Moolenaar
4 * Visual Workshop integration by Gordon Prieur
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.
12 * Integration with Sun Workshop.
14 * This file should not change much, it's also used by other editors that
15 * connect to Workshop. Consider changing workshop.c instead.
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)
31 #include <netinet/in.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/param.h>
46 #include <X11/Intrinsic.h>
48 #include <Xm/AtomMgr.h>
54 # ifdef HAVE_XM_XPMP_H
59 #ifdef HAVE_UTIL_DEBUG_H
60 # include <util/debug.h>
62 #ifdef HAVE_UTIL_MSGI18N_H
63 # include <util/msgi18n.h>
66 #include "integration.h" /* <EditPlugin/integration.h> */
72 # define MAX(a, b) (a) > (b) ? (a) : (b)
76 # define NOCATGETS(x) x
79 /* Functions private to this file */
80 static void workshop_connection_closed(void);
81 static void messageFromEserve(XtPointer clientData
, int *dum1
, XtInputId
*dum2
);
82 static void workshop_disconnect(void);
83 static void workshop_sensitivity(int num
, char *table
);
84 static void adjust_sign_name(char *filename
);
85 static void process_menuItem(char *);
86 static void process_toolbarButton(char *);
87 static void workshop_set_option_first(char *name
, char *value
);
90 #define CMDBUFSIZ 2048
94 static void pldebug(char *, ...);
95 static void unrecognised_message(char *);
97 #define HANDLE_ERRORS(cmd) else unrecognised_message(cmd);
99 #define HANDLE_ERRORS(cmd)
103 * Version number of the protocol between an editor and eserve.
104 * This number should be incremented when the protocol
107 #define PROTOCOL_VERSION "4.0.0"
110 static XtInputId inputHandler
; /* Cookie for input */
112 Boolean save_files
= True
; /* When true, save all files before build actions */
115 workshop_connection_closed(void)
118 * socket closed on other end
120 XtRemoveInput(inputHandler
);
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 */
134 if ((len
= read(sd
, &lenbuf
, 6)) == 6) {
135 lenbuf
[6] = 0; /* Terminate buffer such that atoi() works right */
137 if (cbsize
< (len
+ 1)) {
138 newcb
= (char *) realloc(cmdbuf
,
139 MAX((len
+ 256), CMDBUFSIZ
));
142 cbsize
= MAX((len
+ 256), CMDBUFSIZ
);
145 if (cbsize
>= len
&& (len
= read(sd
, cmdbuf
, len
)) > 0) {
152 if (len
== 0) { /* EOF */
153 workshop_connection_closed();
161 messageFromEserve(XtPointer clientData UNUSED
,
163 XtInputId
*dum2 UNUSED
)
165 char *cmd
; /* the 1st word of the command */
169 /* We're being shut down by eserve and the "quit" message
170 * didn't arrive before the socket connection got closed */
174 pldebug("%s\n", cmd
);
179 strncmp(cmd
, NOCATGETS("ack "), 4) == 0) {
183 ackNum
= atoi(&cmd
[4]);
184 vim_snprintf(buf
, sizeof(buf
),
185 NOCATGETS("ack %d\n"), ackNum
);
186 write(sd
, buf
, strlen(buf
));
187 } else if (strncmp(cmd
,
188 NOCATGETS("addMarkType "), 12) == 0) {
193 idx
= atoi(strtok(&cmd
[12], " "));
194 color
= strtok(NULL
, NOCATGETS("\001"));
195 sign
= strtok(NULL
, NOCATGETS("\001"));
196 /* Skip space that separates names */
203 /* Change sign name to accommodate a different size? */
204 adjust_sign_name(sign
);
205 workshop_add_mark_type(idx
, color
, sign
);
212 NOCATGETS("balloon "), 8) == 0) {
215 tip
= strtok(&cmd
[8], NOCATGETS("\001"));
216 workshop_show_balloon_tip(tip
);
223 NOCATGETS("changeMarkType "), 15) == 0) {
228 file
= strtok(&cmd
[15], " ");
229 markId
= atoi(strtok(NULL
, " "));
230 type
= atoi(strtok(NULL
, " "));
231 workshop_change_mark_type(file
, markId
, type
);
237 if (strncmp(cmd
, NOCATGETS("deleteMark "), 11) == 0) {
241 file
= strtok(&cmd
[11], " ");
242 markId
= atoi(strtok(NULL
, " "));
243 workshop_delete_mark(file
, markId
);
250 strncmp(cmd
, NOCATGETS("footerMsg "), 10) == 0) {
255 atoi(strtok(&cmd
[10], " "));
256 message
= strtok(NULL
, NOCATGETS("\001"));
258 workshop_footer_message(message
, severity
);
259 } else if (strncmp(cmd
,
260 NOCATGETS("frontFile "), 10) == 0) {
263 file
= strtok(&cmd
[10], " ");
264 workshop_front_file(file
);
271 strncmp(cmd
, NOCATGETS("getMarkLine "), 12) == 0) {
277 file
= strtok(&cmd
[12], " ");
278 markid
= atoi(strtok(NULL
, " "));
279 line
= workshop_get_mark_lineno(file
, markid
);
280 vim_snprintf(buf
, sizeof(buf
),
281 NOCATGETS("markLine %s %d %d\n"),
283 write(sd
, buf
, strlen(buf
));
284 } else if (cmd
[1] == 'o' && cmd
[4] == 'L' &&
285 strncmp(cmd
, NOCATGETS("gotoLine "), 9) == 0) {
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) {
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
];
306 vim_snprintf(buffer
, sizeof(buffer
),
307 NOCATGETS("currentFile %d %s"),
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
];
313 vim_snprintf(buffer
, sizeof(buffer
),
314 NOCATGETS("cursorRow %d"), row
);
315 workshop_send_message(buffer
);
316 } else if (strcmp(cmd
, NOCATGETS("getCursorCol")) == 0) {
317 int col
= workshop_test_getcursorcol();
318 char buffer
[2*MAXPATHLEN
];
319 vim_snprintf(buffer
, sizeof(buffer
),
320 NOCATGETS("cursorCol %d"), col
);
321 workshop_send_message(buffer
);
322 } else if (strcmp(cmd
, NOCATGETS("getCursorRowText")) == 0) {
323 char *t
= workshop_test_getcursorrowtext();
324 char buffer
[2*MAXPATHLEN
];
325 vim_snprintf(buffer
, sizeof(buffer
),
326 NOCATGETS("cursorRowText %d %s"),
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
];
332 vim_snprintf(buffer
, sizeof(buffer
),
333 NOCATGETS("selectedText %d %s"),
334 t
? strlen(t
) : 0, t
? t
: "");
335 workshop_send_message(buffer
);
342 if (strncmp(cmd
, NOCATGETS("loadFile "), 9) == 0) {
347 file
= strtok(&cmd
[9], " ");
348 line
= atoi(strtok(NULL
, " "));
349 frameid
= strtok(NULL
, " ");
350 workshop_load_file(file
, line
, frameid
);
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) {
365 } else if (cmd
[1] == 'a' &&
366 strcmp(cmd
, NOCATGETS("maximize")) == 0) {
368 } else if (strcmp(cmd
, NOCATGETS("minimize")) == 0) {
376 strcmp(cmd
, NOCATGETS("option"))) {
380 name
= strtok(&cmd
[7], " ");
381 value
= strtok(NULL
, " ");
382 workshop_set_option_first(name
, value
);
388 if (strcmp(cmd
, NOCATGETS("ping")) == 0) {
392 pingNum
= atoi(&cmd
[5]);
393 workshop_send_ack(ackNum
);
401 if (strncmp(cmd
, NOCATGETS("quit"), 4) == 0) {
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.
415 workshop_disconnect();
424 strncmp(cmd
, NOCATGETS("reloadFile "), 11) == 0) {
428 file
= strtok(&cmd
[11], " ");
429 line
= atoi(strtok(NULL
, " "));
430 workshop_reload_file(file
, line
);
436 if (cmd
[1] == 'e' && cmd
[2] == 't' &&
437 strncmp(cmd
, NOCATGETS("setMark "), 8) == 0) {
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) {
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) {
466 num
= atoi(strtok(&cmd
[12], " "));
467 bracket
= strtok(NULL
, " ");
468 if (*bracket
!= '[') {
469 fprintf(stderr
, NOCATGETS("Parsing "
470 "error for sensitivity\n"));
472 table
= strtok(NULL
, NOCATGETS("]"));
473 workshop_sensitivity(num
, table
);
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
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) {
492 file
= strtok(&cmd
[16], " ");
493 workshop_save_sensitivity(file
);
499 case 't': /* Toolbar */
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();
515 unrecognised_message(cmd
);
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"));
535 if (*accText
== '-') {
538 workshop_menu_item(label
, verb
, acc
, accText
, name
, filepos
, sense
);
544 process_toolbarButton(
545 char *cmd
) /* button definition */
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"));
556 if (!strcmp(label
, NOCATGETS("-"))) {
559 if (!strcmp(help
, NOCATGETS("-"))) {
562 if (!strcmp(file
, NOCATGETS("-"))) {
565 if (!strcmp(senseVerb
, NOCATGETS("-"))) {
568 workshop_toolbar_button(label
, verb
, senseVerb
, filepos
, help
,
575 unrecognised_message(
578 pldebug("Unrecognised eserve message:\n\t%s\n", cmd
);
584 /* Change sign name to accommodate a different size:
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 */
591 adjust_sign_name(char *filename
)
594 static int fontSize
= -1;
597 fontSize
= workshop_get_font_height();
600 if (filename
[0] == '-')
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
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;
612 else if (fontSize
<= 15)
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. */
626 static int result
= -1;
628 result
= (getenv(NOCATGETS("SPRO_EDITOR_SOCKET")) != NULL
);
634 /* Connect back to eserve */
635 void workshop_connect(XtAppContext context
)
638 struct sockaddr_in server
;
639 struct hostent
* host
;
642 struct sockaddr_un server
;
650 address
= getenv(NOCATGETS("SPRO_EDITOR_SOCKET"));
651 if (address
== NULL
) {
656 port
= atoi(address
);
658 if ((sd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1) {
659 PERROR(NOCATGETS("workshop_connect"));
663 /* Get the server internet address and put into addr structure */
664 /* fill in the socket address structure and connect to server */
665 memset((char *)&server
, '\0', sizeof(server
));
666 server
.sin_family
= AF_INET
;
667 server
.sin_port
= port
;
668 if ((host
= gethostbyname(NOCATGETS("localhost"))) == NULL
) {
669 PERROR(NOCATGETS("gethostbyname"));
673 memcpy((char *)&server
.sin_addr
, host
->h_addr
, host
->h_length
);
675 if ((sd
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
676 PERROR(NOCATGETS("workshop_connect"));
680 server
.sun_family
= AF_UNIX
;
681 strcpy(server
.sun_path
, address
);
683 /* Connect to server */
684 if (connect(sd
, (struct sockaddr
*)&server
, sizeof(server
))) {
685 if (errno
== ECONNREFUSED
) {
688 if ((sd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1) {
689 PERROR(NOCATGETS("workshop_connect"));
693 if ((sd
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
694 PERROR(NOCATGETS("workshop_connect"));
698 if (connect(sd
, (struct sockaddr
*)&server
,
700 PERROR(NOCATGETS("workshop_connect"));
705 PERROR(NOCATGETS("workshop_connect"));
710 /* tell notifier we are interested in being called
711 * when there is input on the editor connection socket
713 inputHandler
= XtAppAddInput(context
, sd
, (XtPointer
) XtInputReadMask
,
714 messageFromEserve
, NULL
);
716 if ((file
= getenv(NOCATGETS("SPRO_PLUGIN_DEBUG"))) != NULL
) {
720 vim_snprintf(buf
, sizeof(buf
), "date > %s", file
);
722 dfd
= fopen(file
, "a");
728 vim_snprintf(buf
, sizeof(buf
), NOCATGETS("connected %s %s %s\n"),
729 workshop_get_editor_name(),
731 workshop_get_editor_version());
732 write(sd
, buf
, strlen(buf
));
734 vim_snprintf(buf
, sizeof(buf
), NOCATGETS("ack 1\n"));
735 write(sd
, buf
, strlen(buf
));
738 void workshop_disconnect()
740 /* Probably need to send some message here */
743 * socket closed on other end
745 XtRemoveInput(inputHandler
);
757 /* Set icon for the window */
759 workshop_set_icon(Display
*display
, Widget shell
, char **xpmdata
,
760 int width
, int height
)
763 XpmAttributes xpmAttributes
;
764 XSetWindowAttributes attr
;
770 /* Create the pixmap/icon window which is shown when you
771 * iconify the sccs viewer
772 * This code snipped was adapted from Sun WorkShop's source base,
775 XtVaGetValues(shell
, XmNbackground
, &bgPixel
, NULL
);
776 screenNum
= XScreenNumberOfScreen(XtScreen(shell
));
777 depth
= DisplayPlanes(display
, screenNum
);
778 xpmAttributes
.valuemask
= XpmColorSymbols
;
779 xpmAttributes
.numsymbols
= 1;
780 xpmAttributes
.colorsymbols
=
781 (XpmColorSymbol
*)XtMalloc(sizeof (XpmColorSymbol
) *
782 xpmAttributes
.numsymbols
);
783 xpmAttributes
.colorsymbols
[0].name
= NOCATGETS("BgColor");
784 xpmAttributes
.colorsymbols
[0].value
= NULL
;
785 xpmAttributes
.colorsymbols
[0].pixel
= bgPixel
;
786 if (XpmCreatePixmapFromData(display
,
787 RootWindow(display
, screenNum
), xpmdata
, &pixmap
,
788 NULL
, &xpmAttributes
) >= 0) {
789 attr
.background_pixmap
= pixmap
;
790 iconWindow
= XCreateWindow(display
, RootWindow(display
,
791 screenNum
), 0, 0, width
, height
, 0, depth
,
792 (unsigned int)CopyFromParent
,
793 CopyFromParent
, CWBackPixmap
, &attr
);
796 XtNiconWindow
, iconWindow
, NULL
);
798 XtFree((char *)xpmAttributes
.colorsymbols
);
802 /* Minimize and maximize shells. From libutil's shell.cc. */
804 /* utility functions from libutil's shell.cc */
806 isWindowMapped(Display
*display
, Window win
)
808 XWindowAttributes winAttrs
;
809 XGetWindowAttributes(display
,
812 if (winAttrs
.map_state
== IsViewable
) {
820 isMapped(Widget widget
)
822 if (widget
== NULL
) {
826 if (XtIsRealized(widget
) == False
) {
830 return(isWindowMapped(XtDisplay(widget
), XtWindow(widget
)));
838 Atom act_type
; /* actual Atom type returned */
839 int act_fmt
; /* actual format returned */
840 u_long nitems_ret
; /* number of items returned */
841 u_long bytes_after
; /* number of bytes remaining */
842 u_long
*property
; /* actual property returned */
845 * If a window is iconified its WM_STATE is set to IconicState. See
846 * ICCCM Version 2.0, section 4.1.3.1 for more details.
849 wm_state
= XmInternAtom(XtDisplay(w
), NOCATGETS("WM_STATE"), False
);
850 if (XtWindow(w
) != 0) { /* only check if window exists! */
851 XGetWindowProperty(XtDisplay(w
), XtWindow(w
), wm_state
, 0L, 2L,
852 False
, AnyPropertyType
, &act_type
, &act_fmt
, &nitems_ret
,
853 &bytes_after
, (u_char
**) &property
);
854 if (nitems_ret
== 2 && property
[0] == IconicState
) {
861 } /* end widgetIsIconified */
864 workshop_minimize_shell(Widget shell
)
868 XtIsRealized(shell
) == True
) {
869 if (isMapped(shell
) == True
) {
870 XIconifyWindow(XtDisplay(shell
), XtWindow(shell
),
871 XScreenNumberOfScreen(XtScreen(shell
)));
879 void workshop_maximize_shell(Widget shell
)
882 XtIsRealized(shell
) == True
&&
883 widgetIsIconified(shell
) == True
&&
884 isMapped(shell
) == False
) {
888 XtPopup(shell, XtGrabNone);
889 However, I found that that would drop any transient
890 windows that had been iconified with the window.
891 According to the ICCCM, XtMapWidget should be used
892 to bring a window from Iconic to Normal state.
893 However, Rich Mauri did a lot of work on this during
894 Bart, and found that XtPopDown,XtPopup was required
895 to fix several bugs involving multiple CDE workspaces.
896 I've tested it now and things seem to work fine but
897 I'm leaving this note for history in case this needs
904 Boolean
workshop_get_width_height(int *width
, int *height
)
908 static Boolean firstTime
= True
;
909 static Boolean success
= False
;
914 settings
= getenv(NOCATGETS("SPRO_GUI_WIDTH_HEIGHT"));
915 if (settings
!= NULL
) {
916 wid
= atoi(settings
);
917 settings
= strrchr(settings
, ':');
918 if (settings
++ != NULL
) {
919 hgt
= atoi(settings
);
921 if (wid
> 0 && hgt
> 0) {
936 Boolean
workshop_get_rows_cols(int *rows
, int *cols
)
940 static Boolean firstTime
= True
;
941 static Boolean success
= False
;
946 settings
= getenv(NOCATGETS("SPRO_GUI_ROWS_COLS"));
947 if (settings
!= NULL
) {
949 settings
= strrchr(settings
, ':');
950 if (settings
++ != NULL
) {
953 if (r
> 0 && c
> 0) {
972 void workshop_sensitivity(int num
, char *table
)
974 /* build up a verb table */
978 if ((num
< 1) || (num
> 500)) {
982 vs
= (VerbSense
*)malloc((num
+1)*sizeof(VerbSense
));
984 /* Point to the individual names (destroys the table string, but
985 * that's okay -- this is more efficient than duplicating strings) */
987 for (i
= 0; i
< num
; i
++) {
992 while (*s
&& (*s
!= ' ') && (*s
!= '\001')) {
1017 workshop_frame_sensitivities(vs
);
1025 /* Set an editor option.
1026 * IGNORE an option if you do not recognize it.
1028 void workshop_set_option_first(char *name
, char *value
)
1030 /* Currently value can only be on/off. This may change later (for
1031 * example to set an option like "balloon evaluate delay", but
1032 * for now just convert it into a boolean */
1033 Boolean on
= !strcmp(value
, "on");
1035 if (!strcmp(name
, "workshopkeys")) {
1036 workshop_hotkeys(on
);
1037 } else if (!strcmp(name
, "savefiles")) {
1039 } else if (!strcmp(name
, "balloon")) {
1040 workshop_balloon_mode(on
);
1041 } else if (!strcmp(name
, "balloondelay")) {
1042 int delay
= atoi(value
);
1043 /* Should I validate the number here?? */
1044 workshop_balloon_delay(delay
);
1046 /* Let editor interpret it */
1047 workshop_set_option(name
, value
);
1054 * Send information to eserve on certain editor events
1055 * You must make sure these are called when necessary
1057 void workshop_file_closed(char *filename
)
1059 char buffer
[2*MAXPATHLEN
];
1060 vim_snprintf(buffer
, sizeof(buffer
),
1061 NOCATGETS("deletedFile %s\n"), filename
);
1062 write(sd
, buffer
, strlen(buffer
));
1066 void workshop_file_closed_lineno(char *filename
, int lineno
)
1068 char buffer
[2*MAXPATHLEN
];
1069 vim_snprintf(buffer
, sizeof(buffer
),
1070 NOCATGETS("deletedFile %s %d\n"), filename
, lineno
);
1071 write(sd
, buffer
, strlen(buffer
));
1074 void workshop_file_opened(char *filename
, int readOnly
)
1076 char buffer
[2*MAXPATHLEN
];
1077 vim_snprintf(buffer
, sizeof(buffer
),
1078 NOCATGETS("loadedFile %s %d\n"), filename
, readOnly
);
1079 write(sd
, buffer
, strlen(buffer
));
1083 void workshop_file_saved(char *filename
)
1085 char buffer
[2*MAXPATHLEN
];
1086 vim_snprintf(buffer
, sizeof(buffer
),
1087 NOCATGETS("savedFile %s\n"), filename
);
1088 write(sd
, buffer
, strlen(buffer
));
1090 /* Let editor report any moved marks that the eserve client
1091 * should deal with (for example, moving location-based breakpoints) */
1092 workshop_moved_marks(filename
);
1096 void workshop_file_modified(char *filename
)
1098 char buffer
[2*MAXPATHLEN
];
1099 vim_snprintf(buffer
, sizeof(buffer
),
1100 NOCATGETS("modifiedFile %s\n"), filename
);
1101 write(sd
, buffer
, strlen(buffer
));
1104 void workshop_move_mark(char *filename
, int markId
, int newLineno
)
1106 char buffer
[2*MAXPATHLEN
];
1107 vim_snprintf(buffer
, sizeof(buffer
),
1108 NOCATGETS("moveMark %s %d %d\n"), filename
, markId
, newLineno
);
1109 write(sd
, buffer
, strlen(buffer
));
1113 void workshop_frame_moved(int new_x
, int new_y
, int new_w
, int new_h
)
1119 vim_snprintf(buffer
, sizeof(buffer
),
1120 NOCATGETS("frameAt %d %d %d %d\n"),
1121 new_x
, new_y
, new_w
, new_h
);
1122 write(sd
, buffer
, strlen(buffer
));
1126 /* A button in the toolbar has been pushed.
1127 * Clientdata is a pointer used by the editor code to figure out the
1128 * positions for this toolbar (probably by storing a window pointer,
1129 * and then fetching the current buffer for that window and looking up
1130 * cursor and selection positions etc.) */
1131 void workshop_perform_verb(char *verb
, void *clientData
)
1143 char buf
[2*MAXPATHLEN
];
1144 /* Later: needsFilePos indicates whether or not we need to fetch all this
1145 * info for this verb... for now, however, it looks as if
1146 * eserve parsing routines depend on it always being present */
1148 if (workshop_get_positions(clientData
,
1158 if (selection
== NULL
) {
1159 selection
= NOCATGETS("");
1162 /* Should I save the files??? This is currently done by checking
1163 if the verb is one of a few recognized ones. Later we can pass
1164 this list from eserve to the editor (it's currently hardcoded in
1165 vi and emacs as well). */
1167 if (!strcmp(verb
, "build.build") || !strcmp(verb
, "build.build-file") ||
1168 !strcmp(verb
, "debug.fix") || !strcmp(verb
, "debug.fix-all")) {
1169 workshop_save_files();
1173 vim_snprintf(buf
, sizeof(buf
),
1174 NOCATGETS("toolVerb %s %s %d,%d %d,%d %d,%d %d %s\n"),
1178 selStartLine
, selStartCol
,
1179 selEndLine
, selEndCol
,
1182 write(sd
, buf
, strlen(buf
));
1189 /* Send a message to eserve */
1190 #if defined(NOHANDS_SUPPORT_FUNCTIONS) || defined(FEAT_BEVAL)
1191 void workshop_send_message(char *buf
)
1193 write(sd
, buf
, strlen(buf
));
1197 /* Some methods, like currentFile, cursorPos, etc. are missing here.
1198 * But it looks like these are used for NoHands testing only so we
1199 * won't bother requiring editors to implement these
1207 char *fmt
, /* a printf style format line */
1214 vfprintf(dfd
, fmt
, ap
);