Example #1
0
/*
 * Function given to ExpandGeneric() to obtain the list of menus and menu
 * entries.
 */
char_u *get_menu_names(expand_T *xp, int idx)
{
  static vimmenu_T    *menu = NULL;
#define TBUFFER_LEN 256
  static char_u tbuffer[TBUFFER_LEN];         /*hack*/
  char_u              *str;
  static int should_advance = FALSE;

  if (idx == 0) {           /* first call: start at first item */
    menu = expand_menu;
    should_advance = FALSE;
  }

  /* Skip Browse-style entries, popup menus and separators. */
  while (menu != NULL
         && (   menu_is_hidden(menu->dname)
                || (expand_emenu && menu_is_separator(menu->dname))
                || menu_is_tearoff(menu->dname)
                || menu->dname[STRLEN(menu->dname) - 1] == '.'
                ))
    menu = menu->next;

  if (menu == NULL)         /* at end of linked list */
    return NULL;

  if (menu->modes & expand_modes) {
    if (menu->children != NULL) {
      if (should_advance)
        STRLCPY(tbuffer, menu->en_dname, TBUFFER_LEN - 1);
      else {
        STRLCPY(tbuffer, menu->dname,  TBUFFER_LEN - 1);
        if (menu->en_dname == NULL)
          should_advance = TRUE;
      }
      /* hack on menu separators:  use a 'magic' char for the separator
       * so that '.' in names gets escaped properly */
      STRCAT(tbuffer, "\001");
      str = tbuffer;
    } else {
      if (should_advance)
        str = menu->en_dname;
      else {
        str = menu->dname;
        if (menu->en_dname == NULL)
          should_advance = TRUE;
      }
    }
  } else
    str = (char_u *)"";

  if (should_advance)
    /* Advance to next menu entry. */
    menu = menu->next;

  should_advance = !should_advance;

  return str;
}
Example #2
0
/*
 * Add a menu item to a menu
 */
    void
gui_mch_add_menu_item(
    vimmenu_T	*menu,
    int		idx)
{
    vimmenu_T	*parent = menu->parent;

    menu->id = s_menu_id++;
    menu->submenu_id = NULL;

#ifdef FEAT_TOOLBAR
    if (menu_is_toolbar(parent->name))
    {
	TBBUTTON newtb;

	vim_memset(&newtb, 0, sizeof(newtb));
	if (menu_is_separator(menu->name))
	{
	    newtb.iBitmap = 0;
	    newtb.fsStyle = TBSTYLE_SEP;
	}
	else
	{
	    if (menu->iconidx >= TOOLBAR_BITMAP_COUNT)
		newtb.iBitmap = -1;
	    else
		newtb.iBitmap = menu->iconidx;
	    newtb.fsStyle = TBSTYLE_BUTTON;
	}
	newtb.idCommand = menu->id;
	newtb.fsState = TBSTATE_ENABLED;
	SendMessage(s_toolbarhwnd, TB_INSERTBUTTON, (WPARAM)idx,
							     (LPARAM)&newtb);
	menu->submenu_id = (HMENU)-1;
    }
    else
#endif
    {
	InsertMenu(parent->submenu_id, (UINT)idx,
		(menu_is_separator(menu->name) ? MF_SEPARATOR : MF_STRING)
							      | MF_BYPOSITION,
		(UINT)menu->id, menu->name);
    }
}
Example #3
0
/*
 * Function given to ExpandGeneric() to obtain the list of (sub)menus (not
 * entries).
 */
char_u *get_menu_name(expand_T *xp, int idx)
{
  static vimmenu_T    *menu = NULL;
  char_u              *str;
  static int should_advance = FALSE;

  if (idx == 0) {           /* first call: start at first item */
    menu = expand_menu;
    should_advance = FALSE;
  }

  /* Skip PopUp[nvoci]. */
  while (menu != NULL && (menu_is_hidden(menu->dname)
                          || menu_is_separator(menu->dname)
                          || menu_is_tearoff(menu->dname)
                          || menu->children == NULL))
    menu = menu->next;

  if (menu == NULL)         /* at end of linked list */
    return NULL;

  if (menu->modes & expand_modes)
    if (should_advance)
      str = menu->en_dname;
    else {
      str = menu->dname;
      if (menu->en_dname == NULL)
        should_advance = TRUE;
    }
  else
    str = (char_u *)"";

  if (should_advance)
    /* Advance to next menu entry. */
    menu = menu->next;

  should_advance = !should_advance;

  return str;
}
Example #4
0
/*
 * Open the terminal version of the popup menu and don't return until it is
 * closed.
 */
    void
