Mercurial > vim
view src/workshop.c @ 5899:60cdaa05a6ad v7.4.292
updated for version 7.4.292
Problem: Searching for "a" does not match accented "a" with new regexp
engine, does match with old engine. (David B?rgin)
"ca" does not match "ca" with accented "a" with either engine.
Solution: Change the old engine, check for following composing character
also for single-byte patterns.
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Tue, 13 May 2014 18:04:00 +0200 |
parents | bfade53bcafb |
children | 33ba2adb6065 |
line wrap: on
line source
/* 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 <sys/types.h> #include <netdb.h> #include <netinet/in.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 *); 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); static void load_window(char *, int lnum); static void warp_to_pc(int); #ifdef FEAT_BEVAL void workshop_beval_cb(BalloonEval *, int); static int computeIndex(int, char_u *, int); #endif static char *fixAccelText(char *); static void addMenu(char *, char *, char *); static char *lookupVerb(char *, 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]; 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. */ void workshop_load_file( char *filename, /* the file to load */ int line, /* an optional line number (or 0) */ char *frameid UNUSED) /* 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 bevalServers |= BEVAL_WORKSHOP; #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); } void workshop_front_file( char *filename UNUSED) { #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 */ vim_snprintf(cbuf, sizeof(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) { vim_snprintf(cbuf, sizeof(cbuf), "highlight WS%s guibg=%s", gbuf, colorspec); coloncmd(cbuf, FALSE); vim_snprintf(cibuf, sizeof(cibuf), "linehl=WS%s", gbuf); } else cibuf[0] = NUL; vim_snprintf(cbuf, sizeof(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 vim_snprintf(cbuf, sizeof(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 vim_snprintf(cbuf, sizeof(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 vim_snprintf(cbuf, sizeof(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 vim_snprintf(cbuf, sizeof(cbuf), "sign unplace %d file=%s", markId, filename); coloncmd(cbuf, TRUE); } 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; } /* * 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. */ void workshop_moved_marks(char *filename UNUSED) { #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; } void workshop_footer_message( char *message, int severity UNUSED) /* 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); vim_snprintf(curMenuName, sizeof(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. */ void workshop_menu_item( char *label, char *verb, char *accelerator UNUSED, char *acceleratorText, char *name UNUSED, char *filepos UNUSED, 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) vim_snprintf(accText, sizeof(accText), "<Tab>%s", acceleratorText); else accText[0] = NUL; updatePriority(False); vim_snprintf(namebuf, sizeof(namebuf), "%s.%s", curMenuName, fixup(label)); vim_snprintf(cbuf, sizeof(cbuf), "amenu %s %s%s\t:wsverb %s<CR>", curMenuPriority, namebuf, accText, verb); coloncmd(cbuf, TRUE); addMenu(namebuf, fixAccelText(acceleratorText), verb); if (*sensitive == '0') { vim_snprintf(cbuf, sizeof(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; } void workshop_toolbar_button( char *label, char *verb, char *senseVerb UNUSED, char *filepos UNUSED, 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 *)"\\. "); vim_snprintf(namebuf, sizeof(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 *)" "); vim_snprintf_add(cbuf, sizeof(cbuf), "icon=%s ", p); vim_free(p); } vim_snprintf_add(cbuf, sizeof(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... */ vim_snprintf(cbuf, sizeof(cbuf), "amenu disable %s", namebuf); coloncmd(cbuf, True); } if (help && *help) { /* Do the tooltip */ vim_snprintf(cbuf, sizeof(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) vim_snprintf(cbuf, sizeof(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) { vim_snprintf(cbuf, sizeof(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) { vim_snprintf(cbuf, sizeof(cbuf), "unmap %s", mp->accel); coloncmd(cbuf, TRUE); } } } /* * A button in the toolbar has been pushed. */ 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 if (curbuf->b_ffname == NULL) ffname[0] = NUL; else /* copy so nobody can change b_ffname */ strcpy(ffname, (char *) curbuf->b_ffname); *filename = ffname; *curLine = curwin->w_cursor.lnum; *curCol = curwin->w_cursor.col; if (curbuf->b_visual.vi_mode == 'v' && equalpos(curwin->w_cursor, curbuf->b_visual.vi_end)) { *selStartLine = curbuf->b_visual.vi_start.lnum; *selStartCol = curbuf->b_visual.vi_start.col; *selEndLine = curbuf->b_visual.vi_end.lnum; *selEndCol = curbuf->b_visual.vi_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.vi_mode == 'v') { start = &buf->b_visual.vi_start; end = &buf->b_visual.vi_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; vim_snprintf(cbuf, sizeof(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 { #ifdef FEAT_WINDOWS /* buf is in a window */ if (win != curwin) { win_enter(win, False); /* wsdebug("load_window: window enter %s\n", win->w_buffer->b_sfname); */ } #endif 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 command 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; } 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) vim_snprintf(curMenuPriority, sizeof(curMenuPriority), "%s.%d.0", curMenuPriority, pri); else vim_snprintf(curMenuPriority, sizeof(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; } void workshop_save_sensitivity(char *filename UNUSED) { } #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) { vim_snprintf(buf, sizeof(buf), "<%s%s>", shift, ap); return strdup(buf); } else return NULL; } #ifdef FEAT_BEVAL void workshop_beval_cb( BalloonEval *beval, int state) { win_T *wp; char_u *text; int type; linenr_T lnum; int col; int idx; char buf[MAXPATHLEN * 2]; static int serialNo = -1; if (!p_beval) return; if (get_beval_info(beval, FALSE, &wp, &lnum, &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) { lnum = 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 */ vim_snprintf(buf, sizeof(buf), "toolVerb debug.balloonEval " "%s %ld,0 %d,0 %d,%d %ld %s\n", (char *)wp->w_buffer->b_ffname, (long)lnum, idx, type, serialNo++, (long)strlen((char *)text), (char *)text); balloonEval = beval; workshop_send_message(buf); } } } } 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; } #endif 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) { vim_snprintf(cbuf, sizeof(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); if (getcwd(runpath, MAXPATHLEN) == NULL) runpath[0] = NUL; 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); } }