home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / unix / vim-6.2.tar.bz2 / vim-6.2.tar / vim62 / src / workshop.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-03-10  |  41.3 KB  |  1,886 lines

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