pum_show_popupmenu(vimmenu_T *menu)
{
    vimmenu_T   *mp;
    int		idx = 0;
    pumitem_T	*array;
#ifdef FEAT_BEVAL_TERM
    int		save_bevalterm = p_bevalterm;
#endif
    int		mode;

    pum_undisplay();
    pum_size = 0;
    mode = get_menu_mode_flag();

    for (mp = menu->children; mp != NULL; mp = mp->next)
	if (menu_is_separator(mp->dname)
		|| (mp->modes & mp->enabled & mode))
	    ++pum_size;

    array = (pumitem_T *)alloc_clear((unsigned)sizeof(pumitem_T) * pum_size);
    if (array == NULL)
	return;

    for (mp = menu->children; mp != NULL; mp = mp->next)
	if (menu_is_separator(mp->dname))
	    array[idx++].pum_text = (char_u *)"";
	else if (mp->modes & mp->enabled & mode)
	    array[idx++].pum_text = mp->dname;

    pum_array = array;
    pum_compute_size();
    pum_scrollbar = 0;
    pum_height = pum_size;
    pum_position_at_mouse(20);

    pum_selected = -1;
    pum_first = 0;
#  ifdef FEAT_BEVAL_TERM
    p_bevalterm = TRUE;  /* track mouse movement */
    mch_setmouse(TRUE);
#  endif

    for (;;)
    {
	int	c;

	pum_redraw();
	setcursor_mayforce(TRUE);
	out_flush();

	c = vgetc();
	if (c == ESC || c == Ctrl_C)
	    break;
	else if (c == CAR || c == NL)
	{
	    /* enter: select current item, if any, and close */
	    pum_execute_menu(menu, mode);
	    break;
	}
	else if (c == 'k' || c == K_UP || c == K_MOUSEUP)
	{
	    /* cursor up: select previous item */
	    while (pum_selected > 0)
	    {
		--pum_selected;
		if (*array[pum_selected].pum_text != NUL)
		    break;
	    }
	}
	else if (c == 'j' || c == K_DOWN || c == K_MOUSEDOWN)
	{
	    /* cursor down: select next item */
	    while (pum_selected < pum_size - 1)
	    {
		++pum_selected;
		if (*array[pum_selected].pum_text != NUL)
		    break;
	    }
	}
	else if (c == K_RIGHTMOUSE)
	{
	    /* Right mouse down: reposition the menu. */
	    vungetc(c);
	    break;
	}
	else if (c == K_LEFTDRAG || c == K_RIGHTDRAG || c == K_MOUSEMOVE)
	{
	    /* mouse moved: select item in the mouse row */
	    pum_select_mouse_pos();
	}
	else if (c == K_LEFTMOUSE || c == K_LEFTMOUSE_NM || c == K_RIGHTRELEASE)
	{
	    /* left mouse click: select clicked item, if any, and close;
	     * right mouse release: select clicked item, close if any */
	    pum_select_mouse_pos();
	    if (pum_selected >= 0)
	    {
		pum_execute_menu(menu, mode);
		break;
	    }
	    if (c == K_LEFTMOUSE || c == K_LEFTMOUSE_NM)
		break;
	}
    }

    vim_free(array);
    pum_undisplay();
#  ifdef FEAT_BEVAL_TERM
    p_bevalterm = save_bevalterm;
    mch_setmouse(TRUE);
#  endif
}
Example #5
0
/*
 * Add the menu with the given name to the menu hierarchy
 */
