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 *NOTUSED1
, XtInputId
*NOTUSED2
);
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();
162 messageFromEserve(XtPointer clientData
, int *NOTUSED1
, XtInputId
*NOTUSED2
)
164 char *cmd
; /* the 1st word of the command */
168 /* We're being shut down by eserve and the "quit" message
169 * didn't arrive before the socket connection got closed */
173 pldebug("%s\n", cmd
);
178 strncmp(cmd
, NOCATGETS("ack "), 4) == 0) {
182 ackNum
= atoi(&cmd
[4]);
183 vim_snprintf(buf
, sizeof(buf
),
184 NOCATGETS("ack %d\n"), ackNum
);
185 write(sd
, buf
, strlen(buf
));
186 } else if (strncmp(cmd
,
187 NOCATGETS("addMarkType "), 12) == 0) {
192 idx
= atoi(strtok(&cmd
[12], " "));
193 color
= strtok(NULL
, NOCATGETS("\001"));
194 sign
= strtok(NULL
, NOCATGETS("\001"));
195 /* Skip space that separates names */
202 /* Change sign name to accomodate a different size? */
203 adjust_sign_name(sign
);
204 workshop_add_mark_type(idx
, color
, sign
);
211 NOCATGETS("balloon "), 8) == 0) {
214 tip
= strtok(&cmd
[8], NOCATGETS("\001"));
215 workshop_show_balloon_tip(tip
);
222 NOCATGETS("changeMarkType "), 15) == 0) {
227 file
= strtok(&cmd
[15], " ");
228 markId
= atoi(strtok(NULL
, " "));
229 type
= atoi(strtok(NULL
, " "));
230 workshop_change_mark_type(file
, markId
, type
);
236 if (strncmp(cmd
, NOCATGETS("deleteMark "), 11) == 0) {
240 file
= strtok(&cmd
[11], " ");
241 markId
= atoi(strtok(NULL
, " "));
242 workshop_delete_mark(file
, markId
);
249 strncmp(cmd
, NOCATGETS("footerMsg "), 10) == 0) {
254 atoi(strtok(&cmd
[10], " "));
255 message
= strtok(NULL
, NOCATGETS("\001"));
257 workshop_footer_message(message
, severity
);
258 } else if (strncmp(cmd
,
259 NOCATGETS("frontFile "), 10) == 0) {
262 file
= strtok(&cmd
[10], " ");
263 workshop_front_file(file
);
270 strncmp(cmd
, NOCATGETS("getMarkLine "), 12) == 0) {
276 file
= strtok(&cmd
[12], " ");
277 markid
= atoi(strtok(NULL
, " "));
278 line
= workshop_get_mark_lineno(file
, markid
);
279 vim_snprintf(buf
, sizeof(buf
),
280 NOCATGETS("markLine %s %d %d\n"),
282 write(sd
, buf
, strlen(buf
));
283 } else if (cmd
[1] == 'o' && cmd
[4] == 'L' &&
284 strncmp(cmd
, NOCATGETS("gotoLine "), 9) == 0) {
288 file
= strtok(&cmd
[9], " ");
289 lineno
= atoi(strtok(NULL
, " "));
290 workshop_goto_line(file
, lineno
);
291 } else if (strncmp(cmd
,
292 NOCATGETS("gotoMark "), 9) == 0) {
297 file
= strtok(&cmd
[9], " ");
298 markId
= atoi(strtok(NULL
, " "));
299 message
= strtok(NULL
, NOCATGETS("\001"));
300 workshop_goto_mark(file
, markId
, message
);
301 #ifdef NOHANDS_SUPPORT_FUNCTIONS
302 } else if (strcmp(cmd
, NOCATGETS("getCurrentFile")) == 0) {
303 char *f
= workshop_test_getcurrentfile();
304 char buffer
[2*MAXPATHLEN
];
305 vim_snprintf(buffer
, sizeof(buffer
),
306 NOCATGETS("currentFile %d %s"),
307 f
? strlen(f
) : 0, f
? f
: "");
308 workshop_send_message(buffer
);
309 } else if (strcmp(cmd
, NOCATGETS("getCursorRow")) == 0) {
310 int row
= workshop_test_getcursorrow();
311 char buffer
[2*MAXPATHLEN
];
312 vim_snprintf(buffer
, sizeof(buffer
),
313 NOCATGETS("cursorRow %d"), row
);
314 workshop_send_message(buffer
);
315 } else if (strcmp(cmd
, NOCATGETS("getCursorCol")) == 0) {
316 int col
= workshop_test_getcursorcol();
317 char buffer
[2*MAXPATHLEN
];
318 vim_snprintf(buffer
, sizeof(buffer
),
319 NOCATGETS("cursorCol %d"), col
);
320 workshop_send_message(buffer
);
321 } else if (strcmp(cmd
, NOCATGETS("getCursorRowText")) == 0) {
322 char *t
= workshop_test_getcursorrowtext();
323 char buffer
[2*MAXPATHLEN
];
324 vim_snprintf(buffer
, sizeof(buffer
),
325 NOCATGETS("cursorRowText %d %s"),
326 t
? strlen(t
) : 0, t
? t
: "");
327 workshop_send_message(buffer
);
328 } else if (strcmp(cmd
, NOCATGETS("getSelectedText")) == 0) {
329 char *t
= workshop_test_getselectedtext();
330 char buffer
[2*MAXPATHLEN
];
331 vim_snprintf(buffer
, sizeof(buffer
),
332 NOCATGETS("selectedText %d %s"),
333 t
? strlen(t
) : 0, t
? t
: "");
334 workshop_send_message(buffer
);
341 if (strncmp(cmd
, NOCATGETS("loadFile "), 9) == 0) {
346 file
= strtok(&cmd
[9], " ");
347 line
= atoi(strtok(NULL
, " "));
348 frameid
= strtok(NULL
, " ");
349 workshop_load_file(file
, line
, frameid
);
354 case 'm': /* Menu, minimize, maximize */
355 if (cmd
[1] == 'e' && cmd
[4] == 'B' &&
356 strncmp(cmd
, NOCATGETS("menuBegin "), 10) == 0) {
357 workshop_menu_begin(&cmd
[10]);
358 } else if (cmd
[1] == 'e' && cmd
[4] == 'I' &&
359 strncmp(cmd
, NOCATGETS("menuItem "), 9) == 0) {
360 process_menuItem(cmd
);
361 } else if (cmd
[1] == 'e' && cmd
[4] == 'E' &&
362 strcmp(cmd
, NOCATGETS("menuEnd")) == 0) {
364 } else if (cmd
[1] == 'a' &&
365 strcmp(cmd
, NOCATGETS("maximize")) == 0) {
367 } else if (strcmp(cmd
, NOCATGETS("minimize")) == 0) {
375 strcmp(cmd
, NOCATGETS("option"))) {
379 name
= strtok(&cmd
[7], " ");
380 value
= strtok(NULL
, " ");
381 workshop_set_option_first(name
, value
);
387 if (strcmp(cmd
, NOCATGETS("ping")) == 0) {
391 pingNum
= atoi(&cmd
[5]);
392 workshop_send_ack(ackNum
);
400 if (strncmp(cmd
, NOCATGETS("quit"), 4) == 0) {
402 /* Close the connection. It's important to do
403 * that now, since workshop_quit might be
404 * looking at open files. For example, if you
405 * have modified one of the files without
406 * saving, NEdit will ask you what you want to
407 * do, and spin loop by calling
408 * XtAppProcessEvent while waiting for your
409 * reply. In this case, if we still have an
410 * input handler and the socket has been
411 * closed on the other side when eserve
412 * expired, we will hang in IoWait.
414 workshop_disconnect();
423 strncmp(cmd
, NOCATGETS("reloadFile "), 11) == 0) {
427 file
= strtok(&cmd
[11], " ");
428 line
= atoi(strtok(NULL
, " "));
429 workshop_reload_file(file
, line
);
435 if (cmd
[1] == 'e' && cmd
[2] == 't' &&
436 strncmp(cmd
, NOCATGETS("setMark "), 8) == 0) {
442 file
= strtok(&cmd
[8], " ");
443 line
= atoi(strtok(NULL
, " "));
444 markId
= atoi(strtok(NULL
, " "));
445 type
= atoi(strtok(NULL
, " "));
446 workshop_set_mark(file
, line
, markId
, type
);
447 } else if (cmd
[1] == 'h' &&
448 strncmp(cmd
, NOCATGETS("showFile "), 9) == 0) {
449 workshop_show_file(&cmd
[9]);
450 } else if (cmd
[1] == 'u' &&
451 strncmp(cmd
, NOCATGETS("subMenu "), 8) == 0) {
454 label
= strtok(&cmd
[8], NOCATGETS("\001"));
455 workshop_submenu_begin(label
);
456 } else if (cmd
[1] == 'u' &&
457 strcmp(cmd
, NOCATGETS("subMenuEnd")) == 0) {
458 workshop_submenu_end();
459 } else if (cmd
[1] == 'e' && cmd
[2] == 'n' &&
460 strncmp(cmd
, NOCATGETS("sensitivity "), 12) == 0) {
465 num
= atoi(strtok(&cmd
[12], " "));
466 bracket
= strtok(NULL
, " ");
467 if (*bracket
!= '[') {
468 fprintf(stderr
, NOCATGETS("Parsing "
469 "error for sensitivity\n"));
471 table
= strtok(NULL
, NOCATGETS("]"));
472 workshop_sensitivity(num
, table
);
474 } else if (cmd
[1] == 'e' && cmd
[2] == 'n' && cmd
[3] == 'd' &&
475 strncmp(cmd
, NOCATGETS("sendVerb "), 9) == 0) {
476 /* Send the given verb back (used for the
477 * debug.lineno callback (such that other tools
478 * can obtain the position coordinates or the
482 verb
= strtok(&cmd
[9], " ");
483 workshop_perform_verb(verb
, NULL
);
484 } else if (cmd
[1] == 'a' &&
485 strncmp(cmd
, NOCATGETS("saveFile "), 9) == 0) {
486 workshop_save_file(&cmd
[9]);
487 #ifdef NOHANDS_SUPPORT_FUNCTIONS
488 } else if (strncmp(cmd
, NOCATGETS("saveSensitivity "), 16) == 0) {
491 file
= strtok(&cmd
[16], " ");
492 workshop_save_sensitivity(file
);
498 case 't': /* Toolbar */
500 strncmp(cmd
, NOCATGETS("toolbarBegin"), 12) == 0) {
501 workshop_toolbar_begin();
502 } else if (cmd
[8] == 'u' &&
503 strncmp(cmd
, NOCATGETS("toolbarButton"), 13) == 0) {
504 process_toolbarButton(cmd
);
505 } else if (cmd
[7] == 'E' &&
506 strcmp(cmd
, NOCATGETS("toolbarEnd")) == 0) {
507 workshop_toolbar_end();
514 unrecognised_message(cmd
);
524 char *label
= strtok(&cmd
[9], NOCATGETS("\001"));
525 char *verb
= strtok(NULL
, NOCATGETS("\001"));
526 char *acc
= strtok(NULL
, NOCATGETS("\001"));
527 char *accText
= strtok(NULL
, NOCATGETS("\001"));
528 char *name
= strtok(NULL
, NOCATGETS("\001"));
529 char *sense
= strtok(NULL
, NOCATGETS("\n"));
530 char *filepos
= strtok(NULL
, NOCATGETS("\n"));
534 if (*accText
== '-') {
537 workshop_menu_item(label
, verb
, acc
, accText
, name
, filepos
, sense
);
543 process_toolbarButton(
544 char *cmd
) /* button definition */
546 char *label
= strtok(&cmd
[14], NOCATGETS("\001"));
547 char *verb
= strtok(NULL
, NOCATGETS("\001"));
548 char *senseVerb
= strtok(NULL
, NOCATGETS("\001"));
549 char *filepos
= strtok(NULL
, NOCATGETS("\001"));
550 char *help
= strtok(NULL
, NOCATGETS("\001"));
551 char *sense
= strtok(NULL
, NOCATGETS("\001"));
552 char *file
= strtok(NULL
, NOCATGETS("\001"));
553 char *left
= strtok(NULL
, NOCATGETS("\n"));
555 if (!strcmp(label
, NOCATGETS("-"))) {
558 if (!strcmp(help
, NOCATGETS("-"))) {
561 if (!strcmp(file
, NOCATGETS("-"))) {
564 if (!strcmp(senseVerb
, NOCATGETS("-"))) {
567 workshop_toolbar_button(label
, verb
, senseVerb
, filepos
, help
,
574 unrecognised_message(
577 pldebug("Unrecognised eserve message:\n\t%s\n", cmd
);
583 /* Change sign name to accomodate a different size:
584 * Create the filename based on the height. The filename format
585 * of multisize icons are:
586 * x.xpm : largest icon
587 * x1.xpm : smaller icon
588 * x2.xpm : smallest icon */
590 adjust_sign_name(char *filename
)
593 static int fontSize
= -1;
596 fontSize
= workshop_get_font_height();
599 if (filename
[0] == '-')
602 /* This is ugly: later we should instead pass the fontheight over
603 * to eserve on startup and let eserve just send the right filenames
604 * to us in the first place
606 * I know that the filename will end with 1.xpm (see
607 * GuiEditor.cc`LispPrintSign if you wonder why) */
608 s
= filename
+strlen(filename
)-5;
611 else if (fontSize
<= 15)
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. */
624 static int result
= -1;
626 result
= (getenv(NOCATGETS("SPRO_EDITOR_SOCKET")) != NULL
);
631 /* Connect back to eserve */
632 void workshop_connect(XtAppContext context
)
635 struct sockaddr_in server
;
636 struct hostent
* host
;
639 struct sockaddr_un server
;
647 address
= getenv(NOCATGETS("SPRO_EDITOR_SOCKET"));
648 if (address
== NULL
) {
653 port
= atoi(address
);
655 if ((sd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1) {
656 PERROR(NOCATGETS("workshop_connect"));
660 /* Get the server internet address and put into addr structure */
661 /* fill in the socket address structure and connect to server */
662 memset((char *)&server
, '\0', sizeof(server
));
663 server
.sin_family
= AF_INET
;
664 server
.sin_port
= port
;
665 if ((host
= gethostbyname(NOCATGETS("localhost"))) == NULL
) {
666 PERROR(NOCATGETS("gethostbyname"));
670 memcpy((char *)&server
.sin_addr
, host
->h_addr
, host
->h_length
);
672 if ((sd
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
673 PERROR(NOCATGETS("workshop_connect"));
677 server
.sun_family
= AF_UNIX
;
678 strcpy(server
.sun_path
, address
);
680 /* Connect to server */
681 if (connect(sd
, (struct sockaddr
*)&server
, sizeof(server
))) {
682 if (errno
== ECONNREFUSED
) {
685 if ((sd
= socket(AF_INET
, SOCK_STREAM
, 0)) == -1) {
686 PERROR(NOCATGETS("workshop_connect"));
690 if ((sd
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
691 PERROR(NOCATGETS("workshop_connect"));
695 if (connect(sd
, (struct sockaddr
*)&server
,
697 PERROR(NOCATGETS("workshop_connect"));
702 PERROR(NOCATGETS("workshop_connect"));
707 /* tell notifier we are interested in being called
708 * when there is input on the editor connection socket
710 inputHandler
= XtAppAddInput(context
, sd
, (XtPointer
) XtInputReadMask
,
711 messageFromEserve
, NULL
);
713 if ((file
= getenv(NOCATGETS("SPRO_PLUGIN_DEBUG"))) != NULL
) {
717 vim_snprintf(buf
, sizeof(buf
), "date > %s", file
);
719 dfd
= fopen(file
, "a");
725 vim_snprintf(buf
, sizeof(buf
), NOCATGETS("connected %s %s %s\n"),
726 workshop_get_editor_name(),
728 workshop_get_editor_version());
729 write(sd
, buf
, strlen(buf
));
731 vim_snprintf(buf
, sizeof(buf
), NOCATGETS("ack 1\n"));
732 write(sd
, buf
, strlen(buf
));
735 void workshop_disconnect()
737 /* Probably need to send some message here */
740 * socket closed on other end
742 XtRemoveInput(inputHandler
);
753 /* Set icon for the window */
755 workshop_set_icon(Display
*display
, Widget shell
, char **xpmdata
,
756 int width
, int height
)
759 XpmAttributes xpmAttributes
;
760 XSetWindowAttributes attr
;
766 /* Create the pixmap/icon window which is shown when you
767 * iconify the sccs viewer
768 * This code snipped was adapted from Sun WorkShop's source base,
771 XtVaGetValues(shell
, XmNbackground
, &bgPixel
, NULL
);
772 screenNum
= XScreenNumberOfScreen(XtScreen(shell
));
773 depth
= DisplayPlanes(display
, screenNum
);
774 xpmAttributes
.valuemask
= XpmColorSymbols
;
775 xpmAttributes
.numsymbols
= 1;
776 xpmAttributes
.colorsymbols
=
777 (XpmColorSymbol
*)XtMalloc(sizeof (XpmColorSymbol
) *
778 xpmAttributes
.numsymbols
);
779 xpmAttributes
.colorsymbols
[0].name
= NOCATGETS("BgColor");
780 xpmAttributes
.colorsymbols
[0].value
= NULL
;
781 xpmAttributes
.colorsymbols
[0].pixel
= bgPixel
;
782 if (XpmCreatePixmapFromData(display
,
783 RootWindow(display
, screenNum
), xpmdata
, &pixmap
,
784 NULL
, &xpmAttributes
) >= 0) {
785 attr
.background_pixmap
= pixmap
;
786 iconWindow
= XCreateWindow(display
, RootWindow(display
,
787 screenNum
), 0, 0, width
, height
, 0, depth
,
788 (unsigned int)CopyFromParent
,
789 CopyFromParent
, CWBackPixmap
, &attr
);
792 XtNiconWindow
, iconWindow
, NULL
);
794 XtFree((char *)xpmAttributes
.colorsymbols
);
797 /* Minimize and maximize shells. From libutil's shell.cc. */
799 /* utility functions from libutil's shell.cc */
801 isWindowMapped(Display
*display
, Window win
)
803 XWindowAttributes winAttrs
;
804 XGetWindowAttributes(display
,
807 if (winAttrs
.map_state
== IsViewable
) {
815 isMapped(Widget widget
)
817 if (widget
== NULL
) {
821 if (XtIsRealized(widget
) == False
) {
825 return(isWindowMapped(XtDisplay(widget
), XtWindow(widget
)));
833 Atom act_type
; /* actual Atom type returned */
834 int act_fmt
; /* actual format returned */
835 u_long nitems_ret
; /* number of items returned */
836 u_long bytes_after
; /* number of bytes remaining */
837 u_long
*property
; /* actual property returned */
840 * If a window is iconified its WM_STATE is set to IconicState. See
841 * ICCCM Version 2.0, section 4.1.3.1 for more details.
844 wm_state
= XmInternAtom(XtDisplay(w
), NOCATGETS("WM_STATE"), False
);
845 if (XtWindow(w
) != 0) { /* only check if window exists! */
846 XGetWindowProperty(XtDisplay(w
), XtWindow(w
), wm_state
, 0L, 2L,
847 False
, AnyPropertyType
, &act_type
, &act_fmt
, &nitems_ret
,
848 &bytes_after
, (u_char
**) &property
);
849 if (nitems_ret
== 2 && property
[0] == IconicState
) {
856 } /* end widgetIsIconified */
859 workshop_minimize_shell(Widget shell
)
863 XtIsRealized(shell
) == True
) {
864 if (isMapped(shell
) == True
) {
865 XIconifyWindow(XtDisplay(shell
), XtWindow(shell
),
866 XScreenNumberOfScreen(XtScreen(shell
)));
874 void workshop_maximize_shell(Widget shell
)
877 XtIsRealized(shell
) == True
&&
878 widgetIsIconified(shell
) == True
&&
879 isMapped(shell
) == False
) {
883 XtPopup(shell, XtGrabNone);
884 However, I found that that would drop any transient
885 windows that had been iconified with the window.
886 According to the ICCCM, XtMapWidget should be used
887 to bring a window from Iconic to Normal state.
888 However, Rich Mauri did a lot of work on this during
889 Bart, and found that XtPopDown,XtPopup was required
890 to fix several bugs involving multiple CDE workspaces.
891 I've tested it now and things seem to work fine but
892 I'm leaving this note for history in case this needs
899 Boolean
workshop_get_width_height(int *width
, int *height
)
903 static Boolean firstTime
= True
;
904 static Boolean success
= False
;
909 settings
= getenv(NOCATGETS("SPRO_GUI_WIDTH_HEIGHT"));
910 if (settings
!= NULL
) {
911 wid
= atoi(settings
);
912 settings
= strrchr(settings
, ':');
913 if (settings
++ != NULL
) {
914 hgt
= atoi(settings
);
916 if (wid
> 0 && hgt
> 0) {
931 Boolean
workshop_get_rows_cols(int *rows
, int *cols
)
935 static Boolean firstTime
= True
;
936 static Boolean success
= False
;
941 settings
= getenv(NOCATGETS("SPRO_GUI_ROWS_COLS"));
942 if (settings
!= NULL
) {
944 settings
= strrchr(settings
, ':');
945 if (settings
++ != NULL
) {
948 if (r
> 0 && c
> 0) {
966 void workshop_sensitivity(int num
, char *table
)
968 /* build up a verb table */
972 if ((num
< 1) || (num
> 500)) {
976 vs
= (VerbSense
*)malloc((num
+1)*sizeof(VerbSense
));
978 /* Point to the individual names (destroys the table string, but
979 * that's okay -- this is more efficient than duplicating strings) */
981 for (i
= 0; i
< num
; i
++) {
986 while (*s
&& (*s
!= ' ') && (*s
!= '\001')) {
1011 workshop_frame_sensitivities(vs
);
1019 /* Set an editor option.
1020 * IGNORE an option if you do not recognize it.
1022 void workshop_set_option_first(char *name
, char *value
)
1024 /* Currently value can only be on/off. This may change later (for
1025 * example to set an option like "balloon evaluate delay", but
1026 * for now just convert it into a boolean */
1027 Boolean on
= !strcmp(value
, "on");
1029 if (!strcmp(name
, "workshopkeys")) {
1030 workshop_hotkeys(on
);
1031 } else if (!strcmp(name
, "savefiles")) {
1033 } else if (!strcmp(name
, "balloon")) {
1034 workshop_balloon_mode(on
);
1035 } else if (!strcmp(name
, "balloondelay")) {
1036 int delay
= atoi(value
);
1037 /* Should I validate the number here?? */
1038 workshop_balloon_delay(delay
);
1040 /* Let editor interpret it */
1041 workshop_set_option(name
, value
);
1048 * Send information to eserve on certain editor events
1049 * You must make sure these are called when necessary
1052 void workshop_file_closed(char *filename
)
1054 char buffer
[2*MAXPATHLEN
];
1055 vim_snprintf(buffer
, sizeof(buffer
),
1056 NOCATGETS("deletedFile %s\n"), filename
);
1057 write(sd
, buffer
, strlen(buffer
));
1060 void workshop_file_closed_lineno(char *filename
, int lineno
)
1062 char buffer
[2*MAXPATHLEN
];
1063 vim_snprintf(buffer
, sizeof(buffer
),
1064 NOCATGETS("deletedFile %s %d\n"), filename
, lineno
);
1065 write(sd
, buffer
, strlen(buffer
));
1068 void workshop_file_opened(char *filename
, int readOnly
)
1070 char buffer
[2*MAXPATHLEN
];
1071 vim_snprintf(buffer
, sizeof(buffer
),
1072 NOCATGETS("loadedFile %s %d\n"), filename
, readOnly
);
1073 write(sd
, buffer
, strlen(buffer
));
1077 void workshop_file_saved(char *filename
)
1079 char buffer
[2*MAXPATHLEN
];
1080 vim_snprintf(buffer
, sizeof(buffer
),
1081 NOCATGETS("savedFile %s\n"), filename
);
1082 write(sd
, buffer
, strlen(buffer
));
1084 /* Let editor report any moved marks that the eserve client
1085 * should deal with (for example, moving location-based breakpoints) */
1086 workshop_moved_marks(filename
);
1089 void workshop_move_mark(char *filename
, int markId
, int newLineno
)
1091 char buffer
[2*MAXPATHLEN
];
1092 vim_snprintf(buffer
, sizeof(buffer
),
1093 NOCATGETS("moveMark %s %d %d\n"), filename
, markId
, newLineno
);
1094 write(sd
, buffer
, strlen(buffer
));
1097 void workshop_file_modified(char *filename
)
1099 char buffer
[2*MAXPATHLEN
];
1100 vim_snprintf(buffer
, sizeof(buffer
),
1101 NOCATGETS("modifiedFile %s\n"), filename
);
1102 write(sd
, buffer
, strlen(buffer
));
1105 void workshop_frame_moved(int new_x
, int new_y
, int new_w
, int new_h
)
1111 vim_snprintf(buffer
, sizeof(buffer
),
1112 NOCATGETS("frameAt %d %d %d %d\n"),
1113 new_x
, new_y
, new_w
, new_h
);
1114 write(sd
, buffer
, strlen(buffer
));
1118 /* A button in the toolbar has been pushed.
1119 * Clientdata is a pointer used by the editor code to figure out the
1120 * positions for this toolbar (probably by storing a window pointer,
1121 * and then fetching the current buffer for that window and looking up
1122 * cursor and selection positions etc.) */
1123 void workshop_perform_verb(char *verb
, void *clientData
)
1135 char buf
[2*MAXPATHLEN
];
1136 /* Later: needsFilePos indicates whether or not we need to fetch all this
1137 * info for this verb... for now, however, it looks as if
1138 * eserve parsing routines depend on it always being present */
1140 if (workshop_get_positions(clientData
,
1150 if (selection
== NULL
) {
1151 selection
= NOCATGETS("");
1154 /* Should I save the files??? This is currently done by checking
1155 if the verb is one of a few recognized ones. Later we can pass
1156 this list from eserve to the editor (it's currently hardcoded in
1157 vi and emacs as well). */
1159 if (!strcmp(verb
, "build.build") || !strcmp(verb
, "build.build-file") ||
1160 !strcmp(verb
, "debug.fix") || !strcmp(verb
, "debug.fix-all")) {
1161 workshop_save_files();
1165 vim_snprintf(buf
, sizeof(buf
),
1166 NOCATGETS("toolVerb %s %s %d,%d %d,%d %d,%d %d %s\n"),
1170 selStartLine
, selStartCol
,
1171 selEndLine
, selEndCol
,
1174 write(sd
, buf
, strlen(buf
));
1181 /* Send a message to eserve */
1182 void workshop_send_message(char *buf
)
1184 write(sd
, buf
, strlen(buf
));
1187 /* Some methods, like currentFile, cursorPos, etc. are missing here.
1188 * But it looks like these are used for NoHands testing only so we
1189 * won't bother requiring editors to implement these
1197 char *fmt
, /* a printf style format line */
1204 vfprintf(dfd
, fmt
, ap
);