diff options
Diffstat (limited to 'src/workshop.c')
-rw-r--r-- | src/workshop.c | 1885 |
1 files changed, 1885 insertions, 0 deletions
diff --git a/src/workshop.c b/src/workshop.c new file mode 100644 index 000000000..10f4ea796 --- /dev/null +++ b/src/workshop.c @@ -0,0 +1,1885 @@ +/* vi:set ts=8 sts=4 sw=4: + * + * VIM - Vi IMproved by Bram Moolenaar + * Visual Workshop integration by Gordon Prieur + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +#ifdef HAVE_CONFIG_H +# include "auto/config.h" +#endif +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <fcntl.h> +#include <netdb.h> +#include <netinet/in.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#ifdef HAVE_LIBGEN_H +# include <libgen.h> +#endif +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include <X11/Intrinsic.h> +#include <Xm/Xm.h> +#include <Xm/PushB.h> + +#include "integration.h" /* <EditPlugin/integration.h> */ + +#include "vim.h" +#include "version.h" +#include "gui_beval.h" +#include "workshop.h" + +void workshop_hotkeys(Boolean); + +static Boolean isShowing(int); +static win_T *get_window(buf_T *); +#if 0 +static int get_buffer_number(buf_T *); +#endif +static void updatePriority(Boolean); +static char *addUniqueMnemonic(char *, char *); +static char *fixup(char *); +static char *get_selection(buf_T *); +static char *append_selection(int, char *, int *, int *); +static void load_buffer_by_name(char *, int); +#if 0 +static void load_buffer_by_number(int, int); +#endif +static void load_window(char *, int lnum); +static void warp_to_pc(int); +#ifdef FEAT_BEVAL +static void bevalCB(BalloonEval *, int); +#endif +static char *fixAccelText(char *); +static void addMenu(char *, char *, char *); +static char *lookupVerb(char *, int); +static int computeIndex(int, char_u *, int); +static void coloncmd(char *, Boolean); + +extern Widget vimShell; +extern Widget textArea; +extern XtAppContext app_context; + +static int tbpri; /* ToolBar priority */ +int usingSunWorkShop = 0; /* set if -ws flag is used */ +char curMenuName[BUFSIZ]; +char curMenuPriority[BUFSIZ]; +BalloonEval *balloonEval; + +static Boolean workshopInitDone = False; +static Boolean workshopHotKeysEnabled = False; + +/* + * The following enum is from <gp_dbx/gp_dbx_common.h>. We can't include it + * here because its C++. + */ +enum +{ + GPLineEval_EVALUATE, /* evaluate expression */ + GPLineEval_INDIRECT, /* evaluate *<expression> */ + GPLineEval_TYPE /* type of expression */ +}; + +/* + * Store each verb in the MenuMap. This lets us map from a verb to a menu. + * There may be multiple matches for a single verb in this table. + */ +#define MENU_INC 50 /* menuMap incremental size increases */ +typedef struct +{ + char *name; /* name of the menu */ + char *accel; /* optional accelerator key */ + char *verb; /* menu verb */ +} MenuMap; +static MenuMap *menuMap; /* list of verb/menu mappings */ +static int menuMapSize; /* current size of menuMap */ +static int menuMapMax; /* allocated size of menuMap */ +static char *initialFileCmd; /* save command but defer doing it */ + + + void +workshop_init() +{ + char_u buf[64]; + int is_dirty = FALSE; + int width, height; + XtInputMask mask; + + /* + * Turn on MenuBar, ToolBar, and Footer. + */ + STRCPY(buf, p_go); + if (vim_strchr(p_go, GO_MENUS) == NULL) + { + STRCAT(buf, "m"); + is_dirty = TRUE; + } + if (vim_strchr(p_go, GO_TOOLBAR) == NULL) + { + STRCAT(buf, "T"); + is_dirty = TRUE; + } + if (vim_strchr(p_go, GO_FOOTER) == NULL) + { + STRCAT(buf, "F"); + is_dirty = TRUE; + } + if (is_dirty) + set_option_value((char_u *)"go", 0L, buf, 0); + + /* + * Set size from workshop_get_width_height(). + */ + width = height = 0; + if (workshop_get_width_height(&width, &height)) + { + XtVaSetValues(vimShell, + XmNwidth, width, + XmNheight, height, + NULL); + } + + /* + * Now read in the initial messages from eserve. + */ + while ((mask = XtAppPending(app_context)) + && (mask & XtIMAlternateInput) && !workshopInitDone) + XtAppProcessEvent(app_context, (XtInputMask)XtIMAlternateInput); +} + + void +workshop_postinit() +{ + do_cmdline_cmd((char_u *)initialFileCmd); + ALT_INPUT_LOCK_OFF; + free(initialFileCmd); + initialFileCmd = NULL; +} + + void +ex_wsverb(exarg_T *eap) +{ + msg_clr_cmdline(); + workshop_perform_verb((char *) eap->arg, NULL); +} + +/* + * Editor name + * This string is recognized by eserve and should be all lower case. + * This is how the editor detects that it is talking to gvim instead + * of NEdit, for example, when the connection is initiated from the editor. + */ + char * +workshop_get_editor_name() +{ + return "gvim"; +} + +/* + * Version number of the editor. + * This number is communicated along with the protocol + * version to the application. + */ + char * +workshop_get_editor_version() +{ + return Version; +} + +/* + * Answer functions: called by eserve + */ + +/* + * Name: + * workshop_load_file + * + * Function: + * Load a given file into the WorkShop buffer. + */ +/*ARGSUSED*/ + void +workshop_load_file( + char *filename, /* the file to load */ + int line, /* an optional line number (or 0) */ + char *frameid) /* used for multi-frame support */ +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_load_file(%s, %d)\n", filename, line); +#endif + +#ifdef FEAT_BEVAL + if (balloonEval == NULL) + { + /* + * Set up the Balloon Expression Evaluation area. + * It's enabled by default. Disable it when 'ballooneval' is off. + */ +# ifdef FEAT_GUI_GTK + balloonEval = gui_mch_create_beval_area(gui.drawarea, NULL, + &bevalCB, NULL); +# else + balloonEval = gui_mch_create_beval_area(textArea, NULL, bevalCB, NULL); +# endif + if (!p_beval) + gui_mch_disable_beval_area(balloonEval); + } +#endif + + load_window(filename, line); +} + +/* + * Reload the WorkShop buffer + */ + void +workshop_reload_file( + char *filename, + int line) +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_reload_file(%s, %d)\n", filename, line); +#endif + load_window(filename, line); +} + + void +workshop_show_file( + char *filename) +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_show_file(%s)\n", filename); +#endif + + load_window(filename, 0); +} + + void +workshop_goto_line( + char *filename, + int lineno) +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_goto_line(%s, %d)\n", filename, lineno); +#endif + + load_window(filename, lineno); +} + +/*ARGSUSED*/ + void +workshop_front_file( + char *filename) +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_front_file()\n"); +#endif + /* + * Assumption: This function will always be called after a call to + * workshop_show_file(), so the file is always showing. + */ + if (vimShell != NULL) + XRaiseWindow(gui.dpy, XtWindow(vimShell)); +} + + void +workshop_save_file( + char *filename) +{ + char cbuf[BUFSIZ]; /* build vim command here */ + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_save_file(%s)\n", filename); +#endif + + /* Save the given file */ + sprintf(cbuf, "w %s", filename); + coloncmd(cbuf, TRUE); +} + + void +workshop_save_files() +{ + /* Save the given file */ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_save_files()\n"); +#endif + + add_to_input_buf((char_u *) ":wall\n", 6); +} + + void +workshop_quit() +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_quit()\n"); +#endif + + add_to_input_buf((char_u *) ":qall\n", 6); +} + + void +workshop_minimize() +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_minimize()\n"); +#endif + workshop_minimize_shell(vimShell); +} + void +workshop_maximize() +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_maximize()\n"); +#endif + + workshop_maximize_shell(vimShell); +} + + void +workshop_add_mark_type( + int idx, + char *colorspec, + char *sign) +{ + char gbuf[BUFSIZ]; /* buffer for sign name */ + char cibuf[BUFSIZ]; /* color information */ + char cbuf[BUFSIZ]; /* command buffer */ + char *bp; + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + { + char *cp; + + cp = strrchr(sign, '/'); + if (cp == NULL) + cp = sign; + else + cp++; /* skip '/' character */ + wstrace("workshop_add_mark_type(%d, \"%s\", \"%s\")\n", idx, + colorspec && *colorspec ? colorspec : "<None>", cp); + } +#endif + + /* + * Isolate the basename of sign in gbuf. We will use this for the + * GroupName in the highlight command sent to vim. + */ + STRCPY(gbuf, gettail((char_u *)sign)); + bp = strrchr(gbuf, '.'); + if (bp != NULL) + *bp = NUL; + + if (gbuf[0] != '-' && gbuf[1] != NUL) + { + if (colorspec != NULL && *colorspec) + { + sprintf(cbuf, "highlight WS%s guibg=%s", gbuf, colorspec); + coloncmd(cbuf, FALSE); + sprintf(cibuf, "linehl=WS%s", gbuf); + } + else + cibuf[0] = NUL; + + sprintf(cbuf, "sign define %d %s icon=%s", idx, cibuf, sign); + coloncmd(cbuf, TRUE); + } +} + + void +workshop_set_mark( + char *filename, /* filename which gets the mark */ + int lineno, /* line number which gets the mark */ + int markId, /* unique mark identifier */ + int idx) /* which mark to use */ +{ + char cbuf[BUFSIZ]; /* command buffer */ + + /* Set mark in a given file */ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_set_mark(%s, %d (ln), %d (id), %d (idx))\n", + filename, lineno, markId, idx); +#endif + + sprintf(cbuf, "sign place %d line=%d name=%d file=%s", + markId, lineno, idx, filename); + coloncmd(cbuf, TRUE); +} + + void +workshop_change_mark_type( + char *filename, /* filename which gets the mark */ + int markId, /* unique mark identifier */ + int idx) /* which mark to use */ +{ + char cbuf[BUFSIZ]; /* command buffer */ + + /* Change mark type */ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_change_mark_type(%s, %d, %d)\n", + filename, markId, idx); +#endif + + sprintf(cbuf, "sign place %d name=%d file=%s", markId, idx, filename); + coloncmd(cbuf, TRUE); +} + +/* + * Goto the given mark in a file (e.g. show it). + * If message is not null, display it in the footer. + */ + void +workshop_goto_mark( + char *filename, + int markId, + char *message) +{ + char cbuf[BUFSIZ]; /* command buffer */ + + /* Goto mark */ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_goto_mark(%s, %d (id), %s)\n", + filename, markId, message && *message && + !(*message == ' ' && message[1] == NULL) ? + message : "<None>"); +#endif + + sprintf(cbuf, "sign jump %d file=%s", markId, filename); + coloncmd(cbuf, TRUE); + if (message != NULL && *message != NUL) + gui_mch_set_footer((char_u *)message); +} + + void +workshop_delete_mark( + char *filename, + int markId) +{ + char cbuf[BUFSIZ]; /* command buffer */ + + /* Delete mark */ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_delete_mark(%s, %d (id))\n", + filename, markId); +#endif + + sprintf(cbuf, "sign unplace %d file=%s", markId, filename); + coloncmd(cbuf, TRUE); +} + +#if 0 /* not used */ + void +workshop_delete_all_marks( + void *window, + Boolean doRefresh) +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_delete_all_marks(%#x, %s)\n", + window, doRefresh ? "True" : "False"); +#endif + + coloncmd("sign unplace *", TRUE); +} +#endif + + int +workshop_get_mark_lineno( + char *filename, + int markId) +{ + buf_T *buf; /* buffer containing filename */ + int lineno; /* line number of filename in buf */ + + /* Get mark line number */ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_get_mark_lineno(%s, %d)\n", + filename, markId); +#endif + + lineno = 0; + buf = buflist_findname((char_u *)filename); + if (buf != NULL) + lineno = buf_findsign(buf, markId); + + return lineno; +} + + +#if 0 /* not used */ + void +workshop_adjust_marks(Widget *window, int pos, + int inserted, int deleted) +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("XXXworkshop_adjust_marks(%s, %d, %d, %d)\n", + window ? XtName(window) : "<None>", pos, inserted, deleted); +#endif +} +#endif + +/* + * Are there any moved marks? If so, call workshop_move_mark on + * each of them now. This is how eserve can find out if for example + * breakpoints have moved when a program has been recompiled and + * reloaded into dbx. + */ +/*ARGSUSED*/ + void +workshop_moved_marks(char *filename) +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("XXXworkshop_moved_marks(%s)\n", filename); +#endif +} + + int +workshop_get_font_height() +{ + XmFontList fontList; /* fontList made from gui.norm_font */ + XmString str; + Dimension w; + Dimension h; + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_get_font_height()\n"); +#endif + + /* Pick the proper signs for this font size */ + fontList = gui_motif_create_fontlist((XFontStruct *)gui.norm_font); + h = 0; + if (fontList != NULL) + { + str = XmStringCreateLocalized("A"); + XmStringExtent(fontList, str, &w, &h); + XmStringFree(str); + XmFontListFree(fontList); + } + + return (int)h; +} + +/*ARGSUSED*/ + void +workshop_footer_message( + char *message, + int severity) /* severity is currently unused */ +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_footer_message(%s, %d)\n", message, severity); +#endif + + gui_mch_set_footer((char_u *) message); +} + +/* + * workshop_menu_begin() is passed the menu name. We determine its mnemonic + * here and store its name and priority. + */ + void +workshop_menu_begin( + char *label) +{ + vimmenu_T *menu; /* pointer to last menu */ + int menuPriority = 0; /* priority of new menu */ + char mnembuf[64]; /* store menubar mnemonics here */ + char *name; /* label with a mnemonic */ + char *p; /* used to find mnemonics */ + int idx; /* index into mnembuf */ + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_menu_begin()\n"); +#endif + + /* + * Look through all existing (non-PopUp and non-Toolbar) menus + * and gather their mnemonics. Use this list to decide what + * mnemonic should be used for label. + */ + + idx = 0; + mnembuf[idx++] = 'H'; /* H is mnemonic for Help */ + for (menu = root_menu; menu != NULL; menu = menu->next) + { + if (menu_is_menubar(menu->name)) + { + p = strchr((char *)menu->name, '&'); + if (p != NULL) + mnembuf[idx++] = *++p; + } + if (menu->next != NULL + && strcmp((char *) menu->next->dname, "Help") == 0) + { + menuPriority = menu->priority + 10; + break; + } + } + mnembuf[idx++] = NUL; + name = addUniqueMnemonic(mnembuf, label); + + sprintf(curMenuName, "%s", name); + sprintf(curMenuPriority, "%d.0", menuPriority); +} + +/* + * Append the name and priority to strings to be used in vim menu commands. + */ + void +workshop_submenu_begin( + char *label) +{ +#ifdef WSDEBUG_TRACE + if (ws_debug && ws_dlevel & WS_TRACE + && strncmp(curMenuName, "ToolBar", 7) != 0) + wstrace("workshop_submenu_begin(%s)\n", label); +#endif + + strcat(curMenuName, "."); + strcat(curMenuName, fixup(label)); + + updatePriority(True); +} + +/* + * Remove the submenu name and priority from curMenu*. + */ + + void +workshop_submenu_end() +{ + char *p; + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE) + && strncmp(curMenuName, "ToolBar", 7) != 0) + wstrace("workshop_submenu_end()\n"); +#endif + + p = strrchr(curMenuPriority, '.'); + ASSERT(p != NULL); + *p = NUL; + + p = strrchr(curMenuName, '.'); + ASSERT(p != NULL); + *p = NUL; +} + +/* + * This is where menus are really made. Each item will generate an amenu vim + * command. The globals curMenuName and curMenuPriority contain the name and + * priority of the parent menu tree. + */ +/*ARGSUSED*/ + void +workshop_menu_item( + char *label, + char *verb, + char *accelerator, + char *acceleratorText, + char *name, + char *filepos, + char *sensitive) +{ + char cbuf[BUFSIZ]; + char namebuf[BUFSIZ]; + char accText[BUFSIZ]; + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE) + && strncmp(curMenuName, "ToolBar", 7) != 0) + { + if (ws_dlevel & WS_TRACE_VERBOSE) + wsdebug("workshop_menu_item(\n" + "\tlabel = \"%s\",\n" + "\tverb = %s,\n" + "\taccelerator = %s,\n" + "\tacceleratorText = \"%s\",\n" + "\tname = %s,\n" + "\tfilepos = %s,\n" + "\tsensitive = %s)\n", + label && *label ? label : "<None>", + verb && *verb ? verb : "<None>", + accelerator && *accelerator ? + accelerator : "<None>", + acceleratorText && *acceleratorText ? + acceleratorText : "<None>", + name && *name ? name : "<None>", + filepos && *filepos ? filepos : "<None>", + sensitive); + else if (ws_dlevel & WS_TRACE) + wstrace("workshop_menu_item(\"%s\", %s)\n", + label && *label ? label : "<None>", + verb && *verb ? verb : "<None>", sensitive); + } +#endif +#ifdef WSDEBUG_SENSE + if (ws_debug) + wstrace("menu: %-21.20s%-21.20s(%s)\n", label, verb, + *sensitive == '1' ? "Sensitive" : "Insensitive"); +#endif + + if (acceleratorText != NULL) + sprintf(accText, "<Tab>%s", acceleratorText); + else + accText[0] = NUL; + updatePriority(False); + sprintf(namebuf, "%s.%s", curMenuName, fixup(label)); + sprintf(cbuf, "amenu %s %s%s\t:wsverb %s<CR>", + curMenuPriority, namebuf, accText, verb); + + coloncmd(cbuf, TRUE); + addMenu(namebuf, fixAccelText(acceleratorText), verb); + + if (*sensitive == '0') + { + sprintf(cbuf, "amenu disable %s", namebuf); + coloncmd(cbuf, TRUE); + } +} + +/* + * This function is called when a complete WorkShop menu description has been + * sent over from eserve. We do some menu cleanup. + */ + + void +workshop_menu_end() +{ + Boolean using_tearoff; /* set per current option setting */ + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_menu_end()\n"); +#endif + + using_tearoff = vim_strchr(p_go, GO_TEAROFF) != NULL; + gui_mch_toggle_tearoffs(using_tearoff); +} + + void +workshop_toolbar_begin() +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_toolbar_begin()\n"); +#endif + + coloncmd("aunmenu ToolBar", True); + tbpri = 10; +} + + void +workshop_toolbar_end() +{ + char_u buf[64]; + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + { + wstrace("workshop_toolbar_end()\n"); + } +#endif + + /* + * Turn on ToolBar. + */ + STRCPY(buf, p_go); + if (vim_strchr(p_go, 'T') == NULL) + { + STRCAT(buf, "T"); + set_option_value((char_u *)"go", 0L, buf, 0); + } + workshopInitDone = True; +} + +/*ARGSUSED*/ + void +workshop_toolbar_button( + char *label, + char *verb, + char *senseVerb, + char *filepos, + char *help, + char *sense, + char *file, + char *left) +{ + char cbuf[BUFSIZ + MAXPATHLEN]; + char namebuf[BUFSIZ]; + static int tbid = 1; + char_u *p; + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE)) + wsdebug("workshop_toolbar_button(\"%s\", %s, %s,\n" + "\t%s, \"%s\", %s,\n\t\"%s\",\n\t<%s>)\n", + label && *label ? label : "<None>", + verb && *verb ? verb : "<None>", + senseVerb && *senseVerb ? senseVerb : "<None>", + filepos && *filepos ? filepos : "<None>", + help && *help ? help : "<None>", + sense && *sense ? sense : "<None>", + file && *file ? file : "<None>", + left && *left ? left : "<None>"); + else if (WSDLEVEL(WS_TRACE)) + wstrace("workshop_toolbar_button(\"%s\", %s)\n", + label && *label ? label : "<None>", + verb && *verb ? verb : "<None>"); +#endif +#ifdef WSDEBUG_SENSE + if (ws_debug) + wsdebug("button: %-21.20s%-21.20s(%s)\n", label, verb, + *sense == '1' ? "Sensitive" : "Insensitive"); +#endif + + if (left && *left && atoi(left) > 0) + { + /* Add a separator (but pass the width passed after the ':') */ + sprintf(cbuf, "amenu 1.%d ToolBar.-sep%d:%s- <nul>", + tbpri - 5, tbid++, left); + + coloncmd(cbuf, True); + } + + p = vim_strsave_escaped((char_u *)label, (char_u *)"\\. "); + sprintf(namebuf, "ToolBar.%s", p); + vim_free(p); + STRCPY(cbuf, "amenu <silent> "); + if (file != NULL && *file != NUL) + { + p = vim_strsave_escaped((char_u *)file, (char_u *)" "); + sprintf(cbuf + STRLEN(cbuf), "icon=%s ", p); + vim_free(p); + } + sprintf(cbuf + STRLEN(cbuf), "1.%d %s :wsverb %s<CR>", + tbpri, namebuf, verb); + + /* Define the menu item */ + coloncmd(cbuf, True); + + if (*sense == '0') + { + /* If menu isn't sensitive at startup... */ + sprintf(cbuf, "amenu disable %s", namebuf); + coloncmd(cbuf, True); + } + + if (help && *help) + { + /* Do the tooltip */ + sprintf(cbuf, "tmenu %s %s", namebuf, help); + coloncmd(cbuf, True); + } + + addMenu(namebuf, NULL, verb); + tbpri += 10; +} + + void +workshop_frame_sensitivities( + VerbSense *vs) /* list of verbs to (de)sensitize */ +{ + VerbSense *vp; /* iterate through vs */ + char *menu_name; /* used in menu lookup */ + int cnt; /* count of verbs to skip */ + int len; /* length of nonvariant part of command */ + char cbuf[4096]; + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE) || WSDLEVEL(4)) + { + wsdebug("workshop_frame_sensitivities(\n"); + for (vp = vs; vp->verb != NULL; vp++) + wsdebug("\t%-25s%d\n", vp->verb, vp->sense); + wsdebug(")\n"); + } + else if (WSDLEVEL(WS_TRACE)) + wstrace("workshop_frame_sensitivities()\n"); +#endif +#ifdef WSDEBUG_SENSE + if (ws_debug) + for (vp = vs; vp->verb != NULL; vp++) + wsdebug("change: %-21.20s%-21.20s(%s)\n", + "", vp->verb, vp->sense == 1 ? + "Sensitive" : "Insensitive"); +#endif + + /* + * Look for all matching menu entries for the verb. There may be more + * than one if the verb has both a menu and toolbar entry. + */ + for (vp = vs; vp->verb != NULL; vp++) + { + cnt = 0; + strcpy(cbuf, "amenu"); + strcat(cbuf, " "); + strcat(cbuf, vp->sense ? "enable" : "disable"); + strcat(cbuf, " "); + len = strlen(cbuf); + while ((menu_name = lookupVerb(vp->verb, cnt++)) != NULL) + { + strcpy(&cbuf[len], menu_name); + coloncmd(cbuf, FALSE); + } + } + gui_update_menus(0); + gui_mch_flush(); +} + + void +workshop_set_option( + char *option, /* name of a supported option */ + char *value) /* value to set option to */ +{ + char cbuf[BUFSIZ]; /* command buffer */ + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + { + wstrace("workshop_set_option(%s, %s)\n", option, value); + } +#endif + + cbuf[0] = NUL; + switch (*option) /* switch on 1st letter */ + { + case 's': + if (strcmp(option, "syntax") == 0) + sprintf(cbuf, "syntax %s", value); + else if (strcmp(option, "savefiles") == 0) + ; /* XXX - Not yet implemented */ + break; + + case 'l': + if (strcmp(option, "lineno") == 0) + sprintf(cbuf, "set %snu", + (strcmp(value, "on") == 0) ? "" : "no"); + break; + + case 'p': + if (strcmp(option, "parentheses") == 0) + sprintf(cbuf, "set %ssm", + (strcmp(value, "on") == 0) ? "" : "no"); + break; + + case 'w': + /* this option is set by a direct call */ +#ifdef WSDEBUG + wsdebug("workshop_set_option: " + "Got unexpected workshopkeys option"); +#endif + break; + + case 'b': /* these options are set from direct calls */ + if (option[7] == NUL && strcmp(option, "balloon") == 0) + { +#ifdef WSDEBUG + /* set by direct call to workshop_balloon_mode */ + wsdebug("workshop_set_option: " + "Got unexpected ballooneval option"); +#endif + } + else if (strcmp(option, "balloondelay") == 0) + { +#ifdef WSDEBUG + /* set by direct call to workshop_balloon_delay */ + wsdebug("workshop_set_option: " + "Got unexpected balloondelay option"); +#endif + } + break; + } + if (cbuf[0] != NUL) + coloncmd(cbuf, TRUE); +} + + + void +workshop_balloon_mode( + Boolean on) +{ + char cbuf[BUFSIZ]; /* command buffer */ + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_balloon_mode(%s)\n", on ? "True" : "False"); +#endif + + sprintf(cbuf, "set %sbeval", on ? "" : "no"); + coloncmd(cbuf, TRUE); +} + + + void +workshop_balloon_delay( + int delay) +{ + char cbuf[BUFSIZ]; /* command buffer */ + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_balloon_delay(%d)\n", delay); +#endif + + sprintf(cbuf, "set bdlay=%d", delay); + coloncmd(cbuf, TRUE); +} + + + void +workshop_show_balloon_tip( + char *tip) +{ +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_show_balloon_tip(%s)\n", tip); +#endif + + if (balloonEval != NULL) + gui_mch_post_balloon(balloonEval, (char_u *)tip); +} + + + void +workshop_hotkeys( + Boolean on) +{ + char cbuf[BUFSIZ]; /* command buffer */ + MenuMap *mp; /* iterate over menuMap entries */ + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_hotkeys(%s)\n", on ? "True" : "False"); +#endif + + workshopHotKeysEnabled = on; + if (workshopHotKeysEnabled) + for (mp = menuMap; mp < &menuMap[menuMapSize]; mp++) + { + if (mp->accel != NULL) + { + sprintf(cbuf, "map %s :wsverb %s<CR>", mp->accel, mp->verb); + coloncmd(cbuf, TRUE); + } + } + else + for (mp = menuMap; mp < &menuMap[menuMapSize]; mp++) + { + if (mp->accel != NULL) + { + sprintf(cbuf, "unmap %s", mp->accel); + coloncmd(cbuf, TRUE); + } + } +} + +/* + * A button in the toolbar has been pushed. + */ +/*ARGSUSED*/ + int +workshop_get_positions( + void *clientData, /* unused */ + char **filename, /* output data */ + int *curLine, /* output data */ + int *curCol, /* output data */ + int *selStartLine, /* output data */ + int *selStartCol, /* output data */ + int *selEndLine, /* output data */ + int *selEndCol, /* output data */ + int *selLength, /* output data */ + char **selection) /* output data */ +{ + static char ffname[MAXPATHLEN]; + +#ifdef WSDEBUG_TRACE + if (WSDLEVEL(WS_TRACE_VERBOSE | WS_TRACE)) + wstrace("workshop_get_positions(%#x, \"%s\", ...)\n", + clientData, (curbuf && curbuf->b_sfname != NULL) + ? (char *)curbuf->b_sfname : "<None>"); +#endif + + strcpy(ffname, (char *) curbuf->b_ffname); + *filename = ffname; /* copy so nobody can change b_ffname */ + *curLine = curwin->w_cursor.lnum; + *curCol = curwin->w_cursor.col; + + if (curbuf->b_visual_mode == 'v' && + equalpos(curwin->w_cursor, curbuf->b_visual_end)) + { + *selStartLine = curbuf->b_visual_start.lnum; + *selStartCol = curbuf->b_visual_start.col; + *selEndLine = curbuf->b_visual_end.lnum; + *selEndCol = curbuf->b_visual_end.col; + *selection = get_selection(curbuf); + if (*selection) + *selLength = strlen(*selection); + else + *selLength = 0; + } + else + { + *selStartLine = *selEndLine = -1; + *selStartCol = *selEndCol = -1; + *selLength = 0; + *selection = ""; + } + + return True; +} + + + +/************************************************************************ + * Utility functions + ************************************************************************/ + + static char * +get_selection( + buf_T *buf) /* buffer whose selection we want */ +{ + pos_T *start; /* start of the selection */ + pos_T *end; /* end of the selection */ + char *lp; /* pointer to actual line data */ + int llen; /* length of actual line data */ + char *sp; /* pointer to selection buffer */ + int slen; /* string length in selection buffer */ + int size; /* size of selection buffer */ + char *new_sp; /* temp pointer to new sp */ + int lnum; /* line number we are appending */ + + if (buf->b_visual_mode == 'v') + { + start = &buf->b_visual_start; + end = &buf->b_visual_end; + if (start->lnum == end->lnum) + { + /* selection is all on one line */ + lp = (char *) ml_get_pos(start); + llen = end->col - start->col + 1; + sp = (char *) malloc(llen + 1); + if (sp != NULL) + { + strncpy(sp, lp, llen); + sp[llen] = NUL; + } + } + else + { + /* multi-line selection */ + lp = (char *) ml_get_pos(start); + llen = strlen(lp); + sp = (char *) malloc(BUFSIZ + llen); + if (sp != NULL) + { + size = BUFSIZ + llen; + strcpy(sp, lp); + sp[llen] = '\n'; + slen = llen + 1; + + lnum = start->lnum + 1; + while (lnum < end->lnum) + sp = append_selection(lnum++, sp, &size, &slen); + + lp = (char *) ml_get(end->lnum); + llen = end->col + 1; + if ((slen + llen) >= size) + { + new_sp = (char *) + realloc(sp, slen + llen + 1); + if (new_sp != NULL) + { + size += llen + 1; + sp = new_sp; + } + } + if ((slen + llen) < size) + { + strncpy(&sp[slen], lp, llen); + sp[slen + llen] = NUL; + } + + } + } + } + else + sp = NULL; + + return sp; +} + + static char * +append_selection( + int lnum, /* line number to append */ + char *sp, /* pointer to selection buffer */ + int *size, /* ptr to size of sp */ + int *slen) /* ptr to length of selection string */ +{ + char *lp; /* line of data from buffer */ + int llen; /* strlen of lp */ + char *new_sp; /* temp pointer to new sp */ + + lp = (char *)ml_get((linenr_T)lnum); + llen = strlen(lp); + + if ((*slen + llen) <= *size) + { + new_sp = (char *) realloc((void *) sp, BUFSIZ + *slen + llen); + if (*new_sp != NUL) + { + *size = BUFSIZ + *slen + llen; + sp = new_sp; + } + } + if ((*slen + llen) > *size) + { + strcat(&sp[*slen], lp); + *slen += llen; + sp[*slen++] = '\n'; + } + + return sp; +} + + + + static void +load_buffer_by_name( + char *filename, /* the file to load */ + int lnum) /* an optional line number (or 0) */ +{ + char lnumbuf[16]; /* make line number option for :e */ + char cbuf[BUFSIZ]; /* command buffer */ + + if (lnum > 0) + sprintf(lnumbuf, "+%d", lnum); + else + lnumbuf[0] = NUL; + + sprintf(cbuf, "e %s %s", lnumbuf, filename); + coloncmd(cbuf, False); +} + + + static void +load_window( + char *filename, /* filename to load */ + int lnum) /* linenumber to go to */ +{ + buf_T *buf; /* buffer filename is stored in */ + win_T *win; /* window filenme is displayed in */ + + /* + * Make sure filename is displayed and is the current window. + */ + + buf = buflist_findname((char_u *)filename); + if (buf == NULL || (win = get_window(buf)) == NULL) + { + /* No buffer or buffer is not in current window */ + /* wsdebug("load_window: load_buffer_by_name(\"%s\", %d)\n", + filename, lnum); */ + load_buffer_by_name(filename, lnum); + } + else + { + /* buf is in a window */ + if (win != curwin) + { + win_enter(win, False); + /* wsdebug("load_window: window endter %s\n", + win->w_buffer->b_sfname); */ + } + if (lnum > 0 && win->w_cursor.lnum != lnum) + { + warp_to_pc(lnum); + /* wsdebug("load_window: warp to %s[%d]\n", + win->w_buffer->b_sfname, lnum); */ + } + } + out_flush(); +} + + + + static void +warp_to_pc( + int lnum) /* line number to warp to */ +{ + char lbuf[256]; /* build line comand here */ + + if (lnum > 0) + { + if (State & INSERT) + add_to_input_buf((char_u *) "\033", 1); + if (isShowing(lnum)) + sprintf(lbuf, "%dG", lnum); + else + sprintf(lbuf, "%dz.", lnum); + add_to_input_buf((char_u *) lbuf, strlen(lbuf)); + } +} + + static Boolean +isShowing( + int lnum) /* tell if line number is showing */ +{ + return lnum >= curwin->w_topline && lnum < curwin->w_botline; +} + + + + static win_T * +get_window( + buf_T *buf) /* buffer to find window for */ +{ + win_T *wp = NULL; /* window filename is in */ + + for (wp = firstwin; wp != NULL; wp = W_NEXT(wp)) + if (buf == wp->w_buffer) + break; + return wp; +} + + +#if 0 /* not used */ + static int +get_buffer_number( + buf_T *buf) /* buffer to get position of */ +{ + buf_T *bp; /* iterate over buffer list */ + int pos; /* the position in the buffer list */ + + pos = 1; + for (bp = firstbuf; bp != NULL; bp = bp->b_next) + { + if (bp == buf) + return pos; + pos++; + } + + return 1; +} +#endif + + static void +updatePriority( + Boolean subMenu) /* if True then start new submenu pri */ +{ + int pri; /* priority of this menu/item */ + char *p; + + p = strrchr(curMenuPriority, '.'); + ASSERT(p != NULL); + *p++ = NUL; + + pri = atoi(p) + 10; /* our new priority */ + + if (subMenu) + sprintf(curMenuPriority, "%s.%d.0", curMenuPriority, pri); + else + sprintf(curMenuPriority, "%s.%d", curMenuPriority, pri); +} + + static char * +addUniqueMnemonic( + char *mnemonics, /* currently used mnemonics */ + char *label) /* label of menu needing mnemonic */ +{ + static char name[BUFSIZ]; /* buffer for the updated name */ + char *p; /* pointer into label */ + char *found; /* pointer to possible mnemonic */ + + found = NULL; + for (p = label; *p != NUL; p++) + if (strchr(mnemonics, *p) == 0) + if (found == NULL || (isupper((int)*p) && islower((int)*found))) + found = p; + + if (found != NULL) + { + strncpy(name, label, (found - label)); + strcat(name, "&"); + strcat(name, found); + } + else + strcpy(name, label); + + return name; +} + +/* + * Some characters in a menu name must be escaped in vim. Since this is vim + * specific, it must be done on this side. + */ + static char * +fixup( + char *label) +{ + static char buf[BUFSIZ]; + char *bp; /* pointer into buf */ + char *lp; /* pointer into label */ + + lp = label; + bp = buf; + while (*lp != NUL) + { + if (*lp == ' ' || *lp == '.') + *bp++ = '\\'; + *bp++ = *lp++; + } + *bp = NUL; + + return buf; +} + + +#ifdef NOHANDS_SUPPORT_FUNCTIONS + +/* For the NoHands test suite */ + + char * +workshop_test_getcurrentfile() +{ + char *filename, *selection; + int curLine, curCol, selStartLine, selStartCol, selEndLine; + int selEndCol, selLength; + + if (workshop_get_positions( + NULL, &filename, &curLine, &curCol, &selStartLine, + &selStartCol, &selEndLine, &selEndCol, &selLength, + &selection)) + return filename; + else + return NULL; +} + + int +workshop_test_getcursorrow() +{ + return 0; +} + + int +workshop_test_getcursorcol() +{ + char *filename, *selection; + int curLine, curCol, selStartLine, selStartCol, selEndLine; + int selEndCol, selLength; + + if (workshop_get_positions( + NULL, &filename, &curLine, &curCol, &selStartLine, + &selStartCol, &selEndLine, &selEndCol, &selLength, + &selection)) + return curCol; + else + return -1; +} + + char * +workshop_test_getcursorrowtext() +{ + return NULL; +} + + char * +workshop_test_getselectedtext() +{ + char *filename, *selection; + int curLine, curCol, selStartLine, selStartCol, selEndLine; + int selEndCol, selLength; + + if (workshop_get_positions( + NULL, &filename, &curLine, &curCol, &selStartLine, + &selStartCol, &selEndLine, &selEndCol, &selLength, + &selection)) + return selection; + else + return NULL; +} + +/*ARGSUSED*/ + void +workshop_save_sensitivity(char *filename) +{ +} + +#endif + + static char * +fixAccelText( + char *ap) /* original acceleratorText */ +{ + char buf[256]; /* build in temp buffer */ + char *shift; /* shift string of "" */ + + if (ap == NULL) + return NULL; + + /* If the accelerator is shifted use the vim form */ + if (strncmp("Shift+", ap, 6) == 0) + { + shift = "S-"; + ap += 6; + } + else + shift = ""; + + if (*ap == 'F' && atoi(&ap[1]) > 0) + { + sprintf(buf, "<%s%s>", shift, ap); + return strdup(buf); + } + else + return NULL; +} + +#ifdef FEAT_BEVAL + static void +bevalCB( + BalloonEval *beval, + int state) +{ + char_u *filename; + char_u *text; + int type; + int line; + int col; + int idx; + char buf[MAXPATHLEN * 2]; + static int serialNo = -1; + + if (!p_beval) + return; + + if (gui_mch_get_beval_info(beval, &filename, &line, &text, &col) == OK) + { + if (text && text[0]) + { + /* Send debugger request */ + if (strlen((char *) text) > (MAXPATHLEN/2)) + { + /* + * The user has probably selected the entire + * buffer or something like that - don't attempt + * to evaluate it + */ + return; + } + + /* + * WorkShop expects the col to be a character index, not + * a column number. Compute the index from col. Also set + * line to 0 because thats what dbx expects. + */ + idx = computeIndex(col, text, beval->ts); + if (idx > 0) + { + line = 0; + + /* + * If successful, it will respond with a balloon cmd. + */ + if (state & ControlMask) + /* Evaluate *(expression) */ + type = (int)GPLineEval_INDIRECT; + else if (state & ShiftMask) + /* Evaluate type(expression) */ + type = (int)GPLineEval_TYPE; + else + /* Evaluate value(expression) */ + type = (int)GPLineEval_EVALUATE; + + /* Send request to dbx */ + sprintf(buf, "toolVerb debug.balloonEval " + "%s %d,0 %d,0 %d,%d %d %s\n", (char *) filename, + line, idx, type, serialNo++, + strlen((char *) text), (char *) text); + balloonEval = beval; + workshop_send_message(buf); + } + } + } +} +#endif + + + static int +computeIndex( + int wantedCol, + char_u *line, + int ts) +{ + int col = 0; + int idx = 0; + + while (line[idx]) + { + if (line[idx] == '\t') + col += ts - (col % ts); + else + col++; + idx++; + if (col >= wantedCol) + return idx; + } + + return -1; +} + + static void +addMenu( + char *menu, /* menu name */ + char *accel, /* accelerator text (optional) */ + char *verb) /* WorkShop action-verb */ +{ + MenuMap *newMap; + char cbuf[BUFSIZ]; + + if (menuMapSize >= menuMapMax) + { + newMap = realloc(menuMap, + sizeof(MenuMap) * (menuMapMax + MENU_INC)); + if (newMap != NULL) + { + menuMap = newMap; + menuMapMax += MENU_INC; + } + } + if (menuMapSize < menuMapMax) + { + menuMap[menuMapSize].name = strdup(menu); + menuMap[menuMapSize].accel = accel && *accel ? strdup(accel) : NULL; + menuMap[menuMapSize++].verb = strdup(verb); + if (accel && workshopHotKeysEnabled) + { + sprintf(cbuf, "map %s :wsverb %s<CR>", accel, verb); + coloncmd(cbuf, TRUE); + } + } +} + + static char * +nameStrip( + char *raw) /* menu name, possibly with & chars */ +{ + static char buf[BUFSIZ]; /* build stripped name here */ + char *bp = buf; + + while (*raw) + { + if (*raw != '&') + *bp++ = *raw; + raw++; + } + *bp = NUL; + return buf; +} + + + static char * +lookupVerb( + char *verb, + int skip) /* number of matches to skip */ +{ + int i; /* loop iterator */ + + for (i = 0; i < menuMapSize; i++) + if (strcmp(menuMap[i].verb, verb) == 0 && skip-- == 0) + return nameStrip(menuMap[i].name); + + return NULL; +} + + + static void +coloncmd( + char *cmd, /* the command to print */ + Boolean force) /* force cursor update */ +{ + char_u *cpo_save = p_cpo; + +#ifdef WSDEBUG + if (WSDLEVEL(WS_TRACE_COLONCMD)) + wsdebug("Cmd: %s\n", cmd); +#endif + + p_cpo = empty_option; + + ALT_INPUT_LOCK_ON; + do_cmdline_cmd((char_u *)cmd); + ALT_INPUT_LOCK_OFF; + + p_cpo = cpo_save; + + if (force) + gui_update_screen(); +} + +/* + * setDollarVim - Given the run directory, search for the vim install + * directory and set $VIM. + * + * We can be running out of SUNWspro/bin or out of + * SUNWspro/contrib/contrib6/vim5.6/bin so we check + * relative to both of these directories. + */ + static void +setDollarVim( + char *rundir) +{ + char buf[MAXPATHLEN]; + char *cp; + + /* + * First case: Running from <install-dir>/SUNWspro/bin + */ + strcpy(buf, rundir); + strcat(buf, "/../contrib/contrib6/vim" VIM_VERSION_SHORT "/share/vim/" + VIM_VERSION_NODOT "/syntax/syntax.vim"); + if (access(buf, R_OK) == 0) + { + strcpy(buf, "SPRO_WSDIR="); + strcat(buf, rundir); + cp = strrchr(buf, '/'); + if (cp != NULL) + strcpy(cp, "/WS6U2"); + putenv(strdup(buf)); + + strcpy(buf, "VIM="); + strcat(buf, rundir); + strcat(buf, "/../contrib/contrib6/vim" VIM_VERSION_SHORT "/share/vim/" + VIM_VERSION_NODOT); + putenv(strdup(buf)); + return; + } + + /* + * Second case: Probably running from + * <install-dir>/SUNWspro/contrib/contrib6/vim5.6/bin + */ + strcpy(buf, rundir); + strcat(buf, "/../../../contrib/contrib6/vim" VIM_VERSION_SHORT + "/share/vim/" VIM_VERSION_NODOT "/syntax/syntax.vim"); + if (access(buf, R_OK) == 0) + { + strcpy(buf, "SPRO_WSDIR="); + strcat(buf, rundir); + cp = strrchr(buf, '/'); + if (cp != NULL) + strcpy(cp, "../../../../WS6U2"); + putenv(strdup(buf)); + + strcpy(buf, "VIM="); + strcat(buf, rundir); + strcat(buf, "/../../../contrib/contrib6/vim" VIM_VERSION_SHORT + "/share/vim/" VIM_VERSION_NODOT); + putenv(strdup(buf)); + return; + } +} + +/* + * findYourself - Find the directory we are running from. This is used to + * set $VIM. We need to set this because users can install + * the package in a different directory than the compiled + * directory. This is a Sun Visual WorkShop requirement! + * + * Note: We override a user's $VIM because it won't have the + * WorkShop specific files. S/he may not like this but its + * better than getting the wrong files (especially as the + * user is likely to have $VIM set to 5.4 or later). + */ + void +findYourself( + char *argv0) +{ + char *runpath = NULL; + char *path; + char *pathbuf; + + if (*argv0 == '/') + runpath = strdup(argv0); + else if (*argv0 == '.' || strchr(argv0, '/')) + { + runpath = (char *) malloc(MAXPATHLEN); + getcwd(runpath, MAXPATHLEN); + strcat(runpath, "/"); + strcat(runpath, argv0); + } + else + { + path = getenv("PATH"); + if (path != NULL) + { + runpath = (char *) malloc(MAXPATHLEN); + pathbuf = strdup(path); + path = strtok(pathbuf, ":"); + do + { + strcpy(runpath, path); + strcat(runpath, "/"); + strcat(runpath, argv0); + if (access(runpath, X_OK) == 0) + break; + } while ((path = strtok(NULL, ":")) != NULL); + free(pathbuf); + } + } + + if (runpath != NULL) + { + char runbuf[MAXPATHLEN]; + + /* + * We found the run directory. Now find the install dir. + */ + (void)vim_FullName((char_u *)runpath, (char_u *)runbuf, MAXPATHLEN, 1); + path = strrchr(runbuf, '/'); + if (path != NULL) + *path = NUL; /* remove the vim/gvim name */ + path = strrchr(runbuf, '/'); + if (path != NULL) + { + if (strncmp(path, "/bin", 4) == 0) + setDollarVim(runbuf); + else if (strncmp(path, "/src", 4) == 0) + { + *path = NUL; /* development tree */ + setDollarVim(runbuf); + } + } + free(runpath); + } +} |