static int 
add_menu_path (
    char_u *menu_path,
    vimmenu_T *menuarg,           /* passes modes, iconfile, iconidx,
                                   icon_builtin, silent[0], noremap[0] */
    int *pri_tab,
    char_u *call_data
)
{
  char_u      *path_name;
  int modes = menuarg->modes;
  vimmenu_T   **menup;
  vimmenu_T   *menu = NULL;
  vimmenu_T   *parent;
  vimmenu_T   **lower_pri;
  char_u      *p;
  char_u      *name;
  char_u      *dname;
  char_u      *next_name;
  int i;
  int c;
  int d;
  int pri_idx = 0;
  int old_modes = 0;
  int amenu;
  char_u      *en_name;
  char_u      *map_to = NULL;

  /* Make a copy so we can stuff around with it, since it could be const */
  path_name = vim_strsave(menu_path);
  menup = &root_menu;
  parent = NULL;
  name = path_name;
  while (*name) {
    /* Get name of this element in the menu hierarchy, and the simplified
     * name (without mnemonic and accelerator text). */
    next_name = menu_name_skip(name);
    map_to = menutrans_lookup(name, (int)STRLEN(name));
    if (map_to != NULL) {
      en_name = name;
      name = map_to;
    } else
      en_name = NULL;
    dname = menu_text(name, NULL, NULL);
    if (dname == NULL)
      goto erret;
    if (*dname == NUL) {
      /* Only a mnemonic or accelerator is not valid. */
      EMSG(_("E792: Empty menu name"));
      goto erret;
    }

    /* See if it's already there */
    lower_pri = menup;
    menu = *menup;
    while (menu != NULL) {
      if (menu_name_equal(name, menu) || menu_name_equal(dname, menu)) {
        if (*next_name == NUL && menu->children != NULL) {
          if (!sys_menu)
            EMSG(_("E330: Menu path must not lead to a sub-menu"));
          goto erret;
        }
        if (*next_name != NUL && menu->children == NULL
            ) {
          if (!sys_menu)
            EMSG(_(e_notsubmenu));
          goto erret;
        }
        break;
      }
      menup = &menu->next;

      /* Count menus, to find where this one needs to be inserted.
       * Ignore menus that are not in the menubar (PopUp and Toolbar) */
      if (parent != NULL || menu_is_menubar(menu->name)) {
        if (menu->priority <= pri_tab[pri_idx]) {
          lower_pri = menup;
        }
      }
      menu = menu->next;
    }

    if (menu == NULL) {
      if (*next_name == NUL && parent == NULL) {
        EMSG(_("E331: Must not add menu items directly to menu bar"));
        goto erret;
      }

      if (menu_is_separator(dname) && *next_name != NUL) {
        EMSG(_("E332: Separator cannot be part of a menu path"));
        goto erret;
      }

      /* Not already there, so lets add it */
      menu = xcalloc(1, sizeof(vimmenu_T));

      menu->modes = modes;
      menu->enabled = MENU_ALL_MODES;
      menu->name = vim_strsave(name);
      /* separate mnemonic and accelerator text from actual menu name */
      menu->dname = menu_text(name, &menu->mnemonic, &menu->actext);
      if (en_name != NULL) {
        menu->en_name = vim_strsave(en_name);
        menu->en_dname = menu_text(en_name, NULL, NULL);
      } else {
        menu->en_name = NULL;
        menu->en_dname = NULL;
      }
      menu->priority = pri_tab[pri_idx];
      menu->parent = parent;

      /*
       * Add after menu that has lower priority.
       */
      menu->next = *lower_pri;
      *lower_pri = menu;

      old_modes = 0;

    } else {
      old_modes = menu->modes;

      /*
       * If this menu option was previously only available in other
       * modes, then make sure it's available for this one now
       * Also enable a menu when it's created or changed.
       */
      {
        menu->modes |= modes;
        menu->enabled |= modes;
      }
    }


    menup = &menu->children;
    parent = menu;
    name = next_name;
    free(dname);
    dname = NULL;
    if (pri_tab[pri_idx + 1] != -1)
      ++pri_idx;
  }
  free(path_name);

  /*
   * Only add system menu items which have not been defined yet.
   * First check if this was an ":amenu".
   */
  amenu = ((modes & (MENU_NORMAL_MODE | MENU_INSERT_MODE)) ==
           (MENU_NORMAL_MODE | MENU_INSERT_MODE));
  if (sys_menu)
    modes &= ~old_modes;

  if (menu != NULL && modes) {
    p = (call_data == NULL) ? NULL : vim_strsave(call_data);

    /* loop over all modes, may add more than one */
    for (i = 0; i < MENU_MODES; ++i) {
      if (modes & (1 << i)) {
        /* free any old menu */
        free_menu_string(menu, i);

        /* For "amenu", may insert an extra character.
         * Don't do this if adding a tearbar (addtearoff == FALSE).
         * Don't do this for "<Nop>". */
        c = 0;
        d = 0;
        if (amenu && call_data != NULL && *call_data != NUL
            ) {
          switch (1 << i) {
          case MENU_VISUAL_MODE:
          case MENU_SELECT_MODE:
          case MENU_OP_PENDING_MODE:
          case MENU_CMDLINE_MODE:
            c = Ctrl_C;
            break;
          case MENU_INSERT_MODE:
            c = Ctrl_BSL;
            d = Ctrl_O;
            break;
          }
        }

        if (c != 0) {
          menu->strings[i] = xmalloc(STRLEN(call_data) + 5 );
          menu->strings[i][0] = c;
          if (d == 0)
            STRCPY(menu->strings[i] + 1, call_data);
          else {
            menu->strings[i][1] = d;
            STRCPY(menu->strings[i] + 2, call_data);
          }
          if (c == Ctrl_C) {
            int len = (int)STRLEN(menu->strings[i]);

            /* Append CTRL-\ CTRL-G to obey 'insertmode'. */
            menu->strings[i][len] = Ctrl_BSL;
            menu->strings[i][len + 1] = Ctrl_G;
            menu->strings[i][len + 2] = NUL;
          }
        } else
          menu->strings[i] = p;
        menu->noremap[i] = menuarg->noremap[0];
        menu->silent[i] = menuarg->silent[0];
      }
    }
#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_W32) \
    && (defined(FEAT_BEVAL) || defined(FEAT_GUI_GTK))
    /* Need to update the menu tip. */
    if (modes & MENU_TIP_MODE)
      gui_mch_menu_set_tip(menu);
#endif
  }
  return OK;

erret:
  free(path_name);
  free(dname);

  /* Delete any empty submenu we added before discovering the error.  Repeat
   * for higher levels. */
  while (parent != NULL && parent->children == NULL) {
    if (parent->parent == NULL)
      menup = &root_menu;
    else
      menup = &parent->parent->children;
    for (; *menup != NULL && *menup != parent; menup = &((*menup)->next))
      ;
    if (*menup == NULL)     /* safety check */
      break;
    parent = parent->parent;
    free_menu(menup);
  }
  return FAIL;
}