blob: 425174350fddd30972baa3d3c3a17fe51f6b90e6 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
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
Bram Moolenaar32d19c12018-09-13 17:26:54 +020011#include "protodef.h"
Bram Moolenaar071d4272004-06-13 20:20:40 +000012#ifdef HAVE_CONFIG_H
13# include "auto/config.h"
14#endif
15#include <stdio.h>
16#include <stdlib.h>
Bram Moolenaardfccaf02004-12-31 20:56:11 +000017#include <sys/types.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000018#include <netdb.h>
19#include <netinet/in.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000020#include <sys/socket.h>
21#ifdef HAVE_LIBGEN_H
22# include <libgen.h>
23#endif
24#include <unistd.h>
25#include <string.h>
26#include <stdlib.h>
27#include <ctype.h>
28
29#include <X11/Intrinsic.h>
30#include <Xm/Xm.h>
31#include <Xm/PushB.h>
32
33#include "integration.h" /* <EditPlugin/integration.h> */
34
35#include "vim.h"
36#include "version.h"
Bram Moolenaar071d4272004-06-13 20:20:40 +000037#include "workshop.h"
38
39void workshop_hotkeys(Boolean);
40
41static Boolean isShowing(int);
42static win_T *get_window(buf_T *);
Bram Moolenaar071d4272004-06-13 20:20:40 +000043static void updatePriority(Boolean);
44static char *addUniqueMnemonic(char *, char *);
45static char *fixup(char *);
46static char *get_selection(buf_T *);
47static char *append_selection(int, char *, int *, int *);
48static void load_buffer_by_name(char *, int);
Bram Moolenaar071d4272004-06-13 20:20:40 +000049static void load_window(char *, int lnum);
50static void warp_to_pc(int);
Bram Moolenaarc3719bd2017-11-18 22:13:31 +010051#ifdef FEAT_BEVAL_GUI
Bram Moolenaarba07ce32010-01-06 18:25:34 +010052void workshop_beval_cb(BalloonEval *, int);
Bram Moolenaar04958cb2018-06-23 19:23:02 +020053# ifdef FEAT_VARTABS
54static int computeIndex(int, char_u *, int, int *);
55# else
Bram Moolenaarba07ce32010-01-06 18:25:34 +010056static int computeIndex(int, char_u *, int);
Bram Moolenaar04958cb2018-06-23 19:23:02 +020057# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000058#endif
59static char *fixAccelText(char *);
60static void addMenu(char *, char *, char *);
61static char *lookupVerb(char *, int);
Bram Moolenaar071d4272004-06-13 20:20:40 +000062static void coloncmd(char *, Boolean);
63
64extern Widget vimShell;
65extern Widget textArea;
66extern XtAppContext app_context;
67
68static int tbpri; /* ToolBar priority */
69int usingSunWorkShop = 0; /* set if -ws flag is used */
70char curMenuName[BUFSIZ];
71char curMenuPriority[BUFSIZ];
Bram Moolenaar071d4272004-06-13 20:20:40 +000072
73static Boolean workshopInitDone = False;
74static Boolean workshopHotKeysEnabled = False;
75
76/*
77 * The following enum is from <gp_dbx/gp_dbx_common.h>. We can't include it
Bram Moolenaar9af41842016-09-25 21:45:05 +020078 * here because it's C++.
Bram Moolenaar071d4272004-06-13 20:20:40 +000079 */
80enum
81{
82 GPLineEval_EVALUATE, /* evaluate expression */
83 GPLineEval_INDIRECT, /* evaluate *<expression> */
84 GPLineEval_TYPE /* type of expression */
85};
86
87/*
88 * Store each verb in the MenuMap. This lets us map from a verb to a menu.
89 * There may be multiple matches for a single verb in this table.
90 */
91#define MENU_INC 50 /* menuMap incremental size increases */
92typedef struct
93{
94 char *name; /* name of the menu */
95 char *accel; /* optional accelerator key */
96 char *verb; /* menu verb */
97} MenuMap;
98static MenuMap *menuMap; /* list of verb/menu mappings */
99static int menuMapSize; /* current size of menuMap */
100static int menuMapMax; /* allocated size of menuMap */
101static char *initialFileCmd; /* save command but defer doing it */
102
103
104 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100105workshop_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000106{
107 char_u buf[64];
108 int is_dirty = FALSE;
109 int width, height;
110 XtInputMask mask;
111
112 /*
113 * Turn on MenuBar, ToolBar, and Footer.
114 */
115 STRCPY(buf, p_go);
116 if (vim_strchr(p_go, GO_MENUS) == NULL)
117 {
118 STRCAT(buf, "m");
119 is_dirty = TRUE;
120 }
121 if (vim_strchr(p_go, GO_TOOLBAR) == NULL)
122 {
123 STRCAT(buf, "T");
124 is_dirty = TRUE;
125 }
126 if (vim_strchr(p_go, GO_FOOTER) == NULL)
127 {
128 STRCAT(buf, "F");
129 is_dirty = TRUE;
130 }
131 if (is_dirty)
132 set_option_value((char_u *)"go", 0L, buf, 0);
133
134 /*
135 * Set size from workshop_get_width_height().
136 */
137 width = height = 0;
138 if (workshop_get_width_height(&width, &height))
139 {
140 XtVaSetValues(vimShell,
141 XmNwidth, width,
142 XmNheight, height,
143 NULL);
144 }
145
146 /*
147 * Now read in the initial messages from eserve.
148 */
149 while ((mask = XtAppPending(app_context))
150 && (mask & XtIMAlternateInput) && !workshopInitDone)
151 XtAppProcessEvent(app_context, (XtInputMask)XtIMAlternateInput);
152}
153
154 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100155workshop_postinit(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000156{
157 do_cmdline_cmd((char_u *)initialFileCmd);
158 ALT_INPUT_LOCK_OFF;
159 free(initialFileCmd);
160 initialFileCmd = NULL;
161}
162
163 void
164ex_wsverb(exarg_T *eap)
165{
166 msg_clr_cmdline();
167 workshop_perform_verb((char *) eap->arg, NULL);
168}
169
170/*
171 * Editor name
172 * This string is recognized by eserve and should be all lower case.
173 * This is how the editor detects that it is talking to gvim instead
174 * of NEdit, for example, when the connection is initiated from the editor.
175 */
176 char *
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100177workshop_get_editor_name(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000178{
179 return "gvim";
180}
181
182/*
183 * Version number of the editor.
184 * This number is communicated along with the protocol
185 * version to the application.
186 */
187 char *
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100188workshop_get_editor_version(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000189{
190 return Version;
191}
192
193/*
194 * Answer functions: called by eserve
195 */
196
197/*
198 * Name:
199 * workshop_load_file
200 *
201 * Function:
202 * Load a given file into the WorkShop buffer.
203 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000204 void
205workshop_load_file(
206 char *filename, /* the file to load */
207 int line, /* an optional line number (or 0) */
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000208 char *frameid UNUSED) /* used for multi-frame support */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000209{
210#ifdef WSDEBUG_TRACE
211 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
212 wstrace("workshop_load_file(%s, %d)\n", filename, line);
213#endif
214
Bram Moolenaarc3719bd2017-11-18 22:13:31 +0100215#ifdef FEAT_BEVAL_GUI
Bram Moolenaare4efc3b2005-03-07 23:16:51 +0000216 bevalServers |= BEVAL_WORKSHOP;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000217#endif
218
219 load_window(filename, line);
220}
221
222/*
223 * Reload the WorkShop buffer
224 */
225 void
226workshop_reload_file(
227 char *filename,
228 int line)
229{
230#ifdef WSDEBUG_TRACE
231 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
232 wstrace("workshop_reload_file(%s, %d)\n", filename, line);
233#endif
234 load_window(filename, line);
235}
236
237 void
238workshop_show_file(
239 char *filename)
240{
241#ifdef WSDEBUG_TRACE
242 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
243 wstrace("workshop_show_file(%s)\n", filename);
244#endif
245
246 load_window(filename, 0);
247}
248
249 void
250workshop_goto_line(
251 char *filename,
252 int lineno)
253{
254#ifdef WSDEBUG_TRACE
255 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
256 wstrace("workshop_goto_line(%s, %d)\n", filename, lineno);
257#endif
258
259 load_window(filename, lineno);
260}
261
Bram Moolenaar071d4272004-06-13 20:20:40 +0000262 void
263workshop_front_file(
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000264 char *filename UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000265{
266#ifdef WSDEBUG_TRACE
267 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
268 wstrace("workshop_front_file()\n");
269#endif
270 /*
271 * Assumption: This function will always be called after a call to
272 * workshop_show_file(), so the file is always showing.
273 */
274 if (vimShell != NULL)
275 XRaiseWindow(gui.dpy, XtWindow(vimShell));
276}
277
278 void
279workshop_save_file(
280 char *filename)
281{
282 char cbuf[BUFSIZ]; /* build vim command here */
283
284#ifdef WSDEBUG_TRACE
285 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
286 wstrace("workshop_save_file(%s)\n", filename);
287#endif
288
289 /* Save the given file */
Bram Moolenaar051b7822005-05-19 21:00:46 +0000290 vim_snprintf(cbuf, sizeof(cbuf), "w %s", filename);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000291 coloncmd(cbuf, TRUE);
292}
293
294 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100295workshop_save_files(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000296{
297 /* Save the given file */
298#ifdef WSDEBUG_TRACE
299 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
300 wstrace("workshop_save_files()\n");
301#endif
302
303 add_to_input_buf((char_u *) ":wall\n", 6);
304}
305
306 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100307workshop_quit(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000308{
309#ifdef WSDEBUG_TRACE
310 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
311 wstrace("workshop_quit()\n");
312#endif
313
314 add_to_input_buf((char_u *) ":qall\n", 6);
315}
316
317 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100318workshop_minimize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000319{
320#ifdef WSDEBUG_TRACE
321 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
322 wstrace("workshop_minimize()\n");
323#endif
324 workshop_minimize_shell(vimShell);
325}
326 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100327workshop_maximize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000328{
329#ifdef WSDEBUG_TRACE
330 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
331 wstrace("workshop_maximize()\n");
332#endif
333
334 workshop_maximize_shell(vimShell);
335}
336
337 void
338workshop_add_mark_type(
339 int idx,
340 char *colorspec,
341 char *sign)
342{
343 char gbuf[BUFSIZ]; /* buffer for sign name */
344 char cibuf[BUFSIZ]; /* color information */
345 char cbuf[BUFSIZ]; /* command buffer */
346 char *bp;
347
348#ifdef WSDEBUG_TRACE
349 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
350 {
351 char *cp;
352
353 cp = strrchr(sign, '/');
354 if (cp == NULL)
355 cp = sign;
356 else
357 cp++; /* skip '/' character */
358 wstrace("workshop_add_mark_type(%d, \"%s\", \"%s\")\n", idx,
359 colorspec && *colorspec ? colorspec : "<None>", cp);
360 }
361#endif
362
363 /*
364 * Isolate the basename of sign in gbuf. We will use this for the
365 * GroupName in the highlight command sent to vim.
366 */
367 STRCPY(gbuf, gettail((char_u *)sign));
368 bp = strrchr(gbuf, '.');
369 if (bp != NULL)
370 *bp = NUL;
371
372 if (gbuf[0] != '-' && gbuf[1] != NUL)
373 {
374 if (colorspec != NULL && *colorspec)
375 {
Bram Moolenaar051b7822005-05-19 21:00:46 +0000376 vim_snprintf(cbuf, sizeof(cbuf),
377 "highlight WS%s guibg=%s", gbuf, colorspec);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000378 coloncmd(cbuf, FALSE);
Bram Moolenaar051b7822005-05-19 21:00:46 +0000379 vim_snprintf(cibuf, sizeof(cibuf), "linehl=WS%s", gbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000380 }
381 else
382 cibuf[0] = NUL;
383
Bram Moolenaar051b7822005-05-19 21:00:46 +0000384 vim_snprintf(cbuf, sizeof(cbuf),
385 "sign define %d %s icon=%s", idx, cibuf, sign);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000386 coloncmd(cbuf, TRUE);
387 }
388}
389
390 void
391workshop_set_mark(
392 char *filename, /* filename which gets the mark */
393 int lineno, /* line number which gets the mark */
394 int markId, /* unique mark identifier */
395 int idx) /* which mark to use */
396{
397 char cbuf[BUFSIZ]; /* command buffer */
398
399 /* Set mark in a given file */
400#ifdef WSDEBUG_TRACE
401 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
402 wstrace("workshop_set_mark(%s, %d (ln), %d (id), %d (idx))\n",
403 filename, lineno, markId, idx);
404#endif
405
Bram Moolenaar051b7822005-05-19 21:00:46 +0000406 vim_snprintf(cbuf, sizeof(cbuf), "sign place %d line=%d name=%d file=%s",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000407 markId, lineno, idx, filename);
408 coloncmd(cbuf, TRUE);
409}
410
411 void
412workshop_change_mark_type(
413 char *filename, /* filename which gets the mark */
414 int markId, /* unique mark identifier */
415 int idx) /* which mark to use */
416{
417 char cbuf[BUFSIZ]; /* command buffer */
418
419 /* Change mark type */
420#ifdef WSDEBUG_TRACE
421 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
422 wstrace("workshop_change_mark_type(%s, %d, %d)\n",
423 filename, markId, idx);
424#endif
425
Bram Moolenaar051b7822005-05-19 21:00:46 +0000426 vim_snprintf(cbuf, sizeof(cbuf),
427 "sign place %d name=%d file=%s", markId, idx, filename);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000428 coloncmd(cbuf, TRUE);
429}
430
431/*
432 * Goto the given mark in a file (e.g. show it).
433 * If message is not null, display it in the footer.
434 */
435 void
436workshop_goto_mark(
437 char *filename,
438 int markId,
439 char *message)
440{
441 char cbuf[BUFSIZ]; /* command buffer */
442
443 /* Goto mark */
444#ifdef WSDEBUG_TRACE
445 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
446 wstrace("workshop_goto_mark(%s, %d (id), %s)\n",
447 filename, markId, message && *message &&
448 !(*message == ' ' && message[1] == NULL) ?
449 message : "<None>");
450#endif
451
Bram Moolenaar051b7822005-05-19 21:00:46 +0000452 vim_snprintf(cbuf, sizeof(cbuf), "sign jump %d file=%s", markId, filename);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000453 coloncmd(cbuf, TRUE);
454 if (message != NULL && *message != NUL)
455 gui_mch_set_footer((char_u *)message);
456}
457
458 void
459workshop_delete_mark(
460 char *filename,
461 int markId)
462{
463 char cbuf[BUFSIZ]; /* command buffer */
464
465 /* Delete mark */
466#ifdef WSDEBUG_TRACE
467 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
468 wstrace("workshop_delete_mark(%s, %d (id))\n",
469 filename, markId);
470#endif
471
Bram Moolenaar051b7822005-05-19 21:00:46 +0000472 vim_snprintf(cbuf, sizeof(cbuf),
473 "sign unplace %d file=%s", markId, filename);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000474 coloncmd(cbuf, TRUE);
475}
476
Bram Moolenaar071d4272004-06-13 20:20:40 +0000477 int
478workshop_get_mark_lineno(
479 char *filename,
480 int markId)
481{
482 buf_T *buf; /* buffer containing filename */
483 int lineno; /* line number of filename in buf */
484
485 /* Get mark line number */
486#ifdef WSDEBUG_TRACE
487 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
488 wstrace("workshop_get_mark_lineno(%s, %d)\n",
489 filename, markId);
490#endif
491
492 lineno = 0;
493 buf = buflist_findname((char_u *)filename);
494 if (buf != NULL)
495 lineno = buf_findsign(buf, markId);
496
497 return lineno;
498}
499
500
Bram Moolenaar071d4272004-06-13 20:20:40 +0000501/*
502 * Are there any moved marks? If so, call workshop_move_mark on
503 * each of them now. This is how eserve can find out if for example
504 * breakpoints have moved when a program has been recompiled and
505 * reloaded into dbx.
506 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000507 void
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000508workshop_moved_marks(char *filename UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000509{
510#ifdef WSDEBUG_TRACE
511 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
512 wstrace("XXXworkshop_moved_marks(%s)\n", filename);
513#endif
514}
515
516 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100517workshop_get_font_height(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000518{
519 XmFontList fontList; /* fontList made from gui.norm_font */
520 XmString str;
521 Dimension w;
522 Dimension h;
523
524#ifdef WSDEBUG_TRACE
525 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
526 wstrace("workshop_get_font_height()\n");
527#endif
528
529 /* Pick the proper signs for this font size */
530 fontList = gui_motif_create_fontlist((XFontStruct *)gui.norm_font);
531 h = 0;
532 if (fontList != NULL)
533 {
534 str = XmStringCreateLocalized("A");
535 XmStringExtent(fontList, str, &w, &h);
536 XmStringFree(str);
537 XmFontListFree(fontList);
538 }
539
540 return (int)h;
541}
542
Bram Moolenaar071d4272004-06-13 20:20:40 +0000543 void
544workshop_footer_message(
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000545 char *message,
546 int severity UNUSED) /* severity is currently unused */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000547{
548#ifdef WSDEBUG_TRACE
549 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
550 wstrace("workshop_footer_message(%s, %d)\n", message, severity);
551#endif
552
553 gui_mch_set_footer((char_u *) message);
554}
555
556/*
557 * workshop_menu_begin() is passed the menu name. We determine its mnemonic
558 * here and store its name and priority.
559 */
560 void
561workshop_menu_begin(
562 char *label)
563{
564 vimmenu_T *menu; /* pointer to last menu */
565 int menuPriority = 0; /* priority of new menu */
566 char mnembuf[64]; /* store menubar mnemonics here */
567 char *name; /* label with a mnemonic */
568 char *p; /* used to find mnemonics */
569 int idx; /* index into mnembuf */
570
571#ifdef WSDEBUG_TRACE
572 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
573 wstrace("workshop_menu_begin()\n");
574#endif
575
576 /*
577 * Look through all existing (non-PopUp and non-Toolbar) menus
578 * and gather their mnemonics. Use this list to decide what
579 * mnemonic should be used for label.
580 */
581
582 idx = 0;
583 mnembuf[idx++] = 'H'; /* H is mnemonic for Help */
584 for (menu = root_menu; menu != NULL; menu = menu->next)
585 {
586 if (menu_is_menubar(menu->name))
587 {
588 p = strchr((char *)menu->name, '&');
589 if (p != NULL)
590 mnembuf[idx++] = *++p;
591 }
592 if (menu->next != NULL
593 && strcmp((char *) menu->next->dname, "Help") == 0)
594 {
595 menuPriority = menu->priority + 10;
596 break;
597 }
598 }
599 mnembuf[idx++] = NUL;
600 name = addUniqueMnemonic(mnembuf, label);
601
Bram Moolenaar051b7822005-05-19 21:00:46 +0000602 vim_snprintf(curMenuName, sizeof(curMenuName), "%s", name);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000603 sprintf(curMenuPriority, "%d.0", menuPriority);
604}
605
606/*
607 * Append the name and priority to strings to be used in vim menu commands.
608 */
609 void
610workshop_submenu_begin(
611 char *label)
612{
613#ifdef WSDEBUG_TRACE
614 if (ws_debug && ws_dlevel & WS_TRACE
615 && strncmp(curMenuName, "ToolBar", 7) != 0)
616 wstrace("workshop_submenu_begin(%s)\n", label);
617#endif
618
619 strcat(curMenuName, ".");
620 strcat(curMenuName, fixup(label));
621
622 updatePriority(True);
623}
624
625/*
626 * Remove the submenu name and priority from curMenu*.
627 */
628
629 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100630workshop_submenu_end(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631{
632 char *p;
633
634#ifdef WSDEBUG_TRACE
635 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)
636 && strncmp(curMenuName, "ToolBar", 7) != 0)
637 wstrace("workshop_submenu_end()\n");
638#endif
639
640 p = strrchr(curMenuPriority, '.');
641 ASSERT(p != NULL);
642 *p = NUL;
643
644 p = strrchr(curMenuName, '.');
645 ASSERT(p != NULL);
646 *p = NUL;
647}
648
649/*
650 * This is where menus are really made. Each item will generate an amenu vim
651 * command. The globals curMenuName and curMenuPriority contain the name and
652 * priority of the parent menu tree.
653 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654 void
655workshop_menu_item(
656 char *label,
657 char *verb,
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000658 char *accelerator UNUSED,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000659 char *acceleratorText,
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000660 char *name UNUSED,
661 char *filepos UNUSED,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000662 char *sensitive)
663{
664 char cbuf[BUFSIZ];
665 char namebuf[BUFSIZ];
666 char accText[BUFSIZ];
667
668#ifdef WSDEBUG_TRACE
669 if (WSDLEVEL(WS_TRACE_VERBOSE)
670 && strncmp(curMenuName, "ToolBar", 7) != 0)
671 {
672 if (ws_dlevel & WS_TRACE_VERBOSE)
673 wsdebug("workshop_menu_item(\n"
674 "\tlabel = \"%s\",\n"
675 "\tverb = %s,\n"
676 "\taccelerator = %s,\n"
677 "\tacceleratorText = \"%s\",\n"
678 "\tname = %s,\n"
679 "\tfilepos = %s,\n"
680 "\tsensitive = %s)\n",
681 label && *label ? label : "<None>",
682 verb && *verb ? verb : "<None>",
683 accelerator && *accelerator ?
684 accelerator : "<None>",
685 acceleratorText && *acceleratorText ?
686 acceleratorText : "<None>",
687 name && *name ? name : "<None>",
688 filepos && *filepos ? filepos : "<None>",
689 sensitive);
690 else if (ws_dlevel & WS_TRACE)
691 wstrace("workshop_menu_item(\"%s\", %s)\n",
692 label && *label ? label : "<None>",
693 verb && *verb ? verb : "<None>", sensitive);
694 }
695#endif
696#ifdef WSDEBUG_SENSE
697 if (ws_debug)
698 wstrace("menu: %-21.20s%-21.20s(%s)\n", label, verb,
699 *sensitive == '1' ? "Sensitive" : "Insensitive");
700#endif
701
702 if (acceleratorText != NULL)
Bram Moolenaar051b7822005-05-19 21:00:46 +0000703 vim_snprintf(accText, sizeof(accText), "<Tab>%s", acceleratorText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704 else
705 accText[0] = NUL;
706 updatePriority(False);
Bram Moolenaar051b7822005-05-19 21:00:46 +0000707 vim_snprintf(namebuf, sizeof(namebuf), "%s.%s", curMenuName, fixup(label));
708 vim_snprintf(cbuf, sizeof(cbuf), "amenu %s %s%s\t:wsverb %s<CR>",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000709 curMenuPriority, namebuf, accText, verb);
710
711 coloncmd(cbuf, TRUE);
712 addMenu(namebuf, fixAccelText(acceleratorText), verb);
713
714 if (*sensitive == '0')
715 {
Bram Moolenaar051b7822005-05-19 21:00:46 +0000716 vim_snprintf(cbuf, sizeof(cbuf), "amenu disable %s", namebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000717 coloncmd(cbuf, TRUE);
718 }
719}
720
721/*
722 * This function is called when a complete WorkShop menu description has been
723 * sent over from eserve. We do some menu cleanup.
724 */
725
726 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100727workshop_menu_end(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000728{
729 Boolean using_tearoff; /* set per current option setting */
730
731#ifdef WSDEBUG_TRACE
732 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
733 wstrace("workshop_menu_end()\n");
734#endif
735
736 using_tearoff = vim_strchr(p_go, GO_TEAROFF) != NULL;
737 gui_mch_toggle_tearoffs(using_tearoff);
738}
739
740 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100741workshop_toolbar_begin(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742{
743#ifdef WSDEBUG_TRACE
744 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
745 wstrace("workshop_toolbar_begin()\n");
746#endif
747
748 coloncmd("aunmenu ToolBar", True);
749 tbpri = 10;
750}
751
752 void
Bram Moolenaarb638a7b2016-01-30 21:29:58 +0100753workshop_toolbar_end(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000754{
755 char_u buf[64];
756
757#ifdef WSDEBUG_TRACE
758 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
759 {
760 wstrace("workshop_toolbar_end()\n");
761 }
762#endif
763
764 /*
765 * Turn on ToolBar.
766 */
767 STRCPY(buf, p_go);
768 if (vim_strchr(p_go, 'T') == NULL)
769 {
770 STRCAT(buf, "T");
771 set_option_value((char_u *)"go", 0L, buf, 0);
772 }
773 workshopInitDone = True;
774}
775
Bram Moolenaar071d4272004-06-13 20:20:40 +0000776 void
777workshop_toolbar_button(
778 char *label,
779 char *verb,
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000780 char *senseVerb UNUSED,
781 char *filepos UNUSED,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782 char *help,
783 char *sense,
784 char *file,
785 char *left)
786{
787 char cbuf[BUFSIZ + MAXPATHLEN];
788 char namebuf[BUFSIZ];
789 static int tbid = 1;
790 char_u *p;
791
792#ifdef WSDEBUG_TRACE
793 if (WSDLEVEL(WS_TRACE_VERBOSE))
794 wsdebug("workshop_toolbar_button(\"%s\", %s, %s,\n"
795 "\t%s, \"%s\", %s,\n\t\"%s\",\n\t<%s>)\n",
796 label && *label ? label : "<None>",
797 verb && *verb ? verb : "<None>",
798 senseVerb && *senseVerb ? senseVerb : "<None>",
799 filepos && *filepos ? filepos : "<None>",
800 help && *help ? help : "<None>",
801 sense && *sense ? sense : "<None>",
802 file && *file ? file : "<None>",
803 left && *left ? left : "<None>");
804 else if (WSDLEVEL(WS_TRACE))
805 wstrace("workshop_toolbar_button(\"%s\", %s)\n",
806 label && *label ? label : "<None>",
807 verb && *verb ? verb : "<None>");
808#endif
809#ifdef WSDEBUG_SENSE
810 if (ws_debug)
811 wsdebug("button: %-21.20s%-21.20s(%s)\n", label, verb,
812 *sense == '1' ? "Sensitive" : "Insensitive");
813#endif
814
815 if (left && *left && atoi(left) > 0)
816 {
817 /* Add a separator (but pass the width passed after the ':') */
818 sprintf(cbuf, "amenu 1.%d ToolBar.-sep%d:%s- <nul>",
819 tbpri - 5, tbid++, left);
820
821 coloncmd(cbuf, True);
822 }
823
824 p = vim_strsave_escaped((char_u *)label, (char_u *)"\\. ");
Bram Moolenaar051b7822005-05-19 21:00:46 +0000825 vim_snprintf(namebuf, sizeof(namebuf), "ToolBar.%s", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 vim_free(p);
827 STRCPY(cbuf, "amenu <silent> ");
828 if (file != NULL && *file != NUL)
829 {
830 p = vim_strsave_escaped((char_u *)file, (char_u *)" ");
Bram Moolenaara800b422010-06-27 01:15:55 +0200831 vim_snprintf_add(cbuf, sizeof(cbuf), "icon=%s ", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832 vim_free(p);
833 }
Bram Moolenaara800b422010-06-27 01:15:55 +0200834 vim_snprintf_add(cbuf, sizeof(cbuf),"1.%d %s :wsverb %s<CR>",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000835 tbpri, namebuf, verb);
836
837 /* Define the menu item */
838 coloncmd(cbuf, True);
839
840 if (*sense == '0')
841 {
842 /* If menu isn't sensitive at startup... */
Bram Moolenaar051b7822005-05-19 21:00:46 +0000843 vim_snprintf(cbuf, sizeof(cbuf), "amenu disable %s", namebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844 coloncmd(cbuf, True);
845 }
846
847 if (help && *help)
848 {
849 /* Do the tooltip */
Bram Moolenaar051b7822005-05-19 21:00:46 +0000850 vim_snprintf(cbuf, sizeof(cbuf), "tmenu %s %s", namebuf, help);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851 coloncmd(cbuf, True);
852 }
853
854 addMenu(namebuf, NULL, verb);
855 tbpri += 10;
856}
857
858 void
859workshop_frame_sensitivities(
860 VerbSense *vs) /* list of verbs to (de)sensitize */
861{
862 VerbSense *vp; /* iterate through vs */
863 char *menu_name; /* used in menu lookup */
864 int cnt; /* count of verbs to skip */
865 int len; /* length of nonvariant part of command */
866 char cbuf[4096];
867
868#ifdef WSDEBUG_TRACE
869 if (WSDLEVEL(WS_TRACE_VERBOSE) || WSDLEVEL(4))
870 {
871 wsdebug("workshop_frame_sensitivities(\n");
872 for (vp = vs; vp->verb != NULL; vp++)
873 wsdebug("\t%-25s%d\n", vp->verb, vp->sense);
874 wsdebug(")\n");
875 }
876 else if (WSDLEVEL(WS_TRACE))
877 wstrace("workshop_frame_sensitivities()\n");
878#endif
879#ifdef WSDEBUG_SENSE
880 if (ws_debug)
881 for (vp = vs; vp->verb != NULL; vp++)
882 wsdebug("change: %-21.20s%-21.20s(%s)\n",
883 "", vp->verb, vp->sense == 1 ?
884 "Sensitive" : "Insensitive");
885#endif
886
887 /*
888 * Look for all matching menu entries for the verb. There may be more
889 * than one if the verb has both a menu and toolbar entry.
890 */
891 for (vp = vs; vp->verb != NULL; vp++)
892 {
893 cnt = 0;
894 strcpy(cbuf, "amenu");
895 strcat(cbuf, " ");
896 strcat(cbuf, vp->sense ? "enable" : "disable");
897 strcat(cbuf, " ");
898 len = strlen(cbuf);
899 while ((menu_name = lookupVerb(vp->verb, cnt++)) != NULL)
900 {
901 strcpy(&cbuf[len], menu_name);
902 coloncmd(cbuf, FALSE);
903 }
904 }
905 gui_update_menus(0);
906 gui_mch_flush();
907}
908
909 void
910workshop_set_option(
911 char *option, /* name of a supported option */
912 char *value) /* value to set option to */
913{
914 char cbuf[BUFSIZ]; /* command buffer */
915
916#ifdef WSDEBUG_TRACE
917 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
918 {
919 wstrace("workshop_set_option(%s, %s)\n", option, value);
920 }
921#endif
922
923 cbuf[0] = NUL;
924 switch (*option) /* switch on 1st letter */
925 {
926 case 's':
927 if (strcmp(option, "syntax") == 0)
Bram Moolenaar051b7822005-05-19 21:00:46 +0000928 vim_snprintf(cbuf, sizeof(cbuf), "syntax %s", value);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000929 else if (strcmp(option, "savefiles") == 0)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000930 {
931 /* XXX - Not yet implemented */
932 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000933 break;
934
935 case 'l':
936 if (strcmp(option, "lineno") == 0)
937 sprintf(cbuf, "set %snu",
938 (strcmp(value, "on") == 0) ? "" : "no");
939 break;
940
941 case 'p':
942 if (strcmp(option, "parentheses") == 0)
943 sprintf(cbuf, "set %ssm",
944 (strcmp(value, "on") == 0) ? "" : "no");
945 break;
946
947 case 'w':
948 /* this option is set by a direct call */
949#ifdef WSDEBUG
950 wsdebug("workshop_set_option: "
951 "Got unexpected workshopkeys option");
952#endif
953 break;
954
955 case 'b': /* these options are set from direct calls */
956 if (option[7] == NUL && strcmp(option, "balloon") == 0)
957 {
958#ifdef WSDEBUG
959 /* set by direct call to workshop_balloon_mode */
960 wsdebug("workshop_set_option: "
961 "Got unexpected ballooneval option");
962#endif
963 }
964 else if (strcmp(option, "balloondelay") == 0)
965 {
966#ifdef WSDEBUG
967 /* set by direct call to workshop_balloon_delay */
968 wsdebug("workshop_set_option: "
969 "Got unexpected balloondelay option");
970#endif
971 }
972 break;
973 }
974 if (cbuf[0] != NUL)
975 coloncmd(cbuf, TRUE);
976}
977
978
979 void
980workshop_balloon_mode(
981 Boolean on)
982{
983 char cbuf[BUFSIZ]; /* command buffer */
984
985#ifdef WSDEBUG_TRACE
986 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
987 wstrace("workshop_balloon_mode(%s)\n", on ? "True" : "False");
988#endif
989
990 sprintf(cbuf, "set %sbeval", on ? "" : "no");
991 coloncmd(cbuf, TRUE);
992}
993
994
995 void
996workshop_balloon_delay(
997 int delay)
998{
999 char cbuf[BUFSIZ]; /* command buffer */
1000
1001#ifdef WSDEBUG_TRACE
1002 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
1003 wstrace("workshop_balloon_delay(%d)\n", delay);
1004#endif
1005
1006 sprintf(cbuf, "set bdlay=%d", delay);
1007 coloncmd(cbuf, TRUE);
1008}
1009
1010
1011 void
1012workshop_show_balloon_tip(
1013 char *tip)
1014{
1015#ifdef WSDEBUG_TRACE
1016 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
1017 wstrace("workshop_show_balloon_tip(%s)\n", tip);
1018#endif
1019
1020 if (balloonEval != NULL)
1021 gui_mch_post_balloon(balloonEval, (char_u *)tip);
1022}
1023
1024
1025 void
1026workshop_hotkeys(
1027 Boolean on)
1028{
1029 char cbuf[BUFSIZ]; /* command buffer */
1030 MenuMap *mp; /* iterate over menuMap entries */
1031
1032#ifdef WSDEBUG_TRACE
1033 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
1034 wstrace("workshop_hotkeys(%s)\n", on ? "True" : "False");
1035#endif
1036
1037 workshopHotKeysEnabled = on;
1038 if (workshopHotKeysEnabled)
1039 for (mp = menuMap; mp < &menuMap[menuMapSize]; mp++)
1040 {
1041 if (mp->accel != NULL)
1042 {
Bram Moolenaar051b7822005-05-19 21:00:46 +00001043 vim_snprintf(cbuf, sizeof(cbuf),
1044 "map %s :wsverb %s<CR>", mp->accel, mp->verb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001045 coloncmd(cbuf, TRUE);
1046 }
1047 }
1048 else
1049 for (mp = menuMap; mp < &menuMap[menuMapSize]; mp++)
1050 {
1051 if (mp->accel != NULL)
1052 {
Bram Moolenaar051b7822005-05-19 21:00:46 +00001053 vim_snprintf(cbuf, sizeof(cbuf), "unmap %s", mp->accel);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001054 coloncmd(cbuf, TRUE);
1055 }
1056 }
1057}
1058
1059/*
1060 * A button in the toolbar has been pushed.
1061 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001062 int
1063workshop_get_positions(
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001064 void *clientData UNUSED,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001065 char **filename, /* output data */
1066 int *curLine, /* output data */
1067 int *curCol, /* output data */
1068 int *selStartLine, /* output data */
1069 int *selStartCol, /* output data */
1070 int *selEndLine, /* output data */
1071 int *selEndCol, /* output data */
1072 int *selLength, /* output data */
1073 char **selection) /* output data */
1074{
1075 static char ffname[MAXPATHLEN];
1076
1077#ifdef WSDEBUG_TRACE
1078 if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE))
1079 wstrace("workshop_get_positions(%#x, \"%s\", ...)\n",
1080 clientData, (curbuf && curbuf->b_sfname != NULL)
1081 ? (char *)curbuf->b_sfname : "<None>");
1082#endif
1083
Bram Moolenaara40b4662008-11-28 10:47:47 +00001084 if (curbuf->b_ffname == NULL)
1085 ffname[0] = NUL;
1086 else
1087 /* copy so nobody can change b_ffname */
1088 strcpy(ffname, (char *) curbuf->b_ffname);
1089 *filename = ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001090 *curLine = curwin->w_cursor.lnum;
1091 *curCol = curwin->w_cursor.col;
1092
Bram Moolenaara23ccb82006-02-27 00:08:02 +00001093 if (curbuf->b_visual.vi_mode == 'v' &&
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01001094 EQUAL_POS(curwin->w_cursor, curbuf->b_visual.vi_end))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001095 {
Bram Moolenaara23ccb82006-02-27 00:08:02 +00001096 *selStartLine = curbuf->b_visual.vi_start.lnum;
1097 *selStartCol = curbuf->b_visual.vi_start.col;
1098 *selEndLine = curbuf->b_visual.vi_end.lnum;
1099 *selEndCol = curbuf->b_visual.vi_end.col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001100 *selection = get_selection(curbuf);
1101 if (*selection)
1102 *selLength = strlen(*selection);
1103 else
1104 *selLength = 0;
1105 }
1106 else
1107 {
1108 *selStartLine = *selEndLine = -1;
1109 *selStartCol = *selEndCol = -1;
1110 *selLength = 0;
1111 *selection = "";
1112 }
1113
1114 return True;
1115}
1116
1117
1118
1119/************************************************************************
1120 * Utility functions
1121 ************************************************************************/
1122
1123 static char *
1124get_selection(
1125 buf_T *buf) /* buffer whose selection we want */
1126{
1127 pos_T *start; /* start of the selection */
1128 pos_T *end; /* end of the selection */
1129 char *lp; /* pointer to actual line data */
1130 int llen; /* length of actual line data */
1131 char *sp; /* pointer to selection buffer */
1132 int slen; /* string length in selection buffer */
1133 int size; /* size of selection buffer */
1134 char *new_sp; /* temp pointer to new sp */
1135 int lnum; /* line number we are appending */
1136
Bram Moolenaara23ccb82006-02-27 00:08:02 +00001137 if (buf->b_visual.vi_mode == 'v')
Bram Moolenaar071d4272004-06-13 20:20:40 +00001138 {
Bram Moolenaara23ccb82006-02-27 00:08:02 +00001139 start = &buf->b_visual.vi_start;
1140 end = &buf->b_visual.vi_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001141 if (start->lnum == end->lnum)
1142 {
1143 /* selection is all on one line */
1144 lp = (char *) ml_get_pos(start);
1145 llen = end->col - start->col + 1;
1146 sp = (char *) malloc(llen + 1);
1147 if (sp != NULL)
1148 {
1149 strncpy(sp, lp, llen);
1150 sp[llen] = NUL;
1151 }
1152 }
1153 else
1154 {
1155 /* multi-line selection */
1156 lp = (char *) ml_get_pos(start);
1157 llen = strlen(lp);
1158 sp = (char *) malloc(BUFSIZ + llen);
1159 if (sp != NULL)
1160 {
1161 size = BUFSIZ + llen;
1162 strcpy(sp, lp);
1163 sp[llen] = '\n';
1164 slen = llen + 1;
1165
1166 lnum = start->lnum + 1;
1167 while (lnum < end->lnum)
1168 sp = append_selection(lnum++, sp, &size, &slen);
1169
1170 lp = (char *) ml_get(end->lnum);
1171 llen = end->col + 1;
1172 if ((slen + llen) >= size)
1173 {
1174 new_sp = (char *)
1175 realloc(sp, slen + llen + 1);
1176 if (new_sp != NULL)
1177 {
1178 size += llen + 1;
1179 sp = new_sp;
1180 }
1181 }
1182 if ((slen + llen) < size)
1183 {
1184 strncpy(&sp[slen], lp, llen);
1185 sp[slen + llen] = NUL;
1186 }
1187
1188 }
1189 }
1190 }
1191 else
1192 sp = NULL;
1193
1194 return sp;
1195}
1196
1197 static char *
1198append_selection(
1199 int lnum, /* line number to append */
1200 char *sp, /* pointer to selection buffer */
1201 int *size, /* ptr to size of sp */
1202 int *slen) /* ptr to length of selection string */
1203{
1204 char *lp; /* line of data from buffer */
1205 int llen; /* strlen of lp */
1206 char *new_sp; /* temp pointer to new sp */
1207
1208 lp = (char *)ml_get((linenr_T)lnum);
1209 llen = strlen(lp);
1210
1211 if ((*slen + llen) <= *size)
1212 {
1213 new_sp = (char *) realloc((void *) sp, BUFSIZ + *slen + llen);
1214 if (*new_sp != NUL)
1215 {
1216 *size = BUFSIZ + *slen + llen;
1217 sp = new_sp;
1218 }
1219 }
1220 if ((*slen + llen) > *size)
1221 {
1222 strcat(&sp[*slen], lp);
1223 *slen += llen;
1224 sp[*slen++] = '\n';
1225 }
1226
1227 return sp;
1228}
1229
1230
1231
1232 static void
1233load_buffer_by_name(
1234 char *filename, /* the file to load */
1235 int lnum) /* an optional line number (or 0) */
1236{
1237 char lnumbuf[16]; /* make line number option for :e */
1238 char cbuf[BUFSIZ]; /* command buffer */
1239
1240 if (lnum > 0)
1241 sprintf(lnumbuf, "+%d", lnum);
1242 else
1243 lnumbuf[0] = NUL;
1244
Bram Moolenaar051b7822005-05-19 21:00:46 +00001245 vim_snprintf(cbuf, sizeof(cbuf), "e %s %s", lnumbuf, filename);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001246 coloncmd(cbuf, False);
1247}
1248
1249
1250 static void
1251load_window(
1252 char *filename, /* filename to load */
1253 int lnum) /* linenumber to go to */
1254{
1255 buf_T *buf; /* buffer filename is stored in */
1256 win_T *win; /* window filenme is displayed in */
1257
1258 /*
1259 * Make sure filename is displayed and is the current window.
1260 */
1261
1262 buf = buflist_findname((char_u *)filename);
1263 if (buf == NULL || (win = get_window(buf)) == NULL)
1264 {
1265 /* No buffer or buffer is not in current window */
1266 /* wsdebug("load_window: load_buffer_by_name(\"%s\", %d)\n",
1267 filename, lnum); */
1268 load_buffer_by_name(filename, lnum);
1269 }
1270 else
1271 {
1272 /* buf is in a window */
1273 if (win != curwin)
1274 {
1275 win_enter(win, False);
Bram Moolenaara8ffcbb2010-06-21 06:15:46 +02001276 /* wsdebug("load_window: window enter %s\n",
Bram Moolenaar071d4272004-06-13 20:20:40 +00001277 win->w_buffer->b_sfname); */
1278 }
1279 if (lnum > 0 && win->w_cursor.lnum != lnum)
1280 {
1281 warp_to_pc(lnum);
1282 /* wsdebug("load_window: warp to %s[%d]\n",
1283 win->w_buffer->b_sfname, lnum); */
1284 }
1285 }
1286 out_flush();
1287}
1288
1289
1290
1291 static void
1292warp_to_pc(
1293 int lnum) /* line number to warp to */
1294{
Bram Moolenaar720c7102007-05-10 18:07:50 +00001295 char lbuf[256]; /* build line command here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001296
1297 if (lnum > 0)
1298 {
1299 if (State & INSERT)
1300 add_to_input_buf((char_u *) "\033", 1);
1301 if (isShowing(lnum))
1302 sprintf(lbuf, "%dG", lnum);
1303 else
1304 sprintf(lbuf, "%dz.", lnum);
1305 add_to_input_buf((char_u *) lbuf, strlen(lbuf));
1306 }
1307}
1308
1309 static Boolean
1310isShowing(
1311 int lnum) /* tell if line number is showing */
1312{
1313 return lnum >= curwin->w_topline && lnum < curwin->w_botline;
1314}
1315
1316
1317
1318 static win_T *
1319get_window(
1320 buf_T *buf) /* buffer to find window for */
1321{
1322 win_T *wp = NULL; /* window filename is in */
1323
Bram Moolenaar29323592016-07-24 22:04:11 +02001324 FOR_ALL_WINDOWS(wp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001325 if (buf == wp->w_buffer)
1326 break;
1327 return wp;
1328}
1329
1330
Bram Moolenaar071d4272004-06-13 20:20:40 +00001331 static void
1332updatePriority(
1333 Boolean subMenu) /* if True then start new submenu pri */
1334{
1335 int pri; /* priority of this menu/item */
1336 char *p;
1337
1338 p = strrchr(curMenuPriority, '.');
1339 ASSERT(p != NULL);
1340 *p++ = NUL;
1341
1342 pri = atoi(p) + 10; /* our new priority */
1343
1344 if (subMenu)
Bram Moolenaar051b7822005-05-19 21:00:46 +00001345 vim_snprintf(curMenuPriority, sizeof(curMenuPriority),
1346 "%s.%d.0", curMenuPriority, pri);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001347 else
Bram Moolenaar051b7822005-05-19 21:00:46 +00001348 vim_snprintf(curMenuPriority, sizeof(curMenuPriority),
1349 "%s.%d", curMenuPriority, pri);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001350}
1351
1352 static char *
1353addUniqueMnemonic(
1354 char *mnemonics, /* currently used mnemonics */
1355 char *label) /* label of menu needing mnemonic */
1356{
1357 static char name[BUFSIZ]; /* buffer for the updated name */
1358 char *p; /* pointer into label */
1359 char *found; /* pointer to possible mnemonic */
1360
1361 found = NULL;
1362 for (p = label; *p != NUL; p++)
1363 if (strchr(mnemonics, *p) == 0)
1364 if (found == NULL || (isupper((int)*p) && islower((int)*found)))
1365 found = p;
1366
1367 if (found != NULL)
1368 {
1369 strncpy(name, label, (found - label));
1370 strcat(name, "&");
1371 strcat(name, found);
1372 }
1373 else
1374 strcpy(name, label);
1375
1376 return name;
1377}
1378
1379/*
1380 * Some characters in a menu name must be escaped in vim. Since this is vim
1381 * specific, it must be done on this side.
1382 */
1383 static char *
1384fixup(
1385 char *label)
1386{
1387 static char buf[BUFSIZ];
1388 char *bp; /* pointer into buf */
1389 char *lp; /* pointer into label */
1390
1391 lp = label;
1392 bp = buf;
1393 while (*lp != NUL)
1394 {
1395 if (*lp == ' ' || *lp == '.')
1396 *bp++ = '\\';
1397 *bp++ = *lp++;
1398 }
1399 *bp = NUL;
1400
1401 return buf;
1402}
1403
1404
1405#ifdef NOHANDS_SUPPORT_FUNCTIONS
1406
1407/* For the NoHands test suite */
1408
1409 char *
Bram Moolenaarb638a7b2016-01-30 21:29:58 +01001410workshop_test_getcurrentfile(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001411{
1412 char *filename, *selection;
1413 int curLine, curCol, selStartLine, selStartCol, selEndLine;
1414 int selEndCol, selLength;
1415
1416 if (workshop_get_positions(
1417 NULL, &filename, &curLine, &curCol, &selStartLine,
1418 &selStartCol, &selEndLine, &selEndCol, &selLength,
1419 &selection))
1420 return filename;
1421 else
1422 return NULL;
1423}
1424
1425 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +01001426workshop_test_getcursorrow(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001427{
1428 return 0;
1429}
1430
1431 int
Bram Moolenaarb638a7b2016-01-30 21:29:58 +01001432workshop_test_getcursorcol(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001433{
1434 char *filename, *selection;
1435 int curLine, curCol, selStartLine, selStartCol, selEndLine;
1436 int selEndCol, selLength;
1437
1438 if (workshop_get_positions(
1439 NULL, &filename, &curLine, &curCol, &selStartLine,
1440 &selStartCol, &selEndLine, &selEndCol, &selLength,
1441 &selection))
1442 return curCol;
1443 else
1444 return -1;
1445}
1446
1447 char *
Bram Moolenaarb638a7b2016-01-30 21:29:58 +01001448workshop_test_getcursorrowtext(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001449{
1450 return NULL;
1451}
1452
1453 char *
Bram Moolenaarb638a7b2016-01-30 21:29:58 +01001454workshop_test_getselectedtext(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001455{
1456 char *filename, *selection;
1457 int curLine, curCol, selStartLine, selStartCol, selEndLine;
1458 int selEndCol, selLength;
1459
1460 if (workshop_get_positions(
1461 NULL, &filename, &curLine, &curCol, &selStartLine,
1462 &selStartCol, &selEndLine, &selEndCol, &selLength,
1463 &selection))
1464 return selection;
1465 else
1466 return NULL;
1467}
1468
Bram Moolenaar071d4272004-06-13 20:20:40 +00001469 void
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001470workshop_save_sensitivity(char *filename UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001471{
1472}
1473
1474#endif
1475
1476 static char *
1477fixAccelText(
1478 char *ap) /* original acceleratorText */
1479{
1480 char buf[256]; /* build in temp buffer */
1481 char *shift; /* shift string of "" */
1482
1483 if (ap == NULL)
1484 return NULL;
1485
1486 /* If the accelerator is shifted use the vim form */
1487 if (strncmp("Shift+", ap, 6) == 0)
1488 {
1489 shift = "S-";
1490 ap += 6;
1491 }
1492 else
1493 shift = "";
1494
1495 if (*ap == 'F' && atoi(&ap[1]) > 0)
1496 {
Bram Moolenaar051b7822005-05-19 21:00:46 +00001497 vim_snprintf(buf, sizeof(buf), "<%s%s>", shift, ap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001498 return strdup(buf);
1499 }
1500 else
1501 return NULL;
1502}
1503
Bram Moolenaarc3719bd2017-11-18 22:13:31 +01001504#ifdef FEAT_BEVAL_GUI
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00001505 void
1506workshop_beval_cb(
Bram Moolenaar071d4272004-06-13 20:20:40 +00001507 BalloonEval *beval,
1508 int state)
1509{
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00001510 win_T *wp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001511 char_u *text;
1512 int type;
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00001513 linenr_T lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001514 int col;
1515 int idx;
1516 char buf[MAXPATHLEN * 2];
1517 static int serialNo = -1;
1518
1519 if (!p_beval)
1520 return;
1521
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00001522 if (get_beval_info(beval, FALSE, &wp, &lnum, &text, &col) == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001523 {
1524 if (text && text[0])
1525 {
1526 /* Send debugger request */
1527 if (strlen((char *) text) > (MAXPATHLEN/2))
1528 {
1529 /*
1530 * The user has probably selected the entire
1531 * buffer or something like that - don't attempt
1532 * to evaluate it
1533 */
1534 return;
1535 }
1536
1537 /*
1538 * WorkShop expects the col to be a character index, not
1539 * a column number. Compute the index from col. Also set
1540 * line to 0 because thats what dbx expects.
1541 */
Bram Moolenaar04958cb2018-06-23 19:23:02 +02001542#ifdef FEAT_VARTABS
1543 idx = computeIndex(col, text, beval->ts, beval->vts);
1544#else
Bram Moolenaar32d19c12018-09-13 17:26:54 +02001545 idx = computeIndex(col, text, beval->ts, 0);
Bram Moolenaar04958cb2018-06-23 19:23:02 +02001546#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001547 if (idx > 0)
1548 {
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00001549 lnum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001550
1551 /*
1552 * If successful, it will respond with a balloon cmd.
1553 */
1554 if (state & ControlMask)
1555 /* Evaluate *(expression) */
1556 type = (int)GPLineEval_INDIRECT;
1557 else if (state & ShiftMask)
1558 /* Evaluate type(expression) */
1559 type = (int)GPLineEval_TYPE;
1560 else
1561 /* Evaluate value(expression) */
1562 type = (int)GPLineEval_EVALUATE;
1563
1564 /* Send request to dbx */
Bram Moolenaar051b7822005-05-19 21:00:46 +00001565 vim_snprintf(buf, sizeof(buf), "toolVerb debug.balloonEval "
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00001566 "%s %ld,0 %d,0 %d,%d %ld %s\n",
1567 (char *)wp->w_buffer->b_ffname,
1568 (long)lnum, idx, type, serialNo++,
1569 (long)strlen((char *)text), (char *)text);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001570 balloonEval = beval;
1571 workshop_send_message(buf);
1572 }
1573 }
1574 }
1575}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001576
1577 static int
1578computeIndex(
1579 int wantedCol,
1580 char_u *line,
Bram Moolenaar32d19c12018-09-13 17:26:54 +02001581 int ts,
1582 int *vts UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001583{
1584 int col = 0;
1585 int idx = 0;
1586
1587 while (line[idx])
1588 {
1589 if (line[idx] == '\t')
Bram Moolenaar04958cb2018-06-23 19:23:02 +02001590#ifdef FEAT_VARTABS
1591 col += tabstop_padding(col, ts, vts);
1592#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001593 col += ts - (col % ts);
Bram Moolenaar04958cb2018-06-23 19:23:02 +02001594#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001595 else
1596 col++;
1597 idx++;
1598 if (col >= wantedCol)
1599 return idx;
1600 }
1601
1602 return -1;
1603}
Bram Moolenaarba07ce32010-01-06 18:25:34 +01001604#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001605
1606 static void
1607addMenu(
1608 char *menu, /* menu name */
1609 char *accel, /* accelerator text (optional) */
1610 char *verb) /* WorkShop action-verb */
1611{
1612 MenuMap *newMap;
1613 char cbuf[BUFSIZ];
1614
1615 if (menuMapSize >= menuMapMax)
1616 {
1617 newMap = realloc(menuMap,
1618 sizeof(MenuMap) * (menuMapMax + MENU_INC));
1619 if (newMap != NULL)
1620 {
1621 menuMap = newMap;
1622 menuMapMax += MENU_INC;
1623 }
1624 }
1625 if (menuMapSize < menuMapMax)
1626 {
1627 menuMap[menuMapSize].name = strdup(menu);
1628 menuMap[menuMapSize].accel = accel && *accel ? strdup(accel) : NULL;
1629 menuMap[menuMapSize++].verb = strdup(verb);
1630 if (accel && workshopHotKeysEnabled)
1631 {
Bram Moolenaar051b7822005-05-19 21:00:46 +00001632 vim_snprintf(cbuf, sizeof(cbuf),
1633 "map %s :wsverb %s<CR>", accel, verb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001634 coloncmd(cbuf, TRUE);
1635 }
1636 }
1637}
1638
1639 static char *
1640nameStrip(
1641 char *raw) /* menu name, possibly with & chars */
1642{
1643 static char buf[BUFSIZ]; /* build stripped name here */
1644 char *bp = buf;
1645
1646 while (*raw)
1647 {
1648 if (*raw != '&')
1649 *bp++ = *raw;
1650 raw++;
1651 }
1652 *bp = NUL;
1653 return buf;
1654}
1655
1656
1657 static char *
1658lookupVerb(
1659 char *verb,
1660 int skip) /* number of matches to skip */
1661{
1662 int i; /* loop iterator */
1663
1664 for (i = 0; i < menuMapSize; i++)
1665 if (strcmp(menuMap[i].verb, verb) == 0 && skip-- == 0)
1666 return nameStrip(menuMap[i].name);
1667
1668 return NULL;
1669}
1670
1671
1672 static void
1673coloncmd(
1674 char *cmd, /* the command to print */
1675 Boolean force) /* force cursor update */
1676{
1677 char_u *cpo_save = p_cpo;
1678
1679#ifdef WSDEBUG
1680 if (WSDLEVEL(WS_TRACE_COLONCMD))
1681 wsdebug("Cmd: %s\n", cmd);
1682#endif
1683
1684 p_cpo = empty_option;
1685
1686 ALT_INPUT_LOCK_ON;
1687 do_cmdline_cmd((char_u *)cmd);
1688 ALT_INPUT_LOCK_OFF;
1689
1690 p_cpo = cpo_save;
1691
1692 if (force)
1693 gui_update_screen();
1694}
1695
1696/*
1697 * setDollarVim - Given the run directory, search for the vim install
1698 * directory and set $VIM.
1699 *
1700 * We can be running out of SUNWspro/bin or out of
1701 * SUNWspro/contrib/contrib6/vim5.6/bin so we check
1702 * relative to both of these directories.
1703 */
1704 static void
1705setDollarVim(
1706 char *rundir)
1707{
1708 char buf[MAXPATHLEN];
1709 char *cp;
1710
1711 /*
1712 * First case: Running from <install-dir>/SUNWspro/bin
1713 */
1714 strcpy(buf, rundir);
1715 strcat(buf, "/../contrib/contrib6/vim" VIM_VERSION_SHORT "/share/vim/"
1716 VIM_VERSION_NODOT "/syntax/syntax.vim");
1717 if (access(buf, R_OK) == 0)
1718 {
1719 strcpy(buf, "SPRO_WSDIR=");
1720 strcat(buf, rundir);
1721 cp = strrchr(buf, '/');
1722 if (cp != NULL)
1723 strcpy(cp, "/WS6U2");
1724 putenv(strdup(buf));
1725
1726 strcpy(buf, "VIM=");
1727 strcat(buf, rundir);
1728 strcat(buf, "/../contrib/contrib6/vim" VIM_VERSION_SHORT "/share/vim/"
1729 VIM_VERSION_NODOT);
1730 putenv(strdup(buf));
1731 return;
1732 }
1733
1734 /*
1735 * Second case: Probably running from
1736 * <install-dir>/SUNWspro/contrib/contrib6/vim5.6/bin
1737 */
1738 strcpy(buf, rundir);
1739 strcat(buf, "/../../../contrib/contrib6/vim" VIM_VERSION_SHORT
1740 "/share/vim/" VIM_VERSION_NODOT "/syntax/syntax.vim");
1741 if (access(buf, R_OK) == 0)
1742 {
1743 strcpy(buf, "SPRO_WSDIR=");
1744 strcat(buf, rundir);
1745 cp = strrchr(buf, '/');
1746 if (cp != NULL)
1747 strcpy(cp, "../../../../WS6U2");
1748 putenv(strdup(buf));
1749
1750 strcpy(buf, "VIM=");
1751 strcat(buf, rundir);
1752 strcat(buf, "/../../../contrib/contrib6/vim" VIM_VERSION_SHORT
1753 "/share/vim/" VIM_VERSION_NODOT);
1754 putenv(strdup(buf));
1755 return;
1756 }
1757}
1758
1759/*
1760 * findYourself - Find the directory we are running from. This is used to
1761 * set $VIM. We need to set this because users can install
1762 * the package in a different directory than the compiled
1763 * directory. This is a Sun Visual WorkShop requirement!
1764 *
1765 * Note: We override a user's $VIM because it won't have the
Bram Moolenaar9af41842016-09-25 21:45:05 +02001766 * WorkShop specific files. S/he may not like this but it's
Bram Moolenaar071d4272004-06-13 20:20:40 +00001767 * better than getting the wrong files (especially as the
1768 * user is likely to have $VIM set to 5.4 or later).
1769 */
1770 void
1771findYourself(
1772 char *argv0)
1773{
1774 char *runpath = NULL;
1775 char *path;
1776 char *pathbuf;
1777
1778 if (*argv0 == '/')
1779 runpath = strdup(argv0);
1780 else if (*argv0 == '.' || strchr(argv0, '/'))
1781 {
1782 runpath = (char *) malloc(MAXPATHLEN);
Bram Moolenaar860cae12010-06-05 23:22:07 +02001783 if (getcwd(runpath, MAXPATHLEN) == NULL)
1784 runpath[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001785 strcat(runpath, "/");
1786 strcat(runpath, argv0);
1787 }
1788 else
1789 {
1790 path = getenv("PATH");
1791 if (path != NULL)
1792 {
1793 runpath = (char *) malloc(MAXPATHLEN);
1794 pathbuf = strdup(path);
1795 path = strtok(pathbuf, ":");
1796 do
1797 {
1798 strcpy(runpath, path);
1799 strcat(runpath, "/");
1800 strcat(runpath, argv0);
1801 if (access(runpath, X_OK) == 0)
1802 break;
1803 } while ((path = strtok(NULL, ":")) != NULL);
1804 free(pathbuf);
1805 }
1806 }
1807
1808 if (runpath != NULL)
1809 {
1810 char runbuf[MAXPATHLEN];
1811
1812 /*
1813 * We found the run directory. Now find the install dir.
1814 */
1815 (void)vim_FullName((char_u *)runpath, (char_u *)runbuf, MAXPATHLEN, 1);
1816 path = strrchr(runbuf, '/');
1817 if (path != NULL)
1818 *path = NUL; /* remove the vim/gvim name */
1819 path = strrchr(runbuf, '/');
1820 if (path != NULL)
1821 {
1822 if (strncmp(path, "/bin", 4) == 0)
1823 setDollarVim(runbuf);
1824 else if (strncmp(path, "/src", 4) == 0)
1825 {
1826 *path = NUL; /* development tree */
1827 setDollarVim(runbuf);
1828 }
1829 }
1830 free(runpath);
1831 }
1832}